diff options
Diffstat (limited to 'drivers')
150 files changed, 8798 insertions, 2898 deletions
diff --git a/drivers/aiodev/lm75.c b/drivers/aiodev/lm75.c index 8e5948f468..1900636555 100644 --- a/drivers/aiodev/lm75.c +++ b/drivers/aiodev/lm75.c @@ -182,6 +182,8 @@ static int lm75_probe(struct device_d *dev) clr_mask |= 1 << 5; /* not one-shot mode */ data->resolution = 12; break; + default: + return -EINVAL; } /* configure as specified */ diff --git a/drivers/base/bus.c b/drivers/base/bus.c index 1038d20a12..aac5b69f34 100644 --- a/drivers/base/bus.c +++ b/drivers/base/bus.c @@ -75,7 +75,7 @@ int device_match_of_modalias(struct device_d *dev, struct driver_d *drv) { const struct platform_device_id *id = drv->id_table; const char *of_modalias = NULL, *p; - int cplen; + const struct property *prop; const char *compat; if (!device_match(dev, drv)) @@ -84,25 +84,16 @@ int device_match_of_modalias(struct device_d *dev, struct driver_d *drv) if (!id || !IS_ENABLED(CONFIG_OFDEVICE) || !dev->device_node) return -1; - compat = of_get_property(dev->device_node, "compatible", &cplen); - if (!compat) - return -1; - - p = strchr(compat, ','); - of_modalias = p ? p + 1 : compat; - - while (id->name) { - if (!strcmp(id->name, dev->name)) { - dev->id_entry = id; - return 0; - } + of_property_for_each_string(dev->device_node, "compatible", prop, compat) { + p = strchr(compat, ','); + of_modalias = p ? p + 1 : compat; - if (of_modalias && !strcmp(id->name, of_modalias)) { - dev->id_entry = id; - return 0; + for (id = drv->id_table; id->name; id++) { + if (!strcmp(id->name, dev->name) || !strcmp(id->name, of_modalias)) { + dev->id_entry = id; + return 0; + } } - - id++; } return -1; diff --git a/drivers/base/driver.c b/drivers/base/driver.c index f60533c59e..1fa3f6c6fa 100644 --- a/drivers/base/driver.c +++ b/drivers/base/driver.c @@ -480,9 +480,7 @@ int dev_set_name(struct device_d *dev, const char *fmt, ...) */ free(oldname); - WARN_ON(err < 0); - - return err; + return WARN_ON(err < 0) ? err : 0; } EXPORT_SYMBOL_GPL(dev_set_name); diff --git a/drivers/base/regmap/Makefile b/drivers/base/regmap/Makefile index ab2387037d..b12b695311 100644 --- a/drivers/base/regmap/Makefile +++ b/drivers/base/regmap/Makefile @@ -1,2 +1,3 @@ obj-y += regmap.o obj-y += regmap-mmio.o +obj-$(CONFIG_I2C) += regmap-i2c.o diff --git a/drivers/base/regmap/regmap-i2c.c b/drivers/base/regmap/regmap-i2c.c new file mode 100644 index 0000000000..88b24ae6a8 --- /dev/null +++ b/drivers/base/regmap/regmap-i2c.c @@ -0,0 +1,44 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2021, Ahmad Fatoum, Pengutronix + */ + +#include <i2c/i2c.h> +#include <regmap.h> + + +static int regmap_i2c_reg_read(void *client, unsigned int reg, unsigned int *val) +{ + u8 buf[1]; + int ret; + + ret = i2c_read_reg(client, reg, buf, 1); + if (ret != 1) + return ret; + + *val = buf[0]; + return 0; +} + +static int regmap_i2c_reg_write(void *client, unsigned int reg, unsigned int val) +{ + u8 buf[] = { val & 0xff }; + int ret; + + ret = i2c_write_reg(client, reg, buf, 1); + if (ret != 1) + return ret; + + return 0; +} + +static const struct regmap_bus regmap_regmap_i2c_bus = { + .reg_write = regmap_i2c_reg_write, + .reg_read = regmap_i2c_reg_read, +}; + +struct regmap *regmap_init_i2c(struct i2c_client *client, + const struct regmap_config *config) +{ + return regmap_init(&client->dev, ®map_regmap_i2c_bus, client, config); +} diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c index 6613670263..1af0c15a7b 100644 --- a/drivers/base/regmap/regmap.c +++ b/drivers/base/regmap/regmap.c @@ -132,6 +132,11 @@ struct regmap *dev_get_regmap(struct device_d *dev, const char *name) return ERR_PTR(-ENOENT); } +struct device_d *regmap_get_device(struct regmap *map) +{ + return map->dev; +} + /* * regmap_write - write a register in a map * diff --git a/drivers/clk/at91/clk-audio-pll.c b/drivers/clk/at91/clk-audio-pll.c index 47bff32fe8..e9a30b0516 100644 --- a/drivers/clk/at91/clk-audio-pll.c +++ b/drivers/clk/at91/clk-audio-pll.c @@ -57,7 +57,7 @@ #define AUDIO_PLL_FOUT_MAX 700000000UL struct clk_audio_frac { - struct clk clk; + struct clk_hw hw; struct regmap *regmap; u32 fracr; u8 nd; @@ -65,7 +65,7 @@ struct clk_audio_frac { }; struct clk_audio_pad { - struct clk clk; + struct clk_hw hw; struct regmap *regmap; u8 qdaudio; u8 div; @@ -73,19 +73,19 @@ struct clk_audio_pad { }; struct clk_audio_pmc { - struct clk clk; + struct clk_hw hw; struct regmap *regmap; u8 qdpmc; const char *parent_name; }; -#define to_clk_audio_frac(clk) container_of(clk, struct clk_audio_frac, clk) -#define to_clk_audio_pad(clk) container_of(clk, struct clk_audio_pad, clk) -#define to_clk_audio_pmc(clk) container_of(clk, struct clk_audio_pmc, clk) +#define to_clk_audio_frac(_hw) container_of(_hw, struct clk_audio_frac, hw) +#define to_clk_audio_pad(_hw) container_of(_hw, struct clk_audio_pad, hw) +#define to_clk_audio_pmc(_hw) container_of(_hw, struct clk_audio_pmc, hw) -static int clk_audio_pll_frac_enable(struct clk *clk) +static int clk_audio_pll_frac_enable(struct clk_hw *hw) { - struct clk_audio_frac *frac = to_clk_audio_frac(clk); + struct clk_audio_frac *frac = to_clk_audio_frac(hw); regmap_update_bits(frac->regmap, AT91_PMC_AUDIO_PLL0, AT91_PMC_AUDIO_PLL_RESETN, 0); @@ -108,9 +108,9 @@ static int clk_audio_pll_frac_enable(struct clk *clk) return 0; } -static int clk_audio_pll_pad_enable(struct clk *clk) +static int clk_audio_pll_pad_enable(struct clk_hw *hw) { - struct clk_audio_pad *apad_ck = to_clk_audio_pad(clk); + struct clk_audio_pad *apad_ck = to_clk_audio_pad(hw); regmap_update_bits(apad_ck->regmap, AT91_PMC_AUDIO_PLL1, AT91_PMC_AUDIO_PLL_QDPAD_MASK, @@ -121,9 +121,9 @@ static int clk_audio_pll_pad_enable(struct clk *clk) return 0; } -static int clk_audio_pll_pmc_enable(struct clk *clk) +static int clk_audio_pll_pmc_enable(struct clk_hw *hw) { - struct clk_audio_pmc *apmc_ck = to_clk_audio_pmc(clk); + struct clk_audio_pmc *apmc_ck = to_clk_audio_pmc(hw); regmap_update_bits(apmc_ck->regmap, AT91_PMC_AUDIO_PLL0, AT91_PMC_AUDIO_PLL_PMCEN | @@ -133,9 +133,9 @@ static int clk_audio_pll_pmc_enable(struct clk *clk) return 0; } -static void clk_audio_pll_frac_disable(struct clk *clk) +static void clk_audio_pll_frac_disable(struct clk_hw *hw) { - struct clk_audio_frac *frac = to_clk_audio_frac(clk); + struct clk_audio_frac *frac = to_clk_audio_frac(hw); regmap_update_bits(frac->regmap, AT91_PMC_AUDIO_PLL0, AT91_PMC_AUDIO_PLL_PLLEN, 0); @@ -144,17 +144,17 @@ static void clk_audio_pll_frac_disable(struct clk *clk) AT91_PMC_AUDIO_PLL_RESETN, 0); } -static void clk_audio_pll_pad_disable(struct clk *clk) +static void clk_audio_pll_pad_disable(struct clk_hw *hw) { - struct clk_audio_pad *apad_ck = to_clk_audio_pad(clk); + struct clk_audio_pad *apad_ck = to_clk_audio_pad(hw); regmap_update_bits(apad_ck->regmap, AT91_PMC_AUDIO_PLL0, AT91_PMC_AUDIO_PLL_PADEN, 0); } -static void clk_audio_pll_pmc_disable(struct clk *clk) +static void clk_audio_pll_pmc_disable(struct clk_hw *hw) { - struct clk_audio_pmc *apmc_ck = to_clk_audio_pmc(clk); + struct clk_audio_pmc *apmc_ck = to_clk_audio_pmc(hw); regmap_update_bits(apmc_ck->regmap, AT91_PMC_AUDIO_PLL0, AT91_PMC_AUDIO_PLL_PMCEN, 0); @@ -174,10 +174,10 @@ static unsigned long clk_audio_pll_fout(unsigned long parent_rate, return parent_rate * (nd + 1) + fr; } -static unsigned long clk_audio_pll_frac_recalc_rate(struct clk *clk, +static unsigned long clk_audio_pll_frac_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) { - struct clk_audio_frac *frac = to_clk_audio_frac(clk); + struct clk_audio_frac *frac = to_clk_audio_frac(hw); unsigned long fout; fout = clk_audio_pll_fout(parent_rate, frac->nd, frac->fracr); @@ -188,10 +188,10 @@ static unsigned long clk_audio_pll_frac_recalc_rate(struct clk *clk, return fout; } -static unsigned long clk_audio_pll_pad_recalc_rate(struct clk *clk, +static unsigned long clk_audio_pll_pad_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) { - struct clk_audio_pad *apad_ck = to_clk_audio_pad(clk); + struct clk_audio_pad *apad_ck = to_clk_audio_pad(hw); unsigned long apad_rate = 0; if (apad_ck->qdaudio && apad_ck->div) @@ -203,10 +203,10 @@ static unsigned long clk_audio_pll_pad_recalc_rate(struct clk *clk, return apad_rate; } -static unsigned long clk_audio_pll_pmc_recalc_rate(struct clk *clk, +static unsigned long clk_audio_pll_pmc_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) { - struct clk_audio_pmc *apmc_ck = to_clk_audio_pmc(clk); + struct clk_audio_pmc *apmc_ck = to_clk_audio_pmc(hw); unsigned long apmc_rate = 0; apmc_rate = parent_rate / (apmc_ck->qdpmc + 1); @@ -245,10 +245,10 @@ static int clk_audio_pll_frac_compute_frac(unsigned long rate, return 0; } -static long clk_audio_pll_pad_round_rate(struct clk *clk, unsigned long rate, +static long clk_audio_pll_pad_round_rate(struct clk_hw *hw, unsigned long rate, unsigned long *parent_rate) { - struct clk *pclk = clk_get_parent(clk); + struct clk *pclk = clk_get_parent(clk_hw_to_clk(hw)); long best_rate = -EINVAL; unsigned long best_parent_rate; unsigned long tmp_qd; @@ -296,9 +296,10 @@ static long clk_audio_pll_pad_round_rate(struct clk *clk, unsigned long rate, return best_rate; } -static long clk_audio_pll_pmc_round_rate(struct clk *clk, unsigned long rate, +static long clk_audio_pll_pmc_round_rate(struct clk_hw *hw, unsigned long rate, unsigned long *parent_rate) { + struct clk *clk = clk_hw_to_clk(hw); struct clk *pclk = clk_get_parent(clk); long best_rate = -EINVAL; unsigned long best_parent_rate = 0; @@ -336,10 +337,10 @@ static long clk_audio_pll_pmc_round_rate(struct clk *clk, unsigned long rate, return best_rate; } -static int clk_audio_pll_frac_set_rate(struct clk *clk, unsigned long rate, +static int clk_audio_pll_frac_set_rate(struct clk_hw *hw, unsigned long rate, unsigned long parent_rate) { - struct clk_audio_frac *frac = to_clk_audio_frac(clk); + struct clk_audio_frac *frac = to_clk_audio_frac(hw); unsigned long fracr, nd; int ret; @@ -359,10 +360,10 @@ static int clk_audio_pll_frac_set_rate(struct clk *clk, unsigned long rate, return 0; } -static int clk_audio_pll_pad_set_rate(struct clk *clk, unsigned long rate, +static int clk_audio_pll_pad_set_rate(struct clk_hw *hw, unsigned long rate, unsigned long parent_rate) { - struct clk_audio_pad *apad_ck = to_clk_audio_pad(clk); + struct clk_audio_pad *apad_ck = to_clk_audio_pad(hw); u8 tmp_div; pr_debug("A PLL/PAD: %s, rate = %lu (parent_rate = %lu)\n", __func__, @@ -383,10 +384,10 @@ static int clk_audio_pll_pad_set_rate(struct clk *clk, unsigned long rate, return 0; } -static int clk_audio_pll_pmc_set_rate(struct clk *clk, unsigned long rate, +static int clk_audio_pll_pmc_set_rate(struct clk_hw *hw, unsigned long rate, unsigned long parent_rate) { - struct clk_audio_pmc *apmc_ck = to_clk_audio_pmc(clk); + struct clk_audio_pmc *apmc_ck = to_clk_audio_pmc(hw); if (!rate) return -EINVAL; @@ -433,22 +434,22 @@ at91_clk_register_audio_pll_frac(struct regmap *regmap, const char *name, if (!frac_ck) return ERR_PTR(-ENOMEM); - frac_ck->clk.name = name; - frac_ck->clk.ops = &audio_pll_frac_ops; + frac_ck->hw.clk.name = name; + frac_ck->hw.clk.ops = &audio_pll_frac_ops; frac_ck->parent_name = parent_name; - frac_ck->clk.parent_names = &frac_ck->parent_name; - frac_ck->clk.num_parents = 1; + frac_ck->hw.clk.parent_names = &frac_ck->parent_name; + frac_ck->hw.clk.num_parents = 1; /* frac_ck->clk.flags = CLK_SET_RATE_GATE; */ frac_ck->regmap = regmap; - ret = clk_register(&frac_ck->clk); + ret = bclk_register(&frac_ck->hw.clk); if (ret) { kfree(frac_ck); return ERR_PTR(ret); } - return &frac_ck->clk; + return &frac_ck->hw.clk; } struct clk * __init @@ -462,23 +463,23 @@ at91_clk_register_audio_pll_pad(struct regmap *regmap, const char *name, if (!apad_ck) return ERR_PTR(-ENOMEM); - apad_ck->clk.name = name; - apad_ck->clk.ops = &audio_pll_pad_ops; + apad_ck->hw.clk.name = name; + apad_ck->hw.clk.ops = &audio_pll_pad_ops; apad_ck->parent_name = parent_name; - apad_ck->clk.parent_names = &apad_ck->parent_name; - apad_ck->clk.num_parents = 1; + apad_ck->hw.clk.parent_names = &apad_ck->parent_name; + apad_ck->hw.clk.num_parents = 1; /* apad_ck->clk.flags = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE | CLK_SET_RATE_PARENT; */ apad_ck->regmap = regmap; - ret = clk_register(&apad_ck->clk); + ret = bclk_register(&apad_ck->hw.clk); if (ret) { kfree(apad_ck); return ERR_PTR(ret); } - return &apad_ck->clk; + return &apad_ck->hw.clk; } struct clk * __init @@ -492,21 +493,21 @@ at91_clk_register_audio_pll_pmc(struct regmap *regmap, const char *name, if (!apmc_ck) return ERR_PTR(-ENOMEM); - apmc_ck->clk.name = name; - apmc_ck->clk.ops = &audio_pll_pmc_ops; + apmc_ck->hw.clk.name = name; + apmc_ck->hw.clk.ops = &audio_pll_pmc_ops; apmc_ck->parent_name = parent_name; - apmc_ck->clk.parent_names = &apmc_ck->parent_name; - apmc_ck->clk.num_parents = 1; + apmc_ck->hw.clk.parent_names = &apmc_ck->parent_name; + apmc_ck->hw.clk.num_parents = 1; /* apmc_ck.flags = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE | CLK_SET_RATE_PARENT; */ apmc_ck->regmap = regmap; - ret = clk_register(&apmc_ck->clk); + ret = bclk_register(&apmc_ck->hw.clk); if (ret) { kfree(apmc_ck); return ERR_PTR(ret); } - return &apmc_ck->clk; + return &apmc_ck->hw.clk; } diff --git a/drivers/clk/at91/clk-generated.c b/drivers/clk/at91/clk-generated.c index 56b800facb..628ff407d9 100644 --- a/drivers/clk/at91/clk-generated.c +++ b/drivers/clk/at91/clk-generated.c @@ -23,7 +23,7 @@ #define GCK_INDEX_DT_AUDIO_PLL 5 struct clk_generated { - struct clk hw; + struct clk_hw hw; struct regmap *regmap; struct clk_range range; u32 id; @@ -33,10 +33,10 @@ struct clk_generated { bool audio_pll_allowed; }; -#define to_clk_generated(hw) \ - container_of(hw, struct clk_generated, hw) +#define to_clk_generated(_hw) \ + container_of(_hw, struct clk_generated, hw) -static int clk_generated_enable(struct clk *hw) +static int clk_generated_enable(struct clk_hw *hw) { struct clk_generated *gck = to_clk_generated(hw); @@ -55,7 +55,7 @@ static int clk_generated_enable(struct clk *hw) return 0; } -static void clk_generated_disable(struct clk *hw) +static void clk_generated_disable(struct clk_hw *hw) { struct clk_generated *gck = to_clk_generated(hw); @@ -66,7 +66,7 @@ static void clk_generated_disable(struct clk *hw) gck->layout->cmd); } -static int clk_generated_is_enabled(struct clk *hw) +static int clk_generated_is_enabled(struct clk_hw *hw) { struct clk_generated *gck = to_clk_generated(hw); unsigned int status; @@ -79,7 +79,7 @@ static int clk_generated_is_enabled(struct clk *hw) } static unsigned long -clk_generated_recalc_rate(struct clk *hw, +clk_generated_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) { struct clk_generated *gck = to_clk_generated(hw); @@ -88,18 +88,18 @@ clk_generated_recalc_rate(struct clk *hw, } /* No modification of hardware as we have the flag CLK_SET_PARENT_GATE set */ -static int clk_generated_set_parent(struct clk *hw, u8 index) +static int clk_generated_set_parent(struct clk_hw *hw, u8 index) { struct clk_generated *gck = to_clk_generated(hw); - if (index >= clk_get_num_parents(hw)) + if (index >= clk_get_num_parents(clk_hw_to_clk(hw))) return -EINVAL; gck->parent_id = index; return 0; } -static int clk_generated_get_parent(struct clk *hw) +static int clk_generated_get_parent(struct clk_hw *hw) { struct clk_generated *gck = to_clk_generated(hw); @@ -107,7 +107,7 @@ static int clk_generated_get_parent(struct clk *hw) } /* No modification of hardware as we have the flag CLK_SET_RATE_GATE set */ -static int clk_generated_set_rate(struct clk *hw, +static int clk_generated_set_rate(struct clk_hw *hw, unsigned long rate, unsigned long parent_rate) { @@ -168,7 +168,7 @@ at91_clk_register_generated(struct regmap *regmap, { size_t parents_array_size; struct clk_generated *gck; - struct clk *hw; + struct clk *clk; int ret; gck = kzalloc(sizeof(*gck), GFP_KERNEL); @@ -176,12 +176,12 @@ at91_clk_register_generated(struct regmap *regmap, return ERR_PTR(-ENOMEM); gck->id = id; - gck->hw.name = name; - gck->hw.ops = &generated_ops; + gck->hw.clk.name = name; + gck->hw.clk.ops = &generated_ops; - parents_array_size = num_parents * sizeof(gck->hw.parent_names[0]); - gck->hw.parent_names = xmemdup(parent_names, parents_array_size); - gck->hw.num_parents = num_parents; + parents_array_size = num_parents * sizeof(gck->hw.clk.parent_names[0]); + gck->hw.clk.parent_names = xmemdup(parent_names, parents_array_size); + gck->hw.clk.num_parents = num_parents; /* gck->hw.flags = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE | CLK_SET_PARENT; */ gck->regmap = regmap; @@ -190,14 +190,14 @@ at91_clk_register_generated(struct regmap *regmap, gck->layout = layout; clk_generated_startup(gck); - hw = &gck->hw; - ret = clk_register(&gck->hw); + clk = &gck->hw.clk; + ret = bclk_register(&gck->hw.clk); if (ret) { kfree(gck); - hw = ERR_PTR(ret); + clk = ERR_PTR(ret); } else { pmc_register_id(id); } - return hw; + return clk; } diff --git a/drivers/clk/at91/clk-h32mx.c b/drivers/clk/at91/clk-h32mx.c index 6052886cca..b2c5007cf7 100644 --- a/drivers/clk/at91/clk-h32mx.c +++ b/drivers/clk/at91/clk-h32mx.c @@ -20,14 +20,14 @@ #define H32MX_MAX_FREQ 90000000 struct clk_sama5d4_h32mx { - struct clk hw; + struct clk_hw hw; struct regmap *regmap; const char *parent; }; -#define to_clk_sama5d4_h32mx(hw) container_of(hw, struct clk_sama5d4_h32mx, hw) +#define to_clk_sama5d4_h32mx(_hw) container_of(_hw, struct clk_sama5d4_h32mx, hw) -static unsigned long clk_sama5d4_h32mx_recalc_rate(struct clk *hw, +static unsigned long clk_sama5d4_h32mx_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) { struct clk_sama5d4_h32mx *h32mxclk = to_clk_sama5d4_h32mx(hw); @@ -42,7 +42,7 @@ static unsigned long clk_sama5d4_h32mx_recalc_rate(struct clk *hw, return parent_rate; } -static long clk_sama5d4_h32mx_round_rate(struct clk *hw, unsigned long rate, +static long clk_sama5d4_h32mx_round_rate(struct clk_hw *hw, unsigned long rate, unsigned long *parent_rate) { unsigned long div; @@ -59,7 +59,7 @@ static long clk_sama5d4_h32mx_round_rate(struct clk *hw, unsigned long rate, return *parent_rate; } -static int clk_sama5d4_h32mx_set_rate(struct clk *hw, unsigned long rate, +static int clk_sama5d4_h32mx_set_rate(struct clk_hw *hw, unsigned long rate, unsigned long parent_rate) { struct clk_sama5d4_h32mx *h32mxclk = to_clk_sama5d4_h32mx(hw); @@ -95,19 +95,19 @@ at91_clk_register_h32mx(struct regmap *regmap, const char *name, return ERR_PTR(-ENOMEM); h32mxclk->parent = parent_name; - h32mxclk->hw.name = name; - h32mxclk->hw.ops = &h32mx_ops; - h32mxclk->hw.parent_names = &h32mxclk->parent; - h32mxclk->hw.num_parents = 1; + h32mxclk->hw.clk.name = name; + h32mxclk->hw.clk.ops = &h32mx_ops; + h32mxclk->hw.clk.parent_names = &h32mxclk->parent; + h32mxclk->hw.clk.num_parents = 1; /* h32mxclk.hw.flags = CLK_SET_RATE_GATE; */ h32mxclk->regmap = regmap; - ret = clk_register(&h32mxclk->hw); + ret = bclk_register(&h32mxclk->hw.clk); if (ret) { kfree(h32mxclk); return ERR_PTR(ret); } - return &h32mxclk->hw; + return &h32mxclk->hw.clk; } diff --git a/drivers/clk/at91/clk-i2s-mux.c b/drivers/clk/at91/clk-i2s-mux.c index f906007ed5..510ea24bbc 100644 --- a/drivers/clk/at91/clk-i2s-mux.c +++ b/drivers/clk/at91/clk-i2s-mux.c @@ -21,17 +21,17 @@ #include "pmc.h" struct clk_i2s_mux { - struct clk clk; + struct clk_hw hw; struct regmap *regmap; u8 bus_id; const char *parent_names[]; }; -#define to_clk_i2s_mux(clk) container_of(clk, struct clk_i2s_mux, clk) +#define to_clk_i2s_mux(_hw) container_of(_hw, struct clk_i2s_mux, hw) -static int clk_i2s_mux_get_parent(struct clk *clk) +static int clk_i2s_mux_get_parent(struct clk_hw *hw) { - struct clk_i2s_mux *mux = to_clk_i2s_mux(clk); + struct clk_i2s_mux *mux = to_clk_i2s_mux(hw); u32 val; regmap_read(mux->regmap, AT91_SFR_I2SCLKSEL, &val); @@ -39,9 +39,9 @@ static int clk_i2s_mux_get_parent(struct clk *clk) return (val & BIT(mux->bus_id)) >> mux->bus_id; } -static int clk_i2s_mux_set_parent(struct clk *clk, u8 index) +static int clk_i2s_mux_set_parent(struct clk_hw *hw, u8 index) { - struct clk_i2s_mux *mux = to_clk_i2s_mux(clk); + struct clk_i2s_mux *mux = to_clk_i2s_mux(hw); return regmap_update_bits(mux->regmap, AT91_SFR_I2SCLKSEL, BIT(mux->bus_id), index << mux->bus_id); @@ -66,21 +66,21 @@ at91_clk_i2s_mux_register(struct regmap *regmap, const char *name, if (!i2s_ck) return ERR_PTR(-ENOMEM); - i2s_ck->clk.name = name; - i2s_ck->clk.ops = &clk_i2s_mux_ops; + i2s_ck->hw.clk.name = name; + i2s_ck->hw.clk.ops = &clk_i2s_mux_ops; memcpy(i2s_ck->parent_names, parent_names, num_parents * sizeof(i2s_ck->parent_names[0])); - i2s_ck->clk.parent_names = &i2s_ck->parent_names[0]; - i2s_ck->clk.num_parents = num_parents; + i2s_ck->hw.clk.parent_names = &i2s_ck->parent_names[0]; + i2s_ck->hw.clk.num_parents = num_parents; i2s_ck->bus_id = bus_id; i2s_ck->regmap = regmap; - ret = clk_register(&i2s_ck->clk); + ret = bclk_register(&i2s_ck->hw.clk); if (ret) { kfree(i2s_ck); return ERR_PTR(ret); } - return &i2s_ck->clk; + return &i2s_ck->hw.clk; } diff --git a/drivers/clk/at91/clk-main.c b/drivers/clk/at91/clk-main.c index 08abb1673b..38e72d6538 100644 --- a/drivers/clk/at91/clk-main.c +++ b/drivers/clk/at91/clk-main.c @@ -26,36 +26,36 @@ AT91_PMC_OSCBYPASS)) ? 1 : 0) struct clk_main_osc { - struct clk clk; + struct clk_hw hw; struct regmap *regmap; const char *parent; }; -#define to_clk_main_osc(clk) container_of(clk, struct clk_main_osc, clk) +#define to_clk_main_osc(_hw) container_of(_hw, struct clk_main_osc, hw) struct clk_main_rc_osc { - struct clk clk; + struct clk_hw hw; struct regmap *regmap; unsigned long frequency; }; -#define to_clk_main_rc_osc(clk) container_of(clk, struct clk_main_rc_osc, clk) +#define to_clk_main_rc_osc(_hw) container_of(_hw, struct clk_main_rc_osc, hw) struct clk_rm9200_main { - struct clk clk; + struct clk_hw hw; struct regmap *regmap; const char *parent; }; -#define to_clk_rm9200_main(clk) container_of(clk, struct clk_rm9200_main, clk) +#define to_clk_rm9200_main(_hw) container_of(_hw, struct clk_rm9200_main, hw) struct clk_sam9x5_main { - struct clk clk; + struct clk_hw hw; struct regmap *regmap; u8 parent; }; -#define to_clk_sam9x5_main(clk) container_of(clk, struct clk_sam9x5_main, clk) +#define to_clk_sam9x5_main(_hw) container_of(_hw, struct clk_sam9x5_main, hw) static inline bool clk_main_osc_ready(struct regmap *regmap) { @@ -66,9 +66,9 @@ static inline bool clk_main_osc_ready(struct regmap *regmap) return status & AT91_PMC_MOSCS; } -static int clk_main_osc_enable(struct clk *clk) +static int clk_main_osc_enable(struct clk_hw *hw) { - struct clk_main_osc *osc = to_clk_main_osc(clk); + struct clk_main_osc *osc = to_clk_main_osc(hw); struct regmap *regmap = osc->regmap; u32 tmp; @@ -89,9 +89,9 @@ static int clk_main_osc_enable(struct clk *clk) return 0; } -static void clk_main_osc_disable(struct clk *clk) +static void clk_main_osc_disable(struct clk_hw *hw) { - struct clk_main_osc *osc = to_clk_main_osc(clk); + struct clk_main_osc *osc = to_clk_main_osc(hw); struct regmap *regmap = osc->regmap; u32 tmp; @@ -106,9 +106,9 @@ static void clk_main_osc_disable(struct clk *clk) regmap_write(regmap, AT91_CKGR_MOR, tmp | AT91_PMC_KEY); } -static int clk_main_osc_is_enabled(struct clk *clk) +static int clk_main_osc_is_enabled(struct clk_hw *hw) { - struct clk_main_osc *osc = to_clk_main_osc(clk); + struct clk_main_osc *osc = to_clk_main_osc(hw); struct regmap *regmap = osc->regmap; u32 tmp, status; @@ -142,10 +142,10 @@ at91_clk_register_main_osc(struct regmap *regmap, osc = xzalloc(sizeof(*osc)); osc->parent = parent_name; - osc->clk.name = name; - osc->clk.ops = &main_osc_ops; - osc->clk.parent_names = &osc->parent; - osc->clk.num_parents = 1; + osc->hw.clk.name = name; + osc->hw.clk.ops = &main_osc_ops; + osc->hw.clk.parent_names = &osc->parent; + osc->hw.clk.num_parents = 1; osc->regmap = regmap; if (bypass) @@ -154,13 +154,13 @@ at91_clk_register_main_osc(struct regmap *regmap, AT91_PMC_MOSCEN, AT91_PMC_OSCBYPASS | AT91_PMC_KEY); - ret = clk_register(&osc->clk); + ret = bclk_register(&osc->hw.clk); if (ret) { free(osc); return ERR_PTR(ret); } - return &osc->clk; + return &osc->hw.clk; } static bool clk_main_rc_osc_ready(struct regmap *regmap) @@ -172,9 +172,9 @@ static bool clk_main_rc_osc_ready(struct regmap *regmap) return status & AT91_PMC_MOSCRCS; } -static int clk_main_rc_osc_enable(struct clk *clk) +static int clk_main_rc_osc_enable(struct clk_hw *hw) { - struct clk_main_rc_osc *osc = to_clk_main_rc_osc(clk); + struct clk_main_rc_osc *osc = to_clk_main_rc_osc(hw); struct regmap *regmap = osc->regmap; unsigned int mor; @@ -191,9 +191,9 @@ static int clk_main_rc_osc_enable(struct clk *clk) return 0; } -static void clk_main_rc_osc_disable(struct clk *clk) +static void clk_main_rc_osc_disable(struct clk_hw *hw) { - struct clk_main_rc_osc *osc = to_clk_main_rc_osc(clk); + struct clk_main_rc_osc *osc = to_clk_main_rc_osc(hw); struct regmap *regmap = osc->regmap; unsigned int mor; @@ -206,9 +206,9 @@ static void clk_main_rc_osc_disable(struct clk *clk) MOR_KEY_MASK | AT91_PMC_MOSCRCEN, AT91_PMC_KEY); } -static int clk_main_rc_osc_is_enabled(struct clk *clk) +static int clk_main_rc_osc_is_enabled(struct clk_hw *hw) { - struct clk_main_rc_osc *osc = to_clk_main_rc_osc(clk); + struct clk_main_rc_osc *osc = to_clk_main_rc_osc(hw); struct regmap *regmap = osc->regmap; unsigned int mor, status; @@ -218,10 +218,10 @@ static int clk_main_rc_osc_is_enabled(struct clk *clk) return (mor & AT91_PMC_MOSCRCEN) && (status & AT91_PMC_MOSCRCS); } -static unsigned long clk_main_rc_osc_recalc_rate(struct clk *clk, +static unsigned long clk_main_rc_osc_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) { - struct clk_main_rc_osc *osc = to_clk_main_rc_osc(clk); + struct clk_main_rc_osc *osc = to_clk_main_rc_osc(hw); return osc->frequency; } @@ -246,21 +246,21 @@ at91_clk_register_main_rc_osc(struct regmap *regmap, osc = xzalloc(sizeof(*osc)); - osc->clk.name = name; - osc->clk.ops = &main_rc_osc_ops; - osc->clk.parent_names = NULL; - osc->clk.num_parents = 0; + osc->hw.clk.name = name; + osc->hw.clk.ops = &main_rc_osc_ops; + osc->hw.clk.parent_names = NULL; + osc->hw.clk.num_parents = 0; osc->regmap = regmap; osc->frequency = frequency; - ret = clk_register(&osc->clk); + ret = bclk_register(&osc->hw.clk); if (ret) { kfree(osc); return ERR_PTR(ret); } - return &osc->clk; + return &osc->hw.clk; } static int clk_main_probe_frequency(struct regmap *regmap) @@ -293,16 +293,16 @@ static unsigned long clk_main_recalc_rate(struct regmap *regmap, return ((mcfr & AT91_PMC_MAINF) * SLOW_CLOCK_FREQ) / MAINF_DIV; } -static int clk_rm9200_main_enable(struct clk *clk) +static int clk_rm9200_main_enable(struct clk_hw *hw) { - struct clk_rm9200_main *clkmain = to_clk_rm9200_main(clk); + struct clk_rm9200_main *clkmain = to_clk_rm9200_main(hw); return clk_main_probe_frequency(clkmain->regmap); } -static int clk_rm9200_main_is_enabled(struct clk *clk) +static int clk_rm9200_main_is_enabled(struct clk_hw *hw) { - struct clk_rm9200_main *clkmain = to_clk_rm9200_main(clk); + struct clk_rm9200_main *clkmain = to_clk_rm9200_main(hw); unsigned int status; regmap_read(clkmain->regmap, AT91_CKGR_MCFR, &status); @@ -310,10 +310,10 @@ static int clk_rm9200_main_is_enabled(struct clk *clk) return status & AT91_PMC_MAINRDY ? 1 : 0; } -static unsigned long clk_rm9200_main_recalc_rate(struct clk *clk, +static unsigned long clk_rm9200_main_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) { - struct clk_rm9200_main *clkmain = to_clk_rm9200_main(clk); + struct clk_rm9200_main *clkmain = to_clk_rm9200_main(hw); return clk_main_recalc_rate(clkmain->regmap, parent_rate); } @@ -341,19 +341,19 @@ at91_clk_register_rm9200_main(struct regmap *regmap, clkmain = xzalloc(sizeof(*clkmain)); clkmain->parent = parent_name; - clkmain->clk.name = name; - clkmain->clk.ops = &rm9200_main_ops; - clkmain->clk.parent_names = &clkmain->parent; - clkmain->clk.num_parents = 1; + clkmain->hw.clk.name = name; + clkmain->hw.clk.ops = &rm9200_main_ops; + clkmain->hw.clk.parent_names = &clkmain->parent; + clkmain->hw.clk.num_parents = 1; clkmain->regmap = regmap; - ret = clk_register(&clkmain->clk); + ret = bclk_register(&clkmain->hw.clk); if (ret) { kfree(clkmain); return ERR_PTR(ret); } - return &clkmain->clk; + return &clkmain->hw.clk; } static inline bool clk_sam9x5_main_ready(struct regmap *regmap) @@ -365,9 +365,9 @@ static inline bool clk_sam9x5_main_ready(struct regmap *regmap) return status & AT91_PMC_MOSCSELS ? 1 : 0; } -static int clk_sam9x5_main_enable(struct clk *clk) +static int clk_sam9x5_main_enable(struct clk_hw *hw) { - struct clk_sam9x5_main *clkmain = to_clk_sam9x5_main(clk); + struct clk_sam9x5_main *clkmain = to_clk_sam9x5_main(hw); struct regmap *regmap = clkmain->regmap; while (!clk_sam9x5_main_ready(regmap)) @@ -376,24 +376,24 @@ static int clk_sam9x5_main_enable(struct clk *clk) return clk_main_probe_frequency(regmap); } -static int clk_sam9x5_main_is_enabled(struct clk *clk) +static int clk_sam9x5_main_is_enabled(struct clk_hw *hw) { - struct clk_sam9x5_main *clkmain = to_clk_sam9x5_main(clk); + struct clk_sam9x5_main *clkmain = to_clk_sam9x5_main(hw); return clk_sam9x5_main_ready(clkmain->regmap); } -static unsigned long clk_sam9x5_main_recalc_rate(struct clk *clk, +static unsigned long clk_sam9x5_main_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) { - struct clk_sam9x5_main *clkmain = to_clk_sam9x5_main(clk); + struct clk_sam9x5_main *clkmain = to_clk_sam9x5_main(hw); return clk_main_recalc_rate(clkmain->regmap, parent_rate); } -static int clk_sam9x5_main_set_parent(struct clk *clk, u8 index) +static int clk_sam9x5_main_set_parent(struct clk_hw *hw, u8 index) { - struct clk_sam9x5_main *clkmain = to_clk_sam9x5_main(clk); + struct clk_sam9x5_main *clkmain = to_clk_sam9x5_main(hw); struct regmap *regmap = clkmain->regmap; unsigned int tmp; @@ -414,9 +414,9 @@ static int clk_sam9x5_main_set_parent(struct clk *clk, u8 index) return 0; } -static int clk_sam9x5_main_get_parent(struct clk *clk) +static int clk_sam9x5_main_get_parent(struct clk_hw *hw) { - struct clk_sam9x5_main *clkmain = to_clk_sam9x5_main(clk); + struct clk_sam9x5_main *clkmain = to_clk_sam9x5_main(hw); unsigned int status; regmap_read(clkmain->regmap, AT91_CKGR_MOR, &status); @@ -451,11 +451,11 @@ at91_clk_register_sam9x5_main(struct regmap *regmap, clkmain = xzalloc(sizeof(*clkmain)); - clkmain->clk.name = name; - clkmain->clk.ops = &sam9x5_main_ops; - parents_array_size = num_parents * sizeof (clkmain->clk.parent_names[0]); - clkmain->clk.parent_names = xmemdup(parent_names, parents_array_size); - clkmain->clk.num_parents = num_parents; + clkmain->hw.clk.name = name; + clkmain->hw.clk.ops = &sam9x5_main_ops; + parents_array_size = num_parents * sizeof (clkmain->hw.clk.parent_names[0]); + clkmain->hw.clk.parent_names = xmemdup(parent_names, parents_array_size); + clkmain->hw.clk.num_parents = num_parents; /* init.flags = CLK_SET_PARENT_GATE; */ @@ -463,11 +463,11 @@ at91_clk_register_sam9x5_main(struct regmap *regmap, regmap_read(clkmain->regmap, AT91_CKGR_MOR, &status); clkmain->parent = clk_main_parent_select(status); - ret = clk_register(&clkmain->clk); + ret = bclk_register(&clkmain->hw.clk); if (ret) { kfree(clkmain); return ERR_PTR(ret); } - return &clkmain->clk; + return &clkmain->hw.clk; } diff --git a/drivers/clk/at91/clk-master.c b/drivers/clk/at91/clk-master.c index da5e316988..3e4836b667 100644 --- a/drivers/clk/at91/clk-master.c +++ b/drivers/clk/at91/clk-master.c @@ -18,10 +18,10 @@ #define MASTER_DIV_SHIFT 8 #define MASTER_DIV_MASK 0x3 -#define to_clk_master(clk) container_of(clk, struct clk_master, clk) +#define to_clk_master(_hw) container_of(_hw, struct clk_master, hw) struct clk_master { - struct clk clk; + struct clk_hw hw; struct regmap *regmap; const struct clk_master_layout *layout; const struct clk_master_characteristics *characteristics; @@ -38,9 +38,9 @@ static inline bool clk_master_ready(struct regmap *regmap) return status & AT91_PMC_MCKRDY ? 1 : 0; } -static int clk_master_enable(struct clk *clk) +static int clk_master_enable(struct clk_hw *hw) { - struct clk_master *master = to_clk_master(clk); + struct clk_master *master = to_clk_master(hw); while (!clk_master_ready(master->regmap)) barrier(); @@ -48,20 +48,20 @@ static int clk_master_enable(struct clk *clk) return 0; } -static int clk_master_is_enabled(struct clk *clk) +static int clk_master_is_enabled(struct clk_hw *hw) { - struct clk_master *master = to_clk_master(clk); + struct clk_master *master = to_clk_master(hw); return clk_master_ready(master->regmap); } -static unsigned long clk_master_recalc_rate(struct clk *clk, +static unsigned long clk_master_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) { u8 pres; u8 div; unsigned long rate = parent_rate; - struct clk_master *master = to_clk_master(clk); + struct clk_master *master = to_clk_master(hw); const struct clk_master_layout *layout = master->layout; const struct clk_master_characteristics *characteristics = master->characteristics; @@ -88,9 +88,9 @@ static unsigned long clk_master_recalc_rate(struct clk *clk, return rate; } -static int clk_master_get_parent(struct clk *clk) +static int clk_master_get_parent(struct clk_hw *hw) { - struct clk_master *master = to_clk_master(clk); + struct clk_master *master = to_clk_master(hw); unsigned int mckr; regmap_read(master->regmap, master->layout->offset, &mckr); @@ -121,23 +121,23 @@ at91_clk_register_master(struct regmap *regmap, master = xzalloc(struct_size(master, parents, num_parents)); - master->clk.name = name; - master->clk.ops = &master_ops; + master->hw.clk.name = name; + master->hw.clk.ops = &master_ops; memcpy(master->parents, parent_names, parent_names_size); - master->clk.parent_names = master->parents; - master->clk.num_parents = num_parents; + master->hw.clk.parent_names = master->parents; + master->hw.clk.num_parents = num_parents; master->layout = layout; master->characteristics = characteristics; master->regmap = regmap; - ret = clk_register(&master->clk); + ret = bclk_register(&master->hw.clk); if (ret) { kfree(master); return ERR_PTR(ret); } - return &master->clk; + return &master->hw.clk; } diff --git a/drivers/clk/at91/clk-peripheral.c b/drivers/clk/at91/clk-peripheral.c index 2b9008eb2c..c768947647 100644 --- a/drivers/clk/at91/clk-peripheral.c +++ b/drivers/clk/at91/clk-peripheral.c @@ -23,16 +23,16 @@ #define PERIPHERAL_MAX_SHIFT 3 struct clk_peripheral { - struct clk clk; + struct clk_hw hw; struct regmap *regmap; u32 id; const char *parent; }; -#define to_clk_peripheral(clk) container_of(clk, struct clk_peripheral, clk) +#define to_clk_peripheral(_hw) container_of(_hw, struct clk_peripheral, hw) struct clk_sam9x5_peripheral { - struct clk clk; + struct clk_hw hw; struct regmap *regmap; struct clk_range range; u32 id; @@ -42,12 +42,12 @@ struct clk_sam9x5_peripheral { const char *parent; }; -#define to_clk_sam9x5_peripheral(clk) \ - container_of(clk, struct clk_sam9x5_peripheral, clk) +#define to_clk_sam9x5_peripheral(_hw) \ + container_of(_hw, struct clk_sam9x5_peripheral, hw) -static int clk_peripheral_enable(struct clk *clk) +static int clk_peripheral_enable(struct clk_hw *hw) { - struct clk_peripheral *periph = to_clk_peripheral(clk); + struct clk_peripheral *periph = to_clk_peripheral(hw); int offset = AT91_PMC_PCER; u32 id = periph->id; @@ -60,9 +60,9 @@ static int clk_peripheral_enable(struct clk *clk) return 0; } -static void clk_peripheral_disable(struct clk *clk) +static void clk_peripheral_disable(struct clk_hw *hw) { - struct clk_peripheral *periph = to_clk_peripheral(clk); + struct clk_peripheral *periph = to_clk_peripheral(hw); int offset = AT91_PMC_PCDR; u32 id = periph->id; @@ -73,9 +73,9 @@ static void clk_peripheral_disable(struct clk *clk) regmap_write(periph->regmap, offset, PERIPHERAL_MASK(id)); } -static int clk_peripheral_is_enabled(struct clk *clk) +static int clk_peripheral_is_enabled(struct clk_hw *hw) { - struct clk_peripheral *periph = to_clk_peripheral(clk); + struct clk_peripheral *periph = to_clk_peripheral(hw); int offset = AT91_PMC_PCSR; unsigned int status; u32 id = periph->id; @@ -107,25 +107,25 @@ at91_clk_register_peripheral(struct regmap *regmap, const char *name, periph = xzalloc(sizeof(*periph)); - periph->clk.name = name; - periph->clk.ops = &peripheral_ops; + periph->hw.clk.name = name; + periph->hw.clk.ops = &peripheral_ops; if (parent_name) { periph->parent = parent_name; - periph->clk.parent_names = &periph->parent; - periph->clk.num_parents = 1; + periph->hw.clk.parent_names = &periph->parent; + periph->hw.clk.num_parents = 1; } periph->id = id; periph->regmap = regmap; - ret = clk_register(&periph->clk); + ret = bclk_register(&periph->hw.clk); if (ret) { kfree(periph); return ERR_PTR(ret); } - return &periph->clk; + return &periph->hw.clk; } static void clk_sam9x5_peripheral_autodiv(struct clk_sam9x5_peripheral *periph) @@ -138,7 +138,7 @@ static void clk_sam9x5_peripheral_autodiv(struct clk_sam9x5_peripheral *periph) return; if (periph->range.max) { - parent = clk_get_parent(&periph->clk); + parent = clk_get_parent(&periph->hw.clk); parent_rate = clk_get_rate(parent); if (!parent_rate) return; @@ -153,9 +153,9 @@ static void clk_sam9x5_peripheral_autodiv(struct clk_sam9x5_peripheral *periph) periph->div = shift; } -static int clk_sam9x5_peripheral_enable(struct clk *clk) +static int clk_sam9x5_peripheral_enable(struct clk_hw *hw) { - struct clk_sam9x5_peripheral *periph = to_clk_sam9x5_peripheral(clk); + struct clk_sam9x5_peripheral *periph = to_clk_sam9x5_peripheral(hw); if (periph->id < PERIPHERAL_ID_MIN) return 0; @@ -172,9 +172,9 @@ static int clk_sam9x5_peripheral_enable(struct clk *clk) return 0; } -static void clk_sam9x5_peripheral_disable(struct clk *clk) +static void clk_sam9x5_peripheral_disable(struct clk_hw *hw) { - struct clk_sam9x5_peripheral *periph = to_clk_sam9x5_peripheral(clk); + struct clk_sam9x5_peripheral *periph = to_clk_sam9x5_peripheral(hw); if (periph->id < PERIPHERAL_ID_MIN) return; @@ -186,9 +186,9 @@ static void clk_sam9x5_peripheral_disable(struct clk *clk) periph->layout->cmd); } -static int clk_sam9x5_peripheral_is_enabled(struct clk *clk) +static int clk_sam9x5_peripheral_is_enabled(struct clk_hw *hw) { - struct clk_sam9x5_peripheral *periph = to_clk_sam9x5_peripheral(clk); + struct clk_sam9x5_peripheral *periph = to_clk_sam9x5_peripheral(hw); unsigned int status; if (periph->id < PERIPHERAL_ID_MIN) @@ -202,10 +202,10 @@ static int clk_sam9x5_peripheral_is_enabled(struct clk *clk) } static unsigned long -clk_sam9x5_peripheral_recalc_rate(struct clk *clk, +clk_sam9x5_peripheral_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) { - struct clk_sam9x5_peripheral *periph = to_clk_sam9x5_peripheral(clk); + struct clk_sam9x5_peripheral *periph = to_clk_sam9x5_peripheral(hw); unsigned int status; if (periph->id < PERIPHERAL_ID_MIN) @@ -225,7 +225,7 @@ clk_sam9x5_peripheral_recalc_rate(struct clk *clk, return parent_rate >> periph->div; } -static long clk_sam9x5_peripheral_round_rate(struct clk *clk, +static long clk_sam9x5_peripheral_round_rate(struct clk_hw *hw, unsigned long rate, unsigned long *parent_rate) { @@ -234,7 +234,7 @@ static long clk_sam9x5_peripheral_round_rate(struct clk *clk, unsigned long best_diff; unsigned long cur_rate = *parent_rate; unsigned long cur_diff; - struct clk_sam9x5_peripheral *periph = to_clk_sam9x5_peripheral(clk); + struct clk_sam9x5_peripheral *periph = to_clk_sam9x5_peripheral(hw); if (periph->id < PERIPHERAL_ID_MIN || !periph->range.max) return *parent_rate; @@ -271,12 +271,12 @@ static long clk_sam9x5_peripheral_round_rate(struct clk *clk, return best_rate; } -static int clk_sam9x5_peripheral_set_rate(struct clk *clk, +static int clk_sam9x5_peripheral_set_rate(struct clk_hw *hw, unsigned long rate, unsigned long parent_rate) { int shift; - struct clk_sam9x5_peripheral *periph = to_clk_sam9x5_peripheral(clk); + struct clk_sam9x5_peripheral *periph = to_clk_sam9x5_peripheral(hw); if (periph->id < PERIPHERAL_ID_MIN || !periph->range.max) { if (parent_rate == rate) return 0; @@ -321,13 +321,13 @@ at91_clk_register_sam9x5_peripheral(struct regmap *regmap, periph = xzalloc(sizeof(*periph)); - periph->clk.name = name; - periph->clk.ops = &sam9x5_peripheral_ops; + periph->hw.clk.name = name; + periph->hw.clk.ops = &sam9x5_peripheral_ops; if (parent_name) { periph->parent = parent_name; - periph->clk.parent_names = &periph->parent; - periph->clk.num_parents = 1; + periph->hw.clk.parent_names = &periph->parent; + periph->hw.clk.num_parents = 1; } periph->id = id; @@ -338,7 +338,7 @@ at91_clk_register_sam9x5_peripheral(struct regmap *regmap, periph->layout = layout; periph->range = *range; - ret = clk_register(&periph->clk); + ret = bclk_register(&periph->hw.clk); if (ret) { kfree(periph); return ERR_PTR(ret); @@ -347,5 +347,5 @@ at91_clk_register_sam9x5_peripheral(struct regmap *regmap, clk_sam9x5_peripheral_autodiv(periph); pmc_register_id(id); - return &periph->clk; + return &periph->hw.clk; } diff --git a/drivers/clk/at91/clk-pll.c b/drivers/clk/at91/clk-pll.c index 5cb156e784..d8ea566f49 100644 --- a/drivers/clk/at91/clk-pll.c +++ b/drivers/clk/at91/clk-pll.c @@ -31,10 +31,10 @@ #define PLL_OUT_SHIFT 14 #define PLL_MAX_ID 1 -#define to_clk_pll(clk) container_of(clk, struct clk_pll, clk) +#define to_clk_pll(_hw) container_of(_hw, struct clk_pll, hw) struct clk_pll { - struct clk clk; + struct clk_hw hw; struct regmap *regmap; u8 id; u8 div; @@ -54,9 +54,9 @@ static inline bool clk_pll_ready(struct regmap *regmap, int id) return status & PLL_STATUS_MASK(id) ? 1 : 0; } -static int clk_pll_enable(struct clk *clk) +static int clk_pll_enable(struct clk_hw *hw) { - struct clk_pll *pll = to_clk_pll(clk); + struct clk_pll *pll = to_clk_pll(hw); struct regmap *regmap = pll->regmap; const struct clk_pll_layout *layout = pll->layout; const struct clk_pll_characteristics *characteristics = @@ -97,25 +97,25 @@ static int clk_pll_enable(struct clk *clk) return 0; } -static int clk_pll_is_enabled(struct clk *clk) +static int clk_pll_is_enabled(struct clk_hw *hw) { - struct clk_pll *pll = to_clk_pll(clk); + struct clk_pll *pll = to_clk_pll(hw); return clk_pll_ready(pll->regmap, pll->id); } -static void clk_pll_disable(struct clk *clk) +static void clk_pll_disable(struct clk_hw *hw) { - struct clk_pll *pll = to_clk_pll(clk); + struct clk_pll *pll = to_clk_pll(hw); unsigned int mask = pll->layout->pllr_mask; regmap_write_bits(pll->regmap, PLL_REG(pll->id), mask, ~mask); } -static unsigned long clk_pll_recalc_rate(struct clk *clk, +static unsigned long clk_pll_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) { - struct clk_pll *pll = to_clk_pll(clk); + struct clk_pll *pll = to_clk_pll(hw); if (!pll->div || !pll->mul) return 0; @@ -233,19 +233,19 @@ static long clk_pll_get_best_div_mul(struct clk_pll *pll, unsigned long rate, return bestrate; } -static long clk_pll_round_rate(struct clk *clk, unsigned long rate, +static long clk_pll_round_rate(struct clk_hw *hw, unsigned long rate, unsigned long *parent_rate) { - struct clk_pll *pll = to_clk_pll(clk); + struct clk_pll *pll = to_clk_pll(hw); return clk_pll_get_best_div_mul(pll, rate, *parent_rate, NULL, NULL, NULL); } -static int clk_pll_set_rate(struct clk *clk, unsigned long rate, +static int clk_pll_set_rate(struct clk_hw *hw, unsigned long rate, unsigned long parent_rate) { - struct clk_pll *pll = to_clk_pll(clk); + struct clk_pll *pll = to_clk_pll(hw); long ret; u32 div; u32 mul; @@ -289,10 +289,10 @@ at91_clk_register_pll(struct regmap *regmap, const char *name, pll = xzalloc(sizeof(*pll)); pll->parent = parent_name; - pll->clk.name = name; - pll->clk.ops = &pll_ops; - pll->clk.parent_names = &pll->parent; - pll->clk.num_parents = 1; + pll->hw.clk.name = name; + pll->hw.clk.ops = &pll_ops; + pll->hw.clk.parent_names = &pll->parent; + pll->hw.clk.num_parents = 1; /* init.flags = CLK_SET_RATE_GATE; */ @@ -304,13 +304,13 @@ at91_clk_register_pll(struct regmap *regmap, const char *name, pll->div = PLL_DIV(pllr); pll->mul = PLL_MUL(pllr, layout); - ret = clk_register(&pll->clk); + ret = bclk_register(&pll->hw.clk); if (ret) { kfree(pll); return ERR_PTR(ret); } - return &pll->clk; + return &pll->hw.clk; } diff --git a/drivers/clk/at91/clk-plldiv.c b/drivers/clk/at91/clk-plldiv.c index 1cbb61bb2c..2830b16722 100644 --- a/drivers/clk/at91/clk-plldiv.c +++ b/drivers/clk/at91/clk-plldiv.c @@ -14,18 +14,18 @@ #include "pmc.h" -#define to_clk_plldiv(hw) container_of(clk, struct clk_plldiv, clk) +#define to_clk_plldiv(_hw) container_of(_hw, struct clk_plldiv, hw) struct clk_plldiv { - struct clk clk; + struct clk_hw hw; struct regmap *regmap; const char *parent; }; -static unsigned long clk_plldiv_recalc_rate(struct clk *clk, +static unsigned long clk_plldiv_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) { - struct clk_plldiv *plldiv = to_clk_plldiv(clk); + struct clk_plldiv *plldiv = to_clk_plldiv(hw); unsigned int mckr; regmap_read(plldiv->regmap, AT91_PMC_MCKR, &mckr); @@ -36,7 +36,7 @@ static unsigned long clk_plldiv_recalc_rate(struct clk *clk, return parent_rate; } -static long clk_plldiv_round_rate(struct clk *clk, unsigned long rate, +static long clk_plldiv_round_rate(struct clk_hw *hw, unsigned long rate, unsigned long *parent_rate) { unsigned long div; @@ -53,10 +53,10 @@ static long clk_plldiv_round_rate(struct clk *clk, unsigned long rate, return *parent_rate; } -static int clk_plldiv_set_rate(struct clk *clk, unsigned long rate, +static int clk_plldiv_set_rate(struct clk_hw *hw, unsigned long rate, unsigned long parent_rate) { - struct clk_plldiv *plldiv = to_clk_plldiv(clk); + struct clk_plldiv *plldiv = to_clk_plldiv(hw); if ((parent_rate != rate) && (parent_rate / 2 != rate)) return -EINVAL; @@ -82,24 +82,24 @@ at91_clk_register_plldiv(struct regmap *regmap, const char *name, plldiv = xzalloc(sizeof(*plldiv)); - plldiv->clk.name = name; - plldiv->clk.ops = &plldiv_ops; + plldiv->hw.clk.name = name; + plldiv->hw.clk.ops = &plldiv_ops; if (parent_name) { plldiv->parent = parent_name; - plldiv->clk.parent_names = &plldiv->parent; - plldiv->clk.num_parents = 1; + plldiv->hw.clk.parent_names = &plldiv->parent; + plldiv->hw.clk.num_parents = 1; } /* init.flags = CLK_SET_RATE_GATE; */ plldiv->regmap = regmap; - ret = clk_register(&plldiv->clk); + ret = bclk_register(&plldiv->hw.clk); if (ret) { kfree(plldiv); return ERR_PTR(ret); } - return &plldiv->clk; + return &plldiv->hw.clk; } diff --git a/drivers/clk/at91/clk-programmable.c b/drivers/clk/at91/clk-programmable.c index 99a0fa29a3..ec53f1addd 100644 --- a/drivers/clk/at91/clk-programmable.c +++ b/drivers/clk/at91/clk-programmable.c @@ -22,19 +22,19 @@ #define PROG_MAX_RM9200_CSS 3 struct clk_programmable { - struct clk clk; + struct clk_hw hw; struct regmap *regmap; u8 id; const struct clk_programmable_layout *layout; const char *parent_names[]; }; -#define to_clk_programmable(clk) container_of(clk, struct clk_programmable, clk) +#define to_clk_programmable(_hw) container_of(_hw, struct clk_programmable, hw) -static unsigned long clk_programmable_recalc_rate(struct clk *clk, +static unsigned long clk_programmable_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) { - struct clk_programmable *prog = to_clk_programmable(clk); + struct clk_programmable *prog = to_clk_programmable(hw); const struct clk_programmable_layout *layout = prog->layout; unsigned int pckr; unsigned long rate; @@ -49,9 +49,9 @@ static unsigned long clk_programmable_recalc_rate(struct clk *clk, return rate; } -static int clk_programmable_set_parent(struct clk *clk, u8 index) +static int clk_programmable_set_parent(struct clk_hw *hw, u8 index) { - struct clk_programmable *prog = to_clk_programmable(clk); + struct clk_programmable *prog = to_clk_programmable(hw); const struct clk_programmable_layout *layout = prog->layout; unsigned int mask = layout->css_mask; unsigned int pckr = index; @@ -71,9 +71,9 @@ static int clk_programmable_set_parent(struct clk *clk, u8 index) return 0; } -static int clk_programmable_get_parent(struct clk *clk) +static int clk_programmable_get_parent(struct clk_hw *hw) { - struct clk_programmable *prog = to_clk_programmable(clk); + struct clk_programmable *prog = to_clk_programmable(hw); const struct clk_programmable_layout *layout = prog->layout; unsigned int pckr; u8 ret; @@ -88,10 +88,10 @@ static int clk_programmable_get_parent(struct clk *clk) return ret; } -static int clk_programmable_set_rate(struct clk *clk, unsigned long rate, +static int clk_programmable_set_rate(struct clk_hw *hw, unsigned long rate, unsigned long parent_rate) { - struct clk_programmable *prog = to_clk_programmable(clk); + struct clk_programmable *prog = to_clk_programmable(hw); const struct clk_programmable_layout *layout = prog->layout; unsigned long div = parent_rate / rate; int shift = 0; @@ -144,19 +144,19 @@ at91_clk_register_programmable(struct regmap *regmap, if (!prog) return ERR_PTR(-ENOMEM); - prog->clk.name = name; - prog->clk.ops = &programmable_ops; + prog->hw.clk.name = name; + prog->hw.clk.ops = &programmable_ops; memcpy(prog->parent_names, parent_names, num_parents * sizeof(prog->parent_names[0])); - prog->clk.parent_names = &prog->parent_names[0]; - prog->clk.num_parents = num_parents; + prog->hw.clk.parent_names = &prog->parent_names[0]; + prog->hw.clk.num_parents = num_parents; /* init.flags = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE; */ prog->id = id; prog->layout = layout; prog->regmap = regmap; - ret = clk_register(&prog->clk); + ret = bclk_register(&prog->hw.clk); if (ret) { kfree(prog); return ERR_PTR(ret); @@ -164,7 +164,7 @@ at91_clk_register_programmable(struct regmap *regmap, pmc_register_pck(id); - return &prog->clk; + return &prog->hw.clk; } const struct clk_programmable_layout at91rm9200_programmable_layout = { diff --git a/drivers/clk/at91/clk-sam9x60-pll.c b/drivers/clk/at91/clk-sam9x60-pll.c index 9ca77f8722..744c3833bb 100644 --- a/drivers/clk/at91/clk-sam9x60-pll.c +++ b/drivers/clk/at91/clk-sam9x60-pll.c @@ -55,7 +55,7 @@ struct sam9x60_pll { const char *parent_name; }; -#define to_sam9x60_pll(clk) container_of(clk, struct sam9x60_pll, clk) +#define to_sam9x60_pll(_hw) container_of(_hw->clk, struct sam9x60_pll, clk) static inline bool sam9x60_pll_ready(struct regmap *regmap, int id) { @@ -66,9 +66,9 @@ static inline bool sam9x60_pll_ready(struct regmap *regmap, int id) return !!(status & BIT(id)); } -static int sam9x60_pll_enable(struct clk *clk) +static int sam9x60_pll_enable(struct clk_hw *hw) { - struct sam9x60_pll *pll = to_sam9x60_pll(clk); + struct sam9x60_pll *pll = to_sam9x60_pll(hw); struct regmap *regmap = pll->regmap; u8 div; u16 mul; @@ -127,16 +127,16 @@ static int sam9x60_pll_enable(struct clk *clk) return 0; } -static int sam9x60_pll_is_enabled(struct clk *clk) +static int sam9x60_pll_is_enabled(struct clk_hw *hw) { - struct sam9x60_pll *pll = to_sam9x60_pll(clk); + struct sam9x60_pll *pll = to_sam9x60_pll(hw); return sam9x60_pll_ready(pll->regmap, pll->id); } -static void sam9x60_pll_disable(struct clk *clk) +static void sam9x60_pll_disable(struct clk_hw *hw) { - struct sam9x60_pll *pll = to_sam9x60_pll(clk); + struct sam9x60_pll *pll = to_sam9x60_pll(hw); regmap_write(pll->regmap, PMC_PLL_UPDT, pll->id); @@ -156,10 +156,10 @@ static void sam9x60_pll_disable(struct clk *clk) PMC_PLL_UPDT_UPDATE, PMC_PLL_UPDT_UPDATE); } -static unsigned long sam9x60_pll_recalc_rate(struct clk *clk, +static unsigned long sam9x60_pll_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) { - struct sam9x60_pll *pll = to_sam9x60_pll(clk); + struct sam9x60_pll *pll = to_sam9x60_pll(hw); return (parent_rate * (pll->mul + 1)) / (pll->div + 1); } @@ -253,18 +253,18 @@ static long sam9x60_pll_get_best_div_mul(struct sam9x60_pll *pll, return bestrate; } -static long sam9x60_pll_round_rate(struct clk *clk, unsigned long rate, +static long sam9x60_pll_round_rate(struct clk_hw *hw, unsigned long rate, unsigned long *parent_rate) { - struct sam9x60_pll *pll = to_sam9x60_pll(clk); + struct sam9x60_pll *pll = to_sam9x60_pll(hw); return sam9x60_pll_get_best_div_mul(pll, rate, *parent_rate, false); } -static int sam9x60_pll_set_rate(struct clk *clk, unsigned long rate, +static int sam9x60_pll_set_rate(struct clk_hw *hw, unsigned long rate, unsigned long parent_rate) { - struct sam9x60_pll *pll = to_sam9x60_pll(clk); + struct sam9x60_pll *pll = to_sam9x60_pll(hw); return sam9x60_pll_get_best_div_mul(pll, rate, parent_rate, true); } @@ -311,7 +311,7 @@ sam9x60_clk_register_pll(struct regmap *regmap, regmap_read(regmap, PMC_PLL_CTRL1, &pllr); pll->mul = FIELD_GET(PMC_PLL_CTRL1_MUL_MSK, pllr); - ret = clk_register(&pll->clk); + ret = bclk_register(&pll->clk); if (ret) { kfree(pll); return ERR_PTR(ret); diff --git a/drivers/clk/at91/clk-slow.c b/drivers/clk/at91/clk-slow.c index bcce810fa5..bc4285e4bf 100644 --- a/drivers/clk/at91/clk-slow.c +++ b/drivers/clk/at91/clk-slow.c @@ -18,16 +18,16 @@ #include "pmc.h" struct clk_sam9260_slow { - struct clk clk; + struct clk_hw hw; struct regmap *regmap; const char *parent_names[]; }; -#define to_clk_sam9260_slow(clk) container_of(clk, struct clk_sam9260_slow, clk) +#define to_clk_sam9260_slow(_hw) container_of(_hw, struct clk_sam9260_slow, hw) -static int clk_sam9260_slow_get_parent(struct clk *clk) +static int clk_sam9260_slow_get_parent(struct clk_hw *hw) { - struct clk_sam9260_slow *slowck = to_clk_sam9260_slow(clk); + struct clk_sam9260_slow *slowck = to_clk_sam9260_slow(hw); unsigned int status; regmap_read(slowck->regmap, AT91_PMC_SR, &status); @@ -55,19 +55,19 @@ at91_clk_register_sam9260_slow(struct regmap *regmap, return ERR_PTR(-EINVAL); slowck = xzalloc(struct_size(slowck, parent_names, num_parents)); - slowck->clk.name = name; - slowck->clk.ops = &sam9260_slow_ops; + slowck->hw.clk.name = name; + slowck->hw.clk.ops = &sam9260_slow_ops; memcpy(slowck->parent_names, parent_names, num_parents * sizeof(slowck->parent_names[0])); - slowck->clk.parent_names = slowck->parent_names; - slowck->clk.num_parents = num_parents; + slowck->hw.clk.parent_names = slowck->parent_names; + slowck->hw.clk.num_parents = num_parents; slowck->regmap = regmap; - ret = clk_register(&slowck->clk); + ret = bclk_register(&slowck->hw.clk); if (ret) { kfree(slowck); return ERR_PTR(ret); } - return &slowck->clk; + return &slowck->hw.clk; } diff --git a/drivers/clk/at91/clk-smd.c b/drivers/clk/at91/clk-smd.c index 366f2eaad5..6df698637c 100644 --- a/drivers/clk/at91/clk-smd.c +++ b/drivers/clk/at91/clk-smd.c @@ -21,18 +21,18 @@ #define SMD_MAX_DIV 0xf struct at91sam9x5_clk_smd { - struct clk clk; + struct clk_hw hw; struct regmap *regmap; const char *parent_names[]; }; -#define to_at91sam9x5_clk_smd(clk) \ - container_of(clk, struct at91sam9x5_clk_smd, clk) +#define to_at91sam9x5_clk_smd(_hw) \ + container_of(_hw, struct at91sam9x5_clk_smd, hw) -static unsigned long at91sam9x5_clk_smd_recalc_rate(struct clk *clk, +static unsigned long at91sam9x5_clk_smd_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) { - struct at91sam9x5_clk_smd *smd = to_at91sam9x5_clk_smd(clk); + struct at91sam9x5_clk_smd *smd = to_at91sam9x5_clk_smd(hw); unsigned int smdr; u8 smddiv; @@ -42,7 +42,7 @@ static unsigned long at91sam9x5_clk_smd_recalc_rate(struct clk *clk, return parent_rate / (smddiv + 1); } -static long at91sam9x5_clk_smd_round_rate(struct clk *clk, unsigned long rate, +static long at91sam9x5_clk_smd_round_rate(struct clk_hw *hw, unsigned long rate, unsigned long *parent_rate) { unsigned long div; @@ -64,9 +64,9 @@ static long at91sam9x5_clk_smd_round_rate(struct clk *clk, unsigned long rate, return bestrate; } -static int at91sam9x5_clk_smd_set_parent(struct clk *clk, u8 index) +static int at91sam9x5_clk_smd_set_parent(struct clk_hw *hw, u8 index) { - struct at91sam9x5_clk_smd *smd = to_at91sam9x5_clk_smd(clk); + struct at91sam9x5_clk_smd *smd = to_at91sam9x5_clk_smd(hw); if (index > 1) return -EINVAL; @@ -77,9 +77,9 @@ static int at91sam9x5_clk_smd_set_parent(struct clk *clk, u8 index) return 0; } -static int at91sam9x5_clk_smd_get_parent(struct clk *clk) +static int at91sam9x5_clk_smd_get_parent(struct clk_hw *hw) { - struct at91sam9x5_clk_smd *smd = to_at91sam9x5_clk_smd(clk); + struct at91sam9x5_clk_smd *smd = to_at91sam9x5_clk_smd(hw); unsigned int smdr; regmap_read(smd->regmap, AT91_PMC_SMD, &smdr); @@ -87,10 +87,10 @@ static int at91sam9x5_clk_smd_get_parent(struct clk *clk) return smdr & AT91_PMC_SMDS; } -static int at91sam9x5_clk_smd_set_rate(struct clk *clk, unsigned long rate, +static int at91sam9x5_clk_smd_set_rate(struct clk_hw *hw, unsigned long rate, unsigned long parent_rate) { - struct at91sam9x5_clk_smd *smd = to_at91sam9x5_clk_smd(clk); + struct at91sam9x5_clk_smd *smd = to_at91sam9x5_clk_smd(hw); unsigned long div = parent_rate / rate; if (parent_rate % rate || div < 1 || div > (SMD_MAX_DIV + 1)) @@ -118,20 +118,20 @@ at91sam9x5_clk_register_smd(struct regmap *regmap, const char *name, int ret; smd = xzalloc(struct_size(smd, parent_names, num_parents)); - smd->clk.name = name; - smd->clk.ops = &at91sam9x5_smd_ops; + smd->hw.clk.name = name; + smd->hw.clk.ops = &at91sam9x5_smd_ops; memcpy(smd->parent_names, parent_names, num_parents * sizeof(smd->parent_names[0])); - smd->clk.parent_names = smd->parent_names; - smd->clk.num_parents = num_parents; + smd->hw.clk.parent_names = smd->parent_names; + smd->hw.clk.num_parents = num_parents; /* init.flags = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE; */ smd->regmap = regmap; - ret = clk_register(&smd->clk); + ret = bclk_register(&smd->hw.clk); if (ret) { kfree(smd); return ERR_PTR(ret); } - return &smd->clk; + return &smd->hw.clk; } diff --git a/drivers/clk/at91/clk-system.c b/drivers/clk/at91/clk-system.c index 77f0dff98b..9a15d5b04a 100644 --- a/drivers/clk/at91/clk-system.c +++ b/drivers/clk/at91/clk-system.c @@ -17,9 +17,9 @@ #define SYSTEM_MAX_NAME_SZ 32 -#define to_clk_system(clk) container_of(clk, struct clk_system, clk) +#define to_clk_system(_hw) container_of(_hw, struct clk_system, hw) struct clk_system { - struct clk clk; + struct clk_hw hw; struct regmap *regmap; u8 id; const char *parent_name; @@ -39,9 +39,9 @@ static inline bool clk_system_ready(struct regmap *regmap, int id) return status & (1 << id) ? 1 : 0; } -static int clk_system_enable(struct clk *clk) +static int clk_system_enable(struct clk_hw *hw) { - struct clk_system *sys = to_clk_system(clk); + struct clk_system *sys = to_clk_system(hw); regmap_write(sys->regmap, AT91_PMC_SCER, 1 << sys->id); @@ -54,16 +54,16 @@ static int clk_system_enable(struct clk *clk) return 0; } -static void clk_system_disable(struct clk *clk) +static void clk_system_disable(struct clk_hw *hw) { - struct clk_system *sys = to_clk_system(clk); + struct clk_system *sys = to_clk_system(hw); regmap_write(sys->regmap, AT91_PMC_SCDR, 1 << sys->id); } -static int clk_system_is_enabled(struct clk *clk) +static int clk_system_is_enabled(struct clk_hw *hw) { - struct clk_system *sys = to_clk_system(clk); + struct clk_system *sys = to_clk_system(hw); unsigned int status; regmap_read(sys->regmap, AT91_PMC_SCSR, &status); @@ -96,20 +96,20 @@ at91_clk_register_system(struct regmap *regmap, const char *name, return ERR_PTR(-EINVAL); sys = xzalloc(sizeof(*sys)); - sys->clk.name = name; - sys->clk.ops = &system_ops; + sys->hw.clk.name = name; + sys->hw.clk.ops = &system_ops; sys->parent_name = parent_name; - sys->clk.parent_names = &sys->parent_name; - sys->clk.num_parents = 1; + sys->hw.clk.parent_names = &sys->parent_name; + sys->hw.clk.num_parents = 1; /* init.flags = CLK_SET_RATE_PARENT; */ sys->id = id; sys->regmap = regmap; - ret = clk_register(&sys->clk); + ret = bclk_register(&sys->hw.clk); if (ret) { kfree(sys); return ERR_PTR(ret); } - return &sys->clk; + return &sys->hw.clk; } diff --git a/drivers/clk/at91/clk-usb.c b/drivers/clk/at91/clk-usb.c index 4ca076e777..148befc8ac 100644 --- a/drivers/clk/at91/clk-usb.c +++ b/drivers/clk/at91/clk-usb.c @@ -27,30 +27,30 @@ #define SAM9X60_USBS_MASK GENMASK(1, 0) struct at91sam9x5_clk_usb { - struct clk clk; + struct clk_hw hw; struct regmap *regmap; u32 usbs_mask; u8 num_parents; const char *parent_names[]; }; -#define to_at91sam9x5_clk_usb(clk) \ - container_of(clk, struct at91sam9x5_clk_usb, clk) +#define to_at91sam9x5_clk_usb(_hw) \ + container_of(_hw, struct at91sam9x5_clk_usb, hw) struct at91rm9200_clk_usb { - struct clk clk; + struct clk_hw hw; struct regmap *regmap; u32 divisors[4]; const char *parent_name; }; -#define to_at91rm9200_clk_usb(clk) \ - container_of(clk, struct at91rm9200_clk_usb, clk) +#define to_at91rm9200_clk_usb(_hw) \ + container_of(_hw, struct at91rm9200_clk_usb, hw) -static unsigned long at91sam9x5_clk_usb_recalc_rate(struct clk *clk, +static unsigned long at91sam9x5_clk_usb_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) { - struct at91sam9x5_clk_usb *usb = to_at91sam9x5_clk_usb(clk); + struct at91sam9x5_clk_usb *usb = to_at91sam9x5_clk_usb(hw); unsigned int usbr; u8 usbdiv; @@ -60,9 +60,9 @@ static unsigned long at91sam9x5_clk_usb_recalc_rate(struct clk *clk, return DIV_ROUND_CLOSEST(parent_rate, (usbdiv + 1)); } -static int at91sam9x5_clk_usb_set_parent(struct clk *clk, u8 index) +static int at91sam9x5_clk_usb_set_parent(struct clk_hw *hw, u8 index) { - struct at91sam9x5_clk_usb *usb = to_at91sam9x5_clk_usb(clk); + struct at91sam9x5_clk_usb *usb = to_at91sam9x5_clk_usb(hw); if (index >= usb->num_parents) return -EINVAL; @@ -72,9 +72,9 @@ static int at91sam9x5_clk_usb_set_parent(struct clk *clk, u8 index) return 0; } -static int at91sam9x5_clk_usb_get_parent(struct clk *clk) +static int at91sam9x5_clk_usb_get_parent(struct clk_hw *hw) { - struct at91sam9x5_clk_usb *usb = to_at91sam9x5_clk_usb(clk); + struct at91sam9x5_clk_usb *usb = to_at91sam9x5_clk_usb(hw); unsigned int usbr; regmap_read(usb->regmap, AT91_PMC_USB, &usbr); @@ -82,10 +82,10 @@ static int at91sam9x5_clk_usb_get_parent(struct clk *clk) return usbr & usb->usbs_mask; } -static int at91sam9x5_clk_usb_set_rate(struct clk *clk, unsigned long rate, +static int at91sam9x5_clk_usb_set_rate(struct clk_hw *hw, unsigned long rate, unsigned long parent_rate) { - struct at91sam9x5_clk_usb *usb = to_at91sam9x5_clk_usb(clk); + struct at91sam9x5_clk_usb *usb = to_at91sam9x5_clk_usb(hw); unsigned long div; if (!rate) @@ -108,9 +108,9 @@ static const struct clk_ops at91sam9x5_usb_ops = { .set_rate = at91sam9x5_clk_usb_set_rate, }; -static int at91sam9n12_clk_usb_enable(struct clk *clk) +static int at91sam9n12_clk_usb_enable(struct clk_hw *hw) { - struct at91sam9x5_clk_usb *usb = to_at91sam9x5_clk_usb(clk); + struct at91sam9x5_clk_usb *usb = to_at91sam9x5_clk_usb(hw); regmap_write_bits(usb->regmap, AT91_PMC_USB, AT91_PMC_USBS, AT91_PMC_USBS); @@ -118,16 +118,16 @@ static int at91sam9n12_clk_usb_enable(struct clk *clk) return 0; } -static void at91sam9n12_clk_usb_disable(struct clk *clk) +static void at91sam9n12_clk_usb_disable(struct clk_hw *hw) { - struct at91sam9x5_clk_usb *usb = to_at91sam9x5_clk_usb(clk); + struct at91sam9x5_clk_usb *usb = to_at91sam9x5_clk_usb(hw); regmap_write_bits(usb->regmap, AT91_PMC_USB, AT91_PMC_USBS, 0); } -static int at91sam9n12_clk_usb_is_enabled(struct clk *clk) +static int at91sam9n12_clk_usb_is_enabled(struct clk_hw *hw) { - struct at91sam9x5_clk_usb *usb = to_at91sam9x5_clk_usb(clk); + struct at91sam9x5_clk_usb *usb = to_at91sam9x5_clk_usb(hw); unsigned int usbr; regmap_read(usb->regmap, AT91_PMC_USB, &usbr); @@ -152,26 +152,26 @@ _at91sam9x5_clk_register_usb(struct regmap *regmap, const char *name, int ret; usb = kzalloc(struct_size(usb, parent_names, num_parents), GFP_KERNEL); - usb->clk.name = name; - usb->clk.ops = &at91sam9x5_usb_ops; + usb->hw.clk.name = name; + usb->hw.clk.ops = &at91sam9x5_usb_ops; memcpy(usb->parent_names, parent_names, num_parents * sizeof(usb->parent_names[0])); - usb->clk.parent_names = usb->parent_names; - usb->clk.num_parents = num_parents; - usb->clk.flags = CLK_SET_RATE_PARENT; + usb->hw.clk.parent_names = usb->parent_names; + usb->hw.clk.num_parents = num_parents; + usb->hw.clk.flags = CLK_SET_RATE_PARENT; /* init.flags = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE | */ /* CLK_SET_RATE_PARENT; */ usb->regmap = regmap; usb->usbs_mask = usbs_mask; usb->num_parents = num_parents; - ret = clk_register(&usb->clk); + ret = bclk_register(&usb->hw.clk); if (ret) { kfree(usb); return ERR_PTR(ret); } - return &usb->clk; + return &usb->hw.clk; } struct clk * __init @@ -198,27 +198,27 @@ at91sam9n12_clk_register_usb(struct regmap *regmap, const char *name, int ret; usb = xzalloc(sizeof(*usb)); - usb->clk.name = name; - usb->clk.ops = &at91sam9n12_usb_ops; + usb->hw.clk.name = name; + usb->hw.clk.ops = &at91sam9n12_usb_ops; usb->parent_names[0] = parent_name; - usb->clk.parent_names = &usb->parent_names[0]; - usb->clk.num_parents = 1; + usb->hw.clk.parent_names = &usb->parent_names[0]; + usb->hw.clk.num_parents = 1; /* init.flags = CLK_SET_RATE_GATE | CLK_SET_RATE_PARENT; */ usb->regmap = regmap; - ret = clk_register(&usb->clk); + ret = bclk_register(&usb->hw.clk); if (ret) { kfree(usb); return ERR_PTR(ret); } - return &usb->clk; + return &usb->hw.clk; } -static unsigned long at91rm9200_clk_usb_recalc_rate(struct clk *clk, +static unsigned long at91rm9200_clk_usb_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) { - struct at91rm9200_clk_usb *usb = to_at91rm9200_clk_usb(clk); + struct at91rm9200_clk_usb *usb = to_at91rm9200_clk_usb(hw); unsigned int pllbr; u8 usbdiv; @@ -231,11 +231,11 @@ static unsigned long at91rm9200_clk_usb_recalc_rate(struct clk *clk, return 0; } -static long at91rm9200_clk_usb_round_rate(struct clk *clk, unsigned long rate, +static long at91rm9200_clk_usb_round_rate(struct clk_hw *hw, unsigned long rate, unsigned long *parent_rate) { - struct at91rm9200_clk_usb *usb = to_at91rm9200_clk_usb(clk); - struct clk *parent = clk_get_parent(clk); + struct at91rm9200_clk_usb *usb = to_at91rm9200_clk_usb(hw); + struct clk *parent = clk_get_parent(clk_hw_to_clk(hw)); unsigned long bestrate = 0; int bestdiff = -1; unsigned long tmprate; @@ -272,11 +272,11 @@ static long at91rm9200_clk_usb_round_rate(struct clk *clk, unsigned long rate, return bestrate; } -static int at91rm9200_clk_usb_set_rate(struct clk *clk, unsigned long rate, +static int at91rm9200_clk_usb_set_rate(struct clk_hw *hw, unsigned long rate, unsigned long parent_rate) { int i; - struct at91rm9200_clk_usb *usb = to_at91rm9200_clk_usb(clk); + struct at91rm9200_clk_usb *usb = to_at91rm9200_clk_usb(hw); unsigned long div; if (!rate) @@ -311,21 +311,21 @@ at91rm9200_clk_register_usb(struct regmap *regmap, const char *name, int ret; usb = xzalloc(sizeof(*usb)); - usb->clk.name = name; - usb->clk.ops = &at91rm9200_usb_ops; + usb->hw.clk.name = name; + usb->hw.clk.ops = &at91rm9200_usb_ops; usb->parent_name = parent_name; - usb->clk.parent_names = &usb->parent_name; - usb->clk.num_parents = 1; + usb->hw.clk.parent_names = &usb->parent_name; + usb->hw.clk.num_parents = 1; /* init.flags = CLK_SET_RATE_PARENT; */ usb->regmap = regmap; memcpy(usb->divisors, divisors, sizeof(usb->divisors)); - ret = clk_register(&usb->clk); + ret = bclk_register(&usb->hw.clk); if (ret) { kfree(usb); return ERR_PTR(ret); } - return &usb->clk; + return &usb->hw.clk; } diff --git a/drivers/clk/at91/clk-utmi.c b/drivers/clk/at91/clk-utmi.c index 3d71cd615f..1389983bde 100644 --- a/drivers/clk/at91/clk-utmi.c +++ b/drivers/clk/at91/clk-utmi.c @@ -22,13 +22,13 @@ #define UTMI_RATE 480000000 struct clk_utmi { - struct clk clk; + struct clk_hw hw; const char *parent; struct regmap *regmap_pmc; struct regmap *regmap_sfr; }; -#define to_clk_utmi(clk) container_of(clk, struct clk_utmi, clk) +#define to_clk_utmi(_hw) container_of(_hw, struct clk_utmi, hw) static inline bool clk_utmi_ready(struct regmap *regmap) { @@ -39,10 +39,10 @@ static inline bool clk_utmi_ready(struct regmap *regmap) return status & AT91_PMC_LOCKU; } -static int clk_utmi_enable(struct clk *clk) +static int clk_utmi_enable(struct clk_hw *hw) { struct clk *hw_parent; - struct clk_utmi *utmi = to_clk_utmi(clk); + struct clk_utmi *utmi = to_clk_utmi(hw); unsigned int uckr = AT91_PMC_UPLLEN | AT91_PMC_UPLLCOUNT | AT91_PMC_BIASEN; unsigned int utmi_ref_clk_freq; @@ -53,7 +53,7 @@ static int clk_utmi_enable(struct clk *clk) * FREQ field of the SFR_UTMICKTRIM register to generate properly * the utmi clock. */ - hw_parent = clk_get_parent(clk); + hw_parent = clk_get_parent(clk_hw_to_clk(hw)); parent_rate = clk_get_rate(hw_parent); switch (parent_rate) { @@ -95,22 +95,22 @@ static int clk_utmi_enable(struct clk *clk) return 0; } -static int clk_utmi_is_enabled(struct clk *clk) +static int clk_utmi_is_enabled(struct clk_hw *hw) { - struct clk_utmi *utmi = to_clk_utmi(clk); + struct clk_utmi *utmi = to_clk_utmi(hw); return clk_utmi_ready(utmi->regmap_pmc); } -static void clk_utmi_disable(struct clk *clk) +static void clk_utmi_disable(struct clk_hw *hw) { - struct clk_utmi *utmi = to_clk_utmi(clk); + struct clk_utmi *utmi = to_clk_utmi(hw); regmap_write_bits(utmi->regmap_pmc, AT91_CKGR_UCKR, AT91_PMC_UPLLEN, 0); } -static unsigned long clk_utmi_recalc_rate(struct clk *clk, +static unsigned long clk_utmi_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) { /* UTMI clk rate is fixed */ @@ -133,13 +133,13 @@ at91_clk_register_utmi(struct regmap *regmap_pmc, struct regmap *regmap_sfr, utmi = xzalloc(sizeof(*utmi)); - utmi->clk.name = name; - utmi->clk.ops = &utmi_ops; + utmi->hw.clk.name = name; + utmi->hw.clk.ops = &utmi_ops; if (parent_name) { utmi->parent = parent_name; - utmi->clk.parent_names = &utmi->parent; - utmi->clk.num_parents = 1; + utmi->hw.clk.parent_names = &utmi->parent; + utmi->hw.clk.num_parents = 1; } /* utmi->clk.flags = CLK_SET_RATE_GATE; */ @@ -147,11 +147,11 @@ at91_clk_register_utmi(struct regmap *regmap_pmc, struct regmap *regmap_sfr, utmi->regmap_pmc = regmap_pmc; utmi->regmap_sfr = regmap_sfr; - ret = clk_register(&utmi->clk); + ret = bclk_register(&utmi->hw.clk); if (ret) { kfree(utmi); return ERR_PTR(ret); } - return &utmi->clk; + return &utmi->hw.clk; } diff --git a/drivers/clk/at91/sckc.c b/drivers/clk/at91/sckc.c index d9898f718c..579fbf2479 100644 --- a/drivers/clk/at91/sckc.c +++ b/drivers/clk/at91/sckc.c @@ -34,17 +34,17 @@ struct clk_slow_bits { }; struct clk_slow_osc { - struct clk clk; + struct clk_hw hw; void __iomem *sckcr; const struct clk_slow_bits *bits; unsigned long startup_usec; const char *parent_name; }; -#define to_clk_slow_osc(clk) container_of(clk, struct clk_slow_osc, clk) +#define to_clk_slow_osc(_hw) container_of(_hw, struct clk_slow_osc, hw) struct clk_sama5d4_slow_osc { - struct clk clk; + struct clk_hw hw; void __iomem *sckcr; const struct clk_slow_bits *bits; unsigned long startup_usec; @@ -52,10 +52,10 @@ struct clk_sama5d4_slow_osc { const char *parent_name; }; -#define to_clk_sama5d4_slow_osc(clk) container_of(clk, struct clk_sama5d4_slow_osc, clk) +#define to_clk_sama5d4_slow_osc(_hw) container_of(_hw, struct clk_sama5d4_slow_osc, hw) struct clk_slow_rc_osc { - struct clk clk; + struct clk_hw hw; void __iomem *sckcr; const struct clk_slow_bits *bits; unsigned long frequency; @@ -63,21 +63,21 @@ struct clk_slow_rc_osc { const char *parent_name; }; -#define to_clk_slow_rc_osc(clk) container_of(clk, struct clk_slow_rc_osc, clk) +#define to_clk_slow_rc_osc(_hw) container_of(_hw, struct clk_slow_rc_osc, hw) struct clk_sam9x5_slow { - struct clk clk; + struct clk_hw hw; void __iomem *sckcr; const struct clk_slow_bits *bits; u8 parent; const char *parent_names[]; }; -#define to_clk_sam9x5_slow(clk) container_of(clk, struct clk_sam9x5_slow, clk) +#define to_clk_sam9x5_slow(_hw) container_of(_hw, struct clk_sam9x5_slow, hw) -static int clk_slow_osc_enable(struct clk *clk) +static int clk_slow_osc_enable(struct clk_hw *hw) { - struct clk_slow_osc *osc = to_clk_slow_osc(clk); + struct clk_slow_osc *osc = to_clk_slow_osc(hw); void __iomem *sckcr = osc->sckcr; u32 tmp = readl(sckcr); @@ -91,9 +91,9 @@ static int clk_slow_osc_enable(struct clk *clk) return 0; } -static void clk_slow_osc_disable(struct clk *clk) +static void clk_slow_osc_disable(struct clk_hw *hw) { - struct clk_slow_osc *osc = to_clk_slow_osc(clk); + struct clk_slow_osc *osc = to_clk_slow_osc(hw); void __iomem *sckcr = osc->sckcr; u32 tmp = readl(sckcr); @@ -103,9 +103,9 @@ static void clk_slow_osc_disable(struct clk *clk) writel(tmp & ~osc->bits->cr_osc32en, sckcr); } -static int clk_slow_osc_is_enabled(struct clk *clk) +static int clk_slow_osc_is_enabled(struct clk_hw *hw) { - struct clk_slow_osc *osc = to_clk_slow_osc(clk); + struct clk_slow_osc *osc = to_clk_slow_osc(hw); void __iomem *sckcr = osc->sckcr; u32 tmp = readl(sckcr); @@ -137,11 +137,11 @@ at91_clk_register_slow_osc(void __iomem *sckcr, osc = xzalloc(sizeof(*osc)); - osc->clk.name = name; - osc->clk.ops = &slow_osc_ops; + osc->hw.clk.name = name; + osc->hw.clk.ops = &slow_osc_ops; osc->parent_name = parent_name; - osc->clk.parent_names = &osc->parent_name; - osc->clk.num_parents = 1; + osc->hw.clk.parent_names = &osc->parent_name; + osc->hw.clk.num_parents = 1; /* osc->clk.flags = CLK_IGNORE_UNUSED; */ osc->sckcr = sckcr; @@ -152,34 +152,34 @@ at91_clk_register_slow_osc(void __iomem *sckcr, writel((readl(sckcr) & ~osc->bits->cr_osc32en) | osc->bits->cr_osc32byp, sckcr); - ret = clk_register(&osc->clk); + ret = bclk_register(&osc->hw.clk); if (ret) { kfree(osc); return ERR_PTR(ret); } - return &osc->clk; + return &osc->hw.clk; } static void at91_clk_unregister_slow_osc(struct clk *clk) { - struct clk_slow_osc *osc = to_clk_slow_osc(clk); + struct clk_slow_osc *osc = to_clk_slow_osc(clk_to_clk_hw(clk)); clk_unregister(clk); kfree(osc); } -static unsigned long clk_slow_rc_osc_recalc_rate(struct clk *clk, +static unsigned long clk_slow_rc_osc_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) { - struct clk_slow_rc_osc *osc = to_clk_slow_rc_osc(clk); + struct clk_slow_rc_osc *osc = to_clk_slow_rc_osc(hw); return osc->frequency; } -static int clk_slow_rc_osc_enable(struct clk *clk) +static int clk_slow_rc_osc_enable(struct clk_hw *hw) { - struct clk_slow_rc_osc *osc = to_clk_slow_rc_osc(clk); + struct clk_slow_rc_osc *osc = to_clk_slow_rc_osc(hw); void __iomem *sckcr = osc->sckcr; writel(readl(sckcr) | osc->bits->cr_rcen, sckcr); @@ -189,17 +189,17 @@ static int clk_slow_rc_osc_enable(struct clk *clk) return 0; } -static void clk_slow_rc_osc_disable(struct clk *clk) +static void clk_slow_rc_osc_disable(struct clk_hw *hw) { - struct clk_slow_rc_osc *osc = to_clk_slow_rc_osc(clk); + struct clk_slow_rc_osc *osc = to_clk_slow_rc_osc(hw); void __iomem *sckcr = osc->sckcr; writel(readl(sckcr) & ~osc->bits->cr_rcen, sckcr); } -static int clk_slow_rc_osc_is_enabled(struct clk *clk) +static int clk_slow_rc_osc_is_enabled(struct clk_hw *hw) { - struct clk_slow_rc_osc *osc = to_clk_slow_rc_osc(clk); + struct clk_slow_rc_osc *osc = to_clk_slow_rc_osc(hw); return !!(readl(osc->sckcr) & osc->bits->cr_rcen); } @@ -226,10 +226,10 @@ at91_clk_register_slow_rc_osc(void __iomem *sckcr, return ERR_PTR(-EINVAL); osc = xzalloc(sizeof(*osc)); - osc->clk.name = name; - osc->clk.ops = &slow_rc_osc_ops; - osc->clk.parent_names = NULL; - osc->clk.num_parents = 0; + osc->hw.clk.name = name; + osc->hw.clk.ops = &slow_rc_osc_ops; + osc->hw.clk.parent_names = NULL; + osc->hw.clk.num_parents = 0; /* init.flags = CLK_IGNORE_UNUSED; */ osc->sckcr = sckcr; @@ -237,26 +237,26 @@ at91_clk_register_slow_rc_osc(void __iomem *sckcr, osc->frequency = frequency; osc->startup_usec = startup; - ret = clk_register(&osc->clk); + ret = bclk_register(&osc->hw.clk); if (ret) { kfree(osc); return ERR_PTR(ret); } - return &osc->clk; + return &osc->hw.clk; } static void at91_clk_unregister_slow_rc_osc(struct clk *clk) { - struct clk_slow_rc_osc *osc = to_clk_slow_rc_osc(clk); + struct clk_slow_rc_osc *osc = to_clk_slow_rc_osc(clk_to_clk_hw(clk)); clk_unregister(clk); kfree(osc); } -static int clk_sam9x5_slow_set_parent(struct clk *clk, u8 index) +static int clk_sam9x5_slow_set_parent(struct clk_hw *hw, u8 index) { - struct clk_sam9x5_slow *slowck = to_clk_sam9x5_slow(clk); + struct clk_sam9x5_slow *slowck = to_clk_sam9x5_slow(hw); void __iomem *sckcr = slowck->sckcr; u32 tmp; @@ -281,9 +281,9 @@ static int clk_sam9x5_slow_set_parent(struct clk *clk, u8 index) return 0; } -static int clk_sam9x5_slow_get_parent(struct clk *clk) +static int clk_sam9x5_slow_get_parent(struct clk_hw *hw) { - struct clk_sam9x5_slow *slowck = to_clk_sam9x5_slow(clk); + struct clk_sam9x5_slow *slowck = to_clk_sam9x5_slow(hw); return !!(readl(slowck->sckcr) & slowck->bits->cr_oscsel); } @@ -307,29 +307,29 @@ at91_clk_register_sam9x5_slow(void __iomem *sckcr, return ERR_PTR(-EINVAL); slowck = xzalloc(struct_size(slowck, parent_names, num_parents)); - slowck->clk.name = name; - slowck->clk.ops = &sam9x5_slow_ops; + slowck->hw.clk.name = name; + slowck->hw.clk.ops = &sam9x5_slow_ops; memcpy(slowck->parent_names, parent_names, num_parents * sizeof(slowck->parent_names[0])); - slowck->clk.parent_names = slowck->parent_names; - slowck->clk.num_parents = num_parents; + slowck->hw.clk.parent_names = slowck->parent_names; + slowck->hw.clk.num_parents = num_parents; slowck->sckcr = sckcr; slowck->bits = bits; slowck->parent = !!(readl(sckcr) & slowck->bits->cr_oscsel); - ret = clk_register(&slowck->clk); + ret = bclk_register(&slowck->hw.clk); if (ret) { kfree(slowck); return ERR_PTR(ret); } - return &slowck->clk; + return &slowck->hw.clk; } static void at91_clk_unregister_sam9x5_slow(struct clk *clk) { - struct clk_sam9x5_slow *slowck = to_clk_sam9x5_slow(clk); + struct clk_sam9x5_slow *slowck = to_clk_sam9x5_slow(clk_to_clk_hw(clk)); clk_unregister(clk); kfree(slowck); @@ -505,9 +505,9 @@ unregister_slow_rc: CLK_OF_DECLARE(sam9x60_clk_sckc, "microchip,sam9x60-sckc", of_sam9x60_sckc_setup); -static int clk_sama5d4_slow_osc_enable(struct clk *clk) +static int clk_sama5d4_slow_osc_enable(struct clk_hw *hw) { - struct clk_sama5d4_slow_osc *osc = to_clk_sama5d4_slow_osc(clk); + struct clk_sama5d4_slow_osc *osc = to_clk_sama5d4_slow_osc(hw); if (osc->prepared) return 0; @@ -527,9 +527,9 @@ static int clk_sama5d4_slow_osc_enable(struct clk *clk) return 0; } -static int clk_sama5d4_slow_osc_is_enabled(struct clk *clk) +static int clk_sama5d4_slow_osc_is_enabled(struct clk_hw *hw) { - struct clk_sama5d4_slow_osc *osc = to_clk_sama5d4_slow_osc(clk); + struct clk_sama5d4_slow_osc *osc = to_clk_sama5d4_slow_osc(hw); return osc->prepared; } @@ -560,10 +560,10 @@ static void __init of_sama5d4_sckc_setup(struct device_node *np) osc = xzalloc(sizeof(*osc)); osc->parent_name = of_clk_get_parent_name(np, 0); - osc->clk.name = parent_names[1]; - osc->clk.ops = &sama5d4_slow_osc_ops; - osc->clk.parent_names = &osc->parent_name; - osc->clk.num_parents = 1; + osc->hw.clk.name = parent_names[1]; + osc->hw.clk.ops = &sama5d4_slow_osc_ops; + osc->hw.clk.parent_names = &osc->parent_name; + osc->hw.clk.num_parents = 1; /* osc->clk.flags = CLK_IGNORE_UNUSED; */ @@ -571,7 +571,7 @@ static void __init of_sama5d4_sckc_setup(struct device_node *np) osc->startup_usec = 1200000; osc->bits = &at91sama5d4_bits; - ret = clk_register(&osc->clk); + ret = bclk_register(&osc->hw.clk); if (ret) goto free_slow_osc_data; @@ -590,7 +590,7 @@ static void __init of_sama5d4_sckc_setup(struct device_node *np) unregister_slowck: at91_clk_unregister_sam9x5_slow(slowck); unregister_slow_osc: - clk_unregister(&osc->clk); + clk_unregister(&osc->hw.clk); free_slow_osc_data: kfree(osc); clk_unregister(slow_rc); diff --git a/drivers/clk/clk-ar933x.c b/drivers/clk/clk-ar933x.c index 0e7f2d6a67..c5e57f41ec 100644 --- a/drivers/clk/clk-ar933x.c +++ b/drivers/clk/clk-ar933x.c @@ -19,17 +19,17 @@ static struct clk *clks[ATH79_CLK_END]; static struct clk_onecell_data clk_data; struct clk_ar933x { - struct clk clk; + struct clk_hw hw; void __iomem *base; u32 div_shift; u32 div_mask; const char *parent; }; -static unsigned long clk_ar933x_recalc_rate(struct clk *clk, +static unsigned long clk_ar933x_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) { - struct clk_ar933x *f = container_of(clk, struct clk_ar933x, clk); + struct clk_ar933x *f = container_of(hw, struct clk_ar933x, hw); unsigned long rate; unsigned long freq; u32 clock_ctrl; @@ -79,14 +79,14 @@ static struct clk *clk_ar933x(const char *name, const char *parent, f->div_shift = div_shift; f->div_mask = div_mask; - f->clk.ops = &clk_ar933x_ops; - f->clk.name = name; - f->clk.parent_names = &f->parent; - f->clk.num_parents = 1; + f->hw.clk.ops = &clk_ar933x_ops; + f->hw.clk.name = name; + f->hw.clk.parent_names = &f->parent; + f->hw.clk.num_parents = 1; - clk_register(&f->clk); + bclk_register(&f->hw.clk); - return &f->clk; + return &f->hw.clk; } static void ar933x_pll_init(void __iomem *base) diff --git a/drivers/clk/clk-ar9344.c b/drivers/clk/clk-ar9344.c index 829d4b1f91..d2f63f2608 100644 --- a/drivers/clk/clk-ar9344.c +++ b/drivers/clk/clk-ar9344.c @@ -35,17 +35,17 @@ static struct clk *clks[ATH79_CLK_END]; static struct clk_onecell_data clk_data; struct clk_ar9344 { - struct clk clk; + struct clk_hw hw; void __iomem *base; u32 div_shift; u32 div_mask; const char *parent; }; -static unsigned long clk_ar9344_recalc_rate(struct clk *clk, +static unsigned long clk_ar9344_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) { - struct clk_ar9344 *f = container_of(clk, struct clk_ar9344, clk); + struct clk_ar9344 *f = container_of(hw, struct clk_ar9344, hw); int outdiv, refdiv, nint, nfrac; int cpu_post_div; u32 clock_ctrl; @@ -84,14 +84,14 @@ static struct clk *clk_ar9344(const char *name, const char *parent, f->div_shift = 0; f->div_mask = 0; - f->clk.ops = &clk_ar9344_ops; - f->clk.name = name; - f->clk.parent_names = &f->parent; - f->clk.num_parents = 1; + f->hw.clk.ops = &clk_ar9344_ops; + f->hw.clk.name = name; + f->hw.clk.parent_names = &f->parent; + f->hw.clk.num_parents = 1; - clk_register(&f->clk); + bclk_register(&f->hw.clk); - return &f->clk; + return &f->hw.clk; } static void ar9344_pll_init(void __iomem *base) diff --git a/drivers/clk/clk-bulk.c b/drivers/clk/clk-bulk.c index b8db60dcbc..0a0d0f2cb2 100644 --- a/drivers/clk/clk-bulk.c +++ b/drivers/clk/clk-bulk.c @@ -23,8 +23,9 @@ void clk_bulk_put(int num_clks, struct clk_bulk_data *clks) } EXPORT_SYMBOL_GPL(clk_bulk_put); -int __must_check clk_bulk_get(struct device_d *dev, int num_clks, - struct clk_bulk_data *clks) +static int __clk_bulk_get(struct device_d *dev, int num_clks, + struct clk_bulk_data *clks, + bool optional) { int ret; int i; @@ -36,10 +37,15 @@ int __must_check clk_bulk_get(struct device_d *dev, int num_clks, clks[i].clk = clk_get(dev, clks[i].id); if (IS_ERR(clks[i].clk)) { ret = PTR_ERR(clks[i].clk); + clks[i].clk = NULL; + + if (ret == -ENOENT && optional) + continue; + if (ret != -EPROBE_DEFER) dev_err(dev, "Failed to get clk '%s': %d\n", clks[i].id, ret); - clks[i].clk = NULL; + goto err; } } @@ -51,8 +57,21 @@ err: return ret; } + +int __must_check clk_bulk_get(struct device_d *dev, int num_clks, + struct clk_bulk_data *clks) +{ + return __clk_bulk_get(dev, num_clks, clks, false); +} EXPORT_SYMBOL(clk_bulk_get); +int __must_check clk_bulk_get_optional(struct device_d *dev, int num_clks, + struct clk_bulk_data *clks) +{ + return __clk_bulk_get(dev, num_clks, clks, true); +} +EXPORT_SYMBOL(clk_bulk_get_optional); + static int __must_check of_clk_bulk_get(struct device_node *np, int num_clks, struct clk_bulk_data *clks) { diff --git a/drivers/clk/clk-composite.c b/drivers/clk/clk-composite.c index e0f543bc1c..479ac5e8ef 100644 --- a/drivers/clk/clk-composite.c +++ b/drivers/clk/clk-composite.c @@ -12,85 +12,115 @@ #include <linux/err.h> struct clk_composite { - struct clk clk; + struct clk_hw hw; struct clk *mux_clk; struct clk *rate_clk; struct clk *gate_clk; }; -#define to_clk_composite(_clk) container_of(_clk, struct clk_composite, clk) +#define to_clk_composite(_hw) container_of(_hw, struct clk_composite, hw) -static int clk_composite_get_parent(struct clk *clk) +static int clk_composite_get_parent(struct clk_hw *hw) { - struct clk_composite *composite = to_clk_composite(clk); + struct clk_composite *composite = to_clk_composite(hw); struct clk *mux_clk = composite->mux_clk; + struct clk_hw *mux_hw = clk_to_clk_hw(mux_clk); - return mux_clk ? mux_clk->ops->get_parent(mux_clk) : 0; + return mux_clk ? mux_clk->ops->get_parent(mux_hw) : 0; } -static int clk_composite_set_parent(struct clk *clk, u8 index) +static int clk_composite_set_parent(struct clk_hw *hw, u8 index) { - struct clk_composite *composite = to_clk_composite(clk); + struct clk_composite *composite = to_clk_composite(hw); struct clk *mux_clk = composite->mux_clk; + struct clk_hw *mux_hw = clk_to_clk_hw(mux_clk); - return mux_clk ? mux_clk->ops->set_parent(mux_clk, index) : 0; + return mux_clk ? mux_clk->ops->set_parent(mux_hw, index) : 0; } -static unsigned long clk_composite_recalc_rate(struct clk *clk, +static unsigned long clk_composite_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) { - struct clk_composite *composite = to_clk_composite(clk); + struct clk_composite *composite = to_clk_composite(hw); struct clk *rate_clk = composite->rate_clk; + struct clk_hw *rate_hw = clk_to_clk_hw(rate_clk); if (rate_clk) - return rate_clk->ops->recalc_rate(rate_clk, parent_rate); + return rate_clk->ops->recalc_rate(rate_hw, parent_rate); return parent_rate; } -static long clk_composite_round_rate(struct clk *clk, unsigned long rate, +static long clk_composite_round_rate(struct clk_hw *hw, unsigned long rate, unsigned long *prate) { - struct clk_composite *composite = to_clk_composite(clk); + struct clk_composite *composite = to_clk_composite(hw); struct clk *rate_clk = composite->rate_clk; + struct clk *mux_clk = composite->mux_clk; + struct clk_hw *rate_hw = clk_to_clk_hw(rate_clk); + + if (rate_clk) + return rate_clk->ops->round_rate(rate_hw, rate, prate); - return rate_clk ? rate_clk->ops->round_rate(rate_clk, rate, prate) : 0; + if (!(hw->clk.flags & CLK_SET_RATE_NO_REPARENT) && + mux_clk && + mux_clk->ops->set_rate) + return mux_clk->ops->round_rate(clk_to_clk_hw(mux_clk), rate, prate); + + return *prate; } -static int clk_composite_set_rate(struct clk *clk, unsigned long rate, +static int clk_composite_set_rate(struct clk_hw *hw, unsigned long rate, unsigned long parent_rate) { - struct clk_composite *composite = to_clk_composite(clk); + struct clk_composite *composite = to_clk_composite(hw); struct clk *rate_clk = composite->rate_clk; + struct clk *mux_clk = composite->mux_clk; + struct clk_hw *rate_hw = clk_to_clk_hw(rate_clk); - return rate_clk ? - rate_clk->ops->set_rate(rate_clk, rate, parent_rate) : 0; + /* + * When the rate clock is present use that to set the rate, + * otherwise try the mux clock. We currently do not support + * to find the best rate using a combination of both. + */ + if (rate_clk) + return rate_clk->ops->set_rate(rate_hw, rate, parent_rate); + + if (!(hw->clk.flags & CLK_SET_RATE_NO_REPARENT) && + mux_clk && + mux_clk->ops->set_rate) + return mux_clk->ops->set_rate(clk_to_clk_hw(mux_clk), rate, parent_rate); + + return 0; } -static int clk_composite_is_enabled(struct clk *clk) +static int clk_composite_is_enabled(struct clk_hw *hw) { - struct clk_composite *composite = to_clk_composite(clk); + struct clk_composite *composite = to_clk_composite(hw); struct clk *gate_clk = composite->gate_clk; + struct clk_hw *gate_hw = clk_to_clk_hw(gate_clk); - return gate_clk ? gate_clk->ops->is_enabled(gate_clk) : 0; + return gate_clk ? gate_clk->ops->is_enabled(gate_hw) : 0; } -static int clk_composite_enable(struct clk *clk) +static int clk_composite_enable(struct clk_hw *hw) { - struct clk_composite *composite = to_clk_composite(clk); + struct clk_composite *composite = to_clk_composite(hw); struct clk *gate_clk = composite->gate_clk; + struct clk_hw *gate_hw = clk_to_clk_hw(gate_clk); - return gate_clk ? gate_clk->ops->enable(gate_clk) : 0; + return gate_clk ? gate_clk->ops->enable(gate_hw) : 0; } -static void clk_composite_disable(struct clk *clk) +static void clk_composite_disable(struct clk_hw *hw) { - struct clk_composite *composite = to_clk_composite(clk); + struct clk_composite *composite = to_clk_composite(hw); struct clk *gate_clk = composite->gate_clk; + struct clk_hw *gate_hw = clk_to_clk_hw(gate_clk); if (gate_clk) - gate_clk->ops->disable(gate_clk); + gate_clk->ops->disable(gate_hw); } static struct clk_ops clk_composite_ops = { @@ -116,20 +146,26 @@ struct clk *clk_register_composite(const char *name, composite = xzalloc(sizeof(*composite)); - composite->clk.name = name; - composite->clk.ops = &clk_composite_ops; - composite->clk.flags = flags; - composite->clk.parent_names = parent_names; - composite->clk.num_parents = num_parents; + composite->hw.clk.name = name; + composite->hw.clk.ops = &clk_composite_ops; + composite->hw.clk.flags = flags; + composite->hw.clk.parent_names = parent_names; + composite->hw.clk.num_parents = num_parents; composite->mux_clk = mux_clk; composite->rate_clk = rate_clk; composite->gate_clk = gate_clk; - ret = clk_register(&composite->clk); + ret = bclk_register(&composite->hw.clk); if (ret) goto err; - return &composite->clk; + if (composite->mux_clk) { + composite->mux_clk->parents = composite->hw.clk.parents; + composite->mux_clk->parent_names = composite->hw.clk.parent_names; + composite->mux_clk->num_parents = composite->hw.clk.num_parents; + } + + return &composite->hw.clk; err: kfree(composite); diff --git a/drivers/clk/clk-divider.c b/drivers/clk/clk-divider.c index 7119dd4e59..856b8a0648 100644 --- a/drivers/clk/clk-divider.c +++ b/drivers/clk/clk-divider.c @@ -92,10 +92,11 @@ unsigned long divider_recalc_rate(struct clk *clk, unsigned long parent_rate, return DIV_ROUND_UP_ULL((u64)parent_rate, div); } -static unsigned long clk_divider_recalc_rate(struct clk *clk, +static unsigned long clk_divider_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) { - struct clk_divider *divider = container_of(clk, struct clk_divider, clk); + struct clk *clk = clk_hw_to_clk(hw); + struct clk_divider *divider = container_of(hw, struct clk_divider, hw); unsigned int val; val = readl(divider->reg) >> divider->shift; @@ -233,13 +234,14 @@ long divider_round_rate(struct clk *clk, unsigned long rate, return DIV_ROUND_UP(*prate, div); } -static long clk_divider_round_rate(struct clk *clk, unsigned long rate, +static long clk_divider_round_rate(struct clk_hw *hw, unsigned long rate, unsigned long *prate) { - struct clk_divider *divider = container_of(clk, struct clk_divider, clk); + struct clk *clk = clk_hw_to_clk(hw); + struct clk_divider *divider = to_clk_divider(hw); if (divider->flags & CLK_DIVIDER_READ_ONLY) - return clk_divider_recalc_rate(clk, *prate); + return clk_divider_recalc_rate(hw, *prate); return divider_round_rate(clk, rate, prate, divider->table, divider->width, divider->flags); @@ -261,10 +263,11 @@ int divider_get_val(unsigned long rate, unsigned long parent_rate, return min_t(unsigned int, value, clk_div_mask(width)); } -static int clk_divider_set_rate(struct clk *clk, unsigned long rate, +static int clk_divider_set_rate(struct clk_hw *hw, unsigned long rate, unsigned long parent_rate) { - struct clk_divider *divider = container_of(clk, struct clk_divider, clk); + struct clk *clk = clk_hw_to_clk(hw); + struct clk_divider *divider = to_clk_divider(hw); unsigned int value; u32 val; @@ -293,12 +296,16 @@ static int clk_divider_set_rate(struct clk *clk, unsigned long rate, return 0; } -struct clk_ops clk_divider_ops = { +const struct clk_ops clk_divider_ops = { .set_rate = clk_divider_set_rate, .recalc_rate = clk_divider_recalc_rate, .round_rate = clk_divider_round_rate, }; +const struct clk_ops clk_divider_ro_ops = { + .recalc_rate = clk_divider_recalc_rate, +}; + struct clk *clk_divider_alloc(const char *name, const char *parent, unsigned clk_flags, void __iomem *reg, u8 shift, u8 width, unsigned div_flags) @@ -310,18 +317,19 @@ struct clk *clk_divider_alloc(const char *name, const char *parent, div->width = width; div->parent = parent; div->flags = div_flags; - div->clk.ops = &clk_divider_ops; - div->clk.name = name; - div->clk.flags = clk_flags; - div->clk.parent_names = &div->parent; - div->clk.num_parents = 1; + div->hw.clk.ops = &clk_divider_ops; + div->hw.clk.name = name; + div->hw.clk.flags = clk_flags; + div->hw.clk.parent_names = &div->parent; + div->hw.clk.num_parents = 1; - return &div->clk; + return &div->hw.clk; } void clk_divider_free(struct clk *clk) { - struct clk_divider *d = container_of(clk, struct clk_divider, clk); + struct clk_hw *hw = clk_to_clk_hw(clk); + struct clk_divider *d = to_clk_divider(hw); free(d); } @@ -335,7 +343,7 @@ struct clk *clk_divider(const char *name, const char *parent, unsigned clk_flags d = clk_divider_alloc(name , parent, clk_flags, reg, shift, width, div_flags); - ret = clk_register(d); + ret = bclk_register(d); if (ret) { clk_divider_free(d); return ERR_PTR(ret); @@ -350,12 +358,15 @@ struct clk *clk_divider_one_based(const char *name, const char *parent, { struct clk_divider *div; struct clk *clk; + struct clk_hw *hw; clk = clk_divider(name, parent, clk_flags, reg, shift, width, div_flags); if (IS_ERR(clk)) return clk; - div = container_of(clk, struct clk_divider, clk); + hw = clk_to_clk_hw(clk); + div = to_clk_divider(hw); + div->flags |= CLK_DIVIDER_ONE_BASED; return clk; @@ -375,11 +386,11 @@ struct clk *clk_divider_table(const char *name, const char *parent, div->width = width; div->parent = parent; div->flags = div_flags; - div->clk.ops = &clk_divider_ops; - div->clk.name = name; - div->clk.flags = clk_flags; - div->clk.parent_names = &div->parent; - div->clk.num_parents = 1; + div->hw.clk.ops = &clk_divider_ops; + div->hw.clk.name = name; + div->hw.clk.flags = clk_flags; + div->hw.clk.parent_names = &div->parent; + div->hw.clk.num_parents = 1; div->table = table; for (clkt = div->table; clkt->div; clkt++) { @@ -390,11 +401,30 @@ struct clk *clk_divider_table(const char *name, const char *parent, div->table_size++; } - ret = clk_register(&div->clk); + ret = bclk_register(&div->hw.clk); if (ret) { free(div); return ERR_PTR(ret); } - return &div->clk; + return &div->hw.clk; +} + +struct clk *clk_register_divider_table(struct device_d *dev, const char *name, + const char *parent_name, unsigned long flags, + void __iomem *reg, u8 shift, u8 width, + u8 clk_divider_flags, const struct clk_div_table *table, + spinlock_t *lock) +{ + return clk_divider_table(name, parent_name, flags, reg, shift, width, + table, clk_divider_flags); +} + +struct clk *clk_register_divider(struct device_d *dev, const char *name, + const char *parent_name, unsigned long flags, + void __iomem *reg, u8 shift, u8 width, + u8 clk_divider_flags, spinlock_t *lock) +{ + return clk_divider(name, parent_name, flags, reg, shift, width, + clk_divider_flags); } diff --git a/drivers/clk/clk-fixed-factor.c b/drivers/clk/clk-fixed-factor.c index e7738775f8..fd4a3805f1 100644 --- a/drivers/clk/clk-fixed-factor.c +++ b/drivers/clk/clk-fixed-factor.c @@ -10,25 +10,19 @@ #include <linux/clk.h> #include <linux/err.h> -struct clk_fixed_factor { - struct clk clk; - int mult; - int div; - const char *parent; -}; - -static unsigned long clk_fixed_factor_recalc_rate(struct clk *clk, +static unsigned long clk_fixed_factor_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) { - struct clk_fixed_factor *f = container_of(clk, struct clk_fixed_factor, clk); + struct clk_fixed_factor *f = to_clk_fixed_factor(hw); return (parent_rate / f->div) * f->mult; } -static long clk_factor_round_rate(struct clk *clk, unsigned long rate, +static long clk_factor_round_rate(struct clk_hw *hw, unsigned long rate, unsigned long *prate) { - struct clk_fixed_factor *fix = container_of(clk, struct clk_fixed_factor, clk); + struct clk_fixed_factor *fix = to_clk_fixed_factor(hw); + struct clk *clk = clk_hw_to_clk(hw); if (clk->flags & CLK_SET_RATE_PARENT) { unsigned long best_parent; @@ -40,10 +34,11 @@ static long clk_factor_round_rate(struct clk *clk, unsigned long rate, return (*prate / fix->div) * fix->mult; } -static int clk_factor_set_rate(struct clk *clk, unsigned long rate, +static int clk_factor_set_rate(struct clk_hw *hw, unsigned long rate, unsigned long parent_rate) { - struct clk_fixed_factor *fix = container_of(clk, struct clk_fixed_factor, clk); + struct clk_fixed_factor *fix = to_clk_fixed_factor(hw); + struct clk *clk = clk_hw_to_clk(hw); if (clk->flags & CLK_SET_RATE_PARENT) { return clk_set_rate(clk_get_parent(clk), rate * fix->div / fix->mult); @@ -52,7 +47,7 @@ static int clk_factor_set_rate(struct clk *clk, unsigned long rate, return 0; } -static struct clk_ops clk_fixed_factor_ops = { +struct clk_ops clk_fixed_factor_ops = { .set_rate = clk_factor_set_rate, .round_rate = clk_factor_round_rate, .recalc_rate = clk_fixed_factor_recalc_rate, @@ -67,19 +62,26 @@ struct clk *clk_fixed_factor(const char *name, f->mult = mult; f->div = div; f->parent = parent; - f->clk.ops = &clk_fixed_factor_ops; - f->clk.name = name; - f->clk.flags = flags; - f->clk.parent_names = &f->parent; - f->clk.num_parents = 1; + f->hw.clk.ops = &clk_fixed_factor_ops; + f->hw.clk.name = name; + f->hw.clk.flags = flags; + f->hw.clk.parent_names = &f->parent; + f->hw.clk.num_parents = 1; - ret = clk_register(&f->clk); + ret = bclk_register(&f->hw.clk); if (ret) { free(f); return ERR_PTR(ret); } - return &f->clk; + return &f->hw.clk; +} + +struct clk *clk_register_fixed_factor(struct device_d *dev, const char *name, + const char *parent_name, unsigned long flags, + unsigned int mult, unsigned int div) +{ + return clk_fixed_factor(name, parent_name, mult, div, flags); } /** diff --git a/drivers/clk/clk-fixed.c b/drivers/clk/clk-fixed.c index d7ac59c4d4..b961c382ec 100644 --- a/drivers/clk/clk-fixed.c +++ b/drivers/clk/clk-fixed.c @@ -10,14 +10,14 @@ #include <linux/err.h> struct clk_fixed { - struct clk clk; + struct clk_hw hw; unsigned long rate; }; -static unsigned long clk_fixed_recalc_rate(struct clk *clk, +static unsigned long clk_fixed_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) { - struct clk_fixed *fix = container_of(clk, struct clk_fixed, clk); + struct clk_fixed *fix = container_of(hw, struct clk_fixed, hw); return fix->rate; } @@ -36,27 +36,27 @@ struct clk *clk_register_fixed_rate(const char *name, int ret; fix->rate = rate; - fix->clk.ops = &clk_fixed_ops; - fix->clk.name = name; - fix->clk.flags = flags; + fix->hw.clk.ops = &clk_fixed_ops; + fix->hw.clk.name = name; + fix->hw.clk.flags = flags; if (parent_name) { parent_names = kzalloc(sizeof(const char *), GFP_KERNEL); if (!parent_names) return ERR_PTR(-ENOMEM); - fix->clk.parent_names = parent_names; - fix->clk.num_parents = 1; + fix->hw.clk.parent_names = parent_names; + fix->hw.clk.num_parents = 1; } - ret = clk_register(&fix->clk); + ret = bclk_register(&fix->hw.clk); if (ret) { free(parent_names); free(fix); return ERR_PTR(ret); } - return &fix->clk; + return &fix->hw.clk; } /** diff --git a/drivers/clk/clk-fractional-divider.c b/drivers/clk/clk-fractional-divider.c index 6f0763b05f..3d96360025 100644 --- a/drivers/clk/clk-fractional-divider.c +++ b/drivers/clk/clk-fractional-divider.c @@ -1,86 +1,129 @@ -// SPDX-License-Identifier: GPL-2.0-only +// SPDX-License-Identifier: GPL-2.0 /* * Copyright (C) 2014 Intel Corporation * * Adjustable fractional divider clock implementation. * Output rate = (m / n) * parent_rate. + * Uses rational best approximation algorithm. */ #include <common.h> #include <io.h> #include <malloc.h> #include <linux/clk.h> +#include <linux/spinlock.h> #include <linux/err.h> #include <linux/gcd.h> #include <linux/math64.h> +#include <linux/rational.h> #include <linux/barebox-wrapper.h> -#define to_clk_fd(_hw) container_of(_hw, struct clk_fractional_divider, clk) +static inline u32 clk_fd_readl(struct clk_fractional_divider *fd) +{ + if (fd->flags & CLK_FRAC_DIVIDER_BIG_ENDIAN) + return ioread32be(fd->reg); -struct clk_fractional_divider { - struct clk clk; - void __iomem *reg; - u8 mshift; - u32 mmask; - u8 nshift; - u32 nmask; - u8 flags; -}; + return readl(fd->reg); +} + +static inline void clk_fd_writel(struct clk_fractional_divider *fd, u32 val) +{ + if (fd->flags & CLK_FRAC_DIVIDER_BIG_ENDIAN) + iowrite32be(val, fd->reg); + else + writel(val, fd->reg); +} -static unsigned long clk_fd_recalc_rate(struct clk *hw, +static unsigned long clk_fd_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) { struct clk_fractional_divider *fd = to_clk_fd(hw); - u32 val, m, n; + unsigned long m, n; + u32 val; u64 ret; - val = readl(fd->reg); + val = clk_fd_readl(fd); m = (val & fd->mmask) >> fd->mshift; n = (val & fd->nmask) >> fd->nshift; + if (fd->flags & CLK_FRAC_DIVIDER_ZERO_BASED) { + m++; + n++; + } + + if (!n || !m) + return parent_rate; + ret = (u64)parent_rate * m; do_div(ret, n); return ret; } -static long clk_fd_round_rate(struct clk *hw, unsigned long rate, - unsigned long *prate) +static void clk_fd_general_approximation(struct clk_hw *hw, unsigned long rate, + unsigned long *parent_rate, + unsigned long *m, unsigned long *n) { struct clk_fractional_divider *fd = to_clk_fd(hw); - unsigned maxn = (fd->nmask >> fd->nshift) + 1; - unsigned div; + unsigned long scale; + + /* + * Get rate closer to *parent_rate to guarantee there is no overflow + * for m and n. In the result it will be the nearest rate left shifted + * by (scale - fd->nwidth) bits. + */ + scale = fls_long(*parent_rate / rate - 1); + if (scale > fd->nwidth) + rate <<= scale - fd->nwidth; + + rational_best_approximation(rate, *parent_rate, + GENMASK(fd->mwidth - 1, 0), GENMASK(fd->nwidth - 1, 0), + m, n); +} - if (!rate || rate >= *prate) - return *prate; +static long clk_fd_round_rate(struct clk_hw *hw, unsigned long rate, + unsigned long *parent_rate) +{ + struct clk *clk = clk_hw_to_clk(hw); + struct clk_fractional_divider *fd = to_clk_fd(hw); + unsigned long m, n; + u64 ret; - div = gcd(*prate, rate); + if (!rate || (!(clk->flags & CLK_SET_RATE_PARENT) && rate >= *parent_rate)) + return *parent_rate; - while ((*prate / div) > maxn) { - div <<= 1; - rate <<= 1; - } + if (fd->approximation) + fd->approximation(hw, rate, parent_rate, &m, &n); + else + clk_fd_general_approximation(hw, rate, parent_rate, &m, &n); - return rate; + ret = (u64)*parent_rate * m; + do_div(ret, n); + + return ret; } -static int clk_fd_set_rate(struct clk *hw, unsigned long rate, +static int clk_fd_set_rate(struct clk_hw *hw, unsigned long rate, unsigned long parent_rate) { struct clk_fractional_divider *fd = to_clk_fd(hw); - unsigned long div; - unsigned n, m; + unsigned long m, n; u32 val; - div = gcd(parent_rate, rate); - m = rate / div; - n = parent_rate / div; + rational_best_approximation(rate, parent_rate, + GENMASK(fd->mwidth - 1, 0), GENMASK(fd->nwidth - 1, 0), + &m, &n); + + if (fd->flags & CLK_FRAC_DIVIDER_ZERO_BASED) { + m--; + n--; + } - val = readl(fd->reg); + val = clk_fd_readl(fd); val &= ~(fd->mmask | fd->nmask); val |= (m << fd->mshift) | (n << fd->nshift); - writel(val, fd->reg); + clk_fd_writel(fd, val); return 0; } @@ -103,22 +146,24 @@ struct clk *clk_fractional_divider_alloc( fd->reg = reg; fd->mshift = mshift; - fd->mmask = (BIT(mwidth) - 1) << mshift; + fd->mwidth = mwidth; + fd->mmask = GENMASK(mwidth - 1, 0) << mshift; fd->nshift = nshift; - fd->nmask = (BIT(nwidth) - 1) << nshift; + fd->nwidth = nwidth; + fd->nmask = GENMASK(nwidth - 1, 0) << nshift; fd->flags = clk_divider_flags; - fd->clk.name = name; - fd->clk.ops = &clk_fractional_divider_ops; - fd->clk.flags = flags; - fd->clk.parent_names = parent_name ? &parent_name : NULL; - fd->clk.num_parents = parent_name ? 1 : 0; + fd->hw.clk.name = name; + fd->hw.clk.ops = &clk_fractional_divider_ops; + fd->hw.clk.flags = flags; + fd->hw.clk.parent_names = parent_name ? &parent_name : NULL; + fd->hw.clk.num_parents = parent_name ? 1 : 0; - return &fd->clk; + return &fd->hw.clk; } void clk_fractional_divider_free(struct clk *clk_fd) { - struct clk_fractional_divider *fd = to_clk_fd(clk_fd); + struct clk_fractional_divider *fd = to_clk_fd(clk_to_clk_hw(clk_fd)); free(fd); } @@ -138,7 +183,7 @@ struct clk *clk_fractional_divider( if (IS_ERR(fd)) return fd; - ret = clk_register(fd); + ret = bclk_register(fd); if (ret) { clk_fractional_divider_free(fd); return ERR_PTR(ret); diff --git a/drivers/clk/clk-gate-shared.c b/drivers/clk/clk-gate-shared.c index 54c002e836..069f6975b1 100644 --- a/drivers/clk/clk-gate-shared.c +++ b/drivers/clk/clk-gate-shared.c @@ -11,13 +11,13 @@ #include <linux/err.h> struct clk_gate_shared { - struct clk clk; + struct clk_hw hw; const char *parent; const char *companion_gate; struct clk *companion_clk; }; -#define to_clk_gate_shared(_clk) container_of(_clk, struct clk_gate_shared, clk) +#define to_clk_gate_shared(_hw) container_of(_hw, struct clk_gate_shared, hw) static struct clk *lookup_companion(struct clk_gate_shared *g) { @@ -30,23 +30,23 @@ static struct clk *lookup_companion(struct clk_gate_shared *g) return g->companion_clk; } -static int clk_gate_shared_enable(struct clk *clk) +static int clk_gate_shared_enable(struct clk_hw *hw) { - struct clk_gate_shared *g = to_clk_gate_shared(clk); + struct clk_gate_shared *g = to_clk_gate_shared(hw); return clk_enable(lookup_companion(g)); } -static void clk_gate_shared_disable(struct clk *clk) +static void clk_gate_shared_disable(struct clk_hw *hw) { - struct clk_gate_shared *g = to_clk_gate_shared(clk); + struct clk_gate_shared *g = to_clk_gate_shared(hw); clk_disable(lookup_companion(g)); } -static int clk_gate_shared_is_enabled(struct clk *clk) +static int clk_gate_shared_is_enabled(struct clk_hw *hw) { - struct clk_gate_shared *g = to_clk_gate_shared(clk); + struct clk_gate_shared *g = to_clk_gate_shared(hw); return clk_is_enabled(lookup_companion(g)); } @@ -67,18 +67,19 @@ static struct clk *clk_gate_shared_alloc(const char *name, const char *parent, g->parent = parent; g->companion_gate = companion; g->companion_clk = ERR_PTR(-EINVAL); - g->clk.ops = &clk_gate_shared_ops; - g->clk.name = name; - g->clk.flags = flags; - g->clk.parent_names = &g->parent; - g->clk.num_parents = 1; + g->hw.clk.ops = &clk_gate_shared_ops; + g->hw.clk.name = name; + g->hw.clk.flags = flags; + g->hw.clk.parent_names = &g->parent; + g->hw.clk.num_parents = 1; - return &g->clk; + return &g->hw.clk; } static void clk_gate_shared_free(struct clk *clk) { - struct clk_gate_shared *g = to_clk_gate_shared(clk); + struct clk_hw *hw = clk_to_clk_hw(clk); + struct clk_gate_shared *g = to_clk_gate_shared(hw); free(g); } @@ -103,7 +104,7 @@ struct clk *clk_gate_shared(const char *name, const char *parent, const char *co clk = clk_gate_shared_alloc(name , parent, companion, flags); - ret = clk_register(clk); + ret = bclk_register(clk); if (ret) { clk_gate_shared_free(clk); return ERR_PTR(ret); diff --git a/drivers/clk/clk-gate.c b/drivers/clk/clk-gate.c index 59dd643b99..3cfd707238 100644 --- a/drivers/clk/clk-gate.c +++ b/drivers/clk/clk-gate.c @@ -10,10 +10,10 @@ #include <linux/clk.h> #include <linux/err.h> -static void clk_gate_endisable(struct clk *clk, int enable) +static void clk_gate_endisable(struct clk_hw *hw, int enable) { - struct clk_gate *gate = container_of(clk, struct clk_gate, clk); - int set = gate->flags & CLK_GATE_INVERTED ? 1 : 0; + struct clk_gate *gate = container_of(hw, struct clk_gate, hw); + int set = gate->flags & CLK_GATE_SET_TO_DISABLE ? 1 : 0; u32 val; set ^= enable; @@ -34,29 +34,29 @@ static void clk_gate_endisable(struct clk *clk, int enable) writel(val, gate->reg); } -static int clk_gate_enable(struct clk *clk) +static int clk_gate_enable(struct clk_hw *hw) { - clk_gate_endisable(clk, 1); + clk_gate_endisable(hw, 1); return 0; } -static void clk_gate_disable(struct clk *clk) +static void clk_gate_disable(struct clk_hw *hw) { - clk_gate_endisable(clk, 0); + clk_gate_endisable(hw, 0); } -int clk_gate_is_enabled(struct clk *clk) +int clk_gate_is_enabled(struct clk_hw *hw) { - struct clk_gate *g = container_of(clk, struct clk_gate, clk); + struct clk_gate *g = container_of(hw, struct clk_gate, hw); u32 val; val = readl(g->reg); if (val & (1 << g->shift)) - return g->flags & CLK_GATE_INVERTED ? 0 : 1; + return g->flags & CLK_GATE_SET_TO_DISABLE ? 0 : 1; else - return g->flags & CLK_GATE_INVERTED ? 1 : 0; + return g->flags & CLK_GATE_SET_TO_DISABLE ? 1 : 0; } struct clk_ops clk_gate_ops = { @@ -75,19 +75,20 @@ struct clk *clk_gate_alloc(const char *name, const char *parent, g->parent = parent; g->reg = reg; g->shift = shift; - g->clk.ops = &clk_gate_ops; - g->clk.name = name; - g->clk.flags = flags; - g->clk.parent_names = &g->parent; - g->clk.num_parents = 1; + g->hw.clk.ops = &clk_gate_ops; + g->hw.clk.name = name; + g->hw.clk.flags = flags; + g->hw.clk.parent_names = &g->parent; + g->hw.clk.num_parents = 1; g->flags = clk_gate_flags; - return &g->clk; + return &g->hw.clk; } void clk_gate_free(struct clk *clk_gate) { - struct clk_gate *g = to_clk_gate(clk_gate); + struct clk_hw *hw = clk_to_clk_hw(clk_gate); + struct clk_gate *g = to_clk_gate(hw); free(g); } @@ -100,9 +101,10 @@ struct clk *clk_gate(const char *name, const char *parent, void __iomem *reg, g = clk_gate_alloc(name , parent, reg, shift, flags, clk_gate_flags); - ret = clk_register(g); + ret = bclk_register(g); if (ret) { - free(to_clk_gate(g)); + struct clk_hw *hw = clk_to_clk_hw(g); + free(to_clk_gate(hw)); return ERR_PTR(ret); } @@ -112,5 +114,13 @@ struct clk *clk_gate(const char *name, const char *parent, void __iomem *reg, struct clk *clk_gate_inverted(const char *name, const char *parent, void __iomem *reg, u8 shift, unsigned flags) { - return clk_gate(name, parent, reg, shift, flags, CLK_GATE_INVERTED); + return clk_gate(name, parent, reg, shift, flags, CLK_GATE_SET_TO_DISABLE); +} + +struct clk *clk_register_gate(struct device_d *dev, const char *name, + const char *parent_name, unsigned long flags, + void __iomem *reg, u8 bit_idx, + u8 clk_gate_flags, spinlock_t *lock) +{ + return clk_gate(name, parent_name, reg, bit_idx, flags, clk_gate_flags); } diff --git a/drivers/clk/clk-gpio.c b/drivers/clk/clk-gpio.c index 1345fbc9ea..6ac2e820fa 100644 --- a/drivers/clk/clk-gpio.c +++ b/drivers/clk/clk-gpio.c @@ -14,30 +14,30 @@ #include <init.h> struct clk_gpio { - struct clk clk; + struct clk_hw hw; const char *parent; int gpio; }; -#define to_clk_gpio(_clk) container_of(_clk, struct clk_gpio, clk) +#define to_clk_gpio(_hw) container_of(_hw, struct clk_gpio, hw) -static int clk_gpio_enable(struct clk *clk) +static int clk_gpio_enable(struct clk_hw *hw) { - struct clk_gpio *clk_gpio = to_clk_gpio(clk); + struct clk_gpio *clk_gpio = to_clk_gpio(hw); gpio_set_active(clk_gpio->gpio, true); return 0; } -static void clk_gpio_disable(struct clk *clk) +static void clk_gpio_disable(struct clk_hw *hw) { - struct clk_gpio *clk_gpio = to_clk_gpio(clk); + struct clk_gpio *clk_gpio = to_clk_gpio(hw); gpio_set_active(clk_gpio->gpio, false); } -static int clk_gpio_is_enabled(struct clk *clk) +static int clk_gpio_is_enabled(struct clk_hw *hw) { - struct clk_gpio *clk_gpio = to_clk_gpio(clk); + struct clk_gpio *clk_gpio = to_clk_gpio(hw); return gpio_is_active(clk_gpio->gpio); } @@ -67,13 +67,13 @@ static int of_gpio_clk_setup(struct device_node *node) goto no_parent; } - clk_gpio->clk.ops = &clk_gpio_ops; - clk_gpio->clk.parent_names = &clk_gpio->parent; - clk_gpio->clk.num_parents = 1; + clk_gpio->hw.clk.ops = &clk_gpio_ops; + clk_gpio->hw.clk.parent_names = &clk_gpio->parent; + clk_gpio->hw.clk.num_parents = 1; - clk_gpio->clk.name = node->name; + clk_gpio->hw.clk.name = node->name; of_property_read_string(node, "clock-output-names", - &clk_gpio->clk.name); + &clk_gpio->hw.clk.name); ret = of_get_named_gpio_flags(node, "enable-gpios", 0, &of_flags); @@ -86,15 +86,15 @@ static int of_gpio_clk_setup(struct device_node *node) flags = GPIOF_OUT_INIT_ACTIVE; if (of_flags & OF_GPIO_ACTIVE_LOW) flags |= GPIOF_ACTIVE_LOW; - ret = gpio_request_one(clk_gpio->gpio, flags, clk_gpio->clk.name); + ret = gpio_request_one(clk_gpio->gpio, flags, clk_gpio->hw.clk.name); if (ret) goto no_request; - ret = clk_register(&clk_gpio->clk); + ret = bclk_register(&clk_gpio->hw.clk); if (ret) goto no_register; - return of_clk_add_provider(node, of_clk_src_simple_get, &clk_gpio->clk); + return of_clk_add_provider(node, of_clk_src_simple_get, &clk_gpio->hw.clk); no_register: gpio_free(clk_gpio->gpio); diff --git a/drivers/clk/clk-mux.c b/drivers/clk/clk-mux.c index a4743c51b0..d8c09e4a75 100644 --- a/drivers/clk/clk-mux.c +++ b/drivers/clk/clk-mux.c @@ -10,21 +10,21 @@ #include <linux/clk.h> #include <linux/err.h> -static int clk_mux_get_parent(struct clk *clk) +static int clk_mux_get_parent(struct clk_hw *hw) { - struct clk_mux *m = container_of(clk, struct clk_mux, clk); + struct clk_mux *m = to_clk_mux(hw); int idx = readl(m->reg) >> m->shift & ((1 << m->width) - 1); return idx; } -static int clk_mux_set_parent(struct clk *clk, u8 idx) +static int clk_mux_set_parent(struct clk_hw *hw, u8 idx) { - struct clk_mux *m = container_of(clk, struct clk_mux, clk); + struct clk_mux *m = to_clk_mux(hw); u32 val; if (m->flags & CLK_MUX_READ_ONLY) { - if (clk_mux_get_parent(clk) != idx) + if (clk_mux_get_parent(hw) != idx) return -EPERM; else return 0; @@ -34,20 +34,102 @@ static int clk_mux_set_parent(struct clk *clk, u8 idx) val &= ~(((1 << m->width) - 1) << m->shift); val |= idx << m->shift; - if (clk->flags & CLK_MUX_HIWORD_MASK) + if (m->flags & CLK_MUX_HIWORD_MASK) val |= ((1 << m->width) - 1) << (m->shift + 16); writel(val, m->reg); return 0; } -struct clk_ops clk_mux_ops = { - .set_rate = clk_parent_set_rate, - .round_rate = clk_parent_round_rate, +static struct clk *clk_get_parent_index(struct clk *clk, int num) +{ + if (num >= clk->num_parents) + return NULL; + + if (clk->parents[num]) + return clk->parents[num]; + + clk->parents[num] = clk_lookup(clk->parent_names[num]); + + return clk->parents[num]; +} + +static struct clk *clk_mux_best_parent(struct clk *mux, unsigned long rate, + unsigned long *rrate) +{ + struct clk *bestparent = NULL; + long bestrate = LONG_MAX; + int i; + + for (i = 0; i < mux->num_parents; i++) { + struct clk *parent = clk_get_parent_index(mux, i); + unsigned long r; + + if (IS_ERR_OR_NULL(parent)) + continue; + + if (mux->flags & CLK_SET_RATE_PARENT) + r = clk_round_rate(parent, rate); + else + r = clk_get_rate(parent); + + if (abs((long)rate - r) < abs((long)rate - bestrate)) { + bestrate = r; + bestparent = parent; + } + } + + *rrate = bestrate; + + return bestparent; +} + +static long clk_mux_round_rate(struct clk_hw *hw, unsigned long rate, + unsigned long *prate) +{ + struct clk *clk = clk_hw_to_clk(hw); + unsigned long rrate; + struct clk *bestparent; + + if (clk->flags & CLK_SET_RATE_NO_REPARENT) + return *prate; + + bestparent = clk_mux_best_parent(clk, rate, &rrate); + + return rrate; +} + +static int clk_mux_set_rate(struct clk_hw *hw, unsigned long rate, + unsigned long parent_rate) +{ + struct clk *clk = clk_hw_to_clk(hw); + struct clk *parent; + unsigned long rrate; + int ret; + + if (clk->flags & CLK_SET_RATE_NO_REPARENT) + return 0; + + parent = clk_mux_best_parent(clk, rate, &rrate); + + ret = clk_set_parent(clk, parent); + if (ret) + return ret; + + return clk_set_rate(parent, rate); +} + +const struct clk_ops clk_mux_ops = { + .set_rate = clk_mux_set_rate, + .round_rate = clk_mux_round_rate, .get_parent = clk_mux_get_parent, .set_parent = clk_mux_set_parent, }; +const struct clk_ops clk_mux_ro_ops = { + .get_parent = clk_mux_get_parent, +}; + struct clk *clk_mux_alloc(const char *name, unsigned clk_flags, void __iomem *reg, u8 shift, u8 width, const char * const *parents, u8 num_parents, unsigned mux_flags) @@ -58,18 +140,19 @@ struct clk *clk_mux_alloc(const char *name, unsigned clk_flags, void __iomem *re m->shift = shift; m->width = width; m->flags = mux_flags; - m->clk.ops = &clk_mux_ops; - m->clk.name = name; - m->clk.flags = clk_flags; - m->clk.parent_names = parents; - m->clk.num_parents = num_parents; + m->hw.clk.ops = &clk_mux_ops; + m->hw.clk.name = name; + m->hw.clk.flags = clk_flags; + m->hw.clk.parent_names = parents; + m->hw.clk.num_parents = num_parents; - return &m->clk; + return &m->hw.clk; } void clk_mux_free(struct clk *clk_mux) { - struct clk_mux *m = to_clk_mux(clk_mux); + struct clk_hw *hw = clk_to_clk_hw(clk_mux); + struct clk_mux *m = to_clk_mux(hw); free(m); } @@ -84,11 +167,22 @@ struct clk *clk_mux(const char *name, unsigned clk_flags, void __iomem *reg, m = clk_mux_alloc(name, clk_flags, reg, shift, width, parents, num_parents, mux_flags); - ret = clk_register(m); + ret = bclk_register(m); if (ret) { - free(to_clk_mux(m)); + struct clk_hw *hw = clk_to_clk_hw(m); + free(to_clk_mux(hw)); return ERR_PTR(ret); } return m; } + +struct clk *clk_register_mux(struct device_d *dev, const char *name, + const char * const *parent_names, u8 num_parents, + unsigned long flags, + void __iomem *reg, u8 shift, u8 width, + u8 clk_mux_flags, spinlock_t *lock) +{ + return clk_mux(name, flags, reg, shift, width, parent_names, + num_parents, clk_mux_flags); +} diff --git a/drivers/clk/clk-qoric.c b/drivers/clk/clk-qoric.c index 5bf677d94e..f7dbf7230d 100644 --- a/drivers/clk/clk-qoric.c +++ b/drivers/clk/clk-qoric.c @@ -29,7 +29,7 @@ #define CGB_PLL2 5 struct clockgen_pll_div { - struct clk *clk; + struct clk_hw *hw; char name[32]; }; @@ -254,20 +254,20 @@ static const struct clockgen_chipinfo chipinfo_ls2080a = { }; struct mux_hwclock { - struct clk clk; + struct clk_hw hw; struct clockgen *cg; const struct clockgen_muxinfo *info; u32 __iomem *reg; int num_parents; }; -#define to_mux_hwclock(p) container_of(p, struct mux_hwclock, clk) +#define to_mux_hwclock(p) container_of(p, struct mux_hwclock, hw) #define CLKSEL_MASK 0x78000000 #define CLKSEL_SHIFT 27 -static int mux_set_parent(struct clk *clk, u8 idx) +static int mux_set_parent(struct clk_hw *hw, u8 idx) { - struct mux_hwclock *hwc = to_mux_hwclock(clk); + struct mux_hwclock *hwc = to_mux_hwclock(hw); if (idx >= hwc->num_parents) return -EINVAL; @@ -277,9 +277,9 @@ static int mux_set_parent(struct clk *clk, u8 idx) return 0; } -static int mux_get_parent(struct clk *clk) +static int mux_get_parent(struct clk_hw *hw) { - struct mux_hwclock *hwc = to_mux_hwclock(clk); + struct mux_hwclock *hwc = to_mux_hwclock(hw); return (cg_in(hwc->cg, hwc->reg) & CLKSEL_MASK) >> CLKSEL_SHIFT; } @@ -318,7 +318,7 @@ static struct clk * __init create_mux_common(struct clockgen *cg, const struct clk_ops *ops, const char *fmt, int idx) { - struct clk *clk = &hwc->clk; + struct clk_hw *hw = &hwc->hw; const struct clockgen_pll_div *div; const char **parent_names; int i, ret; @@ -333,20 +333,20 @@ static struct clk * __init create_mux_common(struct clockgen *cg, parent_names[i] = div->name; } - clk->name = xasprintf(fmt, idx);; - clk->ops = ops; - clk->parent_names = parent_names; - clk->num_parents = hwc->num_parents = i; + hw->clk.name = xasprintf(fmt, idx);; + hw->clk.ops = ops; + hw->clk.parent_names = parent_names; + hw->clk.num_parents = hwc->num_parents = i; hwc->cg = cg; - ret = clk_register(clk); + ret = bclk_register(&hw->clk); if (ret) { - pr_err("%s: Couldn't register %s: %d\n", __func__, clk->name, ret); + pr_err("%s: Couldn't register %s: %d\n", __func__, clk_hw_get_name(hw), ret); kfree(hwc); return NULL; } - return clk; + return &hw->clk; } static struct clk * __init create_one_cmux(struct clockgen *cg, int idx) @@ -499,7 +499,7 @@ static void __init create_one_pll(struct clockgen *cg, int idx) continue; } - pll->div[i].clk = clk; + pll->div[i].hw = clk_to_clk_hw(clk); } } @@ -551,7 +551,7 @@ static struct clk *clockgen_clk_get(struct of_phandle_args *clkspec, void *data) pll = &cg->pll[PLATFORM_PLL]; if (idx >= ARRAY_SIZE(pll->div)) goto bad_args; - clk = pll->div[idx].clk; + clk = clk_hw_to_clk(pll->div[idx].hw); break; case 5: if (idx != 0) diff --git a/drivers/clk/clk-stm32mp1.c b/drivers/clk/clk-stm32mp1.c index 2380bd0c21..7ba71b4592 100644 --- a/drivers/clk/clk-stm32mp1.c +++ b/drivers/clk/clk-stm32mp1.c @@ -285,7 +285,7 @@ static const struct clk_div_table ck_trace_div_table[] = { struct stm32_mmux { u8 nbr_clk; - struct clk *hws[MAX_MUX_CLK]; + struct clk_hw *hws[MAX_MUX_CLK]; }; struct stm32_clk_mmux { @@ -419,19 +419,19 @@ _clk_hw_register_mux(void __iomem *base, /* MP1 Gate clock with set & clear registers */ -static int mp1_gate_clk_enable(struct clk *clk) +static int mp1_gate_clk_enable(struct clk_hw *hw) { - if (!clk_gate_ops.is_enabled(clk)) - clk_gate_ops.enable(clk); + if (!clk_gate_ops.is_enabled(hw)) + clk_gate_ops.enable(hw); return 0; } -static void mp1_gate_clk_disable(struct clk *clk) +static void mp1_gate_clk_disable(struct clk_hw *hw) { - struct clk_gate *gate = to_clk_gate(clk); + struct clk_gate *gate = to_clk_gate(hw); - if (clk_gate_ops.is_enabled(clk)) { + if (clk_gate_ops.is_enabled(hw)) { writel(BIT(gate->shift), gate->reg + RCC_CLR); } } @@ -442,12 +442,12 @@ static const struct clk_ops mp1_gate_clk_ops = { .is_enabled = clk_gate_is_enabled, }; -static struct clk *_get_stm32_mux(void __iomem *base, +static struct clk_hw *_get_stm32_mux(void __iomem *base, const struct stm32_mux_cfg *cfg) { struct stm32_clk_mmux *mmux; struct clk_mux *mux; - struct clk *mux_hw; + struct clk_hw *mux_hw; if (cfg->mmux) { mmux = kzalloc(sizeof(*mmux), GFP_KERNEL); @@ -458,7 +458,7 @@ static struct clk *_get_stm32_mux(void __iomem *base, mmux->mux.shift = cfg->mux->shift; mmux->mux.width = cfg->mux->width; mmux->mmux = cfg->mmux; - mux_hw = &mmux->mux.clk; + mux_hw = &mmux->mux.hw; cfg->mmux->hws[cfg->mmux->nbr_clk++] = mux_hw; mux = &mmux->mux; } else { @@ -469,18 +469,18 @@ static struct clk *_get_stm32_mux(void __iomem *base, mux->reg = cfg->mux->reg_off + base; mux->shift = cfg->mux->shift; mux->width = cfg->mux->width; - mux_hw = &mux->clk; + mux_hw = &mux->hw; } if (cfg->ops) - mux->clk.ops = cfg->ops; + mux->hw.clk.ops = cfg->ops; else - mux->clk.ops = &clk_mux_ops; + mux->hw.clk.ops = &clk_mux_ops; return mux_hw; } -static struct clk *_get_stm32_div(void __iomem *base, +static struct clk_hw *_get_stm32_div(void __iomem *base, const struct stm32_div_cfg *cfg) { struct clk_divider *div; @@ -496,11 +496,11 @@ static struct clk *_get_stm32_div(void __iomem *base, div->table = cfg->div->table; if (cfg->ops) - div->clk.ops = cfg->ops; + div->hw.clk.ops = cfg->ops; else - div->clk.ops = &clk_divider_ops; + div->hw.clk.ops = &clk_divider_ops; - return &div->clk; + return &div->hw; } static struct clk_gate * @@ -535,9 +535,9 @@ _get_stm32_gate(void __iomem *base, } if (cfg->ops) - gate->clk.ops = cfg->ops; + gate->hw.clk.ops = cfg->ops; else - gate->clk.ops = &clk_gate_ops; + gate->hw.clk.ops = &clk_gate_ops; return gate; } @@ -558,13 +558,13 @@ clk_stm32_register_gate_ops(const char *name, return ERR_PTR(-ENOMEM); gate->parent = parent_name; - clk = &gate->clk; + clk = &gate->hw.clk; clk->name = name; clk->parent_names = &gate->parent; clk->num_parents = 1; clk->flags = flags; - ret = clk_register(clk); + ret = bclk_register(clk); if (ret) clk = ERR_PTR(ret); @@ -577,7 +577,7 @@ clk_stm32_register_composite(const char *name, const char * const *parent_names, const struct stm32_composite_cfg *cfg, unsigned long flags) { - struct clk *mux_hw, *div_hw, *gate_hw; + struct clk_hw *mux_hw, *div_hw, *gate_hw; struct clk_gate *gate; mux_hw = NULL; @@ -592,36 +592,36 @@ clk_stm32_register_composite(const char *name, const char * const *parent_names, if (cfg->gate) { gate = _get_stm32_gate(base, cfg->gate); - gate_hw = &gate->clk; + gate_hw = &gate->hw; } return clk_register_composite(name, parent_names, num_parents, - mux_hw, div_hw, gate_hw, flags); + &mux_hw->clk, &div_hw->clk, &gate_hw->clk, flags); } #define to_clk_mgate(_gate) container_of(_gate, struct stm32_clk_mgate, gate) -static int mp1_mgate_clk_enable(struct clk *clk) +static int mp1_mgate_clk_enable(struct clk_hw *hw) { - struct clk_gate *gate = to_clk_gate(clk); + struct clk_gate *gate = to_clk_gate(hw); struct stm32_clk_mgate *clk_mgate = to_clk_mgate(gate); clk_mgate->mgate->flag |= clk_mgate->mask; - mp1_gate_clk_enable(clk); + mp1_gate_clk_enable(hw); return 0; } -static void mp1_mgate_clk_disable(struct clk *clk) +static void mp1_mgate_clk_disable(struct clk_hw *hw) { - struct clk_gate *gate = to_clk_gate(clk); + struct clk_gate *gate = to_clk_gate(hw); struct stm32_clk_mgate *clk_mgate = to_clk_mgate(gate); clk_mgate->mgate->flag &= ~clk_mgate->mask; if (clk_mgate->mgate->flag == 0) - mp1_gate_clk_disable(clk); + mp1_gate_clk_disable(hw); } static const struct clk_ops mp1_mgate_clk_ops = { @@ -633,26 +633,26 @@ static const struct clk_ops mp1_mgate_clk_ops = { #define to_clk_mmux(_mux) container_of(_mux, struct stm32_clk_mmux, mux) -static int clk_mmux_get_parent(struct clk *clk) +static int clk_mmux_get_parent(struct clk_hw *hw) { - return clk_mux_ops.get_parent(clk); + return clk_mux_ops.get_parent(hw); } -static int clk_mmux_set_parent(struct clk *clk, u8 index) +static int clk_mmux_set_parent(struct clk_hw *hw, u8 index) { - struct clk_mux *mux = to_clk_mux(clk); + struct clk_mux *mux = to_clk_mux(hw); struct stm32_clk_mmux *clk_mmux = to_clk_mmux(mux); - struct clk *parent; + struct clk_hw *hwp; int ret, n; - ret = clk_mux_ops.set_parent(clk, index); + ret = clk_mux_ops.set_parent(hw, index); if (ret) return ret; - parent = clk_get_parent(clk); + hwp = clk_hw_get_parent(hw); for (n = 0; n < clk_mmux->mmux->nbr_clk; n++) - clk_set_parent(clk_mmux->mmux->hws[n], parent); + clk_hw_set_parent(clk_mmux->mmux->hws[n], hw); return 0; } @@ -691,8 +691,9 @@ static int __pll_is_enabled(struct clk *clk) #define TIMEOUT 5 -static int pll_enable(struct clk *clk) +static int pll_enable(struct clk_hw *hw) { + struct clk *clk = clk_hw_to_clk(hw); struct stm32_pll_obj *clk_elem = to_pll(clk); u32 reg; unsigned int timeout = TIMEOUT; @@ -722,8 +723,9 @@ unlock: return bit_status; } -static void pll_disable(struct clk *clk) +static void pll_disable(struct clk_hw *hw) { + struct clk *clk = clk_hw_to_clk(hw); struct stm32_pll_obj *clk_elem = to_pll(clk); u32 reg; @@ -744,9 +746,10 @@ static u32 pll_frac_val(struct clk *clk) return frac; } -static unsigned long pll_recalc_rate(struct clk *clk, +static unsigned long pll_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) { + struct clk *clk = clk_hw_to_clk(hw); struct stm32_pll_obj *clk_elem = to_pll(clk); u32 reg; u32 frac, divm, divn; @@ -769,8 +772,9 @@ static unsigned long pll_recalc_rate(struct clk *clk, return rate + rate_frac; } -static int pll_is_enabled(struct clk *clk) +static int pll_is_enabled(struct clk_hw *hw) { + struct clk *clk = clk_hw_to_clk(hw); int ret; ret = __pll_is_enabled(clk); @@ -810,7 +814,7 @@ static struct clk *clk_register_pll(const char *name, element->reg = reg; - err = clk_register(clk); + err = bclk_register(clk); if (err) { kfree(element); @@ -852,17 +856,19 @@ static unsigned long __bestmult(struct clk *clk, unsigned long rate, return mult; } -static long timer_ker_round_rate(struct clk *clk, unsigned long rate, +static long timer_ker_round_rate(struct clk_hw *hw, unsigned long rate, unsigned long *parent_rate) { + struct clk *clk = clk_hw_to_clk(hw); unsigned long factor = __bestmult(clk, rate, *parent_rate); return *parent_rate * factor; } -static int timer_ker_set_rate(struct clk *clk, unsigned long rate, +static int timer_ker_set_rate(struct clk_hw *hw, unsigned long rate, unsigned long parent_rate) { + struct clk *clk = clk_hw_to_clk(hw); struct timer_cker *tim_ker = to_timer_cker(clk); unsigned long factor = __bestmult(clk, rate, parent_rate); int ret = 0; @@ -883,10 +889,11 @@ static int timer_ker_set_rate(struct clk *clk, unsigned long rate, return ret; } -static unsigned long timer_ker_recalc_rate(struct clk *hw, +static unsigned long timer_ker_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) { - struct timer_cker *tim_ker = to_timer_cker(hw); + struct clk *clk = clk_hw_to_clk(hw); + struct timer_cker *tim_ker = to_timer_cker(clk); u32 prescaler, timpre; u32 mul; @@ -934,7 +941,7 @@ static struct clk *clk_register_cktim(const char *name, tim_ker->apbdiv = apbdiv; tim_ker->timpre = timpre; - err = clk_register(clk); + err = bclk_register(clk); if (err) { kfree(tim_ker); return ERR_PTR(err); diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index b04d44593b..ba726c342c 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -36,6 +36,7 @@ static void clk_parent_disable(struct clk *clk) int clk_enable(struct clk *clk) { + struct clk_hw *hw; int ret; if (!clk) @@ -44,13 +45,15 @@ int clk_enable(struct clk *clk) if (IS_ERR(clk)) return PTR_ERR(clk); + hw = clk_to_clk_hw(clk); + if (!clk->enable_count) { ret = clk_parent_enable(clk); if (ret) return ret; if (clk->ops->enable) { - ret = clk->ops->enable(clk); + ret = clk->ops->enable(hw); if (ret) { clk_parent_disable(clk); return ret; @@ -65,6 +68,8 @@ int clk_enable(struct clk *clk) void clk_disable(struct clk *clk) { + struct clk_hw *hw; + if (!clk) return; @@ -81,9 +86,11 @@ void clk_disable(struct clk *clk) clk->enable_count--; + hw = clk_to_clk_hw(clk); + if (!clk->enable_count) { if (clk->ops->disable) - clk->ops->disable(clk); + clk->ops->disable(hw); clk_parent_disable(clk); } @@ -91,6 +98,7 @@ void clk_disable(struct clk *clk) unsigned long clk_get_rate(struct clk *clk) { + struct clk_hw *hw; struct clk *parent; unsigned long parent_rate = 0; @@ -106,14 +114,22 @@ unsigned long clk_get_rate(struct clk *clk) if (!IS_ERR_OR_NULL(parent)) parent_rate = clk_get_rate(parent); + hw = clk_to_clk_hw(clk); + if (clk->ops->recalc_rate) - return clk->ops->recalc_rate(clk, parent_rate); + return clk->ops->recalc_rate(hw, parent_rate); return parent_rate; } +unsigned long clk_hw_get_rate(struct clk_hw *hw) +{ + return clk_get_rate(clk_hw_to_clk(hw)); +} + long clk_round_rate(struct clk *clk, unsigned long rate) { + struct clk_hw *hw; unsigned long parent_rate = 0; struct clk *parent; @@ -127,14 +143,22 @@ long clk_round_rate(struct clk *clk, unsigned long rate) if (parent) parent_rate = clk_get_rate(parent); + hw = clk_to_clk_hw(clk); + if (clk->ops->round_rate) - return clk->ops->round_rate(clk, rate, &parent_rate); + return clk->ops->round_rate(hw, rate, &parent_rate); return clk_get_rate(clk); } +long clk_hw_round_rate(struct clk_hw *hw, unsigned long rate) +{ + return clk_round_rate(&hw->clk, rate); +} + int clk_set_rate(struct clk *clk, unsigned long rate) { + struct clk_hw *hw; struct clk *parent; unsigned long parent_rate = 0; int ret; @@ -145,9 +169,18 @@ int clk_set_rate(struct clk *clk, unsigned long rate) if (IS_ERR(clk)) return PTR_ERR(clk); + if (clk_get_rate(clk) == clk_round_rate(clk, rate)) + return 0; + if (!clk->ops->set_rate) return -ENOSYS; + if (clk->flags & CLK_SET_RATE_UNGATE) { + ret = clk_enable(clk); + if (ret) + return ret; + } + parent = clk_get_parent(clk); if (parent) { parent_rate = clk_get_rate(parent); @@ -155,18 +188,29 @@ int clk_set_rate(struct clk *clk, unsigned long rate) if (clk->flags & CLK_OPS_PARENT_ENABLE) { ret = clk_enable(parent); if (ret) - return ret; + goto out; } } - ret = clk->ops->set_rate(clk, rate, parent_rate); + hw = clk_to_clk_hw(clk); + + ret = clk->ops->set_rate(hw, rate, parent_rate); if (parent && clk->flags & CLK_OPS_PARENT_ENABLE) clk_disable(parent); +out: + if (clk->flags & CLK_SET_RATE_UNGATE) + clk_disable(clk); + return ret; } +int clk_hw_set_rate(struct clk_hw *hw, unsigned long rate) +{ + return clk_set_rate(&hw->clk, rate); +} + struct clk *clk_lookup(const char *name) { struct clk *c; @@ -184,6 +228,7 @@ struct clk *clk_lookup(const char *name) int clk_set_parent(struct clk *clk, struct clk *newparent) { + struct clk_hw *hw; int i, ret; struct clk *curparent = clk_get_parent(clk); @@ -217,7 +262,9 @@ int clk_set_parent(struct clk *clk, struct clk *newparent) clk_enable(newparent); } - ret = clk->ops->set_parent(clk, i); + hw = clk_to_clk_hw(clk); + + ret = clk->ops->set_parent(hw, i); if (clk->flags & CLK_OPS_PARENT_ENABLE) { clk_disable(curparent); @@ -230,8 +277,14 @@ int clk_set_parent(struct clk *clk, struct clk *newparent) return ret; } +int clk_hw_set_parent(struct clk_hw *hw, struct clk_hw *newparent) +{ + return clk_set_parent(&hw->clk, &newparent->clk); +} + struct clk *clk_get_parent(struct clk *clk) { + struct clk_hw *hw; int idx; if (IS_ERR(clk)) @@ -240,11 +293,13 @@ struct clk *clk_get_parent(struct clk *clk) if (!clk->num_parents) return ERR_PTR(-ENODEV); + hw = clk_to_clk_hw(clk); + if (clk->num_parents != 1) { if (!clk->ops->get_parent) return ERR_PTR(-EINVAL); - idx = clk->ops->get_parent(clk); + idx = clk->ops->get_parent(hw); if (idx >= clk->num_parents) return ERR_PTR(-ENODEV); @@ -258,9 +313,76 @@ struct clk *clk_get_parent(struct clk *clk) return clk->parents[idx]; } -int clk_register(struct clk *clk) +struct clk_hw *clk_hw_get_parent(struct clk_hw *hw) +{ + struct clk *clk = clk_get_parent(clk_hw_to_clk(hw)); + + if (IS_ERR(clk)) + return ERR_CAST(clk); + + return clk_to_clk_hw(clk); +} + +/** + * clk_set_phase - adjust the phase shift of a clock signal + * @clk: clock signal source + * @degrees: number of degrees the signal is shifted + * + * Shifts the phase of a clock signal by the specified + * degrees. Returns 0 on success, -EERROR otherwise. + * + * This function makes no distinction about the input or reference + * signal that we adjust the clock signal phase against. For example + * phase locked-loop clock signal generators we may shift phase with + * respect to feedback clock signal input, but for other cases the + * clock phase may be shifted with respect to some other, unspecified + * signal. + * + * Additionally the concept of phase shift does not propagate through + * the clock tree hierarchy, which sets it apart from clock rates and + * clock accuracy. A parent clock phase attribute does not have an + * impact on the phase attribute of a child clock. + */ +int clk_set_phase(struct clk *clk, int degrees) { + if (!clk) + return 0; + + /* sanity check degrees */ + degrees %= 360; + if (degrees < 0) + degrees += 360; + + if (!clk->ops->set_phase) + return -EINVAL; + + return clk->ops->set_phase(clk_to_clk_hw(clk), degrees); +} + +/** + * clk_get_phase - return the phase shift of a clock signal + * @clk: clock signal source + * + * Returns the phase shift of a clock node in degrees, otherwise returns + * -EERROR. + */ +int clk_get_phase(struct clk *clk) +{ + int ret; + + if (!clk->ops->get_phase) + return 0; + + ret = clk->ops->get_phase(clk_to_clk_hw(clk)); + + return ret; +} + +int bclk_register(struct clk *clk) +{ + struct clk_hw *hw = clk_to_clk_hw(clk); struct clk *c; + int ret; list_for_each_entry(c, &clks, list) { if (!strcmp(c->name, clk->name)) { @@ -274,15 +396,64 @@ int clk_register(struct clk *clk) list_add_tail(&clk->list, &clks); + if (clk->ops->init) { + ret = clk->ops->init(hw); + if (ret) + goto out; + } + if (clk->flags & CLK_IS_CRITICAL) clk_enable(clk); return 0; +out: + list_del(&clk->list); + free(clk->parents); + + return ret; +} + +struct clk *clk_register(struct device_d *dev, struct clk_hw *hw) +{ + struct clk *clk; + const struct clk_init_data *init = hw->init; + char **parent_names; + int i, ret; + + if (!hw->init) + return ERR_PTR(-EINVAL); + + clk = clk_hw_to_clk(hw); + + memset(clk, 0, sizeof(*clk)); + + clk->name = xstrdup(init->name); + clk->ops = init->ops; + clk->num_parents = init->num_parents; + parent_names = xzalloc(init->num_parents * sizeof(char *)); + + for (i = 0; i < init->num_parents; i++) + parent_names[i] = xstrdup(init->parent_names[i]); + + clk->parent_names = (const char *const*)parent_names; + + clk->flags = init->flags; + + ret = bclk_register(clk); + if (ret) { + for (i = 0; i < init->num_parents; i++) + free(parent_names[i]); + free(parent_names); + return ERR_PTR(ret); + } + + return clk; } int clk_is_enabled(struct clk *clk) { int enabled; + struct clk_hw *hw = clk_to_clk_hw(clk); if (IS_ERR(clk)) return 0; @@ -291,7 +462,7 @@ int clk_is_enabled(struct clk *clk) /* * If we can ask a clk, do it */ - enabled = clk->ops->is_enabled(clk); + enabled = clk->ops->is_enabled(hw); } else { if (clk->ops->enable) { /* @@ -320,26 +491,35 @@ int clk_is_enabled(struct clk *clk) return clk_is_enabled(clk); } +int clk_hw_is_enabled(struct clk_hw *hw) +{ + return clk_is_enabled(&hw->clk); +} + /* * Generic struct clk_ops callbacks */ -int clk_is_enabled_always(struct clk *clk) +int clk_is_enabled_always(struct clk_hw *hw) { return 1; } -long clk_parent_round_rate(struct clk *clk, unsigned long rate, +long clk_parent_round_rate(struct clk_hw *hw, unsigned long rate, unsigned long *prate) { + struct clk *clk = clk_hw_to_clk(hw); + if (!(clk->flags & CLK_SET_RATE_PARENT)) return *prate; return clk_round_rate(clk_get_parent(clk), rate); } -int clk_parent_set_rate(struct clk *clk, unsigned long rate, +int clk_parent_set_rate(struct clk_hw *hw, unsigned long rate, unsigned long parent_rate) { + struct clk *clk = clk_hw_to_clk(hw); + if (!(clk->flags & CLK_SET_RATE_PARENT)) return 0; return clk_set_rate(clk_get_parent(clk), rate); @@ -663,8 +843,10 @@ int of_clk_init(struct device_node *root, const struct of_device_id *matches) static const char *clk_hw_stat(struct clk *clk) { + struct clk_hw *hw = clk_to_clk_hw(clk); + if (clk->ops->is_enabled) { - if (clk->ops->is_enabled(clk)) + if (clk->ops->is_enabled(hw)) return "enabled"; else return "disabled"; diff --git a/drivers/clk/imx/clk-composite-8m.c b/drivers/clk/imx/clk-composite-8m.c index 6c7f10a2c9..96fccc51d8 100644 --- a/drivers/clk/imx/clk-composite-8m.c +++ b/drivers/clk/imx/clk-composite-8m.c @@ -26,10 +26,11 @@ #define clk_div_mask(width) ((1 << (width)) - 1) -static unsigned long imx8m_clk_composite_divider_recalc_rate(struct clk *clk, +static unsigned long imx8m_clk_composite_divider_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) { - struct clk_divider *divider = container_of(clk, struct clk_divider, clk); + struct clk_divider *divider = container_of(hw, struct clk_divider, hw); + struct clk *clk = clk_hw_to_clk(hw); unsigned long prediv_rate; unsigned int prediv_value; unsigned int div_value; @@ -74,7 +75,7 @@ static int imx8m_clk_composite_compute_dividers(unsigned long rate, return ret; } -static long imx8m_clk_composite_divider_round_rate(struct clk *clk, +static long imx8m_clk_composite_divider_round_rate(struct clk_hw *hw, unsigned long rate, unsigned long *prate) { @@ -89,11 +90,11 @@ static long imx8m_clk_composite_divider_round_rate(struct clk *clk, } -static int imx8m_clk_composite_divider_set_rate(struct clk *clk, +static int imx8m_clk_composite_divider_set_rate(struct clk_hw *hw, unsigned long rate, unsigned long parent_rate) { - struct clk_divider *divider = container_of(clk, struct clk_divider, clk); + struct clk_divider *divider = container_of(hw, struct clk_divider, hw); int prediv_value; int div_value; int ret; @@ -114,14 +115,14 @@ static int imx8m_clk_composite_divider_set_rate(struct clk *clk, return ret; } -static int imx8m_clk_composite_mux_get_parent(struct clk *clk) +static int imx8m_clk_composite_mux_get_parent(struct clk_hw *hw) { - return clk_mux_ops.get_parent(clk); + return clk_mux_ops.get_parent(hw); } -static int imx8m_clk_composite_mux_set_parent(struct clk *clk, u8 index) +static int imx8m_clk_composite_mux_set_parent(struct clk_hw *hw, u8 index) { - struct clk_mux *m = container_of(clk, struct clk_mux, clk); + struct clk_mux *m = container_of(hw, struct clk_mux, hw); u32 val; val = readl(m->reg); @@ -161,7 +162,6 @@ struct clk *imx8m_clk_composite_flags(const char *name, struct clk_divider *div = NULL; struct clk_gate *gate = NULL; struct clk_mux *mux = NULL; - const struct clk_ops *divider_ops; const struct clk_ops *mux_ops; mux = kzalloc(sizeof(*mux), GFP_KERNEL); @@ -171,7 +171,7 @@ struct clk *imx8m_clk_composite_flags(const char *name, mux->reg = reg; mux->shift = PCG_PCS_SHIFT; mux->width = PCG_PCS_WIDTH; - mux->clk.ops = &clk_mux_ops; + mux->hw.clk.ops = &clk_mux_ops; div = kzalloc(sizeof(*div), GFP_KERNEL); if (!div) @@ -181,20 +181,19 @@ struct clk *imx8m_clk_composite_flags(const char *name, if (composite_flags & IMX_COMPOSITE_CORE) { div->shift = PCG_DIV_SHIFT; div->width = PCG_CORE_DIV_WIDTH; - divider_ops = &clk_divider_ops; + div->hw.clk.ops = &clk_divider_ops; mux_ops = &imx8m_clk_composite_mux_ops; } else if (composite_flags & IMX_COMPOSITE_BUS) { div->shift = PCG_PREDIV_SHIFT; div->width = PCG_PREDIV_WIDTH; - divider_ops = &imx8m_clk_composite_divider_ops; + div->hw.clk.ops = &imx8m_clk_composite_divider_ops; mux_ops = &imx8m_clk_composite_mux_ops; } else { div->shift = PCG_PREDIV_SHIFT; div->width = PCG_PREDIV_WIDTH; - divider_ops = &imx8m_clk_composite_divider_ops; + div->hw.clk.ops = &imx8m_clk_composite_divider_ops; mux_ops = &clk_mux_ops; } - div->clk.ops = divider_ops; gate = kzalloc(sizeof(*gate), GFP_KERNEL); if (!gate) @@ -202,10 +201,10 @@ struct clk *imx8m_clk_composite_flags(const char *name, gate->reg = reg; gate->shift = PCG_CGC_SHIFT; - gate->clk.ops = &clk_gate_ops; + gate->hw.clk.ops = &clk_gate_ops; comp = clk_register_composite(name, parent_names, num_parents, - &mux->clk, &div->clk, &gate->clk, flags); + &mux->hw.clk, &div->hw.clk, &gate->hw.clk, flags); if (IS_ERR(comp)) goto fail; diff --git a/drivers/clk/imx/clk-cpu.c b/drivers/clk/imx/clk-cpu.c index f8d54ddba3..0ca5dd63c5 100644 --- a/drivers/clk/imx/clk-cpu.c +++ b/drivers/clk/imx/clk-cpu.c @@ -16,38 +16,38 @@ #include "clk.h" struct clk_cpu { - struct clk clk; + struct clk_hw hw; struct clk *div; struct clk *mux; struct clk *pll; struct clk *step; }; -static inline struct clk_cpu *to_clk_cpu(struct clk *clk) +static inline struct clk_cpu *to_clk_cpu(struct clk_hw *hw) { - return container_of(clk, struct clk_cpu, clk); + return container_of(hw, struct clk_cpu, hw); } -static unsigned long clk_cpu_recalc_rate(struct clk *clk, +static unsigned long clk_cpu_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) { - struct clk_cpu *cpu = to_clk_cpu(clk); + struct clk_cpu *cpu = to_clk_cpu(hw); return clk_get_rate(cpu->div); } -static long clk_cpu_round_rate(struct clk *clk, unsigned long rate, +static long clk_cpu_round_rate(struct clk_hw *hw, unsigned long rate, unsigned long *prate) { - struct clk_cpu *cpu = to_clk_cpu(clk); + struct clk_cpu *cpu = to_clk_cpu(hw); return clk_round_rate(cpu->pll, rate); } -static int clk_cpu_set_rate(struct clk *clk, unsigned long rate, +static int clk_cpu_set_rate(struct clk_hw *hw, unsigned long rate, unsigned long parent_rate) { - struct clk_cpu *cpu = to_clk_cpu(clk); + struct clk_cpu *cpu = to_clk_cpu(hw); int ret; /* switch to PLL bypass clock */ @@ -98,17 +98,17 @@ struct clk *imx_clk_cpu(const char *name, const char *parent_name, cpu->pll = pll; cpu->step = step; - cpu->clk.name = name; - cpu->clk.ops = &clk_cpu_ops; - cpu->clk.flags = CLK_IS_CRITICAL; - cpu->clk.parent_names = &icpu->parent_name; - cpu->clk.num_parents = 1; + cpu->hw.clk.name = name; + cpu->hw.clk.ops = &clk_cpu_ops; + cpu->hw.clk.flags = CLK_IS_CRITICAL; + cpu->hw.clk.parent_names = &icpu->parent_name; + cpu->hw.clk.num_parents = 1; - ret = clk_register(&cpu->clk); + ret = bclk_register(&cpu->hw.clk); if (ret) { free(cpu); return NULL; } - return &cpu->clk; + return &cpu->hw.clk; } diff --git a/drivers/clk/imx/clk-frac-pll.c b/drivers/clk/imx/clk-frac-pll.c index 48866eadf0..d3fc760717 100644 --- a/drivers/clk/imx/clk-frac-pll.c +++ b/drivers/clk/imx/clk-frac-pll.c @@ -26,12 +26,12 @@ #define PLL_FRAC_DENOM 0x1000000 struct clk_frac_pll { - struct clk clk; + struct clk_hw hw; void __iomem *base; const char *parent; }; -#define to_clk_frac_pll(_clk) container_of(_clk, struct clk_frac_pll, clk) +#define to_clk_frac_pll(_hw) container_of(_hw, struct clk_frac_pll, hw) static int clk_wait_lock(struct clk_frac_pll *pll) { @@ -63,9 +63,9 @@ static int clk_wait_ack(struct clk_frac_pll *pll) return readl(pll->base) & PLL_NEWDIV_ACK ? 0 : ETIMEDOUT; } -static int clk_pll_enable(struct clk *clk) +static int clk_pll_enable(struct clk_hw *hw) { - struct clk_frac_pll *pll = to_clk_frac_pll(clk); + struct clk_frac_pll *pll = to_clk_frac_pll(hw); u32 val; val = readl(pll->base + PLL_CFG0); @@ -75,9 +75,9 @@ static int clk_pll_enable(struct clk *clk) return clk_wait_lock(pll); } -static void clk_pll_disable(struct clk *clk) +static void clk_pll_disable(struct clk_hw *hw) { - struct clk_frac_pll *pll = to_clk_frac_pll(clk); + struct clk_frac_pll *pll = to_clk_frac_pll(hw); u32 val; val = readl(pll->base + PLL_CFG0); @@ -85,19 +85,19 @@ static void clk_pll_disable(struct clk *clk) writel(val, pll->base + PLL_CFG0); } -static int clk_pll_is_enabled(struct clk *clk) +static int clk_pll_is_enabled(struct clk_hw *hw) { - struct clk_frac_pll *pll = to_clk_frac_pll(clk); + struct clk_frac_pll *pll = to_clk_frac_pll(hw); u32 val; val = readl(pll->base + PLL_CFG0); return (val & (1 << PLL_PD)) ? 0 : 1; } -static unsigned long clk_pll_recalc_rate(struct clk *clk, +static unsigned long clk_pll_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) { - struct clk_frac_pll *pll = to_clk_frac_pll(clk); + struct clk_frac_pll *pll = to_clk_frac_pll(hw); u32 val, divff, divfi, divq; u64 temp64; @@ -115,7 +115,7 @@ static unsigned long clk_pll_recalc_rate(struct clk *clk, return parent_rate * 8 * (divfi + 1) / divq + (unsigned long)temp64; } -static long clk_pll_round_rate(struct clk *clk, unsigned long rate, +static long clk_pll_round_rate(struct clk_hw *hw, unsigned long rate, unsigned long *prate) { u32 divff, divfi; @@ -144,10 +144,10 @@ static long clk_pll_round_rate(struct clk *clk, unsigned long rate, * pllout = parent_rate * 8 / 2 * DIVF_VAL; * where DIVF_VAL = 1 + DIVFI + DIVFF / 2^24. */ -static int clk_pll_set_rate(struct clk *clk, unsigned long rate, +static int clk_pll_set_rate(struct clk_hw *hw, unsigned long rate, unsigned long parent_rate) { - struct clk_frac_pll *pll = to_clk_frac_pll(clk); + struct clk_frac_pll *pll = to_clk_frac_pll(hw); u32 val, divfi, divff; u64 temp64; int ret; @@ -205,16 +205,16 @@ struct clk *imx_clk_frac_pll(const char *name, const char *parent, pll->base = base; pll->parent = parent; - pll->clk.ops = &clk_frac_pll_ops; - pll->clk.name = name; - pll->clk.parent_names = &pll->parent; - pll->clk.num_parents = 1; + pll->hw.clk.ops = &clk_frac_pll_ops; + pll->hw.clk.name = name; + pll->hw.clk.parent_names = &pll->parent; + pll->hw.clk.num_parents = 1; - ret = clk_register(&pll->clk); + ret = bclk_register(&pll->hw.clk); if (ret) { free(pll); return ERR_PTR(ret); } - return &pll->clk; + return &pll->hw.clk; } diff --git a/drivers/clk/imx/clk-gate-exclusive.c b/drivers/clk/imx/clk-gate-exclusive.c index 4bf4de8bd3..473249a356 100644 --- a/drivers/clk/imx/clk-gate-exclusive.c +++ b/drivers/clk/imx/clk-gate-exclusive.c @@ -24,17 +24,21 @@ * register is mutually exclusive to this gate clock. */ struct clk_gate_exclusive { - struct clk clk; + struct clk_hw hw; void __iomem *reg; int shift; const char *parent; u32 exclusive_mask; }; -static int clk_gate_exclusive_enable(struct clk *clk) +static inline struct clk_gate_exclusive *to_clk_gate_exclusive(struct clk_hw *hw) { - struct clk_gate_exclusive *exgate = container_of(clk, - struct clk_gate_exclusive, clk); + return container_of(hw, struct clk_gate_exclusive, hw); +} + +static int clk_gate_exclusive_enable(struct clk_hw *hw) +{ + struct clk_gate_exclusive *exgate = to_clk_gate_exclusive(hw); u32 val = readl(exgate->reg); if (val & exgate->exclusive_mask) @@ -47,10 +51,9 @@ static int clk_gate_exclusive_enable(struct clk *clk) return 0; } -static void clk_gate_exclusive_disable(struct clk *clk) +static void clk_gate_exclusive_disable(struct clk_hw *hw) { - struct clk_gate_exclusive *exgate = container_of(clk, - struct clk_gate_exclusive, clk); + struct clk_gate_exclusive *exgate = to_clk_gate_exclusive(hw); u32 val = readl(exgate->reg); val &= ~(1 << exgate->shift); @@ -58,10 +61,9 @@ static void clk_gate_exclusive_disable(struct clk *clk) writel(val, exgate->reg); } -static int clk_gate_exclusive_is_enabled(struct clk *clk) +static int clk_gate_exclusive_is_enabled(struct clk_hw *hw) { - struct clk_gate_exclusive *exgate = container_of(clk, - struct clk_gate_exclusive, clk); + struct clk_gate_exclusive *exgate = to_clk_gate_exclusive(hw); return readl(exgate->reg) & (1 << exgate->shift); } @@ -80,21 +82,21 @@ struct clk *imx_clk_gate_exclusive(const char *name, const char *parent, exgate = xzalloc(sizeof(*exgate)); exgate->parent = parent; - exgate->clk.name = name; - exgate->clk.ops = &clk_gate_exclusive_ops; - exgate->clk.flags = CLK_SET_RATE_PARENT; - exgate->clk.parent_names = &exgate->parent; - exgate->clk.num_parents = 1; + exgate->hw.clk.name = name; + exgate->hw.clk.ops = &clk_gate_exclusive_ops; + exgate->hw.clk.flags = CLK_SET_RATE_PARENT; + exgate->hw.clk.parent_names = &exgate->parent; + exgate->hw.clk.num_parents = 1; exgate->reg = reg; exgate->shift = shift; exgate->exclusive_mask = exclusive_mask; - ret = clk_register(&exgate->clk); + ret = bclk_register(&exgate->hw.clk); if (ret) { free(exgate); return ERR_PTR(ret); } - return &exgate->clk; + return &exgate->hw.clk; } diff --git a/drivers/clk/imx/clk-gate2.c b/drivers/clk/imx/clk-gate2.c index 88eaae8db3..af83e93b12 100644 --- a/drivers/clk/imx/clk-gate2.c +++ b/drivers/clk/imx/clk-gate2.c @@ -13,25 +13,27 @@ struct clk_gate2 { - struct clk clk; + struct clk_hw hw; void __iomem *reg; int shift; u8 cgr_val; const char *parent; -#define CLK_GATE_INVERTED (1 << 0) unsigned flags; }; -#define to_clk_gate2(_clk) container_of(_clk, struct clk_gate2, clk) +static inline struct clk_gate2 *to_clk_gate2(struct clk_hw *hw) +{ + return container_of(hw, struct clk_gate2, hw); +} -static int clk_gate2_enable(struct clk *clk) +static int clk_gate2_enable(struct clk_hw *hw) { - struct clk_gate2 *g = to_clk_gate2(clk); + struct clk_gate2 *g = to_clk_gate2(hw); u32 val; val = readl(g->reg); - if (g->flags & CLK_GATE_INVERTED) + if (g->flags & CLK_GATE_SET_TO_DISABLE) val &= ~(3 << g->shift); else val |= g->cgr_val << g->shift; @@ -41,14 +43,14 @@ static int clk_gate2_enable(struct clk *clk) return 0; } -static void clk_gate2_disable(struct clk *clk) +static void clk_gate2_disable(struct clk_hw *hw) { - struct clk_gate2 *g = to_clk_gate2(clk); + struct clk_gate2 *g = to_clk_gate2(hw); u32 val; val = readl(g->reg); - if (g->flags & CLK_GATE_INVERTED) + if (g->flags & CLK_GATE_SET_TO_DISABLE) val |= 3 << g->shift; else val &= ~(3 << g->shift); @@ -56,17 +58,17 @@ static void clk_gate2_disable(struct clk *clk) writel(val, g->reg); } -static int clk_gate2_is_enabled(struct clk *clk) +static int clk_gate2_is_enabled(struct clk_hw *hw) { - struct clk_gate2 *g = to_clk_gate2(clk); + struct clk_gate2 *g = to_clk_gate2(hw); u32 val; val = readl(g->reg); if (val & (1 << g->shift)) - return g->flags & CLK_GATE_INVERTED ? 0 : 1; + return g->flags & CLK_GATE_SET_TO_DISABLE ? 0 : 1; else - return g->flags & CLK_GATE_INVERTED ? 1 : 0; + return g->flags & CLK_GATE_SET_TO_DISABLE ? 1 : 0; } static struct clk_ops clk_gate2_ops = { @@ -87,13 +89,13 @@ static struct clk *clk_gate2_alloc(const char *name, const char *parent, g->reg = reg; g->cgr_val = cgr_val; g->shift = shift; - g->clk.ops = &clk_gate2_ops; - g->clk.name = name; - g->clk.parent_names = &g->parent; - g->clk.num_parents = 1; - g->clk.flags = CLK_SET_RATE_PARENT | flags; + g->hw.clk.ops = &clk_gate2_ops; + g->hw.clk.name = name; + g->hw.clk.parent_names = &g->parent; + g->hw.clk.num_parents = 1; + g->hw.clk.flags = CLK_SET_RATE_PARENT | flags; - return &g->clk; + return &g->hw.clk; } struct clk *clk_gate2(const char *name, const char *parent, void __iomem *reg, @@ -104,9 +106,10 @@ struct clk *clk_gate2(const char *name, const char *parent, void __iomem *reg, g = clk_gate2_alloc(name , parent, reg, shift, cgr_val, flags); - ret = clk_register(g); + ret = bclk_register(g); if (ret) { - free(to_clk_gate2(g)); + struct clk_hw *hw = clk_to_clk_hw(g); + free(to_clk_gate2(hw)); return ERR_PTR(ret); } diff --git a/drivers/clk/imx/clk-imx6ul.c b/drivers/clk/imx/clk-imx6ul.c index 6668146860..af5d582ffc 100644 --- a/drivers/clk/imx/clk-imx6ul.c +++ b/drivers/clk/imx/clk-imx6ul.c @@ -98,6 +98,7 @@ static int imx6_ccm_probe(struct device_d *dev) void __iomem *base, *anatop_base, *ccm_base; int i; struct device_node *ccm_node = dev->device_node; + struct clk_hw *hw; anatop_base = IOMEM(MX6_ANATOP_BASE_ADDR); iores = dev_request_mem_resource(dev, 0); @@ -445,7 +446,8 @@ static int imx6_ccm_probe(struct device_d *dev) clks[IMX6UL_CLK_PLL3_PFD2]); /* Disable GPMI_IO clk before reparenting to avoid glitches */ - clks[IMX6UL_CLK_GPMI_IO]->ops->disable(clks[IMX6UL_CLK_GPMI_IO]); + hw = clk_to_clk_hw(clks[IMX6UL_CLK_GPMI_IO]); + clks[IMX6UL_CLK_GPMI_IO]->ops->disable(hw); clk_set_parent(clks[IMX6UL_CLK_ENFC_SEL], clks[IMX6UL_CLK_PLL2_PFD2]); diff --git a/drivers/clk/imx/clk-pfd.c b/drivers/clk/imx/clk-pfd.c index a7ca664524..d16e39f85c 100644 --- a/drivers/clk/imx/clk-pfd.c +++ b/drivers/clk/imx/clk-pfd.c @@ -27,37 +27,37 @@ * register has SET, CLR and TOG registers at offset 0x4 0x8 and 0xc. */ struct clk_pfd { - struct clk clk; + struct clk_hw hw; void __iomem *reg; u8 idx; const char *parent; }; -#define to_clk_pfd(_clk) container_of(_clk, struct clk_pfd, clk) +#define to_clk_pfd(_hw) container_of(_hw, struct clk_pfd, hw) #define SET 0x4 #define CLR 0x8 #define OTG 0xc -static int clk_pfd_enable(struct clk *clk) +static int clk_pfd_enable(struct clk_hw *hw) { - struct clk_pfd *pfd = to_clk_pfd(clk); + struct clk_pfd *pfd = to_clk_pfd(hw); writel(1 << ((pfd->idx + 1) * 8 - 1), pfd->reg + CLR); return 0; } -static void clk_pfd_disable(struct clk *clk) +static void clk_pfd_disable(struct clk_hw *hw) { - struct clk_pfd *pfd = to_clk_pfd(clk); + struct clk_pfd *pfd = to_clk_pfd(hw); writel(1 << ((pfd->idx + 1) * 8 - 1), pfd->reg + SET); } -static unsigned long clk_pfd_recalc_rate(struct clk *clk, +static unsigned long clk_pfd_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) { - struct clk_pfd *pfd = to_clk_pfd(clk); + struct clk_pfd *pfd = to_clk_pfd(hw); u64 tmp = parent_rate; u8 frac = (readl(pfd->reg) >> (pfd->idx * 8)) & 0x3f; @@ -67,7 +67,7 @@ static unsigned long clk_pfd_recalc_rate(struct clk *clk, return tmp; } -static long clk_pfd_round_rate(struct clk *clk, unsigned long rate, +static long clk_pfd_round_rate(struct clk_hw *hw, unsigned long rate, unsigned long *prate) { u64 tmp = *prate; @@ -87,10 +87,10 @@ static long clk_pfd_round_rate(struct clk *clk, unsigned long rate, return tmp; } -static int clk_pfd_set_rate(struct clk *clk, unsigned long rate, +static int clk_pfd_set_rate(struct clk_hw *hw, unsigned long rate, unsigned long parent_rate) { - struct clk_pfd *pfd = to_clk_pfd(clk); + struct clk_pfd *pfd = to_clk_pfd(hw); u64 tmp = parent_rate; u8 frac; @@ -127,16 +127,16 @@ struct clk *imx_clk_pfd(const char *name, const char *parent, pfd->reg = reg; pfd->idx = idx; pfd->parent = parent; - pfd->clk.name = name; - pfd->clk.ops = &clk_pfd_ops; - pfd->clk.parent_names = &pfd->parent; - pfd->clk.num_parents = 1; + pfd->hw.clk.name = name; + pfd->hw.clk.ops = &clk_pfd_ops; + pfd->hw.clk.parent_names = &pfd->parent; + pfd->hw.clk.num_parents = 1; - ret = clk_register(&pfd->clk); + ret = bclk_register(&pfd->hw.clk); if (ret) { free(pfd); return ERR_PTR(ret); } - return &pfd->clk; + return &pfd->hw.clk; } diff --git a/drivers/clk/imx/clk-pll14xx.c b/drivers/clk/imx/clk-pll14xx.c index 3fd5a49ee7..bc837bd838 100644 --- a/drivers/clk/imx/clk-pll14xx.c +++ b/drivers/clk/imx/clk-pll14xx.c @@ -37,7 +37,7 @@ #define LOCK_TIMEOUT_US 10000 struct clk_pll14xx { - struct clk clk; + struct clk_hw hw; void __iomem *base; enum imx_pll14xx_type type; const struct imx_pll14xx_rate_table *rate_table; @@ -45,7 +45,7 @@ struct clk_pll14xx { const char *parent; }; -#define to_clk_pll14xx(clk) container_of(clk, struct clk_pll14xx, clk) +#define to_clk_pll14xx(_hw) container_of(_hw, struct clk_pll14xx, hw) static const struct imx_pll14xx_rate_table imx_pll1416x_tbl[] = { PLL_1416X_RATE(1800000000U, 225, 3, 0), @@ -92,10 +92,10 @@ static const struct imx_pll14xx_rate_table *imx_get_pll_settings( return NULL; } -static long clk_pll14xx_round_rate(struct clk *clk, unsigned long rate, +static long clk_pll14xx_round_rate(struct clk_hw *hw, unsigned long rate, unsigned long *prate) { - struct clk_pll14xx *pll = to_clk_pll14xx(clk); + struct clk_pll14xx *pll = to_clk_pll14xx(hw); const struct imx_pll14xx_rate_table *rate_table = pll->rate_table; int i; @@ -108,10 +108,10 @@ static long clk_pll14xx_round_rate(struct clk *clk, unsigned long rate, return rate_table[i - 1].rate; } -static unsigned long clk_pll1416x_recalc_rate(struct clk *clk, +static unsigned long clk_pll1416x_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) { - struct clk_pll14xx *pll = to_clk_pll14xx(clk); + struct clk_pll14xx *pll = to_clk_pll14xx(hw); u32 mdiv, pdiv, sdiv, pll_div; u64 fvco = parent_rate; @@ -126,10 +126,10 @@ static unsigned long clk_pll1416x_recalc_rate(struct clk *clk, return fvco; } -static unsigned long clk_pll1443x_recalc_rate(struct clk *clk, +static unsigned long clk_pll1443x_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) { - struct clk_pll14xx *pll = to_clk_pll14xx(clk); + struct clk_pll14xx *pll = to_clk_pll14xx(hw); u32 mdiv, pdiv, sdiv, pll_div_ctl0, pll_div_ctl1; short int kdiv; u64 fvco = parent_rate; @@ -169,10 +169,10 @@ static int clk_pll14xx_wait_lock(struct clk_pll14xx *pll) LOCK_TIMEOUT_US); } -static int clk_pll1416x_set_rate(struct clk *clk, unsigned long drate, +static int clk_pll1416x_set_rate(struct clk_hw *hw, unsigned long drate, unsigned long prate) { - struct clk_pll14xx *pll = to_clk_pll14xx(clk); + struct clk_pll14xx *pll = to_clk_pll14xx(hw); const struct imx_pll14xx_rate_table *rate; u32 tmp, div_val; int ret; @@ -180,7 +180,7 @@ static int clk_pll1416x_set_rate(struct clk *clk, unsigned long drate, rate = imx_get_pll_settings(pll, drate); if (!rate) { pr_err("%s: Invalid rate : %lu for pll clk %s\n", __func__, - drate, clk->name); + drate, hw->clk.name); return -EINVAL; } @@ -239,7 +239,7 @@ int clk_pll1416x_early_set_rate(void __iomem *base, unsigned long drate, unsigned long prate) { struct clk_pll14xx pll = { - .clk = { + .hw.clk = { .name = "pll1416x", }, .base = base, @@ -247,13 +247,14 @@ int clk_pll1416x_early_set_rate(void __iomem *base, unsigned long drate, .rate_count = ARRAY_SIZE(imx_pll1416x_tbl), }; - return clk_pll1416x_set_rate(&pll.clk, drate, prate); + return clk_pll1416x_set_rate(&pll.hw, drate, prate); } -static int clk_pll1443x_set_rate(struct clk *clk, unsigned long drate, +static int clk_pll1443x_set_rate(struct clk_hw *hw, unsigned long drate, unsigned long prate) { - struct clk_pll14xx *pll = to_clk_pll14xx(clk); + struct clk_pll14xx *pll = to_clk_pll14xx(hw); + struct clk *clk = clk_hw_to_clk(hw); const struct imx_pll14xx_rate_table *rate; u32 tmp, div_val; int ret; @@ -316,9 +317,9 @@ static int clk_pll1443x_set_rate(struct clk *clk, unsigned long drate, return 0; } -static int clk_pll14xx_prepare(struct clk *clk) +static int clk_pll14xx_prepare(struct clk_hw *hw) { - struct clk_pll14xx *pll = to_clk_pll14xx(clk); + struct clk_pll14xx *pll = to_clk_pll14xx(hw); u32 val; int ret; @@ -344,9 +345,9 @@ static int clk_pll14xx_prepare(struct clk *clk) return 0; } -static int clk_pll14xx_is_prepared(struct clk *clk) +static int clk_pll14xx_is_prepared(struct clk_hw *hw) { - struct clk_pll14xx *pll = to_clk_pll14xx(clk); + struct clk_pll14xx *pll = to_clk_pll14xx(hw); u32 val; val = readl(pll->base + GNRL_CTL); @@ -354,9 +355,9 @@ static int clk_pll14xx_is_prepared(struct clk *clk) return (val & RST_MASK) ? 1 : 0; } -static void clk_pll14xx_unprepare(struct clk *clk) +static void clk_pll14xx_unprepare(struct clk_hw *hw) { - struct clk_pll14xx *pll = to_clk_pll14xx(clk); + struct clk_pll14xx *pll = to_clk_pll14xx(hw); u32 val; /* @@ -403,7 +404,7 @@ struct clk *imx_clk_pll14xx(const char *name, const char *parent_name, if (!pll) return ERR_PTR(-ENOMEM); - clk = &pll->clk; + clk = &pll->hw.clk; pll->parent = parent_name; clk->name = name; @@ -435,7 +436,7 @@ struct clk *imx_clk_pll14xx(const char *name, const char *parent_name, val &= ~BYPASS_MASK; writel(val, pll->base + GNRL_CTL); - ret = clk_register(clk); + ret = bclk_register(clk); if (ret) { free(pll); return ERR_PTR(ret); diff --git a/drivers/clk/imx/clk-pllv1.c b/drivers/clk/imx/clk-pllv1.c index 36192bb211..62afa2b6b2 100644 --- a/drivers/clk/imx/clk-pllv1.c +++ b/drivers/clk/imx/clk-pllv1.c @@ -17,7 +17,7 @@ #define MFN_MASK (MFN_SIGN - 1) struct clk_pllv1 { - struct clk clk; + struct clk_hw hw; void __iomem *reg; const char *parent; }; @@ -27,10 +27,10 @@ static inline bool mfn_is_negative(unsigned int mfn) return mfn & MFN_SIGN; } -static unsigned long clk_pllv1_recalc_rate(struct clk *clk, +static unsigned long clk_pllv1_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) { - struct clk_pllv1 *pll = container_of(clk, struct clk_pllv1, clk); + struct clk_pllv1 *pll = container_of(hw, struct clk_pllv1, hw); unsigned long long ll; int mfn_abs; unsigned int mfi, mfn, mfd, pd; @@ -79,16 +79,16 @@ struct clk *imx_clk_pllv1(const char *name, const char *parent, pll->parent = parent; pll->reg = base; - pll->clk.ops = &clk_pllv1_ops; - pll->clk.name = name; - pll->clk.parent_names = &pll->parent; - pll->clk.num_parents = 1; + pll->hw.clk.ops = &clk_pllv1_ops; + pll->hw.clk.name = name; + pll->hw.clk.parent_names = &pll->parent; + pll->hw.clk.num_parents = 1; - ret = clk_register(&pll->clk); + ret = bclk_register(&pll->hw.clk); if (ret) { free(pll); return ERR_PTR(ret); } - return &pll->clk; + return &pll->hw.clk; } diff --git a/drivers/clk/imx/clk-pllv2.c b/drivers/clk/imx/clk-pllv2.c index 6af2d71352..d997e465d5 100644 --- a/drivers/clk/imx/clk-pllv2.c +++ b/drivers/clk/imx/clk-pllv2.c @@ -70,7 +70,7 @@ #define MAX_DPLL_WAIT_TRIES 1000 /* 1000 * udelay(1) = 1ms */ struct clk_pllv2 { - struct clk clk; + struct clk_hw hw; void __iomem *reg; const char *parent; }; @@ -110,12 +110,12 @@ static unsigned long __clk_pllv2_recalc_rate(unsigned long parent_rate, return temp; } -static unsigned long clk_pllv2_recalc_rate(struct clk *clk, +static unsigned long clk_pllv2_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) { u32 dp_op, dp_mfd, dp_mfn, dp_ctl; void __iomem *pllbase; - struct clk_pllv2 *pll = container_of(clk, struct clk_pllv2, clk); + struct clk_pllv2 *pll = container_of(hw, struct clk_pllv2, hw); pllbase = pll->reg; @@ -156,10 +156,10 @@ static int __clk_pllv2_set_rate(unsigned long rate, unsigned long parent_rate, return 0; } -static int clk_pllv2_set_rate(struct clk *clk, unsigned long rate, +static int clk_pllv2_set_rate(struct clk_hw *hw, unsigned long rate, unsigned long parent_rate) { - struct clk_pllv2 *pll = container_of(clk, struct clk_pllv2, clk); + struct clk_pllv2 *pll = container_of(hw, struct clk_pllv2, hw); void __iomem *pllbase; u32 dp_ctl, dp_op, dp_mfd, dp_mfn; int ret; @@ -181,7 +181,7 @@ static int clk_pllv2_set_rate(struct clk *clk, unsigned long rate, return 0; } -static long clk_pllv2_round_rate(struct clk *clk, unsigned long rate, +static long clk_pllv2_round_rate(struct clk_hw *hw, unsigned long rate, unsigned long *prate) { u32 dp_op, dp_mfd, dp_mfn; @@ -205,16 +205,16 @@ struct clk *imx_clk_pllv2(const char *name, const char *parent, pll->parent = parent; pll->reg = base; - pll->clk.ops = &clk_pllv2_ops; - pll->clk.name = name; - pll->clk.parent_names = &pll->parent; - pll->clk.num_parents = 1; + pll->hw.clk.ops = &clk_pllv2_ops; + pll->hw.clk.name = name; + pll->hw.clk.parent_names = &pll->parent; + pll->hw.clk.num_parents = 1; - ret = clk_register(&pll->clk); + ret = bclk_register(&pll->hw.clk); if (ret) { free(pll); return ERR_PTR(ret); } - return &pll->clk; + return &pll->hw.clk; } diff --git a/drivers/clk/imx/clk-pllv3.c b/drivers/clk/imx/clk-pllv3.c index 51e620a040..cb1d65058f 100644 --- a/drivers/clk/imx/clk-pllv3.c +++ b/drivers/clk/imx/clk-pllv3.c @@ -25,7 +25,7 @@ #define IMX7_ENET_PLL_POWER (0x1 << 5) struct clk_pllv3 { - struct clk clk; + struct clk_hw hw; void __iomem *base; bool powerup_set; u32 div_mask; @@ -35,11 +35,11 @@ struct clk_pllv3 { u32 power_bit; }; -#define to_clk_pllv3(_clk) container_of(_clk, struct clk_pllv3, clk) +#define to_clk_pllv3(_hw) container_of(_hw, struct clk_pllv3, hw) -static int clk_pllv3_enable(struct clk *clk) +static int clk_pllv3_enable(struct clk_hw *hw) { - struct clk_pllv3 *pll = to_clk_pllv3(clk); + struct clk_pllv3 *pll = to_clk_pllv3(hw); u32 val; int timeout = 10000; @@ -66,9 +66,9 @@ static int clk_pllv3_enable(struct clk *clk) return 0; } -static void clk_pllv3_disable(struct clk *clk) +static void clk_pllv3_disable(struct clk_hw *hw) { - struct clk_pllv3 *pll = to_clk_pllv3(clk); + struct clk_pllv3 *pll = to_clk_pllv3(hw); u32 val; val = readl(pll->base); @@ -82,16 +82,16 @@ static void clk_pllv3_disable(struct clk *clk) writel(val, pll->base); } -static unsigned long clk_pllv3_recalc_rate(struct clk *clk, +static unsigned long clk_pllv3_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) { - struct clk_pllv3 *pll = to_clk_pllv3(clk); + struct clk_pllv3 *pll = to_clk_pllv3(hw); u32 div = (readl(pll->base) >> pll->div_shift) & pll->div_mask; return (div == 1) ? parent_rate * 22 : parent_rate * 20; } -static long clk_pllv3_round_rate(struct clk *clk, unsigned long rate, +static long clk_pllv3_round_rate(struct clk_hw *hw, unsigned long rate, unsigned long *prate) { unsigned long parent_rate = *prate; @@ -100,10 +100,10 @@ static long clk_pllv3_round_rate(struct clk *clk, unsigned long rate, parent_rate * 20; } -static int clk_pllv3_set_rate(struct clk *clk, unsigned long rate, +static int clk_pllv3_set_rate(struct clk_hw *hw, unsigned long rate, unsigned long parent_rate) { - struct clk_pllv3 *pll = to_clk_pllv3(clk); + struct clk_pllv3 *pll = to_clk_pllv3(hw); u32 val, div; if (rate == parent_rate * 22) @@ -129,16 +129,16 @@ static const struct clk_ops clk_pllv3_ops = { .set_rate = clk_pllv3_set_rate, }; -static unsigned long clk_pllv3_sys_recalc_rate(struct clk *clk, +static unsigned long clk_pllv3_sys_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) { - struct clk_pllv3 *pll = to_clk_pllv3(clk); + struct clk_pllv3 *pll = to_clk_pllv3(hw); u32 div = readl(pll->base) & pll->div_mask; return parent_rate * div / 2; } -static long clk_pllv3_sys_round_rate(struct clk *clk, unsigned long rate, +static long clk_pllv3_sys_round_rate(struct clk_hw *hw, unsigned long rate, unsigned long *prate) { unsigned long parent_rate = *prate; @@ -155,10 +155,10 @@ static long clk_pllv3_sys_round_rate(struct clk *clk, unsigned long rate, return parent_rate * div / 2; } -static int clk_pllv3_sys_set_rate(struct clk *clk, unsigned long rate, +static int clk_pllv3_sys_set_rate(struct clk_hw *hw, unsigned long rate, unsigned long parent_rate) { - struct clk_pllv3 *pll = to_clk_pllv3(clk); + struct clk_pllv3 *pll = to_clk_pllv3(hw); unsigned long min_rate = parent_rate * 54 / 2; unsigned long max_rate = parent_rate * 108 / 2; u32 val, div; @@ -183,10 +183,11 @@ static const struct clk_ops clk_pllv3_sys_ops = { .set_rate = clk_pllv3_sys_set_rate, }; -static unsigned long clk_pllv3_av_recalc_rate(struct clk *clk, +static unsigned long clk_pllv3_av_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) { - struct clk_pllv3 *pll = to_clk_pllv3(clk); + struct clk_pllv3 *pll = to_clk_pllv3(hw); + u32 mfn = readl(pll->base + PLL_NUM_OFFSET); u32 mfd = readl(pll->base + PLL_DENOM_OFFSET); u32 div = readl(pll->base) & pll->div_mask; @@ -194,7 +195,7 @@ static unsigned long clk_pllv3_av_recalc_rate(struct clk *clk, return (parent_rate * div) + ((parent_rate / mfd) * mfn); } -static long clk_pllv3_av_round_rate(struct clk *clk, unsigned long rate, +static long clk_pllv3_av_round_rate(struct clk_hw *hw, unsigned long rate, unsigned long *prate) { unsigned long parent_rate = *prate; @@ -218,10 +219,11 @@ static long clk_pllv3_av_round_rate(struct clk *clk, unsigned long rate, return parent_rate * div + parent_rate / mfd * mfn; } -static int clk_pllv3_av_set_rate(struct clk *clk, unsigned long rate, +static int clk_pllv3_av_set_rate(struct clk_hw *hw, unsigned long rate, unsigned long parent_rate) { - struct clk_pllv3 *pll = to_clk_pllv3(clk); + struct clk_pllv3 *pll = to_clk_pllv3(hw); + unsigned long min_rate = parent_rate * 27; unsigned long max_rate = parent_rate * 54; u32 val, div; @@ -255,10 +257,10 @@ static const struct clk_ops clk_pllv3_av_ops = { .set_rate = clk_pllv3_av_set_rate, }; -static unsigned long clk_pllv3_enet_recalc_rate(struct clk *clk, +static unsigned long clk_pllv3_enet_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) { - struct clk_pllv3 *pll = to_clk_pllv3(clk); + struct clk_pllv3 *pll = to_clk_pllv3(hw); return pll->ref_clock; } @@ -274,10 +276,10 @@ static const struct clk_ops clk_pllv3_mlb_ops = { .disable = clk_pllv3_disable, }; -static unsigned long clk_pllv3_sys_vf610_recalc_rate(struct clk *clk, +static unsigned long clk_pllv3_sys_vf610_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) { - struct clk_pllv3 *pll = to_clk_pllv3(clk); + struct clk_pllv3 *pll = to_clk_pllv3(hw); u32 mfn = readl(pll->base + SYS_VF610_PLL_OFFSET + PLL_NUM_OFFSET); u32 mfd = readl(pll->base + SYS_VF610_PLL_OFFSET + PLL_DENOM_OFFSET); @@ -286,7 +288,7 @@ static unsigned long clk_pllv3_sys_vf610_recalc_rate(struct clk *clk, return (parent_rate * div) + ((parent_rate / mfd) * mfn); } -static long clk_pllv3_sys_vf610_round_rate(struct clk *clk, unsigned long rate, +static long clk_pllv3_sys_vf610_round_rate(struct clk_hw *hw, unsigned long rate, unsigned long *prate) { unsigned long parent_rate = *prate; @@ -308,10 +310,10 @@ static long clk_pllv3_sys_vf610_round_rate(struct clk *clk, unsigned long rate, return parent_rate * 20 + parent_rate / mfd * mfn; } -static int clk_pllv3_sys_vf610_set_rate(struct clk *clk, unsigned long rate, +static int clk_pllv3_sys_vf610_set_rate(struct clk_hw *hw, unsigned long rate, unsigned long parent_rate) { - struct clk_pllv3 *pll = to_clk_pllv3(clk); + struct clk_pllv3 *pll = to_clk_pllv3(hw); unsigned long min_rate = parent_rate * 20; unsigned long max_rate = 528000000; u32 val; @@ -400,20 +402,20 @@ struct clk *imx_clk_pllv3(enum imx_pllv3_type type, const char *name, pll->base = base; pll->div_mask = div_mask; pll->parent = parent; - pll->clk.ops = ops; - pll->clk.name = name; - pll->clk.parent_names = &pll->parent; - pll->clk.num_parents = 1; + pll->hw.clk.ops = ops; + pll->hw.clk.name = name; + pll->hw.clk.parent_names = &pll->parent; + pll->hw.clk.num_parents = 1; val = readl(pll->base); val &= ~BM_PLL_BYPASS; writel(val, pll->base); - ret = clk_register(&pll->clk); + ret = bclk_register(&pll->hw.clk); if (ret) { free(pll); return ERR_PTR(ret); } - return &pll->clk; + return &pll->hw.clk; } diff --git a/drivers/clk/imx/clk-sccg-pll.c b/drivers/clk/imx/clk-sccg-pll.c index 755ece0e12..f911bf4aa1 100644 --- a/drivers/clk/imx/clk-sccg-pll.c +++ b/drivers/clk/imx/clk-sccg-pll.c @@ -39,26 +39,26 @@ #define OSC_27M 27000000 struct clk_sccg_pll { - struct clk clk; + struct clk_hw hw; void __iomem *base; const char *parent; }; -#define to_clk_sccg_pll(_clk) container_of(_clk, struct clk_sccg_pll, clk) +#define to_clk_sccg_pll(_hw) container_of(_hw, struct clk_sccg_pll, hw) -static int clk_pll1_is_prepared(struct clk *clk) +static int clk_pll1_is_prepared(struct clk_hw *hw) { - struct clk_sccg_pll *pll = to_clk_sccg_pll(clk); + struct clk_sccg_pll *pll = to_clk_sccg_pll(hw); u32 val; val = readl(pll->base + PLL_CFG0); return (val & (1 << PLL_PD)) ? 0 : 1; } -static unsigned long clk_pll1_recalc_rate(struct clk *clk, +static unsigned long clk_pll1_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) { - struct clk_sccg_pll *pll = to_clk_sccg_pll(clk); + struct clk_sccg_pll *pll = to_clk_sccg_pll(hw); u32 val, divf; val = readl(pll->base + PLL_CFG2); @@ -67,7 +67,7 @@ static unsigned long clk_pll1_recalc_rate(struct clk *clk, return parent_rate * 2 * (divf + 1); } -static long clk_pll1_round_rate(struct clk *clk, unsigned long rate, +static long clk_pll1_round_rate(struct clk_hw *hw, unsigned long rate, unsigned long *prate) { unsigned long parent_rate = *prate; @@ -78,10 +78,10 @@ static long clk_pll1_round_rate(struct clk *clk, unsigned long rate, return parent_rate * div * 2; } -static int clk_pll1_set_rate(struct clk *clk, unsigned long rate, +static int clk_pll1_set_rate(struct clk_hw *hw, unsigned long rate, unsigned long parent_rate) { - struct clk_sccg_pll *pll = to_clk_sccg_pll(clk); + struct clk_sccg_pll *pll = to_clk_sccg_pll(hw); u32 val; u32 divf; @@ -97,9 +97,9 @@ static int clk_pll1_set_rate(struct clk *clk, unsigned long rate, return 0; } -static int clk_pll1_prepare(struct clk *clk) +static int clk_pll1_prepare(struct clk_hw *hw) { - struct clk_sccg_pll *pll = to_clk_sccg_pll(clk); + struct clk_sccg_pll *pll = to_clk_sccg_pll(hw); u32 val; val = readl(pll->base); @@ -111,19 +111,20 @@ static int clk_pll1_prepare(struct clk *clk) return 0; } -static void clk_pll1_unprepare(struct clk *clk) +static void clk_pll1_unprepare(struct clk_hw *hw) { - struct clk_sccg_pll *pll = to_clk_sccg_pll(clk); + struct clk_sccg_pll *pll = to_clk_sccg_pll(hw); u32 val; + val = readl(pll->base); val |= (1 << PLL_PD); writel(val, pll->base); } -static unsigned long clk_pll2_recalc_rate(struct clk *clk, +static unsigned long clk_pll2_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) { - struct clk_sccg_pll *pll = to_clk_sccg_pll(clk); + struct clk_sccg_pll *pll = to_clk_sccg_pll(hw); u32 val, ref, divr1, divf1, divr2, divf2; u64 temp64; @@ -154,7 +155,7 @@ static unsigned long clk_pll2_recalc_rate(struct clk *clk, return (unsigned long)temp64; } -static long clk_pll2_round_rate(struct clk *clk, unsigned long rate, +static long clk_pll2_round_rate(struct clk_hw *hw, unsigned long rate, unsigned long *prate) { u32 div; @@ -165,12 +166,12 @@ static long clk_pll2_round_rate(struct clk *clk, unsigned long rate, return parent_rate * div; } -static int clk_pll2_set_rate(struct clk *clk, unsigned long rate, +static int clk_pll2_set_rate(struct clk_hw *hw, unsigned long rate, unsigned long parent_rate) { + struct clk_sccg_pll *pll = to_clk_sccg_pll(hw); u32 val; u32 divf; - struct clk_sccg_pll *pll = to_clk_sccg_pll(clk); divf = rate / (parent_rate); @@ -210,25 +211,25 @@ struct clk *imx_clk_sccg_pll(const char *name, const char *parent_name, return ERR_PTR(-ENOMEM); pll->base = base; - pll->clk.name = name; + pll->hw.clk.name = name; switch (pll_type) { case SCCG_PLL1: - pll->clk.ops = &clk_sccg_pll1_ops; + pll->hw.clk.ops = &clk_sccg_pll1_ops; break; case SCCG_PLL2: - pll->clk.ops = &clk_sccg_pll2_ops; + pll->hw.clk.ops = &clk_sccg_pll2_ops; break; } pll->parent = parent_name; - pll->clk.parent_names = &pll->parent; - pll->clk.num_parents = 1; + pll->hw.clk.parent_names = &pll->parent; + pll->hw.clk.num_parents = 1; - ret = clk_register(&pll->clk); + ret = bclk_register(&pll->hw.clk); if (ret) { free(pll); return ERR_PTR(ret); } - return &pll->clk; + return &pll->hw.clk; } diff --git a/drivers/clk/loongson/clk-ls1b200.c b/drivers/clk/loongson/clk-ls1b200.c index 66f8e261ac..6ac545224f 100644 --- a/drivers/clk/loongson/clk-ls1b200.c +++ b/drivers/clk/loongson/clk-ls1b200.c @@ -35,21 +35,21 @@ static struct clk *clks[LS1B_CLK_END]; static struct clk_onecell_data clk_data; struct clk_ls1b200 { - struct clk clk; + struct clk_hw hw; void __iomem *base; int div_shift; int div_mask; const char *parent; }; -static unsigned long clk_ls1b200_recalc_rate(struct clk *clk, unsigned long parent_rate) +static unsigned long clk_ls1b200_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) { int n; unsigned long rate; int pll_freq; struct clk_ls1b200 *ls1bclk; - ls1bclk = container_of(clk, struct clk_ls1b200, clk); + ls1bclk = container_of(hw, struct clk_ls1b200, hw); pll_freq = __raw_readl(ls1bclk->base); n = 12 * 1024; @@ -77,14 +77,14 @@ static struct clk *clk_ls1b200(const char *name, const char *parent, f->div_shift = div_shift; f->div_mask = div_mask; - f->clk.ops = &clk_ls1b200_ops; - f->clk.name = name; - f->clk.parent_names = &f->parent; - f->clk.num_parents = 1; + f->hw.clk.ops = &clk_ls1b200_ops; + f->hw.clk.name = name; + f->hw.clk.parent_names = &f->parent; + f->hw.clk.num_parents = 1; - clk_register(&f->clk); + bclk_register(&f->hw.clk); - return &f->clk; + return &f->hw.clk; } static const char * const cpu_mux[] = {"cpu_div", "oscillator", }; diff --git a/drivers/clk/mvebu/corediv.c b/drivers/clk/mvebu/corediv.c index 1577a2149c..1b7fa12701 100644 --- a/drivers/clk/mvebu/corediv.c +++ b/drivers/clk/mvebu/corediv.c @@ -51,7 +51,7 @@ struct clk_corediv_soc_desc { * existing in the current SoC. */ struct clk_corediv { - struct clk clk; + struct clk_hw hw; void __iomem *reg; const struct clk_corediv_desc *desc; const struct clk_corediv_soc_desc *soc_desc; @@ -70,11 +70,11 @@ static const struct clk_corediv_desc mvebu_corediv_desc[] = { #define CORE_CLK_DIV_RATIO_MASK 0xff -#define to_corediv_clk(p) container_of(p, struct clk_corediv, clk) +#define to_corediv_clk(p) container_of(p, struct clk_corediv, hw) -static int clk_corediv_is_enabled(struct clk *clk) +static int clk_corediv_is_enabled(struct clk_hw *hw) { - struct clk_corediv *corediv = to_corediv_clk(clk); + struct clk_corediv *corediv = to_corediv_clk(hw); const struct clk_corediv_soc_desc *soc_desc = corediv->soc_desc; const struct clk_corediv_desc *desc = corediv->desc; u32 enable_mask = BIT(desc->fieldbit) << soc_desc->enable_bit_offset; @@ -82,9 +82,9 @@ static int clk_corediv_is_enabled(struct clk *clk) return !!(readl(corediv->reg) & enable_mask); } -static int clk_corediv_enable(struct clk *clk) +static int clk_corediv_enable(struct clk_hw *hw) { - struct clk_corediv *corediv = to_corediv_clk(clk); + struct clk_corediv *corediv = to_corediv_clk(hw); const struct clk_corediv_soc_desc *soc_desc = corediv->soc_desc; const struct clk_corediv_desc *desc = corediv->desc; u32 reg; @@ -96,9 +96,9 @@ static int clk_corediv_enable(struct clk *clk) return 0; } -static void clk_corediv_disable(struct clk *clk) +static void clk_corediv_disable(struct clk_hw *hw) { - struct clk_corediv *corediv = to_corediv_clk(clk); + struct clk_corediv *corediv = to_corediv_clk(hw); const struct clk_corediv_soc_desc *soc_desc = corediv->soc_desc; const struct clk_corediv_desc *desc = corediv->desc; u32 reg; @@ -108,10 +108,10 @@ static void clk_corediv_disable(struct clk *clk) writel(reg, corediv->reg); } -static unsigned long clk_corediv_recalc_rate(struct clk *clk, +static unsigned long clk_corediv_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) { - struct clk_corediv *corediv = to_corediv_clk(clk); + struct clk_corediv *corediv = to_corediv_clk(hw); const struct clk_corediv_soc_desc *soc_desc = corediv->soc_desc; const struct clk_corediv_desc *desc = corediv->desc; u32 reg, div; @@ -121,7 +121,7 @@ static unsigned long clk_corediv_recalc_rate(struct clk *clk, return parent_rate / div; } -static long clk_corediv_round_rate(struct clk *clk, unsigned long rate, +static long clk_corediv_round_rate(struct clk_hw *hw, unsigned long rate, unsigned long *parent_rate) { /* Valid ratio are 1:4, 1:5, 1:6 and 1:8 */ @@ -136,10 +136,10 @@ static long clk_corediv_round_rate(struct clk *clk, unsigned long rate, return *parent_rate / div; } -static int clk_corediv_set_rate(struct clk *clk, unsigned long rate, +static int clk_corediv_set_rate(struct clk_hw *hw, unsigned long rate, unsigned long parent_rate) { - struct clk_corediv *corediv = to_corediv_clk(clk); + struct clk_corediv *corediv = to_corediv_clk(hw); const struct clk_corediv_soc_desc *soc_desc = corediv->soc_desc; const struct clk_corediv_desc *desc = corediv->desc; u32 reg, div; @@ -225,7 +225,7 @@ static int mvebu_corediv_clk_probe(struct device_d *dev) for (n = 0; n < clk_data.clk_num; n++) { const char *clk_name; - struct clk *clk = &corediv->clk; + struct clk *clk = &corediv->hw.clk; if (of_property_read_string_index(np, "clock-output-names", n, &clk_name)) { @@ -242,7 +242,7 @@ static int mvebu_corediv_clk_probe(struct device_d *dev) corediv->desc = &soc_desc->descs[n]; corediv->reg = base; clk_data.clks[n] = clk; - WARN_ON(IS_ERR_VALUE(clk_register(clk))); + WARN_ON(IS_ERR_VALUE(bclk_register(clk))); } return of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data); diff --git a/drivers/clk/mxs/clk-div.c b/drivers/clk/mxs/clk-div.c index 104587a8dc..17083a051a 100644 --- a/drivers/clk/mxs/clk-div.c +++ b/drivers/clk/mxs/clk-div.c @@ -28,40 +28,40 @@ struct clk_div { u8 busy; }; -static inline struct clk_div *to_clk_div(struct clk *clk) +static inline struct clk_div *to_clk_div(struct clk_hw *hw) { - struct clk_divider *divider = container_of(clk, struct clk_divider, clk); + struct clk_divider *divider = to_clk_divider(hw); return container_of(divider, struct clk_div, divider); } -static unsigned long clk_div_recalc_rate(struct clk *clk, +static unsigned long clk_div_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) { - struct clk_div *div = to_clk_div(clk); + struct clk_div *div = to_clk_div(hw); - return div->ops->recalc_rate(&div->divider.clk, parent_rate); + return div->ops->recalc_rate(&div->divider.hw, parent_rate); } -static long clk_div_round_rate(struct clk *clk, unsigned long rate, +static long clk_div_round_rate(struct clk_hw *hw, unsigned long rate, unsigned long *prate) { - struct clk_div *div = to_clk_div(clk); + struct clk_div *div = to_clk_div(hw); - return div->ops->round_rate(&div->divider.clk, rate, prate); + return div->ops->round_rate(&div->divider.hw, rate, prate); } -static int clk_div_set_rate(struct clk *clk, unsigned long rate, +static int clk_div_set_rate(struct clk_hw *hw, unsigned long rate, unsigned long parent_rate) { - struct clk_div *div = to_clk_div(clk); + struct clk_div *div = to_clk_div(hw); int ret; - ret = div->ops->set_rate(&div->divider.clk, rate, parent_rate); + ret = div->ops->set_rate(&div->divider.hw, rate, parent_rate); if (ret) return ret; - if (clk_is_enabled(clk)) + if (clk_hw_is_enabled(hw)) while (readl(div->reg) & 1 << div->busy); return 0; @@ -82,10 +82,10 @@ struct clk *mxs_clk_div(const char *name, const char *parent_name, div = xzalloc(sizeof(*div)); div->parent = parent_name; - div->divider.clk.name = name; - div->divider.clk.ops = &clk_div_ops; - div->divider.clk.parent_names = &div->parent; - div->divider.clk.num_parents = 1; + div->divider.hw.clk.name = name; + div->divider.hw.clk.ops = &clk_div_ops; + div->divider.hw.clk.parent_names = &div->parent; + div->divider.hw.clk.num_parents = 1; div->reg = reg; div->busy = busy; @@ -96,9 +96,9 @@ struct clk *mxs_clk_div(const char *name, const char *parent_name, div->divider.flags = CLK_DIVIDER_ONE_BASED; div->ops = &clk_divider_ops; - ret = clk_register(&div->divider.clk); + ret = bclk_register(&div->divider.hw.clk); if (ret) return ERR_PTR(ret); - return &div->divider.clk; + return &div->divider.hw.clk; } diff --git a/drivers/clk/mxs/clk-frac.c b/drivers/clk/mxs/clk-frac.c index a9d390121e..6fb479dfad 100644 --- a/drivers/clk/mxs/clk-frac.c +++ b/drivers/clk/mxs/clk-frac.c @@ -23,7 +23,7 @@ * when the divider is adjusted. */ struct clk_frac { - struct clk clk; + struct clk_hw hw; const char *parent; void __iomem *reg; u8 shift; @@ -31,12 +31,12 @@ struct clk_frac { u8 busy; }; -#define to_clk_frac(_hw) container_of(_hw, struct clk_frac, clk) +#define to_clk_frac(_hw) container_of(_hw, struct clk_frac, hw) -static unsigned long clk_frac_recalc_rate(struct clk *clk, +static unsigned long clk_frac_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) { - struct clk_frac *frac = to_clk_frac(clk); + struct clk_frac *frac = to_clk_frac(hw); u32 div; div = readl(frac->reg) >> frac->shift; @@ -45,10 +45,10 @@ static unsigned long clk_frac_recalc_rate(struct clk *clk, return (parent_rate >> frac->width) * div; } -static long clk_frac_round_rate(struct clk *clk, unsigned long rate, +static long clk_frac_round_rate(struct clk_hw *hw, unsigned long rate, unsigned long *prate) { - struct clk_frac *frac = to_clk_frac(clk); + struct clk_frac *frac = to_clk_frac(hw); unsigned long parent_rate = *prate; u32 div; u64 tmp; @@ -67,10 +67,10 @@ static long clk_frac_round_rate(struct clk *clk, unsigned long rate, return (parent_rate >> frac->width) * div; } -static int clk_frac_set_rate(struct clk *clk, unsigned long rate, +static int clk_frac_set_rate(struct clk_hw *hw, unsigned long rate, unsigned long parent_rate) { - struct clk_frac *frac = to_clk_frac(clk); + struct clk_frac *frac = to_clk_frac(hw); u32 div, val; u64 tmp; @@ -90,7 +90,7 @@ static int clk_frac_set_rate(struct clk *clk, unsigned long rate, val |= div << frac->shift; writel(val, frac->reg); - if (clk_is_enabled(clk)) + if (clk_hw_is_enabled(hw)) while (readl(frac->reg) & 1 << frac->busy); return 0; @@ -113,18 +113,18 @@ struct clk *mxs_clk_frac(const char *name, const char *parent_name, return ERR_PTR(-ENOMEM); frac->parent = parent_name; - frac->clk.name = name; - frac->clk.ops = &clk_frac_ops; - frac->clk.parent_names = &frac->parent; - frac->clk.num_parents = 1; + frac->hw.clk.name = name; + frac->hw.clk.ops = &clk_frac_ops; + frac->hw.clk.parent_names = &frac->parent; + frac->hw.clk.num_parents = 1; frac->reg = reg; frac->shift = shift; frac->width = width; - ret = clk_register(&frac->clk); + ret = bclk_register(&frac->hw.clk); if (ret) return ERR_PTR(ret); - return &frac->clk; + return &frac->hw.clk; } diff --git a/drivers/clk/mxs/clk-lcdif.c b/drivers/clk/mxs/clk-lcdif.c index 246e68068d..a395701262 100644 --- a/drivers/clk/mxs/clk-lcdif.c +++ b/drivers/clk/mxs/clk-lcdif.c @@ -7,18 +7,18 @@ #include "clk.h" struct clk_lcdif { - struct clk clk; + struct clk_hw hw; struct clk *frac, *div, *gate; const char *parent; }; -#define to_clk_lcdif(_hw) container_of(_hw, struct clk_lcdif, clk) +#define to_clk_lcdif(_hw) container_of(_hw, struct clk_lcdif, hw) -static int clk_lcdif_set_rate(struct clk *clk, unsigned long rate, +static int clk_lcdif_set_rate(struct clk_hw *hw, unsigned long rate, unsigned long unused) { - struct clk_lcdif *lcdif = to_clk_lcdif(clk); + struct clk_lcdif *lcdif = to_clk_lcdif(hw); unsigned long frac, div, best_div = 1; int delta, best_delta = 0x7fffffff; unsigned long frate, rrate, best_frate; @@ -63,14 +63,14 @@ struct clk *mxs_clk_lcdif(const char *name, struct clk *frac, struct clk *div, lcdif->frac = frac; lcdif->div = div; lcdif->gate = gate; - lcdif->clk.name = name; - lcdif->clk.ops = &clk_lcdif_ops; - lcdif->clk.parent_names = &lcdif->parent; - lcdif->clk.num_parents = 1; + lcdif->hw.clk.name = name; + lcdif->hw.clk.ops = &clk_lcdif_ops; + lcdif->hw.clk.parent_names = &lcdif->parent; + lcdif->hw.clk.num_parents = 1; - ret = clk_register(&lcdif->clk); + ret = bclk_register(&lcdif->hw.clk); if (ret) return ERR_PTR(ret); - return &lcdif->clk; + return &lcdif->hw.clk; } diff --git a/drivers/clk/mxs/clk-pll.c b/drivers/clk/mxs/clk-pll.c index 7527a77731..2c55ab7d8b 100644 --- a/drivers/clk/mxs/clk-pll.c +++ b/drivers/clk/mxs/clk-pll.c @@ -24,18 +24,18 @@ * and the shift of gate bit is always 31. */ struct clk_pll { - struct clk clk; + struct clk_hw hw; const char *parent; void __iomem *base; u8 power; unsigned long rate; }; -#define to_clk_pll(_hw) container_of(_hw, struct clk_pll, clk) +#define to_clk_pll(_hw) container_of(_hw, struct clk_pll, hw) -static int clk_pll_enable(struct clk *clk) +static int clk_pll_enable(struct clk_hw *hw) { - struct clk_pll *pll = to_clk_pll(clk); + struct clk_pll *pll = to_clk_pll(hw); writel(1 << pll->power, pll->base + SET); @@ -46,18 +46,18 @@ static int clk_pll_enable(struct clk *clk) return 0; } -static void clk_pll_disable(struct clk *clk) +static void clk_pll_disable(struct clk_hw *hw) { - struct clk_pll *pll = to_clk_pll(clk); + struct clk_pll *pll = to_clk_pll(hw); writel(1 << 31, pll->base + SET); writel(1 << pll->power, pll->base + CLR); } -static int clk_pll_is_enabled(struct clk *clk) +static int clk_pll_is_enabled(struct clk_hw *hw) { - struct clk_pll *pll = to_clk_pll(clk); + struct clk_pll *pll = to_clk_pll(hw); u32 val; val = readl(pll->base); @@ -68,10 +68,10 @@ static int clk_pll_is_enabled(struct clk *clk) return 1; } -static unsigned long clk_pll_recalc_rate(struct clk *clk, +static unsigned long clk_pll_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) { - struct clk_pll *pll = to_clk_pll(clk); + struct clk_pll *pll = to_clk_pll(hw); return pll->rate; } @@ -92,18 +92,18 @@ struct clk *mxs_clk_pll(const char *name, const char *parent_name, pll = xzalloc(sizeof(*pll)); pll->parent = parent_name; - pll->clk.name = name; - pll->clk.ops = &clk_pll_ops; - pll->clk.parent_names = &pll->parent; - pll->clk.num_parents = 1; + pll->hw.clk.name = name; + pll->hw.clk.ops = &clk_pll_ops; + pll->hw.clk.parent_names = &pll->parent; + pll->hw.clk.num_parents = 1; pll->base = base; pll->rate = rate; pll->power = power; - ret = clk_register(&pll->clk); + ret = bclk_register(&pll->hw.clk); if (ret) ERR_PTR(ret); - return &pll->clk; + return &pll->hw.clk; } diff --git a/drivers/clk/mxs/clk-ref.c b/drivers/clk/mxs/clk-ref.c index 69361f9ac3..d483c9c6b2 100644 --- a/drivers/clk/mxs/clk-ref.c +++ b/drivers/clk/mxs/clk-ref.c @@ -23,20 +23,20 @@ * as pll rate * (18 / FRAC), where FRAC = 18 ~ 35. */ struct clk_ref { - struct clk clk; + struct clk_hw hw; const char *parent; void __iomem *reg; u8 idx; }; -#define to_clk_ref(_hw) container_of(_hw, struct clk_ref, clk) +#define to_clk_ref(_hw) container_of(_hw, struct clk_ref, hw) #define SET 0x4 #define CLR 0x8 -static int clk_ref_is_enabled(struct clk *clk) +static int clk_ref_is_enabled(struct clk_hw *hw) { - struct clk_ref *ref = to_clk_ref(clk); + struct clk_ref *ref = to_clk_ref(hw); u32 reg = readl(ref->reg); if (reg & 1 << ((ref->idx + 1) * 8 - 1)) @@ -45,26 +45,26 @@ static int clk_ref_is_enabled(struct clk *clk) return 1; } -static int clk_ref_enable(struct clk *clk) +static int clk_ref_enable(struct clk_hw *hw) { - struct clk_ref *ref = to_clk_ref(clk); + struct clk_ref *ref = to_clk_ref(hw); writel(1 << ((ref->idx + 1) * 8 - 1), ref->reg + CLR); return 0; } -static void clk_ref_disable(struct clk *clk) +static void clk_ref_disable(struct clk_hw *hw) { - struct clk_ref *ref = to_clk_ref(clk); + struct clk_ref *ref = to_clk_ref(hw); writel(1 << ((ref->idx + 1) * 8 - 1), ref->reg + SET); } -static unsigned long clk_ref_recalc_rate(struct clk *clk, +static unsigned long clk_ref_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) { - struct clk_ref *ref = to_clk_ref(clk); + struct clk_ref *ref = to_clk_ref(hw); u64 tmp = parent_rate; u8 frac = (readl(ref->reg) >> (ref->idx * 8)) & 0x3f; @@ -74,7 +74,7 @@ static unsigned long clk_ref_recalc_rate(struct clk *clk, return tmp; } -static long clk_ref_round_rate(struct clk *clk, unsigned long rate, +static long clk_ref_round_rate(struct clk_hw *hw, unsigned long rate, unsigned long *prate) { unsigned long parent_rate = *prate; @@ -97,10 +97,10 @@ static long clk_ref_round_rate(struct clk *clk, unsigned long rate, return tmp; } -static int clk_ref_set_rate(struct clk *clk, unsigned long rate, +static int clk_ref_set_rate(struct clk_hw *hw, unsigned long rate, unsigned long parent_rate) { - struct clk_ref *ref = to_clk_ref(clk); + struct clk_ref *ref = to_clk_ref(hw); u64 tmp = parent_rate; u32 val; u32 frac, shift = ref->idx * 8; @@ -140,17 +140,17 @@ struct clk *mxs_clk_ref(const char *name, const char *parent_name, ref = xzalloc(sizeof(*ref)); ref->parent = parent_name; - ref->clk.name = name; - ref->clk.ops = &clk_ref_ops; - ref->clk.parent_names = &ref->parent; - ref->clk.num_parents = 1; + ref->hw.clk.name = name; + ref->hw.clk.ops = &clk_ref_ops; + ref->hw.clk.parent_names = &ref->parent; + ref->hw.clk.num_parents = 1; ref->reg = reg; ref->idx = idx; - ret = clk_register(&ref->clk); + ret = bclk_register(&ref->hw.clk); if (ret) return ERR_PTR(ret); - return &ref->clk; + return &ref->hw.clk; } diff --git a/drivers/clk/rockchip/Makefile b/drivers/clk/rockchip/Makefile index 5fcf0c2515..a2461d16c1 100644 --- a/drivers/clk/rockchip/Makefile +++ b/drivers/clk/rockchip/Makefile @@ -1,4 +1,6 @@ # SPDX-License-Identifier: GPL-2.0-only -obj-y += clk-cpu.o clk-pll.o clk.o +obj-y += clk-cpu.o clk-pll.o clk.o clk-muxgrf.o clk-mmc-phase.o clk-inverter.o +obj-$(CONFIG_RESET_CONTROLLER) += softrst.o obj-$(CONFIG_ARCH_RK3188) += clk-rk3188.o obj-$(CONFIG_ARCH_RK3288) += clk-rk3288.o +obj-$(CONFIG_ARCH_RK3568) += clk-rk3568.o diff --git a/drivers/clk/rockchip/clk-cpu.c b/drivers/clk/rockchip/clk-cpu.c index 71a64f71f6..8b5d4a0330 100644 --- a/drivers/clk/rockchip/clk-cpu.c +++ b/drivers/clk/rockchip/clk-cpu.c @@ -34,8 +34,10 @@ #include <malloc.h> #include <io.h> #include <xfuncs.h> -#include "clk.h" #include <linux/barebox-wrapper.h> +#include <linux/clk.h> +#include <linux/spinlock.h> +#include "clk.h" /** * struct rockchip_cpuclk: information about clock supplied to a CPU core. @@ -43,31 +45,34 @@ * @alt_parent: alternate parent clock to use when switching the speed * of the primary parent clock. * @reg_base: base register for cpu-clock values. + * @clk_nb: clock notifier registered for changes in clock speed of the + * primary parent clock. * @rate_count: number of rates in the rate_table * @rate_table: pll-rates and their associated dividers * @reg_data: cpu-specific register settings + * @lock: clock lock */ struct rockchip_cpuclk { - struct clk hw; - + struct clk_hw hw; struct clk *alt_parent; void __iomem *reg_base; unsigned int rate_count; struct rockchip_cpuclk_rate_table *rate_table; const struct rockchip_cpuclk_reg_data *reg_data; + spinlock_t *lock; }; #define to_rockchip_cpuclk_hw(hw) container_of(hw, struct rockchip_cpuclk, hw) -static unsigned long rockchip_cpuclk_recalc_rate(struct clk *hw, +static unsigned long rockchip_cpuclk_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) { struct rockchip_cpuclk *cpuclk = to_rockchip_cpuclk_hw(hw); const struct rockchip_cpuclk_reg_data *reg_data = cpuclk->reg_data; - u32 clksel0 = readl(cpuclk->reg_base + reg_data->core_reg); + u32 clksel0 = readl_relaxed(cpuclk->reg_base + reg_data->core_reg[0]); - clksel0 >>= reg_data->div_core_shift; - clksel0 &= reg_data->div_core_mask; + clksel0 >>= reg_data->div_core_shift[0]; + clksel0 &= reg_data->div_core_mask[0]; return parent_rate / (clksel0 + 1); } @@ -76,17 +81,18 @@ static const struct clk_ops rockchip_cpuclk_ops = { }; struct clk *rockchip_clk_register_cpuclk(const char *name, - const char **parent_names, u8 num_parents, + const char *const *parent_names, u8 num_parents, const struct rockchip_cpuclk_reg_data *reg_data, const struct rockchip_cpuclk_rate_table *rates, - int nrates, void __iomem *reg_base) + int nrates, void __iomem *reg_base, spinlock_t *lock) { struct rockchip_cpuclk *cpuclk; - struct clk *clk; + struct clk_init_data init; + struct clk *clk, *cclk; int ret; - if (num_parents != 2) { - pr_err("%s: needs two parent clocks\n", __func__); + if (num_parents < 2) { + pr_err("%s: needs at least two parent clocks\n", __func__); return ERR_PTR(-EINVAL); } @@ -94,21 +100,28 @@ struct clk *rockchip_clk_register_cpuclk(const char *name, if (!cpuclk) return ERR_PTR(-ENOMEM); - cpuclk->hw.name = name; - cpuclk->hw.parent_names = &parent_names[0]; - cpuclk->hw.num_parents = 1; - cpuclk->hw.ops = &rockchip_cpuclk_ops; + init.name = name; + init.parent_names = &parent_names[reg_data->mux_core_main]; + init.num_parents = 1; + init.ops = &rockchip_cpuclk_ops; /* only allow rate changes when we have a rate table */ - cpuclk->hw.flags = (nrates > 0) ? CLK_SET_RATE_PARENT : 0; + init.flags = (nrates > 0) ? CLK_SET_RATE_PARENT : 0; + + /* disallow automatic parent changes by ccf */ + init.flags |= CLK_SET_RATE_NO_REPARENT; + + init.flags |= CLK_GET_RATE_NOCACHE; cpuclk->reg_base = reg_base; + cpuclk->lock = lock; cpuclk->reg_data = reg_data; + cpuclk->hw.init = &init; - cpuclk->alt_parent = __clk_lookup(parent_names[1]); + cpuclk->alt_parent = __clk_lookup(parent_names[reg_data->mux_core_alt]); if (!cpuclk->alt_parent) { - pr_err("%s: could not lookup alternate parent\n", - __func__); + pr_err("%s: could not lookup alternate parent: (%d)\n", + __func__, reg_data->mux_core_alt); ret = -EINVAL; goto free_cpuclk; } @@ -120,37 +133,40 @@ struct clk *rockchip_clk_register_cpuclk(const char *name, goto free_cpuclk; } - clk = __clk_lookup(parent_names[0]); + clk = __clk_lookup(parent_names[reg_data->mux_core_main]); if (!clk) { - pr_err("%s: could not lookup parent clock %s\n", - __func__, parent_names[0]); + pr_err("%s: could not lookup parent clock: (%d) %s\n", + __func__, reg_data->mux_core_main, + parent_names[reg_data->mux_core_main]); ret = -EINVAL; - goto free_cpuclk; + goto free_alt_parent; } if (nrates > 0) { cpuclk->rate_count = nrates; - cpuclk->rate_table = xmemdup(rates, - sizeof(*rates) * nrates - ); + cpuclk->rate_table = kmemdup(rates, + sizeof(*rates) * nrates, + GFP_KERNEL); if (!cpuclk->rate_table) { - pr_err("%s: could not allocate memory for cpuclk rates\n", - __func__); ret = -ENOMEM; - goto free_cpuclk; + goto unregister_notifier; } } - ret = clk_register(&cpuclk->hw); - if (ret) { + cclk = clk_register(NULL, &cpuclk->hw); + if (IS_ERR(cclk)) { pr_err("%s: could not register cpuclk %s\n", __func__, name); + ret = PTR_ERR(cclk); goto free_rate_table; } - return &cpuclk->hw; + return cclk; free_rate_table: kfree(cpuclk->rate_table); +unregister_notifier: +free_alt_parent: + clk_disable(cpuclk->alt_parent); free_cpuclk: kfree(cpuclk); return ERR_PTR(ret); diff --git a/drivers/clk/rockchip/clk-inverter.c b/drivers/clk/rockchip/clk-inverter.c new file mode 100644 index 0000000000..7cdcf15fd8 --- /dev/null +++ b/drivers/clk/rockchip/clk-inverter.c @@ -0,0 +1,107 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright 2015 Heiko Stuebner <heiko@sntech.de> + */ + +#include <common.h> +#include <of.h> +#include <malloc.h> +#include <io.h> +#include <xfuncs.h> +#include <linux/barebox-wrapper.h> +#include <linux/clk.h> +#include <regmap.h> +#include <linux/spinlock.h> +#include "clk.h" + +struct rockchip_inv_clock { + struct clk_hw hw; + void __iomem *reg; + int shift; + int flags; + spinlock_t *lock; +}; + +#define to_inv_clock(_hw) container_of(_hw, struct rockchip_inv_clock, hw) + +#define INVERTER_MASK 0x1 + +static int rockchip_inv_get_phase(struct clk_hw *hw) +{ + struct rockchip_inv_clock *inv_clock = to_inv_clock(hw); + u32 val; + + val = readl(inv_clock->reg) >> inv_clock->shift; + val &= INVERTER_MASK; + return val ? 180 : 0; +} + +static int rockchip_inv_set_phase(struct clk_hw *hw, int degrees) +{ + struct rockchip_inv_clock *inv_clock = to_inv_clock(hw); + u32 val; + + if (degrees % 180 == 0) { + val = !!degrees; + } else { + pr_err("%s: unsupported phase %d for %s\n", + __func__, degrees, clk_hw_get_name(hw)); + return -EINVAL; + } + + if (inv_clock->flags & ROCKCHIP_INVERTER_HIWORD_MASK) { + writel(HIWORD_UPDATE(val, INVERTER_MASK, inv_clock->shift), + inv_clock->reg); + } else { + unsigned long flags; + u32 reg; + + spin_lock_irqsave(inv_clock->lock, flags); + + reg = readl(inv_clock->reg); + reg &= ~BIT(inv_clock->shift); + reg |= val; + writel(reg, inv_clock->reg); + + spin_unlock_irqrestore(inv_clock->lock, flags); + } + + return 0; +} + +static const struct clk_ops rockchip_inv_clk_ops = { + .get_phase = rockchip_inv_get_phase, + .set_phase = rockchip_inv_set_phase, +}; + +struct clk *rockchip_clk_register_inverter(const char *name, + const char *const *parent_names, u8 num_parents, + void __iomem *reg, int shift, int flags, + spinlock_t *lock) +{ + struct clk_init_data init; + struct rockchip_inv_clock *inv_clock; + struct clk *clk; + + inv_clock = kzalloc(sizeof(*inv_clock), GFP_KERNEL); + if (!inv_clock) + return ERR_PTR(-ENOMEM); + + init.name = name; + init.num_parents = num_parents; + init.flags = CLK_SET_RATE_PARENT; + init.parent_names = parent_names; + init.ops = &rockchip_inv_clk_ops; + + inv_clock->hw.init = &init; + inv_clock->reg = reg; + inv_clock->shift = shift; + inv_clock->flags = flags; + inv_clock->lock = lock; + + clk = clk_register(NULL, &inv_clock->hw); + if (IS_ERR(clk)) + kfree(inv_clock); + + return clk; +} diff --git a/drivers/clk/rockchip/clk-mmc-phase.c b/drivers/clk/rockchip/clk-mmc-phase.c new file mode 100644 index 0000000000..822189a2fd --- /dev/null +++ b/drivers/clk/rockchip/clk-mmc-phase.c @@ -0,0 +1,192 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright 2014 Google, Inc + * Author: Alexandru M Stan <amstan@chromium.org> + */ + +#include <common.h> +#include <of.h> +#include <malloc.h> +#include <io.h> +#include <xfuncs.h> +#include <linux/barebox-wrapper.h> +#include <linux/clk.h> +#include <linux/spinlock.h> +#include "clk.h" + +struct rockchip_mmc_clock { + struct clk_hw hw; + void __iomem *reg; + int id; + int shift; + int cached_phase; +}; + +#define to_mmc_clock(_hw) container_of(_hw, struct rockchip_mmc_clock, hw) + +#define RK3288_MMC_CLKGEN_DIV 2 + +static unsigned long rockchip_mmc_recalc(struct clk_hw *hw, + unsigned long parent_rate) +{ + return parent_rate / RK3288_MMC_CLKGEN_DIV; +} + +#define ROCKCHIP_MMC_DELAY_SEL BIT(10) +#define ROCKCHIP_MMC_DEGREE_MASK 0x3 +#define ROCKCHIP_MMC_DELAYNUM_OFFSET 2 +#define ROCKCHIP_MMC_DELAYNUM_MASK (0xff << ROCKCHIP_MMC_DELAYNUM_OFFSET) + +#define PSECS_PER_SEC 1000000000000LL + +/* + * Each fine delay is between 44ps-77ps. Assume each fine delay is 60ps to + * simplify calculations. So 45degs could be anywhere between 33deg and 57.8deg. + */ +#define ROCKCHIP_MMC_DELAY_ELEMENT_PSEC 60 + +static int rockchip_mmc_get_phase(struct clk_hw *hw) +{ + struct rockchip_mmc_clock *mmc_clock = to_mmc_clock(hw); + unsigned long rate = clk_hw_get_rate(hw); + u32 raw_value; + u16 degrees; + u32 delay_num = 0; + + /* Constant signal, no measurable phase shift */ + if (!rate) + return 0; + + raw_value = readl(mmc_clock->reg) >> (mmc_clock->shift); + + degrees = (raw_value & ROCKCHIP_MMC_DEGREE_MASK) * 90; + + if (raw_value & ROCKCHIP_MMC_DELAY_SEL) { + /* degrees/delaynum * 1000000 */ + unsigned long factor = (ROCKCHIP_MMC_DELAY_ELEMENT_PSEC / 10) * + 36 * (rate / 10000); + + delay_num = (raw_value & ROCKCHIP_MMC_DELAYNUM_MASK); + delay_num >>= ROCKCHIP_MMC_DELAYNUM_OFFSET; + degrees += DIV_ROUND_CLOSEST(delay_num * factor, 1000000); + } + + return degrees % 360; +} + +static int rockchip_mmc_set_phase(struct clk_hw *hw, int degrees) +{ + struct rockchip_mmc_clock *mmc_clock = to_mmc_clock(hw); + unsigned long rate = clk_hw_get_rate(hw); + u8 nineties, remainder; + u8 delay_num; + u32 raw_value; + u32 delay; + + /* + * The below calculation is based on the output clock from + * MMC host to the card, which expects the phase clock inherits + * the clock rate from its parent, namely the output clock + * provider of MMC host. However, things may go wrong if + * (1) It is orphan. + * (2) It is assigned to the wrong parent. + * + * This check help debug the case (1), which seems to be the + * most likely problem we often face and which makes it difficult + * for people to debug unstable mmc tuning results. + */ + if (!rate) { + pr_err("%s: invalid clk rate\n", __func__); + return -EINVAL; + } + + nineties = degrees / 90; + remainder = (degrees % 90); + + /* + * Due to the inexact nature of the "fine" delay, we might + * actually go non-monotonic. We don't go _too_ monotonic + * though, so we should be OK. Here are options of how we may + * work: + * + * Ideally we end up with: + * 1.0, 2.0, ..., 69.0, 70.0, ..., 89.0, 90.0 + * + * On one extreme (if delay is actually 44ps): + * .73, 1.5, ..., 50.6, 51.3, ..., 65.3, 90.0 + * The other (if delay is actually 77ps): + * 1.3, 2.6, ..., 88.6. 89.8, ..., 114.0, 90 + * + * It's possible we might make a delay that is up to 25 + * degrees off from what we think we're making. That's OK + * though because we should be REALLY far from any bad range. + */ + + /* + * Convert to delay; do a little extra work to make sure we + * don't overflow 32-bit / 64-bit numbers. + */ + delay = 10000000; /* PSECS_PER_SEC / 10000 / 10 */ + delay *= remainder; + delay = DIV_ROUND_CLOSEST(delay, + (rate / 1000) * 36 * + (ROCKCHIP_MMC_DELAY_ELEMENT_PSEC / 10)); + + delay_num = (u8) min_t(u32, delay, 255); + + raw_value = delay_num ? ROCKCHIP_MMC_DELAY_SEL : 0; + raw_value |= delay_num << ROCKCHIP_MMC_DELAYNUM_OFFSET; + raw_value |= nineties; + writel(HIWORD_UPDATE(raw_value, 0x07ff, mmc_clock->shift), + mmc_clock->reg); + + pr_debug("%s->set_phase(%d) delay_nums=%u reg[0x%p]=0x%03x actual_degrees=%d\n", + clk_hw_get_name(hw), degrees, delay_num, + mmc_clock->reg, raw_value>>(mmc_clock->shift), + rockchip_mmc_get_phase(hw) + ); + + return 0; +} + +static const struct clk_ops rockchip_mmc_clk_ops = { + .recalc_rate = rockchip_mmc_recalc, + .get_phase = rockchip_mmc_get_phase, + .set_phase = rockchip_mmc_set_phase, +}; + +struct clk *rockchip_clk_register_mmc(const char *name, + const char *const *parent_names, u8 num_parents, + void __iomem *reg, int shift) +{ + struct clk_init_data init; + struct rockchip_mmc_clock *mmc_clock; + struct clk *clk; + int ret; + + mmc_clock = kzalloc(sizeof(*mmc_clock), GFP_KERNEL); + if (!mmc_clock) + return ERR_PTR(-ENOMEM); + + init.name = name; + init.flags = 0; + init.num_parents = num_parents; + init.parent_names = parent_names; + init.ops = &rockchip_mmc_clk_ops; + + mmc_clock->hw.init = &init; + mmc_clock->reg = reg; + mmc_clock->shift = shift; + + clk = clk_register(NULL, &mmc_clock->hw); + if (IS_ERR(clk)) { + ret = PTR_ERR(clk); + goto err_register; + } + + return clk; + +err_register: + kfree(mmc_clock); + return ERR_PTR(ret); +} diff --git a/drivers/clk/rockchip/clk-muxgrf.c b/drivers/clk/rockchip/clk-muxgrf.c new file mode 100644 index 0000000000..f06fa69514 --- /dev/null +++ b/drivers/clk/rockchip/clk-muxgrf.c @@ -0,0 +1,95 @@ +// SPDX-License-Identifier: GPL-2.0-only + +#include <common.h> +#include <of.h> +#include <malloc.h> +#include <io.h> +#include <xfuncs.h> +#include <linux/barebox-wrapper.h> +#include <linux/clk.h> +#include <regmap.h> +#include <linux/spinlock.h> +#include "clk.h" + +struct rockchip_muxgrf_clock { + struct clk_hw hw; + struct regmap *regmap; + u32 reg; + u32 shift; + u32 width; + int flags; +}; + +#define to_muxgrf_clock(_hw) container_of(_hw, struct rockchip_muxgrf_clock, hw) + +static int rockchip_muxgrf_get_parent(struct clk_hw *hw) +{ + struct rockchip_muxgrf_clock *mux = to_muxgrf_clock(hw); + unsigned int mask = GENMASK(mux->width - 1, 0); + unsigned int val; + + regmap_read(mux->regmap, mux->reg, &val); + + val >>= mux->shift; + val &= mask; + + return val; +} + +static int rockchip_muxgrf_set_parent(struct clk_hw *hw, u8 index) +{ + struct rockchip_muxgrf_clock *mux = to_muxgrf_clock(hw); + unsigned int mask = GENMASK(mux->width + mux->shift - 1, mux->shift); + unsigned int val; + + val = index; + val <<= mux->shift; + + if (mux->flags & CLK_MUX_HIWORD_MASK) + return regmap_write(mux->regmap, mux->reg, val | (mask << 16)); + else + return regmap_update_bits(mux->regmap, mux->reg, mask, val); +} + +static const struct clk_ops rockchip_muxgrf_clk_ops = { + .get_parent = rockchip_muxgrf_get_parent, + .set_parent = rockchip_muxgrf_set_parent, +}; + +struct clk *rockchip_clk_register_muxgrf(const char *name, + const char *const *parent_names, u8 num_parents, + int flags, struct regmap *regmap, int reg, + int shift, int width, int mux_flags) +{ + struct rockchip_muxgrf_clock *muxgrf_clock; + struct clk_init_data init; + struct clk *clk; + + if (IS_ERR(regmap)) { + pr_err("%s: regmap not available\n", __func__); + return ERR_PTR(-ENOTSUPP); + } + + muxgrf_clock = kzalloc(sizeof(*muxgrf_clock), GFP_KERNEL); + if (!muxgrf_clock) + return ERR_PTR(-ENOMEM); + + init.name = name; + init.flags = flags; + init.num_parents = num_parents; + init.parent_names = parent_names; + init.ops = &rockchip_muxgrf_clk_ops; + + muxgrf_clock->hw.init = &init; + muxgrf_clock->regmap = regmap; + muxgrf_clock->reg = reg; + muxgrf_clock->shift = shift; + muxgrf_clock->width = width; + muxgrf_clock->flags = mux_flags; + + clk = clk_register(NULL, &muxgrf_clock->hw); + if (IS_ERR(clk)) + kfree(muxgrf_clock); + + return clk; +} diff --git a/drivers/clk/rockchip/clk-pll.c b/drivers/clk/rockchip/clk-pll.c index 6bb8156f8c..fdbb016e7f 100644 --- a/drivers/clk/rockchip/clk-pll.c +++ b/drivers/clk/rockchip/clk-pll.c @@ -2,6 +2,9 @@ /* * Copyright (c) 2014 MundoReader S.L. * Author: Heiko Stuebner <heiko@sntech.de> + * + * Copyright (c) 2015 Rockchip Electronics Co. Ltd. + * Author: Xing Zheng <zhengxing@rock-chips.com> */ #include <linux/math64.h> @@ -14,16 +17,19 @@ #include <linux/barebox-wrapper.h> #include "clk.h" #include <xfuncs.h> +#include <regmap.h> +#include <linux/iopoll.h> -#define PLL_MODE_MASK 0x3 +#define PLL_MODE_WIDTH 2 #define PLL_MODE_SLOW 0x0 #define PLL_MODE_NORM 0x1 #define PLL_MODE_DEEP 0x2 +#define PLL_RK3328_MODE_WIDTH 1 struct rockchip_clk_pll { - struct clk hw; + struct clk_hw hw; - struct clk pll_mux; + struct clk_mux pll_mux; const struct clk_ops *pll_mux_ops; void __iomem *reg_base; @@ -33,7 +39,9 @@ struct rockchip_clk_pll { u8 flags; const struct rockchip_pll_rate_table *rate_table; unsigned int rate_count; - char pll_name[20]; + spinlock_t *lock; + + struct rockchip_clk_provider *ctx; }; #define to_rockchip_clk_pll(_hw) container_of(_hw, struct rockchip_clk_pll, hw) @@ -52,7 +60,7 @@ static const struct rockchip_pll_rate_table *rockchip_get_pll_settings( return NULL; } -static long rockchip_pll_round_rate(struct clk *hw, +static long rockchip_pll_round_rate(struct clk_hw *hw, unsigned long drate, unsigned long *prate) { struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw); @@ -74,26 +82,282 @@ static long rockchip_pll_round_rate(struct clk *hw, * The calling set_rate function is responsible for making sure the * grf regmap is available. */ -#define RK3188_PLL_LOCK_REG 0x200080ac - static int rockchip_pll_wait_lock(struct rockchip_clk_pll *pll) { - int delay = 24000000; - int val; + struct regmap *grf = pll->ctx->grf; + unsigned int val; + int ret; + + ret = regmap_read_poll_timeout(grf, pll->lock_offset, val, + val & BIT(pll->lock_shift), 1000); + if (ret) + pr_err("%s: timeout waiting for pll to lock\n", __func__); + + return ret; +} + +/* + * PLL used in RK3036 + */ + +#define RK3036_PLLCON(i) (i * 0x4) +#define RK3036_PLLCON0_FBDIV_MASK 0xfff +#define RK3036_PLLCON0_FBDIV_SHIFT 0 +#define RK3036_PLLCON0_POSTDIV1_MASK 0x7 +#define RK3036_PLLCON0_POSTDIV1_SHIFT 12 +#define RK3036_PLLCON1_REFDIV_MASK 0x3f +#define RK3036_PLLCON1_REFDIV_SHIFT 0 +#define RK3036_PLLCON1_POSTDIV2_MASK 0x7 +#define RK3036_PLLCON1_POSTDIV2_SHIFT 6 +#define RK3036_PLLCON1_LOCK_STATUS BIT(10) +#define RK3036_PLLCON1_DSMPD_MASK 0x1 +#define RK3036_PLLCON1_DSMPD_SHIFT 12 +#define RK3036_PLLCON1_PWRDOWN BIT(13) +#define RK3036_PLLCON2_FRAC_MASK 0xffffff +#define RK3036_PLLCON2_FRAC_SHIFT 0 + +static int rockchip_rk3036_pll_wait_lock(struct rockchip_clk_pll *pll) +{ + u32 pllcon; + int ret; + + /* + * Lock time typical 250, max 500 input clock cycles @24MHz + * So define a very safe maximum of 1000us, meaning 24000 cycles. + */ + ret = readl_poll_timeout(pll->reg_base + RK3036_PLLCON(1), + pllcon, + pllcon & RK3036_PLLCON1_LOCK_STATUS, + 1000); + if (ret) + pr_err("%s: timeout waiting for pll to lock\n", __func__); + + return ret; +} + +static void rockchip_rk3036_pll_get_params(struct rockchip_clk_pll *pll, + struct rockchip_pll_rate_table *rate) +{ + u32 pllcon; + + pllcon = readl_relaxed(pll->reg_base + RK3036_PLLCON(0)); + rate->fbdiv = ((pllcon >> RK3036_PLLCON0_FBDIV_SHIFT) + & RK3036_PLLCON0_FBDIV_MASK); + rate->postdiv1 = ((pllcon >> RK3036_PLLCON0_POSTDIV1_SHIFT) + & RK3036_PLLCON0_POSTDIV1_MASK); + + pllcon = readl_relaxed(pll->reg_base + RK3036_PLLCON(1)); + rate->refdiv = ((pllcon >> RK3036_PLLCON1_REFDIV_SHIFT) + & RK3036_PLLCON1_REFDIV_MASK); + rate->postdiv2 = ((pllcon >> RK3036_PLLCON1_POSTDIV2_SHIFT) + & RK3036_PLLCON1_POSTDIV2_MASK); + rate->dsmpd = ((pllcon >> RK3036_PLLCON1_DSMPD_SHIFT) + & RK3036_PLLCON1_DSMPD_MASK); + + pllcon = readl_relaxed(pll->reg_base + RK3036_PLLCON(2)); + rate->frac = ((pllcon >> RK3036_PLLCON2_FRAC_SHIFT) + & RK3036_PLLCON2_FRAC_MASK); +} + +static unsigned long rockchip_rk3036_pll_recalc_rate(struct clk_hw *hw, + unsigned long prate) +{ + struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw); + struct rockchip_pll_rate_table cur; + u64 rate64 = prate; + + rockchip_rk3036_pll_get_params(pll, &cur); + + rate64 *= cur.fbdiv; + do_div(rate64, cur.refdiv); + + if (cur.dsmpd == 0) { + /* fractional mode */ + u64 frac_rate64 = prate * cur.frac; + + do_div(frac_rate64, cur.refdiv); + rate64 += frac_rate64 >> 24; + } + + do_div(rate64, cur.postdiv1); + do_div(rate64, cur.postdiv2); + + return (unsigned long)rate64; +} + +static int rockchip_rk3036_pll_set_params(struct rockchip_clk_pll *pll, + const struct rockchip_pll_rate_table *rate) +{ + const struct clk_ops *pll_mux_ops = pll->pll_mux_ops; + struct clk_mux *pll_mux = &pll->pll_mux; + struct rockchip_pll_rate_table cur; + u32 pllcon; + int rate_change_remuxed = 0; + int cur_parent; + int ret; + + pr_debug("%s: rate settings for %lu fbdiv: %d, postdiv1: %d, refdiv: %d, postdiv2: %d, dsmpd: %d, frac: %d\n", + __func__, rate->rate, rate->fbdiv, rate->postdiv1, rate->refdiv, + rate->postdiv2, rate->dsmpd, rate->frac); + + rockchip_rk3036_pll_get_params(pll, &cur); + cur.rate = 0; + + cur_parent = pll_mux_ops->get_parent(&pll_mux->hw); + if (cur_parent == PLL_MODE_NORM) { + pll_mux_ops->set_parent(&pll_mux->hw, PLL_MODE_SLOW); + rate_change_remuxed = 1; + } + + /* update pll values */ + writel_relaxed(HIWORD_UPDATE(rate->fbdiv, RK3036_PLLCON0_FBDIV_MASK, + RK3036_PLLCON0_FBDIV_SHIFT) | + HIWORD_UPDATE(rate->postdiv1, RK3036_PLLCON0_POSTDIV1_MASK, + RK3036_PLLCON0_POSTDIV1_SHIFT), + pll->reg_base + RK3036_PLLCON(0)); + + writel_relaxed(HIWORD_UPDATE(rate->refdiv, RK3036_PLLCON1_REFDIV_MASK, + RK3036_PLLCON1_REFDIV_SHIFT) | + HIWORD_UPDATE(rate->postdiv2, RK3036_PLLCON1_POSTDIV2_MASK, + RK3036_PLLCON1_POSTDIV2_SHIFT) | + HIWORD_UPDATE(rate->dsmpd, RK3036_PLLCON1_DSMPD_MASK, + RK3036_PLLCON1_DSMPD_SHIFT), + pll->reg_base + RK3036_PLLCON(1)); + + /* GPLL CON2 is not HIWORD_MASK */ + pllcon = readl_relaxed(pll->reg_base + RK3036_PLLCON(2)); + pllcon &= ~(RK3036_PLLCON2_FRAC_MASK << RK3036_PLLCON2_FRAC_SHIFT); + pllcon |= rate->frac << RK3036_PLLCON2_FRAC_SHIFT; + writel_relaxed(pllcon, pll->reg_base + RK3036_PLLCON(2)); /* wait for the pll to lock */ - while (delay > 0) { - val = readl(RK3188_PLL_LOCK_REG); - if (val & BIT(pll->lock_shift)) + ret = rockchip_rk3036_pll_wait_lock(pll); + if (ret) { + pr_warn("%s: pll update unsuccessful, trying to restore old params\n", + __func__); + rockchip_rk3036_pll_set_params(pll, &cur); + } + + if (rate_change_remuxed) + pll_mux_ops->set_parent(&pll_mux->hw, PLL_MODE_NORM); + + return ret; +} + +static int rockchip_rk3036_pll_set_rate(struct clk_hw *hw, unsigned long drate, + unsigned long prate) +{ + struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw); + const struct rockchip_pll_rate_table *rate; + + pr_debug("%s: changing %s to %lu with a parent rate of %lu\n", + __func__, clk_hw_get_name(hw), drate, prate); + + /* Get required rate settings from table */ + rate = rockchip_get_pll_settings(pll, drate); + if (!rate) { + pr_err("%s: Invalid rate : %lu for pll clk %s\n", __func__, + drate, clk_hw_get_name(hw)); + return -EINVAL; + } + + return rockchip_rk3036_pll_set_params(pll, rate); +} + +static int rockchip_rk3036_pll_enable(struct clk_hw *hw) +{ + struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw); + + writel(HIWORD_UPDATE(0, RK3036_PLLCON1_PWRDOWN, 0), + pll->reg_base + RK3036_PLLCON(1)); + rockchip_rk3036_pll_wait_lock(pll); + + return 0; +} + +static void rockchip_rk3036_pll_disable(struct clk_hw *hw) +{ + struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw); + + writel(HIWORD_UPDATE(RK3036_PLLCON1_PWRDOWN, + RK3036_PLLCON1_PWRDOWN, 0), + pll->reg_base + RK3036_PLLCON(1)); +} + +static int rockchip_rk3036_pll_is_enabled(struct clk_hw *hw) +{ + struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw); + u32 pllcon = readl(pll->reg_base + RK3036_PLLCON(1)); + + return !(pllcon & RK3036_PLLCON1_PWRDOWN); +} + +static int rockchip_rk3036_pll_init(struct clk_hw *hw) +{ + struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw); + const struct rockchip_pll_rate_table *rate; + struct rockchip_pll_rate_table cur; + unsigned long drate; + + if (!(pll->flags & ROCKCHIP_PLL_SYNC_RATE)) + return 0; + + drate = clk_hw_get_rate(hw); + rate = rockchip_get_pll_settings(pll, drate); + + /* when no rate setting for the current rate, rely on clk_set_rate */ + if (!rate) + return 0; + + rockchip_rk3036_pll_get_params(pll, &cur); + + pr_debug("%s: pll %s@%lu: Hz\n", __func__, clk_hw_get_name(hw), + drate); + pr_debug("old - fbdiv: %d, postdiv1: %d, refdiv: %d, postdiv2: %d, dsmpd: %d, frac: %d\n", + cur.fbdiv, cur.postdiv1, cur.refdiv, cur.postdiv2, + cur.dsmpd, cur.frac); + pr_debug("new - fbdiv: %d, postdiv1: %d, refdiv: %d, postdiv2: %d, dsmpd: %d, frac: %d\n", + rate->fbdiv, rate->postdiv1, rate->refdiv, rate->postdiv2, + rate->dsmpd, rate->frac); + + if (rate->fbdiv != cur.fbdiv || rate->postdiv1 != cur.postdiv1 || + rate->refdiv != cur.refdiv || rate->postdiv2 != cur.postdiv2 || + rate->dsmpd != cur.dsmpd || + (!cur.dsmpd && (rate->frac != cur.frac))) { + struct clk *parent = clk_get_parent(clk_hw_to_clk(hw)); + + if (!parent) { + pr_warn("%s: parent of %s not available\n", + __func__, clk_hw_get_name(hw)); return 0; - delay--; + } + + pr_debug("%s: pll %s: rate params do not match rate table, adjusting\n", + __func__, clk_hw_get_name(hw)); + rockchip_rk3036_pll_set_params(pll, rate); } - pr_err("%s: timeout waiting for pll to lock\n", __func__); - return -ETIMEDOUT; + return 0; } -/** +static const struct clk_ops rockchip_rk3036_pll_clk_norate_ops = { + .recalc_rate = rockchip_rk3036_pll_recalc_rate, + .enable = rockchip_rk3036_pll_enable, + .disable = rockchip_rk3036_pll_disable, + .is_enabled = rockchip_rk3036_pll_is_enabled, +}; + +static const struct clk_ops rockchip_rk3036_pll_clk_ops = { + .recalc_rate = rockchip_rk3036_pll_recalc_rate, + .round_rate = rockchip_pll_round_rate, + .set_rate = rockchip_rk3036_pll_set_rate, + .enable = rockchip_rk3036_pll_enable, + .disable = rockchip_rk3036_pll_disable, + .is_enabled = rockchip_rk3036_pll_is_enabled, + .init = rockchip_rk3036_pll_init, +}; + +/* * PLL used in RK3066, RK3188 and RK3288 */ @@ -106,75 +370,75 @@ static int rockchip_pll_wait_lock(struct rockchip_clk_pll *pll) #define RK3066_PLLCON0_NR_SHIFT 8 #define RK3066_PLLCON1_NF_MASK 0x1fff #define RK3066_PLLCON1_NF_SHIFT 0 -#define RK3066_PLLCON2_BWADJ_MASK 0xfff -#define RK3066_PLLCON2_BWADJ_SHIFT 0 +#define RK3066_PLLCON2_NB_MASK 0xfff +#define RK3066_PLLCON2_NB_SHIFT 0 #define RK3066_PLLCON3_RESET (1 << 5) #define RK3066_PLLCON3_PWRDOWN (1 << 1) #define RK3066_PLLCON3_BYPASS (1 << 0) -static unsigned long rockchip_rk3066_pll_recalc_rate(struct clk *hw, +static void rockchip_rk3066_pll_get_params(struct rockchip_clk_pll *pll, + struct rockchip_pll_rate_table *rate) +{ + u32 pllcon; + + pllcon = readl_relaxed(pll->reg_base + RK3066_PLLCON(0)); + rate->nr = ((pllcon >> RK3066_PLLCON0_NR_SHIFT) + & RK3066_PLLCON0_NR_MASK) + 1; + rate->no = ((pllcon >> RK3066_PLLCON0_OD_SHIFT) + & RK3066_PLLCON0_OD_MASK) + 1; + + pllcon = readl_relaxed(pll->reg_base + RK3066_PLLCON(1)); + rate->nf = ((pllcon >> RK3066_PLLCON1_NF_SHIFT) + & RK3066_PLLCON1_NF_MASK) + 1; + + pllcon = readl_relaxed(pll->reg_base + RK3066_PLLCON(2)); + rate->nb = ((pllcon >> RK3066_PLLCON2_NB_SHIFT) + & RK3066_PLLCON2_NB_MASK) + 1; +} + +static unsigned long rockchip_rk3066_pll_recalc_rate(struct clk_hw *hw, unsigned long prate) { struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw); - u64 nf, nr, no, rate64 = prate; + struct rockchip_pll_rate_table cur; + u64 rate64 = prate; u32 pllcon; - pllcon = readl(pll->reg_base + RK3066_PLLCON(3)); + pllcon = readl_relaxed(pll->reg_base + RK3066_PLLCON(3)); if (pllcon & RK3066_PLLCON3_BYPASS) { pr_debug("%s: pll %s is bypassed\n", __func__, - __clk_get_name(hw)); + clk_hw_get_name(hw)); return prate; } - pllcon = readl(pll->reg_base + RK3066_PLLCON(1)); - nf = (pllcon >> RK3066_PLLCON1_NF_SHIFT) & RK3066_PLLCON1_NF_MASK; - - pllcon = readl(pll->reg_base + RK3066_PLLCON(0)); - nr = (pllcon >> RK3066_PLLCON0_NR_SHIFT) & RK3066_PLLCON0_NR_MASK; - no = (pllcon >> RK3066_PLLCON0_OD_SHIFT) & RK3066_PLLCON0_OD_MASK; + rockchip_rk3066_pll_get_params(pll, &cur); - rate64 *= (nf + 1); - do_div(rate64, nr + 1); - do_div(rate64, no + 1); - - pr_debug("%s: %s rate=%lu\n", - __func__, hw->name, (unsigned long)rate64); + rate64 *= cur.nf; + do_div(rate64, cur.nr); + do_div(rate64, cur.no); return (unsigned long)rate64; } -static int rockchip_rk3066_pll_set_rate(struct clk *hw, unsigned long drate, - unsigned long prate) +static int rockchip_rk3066_pll_set_params(struct rockchip_clk_pll *pll, + const struct rockchip_pll_rate_table *rate) { - struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw); - const struct rockchip_pll_rate_table *rate; - unsigned long old_rate = rockchip_rk3066_pll_recalc_rate(hw, prate); - struct clk *pll_mux = &pll->pll_mux; const struct clk_ops *pll_mux_ops = pll->pll_mux_ops; + struct clk_mux *pll_mux = &pll->pll_mux; + struct rockchip_pll_rate_table cur; int rate_change_remuxed = 0; int cur_parent; int ret; - if (old_rate == drate) - return 0; - - pr_debug("%s: changing %s from %lu to %lu with a parent rate of %lu\n", - __func__, __clk_get_name(hw), old_rate, drate, prate); - - /* Get required rate settings from table */ - rate = rockchip_get_pll_settings(pll, drate); - if (!rate) { - pr_err("%s: Invalid rate : %lu for pll clk %s\n", __func__, - drate, __clk_get_name(hw)); - return -EINVAL; - } - pr_debug("%s: rate settings for %lu (nr, no, nf): (%d, %d, %d)\n", __func__, rate->rate, rate->nr, rate->no, rate->nf); - cur_parent = pll_mux_ops->get_parent(pll_mux); + rockchip_rk3066_pll_get_params(pll, &cur); + cur.rate = 0; + + cur_parent = pll_mux_ops->get_parent(&pll_mux->hw); if (cur_parent == PLL_MODE_NORM) { - pll_mux_ops->set_parent(pll_mux, PLL_MODE_SLOW); + pll_mux_ops->set_parent(&pll_mux->hw, PLL_MODE_SLOW); rate_change_remuxed = 1; } @@ -189,11 +453,11 @@ static int rockchip_rk3066_pll_set_rate(struct clk *hw, unsigned long drate, RK3066_PLLCON0_OD_SHIFT), pll->reg_base + RK3066_PLLCON(0)); - writel(HIWORD_UPDATE(rate->nf - 1, RK3066_PLLCON1_NF_MASK, + writel_relaxed(HIWORD_UPDATE(rate->nf - 1, RK3066_PLLCON1_NF_MASK, RK3066_PLLCON1_NF_SHIFT), pll->reg_base + RK3066_PLLCON(1)); - writel(HIWORD_UPDATE(rate->bwadj, RK3066_PLLCON2_BWADJ_MASK, - RK3066_PLLCON2_BWADJ_SHIFT), + writel_relaxed(HIWORD_UPDATE(rate->nb - 1, RK3066_PLLCON2_NB_MASK, + RK3066_PLLCON2_NB_SHIFT), pll->reg_base + RK3066_PLLCON(2)); /* leave reset and wait the reset_delay */ @@ -204,28 +468,49 @@ static int rockchip_rk3066_pll_set_rate(struct clk *hw, unsigned long drate, /* wait for the pll to lock */ ret = rockchip_pll_wait_lock(pll); if (ret) { - pr_warn("%s: pll did not lock, trying to restore old rate %lu\n", - __func__, old_rate); - rockchip_rk3066_pll_set_rate(hw, old_rate, prate); + pr_warn("%s: pll update unsuccessful, trying to restore old params\n", + __func__); + rockchip_rk3066_pll_set_params(pll, &cur); } if (rate_change_remuxed) - pll_mux_ops->set_parent(pll_mux, PLL_MODE_NORM); + pll_mux_ops->set_parent(&pll_mux->hw, PLL_MODE_NORM); return ret; } -static int rockchip_rk3066_pll_enable(struct clk *hw) +static int rockchip_rk3066_pll_set_rate(struct clk_hw *hw, unsigned long drate, + unsigned long prate) +{ + struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw); + const struct rockchip_pll_rate_table *rate; + + pr_debug("%s: changing %s to %lu with a parent rate of %lu\n", + __func__, clk_hw_get_name(hw), drate, prate); + + /* Get required rate settings from table */ + rate = rockchip_get_pll_settings(pll, drate); + if (!rate) { + pr_err("%s: Invalid rate : %lu for pll clk %s\n", __func__, + drate, clk_hw_get_name(hw)); + return -EINVAL; + } + + return rockchip_rk3066_pll_set_params(pll, rate); +} + +static int rockchip_rk3066_pll_enable(struct clk_hw *hw) { struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw); writel(HIWORD_UPDATE(0, RK3066_PLLCON3_PWRDOWN, 0), pll->reg_base + RK3066_PLLCON(3)); + rockchip_pll_wait_lock(pll); return 0; } -static void rockchip_rk3066_pll_disable(struct clk *hw) +static void rockchip_rk3066_pll_disable(struct clk_hw *hw) { struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw); @@ -234,7 +519,7 @@ static void rockchip_rk3066_pll_disable(struct clk *hw) pll->reg_base + RK3066_PLLCON(3)); } -static int rockchip_rk3066_pll_is_enabled(struct clk *hw) +static int rockchip_rk3066_pll_is_enabled(struct clk_hw *hw) { struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw); u32 pllcon = readl(pll->reg_base + RK3066_PLLCON(3)); @@ -242,6 +527,38 @@ static int rockchip_rk3066_pll_is_enabled(struct clk *hw) return !(pllcon & RK3066_PLLCON3_PWRDOWN); } +static int rockchip_rk3066_pll_init(struct clk_hw *hw) +{ + struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw); + const struct rockchip_pll_rate_table *rate; + struct rockchip_pll_rate_table cur; + unsigned long drate; + + if (!(pll->flags & ROCKCHIP_PLL_SYNC_RATE)) + return 0; + + drate = clk_hw_get_rate(hw); + rate = rockchip_get_pll_settings(pll, drate); + + /* when no rate setting for the current rate, rely on clk_set_rate */ + if (!rate) + return 0; + + rockchip_rk3066_pll_get_params(pll, &cur); + + pr_debug("%s: pll %s@%lu: nr (%d:%d); no (%d:%d); nf(%d:%d), nb(%d:%d)\n", + __func__, clk_hw_get_name(hw), drate, rate->nr, cur.nr, + rate->no, cur.no, rate->nf, cur.nf, rate->nb, cur.nb); + if (rate->nr != cur.nr || rate->no != cur.no || rate->nf != cur.nf + || rate->nb != cur.nb) { + pr_debug("%s: pll %s: rate params do not match rate table, adjusting\n", + __func__, clk_hw_get_name(hw)); + rockchip_rk3066_pll_set_params(pll, rate); + } + + return 0; +} + static const struct clk_ops rockchip_rk3066_pll_clk_norate_ops = { .recalc_rate = rockchip_rk3066_pll_recalc_rate, .enable = rockchip_rk3066_pll_enable, @@ -256,44 +573,351 @@ static const struct clk_ops rockchip_rk3066_pll_clk_ops = { .enable = rockchip_rk3066_pll_enable, .disable = rockchip_rk3066_pll_disable, .is_enabled = rockchip_rk3066_pll_is_enabled, + .init = rockchip_rk3066_pll_init, +}; + +/* + * PLL used in RK3399 + */ + +#define RK3399_PLLCON(i) (i * 0x4) +#define RK3399_PLLCON0_FBDIV_MASK 0xfff +#define RK3399_PLLCON0_FBDIV_SHIFT 0 +#define RK3399_PLLCON1_REFDIV_MASK 0x3f +#define RK3399_PLLCON1_REFDIV_SHIFT 0 +#define RK3399_PLLCON1_POSTDIV1_MASK 0x7 +#define RK3399_PLLCON1_POSTDIV1_SHIFT 8 +#define RK3399_PLLCON1_POSTDIV2_MASK 0x7 +#define RK3399_PLLCON1_POSTDIV2_SHIFT 12 +#define RK3399_PLLCON2_FRAC_MASK 0xffffff +#define RK3399_PLLCON2_FRAC_SHIFT 0 +#define RK3399_PLLCON2_LOCK_STATUS BIT(31) +#define RK3399_PLLCON3_PWRDOWN BIT(0) +#define RK3399_PLLCON3_DSMPD_MASK 0x1 +#define RK3399_PLLCON3_DSMPD_SHIFT 3 + +static int rockchip_rk3399_pll_wait_lock(struct rockchip_clk_pll *pll) +{ + u32 pllcon; + int ret; + + /* + * Lock time typical 250, max 500 input clock cycles @24MHz + * So define a very safe maximum of 1000us, meaning 24000 cycles. + */ + ret = readl_relaxed_poll_timeout(pll->reg_base + RK3399_PLLCON(2), + pllcon, + pllcon & RK3399_PLLCON2_LOCK_STATUS, + 1000); + if (ret) + pr_err("%s: timeout waiting for pll to lock\n", __func__); + + return ret; +} + +static void rockchip_rk3399_pll_get_params(struct rockchip_clk_pll *pll, + struct rockchip_pll_rate_table *rate) +{ + u32 pllcon; + + pllcon = readl_relaxed(pll->reg_base + RK3399_PLLCON(0)); + rate->fbdiv = ((pllcon >> RK3399_PLLCON0_FBDIV_SHIFT) + & RK3399_PLLCON0_FBDIV_MASK); + + pllcon = readl_relaxed(pll->reg_base + RK3399_PLLCON(1)); + rate->refdiv = ((pllcon >> RK3399_PLLCON1_REFDIV_SHIFT) + & RK3399_PLLCON1_REFDIV_MASK); + rate->postdiv1 = ((pllcon >> RK3399_PLLCON1_POSTDIV1_SHIFT) + & RK3399_PLLCON1_POSTDIV1_MASK); + rate->postdiv2 = ((pllcon >> RK3399_PLLCON1_POSTDIV2_SHIFT) + & RK3399_PLLCON1_POSTDIV2_MASK); + + pllcon = readl_relaxed(pll->reg_base + RK3399_PLLCON(2)); + rate->frac = ((pllcon >> RK3399_PLLCON2_FRAC_SHIFT) + & RK3399_PLLCON2_FRAC_MASK); + + pllcon = readl_relaxed(pll->reg_base + RK3399_PLLCON(3)); + rate->dsmpd = ((pllcon >> RK3399_PLLCON3_DSMPD_SHIFT) + & RK3399_PLLCON3_DSMPD_MASK); +} + +static unsigned long rockchip_rk3399_pll_recalc_rate(struct clk_hw *hw, + unsigned long prate) +{ + struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw); + struct rockchip_pll_rate_table cur; + u64 rate64 = prate; + + rockchip_rk3399_pll_get_params(pll, &cur); + + rate64 *= cur.fbdiv; + do_div(rate64, cur.refdiv); + + if (cur.dsmpd == 0) { + /* fractional mode */ + u64 frac_rate64 = prate * cur.frac; + + do_div(frac_rate64, cur.refdiv); + rate64 += frac_rate64 >> 24; + } + + do_div(rate64, cur.postdiv1); + do_div(rate64, cur.postdiv2); + + return (unsigned long)rate64; +} + +static int rockchip_rk3399_pll_set_params(struct rockchip_clk_pll *pll, + const struct rockchip_pll_rate_table *rate) +{ + const struct clk_ops *pll_mux_ops = pll->pll_mux_ops; + struct clk_mux *pll_mux = &pll->pll_mux; + struct rockchip_pll_rate_table cur; + u32 pllcon; + int rate_change_remuxed = 0; + int cur_parent; + int ret; + + pr_debug("%s: rate settings for %lu fbdiv: %d, postdiv1: %d, refdiv: %d, postdiv2: %d, dsmpd: %d, frac: %d\n", + __func__, rate->rate, rate->fbdiv, rate->postdiv1, rate->refdiv, + rate->postdiv2, rate->dsmpd, rate->frac); + + rockchip_rk3399_pll_get_params(pll, &cur); + cur.rate = 0; + + cur_parent = pll_mux_ops->get_parent(&pll_mux->hw); + if (cur_parent == PLL_MODE_NORM) { + pll_mux_ops->set_parent(&pll_mux->hw, PLL_MODE_SLOW); + rate_change_remuxed = 1; + } + + /* update pll values */ + writel_relaxed(HIWORD_UPDATE(rate->fbdiv, RK3399_PLLCON0_FBDIV_MASK, + RK3399_PLLCON0_FBDIV_SHIFT), + pll->reg_base + RK3399_PLLCON(0)); + + writel_relaxed(HIWORD_UPDATE(rate->refdiv, RK3399_PLLCON1_REFDIV_MASK, + RK3399_PLLCON1_REFDIV_SHIFT) | + HIWORD_UPDATE(rate->postdiv1, RK3399_PLLCON1_POSTDIV1_MASK, + RK3399_PLLCON1_POSTDIV1_SHIFT) | + HIWORD_UPDATE(rate->postdiv2, RK3399_PLLCON1_POSTDIV2_MASK, + RK3399_PLLCON1_POSTDIV2_SHIFT), + pll->reg_base + RK3399_PLLCON(1)); + + /* xPLL CON2 is not HIWORD_MASK */ + pllcon = readl_relaxed(pll->reg_base + RK3399_PLLCON(2)); + pllcon &= ~(RK3399_PLLCON2_FRAC_MASK << RK3399_PLLCON2_FRAC_SHIFT); + pllcon |= rate->frac << RK3399_PLLCON2_FRAC_SHIFT; + writel_relaxed(pllcon, pll->reg_base + RK3399_PLLCON(2)); + + writel_relaxed(HIWORD_UPDATE(rate->dsmpd, RK3399_PLLCON3_DSMPD_MASK, + RK3399_PLLCON3_DSMPD_SHIFT), + pll->reg_base + RK3399_PLLCON(3)); + + /* wait for the pll to lock */ + ret = rockchip_rk3399_pll_wait_lock(pll); + if (ret) { + pr_warn("%s: pll update unsuccessful, trying to restore old params\n", + __func__); + rockchip_rk3399_pll_set_params(pll, &cur); + } + + if (rate_change_remuxed) + pll_mux_ops->set_parent(&pll_mux->hw, PLL_MODE_NORM); + + return ret; +} + +static int rockchip_rk3399_pll_set_rate(struct clk_hw *hw, unsigned long drate, + unsigned long prate) +{ + struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw); + const struct rockchip_pll_rate_table *rate; + + pr_debug("%s: changing %s to %lu with a parent rate of %lu\n", + __func__, clk_hw_get_name(hw), drate, prate); + + /* Get required rate settings from table */ + rate = rockchip_get_pll_settings(pll, drate); + if (!rate) { + pr_err("%s: Invalid rate : %lu for pll clk %s\n", __func__, + drate, clk_hw_get_name(hw)); + return -EINVAL; + } + + return rockchip_rk3399_pll_set_params(pll, rate); +} + +static int rockchip_rk3399_pll_enable(struct clk_hw *hw) +{ + struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw); + + writel(HIWORD_UPDATE(0, RK3399_PLLCON3_PWRDOWN, 0), + pll->reg_base + RK3399_PLLCON(3)); + rockchip_rk3399_pll_wait_lock(pll); + + return 0; +} + +static void rockchip_rk3399_pll_disable(struct clk_hw *hw) +{ + struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw); + + writel(HIWORD_UPDATE(RK3399_PLLCON3_PWRDOWN, + RK3399_PLLCON3_PWRDOWN, 0), + pll->reg_base + RK3399_PLLCON(3)); +} + +static int rockchip_rk3399_pll_is_enabled(struct clk_hw *hw) +{ + struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw); + u32 pllcon = readl(pll->reg_base + RK3399_PLLCON(3)); + + return !(pllcon & RK3399_PLLCON3_PWRDOWN); +} + +static int rockchip_rk3399_pll_init(struct clk_hw *hw) +{ + struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw); + const struct rockchip_pll_rate_table *rate; + struct rockchip_pll_rate_table cur; + unsigned long drate; + + if (!(pll->flags & ROCKCHIP_PLL_SYNC_RATE)) + return 0; + + drate = clk_hw_get_rate(hw); + rate = rockchip_get_pll_settings(pll, drate); + + /* when no rate setting for the current rate, rely on clk_set_rate */ + if (!rate) + return 0; + + rockchip_rk3399_pll_get_params(pll, &cur); + + pr_debug("%s: pll %s@%lu: Hz\n", __func__, clk_hw_get_name(hw), + drate); + pr_debug("old - fbdiv: %d, postdiv1: %d, refdiv: %d, postdiv2: %d, dsmpd: %d, frac: %d\n", + cur.fbdiv, cur.postdiv1, cur.refdiv, cur.postdiv2, + cur.dsmpd, cur.frac); + pr_debug("new - fbdiv: %d, postdiv1: %d, refdiv: %d, postdiv2: %d, dsmpd: %d, frac: %d\n", + rate->fbdiv, rate->postdiv1, rate->refdiv, rate->postdiv2, + rate->dsmpd, rate->frac); + + if (rate->fbdiv != cur.fbdiv || rate->postdiv1 != cur.postdiv1 || + rate->refdiv != cur.refdiv || rate->postdiv2 != cur.postdiv2 || + rate->dsmpd != cur.dsmpd || + (!cur.dsmpd && (rate->frac != cur.frac))) { + struct clk *parent = clk_get_parent(clk_hw_to_clk(hw)); + + if (!parent) { + pr_warn("%s: parent of %s not available\n", + __func__, clk_hw_get_name(hw)); + return 0; + } + + pr_debug("%s: pll %s: rate params do not match rate table, adjusting\n", + __func__, clk_hw_get_name(hw)); + rockchip_rk3399_pll_set_params(pll, rate); + } + + return 0; +} + +static const struct clk_ops rockchip_rk3399_pll_clk_norate_ops = { + .recalc_rate = rockchip_rk3399_pll_recalc_rate, + .enable = rockchip_rk3399_pll_enable, + .disable = rockchip_rk3399_pll_disable, + .is_enabled = rockchip_rk3399_pll_is_enabled, +}; + +static const struct clk_ops rockchip_rk3399_pll_clk_ops = { + .recalc_rate = rockchip_rk3399_pll_recalc_rate, + .round_rate = rockchip_pll_round_rate, + .set_rate = rockchip_rk3399_pll_set_rate, + .enable = rockchip_rk3399_pll_enable, + .disable = rockchip_rk3399_pll_disable, + .is_enabled = rockchip_rk3399_pll_is_enabled, + .init = rockchip_rk3399_pll_init, }; /* * Common registering of pll clocks */ -struct clk *rockchip_clk_register_pll(enum rockchip_pll_type pll_type, - const char *name, const char **parent_names, u8 num_parents, - void __iomem *base, int con_offset, int grf_lock_offset, +struct clk *rockchip_clk_register_pll(struct rockchip_clk_provider *ctx, + enum rockchip_pll_type pll_type, + const char *name, const char *const *parent_names, + u8 num_parents, int con_offset, int grf_lock_offset, int lock_shift, int mode_offset, int mode_shift, struct rockchip_pll_rate_table *rate_table, - u8 clk_pll_flags) + unsigned long flags, u8 clk_pll_flags) { - const char **pll_parents; + const char *pll_parents[3]; + struct clk_init_data init; struct rockchip_clk_pll *pll; - struct clk *pll_mux; - struct clk *mux_clk; - int ret; + struct clk_mux *pll_mux; + struct clk *pll_clk, *mux_clk; + char pll_name[20]; - if (num_parents != 2) { + if ((pll_type != pll_rk3328 && num_parents != 2) || + (pll_type == pll_rk3328 && num_parents != 1)) { pr_err("%s: needs two parent clocks\n", __func__); return ERR_PTR(-EINVAL); } + /* name the actual pll */ + snprintf(pll_name, sizeof(pll_name), "pll_%s", name); + pll = kzalloc(sizeof(*pll), GFP_KERNEL); if (!pll) return ERR_PTR(-ENOMEM); - pll_parents = kzalloc(sizeof(char *)*3, GFP_KERNEL); - if (!pll_parents) - return ERR_PTR(-ENOMEM); + /* create the mux on top of the real pll */ + pll->pll_mux_ops = &clk_mux_ops; + pll_mux = &pll->pll_mux; + pll_mux->reg = ctx->reg_base + mode_offset; + pll_mux->shift = mode_shift; + if (pll_type == pll_rk3328) + pll_mux->width = PLL_RK3328_MODE_WIDTH; + else + pll_mux->width = PLL_MODE_WIDTH; + pll_mux->flags = 0; + pll_mux->lock = &ctx->lock; + pll_mux->hw.init = &init; + + if (pll_type == pll_rk3036 || + pll_type == pll_rk3066 || + pll_type == pll_rk3328 || + pll_type == pll_rk3399) + pll_mux->flags |= CLK_MUX_HIWORD_MASK; - /* name the actual pll */ - snprintf(pll->pll_name, sizeof(pll->pll_name), "pll_%s", name); - pll->hw.name = pll->pll_name; + /* the actual muxing is xin24m, pll-output, xin32k */ + pll_parents[0] = parent_names[0]; + pll_parents[1] = pll_name; + pll_parents[2] = parent_names[1]; + + init.name = name; + init.flags = CLK_SET_RATE_PARENT; + init.ops = pll->pll_mux_ops; + init.parent_names = pll_parents; + if (pll_type == pll_rk3328) + init.num_parents = 2; + else + init.num_parents = ARRAY_SIZE(pll_parents); - pll->hw.parent_names = &parent_names[0]; - pll->hw.num_parents = 1; + mux_clk = clk_register(NULL, &pll_mux->hw); + if (IS_ERR(mux_clk)) + goto err_mux; + + /* now create the actual pll */ + init.name = pll_name; + + /* keep all plls untouched for now */ + init.flags = flags | CLK_IGNORE_UNUSED; + + init.parent_names = &parent_names[0]; + init.num_parents = 1; if (rate_table) { int len; @@ -303,61 +927,62 @@ struct clk *rockchip_clk_register_pll(enum rockchip_pll_type pll_type, len++; pll->rate_count = len; - pll->rate_table = xmemdup(rate_table, + pll->rate_table = kmemdup(rate_table, pll->rate_count * - sizeof(struct rockchip_pll_rate_table) - ); + sizeof(struct rockchip_pll_rate_table), + GFP_KERNEL); WARN(!pll->rate_table, "%s: could not allocate rate table for %s\n", __func__, name); } switch (pll_type) { + case pll_rk3036: + case pll_rk3328: + if (!pll->rate_table || IS_ERR(ctx->grf)) + init.ops = &rockchip_rk3036_pll_clk_norate_ops; + else + init.ops = &rockchip_rk3036_pll_clk_ops; + break; case pll_rk3066: + if (!pll->rate_table || IS_ERR(ctx->grf)) + init.ops = &rockchip_rk3066_pll_clk_norate_ops; + else + init.ops = &rockchip_rk3066_pll_clk_ops; + break; + case pll_rk3399: if (!pll->rate_table) - pll->hw.ops = &rockchip_rk3066_pll_clk_norate_ops; + init.ops = &rockchip_rk3399_pll_clk_norate_ops; else - pll->hw.ops = &rockchip_rk3066_pll_clk_ops; + init.ops = &rockchip_rk3399_pll_clk_ops; break; default: pr_warn("%s: Unknown pll type for pll clk %s\n", __func__, name); } + pll->hw.init = &init; pll->type = pll_type; - pll->reg_base = base + con_offset; + pll->reg_base = ctx->reg_base + con_offset; pll->lock_offset = grf_lock_offset; pll->lock_shift = lock_shift; pll->flags = clk_pll_flags; - - ret = clk_register(&pll->hw); - if (ret) { - pr_err("%s: failed to register pll clock %s : %d\n", - __func__, name, ret); - mux_clk = &pll->hw; - goto err_exit; + pll->lock = &ctx->lock; + pll->ctx = ctx; + + pll_clk = clk_register(NULL, &pll->hw); + if (IS_ERR(pll_clk)) { + pr_err("%s: failed to register pll clock %s : %ld\n", + __func__, name, PTR_ERR(pll_clk)); + goto err_pll; } - /* the actual muxing is xin24m, pll-output, xin32k */ - pll_parents[0] = parent_names[0]; - pll_parents[1] = pll->pll_name; - pll_parents[2] = parent_names[1]; - - pll_mux = clk_mux_alloc(name, CLK_SET_RATE_PARENT, base + mode_offset, mode_shift, - PLL_MODE_MASK, pll_parents, 3, 0); - pll->pll_mux_ops = pll_mux->ops; - mux_clk = pll_mux; - - if (pll_type == pll_rk3066) - pll_mux->flags |= CLK_MUX_HIWORD_MASK; - - ret = clk_register(pll_mux); - if (ret) - goto err_exit; - return mux_clk; -err_exit: +err_pll: + clk_unregister(mux_clk); + mux_clk = pll_clk; +err_mux: kfree(pll); return mux_clk; } diff --git a/drivers/clk/rockchip/clk-rk3188.c b/drivers/clk/rockchip/clk-rk3188.c index 61dfb27ef4..8597a9d229 100644 --- a/drivers/clk/rockchip/clk-rk3188.c +++ b/drivers/clk/rockchip/clk-rk3188.c @@ -20,7 +20,7 @@ enum rk3188_plls { apll, cpll, dpll, gpll, }; -struct rockchip_pll_rate_table rk3188_pll_rates[] = { +static struct rockchip_pll_rate_table rk3188_pll_rates[] = { RK3066_PLL_RATE(2208000000, 1, 92, 1), RK3066_PLL_RATE(2184000000, 1, 91, 1), RK3066_PLL_RATE(2160000000, 1, 90, 1), @@ -82,6 +82,7 @@ struct rockchip_pll_rate_table rk3188_pll_rates[] = { RK3066_PLL_RATE( 504000000, 1, 84, 4), RK3066_PLL_RATE( 456000000, 1, 76, 4), RK3066_PLL_RATE( 408000000, 1, 68, 4), + RK3066_PLL_RATE( 400000000, 3, 100, 2), RK3066_PLL_RATE( 384000000, 2, 128, 4), RK3066_PLL_RATE( 360000000, 1, 60, 4), RK3066_PLL_RATE( 312000000, 1, 52, 4), @@ -145,10 +146,14 @@ static struct rockchip_cpuclk_rate_table rk3066_cpuclk_rates[] __initdata = { }; static const struct rockchip_cpuclk_reg_data rk3066_cpuclk_data = { - .core_reg = RK2928_CLKSEL_CON(0), - .div_core_shift = 0, - .div_core_mask = 0x1f, + .core_reg[0] = RK2928_CLKSEL_CON(0), + .div_core_shift[0] = 0, + .div_core_mask[0] = 0x1f, + .num_cores = 1, + .mux_core_alt = 1, + .mux_core_main = 0, .mux_core_shift = 8, + .mux_core_mask = 0x1, }; #define RK3188_DIV_ACLK_CORE_MASK 0x7 @@ -181,10 +186,14 @@ static struct rockchip_cpuclk_rate_table rk3188_cpuclk_rates[] __initdata = { }; static const struct rockchip_cpuclk_reg_data rk3188_cpuclk_data = { - .core_reg = RK2928_CLKSEL_CON(0), - .div_core_shift = 9, - .div_core_mask = 0x1f, + .core_reg[0] = RK2928_CLKSEL_CON(0), + .div_core_shift[0] = 9, + .div_core_mask[0] = 0x1f, + .num_cores = 1, + .mux_core_alt = 1, + .mux_core_main = 0, .mux_core_shift = 8, + .mux_core_mask = 0x1, }; PNAME(mux_pll_p) = { "xin24m", "xin32k" }; @@ -195,7 +204,7 @@ PNAME(mux_pll_src_cpll_gpll_p) = { "cpll", "gpll" }; PNAME(mux_aclk_cpu_p) = { "apll", "gpll" }; PNAME(mux_sclk_cif0_p) = { "cif0_pre", "xin24m" }; PNAME(mux_sclk_i2s0_p) = { "i2s0_pre", "i2s0_frac", "xin12m" }; -PNAME(mux_sclk_spdif_p) = { "spdif_src", "spdif_frac", "xin12m" }; +PNAME(mux_sclk_spdif_p) = { "spdif_pre", "spdif_frac", "xin12m" }; PNAME(mux_sclk_uart0_p) = { "uart0_pre", "uart0_frac", "xin24m" }; PNAME(mux_sclk_uart1_p) = { "uart1_pre", "uart1_frac", "xin24m" }; PNAME(mux_sclk_uart2_p) = { "uart2_pre", "uart2_frac", "xin24m" }; @@ -229,6 +238,7 @@ static struct rockchip_pll_clock rk3188_pll_clks[] __initdata = { #define MFLAGS CLK_MUX_HIWORD_MASK #define DFLAGS CLK_DIVIDER_HIWORD_MASK #define GFLAGS (CLK_GATE_HIWORD_MASK | CLK_GATE_SET_TO_DISABLE) +#define IFLAGS ROCKCHIP_INVERTER_HIWORD_MASK /* 2 ^ (val + 1) */ static struct clk_div_table div_core_peri_t[] = { @@ -239,6 +249,30 @@ static struct clk_div_table div_core_peri_t[] = { { /* sentinel */ }, }; +static struct rockchip_clk_branch common_hsadc_out_fracmux __initdata = + MUX(0, "sclk_hsadc_out", mux_sclk_hsadc_p, 0, + RK2928_CLKSEL_CON(22), 4, 2, MFLAGS); + +static struct rockchip_clk_branch common_spdif_fracmux __initdata = + MUX(SCLK_SPDIF, "sclk_spdif", mux_sclk_spdif_p, CLK_SET_RATE_PARENT, + RK2928_CLKSEL_CON(5), 8, 2, MFLAGS); + +static struct rockchip_clk_branch common_uart0_fracmux __initdata = + MUX(SCLK_UART0, "sclk_uart0", mux_sclk_uart0_p, CLK_SET_RATE_PARENT, + RK2928_CLKSEL_CON(13), 8, 2, MFLAGS); + +static struct rockchip_clk_branch common_uart1_fracmux __initdata = + MUX(SCLK_UART1, "sclk_uart1", mux_sclk_uart1_p, CLK_SET_RATE_PARENT, + RK2928_CLKSEL_CON(14), 8, 2, MFLAGS); + +static struct rockchip_clk_branch common_uart2_fracmux __initdata = + MUX(SCLK_UART2, "sclk_uart2", mux_sclk_uart2_p, CLK_SET_RATE_PARENT, + RK2928_CLKSEL_CON(15), 8, 2, MFLAGS); + +static struct rockchip_clk_branch common_uart3_fracmux __initdata = + MUX(SCLK_UART3, "sclk_uart3", mux_sclk_uart3_p, CLK_SET_RATE_PARENT, + RK2928_CLKSEL_CON(16), 8, 2, MFLAGS); + static struct rockchip_clk_branch common_clk_branches[] __initdata = { /* * Clock-Architecture Diagram 2 @@ -251,15 +285,15 @@ static struct rockchip_clk_branch common_clk_branches[] __initdata = { RK2928_CLKSEL_CON(0), 6, 2, DFLAGS | CLK_DIVIDER_READ_ONLY, div_core_peri_t, RK2928_CLKGATE_CON(0), 0, GFLAGS), - COMPOSITE(0, "aclk_vepu", mux_pll_src_cpll_gpll_p, 0, + COMPOSITE(ACLK_VEPU, "aclk_vepu", mux_pll_src_cpll_gpll_p, 0, RK2928_CLKSEL_CON(32), 7, 1, MFLAGS, 0, 5, DFLAGS, RK2928_CLKGATE_CON(3), 9, GFLAGS), - GATE(0, "hclk_vepu", "aclk_vepu", 0, + GATE(HCLK_VEPU, "hclk_vepu", "aclk_vepu", 0, RK2928_CLKGATE_CON(3), 10, GFLAGS), - COMPOSITE(0, "aclk_vdpu", mux_pll_src_cpll_gpll_p, 0, + COMPOSITE(ACLK_VDPU, "aclk_vdpu", mux_pll_src_cpll_gpll_p, 0, RK2928_CLKSEL_CON(32), 15, 1, MFLAGS, 8, 5, DFLAGS, RK2928_CLKGATE_CON(3), 11, GFLAGS), - GATE(0, "hclk_vdpu", "aclk_vdpu", 0, + GATE(HCLK_VDPU, "hclk_vdpu", "aclk_vdpu", 0, RK2928_CLKGATE_CON(3), 12, GFLAGS), GATE(0, "gpll_ddr", "gpll", CLK_IGNORE_UNUSED, @@ -268,14 +302,14 @@ static struct rockchip_clk_branch common_clk_branches[] __initdata = { RK2928_CLKSEL_CON(26), 8, 1, MFLAGS, 0, 2, DFLAGS | CLK_DIVIDER_POWER_OF_TWO, RK2928_CLKGATE_CON(0), 2, GFLAGS), - GATE(0, "aclk_cpu", "aclk_cpu_pre", 0, + GATE(ACLK_CPU, "aclk_cpu", "aclk_cpu_pre", 0, RK2928_CLKGATE_CON(0), 3, GFLAGS), GATE(0, "atclk_cpu", "pclk_cpu_pre", 0, RK2928_CLKGATE_CON(0), 6, GFLAGS), - GATE(0, "pclk_cpu", "pclk_cpu_pre", 0, + GATE(PCLK_CPU, "pclk_cpu", "pclk_cpu_pre", 0, RK2928_CLKGATE_CON(0), 5, GFLAGS), - GATE(0, "hclk_cpu", "hclk_cpu_pre", CLK_IGNORE_UNUSED, + GATE(HCLK_CPU, "hclk_cpu", "hclk_cpu_pre", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(0), 4, GFLAGS), COMPOSITE(0, "aclk_lcdc0_pre", mux_pll_src_cpll_gpll_p, CLK_IGNORE_UNUSED, @@ -285,12 +319,12 @@ static struct rockchip_clk_branch common_clk_branches[] __initdata = { RK2928_CLKSEL_CON(31), 15, 1, MFLAGS, 8, 5, DFLAGS, RK2928_CLKGATE_CON(1), 4, GFLAGS), - GATE(0, "aclk_peri", "aclk_peri_pre", 0, + GATE(ACLK_PERI, "aclk_peri", "aclk_peri_pre", 0, RK2928_CLKGATE_CON(2), 1, GFLAGS), - COMPOSITE_NOMUX(0, "hclk_peri", "aclk_peri_pre", 0, + COMPOSITE_NOMUX(HCLK_PERI, "hclk_peri", "aclk_peri_pre", 0, RK2928_CLKSEL_CON(10), 8, 2, DFLAGS | CLK_DIVIDER_POWER_OF_TWO, RK2928_CLKGATE_CON(2), 2, GFLAGS), - COMPOSITE_NOMUX(0, "pclk_peri", "aclk_peri_pre", 0, + COMPOSITE_NOMUX(PCLK_PERI, "pclk_peri", "aclk_peri_pre", 0, RK2928_CLKSEL_CON(10), 12, 2, DFLAGS | CLK_DIVIDER_POWER_OF_TWO, RK2928_CLKGATE_CON(2), 3, GFLAGS), @@ -304,14 +338,18 @@ static struct rockchip_clk_branch common_clk_branches[] __initdata = { GATE(0, "pclkin_cif0", "ext_cif0", 0, RK2928_CLKGATE_CON(3), 3, GFLAGS), + INVERTER(0, "pclk_cif0", "pclkin_cif0", + RK2928_CLKSEL_CON(30), 8, IFLAGS), + + FACTOR(0, "xin12m", "xin24m", 0, 1, 2), /* * the 480m are generated inside the usb block from these clocks, * but they are also a source for the hsicphy clock. */ - GATE(SCLK_OTGPHY0, "sclk_otgphy0", "usb480m", CLK_IGNORE_UNUSED, + GATE(SCLK_OTGPHY0, "sclk_otgphy0", "xin24m", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(1), 5, GFLAGS), - GATE(SCLK_OTGPHY1, "sclk_otgphy1", "usb480m", CLK_IGNORE_UNUSED, + GATE(SCLK_OTGPHY1, "sclk_otgphy1", "xin24m", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(1), 6, GFLAGS), COMPOSITE(0, "mac_src", mux_mac_p, 0, @@ -319,17 +357,18 @@ static struct rockchip_clk_branch common_clk_branches[] __initdata = { RK2928_CLKGATE_CON(2), 5, GFLAGS), MUX(SCLK_MAC, "sclk_macref", mux_sclk_macref_p, CLK_SET_RATE_PARENT, RK2928_CLKSEL_CON(21), 4, 1, MFLAGS), - GATE(0, "sclk_mac_lbtest", "sclk_macref", - RK2928_CLKGATE_CON(2), 12, 0, GFLAGS), + GATE(0, "sclk_mac_lbtest", "sclk_macref", 0, + RK2928_CLKGATE_CON(2), 12, GFLAGS), COMPOSITE(0, "hsadc_src", mux_pll_src_gpll_cpll_p, 0, RK2928_CLKSEL_CON(22), 0, 1, MFLAGS, 8, 8, DFLAGS, RK2928_CLKGATE_CON(2), 6, GFLAGS), - COMPOSITE_FRAC(0, "hsadc_frac", "hsadc_src", 0, + COMPOSITE_FRACMUX(0, "hsadc_frac", "hsadc_src", 0, RK2928_CLKSEL_CON(23), 0, - RK2928_CLKGATE_CON(2), 7, GFLAGS), - MUX(SCLK_HSADC, "sclk_hsadc", mux_sclk_hsadc_p, 0, - RK2928_CLKSEL_CON(22), 4, 2, MFLAGS), + RK2928_CLKGATE_CON(2), 7, GFLAGS, + &common_hsadc_out_fracmux), + INVERTER(SCLK_HSADC, "sclk_hsadc", "sclk_hsadc_out", + RK2928_CLKSEL_CON(22), 7, IFLAGS), COMPOSITE_NOMUX(SCLK_SARADC, "sclk_saradc", "xin24m", 0, RK2928_CLKSEL_CON(24), 8, 8, DFLAGS, @@ -338,18 +377,17 @@ static struct rockchip_clk_branch common_clk_branches[] __initdata = { COMPOSITE_NOMUX(0, "spdif_pre", "i2s_src", 0, RK2928_CLKSEL_CON(5), 0, 7, DFLAGS, RK2928_CLKGATE_CON(0), 13, GFLAGS), - COMPOSITE_FRAC(0, "spdif_frac", "spdif_pll", 0, + COMPOSITE_FRACMUX(0, "spdif_frac", "spdif_pre", CLK_SET_RATE_PARENT, RK2928_CLKSEL_CON(9), 0, - RK2928_CLKGATE_CON(0), 14, GFLAGS), - MUX(SCLK_SPDIF, "sclk_spdif", mux_sclk_spdif_p, 0, - RK2928_CLKSEL_CON(5), 8, 2, MFLAGS), + RK2928_CLKGATE_CON(0), 14, GFLAGS, + &common_spdif_fracmux), /* * Clock-Architecture Diagram 4 */ - GATE(SCLK_SMC, "sclk_smc", "hclk_peri", - RK2928_CLKGATE_CON(2), 4, 0, GFLAGS), + GATE(SCLK_SMC, "sclk_smc", "hclk_peri", 0, + RK2928_CLKGATE_CON(2), 4, GFLAGS), COMPOSITE_NOMUX(SCLK_SPI0, "sclk_spi0", "pclk_peri", 0, RK2928_CLKSEL_CON(25), 0, 7, DFLAGS, @@ -373,35 +411,31 @@ static struct rockchip_clk_branch common_clk_branches[] __initdata = { COMPOSITE_NOMUX(0, "uart0_pre", "uart_src", 0, RK2928_CLKSEL_CON(13), 0, 7, DFLAGS, RK2928_CLKGATE_CON(1), 8, GFLAGS), - COMPOSITE_FRAC(0, "uart0_frac", "uart0_pre", 0, + COMPOSITE_FRACMUX(0, "uart0_frac", "uart0_pre", CLK_SET_RATE_PARENT, RK2928_CLKSEL_CON(17), 0, - RK2928_CLKGATE_CON(1), 9, GFLAGS), - MUX(SCLK_UART0, "sclk_uart0", mux_sclk_uart0_p, 0, - RK2928_CLKSEL_CON(13), 8, 2, MFLAGS), + RK2928_CLKGATE_CON(1), 9, GFLAGS, + &common_uart0_fracmux), COMPOSITE_NOMUX(0, "uart1_pre", "uart_src", 0, RK2928_CLKSEL_CON(14), 0, 7, DFLAGS, RK2928_CLKGATE_CON(1), 10, GFLAGS), - COMPOSITE_FRAC(0, "uart1_frac", "uart1_pre", 0, + COMPOSITE_FRACMUX(0, "uart1_frac", "uart1_pre", CLK_SET_RATE_PARENT, RK2928_CLKSEL_CON(18), 0, - RK2928_CLKGATE_CON(1), 11, GFLAGS), - MUX(SCLK_UART1, "sclk_uart1", mux_sclk_uart1_p, 0, - RK2928_CLKSEL_CON(14), 8, 2, MFLAGS), + RK2928_CLKGATE_CON(1), 11, GFLAGS, + &common_uart1_fracmux), COMPOSITE_NOMUX(0, "uart2_pre", "uart_src", 0, RK2928_CLKSEL_CON(15), 0, 7, DFLAGS, RK2928_CLKGATE_CON(1), 12, GFLAGS), - COMPOSITE_FRAC(0, "uart2_frac", "uart2_pre", 0, + COMPOSITE_FRACMUX(0, "uart2_frac", "uart2_pre", CLK_SET_RATE_PARENT, RK2928_CLKSEL_CON(19), 0, - RK2928_CLKGATE_CON(1), 13, GFLAGS), - MUX(SCLK_UART2, "sclk_uart2", mux_sclk_uart2_p, 0, - RK2928_CLKSEL_CON(15), 8, 2, MFLAGS), + RK2928_CLKGATE_CON(1), 13, GFLAGS, + &common_uart2_fracmux), COMPOSITE_NOMUX(0, "uart3_pre", "uart_src", 0, RK2928_CLKSEL_CON(16), 0, 7, DFLAGS, RK2928_CLKGATE_CON(1), 14, GFLAGS), - COMPOSITE_FRAC(0, "uart3_frac", "uart3_pre", 0, + COMPOSITE_FRACMUX(0, "uart3_frac", "uart3_pre", CLK_SET_RATE_PARENT, RK2928_CLKSEL_CON(20), 0, - RK2928_CLKGATE_CON(1), 15, GFLAGS), - MUX(SCLK_UART3, "sclk_uart3", mux_sclk_uart3_p, 0, - RK2928_CLKSEL_CON(16), 8, 2, MFLAGS), + RK2928_CLKGATE_CON(1), 15, GFLAGS, + &common_uart3_fracmux), GATE(SCLK_JTAG, "jtag", "ext_jtag", 0, RK2928_CLKGATE_CON(1), 3, GFLAGS), @@ -418,7 +452,6 @@ static struct rockchip_clk_branch common_clk_branches[] __initdata = { /* hclk_cpu gates */ GATE(HCLK_ROM, "hclk_rom", "hclk_cpu", 0, RK2928_CLKGATE_CON(5), 6, GFLAGS), - GATE(HCLK_I2S0, "hclk_i2s0", "hclk_cpu", 0, RK2928_CLKGATE_CON(7), 2, GFLAGS), GATE(HCLK_SPDIF, "hclk_spdif", "hclk_cpu", 0, RK2928_CLKGATE_CON(7), 1, GFLAGS), GATE(0, "hclk_cpubus", "hclk_cpu", 0, RK2928_CLKGATE_CON(4), 8, GFLAGS), /* hclk_ahb2apb is part of a clk branch */ @@ -468,8 +501,8 @@ static struct rockchip_clk_branch common_clk_branches[] __initdata = { GATE(PCLK_GPIO2, "pclk_gpio2", "pclk_cpu", 0, RK2928_CLKGATE_CON(8), 11, GFLAGS), GATE(PCLK_EFUSE, "pclk_efuse", "pclk_cpu", 0, RK2928_CLKGATE_CON(5), 2, GFLAGS), GATE(PCLK_TZPC, "pclk_tzpc", "pclk_cpu", 0, RK2928_CLKGATE_CON(5), 3, GFLAGS), - GATE(0, "pclk_ddrupctl", "pclk_cpu", 0, RK2928_CLKGATE_CON(5), 7, GFLAGS), - GATE(0, "pclk_ddrpubl", "pclk_cpu", 0, RK2928_CLKGATE_CON(9), 6, GFLAGS), + GATE(PCLK_DDRUPCTL, "pclk_ddrupctl", "pclk_cpu", 0, RK2928_CLKGATE_CON(5), 7, GFLAGS), + GATE(PCLK_PUBL, "pclk_ddrpubl", "pclk_cpu", 0, RK2928_CLKGATE_CON(9), 6, GFLAGS), GATE(0, "pclk_dbg", "pclk_cpu", 0, RK2928_CLKGATE_CON(9), 1, GFLAGS), GATE(PCLK_GRF, "pclk_grf", "pclk_cpu", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(5), 4, GFLAGS), GATE(PCLK_PMU, "pclk_pmu", "pclk_cpu", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(5), 5, GFLAGS), @@ -511,6 +544,18 @@ static struct clk_div_table div_aclk_cpu_t[] = { { /* sentinel */ }, }; +static struct rockchip_clk_branch rk3066a_i2s0_fracmux __initdata = + MUX(SCLK_I2S0, "sclk_i2s0", mux_sclk_i2s0_p, CLK_SET_RATE_PARENT, + RK2928_CLKSEL_CON(2), 8, 2, MFLAGS); + +static struct rockchip_clk_branch rk3066a_i2s1_fracmux __initdata = + MUX(SCLK_I2S1, "sclk_i2s1", mux_sclk_i2s1_p, CLK_SET_RATE_PARENT, + RK2928_CLKSEL_CON(3), 8, 2, MFLAGS); + +static struct rockchip_clk_branch rk3066a_i2s2_fracmux __initdata = + MUX(SCLK_I2S2, "sclk_i2s2", mux_sclk_i2s2_p, CLK_SET_RATE_PARENT, + RK2928_CLKSEL_CON(4), 8, 2, MFLAGS); + static struct rockchip_clk_branch rk3066a_clk_branches[] __initdata = { DIVTBL(0, "aclk_cpu_pre", "armclk", 0, RK2928_CLKSEL_CON(1), 0, 3, DFLAGS | CLK_DIVIDER_READ_ONLY, div_aclk_cpu_t), @@ -535,12 +580,12 @@ static struct rockchip_clk_branch rk3066a_clk_branches[] __initdata = { COMPOSITE(0, "dclk_lcdc0_src", mux_pll_src_cpll_gpll_p, 0, RK2928_CLKSEL_CON(27), 0, 1, MFLAGS, 8, 8, DFLAGS, RK2928_CLKGATE_CON(3), 1, GFLAGS), - MUX(DCLK_LCDC0, "dclk_lcdc0", mux_rk3066_lcdc0_p, 0, + MUX(DCLK_LCDC0, "dclk_lcdc0", mux_rk3066_lcdc0_p, CLK_SET_RATE_PARENT, RK2928_CLKSEL_CON(27), 4, 1, MFLAGS), COMPOSITE(0, "dclk_lcdc1_src", mux_pll_src_cpll_gpll_p, 0, RK2928_CLKSEL_CON(28), 0, 1, MFLAGS, 8, 8, DFLAGS, RK2928_CLKGATE_CON(3), 2, GFLAGS), - MUX(DCLK_LCDC1, "dclk_lcdc1", mux_rk3066_lcdc1_p, 0, + MUX(DCLK_LCDC1, "dclk_lcdc1", mux_rk3066_lcdc1_p, CLK_SET_RATE_PARENT, RK2928_CLKSEL_CON(28), 4, 1, MFLAGS), COMPOSITE_NOMUX(0, "cif1_pre", "cif_src", 0, @@ -551,6 +596,8 @@ static struct rockchip_clk_branch rk3066a_clk_branches[] __initdata = { GATE(0, "pclkin_cif1", "ext_cif1", 0, RK2928_CLKGATE_CON(3), 4, GFLAGS), + INVERTER(0, "pclk_cif1", "pclkin_cif1", + RK2928_CLKSEL_CON(30), 12, IFLAGS), COMPOSITE(0, "aclk_gpu_src", mux_pll_src_cpll_gpll_p, 0, RK2928_CLKSEL_CON(33), 8, 1, MFLAGS, 0, 5, DFLAGS, @@ -561,7 +608,7 @@ static struct rockchip_clk_branch rk3066a_clk_branches[] __initdata = { GATE(SCLK_TIMER2, "timer2", "xin24m", 0, RK2928_CLKGATE_CON(3), 2, GFLAGS), - COMPOSITE_NOMUX(0, "sclk_tsadc", "xin24m", 0, + COMPOSITE_NOMUX(SCLK_TSADC, "sclk_tsadc", "xin24m", 0, RK2928_CLKSEL_CON(34), 0, 16, DFLAGS, RK2928_CLKGATE_CON(2), 15, GFLAGS), @@ -570,37 +617,35 @@ static struct rockchip_clk_branch rk3066a_clk_branches[] __initdata = { COMPOSITE_NOMUX(0, "i2s0_pre", "i2s_src", 0, RK2928_CLKSEL_CON(2), 0, 7, DFLAGS, RK2928_CLKGATE_CON(0), 7, GFLAGS), - COMPOSITE_FRAC(0, "i2s0_frac", "i2s0_pre", 0, + COMPOSITE_FRACMUX(0, "i2s0_frac", "i2s0_pre", CLK_SET_RATE_PARENT, RK2928_CLKSEL_CON(6), 0, - RK2928_CLKGATE_CON(0), 8, GFLAGS), - MUX(SCLK_I2S0, "sclk_i2s0", mux_sclk_i2s0_p, 0, - RK2928_CLKSEL_CON(2), 8, 2, MFLAGS), + RK2928_CLKGATE_CON(0), 8, GFLAGS, + &rk3066a_i2s0_fracmux), COMPOSITE_NOMUX(0, "i2s1_pre", "i2s_src", 0, RK2928_CLKSEL_CON(3), 0, 7, DFLAGS, RK2928_CLKGATE_CON(0), 9, GFLAGS), - COMPOSITE_FRAC(0, "i2s1_frac", "i2s1_pre", 0, + COMPOSITE_FRACMUX(0, "i2s1_frac", "i2s1_pre", CLK_SET_RATE_PARENT, RK2928_CLKSEL_CON(7), 0, - RK2928_CLKGATE_CON(0), 10, GFLAGS), - MUX(SCLK_I2S1, "sclk_i2s1", mux_sclk_i2s1_p, 0, - RK2928_CLKSEL_CON(3), 8, 2, MFLAGS), + RK2928_CLKGATE_CON(0), 10, GFLAGS, + &rk3066a_i2s1_fracmux), COMPOSITE_NOMUX(0, "i2s2_pre", "i2s_src", 0, RK2928_CLKSEL_CON(4), 0, 7, DFLAGS, RK2928_CLKGATE_CON(0), 11, GFLAGS), - COMPOSITE_FRAC(0, "i2s2_frac", "i2s2_pre", 0, + COMPOSITE_FRACMUX(0, "i2s2_frac", "i2s2_pre", CLK_SET_RATE_PARENT, RK2928_CLKSEL_CON(8), 0, - RK2928_CLKGATE_CON(0), 12, GFLAGS), - MUX(SCLK_I2S2, "sclk_i2s2", mux_sclk_i2s2_p, 0, - RK2928_CLKSEL_CON(4), 8, 2, MFLAGS), + RK2928_CLKGATE_CON(0), 12, GFLAGS, + &rk3066a_i2s2_fracmux), - GATE(HCLK_I2S1, "hclk_i2s1", "hclk_cpu", 0, RK2928_CLKGATE_CON(7), 3, GFLAGS), - GATE(HCLK_I2S2, "hclk_i2s2", "hclk_cpu", 0, RK2928_CLKGATE_CON(7), 4, GFLAGS), - GATE(0, "hclk_cif1", "hclk_cpu", 0, RK2928_CLKGATE_CON(6), 6, GFLAGS), - GATE(0, "hclk_hdmi", "hclk_cpu", 0, RK2928_CLKGATE_CON(4), 14, GFLAGS), + GATE(HCLK_I2S0, "hclk_i2s0", "hclk_cpu", 0, RK2928_CLKGATE_CON(7), 4, GFLAGS), + GATE(HCLK_I2S1, "hclk_i2s1", "hclk_cpu", 0, RK2928_CLKGATE_CON(7), 2, GFLAGS), + GATE(HCLK_I2S2, "hclk_i2s2", "hclk_cpu", 0, RK2928_CLKGATE_CON(7), 3, GFLAGS), + GATE(HCLK_CIF1, "hclk_cif1", "hclk_cpu", 0, RK2928_CLKGATE_CON(6), 6, GFLAGS), + GATE(HCLK_HDMI, "hclk_hdmi", "hclk_cpu", 0, RK2928_CLKGATE_CON(4), 14, GFLAGS), GATE(HCLK_OTG1, "hclk_usbotg1", "hclk_peri", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(5), 14, GFLAGS), - GATE(0, "aclk_cif1", "aclk_vio1", 0, RK2928_CLKGATE_CON(6), 7, GFLAGS), + GATE(ACLK_CIF1, "aclk_cif1", "aclk_vio1", 0, RK2928_CLKGATE_CON(6), 7, GFLAGS), GATE(PCLK_TIMER1, "pclk_timer1", "pclk_cpu", 0, RK2928_CLKGATE_CON(7), 8, GFLAGS), GATE(PCLK_TIMER2, "pclk_timer2", "pclk_cpu", 0, RK2928_CLKGATE_CON(7), 9, GFLAGS), @@ -621,9 +666,13 @@ static struct clk_div_table div_rk3188_aclk_core_t[] = { { /* sentinel */ }, }; -PNAME(mux_hsicphy_p) = { "sclk_otgphy0", "sclk_otgphy1", +PNAME(mux_hsicphy_p) = { "sclk_otgphy0_480m", "sclk_otgphy1_480m", "gpll", "cpll" }; +static struct rockchip_clk_branch rk3188_i2s0_fracmux __initdata = + MUX(SCLK_I2S0, "sclk_i2s0", mux_sclk_i2s0_p, CLK_SET_RATE_PARENT, + RK2928_CLKSEL_CON(3), 8, 2, MFLAGS); + static struct rockchip_clk_branch rk3188_clk_branches[] __initdata = { COMPOSITE_NOMUX_DIVTBL(0, "aclk_core", "armclk", CLK_IGNORE_UNUSED, RK2928_CLKSEL_CON(1), 3, 3, DFLAGS | CLK_DIVIDER_READ_ONLY, @@ -677,12 +726,12 @@ static struct rockchip_clk_branch rk3188_clk_branches[] __initdata = { COMPOSITE_NOMUX(0, "i2s0_pre", "i2s_src", 0, RK2928_CLKSEL_CON(3), 0, 7, DFLAGS, RK2928_CLKGATE_CON(0), 9, GFLAGS), - COMPOSITE_FRAC(0, "i2s0_frac", "i2s0_pre", 0, + COMPOSITE_FRACMUX(0, "i2s0_frac", "i2s0_pre", CLK_SET_RATE_PARENT, RK2928_CLKSEL_CON(7), 0, - RK2928_CLKGATE_CON(0), 10, GFLAGS), - MUX(SCLK_I2S0, "sclk_i2s0", mux_sclk_i2s0_p, 0, - RK2928_CLKSEL_CON(3), 8, 2, MFLAGS), + RK2928_CLKGATE_CON(0), 10, GFLAGS, + &rk3188_i2s0_fracmux), + GATE(HCLK_I2S0, "hclk_i2s0", "hclk_cpu", 0, RK2928_CLKGATE_CON(7), 2, GFLAGS), GATE(0, "hclk_imem0", "hclk_cpu", 0, RK2928_CLKGATE_CON(4), 14, GFLAGS), GATE(0, "hclk_imem1", "hclk_cpu", 0, RK2928_CLKGATE_CON(4), 15, GFLAGS), @@ -698,142 +747,104 @@ static struct rockchip_clk_branch rk3188_clk_branches[] __initdata = { GATE(ACLK_GPS, "aclk_gps", "aclk_peri", 0, RK2928_CLKGATE_CON(8), 13, GFLAGS), }; -static const char *rk3188_critical_clocks[] __initconst = { +static const char *const rk3188_critical_clocks[] __initconst = { "aclk_cpu", "aclk_peri", "hclk_peri", + "pclk_cpu", + "pclk_peri", + "hclk_cpubus", + "hclk_vio_bus", + "sclk_mac_lbtest", }; - -static void __init rockchip_reparent_clk(char *clock, char *new_parent) -{ - struct clk *clk1, *clk2; - unsigned long rate; - int ret; - - clk1 = __clk_lookup(clock); - clk2 = __clk_lookup(new_parent); - if (!IS_ERR(clk1) && !IS_ERR(clk2)) { - rate = clk_get_rate(clk1); - - ret = clk_set_parent(clk1, clk2); - if (ret < 0) - pr_err("%s: could not reparent %s to %s, ret=%d\n", - __func__, clock, new_parent, ret); - - clk_set_rate(clk1, rate); - } else { - pr_err("%s: missing clocks to reparent %s to %s\n", - __func__, clock, new_parent); - } -} - -static void __init rockchip_clk_set_rate(char *clock, unsigned long rate) -{ - struct clk *clk; - - clk = __clk_lookup(clock); - if(clk && !IS_ERR(clk)) { - clk_set_rate(clk, rate); - return; - } - pr_err("%s: missing clock %s when setting initial rate to %lu\n", - __func__, clock, rate); -} - -static void __init rockchip_clk_set_defaults(void) -{ - struct rockchip_initial_rate { - char *name; - unsigned long rate; - }; - int i; - - struct rockchip_initial_rate rates[] = { - {"gpll", 891000000}, - {"cpll", 600000000}, - {"aclk_cpu", 300000000}, - {"hclk_cpu", 150000000}, - {"pclk_cpu", 75000000}, - {"hclk_ahb2apb", 75000000}, - {"aclk_peri_pre", 150000000}, - {"hclk_peri", 150000000}, - {"pclk_peri", 75000000}, - }; - - rockchip_reparent_clk("aclk_cpu_pre", "gpll"); - rockchip_reparent_clk("mac_src", "dpll"); - rockchip_reparent_clk("aclk_peri_pre", "cpll"); - - for(i = 0; i < ARRAY_SIZE(rates); i++) - rockchip_clk_set_rate(rates[i].name, rates[i].rate); -} - -static void __init rk3188_common_clk_init(struct device_node *np) +static struct rockchip_clk_provider *__init rk3188_common_clk_init(struct device_node *np) { + struct rockchip_clk_provider *ctx; void __iomem *reg_base; - struct clk *clk; reg_base = of_iomap(np, 0); if (!reg_base) { pr_err("%s: could not map cru region\n", __func__); - return; + return ERR_PTR(-ENOMEM); } - rockchip_clk_init(np, reg_base, CLK_NR_CLKS); - - /* Fixed-clock should be registered before all others */ - clk=clk_fixed("xin24m",24000000); - if (IS_ERR(clk)) - pr_warn("%s: could not register clock xin24m: %ld\n", - __func__, PTR_ERR(clk)); - - /* xin12m is created by an cru-internal divider */ - clk = clk_fixed_factor("xin12m", "xin24m", 1, 2, 0); - if (IS_ERR(clk)) - pr_warn("%s: could not register clock xin12m: %ld\n", - __func__, PTR_ERR(clk)); - - clk = clk_fixed_factor("usb480m", "xin24m", 20, 1, 0); - if (IS_ERR(clk)) - pr_warn("%s: could not register clock usb480m: %ld\n", - __func__, PTR_ERR(clk)); + ctx = rockchip_clk_init(np, reg_base, CLK_NR_CLKS); + if (IS_ERR(ctx)) { + pr_err("%s: rockchip clk init failed\n", __func__); + return ERR_PTR(-ENOMEM); + } - rockchip_clk_register_branches(common_clk_branches, + rockchip_clk_register_branches(ctx, common_clk_branches, ARRAY_SIZE(common_clk_branches)); - rockchip_clk_protect_critical(rk3188_critical_clocks, - ARRAY_SIZE(rk3188_critical_clocks)); + + return ctx; } static void __init rk3066a_clk_init(struct device_node *np) { - rk3188_common_clk_init(np); - rockchip_clk_register_plls(rk3066_pll_clks, + struct rockchip_clk_provider *ctx; + + ctx = rk3188_common_clk_init(np); + if (IS_ERR(ctx)) + return; + + rockchip_clk_register_plls(ctx, rk3066_pll_clks, ARRAY_SIZE(rk3066_pll_clks), RK3066_GRF_SOC_STATUS); - rockchip_clk_register_branches(rk3066a_clk_branches, + rockchip_clk_register_branches(ctx, rk3066a_clk_branches, ARRAY_SIZE(rk3066a_clk_branches)); - rockchip_clk_register_armclk(ARMCLK, "armclk", + rockchip_clk_register_armclk(ctx, ARMCLK, "armclk", mux_armclk_p, ARRAY_SIZE(mux_armclk_p), &rk3066_cpuclk_data, rk3066_cpuclk_rates, ARRAY_SIZE(rk3066_cpuclk_rates)); + rockchip_clk_protect_critical(rk3188_critical_clocks, + ARRAY_SIZE(rk3188_critical_clocks)); + rockchip_clk_of_add_provider(np, ctx); } CLK_OF_DECLARE(rk3066a_cru, "rockchip,rk3066a-cru", rk3066a_clk_init); static void __init rk3188a_clk_init(struct device_node *np) { - rk3188_common_clk_init(np); - rockchip_clk_register_plls(rk3188_pll_clks, + struct rockchip_clk_provider *ctx; + struct clk *clk1, *clk2; + unsigned long rate; + int ret; + + ctx = rk3188_common_clk_init(np); + if (IS_ERR(ctx)) + return; + + rockchip_clk_register_plls(ctx, rk3188_pll_clks, ARRAY_SIZE(rk3188_pll_clks), RK3188_GRF_SOC_STATUS); - rockchip_clk_register_branches(rk3188_clk_branches, + rockchip_clk_register_branches(ctx, rk3188_clk_branches, ARRAY_SIZE(rk3188_clk_branches)); - rockchip_clk_register_armclk(ARMCLK, "armclk", + rockchip_clk_register_armclk(ctx, ARMCLK, "armclk", mux_armclk_p, ARRAY_SIZE(mux_armclk_p), &rk3188_cpuclk_data, rk3188_cpuclk_rates, ARRAY_SIZE(rk3188_cpuclk_rates)); - rockchip_clk_set_defaults(); + /* reparent aclk_cpu_pre from apll */ + clk1 = __clk_lookup("aclk_cpu_pre"); + clk2 = __clk_lookup("gpll"); + if (clk1 && clk2) { + rate = clk_get_rate(clk1); + + ret = clk_set_parent(clk1, clk2); + if (ret < 0) + pr_warn("%s: could not reparent aclk_cpu_pre to gpll\n", + __func__); + + clk_set_rate(clk1, rate); + } else { + pr_warn("%s: missing clocks to reparent aclk_cpu_pre to gpll\n", + __func__); + } + + rockchip_clk_protect_critical(rk3188_critical_clocks, + ARRAY_SIZE(rk3188_critical_clocks)); + rockchip_clk_of_add_provider(np, ctx); } CLK_OF_DECLARE(rk3188a_cru, "rockchip,rk3188a-cru", rk3188a_clk_init); @@ -850,7 +861,7 @@ static void __init rk3188_clk_init(struct device_node *np) rate = pll->rate_table; while (rate->rate > 0) { - rate->bwadj = 0; + rate->nb = 1; rate++; } } diff --git a/drivers/clk/rockchip/clk-rk3288.c b/drivers/clk/rockchip/clk-rk3288.c index b6c122d393..fc9554e0f3 100644 --- a/drivers/clk/rockchip/clk-rk3288.c +++ b/drivers/clk/rockchip/clk-rk3288.c @@ -16,6 +16,11 @@ #define RK3288_GRF_SOC_CON(x) (0x244 + x * 4) #define RK3288_GRF_SOC_STATUS1 0x284 +enum rk3288_variant { + RK3288_CRU, + RK3288W_CRU, +}; + enum rk3288_plls { apll, dpll, cpll, gpll, npll, }; @@ -76,24 +81,44 @@ static struct rockchip_pll_rate_table rk3288_pll_rates[] = { RK3066_PLL_RATE( 768000000, 1, 64, 2), RK3066_PLL_RATE( 742500000, 8, 495, 2), RK3066_PLL_RATE( 696000000, 1, 58, 2), + RK3066_PLL_RATE_NB(621000000, 1, 207, 8, 1), RK3066_PLL_RATE( 600000000, 1, 50, 2), - RK3066_PLL_RATE_BWADJ(594000000, 1, 198, 8, 1), + RK3066_PLL_RATE_NB(594000000, 1, 198, 8, 1), RK3066_PLL_RATE( 552000000, 1, 46, 2), RK3066_PLL_RATE( 504000000, 1, 84, 4), RK3066_PLL_RATE( 500000000, 3, 125, 2), RK3066_PLL_RATE( 456000000, 1, 76, 4), + RK3066_PLL_RATE( 428000000, 1, 107, 6), RK3066_PLL_RATE( 408000000, 1, 68, 4), RK3066_PLL_RATE( 400000000, 3, 100, 2), + RK3066_PLL_RATE_NB( 394000000, 1, 197, 12, 1), RK3066_PLL_RATE( 384000000, 2, 128, 4), RK3066_PLL_RATE( 360000000, 1, 60, 4), + RK3066_PLL_RATE_NB( 356000000, 1, 178, 12, 1), + RK3066_PLL_RATE_NB( 324000000, 1, 189, 14, 1), RK3066_PLL_RATE( 312000000, 1, 52, 4), - RK3066_PLL_RATE( 300000000, 1, 50, 4), - RK3066_PLL_RATE( 297000000, 2, 198, 8), + RK3066_PLL_RATE_NB( 308000000, 1, 154, 12, 1), + RK3066_PLL_RATE_NB( 303000000, 1, 202, 16, 1), + RK3066_PLL_RATE( 300000000, 1, 75, 6), + RK3066_PLL_RATE_NB( 297750000, 2, 397, 16, 1), + RK3066_PLL_RATE_NB( 293250000, 2, 391, 16, 1), + RK3066_PLL_RATE_NB( 292500000, 1, 195, 16, 1), + RK3066_PLL_RATE( 273600000, 1, 114, 10), + RK3066_PLL_RATE_NB( 273000000, 1, 182, 16, 1), + RK3066_PLL_RATE_NB( 270000000, 1, 180, 16, 1), + RK3066_PLL_RATE_NB( 266250000, 2, 355, 16, 1), + RK3066_PLL_RATE_NB( 256500000, 1, 171, 16, 1), RK3066_PLL_RATE( 252000000, 1, 84, 8), - RK3066_PLL_RATE( 216000000, 1, 72, 8), - RK3066_PLL_RATE( 148500000, 2, 99, 8), + RK3066_PLL_RATE_NB( 250500000, 1, 167, 16, 1), + RK3066_PLL_RATE_NB( 243428571, 1, 142, 14, 1), + RK3066_PLL_RATE( 238000000, 1, 119, 12), + RK3066_PLL_RATE_NB( 219750000, 2, 293, 16, 1), + RK3066_PLL_RATE_NB( 216000000, 1, 144, 16, 1), + RK3066_PLL_RATE_NB( 213000000, 1, 142, 16, 1), + RK3066_PLL_RATE( 195428571, 1, 114, 14), + RK3066_PLL_RATE( 160000000, 1, 80, 12), + RK3066_PLL_RATE( 157500000, 1, 105, 16), RK3066_PLL_RATE( 126000000, 1, 84, 16), - RK3066_PLL_RATE( 48000000, 1, 64, 32), { /* sentinel */ }, }; @@ -155,10 +180,14 @@ static struct rockchip_cpuclk_rate_table rk3288_cpuclk_rates[] __initdata = { }; static const struct rockchip_cpuclk_reg_data rk3288_cpuclk_data = { - .core_reg = RK3288_CLKSEL_CON(0), - .div_core_shift = 8, - .div_core_mask = 0x1f, + .core_reg[0] = RK3288_CLKSEL_CON(0), + .div_core_shift[0] = 8, + .div_core_mask[0] = 0x1f, + .num_cores = 1, + .mux_core_alt = 1, + .mux_core_main = 0, .mux_core_shift = 15, + .mux_core_mask = 0x1, }; PNAME(mux_pll_p) = { "xin24m", "xin32k" }; @@ -169,8 +198,8 @@ PNAME(mux_aclk_cpu_src_p) = { "cpll_aclk_cpu", "gpll_aclk_cpu" }; PNAME(mux_pll_src_cpll_gpll_p) = { "cpll", "gpll" }; PNAME(mux_pll_src_npll_cpll_gpll_p) = { "npll", "cpll", "gpll" }; PNAME(mux_pll_src_cpll_gpll_npll_p) = { "cpll", "gpll", "npll" }; -PNAME(mux_pll_src_cpll_gpll_usb480m_p) = { "cpll", "gpll", "usbphy480m_src" }; -PNAME(mux_pll_src_cpll_gll_usb_npll_p) = { "cpll", "gpll", "usbphy480m_src", "npll" }; +PNAME(mux_pll_src_cpll_gpll_usb480m_p) = { "cpll", "gpll", "unstable:usbphy480m_src" }; +PNAME(mux_pll_src_cpll_gll_usb_npll_p) = { "cpll", "gpll", "unstable:usbphy480m_src", "npll" }; PNAME(mux_mmc_src_p) = { "cpll", "gpll", "xin24m", "xin24m" }; PNAME(mux_i2s_pre_p) = { "i2s_src", "i2s_frac", "ext_i2s", "xin12m" }; @@ -188,8 +217,9 @@ PNAME(mux_hsadcout_p) = { "hsadc_src", "ext_hsadc" }; PNAME(mux_edp_24m_p) = { "ext_edp_24m", "xin24m" }; PNAME(mux_tspout_p) = { "cpll", "gpll", "npll", "xin27m" }; -PNAME(mux_usbphy480m_p) = { "sclk_otgphy1", "sclk_otgphy2", - "sclk_otgphy0" }; +PNAME(mux_aclk_vcodec_pre_p) = { "aclk_vdpu", "aclk_vepu" }; +PNAME(mux_usbphy480m_p) = { "sclk_otgphy1_480m", "sclk_otgphy2_480m", + "sclk_otgphy0_480m" }; PNAME(mux_hsicphy480m_p) = { "cpll", "gpll", "usbphy480m_src" }; PNAME(mux_hsicphy12m_p) = { "hsicphy12m_xin12m", "hsicphy12m_usbphy" }; @@ -216,6 +246,39 @@ static struct clk_div_table div_hclk_cpu_t[] = { #define MFLAGS CLK_MUX_HIWORD_MASK #define DFLAGS CLK_DIVIDER_HIWORD_MASK #define GFLAGS (CLK_GATE_HIWORD_MASK | CLK_GATE_SET_TO_DISABLE) +#define IFLAGS ROCKCHIP_INVERTER_HIWORD_MASK + +static struct rockchip_clk_branch rk3288_i2s_fracmux __initdata = + MUX(0, "i2s_pre", mux_i2s_pre_p, CLK_SET_RATE_PARENT, + RK3288_CLKSEL_CON(4), 8, 2, MFLAGS); + +static struct rockchip_clk_branch rk3288_spdif_fracmux __initdata = + MUX(0, "spdif_mux", mux_spdif_p, CLK_SET_RATE_PARENT, + RK3288_CLKSEL_CON(5), 8, 2, MFLAGS); + +static struct rockchip_clk_branch rk3288_spdif_8ch_fracmux __initdata = + MUX(0, "spdif_8ch_mux", mux_spdif_8ch_p, CLK_SET_RATE_PARENT, + RK3288_CLKSEL_CON(40), 8, 2, MFLAGS); + +static struct rockchip_clk_branch rk3288_uart0_fracmux __initdata = + MUX(SCLK_UART0, "sclk_uart0", mux_uart0_p, CLK_SET_RATE_PARENT, + RK3288_CLKSEL_CON(13), 8, 2, MFLAGS); + +static struct rockchip_clk_branch rk3288_uart1_fracmux __initdata = + MUX(SCLK_UART1, "sclk_uart1", mux_uart1_p, CLK_SET_RATE_PARENT, + RK3288_CLKSEL_CON(14), 8, 2, MFLAGS); + +static struct rockchip_clk_branch rk3288_uart2_fracmux __initdata = + MUX(SCLK_UART2, "sclk_uart2", mux_uart2_p, CLK_SET_RATE_PARENT, + RK3288_CLKSEL_CON(15), 8, 2, MFLAGS); + +static struct rockchip_clk_branch rk3288_uart3_fracmux __initdata = + MUX(SCLK_UART3, "sclk_uart3", mux_uart3_p, CLK_SET_RATE_PARENT, + RK3288_CLKSEL_CON(16), 8, 2, MFLAGS); + +static struct rockchip_clk_branch rk3288_uart4_fracmux __initdata = + MUX(SCLK_UART4, "sclk_uart4", mux_uart4_p, CLK_SET_RATE_PARENT, + RK3288_CLKSEL_CON(3), 8, 2, MFLAGS); static struct rockchip_clk_branch rk3288_clk_branches[] __initdata = { /* @@ -287,20 +350,21 @@ static struct rockchip_clk_branch rk3288_clk_branches[] __initdata = { RK3288_CLKGATE_CON(0), 4, GFLAGS), GATE(0, "c2c_host", "aclk_cpu_src", 0, RK3288_CLKGATE_CON(13), 8, GFLAGS), - COMPOSITE_NOMUX(0, "crypto", "aclk_cpu_pre", 0, + COMPOSITE_NOMUX(SCLK_CRYPTO, "crypto", "aclk_cpu_pre", 0, RK3288_CLKSEL_CON(26), 6, 2, DFLAGS, RK3288_CLKGATE_CON(5), 4, GFLAGS), GATE(0, "aclk_bus_2pmu", "aclk_cpu_pre", CLK_IGNORE_UNUSED, RK3288_CLKGATE_CON(0), 7, GFLAGS), + FACTOR(0, "xin12m", "xin24m", 0, 1, 2), + COMPOSITE(0, "i2s_src", mux_pll_src_cpll_gpll_p, 0, RK3288_CLKSEL_CON(4), 15, 1, MFLAGS, 0, 7, DFLAGS, RK3288_CLKGATE_CON(4), 1, GFLAGS), - COMPOSITE_FRAC(0, "i2s_frac", "i2s_src", CLK_SET_RATE_PARENT, + COMPOSITE_FRACMUX(0, "i2s_frac", "i2s_src", CLK_SET_RATE_PARENT, RK3288_CLKSEL_CON(8), 0, - RK3288_CLKGATE_CON(4), 2, GFLAGS), - MUX(0, "i2s_pre", mux_i2s_pre_p, CLK_SET_RATE_PARENT, - RK3288_CLKSEL_CON(4), 8, 2, MFLAGS), + RK3288_CLKGATE_CON(4), 2, GFLAGS, + &rk3288_i2s_fracmux), COMPOSITE_NODIV(SCLK_I2S0_OUT, "i2s0_clkout", mux_i2s_clkout_p, 0, RK3288_CLKSEL_CON(4), 12, 1, MFLAGS, RK3288_CLKGATE_CON(4), 0, GFLAGS), @@ -309,27 +373,28 @@ static struct rockchip_clk_branch rk3288_clk_branches[] __initdata = { MUX(0, "spdif_src", mux_pll_src_cpll_gpll_p, 0, RK3288_CLKSEL_CON(5), 15, 1, MFLAGS), - COMPOSITE_NOMUX(0, "spdif_pre", "spdif_src", 0, + COMPOSITE_NOMUX(0, "spdif_pre", "spdif_src", CLK_SET_RATE_PARENT, RK3288_CLKSEL_CON(5), 0, 7, DFLAGS, RK3288_CLKGATE_CON(4), 4, GFLAGS), - COMPOSITE_FRAC(0, "spdif_frac", "spdif_src", 0, + COMPOSITE_FRACMUX(0, "spdif_frac", "spdif_src", CLK_SET_RATE_PARENT, RK3288_CLKSEL_CON(9), 0, - RK3288_CLKGATE_CON(4), 5, GFLAGS), - COMPOSITE_NODIV(SCLK_SPDIF, "sclk_spdif", mux_spdif_p, 0, - RK3288_CLKSEL_CON(5), 8, 2, MFLAGS, + RK3288_CLKGATE_CON(4), 5, GFLAGS, + &rk3288_spdif_fracmux), + GATE(SCLK_SPDIF, "sclk_spdif", "spdif_mux", CLK_SET_RATE_PARENT, RK3288_CLKGATE_CON(4), 6, GFLAGS), - COMPOSITE_NOMUX(0, "spdif_8ch_pre", "spdif_src", 0, + COMPOSITE_NOMUX(0, "spdif_8ch_pre", "spdif_src", CLK_SET_RATE_PARENT, RK3288_CLKSEL_CON(40), 0, 7, DFLAGS, RK3288_CLKGATE_CON(4), 7, GFLAGS), - COMPOSITE_FRAC(0, "spdif_8ch_frac", "spdif_8ch_pre", 0, + COMPOSITE_FRACMUX(0, "spdif_8ch_frac", "spdif_8ch_pre", CLK_SET_RATE_PARENT, RK3288_CLKSEL_CON(41), 0, - RK3288_CLKGATE_CON(4), 8, GFLAGS), - COMPOSITE_NODIV(SCLK_SPDIF8CH, "sclk_spdif_8ch", mux_spdif_8ch_p, 0, - RK3288_CLKSEL_CON(40), 8, 2, MFLAGS, + RK3288_CLKGATE_CON(4), 8, GFLAGS, + &rk3288_spdif_8ch_fracmux), + GATE(SCLK_SPDIF8CH, "sclk_spdif_8ch", "spdif_8ch_mux", CLK_SET_RATE_PARENT, RK3288_CLKGATE_CON(4), 9, GFLAGS), GATE(0, "sclk_acc_efuse", "xin24m", 0, RK3288_CLKGATE_CON(0), 12, GFLAGS), + GATE(SCLK_TIMER0, "sclk_timer0", "xin24m", 0, RK3288_CLKGATE_CON(1), 0, GFLAGS), GATE(SCLK_TIMER1, "sclk_timer1", "xin24m", 0, @@ -342,6 +407,7 @@ static struct rockchip_clk_branch rk3288_clk_branches[] __initdata = { RK3288_CLKGATE_CON(1), 4, GFLAGS), GATE(SCLK_TIMER5, "sclk_timer5", "xin24m", 0, RK3288_CLKGATE_CON(1), 5, GFLAGS), + /* * Clock-Architecture Diagram 2 */ @@ -352,26 +418,20 @@ static struct rockchip_clk_branch rk3288_clk_branches[] __initdata = { COMPOSITE(0, "aclk_vdpu", mux_pll_src_cpll_gpll_usb480m_p, 0, RK3288_CLKSEL_CON(32), 14, 2, MFLAGS, 8, 5, DFLAGS, RK3288_CLKGATE_CON(3), 11, GFLAGS), - /* - * We use aclk_vdpu by default GRF_SOC_CON0[7] setting in system, - * so we ignore the mux and make clocks nodes as following, - */ - GATE(ACLK_VCODEC, "aclk_vcodec", "aclk_vdpu", 0, + MUXGRF(0, "aclk_vcodec_pre", mux_aclk_vcodec_pre_p, CLK_SET_RATE_PARENT, + RK3288_GRF_SOC_CON(0), 7, 1, MFLAGS), + GATE(ACLK_VCODEC, "aclk_vcodec", "aclk_vcodec_pre", 0, RK3288_CLKGATE_CON(9), 0, GFLAGS), - /* - * We introduce a virtul node of hclk_vodec_pre_v to split one clock - * struct with a gate and a fix divider into two node in software. - */ - GATE(0, "hclk_vcodec_pre_v", "aclk_vdpu", 0, + + FACTOR_GATE(0, "hclk_vcodec_pre", "aclk_vcodec_pre", 0, 1, 4, RK3288_CLKGATE_CON(3), 10, GFLAGS), + GATE(HCLK_VCODEC, "hclk_vcodec", "hclk_vcodec_pre", 0, RK3288_CLKGATE_CON(9), 1, GFLAGS), COMPOSITE(0, "aclk_vio0", mux_pll_src_cpll_gpll_usb480m_p, CLK_IGNORE_UNUSED, RK3288_CLKSEL_CON(31), 6, 2, MFLAGS, 0, 5, DFLAGS, RK3288_CLKGATE_CON(3), 0, GFLAGS), - DIV(0, "hclk_vio", "aclk_vio0", 0, - RK3288_CLKSEL_CON(28), 8, 5, DFLAGS), COMPOSITE(0, "aclk_vio1", mux_pll_src_cpll_gpll_usb480m_p, CLK_IGNORE_UNUSED, RK3288_CLKSEL_CON(31), 14, 2, MFLAGS, 8, 5, DFLAGS, RK3288_CLKGATE_CON(3), 2, GFLAGS), @@ -425,7 +485,7 @@ static struct rockchip_clk_branch rk3288_clk_branches[] __initdata = { COMPOSITE_NODIV(0, "vip_src", mux_pll_src_cpll_gpll_p, 0, RK3288_CLKSEL_CON(26), 8, 1, MFLAGS, RK3288_CLKGATE_CON(3), 7, GFLAGS), - COMPOSITE_NOGATE(0, "sclk_vip_out", mux_vip_out_p, 0, + COMPOSITE_NOGATE(SCLK_VIP_OUT, "sclk_vip_out", mux_vip_out_p, 0, RK3288_CLKSEL_CON(26), 15, 1, MFLAGS, 9, 5, DFLAGS), DIV(0, "pclk_pd_alive", "gpll", 0, @@ -496,11 +556,11 @@ static struct rockchip_clk_branch rk3288_clk_branches[] __initdata = { RK3288_CLKSEL_CON(35), 6, 2, MFLAGS, 0, 5, DFLAGS, RK3288_CLKGATE_CON(4), 10, GFLAGS), - GATE(SCLK_OTGPHY0, "sclk_otgphy0", "usb480m", CLK_IGNORE_UNUSED, + GATE(SCLK_OTGPHY0, "sclk_otgphy0", "xin24m", CLK_IGNORE_UNUSED, RK3288_CLKGATE_CON(13), 4, GFLAGS), - GATE(SCLK_OTGPHY1, "sclk_otgphy1", "usb480m", CLK_IGNORE_UNUSED, + GATE(SCLK_OTGPHY1, "sclk_otgphy1", "xin24m", CLK_IGNORE_UNUSED, RK3288_CLKGATE_CON(13), 5, GFLAGS), - GATE(SCLK_OTGPHY2, "sclk_otgphy2", "usb480m", CLK_IGNORE_UNUSED, + GATE(SCLK_OTGPHY2, "sclk_otgphy2", "xin24m", CLK_IGNORE_UNUSED, RK3288_CLKGATE_CON(13), 6, GFLAGS), GATE(SCLK_OTG_ADP, "sclk_otg_adp", "xin32k", CLK_IGNORE_UNUSED, RK3288_CLKGATE_CON(13), 7, GFLAGS), @@ -526,45 +586,40 @@ static struct rockchip_clk_branch rk3288_clk_branches[] __initdata = { COMPOSITE(0, "uart0_src", mux_pll_src_cpll_gll_usb_npll_p, 0, RK3288_CLKSEL_CON(13), 13, 2, MFLAGS, 0, 7, DFLAGS, RK3288_CLKGATE_CON(1), 8, GFLAGS), - COMPOSITE_FRAC(0, "uart0_frac", "uart0_src", CLK_SET_RATE_PARENT, + COMPOSITE_FRACMUX(0, "uart0_frac", "uart0_src", CLK_SET_RATE_PARENT, RK3288_CLKSEL_CON(17), 0, - RK3288_CLKGATE_CON(1), 9, GFLAGS), - MUX(SCLK_UART0, "sclk_uart0", mux_uart0_p, CLK_SET_RATE_PARENT, - RK3288_CLKSEL_CON(13), 8, 2, MFLAGS), + RK3288_CLKGATE_CON(1), 9, GFLAGS, + &rk3288_uart0_fracmux), MUX(0, "uart_src", mux_pll_src_cpll_gpll_p, 0, RK3288_CLKSEL_CON(13), 15, 1, MFLAGS), COMPOSITE_NOMUX(0, "uart1_src", "uart_src", 0, RK3288_CLKSEL_CON(14), 0, 7, DFLAGS, RK3288_CLKGATE_CON(1), 10, GFLAGS), - COMPOSITE_FRAC(0, "uart1_frac", "uart1_src", CLK_SET_RATE_PARENT, + COMPOSITE_FRACMUX(0, "uart1_frac", "uart1_src", CLK_SET_RATE_PARENT, RK3288_CLKSEL_CON(18), 0, - RK3288_CLKGATE_CON(1), 11, GFLAGS), - MUX(SCLK_UART1, "sclk_uart1", mux_uart1_p, CLK_SET_RATE_PARENT, - RK3288_CLKSEL_CON(14), 8, 2, MFLAGS), + RK3288_CLKGATE_CON(1), 11, GFLAGS, + &rk3288_uart1_fracmux), COMPOSITE_NOMUX(0, "uart2_src", "uart_src", 0, RK3288_CLKSEL_CON(15), 0, 7, DFLAGS, RK3288_CLKGATE_CON(1), 12, GFLAGS), - COMPOSITE_FRAC(0, "uart2_frac", "uart2_src", CLK_SET_RATE_PARENT, + COMPOSITE_FRACMUX(0, "uart2_frac", "uart2_src", CLK_SET_RATE_PARENT, RK3288_CLKSEL_CON(19), 0, - RK3288_CLKGATE_CON(1), 13, GFLAGS), - MUX(SCLK_UART2, "sclk_uart2", mux_uart2_p, CLK_SET_RATE_PARENT, - RK3288_CLKSEL_CON(15), 8, 2, MFLAGS), + RK3288_CLKGATE_CON(1), 13, GFLAGS, + &rk3288_uart2_fracmux), COMPOSITE_NOMUX(0, "uart3_src", "uart_src", 0, RK3288_CLKSEL_CON(16), 0, 7, DFLAGS, RK3288_CLKGATE_CON(1), 14, GFLAGS), - COMPOSITE_FRAC(0, "uart3_frac", "uart3_src", CLK_SET_RATE_PARENT, + COMPOSITE_FRACMUX(0, "uart3_frac", "uart3_src", CLK_SET_RATE_PARENT, RK3288_CLKSEL_CON(20), 0, - RK3288_CLKGATE_CON(1), 15, GFLAGS), - MUX(SCLK_UART3, "sclk_uart3", mux_uart3_p, CLK_SET_RATE_PARENT, - RK3288_CLKSEL_CON(16), 8, 2, MFLAGS), + RK3288_CLKGATE_CON(1), 15, GFLAGS, + &rk3288_uart3_fracmux), COMPOSITE_NOMUX(0, "uart4_src", "uart_src", 0, RK3288_CLKSEL_CON(3), 0, 7, DFLAGS, RK3288_CLKGATE_CON(2), 12, GFLAGS), - COMPOSITE_FRAC(0, "uart4_frac", "uart4_src", CLK_SET_RATE_PARENT, + COMPOSITE_FRACMUX(0, "uart4_frac", "uart4_src", CLK_SET_RATE_PARENT, RK3288_CLKSEL_CON(7), 0, - RK3288_CLKGATE_CON(2), 13, GFLAGS), - MUX(SCLK_UART4, "sclk_uart4", mux_uart4_p, CLK_SET_RATE_PARENT, - RK3288_CLKSEL_CON(3), 8, 2, MFLAGS), + RK3288_CLKGATE_CON(2), 13, GFLAGS, + &rk3288_uart4_fracmux), COMPOSITE(0, "mac_pll_src", mux_pll_src_npll_cpll_gpll_p, 0, RK3288_CLKSEL_CON(21), 0, 2, MFLAGS, 8, 5, DFLAGS, @@ -585,6 +640,8 @@ static struct rockchip_clk_branch rk3288_clk_branches[] __initdata = { RK3288_CLKGATE_CON(2), 6, GFLAGS), MUX(0, "sclk_hsadc_out", mux_hsadcout_p, 0, RK3288_CLKSEL_CON(22), 4, 1, MFLAGS), + INVERTER(SCLK_HSADC, "sclk_hsadc", "sclk_hsadc_out", + RK3288_CLKSEL_CON(22), 7, IFLAGS), GATE(0, "jtag", "ext_jtag", 0, RK3288_CLKGATE_CON(4), 14, GFLAGS), @@ -632,11 +689,11 @@ static struct rockchip_clk_branch rk3288_clk_branches[] __initdata = { GATE(PCLK_PUBL0, "pclk_publ0", "pclk_cpu", 0, RK3288_CLKGATE_CON(10), 15, GFLAGS), GATE(PCLK_DDRUPCTL1, "pclk_ddrupctl1", "pclk_cpu", 0, RK3288_CLKGATE_CON(11), 0, GFLAGS), GATE(PCLK_PUBL1, "pclk_publ1", "pclk_cpu", 0, RK3288_CLKGATE_CON(11), 1, GFLAGS), - GATE(0, "pclk_efuse_1024", "pclk_cpu", 0, RK3288_CLKGATE_CON(11), 2, GFLAGS), + GATE(PCLK_EFUSE1024, "pclk_efuse_1024", "pclk_cpu", 0, RK3288_CLKGATE_CON(11), 2, GFLAGS), GATE(PCLK_TZPC, "pclk_tzpc", "pclk_cpu", 0, RK3288_CLKGATE_CON(11), 3, GFLAGS), GATE(PCLK_UART2, "pclk_uart2", "pclk_cpu", 0, RK3288_CLKGATE_CON(11), 9, GFLAGS), - GATE(0, "pclk_efuse_256", "pclk_cpu", 0, RK3288_CLKGATE_CON(11), 10, GFLAGS), - GATE(PCLK_RKPWM, "pclk_rkpwm", "pclk_cpu", CLK_IGNORE_UNUSED, RK3288_CLKGATE_CON(11), 11, GFLAGS), + GATE(PCLK_EFUSE256, "pclk_efuse_256", "pclk_cpu", 0, RK3288_CLKGATE_CON(11), 10, GFLAGS), + GATE(PCLK_RKPWM, "pclk_rkpwm", "pclk_cpu", 0, RK3288_CLKGATE_CON(11), 11, GFLAGS), /* ddrctrl [DDR Controller PHY clock] gates */ GATE(0, "nclk_ddrupctl0", "ddrphy", CLK_IGNORE_UNUSED, RK3288_CLKGATE_CON(11), 4, GFLAGS), @@ -649,7 +706,7 @@ static struct rockchip_clk_branch rk3288_clk_branches[] __initdata = { /* aclk_peri gates */ GATE(0, "aclk_peri_axi_matrix", "aclk_peri", CLK_IGNORE_UNUSED, RK3288_CLKGATE_CON(6), 2, GFLAGS), GATE(ACLK_DMAC2, "aclk_dmac2", "aclk_peri", 0, RK3288_CLKGATE_CON(6), 3, GFLAGS), - GATE(0, "aclk_peri_niu", "aclk_peri", CLK_IGNORE_UNUSED, RK3288_CLKGATE_CON(7), 11, GFLAGS), + GATE(0, "aclk_peri_niu", "aclk_peri", 0, RK3288_CLKGATE_CON(7), 11, GFLAGS), GATE(ACLK_MMU, "aclk_mmu", "aclk_peri", CLK_IGNORE_UNUSED, RK3288_CLKGATE_CON(8), 12, GFLAGS), GATE(ACLK_GMAC, "aclk_gmac", "aclk_peri", 0, RK3288_CLKGATE_CON(8), 0, GFLAGS), GATE(HCLK_GPS, "hclk_gps", "aclk_peri", 0, RK3288_CLKGATE_CON(8), 2, GFLAGS), @@ -697,7 +754,7 @@ static struct rockchip_clk_branch rk3288_clk_branches[] __initdata = { GATE(SCLK_LCDC_PWM1, "sclk_lcdc_pwm1", "xin24m", 0, RK3288_CLKGATE_CON(13), 11, GFLAGS), GATE(SCLK_PVTM_CORE, "sclk_pvtm_core", "xin24m", 0, RK3288_CLKGATE_CON(5), 9, GFLAGS), GATE(SCLK_PVTM_GPU, "sclk_pvtm_gpu", "xin24m", 0, RK3288_CLKGATE_CON(5), 10, GFLAGS), - GATE(0, "sclk_mipidsi_24m", "xin24m", 0, RK3288_CLKGATE_CON(5), 15, GFLAGS), + GATE(SCLK_MIPIDSI_24M, "sclk_mipidsi_24m", "xin24m", 0, RK3288_CLKGATE_CON(5), 15, GFLAGS), /* sclk_gpu gates */ GATE(ACLK_GPU, "aclk_gpu", "sclk_gpu", 0, RK3288_CLKGATE_CON(18), 0, GFLAGS), @@ -712,12 +769,15 @@ static struct rockchip_clk_branch rk3288_clk_branches[] __initdata = { GATE(PCLK_GPIO5, "pclk_gpio5", "pclk_pd_alive", 0, RK3288_CLKGATE_CON(14), 5, GFLAGS), GATE(PCLK_GPIO6, "pclk_gpio6", "pclk_pd_alive", 0, RK3288_CLKGATE_CON(14), 6, GFLAGS), GATE(PCLK_GRF, "pclk_grf", "pclk_pd_alive", CLK_IGNORE_UNUSED, RK3288_CLKGATE_CON(14), 11, GFLAGS), - GATE(0, "pclk_alive_niu", "pclk_pd_alive", CLK_IGNORE_UNUSED, RK3288_CLKGATE_CON(14), 12, GFLAGS), + GATE(0, "pclk_alive_niu", "pclk_pd_alive", 0, RK3288_CLKGATE_CON(14), 12, GFLAGS), + + /* Watchdog pclk is controlled by RK3288_SGRF_SOC_CON0[1]. */ + SGRF_GATE(PCLK_WDT, "pclk_wdt", "pclk_pd_alive"), /* pclk_pd_pmu gates */ GATE(PCLK_PMU, "pclk_pmu", "pclk_pd_pmu", CLK_IGNORE_UNUSED, RK3288_CLKGATE_CON(17), 0, GFLAGS), GATE(0, "pclk_intmem1", "pclk_pd_pmu", CLK_IGNORE_UNUSED, RK3288_CLKGATE_CON(17), 1, GFLAGS), - GATE(0, "pclk_pmu_niu", "pclk_pd_pmu", CLK_IGNORE_UNUSED, RK3288_CLKGATE_CON(17), 2, GFLAGS), + GATE(0, "pclk_pmu_niu", "pclk_pd_pmu", 0, RK3288_CLKGATE_CON(17), 2, GFLAGS), GATE(PCLK_SGRF, "pclk_sgrf", "pclk_pd_pmu", CLK_IGNORE_UNUSED, RK3288_CLKGATE_CON(17), 3, GFLAGS), GATE(PCLK_GPIO0, "pclk_gpio0", "pclk_pd_pmu", 0, RK3288_CLKGATE_CON(17), 4, GFLAGS), @@ -726,7 +786,7 @@ static struct rockchip_clk_branch rk3288_clk_branches[] __initdata = { GATE(HCLK_VOP0, "hclk_vop0", "hclk_vio", 0, RK3288_CLKGATE_CON(15), 6, GFLAGS), GATE(HCLK_VOP1, "hclk_vop1", "hclk_vio", 0, RK3288_CLKGATE_CON(15), 8, GFLAGS), GATE(HCLK_VIO_AHB_ARBI, "hclk_vio_ahb_arbi", "hclk_vio", CLK_IGNORE_UNUSED, RK3288_CLKGATE_CON(15), 9, GFLAGS), - GATE(HCLK_VIO_NIU, "hclk_vio_niu", "hclk_vio", CLK_IGNORE_UNUSED, RK3288_CLKGATE_CON(15), 10, GFLAGS), + GATE(HCLK_VIO_NIU, "hclk_vio_niu", "hclk_vio", 0, RK3288_CLKGATE_CON(15), 10, GFLAGS), GATE(HCLK_VIP, "hclk_vip", "hclk_vio", 0, RK3288_CLKGATE_CON(15), 15, GFLAGS), GATE(HCLK_IEP, "hclk_iep", "hclk_vio", 0, RK3288_CLKGATE_CON(15), 3, GFLAGS), GATE(HCLK_ISP, "hclk_isp", "hclk_vio", 0, RK3288_CLKGATE_CON(16), 1, GFLAGS), @@ -742,83 +802,106 @@ static struct rockchip_clk_branch rk3288_clk_branches[] __initdata = { /* aclk_vio0 gates */ GATE(ACLK_VOP0, "aclk_vop0", "aclk_vio0", 0, RK3288_CLKGATE_CON(15), 5, GFLAGS), GATE(ACLK_IEP, "aclk_iep", "aclk_vio0", 0, RK3288_CLKGATE_CON(15), 2, GFLAGS), - GATE(ACLK_VIO0_NIU, "aclk_vio0_niu", "aclk_vio0", CLK_IGNORE_UNUSED, RK3288_CLKGATE_CON(15), 11, GFLAGS), + GATE(ACLK_VIO0_NIU, "aclk_vio0_niu", "aclk_vio0", 0, RK3288_CLKGATE_CON(15), 11, GFLAGS), GATE(ACLK_VIP, "aclk_vip", "aclk_vio0", 0, RK3288_CLKGATE_CON(15), 14, GFLAGS), /* aclk_vio1 gates */ GATE(ACLK_VOP1, "aclk_vop1", "aclk_vio1", 0, RK3288_CLKGATE_CON(15), 7, GFLAGS), GATE(ACLK_ISP, "aclk_isp", "aclk_vio1", 0, RK3288_CLKGATE_CON(16), 2, GFLAGS), - GATE(ACLK_VIO1_NIU, "aclk_vio1_niu", "aclk_vio1", CLK_IGNORE_UNUSED, RK3288_CLKGATE_CON(15), 12, GFLAGS), + GATE(ACLK_VIO1_NIU, "aclk_vio1_niu", "aclk_vio1", 0, RK3288_CLKGATE_CON(15), 12, GFLAGS), /* aclk_rga_pre gates */ GATE(ACLK_RGA, "aclk_rga", "aclk_rga_pre", 0, RK3288_CLKGATE_CON(15), 0, GFLAGS), - GATE(ACLK_RGA_NIU, "aclk_rga_niu", "aclk_rga_pre", CLK_IGNORE_UNUSED, RK3288_CLKGATE_CON(15), 13, GFLAGS), + GATE(ACLK_RGA_NIU, "aclk_rga_niu", "aclk_rga_pre", 0, RK3288_CLKGATE_CON(15), 13, GFLAGS), /* * Other ungrouped clocks. */ GATE(0, "pclk_vip_in", "ext_vip", 0, RK3288_CLKGATE_CON(16), 0, GFLAGS), - GATE(0, "pclk_isp_in", "ext_isp", 0, RK3288_CLKGATE_CON(16), 3, GFLAGS), + INVERTER(0, "pclk_vip", "pclk_vip_in", RK3288_CLKSEL_CON(29), 4, IFLAGS), + GATE(PCLK_ISP_IN, "pclk_isp_in", "ext_isp", 0, RK3288_CLKGATE_CON(16), 3, GFLAGS), + INVERTER(0, "pclk_isp", "pclk_isp_in", RK3288_CLKSEL_CON(29), 3, IFLAGS), +}; + +static struct rockchip_clk_branch rk3288w_hclkvio_branch[] __initdata = { + DIV(0, "hclk_vio", "aclk_vio1", 0, + RK3288_CLKSEL_CON(28), 8, 5, DFLAGS), }; -static const char *rk3288_critical_clocks[] __initconst = { +static struct rockchip_clk_branch rk3288_hclkvio_branch[] __initdata = { + DIV(0, "hclk_vio", "aclk_vio0", 0, + RK3288_CLKSEL_CON(28), 8, 5, DFLAGS), +}; + +static const char *const rk3288_critical_clocks[] __initconst = { "aclk_cpu", "aclk_peri", + "aclk_peri_niu", + "aclk_vio0_niu", + "aclk_vio1_niu", + "aclk_rga_niu", "hclk_peri", + "hclk_vio_niu", + "pclk_alive_niu", "pclk_pd_pmu", + "pclk_pmu_niu", + "pmu_hclk_otg0", + /* pwm-regulators on some boards, so handoff-critical later */ + "pclk_rkpwm", }; -static int __init rk3288_clk_init(struct device_node *np) +static void __iomem *rk3288_cru_base; + +static void __init rk3288_common_init(struct device_node *np, + enum rk3288_variant soc) { - void __iomem *reg_base; - struct clk *clk; + struct rockchip_clk_provider *ctx; - reg_base = of_iomap(np, 0); - if (!reg_base) { + rk3288_cru_base = of_iomap(np, 0); + if (!rk3288_cru_base) { pr_err("%s: could not map cru region\n", __func__); - return -ENOMEM; + return; } - rockchip_clk_init(np, reg_base, CLK_NR_CLKS); - - /* xin12m is created by an cru-internal divider */ - clk = clk_fixed_factor("xin12m", "xin24m", 1, 2, 0); - if (IS_ERR(clk)) - pr_warn("%s: could not register clock xin12m: %ld\n", - __func__, PTR_ERR(clk)); - - clk = clk_fixed_factor("usb480m", "xin24m", 20, 1, 0); - if (IS_ERR(clk)) - pr_warn("%s: could not register clock usb480m: %ld\n", - __func__, PTR_ERR(clk)); - - clk = clk_fixed_factor("hclk_vcodec_pre", - "hclk_vcodec_pre_v", 1, 4, 0); - if (IS_ERR(clk)) - pr_warn("%s: could not register clock hclk_vcodec_pre: %ld\n", - __func__, PTR_ERR(clk)); - - /* Watchdog pclk is controlled by RK3288_SGRF_SOC_CON0[1]. */ - clk = clk_fixed_factor("pclk_wdt", "pclk_pd_alive", 1, 1, 0); - if (IS_ERR(clk)) - pr_warn("%s: could not register clock pclk_wdt: %ld\n", - __func__, PTR_ERR(clk)); - else - rockchip_clk_add_lookup(clk, PCLK_WDT); + ctx = rockchip_clk_init(np, rk3288_cru_base, CLK_NR_CLKS); + if (IS_ERR(ctx)) { + pr_err("%s: rockchip clk init failed\n", __func__); + return; + } - rockchip_clk_register_plls(rk3288_pll_clks, + rockchip_clk_register_plls(ctx, rk3288_pll_clks, ARRAY_SIZE(rk3288_pll_clks), RK3288_GRF_SOC_STATUS1); - rockchip_clk_register_branches(rk3288_clk_branches, + rockchip_clk_register_branches(ctx, rk3288_clk_branches, ARRAY_SIZE(rk3288_clk_branches)); + + if (soc == RK3288W_CRU) + rockchip_clk_register_branches(ctx, rk3288w_hclkvio_branch, + ARRAY_SIZE(rk3288w_hclkvio_branch)); + else + rockchip_clk_register_branches(ctx, rk3288_hclkvio_branch, + ARRAY_SIZE(rk3288_hclkvio_branch)); + rockchip_clk_protect_critical(rk3288_critical_clocks, ARRAY_SIZE(rk3288_critical_clocks)); - rockchip_clk_register_armclk(ARMCLK, "armclk", + rockchip_clk_register_armclk(ctx, ARMCLK, "armclk", mux_armclk_p, ARRAY_SIZE(mux_armclk_p), &rk3288_cpuclk_data, rk3288_cpuclk_rates, ARRAY_SIZE(rk3288_cpuclk_rates)); - return 0; + + rockchip_clk_of_add_provider(np, ctx); +} + +static void __init rk3288_clk_init(struct device_node *np) +{ + rk3288_common_init(np, RK3288_CRU); } CLK_OF_DECLARE(rk3288_cru, "rockchip,rk3288-cru", rk3288_clk_init); + +static void __init rk3288w_clk_init(struct device_node *np) +{ + rk3288_common_init(np, RK3288W_CRU); +} +CLK_OF_DECLARE(rk3288w_cru, "rockchip,rk3288w-cru", rk3288w_clk_init); diff --git a/drivers/clk/rockchip/clk-rk3568.c b/drivers/clk/rockchip/clk-rk3568.c new file mode 100644 index 0000000000..4605158500 --- /dev/null +++ b/drivers/clk/rockchip/clk-rk3568.c @@ -0,0 +1,1706 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2021 Rockchip Electronics Co. Ltd. + * Author: Elaine Zhang <zhangqing@rock-chips.com> + */ + +#include <common.h> +#include <linux/clk.h> +#include <of.h> +#include <of_address.h> +#include <linux/barebox-wrapper.h> +#include <init.h> +#include <linux/spinlock.h> +#include <of_device.h> +#include <dt-bindings/clock/rk3568-cru.h> +#include "clk.h" + +#define RK3568_GRF_SOC_STATUS0 0x580 + +enum rk3568_pmu_plls { + ppll, hpll, +}; + +enum rk3568_plls { + apll, dpll, gpll, cpll, npll, vpll, +}; + +static struct rockchip_pll_rate_table rk3568_pll_rates[] = { + /* _mhz, _refdiv, _fbdiv, _postdiv1, _postdiv2, _dsmpd, _frac */ + RK3036_PLL_RATE(2208000000, 1, 92, 1, 1, 1, 0), + RK3036_PLL_RATE(2184000000, 1, 91, 1, 1, 1, 0), + RK3036_PLL_RATE(2160000000, 1, 90, 1, 1, 1, 0), + RK3036_PLL_RATE(2088000000, 1, 87, 1, 1, 1, 0), + RK3036_PLL_RATE(2064000000, 1, 86, 1, 1, 1, 0), + RK3036_PLL_RATE(2040000000, 1, 85, 1, 1, 1, 0), + RK3036_PLL_RATE(2016000000, 1, 84, 1, 1, 1, 0), + RK3036_PLL_RATE(1992000000, 1, 83, 1, 1, 1, 0), + RK3036_PLL_RATE(1920000000, 1, 80, 1, 1, 1, 0), + RK3036_PLL_RATE(1896000000, 1, 79, 1, 1, 1, 0), + RK3036_PLL_RATE(1800000000, 1, 75, 1, 1, 1, 0), + RK3036_PLL_RATE(1704000000, 1, 71, 1, 1, 1, 0), + RK3036_PLL_RATE(1608000000, 1, 67, 1, 1, 1, 0), + RK3036_PLL_RATE(1600000000, 3, 200, 1, 1, 1, 0), + RK3036_PLL_RATE(1584000000, 1, 132, 2, 1, 1, 0), + RK3036_PLL_RATE(1560000000, 1, 130, 2, 1, 1, 0), + RK3036_PLL_RATE(1536000000, 1, 128, 2, 1, 1, 0), + RK3036_PLL_RATE(1512000000, 1, 126, 2, 1, 1, 0), + RK3036_PLL_RATE(1488000000, 1, 124, 2, 1, 1, 0), + RK3036_PLL_RATE(1464000000, 1, 122, 2, 1, 1, 0), + RK3036_PLL_RATE(1440000000, 1, 120, 2, 1, 1, 0), + RK3036_PLL_RATE(1416000000, 1, 118, 2, 1, 1, 0), + RK3036_PLL_RATE(1400000000, 3, 350, 2, 1, 1, 0), + RK3036_PLL_RATE(1392000000, 1, 116, 2, 1, 1, 0), + RK3036_PLL_RATE(1368000000, 1, 114, 2, 1, 1, 0), + RK3036_PLL_RATE(1344000000, 1, 112, 2, 1, 1, 0), + RK3036_PLL_RATE(1320000000, 1, 110, 2, 1, 1, 0), + RK3036_PLL_RATE(1296000000, 1, 108, 2, 1, 1, 0), + RK3036_PLL_RATE(1272000000, 1, 106, 2, 1, 1, 0), + RK3036_PLL_RATE(1248000000, 1, 104, 2, 1, 1, 0), + RK3036_PLL_RATE(1200000000, 1, 100, 2, 1, 1, 0), + RK3036_PLL_RATE(1188000000, 1, 99, 2, 1, 1, 0), + RK3036_PLL_RATE(1104000000, 1, 92, 2, 1, 1, 0), + RK3036_PLL_RATE(1100000000, 3, 275, 2, 1, 1, 0), + RK3036_PLL_RATE(1008000000, 1, 84, 2, 1, 1, 0), + RK3036_PLL_RATE(1000000000, 3, 250, 2, 1, 1, 0), + RK3036_PLL_RATE(912000000, 1, 76, 2, 1, 1, 0), + RK3036_PLL_RATE(816000000, 1, 68, 2, 1, 1, 0), + RK3036_PLL_RATE(800000000, 3, 200, 2, 1, 1, 0), + RK3036_PLL_RATE(700000000, 3, 350, 4, 1, 1, 0), + RK3036_PLL_RATE(696000000, 1, 116, 4, 1, 1, 0), + RK3036_PLL_RATE(600000000, 1, 100, 4, 1, 1, 0), + RK3036_PLL_RATE(594000000, 1, 99, 4, 1, 1, 0), + RK3036_PLL_RATE(500000000, 1, 125, 6, 1, 1, 0), + RK3036_PLL_RATE(408000000, 1, 68, 2, 2, 1, 0), + RK3036_PLL_RATE(312000000, 1, 78, 6, 1, 1, 0), + RK3036_PLL_RATE(216000000, 1, 72, 4, 2, 1, 0), + RK3036_PLL_RATE(200000000, 1, 100, 3, 4, 1, 0), + RK3036_PLL_RATE(148500000, 1, 99, 4, 4, 1, 0), + RK3036_PLL_RATE(100000000, 1, 150, 6, 6, 1, 0), + RK3036_PLL_RATE(96000000, 1, 96, 6, 4, 1, 0), + RK3036_PLL_RATE(74250000, 2, 99, 4, 4, 1, 0), + { /* sentinel */ }, +}; + +#define RK3568_DIV_ATCLK_CORE_MASK 0x1f +#define RK3568_DIV_ATCLK_CORE_SHIFT 0 +#define RK3568_DIV_GICCLK_CORE_MASK 0x1f +#define RK3568_DIV_GICCLK_CORE_SHIFT 8 +#define RK3568_DIV_PCLK_CORE_MASK 0x1f +#define RK3568_DIV_PCLK_CORE_SHIFT 0 +#define RK3568_DIV_PERIPHCLK_CORE_MASK 0x1f +#define RK3568_DIV_PERIPHCLK_CORE_SHIFT 8 +#define RK3568_DIV_ACLK_CORE_MASK 0x1f +#define RK3568_DIV_ACLK_CORE_SHIFT 8 + +#define RK3568_DIV_SCLK_CORE_MASK 0xf +#define RK3568_DIV_SCLK_CORE_SHIFT 0 +#define RK3568_MUX_SCLK_CORE_MASK 0x3 +#define RK3568_MUX_SCLK_CORE_SHIFT 8 +#define RK3568_MUX_SCLK_CORE_NPLL_MASK 0x1 +#define RK3568_MUX_SCLK_CORE_NPLL_SHIFT 15 +#define RK3568_MUX_CLK_CORE_APLL_MASK 0x1 +#define RK3568_MUX_CLK_CORE_APLL_SHIFT 7 +#define RK3568_MUX_CLK_PVTPLL_MASK 0x1 +#define RK3568_MUX_CLK_PVTPLL_SHIFT 15 + +#define RK3568_CLKSEL1(_sclk_core) \ +{ \ + .reg = RK3568_CLKSEL_CON(2), \ + .val = HIWORD_UPDATE(_sclk_core, RK3568_MUX_SCLK_CORE_NPLL_MASK, \ + RK3568_MUX_SCLK_CORE_NPLL_SHIFT) | \ + HIWORD_UPDATE(_sclk_core, RK3568_MUX_SCLK_CORE_MASK, \ + RK3568_MUX_SCLK_CORE_SHIFT) | \ + HIWORD_UPDATE(1, RK3568_DIV_SCLK_CORE_MASK, \ + RK3568_DIV_SCLK_CORE_SHIFT), \ +} + +#define RK3568_CLKSEL2(_aclk_core) \ +{ \ + .reg = RK3568_CLKSEL_CON(5), \ + .val = HIWORD_UPDATE(_aclk_core, RK3568_DIV_ACLK_CORE_MASK, \ + RK3568_DIV_ACLK_CORE_SHIFT), \ +} + +#define RK3568_CLKSEL3(_atclk_core, _gic_core) \ +{ \ + .reg = RK3568_CLKSEL_CON(3), \ + .val = HIWORD_UPDATE(_atclk_core, RK3568_DIV_ATCLK_CORE_MASK, \ + RK3568_DIV_ATCLK_CORE_SHIFT) | \ + HIWORD_UPDATE(_gic_core, RK3568_DIV_GICCLK_CORE_MASK, \ + RK3568_DIV_GICCLK_CORE_SHIFT), \ +} + +#define RK3568_CLKSEL4(_pclk_core, _periph_core) \ +{ \ + .reg = RK3568_CLKSEL_CON(4), \ + .val = HIWORD_UPDATE(_pclk_core, RK3568_DIV_PCLK_CORE_MASK, \ + RK3568_DIV_PCLK_CORE_SHIFT) | \ + HIWORD_UPDATE(_periph_core, RK3568_DIV_PERIPHCLK_CORE_MASK, \ + RK3568_DIV_PERIPHCLK_CORE_SHIFT), \ +} + +#define RK3568_CPUCLK_RATE(_prate, _sclk, _acore, _atcore, _gicclk, _pclk, _periph) \ +{ \ + .prate = _prate##U, \ + .divs = { \ + RK3568_CLKSEL1(_sclk), \ + RK3568_CLKSEL2(_acore), \ + RK3568_CLKSEL3(_atcore, _gicclk), \ + RK3568_CLKSEL4(_pclk, _periph), \ + }, \ +} + +static struct rockchip_cpuclk_rate_table rk3568_cpuclk_rates[] __initdata = { + RK3568_CPUCLK_RATE(1800000000, 0, 1, 7, 7, 7, 7), + RK3568_CPUCLK_RATE(1704000000, 0, 1, 7, 7, 7, 7), + RK3568_CPUCLK_RATE(1608000000, 0, 1, 5, 5, 5, 5), + RK3568_CPUCLK_RATE(1584000000, 0, 1, 5, 5, 5, 5), + RK3568_CPUCLK_RATE(1560000000, 0, 1, 5, 5, 5, 5), + RK3568_CPUCLK_RATE(1536000000, 0, 1, 5, 5, 5, 5), + RK3568_CPUCLK_RATE(1512000000, 0, 1, 5, 5, 5, 5), + RK3568_CPUCLK_RATE(1488000000, 0, 1, 5, 5, 5, 5), + RK3568_CPUCLK_RATE(1464000000, 0, 1, 5, 5, 5, 5), + RK3568_CPUCLK_RATE(1440000000, 0, 1, 5, 5, 5, 5), + RK3568_CPUCLK_RATE(1416000000, 0, 1, 5, 5, 5, 5), + RK3568_CPUCLK_RATE(1392000000, 0, 1, 5, 5, 5, 5), + RK3568_CPUCLK_RATE(1368000000, 0, 1, 5, 5, 5, 5), + RK3568_CPUCLK_RATE(1344000000, 0, 1, 5, 5, 5, 5), + RK3568_CPUCLK_RATE(1320000000, 0, 1, 5, 5, 5, 5), + RK3568_CPUCLK_RATE(1296000000, 0, 1, 5, 5, 5, 5), + RK3568_CPUCLK_RATE(1272000000, 0, 1, 5, 5, 5, 5), + RK3568_CPUCLK_RATE(1248000000, 0, 1, 5, 5, 5, 5), + RK3568_CPUCLK_RATE(1224000000, 0, 1, 5, 5, 5, 5), + RK3568_CPUCLK_RATE(1200000000, 0, 1, 3, 3, 3, 3), + RK3568_CPUCLK_RATE(1104000000, 0, 1, 3, 3, 3, 3), + RK3568_CPUCLK_RATE(1008000000, 0, 1, 3, 3, 3, 3), + RK3568_CPUCLK_RATE(912000000, 0, 1, 3, 3, 3, 3), + RK3568_CPUCLK_RATE(816000000, 0, 1, 3, 3, 3, 3), + RK3568_CPUCLK_RATE(696000000, 0, 1, 3, 3, 3, 3), + RK3568_CPUCLK_RATE(600000000, 0, 1, 3, 3, 3, 3), + RK3568_CPUCLK_RATE(408000000, 0, 1, 3, 3, 3, 3), + RK3568_CPUCLK_RATE(312000000, 0, 1, 3, 3, 3, 3), + RK3568_CPUCLK_RATE(216000000, 0, 1, 3, 3, 3, 3), + RK3568_CPUCLK_RATE(96000000, 0, 1, 3, 3, 3, 3), +}; + +static const struct rockchip_cpuclk_reg_data rk3568_cpuclk_data = { + .core_reg[0] = RK3568_CLKSEL_CON(0), + .div_core_shift[0] = 0, + .div_core_mask[0] = 0x1f, + .core_reg[1] = RK3568_CLKSEL_CON(0), + .div_core_shift[1] = 8, + .div_core_mask[1] = 0x1f, + .core_reg[2] = RK3568_CLKSEL_CON(1), + .div_core_shift[2] = 0, + .div_core_mask[2] = 0x1f, + .core_reg[3] = RK3568_CLKSEL_CON(1), + .div_core_shift[3] = 8, + .div_core_mask[3] = 0x1f, + .num_cores = 4, + .mux_core_alt = 1, + .mux_core_main = 0, + .mux_core_shift = 6, + .mux_core_mask = 0x1, +}; + +PNAME(mux_pll_p) = { "xin24m" }; +PNAME(mux_usb480m_p) = { "xin24m", "usb480m_phy", "clk_rtc_32k" }; +PNAME(mux_armclk_p) = { "apll", "gpll" }; +PNAME(clk_i2s0_8ch_tx_p) = { "clk_i2s0_8ch_tx_src", "clk_i2s0_8ch_tx_frac", "i2s0_mclkin", "xin_osc0_half" }; +PNAME(clk_i2s0_8ch_rx_p) = { "clk_i2s0_8ch_rx_src", "clk_i2s0_8ch_rx_frac", "i2s0_mclkin", "xin_osc0_half" }; +PNAME(clk_i2s1_8ch_tx_p) = { "clk_i2s1_8ch_tx_src", "clk_i2s1_8ch_tx_frac", "i2s1_mclkin", "xin_osc0_half" }; +PNAME(clk_i2s1_8ch_rx_p) = { "clk_i2s1_8ch_rx_src", "clk_i2s1_8ch_rx_frac", "i2s1_mclkin", "xin_osc0_half" }; +PNAME(clk_i2s2_2ch_p) = { "clk_i2s2_2ch_src", "clk_i2s2_2ch_frac", "i2s2_mclkin", "xin_osc0_half "}; +PNAME(clk_i2s3_2ch_tx_p) = { "clk_i2s3_2ch_tx_src", "clk_i2s3_2ch_tx_frac", "i2s3_mclkin", "xin_osc0_half" }; +PNAME(clk_i2s3_2ch_rx_p) = { "clk_i2s3_2ch_rx_src", "clk_i2s3_2ch_rx_frac", "i2s3_mclkin", "xin_osc0_half" }; +PNAME(mclk_spdif_8ch_p) = { "mclk_spdif_8ch_src", "mclk_spdif_8ch_frac" }; +PNAME(sclk_audpwm_p) = { "sclk_audpwm_src", "sclk_audpwm_frac" }; +PNAME(sclk_uart1_p) = { "clk_uart1_src", "clk_uart1_frac", "xin24m" }; +PNAME(sclk_uart2_p) = { "clk_uart2_src", "clk_uart2_frac", "xin24m" }; +PNAME(sclk_uart3_p) = { "clk_uart3_src", "clk_uart3_frac", "xin24m" }; +PNAME(sclk_uart4_p) = { "clk_uart4_src", "clk_uart4_frac", "xin24m" }; +PNAME(sclk_uart5_p) = { "clk_uart5_src", "clk_uart5_frac", "xin24m" }; +PNAME(sclk_uart6_p) = { "clk_uart6_src", "clk_uart6_frac", "xin24m" }; +PNAME(sclk_uart7_p) = { "clk_uart7_src", "clk_uart7_frac", "xin24m" }; +PNAME(sclk_uart8_p) = { "clk_uart8_src", "clk_uart8_frac", "xin24m" }; +PNAME(sclk_uart9_p) = { "clk_uart9_src", "clk_uart9_frac", "xin24m" }; +PNAME(sclk_uart0_p) = { "sclk_uart0_div", "sclk_uart0_frac", "xin24m" }; +PNAME(clk_rtc32k_pmu_p) = { "clk_32k_pvtm", "xin32k", "clk_rtc32k_frac" }; +PNAME(mpll_gpll_cpll_npll_p) = { "mpll", "gpll", "cpll", "npll" }; +PNAME(gpll_cpll_npll_p) = { "gpll", "cpll", "npll" }; +PNAME(npll_gpll_p) = { "npll", "gpll" }; +PNAME(cpll_gpll_p) = { "cpll", "gpll" }; +PNAME(gpll_cpll_p) = { "gpll", "cpll" }; +PNAME(gpll_cpll_npll_vpll_p) = { "gpll", "cpll", "npll", "vpll" }; +PNAME(apll_gpll_npll_p) = { "apll", "gpll", "npll" }; +PNAME(sclk_core_pre_p) = { "sclk_core_src", "npll" }; +PNAME(gpll150_gpll100_gpll75_xin24m_p) = { "gpll_150m", "gpll_100m", "gpll_75m", "xin24m" }; +PNAME(clk_gpu_pre_mux_p) = { "clk_gpu_src", "gpu_pvtpll_out" }; +PNAME(clk_npu_pre_ndft_p) = { "clk_npu_src", "dummy"}; +PNAME(clk_npu_p) = { "clk_npu_pre_ndft", "npu_pvtpll_out" }; +PNAME(dpll_gpll_cpll_p) = { "dpll", "gpll", "cpll" }; +PNAME(clk_ddr1x_p) = { "clk_ddrphy1x_src", "dpll" }; +PNAME(gpll200_gpll150_gpll100_xin24m_p) = { "gpll_200m", "gpll_150m", "gpll_100m", "xin24m" }; +PNAME(gpll100_gpll75_gpll50_p) = { "gpll_100m", "gpll_75m", "cpll_50m" }; +PNAME(i2s0_mclkout_tx_p) = { "clk_i2s0_8ch_tx", "xin_osc0_half" }; +PNAME(i2s0_mclkout_rx_p) = { "clk_i2s0_8ch_rx", "xin_osc0_half" }; +PNAME(i2s1_mclkout_tx_p) = { "clk_i2s1_8ch_tx", "xin_osc0_half" }; +PNAME(i2s1_mclkout_rx_p) = { "clk_i2s1_8ch_rx", "xin_osc0_half" }; +PNAME(i2s2_mclkout_p) = { "clk_i2s2_2ch", "xin_osc0_half" }; +PNAME(i2s3_mclkout_tx_p) = { "clk_i2s3_2ch_tx", "xin_osc0_half" }; +PNAME(i2s3_mclkout_rx_p) = { "clk_i2s3_2ch_rx", "xin_osc0_half" }; +PNAME(mclk_pdm_p) = { "gpll_300m", "cpll_250m", "gpll_200m", "gpll_100m" }; +PNAME(clk_i2c_p) = { "gpll_200m", "gpll_100m", "xin24m", "cpll_100m" }; +PNAME(gpll200_gpll150_gpll100_p) = { "gpll_200m", "gpll_150m", "gpll_100m" }; +PNAME(gpll300_gpll200_gpll100_p) = { "gpll_300m", "gpll_200m", "gpll_100m" }; +PNAME(clk_nandc_p) = { "gpll_200m", "gpll_150m", "cpll_100m", "xin24m" }; +PNAME(sclk_sfc_p) = { "xin24m", "cpll_50m", "gpll_75m", "gpll_100m", "cpll_125m", "gpll_150m" }; +PNAME(gpll200_gpll150_cpll125_p) = { "gpll_200m", "gpll_150m", "cpll_125m" }; +PNAME(cclk_emmc_p) = { "xin24m", "gpll_200m", "gpll_150m", "cpll_100m", "cpll_50m", "clk_osc0_div_375k" }; +PNAME(aclk_pipe_p) = { "gpll_400m", "gpll_300m", "gpll_200m", "xin24m" }; +PNAME(gpll200_cpll125_p) = { "gpll_200m", "cpll_125m" }; +PNAME(gpll300_gpll200_gpll100_xin24m_p) = { "gpll_300m", "gpll_200m", "gpll_100m", "xin24m" }; +PNAME(clk_sdmmc_p) = { "xin24m", "gpll_400m", "gpll_300m", "cpll_100m", "cpll_50m", "clk_osc0_div_750k" }; +PNAME(cpll125_cpll50_cpll25_xin24m_p) = { "cpll_125m", "cpll_50m", "cpll_25m", "xin24m" }; +PNAME(clk_gmac_ptp_p) = { "cpll_62p5", "gpll_100m", "cpll_50m", "xin24m" }; +PNAME(cpll333_gpll300_gpll200_p) = { "cpll_333m", "gpll_300m", "gpll_200m" }; +PNAME(cpll_gpll_hpll_p) = { "cpll", "gpll", "hpll" }; +PNAME(gpll_usb480m_xin24m_p) = { "gpll", "usb480m", "xin24m", "xin24m" }; +PNAME(gpll300_cpll250_gpll100_xin24m_p) = { "gpll_300m", "cpll_250m", "gpll_100m", "xin24m" }; +PNAME(cpll_gpll_hpll_vpll_p) = { "cpll", "gpll", "hpll", "vpll" }; +PNAME(hpll_vpll_gpll_cpll_p) = { "hpll", "vpll", "gpll", "cpll" }; +PNAME(gpll400_cpll333_gpll200_p) = { "gpll_400m", "cpll_333m", "gpll_200m" }; +PNAME(gpll100_gpll75_cpll50_xin24m_p) = { "gpll_100m", "gpll_75m", "cpll_50m", "xin24m" }; +PNAME(xin24m_gpll100_cpll100_p) = { "xin24m", "gpll_100m", "cpll_100m" }; +PNAME(gpll_cpll_usb480m_p) = { "gpll", "cpll", "usb480m" }; +PNAME(gpll100_xin24m_cpll100_p) = { "gpll_100m", "xin24m", "cpll_100m" }; +PNAME(gpll200_xin24m_cpll100_p) = { "gpll_200m", "xin24m", "cpll_100m" }; +PNAME(xin24m_32k_p) = { "xin24m", "clk_rtc_32k" }; +PNAME(cpll500_gpll400_gpll300_xin24m_p) = { "cpll_500m", "gpll_400m", "gpll_300m", "xin24m" }; +PNAME(gpll400_gpll300_gpll200_xin24m_p) = { "gpll_400m", "gpll_300m", "gpll_200m", "xin24m" }; +PNAME(xin24m_cpll100_p) = { "xin24m", "cpll_100m" }; +PNAME(ppll_usb480m_cpll_gpll_p) = { "ppll", "usb480m", "cpll", "gpll"}; +PNAME(clk_usbphy0_ref_p) = { "clk_ref24m", "xin_osc0_usbphy0_g" }; +PNAME(clk_usbphy1_ref_p) = { "clk_ref24m", "xin_osc0_usbphy1_g" }; +PNAME(clk_mipidsiphy0_ref_p) = { "clk_ref24m", "xin_osc0_mipidsiphy0_g" }; +PNAME(clk_mipidsiphy1_ref_p) = { "clk_ref24m", "xin_osc0_mipidsiphy1_g" }; +PNAME(clk_wifi_p) = { "clk_wifi_osc0", "clk_wifi_div" }; +PNAME(clk_pciephy0_ref_p) = { "clk_pciephy0_osc0", "clk_pciephy0_div" }; +PNAME(clk_pciephy1_ref_p) = { "clk_pciephy1_osc0", "clk_pciephy1_div" }; +PNAME(clk_pciephy2_ref_p) = { "clk_pciephy2_osc0", "clk_pciephy2_div" }; +PNAME(mux_gmac0_p) = { "clk_mac0_2top", "gmac0_clkin" }; +PNAME(mux_gmac0_rgmii_speed_p) = { "clk_gmac0", "clk_gmac0", "clk_gmac0_tx_div50", "clk_gmac0_tx_div5" }; +PNAME(mux_gmac0_rmii_speed_p) = { "clk_gmac0_rx_div20", "clk_gmac0_rx_div2" }; +PNAME(mux_gmac0_rx_tx_p) = { "clk_gmac0_rgmii_speed", "clk_gmac0_rmii_speed", "clk_gmac0_xpcs_mii" }; +PNAME(mux_gmac1_p) = { "clk_mac1_2top", "gmac1_clkin" }; +PNAME(mux_gmac1_rgmii_speed_p) = { "clk_gmac1", "clk_gmac1", "clk_gmac1_tx_div50", "clk_gmac1_tx_div5" }; +PNAME(mux_gmac1_rmii_speed_p) = { "clk_gmac1_rx_div20", "clk_gmac1_rx_div2" }; +PNAME(mux_gmac1_rx_tx_p) = { "clk_gmac1_rgmii_speed", "clk_gmac1_rmii_speed", "clk_gmac1_xpcs_mii" }; +PNAME(clk_hdmi_ref_p) = { "hpll", "hpll_ph0" }; +PNAME(clk_pdpmu_p) = { "ppll", "gpll" }; +PNAME(clk_mac_2top_p) = { "cpll_125m", "cpll_50m", "cpll_25m", "ppll" }; +PNAME(clk_pwm0_p) = { "xin24m", "clk_pdpmu" }; +PNAME(aclk_rkvdec_pre_p) = { "gpll", "cpll" }; +PNAME(clk_rkvdec_core_p) = { "gpll", "cpll", "dummy_npll", "dummy_vpll" }; + +static struct rockchip_pll_clock rk3568_pmu_pll_clks[] __initdata = { + [ppll] = PLL(pll_rk3328, PLL_PPLL, "ppll", mux_pll_p, + 0, RK3568_PMU_PLL_CON(0), + RK3568_PMU_MODE_CON0, 0, 4, 0, rk3568_pll_rates), + [hpll] = PLL(pll_rk3328, PLL_HPLL, "hpll", mux_pll_p, + 0, RK3568_PMU_PLL_CON(16), + RK3568_PMU_MODE_CON0, 2, 7, 0, rk3568_pll_rates), +}; + +static struct rockchip_pll_clock rk3568_pll_clks[] __initdata = { + [apll] = PLL(pll_rk3328, PLL_APLL, "apll", mux_pll_p, + 0, RK3568_PLL_CON(0), + RK3568_MODE_CON0, 0, 0, 0, rk3568_pll_rates), + [dpll] = PLL(pll_rk3328, PLL_DPLL, "dpll", mux_pll_p, + 0, RK3568_PLL_CON(8), + RK3568_MODE_CON0, 2, 1, 0, NULL), + [cpll] = PLL(pll_rk3328, PLL_CPLL, "cpll", mux_pll_p, + 0, RK3568_PLL_CON(24), + RK3568_MODE_CON0, 4, 2, 0, rk3568_pll_rates), + [gpll] = PLL(pll_rk3328, PLL_GPLL, "gpll", mux_pll_p, + 0, RK3568_PLL_CON(16), + RK3568_MODE_CON0, 6, 3, 0, rk3568_pll_rates), + [npll] = PLL(pll_rk3328, PLL_NPLL, "npll", mux_pll_p, + 0, RK3568_PLL_CON(32), + RK3568_MODE_CON0, 10, 5, 0, rk3568_pll_rates), + [vpll] = PLL(pll_rk3328, PLL_VPLL, "vpll", mux_pll_p, + 0, RK3568_PLL_CON(40), + RK3568_MODE_CON0, 12, 6, 0, rk3568_pll_rates), +}; + +#define MFLAGS CLK_MUX_HIWORD_MASK +#define DFLAGS CLK_DIVIDER_HIWORD_MASK +#define GFLAGS (CLK_GATE_HIWORD_MASK | CLK_GATE_SET_TO_DISABLE) + +static struct rockchip_clk_branch rk3568_i2s0_8ch_tx_fracmux __initdata = + MUX(CLK_I2S0_8CH_TX, "clk_i2s0_8ch_tx", clk_i2s0_8ch_tx_p, CLK_SET_RATE_PARENT, + RK3568_CLKSEL_CON(11), 10, 2, MFLAGS); + +static struct rockchip_clk_branch rk3568_i2s0_8ch_rx_fracmux __initdata = + MUX(CLK_I2S0_8CH_RX, "clk_i2s0_8ch_rx", clk_i2s0_8ch_rx_p, CLK_SET_RATE_PARENT, + RK3568_CLKSEL_CON(13), 10, 2, MFLAGS); + +static struct rockchip_clk_branch rk3568_i2s1_8ch_tx_fracmux __initdata = + MUX(CLK_I2S1_8CH_TX, "clk_i2s1_8ch_tx", clk_i2s1_8ch_tx_p, CLK_SET_RATE_PARENT, + RK3568_CLKSEL_CON(15), 10, 2, MFLAGS); + +static struct rockchip_clk_branch rk3568_i2s1_8ch_rx_fracmux __initdata = + MUX(CLK_I2S1_8CH_RX, "clk_i2s1_8ch_rx", clk_i2s1_8ch_rx_p, CLK_SET_RATE_PARENT, + RK3568_CLKSEL_CON(17), 10, 2, MFLAGS); + +static struct rockchip_clk_branch rk3568_i2s2_2ch_fracmux __initdata = + MUX(CLK_I2S2_2CH, "clk_i2s2_2ch", clk_i2s2_2ch_p, CLK_SET_RATE_PARENT, + RK3568_CLKSEL_CON(19), 10, 2, MFLAGS); + +static struct rockchip_clk_branch rk3568_i2s3_2ch_tx_fracmux __initdata = + MUX(CLK_I2S3_2CH_TX, "clk_i2s3_2ch_tx", clk_i2s3_2ch_tx_p, CLK_SET_RATE_PARENT, + RK3568_CLKSEL_CON(21), 10, 2, MFLAGS); + +static struct rockchip_clk_branch rk3568_i2s3_2ch_rx_fracmux __initdata = + MUX(CLK_I2S3_2CH_RX, "clk_i2s3_2ch_rx", clk_i2s3_2ch_rx_p, CLK_SET_RATE_PARENT, + RK3568_CLKSEL_CON(83), 10, 2, MFLAGS); + +static struct rockchip_clk_branch rk3568_spdif_8ch_fracmux __initdata = + MUX(MCLK_SPDIF_8CH, "mclk_spdif_8ch", mclk_spdif_8ch_p, CLK_SET_RATE_PARENT, + RK3568_CLKSEL_CON(23), 15, 1, MFLAGS); + +static struct rockchip_clk_branch rk3568_audpwm_fracmux __initdata = + MUX(SCLK_AUDPWM, "sclk_audpwm", sclk_audpwm_p, CLK_SET_RATE_PARENT, + RK3568_CLKSEL_CON(25), 15, 1, MFLAGS); + +static struct rockchip_clk_branch rk3568_uart1_fracmux __initdata = + MUX(0, "sclk_uart1_mux", sclk_uart1_p, CLK_SET_RATE_PARENT, + RK3568_CLKSEL_CON(52), 12, 2, MFLAGS); + +static struct rockchip_clk_branch rk3568_uart2_fracmux __initdata = + MUX(0, "sclk_uart2_mux", sclk_uart2_p, CLK_SET_RATE_PARENT, + RK3568_CLKSEL_CON(54), 12, 2, MFLAGS); + +static struct rockchip_clk_branch rk3568_uart3_fracmux __initdata = + MUX(0, "sclk_uart3_mux", sclk_uart3_p, CLK_SET_RATE_PARENT, + RK3568_CLKSEL_CON(56), 12, 2, MFLAGS); + +static struct rockchip_clk_branch rk3568_uart4_fracmux __initdata = + MUX(0, "sclk_uart4_mux", sclk_uart4_p, CLK_SET_RATE_PARENT, + RK3568_CLKSEL_CON(58), 12, 2, MFLAGS); + +static struct rockchip_clk_branch rk3568_uart5_fracmux __initdata = + MUX(0, "sclk_uart5_mux", sclk_uart5_p, CLK_SET_RATE_PARENT, + RK3568_CLKSEL_CON(60), 12, 2, MFLAGS); + +static struct rockchip_clk_branch rk3568_uart6_fracmux __initdata = + MUX(0, "sclk_uart6_mux", sclk_uart6_p, CLK_SET_RATE_PARENT, + RK3568_CLKSEL_CON(62), 12, 2, MFLAGS); + +static struct rockchip_clk_branch rk3568_uart7_fracmux __initdata = + MUX(0, "sclk_uart7_mux", sclk_uart7_p, CLK_SET_RATE_PARENT, + RK3568_CLKSEL_CON(64), 12, 2, MFLAGS); + +static struct rockchip_clk_branch rk3568_uart8_fracmux __initdata = + MUX(0, "sclk_uart8_mux", sclk_uart8_p, CLK_SET_RATE_PARENT, + RK3568_CLKSEL_CON(66), 12, 2, MFLAGS); + +static struct rockchip_clk_branch rk3568_uart9_fracmux __initdata = + MUX(0, "sclk_uart9_mux", sclk_uart9_p, CLK_SET_RATE_PARENT, + RK3568_CLKSEL_CON(68), 12, 2, MFLAGS); + +static struct rockchip_clk_branch rk3568_uart0_fracmux __initdata = + MUX(0, "sclk_uart0_mux", sclk_uart0_p, CLK_SET_RATE_PARENT, + RK3568_PMU_CLKSEL_CON(4), 10, 2, MFLAGS); + +static struct rockchip_clk_branch rk3568_rtc32k_pmu_fracmux __initdata = + MUX(CLK_RTC_32K, "clk_rtc_32k", clk_rtc32k_pmu_p, CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT, + RK3568_PMU_CLKSEL_CON(0), 6, 2, MFLAGS); + +static struct rockchip_clk_branch rk3568_clk_branches[] __initdata = { + /* + * Clock-Architecture Diagram 1 + */ + /* SRC_CLK */ + COMPOSITE_NOMUX(0, "gpll_400m", "gpll", CLK_IGNORE_UNUSED, + RK3568_CLKSEL_CON(75), 0, 5, DFLAGS, + RK3568_CLKGATE_CON(35), 0, GFLAGS), + COMPOSITE_NOMUX(0, "gpll_300m", "gpll", CLK_IGNORE_UNUSED, + RK3568_CLKSEL_CON(75), 8, 5, DFLAGS, + RK3568_CLKGATE_CON(35), 1, GFLAGS), + COMPOSITE_NOMUX(0, "gpll_200m", "gpll", CLK_IGNORE_UNUSED, + RK3568_CLKSEL_CON(76), 0, 5, DFLAGS, + RK3568_CLKGATE_CON(35), 2, GFLAGS), + COMPOSITE_NOMUX(0, "gpll_150m", "gpll", CLK_IGNORE_UNUSED, + RK3568_CLKSEL_CON(76), 8, 5, DFLAGS, + RK3568_CLKGATE_CON(35), 3, GFLAGS), + COMPOSITE_NOMUX(0, "gpll_100m", "gpll", CLK_IGNORE_UNUSED, + RK3568_CLKSEL_CON(77), 0, 5, DFLAGS, + RK3568_CLKGATE_CON(35), 4, GFLAGS), + COMPOSITE_NOMUX(0, "gpll_75m", "gpll", CLK_IGNORE_UNUSED, + RK3568_CLKSEL_CON(77), 8, 5, DFLAGS, + RK3568_CLKGATE_CON(35), 5, GFLAGS), + COMPOSITE_NOMUX(0, "gpll_20m", "gpll", CLK_IGNORE_UNUSED, + RK3568_CLKSEL_CON(78), 0, 6, DFLAGS, + RK3568_CLKGATE_CON(35), 6, GFLAGS), + COMPOSITE_NOMUX(CPLL_500M, "cpll_500m", "cpll", CLK_IGNORE_UNUSED, + RK3568_CLKSEL_CON(78), 8, 5, DFLAGS, + RK3568_CLKGATE_CON(35), 7, GFLAGS), + COMPOSITE_NOMUX(CPLL_333M, "cpll_333m", "cpll", CLK_IGNORE_UNUSED, + RK3568_CLKSEL_CON(79), 0, 5, DFLAGS, + RK3568_CLKGATE_CON(35), 8, GFLAGS), + COMPOSITE_NOMUX(CPLL_250M, "cpll_250m", "cpll", CLK_IGNORE_UNUSED, + RK3568_CLKSEL_CON(79), 8, 5, DFLAGS, + RK3568_CLKGATE_CON(35), 9, GFLAGS), + COMPOSITE_NOMUX(CPLL_125M, "cpll_125m", "cpll", CLK_IGNORE_UNUSED, + RK3568_CLKSEL_CON(80), 0, 5, DFLAGS, + RK3568_CLKGATE_CON(35), 10, GFLAGS), + COMPOSITE_NOMUX(CPLL_100M, "cpll_100m", "cpll", CLK_IGNORE_UNUSED, + RK3568_CLKSEL_CON(82), 0, 5, DFLAGS, + RK3568_CLKGATE_CON(35), 11, GFLAGS), + COMPOSITE_NOMUX(CPLL_62P5M, "cpll_62p5", "cpll", CLK_IGNORE_UNUSED, + RK3568_CLKSEL_CON(80), 8, 5, DFLAGS, + RK3568_CLKGATE_CON(35), 12, GFLAGS), + COMPOSITE_NOMUX(CPLL_50M, "cpll_50m", "cpll", CLK_IGNORE_UNUSED, + RK3568_CLKSEL_CON(81), 0, 5, DFLAGS, + RK3568_CLKGATE_CON(35), 13, GFLAGS), + COMPOSITE_NOMUX(CPLL_25M, "cpll_25m", "cpll", CLK_IGNORE_UNUSED, + RK3568_CLKSEL_CON(81), 8, 6, DFLAGS, + RK3568_CLKGATE_CON(35), 14, GFLAGS), + COMPOSITE_NOMUX(0, "clk_osc0_div_750k", "xin24m", CLK_IGNORE_UNUSED, + RK3568_CLKSEL_CON(82), 8, 6, DFLAGS, + RK3568_CLKGATE_CON(35), 15, GFLAGS), + FACTOR(0, "clk_osc0_div_375k", "clk_osc0_div_750k", 0, 1, 2), + FACTOR(0, "xin_osc0_half", "xin24m", 0, 1, 2), + MUX(USB480M, "usb480m", mux_usb480m_p, CLK_SET_RATE_PARENT, + RK3568_MODE_CON0, 14, 2, MFLAGS), + + /* PD_CORE */ + COMPOSITE(0, "sclk_core_src", apll_gpll_npll_p, CLK_IGNORE_UNUSED, + RK3568_CLKSEL_CON(2), 8, 2, MFLAGS, 0, 4, DFLAGS | CLK_DIVIDER_READ_ONLY, + RK3568_CLKGATE_CON(0), 5, GFLAGS), + COMPOSITE_NODIV(0, "sclk_core", sclk_core_pre_p, CLK_IGNORE_UNUSED, + RK3568_CLKSEL_CON(2), 15, 1, MFLAGS, + RK3568_CLKGATE_CON(0), 7, GFLAGS), + + COMPOSITE_NOMUX(0, "atclk_core", "armclk", CLK_IGNORE_UNUSED, + RK3568_CLKSEL_CON(3), 0, 5, DFLAGS | CLK_DIVIDER_READ_ONLY, + RK3568_CLKGATE_CON(0), 8, GFLAGS), + COMPOSITE_NOMUX(0, "gicclk_core", "armclk", CLK_IGNORE_UNUSED, + RK3568_CLKSEL_CON(3), 8, 5, DFLAGS | CLK_DIVIDER_READ_ONLY, + RK3568_CLKGATE_CON(0), 9, GFLAGS), + COMPOSITE_NOMUX(0, "pclk_core_pre", "armclk", CLK_IGNORE_UNUSED, + RK3568_CLKSEL_CON(4), 0, 5, DFLAGS | CLK_DIVIDER_READ_ONLY, + RK3568_CLKGATE_CON(0), 10, GFLAGS), + COMPOSITE_NOMUX(0, "periphclk_core_pre", "armclk", CLK_IGNORE_UNUSED, + RK3568_CLKSEL_CON(4), 8, 5, DFLAGS | CLK_DIVIDER_READ_ONLY, + RK3568_CLKGATE_CON(0), 11, GFLAGS), + COMPOSITE_NOMUX(0, "tsclk_core", "periphclk_core_pre", CLK_IGNORE_UNUSED, + RK3568_CLKSEL_CON(5), 0, 4, DFLAGS | CLK_DIVIDER_READ_ONLY, + RK3568_CLKGATE_CON(0), 14, GFLAGS), + COMPOSITE_NOMUX(0, "cntclk_core", "periphclk_core_pre", CLK_IGNORE_UNUSED, + RK3568_CLKSEL_CON(5), 4, 4, DFLAGS | CLK_DIVIDER_READ_ONLY, + RK3568_CLKGATE_CON(0), 15, GFLAGS), + COMPOSITE_NOMUX(0, "aclk_core", "sclk_core", CLK_IGNORE_UNUSED, + RK3568_CLKSEL_CON(5), 8, 5, DFLAGS | CLK_DIVIDER_READ_ONLY, + RK3568_CLKGATE_CON(1), 0, GFLAGS), + + COMPOSITE_NODIV(ACLK_CORE_NIU2BUS, "aclk_core_niu2bus", gpll150_gpll100_gpll75_xin24m_p, CLK_IGNORE_UNUSED, + RK3568_CLKSEL_CON(5), 14, 2, MFLAGS, + RK3568_CLKGATE_CON(1), 2, GFLAGS), + + GATE(CLK_CORE_PVTM, "clk_core_pvtm", "xin24m", 0, + RK3568_CLKGATE_CON(1), 10, GFLAGS), + GATE(CLK_CORE_PVTM_CORE, "clk_core_pvtm_core", "armclk", 0, + RK3568_CLKGATE_CON(1), 11, GFLAGS), + GATE(CLK_CORE_PVTPLL, "clk_core_pvtpll", "armclk", CLK_IGNORE_UNUSED, + RK3568_CLKGATE_CON(1), 12, GFLAGS), + GATE(PCLK_CORE_PVTM, "pclk_core_pvtm", "pclk_core_pre", 0, + RK3568_CLKGATE_CON(1), 9, GFLAGS), + + /* PD_GPU */ + COMPOSITE(CLK_GPU_SRC, "clk_gpu_src", mpll_gpll_cpll_npll_p, 0, + RK3568_CLKSEL_CON(6), 6, 2, MFLAGS | CLK_MUX_READ_ONLY, 0, 4, DFLAGS | CLK_DIVIDER_READ_ONLY, + RK3568_CLKGATE_CON(2), 0, GFLAGS), + MUX(CLK_GPU_PRE_MUX, "clk_gpu_pre_mux", clk_gpu_pre_mux_p, CLK_SET_RATE_PARENT, + RK3568_CLKSEL_CON(6), 11, 1, MFLAGS | CLK_MUX_READ_ONLY), + DIV(ACLK_GPU_PRE, "aclk_gpu_pre", "clk_gpu_pre_mux", 0, + RK3568_CLKSEL_CON(6), 8, 2, DFLAGS), + DIV(PCLK_GPU_PRE, "pclk_gpu_pre", "clk_gpu_pre_mux", 0, + RK3568_CLKSEL_CON(6), 12, 4, DFLAGS), + GATE(CLK_GPU, "clk_gpu", "clk_gpu_pre_mux", 0, + RK3568_CLKGATE_CON(2), 3, GFLAGS), + + GATE(PCLK_GPU_PVTM, "pclk_gpu_pvtm", "pclk_gpu_pre", 0, + RK3568_CLKGATE_CON(2), 6, GFLAGS), + GATE(CLK_GPU_PVTM, "clk_gpu_pvtm", "xin24m", 0, + RK3568_CLKGATE_CON(2), 7, GFLAGS), + GATE(CLK_GPU_PVTM_CORE, "clk_gpu_pvtm_core", "clk_gpu_src", 0, + RK3568_CLKGATE_CON(2), 8, GFLAGS), + GATE(CLK_GPU_PVTPLL, "clk_gpu_pvtpll", "clk_gpu_src", CLK_IGNORE_UNUSED, + RK3568_CLKGATE_CON(2), 9, GFLAGS), + + /* PD_NPU */ + COMPOSITE(CLK_NPU_SRC, "clk_npu_src", npll_gpll_p, 0, + RK3568_CLKSEL_CON(7), 6, 1, MFLAGS, 0, 4, DFLAGS, + RK3568_CLKGATE_CON(3), 0, GFLAGS), + MUX(CLK_NPU_PRE_NDFT, "clk_npu_pre_ndft", clk_npu_pre_ndft_p, CLK_SET_RATE_PARENT | CLK_OPS_PARENT_ENABLE, + RK3568_CLKSEL_CON(7), 8, 1, MFLAGS), + MUX(CLK_NPU, "clk_npu", clk_npu_p, CLK_SET_RATE_PARENT, + RK3568_CLKSEL_CON(7), 15, 1, MFLAGS), + COMPOSITE_NOMUX(HCLK_NPU_PRE, "hclk_npu_pre", "clk_npu", 0, + RK3568_CLKSEL_CON(8), 0, 4, DFLAGS, + RK3568_CLKGATE_CON(3), 2, GFLAGS), + COMPOSITE_NOMUX(PCLK_NPU_PRE, "pclk_npu_pre", "clk_npu", 0, + RK3568_CLKSEL_CON(8), 4, 4, DFLAGS, + RK3568_CLKGATE_CON(3), 3, GFLAGS), + GATE(ACLK_NPU_PRE, "aclk_npu_pre", "clk_npu", 0, + RK3568_CLKGATE_CON(3), 4, GFLAGS), + GATE(ACLK_NPU, "aclk_npu", "aclk_npu_pre", 0, + RK3568_CLKGATE_CON(3), 7, GFLAGS), + GATE(HCLK_NPU, "hclk_npu", "hclk_npu_pre", 0, + RK3568_CLKGATE_CON(3), 8, GFLAGS), + + GATE(PCLK_NPU_PVTM, "pclk_npu_pvtm", "pclk_npu_pre", 0, + RK3568_CLKGATE_CON(3), 9, GFLAGS), + GATE(CLK_NPU_PVTM, "clk_npu_pvtm", "xin24m", 0, + RK3568_CLKGATE_CON(3), 10, GFLAGS), + GATE(CLK_NPU_PVTM_CORE, "clk_npu_pvtm_core", "clk_npu_pre_ndft", 0, + RK3568_CLKGATE_CON(3), 11, GFLAGS), + GATE(CLK_NPU_PVTPLL, "clk_npu_pvtpll", "clk_npu_pre_ndft", CLK_IGNORE_UNUSED, + RK3568_CLKGATE_CON(3), 12, GFLAGS), + + /* PD_DDR */ + COMPOSITE(CLK_DDRPHY1X_SRC, "clk_ddrphy1x_src", dpll_gpll_cpll_p, CLK_IGNORE_UNUSED, + RK3568_CLKSEL_CON(9), 6, 2, MFLAGS, 0, 5, DFLAGS, + RK3568_CLKGATE_CON(4), 0, GFLAGS), + MUXGRF(CLK_DDR1X, "clk_ddr1x", clk_ddr1x_p, CLK_SET_RATE_PARENT, + RK3568_CLKSEL_CON(9), 15, 1, MFLAGS), + + COMPOSITE_NOMUX(CLK_MSCH, "clk_msch", "clk_ddr1x", CLK_IGNORE_UNUSED, + RK3568_CLKSEL_CON(10), 0, 2, DFLAGS, + RK3568_CLKGATE_CON(4), 2, GFLAGS), + GATE(CLK24_DDRMON, "clk24_ddrmon", "xin24m", CLK_IGNORE_UNUSED, + RK3568_CLKGATE_CON(4), 15, GFLAGS), + + /* PD_GIC_AUDIO */ + COMPOSITE_NODIV(ACLK_GIC_AUDIO, "aclk_gic_audio", gpll200_gpll150_gpll100_xin24m_p, CLK_IGNORE_UNUSED, + RK3568_CLKSEL_CON(10), 8, 2, MFLAGS, + RK3568_CLKGATE_CON(5), 0, GFLAGS), + COMPOSITE_NODIV(HCLK_GIC_AUDIO, "hclk_gic_audio", gpll150_gpll100_gpll75_xin24m_p, CLK_IGNORE_UNUSED, + RK3568_CLKSEL_CON(10), 10, 2, MFLAGS, + RK3568_CLKGATE_CON(5), 1, GFLAGS), + GATE(HCLK_SDMMC_BUFFER, "hclk_sdmmc_buffer", "hclk_gic_audio", 0, + RK3568_CLKGATE_CON(5), 8, GFLAGS), + COMPOSITE_NODIV(DCLK_SDMMC_BUFFER, "dclk_sdmmc_buffer", gpll100_gpll75_gpll50_p, 0, + RK3568_CLKSEL_CON(10), 12, 2, MFLAGS, + RK3568_CLKGATE_CON(5), 9, GFLAGS), + GATE(ACLK_GIC600, "aclk_gic600", "aclk_gic_audio", CLK_IGNORE_UNUSED, + RK3568_CLKGATE_CON(5), 4, GFLAGS), + GATE(ACLK_SPINLOCK, "aclk_spinlock", "aclk_gic_audio", CLK_IGNORE_UNUSED, + RK3568_CLKGATE_CON(5), 7, GFLAGS), + GATE(HCLK_I2S0_8CH, "hclk_i2s0_8ch", "hclk_gic_audio", 0, + RK3568_CLKGATE_CON(5), 10, GFLAGS), + GATE(HCLK_I2S1_8CH, "hclk_i2s1_8ch", "hclk_gic_audio", 0, + RK3568_CLKGATE_CON(5), 11, GFLAGS), + GATE(HCLK_I2S2_2CH, "hclk_i2s2_2ch", "hclk_gic_audio", 0, + RK3568_CLKGATE_CON(5), 12, GFLAGS), + GATE(HCLK_I2S3_2CH, "hclk_i2s3_2ch", "hclk_gic_audio", 0, + RK3568_CLKGATE_CON(5), 13, GFLAGS), + + COMPOSITE(CLK_I2S0_8CH_TX_SRC, "clk_i2s0_8ch_tx_src", gpll_cpll_npll_p, 0, + RK3568_CLKSEL_CON(11), 8, 2, MFLAGS, 0, 7, DFLAGS, + RK3568_CLKGATE_CON(6), 0, GFLAGS), + COMPOSITE_FRACMUX(CLK_I2S0_8CH_TX_FRAC, "clk_i2s0_8ch_tx_frac", "clk_i2s0_8ch_tx_src", CLK_SET_RATE_PARENT, + RK3568_CLKSEL_CON(12), 0, + RK3568_CLKGATE_CON(6), 1, GFLAGS, + &rk3568_i2s0_8ch_tx_fracmux), + GATE(MCLK_I2S0_8CH_TX, "mclk_i2s0_8ch_tx", "clk_i2s0_8ch_tx", 0, + RK3568_CLKGATE_CON(6), 2, GFLAGS), + COMPOSITE_NODIV(I2S0_MCLKOUT_TX, "i2s0_mclkout_tx", i2s0_mclkout_tx_p, CLK_SET_RATE_PARENT, + RK3568_CLKSEL_CON(11), 15, 1, MFLAGS, + RK3568_CLKGATE_CON(6), 3, GFLAGS), + + COMPOSITE(CLK_I2S0_8CH_RX_SRC, "clk_i2s0_8ch_rx_src", gpll_cpll_npll_p, 0, + RK3568_CLKSEL_CON(13), 8, 2, MFLAGS, 0, 7, DFLAGS, + RK3568_CLKGATE_CON(6), 4, GFLAGS), + COMPOSITE_FRACMUX(CLK_I2S0_8CH_RX_FRAC, "clk_i2s0_8ch_rx_frac", "clk_i2s0_8ch_rx_src", CLK_SET_RATE_PARENT, + RK3568_CLKSEL_CON(14), 0, + RK3568_CLKGATE_CON(6), 5, GFLAGS, + &rk3568_i2s0_8ch_rx_fracmux), + GATE(MCLK_I2S0_8CH_RX, "mclk_i2s0_8ch_rx", "clk_i2s0_8ch_rx", 0, + RK3568_CLKGATE_CON(6), 6, GFLAGS), + COMPOSITE_NODIV(I2S0_MCLKOUT_RX, "i2s0_mclkout_rx", i2s0_mclkout_rx_p, CLK_SET_RATE_PARENT, + RK3568_CLKSEL_CON(13), 15, 1, MFLAGS, + RK3568_CLKGATE_CON(6), 7, GFLAGS), + + COMPOSITE(CLK_I2S1_8CH_TX_SRC, "clk_i2s1_8ch_tx_src", gpll_cpll_npll_p, 0, + RK3568_CLKSEL_CON(15), 8, 2, MFLAGS, 0, 7, DFLAGS, + RK3568_CLKGATE_CON(6), 8, GFLAGS), + COMPOSITE_FRACMUX(CLK_I2S1_8CH_TX_FRAC, "clk_i2s1_8ch_tx_frac", "clk_i2s1_8ch_tx_src", CLK_SET_RATE_PARENT, + RK3568_CLKSEL_CON(16), 0, + RK3568_CLKGATE_CON(6), 9, GFLAGS, + &rk3568_i2s1_8ch_tx_fracmux), + GATE(MCLK_I2S1_8CH_TX, "mclk_i2s1_8ch_tx", "clk_i2s1_8ch_tx", 0, + RK3568_CLKGATE_CON(6), 10, GFLAGS), + COMPOSITE_NODIV(I2S1_MCLKOUT_TX, "i2s1_mclkout_tx", i2s1_mclkout_tx_p, CLK_SET_RATE_PARENT, + RK3568_CLKSEL_CON(15), 15, 1, MFLAGS, + RK3568_CLKGATE_CON(6), 11, GFLAGS), + + COMPOSITE(CLK_I2S1_8CH_RX_SRC, "clk_i2s1_8ch_rx_src", gpll_cpll_npll_p, 0, + RK3568_CLKSEL_CON(17), 8, 2, MFLAGS, 0, 7, DFLAGS, + RK3568_CLKGATE_CON(6), 12, GFLAGS), + COMPOSITE_FRACMUX(CLK_I2S1_8CH_RX_FRAC, "clk_i2s1_8ch_rx_frac", "clk_i2s1_8ch_rx_src", CLK_SET_RATE_PARENT, + RK3568_CLKSEL_CON(18), 0, + RK3568_CLKGATE_CON(6), 13, GFLAGS, + &rk3568_i2s1_8ch_rx_fracmux), + GATE(MCLK_I2S1_8CH_RX, "mclk_i2s1_8ch_rx", "clk_i2s1_8ch_rx", 0, + RK3568_CLKGATE_CON(6), 14, GFLAGS), + COMPOSITE_NODIV(I2S1_MCLKOUT_RX, "i2s1_mclkout_rx", i2s1_mclkout_rx_p, CLK_SET_RATE_PARENT, + RK3568_CLKSEL_CON(17), 15, 1, MFLAGS, + RK3568_CLKGATE_CON(6), 15, GFLAGS), + + COMPOSITE(CLK_I2S2_2CH_SRC, "clk_i2s2_2ch_src", gpll_cpll_npll_p, 0, + RK3568_CLKSEL_CON(19), 8, 2, MFLAGS, 0, 7, DFLAGS, + RK3568_CLKGATE_CON(7), 0, GFLAGS), + COMPOSITE_FRACMUX(CLK_I2S2_2CH_FRAC, "clk_i2s2_2ch_frac", "clk_i2s2_2ch_src", CLK_SET_RATE_PARENT, + RK3568_CLKSEL_CON(20), 0, + RK3568_CLKGATE_CON(7), 1, GFLAGS, + &rk3568_i2s2_2ch_fracmux), + GATE(MCLK_I2S2_2CH, "mclk_i2s2_2ch", "clk_i2s2_2ch", 0, + RK3568_CLKGATE_CON(7), 2, GFLAGS), + COMPOSITE_NODIV(I2S2_MCLKOUT, "i2s2_mclkout", i2s2_mclkout_p, CLK_SET_RATE_PARENT, + RK3568_CLKSEL_CON(19), 15, 1, MFLAGS, + RK3568_CLKGATE_CON(7), 3, GFLAGS), + + COMPOSITE(CLK_I2S3_2CH_TX_SRC, "clk_i2s3_2ch_tx_src", gpll_cpll_npll_p, 0, + RK3568_CLKSEL_CON(21), 8, 2, MFLAGS, 0, 7, DFLAGS, + RK3568_CLKGATE_CON(7), 4, GFLAGS), + COMPOSITE_FRACMUX(CLK_I2S3_2CH_TX_FRAC, "clk_i2s3_2ch_tx_frac", "clk_i2s3_2ch_tx_src", CLK_SET_RATE_PARENT, + RK3568_CLKSEL_CON(22), 0, + RK3568_CLKGATE_CON(7), 5, GFLAGS, + &rk3568_i2s3_2ch_tx_fracmux), + GATE(MCLK_I2S3_2CH_TX, "mclk_i2s3_2ch_tx", "clk_i2s3_2ch_tx", 0, + RK3568_CLKGATE_CON(7), 6, GFLAGS), + COMPOSITE_NODIV(I2S3_MCLKOUT_TX, "i2s3_mclkout_tx", i2s3_mclkout_tx_p, CLK_SET_RATE_PARENT, + RK3568_CLKSEL_CON(21), 15, 1, MFLAGS, + RK3568_CLKGATE_CON(7), 7, GFLAGS), + + COMPOSITE(CLK_I2S3_2CH_RX_SRC, "clk_i2s3_2ch_rx_src", gpll_cpll_npll_p, 0, + RK3568_CLKSEL_CON(83), 8, 2, MFLAGS, 0, 7, DFLAGS, + RK3568_CLKGATE_CON(7), 8, GFLAGS), + COMPOSITE_FRACMUX(CLK_I2S3_2CH_RX_FRAC, "clk_i2s3_2ch_rx_frac", "clk_i2s3_2ch_rx_src", CLK_SET_RATE_PARENT, + RK3568_CLKSEL_CON(84), 0, + RK3568_CLKGATE_CON(7), 9, GFLAGS, + &rk3568_i2s3_2ch_rx_fracmux), + GATE(MCLK_I2S3_2CH_RX, "mclk_i2s3_2ch_rx", "clk_i2s3_2ch_rx", 0, + RK3568_CLKGATE_CON(7), 10, GFLAGS), + COMPOSITE_NODIV(I2S3_MCLKOUT_RX, "i2s3_mclkout_rx", i2s3_mclkout_rx_p, CLK_SET_RATE_PARENT, + RK3568_CLKSEL_CON(83), 15, 1, MFLAGS, + RK3568_CLKGATE_CON(7), 11, GFLAGS), + + GATE(HCLK_PDM, "hclk_pdm", "hclk_gic_audio", 0, + RK3568_CLKGATE_CON(5), 14, GFLAGS), + COMPOSITE_NODIV(MCLK_PDM, "mclk_pdm", mclk_pdm_p, 0, + RK3568_CLKSEL_CON(23), 8, 2, MFLAGS, + RK3568_CLKGATE_CON(5), 15, GFLAGS), + GATE(HCLK_VAD, "hclk_vad", "hclk_gic_audio", 0, + RK3568_CLKGATE_CON(7), 12, GFLAGS), + GATE(HCLK_SPDIF_8CH, "hclk_spdif_8ch", "hclk_gic_audio", 0, + RK3568_CLKGATE_CON(7), 13, GFLAGS), + + COMPOSITE(MCLK_SPDIF_8CH_SRC, "mclk_spdif_8ch_src", cpll_gpll_p, 0, + RK3568_CLKSEL_CON(23), 14, 1, MFLAGS, 0, 7, DFLAGS, + RK3568_CLKGATE_CON(7), 14, GFLAGS), + COMPOSITE_FRACMUX(MCLK_SPDIF_8CH_FRAC, "mclk_spdif_8ch_frac", "mclk_spdif_8ch_src", CLK_SET_RATE_PARENT, + RK3568_CLKSEL_CON(24), 0, + RK3568_CLKGATE_CON(7), 15, GFLAGS, + &rk3568_spdif_8ch_fracmux), + + GATE(HCLK_AUDPWM, "hclk_audpwm", "hclk_gic_audio", 0, + RK3568_CLKGATE_CON(8), 0, GFLAGS), + COMPOSITE(SCLK_AUDPWM_SRC, "sclk_audpwm_src", gpll_cpll_p, 0, + RK3568_CLKSEL_CON(25), 14, 1, MFLAGS, 0, 6, DFLAGS, + RK3568_CLKGATE_CON(8), 1, GFLAGS), + COMPOSITE_FRACMUX(SCLK_AUDPWM_FRAC, "sclk_audpwm_frac", "sclk_audpwm_src", CLK_SET_RATE_PARENT, + RK3568_CLKSEL_CON(26), 0, + RK3568_CLKGATE_CON(8), 2, GFLAGS, + &rk3568_audpwm_fracmux), + + GATE(HCLK_ACDCDIG, "hclk_acdcdig", "hclk_gic_audio", 0, + RK3568_CLKGATE_CON(8), 3, GFLAGS), + COMPOSITE_NODIV(CLK_ACDCDIG_I2C, "clk_acdcdig_i2c", clk_i2c_p, 0, + RK3568_CLKSEL_CON(23), 10, 2, MFLAGS, + RK3568_CLKGATE_CON(8), 4, GFLAGS), + GATE(CLK_ACDCDIG_DAC, "clk_acdcdig_dac", "mclk_i2s3_2ch_tx", 0, + RK3568_CLKGATE_CON(8), 5, GFLAGS), + GATE(CLK_ACDCDIG_ADC, "clk_acdcdig_adc", "mclk_i2s3_2ch_rx", 0, + RK3568_CLKGATE_CON(8), 6, GFLAGS), + + /* PD_SECURE_FLASH */ + COMPOSITE_NODIV(ACLK_SECURE_FLASH, "aclk_secure_flash", gpll200_gpll150_gpll100_xin24m_p, 0, + RK3568_CLKSEL_CON(27), 0, 2, MFLAGS, + RK3568_CLKGATE_CON(8), 7, GFLAGS), + COMPOSITE_NODIV(HCLK_SECURE_FLASH, "hclk_secure_flash", gpll150_gpll100_gpll75_xin24m_p, 0, + RK3568_CLKSEL_CON(27), 2, 2, MFLAGS, + RK3568_CLKGATE_CON(8), 8, GFLAGS), + GATE(ACLK_CRYPTO_NS, "aclk_crypto_ns", "aclk_secure_flash", 0, + RK3568_CLKGATE_CON(8), 11, GFLAGS), + GATE(HCLK_CRYPTO_NS, "hclk_crypto_ns", "hclk_secure_flash", 0, + RK3568_CLKGATE_CON(8), 12, GFLAGS), + COMPOSITE_NODIV(CLK_CRYPTO_NS_CORE, "clk_crypto_ns_core", gpll200_gpll150_gpll100_p, 0, + RK3568_CLKSEL_CON(27), 4, 2, MFLAGS, + RK3568_CLKGATE_CON(8), 13, GFLAGS), + COMPOSITE_NODIV(CLK_CRYPTO_NS_PKA, "clk_crypto_ns_pka", gpll300_gpll200_gpll100_p, 0, + RK3568_CLKSEL_CON(27), 6, 2, MFLAGS, + RK3568_CLKGATE_CON(8), 14, GFLAGS), + GATE(CLK_CRYPTO_NS_RNG, "clk_crypto_ns_rng", "hclk_secure_flash", 0, + RK3568_CLKGATE_CON(8), 15, GFLAGS), + GATE(HCLK_TRNG_NS, "hclk_trng_ns", "hclk_secure_flash", CLK_IGNORE_UNUSED, + RK3568_CLKGATE_CON(9), 10, GFLAGS), + GATE(CLK_TRNG_NS, "clk_trng_ns", "hclk_secure_flash", CLK_IGNORE_UNUSED, + RK3568_CLKGATE_CON(9), 11, GFLAGS), + GATE(PCLK_OTPC_NS, "pclk_otpc_ns", "hclk_secure_flash", 0, + RK3568_CLKGATE_CON(26), 9, GFLAGS), + GATE(CLK_OTPC_NS_SBPI, "clk_otpc_ns_sbpi", "xin24m", 0, + RK3568_CLKGATE_CON(26), 10, GFLAGS), + GATE(CLK_OTPC_NS_USR, "clk_otpc_ns_usr", "xin_osc0_half", 0, + RK3568_CLKGATE_CON(26), 11, GFLAGS), + GATE(HCLK_NANDC, "hclk_nandc", "hclk_secure_flash", 0, + RK3568_CLKGATE_CON(9), 0, GFLAGS), + COMPOSITE_NODIV(NCLK_NANDC, "nclk_nandc", clk_nandc_p, 0, + RK3568_CLKSEL_CON(28), 0, 2, MFLAGS, + RK3568_CLKGATE_CON(9), 1, GFLAGS), + GATE(HCLK_SFC, "hclk_sfc", "hclk_secure_flash", 0, + RK3568_CLKGATE_CON(9), 2, GFLAGS), + GATE(HCLK_SFC_XIP, "hclk_sfc_xip", "hclk_secure_flash", 0, + RK3568_CLKGATE_CON(9), 3, GFLAGS), + COMPOSITE_NODIV(SCLK_SFC, "sclk_sfc", sclk_sfc_p, 0, + RK3568_CLKSEL_CON(28), 4, 3, MFLAGS, + RK3568_CLKGATE_CON(9), 4, GFLAGS), + GATE(ACLK_EMMC, "aclk_emmc", "aclk_secure_flash", 0, + RK3568_CLKGATE_CON(9), 5, GFLAGS), + GATE(HCLK_EMMC, "hclk_emmc", "hclk_secure_flash", 0, + RK3568_CLKGATE_CON(9), 6, GFLAGS), + COMPOSITE_NODIV(BCLK_EMMC, "bclk_emmc", gpll200_gpll150_cpll125_p, 0, + RK3568_CLKSEL_CON(28), 8, 2, MFLAGS, + RK3568_CLKGATE_CON(9), 7, GFLAGS), + COMPOSITE_NODIV(CCLK_EMMC, "cclk_emmc", cclk_emmc_p, 0, + RK3568_CLKSEL_CON(28), 12, 3, MFLAGS, + RK3568_CLKGATE_CON(9), 8, GFLAGS), + GATE(TCLK_EMMC, "tclk_emmc", "xin24m", 0, + RK3568_CLKGATE_CON(9), 9, GFLAGS), + MMC(SCLK_EMMC_DRV, "emmc_drv", "cclk_emmc", RK3568_EMMC_CON0, 1), + MMC(SCLK_EMMC_SAMPLE, "emmc_sample", "cclk_emmc", RK3568_EMMC_CON1, 1), + + /* PD_PIPE */ + COMPOSITE_NODIV(ACLK_PIPE, "aclk_pipe", aclk_pipe_p, 0, + RK3568_CLKSEL_CON(29), 0, 2, MFLAGS, + RK3568_CLKGATE_CON(10), 0, GFLAGS), + COMPOSITE_NOMUX(PCLK_PIPE, "pclk_pipe", "aclk_pipe", 0, + RK3568_CLKSEL_CON(29), 4, 4, DFLAGS, + RK3568_CLKGATE_CON(10), 1, GFLAGS), + GATE(ACLK_PCIE20_MST, "aclk_pcie20_mst", "aclk_pipe", 0, + RK3568_CLKGATE_CON(12), 0, GFLAGS), + GATE(ACLK_PCIE20_SLV, "aclk_pcie20_slv", "aclk_pipe", 0, + RK3568_CLKGATE_CON(12), 1, GFLAGS), + GATE(ACLK_PCIE20_DBI, "aclk_pcie20_dbi", "aclk_pipe", 0, + RK3568_CLKGATE_CON(12), 2, GFLAGS), + GATE(PCLK_PCIE20, "pclk_pcie20", "pclk_pipe", 0, + RK3568_CLKGATE_CON(12), 3, GFLAGS), + GATE(CLK_PCIE20_AUX_NDFT, "clk_pcie20_aux_ndft", "xin24m", 0, + RK3568_CLKGATE_CON(12), 4, GFLAGS), + GATE(ACLK_PCIE30X1_MST, "aclk_pcie30x1_mst", "aclk_pipe", 0, + RK3568_CLKGATE_CON(12), 8, GFLAGS), + GATE(ACLK_PCIE30X1_SLV, "aclk_pcie30x1_slv", "aclk_pipe", 0, + RK3568_CLKGATE_CON(12), 9, GFLAGS), + GATE(ACLK_PCIE30X1_DBI, "aclk_pcie30x1_dbi", "aclk_pipe", 0, + RK3568_CLKGATE_CON(12), 10, GFLAGS), + GATE(PCLK_PCIE30X1, "pclk_pcie30x1", "pclk_pipe", 0, + RK3568_CLKGATE_CON(12), 11, GFLAGS), + GATE(CLK_PCIE30X1_AUX_NDFT, "clk_pcie30x1_aux_ndft", "xin24m", 0, + RK3568_CLKGATE_CON(12), 12, GFLAGS), + GATE(ACLK_PCIE30X2_MST, "aclk_pcie30x2_mst", "aclk_pipe", 0, + RK3568_CLKGATE_CON(13), 0, GFLAGS), + GATE(ACLK_PCIE30X2_SLV, "aclk_pcie30x2_slv", "aclk_pipe", 0, + RK3568_CLKGATE_CON(13), 1, GFLAGS), + GATE(ACLK_PCIE30X2_DBI, "aclk_pcie30x2_dbi", "aclk_pipe", 0, + RK3568_CLKGATE_CON(13), 2, GFLAGS), + GATE(PCLK_PCIE30X2, "pclk_pcie30x2", "pclk_pipe", 0, + RK3568_CLKGATE_CON(13), 3, GFLAGS), + GATE(CLK_PCIE30X2_AUX_NDFT, "clk_pcie30x2_aux_ndft", "xin24m", 0, + RK3568_CLKGATE_CON(13), 4, GFLAGS), + GATE(ACLK_SATA0, "aclk_sata0", "aclk_pipe", 0, + RK3568_CLKGATE_CON(11), 0, GFLAGS), + GATE(CLK_SATA0_PMALIVE, "clk_sata0_pmalive", "gpll_20m", 0, + RK3568_CLKGATE_CON(11), 1, GFLAGS), + GATE(CLK_SATA0_RXOOB, "clk_sata0_rxoob", "cpll_50m", 0, + RK3568_CLKGATE_CON(11), 2, GFLAGS), + GATE(ACLK_SATA1, "aclk_sata1", "aclk_pipe", 0, + RK3568_CLKGATE_CON(11), 4, GFLAGS), + GATE(CLK_SATA1_PMALIVE, "clk_sata1_pmalive", "gpll_20m", 0, + RK3568_CLKGATE_CON(11), 5, GFLAGS), + GATE(CLK_SATA1_RXOOB, "clk_sata1_rxoob", "cpll_50m", 0, + RK3568_CLKGATE_CON(11), 6, GFLAGS), + GATE(ACLK_SATA2, "aclk_sata2", "aclk_pipe", 0, + RK3568_CLKGATE_CON(11), 8, GFLAGS), + GATE(CLK_SATA2_PMALIVE, "clk_sata2_pmalive", "gpll_20m", 0, + RK3568_CLKGATE_CON(11), 9, GFLAGS), + GATE(CLK_SATA2_RXOOB, "clk_sata2_rxoob", "cpll_50m", 0, + RK3568_CLKGATE_CON(11), 10, GFLAGS), + GATE(ACLK_USB3OTG0, "aclk_usb3otg0", "aclk_pipe", 0, + RK3568_CLKGATE_CON(10), 8, GFLAGS), + GATE(CLK_USB3OTG0_REF, "clk_usb3otg0_ref", "xin24m", 0, + RK3568_CLKGATE_CON(10), 9, GFLAGS), + COMPOSITE_NODIV(CLK_USB3OTG0_SUSPEND, "clk_usb3otg0_suspend", xin24m_32k_p, 0, + RK3568_CLKSEL_CON(29), 8, 1, MFLAGS, + RK3568_CLKGATE_CON(10), 10, GFLAGS), + GATE(ACLK_USB3OTG1, "aclk_usb3otg1", "aclk_pipe", 0, + RK3568_CLKGATE_CON(10), 12, GFLAGS), + GATE(CLK_USB3OTG1_REF, "clk_usb3otg1_ref", "xin24m", 0, + RK3568_CLKGATE_CON(10), 13, GFLAGS), + COMPOSITE_NODIV(CLK_USB3OTG1_SUSPEND, "clk_usb3otg1_suspend", xin24m_32k_p, 0, + RK3568_CLKSEL_CON(29), 9, 1, MFLAGS, + RK3568_CLKGATE_CON(10), 14, GFLAGS), + COMPOSITE_NODIV(CLK_XPCS_EEE, "clk_xpcs_eee", gpll200_cpll125_p, 0, + RK3568_CLKSEL_CON(29), 13, 1, MFLAGS, + RK3568_CLKGATE_CON(10), 4, GFLAGS), + GATE(PCLK_XPCS, "pclk_xpcs", "pclk_pipe", 0, + RK3568_CLKGATE_CON(13), 6, GFLAGS), + + /* PD_PHP */ + COMPOSITE_NODIV(ACLK_PHP, "aclk_php", gpll300_gpll200_gpll100_xin24m_p, 0, + RK3568_CLKSEL_CON(30), 0, 2, MFLAGS, + RK3568_CLKGATE_CON(14), 8, GFLAGS), + COMPOSITE_NODIV(HCLK_PHP, "hclk_php", gpll150_gpll100_gpll75_xin24m_p, 0, + RK3568_CLKSEL_CON(30), 2, 2, MFLAGS, + RK3568_CLKGATE_CON(14), 9, GFLAGS), + COMPOSITE_NOMUX(PCLK_PHP, "pclk_php", "aclk_php", 0, + RK3568_CLKSEL_CON(30), 4, 4, DFLAGS, + RK3568_CLKGATE_CON(14), 10, GFLAGS), + GATE(HCLK_SDMMC0, "hclk_sdmmc0", "hclk_php", 0, + RK3568_CLKGATE_CON(15), 0, GFLAGS), + COMPOSITE_NODIV(CLK_SDMMC0, "clk_sdmmc0", clk_sdmmc_p, 0, + RK3568_CLKSEL_CON(30), 8, 3, MFLAGS, + RK3568_CLKGATE_CON(15), 1, GFLAGS), + MMC(SCLK_SDMMC0_DRV, "sdmmc0_drv", "clk_sdmmc0", RK3568_SDMMC0_CON0, 1), + MMC(SCLK_SDMMC0_SAMPLE, "sdmmc0_sample", "clk_sdmmc0", RK3568_SDMMC0_CON1, 1), + + GATE(HCLK_SDMMC1, "hclk_sdmmc1", "hclk_php", 0, + RK3568_CLKGATE_CON(15), 2, GFLAGS), + COMPOSITE_NODIV(CLK_SDMMC1, "clk_sdmmc1", clk_sdmmc_p, 0, + RK3568_CLKSEL_CON(30), 12, 3, MFLAGS, + RK3568_CLKGATE_CON(15), 3, GFLAGS), + MMC(SCLK_SDMMC1_DRV, "sdmmc1_drv", "clk_sdmmc1", RK3568_SDMMC1_CON0, 1), + MMC(SCLK_SDMMC1_SAMPLE, "sdmmc1_sample", "clk_sdmmc1", RK3568_SDMMC1_CON1, 1), + + GATE(ACLK_GMAC0, "aclk_gmac0", "aclk_php", 0, + RK3568_CLKGATE_CON(15), 5, GFLAGS), + GATE(PCLK_GMAC0, "pclk_gmac0", "pclk_php", 0, + RK3568_CLKGATE_CON(15), 6, GFLAGS), + COMPOSITE_NODIV(CLK_MAC0_2TOP, "clk_mac0_2top", clk_mac_2top_p, 0, + RK3568_CLKSEL_CON(31), 8, 2, MFLAGS, + RK3568_CLKGATE_CON(15), 7, GFLAGS), + COMPOSITE_NODIV(CLK_MAC0_OUT, "clk_mac0_out", cpll125_cpll50_cpll25_xin24m_p, 0, + RK3568_CLKSEL_CON(31), 14, 2, MFLAGS, + RK3568_CLKGATE_CON(15), 8, GFLAGS), + GATE(CLK_MAC0_REFOUT, "clk_mac0_refout", "clk_mac0_2top", 0, + RK3568_CLKGATE_CON(15), 12, GFLAGS), + COMPOSITE_NODIV(CLK_GMAC0_PTP_REF, "clk_gmac0_ptp_ref", clk_gmac_ptp_p, 0, + RK3568_CLKSEL_CON(31), 12, 2, MFLAGS, + RK3568_CLKGATE_CON(15), 4, GFLAGS), + MUX(SCLK_GMAC0, "clk_gmac0", mux_gmac0_p, CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT, + RK3568_CLKSEL_CON(31), 2, 1, MFLAGS), + FACTOR(0, "clk_gmac0_tx_div5", "clk_gmac0", 0, 1, 5), + FACTOR(0, "clk_gmac0_tx_div50", "clk_gmac0", 0, 1, 50), + FACTOR(0, "clk_gmac0_rx_div2", "clk_gmac0", 0, 1, 2), + FACTOR(0, "clk_gmac0_rx_div20", "clk_gmac0", 0, 1, 20), + MUX(SCLK_GMAC0_RGMII_SPEED, "clk_gmac0_rgmii_speed", mux_gmac0_rgmii_speed_p, 0, + RK3568_CLKSEL_CON(31), 4, 2, MFLAGS), + MUX(SCLK_GMAC0_RMII_SPEED, "clk_gmac0_rmii_speed", mux_gmac0_rmii_speed_p, 0, + RK3568_CLKSEL_CON(31), 3, 1, MFLAGS), + MUX(SCLK_GMAC0_RX_TX, "clk_gmac0_rx_tx", mux_gmac0_rx_tx_p, CLK_SET_RATE_PARENT, + RK3568_CLKSEL_CON(31), 0, 2, MFLAGS), + + /* PD_USB */ + COMPOSITE_NODIV(ACLK_USB, "aclk_usb", gpll300_gpll200_gpll100_xin24m_p, 0, + RK3568_CLKSEL_CON(32), 0, 2, MFLAGS, + RK3568_CLKGATE_CON(16), 0, GFLAGS), + COMPOSITE_NODIV(HCLK_USB, "hclk_usb", gpll150_gpll100_gpll75_xin24m_p, 0, + RK3568_CLKSEL_CON(32), 2, 2, MFLAGS, + RK3568_CLKGATE_CON(16), 1, GFLAGS), + COMPOSITE_NOMUX(PCLK_USB, "pclk_usb", "aclk_usb", 0, + RK3568_CLKSEL_CON(32), 4, 4, DFLAGS, + RK3568_CLKGATE_CON(16), 2, GFLAGS), + GATE(HCLK_USB2HOST0, "hclk_usb2host0", "hclk_usb", 0, + RK3568_CLKGATE_CON(16), 12, GFLAGS), + GATE(HCLK_USB2HOST0_ARB, "hclk_usb2host0_arb", "hclk_usb", 0, + RK3568_CLKGATE_CON(16), 13, GFLAGS), + GATE(HCLK_USB2HOST1, "hclk_usb2host1", "hclk_usb", 0, + RK3568_CLKGATE_CON(16), 14, GFLAGS), + GATE(HCLK_USB2HOST1_ARB, "hclk_usb2host1_arb", "hclk_usb", 0, + RK3568_CLKGATE_CON(16), 15, GFLAGS), + GATE(HCLK_SDMMC2, "hclk_sdmmc2", "hclk_usb", 0, + RK3568_CLKGATE_CON(17), 0, GFLAGS), + COMPOSITE_NODIV(CLK_SDMMC2, "clk_sdmmc2", clk_sdmmc_p, 0, + RK3568_CLKSEL_CON(32), 8, 3, MFLAGS, + RK3568_CLKGATE_CON(17), 1, GFLAGS), + MMC(SCLK_SDMMC2_DRV, "sdmmc2_drv", "clk_sdmmc2", RK3568_SDMMC2_CON0, 1), + MMC(SCLK_SDMMC2_SAMPLE, "sdmmc2_sample", "clk_sdmmc2", RK3568_SDMMC2_CON1, 1), + + GATE(ACLK_GMAC1, "aclk_gmac1", "aclk_usb", 0, + RK3568_CLKGATE_CON(17), 3, GFLAGS), + GATE(PCLK_GMAC1, "pclk_gmac1", "pclk_usb", 0, + RK3568_CLKGATE_CON(17), 4, GFLAGS), + COMPOSITE_NODIV(CLK_MAC1_2TOP, "clk_mac1_2top", clk_mac_2top_p, 0, + RK3568_CLKSEL_CON(33), 8, 2, MFLAGS, + RK3568_CLKGATE_CON(17), 5, GFLAGS), + COMPOSITE_NODIV(CLK_MAC1_OUT, "clk_mac1_out", cpll125_cpll50_cpll25_xin24m_p, 0, + RK3568_CLKSEL_CON(33), 14, 2, MFLAGS, + RK3568_CLKGATE_CON(17), 6, GFLAGS), + GATE(CLK_MAC1_REFOUT, "clk_mac1_refout", "clk_mac1_2top", 0, + RK3568_CLKGATE_CON(17), 10, GFLAGS), + COMPOSITE_NODIV(CLK_GMAC1_PTP_REF, "clk_gmac1_ptp_ref", clk_gmac_ptp_p, 0, + RK3568_CLKSEL_CON(33), 12, 2, MFLAGS, + RK3568_CLKGATE_CON(17), 2, GFLAGS), + MUX(SCLK_GMAC1, "clk_gmac1", mux_gmac1_p, CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT, + RK3568_CLKSEL_CON(33), 2, 1, MFLAGS), + FACTOR(0, "clk_gmac1_tx_div5", "clk_gmac1", 0, 1, 5), + FACTOR(0, "clk_gmac1_tx_div50", "clk_gmac1", 0, 1, 50), + FACTOR(0, "clk_gmac1_rx_div2", "clk_gmac1", 0, 1, 2), + FACTOR(0, "clk_gmac1_rx_div20", "clk_gmac1", 0, 1, 20), + MUX(SCLK_GMAC1_RGMII_SPEED, "clk_gmac1_rgmii_speed", mux_gmac1_rgmii_speed_p, 0, + RK3568_CLKSEL_CON(33), 4, 2, MFLAGS), + MUX(SCLK_GMAC1_RMII_SPEED, "clk_gmac1_rmii_speed", mux_gmac1_rmii_speed_p, 0, + RK3568_CLKSEL_CON(33), 3, 1, MFLAGS), + MUX(SCLK_GMAC1_RX_TX, "clk_gmac1_rx_tx", mux_gmac1_rx_tx_p, CLK_SET_RATE_PARENT, + RK3568_CLKSEL_CON(33), 0, 2, MFLAGS), + + /* PD_PERI */ + COMPOSITE_NODIV(ACLK_PERIMID, "aclk_perimid", gpll300_gpll200_gpll100_xin24m_p, CLK_IGNORE_UNUSED, + RK3568_CLKSEL_CON(10), 4, 2, MFLAGS, + RK3568_CLKGATE_CON(14), 0, GFLAGS), + COMPOSITE_NODIV(HCLK_PERIMID, "hclk_perimid", gpll150_gpll100_gpll75_xin24m_p, CLK_IGNORE_UNUSED, + RK3568_CLKSEL_CON(10), 6, 2, MFLAGS, + RK3568_CLKGATE_CON(14), 1, GFLAGS), + + /* PD_VI */ + COMPOSITE_NODIV(ACLK_VI, "aclk_vi", gpll400_gpll300_gpll200_xin24m_p, 0, + RK3568_CLKSEL_CON(34), 0, 2, MFLAGS, + RK3568_CLKGATE_CON(18), 0, GFLAGS), + COMPOSITE_NOMUX(HCLK_VI, "hclk_vi", "aclk_vi", 0, + RK3568_CLKSEL_CON(34), 4, 4, DFLAGS, + RK3568_CLKGATE_CON(18), 1, GFLAGS), + COMPOSITE_NOMUX(PCLK_VI, "pclk_vi", "aclk_vi", 0, + RK3568_CLKSEL_CON(34), 8, 4, DFLAGS, + RK3568_CLKGATE_CON(18), 2, GFLAGS), + GATE(ACLK_VICAP, "aclk_vicap", "aclk_vi", 0, + RK3568_CLKGATE_CON(18), 9, GFLAGS), + GATE(HCLK_VICAP, "hclk_vicap", "hclk_vi", 0, + RK3568_CLKGATE_CON(18), 10, GFLAGS), + COMPOSITE_NODIV(DCLK_VICAP, "dclk_vicap", cpll333_gpll300_gpll200_p, 0, + RK3568_CLKSEL_CON(34), 14, 2, MFLAGS, + RK3568_CLKGATE_CON(18), 11, GFLAGS), + GATE(ICLK_VICAP_G, "iclk_vicap_g", "iclk_vicap", 0, + RK3568_CLKGATE_CON(18), 13, GFLAGS), + GATE(ACLK_ISP, "aclk_isp", "aclk_vi", 0, + RK3568_CLKGATE_CON(19), 0, GFLAGS), + GATE(HCLK_ISP, "hclk_isp", "hclk_vi", 0, + RK3568_CLKGATE_CON(19), 1, GFLAGS), + COMPOSITE(CLK_ISP, "clk_isp", cpll_gpll_hpll_p, 0, + RK3568_CLKSEL_CON(35), 6, 2, MFLAGS, 0, 5, DFLAGS, + RK3568_CLKGATE_CON(19), 2, GFLAGS), + GATE(PCLK_CSI2HOST1, "pclk_csi2host1", "pclk_vi", 0, + RK3568_CLKGATE_CON(19), 4, GFLAGS), + COMPOSITE(CLK_CIF_OUT, "clk_cif_out", gpll_usb480m_xin24m_p, 0, + RK3568_CLKSEL_CON(35), 14, 2, MFLAGS, 8, 6, DFLAGS, + RK3568_CLKGATE_CON(19), 8, GFLAGS), + COMPOSITE(CLK_CAM0_OUT, "clk_cam0_out", gpll_usb480m_xin24m_p, 0, + RK3568_CLKSEL_CON(36), 6, 2, MFLAGS, 0, 6, DFLAGS, + RK3568_CLKGATE_CON(19), 9, GFLAGS), + COMPOSITE(CLK_CAM1_OUT, "clk_cam1_out", gpll_usb480m_xin24m_p, 0, + RK3568_CLKSEL_CON(36), 14, 2, MFLAGS, 8, 6, DFLAGS, + RK3568_CLKGATE_CON(19), 10, GFLAGS), + + /* PD_VO */ + COMPOSITE_NODIV(ACLK_VO, "aclk_vo", gpll300_cpll250_gpll100_xin24m_p, 0, + RK3568_CLKSEL_CON(37), 0, 2, MFLAGS, + RK3568_CLKGATE_CON(20), 0, GFLAGS), + COMPOSITE_NOMUX(HCLK_VO, "hclk_vo", "aclk_vo", 0, + RK3568_CLKSEL_CON(37), 8, 4, DFLAGS, + RK3568_CLKGATE_CON(20), 1, GFLAGS), + COMPOSITE_NOMUX(PCLK_VO, "pclk_vo", "aclk_vo", 0, + RK3568_CLKSEL_CON(37), 12, 4, DFLAGS, + RK3568_CLKGATE_CON(20), 2, GFLAGS), + COMPOSITE(ACLK_VOP_PRE, "aclk_vop_pre", cpll_gpll_hpll_vpll_p, 0, + RK3568_CLKSEL_CON(38), 6, 2, MFLAGS, 0, 5, DFLAGS, + RK3568_CLKGATE_CON(20), 6, GFLAGS), + GATE(ACLK_VOP, "aclk_vop", "aclk_vop_pre", 0, + RK3568_CLKGATE_CON(20), 8, GFLAGS), + GATE(HCLK_VOP, "hclk_vop", "hclk_vo", 0, + RK3568_CLKGATE_CON(20), 9, GFLAGS), + COMPOSITE(DCLK_VOP0, "dclk_vop0", hpll_vpll_gpll_cpll_p, CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT, + RK3568_CLKSEL_CON(39), 10, 2, MFLAGS, 0, 8, DFLAGS, + RK3568_CLKGATE_CON(20), 10, GFLAGS), + COMPOSITE(DCLK_VOP1, "dclk_vop1", hpll_vpll_gpll_cpll_p, CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT, + RK3568_CLKSEL_CON(40), 10, 2, MFLAGS, 0, 8, DFLAGS, + RK3568_CLKGATE_CON(20), 11, GFLAGS), + COMPOSITE(DCLK_VOP2, "dclk_vop2", hpll_vpll_gpll_cpll_p, 0, + RK3568_CLKSEL_CON(41), 10, 2, MFLAGS, 0, 8, DFLAGS, + RK3568_CLKGATE_CON(20), 12, GFLAGS), + GATE(CLK_VOP_PWM, "clk_vop_pwm", "xin24m", 0, + RK3568_CLKGATE_CON(20), 13, GFLAGS), + GATE(ACLK_HDCP, "aclk_hdcp", "aclk_vo", 0, + RK3568_CLKGATE_CON(21), 0, GFLAGS), + GATE(HCLK_HDCP, "hclk_hdcp", "hclk_vo", 0, + RK3568_CLKGATE_CON(21), 1, GFLAGS), + GATE(PCLK_HDCP, "pclk_hdcp", "pclk_vo", 0, + RK3568_CLKGATE_CON(21), 2, GFLAGS), + GATE(PCLK_HDMI_HOST, "pclk_hdmi_host", "pclk_vo", 0, + RK3568_CLKGATE_CON(21), 3, GFLAGS), + GATE(CLK_HDMI_SFR, "clk_hdmi_sfr", "xin24m", 0, + RK3568_CLKGATE_CON(21), 4, GFLAGS), + GATE(CLK_HDMI_CEC, "clk_hdmi_cec", "clk_rtc_32k", 0, + RK3568_CLKGATE_CON(21), 5, GFLAGS), + GATE(PCLK_DSITX_0, "pclk_dsitx_0", "pclk_vo", 0, + RK3568_CLKGATE_CON(21), 6, GFLAGS), + GATE(PCLK_DSITX_1, "pclk_dsitx_1", "pclk_vo", 0, + RK3568_CLKGATE_CON(21), 7, GFLAGS), + GATE(PCLK_EDP_CTRL, "pclk_edp_ctrl", "pclk_vo", 0, + RK3568_CLKGATE_CON(21), 8, GFLAGS), + COMPOSITE_NODIV(CLK_EDP_200M, "clk_edp_200m", gpll200_gpll150_cpll125_p, 0, + RK3568_CLKSEL_CON(38), 8, 2, MFLAGS, + RK3568_CLKGATE_CON(21), 9, GFLAGS), + + /* PD_VPU */ + COMPOSITE(ACLK_VPU_PRE, "aclk_vpu_pre", gpll_cpll_p, 0, + RK3568_CLKSEL_CON(42), 7, 1, MFLAGS, 0, 5, DFLAGS, + RK3568_CLKGATE_CON(22), 0, GFLAGS), + COMPOSITE_NOMUX(HCLK_VPU_PRE, "hclk_vpu_pre", "aclk_vpu_pre", 0, + RK3568_CLKSEL_CON(42), 8, 4, DFLAGS, + RK3568_CLKGATE_CON(22), 1, GFLAGS), + GATE(ACLK_VPU, "aclk_vpu", "aclk_vpu_pre", 0, + RK3568_CLKGATE_CON(22), 4, GFLAGS), + GATE(HCLK_VPU, "hclk_vpu", "hclk_vpu_pre", 0, + RK3568_CLKGATE_CON(22), 5, GFLAGS), + + /* PD_RGA */ + COMPOSITE_NODIV(ACLK_RGA_PRE, "aclk_rga_pre", gpll300_cpll250_gpll100_xin24m_p, 0, + RK3568_CLKSEL_CON(43), 0, 2, MFLAGS, + RK3568_CLKGATE_CON(23), 0, GFLAGS), + COMPOSITE_NOMUX(HCLK_RGA_PRE, "hclk_rga_pre", "aclk_rga_pre", 0, + RK3568_CLKSEL_CON(43), 8, 4, DFLAGS, + RK3568_CLKGATE_CON(23), 1, GFLAGS), + COMPOSITE_NOMUX(PCLK_RGA_PRE, "pclk_rga_pre", "aclk_rga_pre", 0, + RK3568_CLKSEL_CON(43), 12, 4, DFLAGS, + RK3568_CLKGATE_CON(22), 12, GFLAGS), + GATE(ACLK_RGA, "aclk_rga", "aclk_rga_pre", 0, + RK3568_CLKGATE_CON(23), 4, GFLAGS), + GATE(HCLK_RGA, "hclk_rga", "hclk_rga_pre", 0, + RK3568_CLKGATE_CON(23), 5, GFLAGS), + COMPOSITE_NODIV(CLK_RGA_CORE, "clk_rga_core", gpll300_gpll200_gpll100_p, 0, + RK3568_CLKSEL_CON(43), 2, 2, MFLAGS, + RK3568_CLKGATE_CON(23), 6, GFLAGS), + GATE(ACLK_IEP, "aclk_iep", "aclk_rga_pre", 0, + RK3568_CLKGATE_CON(23), 7, GFLAGS), + GATE(HCLK_IEP, "hclk_iep", "hclk_rga_pre", 0, + RK3568_CLKGATE_CON(23), 8, GFLAGS), + COMPOSITE_NODIV(CLK_IEP_CORE, "clk_iep_core", gpll300_gpll200_gpll100_p, 0, + RK3568_CLKSEL_CON(43), 4, 2, MFLAGS, + RK3568_CLKGATE_CON(23), 9, GFLAGS), + GATE(HCLK_EBC, "hclk_ebc", "hclk_rga_pre", 0, RK3568_CLKGATE_CON(23), 10, GFLAGS), + COMPOSITE_NODIV(DCLK_EBC, "dclk_ebc", gpll400_cpll333_gpll200_p, 0, + RK3568_CLKSEL_CON(43), 6, 2, MFLAGS, + RK3568_CLKGATE_CON(23), 11, GFLAGS), + GATE(ACLK_JDEC, "aclk_jdec", "aclk_rga_pre", 0, + RK3568_CLKGATE_CON(23), 12, GFLAGS), + GATE(HCLK_JDEC, "hclk_jdec", "hclk_rga_pre", 0, + RK3568_CLKGATE_CON(23), 13, GFLAGS), + GATE(ACLK_JENC, "aclk_jenc", "aclk_rga_pre", 0, + RK3568_CLKGATE_CON(23), 14, GFLAGS), + GATE(HCLK_JENC, "hclk_jenc", "hclk_rga_pre", 0, + RK3568_CLKGATE_CON(23), 15, GFLAGS), + GATE(PCLK_EINK, "pclk_eink", "pclk_rga_pre", 0, + RK3568_CLKGATE_CON(22), 14, GFLAGS), + GATE(HCLK_EINK, "hclk_eink", "hclk_rga_pre", 0, + RK3568_CLKGATE_CON(22), 15, GFLAGS), + + /* PD_RKVENC */ + COMPOSITE(ACLK_RKVENC_PRE, "aclk_rkvenc_pre", gpll_cpll_npll_p, 0, + RK3568_CLKSEL_CON(44), 6, 2, MFLAGS, 0, 5, DFLAGS, + RK3568_CLKGATE_CON(24), 0, GFLAGS), + COMPOSITE_NOMUX(HCLK_RKVENC_PRE, "hclk_rkvenc_pre", "aclk_rkvenc_pre", 0, + RK3568_CLKSEL_CON(44), 8, 4, DFLAGS, + RK3568_CLKGATE_CON(24), 1, GFLAGS), + GATE(ACLK_RKVENC, "aclk_rkvenc", "aclk_rkvenc_pre", 0, + RK3568_CLKGATE_CON(24), 6, GFLAGS), + GATE(HCLK_RKVENC, "hclk_rkvenc", "hclk_rkvenc_pre", 0, + RK3568_CLKGATE_CON(24), 7, GFLAGS), + COMPOSITE(CLK_RKVENC_CORE, "clk_rkvenc_core", gpll_cpll_npll_vpll_p, 0, + RK3568_CLKSEL_CON(45), 14, 2, MFLAGS, 0, 5, DFLAGS, + RK3568_CLKGATE_CON(24), 8, GFLAGS), + COMPOSITE(ACLK_RKVDEC_PRE, "aclk_rkvdec_pre", aclk_rkvdec_pre_p, CLK_SET_RATE_NO_REPARENT, + RK3568_CLKSEL_CON(47), 7, 1, MFLAGS, 0, 5, DFLAGS, + RK3568_CLKGATE_CON(25), 0, GFLAGS), + COMPOSITE_NOMUX(HCLK_RKVDEC_PRE, "hclk_rkvdec_pre", "aclk_rkvdec_pre", 0, + RK3568_CLKSEL_CON(47), 8, 4, DFLAGS, + RK3568_CLKGATE_CON(25), 1, GFLAGS), + GATE(ACLK_RKVDEC, "aclk_rkvdec", "aclk_rkvdec_pre", 0, + RK3568_CLKGATE_CON(25), 4, GFLAGS), + GATE(HCLK_RKVDEC, "hclk_rkvdec", "hclk_rkvdec_pre", 0, + RK3568_CLKGATE_CON(25), 5, GFLAGS), + COMPOSITE(CLK_RKVDEC_CA, "clk_rkvdec_ca", gpll_cpll_npll_vpll_p, 0, + RK3568_CLKSEL_CON(48), 6, 2, MFLAGS, 0, 5, DFLAGS, + RK3568_CLKGATE_CON(25), 6, GFLAGS), + COMPOSITE(CLK_RKVDEC_CORE, "clk_rkvdec_core", clk_rkvdec_core_p, CLK_SET_RATE_NO_REPARENT, + RK3568_CLKSEL_CON(49), 14, 2, MFLAGS, 8, 5, DFLAGS, + RK3568_CLKGATE_CON(25), 7, GFLAGS), + COMPOSITE(CLK_RKVDEC_HEVC_CA, "clk_rkvdec_hevc_ca", gpll_cpll_npll_vpll_p, 0, + RK3568_CLKSEL_CON(49), 6, 2, MFLAGS, 0, 5, DFLAGS, + RK3568_CLKGATE_CON(25), 8, GFLAGS), + + /* PD_BUS */ + COMPOSITE_NODIV(ACLK_BUS, "aclk_bus", gpll200_gpll150_gpll100_xin24m_p, 0, + RK3568_CLKSEL_CON(50), 0, 2, MFLAGS, + RK3568_CLKGATE_CON(26), 0, GFLAGS), + COMPOSITE_NODIV(PCLK_BUS, "pclk_bus", gpll100_gpll75_cpll50_xin24m_p, 0, + RK3568_CLKSEL_CON(50), 4, 2, MFLAGS, + RK3568_CLKGATE_CON(26), 1, GFLAGS), + GATE(PCLK_TSADC, "pclk_tsadc", "pclk_bus", 0, + RK3568_CLKGATE_CON(26), 4, GFLAGS), + COMPOSITE(CLK_TSADC_TSEN, "clk_tsadc_tsen", xin24m_gpll100_cpll100_p, 0, + RK3568_CLKSEL_CON(51), 4, 2, MFLAGS, 0, 3, DFLAGS, + RK3568_CLKGATE_CON(26), 5, GFLAGS), + COMPOSITE_NOMUX(CLK_TSADC, "clk_tsadc", "clk_tsadc_tsen", 0, + RK3568_CLKSEL_CON(51), 8, 7, DFLAGS, + RK3568_CLKGATE_CON(26), 6, GFLAGS), + GATE(PCLK_SARADC, "pclk_saradc", "pclk_bus", 0, + RK3568_CLKGATE_CON(26), 7, GFLAGS), + GATE(CLK_SARADC, "clk_saradc", "xin24m", 0, + RK3568_CLKGATE_CON(26), 8, GFLAGS), + GATE(PCLK_SCR, "pclk_scr", "pclk_bus", CLK_IGNORE_UNUSED, + RK3568_CLKGATE_CON(26), 12, GFLAGS), + GATE(PCLK_WDT_NS, "pclk_wdt_ns", "pclk_bus", 0, + RK3568_CLKGATE_CON(26), 13, GFLAGS), + GATE(TCLK_WDT_NS, "tclk_wdt_ns", "xin24m", 0, + RK3568_CLKGATE_CON(26), 14, GFLAGS), + GATE(ACLK_MCU, "aclk_mcu", "aclk_bus", CLK_IGNORE_UNUSED, + RK3568_CLKGATE_CON(32), 13, GFLAGS), + GATE(PCLK_INTMUX, "pclk_intmux", "pclk_bus", CLK_IGNORE_UNUSED, + RK3568_CLKGATE_CON(32), 14, GFLAGS), + GATE(PCLK_MAILBOX, "pclk_mailbox", "pclk_bus", 0, + RK3568_CLKGATE_CON(32), 15, GFLAGS), + + GATE(PCLK_UART1, "pclk_uart1", "pclk_bus", 0, + RK3568_CLKGATE_CON(27), 12, GFLAGS), + COMPOSITE(CLK_UART1_SRC, "clk_uart1_src", gpll_cpll_usb480m_p, 0, + RK3568_CLKSEL_CON(52), 8, 2, MFLAGS, 0, 7, DFLAGS, + RK3568_CLKGATE_CON(27), 13, GFLAGS), + COMPOSITE_FRACMUX(CLK_UART1_FRAC, "clk_uart1_frac", "clk_uart1_src", CLK_SET_RATE_PARENT, + RK3568_CLKSEL_CON(53), 0, + RK3568_CLKGATE_CON(27), 14, GFLAGS, + &rk3568_uart1_fracmux), + GATE(SCLK_UART1, "sclk_uart1", "sclk_uart1_mux", 0, + RK3568_CLKGATE_CON(27), 15, GFLAGS), + + GATE(PCLK_UART2, "pclk_uart2", "pclk_bus", 0, + RK3568_CLKGATE_CON(28), 0, GFLAGS), + COMPOSITE(CLK_UART2_SRC, "clk_uart2_src", gpll_cpll_usb480m_p, 0, + RK3568_CLKSEL_CON(54), 8, 2, MFLAGS, 0, 7, DFLAGS, + RK3568_CLKGATE_CON(28), 1, GFLAGS), + COMPOSITE_FRACMUX(CLK_UART2_FRAC, "clk_uart2_frac", "clk_uart2_src", CLK_SET_RATE_PARENT, + RK3568_CLKSEL_CON(55), 0, + RK3568_CLKGATE_CON(28), 2, GFLAGS, + &rk3568_uart2_fracmux), + GATE(SCLK_UART2, "sclk_uart2", "sclk_uart2_mux", 0, + RK3568_CLKGATE_CON(28), 3, GFLAGS), + + GATE(PCLK_UART3, "pclk_uart3", "pclk_bus", 0, + RK3568_CLKGATE_CON(28), 4, GFLAGS), + COMPOSITE(CLK_UART3_SRC, "clk_uart3_src", gpll_cpll_usb480m_p, 0, + RK3568_CLKSEL_CON(56), 8, 2, MFLAGS, 0, 7, DFLAGS, + RK3568_CLKGATE_CON(28), 5, GFLAGS), + COMPOSITE_FRACMUX(CLK_UART3_FRAC, "clk_uart3_frac", "clk_uart3_src", CLK_SET_RATE_PARENT, + RK3568_CLKSEL_CON(57), 0, + RK3568_CLKGATE_CON(28), 6, GFLAGS, + &rk3568_uart3_fracmux), + GATE(SCLK_UART3, "sclk_uart3", "sclk_uart3_mux", 0, + RK3568_CLKGATE_CON(28), 7, GFLAGS), + + GATE(PCLK_UART4, "pclk_uart4", "pclk_bus", 0, + RK3568_CLKGATE_CON(28), 8, GFLAGS), + COMPOSITE(CLK_UART4_SRC, "clk_uart4_src", gpll_cpll_usb480m_p, 0, + RK3568_CLKSEL_CON(58), 8, 2, MFLAGS, 0, 7, DFLAGS, + RK3568_CLKGATE_CON(28), 9, GFLAGS), + COMPOSITE_FRACMUX(CLK_UART4_FRAC, "clk_uart4_frac", "clk_uart4_src", CLK_SET_RATE_PARENT, + RK3568_CLKSEL_CON(59), 0, + RK3568_CLKGATE_CON(28), 10, GFLAGS, + &rk3568_uart4_fracmux), + GATE(SCLK_UART4, "sclk_uart4", "sclk_uart4_mux", 0, + RK3568_CLKGATE_CON(28), 11, GFLAGS), + + GATE(PCLK_UART5, "pclk_uart5", "pclk_bus", 0, + RK3568_CLKGATE_CON(28), 12, GFLAGS), + COMPOSITE(CLK_UART5_SRC, "clk_uart5_src", gpll_cpll_usb480m_p, 0, + RK3568_CLKSEL_CON(60), 8, 2, MFLAGS, 0, 7, DFLAGS, + RK3568_CLKGATE_CON(28), 13, GFLAGS), + COMPOSITE_FRACMUX(CLK_UART5_FRAC, "clk_uart5_frac", "clk_uart5_src", CLK_SET_RATE_PARENT, + RK3568_CLKSEL_CON(61), 0, + RK3568_CLKGATE_CON(28), 14, GFLAGS, + &rk3568_uart5_fracmux), + GATE(SCLK_UART5, "sclk_uart5", "sclk_uart5_mux", 0, + RK3568_CLKGATE_CON(28), 15, GFLAGS), + + GATE(PCLK_UART6, "pclk_uart6", "pclk_bus", 0, + RK3568_CLKGATE_CON(29), 0, GFLAGS), + COMPOSITE(CLK_UART6_SRC, "clk_uart6_src", gpll_cpll_usb480m_p, 0, + RK3568_CLKSEL_CON(62), 8, 2, MFLAGS, 0, 7, DFLAGS, + RK3568_CLKGATE_CON(29), 1, GFLAGS), + COMPOSITE_FRACMUX(CLK_UART6_FRAC, "clk_uart6_frac", "clk_uart6_src", CLK_SET_RATE_PARENT, + RK3568_CLKSEL_CON(63), 0, + RK3568_CLKGATE_CON(29), 2, GFLAGS, + &rk3568_uart6_fracmux), + GATE(SCLK_UART6, "sclk_uart6", "sclk_uart6_mux", 0, + RK3568_CLKGATE_CON(29), 3, GFLAGS), + + GATE(PCLK_UART7, "pclk_uart7", "pclk_bus", 0, + RK3568_CLKGATE_CON(29), 4, GFLAGS), + COMPOSITE(CLK_UART7_SRC, "clk_uart7_src", gpll_cpll_usb480m_p, 0, + RK3568_CLKSEL_CON(64), 8, 2, MFLAGS, 0, 7, DFLAGS, + RK3568_CLKGATE_CON(29), 5, GFLAGS), + COMPOSITE_FRACMUX(CLK_UART7_FRAC, "clk_uart7_frac", "clk_uart7_src", CLK_SET_RATE_PARENT, + RK3568_CLKSEL_CON(65), 0, + RK3568_CLKGATE_CON(29), 6, GFLAGS, + &rk3568_uart7_fracmux), + GATE(SCLK_UART7, "sclk_uart7", "sclk_uart7_mux", 0, + RK3568_CLKGATE_CON(29), 7, GFLAGS), + + GATE(PCLK_UART8, "pclk_uart8", "pclk_bus", 0, + RK3568_CLKGATE_CON(29), 8, GFLAGS), + COMPOSITE(CLK_UART8_SRC, "clk_uart8_src", gpll_cpll_usb480m_p, 0, + RK3568_CLKSEL_CON(66), 8, 2, MFLAGS, 0, 7, DFLAGS, + RK3568_CLKGATE_CON(29), 9, GFLAGS), + COMPOSITE_FRACMUX(CLK_UART8_FRAC, "clk_uart8_frac", "clk_uart8_src", CLK_SET_RATE_PARENT, + RK3568_CLKSEL_CON(67), 0, + RK3568_CLKGATE_CON(29), 10, GFLAGS, + &rk3568_uart8_fracmux), + GATE(SCLK_UART8, "sclk_uart8", "sclk_uart8_mux", 0, + RK3568_CLKGATE_CON(29), 11, GFLAGS), + + GATE(PCLK_UART9, "pclk_uart9", "pclk_bus", 0, + RK3568_CLKGATE_CON(29), 12, GFLAGS), + COMPOSITE(CLK_UART9_SRC, "clk_uart9_src", gpll_cpll_usb480m_p, 0, + RK3568_CLKSEL_CON(68), 8, 2, MFLAGS, 0, 7, DFLAGS, + RK3568_CLKGATE_CON(29), 13, GFLAGS), + COMPOSITE_FRACMUX(CLK_UART9_FRAC, "clk_uart9_frac", "clk_uart9_src", CLK_SET_RATE_PARENT, + RK3568_CLKSEL_CON(69), 0, + RK3568_CLKGATE_CON(29), 14, GFLAGS, + &rk3568_uart9_fracmux), + GATE(SCLK_UART9, "sclk_uart9", "sclk_uart9_mux", 0, + RK3568_CLKGATE_CON(29), 15, GFLAGS), + + GATE(PCLK_CAN0, "pclk_can0", "pclk_bus", 0, + RK3568_CLKGATE_CON(27), 5, GFLAGS), + COMPOSITE(CLK_CAN0, "clk_can0", gpll_cpll_p, 0, + RK3568_CLKSEL_CON(70), 7, 1, MFLAGS, 0, 5, DFLAGS, + RK3568_CLKGATE_CON(27), 6, GFLAGS), + GATE(PCLK_CAN1, "pclk_can1", "pclk_bus", 0, + RK3568_CLKGATE_CON(27), 7, GFLAGS), + COMPOSITE(CLK_CAN1, "clk_can1", gpll_cpll_p, 0, + RK3568_CLKSEL_CON(70), 15, 1, MFLAGS, 8, 5, DFLAGS, + RK3568_CLKGATE_CON(27), 8, GFLAGS), + GATE(PCLK_CAN2, "pclk_can2", "pclk_bus", 0, + RK3568_CLKGATE_CON(27), 9, GFLAGS), + COMPOSITE(CLK_CAN2, "clk_can2", gpll_cpll_p, 0, + RK3568_CLKSEL_CON(71), 7, 1, MFLAGS, 0, 5, DFLAGS, + RK3568_CLKGATE_CON(27), 10, GFLAGS), + COMPOSITE_NODIV(CLK_I2C, "clk_i2c", clk_i2c_p, 0, + RK3568_CLKSEL_CON(71), 8, 2, MFLAGS, + RK3568_CLKGATE_CON(32), 10, GFLAGS), + GATE(PCLK_I2C1, "pclk_i2c1", "pclk_bus", 0, + RK3568_CLKGATE_CON(30), 0, GFLAGS), + GATE(CLK_I2C1, "clk_i2c1", "clk_i2c", 0, + RK3568_CLKGATE_CON(30), 1, GFLAGS), + GATE(PCLK_I2C2, "pclk_i2c2", "pclk_bus", 0, + RK3568_CLKGATE_CON(30), 2, GFLAGS), + GATE(CLK_I2C2, "clk_i2c2", "clk_i2c", 0, + RK3568_CLKGATE_CON(30), 3, GFLAGS), + GATE(PCLK_I2C3, "pclk_i2c3", "pclk_bus", 0, + RK3568_CLKGATE_CON(30), 4, GFLAGS), + GATE(CLK_I2C3, "clk_i2c3", "clk_i2c", 0, + RK3568_CLKGATE_CON(30), 5, GFLAGS), + GATE(PCLK_I2C4, "pclk_i2c4", "pclk_bus", 0, + RK3568_CLKGATE_CON(30), 6, GFLAGS), + GATE(CLK_I2C4, "clk_i2c4", "clk_i2c", 0, + RK3568_CLKGATE_CON(30), 7, GFLAGS), + GATE(PCLK_I2C5, "pclk_i2c5", "pclk_bus", 0, + RK3568_CLKGATE_CON(30), 8, GFLAGS), + GATE(CLK_I2C5, "clk_i2c5", "clk_i2c", 0, + RK3568_CLKGATE_CON(30), 9, GFLAGS), + GATE(PCLK_SPI0, "pclk_spi0", "pclk_bus", 0, + RK3568_CLKGATE_CON(30), 10, GFLAGS), + COMPOSITE_NODIV(CLK_SPI0, "clk_spi0", gpll200_xin24m_cpll100_p, 0, + RK3568_CLKSEL_CON(72), 0, 1, MFLAGS, + RK3568_CLKGATE_CON(30), 11, GFLAGS), + GATE(PCLK_SPI1, "pclk_spi1", "pclk_bus", 0, + RK3568_CLKGATE_CON(30), 12, GFLAGS), + COMPOSITE_NODIV(CLK_SPI1, "clk_spi1", gpll200_xin24m_cpll100_p, 0, + RK3568_CLKSEL_CON(72), 2, 1, MFLAGS, + RK3568_CLKGATE_CON(30), 13, GFLAGS), + GATE(PCLK_SPI2, "pclk_spi2", "pclk_bus", 0, + RK3568_CLKGATE_CON(30), 14, GFLAGS), + COMPOSITE_NODIV(CLK_SPI2, "clk_spi2", gpll200_xin24m_cpll100_p, 0, + RK3568_CLKSEL_CON(72), 4, 1, MFLAGS, + RK3568_CLKGATE_CON(30), 15, GFLAGS), + GATE(PCLK_SPI3, "pclk_spi3", "pclk_bus", 0, + RK3568_CLKGATE_CON(31), 0, GFLAGS), + COMPOSITE_NODIV(CLK_SPI3, "clk_spi3", gpll200_xin24m_cpll100_p, 0, + RK3568_CLKSEL_CON(72), 6, 1, MFLAGS, RK3568_CLKGATE_CON(31), 1, GFLAGS), + GATE(PCLK_PWM1, "pclk_pwm1", "pclk_bus", 0, RK3568_CLKGATE_CON(31), 10, GFLAGS), + COMPOSITE_NODIV(CLK_PWM1, "clk_pwm1", gpll100_xin24m_cpll100_p, 0, + RK3568_CLKSEL_CON(72), 8, 1, MFLAGS, + RK3568_CLKGATE_CON(31), 11, GFLAGS), + GATE(CLK_PWM1_CAPTURE, "clk_pwm1_capture", "xin24m", 0, + RK3568_CLKGATE_CON(31), 12, GFLAGS), + GATE(PCLK_PWM2, "pclk_pwm2", "pclk_bus", 0, + RK3568_CLKGATE_CON(31), 13, GFLAGS), + COMPOSITE_NODIV(CLK_PWM2, "clk_pwm2", gpll100_xin24m_cpll100_p, 0, + RK3568_CLKSEL_CON(72), 10, 1, MFLAGS, + RK3568_CLKGATE_CON(31), 14, GFLAGS), + GATE(CLK_PWM2_CAPTURE, "clk_pwm2_capture", "xin24m", 0, + RK3568_CLKGATE_CON(31), 15, GFLAGS), + GATE(PCLK_PWM3, "pclk_pwm3", "pclk_bus", 0, + RK3568_CLKGATE_CON(32), 0, GFLAGS), + COMPOSITE_NODIV(CLK_PWM3, "clk_pwm3", gpll100_xin24m_cpll100_p, 0, + RK3568_CLKSEL_CON(72), 12, 1, MFLAGS, + RK3568_CLKGATE_CON(32), 1, GFLAGS), + GATE(CLK_PWM3_CAPTURE, "clk_pwm3_capture", "xin24m", 0, + RK3568_CLKGATE_CON(32), 2, GFLAGS), + COMPOSITE_NODIV(DBCLK_GPIO, "dbclk_gpio", xin24m_32k_p, 0, + RK3568_CLKSEL_CON(72), 14, 1, MFLAGS, + RK3568_CLKGATE_CON(32), 11, GFLAGS), + GATE(PCLK_GPIO1, "pclk_gpio1", "pclk_bus", 0, + RK3568_CLKGATE_CON(31), 2, GFLAGS), + GATE(DBCLK_GPIO1, "dbclk_gpio1", "dbclk_gpio", 0, + RK3568_CLKGATE_CON(31), 3, GFLAGS), + GATE(PCLK_GPIO2, "pclk_gpio2", "pclk_bus", 0, + RK3568_CLKGATE_CON(31), 4, GFLAGS), + GATE(DBCLK_GPIO2, "dbclk_gpio2", "dbclk_gpio", 0, + RK3568_CLKGATE_CON(31), 5, GFLAGS), + GATE(PCLK_GPIO3, "pclk_gpio3", "pclk_bus", 0, + RK3568_CLKGATE_CON(31), 6, GFLAGS), + GATE(DBCLK_GPIO3, "dbclk_gpio3", "dbclk_gpio", 0, + RK3568_CLKGATE_CON(31), 7, GFLAGS), + GATE(PCLK_GPIO4, "pclk_gpio4", "pclk_bus", 0, + RK3568_CLKGATE_CON(31), 8, GFLAGS), + GATE(DBCLK_GPIO4, "dbclk_gpio4", "dbclk_gpio", 0, + RK3568_CLKGATE_CON(31), 9, GFLAGS), + GATE(PCLK_TIMER, "pclk_timer", "pclk_bus", 0, + RK3568_CLKGATE_CON(32), 3, GFLAGS), + GATE(CLK_TIMER0, "clk_timer0", "xin24m", 0, + RK3568_CLKGATE_CON(32), 4, GFLAGS), + GATE(CLK_TIMER1, "clk_timer1", "xin24m", 0, + RK3568_CLKGATE_CON(32), 5, GFLAGS), + GATE(CLK_TIMER2, "clk_timer2", "xin24m", 0, + RK3568_CLKGATE_CON(32), 6, GFLAGS), + GATE(CLK_TIMER3, "clk_timer3", "xin24m", 0, + RK3568_CLKGATE_CON(32), 7, GFLAGS), + GATE(CLK_TIMER4, "clk_timer4", "xin24m", 0, + RK3568_CLKGATE_CON(32), 8, GFLAGS), + GATE(CLK_TIMER5, "clk_timer5", "xin24m", 0, + RK3568_CLKGATE_CON(32), 9, GFLAGS), + + /* PD_TOP */ + COMPOSITE_NODIV(ACLK_TOP_HIGH, "aclk_top_high", cpll500_gpll400_gpll300_xin24m_p, 0, + RK3568_CLKSEL_CON(73), 0, 2, MFLAGS, + RK3568_CLKGATE_CON(33), 0, GFLAGS), + COMPOSITE_NODIV(ACLK_TOP_LOW, "aclk_top_low", gpll400_gpll300_gpll200_xin24m_p, 0, + RK3568_CLKSEL_CON(73), 4, 2, MFLAGS, + RK3568_CLKGATE_CON(33), 1, GFLAGS), + COMPOSITE_NODIV(HCLK_TOP, "hclk_top", gpll150_gpll100_gpll75_xin24m_p, 0, + RK3568_CLKSEL_CON(73), 8, 2, MFLAGS, + RK3568_CLKGATE_CON(33), 2, GFLAGS), + COMPOSITE_NODIV(PCLK_TOP, "pclk_top", gpll100_gpll75_cpll50_xin24m_p, 0, + RK3568_CLKSEL_CON(73), 12, 2, MFLAGS, + RK3568_CLKGATE_CON(33), 3, GFLAGS), + GATE(PCLK_PCIE30PHY, "pclk_pcie30phy", "pclk_top", 0, + RK3568_CLKGATE_CON(33), 8, GFLAGS), + COMPOSITE_NODIV(CLK_OPTC_ARB, "clk_optc_arb", xin24m_cpll100_p, 0, + RK3568_CLKSEL_CON(73), 15, 1, MFLAGS, + RK3568_CLKGATE_CON(33), 9, GFLAGS), + GATE(PCLK_MIPICSIPHY, "pclk_mipicsiphy", "pclk_top", 0, + RK3568_CLKGATE_CON(33), 13, GFLAGS), + GATE(PCLK_MIPIDSIPHY0, "pclk_mipidsiphy0", "pclk_top", 0, + RK3568_CLKGATE_CON(33), 14, GFLAGS), + GATE(PCLK_MIPIDSIPHY1, "pclk_mipidsiphy1", "pclk_top", 0, + RK3568_CLKGATE_CON(33), 15, GFLAGS), + GATE(PCLK_PIPEPHY0, "pclk_pipephy0", "pclk_top", 0, + RK3568_CLKGATE_CON(34), 4, GFLAGS), + GATE(PCLK_PIPEPHY1, "pclk_pipephy1", "pclk_top", 0, + RK3568_CLKGATE_CON(34), 5, GFLAGS), + GATE(PCLK_PIPEPHY2, "pclk_pipephy2", "pclk_top", 0, + RK3568_CLKGATE_CON(34), 6, GFLAGS), + GATE(PCLK_CPU_BOOST, "pclk_cpu_boost", "pclk_top", 0, + RK3568_CLKGATE_CON(34), 11, GFLAGS), + GATE(CLK_CPU_BOOST, "clk_cpu_boost", "xin24m", 0, + RK3568_CLKGATE_CON(34), 12, GFLAGS), + GATE(PCLK_OTPPHY, "pclk_otpphy", "pclk_top", 0, + RK3568_CLKGATE_CON(34), 13, GFLAGS), + GATE(PCLK_EDPPHY_GRF, "pclk_edpphy_grf", "pclk_top", 0, + RK3568_CLKGATE_CON(34), 14, GFLAGS), +}; + +static struct rockchip_clk_branch rk3568_clk_pmu_branches[] __initdata = { + /* PD_PMU */ + FACTOR(0, "ppll_ph0", "ppll", 0, 1, 2), + FACTOR(0, "ppll_ph180", "ppll", 0, 1, 2), + FACTOR(0, "hpll_ph0", "hpll", 0, 1, 2), + + MUX(CLK_PDPMU, "clk_pdpmu", clk_pdpmu_p, 0, + RK3568_PMU_CLKSEL_CON(2), 15, 1, MFLAGS), + COMPOSITE_NOMUX(PCLK_PDPMU, "pclk_pdpmu", "clk_pdpmu", 0, + RK3568_PMU_CLKSEL_CON(2), 0, 5, DFLAGS, + RK3568_PMU_CLKGATE_CON(0), 2, GFLAGS), + GATE(PCLK_PMU, "pclk_pmu", "pclk_pdpmu", 0, + RK3568_PMU_CLKGATE_CON(0), 6, GFLAGS), + GATE(CLK_PMU, "clk_pmu", "xin24m", 0, + RK3568_PMU_CLKGATE_CON(0), 7, GFLAGS), + GATE(PCLK_I2C0, "pclk_i2c0", "pclk_pdpmu", 0, + RK3568_PMU_CLKGATE_CON(1), 0, GFLAGS), + COMPOSITE_NOMUX(CLK_I2C0, "clk_i2c0", "clk_pdpmu", 0, + RK3568_PMU_CLKSEL_CON(3), 0, 7, DFLAGS, + RK3568_PMU_CLKGATE_CON(1), 1, GFLAGS), + GATE(PCLK_UART0, "pclk_uart0", "pclk_pdpmu", 0, + RK3568_PMU_CLKGATE_CON(1), 2, GFLAGS), + + COMPOSITE_FRACMUX(CLK_RTC32K_FRAC, "clk_rtc32k_frac", "xin24m", CLK_IGNORE_UNUSED, + RK3568_PMU_CLKSEL_CON(1), 0, + RK3568_PMU_CLKGATE_CON(0), 1, GFLAGS, + &rk3568_rtc32k_pmu_fracmux), + + COMPOSITE_NOMUX(XIN_OSC0_DIV, "xin_osc0_div", "xin24m", CLK_IGNORE_UNUSED, + RK3568_PMU_CLKSEL_CON(0), 0, 5, DFLAGS, + RK3568_PMU_CLKGATE_CON(0), 0, GFLAGS), + + COMPOSITE(CLK_UART0_DIV, "sclk_uart0_div", ppll_usb480m_cpll_gpll_p, 0, + RK3568_PMU_CLKSEL_CON(4), 8, 2, MFLAGS, 0, 7, DFLAGS, + RK3568_PMU_CLKGATE_CON(1), 3, GFLAGS), + COMPOSITE_FRACMUX(CLK_UART0_FRAC, "sclk_uart0_frac", "sclk_uart0_div", CLK_SET_RATE_PARENT, + RK3568_PMU_CLKSEL_CON(5), 0, + RK3568_PMU_CLKGATE_CON(1), 4, GFLAGS, + &rk3568_uart0_fracmux), + GATE(SCLK_UART0, "sclk_uart0", "sclk_uart0_mux", 0, + RK3568_PMU_CLKGATE_CON(1), 5, GFLAGS), + + GATE(PCLK_GPIO0, "pclk_gpio0", "pclk_pdpmu", 0, + RK3568_PMU_CLKGATE_CON(1), 9, GFLAGS), + COMPOSITE_NODIV(DBCLK_GPIO0, "dbclk_gpio0", xin24m_32k_p, 0, + RK3568_PMU_CLKSEL_CON(6), 15, 1, MFLAGS, + RK3568_PMU_CLKGATE_CON(1), 10, GFLAGS), + GATE(PCLK_PWM0, "pclk_pwm0", "pclk_pdpmu", 0, + RK3568_PMU_CLKGATE_CON(1), 6, GFLAGS), + COMPOSITE(CLK_PWM0, "clk_pwm0", clk_pwm0_p, 0, + RK3568_PMU_CLKSEL_CON(6), 7, 1, MFLAGS, 0, 7, DFLAGS, + RK3568_PMU_CLKGATE_CON(1), 7, GFLAGS), + GATE(CLK_CAPTURE_PWM0_NDFT, "clk_capture_pwm0_ndft", "xin24m", 0, + RK3568_PMU_CLKGATE_CON(1), 8, GFLAGS), + GATE(PCLK_PMUPVTM, "pclk_pmupvtm", "pclk_pdpmu", 0, + RK3568_PMU_CLKGATE_CON(1), 11, GFLAGS), + GATE(CLK_PMUPVTM, "clk_pmupvtm", "xin24m", 0, + RK3568_PMU_CLKGATE_CON(1), 12, GFLAGS), + GATE(CLK_CORE_PMUPVTM, "clk_core_pmupvtm", "xin24m", 0, + RK3568_PMU_CLKGATE_CON(1), 13, GFLAGS), + COMPOSITE_NOMUX(CLK_REF24M, "clk_ref24m", "clk_pdpmu", 0, + RK3568_PMU_CLKSEL_CON(7), 0, 6, DFLAGS, + RK3568_PMU_CLKGATE_CON(2), 0, GFLAGS), + GATE(XIN_OSC0_USBPHY0_G, "xin_osc0_usbphy0_g", "xin24m", 0, + RK3568_PMU_CLKGATE_CON(2), 1, GFLAGS), + MUX(CLK_USBPHY0_REF, "clk_usbphy0_ref", clk_usbphy0_ref_p, 0, + RK3568_PMU_CLKSEL_CON(8), 0, 1, MFLAGS), + GATE(XIN_OSC0_USBPHY1_G, "xin_osc0_usbphy1_g", "xin24m", 0, + RK3568_PMU_CLKGATE_CON(2), 2, GFLAGS), + MUX(CLK_USBPHY1_REF, "clk_usbphy1_ref", clk_usbphy1_ref_p, 0, + RK3568_PMU_CLKSEL_CON(8), 1, 1, MFLAGS), + GATE(XIN_OSC0_MIPIDSIPHY0_G, "xin_osc0_mipidsiphy0_g", "xin24m", 0, + RK3568_PMU_CLKGATE_CON(2), 3, GFLAGS), + MUX(CLK_MIPIDSIPHY0_REF, "clk_mipidsiphy0_ref", clk_mipidsiphy0_ref_p, 0, + RK3568_PMU_CLKSEL_CON(8), 2, 1, MFLAGS), + GATE(XIN_OSC0_MIPIDSIPHY1_G, "xin_osc0_mipidsiphy1_g", "xin24m", 0, + RK3568_PMU_CLKGATE_CON(2), 4, GFLAGS), + MUX(CLK_MIPIDSIPHY1_REF, "clk_mipidsiphy1_ref", clk_mipidsiphy1_ref_p, 0, + RK3568_PMU_CLKSEL_CON(8), 3, 1, MFLAGS), + COMPOSITE_NOMUX(CLK_WIFI_DIV, "clk_wifi_div", "clk_pdpmu", 0, + RK3568_PMU_CLKSEL_CON(8), 8, 6, DFLAGS, + RK3568_PMU_CLKGATE_CON(2), 5, GFLAGS), + GATE(CLK_WIFI_OSC0, "clk_wifi_osc0", "xin24m", 0, + RK3568_PMU_CLKGATE_CON(2), 6, GFLAGS), + MUX(CLK_WIFI, "clk_wifi", clk_wifi_p, CLK_SET_RATE_PARENT, + RK3568_PMU_CLKSEL_CON(8), 15, 1, MFLAGS), + COMPOSITE_NOMUX(CLK_PCIEPHY0_DIV, "clk_pciephy0_div", "ppll_ph0", 0, + RK3568_PMU_CLKSEL_CON(9), 0, 3, DFLAGS, + RK3568_PMU_CLKGATE_CON(2), 7, GFLAGS), + GATE(CLK_PCIEPHY0_OSC0, "clk_pciephy0_osc0", "xin24m", 0, + RK3568_PMU_CLKGATE_CON(2), 8, GFLAGS), + MUX(CLK_PCIEPHY0_REF, "clk_pciephy0_ref", clk_pciephy0_ref_p, CLK_SET_RATE_PARENT, + RK3568_PMU_CLKSEL_CON(9), 3, 1, MFLAGS), + COMPOSITE_NOMUX(CLK_PCIEPHY1_DIV, "clk_pciephy1_div", "ppll_ph0", 0, + RK3568_PMU_CLKSEL_CON(9), 4, 3, DFLAGS, + RK3568_PMU_CLKGATE_CON(2), 9, GFLAGS), + GATE(CLK_PCIEPHY1_OSC0, "clk_pciephy1_osc0", "xin24m", 0, + RK3568_PMU_CLKGATE_CON(2), 10, GFLAGS), + MUX(CLK_PCIEPHY1_REF, "clk_pciephy1_ref", clk_pciephy1_ref_p, CLK_SET_RATE_PARENT, + RK3568_PMU_CLKSEL_CON(9), 7, 1, MFLAGS), + COMPOSITE_NOMUX(CLK_PCIEPHY2_DIV, "clk_pciephy2_div", "ppll_ph0", 0, + RK3568_PMU_CLKSEL_CON(9), 8, 3, DFLAGS, + RK3568_PMU_CLKGATE_CON(2), 11, GFLAGS), + GATE(CLK_PCIEPHY2_OSC0, "clk_pciephy2_osc0", "xin24m", 0, + RK3568_PMU_CLKGATE_CON(2), 12, GFLAGS), + MUX(CLK_PCIEPHY2_REF, "clk_pciephy2_ref", clk_pciephy2_ref_p, CLK_SET_RATE_PARENT, + RK3568_PMU_CLKSEL_CON(9), 11, 1, MFLAGS), + GATE(CLK_PCIE30PHY_REF_M, "clk_pcie30phy_ref_m", "ppll_ph0", 0, + RK3568_PMU_CLKGATE_CON(2), 13, GFLAGS), + GATE(CLK_PCIE30PHY_REF_N, "clk_pcie30phy_ref_n", "ppll_ph180", 0, + RK3568_PMU_CLKGATE_CON(2), 14, GFLAGS), + GATE(XIN_OSC0_EDPPHY_G, "xin_osc0_edpphy_g", "xin24m", 0, + RK3568_PMU_CLKGATE_CON(2), 15, GFLAGS), + MUX(CLK_HDMI_REF, "clk_hdmi_ref", clk_hdmi_ref_p, 0, + RK3568_PMU_CLKSEL_CON(8), 7, 1, MFLAGS), +}; + +static const char *const rk3568_cru_critical_clocks[] __initconst = { + "armclk", + "pclk_core_pre", + "aclk_bus", + "pclk_bus", + "aclk_top_high", + "aclk_top_low", + "hclk_top", + "pclk_top", + "aclk_perimid", + "hclk_perimid", + "aclk_secure_flash", + "hclk_secure_flash", + "aclk_core_niu2bus", + "npll", + "clk_optc_arb", + "hclk_php", + "pclk_php", + "hclk_usb", +}; + +static const char *const rk3568_pmucru_critical_clocks[] __initconst = { + "pclk_pdpmu", + "pclk_pmu", + "clk_pmu", +}; + +static void __init rk3568_pmu_clk_init(struct device_node *np) +{ + struct rockchip_clk_provider *ctx; + void __iomem *reg_base; + + reg_base = of_iomap(np, 0); + if (!reg_base) { + pr_err("%s: could not map cru pmu region\n", __func__); + return; + } + + ctx = rockchip_clk_init(np, reg_base, CLKPMU_NR_CLKS); + if (IS_ERR(ctx)) { + pr_err("%s: rockchip pmu clk init failed\n", __func__); + return; + } + + rockchip_clk_register_plls(ctx, rk3568_pmu_pll_clks, + ARRAY_SIZE(rk3568_pmu_pll_clks), + RK3568_GRF_SOC_STATUS0); + + rockchip_clk_register_branches(ctx, rk3568_clk_pmu_branches, + ARRAY_SIZE(rk3568_clk_pmu_branches)); + + rockchip_clk_protect_critical(rk3568_pmucru_critical_clocks, + ARRAY_SIZE(rk3568_pmucru_critical_clocks)); + + rockchip_clk_of_add_provider(np, ctx); +} + +static void __init rk3568_clk_init(struct device_node *np) +{ + struct rockchip_clk_provider *ctx; + void __iomem *reg_base; + + reg_base = of_iomap(np, 0); + if (!reg_base) { + pr_err("%s: could not map cru region\n", __func__); + return; + } + + ctx = rockchip_clk_init(np, reg_base, CLK_NR_CLKS); + if (IS_ERR(ctx)) { + pr_err("%s: rockchip clk init failed\n", __func__); + return; + } + + rockchip_clk_register_plls(ctx, rk3568_pll_clks, + ARRAY_SIZE(rk3568_pll_clks), + RK3568_GRF_SOC_STATUS0); + + rockchip_clk_register_armclk(ctx, ARMCLK, "armclk", + mux_armclk_p, ARRAY_SIZE(mux_armclk_p), + &rk3568_cpuclk_data, rk3568_cpuclk_rates, + ARRAY_SIZE(rk3568_cpuclk_rates)); + + rockchip_clk_register_branches(ctx, rk3568_clk_branches, + ARRAY_SIZE(rk3568_clk_branches)); + + rockchip_register_restart_notifier(ctx, RK3568_GLB_SRST_FST); + + rockchip_clk_protect_critical(rk3568_cru_critical_clocks, + ARRAY_SIZE(rk3568_cru_critical_clocks)); + + rockchip_clk_of_add_provider(np, ctx); +} + +struct clk_rk3568_inits { + void (*inits)(struct device_node *np); +}; + +static const struct clk_rk3568_inits clk_rk3568_pmucru_init = { + .inits = rk3568_pmu_clk_init, +}; + +static const struct clk_rk3568_inits clk_3568_cru_init = { + .inits = rk3568_clk_init, +}; + +static const struct of_device_id clk_rk3568_match_table[] = { + { + .compatible = "rockchip,rk3568-cru", + .data = &clk_3568_cru_init, + }, { + .compatible = "rockchip,rk3568-pmucru", + .data = &clk_rk3568_pmucru_init, + }, + { } +}; + +static int __init clk_rk3568_probe(struct device_d *dev) +{ + struct device_node *np = dev->device_node; + const struct clk_rk3568_inits *init_data; + + init_data = of_device_get_match_data(dev); + if (init_data->inits) + init_data->inits(np); + + return 0; +} + +static struct driver_d clk_rk3568_driver = { + .probe = clk_rk3568_probe, + .name = "clk-rk3568", + .of_compatible = DRV_OF_COMPAT(clk_rk3568_match_table), +}; + +core_platform_driver(clk_rk3568_driver); diff --git a/drivers/clk/rockchip/clk.c b/drivers/clk/rockchip/clk.c index 833e9bed0e..6e7bba414f 100644 --- a/drivers/clk/rockchip/clk.c +++ b/drivers/clk/rockchip/clk.c @@ -3,6 +3,9 @@ * Copyright (c) 2014 MundoReader S.L. * Author: Heiko Stuebner <heiko@sntech.de> * + * Copyright (c) 2016 Rockchip Electronics Co. Ltd. + * Author: Xing Zheng <zhengxing@rock-chips.com> + * * based on * * samsung/clk.c @@ -14,10 +17,14 @@ #include <common.h> #include <malloc.h> #include <linux/clk.h> +#include <regmap.h> +#include <mfd/syscon.h> +#include <linux/spinlock.h> +#include <linux/rational.h> +#include <restart.h> #include "clk.h" -#include <init.h> -/** +/* * Register a clock branch. * Most clock branches have a form like * @@ -28,134 +35,366 @@ * sometimes without one of those components. */ static struct clk *rockchip_clk_register_branch(const char *name, - const char **parent_names, u8 num_parents, void __iomem *base, + const char *const *parent_names, u8 num_parents, + void __iomem *base, int muxdiv_offset, u8 mux_shift, u8 mux_width, u8 mux_flags, - u8 div_shift, u8 div_width, u8 div_flags, + int div_offset, u8 div_shift, u8 div_width, u8 div_flags, struct clk_div_table *div_table, int gate_offset, - u8 gate_shift, u8 gate_flags, unsigned long flags - ) + u8 gate_shift, u8 gate_flags, unsigned long flags, + spinlock_t *lock) { struct clk *clk; - struct clk *mux = NULL; - struct clk *gate = NULL; - struct clk *div = NULL; + struct clk_mux *mux = NULL; + struct clk_gate *gate = NULL; + struct clk_divider *div = NULL; + int ret; if (num_parents > 1) { - mux = clk_mux_alloc(name, 0, base + muxdiv_offset, mux_shift, - mux_width, parent_names, num_parents, mux_flags); + mux = kzalloc(sizeof(*mux), GFP_KERNEL); if (!mux) return ERR_PTR(-ENOMEM); + + mux->reg = base + muxdiv_offset; + mux->shift = mux_shift; + mux->width = mux_width; + mux->flags = mux_flags; + mux->lock = lock; + mux->hw.clk.ops = (mux_flags & CLK_MUX_READ_ONLY) ? &clk_mux_ro_ops + : &clk_mux_ops; } if (gate_offset >= 0) { - gate = clk_gate_alloc(name, *parent_names, base + gate_offset, - gate_shift, flags, gate_flags); - if (!gate) - return ERR_PTR(-ENOMEM); + gate = kzalloc(sizeof(*gate), GFP_KERNEL); + if (!gate) { + ret = -ENOMEM; + goto err_gate; + } + + gate->flags = gate_flags; + gate->reg = base + gate_offset; + gate->shift = gate_shift; + gate->lock = lock; + gate->hw.clk.ops = &clk_gate_ops; } if (div_width > 0) { - div = clk_divider_alloc(name, *parent_names, 0, - base + muxdiv_offset, div_shift, div_width, div_flags); - if (!div) - return ERR_PTR(-ENOMEM); + div = kzalloc(sizeof(*div), GFP_KERNEL); + if (!div) { + ret = -ENOMEM; + goto err_div; + } + + div->flags = div_flags; + if (div_offset) + div->reg = base + div_offset; + else + div->reg = base + muxdiv_offset; + div->shift = div_shift; + div->width = div_width; + div->lock = lock; + div->table = div_table; + div->hw.clk.ops = (div_flags & CLK_DIVIDER_READ_ONLY) + ? &clk_divider_ro_ops + : &clk_divider_ops; } clk = clk_register_composite(name, parent_names, num_parents, - mux, - div, - gate, - flags); + mux ? &mux->hw.clk : NULL, + div ? &div->hw.clk : NULL, + gate ? &gate->hw.clk : NULL, + flags); + if (IS_ERR(clk)) { + kfree(div); + kfree(gate); + return ERR_CAST(clk); + } return clk; +err_div: + kfree(gate); +err_gate: + kfree(mux); + return ERR_PTR(ret); } -static struct clk *rockchip_clk_register_frac_branch(const char *name, - const char **parent_names, u8 num_parents, void __iomem *base, - int muxdiv_offset, u8 div_flags, +struct rockchip_clk_frac { + struct clk_fractional_divider div; + struct clk_gate gate; + + struct clk_mux mux; + const struct clk_ops *mux_ops; + int mux_frac_idx; + + bool rate_change_remuxed; + int rate_change_idx; +}; + +/* + * fractional divider must set that denominator is 20 times larger than + * numerator to generate precise clock frequency. + */ +static void rockchip_fractional_approximation(struct clk_hw *hw, + unsigned long rate, unsigned long *parent_rate, + unsigned long *m, unsigned long *n) +{ + struct clk_fractional_divider *fd = to_clk_fd(hw); + unsigned long p_rate, p_parent_rate; + struct clk_hw *p_parent; + unsigned long scale; + + p_rate = clk_hw_get_rate(clk_hw_get_parent(hw)); + if ((rate * 20 > p_rate) && (p_rate % rate != 0)) { + p_parent = clk_hw_get_parent(clk_hw_get_parent(hw)); + p_parent_rate = clk_hw_get_rate(p_parent); + *parent_rate = p_parent_rate; + } + + /* + * Get rate closer to *parent_rate to guarantee there is no overflow + * for m and n. In the result it will be the nearest rate left shifted + * by (scale - fd->nwidth) bits. + */ + scale = fls_long(*parent_rate / rate - 1); + if (scale > fd->nwidth) + rate <<= scale - fd->nwidth; + + rational_best_approximation(rate, *parent_rate, + GENMASK(fd->mwidth - 1, 0), GENMASK(fd->nwidth - 1, 0), + m, n); +} + +static struct clk *rockchip_clk_register_frac_branch( + struct rockchip_clk_provider *ctx, const char *name, + const char *const *parent_names, u8 num_parents, + void __iomem *base, int muxdiv_offset, u8 div_flags, int gate_offset, u8 gate_shift, u8 gate_flags, - unsigned long flags) + unsigned long flags, struct rockchip_clk_branch *child, + spinlock_t *lock) { struct clk *clk; - struct clk *gate = NULL; - struct clk *div = NULL; - - if (gate_offset >= 0) { - gate = clk_gate_alloc(name, *parent_names, base + gate_offset, - gate_shift, flags, gate_flags); - if (!gate) - return ERR_PTR(-ENOMEM); - } + struct rockchip_clk_frac *frac; + struct clk_gate *gate = NULL; + struct clk_fractional_divider *div = NULL; if (muxdiv_offset < 0) return ERR_PTR(-EINVAL); - div = clk_fractional_divider_alloc(name, *parent_names, flags, - base + muxdiv_offset, 16, 16, 0, 16, div_flags); - if (!div) + if (child && child->branch_type != branch_mux) { + pr_err("%s: fractional child clock for %s can only be a mux\n", + __func__, name); + return ERR_PTR(-EINVAL); + } + + frac = kzalloc(sizeof(*frac), GFP_KERNEL); + if (!frac) return ERR_PTR(-ENOMEM); + if (gate_offset >= 0) { + gate = &frac->gate; + gate->flags = gate_flags; + gate->reg = base + gate_offset; + gate->shift = gate_shift; + gate->lock = lock; + gate->hw.clk.ops = &clk_gate_ops; + } + + div = &frac->div; + div->flags = div_flags; + div->reg = base + muxdiv_offset; + div->mshift = 16; + div->mwidth = 16; + div->mmask = GENMASK(div->mwidth - 1, 0) << div->mshift; + div->nshift = 0; + div->nwidth = 16; + div->nmask = GENMASK(div->nwidth - 1, 0) << div->nshift; + div->lock = lock; + div->approximation = rockchip_fractional_approximation; + div->hw.clk.ops = &clk_fractional_divider_ops; + clk = clk_register_composite(name, parent_names, num_parents, - NULL, - div, - gate, - flags); + NULL, + &div->hw.clk, + gate ? &gate->hw.clk : NULL, + flags | CLK_SET_RATE_UNGATE); + if (IS_ERR(clk)) { + kfree(frac); + return ERR_CAST(clk); + } + + if (child) { + struct clk_mux *frac_mux = &frac->mux; + struct clk_init_data init; + struct clk *mux_clk; + + frac->mux_frac_idx = match_string(child->parent_names, + child->num_parents, name); + frac->mux_ops = &clk_mux_ops; + + frac_mux->reg = base + child->muxdiv_offset; + frac_mux->shift = child->mux_shift; + frac_mux->width = child->mux_width; + frac_mux->flags = child->mux_flags; + frac_mux->lock = lock; + frac_mux->hw.init = &init; + + init.name = child->name; + init.flags = child->flags | CLK_SET_RATE_PARENT; + init.ops = frac->mux_ops; + init.parent_names = child->parent_names; + init.num_parents = child->num_parents; + + mux_clk = clk_register(NULL, &frac_mux->hw); + if (IS_ERR(mux_clk)) { + kfree(frac); + return mux_clk; + } + + rockchip_clk_add_lookup(ctx, mux_clk, child->id); + + /* notifier on the fraction divider to catch rate changes */ + if (frac->mux_frac_idx >= 0) { + pr_debug("%s: found fractional parent in mux at pos %d\n", + __func__, frac->mux_frac_idx); + } else { + pr_warn("%s: could not find %s as parent of %s, rate changes may not work\n", + __func__, name, child->name); + } + } return clk; } -static struct clk **clk_table; -static void __iomem *reg_base; -static struct clk_onecell_data clk_data; -static struct device_node *cru_node; +static struct clk *rockchip_clk_register_factor_branch(const char *name, + const char *const *parent_names, u8 num_parents, + void __iomem *base, unsigned int mult, unsigned int div, + int gate_offset, u8 gate_shift, u8 gate_flags, + unsigned long flags, spinlock_t *lock) +{ + struct clk *clk; + struct clk_gate *gate = NULL; + struct clk_fixed_factor *fix = NULL; + + /* without gate, register a simple factor clock */ + if (gate_offset == 0) { + return clk_register_fixed_factor(NULL, name, + parent_names[0], flags, mult, + div); + } + + gate = kzalloc(sizeof(*gate), GFP_KERNEL); + if (!gate) + return ERR_PTR(-ENOMEM); + + gate->flags = gate_flags; + gate->reg = base + gate_offset; + gate->shift = gate_shift; + gate->lock = lock; + gate->hw.clk.ops = &clk_gate_ops; + + fix = kzalloc(sizeof(*fix), GFP_KERNEL); + if (!fix) { + kfree(gate); + return ERR_PTR(-ENOMEM); + } + + fix->mult = mult; + fix->div = div; + fix->hw.clk.ops = &clk_fixed_factor_ops; -void __init rockchip_clk_init(struct device_node *np, void __iomem *base, - unsigned long nr_clks) + clk = clk_register_composite(name, parent_names, num_parents, + NULL, + &fix->hw.clk, + &gate->hw.clk, flags); + if (IS_ERR(clk)) { + kfree(fix); + kfree(gate); + return ERR_CAST(clk); + } + + return clk; +} + +struct rockchip_clk_provider *rockchip_clk_init(struct device_node *np, + void __iomem *base, + unsigned long nr_clks) { - reg_base = base; - cru_node = np; + struct rockchip_clk_provider *ctx; + struct clk **clk_table; + int i; + + ctx = kzalloc(sizeof(struct rockchip_clk_provider), GFP_KERNEL); + if (!ctx) + return ERR_PTR(-ENOMEM); - clk_table = calloc(nr_clks, sizeof(struct clk *)); + clk_table = kcalloc(nr_clks, sizeof(struct clk *), GFP_KERNEL); if (!clk_table) - pr_err("%s: could not allocate clock lookup table\n", __func__); + goto err_free; + + for (i = 0; i < nr_clks; ++i) + clk_table[i] = ERR_PTR(-ENOENT); + + ctx->reg_base = base; + ctx->clk_data.clks = clk_table; + ctx->clk_data.clk_num = nr_clks; + ctx->cru_node = np; + spin_lock_init(&ctx->lock); - clk_data.clks = clk_table; - clk_data.clk_num = nr_clks; - of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data); + ctx->grf = syscon_regmap_lookup_by_phandle(ctx->cru_node, + "rockchip,grf"); + + return ctx; + +err_free: + kfree(ctx); + return ERR_PTR(-ENOMEM); +} +EXPORT_SYMBOL_GPL(rockchip_clk_init); + +void rockchip_clk_of_add_provider(struct device_node *np, + struct rockchip_clk_provider *ctx) +{ + if (of_clk_add_provider(np, of_clk_src_onecell_get, + &ctx->clk_data)) + pr_err("%s: could not register clk provider\n", __func__); } +EXPORT_SYMBOL_GPL(rockchip_clk_of_add_provider); -void rockchip_clk_add_lookup(struct clk *clk, unsigned int id) +void rockchip_clk_add_lookup(struct rockchip_clk_provider *ctx, + struct clk *clk, unsigned int id) { - if (clk_table && id) - clk_table[id] = clk; + if (ctx->clk_data.clks && id) + ctx->clk_data.clks[id] = clk; } +EXPORT_SYMBOL_GPL(rockchip_clk_add_lookup); -void __init rockchip_clk_register_plls(struct rockchip_pll_clock *list, +void rockchip_clk_register_plls(struct rockchip_clk_provider *ctx, + struct rockchip_pll_clock *list, unsigned int nr_pll, int grf_lock_offset) { struct clk *clk; int idx; for (idx = 0; idx < nr_pll; idx++, list++) { - clk = rockchip_clk_register_pll(list->type, list->name, + clk = rockchip_clk_register_pll(ctx, list->type, list->name, list->parent_names, list->num_parents, - reg_base, list->con_offset, grf_lock_offset, + list->con_offset, grf_lock_offset, list->lock_shift, list->mode_offset, list->mode_shift, list->rate_table, - list->pll_flags); + list->flags, list->pll_flags); if (IS_ERR(clk)) { pr_err("%s: failed to register clock %s\n", __func__, list->name); continue; } - rockchip_clk_add_lookup(clk, list->id); + rockchip_clk_add_lookup(ctx, clk, list->id); } } +EXPORT_SYMBOL_GPL(rockchip_clk_register_plls); -void __init rockchip_clk_register_branches( - struct rockchip_clk_branch *list, - unsigned int nr_clk) +void rockchip_clk_register_branches(struct rockchip_clk_provider *ctx, + struct rockchip_clk_branch *list, + unsigned int nr_clk) { struct clk *clk = NULL; unsigned int idx; @@ -167,50 +406,89 @@ void __init rockchip_clk_register_branches( /* catch simple muxes */ switch (list->branch_type) { case branch_mux: - clk = clk_mux(list->name, flags, - reg_base + list->muxdiv_offset, list->mux_shift, - list->mux_width, list->parent_names, - list->num_parents, list->mux_flags); + clk = clk_register_mux(NULL, list->name, + list->parent_names, list->num_parents, + flags, ctx->reg_base + list->muxdiv_offset, + list->mux_shift, list->mux_width, + list->mux_flags, &ctx->lock); + break; + case branch_muxgrf: + clk = rockchip_clk_register_muxgrf(list->name, + list->parent_names, list->num_parents, + flags, ctx->grf, list->muxdiv_offset, + list->mux_shift, list->mux_width, + list->mux_flags); break; case branch_divider: if (list->div_table) - clk = clk_divider_table(list->name, - list->parent_names[0], flags, - reg_base + list->muxdiv_offset, - list->div_shift, list->div_width, - list->div_table, list->div_flags); + clk = clk_register_divider_table(NULL, + list->name, list->parent_names[0], + flags, + ctx->reg_base + list->muxdiv_offset, + list->div_shift, list->div_width, + list->div_flags, list->div_table, + &ctx->lock); else - clk = clk_divider(list->name, - list->parent_names[0], flags, - reg_base + list->muxdiv_offset, - list->div_shift, list->div_width, - list->div_flags); + clk = clk_register_divider(NULL, list->name, + list->parent_names[0], flags, + ctx->reg_base + list->muxdiv_offset, + list->div_shift, list->div_width, + list->div_flags, &ctx->lock); break; case branch_fraction_divider: - clk = rockchip_clk_register_frac_branch(list->name, + clk = rockchip_clk_register_frac_branch(ctx, list->name, list->parent_names, list->num_parents, - reg_base, list->muxdiv_offset, list->div_flags, + ctx->reg_base, list->muxdiv_offset, + list->div_flags, list->gate_offset, list->gate_shift, - list->gate_flags, flags); + list->gate_flags, flags, list->child, + &ctx->lock); + break; + case branch_half_divider: break; case branch_gate: flags |= CLK_SET_RATE_PARENT; - clk = clk_gate(list->name, list->parent_names[0], - reg_base + list->gate_offset, list->gate_shift, - flags, list->gate_flags); + clk = clk_register_gate(NULL, list->name, + list->parent_names[0], flags, + ctx->reg_base + list->gate_offset, + list->gate_shift, list->gate_flags, &ctx->lock); break; case branch_composite: clk = rockchip_clk_register_branch(list->name, list->parent_names, list->num_parents, - reg_base, list->muxdiv_offset, list->mux_shift, + ctx->reg_base, list->muxdiv_offset, + list->mux_shift, list->mux_width, list->mux_flags, - list->div_shift, list->div_width, + list->div_offset, list->div_shift, list->div_width, list->div_flags, list->div_table, list->gate_offset, list->gate_shift, - list->gate_flags, flags); + list->gate_flags, flags, &ctx->lock); break; case branch_mmc: + clk = rockchip_clk_register_mmc( + list->name, + list->parent_names, list->num_parents, + ctx->reg_base + list->muxdiv_offset, + list->div_shift + ); + break; + case branch_inverter: + clk = rockchip_clk_register_inverter( + list->name, list->parent_names, + list->num_parents, + ctx->reg_base + list->muxdiv_offset, + list->div_shift, list->div_flags, &ctx->lock); + break; + case branch_factor: + clk = rockchip_clk_register_factor_branch( + list->name, list->parent_names, + list->num_parents, ctx->reg_base, + list->div_shift, list->div_width, + list->gate_offset, list->gate_shift, + list->gate_flags, flags, &ctx->lock); + break; + case branch_ddrclk: break; } @@ -227,32 +505,36 @@ void __init rockchip_clk_register_branches( continue; } - rockchip_clk_add_lookup(clk, list->id); + rockchip_clk_add_lookup(ctx, clk, list->id); } } - -void __init rockchip_clk_register_armclk(unsigned int lookup_id, - const char *name, const char **parent_names, - u8 num_parents, - const struct rockchip_cpuclk_reg_data *reg_data, - const struct rockchip_cpuclk_rate_table *rates, - int nrates) +EXPORT_SYMBOL_GPL(rockchip_clk_register_branches); + +void rockchip_clk_register_armclk(struct rockchip_clk_provider *ctx, + unsigned int lookup_id, + const char *name, const char *const *parent_names, + u8 num_parents, + const struct rockchip_cpuclk_reg_data *reg_data, + const struct rockchip_cpuclk_rate_table *rates, + int nrates) { struct clk *clk; clk = rockchip_clk_register_cpuclk(name, parent_names, num_parents, - reg_data, rates, nrates, reg_base - ); + reg_data, rates, nrates, + ctx->reg_base, &ctx->lock); if (IS_ERR(clk)) { pr_err("%s: failed to register clock %s: %ld\n", __func__, name, PTR_ERR(clk)); return; } - rockchip_clk_add_lookup(clk, lookup_id); + rockchip_clk_add_lookup(ctx, clk, lookup_id); } +EXPORT_SYMBOL_GPL(rockchip_clk_register_armclk); -void __init rockchip_clk_protect_critical(const char *clocks[], int nclocks) +void rockchip_clk_protect_critical(const char *const clocks[], + int nclocks) { int i; @@ -260,7 +542,34 @@ void __init rockchip_clk_protect_critical(const char *clocks[], int nclocks) for (i = 0; i < nclocks; i++) { struct clk *clk = __clk_lookup(clocks[i]); - if (clk) - clk_enable(clk); + clk_enable(clk); } } +EXPORT_SYMBOL_GPL(rockchip_clk_protect_critical); + +static void rockchip_restart(struct restart_handler *this) +{ + struct rockchip_clk_provider *ctx = + container_of(this, struct rockchip_clk_provider, restart_handler); + + writel(0xfdb9, ctx->reg_base + ctx->reg_restart); + mdelay(1000); +} + +void rockchip_register_restart_notifier(struct rockchip_clk_provider *ctx, + unsigned int reg) +{ + int ret; + + ctx->restart_handler.name = "rockchip-pmu", + ctx->restart_handler.restart = rockchip_restart, + ctx->restart_handler.priority = RESTART_DEFAULT_PRIORITY, + + ctx->reg_restart = reg; + + ret = restart_handler_register(&ctx->restart_handler); + if (ret) + pr_err("%s: cannot register restart handler, %d\n", + __func__, ret); +} +EXPORT_SYMBOL_GPL(rockchip_register_restart_notifier); diff --git a/drivers/clk/rockchip/clk.h b/drivers/clk/rockchip/clk.h index 006225b7e8..a3db88dfc8 100644 --- a/drivers/clk/rockchip/clk.h +++ b/drivers/clk/rockchip/clk.h @@ -3,6 +3,9 @@ * Copyright (c) 2014 MundoReader S.L. * Author: Heiko Stuebner <heiko@sntech.de> * + * Copyright (c) 2015 Rockchip Electronics Co. Ltd. + * Author: Xing Zheng <zhengxing@rock-chips.com> + * * based on * * samsung/clk.h @@ -16,31 +19,97 @@ #include <io.h> #include <linux/clk.h> - -/* To keep changes from kernel smaller */ -#define CLK_GATE_SET_TO_DISABLE CLK_GATE_INVERTED -#define CLK_GET_RATE_NOCACHE 0 +#include <restart.h> #define HIWORD_UPDATE(val, mask, shift) \ ((val) << (shift) | (mask) << ((shift) + 16)) -/* register positions shared by RK2928, RK3066 and RK3188 */ -#define RK2928_PLL_CON(x) (x * 0x4) +/* register positions shared by PX30, RV1108, RK2928, RK3036, RK3066, RK3188 and RK3228 */ +#define BOOST_PLL_H_CON(x) ((x) * 0x4) +#define BOOST_CLK_CON 0x0008 +#define BOOST_BOOST_CON 0x000c +#define BOOST_SWITCH_CNT 0x0010 +#define BOOST_HIGH_PERF_CNT0 0x0014 +#define BOOST_HIGH_PERF_CNT1 0x0018 +#define BOOST_STATIS_THRESHOLD 0x001c +#define BOOST_SHORT_SWITCH_CNT 0x0020 +#define BOOST_SWITCH_THRESHOLD 0x0024 +#define BOOST_FSM_STATUS 0x0028 +#define BOOST_PLL_L_CON(x) ((x) * 0x4 + 0x2c) +#define BOOST_RECOVERY_MASK 0x1 +#define BOOST_RECOVERY_SHIFT 1 +#define BOOST_SW_CTRL_MASK 0x1 +#define BOOST_SW_CTRL_SHIFT 2 +#define BOOST_LOW_FREQ_EN_MASK 0x1 +#define BOOST_LOW_FREQ_EN_SHIFT 3 +#define BOOST_BUSY_STATE BIT(8) + +#define PX30_PLL_CON(x) ((x) * 0x4) +#define PX30_CLKSEL_CON(x) ((x) * 0x4 + 0x100) +#define PX30_CLKGATE_CON(x) ((x) * 0x4 + 0x200) +#define PX30_GLB_SRST_FST 0xb8 +#define PX30_GLB_SRST_SND 0xbc +#define PX30_SOFTRST_CON(x) ((x) * 0x4 + 0x300) +#define PX30_MODE_CON 0xa0 +#define PX30_MISC_CON 0xa4 +#define PX30_SDMMC_CON0 0x380 +#define PX30_SDMMC_CON1 0x384 +#define PX30_SDIO_CON0 0x388 +#define PX30_SDIO_CON1 0x38c +#define PX30_EMMC_CON0 0x390 +#define PX30_EMMC_CON1 0x394 + +#define PX30_PMU_PLL_CON(x) ((x) * 0x4) +#define PX30_PMU_CLKSEL_CON(x) ((x) * 0x4 + 0x40) +#define PX30_PMU_CLKGATE_CON(x) ((x) * 0x4 + 0x80) +#define PX30_PMU_MODE 0x0020 + +#define RV1108_PLL_CON(x) ((x) * 0x4) +#define RV1108_CLKSEL_CON(x) ((x) * 0x4 + 0x60) +#define RV1108_CLKGATE_CON(x) ((x) * 0x4 + 0x120) +#define RV1108_SOFTRST_CON(x) ((x) * 0x4 + 0x180) +#define RV1108_GLB_SRST_FST 0x1c0 +#define RV1108_GLB_SRST_SND 0x1c4 +#define RV1108_MISC_CON 0x1cc +#define RV1108_SDMMC_CON0 0x1d8 +#define RV1108_SDMMC_CON1 0x1dc +#define RV1108_SDIO_CON0 0x1e0 +#define RV1108_SDIO_CON1 0x1e4 +#define RV1108_EMMC_CON0 0x1e8 +#define RV1108_EMMC_CON1 0x1ec + +#define RK2928_PLL_CON(x) ((x) * 0x4) #define RK2928_MODE_CON 0x40 -#define RK2928_CLKSEL_CON(x) (x * 0x4 + 0x44) -#define RK2928_CLKGATE_CON(x) (x * 0x4 + 0xd0) +#define RK2928_CLKSEL_CON(x) ((x) * 0x4 + 0x44) +#define RK2928_CLKGATE_CON(x) ((x) * 0x4 + 0xd0) #define RK2928_GLB_SRST_FST 0x100 #define RK2928_GLB_SRST_SND 0x104 -#define RK2928_SOFTRST_CON(x) (x * 0x4 + 0x110) +#define RK2928_SOFTRST_CON(x) ((x) * 0x4 + 0x110) #define RK2928_MISC_CON 0x134 +#define RK3036_SDMMC_CON0 0x144 +#define RK3036_SDMMC_CON1 0x148 +#define RK3036_SDIO_CON0 0x14c +#define RK3036_SDIO_CON1 0x150 +#define RK3036_EMMC_CON0 0x154 +#define RK3036_EMMC_CON1 0x158 + +#define RK3228_GLB_SRST_FST 0x1f0 +#define RK3228_GLB_SRST_SND 0x1f4 +#define RK3228_SDMMC_CON0 0x1c0 +#define RK3228_SDMMC_CON1 0x1c4 +#define RK3228_SDIO_CON0 0x1c8 +#define RK3228_SDIO_CON1 0x1cc +#define RK3228_EMMC_CON0 0x1d8 +#define RK3228_EMMC_CON1 0x1dc + #define RK3288_PLL_CON(x) RK2928_PLL_CON(x) #define RK3288_MODE_CON 0x50 -#define RK3288_CLKSEL_CON(x) (x * 0x4 + 0x60) -#define RK3288_CLKGATE_CON(x) (x * 0x4 + 0x160) +#define RK3288_CLKSEL_CON(x) ((x) * 0x4 + 0x60) +#define RK3288_CLKGATE_CON(x) ((x) * 0x4 + 0x160) #define RK3288_GLB_SRST_FST 0x1b0 #define RK3288_GLB_SRST_SND 0x1b4 -#define RK3288_SOFTRST_CON(x) (x * 0x4 + 0x1b8) +#define RK3288_SOFTRST_CON(x) ((x) * 0x4 + 0x1b8) #define RK3288_MISC_CON 0x1e8 #define RK3288_SDMMC_CON0 0x200 #define RK3288_SDMMC_CON1 0x204 @@ -51,41 +120,177 @@ #define RK3288_EMMC_CON0 0x218 #define RK3288_EMMC_CON1 0x21c +#define RK3308_PLL_CON(x) RK2928_PLL_CON(x) +#define RK3308_CLKSEL_CON(x) ((x) * 0x4 + 0x100) +#define RK3308_CLKGATE_CON(x) ((x) * 0x4 + 0x300) +#define RK3308_GLB_SRST_FST 0xb8 +#define RK3308_SOFTRST_CON(x) ((x) * 0x4 + 0x400) +#define RK3308_MODE_CON 0xa0 +#define RK3308_SDMMC_CON0 0x480 +#define RK3308_SDMMC_CON1 0x484 +#define RK3308_SDIO_CON0 0x488 +#define RK3308_SDIO_CON1 0x48c +#define RK3308_EMMC_CON0 0x490 +#define RK3308_EMMC_CON1 0x494 + +#define RK3328_PLL_CON(x) RK2928_PLL_CON(x) +#define RK3328_CLKSEL_CON(x) ((x) * 0x4 + 0x100) +#define RK3328_CLKGATE_CON(x) ((x) * 0x4 + 0x200) +#define RK3328_GRFCLKSEL_CON(x) ((x) * 0x4 + 0x100) +#define RK3328_GLB_SRST_FST 0x9c +#define RK3328_GLB_SRST_SND 0x98 +#define RK3328_SOFTRST_CON(x) ((x) * 0x4 + 0x300) +#define RK3328_MODE_CON 0x80 +#define RK3328_MISC_CON 0x84 +#define RK3328_SDMMC_CON0 0x380 +#define RK3328_SDMMC_CON1 0x384 +#define RK3328_SDIO_CON0 0x388 +#define RK3328_SDIO_CON1 0x38c +#define RK3328_EMMC_CON0 0x390 +#define RK3328_EMMC_CON1 0x394 +#define RK3328_SDMMC_EXT_CON0 0x398 +#define RK3328_SDMMC_EXT_CON1 0x39C + +#define RK3368_PLL_CON(x) RK2928_PLL_CON(x) +#define RK3368_CLKSEL_CON(x) ((x) * 0x4 + 0x100) +#define RK3368_CLKGATE_CON(x) ((x) * 0x4 + 0x200) +#define RK3368_GLB_SRST_FST 0x280 +#define RK3368_GLB_SRST_SND 0x284 +#define RK3368_SOFTRST_CON(x) ((x) * 0x4 + 0x300) +#define RK3368_MISC_CON 0x380 +#define RK3368_SDMMC_CON0 0x400 +#define RK3368_SDMMC_CON1 0x404 +#define RK3368_SDIO0_CON0 0x408 +#define RK3368_SDIO0_CON1 0x40c +#define RK3368_SDIO1_CON0 0x410 +#define RK3368_SDIO1_CON1 0x414 +#define RK3368_EMMC_CON0 0x418 +#define RK3368_EMMC_CON1 0x41c + +#define RK3399_PLL_CON(x) RK2928_PLL_CON(x) +#define RK3399_CLKSEL_CON(x) ((x) * 0x4 + 0x100) +#define RK3399_CLKGATE_CON(x) ((x) * 0x4 + 0x300) +#define RK3399_SOFTRST_CON(x) ((x) * 0x4 + 0x400) +#define RK3399_GLB_SRST_FST 0x500 +#define RK3399_GLB_SRST_SND 0x504 +#define RK3399_GLB_CNT_TH 0x508 +#define RK3399_MISC_CON 0x50c +#define RK3399_RST_CON 0x510 +#define RK3399_RST_ST 0x514 +#define RK3399_SDMMC_CON0 0x580 +#define RK3399_SDMMC_CON1 0x584 +#define RK3399_SDIO_CON0 0x588 +#define RK3399_SDIO_CON1 0x58c + +#define RK3399_PMU_PLL_CON(x) RK2928_PLL_CON(x) +#define RK3399_PMU_CLKSEL_CON(x) ((x) * 0x4 + 0x80) +#define RK3399_PMU_CLKGATE_CON(x) ((x) * 0x4 + 0x100) +#define RK3399_PMU_SOFTRST_CON(x) ((x) * 0x4 + 0x110) + +#define RK3568_PLL_CON(x) RK2928_PLL_CON(x) +#define RK3568_MODE_CON0 0xc0 +#define RK3568_MISC_CON0 0xc4 +#define RK3568_MISC_CON1 0xc8 +#define RK3568_MISC_CON2 0xcc +#define RK3568_GLB_CNT_TH 0xd0 +#define RK3568_GLB_SRST_FST 0xd4 +#define RK3568_GLB_SRST_SND 0xd8 +#define RK3568_GLB_RST_CON 0xdc +#define RK3568_GLB_RST_ST 0xe0 +#define RK3568_CLKSEL_CON(x) ((x) * 0x4 + 0x100) +#define RK3568_CLKGATE_CON(x) ((x) * 0x4 + 0x300) +#define RK3568_SOFTRST_CON(x) ((x) * 0x4 + 0x400) +#define RK3568_SDMMC0_CON0 0x580 +#define RK3568_SDMMC0_CON1 0x584 +#define RK3568_SDMMC1_CON0 0x588 +#define RK3568_SDMMC1_CON1 0x58c +#define RK3568_SDMMC2_CON0 0x590 +#define RK3568_SDMMC2_CON1 0x594 +#define RK3568_EMMC_CON0 0x598 +#define RK3568_EMMC_CON1 0x59c + +#define RK3568_PMU_PLL_CON(x) RK2928_PLL_CON(x) +#define RK3568_PMU_MODE_CON0 0x80 +#define RK3568_PMU_CLKSEL_CON(x) ((x) * 0x4 + 0x100) +#define RK3568_PMU_CLKGATE_CON(x) ((x) * 0x4 + 0x180) +#define RK3568_PMU_SOFTRST_CON(x) ((x) * 0x4 + 0x200) + enum rockchip_pll_type { + pll_rk3036, pll_rk3066, + pll_rk3328, + pll_rk3399, }; +#define RK3036_PLL_RATE(_rate, _refdiv, _fbdiv, _postdiv1, \ + _postdiv2, _dsmpd, _frac) \ +{ \ + .rate = _rate##U, \ + .fbdiv = _fbdiv, \ + .postdiv1 = _postdiv1, \ + .refdiv = _refdiv, \ + .postdiv2 = _postdiv2, \ + .dsmpd = _dsmpd, \ + .frac = _frac, \ +} + #define RK3066_PLL_RATE(_rate, _nr, _nf, _no) \ { \ .rate = _rate##U, \ .nr = _nr, \ .nf = _nf, \ .no = _no, \ - .bwadj = (_nf >> 1), \ + .nb = ((_nf) < 2) ? 1 : (_nf) >> 1, \ } -#define RK3066_PLL_RATE_BWADJ(_rate, _nr, _nf, _no, _bw) \ +#define RK3066_PLL_RATE_NB(_rate, _nr, _nf, _no, _nb) \ { \ .rate = _rate##U, \ .nr = _nr, \ .nf = _nf, \ .no = _no, \ - .bwadj = _bw, \ + .nb = _nb, \ } +/** + * struct rockchip_clk_provider - information about clock provider + * @reg_base: virtual address for the register base. + * @clk_data: holds clock related data like clk* and number of clocks. + * @cru_node: device-node of the clock-provider + * @grf: regmap of the general-register-files syscon + * @lock: maintains exclusion between callbacks for a given clock-provider. + */ +struct rockchip_clk_provider { + void __iomem *reg_base; + struct clk_onecell_data clk_data; + struct device_node *cru_node; + struct regmap *grf; + struct restart_handler restart_handler; + unsigned int reg_restart; + spinlock_t lock; +}; + struct rockchip_pll_rate_table { unsigned long rate; unsigned int nr; unsigned int nf; unsigned int no; - unsigned int bwadj; + unsigned int nb; + /* for RK3036/RK3399 */ + unsigned int fbdiv; + unsigned int postdiv1; + unsigned int refdiv; + unsigned int postdiv2; + unsigned int dsmpd; + unsigned int frac; }; /** - * struct rockchip_pll_clock: information about pll clock + * struct rockchip_pll_clock - information about pll clock * @id: platform specific id of the clock. * @name: name of this pll clock. - * @parent_name: name of the parent clock. + * @parent_names: name of the parent clock. + * @num_parents: number of parents * @flags: optional flags for basic clock. * @con_offset: offset of the register for configuring the PLL. * @mode_offset: offset of the register for configuring the PLL-mode. @@ -102,7 +307,7 @@ struct rockchip_pll_rate_table { struct rockchip_pll_clock { unsigned int id; const char *name; - const char **parent_names; + const char *const *parent_names; u8 num_parents; unsigned long flags; int con_offset; @@ -133,71 +338,111 @@ struct rockchip_pll_clock { .rate_table = _rtable, \ } -struct clk *rockchip_clk_register_pll(enum rockchip_pll_type pll_type, - const char *name, const char **parent_names, u8 num_parents, - void __iomem *base, int con_offset, int grf_lock_offset, - int lock_shift, int reg_mode, int mode_shift, +struct clk *rockchip_clk_register_pll(struct rockchip_clk_provider *ctx, + enum rockchip_pll_type pll_type, + const char *name, const char *const *parent_names, + u8 num_parents, int con_offset, int grf_lock_offset, + int lock_shift, int mode_offset, int mode_shift, struct rockchip_pll_rate_table *rate_table, - u8 clk_pll_flags); + unsigned long flags, u8 clk_pll_flags); struct rockchip_cpuclk_clksel { int reg; u32 val; }; -#define ROCKCHIP_CPUCLK_NUM_DIVIDERS 2 +#define ROCKCHIP_CPUCLK_NUM_DIVIDERS 5 +#define ROCKCHIP_CPUCLK_MAX_CORES 4 struct rockchip_cpuclk_rate_table { unsigned long prate; struct rockchip_cpuclk_clksel divs[ROCKCHIP_CPUCLK_NUM_DIVIDERS]; }; /** - * struct rockchip_cpuclk_reg_data: describes register offsets and masks of the cpuclock - * @core_reg: register offset of the core settings register - * @div_core_shift: core divider offset used to divide the pll value - * @div_core_mask: core divider mask + * struct rockchip_cpuclk_reg_data - register offsets and masks of the cpuclock + * @core_reg[]: register offset of the cores setting register + * @div_core_shift[]: cores divider offset used to divide the pll value + * @div_core_mask[]: cores divider mask + * @num_cores: number of cpu cores + * @mux_core_main: mux value to select main parent of core * @mux_core_shift: offset of the core multiplexer + * @mux_core_mask: core multiplexer mask */ struct rockchip_cpuclk_reg_data { - int core_reg; - u8 div_core_shift; - u32 div_core_mask; - int mux_core_reg; - u8 mux_core_shift; + int core_reg[ROCKCHIP_CPUCLK_MAX_CORES]; + u8 div_core_shift[ROCKCHIP_CPUCLK_MAX_CORES]; + u32 div_core_mask[ROCKCHIP_CPUCLK_MAX_CORES]; + int num_cores; + u8 mux_core_alt; + u8 mux_core_main; + u8 mux_core_shift; + u32 mux_core_mask; }; struct clk *rockchip_clk_register_cpuclk(const char *name, - const char **parent_names, u8 num_parents, + const char *const *parent_names, u8 num_parents, const struct rockchip_cpuclk_reg_data *reg_data, const struct rockchip_cpuclk_rate_table *rates, - int nrates, void __iomem *reg_base); + int nrates, void __iomem *reg_base, spinlock_t *lock); struct clk *rockchip_clk_register_mmc(const char *name, - const char **parent_names, u8 num_parents, + const char *const *parent_names, u8 num_parents, void __iomem *reg, int shift); -#define PNAME(x) static const char *x[] __initconst +/* + * DDRCLK flags, including method of setting the rate + * ROCKCHIP_DDRCLK_SIP: use SIP call to bl31 to change ddrclk rate. + */ +#define ROCKCHIP_DDRCLK_SIP BIT(0) + +struct clk *rockchip_clk_register_ddrclk(const char *name, int flags, + const char *const *parent_names, + u8 num_parents, int mux_offset, + int mux_shift, int mux_width, + int div_shift, int div_width, + int ddr_flags, void __iomem *reg_base, + spinlock_t *lock); + +#define ROCKCHIP_INVERTER_HIWORD_MASK BIT(0) + +struct clk *rockchip_clk_register_inverter(const char *name, + const char *const *parent_names, u8 num_parents, + void __iomem *reg, int shift, int flags, + spinlock_t *lock); + +struct clk *rockchip_clk_register_muxgrf(const char *name, + const char *const *parent_names, u8 num_parents, + int flags, struct regmap *grf, int reg, + int shift, int width, int mux_flags); + +#define PNAME(x) static const char *const x[] __initconst enum rockchip_clk_branch_type { branch_composite, branch_mux, + branch_muxgrf, branch_divider, branch_fraction_divider, branch_gate, branch_mmc, + branch_inverter, + branch_factor, + branch_ddrclk, + branch_half_divider, }; struct rockchip_clk_branch { unsigned int id; enum rockchip_clk_branch_type branch_type; const char *name; - const char **parent_names; + const char *const *parent_names; u8 num_parents; unsigned long flags; int muxdiv_offset; u8 mux_shift; u8 mux_width; u8 mux_flags; + int div_offset; u8 div_shift; u8 div_width; u8 div_flags; @@ -205,6 +450,7 @@ struct rockchip_clk_branch { int gate_offset; u8 gate_shift; u8 gate_flags; + struct rockchip_clk_branch *child; }; #define COMPOSITE(_id, cname, pnames, f, mo, ms, mw, mf, ds, dw,\ @@ -228,6 +474,28 @@ struct rockchip_clk_branch { .gate_flags = gf, \ } +#define COMPOSITE_DIV_OFFSET(_id, cname, pnames, f, mo, ms, mw, \ + mf, do, ds, dw, df, go, gs, gf) \ + { \ + .id = _id, \ + .branch_type = branch_composite, \ + .name = cname, \ + .parent_names = pnames, \ + .num_parents = ARRAY_SIZE(pnames), \ + .flags = f, \ + .muxdiv_offset = mo, \ + .mux_shift = ms, \ + .mux_width = mw, \ + .mux_flags = mf, \ + .div_offset = do, \ + .div_shift = ds, \ + .div_width = dw, \ + .div_flags = df, \ + .gate_offset = go, \ + .gate_shift = gs, \ + .gate_flags = gf, \ + } + #define COMPOSITE_NOMUX(_id, cname, pname, f, mo, ds, dw, df, \ go, gs, gf) \ { \ @@ -302,6 +570,26 @@ struct rockchip_clk_branch { .gate_offset = -1, \ } +#define COMPOSITE_NOGATE_DIVTBL(_id, cname, pnames, f, mo, ms, \ + mw, mf, ds, dw, df, dt) \ + { \ + .id = _id, \ + .branch_type = branch_composite, \ + .name = cname, \ + .parent_names = pnames, \ + .num_parents = ARRAY_SIZE(pnames), \ + .flags = f, \ + .muxdiv_offset = mo, \ + .mux_shift = ms, \ + .mux_width = mw, \ + .mux_flags = mf, \ + .div_shift = ds, \ + .div_width = dw, \ + .div_flags = df, \ + .div_table = dt, \ + .gate_offset = -1, \ + } + #define COMPOSITE_FRAC(_id, cname, pname, f, mo, df, go, gs, gf)\ { \ .id = _id, \ @@ -319,6 +607,58 @@ struct rockchip_clk_branch { .gate_flags = gf, \ } +#define COMPOSITE_FRACMUX(_id, cname, pname, f, mo, df, go, gs, gf, ch) \ + { \ + .id = _id, \ + .branch_type = branch_fraction_divider, \ + .name = cname, \ + .parent_names = (const char *[]){ pname }, \ + .num_parents = 1, \ + .flags = f, \ + .muxdiv_offset = mo, \ + .div_shift = 16, \ + .div_width = 16, \ + .div_flags = df, \ + .gate_offset = go, \ + .gate_shift = gs, \ + .gate_flags = gf, \ + .child = ch, \ + } + +#define COMPOSITE_FRACMUX_NOGATE(_id, cname, pname, f, mo, df, ch) \ + { \ + .id = _id, \ + .branch_type = branch_fraction_divider, \ + .name = cname, \ + .parent_names = (const char *[]){ pname }, \ + .num_parents = 1, \ + .flags = f, \ + .muxdiv_offset = mo, \ + .div_shift = 16, \ + .div_width = 16, \ + .div_flags = df, \ + .gate_offset = -1, \ + .child = ch, \ + } + +#define COMPOSITE_DDRCLK(_id, cname, pnames, f, mo, ms, mw, \ + ds, dw, df) \ + { \ + .id = _id, \ + .branch_type = branch_ddrclk, \ + .name = cname, \ + .parent_names = pnames, \ + .num_parents = ARRAY_SIZE(pnames), \ + .flags = f, \ + .muxdiv_offset = mo, \ + .mux_shift = ms, \ + .mux_width = mw, \ + .div_shift = ds, \ + .div_width = dw, \ + .div_flags = df, \ + .gate_offset = -1, \ + } + #define MUX(_id, cname, pnames, f, o, s, w, mf) \ { \ .id = _id, \ @@ -334,6 +674,21 @@ struct rockchip_clk_branch { .gate_offset = -1, \ } +#define MUXGRF(_id, cname, pnames, f, o, s, w, mf) \ + { \ + .id = _id, \ + .branch_type = branch_muxgrf, \ + .name = cname, \ + .parent_names = pnames, \ + .num_parents = ARRAY_SIZE(pnames), \ + .flags = f, \ + .muxdiv_offset = o, \ + .mux_shift = s, \ + .mux_width = w, \ + .mux_flags = mf, \ + .gate_offset = -1, \ + } + #define DIV(_id, cname, pname, f, o, s, w, df) \ { \ .id = _id, \ @@ -388,19 +743,83 @@ struct rockchip_clk_branch { .div_shift = shift, \ } -void rockchip_clk_init(struct device_node *np, void __iomem *base, - unsigned long nr_clks); -struct regmap *rockchip_clk_get_grf(void); -void rockchip_clk_add_lookup(struct clk *clk, unsigned int id); -void rockchip_clk_register_branches(struct rockchip_clk_branch *clk_list, +#define INVERTER(_id, cname, pname, io, is, if) \ + { \ + .id = _id, \ + .branch_type = branch_inverter, \ + .name = cname, \ + .parent_names = (const char *[]){ pname }, \ + .num_parents = 1, \ + .muxdiv_offset = io, \ + .div_shift = is, \ + .div_flags = if, \ + } + +#define FACTOR(_id, cname, pname, f, fm, fd) \ + { \ + .id = _id, \ + .branch_type = branch_factor, \ + .name = cname, \ + .parent_names = (const char *[]){ pname }, \ + .num_parents = 1, \ + .flags = f, \ + .div_shift = fm, \ + .div_width = fd, \ + } + +#define FACTOR_GATE(_id, cname, pname, f, fm, fd, go, gb, gf) \ + { \ + .id = _id, \ + .branch_type = branch_factor, \ + .name = cname, \ + .parent_names = (const char *[]){ pname }, \ + .num_parents = 1, \ + .flags = f, \ + .div_shift = fm, \ + .div_width = fd, \ + .gate_offset = go, \ + .gate_shift = gb, \ + .gate_flags = gf, \ + } + +/* SGRF clocks are only accessible from secure mode, so not controllable */ +#define SGRF_GATE(_id, cname, pname) \ + FACTOR(_id, cname, pname, 0, 1, 1) + +struct rockchip_clk_provider *rockchip_clk_init(struct device_node *np, + void __iomem *base, unsigned long nr_clks); +void rockchip_clk_of_add_provider(struct device_node *np, + struct rockchip_clk_provider *ctx); +void rockchip_clk_add_lookup(struct rockchip_clk_provider *ctx, + struct clk *clk, unsigned int id); +void rockchip_clk_register_branches(struct rockchip_clk_provider *ctx, + struct rockchip_clk_branch *list, unsigned int nr_clk); -void rockchip_clk_register_plls(struct rockchip_pll_clock *pll_list, +void rockchip_clk_register_plls(struct rockchip_clk_provider *ctx, + struct rockchip_pll_clock *pll_list, unsigned int nr_pll, int grf_lock_offset); -void rockchip_clk_register_armclk(unsigned int lookup_id, const char *name, - const char **parent_names, u8 num_parents, +void rockchip_clk_register_armclk(struct rockchip_clk_provider *ctx, + unsigned int lookup_id, const char *name, + const char *const *parent_names, u8 num_parents, const struct rockchip_cpuclk_reg_data *reg_data, const struct rockchip_cpuclk_rate_table *rates, int nrates); -void rockchip_clk_protect_critical(const char *clocks[], int nclocks); +void rockchip_clk_protect_critical(const char *const clocks[], int nclocks); +void rockchip_register_restart_notifier(struct rockchip_clk_provider *ctx, + unsigned int reg); + +#ifdef CONFIG_RESET_CONTROLLER +void rockchip_register_softrst(struct device_node *np, + unsigned int num_regs, + void __iomem *base, u8 flags); +#else +static inline void rockchip_register_softrst(struct device_node *np, + unsigned int num_regs, + void __iomem *base, u8 flags) +{ +} +#endif + +#define ROCKCHIP_SOFTRST_HIWORD_MASK BIT(0) #endif diff --git a/drivers/clk/rockchip/softrst.c b/drivers/clk/rockchip/softrst.c new file mode 100644 index 0000000000..e3f3937ca0 --- /dev/null +++ b/drivers/clk/rockchip/softrst.c @@ -0,0 +1,110 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (c) 2014 MundoReader S.L. + * Author: Heiko Stuebner <heiko@sntech.de> + */ + +#include <common.h> +#include <io.h> +#include <linux/bitops.h> +#include <linux/reset-controller.h> +#include <linux/spinlock.h> +#include "clk.h" + +struct rockchip_softrst { + struct reset_controller_dev rcdev; + void __iomem *reg_base; + int num_regs; + int num_per_reg; + u8 flags; + spinlock_t lock; +}; + +static int rockchip_softrst_assert(struct reset_controller_dev *rcdev, + unsigned long id) +{ + struct rockchip_softrst *softrst = container_of(rcdev, + struct rockchip_softrst, + rcdev); + int bank = id / softrst->num_per_reg; + int offset = id % softrst->num_per_reg; + + if (softrst->flags & ROCKCHIP_SOFTRST_HIWORD_MASK) { + writel(BIT(offset) | (BIT(offset) << 16), + softrst->reg_base + (bank * 4)); + } else { + unsigned long flags; + u32 reg; + + spin_lock_irqsave(&softrst->lock, flags); + + reg = readl(softrst->reg_base + (bank * 4)); + writel(reg | BIT(offset), softrst->reg_base + (bank * 4)); + + spin_unlock_irqrestore(&softrst->lock, flags); + } + + return 0; +} + +static int rockchip_softrst_deassert(struct reset_controller_dev *rcdev, + unsigned long id) +{ + struct rockchip_softrst *softrst = container_of(rcdev, + struct rockchip_softrst, + rcdev); + int bank = id / softrst->num_per_reg; + int offset = id % softrst->num_per_reg; + + if (softrst->flags & ROCKCHIP_SOFTRST_HIWORD_MASK) { + writel((BIT(offset) << 16), softrst->reg_base + (bank * 4)); + } else { + unsigned long flags; + u32 reg; + + spin_lock_irqsave(&softrst->lock, flags); + + reg = readl(softrst->reg_base + (bank * 4)); + writel(reg & ~BIT(offset), softrst->reg_base + (bank * 4)); + + spin_unlock_irqrestore(&softrst->lock, flags); + } + + return 0; +} + +static const struct reset_control_ops rockchip_softrst_ops = { + .assert = rockchip_softrst_assert, + .deassert = rockchip_softrst_deassert, +}; + +void rockchip_register_softrst(struct device_node *np, + unsigned int num_regs, + void __iomem *base, u8 flags) +{ + struct rockchip_softrst *softrst; + int ret; + + softrst = kzalloc(sizeof(*softrst), GFP_KERNEL); + if (!softrst) + return; + + spin_lock_init(&softrst->lock); + + softrst->reg_base = base; + softrst->flags = flags; + softrst->num_regs = num_regs; + softrst->num_per_reg = (flags & ROCKCHIP_SOFTRST_HIWORD_MASK) ? 16 + : 32; + + softrst->rcdev.nr_resets = num_regs * softrst->num_per_reg; + softrst->rcdev.ops = &rockchip_softrst_ops; + softrst->rcdev.of_node = np; + ret = reset_controller_register(&softrst->rcdev); + if (ret) { + pr_err("%s: could not register reset controller, %d\n", + __func__, ret); + kfree(softrst); + } +}; +EXPORT_SYMBOL_GPL(rockchip_register_softrst); diff --git a/drivers/clk/sifive/sifive-prci.c b/drivers/clk/sifive/sifive-prci.c index b452bbf8cc..1701a2c5a0 100644 --- a/drivers/clk/sifive/sifive-prci.c +++ b/drivers/clk/sifive/sifive-prci.c @@ -185,7 +185,7 @@ static void __prci_wrpll_write_cfg1(struct __prci_data *pd, * these functions. */ -unsigned long sifive_prci_wrpll_recalc_rate(struct clk *hw, +unsigned long sifive_prci_wrpll_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) { struct __prci_clock *pc = clk_hw_to_prci_clock(hw); @@ -194,7 +194,7 @@ unsigned long sifive_prci_wrpll_recalc_rate(struct clk *hw, return wrpll_calc_output_rate(&pwd->c, parent_rate); } -long sifive_prci_wrpll_round_rate(struct clk *hw, +long sifive_prci_wrpll_round_rate(struct clk_hw *hw, unsigned long rate, unsigned long *parent_rate) { @@ -209,7 +209,7 @@ long sifive_prci_wrpll_round_rate(struct clk *hw, return wrpll_calc_output_rate(&c, *parent_rate); } -int sifive_prci_wrpll_set_rate(struct clk *hw, +int sifive_prci_wrpll_set_rate(struct clk_hw *hw, unsigned long rate, unsigned long parent_rate) { struct __prci_clock *pc = clk_hw_to_prci_clock(hw); @@ -231,7 +231,7 @@ int sifive_prci_wrpll_set_rate(struct clk *hw, return 0; } -int sifive_clk_is_enabled(struct clk *hw) +int sifive_clk_is_enabled(struct clk_hw *hw) { struct __prci_clock *pc = clk_hw_to_prci_clock(hw); struct __prci_wrpll_data *pwd = pc->pwd; @@ -246,7 +246,7 @@ int sifive_clk_is_enabled(struct clk *hw) return 0; } -int sifive_prci_clock_enable(struct clk *hw) +int sifive_prci_clock_enable(struct clk_hw *hw) { struct __prci_clock *pc = clk_hw_to_prci_clock(hw); struct __prci_wrpll_data *pwd = pc->pwd; @@ -263,7 +263,7 @@ int sifive_prci_clock_enable(struct clk *hw) return 0; } -void sifive_prci_clock_disable(struct clk *hw) +void sifive_prci_clock_disable(struct clk_hw *hw) { struct __prci_clock *pc = clk_hw_to_prci_clock(hw); struct __prci_wrpll_data *pwd = pc->pwd; @@ -281,7 +281,7 @@ void sifive_prci_clock_disable(struct clk *hw) /* TLCLKSEL clock integration */ -unsigned long sifive_prci_tlclksel_recalc_rate(struct clk *hw, +unsigned long sifive_prci_tlclksel_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) { struct __prci_clock *pc = clk_hw_to_prci_clock(hw); @@ -298,7 +298,7 @@ unsigned long sifive_prci_tlclksel_recalc_rate(struct clk *hw, /* HFPCLK clock integration */ -unsigned long sifive_prci_hfpclkplldiv_recalc_rate(struct clk *hw, +unsigned long sifive_prci_hfpclkplldiv_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) { struct __prci_clock *pc = clk_hw_to_prci_clock(hw); @@ -473,6 +473,7 @@ void sifive_prci_hfpclkpllsel_use_hfpclkpll(struct __prci_data *pd) static int __prci_register_clocks(struct device_d *dev, struct __prci_data *pd, const struct prci_clk_desc *desc) { + struct clk_init_data init = { }; struct __prci_clock *pic; int parent_count, i, r; @@ -485,33 +486,36 @@ static int __prci_register_clocks(struct device_d *dev, struct __prci_data *pd, /* Register PLLs */ for (i = 0; i < desc->num_clks; ++i) { + struct clk *clk; + pic = &(desc->clks[i]); - pic->hw.name = pic->name; - pic->hw.parent_names = &pic->parent_name; - pic->hw.num_parents = 1; - pic->hw.ops = pic->ops; + init.name = pic->name; + init.parent_names = &pic->parent_name; + init.num_parents = 1; + init.ops = pic->ops; + pic->hw.init = &init; pic->pd = pd; if (pic->pwd) __prci_wrpll_read_cfg0(pd, pic->pwd); - r = clk_register(&pic->hw); - if (r) { + clk = clk_register(dev, &pic->hw); + if (IS_ERR(clk)) { dev_warn(dev, "Failed to register clock %s: %d\n", - pic->hw.name, r); - return r; + clk_hw_get_name(&pic->hw), r); + return PTR_ERR(clk); } - r = clk_register_clkdev(&pic->hw, pic->name, dev_name(dev)); + r = clk_register_clkdev(clk, pic->name, dev_name(dev)); if (r) { dev_warn(dev, "Failed to register clkdev for %s: %d\n", - pic->hw.name, r); + clk_hw_get_name(&pic->hw), r); return r; } - pd->hw_clks.clks[i] = &pic->hw; + pd->hw_clks.clks[i] = clk; } pd->hw_clks.clk_num = i; diff --git a/drivers/clk/sifive/sifive-prci.h b/drivers/clk/sifive/sifive-prci.h index d851553818..e7a04ae790 100644 --- a/drivers/clk/sifive/sifive-prci.h +++ b/drivers/clk/sifive/sifive-prci.h @@ -254,7 +254,7 @@ struct __prci_clock { const char *name; const char *parent_name; const struct clk_ops *ops; - struct clk hw; + struct clk_hw hw; struct __prci_wrpll_data *pwd; struct __prci_data *pd; }; @@ -281,18 +281,18 @@ void sifive_prci_hfpclkpllsel_use_hfclk(struct __prci_data *pd); void sifive_prci_hfpclkpllsel_use_hfpclkpll(struct __prci_data *pd); /* Linux clock framework integration */ -long sifive_prci_wrpll_round_rate(struct clk *hw, unsigned long rate, +long sifive_prci_wrpll_round_rate(struct clk_hw *hw, unsigned long rate, unsigned long *parent_rate); -int sifive_prci_wrpll_set_rate(struct clk *hw, unsigned long rate, +int sifive_prci_wrpll_set_rate(struct clk_hw *hw, unsigned long rate, unsigned long parent_rate); -int sifive_clk_is_enabled(struct clk *hw); -int sifive_prci_clock_enable(struct clk *hw); -void sifive_prci_clock_disable(struct clk *hw); -unsigned long sifive_prci_wrpll_recalc_rate(struct clk *hw, +int sifive_clk_is_enabled(struct clk_hw *hw); +int sifive_prci_clock_enable(struct clk_hw *hw); +void sifive_prci_clock_disable(struct clk_hw *hw); +unsigned long sifive_prci_wrpll_recalc_rate(struct clk_hw *hw, unsigned long parent_rate); -unsigned long sifive_prci_tlclksel_recalc_rate(struct clk *hw, +unsigned long sifive_prci_tlclksel_recalc_rate(struct clk_hw *hw, unsigned long parent_rate); -unsigned long sifive_prci_hfpclkplldiv_recalc_rate(struct clk *hw, +unsigned long sifive_prci_hfpclkplldiv_recalc_rate(struct clk_hw *hw, unsigned long parent_rate); #endif /* __SIFIVE_CLK_SIFIVE_PRCI_H */ diff --git a/drivers/clk/socfpga/clk-gate-a10.c b/drivers/clk/socfpga/clk-gate-a10.c index 401eb20d24..cbdec98fc6 100644 --- a/drivers/clk/socfpga/clk-gate-a10.c +++ b/drivers/clk/socfpga/clk-gate-a10.c @@ -14,15 +14,15 @@ #include "clk.h" -#define to_socfpga_gate_clk(p) container_of(p, struct socfpga_gate_clk, clk) +#define to_socfpga_gate_clk(p) container_of(p, struct socfpga_gate_clk, hw) /* SDMMC Group for System Manager defines */ #define SYSMGR_SDMMCGRP_CTRL_OFFSET 0x28 -static unsigned long socfpga_gate_clk_recalc_rate(struct clk *clk, +static unsigned long socfpga_gate_clk_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) { - struct socfpga_gate_clk *socfpgaclk = to_socfpga_gate_clk(clk); + struct socfpga_gate_clk *socfpgaclk = to_socfpga_gate_clk(hw); u32 div = 1, val; if (socfpgaclk->fixed_div) @@ -36,9 +36,9 @@ static unsigned long socfpga_gate_clk_recalc_rate(struct clk *clk, return parent_rate / div; } -static int socfpga_clk_prepare(struct clk *clk) +static int socfpga_clk_prepare(struct clk_hw *hw) { - struct socfpga_gate_clk *socfpgaclk = to_socfpga_gate_clk(clk); + struct socfpga_gate_clk *socfpgaclk = to_socfpga_gate_clk(hw); int i; u32 hs_timing; u32 clk_phase[2]; @@ -82,12 +82,12 @@ static int socfpga_clk_prepare(struct clk *clk) return 0; } -static int clk_socfpga_enable(struct clk *clk) +static int clk_socfpga_enable(struct clk_hw *hw) { - struct socfpga_gate_clk *socfpga_clk = to_socfpga_gate_clk(clk); + struct socfpga_gate_clk *socfpga_clk = to_socfpga_gate_clk(hw); u32 val; - socfpga_clk_prepare(clk); + socfpga_clk_prepare(hw); val = readl(socfpga_clk->reg); val |= 1 << socfpga_clk->bit_idx; @@ -96,9 +96,9 @@ static int clk_socfpga_enable(struct clk *clk) return 0; } -static void clk_socfpga_disable(struct clk *clk) +static void clk_socfpga_disable(struct clk_hw *hw) { - struct socfpga_gate_clk *socfpga_clk = to_socfpga_gate_clk(clk); + struct socfpga_gate_clk *socfpga_clk = to_socfpga_gate_clk(hw); u32 val; val = readl(socfpga_clk->reg); @@ -159,8 +159,8 @@ static struct clk *__socfpga_gate_init(struct device_node *node, of_property_read_string(node, "clock-output-names", &clk_name); - socfpga_clk->clk.name = xstrdup(clk_name); - socfpga_clk->clk.ops = ops; + socfpga_clk->hw.clk.name = xstrdup(clk_name); + socfpga_clk->hw.clk.ops = ops; for (i = 0; i < SOCFPGA_MAX_PARENTS; i++) { socfpga_clk->parent_names[i] = of_clk_get_parent_name(node, i); @@ -168,16 +168,16 @@ static struct clk *__socfpga_gate_init(struct device_node *node, break; } - socfpga_clk->clk.num_parents = i; - socfpga_clk->clk.parent_names = socfpga_clk->parent_names; + socfpga_clk->hw.clk.num_parents = i; + socfpga_clk->hw.clk.parent_names = socfpga_clk->parent_names; - rc = clk_register(&socfpga_clk->clk); + rc = bclk_register(&socfpga_clk->hw.clk); if (rc) { free(socfpga_clk); return ERR_PTR(rc); } - return &socfpga_clk->clk; + return &socfpga_clk->hw.clk; } struct clk *socfpga_a10_gate_init(struct device_node *node) diff --git a/drivers/clk/socfpga/clk-periph-a10.c b/drivers/clk/socfpga/clk-periph-a10.c index 4ef00052e4..f9cf40b0aa 100644 --- a/drivers/clk/socfpga/clk-periph-a10.c +++ b/drivers/clk/socfpga/clk-periph-a10.c @@ -17,12 +17,12 @@ #define SOCFPGA_MPU_FREE_CLK "mpu_free_clk" #define SOCFPGA_NOC_FREE_CLK "noc_free_clk" #define SOCFPGA_SDMMC_FREE_CLK "sdmmc_free_clk" -#define to_socfpga_periph_clk(p) container_of(p, struct socfpga_periph_clk, clk) +#define to_socfpga_periph_clk(p) container_of(p, struct socfpga_periph_clk, hw) -static unsigned long clk_periclk_recalc_rate(struct clk *clk, +static unsigned long clk_periclk_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) { - struct socfpga_periph_clk *socfpgaclk = to_socfpga_periph_clk(clk); + struct socfpga_periph_clk *socfpgaclk = to_socfpga_periph_clk(hw); u32 div; if (socfpgaclk->fixed_div) { @@ -38,15 +38,15 @@ static unsigned long clk_periclk_recalc_rate(struct clk *clk, return parent_rate / div; } -static int clk_periclk_get_parent(struct clk *clk) +static int clk_periclk_get_parent(struct clk_hw *hw) { - struct socfpga_periph_clk *socfpgaclk = to_socfpga_periph_clk(clk); + struct socfpga_periph_clk *socfpgaclk = to_socfpga_periph_clk(hw); u32 clk_src; clk_src = readl(socfpgaclk->reg); - if (streq(clk->name, SOCFPGA_MPU_FREE_CLK) || - streq(clk->name, SOCFPGA_NOC_FREE_CLK) || - streq(clk->name, SOCFPGA_SDMMC_FREE_CLK)) + if (streq(clk_hw_get_name(hw), SOCFPGA_MPU_FREE_CLK) || + streq(clk_hw_get_name(hw), SOCFPGA_NOC_FREE_CLK) || + streq(clk_hw_get_name(hw), SOCFPGA_SDMMC_FREE_CLK)) return (clk_src >> CLK_MGR_FREE_SHIFT) & CLK_MGR_FREE_MASK; else @@ -98,19 +98,19 @@ static struct clk *__socfpga_periph_init(struct device_node *node, break; } - periph_clk->clk.num_parents = i; - periph_clk->clk.parent_names = periph_clk->parent_names; + periph_clk->hw.clk.num_parents = i; + periph_clk->hw.clk.parent_names = periph_clk->parent_names; - periph_clk->clk.name = xstrdup(clk_name); - periph_clk->clk.ops = ops; + periph_clk->hw.clk.name = xstrdup(clk_name); + periph_clk->hw.clk.ops = ops; - rc = clk_register(&periph_clk->clk); + rc = bclk_register(&periph_clk->hw.clk); if (rc) { free(periph_clk); return ERR_PTR(rc); } - return &periph_clk->clk; + return &periph_clk->hw.clk; } struct clk *socfpga_a10_periph_init(struct device_node *node) diff --git a/drivers/clk/socfpga/clk-pll-a10.c b/drivers/clk/socfpga/clk-pll-a10.c index fcf31e9ea1..2e58a2eb5d 100644 --- a/drivers/clk/socfpga/clk-pll-a10.c +++ b/drivers/clk/socfpga/clk-pll-a10.c @@ -28,12 +28,12 @@ #define SOCFPGA_MAIN_PLL_CLK "main_pll" #define SOCFPGA_PERIP_PLL_CLK "periph_pll" -#define to_socfpga_clk(p) container_of(p, struct socfpga_pll, clk) +#define to_socfpga_clk(p) container_of(p, struct socfpga_pll, hw) -static unsigned long clk_pll_recalc_rate(struct clk *clk, +static unsigned long clk_pll_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) { - struct socfpga_pll *socfpgaclk = to_socfpga_clk(clk); + struct socfpga_pll *socfpgaclk = to_socfpga_clk(hw); unsigned long divf, divq, reg; unsigned long long vco_freq; @@ -46,9 +46,9 @@ static unsigned long clk_pll_recalc_rate(struct clk *clk, return (unsigned long)vco_freq; } -static int clk_pll_get_parent(struct clk *clk) +static int clk_pll_get_parent(struct clk_hw *hw) { - struct socfpga_pll *socfpgaclk = to_socfpga_clk(clk); + struct socfpga_pll *socfpgaclk = to_socfpga_clk(hw); u32 pll_src; pll_src = readl(socfpgaclk->reg); @@ -57,9 +57,9 @@ static int clk_pll_get_parent(struct clk *clk) CLK_MGR_PLL_CLK_SRC_MASK; } -static int clk_socfpga_enable(struct clk *clk) +static int clk_socfpga_enable(struct clk_hw *hw) { - struct socfpga_pll *socfpga_clk = to_socfpga_clk(clk); + struct socfpga_pll *socfpga_clk = to_socfpga_clk(hw); u32 val; val = readl(socfpga_clk->reg); @@ -69,9 +69,9 @@ static int clk_socfpga_enable(struct clk *clk) return 0; } -static void clk_socfpga_disable(struct clk *clk) +static void clk_socfpga_disable(struct clk_hw *hw) { - struct socfpga_pll *socfpga_clk = to_socfpga_clk(clk); + struct socfpga_pll *socfpga_clk = to_socfpga_clk(hw); u32 val; val = readl(socfpga_clk->reg); @@ -101,8 +101,8 @@ static struct clk *__socfpga_pll_init(struct device_node *node, of_property_read_string(node, "clock-output-names", &clk_name); - pll_clk->clk.name = xstrdup(clk_name); - pll_clk->clk.ops = ops; + pll_clk->hw.clk.name = xstrdup(clk_name); + pll_clk->hw.clk.ops = ops; for (i = 0; i < SOCFPGA_MAX_PARENTS; i++) { pll_clk->parent_names[i] = of_clk_get_parent_name(node, i); @@ -111,19 +111,19 @@ static struct clk *__socfpga_pll_init(struct device_node *node, } pll_clk->bit_idx = SOCFPGA_PLL_EXT_ENA; - pll_clk->clk.num_parents = i; - pll_clk->clk.parent_names = pll_clk->parent_names; + pll_clk->hw.clk.num_parents = i; + pll_clk->hw.clk.parent_names = pll_clk->parent_names; clk_pll_ops.enable = clk_socfpga_enable; clk_pll_ops.disable = clk_socfpga_disable; - rc = clk_register(&pll_clk->clk); + rc = bclk_register(&pll_clk->hw.clk); if (rc) { free(pll_clk); return NULL; } - return &pll_clk->clk; + return &pll_clk->hw.clk; } struct clk *socfpga_a10_pll_init(struct device_node *node) diff --git a/drivers/clk/socfpga/clk.c b/drivers/clk/socfpga/clk.c index 09e2039bd5..8ee405c6c6 100644 --- a/drivers/clk/socfpga/clk.c +++ b/drivers/clk/socfpga/clk.c @@ -50,15 +50,15 @@ void __iomem *clk_mgr_base_addr; struct clk_pll { - struct clk clk; + struct clk_hw hw; const char *parent; unsigned regofs; }; -static unsigned long clk_pll_recalc_rate(struct clk *clk, +static unsigned long clk_pll_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) { - struct clk_pll *pll = container_of(clk, struct clk_pll, clk); + struct clk_pll *pll = container_of(hw, struct clk_pll, hw); unsigned long divf, divq, vco_freq, reg; unsigned long bypass; @@ -90,24 +90,24 @@ static struct clk *socfpga_pll_clk(struct device_node *node) if (!pll->parent) return ERR_PTR(-EINVAL); - pll->clk.parent_names = &pll->parent; - pll->clk.num_parents = 1; - pll->clk.name = xstrdup(node->name); - pll->clk.ops = &clk_pll_ops; + pll->hw.clk.parent_names = &pll->parent; + pll->hw.clk.num_parents = 1; + pll->hw.clk.name = xstrdup(node->name); + pll->hw.clk.ops = &clk_pll_ops; of_property_read_u32(node, "reg", &pll->regofs); - ret = clk_register(&pll->clk); + ret = bclk_register(&pll->hw.clk); if (ret) { free(pll); return ERR_PTR(ret); } - return &pll->clk; + return &pll->hw.clk; } struct clk_periph { - struct clk clk; + struct clk_hw hw; const char *parent; unsigned regofs; unsigned int fixed_div; @@ -116,10 +116,10 @@ struct clk_periph { unsigned int shift; }; -static unsigned long clk_periph_recalc_rate(struct clk *clk, +static unsigned long clk_periph_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) { - struct clk_periph *periph = container_of(clk, struct clk_periph, clk); + struct clk_periph *periph = container_of(hw, struct clk_periph, hw); u32 div, val; if (periph->fixed_div) { @@ -152,10 +152,10 @@ static struct clk *socfpga_periph_clk(struct device_node *node) if (!periph->parent) return ERR_PTR(-EINVAL); - periph->clk.parent_names = &periph->parent; - periph->clk.num_parents = 1; - periph->clk.name = xstrdup(node->name); - periph->clk.ops = &clk_periph_ops; + periph->hw.clk.parent_names = &periph->parent; + periph->hw.clk.num_parents = 1; + periph->hw.clk.name = xstrdup(node->name); + periph->hw.clk.ops = &clk_periph_ops; ret = of_property_read_u32_array(node, "div-reg", div_reg, 3); if (!ret) { @@ -169,17 +169,17 @@ static struct clk *socfpga_periph_clk(struct device_node *node) of_property_read_u32(node, "reg", &periph->regofs); of_property_read_u32(node, "fixed-divider", &periph->fixed_div); - ret = clk_register(&periph->clk); + ret = bclk_register(&periph->hw.clk); if (ret) { free(periph); return ERR_PTR(ret); } - return &periph->clk; + return &periph->hw.clk; } struct clk_socfpga { - struct clk clk; + struct clk_hw hw; const char *parent; void __iomem *reg; void __iomem *div_reg; @@ -190,9 +190,9 @@ struct clk_socfpga { const char *parent_names[SOCFGPA_MAX_PARENTS]; }; -static int clk_socfpga_enable(struct clk *clk) +static int clk_socfpga_enable(struct clk_hw *hw) { - struct clk_socfpga *cs = container_of(clk, struct clk_socfpga, clk); + struct clk_socfpga *cs = container_of(hw, struct clk_socfpga, hw); u32 val; val = readl(cs->reg); @@ -202,9 +202,9 @@ static int clk_socfpga_enable(struct clk *clk) return 0; } -static void clk_socfpga_disable(struct clk *clk) +static void clk_socfpga_disable(struct clk_hw *hw) { - struct clk_socfpga *cs = container_of(clk, struct clk_socfpga, clk); + struct clk_socfpga *cs = container_of(hw, struct clk_socfpga, hw); u32 val; val = readl(cs->reg); @@ -212,9 +212,9 @@ static void clk_socfpga_disable(struct clk *clk) writel(val, cs->reg); } -static int clk_socfpga_is_enabled(struct clk *clk) +static int clk_socfpga_is_enabled(struct clk_hw *hw) { - struct clk_socfpga *cs = container_of(clk, struct clk_socfpga, clk); + struct clk_socfpga *cs = container_of(hw, struct clk_socfpga, hw); u32 val; val = readl(cs->reg); @@ -225,10 +225,10 @@ static int clk_socfpga_is_enabled(struct clk *clk) return 0; } -static unsigned long clk_socfpga_recalc_rate(struct clk *clk, +static unsigned long clk_socfpga_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) { - struct clk_socfpga *cs = container_of(clk, struct clk_socfpga, clk); + struct clk_socfpga *cs = container_of(hw, struct clk_socfpga, hw); u32 div = 1, val; if (cs->fixed_div) { @@ -236,7 +236,7 @@ static unsigned long clk_socfpga_recalc_rate(struct clk *clk, } else if (cs->div_reg) { val = readl(cs->div_reg) >> cs->shift; val &= div_mask(cs->width); - if (streq(clk->name, SOCFPGA_DB_CLK)) + if (streq(clk_hw_get_name(hw), SOCFPGA_DB_CLK)) div = val + 1; else div = (1 << val); @@ -245,8 +245,9 @@ static unsigned long clk_socfpga_recalc_rate(struct clk *clk, return parent_rate / div; } -static int clk_socfpga_get_parent(struct clk *clk) +static int clk_socfpga_get_parent(struct clk_hw *hw) { + struct clk *clk = clk_hw_to_clk(hw); u32 perpll_src; u32 l4_src; @@ -270,8 +271,9 @@ static int clk_socfpga_get_parent(struct clk *clk) return (perpll_src >> 4) & 3; } -static int clk_socfpga_set_parent(struct clk *clk, u8 parent) +static int clk_socfpga_set_parent(struct clk_hw *hw, u8 parent) { + struct clk *clk = clk_hw_to_clk(hw); u32 src_reg; if (streq(clk->name, SOCFPGA_L4_MP_CLK)) { @@ -351,18 +353,18 @@ static struct clk *socfpga_gate_clk(struct device_node *node) break; } - cs->clk.parent_names = cs->parent_names; - cs->clk.num_parents = i; - cs->clk.name = xstrdup(node->name); - cs->clk.ops = &clk_socfpga_ops; + cs->hw.clk.parent_names = cs->parent_names; + cs->hw.clk.num_parents = i; + cs->hw.clk.name = xstrdup(node->name); + cs->hw.clk.ops = &clk_socfpga_ops; - ret = clk_register(&cs->clk); + ret = bclk_register(&cs->hw.clk); if (ret) { free(cs); return ERR_PTR(ret); } - return &cs->clk; + return &cs->hw.clk; } static void socfpga_register_clocks(struct device_d *dev, struct device_node *node) diff --git a/drivers/clk/socfpga/clk.h b/drivers/clk/socfpga/clk.h index 9d291f7243..402f714436 100644 --- a/drivers/clk/socfpga/clk.h +++ b/drivers/clk/socfpga/clk.h @@ -47,14 +47,14 @@ static inline struct clk *socfpga_a10_gate_init(struct device_node *node) #endif struct socfpga_pll { - struct clk clk; + struct clk_hw hw; void __iomem *reg; u32 bit_idx; const char *parent_names[SOCFPGA_MAX_PARENTS]; }; struct socfpga_gate_clk { - struct clk clk; + struct clk_hw hw; char *parent_name; u32 fixed_div; void __iomem *div_reg; @@ -68,7 +68,7 @@ struct socfpga_gate_clk { }; struct socfpga_periph_clk { - struct clk clk; + struct clk_hw hw; void __iomem *reg; char *parent_name; u32 fixed_div; diff --git a/drivers/clk/tegra/clk-divider.c b/drivers/clk/tegra/clk-divider.c index cc8b85520c..f1a913d983 100644 --- a/drivers/clk/tegra/clk-divider.c +++ b/drivers/clk/tegra/clk-divider.c @@ -46,21 +46,22 @@ static int get_div(struct tegra_clk_frac_div *divider, unsigned long rate, if (flags & TEGRA_DIVIDER_INT) divider_ux1 *= mul; - divider_ux1 -= mul; - - if (divider_ux1 < 0) + if (divider_ux1 < mul) return 0; + divider_ux1 -= mul; + if (divider_ux1 > get_max_div(divider)) return -EINVAL; return divider_ux1; } -static unsigned long clk_frac_div_recalc_rate(struct clk *hw, +static unsigned long clk_frac_div_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) { - struct tegra_clk_frac_div *divider = to_clk_frac_div(hw); + struct clk *clk = clk_hw_to_clk(hw); + struct tegra_clk_frac_div *divider = to_clk_frac_div(clk); u32 reg; int div, mul; u64 rate = parent_rate; @@ -78,10 +79,11 @@ static unsigned long clk_frac_div_recalc_rate(struct clk *hw, return rate; } -static long clk_frac_div_round_rate(struct clk *hw, unsigned long rate, +static long clk_frac_div_round_rate(struct clk_hw *hw, unsigned long rate, unsigned long *prate) { - struct tegra_clk_frac_div *divider = to_clk_frac_div(hw); + struct clk *clk = clk_hw_to_clk(hw); + struct tegra_clk_frac_div *divider = to_clk_frac_div(clk); int div, mul; unsigned long output_rate = *prate; @@ -97,10 +99,11 @@ static long clk_frac_div_round_rate(struct clk *hw, unsigned long rate, return DIV_ROUND_UP(output_rate * mul, div + mul); } -static int clk_frac_div_set_rate(struct clk *hw, unsigned long rate, +static int clk_frac_div_set_rate(struct clk_hw *hw, unsigned long rate, unsigned long parent_rate) { - struct tegra_clk_frac_div *divider = to_clk_frac_div(hw); + struct clk *clk = clk_hw_to_clk(hw); + struct tegra_clk_frac_div *divider = to_clk_frac_div(clk); int div; u32 val; @@ -180,7 +183,7 @@ struct clk *tegra_clk_register_divider(const char *name, reg, flags, clk_divider_flags, shift, width, frac_width)); - ret = clk_register(÷r->hw); + ret = bclk_register(÷r->hw); if (ret) { kfree(divider); return ERR_PTR(ret); diff --git a/drivers/clk/tegra/clk-periph.c b/drivers/clk/tegra/clk-periph.c index 0cd5200e84..7bfb14875d 100644 --- a/drivers/clk/tegra/clk-periph.c +++ b/drivers/clk/tegra/clk-periph.c @@ -16,65 +16,65 @@ #define to_clk_periph(_hw) container_of(_hw, struct tegra_clk_periph, hw) -static int clk_periph_get_parent(struct clk *hw) +static int clk_periph_get_parent(struct clk_hw *hw) { struct tegra_clk_periph *periph = to_clk_periph(hw); - return periph->mux->ops->get_parent(periph->mux); + return periph->mux->ops->get_parent(clk_to_clk_hw(periph->mux)); } -static int clk_periph_set_parent(struct clk *hw, u8 index) +static int clk_periph_set_parent(struct clk_hw *hw, u8 index) { struct tegra_clk_periph *periph = to_clk_periph(hw); - return periph->mux->ops->set_parent(periph->mux, index); + return periph->mux->ops->set_parent(clk_to_clk_hw(periph->mux), index); } -static unsigned long clk_periph_recalc_rate(struct clk *hw, +static unsigned long clk_periph_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) { struct tegra_clk_periph *periph = to_clk_periph(hw); - return periph->div->ops->recalc_rate(periph->div, parent_rate); + return periph->div->ops->recalc_rate(clk_to_clk_hw(periph->div), parent_rate); } -static long clk_periph_round_rate(struct clk *hw, unsigned long rate, +static long clk_periph_round_rate(struct clk_hw *hw, unsigned long rate, unsigned long *prate) { struct tegra_clk_periph *periph = to_clk_periph(hw); - return periph->div->ops->round_rate(periph->div, rate, prate); + return periph->div->ops->round_rate(clk_to_clk_hw(periph->div), rate, prate); } -static int clk_periph_set_rate(struct clk *hw, unsigned long rate, +static int clk_periph_set_rate(struct clk_hw *hw, unsigned long rate, unsigned long parent_rate) { struct tegra_clk_periph *periph = to_clk_periph(hw); - return periph->div->ops->set_rate(periph->div, rate, parent_rate); + return periph->div->ops->set_rate(clk_to_clk_hw(periph->div), rate, parent_rate); } -static int clk_periph_is_enabled(struct clk *hw) +static int clk_periph_is_enabled(struct clk_hw *hw) { struct tegra_clk_periph *periph = to_clk_periph(hw); - return periph->gate->ops->is_enabled(periph->gate); + return periph->gate->ops->is_enabled(clk_to_clk_hw(periph->gate)); } -static int clk_periph_enable(struct clk *hw) +static int clk_periph_enable(struct clk_hw *hw) { struct tegra_clk_periph *periph = to_clk_periph(hw); - periph->gate->ops->enable(periph->gate); + periph->gate->ops->enable(clk_to_clk_hw(periph->gate)); return 0; } -static void clk_periph_disable(struct clk *hw) +static void clk_periph_disable(struct clk_hw *hw) { struct tegra_clk_periph *periph = to_clk_periph(hw); - periph->gate->ops->disable(periph->gate); + periph->gate->ops->disable(clk_to_clk_hw(periph->gate)); } const struct clk_ops tegra_clk_periph_ops = { @@ -139,11 +139,11 @@ static struct clk *_tegra_clk_register_periph(const char *name, goto out_div; } - periph->hw.name = name; - periph->hw.ops = div ? &tegra_clk_periph_ops : + periph->hw.clk.name = name; + periph->hw.clk.ops = div ? &tegra_clk_periph_ops : &tegra_clk_periph_nodiv_ops; - periph->hw.parent_names = parent_names; - periph->hw.num_parents = num_parents; + periph->hw.clk.parent_names = parent_names; + periph->hw.clk.num_parents = num_parents; periph->flags = flags; if (id >= 96) @@ -153,11 +153,11 @@ static struct clk *_tegra_clk_register_periph(const char *name, periph->rst_reg = clk_base + rst_offs; periph->rst_shift = id & 0x1f; - ret = clk_register(&periph->hw); + ret = bclk_register(&periph->hw.clk); if (ret) goto out_register; - return &periph->hw; + return &periph->hw.clk; out_register: tegra_clk_divider_free(periph->div); diff --git a/drivers/clk/tegra/clk-pll-out.c b/drivers/clk/tegra/clk-pll-out.c index e186275563..f14b41c04a 100644 --- a/drivers/clk/tegra/clk-pll-out.c +++ b/drivers/clk/tegra/clk-pll-out.c @@ -18,7 +18,7 @@ #define to_clk_pll_out(_hw) container_of(_hw, struct tegra_clk_pll_out, hw) -static int clk_pll_out_is_enabled(struct clk *hw) +static int clk_pll_out_is_enabled(struct clk_hw *hw) { struct tegra_clk_pll_out *pll_out = to_clk_pll_out(hw); u32 val = readl(pll_out->reg); @@ -30,7 +30,7 @@ static int clk_pll_out_is_enabled(struct clk *hw) return state; } -static int clk_pll_out_enable(struct clk *hw) +static int clk_pll_out_enable(struct clk_hw *hw) { struct tegra_clk_pll_out *pll_out = to_clk_pll_out(hw); u32 val; @@ -45,7 +45,7 @@ static int clk_pll_out_enable(struct clk *hw) return 0; } -static void clk_pll_out_disable(struct clk *hw) +static void clk_pll_out_disable(struct clk_hw *hw) { struct tegra_clk_pll_out *pll_out = to_clk_pll_out(hw); u32 val; @@ -58,28 +58,28 @@ static void clk_pll_out_disable(struct clk *hw) udelay(2); } -static unsigned long clk_pll_out_recalc_rate(struct clk *hw, +static unsigned long clk_pll_out_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) { struct tegra_clk_pll_out *pll_out = to_clk_pll_out(hw); - return pll_out->div->ops->recalc_rate(pll_out->div, parent_rate); + return pll_out->div->ops->recalc_rate(clk_to_clk_hw(pll_out->div), parent_rate); } -static long clk_pll_out_round_rate(struct clk *hw, unsigned long rate, +static long clk_pll_out_round_rate(struct clk_hw *hw, unsigned long rate, unsigned long *prate) { struct tegra_clk_pll_out *pll_out = to_clk_pll_out(hw); - return pll_out->div->ops->round_rate(pll_out->div, rate, prate); + return pll_out->div->ops->round_rate(clk_to_clk_hw(pll_out->div), rate, prate); } -static int clk_pll_out_set_rate(struct clk *hw, unsigned long rate, +static int clk_pll_out_set_rate(struct clk_hw *hw, unsigned long rate, unsigned long parent_rate) { struct tegra_clk_pll_out *pll_out = to_clk_pll_out(hw); - return pll_out->div->ops->set_rate(pll_out->div, rate, parent_rate); + return pll_out->div->ops->set_rate(clk_to_clk_hw(pll_out->div), rate, parent_rate); } const struct clk_ops tegra_clk_pll_out_ops = { @@ -108,21 +108,21 @@ struct clk *tegra_clk_register_pll_out(const char *name, } pll_out->parent = parent_name; - pll_out->hw.name = name; - pll_out->hw.ops = &tegra_clk_pll_out_ops; - pll_out->hw.parent_names = (pll_out->parent ? &pll_out->parent : NULL); - pll_out->hw.num_parents = (pll_out->parent ? 1 : 0); + pll_out->hw.clk.name = name; + pll_out->hw.clk.ops = &tegra_clk_pll_out_ops; + pll_out->hw.clk.parent_names = (pll_out->parent ? &pll_out->parent : NULL); + pll_out->hw.clk.num_parents = (pll_out->parent ? 1 : 0); pll_out->reg = reg; pll_out->enb_bit_idx = shift + 1; pll_out->rst_bit_idx = shift; - ret = clk_register(&pll_out->hw); + ret = bclk_register(&pll_out->hw.clk); if (ret) { tegra_clk_divider_free(pll_out->div); kfree(pll_out); return ERR_PTR(ret); } - return &pll_out->hw; + return &pll_out->hw.clk; } diff --git a/drivers/clk/tegra/clk-pll.c b/drivers/clk/tegra/clk-pll.c index 832b3c5ea1..0d364f318d 100644 --- a/drivers/clk/tegra/clk-pll.c +++ b/drivers/clk/tegra/clk-pll.c @@ -144,7 +144,7 @@ #define to_clk_pll(_hw) container_of(_hw, struct tegra_clk_pll, hw) -static int clk_pll_is_enabled(struct clk *hw) +static int clk_pll_is_enabled(struct clk_hw *hw) { struct tegra_clk_pll *pll = to_clk_pll(hw); u32 val; @@ -187,12 +187,12 @@ static int clk_pll_wait_for_lock(struct tegra_clk_pll *pll, } pr_err("%s: Timed out waiting for pll %s lock\n", __func__, - pll->hw.name); + clk_hw_get_name(&pll->hw)); return -1; } -static int clk_pll_enable(struct clk *hw) +static int clk_pll_enable(struct clk_hw *hw) { struct tegra_clk_pll *pll = to_clk_pll(hw); u32 val; @@ -210,7 +210,7 @@ static int clk_pll_enable(struct clk *hw) return 0; } -static void clk_pll_disable(struct clk *hw) +static void clk_pll_disable(struct clk_hw *hw) { struct tegra_clk_pll *pll = to_clk_pll(hw); u32 val; @@ -220,7 +220,7 @@ static void clk_pll_disable(struct clk *hw) pll_writel_base(val, pll); } -static int _get_table_rate(struct clk *hw, +static int _get_table_rate(struct clk_hw *hw, struct tegra_clk_pll_freq_table *cfg, unsigned long rate, unsigned long parent_rate) { @@ -245,7 +245,7 @@ static int _get_table_rate(struct clk *hw, return 0; } -static unsigned long clk_pll_recalc_rate(struct clk *hw, +static unsigned long clk_pll_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) { struct tegra_clk_pll *pll = to_clk_pll(hw); @@ -260,7 +260,7 @@ static unsigned long clk_pll_recalc_rate(struct clk *hw, struct tegra_clk_pll_freq_table sel; if (_get_table_rate(hw, &sel, pll->fixed_rate, parent_rate)) { pr_err("Clock %s has unknown fixed frequency\n", - hw->name); + clk_hw_get_name(hw)); BUG(); } return pll->fixed_rate; @@ -280,7 +280,7 @@ static unsigned long clk_pll_recalc_rate(struct clk *hw, return rate; } -static int _calc_rate(struct clk *hw, struct tegra_clk_pll_freq_table *cfg, +static int _calc_rate(struct clk_hw *hw, struct tegra_clk_pll_freq_table *cfg, unsigned long rate, unsigned long parent_rate) { struct tegra_clk_pll *pll = to_clk_pll(hw); @@ -325,14 +325,14 @@ static int _calc_rate(struct clk *hw, struct tegra_clk_pll_freq_table *cfg, if (cfg->m > divm_max(pll) || cfg->n > divn_max(pll) || cfg->p > divp_max(pll) || cfg->output_rate > pll->params->vco_max) { pr_err("%s: Failed to set %s rate %lu\n", - __func__, hw->name, rate); + __func__, clk_hw_get_name(hw), rate); return -EINVAL; } return 0; } -static long clk_pll_round_rate(struct clk *hw, unsigned long rate, +static long clk_pll_round_rate(struct clk_hw *hw, unsigned long rate, unsigned long *prate) { struct tegra_clk_pll *pll = to_clk_pll(hw); @@ -344,7 +344,7 @@ static long clk_pll_round_rate(struct clk *hw, unsigned long rate, /* PLLM is used for memory; we do not change rate */ if (pll->flags & TEGRA_PLLM) - return clk_get_rate(hw); + return clk_get_rate(clk_hw_to_clk(hw)); if (_get_table_rate(hw, &cfg, rate, *prate) && _calc_rate(hw, &cfg, rate, *prate)) @@ -356,7 +356,7 @@ static long clk_pll_round_rate(struct clk *hw, unsigned long rate, return output_rate; } -static int _program_pll(struct clk *hw, struct tegra_clk_pll_freq_table *cfg, +static int _program_pll(struct clk_hw *hw, struct tegra_clk_pll_freq_table *cfg, unsigned long rate) { struct tegra_clk_pll *pll = to_clk_pll(hw); @@ -411,7 +411,7 @@ static int _program_pll(struct clk *hw, struct tegra_clk_pll_freq_table *cfg, return 0; } -static int clk_pll_set_rate(struct clk *hw, unsigned long rate, +static int clk_pll_set_rate(struct clk_hw *hw, unsigned long rate, unsigned long parent_rate) { struct tegra_clk_pll_freq_table cfg; @@ -432,7 +432,7 @@ const struct clk_ops tegra_clk_pll_ops = { .set_rate = clk_pll_set_rate, }; -static unsigned long clk_plle_recalc_rate(struct clk *hw, +static unsigned long clk_plle_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) { struct tegra_clk_pll *pll = to_clk_pll(hw); @@ -474,10 +474,10 @@ static int clk_plle_training(struct tegra_clk_pll *pll) (pll_readl_misc(pll) & PLLE_MISC_READY)); } -static int clk_plle_enable(struct clk *hw) +static int clk_plle_enable(struct clk_hw *hw) { struct tegra_clk_pll *pll = to_clk_pll(hw); - unsigned long input_rate = clk_get_rate(clk_get_parent(hw)); + unsigned long input_rate = clk_get_rate(clk_get_parent(clk_hw_to_clk(hw))); struct tegra_clk_pll_freq_table sel; u32 val; int err; @@ -534,10 +534,10 @@ const struct clk_ops tegra_clk_plle_ops = { .enable = clk_plle_enable, }; -static int clk_plle_tegra114_enable(struct clk *hw) +static int clk_plle_tegra114_enable(struct clk_hw *hw) { struct tegra_clk_pll *pll = to_clk_pll(hw); - unsigned long input_rate = clk_get_rate(clk_get_parent(hw)); + unsigned long input_rate = clk_get_rate(clk_get_parent(clk_hw_to_clk(hw))); struct tegra_clk_pll_freq_table sel; u32 val; int ret; @@ -623,7 +623,7 @@ static int clk_plle_tegra114_enable(struct clk *hw) return ret; } -static void clk_plle_tegra114_disable(struct clk *hw) +static void clk_plle_tegra114_disable(struct clk_hw *hw) { struct tegra_clk_pll *pll = to_clk_pll(hw); u32 val; @@ -658,11 +658,11 @@ static struct clk *_tegra_clk_register_pll(const char *name, return NULL; pll->parent = parent_name; - pll->hw.name = name; - pll->hw.ops = ops; - pll->hw.flags = flags; - pll->hw.parent_names = (pll->parent ? &pll->parent : NULL); - pll->hw.num_parents = (pll->parent ? 1 : 0); + pll->hw.clk.name = name; + pll->hw.clk.ops = ops; + pll->hw.clk.flags = flags; + pll->hw.clk.parent_names = (pll->parent ? &pll->parent : NULL); + pll->hw.clk.num_parents = (pll->parent ? 1 : 0); pll->clk_base = clk_base; @@ -678,13 +678,13 @@ static struct clk *_tegra_clk_register_pll(const char *name, pll->divm_shift = PLL_BASE_DIVM_SHIFT; pll->divm_width = PLL_BASE_DIVM_WIDTH; - ret = clk_register(&pll->hw); + ret = bclk_register(&pll->hw.clk); if (ret) { kfree(pll); return ERR_PTR(ret); } - return &pll->hw; + return &pll->hw.clk; } struct clk *tegra_clk_register_pll(const char *name, const char *parent_name, diff --git a/drivers/clk/tegra/clk.h b/drivers/clk/tegra/clk.h index 5195e6dba4..80a83c7865 100644 --- a/drivers/clk/tegra/clk.h +++ b/drivers/clk/tegra/clk.h @@ -61,7 +61,7 @@ struct tegra_clk_pll_params { /* struct tegra_clk_pll - Tegra PLL clock */ struct tegra_clk_pll { - struct clk hw; + struct clk_hw hw; void __iomem *clk_base; u8 flags; unsigned long fixed_rate; @@ -105,7 +105,7 @@ struct clk *tegra_clk_register_plle_tegra114(const char *name, /* struct tegra_clk_pll_out - PLL output divider */ struct tegra_clk_pll_out { - struct clk hw; + struct clk_hw hw; struct clk *div; void __iomem *reg; u8 enb_bit_idx; @@ -119,7 +119,7 @@ struct clk *tegra_clk_register_pll_out(const char *name, /* struct clk-periph - peripheral clock */ struct tegra_clk_periph { - struct clk hw; + struct clk_hw hw; struct clk *gate; struct clk *mux; struct clk *div; diff --git a/drivers/clk/vexpress/clk-sp810.c b/drivers/clk/vexpress/clk-sp810.c index 968921203b..6eba0a2285 100644 --- a/drivers/clk/vexpress/clk-sp810.c +++ b/drivers/clk/vexpress/clk-sp810.c @@ -15,15 +15,15 @@ struct clk_sp810; struct clk_sp810_timerclken { - struct clk hw; + struct clk_hw hw; struct clk_sp810 *sp810; int channel; }; static inline struct clk_sp810_timerclken * -to_clk_sp810_timerclken(struct clk *clk) +to_clk_sp810_timerclken(struct clk_hw *hw) { - return container_of(clk, struct clk_sp810_timerclken, hw); + return container_of(hw, struct clk_sp810_timerclken, hw); } struct clk_sp810 { @@ -32,12 +32,12 @@ struct clk_sp810 { struct clk_sp810_timerclken timerclken[4]; }; -static int clk_sp810_timerclken_get_parent(struct clk *hw) +static int clk_sp810_timerclken_get_parent(struct clk_hw *hw) { return 1; } -static int clk_sp810_timerclken_set_parent(struct clk *hw, u8 index) +static int clk_sp810_timerclken_set_parent(struct clk_hw *hw, u8 index) { struct clk_sp810_timerclken *timerclken = to_clk_sp810_timerclken(hw); struct clk_sp810 *sp810 = timerclken->sp810; @@ -71,7 +71,7 @@ static struct clk *clk_sp810_timerclken_of_get(struct of_phandle_args *clkspec, clkspec->args[0] >= ARRAY_SIZE(sp810->timerclken))) return NULL; - return &sp810->timerclken[clkspec->args[0]].hw; + return &sp810->timerclken[clkspec->args[0]].hw.clk; } static void clk_sp810_of_setup(struct device_node *node) @@ -100,18 +100,18 @@ static void clk_sp810_of_setup(struct device_node *node) sp810->timerclken[i].sp810 = sp810; sp810->timerclken[i].channel = i; - sp810->timerclken[i].hw.name = strdup(name); - sp810->timerclken[i].hw.parent_names = parent_names; - sp810->timerclken[i].hw.num_parents = num; - sp810->timerclken[i].hw.ops = &clk_sp810_timerclken_ops; + sp810->timerclken[i].hw.clk.name = strdup(name); + sp810->timerclken[i].hw.clk.parent_names = parent_names; + sp810->timerclken[i].hw.clk.num_parents = num; + sp810->timerclken[i].hw.clk.ops = &clk_sp810_timerclken_ops; + + bclk_register(&sp810->timerclken[i].hw.clk); /* * Always set parent to 1MHz clock to match QEMU emulation * and satisfy requirements on real HW. */ clk_sp810_timerclken_set_parent(&sp810->timerclken[i].hw, 1); - - clk_register(&sp810->timerclken[i].hw); } of_clk_add_provider(node, clk_sp810_timerclken_of_get, sp810); diff --git a/drivers/clk/zynq/clkc.c b/drivers/clk/zynq/clkc.c index 23259a5324..e4ce102d6e 100644 --- a/drivers/clk/zynq/clkc.c +++ b/drivers/clk/zynq/clkc.c @@ -50,25 +50,25 @@ static struct clk *clks[clk_max]; static struct clk_onecell_data clk_data; struct zynq_pll_clk { - struct clk clk; + struct clk_hw hw; u32 pll_lock; void __iomem *pll_ctrl; }; -#define to_zynq_pll_clk(c) container_of(c, struct zynq_pll_clk, clk) +#define to_zynq_pll_clk(c) container_of(c, struct zynq_pll_clk, hw) #define PLL_CTRL_FDIV(x) (((x) >> 12) & 0x7F) -static unsigned long zynq_pll_recalc_rate(struct clk *clk, +static unsigned long zynq_pll_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) { - struct zynq_pll_clk *pll = to_zynq_pll_clk(clk); + struct zynq_pll_clk *pll = to_zynq_pll_clk(hw); return parent_rate * PLL_CTRL_FDIV(readl(pll->pll_ctrl)); } -static int zynq_pll_enable(struct clk *clk) +static int zynq_pll_enable(struct clk_hw *hw) { - struct zynq_pll_clk *pll = to_zynq_pll_clk(clk); + struct zynq_pll_clk *pll = to_zynq_pll_clk(hw); u32 val; int timeout = 10000; @@ -87,9 +87,9 @@ static int zynq_pll_enable(struct clk *clk) return 0; } -static int zynq_pll_is_enabled(struct clk *clk) +static int zynq_pll_is_enabled(struct clk_hw *hw) { - struct zynq_pll_clk *pll = to_zynq_pll_clk(clk); + struct zynq_pll_clk *pll = to_zynq_pll_clk(hw); u32 val = readl(pll->pll_ctrl); return !(val & (PLL_CTRL_PWRDOWN | PLL_CTRL_RESET)); @@ -111,10 +111,10 @@ static inline struct clk *zynq_pll_clk(enum zynq_pll_type type, pll = xzalloc(sizeof(*pll)); pll->pll_ctrl = pll_ctrl; - pll->clk.ops = &zynq_pll_clk_ops; - pll->clk.name = name; - pll->clk.parent_names = &pll_parent; - pll->clk.num_parents = 1; + pll->hw.clk.ops = &zynq_pll_clk_ops; + pll->hw.clk.name = name; + pll->hw.clk.parent_names = &pll_parent; + pll->hw.clk.num_parents = 1; switch(type) { case ZYNQ_PLL_ARM: @@ -128,17 +128,17 @@ static inline struct clk *zynq_pll_clk(enum zynq_pll_type type, break; } - ret = clk_register(&pll->clk); + ret = bclk_register(&pll->hw.clk); if (ret) { free(pll); return ERR_PTR(ret); } - return &pll->clk; + return &pll->hw.clk; } struct zynq_periph_clk { - struct clk clk; + struct clk_hw hw; void __iomem *clk_ctrl; }; @@ -150,16 +150,16 @@ static const u8 periph_clk_parent_map[] = { #define PERIPH_CLK_CTRL_SRC(x) (periph_clk_parent_map[((x) & 0x30) >> 4]) #define PERIPH_CLK_CTRL_DIV(x) (((x) & 0x3F00) >> 8) -static unsigned long zynq_periph_recalc_rate(struct clk *clk, +static unsigned long zynq_periph_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) { - struct zynq_periph_clk *periph = to_zynq_periph_clk(clk); + struct zynq_periph_clk *periph = to_zynq_periph_clk(hw); return parent_rate / PERIPH_CLK_CTRL_DIV(readl(periph->clk_ctrl)); } -static int zynq_periph_get_parent(struct clk *clk) +static int zynq_periph_get_parent(struct clk_hw *hw) { - struct zynq_periph_clk *periph = to_zynq_periph_clk(clk); + struct zynq_periph_clk *periph = to_zynq_periph_clk(hw); return PERIPH_CLK_CTRL_SRC(readl(periph->clk_ctrl)); } @@ -181,18 +181,18 @@ static struct clk *zynq_periph_clk(const char *name, void __iomem *clk_ctrl) periph = xzalloc(sizeof(*periph)); periph->clk_ctrl = clk_ctrl; - periph->clk.name = name; - periph->clk.ops = &zynq_periph_clk_ops; - periph->clk.parent_names = peripheral_parents; - periph->clk.num_parents = ARRAY_SIZE(peripheral_parents); + periph->hw.clk.name = name; + periph->hw.clk.ops = &zynq_periph_clk_ops; + periph->hw.clk.parent_names = peripheral_parents; + periph->hw.clk.num_parents = ARRAY_SIZE(peripheral_parents); - ret = clk_register(&periph->clk); + ret = bclk_register(&periph->hw.clk); if (ret) { free(periph); return ERR_PTR(ret); } - return &periph->clk; + return &periph->hw.clk; } /* CPU Clock domain is modelled as a mux with 4 children subclks, whose @@ -200,7 +200,7 @@ static struct clk *zynq_periph_clk(const char *name, void __iomem *clk_ctrl) */ struct zynq_cpu_clk { - struct clk clk; + struct clk_hw hw; void __iomem *clk_ctrl; }; @@ -212,16 +212,16 @@ static const u8 zynq_cpu_clk_parent_map[] = { #define CPU_CLK_SRCSEL(x) (zynq_cpu_clk_parent_map[(((x) & 0x30) >> 4)]) #define CPU_CLK_CTRL_DIV(x) (((x) & 0x3F00) >> 8) -static unsigned long zynq_cpu_clk_recalc_rate(struct clk *clk, +static unsigned long zynq_cpu_clk_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) { - struct zynq_cpu_clk *cpuclk = to_zynq_cpu_clk(clk); + struct zynq_cpu_clk *cpuclk = to_zynq_cpu_clk(hw); return parent_rate / CPU_CLK_CTRL_DIV(readl(cpuclk->clk_ctrl)); } -static int zynq_cpu_clk_get_parent(struct clk *clk) +static int zynq_cpu_clk_get_parent(struct clk_hw *hw) { - struct zynq_cpu_clk *cpuclk = to_zynq_cpu_clk(clk); + struct zynq_cpu_clk *cpuclk = to_zynq_cpu_clk(hw); return CPU_CLK_SRCSEL(readl(cpuclk->clk_ctrl)); } @@ -243,18 +243,18 @@ static struct clk *zynq_cpu_clk(const char *name, void __iomem *clk_ctrl) cpu = xzalloc(sizeof(*cpu)); cpu->clk_ctrl = clk_ctrl; - cpu->clk.ops = &zynq_cpu_clk_ops; - cpu->clk.name = name; - cpu->clk.parent_names = cpu_parents; - cpu->clk.num_parents = ARRAY_SIZE(cpu_parents); + cpu->hw.clk.ops = &zynq_cpu_clk_ops; + cpu->hw.clk.name = name; + cpu->hw.clk.parent_names = cpu_parents; + cpu->hw.clk.num_parents = ARRAY_SIZE(cpu_parents); - ret = clk_register(&cpu->clk); + ret = bclk_register(&cpu->hw.clk); if (ret) { free(cpu); return ERR_PTR(ret); } - return &cpu->clk; + return &cpu->hw.clk; } enum zynq_cpu_subclk_which { @@ -265,7 +265,7 @@ enum zynq_cpu_subclk_which { }; struct zynq_cpu_subclk { - struct clk clk; + struct clk_hw hw; void __iomem *clk_ctrl; void __iomem *clk_621; enum zynq_cpu_subclk_which which; @@ -273,16 +273,16 @@ struct zynq_cpu_subclk { #define CLK_621_TRUE(x) ((x) & 1) -#define to_zynq_cpu_subclk(c) container_of(c, struct zynq_cpu_subclk, c); +#define to_zynq_cpu_subclk(c) container_of(c, struct zynq_cpu_subclk, hw); -static unsigned long zynq_cpu_subclk_recalc_rate(struct clk *clk, +static unsigned long zynq_cpu_subclk_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) { unsigned long uninitialized_var(rate); struct zynq_cpu_subclk *subclk; bool is_621; - subclk = to_zynq_cpu_subclk(clk); + subclk = to_zynq_cpu_subclk(hw); is_621 = CLK_621_TRUE(readl(subclk->clk_621)); switch (subclk->which) { @@ -303,12 +303,12 @@ static unsigned long zynq_cpu_subclk_recalc_rate(struct clk *clk, return rate; } -static int zynq_cpu_subclk_enable(struct clk *clk) +static int zynq_cpu_subclk_enable(struct clk_hw *hw) { struct zynq_cpu_subclk *subclk; u32 tmp; - subclk = to_zynq_cpu_subclk(clk); + subclk = to_zynq_cpu_subclk(hw); tmp = readl(subclk->clk_ctrl); tmp |= 1 << (24 + subclk->which); @@ -317,12 +317,12 @@ static int zynq_cpu_subclk_enable(struct clk *clk) return 0; } -static void zynq_cpu_subclk_disable(struct clk *clk) +static void zynq_cpu_subclk_disable(struct clk_hw *hw) { struct zynq_cpu_subclk *subclk; u32 tmp; - subclk = to_zynq_cpu_subclk(clk); + subclk = to_zynq_cpu_subclk(hw); tmp = readl(subclk->clk_ctrl); tmp &= ~(1 << (24 + subclk->which)); @@ -349,19 +349,19 @@ static struct clk *zynq_cpu_subclk(const char *name, subclk->clk_ctrl = clk_ctrl; subclk->clk_621 = clk_621; subclk->which = which; - subclk->clk.name = name; - subclk->clk.ops = &zynq_cpu_subclk_ops; + subclk->hw.clk.name = name; + subclk->hw.clk.ops = &zynq_cpu_subclk_ops; - subclk->clk.parent_names = &subclk_parent; - subclk->clk.num_parents = 1; + subclk->hw.clk.parent_names = &subclk_parent; + subclk->hw.clk.num_parents = 1; - ret = clk_register(&subclk->clk); + ret = bclk_register(&subclk->hw.clk); if (ret) { free(subclk); return ERR_PTR(ret); } - return &subclk->clk; + return &subclk->hw.clk; } static int zynq_clock_probe(struct device_d *dev) diff --git a/drivers/clk/zynqmp/clk-divider-zynqmp.c b/drivers/clk/zynqmp/clk-divider-zynqmp.c index 2fe65b566a..b96cab615b 100644 --- a/drivers/clk/zynqmp/clk-divider-zynqmp.c +++ b/drivers/clk/zynqmp/clk-divider-zynqmp.c @@ -16,14 +16,14 @@ #include "clk-zynqmp.h" struct zynqmp_clk_divider { - struct clk clk; + struct clk_hw hw; unsigned int clk_id; enum topology_type type; const char *parent; const struct zynqmp_eemi_ops *ops; }; -#define to_zynqmp_clk_divider(clk) \ - container_of(clk, struct zynqmp_clk_divider, clk) +#define to_zynqmp_clk_divider(_hw) \ + container_of(_hw, struct zynqmp_clk_divider, hw) static int zynqmp_clk_divider_bestdiv(unsigned long rate, unsigned long *best_parent_rate) @@ -31,10 +31,10 @@ static int zynqmp_clk_divider_bestdiv(unsigned long rate, return DIV_ROUND_CLOSEST(*best_parent_rate, rate); } -static unsigned long zynqmp_clk_divider_recalc_rate(struct clk *clk, +static unsigned long zynqmp_clk_divider_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) { - struct zynqmp_clk_divider *div = to_zynqmp_clk_divider(clk); + struct zynqmp_clk_divider *div = to_zynqmp_clk_divider(hw); u32 value; div->ops->clock_getdivider(div->clk_id, &value); @@ -46,7 +46,7 @@ static unsigned long zynqmp_clk_divider_recalc_rate(struct clk *clk, return DIV_ROUND_UP(parent_rate, value); } -static long zynqmp_clk_divider_round_rate(struct clk *clk, unsigned long rate, +static long zynqmp_clk_divider_round_rate(struct clk_hw *hw, unsigned long rate, unsigned long *parent_rate) { int bestdiv; @@ -56,10 +56,10 @@ static long zynqmp_clk_divider_round_rate(struct clk *clk, unsigned long rate, return *parent_rate / bestdiv; } -static int zynqmp_clk_divider_set_rate(struct clk *clk, unsigned long rate, +static int zynqmp_clk_divider_set_rate(struct clk_hw *hw, unsigned long rate, unsigned long parent_rate) { - struct zynqmp_clk_divider *div = to_zynqmp_clk_divider(clk); + struct zynqmp_clk_divider *div = to_zynqmp_clk_divider(hw); u32 bestdiv; bestdiv = zynqmp_clk_divider_bestdiv(rate, &parent_rate); @@ -95,17 +95,17 @@ struct clk *zynqmp_clk_register_divider(const char *name, div->ops = zynqmp_pm_get_eemi_ops(); div->parent = strdup(parents[0]); - div->clk.name = strdup(name); - div->clk.ops = &zynqmp_clk_divider_ops; - div->clk.flags = nodes->flag; - div->clk.parent_names = &div->parent; - div->clk.num_parents = 1; + div->hw.clk.name = strdup(name); + div->hw.clk.ops = &zynqmp_clk_divider_ops; + div->hw.clk.flags = nodes->flag; + div->hw.clk.parent_names = &div->parent; + div->hw.clk.num_parents = 1; - ret = clk_register(&div->clk); + ret = bclk_register(&div->hw.clk); if (ret) { kfree(div); return ERR_PTR(ret); } - return &div->clk; + return &div->hw.clk; } diff --git a/drivers/clk/zynqmp/clk-gate-zynqmp.c b/drivers/clk/zynqmp/clk-gate-zynqmp.c index 6f03357768..a3b9ee21e5 100644 --- a/drivers/clk/zynqmp/clk-gate-zynqmp.c +++ b/drivers/clk/zynqmp/clk-gate-zynqmp.c @@ -16,31 +16,31 @@ #include "clk-zynqmp.h" struct zynqmp_clk_gate { - struct clk clk; + struct clk_hw hw; unsigned int clk_id; const char *parent; const struct zynqmp_eemi_ops *ops; }; -#define to_zynqmp_clk_gate(_hw) container_of(_hw, struct zynqmp_clk_gate, clk) +#define to_zynqmp_clk_gate(_hw) container_of(_hw, struct zynqmp_clk_gate, hw) -static int zynqmp_clk_gate_enable(struct clk *clk) +static int zynqmp_clk_gate_enable(struct clk_hw *hw) { - struct zynqmp_clk_gate *gate = to_zynqmp_clk_gate(clk); + struct zynqmp_clk_gate *gate = to_zynqmp_clk_gate(hw); return gate->ops->clock_enable(gate->clk_id); } -static void zynqmp_clk_gate_disable(struct clk *clk) +static void zynqmp_clk_gate_disable(struct clk_hw *hw) { - struct zynqmp_clk_gate *gate = to_zynqmp_clk_gate(clk); + struct zynqmp_clk_gate *gate = to_zynqmp_clk_gate(hw); gate->ops->clock_disable(gate->clk_id); } -static int zynqmp_clk_gate_is_enabled(struct clk *clk) +static int zynqmp_clk_gate_is_enabled(struct clk_hw *hw) { - struct zynqmp_clk_gate *gate = to_zynqmp_clk_gate(clk); + struct zynqmp_clk_gate *gate = to_zynqmp_clk_gate(hw); u32 state; int ret; const struct zynqmp_eemi_ops *eemi_ops = zynqmp_pm_get_eemi_ops(); @@ -77,17 +77,17 @@ struct clk *zynqmp_clk_register_gate(const char *name, gate->ops = zynqmp_pm_get_eemi_ops(); gate->parent = strdup(parents[0]); - gate->clk.name = strdup(name); - gate->clk.ops = &zynqmp_clk_gate_ops; - gate->clk.flags = nodes->flag | CLK_SET_RATE_PARENT; - gate->clk.parent_names = &gate->parent; - gate->clk.num_parents = 1; + gate->hw.clk.name = strdup(name); + gate->hw.clk.ops = &zynqmp_clk_gate_ops; + gate->hw.clk.flags = nodes->flag | CLK_SET_RATE_PARENT; + gate->hw.clk.parent_names = &gate->parent; + gate->hw.clk.num_parents = 1; - ret = clk_register(&gate->clk); + ret = bclk_register(&gate->hw.clk); if (ret) { kfree(gate); return ERR_PTR(ret); } - return &gate->clk; + return &gate->hw.clk; } diff --git a/drivers/clk/zynqmp/clk-mux-zynqmp.c b/drivers/clk/zynqmp/clk-mux-zynqmp.c index 4c15223980..e7264375f5 100644 --- a/drivers/clk/zynqmp/clk-mux-zynqmp.c +++ b/drivers/clk/zynqmp/clk-mux-zynqmp.c @@ -18,17 +18,17 @@ #define ZYNQMP_CLK_MUX_READ_ONLY BIT(3) struct zynqmp_clk_mux { - struct clk clk; + struct clk_hw hw; u32 clk_id; const struct zynqmp_eemi_ops *ops; }; -#define to_zynqmp_clk_mux(clk) \ - container_of(clk, struct zynqmp_clk_mux, clk) +#define to_zynqmp_clk_mux(_hw) \ + container_of(_hw, struct zynqmp_clk_mux, hw) -static int zynqmp_clk_mux_get_parent(struct clk *clk) +static int zynqmp_clk_mux_get_parent(struct clk_hw *hw) { - struct zynqmp_clk_mux *mux = to_zynqmp_clk_mux(clk); + struct zynqmp_clk_mux *mux = to_zynqmp_clk_mux(hw); u32 value; mux->ops->clock_getparent(mux->clk_id, &value); @@ -36,9 +36,9 @@ static int zynqmp_clk_mux_get_parent(struct clk *clk) return value; } -static int zynqmp_clk_mux_set_parent(struct clk *clk, u8 index) +static int zynqmp_clk_mux_set_parent(struct clk_hw *hw, u8 index) { - struct zynqmp_clk_mux *mux = to_zynqmp_clk_mux(clk); + struct zynqmp_clk_mux *mux = to_zynqmp_clk_mux(hw); return mux->ops->clock_setparent(mux->clk_id, index); } @@ -82,21 +82,21 @@ struct clk *zynqmp_clk_register_mux(const char *name, mux->clk_id = clk_id; mux->ops = zynqmp_pm_get_eemi_ops(); - mux->clk.name = strdup(name); + mux->hw.clk.name = strdup(name); if (nodes->type_flag & ZYNQMP_CLK_MUX_READ_ONLY) - mux->clk.ops = &zynqmp_clk_mux_ro_ops; + mux->hw.clk.ops = &zynqmp_clk_mux_ro_ops; else - mux->clk.ops = &zynqmp_clk_mux_ops; - mux->clk.flags = nodes->flag | CLK_SET_RATE_PARENT; - mux->clk.parent_names = parent_names; - mux->clk.num_parents = num_parents; + mux->hw.clk.ops = &zynqmp_clk_mux_ops; + mux->hw.clk.flags = nodes->flag | CLK_SET_RATE_PARENT; + mux->hw.clk.parent_names = parent_names; + mux->hw.clk.num_parents = num_parents; - ret = clk_register(&mux->clk); + ret = bclk_register(&mux->hw.clk); if (ret) { kfree(parent_names); kfree(mux); return ERR_PTR(ret); } - return &mux->clk; + return &mux->hw.clk; } diff --git a/drivers/clk/zynqmp/clk-pll-zynqmp.c b/drivers/clk/zynqmp/clk-pll-zynqmp.c index e4b759b73c..2e24d9d01c 100644 --- a/drivers/clk/zynqmp/clk-pll-zynqmp.c +++ b/drivers/clk/zynqmp/clk-pll-zynqmp.c @@ -16,14 +16,14 @@ #include "clk-zynqmp.h" struct zynqmp_pll { - struct clk clk; + struct clk_hw hw; unsigned int clk_id; const char *parent; const struct zynqmp_eemi_ops *ops; }; -#define to_zynqmp_pll(clk) \ - container_of(clk, struct zynqmp_pll, clk) +#define to_zynqmp_pll(_hw) \ + container_of(_hw, struct zynqmp_pll, hw) #define PLL_FBDIV_MIN 25 #define PLL_FBDIV_MAX 125 @@ -53,10 +53,10 @@ static inline void zynqmp_pll_set_mode(struct zynqmp_pll *pll, enum pll_mode mod pll->ops->ioctl(0, IOCTL_SET_PLL_FRAC_MODE, pll->clk_id, mode, NULL); } -static long zynqmp_pll_round_rate(struct clk *clk, unsigned long rate, +static long zynqmp_pll_round_rate(struct clk_hw *hw, unsigned long rate, unsigned long *prate) { - struct zynqmp_pll *pll = to_zynqmp_pll(clk); + struct zynqmp_pll *pll = to_zynqmp_pll(hw); u32 fbdiv; long rate_div; @@ -84,10 +84,10 @@ static long zynqmp_pll_round_rate(struct clk *clk, unsigned long rate, return rate; } -static unsigned long zynqmp_pll_recalc_rate(struct clk *clk, +static unsigned long zynqmp_pll_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) { - struct zynqmp_pll *pll = to_zynqmp_pll(clk); + struct zynqmp_pll *pll = to_zynqmp_pll(hw); u32 clk_id = pll->clk_id; u32 fbdiv, data; unsigned long rate, frac; @@ -109,10 +109,10 @@ static unsigned long zynqmp_pll_recalc_rate(struct clk *clk, return rate; } -static int zynqmp_pll_set_rate(struct clk *clk, unsigned long rate, +static int zynqmp_pll_set_rate(struct clk_hw *hw, unsigned long rate, unsigned long parent_rate) { - struct zynqmp_pll *pll = to_zynqmp_pll(clk); + struct zynqmp_pll *pll = to_zynqmp_pll(hw); u32 clk_id = pll->clk_id; u32 fbdiv; long rate_div, frac, m, f; @@ -138,9 +138,9 @@ static int zynqmp_pll_set_rate(struct clk *clk, unsigned long rate, } } -static int zynqmp_pll_is_enabled(struct clk *clk) +static int zynqmp_pll_is_enabled(struct clk_hw *hw) { - struct zynqmp_pll *pll = to_zynqmp_pll(clk); + struct zynqmp_pll *pll = to_zynqmp_pll(hw); u32 is_enabled; int ret; @@ -151,21 +151,21 @@ static int zynqmp_pll_is_enabled(struct clk *clk) return !!(is_enabled); } -static int zynqmp_pll_enable(struct clk *clk) +static int zynqmp_pll_enable(struct clk_hw *hw) { - struct zynqmp_pll *pll = to_zynqmp_pll(clk); + struct zynqmp_pll *pll = to_zynqmp_pll(hw); - if (zynqmp_pll_is_enabled(clk)) + if (zynqmp_pll_is_enabled(hw)) return 0; return pll->ops->clock_enable(pll->clk_id); } -static void zynqmp_pll_disable(struct clk *clk) +static void zynqmp_pll_disable(struct clk_hw *hw) { - struct zynqmp_pll *pll = to_zynqmp_pll(clk); + struct zynqmp_pll *pll = to_zynqmp_pll(hw); - if (!zynqmp_pll_is_enabled(clk)) + if (!zynqmp_pll_is_enabled(hw)) return; pll->ops->clock_disable(pll->clk_id); @@ -197,17 +197,17 @@ struct clk *zynqmp_clk_register_pll(const char *name, pll->ops = zynqmp_pm_get_eemi_ops(); pll->parent = strdup(parents[0]); - pll->clk.name = strdup(name); - pll->clk.ops = &zynqmp_pll_ops; - pll->clk.flags = nodes->flag | CLK_SET_RATE_PARENT; - pll->clk.parent_names = &pll->parent; - pll->clk.num_parents = 1; + pll->hw.clk.name = strdup(name); + pll->hw.clk.ops = &zynqmp_pll_ops; + pll->hw.clk.flags = nodes->flag | CLK_SET_RATE_PARENT; + pll->hw.clk.parent_names = &pll->parent; + pll->hw.clk.num_parents = 1; - ret = clk_register(&pll->clk); + ret = bclk_register(&pll->hw.clk); if (ret) { kfree(pll); return ERR_PTR(ret); } - return &pll->clk; + return &pll->hw.clk; } diff --git a/drivers/clk/zynqmp/clkc.c b/drivers/clk/zynqmp/clkc.c index 366a12e70a..86d85b6daa 100644 --- a/drivers/clk/zynqmp/clkc.c +++ b/drivers/clk/zynqmp/clkc.c @@ -453,7 +453,7 @@ static int zynqmp_register_clocks(struct device_d *dev, const char *parent_names[MAX_PARENT]; char *name; struct device_node *node = dev->device_node; - unsigned int num_parents; + int num_parents; for (i = 0; i < num_clocks; i++) { if (zynqmp_get_clock_type(i) != CLK_TYPE_OUTPUT) diff --git a/drivers/eeprom/at24.c b/drivers/eeprom/at24.c index 8c04c5684b..1d35088c6b 100644 --- a/drivers/eeprom/at24.c +++ b/drivers/eeprom/at24.c @@ -245,12 +245,9 @@ static ssize_t at24_read(struct at24_data *at24, return retval; } -static int at24_nvmem_read(struct device_d *dev, int off, - void *buf, int count) +static int at24_nvmem_read(void *ctx, unsigned off, void *buf, size_t count) { - struct at24_data *at24 = dev->parent->priv; - - return at24_read(at24, buf, off, count); + return at24_read(ctx, buf, off, count); } /* @@ -363,12 +360,9 @@ static ssize_t at24_write(struct at24_data *at24, const char *buf, loff_t off, return retval; } -static int at24_nvmem_write(struct device_d *dev, const int off, - const void *buf, int count) +static int at24_nvmem_write(void *ctx, unsigned off, const void *buf, size_t count) { - struct at24_data *at24 = dev->parent->priv; - - return at24_write(at24, buf, off, count); + return at24_write(ctx, buf, off, count); } static const struct nvmem_bus at24_nvmem_bus = { @@ -495,14 +489,13 @@ static int at24_probe(struct device_d *dev) at24->nvmem_config.name = devname; at24->nvmem_config.dev = dev; + at24->nvmem_config.priv = at24; at24->nvmem_config.read_only = !writable; at24->nvmem_config.bus = &at24_nvmem_bus; at24->nvmem_config.stride = 1; at24->nvmem_config.word_size = 1; at24->nvmem_config.size = chip.byte_len; - dev->priv = at24; - at24->nvmem = nvmem_register(&at24->nvmem_config); err = PTR_ERR_OR_ZERO(at24->nvmem); if (err) diff --git a/drivers/gpio/gpio-davinci.c b/drivers/gpio/gpio-davinci.c index 20311d968b..b4f2176606 100644 --- a/drivers/gpio/gpio-davinci.c +++ b/drivers/gpio/gpio-davinci.c @@ -13,9 +13,6 @@ #include <io.h> #include <linux/err.h> -#define readl_relaxed readl -#define writel_relaxed writel - struct davinci_gpio_regs { u32 dir; u32 out_data; diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 7b7261d01f..387b410f12 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -555,27 +555,39 @@ static int of_gpiochip_scan_hogs(struct gpio_chip *chip) return 0; } +static const char *gpio_suffixes[] = { + "gpios", + "gpio", +}; + /* Linux compatibility helper: Get a GPIO descriptor from device tree */ int gpiod_get(struct device_d *dev, const char *_con_id, enum gpiod_flags flags) { struct device_node *np = dev->device_node; enum of_gpio_flags of_flags; - const char *con_id = "gpios", *label = dev_name(dev); - char *buf = NULL; + const char *label = dev_name(dev); + char *buf = NULL, *con_id; int gpio; - int ret; + int ret, i; if (!IS_ENABLED(CONFIG_OFDEVICE) || !dev->device_node) return -ENODEV; - if (_con_id) { - con_id = buf = basprintf("%s-gpios", _con_id); - if (!buf) + for (i = 0; i < ARRAY_SIZE(gpio_suffixes); i++) { + if (_con_id) + con_id = basprintf("%s-%s", _con_id, gpio_suffixes[i]); + else + con_id = basprintf("%s", gpio_suffixes[i]); + + if (!con_id) return -ENOMEM; - } - gpio = of_get_named_gpio_flags(np, con_id, 0, &of_flags); - free(buf); + gpio = of_get_named_gpio_flags(np, con_id, 0, &of_flags); + free(con_id); + + if (gpio_is_valid(gpio)) + break; + } if (!gpio_is_valid(gpio)) return gpio < 0 ? gpio : -EINVAL; diff --git a/drivers/i2c/busses/i2c-designware.c b/drivers/i2c/busses/i2c-designware.c index bb9a0b7c4a..8508fac717 100644 --- a/drivers/i2c/busses/i2c-designware.c +++ b/drivers/i2c/busses/i2c-designware.c @@ -274,7 +274,7 @@ static void i2c_dw_setup_timings(struct dw_i2c_dev *dw) if (!(dw->sda_hold_time & DW_IC_SDA_HOLD_RX_MASK)) dw->sda_hold_time |= 1 << DW_IC_SDA_HOLD_RX_SHIFT; - dev_dbg(&dw->adapter.dev, "adjust SDA hold time.\n"); + dev_dbg(dw->adapter.dev.parent, "adjust SDA hold time.\n"); writel(dw->sda_hold_time, dw->base + DW_IC_SDA_HOLD); } } @@ -547,9 +547,7 @@ static int i2c_dw_probe(struct device_d *pdev) ic_comp_type_value = readl(dw->base + DW_IC_COMP_TYPE); if (ic_comp_type_value != DW_IC_COMP_TYPE_VALUE) { - dev_err(pdev, - "unknown DesignWare IP block 0x%08x", - ic_comp_type_value); + dev_err(pdev, "unknown DesignWare IP block 0x%08x\n", ic_comp_type_value); ret = -ENODEV; goto fail; } @@ -574,7 +572,7 @@ static int i2c_dw_probe(struct device_d *pdev) ic_con = DW_IC_CON_SPEED_FAST; break; default: - dev_warn(pdev, "requested bitrate (%d) is not supported." + dev_warn(pdev, "requested bitrate (%d) is not supported.\n" " Falling back to 100kHz", bitrate); case 100000: /* FALLTHROUGH */ ic_con = DW_IC_CON_SPEED_STD; diff --git a/drivers/mci/Kconfig b/drivers/mci/Kconfig index 7d4e72138d..e1fcd41271 100644 --- a/drivers/mci/Kconfig +++ b/drivers/mci/Kconfig @@ -79,6 +79,13 @@ config MCI_MXS Enable this entry to add support to read and write SD cards on a i.MX23/i.MX28 based system. +config MCI_ROCKCHIP_DWCMSHC + bool "MCI sdhc support for Rockchip SoCs" + select MCI_SDHCI + help + Enable this entry to add support for a Rockchip derivation of the + DWCMSHC controller found on some Rockchip SoCs like the RK3568. + config MCI_S3C bool "S3C" depends on ARCH_S3C24xx diff --git a/drivers/mci/Makefile b/drivers/mci/Makefile index 60dc100c37..b113b1c732 100644 --- a/drivers/mci/Makefile +++ b/drivers/mci/Makefile @@ -14,6 +14,7 @@ obj-$(CONFIG_MCI_MXS) += mxs.o obj-$(CONFIG_MCI_OMAP_HSMMC) += omap_hsmmc.o obj-$(CONFIG_MCI_PXA) += pxamci.o obj-$(CONFIG_MCI_S3C) += s3c.o +obj-$(CONFIG_MCI_ROCKCHIP_DWCMSHC) += rockchip-dwcmshc-sdhci.o obj-$(CONFIG_MCI_TEGRA) += tegra-sdmmc.o obj-$(CONFIG_MCI_SPI) += mci_spi.o obj-$(CONFIG_MCI_DW) += dw_mmc.o diff --git a/drivers/mci/arasan-sdhci.c b/drivers/mci/arasan-sdhci.c index 520bf30ff9..d45f9184cd 100644 --- a/drivers/mci/arasan-sdhci.c +++ b/drivers/mci/arasan-sdhci.c @@ -12,20 +12,20 @@ #define SDHCI_ARASAN_HCAP_CLK_FREQ_MASK 0xFF00 #define SDHCI_ARASAN_HCAP_CLK_FREQ_SHIFT 8 #define SDHCI_INT_ADMAE BIT(29) -#define SDHCI_ARASAN_INT_DATA_MASK SDHCI_INT_XFER_COMPLETE | \ +#define SDHCI_ARASAN_INT_DATA_MASK (SDHCI_INT_XFER_COMPLETE | \ SDHCI_INT_DMA | \ SDHCI_INT_SPACE_AVAIL | \ SDHCI_INT_DATA_AVAIL | \ SDHCI_INT_DATA_TIMEOUT | \ SDHCI_INT_DATA_CRC | \ SDHCI_INT_DATA_END_BIT | \ - SDHCI_INT_ADMAE + SDHCI_INT_ADMAE) -#define SDHCI_ARASAN_INT_CMD_MASK SDHCI_INT_CMD_COMPLETE | \ +#define SDHCI_ARASAN_INT_CMD_MASK (SDHCI_INT_CMD_COMPLETE | \ SDHCI_INT_TIMEOUT | \ SDHCI_INT_CRC | \ SDHCI_INT_END_BIT | \ - SDHCI_INT_INDEX + SDHCI_INT_INDEX) #define SDHCI_ARASAN_BUS_WIDTH 4 #define TIMEOUT_VAL 0xE @@ -33,14 +33,12 @@ struct arasan_sdhci_host { struct mci_host mci; struct sdhci sdhci; - void __iomem *ioaddr; unsigned int quirks; /* Arasan deviations from spec */ /* Controller does not have CD wired and will not function normally without */ #define SDHCI_ARASAN_QUIRK_FORCE_CDTEST BIT(0) #define SDHCI_ARASAN_QUIRK_NO_1_8_V BIT(1) }; - static inline struct arasan_sdhci_host *to_arasan_sdhci_host(struct mci_host *mci) { @@ -53,60 +51,24 @@ struct arasan_sdhci_host *sdhci_to_arasan(struct sdhci *sdhci) return container_of(sdhci, struct arasan_sdhci_host, sdhci); } -static void arasan_sdhci_writel(struct sdhci *sdhci, int reg, u32 val) -{ - struct arasan_sdhci_host *p = sdhci_to_arasan(sdhci); - - writel(val, p->ioaddr + reg); -} - -static void arasan_sdhci_writew(struct sdhci *sdhci, int reg, u16 val) -{ - struct arasan_sdhci_host *p = sdhci_to_arasan(sdhci); - - writew(val, p->ioaddr + reg); -} - -static void arasan_sdhci_writeb(struct sdhci *sdhci, int reg, u8 val) -{ - struct arasan_sdhci_host *p = sdhci_to_arasan(sdhci); - - writeb(val, p->ioaddr + reg); -} - -static u32 arasan_sdhci_readl(struct sdhci *sdhci, int reg) -{ - struct arasan_sdhci_host *p = sdhci_to_arasan(sdhci); - - return readl(p->ioaddr + reg); -} - -static u16 arasan_sdhci_readw(struct sdhci *sdhci, int reg) -{ - struct arasan_sdhci_host *p = sdhci_to_arasan(sdhci); - - return readw(p->ioaddr + reg); -} - -static u8 arasan_sdhci_readb(struct sdhci *sdhci, int reg) -{ - struct arasan_sdhci_host *p = sdhci_to_arasan(sdhci); - - return readb(p->ioaddr + reg); -} - static int arasan_sdhci_card_present(struct mci_host *mci) { struct arasan_sdhci_host *host = to_arasan_sdhci_host(mci); + u32 val; + + val = sdhci_read32(&host->sdhci, SDHCI_PRESENT_STATE); - return !!(sdhci_read32(&host->sdhci, SDHCI_PRESENT_STATE) & SDHCI_CARD_DETECT); + return !!(val & SDHCI_CARD_DETECT); } static int arasan_sdhci_card_write_protected(struct mci_host *mci) { struct arasan_sdhci_host *host = to_arasan_sdhci_host(mci); + u32 val; - return !(sdhci_read32(&host->sdhci, SDHCI_PRESENT_STATE) & SDHCI_WRITE_PROTECT); + val = sdhci_read32(&host->sdhci, SDHCI_PRESENT_STATE); + + return !(val & SDHCI_WRITE_PROTECT); } static int arasan_sdhci_reset(struct arasan_sdhci_host *host, u8 mask) @@ -115,7 +77,7 @@ static int arasan_sdhci_reset(struct arasan_sdhci_host *host, u8 mask) /* wait for reset completion */ if (wait_on_timeout(100 * MSECOND, - !(sdhci_read8(&host->sdhci, SDHCI_SOFTWARE_RESET) & mask))){ + !(sdhci_read8(&host->sdhci, SDHCI_SOFTWARE_RESET) & mask))) { dev_err(host->mci.hw_dev, "SDHCI reset timeout\n"); return -ETIMEDOUT; } @@ -124,7 +86,7 @@ static int arasan_sdhci_reset(struct arasan_sdhci_host *host, u8 mask) u8 ctrl; ctrl = sdhci_read8(&host->sdhci, SDHCI_HOST_CONTROL); - ctrl |= SDHCI_CARD_DETECT_TEST_LEVEL | SDHCI_CARD_DETECT_SIGNAL_SELECTION; + ctrl |= SDHCI_CTRL_CDTEST_INS | SDHCI_CTRL_CDTEST_INS; sdhci_write8(&host->sdhci, ctrl, SDHCI_HOST_CONTROL); } @@ -141,82 +103,32 @@ static int arasan_sdhci_init(struct mci_host *mci, struct device_d *dev) return ret; sdhci_write8(&host->sdhci, SDHCI_POWER_CONTROL, - SDHCI_BUS_VOLTAGE_330 | SDHCI_BUS_POWER_EN); + SDHCI_BUS_VOLTAGE_330 | SDHCI_BUS_POWER_EN); udelay(400); sdhci_write32(&host->sdhci, SDHCI_INT_ENABLE, - SDHCI_ARASAN_INT_DATA_MASK | - SDHCI_ARASAN_INT_CMD_MASK); - sdhci_write32(&host->sdhci, SDHCI_SIGNAL_ENABLE, 0x00); + SDHCI_ARASAN_INT_DATA_MASK | SDHCI_ARASAN_INT_CMD_MASK); + sdhci_write32(&host->sdhci, SDHCI_SIGNAL_ENABLE, 0); return 0; } -#define SDHCI_MAX_DIV_SPEC_300 2046 - -static u16 arasan_sdhci_get_clock_divider(struct arasan_sdhci_host *host, - unsigned int reqclk) -{ - u16 div; - - for (div = 1; div < SDHCI_MAX_DIV_SPEC_300; div += 2) - if ((host->mci.f_max / div) <= reqclk) - break; - div /= 2; - - return div; -} - -#define SDHCI_FREQ_SEL_10_BIT(x) (((x) & 0x300) >> 2) - static void arasan_sdhci_set_ios(struct mci_host *mci, struct mci_ios *ios) { struct arasan_sdhci_host *host = to_arasan_sdhci_host(mci); u16 val; - /* stop clock */ - sdhci_write16(&host->sdhci, SDHCI_CLOCK_CONTROL, 0); - - if (ios->clock) { - u64 start; - - /* set & start clock */ - val = arasan_sdhci_get_clock_divider(host, ios->clock); - /* Bit 6 & 7 are upperbits of 10bit divider */ - val = SDHCI_FREQ_SEL(val) | SDHCI_FREQ_SEL_10_BIT(val); - val |= SDHCI_INTCLOCK_EN; - sdhci_write16(&host->sdhci, SDHCI_CLOCK_CONTROL, val); - - start = get_time_ns(); - while (!(sdhci_read16(&host->sdhci, SDHCI_CLOCK_CONTROL) & - SDHCI_INTCLOCK_STABLE)) { - if (is_timeout(start, 20 * MSECOND)) { - dev_err(host->mci.hw_dev, - "SDHCI clock stable timeout\n"); - return; - } - } - /* enable bus clock */ - sdhci_write16(&host->sdhci, SDHCI_CLOCK_CONTROL, - val | SDHCI_SDCLOCK_EN); - } + if (ios->clock) + sdhci_set_clock(&host->sdhci, ios->clock, host->sdhci.max_clk); - val = sdhci_read8(&host->sdhci, SDHCI_HOST_CONTROL) & - ~(SDHCI_DATA_WIDTH_4BIT | SDHCI_DATA_WIDTH_8BIT); + sdhci_set_bus_width(&host->sdhci, ios->bus_width); - switch (ios->bus_width) { - case MMC_BUS_WIDTH_8: - val |= SDHCI_DATA_WIDTH_8BIT; - break; - case MMC_BUS_WIDTH_4: - val |= SDHCI_DATA_WIDTH_4BIT; - break; - } + val = sdhci_read8(&host->sdhci, SDHCI_HOST_CONTROL); if (ios->clock > 26000000) - val |= SDHCI_HIGHSPEED_EN; + val |= SDHCI_CTRL_HISPD; else - val &= ~SDHCI_HIGHSPEED_EN; + val &= ~SDHCI_CTRL_HISPD; sdhci_write8(&host->sdhci, SDHCI_HOST_CONTROL, val); } @@ -225,18 +137,21 @@ static int arasan_sdhci_wait_for_done(struct arasan_sdhci_host *host, u32 mask) { u64 start = get_time_ns(); u16 stat; + u16 error; do { stat = sdhci_read16(&host->sdhci, SDHCI_INT_NORMAL_STATUS); if (stat & SDHCI_INT_ERROR) { + error = sdhci_read16(&host->sdhci, + SDHCI_INT_ERROR_STATUS); dev_err(host->mci.hw_dev, "SDHCI_INT_ERROR: 0x%08x\n", - sdhci_read16(&host->sdhci, SDHCI_INT_ERROR_STATUS)); + error); return -EPERM; } if (is_timeout(start, 1000 * MSECOND)) { dev_err(host->mci.hw_dev, - "SDHCI timeout while waiting for done\n"); + "SDHCI timeout while waiting for done\n"); return -ETIMEDOUT; } } while ((stat & mask) != mask); @@ -247,7 +162,7 @@ static int arasan_sdhci_wait_for_done(struct arasan_sdhci_host *host, u32 mask) static void print_error(struct arasan_sdhci_host *host, int cmdidx) { dev_err(host->mci.hw_dev, - "error while transfering data for command %d\n", cmdidx); + "error while transferring data for command %d\n", cmdidx); dev_err(host->mci.hw_dev, "state = 0x%08x , interrupt = 0x%08x\n", sdhci_read32(&host->sdhci, SDHCI_PRESENT_STATE), sdhci_read32(&host->sdhci, SDHCI_INT_NORMAL_STATUS)); @@ -266,27 +181,31 @@ static int arasan_sdhci_send_cmd(struct mci_host *mci, struct mci_cmd *cmd, mask |= SDHCI_CMD_INHIBIT_DATA; ret = wait_on_timeout(10 * MSECOND, - !(sdhci_read32(&host->sdhci, SDHCI_PRESENT_STATE) & mask)); - + !(sdhci_read32(&host->sdhci, SDHCI_PRESENT_STATE) & mask)); if (ret) { dev_err(host->mci.hw_dev, - "SDHCI timeout while waiting for idle\n"); + "SDHCI timeout while waiting for idle\n"); return ret; } sdhci_write32(&host->sdhci, SDHCI_INT_STATUS, ~0); mask = SDHCI_INT_CMD_COMPLETE; - if (data) + if (data && data->flags == MMC_DATA_READ) mask |= SDHCI_INT_DATA_AVAIL; + if (cmd->resp_type & MMC_RSP_BUSY) + mask |= SDHCI_INT_XFER_COMPLETE; - sdhci_set_cmd_xfer_mode(&host->sdhci, cmd, data, false, &command, &xfer); + sdhci_set_cmd_xfer_mode(&host->sdhci, + cmd, data, false, &command, &xfer); sdhci_write8(&host->sdhci, SDHCI_TIMEOUT_CONTROL, TIMEOUT_VAL); - sdhci_write16(&host->sdhci, SDHCI_TRANSFER_MODE, xfer); - sdhci_write16(&host->sdhci, SDHCI_BLOCK_SIZE, SDHCI_DMA_BOUNDARY_512K | - SDHCI_TRANSFER_BLOCK_SIZE(data->blocksize)); - sdhci_write16(&host->sdhci, SDHCI_BLOCK_COUNT, data->blocks); + if (data) { + sdhci_write16(&host->sdhci, SDHCI_TRANSFER_MODE, xfer); + sdhci_write16(&host->sdhci, SDHCI_BLOCK_SIZE, + SDHCI_DMA_BOUNDARY_512K | SDHCI_TRANSFER_BLOCK_SIZE(data->blocksize)); + sdhci_write16(&host->sdhci, SDHCI_BLOCK_COUNT, data->blocks); + } sdhci_write32(&host->sdhci, SDHCI_ARGUMENT, cmd->cmdarg); sdhci_write16(&host->sdhci, SDHCI_COMMAND, command); @@ -300,7 +219,7 @@ static int arasan_sdhci_send_cmd(struct mci_host *mci, struct mci_cmd *cmd, sdhci_write32(&host->sdhci, SDHCI_INT_STATUS, mask); if (data) - ret = sdhci_transfer_data(&host->sdhci, data); + ret = sdhci_transfer_data_pio(&host->sdhci, data); error: if (ret) { @@ -310,33 +229,8 @@ error: } sdhci_write32(&host->sdhci, SDHCI_INT_STATUS, ~0); - return ret; -} - - -static void arasan_sdhci_set_mci_caps(struct arasan_sdhci_host *host) -{ - u16 caps = sdhci_read16(&host->sdhci, SDHCI_CAPABILITIES_1); - - if ((caps & SDHCI_HOSTCAP_VOLTAGE_180) && - !(host->quirks & SDHCI_ARASAN_QUIRK_NO_1_8_V)) - host->mci.voltages |= MMC_VDD_165_195; - if (caps & SDHCI_HOSTCAP_VOLTAGE_300) - host->mci.voltages |= MMC_VDD_29_30 | MMC_VDD_30_31; - if (caps & SDHCI_HOSTCAP_VOLTAGE_330) - host->mci.voltages |= MMC_VDD_32_33 | MMC_VDD_33_34; - if (caps & SDHCI_HOSTCAP_HIGHSPEED) - host->mci.host_caps |= (MMC_CAP_MMC_HIGHSPEED_52MHZ | - MMC_CAP_MMC_HIGHSPEED | - MMC_CAP_SD_HIGHSPEED); - - /* parse board supported bus width capabilities */ - mci_of_parse(&host->mci); - - /* limit bus widths to controller capabilities */ - if (!(caps & SDHCI_HOSTCAP_8BIT)) - host->mci.host_caps &= ~MMC_CAP_8_BIT_DATA; + return ret; } static int arasan_sdhci_probe(struct device_d *dev) @@ -355,7 +249,6 @@ static int arasan_sdhci_probe(struct device_d *dev) iores = dev_request_mem_resource(dev, 0); if (IS_ERR(iores)) return PTR_ERR(iores); - arasan_sdhci->ioaddr = IOMEM(iores->start); clk_ahb = clk_get(dev, "clk_ahb"); if (IS_ERR(clk_ahb)) { @@ -387,12 +280,8 @@ static int arasan_sdhci_probe(struct device_d *dev) if (of_property_read_bool(np, "no-1-8-v")) arasan_sdhci->quirks |= SDHCI_ARASAN_QUIRK_NO_1_8_V; - arasan_sdhci->sdhci.read32 = arasan_sdhci_readl; - arasan_sdhci->sdhci.read16 = arasan_sdhci_readw; - arasan_sdhci->sdhci.read8 = arasan_sdhci_readb; - arasan_sdhci->sdhci.write32 = arasan_sdhci_writel; - arasan_sdhci->sdhci.write16 = arasan_sdhci_writew; - arasan_sdhci->sdhci.write8 = arasan_sdhci_writeb; + arasan_sdhci->sdhci.base = IOMEM(iores->start); + arasan_sdhci->sdhci.mci = mci; mci->send_cmd = arasan_sdhci_send_cmd; mci->set_ios = arasan_sdhci_set_ios; mci->init = arasan_sdhci_init; @@ -403,7 +292,10 @@ static int arasan_sdhci_probe(struct device_d *dev) mci->f_max = clk_get_rate(clk_xin); mci->f_min = 50000000 / 256; - arasan_sdhci_set_mci_caps(arasan_sdhci); + /* parse board supported bus width capabilities */ + mci_of_parse(&arasan_sdhci->mci); + + sdhci_setup_host(&arasan_sdhci->sdhci); dev->priv = arasan_sdhci; diff --git a/drivers/mci/atmel-sdhci-common.c b/drivers/mci/atmel-sdhci-common.c index a83610c3d0..eff2a993db 100644 --- a/drivers/mci/atmel-sdhci-common.c +++ b/drivers/mci/atmel-sdhci-common.c @@ -11,6 +11,7 @@ #include <common.h> #include <mci.h> +#include <linux/bitfield.h> #include <mach/early_udelay.h> @@ -24,8 +25,6 @@ #include "atmel-sdhci.h" -#define AT91_SDHCI_CA1R 0x44 /* Capabilities 1 Register */ - #define AT91_SDHCI_MC1R 0x204 #define AT91_SDHCI_MC1_FCD BIT(7) #define AT91_SDHCI_CALCR 0x240 @@ -42,13 +41,13 @@ void at91_sdhci_host_capability(struct at91_sdhci *host, { u16 caps; - caps = sdhci_read16(&host->sdhci, SDHCI_CAPABILITIES_1); + caps = sdhci_read32(&host->sdhci, SDHCI_CAPABILITIES); - if (caps & SDHCI_HOSTCAP_VOLTAGE_330) + if (caps & SDHCI_CAN_VDD_330) *voltages |= MMC_VDD_32_33 | MMC_VDD_33_34; - if (caps & SDHCI_HOSTCAP_VOLTAGE_300) + if (caps & SDHCI_CAN_VDD_300) *voltages |= MMC_VDD_29_30 | MMC_VDD_30_31; - if (caps & SDHCI_HOSTCAP_VOLTAGE_180) + if (caps & SDHCI_CAN_VDD_180) *voltages |= MMC_VDD_165_195; } @@ -167,7 +166,7 @@ int at91_sdhci_send_command(struct at91_sdhci *host, struct mci_cmd *cmd, sdhci_write32(sdhci, SDHCI_INT_STATUS, mask); if (data) - sdhci_transfer_data(sdhci, data); + sdhci_transfer_data_pio(sdhci, data); udelay(1000); @@ -237,9 +236,9 @@ static int at91_sdhci_set_clock(struct at91_sdhci *host, unsigned clock) if (clock == 0) return 0; - caps = sdhci_read32(sdhci, AT91_SDHCI_CA1R); + caps = sdhci_read32(sdhci, SDHCI_CAPABILITIES_1); - caps_clk_mult = (caps & SDHCI_CLOCK_MUL_MASK) >> SDHCI_CLOCK_MUL_SHIFT; + caps_clk_mult = FIELD_GET(SDHCI_CLOCK_MUL_MASK, caps); if (caps_clk_mult) { for (clk_div = 1; clk_div <= 1024; clk_div++) { @@ -264,26 +263,26 @@ static int at91_sdhci_set_clock(struct at91_sdhci *host, unsigned clock) clk |= SDHCI_FREQ_SEL(clk_div); clk |= ((clk_div & SDHCI_DIV_HI_MASK) >> SDHCI_DIV_MASK_LEN) << SDHCI_DIVIDER_HI_SHIFT; - clk |= SDHCI_INTCLOCK_EN; + clk |= SDHCI_CLOCK_INT_EN; sdhci_write16(sdhci, SDHCI_CLOCK_CONTROL, clk); ret = sdhci_read32_poll_timeout(sdhci, SDHCI_CLOCK_CONTROL, clk, - clk & SDHCI_INTCLOCK_STABLE, + clk & SDHCI_CLOCK_INT_STABLE, 20 * USEC_PER_MSEC); if (ret) { dev_warn(host->dev, "Timeout waiting for clock stable\n"); return ret; } - clk |= SDHCI_SDCLOCK_EN; + clk |= SDHCI_CLOCK_CARD_EN; sdhci_write16(sdhci, SDHCI_CLOCK_CONTROL, clk); reg = sdhci_read8(sdhci, SDHCI_HOST_CONTROL); if (clock > 26000000) - reg |= SDHCI_HIGHSPEED_EN; + reg |= SDHCI_CTRL_HISPD; else - reg &= ~SDHCI_HIGHSPEED_EN; + reg &= ~SDHCI_CTRL_HISPD; sdhci_write8(sdhci, SDHCI_HOST_CONTROL, reg); @@ -299,15 +298,15 @@ static int at91_sdhci_set_bus_width(struct at91_sdhci *host, unsigned bus_width) switch(bus_width) { case MMC_BUS_WIDTH_8: - reg |= SDHCI_DATA_WIDTH_8BIT; + reg |= SDHCI_CTRL_8BITBUS; break; case MMC_BUS_WIDTH_4: - reg &= ~SDHCI_DATA_WIDTH_8BIT; - reg |= SDHCI_DATA_WIDTH_4BIT; + reg &= ~SDHCI_CTRL_8BITBUS; + reg |= SDHCI_CTRL_8BITBUS; break; default: - reg &= ~SDHCI_DATA_WIDTH_8BIT; - reg &= ~SDHCI_DATA_WIDTH_4BIT; + reg &= ~SDHCI_CTRL_8BITBUS; + reg &= ~SDHCI_CTRL_8BITBUS; } sdhci_write8(sdhci, SDHCI_HOST_CONTROL, reg); @@ -379,43 +378,7 @@ int at91_sdhci_init(struct at91_sdhci *host, u32 maxclk, return 0; } -static u32 at91_sdhci_read32(struct sdhci *sdhci, int reg) -{ - return readl(to_priv(sdhci)->base + reg); -} - -static void at91_sdhci_write32(struct sdhci *sdhci, int reg, u32 value) -{ - writel(value, to_priv(sdhci)->base + reg); -} - -static u16 at91_sdhci_read16(struct sdhci *sdhci, int reg) -{ - return readw(to_priv(sdhci)->base + reg); -} - -static void at91_sdhci_write16(struct sdhci *sdhci, int reg, u16 value) -{ - writew(value, to_priv(sdhci)->base + reg); -} - -static u8 at91_sdhci_read8(struct sdhci *sdhci, int reg) -{ - return readb(to_priv(sdhci)->base + reg); -} - -static void at91_sdhci_write8(struct sdhci *sdhci, int reg, u8 value) -{ - writeb(value, to_priv(sdhci)->base + reg); -} - void at91_sdhci_mmio_init(struct at91_sdhci *host, void __iomem *base) { - host->base = base; - host->sdhci.read8 = at91_sdhci_read8; - host->sdhci.read16 = at91_sdhci_read16; - host->sdhci.read32 = at91_sdhci_read32; - host->sdhci.write8 = at91_sdhci_write8; - host->sdhci.write16 = at91_sdhci_write16; - host->sdhci.write32 = at91_sdhci_write32; + host->sdhci.base = base; } diff --git a/drivers/mci/dove-sdhci.c b/drivers/mci/dove-sdhci.c index c734a6e0dd..e6ac769bde 100644 --- a/drivers/mci/dove-sdhci.c +++ b/drivers/mci/dove-sdhci.c @@ -20,55 +20,12 @@ struct dove_sdhci { struct mci_host mci; - void __iomem *base; struct sdhci sdhci; }; #define priv_from_mci_host(h) \ container_of(h, struct dove_sdhci, mci); -static void dove_sdhci_writel(struct sdhci *sdhci, int reg, u32 val) -{ - struct dove_sdhci *p = container_of(sdhci, struct dove_sdhci, sdhci); - - writel(val, p->base + reg); -} - -static void dove_sdhci_writew(struct sdhci *sdhci, int reg, u16 val) -{ - struct dove_sdhci *p = container_of(sdhci, struct dove_sdhci, sdhci); - - writew(val, p->base + reg); -} - -static void dove_sdhci_writeb(struct sdhci *sdhci, int reg, u8 val) -{ - struct dove_sdhci *p = container_of(sdhci, struct dove_sdhci, sdhci); - - writeb(val, p->base + reg); -} - -static u32 dove_sdhci_readl(struct sdhci *sdhci, int reg) -{ - struct dove_sdhci *p = container_of(sdhci, struct dove_sdhci, sdhci); - - return readl(p->base + reg); -} - -static u16 dove_sdhci_readw(struct sdhci *sdhci, int reg) -{ - struct dove_sdhci *p = container_of(sdhci, struct dove_sdhci, sdhci); - - return readw(p->base + reg); -} - -static u8 dove_sdhci_readb(struct sdhci *sdhci, int reg) -{ - struct dove_sdhci *p = container_of(sdhci, struct dove_sdhci, sdhci); - - return readb(p->base + reg); -} - static int dove_sdhci_wait_for_done(struct dove_sdhci *host, u16 mask) { u16 status; @@ -197,7 +154,7 @@ static u16 dove_sdhci_get_clock_divider(struct dove_sdhci *host, u32 reqclk) { u16 div; - for (div = 1; div < SDHCI_SPEC_200_MAX_CLK_DIVIDER; div *= 2) + for (div = 1; div < SDHCI_MAX_DIV_SPEC_200; div *= 2) if ((host->mci.f_max / div) <= reqclk) break; div /= 2; @@ -224,33 +181,33 @@ static void dove_sdhci_mci_set_ios(struct mci_host *mci, struct mci_ios *ios) /* set bus width */ val = sdhci_read8(&host->sdhci, SDHCI_HOST_CONTROL) & - ~(SDHCI_DATA_WIDTH_4BIT | SDHCI_DATA_WIDTH_8BIT); + ~(SDHCI_CTRL_8BITBUS | SDHCI_CTRL_8BITBUS); switch (ios->bus_width) { case MMC_BUS_WIDTH_8: - val |= SDHCI_DATA_WIDTH_8BIT; + val |= SDHCI_CTRL_8BITBUS; break; case MMC_BUS_WIDTH_4: - val |= SDHCI_DATA_WIDTH_4BIT; + val |= SDHCI_CTRL_8BITBUS; break; } if (ios->clock > 26000000) - val |= SDHCI_HIGHSPEED_EN; + val |= SDHCI_CTRL_HISPD; else - val &= ~SDHCI_HIGHSPEED_EN; + val &= ~SDHCI_CTRL_HISPD; sdhci_write8(&host->sdhci, SDHCI_HOST_CONTROL, val); /* set bus clock */ sdhci_write16(&host->sdhci, SDHCI_CLOCK_CONTROL, 0); val = dove_sdhci_get_clock_divider(host, ios->clock); - val = SDHCI_INTCLOCK_EN | SDHCI_FREQ_SEL(val); + val = SDHCI_CLOCK_INT_EN | SDHCI_FREQ_SEL(val); sdhci_write16(&host->sdhci, SDHCI_CLOCK_CONTROL, val); /* wait for internal clock stable */ start = get_time_ns(); while (!(sdhci_read16(&host->sdhci, SDHCI_CLOCK_CONTROL) & - SDHCI_INTCLOCK_STABLE)) { + SDHCI_CLOCK_INT_STABLE)) { if (is_timeout(start, 20 * MSECOND)) { dev_err(host->mci.hw_dev, "SDHCI clock stable timeout\n"); return; @@ -258,7 +215,7 @@ static void dove_sdhci_mci_set_ios(struct mci_host *mci, struct mci_ios *ios) } /* enable bus clock */ - sdhci_write16(&host->sdhci, SDHCI_CLOCK_CONTROL, val | SDHCI_SDCLOCK_EN); + sdhci_write16(&host->sdhci, SDHCI_CLOCK_CONTROL, val | SDHCI_CLOCK_CARD_EN); } static int dove_sdhci_mci_init(struct mci_host *mci, struct device_d *dev) @@ -290,19 +247,18 @@ static int dove_sdhci_mci_init(struct mci_host *mci, struct device_d *dev) static void dove_sdhci_set_mci_caps(struct dove_sdhci *host) { - u16 caps[2]; + u32 caps; - caps[0] = sdhci_read16(&host->sdhci, SDHCI_CAPABILITIES); - caps[1] = sdhci_read16(&host->sdhci, SDHCI_CAPABILITIES_1); + caps = sdhci_read32(&host->sdhci, SDHCI_CAPABILITIES); - if (caps[1] & SDHCI_HOSTCAP_VOLTAGE_180) + if (caps & SDHCI_CAN_VDD_180) host->mci.voltages |= MMC_VDD_165_195; - if (caps[1] & SDHCI_HOSTCAP_VOLTAGE_300) + if (caps & SDHCI_CAN_VDD_300) host->mci.voltages |= MMC_VDD_29_30 | MMC_VDD_30_31; - if (caps[1] & SDHCI_HOSTCAP_VOLTAGE_330) + if (caps & SDHCI_CAN_VDD_330) host->mci.voltages |= MMC_VDD_32_33 | MMC_VDD_33_34; - if (caps[1] & SDHCI_HOSTCAP_HIGHSPEED) + if (caps & SDHCI_CAN_DO_HISPD) host->mci.host_caps |= (MMC_CAP_MMC_HIGHSPEED_52MHZ | MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED); @@ -311,7 +267,7 @@ static void dove_sdhci_set_mci_caps(struct dove_sdhci *host) mci_of_parse(&host->mci); /* limit bus widths to controller capabilities */ - if ((caps[1] & SDHCI_HOSTCAP_8BIT) == 0) + if ((caps & SDHCI_CAN_DO_8BIT) == 0) host->mci.host_caps &= ~MMC_CAP_8_BIT_DATA; } @@ -321,7 +277,7 @@ static int dove_sdhci_probe(struct device_d *dev) int ret; host = xzalloc(sizeof(*host)); - host->base = dev_request_mem_region(dev, 0); + host->sdhci.base = dev_request_mem_region(dev, 0); host->mci.max_req_size = 0x8000; host->mci.hw_dev = dev; host->mci.send_cmd = dove_sdhci_mci_send_cmd; @@ -329,12 +285,6 @@ static int dove_sdhci_probe(struct device_d *dev) host->mci.init = dove_sdhci_mci_init; host->mci.f_max = 50000000; host->mci.f_min = host->mci.f_max / 256; - host->sdhci.read32 = dove_sdhci_readl; - host->sdhci.read16 = dove_sdhci_readw; - host->sdhci.read8 = dove_sdhci_readb; - host->sdhci.write32 = dove_sdhci_writel; - host->sdhci.write16 = dove_sdhci_writew; - host->sdhci.write8 = dove_sdhci_writeb; dove_sdhci_set_mci_caps(host); diff --git a/drivers/mci/dw_mmc.c b/drivers/mci/dw_mmc.c index 7979568841..930b538adc 100644 --- a/drivers/mci/dw_mmc.c +++ b/drivers/mci/dw_mmc.c @@ -25,6 +25,7 @@ struct dwmci_host { struct mci_host mci; + struct device_d *dev; struct clk *clk_biu, *clk_ciu; void *ioaddr; unsigned int fifo_size_bytes; @@ -34,6 +35,7 @@ struct dwmci_host { int ciu_div; u32 fifoth_val; u32 pwren_value; + dma_addr_t idmac_dma; }; struct dwmci_idmac { @@ -110,12 +112,12 @@ static int dwmci_prepare_data_pio(struct dwmci_host *host, } static int dwmci_prepare_data_dma(struct dwmci_host *host, - struct mci_data *data) + struct mci_data *data, dma_addr_t dma) { unsigned long ctrl; unsigned int i = 0, flags, cnt, blk_cnt; - unsigned start_addr; struct dwmci_idmac *desc = host->idmac; + dma_addr_t desc_dma = host->idmac_dma; blk_cnt = data->blocks; @@ -124,12 +126,7 @@ static int dwmci_prepare_data_dma(struct dwmci_host *host, dwmci_wait_reset(host, DWMCI_CTRL_FIFO_RESET); - dwmci_writel(host, DWMCI_DBADDR, (uint32_t)desc); - - if (data->flags & MMC_DATA_READ) - start_addr = (uint32_t)data->dest; - else - start_addr = (uint32_t)data->src; + dwmci_writel(host, DWMCI_DBADDR, desc_dma); do { flags = DWMCI_IDMAC_OWN | DWMCI_IDMAC_CH; @@ -142,10 +139,12 @@ static int dwmci_prepare_data_dma(struct dwmci_host *host, cnt = data->blocksize * 8; } + desc_dma += sizeof(*desc); + desc->flags = flags; desc->cnt = cnt; - desc->addr = start_addr + (i * PAGE_SIZE); - desc->next_addr = (uint32_t)(desc + 1); + desc->addr = dma + (i * PAGE_SIZE); + desc->next_addr = desc_dma; dev_dbg(host->mci.hw_dev, "desc@ 0x%p 0x%08x 0x%08x 0x%08x 0x%08x\n", desc, flags, cnt, desc->addr, desc->next_addr); @@ -172,12 +171,12 @@ static int dwmci_prepare_data_dma(struct dwmci_host *host, } static int dwmci_prepare_data(struct dwmci_host *host, - struct mci_data *data) + struct mci_data *data, dma_addr_t dma) { if (dwmci_use_pio(host)) return dwmci_prepare_data_pio(host, data); else - return dwmci_prepare_data_dma(host, data); + return dwmci_prepare_data_dma(host, data, dma); } static int dwmci_set_transfer_mode(struct dwmci_host *host, @@ -272,6 +271,7 @@ dwmci_cmd(struct mci_host *mci, struct mci_cmd *cmd, struct mci_data *data) uint64_t start; int ret; unsigned int num_bytes = 0; + dma_addr_t dma = 0; start = get_time_ns(); while (1) { @@ -287,16 +287,20 @@ dwmci_cmd(struct mci_host *mci, struct mci_cmd *cmd, struct mci_data *data) dwmci_writel(host, DWMCI_RINTSTS, DWMCI_INTMSK_ALL); if (data) { + num_bytes = data->blocks * data->blocksize; if (data->flags & MMC_DATA_WRITE) - dma_sync_single_for_device((unsigned long)data->src, - num_bytes, DMA_TO_DEVICE); + dma = dma_map_single(host->dev, (void *)data->src, num_bytes, + DMA_TO_DEVICE); else - dma_sync_single_for_device((unsigned long)data->dest, - num_bytes, DMA_FROM_DEVICE); + dma = dma_map_single(host->dev, data->dest, num_bytes, + DMA_FROM_DEVICE); - ret = dwmci_prepare_data(host, data); + if (dma_mapping_error(host->dev, dma)) + return -EFAULT; + + ret = dwmci_prepare_data(host, data, dma); if (ret) return ret; } @@ -400,11 +404,11 @@ dwmci_cmd(struct mci_host *mci, struct mci_cmd *cmd, struct mci_data *data) dwmci_writel(host, DWMCI_CTRL, ctrl); if (data->flags & MMC_DATA_WRITE) - dma_sync_single_for_cpu((unsigned long)data->src, - num_bytes, DMA_TO_DEVICE); + dma_unmap_single(host->dev, dma, num_bytes, + DMA_TO_DEVICE); else - dma_sync_single_for_cpu((unsigned long)data->dest, - num_bytes, DMA_FROM_DEVICE); + dma_unmap_single(host->dev, dma, num_bytes, + DMA_FROM_DEVICE); } } @@ -550,6 +554,9 @@ static int dw_mmc_probe(struct device_d *dev) host = xzalloc(sizeof(*host)); + dma_set_mask(dev, DMA_BIT_MASK(32)); + host->dev = dev; + host->clk_biu = clk_get(dev, "biu"); if (IS_ERR(host->clk_biu)) return PTR_ERR(host->clk_biu); @@ -567,7 +574,9 @@ static int dw_mmc_probe(struct device_d *dev) host->ioaddr = IOMEM(iores->start); host->idmac = dma_alloc_coherent(sizeof(*host->idmac) * DW_MMC_NUM_IDMACS, - DMA_ADDRESS_BROKEN); + &host->idmac_dma); + if (!host->idmac) + return -ENOMEM; host->mci.send_cmd = dwmci_cmd; host->mci.set_ios = dwmci_set_ios; diff --git a/drivers/mci/imx-esdhc-common.c b/drivers/mci/imx-esdhc-common.c index c9d589468f..77d7e4d478 100644 --- a/drivers/mci/imx-esdhc-common.c +++ b/drivers/mci/imx-esdhc-common.c @@ -10,48 +10,41 @@ #define PRSSTAT_DAT0 0x01000000 -struct fsl_esdhc_dma_transfer { - dma_addr_t dma; - unsigned int size; - enum dma_data_direction dir; -}; - -static u32 esdhc_op_read32_le(struct sdhci *sdhci, int reg) +static u32 esdhc_op_read32_be(struct sdhci *sdhci, int reg) { struct fsl_esdhc_host *host = sdhci_to_esdhc(sdhci); - return readl(host->regs + reg); + return in_be32(host->sdhci.base + reg); } -static u32 esdhc_op_read32_be(struct sdhci *sdhci, int reg) +static void esdhc_op_write32_be(struct sdhci *sdhci, int reg, u32 val) { struct fsl_esdhc_host *host = sdhci_to_esdhc(sdhci); - return in_be32(host->regs + reg); + out_be32(host->sdhci.base + reg, val); } -static void esdhc_op_write32_le(struct sdhci *sdhci, int reg, u32 val) +static u16 esdhc_op_read16_be(struct sdhci *sdhci, int reg) { struct fsl_esdhc_host *host = sdhci_to_esdhc(sdhci); - writel(val, host->regs + reg); + return in_be16(host->sdhci.base + reg); } -static void esdhc_op_write32_be(struct sdhci *sdhci, int reg, u32 val) +static void esdhc_op_write16_be(struct sdhci *sdhci, int reg, u16 val) { struct fsl_esdhc_host *host = sdhci_to_esdhc(sdhci); - out_be32(host->regs + reg, val); + out_be16(host->sdhci.base + reg, val); } void esdhc_populate_sdhci(struct fsl_esdhc_host *host) { if (host->socdata->flags & ESDHC_FLAG_BIGENDIAN) { + host->sdhci.read16 = esdhc_op_read16_be; + host->sdhci.write16 = esdhc_op_write16_be; host->sdhci.read32 = esdhc_op_read32_be; host->sdhci.write32 = esdhc_op_write32_be; - } else { - host->sdhci.read32 = esdhc_op_read32_le; - host->sdhci.write32 = esdhc_op_write32_le; } } @@ -59,71 +52,33 @@ static bool esdhc_use_pio_mode(void) { return IN_PBL || IS_ENABLED(CONFIG_MCI_IMX_ESDHC_PIO); } + static int esdhc_setup_data(struct fsl_esdhc_host *host, struct mci_data *data, - struct fsl_esdhc_dma_transfer *tr) + dma_addr_t *dma) { u32 wml_value; - void *ptr; - - if (!esdhc_use_pio_mode()) { - wml_value = data->blocksize/4; - - if (data->flags & MMC_DATA_READ) { - if (wml_value > 0x10) - wml_value = 0x10; - - esdhc_clrsetbits32(host, IMX_SDHCI_WML, WML_RD_WML_MASK, wml_value); - } else { - if (wml_value > 0x80) - wml_value = 0x80; - - esdhc_clrsetbits32(host, IMX_SDHCI_WML, WML_WR_WML_MASK, - wml_value << 16); - } - - tr->size = data->blocks * data->blocksize; - if (data->flags & MMC_DATA_WRITE) { - ptr = (void *)data->src; - tr->dir = DMA_TO_DEVICE; - } else { - ptr = data->dest; - tr->dir = DMA_FROM_DEVICE; - } + wml_value = data->blocksize / 4; - tr->dma = dma_map_single(host->dev, ptr, tr->size, tr->dir); - if (dma_mapping_error(host->dev, tr->dma)) - return -EFAULT; + if (data->flags & MMC_DATA_READ) { + if (wml_value > 0x10) + wml_value = 0x10; + esdhc_clrsetbits32(host, IMX_SDHCI_WML, WML_RD_WML_MASK, wml_value); + } else { + if (wml_value > 0x80) + wml_value = 0x80; - sdhci_write32(&host->sdhci, SDHCI_DMA_ADDRESS, tr->dma); + esdhc_clrsetbits32(host, IMX_SDHCI_WML, WML_WR_WML_MASK, + wml_value << 16); } - sdhci_write32(&host->sdhci, SDHCI_BLOCK_SIZE__BLOCK_COUNT, data->blocks << 16 | data->blocksize); - - return 0; -} - -static int esdhc_do_data(struct fsl_esdhc_host *host, struct mci_data *data, - struct fsl_esdhc_dma_transfer *tr) -{ - u32 irqstat; + host->sdhci.sdma_boundary = 0; if (esdhc_use_pio_mode()) - return sdhci_transfer_data(&host->sdhci, data); - - do { - irqstat = sdhci_read32(&host->sdhci, SDHCI_INT_STATUS); - - if (irqstat & DATA_ERR) - return -EIO; - - if (irqstat & SDHCI_INT_DATA_TIMEOUT) - return -ETIMEDOUT; - } while (!(irqstat & SDHCI_INT_XFER_COMPLETE) && - (sdhci_read32(&host->sdhci, SDHCI_PRESENT_STATE) & SDHCI_DATA_LINE_ACTIVE)); - - dma_unmap_single(host->dev, tr->dma, tr->size, tr->dir); + sdhci_setup_data_pio(&host->sdhci, data); + else + sdhci_setup_data_dma(&host->sdhci, data, dma); return 0; } @@ -156,7 +111,9 @@ static void __udelay(int us) #define udelay(n) __udelay(n) #undef dev_err +#undef dev_dbg #define dev_err(d, ...) pr_err(__VA_ARGS__) +#define dev_dbg(d, ...) pr_debug(__VA_ARGS__) #endif @@ -173,7 +130,7 @@ int __esdhc_send_cmd(struct fsl_esdhc_host *host, struct mci_cmd *cmd, { u32 xfertyp, mixctrl, command; u32 irqstat; - struct fsl_esdhc_dma_transfer tr = { 0 }; + dma_addr_t dma = SDHCI_NO_DMA; int ret; sdhci_write32(&host->sdhci, SDHCI_INT_STATUS, -1); @@ -183,13 +140,13 @@ int __esdhc_send_cmd(struct fsl_esdhc_host *host, struct mci_cmd *cmd, /* Set up for a data transfer if we have one */ if (data) { - ret = esdhc_setup_data(host, data, &tr); + ret = esdhc_setup_data(host, data, &dma); if (ret) return ret; } sdhci_set_cmd_xfer_mode(&host->sdhci, cmd, data, - !esdhc_use_pio_mode(), &command, &xfertyp); + dma != SDHCI_NO_DMA, &command, &xfertyp); if ((host->socdata->flags & ESDHC_FLAG_MULTIBLK_NO_INT) && (cmd->cmdidx == MMC_CMD_STOP_TRANSMISSION)) @@ -246,7 +203,11 @@ int __esdhc_send_cmd(struct fsl_esdhc_host *host, struct mci_cmd *cmd, /* Wait until all of the blocks are transferred */ if (data) { - ret = esdhc_do_data(host, data, &tr); + if (esdhc_use_pio_mode()) + ret = sdhci_transfer_data_pio(&host->sdhci, data); + else + ret = sdhci_transfer_data_dma(&host->sdhci, data, dma); + if (ret) return ret; } diff --git a/drivers/mci/imx-esdhc-pbl.c b/drivers/mci/imx-esdhc-pbl.c index c3a8b377e2..d7136f5492 100644 --- a/drivers/mci/imx-esdhc-pbl.c +++ b/drivers/mci/imx-esdhc-pbl.c @@ -200,14 +200,14 @@ static int imx8m_esdhc_init(struct fsl_esdhc_host *host, { switch (instance) { case 0: - host->regs = IOMEM(MX8M_USDHC1_BASE_ADDR); + host->sdhci.base = IOMEM(MX8M_USDHC1_BASE_ADDR); break; case 1: - host->regs = IOMEM(MX8M_USDHC2_BASE_ADDR); + host->sdhci.base = IOMEM(MX8M_USDHC2_BASE_ADDR); break; case 2: /* Only exists on i.MX8MM, not on i.MX8MQ */ - host->regs = IOMEM(MX8MM_USDHC3_BASE_ADDR); + host->sdhci.base = IOMEM(MX8MM_USDHC3_BASE_ADDR); break; default: return -EINVAL; @@ -237,16 +237,16 @@ int imx6_esdhc_start_image(int instance) switch (instance) { case 0: - host.regs = IOMEM(MX6_USDHC1_BASE_ADDR); + host.sdhci.base = IOMEM(MX6_USDHC1_BASE_ADDR); break; case 1: - host.regs = IOMEM(MX6_USDHC2_BASE_ADDR); + host.sdhci.base = IOMEM(MX6_USDHC2_BASE_ADDR); break; case 2: - host.regs = IOMEM(MX6_USDHC3_BASE_ADDR); + host.sdhci.base = IOMEM(MX6_USDHC3_BASE_ADDR); break; case 3: - host.regs = IOMEM(MX6_USDHC4_BASE_ADDR); + host.sdhci.base = IOMEM(MX6_USDHC4_BASE_ADDR); break; default: return -EINVAL; @@ -276,13 +276,13 @@ int imx7_esdhc_start_image(int instance) switch (instance) { case 0: - host.regs = IOMEM(MX7_USDHC1_BASE_ADDR); + host.sdhci.base = IOMEM(MX7_USDHC1_BASE_ADDR); break; case 1: - host.regs = IOMEM(MX7_USDHC2_BASE_ADDR); + host.sdhci.base = IOMEM(MX7_USDHC2_BASE_ADDR); break; case 2: - host.regs = IOMEM(MX7_USDHC3_BASE_ADDR); + host.sdhci.base = IOMEM(MX7_USDHC3_BASE_ADDR); break; default: return -EINVAL; @@ -375,7 +375,7 @@ int ls1046a_esdhc_start_image(unsigned long r0, unsigned long r1, unsigned long .flags = ESDHC_FLAG_BIGENDIAN, }; struct fsl_esdhc_host host = { - .regs = IOMEM(0x01560000), + .sdhci.base = IOMEM(0x01560000), .socdata = &data, }; unsigned long sdram = 0x80000000; diff --git a/drivers/mci/imx-esdhc.c b/drivers/mci/imx-esdhc.c index 93f3c57d4e..5a664ce4c3 100644 --- a/drivers/mci/imx-esdhc.c +++ b/drivers/mci/imx-esdhc.c @@ -230,7 +230,6 @@ static int fsl_esdhc_probe(struct device_d *dev) struct resource *iores; struct fsl_esdhc_host *host; struct mci_host *mci; - u32 caps; int ret; unsigned long rate; struct esdhc_platform_data *pdata = dev->platform_data; @@ -265,33 +264,26 @@ static int fsl_esdhc_probe(struct device_d *dev) ret = PTR_ERR(iores); goto err_clk_disable; } - host->regs = IOMEM(iores->start); + host->sdhci.base = IOMEM(iores->start); esdhc_populate_sdhci(host); - caps = sdhci_read32(&host->sdhci, SDHCI_CAPABILITIES); - - if (caps & ESDHC_HOSTCAPBLT_VS18) - mci->voltages |= MMC_VDD_165_195; - if (caps & ESDHC_HOSTCAPBLT_VS30) - mci->voltages |= MMC_VDD_29_30 | MMC_VDD_30_31; - if (caps & ESDHC_HOSTCAPBLT_VS33) - mci->voltages |= MMC_VDD_32_33 | MMC_VDD_33_34; - if (pdata) { mci->host_caps = pdata->caps; if (pdata->devname) mci->devname = pdata->devname; } - if (caps & ESDHC_HOSTCAPBLT_HSS) - mci->host_caps |= MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED; - host->mci.send_cmd = esdhc_send_cmd; host->mci.set_ios = esdhc_set_ios; host->mci.init = esdhc_init; host->mci.card_present = esdhc_card_present; host->mci.hw_dev = dev; + host->sdhci.mci = &host->mci; + + ret = sdhci_setup_host(&host->sdhci); + if (ret) + goto err_clk_disable; rate = clk_get_rate(host->clk); host->mci.f_min = rate >> 12; diff --git a/drivers/mci/imx-esdhc.h b/drivers/mci/imx-esdhc.h index 8abe1207d7..f1685eac06 100644 --- a/drivers/mci/imx-esdhc.h +++ b/drivers/mci/imx-esdhc.h @@ -37,13 +37,6 @@ #define BLKATTR_SIZE(x) (x & 0x1fff) #define MAX_BLK_CNT 0x7fff /* so malloc will have enough room with 32M */ -#define ESDHC_HOSTCAPBLT_VS18 0x04000000 -#define ESDHC_HOSTCAPBLT_VS30 0x02000000 -#define ESDHC_HOSTCAPBLT_VS33 0x01000000 -#define ESDHC_HOSTCAPBLT_SRS 0x00800000 -#define ESDHC_HOSTCAPBLT_DMAS 0x00400000 -#define ESDHC_HOSTCAPBLT_HSS 0x00200000 - #define PIO_TIMEOUT 100000 #define IMX_SDHCI_WML 0x44 @@ -108,7 +101,6 @@ struct fsl_esdhc_host { struct mci_host mci; struct clk *clk; struct device_d *dev; - void __iomem *regs; const struct esdhc_soc_data *socdata; struct sdhci sdhci; }; diff --git a/drivers/mci/mci-bcm2835.c b/drivers/mci/mci-bcm2835.c index 91027857be..0450f899c6 100644 --- a/drivers/mci/mci-bcm2835.c +++ b/drivers/mci/mci-bcm2835.c @@ -172,7 +172,7 @@ static int bcm2835_mci_request(struct mci_host *mci, struct mci_cmd *cmd, } if (!ret && data) - ret = sdhci_transfer_data(&host->sdhci, data); + ret = sdhci_transfer_data_pio(&host->sdhci, data); sdhci_write32(&host->sdhci, SDHCI_INT_STATUS, 0xFFFFFFFF); if (ret) { diff --git a/drivers/mci/mci-core.c b/drivers/mci/mci-core.c index a160b98894..a094f3cbf5 100644 --- a/drivers/mci/mci-core.c +++ b/drivers/mci/mci-core.c @@ -1358,7 +1358,8 @@ static int __maybe_unused mci_sd_write(struct block_device *blk, mci_blk_part_switch(part); - if (host->card_write_protected && host->card_write_protected(host)) { + if (!host->disable_wp && + host->card_write_protected && host->card_write_protected(host)) { dev_err(&mci->dev, "card write protected\n"); return -EPERM; } @@ -2016,6 +2017,7 @@ void mci_of_parse_node(struct mci_host *host, host->non_removable = of_property_read_bool(np, "non-removable"); host->no_sd = of_property_read_bool(np, "no-sd"); + host->disable_wp = of_property_read_bool(np, "disable-wp"); } void mci_of_parse(struct mci_host *host) diff --git a/drivers/mci/rockchip-dwcmshc-sdhci.c b/drivers/mci/rockchip-dwcmshc-sdhci.c new file mode 100644 index 0000000000..164f662552 --- /dev/null +++ b/drivers/mci/rockchip-dwcmshc-sdhci.c @@ -0,0 +1,377 @@ +// SPDX-License-Identifier: GPL-2.0-or-later + +#include <clock.h> +#include <common.h> +#include <driver.h> +#include <init.h> +#include <linux/clk.h> +#include <mci.h> +#include <dma.h> +#include <linux/iopoll.h> + +#include "sdhci.h" + +/* DWCMSHC specific Mode Select value */ +#define DWCMSHC_CTRL_HS400 0x7 + +#define DWCMSHC_VER_ID 0x500 +#define DWCMSHC_VER_TYPE 0x504 +#define DWCMSHC_HOST_CTRL3 0x508 +#define DWCMSHC_EMMC_CONTROL 0x52c +#define DWCMSHC_EMMC_ATCTRL 0x540 + +/* Rockchip specific Registers */ +#define DWCMSHC_EMMC_DLL_CTRL 0x800 +#define DWCMSHC_EMMC_DLL_RXCLK 0x804 +#define DWCMSHC_EMMC_DLL_TXCLK 0x808 +#define DWCMSHC_EMMC_DLL_STRBIN 0x80c +#define DWCMSHC_EMMC_DLL_STATUS0 0x840 +#define DWCMSHC_EMMC_DLL_START BIT(0) +#define DWCMSHC_EMMC_DLL_RXCLK_SRCSEL 29 +#define DWCMSHC_EMMC_DLL_START_POINT 16 +#define DWCMSHC_EMMC_DLL_INC 8 +#define DWCMSHC_EMMC_DLL_DLYENA BIT(27) +#define DLL_TXCLK_TAPNUM_DEFAULT 0x8 +#define DLL_STRBIN_TAPNUM_DEFAULT 0x8 +#define DLL_TXCLK_TAPNUM_FROM_SW BIT(24) +#define DLL_STRBIN_TAPNUM_FROM_SW BIT(24) +#define DWCMSHC_EMMC_DLL_LOCKED BIT(8) +#define DWCMSHC_EMMC_DLL_TIMEOUT BIT(9) +#define DLL_RXCLK_NO_INVERTER 1 +#define DLL_RXCLK_INVERTER 0 +#define DWCMSHC_ENHANCED_STROBE BIT(8) +#define DLL_LOCK_WO_TMOUT(x) \ + ((((x) & DWCMSHC_EMMC_DLL_LOCKED) == DWCMSHC_EMMC_DLL_LOCKED) && \ + (((x) & DWCMSHC_EMMC_DLL_TIMEOUT) == 0)) + +#define SDHCI_DWCMSHC_INT_DATA_MASK SDHCI_INT_XFER_COMPLETE | \ + SDHCI_INT_DMA | \ + SDHCI_INT_SPACE_AVAIL | \ + SDHCI_INT_DATA_AVAIL | \ + SDHCI_INT_DATA_TIMEOUT | \ + SDHCI_INT_DATA_CRC | \ + SDHCI_INT_DATA_END_BIT + +#define SDHCI_DWCMSHC_INT_CMD_MASK SDHCI_INT_CMD_COMPLETE | \ + SDHCI_INT_TIMEOUT | \ + SDHCI_INT_CRC | \ + SDHCI_INT_END_BIT | \ + SDHCI_INT_INDEX + +enum { + CLK_CORE, + CLK_BUS, + CLK_AXI, + CLK_BLOCK, + CLK_TIMER, + CLK_MAX, +}; + +struct rk_sdhci_host { + struct mci_host mci; + struct sdhci sdhci; + struct clk_bulk_data clks[CLK_MAX]; +}; + + +static inline +struct rk_sdhci_host *to_rk_sdhci_host(struct mci_host *mci) +{ + return container_of(mci, struct rk_sdhci_host, mci); +} + +static int rk_sdhci_card_present(struct mci_host *mci) +{ + struct rk_sdhci_host *host = to_rk_sdhci_host(mci); + + return !!(sdhci_read32(&host->sdhci, SDHCI_PRESENT_STATE) & SDHCI_CARD_DETECT); +} + +static int rk_sdhci_reset(struct rk_sdhci_host *host, u8 mask) +{ + sdhci_write8(&host->sdhci, SDHCI_SOFTWARE_RESET, mask); + + /* wait for reset completion */ + if (wait_on_timeout(100 * MSECOND, + !(sdhci_read8(&host->sdhci, SDHCI_SOFTWARE_RESET) & mask))){ + dev_err(host->mci.hw_dev, "SDHCI reset timeout\n"); + return -ETIMEDOUT; + } + + return 0; +} + +static int rk_sdhci_init(struct mci_host *mci, struct device_d *dev) +{ + struct rk_sdhci_host *host = to_rk_sdhci_host(mci); + int ret; + + ret = rk_sdhci_reset(host, SDHCI_RESET_ALL); + if (ret) + return ret; + + sdhci_write8(&host->sdhci, SDHCI_POWER_CONTROL, + SDHCI_BUS_VOLTAGE_330 | SDHCI_BUS_POWER_EN); + udelay(400); + + sdhci_write32(&host->sdhci, SDHCI_INT_ENABLE, + SDHCI_DWCMSHC_INT_DATA_MASK | + SDHCI_DWCMSHC_INT_CMD_MASK); + sdhci_write32(&host->sdhci, SDHCI_SIGNAL_ENABLE, 0x00); + + /* Disable cmd conflict check */ + sdhci_write32(&host->sdhci, DWCMSHC_HOST_CTRL3, 0x0); + /* Reset previous settings */ + sdhci_write32(&host->sdhci, DWCMSHC_EMMC_DLL_TXCLK, 0); + sdhci_write32(&host->sdhci, DWCMSHC_EMMC_DLL_STRBIN, 0); + + return 0; +} + +static void rk_sdhci_set_clock(struct rk_sdhci_host *host, unsigned int clock) +{ + u32 txclk_tapnum = DLL_TXCLK_TAPNUM_DEFAULT, extra; + int err; + + host->mci.clock = 0; + + /* DO NOT TOUCH THIS SETTING */ + extra = DWCMSHC_EMMC_DLL_DLYENA | + DLL_RXCLK_NO_INVERTER << DWCMSHC_EMMC_DLL_RXCLK_SRCSEL; + sdhci_write32(&host->sdhci, DWCMSHC_EMMC_DLL_RXCLK, extra); + + if (clock == 0) + return; + + /* Rockchip platform only support 375KHz for identify mode */ + if (clock <= 400000) + clock = 375000; + + clk_set_rate(host->clks[CLK_CORE].clk, clock); + + sdhci_set_clock(&host->sdhci, clock, clk_get_rate(host->clks[CLK_CORE].clk)); + + if (clock <= 400000) + return; + + /* Reset DLL */ + sdhci_write32(&host->sdhci, DWCMSHC_EMMC_DLL_CTRL, BIT(1)); + udelay(1); + sdhci_write32(&host->sdhci, DWCMSHC_EMMC_DLL_CTRL, 0x0); + + /* Init DLL settings */ + extra = 0x5 << DWCMSHC_EMMC_DLL_START_POINT | + 0x2 << DWCMSHC_EMMC_DLL_INC | + DWCMSHC_EMMC_DLL_START; + sdhci_write32(&host->sdhci, DWCMSHC_EMMC_DLL_CTRL, extra); + err = readl_poll_timeout(host->sdhci.base + DWCMSHC_EMMC_DLL_STATUS0, + extra, DLL_LOCK_WO_TMOUT(extra), + 500 * USEC_PER_MSEC); + if (err) { + dev_err(host->mci.hw_dev, "DLL lock timeout!\n"); + return; + } + + /* Disable cmd conflict check */ + extra = sdhci_read32(&host->sdhci, DWCMSHC_HOST_CTRL3); + extra &= ~BIT(0); + sdhci_write32(&host->sdhci, DWCMSHC_HOST_CTRL3, extra); + + extra = 0x1 << 16 | /* tune clock stop en */ + 0x2 << 17 | /* pre-change delay */ + 0x3 << 19; /* post-change delay */ + sdhci_write32(&host->sdhci, DWCMSHC_EMMC_ATCTRL, extra); + + extra = DWCMSHC_EMMC_DLL_DLYENA | + DLL_TXCLK_TAPNUM_FROM_SW | + txclk_tapnum; + sdhci_write32(&host->sdhci, DWCMSHC_EMMC_DLL_TXCLK, extra); + + extra = DWCMSHC_EMMC_DLL_DLYENA | + DLL_STRBIN_TAPNUM_DEFAULT | + DLL_STRBIN_TAPNUM_FROM_SW; + sdhci_write32(&host->sdhci, DWCMSHC_EMMC_DLL_STRBIN, extra); +} + +static void rk_sdhci_set_ios(struct mci_host *mci, struct mci_ios *ios) +{ + struct rk_sdhci_host *host = to_rk_sdhci_host(mci); + u16 val; + + /* stop clock */ + sdhci_write16(&host->sdhci, SDHCI_CLOCK_CONTROL, 0); + + if (ios->clock) + rk_sdhci_set_clock(host, ios->clock); + + sdhci_set_bus_width(&host->sdhci, ios->bus_width); + + val = sdhci_read8(&host->sdhci, SDHCI_HOST_CONTROL); + + if (ios->clock > 26000000) + val |= SDHCI_CTRL_HISPD; + else + val &= ~SDHCI_CTRL_HISPD; + + sdhci_write8(&host->sdhci, SDHCI_HOST_CONTROL, val); +} + +static int rk_sdhci_wait_for_done(struct rk_sdhci_host *host, u32 mask) +{ + u64 start = get_time_ns(); + u16 stat; + + do { + stat = sdhci_read16(&host->sdhci, SDHCI_INT_NORMAL_STATUS); + if (stat & SDHCI_INT_ERROR) { + dev_err(host->mci.hw_dev, "SDHCI_INT_ERROR: 0x%08x\n", + sdhci_read16(&host->sdhci, SDHCI_INT_ERROR_STATUS)); + return -EPERM; + } + + if (is_timeout(start, 1000 * MSECOND)) { + dev_err(host->mci.hw_dev, + "SDHCI timeout while waiting for done\n"); + return -ETIMEDOUT; + } + } while ((stat & mask) != mask); + + return 0; +} + +static void print_error(struct rk_sdhci_host *host, int cmdidx) +{ + dev_err(host->mci.hw_dev, + "error while transfering data for command %d\n", cmdidx); + dev_err(host->mci.hw_dev, "state = 0x%08x , interrupt = 0x%08x\n", + sdhci_read32(&host->sdhci, SDHCI_PRESENT_STATE), + sdhci_read32(&host->sdhci, SDHCI_INT_NORMAL_STATUS)); +} + +static int rk_sdhci_send_cmd(struct mci_host *mci, struct mci_cmd *cmd, + struct mci_data *data) +{ + struct rk_sdhci_host *host = to_rk_sdhci_host(mci); + u32 mask, command, xfer; + int ret; + dma_addr_t dma; + + /* Wait for idle before next command */ + mask = SDHCI_CMD_INHIBIT_CMD; + if (cmd->cmdidx != MMC_CMD_STOP_TRANSMISSION) + mask |= SDHCI_CMD_INHIBIT_DATA; + + ret = wait_on_timeout(10 * MSECOND, + !(sdhci_read32(&host->sdhci, SDHCI_PRESENT_STATE) & mask)); + + if (ret) { + dev_err(host->mci.hw_dev, + "SDHCI timeout while waiting for idle\n"); + return ret; + } + + sdhci_write32(&host->sdhci, SDHCI_INT_STATUS, ~0); + + sdhci_write8(&host->sdhci, SDHCI_TIMEOUT_CONTROL, 0xe); + + sdhci_setup_data_dma(&host->sdhci, data, &dma); + + sdhci_set_cmd_xfer_mode(&host->sdhci, cmd, data, + dma == SDHCI_NO_DMA ? false : true, + &command, &xfer); + + sdhci_write16(&host->sdhci, SDHCI_TRANSFER_MODE, xfer); + + sdhci_write32(&host->sdhci, SDHCI_ARGUMENT, cmd->cmdarg); + sdhci_write16(&host->sdhci, SDHCI_COMMAND, command); + + ret = rk_sdhci_wait_for_done(host, SDHCI_INT_CMD_COMPLETE); + if (ret == -EPERM) + goto error; + else if (ret) + return ret; + + sdhci_read_response(&host->sdhci, cmd); + sdhci_write32(&host->sdhci, SDHCI_INT_STATUS, SDHCI_INT_CMD_COMPLETE); + + ret = sdhci_transfer_data_dma(&host->sdhci, data, dma); + +error: + if (ret) { + print_error(host, cmd->cmdidx); + rk_sdhci_reset(host, BIT(1)); /* SDHCI_RESET_CMD */ + rk_sdhci_reset(host, BIT(2)); /* SDHCI_RESET_DATA */ + } + + sdhci_write32(&host->sdhci, SDHCI_INT_STATUS, ~0); + return ret; +} + +static int rk_sdhci_probe(struct device_d *dev) +{ + struct rk_sdhci_host *host; + struct resource *iores; + struct mci_host *mci; + int ret; + + host = xzalloc(sizeof(*host)); + + mci = &host->mci; + + iores = dev_request_mem_resource(dev, 0); + if (IS_ERR(iores)) + return PTR_ERR(iores); + + host->sdhci.base = IOMEM(iores->start); + host->sdhci.mci = mci; + mci->send_cmd = rk_sdhci_send_cmd; + mci->set_ios = rk_sdhci_set_ios; + mci->init = rk_sdhci_init; + mci->card_present = rk_sdhci_card_present; + mci->hw_dev = dev; + + host->clks[CLK_CORE].id = "core"; + host->clks[CLK_BUS].id = "bus"; + host->clks[CLK_AXI].id = "axi"; + host->clks[CLK_BLOCK].id = "block"; + host->clks[CLK_TIMER].id = "timer"; + + ret = clk_bulk_get(host->mci.hw_dev, CLK_MAX, host->clks); + if (ret) { + dev_err(host->mci.hw_dev, "failed to get clocks: %s\n", + strerror(-ret)); + return ret; + } + + ret = clk_bulk_enable(CLK_MAX, host->clks); + if (ret) { + dev_err(host->mci.hw_dev, "failed to enable clocks: %s\n", + strerror(-ret)); + return ret; + } + + host->sdhci.max_clk = clk_get_rate(host->clks[CLK_CORE].clk); + + mci_of_parse(&host->mci); + + sdhci_setup_host(&host->sdhci); + + dev->priv = host; + + return mci_register(&host->mci); +} + +static __maybe_unused struct of_device_id rk_sdhci_compatible[] = { + { + .compatible = "rockchip,rk3568-dwcmshc" + }, { + /* sentinel */ + } +}; + +static struct driver_d rk_sdhci_driver = { + .name = "rk3568-dwcmshc-sdhci", + .probe = rk_sdhci_probe, + .of_compatible = DRV_OF_COMPAT(rk_sdhci_compatible), +}; +device_platform_driver(rk_sdhci_driver); diff --git a/drivers/mci/sdhci.c b/drivers/mci/sdhci.c index dba26b2665..aca4a5a6f9 100644 --- a/drivers/mci/sdhci.c +++ b/drivers/mci/sdhci.c @@ -4,6 +4,8 @@ #include <driver.h> #include <mci.h> #include <io.h> +#include <dma.h> +#include <linux/bitfield.h> #include "sdhci.h" @@ -88,6 +90,27 @@ static void sdhci_tx_pio(struct sdhci *sdhci, struct mci_data *data, sdhci_write32(sdhci, SDHCI_BUFFER, buf[i]); } +void sdhci_set_bus_width(struct sdhci *host, int width) +{ + u8 ctrl; + + BUG_ON(!host->mci); /* Call sdhci_setup_host() before using this */ + + ctrl = sdhci_read8(host, SDHCI_HOST_CONTROL); + if (width == MMC_BUS_WIDTH_8) { + ctrl &= ~SDHCI_CTRL_4BITBUS; + ctrl |= SDHCI_CTRL_8BITBUS; + } else { + if (host->mci->host_caps & MMC_CAP_8_BIT_DATA) + ctrl &= ~SDHCI_CTRL_8BITBUS; + if (width == MMC_BUS_WIDTH_4) + ctrl |= SDHCI_CTRL_4BITBUS; + else + ctrl &= ~SDHCI_CTRL_4BITBUS; + } + sdhci_write8(host, SDHCI_HOST_CONTROL, ctrl); +} + #ifdef __PBL__ /* * Stubs to make timeout logic below work in PBL @@ -101,12 +124,112 @@ static void sdhci_tx_pio(struct sdhci *sdhci, struct mci_data *data, #endif -int sdhci_transfer_data(struct sdhci *sdhci, struct mci_data *data) +void sdhci_setup_data_pio(struct sdhci *sdhci, struct mci_data *data) +{ + if (!data) + return; + + sdhci_write16(sdhci, SDHCI_BLOCK_SIZE, sdhci->sdma_boundary | + SDHCI_TRANSFER_BLOCK_SIZE(data->blocksize)); + sdhci_write16(sdhci, SDHCI_BLOCK_COUNT, data->blocks); +} + +void sdhci_setup_data_dma(struct sdhci *sdhci, struct mci_data *data, + dma_addr_t *dma) +{ + struct device_d *dev = sdhci->mci->hw_dev; + int nbytes; + + if (!data) + return; + + sdhci_setup_data_pio(sdhci, data); + + if (!dma) + return; + + nbytes = data->blocks * data->blocksize; + + if (data->flags & MMC_DATA_READ) + *dma = dma_map_single(dev, (void *)data->src, nbytes, + DMA_FROM_DEVICE); + else + *dma = dma_map_single(dev, data->dest, nbytes, + DMA_TO_DEVICE); + + if (dma_mapping_error(dev, *dma)) { + *dma = SDHCI_NO_DMA; + return; + } + + sdhci_write32(sdhci, SDHCI_DMA_ADDRESS, *dma); +} + +int sdhci_transfer_data_dma(struct sdhci *sdhci, struct mci_data *data, + dma_addr_t dma) +{ + struct device_d *dev = sdhci->mci->hw_dev; + int nbytes; + u32 irqstat; + int ret; + + if (!data) + return 0; + + nbytes = data->blocks * data->blocksize; + + do { + irqstat = sdhci_read32(sdhci, SDHCI_INT_STATUS); + + if (irqstat & SDHCI_INT_DATA_END_BIT) { + ret = -EIO; + goto out; + } + + if (irqstat & SDHCI_INT_DATA_CRC) { + ret = -EBADMSG; + goto out; + } + + if (irqstat & SDHCI_INT_DATA_TIMEOUT) { + ret = -ETIMEDOUT; + goto out; + } + + if (irqstat & SDHCI_INT_DMA) { + u32 addr = sdhci_read32(sdhci, SDHCI_DMA_ADDRESS); + + /* + * DMA engine has stopped on buffer boundary. Acknowledge + * the interrupt and kick the DMA engine again. + */ + sdhci_write32(sdhci, SDHCI_INT_STATUS, SDHCI_INT_DMA); + sdhci_write32(sdhci, SDHCI_DMA_ADDRESS, addr); + } + + if (irqstat & SDHCI_INT_XFER_COMPLETE) + break; + } while (1); + + ret = 0; +out: + if (data->flags & MMC_DATA_READ) + dma_unmap_single(dev, dma, nbytes, DMA_FROM_DEVICE); + else + dma_unmap_single(dev, dma, nbytes, DMA_TO_DEVICE); + + return 0; +} + +int sdhci_transfer_data_pio(struct sdhci *sdhci, struct mci_data *data) { unsigned int block = 0; u32 stat, prs; uint64_t start = get_time_ns(); + if (!data) + return 0; + do { stat = sdhci_read32(sdhci, SDHCI_INT_STATUS); if (stat & SDHCI_INT_ERROR) @@ -139,6 +262,19 @@ int sdhci_transfer_data(struct sdhci *sdhci, struct mci_data *data) return 0; } +int sdhci_transfer_data(struct sdhci *sdhci, struct mci_data *data, dma_addr_t dma) +{ + struct device_d *dev = sdhci->mci->hw_dev; + + if (!data) + return 0; + + if (dma_mapping_error(dev, dma)) + return sdhci_transfer_data_pio(sdhci, data); + else + return sdhci_transfer_data_dma(sdhci, data, dma); +} + int sdhci_reset(struct sdhci *sdhci, u8 mask) { u8 val; @@ -149,3 +285,264 @@ int sdhci_reset(struct sdhci *sdhci, u8 mask) val, !(val & mask), 100 * USEC_PER_MSEC); } + +static u16 sdhci_get_preset_value(struct sdhci *host) +{ + u16 preset = 0; + + BUG_ON(!host->mci); /* Call sdhci_setup_host() before using this */ + + switch (host->timing) { + case MMC_TIMING_UHS_SDR12: + preset = sdhci_read16(host, SDHCI_PRESET_FOR_SDR12); + break; + case MMC_TIMING_UHS_SDR25: + preset = sdhci_read16(host, SDHCI_PRESET_FOR_SDR25); + break; + case MMC_TIMING_UHS_SDR50: + preset = sdhci_read16(host, SDHCI_PRESET_FOR_SDR50); + break; + case MMC_TIMING_UHS_SDR104: + case MMC_TIMING_MMC_HS200: + preset = sdhci_read16(host, SDHCI_PRESET_FOR_SDR104); + break; + case MMC_TIMING_UHS_DDR50: + case MMC_TIMING_MMC_DDR52: + preset = sdhci_read16(host, SDHCI_PRESET_FOR_DDR50); + break; + case MMC_TIMING_MMC_HS400: + preset = sdhci_read16(host, SDHCI_PRESET_FOR_HS400); + break; + default: + dev_warn(host->mci->hw_dev, "Invalid UHS-I mode selected\n"); + preset = sdhci_read16(host, SDHCI_PRESET_FOR_SDR12); + break; + } + return preset; +} + +u16 sdhci_calc_clk(struct sdhci *host, unsigned int clock, + unsigned int *actual_clock, unsigned int input_clock) +{ + int div = 0; /* Initialized for compiler warning */ + int real_div = div, clk_mul = 1; + u16 clk = 0; + bool switch_base_clk = false; + + BUG_ON(!host->mci); /* Call sdhci_setup_host() before using this */ + + if (host->version >= SDHCI_SPEC_300) { + if (host->preset_enabled) { + u16 pre_val; + + clk = sdhci_read16(host, SDHCI_CLOCK_CONTROL); + pre_val = sdhci_get_preset_value(host); + div = FIELD_GET(SDHCI_PRESET_SDCLK_FREQ_MASK, pre_val); + if (host->clk_mul && + (pre_val & SDHCI_PRESET_CLKGEN_SEL)) { + clk = SDHCI_PROG_CLOCK_MODE; + real_div = div + 1; + clk_mul = host->clk_mul; + } else { + real_div = max_t(int, 1, div << 1); + } + goto clock_set; + } + + /* + * Check if the Host Controller supports Programmable Clock + * Mode. + */ + if (host->clk_mul) { + for (div = 1; div <= 1024; div++) { + if ((input_clock * host->clk_mul / div) + <= clock) + break; + } + if ((input_clock * host->clk_mul / div) <= clock) { + /* + * Set Programmable Clock Mode in the Clock + * Control register. + */ + clk = SDHCI_PROG_CLOCK_MODE; + real_div = div; + clk_mul = host->clk_mul; + div--; + } else { + /* + * Divisor can be too small to reach clock + * speed requirement. Then use the base clock. + */ + switch_base_clk = true; + } + } + + if (!host->clk_mul || switch_base_clk) { + /* Version 3.00 divisors must be a multiple of 2. */ + if (input_clock <= clock) + div = 1; + else { + for (div = 2; div < SDHCI_MAX_DIV_SPEC_300; + div += 2) { + if ((input_clock / div) <= clock) + break; + } + } + real_div = div; + div >>= 1; + if ((host->quirks2 & SDHCI_QUIRK2_CLOCK_DIV_ZERO_BROKEN) + && !div && input_clock <= 25000000) + div = 1; + } + } else { + /* Version 2.00 divisors must be a power of 2. */ + for (div = 1; div < SDHCI_MAX_DIV_SPEC_200; div *= 2) { + if ((input_clock / div) <= clock) + break; + } + real_div = div; + div >>= 1; + } + +clock_set: + if (real_div) + *actual_clock = (input_clock * clk_mul) / real_div; + clk |= (div & SDHCI_DIV_MASK) << SDHCI_DIVIDER_SHIFT; + clk |= ((div & SDHCI_DIV_HI_MASK) >> SDHCI_DIV_MASK_LEN) + << SDHCI_DIVIDER_HI_SHIFT; + + return clk; +} + +void sdhci_enable_clk(struct sdhci *host, u16 clk) +{ + u64 start; + + BUG_ON(!host->mci); /* Call sdhci_setup_host() before using this */ + + clk |= SDHCI_CLOCK_INT_EN; + sdhci_write16(host, SDHCI_CLOCK_CONTROL, clk); + + start = get_time_ns(); + while (!(sdhci_read16(host, SDHCI_CLOCK_CONTROL) & + SDHCI_CLOCK_INT_STABLE)) { + if (is_timeout(start, 150 * MSECOND)) { + dev_err(host->mci->hw_dev, + "SDHCI clock stable timeout\n"); + return; + } + } + + clk |= SDHCI_CLOCK_CARD_EN; + sdhci_write16(host, SDHCI_CLOCK_CONTROL, clk); +} + +void sdhci_set_clock(struct sdhci *host, unsigned int clock, unsigned int input_clock) +{ + u16 clk; + + BUG_ON(!host->mci); /* Call sdhci_setup_host() before using this */ + + host->mci->clock = 0; + + sdhci_write16(host, SDHCI_CLOCK_CONTROL, 0); + + if (clock == 0) + return; + + clk = sdhci_calc_clk(host, clock, &host->mci->clock, input_clock); + sdhci_enable_clk(host, clk); +} + +void __sdhci_read_caps(struct sdhci *host, const u16 *ver, + const u32 *caps, const u32 *caps1) +{ + u16 v; + u64 dt_caps_mask = 0; + u64 dt_caps = 0; + struct device_node *np = host->mci->hw_dev->device_node; + + BUG_ON(!host->mci); /* Call sdhci_setup_host() before using this */ + + if (host->read_caps) + return; + + host->read_caps = true; + + sdhci_reset(host, SDHCI_RESET_ALL); + + of_property_read_u64(np, "sdhci-caps-mask", &dt_caps_mask); + of_property_read_u64(np, "sdhci-caps", &dt_caps); + + v = ver ? *ver : sdhci_read16(host, SDHCI_HOST_VERSION); + host->version = (v & SDHCI_SPEC_VER_MASK) >> SDHCI_SPEC_VER_SHIFT; + + if (host->quirks & SDHCI_QUIRK_MISSING_CAPS) + return; + + if (caps) { + host->caps = *caps; + } else { + host->caps = sdhci_read32(host, SDHCI_CAPABILITIES); + host->caps &= ~lower_32_bits(dt_caps_mask); + host->caps |= lower_32_bits(dt_caps); + } + + if (host->version < SDHCI_SPEC_300) + return; + + if (caps1) { + host->caps1 = *caps1; + } else { + host->caps1 = sdhci_read32(host, SDHCI_CAPABILITIES_1); + host->caps1 &= ~upper_32_bits(dt_caps_mask); + host->caps1 |= upper_32_bits(dt_caps); + } +} + +int sdhci_setup_host(struct sdhci *host) +{ + struct mci_host *mci = host->mci; + + BUG_ON(!mci); + + sdhci_read_caps(host); + + if (!host->max_clk) { + if (host->version >= SDHCI_SPEC_300) + host->max_clk = FIELD_GET(SDHCI_CLOCK_V3_BASE_MASK, host->caps); + else + host->max_clk = FIELD_GET(SDHCI_CLOCK_BASE_MASK, host->caps); + + host->max_clk *= 1000000; + } + + /* + * In case of Host Controller v3.00, find out whether clock + * multiplier is supported. + */ + host->clk_mul = FIELD_GET(SDHCI_CLOCK_MUL_MASK, host->caps1); + + /* + * In case the value in Clock Multiplier is 0, then programmable + * clock mode is not supported, otherwise the actual clock + * multiplier is one more than the value of Clock Multiplier + * in the Capabilities Register. + */ + if (host->clk_mul) + host->clk_mul += 1; + + if (host->caps & SDHCI_CAN_VDD_180) + mci->voltages |= MMC_VDD_165_195; + if (host->caps & SDHCI_CAN_VDD_300) + mci->voltages |= MMC_VDD_29_30 | MMC_VDD_30_31; + if (host->caps & SDHCI_CAN_VDD_330) + mci->voltages |= MMC_VDD_32_33 | MMC_VDD_33_34; + + if (host->caps & SDHCI_CAN_DO_HISPD) + mci->host_caps |= MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED; + + host->sdma_boundary = SDHCI_DMA_BOUNDARY_512K; + + return 0; +} diff --git a/drivers/mci/sdhci.h b/drivers/mci/sdhci.h index 7b3f64486f..351940a511 100644 --- a/drivers/mci/sdhci.h +++ b/drivers/mci/sdhci.h @@ -2,6 +2,7 @@ #define __MCI_SDHCI_H #include <pbl.h> +#include <dma.h> #include <linux/iopoll.h> #define SDHCI_DMA_ADDRESS 0x00 @@ -54,11 +55,18 @@ #define SDHCI_PRESENT_STATE1 0x26 #define SDHCI_HOST_CONTROL__POWER_CONTROL__BLOCK_GAP_CONTROL 0x28 #define SDHCI_HOST_CONTROL 0x28 -#define SDHCI_CARD_DETECT_SIGNAL_SELECTION BIT(7) -#define SDHCI_CARD_DETECT_TEST_LEVEL BIT(6) -#define SDHCI_DATA_WIDTH_8BIT BIT(5) -#define SDHCI_HIGHSPEED_EN BIT(2) -#define SDHCI_DATA_WIDTH_4BIT BIT(1) +#define SDHCI_CTRL_LED BIT(0) +#define SDHCI_CTRL_4BITBUS BIT(1) +#define SDHCI_CTRL_HISPD BIT(2) +#define SDHCI_CTRL_DMA_MASK 0x18 +#define SDHCI_CTRL_SDMA 0x00 +#define SDHCI_CTRL_ADMA1 0x08 +#define SDHCI_CTRL_ADMA32 0x10 +#define SDHCI_CTRL_ADMA64 0x18 +#define SDHCI_CTRL_ADMA3 0x18 +#define SDHCI_CTRL_8BITBUS BIT(5) +#define SDHCI_CTRL_CDTEST_INS BIT(6) +#define SDHCI_CTRL_CDTEST_EN BIT(7) #define SDHCI_POWER_CONTROL 0x29 #define SDHCI_POWER_ON 0x01 #define SDHCI_POWER_180 0x0A @@ -68,15 +76,19 @@ #define SDHCI_BUS_VOLTAGE(v) ((v) << 1) #define SDHCI_BUS_POWER_EN BIT(0) #define SDHCI_CLOCK_CONTROL__TIMEOUT_CONTROL__SOFTWARE_RESET 0x2c -#define SDHCI_CLOCK_CONTROL 0x2c +#define SDHCI_CLOCK_CONTROL 0x2C +#define SDHCI_DIVIDER_SHIFT 8 #define SDHCI_DIVIDER_HI_SHIFT 6 +#define SDHCI_DIV_MASK 0xFF #define SDHCI_DIV_HI_MASK 0x300 #define SDHCI_DIV_MASK_LEN 8 -#define SDHCI_FREQ_SEL(x) (((x) & 0xff) << 8) +#define SDHCI_FREQ_SEL(x) (((x) & 0xff) << 8) +#define SDHCI_DIV_HI_MASK 0x300 #define SDHCI_PROG_CLOCK_MODE BIT(5) -#define SDHCI_SDCLOCK_EN BIT(2) -#define SDHCI_INTCLOCK_STABLE BIT(1) -#define SDHCI_INTCLOCK_EN BIT(0) +#define SDHCI_CLOCK_CARD_EN BIT(2) +#define SDHCI_CLOCK_PLL_EN BIT(3) +#define SDHCI_CLOCK_INT_STABLE BIT(1) +#define SDHCI_CLOCK_INT_EN BIT(0) #define SDHCI_TIMEOUT_CONTROL 0x2e #define SDHCI_SOFTWARE_RESET 0x2f #define SDHCI_RESET_ALL BIT(0) @@ -105,19 +117,66 @@ #define SDHCI_SIGNAL_ENABLE 0x38 #define SDHCI_ACMD12_ERR__HOST_CONTROL2 0x3C #define SDHCI_CAPABILITIES 0x40 -#define SDHCI_CAPABILITIES_1 0x42 -#define SDHCI_HOSTCAP_VOLTAGE_180 BIT(10) -#define SDHCI_HOSTCAP_VOLTAGE_300 BIT(9) -#define SDHCI_HOSTCAP_VOLTAGE_330 BIT(8) -#define SDHCI_HOSTCAP_HIGHSPEED BIT(5) -#define SDHCI_HOSTCAP_8BIT BIT(2) - -#define SDHCI_CLOCK_MUL_MASK 0x00FF0000 +#define SDHCI_TIMEOUT_CLK_MASK GENMASK(5, 0) +#define SDHCI_TIMEOUT_CLK_UNIT 0x00000080 +#define SDHCI_CLOCK_BASE_MASK GENMASK(13, 8) +#define SDHCI_CLOCK_V3_BASE_MASK GENMASK(15, 8) +#define SDHCI_MAX_BLOCK_MASK 0x00030000 +#define SDHCI_MAX_BLOCK_SHIFT 16 +#define SDHCI_CAN_DO_8BIT 0x00040000 +#define SDHCI_CAN_DO_ADMA2 0x00080000 +#define SDHCI_CAN_DO_ADMA1 0x00100000 +#define SDHCI_CAN_DO_HISPD 0x00200000 +#define SDHCI_CAN_DO_SDMA 0x00400000 +#define SDHCI_CAN_DO_SUSPEND 0x00800000 +#define SDHCI_CAN_VDD_330 0x01000000 +#define SDHCI_CAN_VDD_300 0x02000000 +#define SDHCI_CAN_VDD_180 0x04000000 +#define SDHCI_CAN_64BIT_V4 0x08000000 +#define SDHCI_CAN_64BIT 0x10000000 + +#define SDHCI_CAPABILITIES_1 0x44 +#define SDHCI_SUPPORT_SDR50 0x00000001 +#define SDHCI_SUPPORT_SDR104 0x00000002 +#define SDHCI_SUPPORT_DDR50 0x00000004 +#define SDHCI_DRIVER_TYPE_A 0x00000010 +#define SDHCI_DRIVER_TYPE_C 0x00000020 +#define SDHCI_DRIVER_TYPE_D 0x00000040 +#define SDHCI_RETUNING_TIMER_COUNT_MASK GENMASK(11, 8) +#define SDHCI_USE_SDR50_TUNING 0x00002000 +#define SDHCI_RETUNING_MODE_MASK GENMASK(15, 14) +#define SDHCI_CLOCK_MUL_MASK GENMASK(23, 16) +#define SDHCI_CAN_DO_ADMA3 0x08000000 +#define SDHCI_SUPPORT_HS400 0x80000000 /* Non-standard */ + +#define SDHCI_PRESET_FOR_SDR12 0x66 +#define SDHCI_PRESET_FOR_SDR25 0x68 +#define SDHCI_PRESET_FOR_SDR50 0x6A +#define SDHCI_PRESET_FOR_SDR104 0x6C +#define SDHCI_PRESET_FOR_DDR50 0x6E +#define SDHCI_PRESET_FOR_HS400 0x74 /* Non-standard */ +#define SDHCI_PRESET_CLKGEN_SEL BIT(10) +#define SDHCI_PRESET_SDCLK_FREQ_MASK GENMASK(9, 0) + +#define SDHCI_HOST_VERSION 0xFE +#define SDHCI_VENDOR_VER_MASK 0xFF00 +#define SDHCI_VENDOR_VER_SHIFT 8 +#define SDHCI_SPEC_VER_MASK 0x00FF +#define SDHCI_SPEC_VER_SHIFT 0 +#define SDHCI_SPEC_100 0 +#define SDHCI_SPEC_200 1 +#define SDHCI_SPEC_300 2 +#define SDHCI_SPEC_400 3 +#define SDHCI_SPEC_410 4 +#define SDHCI_SPEC_420 5 + #define SDHCI_CLOCK_MUL_SHIFT 16 -#define SDHCI_SPEC_200_MAX_CLK_DIVIDER 256 #define SDHCI_MMC_BOOT 0xC4 +#define SDHCI_MAX_DIV_SPEC_200 256 +#define SDHCI_MAX_DIV_SPEC_300 2046 + struct sdhci { u32 (*read32)(struct sdhci *host, int reg); u16 (*read16)(struct sdhci *host, int reg); @@ -125,44 +184,101 @@ struct sdhci { void (*write32)(struct sdhci *host, int reg, u32 val); void (*write16)(struct sdhci *host, int reg, u16 val); void (*write8)(struct sdhci *host, int reg, u8 val); + + void __iomem *base; + + int max_clk; /* Max possible freq (Hz) */ + int clk_mul; /* Clock Muliplier value */ + + unsigned int version; /* SDHCI spec. version */ + + enum mci_timing timing; + bool preset_enabled; /* Preset is enabled */ + + unsigned int quirks; +#define SDHCI_QUIRK_MISSING_CAPS BIT(27) + unsigned int quirks2; +#define SDHCI_QUIRK2_CLOCK_DIV_ZERO_BROKEN BIT(15) + u32 caps; /* CAPABILITY_0 */ + u32 caps1; /* CAPABILITY_1 */ + bool read_caps; /* Capability flags have been read */ + u32 sdma_boundary; + + struct mci_host *mci; }; static inline u32 sdhci_read32(struct sdhci *host, int reg) { - return host->read32(host, reg); + if (host->read32) + return host->read32(host, reg); + else + return readl(host->base + reg); } static inline u32 sdhci_read16(struct sdhci *host, int reg) { - return host->read16(host, reg); + if (host->read16) + return host->read16(host, reg); + else + return readw(host->base + reg); } static inline u32 sdhci_read8(struct sdhci *host, int reg) { - return host->read8(host, reg); + if (host->read8) + return host->read8(host, reg); + else + return readb(host->base + reg); } static inline void sdhci_write32(struct sdhci *host, int reg, u32 val) { - host->write32(host, reg, val); + if (host->write32) + host->write32(host, reg, val); + else + writel(val, host->base + reg); } static inline void sdhci_write16(struct sdhci *host, int reg, u32 val) { - host->write16(host, reg, val); + if (host->write16) + host->write16(host, reg, val); + else + writew(val, host->base + reg); } static inline void sdhci_write8(struct sdhci *host, int reg, u32 val) { - host->write8(host, reg, val); + if (host->write8) + host->write8(host, reg, val); + else + writeb(val, host->base + reg); } +#define SDHCI_NO_DMA DMA_ERROR_CODE void sdhci_read_response(struct sdhci *host, struct mci_cmd *cmd); void sdhci_set_cmd_xfer_mode(struct sdhci *host, struct mci_cmd *cmd, struct mci_data *data, bool dma, u32 *command, u32 *xfer); -int sdhci_transfer_data(struct sdhci *sdhci, struct mci_data *data); +void sdhci_setup_data_pio(struct sdhci *sdhci, struct mci_data *data); +void sdhci_setup_data_dma(struct sdhci *sdhci, struct mci_data *data, dma_addr_t *dma); +int sdhci_transfer_data(struct sdhci *sdhci, struct mci_data *data, dma_addr_t dma); +int sdhci_transfer_data_pio(struct sdhci *sdhci, struct mci_data *data); +int sdhci_transfer_data_dma(struct sdhci *sdhci, struct mci_data *data, + dma_addr_t dma); int sdhci_reset(struct sdhci *sdhci, u8 mask); +u16 sdhci_calc_clk(struct sdhci *host, unsigned int clock, + unsigned int *actual_clock, unsigned int input_clock); +void sdhci_set_clock(struct sdhci *host, unsigned int clock, unsigned int input_clock); +void sdhci_enable_clk(struct sdhci *host, u16 clk); +int sdhci_setup_host(struct sdhci *host); +void __sdhci_read_caps(struct sdhci *host, const u16 *ver, + const u32 *caps, const u32 *caps1); +static inline void sdhci_read_caps(struct sdhci *host) +{ + __sdhci_read_caps(host, NULL, NULL, NULL); +} +void sdhci_set_bus_width(struct sdhci *host, int width); #define sdhci_read8_poll_timeout(sdhci, reg, val, cond, timeout_us) \ read_poll_timeout(sdhci_read8, val, cond, timeout_us, sdhci, reg) diff --git a/drivers/mfd/stpmic1.c b/drivers/mfd/stpmic1.c index d22758bd61..11154e742e 100644 --- a/drivers/mfd/stpmic1.c +++ b/drivers/mfd/stpmic1.c @@ -8,47 +8,10 @@ #include <errno.h> #include <i2c/i2c.h> #include <init.h> -#include <malloc.h> #include <of.h> #include <regmap.h> -#include <xfuncs.h> #include <linux/mfd/stpmic1.h> -struct stpmic1 { - struct device_d *dev; - struct i2c_client *client; -}; - -static int stpmic1_i2c_reg_read(void *ctx, unsigned int reg, unsigned int *val) -{ - struct stpmic1 *stpmic1 = ctx; - u8 buf[1]; - int ret; - - ret = i2c_read_reg(stpmic1->client, reg, buf, 1); - *val = buf[0]; - - return ret == 1 ? 0 : ret; -} - -static int stpmic1_i2c_reg_write(void *ctx, unsigned int reg, unsigned int val) -{ - struct stpmic1 *stpmic1 = ctx; - u8 buf[] = { - val & 0xff, - }; - int ret; - - ret = i2c_write_reg(stpmic1->client, reg, buf, 1); - - return ret == 1 ? 0 : ret; -} - -static struct regmap_bus regmap_stpmic1_i2c_bus = { - .reg_write = stpmic1_i2c_reg_write, - .reg_read = stpmic1_i2c_reg_read, -}; - static const struct regmap_config stpmic1_regmap_i2c_config = { .reg_bits = 8, .val_bits = 8, @@ -57,17 +20,13 @@ static const struct regmap_config stpmic1_regmap_i2c_config = { static int __init stpmic1_probe(struct device_d *dev) { - struct stpmic1 *stpmic1; struct regmap *regmap; u32 reg; int ret; - stpmic1 = xzalloc(sizeof(*stpmic1)); - stpmic1->dev = dev; - - stpmic1->client = to_i2c_client(dev); - regmap = regmap_init(dev, ®map_stpmic1_i2c_bus, - stpmic1, &stpmic1_regmap_i2c_config); + regmap = regmap_init_i2c(to_i2c_client(dev), &stpmic1_regmap_i2c_config); + if (IS_ERR(regmap)) + return PTR_ERR(regmap); ret = regmap_register_cdev(regmap, NULL); if (ret) diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig index 7c93260892..c69e5ce4e1 100644 --- a/drivers/mtd/nand/Kconfig +++ b/drivers/mtd/nand/Kconfig @@ -32,14 +32,27 @@ config NAND_ALLOW_ERASE_BAD config NAND_IMX bool - prompt "i.MX NAND driver" + prompt "i.MX21 to 53 NAND driver aka 'mxc', for NFC" depends on ARCH_IMX + help + Support for NAND flash on Freescale/NXP i.MX devices. This is for the + "MXC" series: i.MX21/25/27/31/35/51/53. + + This is not for the "MXS" series i.MX processors (23 & 28), or i.MX6 + and later, which use the GPMI NAND controller from the MXS series. + See the i.MX 'mxs' driver for those chips. config NAND_MXS bool select STMP_DEVICE - prompt "i.MX23/28/6 NAND driver" + prompt "i.MX23/28 & 6+ NAND driver aka 'mxs', for GPMI" depends on MXS_APBH_DMA + help + Support for NAND flash on Freescale/NXP i.MX devices. This is for the + "MXS" series: i.MX23/28 and all i.MX6 and later SoCs. + + This is not for the "MXC" series of i.MX processors in the i.MX21 to + i.MX53 range. See the i.MX "mxc" driver for those chips. config NAND_OMAP_GPMC tristate "NAND Flash Support for GPMC based OMAP platforms" diff --git a/drivers/mtd/nor/cfi_flash.c b/drivers/mtd/nor/cfi_flash.c index ba0bd1b4eb..ffd29d80a7 100644 --- a/drivers/mtd/nor/cfi_flash.c +++ b/drivers/mtd/nor/cfi_flash.c @@ -466,9 +466,16 @@ flash_sect_t find_sector(struct flash_info *info, unsigned long addr) { flash_sect_t sector; - for (sector = info->sector_count - 1; sector >= 0; sector--) { + sector = info->sector_count - 1; + + while (1) { if (addr >= info->start[sector]) break; + + if (sector == 0) + BUG(); + + sector--; } return sector; diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index 0d55ea7a3b..18931211b5 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -108,6 +108,12 @@ config DRIVER_NET_DESIGNWARE_TEGRA186 help This option enables support for the ethernet MAC on the Tegra186 & 194. +config DRIVER_NET_DESIGNWARE_ROCKCHIP + bool "Designware Universal MAC ethernet driver for Rockchip platforms" + select MFD_SYSCON + help + This option enables support for the ethernet MAC on different Rockchip SoCs + endif config DRIVER_NET_DM9K diff --git a/drivers/net/Makefile b/drivers/net/Makefile index 656d45a868..1674d53dff 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile @@ -14,6 +14,7 @@ obj-$(CONFIG_DRIVER_NET_DESIGNWARE_SOCFPGA) += designware_socfpga.o obj-$(CONFIG_DRIVER_NET_DESIGNWARE_EQOS) += designware_eqos.o obj-$(CONFIG_DRIVER_NET_DESIGNWARE_STM32) += designware_stm32.o obj-$(CONFIG_DRIVER_NET_DESIGNWARE_TEGRA186) += designware_tegra186.o +obj-$(CONFIG_DRIVER_NET_DESIGNWARE_ROCKCHIP) += designware_rockchip.o obj-$(CONFIG_DRIVER_NET_DM9K) += dm9k.o obj-$(CONFIG_DRIVER_NET_E1000) += e1000/regio.o e1000/main.o e1000/eeprom.o obj-$(CONFIG_DRIVER_NET_ENC28J60) += enc28j60.o diff --git a/drivers/net/designware_eqos.c b/drivers/net/designware_eqos.c index d2baaeaf63..f83ec12714 100644 --- a/drivers/net/designware_eqos.c +++ b/drivers/net/designware_eqos.c @@ -8,9 +8,12 @@ #include <common.h> #include <init.h> +#include <gpio.h> +#include <gpiod.h> #include <dma.h> #include <net.h> #include <of_net.h> +#include <of_gpio.h> #include <linux/iopoll.h> #include <linux/time.h> #include <linux/sizes.h> @@ -189,6 +192,27 @@ struct eqos_desc { #define MII_BUSY (1 << 0) +static int eqos_phy_reset(struct device_d *dev, struct eqos *eqos) +{ + int phy_reset; + u32 delays[3] = { 0, 0, 0 }; + + phy_reset = gpiod_get(dev, "snps,reset", GPIOF_OUT_INIT_ACTIVE); + + if (!gpio_is_valid(phy_reset)) + return 0; + + of_property_read_u32_array(dev->device_node, + "snps,reset-delays-us", + delays, ARRAY_SIZE(delays)); + + udelay(delays[1]); + gpio_set_active(phy_reset, false); + udelay(delays[2]); + + return 0; +} + static int eqos_mdio_wait_idle(struct eqos *eqos) { u32 idle; @@ -838,11 +862,16 @@ int eqos_probe(struct device_d *dev, const struct eqos_ops *ops, void *priv) miibus->read = eqos_mdio_read; miibus->write = eqos_mdio_write; miibus->priv = eqos; + miibus->dev.device_node = of_get_child_by_name(dev->device_node, "mdio"); ret = eqos_init(dev, eqos); if (ret) return ret; + ret = eqos_phy_reset(dev, eqos); + if (ret) + return ret; + ret = mdiobus_register(miibus); if (ret) return ret; diff --git a/drivers/net/designware_rockchip.c b/drivers/net/designware_rockchip.c new file mode 100644 index 0000000000..e4f74f646f --- /dev/null +++ b/drivers/net/designware_rockchip.c @@ -0,0 +1,317 @@ +// SPDX-License-Identifier: GPL-2.0 + +#include <common.h> +#include <init.h> +#include <dma.h> +#include <net.h> +#include <regmap.h> +#include <of_net.h> +#include <mfd/syscon.h> +#include <linux/iopoll.h> +#include <linux/sizes.h> +#include <linux/time.h> +#include <linux/clk.h> + +#include "designware_eqos.h" + +struct rk_gmac_ops { + void (*set_to_rgmii)(struct eqos *eqos, + int tx_delay, int rx_delay); + void (*set_to_rmii)(struct eqos *eqos); + void (*set_rmii_speed)(struct eqos *eqos, int speed); + void (*set_rgmii_speed)(struct eqos *eqos, int speed); + void (*integrated_phy_powerup)(struct eqos *eqos); +}; + +struct eqos_rk_gmac { + struct clk_bulk_data *clks; + int num_clks; + bool clock_input; + const struct rk_gmac_ops *ops; + struct regmap *grf; + int bus_id; + u32 tx_delay; + u32 rx_delay; + struct device_d *dev; +}; + +enum { + CLK_STMMACETH, + CLK_MAC_RX, + CLK_MAC_TX, + CLK_MAC_REFOUT, + CLK_MAC_ACLK, + CLK_MAC_PCLK, + CLK_MAC_SPEED, + CLK_PTP_REF, + CLK_XPCS_PCLK, +}; + +static const struct clk_bulk_data rk_gmac_clks[] = { + [CLK_STMMACETH] = { .id = "stmmaceth" }, + [CLK_MAC_RX] = { .id = "mac_clk_rx" }, + [CLK_MAC_TX] = { .id = "mac_clk_tx" }, + [CLK_MAC_REFOUT] = { .id = "clk_mac_refout" }, + [CLK_MAC_ACLK] = { .id = "aclk_mac" }, + [CLK_MAC_PCLK] = { .id = "pclk_mac" }, + [CLK_MAC_SPEED] = { .id = "clk_mac_speed" }, + [CLK_PTP_REF] = { .id = "ptp_ref" }, + [CLK_XPCS_PCLK] = { .id = "pclk_xpcs" }, +}; + +static inline struct eqos_rk_gmac *to_rk_gmac(struct eqos *eqos) +{ + return eqos->priv; +} + +#define HIWORD_UPDATE(val, mask, shift) \ + ((val) << (shift) | (mask) << ((shift) + 16)) + +#define GRF_BIT(nr) (BIT(nr) | BIT((nr) + 16)) +#define GRF_CLR_BIT(nr) (BIT((nr) + 16)) + +#define RK3568_GRF_GMAC0_CON0 0x0380 +#define RK3568_GRF_GMAC0_CON1 0x0384 +#define RK3568_GRF_GMAC1_CON0 0x0388 +#define RK3568_GRF_GMAC1_CON1 0x038c + +/* RK3568_GRF_GMAC0_CON1 && RK3568_GRF_GMAC1_CON1 */ +#define RK3568_GMAC_PHY_INTF_SEL_RGMII \ + (GRF_BIT(4) | GRF_CLR_BIT(5) | GRF_CLR_BIT(6)) +#define RK3568_GMAC_PHY_INTF_SEL_RMII \ + (GRF_CLR_BIT(4) | GRF_CLR_BIT(5) | GRF_BIT(6)) +#define RK3568_GMAC_FLOW_CTRL GRF_BIT(3) +#define RK3568_GMAC_FLOW_CTRL_CLR GRF_CLR_BIT(3) +#define RK3568_GMAC_RXCLK_DLY_ENABLE GRF_BIT(1) +#define RK3568_GMAC_RXCLK_DLY_DISABLE GRF_CLR_BIT(1) +#define RK3568_GMAC_TXCLK_DLY_ENABLE GRF_BIT(0) +#define RK3568_GMAC_TXCLK_DLY_DISABLE GRF_CLR_BIT(0) + +/* RK3568_GRF_GMAC0_CON0 && RK3568_GRF_GMAC1_CON0 */ +#define RK3568_GMAC_CLK_RX_DL_CFG(val) HIWORD_UPDATE(val, 0x7F, 8) +#define RK3568_GMAC_CLK_TX_DL_CFG(val) HIWORD_UPDATE(val, 0x7F, 0) + +static unsigned long eqos_get_csr_clk_rate_rk_gmac(struct eqos *eqos) +{ + struct eqos_rk_gmac *priv = to_rk_gmac(eqos); + + return clk_get_rate(priv->clks[CLK_STMMACETH].clk); +} + +static void rk3568_set_to_rgmii(struct eqos *eqos, + int tx_delay, int rx_delay) +{ + struct eqos_rk_gmac *priv = to_rk_gmac(eqos); + struct device_d *dev = priv->dev; + u32 offset_con0, offset_con1; + + if (IS_ERR(priv->grf)) { + dev_err(dev, "Missing rockchip,grf property\n"); + return; + } + + offset_con0 = (priv->bus_id == 1) + ? RK3568_GRF_GMAC1_CON0 : RK3568_GRF_GMAC0_CON0; + offset_con1 = (priv->bus_id == 1) + ? RK3568_GRF_GMAC1_CON1 : RK3568_GRF_GMAC0_CON1; + + regmap_write(priv->grf, offset_con1, + RK3568_GMAC_PHY_INTF_SEL_RGMII | + RK3568_GMAC_RXCLK_DLY_ENABLE | + RK3568_GMAC_TXCLK_DLY_ENABLE); + + regmap_write(priv->grf, offset_con0, + RK3568_GMAC_CLK_RX_DL_CFG(rx_delay) | + RK3568_GMAC_CLK_TX_DL_CFG(tx_delay)); +} + +static void rk3568_set_to_rmii(struct eqos *eqos) +{ + struct eqos_rk_gmac *priv = to_rk_gmac(eqos); + struct device_d *dev = priv->dev; + u32 offset_con1; + + if (IS_ERR(priv->grf)) { + dev_err(dev, "%s: Missing rockchip,grf property\n", __func__); + return; + } + + offset_con1 = (priv->bus_id == 1) + ? RK3568_GRF_GMAC1_CON1 : RK3568_GRF_GMAC0_CON1; + + regmap_write(priv->grf, offset_con1, + RK3568_GMAC_PHY_INTF_SEL_RMII); +} + +static void rk3568_set_gmac_speed(struct eqos *eqos, int speed) +{ + struct eqos_rk_gmac *priv = to_rk_gmac(eqos); + struct device_d *dev = priv->dev; + unsigned long rate; + int ret; + + switch (speed) { + case SPEED_10: + rate = 2500000; + break; + case SPEED_100: + rate = 25000000; + break; + case SPEED_1000: + rate = 125000000; + break; + default: + dev_err(dev, "unknown speed value for GMAC speed=%d", speed); + return; + } + + ret = clk_set_rate(priv->clks[CLK_MAC_SPEED].clk, rate); + if (ret) + dev_err(dev, "%s: set clk_mac_speed rate %ld failed %d\n", + __func__, rate, ret); +} + +static const struct rk_gmac_ops rk3568_ops = { + .set_to_rgmii = rk3568_set_to_rgmii, + .set_to_rmii = rk3568_set_to_rmii, + .set_rmii_speed = rk3568_set_gmac_speed, + .set_rgmii_speed = rk3568_set_gmac_speed, +}; + +static int rk_gmac_powerup(struct eqos *eqos) +{ + struct eqos_rk_gmac *priv = to_rk_gmac(eqos); + struct device_d *dev = priv->dev; + + /*rmii or rgmii*/ + switch (eqos->interface) { + case PHY_INTERFACE_MODE_RGMII: + dev_dbg(dev, "init for RGMII\n"); + priv->ops->set_to_rgmii(eqos, priv->tx_delay, + priv->rx_delay); + break; + case PHY_INTERFACE_MODE_RGMII_ID: + dev_dbg(dev, "init for RGMII_ID\n"); + priv->ops->set_to_rgmii(eqos, 0, 0); + break; + case PHY_INTERFACE_MODE_RGMII_RXID: + dev_dbg(dev, "init for RGMII_RXID\n"); + priv->ops->set_to_rgmii(eqos, priv->tx_delay, 0); + break; + case PHY_INTERFACE_MODE_RGMII_TXID: + dev_dbg(dev, "init for RGMII_TXID\n"); + priv->ops->set_to_rgmii(eqos, 0, priv->rx_delay); + break; + case PHY_INTERFACE_MODE_RMII: + dev_dbg(dev, "init for RMII\n"); + priv->ops->set_to_rmii(eqos); + break; + default: + dev_err(dev, "NO interface defined!\n"); + } + + return 0; +} + +static void eqos_rk_adjust_link(struct eth_device *edev) +{ + struct eqos *eqos = edev->priv; + struct eqos_rk_gmac *priv = to_rk_gmac(eqos); + + if (phy_interface_mode_is_rgmii(eqos->interface)) + priv->ops->set_rgmii_speed(eqos, edev->phydev->speed); + else + priv->ops->set_rmii_speed(eqos, edev->phydev->speed); + + eqos_adjust_link(edev); +} + +static int eqos_init_rk_gmac(struct device_d *dev, struct eqos *eqos) +{ + struct device_node *np = dev->device_node; + struct eqos_rk_gmac *priv = to_rk_gmac(eqos); + int ret; + const char *strings; + + priv->dev = dev; + + ret = of_property_read_string(np, "clock_in_out", &strings); + if (ret) { + dev_err(dev, "Can not read property: clock_in_out.\n"); + priv->clock_input = true; + } else { + dev_dbg(dev, "clock is %s\n", strings); + if (!strcmp(strings, "input")) + priv->clock_input = true; + else + priv->clock_input = false; + } + + priv->ops = device_get_match_data(dev); + + priv->bus_id = of_alias_get_id(np, "ethernet"); + + priv->grf = syscon_regmap_lookup_by_phandle(np, "rockchip,grf"); + if (IS_ERR(priv->grf)) { + dev_err(dev, "unable to get grf"); + return PTR_ERR(priv->grf); + } + + priv->tx_delay = 0x30; + of_property_read_u32(np, "tx_delay", &priv->tx_delay); + priv->rx_delay = 0x10; + of_property_read_u32(np, "rx_delay", &priv->rx_delay); + + priv->num_clks = ARRAY_SIZE(rk_gmac_clks); + priv->clks = xmalloc(priv->num_clks * sizeof(*priv->clks)); + memcpy(priv->clks, rk_gmac_clks, sizeof rk_gmac_clks); + + ret = clk_bulk_get(dev, priv->num_clks, priv->clks); + if (ret) { + dev_err(dev, "Failed to get clks: %s\n", strerror(-ret)); + return ret; + } + + ret = clk_bulk_enable(priv->num_clks, priv->clks); + if (ret) { + dev_err(dev, "Failed to enable clks: %s\n", strerror(-ret)); + return ret; + } + + rk_gmac_powerup(eqos); + + return 0; +} + +static struct eqos_ops rk_gmac_ops = { + .init = eqos_init_rk_gmac, + .get_ethaddr = eqos_get_ethaddr, + .set_ethaddr = eqos_set_ethaddr, + .adjust_link = eqos_rk_adjust_link, + .get_csr_clk_rate = eqos_get_csr_clk_rate_rk_gmac, + + .clk_csr = EQOS_MDIO_ADDR_CR_250_300, + .config_mac = EQOS_MAC_RXQ_CTRL0_RXQ0EN_ENABLED_AV, +}; + +static int rk_gmac_probe(struct device_d *dev) +{ + return eqos_probe(dev, &rk_gmac_ops, xzalloc(sizeof(struct eqos_rk_gmac))); +} + +static __maybe_unused struct of_device_id rk_gmac_compatible[] = { + { + .compatible = "rockchip,rk3568-gmac", + .data = &rk3568_ops, + }, { + /* sentinel */ + } +}; + +static struct driver_d rk_gmac_driver = { + .name = "eqos-rockchip", + .probe = rk_gmac_probe, + .remove = eqos_remove, + .of_compatible = DRV_OF_COMPAT(rk_gmac_compatible), +}; +device_platform_driver(rk_gmac_driver); diff --git a/drivers/net/macb.c b/drivers/net/macb.c index 14a0b45322..511846122a 100644 --- a/drivers/net/macb.c +++ b/drivers/net/macb.c @@ -52,6 +52,10 @@ #define TX_RING_BYTES (sizeof(struct macb_dma_desc) * TX_RING_SIZE) #define GEM_Q1_DESC_BYTES (sizeof(struct macb_dma_desc) * GEM_Q1_DESCS) +struct macb_config { + int (*txclk_init)(struct device_d *dev, struct clk **tx_clk); +}; + struct macb_device { void __iomem *regs; @@ -666,12 +670,115 @@ static void macb_init_rx_buffer_size(struct macb_device *bp, size_t size) size, bp->rx_buffer_size); } +#ifdef CONFIG_COMMON_CLK +/* This structure is only used for MACB on SiFive FU540 devices */ +struct sifive_fu540_macb_mgmt { + void __iomem *reg; + unsigned long rate; + struct clk clk; +}; + +static struct sifive_fu540_macb_mgmt *mgmt; + +static unsigned long fu540_macb_tx_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + return mgmt->rate; +} + +static long fu540_macb_tx_round_rate(struct clk_hw *hw, unsigned long rate, + unsigned long *parent_rate) +{ + if (WARN_ON(rate < 2500000)) + return 2500000; + else if (rate == 2500000) + return 2500000; + else if (WARN_ON(rate < 13750000)) + return 2500000; + else if (WARN_ON(rate < 25000000)) + return 25000000; + else if (rate == 25000000) + return 25000000; + else if (WARN_ON(rate < 75000000)) + return 25000000; + else if (WARN_ON(rate < 125000000)) + return 125000000; + else if (rate == 125000000) + return 125000000; + + WARN_ON(rate > 125000000); + + return 125000000; +} + +static int fu540_macb_tx_set_rate(struct clk_hw *hw, unsigned long rate, + unsigned long parent_rate) +{ + rate = fu540_macb_tx_round_rate(hw, rate, &parent_rate); + if (rate != 125000000) + iowrite32(1, mgmt->reg); + else + iowrite32(0, mgmt->reg); + mgmt->rate = rate; + + return 0; +} + +static const struct clk_ops fu540_c000_ops = { + .recalc_rate = fu540_macb_tx_recalc_rate, + .round_rate = fu540_macb_tx_round_rate, + .set_rate = fu540_macb_tx_set_rate, +}; + +static int fu540_c000_txclk_init(struct device_d *dev, struct clk **tx_clk) +{ + struct clk *clk; + struct resource *res; + int err = 0; + + mgmt = xzalloc(sizeof(*mgmt)); + + res = dev_request_mem_resource(dev, 1); + if (IS_ERR(res)) + return PTR_ERR(res); + + mgmt->reg = IOMEM(res->start); + + clk = &mgmt->clk; + + clk->name = "sifive-gemgxl-mgmt"; + clk->ops = &fu540_c000_ops; + + err = bclk_register(&mgmt->clk); + if (err) + return err; + + *tx_clk = &mgmt->clk; + + err = clk_enable(*tx_clk); + if (err) { + dev_err(dev, "failed to enable tx_clk (%u)\n", err); + *tx_clk = NULL; + return err; + } + + dev_info(dev, "Registered clk switch '%s'\n", clk->name); + return 0; +} +#else +static int fu540_c000_txclk_init(struct device_d *dev, struct clk **tx_clk) +{ + return -ENOSYS; +} +#endif + static int macb_probe(struct device_d *dev) { struct resource *iores; struct eth_device *edev; struct macb_device *macb; const char *pclk_name, *hclk_name; + const struct macb_config *config = NULL; u32 ncfgr; macb = xzalloc(sizeof(*macb)); @@ -725,6 +832,8 @@ static int macb_probe(struct device_d *dev) macb->phy_addr = -1; pclk_name = "pclk"; hclk_name = "hclk"; + + config = device_get_match_data(dev); } else { dev_err(dev, "macb: no platform_data\n"); return -ENODEV; @@ -767,6 +876,12 @@ static int macb_probe(struct device_d *dev) if (!IS_ERR(macb->rxclk)) clk_enable(macb->rxclk); + if (config) { + int ret = config->txclk_init(dev, &macb->txclk); + if (ret) + return ret; + } + macb->is_gem = read_is_gem(macb); if (macb_is_gem(macb)) @@ -808,12 +923,17 @@ static void macb_remove(struct device_d *dev) macb_halt(&macb->netdev); } +static const struct macb_config fu540_c000_config = { + .txclk_init = fu540_c000_txclk_init, +}; + static const struct of_device_id macb_dt_ids[] = { { .compatible = "cdns,at91sam9260-macb",}, { .compatible = "atmel,sama5d2-gem",}, { .compatible = "atmel,sama5d3-gem",}, { .compatible = "cdns,zynq-gem",}, { .compatible = "cdns,zynqmp-gem",}, + { .compatible = "sifive,fu540-c000-gem", .data = &fu540_c000_config }, { /* sentinel */ } }; diff --git a/drivers/net/phy/micrel.c b/drivers/net/phy/micrel.c index 4e46370241..ea193c84a7 100644 --- a/drivers/net/phy/micrel.c +++ b/drivers/net/phy/micrel.c @@ -28,13 +28,16 @@ #define KSZPHY_OMSO_MII_OVERRIDE BIT(0) /* general PHY control reg in vendor specific block. */ -#define MII_KSZPHY_CTRL 0x1F +#define MII_KSZPHY_CTRL 0x1F /* bitmap of PHY register to set interrupt mode */ #define KSZPHY_CTRL_INT_ACTIVE_HIGH BIT(9) #define KSZ9021_CTRL_INT_ACTIVE_HIGH BIT(14) #define KS8737_CTRL_INT_ACTIVE_HIGH BIT(14) #define KSZ8051_RMII_50MHZ_CLK BIT(7) +/* PHY Control 1 */ +#define MII_KSZPHY_CTRL_1 0x1e + /* Write/read to/from extended registers */ #define MII_KSZPHY_EXTREG 0x0b #define KSZPHY_EXTREG_WRITE 0x8000 @@ -63,18 +66,35 @@ static int kszphy_extended_read(struct phy_device *phydev, return phy_read(phydev, MII_KSZPHY_EXTREG_READ); } +/* Handle LED mode, shift = position of first led mode bit, usually 4 or 14 */ +static int kszphy_led_mode(struct phy_device *phydev, int reg, int shift) +{ + const struct device_d *dev = &phydev->dev; + const struct device_node *of_node = dev->device_node ? : dev->parent->device_node; + u32 val; + + if (!of_property_read_u32(of_node, "micrel,led-mode", &val)) { + if (val > 0x03) { + dev_err(dev, "led-mode 0x%02x out of range\n", val); + return -1; + } + return phy_modify(phydev, reg, 0x03 << shift, val << shift); + } + return 0; +} + static int kszphy_config_init(struct phy_device *phydev) { + kszphy_led_mode(phydev, MII_KSZPHY_CTRL_1, 14); + return 0; } static int ksz8021_config_init(struct phy_device *phydev) { - u16 val; + phy_set_bits(phydev, MII_KSZPHY_OMSO, KSZPHY_OMSO_B_CAST_OFF); - val = phy_read(phydev, MII_KSZPHY_OMSO); - val |= KSZPHY_OMSO_B_CAST_OFF; - phy_write(phydev, MII_KSZPHY_OMSO, val); + kszphy_led_mode(phydev, MII_KSZPHY_CTRL, 4); return 0; } @@ -89,6 +109,8 @@ static int ks8051_config_init(struct phy_device *phydev) phy_write(phydev, MII_KSZPHY_CTRL, regval); } + kszphy_led_mode(phydev, MII_KSZPHY_CTRL, 4); + return 0; } @@ -143,6 +165,8 @@ static int ksz9021_config_init(struct phy_device *phydev) ksz9021_load_values_from_of(phydev, of_node, MII_KSZPHY_TX_DATA_PAD_SKEW, tx_pad_skew_names); + + kszphy_led_mode(phydev, 0x11, 6); } return 0; diff --git a/drivers/net/phy/mv88e6xxx/chip.c b/drivers/net/phy/mv88e6xxx/chip.c index b1bffe5cbc..873c6f8463 100644 --- a/drivers/net/phy/mv88e6xxx/chip.c +++ b/drivers/net/phy/mv88e6xxx/chip.c @@ -779,10 +779,9 @@ static int mv88e6xxx_switch_reset(struct mv88e6xxx_chip *chip) return 0; } -static int mv88e6xxx_eeprom_read(struct device_d *dev, const int offset, - void *val, int bytes) +static int mv88e6xxx_eeprom_read(void *ctx, unsigned offset, void *val, size_t bytes) { - struct mv88e6xxx_chip *chip = dev->parent->priv; + struct mv88e6xxx_chip *chip = ctx; struct ethtool_eeprom eeprom = { .offset = offset, .len = bytes, @@ -794,10 +793,9 @@ static int mv88e6xxx_eeprom_read(struct device_d *dev, const int offset, return chip->info->ops->get_eeprom(chip, &eeprom, val); } -static int mv88e6xxx_eeprom_write(struct device_d *dev, const int offset, - const void *val, int bytes) +static int mv88e6xxx_eeprom_write(void *ctx, unsigned offset, const void *val, size_t bytes) { - struct mv88e6xxx_chip *chip = dev->parent->priv; + struct mv88e6xxx_chip *chip = ctx; struct ethtool_eeprom eeprom = { .offset = offset, .len = bytes, @@ -883,6 +881,7 @@ static int mv88e6xxx_probe(struct device_d *dev) struct nvmem_config config = { .name = basprintf("%s-eeprom", dev_name(dev)), .dev = dev, + .priv = chip, .word_size = 1, .stride = 1, .size = eeprom_len, diff --git a/drivers/nvmem/Makefile b/drivers/nvmem/Makefile index 7101c5aca4..617e3725a7 100644 --- a/drivers/nvmem/Makefile +++ b/drivers/nvmem/Makefile @@ -3,7 +3,7 @@ # obj-$(CONFIG_NVMEM) += nvmem_core.o -nvmem_core-y := core.o +nvmem_core-y := core.o regmap.o # Devices obj-$(CONFIG_NVMEM_SNVS_LPGPR) += nvmem_snvs_lpgpr.o diff --git a/drivers/nvmem/bsec.c b/drivers/nvmem/bsec.c index 836e62ecbc..509a5fa872 100644 --- a/drivers/nvmem/bsec.c +++ b/drivers/nvmem/bsec.c @@ -21,9 +21,7 @@ #define BSEC_OTP_SERIAL 13 struct bsec_priv { - struct regmap *map; u32 svc_id; - struct device_d dev; struct regmap_config map_config; struct nvmem_config config; }; @@ -72,61 +70,6 @@ static struct regmap_bus stm32_bsec_regmap_bus = { .reg_read = stm32_bsec_read_shadow, }; -static int stm32_bsec_write(struct device_d *dev, int offset, - const void *val, int bytes) -{ - struct bsec_priv *priv = dev->parent->priv; - - /* Allow only writing complete 32-bits aligned words */ - if ((bytes % 4) || (offset % 4)) - return -EINVAL; - - return regmap_bulk_write(priv->map, offset, val, bytes); -} - -static int stm32_bsec_read(struct device_d *dev, int offset, - void *buf, int bytes) -{ - struct bsec_priv *priv = dev->parent->priv; - u32 roffset, rbytes, val; - u8 *buf8 = buf, *val8 = (u8 *)&val; - int i, j = 0, ret, skip_bytes, size; - - /* Round unaligned access to 32-bits */ - roffset = rounddown(offset, 4); - skip_bytes = offset & 0x3; - rbytes = roundup(bytes + skip_bytes, 4); - - if (roffset + rbytes > priv->config.size) - return -EINVAL; - - for (i = roffset; i < roffset + rbytes; i += 4) { - ret = regmap_bulk_read(priv->map, i, &val, 4); - if (ret) { - dev_err(dev, "Can't read data%d (%d)\n", i, ret); - return ret; - } - - /* skip first bytes in case of unaligned read */ - if (skip_bytes) - size = min(bytes, 4 - skip_bytes); - else - size = min(bytes, 4); - - memcpy(&buf8[j], &val8[skip_bytes], size); - bytes -= size; - j += size; - skip_bytes = 0; - } - - return 0; -} - -static const struct nvmem_bus stm32_bsec_nvmem_bus = { - .write = stm32_bsec_write, - .read = stm32_bsec_read, -}; - static void stm32_bsec_set_unique_machine_id(struct regmap *map) { u32 unique_id[3]; @@ -153,9 +96,9 @@ static int stm32_bsec_read_mac(struct regmap *map, int offset, u8 *mac) return 0; } -static void stm32_bsec_init_dt(struct bsec_priv *priv) +static void stm32_bsec_init_dt(struct device_d *dev, struct regmap *map) { - struct device_node *node = priv->dev.parent->device_node; + struct device_node *node = dev->device_node; struct device_node *rnode; u32 phandle, offset; char mac[ETH_ALEN]; @@ -164,9 +107,6 @@ static void stm32_bsec_init_dt(struct bsec_priv *priv) int len; int ret; - if (!node) - return; - prop = of_get_property(node, "barebox,provide-mac-address", &len); if (!prop) return; @@ -179,10 +119,9 @@ static void stm32_bsec_init_dt(struct bsec_priv *priv) rnode = of_find_node_by_phandle(phandle); offset = be32_to_cpup(prop++); - ret = stm32_bsec_read_mac(priv->map, offset, mac); + ret = stm32_bsec_read_mac(map, offset, mac); if (ret) { - dev_warn(&priv->dev, "error setting MAC address: %s\n", - strerror(-ret)); + dev_warn(dev, "error setting MAC address: %s\n", strerror(-ret)); return; } @@ -191,6 +130,7 @@ static void stm32_bsec_init_dt(struct bsec_priv *priv) static int stm32_bsec_probe(struct device_d *dev) { + struct regmap *map; struct bsec_priv *priv; int ret = 0; const struct stm32_bsec_data *data; @@ -204,35 +144,23 @@ static int stm32_bsec_probe(struct device_d *dev) priv->svc_id = data->svc_id; - dev_set_name(&priv->dev, "bsec"); - priv->dev.parent = dev; - register_device(&priv->dev); - priv->map_config.reg_bits = 32; priv->map_config.val_bits = 32; priv->map_config.reg_stride = 4; priv->map_config.max_register = data->num_regs; - priv->map = regmap_init(dev, &stm32_bsec_regmap_bus, priv, &priv->map_config); - if (IS_ERR(priv->map)) - return PTR_ERR(priv->map); - - priv->config.name = "stm32-bsec"; - priv->config.dev = dev; - priv->config.stride = 1; - priv->config.word_size = 1; - priv->config.size = data->num_regs; - priv->config.bus = &stm32_bsec_nvmem_bus; - dev->priv = priv; + map = regmap_init(dev, &stm32_bsec_regmap_bus, priv, &priv->map_config); + if (IS_ERR(map)) + return PTR_ERR(map); - nvmem = nvmem_register(&priv->config); + nvmem = nvmem_regmap_register(map, "stm32-bsec"); if (IS_ERR(nvmem)) return PTR_ERR(nvmem); if (IS_ENABLED(CONFIG_MACHINE_ID)) - stm32_bsec_set_unique_machine_id(priv->map); + stm32_bsec_set_unique_machine_id(map); - stm32_bsec_init_dt(priv); + stm32_bsec_init_dt(dev, map); return 0; } diff --git a/drivers/nvmem/core.c b/drivers/nvmem/core.c index 2a1c4b6941..cfeecf70cd 100644 --- a/drivers/nvmem/core.c +++ b/drivers/nvmem/core.c @@ -33,6 +33,7 @@ struct nvmem_device { size_t size; bool read_only; struct cdev cdev; + void *priv; }; struct nvmem_cell { @@ -206,6 +207,7 @@ struct nvmem_device *nvmem_register(const struct nvmem_config *config) nvmem->bus = config->bus; np = config->dev->device_node; nvmem->dev.device_node = np; + nvmem->priv = config->priv; nvmem->read_only = of_property_read_bool(np, "read-only") | config->read_only; @@ -507,7 +509,7 @@ static int __nvmem_cell_read(struct nvmem_device *nvmem, { int rc; - rc = nvmem->bus->read(&nvmem->dev, cell->offset, buf, cell->bytes); + rc = nvmem->bus->read(nvmem->priv, cell->offset, buf, cell->bytes); if (IS_ERR_VALUE(rc)) return rc; @@ -572,7 +574,7 @@ static inline void *nvmem_cell_prepare_write_buffer(struct nvmem_cell *cell, *b <<= bit_offset; /* setup the first byte with lsb bits from nvmem */ - rc = nvmem->bus->read(&nvmem->dev, cell->offset, &v, 1); + rc = nvmem->bus->read(nvmem->priv, cell->offset, &v, 1); *b++ |= GENMASK(bit_offset - 1, 0) & v; /* setup rest of the byte if any */ @@ -589,7 +591,7 @@ static inline void *nvmem_cell_prepare_write_buffer(struct nvmem_cell *cell, /* if it's not end on byte boundary */ if ((nbits + bit_offset) % BITS_PER_BYTE) { /* setup the last byte with msb bits from nvmem */ - rc = nvmem->bus->read(&nvmem->dev, cell->offset + cell->bytes - 1, + rc = nvmem->bus->read(nvmem->priv, cell->offset + cell->bytes - 1, &v, 1); *p |= GENMASK(7, (nbits + bit_offset) % BITS_PER_BYTE) & v; @@ -622,7 +624,7 @@ int nvmem_cell_write(struct nvmem_cell *cell, void *buf, size_t len) return PTR_ERR(buf); } - rc = nvmem->bus->write(&nvmem->dev, cell->offset, buf, cell->bytes); + rc = nvmem->bus->write(nvmem->priv, cell->offset, buf, cell->bytes); /* free the tmp buffer */ if (cell->bit_offset || cell->nbits) @@ -719,7 +721,7 @@ int nvmem_device_read(struct nvmem_device *nvmem, if (!bytes) return 0; - rc = nvmem->bus->read(&nvmem->dev, offset, buf, bytes); + rc = nvmem->bus->read(nvmem->priv, offset, buf, bytes); if (IS_ERR_VALUE(rc)) return rc; @@ -753,7 +755,7 @@ int nvmem_device_write(struct nvmem_device *nvmem, if (!bytes) return 0; - rc = nvmem->bus->write(&nvmem->dev, offset, buf, bytes); + rc = nvmem->bus->write(nvmem->priv, offset, buf, bytes); if (IS_ERR_VALUE(rc)) return rc; diff --git a/drivers/nvmem/eeprom_93xx46.c b/drivers/nvmem/eeprom_93xx46.c index 49ed396dc2..5833cb0d86 100644 --- a/drivers/nvmem/eeprom_93xx46.c +++ b/drivers/nvmem/eeprom_93xx46.c @@ -79,10 +79,9 @@ static inline bool has_quirk_instruction_length(struct eeprom_93xx46_dev *edev) return edev->pdata->quirks & EEPROM_93XX46_QUIRK_INSTRUCTION_LENGTH; } -static int eeprom_93xx46_read(struct device_d *dev, int off, - void *val, int count) +static int eeprom_93xx46_read(void *ctx, unsigned off, void *val, size_t count) { - struct eeprom_93xx46_dev *edev = dev->parent->priv; + struct eeprom_93xx46_dev *edev = ctx; char *buf = val; int err = 0; @@ -241,10 +240,9 @@ eeprom_93xx46_write_word(struct eeprom_93xx46_dev *edev, return ret; } -static int eeprom_93xx46_write(struct device_d *dev, const int off, - const void *val, int count) +static int eeprom_93xx46_write(void *ctx, unsigned off, const void *val, size_t count) { - struct eeprom_93xx46_dev *edev = dev->parent->priv; + struct eeprom_93xx46_dev *edev = ctx; const char *buf = val; int i, ret, step = 1; @@ -411,14 +409,13 @@ static int eeprom_93xx46_probe(struct device_d *dev) edev->size = 128; edev->nvmem_config.name = dev_name(&spi->dev); edev->nvmem_config.dev = &spi->dev; + edev->nvmem_config.priv = edev; edev->nvmem_config.read_only = pd->flags & EE_READONLY; edev->nvmem_config.bus = &eeprom_93xx46_nvmem_bus; edev->nvmem_config.stride = 4; edev->nvmem_config.word_size = 1; edev->nvmem_config.size = edev->size; - dev->priv = edev; - edev->nvmem = nvmem_register(&edev->nvmem_config); if (IS_ERR(edev->nvmem)) { err = PTR_ERR(edev->nvmem); diff --git a/drivers/nvmem/ocotp.c b/drivers/nvmem/ocotp.c index cee50955e9..b2fad3c687 100644 --- a/drivers/nvmem/ocotp.c +++ b/drivers/nvmem/ocotp.c @@ -673,18 +673,16 @@ static void imx_ocotp_init_dt(struct ocotp_priv *priv) } } -static int imx_ocotp_write(struct device_d *dev, const int offset, - const void *val, int bytes) +static int imx_ocotp_write(void *ctx, unsigned offset, const void *val, size_t bytes) { - struct ocotp_priv *priv = dev->parent->priv; + struct ocotp_priv *priv = ctx; return regmap_bulk_write(priv->map, offset, val, bytes); } -static int imx_ocotp_read(struct device_d *dev, const int offset, void *val, - int bytes) +static int imx_ocotp_read(void *ctx, unsigned offset, void *val, size_t bytes) { - struct ocotp_priv *priv = dev->parent->priv; + struct ocotp_priv *priv = ctx; return regmap_bulk_read(priv->map, offset, val, bytes); } @@ -746,11 +744,11 @@ static int imx_ocotp_probe(struct device_d *dev) priv->config.name = "imx-ocotp"; priv->config.dev = dev; + priv->config.priv = priv; priv->config.stride = 4; priv->config.word_size = 4; priv->config.size = data->num_regs; priv->config.bus = &imx_ocotp_nvmem_bus; - dev->priv = priv; nvmem = nvmem_register(&priv->config); if (IS_ERR(nvmem)) diff --git a/drivers/nvmem/rave-sp-eeprom.c b/drivers/nvmem/rave-sp-eeprom.c index 6c6ed17f18..f27491e547 100644 --- a/drivers/nvmem/rave-sp-eeprom.c +++ b/drivers/nvmem/rave-sp-eeprom.c @@ -280,19 +280,15 @@ static int rave_sp_eeprom_access(struct rave_sp_eeprom *eeprom, return 0; } -static int rave_sp_eeprom_read(struct device_d *dev, const int offset, - void *val, int bytes) +static int rave_sp_eeprom_read(void *ctx, unsigned offset, void *val, size_t bytes) { - return rave_sp_eeprom_access(dev->parent->priv, - RAVE_SP_EEPROM_READ, + return rave_sp_eeprom_access(ctx, RAVE_SP_EEPROM_READ, offset, val, bytes); } -static int rave_sp_eeprom_write(struct device_d *dev, const int offset, - const void *val, int bytes) +static int rave_sp_eeprom_write(void *ctx, unsigned offset, const void *val, size_t bytes) { - return rave_sp_eeprom_access(dev->parent->priv, - RAVE_SP_EEPROM_WRITE, + return rave_sp_eeprom_access(ctx, RAVE_SP_EEPROM_WRITE, offset, (void *)val, bytes); } @@ -329,8 +325,6 @@ static int rave_sp_eeprom_probe(struct device_d *dev) eeprom->address = reg[0]; eeprom->sp = sp; - dev->priv = eeprom; - if (size > SZ_8K) eeprom->header_size = RAVE_SP_EEPROM_HEADER_BIG; else @@ -343,6 +337,7 @@ static int rave_sp_eeprom_probe(struct device_d *dev) of_property_read_string(dev->device_node, "zii,eeprom-name", &config.name); config.dev = dev; + config.priv = eeprom; config.word_size = 1; config.stride = 1; config.size = reg[1]; diff --git a/drivers/nvmem/regmap.c b/drivers/nvmem/regmap.c new file mode 100644 index 0000000000..346d2516f3 --- /dev/null +++ b/drivers/nvmem/regmap.c @@ -0,0 +1,78 @@ +// SPDX-License-Identifier: GPL-2.0 +#include <common.h> +#include <driver.h> +#include <malloc.h> +#include <xfuncs.h> +#include <errno.h> +#include <init.h> +#include <io.h> +#include <regmap.h> +#include <linux/nvmem-provider.h> + +static int nvmem_regmap_write(void *ctx, unsigned offset, const void *val, size_t bytes) +{ + return regmap_bulk_write(ctx, offset, val, bytes); +} + +static int nvmem_regmap_read(void *ctx, unsigned offset, void *buf, size_t bytes) +{ + struct regmap *map = ctx; + size_t rbytes, stride, skip_bytes; + u32 roffset, val; + u8 *buf8 = buf, *val8 = (u8 *)&val; + int i, j = 0, ret, size; + + stride = regmap_get_reg_stride(map); + + roffset = rounddown(offset, stride); + skip_bytes = offset & (stride - 1); + rbytes = roundup(bytes + skip_bytes, stride); + + if (roffset + rbytes > stride * regmap_get_max_register(map)) + return -EINVAL; + + for (i = roffset; i < roffset + rbytes; i += stride) { + ret = regmap_bulk_read(map, i, &val, stride); + if (ret) { + dev_err(regmap_get_device(map), "Can't read data%d (%d)\n", i, ret); + return ret; + } + + /* skip first bytes in case of unaligned read */ + if (skip_bytes) + size = min(bytes, stride - skip_bytes); + else + size = min(bytes, stride); + + memcpy(&buf8[j], &val8[skip_bytes], size); + bytes -= size; + j += size; + skip_bytes = 0; + } + + return 0; +} + +static struct nvmem_bus nvmem_regmap_bus = { + .read = nvmem_regmap_read, + .write = nvmem_regmap_write, +}; + +struct nvmem_device *nvmem_regmap_register(struct regmap *map, const char *name) +{ + struct nvmem_config config; + + /* Can be retrofitted if needed */ + if (regmap_get_reg_stride(map) != regmap_get_val_bytes(map)) + return ERR_PTR(-EINVAL); + + config.name = name; + config.dev = regmap_get_device(map); + config.priv = map; + config.stride = 1; + config.word_size = 1; + config.size = regmap_get_max_register(map) * regmap_get_reg_stride(map); + config.bus = &nvmem_regmap_bus; + + return nvmem_register(&config); +} diff --git a/drivers/nvmem/snvs_lpgpr.c b/drivers/nvmem/snvs_lpgpr.c index fe7fe599f6..1890af135d 100644 --- a/drivers/nvmem/snvs_lpgpr.c +++ b/drivers/nvmem/snvs_lpgpr.c @@ -42,10 +42,9 @@ static const struct snvs_lpgpr_cfg snvs_lpgpr_cfg_imx6q = { .offset_lplr = IMX6Q_SNVS_LPLR, }; -static int snvs_lpgpr_write(struct device_d *dev, const int offset, - const void *val, int bytes) +static int snvs_lpgpr_write(void *ctx, unsigned offset, const void *val, size_t bytes) { - struct snvs_lpgpr_priv *priv = dev->parent->priv; + struct snvs_lpgpr_priv *priv = ctx; const struct snvs_lpgpr_cfg *dcfg = priv->dcfg; unsigned int lock_reg; int ret; @@ -68,10 +67,9 @@ static int snvs_lpgpr_write(struct device_d *dev, const int offset, bytes); } -static int snvs_lpgpr_read(struct device_d *dev, const int offset, void *val, - int bytes) +static int snvs_lpgpr_read(void *ctx, unsigned offset, void *val, size_t bytes) { - struct snvs_lpgpr_priv *priv = dev->parent->priv; + struct snvs_lpgpr_priv *priv = ctx; const struct snvs_lpgpr_cfg *dcfg = priv->dcfg; return regmap_bulk_read(priv->regmap, dcfg->offset + offset, @@ -113,6 +111,7 @@ static int snvs_lpgpr_probe(struct device_d *dev) cfg = &priv->cfg; cfg->name = dev_name(dev); cfg->dev = dev; + cfg->priv = priv; cfg->stride = 4; cfg->word_size = 4; cfg->size = 4; @@ -124,8 +123,6 @@ static int snvs_lpgpr_probe(struct device_d *dev) return PTR_ERR(nvmem); } - dev->priv = priv; - return 0; } diff --git a/drivers/of/base.c b/drivers/of/base.c index 6fe02649ee..193bae7fa0 100644 --- a/drivers/of/base.c +++ b/drivers/of/base.c @@ -1048,7 +1048,7 @@ int of_property_match_string(struct device_node *np, const char *propname, } EXPORT_SYMBOL_GPL(of_property_match_string); -const __be32 *of_prop_next_u32(struct property *prop, const __be32 *cur, +const __be32 *of_prop_next_u32(const struct property *prop, const __be32 *cur, u32 *pu) { const void *curv = cur; @@ -1074,7 +1074,7 @@ out_val: } EXPORT_SYMBOL_GPL(of_prop_next_u32); -const char *of_prop_next_string(struct property *prop, const char *cur) +const char *of_prop_next_string(const struct property *prop, const char *cur) { const void *curv = cur; const void *value; @@ -1699,32 +1699,34 @@ int of_set_root_node(struct device_node *node) return 0; } -void barebox_register_of(struct device_node *root) +int barebox_register_of(struct device_node *root) { if (root_node) - return; + return -EBUSY; of_set_root_node(root); of_fix_tree(root); if (IS_ENABLED(CONFIG_OFDEVICE)) - of_probe(); + return of_probe(); + + return 0; } -void barebox_register_fdt(const void *dtb) +int barebox_register_fdt(const void *dtb) { struct device_node *root; if (root_node) - return; + return -EBUSY; root = of_unflatten_dtb(dtb); if (IS_ERR(root)) { pr_err("Cannot unflatten dtb: %pe\n", root); - return; + return PTR_ERR(root); } - barebox_register_of(root); + return barebox_register_of(root); } /** @@ -2002,6 +2004,14 @@ static void __of_print_property(struct property *p, int indent) printf(";\n"); } +void of_print_properties(struct device_node *node) +{ + struct property *prop; + + list_for_each_entry(prop, &node->properties, list) + __of_print_property(prop, 0); +} + static int __of_print_parents(struct device_node *node) { int indent, i; @@ -2246,6 +2256,7 @@ int of_add_memory(struct device_node *node, bool dump) return -ENXIO; while (!of_address_to_resource(node, n, &res)) { + int err; n++; if (!resource_size(&res)) continue; @@ -2253,12 +2264,15 @@ int of_add_memory(struct device_node *node, bool dump) if (!of_device_is_available(node)) continue; - of_add_memory_bank(node, dump, mem_bank_num, + err = of_add_memory_bank(node, dump, mem_bank_num, res.start, resource_size(&res)); + if (err) + ret = err; + mem_bank_num++; } - return 0; + return ret; } static struct device_node *of_chosen; @@ -2281,18 +2295,25 @@ const struct of_device_id of_default_bus_match_table[] = { } }; -static void of_probe_memory(void) +static int of_probe_memory(void) { struct device_node *memory = root_node; + int ret = 0; /* Parse all available node with "memory" device_type */ while (1) { + int err; + memory = of_find_node_by_type(memory, "memory"); if (!memory) break; - of_add_memory(memory, false); + err = of_add_memory(memory, false); + if (err) + ret = err; } + + return ret; } static void of_platform_device_create_root(struct device_node *np) @@ -2313,6 +2334,7 @@ static void of_platform_device_create_root(struct device_node *np) int of_probe(void) { struct device_node *firmware; + int ret; if(!root_node) return -ENODEV; @@ -2323,7 +2345,7 @@ int of_probe(void) if (of_model) barebox_set_model(of_model); - of_probe_memory(); + ret = of_probe_memory(); firmware = of_find_node_by_path("/firmware"); if (firmware) @@ -2334,7 +2356,7 @@ int of_probe(void) of_clk_init(root_node, NULL); of_platform_populate(root_node, of_default_bus_match_table, NULL); - return 0; + return ret; } /** diff --git a/drivers/of/mem_generic.c b/drivers/of/mem_generic.c index 9094243c04..55d93bcb06 100644 --- a/drivers/of/mem_generic.c +++ b/drivers/of/mem_generic.c @@ -2,14 +2,15 @@ #include <of.h> #include <memory.h> -void of_add_memory_bank(struct device_node *node, bool dump, int r, +int of_add_memory_bank(struct device_node *node, bool dump, int r, u64 base, u64 size) { static char str[6]; sprintf(str, "ram%d", r); - barebox_add_memory_bank(str, base, size); if (dump) pr_info("%s: %s: 0x%llx@0x%llx\n", node->name, str, size, base); + + return barebox_add_memory_bank(str, base, size); } diff --git a/drivers/of/of_gpio.c b/drivers/of/of_gpio.c index 7cbeeaf69e..e1cafdc848 100644 --- a/drivers/of/of_gpio.c +++ b/drivers/of/of_gpio.c @@ -35,6 +35,13 @@ static void of_gpio_flags_quirks(struct device_node *np, if (active_low) *flags |= OF_GPIO_ACTIVE_LOW; } + + /* Legacy handling of stmmac's active-low PHY reset line */ + if (IS_ENABLED(CONFIG_DRIVER_NET_DESIGNWARE_EQOS) && + !strcmp(propname, "snps,reset-gpio") && + of_property_read_bool(np, "snps,reset-active-low")) + *flags |= OF_GPIO_ACTIVE_LOW; + } /** diff --git a/drivers/pci/pci-mvebu.c b/drivers/pci/pci-mvebu.c index ae2e83dacd..0c5e34116c 100644 --- a/drivers/pci/pci-mvebu.c +++ b/drivers/pci/pci-mvebu.c @@ -270,8 +270,8 @@ static struct mvebu_pcie *mvebu_pcie_port_probe(struct device_d *dev, enum of_gpio_flags flags; struct property *prop; const __be32 *p; - int reset_gpio; - u32 u, port, lane, lane_mask, devfn; + int reset_gpio, devfn; + u32 u, port, lane, lane_mask; int mem_target, mem_attr; int io_target, io_attr; int ret; diff --git a/drivers/pinctrl/pinctrl-rockchip.c b/drivers/pinctrl/pinctrl-rockchip.c index 58f2c4af26..be44067c8f 100644 --- a/drivers/pinctrl/pinctrl-rockchip.c +++ b/drivers/pinctrl/pinctrl-rockchip.c @@ -27,6 +27,7 @@ #include <of.h> #include <of_address.h> #include <pinctrl.h> +#include <dt-bindings/pinctrl/rockchip.h> #include <linux/basic_mmio_gpio.h> #include <linux/clk.h> @@ -36,6 +37,7 @@ enum rockchip_pinctrl_type { RK2928, RK3066B, RK3188, + RK3568, }; enum rockchip_pin_bank_type { @@ -43,6 +45,70 @@ enum rockchip_pin_bank_type { RK3188_BANK0, }; +/** + * Generate a bitmask for setting a value (v) with a write mask bit in hiword + * register 31:16 area. + */ +#define WRITE_MASK_VAL(h, l, v) \ + (GENMASK(((h) + 16), ((l) + 16)) | (((v) << (l)) & GENMASK((h), (l)))) + +/* + * Encode variants of iomux registers into a type variable + */ +#define IOMUX_GPIO_ONLY BIT(0) +#define IOMUX_WIDTH_4BIT BIT(1) +#define IOMUX_SOURCE_PMU BIT(2) +#define IOMUX_UNROUTED BIT(3) +#define IOMUX_WIDTH_3BIT BIT(4) +#define IOMUX_WIDTH_2BIT BIT(5) + +/** + * struct rockchip_iomux + * @type: iomux variant using IOMUX_* constants + * @offset: if initialized to -1 it will be autocalculated, by specifying + * an initial offset value the relevant source offset can be reset + * to a new value for autocalculating the following iomux registers. + */ +struct rockchip_iomux { + int type; + int offset; +}; + +/* + * enum type index corresponding to rockchip_perpin_drv_list arrays index. + */ +enum rockchip_pin_drv_type { + DRV_TYPE_IO_DEFAULT = 0, + DRV_TYPE_IO_1V8_OR_3V0, + DRV_TYPE_IO_1V8_ONLY, + DRV_TYPE_IO_1V8_3V0_AUTO, + DRV_TYPE_IO_3V3_ONLY, + DRV_TYPE_MAX +}; + +/* + * enum type index corresponding to rockchip_pull_list arrays index. + */ +enum rockchip_pin_pull_type { + PULL_TYPE_IO_DEFAULT = 0, + PULL_TYPE_IO_1V8_ONLY, + PULL_TYPE_MAX +}; + +/** + * struct rockchip_drv + * @drv_type: drive strength variant using rockchip_perpin_drv_type + * @offset: if initialized to -1 it will be autocalculated, by specifying + * an initial offset value the relevant source offset can be reset + * to a new value for autocalculating the following drive strength + * registers. if used chips own cal_drv func instead to calculate + * registers offset, the variant could be ignored. + */ +struct rockchip_drv { + enum rockchip_pin_drv_type drv_type; + int offset; +}; + struct rockchip_pin_bank { void __iomem *reg_base; struct clk *clk; @@ -50,11 +116,14 @@ struct rockchip_pin_bank { u8 nr_pins; char *name; u8 bank_num; + struct rockchip_iomux iomux[4]; + struct rockchip_drv drv[4]; enum rockchip_pin_bank_type bank_type; bool valid; struct device_node *of_node; struct rockchip_pinctrl *drvdata; struct bgpio_chip bgpio_chip; + u32 route_mask; }; #define PIN_BANK(id, pins, label) \ @@ -64,15 +133,78 @@ struct rockchip_pin_bank { .name = label, \ } +#define PIN_BANK_IOMUX_FLAGS(id, pins, label, iom0, iom1, iom2, iom3) \ + { \ + .bank_num = id, \ + .nr_pins = pins, \ + .name = label, \ + .iomux = { \ + { .type = iom0, .offset = -1 }, \ + { .type = iom1, .offset = -1 }, \ + { .type = iom2, .offset = -1 }, \ + { .type = iom3, .offset = -1 }, \ + }, \ + } + +#define PIN_BANK_MUX_ROUTE_FLAGS(ID, PIN, FUNC, REG, VAL, FLAG) \ + { \ + .bank_num = ID, \ + .pin = PIN, \ + .func = FUNC, \ + .route_offset = REG, \ + .route_val = VAL, \ + .route_location = FLAG, \ + } + +#define RK_MUXROUTE_SAME(ID, PIN, FUNC, REG, VAL) \ + PIN_BANK_MUX_ROUTE_FLAGS(ID, PIN, FUNC, REG, VAL, ROCKCHIP_ROUTE_SAME) + +#define RK_MUXROUTE_GRF(ID, PIN, FUNC, REG, VAL) \ + PIN_BANK_MUX_ROUTE_FLAGS(ID, PIN, FUNC, REG, VAL, ROCKCHIP_ROUTE_GRF) + +#define RK_MUXROUTE_PMU(ID, PIN, FUNC, REG, VAL) \ + PIN_BANK_MUX_ROUTE_FLAGS(ID, PIN, FUNC, REG, VAL, ROCKCHIP_ROUTE_PMU) + +enum rockchip_mux_route_location { + ROCKCHIP_ROUTE_SAME = 0, + ROCKCHIP_ROUTE_PMU, + ROCKCHIP_ROUTE_GRF, +}; + +/** + * struct rockchip_mux_recalced_data: represent a pin iomux data. + * @bank_num: bank number. + * @pin: index at register or used to calc index. + * @func: the min pin. + * @route_location: the mux route location (same, pmu, grf). + * @route_offset: the max pin. + * @route_val: the register offset. + */ +struct rockchip_mux_route_data { + u8 bank_num; + u8 pin; + u8 func; + enum rockchip_mux_route_location route_location; + u32 route_offset; + u32 route_val; +}; + struct rockchip_pin_ctrl { struct rockchip_pin_bank *pin_banks; u32 nr_banks; u32 nr_pins; char *label; enum rockchip_pinctrl_type type; - int mux_offset; + int grf_mux_offset; + int pmu_mux_offset; + int grf_drv_offset; + int pmu_drv_offset; + struct rockchip_mux_route_data *iomux_routes; + u32 niomux_routes; void (*pull_calc_reg)(struct rockchip_pin_bank *bank, int pin_num, void __iomem **reg, u8 *bit); + void (*drv_calc_reg)(struct rockchip_pin_bank *bank, + int pin_num, void __iomem **reg, u8 *bit); }; struct rockchip_pinctrl { @@ -96,6 +228,110 @@ enum { RK_GPIO_EXT_PORT = 0x50, }; +/* GPIO registers */ +enum { + RK_GPIOV2_DR_L = 0x00, + RK_GPIOV2_DR_H = 0x04, + RK_GPIOV2_DDR_L = 0x08, + RK_GPIOV2_DDR_H = 0x0c, +}; + +static struct rockchip_pin_bank *gc_to_rockchip_pinctrl(struct gpio_chip *gc) +{ + struct bgpio_chip *bgc = to_bgpio_chip(gc); + + return container_of(bgc, struct rockchip_pin_bank, bgpio_chip); +} + +static int rockchip_gpiov2_direction_input(struct gpio_chip *gc, unsigned int gpio) +{ + struct rockchip_pin_bank *bank = gc_to_rockchip_pinctrl(gc); + u32 mask; + + mask = 1 << (16 + (gpio % 16)); + + if (gpio < 16) + writel(mask, bank->reg_base + RK_GPIOV2_DDR_L); + else + writel(mask, bank->reg_base + RK_GPIOV2_DDR_H); + + return 0; +} + +static int rockchip_gpiov2_get_direction(struct gpio_chip *gc, unsigned int gpio) +{ + struct rockchip_pin_bank *bank = gc_to_rockchip_pinctrl(gc); + u32 r; + + if (gpio < 16) + r = readl(bank->reg_base + RK_GPIOV2_DDR_L); + else + r = readl(bank->reg_base + RK_GPIOV2_DDR_H); + + return r & BIT(gpio % 16) ? GPIOF_DIR_OUT : GPIOF_DIR_IN; +} + +static void rockchip_gpiov2_set_value(struct gpio_chip *gc, unsigned int gpio, + int val) +{ + struct rockchip_pin_bank *bank = gc_to_rockchip_pinctrl(gc); + u32 mask, vval = 0; + + mask = 1 << (16 + (gpio % 16)); + if (val) + vval = 1 << (gpio % 16); + + if (gpio < 16) + writel(mask | vval, bank->reg_base + RK_GPIOV2_DR_L); + else + writel(mask | vval, bank->reg_base + RK_GPIOV2_DR_H); +} + +static int rockchip_gpiov2_direction_output(struct gpio_chip *gc, + unsigned int gpio, int val) +{ + struct rockchip_pin_bank *bank = gc_to_rockchip_pinctrl(gc); + u32 mask, out, vval = 0; + + mask = 1 << (16 + (gpio % 16)); + out = 1 << (gpio % 16); + if (val) + vval = 1 << (gpio % 16); + + if (gpio < 16) { + writel(mask | vval, bank->reg_base + RK_GPIOV2_DR_L); + writel(mask | out, bank->reg_base + RK_GPIOV2_DDR_L); + } else { + writel(mask | vval, bank->reg_base + RK_GPIOV2_DR_H); + writel(mask | out, bank->reg_base + RK_GPIOV2_DDR_H); + } + + return 0; +} + +static int rockchip_gpiov2_get_value(struct gpio_chip *gc, unsigned int gpio) +{ + struct rockchip_pin_bank *bank = gc_to_rockchip_pinctrl(gc); + u32 mask, r; + + mask = 1 << (gpio % 16); + + if (gpio < 16) + r = readl(bank->reg_base + RK_GPIOV2_DR_L); + else + r = readl(bank->reg_base + RK_GPIOV2_DR_L); + + return r & mask ? 1 : 0; +} + +static struct gpio_ops rockchip_gpio_ops = { + .direction_input = rockchip_gpiov2_direction_input, + .direction_output = rockchip_gpiov2_direction_output, + .get = rockchip_gpiov2_get_value, + .set = rockchip_gpiov2_set_value, + .get_direction = rockchip_gpiov2_get_direction, +}; + static int rockchip_gpiolib_register(struct device_d *dev, struct rockchip_pinctrl *info) { @@ -106,6 +342,8 @@ static int rockchip_gpiolib_register(struct device_d *dev, int i; for (i = 0; i < ctrl->nr_banks; ++i, ++bank) { + struct gpio_chip *gpio = &bank->bgpio_chip.gc; + if (!bank->valid) { dev_warn(dev, "bank %s is not valid\n", bank->name); continue; @@ -113,12 +351,24 @@ static int rockchip_gpiolib_register(struct device_d *dev, reg_base = bank->reg_base; - ret = bgpio_init(&bank->bgpio_chip, dev, 4, - reg_base + RK_GPIO_EXT_PORT, - reg_base + RK_GPIO_SWPORT_DR, NULL, - reg_base + RK_GPIO_SWPORT_DDR, NULL, 0); - if (ret) - goto fail; + if (ctrl->type == RK3568) { + gpio->ngpio = 32; + gpio->dev = dev; + gpio->ops = &rockchip_gpio_ops; + gpio->base = of_alias_get_id(bank->of_node, "gpio"); + if (gpio->base < 0) + return -EINVAL; + gpio->base *= 32; + } else { + ret = bgpio_init(&bank->bgpio_chip, dev, 4, + reg_base + RK_GPIO_EXT_PORT, + reg_base + RK_GPIO_SWPORT_DR, NULL, + reg_base + RK_GPIO_SWPORT_DDR, NULL, 0); + if (ret) + goto fail; + } + + bank->bgpio_chip.gc.dev = of_find_device_by_node(bank->of_node); bank->bgpio_chip.gc.ngpio = bank->nr_pins; ret = gpiochip_add(&bank->bgpio_chip.gc); @@ -225,18 +475,147 @@ static void rk3188_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank, } } +#define RK3568_PULL_PMU_OFFSET 0x20 +#define RK3568_PULL_GRF_OFFSET 0x80 +#define RK3568_PULL_BITS_PER_PIN 2 +#define RK3568_PULL_PINS_PER_REG 8 +#define RK3568_PULL_BANK_STRIDE 0x10 + +static void rk3568_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank, + int pin_num, void __iomem **reg, + u8 *bit) +{ + struct rockchip_pinctrl *info = bank->drvdata; + + if (bank->bank_num == 0) { + *reg = info->reg_pmu + RK3568_PULL_PMU_OFFSET; + *reg += bank->bank_num * RK3568_PULL_BANK_STRIDE; + *reg += ((pin_num / RK3568_PULL_PINS_PER_REG) * 4); + + *bit = pin_num % RK3568_PULL_PINS_PER_REG; + *bit *= RK3568_PULL_BITS_PER_PIN; + } else { + *reg = info->reg_base + RK3568_PULL_GRF_OFFSET; + *reg += (bank->bank_num - 1) * RK3568_PULL_BANK_STRIDE; + *reg += ((pin_num / RK3568_PULL_PINS_PER_REG) * 4); + + *bit = (pin_num % RK3568_PULL_PINS_PER_REG); + *bit *= RK3568_PULL_BITS_PER_PIN; + } +} + +#define RK3568_DRV_PMU_OFFSET 0x70 +#define RK3568_DRV_GRF_OFFSET 0x200 +#define RK3568_DRV_BITS_PER_PIN 8 +#define RK3568_DRV_PINS_PER_REG 2 +#define RK3568_DRV_BANK_STRIDE 0x40 + +static void rk3568_calc_drv_reg_and_bit(struct rockchip_pin_bank *bank, + int pin_num, void __iomem **reg, u8 *bit) +{ + struct rockchip_pinctrl *info = bank->drvdata; + + /* The first 32 pins of the first bank are located in PMU */ + if (bank->bank_num == 0) { + *reg = info->reg_pmu + RK3568_DRV_PMU_OFFSET; + *reg += ((pin_num / RK3568_DRV_PINS_PER_REG) * 4); + + *bit = pin_num % RK3568_DRV_PINS_PER_REG; + *bit *= RK3568_DRV_BITS_PER_PIN; + } else { + *reg = info->reg_base + RK3568_DRV_GRF_OFFSET; + *reg += (bank->bank_num - 1) * RK3568_DRV_BANK_STRIDE; + *reg += ((pin_num / RK3568_DRV_PINS_PER_REG) * 4); + + *bit = (pin_num % RK3568_DRV_PINS_PER_REG); + *bit *= RK3568_DRV_BITS_PER_PIN; + } +} + +static struct rockchip_mux_route_data rk3188_mux_route_data[] = { + RK_MUXROUTE_SAME(0, RK_PD0, 1, 0xa0, BIT(16 + 11)), /* non-iomuxed emmc/flash pins on flash-dqs */ + RK_MUXROUTE_SAME(0, RK_PD0, 2, 0xa0, BIT(16 + 11) | BIT(11)), /* non-iomuxed emmc/flash pins on emmc-clk */ +}; + +static bool rockchip_get_mux_route(struct rockchip_pin_bank *bank, int pin, + int mux, u32 *loc, u32 *reg, u32 *value) +{ + struct rockchip_pinctrl *info = bank->drvdata; + struct rockchip_pin_ctrl *ctrl = info->ctrl; + struct rockchip_mux_route_data *data; + int i; + + for (i = 0; i < ctrl->niomux_routes; i++) { + data = &ctrl->iomux_routes[i]; + if ((data->bank_num == bank->bank_num) && + (data->pin == pin) && (data->func == mux)) + break; + } + + if (i >= ctrl->niomux_routes) + return false; + + *loc = data->route_location; + *reg = data->route_offset; + *value = data->route_val; + + return true; +} + static int rockchip_pinctrl_set_func(struct rockchip_pin_bank *bank, int pin, int mux) { struct rockchip_pinctrl *info = bank->drvdata; - void __iomem *reg = info->reg_base + info->ctrl->mux_offset; + void __iomem *base, *reg; u8 bit; - u32 data; + u32 data, route_location, route_reg, route_val; + int iomux_num = (pin / 8); + int mux_type; + int mask; + + base = (bank->iomux[iomux_num].type & IOMUX_SOURCE_PMU) + ? info->reg_pmu : info->reg_base; + + /* get basic quadrupel of mux registers and the correct reg inside */ + mux_type = bank->iomux[iomux_num].type; + reg = base + bank->iomux[iomux_num].offset; + + dev_dbg(info->pctl_dev.dev, "setting func of GPIO%d-%d to %d\n", + bank->bank_num, pin, mux); + + if (mux_type & IOMUX_WIDTH_4BIT) { + if ((pin % 8) >= 4) + reg += 0x4; + bit = (pin % 4) * 4; + mask = 0xf; + } else if (mux_type & IOMUX_WIDTH_3BIT) { + if ((pin % 8) >= 5) + reg += 0x4; + bit = (pin % 8 % 5) * 3; + mask = 0x7; + } else { + bit = (pin % 8) * 2; + mask = 0x3; + } - /* get basic quadruple of mux registers and the correct reg inside */ - reg += bank->bank_num * 0x10; - reg += (pin / 8) * 4; - bit = (pin % 8) * 2; + if (bank->route_mask & BIT(pin)) { + if (rockchip_get_mux_route(bank, pin, mux, &route_location, + &route_reg, &route_val)) { + void __iomem *route = base; + + /* handle special locations */ + switch (route_location) { + case ROCKCHIP_ROUTE_PMU: + route = info->reg_pmu; + break; + case ROCKCHIP_ROUTE_GRF: + route = info->reg_base; + break; + } + + writel(route_val, route + route_reg); + } + } data = 3 << (bit + 16); data |= (mux & 3) << bit; @@ -271,6 +650,18 @@ static int rockchip_pinctrl_set_pull(struct rockchip_pin_bank *bank, writel(data, reg); break; case RK3188: + case RK3568: + /* + * In the TRM, pull-up being 1 for everything except the GPIO0_D0-D6, + * where that pull up value becomes 3. + */ + if (ctrl->type == RK3568 && + bank->bank_num == 0 && + pin_num >= 27 && + pin_num <= 30 && + pull == RK_BIAS_PULL_UP) + pull = 3; + data = ((1 << RK3188_PULL_BITS_PER_PIN) - 1) << (bit + 16); data |= pull << bit; writel(data, reg); @@ -283,12 +674,135 @@ static int rockchip_pinctrl_set_pull(struct rockchip_pin_bank *bank, return 0; } +static int rockchip_perpin_drv_list[DRV_TYPE_MAX][8] = { + { 2, 4, 8, 12, -1, -1, -1, -1 }, + { 3, 6, 9, 12, -1, -1, -1, -1 }, + { 5, 10, 15, 20, -1, -1, -1, -1 }, + { 4, 6, 8, 10, 12, 14, 16, 18 }, + { 4, 7, 10, 13, 16, 19, 22, 26 } +}; + +#define RK3288_DRV_BITS_PER_PIN 2 +#define RK3399_DRV_3BITS_PER_PIN 3 + +static int rockchip_set_drive_perpin(struct rockchip_pin_bank *bank, + int pin_num, int strength) +{ + struct rockchip_pinctrl *info = bank->drvdata; + struct rockchip_pin_ctrl *ctrl = info->ctrl; + int ret, i; + void __iomem *reg; + u32 data, rmask, rmask_bits, temp, val; + u8 bit; + int drv_type = bank->drv[pin_num / 8].drv_type; + + if (!ctrl->drv_calc_reg) + return -ENOTSUPP; + + dev_dbg(info->pctl_dev.dev, "setting drive of GPIO%d-%d to %d\n", + bank->bank_num, pin_num, strength); + + ctrl->drv_calc_reg(bank, pin_num, ®, &bit); + if (ctrl->type == RK3568) { + rmask_bits = RK3568_DRV_BITS_PER_PIN; + ret = (1 << (strength + 1)) - 1; + goto config; + } + + ret = -EINVAL; + for (i = 0; i < ARRAY_SIZE(rockchip_perpin_drv_list[drv_type]); i++) { + if (rockchip_perpin_drv_list[drv_type][i] == strength) { + ret = i; + break; + } else if (rockchip_perpin_drv_list[drv_type][i] < 0) { + ret = rockchip_perpin_drv_list[drv_type][i]; + break; + } + } + + if (ret < 0) { + dev_err(info->pctl_dev.dev, "unsupported driver strength %d\n", + strength); + return ret; + } + + switch (drv_type) { + case DRV_TYPE_IO_1V8_3V0_AUTO: + case DRV_TYPE_IO_3V3_ONLY: + rmask_bits = RK3399_DRV_3BITS_PER_PIN; + switch (bit) { + case 0 ... 12: + /* regular case, nothing to do */ + break; + case 15: + /* + * drive-strength offset is special, as it is spread + * over 2 registers, the bit data[15] contains bit 0 + * of the value while temp[1:0] contains bits 2 and 1 + */ + data = (ret & 0x1) << 15; + temp = (ret >> 0x1) & 0x3; + + rmask = BIT(15) | BIT(31); + data |= BIT(31); + + val = readl(reg); + val &= ~rmask; + val |= data & rmask; + writel(val, reg); + + rmask = 0x3 | (0x3 << 16); + temp |= (0x3 << 16); + reg += 0x4; + + val = readl(reg); + val &= ~rmask; + val |= temp & rmask; + writel(val, reg); + + return ret; + case 18 ... 21: + /* setting fully enclosed in the second register */ + reg += 4; + bit -= 16; + break; + default: + dev_err(info->pctl_dev.dev, "unsupported bit: %d for pinctrl drive type: %d\n", + bit, drv_type); + return -EINVAL; + } + break; + case DRV_TYPE_IO_DEFAULT: + case DRV_TYPE_IO_1V8_OR_3V0: + case DRV_TYPE_IO_1V8_ONLY: + rmask_bits = RK3288_DRV_BITS_PER_PIN; + break; + default: + dev_err(info->pctl_dev.dev, "unsupported pinctrl drive type: %d\n", + drv_type); + return -EINVAL; + } + +config: + /* enable the write to the equivalent lower bits */ + data = ((1 << rmask_bits) - 1) << (bit + 16); + rmask = data | (data >> 16); + data |= (ret << bit); + + val = readl(reg); + val &= ~rmask; + val |= data & rmask; + writel(val, reg); + + return ret; +} + static int rockchip_pinctrl_set_state(struct pinctrl_device *pdev, struct device_node *np) { struct rockchip_pinctrl *info = to_rockchip_pinctrl(pdev); const __be32 *list; - int i, size; + int i, size, ret; int bank_num, pin_num, func; /* @@ -307,6 +821,7 @@ static int rockchip_pinctrl_set_state(struct pinctrl_device *pdev, const __be32 *phandle; struct device_node *np_config; struct rockchip_pin_bank *bank; + u32 drive_strength; bank_num = be32_to_cpu(*list++); pin_num = be32_to_cpu(*list++); @@ -321,6 +836,10 @@ static int rockchip_pinctrl_set_state(struct pinctrl_device *pdev, rockchip_pinctrl_set_func(bank, pin_num, func); rockchip_pinctrl_set_pull(bank, pin_num, parse_bias_config(np_config)); + + ret = of_property_read_u32(np_config, "drive-strength", &drive_strength); + if (!ret) + rockchip_set_drive_perpin(bank, pin_num, drive_strength); } return 0; @@ -342,8 +861,8 @@ static int rockchip_get_bank_data(struct rockchip_pin_bank *bank, res = request_iomem_region(dev_name(dev), node_res.start, node_res.end); if (IS_ERR(res)) { - dev_err(dev, "cannot request iomem region %08x\n", - node_res.start); + dev_err(dev, "cannot request iomem region %pa\n", + &node_res.start); return PTR_ERR(res); } @@ -373,7 +892,7 @@ static struct rockchip_pin_ctrl *rockchip_pinctrl_get_soc_data( struct rockchip_pin_ctrl *ctrl; struct rockchip_pin_bank *bank; char *name; - int i; + int grf_offs, pmu_offs, drv_grf_offs, drv_pmu_offs, i, j; match = of_match_node(rockchip_pinctrl_dt_match, node); ctrl = (struct rockchip_pin_ctrl *)match->data; @@ -395,11 +914,91 @@ static struct rockchip_pin_ctrl *rockchip_pinctrl_get_soc_data( } } + grf_offs = ctrl->grf_mux_offset; + pmu_offs = ctrl->pmu_mux_offset; + drv_pmu_offs = ctrl->pmu_drv_offset; + drv_grf_offs = ctrl->grf_drv_offset; bank = ctrl->pin_banks; for (i = 0; i < ctrl->nr_banks; ++i, ++bank) { + int bank_pins = 0; + bank->drvdata = d; bank->pin_base = ctrl->nr_pins; ctrl->nr_pins += bank->nr_pins; + + /* calculate iomux and drv offsets */ + for (j = 0; j < 4; j++) { + struct rockchip_iomux *iom = &bank->iomux[j]; + struct rockchip_drv *drv = &bank->drv[j]; + int inc; + + if (bank_pins >= bank->nr_pins) + break; + + /* preset iomux offset value, set new start value */ + if (iom->offset >= 0) { + if (iom->type & IOMUX_SOURCE_PMU) + pmu_offs = iom->offset; + else + grf_offs = iom->offset; + } else { /* set current iomux offset */ + iom->offset = (iom->type & IOMUX_SOURCE_PMU) ? + pmu_offs : grf_offs; + } + + /* preset drv offset value, set new start value */ + if (drv->offset >= 0) { + if (iom->type & IOMUX_SOURCE_PMU) + drv_pmu_offs = drv->offset; + else + drv_grf_offs = drv->offset; + } else { /* set current drv offset */ + drv->offset = (iom->type & IOMUX_SOURCE_PMU) ? + drv_pmu_offs : drv_grf_offs; + } + + dev_dbg(dev, "bank %d, iomux %d has iom_offset 0x%x drv_offset 0x%x\n", + i, j, iom->offset, drv->offset); + + /* + * Increase offset according to iomux width. + * 4bit iomux'es are spread over two registers. + */ + inc = (iom->type & (IOMUX_WIDTH_4BIT | + IOMUX_WIDTH_3BIT | + IOMUX_WIDTH_2BIT)) ? 8 : 4; + if (iom->type & IOMUX_SOURCE_PMU) + pmu_offs += inc; + else + grf_offs += inc; + + /* + * Increase offset according to drv width. + * 3bit drive-strenth'es are spread over two registers. + */ + if ((drv->drv_type == DRV_TYPE_IO_1V8_3V0_AUTO) || + (drv->drv_type == DRV_TYPE_IO_3V3_ONLY)) + inc = 8; + else + inc = 4; + + if (iom->type & IOMUX_SOURCE_PMU) + drv_pmu_offs += inc; + else + drv_grf_offs += inc; + + bank_pins += 8; + } + + /* calculate the per-bank route_mask */ + for (j = 0; j < ctrl->niomux_routes; j++) { + int pin = 0; + + if (ctrl->iomux_routes[j].bank_num == bank->bank_num) { + pin = ctrl->iomux_routes[j].pin; + bank->route_mask |= BIT(pin); + } + } } return ctrl; @@ -411,6 +1010,8 @@ static int rockchip_pinctrl_probe(struct device_d *dev) struct rockchip_pin_ctrl *ctrl; int ret; + of_platform_populate(dev->device_node, NULL, NULL); + info = xzalloc(sizeof(struct rockchip_pinctrl)); ctrl = rockchip_pinctrl_get_soc_data(info, dev); @@ -462,7 +1063,7 @@ static struct rockchip_pin_ctrl rk2928_pin_ctrl = { .pin_banks = rk2928_pin_banks, .nr_banks = ARRAY_SIZE(rk2928_pin_banks), .type = RK2928, - .mux_offset = 0xa8, + .grf_mux_offset = 0xa8, .pull_calc_reg = rk2928_calc_pull_reg_and_bit, }; @@ -479,7 +1080,7 @@ static struct rockchip_pin_ctrl rk3066a_pin_ctrl = { .pin_banks = rk3066a_pin_banks, .nr_banks = ARRAY_SIZE(rk3066a_pin_banks), .type = RK2928, - .mux_offset = 0xa8, + .grf_mux_offset = 0xa8, .pull_calc_reg = rk2928_calc_pull_reg_and_bit, }; @@ -494,11 +1095,11 @@ static struct rockchip_pin_ctrl rk3066b_pin_ctrl = { .pin_banks = rk3066b_pin_banks, .nr_banks = ARRAY_SIZE(rk3066b_pin_banks), .type = RK3066B, - .mux_offset = 0x60, + .grf_mux_offset = 0x60, }; static struct rockchip_pin_bank rk3188_pin_banks[] = { - PIN_BANK(0, 32, "gpio0"), + PIN_BANK_IOMUX_FLAGS(0, 32, "gpio0", IOMUX_GPIO_ONLY, 0, 0, 0), PIN_BANK(1, 32, "gpio1"), PIN_BANK(2, 32, "gpio2"), PIN_BANK(3, 32, "gpio3"), @@ -508,10 +1109,146 @@ static struct rockchip_pin_ctrl rk3188_pin_ctrl = { .pin_banks = rk3188_pin_banks, .nr_banks = ARRAY_SIZE(rk3188_pin_banks), .type = RK3188, - .mux_offset = 0x60, + .grf_mux_offset = 0x60, + .iomux_routes = rk3188_mux_route_data, + .niomux_routes = ARRAY_SIZE(rk3188_mux_route_data), .pull_calc_reg = rk3188_calc_pull_reg_and_bit, }; +static struct rockchip_mux_route_data rk3568_mux_route_data[] = { + RK_MUXROUTE_PMU(0, RK_PB7, 1, 0x0110, WRITE_MASK_VAL(1, 0, 0)), /* PWM0 IO mux M0 */ + RK_MUXROUTE_PMU(0, RK_PC7, 2, 0x0110, WRITE_MASK_VAL(1, 0, 1)), /* PWM0 IO mux M1 */ + RK_MUXROUTE_PMU(0, RK_PC0, 1, 0x0110, WRITE_MASK_VAL(3, 2, 0)), /* PWM1 IO mux M0 */ + RK_MUXROUTE_PMU(0, RK_PB5, 4, 0x0110, WRITE_MASK_VAL(3, 2, 1)), /* PWM1 IO mux M1 */ + RK_MUXROUTE_PMU(0, RK_PC1, 1, 0x0110, WRITE_MASK_VAL(5, 4, 0)), /* PWM2 IO mux M0 */ + RK_MUXROUTE_PMU(0, RK_PB6, 4, 0x0110, WRITE_MASK_VAL(5, 4, 1)), /* PWM2 IO mux M1 */ + RK_MUXROUTE_PMU(0, RK_PB3, 2, 0x0300, WRITE_MASK_VAL(0, 0, 0)), /* CAN0 IO mux M0 */ + RK_MUXROUTE_GRF(2, RK_PA1, 4, 0x0300, WRITE_MASK_VAL(0, 0, 1)), /* CAN0 IO mux M1 */ + RK_MUXROUTE_GRF(1, RK_PA1, 3, 0x0300, WRITE_MASK_VAL(2, 2, 0)), /* CAN1 IO mux M0 */ + RK_MUXROUTE_GRF(4, RK_PC3, 3, 0x0300, WRITE_MASK_VAL(2, 2, 1)), /* CAN1 IO mux M1 */ + RK_MUXROUTE_GRF(4, RK_PB5, 3, 0x0300, WRITE_MASK_VAL(4, 4, 0)), /* CAN2 IO mux M0 */ + RK_MUXROUTE_GRF(2, RK_PB2, 4, 0x0300, WRITE_MASK_VAL(4, 4, 1)), /* CAN2 IO mux M1 */ + RK_MUXROUTE_GRF(4, RK_PC4, 1, 0x0300, WRITE_MASK_VAL(6, 6, 0)), /* HPDIN IO mux M0 */ + RK_MUXROUTE_PMU(0, RK_PC2, 2, 0x0300, WRITE_MASK_VAL(6, 6, 1)), /* HPDIN IO mux M1 */ + RK_MUXROUTE_GRF(3, RK_PB1, 3, 0x0300, WRITE_MASK_VAL(8, 8, 0)), /* GMAC1 IO mux M0 */ + RK_MUXROUTE_GRF(4, RK_PA7, 3, 0x0300, WRITE_MASK_VAL(8, 8, 1)), /* GMAC1 IO mux M1 */ + RK_MUXROUTE_GRF(4, RK_PD1, 1, 0x0300, WRITE_MASK_VAL(10, 10, 0)), /* HDMITX IO mux M0 */ + RK_MUXROUTE_PMU(0, RK_PC7, 1, 0x0300, WRITE_MASK_VAL(10, 10, 1)), /* HDMITX IO mux M1 */ + RK_MUXROUTE_PMU(0, RK_PB6, 1, 0x0300, WRITE_MASK_VAL(14, 14, 0)), /* I2C2 IO mux M0 */ + RK_MUXROUTE_GRF(4, RK_PB4, 1, 0x0300, WRITE_MASK_VAL(14, 14, 1)), /* I2C2 IO mux M1 */ + RK_MUXROUTE_GRF(1, RK_PA0, 1, 0x0304, WRITE_MASK_VAL(0, 0, 0)), /* I2C3 IO mux M0 */ + RK_MUXROUTE_GRF(3, RK_PB6, 4, 0x0304, WRITE_MASK_VAL(0, 0, 1)), /* I2C3 IO mux M1 */ + RK_MUXROUTE_GRF(4, RK_PB2, 1, 0x0304, WRITE_MASK_VAL(2, 2, 0)), /* I2C4 IO mux M0 */ + RK_MUXROUTE_GRF(2, RK_PB1, 2, 0x0304, WRITE_MASK_VAL(2, 2, 1)), /* I2C4 IO mux M1 */ + RK_MUXROUTE_GRF(3, RK_PB4, 4, 0x0304, WRITE_MASK_VAL(4, 4, 0)), /* I2C5 IO mux M0 */ + RK_MUXROUTE_GRF(4, RK_PD0, 2, 0x0304, WRITE_MASK_VAL(4, 4, 1)), /* I2C5 IO mux M1 */ + RK_MUXROUTE_GRF(3, RK_PB1, 5, 0x0304, WRITE_MASK_VAL(14, 14, 0)), /* PWM8 IO mux M0 */ + RK_MUXROUTE_GRF(1, RK_PD5, 4, 0x0304, WRITE_MASK_VAL(14, 14, 1)), /* PWM8 IO mux M1 */ + RK_MUXROUTE_GRF(3, RK_PB2, 5, 0x0308, WRITE_MASK_VAL(0, 0, 0)), /* PWM9 IO mux M0 */ + RK_MUXROUTE_GRF(1, RK_PD6, 4, 0x0308, WRITE_MASK_VAL(0, 0, 1)), /* PWM9 IO mux M1 */ + RK_MUXROUTE_GRF(3, RK_PB5, 5, 0x0308, WRITE_MASK_VAL(2, 2, 0)), /* PWM10 IO mux M0 */ + RK_MUXROUTE_GRF(2, RK_PA1, 2, 0x0308, WRITE_MASK_VAL(2, 2, 1)), /* PWM10 IO mux M1 */ + RK_MUXROUTE_GRF(3, RK_PB6, 5, 0x0308, WRITE_MASK_VAL(4, 4, 0)), /* PWM11 IO mux M0 */ + RK_MUXROUTE_GRF(4, RK_PC0, 3, 0x0308, WRITE_MASK_VAL(4, 4, 1)), /* PWM11 IO mux M1 */ + RK_MUXROUTE_GRF(3, RK_PB7, 2, 0x0308, WRITE_MASK_VAL(6, 6, 0)), /* PWM12 IO mux M0 */ + RK_MUXROUTE_GRF(4, RK_PC5, 1, 0x0308, WRITE_MASK_VAL(6, 6, 1)), /* PWM12 IO mux M1 */ + RK_MUXROUTE_GRF(3, RK_PC0, 2, 0x0308, WRITE_MASK_VAL(8, 8, 0)), /* PWM13 IO mux M0 */ + RK_MUXROUTE_GRF(4, RK_PC6, 1, 0x0308, WRITE_MASK_VAL(8, 8, 1)), /* PWM13 IO mux M1 */ + RK_MUXROUTE_GRF(3, RK_PC4, 1, 0x0308, WRITE_MASK_VAL(10, 10, 0)), /* PWM14 IO mux M0 */ + RK_MUXROUTE_GRF(4, RK_PC2, 1, 0x0308, WRITE_MASK_VAL(10, 10, 1)), /* PWM14 IO mux M1 */ + RK_MUXROUTE_GRF(3, RK_PC5, 1, 0x0308, WRITE_MASK_VAL(12, 12, 0)), /* PWM15 IO mux M0 */ + RK_MUXROUTE_GRF(4, RK_PC3, 1, 0x0308, WRITE_MASK_VAL(12, 12, 1)), /* PWM15 IO mux M1 */ + RK_MUXROUTE_GRF(3, RK_PD2, 3, 0x0308, WRITE_MASK_VAL(14, 14, 0)), /* SDMMC2 IO mux M0 */ + RK_MUXROUTE_GRF(3, RK_PA5, 5, 0x0308, WRITE_MASK_VAL(14, 14, 1)), /* SDMMC2 IO mux M1 */ + RK_MUXROUTE_PMU(0, RK_PB5, 2, 0x030c, WRITE_MASK_VAL(0, 0, 0)), /* SPI0 IO mux M0 */ + RK_MUXROUTE_GRF(2, RK_PD3, 3, 0x030c, WRITE_MASK_VAL(0, 0, 1)), /* SPI0 IO mux M1 */ + RK_MUXROUTE_GRF(2, RK_PB5, 3, 0x030c, WRITE_MASK_VAL(2, 2, 0)), /* SPI1 IO mux M0 */ + RK_MUXROUTE_GRF(3, RK_PC3, 3, 0x030c, WRITE_MASK_VAL(2, 2, 1)), /* SPI1 IO mux M1 */ + RK_MUXROUTE_GRF(2, RK_PC1, 4, 0x030c, WRITE_MASK_VAL(4, 4, 0)), /* SPI2 IO mux M0 */ + RK_MUXROUTE_GRF(3, RK_PA0, 3, 0x030c, WRITE_MASK_VAL(4, 4, 1)), /* SPI2 IO mux M1 */ + RK_MUXROUTE_GRF(4, RK_PB3, 4, 0x030c, WRITE_MASK_VAL(6, 6, 0)), /* SPI3 IO mux M0 */ + RK_MUXROUTE_GRF(4, RK_PC2, 2, 0x030c, WRITE_MASK_VAL(6, 6, 1)), /* SPI3 IO mux M1 */ + RK_MUXROUTE_GRF(2, RK_PB4, 2, 0x030c, WRITE_MASK_VAL(8, 8, 0)), /* UART1 IO mux M0 */ + RK_MUXROUTE_PMU(0, RK_PD1, 1, 0x030c, WRITE_MASK_VAL(8, 8, 1)), /* UART1 IO mux M1 */ + RK_MUXROUTE_PMU(0, RK_PD1, 1, 0x030c, WRITE_MASK_VAL(10, 10, 0)), /* UART2 IO mux M0 */ + RK_MUXROUTE_GRF(1, RK_PD5, 2, 0x030c, WRITE_MASK_VAL(10, 10, 1)), /* UART2 IO mux M1 */ + RK_MUXROUTE_GRF(1, RK_PA1, 2, 0x030c, WRITE_MASK_VAL(12, 12, 0)), /* UART3 IO mux M0 */ + RK_MUXROUTE_GRF(3, RK_PB7, 4, 0x030c, WRITE_MASK_VAL(12, 12, 1)), /* UART3 IO mux M1 */ + RK_MUXROUTE_GRF(1, RK_PA6, 2, 0x030c, WRITE_MASK_VAL(14, 14, 0)), /* UART4 IO mux M0 */ + RK_MUXROUTE_GRF(3, RK_PB2, 4, 0x030c, WRITE_MASK_VAL(14, 14, 1)), /* UART4 IO mux M1 */ + RK_MUXROUTE_GRF(2, RK_PA2, 3, 0x0310, WRITE_MASK_VAL(0, 0, 0)), /* UART5 IO mux M0 */ + RK_MUXROUTE_GRF(3, RK_PC2, 4, 0x0310, WRITE_MASK_VAL(0, 0, 1)), /* UART5 IO mux M1 */ + RK_MUXROUTE_GRF(2, RK_PA4, 3, 0x0310, WRITE_MASK_VAL(2, 2, 0)), /* UART6 IO mux M0 */ + RK_MUXROUTE_GRF(1, RK_PD5, 3, 0x0310, WRITE_MASK_VAL(2, 2, 1)), /* UART6 IO mux M1 */ + RK_MUXROUTE_GRF(2, RK_PA6, 3, 0x0310, WRITE_MASK_VAL(5, 4, 0)), /* UART7 IO mux M0 */ + RK_MUXROUTE_GRF(3, RK_PC4, 4, 0x0310, WRITE_MASK_VAL(5, 4, 1)), /* UART7 IO mux M1 */ + RK_MUXROUTE_GRF(4, RK_PA2, 4, 0x0310, WRITE_MASK_VAL(5, 4, 2)), /* UART7 IO mux M2 */ + RK_MUXROUTE_GRF(2, RK_PC5, 3, 0x0310, WRITE_MASK_VAL(6, 6, 0)), /* UART8 IO mux M0 */ + RK_MUXROUTE_GRF(2, RK_PD7, 4, 0x0310, WRITE_MASK_VAL(6, 6, 1)), /* UART8 IO mux M1 */ + RK_MUXROUTE_GRF(2, RK_PB0, 3, 0x0310, WRITE_MASK_VAL(9, 8, 0)), /* UART9 IO mux M0 */ + RK_MUXROUTE_GRF(4, RK_PC5, 4, 0x0310, WRITE_MASK_VAL(9, 8, 1)), /* UART9 IO mux M1 */ + RK_MUXROUTE_GRF(4, RK_PA4, 4, 0x0310, WRITE_MASK_VAL(9, 8, 2)), /* UART9 IO mux M2 */ + RK_MUXROUTE_GRF(1, RK_PA2, 1, 0x0310, WRITE_MASK_VAL(11, 10, 0)), /* I2S1 IO mux M0 */ + RK_MUXROUTE_GRF(3, RK_PC6, 4, 0x0310, WRITE_MASK_VAL(11, 10, 1)), /* I2S1 IO mux M1 */ + RK_MUXROUTE_GRF(2, RK_PD0, 5, 0x0310, WRITE_MASK_VAL(11, 10, 2)), /* I2S1 IO mux M2 */ + RK_MUXROUTE_GRF(2, RK_PC1, 1, 0x0310, WRITE_MASK_VAL(12, 12, 0)), /* I2S2 IO mux M0 */ + RK_MUXROUTE_GRF(4, RK_PB6, 5, 0x0310, WRITE_MASK_VAL(12, 12, 1)), /* I2S2 IO mux M1 */ + RK_MUXROUTE_GRF(3, RK_PA2, 4, 0x0310, WRITE_MASK_VAL(14, 14, 0)), /* I2S3 IO mux M0 */ + RK_MUXROUTE_GRF(4, RK_PC2, 5, 0x0310, WRITE_MASK_VAL(14, 14, 1)), /* I2S3 IO mux M1 */ + RK_MUXROUTE_GRF(1, RK_PA4, 3, 0x0314, WRITE_MASK_VAL(1, 0, 0)), /* PDM IO mux M0 */ + RK_MUXROUTE_GRF(1, RK_PA6, 3, 0x0314, WRITE_MASK_VAL(1, 0, 0)), /* PDM IO mux M0 */ + RK_MUXROUTE_GRF(3, RK_PD6, 5, 0x0314, WRITE_MASK_VAL(1, 0, 1)), /* PDM IO mux M1 */ + RK_MUXROUTE_GRF(4, RK_PA0, 4, 0x0314, WRITE_MASK_VAL(1, 0, 1)), /* PDM IO mux M1 */ + RK_MUXROUTE_GRF(3, RK_PC4, 5, 0x0314, WRITE_MASK_VAL(1, 0, 2)), /* PDM IO mux M2 */ + RK_MUXROUTE_PMU(0, RK_PA5, 3, 0x0314, WRITE_MASK_VAL(3, 2, 0)), /* PCIE20 IO mux M0 */ + RK_MUXROUTE_GRF(2, RK_PD0, 4, 0x0314, WRITE_MASK_VAL(3, 2, 1)), /* PCIE20 IO mux M1 */ + RK_MUXROUTE_GRF(1, RK_PB0, 4, 0x0314, WRITE_MASK_VAL(3, 2, 2)), /* PCIE20 IO mux M2 */ + RK_MUXROUTE_PMU(0, RK_PA4, 3, 0x0314, WRITE_MASK_VAL(5, 4, 0)), /* PCIE30X1 IO mux M0 */ + RK_MUXROUTE_GRF(2, RK_PD2, 4, 0x0314, WRITE_MASK_VAL(5, 4, 1)), /* PCIE30X1 IO mux M1 */ + RK_MUXROUTE_GRF(1, RK_PA5, 4, 0x0314, WRITE_MASK_VAL(5, 4, 2)), /* PCIE30X1 IO mux M2 */ + RK_MUXROUTE_PMU(0, RK_PA6, 2, 0x0314, WRITE_MASK_VAL(7, 6, 0)), /* PCIE30X2 IO mux M0 */ + RK_MUXROUTE_GRF(2, RK_PD4, 4, 0x0314, WRITE_MASK_VAL(7, 6, 1)), /* PCIE30X2 IO mux M1 */ + RK_MUXROUTE_GRF(4, RK_PC2, 4, 0x0314, WRITE_MASK_VAL(7, 6, 2)), /* PCIE30X2 IO mux M2 */ +}; + +static struct rockchip_pin_bank rk3568_pin_banks[] = { + PIN_BANK_IOMUX_FLAGS(0, 32, "gpio0", IOMUX_SOURCE_PMU | IOMUX_WIDTH_4BIT, + IOMUX_SOURCE_PMU | IOMUX_WIDTH_4BIT, + IOMUX_SOURCE_PMU | IOMUX_WIDTH_4BIT, + IOMUX_SOURCE_PMU | IOMUX_WIDTH_4BIT), + PIN_BANK_IOMUX_FLAGS(1, 32, "gpio1", IOMUX_WIDTH_4BIT, + IOMUX_WIDTH_4BIT, + IOMUX_WIDTH_4BIT, + IOMUX_WIDTH_4BIT), + PIN_BANK_IOMUX_FLAGS(2, 32, "gpio2", IOMUX_WIDTH_4BIT, + IOMUX_WIDTH_4BIT, + IOMUX_WIDTH_4BIT, + IOMUX_WIDTH_4BIT), + PIN_BANK_IOMUX_FLAGS(3, 32, "gpio3", IOMUX_WIDTH_4BIT, + IOMUX_WIDTH_4BIT, + IOMUX_WIDTH_4BIT, + IOMUX_WIDTH_4BIT), + PIN_BANK_IOMUX_FLAGS(4, 32, "gpio4", IOMUX_WIDTH_4BIT, + IOMUX_WIDTH_4BIT, + IOMUX_WIDTH_4BIT, + IOMUX_WIDTH_4BIT), +}; + +static struct rockchip_pin_ctrl rk3568_pin_ctrl = { + .pin_banks = rk3568_pin_banks, + .nr_banks = ARRAY_SIZE(rk3568_pin_banks), + .label = "RK3568-GPIO", + .type = RK3568, + .grf_mux_offset = 0x0, + .pmu_mux_offset = 0x0, + .grf_drv_offset = 0x0200, + .pmu_drv_offset = 0x0070, + .iomux_routes = rk3568_mux_route_data, + .niomux_routes = ARRAY_SIZE(rk3568_mux_route_data), + .pull_calc_reg = rk3568_calc_pull_reg_and_bit, + .drv_calc_reg = rk3568_calc_drv_reg_and_bit, +}; + static struct of_device_id rockchip_pinctrl_dt_match[] = { { .compatible = "rockchip,rk2928-pinctrl", @@ -528,7 +1265,12 @@ static struct of_device_id rockchip_pinctrl_dt_match[] = { { .compatible = "rockchip,rk3188-pinctrl", .data = &rk3188_pin_ctrl, - }, { + }, + { + .compatible = "rockchip,rk3568-pinctrl", + .data = &rk3568_pin_ctrl + }, + { /* sentinel */ } }; @@ -539,4 +1281,4 @@ static struct driver_d rockchip_pinctrl_driver = { .of_compatible = DRV_OF_COMPAT(rockchip_pinctrl_dt_match), }; -console_platform_driver(rockchip_pinctrl_driver); +core_platform_driver(rockchip_pinctrl_driver); diff --git a/drivers/regulator/of_regulator.c b/drivers/regulator/of_regulator.c index 3e8caa8710..c536a82c43 100644 --- a/drivers/regulator/of_regulator.c +++ b/drivers/regulator/of_regulator.c @@ -9,145 +9,6 @@ #include <common.h> #include <of.h> #include <linux/regulator/of_regulator.h> -#include <linux/regulator/machine.h> - -static int of_get_regulation_constraints(struct device_d *dev, - struct device_node *np, - struct regulator_init_data **init_data, - const struct regulator_desc *desc) -{ - struct regulation_constraints *constraints = &(*init_data)->constraints; - int ret; - u32 pval; - - constraints->name = of_get_property(np, "regulator-name", NULL); - - if (!of_property_read_u32(np, "regulator-min-microvolt", &pval)) - constraints->min_uV = pval; - - if (!of_property_read_u32(np, "regulator-max-microvolt", &pval)) - constraints->max_uV = pval; - - /* Voltage change possible? */ - if (constraints->min_uV != constraints->max_uV) - constraints->valid_ops_mask |= REGULATOR_CHANGE_VOLTAGE; - - /* Do we have a voltage range, if so try to apply it? */ - if (constraints->min_uV && constraints->max_uV) - constraints->apply_uV = true; - - if (!of_property_read_u32(np, "regulator-microvolt-offset", &pval)) - constraints->uV_offset = pval; - if (!of_property_read_u32(np, "regulator-min-microamp", &pval)) - constraints->min_uA = pval; - if (!of_property_read_u32(np, "regulator-max-microamp", &pval)) - constraints->max_uA = pval; - - if (!of_property_read_u32(np, "regulator-input-current-limit-microamp", - &pval)) - constraints->ilim_uA = pval; - - /* Current change possible? */ - if (constraints->min_uA != constraints->max_uA) - constraints->valid_ops_mask |= REGULATOR_CHANGE_CURRENT; - - constraints->boot_on = of_property_read_bool(np, "regulator-boot-on"); - constraints->always_on = of_property_read_bool(np, "regulator-always-on"); - if (!constraints->always_on) /* status change should be possible. */ - constraints->valid_ops_mask |= REGULATOR_CHANGE_STATUS; - - constraints->pull_down = of_property_read_bool(np, "regulator-pull-down"); - - if (of_property_read_bool(np, "regulator-allow-bypass")) - constraints->valid_ops_mask |= REGULATOR_CHANGE_BYPASS; - - if (of_property_read_bool(np, "regulator-allow-set-load")) - constraints->valid_ops_mask |= REGULATOR_CHANGE_DRMS; - - ret = of_property_read_u32(np, "regulator-ramp-delay", &pval); - if (!ret) { - if (pval) - constraints->ramp_delay = pval; - else - constraints->ramp_disable = true; - } - - ret = of_property_read_u32(np, "regulator-settling-time-us", &pval); - if (!ret) - constraints->settling_time = pval; - - ret = of_property_read_u32(np, "regulator-settling-time-up-us", &pval); - if (!ret) - constraints->settling_time_up = pval; - if (constraints->settling_time_up && constraints->settling_time) { - pr_warn("%pOFn: ambiguous configuration for settling time, ignoring 'regulator-settling-time-up-us'\n", - np); - constraints->settling_time_up = 0; - } - - ret = of_property_read_u32(np, "regulator-settling-time-down-us", - &pval); - if (!ret) - constraints->settling_time_down = pval; - if (constraints->settling_time_down && constraints->settling_time) { - pr_warn("%pOFn: ambiguous configuration for settling time, ignoring 'regulator-settling-time-down-us'\n", - np); - constraints->settling_time_down = 0; - } - - ret = of_property_read_u32(np, "regulator-enable-ramp-delay", &pval); - if (!ret) - constraints->enable_time = pval; - - constraints->soft_start = of_property_read_bool(np, - "regulator-soft-start"); - ret = of_property_read_u32(np, "regulator-active-discharge", &pval); - if (!ret) { - constraints->active_discharge = - (pval) ? REGULATOR_ACTIVE_DISCHARGE_ENABLE : - REGULATOR_ACTIVE_DISCHARGE_DISABLE; - } - - if (!of_property_read_u32(np, "regulator-system-load", &pval)) - constraints->system_load = pval; - - if (!of_property_read_u32(np, "regulator-max-step-microvolt", - &pval)) - constraints->max_uV_step = pval; - - constraints->over_current_protection = of_property_read_bool(np, - "regulator-over-current-protection"); - - return 0; -} - -/** - * of_get_regulator_init_data - extract regulator_init_data structure info - * @dev: device requesting for regulator_init_data - * @node: regulator device node - * @desc: regulator description - * - * Populates regulator_init_data structure by extracting data from device - * tree node, returns a pointer to the populated structure or NULL if memory - * alloc fails. - */ -struct regulator_init_data *of_get_regulator_init_data(struct device_d *dev, - struct device_node *node, - const struct regulator_desc *desc) -{ - struct regulator_init_data *init_data; - - if (!node) - return NULL; - - init_data = xzalloc(sizeof(*init_data)); - - if (of_get_regulation_constraints(dev, node, &init_data, desc)) - return NULL; - - return init_data; -} -EXPORT_SYMBOL_GPL(of_get_regulator_init_data); struct devm_of_regulator_matches { struct of_regulator_match *matches; @@ -192,7 +53,6 @@ int of_regulator_match(struct device_d *dev, struct device_node *node, for (i = 0; i < num_matches; i++) { struct of_regulator_match *match = &matches[i]; - match->init_data = NULL; match->of_node = NULL; } @@ -210,14 +70,6 @@ int of_regulator_match(struct device_d *dev, struct device_node *node, if (strcmp(match->name, name)) continue; - match->init_data = of_get_regulator_init_data(dev, child, - match->desc); - if (!match->init_data) { - dev_err(dev, - "failed to parse DT for regulator %pOFn\n", - child); - return -EINVAL; - } match->of_node = child; count++; break; diff --git a/drivers/regulator/stm32-vrefbuf.c b/drivers/regulator/stm32-vrefbuf.c index 3956b1f64f..77287c2b0e 100644 --- a/drivers/regulator/stm32-vrefbuf.c +++ b/drivers/regulator/stm32-vrefbuf.c @@ -10,6 +10,7 @@ #include <linux/clk.h> #include <linux/iopoll.h> #include <of.h> +#include <io.h> #include <regulator.h> /* STM32 VREFBUF registers */ @@ -23,9 +24,6 @@ #define STM32_VREFBUF_AUTO_SUSPEND_DELAY_MS 10 -#define readl_relaxed readl -#define writel_relaxed writel - struct stm32_vrefbuf { void __iomem *base; struct clk *clk; diff --git a/drivers/rtc/rtc-imxdi.c b/drivers/rtc/rtc-imxdi.c index 8fcaf631ff..82ed6d5007 100644 --- a/drivers/rtc/rtc-imxdi.c +++ b/drivers/rtc/rtc-imxdi.c @@ -511,10 +511,9 @@ static const struct rtc_class_ops dryice_rtc_ops = { .set_time = dryice_rtc_set_time, }; -static int nvstore_write(struct device_d *dev, const int reg, const void *val, - int bytes) +static int nvstore_write(void *ctx, unsigned reg, const void *val, size_t bytes) { - struct imxdi_dev *imxdi = dev->parent->priv; + struct imxdi_dev *imxdi = ctx; const u32 *val32 = val; if (bytes != 4) @@ -525,10 +524,9 @@ static int nvstore_write(struct device_d *dev, const int reg, const void *val, return 0; } -static int nvstore_read(struct device_d *dev, const int reg, void *val, - int bytes) +static int nvstore_read(void *ctx, unsigned reg, void *val, size_t bytes) { - struct imxdi_dev *imxdi = dev->parent->priv; + struct imxdi_dev *imxdi = ctx; u32 *val32 = val; if (bytes != 4) @@ -588,9 +586,8 @@ static int __init dryice_rtc_probe(struct device_d *dev) if (ret) goto err; - dev->priv = imxdi; - nvstore_nvmem_config.dev = dev; + nvstore_nvmem_config.priv = imxdi; imxdi->nvmem = nvmem_register(&nvstore_nvmem_config); if (IS_ENABLED(CONFIG_NVMEM) && IS_ERR(imxdi->nvmem)) { diff --git a/drivers/spi/atmel-quadspi.c b/drivers/spi/atmel-quadspi.c index 6799f95ea3..af2191726f 100644 --- a/drivers/spi/atmel-quadspi.c +++ b/drivers/spi/atmel-quadspi.c @@ -34,9 +34,6 @@ #include <of_device.h> #include <linux/iopoll.h> -#define writel_relaxed writel -#define readl_relaxed readl - /* QSPI register offsets */ #define QSPI_CR 0x0000 /* Control Register */ #define QSPI_MR 0x0004 /* Mode Register */ diff --git a/drivers/usb/gadget/udc-core.c b/drivers/usb/gadget/udc-core.c index 2516676f86..bd3404f9cf 100644 --- a/drivers/usb/gadget/udc-core.c +++ b/drivers/usb/gadget/udc-core.c @@ -46,61 +46,6 @@ static LIST_HEAD(udc_list); /* ------------------------------------------------------------------------- */ -#ifdef CONFIG_KERNEL_HAS_DMA - -int usb_gadget_map_request(struct usb_gadget *gadget, - struct usb_request *req, int is_in) -{ - if (req->length == 0) - return 0; - - if (req->num_sgs) { - int mapped; - - mapped = dma_map_sg(&gadget->dev, req->sg, req->num_sgs, - is_in ? DMA_TO_DEVICE : DMA_FROM_DEVICE); - if (mapped == 0) { - dev_err(&gadget->dev, "failed to map SGs\n"); - return -EFAULT; - } - - req->num_mapped_sgs = mapped; - } else { - req->dma = dma_map_single(&gadget->dev, req->buf, req->length, - is_in ? DMA_TO_DEVICE : DMA_FROM_DEVICE); - - if (dma_mapping_error(&gadget->dev, req->dma)) { - dev_err(&gadget->dev, "failed to map buffer\n"); - return -EFAULT; - } - } - - return 0; -} -EXPORT_SYMBOL_GPL(usb_gadget_map_request); - -void usb_gadget_unmap_request(struct usb_gadget *gadget, - struct usb_request *req, int is_in) -{ - if (req->length == 0) - return; - - if (req->num_mapped_sgs) { - dma_unmap_sg(&gadget->dev, req->sg, req->num_mapped_sgs, - is_in ? DMA_TO_DEVICE : DMA_FROM_DEVICE); - - req->num_mapped_sgs = 0; - } else { - dma_unmap_single(&gadget->dev, req->dma, req->length, - is_in ? DMA_TO_DEVICE : DMA_FROM_DEVICE); - } -} -EXPORT_SYMBOL_GPL(usb_gadget_unmap_request); - -#endif /* CONFIG_HAS_DMA */ - -/* ------------------------------------------------------------------------- */ - void usb_gadget_set_state(struct usb_gadget *gadget, enum usb_device_state state) { diff --git a/drivers/usb/imx/chipidea-imx.c b/drivers/usb/imx/chipidea-imx.c index 7b87f302a9..aa27941c8c 100644 --- a/drivers/usb/imx/chipidea-imx.c +++ b/drivers/usb/imx/chipidea-imx.c @@ -256,8 +256,11 @@ static int imx_chipidea_probe(struct device_d *dev) } ci->vbus = regulator_get(dev, "vbus"); - if (IS_ERR(ci->vbus)) + if (IS_ERR(ci->vbus)) { + dev_warn(dev, "Cannot get vbus regulator: %pe (ignoring)\n", + ci->vbus); ci->vbus = NULL; + } /* * Some devices have more than one clock, in this case they are enabled diff --git a/drivers/video/atmel_lcdfb_core.c b/drivers/video/atmel_lcdfb_core.c index daabfe92d2..e7e420d38f 100644 --- a/drivers/video/atmel_lcdfb_core.c +++ b/drivers/video/atmel_lcdfb_core.c @@ -489,6 +489,7 @@ int atmel_lcdc_register(struct device_d *dev, struct atmel_lcdfb_devdata *data) sinfo->dma_desc = dma_alloc_coherent(data->dma_desc_size, DMA_ADDRESS_BROKEN); + info->dev.parent = dev; ret = register_framebuffer(info); if (ret != 0) { dev_err(dev, "Failed to register framebuffer\n"); diff --git a/drivers/video/bcm2835.c b/drivers/video/bcm2835.c index 3d52f8b6b8..d808bc5c9f 100644 --- a/drivers/video/bcm2835.c +++ b/drivers/video/bcm2835.c @@ -118,6 +118,7 @@ static int bcm2835fb_probe(struct device_d *dev) info->fbi.mode->xres = info->fbi.xres; info->fbi.mode->yres = info->fbi.yres; + info->fbi.dev.parent = dev; ret = register_framebuffer(&info->fbi); if (ret) { free(info); diff --git a/drivers/video/bochs/bochs_hw.c b/drivers/video/bochs/bochs_hw.c index 252350aebb..debdd36941 100644 --- a/drivers/video/bochs/bochs_hw.c +++ b/drivers/video/bochs/bochs_hw.c @@ -201,5 +201,6 @@ int bochs_hw_probe(struct device_d *dev, void __iomem *fb_map, void __iomem *mmi fb->priv = bochs; fb->fbops = &bochs_fb_ops; + fb->dev.parent = dev; return register_framebuffer(fb); } diff --git a/drivers/video/imx-ipu-fb.c b/drivers/video/imx-ipu-fb.c index a3f195373b..f39b74676c 100644 --- a/drivers/video/imx-ipu-fb.c +++ b/drivers/video/imx-ipu-fb.c @@ -969,6 +969,7 @@ static int sdc_fb_register_overlay(struct ipu_fb_info *fbi, void *fb) sdc_enable_channel(fbi, overlay->screen_base, IDMAC_SDC_1); + fbi->overlay.dev.parent = &fbi->info.dev; ret = register_framebuffer(&fbi->overlay); if (ret < 0) { dev_err(fbi->dev, "failed to register framebuffer\n"); @@ -1039,6 +1040,7 @@ static int imxfb_probe(struct device_d *dev) sdc_enable_channel(fbi, info->screen_base, IDMAC_SDC_0); + fbi->info.dev.parent = dev; ret = register_framebuffer(&fbi->info); if (ret < 0) { dev_err(dev, "failed to register framebuffer\n"); diff --git a/drivers/video/imx-ipu-v3/ipu-di.c b/drivers/video/imx-ipu-v3/ipu-di.c index 97613207c9..85dde1882e 100644 --- a/drivers/video/imx-ipu-v3/ipu-di.c +++ b/drivers/video/imx-ipu-v3/ipu-di.c @@ -167,9 +167,10 @@ static int ipu_di_clk_calc_div(unsigned long inrate, unsigned long outrate) return div; } -static unsigned long clk_di_recalc_rate(struct clk *clk, +static unsigned long clk_di_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) { + struct clk *clk = clk_hw_to_clk(hw); struct ipu_di *di = container_of(clk, struct ipu_di, clk_di_pixel); unsigned long outrate; u32 div = ipu_di_read(di, DI_BS_CLKGEN0); @@ -182,9 +183,10 @@ static unsigned long clk_di_recalc_rate(struct clk *clk, return outrate; } -static long clk_di_round_rate(struct clk *clk, unsigned long rate, +static long clk_di_round_rate(struct clk_hw *hw, unsigned long rate, unsigned long *prate) { + struct clk *clk = clk_hw_to_clk(hw); struct ipu_di *di = container_of(clk, struct ipu_di, clk_di_pixel); unsigned long outrate; int div; @@ -206,9 +208,10 @@ static long clk_di_round_rate(struct clk *clk, unsigned long rate, return outrate; } -static int clk_di_set_rate(struct clk *clk, unsigned long rate, +static int clk_di_set_rate(struct clk_hw *hw, unsigned long rate, unsigned long parent_rate) { + struct clk *clk = clk_hw_to_clk(hw); struct ipu_di *di = container_of(clk, struct ipu_di, clk_di_pixel); int div; u32 clkgen0; @@ -224,8 +227,9 @@ static int clk_di_set_rate(struct clk *clk, unsigned long rate, return 0; } -static int clk_di_get_parent(struct clk *clk) +static int clk_di_get_parent(struct clk_hw *hw) { + struct clk *clk = clk_hw_to_clk(hw); struct ipu_di *di = container_of(clk, struct ipu_di, clk_di_pixel); u32 val; @@ -234,8 +238,9 @@ static int clk_di_get_parent(struct clk *clk) return val & DI_GEN_DI_CLK_EXT ? 1 : 0; } -static int clk_di_set_parent(struct clk *clk, u8 index) +static int clk_di_set_parent(struct clk_hw *hw, u8 index) { + struct clk *clk = clk_hw_to_clk(hw); struct ipu_di *di = container_of(clk, struct ipu_di, clk_di_pixel); u32 val; @@ -740,7 +745,7 @@ int ipu_di_init(struct ipu_soc *ipu, struct device_d *dev, int id, di->clk_di_pixel.ops = &clk_di_ops; di->clk_di_pixel.num_parents = 2; di->clk_di_pixel.name = di->clk_name; - ret = clk_register(&di->clk_di_pixel); + ret = bclk_register(&di->clk_di_pixel); if (ret) goto failed_clk_register; diff --git a/drivers/video/imx-ipu-v3/ipufb.c b/drivers/video/imx-ipu-v3/ipufb.c index 0b53916434..68e87ff3fb 100644 --- a/drivers/video/imx-ipu-v3/ipufb.c +++ b/drivers/video/imx-ipu-v3/ipufb.c @@ -336,6 +336,7 @@ static int ipufb_probe(struct device_d *dev) if (ret) dev_dbg(fbi->dev, "failed to get modes: %s\n", strerror(-ret)); + info->dev.parent = dev; ret = register_framebuffer(info); if (ret < 0) { dev_err(fbi->dev, "failed to register framebuffer\n"); diff --git a/drivers/video/imx.c b/drivers/video/imx.c index e93859775a..f4f58b3ce3 100644 --- a/drivers/video/imx.c +++ b/drivers/video/imx.c @@ -514,6 +514,7 @@ static int imxfb_register_overlay(struct imxfb_info *fbi, void *fb) overlay->blue = rgb->blue; overlay->transp = rgb->transp; + overlay->dev.parent = &fbi->info.dev; ret = register_framebuffer(overlay); if (ret < 0) { dev_err(fbi->dev, "failed to register framebuffer\n"); @@ -592,6 +593,7 @@ static int imxfb_probe(struct device_d *dev) imxfb_activate_var(&fbi->info); + fbi->info.dev.parent = dev; ret = register_framebuffer(&fbi->info); if (ret < 0) { dev_err(dev, "failed to register framebuffer\n"); diff --git a/drivers/video/omap.c b/drivers/video/omap.c index 009626fefc..52a68ef627 100644 --- a/drivers/video/omap.c +++ b/drivers/video/omap.c @@ -493,6 +493,7 @@ static int omapfb_probe(struct device_d *dev) goto out; } + info->dev.parent = dev; rc = register_framebuffer(info); if (rc < 0) { dev_err(dev, "failed to register framebuffer: %d\n", rc); diff --git a/drivers/video/pxa.c b/drivers/video/pxa.c index a2ff4bce2a..45efa6b71d 100644 --- a/drivers/video/pxa.c +++ b/drivers/video/pxa.c @@ -533,6 +533,7 @@ static int pxafb_probe(struct device_d *dev) pxafb_activate_var(fbi); + fbi->info.dev.parent = dev; ret = register_framebuffer(&fbi->info); if (ret < 0) { dev_err(dev, "failed to register framebuffer\n"); diff --git a/drivers/video/s3c24xx.c b/drivers/video/s3c24xx.c index 84ed0aee39..eb784162db 100644 --- a/drivers/video/s3c24xx.c +++ b/drivers/video/s3c24xx.c @@ -395,6 +395,7 @@ static int s3cfb_probe(struct device_d *hw_dev) if (IS_ENABLED(CONFIG_DRIVER_VIDEO_S3C_VERBOSE)) hw_dev->info = s3cfb_info; + fbi.info.dev.parent = hw_dev; ret = register_framebuffer(&fbi.info); if (ret != 0) { dev_err(hw_dev, "Failed to register framebuffer\n"); diff --git a/drivers/video/simplefb-client.c b/drivers/video/simplefb-client.c index 2d0495f616..1f26ac5067 100644 --- a/drivers/video/simplefb-client.c +++ b/drivers/video/simplefb-client.c @@ -121,6 +121,7 @@ static int simplefb_probe(struct device_d *dev) info->xres, info->yres, info->bits_per_pixel, info->line_length); + info->dev.parent = dev; ret = register_framebuffer(info); if (ret < 0) { dev_err(dev, "Unable to register simplefb: %d\n", ret); diff --git a/drivers/video/ssd1307fb.c b/drivers/video/ssd1307fb.c index 994f43dc5c..af5d6086e1 100644 --- a/drivers/video/ssd1307fb.c +++ b/drivers/video/ssd1307fb.c @@ -543,6 +543,7 @@ static int ssd1307fb_probe(struct device_d *dev) if (ret) goto reset_oled_error; + info->dev.parent = dev; ret = register_framebuffer(info); if (ret) { dev_err(&client->dev, "Couldn't register the framebuffer\n"); diff --git a/drivers/video/stm.c b/drivers/video/stm.c index d4a618fe50..28ddc649f8 100644 --- a/drivers/video/stm.c +++ b/drivers/video/stm.c @@ -571,6 +571,7 @@ static int stmfb_probe(struct device_d *hw_dev) fb_of_reserve_add_fixup(&fbi.info); + fbi.info.dev.parent = hw_dev; ret = register_framebuffer(&fbi.info); if (ret != 0) { dev_err(hw_dev, "Failed to register framebuffer\n"); diff --git a/drivers/watchdog/wd_core.c b/drivers/watchdog/wd_core.c index 4b0ee31d5b..2e2814a8f2 100644 --- a/drivers/watchdog/wd_core.c +++ b/drivers/watchdog/wd_core.c @@ -18,6 +18,7 @@ #include <errno.h> #include <linux/ctype.h> #include <watchdog.h> +#include <restart.h> static LIST_HEAD(watchdog_list); @@ -177,6 +178,24 @@ static int seconds_to_expire_get(struct param_d *p, void *priv) return 0; } +static void __noreturn watchdog_restart_handle(struct restart_handler *this) +{ + struct watchdog *wd = watchdog_get_default(); + int ret = -ENODEV; + + if (wd) + ret = watchdog_set_timeout(wd, 1); + + BUG_ON(ret); + mdelay(2000); + __builtin_unreachable(); +} + +static struct restart_handler restart_handler = { + .restart = watchdog_restart_handle, + .name = "watchdog-restart", +}; + int watchdog_register(struct watchdog *wd) { struct param_d *p; @@ -247,6 +266,13 @@ int watchdog_register(struct watchdog *wd) goto error_unregister; } + if (!restart_handler.priority) { + restart_handler.priority = 10; /* don't override others */ + ret = restart_handler_register(&restart_handler); + if (ret) + dev_warn(&wd->dev, "failed to register restart handler\n"); + } + list_add_tail(&wd->list, &watchdog_list); pr_debug("registering watchdog %s with priority %d\n", watchdog_name(wd), |