diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2021-07-08 12:12:22 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2021-07-08 12:12:22 -0700 |
commit | b0dfd9af28b60d7ec42c359ae84c1ba97e093100 (patch) | |
tree | 47e830830afe7cbc2e01f22d4db04a5e33202abf | |
parent | 316a2c9b6a5f6f056441275f748e077027179f36 (diff) | |
parent | 783d08bd02f5d33d6e9e7fea62b727e2b6fe6462 (diff) |
Merge tag 'clk-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/clk/linux
Pull more clk updates from Stephen Boyd:
- A handful of fixes for lmk04832 driver
- Migrate the basic clk divider to use determine rate ops
- Fix modpost build for hisilicon hi3559a driver
- Actually set the parent in k210_clk_set_parent()
* tag 'clk-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/clk/linux:
Revert "clk: divider: Switch from .round_rate to .determine_rate by default"
clk: hisilicon: hi3559a: Drop __init markings everywhere
clk: meson: regmap: switch to determine_rate for the dividers
clk: divider: Switch from .round_rate to .determine_rate by default
clk: divider: Add re-usable determine_rate implementations
clk: k210: Fix k210_clk_set_parent()
clk: lmk04832: Fix spelling mistakes in dev_err messages and comments
clk: lmk04832: fix return value check in lmk04832_probe()
clk: stm32mp1: fix missing spin_lock_init()
-rw-r--r-- | drivers/clk/clk-divider.c | 75 | ||||
-rw-r--r-- | drivers/clk/clk-k210.c | 1 | ||||
-rw-r--r-- | drivers/clk/clk-lmk04832.c | 20 | ||||
-rw-r--r-- | drivers/clk/clk-stm32mp1.c | 1 | ||||
-rw-r--r-- | drivers/clk/hisilicon/clk-hi3559a.c | 39 | ||||
-rw-r--r-- | drivers/clk/meson/clk-regmap.c | 19 | ||||
-rw-r--r-- | include/linux/clk-provider.h | 6 |
7 files changed, 107 insertions, 54 deletions
diff --git a/drivers/clk/clk-divider.c b/drivers/clk/clk-divider.c index 344997203f0e..87ba4966b0e8 100644 --- a/drivers/clk/clk-divider.c +++ b/drivers/clk/clk-divider.c @@ -343,16 +343,63 @@ static int clk_divider_bestdiv(struct clk_hw *hw, struct clk_hw *parent, return bestdiv; } +int divider_determine_rate(struct clk_hw *hw, struct clk_rate_request *req, + const struct clk_div_table *table, u8 width, + unsigned long flags) +{ + int div; + + div = clk_divider_bestdiv(hw, req->best_parent_hw, req->rate, + &req->best_parent_rate, table, width, flags); + + req->rate = DIV_ROUND_UP_ULL((u64)req->best_parent_rate, div); + + return 0; +} +EXPORT_SYMBOL_GPL(divider_determine_rate); + +int divider_ro_determine_rate(struct clk_hw *hw, struct clk_rate_request *req, + const struct clk_div_table *table, u8 width, + unsigned long flags, unsigned int val) +{ + int div; + + div = _get_div(table, val, flags, width); + + /* Even a read-only clock can propagate a rate change */ + if (clk_hw_get_flags(hw) & CLK_SET_RATE_PARENT) { + if (!req->best_parent_hw) + return -EINVAL; + + req->best_parent_rate = clk_hw_round_rate(req->best_parent_hw, + req->rate * div); + } + + req->rate = DIV_ROUND_UP_ULL((u64)req->best_parent_rate, div); + + return 0; +} +EXPORT_SYMBOL_GPL(divider_ro_determine_rate); + long divider_round_rate_parent(struct clk_hw *hw, struct clk_hw *parent, unsigned long rate, unsigned long *prate, const struct clk_div_table *table, u8 width, unsigned long flags) { - int div; + struct clk_rate_request req = { + .rate = rate, + .best_parent_rate = *prate, + .best_parent_hw = parent, + }; + int ret; - div = clk_divider_bestdiv(hw, parent, rate, prate, table, width, flags); + ret = divider_determine_rate(hw, &req, table, width, flags); + if (ret) + return ret; - return DIV_ROUND_UP_ULL((u64)*prate, div); + *prate = req.best_parent_rate; + + return req.rate; } EXPORT_SYMBOL_GPL(divider_round_rate_parent); @@ -361,23 +408,23 @@ long divider_ro_round_rate_parent(struct clk_hw *hw, struct clk_hw *parent, const struct clk_div_table *table, u8 width, unsigned long flags, unsigned int val) { - int div; - - div = _get_div(table, val, flags, width); + struct clk_rate_request req = { + .rate = rate, + .best_parent_rate = *prate, + .best_parent_hw = parent, + }; + int ret; - /* Even a read-only clock can propagate a rate change */ - if (clk_hw_get_flags(hw) & CLK_SET_RATE_PARENT) { - if (!parent) - return -EINVAL; + ret = divider_ro_determine_rate(hw, &req, table, width, flags, val); + if (ret) + return ret; - *prate = clk_hw_round_rate(parent, rate * div); - } + *prate = req.best_parent_rate; - return DIV_ROUND_UP_ULL((u64)*prate, div); + return req.rate; } EXPORT_SYMBOL_GPL(divider_ro_round_rate_parent); - static long clk_divider_round_rate(struct clk_hw *hw, unsigned long rate, unsigned long *prate) { diff --git a/drivers/clk/clk-k210.c b/drivers/clk/clk-k210.c index 6c84abf5b2e3..67a7cb3503c3 100644 --- a/drivers/clk/clk-k210.c +++ b/drivers/clk/clk-k210.c @@ -722,6 +722,7 @@ static int k210_clk_set_parent(struct clk_hw *hw, u8 index) reg |= BIT(cfg->mux_bit); else reg &= ~BIT(cfg->mux_bit); + writel(reg, ksc->regs + cfg->mux_reg); spin_unlock_irqrestore(&ksc->clk_lock, flags); return 0; diff --git a/drivers/clk/clk-lmk04832.c b/drivers/clk/clk-lmk04832.c index c1095e733220..c7a3a029fb1e 100644 --- a/drivers/clk/clk-lmk04832.c +++ b/drivers/clk/clk-lmk04832.c @@ -519,7 +519,7 @@ static long lmk04832_vco_round_rate(struct clk_hw *hw, unsigned long rate, vco_rate = lmk04832_calc_pll2_params(*prate, rate, &n, &p, &r); if (vco_rate < 0) { - dev_err(lmk->dev, "PLL2 parmeters out of range\n"); + dev_err(lmk->dev, "PLL2 parameters out of range\n"); return vco_rate; } @@ -550,7 +550,7 @@ static int lmk04832_vco_set_rate(struct clk_hw *hw, unsigned long rate, vco_rate = lmk04832_calc_pll2_params(prate, rate, &n, &p, &r); if (vco_rate < 0) { - dev_err(lmk->dev, "failed to determine PLL2 parmeters\n"); + dev_err(lmk->dev, "failed to determine PLL2 parameters\n"); return vco_rate; } @@ -573,7 +573,7 @@ static int lmk04832_vco_set_rate(struct clk_hw *hw, unsigned long rate, /* * PLL2_N registers must be programmed after other PLL2 dividers are - * programed to ensure proper VCO frequency calibration + * programmed to ensure proper VCO frequency calibration */ ret = regmap_write(lmk->regmap, LMK04832_REG_PLL2_N_0, FIELD_GET(0x030000, n)); @@ -1120,7 +1120,7 @@ static int lmk04832_dclk_set_rate(struct clk_hw *hw, unsigned long rate, return -EINVAL; } - /* Enable Duty Cycle Corretion */ + /* Enable Duty Cycle Correction */ if (dclk_div == 1) { ret = regmap_update_bits(lmk->regmap, LMK04832_REG_CLKOUT_CTRL3(dclk->id), @@ -1425,23 +1425,23 @@ static int lmk04832_probe(struct spi_device *spi) lmk->dclk = devm_kcalloc(lmk->dev, info->num_channels >> 1, sizeof(struct lmk_dclk), GFP_KERNEL); - if (IS_ERR(lmk->dclk)) { - ret = PTR_ERR(lmk->dclk); + if (!lmk->dclk) { + ret = -ENOMEM; goto err_disable_oscin; } lmk->clkout = devm_kcalloc(lmk->dev, info->num_channels, sizeof(*lmk->clkout), GFP_KERNEL); - if (IS_ERR(lmk->clkout)) { - ret = PTR_ERR(lmk->clkout); + if (!lmk->clkout) { + ret = -ENOMEM; goto err_disable_oscin; } lmk->clk_data = devm_kzalloc(lmk->dev, struct_size(lmk->clk_data, hws, info->num_channels), GFP_KERNEL); - if (IS_ERR(lmk->clk_data)) { - ret = PTR_ERR(lmk->clk_data); + if (!lmk->clk_data) { + ret = -ENOMEM; goto err_disable_oscin; } diff --git a/drivers/clk/clk-stm32mp1.c b/drivers/clk/clk-stm32mp1.c index 6adc625e79cb..256575bd29b9 100644 --- a/drivers/clk/clk-stm32mp1.c +++ b/drivers/clk/clk-stm32mp1.c @@ -2263,6 +2263,7 @@ static int stm32_rcc_reset_init(struct device *dev, void __iomem *base, if (!reset_data) return -ENOMEM; + spin_lock_init(&reset_data->lock); reset_data->membase = base; reset_data->rcdev.owner = THIS_MODULE; reset_data->rcdev.ops = &stm32_reset_ops; diff --git a/drivers/clk/hisilicon/clk-hi3559a.c b/drivers/clk/hisilicon/clk-hi3559a.c index b1f19c43b558..56012a3d0219 100644 --- a/drivers/clk/hisilicon/clk-hi3559a.c +++ b/drivers/clk/hisilicon/clk-hi3559a.c @@ -107,25 +107,25 @@ static const struct hisi_fixed_rate_clock hi3559av100_fixed_rate_clks_crg[] = { }; -static const char *fmc_mux_p[] __initconst = { +static const char *fmc_mux_p[] = { "24m", "75m", "125m", "150m", "200m", "250m", "300m", "400m" }; -static const char *mmc_mux_p[] __initconst = { +static const char *mmc_mux_p[] = { "100k", "25m", "49p5m", "99m", "187p5m", "150m", "198m", "400k" }; -static const char *sysapb_mux_p[] __initconst = { +static const char *sysapb_mux_p[] = { "24m", "50m", }; -static const char *sysbus_mux_p[] __initconst = { +static const char *sysbus_mux_p[] = { "24m", "300m" }; -static const char *uart_mux_p[] __initconst = { "50m", "24m", "3m" }; +static const char *uart_mux_p[] = { "50m", "24m", "3m" }; -static const char *a73_clksel_mux_p[] __initconst = { +static const char *a73_clksel_mux_p[] = { "24m", "apll", "1000m" }; @@ -136,7 +136,7 @@ static const u32 sysbus_mux_table[] = { 0, 1 }; static const u32 uart_mux_table[] = { 0, 1, 2 }; static const u32 a73_clksel_mux_table[] = { 0, 1, 2 }; -static struct hisi_mux_clock hi3559av100_mux_clks_crg[] __initdata = { +static struct hisi_mux_clock hi3559av100_mux_clks_crg[] = { { HI3559AV100_FMC_MUX, "fmc_mux", fmc_mux_p, ARRAY_SIZE(fmc_mux_p), CLK_SET_RATE_PARENT, 0x170, 2, 3, 0, fmc_mux_table, @@ -181,7 +181,7 @@ static struct hisi_mux_clock hi3559av100_mux_clks_crg[] __initdata = { }, }; -static struct hisi_gate_clock hi3559av100_gate_clks[] __initdata = { +static struct hisi_gate_clock hi3559av100_gate_clks[] = { { HI3559AV100_FMC_CLK, "clk_fmc", "fmc_mux", CLK_SET_RATE_PARENT, 0x170, 1, 0, @@ -336,7 +336,7 @@ static struct hisi_gate_clock hi3559av100_gate_clks[] __initdata = { }, }; -static struct hi3559av100_pll_clock hi3559av100_pll_clks[] __initdata = { +static struct hi3559av100_pll_clock hi3559av100_pll_clks[] = { { HI3559AV100_APLL_CLK, "apll", NULL, 0x0, 0, 24, 24, 3, 28, 3, 0x4, 0, 12, 12, 6 @@ -502,7 +502,7 @@ static void hisi_clk_register_pll(struct hi3559av100_pll_clock *clks, } } -static __init struct hisi_clock_data *hi3559av100_clk_register( +static struct hisi_clock_data *hi3559av100_clk_register( struct platform_device *pdev) { struct hisi_clock_data *clk_data; @@ -549,7 +549,7 @@ unregister_fixed_rate: return ERR_PTR(ret); } -static __init void hi3559av100_clk_unregister(struct platform_device *pdev) +static void hi3559av100_clk_unregister(struct platform_device *pdev) { struct hisi_crg_dev *crg = platform_get_drvdata(pdev); @@ -568,8 +568,7 @@ static const struct hisi_crg_funcs hi3559av100_crg_funcs = { .unregister_clks = hi3559av100_clk_unregister, }; -static struct hisi_fixed_rate_clock hi3559av100_shub_fixed_rate_clks[] - __initdata = { +static struct hisi_fixed_rate_clock hi3559av100_shub_fixed_rate_clks[] = { { HI3559AV100_SHUB_SOURCE_SOC_24M, "clk_source_24M", NULL, 0, 24000000UL, }, { HI3559AV100_SHUB_SOURCE_SOC_200M, "clk_source_200M", NULL, 0, 200000000UL, }, { HI3559AV100_SHUB_SOURCE_SOC_300M, "clk_source_300M", NULL, 0, 300000000UL, }, @@ -587,16 +586,16 @@ static struct hisi_fixed_rate_clock hi3559av100_shub_fixed_rate_clks[] /* shub mux clk */ static u32 shub_source_clk_mux_table[] = {0, 1, 2, 3}; -static const char *shub_source_clk_mux_p[] __initconst = { +static const char *shub_source_clk_mux_p[] = { "clk_source_24M", "clk_source_200M", "clk_source_300M", "clk_source_PLL" }; static u32 shub_uart_source_clk_mux_table[] = {0, 1, 2, 3}; -static const char *shub_uart_source_clk_mux_p[] __initconst = { +static const char *shub_uart_source_clk_mux_p[] = { "clk_uart_32K", "clk_uart_div_clk", "clk_uart_div_clk", "clk_source_24M" }; -static struct hisi_mux_clock hi3559av100_shub_mux_clks[] __initdata = { +static struct hisi_mux_clock hi3559av100_shub_mux_clks[] = { { HI3559AV100_SHUB_SOURCE_CLK, "shub_clk", shub_source_clk_mux_p, ARRAY_SIZE(shub_source_clk_mux_p), @@ -615,7 +614,7 @@ static struct hisi_mux_clock hi3559av100_shub_mux_clks[] __initdata = { static struct clk_div_table shub_spi_clk_table[] = {{0, 8}, {1, 4}, {2, 2}}; static struct clk_div_table shub_uart_div_clk_table[] = {{1, 8}, {2, 4}}; -static struct hisi_divider_clock hi3559av100_shub_div_clks[] __initdata = { +static struct hisi_divider_clock hi3559av100_shub_div_clks[] = { { HI3559AV100_SHUB_SPI_SOURCE_CLK, "clk_spi_clk", "shub_clk", 0, 0x20, 24, 2, CLK_DIVIDER_ALLOW_ZERO, shub_spi_clk_table, }, @@ -625,7 +624,7 @@ static struct hisi_divider_clock hi3559av100_shub_div_clks[] __initdata = { }; /* shub gate clk */ -static struct hisi_gate_clock hi3559av100_shub_gate_clks[] __initdata = { +static struct hisi_gate_clock hi3559av100_shub_gate_clks[] = { { HI3559AV100_SHUB_SPI0_CLK, "clk_shub_spi0", "clk_spi_clk", 0, 0x20, 1, 0, @@ -697,7 +696,7 @@ static int hi3559av100_shub_default_clk_set(void) return 0; } -static __init struct hisi_clock_data *hi3559av100_shub_clk_register( +static struct hisi_clock_data *hi3559av100_shub_clk_register( struct platform_device *pdev) { struct hisi_clock_data *clk_data = NULL; @@ -751,7 +750,7 @@ unregister_fixed_rate: return ERR_PTR(ret); } -static __init void hi3559av100_shub_clk_unregister(struct platform_device *pdev) +static void hi3559av100_shub_clk_unregister(struct platform_device *pdev) { struct hisi_crg_dev *crg = platform_get_drvdata(pdev); diff --git a/drivers/clk/meson/clk-regmap.c b/drivers/clk/meson/clk-regmap.c index dcd1757cc5df..8ad8977cf1c2 100644 --- a/drivers/clk/meson/clk-regmap.c +++ b/drivers/clk/meson/clk-regmap.c @@ -75,8 +75,8 @@ static unsigned long clk_regmap_div_recalc_rate(struct clk_hw *hw, div->width); } -static long clk_regmap_div_round_rate(struct clk_hw *hw, unsigned long rate, - unsigned long *prate) +static int clk_regmap_div_determine_rate(struct clk_hw *hw, + struct clk_rate_request *req) { struct clk_regmap *clk = to_clk_regmap(hw); struct clk_regmap_div_data *div = clk_get_regmap_div_data(clk); @@ -87,18 +87,17 @@ static long clk_regmap_div_round_rate(struct clk_hw *hw, unsigned long rate, if (div->flags & CLK_DIVIDER_READ_ONLY) { ret = regmap_read(clk->map, div->offset, &val); if (ret) - /* Gives a hint that something is wrong */ - return 0; + return ret; val >>= div->shift; val &= clk_div_mask(div->width); - return divider_ro_round_rate(hw, rate, prate, div->table, - div->width, div->flags, val); + return divider_ro_determine_rate(hw, req, div->table, + div->width, div->flags, val); } - return divider_round_rate(hw, rate, prate, div->table, div->width, - div->flags); + return divider_determine_rate(hw, req, div->table, div->width, + div->flags); } static int clk_regmap_div_set_rate(struct clk_hw *hw, unsigned long rate, @@ -123,14 +122,14 @@ static int clk_regmap_div_set_rate(struct clk_hw *hw, unsigned long rate, const struct clk_ops clk_regmap_divider_ops = { .recalc_rate = clk_regmap_div_recalc_rate, - .round_rate = clk_regmap_div_round_rate, + .determine_rate = clk_regmap_div_determine_rate, .set_rate = clk_regmap_div_set_rate, }; EXPORT_SYMBOL_GPL(clk_regmap_divider_ops); const struct clk_ops clk_regmap_divider_ro_ops = { .recalc_rate = clk_regmap_div_recalc_rate, - .round_rate = clk_regmap_div_round_rate, + .determine_rate = clk_regmap_div_determine_rate, }; EXPORT_SYMBOL_GPL(clk_regmap_divider_ro_ops); diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h index 162a2e5546a3..d83b829305c0 100644 --- a/include/linux/clk-provider.h +++ b/include/linux/clk-provider.h @@ -629,6 +629,12 @@ long divider_ro_round_rate_parent(struct clk_hw *hw, struct clk_hw *parent, unsigned long rate, unsigned long *prate, const struct clk_div_table *table, u8 width, unsigned long flags, unsigned int val); +int divider_determine_rate(struct clk_hw *hw, struct clk_rate_request *req, + const struct clk_div_table *table, u8 width, + unsigned long flags); +int divider_ro_determine_rate(struct clk_hw *hw, struct clk_rate_request *req, + const struct clk_div_table *table, u8 width, + unsigned long flags, unsigned int val); int divider_get_val(unsigned long rate, unsigned long parent_rate, const struct clk_div_table *table, u8 width, unsigned long flags); |