diff options
Diffstat (limited to 'drivers/clk')
43 files changed, 1322 insertions, 202 deletions
diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile index 1db133652f0c..6415e37548e8 100644 --- a/drivers/clk/Makefile +++ b/drivers/clk/Makefile @@ -34,6 +34,7 @@ obj-$(CONFIG_ARCH_HIGHBANK) += clk-highbank.o obj-$(CONFIG_CLK_HSDK) += clk-hsdk-pll.o obj-$(CONFIG_COMMON_CLK_MAX77686) += clk-max77686.o obj-$(CONFIG_COMMON_CLK_MAX9485) += clk-max9485.o +obj-$(CONFIG_ARCH_MILBEAUT_M10V) += clk-milbeaut.o obj-$(CONFIG_ARCH_MOXART) += clk-moxart.o obj-$(CONFIG_ARCH_NOMADIK) += clk-nomadik.o obj-$(CONFIG_ARCH_NPCM7XX) += clk-npcm7xx.o diff --git a/drivers/clk/at91/clk-programmable.c b/drivers/clk/at91/clk-programmable.c index 89d6f3736dbf..f8edbb65eda3 100644 --- a/drivers/clk/at91/clk-programmable.c +++ b/drivers/clk/at91/clk-programmable.c @@ -20,8 +20,7 @@ #define PROG_ID_MAX 7 #define PROG_STATUS_MASK(id) (1 << ((id) + 8)) -#define PROG_PRES_MASK 0x7 -#define PROG_PRES(layout, pckr) ((pckr >> layout->pres_shift) & PROG_PRES_MASK) +#define PROG_PRES(layout, pckr) ((pckr >> layout->pres_shift) & layout->pres_mask) #define PROG_MAX_RM9200_CSS 3 struct clk_programmable { @@ -37,20 +36,29 @@ static unsigned long clk_programmable_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) { struct clk_programmable *prog = to_clk_programmable(hw); + const struct clk_programmable_layout *layout = prog->layout; unsigned int pckr; + unsigned long rate; regmap_read(prog->regmap, AT91_PMC_PCKR(prog->id), &pckr); - return parent_rate >> PROG_PRES(prog->layout, pckr); + if (layout->is_pres_direct) + rate = parent_rate / (PROG_PRES(layout, pckr) + 1); + else + rate = parent_rate >> PROG_PRES(layout, pckr); + + return rate; } static int clk_programmable_determine_rate(struct clk_hw *hw, struct clk_rate_request *req) { + struct clk_programmable *prog = to_clk_programmable(hw); + const struct clk_programmable_layout *layout = prog->layout; struct clk_hw *parent; long best_rate = -EINVAL; unsigned long parent_rate; - unsigned long tmp_rate; + unsigned long tmp_rate = 0; int shift; int i; @@ -60,10 +68,18 @@ static int clk_programmable_determine_rate(struct clk_hw *hw, continue; parent_rate = clk_hw_get_rate(parent); - for (shift = 0; shift < PROG_PRES_MASK; shift++) { - tmp_rate = parent_rate >> shift; - if (tmp_rate <= req->rate) - break; + if (layout->is_pres_direct) { + for (shift = 0; shift <= layout->pres_mask; shift++) { + tmp_rate = parent_rate / (shift + 1); + if (tmp_rate <= req->rate) + break; + } + } else { + for (shift = 0; shift < layout->pres_mask; shift++) { + tmp_rate = parent_rate >> shift; + if (tmp_rate <= req->rate) + break; + } } if (tmp_rate > req->rate) @@ -137,16 +153,23 @@ static int clk_programmable_set_rate(struct clk_hw *hw, unsigned long rate, if (!div) return -EINVAL; - shift = fls(div) - 1; + if (layout->is_pres_direct) { + shift = div - 1; - if (div != (1 << shift)) - return -EINVAL; + if (shift > layout->pres_mask) + return -EINVAL; + } else { + shift = fls(div) - 1; - if (shift >= PROG_PRES_MASK) - return -EINVAL; + if (div != (1 << shift)) + return -EINVAL; + + if (shift >= layout->pres_mask) + return -EINVAL; + } regmap_update_bits(prog->regmap, AT91_PMC_PCKR(prog->id), - PROG_PRES_MASK << layout->pres_shift, + layout->pres_mask << layout->pres_shift, shift << layout->pres_shift); return 0; @@ -202,19 +225,25 @@ at91_clk_register_programmable(struct regmap *regmap, } const struct clk_programmable_layout at91rm9200_programmable_layout = { + .pres_mask = 0x7, .pres_shift = 2, .css_mask = 0x3, .have_slck_mck = 0, + .is_pres_direct = 0, }; const struct clk_programmable_layout at91sam9g45_programmable_layout = { + .pres_mask = 0x7, .pres_shift = 2, .css_mask = 0x3, .have_slck_mck = 1, + .is_pres_direct = 0, }; const struct clk_programmable_layout at91sam9x5_programmable_layout = { + .pres_mask = 0x7, .pres_shift = 4, .css_mask = 0x7, .have_slck_mck = 0, + .is_pres_direct = 0, }; diff --git a/drivers/clk/at91/pmc.h b/drivers/clk/at91/pmc.h index 672a79bda88c..a0e5ce9c9b9e 100644 --- a/drivers/clk/at91/pmc.h +++ b/drivers/clk/at91/pmc.h @@ -71,9 +71,11 @@ struct clk_pll_characteristics { }; struct clk_programmable_layout { + u8 pres_mask; u8 pres_shift; u8 css_mask; u8 have_slck_mck; + u8 is_pres_direct; }; extern const struct clk_programmable_layout at91rm9200_programmable_layout; diff --git a/drivers/clk/at91/sama5d2.c b/drivers/clk/at91/sama5d2.c index 1f70cb164b06..81943fac4537 100644 --- a/drivers/clk/at91/sama5d2.c +++ b/drivers/clk/at91/sama5d2.c @@ -125,6 +125,14 @@ static const struct { .pll = true }, }; +static const struct clk_programmable_layout sama5d2_programmable_layout = { + .pres_mask = 0xff, + .pres_shift = 4, + .css_mask = 0x7, + .have_slck_mck = 0, + .is_pres_direct = 1, +}; + static void __init sama5d2_pmc_setup(struct device_node *np) { struct clk_range range = CLK_RANGE(0, 0); @@ -249,7 +257,7 @@ static void __init sama5d2_pmc_setup(struct device_node *np) hw = at91_clk_register_programmable(regmap, name, parent_names, 6, i, - &at91sam9x5_programmable_layout); + &sama5d2_programmable_layout); if (IS_ERR(hw)) goto err_free; } diff --git a/drivers/clk/clk-milbeaut.c b/drivers/clk/clk-milbeaut.c new file mode 100644 index 000000000000..5fc78faf820c --- /dev/null +++ b/drivers/clk/clk-milbeaut.c @@ -0,0 +1,663 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2018 Socionext Inc. + * Copyright (C) 2016 Linaro Ltd. + */ + +#include <linux/clk-provider.h> +#include <linux/err.h> +#include <linux/io.h> +#include <linux/iopoll.h> +#include <linux/of_address.h> +#include <linux/platform_device.h> +#include <linux/slab.h> +#include <linux/spinlock.h> + +#define M10V_CLKSEL1 0x0 +#define CLKSEL(n) (((n) - 1) * 4 + M10V_CLKSEL1) + +#define M10V_PLL1 "pll1" +#define M10V_PLL1DIV2 "pll1-2" +#define M10V_PLL2 "pll2" +#define M10V_PLL2DIV2 "pll2-2" +#define M10V_PLL6 "pll6" +#define M10V_PLL6DIV2 "pll6-2" +#define M10V_PLL6DIV3 "pll6-3" +#define M10V_PLL7 "pll7" +#define M10V_PLL7DIV2 "pll7-2" +#define M10V_PLL7DIV5 "pll7-5" +#define M10V_PLL9 "pll9" +#define M10V_PLL10 "pll10" +#define M10V_PLL10DIV2 "pll10-2" +#define M10V_PLL11 "pll11" + +#define M10V_SPI_PARENT0 "spi-parent0" +#define M10V_SPI_PARENT1 "spi-parent1" +#define M10V_SPI_PARENT2 "spi-parent2" +#define M10V_UHS1CLK2_PARENT0 "uhs1clk2-parent0" +#define M10V_UHS1CLK2_PARENT1 "uhs1clk2-parent1" +#define M10V_UHS1CLK2_PARENT2 "uhs1clk2-parent2" +#define M10V_UHS1CLK1_PARENT0 "uhs1clk1-parent0" +#define M10V_UHS1CLK1_PARENT1 "uhs1clk1-parent1" +#define M10V_NFCLK_PARENT0 "nfclk-parent0" +#define M10V_NFCLK_PARENT1 "nfclk-parent1" +#define M10V_NFCLK_PARENT2 "nfclk-parent2" +#define M10V_NFCLK_PARENT3 "nfclk-parent3" +#define M10V_NFCLK_PARENT4 "nfclk-parent4" +#define M10V_NFCLK_PARENT5 "nfclk-parent5" + +#define M10V_DCHREQ 1 +#define M10V_UPOLL_RATE 1 +#define M10V_UTIMEOUT 250 + +#define M10V_EMMCCLK_ID 0 +#define M10V_ACLK_ID 1 +#define M10V_HCLK_ID 2 +#define M10V_PCLK_ID 3 +#define M10V_RCLK_ID 4 +#define M10V_SPICLK_ID 5 +#define M10V_NFCLK_ID 6 +#define M10V_UHS1CLK2_ID 7 +#define M10V_NUM_CLKS 8 + +#define to_m10v_div(_hw) container_of(_hw, struct m10v_clk_divider, hw) + +static struct clk_hw_onecell_data *m10v_clk_data; + +static DEFINE_SPINLOCK(m10v_crglock); + +struct m10v_clk_div_factors { + const char *name; + const char *parent_name; + u32 offset; + u8 shift; + u8 width; + const struct clk_div_table *table; + unsigned long div_flags; + int onecell_idx; +}; + +struct m10v_clk_div_fixed_data { + const char *name; + const char *parent_name; + u8 div; + u8 mult; + int onecell_idx; +}; + +struct m10v_clk_mux_factors { + const char *name; + const char * const *parent_names; + u8 num_parents; + u32 offset; + u8 shift; + u8 mask; + u32 *table; + unsigned long mux_flags; + int onecell_idx; +}; + +static const struct clk_div_table emmcclk_table[] = { + { .val = 0, .div = 8 }, + { .val = 1, .div = 9 }, + { .val = 2, .div = 10 }, + { .val = 3, .div = 15 }, + { .div = 0 }, +}; + +static const struct clk_div_table mclk400_table[] = { + { .val = 1, .div = 2 }, + { .val = 3, .div = 4 }, + { .div = 0 }, +}; + +static const struct clk_div_table mclk200_table[] = { + { .val = 3, .div = 4 }, + { .val = 7, .div = 8 }, + { .div = 0 }, +}; + +static const struct clk_div_table aclk400_table[] = { + { .val = 1, .div = 2 }, + { .val = 3, .div = 4 }, + { .div = 0 }, +}; + +static const struct clk_div_table aclk300_table[] = { + { .val = 0, .div = 2 }, + { .val = 1, .div = 3 }, + { .div = 0 }, +}; + +static const struct clk_div_table aclk_table[] = { + { .val = 3, .div = 4 }, + { .val = 7, .div = 8 }, + { .div = 0 }, +}; + +static const struct clk_div_table aclkexs_table[] = { + { .val = 3, .div = 4 }, + { .val = 4, .div = 5 }, + { .val = 5, .div = 6 }, + { .val = 7, .div = 8 }, + { .div = 0 }, +}; + +static const struct clk_div_table hclk_table[] = { + { .val = 7, .div = 8 }, + { .val = 15, .div = 16 }, + { .div = 0 }, +}; + +static const struct clk_div_table hclkbmh_table[] = { + { .val = 3, .div = 4 }, + { .val = 7, .div = 8 }, + { .div = 0 }, +}; + +static const struct clk_div_table pclk_table[] = { + { .val = 15, .div = 16 }, + { .val = 31, .div = 32 }, + { .div = 0 }, +}; + +static const struct clk_div_table rclk_table[] = { + { .val = 0, .div = 8 }, + { .val = 1, .div = 16 }, + { .val = 2, .div = 24 }, + { .val = 3, .div = 32 }, + { .div = 0 }, +}; + +static const struct clk_div_table uhs1clk0_table[] = { + { .val = 0, .div = 2 }, + { .val = 1, .div = 3 }, + { .val = 2, .div = 4 }, + { .val = 3, .div = 8 }, + { .val = 4, .div = 16 }, + { .div = 0 }, +}; + +static const struct clk_div_table uhs2clk_table[] = { + { .val = 0, .div = 9 }, + { .val = 1, .div = 10 }, + { .val = 2, .div = 11 }, + { .val = 3, .div = 12 }, + { .val = 4, .div = 13 }, + { .val = 5, .div = 14 }, + { .val = 6, .div = 16 }, + { .val = 7, .div = 18 }, + { .div = 0 }, +}; + +static u32 spi_mux_table[] = {0, 1, 2}; +static const char * const spi_mux_names[] = { + M10V_SPI_PARENT0, M10V_SPI_PARENT1, M10V_SPI_PARENT2 +}; + +static u32 uhs1clk2_mux_table[] = {2, 3, 4, 8}; +static const char * const uhs1clk2_mux_names[] = { + M10V_UHS1CLK2_PARENT0, M10V_UHS1CLK2_PARENT1, + M10V_UHS1CLK2_PARENT2, M10V_PLL6DIV2 +}; + +static u32 uhs1clk1_mux_table[] = {3, 4, 8}; +static const char * const uhs1clk1_mux_names[] = { + M10V_UHS1CLK1_PARENT0, M10V_UHS1CLK1_PARENT1, M10V_PLL6DIV2 +}; + +static u32 nfclk_mux_table[] = {0, 1, 2, 3, 4, 8}; +static const char * const nfclk_mux_names[] = { + M10V_NFCLK_PARENT0, M10V_NFCLK_PARENT1, M10V_NFCLK_PARENT2, + M10V_NFCLK_PARENT3, M10V_NFCLK_PARENT4, M10V_NFCLK_PARENT5 +}; + +static const struct m10v_clk_div_fixed_data m10v_pll_fixed_data[] = { + {M10V_PLL1, NULL, 1, 40, -1}, + {M10V_PLL2, NULL, 1, 30, -1}, + {M10V_PLL6, NULL, 1, 35, -1}, + {M10V_PLL7, NULL, 1, 40, -1}, + {M10V_PLL9, NULL, 1, 33, -1}, + {M10V_PLL10, NULL, 5, 108, -1}, + {M10V_PLL10DIV2, M10V_PLL10, 2, 1, -1}, + {M10V_PLL11, NULL, 2, 75, -1}, +}; + +static const struct m10v_clk_div_fixed_data m10v_div_fixed_data[] = { + {"usb2", NULL, 2, 1, -1}, + {"pcisuppclk", NULL, 20, 1, -1}, + {M10V_PLL1DIV2, M10V_PLL1, 2, 1, -1}, + {M10V_PLL2DIV2, M10V_PLL2, 2, 1, -1}, + {M10V_PLL6DIV2, M10V_PLL6, 2, 1, -1}, + {M10V_PLL6DIV3, M10V_PLL6, 3, 1, -1}, + {M10V_PLL7DIV2, M10V_PLL7, 2, 1, -1}, + {M10V_PLL7DIV5, M10V_PLL7, 5, 1, -1}, + {"ca7wd", M10V_PLL2DIV2, 12, 1, -1}, + {"pclkca7wd", M10V_PLL1DIV2, 16, 1, -1}, + {M10V_SPI_PARENT0, M10V_PLL10DIV2, 2, 1, -1}, + {M10V_SPI_PARENT1, M10V_PLL10DIV2, 4, 1, -1}, + {M10V_SPI_PARENT2, M10V_PLL7DIV2, 8, 1, -1}, + {M10V_UHS1CLK2_PARENT0, M10V_PLL7, 4, 1, -1}, + {M10V_UHS1CLK2_PARENT1, M10V_PLL7, 8, 1, -1}, + {M10V_UHS1CLK2_PARENT2, M10V_PLL7, 16, 1, -1}, + {M10V_UHS1CLK1_PARENT0, M10V_PLL7, 8, 1, -1}, + {M10V_UHS1CLK1_PARENT1, M10V_PLL7, 16, 1, -1}, + {M10V_NFCLK_PARENT0, M10V_PLL7DIV2, 8, 1, -1}, + {M10V_NFCLK_PARENT1, M10V_PLL7DIV2, 10, 1, -1}, + {M10V_NFCLK_PARENT2, M10V_PLL7DIV2, 13, 1, -1}, + {M10V_NFCLK_PARENT3, M10V_PLL7DIV2, 16, 1, -1}, + {M10V_NFCLK_PARENT4, M10V_PLL7DIV2, 40, 1, -1}, + {M10V_NFCLK_PARENT5, M10V_PLL7DIV5, 10, 1, -1}, +}; + +static const struct m10v_clk_div_factors m10v_div_factor_data[] = { + {"emmc", M10V_PLL11, CLKSEL(1), 28, 3, emmcclk_table, 0, + M10V_EMMCCLK_ID}, + {"mclk400", M10V_PLL1DIV2, CLKSEL(10), 7, 3, mclk400_table, 0, -1}, + {"mclk200", M10V_PLL1DIV2, CLKSEL(10), 3, 4, mclk200_table, 0, -1}, + {"aclk400", M10V_PLL1DIV2, CLKSEL(10), 0, 3, aclk400_table, 0, -1}, + {"aclk300", M10V_PLL2DIV2, CLKSEL(12), 0, 2, aclk300_table, 0, -1}, + {"aclk", M10V_PLL1DIV2, CLKSEL(9), 20, 4, aclk_table, 0, M10V_ACLK_ID}, + {"aclkexs", M10V_PLL1DIV2, CLKSEL(9), 16, 4, aclkexs_table, 0, -1}, + {"hclk", M10V_PLL1DIV2, CLKSEL(9), 7, 5, hclk_table, 0, M10V_HCLK_ID}, + {"hclkbmh", M10V_PLL1DIV2, CLKSEL(9), 12, 4, hclkbmh_table, 0, -1}, + {"pclk", M10V_PLL1DIV2, CLKSEL(9), 0, 7, pclk_table, 0, M10V_PCLK_ID}, + {"uhs1clk0", M10V_PLL7, CLKSEL(1), 3, 5, uhs1clk0_table, 0, -1}, + {"uhs2clk", M10V_PLL6DIV3, CLKSEL(1), 18, 4, uhs2clk_table, 0, -1}, +}; + +static const struct m10v_clk_mux_factors m10v_mux_factor_data[] = { + {"spi", spi_mux_names, ARRAY_SIZE(spi_mux_names), + CLKSEL(8), 3, 7, spi_mux_table, 0, M10V_SPICLK_ID}, + {"uhs1clk2", uhs1clk2_mux_names, ARRAY_SIZE(uhs1clk2_mux_names), + CLKSEL(1), 13, 31, uhs1clk2_mux_table, 0, M10V_UHS1CLK2_ID}, + {"uhs1clk1", uhs1clk1_mux_names, ARRAY_SIZE(uhs1clk1_mux_names), + CLKSEL(1), 8, 31, uhs1clk1_mux_table, 0, -1}, + {"nfclk", nfclk_mux_names, ARRAY_SIZE(nfclk_mux_names), + CLKSEL(1), 22, 127, nfclk_mux_table, 0, M10V_NFCLK_ID}, +}; + +static u8 m10v_mux_get_parent(struct clk_hw *hw) +{ + struct clk_mux *mux = to_clk_mux(hw); + u32 val; + + val = readl(mux->reg) >> mux->shift; + val &= mux->mask; + + return clk_mux_val_to_index(hw, mux->table, mux->flags, val); +} + +static int m10v_mux_set_parent(struct clk_hw *hw, u8 index) +{ + struct clk_mux *mux = to_clk_mux(hw); + u32 val = clk_mux_index_to_val(mux->table, mux->flags, index); + unsigned long flags = 0; + u32 reg; + u32 write_en = BIT(fls(mux->mask) - 1); + + if (mux->lock) + spin_lock_irqsave(mux->lock, flags); + else + __acquire(mux->lock); + + reg = readl(mux->reg); + reg &= ~(mux->mask << mux->shift); + + val = (val | write_en) << mux->shift; + reg |= val; + writel(reg, mux->reg); + + if (mux->lock) + spin_unlock_irqrestore(mux->lock, flags); + else + __release(mux->lock); + + return 0; +} + +static const struct clk_ops m10v_mux_ops = { + .get_parent = m10v_mux_get_parent, + .set_parent = m10v_mux_set_parent, + .determine_rate = __clk_mux_determine_rate, +}; + +static struct clk_hw *m10v_clk_hw_register_mux(struct device *dev, + const char *name, const char * const *parent_names, + u8 num_parents, unsigned long flags, void __iomem *reg, + u8 shift, u32 mask, u8 clk_mux_flags, u32 *table, + spinlock_t *lock) +{ + struct clk_mux *mux; + struct clk_hw *hw; + struct clk_init_data init; + int ret; + + mux = kzalloc(sizeof(*mux), GFP_KERNEL); + if (!mux) + return ERR_PTR(-ENOMEM); + + init.name = name; + init.ops = &m10v_mux_ops; + init.flags = flags; + init.parent_names = parent_names; + init.num_parents = num_parents; + + mux->reg = reg; + mux->shift = shift; + mux->mask = mask; + mux->flags = clk_mux_flags; + mux->lock = lock; + mux->table = table; + mux->hw.init = &init; + + hw = &mux->hw; + ret = clk_hw_register(dev, hw); + if (ret) { + kfree(mux); + hw = ERR_PTR(ret); + } + + return hw; + +} + +struct m10v_clk_divider { + struct clk_hw hw; + void __iomem *reg; + u8 shift; + u8 width; + u8 flags; + const struct clk_div_table *table; + spinlock_t *lock; + void __iomem *write_valid_reg; +}; + +static unsigned long m10v_clk_divider_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + struct m10v_clk_divider *divider = to_m10v_div(hw); + unsigned int val; + + val = readl(divider->reg) >> divider->shift; + val &= clk_div_mask(divider->width); + + return divider_recalc_rate(hw, parent_rate, val, divider->table, + divider->flags, divider->width); +} + +static long m10v_clk_divider_round_rate(struct clk_hw *hw, unsigned long rate, + unsigned long *prate) +{ + struct m10v_clk_divider *divider = to_m10v_div(hw); + + /* if read only, just return current value */ + if (divider->flags & CLK_DIVIDER_READ_ONLY) { + u32 val; + + val = readl(divider->reg) >> divider->shift; + val &= clk_div_mask(divider->width); + + return divider_ro_round_rate(hw, rate, prate, divider->table, + divider->width, divider->flags, + val); + } + + return divider_round_rate(hw, rate, prate, divider->table, + divider->width, divider->flags); +} + +static int m10v_clk_divider_set_rate(struct clk_hw *hw, unsigned long rate, + unsigned long parent_rate) +{ + struct m10v_clk_divider *divider = to_m10v_div(hw); + int value; + unsigned long flags = 0; + u32 val; + u32 write_en = BIT(divider->width - 1); + + value = divider_get_val(rate, parent_rate, divider->table, + divider->width, divider->flags); + if (value < 0) + return value; + + if (divider->lock) + spin_lock_irqsave(divider->lock, flags); + else + __acquire(divider->lock); + + val = readl(divider->reg); + val &= ~(clk_div_mask(divider->width) << divider->shift); + + val |= ((u32)value | write_en) << divider->shift; + writel(val, divider->reg); + + if (divider->write_valid_reg) { + writel(M10V_DCHREQ, divider->write_valid_reg); + if (readl_poll_timeout(divider->write_valid_reg, val, + !val, M10V_UPOLL_RATE, M10V_UTIMEOUT)) + pr_err("%s:%s couldn't stabilize\n", + __func__, divider->hw.init->name); + } + + if (divider->lock) + spin_unlock_irqrestore(divider->lock, flags); + else + __release(divider->lock); + + return 0; +} + +static const struct clk_ops m10v_clk_divider_ops = { + .recalc_rate = m10v_clk_divider_recalc_rate, + .round_rate = m10v_clk_divider_round_rate, + .set_rate = m10v_clk_divider_set_rate, +}; + +static struct clk_hw *m10v_clk_hw_register_divider(struct device *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, void __iomem *write_valid_reg) +{ + struct m10v_clk_divider *div; + struct clk_hw *hw; + struct clk_init_data init; + int ret; + + div = kzalloc(sizeof(*div), GFP_KERNEL); + if (!div) + return ERR_PTR(-ENOMEM); + + init.name = name; + init.ops = &m10v_clk_divider_ops; + init.flags = flags; + init.parent_names = &parent_name; + init.num_parents = 1; + + div->reg = reg; + div->shift = shift; + div->width = width; + div->flags = clk_divider_flags; + div->lock = lock; + div->hw.init = &init; + div->table = table; + div->write_valid_reg = write_valid_reg; + + /* register the clock */ + hw = &div->hw; + ret = clk_hw_register(dev, hw); + if (ret) { + kfree(div); + hw = ERR_PTR(ret); + } + + return hw; +} + +static void m10v_reg_div_pre(const struct m10v_clk_div_factors *factors, + struct clk_hw_onecell_data *clk_data, + void __iomem *base) +{ + struct clk_hw *hw; + void __iomem *write_valid_reg; + + /* + * The registers on CLKSEL(9) or CLKSEL(10) need additional + * writing to become valid. + */ + if ((factors->offset == CLKSEL(9)) || (factors->offset == CLKSEL(10))) + write_valid_reg = base + CLKSEL(11); + else + write_valid_reg = NULL; + + hw = m10v_clk_hw_register_divider(NULL, factors->name, + factors->parent_name, + CLK_SET_RATE_PARENT, + base + factors->offset, + factors->shift, + factors->width, factors->div_flags, + factors->table, + &m10v_crglock, write_valid_reg); + + if (factors->onecell_idx >= 0) + clk_data->hws[factors->onecell_idx] = hw; +} + +static void m10v_reg_fixed_pre(const struct m10v_clk_div_fixed_data *factors, + struct clk_hw_onecell_data *clk_data, + const char *parent_name) +{ + struct clk_hw *hw; + const char *pn = factors->parent_name ? + factors->parent_name : parent_name; + + hw = clk_hw_register_fixed_factor(NULL, factors->name, pn, 0, + factors->mult, factors->div); + + if (factors->onecell_idx >= 0) + clk_data->hws[factors->onecell_idx] = hw; +} + +static void m10v_reg_mux_pre(const struct m10v_clk_mux_factors *factors, + struct clk_hw_onecell_data *clk_data, + void __iomem *base) +{ + struct clk_hw *hw; + + hw = m10v_clk_hw_register_mux(NULL, factors->name, + factors->parent_names, + factors->num_parents, + CLK_SET_RATE_PARENT, + base + factors->offset, factors->shift, + factors->mask, factors->mux_flags, + factors->table, &m10v_crglock); + + if (factors->onecell_idx >= 0) + clk_data->hws[factors->onecell_idx] = hw; +} + +static int m10v_clk_probe(struct platform_device *pdev) +{ + int id; + struct resource *res; + struct device *dev = &pdev->dev; + struct device_node *np = dev->of_node; + void __iomem *base; + const char *parent_name; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + base = devm_ioremap_resource(dev, res); + if (IS_ERR(base)) + return PTR_ERR(base); + + parent_name = of_clk_get_parent_name(np, 0); + + for (id = 0; id < ARRAY_SIZE(m10v_div_factor_data); ++id) + m10v_reg_div_pre(&m10v_div_factor_data[id], + m10v_clk_data, base); + + for (id = 0; id < ARRAY_SIZE(m10v_div_fixed_data); ++id) + m10v_reg_fixed_pre(&m10v_div_fixed_data[id], + m10v_clk_data, parent_name); + + for (id = 0; id < ARRAY_SIZE(m10v_mux_factor_data); ++id) + m10v_reg_mux_pre(&m10v_mux_factor_data[id], + m10v_clk_data, base); + + for (id = 0; id < M10V_NUM_CLKS; id++) { + if (IS_ERR(m10v_clk_data->hws[id])) + return PTR_ERR(m10v_clk_data->hws[id]); + } + + return 0; +} + +static const struct of_device_id m10v_clk_dt_ids[] = { + { .compatible = "socionext,milbeaut-m10v-ccu", }, + { } +}; + +static struct platform_driver m10v_clk_driver = { + .probe = m10v_clk_probe, + .driver = { + .name = "m10v-ccu", + .of_match_table = m10v_clk_dt_ids, + }, +}; +builtin_platform_driver(m10v_clk_driver); + +static void __init m10v_cc_init(struct device_node *np) +{ + int id; + void __iomem *base; + const char *parent_name; + struct clk_hw *hw; + + m10v_clk_data = kzalloc(struct_size(m10v_clk_data, hws, + M10V_NUM_CLKS), + GFP_KERNEL); + + if (!m10v_clk_data) + return; + + base = of_iomap(np, 0); + if (!base) { + kfree(m10v_clk_data); + return; + } + + parent_name = of_clk_get_parent_name(np, 0); + if (!parent_name) { + kfree(m10v_clk_data); + iounmap(base); + return; + } + + /* + * This way all clocks fetched before the platform device probes, + * except those we assign here for early use, will be deferred. + */ + for (id = 0; id < M10V_NUM_CLKS; id++) + m10v_clk_data->hws[id] = ERR_PTR(-EPROBE_DEFER); + + /* + * PLLs are set by bootloader so this driver registers them as the + * fixed factor. + */ + for (id = 0; id < ARRAY_SIZE(m10v_pll_fixed_data); ++id) + m10v_reg_fixed_pre(&m10v_pll_fixed_data[id], + m10v_clk_data, parent_name); + + /* + * timer consumes "rclk" so it needs to register here. + */ + hw = m10v_clk_hw_register_divider(NULL, "rclk", M10V_PLL10DIV2, 0, + base + CLKSEL(1), 0, 3, 0, rclk_table, + &m10v_crglock, NULL); + m10v_clk_data->hws[M10V_RCLK_ID] = hw; + + m10v_clk_data->num = M10V_NUM_CLKS; + of_clk_add_hw_provider(np, of_clk_hw_onecell_get, m10v_clk_data); +} +CLK_OF_DECLARE_DRIVER(m10v_cc, "socionext,milbeaut-m10v-ccu", m10v_cc_init); diff --git a/drivers/clk/clkdev.c b/drivers/clk/clkdev.c index 8c4435c53f09..6e787cc9e5b9 100644 --- a/drivers/clk/clkdev.c +++ b/drivers/clk/clkdev.c @@ -46,6 +46,8 @@ static struct clk_lookup *clk_find(const char *dev_id, const char *con_id) if (con_id) best_possible += 1; + lockdep_assert_held(&clocks_mutex); + list_for_each_entry(p, &clocks, node) { match = 0; if (p->dev_id) { @@ -402,7 +404,10 @@ void devm_clk_release_clkdev(struct device *dev, const char *con_id, struct clk_lookup *cl; int rval; + mutex_lock(&clocks_mutex); cl = clk_find(dev_id, con_id); + mutex_unlock(&clocks_mutex); + WARN_ON(!cl); rval = devres_release(dev, devm_clkdev_release, devm_clk_match_clkdev, cl); diff --git a/drivers/clk/imx/Makefile b/drivers/clk/imx/Makefile index 0d5180fbe988..05641c64b317 100644 --- a/drivers/clk/imx/Makefile +++ b/drivers/clk/imx/Makefile @@ -35,7 +35,7 @@ obj-$(CONFIG_SOC_IMX25) += clk-imx25.o obj-$(CONFIG_SOC_IMX27) += clk-imx27.o obj-$(CONFIG_SOC_IMX31) += clk-imx31.o obj-$(CONFIG_SOC_IMX35) += clk-imx35.o -obj-$(CONFIG_SOC_IMX5) += clk-imx51-imx53.o +obj-$(CONFIG_SOC_IMX5) += clk-imx5.o obj-$(CONFIG_SOC_IMX6Q) += clk-imx6q.o obj-$(CONFIG_SOC_IMX6SL) += clk-imx6sl.o obj-$(CONFIG_SOC_IMX6SLL) += clk-imx6sll.o diff --git a/drivers/clk/imx/clk-imx51-imx53.c b/drivers/clk/imx/clk-imx5.c index e91c826bce70..c85ebd74a8a5 100644 --- a/drivers/clk/imx/clk-imx51-imx53.c +++ b/drivers/clk/imx/clk-imx5.c @@ -164,10 +164,6 @@ static void __init mx5_clocks_common_init(void __iomem *ccm_base) clk[IMX5_CLK_CKIH1] = imx_obtain_fixed_clock("ckih1", 0); clk[IMX5_CLK_CKIH2] = imx_obtain_fixed_clock("ckih2", 0); - clk[IMX5_CLK_PERIPH_APM] = imx_clk_mux("periph_apm", MXC_CCM_CBCMR, 12, 2, - periph_apm_sel, ARRAY_SIZE(periph_apm_sel)); - clk[IMX5_CLK_MAIN_BUS] = imx_clk_mux("main_bus", MXC_CCM_CBCDR, 25, 1, - main_bus_sel, ARRAY_SIZE(main_bus_sel)); clk[IMX5_CLK_PER_LP_APM] = imx_clk_mux("per_lp_apm", MXC_CCM_CBCMR, 1, 1, per_lp_apm_sel, ARRAY_SIZE(per_lp_apm_sel)); clk[IMX5_CLK_PER_PRED1] = imx_clk_divider("per_pred1", "per_lp_apm", MXC_CCM_CBCDR, 6, 2); @@ -191,16 +187,10 @@ static void __init mx5_clocks_common_init(void __iomem *ccm_base) clk[IMX5_CLK_UART_PRED] = imx_clk_divider("uart_pred", "uart_sel", MXC_CCM_CSCDR1, 3, 3); clk[IMX5_CLK_UART_ROOT] = imx_clk_divider("uart_root", "uart_pred", MXC_CCM_CSCDR1, 0, 3); - clk[IMX5_CLK_ESDHC_A_SEL] = imx_clk_mux("esdhc_a_sel", MXC_CCM_CSCMR1, 20, 2, - standard_pll_sel, ARRAY_SIZE(standard_pll_sel)); - clk[IMX5_CLK_ESDHC_B_SEL] = imx_clk_mux("esdhc_b_sel", MXC_CCM_CSCMR1, 16, 2, - standard_pll_sel, ARRAY_SIZE(standard_pll_sel)); clk[IMX5_CLK_ESDHC_A_PRED] = imx_clk_divider("esdhc_a_pred", "esdhc_a_sel", MXC_CCM_CSCDR1, 16, 3); clk[IMX5_CLK_ESDHC_A_PODF] = imx_clk_divider("esdhc_a_podf", "esdhc_a_pred", MXC_CCM_CSCDR1, 11, 3); clk[IMX5_CLK_ESDHC_B_PRED] = imx_clk_divider("esdhc_b_pred", "esdhc_b_sel", MXC_CCM_CSCDR1, 22, 3); clk[IMX5_CLK_ESDHC_B_PODF] = imx_clk_divider("esdhc_b_podf", "esdhc_b_pred", MXC_CCM_CSCDR1, 19, 3); - clk[IMX5_CLK_ESDHC_C_SEL] = imx_clk_mux("esdhc_c_sel", MXC_CCM_CSCMR1, 19, 1, esdhc_c_sel, ARRAY_SIZE(esdhc_c_sel)); - clk[IMX5_CLK_ESDHC_D_SEL] = imx_clk_mux("esdhc_d_sel", MXC_CCM_CSCMR1, 18, 1, esdhc_d_sel, ARRAY_SIZE(esdhc_d_sel)); clk[IMX5_CLK_EMI_SEL] = imx_clk_mux("emi_sel", MXC_CCM_CBCDR, 26, 1, emi_slow_sel, ARRAY_SIZE(emi_slow_sel)); @@ -311,10 +301,6 @@ static void __init mx5_clocks_common_init(void __iomem *ccm_base) clk_register_clkdev(clk[IMX5_CLK_CPU_PODF], NULL, "cpu0"); clk_register_clkdev(clk[IMX5_CLK_GPC_DVFS], "gpc_dvfs", NULL); - /* Set SDHC parents to be PLL2 */ - clk_set_parent(clk[IMX5_CLK_ESDHC_A_SEL], clk[IMX5_CLK_PLL2_SW]); - clk_set_parent(clk[IMX5_CLK_ESDHC_B_SEL], clk[IMX5_CLK_PLL2_SW]); - /* move usb phy clk to 24MHz */ clk_set_parent(clk[IMX5_CLK_USB_PHY_SEL], clk[IMX5_CLK_OSC]); } @@ -342,8 +328,21 @@ static void __init mx50_clocks_init(struct device_node *np) mx5_clocks_common_init(ccm_base); + /* + * This clock is called periph_clk in the i.MX50 Reference Manual, but + * it comes closest in scope to the main_bus_clk of i.MX51 and i.MX53 + */ + clk[IMX5_CLK_MAIN_BUS] = imx_clk_mux("main_bus", MXC_CCM_CBCDR, 25, 2, + standard_pll_sel, ARRAY_SIZE(standard_pll_sel)); + clk[IMX5_CLK_LP_APM] = imx_clk_mux("lp_apm", MXC_CCM_CCSR, 10, 1, lp_apm_sel, ARRAY_SIZE(lp_apm_sel)); + clk[IMX5_CLK_ESDHC_A_SEL] = imx_clk_mux("esdhc_a_sel", MXC_CCM_CSCMR1, 21, 2, + standard_pll_sel, ARRAY_SIZE(standard_pll_sel)); + clk[IMX5_CLK_ESDHC_B_SEL] = imx_clk_mux("esdhc_b_sel", MXC_CCM_CSCMR1, 16, 2, + standard_pll_sel, ARRAY_SIZE(standard_pll_sel)); + clk[IMX5_CLK_ESDHC_C_SEL] = imx_clk_mux("esdhc_c_sel", MXC_CCM_CSCMR1, 20, 1, esdhc_c_sel, ARRAY_SIZE(esdhc_c_sel)); + clk[IMX5_CLK_ESDHC_D_SEL] = imx_clk_mux("esdhc_d_sel", MXC_CCM_CSCMR1, 19, 1, esdhc_d_sel, ARRAY_SIZE(esdhc_d_sel)); clk[IMX5_CLK_ESDHC1_PER_GATE] = imx_clk_gate2("esdhc1_per_gate", "esdhc_a_podf", MXC_CCM_CCGR3, 2); clk[IMX5_CLK_ESDHC2_PER_GATE] = imx_clk_gate2("esdhc2_per_gate", "esdhc_c_sel", MXC_CCM_CCGR3, 6); clk[IMX5_CLK_ESDHC3_PER_GATE] = imx_clk_gate2("esdhc3_per_gate", "esdhc_b_podf", MXC_CCM_CCGR3, 10); @@ -372,6 +371,10 @@ static void __init mx50_clocks_init(struct device_node *np) clk_data.clk_num = ARRAY_SIZE(clk); of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data); + /* Set SDHC parents to be PLL2 */ + clk_set_parent(clk[IMX5_CLK_ESDHC_A_SEL], clk[IMX5_CLK_PLL2_SW]); + clk_set_parent(clk[IMX5_CLK_ESDHC_B_SEL], clk[IMX5_CLK_PLL2_SW]); + /* set SDHC root clock to 200MHZ*/ clk_set_rate(clk[IMX5_CLK_ESDHC_A_PODF], 200000000); clk_set_rate(clk[IMX5_CLK_ESDHC_B_PODF], 200000000); @@ -410,6 +413,10 @@ static void __init mx51_clocks_init(struct device_node *np) mx5_clocks_common_init(ccm_base); + clk[IMX5_CLK_PERIPH_APM] = imx_clk_mux("periph_apm", MXC_CCM_CBCMR, 12, 2, + periph_apm_sel, ARRAY_SIZE(periph_apm_sel)); + clk[IMX5_CLK_MAIN_BUS] = imx_clk_mux("main_bus", MXC_CCM_CBCDR, 25, 1, + main_bus_sel, ARRAY_SIZE(main_bus_sel)); clk[IMX5_CLK_LP_APM] = imx_clk_mux("lp_apm", MXC_CCM_CCSR, 9, 1, lp_apm_sel, ARRAY_SIZE(lp_apm_sel)); clk[IMX5_CLK_IPU_DI0_SEL] = imx_clk_mux_flags("ipu_di0_sel", MXC_CCM_CSCMR2, 26, 3, @@ -422,6 +429,12 @@ static void __init mx51_clocks_init(struct device_node *np) mx51_tve_sel, ARRAY_SIZE(mx51_tve_sel)); clk[IMX5_CLK_TVE_GATE] = imx_clk_gate2("tve_gate", "tve_sel", MXC_CCM_CCGR2, 30); clk[IMX5_CLK_TVE_PRED] = imx_clk_divider("tve_pred", "pll3_sw", MXC_CCM_CDCDR, 28, 3); + clk[IMX5_CLK_ESDHC_A_SEL] = imx_clk_mux("esdhc_a_sel", MXC_CCM_CSCMR1, 20, 2, + standard_pll_sel, ARRAY_SIZE(standard_pll_sel)); + clk[IMX5_CLK_ESDHC_B_SEL] = imx_clk_mux("esdhc_b_sel", MXC_CCM_CSCMR1, 16, 2, + standard_pll_sel, ARRAY_SIZE(standard_pll_sel)); + clk[IMX5_CLK_ESDHC_C_SEL] = imx_clk_mux("esdhc_c_sel", MXC_CCM_CSCMR1, 19, 1, esdhc_c_sel, ARRAY_SIZE(esdhc_c_sel)); + clk[IMX5_CLK_ESDHC_D_SEL] = imx_clk_mux("esdhc_d_sel", MXC_CCM_CSCMR1, 18, 1, esdhc_d_sel, ARRAY_SIZE(esdhc_d_sel)); clk[IMX5_CLK_ESDHC1_PER_GATE] = imx_clk_gate2("esdhc1_per_gate", "esdhc_a_podf", MXC_CCM_CCGR3, 2); clk[IMX5_CLK_ESDHC2_PER_GATE] = imx_clk_gate2("esdhc2_per_gate", "esdhc_b_podf", MXC_CCM_CCGR3, 6); clk[IMX5_CLK_ESDHC3_PER_GATE] = imx_clk_gate2("esdhc3_per_gate", "esdhc_c_sel", MXC_CCM_CCGR3, 10); @@ -452,6 +465,10 @@ static void __init mx51_clocks_init(struct device_node *np) /* set the usboh3 parent to pll2_sw */ clk_set_parent(clk[IMX5_CLK_USBOH3_SEL], clk[IMX5_CLK_PLL2_SW]); + /* Set SDHC parents to be PLL2 */ + clk_set_parent(clk[IMX5_CLK_ESDHC_A_SEL], clk[IMX5_CLK_PLL2_SW]); + clk_set_parent(clk[IMX5_CLK_ESDHC_B_SEL], clk[IMX5_CLK_PLL2_SW]); + /* set SDHC root clock to 166.25MHZ*/ clk_set_rate(clk[IMX5_CLK_ESDHC_A_PODF], 166250000); clk_set_rate(clk[IMX5_CLK_ESDHC_B_PODF], 166250000); @@ -506,6 +523,10 @@ static void __init mx53_clocks_init(struct device_node *np) mx5_clocks_common_init(ccm_base); + clk[IMX5_CLK_PERIPH_APM] = imx_clk_mux("periph_apm", MXC_CCM_CBCMR, 12, 2, + periph_apm_sel, ARRAY_SIZE(periph_apm_sel)); + clk[IMX5_CLK_MAIN_BUS] = imx_clk_mux("main_bus", MXC_CCM_CBCDR, 25, 1, + main_bus_sel, ARRAY_SIZE(main_bus_sel)); clk[IMX5_CLK_LP_APM] = imx_clk_mux("lp_apm", MXC_CCM_CCSR, 10, 1, lp_apm_sel, ARRAY_SIZE(lp_apm_sel)); clk[IMX5_CLK_LDB_DI1_DIV_3_5] = imx_clk_fixed_factor("ldb_di1_div_3_5", "ldb_di1_sel", 2, 7); @@ -527,6 +548,12 @@ static void __init mx53_clocks_init(struct device_node *np) mx53_tve_ext_sel, ARRAY_SIZE(mx53_tve_ext_sel), CLK_SET_RATE_PARENT); clk[IMX5_CLK_TVE_GATE] = imx_clk_gate2("tve_gate", "tve_pred", MXC_CCM_CCGR2, 30); clk[IMX5_CLK_TVE_PRED] = imx_clk_divider("tve_pred", "tve_ext_sel", MXC_CCM_CDCDR, 28, 3); + clk[IMX5_CLK_ESDHC_A_SEL] = imx_clk_mux("esdhc_a_sel", MXC_CCM_CSCMR1, 20, 2, + standard_pll_sel, ARRAY_SIZE(standard_pll_sel)); + clk[IMX5_CLK_ESDHC_B_SEL] = imx_clk_mux("esdhc_b_sel", MXC_CCM_CSCMR1, 16, 2, + standard_pll_sel, ARRAY_SIZE(standard_pll_sel)); + clk[IMX5_CLK_ESDHC_C_SEL] = imx_clk_mux("esdhc_c_sel", MXC_CCM_CSCMR1, 19, 1, esdhc_c_sel, ARRAY_SIZE(esdhc_c_sel)); + clk[IMX5_CLK_ESDHC_D_SEL] = imx_clk_mux("esdhc_d_sel", MXC_CCM_CSCMR1, 18, 1, esdhc_d_sel, ARRAY_SIZE(esdhc_d_sel)); clk[IMX5_CLK_ESDHC1_PER_GATE] = imx_clk_gate2("esdhc1_per_gate", "esdhc_a_podf", MXC_CCM_CCGR3, 2); clk[IMX5_CLK_ESDHC2_PER_GATE] = imx_clk_gate2("esdhc2_per_gate", "esdhc_c_sel", MXC_CCM_CCGR3, 6); clk[IMX5_CLK_ESDHC3_PER_GATE] = imx_clk_gate2("esdhc3_per_gate", "esdhc_b_podf", MXC_CCM_CCGR3, 10); @@ -589,6 +616,10 @@ static void __init mx53_clocks_init(struct device_node *np) clk_data.clk_num = ARRAY_SIZE(clk); of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data); + /* Set SDHC parents to be PLL2 */ + clk_set_parent(clk[IMX5_CLK_ESDHC_A_SEL], clk[IMX5_CLK_PLL2_SW]); + clk_set_parent(clk[IMX5_CLK_ESDHC_B_SEL], clk[IMX5_CLK_PLL2_SW]); + /* set SDHC root clock to 200MHZ*/ clk_set_rate(clk[IMX5_CLK_ESDHC_A_PODF], 200000000); clk_set_rate(clk[IMX5_CLK_ESDHC_B_PODF], 200000000); diff --git a/drivers/clk/imx/clk-imx6sll.c b/drivers/clk/imx/clk-imx6sll.c index 3bd2044cf25c..7eea448cb9a9 100644 --- a/drivers/clk/imx/clk-imx6sll.c +++ b/drivers/clk/imx/clk-imx6sll.c @@ -76,6 +76,20 @@ static u32 share_count_ssi1; static u32 share_count_ssi2; static u32 share_count_ssi3; +static struct clk ** const uart_clks[] __initconst = { + &clks[IMX6SLL_CLK_UART1_IPG], + &clks[IMX6SLL_CLK_UART1_SERIAL], + &clks[IMX6SLL_CLK_UART2_IPG], + &clks[IMX6SLL_CLK_UART2_SERIAL], + &clks[IMX6SLL_CLK_UART3_IPG], + &clks[IMX6SLL_CLK_UART3_SERIAL], + &clks[IMX6SLL_CLK_UART4_IPG], + &clks[IMX6SLL_CLK_UART4_SERIAL], + &clks[IMX6SLL_CLK_UART5_IPG], + &clks[IMX6SLL_CLK_UART5_SERIAL], + NULL +}; + static void __init imx6sll_clocks_init(struct device_node *ccm_node) { struct device_node *np; @@ -268,7 +282,7 @@ static void __init imx6sll_clocks_init(struct device_node *ccm_node) clks[IMX6SLL_CLK_GPT_BUS] = imx_clk_gate2("gpt1_bus", "perclk", base + 0x6c, 20); clks[IMX6SLL_CLK_GPT_SERIAL] = imx_clk_gate2("gpt1_serial", "perclk", base + 0x6c, 22); clks[IMX6SLL_CLK_UART4_IPG] = imx_clk_gate2("uart4_ipg", "ipg", base + 0x6c, 24); - clks[IMX6SLL_CLK_UART4_SERIAL] = imx_clk_gate2("uart4_serail", "uart_podf", base + 0x6c, 24); + clks[IMX6SLL_CLK_UART4_SERIAL] = imx_clk_gate2("uart4_serial", "uart_podf", base + 0x6c, 24); clks[IMX6SLL_CLK_GPIO1] = imx_clk_gate2("gpio1", "ipg", base + 0x6c, 26); clks[IMX6SLL_CLK_GPIO5] = imx_clk_gate2("gpio5", "ipg", base + 0x6c, 30); @@ -334,6 +348,8 @@ static void __init imx6sll_clocks_init(struct device_node *ccm_node) clk_data.clk_num = ARRAY_SIZE(clks); of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data); + imx_register_uart_clocks(uart_clks); + /* Lower the AHB clock rate before changing the clock source. */ clk_set_rate(clks[IMX6SLL_CLK_AHB], 99000000); diff --git a/drivers/clk/imx/clk-imx7d.c b/drivers/clk/imx/clk-imx7d.c index cfbd8d4edb85..5b8a0c729f90 100644 --- a/drivers/clk/imx/clk-imx7d.c +++ b/drivers/clk/imx/clk-imx7d.c @@ -417,8 +417,8 @@ static void __init imx7d_clocks_init(struct device_node *ccm_node) clks[IMX7D_PLL_DRAM_MAIN] = imx_clk_pllv3(IMX_PLLV3_DDR_IMX7, "pll_dram_main", "osc", base + 0x70, 0x7f); clks[IMX7D_PLL_SYS_MAIN] = imx_clk_pllv3(IMX_PLLV3_GENERIC, "pll_sys_main", "osc", base + 0xb0, 0x1); clks[IMX7D_PLL_ENET_MAIN] = imx_clk_pllv3(IMX_PLLV3_ENET_IMX7, "pll_enet_main", "osc", base + 0xe0, 0x0); - clks[IMX7D_PLL_AUDIO_MAIN] = imx_clk_pllv3(IMX_PLLV3_AV, "pll_audio_main", "osc", base + 0xf0, 0x7f); - clks[IMX7D_PLL_VIDEO_MAIN] = imx_clk_pllv3(IMX_PLLV3_AV, "pll_video_main", "osc", base + 0x130, 0x7f); + clks[IMX7D_PLL_AUDIO_MAIN] = imx_clk_pllv3(IMX_PLLV3_AV_IMX7, "pll_audio_main", "osc", base + 0xf0, 0x7f); + clks[IMX7D_PLL_VIDEO_MAIN] = imx_clk_pllv3(IMX_PLLV3_AV_IMX7, "pll_video_main", "osc", base + 0x130, 0x7f); clks[IMX7D_PLL_ARM_MAIN_BYPASS] = imx_clk_mux_flags("pll_arm_main_bypass", base + 0x60, 16, 1, pll_arm_bypass_sel, ARRAY_SIZE(pll_arm_bypass_sel), CLK_SET_RATE_PARENT); clks[IMX7D_PLL_DRAM_MAIN_BYPASS] = imx_clk_mux_flags("pll_dram_main_bypass", base + 0x70, 16, 1, pll_dram_bypass_sel, ARRAY_SIZE(pll_dram_bypass_sel), CLK_SET_RATE_PARENT); diff --git a/drivers/clk/imx/clk-imx7ulp.c b/drivers/clk/imx/clk-imx7ulp.c index ce306631e844..66682100f14c 100644 --- a/drivers/clk/imx/clk-imx7ulp.c +++ b/drivers/clk/imx/clk-imx7ulp.c @@ -151,7 +151,6 @@ static void __init imx7ulp_clk_pcc2_init(struct device_node *np) clks[IMX7ULP_CLK_DMA1] = imx_clk_hw_gate("dma1", "nic1_clk", base + 0x20, 30); clks[IMX7ULP_CLK_RGPIO2P1] = imx_clk_hw_gate("rgpio2p1", "nic1_bus_clk", base + 0x3c, 30); clks[IMX7ULP_CLK_DMA_MUX1] = imx_clk_hw_gate("dma_mux1", "nic1_bus_clk", base + 0x84, 30); - clks[IMX7ULP_CLK_SNVS] = imx_clk_hw_gate("snvs", "nic1_bus_clk", base + 0x8c, 30); clks[IMX7ULP_CLK_CAAM] = imx_clk_hw_gate("caam", "nic1_clk", base + 0x90, 30); clks[IMX7ULP_CLK_LPTPM4] = imx7ulp_clk_composite("lptpm4", periph_bus_sels, ARRAY_SIZE(periph_bus_sels), true, false, true, base + 0x94); clks[IMX7ULP_CLK_LPTPM5] = imx7ulp_clk_composite("lptpm5", periph_bus_sels, ARRAY_SIZE(periph_bus_sels), true, false, true, base + 0x98); diff --git a/drivers/clk/imx/clk-imx8mq.c b/drivers/clk/imx/clk-imx8mq.c index a9b3888aef0c..daf1841b2adb 100644 --- a/drivers/clk/imx/clk-imx8mq.c +++ b/drivers/clk/imx/clk-imx8mq.c @@ -458,6 +458,7 @@ static int imx8mq_clocks_probe(struct platform_device *pdev) clks[IMX8MQ_CLK_DSI_DBI] = imx8m_clk_composite("dsi_dbi", imx8mq_dsi_dbi_sels, base + 0xbc00); clks[IMX8MQ_CLK_DSI_ESC] = imx8m_clk_composite("dsi_esc", imx8mq_dsi_esc_sels, base + 0xbc80); clks[IMX8MQ_CLK_DSI_AHB] = imx8m_clk_composite("dsi_ahb", imx8mq_dsi_ahb_sels, base + 0x9200); + clks[IMX8MQ_CLK_DSI_IPG_DIV] = imx_clk_divider2("dsi_ipg_div", "dsi_ahb", base + 0x9280, 0, 6); clks[IMX8MQ_CLK_CSI1_CORE] = imx8m_clk_composite("csi1_core", imx8mq_csi1_core_sels, base + 0xbd00); clks[IMX8MQ_CLK_CSI1_PHY_REF] = imx8m_clk_composite("csi1_phy_ref", imx8mq_csi1_phy_sels, base + 0xbd80); clks[IMX8MQ_CLK_CSI1_ESC] = imx8m_clk_composite("csi1_esc", imx8mq_csi1_esc_sels, base + 0xbe00); diff --git a/drivers/clk/imx/clk-pfdv2.c b/drivers/clk/imx/clk-pfdv2.c index 7e9134b205ab..fb567dcc2118 100644 --- a/drivers/clk/imx/clk-pfdv2.c +++ b/drivers/clk/imx/clk-pfdv2.c @@ -43,7 +43,7 @@ static int clk_pfdv2_wait(struct clk_pfdv2 *pfd) { u32 val; - return readl_poll_timeout(pfd->reg, val, val & pfd->vld_bit, + return readl_poll_timeout(pfd->reg, val, val & (1 << pfd->vld_bit), 0, LOCK_TIMEOUT_US); } @@ -55,7 +55,7 @@ static int clk_pfdv2_enable(struct clk_hw *hw) spin_lock_irqsave(&pfd_lock, flags); val = readl_relaxed(pfd->reg); - val &= ~pfd->gate_bit; + val &= ~(1 << pfd->gate_bit); writel_relaxed(val, pfd->reg); spin_unlock_irqrestore(&pfd_lock, flags); @@ -70,7 +70,7 @@ static void clk_pfdv2_disable(struct clk_hw *hw) spin_lock_irqsave(&pfd_lock, flags); val = readl_relaxed(pfd->reg); - val |= pfd->gate_bit; + val |= (1 << pfd->gate_bit); writel_relaxed(val, pfd->reg); spin_unlock_irqrestore(&pfd_lock, flags); } @@ -123,7 +123,7 @@ static int clk_pfdv2_is_enabled(struct clk_hw *hw) { struct clk_pfdv2 *pfd = to_clk_pfdv2(hw); - if (readl_relaxed(pfd->reg) & pfd->gate_bit) + if (readl_relaxed(pfd->reg) & (1 << pfd->gate_bit)) return 0; return 1; @@ -180,7 +180,7 @@ struct clk_hw *imx_clk_pfdv2(const char *name, const char *parent_name, return ERR_PTR(-ENOMEM); pfd->reg = reg; - pfd->gate_bit = 1 << ((idx + 1) * 8 - 1); + pfd->gate_bit = (idx + 1) * 8 - 1; pfd->vld_bit = pfd->gate_bit - 1; pfd->frac_off = idx * 8; diff --git a/drivers/clk/imx/clk-pll14xx.c b/drivers/clk/imx/clk-pll14xx.c index 1acfa3e3cfb4..b7213023b238 100644 --- a/drivers/clk/imx/clk-pll14xx.c +++ b/drivers/clk/imx/clk-pll14xx.c @@ -74,10 +74,9 @@ static unsigned long clk_pll1416x_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) { struct clk_pll14xx *pll = to_clk_pll14xx(hw); - u32 mdiv, pdiv, sdiv, pll_gnrl, pll_div; + u32 mdiv, pdiv, sdiv, pll_div; u64 fvco = parent_rate; - pll_gnrl = readl_relaxed(pll->base); pll_div = readl_relaxed(pll->base + 4); mdiv = (pll_div & MDIV_MASK) >> MDIV_SHIFT; pdiv = (pll_div & PDIV_MASK) >> PDIV_SHIFT; @@ -93,11 +92,10 @@ static unsigned long clk_pll1443x_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) { struct clk_pll14xx *pll = to_clk_pll14xx(hw); - u32 mdiv, pdiv, sdiv, pll_gnrl, pll_div_ctl0, pll_div_ctl1; + u32 mdiv, pdiv, sdiv, pll_div_ctl0, pll_div_ctl1; short int kdiv; u64 fvco = parent_rate; - pll_gnrl = readl_relaxed(pll->base); pll_div_ctl0 = readl_relaxed(pll->base + 4); pll_div_ctl1 = readl_relaxed(pll->base + 8); mdiv = (pll_div_ctl0 & MDIV_MASK) >> MDIV_SHIFT; @@ -362,7 +360,7 @@ struct clk *imx_clk_pll14xx(const char *name, const char *parent_name, switch (pll_clk->type) { case PLL_1416X: - if (!pll->rate_table) + if (!pll_clk->rate_table) init.ops = &clk_pll1416x_min_ops; else init.ops = &clk_pll1416x_ops; diff --git a/drivers/clk/imx/clk-pllv3.c b/drivers/clk/imx/clk-pllv3.c index 9af62ee8f347..4110e713d259 100644 --- a/drivers/clk/imx/clk-pllv3.c +++ b/drivers/clk/imx/clk-pllv3.c @@ -20,6 +20,8 @@ #define PLL_NUM_OFFSET 0x10 #define PLL_DENOM_OFFSET 0x20 +#define PLL_IMX7_NUM_OFFSET 0x20 +#define PLL_IMX7_DENOM_OFFSET 0x30 #define PLL_VF610_NUM_OFFSET 0x20 #define PLL_VF610_DENOM_OFFSET 0x30 @@ -49,6 +51,8 @@ struct clk_pllv3 { u32 div_mask; u32 div_shift; unsigned long ref_clock; + u32 num_offset; + u32 denom_offset; }; #define to_clk_pllv3(_hw) container_of(_hw, struct clk_pllv3, hw) @@ -219,8 +223,8 @@ static unsigned long clk_pllv3_av_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) { struct clk_pllv3 *pll = to_clk_pllv3(hw); - u32 mfn = readl_relaxed(pll->base + PLL_NUM_OFFSET); - u32 mfd = readl_relaxed(pll->base + PLL_DENOM_OFFSET); + u32 mfn = readl_relaxed(pll->base + pll->num_offset); + u32 mfd = readl_relaxed(pll->base + pll->denom_offset); u32 div = readl_relaxed(pll->base) & pll->div_mask; u64 temp64 = (u64)parent_rate; @@ -289,8 +293,8 @@ static int clk_pllv3_av_set_rate(struct clk_hw *hw, unsigned long rate, val &= ~pll->div_mask; val |= div; writel_relaxed(val, pll->base); - writel_relaxed(mfn, pll->base + PLL_NUM_OFFSET); - writel_relaxed(mfd, pll->base + PLL_DENOM_OFFSET); + writel_relaxed(mfn, pll->base + pll->num_offset); + writel_relaxed(mfd, pll->base + pll->denom_offset); return clk_pllv3_wait_lock(pll); } @@ -352,8 +356,8 @@ static unsigned long clk_pllv3_vf610_recalc_rate(struct clk_hw *hw, struct clk_pllv3 *pll = to_clk_pllv3(hw); struct clk_pllv3_vf610_mf mf; - mf.mfn = readl_relaxed(pll->base + PLL_VF610_NUM_OFFSET); - mf.mfd = readl_relaxed(pll->base + PLL_VF610_DENOM_OFFSET); + mf.mfn = readl_relaxed(pll->base + pll->num_offset); + mf.mfd = readl_relaxed(pll->base + pll->denom_offset); mf.mfi = (readl_relaxed(pll->base) & pll->div_mask) ? 22 : 20; return clk_pllv3_vf610_mf_to_rate(parent_rate, mf); @@ -382,8 +386,8 @@ static int clk_pllv3_vf610_set_rate(struct clk_hw *hw, unsigned long rate, val |= pll->div_mask; /* set bit for mfi=22 */ writel_relaxed(val, pll->base); - writel_relaxed(mf.mfn, pll->base + PLL_VF610_NUM_OFFSET); - writel_relaxed(mf.mfd, pll->base + PLL_VF610_DENOM_OFFSET); + writel_relaxed(mf.mfn, pll->base + pll->num_offset); + writel_relaxed(mf.mfd, pll->base + pll->denom_offset); return clk_pllv3_wait_lock(pll); } @@ -426,6 +430,8 @@ struct clk *imx_clk_pllv3(enum imx_pllv3_type type, const char *name, return ERR_PTR(-ENOMEM); pll->power_bit = BM_PLL_POWER; + pll->num_offset = PLL_NUM_OFFSET; + pll->denom_offset = PLL_DENOM_OFFSET; switch (type) { case IMX_PLLV3_SYS: @@ -433,13 +439,20 @@ struct clk *imx_clk_pllv3(enum imx_pllv3_type type, const char *name, break; case IMX_PLLV3_SYS_VF610: ops = &clk_pllv3_vf610_ops; + pll->num_offset = PLL_VF610_NUM_OFFSET; + pll->denom_offset = PLL_VF610_DENOM_OFFSET; break; case IMX_PLLV3_USB_VF610: pll->div_shift = 1; + /* fall through */ case IMX_PLLV3_USB: ops = &clk_pllv3_ops; pll->powerup_set = true; break; + case IMX_PLLV3_AV_IMX7: + pll->num_offset = PLL_IMX7_NUM_OFFSET; + pll->denom_offset = PLL_IMX7_DENOM_OFFSET; + /* fall through */ case IMX_PLLV3_AV: ops = &clk_pllv3_av_ops; break; @@ -454,6 +467,8 @@ struct clk *imx_clk_pllv3(enum imx_pllv3_type type, const char *name, break; case IMX_PLLV3_DDR_IMX7: pll->power_bit = IMX7_DDR_PLL_POWER; + pll->num_offset = PLL_IMX7_NUM_OFFSET; + pll->denom_offset = PLL_IMX7_DENOM_OFFSET; ops = &clk_pllv3_av_ops; break; default: diff --git a/drivers/clk/imx/clk-pllv4.c b/drivers/clk/imx/clk-pllv4.c index d38bc9f87c1d..d7e62c3620d3 100644 --- a/drivers/clk/imx/clk-pllv4.c +++ b/drivers/clk/imx/clk-pllv4.c @@ -30,6 +30,9 @@ /* PLL Denominator Register (xPLLDENOM) */ #define PLL_DENOM_OFFSET 0x14 +#define MAX_MFD 0x3fffffff +#define DEFAULT_MFD 1000000 + struct clk_pllv4 { struct clk_hw hw; void __iomem *base; @@ -64,13 +67,20 @@ static unsigned long clk_pllv4_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) { struct clk_pllv4 *pll = to_clk_pllv4(hw); - u32 div; + u32 mult, mfn, mfd; + u64 temp64; + + mult = readl_relaxed(pll->base + PLL_CFG_OFFSET); + mult &= BM_PLL_MULT; + mult >>= BP_PLL_MULT; - div = readl_relaxed(pll->base + PLL_CFG_OFFSET); - div &= BM_PLL_MULT; - div >>= BP_PLL_MULT; + mfn = readl_relaxed(pll->base + PLL_NUM_OFFSET); + mfd = readl_relaxed(pll->base + PLL_DENOM_OFFSET); + temp64 = parent_rate; + temp64 *= mfn; + do_div(temp64, mfd); - return parent_rate * div; + return (parent_rate * mult) + (u32)temp64; } static long clk_pllv4_round_rate(struct clk_hw *hw, unsigned long rate, @@ -78,14 +88,46 @@ static long clk_pllv4_round_rate(struct clk_hw *hw, unsigned long rate, { unsigned long parent_rate = *prate; unsigned long round_rate, i; + u32 mfn, mfd = DEFAULT_MFD; + bool found = false; + u64 temp64; for (i = 0; i < ARRAY_SIZE(pllv4_mult_table); i++) { round_rate = parent_rate * pllv4_mult_table[i]; - if (rate >= round_rate) - return round_rate; + if (rate >= round_rate) { + found = true; + break; + } + } + + if (!found) { + pr_warn("%s: unable to round rate %lu, parent rate %lu\n", + clk_hw_get_name(hw), rate, parent_rate); + return 0; } - return round_rate; + if (parent_rate <= MAX_MFD) + mfd = parent_rate; + + temp64 = (u64)(rate - round_rate); + temp64 *= mfd; + do_div(temp64, parent_rate); + mfn = temp64; + + /* + * NOTE: The value of numerator must always be configured to be + * less than the value of the denominator. If we can't get a proper + * pair of mfn/mfd, we simply return the round_rate without using + * the frac part. + */ + if (mfn >= mfd) + return round_rate; + + temp64 = (u64)parent_rate; + temp64 *= mfn; + do_div(temp64, mfd); + + return round_rate + (u32)temp64; } static bool clk_pllv4_is_valid_mult(unsigned int mult) @@ -105,18 +147,30 @@ static int clk_pllv4_set_rate(struct clk_hw *hw, unsigned long rate, unsigned long parent_rate) { struct clk_pllv4 *pll = to_clk_pllv4(hw); - u32 val, mult; + u32 val, mult, mfn, mfd = DEFAULT_MFD; + u64 temp64; mult = rate / parent_rate; if (!clk_pllv4_is_valid_mult(mult)) return -EINVAL; + if (parent_rate <= MAX_MFD) + mfd = parent_rate; + + temp64 = (u64)(rate - mult * parent_rate); + temp64 *= mfd; + do_div(temp64, parent_rate); + mfn = temp64; + val = readl_relaxed(pll->base + PLL_CFG_OFFSET); val &= ~BM_PLL_MULT; val |= mult << BP_PLL_MULT; writel_relaxed(val, pll->base + PLL_CFG_OFFSET); + writel_relaxed(mfn, pll->base + PLL_NUM_OFFSET); + writel_relaxed(mfd, pll->base + PLL_DENOM_OFFSET); + return 0; } diff --git a/drivers/clk/imx/clk.h b/drivers/clk/imx/clk.h index 5748ec8673e4..8639a8f2153e 100644 --- a/drivers/clk/imx/clk.h +++ b/drivers/clk/imx/clk.h @@ -77,6 +77,7 @@ enum imx_pllv3_type { IMX_PLLV3_ENET_IMX7, IMX_PLLV3_SYS_VF610, IMX_PLLV3_DDR_IMX7, + IMX_PLLV3_AV_IMX7, }; struct clk *imx_clk_pllv3(enum imx_pllv3_type type, const char *name, @@ -138,11 +139,6 @@ static inline struct clk_hw *imx_clk_hw_fixed(const char *name, int rate) return clk_hw_register_fixed_rate(NULL, name, NULL, 0, rate); } -static inline struct clk_hw *imx_get_clk_hw_fixed(const char *name, int rate) -{ - return clk_hw_register_fixed_rate(NULL, name, NULL, 0, rate); -} - static inline struct clk *imx_clk_mux_ldb(const char *name, void __iomem *reg, u8 shift, u8 width, const char * const *parents, int num_parents) diff --git a/drivers/clk/mediatek/clk-gate.c b/drivers/clk/mediatek/clk-gate.c index 9628d4e7690b..85daf826619a 100644 --- a/drivers/clk/mediatek/clk-gate.c +++ b/drivers/clk/mediatek/clk-gate.c @@ -169,11 +169,10 @@ struct clk *mtk_clk_register_gate( return ERR_PTR(-ENOMEM); init.name = name; - init.flags = CLK_SET_RATE_PARENT; + init.flags = flags | CLK_SET_RATE_PARENT; init.parent_names = parent_name ? &parent_name : NULL; init.num_parents = parent_name ? 1 : 0; init.ops = ops; - init.flags = flags; cg->regmap = regmap; cg->set_ofs = set_ofs; diff --git a/drivers/clk/meson/clk-pll.c b/drivers/clk/meson/clk-pll.c index 41e16dd7272a..7a14ac9b2fec 100644 --- a/drivers/clk/meson/clk-pll.c +++ b/drivers/clk/meson/clk-pll.c @@ -120,7 +120,7 @@ static bool meson_clk_pll_is_better(unsigned long rate, return true; } else { /* Round down */ - if (now < rate && best < now) + if (now <= rate && best < now) return true; } diff --git a/drivers/clk/meson/g12a.c b/drivers/clk/meson/g12a.c index 0e1ce8c03259..f7b11e1eeebe 100644 --- a/drivers/clk/meson/g12a.c +++ b/drivers/clk/meson/g12a.c @@ -960,14 +960,14 @@ static struct clk_regmap g12a_sd_emmc_c_clk0 = { /* VPU Clock */ static const char * const g12a_vpu_parent_names[] = { - "fclk_div4", "fclk_div3", "fclk_div5", "fclk_div7", + "fclk_div3", "fclk_div4", "fclk_div5", "fclk_div7", "mpll1", "vid_pll", "hifi_pll", "gp0_pll", }; static struct clk_regmap g12a_vpu_0_sel = { .data = &(struct clk_regmap_mux_data){ .offset = HHI_VPU_CLK_CNTL, - .mask = 0x3, + .mask = 0x7, .shift = 9, }, .hw.init = &(struct clk_init_data){ @@ -1011,7 +1011,7 @@ static struct clk_regmap g12a_vpu_0 = { static struct clk_regmap g12a_vpu_1_sel = { .data = &(struct clk_regmap_mux_data){ .offset = HHI_VPU_CLK_CNTL, - .mask = 0x3, + .mask = 0x7, .shift = 25, }, .hw.init = &(struct clk_init_data){ diff --git a/drivers/clk/meson/gxbb.c b/drivers/clk/meson/gxbb.c index 04df2e208ed6..29ffb4fde714 100644 --- a/drivers/clk/meson/gxbb.c +++ b/drivers/clk/meson/gxbb.c @@ -2216,6 +2216,7 @@ static struct clk_regmap gxbb_vdec_1_div = { .offset = HHI_VDEC_CLK_CNTL, .shift = 0, .width = 7, + .flags = CLK_DIVIDER_ROUND_CLOSEST, }, .hw.init = &(struct clk_init_data){ .name = "vdec_1_div", @@ -2261,6 +2262,7 @@ static struct clk_regmap gxbb_vdec_hevc_div = { .offset = HHI_VDEC2_CLK_CNTL, .shift = 16, .width = 7, + .flags = CLK_DIVIDER_ROUND_CLOSEST, }, .hw.init = &(struct clk_init_data){ .name = "vdec_hevc_div", diff --git a/drivers/clk/meson/vid-pll-div.c b/drivers/clk/meson/vid-pll-div.c index 08bcc01c0923..daff235bc763 100644 --- a/drivers/clk/meson/vid-pll-div.c +++ b/drivers/clk/meson/vid-pll-div.c @@ -82,8 +82,8 @@ static unsigned long meson_vid_pll_div_recalc_rate(struct clk_hw *hw, div = _get_table_val(meson_parm_read(clk->map, &pll_div->val), meson_parm_read(clk->map, &pll_div->sel)); if (!div || !div->divider) { - pr_info("%s: Invalid config value for vid_pll_div\n", __func__); - return parent_rate; + pr_debug("%s: Invalid config value for vid_pll_div\n", __func__); + return 0; } return DIV_ROUND_UP_ULL(parent_rate * div->multiplier, div->divider); diff --git a/drivers/clk/qcom/Kconfig b/drivers/clk/qcom/Kconfig index 1c04575c118f..18bdf34d5e64 100644 --- a/drivers/clk/qcom/Kconfig +++ b/drivers/clk/qcom/Kconfig @@ -243,6 +243,12 @@ config SDM_GCC_660 Say Y if you want to use peripheral devices such as UART, SPI, i2C, USB, UFS, SDDC, PCIe, etc. +config QCS_TURING_404 + tristate "QCS404 Turing Clock Controller" + help + Support for the Turing Clock Controller on QCS404, provides clocks + and resets for the Turing subsystem. + config SDM_GCC_845 tristate "SDM845 Global Clock Controller" select QCOM_GDSC diff --git a/drivers/clk/qcom/Makefile b/drivers/clk/qcom/Makefile index ee8d0698e370..f0768fb1f037 100644 --- a/drivers/clk/qcom/Makefile +++ b/drivers/clk/qcom/Makefile @@ -42,6 +42,7 @@ obj-$(CONFIG_QCOM_CLK_RPM) += clk-rpm.o obj-$(CONFIG_QCOM_CLK_RPMH) += clk-rpmh.o obj-$(CONFIG_QCOM_CLK_SMD_RPM) += clk-smd-rpm.o obj-$(CONFIG_QCS_GCC_404) += gcc-qcs404.o +obj-$(CONFIG_QCS_TURING_404) += turingcc-qcs404.o obj-$(CONFIG_SDM_CAMCC_845) += camcc-sdm845.o obj-$(CONFIG_SDM_DISPCC_845) += dispcc-sdm845.o obj-$(CONFIG_SDM_GCC_660) += gcc-sdm660.o diff --git a/drivers/clk/qcom/clk-branch.c b/drivers/clk/qcom/clk-branch.c index 99446bf630aa..f869fc6aaed6 100644 --- a/drivers/clk/qcom/clk-branch.c +++ b/drivers/clk/qcom/clk-branch.c @@ -146,6 +146,12 @@ const struct clk_ops clk_branch2_ops = { }; EXPORT_SYMBOL_GPL(clk_branch2_ops); +const struct clk_ops clk_branch2_aon_ops = { + .enable = clk_branch2_enable, + .is_enabled = clk_is_enabled_regmap, +}; +EXPORT_SYMBOL_GPL(clk_branch2_aon_ops); + const struct clk_ops clk_branch_simple_ops = { .enable = clk_enable_regmap, .disable = clk_disable_regmap, diff --git a/drivers/clk/qcom/clk-branch.h b/drivers/clk/qcom/clk-branch.h index b3561e0a3984..17a58119165e 100644 --- a/drivers/clk/qcom/clk-branch.h +++ b/drivers/clk/qcom/clk-branch.h @@ -40,6 +40,7 @@ struct clk_branch { extern const struct clk_ops clk_branch_ops; extern const struct clk_ops clk_branch2_ops; extern const struct clk_ops clk_branch_simple_ops; +extern const struct clk_ops clk_branch2_aon_ops; #define to_clk_branch(_hw) \ container_of(to_clk_regmap(_hw), struct clk_branch, clkr) diff --git a/drivers/clk/qcom/gcc-msm8998.c b/drivers/clk/qcom/gcc-msm8998.c index c240fba794c7..033688264c7b 100644 --- a/drivers/clk/qcom/gcc-msm8998.c +++ b/drivers/clk/qcom/gcc-msm8998.c @@ -2161,7 +2161,7 @@ static struct clk_branch gcc_pcie_0_mstr_axi_clk = { static struct clk_branch gcc_pcie_0_pipe_clk = { .halt_reg = 0x6b018, - .halt_check = BRANCH_HALT, + .halt_check = BRANCH_HALT_SKIP, .clkr = { .enable_reg = 0x6b018, .enable_mask = BIT(0), diff --git a/drivers/clk/qcom/gcc-qcs404.c b/drivers/clk/qcom/gcc-qcs404.c index 5a62f64ada93..a54807eb3b28 100644 --- a/drivers/clk/qcom/gcc-qcs404.c +++ b/drivers/clk/qcom/gcc-qcs404.c @@ -260,6 +260,20 @@ static const char * const gcc_parent_names_15[] = { "core_bi_pll_test_se", }; +static const struct parent_map gcc_parent_map_16[] = { + { P_XO, 0 }, + { P_GPLL0_OUT_MAIN, 1 }, + { P_GPLL0_OUT_AUX, 2 }, + { P_CORE_BI_PLL_TEST_SE, 7 }, +}; + +static const char * const gcc_parent_names_16[] = { + "cxo", + "gpll0_out_main", + "gpll0_out_aux", + "core_bi_pll_test_se", +}; + static struct clk_fixed_factor cxo = { .mult = 1, .div = 1, @@ -1194,6 +1208,28 @@ static struct clk_rcg2 vsync_clk_src = { }, }; +static const struct freq_tbl ftbl_cdsp_bimc_clk_src[] = { + F(19200000, P_XO, 1, 0, 0), + F(133333333, P_GPLL0_OUT_MAIN, 6, 0, 0), + F(266666667, P_GPLL0_OUT_MAIN, 3, 0, 0), + F(320000000, P_GPLL0_OUT_MAIN, 2.5, 0, 0), + { } +}; + +static struct clk_rcg2 cdsp_bimc_clk_src = { + .cmd_rcgr = 0x5e010, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gcc_parent_map_16, + .freq_tbl = ftbl_cdsp_bimc_clk_src, + .clkr.hw.init = &(struct clk_init_data) { + .name = "cdsp_bimc_clk_src", + .parent_names = gcc_parent_names_16, + .num_parents = 4, + .ops = &clk_rcg2_ops, + }, +}; + static struct clk_branch gcc_apss_ahb_clk = { .halt_reg = 0x4601c, .halt_check = BRANCH_HALT_VOTED, @@ -1255,6 +1291,24 @@ static struct clk_branch gcc_bimc_gpu_clk = { }, }; +static struct clk_branch gcc_bimc_cdsp_clk = { + .halt_reg = 0x31030, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x31030, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data) { + .name = "gcc_bimc_cdsp_clk", + .parent_names = (const char *[]) { + "cdsp_bimc_clk_src", + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + static struct clk_branch gcc_bimc_mdss_clk = { .halt_reg = 0x31038, .halt_check = BRANCH_HALT, @@ -1792,6 +1846,24 @@ static struct clk_branch gcc_gfx_tbu_clk = { }, }; +static struct clk_branch gcc_cdsp_tbu_clk = { + .halt_reg = 0x1203c, + .halt_check = BRANCH_VOTED, + .clkr = { + .enable_reg = 0x13020, + .enable_mask = BIT(9), + .hw.init = &(struct clk_init_data) { + .name = "gcc_cdsp_tbu_clk", + .parent_names = (const char *[]) { + "cdsp_bimc_clk_src", + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + static struct clk_branch gcc_gp1_clk = { .halt_reg = 0x8000, .halt_check = BRANCH_HALT, @@ -2304,6 +2376,19 @@ static struct clk_branch gcc_sdcc1_ice_core_clk = { }, }; +static struct clk_branch gcc_cdsp_cfg_ahb_clk = { + .halt_reg = 0x5e004, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x5e004, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data) { + .name = "gcc_cdsp_cfg_ahb_cbcr", + .ops = &clk_branch2_ops, + }, + }, +}; + static struct clk_branch gcc_sdcc2_ahb_clk = { .halt_reg = 0x4301c, .halt_check = BRANCH_HALT, @@ -2548,6 +2633,7 @@ static struct clk_regmap *gcc_qcs404_clocks[] = { [GCC_ESC0_CLK_SRC] = &esc0_clk_src.clkr, [GCC_APSS_AHB_CLK] = &gcc_apss_ahb_clk.clkr, [GCC_BIMC_GFX_CLK] = &gcc_bimc_gfx_clk.clkr, + [GCC_BIMC_CDSP_CLK] = &gcc_bimc_cdsp_clk.clkr, [GCC_BIMC_MDSS_CLK] = &gcc_bimc_mdss_clk.clkr, [GCC_BLSP1_AHB_CLK] = &gcc_blsp1_ahb_clk.clkr, [GCC_BLSP1_QUP0_I2C_APPS_CLK] = &gcc_blsp1_qup0_i2c_apps_clk.clkr, @@ -2605,6 +2691,7 @@ static struct clk_regmap *gcc_qcs404_clocks[] = { [GCC_SDCC1_AHB_CLK] = &gcc_sdcc1_ahb_clk.clkr, [GCC_SDCC1_APPS_CLK] = &gcc_sdcc1_apps_clk.clkr, [GCC_SDCC1_ICE_CORE_CLK] = &gcc_sdcc1_ice_core_clk.clkr, + [GCC_CDSP_CFG_AHB_CLK] = &gcc_cdsp_cfg_ahb_clk.clkr, [GCC_SDCC2_AHB_CLK] = &gcc_sdcc2_ahb_clk.clkr, [GCC_SDCC2_APPS_CLK] = &gcc_sdcc2_apps_clk.clkr, [GCC_SYS_NOC_USB3_CLK] = &gcc_sys_noc_usb3_clk.clkr, @@ -2645,6 +2732,7 @@ static struct clk_regmap *gcc_qcs404_clocks[] = { [GCC_USB3_PHY_AUX_CLK_SRC] = &usb3_phy_aux_clk_src.clkr, [GCC_USB_HS_SYSTEM_CLK_SRC] = &usb_hs_system_clk_src.clkr, [GCC_VSYNC_CLK_SRC] = &vsync_clk_src.clkr, + [GCC_CDSP_BIMC_CLK_SRC] = &cdsp_bimc_clk_src.clkr, [GCC_USB_HS_INACTIVITY_TIMERS_CLK] = &gcc_usb_hs_inactivity_timers_clk.clkr, [GCC_BIMC_GPU_CLK] = &gcc_bimc_gpu_clk.clkr, @@ -2653,6 +2741,7 @@ static struct clk_regmap *gcc_qcs404_clocks[] = { [GCC_GFX_TBU_CLK] = &gcc_gfx_tbu_clk.clkr, [GCC_SMMU_CFG_CLK] = &gcc_smmu_cfg_clk.clkr, [GCC_APSS_TCU_CLK] = &gcc_apss_tcu_clk.clkr, + [GCC_CDSP_TBU_CLK] = &gcc_cdsp_tbu_clk.clkr, [GCC_CRYPTO_AHB_CLK] = &gcc_crypto_ahb_clk.clkr, [GCC_CRYPTO_AXI_CLK] = &gcc_crypto_axi_clk.clkr, [GCC_CRYPTO_CLK] = &gcc_crypto_clk.clkr, @@ -2664,6 +2753,7 @@ static struct clk_regmap *gcc_qcs404_clocks[] = { static const struct qcom_reset_map gcc_qcs404_resets[] = { [GCC_GENI_IR_BCR] = { 0x0F000 }, + [GCC_CDSP_RESTART] = { 0x18000 }, [GCC_USB_HS_BCR] = { 0x41000 }, [GCC_USB2_HS_PHY_ONLY_BCR] = { 0x41034 }, [GCC_QUSB2_PHY_BCR] = { 0x4103c }, diff --git a/drivers/clk/qcom/turingcc-qcs404.c b/drivers/clk/qcom/turingcc-qcs404.c new file mode 100644 index 000000000000..aa859e6ec9bd --- /dev/null +++ b/drivers/clk/qcom/turingcc-qcs404.c @@ -0,0 +1,170 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2019, Linaro Ltd. + */ + +#include <linux/bitops.h> +#include <linux/err.h> +#include <linux/platform_device.h> +#include <linux/module.h> +#include <linux/of_address.h> +#include <linux/pm_clock.h> +#include <linux/pm_runtime.h> +#include <linux/regmap.h> + +#include <dt-bindings/clock/qcom,turingcc-qcs404.h> + +#include "clk-regmap.h" +#include "clk-branch.h" +#include "common.h" +#include "reset.h" + +static struct clk_branch turing_wrapper_aon_cbcr = { + .halt_reg = 0x5098, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x5098, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data) { + .name = "turing_wrapper_aon_clk", + .ops = &clk_branch2_aon_ops, + }, + }, +}; + +static struct clk_branch turing_q6ss_ahbm_aon_cbcr = { + .halt_reg = 0x9000, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x9000, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data) { + .name = "turing_q6ss_ahbm_aon_cbcr", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch turing_q6ss_q6_axim_clk = { + .halt_reg = 0xb000, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0xb000, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data) { + .name = "turing_q6ss_q6_axim_clk", + .ops = &clk_branch2_aon_ops, + }, + }, +}; + +static struct clk_branch turing_q6ss_ahbs_aon_cbcr = { + .halt_reg = 0x10000, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x10000, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data) { + .name = "turing_q6ss_ahbs_aon_clk", + .ops = &clk_branch2_aon_ops, + }, + }, +}; + +static struct clk_branch turing_wrapper_qos_ahbs_aon_cbcr = { + .halt_reg = 0x11014, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x11014, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data) { + .name = "turing_wrapper_qos_ahbs_aon_clk", + .ops = &clk_branch2_aon_ops, + }, + }, +}; + +static struct clk_regmap *turingcc_clocks[] = { + [TURING_WRAPPER_AON_CLK] = &turing_wrapper_aon_cbcr.clkr, + [TURING_Q6SS_AHBM_AON_CLK] = &turing_q6ss_ahbm_aon_cbcr.clkr, + [TURING_Q6SS_Q6_AXIM_CLK] = &turing_q6ss_q6_axim_clk.clkr, + [TURING_Q6SS_AHBS_AON_CLK] = &turing_q6ss_ahbs_aon_cbcr.clkr, + [TURING_WRAPPER_QOS_AHBS_AON_CLK] = &turing_wrapper_qos_ahbs_aon_cbcr.clkr, +}; + +static const struct regmap_config turingcc_regmap_config = { + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + .max_register = 0x30000, + .fast_io = true, +}; + +static const struct qcom_cc_desc turingcc_desc = { + .config = &turingcc_regmap_config, + .clks = turingcc_clocks, + .num_clks = ARRAY_SIZE(turingcc_clocks), +}; + +static int turingcc_probe(struct platform_device *pdev) +{ + int ret; + + pm_runtime_enable(&pdev->dev); + ret = pm_clk_create(&pdev->dev); + if (ret) + goto disable_pm_runtime; + + ret = pm_clk_add(&pdev->dev, NULL); + if (ret < 0) { + dev_err(&pdev->dev, "failed to acquire iface clock\n"); + goto destroy_pm_clk; + } + + ret = qcom_cc_probe(pdev, &turingcc_desc); + if (ret < 0) + goto destroy_pm_clk; + + return 0; + +destroy_pm_clk: + pm_clk_destroy(&pdev->dev); + +disable_pm_runtime: + pm_runtime_disable(&pdev->dev); + + return ret; +} + +static int turingcc_remove(struct platform_device *pdev) +{ + pm_clk_destroy(&pdev->dev); + pm_runtime_disable(&pdev->dev); + + return 0; +} + +static const struct dev_pm_ops turingcc_pm_ops = { + SET_RUNTIME_PM_OPS(pm_clk_suspend, pm_clk_resume, NULL) +}; + +static const struct of_device_id turingcc_match_table[] = { + { .compatible = "qcom,qcs404-turingcc" }, + { } +}; +MODULE_DEVICE_TABLE(of, turingcc_match_table); + +static struct platform_driver turingcc_driver = { + .probe = turingcc_probe, + .remove = turingcc_remove, + .driver = { + .name = "qcs404-turingcc", + .of_match_table = turingcc_match_table, + .pm = &turingcc_pm_ops, + }, +}; + +module_platform_driver(turingcc_driver); + +MODULE_DESCRIPTION("Qualcomm QCS404 Turing Clock Controller"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/clk/renesas/r7s9210-cpg-mssr.c b/drivers/clk/renesas/r7s9210-cpg-mssr.c index 57c49fe88295..cf65d4e0e116 100644 --- a/drivers/clk/renesas/r7s9210-cpg-mssr.c +++ b/drivers/clk/renesas/r7s9210-cpg-mssr.c @@ -11,6 +11,7 @@ #include <linux/clk.h> #include <linux/clk-provider.h> +#include <linux/io.h> #include <dt-bindings/clock/r7s9210-cpg-mssr.h> #include "renesas-cpg-mssr.h" @@ -119,7 +120,7 @@ static void __init r7s9210_update_clk_table(struct clk *extal_clk, if (clk_get_rate(extal_clk) > 12000000) cpg_mode = 1; - frqcr = clk_readl(base + CPG_FRQCR) & 0xFFF; + frqcr = readl(base + CPG_FRQCR) & 0xFFF; if (frqcr == 0x012) index = 0; else if (frqcr == 0x112) diff --git a/drivers/clk/renesas/r8a774a1-cpg-mssr.c b/drivers/clk/renesas/r8a774a1-cpg-mssr.c index 4d92b27a6153..76ed7d1bae36 100644 --- a/drivers/clk/renesas/r8a774a1-cpg-mssr.c +++ b/drivers/clk/renesas/r8a774a1-cpg-mssr.c @@ -71,8 +71,8 @@ static const struct cpg_core_clk r8a774a1_core_clks[] __initconst = { DEF_GEN3_OSC(".r", CLK_RINT, CLK_EXTAL, 32), /* Core Clock Outputs */ - DEF_BASE("z", R8A774A1_CLK_Z, CLK_TYPE_GEN3_Z, CLK_PLL0), - DEF_BASE("z2", R8A774A1_CLK_Z2, CLK_TYPE_GEN3_Z2, CLK_PLL2), + DEF_GEN3_Z("z", R8A774A1_CLK_Z, CLK_TYPE_GEN3_Z, CLK_PLL0, 2, 8), + DEF_GEN3_Z("z2", R8A774A1_CLK_Z2, CLK_TYPE_GEN3_Z, CLK_PLL2, 2, 0), DEF_FIXED("ztr", R8A774A1_CLK_ZTR, CLK_PLL1_DIV2, 6, 1), DEF_FIXED("ztrd2", R8A774A1_CLK_ZTRD2, CLK_PLL1_DIV2, 12, 1), DEF_FIXED("zt", R8A774A1_CLK_ZT, CLK_PLL1_DIV2, 4, 1), @@ -123,8 +123,8 @@ static const struct mssr_mod_clk r8a774a1_mod_clks[] __initconst = { DEF_MOD("msiof2", 209, R8A774A1_CLK_MSO), DEF_MOD("msiof1", 210, R8A774A1_CLK_MSO), DEF_MOD("msiof0", 211, R8A774A1_CLK_MSO), - DEF_MOD("sys-dmac2", 217, R8A774A1_CLK_S0D3), - DEF_MOD("sys-dmac1", 218, R8A774A1_CLK_S0D3), + DEF_MOD("sys-dmac2", 217, R8A774A1_CLK_S3D1), + DEF_MOD("sys-dmac1", 218, R8A774A1_CLK_S3D1), DEF_MOD("sys-dmac0", 219, R8A774A1_CLK_S0D3), DEF_MOD("cmt3", 300, R8A774A1_CLK_R), DEF_MOD("cmt2", 301, R8A774A1_CLK_R), @@ -143,8 +143,8 @@ static const struct mssr_mod_clk r8a774a1_mod_clks[] __initconst = { DEF_MOD("rwdt", 402, R8A774A1_CLK_R), DEF_MOD("intc-ex", 407, R8A774A1_CLK_CP), DEF_MOD("intc-ap", 408, R8A774A1_CLK_S0D3), - DEF_MOD("audmac1", 501, R8A774A1_CLK_S0D3), - DEF_MOD("audmac0", 502, R8A774A1_CLK_S0D3), + DEF_MOD("audmac1", 501, R8A774A1_CLK_S1D2), + DEF_MOD("audmac0", 502, R8A774A1_CLK_S1D2), DEF_MOD("hscif4", 516, R8A774A1_CLK_S3D1), DEF_MOD("hscif3", 517, R8A774A1_CLK_S3D1), DEF_MOD("hscif2", 518, R8A774A1_CLK_S3D1), @@ -165,9 +165,9 @@ static const struct mssr_mod_clk r8a774a1_mod_clks[] __initconst = { DEF_MOD("vspd0", 623, R8A774A1_CLK_S0D2), DEF_MOD("vspb", 626, R8A774A1_CLK_S0D1), DEF_MOD("vspi0", 631, R8A774A1_CLK_S0D1), - DEF_MOD("ehci1", 702, R8A774A1_CLK_S3D4), - DEF_MOD("ehci0", 703, R8A774A1_CLK_S3D4), - DEF_MOD("hsusb", 704, R8A774A1_CLK_S3D4), + DEF_MOD("ehci1", 702, R8A774A1_CLK_S3D2), + DEF_MOD("ehci0", 703, R8A774A1_CLK_S3D2), + DEF_MOD("hsusb", 704, R8A774A1_CLK_S3D2), DEF_MOD("csi20", 714, R8A774A1_CLK_CSI0), DEF_MOD("csi40", 716, R8A774A1_CLK_CSI0), DEF_MOD("du2", 722, R8A774A1_CLK_S2D1), diff --git a/drivers/clk/renesas/r8a774c0-cpg-mssr.c b/drivers/clk/renesas/r8a774c0-cpg-mssr.c index 34e274f2a273..f91e7a484753 100644 --- a/drivers/clk/renesas/r8a774c0-cpg-mssr.c +++ b/drivers/clk/renesas/r8a774c0-cpg-mssr.c @@ -81,6 +81,7 @@ static const struct cpg_core_clk r8a774c0_core_clks[] __initconst = { /* Core Clock Outputs */ DEF_FIXED("za2", R8A774C0_CLK_ZA2, CLK_PLL0D24, 1, 1), DEF_FIXED("za8", R8A774C0_CLK_ZA8, CLK_PLL0D8, 1, 1), + DEF_GEN3_Z("z2", R8A774C0_CLK_Z2, CLK_TYPE_GEN3_Z, CLK_PLL0, 4, 8), DEF_FIXED("ztr", R8A774C0_CLK_ZTR, CLK_PLL1, 6, 1), DEF_FIXED("zt", R8A774C0_CLK_ZT, CLK_PLL1, 4, 1), DEF_FIXED("zx", R8A774C0_CLK_ZX, CLK_PLL1, 3, 1), @@ -157,7 +158,7 @@ static const struct mssr_mod_clk r8a774c0_mod_clks[] __initconst = { DEF_MOD("intc-ex", 407, R8A774C0_CLK_CP), DEF_MOD("intc-ap", 408, R8A774C0_CLK_S0D3), - DEF_MOD("audmac0", 502, R8A774C0_CLK_S3D4), + DEF_MOD("audmac0", 502, R8A774C0_CLK_S1D2), DEF_MOD("hscif4", 516, R8A774C0_CLK_S3D1C), DEF_MOD("hscif3", 517, R8A774C0_CLK_S3D1C), DEF_MOD("hscif2", 518, R8A774C0_CLK_S3D1C), @@ -177,8 +178,8 @@ static const struct mssr_mod_clk r8a774c0_mod_clks[] __initconst = { DEF_MOD("vspb", 626, R8A774C0_CLK_S0D1), DEF_MOD("vspi0", 631, R8A774C0_CLK_S0D1), - DEF_MOD("ehci0", 703, R8A774C0_CLK_S3D4), - DEF_MOD("hsusb", 704, R8A774C0_CLK_S3D4), + DEF_MOD("ehci0", 703, R8A774C0_CLK_S3D2), + DEF_MOD("hsusb", 704, R8A774C0_CLK_S3D2), DEF_MOD("csi40", 716, R8A774C0_CLK_CSI0), DEF_MOD("du1", 723, R8A774C0_CLK_S1D1), DEF_MOD("du0", 724, R8A774C0_CLK_S1D1), diff --git a/drivers/clk/renesas/r8a7795-cpg-mssr.c b/drivers/clk/renesas/r8a7795-cpg-mssr.c index 86842c9fd314..9e9a6f2c31e8 100644 --- a/drivers/clk/renesas/r8a7795-cpg-mssr.c +++ b/drivers/clk/renesas/r8a7795-cpg-mssr.c @@ -3,6 +3,7 @@ * r8a7795 Clock Pulse Generator / Module Standby and Software Reset * * Copyright (C) 2015 Glider bvba + * Copyright (C) 2018-2019 Renesas Electronics Corp. * * Based on clk-rcar-gen3.c * @@ -73,8 +74,8 @@ static struct cpg_core_clk r8a7795_core_clks[] __initdata = { DEF_GEN3_OSC(".r", CLK_RINT, CLK_EXTAL, 32), /* Core Clock Outputs */ - DEF_BASE("z", R8A7795_CLK_Z, CLK_TYPE_GEN3_Z, CLK_PLL0), - DEF_BASE("z2", R8A7795_CLK_Z2, CLK_TYPE_GEN3_Z2, CLK_PLL2), + DEF_GEN3_Z("z", R8A7795_CLK_Z, CLK_TYPE_GEN3_Z, CLK_PLL0, 2, 8), + DEF_GEN3_Z("z2", R8A7795_CLK_Z2, CLK_TYPE_GEN3_Z, CLK_PLL2, 2, 0), DEF_FIXED("ztr", R8A7795_CLK_ZTR, CLK_PLL1_DIV2, 6, 1), DEF_FIXED("ztrd2", R8A7795_CLK_ZTRD2, CLK_PLL1_DIV2, 12, 1), DEF_FIXED("zt", R8A7795_CLK_ZT, CLK_PLL1_DIV2, 4, 1), @@ -129,8 +130,8 @@ static struct mssr_mod_clk r8a7795_mod_clks[] __initdata = { DEF_MOD("msiof2", 209, R8A7795_CLK_MSO), DEF_MOD("msiof1", 210, R8A7795_CLK_MSO), DEF_MOD("msiof0", 211, R8A7795_CLK_MSO), - DEF_MOD("sys-dmac2", 217, R8A7795_CLK_S0D3), - DEF_MOD("sys-dmac1", 218, R8A7795_CLK_S0D3), + DEF_MOD("sys-dmac2", 217, R8A7795_CLK_S3D1), + DEF_MOD("sys-dmac1", 218, R8A7795_CLK_S3D1), DEF_MOD("sys-dmac0", 219, R8A7795_CLK_S0D3), DEF_MOD("sceg-pub", 229, R8A7795_CLK_CR), DEF_MOD("cmt3", 300, R8A7795_CLK_R), @@ -153,16 +154,16 @@ static struct mssr_mod_clk r8a7795_mod_clks[] __initdata = { DEF_MOD("rwdt", 402, R8A7795_CLK_R), DEF_MOD("intc-ex", 407, R8A7795_CLK_CP), DEF_MOD("intc-ap", 408, R8A7795_CLK_S0D3), - DEF_MOD("audmac1", 501, R8A7795_CLK_S0D3), - DEF_MOD("audmac0", 502, R8A7795_CLK_S0D3), - DEF_MOD("drif7", 508, R8A7795_CLK_S3D2), - DEF_MOD("drif6", 509, R8A7795_CLK_S3D2), - DEF_MOD("drif5", 510, R8A7795_CLK_S3D2), - DEF_MOD("drif4", 511, R8A7795_CLK_S3D2), - DEF_MOD("drif3", 512, R8A7795_CLK_S3D2), - DEF_MOD("drif2", 513, R8A7795_CLK_S3D2), - DEF_MOD("drif1", 514, R8A7795_CLK_S3D2), - DEF_MOD("drif0", 515, R8A7795_CLK_S3D2), + DEF_MOD("audmac1", 501, R8A7795_CLK_S1D2), + DEF_MOD("audmac0", 502, R8A7795_CLK_S1D2), + DEF_MOD("drif31", 508, R8A7795_CLK_S3D2), + DEF_MOD("drif30", 509, R8A7795_CLK_S3D2), + DEF_MOD("drif21", 510, R8A7795_CLK_S3D2), + DEF_MOD("drif20", 511, R8A7795_CLK_S3D2), + DEF_MOD("drif11", 512, R8A7795_CLK_S3D2), + DEF_MOD("drif10", 513, R8A7795_CLK_S3D2), + DEF_MOD("drif01", 514, R8A7795_CLK_S3D2), + DEF_MOD("drif00", 515, R8A7795_CLK_S3D2), DEF_MOD("hscif4", 516, R8A7795_CLK_S3D1), DEF_MOD("hscif3", 517, R8A7795_CLK_S3D1), DEF_MOD("hscif2", 518, R8A7795_CLK_S3D1), @@ -194,12 +195,12 @@ static struct mssr_mod_clk r8a7795_mod_clks[] __initdata = { DEF_MOD("vspi2", 629, R8A7795_CLK_S2D1), /* ES1.x */ DEF_MOD("vspi1", 630, R8A7795_CLK_S0D1), DEF_MOD("vspi0", 631, R8A7795_CLK_S0D1), - DEF_MOD("ehci3", 700, R8A7795_CLK_S3D4), - DEF_MOD("ehci2", 701, R8A7795_CLK_S3D4), - DEF_MOD("ehci1", 702, R8A7795_CLK_S3D4), - DEF_MOD("ehci0", 703, R8A7795_CLK_S3D4), - DEF_MOD("hsusb", 704, R8A7795_CLK_S3D4), - DEF_MOD("hsusb3", 705, R8A7795_CLK_S3D4), + DEF_MOD("ehci3", 700, R8A7795_CLK_S3D2), + DEF_MOD("ehci2", 701, R8A7795_CLK_S3D2), + DEF_MOD("ehci1", 702, R8A7795_CLK_S3D2), + DEF_MOD("ehci0", 703, R8A7795_CLK_S3D2), + DEF_MOD("hsusb", 704, R8A7795_CLK_S3D2), + DEF_MOD("hsusb3", 705, R8A7795_CLK_S3D2), DEF_MOD("csi21", 713, R8A7795_CLK_CSI0), /* ES1.x */ DEF_MOD("csi20", 714, R8A7795_CLK_CSI0), DEF_MOD("csi41", 715, R8A7795_CLK_CSI0), diff --git a/drivers/clk/renesas/r8a7796-cpg-mssr.c b/drivers/clk/renesas/r8a7796-cpg-mssr.c index 12c455859f2c..d8e9af5d9ae9 100644 --- a/drivers/clk/renesas/r8a7796-cpg-mssr.c +++ b/drivers/clk/renesas/r8a7796-cpg-mssr.c @@ -3,6 +3,7 @@ * r8a7796 Clock Pulse Generator / Module Standby and Software Reset * * Copyright (C) 2016 Glider bvba + * Copyright (C) 2018 Renesas Electronics Corp. * * Based on r8a7795-cpg-mssr.c * @@ -73,8 +74,8 @@ static const struct cpg_core_clk r8a7796_core_clks[] __initconst = { DEF_GEN3_OSC(".r", CLK_RINT, CLK_EXTAL, 32), /* Core Clock Outputs */ - DEF_BASE("z", R8A7796_CLK_Z, CLK_TYPE_GEN3_Z, CLK_PLL0), - DEF_BASE("z2", R8A7796_CLK_Z2, CLK_TYPE_GEN3_Z2, CLK_PLL2), + DEF_GEN3_Z("z", R8A7796_CLK_Z, CLK_TYPE_GEN3_Z, CLK_PLL0, 2, 8), + DEF_GEN3_Z("z2", R8A7796_CLK_Z2, CLK_TYPE_GEN3_Z, CLK_PLL2, 2, 0), DEF_FIXED("ztr", R8A7796_CLK_ZTR, CLK_PLL1_DIV2, 6, 1), DEF_FIXED("ztrd2", R8A7796_CLK_ZTRD2, CLK_PLL1_DIV2, 12, 1), DEF_FIXED("zt", R8A7796_CLK_ZT, CLK_PLL1_DIV2, 4, 1), @@ -126,8 +127,8 @@ static const struct mssr_mod_clk r8a7796_mod_clks[] __initconst = { DEF_MOD("msiof2", 209, R8A7796_CLK_MSO), DEF_MOD("msiof1", 210, R8A7796_CLK_MSO), DEF_MOD("msiof0", 211, R8A7796_CLK_MSO), - DEF_MOD("sys-dmac2", 217, R8A7796_CLK_S0D3), - DEF_MOD("sys-dmac1", 218, R8A7796_CLK_S0D3), + DEF_MOD("sys-dmac2", 217, R8A7796_CLK_S3D1), + DEF_MOD("sys-dmac1", 218, R8A7796_CLK_S3D1), DEF_MOD("sys-dmac0", 219, R8A7796_CLK_S0D3), DEF_MOD("cmt3", 300, R8A7796_CLK_R), DEF_MOD("cmt2", 301, R8A7796_CLK_R), @@ -146,16 +147,16 @@ static const struct mssr_mod_clk r8a7796_mod_clks[] __initconst = { DEF_MOD("rwdt", 402, R8A7796_CLK_R), DEF_MOD("intc-ex", 407, R8A7796_CLK_CP), DEF_MOD("intc-ap", 408, R8A7796_CLK_S0D3), - DEF_MOD("audmac1", 501, R8A7796_CLK_S0D3), - DEF_MOD("audmac0", 502, R8A7796_CLK_S0D3), - DEF_MOD("drif7", 508, R8A7796_CLK_S3D2), - DEF_MOD("drif6", 509, R8A7796_CLK_S3D2), - DEF_MOD("drif5", 510, R8A7796_CLK_S3D2), - DEF_MOD("drif4", 511, R8A7796_CLK_S3D2), - DEF_MOD("drif3", 512, R8A7796_CLK_S3D2), - DEF_MOD("drif2", 513, R8A7796_CLK_S3D2), - DEF_MOD("drif1", 514, R8A7796_CLK_S3D2), - DEF_MOD("drif0", 515, R8A7796_CLK_S3D2), + DEF_MOD("audmac1", 501, R8A7796_CLK_S1D2), + DEF_MOD("audmac0", 502, R8A7796_CLK_S1D2), + DEF_MOD("drif31", 508, R8A7796_CLK_S3D2), + DEF_MOD("drif30", 509, R8A7796_CLK_S3D2), + DEF_MOD("drif21", 510, R8A7796_CLK_S3D2), + DEF_MOD("drif20", 511, R8A7796_CLK_S3D2), + DEF_MOD("drif11", 512, R8A7796_CLK_S3D2), + DEF_MOD("drif10", 513, R8A7796_CLK_S3D2), + DEF_MOD("drif01", 514, R8A7796_CLK_S3D2), + DEF_MOD("drif00", 515, R8A7796_CLK_S3D2), DEF_MOD("hscif4", 516, R8A7796_CLK_S3D1), DEF_MOD("hscif3", 517, R8A7796_CLK_S3D1), DEF_MOD("hscif2", 518, R8A7796_CLK_S3D1), @@ -176,9 +177,9 @@ static const struct mssr_mod_clk r8a7796_mod_clks[] __initconst = { DEF_MOD("vspd0", 623, R8A7796_CLK_S0D2), DEF_MOD("vspb", 626, R8A7796_CLK_S0D1), DEF_MOD("vspi0", 631, R8A7796_CLK_S0D1), - DEF_MOD("ehci1", 702, R8A7796_CLK_S3D4), - DEF_MOD("ehci0", 703, R8A7796_CLK_S3D4), - DEF_MOD("hsusb", 704, R8A7796_CLK_S3D4), + DEF_MOD("ehci1", 702, R8A7796_CLK_S3D2), + DEF_MOD("ehci0", 703, R8A7796_CLK_S3D2), + DEF_MOD("hsusb", 704, R8A7796_CLK_S3D2), DEF_MOD("csi20", 714, R8A7796_CLK_CSI0), DEF_MOD("csi40", 716, R8A7796_CLK_CSI0), DEF_MOD("du2", 722, R8A7796_CLK_S2D1), diff --git a/drivers/clk/renesas/r8a77965-cpg-mssr.c b/drivers/clk/renesas/r8a77965-cpg-mssr.c index eb1cca58a1e1..8f87e314d949 100644 --- a/drivers/clk/renesas/r8a77965-cpg-mssr.c +++ b/drivers/clk/renesas/r8a77965-cpg-mssr.c @@ -3,6 +3,7 @@ * r8a77965 Clock Pulse Generator / Module Standby and Software Reset * * Copyright (C) 2018 Jacopo Mondi <jacopo+renesas@jmondi.org> + * Copyright (C) 2019 Renesas Electronics Corp. * * Based on r8a7795-cpg-mssr.c * @@ -71,7 +72,7 @@ static const struct cpg_core_clk r8a77965_core_clks[] __initconst = { DEF_GEN3_OSC(".r", CLK_RINT, CLK_EXTAL, 32), /* Core Clock Outputs */ - DEF_BASE("z", R8A77965_CLK_Z, CLK_TYPE_GEN3_Z, CLK_PLL0), + DEF_GEN3_Z("z", R8A77965_CLK_Z, CLK_TYPE_GEN3_Z, CLK_PLL0, 2, 8), DEF_FIXED("ztr", R8A77965_CLK_ZTR, CLK_PLL1_DIV2, 6, 1), DEF_FIXED("ztrd2", R8A77965_CLK_ZTRD2, CLK_PLL1_DIV2, 12, 1), DEF_FIXED("zt", R8A77965_CLK_ZT, CLK_PLL1_DIV2, 4, 1), @@ -123,8 +124,8 @@ static const struct mssr_mod_clk r8a77965_mod_clks[] __initconst = { DEF_MOD("msiof2", 209, R8A77965_CLK_MSO), DEF_MOD("msiof1", 210, R8A77965_CLK_MSO), DEF_MOD("msiof0", 211, R8A77965_CLK_MSO), - DEF_MOD("sys-dmac2", 217, R8A77965_CLK_S0D3), - DEF_MOD("sys-dmac1", 218, R8A77965_CLK_S0D3), + DEF_MOD("sys-dmac2", 217, R8A77965_CLK_S3D1), + DEF_MOD("sys-dmac1", 218, R8A77965_CLK_S3D1), DEF_MOD("sys-dmac0", 219, R8A77965_CLK_S0D3), DEF_MOD("cmt3", 300, R8A77965_CLK_R), @@ -146,16 +147,16 @@ static const struct mssr_mod_clk r8a77965_mod_clks[] __initconst = { DEF_MOD("intc-ex", 407, R8A77965_CLK_CP), DEF_MOD("intc-ap", 408, R8A77965_CLK_S0D3), - DEF_MOD("audmac1", 501, R8A77965_CLK_S0D3), - DEF_MOD("audmac0", 502, R8A77965_CLK_S0D3), - DEF_MOD("drif7", 508, R8A77965_CLK_S3D2), - DEF_MOD("drif6", 509, R8A77965_CLK_S3D2), - DEF_MOD("drif5", 510, R8A77965_CLK_S3D2), - DEF_MOD("drif4", 511, R8A77965_CLK_S3D2), - DEF_MOD("drif3", 512, R8A77965_CLK_S3D2), - DEF_MOD("drif2", 513, R8A77965_CLK_S3D2), - DEF_MOD("drif1", 514, R8A77965_CLK_S3D2), - DEF_MOD("drif0", 515, R8A77965_CLK_S3D2), + DEF_MOD("audmac1", 501, R8A77965_CLK_S1D2), + DEF_MOD("audmac0", 502, R8A77965_CLK_S1D2), + DEF_MOD("drif31", 508, R8A77965_CLK_S3D2), + DEF_MOD("drif30", 509, R8A77965_CLK_S3D2), + DEF_MOD("drif21", 510, R8A77965_CLK_S3D2), + DEF_MOD("drif20", 511, R8A77965_CLK_S3D2), + DEF_MOD("drif11", 512, R8A77965_CLK_S3D2), + DEF_MOD("drif10", 513, R8A77965_CLK_S3D2), + DEF_MOD("drif01", 514, R8A77965_CLK_S3D2), + DEF_MOD("drif00", 515, R8A77965_CLK_S3D2), DEF_MOD("hscif4", 516, R8A77965_CLK_S3D1), DEF_MOD("hscif3", 517, R8A77965_CLK_S3D1), DEF_MOD("hscif2", 518, R8A77965_CLK_S3D1), @@ -175,9 +176,9 @@ static const struct mssr_mod_clk r8a77965_mod_clks[] __initconst = { DEF_MOD("vspb", 626, R8A77965_CLK_S0D1), DEF_MOD("vspi0", 631, R8A77965_CLK_S0D1), - DEF_MOD("ehci1", 702, R8A77965_CLK_S3D4), - DEF_MOD("ehci0", 703, R8A77965_CLK_S3D4), - DEF_MOD("hsusb", 704, R8A77965_CLK_S3D4), + DEF_MOD("ehci1", 702, R8A77965_CLK_S3D2), + DEF_MOD("ehci0", 703, R8A77965_CLK_S3D2), + DEF_MOD("hsusb", 704, R8A77965_CLK_S3D2), DEF_MOD("csi20", 714, R8A77965_CLK_CSI0), DEF_MOD("csi40", 716, R8A77965_CLK_CSI0), DEF_MOD("du3", 721, R8A77965_CLK_S2D1), diff --git a/drivers/clk/renesas/r8a77980-cpg-mssr.c b/drivers/clk/renesas/r8a77980-cpg-mssr.c index f9e07fcc0d96..7227f675e61f 100644 --- a/drivers/clk/renesas/r8a77980-cpg-mssr.c +++ b/drivers/clk/renesas/r8a77980-cpg-mssr.c @@ -171,7 +171,7 @@ static const struct mssr_mod_clk r8a77980_mod_clks[] __initconst = { DEF_MOD("gpio1", 911, R8A77980_CLK_CP), DEF_MOD("gpio0", 912, R8A77980_CLK_CP), DEF_MOD("can-fd", 914, R8A77980_CLK_S3D2), - DEF_MOD("rpc-if", 917, R8A77980_CLK_RPC), + DEF_MOD("rpc-if", 917, R8A77980_CLK_RPCD2), DEF_MOD("i2c4", 927, R8A77980_CLK_S0D6), DEF_MOD("i2c3", 928, R8A77980_CLK_S0D6), DEF_MOD("i2c2", 929, R8A77980_CLK_S3D2), diff --git a/drivers/clk/renesas/r8a77990-cpg-mssr.c b/drivers/clk/renesas/r8a77990-cpg-mssr.c index 9a278c75c918..9570404baa58 100644 --- a/drivers/clk/renesas/r8a77990-cpg-mssr.c +++ b/drivers/clk/renesas/r8a77990-cpg-mssr.c @@ -2,7 +2,7 @@ /* * r8a77990 Clock Pulse Generator / Module Standby and Software Reset * - * Copyright (C) 2018 Renesas Electronics Corp. + * Copyright (C) 2018-2019 Renesas Electronics Corp. * * Based on r8a7795-cpg-mssr.c * @@ -81,6 +81,7 @@ static const struct cpg_core_clk r8a77990_core_clks[] __initconst = { /* Core Clock Outputs */ DEF_FIXED("za2", R8A77990_CLK_ZA2, CLK_PLL0D24, 1, 1), DEF_FIXED("za8", R8A77990_CLK_ZA8, CLK_PLL0D8, 1, 1), + DEF_GEN3_Z("z2", R8A77990_CLK_Z2, CLK_TYPE_GEN3_Z, CLK_PLL0, 4, 8), DEF_FIXED("ztr", R8A77990_CLK_ZTR, CLK_PLL1, 6, 1), DEF_FIXED("zt", R8A77990_CLK_ZT, CLK_PLL1, 4, 1), DEF_FIXED("zx", R8A77990_CLK_ZX, CLK_PLL1, 3, 1), @@ -152,15 +153,15 @@ static const struct mssr_mod_clk r8a77990_mod_clks[] __initconst = { DEF_MOD("intc-ex", 407, R8A77990_CLK_CP), DEF_MOD("intc-ap", 408, R8A77990_CLK_S0D3), - DEF_MOD("audmac0", 502, R8A77990_CLK_S3D4), - DEF_MOD("drif7", 508, R8A77990_CLK_S3D2), - DEF_MOD("drif6", 509, R8A77990_CLK_S3D2), - DEF_MOD("drif5", 510, R8A77990_CLK_S3D2), - DEF_MOD("drif4", 511, R8A77990_CLK_S3D2), - DEF_MOD("drif3", 512, R8A77990_CLK_S3D2), - DEF_MOD("drif2", 513, R8A77990_CLK_S3D2), - DEF_MOD("drif1", 514, R8A77990_CLK_S3D2), - DEF_MOD("drif0", 515, R8A77990_CLK_S3D2), + DEF_MOD("audmac0", 502, R8A77990_CLK_S1D2), + DEF_MOD("drif31", 508, R8A77990_CLK_S3D2), + DEF_MOD("drif30", 509, R8A77990_CLK_S3D2), + DEF_MOD("drif21", 510, R8A77990_CLK_S3D2), + DEF_MOD("drif20", 511, R8A77990_CLK_S3D2), + DEF_MOD("drif11", 512, R8A77990_CLK_S3D2), + DEF_MOD("drif10", 513, R8A77990_CLK_S3D2), + DEF_MOD("drif01", 514, R8A77990_CLK_S3D2), + DEF_MOD("drif00", 515, R8A77990_CLK_S3D2), DEF_MOD("hscif4", 516, R8A77990_CLK_S3D1C), DEF_MOD("hscif3", 517, R8A77990_CLK_S3D1C), DEF_MOD("hscif2", 518, R8A77990_CLK_S3D1C), @@ -180,8 +181,8 @@ static const struct mssr_mod_clk r8a77990_mod_clks[] __initconst = { DEF_MOD("vspb", 626, R8A77990_CLK_S0D1), DEF_MOD("vspi0", 631, R8A77990_CLK_S0D1), - DEF_MOD("ehci0", 703, R8A77990_CLK_S3D4), - DEF_MOD("hsusb", 704, R8A77990_CLK_S3D4), + DEF_MOD("ehci0", 703, R8A77990_CLK_S3D2), + DEF_MOD("hsusb", 704, R8A77990_CLK_S3D2), DEF_MOD("csi40", 716, R8A77990_CLK_CSI0), DEF_MOD("du1", 723, R8A77990_CLK_S1D1), DEF_MOD("du0", 724, R8A77990_CLK_S1D1), diff --git a/drivers/clk/renesas/r8a77995-cpg-mssr.c b/drivers/clk/renesas/r8a77995-cpg-mssr.c index eee3874865a9..68707277b17b 100644 --- a/drivers/clk/renesas/r8a77995-cpg-mssr.c +++ b/drivers/clk/renesas/r8a77995-cpg-mssr.c @@ -133,7 +133,7 @@ static const struct mssr_mod_clk r8a77995_mod_clks[] __initconst = { DEF_MOD("rwdt", 402, R8A77995_CLK_R), DEF_MOD("intc-ex", 407, R8A77995_CLK_CP), DEF_MOD("intc-ap", 408, R8A77995_CLK_S1D2), - DEF_MOD("audmac0", 502, R8A77995_CLK_S3D1), + DEF_MOD("audmac0", 502, R8A77995_CLK_S1D2), DEF_MOD("hscif3", 517, R8A77995_CLK_S3D1C), DEF_MOD("hscif0", 520, R8A77995_CLK_S3D1C), DEF_MOD("thermal", 522, R8A77995_CLK_CP), diff --git a/drivers/clk/renesas/r9a06g032-clocks.c b/drivers/clk/renesas/r9a06g032-clocks.c index 658cb11b6f55..97c72477cd54 100644 --- a/drivers/clk/renesas/r9a06g032-clocks.c +++ b/drivers/clk/renesas/r9a06g032-clocks.c @@ -170,6 +170,7 @@ static const struct r9a06g032_clkdesc r9a06g032_clocks[] __initconst = { D_GATE(CLK_P6_PG2, "clk_p6_pg2", DIV_P6_PG, 0x8a3, 0x8a4, 0x8a5, 0, 0xb61, 0, 0), D_GATE(CLK_P6_PG3, "clk_p6_pg3", DIV_P6_PG, 0x8a6, 0x8a7, 0x8a8, 0, 0xb62, 0, 0), D_GATE(CLK_P6_PG4, "clk_p6_pg4", DIV_P6_PG, 0x8a9, 0x8aa, 0x8ab, 0, 0xb63, 0, 0), + D_GATE(CLK_PCI_USB, "clk_pci_usb", CLKOUT_D40, 0xe6, 0, 0, 0, 0, 0, 0), D_GATE(CLK_QSPI0, "clk_qspi0", DIV_QSPI0, 0x2a4, 0x2a5, 0, 0, 0, 0, 0), D_GATE(CLK_QSPI1, "clk_qspi1", DIV_QSPI1, 0x484, 0x485, 0, 0, 0, 0, 0), D_GATE(CLK_RGMII_REF, "clk_rgmii_ref", CLKOUT_D8, 0x340, 0, 0, 0, 0, 0, 0), diff --git a/drivers/clk/renesas/rcar-gen3-cpg.c b/drivers/clk/renesas/rcar-gen3-cpg.c index 9a8071a8114d..d25c8ba00a65 100644 --- a/drivers/clk/renesas/rcar-gen3-cpg.c +++ b/drivers/clk/renesas/rcar-gen3-cpg.c @@ -3,6 +3,7 @@ * R-Car Gen3 Clock Pulse Generator * * Copyright (C) 2015-2018 Glider bvba + * Copyright (C) 2019 Renesas Electronics Corp. * * Based on clk-rcar-gen3.c * @@ -88,14 +89,13 @@ static void cpg_simple_notifier_register(struct raw_notifier_head *notifiers, #define CPG_FRQCRB 0x00000004 #define CPG_FRQCRB_KICK BIT(31) #define CPG_FRQCRC 0x000000e0 -#define CPG_FRQCRC_ZFC_MASK GENMASK(12, 8) -#define CPG_FRQCRC_Z2FC_MASK GENMASK(4, 0) struct cpg_z_clk { struct clk_hw hw; void __iomem *reg; void __iomem *kick_reg; unsigned long mask; + unsigned int fixed_div; }; #define to_z_clk(_hw) container_of(_hw, struct cpg_z_clk, hw) @@ -110,17 +110,18 @@ static unsigned long cpg_z_clk_recalc_rate(struct clk_hw *hw, val = readl(zclk->reg) & zclk->mask; mult = 32 - (val >> __ffs(zclk->mask)); - /* Factor of 2 is for fixed divider */ - return DIV_ROUND_CLOSEST_ULL((u64)parent_rate * mult, 32 * 2); + return DIV_ROUND_CLOSEST_ULL((u64)parent_rate * mult, + 32 * zclk->fixed_div); } static long cpg_z_clk_round_rate(struct clk_hw *hw, unsigned long rate, unsigned long *parent_rate) { - /* Factor of 2 is for fixed divider */ - unsigned long prate = *parent_rate / 2; + struct cpg_z_clk *zclk = to_z_clk(hw); + unsigned long prate; unsigned int mult; + prate = *parent_rate / zclk->fixed_div; mult = div_u64(rate * 32ULL, prate); mult = clamp(mult, 1U, 32U); @@ -134,8 +135,8 @@ static int cpg_z_clk_set_rate(struct clk_hw *hw, unsigned long rate, unsigned int mult; unsigned int i; - /* Factor of 2 is for fixed divider */ - mult = DIV_ROUND_CLOSEST_ULL(rate * 32ULL * 2, parent_rate); + mult = DIV64_U64_ROUND_CLOSEST(rate * 32ULL * zclk->fixed_div, + parent_rate); mult = clamp(mult, 1U, 32U); if (readl(zclk->kick_reg) & CPG_FRQCRB_KICK) @@ -178,7 +179,8 @@ static const struct clk_ops cpg_z_clk_ops = { static struct clk * __init cpg_z_clk_register(const char *name, const char *parent_name, void __iomem *reg, - unsigned long mask) + unsigned int div, + unsigned int offset) { struct clk_init_data init; struct cpg_z_clk *zclk; @@ -197,7 +199,8 @@ static struct clk * __init cpg_z_clk_register(const char *name, zclk->reg = reg + CPG_FRQCRC; zclk->kick_reg = reg + CPG_FRQCRB; zclk->hw.init = &init; - zclk->mask = mask; + zclk->mask = GENMASK(offset + 4, offset); + zclk->fixed_div = div; /* PLLVCO x 1/div x SYS-CPU divider */ clk = clk_register(NULL, &zclk->hw); if (IS_ERR(clk)) @@ -234,8 +237,6 @@ struct sd_clock { const struct sd_div_table *div_table; struct cpg_simple_notifier csn; unsigned int div_num; - unsigned int div_min; - unsigned int div_max; unsigned int cur_div_idx; }; @@ -312,14 +313,20 @@ static unsigned int cpg_sd_clock_calc_div(struct sd_clock *clock, unsigned long rate, unsigned long parent_rate) { - unsigned int div; - - if (!rate) - rate = 1; - - div = DIV_ROUND_CLOSEST(parent_rate, rate); + unsigned long calc_rate, diff, diff_min = ULONG_MAX; + unsigned int i, best_div = 0; + + for (i = 0; i < clock->div_num; i++) { + calc_rate = DIV_ROUND_CLOSEST(parent_rate, + clock->div_table[i].div); + diff = calc_rate > rate ? calc_rate - rate : rate - calc_rate; + if (diff < diff_min) { + best_div = clock->div_table[i].div; + diff_min = diff; + } + } - return clamp_t(unsigned int, div, clock->div_min, clock->div_max); + return best_div; } static long cpg_sd_clock_round_rate(struct clk_hw *hw, unsigned long rate, @@ -369,27 +376,26 @@ static u32 cpg_quirks __initdata; #define RCKCR_CKSEL BIT(1) /* Manual RCLK parent selection */ #define SD_SKIP_FIRST BIT(2) /* Skip first clock in SD table */ -static struct clk * __init cpg_sd_clk_register(const struct cpg_core_clk *core, - void __iomem *base, const char *parent_name, +static struct clk * __init cpg_sd_clk_register(const char *name, + void __iomem *base, unsigned int offset, const char *parent_name, struct raw_notifier_head *notifiers) { struct clk_init_data init; struct sd_clock *clock; struct clk *clk; - unsigned int i; u32 val; clock = kzalloc(sizeof(*clock), GFP_KERNEL); if (!clock) return ERR_PTR(-ENOMEM); - init.name = core->name; + init.name = name; init.ops = &cpg_sd_clock_ops; init.flags = CLK_SET_RATE_PARENT; init.parent_names = &parent_name; init.num_parents = 1; - clock->csn.reg = base + core->offset; + clock->csn.reg = base + offset; clock->hw.init = &init; clock->div_table = cpg_sd_div_table; clock->div_num = ARRAY_SIZE(cpg_sd_div_table); @@ -403,13 +409,6 @@ static struct clk * __init cpg_sd_clk_register(const struct cpg_core_clk *core, val |= CPG_SD_STP_MASK | (clock->div_table[0].val & CPG_SD_FC_MASK); writel(val, clock->csn.reg); - clock->div_max = clock->div_table[0].div; - clock->div_min = clock->div_max; - for (i = 1; i < clock->div_num; i++) { - clock->div_max = max(clock->div_max, clock->div_table[i].div); - clock->div_min = min(clock->div_min, clock->div_table[i].div); - } - clk = clk_register(NULL, &clock->hw); if (IS_ERR(clk)) goto free_clock; @@ -606,8 +605,8 @@ struct clk * __init rcar_gen3_cpg_clk_register(struct device *dev, break; case CLK_TYPE_GEN3_SD: - return cpg_sd_clk_register(core, base, __clk_get_name(parent), - notifiers); + return cpg_sd_clk_register(core->name, base, core->offset, + __clk_get_name(parent), notifiers); case CLK_TYPE_GEN3_R: if (cpg_quirks & RCKCR_CKSEL) { @@ -658,11 +657,7 @@ struct clk * __init rcar_gen3_cpg_clk_register(struct device *dev, case CLK_TYPE_GEN3_Z: return cpg_z_clk_register(core->name, __clk_get_name(parent), - base, CPG_FRQCRC_ZFC_MASK); - - case CLK_TYPE_GEN3_Z2: - return cpg_z_clk_register(core->name, __clk_get_name(parent), - base, CPG_FRQCRC_Z2FC_MASK); + base, core->div, core->offset); case CLK_TYPE_GEN3_OSC: /* diff --git a/drivers/clk/renesas/rcar-gen3-cpg.h b/drivers/clk/renesas/rcar-gen3-cpg.h index eac1b057455a..15700d219a05 100644 --- a/drivers/clk/renesas/rcar-gen3-cpg.h +++ b/drivers/clk/renesas/rcar-gen3-cpg.h @@ -3,6 +3,7 @@ * R-Car Gen3 Clock Pulse Generator * * Copyright (C) 2015-2018 Glider bvba + * Copyright (C) 2018 Renesas Electronics Corp. * */ @@ -20,7 +21,6 @@ enum rcar_gen3_clk_types { CLK_TYPE_GEN3_R, CLK_TYPE_GEN3_MDSEL, /* Select parent/divider using mode pin */ CLK_TYPE_GEN3_Z, - CLK_TYPE_GEN3_Z2, CLK_TYPE_GEN3_OSC, /* OSC EXTAL predivider and fixed divider */ CLK_TYPE_GEN3_RCKSEL, /* Select parent/divider using RCKCR.CKSEL */ CLK_TYPE_GEN3_RPCSRC, @@ -51,6 +51,9 @@ enum rcar_gen3_clk_types { DEF_BASE(_name, _id, CLK_TYPE_GEN3_RCKSEL, \ (_parent0) << 16 | (_parent1), .div = (_div0) << 16 | (_div1)) +#define DEF_GEN3_Z(_name, _id, _type, _parent, _div, _offset) \ + DEF_BASE(_name, _id, _type, _parent, .div = _div, .offset = _offset) + struct rcar_gen3_cpg_pll_config { u8 extal_div; u8 pll1_mult; diff --git a/drivers/clk/sunxi-ng/ccu_nkmp.c b/drivers/clk/sunxi-ng/ccu_nkmp.c index 9b49adb20d07..cbcdf664f336 100644 --- a/drivers/clk/sunxi-ng/ccu_nkmp.c +++ b/drivers/clk/sunxi-ng/ccu_nkmp.c @@ -167,7 +167,7 @@ static int ccu_nkmp_set_rate(struct clk_hw *hw, unsigned long rate, unsigned long parent_rate) { struct ccu_nkmp *nkmp = hw_to_ccu_nkmp(hw); - u32 n_mask, k_mask, m_mask, p_mask; + u32 n_mask = 0, k_mask = 0, m_mask = 0, p_mask = 0; struct _ccu_nkmp _nkmp; unsigned long flags; u32 reg; @@ -186,10 +186,24 @@ static int ccu_nkmp_set_rate(struct clk_hw *hw, unsigned long rate, ccu_nkmp_find_best(parent_rate, rate, &_nkmp); - n_mask = GENMASK(nkmp->n.width + nkmp->n.shift - 1, nkmp->n.shift); - k_mask = GENMASK(nkmp->k.width + nkmp->k.shift - 1, nkmp->k.shift); - m_mask = GENMASK(nkmp->m.width + nkmp->m.shift - 1, nkmp->m.shift); - p_mask = GENMASK(nkmp->p.width + nkmp->p.shift - 1, nkmp->p.shift); + /* + * If width is 0, GENMASK() macro may not generate expected mask (0) + * as it falls under undefined behaviour by C standard due to shifts + * which are equal or greater than width of left operand. This can + * be easily avoided by explicitly checking if width is 0. + */ + if (nkmp->n.width) + n_mask = GENMASK(nkmp->n.width + nkmp->n.shift - 1, + nkmp->n.shift); + if (nkmp->k.width) + k_mask = GENMASK(nkmp->k.width + nkmp->k.shift - 1, + nkmp->k.shift); + if (nkmp->m.width) + m_mask = GENMASK(nkmp->m.width + nkmp->m.shift - 1, + nkmp->m.shift); + if (nkmp->p.width) + p_mask = GENMASK(nkmp->p.width + nkmp->p.shift - 1, + nkmp->p.shift); spin_lock_irqsave(nkmp->common.lock, flags); diff --git a/drivers/clk/x86/clk-pmc-atom.c b/drivers/clk/x86/clk-pmc-atom.c index d977193842df..19174835693b 100644 --- a/drivers/clk/x86/clk-pmc-atom.c +++ b/drivers/clk/x86/clk-pmc-atom.c @@ -165,7 +165,7 @@ static const struct clk_ops plt_clk_ops = { }; static struct clk_plt *plt_clk_register(struct platform_device *pdev, int id, - void __iomem *base, + const struct pmc_clk_data *pmc_data, const char **parent_names, int num_parents) { @@ -184,9 +184,17 @@ static struct clk_plt *plt_clk_register(struct platform_device *pdev, int id, init.num_parents = num_parents; pclk->hw.init = &init; - pclk->reg = base + PMC_CLK_CTL_OFFSET + id * PMC_CLK_CTL_SIZE; + pclk->reg = pmc_data->base + PMC_CLK_CTL_OFFSET + id * PMC_CLK_CTL_SIZE; spin_lock_init(&pclk->lock); + /* + * On some systems, the pmc_plt_clocks already enabled by the + * firmware are being marked as critical to avoid them being + * gated by the clock framework. + */ + if (pmc_data->critical && plt_clk_is_enabled(&pclk->hw)) + init.flags |= CLK_IS_CRITICAL; + ret = devm_clk_hw_register(&pdev->dev, &pclk->hw); if (ret) { pclk = ERR_PTR(ret); @@ -332,7 +340,7 @@ static int plt_clk_probe(struct platform_device *pdev) return PTR_ERR(parent_names); for (i = 0; i < PMC_CLK_NUM; i++) { - data->clks[i] = plt_clk_register(pdev, i, pmc_data->base, + data->clks[i] = plt_clk_register(pdev, i, pmc_data, parent_names, data->nparents); if (IS_ERR(data->clks[i])) { err = PTR_ERR(data->clks[i]); |