100f1cb17SEmil Renner Berthing // SPDX-License-Identifier: GPL-2.0 200f1cb17SEmil Renner Berthing /* 3147455edSEmil Renner Berthing * StarFive JH71X0 Clock Generator Driver 400f1cb17SEmil Renner Berthing * 500f1cb17SEmil Renner Berthing * Copyright (C) 2021-2022 Emil Renner Berthing <kernel@esmil.dk> 600f1cb17SEmil Renner Berthing */ 700f1cb17SEmil Renner Berthing 800f1cb17SEmil Renner Berthing #include <linux/clk-provider.h> 900f1cb17SEmil Renner Berthing #include <linux/debugfs.h> 1000f1cb17SEmil Renner Berthing #include <linux/device.h> 1100f1cb17SEmil Renner Berthing #include <linux/io.h> 1200f1cb17SEmil Renner Berthing 13e19aa786SEmil Renner Berthing #include "clk-starfive-jh71x0.h" 1400f1cb17SEmil Renner Berthing 15147455edSEmil Renner Berthing static struct jh71x0_clk *jh71x0_clk_from(struct clk_hw *hw) 1600f1cb17SEmil Renner Berthing { 17147455edSEmil Renner Berthing return container_of(hw, struct jh71x0_clk, hw); 1800f1cb17SEmil Renner Berthing } 1900f1cb17SEmil Renner Berthing 20147455edSEmil Renner Berthing static struct jh71x0_clk_priv *jh71x0_priv_from(struct jh71x0_clk *clk) 2100f1cb17SEmil Renner Berthing { 22147455edSEmil Renner Berthing return container_of(clk, struct jh71x0_clk_priv, reg[clk->idx]); 2300f1cb17SEmil Renner Berthing } 2400f1cb17SEmil Renner Berthing 25147455edSEmil Renner Berthing static u32 jh71x0_clk_reg_get(struct jh71x0_clk *clk) 2600f1cb17SEmil Renner Berthing { 27147455edSEmil Renner Berthing struct jh71x0_clk_priv *priv = jh71x0_priv_from(clk); 2800f1cb17SEmil Renner Berthing void __iomem *reg = priv->base + 4 * clk->idx; 2900f1cb17SEmil Renner Berthing 3000f1cb17SEmil Renner Berthing return readl_relaxed(reg); 3100f1cb17SEmil Renner Berthing } 3200f1cb17SEmil Renner Berthing 33147455edSEmil Renner Berthing static void jh71x0_clk_reg_rmw(struct jh71x0_clk *clk, u32 mask, u32 value) 3400f1cb17SEmil Renner Berthing { 35147455edSEmil Renner Berthing struct jh71x0_clk_priv *priv = jh71x0_priv_from(clk); 3600f1cb17SEmil Renner Berthing void __iomem *reg = priv->base + 4 * clk->idx; 3700f1cb17SEmil Renner Berthing unsigned long flags; 3800f1cb17SEmil Renner Berthing 3900f1cb17SEmil Renner Berthing spin_lock_irqsave(&priv->rmw_lock, flags); 4000f1cb17SEmil Renner Berthing value |= readl_relaxed(reg) & ~mask; 4100f1cb17SEmil Renner Berthing writel_relaxed(value, reg); 4200f1cb17SEmil Renner Berthing spin_unlock_irqrestore(&priv->rmw_lock, flags); 4300f1cb17SEmil Renner Berthing } 4400f1cb17SEmil Renner Berthing 45147455edSEmil Renner Berthing static int jh71x0_clk_enable(struct clk_hw *hw) 4600f1cb17SEmil Renner Berthing { 47147455edSEmil Renner Berthing struct jh71x0_clk *clk = jh71x0_clk_from(hw); 4800f1cb17SEmil Renner Berthing 49147455edSEmil Renner Berthing jh71x0_clk_reg_rmw(clk, JH71X0_CLK_ENABLE, JH71X0_CLK_ENABLE); 5000f1cb17SEmil Renner Berthing return 0; 5100f1cb17SEmil Renner Berthing } 5200f1cb17SEmil Renner Berthing 53147455edSEmil Renner Berthing static void jh71x0_clk_disable(struct clk_hw *hw) 5400f1cb17SEmil Renner Berthing { 55147455edSEmil Renner Berthing struct jh71x0_clk *clk = jh71x0_clk_from(hw); 5600f1cb17SEmil Renner Berthing 57147455edSEmil Renner Berthing jh71x0_clk_reg_rmw(clk, JH71X0_CLK_ENABLE, 0); 5800f1cb17SEmil Renner Berthing } 5900f1cb17SEmil Renner Berthing 60147455edSEmil Renner Berthing static int jh71x0_clk_is_enabled(struct clk_hw *hw) 6100f1cb17SEmil Renner Berthing { 62147455edSEmil Renner Berthing struct jh71x0_clk *clk = jh71x0_clk_from(hw); 6300f1cb17SEmil Renner Berthing 64147455edSEmil Renner Berthing return !!(jh71x0_clk_reg_get(clk) & JH71X0_CLK_ENABLE); 6500f1cb17SEmil Renner Berthing } 6600f1cb17SEmil Renner Berthing 67147455edSEmil Renner Berthing static unsigned long jh71x0_clk_recalc_rate(struct clk_hw *hw, 6800f1cb17SEmil Renner Berthing unsigned long parent_rate) 6900f1cb17SEmil Renner Berthing { 70147455edSEmil Renner Berthing struct jh71x0_clk *clk = jh71x0_clk_from(hw); 71147455edSEmil Renner Berthing u32 div = jh71x0_clk_reg_get(clk) & JH71X0_CLK_DIV_MASK; 7200f1cb17SEmil Renner Berthing 7300f1cb17SEmil Renner Berthing return div ? parent_rate / div : 0; 7400f1cb17SEmil Renner Berthing } 7500f1cb17SEmil Renner Berthing 76147455edSEmil Renner Berthing static int jh71x0_clk_determine_rate(struct clk_hw *hw, 7700f1cb17SEmil Renner Berthing struct clk_rate_request *req) 7800f1cb17SEmil Renner Berthing { 79147455edSEmil Renner Berthing struct jh71x0_clk *clk = jh71x0_clk_from(hw); 8000f1cb17SEmil Renner Berthing unsigned long parent = req->best_parent_rate; 8100f1cb17SEmil Renner Berthing unsigned long rate = clamp(req->rate, req->min_rate, req->max_rate); 8200f1cb17SEmil Renner Berthing unsigned long div = min_t(unsigned long, DIV_ROUND_UP(parent, rate), clk->max_div); 8300f1cb17SEmil Renner Berthing unsigned long result = parent / div; 8400f1cb17SEmil Renner Berthing 8500f1cb17SEmil Renner Berthing /* 8600f1cb17SEmil Renner Berthing * we want the result clamped by min_rate and max_rate if possible: 8700f1cb17SEmil Renner Berthing * case 1: div hits the max divider value, which means it's less than 8800f1cb17SEmil Renner Berthing * parent / rate, so the result is greater than rate and min_rate in 8900f1cb17SEmil Renner Berthing * particular. we can't do anything about result > max_rate because the 9000f1cb17SEmil Renner Berthing * divider doesn't go any further. 9100f1cb17SEmil Renner Berthing * case 2: div = DIV_ROUND_UP(parent, rate) which means the result is 9200f1cb17SEmil Renner Berthing * always lower or equal to rate and max_rate. however the result may 9300f1cb17SEmil Renner Berthing * turn out lower than min_rate, but then the next higher rate is fine: 9400f1cb17SEmil Renner Berthing * div - 1 = ceil(parent / rate) - 1 < parent / rate 9500f1cb17SEmil Renner Berthing * and thus 9600f1cb17SEmil Renner Berthing * min_rate <= rate < parent / (div - 1) 9700f1cb17SEmil Renner Berthing */ 9800f1cb17SEmil Renner Berthing if (result < req->min_rate && div > 1) 9900f1cb17SEmil Renner Berthing result = parent / (div - 1); 10000f1cb17SEmil Renner Berthing 10100f1cb17SEmil Renner Berthing req->rate = result; 10200f1cb17SEmil Renner Berthing return 0; 10300f1cb17SEmil Renner Berthing } 10400f1cb17SEmil Renner Berthing 105147455edSEmil Renner Berthing static int jh71x0_clk_set_rate(struct clk_hw *hw, 10600f1cb17SEmil Renner Berthing unsigned long rate, 10700f1cb17SEmil Renner Berthing unsigned long parent_rate) 10800f1cb17SEmil Renner Berthing { 109147455edSEmil Renner Berthing struct jh71x0_clk *clk = jh71x0_clk_from(hw); 11000f1cb17SEmil Renner Berthing unsigned long div = clamp(DIV_ROUND_CLOSEST(parent_rate, rate), 11100f1cb17SEmil Renner Berthing 1UL, (unsigned long)clk->max_div); 11200f1cb17SEmil Renner Berthing 113147455edSEmil Renner Berthing jh71x0_clk_reg_rmw(clk, JH71X0_CLK_DIV_MASK, div); 11400f1cb17SEmil Renner Berthing return 0; 11500f1cb17SEmil Renner Berthing } 11600f1cb17SEmil Renner Berthing 117147455edSEmil Renner Berthing static unsigned long jh71x0_clk_frac_recalc_rate(struct clk_hw *hw, 11800f1cb17SEmil Renner Berthing unsigned long parent_rate) 11900f1cb17SEmil Renner Berthing { 120147455edSEmil Renner Berthing struct jh71x0_clk *clk = jh71x0_clk_from(hw); 121147455edSEmil Renner Berthing u32 reg = jh71x0_clk_reg_get(clk); 122147455edSEmil Renner Berthing unsigned long div100 = 100 * (reg & JH71X0_CLK_INT_MASK) + 123147455edSEmil Renner Berthing ((reg & JH71X0_CLK_FRAC_MASK) >> JH71X0_CLK_FRAC_SHIFT); 12400f1cb17SEmil Renner Berthing 125147455edSEmil Renner Berthing return (div100 >= JH71X0_CLK_FRAC_MIN) ? 100 * parent_rate / div100 : 0; 12600f1cb17SEmil Renner Berthing } 12700f1cb17SEmil Renner Berthing 128147455edSEmil Renner Berthing static int jh71x0_clk_frac_determine_rate(struct clk_hw *hw, 12900f1cb17SEmil Renner Berthing struct clk_rate_request *req) 13000f1cb17SEmil Renner Berthing { 13100f1cb17SEmil Renner Berthing unsigned long parent100 = 100 * req->best_parent_rate; 13200f1cb17SEmil Renner Berthing unsigned long rate = clamp(req->rate, req->min_rate, req->max_rate); 13300f1cb17SEmil Renner Berthing unsigned long div100 = clamp(DIV_ROUND_CLOSEST(parent100, rate), 134147455edSEmil Renner Berthing JH71X0_CLK_FRAC_MIN, JH71X0_CLK_FRAC_MAX); 13500f1cb17SEmil Renner Berthing unsigned long result = parent100 / div100; 13600f1cb17SEmil Renner Berthing 137147455edSEmil Renner Berthing /* clamp the result as in jh71x0_clk_determine_rate() above */ 138147455edSEmil Renner Berthing if (result > req->max_rate && div100 < JH71X0_CLK_FRAC_MAX) 13900f1cb17SEmil Renner Berthing result = parent100 / (div100 + 1); 140147455edSEmil Renner Berthing if (result < req->min_rate && div100 > JH71X0_CLK_FRAC_MIN) 14100f1cb17SEmil Renner Berthing result = parent100 / (div100 - 1); 14200f1cb17SEmil Renner Berthing 14300f1cb17SEmil Renner Berthing req->rate = result; 14400f1cb17SEmil Renner Berthing return 0; 14500f1cb17SEmil Renner Berthing } 14600f1cb17SEmil Renner Berthing 147147455edSEmil Renner Berthing static int jh71x0_clk_frac_set_rate(struct clk_hw *hw, 14800f1cb17SEmil Renner Berthing unsigned long rate, 14900f1cb17SEmil Renner Berthing unsigned long parent_rate) 15000f1cb17SEmil Renner Berthing { 151147455edSEmil Renner Berthing struct jh71x0_clk *clk = jh71x0_clk_from(hw); 15200f1cb17SEmil Renner Berthing unsigned long div100 = clamp(DIV_ROUND_CLOSEST(100 * parent_rate, rate), 153147455edSEmil Renner Berthing JH71X0_CLK_FRAC_MIN, JH71X0_CLK_FRAC_MAX); 154147455edSEmil Renner Berthing u32 value = ((div100 % 100) << JH71X0_CLK_FRAC_SHIFT) | (div100 / 100); 15500f1cb17SEmil Renner Berthing 156147455edSEmil Renner Berthing jh71x0_clk_reg_rmw(clk, JH71X0_CLK_DIV_MASK, value); 15700f1cb17SEmil Renner Berthing return 0; 15800f1cb17SEmil Renner Berthing } 15900f1cb17SEmil Renner Berthing 160147455edSEmil Renner Berthing static u8 jh71x0_clk_get_parent(struct clk_hw *hw) 16100f1cb17SEmil Renner Berthing { 162147455edSEmil Renner Berthing struct jh71x0_clk *clk = jh71x0_clk_from(hw); 163147455edSEmil Renner Berthing u32 value = jh71x0_clk_reg_get(clk); 16400f1cb17SEmil Renner Berthing 165147455edSEmil Renner Berthing return (value & JH71X0_CLK_MUX_MASK) >> JH71X0_CLK_MUX_SHIFT; 16600f1cb17SEmil Renner Berthing } 16700f1cb17SEmil Renner Berthing 168147455edSEmil Renner Berthing static int jh71x0_clk_set_parent(struct clk_hw *hw, u8 index) 16900f1cb17SEmil Renner Berthing { 170147455edSEmil Renner Berthing struct jh71x0_clk *clk = jh71x0_clk_from(hw); 171147455edSEmil Renner Berthing u32 value = (u32)index << JH71X0_CLK_MUX_SHIFT; 17200f1cb17SEmil Renner Berthing 173147455edSEmil Renner Berthing jh71x0_clk_reg_rmw(clk, JH71X0_CLK_MUX_MASK, value); 17400f1cb17SEmil Renner Berthing return 0; 17500f1cb17SEmil Renner Berthing } 17600f1cb17SEmil Renner Berthing 177147455edSEmil Renner Berthing static int jh71x0_clk_get_phase(struct clk_hw *hw) 17800f1cb17SEmil Renner Berthing { 179147455edSEmil Renner Berthing struct jh71x0_clk *clk = jh71x0_clk_from(hw); 180147455edSEmil Renner Berthing u32 value = jh71x0_clk_reg_get(clk); 18100f1cb17SEmil Renner Berthing 182147455edSEmil Renner Berthing return (value & JH71X0_CLK_INVERT) ? 180 : 0; 18300f1cb17SEmil Renner Berthing } 18400f1cb17SEmil Renner Berthing 185147455edSEmil Renner Berthing static int jh71x0_clk_set_phase(struct clk_hw *hw, int degrees) 18600f1cb17SEmil Renner Berthing { 187147455edSEmil Renner Berthing struct jh71x0_clk *clk = jh71x0_clk_from(hw); 18800f1cb17SEmil Renner Berthing u32 value; 18900f1cb17SEmil Renner Berthing 19000f1cb17SEmil Renner Berthing if (degrees == 0) 19100f1cb17SEmil Renner Berthing value = 0; 19200f1cb17SEmil Renner Berthing else if (degrees == 180) 193147455edSEmil Renner Berthing value = JH71X0_CLK_INVERT; 19400f1cb17SEmil Renner Berthing else 19500f1cb17SEmil Renner Berthing return -EINVAL; 19600f1cb17SEmil Renner Berthing 197147455edSEmil Renner Berthing jh71x0_clk_reg_rmw(clk, JH71X0_CLK_INVERT, value); 19800f1cb17SEmil Renner Berthing return 0; 19900f1cb17SEmil Renner Berthing } 20000f1cb17SEmil Renner Berthing 20100f1cb17SEmil Renner Berthing #ifdef CONFIG_DEBUG_FS 202147455edSEmil Renner Berthing static void jh71x0_clk_debug_init(struct clk_hw *hw, struct dentry *dentry) 20300f1cb17SEmil Renner Berthing { 204147455edSEmil Renner Berthing static const struct debugfs_reg32 jh71x0_clk_reg = { 20500f1cb17SEmil Renner Berthing .name = "CTRL", 20600f1cb17SEmil Renner Berthing .offset = 0, 20700f1cb17SEmil Renner Berthing }; 208147455edSEmil Renner Berthing struct jh71x0_clk *clk = jh71x0_clk_from(hw); 209147455edSEmil Renner Berthing struct jh71x0_clk_priv *priv = jh71x0_priv_from(clk); 21000f1cb17SEmil Renner Berthing struct debugfs_regset32 *regset; 21100f1cb17SEmil Renner Berthing 21200f1cb17SEmil Renner Berthing regset = devm_kzalloc(priv->dev, sizeof(*regset), GFP_KERNEL); 21300f1cb17SEmil Renner Berthing if (!regset) 21400f1cb17SEmil Renner Berthing return; 21500f1cb17SEmil Renner Berthing 216147455edSEmil Renner Berthing regset->regs = &jh71x0_clk_reg; 21700f1cb17SEmil Renner Berthing regset->nregs = 1; 21800f1cb17SEmil Renner Berthing regset->base = priv->base + 4 * clk->idx; 21900f1cb17SEmil Renner Berthing 22000f1cb17SEmil Renner Berthing debugfs_create_regset32("registers", 0400, dentry, regset); 22100f1cb17SEmil Renner Berthing } 22200f1cb17SEmil Renner Berthing #else 223147455edSEmil Renner Berthing #define jh71x0_clk_debug_init NULL 22400f1cb17SEmil Renner Berthing #endif 22500f1cb17SEmil Renner Berthing 226147455edSEmil Renner Berthing static const struct clk_ops jh71x0_clk_gate_ops = { 227147455edSEmil Renner Berthing .enable = jh71x0_clk_enable, 228147455edSEmil Renner Berthing .disable = jh71x0_clk_disable, 229147455edSEmil Renner Berthing .is_enabled = jh71x0_clk_is_enabled, 230147455edSEmil Renner Berthing .debug_init = jh71x0_clk_debug_init, 23100f1cb17SEmil Renner Berthing }; 23200f1cb17SEmil Renner Berthing 233147455edSEmil Renner Berthing static const struct clk_ops jh71x0_clk_div_ops = { 234147455edSEmil Renner Berthing .recalc_rate = jh71x0_clk_recalc_rate, 235147455edSEmil Renner Berthing .determine_rate = jh71x0_clk_determine_rate, 236147455edSEmil Renner Berthing .set_rate = jh71x0_clk_set_rate, 237147455edSEmil Renner Berthing .debug_init = jh71x0_clk_debug_init, 23800f1cb17SEmil Renner Berthing }; 23900f1cb17SEmil Renner Berthing 240147455edSEmil Renner Berthing static const struct clk_ops jh71x0_clk_fdiv_ops = { 241147455edSEmil Renner Berthing .recalc_rate = jh71x0_clk_frac_recalc_rate, 242147455edSEmil Renner Berthing .determine_rate = jh71x0_clk_frac_determine_rate, 243147455edSEmil Renner Berthing .set_rate = jh71x0_clk_frac_set_rate, 244147455edSEmil Renner Berthing .debug_init = jh71x0_clk_debug_init, 24500f1cb17SEmil Renner Berthing }; 24600f1cb17SEmil Renner Berthing 247147455edSEmil Renner Berthing static const struct clk_ops jh71x0_clk_gdiv_ops = { 248147455edSEmil Renner Berthing .enable = jh71x0_clk_enable, 249147455edSEmil Renner Berthing .disable = jh71x0_clk_disable, 250147455edSEmil Renner Berthing .is_enabled = jh71x0_clk_is_enabled, 251147455edSEmil Renner Berthing .recalc_rate = jh71x0_clk_recalc_rate, 252147455edSEmil Renner Berthing .determine_rate = jh71x0_clk_determine_rate, 253147455edSEmil Renner Berthing .set_rate = jh71x0_clk_set_rate, 254147455edSEmil Renner Berthing .debug_init = jh71x0_clk_debug_init, 25500f1cb17SEmil Renner Berthing }; 25600f1cb17SEmil Renner Berthing 257147455edSEmil Renner Berthing static const struct clk_ops jh71x0_clk_mux_ops = { 258*8303d4eeSChristophe JAILLET .determine_rate = __clk_mux_determine_rate, 259147455edSEmil Renner Berthing .set_parent = jh71x0_clk_set_parent, 260147455edSEmil Renner Berthing .get_parent = jh71x0_clk_get_parent, 261147455edSEmil Renner Berthing .debug_init = jh71x0_clk_debug_init, 26200f1cb17SEmil Renner Berthing }; 26300f1cb17SEmil Renner Berthing 264147455edSEmil Renner Berthing static const struct clk_ops jh71x0_clk_gmux_ops = { 265147455edSEmil Renner Berthing .enable = jh71x0_clk_enable, 266147455edSEmil Renner Berthing .disable = jh71x0_clk_disable, 267147455edSEmil Renner Berthing .is_enabled = jh71x0_clk_is_enabled, 268*8303d4eeSChristophe JAILLET .determine_rate = __clk_mux_determine_rate, 269147455edSEmil Renner Berthing .set_parent = jh71x0_clk_set_parent, 270147455edSEmil Renner Berthing .get_parent = jh71x0_clk_get_parent, 271147455edSEmil Renner Berthing .debug_init = jh71x0_clk_debug_init, 27200f1cb17SEmil Renner Berthing }; 27300f1cb17SEmil Renner Berthing 274147455edSEmil Renner Berthing static const struct clk_ops jh71x0_clk_mdiv_ops = { 275147455edSEmil Renner Berthing .recalc_rate = jh71x0_clk_recalc_rate, 276147455edSEmil Renner Berthing .determine_rate = jh71x0_clk_determine_rate, 277147455edSEmil Renner Berthing .get_parent = jh71x0_clk_get_parent, 278147455edSEmil Renner Berthing .set_parent = jh71x0_clk_set_parent, 279147455edSEmil Renner Berthing .set_rate = jh71x0_clk_set_rate, 280147455edSEmil Renner Berthing .debug_init = jh71x0_clk_debug_init, 28100f1cb17SEmil Renner Berthing }; 28200f1cb17SEmil Renner Berthing 283147455edSEmil Renner Berthing static const struct clk_ops jh71x0_clk_gmd_ops = { 284147455edSEmil Renner Berthing .enable = jh71x0_clk_enable, 285147455edSEmil Renner Berthing .disable = jh71x0_clk_disable, 286147455edSEmil Renner Berthing .is_enabled = jh71x0_clk_is_enabled, 287147455edSEmil Renner Berthing .recalc_rate = jh71x0_clk_recalc_rate, 288147455edSEmil Renner Berthing .determine_rate = jh71x0_clk_determine_rate, 289147455edSEmil Renner Berthing .get_parent = jh71x0_clk_get_parent, 290147455edSEmil Renner Berthing .set_parent = jh71x0_clk_set_parent, 291147455edSEmil Renner Berthing .set_rate = jh71x0_clk_set_rate, 292147455edSEmil Renner Berthing .debug_init = jh71x0_clk_debug_init, 29300f1cb17SEmil Renner Berthing }; 29400f1cb17SEmil Renner Berthing 295147455edSEmil Renner Berthing static const struct clk_ops jh71x0_clk_inv_ops = { 296147455edSEmil Renner Berthing .get_phase = jh71x0_clk_get_phase, 297147455edSEmil Renner Berthing .set_phase = jh71x0_clk_set_phase, 298147455edSEmil Renner Berthing .debug_init = jh71x0_clk_debug_init, 29900f1cb17SEmil Renner Berthing }; 30000f1cb17SEmil Renner Berthing 301147455edSEmil Renner Berthing const struct clk_ops *starfive_jh71x0_clk_ops(u32 max) 30200f1cb17SEmil Renner Berthing { 303147455edSEmil Renner Berthing if (max & JH71X0_CLK_DIV_MASK) { 304147455edSEmil Renner Berthing if (max & JH71X0_CLK_MUX_MASK) { 305147455edSEmil Renner Berthing if (max & JH71X0_CLK_ENABLE) 306147455edSEmil Renner Berthing return &jh71x0_clk_gmd_ops; 307147455edSEmil Renner Berthing return &jh71x0_clk_mdiv_ops; 30800f1cb17SEmil Renner Berthing } 309147455edSEmil Renner Berthing if (max & JH71X0_CLK_ENABLE) 310147455edSEmil Renner Berthing return &jh71x0_clk_gdiv_ops; 311147455edSEmil Renner Berthing if (max == JH71X0_CLK_FRAC_MAX) 312147455edSEmil Renner Berthing return &jh71x0_clk_fdiv_ops; 313147455edSEmil Renner Berthing return &jh71x0_clk_div_ops; 31400f1cb17SEmil Renner Berthing } 31500f1cb17SEmil Renner Berthing 316147455edSEmil Renner Berthing if (max & JH71X0_CLK_MUX_MASK) { 317147455edSEmil Renner Berthing if (max & JH71X0_CLK_ENABLE) 318147455edSEmil Renner Berthing return &jh71x0_clk_gmux_ops; 319147455edSEmil Renner Berthing return &jh71x0_clk_mux_ops; 32000f1cb17SEmil Renner Berthing } 32100f1cb17SEmil Renner Berthing 322147455edSEmil Renner Berthing if (max & JH71X0_CLK_ENABLE) 323147455edSEmil Renner Berthing return &jh71x0_clk_gate_ops; 32400f1cb17SEmil Renner Berthing 325147455edSEmil Renner Berthing return &jh71x0_clk_inv_ops; 32600f1cb17SEmil Renner Berthing } 327147455edSEmil Renner Berthing EXPORT_SYMBOL_GPL(starfive_jh71x0_clk_ops); 328