diff options
Diffstat (limited to 'drivers/clk')
61 files changed, 10717 insertions, 237 deletions
diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig index c3e3a02f7f1f..d2d3871e64c9 100644 --- a/drivers/clk/Kconfig +++ b/drivers/clk/Kconfig @@ -116,6 +116,12 @@ config COMMON_CLK_CDCE925 Given a target output frequency, the driver will set the PLL and divider to best approximate the desired output. +config COMMON_CLK_CS2000_CP + tristate "Clock driver for CS2000 Fractional-N Clock Synthesizer & Clock Multiplier" + depends on I2C + help + If you say yes here you get support for the CS2000 clock multiplier. + config COMMON_CLK_S2MPS11 tristate "Clock driver for S2MPS1X/S5M8767 MFD" depends on MFD_SEC_CORE diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile index 820714c72d36..0e0fdac2a599 100644 --- a/drivers/clk/Makefile +++ b/drivers/clk/Makefile @@ -21,6 +21,7 @@ obj-$(CONFIG_MACH_ASM9260) += clk-asm9260.o obj-$(CONFIG_COMMON_CLK_AXI_CLKGEN) += clk-axi-clkgen.o obj-$(CONFIG_ARCH_AXXIA) += clk-axm5516.o obj-$(CONFIG_COMMON_CLK_CDCE706) += clk-cdce706.o +obj-$(CONFIG_COMMON_CLK_CS2000_CP) += clk-cs2000-cp.o obj-$(CONFIG_ARCH_CLPS711X) += clk-clps711x.o obj-$(CONFIG_ARCH_EFM32) += clk-efm32gg.o obj-$(CONFIG_ARCH_HIGHBANK) += clk-highbank.o @@ -42,6 +43,7 @@ obj-$(CONFIG_COMMON_CLK_SI514) += clk-si514.o obj-$(CONFIG_COMMON_CLK_SI570) += clk-si570.o obj-$(CONFIG_COMMON_CLK_CDCE925) += clk-cdce925.o obj-$(CONFIG_ARCH_STM32) += clk-stm32f4.o +obj-$(CONFIG_ARCH_TANGOX) += clk-tango4.o obj-$(CONFIG_CLK_TWL6040) += clk-twl6040.o obj-$(CONFIG_ARCH_U300) += clk-u300.o obj-$(CONFIG_ARCH_VT8500) += clk-vt8500.o @@ -69,6 +71,7 @@ obj-$(CONFIG_COMMON_CLK_QCOM) += qcom/ obj-$(CONFIG_ARCH_ROCKCHIP) += rockchip/ obj-$(CONFIG_COMMON_CLK_SAMSUNG) += samsung/ obj-$(CONFIG_ARCH_SHMOBILE_MULTI) += shmobile/ +obj-$(CONFIG_ARCH_RENESAS) += shmobile/ obj-$(CONFIG_ARCH_SIRF) += sirf/ obj-$(CONFIG_ARCH_SOCFPGA) += socfpga/ obj-$(CONFIG_PLAT_SPEAR) += spear/ diff --git a/drivers/clk/at91/clk-slow.c b/drivers/clk/at91/clk-slow.c index d0d5076a9b94..6f99a530ead6 100644 --- a/drivers/clk/at91/clk-slow.c +++ b/drivers/clk/at91/clk-slow.c @@ -10,7 +10,6 @@ * */ -#include <linux/clk.h> #include <linux/clk-provider.h> #include <linux/clkdev.h> #include <linux/slab.h> @@ -72,8 +71,6 @@ struct clk_sam9x5_slow { #define to_clk_sam9x5_slow(hw) container_of(hw, struct clk_sam9x5_slow, hw) -static struct clk *slow_clk; - static int clk_slow_osc_prepare(struct clk_hw *hw) { struct clk_slow_osc *osc = to_clk_slow_osc(hw); @@ -360,8 +357,6 @@ at91_clk_register_sam9x5_slow(void __iomem *sckcr, clk = clk_register(NULL, &slowck->hw); if (IS_ERR(clk)) kfree(slowck); - else - slow_clk = clk; return clk; } @@ -433,8 +428,6 @@ at91_clk_register_sam9260_slow(struct at91_pmc *pmc, clk = clk_register(NULL, &slowck->hw); if (IS_ERR(clk)) kfree(slowck); - else - slow_clk = clk; return clk; } @@ -462,25 +455,3 @@ void __init of_at91sam9260_clk_slow_setup(struct device_node *np, of_clk_add_provider(np, of_clk_src_simple_get, clk); } - -/* - * FIXME: All slow clk users are not properly claiming it (get + prepare + - * enable) before using it. - * If all users properly claiming this clock decide that they don't need it - * anymore (or are removed), it is disabled while faulty users are still - * requiring it, and the system hangs. - * Prevent this clock from being disabled until all users are properly - * requesting it. - * Once this is done we should remove this function and the slow_clk variable. - */ -static int __init of_at91_clk_slow_retain(void) -{ - if (!slow_clk) - return 0; - - __clk_get(slow_clk); - clk_prepare_enable(slow_clk); - - return 0; -} -arch_initcall(of_at91_clk_slow_retain); diff --git a/drivers/clk/bcm/Kconfig b/drivers/clk/bcm/Kconfig index 85260fb96b36..f2878459199a 100644 --- a/drivers/clk/bcm/Kconfig +++ b/drivers/clk/bcm/Kconfig @@ -1,3 +1,13 @@ +config CLK_BCM_63XX + bool "Broadcom BCM63xx clock support" + depends on ARCH_BCM_63XX || COMPILE_TEST + depends on COMMON_CLK + select COMMON_CLK_IPROC + default ARCH_BCM_63XX + help + Enable common clock framework support for Broadcom BCM63xx DSL SoCs + based on the ARM architecture + config CLK_BCM_KONA bool "Broadcom Kona CCU clock support" depends on ARCH_BCM_MOBILE || COMPILE_TEST diff --git a/drivers/clk/bcm/Makefile b/drivers/clk/bcm/Makefile index 3fc95060d875..247c26750d8b 100644 --- a/drivers/clk/bcm/Makefile +++ b/drivers/clk/bcm/Makefile @@ -1,3 +1,4 @@ +obj-$(CONFIG_CLK_BCM_63XX) += clk-bcm63xx.o obj-$(CONFIG_CLK_BCM_KONA) += clk-kona.o obj-$(CONFIG_CLK_BCM_KONA) += clk-kona-setup.o obj-$(CONFIG_CLK_BCM_KONA) += clk-bcm281xx.o diff --git a/drivers/clk/bcm/clk-bcm63xx.c b/drivers/clk/bcm/clk-bcm63xx.c new file mode 100644 index 000000000000..fbc17ae5ff2b --- /dev/null +++ b/drivers/clk/bcm/clk-bcm63xx.c @@ -0,0 +1,22 @@ +/* + * Copyright (C) 2015 Broadcom Corporation + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation version 2. + * + * This program is distributed "as is" WITHOUT ANY WARRANTY of any + * kind, whether express or implied; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ +#include <linux/init.h> +#include <linux/clk-provider.h> +#include <linux/of.h> +#include "clk-iproc.h" + +static void __init bcm63138_armpll_init(struct device_node *node) +{ + iproc_armpll_setup(node); +} +CLK_OF_DECLARE(bcm63138_armpll, "brcm,bcm63138-armpll", bcm63138_armpll_init); diff --git a/drivers/clk/clk-cs2000-cp.c b/drivers/clk/clk-cs2000-cp.c new file mode 100644 index 000000000000..7379de8dc894 --- /dev/null +++ b/drivers/clk/clk-cs2000-cp.c @@ -0,0 +1,510 @@ +/* + * CS2000 -- CIRRUS LOGIC Fractional-N Clock Synthesizer & Clock Multiplier + * + * Copyright (C) 2015 Renesas Electronics Corporation + * Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#include <linux/clk-provider.h> +#include <linux/delay.h> +#include <linux/clk.h> +#include <linux/i2c.h> +#include <linux/of_device.h> +#include <linux/module.h> + +#define CH_MAX 4 +#define RATIO_REG_SIZE 4 + +#define DEVICE_ID 0x1 +#define DEVICE_CTRL 0x2 +#define DEVICE_CFG1 0x3 +#define DEVICE_CFG2 0x4 +#define GLOBAL_CFG 0x5 +#define Ratio_Add(x, nth) (6 + (x * 4) + (nth)) +#define Ratio_Val(x, nth) ((x >> (24 - (8 * nth))) & 0xFF) +#define Val_Ratio(x, nth) ((x & 0xFF) << (24 - (8 * nth))) +#define FUNC_CFG1 0x16 +#define FUNC_CFG2 0x17 + +/* DEVICE_ID */ +#define REVISION_MASK (0x7) +#define REVISION_B2_B3 (0x4) +#define REVISION_C1 (0x6) + +/* DEVICE_CTRL */ +#define PLL_UNLOCK (1 << 7) + +/* DEVICE_CFG1 */ +#define RSEL(x) (((x) & 0x3) << 3) +#define RSEL_MASK RSEL(0x3) +#define ENDEV1 (0x1) + +/* GLOBAL_CFG */ +#define ENDEV2 (0x1) + +#define CH_SIZE_ERR(ch) ((ch < 0) || (ch >= CH_MAX)) +#define hw_to_priv(_hw) container_of(_hw, struct cs2000_priv, hw) +#define priv_to_client(priv) (priv->client) +#define priv_to_dev(priv) (&(priv_to_client(priv)->dev)) + +#define CLK_IN 0 +#define REF_CLK 1 +#define CLK_MAX 2 + +struct cs2000_priv { + struct clk_hw hw; + struct i2c_client *client; + struct clk *clk_in; + struct clk *ref_clk; + struct clk *clk_out; +}; + +static const struct of_device_id cs2000_of_match[] = { + { .compatible = "cirrus,cs2000-cp", }, + {}, +}; +MODULE_DEVICE_TABLE(of, cs2000_of_match); + +static const struct i2c_device_id cs2000_id[] = { + { "cs2000-cp", }, + {} +}; +MODULE_DEVICE_TABLE(i2c, cs2000_id); + +#define cs2000_read(priv, addr) \ + i2c_smbus_read_byte_data(priv_to_client(priv), addr) +#define cs2000_write(priv, addr, val) \ + i2c_smbus_write_byte_data(priv_to_client(priv), addr, val) + +static int cs2000_bset(struct cs2000_priv *priv, u8 addr, u8 mask, u8 val) +{ + s32 data; + + data = cs2000_read(priv, addr); + if (data < 0) + return data; + + data &= ~mask; + data |= (val & mask); + + return cs2000_write(priv, addr, data); +} + +static int cs2000_enable_dev_config(struct cs2000_priv *priv, bool enable) +{ + int ret; + + ret = cs2000_bset(priv, DEVICE_CFG1, ENDEV1, + enable ? ENDEV1 : 0); + if (ret < 0) + return ret; + + ret = cs2000_bset(priv, GLOBAL_CFG, ENDEV2, + enable ? ENDEV2 : 0); + if (ret < 0) + return ret; + + return 0; +} + +static int cs2000_clk_in_bound_rate(struct cs2000_priv *priv, + u32 rate_in) +{ + u32 val; + + if (rate_in >= 32000000 && rate_in < 56000000) + val = 0x0; + else if (rate_in >= 16000000 && rate_in < 28000000) + val = 0x1; + else if (rate_in >= 8000000 && rate_in < 14000000) + val = 0x2; + else + return -EINVAL; + + return cs2000_bset(priv, FUNC_CFG1, 0x3 << 3, val << 3); +} + +static int cs2000_wait_pll_lock(struct cs2000_priv *priv) +{ + struct device *dev = priv_to_dev(priv); + s32 val; + unsigned int i; + + for (i = 0; i < 256; i++) { + val = cs2000_read(priv, DEVICE_CTRL); + if (val < 0) + return val; + if (!(val & PLL_UNLOCK)) + return 0; + udelay(1); + } + + dev_err(dev, "pll lock failed\n"); + + return -ETIMEDOUT; +} + +static int cs2000_clk_out_enable(struct cs2000_priv *priv, bool enable) +{ + /* enable both AUX_OUT, CLK_OUT */ + return cs2000_write(priv, DEVICE_CTRL, enable ? 0 : 0x3); +} + +static u32 cs2000_rate_to_ratio(u32 rate_in, u32 rate_out) +{ + u64 ratio; + + /* + * ratio = rate_out / rate_in * 2^20 + * + * To avoid over flow, rate_out is u64. + * The result should be u32. + */ + ratio = (u64)rate_out << 20; + do_div(ratio, rate_in); + + return ratio; +} + +static unsigned long cs2000_ratio_to_rate(u32 ratio, u32 rate_in) +{ + u64 rate_out; + + /* + * ratio = rate_out / rate_in * 2^20 + * + * To avoid over flow, rate_out is u64. + * The result should be u32 or unsigned long. + */ + + rate_out = (u64)ratio * rate_in; + return rate_out >> 20; +} + +static int cs2000_ratio_set(struct cs2000_priv *priv, + int ch, u32 rate_in, u32 rate_out) +{ + u32 val; + unsigned int i; + int ret; + + if (CH_SIZE_ERR(ch)) + return -EINVAL; + + val = cs2000_rate_to_ratio(rate_in, rate_out); + for (i = 0; i < RATIO_REG_SIZE; i++) { + ret = cs2000_write(priv, + Ratio_Add(ch, i), + Ratio_Val(val, i)); + if (ret < 0) + return ret; + } + + return 0; +} + +static u32 cs2000_ratio_get(struct cs2000_priv *priv, int ch) +{ + s32 tmp; + u32 val; + unsigned int i; + + val = 0; + for (i = 0; i < RATIO_REG_SIZE; i++) { + tmp = cs2000_read(priv, Ratio_Add(ch, i)); + if (tmp < 0) + return 0; + + val |= Val_Ratio(tmp, i); + } + + return val; +} + +static int cs2000_ratio_select(struct cs2000_priv *priv, int ch) +{ + int ret; + + if (CH_SIZE_ERR(ch)) + return -EINVAL; + + /* + * FIXME + * + * this driver supports static ratio mode only at this point. + */ + ret = cs2000_bset(priv, DEVICE_CFG1, RSEL_MASK, RSEL(ch)); + if (ret < 0) + return ret; + + ret = cs2000_write(priv, DEVICE_CFG2, 0x0); + if (ret < 0) + return ret; + + return 0; +} + +static unsigned long cs2000_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + struct cs2000_priv *priv = hw_to_priv(hw); + int ch = 0; /* it uses ch0 only at this point */ + u32 ratio; + + ratio = cs2000_ratio_get(priv, ch); + + return cs2000_ratio_to_rate(ratio, parent_rate); +} + +static long cs2000_round_rate(struct clk_hw *hw, unsigned long rate, + unsigned long *parent_rate) +{ + u32 ratio; + + ratio = cs2000_rate_to_ratio(*parent_rate, rate); + + return cs2000_ratio_to_rate(ratio, *parent_rate); +} + +static int __cs2000_set_rate(struct cs2000_priv *priv, int ch, + unsigned long rate, unsigned long parent_rate) + +{ + int ret; + + ret = cs2000_clk_in_bound_rate(priv, parent_rate); + if (ret < 0) + return ret; + + ret = cs2000_ratio_set(priv, ch, parent_rate, rate); + if (ret < 0) + return ret; + + ret = cs2000_ratio_select(priv, ch); + if (ret < 0) + return ret; + + return 0; +} + +static int cs2000_set_rate(struct clk_hw *hw, + unsigned long rate, unsigned long parent_rate) +{ + struct cs2000_priv *priv = hw_to_priv(hw); + int ch = 0; /* it uses ch0 only at this point */ + + return __cs2000_set_rate(priv, ch, rate, parent_rate); +} + +static int cs2000_enable(struct clk_hw *hw) +{ + struct cs2000_priv *priv = hw_to_priv(hw); + int ret; + + ret = cs2000_enable_dev_config(priv, true); + if (ret < 0) + return ret; + + ret = cs2000_clk_out_enable(priv, true); + if (ret < 0) + return ret; + + ret = cs2000_wait_pll_lock(priv); + if (ret < 0) + return ret; + + return ret; +} + +static void cs2000_disable(struct clk_hw *hw) +{ + struct cs2000_priv *priv = hw_to_priv(hw); + + cs2000_enable_dev_config(priv, false); + + cs2000_clk_out_enable(priv, false); +} + +static u8 cs2000_get_parent(struct clk_hw *hw) +{ + /* always return REF_CLK */ + return REF_CLK; +} + +static const struct clk_ops cs2000_ops = { + .get_parent = cs2000_get_parent, + .recalc_rate = cs2000_recalc_rate, + .round_rate = cs2000_round_rate, + .set_rate = cs2000_set_rate, + .prepare = cs2000_enable, + .unprepare = cs2000_disable, +}; + +static int cs2000_clk_get(struct cs2000_priv *priv) +{ + struct i2c_client *client = priv_to_client(priv); + struct device *dev = &client->dev; + struct clk *clk_in, *ref_clk; + + clk_in = devm_clk_get(dev, "clk_in"); + /* not yet provided */ + if (IS_ERR(clk_in)) + return -EPROBE_DEFER; + + ref_clk = devm_clk_get(dev, "ref_clk"); + /* not yet provided */ + if (IS_ERR(ref_clk)) + return -EPROBE_DEFER; + + priv->clk_in = clk_in; + priv->ref_clk = ref_clk; + + return 0; +} + +static int cs2000_clk_register(struct cs2000_priv *priv) +{ + struct device *dev = priv_to_dev(priv); + struct device_node *np = dev->of_node; + struct clk_init_data init; + const char *name = np->name; + struct clk *clk; + static const char *parent_names[CLK_MAX]; + int ch = 0; /* it uses ch0 only at this point */ + int rate; + int ret; + + of_property_read_string(np, "clock-output-names", &name); + + /* + * set default rate as 1/1. + * otherwise .set_rate which setup ratio + * is never called if user requests 1/1 rate + */ + rate = clk_get_rate(priv->ref_clk); + ret = __cs2000_set_rate(priv, ch, rate, rate); + if (ret < 0) + return ret; + + parent_names[CLK_IN] = __clk_get_name(priv->clk_in); + parent_names[REF_CLK] = __clk_get_name(priv->ref_clk); + + init.name = name; + init.ops = &cs2000_ops; + init.flags = CLK_SET_RATE_GATE; + init.parent_names = parent_names; + init.num_parents = ARRAY_SIZE(parent_names); + + priv->hw.init = &init; + + clk = clk_register(dev, &priv->hw); + if (IS_ERR(clk)) + return PTR_ERR(clk); + + ret = of_clk_add_provider(np, of_clk_src_simple_get, clk); + if (ret < 0) { + clk_unregister(clk); + return ret; + } + + priv->clk_out = clk; + + return 0; +} + +static int cs2000_version_print(struct cs2000_priv *priv) +{ + struct i2c_client *client = priv_to_client(priv); + struct device *dev = &client->dev; + s32 val; + const char *revision; + + val = cs2000_read(priv, DEVICE_ID); + if (val < 0) + return val; + + /* CS2000 should be 0x0 */ + if (val >> 3) + return -EIO; + + switch (val & REVISION_MASK) { + case REVISION_B2_B3: + revision = "B2 / B3"; + break; + case REVISION_C1: + revision = "C1"; + break; + default: + return -EIO; + } + + dev_info(dev, "revision - %s\n", revision); + + return 0; +} + +static int cs2000_remove(struct i2c_client *client) +{ + struct cs2000_priv *priv = i2c_get_clientdata(client); + struct device *dev = &client->dev; + struct device_node *np = dev->of_node; + + of_clk_del_provider(np); + + clk_unregister(priv->clk_out); + + return 0; +} + +static int cs2000_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct cs2000_priv *priv; + struct device *dev = &client->dev; + int ret; + + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + priv->client = client; + i2c_set_clientdata(client, priv); + + ret = cs2000_clk_get(priv); + if (ret < 0) + return ret; + + ret = cs2000_clk_register(priv); + if (ret < 0) + return ret; + + ret = cs2000_version_print(priv); + if (ret < 0) + goto probe_err; + + return 0; + +probe_err: + cs2000_remove(client); + + return ret; +} + +static struct i2c_driver cs2000_driver = { + .driver = { + .name = "cs2000-cp", + .of_match_table = cs2000_of_match, + }, + .probe = cs2000_probe, + .remove = cs2000_remove, + .id_table = cs2000_id, +}; + +module_i2c_driver(cs2000_driver); + +MODULE_DESCRIPTION("CS2000-CP driver"); +MODULE_AUTHOR("Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/clk/clk-divider.c b/drivers/clk/clk-divider.c index 3ace102a2a0a..ded3ff4b91b9 100644 --- a/drivers/clk/clk-divider.c +++ b/drivers/clk/clk-divider.c @@ -32,13 +32,14 @@ #define div_mask(width) ((1 << (width)) - 1) -static unsigned int _get_table_maxdiv(const struct clk_div_table *table) +static unsigned int _get_table_maxdiv(const struct clk_div_table *table, + u8 width) { - unsigned int maxdiv = 0; + unsigned int maxdiv = 0, mask = div_mask(width); const struct clk_div_table *clkt; for (clkt = table; clkt->div; clkt++) - if (clkt->div > maxdiv) + if (clkt->div > maxdiv && clkt->val <= mask) maxdiv = clkt->div; return maxdiv; } @@ -62,7 +63,7 @@ static unsigned int _get_maxdiv(const struct clk_div_table *table, u8 width, if (flags & CLK_DIVIDER_POWER_OF_TWO) return 1 << div_mask(width); if (table) - return _get_table_maxdiv(table); + return _get_table_maxdiv(table, width); return div_mask(width) + 1; } diff --git a/drivers/clk/clk-mux.c b/drivers/clk/clk-mux.c index 7129c86a79db..5ed03c8a8df9 100644 --- a/drivers/clk/clk-mux.c +++ b/drivers/clk/clk-mux.c @@ -71,10 +71,9 @@ static int clk_mux_set_parent(struct clk_hw *hw, u8 index) u32 val; unsigned long flags = 0; - if (mux->table) + if (mux->table) { index = mux->table[index]; - - else { + } else { if (mux->flags & CLK_MUX_INDEX_BIT) index = 1 << index; diff --git a/drivers/clk/clk-si5351.c b/drivers/clk/clk-si5351.c index e346b223199d..850316ac8831 100644 --- a/drivers/clk/clk-si5351.c +++ b/drivers/clk/clk-si5351.c @@ -1091,6 +1091,13 @@ static int si5351_clkout_set_rate(struct clk_hw *hw, unsigned long rate, si5351_set_bits(hwdata->drvdata, SI5351_CLK0_CTRL + hwdata->num, SI5351_CLK_POWERDOWN, 0); + /* + * Do a pll soft reset on both plls, needed in some cases to get + * all outputs running. + */ + si5351_reg_write(hwdata->drvdata, SI5351_PLL_RESET, + SI5351_PLL_RESET_A | SI5351_PLL_RESET_B); + dev_dbg(&hwdata->drvdata->client->dev, "%s - %s: rdiv = %u, parent_rate = %lu, rate = %lu\n", __func__, clk_hw_get_name(hw), (1 << rdiv), diff --git a/drivers/clk/clk-tango4.c b/drivers/clk/clk-tango4.c new file mode 100644 index 000000000000..004ab7dfcfe3 --- /dev/null +++ b/drivers/clk/clk-tango4.c @@ -0,0 +1,61 @@ +#include <linux/kernel.h> +#include <linux/clk-provider.h> +#include <linux/of_address.h> +#include <linux/init.h> +#include <linux/io.h> + +static struct clk *out[2]; +static struct clk_onecell_data clk_data = { out, 2 }; + +#define SYSCLK_CTRL 0x20 +#define CPUCLK_CTRL 0x24 +#define LEGACY_DIV 0x3c + +#define PLL_N(val) (((val) >> 0) & 0x7f) +#define PLL_K(val) (((val) >> 13) & 0x7) +#define PLL_M(val) (((val) >> 16) & 0x7) +#define DIV_INDEX(val) (((val) >> 8) & 0xf) + +static void __init make_pll(int idx, const char *parent, void __iomem *base) +{ + char name[8]; + u32 val, mul, div; + + sprintf(name, "pll%d", idx); + val = readl_relaxed(base + idx*8); + mul = PLL_N(val) + 1; + div = (PLL_M(val) + 1) << PLL_K(val); + clk_register_fixed_factor(NULL, name, parent, 0, mul, div); +} + +static int __init get_div(void __iomem *base) +{ + u8 sysclk_tab[16] = { 2, 4, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4 }; + int idx = DIV_INDEX(readl_relaxed(base + LEGACY_DIV)); + + return sysclk_tab[idx]; +} + +static void __init tango4_clkgen_setup(struct device_node *np) +{ + int div, ret; + void __iomem *base = of_iomap(np, 0); + const char *parent = of_clk_get_parent_name(np, 0); + + if (!base) + panic("%s: invalid address\n", np->full_name); + + make_pll(0, parent, base); + make_pll(1, parent, base); + + out[0] = clk_register_divider(NULL, "cpuclk", "pll0", 0, + base + CPUCLK_CTRL, 8, 8, CLK_DIVIDER_ONE_BASED, NULL); + + div = readl_relaxed(base + SYSCLK_CTRL) & BIT(23) ? get_div(base) : 4; + out[1] = clk_register_fixed_factor(NULL, "sysclk", "pll1", 0, 1, div); + + ret = of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data); + if (IS_ERR(out[0]) || IS_ERR(out[1]) || ret < 0) + panic("%s: clk registration failed\n", np->full_name); +} +CLK_OF_DECLARE(tango4_clkgen, "sigma,tango4-clkgen", tango4_clkgen_setup); diff --git a/drivers/clk/clk-xgene.c b/drivers/clk/clk-xgene.c index 27c0da29eca3..10224b01b97c 100644 --- a/drivers/clk/clk-xgene.c +++ b/drivers/clk/clk-xgene.c @@ -351,7 +351,8 @@ static int xgene_clk_set_rate(struct clk_hw *hw, unsigned long rate, /* Set new divider */ data = xgene_clk_read(pclk->param.divider_reg + pclk->param.reg_divider_offset); - data &= ~((1 << pclk->param.reg_divider_width) - 1); + data &= ~((1 << pclk->param.reg_divider_width) - 1) + << pclk->param.reg_divider_shift; data |= divider; xgene_clk_write(data, pclk->param.divider_reg + pclk->param.reg_divider_offset); diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index f13c3f4228d4..9352a13395c8 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -1944,7 +1944,7 @@ bool clk_is_match(const struct clk *p, const struct clk *q) if (p == q) return true; - /* true if clk->core pointers match. Avoid derefing garbage */ + /* true if clk->core pointers match. Avoid dereferencing garbage */ if (!IS_ERR_OR_NULL(p) && !IS_ERR_OR_NULL(q)) if (p->core == q->core) return true; @@ -2482,7 +2482,7 @@ struct clk *__clk_create_clk(struct clk_hw *hw, const char *dev_id, struct clk *clk; /* This is to allow this function to be chained to others */ - if (!hw || IS_ERR(hw)) + if (IS_ERR_OR_NULL(hw)) return (struct clk *) hw; clk = kzalloc(sizeof(*clk), GFP_KERNEL); @@ -2806,10 +2806,9 @@ void __clk_put(struct clk *clk) * re-enter into the clk framework by calling any top-level clk APIs; * this will cause a nested prepare_lock mutex. * - * In all notification cases cases (pre, post and abort rate change) the - * original clock rate is passed to the callback via struct - * clk_notifier_data.old_rate and the new frequency is passed via struct - * clk_notifier_data.new_rate. + * In all notification cases (pre, post and abort rate change) the original + * clock rate is passed to the callback via struct clk_notifier_data.old_rate + * and the new frequency is passed via struct clk_notifier_data.new_rate. * * clk_notifier_register() must be called from non-atomic context. * Returns -EINVAL if called with null arguments, -ENOMEM upon @@ -3062,9 +3061,6 @@ const char *of_clk_get_parent_name(struct device_node *np, int index) int count; struct clk *clk; - if (index < 0) - return NULL; - rc = of_parse_phandle_with_args(np, "clocks", "#clock-cells", index, &clkspec); if (rc) @@ -3083,6 +3079,9 @@ const char *of_clk_get_parent_name(struct device_node *np, int index) } count++; } + /* We went off the end of 'clock-indices' without finding it */ + if (prop && !vp) + return NULL; if (of_property_read_string_index(clkspec.np, "clock-output-names", index, diff --git a/drivers/clk/imx/clk-imx25.c b/drivers/clk/imx/clk-imx25.c index c4c141cab444..23686f756b5e 100644 --- a/drivers/clk/imx/clk-imx25.c +++ b/drivers/clk/imx/clk-imx25.c @@ -96,13 +96,11 @@ static struct clk ** const uart_clks[] __initconst = { NULL }; -static int __init __mx25_clocks_init(unsigned long osc_rate, - void __iomem *ccm_base) +static int __init __mx25_clocks_init(void __iomem *ccm_base) { BUG_ON(!ccm_base); clk[dummy] = imx_clk_fixed("dummy", 0); - clk[osc] = imx_clk_fixed("osc", osc_rate); clk[mpll] = imx_clk_pllv1(IMX_PLLV1_IMX25, "mpll", "osc", ccm(CCM_MPCTL)); clk[upll] = imx_clk_pllv1(IMX_PLLV1_IMX25, "upll", "osc", ccm(CCM_UPCTL)); clk[mpll_cpu_3_4] = imx_clk_fixed_factor("mpll_cpu_3_4", "mpll", 3, 4); @@ -250,22 +248,10 @@ static int __init __mx25_clocks_init(unsigned long osc_rate, static void __init mx25_clocks_init_dt(struct device_node *np) { - struct device_node *refnp; - unsigned long osc_rate = 24000000; void __iomem *ccm; - /* retrieve the freqency of fixed clocks from device tree */ - for_each_compatible_node(refnp, NULL, "fixed-clock") { - u32 rate; - if (of_property_read_u32(refnp, "clock-frequency", &rate)) - continue; - - if (of_device_is_compatible(refnp, "fsl,imx-osc")) - osc_rate = rate; - } - ccm = of_iomap(np, 0); - __mx25_clocks_init(osc_rate, ccm); + __mx25_clocks_init(ccm); clk_data.clks = clk; clk_data.clk_num = ARRAY_SIZE(clk); diff --git a/drivers/clk/imx/clk-imx51-imx53.c b/drivers/clk/imx/clk-imx51-imx53.c index c6770348d2ab..29d4c44ef356 100644 --- a/drivers/clk/imx/clk-imx51-imx53.c +++ b/drivers/clk/imx/clk-imx51-imx53.c @@ -519,10 +519,10 @@ static void __init mx53_clocks_init(struct device_node *np) mx53_ldb_di0_sel, ARRAY_SIZE(mx53_ldb_di0_sel), CLK_SET_RATE_PARENT); clk[IMX5_CLK_LDB_DI0_GATE] = imx_clk_gate2("ldb_di0_gate", "ldb_di0_div", MXC_CCM_CCGR6, 28); clk[IMX5_CLK_LDB_DI1_GATE] = imx_clk_gate2("ldb_di1_gate", "ldb_di1_div", MXC_CCM_CCGR6, 30); - clk[IMX5_CLK_IPU_DI0_SEL] = imx_clk_mux("ipu_di0_sel", MXC_CCM_CSCMR2, 26, 3, - mx53_ipu_di0_sel, ARRAY_SIZE(mx53_ipu_di0_sel)); - clk[IMX5_CLK_IPU_DI1_SEL] = imx_clk_mux("ipu_di1_sel", MXC_CCM_CSCMR2, 29, 3, - mx53_ipu_di1_sel, ARRAY_SIZE(mx53_ipu_di1_sel)); + clk[IMX5_CLK_IPU_DI0_SEL] = imx_clk_mux_flags("ipu_di0_sel", MXC_CCM_CSCMR2, 26, 3, + mx53_ipu_di0_sel, ARRAY_SIZE(mx53_ipu_di0_sel), CLK_SET_RATE_PARENT); + clk[IMX5_CLK_IPU_DI1_SEL] = imx_clk_mux_flags("ipu_di1_sel", MXC_CCM_CSCMR2, 29, 3, + mx53_ipu_di1_sel, ARRAY_SIZE(mx53_ipu_di1_sel), CLK_SET_RATE_PARENT); clk[IMX5_CLK_TVE_EXT_SEL] = imx_clk_mux_flags("tve_ext_sel", MXC_CCM_CSCMR1, 6, 1, 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); diff --git a/drivers/clk/imx/clk-imx6q.c b/drivers/clk/imx/clk-imx6q.c index c1935081d34a..f0efc6feeec2 100644 --- a/drivers/clk/imx/clk-imx6q.c +++ b/drivers/clk/imx/clk-imx6q.c @@ -70,7 +70,8 @@ static const char *cko_sels[] = { "cko1", "cko2", }; static const char *lvds_sels[] = { "dummy", "dummy", "dummy", "dummy", "dummy", "dummy", "pll4_audio", "pll5_video", "pll8_mlb", "enet_ref", - "pcie_ref_125m", "sata_ref_100m", + "pcie_ref_125m", "sata_ref_100m", "usbphy1", "usbphy2", + "dummy", "dummy", "dummy", "dummy", "osc", }; static const char *pll_bypass_src_sels[] = { "osc", "lvds1_in", "lvds2_in", "dummy", }; static const char *pll1_bypass_sels[] = { "pll1", "pll1_bypass_src", }; diff --git a/drivers/clk/imx/clk-imx6ul.c b/drivers/clk/imx/clk-imx6ul.c index 01718d05e952..08692d74b884 100644 --- a/drivers/clk/imx/clk-imx6ul.c +++ b/drivers/clk/imx/clk-imx6ul.c @@ -399,9 +399,7 @@ static void __init imx6ul_clocks_init(struct device_node *ccm_node) /* mask handshake of mmdc */ writel_relaxed(BM_CCM_CCDR_MMDC_CH0_MASK, base + CCDR); - for (i = 0; i < ARRAY_SIZE(clks); i++) - if (IS_ERR(clks[i])) - pr_err("i.MX6UL clk %d: register failed with %ld\n", i, PTR_ERR(clks[i])); + imx_check_clocks(clks, ARRAY_SIZE(clks)); clk_data.clks = clks; clk_data.clk_num = ARRAY_SIZE(clks); diff --git a/drivers/clk/imx/clk-imx7d.c b/drivers/clk/imx/clk-imx7d.c index 448ef321948b..fbb6a8c8653d 100644 --- a/drivers/clk/imx/clk-imx7d.c +++ b/drivers/clk/imx/clk-imx7d.c @@ -833,10 +833,13 @@ static void __init imx7d_clocks_init(struct device_node *ccm_node) clks[IMX7D_GPT_3M_CLK] = imx_clk_fixed_factor("gpt_3m", "osc", 1, 8); - for (i = 0; i < ARRAY_SIZE(clks); i++) - if (IS_ERR(clks[i])) - pr_err("i.MX7D clk %d: register failed with %ld\n", - i, PTR_ERR(clks[i])); + clks[IMX7D_CLK_ARM] = imx_clk_cpu("arm", "arm_a7_root_clk", + clks[IMX7D_ARM_A7_ROOT_CLK], + clks[IMX7D_ARM_A7_ROOT_SRC], + clks[IMX7D_PLL_ARM_MAIN_CLK], + clks[IMX7D_PLL_SYS_MAIN_CLK]); + + imx_check_clocks(clks, ARRAY_SIZE(clks)); clk_data.clks = clks; clk_data.clk_num = ARRAY_SIZE(clks); diff --git a/drivers/clk/imx/clk-pllv3.c b/drivers/clk/imx/clk-pllv3.c index 6addf8f58b97..c05c43d56a94 100644 --- a/drivers/clk/imx/clk-pllv3.c +++ b/drivers/clk/imx/clk-pllv3.c @@ -97,6 +97,16 @@ static void clk_pllv3_unprepare(struct clk_hw *hw) writel_relaxed(val, pll->base); } +static int clk_pllv3_is_prepared(struct clk_hw *hw) +{ + struct clk_pllv3 *pll = to_clk_pllv3(hw); + + if (readl_relaxed(pll->base) & BM_PLL_LOCK) + return 1; + + return 0; +} + static unsigned long clk_pllv3_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) { @@ -139,6 +149,7 @@ static int clk_pllv3_set_rate(struct clk_hw *hw, unsigned long rate, static const struct clk_ops clk_pllv3_ops = { .prepare = clk_pllv3_prepare, .unprepare = clk_pllv3_unprepare, + .is_prepared = clk_pllv3_is_prepared, .recalc_rate = clk_pllv3_recalc_rate, .round_rate = clk_pllv3_round_rate, .set_rate = clk_pllv3_set_rate, @@ -193,6 +204,7 @@ static int clk_pllv3_sys_set_rate(struct clk_hw *hw, unsigned long rate, static const struct clk_ops clk_pllv3_sys_ops = { .prepare = clk_pllv3_prepare, .unprepare = clk_pllv3_unprepare, + .is_prepared = clk_pllv3_is_prepared, .recalc_rate = clk_pllv3_sys_recalc_rate, .round_rate = clk_pllv3_sys_round_rate, .set_rate = clk_pllv3_sys_set_rate, @@ -265,6 +277,7 @@ static int clk_pllv3_av_set_rate(struct clk_hw *hw, unsigned long rate, static const struct clk_ops clk_pllv3_av_ops = { .prepare = clk_pllv3_prepare, .unprepare = clk_pllv3_unprepare, + .is_prepared = clk_pllv3_is_prepared, .recalc_rate = clk_pllv3_av_recalc_rate, .round_rate = clk_pllv3_av_round_rate, .set_rate = clk_pllv3_av_set_rate, @@ -279,6 +292,7 @@ static unsigned long clk_pllv3_enet_recalc_rate(struct clk_hw *hw, static const struct clk_ops clk_pllv3_enet_ops = { .prepare = clk_pllv3_prepare, .unprepare = clk_pllv3_unprepare, + .is_prepared = clk_pllv3_is_prepared, .recalc_rate = clk_pllv3_enet_recalc_rate, }; diff --git a/drivers/clk/qcom/Kconfig b/drivers/clk/qcom/Kconfig index ee4c83aab4f4..b552eceec2be 100644 --- a/drivers/clk/qcom/Kconfig +++ b/drivers/clk/qcom/Kconfig @@ -106,3 +106,20 @@ config MSM_MMCC_8974 Support for the multimedia clock controller on msm8974 devices. Say Y if you want to support multimedia devices such as display, graphics, video encode/decode, camera, etc. + +config MSM_GCC_8996 + tristate "MSM8996 Global Clock Controller" + depends on COMMON_CLK_QCOM + help + Support for the global clock controller on msm8996 devices. + Say Y if you want to use peripheral devices such as UART, SPI, + i2c, USB, UFS, SD/eMMC, PCIe, etc. + +config MSM_MMCC_8996 + tristate "MSM8996 Multimedia Clock Controller" + select MSM_GCC_8996 + depends on COMMON_CLK_QCOM + help + Support for the multimedia clock controller on msm8996 devices. + Say Y if you want to support multimedia devices such as display, + graphics, video encode/decode, camera, etc. diff --git a/drivers/clk/qcom/Makefile b/drivers/clk/qcom/Makefile index fe6252349e55..dc4280b85db1 100644 --- a/drivers/clk/qcom/Makefile +++ b/drivers/clk/qcom/Makefile @@ -2,6 +2,7 @@ obj-$(CONFIG_COMMON_CLK_QCOM) += clk-qcom.o clk-qcom-y += common.o clk-qcom-y += clk-regmap.o +clk-qcom-y += clk-alpha-pll.o clk-qcom-y += clk-pll.o clk-qcom-y += clk-rcg.o clk-qcom-y += clk-rcg2.o @@ -20,5 +21,7 @@ obj-$(CONFIG_MSM_GCC_8916) += gcc-msm8916.o obj-$(CONFIG_MSM_GCC_8960) += gcc-msm8960.o obj-$(CONFIG_MSM_LCC_8960) += lcc-msm8960.o obj-$(CONFIG_MSM_GCC_8974) += gcc-msm8974.o +obj-$(CONFIG_MSM_GCC_8996) += gcc-msm8996.o obj-$(CONFIG_MSM_MMCC_8960) += mmcc-msm8960.o obj-$(CONFIG_MSM_MMCC_8974) += mmcc-msm8974.o +obj-$(CONFIG_MSM_MMCC_8996) += mmcc-msm8996.o diff --git a/drivers/clk/qcom/clk-alpha-pll.c b/drivers/clk/qcom/clk-alpha-pll.c new file mode 100644 index 000000000000..e6a03eaf7a93 --- /dev/null +++ b/drivers/clk/qcom/clk-alpha-pll.c @@ -0,0 +1,355 @@ +/* + * Copyright (c) 2015, The Linux Foundation. All rights reserved. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include <linux/kernel.h> +#include <linux/export.h> +#include <linux/clk-provider.h> +#include <linux/regmap.h> +#include <linux/delay.h> + +#include "clk-alpha-pll.h" + +#define PLL_MODE 0x00 +# define PLL_OUTCTRL BIT(0) +# define PLL_BYPASSNL BIT(1) +# define PLL_RESET_N BIT(2) +# define PLL_LOCK_COUNT_SHIFT 8 +# define PLL_LOCK_COUNT_MASK 0x3f +# define PLL_BIAS_COUNT_SHIFT 14 +# define PLL_BIAS_COUNT_MASK 0x3f +# define PLL_VOTE_FSM_ENA BIT(20) +# define PLL_VOTE_FSM_RESET BIT(21) +# define PLL_ACTIVE_FLAG BIT(30) +# define PLL_LOCK_DET BIT(31) + +#define PLL_L_VAL 0x04 +#define PLL_ALPHA_VAL 0x08 +#define PLL_ALPHA_VAL_U 0x0c + +#define PLL_USER_CTL 0x10 +# define PLL_POST_DIV_SHIFT 8 +# define PLL_POST_DIV_MASK 0xf +# define PLL_ALPHA_EN BIT(24) +# define PLL_VCO_SHIFT 20 +# define PLL_VCO_MASK 0x3 + +#define PLL_USER_CTL_U 0x14 + +#define PLL_CONFIG_CTL 0x18 +#define PLL_TEST_CTL 0x1c +#define PLL_TEST_CTL_U 0x20 +#define PLL_STATUS 0x24 + +/* + * Even though 40 bits are present, use only 32 for ease of calculation. + */ +#define ALPHA_REG_BITWIDTH 40 +#define ALPHA_BITWIDTH 32 + +#define to_clk_alpha_pll(_hw) container_of(to_clk_regmap(_hw), \ + struct clk_alpha_pll, clkr) + +#define to_clk_alpha_pll_postdiv(_hw) container_of(to_clk_regmap(_hw), \ + struct clk_alpha_pll_postdiv, clkr) + +static int wait_for_pll(struct clk_alpha_pll *pll) +{ + u32 val, mask, off; + int count; + int ret; + const char *name = clk_hw_get_name(&pll->clkr.hw); + + off = pll->offset; + ret = regmap_read(pll->clkr.regmap, off + PLL_MODE, &val); + if (ret) + return ret; + + if (val & PLL_VOTE_FSM_ENA) + mask = PLL_ACTIVE_FLAG; + else + mask = PLL_LOCK_DET; + + /* Wait for pll to enable. */ + for (count = 100; count > 0; count--) { + ret = regmap_read(pll->clkr.regmap, off + PLL_MODE, &val); + if (ret) + return ret; + if ((val & mask) == mask) + return 0; + + udelay(1); + } + + WARN(1, "%s didn't enable after voting for it!\n", name); + return -ETIMEDOUT; +} + +static int clk_alpha_pll_enable(struct clk_hw *hw) +{ + int ret; + struct clk_alpha_pll *pll = to_clk_alpha_pll(hw); + u32 val, mask, off; + + off = pll->offset; + + mask = PLL_OUTCTRL | PLL_RESET_N | PLL_BYPASSNL; + ret = regmap_read(pll->clkr.regmap, off + PLL_MODE, &val); + if (ret) + return ret; + + /* If in FSM mode, just vote for it */ + if (val & PLL_VOTE_FSM_ENA) { + ret = clk_enable_regmap(hw); + if (ret) + return ret; + return wait_for_pll(pll); + } + + /* Skip if already enabled */ + if ((val & mask) == mask) + return 0; + + ret = regmap_update_bits(pll->clkr.regmap, off + PLL_MODE, + PLL_BYPASSNL, PLL_BYPASSNL); + if (ret) + return ret; + + /* + * H/W requires a 5us delay between disabling the bypass and + * de-asserting the reset. + */ + mb(); + udelay(5); + + ret = regmap_update_bits(pll->clkr.regmap, off + PLL_MODE, + PLL_RESET_N, PLL_RESET_N); + if (ret) + return ret; + + ret = wait_for_pll(pll); + if (ret) + return ret; + + ret = regmap_update_bits(pll->clkr.regmap, off + PLL_MODE, + PLL_OUTCTRL, PLL_OUTCTRL); + + /* Ensure that the write above goes through before returning. */ + mb(); + return ret; +} + +static void clk_alpha_pll_disable(struct clk_hw *hw) +{ + int ret; + struct clk_alpha_pll *pll = to_clk_alpha_pll(hw); + u32 val, mask, off; + + off = pll->offset; + + ret = regmap_read(pll->clkr.regmap, off + PLL_MODE, &val); + if (ret) + return; + + /* If in FSM mode, just unvote it */ + if (val & PLL_VOTE_FSM_ENA) { + clk_disable_regmap(hw); + return; + } + + mask = PLL_OUTCTRL; + regmap_update_bits(pll->clkr.regmap, off + PLL_MODE, mask, 0); + + /* Delay of 2 output clock ticks required until output is disabled */ + mb(); + udelay(1); + + mask = PLL_RESET_N | PLL_BYPASSNL; + regmap_update_bits(pll->clkr.regmap, off + PLL_MODE, mask, 0); +} + +static unsigned long alpha_pll_calc_rate(u64 prate, u32 l, u32 a) +{ + return (prate * l) + ((prate * a) >> ALPHA_BITWIDTH); +} + +static unsigned long +alpha_pll_round_rate(unsigned long rate, unsigned long prate, u32 *l, u64 *a) +{ + u64 remainder; + u64 quotient; + + quotient = rate; + remainder = do_div(quotient, prate); + *l = quotient; + + if (!remainder) { + *a = 0; + return rate; + } + + /* Upper ALPHA_BITWIDTH bits of Alpha */ + quotient = remainder << ALPHA_BITWIDTH; + remainder = do_div(quotient, prate); + + if (remainder) + quotient++; + + *a = quotient; + return alpha_pll_calc_rate(prate, *l, *a); +} + +static const struct pll_vco * +alpha_pll_find_vco(const struct clk_alpha_pll *pll, unsigned long rate) +{ + const struct pll_vco *v = pll->vco_table; + const struct pll_vco *end = v + pll->num_vco; + + for (; v < end; v++) + if (rate >= v->min_freq && rate <= v->max_freq) + return v; + + return NULL; +} + +static unsigned long +clk_alpha_pll_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) +{ + u32 l, low, high, ctl; + u64 a = 0, prate = parent_rate; + struct clk_alpha_pll *pll = to_clk_alpha_pll(hw); + u32 off = pll->offset; + + regmap_read(pll->clkr.regmap, off + PLL_L_VAL, &l); + + regmap_read(pll->clkr.regmap, off + PLL_USER_CTL, &ctl); + if (ctl & PLL_ALPHA_EN) { + regmap_read(pll->clkr.regmap, off + PLL_ALPHA_VAL, &low); + regmap_read(pll->clkr.regmap, off + PLL_ALPHA_VAL_U, &high); + a = (u64)high << 32 | low; + a >>= ALPHA_REG_BITWIDTH - ALPHA_BITWIDTH; + } + + return alpha_pll_calc_rate(prate, l, a); +} + +static int clk_alpha_pll_set_rate(struct clk_hw *hw, unsigned long rate, + unsigned long prate) +{ + struct clk_alpha_pll *pll = to_clk_alpha_pll(hw); + const struct pll_vco *vco; + u32 l, off = pll->offset; + u64 a; + + rate = alpha_pll_round_rate(rate, prate, &l, &a); + vco = alpha_pll_find_vco(pll, rate); + if (!vco) { + pr_err("alpha pll not in a valid vco range\n"); + return -EINVAL; + } + + a <<= (ALPHA_REG_BITWIDTH - ALPHA_BITWIDTH); + + regmap_write(pll->clkr.regmap, off + PLL_L_VAL, l); + regmap_write(pll->clkr.regmap, off + PLL_ALPHA_VAL, a); + regmap_write(pll->clkr.regmap, off + PLL_ALPHA_VAL_U, a >> 32); + + regmap_update_bits(pll->clkr.regmap, off + PLL_USER_CTL, + PLL_VCO_MASK << PLL_VCO_SHIFT, + vco->val << PLL_VCO_SHIFT); + + regmap_update_bits(pll->clkr.regmap, off + PLL_USER_CTL, PLL_ALPHA_EN, + PLL_ALPHA_EN); + + return 0; +} + +static long clk_alpha_pll_round_rate(struct clk_hw *hw, unsigned long rate, + unsigned long *prate) +{ + struct clk_alpha_pll *pll = to_clk_alpha_pll(hw); + u32 l; + u64 a; + unsigned long min_freq, max_freq; + + rate = alpha_pll_round_rate(rate, *prate, &l, &a); + if (alpha_pll_find_vco(pll, rate)) + return rate; + + min_freq = pll->vco_table[0].min_freq; + max_freq = pll->vco_table[pll->num_vco - 1].max_freq; + + return clamp(rate, min_freq, max_freq); +} + +const struct clk_ops clk_alpha_pll_ops = { + .enable = clk_alpha_pll_enable, + .disable = clk_alpha_pll_disable, + .recalc_rate = clk_alpha_pll_recalc_rate, + .round_rate = clk_alpha_pll_round_rate, + .set_rate = clk_alpha_pll_set_rate, +}; +EXPORT_SYMBOL_GPL(clk_alpha_pll_ops); + +static unsigned long +clk_alpha_pll_postdiv_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) +{ + struct clk_alpha_pll_postdiv *pll = to_clk_alpha_pll_postdiv(hw); + u32 ctl; + + regmap_read(pll->clkr.regmap, pll->offset + PLL_USER_CTL, &ctl); + + ctl >>= PLL_POST_DIV_SHIFT; + ctl &= PLL_POST_DIV_MASK; + + return parent_rate >> fls(ctl); +} + +static const struct clk_div_table clk_alpha_div_table[] = { + { 0x0, 1 }, + { 0x1, 2 }, + { 0x3, 4 }, + { 0x7, 8 }, + { 0xf, 16 }, + { } +}; + +static long +clk_alpha_pll_postdiv_round_rate(struct clk_hw *hw, unsigned long rate, + unsigned long *prate) +{ + struct clk_alpha_pll_postdiv *pll = to_clk_alpha_pll_postdiv(hw); + + return divider_round_rate(hw, rate, prate, clk_alpha_div_table, + pll->width, CLK_DIVIDER_POWER_OF_TWO); +} + +static int clk_alpha_pll_postdiv_set_rate(struct clk_hw *hw, unsigned long rate, + unsigned long parent_rate) +{ + struct clk_alpha_pll_postdiv *pll = to_clk_alpha_pll_postdiv(hw); + int div; + + /* 16 -> 0xf, 8 -> 0x7, 4 -> 0x3, 2 -> 0x1, 1 -> 0x0 */ + div = DIV_ROUND_UP_ULL((u64)parent_rate, rate) - 1; + + return regmap_update_bits(pll->clkr.regmap, pll->offset + PLL_USER_CTL, + PLL_POST_DIV_MASK << PLL_POST_DIV_SHIFT, + div << PLL_POST_DIV_SHIFT); +} + +const struct clk_ops clk_alpha_pll_postdiv_ops = { + .recalc_rate = clk_alpha_pll_postdiv_recalc_rate, + .round_rate = clk_alpha_pll_postdiv_round_rate, + .set_rate = clk_alpha_pll_postdiv_set_rate, +}; +EXPORT_SYMBOL_GPL(clk_alpha_pll_postdiv_ops); diff --git a/drivers/clk/qcom/clk-alpha-pll.h b/drivers/clk/qcom/clk-alpha-pll.h new file mode 100644 index 000000000000..90ce2016e1a0 --- /dev/null +++ b/drivers/clk/qcom/clk-alpha-pll.h @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2015, The Linux Foundation. All rights reserved. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef __QCOM_CLK_ALPHA_PLL_H__ +#define __QCOM_CLK_ALPHA_PLL_H__ + +#include <linux/clk-provider.h> +#include "clk-regmap.h" + +struct pll_vco { + unsigned long min_freq; + unsigned long max_freq; + u32 val; +}; + +/** + * struct clk_alpha_pll - phase locked loop (PLL) + * @offset: base address of registers + * @vco_table: array of VCO settings + * @clkr: regmap clock handle + */ +struct clk_alpha_pll { + u32 offset; + + const struct pll_vco *vco_table; + size_t num_vco; + + struct clk_regmap clkr; +}; + +/** + * struct clk_alpha_pll_postdiv - phase locked loop (PLL) post-divider + * @offset: base address of registers + * @width: width of post-divider + * @clkr: regmap clock handle + */ +struct clk_alpha_pll_postdiv { + u32 offset; + u8 width; + + struct clk_regmap clkr; +}; + +extern const struct clk_ops clk_alpha_pll_ops; +extern const struct clk_ops clk_alpha_pll_postdiv_ops; + +#endif diff --git a/drivers/clk/qcom/clk-rcg.h b/drivers/clk/qcom/clk-rcg.h index 4b1e94bdf29e..b904c335cda4 100644 --- a/drivers/clk/qcom/clk-rcg.h +++ b/drivers/clk/qcom/clk-rcg.h @@ -178,5 +178,6 @@ extern const struct clk_ops clk_edp_pixel_ops; extern const struct clk_ops clk_byte_ops; extern const struct clk_ops clk_byte2_ops; extern const struct clk_ops clk_pixel_ops; +extern const struct clk_ops clk_gfx3d_ops; #endif diff --git a/drivers/clk/qcom/clk-rcg2.c b/drivers/clk/qcom/clk-rcg2.c index b544bb302f79..a071bba8018c 100644 --- a/drivers/clk/qcom/clk-rcg2.c +++ b/drivers/clk/qcom/clk-rcg2.c @@ -723,3 +723,90 @@ const struct clk_ops clk_pixel_ops = { .determine_rate = clk_pixel_determine_rate, }; EXPORT_SYMBOL_GPL(clk_pixel_ops); + +static int clk_gfx3d_determine_rate(struct clk_hw *hw, + struct clk_rate_request *req) +{ + struct clk_rate_request parent_req = { }; + struct clk_hw *p2, *p8, *p9, *xo; + unsigned long p9_rate; + int ret; + + xo = clk_hw_get_parent_by_index(hw, 0); + if (req->rate == clk_hw_get_rate(xo)) { + req->best_parent_hw = xo; + return 0; + } + + p9 = clk_hw_get_parent_by_index(hw, 2); + p2 = clk_hw_get_parent_by_index(hw, 3); + p8 = clk_hw_get_parent_by_index(hw, 4); + + /* PLL9 is a fixed rate PLL */ + p9_rate = clk_hw_get_rate(p9); + + parent_req.rate = req->rate = min(req->rate, p9_rate); + if (req->rate == p9_rate) { + req->rate = req->best_parent_rate = p9_rate; + req->best_parent_hw = p9; + return 0; + } + + if (req->best_parent_hw == p9) { + /* Are we going back to a previously used rate? */ + if (clk_hw_get_rate(p8) == req->rate) + req->best_parent_hw = p8; + else + req->best_parent_hw = p2; + } else if (req->best_parent_hw == p8) { + req->best_parent_hw = p2; + } else { + req->best_parent_hw = p8; + } + + ret = __clk_determine_rate(req->best_parent_hw, &parent_req); + if (ret) + return ret; + + req->rate = req->best_parent_rate = parent_req.rate; + + return 0; +} + +static int clk_gfx3d_set_rate_and_parent(struct clk_hw *hw, unsigned long rate, + unsigned long parent_rate, u8 index) +{ + struct clk_rcg2 *rcg = to_clk_rcg2(hw); + u32 cfg; + int ret; + + /* Just mux it, we don't use the division or m/n hardware */ + cfg = rcg->parent_map[index].cfg << CFG_SRC_SEL_SHIFT; + ret = regmap_write(rcg->clkr.regmap, rcg->cmd_rcgr + CFG_REG, cfg); + if (ret) + return ret; + + return update_config(rcg); +} + +static int clk_gfx3d_set_rate(struct clk_hw *hw, unsigned long rate, + unsigned long parent_rate) +{ + /* + * We should never get here; clk_gfx3d_determine_rate() should always + * make us use a different parent than what we're currently using, so + * clk_gfx3d_set_rate_and_parent() should always be called. + */ + return 0; +} + +const struct clk_ops clk_gfx3d_ops = { + .is_enabled = clk_rcg2_is_enabled, + .get_parent = clk_rcg2_get_parent, + .set_parent = clk_rcg2_set_parent, + .recalc_rate = clk_rcg2_recalc_rate, + .set_rate = clk_gfx3d_set_rate, + .set_rate_and_parent = clk_gfx3d_set_rate_and_parent, + .determine_rate = clk_gfx3d_determine_rate, +}; +EXPORT_SYMBOL_GPL(clk_gfx3d_ops); diff --git a/drivers/clk/qcom/common.c b/drivers/clk/qcom/common.c index 8fa477293ae0..c112ebaba70d 100644 --- a/drivers/clk/qcom/common.c +++ b/drivers/clk/qcom/common.c @@ -17,6 +17,7 @@ #include <linux/platform_device.h> #include <linux/clk-provider.h> #include <linux/reset-controller.h> +#include <linux/of.h> #include "common.h" #include "clk-rcg.h" @@ -88,6 +89,92 @@ static void qcom_cc_gdsc_unregister(void *data) gdsc_unregister(data); } +/* + * Backwards compatibility with old DTs. Register a pass-through factor 1/1 + * clock to translate 'path' clk into 'name' clk and regsiter the 'path' + * clk as a fixed rate clock if it isn't present. + */ +static int _qcom_cc_register_board_clk(struct device *dev, const char *path, + const char *name, unsigned long rate, + bool add_factor) +{ + struct device_node *node = NULL; + struct device_node *clocks_node; + struct clk_fixed_factor *factor; + struct clk_fixed_rate *fixed; + struct clk *clk; + struct clk_init_data init_data = { }; + + clocks_node = of_find_node_by_path("/clocks"); + if (clocks_node) + node = of_find_node_by_name(clocks_node, path); + of_node_put(clocks_node); + + if (!node) { + fixed = devm_kzalloc(dev, sizeof(*fixed), GFP_KERNEL); + if (!fixed) + return -EINVAL; + + fixed->fixed_rate = rate; + fixed->hw.init = &init_data; + + init_data.name = path; + init_data.flags = CLK_IS_ROOT; + init_data.ops = &clk_fixed_rate_ops; + + clk = devm_clk_register(dev, &fixed->hw); + if (IS_ERR(clk)) + return PTR_ERR(clk); + } + of_node_put(node); + + if (add_factor) { + factor = devm_kzalloc(dev, sizeof(*factor), GFP_KERNEL); + if (!factor) + return -EINVAL; + + factor->mult = factor->div = 1; + factor->hw.init = &init_data; + + init_data.name = name; + init_data.parent_names = &path; + init_data.num_parents = 1; + init_data.flags = 0; + init_data.ops = &clk_fixed_factor_ops; + + clk = devm_clk_register(dev, &factor->hw); + if (IS_ERR(clk)) + return PTR_ERR(clk); + } + + return 0; +} + +int qcom_cc_register_board_clk(struct device *dev, const char *path, + const char *name, unsigned long rate) +{ + bool add_factor = true; + struct device_node *node; + + /* The RPM clock driver will add the factor clock if present */ + if (IS_ENABLED(CONFIG_QCOM_RPMCC)) { + node = of_find_compatible_node(NULL, NULL, "qcom,rpmcc"); + if (of_device_is_available(node)) + add_factor = false; + of_node_put(node); + } + + return _qcom_cc_register_board_clk(dev, path, name, rate, add_factor); +} +EXPORT_SYMBOL_GPL(qcom_cc_register_board_clk); + +int qcom_cc_register_sleep_clk(struct device *dev) +{ + return _qcom_cc_register_board_clk(dev, "sleep_clk", "sleep_clk_src", + 32768, true); +} +EXPORT_SYMBOL_GPL(qcom_cc_register_sleep_clk); + int qcom_cc_really_probe(struct platform_device *pdev, const struct qcom_cc_desc *desc, struct regmap *regmap) { diff --git a/drivers/clk/qcom/common.h b/drivers/clk/qcom/common.h index 7c1fba3ebc03..ae9bdeb21f29 100644 --- a/drivers/clk/qcom/common.h +++ b/drivers/clk/qcom/common.h @@ -37,6 +37,10 @@ extern const struct freq_tbl *qcom_find_freq(const struct freq_tbl *f, extern int qcom_find_src_index(struct clk_hw *hw, const struct parent_map *map, u8 src); +extern int qcom_cc_register_board_clk(struct device *dev, const char *path, + const char *name, unsigned long rate); +extern int qcom_cc_register_sleep_clk(struct device *dev); + extern struct regmap *qcom_cc_map(struct platform_device *pdev, const struct qcom_cc_desc *desc); extern int qcom_cc_really_probe(struct platform_device *pdev, diff --git a/drivers/clk/qcom/gcc-apq8084.c b/drivers/clk/qcom/gcc-apq8084.c index 1567c3a79534..cf73e539e9f6 100644 --- a/drivers/clk/qcom/gcc-apq8084.c +++ b/drivers/clk/qcom/gcc-apq8084.c @@ -3587,6 +3587,7 @@ static const struct regmap_config gcc_apq8084_regmap_config = { .val_bits = 32, .max_register = 0x1fc0, .fast_io = true, + .val_format_endian = REGMAP_ENDIAN_LITTLE, }; static const struct qcom_cc_desc gcc_apq8084_desc = { @@ -3607,18 +3608,16 @@ MODULE_DEVICE_TABLE(of, gcc_apq8084_match_table); static int gcc_apq8084_probe(struct platform_device *pdev) { - struct clk *clk; + int ret; struct device *dev = &pdev->dev; - /* Temporary until RPM clocks supported */ - clk = clk_register_fixed_rate(dev, "xo", NULL, CLK_IS_ROOT, 19200000); - if (IS_ERR(clk)) - return PTR_ERR(clk); + ret = qcom_cc_register_board_clk(dev, "xo_board", "xo", 19200000); + if (ret) + return ret; - clk = clk_register_fixed_rate(dev, "sleep_clk_src", NULL, - CLK_IS_ROOT, 32768); - if (IS_ERR(clk)) - return PTR_ERR(clk); + ret = qcom_cc_register_sleep_clk(dev); + if (ret) + return ret; return qcom_cc_probe(pdev, &gcc_apq8084_desc); } diff --git a/drivers/clk/qcom/gcc-ipq806x.c b/drivers/clk/qcom/gcc-ipq806x.c index 16fc64c082a5..b692ae881d6a 100644 --- a/drivers/clk/qcom/gcc-ipq806x.c +++ b/drivers/clk/qcom/gcc-ipq806x.c @@ -3005,6 +3005,7 @@ static const struct regmap_config gcc_ipq806x_regmap_config = { .val_bits = 32, .max_register = 0x3e40, .fast_io = true, + .val_format_endian = REGMAP_ENDIAN_LITTLE, }; static const struct qcom_cc_desc gcc_ipq806x_desc = { @@ -3023,19 +3024,17 @@ MODULE_DEVICE_TABLE(of, gcc_ipq806x_match_table); static int gcc_ipq806x_probe(struct platform_device *pdev) { - struct clk *clk; struct device *dev = &pdev->dev; struct regmap *regmap; int ret; - /* Temporary until RPM clocks supported */ - clk = clk_register_fixed_rate(dev, "cxo", NULL, CLK_IS_ROOT, 25000000); - if (IS_ERR(clk)) - return PTR_ERR(clk); + ret = qcom_cc_register_board_clk(dev, "cxo_board", "cxo", 19200000); + if (ret) + return ret; - clk = clk_register_fixed_rate(dev, "pxo", NULL, CLK_IS_ROOT, 25000000); - if (IS_ERR(clk)) - return PTR_ERR(clk); + ret = qcom_cc_register_board_clk(dev, "pxo_board", "pxo", 27000000); + if (ret) + return ret; ret = qcom_cc_probe(pdev, &gcc_ipq806x_desc); if (ret) diff --git a/drivers/clk/qcom/gcc-msm8660.c b/drivers/clk/qcom/gcc-msm8660.c index f110bb5a1df3..f6a2b14dfec4 100644 --- a/drivers/clk/qcom/gcc-msm8660.c +++ b/drivers/clk/qcom/gcc-msm8660.c @@ -2702,6 +2702,7 @@ static const struct regmap_config gcc_msm8660_regmap_config = { .val_bits = 32, .max_register = 0x363c, .fast_io = true, + .val_format_endian = REGMAP_ENDIAN_LITTLE, }; static const struct qcom_cc_desc gcc_msm8660_desc = { @@ -2720,17 +2721,16 @@ MODULE_DEVICE_TABLE(of, gcc_msm8660_match_table); static int gcc_msm8660_probe(struct platform_device *pdev) { - struct clk *clk; + int ret; struct device *dev = &pdev->dev; - /* Temporary until RPM clocks supported */ - clk = clk_register_fixed_rate(dev, "cxo", NULL, CLK_IS_ROOT, 19200000); - if (IS_ERR(clk)) - return PTR_ERR(clk); + ret = qcom_cc_register_board_clk(dev, "cxo_board", "cxo", 19200000); + if (ret) + return ret; - clk = clk_register_fixed_rate(dev, "pxo", NULL, CLK_IS_ROOT, 27000000); - if (IS_ERR(clk)) - return PTR_ERR(clk); + ret = qcom_cc_register_board_clk(dev, "pxo_board", "pxo", 27000000); + if (ret) + return ret; return qcom_cc_probe(pdev, &gcc_msm8660_desc); } diff --git a/drivers/clk/qcom/gcc-msm8916.c b/drivers/clk/qcom/gcc-msm8916.c index d0a0313d6bef..e3bf09d7d0ef 100644 --- a/drivers/clk/qcom/gcc-msm8916.c +++ b/drivers/clk/qcom/gcc-msm8916.c @@ -3336,6 +3336,7 @@ static const struct regmap_config gcc_msm8916_regmap_config = { .val_bits = 32, .max_register = 0x80000, .fast_io = true, + .val_format_endian = REGMAP_ENDIAN_LITTLE, }; static const struct qcom_cc_desc gcc_msm8916_desc = { @@ -3356,18 +3357,16 @@ MODULE_DEVICE_TABLE(of, gcc_msm8916_match_table); static int gcc_msm8916_probe(struct platform_device *pdev) { - struct clk *clk; + int ret; struct device *dev = &pdev->dev; - /* Temporary until RPM clocks supported */ - clk = clk_register_fixed_rate(dev, "xo", NULL, CLK_IS_ROOT, 19200000); - if (IS_ERR(clk)) - return PTR_ERR(clk); + ret = qcom_cc_register_board_clk(dev, "xo_board", "xo", 19200000); + if (ret) + return ret; - clk = clk_register_fixed_rate(dev, "sleep_clk_src", NULL, - CLK_IS_ROOT, 32768); - if (IS_ERR(clk)) - return PTR_ERR(clk); + ret = qcom_cc_register_sleep_clk(dev); + if (ret) + return ret; return qcom_cc_probe(pdev, &gcc_msm8916_desc); } diff --git a/drivers/clk/qcom/gcc-msm8960.c b/drivers/clk/qcom/gcc-msm8960.c index 66c18bc97857..f31111e32d44 100644 --- a/drivers/clk/qcom/gcc-msm8960.c +++ b/drivers/clk/qcom/gcc-msm8960.c @@ -3468,6 +3468,7 @@ static const struct regmap_config gcc_msm8960_regmap_config = { .val_bits = 32, .max_register = 0x3660, .fast_io = true, + .val_format_endian = REGMAP_ENDIAN_LITTLE, }; static const struct regmap_config gcc_apq8064_regmap_config = { @@ -3476,6 +3477,7 @@ static const struct regmap_config gcc_apq8064_regmap_config = { .val_bits = 32, .max_register = 0x3880, .fast_io = true, + .val_format_endian = REGMAP_ENDIAN_LITTLE, }; static const struct qcom_cc_desc gcc_msm8960_desc = { @@ -3503,7 +3505,6 @@ MODULE_DEVICE_TABLE(of, gcc_msm8960_match_table); static int gcc_msm8960_probe(struct platform_device *pdev) { - struct clk *clk; struct device *dev = &pdev->dev; const struct of_device_id *match; struct platform_device *tsens; @@ -3513,14 +3514,13 @@ static int gcc_msm8960_probe(struct platform_device *pdev) if (!match) return -EINVAL; - /* Temporary until RPM clocks supported */ - clk = clk_register_fixed_rate(dev, "cxo", NULL, CLK_IS_ROOT, 19200000); - if (IS_ERR(clk)) - return PTR_ERR(clk); + ret = qcom_cc_register_board_clk(dev, "cxo_board", "cxo", 19200000); + if (ret) + return ret; - clk = clk_register_fixed_rate(dev, "pxo", NULL, CLK_IS_ROOT, 27000000); - if (IS_ERR(clk)) - return PTR_ERR(clk); + ret = qcom_cc_register_board_clk(dev, "pxo_board", "pxo", 27000000); + if (ret) + return ret; ret = qcom_cc_probe(pdev, match->data); if (ret) diff --git a/drivers/clk/qcom/gcc-msm8974.c b/drivers/clk/qcom/gcc-msm8974.c index 28abb8f8f293..df164d618e34 100644 --- a/drivers/clk/qcom/gcc-msm8974.c +++ b/drivers/clk/qcom/gcc-msm8974.c @@ -2680,6 +2680,7 @@ static const struct regmap_config gcc_msm8974_regmap_config = { .val_bits = 32, .max_register = 0x1fc0, .fast_io = true, + .val_format_endian = REGMAP_ENDIAN_LITTLE, }; static const struct qcom_cc_desc gcc_msm8974_desc = { @@ -2717,7 +2718,7 @@ static void msm8974_pro_clock_override(void) static int gcc_msm8974_probe(struct platform_device *pdev) { - struct clk *clk; + int ret; struct device *dev = &pdev->dev; bool pro; const struct of_device_id *id; @@ -2730,16 +2731,13 @@ static int gcc_msm8974_probe(struct platform_device *pdev) if (pro) msm8974_pro_clock_override(); - /* Temporary until RPM clocks supported */ - clk = clk_register_fixed_rate(dev, "xo", NULL, CLK_IS_ROOT, 19200000); - if (IS_ERR(clk)) - return PTR_ERR(clk); + ret = qcom_cc_register_board_clk(dev, "xo_board", "xo", 19200000); + if (ret) + return ret; - /* Should move to DT node? */ - clk = clk_register_fixed_rate(dev, "sleep_clk_src", NULL, - CLK_IS_ROOT, 32768); - if (IS_ERR(clk)) - return PTR_ERR(clk); + ret = qcom_cc_register_sleep_clk(dev); + if (ret) + return ret; return qcom_cc_probe(pdev, &gcc_msm8974_desc); } diff --git a/drivers/clk/qcom/gcc-msm8996.c b/drivers/clk/qcom/gcc-msm8996.c new file mode 100644 index 000000000000..16d7c323db49 --- /dev/null +++ b/drivers/clk/qcom/gcc-msm8996.c @@ -0,0 +1,3422 @@ +/* + * Copyright (c) 2015, The Linux Foundation. All rights reserved. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include <linux/kernel.h> +#include <linux/bitops.h> +#include <linux/err.h> +#include <linux/platform_device.h> +#include <linux/module.h> +#include <linux/of.h> +#include <linux/of_device.h> +#include <linux/clk-provider.h> +#include <linux/regmap.h> +#include <linux/reset-controller.h> + +#include <dt-bindings/clock/qcom,gcc-msm8996.h> + +#include "common.h" +#include "clk-regmap.h" +#include "clk-alpha-pll.h" +#include "clk-rcg.h" +#include "clk-branch.h" +#include "reset.h" + +#define F(f, s, h, m, n) { (f), (s), (2 * (h) - 1), (m), (n) } + +enum { + P_XO, + P_GPLL0, + P_GPLL2, + P_GPLL3, + P_GPLL1, + P_GPLL2_EARLY, + P_GPLL0_EARLY_DIV, + P_SLEEP_CLK, + P_GPLL4, + P_AUD_REF_CLK, + P_GPLL1_EARLY_DIV +}; + +static const struct parent_map gcc_sleep_clk_map[] = { + { P_SLEEP_CLK, 5 } +}; + +static const char * const gcc_sleep_clk[] = { + "sleep_clk" +}; + +static const struct parent_map gcc_xo_gpll0_map[] = { + { P_XO, 0 }, + { P_GPLL0, 1 } +}; + +static const char * const gcc_xo_gpll0[] = { + "xo", + "gpll0" +}; + +static const struct parent_map gcc_xo_sleep_clk_map[] = { + { P_XO, 0 }, + { P_SLEEP_CLK, 5 } +}; + +static const char * const gcc_xo_sleep_clk[] = { + "xo", + "sleep_clk" +}; + +static const struct parent_map gcc_xo_gpll0_gpll0_early_div_map[] = { + { P_XO, 0 }, + { P_GPLL0, 1 }, + { P_GPLL0_EARLY_DIV, 6 } +}; + +static const char * const gcc_xo_gpll0_gpll0_early_div[] = { + "xo", + "gpll0", + "gpll0_early_div" +}; + +static const struct parent_map gcc_xo_gpll0_gpll4_map[] = { + { P_XO, 0 }, + { P_GPLL0, 1 }, + { P_GPLL4, 5 } +}; + +static const char * const gcc_xo_gpll0_gpll4[] = { + "xo", + "gpll0", + "gpll4" +}; + +static const struct parent_map gcc_xo_gpll0_aud_ref_clk_map[] = { + { P_XO, 0 }, + { P_GPLL0, 1 }, + { P_AUD_REF_CLK, 2 } +}; + +static const char * const gcc_xo_gpll0_aud_ref_clk[] = { + "xo", + "gpll0", + "aud_ref_clk" +}; + +static const struct parent_map gcc_xo_gpll0_sleep_clk_gpll0_early_div_map[] = { + { P_XO, 0 }, + { P_GPLL0, 1 }, + { P_SLEEP_CLK, 5 }, + { P_GPLL0_EARLY_DIV, 6 } +}; + +static const char * const gcc_xo_gpll0_sleep_clk_gpll0_early_div[] = { + "xo", + "gpll0", + "sleep_clk", + "gpll0_early_div" +}; + +static const struct parent_map gcc_xo_gpll0_gpll4_gpll0_early_div_map[] = { + { P_XO, 0 }, + { P_GPLL0, 1 }, + { P_GPLL4, 5 }, + { P_GPLL0_EARLY_DIV, 6 } +}; + +static const char * const gcc_xo_gpll0_gpll4_gpll0_early_div[] = { + "xo", + "gpll0", + "gpll4", + "gpll0_early_div" +}; + +static const struct parent_map gcc_xo_gpll0_gpll2_gpll3_gpll0_early_div_map[] = { + { P_XO, 0 }, + { P_GPLL0, 1 }, + { P_GPLL2, 2 }, + { P_GPLL3, 3 }, + { P_GPLL0_EARLY_DIV, 6 } +}; + +static const char * const gcc_xo_gpll0_gpll2_gpll3_gpll0_early_div[] = { + "xo", + "gpll0", + "gpll2", + "gpll3", + "gpll0_early_div" +}; + +static const struct parent_map gcc_xo_gpll0_gpll1_early_div_gpll1_gpll4_gpll0_early_div_map[] = { + { P_XO, 0 }, + { P_GPLL0, 1 }, + { P_GPLL1_EARLY_DIV, 3 }, + { P_GPLL1, 4 }, + { P_GPLL4, 5 }, + { P_GPLL0_EARLY_DIV, 6 } +}; + +static const char * const gcc_xo_gpll0_gpll1_early_div_gpll1_gpll4_gpll0_early_div[] = { + "xo", + "gpll0", + "gpll1_early_div", + "gpll1", + "gpll4", + "gpll0_early_div" +}; + +static const struct parent_map gcc_xo_gpll0_gpll2_gpll3_gpll1_gpll2_early_gpll0_early_div_map[] = { + { P_XO, 0 }, + { P_GPLL0, 1 }, + { P_GPLL2, 2 }, + { P_GPLL3, 3 }, + { P_GPLL1, 4 }, + { P_GPLL2_EARLY, 5 }, + { P_GPLL0_EARLY_DIV, 6 } +}; + +static const char * const gcc_xo_gpll0_gpll2_gpll3_gpll1_gpll2_early_gpll0_early_div[] = { + "xo", + "gpll0", + "gpll2", + "gpll3", + "gpll1", + "gpll2_early", + "gpll0_early_div" +}; + +static const struct parent_map gcc_xo_gpll0_gpll2_gpll3_gpll1_gpll4_gpll0_early_div_map[] = { + { P_XO, 0 }, + { P_GPLL0, 1 }, + { P_GPLL2, 2 }, + { P_GPLL3, 3 }, + { P_GPLL1, 4 }, + { P_GPLL4, 5 }, + { P_GPLL0_EARLY_DIV, 6 } +}; + +static const char * const gcc_xo_gpll0_gpll2_gpll3_gpll1_gpll4_gpll0_early_div[] = { + "xo", + "gpll0", + "gpll2", + "gpll3", + "gpll1", + "gpll4", + "gpll0_early_div" +}; + +static struct clk_fixed_factor xo = { + .mult = 1, + .div = 1, + .hw.init = &(struct clk_init_data){ + .name = "xo", + .parent_names = (const char *[]){ "xo_board" }, + .num_parents = 1, + .ops = &clk_fixed_factor_ops, + }, +}; + +static struct clk_alpha_pll gpll0_early = { + .offset = 0x00000, + .clkr = { + .enable_reg = 0x52000, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gpll0_early", + .parent_names = (const char *[]){ "xo" }, + .num_parents = 1, + .ops = &clk_alpha_pll_ops, + }, + }, +}; + +static struct clk_fixed_factor gpll0_early_div = { + .mult = 1, + .div = 2, + .hw.init = &(struct clk_init_data){ + .name = "gpll0_early_div", + .parent_names = (const char *[]){ "gpll0_early" }, + .num_parents = 1, + .ops = &clk_fixed_factor_ops, + }, +}; + +static struct clk_alpha_pll_postdiv gpll0 = { + .offset = 0x00000, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gpll0", + .parent_names = (const char *[]){ "gpll0_early" }, + .num_parents = 1, + .ops = &clk_alpha_pll_postdiv_ops, + }, +}; + +static struct clk_alpha_pll gpll4_early = { + .offset = 0x77000, + .clkr = { + .enable_reg = 0x52000, + .enable_mask = BIT(4), + .hw.init = &(struct clk_init_data){ + .name = "gpll4_early", + .parent_names = (const char *[]){ "xo" }, + .num_parents = 1, + .ops = &clk_alpha_pll_ops, + }, + }, +}; + +static struct clk_alpha_pll_postdiv gpll4 = { + .offset = 0x77000, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gpll4", + .parent_names = (const char *[]){ "gpll4_early" }, + .num_parents = 1, + .ops = &clk_alpha_pll_postdiv_ops, + }, +}; + +static const struct freq_tbl ftbl_system_noc_clk_src[] = { + F(19200000, P_XO, 1, 0, 0), + F(50000000, P_GPLL0_EARLY_DIV, 6, 0, 0), + F(100000000, P_GPLL0, 6, 0, 0), + F(150000000, P_GPLL0, 4, 0, 0), + F(200000000, P_GPLL0, 3, 0, 0), + F(240000000, P_GPLL0, 2.5, 0, 0), + { } +}; + +static struct clk_rcg2 system_noc_clk_src = { + .cmd_rcgr = 0x0401c, + .hid_width = 5, + .parent_map = gcc_xo_gpll0_gpll2_gpll3_gpll1_gpll2_early_gpll0_early_div_map, + .freq_tbl = ftbl_system_noc_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "system_noc_clk_src", + .parent_names = gcc_xo_gpll0_gpll2_gpll3_gpll1_gpll2_early_gpll0_early_div, + .num_parents = 7, + .ops = &clk_rcg2_ops, + }, +}; + +static const struct freq_tbl ftbl_config_noc_clk_src[] = { + F(19200000, P_XO, 1, 0, 0), + F(37500000, P_GPLL0, 16, 0, 0), + F(75000000, P_GPLL0, 8, 0, 0), + { } +}; + +static struct clk_rcg2 config_noc_clk_src = { + .cmd_rcgr = 0x0500c, + .hid_width = 5, + .parent_map = gcc_xo_gpll0_map, + .freq_tbl = ftbl_config_noc_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "config_noc_clk_src", + .parent_names = gcc_xo_gpll0, + .num_parents = 2, + .ops = &clk_rcg2_ops, + }, +}; + +static const struct freq_tbl ftbl_periph_noc_clk_src[] = { + F(19200000, P_XO, 1, 0, 0), + F(37500000, P_GPLL0, 16, 0, 0), + F(50000000, P_GPLL0, 12, 0, 0), + F(75000000, P_GPLL0, 8, 0, 0), + F(100000000, P_GPLL0, 6, 0, 0), + { } +}; + +static struct clk_rcg2 periph_noc_clk_src = { + .cmd_rcgr = 0x06014, + .hid_width = 5, + .parent_map = gcc_xo_gpll0_map, + .freq_tbl = ftbl_periph_noc_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "periph_noc_clk_src", + .parent_names = gcc_xo_gpll0, + .num_parents = 2, + .ops = &clk_rcg2_ops, + }, +}; + +static const struct freq_tbl ftbl_usb30_master_clk_src[] = { + F(19200000, P_XO, 1, 0, 0), + F(120000000, P_GPLL0, 5, 0, 0), + F(150000000, P_GPLL0, 4, 0, 0), + { } +}; + +static struct clk_rcg2 usb30_master_clk_src = { + .cmd_rcgr = 0x0f014, + .mnd_width = 8, + .hid_width = 5, + .parent_map = gcc_xo_gpll0_gpll0_early_div_map, + .freq_tbl = ftbl_usb30_master_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "usb30_master_clk_src", + .parent_names = gcc_xo_gpll0_gpll0_early_div, + .num_parents = 3, + .ops = &clk_rcg2_ops, + }, +}; + +static const struct freq_tbl ftbl_usb30_mock_utmi_clk_src[] = { + F(19200000, P_XO, 1, 0, 0), + { } +}; + +static struct clk_rcg2 usb30_mock_utmi_clk_src = { + .cmd_rcgr = 0x0f028, + .hid_width = 5, + .parent_map = gcc_xo_gpll0_gpll0_early_div_map, + .freq_tbl = ftbl_usb30_mock_utmi_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "usb30_mock_utmi_clk_src", + .parent_names = gcc_xo_gpll0_gpll0_early_div, + .num_parents = 3, + .ops = &clk_rcg2_ops, + }, +}; + +static const struct freq_tbl ftbl_usb3_phy_aux_clk_src[] = { + F(1200000, P_XO, 16, 0, 0), + { } +}; + +static struct clk_rcg2 usb3_phy_aux_clk_src = { + .cmd_rcgr = 0x5000c, + .hid_width = 5, + .parent_map = gcc_xo_sleep_clk_map, + .freq_tbl = ftbl_usb3_phy_aux_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "usb3_phy_aux_clk_src", + .parent_names = gcc_xo_sleep_clk, + .num_parents = 2, + .ops = &clk_rcg2_ops, + }, +}; + +static const struct freq_tbl ftbl_usb20_master_clk_src[] = { + F(120000000, P_GPLL0, 5, 0, 0), + { } +}; + +static struct clk_rcg2 usb20_master_clk_src = { + .cmd_rcgr = 0x12010, + .mnd_width = 8, + .hid_width = 5, + .parent_map = gcc_xo_gpll0_gpll0_early_div_map, + .freq_tbl = ftbl_usb20_master_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "usb20_master_clk_src", + .parent_names = gcc_xo_gpll0_gpll0_early_div, + .num_parents = 3, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 usb20_mock_utmi_clk_src = { + .cmd_rcgr = 0x12024, + .hid_width = 5, + .parent_map = gcc_xo_gpll0_gpll0_early_div_map, + .freq_tbl = ftbl_usb30_mock_utmi_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "usb20_mock_utmi_clk_src", + .parent_names = gcc_xo_gpll0_gpll0_early_div, + .num_parents = 3, + .ops = &clk_rcg2_ops, + }, +}; + +static const struct freq_tbl ftbl_sdcc1_apps_clk_src[] = { + F(144000, P_XO, 16, 3, 25), + F(400000, P_XO, 12, 1, 4), + F(20000000, P_GPLL0, 15, 1, 2), + F(25000000, P_GPLL0, 12, 1, 2), + F(50000000, P_GPLL0, 12, 0, 0), + F(96000000, P_GPLL4, 4, 0, 0), + F(192000000, P_GPLL4, 2, 0, 0), + F(384000000, P_GPLL4, 1, 0, 0), + { } +}; + +static struct clk_rcg2 sdcc1_apps_clk_src = { + .cmd_rcgr = 0x13010, + .mnd_width = 8, + .hid_width = 5, + .parent_map = gcc_xo_gpll0_gpll4_gpll0_early_div_map, + .freq_tbl = ftbl_sdcc1_apps_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "sdcc1_apps_clk_src", + .parent_names = gcc_xo_gpll0_gpll4_gpll0_early_div, + .num_parents = 4, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 sdcc1_ice_core_clk_src = { + .cmd_rcgr = 0x13024, + .hid_width = 5, + .parent_map = gcc_xo_gpll0_gpll4_gpll0_early_div_map, + .clkr.hw.init = &(struct clk_init_data){ + .name = "sdcc1_ice_core_clk_src", + .parent_names = gcc_xo_gpll0_gpll4_gpll0_early_div, + .num_parents = 4, + .ops = &clk_rcg2_ops, + }, +}; + +static const struct freq_tbl ftbl_sdcc2_apps_clk_src[] = { + F(144000, P_XO, 16, 3, 25), + F(400000, P_XO, 12, 1, 4), + F(20000000, P_GPLL0, 15, 1, 2), + F(25000000, P_GPLL0, 12, 1, 2), + F(50000000, P_GPLL0, 12, 0, 0), + F(100000000, P_GPLL0, 6, 0, 0), + F(200000000, P_GPLL0, 3, 0, 0), + { } +}; + +static struct clk_rcg2 sdcc2_apps_clk_src = { + .cmd_rcgr = 0x14010, + .mnd_width = 8, + .hid_width = 5, + .parent_map = gcc_xo_gpll0_gpll4_map, + .freq_tbl = ftbl_sdcc2_apps_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "sdcc2_apps_clk_src", + .parent_names = gcc_xo_gpll0_gpll4, + .num_parents = 3, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 sdcc3_apps_clk_src = { + .cmd_rcgr = 0x15010, + .mnd_width = 8, + .hid_width = 5, + .parent_map = gcc_xo_gpll0_gpll4_map, + .freq_tbl = ftbl_sdcc2_apps_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "sdcc3_apps_clk_src", + .parent_names = gcc_xo_gpll0_gpll4, + .num_parents = 3, + .ops = &clk_rcg2_ops, + }, +}; + +static const struct freq_tbl ftbl_sdcc4_apps_clk_src[] = { + F(144000, P_XO, 16, 3, 25), + F(400000, P_XO, 12, 1, 4), + F(20000000, P_GPLL0, 15, 1, 2), + F(25000000, P_GPLL0, 12, 1, 2), + F(50000000, P_GPLL0, 12, 0, 0), + F(100000000, P_GPLL0, 6, 0, 0), + { } +}; + +static struct clk_rcg2 sdcc4_apps_clk_src = { + .cmd_rcgr = 0x16010, + .mnd_width = 8, + .hid_width = 5, + .parent_map = gcc_xo_gpll0_map, + .freq_tbl = ftbl_sdcc4_apps_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "sdcc4_apps_clk_src", + .parent_names = gcc_xo_gpll0, + .num_parents = 2, + .ops = &clk_rcg2_ops, + }, +}; + +static const struct freq_tbl ftbl_blsp1_qup1_spi_apps_clk_src[] = { + F(960000, P_XO, 10, 1, 2), + F(4800000, P_XO, 4, 0, 0), + F(9600000, P_XO, 2, 0, 0), + F(15000000, P_GPLL0, 10, 1, 4), + F(19200000, P_XO, 1, 0, 0), + F(25000000, P_GPLL0, 12, 1, 2), + F(50000000, P_GPLL0, 12, 0, 0), + { } +}; + +static struct clk_rcg2 blsp1_qup1_spi_apps_clk_src = { + .cmd_rcgr = 0x1900c, + .mnd_width = 8, + .hid_width = 5, + .parent_map = gcc_xo_gpll0_map, + .freq_tbl = ftbl_blsp1_qup1_spi_apps_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "blsp1_qup1_spi_apps_clk_src", + .parent_names = gcc_xo_gpll0, + .num_parents = 2, + .ops = &clk_rcg2_ops, + }, +}; + +static const struct freq_tbl ftbl_blsp1_qup1_i2c_apps_clk_src[] = { + F(19200000, P_XO, 1, 0, 0), + F(50000000, P_GPLL0, 12, 0, 0), + { } +}; + +static struct clk_rcg2 blsp1_qup1_i2c_apps_clk_src = { + .cmd_rcgr = 0x19020, + .hid_width = 5, + .parent_map = gcc_xo_gpll0_map, + .freq_tbl = ftbl_blsp1_qup1_i2c_apps_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "blsp1_qup1_i2c_apps_clk_src", + .parent_names = gcc_xo_gpll0, + .num_parents = 2, + .ops = &clk_rcg2_ops, + }, +}; + +static const struct freq_tbl ftbl_blsp1_uart1_apps_clk_src[] = { + F(3686400, P_GPLL0, 1, 96, 15625), + F(7372800, P_GPLL0, 1, 192, 15625), + F(14745600, P_GPLL0, 1, 384, 15625), + F(16000000, P_GPLL0, 5, 2, 15), + F(19200000, P_XO, 1, 0, 0), + F(24000000, P_GPLL0, 5, 1, 5), + F(32000000, P_GPLL0, 1, 4, 75), + F(40000000, P_GPLL0, 15, 0, 0), + F(46400000, P_GPLL0, 1, 29, 375), + F(48000000, P_GPLL0, 12.5, 0, 0), + F(51200000, P_GPLL0, 1, 32, 375), + F(56000000, P_GPLL0, 1, 7, 75), + F(58982400, P_GPLL0, 1, 1536, 15625), + F(60000000, P_GPLL0, 10, 0, 0), + F(63157895, P_GPLL0, 9.5, 0, 0), + { } +}; + +static struct clk_rcg2 blsp1_uart1_apps_clk_src = { + .cmd_rcgr = 0x1a00c, + .mnd_width = 16, + .hid_width = 5, + .parent_map = gcc_xo_gpll0_map, + .freq_tbl = ftbl_blsp1_uart1_apps_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "blsp1_uart1_apps_clk_src", + .parent_names = gcc_xo_gpll0, + .num_parents = 2, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 blsp1_qup2_spi_apps_clk_src = { + .cmd_rcgr = 0x1b00c, + .mnd_width = 8, + .hid_width = 5, + .parent_map = gcc_xo_gpll0_map, + .freq_tbl = ftbl_blsp1_qup1_spi_apps_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "blsp1_qup2_spi_apps_clk_src", + .parent_names = gcc_xo_gpll0, + .num_parents = 2, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 blsp1_qup2_i2c_apps_clk_src = { + .cmd_rcgr = 0x1b020, + .hid_width = 5, + .parent_map = gcc_xo_gpll0_map, + .freq_tbl = ftbl_blsp1_qup1_i2c_apps_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "blsp1_qup2_i2c_apps_clk_src", + .parent_names = gcc_xo_gpll0, + .num_parents = 2, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 blsp1_uart2_apps_clk_src = { + .cmd_rcgr = 0x1c00c, + .mnd_width = 16, + .hid_width = 5, + .parent_map = gcc_xo_gpll0_map, + .freq_tbl = ftbl_blsp1_uart1_apps_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "blsp1_uart2_apps_clk_src", + .parent_names = gcc_xo_gpll0, + .num_parents = 2, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 blsp1_qup3_spi_apps_clk_src = { + .cmd_rcgr = 0x1d00c, + .mnd_width = 8, + .hid_width = 5, + .parent_map = gcc_xo_gpll0_map, + .freq_tbl = ftbl_blsp1_qup1_spi_apps_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "blsp1_qup3_spi_apps_clk_src", + .parent_names = gcc_xo_gpll0, + .num_parents = 2, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 blsp1_qup3_i2c_apps_clk_src = { + .cmd_rcgr = 0x1d020, + .hid_width = 5, + .parent_map = gcc_xo_gpll0_map, + .freq_tbl = ftbl_blsp1_qup1_i2c_apps_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "blsp1_qup3_i2c_apps_clk_src", + .parent_names = gcc_xo_gpll0, + .num_parents = 2, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 blsp1_uart3_apps_clk_src = { + .cmd_rcgr = 0x1e00c, + .mnd_width = 16, + .hid_width = 5, + .parent_map = gcc_xo_gpll0_map, + .freq_tbl = ftbl_blsp1_uart1_apps_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "blsp1_uart3_apps_clk_src", + .parent_names = gcc_xo_gpll0, + .num_parents = 2, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 blsp1_qup4_spi_apps_clk_src = { + .cmd_rcgr = 0x1f00c, + .mnd_width = 8, + .hid_width = 5, + .parent_map = gcc_xo_gpll0_map, + .freq_tbl = ftbl_blsp1_qup1_spi_apps_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "blsp1_qup4_spi_apps_clk_src", + .parent_names = gcc_xo_gpll0, + .num_parents = 2, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 blsp1_qup4_i2c_apps_clk_src = { + .cmd_rcgr = 0x1f020, + .hid_width = 5, + .parent_map = gcc_xo_gpll0_map, + .freq_tbl = ftbl_blsp1_qup1_i2c_apps_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "blsp1_qup4_i2c_apps_clk_src", + .parent_names = gcc_xo_gpll0, + .num_parents = 2, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 blsp1_uart4_apps_clk_src = { + .cmd_rcgr = 0x2000c, + .mnd_width = 16, + .hid_width = 5, + .parent_map = gcc_xo_gpll0_map, + .freq_tbl = ftbl_blsp1_uart1_apps_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "blsp1_uart4_apps_clk_src", + .parent_names = gcc_xo_gpll0, + .num_parents = 2, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 blsp1_qup5_spi_apps_clk_src = { + .cmd_rcgr = 0x2100c, + .mnd_width = 8, + .hid_width = 5, + .parent_map = gcc_xo_gpll0_map, + .freq_tbl = ftbl_blsp1_qup1_spi_apps_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "blsp1_qup5_spi_apps_clk_src", + .parent_names = gcc_xo_gpll0, + .num_parents = 2, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 blsp1_qup5_i2c_apps_clk_src = { + .cmd_rcgr = 0x21020, + .hid_width = 5, + .parent_map = gcc_xo_gpll0_map, + .freq_tbl = ftbl_blsp1_qup1_i2c_apps_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "blsp1_qup5_i2c_apps_clk_src", + .parent_names = gcc_xo_gpll0, + .num_parents = 2, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 blsp1_uart5_apps_clk_src = { + .cmd_rcgr = 0x2200c, + .mnd_width = 16, + .hid_width = 5, + .parent_map = gcc_xo_gpll0_map, + .freq_tbl = ftbl_blsp1_uart1_apps_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "blsp1_uart5_apps_clk_src", + .parent_names = gcc_xo_gpll0, + .num_parents = 2, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 blsp1_qup6_spi_apps_clk_src = { + .cmd_rcgr = 0x2300c, + .mnd_width = 8, + .hid_width = 5, + .parent_map = gcc_xo_gpll0_map, + .freq_tbl = ftbl_blsp1_qup1_spi_apps_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "blsp1_qup6_spi_apps_clk_src", + .parent_names = gcc_xo_gpll0, + .num_parents = 2, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 blsp1_qup6_i2c_apps_clk_src = { + .cmd_rcgr = 0x23020, + .hid_width = 5, + .parent_map = gcc_xo_gpll0_map, + .freq_tbl = ftbl_blsp1_qup1_i2c_apps_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "blsp1_qup6_i2c_apps_clk_src", + .parent_names = gcc_xo_gpll0, + .num_parents = 2, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 blsp1_uart6_apps_clk_src = { + .cmd_rcgr = 0x2400c, + .mnd_width = 16, + .hid_width = 5, + .parent_map = gcc_xo_gpll0_map, + .freq_tbl = ftbl_blsp1_uart1_apps_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "blsp1_uart6_apps_clk_src", + .parent_names = gcc_xo_gpll0, + .num_parents = 2, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 blsp2_qup1_spi_apps_clk_src = { + .cmd_rcgr = 0x2600c, + .mnd_width = 8, + .hid_width = 5, + .parent_map = gcc_xo_gpll0_map, + .freq_tbl = ftbl_blsp1_qup1_spi_apps_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "blsp2_qup1_spi_apps_clk_src", + .parent_names = gcc_xo_gpll0, + .num_parents = 2, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 blsp2_qup1_i2c_apps_clk_src = { + .cmd_rcgr = 0x26020, + .hid_width = 5, + .parent_map = gcc_xo_gpll0_map, + .freq_tbl = ftbl_blsp1_qup1_i2c_apps_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "blsp2_qup1_i2c_apps_clk_src", + .parent_names = gcc_xo_gpll0, + .num_parents = 2, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 blsp2_uart1_apps_clk_src = { + .cmd_rcgr = 0x2700c, + .mnd_width = 16, + .hid_width = 5, + .parent_map = gcc_xo_gpll0_map, + .freq_tbl = ftbl_blsp1_uart1_apps_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "blsp2_uart1_apps_clk_src", + .parent_names = gcc_xo_gpll0, + .num_parents = 2, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 blsp2_qup2_spi_apps_clk_src = { + .cmd_rcgr = 0x2800c, + .mnd_width = 8, + .hid_width = 5, + .parent_map = gcc_xo_gpll0_map, + .freq_tbl = ftbl_blsp1_qup1_spi_apps_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "blsp2_qup2_spi_apps_clk_src", + .parent_names = gcc_xo_gpll0, + .num_parents = 2, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 blsp2_qup2_i2c_apps_clk_src = { + .cmd_rcgr = 0x28020, + .hid_width = 5, + .parent_map = gcc_xo_gpll0_map, + .freq_tbl = ftbl_blsp1_qup1_i2c_apps_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "blsp2_qup2_i2c_apps_clk_src", + .parent_names = gcc_xo_gpll0, + .num_parents = 2, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 blsp2_uart2_apps_clk_src = { + .cmd_rcgr = 0x2900c, + .mnd_width = 16, + .hid_width = 5, + .parent_map = gcc_xo_gpll0_map, + .freq_tbl = ftbl_blsp1_uart1_apps_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "blsp2_uart2_apps_clk_src", + .parent_names = gcc_xo_gpll0, + .num_parents = 2, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 blsp2_qup3_spi_apps_clk_src = { + .cmd_rcgr = 0x2a00c, + .mnd_width = 8, + .hid_width = 5, + .parent_map = gcc_xo_gpll0_map, + .freq_tbl = ftbl_blsp1_qup1_spi_apps_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "blsp2_qup3_spi_apps_clk_src", + .parent_names = gcc_xo_gpll0, + .num_parents = 2, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 blsp2_qup3_i2c_apps_clk_src = { + .cmd_rcgr = 0x2a020, + .hid_width = 5, + .parent_map = gcc_xo_gpll0_map, + .freq_tbl = ftbl_blsp1_qup1_i2c_apps_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "blsp2_qup3_i2c_apps_clk_src", + .parent_names = gcc_xo_gpll0, + .num_parents = 2, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 blsp2_uart3_apps_clk_src = { + .cmd_rcgr = 0x2b00c, + .mnd_width = 16, + .hid_width = 5, + .parent_map = gcc_xo_gpll0_map, + .freq_tbl = ftbl_blsp1_uart1_apps_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "blsp2_uart3_apps_clk_src", + .parent_names = gcc_xo_gpll0, + .num_parents = 2, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 blsp2_qup4_spi_apps_clk_src = { + .cmd_rcgr = 0x2c00c, + .mnd_width = 8, + .hid_width = 5, + .parent_map = gcc_xo_gpll0_map, + .freq_tbl = ftbl_blsp1_qup1_spi_apps_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "blsp2_qup4_spi_apps_clk_src", + .parent_names = gcc_xo_gpll0, + .num_parents = 2, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 blsp2_qup4_i2c_apps_clk_src = { + .cmd_rcgr = 0x2c020, + .hid_width = 5, + .parent_map = gcc_xo_gpll0_map, + .freq_tbl = ftbl_blsp1_qup1_i2c_apps_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "blsp2_qup4_i2c_apps_clk_src", + .parent_names = gcc_xo_gpll0, + .num_parents = 2, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 blsp2_uart4_apps_clk_src = { + .cmd_rcgr = 0x2d00c, + .mnd_width = 16, + .hid_width = 5, + .parent_map = gcc_xo_gpll0_map, + .freq_tbl = ftbl_blsp1_uart1_apps_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "blsp2_uart4_apps_clk_src", + .parent_names = gcc_xo_gpll0, + .num_parents = 2, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 blsp2_qup5_spi_apps_clk_src = { + .cmd_rcgr = 0x2e00c, + .mnd_width = 8, + .hid_width = 5, + .parent_map = gcc_xo_gpll0_map, + .freq_tbl = ftbl_blsp1_qup1_spi_apps_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "blsp2_qup5_spi_apps_clk_src", + .parent_names = gcc_xo_gpll0, + .num_parents = 2, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 blsp2_qup5_i2c_apps_clk_src = { + .cmd_rcgr = 0x2e020, + .hid_width = 5, + .parent_map = gcc_xo_gpll0_map, + .freq_tbl = ftbl_blsp1_qup1_i2c_apps_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "blsp2_qup5_i2c_apps_clk_src", + .parent_names = gcc_xo_gpll0, + .num_parents = 2, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 blsp2_uart5_apps_clk_src = { + .cmd_rcgr = 0x2f00c, + .mnd_width = 16, + .hid_width = 5, + .parent_map = gcc_xo_gpll0_map, + .freq_tbl = ftbl_blsp1_uart1_apps_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "blsp2_uart5_apps_clk_src", + .parent_names = gcc_xo_gpll0, + .num_parents = 2, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 blsp2_qup6_spi_apps_clk_src = { + .cmd_rcgr = 0x3000c, + .mnd_width = 8, + .hid_width = 5, + .parent_map = gcc_xo_gpll0_map, + .freq_tbl = ftbl_blsp1_qup1_spi_apps_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "blsp2_qup6_spi_apps_clk_src", + .parent_names = gcc_xo_gpll0, + .num_parents = 2, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 blsp2_qup6_i2c_apps_clk_src = { + .cmd_rcgr = 0x30020, + .hid_width = 5, + .parent_map = gcc_xo_gpll0_map, + .freq_tbl = ftbl_blsp1_qup1_i2c_apps_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "blsp2_qup6_i2c_apps_clk_src", + .parent_names = gcc_xo_gpll0, + .num_parents = 2, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 blsp2_uart6_apps_clk_src = { + .cmd_rcgr = 0x3100c, + .mnd_width = 16, + .hid_width = 5, + .parent_map = gcc_xo_gpll0_map, + .freq_tbl = ftbl_blsp1_uart1_apps_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "blsp2_uart6_apps_clk_src", + .parent_names = gcc_xo_gpll0, + .num_parents = 2, + .ops = &clk_rcg2_ops, + }, +}; + +static const struct freq_tbl ftbl_pdm2_clk_src[] = { + F(60000000, P_GPLL0, 10, 0, 0), + { } +}; + +static struct clk_rcg2 pdm2_clk_src = { + .cmd_rcgr = 0x33010, + .hid_width = 5, + .parent_map = gcc_xo_gpll0_map, + .freq_tbl = ftbl_pdm2_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "pdm2_clk_src", + .parent_names = gcc_xo_gpll0, + .num_parents = 2, + .ops = &clk_rcg2_ops, + }, +}; + +static const struct freq_tbl ftbl_tsif_ref_clk_src[] = { + F(105495, P_XO, 1, 1, 182), + { } +}; + +static struct clk_rcg2 tsif_ref_clk_src = { + .cmd_rcgr = 0x36010, + .mnd_width = 8, + .hid_width = 5, + .parent_map = gcc_xo_gpll0_aud_ref_clk_map, + .freq_tbl = ftbl_tsif_ref_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "tsif_ref_clk_src", + .parent_names = gcc_xo_gpll0_aud_ref_clk, + .num_parents = 3, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 gcc_sleep_clk_src = { + .cmd_rcgr = 0x43014, + .hid_width = 5, + .parent_map = gcc_sleep_clk_map, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gcc_sleep_clk_src", + .parent_names = gcc_sleep_clk, + .num_parents = 1, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 hmss_rbcpr_clk_src = { + .cmd_rcgr = 0x48040, + .hid_width = 5, + .parent_map = gcc_xo_gpll0_map, + .freq_tbl = ftbl_usb30_mock_utmi_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "hmss_rbcpr_clk_src", + .parent_names = gcc_xo_gpll0, + .num_parents = 2, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 hmss_gpll0_clk_src = { + .cmd_rcgr = 0x48058, + .hid_width = 5, + .parent_map = gcc_xo_gpll0_map, + .clkr.hw.init = &(struct clk_init_data){ + .name = "hmss_gpll0_clk_src", + .parent_names = gcc_xo_gpll0, + .num_parents = 2, + .ops = &clk_rcg2_ops, + }, +}; + +static const struct freq_tbl ftbl_gp1_clk_src[] = { + F(19200000, P_XO, 1, 0, 0), + F(100000000, P_GPLL0, 6, 0, 0), + F(200000000, P_GPLL0, 3, 0, 0), + { } +}; + +static struct clk_rcg2 gp1_clk_src = { + .cmd_rcgr = 0x64004, + .mnd_width = 8, + .hid_width = 5, + .parent_map = gcc_xo_gpll0_sleep_clk_gpll0_early_div_map, + .freq_tbl = ftbl_gp1_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gp1_clk_src", + .parent_names = gcc_xo_gpll0_sleep_clk_gpll0_early_div, + .num_parents = 4, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 gp2_clk_src = { + .cmd_rcgr = 0x65004, + .mnd_width = 8, + .hid_width = 5, + .parent_map = gcc_xo_gpll0_sleep_clk_gpll0_early_div_map, + .freq_tbl = ftbl_gp1_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gp2_clk_src", + .parent_names = gcc_xo_gpll0_sleep_clk_gpll0_early_div, + .num_parents = 4, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 gp3_clk_src = { + .cmd_rcgr = 0x66004, + .mnd_width = 8, + .hid_width = 5, + .parent_map = gcc_xo_gpll0_sleep_clk_gpll0_early_div_map, + .freq_tbl = ftbl_gp1_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gp3_clk_src", + .parent_names = gcc_xo_gpll0_sleep_clk_gpll0_early_div, + .num_parents = 4, + .ops = &clk_rcg2_ops, + }, +}; + +static const struct freq_tbl ftbl_pcie_aux_clk_src[] = { + F(1010526, P_XO, 1, 1, 19), + { } +}; + +static struct clk_rcg2 pcie_aux_clk_src = { + .cmd_rcgr = 0x6c000, + .mnd_width = 16, + .hid_width = 5, + .parent_map = gcc_xo_sleep_clk_map, + .freq_tbl = ftbl_pcie_aux_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "pcie_aux_clk_src", + .parent_names = gcc_xo_sleep_clk, + .num_parents = 2, + .ops = &clk_rcg2_ops, + }, +}; + +static const struct freq_tbl ftbl_ufs_axi_clk_src[] = { + F(100000000, P_GPLL0, 6, 0, 0), + F(200000000, P_GPLL0, 3, 0, 0), + F(240000000, P_GPLL0, 2.5, 0, 0), + { } +}; + +static struct clk_rcg2 ufs_axi_clk_src = { + .cmd_rcgr = 0x75024, + .mnd_width = 8, + .hid_width = 5, + .parent_map = gcc_xo_gpll0_map, + .freq_tbl = ftbl_ufs_axi_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "ufs_axi_clk_src", + .parent_names = gcc_xo_gpll0, + .num_parents = 2, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 ufs_ice_core_clk_src = { + .cmd_rcgr = 0x76014, + .hid_width = 5, + .parent_map = gcc_xo_gpll0_map, + .clkr.hw.init = &(struct clk_init_data){ + .name = "ufs_ice_core_clk_src", + .parent_names = gcc_xo_gpll0, + .num_parents = 2, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 qspi_ser_clk_src = { + .cmd_rcgr = 0x8b00c, + .hid_width = 5, + .parent_map = gcc_xo_gpll0_gpll1_early_div_gpll1_gpll4_gpll0_early_div_map, + .clkr.hw.init = &(struct clk_init_data){ + .name = "qspi_ser_clk_src", + .parent_names = gcc_xo_gpll0_gpll1_early_div_gpll1_gpll4_gpll0_early_div, + .num_parents = 6, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_branch gcc_sys_noc_usb3_axi_clk = { + .halt_reg = 0x0f03c, + .clkr = { + .enable_reg = 0x0f03c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_sys_noc_usb3_axi_clk", + .parent_names = (const char *[]){ "usb30_master_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_sys_noc_ufs_axi_clk = { + .halt_reg = 0x75038, + .clkr = { + .enable_reg = 0x75038, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_sys_noc_ufs_axi_clk", + .parent_names = (const char *[]){ "ufs_axi_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_periph_noc_usb20_ahb_clk = { + .halt_reg = 0x6010, + .clkr = { + .enable_reg = 0x6010, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_periph_noc_usb20_ahb_clk", + .parent_names = (const char *[]){ "usb20_master_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_mmss_noc_cfg_ahb_clk = { + .halt_reg = 0x9008, + .clkr = { + .enable_reg = 0x9008, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_mmss_noc_cfg_ahb_clk", + .parent_names = (const char *[]){ "config_noc_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_mmss_bimc_gfx_clk = { + .halt_reg = 0x9010, + .clkr = { + .enable_reg = 0x9010, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_mmss_bimc_gfx_clk", + .flags = CLK_SET_RATE_PARENT | CLK_IS_ROOT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_usb30_master_clk = { + .halt_reg = 0x0f008, + .clkr = { + .enable_reg = 0x0f008, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_usb30_master_clk", + .parent_names = (const char *[]){ "usb30_master_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_usb30_sleep_clk = { + .halt_reg = 0x0f00c, + .clkr = { + .enable_reg = 0x0f00c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_usb30_sleep_clk", + .parent_names = (const char *[]){ "gcc_sleep_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_usb30_mock_utmi_clk = { + .halt_reg = 0x0f010, + .clkr = { + .enable_reg = 0x0f010, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_usb30_mock_utmi_clk", + .parent_names = (const char *[]){ "usb30_mock_utmi_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_usb3_phy_aux_clk = { + .halt_reg = 0x50000, + .clkr = { + .enable_reg = 0x50000, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_usb3_phy_aux_clk", + .parent_names = (const char *[]){ "usb3_phy_aux_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_usb3_phy_pipe_clk = { + .halt_reg = 0x50004, + .clkr = { + .enable_reg = 0x50004, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_usb3_phy_pipe_clk", + .parent_names = (const char *[]){ "usb3_phy_pipe_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_usb20_master_clk = { + .halt_reg = 0x12004, + .clkr = { + .enable_reg = 0x12004, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_usb20_master_clk", + .parent_names = (const char *[]){ "usb20_master_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_usb20_sleep_clk = { + .halt_reg = 0x12008, + .clkr = { + .enable_reg = 0x12008, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_usb20_sleep_clk", + .parent_names = (const char *[]){ "gcc_sleep_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_usb20_mock_utmi_clk = { + .halt_reg = 0x1200c, + .clkr = { + .enable_reg = 0x1200c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_usb20_mock_utmi_clk", + .parent_names = (const char *[]){ "usb20_mock_utmi_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_usb_phy_cfg_ahb2phy_clk = { + .halt_reg = 0x6a004, + .clkr = { + .enable_reg = 0x6a004, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_usb_phy_cfg_ahb2phy_clk", + .parent_names = (const char *[]){ "periph_noc_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_sdcc1_apps_clk = { + .halt_reg = 0x13004, + .clkr = { + .enable_reg = 0x13004, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_sdcc1_apps_clk", + .parent_names = (const char *[]){ "sdcc1_apps_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_sdcc1_ahb_clk = { + .halt_reg = 0x13008, + .clkr = { + .enable_reg = 0x13008, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_sdcc1_ahb_clk", + .parent_names = (const char *[]){ "periph_noc_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_sdcc1_ice_core_clk = { + .halt_reg = 0x13038, + .clkr = { + .enable_reg = 0x13038, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_sdcc1_ice_core_clk", + .parent_names = (const char *[]){ "sdcc1_ice_core_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_sdcc2_apps_clk = { + .halt_reg = 0x14004, + .clkr = { + .enable_reg = 0x14004, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_sdcc2_apps_clk", + .parent_names = (const char *[]){ "sdcc2_apps_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_sdcc2_ahb_clk = { + .halt_reg = 0x14008, + .clkr = { + .enable_reg = 0x14008, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_sdcc2_ahb_clk", + .parent_names = (const char *[]){ "periph_noc_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_sdcc3_apps_clk = { + .halt_reg = 0x15004, + .clkr = { + .enable_reg = 0x15004, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_sdcc3_apps_clk", + .parent_names = (const char *[]){ "sdcc3_apps_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_sdcc3_ahb_clk = { + .halt_reg = 0x15008, + .clkr = { + .enable_reg = 0x15008, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_sdcc3_ahb_clk", + .parent_names = (const char *[]){ "periph_noc_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_sdcc4_apps_clk = { + .halt_reg = 0x16004, + .clkr = { + .enable_reg = 0x16004, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_sdcc4_apps_clk", + .parent_names = (const char *[]){ "sdcc4_apps_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_sdcc4_ahb_clk = { + .halt_reg = 0x16008, + .clkr = { + .enable_reg = 0x16008, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_sdcc4_ahb_clk", + .parent_names = (const char *[]){ "periph_noc_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_blsp1_ahb_clk = { + .halt_reg = 0x17004, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x52004, + .enable_mask = BIT(17), + .hw.init = &(struct clk_init_data){ + .name = "gcc_blsp1_ahb_clk", + .parent_names = (const char *[]){ "periph_noc_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_blsp1_sleep_clk = { + .halt_reg = 0x17008, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x52004, + .enable_mask = BIT(16), + .hw.init = &(struct clk_init_data){ + .name = "gcc_blsp1_sleep_clk", + .parent_names = (const char *[]){ "gcc_sleep_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_blsp1_qup1_spi_apps_clk = { + .halt_reg = 0x19004, + .clkr = { + .enable_reg = 0x19004, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_blsp1_qup1_spi_apps_clk", + .parent_names = (const char *[]){ "blsp1_qup1_spi_apps_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_blsp1_qup1_i2c_apps_clk = { + .halt_reg = 0x19008, + .clkr = { + .enable_reg = 0x19008, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_blsp1_qup1_i2c_apps_clk", + .parent_names = (const char *[]){ "blsp1_qup1_i2c_apps_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_blsp1_uart1_apps_clk = { + .halt_reg = 0x1a004, + .clkr = { + .enable_reg = 0x1a004, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_blsp1_uart1_apps_clk", + .parent_names = (const char *[]){ "blsp1_uart1_apps_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_blsp1_qup2_spi_apps_clk = { + .halt_reg = 0x1b004, + .clkr = { + .enable_reg = 0x1b004, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_blsp1_qup2_spi_apps_clk", + .parent_names = (const char *[]){ "blsp1_qup2_spi_apps_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_blsp1_qup2_i2c_apps_clk = { + .halt_reg = 0x1b008, + .clkr = { + .enable_reg = 0x1b008, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_blsp1_qup2_i2c_apps_clk", + .parent_names = (const char *[]){ "blsp1_qup2_i2c_apps_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_blsp1_uart2_apps_clk = { + .halt_reg = 0x1c004, + .clkr = { + .enable_reg = 0x1c004, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_blsp1_uart2_apps_clk", + .parent_names = (const char *[]){ "blsp1_uart2_apps_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_blsp1_qup3_spi_apps_clk = { + .halt_reg = 0x1d004, + .clkr = { + .enable_reg = 0x1d004, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_blsp1_qup3_spi_apps_clk", + .parent_names = (const char *[]){ "blsp1_qup3_spi_apps_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_blsp1_qup3_i2c_apps_clk = { + .halt_reg = 0x1d008, + .clkr = { + .enable_reg = 0x1d008, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_blsp1_qup3_i2c_apps_clk", + .parent_names = (const char *[]){ "blsp1_qup3_i2c_apps_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_blsp1_uart3_apps_clk = { + .halt_reg = 0x1e004, + .clkr = { + .enable_reg = 0x1e004, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_blsp1_uart3_apps_clk", + .parent_names = (const char *[]){ "blsp1_uart3_apps_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_blsp1_qup4_spi_apps_clk = { + .halt_reg = 0x1f004, + .clkr = { + .enable_reg = 0x1f004, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_blsp1_qup4_spi_apps_clk", + .parent_names = (const char *[]){ "blsp1_qup4_spi_apps_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_blsp1_qup4_i2c_apps_clk = { + .halt_reg = 0x1f008, + .clkr = { + .enable_reg = 0x1f008, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_blsp1_qup4_i2c_apps_clk", + .parent_names = (const char *[]){ "blsp1_qup4_i2c_apps_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_blsp1_uart4_apps_clk = { + .halt_reg = 0x20004, + .clkr = { + .enable_reg = 0x20004, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_blsp1_uart4_apps_clk", + .parent_names = (const char *[]){ "blsp1_uart4_apps_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_blsp1_qup5_spi_apps_clk = { + .halt_reg = 0x21004, + .clkr = { + .enable_reg = 0x21004, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_blsp1_qup5_spi_apps_clk", + .parent_names = (const char *[]){ "blsp1_qup5_spi_apps_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_blsp1_qup5_i2c_apps_clk = { + .halt_reg = 0x21008, + .clkr = { + .enable_reg = 0x21008, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_blsp1_qup5_i2c_apps_clk", + .parent_names = (const char *[]){ "blsp1_qup5_i2c_apps_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_blsp1_uart5_apps_clk = { + .halt_reg = 0x22004, + .clkr = { + .enable_reg = 0x22004, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_blsp1_uart5_apps_clk", + .parent_names = (const char *[]){ "blsp1_uart5_apps_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_blsp1_qup6_spi_apps_clk = { + .halt_reg = 0x23004, + .clkr = { + .enable_reg = 0x23004, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_blsp1_qup6_spi_apps_clk", + .parent_names = (const char *[]){ "blsp1_qup6_spi_apps_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_blsp1_qup6_i2c_apps_clk = { + .halt_reg = 0x23008, + .clkr = { + .enable_reg = 0x23008, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_blsp1_qup6_i2c_apps_clk", + .parent_names = (const char *[]){ "blsp1_qup6_i2c_apps_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_blsp1_uart6_apps_clk = { + .halt_reg = 0x24004, + .clkr = { + .enable_reg = 0x24004, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_blsp1_uart6_apps_clk", + .parent_names = (const char *[]){ "blsp1_uart6_apps_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_blsp2_ahb_clk = { + .halt_reg = 0x25004, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x52004, + .enable_mask = BIT(15), + .hw.init = &(struct clk_init_data){ + .name = "gcc_blsp2_ahb_clk", + .parent_names = (const char *[]){ "periph_noc_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_blsp2_sleep_clk = { + .halt_reg = 0x25008, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x52004, + .enable_mask = BIT(14), + .hw.init = &(struct clk_init_data){ + .name = "gcc_blsp2_sleep_clk", + .parent_names = (const char *[]){ "gcc_sleep_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_blsp2_qup1_spi_apps_clk = { + .halt_reg = 0x26004, + .clkr = { + .enable_reg = 0x26004, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_blsp2_qup1_spi_apps_clk", + .parent_names = (const char *[]){ "blsp2_qup1_spi_apps_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_blsp2_qup1_i2c_apps_clk = { + .halt_reg = 0x26008, + .clkr = { + .enable_reg = 0x26008, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_blsp2_qup1_i2c_apps_clk", + .parent_names = (const char *[]){ "blsp2_qup1_i2c_apps_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_blsp2_uart1_apps_clk = { + .halt_reg = 0x27004, + .clkr = { + .enable_reg = 0x27004, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_blsp2_uart1_apps_clk", + .parent_names = (const char *[]){ "blsp2_uart1_apps_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_blsp2_qup2_spi_apps_clk = { + .halt_reg = 0x28004, + .clkr = { + .enable_reg = 0x28004, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_blsp2_qup2_spi_apps_clk", + .parent_names = (const char *[]){ "blsp2_qup2_spi_apps_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_blsp2_qup2_i2c_apps_clk = { + .halt_reg = 0x28008, + .clkr = { + .enable_reg = 0x28008, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_blsp2_qup2_i2c_apps_clk", + .parent_names = (const char *[]){ "blsp2_qup2_i2c_apps_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_blsp2_uart2_apps_clk = { + .halt_reg = 0x29004, + .clkr = { + .enable_reg = 0x29004, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_blsp2_uart2_apps_clk", + .parent_names = (const char *[]){ "blsp2_uart2_apps_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_blsp2_qup3_spi_apps_clk = { + .halt_reg = 0x2a004, + .clkr = { + .enable_reg = 0x2a004, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_blsp2_qup3_spi_apps_clk", + .parent_names = (const char *[]){ "blsp2_qup3_spi_apps_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_blsp2_qup3_i2c_apps_clk = { + .halt_reg = 0x2a008, + .clkr = { + .enable_reg = 0x2a008, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_blsp2_qup3_i2c_apps_clk", + .parent_names = (const char *[]){ "blsp2_qup3_i2c_apps_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_blsp2_uart3_apps_clk = { + .halt_reg = 0x2b004, + .clkr = { + .enable_reg = 0x2b004, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_blsp2_uart3_apps_clk", + .parent_names = (const char *[]){ "blsp2_uart3_apps_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_blsp2_qup4_spi_apps_clk = { + .halt_reg = 0x2c004, + .clkr = { + .enable_reg = 0x2c004, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_blsp2_qup4_spi_apps_clk", + .parent_names = (const char *[]){ "blsp2_qup4_spi_apps_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_blsp2_qup4_i2c_apps_clk = { + .halt_reg = 0x2c008, + .clkr = { + .enable_reg = 0x2c008, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_blsp2_qup4_i2c_apps_clk", + .parent_names = (const char *[]){ "blsp2_qup4_i2c_apps_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_blsp2_uart4_apps_clk = { + .halt_reg = 0x2d004, + .clkr = { + .enable_reg = 0x2d004, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_blsp2_uart4_apps_clk", + .parent_names = (const char *[]){ "blsp2_uart4_apps_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_blsp2_qup5_spi_apps_clk = { + .halt_reg = 0x2e004, + .clkr = { + .enable_reg = 0x2e004, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_blsp2_qup5_spi_apps_clk", + .parent_names = (const char *[]){ "blsp2_qup5_spi_apps_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_blsp2_qup5_i2c_apps_clk = { + .halt_reg = 0x2e008, + .clkr = { + .enable_reg = 0x2e008, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_blsp2_qup5_i2c_apps_clk", + .parent_names = (const char *[]){ "blsp2_qup5_i2c_apps_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_blsp2_uart5_apps_clk = { + .halt_reg = 0x2f004, + .clkr = { + .enable_reg = 0x2f004, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_blsp2_uart5_apps_clk", + .parent_names = (const char *[]){ "blsp2_uart5_apps_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_blsp2_qup6_spi_apps_clk = { + .halt_reg = 0x30004, + .clkr = { + .enable_reg = 0x30004, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_blsp2_qup6_spi_apps_clk", + .parent_names = (const char *[]){ "blsp2_qup6_spi_apps_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_blsp2_qup6_i2c_apps_clk = { + .halt_reg = 0x30008, + .clkr = { + .enable_reg = 0x30008, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_blsp2_qup6_i2c_apps_clk", + .parent_names = (const char *[]){ "blsp2_qup6_i2c_apps_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_blsp2_uart6_apps_clk = { + .halt_reg = 0x31004, + .clkr = { + .enable_reg = 0x31004, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_blsp2_uart6_apps_clk", + .parent_names = (const char *[]){ "blsp2_uart6_apps_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pdm_ahb_clk = { + .halt_reg = 0x33004, + .clkr = { + .enable_reg = 0x33004, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_pdm_ahb_clk", + .parent_names = (const char *[]){ "periph_noc_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pdm2_clk = { + .halt_reg = 0x3300c, + .clkr = { + .enable_reg = 0x3300c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_pdm2_clk", + .parent_names = (const char *[]){ "pdm2_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_prng_ahb_clk = { + .halt_reg = 0x34004, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x52004, + .enable_mask = BIT(13), + .hw.init = &(struct clk_init_data){ + .name = "gcc_prng_ahb_clk", + .parent_names = (const char *[]){ "config_noc_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_tsif_ahb_clk = { + .halt_reg = 0x36004, + .clkr = { + .enable_reg = 0x36004, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_tsif_ahb_clk", + .parent_names = (const char *[]){ "periph_noc_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_tsif_ref_clk = { + .halt_reg = 0x36008, + .clkr = { + .enable_reg = 0x36008, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_tsif_ref_clk", + .parent_names = (const char *[]){ "tsif_ref_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_tsif_inactivity_timers_clk = { + .halt_reg = 0x3600c, + .clkr = { + .enable_reg = 0x3600c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_tsif_inactivity_timers_clk", + .parent_names = (const char *[]){ "gcc_sleep_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_boot_rom_ahb_clk = { + .halt_reg = 0x38004, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x52004, + .enable_mask = BIT(10), + .hw.init = &(struct clk_init_data){ + .name = "gcc_boot_rom_ahb_clk", + .parent_names = (const char *[]){ "config_noc_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_bimc_gfx_clk = { + .halt_reg = 0x46018, + .clkr = { + .enable_reg = 0x46018, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_bimc_gfx_clk", + .flags = CLK_SET_RATE_PARENT | CLK_IS_ROOT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_hmss_rbcpr_clk = { + .halt_reg = 0x4800c, + .clkr = { + .enable_reg = 0x4800c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_hmss_rbcpr_clk", + .parent_names = (const char *[]){ "hmss_rbcpr_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_gp1_clk = { + .halt_reg = 0x64000, + .clkr = { + .enable_reg = 0x64000, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_gp1_clk", + .parent_names = (const char *[]){ "gp1_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_gp2_clk = { + .halt_reg = 0x65000, + .clkr = { + .enable_reg = 0x65000, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_gp2_clk", + .parent_names = (const char *[]){ "gp2_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_gp3_clk = { + .halt_reg = 0x66000, + .clkr = { + .enable_reg = 0x66000, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_gp3_clk", + .parent_names = (const char *[]){ "gp3_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pcie_0_slv_axi_clk = { + .halt_reg = 0x6b008, + .clkr = { + .enable_reg = 0x6b008, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_pcie_0_slv_axi_clk", + .parent_names = (const char *[]){ "system_noc_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pcie_0_mstr_axi_clk = { + .halt_reg = 0x6b00c, + .clkr = { + .enable_reg = 0x6b00c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_pcie_0_mstr_axi_clk", + .parent_names = (const char *[]){ "system_noc_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pcie_0_cfg_ahb_clk = { + .halt_reg = 0x6b010, + .clkr = { + .enable_reg = 0x6b010, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_pcie_0_cfg_ahb_clk", + .parent_names = (const char *[]){ "config_noc_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pcie_0_aux_clk = { + .halt_reg = 0x6b014, + .clkr = { + .enable_reg = 0x6b014, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_pcie_0_aux_clk", + .parent_names = (const char *[]){ "pcie_aux_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pcie_0_pipe_clk = { + .halt_reg = 0x6b018, + .clkr = { + .enable_reg = 0x6b018, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_pcie_0_pipe_clk", + .parent_names = (const char *[]){ "pcie_0_pipe_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pcie_1_slv_axi_clk = { + .halt_reg = 0x6d008, + .clkr = { + .enable_reg = 0x6d008, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_pcie_1_slv_axi_clk", + .parent_names = (const char *[]){ "system_noc_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pcie_1_mstr_axi_clk = { + .halt_reg = 0x6d00c, + .clkr = { + .enable_reg = 0x6d00c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_pcie_1_mstr_axi_clk", + .parent_names = (const char *[]){ "system_noc_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pcie_1_cfg_ahb_clk = { + .halt_reg = 0x6d010, + .clkr = { + .enable_reg = 0x6d010, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_pcie_1_cfg_ahb_clk", + .parent_names = (const char *[]){ "config_noc_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pcie_1_aux_clk = { + .halt_reg = 0x6d014, + .clkr = { + .enable_reg = 0x6d014, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_pcie_1_aux_clk", + .parent_names = (const char *[]){ "pcie_aux_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pcie_1_pipe_clk = { + .halt_reg = 0x6d018, + .clkr = { + .enable_reg = 0x6d018, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_pcie_1_pipe_clk", + .parent_names = (const char *[]){ "pcie_1_pipe_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pcie_2_slv_axi_clk = { + .halt_reg = 0x6e008, + .clkr = { + .enable_reg = 0x6e008, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_pcie_2_slv_axi_clk", + .parent_names = (const char *[]){ "system_noc_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pcie_2_mstr_axi_clk = { + .halt_reg = 0x6e00c, + .clkr = { + .enable_reg = 0x6e00c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_pcie_2_mstr_axi_clk", + .parent_names = (const char *[]){ "system_noc_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pcie_2_cfg_ahb_clk = { + .halt_reg = 0x6e010, + .clkr = { + .enable_reg = 0x6e010, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_pcie_2_cfg_ahb_clk", + .parent_names = (const char *[]){ "config_noc_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pcie_2_aux_clk = { + .halt_reg = 0x6e014, + .clkr = { + .enable_reg = 0x6e014, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_pcie_2_aux_clk", + .parent_names = (const char *[]){ "pcie_aux_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pcie_2_pipe_clk = { + .halt_reg = 0x6e108, + .clkr = { + .enable_reg = 0x6e108, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_pcie_2_pipe_clk", + .parent_names = (const char *[]){ "pcie_2_pipe_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pcie_phy_cfg_ahb_clk = { + .halt_reg = 0x6f004, + .clkr = { + .enable_reg = 0x6f004, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_pcie_phy_cfg_ahb_clk", + .parent_names = (const char *[]){ "config_noc_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pcie_phy_aux_clk = { + .halt_reg = 0x6f008, + .clkr = { + .enable_reg = 0x6f008, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_pcie_phy_aux_clk", + .parent_names = (const char *[]){ "pcie_aux_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_ufs_axi_clk = { + .halt_reg = 0x75008, + .clkr = { + .enable_reg = 0x75008, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_ufs_axi_clk", + .parent_names = (const char *[]){ "ufs_axi_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_ufs_ahb_clk = { + .halt_reg = 0x7500c, + .clkr = { + .enable_reg = 0x7500c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_ufs_ahb_clk", + .parent_names = (const char *[]){ "config_noc_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_fixed_factor ufs_tx_cfg_clk_src = { + .mult = 1, + .div = 16, + .hw.init = &(struct clk_init_data){ + .name = "ufs_tx_cfg_clk_src", + .parent_names = (const char *[]){ "ufs_axi_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_fixed_factor_ops, + }, +}; + +static struct clk_branch gcc_ufs_tx_cfg_clk = { + .halt_reg = 0x75010, + .clkr = { + .enable_reg = 0x75010, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_ufs_tx_cfg_clk", + .parent_names = (const char *[]){ "ufs_tx_cfg_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_fixed_factor ufs_rx_cfg_clk_src = { + .mult = 1, + .div = 16, + .hw.init = &(struct clk_init_data){ + .name = "ufs_rx_cfg_clk_src", + .parent_names = (const char *[]){ "ufs_axi_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_fixed_factor_ops, + }, +}; + +static struct clk_branch gcc_ufs_rx_cfg_clk = { + .halt_reg = 0x75014, + .clkr = { + .enable_reg = 0x75014, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_ufs_rx_cfg_clk", + .parent_names = (const char *[]){ "ufs_rx_cfg_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_ufs_tx_symbol_0_clk = { + .halt_reg = 0x75018, + .clkr = { + .enable_reg = 0x75018, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_ufs_tx_symbol_0_clk", + .parent_names = (const char *[]){ "ufs_tx_symbol_0_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_ufs_rx_symbol_0_clk = { + .halt_reg = 0x7501c, + .clkr = { + .enable_reg = 0x7501c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_ufs_rx_symbol_0_clk", + .parent_names = (const char *[]){ "ufs_rx_symbol_0_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_ufs_rx_symbol_1_clk = { + .halt_reg = 0x75020, + .clkr = { + .enable_reg = 0x75020, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_ufs_rx_symbol_1_clk", + .parent_names = (const char *[]){ "ufs_rx_symbol_1_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_fixed_factor ufs_ice_core_postdiv_clk_src = { + .mult = 1, + .div = 2, + .hw.init = &(struct clk_init_data){ + .name = "ufs_ice_core_postdiv_clk_src", + .parent_names = (const char *[]){ "ufs_ice_core_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_fixed_factor_ops, + }, +}; + +static struct clk_branch gcc_ufs_unipro_core_clk = { + .halt_reg = 0x7600c, + .clkr = { + .enable_reg = 0x7600c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_ufs_unipro_core_clk", + .parent_names = (const char *[]){ "ufs_ice_core_postdiv_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_ufs_ice_core_clk = { + .halt_reg = 0x76010, + .clkr = { + .enable_reg = 0x76010, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_ufs_ice_core_clk", + .parent_names = (const char *[]){ "ufs_ice_core_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_ufs_sys_clk_core_clk = { + .halt_check = BRANCH_HALT_DELAY, + .clkr = { + .enable_reg = 0x76030, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_ufs_sys_clk_core_clk", + .ops = &clk_branch2_ops, + .flags = CLK_IS_ROOT, + }, + }, +}; + +static struct clk_branch gcc_ufs_tx_symbol_clk_core_clk = { + .halt_check = BRANCH_HALT_DELAY, + .clkr = { + .enable_reg = 0x76034, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_ufs_tx_symbol_clk_core_clk", + .ops = &clk_branch2_ops, + .flags = CLK_IS_ROOT, + }, + }, +}; + +static struct clk_branch gcc_aggre0_snoc_axi_clk = { + .halt_reg = 0x81008, + .clkr = { + .enable_reg = 0x81008, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_aggre0_snoc_axi_clk", + .parent_names = (const char *[]){ "system_noc_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_aggre0_cnoc_ahb_clk = { + .halt_reg = 0x8100c, + .clkr = { + .enable_reg = 0x8100c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_aggre0_cnoc_ahb_clk", + .parent_names = (const char *[]){ "config_noc_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_smmu_aggre0_axi_clk = { + .halt_reg = 0x81014, + .clkr = { + .enable_reg = 0x81014, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_smmu_aggre0_axi_clk", + .parent_names = (const char *[]){ "system_noc_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_smmu_aggre0_ahb_clk = { + .halt_reg = 0x81018, + .clkr = { + .enable_reg = 0x81018, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_smmu_aggre0_ahb_clk", + .parent_names = (const char *[]){ "config_noc_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_aggre1_pnoc_ahb_clk = { + .halt_reg = 0x82014, + .clkr = { + .enable_reg = 0x82014, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_aggre1_pnoc_ahb_clk", + .parent_names = (const char *[]){ "periph_noc_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_aggre2_ufs_axi_clk = { + .halt_reg = 0x83014, + .clkr = { + .enable_reg = 0x83014, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_aggre2_ufs_axi_clk", + .parent_names = (const char *[]){ "ufs_axi_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_aggre2_usb3_axi_clk = { + .halt_reg = 0x83018, + .clkr = { + .enable_reg = 0x83018, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_aggre2_usb3_axi_clk", + .parent_names = (const char *[]){ "usb30_master_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qspi_ahb_clk = { + .halt_reg = 0x8b004, + .clkr = { + .enable_reg = 0x8b004, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_qspi_ahb_clk", + .parent_names = (const char *[]){ "periph_noc_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qspi_ser_clk = { + .halt_reg = 0x8b008, + .clkr = { + .enable_reg = 0x8b008, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_qspi_ser_clk", + .parent_names = (const char *[]){ "qspi_ser_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_usb3_clkref_clk = { + .halt_reg = 0x8800C, + .clkr = { + .enable_reg = 0x8800C, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_usb3_clkref_clk", + .parent_names = (const char *[]){ "xo" }, + .num_parents = 1, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_hdmi_clkref_clk = { + .halt_reg = 0x88000, + .clkr = { + .enable_reg = 0x88000, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_hdmi_clkref_clk", + .parent_names = (const char *[]){ "xo" }, + .num_parents = 1, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_ufs_clkref_clk = { + .halt_reg = 0x88008, + .clkr = { + .enable_reg = 0x88008, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_ufs_clkref_clk", + .parent_names = (const char *[]){ "xo" }, + .num_parents = 1, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pcie_clkref_clk = { + .halt_reg = 0x88010, + .clkr = { + .enable_reg = 0x88010, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_pcie_clkref_clk", + .parent_names = (const char *[]){ "xo" }, + .num_parents = 1, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_rx2_usb2_clkref_clk = { + .halt_reg = 0x88014, + .clkr = { + .enable_reg = 0x88014, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_rx2_usb2_clkref_clk", + .parent_names = (const char *[]){ "xo" }, + .num_parents = 1, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_rx1_usb2_clkref_clk = { + .halt_reg = 0x88018, + .clkr = { + .enable_reg = 0x88018, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_rx1_usb2_clkref_clk", + .parent_names = (const char *[]){ "xo" }, + .num_parents = 1, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_hw *gcc_msm8996_hws[] = { + &xo.hw, + &gpll0_early_div.hw, + &ufs_tx_cfg_clk_src.hw, + &ufs_rx_cfg_clk_src.hw, + &ufs_ice_core_postdiv_clk_src.hw, +}; + +static struct clk_regmap *gcc_msm8996_clocks[] = { + [GPLL0_EARLY] = &gpll0_early.clkr, + [GPLL0] = &gpll0.clkr, + [GPLL4_EARLY] = &gpll4_early.clkr, + [GPLL4] = &gpll4.clkr, + [SYSTEM_NOC_CLK_SRC] = &system_noc_clk_src.clkr, + [CONFIG_NOC_CLK_SRC] = &config_noc_clk_src.clkr, + [PERIPH_NOC_CLK_SRC] = &periph_noc_clk_src.clkr, + [USB30_MASTER_CLK_SRC] = &usb30_master_clk_src.clkr, + [USB30_MOCK_UTMI_CLK_SRC] = &usb30_mock_utmi_clk_src.clkr, + [USB3_PHY_AUX_CLK_SRC] = &usb3_phy_aux_clk_src.clkr, + [USB20_MASTER_CLK_SRC] = &usb20_master_clk_src.clkr, + [USB20_MOCK_UTMI_CLK_SRC] = &usb20_mock_utmi_clk_src.clkr, + [SDCC1_APPS_CLK_SRC] = &sdcc1_apps_clk_src.clkr, + [SDCC1_ICE_CORE_CLK_SRC] = &sdcc1_ice_core_clk_src.clkr, + [SDCC2_APPS_CLK_SRC] = &sdcc2_apps_clk_src.clkr, + [SDCC3_APPS_CLK_SRC] = &sdcc3_apps_clk_src.clkr, + [SDCC4_APPS_CLK_SRC] = &sdcc4_apps_clk_src.clkr, + [BLSP1_QUP1_SPI_APPS_CLK_SRC] = &blsp1_qup1_spi_apps_clk_src.clkr, + [BLSP1_QUP1_I2C_APPS_CLK_SRC] = &blsp1_qup1_i2c_apps_clk_src.clkr, + [BLSP1_UART1_APPS_CLK_SRC] = &blsp1_uart1_apps_clk_src.clkr, + [BLSP1_QUP2_SPI_APPS_CLK_SRC] = &blsp1_qup2_spi_apps_clk_src.clkr, + [BLSP1_QUP2_I2C_APPS_CLK_SRC] = &blsp1_qup2_i2c_apps_clk_src.clkr, + [BLSP1_UART2_APPS_CLK_SRC] = &blsp1_uart2_apps_clk_src.clkr, + [BLSP1_QUP3_SPI_APPS_CLK_SRC] = &blsp1_qup3_spi_apps_clk_src.clkr, + [BLSP1_QUP3_I2C_APPS_CLK_SRC] = &blsp1_qup3_i2c_apps_clk_src.clkr, + [BLSP1_UART3_APPS_CLK_SRC] = &blsp1_uart3_apps_clk_src.clkr, + [BLSP1_QUP4_SPI_APPS_CLK_SRC] = &blsp1_qup4_spi_apps_clk_src.clkr, + [BLSP1_QUP4_I2C_APPS_CLK_SRC] = &blsp1_qup4_i2c_apps_clk_src.clkr, + [BLSP1_UART4_APPS_CLK_SRC] = &blsp1_uart4_apps_clk_src.clkr, + [BLSP1_QUP5_SPI_APPS_CLK_SRC] = &blsp1_qup5_spi_apps_clk_src.clkr, + [BLSP1_QUP5_I2C_APPS_CLK_SRC] = &blsp1_qup5_i2c_apps_clk_src.clkr, + [BLSP1_UART5_APPS_CLK_SRC] = &blsp1_uart5_apps_clk_src.clkr, + [BLSP1_QUP6_SPI_APPS_CLK_SRC] = &blsp1_qup6_spi_apps_clk_src.clkr, + [BLSP1_QUP6_I2C_APPS_CLK_SRC] = &blsp1_qup6_i2c_apps_clk_src.clkr, + [BLSP1_UART6_APPS_CLK_SRC] = &blsp1_uart6_apps_clk_src.clkr, + [BLSP2_QUP1_SPI_APPS_CLK_SRC] = &blsp2_qup1_spi_apps_clk_src.clkr, + [BLSP2_QUP1_I2C_APPS_CLK_SRC] = &blsp2_qup1_i2c_apps_clk_src.clkr, + [BLSP2_UART1_APPS_CLK_SRC] = &blsp2_uart1_apps_clk_src.clkr, + [BLSP2_QUP2_SPI_APPS_CLK_SRC] = &blsp2_qup2_spi_apps_clk_src.clkr, + [BLSP2_QUP2_I2C_APPS_CLK_SRC] = &blsp2_qup2_i2c_apps_clk_src.clkr, + [BLSP2_UART2_APPS_CLK_SRC] = &blsp2_uart2_apps_clk_src.clkr, + [BLSP2_QUP3_SPI_APPS_CLK_SRC] = &blsp2_qup3_spi_apps_clk_src.clkr, + [BLSP2_QUP3_I2C_APPS_CLK_SRC] = &blsp2_qup3_i2c_apps_clk_src.clkr, + [BLSP2_UART3_APPS_CLK_SRC] = &blsp2_uart3_apps_clk_src.clkr, + [BLSP2_QUP4_SPI_APPS_CLK_SRC] = &blsp2_qup4_spi_apps_clk_src.clkr, + [BLSP2_QUP4_I2C_APPS_CLK_SRC] = &blsp2_qup4_i2c_apps_clk_src.clkr, + [BLSP2_UART4_APPS_CLK_SRC] = &blsp2_uart4_apps_clk_src.clkr, + [BLSP2_QUP5_SPI_APPS_CLK_SRC] = &blsp2_qup5_spi_apps_clk_src.clkr, + [BLSP2_QUP5_I2C_APPS_CLK_SRC] = &blsp2_qup5_i2c_apps_clk_src.clkr, + [BLSP2_UART5_APPS_CLK_SRC] = &blsp2_uart5_apps_clk_src.clkr, + [BLSP2_QUP6_SPI_APPS_CLK_SRC] = &blsp2_qup6_spi_apps_clk_src.clkr, + [BLSP2_QUP6_I2C_APPS_CLK_SRC] = &blsp2_qup6_i2c_apps_clk_src.clkr, + [BLSP2_UART6_APPS_CLK_SRC] = &blsp2_uart6_apps_clk_src.clkr, + [PDM2_CLK_SRC] = &pdm2_clk_src.clkr, + [TSIF_REF_CLK_SRC] = &tsif_ref_clk_src.clkr, + [GCC_SLEEP_CLK_SRC] = &gcc_sleep_clk_src.clkr, + [HMSS_RBCPR_CLK_SRC] = &hmss_rbcpr_clk_src.clkr, + [HMSS_GPLL0_CLK_SRC] = &hmss_gpll0_clk_src.clkr, + [GP1_CLK_SRC] = &gp1_clk_src.clkr, + [GP2_CLK_SRC] = &gp2_clk_src.clkr, + [GP3_CLK_SRC] = &gp3_clk_src.clkr, + [PCIE_AUX_CLK_SRC] = &pcie_aux_clk_src.clkr, + [UFS_AXI_CLK_SRC] = &ufs_axi_clk_src.clkr, + [UFS_ICE_CORE_CLK_SRC] = &ufs_ice_core_clk_src.clkr, + [QSPI_SER_CLK_SRC] = &qspi_ser_clk_src.clkr, + [GCC_SYS_NOC_USB3_AXI_CLK] = &gcc_sys_noc_usb3_axi_clk.clkr, + [GCC_SYS_NOC_UFS_AXI_CLK] = &gcc_sys_noc_ufs_axi_clk.clkr, + [GCC_PERIPH_NOC_USB20_AHB_CLK] = &gcc_periph_noc_usb20_ahb_clk.clkr, + [GCC_MMSS_NOC_CFG_AHB_CLK] = &gcc_mmss_noc_cfg_ahb_clk.clkr, + [GCC_MMSS_BIMC_GFX_CLK] = &gcc_mmss_bimc_gfx_clk.clkr, + [GCC_USB30_MASTER_CLK] = &gcc_usb30_master_clk.clkr, + [GCC_USB30_SLEEP_CLK] = &gcc_usb30_sleep_clk.clkr, + [GCC_USB30_MOCK_UTMI_CLK] = &gcc_usb30_mock_utmi_clk.clkr, + [GCC_USB3_PHY_AUX_CLK] = &gcc_usb3_phy_aux_clk.clkr, + [GCC_USB3_PHY_PIPE_CLK] = &gcc_usb3_phy_pipe_clk.clkr, + [GCC_USB20_MASTER_CLK] = &gcc_usb20_master_clk.clkr, + [GCC_USB20_SLEEP_CLK] = &gcc_usb20_sleep_clk.clkr, + [GCC_USB20_MOCK_UTMI_CLK] = &gcc_usb20_mock_utmi_clk.clkr, + [GCC_USB_PHY_CFG_AHB2PHY_CLK] = &gcc_usb_phy_cfg_ahb2phy_clk.clkr, + [GCC_SDCC1_APPS_CLK] = &gcc_sdcc1_apps_clk.clkr, + [GCC_SDCC1_AHB_CLK] = &gcc_sdcc1_ahb_clk.clkr, + [GCC_SDCC1_ICE_CORE_CLK] = &gcc_sdcc1_ice_core_clk.clkr, + [GCC_SDCC2_APPS_CLK] = &gcc_sdcc2_apps_clk.clkr, + [GCC_SDCC2_AHB_CLK] = &gcc_sdcc2_ahb_clk.clkr, + [GCC_SDCC3_APPS_CLK] = &gcc_sdcc3_apps_clk.clkr, + [GCC_SDCC3_AHB_CLK] = &gcc_sdcc3_ahb_clk.clkr, + [GCC_SDCC4_APPS_CLK] = &gcc_sdcc4_apps_clk.clkr, + [GCC_SDCC4_AHB_CLK] = &gcc_sdcc4_ahb_clk.clkr, + [GCC_BLSP1_AHB_CLK] = &gcc_blsp1_ahb_clk.clkr, + [GCC_BLSP1_SLEEP_CLK] = &gcc_blsp1_sleep_clk.clkr, + [GCC_BLSP1_QUP1_SPI_APPS_CLK] = &gcc_blsp1_qup1_spi_apps_clk.clkr, + [GCC_BLSP1_QUP1_I2C_APPS_CLK] = &gcc_blsp1_qup1_i2c_apps_clk.clkr, + [GCC_BLSP1_UART1_APPS_CLK] = &gcc_blsp1_uart1_apps_clk.clkr, + [GCC_BLSP1_QUP2_SPI_APPS_CLK] = &gcc_blsp1_qup2_spi_apps_clk.clkr, + [GCC_BLSP1_QUP2_I2C_APPS_CLK] = &gcc_blsp1_qup2_i2c_apps_clk.clkr, + [GCC_BLSP1_UART2_APPS_CLK] = &gcc_blsp1_uart2_apps_clk.clkr, + [GCC_BLSP1_QUP3_SPI_APPS_CLK] = &gcc_blsp1_qup3_spi_apps_clk.clkr, + [GCC_BLSP1_QUP3_I2C_APPS_CLK] = &gcc_blsp1_qup3_i2c_apps_clk.clkr, + [GCC_BLSP1_UART3_APPS_CLK] = &gcc_blsp1_uart3_apps_clk.clkr, + [GCC_BLSP1_QUP4_SPI_APPS_CLK] = &gcc_blsp1_qup4_spi_apps_clk.clkr, + [GCC_BLSP1_QUP4_I2C_APPS_CLK] = &gcc_blsp1_qup4_i2c_apps_clk.clkr, + [GCC_BLSP1_UART4_APPS_CLK] = &gcc_blsp1_uart4_apps_clk.clkr, + [GCC_BLSP1_QUP5_SPI_APPS_CLK] = &gcc_blsp1_qup5_spi_apps_clk.clkr, + [GCC_BLSP1_QUP5_I2C_APPS_CLK] = &gcc_blsp1_qup5_i2c_apps_clk.clkr, + [GCC_BLSP1_UART5_APPS_CLK] = &gcc_blsp1_uart5_apps_clk.clkr, + [GCC_BLSP1_QUP6_SPI_APPS_CLK] = &gcc_blsp1_qup6_spi_apps_clk.clkr, + [GCC_BLSP1_QUP6_I2C_APPS_CLK] = &gcc_blsp1_qup6_i2c_apps_clk.clkr, + [GCC_BLSP1_UART6_APPS_CLK] = &gcc_blsp1_uart6_apps_clk.clkr, + [GCC_BLSP2_AHB_CLK] = &gcc_blsp2_ahb_clk.clkr, + [GCC_BLSP2_SLEEP_CLK] = &gcc_blsp2_sleep_clk.clkr, + [GCC_BLSP2_QUP1_SPI_APPS_CLK] = &gcc_blsp2_qup1_spi_apps_clk.clkr, + [GCC_BLSP2_QUP1_I2C_APPS_CLK] = &gcc_blsp2_qup1_i2c_apps_clk.clkr, + [GCC_BLSP2_UART1_APPS_CLK] = &gcc_blsp2_uart1_apps_clk.clkr, + [GCC_BLSP2_QUP2_SPI_APPS_CLK] = &gcc_blsp2_qup2_spi_apps_clk.clkr, + [GCC_BLSP2_QUP2_I2C_APPS_CLK] = &gcc_blsp2_qup2_i2c_apps_clk.clkr, + [GCC_BLSP2_UART2_APPS_CLK] = &gcc_blsp2_uart2_apps_clk.clkr, + [GCC_BLSP2_QUP3_SPI_APPS_CLK] = &gcc_blsp2_qup3_spi_apps_clk.clkr, + [GCC_BLSP2_QUP3_I2C_APPS_CLK] = &gcc_blsp2_qup3_i2c_apps_clk.clkr, + [GCC_BLSP2_UART3_APPS_CLK] = &gcc_blsp2_uart3_apps_clk.clkr, + [GCC_BLSP2_QUP4_SPI_APPS_CLK] = &gcc_blsp2_qup4_spi_apps_clk.clkr, + [GCC_BLSP2_QUP4_I2C_APPS_CLK] = &gcc_blsp2_qup4_i2c_apps_clk.clkr, + [GCC_BLSP2_UART4_APPS_CLK] = &gcc_blsp2_uart4_apps_clk.clkr, + [GCC_BLSP2_QUP5_SPI_APPS_CLK] = &gcc_blsp2_qup5_spi_apps_clk.clkr, + [GCC_BLSP2_QUP5_I2C_APPS_CLK] = &gcc_blsp2_qup5_i2c_apps_clk.clkr, + [GCC_BLSP2_UART5_APPS_CLK] = &gcc_blsp2_uart5_apps_clk.clkr, + [GCC_BLSP2_QUP6_SPI_APPS_CLK] = &gcc_blsp2_qup6_spi_apps_clk.clkr, + [GCC_BLSP2_QUP6_I2C_APPS_CLK] = &gcc_blsp2_qup6_i2c_apps_clk.clkr, + [GCC_BLSP2_UART6_APPS_CLK] = &gcc_blsp2_uart6_apps_clk.clkr, + [GCC_PDM_AHB_CLK] = &gcc_pdm_ahb_clk.clkr, + [GCC_PDM2_CLK] = &gcc_pdm2_clk.clkr, + [GCC_PRNG_AHB_CLK] = &gcc_prng_ahb_clk.clkr, + [GCC_TSIF_AHB_CLK] = &gcc_tsif_ahb_clk.clkr, + [GCC_TSIF_REF_CLK] = &gcc_tsif_ref_clk.clkr, + [GCC_TSIF_INACTIVITY_TIMERS_CLK] = &gcc_tsif_inactivity_timers_clk.clkr, + [GCC_BOOT_ROM_AHB_CLK] = &gcc_boot_rom_ahb_clk.clkr, + [GCC_BIMC_GFX_CLK] = &gcc_bimc_gfx_clk.clkr, + [GCC_HMSS_RBCPR_CLK] = &gcc_hmss_rbcpr_clk.clkr, + [GCC_GP1_CLK] = &gcc_gp1_clk.clkr, + [GCC_GP2_CLK] = &gcc_gp2_clk.clkr, + [GCC_GP3_CLK] = &gcc_gp3_clk.clkr, + [GCC_PCIE_0_SLV_AXI_CLK] = &gcc_pcie_0_slv_axi_clk.clkr, + [GCC_PCIE_0_MSTR_AXI_CLK] = &gcc_pcie_0_mstr_axi_clk.clkr, + [GCC_PCIE_0_CFG_AHB_CLK] = &gcc_pcie_0_cfg_ahb_clk.clkr, + [GCC_PCIE_0_AUX_CLK] = &gcc_pcie_0_aux_clk.clkr, + [GCC_PCIE_0_PIPE_CLK] = &gcc_pcie_0_pipe_clk.clkr, + [GCC_PCIE_1_SLV_AXI_CLK] = &gcc_pcie_1_slv_axi_clk.clkr, + [GCC_PCIE_1_MSTR_AXI_CLK] = &gcc_pcie_1_mstr_axi_clk.clkr, + [GCC_PCIE_1_CFG_AHB_CLK] = &gcc_pcie_1_cfg_ahb_clk.clkr, + [GCC_PCIE_1_AUX_CLK] = &gcc_pcie_1_aux_clk.clkr, + [GCC_PCIE_1_PIPE_CLK] = &gcc_pcie_1_pipe_clk.clkr, + [GCC_PCIE_2_SLV_AXI_CLK] = &gcc_pcie_2_slv_axi_clk.clkr, + [GCC_PCIE_2_MSTR_AXI_CLK] = &gcc_pcie_2_mstr_axi_clk.clkr, + [GCC_PCIE_2_CFG_AHB_CLK] = &gcc_pcie_2_cfg_ahb_clk.clkr, + [GCC_PCIE_2_AUX_CLK] = &gcc_pcie_2_aux_clk.clkr, + [GCC_PCIE_2_PIPE_CLK] = &gcc_pcie_2_pipe_clk.clkr, + [GCC_PCIE_PHY_CFG_AHB_CLK] = &gcc_pcie_phy_cfg_ahb_clk.clkr, + [GCC_PCIE_PHY_AUX_CLK] = &gcc_pcie_phy_aux_clk.clkr, + [GCC_UFS_AXI_CLK] = &gcc_ufs_axi_clk.clkr, + [GCC_UFS_AHB_CLK] = &gcc_ufs_ahb_clk.clkr, + [GCC_UFS_TX_CFG_CLK] = &gcc_ufs_tx_cfg_clk.clkr, + [GCC_UFS_RX_CFG_CLK] = &gcc_ufs_rx_cfg_clk.clkr, + [GCC_UFS_TX_SYMBOL_0_CLK] = &gcc_ufs_tx_symbol_0_clk.clkr, + [GCC_UFS_RX_SYMBOL_0_CLK] = &gcc_ufs_rx_symbol_0_clk.clkr, + [GCC_UFS_RX_SYMBOL_1_CLK] = &gcc_ufs_rx_symbol_1_clk.clkr, + [GCC_UFS_UNIPRO_CORE_CLK] = &gcc_ufs_unipro_core_clk.clkr, + [GCC_UFS_ICE_CORE_CLK] = &gcc_ufs_ice_core_clk.clkr, + [GCC_UFS_SYS_CLK_CORE_CLK] = &gcc_ufs_sys_clk_core_clk.clkr, + [GCC_UFS_TX_SYMBOL_CLK_CORE_CLK] = &gcc_ufs_tx_symbol_clk_core_clk.clkr, + [GCC_AGGRE0_SNOC_AXI_CLK] = &gcc_aggre0_snoc_axi_clk.clkr, + [GCC_AGGRE0_CNOC_AHB_CLK] = &gcc_aggre0_cnoc_ahb_clk.clkr, + [GCC_SMMU_AGGRE0_AXI_CLK] = &gcc_smmu_aggre0_axi_clk.clkr, + [GCC_SMMU_AGGRE0_AHB_CLK] = &gcc_smmu_aggre0_ahb_clk.clkr, + [GCC_AGGRE1_PNOC_AHB_CLK] = &gcc_aggre1_pnoc_ahb_clk.clkr, + [GCC_AGGRE2_UFS_AXI_CLK] = &gcc_aggre2_ufs_axi_clk.clkr, + [GCC_AGGRE2_USB3_AXI_CLK] = &gcc_aggre2_usb3_axi_clk.clkr, + [GCC_QSPI_AHB_CLK] = &gcc_qspi_ahb_clk.clkr, + [GCC_QSPI_SER_CLK] = &gcc_qspi_ser_clk.clkr, + [GCC_USB3_CLKREF_CLK] = &gcc_usb3_clkref_clk.clkr, + [GCC_HDMI_CLKREF_CLK] = &gcc_hdmi_clkref_clk.clkr, + [GCC_UFS_CLKREF_CLK] = &gcc_ufs_clkref_clk.clkr, + [GCC_PCIE_CLKREF_CLK] = &gcc_pcie_clkref_clk.clkr, + [GCC_RX2_USB2_CLKREF_CLK] = &gcc_rx2_usb2_clkref_clk.clkr, + [GCC_RX1_USB2_CLKREF_CLK] = &gcc_rx1_usb2_clkref_clk.clkr, +}; + +static const struct qcom_reset_map gcc_msm8996_resets[] = { + [GCC_SYSTEM_NOC_BCR] = { 0x4000 }, + [GCC_CONFIG_NOC_BCR] = { 0x5000 }, + [GCC_PERIPH_NOC_BCR] = { 0x6000 }, + [GCC_IMEM_BCR] = { 0x8000 }, + [GCC_MMSS_BCR] = { 0x9000 }, + [GCC_PIMEM_BCR] = { 0x0a000 }, + [GCC_QDSS_BCR] = { 0x0c000 }, + [GCC_USB_30_BCR] = { 0x0f000 }, + [GCC_USB_20_BCR] = { 0x12000 }, + [GCC_QUSB2PHY_PRIM_BCR] = { 0x12038 }, + [GCC_QUSB2PHY_SEC_BCR] = { 0x1203c }, + [GCC_USB_PHY_CFG_AHB2PHY_BCR] = { 0x6a000 }, + [GCC_SDCC1_BCR] = { 0x13000 }, + [GCC_SDCC2_BCR] = { 0x14000 }, + [GCC_SDCC3_BCR] = { 0x15000 }, + [GCC_SDCC4_BCR] = { 0x16000 }, + [GCC_BLSP1_BCR] = { 0x17000 }, + [GCC_BLSP1_QUP1_BCR] = { 0x19000 }, + [GCC_BLSP1_UART1_BCR] = { 0x1a000 }, + [GCC_BLSP1_QUP2_BCR] = { 0x1b000 }, + [GCC_BLSP1_UART2_BCR] = { 0x1c000 }, + [GCC_BLSP1_QUP3_BCR] = { 0x1d000 }, + [GCC_BLSP1_UART3_BCR] = { 0x1e000 }, + [GCC_BLSP1_QUP4_BCR] = { 0x1f000 }, + [GCC_BLSP1_UART4_BCR] = { 0x20000 }, + [GCC_BLSP1_QUP5_BCR] = { 0x21000 }, + [GCC_BLSP1_UART5_BCR] = { 0x22000 }, + [GCC_BLSP1_QUP6_BCR] = { 0x23000 }, + [GCC_BLSP1_UART6_BCR] = { 0x24000 }, + [GCC_BLSP2_BCR] = { 0x25000 }, + [GCC_BLSP2_QUP1_BCR] = { 0x26000 }, + [GCC_BLSP2_UART1_BCR] = { 0x27000 }, + [GCC_BLSP2_QUP2_BCR] = { 0x28000 }, + [GCC_BLSP2_UART2_BCR] = { 0x29000 }, + [GCC_BLSP2_QUP3_BCR] = { 0x2a000 }, + [GCC_BLSP2_UART3_BCR] = { 0x2b000 }, + [GCC_BLSP2_QUP4_BCR] = { 0x2c000 }, + [GCC_BLSP2_UART4_BCR] = { 0x2d000 }, + [GCC_BLSP2_QUP5_BCR] = { 0x2e000 }, + [GCC_BLSP2_UART5_BCR] = { 0x2f000 }, + [GCC_BLSP2_QUP6_BCR] = { 0x30000 }, + [GCC_BLSP2_UART6_BCR] = { 0x31000 }, + [GCC_PDM_BCR] = { 0x33000 }, + [GCC_PRNG_BCR] = { 0x34000 }, + [GCC_TSIF_BCR] = { 0x36000 }, + [GCC_TCSR_BCR] = { 0x37000 }, + [GCC_BOOT_ROM_BCR] = { 0x38000 }, + [GCC_MSG_RAM_BCR] = { 0x39000 }, + [GCC_TLMM_BCR] = { 0x3a000 }, + [GCC_MPM_BCR] = { 0x3b000 }, + [GCC_SEC_CTRL_BCR] = { 0x3d000 }, + [GCC_SPMI_BCR] = { 0x3f000 }, + [GCC_SPDM_BCR] = { 0x40000 }, + [GCC_CE1_BCR] = { 0x41000 }, + [GCC_BIMC_BCR] = { 0x44000 }, + [GCC_SNOC_BUS_TIMEOUT0_BCR] = { 0x49000 }, + [GCC_SNOC_BUS_TIMEOUT2_BCR] = { 0x49008 }, + [GCC_SNOC_BUS_TIMEOUT1_BCR] = { 0x49010 }, + [GCC_SNOC_BUS_TIMEOUT3_BCR] = { 0x49018 }, + [GCC_SNOC_BUS_TIMEOUT_EXTREF_BCR] = { 0x49020 }, + [GCC_PNOC_BUS_TIMEOUT0_BCR] = { 0x4a000 }, + [GCC_PNOC_BUS_TIMEOUT1_BCR] = { 0x4a008 }, + [GCC_PNOC_BUS_TIMEOUT2_BCR] = { 0x4a010 }, + [GCC_PNOC_BUS_TIMEOUT3_BCR] = { 0x4a018 }, + [GCC_PNOC_BUS_TIMEOUT4_BCR] = { 0x4a020 }, + [GCC_CNOC_BUS_TIMEOUT0_BCR] = { 0x4b000 }, + [GCC_CNOC_BUS_TIMEOUT1_BCR] = { 0x4b008 }, + [GCC_CNOC_BUS_TIMEOUT2_BCR] = { 0x4b010 }, + [GCC_CNOC_BUS_TIMEOUT3_BCR] = { 0x4b018 }, + [GCC_CNOC_BUS_TIMEOUT4_BCR] = { 0x4b020 }, + [GCC_CNOC_BUS_TIMEOUT5_BCR] = { 0x4b028 }, + [GCC_CNOC_BUS_TIMEOUT6_BCR] = { 0x4b030 }, + [GCC_CNOC_BUS_TIMEOUT7_BCR] = { 0x4b038 }, + [GCC_CNOC_BUS_TIMEOUT8_BCR] = { 0x80000 }, + [GCC_CNOC_BUS_TIMEOUT9_BCR] = { 0x80008 }, + [GCC_CNOC_BUS_TIMEOUT_EXTREF_BCR] = { 0x80010 }, + [GCC_APB2JTAG_BCR] = { 0x4c000 }, + [GCC_RBCPR_CX_BCR] = { 0x4e000 }, + [GCC_RBCPR_MX_BCR] = { 0x4f000 }, + [GCC_PCIE_0_BCR] = { 0x6b000 }, + [GCC_PCIE_0_PHY_BCR] = { 0x6c01c }, + [GCC_PCIE_1_BCR] = { 0x6d000 }, + [GCC_PCIE_1_PHY_BCR] = { 0x6d038 }, + [GCC_PCIE_2_BCR] = { 0x6e000 }, + [GCC_PCIE_2_PHY_BCR] = { 0x6e038 }, + [GCC_PCIE_PHY_BCR] = { 0x6f000 }, + [GCC_DCD_BCR] = { 0x70000 }, + [GCC_OBT_ODT_BCR] = { 0x73000 }, + [GCC_UFS_BCR] = { 0x75000 }, + [GCC_SSC_BCR] = { 0x63000 }, + [GCC_VS_BCR] = { 0x7a000 }, + [GCC_AGGRE0_NOC_BCR] = { 0x81000 }, + [GCC_AGGRE1_NOC_BCR] = { 0x82000 }, + [GCC_AGGRE2_NOC_BCR] = { 0x83000 }, + [GCC_DCC_BCR] = { 0x84000 }, + [GCC_IPA_BCR] = { 0x89000 }, + [GCC_QSPI_BCR] = { 0x8b000 }, + [GCC_SKL_BCR] = { 0x8c000 }, + [GCC_MSMPU_BCR] = { 0x8d000 }, + [GCC_MSS_Q6_BCR] = { 0x8e000 }, + [GCC_QREFS_VBG_CAL_BCR] = { 0x88020 }, +}; + +static const struct regmap_config gcc_msm8996_regmap_config = { + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + .max_register = 0x8f010, + .fast_io = true, +}; + +static const struct qcom_cc_desc gcc_msm8996_desc = { + .config = &gcc_msm8996_regmap_config, + .clks = gcc_msm8996_clocks, + .num_clks = ARRAY_SIZE(gcc_msm8996_clocks), + .resets = gcc_msm8996_resets, + .num_resets = ARRAY_SIZE(gcc_msm8996_resets), +}; + +static const struct of_device_id gcc_msm8996_match_table[] = { + { .compatible = "qcom,gcc-msm8996" }, + { } +}; +MODULE_DEVICE_TABLE(of, gcc_msm8996_match_table); + +static int gcc_msm8996_probe(struct platform_device *pdev) +{ + struct clk *clk; + struct device *dev = &pdev->dev; + int i; + struct regmap *regmap; + + regmap = qcom_cc_map(pdev, &gcc_msm8996_desc); + if (IS_ERR(regmap)) + return PTR_ERR(regmap); + + /* + * Set the HMSS_AHB_CLK_SLEEP_ENA bit to allow the hmss_ahb_clk to be + * turned off by hardware during certain apps low power modes. + */ + regmap_update_bits(regmap, 0x52008, BIT(21), BIT(21)); + + for (i = 0; i < ARRAY_SIZE(gcc_msm8996_hws); i++) { + clk = devm_clk_register(dev, gcc_msm8996_hws[i]); + if (IS_ERR(clk)) + return PTR_ERR(clk); + } + + return qcom_cc_really_probe(pdev, &gcc_msm8996_desc, regmap); +} + +static struct platform_driver gcc_msm8996_driver = { + .probe = gcc_msm8996_probe, + .driver = { + .name = "gcc-msm8996", + .of_match_table = gcc_msm8996_match_table, + }, +}; + +static int __init gcc_msm8996_init(void) +{ + return platform_driver_register(&gcc_msm8996_driver); +} +core_initcall(gcc_msm8996_init); + +static void __exit gcc_msm8996_exit(void) +{ + platform_driver_unregister(&gcc_msm8996_driver); +} +module_exit(gcc_msm8996_exit); + +MODULE_DESCRIPTION("QCOM GCC MSM8996 Driver"); +MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("platform:gcc-msm8996"); diff --git a/drivers/clk/qcom/lcc-ipq806x.c b/drivers/clk/qcom/lcc-ipq806x.c index db3998e5e2d8..62e79fadd5f7 100644 --- a/drivers/clk/qcom/lcc-ipq806x.c +++ b/drivers/clk/qcom/lcc-ipq806x.c @@ -419,6 +419,7 @@ static const struct regmap_config lcc_ipq806x_regmap_config = { .val_bits = 32, .max_register = 0xfc, .fast_io = true, + .val_format_endian = REGMAP_ENDIAN_LITTLE, }; static const struct qcom_cc_desc lcc_ipq806x_desc = { diff --git a/drivers/clk/qcom/lcc-msm8960.c b/drivers/clk/qcom/lcc-msm8960.c index 4fcf9d1d233c..bf95bb0ea1b8 100644 --- a/drivers/clk/qcom/lcc-msm8960.c +++ b/drivers/clk/qcom/lcc-msm8960.c @@ -524,6 +524,7 @@ static const struct regmap_config lcc_msm8960_regmap_config = { .val_bits = 32, .max_register = 0xfc, .fast_io = true, + .val_format_endian = REGMAP_ENDIAN_LITTLE, }; static const struct qcom_cc_desc lcc_msm8960_desc = { diff --git a/drivers/clk/qcom/mmcc-apq8084.c b/drivers/clk/qcom/mmcc-apq8084.c index 30777f9f1a43..1e703fda8a0f 100644 --- a/drivers/clk/qcom/mmcc-apq8084.c +++ b/drivers/clk/qcom/mmcc-apq8084.c @@ -3368,6 +3368,7 @@ static const struct regmap_config mmcc_apq8084_regmap_config = { .val_bits = 32, .max_register = 0x5104, .fast_io = true, + .val_format_endian = REGMAP_ENDIAN_LITTLE, }; static const struct qcom_cc_desc mmcc_apq8084_desc = { diff --git a/drivers/clk/qcom/mmcc-msm8960.c b/drivers/clk/qcom/mmcc-msm8960.c index 00e36192a1de..d73a048d3b9d 100644 --- a/drivers/clk/qcom/mmcc-msm8960.c +++ b/drivers/clk/qcom/mmcc-msm8960.c @@ -3029,6 +3029,7 @@ static const struct regmap_config mmcc_msm8960_regmap_config = { .val_bits = 32, .max_register = 0x334, .fast_io = true, + .val_format_endian = REGMAP_ENDIAN_LITTLE, }; static const struct regmap_config mmcc_apq8064_regmap_config = { @@ -3037,6 +3038,7 @@ static const struct regmap_config mmcc_apq8064_regmap_config = { .val_bits = 32, .max_register = 0x350, .fast_io = true, + .val_format_endian = REGMAP_ENDIAN_LITTLE, }; static const struct qcom_cc_desc mmcc_msm8960_desc = { diff --git a/drivers/clk/qcom/mmcc-msm8974.c b/drivers/clk/qcom/mmcc-msm8974.c index 9d790bcadf25..bbe28ed93669 100644 --- a/drivers/clk/qcom/mmcc-msm8974.c +++ b/drivers/clk/qcom/mmcc-msm8974.c @@ -2594,6 +2594,7 @@ static const struct regmap_config mmcc_msm8974_regmap_config = { .val_bits = 32, .max_register = 0x5104, .fast_io = true, + .val_format_endian = REGMAP_ENDIAN_LITTLE, }; static const struct qcom_cc_desc mmcc_msm8974_desc = { diff --git a/drivers/clk/qcom/mmcc-msm8996.c b/drivers/clk/qcom/mmcc-msm8996.c new file mode 100644 index 000000000000..064f3eaa39d0 --- /dev/null +++ b/drivers/clk/qcom/mmcc-msm8996.c @@ -0,0 +1,3217 @@ +/*x + * Copyright (c) 2015, The Linux Foundation. All rights reserved. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include <linux/kernel.h> +#include <linux/bitops.h> +#include <linux/err.h> +#include <linux/platform_device.h> +#include <linux/module.h> +#include <linux/of.h> +#include <linux/of_device.h> +#include <linux/clk-provider.h> +#include <linux/regmap.h> +#include <linux/reset-controller.h> +#include <linux/clk.h> + +#include <dt-bindings/clock/qcom,mmcc-msm8996.h> + +#include "common.h" +#include "clk-regmap.h" +#include "clk-regmap-divider.h" +#include "clk-alpha-pll.h" +#include "clk-rcg.h" +#include "clk-branch.h" +#include "reset.h" + +#define F(f, s, h, m, n) { (f), (s), (2 * (h) - 1), (m), (n) } + +enum { + P_XO, + P_MMPLL0, + P_GPLL0, + P_GPLL0_DIV, + P_MMPLL1, + P_MMPLL9, + P_MMPLL2, + P_MMPLL8, + P_MMPLL3, + P_DSI0PLL, + P_DSI1PLL, + P_MMPLL5, + P_HDMIPLL, + P_DSI0PLL_BYTE, + P_DSI1PLL_BYTE, + P_MMPLL4, +}; + +static const struct parent_map mmss_xo_hdmi_map[] = { + { P_XO, 0 }, + { P_HDMIPLL, 1 } +}; + +static const char * const mmss_xo_hdmi[] = { + "xo", + "hdmipll" +}; + +static const struct parent_map mmss_xo_dsi0pll_dsi1pll_map[] = { + { P_XO, 0 }, + { P_DSI0PLL, 1 }, + { P_DSI1PLL, 2 } +}; + +static const char * const mmss_xo_dsi0pll_dsi1pll[] = { + "xo", + "dsi0pll", + "dsi1pll" +}; + +static const struct parent_map mmss_xo_gpll0_gpll0_div_map[] = { + { P_XO, 0 }, + { P_GPLL0, 5 }, + { P_GPLL0_DIV, 6 } +}; + +static const char * const mmss_xo_gpll0_gpll0_div[] = { + "xo", + "gpll0", + "gpll0_div" +}; + +static const struct parent_map mmss_xo_dsibyte_map[] = { + { P_XO, 0 }, + { P_DSI0PLL_BYTE, 1 }, + { P_DSI1PLL_BYTE, 2 } +}; + +static const char * const mmss_xo_dsibyte[] = { + "xo", + "dsi0pllbyte", + "dsi1pllbyte" +}; + +static const struct parent_map mmss_xo_mmpll0_gpll0_gpll0_div_map[] = { + { P_XO, 0 }, + { P_MMPLL0, 1 }, + { P_GPLL0, 5 }, + { P_GPLL0_DIV, 6 } +}; + +static const char * const mmss_xo_mmpll0_gpll0_gpll0_div[] = { + "xo", + "mmpll0", + "gpll0", + "gpll0_div" +}; + +static const struct parent_map mmss_xo_mmpll0_mmpll1_gpll0_gpll0_div_map[] = { + { P_XO, 0 }, + { P_MMPLL0, 1 }, + { P_MMPLL1, 2 }, + { P_GPLL0, 5 }, + { P_GPLL0_DIV, 6 } +}; + +static const char * const mmss_xo_mmpll0_mmpll1_gpll0_gpll0_div[] = { + "xo", + "mmpll0", + "mmpll1", + "gpll0", + "gpll0_div" +}; + +static const struct parent_map mmss_xo_mmpll0_mmpll3_gpll0_gpll0_div_map[] = { + { P_XO, 0 }, + { P_MMPLL0, 1 }, + { P_MMPLL3, 3 }, + { P_GPLL0, 5 }, + { P_GPLL0_DIV, 6 } +}; + +static const char * const mmss_xo_mmpll0_mmpll3_gpll0_gpll0_div[] = { + "xo", + "mmpll0", + "mmpll3", + "gpll0", + "gpll0_div" +}; + +static const struct parent_map mmss_xo_mmpll0_mmpll5_gpll0_gpll0_div_map[] = { + { P_XO, 0 }, + { P_MMPLL0, 1 }, + { P_MMPLL5, 2 }, + { P_GPLL0, 5 }, + { P_GPLL0_DIV, 6 } +}; + +static const char * const mmss_xo_mmpll0_mmpll5_gpll0_gpll0_div[] = { + "xo", + "mmpll0", + "mmpll5", + "gpll0", + "gpll0_div" +}; + +static const struct parent_map mmss_xo_mmpll0_mmpll4_gpll0_gpll0_div_map[] = { + { P_XO, 0 }, + { P_MMPLL0, 1 }, + { P_MMPLL4, 3 }, + { P_GPLL0, 5 }, + { P_GPLL0_DIV, 6 } +}; + +static const char * const mmss_xo_mmpll0_mmpll4_gpll0_gpll0_div[] = { + "xo", + "mmpll0", + "mmpll4", + "gpll0", + "gpll0_div" +}; + +static const struct parent_map mmss_xo_mmpll0_mmpll9_mmpll2_mmpll8_gpll0_map[] = { + { P_XO, 0 }, + { P_MMPLL0, 1 }, + { P_MMPLL9, 2 }, + { P_MMPLL2, 3 }, + { P_MMPLL8, 4 }, + { P_GPLL0, 5 } +}; + +static const char * const mmss_xo_mmpll0_mmpll9_mmpll2_mmpll8_gpll0[] = { + "xo", + "mmpll0", + "mmpll9", + "mmpll2", + "mmpll8", + "gpll0" +}; + +static const struct parent_map mmss_xo_mmpll0_mmpll9_mmpll2_mmpll8_gpll0_gpll0_div_map[] = { + { P_XO, 0 }, + { P_MMPLL0, 1 }, + { P_MMPLL9, 2 }, + { P_MMPLL2, 3 }, + { P_MMPLL8, 4 }, + { P_GPLL0, 5 }, + { P_GPLL0_DIV, 6 } +}; + +static const char * const mmss_xo_mmpll0_mmpll9_mmpll2_mmpll8_gpll0_gpll0_div[] = { + "xo", + "mmpll0", + "mmpll9", + "mmpll2", + "mmpll8", + "gpll0", + "gpll0_div" +}; + +static const struct parent_map mmss_xo_mmpll0_mmpll1_mmpll4_mmpll3_gpll0_gpll0_div_map[] = { + { P_XO, 0 }, + { P_MMPLL0, 1 }, + { P_MMPLL1, 2 }, + { P_MMPLL4, 3 }, + { P_MMPLL3, 4 }, + { P_GPLL0, 5 }, + { P_GPLL0_DIV, 6 } +}; + +static const char * const mmss_xo_mmpll0_mmpll1_mmpll4_mmpll3_gpll0_gpll0_div[] = { + "xo", + "mmpll0", + "mmpll1", + "mmpll4", + "mmpll3", + "gpll0", + "gpll0_div" +}; + +static struct clk_fixed_factor gpll0_div = { + .mult = 1, + .div = 2, + .hw.init = &(struct clk_init_data){ + .name = "gpll0_div", + .parent_names = (const char *[]){ "gpll0" }, + .num_parents = 1, + .ops = &clk_fixed_factor_ops, + }, +}; + +static struct pll_vco mmpll_p_vco[] = { + { 250000000, 500000000, 3 }, + { 500000000, 1000000000, 2 }, + { 1000000000, 1500000000, 1 }, + { 1500000000, 2000000000, 0 }, +}; + +static struct pll_vco mmpll_gfx_vco[] = { + { 400000000, 1000000000, 2 }, + { 1000000000, 1500000000, 1 }, + { 1500000000, 2000000000, 0 }, +}; + +static struct pll_vco mmpll_t_vco[] = { + { 500000000, 1500000000, 0 }, +}; + +static struct clk_alpha_pll mmpll0_early = { + .offset = 0x0, + .vco_table = mmpll_p_vco, + .num_vco = ARRAY_SIZE(mmpll_p_vco), + .clkr = { + .enable_reg = 0x100, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "mmpll0_early", + .parent_names = (const char *[]){ "xo" }, + .num_parents = 1, + .ops = &clk_alpha_pll_ops, + }, + }, +}; + +static struct clk_alpha_pll_postdiv mmpll0 = { + .offset = 0x0, + .width = 4, + .clkr.hw.init = &(struct clk_init_data){ + .name = "mmpll0", + .parent_names = (const char *[]){ "mmpll0_early" }, + .num_parents = 1, + .ops = &clk_alpha_pll_postdiv_ops, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_alpha_pll mmpll1_early = { + .offset = 0x30, + .vco_table = mmpll_p_vco, + .num_vco = ARRAY_SIZE(mmpll_p_vco), + .clkr = { + .enable_reg = 0x100, + .enable_mask = BIT(1), + .hw.init = &(struct clk_init_data){ + .name = "mmpll1_early", + .parent_names = (const char *[]){ "xo" }, + .num_parents = 1, + .ops = &clk_alpha_pll_ops, + } + }, +}; + +static struct clk_alpha_pll_postdiv mmpll1 = { + .offset = 0x30, + .width = 4, + .clkr.hw.init = &(struct clk_init_data){ + .name = "mmpll1", + .parent_names = (const char *[]){ "mmpll1_early" }, + .num_parents = 1, + .ops = &clk_alpha_pll_postdiv_ops, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_alpha_pll mmpll2_early = { + .offset = 0x4100, + .vco_table = mmpll_gfx_vco, + .num_vco = ARRAY_SIZE(mmpll_gfx_vco), + .clkr.hw.init = &(struct clk_init_data){ + .name = "mmpll2_early", + .parent_names = (const char *[]){ "xo" }, + .num_parents = 1, + .ops = &clk_alpha_pll_ops, + }, +}; + +static struct clk_alpha_pll_postdiv mmpll2 = { + .offset = 0x4100, + .width = 4, + .clkr.hw.init = &(struct clk_init_data){ + .name = "mmpll2", + .parent_names = (const char *[]){ "mmpll2_early" }, + .num_parents = 1, + .ops = &clk_alpha_pll_postdiv_ops, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_alpha_pll mmpll3_early = { + .offset = 0x60, + .vco_table = mmpll_p_vco, + .num_vco = ARRAY_SIZE(mmpll_p_vco), + .clkr.hw.init = &(struct clk_init_data){ + .name = "mmpll3_early", + .parent_names = (const char *[]){ "xo" }, + .num_parents = 1, + .ops = &clk_alpha_pll_ops, + }, +}; + +static struct clk_alpha_pll_postdiv mmpll3 = { + .offset = 0x60, + .width = 4, + .clkr.hw.init = &(struct clk_init_data){ + .name = "mmpll3", + .parent_names = (const char *[]){ "mmpll3_early" }, + .num_parents = 1, + .ops = &clk_alpha_pll_postdiv_ops, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_alpha_pll mmpll4_early = { + .offset = 0x90, + .vco_table = mmpll_t_vco, + .num_vco = ARRAY_SIZE(mmpll_t_vco), + .clkr.hw.init = &(struct clk_init_data){ + .name = "mmpll4_early", + .parent_names = (const char *[]){ "xo" }, + .num_parents = 1, + .ops = &clk_alpha_pll_ops, + }, +}; + +static struct clk_alpha_pll_postdiv mmpll4 = { + .offset = 0x90, + .width = 2, + .clkr.hw.init = &(struct clk_init_data){ + .name = "mmpll4", + .parent_names = (const char *[]){ "mmpll4_early" }, + .num_parents = 1, + .ops = &clk_alpha_pll_postdiv_ops, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_alpha_pll mmpll5_early = { + .offset = 0xc0, + .vco_table = mmpll_p_vco, + .num_vco = ARRAY_SIZE(mmpll_p_vco), + .clkr.hw.init = &(struct clk_init_data){ + .name = "mmpll5_early", + .parent_names = (const char *[]){ "xo" }, + .num_parents = 1, + .ops = &clk_alpha_pll_ops, + }, +}; + +static struct clk_alpha_pll_postdiv mmpll5 = { + .offset = 0xc0, + .width = 4, + .clkr.hw.init = &(struct clk_init_data){ + .name = "mmpll5", + .parent_names = (const char *[]){ "mmpll5_early" }, + .num_parents = 1, + .ops = &clk_alpha_pll_postdiv_ops, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_alpha_pll mmpll8_early = { + .offset = 0x4130, + .vco_table = mmpll_gfx_vco, + .num_vco = ARRAY_SIZE(mmpll_gfx_vco), + .clkr.hw.init = &(struct clk_init_data){ + .name = "mmpll8_early", + .parent_names = (const char *[]){ "xo" }, + .num_parents = 1, + .ops = &clk_alpha_pll_ops, + }, +}; + +static struct clk_alpha_pll_postdiv mmpll8 = { + .offset = 0x4130, + .width = 4, + .clkr.hw.init = &(struct clk_init_data){ + .name = "mmpll8", + .parent_names = (const char *[]){ "mmpll8_early" }, + .num_parents = 1, + .ops = &clk_alpha_pll_postdiv_ops, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_alpha_pll mmpll9_early = { + .offset = 0x4200, + .vco_table = mmpll_t_vco, + .num_vco = ARRAY_SIZE(mmpll_t_vco), + .clkr.hw.init = &(struct clk_init_data){ + .name = "mmpll9_early", + .parent_names = (const char *[]){ "xo" }, + .num_parents = 1, + .ops = &clk_alpha_pll_ops, + }, +}; + +static struct clk_alpha_pll_postdiv mmpll9 = { + .offset = 0x4200, + .width = 2, + .clkr.hw.init = &(struct clk_init_data){ + .name = "mmpll9", + .parent_names = (const char *[]){ "mmpll9_early" }, + .num_parents = 1, + .ops = &clk_alpha_pll_postdiv_ops, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static const struct freq_tbl ftbl_ahb_clk_src[] = { + F(19200000, P_XO, 1, 0, 0), + F(40000000, P_GPLL0_DIV, 7.5, 0, 0), + F(80000000, P_MMPLL0, 10, 0, 0), + { } +}; + +static struct clk_rcg2 ahb_clk_src = { + .cmd_rcgr = 0x5000, + .hid_width = 5, + .parent_map = mmss_xo_mmpll0_gpll0_gpll0_div_map, + .freq_tbl = ftbl_ahb_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "ahb_clk_src", + .parent_names = mmss_xo_mmpll0_gpll0_gpll0_div, + .num_parents = 4, + .ops = &clk_rcg2_ops, + }, +}; + +static const struct freq_tbl ftbl_axi_clk_src[] = { + F(19200000, P_XO, 1, 0, 0), + F(75000000, P_GPLL0_DIV, 4, 0, 0), + F(100000000, P_GPLL0, 6, 0, 0), + F(171430000, P_GPLL0, 3.5, 0, 0), + F(200000000, P_GPLL0, 3, 0, 0), + F(320000000, P_MMPLL0, 2.5, 0, 0), + F(400000000, P_MMPLL0, 2, 0, 0), + { } +}; + +static struct clk_rcg2 axi_clk_src = { + .cmd_rcgr = 0x5040, + .hid_width = 5, + .parent_map = mmss_xo_mmpll0_mmpll1_gpll0_gpll0_div_map, + .freq_tbl = ftbl_axi_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "axi_clk_src", + .parent_names = mmss_xo_mmpll0_mmpll1_gpll0_gpll0_div, + .num_parents = 5, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 maxi_clk_src = { + .cmd_rcgr = 0x5090, + .hid_width = 5, + .parent_map = mmss_xo_mmpll0_mmpll1_gpll0_gpll0_div_map, + .freq_tbl = ftbl_axi_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "maxi_clk_src", + .parent_names = mmss_xo_mmpll0_mmpll1_gpll0_gpll0_div, + .num_parents = 5, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 gfx3d_clk_src = { + .cmd_rcgr = 0x4000, + .hid_width = 5, + .parent_map = mmss_xo_mmpll0_mmpll9_mmpll2_mmpll8_gpll0_map, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gfx3d_clk_src", + .parent_names = mmss_xo_mmpll0_mmpll9_mmpll2_mmpll8_gpll0, + .num_parents = 6, + .ops = &clk_gfx3d_ops, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static const struct freq_tbl ftbl_rbbmtimer_clk_src[] = { + F(19200000, P_XO, 1, 0, 0), + { } +}; + +static struct clk_rcg2 rbbmtimer_clk_src = { + .cmd_rcgr = 0x4090, + .hid_width = 5, + .parent_map = mmss_xo_mmpll0_gpll0_gpll0_div_map, + .freq_tbl = ftbl_rbbmtimer_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "rbbmtimer_clk_src", + .parent_names = mmss_xo_mmpll0_gpll0_gpll0_div, + .num_parents = 4, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 isense_clk_src = { + .cmd_rcgr = 0x4010, + .hid_width = 5, + .parent_map = mmss_xo_mmpll0_mmpll9_mmpll2_mmpll8_gpll0_gpll0_div_map, + .clkr.hw.init = &(struct clk_init_data){ + .name = "isense_clk_src", + .parent_names = mmss_xo_mmpll0_mmpll9_mmpll2_mmpll8_gpll0_gpll0_div, + .num_parents = 7, + .ops = &clk_rcg2_ops, + }, +}; + +static const struct freq_tbl ftbl_rbcpr_clk_src[] = { + F(19200000, P_XO, 1, 0, 0), + F(50000000, P_GPLL0, 12, 0, 0), + { } +}; + +static struct clk_rcg2 rbcpr_clk_src = { + .cmd_rcgr = 0x4060, + .hid_width = 5, + .parent_map = mmss_xo_mmpll0_gpll0_gpll0_div_map, + .freq_tbl = ftbl_rbcpr_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "rbcpr_clk_src", + .parent_names = mmss_xo_mmpll0_gpll0_gpll0_div, + .num_parents = 4, + .ops = &clk_rcg2_ops, + }, +}; + +static const struct freq_tbl ftbl_video_core_clk_src[] = { + F(75000000, P_GPLL0_DIV, 4, 0, 0), + F(150000000, P_GPLL0, 4, 0, 0), + F(346666667, P_MMPLL3, 3, 0, 0), + F(520000000, P_MMPLL3, 2, 0, 0), + { } +}; + +static struct clk_rcg2 video_core_clk_src = { + .cmd_rcgr = 0x1000, + .mnd_width = 8, + .hid_width = 5, + .parent_map = mmss_xo_mmpll0_mmpll3_gpll0_gpll0_div_map, + .freq_tbl = ftbl_video_core_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "video_core_clk_src", + .parent_names = mmss_xo_mmpll0_mmpll3_gpll0_gpll0_div, + .num_parents = 5, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 video_subcore0_clk_src = { + .cmd_rcgr = 0x1060, + .mnd_width = 8, + .hid_width = 5, + .parent_map = mmss_xo_mmpll0_mmpll3_gpll0_gpll0_div_map, + .freq_tbl = ftbl_video_core_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "video_subcore0_clk_src", + .parent_names = mmss_xo_mmpll0_mmpll3_gpll0_gpll0_div, + .num_parents = 5, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 video_subcore1_clk_src = { + .cmd_rcgr = 0x1080, + .mnd_width = 8, + .hid_width = 5, + .parent_map = mmss_xo_mmpll0_mmpll3_gpll0_gpll0_div_map, + .freq_tbl = ftbl_video_core_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "video_subcore1_clk_src", + .parent_names = mmss_xo_mmpll0_mmpll3_gpll0_gpll0_div, + .num_parents = 5, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 pclk0_clk_src = { + .cmd_rcgr = 0x2000, + .mnd_width = 8, + .hid_width = 5, + .parent_map = mmss_xo_dsi0pll_dsi1pll_map, + .clkr.hw.init = &(struct clk_init_data){ + .name = "pclk0_clk_src", + .parent_names = mmss_xo_dsi0pll_dsi1pll, + .num_parents = 3, + .ops = &clk_pixel_ops, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_rcg2 pclk1_clk_src = { + .cmd_rcgr = 0x2020, + .mnd_width = 8, + .hid_width = 5, + .parent_map = mmss_xo_dsi0pll_dsi1pll_map, + .clkr.hw.init = &(struct clk_init_data){ + .name = "pclk1_clk_src", + .parent_names = mmss_xo_dsi0pll_dsi1pll, + .num_parents = 3, + .ops = &clk_pixel_ops, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static const struct freq_tbl ftbl_mdp_clk_src[] = { + F(85714286, P_GPLL0, 7, 0, 0), + F(100000000, P_GPLL0, 6, 0, 0), + F(150000000, P_GPLL0, 4, 0, 0), + F(171428571, P_GPLL0, 3.5, 0, 0), + F(200000000, P_GPLL0, 3, 0, 0), + F(275000000, P_MMPLL5, 3, 0, 0), + F(300000000, P_GPLL0, 2, 0, 0), + F(330000000, P_MMPLL5, 2.5, 0, 0), + F(412500000, P_MMPLL5, 2, 0, 0), + { } +}; + +static struct clk_rcg2 mdp_clk_src = { + .cmd_rcgr = 0x2040, + .hid_width = 5, + .parent_map = mmss_xo_mmpll0_mmpll5_gpll0_gpll0_div_map, + .freq_tbl = ftbl_mdp_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "mdp_clk_src", + .parent_names = mmss_xo_mmpll0_mmpll5_gpll0_gpll0_div, + .num_parents = 5, + .ops = &clk_rcg2_ops, + }, +}; + +static struct freq_tbl extpclk_freq_tbl[] = { + { .src = P_HDMIPLL }, + { } +}; + +static struct clk_rcg2 extpclk_clk_src = { + .cmd_rcgr = 0x2060, + .hid_width = 5, + .parent_map = mmss_xo_hdmi_map, + .freq_tbl = extpclk_freq_tbl, + .clkr.hw.init = &(struct clk_init_data){ + .name = "extpclk_clk_src", + .parent_names = mmss_xo_hdmi, + .num_parents = 2, + .ops = &clk_byte_ops, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct freq_tbl ftbl_mdss_vsync_clk[] = { + F(19200000, P_XO, 1, 0, 0), + { } +}; + +static struct clk_rcg2 vsync_clk_src = { + .cmd_rcgr = 0x2080, + .hid_width = 5, + .parent_map = mmss_xo_gpll0_gpll0_div_map, + .freq_tbl = ftbl_mdss_vsync_clk, + .clkr.hw.init = &(struct clk_init_data){ + .name = "vsync_clk_src", + .parent_names = mmss_xo_gpll0_gpll0_div, + .num_parents = 3, + .ops = &clk_rcg2_ops, + }, +}; + +static struct freq_tbl ftbl_mdss_hdmi_clk[] = { + F(19200000, P_XO, 1, 0, 0), + { } +}; + +static struct clk_rcg2 hdmi_clk_src = { + .cmd_rcgr = 0x2100, + .hid_width = 5, + .parent_map = mmss_xo_gpll0_gpll0_div_map, + .freq_tbl = ftbl_mdss_hdmi_clk, + .clkr.hw.init = &(struct clk_init_data){ + .name = "hdmi_clk_src", + .parent_names = mmss_xo_gpll0_gpll0_div, + .num_parents = 3, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 byte0_clk_src = { + .cmd_rcgr = 0x2120, + .hid_width = 5, + .parent_map = mmss_xo_dsibyte_map, + .clkr.hw.init = &(struct clk_init_data){ + .name = "byte0_clk_src", + .parent_names = mmss_xo_dsibyte, + .num_parents = 3, + .ops = &clk_byte2_ops, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_rcg2 byte1_clk_src = { + .cmd_rcgr = 0x2140, + .hid_width = 5, + .parent_map = mmss_xo_dsibyte_map, + .clkr.hw.init = &(struct clk_init_data){ + .name = "byte1_clk_src", + .parent_names = mmss_xo_dsibyte, + .num_parents = 3, + .ops = &clk_byte2_ops, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct freq_tbl ftbl_mdss_esc0_1_clk[] = { + F(19200000, P_XO, 1, 0, 0), + { } +}; + +static struct clk_rcg2 esc0_clk_src = { + .cmd_rcgr = 0x2160, + .hid_width = 5, + .parent_map = mmss_xo_dsibyte_map, + .freq_tbl = ftbl_mdss_esc0_1_clk, + .clkr.hw.init = &(struct clk_init_data){ + .name = "esc0_clk_src", + .parent_names = mmss_xo_dsibyte, + .num_parents = 3, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 esc1_clk_src = { + .cmd_rcgr = 0x2180, + .hid_width = 5, + .parent_map = mmss_xo_dsibyte_map, + .freq_tbl = ftbl_mdss_esc0_1_clk, + .clkr.hw.init = &(struct clk_init_data){ + .name = "esc1_clk_src", + .parent_names = mmss_xo_dsibyte, + .num_parents = 3, + .ops = &clk_rcg2_ops, + }, +}; + +static const struct freq_tbl ftbl_camss_gp0_clk_src[] = { + F(10000, P_XO, 16, 1, 120), + F(24000, P_XO, 16, 1, 50), + F(6000000, P_GPLL0_DIV, 10, 1, 5), + F(12000000, P_GPLL0_DIV, 1, 1, 25), + F(13000000, P_GPLL0_DIV, 2, 13, 150), + F(24000000, P_GPLL0_DIV, 1, 2, 25), + { } +}; + +static struct clk_rcg2 camss_gp0_clk_src = { + .cmd_rcgr = 0x3420, + .mnd_width = 8, + .hid_width = 5, + .parent_map = mmss_xo_mmpll0_mmpll4_gpll0_gpll0_div_map, + .freq_tbl = ftbl_camss_gp0_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "camss_gp0_clk_src", + .parent_names = mmss_xo_mmpll0_mmpll4_gpll0_gpll0_div, + .num_parents = 5, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 camss_gp1_clk_src = { + .cmd_rcgr = 0x3450, + .mnd_width = 8, + .hid_width = 5, + .parent_map = mmss_xo_mmpll0_mmpll4_gpll0_gpll0_div_map, + .freq_tbl = ftbl_camss_gp0_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "camss_gp1_clk_src", + .parent_names = mmss_xo_mmpll0_mmpll4_gpll0_gpll0_div, + .num_parents = 5, + .ops = &clk_rcg2_ops, + }, +}; + +static const struct freq_tbl ftbl_mclk0_clk_src[] = { + F(4800000, P_XO, 4, 0, 0), + F(6000000, P_GPLL0_DIV, 10, 1, 5), + F(8000000, P_GPLL0_DIV, 1, 2, 75), + F(9600000, P_XO, 2, 0, 0), + F(16666667, P_GPLL0_DIV, 2, 1, 9), + F(19200000, P_XO, 1, 0, 0), + F(24000000, P_GPLL0_DIV, 1, 2, 25), + F(33333333, P_GPLL0_DIV, 1, 1, 9), + F(48000000, P_GPLL0, 1, 2, 25), + F(66666667, P_GPLL0, 1, 1, 9), + { } +}; + +static struct clk_rcg2 mclk0_clk_src = { + .cmd_rcgr = 0x3360, + .mnd_width = 8, + .hid_width = 5, + .parent_map = mmss_xo_mmpll0_mmpll4_gpll0_gpll0_div_map, + .freq_tbl = ftbl_mclk0_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "mclk0_clk_src", + .parent_names = mmss_xo_mmpll0_mmpll4_gpll0_gpll0_div, + .num_parents = 5, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 mclk1_clk_src = { + .cmd_rcgr = 0x3390, + .mnd_width = 8, + .hid_width = 5, + .parent_map = mmss_xo_mmpll0_mmpll4_gpll0_gpll0_div_map, + .freq_tbl = ftbl_mclk0_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "mclk1_clk_src", + .parent_names = mmss_xo_mmpll0_mmpll4_gpll0_gpll0_div, + .num_parents = 5, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 mclk2_clk_src = { + .cmd_rcgr = 0x33c0, + .mnd_width = 8, + .hid_width = 5, + .parent_map = mmss_xo_mmpll0_mmpll4_gpll0_gpll0_div_map, + .freq_tbl = ftbl_mclk0_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "mclk2_clk_src", + .parent_names = mmss_xo_mmpll0_mmpll4_gpll0_gpll0_div, + .num_parents = 5, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 mclk3_clk_src = { + .cmd_rcgr = 0x33f0, + .mnd_width = 8, + .hid_width = 5, + .parent_map = mmss_xo_mmpll0_mmpll4_gpll0_gpll0_div_map, + .freq_tbl = ftbl_mclk0_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "mclk3_clk_src", + .parent_names = mmss_xo_mmpll0_mmpll4_gpll0_gpll0_div, + .num_parents = 5, + .ops = &clk_rcg2_ops, + }, +}; + +static const struct freq_tbl ftbl_cci_clk_src[] = { + F(19200000, P_XO, 1, 0, 0), + F(37500000, P_GPLL0, 16, 0, 0), + F(50000000, P_GPLL0, 12, 0, 0), + F(100000000, P_GPLL0, 6, 0, 0), + { } +}; + +static struct clk_rcg2 cci_clk_src = { + .cmd_rcgr = 0x3300, + .mnd_width = 8, + .hid_width = 5, + .parent_map = mmss_xo_mmpll0_mmpll4_gpll0_gpll0_div_map, + .freq_tbl = ftbl_cci_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "cci_clk_src", + .parent_names = mmss_xo_mmpll0_mmpll4_gpll0_gpll0_div, + .num_parents = 5, + .ops = &clk_rcg2_ops, + }, +}; + +static const struct freq_tbl ftbl_csi0phytimer_clk_src[] = { + F(100000000, P_GPLL0_DIV, 3, 0, 0), + F(200000000, P_GPLL0, 3, 0, 0), + F(266666667, P_MMPLL0, 3, 0, 0), + { } +}; + +static struct clk_rcg2 csi0phytimer_clk_src = { + .cmd_rcgr = 0x3000, + .hid_width = 5, + .parent_map = mmss_xo_mmpll0_mmpll1_mmpll4_mmpll3_gpll0_gpll0_div_map, + .freq_tbl = ftbl_csi0phytimer_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "csi0phytimer_clk_src", + .parent_names = mmss_xo_mmpll0_mmpll1_mmpll4_mmpll3_gpll0_gpll0_div, + .num_parents = 7, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 csi1phytimer_clk_src = { + .cmd_rcgr = 0x3030, + .hid_width = 5, + .parent_map = mmss_xo_mmpll0_mmpll1_mmpll4_mmpll3_gpll0_gpll0_div_map, + .freq_tbl = ftbl_csi0phytimer_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "csi1phytimer_clk_src", + .parent_names = mmss_xo_mmpll0_mmpll1_mmpll4_mmpll3_gpll0_gpll0_div, + .num_parents = 7, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 csi2phytimer_clk_src = { + .cmd_rcgr = 0x3060, + .hid_width = 5, + .parent_map = mmss_xo_mmpll0_mmpll1_mmpll4_mmpll3_gpll0_gpll0_div_map, + .freq_tbl = ftbl_csi0phytimer_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "csi2phytimer_clk_src", + .parent_names = mmss_xo_mmpll0_mmpll1_mmpll4_mmpll3_gpll0_gpll0_div, + .num_parents = 7, + .ops = &clk_rcg2_ops, + }, +}; + +static const struct freq_tbl ftbl_csiphy0_3p_clk_src[] = { + F(100000000, P_GPLL0_DIV, 3, 0, 0), + F(200000000, P_GPLL0, 3, 0, 0), + F(320000000, P_MMPLL4, 3, 0, 0), + F(384000000, P_MMPLL4, 2.5, 0, 0), + { } +}; + +static struct clk_rcg2 csiphy0_3p_clk_src = { + .cmd_rcgr = 0x3240, + .hid_width = 5, + .parent_map = mmss_xo_mmpll0_mmpll1_mmpll4_mmpll3_gpll0_gpll0_div_map, + .freq_tbl = ftbl_csiphy0_3p_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "csiphy0_3p_clk_src", + .parent_names = mmss_xo_mmpll0_mmpll1_mmpll4_mmpll3_gpll0_gpll0_div, + .num_parents = 7, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 csiphy1_3p_clk_src = { + .cmd_rcgr = 0x3260, + .hid_width = 5, + .parent_map = mmss_xo_mmpll0_mmpll1_mmpll4_mmpll3_gpll0_gpll0_div_map, + .freq_tbl = ftbl_csiphy0_3p_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "csiphy1_3p_clk_src", + .parent_names = mmss_xo_mmpll0_mmpll1_mmpll4_mmpll3_gpll0_gpll0_div, + .num_parents = 7, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 csiphy2_3p_clk_src = { + .cmd_rcgr = 0x3280, + .hid_width = 5, + .parent_map = mmss_xo_mmpll0_mmpll1_mmpll4_mmpll3_gpll0_gpll0_div_map, + .freq_tbl = ftbl_csiphy0_3p_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "csiphy2_3p_clk_src", + .parent_names = mmss_xo_mmpll0_mmpll1_mmpll4_mmpll3_gpll0_gpll0_div, + .num_parents = 7, + .ops = &clk_rcg2_ops, + }, +}; + +static const struct freq_tbl ftbl_jpeg0_clk_src[] = { + F(75000000, P_GPLL0_DIV, 4, 0, 0), + F(150000000, P_GPLL0, 4, 0, 0), + F(228571429, P_MMPLL0, 3.5, 0, 0), + F(266666667, P_MMPLL0, 3, 0, 0), + F(320000000, P_MMPLL0, 2.5, 0, 0), + F(480000000, P_MMPLL4, 2, 0, 0), + { } +}; + +static struct clk_rcg2 jpeg0_clk_src = { + .cmd_rcgr = 0x3500, + .hid_width = 5, + .parent_map = mmss_xo_mmpll0_mmpll1_mmpll4_mmpll3_gpll0_gpll0_div_map, + .freq_tbl = ftbl_jpeg0_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "jpeg0_clk_src", + .parent_names = mmss_xo_mmpll0_mmpll1_mmpll4_mmpll3_gpll0_gpll0_div, + .num_parents = 7, + .ops = &clk_rcg2_ops, + }, +}; + +static const struct freq_tbl ftbl_jpeg2_clk_src[] = { + F(75000000, P_GPLL0_DIV, 4, 0, 0), + F(150000000, P_GPLL0, 4, 0, 0), + F(228571429, P_MMPLL0, 3.5, 0, 0), + F(266666667, P_MMPLL0, 3, 0, 0), + F(320000000, P_MMPLL0, 2.5, 0, 0), + { } +}; + +static struct clk_rcg2 jpeg2_clk_src = { + .cmd_rcgr = 0x3540, + .hid_width = 5, + .parent_map = mmss_xo_mmpll0_mmpll1_mmpll4_mmpll3_gpll0_gpll0_div_map, + .freq_tbl = ftbl_jpeg2_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "jpeg2_clk_src", + .parent_names = mmss_xo_mmpll0_mmpll1_mmpll4_mmpll3_gpll0_gpll0_div, + .num_parents = 7, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 jpeg_dma_clk_src = { + .cmd_rcgr = 0x3560, + .hid_width = 5, + .parent_map = mmss_xo_mmpll0_mmpll1_mmpll4_mmpll3_gpll0_gpll0_div_map, + .freq_tbl = ftbl_jpeg0_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "jpeg_dma_clk_src", + .parent_names = mmss_xo_mmpll0_mmpll1_mmpll4_mmpll3_gpll0_gpll0_div, + .num_parents = 7, + .ops = &clk_rcg2_ops, + }, +}; + +static const struct freq_tbl ftbl_vfe0_clk_src[] = { + F(75000000, P_GPLL0_DIV, 4, 0, 0), + F(100000000, P_GPLL0_DIV, 3, 0, 0), + F(300000000, P_GPLL0, 2, 0, 0), + F(320000000, P_MMPLL0, 2.5, 0, 0), + F(480000000, P_MMPLL4, 2, 0, 0), + F(600000000, P_GPLL0, 1, 0, 0), + { } +}; + +static struct clk_rcg2 vfe0_clk_src = { + .cmd_rcgr = 0x3600, + .hid_width = 5, + .parent_map = mmss_xo_mmpll0_mmpll1_mmpll4_mmpll3_gpll0_gpll0_div_map, + .freq_tbl = ftbl_vfe0_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "vfe0_clk_src", + .parent_names = mmss_xo_mmpll0_mmpll1_mmpll4_mmpll3_gpll0_gpll0_div, + .num_parents = 7, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 vfe1_clk_src = { + .cmd_rcgr = 0x3620, + .hid_width = 5, + .parent_map = mmss_xo_mmpll0_mmpll1_mmpll4_mmpll3_gpll0_gpll0_div_map, + .freq_tbl = ftbl_vfe0_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "vfe1_clk_src", + .parent_names = mmss_xo_mmpll0_mmpll1_mmpll4_mmpll3_gpll0_gpll0_div, + .num_parents = 7, + .ops = &clk_rcg2_ops, + }, +}; + +static const struct freq_tbl ftbl_cpp_clk_src[] = { + F(100000000, P_GPLL0_DIV, 3, 0, 0), + F(200000000, P_GPLL0, 3, 0, 0), + F(320000000, P_MMPLL0, 2.5, 0, 0), + F(480000000, P_MMPLL4, 2, 0, 0), + F(640000000, P_MMPLL4, 1.5, 0, 0), + { } +}; + +static struct clk_rcg2 cpp_clk_src = { + .cmd_rcgr = 0x3640, + .hid_width = 5, + .parent_map = mmss_xo_mmpll0_mmpll1_mmpll4_mmpll3_gpll0_gpll0_div_map, + .freq_tbl = ftbl_cpp_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "cpp_clk_src", + .parent_names = mmss_xo_mmpll0_mmpll1_mmpll4_mmpll3_gpll0_gpll0_div, + .num_parents = 7, + .ops = &clk_rcg2_ops, + }, +}; + +static const struct freq_tbl ftbl_csi0_clk_src[] = { + F(100000000, P_GPLL0_DIV, 3, 0, 0), + F(200000000, P_GPLL0, 3, 0, 0), + F(266666667, P_MMPLL0, 3, 0, 0), + F(480000000, P_MMPLL4, 2, 0, 0), + F(600000000, P_GPLL0, 1, 0, 0), + { } +}; + +static struct clk_rcg2 csi0_clk_src = { + .cmd_rcgr = 0x3090, + .hid_width = 5, + .parent_map = mmss_xo_mmpll0_mmpll1_mmpll4_mmpll3_gpll0_gpll0_div_map, + .freq_tbl = ftbl_csi0_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "csi0_clk_src", + .parent_names = mmss_xo_mmpll0_mmpll1_mmpll4_mmpll3_gpll0_gpll0_div, + .num_parents = 7, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 csi1_clk_src = { + .cmd_rcgr = 0x3100, + .hid_width = 5, + .parent_map = mmss_xo_mmpll0_mmpll1_mmpll4_mmpll3_gpll0_gpll0_div_map, + .freq_tbl = ftbl_csi0_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "csi1_clk_src", + .parent_names = mmss_xo_mmpll0_mmpll1_mmpll4_mmpll3_gpll0_gpll0_div, + .num_parents = 7, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 csi2_clk_src = { + .cmd_rcgr = 0x3160, + .hid_width = 5, + .parent_map = mmss_xo_mmpll0_mmpll1_mmpll4_mmpll3_gpll0_gpll0_div_map, + .freq_tbl = ftbl_csi0_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "csi2_clk_src", + .parent_names = mmss_xo_mmpll0_mmpll1_mmpll4_mmpll3_gpll0_gpll0_div, + .num_parents = 7, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 csi3_clk_src = { + .cmd_rcgr = 0x31c0, + .hid_width = 5, + .parent_map = mmss_xo_mmpll0_mmpll1_mmpll4_mmpll3_gpll0_gpll0_div_map, + .freq_tbl = ftbl_csi0_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "csi3_clk_src", + .parent_names = mmss_xo_mmpll0_mmpll1_mmpll4_mmpll3_gpll0_gpll0_div, + .num_parents = 7, + .ops = &clk_rcg2_ops, + }, +}; + +static const struct freq_tbl ftbl_fd_core_clk_src[] = { + F(100000000, P_GPLL0_DIV, 3, 0, 0), + F(200000000, P_GPLL0, 3, 0, 0), + F(400000000, P_MMPLL0, 2, 0, 0), + { } +}; + +static struct clk_rcg2 fd_core_clk_src = { + .cmd_rcgr = 0x3b00, + .hid_width = 5, + .parent_map = mmss_xo_mmpll0_mmpll4_gpll0_gpll0_div_map, + .freq_tbl = ftbl_fd_core_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "fd_core_clk_src", + .parent_names = mmss_xo_mmpll0_mmpll4_gpll0_gpll0_div, + .num_parents = 5, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_branch mmss_mmagic_ahb_clk = { + .halt_reg = 0x5024, + .clkr = { + .enable_reg = 0x5024, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "mmss_mmagic_ahb_clk", + .parent_names = (const char *[]){ "ahb_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch mmss_mmagic_cfg_ahb_clk = { + .halt_reg = 0x5054, + .clkr = { + .enable_reg = 0x5054, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "mmss_mmagic_cfg_ahb_clk", + .parent_names = (const char *[]){ "ahb_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch mmss_misc_ahb_clk = { + .halt_reg = 0x5018, + .clkr = { + .enable_reg = 0x5018, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "mmss_misc_ahb_clk", + .parent_names = (const char *[]){ "ahb_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch mmss_misc_cxo_clk = { + .halt_reg = 0x5014, + .clkr = { + .enable_reg = 0x5014, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "mmss_misc_cxo_clk", + .parent_names = (const char *[]){ "xo" }, + .num_parents = 1, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch mmss_mmagic_axi_clk = { + .halt_reg = 0x506c, + .clkr = { + .enable_reg = 0x506c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "mmss_mmagic_axi_clk", + .parent_names = (const char *[]){ "axi_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch mmss_mmagic_maxi_clk = { + .halt_reg = 0x5074, + .clkr = { + .enable_reg = 0x5074, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "mmss_mmagic_maxi_clk", + .parent_names = (const char *[]){ "maxi_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch mmagic_camss_axi_clk = { + .halt_reg = 0x3c44, + .clkr = { + .enable_reg = 0x3c44, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "mmagic_camss_axi_clk", + .parent_names = (const char *[]){ "axi_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch mmagic_camss_noc_cfg_ahb_clk = { + .halt_reg = 0x3c48, + .clkr = { + .enable_reg = 0x3c48, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "mmagic_camss_noc_cfg_ahb_clk", + .parent_names = (const char *[]){ "gcc_mmss_noc_cfg_ahb_clk" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch smmu_vfe_ahb_clk = { + .halt_reg = 0x3c04, + .clkr = { + .enable_reg = 0x3c04, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "smmu_vfe_ahb_clk", + .parent_names = (const char *[]){ "ahb_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch smmu_vfe_axi_clk = { + .halt_reg = 0x3c08, + .clkr = { + .enable_reg = 0x3c08, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "smmu_vfe_axi_clk", + .parent_names = (const char *[]){ "axi_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch smmu_cpp_ahb_clk = { + .halt_reg = 0x3c14, + .clkr = { + .enable_reg = 0x3c14, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "smmu_cpp_ahb_clk", + .parent_names = (const char *[]){ "ahb_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch smmu_cpp_axi_clk = { + .halt_reg = 0x3c18, + .clkr = { + .enable_reg = 0x3c18, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "smmu_cpp_axi_clk", + .parent_names = (const char *[]){ "axi_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch smmu_jpeg_ahb_clk = { + .halt_reg = 0x3c24, + .clkr = { + .enable_reg = 0x3c24, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "smmu_jpeg_ahb_clk", + .parent_names = (const char *[]){ "ahb_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch smmu_jpeg_axi_clk = { + .halt_reg = 0x3c28, + .clkr = { + .enable_reg = 0x3c28, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "smmu_jpeg_axi_clk", + .parent_names = (const char *[]){ "axi_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch mmagic_mdss_axi_clk = { + .halt_reg = 0x2474, + .clkr = { + .enable_reg = 0x2474, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "mmagic_mdss_axi_clk", + .parent_names = (const char *[]){ "axi_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch mmagic_mdss_noc_cfg_ahb_clk = { + .halt_reg = 0x2478, + .clkr = { + .enable_reg = 0x2478, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "mmagic_mdss_noc_cfg_ahb_clk", + .parent_names = (const char *[]){ "gcc_mmss_noc_cfg_ahb_clk" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch smmu_rot_ahb_clk = { + .halt_reg = 0x2444, + .clkr = { + .enable_reg = 0x2444, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "smmu_rot_ahb_clk", + .parent_names = (const char *[]){ "ahb_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch smmu_rot_axi_clk = { + .halt_reg = 0x2448, + .clkr = { + .enable_reg = 0x2448, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "smmu_rot_axi_clk", + .parent_names = (const char *[]){ "axi_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch smmu_mdp_ahb_clk = { + .halt_reg = 0x2454, + .clkr = { + .enable_reg = 0x2454, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "smmu_mdp_ahb_clk", + .parent_names = (const char *[]){ "ahb_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch smmu_mdp_axi_clk = { + .halt_reg = 0x2458, + .clkr = { + .enable_reg = 0x2458, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "smmu_mdp_axi_clk", + .parent_names = (const char *[]){ "axi_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch mmagic_video_axi_clk = { + .halt_reg = 0x1194, + .clkr = { + .enable_reg = 0x1194, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "mmagic_video_axi_clk", + .parent_names = (const char *[]){ "axi_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch mmagic_video_noc_cfg_ahb_clk = { + .halt_reg = 0x1198, + .clkr = { + .enable_reg = 0x1198, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "mmagic_video_noc_cfg_ahb_clk", + .parent_names = (const char *[]){ "gcc_mmss_noc_cfg_ahb_clk" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch smmu_video_ahb_clk = { + .halt_reg = 0x1174, + .clkr = { + .enable_reg = 0x1174, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "smmu_video_ahb_clk", + .parent_names = (const char *[]){ "ahb_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch smmu_video_axi_clk = { + .halt_reg = 0x1178, + .clkr = { + .enable_reg = 0x1178, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "smmu_video_axi_clk", + .parent_names = (const char *[]){ "axi_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch mmagic_bimc_axi_clk = { + .halt_reg = 0x5294, + .clkr = { + .enable_reg = 0x5294, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "mmagic_bimc_axi_clk", + .parent_names = (const char *[]){ "axi_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch mmagic_bimc_noc_cfg_ahb_clk = { + .halt_reg = 0x5298, + .clkr = { + .enable_reg = 0x5298, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "mmagic_bimc_noc_cfg_ahb_clk", + .parent_names = (const char *[]){ "gcc_mmss_noc_cfg_ahb_clk" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gpu_gx_gfx3d_clk = { + .halt_reg = 0x4028, + .clkr = { + .enable_reg = 0x4028, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gpu_gx_gfx3d_clk", + .parent_names = (const char *[]){ "gfx3d_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gpu_gx_rbbmtimer_clk = { + .halt_reg = 0x40b0, + .clkr = { + .enable_reg = 0x40b0, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gpu_gx_rbbmtimer_clk", + .parent_names = (const char *[]){ "rbbmtimer_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gpu_ahb_clk = { + .halt_reg = 0x403c, + .clkr = { + .enable_reg = 0x403c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gpu_ahb_clk", + .parent_names = (const char *[]){ "ahb_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gpu_aon_isense_clk = { + .halt_reg = 0x4044, + .clkr = { + .enable_reg = 0x4044, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gpu_aon_isense_clk", + .parent_names = (const char *[]){ "isense_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch vmem_maxi_clk = { + .halt_reg = 0x1204, + .clkr = { + .enable_reg = 0x1204, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "vmem_maxi_clk", + .parent_names = (const char *[]){ "maxi_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch vmem_ahb_clk = { + .halt_reg = 0x1208, + .clkr = { + .enable_reg = 0x1208, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "vmem_ahb_clk", + .parent_names = (const char *[]){ "ahb_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch mmss_rbcpr_clk = { + .halt_reg = 0x4084, + .clkr = { + .enable_reg = 0x4084, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "mmss_rbcpr_clk", + .parent_names = (const char *[]){ "rbcpr_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch mmss_rbcpr_ahb_clk = { + .halt_reg = 0x4088, + .clkr = { + .enable_reg = 0x4088, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "mmss_rbcpr_ahb_clk", + .parent_names = (const char *[]){ "ahb_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch video_core_clk = { + .halt_reg = 0x1028, + .clkr = { + .enable_reg = 0x1028, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "video_core_clk", + .parent_names = (const char *[]){ "video_core_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch video_axi_clk = { + .halt_reg = 0x1034, + .clkr = { + .enable_reg = 0x1034, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "video_axi_clk", + .parent_names = (const char *[]){ "axi_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch video_maxi_clk = { + .halt_reg = 0x1038, + .clkr = { + .enable_reg = 0x1038, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "video_maxi_clk", + .parent_names = (const char *[]){ "maxi_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch video_ahb_clk = { + .halt_reg = 0x1030, + .clkr = { + .enable_reg = 0x1030, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "video_ahb_clk", + .parent_names = (const char *[]){ "ahb_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch video_subcore0_clk = { + .halt_reg = 0x1048, + .clkr = { + .enable_reg = 0x1048, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "video_subcore0_clk", + .parent_names = (const char *[]){ "video_subcore0_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch video_subcore1_clk = { + .halt_reg = 0x104c, + .clkr = { + .enable_reg = 0x104c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "video_subcore1_clk", + .parent_names = (const char *[]){ "video_subcore1_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch mdss_ahb_clk = { + .halt_reg = 0x2308, + .clkr = { + .enable_reg = 0x2308, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "mdss_ahb_clk", + .parent_names = (const char *[]){ "ahb_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch mdss_hdmi_ahb_clk = { + .halt_reg = 0x230c, + .clkr = { + .enable_reg = 0x230c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "mdss_hdmi_ahb_clk", + .parent_names = (const char *[]){ "ahb_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch mdss_axi_clk = { + .halt_reg = 0x2310, + .clkr = { + .enable_reg = 0x2310, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "mdss_axi_clk", + .parent_names = (const char *[]){ "axi_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch mdss_pclk0_clk = { + .halt_reg = 0x2314, + .clkr = { + .enable_reg = 0x2314, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "mdss_pclk0_clk", + .parent_names = (const char *[]){ "pclk0_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch mdss_pclk1_clk = { + .halt_reg = 0x2318, + .clkr = { + .enable_reg = 0x2318, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "mdss_pclk1_clk", + .parent_names = (const char *[]){ "pclk1_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch mdss_mdp_clk = { + .halt_reg = 0x231c, + .clkr = { + .enable_reg = 0x231c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "mdss_mdp_clk", + .parent_names = (const char *[]){ "mdp_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch mdss_extpclk_clk = { + .halt_reg = 0x2324, + .clkr = { + .enable_reg = 0x2324, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "mdss_extpclk_clk", + .parent_names = (const char *[]){ "extpclk_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch mdss_vsync_clk = { + .halt_reg = 0x2328, + .clkr = { + .enable_reg = 0x2328, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "mdss_vsync_clk", + .parent_names = (const char *[]){ "vsync_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch mdss_hdmi_clk = { + .halt_reg = 0x2338, + .clkr = { + .enable_reg = 0x2338, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "mdss_hdmi_clk", + .parent_names = (const char *[]){ "hdmi_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch mdss_byte0_clk = { + .halt_reg = 0x233c, + .clkr = { + .enable_reg = 0x233c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "mdss_byte0_clk", + .parent_names = (const char *[]){ "byte0_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch mdss_byte1_clk = { + .halt_reg = 0x2340, + .clkr = { + .enable_reg = 0x2340, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "mdss_byte1_clk", + .parent_names = (const char *[]){ "byte1_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch mdss_esc0_clk = { + .halt_reg = 0x2344, + .clkr = { + .enable_reg = 0x2344, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "mdss_esc0_clk", + .parent_names = (const char *[]){ "esc0_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch mdss_esc1_clk = { + .halt_reg = 0x2348, + .clkr = { + .enable_reg = 0x2348, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "mdss_esc1_clk", + .parent_names = (const char *[]){ "esc1_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch camss_top_ahb_clk = { + .halt_reg = 0x3484, + .clkr = { + .enable_reg = 0x3484, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "camss_top_ahb_clk", + .parent_names = (const char *[]){ "ahb_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch camss_ahb_clk = { + .halt_reg = 0x348c, + .clkr = { + .enable_reg = 0x348c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "camss_ahb_clk", + .parent_names = (const char *[]){ "ahb_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch camss_micro_ahb_clk = { + .halt_reg = 0x3494, + .clkr = { + .enable_reg = 0x3494, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "camss_micro_ahb_clk", + .parent_names = (const char *[]){ "ahb_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch camss_gp0_clk = { + .halt_reg = 0x3444, + .clkr = { + .enable_reg = 0x3444, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "camss_gp0_clk", + .parent_names = (const char *[]){ "camss_gp0_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch camss_gp1_clk = { + .halt_reg = 0x3474, + .clkr = { + .enable_reg = 0x3474, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "camss_gp1_clk", + .parent_names = (const char *[]){ "camss_gp1_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch camss_mclk0_clk = { + .halt_reg = 0x3384, + .clkr = { + .enable_reg = 0x3384, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "camss_mclk0_clk", + .parent_names = (const char *[]){ "mclk0_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch camss_mclk1_clk = { + .halt_reg = 0x33b4, + .clkr = { + .enable_reg = 0x33b4, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "camss_mclk1_clk", + .parent_names = (const char *[]){ "mclk1_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch camss_mclk2_clk = { + .halt_reg = 0x33e4, + .clkr = { + .enable_reg = 0x33e4, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "camss_mclk2_clk", + .parent_names = (const char *[]){ "mclk2_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch camss_mclk3_clk = { + .halt_reg = 0x3414, + .clkr = { + .enable_reg = 0x3414, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "camss_mclk3_clk", + .parent_names = (const char *[]){ "mclk3_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch camss_cci_clk = { + .halt_reg = 0x3344, + .clkr = { + .enable_reg = 0x3344, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "camss_cci_clk", + .parent_names = (const char *[]){ "cci_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch camss_cci_ahb_clk = { + .halt_reg = 0x3348, + .clkr = { + .enable_reg = 0x3348, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "camss_cci_ahb_clk", + .parent_names = (const char *[]){ "ahb_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch camss_csi0phytimer_clk = { + .halt_reg = 0x3024, + .clkr = { + .enable_reg = 0x3024, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "camss_csi0phytimer_clk", + .parent_names = (const char *[]){ "csi0phytimer_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch camss_csi1phytimer_clk = { + .halt_reg = 0x3054, + .clkr = { + .enable_reg = 0x3054, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "camss_csi1phytimer_clk", + .parent_names = (const char *[]){ "csi1phytimer_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch camss_csi2phytimer_clk = { + .halt_reg = 0x3084, + .clkr = { + .enable_reg = 0x3084, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "camss_csi2phytimer_clk", + .parent_names = (const char *[]){ "csi2phytimer_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch camss_csiphy0_3p_clk = { + .halt_reg = 0x3234, + .clkr = { + .enable_reg = 0x3234, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "camss_csiphy0_3p_clk", + .parent_names = (const char *[]){ "csiphy0_3p_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch camss_csiphy1_3p_clk = { + .halt_reg = 0x3254, + .clkr = { + .enable_reg = 0x3254, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "camss_csiphy1_3p_clk", + .parent_names = (const char *[]){ "csiphy1_3p_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch camss_csiphy2_3p_clk = { + .halt_reg = 0x3274, + .clkr = { + .enable_reg = 0x3274, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "camss_csiphy2_3p_clk", + .parent_names = (const char *[]){ "csiphy2_3p_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch camss_jpeg0_clk = { + .halt_reg = 0x35a8, + .clkr = { + .enable_reg = 0x35a8, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "camss_jpeg0_clk", + .parent_names = (const char *[]){ "jpeg0_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch camss_jpeg2_clk = { + .halt_reg = 0x35b0, + .clkr = { + .enable_reg = 0x35b0, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "camss_jpeg2_clk", + .parent_names = (const char *[]){ "jpeg2_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch camss_jpeg_dma_clk = { + .halt_reg = 0x35c0, + .clkr = { + .enable_reg = 0x35c0, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "camss_jpeg_dma_clk", + .parent_names = (const char *[]){ "jpeg_dma_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch camss_jpeg_ahb_clk = { + .halt_reg = 0x35b4, + .clkr = { + .enable_reg = 0x35b4, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "camss_jpeg_ahb_clk", + .parent_names = (const char *[]){ "ahb_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch camss_jpeg_axi_clk = { + .halt_reg = 0x35b8, + .clkr = { + .enable_reg = 0x35b8, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "camss_jpeg_axi_clk", + .parent_names = (const char *[]){ "axi_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch camss_vfe_ahb_clk = { + .halt_reg = 0x36b8, + .clkr = { + .enable_reg = 0x36b8, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "camss_vfe_ahb_clk", + .parent_names = (const char *[]){ "ahb_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch camss_vfe_axi_clk = { + .halt_reg = 0x36bc, + .clkr = { + .enable_reg = 0x36bc, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "camss_vfe_axi_clk", + .parent_names = (const char *[]){ "axi_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch camss_vfe0_clk = { + .halt_reg = 0x36a8, + .clkr = { + .enable_reg = 0x36a8, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "camss_vfe0_clk", + .parent_names = (const char *[]){ "vfe0_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch camss_vfe0_stream_clk = { + .halt_reg = 0x3720, + .clkr = { + .enable_reg = 0x3720, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "camss_vfe0_stream_clk", + .parent_names = (const char *[]){ "vfe0_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch camss_vfe0_ahb_clk = { + .halt_reg = 0x3668, + .clkr = { + .enable_reg = 0x3668, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "camss_vfe0_ahb_clk", + .parent_names = (const char *[]){ "ahb_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch camss_vfe1_clk = { + .halt_reg = 0x36ac, + .clkr = { + .enable_reg = 0x36ac, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "camss_vfe1_clk", + .parent_names = (const char *[]){ "vfe1_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch camss_vfe1_stream_clk = { + .halt_reg = 0x3724, + .clkr = { + .enable_reg = 0x3724, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "camss_vfe1_stream_clk", + .parent_names = (const char *[]){ "vfe1_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch camss_vfe1_ahb_clk = { + .halt_reg = 0x3678, + .clkr = { + .enable_reg = 0x3678, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "camss_vfe1_ahb_clk", + .parent_names = (const char *[]){ "ahb_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch camss_csi_vfe0_clk = { + .halt_reg = 0x3704, + .clkr = { + .enable_reg = 0x3704, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "camss_csi_vfe0_clk", + .parent_names = (const char *[]){ "vfe0_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch camss_csi_vfe1_clk = { + .halt_reg = 0x3714, + .clkr = { + .enable_reg = 0x3714, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "camss_csi_vfe1_clk", + .parent_names = (const char *[]){ "vfe1_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch camss_cpp_vbif_ahb_clk = { + .halt_reg = 0x36c8, + .clkr = { + .enable_reg = 0x36c8, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "camss_cpp_vbif_ahb_clk", + .parent_names = (const char *[]){ "ahb_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch camss_cpp_axi_clk = { + .halt_reg = 0x36c4, + .clkr = { + .enable_reg = 0x36c4, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "camss_cpp_axi_clk", + .parent_names = (const char *[]){ "axi_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch camss_cpp_clk = { + .halt_reg = 0x36b0, + .clkr = { + .enable_reg = 0x36b0, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "camss_cpp_clk", + .parent_names = (const char *[]){ "cpp_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch camss_cpp_ahb_clk = { + .halt_reg = 0x36b4, + .clkr = { + .enable_reg = 0x36b4, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "camss_cpp_ahb_clk", + .parent_names = (const char *[]){ "ahb_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch camss_csi0_clk = { + .halt_reg = 0x30b4, + .clkr = { + .enable_reg = 0x30b4, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "camss_csi0_clk", + .parent_names = (const char *[]){ "csi0_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch camss_csi0_ahb_clk = { + .halt_reg = 0x30bc, + .clkr = { + .enable_reg = 0x30bc, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "camss_csi0_ahb_clk", + .parent_names = (const char *[]){ "ahb_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch camss_csi0phy_clk = { + .halt_reg = 0x30c4, + .clkr = { + .enable_reg = 0x30c4, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "camss_csi0phy_clk", + .parent_names = (const char *[]){ "csi0_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch camss_csi0rdi_clk = { + .halt_reg = 0x30d4, + .clkr = { + .enable_reg = 0x30d4, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "camss_csi0rdi_clk", + .parent_names = (const char *[]){ "csi0_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch camss_csi0pix_clk = { + .halt_reg = 0x30e4, + .clkr = { + .enable_reg = 0x30e4, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "camss_csi0pix_clk", + .parent_names = (const char *[]){ "csi0_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch camss_csi1_clk = { + .halt_reg = 0x3124, + .clkr = { + .enable_reg = 0x3124, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "camss_csi1_clk", + .parent_names = (const char *[]){ "csi1_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch camss_csi1_ahb_clk = { + .halt_reg = 0x3128, + .clkr = { + .enable_reg = 0x3128, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "camss_csi1_ahb_clk", + .parent_names = (const char *[]){ "ahb_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch camss_csi1phy_clk = { + .halt_reg = 0x3134, + .clkr = { + .enable_reg = 0x3134, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "camss_csi1phy_clk", + .parent_names = (const char *[]){ "csi1_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch camss_csi1rdi_clk = { + .halt_reg = 0x3144, + .clkr = { + .enable_reg = 0x3144, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "camss_csi1rdi_clk", + .parent_names = (const char *[]){ "csi1_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch camss_csi1pix_clk = { + .halt_reg = 0x3154, + .clkr = { + .enable_reg = 0x3154, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "camss_csi1pix_clk", + .parent_names = (const char *[]){ "csi1_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch camss_csi2_clk = { + .halt_reg = 0x3184, + .clkr = { + .enable_reg = 0x3184, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "camss_csi2_clk", + .parent_names = (const char *[]){ "csi2_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch camss_csi2_ahb_clk = { + .halt_reg = 0x3188, + .clkr = { + .enable_reg = 0x3188, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "camss_csi2_ahb_clk", + .parent_names = (const char *[]){ "ahb_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch camss_csi2phy_clk = { + .halt_reg = 0x3194, + .clkr = { + .enable_reg = 0x3194, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "camss_csi2phy_clk", + .parent_names = (const char *[]){ "csi2_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch camss_csi2rdi_clk = { + .halt_reg = 0x31a4, + .clkr = { + .enable_reg = 0x31a4, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "camss_csi2rdi_clk", + .parent_names = (const char *[]){ "csi2_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch camss_csi2pix_clk = { + .halt_reg = 0x31b4, + .clkr = { + .enable_reg = 0x31b4, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "camss_csi2pix_clk", + .parent_names = (const char *[]){ "csi2_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch camss_csi3_clk = { + .halt_reg = 0x31e4, + .clkr = { + .enable_reg = 0x31e4, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "camss_csi3_clk", + .parent_names = (const char *[]){ "csi3_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch camss_csi3_ahb_clk = { + .halt_reg = 0x31e8, + .clkr = { + .enable_reg = 0x31e8, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "camss_csi3_ahb_clk", + .parent_names = (const char *[]){ "ahb_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch camss_csi3phy_clk = { + .halt_reg = 0x31f4, + .clkr = { + .enable_reg = 0x31f4, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "camss_csi3phy_clk", + .parent_names = (const char *[]){ "csi3_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch camss_csi3rdi_clk = { + .halt_reg = 0x3204, + .clkr = { + .enable_reg = 0x3204, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "camss_csi3rdi_clk", + .parent_names = (const char *[]){ "csi3_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch camss_csi3pix_clk = { + .halt_reg = 0x3214, + .clkr = { + .enable_reg = 0x3214, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "camss_csi3pix_clk", + .parent_names = (const char *[]){ "csi3_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch camss_ispif_ahb_clk = { + .halt_reg = 0x3224, + .clkr = { + .enable_reg = 0x3224, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "camss_ispif_ahb_clk", + .parent_names = (const char *[]){ "ahb_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch fd_core_clk = { + .halt_reg = 0x3b68, + .clkr = { + .enable_reg = 0x3b68, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "fd_core_clk", + .parent_names = (const char *[]){ "fd_core_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch fd_core_uar_clk = { + .halt_reg = 0x3b6c, + .clkr = { + .enable_reg = 0x3b6c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "fd_core_uar_clk", + .parent_names = (const char *[]){ "fd_core_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch fd_ahb_clk = { + .halt_reg = 0x3ba74, + .clkr = { + .enable_reg = 0x3ba74, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "fd_ahb_clk", + .parent_names = (const char *[]){ "ahb_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_hw *mmcc_msm8996_hws[] = { + &gpll0_div.hw, +}; + +static struct clk_regmap *mmcc_msm8996_clocks[] = { + [MMPLL0_EARLY] = &mmpll0_early.clkr, + [MMPLL0_PLL] = &mmpll0.clkr, + [MMPLL1_EARLY] = &mmpll1_early.clkr, + [MMPLL1_PLL] = &mmpll1.clkr, + [MMPLL2_EARLY] = &mmpll2_early.clkr, + [MMPLL2_PLL] = &mmpll2.clkr, + [MMPLL3_EARLY] = &mmpll3_early.clkr, + [MMPLL3_PLL] = &mmpll3.clkr, + [MMPLL4_EARLY] = &mmpll4_early.clkr, + [MMPLL4_PLL] = &mmpll4.clkr, + [MMPLL5_EARLY] = &mmpll5_early.clkr, + [MMPLL5_PLL] = &mmpll5.clkr, + [MMPLL8_EARLY] = &mmpll8_early.clkr, + [MMPLL8_PLL] = &mmpll8.clkr, + [MMPLL9_EARLY] = &mmpll9_early.clkr, + [MMPLL9_PLL] = &mmpll9.clkr, + [AHB_CLK_SRC] = &ahb_clk_src.clkr, + [AXI_CLK_SRC] = &axi_clk_src.clkr, + [MAXI_CLK_SRC] = &maxi_clk_src.clkr, + [GFX3D_CLK_SRC] = &gfx3d_clk_src.clkr, + [RBBMTIMER_CLK_SRC] = &rbbmtimer_clk_src.clkr, + [ISENSE_CLK_SRC] = &isense_clk_src.clkr, + [RBCPR_CLK_SRC] = &rbcpr_clk_src.clkr, + [VIDEO_CORE_CLK_SRC] = &video_core_clk_src.clkr, + [VIDEO_SUBCORE0_CLK_SRC] = &video_subcore0_clk_src.clkr, + [VIDEO_SUBCORE1_CLK_SRC] = &video_subcore1_clk_src.clkr, + [PCLK0_CLK_SRC] = &pclk0_clk_src.clkr, + [PCLK1_CLK_SRC] = &pclk1_clk_src.clkr, + [MDP_CLK_SRC] = &mdp_clk_src.clkr, + [EXTPCLK_CLK_SRC] = &extpclk_clk_src.clkr, + [VSYNC_CLK_SRC] = &vsync_clk_src.clkr, + [HDMI_CLK_SRC] = &hdmi_clk_src.clkr, + [BYTE0_CLK_SRC] = &byte0_clk_src.clkr, + [BYTE1_CLK_SRC] = &byte1_clk_src.clkr, + [ESC0_CLK_SRC] = &esc0_clk_src.clkr, + [ESC1_CLK_SRC] = &esc1_clk_src.clkr, + [CAMSS_GP0_CLK_SRC] = &camss_gp0_clk_src.clkr, + [CAMSS_GP1_CLK_SRC] = &camss_gp1_clk_src.clkr, + [MCLK0_CLK_SRC] = &mclk0_clk_src.clkr, + [MCLK1_CLK_SRC] = &mclk1_clk_src.clkr, + [MCLK2_CLK_SRC] = &mclk2_clk_src.clkr, + [MCLK3_CLK_SRC] = &mclk3_clk_src.clkr, + [CCI_CLK_SRC] = &cci_clk_src.clkr, + [CSI0PHYTIMER_CLK_SRC] = &csi0phytimer_clk_src.clkr, + [CSI1PHYTIMER_CLK_SRC] = &csi1phytimer_clk_src.clkr, + [CSI2PHYTIMER_CLK_SRC] = &csi2phytimer_clk_src.clkr, + [CSIPHY0_3P_CLK_SRC] = &csiphy0_3p_clk_src.clkr, + [CSIPHY1_3P_CLK_SRC] = &csiphy1_3p_clk_src.clkr, + [CSIPHY2_3P_CLK_SRC] = &csiphy2_3p_clk_src.clkr, + [JPEG0_CLK_SRC] = &jpeg0_clk_src.clkr, + [JPEG2_CLK_SRC] = &jpeg2_clk_src.clkr, + [JPEG_DMA_CLK_SRC] = &jpeg_dma_clk_src.clkr, + [VFE0_CLK_SRC] = &vfe0_clk_src.clkr, + [VFE1_CLK_SRC] = &vfe1_clk_src.clkr, + [CPP_CLK_SRC] = &cpp_clk_src.clkr, + [CSI0_CLK_SRC] = &csi0_clk_src.clkr, + [CSI1_CLK_SRC] = &csi1_clk_src.clkr, + [CSI2_CLK_SRC] = &csi2_clk_src.clkr, + [CSI3_CLK_SRC] = &csi3_clk_src.clkr, + [FD_CORE_CLK_SRC] = &fd_core_clk_src.clkr, + [MMSS_MMAGIC_AHB_CLK] = &mmss_mmagic_ahb_clk.clkr, + [MMSS_MMAGIC_CFG_AHB_CLK] = &mmss_mmagic_cfg_ahb_clk.clkr, + [MMSS_MISC_AHB_CLK] = &mmss_misc_ahb_clk.clkr, + [MMSS_MISC_CXO_CLK] = &mmss_misc_cxo_clk.clkr, + [MMSS_MMAGIC_AXI_CLK] = &mmss_mmagic_axi_clk.clkr, + [MMSS_MMAGIC_MAXI_CLK] = &mmss_mmagic_maxi_clk.clkr, + [MMAGIC_CAMSS_AXI_CLK] = &mmagic_camss_axi_clk.clkr, + [MMAGIC_CAMSS_NOC_CFG_AHB_CLK] = &mmagic_camss_noc_cfg_ahb_clk.clkr, + [SMMU_VFE_AHB_CLK] = &smmu_vfe_ahb_clk.clkr, + [SMMU_VFE_AXI_CLK] = &smmu_vfe_axi_clk.clkr, + [SMMU_CPP_AHB_CLK] = &smmu_cpp_ahb_clk.clkr, + [SMMU_CPP_AXI_CLK] = &smmu_cpp_axi_clk.clkr, + [SMMU_JPEG_AHB_CLK] = &smmu_jpeg_ahb_clk.clkr, + [SMMU_JPEG_AXI_CLK] = &smmu_jpeg_axi_clk.clkr, + [MMAGIC_MDSS_AXI_CLK] = &mmagic_mdss_axi_clk.clkr, + [MMAGIC_MDSS_NOC_CFG_AHB_CLK] = &mmagic_mdss_noc_cfg_ahb_clk.clkr, + [SMMU_ROT_AHB_CLK] = &smmu_rot_ahb_clk.clkr, + [SMMU_ROT_AXI_CLK] = &smmu_rot_axi_clk.clkr, + [SMMU_MDP_AHB_CLK] = &smmu_mdp_ahb_clk.clkr, + [SMMU_MDP_AXI_CLK] = &smmu_mdp_axi_clk.clkr, + [MMAGIC_VIDEO_AXI_CLK] = &mmagic_video_axi_clk.clkr, + [MMAGIC_VIDEO_NOC_CFG_AHB_CLK] = &mmagic_video_noc_cfg_ahb_clk.clkr, + [SMMU_VIDEO_AHB_CLK] = &smmu_video_ahb_clk.clkr, + [SMMU_VIDEO_AXI_CLK] = &smmu_video_axi_clk.clkr, + [MMAGIC_BIMC_AXI_CLK] = &mmagic_bimc_axi_clk.clkr, + [MMAGIC_BIMC_NOC_CFG_AHB_CLK] = &mmagic_bimc_noc_cfg_ahb_clk.clkr, + [GPU_GX_GFX3D_CLK] = &gpu_gx_gfx3d_clk.clkr, + [GPU_GX_RBBMTIMER_CLK] = &gpu_gx_rbbmtimer_clk.clkr, + [GPU_AHB_CLK] = &gpu_ahb_clk.clkr, + [GPU_AON_ISENSE_CLK] = &gpu_aon_isense_clk.clkr, + [VMEM_MAXI_CLK] = &vmem_maxi_clk.clkr, + [VMEM_AHB_CLK] = &vmem_ahb_clk.clkr, + [MMSS_RBCPR_CLK] = &mmss_rbcpr_clk.clkr, + [MMSS_RBCPR_AHB_CLK] = &mmss_rbcpr_ahb_clk.clkr, + [VIDEO_CORE_CLK] = &video_core_clk.clkr, + [VIDEO_AXI_CLK] = &video_axi_clk.clkr, + [VIDEO_MAXI_CLK] = &video_maxi_clk.clkr, + [VIDEO_AHB_CLK] = &video_ahb_clk.clkr, + [VIDEO_SUBCORE0_CLK] = &video_subcore0_clk.clkr, + [VIDEO_SUBCORE1_CLK] = &video_subcore1_clk.clkr, + [MDSS_AHB_CLK] = &mdss_ahb_clk.clkr, + [MDSS_HDMI_AHB_CLK] = &mdss_hdmi_ahb_clk.clkr, + [MDSS_AXI_CLK] = &mdss_axi_clk.clkr, + [MDSS_PCLK0_CLK] = &mdss_pclk0_clk.clkr, + [MDSS_PCLK1_CLK] = &mdss_pclk1_clk.clkr, + [MDSS_MDP_CLK] = &mdss_mdp_clk.clkr, + [MDSS_EXTPCLK_CLK] = &mdss_extpclk_clk.clkr, + [MDSS_VSYNC_CLK] = &mdss_vsync_clk.clkr, + [MDSS_HDMI_CLK] = &mdss_hdmi_clk.clkr, + [MDSS_BYTE0_CLK] = &mdss_byte0_clk.clkr, + [MDSS_BYTE1_CLK] = &mdss_byte1_clk.clkr, + [MDSS_ESC0_CLK] = &mdss_esc0_clk.clkr, + [MDSS_ESC1_CLK] = &mdss_esc1_clk.clkr, + [CAMSS_TOP_AHB_CLK] = &camss_top_ahb_clk.clkr, + [CAMSS_AHB_CLK] = &camss_ahb_clk.clkr, + [CAMSS_MICRO_AHB_CLK] = &camss_micro_ahb_clk.clkr, + [CAMSS_GP0_CLK] = &camss_gp0_clk.clkr, + [CAMSS_GP1_CLK] = &camss_gp1_clk.clkr, + [CAMSS_MCLK0_CLK] = &camss_mclk0_clk.clkr, + [CAMSS_MCLK1_CLK] = &camss_mclk1_clk.clkr, + [CAMSS_MCLK2_CLK] = &camss_mclk2_clk.clkr, + [CAMSS_MCLK3_CLK] = &camss_mclk3_clk.clkr, + [CAMSS_CCI_CLK] = &camss_cci_clk.clkr, + [CAMSS_CCI_AHB_CLK] = &camss_cci_ahb_clk.clkr, + [CAMSS_CSI0PHYTIMER_CLK] = &camss_csi0phytimer_clk.clkr, + [CAMSS_CSI1PHYTIMER_CLK] = &camss_csi1phytimer_clk.clkr, + [CAMSS_CSI2PHYTIMER_CLK] = &camss_csi2phytimer_clk.clkr, + [CAMSS_CSIPHY0_3P_CLK] = &camss_csiphy0_3p_clk.clkr, + [CAMSS_CSIPHY1_3P_CLK] = &camss_csiphy1_3p_clk.clkr, + [CAMSS_CSIPHY2_3P_CLK] = &camss_csiphy2_3p_clk.clkr, + [CAMSS_JPEG0_CLK] = &camss_jpeg0_clk.clkr, + [CAMSS_JPEG2_CLK] = &camss_jpeg2_clk.clkr, + [CAMSS_JPEG_DMA_CLK] = &camss_jpeg_dma_clk.clkr, + [CAMSS_JPEG_AHB_CLK] = &camss_jpeg_ahb_clk.clkr, + [CAMSS_JPEG_AXI_CLK] = &camss_jpeg_axi_clk.clkr, + [CAMSS_VFE_AHB_CLK] = &camss_vfe_ahb_clk.clkr, + [CAMSS_VFE_AXI_CLK] = &camss_vfe_axi_clk.clkr, + [CAMSS_VFE0_CLK] = &camss_vfe0_clk.clkr, + [CAMSS_VFE0_STREAM_CLK] = &camss_vfe0_stream_clk.clkr, + [CAMSS_VFE0_AHB_CLK] = &camss_vfe0_ahb_clk.clkr, + [CAMSS_VFE1_CLK] = &camss_vfe1_clk.clkr, + [CAMSS_VFE1_STREAM_CLK] = &camss_vfe1_stream_clk.clkr, + [CAMSS_VFE1_AHB_CLK] = &camss_vfe1_ahb_clk.clkr, + [CAMSS_CSI_VFE0_CLK] = &camss_csi_vfe0_clk.clkr, + [CAMSS_CSI_VFE1_CLK] = &camss_csi_vfe1_clk.clkr, + [CAMSS_CPP_VBIF_AHB_CLK] = &camss_cpp_vbif_ahb_clk.clkr, + [CAMSS_CPP_AXI_CLK] = &camss_cpp_axi_clk.clkr, + [CAMSS_CPP_CLK] = &camss_cpp_clk.clkr, + [CAMSS_CPP_AHB_CLK] = &camss_cpp_ahb_clk.clkr, + [CAMSS_CSI0_CLK] = &camss_csi0_clk.clkr, + [CAMSS_CSI0_AHB_CLK] = &camss_csi0_ahb_clk.clkr, + [CAMSS_CSI0PHY_CLK] = &camss_csi0phy_clk.clkr, + [CAMSS_CSI0RDI_CLK] = &camss_csi0rdi_clk.clkr, + [CAMSS_CSI0PIX_CLK] = &camss_csi0pix_clk.clkr, + [CAMSS_CSI1_CLK] = &camss_csi1_clk.clkr, + [CAMSS_CSI1_AHB_CLK] = &camss_csi1_ahb_clk.clkr, + [CAMSS_CSI1PHY_CLK] = &camss_csi1phy_clk.clkr, + [CAMSS_CSI1RDI_CLK] = &camss_csi1rdi_clk.clkr, + [CAMSS_CSI1PIX_CLK] = &camss_csi1pix_clk.clkr, + [CAMSS_CSI2_CLK] = &camss_csi2_clk.clkr, + [CAMSS_CSI2_AHB_CLK] = &camss_csi2_ahb_clk.clkr, + [CAMSS_CSI2PHY_CLK] = &camss_csi2phy_clk.clkr, + [CAMSS_CSI2RDI_CLK] = &camss_csi2rdi_clk.clkr, + [CAMSS_CSI2PIX_CLK] = &camss_csi2pix_clk.clkr, + [CAMSS_CSI3_CLK] = &camss_csi3_clk.clkr, + [CAMSS_CSI3_AHB_CLK] = &camss_csi3_ahb_clk.clkr, + [CAMSS_CSI3PHY_CLK] = &camss_csi3phy_clk.clkr, + [CAMSS_CSI3RDI_CLK] = &camss_csi3rdi_clk.clkr, + [CAMSS_CSI3PIX_CLK] = &camss_csi3pix_clk.clkr, + [CAMSS_ISPIF_AHB_CLK] = &camss_ispif_ahb_clk.clkr, + [FD_CORE_CLK] = &fd_core_clk.clkr, + [FD_CORE_UAR_CLK] = &fd_core_uar_clk.clkr, + [FD_AHB_CLK] = &fd_ahb_clk.clkr, +}; + +static const struct qcom_reset_map mmcc_msm8996_resets[] = { + [MMAGICAHB_BCR] = { 0x5020 }, + [MMAGIC_CFG_BCR] = { 0x5050 }, + [MISC_BCR] = { 0x5010 }, + [BTO_BCR] = { 0x5030 }, + [MMAGICAXI_BCR] = { 0x5060 }, + [MMAGICMAXI_BCR] = { 0x5070 }, + [DSA_BCR] = { 0x50a0 }, + [MMAGIC_CAMSS_BCR] = { 0x3c40 }, + [THROTTLE_CAMSS_BCR] = { 0x3c30 }, + [SMMU_VFE_BCR] = { 0x3c00 }, + [SMMU_CPP_BCR] = { 0x3c10 }, + [SMMU_JPEG_BCR] = { 0x3c20 }, + [MMAGIC_MDSS_BCR] = { 0x2470 }, + [THROTTLE_MDSS_BCR] = { 0x2460 }, + [SMMU_ROT_BCR] = { 0x2440 }, + [SMMU_MDP_BCR] = { 0x2450 }, + [MMAGIC_VIDEO_BCR] = { 0x1190 }, + [THROTTLE_VIDEO_BCR] = { 0x1180 }, + [SMMU_VIDEO_BCR] = { 0x1170 }, + [MMAGIC_BIMC_BCR] = { 0x5290 }, + [GPU_GX_BCR] = { 0x4020 }, + [GPU_BCR] = { 0x4030 }, + [GPU_AON_BCR] = { 0x4040 }, + [VMEM_BCR] = { 0x1200 }, + [MMSS_RBCPR_BCR] = { 0x4080 }, + [VIDEO_BCR] = { 0x1020 }, + [MDSS_BCR] = { 0x2300 }, + [CAMSS_TOP_BCR] = { 0x3480 }, + [CAMSS_AHB_BCR] = { 0x3488 }, + [CAMSS_MICRO_BCR] = { 0x3490 }, + [CAMSS_CCI_BCR] = { 0x3340 }, + [CAMSS_PHY0_BCR] = { 0x3020 }, + [CAMSS_PHY1_BCR] = { 0x3050 }, + [CAMSS_PHY2_BCR] = { 0x3080 }, + [CAMSS_CSIPHY0_3P_BCR] = { 0x3230 }, + [CAMSS_CSIPHY1_3P_BCR] = { 0x3250 }, + [CAMSS_CSIPHY2_3P_BCR] = { 0x3270 }, + [CAMSS_JPEG_BCR] = { 0x35a0 }, + [CAMSS_VFE_BCR] = { 0x36a0 }, + [CAMSS_VFE0_BCR] = { 0x3660 }, + [CAMSS_VFE1_BCR] = { 0x3670 }, + [CAMSS_CSI_VFE0_BCR] = { 0x3700 }, + [CAMSS_CSI_VFE1_BCR] = { 0x3710 }, + [CAMSS_CPP_TOP_BCR] = { 0x36c0 }, + [CAMSS_CPP_BCR] = { 0x36d0 }, + [CAMSS_CSI0_BCR] = { 0x30b0 }, + [CAMSS_CSI0RDI_BCR] = { 0x30d0 }, + [CAMSS_CSI0PIX_BCR] = { 0x30e0 }, + [CAMSS_CSI1_BCR] = { 0x3120 }, + [CAMSS_CSI1RDI_BCR] = { 0x3140 }, + [CAMSS_CSI1PIX_BCR] = { 0x3150 }, + [CAMSS_CSI2_BCR] = { 0x3180 }, + [CAMSS_CSI2RDI_BCR] = { 0x31a0 }, + [CAMSS_CSI2PIX_BCR] = { 0x31b0 }, + [CAMSS_CSI3_BCR] = { 0x31e0 }, + [CAMSS_CSI3RDI_BCR] = { 0x3200 }, + [CAMSS_CSI3PIX_BCR] = { 0x3210 }, + [CAMSS_ISPIF_BCR] = { 0x3220 }, + [FD_BCR] = { 0x3b60 }, + [MMSS_SPDM_RM_BCR] = { 0x300 }, +}; + +static const struct regmap_config mmcc_msm8996_regmap_config = { + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + .max_register = 0xb008, + .fast_io = true, +}; + +static const struct qcom_cc_desc mmcc_msm8996_desc = { + .config = &mmcc_msm8996_regmap_config, + .clks = mmcc_msm8996_clocks, + .num_clks = ARRAY_SIZE(mmcc_msm8996_clocks), + .resets = mmcc_msm8996_resets, + .num_resets = ARRAY_SIZE(mmcc_msm8996_resets), +}; + +static const struct of_device_id mmcc_msm8996_match_table[] = { + { .compatible = "qcom,mmcc-msm8996" }, + { } +}; +MODULE_DEVICE_TABLE(of, mmcc_msm8996_match_table); + +static int mmcc_msm8996_probe(struct platform_device *pdev) +{ + struct clk *clk; + struct device *dev = &pdev->dev; + int i; + struct regmap *regmap; + + regmap = qcom_cc_map(pdev, &mmcc_msm8996_desc); + if (IS_ERR(regmap)) + return PTR_ERR(regmap); + + /* Disable the AHB DCD */ + regmap_update_bits(regmap, 0x50d8, BIT(31), 0); + /* Disable the NoC FSM for mmss_mmagic_cfg_ahb_clk */ + regmap_update_bits(regmap, 0x5054, BIT(15), 0); + + for (i = 0; i < ARRAY_SIZE(mmcc_msm8996_hws); i++) { + clk = devm_clk_register(dev, mmcc_msm8996_hws[i]); + if (IS_ERR(clk)) + return PTR_ERR(clk); + } + + return qcom_cc_really_probe(pdev, &mmcc_msm8996_desc, regmap); +} + +static struct platform_driver mmcc_msm8996_driver = { + .probe = mmcc_msm8996_probe, + .driver = { + .name = "mmcc-msm8996", + .of_match_table = mmcc_msm8996_match_table, + }, +}; +module_platform_driver(mmcc_msm8996_driver); + +MODULE_DESCRIPTION("QCOM MMCC MSM8996 Driver"); +MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("platform:mmcc-msm8996"); diff --git a/drivers/clk/rockchip/Makefile b/drivers/clk/rockchip/Makefile index b27edd6c8183..80b9a379beb4 100644 --- a/drivers/clk/rockchip/Makefile +++ b/drivers/clk/rockchip/Makefile @@ -10,6 +10,8 @@ obj-y += clk-inverter.o obj-y += clk-mmc-phase.o obj-$(CONFIG_RESET_CONTROLLER) += softrst.o +obj-y += clk-rk3036.o obj-y += clk-rk3188.o +obj-y += clk-rk3228.o obj-y += clk-rk3288.o obj-y += clk-rk3368.o diff --git a/drivers/clk/rockchip/clk-cpu.c b/drivers/clk/rockchip/clk-cpu.c index 330870a6d8bf..d07374f48caf 100644 --- a/drivers/clk/rockchip/clk-cpu.c +++ b/drivers/clk/rockchip/clk-cpu.c @@ -242,8 +242,8 @@ struct clk *rockchip_clk_register_cpuclk(const char *name, struct clk *clk, *cclk; int ret; - if (num_parents != 2) { - pr_err("%s: needs two parent clocks\n", __func__); + if (num_parents < 2) { + pr_err("%s: needs at least two parent clocks\n", __func__); return ERR_PTR(-EINVAL); } diff --git a/drivers/clk/rockchip/clk-pll.c b/drivers/clk/rockchip/clk-pll.c index 4881eb8a1576..b7e66c9dd9f2 100644 --- a/drivers/clk/rockchip/clk-pll.c +++ b/drivers/clk/rockchip/clk-pll.c @@ -2,6 +2,9 @@ * Copyright (c) 2014 MundoReader S.L. * Author: Heiko Stuebner <heiko@sntech.de> * + * Copyright (c) 2015 Rockchip Electronics Co. Ltd. + * Author: Xing Zheng <zhengxing@rock-chips.com> + * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or @@ -19,6 +22,7 @@ #include <linux/delay.h> #include <linux/clk-provider.h> #include <linux/regmap.h> +#include <linux/clk.h> #include "clk.h" #define PLL_MODE_MASK 0x3 @@ -108,6 +112,252 @@ static int rockchip_pll_wait_lock(struct rockchip_clk_pll *pll) } /** + * PLL used in RK3036 + */ + +#define RK3036_PLLCON(i) (i * 0x4) +#define RK3036_PLLCON0_FBDIV_MASK 0xfff +#define RK3036_PLLCON0_FBDIV_SHIFT 0 +#define RK3036_PLLCON0_POSTDIV1_MASK 0x7 +#define RK3036_PLLCON0_POSTDIV1_SHIFT 12 +#define RK3036_PLLCON1_REFDIV_MASK 0x3f +#define RK3036_PLLCON1_REFDIV_SHIFT 0 +#define RK3036_PLLCON1_POSTDIV2_MASK 0x7 +#define RK3036_PLLCON1_POSTDIV2_SHIFT 6 +#define RK3036_PLLCON1_DSMPD_MASK 0x1 +#define RK3036_PLLCON1_DSMPD_SHIFT 12 +#define RK3036_PLLCON2_FRAC_MASK 0xffffff +#define RK3036_PLLCON2_FRAC_SHIFT 0 + +#define RK3036_PLLCON1_PWRDOWN (1 << 13) + +static void rockchip_rk3036_pll_get_params(struct rockchip_clk_pll *pll, + struct rockchip_pll_rate_table *rate) +{ + u32 pllcon; + + pllcon = readl_relaxed(pll->reg_base + RK3036_PLLCON(0)); + rate->fbdiv = ((pllcon >> RK3036_PLLCON0_FBDIV_SHIFT) + & RK3036_PLLCON0_FBDIV_MASK); + rate->postdiv1 = ((pllcon >> RK3036_PLLCON0_POSTDIV1_SHIFT) + & RK3036_PLLCON0_POSTDIV1_MASK); + + pllcon = readl_relaxed(pll->reg_base + RK3036_PLLCON(1)); + rate->refdiv = ((pllcon >> RK3036_PLLCON1_REFDIV_SHIFT) + & RK3036_PLLCON1_REFDIV_MASK); + rate->postdiv2 = ((pllcon >> RK3036_PLLCON1_POSTDIV2_SHIFT) + & RK3036_PLLCON1_POSTDIV2_MASK); + rate->dsmpd = ((pllcon >> RK3036_PLLCON1_DSMPD_SHIFT) + & RK3036_PLLCON1_DSMPD_MASK); + + pllcon = readl_relaxed(pll->reg_base + RK3036_PLLCON(2)); + rate->frac = ((pllcon >> RK3036_PLLCON2_FRAC_SHIFT) + & RK3036_PLLCON2_FRAC_MASK); +} + +static unsigned long rockchip_rk3036_pll_recalc_rate(struct clk_hw *hw, + unsigned long prate) +{ + struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw); + struct rockchip_pll_rate_table cur; + u64 rate64 = prate; + + rockchip_rk3036_pll_get_params(pll, &cur); + + rate64 *= cur.fbdiv; + do_div(rate64, cur.refdiv); + + if (cur.dsmpd == 0) { + /* fractional mode */ + u64 frac_rate64 = prate * cur.frac; + + do_div(frac_rate64, cur.refdiv); + rate64 += frac_rate64 >> 24; + } + + do_div(rate64, cur.postdiv1); + do_div(rate64, cur.postdiv2); + + return (unsigned long)rate64; +} + +static int rockchip_rk3036_pll_set_params(struct rockchip_clk_pll *pll, + const struct rockchip_pll_rate_table *rate) +{ + const struct clk_ops *pll_mux_ops = pll->pll_mux_ops; + struct clk_mux *pll_mux = &pll->pll_mux; + struct rockchip_pll_rate_table cur; + u32 pllcon; + int rate_change_remuxed = 0; + int cur_parent; + int ret; + + pr_debug("%s: rate settings for %lu fbdiv: %d, postdiv1: %d, refdiv: %d, postdiv2: %d, dsmpd: %d, frac: %d\n", + __func__, rate->rate, rate->fbdiv, rate->postdiv1, rate->refdiv, + rate->postdiv2, rate->dsmpd, rate->frac); + + rockchip_rk3036_pll_get_params(pll, &cur); + cur.rate = 0; + + cur_parent = pll_mux_ops->get_parent(&pll_mux->hw); + if (cur_parent == PLL_MODE_NORM) { + pll_mux_ops->set_parent(&pll_mux->hw, PLL_MODE_SLOW); + rate_change_remuxed = 1; + } + + /* update pll values */ + writel_relaxed(HIWORD_UPDATE(rate->fbdiv, RK3036_PLLCON0_FBDIV_MASK, + RK3036_PLLCON0_FBDIV_SHIFT) | + HIWORD_UPDATE(rate->postdiv1, RK3036_PLLCON0_POSTDIV1_MASK, + RK3036_PLLCON0_POSTDIV1_SHIFT), + pll->reg_base + RK3036_PLLCON(0)); + + writel_relaxed(HIWORD_UPDATE(rate->refdiv, RK3036_PLLCON1_REFDIV_MASK, + RK3036_PLLCON1_REFDIV_SHIFT) | + HIWORD_UPDATE(rate->postdiv2, RK3036_PLLCON1_POSTDIV2_MASK, + RK3036_PLLCON1_POSTDIV2_SHIFT) | + HIWORD_UPDATE(rate->dsmpd, RK3036_PLLCON1_DSMPD_MASK, + RK3036_PLLCON1_DSMPD_SHIFT), + pll->reg_base + RK3036_PLLCON(1)); + + /* GPLL CON2 is not HIWORD_MASK */ + pllcon = readl_relaxed(pll->reg_base + RK3036_PLLCON(2)); + pllcon &= ~(RK3036_PLLCON2_FRAC_MASK << RK3036_PLLCON2_FRAC_SHIFT); + pllcon |= rate->frac << RK3036_PLLCON2_FRAC_SHIFT; + writel_relaxed(pllcon, pll->reg_base + RK3036_PLLCON(2)); + + /* wait for the pll to lock */ + ret = rockchip_pll_wait_lock(pll); + if (ret) { + pr_warn("%s: pll update unsucessful, trying to restore old params\n", + __func__); + rockchip_rk3036_pll_set_params(pll, &cur); + } + + if (rate_change_remuxed) + pll_mux_ops->set_parent(&pll_mux->hw, PLL_MODE_NORM); + + return ret; +} + +static int rockchip_rk3036_pll_set_rate(struct clk_hw *hw, unsigned long drate, + unsigned long prate) +{ + struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw); + const struct rockchip_pll_rate_table *rate; + unsigned long old_rate = rockchip_rk3036_pll_recalc_rate(hw, prate); + struct regmap *grf = rockchip_clk_get_grf(); + + if (IS_ERR(grf)) { + pr_debug("%s: grf regmap not available, aborting rate change\n", + __func__); + return PTR_ERR(grf); + } + + pr_debug("%s: changing %s from %lu to %lu with a parent rate of %lu\n", + __func__, __clk_get_name(hw->clk), old_rate, drate, prate); + + /* Get required rate settings from table */ + rate = rockchip_get_pll_settings(pll, drate); + if (!rate) { + pr_err("%s: Invalid rate : %lu for pll clk %s\n", __func__, + drate, __clk_get_name(hw->clk)); + return -EINVAL; + } + + return rockchip_rk3036_pll_set_params(pll, rate); +} + +static int rockchip_rk3036_pll_enable(struct clk_hw *hw) +{ + struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw); + + writel(HIWORD_UPDATE(0, RK3036_PLLCON1_PWRDOWN, 0), + pll->reg_base + RK3036_PLLCON(1)); + + return 0; +} + +static void rockchip_rk3036_pll_disable(struct clk_hw *hw) +{ + struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw); + + writel(HIWORD_UPDATE(RK3036_PLLCON1_PWRDOWN, + RK3036_PLLCON1_PWRDOWN, 0), + pll->reg_base + RK3036_PLLCON(1)); +} + +static int rockchip_rk3036_pll_is_enabled(struct clk_hw *hw) +{ + struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw); + u32 pllcon = readl(pll->reg_base + RK3036_PLLCON(1)); + + return !(pllcon & RK3036_PLLCON1_PWRDOWN); +} + +static void rockchip_rk3036_pll_init(struct clk_hw *hw) +{ + struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw); + const struct rockchip_pll_rate_table *rate; + struct rockchip_pll_rate_table cur; + unsigned long drate; + + if (!(pll->flags & ROCKCHIP_PLL_SYNC_RATE)) + return; + + drate = clk_hw_get_rate(hw); + rate = rockchip_get_pll_settings(pll, drate); + + /* when no rate setting for the current rate, rely on clk_set_rate */ + if (!rate) + return; + + rockchip_rk3036_pll_get_params(pll, &cur); + + pr_debug("%s: pll %s@%lu: Hz\n", __func__, __clk_get_name(hw->clk), + drate); + pr_debug("old - fbdiv: %d, postdiv1: %d, refdiv: %d, postdiv2: %d, dsmpd: %d, frac: %d\n", + cur.fbdiv, cur.postdiv1, cur.refdiv, cur.postdiv2, + cur.dsmpd, cur.frac); + pr_debug("new - fbdiv: %d, postdiv1: %d, refdiv: %d, postdiv2: %d, dsmpd: %d, frac: %d\n", + rate->fbdiv, rate->postdiv1, rate->refdiv, rate->postdiv2, + rate->dsmpd, rate->frac); + + if (rate->fbdiv != cur.fbdiv || rate->postdiv1 != cur.postdiv1 || + rate->refdiv != cur.refdiv || rate->postdiv2 != cur.postdiv2 || + rate->dsmpd != cur.dsmpd || rate->frac != cur.frac) { + struct clk *parent = clk_get_parent(hw->clk); + + if (!parent) { + pr_warn("%s: parent of %s not available\n", + __func__, __clk_get_name(hw->clk)); + return; + } + + pr_debug("%s: pll %s: rate params do not match rate table, adjusting\n", + __func__, __clk_get_name(hw->clk)); + rockchip_rk3036_pll_set_params(pll, rate); + } +} + +static const struct clk_ops rockchip_rk3036_pll_clk_norate_ops = { + .recalc_rate = rockchip_rk3036_pll_recalc_rate, + .enable = rockchip_rk3036_pll_enable, + .disable = rockchip_rk3036_pll_disable, + .is_enabled = rockchip_rk3036_pll_is_enabled, +}; + +static const struct clk_ops rockchip_rk3036_pll_clk_ops = { + .recalc_rate = rockchip_rk3036_pll_recalc_rate, + .round_rate = rockchip_pll_round_rate, + .set_rate = rockchip_rk3036_pll_set_rate, + .enable = rockchip_rk3036_pll_enable, + .disable = rockchip_rk3036_pll_disable, + .is_enabled = rockchip_rk3036_pll_is_enabled, + .init = rockchip_rk3036_pll_init, +}; + +/** * PLL used in RK3066, RK3188 and RK3288 */ @@ -376,7 +626,7 @@ struct clk *rockchip_clk_register_pll(enum rockchip_pll_type pll_type, pll_mux->lock = lock; pll_mux->hw.init = &init; - if (pll_type == pll_rk3066) + if (pll_type == pll_rk3036 || pll_type == pll_rk3066) pll_mux->flags |= CLK_MUX_HIWORD_MASK; /* the actual muxing is xin24m, pll-output, xin32k */ @@ -421,6 +671,12 @@ struct clk *rockchip_clk_register_pll(enum rockchip_pll_type pll_type, } switch (pll_type) { + case pll_rk3036: + if (!pll->rate_table) + init.ops = &rockchip_rk3036_pll_clk_norate_ops; + else + init.ops = &rockchip_rk3036_pll_clk_ops; + break; case pll_rk3066: if (!pll->rate_table) init.ops = &rockchip_rk3066_pll_clk_norate_ops; diff --git a/drivers/clk/rockchip/clk-rk3036.c b/drivers/clk/rockchip/clk-rk3036.c new file mode 100644 index 000000000000..7333b05342ff --- /dev/null +++ b/drivers/clk/rockchip/clk-rk3036.c @@ -0,0 +1,478 @@ +/* + * Copyright (c) 2014 MundoReader S.L. + * Author: Heiko Stuebner <heiko@sntech.de> + * + * Copyright (c) 2015 Rockchip Electronics Co. Ltd. + * Author: Xing Zheng <zhengxing@rock-chips.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include <linux/clk-provider.h> +#include <linux/of.h> +#include <linux/of_address.h> +#include <linux/syscore_ops.h> +#include <dt-bindings/clock/rk3036-cru.h> +#include "clk.h" + +#define RK3036_GRF_SOC_STATUS0 0x14c + +enum rk3036_plls { + apll, dpll, gpll, +}; + +static struct rockchip_pll_rate_table rk3036_pll_rates[] = { + /* _mhz, _refdiv, _fbdiv, _postdiv1, _postdiv2, _dsmpd, _frac */ + RK3036_PLL_RATE(1608000000, 1, 67, 1, 1, 1, 0), + RK3036_PLL_RATE(1584000000, 1, 66, 1, 1, 1, 0), + RK3036_PLL_RATE(1560000000, 1, 65, 1, 1, 1, 0), + RK3036_PLL_RATE(1536000000, 1, 64, 1, 1, 1, 0), + RK3036_PLL_RATE(1512000000, 1, 63, 1, 1, 1, 0), + RK3036_PLL_RATE(1488000000, 1, 62, 1, 1, 1, 0), + RK3036_PLL_RATE(1464000000, 1, 61, 1, 1, 1, 0), + RK3036_PLL_RATE(1440000000, 1, 60, 1, 1, 1, 0), + RK3036_PLL_RATE(1416000000, 1, 59, 1, 1, 1, 0), + RK3036_PLL_RATE(1392000000, 1, 58, 1, 1, 1, 0), + RK3036_PLL_RATE(1368000000, 1, 57, 1, 1, 1, 0), + RK3036_PLL_RATE(1344000000, 1, 56, 1, 1, 1, 0), + RK3036_PLL_RATE(1320000000, 1, 55, 1, 1, 1, 0), + RK3036_PLL_RATE(1296000000, 1, 54, 1, 1, 1, 0), + RK3036_PLL_RATE(1272000000, 1, 53, 1, 1, 1, 0), + RK3036_PLL_RATE(1248000000, 1, 52, 1, 1, 1, 0), + RK3036_PLL_RATE(1200000000, 1, 50, 1, 1, 1, 0), + RK3036_PLL_RATE(1188000000, 2, 99, 1, 1, 1, 0), + RK3036_PLL_RATE(1104000000, 1, 46, 1, 1, 1, 0), + RK3036_PLL_RATE(1100000000, 12, 550, 1, 1, 1, 0), + RK3036_PLL_RATE(1008000000, 1, 84, 2, 1, 1, 0), + RK3036_PLL_RATE(1000000000, 6, 500, 2, 1, 1, 0), + RK3036_PLL_RATE( 984000000, 1, 82, 2, 1, 1, 0), + RK3036_PLL_RATE( 960000000, 1, 80, 2, 1, 1, 0), + RK3036_PLL_RATE( 936000000, 1, 78, 2, 1, 1, 0), + RK3036_PLL_RATE( 912000000, 1, 76, 2, 1, 1, 0), + RK3036_PLL_RATE( 900000000, 4, 300, 2, 1, 1, 0), + RK3036_PLL_RATE( 888000000, 1, 74, 2, 1, 1, 0), + RK3036_PLL_RATE( 864000000, 1, 72, 2, 1, 1, 0), + RK3036_PLL_RATE( 840000000, 1, 70, 2, 1, 1, 0), + RK3036_PLL_RATE( 816000000, 1, 68, 2, 1, 1, 0), + RK3036_PLL_RATE( 800000000, 6, 400, 2, 1, 1, 0), + RK3036_PLL_RATE( 700000000, 6, 350, 2, 1, 1, 0), + RK3036_PLL_RATE( 696000000, 1, 58, 2, 1, 1, 0), + RK3036_PLL_RATE( 600000000, 1, 75, 3, 1, 1, 0), + RK3036_PLL_RATE( 594000000, 2, 99, 2, 1, 1, 0), + RK3036_PLL_RATE( 504000000, 1, 63, 3, 1, 1, 0), + RK3036_PLL_RATE( 500000000, 6, 250, 2, 1, 1, 0), + RK3036_PLL_RATE( 408000000, 1, 68, 2, 2, 1, 0), + RK3036_PLL_RATE( 312000000, 1, 52, 2, 2, 1, 0), + RK3036_PLL_RATE( 216000000, 1, 72, 4, 2, 1, 0), + RK3036_PLL_RATE( 96000000, 1, 64, 4, 4, 1, 0), + { /* sentinel */ }, +}; + +#define RK3036_DIV_CPU_MASK 0x1f +#define RK3036_DIV_CPU_SHIFT 8 + +#define RK3036_DIV_PERI_MASK 0xf +#define RK3036_DIV_PERI_SHIFT 0 +#define RK3036_DIV_ACLK_MASK 0x7 +#define RK3036_DIV_ACLK_SHIFT 4 +#define RK3036_DIV_HCLK_MASK 0x3 +#define RK3036_DIV_HCLK_SHIFT 8 +#define RK3036_DIV_PCLK_MASK 0x7 +#define RK3036_DIV_PCLK_SHIFT 12 + +#define RK3036_CLKSEL1(_core_periph_div) \ + { \ + .reg = RK2928_CLKSEL_CON(1), \ + .val = HIWORD_UPDATE(_core_periph_div, RK3036_DIV_PERI_MASK, \ + RK3036_DIV_PERI_SHIFT) \ + } + +#define RK3036_CPUCLK_RATE(_prate, _core_periph_div) \ + { \ + .prate = _prate, \ + .divs = { \ + RK3036_CLKSEL1(_core_periph_div), \ + }, \ + } + +static struct rockchip_cpuclk_rate_table rk3036_cpuclk_rates[] __initdata = { + RK3036_CPUCLK_RATE(816000000, 4), + RK3036_CPUCLK_RATE(600000000, 4), + RK3036_CPUCLK_RATE(312000000, 4), +}; + +static const struct rockchip_cpuclk_reg_data rk3036_cpuclk_data = { + .core_reg = RK2928_CLKSEL_CON(0), + .div_core_shift = 0, + .div_core_mask = 0x1f, + .mux_core_shift = 7, +}; + +PNAME(mux_pll_p) = { "xin24m", "xin24m" }; + +PNAME(mux_armclk_p) = { "apll", "gpll_armclk" }; +PNAME(mux_busclk_p) = { "apll", "dpll_cpu", "gpll_cpu" }; +PNAME(mux_ddrphy_p) = { "dpll_ddr", "gpll_ddr" }; +PNAME(mux_pll_src_3plls_p) = { "apll", "dpll", "gpll" }; +PNAME(mux_timer_p) = { "xin24m", "pclk_peri_src" }; + +PNAME(mux_pll_src_apll_dpll_gpll_usb480m_p) = { "apll", "dpll", "gpll" "usb480m" }; + +PNAME(mux_mmc_src_p) = { "apll", "dpll", "gpll", "xin24m" }; +PNAME(mux_i2s_pre_p) = { "i2s_src", "i2s_frac", "ext_i2s", "xin12m" }; +PNAME(mux_i2s_clkout_p) = { "i2s_pre", "xin12m" }; +PNAME(mux_spdif_p) = { "spdif_src", "spdif_frac", "xin12m" }; +PNAME(mux_uart0_p) = { "uart0_src", "uart0_frac", "xin24m" }; +PNAME(mux_uart1_p) = { "uart1_src", "uart1_frac", "xin24m" }; +PNAME(mux_uart2_p) = { "uart2_src", "uart2_frac", "xin24m" }; +PNAME(mux_mac_p) = { "mac_pll_src", "ext_gmac" }; +PNAME(mux_dclk_p) = { "dclk_lcdc", "dclk_cru" }; + +static struct rockchip_pll_clock rk3036_pll_clks[] __initdata = { + [apll] = PLL(pll_rk3036, PLL_APLL, "apll", mux_pll_p, 0, RK2928_PLL_CON(0), + RK2928_MODE_CON, 0, 5, 0, rk3036_pll_rates), + [dpll] = PLL(pll_rk3036, PLL_DPLL, "dpll", mux_pll_p, 0, RK2928_PLL_CON(4), + RK2928_MODE_CON, 4, 4, 0, NULL), + [gpll] = PLL(pll_rk3036, PLL_GPLL, "gpll", mux_pll_p, 0, RK2928_PLL_CON(12), + RK2928_MODE_CON, 12, 6, ROCKCHIP_PLL_SYNC_RATE, rk3036_pll_rates), +}; + +#define MFLAGS CLK_MUX_HIWORD_MASK +#define DFLAGS CLK_DIVIDER_HIWORD_MASK +#define GFLAGS (CLK_GATE_HIWORD_MASK | CLK_GATE_SET_TO_DISABLE) + +static struct rockchip_clk_branch rk3036_clk_branches[] __initdata = { + /* + * Clock-Architecture Diagram 1 + */ + + GATE(0, "gpll_armclk", "gpll", CLK_IGNORE_UNUSED, + RK2928_CLKGATE_CON(0), 6, GFLAGS), + + /* + * Clock-Architecture Diagram 2 + */ + + GATE(0, "dpll_ddr", "dpll", CLK_IGNORE_UNUSED, + RK2928_CLKGATE_CON(0), 2, GFLAGS), + GATE(0, "gpll_ddr", "gpll", CLK_IGNORE_UNUSED, + RK2928_CLKGATE_CON(0), 8, GFLAGS), + COMPOSITE_NOGATE(0, "ddrphy2x", mux_ddrphy_p, CLK_IGNORE_UNUSED, + RK2928_CLKSEL_CON(26), 8, 1, MFLAGS, 0, 2, DFLAGS | CLK_DIVIDER_POWER_OF_TWO), + + COMPOSITE_NOMUX(0, "pclk_dbg", "armclk", CLK_IGNORE_UNUSED, + RK2928_CLKSEL_CON(1), 0, 4, DFLAGS | CLK_DIVIDER_READ_ONLY, + RK2928_CLKGATE_CON(0), 7, GFLAGS), + COMPOSITE_NOMUX(0, "aclk_core_pre", "armclk", CLK_IGNORE_UNUSED, + RK2928_CLKSEL_CON(1), 4, 3, DFLAGS | CLK_DIVIDER_READ_ONLY, + RK2928_CLKGATE_CON(0), 7, GFLAGS), + + GATE(0, "dpll_cpu", "dpll", 0, RK2928_CLKGATE_CON(10), 8, GFLAGS), + GATE(0, "gpll_cpu", "gpll", 0, RK2928_CLKGATE_CON(0), 1, GFLAGS), + COMPOSITE_NOGATE(0, "aclk_cpu_src", mux_busclk_p, 0, + RK2928_CLKSEL_CON(0), 14, 2, MFLAGS, 8, 5, DFLAGS), + GATE(ACLK_CPU, "aclk_cpu", "aclk_cpu_src", CLK_IGNORE_UNUSED, + RK2928_CLKGATE_CON(0), 3, GFLAGS), + COMPOSITE_NOMUX(PCLK_CPU, "pclk_cpu", "aclk_cpu_src", CLK_IGNORE_UNUSED, + RK2928_CLKSEL_CON(1), 12, 3, DFLAGS | CLK_DIVIDER_READ_ONLY, + RK2928_CLKGATE_CON(0), 5, GFLAGS), + COMPOSITE_NOMUX(HCLK_CPU, "hclk_cpu", "aclk_cpu_src", CLK_IGNORE_UNUSED, + RK2928_CLKSEL_CON(1), 8, 2, DFLAGS | CLK_DIVIDER_READ_ONLY, + RK2928_CLKGATE_CON(0), 4, GFLAGS), + + COMPOSITE(0, "aclk_peri_src", mux_pll_src_3plls_p, 0, + RK2928_CLKSEL_CON(10), 14, 2, MFLAGS, 0, 5, DFLAGS, + RK2928_CLKGATE_CON(2), 0, GFLAGS), + + GATE(ACLK_PERI, "aclk_peri", "aclk_peri_src", 0, + RK2928_CLKGATE_CON(2), 1, GFLAGS), + DIV(0, "pclk_peri_src", "aclk_peri_src", CLK_IGNORE_UNUSED, + RK2928_CLKSEL_CON(10), 12, 2, DFLAGS | CLK_DIVIDER_POWER_OF_TWO), + GATE(PCLK_PERI, "pclk_peri", "pclk_peri_src", 0, + RK2928_CLKGATE_CON(2), 3, GFLAGS), + DIV(0, "hclk_peri_src", "aclk_peri_src", CLK_IGNORE_UNUSED, + RK2928_CLKSEL_CON(10), 8, 2, DFLAGS | CLK_DIVIDER_POWER_OF_TWO), + GATE(HCLK_PERI, "hclk_peri", "hclk_peri_src", 0, + RK2928_CLKGATE_CON(2), 2, GFLAGS), + + COMPOSITE_NODIV(SCLK_TIMER0, "sclk_timer0", mux_timer_p, CLK_IGNORE_UNUSED, + RK2928_CLKSEL_CON(2), 4, 1, DFLAGS, + RK2928_CLKGATE_CON(1), 0, GFLAGS), + COMPOSITE_NODIV(SCLK_TIMER1, "sclk_timer1", mux_timer_p, CLK_IGNORE_UNUSED, + RK2928_CLKSEL_CON(2), 5, 1, DFLAGS, + RK2928_CLKGATE_CON(1), 1, GFLAGS), + COMPOSITE_NODIV(SCLK_TIMER2, "sclk_timer2", mux_timer_p, CLK_IGNORE_UNUSED, + RK2928_CLKSEL_CON(2), 6, 1, DFLAGS, + RK2928_CLKGATE_CON(2), 4, GFLAGS), + COMPOSITE_NODIV(SCLK_TIMER3, "sclk_timer3", mux_timer_p, CLK_IGNORE_UNUSED, + RK2928_CLKSEL_CON(2), 7, 1, DFLAGS, + RK2928_CLKGATE_CON(2), 5, GFLAGS), + + MUX(0, "uart_pll_clk", mux_pll_src_apll_dpll_gpll_usb480m_p, 0, + RK2928_CLKSEL_CON(13), 10, 2, MFLAGS), + COMPOSITE_NOMUX(0, "uart0_src", "uart_pll_clk", 0, + RK2928_CLKSEL_CON(13), 0, 7, DFLAGS, + RK2928_CLKGATE_CON(1), 8, GFLAGS), + COMPOSITE_NOMUX(0, "uart1_src", "uart_pll_clk", 0, + RK2928_CLKSEL_CON(13), 0, 7, DFLAGS, + RK2928_CLKGATE_CON(1), 8, GFLAGS), + COMPOSITE_NOMUX(0, "uart2_src", "uart_pll_clk", 0, + RK2928_CLKSEL_CON(13), 0, 7, DFLAGS, + RK2928_CLKGATE_CON(1), 8, GFLAGS), + COMPOSITE_FRAC(0, "uart0_frac", "uart0_src", CLK_SET_RATE_PARENT, + RK2928_CLKSEL_CON(17), 0, + RK2928_CLKGATE_CON(1), 9, GFLAGS), + COMPOSITE_FRAC(0, "uart1_frac", "uart1_src", CLK_SET_RATE_PARENT, + RK2928_CLKSEL_CON(18), 0, + RK2928_CLKGATE_CON(1), 11, GFLAGS), + COMPOSITE_FRAC(0, "uart2_frac", "uart2_src", CLK_SET_RATE_PARENT, + RK2928_CLKSEL_CON(19), 0, + RK2928_CLKGATE_CON(1), 13, GFLAGS), + MUX(SCLK_UART0, "sclk_uart0", mux_uart0_p, CLK_SET_RATE_PARENT, + RK2928_CLKSEL_CON(13), 8, 2, MFLAGS), + MUX(SCLK_UART1, "sclk_uart1", mux_uart1_p, CLK_SET_RATE_PARENT, + RK2928_CLKSEL_CON(14), 8, 2, MFLAGS), + MUX(SCLK_UART2, "sclk_uart2", mux_uart2_p, CLK_SET_RATE_PARENT, + RK2928_CLKSEL_CON(15), 8, 2, MFLAGS), + + COMPOSITE(0, "aclk_vcodec", mux_pll_src_3plls_p, 0, + RK2928_CLKSEL_CON(32), 14, 2, MFLAGS, 8, 5, DFLAGS, + RK2928_CLKGATE_CON(3), 11, GFLAGS), + + COMPOSITE(0, "aclk_hvec", mux_pll_src_3plls_p, 0, + RK2928_CLKSEL_CON(20), 0, 2, MFLAGS, 2, 5, DFLAGS, + RK2928_CLKGATE_CON(10), 6, GFLAGS), + + COMPOSITE(0, "aclk_disp1_pre", mux_pll_src_3plls_p, 0, + RK2928_CLKSEL_CON(31), 14, 2, MFLAGS, 8, 5, DFLAGS, + RK2928_CLKGATE_CON(1), 4, GFLAGS), + COMPOSITE(0, "hclk_disp_pre", mux_pll_src_3plls_p, 0, + RK2928_CLKSEL_CON(30), 14, 2, MFLAGS, 8, 5, DFLAGS, + RK2928_CLKGATE_CON(0), 11, GFLAGS), + COMPOSITE(SCLK_LCDC, "dclk_lcdc", mux_pll_src_3plls_p, 0, + RK2928_CLKSEL_CON(28), 0, 2, MFLAGS, 8, 8, DFLAGS, + RK2928_CLKGATE_CON(3), 2, GFLAGS), + + COMPOSITE_NODIV(0, "sclk_sdmmc_src", mux_mmc_src_p, 0, + RK2928_CLKSEL_CON(12), 8, 2, DFLAGS, + RK2928_CLKGATE_CON(2), 11, GFLAGS), + DIV(SCLK_SDMMC, "sclk_sdmmc", "sclk_sdmmc_src", 0, + RK2928_CLKSEL_CON(11), 0, 7, DFLAGS), + + COMPOSITE_NODIV(0, "sclk_sdio_src", mux_mmc_src_p, 0, + RK2928_CLKSEL_CON(12), 10, 2, DFLAGS, + RK2928_CLKGATE_CON(2), 13, GFLAGS), + DIV(SCLK_SDIO, "sclk_sdio", "sclk_sdio_src", 0, + RK2928_CLKSEL_CON(11), 8, 7, DFLAGS), + + COMPOSITE(SCLK_EMMC, "sclk_emmc", mux_mmc_src_p, 0, + RK2928_CLKSEL_CON(12), 12, 2, MFLAGS, 0, 7, DFLAGS, + RK2928_CLKGATE_CON(2), 14, GFLAGS), + + MMC(SCLK_SDMMC_DRV, "sdmmc_drv", "sclk_sdmmc", RK3036_SDMMC_CON0, 1), + MMC(SCLK_SDMMC_SAMPLE, "sdmmc_sample", "sclk_sdmmc", RK3036_SDMMC_CON1, 0), + + MMC(SCLK_SDIO_DRV, "sdio_drv", "sclk_sdio", RK3036_SDIO_CON0, 1), + MMC(SCLK_SDIO_SAMPLE, "sdio_sample", "sclk_sdio", RK3036_SDIO_CON1, 0), + + MMC(SCLK_EMMC_DRV, "emmc_drv", "sclk_emmc", RK3036_EMMC_CON0, 1), + MMC(SCLK_EMMC_SAMPLE, "emmc_sample", "sclk_emmc", RK3036_EMMC_CON1, 0), + + COMPOSITE(0, "i2s_src", mux_pll_src_3plls_p, 0, + RK2928_CLKSEL_CON(3), 14, 2, MFLAGS, 0, 7, DFLAGS, + RK2928_CLKGATE_CON(0), 9, GFLAGS), + COMPOSITE_FRAC(0, "i2s_frac", "i2s_src", CLK_SET_RATE_PARENT, + RK2928_CLKSEL_CON(7), 0, + RK2928_CLKGATE_CON(0), 10, GFLAGS), + MUX(0, "i2s_pre", mux_i2s_pre_p, CLK_SET_RATE_PARENT, + RK2928_CLKSEL_CON(3), 8, 2, MFLAGS), + COMPOSITE_NODIV(SCLK_I2S_OUT, "i2s_clkout", mux_i2s_clkout_p, 0, + RK2928_CLKSEL_CON(3), 12, 1, MFLAGS, + RK2928_CLKGATE_CON(0), 13, GFLAGS), + GATE(SCLK_I2S, "sclk_i2s", "i2s_pre", CLK_SET_RATE_PARENT, + RK2928_CLKGATE_CON(0), 14, GFLAGS), + + COMPOSITE(0, "spdif_src", mux_pll_src_3plls_p, 0, + RK2928_CLKSEL_CON(5), 10, 2, MFLAGS, 0, 7, DFLAGS, + RK2928_CLKGATE_CON(2), 10, GFLAGS), + COMPOSITE_FRAC(0, "spdif_frac", "spdif_src", 0, + RK2928_CLKSEL_CON(9), 0, + RK2928_CLKGATE_CON(2), 12, GFLAGS), + MUX(SCLK_SPDIF, "sclk_spdif", mux_spdif_p, 0, + RK2928_CLKSEL_CON(5), 8, 2, MFLAGS), + + GATE(SCLK_OTGPHY0, "sclk_otgphy0", "xin12m", CLK_IGNORE_UNUSED, + RK2928_CLKGATE_CON(1), 5, GFLAGS), + + COMPOSITE(SCLK_GPU, "sclk_gpu", mux_pll_src_3plls_p, 0, + RK2928_CLKSEL_CON(34), 8, 2, MFLAGS, 0, 5, DFLAGS, + RK2928_CLKGATE_CON(3), 13, GFLAGS), + + COMPOSITE(SCLK_SPI, "sclk_spi", mux_pll_src_3plls_p, 0, + RK2928_CLKSEL_CON(25), 8, 2, MFLAGS, 0, 7, DFLAGS, + RK2928_CLKGATE_CON(2), 9, GFLAGS), + + COMPOSITE(SCLK_NANDC, "sclk_nandc", mux_pll_src_3plls_p, 0, + RK2928_CLKSEL_CON(16), 8, 2, MFLAGS, 10, 5, DFLAGS, + RK2928_CLKGATE_CON(10), 4, GFLAGS), + + COMPOSITE(SCLK_SFC, "sclk_sfc", mux_pll_src_apll_dpll_gpll_usb480m_p, 0, + RK2928_CLKSEL_CON(16), 0, 2, MFLAGS, 2, 5, DFLAGS, + RK2928_CLKGATE_CON(10), 5, GFLAGS), + + COMPOSITE_NOGATE(0, "mac_pll_src", mux_pll_src_3plls_p, 0, + RK2928_CLKSEL_CON(21), 0, 2, MFLAGS, 4, 5, DFLAGS), + MUX(SCLK_MACREF, "mac_clk_ref", mux_mac_p, CLK_SET_RATE_PARENT, + RK2928_CLKSEL_CON(21), 3, 1, MFLAGS), + + COMPOSITE_NOMUX(SCLK_MAC, "mac_clk", "mac_clk_ref", 0, + RK2928_CLKSEL_CON(21), 9, 5, DFLAGS, + RK2928_CLKGATE_CON(2), 6, GFLAGS), + + MUX(SCLK_HDMI, "dclk_hdmi", mux_dclk_p, 0, + RK2928_CLKSEL_CON(31), 0, 1, MFLAGS), + + /* + * Clock-Architecture Diagram 3 + */ + + /* aclk_cpu gates */ + GATE(0, "sclk_intmem", "aclk_cpu", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(4), 12, GFLAGS), + GATE(0, "aclk_strc_sys", "aclk_cpu", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(4), 10, GFLAGS), + + /* hclk_cpu gates */ + GATE(HCLK_ROM, "hclk_rom", "hclk_cpu", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(5), 6, GFLAGS), + + /* pclk_cpu gates */ + GATE(PCLK_GRF, "pclk_grf", "pclk_cpu", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(5), 4, GFLAGS), + GATE(PCLK_DDRUPCTL, "pclk_ddrupctl", "pclk_cpu", 0, RK2928_CLKGATE_CON(5), 7, GFLAGS), + GATE(PCLK_ACODEC, "pclk_acodec", "pclk_cpu", 0, RK2928_CLKGATE_CON(5), 14, GFLAGS), + GATE(PCLK_HDMI, "pclk_hdmi", "pclk_cpu", 0, RK2928_CLKGATE_CON(3), 8, GFLAGS), + + /* aclk_vio gates */ + GATE(ACLK_VIO, "aclk_vio", "aclk_disp1_pre", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(6), 13, GFLAGS), + GATE(ACLK_LCDC, "aclk_lcdc", "aclk_disp1_pre", 0, RK2928_CLKGATE_CON(9), 6, GFLAGS), + + GATE(HCLK_VIO_BUS, "hclk_vio_bus", "hclk_disp_pre", 0, RK2928_CLKGATE_CON(6), 12, GFLAGS), + GATE(HCLK_LCDC, "hclk_lcdc", "hclk_disp_pre", 0, RK2928_CLKGATE_CON(9), 5, GFLAGS), + + /* hclk_video gates */ + GATE(HCLK_VCODEC, "hclk_vcodec", "hclk_disp_pre", 0, RK2928_CLKGATE_CON(3), 12, GFLAGS), + + /* xin24m gates */ + GATE(SCLK_PVTM_CORE, "sclk_pvtm_core", "xin24m", 0, RK2928_CLKGATE_CON(10), 0, GFLAGS), + GATE(SCLK_PVTM_GPU, "sclk_pvtm_gpu", "xin24m", 0, RK2928_CLKGATE_CON(10), 1, GFLAGS), + + /* aclk_peri gates */ + GATE(0, "aclk_peri_axi_matrix", "aclk_peri", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(4), 3, GFLAGS), + GATE(0, "aclk_cpu_peri", "aclk_peri", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(4), 2, GFLAGS), + GATE(ACLK_DMAC2, "aclk_dmac2", "aclk_peri", 0, RK2928_CLKGATE_CON(5), 1, GFLAGS), + GATE(0, "aclk_peri_niu", "aclk_peri", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(9), 15, GFLAGS), + + /* hclk_peri gates */ + GATE(0, "hclk_peri_matrix", "hclk_peri", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(4), 0, GFLAGS), + GATE(0, "hclk_usb_peri", "hclk_peri", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(9), 13, GFLAGS), + GATE(0, "hclk_peri_arbi", "hclk_peri", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(9), 14, GFLAGS), + GATE(HCLK_NANDC, "hclk_nandc", "hclk_peri", 0, RK2928_CLKGATE_CON(5), 9, GFLAGS), + GATE(HCLK_SDMMC, "hclk_sdmmc", "hclk_peri", 0, RK2928_CLKGATE_CON(5), 10, GFLAGS), + GATE(HCLK_SDIO, "hclk_sdio", "hclk_peri", 0, RK2928_CLKGATE_CON(5), 11, GFLAGS), + GATE(HCLK_EMMC, "hclk_emmc", "hclk_peri", 0, RK2928_CLKGATE_CON(7), 0, GFLAGS), + GATE(HCLK_OTG0, "hclk_otg0", "hclk_peri", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(5), 13, GFLAGS), + GATE(HCLK_OTG1, "hclk_otg1", "hclk_peri", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(7), 3, GFLAGS), + GATE(HCLK_I2S, "hclk_i2s", "hclk_peri", 0, RK2928_CLKGATE_CON(7), 2, GFLAGS), + GATE(0, "hclk_sfc", "hclk_peri", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(3), 14, GFLAGS), + GATE(0, "hclk_mac", "hclk_peri", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(3), 15, GFLAGS), + + /* pclk_peri gates */ + GATE(0, "pclk_peri_matrix", "pclk_peri", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(4), 1, GFLAGS), + GATE(0, "pclk_efuse", "pclk_peri", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(5), 2, GFLAGS), + GATE(PCLK_TIMER, "pclk_timer", "pclk_peri", 0, RK2928_CLKGATE_CON(7), 7, GFLAGS), + GATE(PCLK_PWM, "pclk_pwm", "pclk_peri", 0, RK2928_CLKGATE_CON(7), 10, GFLAGS), + GATE(PCLK_SPI, "pclk_spi", "pclk_peri", 0, RK2928_CLKGATE_CON(7), 12, GFLAGS), + GATE(PCLK_WDT, "pclk_wdt", "pclk_peri", 0, RK2928_CLKGATE_CON(7), 15, GFLAGS), + GATE(PCLK_UART0, "pclk_uart0", "pclk_peri", 0, RK2928_CLKGATE_CON(8), 0, GFLAGS), + GATE(PCLK_UART1, "pclk_uart1", "pclk_peri", 0, RK2928_CLKGATE_CON(8), 1, GFLAGS), + GATE(PCLK_UART2, "pclk_uart2", "pclk_peri", 0, RK2928_CLKGATE_CON(8), 2, GFLAGS), + GATE(PCLK_I2C0, "pclk_i2c0", "pclk_peri", 0, RK2928_CLKGATE_CON(8), 4, GFLAGS), + GATE(PCLK_I2C1, "pclk_i2c1", "pclk_peri", 0, RK2928_CLKGATE_CON(8), 5, GFLAGS), + GATE(PCLK_I2C2, "pclk_i2c2", "pclk_peri", 0, RK2928_CLKGATE_CON(8), 6, GFLAGS), + GATE(PCLK_GPIO0, "pclk_gpio0", "pclk_peri", 0, RK2928_CLKGATE_CON(8), 9, GFLAGS), + GATE(PCLK_GPIO1, "pclk_gpio1", "pclk_peri", 0, RK2928_CLKGATE_CON(8), 10, GFLAGS), + GATE(PCLK_GPIO2, "pclk_gpio2", "pclk_peri", 0, RK2928_CLKGATE_CON(8), 11, GFLAGS), +}; + +static const char *const rk3036_critical_clocks[] __initconst = { + "aclk_cpu", + "aclk_peri", + "hclk_peri", + "pclk_peri", +}; + +static void __init rk3036_clk_init(struct device_node *np) +{ + void __iomem *reg_base; + struct clk *clk; + + reg_base = of_iomap(np, 0); + if (!reg_base) { + pr_err("%s: could not map cru region\n", __func__); + return; + } + + rockchip_clk_init(np, reg_base, CLK_NR_CLKS); + + /* xin12m is created by an cru-internal divider */ + clk = clk_register_fixed_factor(NULL, "xin12m", "xin24m", 0, 1, 2); + if (IS_ERR(clk)) + pr_warn("%s: could not register clock xin12m: %ld\n", + __func__, PTR_ERR(clk)); + + clk = clk_register_fixed_factor(NULL, "usb480m", "xin24m", 0, 20, 1); + if (IS_ERR(clk)) + pr_warn("%s: could not register clock usb480m: %ld\n", + __func__, PTR_ERR(clk)); + + clk = clk_register_fixed_factor(NULL, "ddrphy", "ddrphy2x", 0, 1, 2); + if (IS_ERR(clk)) + pr_warn("%s: could not register clock ddrphy: %ld\n", + __func__, PTR_ERR(clk)); + + clk = clk_register_fixed_factor(NULL, "hclk_vcodec_pre", + "aclk_vcodec", 0, 1, 4); + if (IS_ERR(clk)) + pr_warn("%s: could not register clock hclk_vcodec_pre: %ld\n", + __func__, PTR_ERR(clk)); + + clk = clk_register_fixed_factor(NULL, "sclk_macref_out", + "hclk_peri_src", 0, 1, 2); + if (IS_ERR(clk)) + pr_warn("%s: could not register clock sclk_macref_out: %ld\n", + __func__, PTR_ERR(clk)); + + rockchip_clk_register_plls(rk3036_pll_clks, + ARRAY_SIZE(rk3036_pll_clks), + RK3036_GRF_SOC_STATUS0); + rockchip_clk_register_branches(rk3036_clk_branches, + ARRAY_SIZE(rk3036_clk_branches)); + rockchip_clk_protect_critical(rk3036_critical_clocks, + ARRAY_SIZE(rk3036_critical_clocks)); + + rockchip_clk_register_armclk(ARMCLK, "armclk", + mux_armclk_p, ARRAY_SIZE(mux_armclk_p), + &rk3036_cpuclk_data, rk3036_cpuclk_rates, + ARRAY_SIZE(rk3036_cpuclk_rates)); + + rockchip_register_softrst(np, 9, reg_base + RK2928_SOFTRST_CON(0), + ROCKCHIP_SOFTRST_HIWORD_MASK); + + rockchip_register_restart_notifier(RK2928_GLB_SRST_FST, NULL); +} +CLK_OF_DECLARE(rk3036_cru, "rockchip,rk3036-cru", rk3036_clk_init); diff --git a/drivers/clk/rockchip/clk-rk3188.c b/drivers/clk/rockchip/clk-rk3188.c index abb47608713b..c2c35d4cdda8 100644 --- a/drivers/clk/rockchip/clk-rk3188.c +++ b/drivers/clk/rockchip/clk-rk3188.c @@ -750,7 +750,7 @@ static void __init rk3188_common_clk_init(struct device_node *np) rockchip_register_softrst(np, 9, reg_base + RK2928_SOFTRST_CON(0), ROCKCHIP_SOFTRST_HIWORD_MASK); - rockchip_register_restart_notifier(RK2928_GLB_SRST_FST); + rockchip_register_restart_notifier(RK2928_GLB_SRST_FST, NULL); } static void __init rk3066a_clk_init(struct device_node *np) diff --git a/drivers/clk/rockchip/clk-rk3228.c b/drivers/clk/rockchip/clk-rk3228.c new file mode 100644 index 000000000000..981a50205339 --- /dev/null +++ b/drivers/clk/rockchip/clk-rk3228.c @@ -0,0 +1,678 @@ +/* + * Copyright (c) 2015 Rockchip Electronics Co. Ltd. + * Author: Xing Zheng <zhengxing@rock-chips.com> + * Jeffy Chen <jeffy.chen@rock-chips.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include <linux/clk-provider.h> +#include <linux/of.h> +#include <linux/of_address.h> +#include <linux/syscore_ops.h> +#include <dt-bindings/clock/rk3228-cru.h> +#include "clk.h" + +#define RK3228_GRF_SOC_STATUS0 0x480 + +enum rk3228_plls { + apll, dpll, cpll, gpll, +}; + +static struct rockchip_pll_rate_table rk3228_pll_rates[] = { + /* _mhz, _refdiv, _fbdiv, _postdiv1, _postdiv2, _dsmpd, _frac */ + RK3036_PLL_RATE(1608000000, 1, 67, 1, 1, 1, 0), + RK3036_PLL_RATE(1584000000, 1, 66, 1, 1, 1, 0), + RK3036_PLL_RATE(1560000000, 1, 65, 1, 1, 1, 0), + RK3036_PLL_RATE(1536000000, 1, 64, 1, 1, 1, 0), + RK3036_PLL_RATE(1512000000, 1, 63, 1, 1, 1, 0), + RK3036_PLL_RATE(1488000000, 1, 62, 1, 1, 1, 0), + RK3036_PLL_RATE(1464000000, 1, 61, 1, 1, 1, 0), + RK3036_PLL_RATE(1440000000, 1, 60, 1, 1, 1, 0), + RK3036_PLL_RATE(1416000000, 1, 59, 1, 1, 1, 0), + RK3036_PLL_RATE(1392000000, 1, 58, 1, 1, 1, 0), + RK3036_PLL_RATE(1368000000, 1, 57, 1, 1, 1, 0), + RK3036_PLL_RATE(1344000000, 1, 56, 1, 1, 1, 0), + RK3036_PLL_RATE(1320000000, 1, 55, 1, 1, 1, 0), + RK3036_PLL_RATE(1296000000, 1, 54, 1, 1, 1, 0), + RK3036_PLL_RATE(1272000000, 1, 53, 1, 1, 1, 0), + RK3036_PLL_RATE(1248000000, 1, 52, 1, 1, 1, 0), + RK3036_PLL_RATE(1200000000, 1, 50, 1, 1, 1, 0), + RK3036_PLL_RATE(1188000000, 2, 99, 1, 1, 1, 0), + RK3036_PLL_RATE(1104000000, 1, 46, 1, 1, 1, 0), + RK3036_PLL_RATE(1100000000, 12, 550, 1, 1, 1, 0), + RK3036_PLL_RATE(1008000000, 1, 84, 2, 1, 1, 0), + RK3036_PLL_RATE(1000000000, 6, 500, 2, 1, 1, 0), + RK3036_PLL_RATE( 984000000, 1, 82, 2, 1, 1, 0), + RK3036_PLL_RATE( 960000000, 1, 80, 2, 1, 1, 0), + RK3036_PLL_RATE( 936000000, 1, 78, 2, 1, 1, 0), + RK3036_PLL_RATE( 912000000, 1, 76, 2, 1, 1, 0), + RK3036_PLL_RATE( 900000000, 4, 300, 2, 1, 1, 0), + RK3036_PLL_RATE( 888000000, 1, 74, 2, 1, 1, 0), + RK3036_PLL_RATE( 864000000, 1, 72, 2, 1, 1, 0), + RK3036_PLL_RATE( 840000000, 1, 70, 2, 1, 1, 0), + RK3036_PLL_RATE( 816000000, 1, 68, 2, 1, 1, 0), + RK3036_PLL_RATE( 800000000, 6, 400, 2, 1, 1, 0), + RK3036_PLL_RATE( 700000000, 6, 350, 2, 1, 1, 0), + RK3036_PLL_RATE( 696000000, 1, 58, 2, 1, 1, 0), + RK3036_PLL_RATE( 600000000, 1, 75, 3, 1, 1, 0), + RK3036_PLL_RATE( 594000000, 2, 99, 2, 1, 1, 0), + RK3036_PLL_RATE( 504000000, 1, 63, 3, 1, 1, 0), + RK3036_PLL_RATE( 500000000, 6, 250, 2, 1, 1, 0), + RK3036_PLL_RATE( 408000000, 1, 68, 2, 2, 1, 0), + RK3036_PLL_RATE( 312000000, 1, 52, 2, 2, 1, 0), + RK3036_PLL_RATE( 216000000, 1, 72, 4, 2, 1, 0), + RK3036_PLL_RATE( 96000000, 1, 64, 4, 4, 1, 0), + { /* sentinel */ }, +}; + +#define RK3228_DIV_CPU_MASK 0x1f +#define RK3228_DIV_CPU_SHIFT 8 + +#define RK3228_DIV_PERI_MASK 0xf +#define RK3228_DIV_PERI_SHIFT 0 +#define RK3228_DIV_ACLK_MASK 0x7 +#define RK3228_DIV_ACLK_SHIFT 4 +#define RK3228_DIV_HCLK_MASK 0x3 +#define RK3228_DIV_HCLK_SHIFT 8 +#define RK3228_DIV_PCLK_MASK 0x7 +#define RK3228_DIV_PCLK_SHIFT 12 + +#define RK3228_CLKSEL1(_core_peri_div) \ + { \ + .reg = RK2928_CLKSEL_CON(1), \ + .val = HIWORD_UPDATE(_core_peri_div, RK3228_DIV_PERI_MASK, \ + RK3228_DIV_PERI_SHIFT) \ + } + +#define RK3228_CPUCLK_RATE(_prate, _core_peri_div) \ + { \ + .prate = _prate, \ + .divs = { \ + RK3228_CLKSEL1(_core_peri_div), \ + }, \ + } + +static struct rockchip_cpuclk_rate_table rk3228_cpuclk_rates[] __initdata = { + RK3228_CPUCLK_RATE(816000000, 4), + RK3228_CPUCLK_RATE(600000000, 4), + RK3228_CPUCLK_RATE(312000000, 4), +}; + +static const struct rockchip_cpuclk_reg_data rk3228_cpuclk_data = { + .core_reg = RK2928_CLKSEL_CON(0), + .div_core_shift = 0, + .div_core_mask = 0x1f, + .mux_core_shift = 6, +}; + +PNAME(mux_pll_p) = { "clk_24m", "xin24m" }; + +PNAME(mux_ddrphy_p) = { "dpll_ddr", "gpll_ddr", "apll_ddr" }; +PNAME(mux_armclk_p) = { "apll_core", "gpll_core", "dpll_core" }; +PNAME(mux_usb480m_phy_p) = { "usb480m_phy0", "usb480m_phy1" }; +PNAME(mux_usb480m_p) = { "usb480m_phy", "xin24m" }; +PNAME(mux_hdmiphy_p) = { "hdmiphy_phy", "xin24m" }; +PNAME(mux_aclk_cpu_src_p) = { "cpll_aclk_cpu", "gpll_aclk_cpu", "hdmiphy_aclk_cpu" }; + +PNAME(mux_pll_src_4plls_p) = { "cpll", "gpll", "hdmiphy" "usb480m" }; +PNAME(mux_pll_src_3plls_p) = { "cpll", "gpll", "hdmiphy" }; +PNAME(mux_pll_src_2plls_p) = { "cpll", "gpll" }; +PNAME(mux_sclk_hdmi_cec_p) = { "cpll", "gpll", "xin24m" }; +PNAME(mux_aclk_peri_src_p) = { "cpll_peri", "gpll_peri", "hdmiphy_peri" }; +PNAME(mux_mmc_src_p) = { "cpll", "gpll", "xin24m", "usb480m" }; +PNAME(mux_pll_src_cpll_gpll_usb480m_p) = { "cpll", "gpll", "usb480m" }; + +PNAME(mux_sclk_rga_p) = { "gpll", "cpll", "sclk_rga_src" }; + +PNAME(mux_sclk_vop_src_p) = { "gpll_vop", "cpll_vop" }; +PNAME(mux_dclk_vop_p) = { "hdmiphy", "sclk_vop_pre" }; + +PNAME(mux_i2s0_p) = { "i2s0_src", "i2s0_frac", "ext_i2s", "xin12m" }; +PNAME(mux_i2s1_pre_p) = { "i2s1_src", "i2s1_frac", "ext_i2s", "xin12m" }; +PNAME(mux_i2s_out_p) = { "i2s1_pre", "xin12m" }; +PNAME(mux_i2s2_p) = { "i2s2_src", "i2s2_frac", "xin12m" }; +PNAME(mux_sclk_spdif_p) = { "sclk_spdif_src", "spdif_frac", "xin12m" }; + +PNAME(mux_aclk_gpu_pre_p) = { "cpll_gpu", "gpll_gpu", "hdmiphy_gpu", "usb480m_gpu" }; + +PNAME(mux_uart0_p) = { "uart0_src", "uart0_frac", "xin24m" }; +PNAME(mux_uart1_p) = { "uart1_src", "uart1_frac", "xin24m" }; +PNAME(mux_uart2_p) = { "uart2_src", "uart2_frac", "xin24m" }; + +PNAME(mux_sclk_macphy_50m_p) = { "ext_gmac", "phy_50m_out" }; +PNAME(mux_sclk_gmac_pre_p) = { "sclk_gmac_src", "sclk_macphy_50m" }; +PNAME(mux_sclk_macphy_p) = { "sclk_gmac_src", "ext_gmac" }; + +static struct rockchip_pll_clock rk3228_pll_clks[] __initdata = { + [apll] = PLL(pll_rk3036, PLL_APLL, "apll", mux_pll_p, 0, RK2928_PLL_CON(0), + RK2928_MODE_CON, 0, 7, 0, rk3228_pll_rates), + [dpll] = PLL(pll_rk3036, PLL_DPLL, "dpll", mux_pll_p, 0, RK2928_PLL_CON(3), + RK2928_MODE_CON, 4, 6, 0, NULL), + [cpll] = PLL(pll_rk3036, PLL_CPLL, "cpll", mux_pll_p, 0, RK2928_PLL_CON(6), + RK2928_MODE_CON, 8, 8, 0, NULL), + [gpll] = PLL(pll_rk3036, PLL_GPLL, "gpll", mux_pll_p, 0, RK2928_PLL_CON(9), + RK2928_MODE_CON, 12, 9, ROCKCHIP_PLL_SYNC_RATE, rk3228_pll_rates), +}; + +#define MFLAGS CLK_MUX_HIWORD_MASK +#define DFLAGS CLK_DIVIDER_HIWORD_MASK +#define GFLAGS (CLK_GATE_HIWORD_MASK | CLK_GATE_SET_TO_DISABLE) + +static struct rockchip_clk_branch rk3228_clk_branches[] __initdata = { + /* + * Clock-Architecture Diagram 1 + */ + + DIV(0, "clk_24m", "xin24m", CLK_IGNORE_UNUSED, + RK2928_CLKSEL_CON(4), 8, 5, DFLAGS), + + /* PD_DDR */ + GATE(0, "apll_ddr", "apll", CLK_IGNORE_UNUSED, + RK2928_CLKGATE_CON(0), 2, GFLAGS), + GATE(0, "dpll_ddr", "dpll", CLK_IGNORE_UNUSED, + RK2928_CLKGATE_CON(0), 2, GFLAGS), + GATE(0, "gpll_ddr", "gpll", CLK_IGNORE_UNUSED, + RK2928_CLKGATE_CON(0), 2, GFLAGS), + COMPOSITE(0, "ddrphy4x", mux_ddrphy_p, CLK_IGNORE_UNUSED, + RK2928_CLKSEL_CON(26), 8, 2, MFLAGS, 0, 3, DFLAGS | CLK_DIVIDER_POWER_OF_TWO, + RK2928_CLKGATE_CON(7), 1, GFLAGS), + GATE(0, "ddrc", "ddrphy_pre", CLK_IGNORE_UNUSED, + RK2928_CLKGATE_CON(8), 5, GFLAGS), + GATE(0, "ddrphy", "ddrphy_pre", CLK_IGNORE_UNUSED, + RK2928_CLKGATE_CON(7), 0, GFLAGS), + + /* PD_CORE */ + GATE(0, "dpll_core", "dpll", CLK_IGNORE_UNUSED, + RK2928_CLKGATE_CON(0), 6, GFLAGS), + GATE(0, "apll_core", "apll", CLK_IGNORE_UNUSED, + RK2928_CLKGATE_CON(0), 6, GFLAGS), + GATE(0, "gpll_core", "gpll", CLK_IGNORE_UNUSED, + RK2928_CLKGATE_CON(0), 6, GFLAGS), + COMPOSITE_NOMUX(0, "pclk_dbg", "armclk", CLK_IGNORE_UNUSED, + RK2928_CLKSEL_CON(1), 0, 4, DFLAGS | CLK_DIVIDER_READ_ONLY, + RK2928_CLKGATE_CON(4), 1, GFLAGS), + COMPOSITE_NOMUX(0, "armcore", "armclk", CLK_IGNORE_UNUSED, + RK2928_CLKSEL_CON(1), 4, 3, DFLAGS | CLK_DIVIDER_READ_ONLY, + RK2928_CLKGATE_CON(4), 0, GFLAGS), + + /* PD_MISC */ + MUX(0, "hdmiphy", mux_hdmiphy_p, CLK_SET_RATE_PARENT, + RK2928_MISC_CON, 13, 1, MFLAGS), + MUX(0, "usb480m_phy", mux_usb480m_phy_p, CLK_SET_RATE_PARENT, + RK2928_MISC_CON, 14, 1, MFLAGS), + MUX(0, "usb480m", mux_usb480m_p, CLK_SET_RATE_PARENT, + RK2928_MISC_CON, 15, 1, MFLAGS), + + /* PD_BUS */ + GATE(0, "hdmiphy_aclk_cpu", "hdmiphy", CLK_IGNORE_UNUSED, + RK2928_CLKGATE_CON(0), 1, GFLAGS), + GATE(0, "gpll_aclk_cpu", "gpll", CLK_IGNORE_UNUSED, + RK2928_CLKGATE_CON(0), 1, GFLAGS), + GATE(0, "cpll_aclk_cpu", "cpll", CLK_IGNORE_UNUSED, + RK2928_CLKGATE_CON(0), 1, GFLAGS), + COMPOSITE_NOGATE(0, "aclk_cpu_src", mux_aclk_cpu_src_p, 0, + RK2928_CLKSEL_CON(0), 13, 2, MFLAGS, 8, 5, DFLAGS), + GATE(ARMCLK, "aclk_cpu", "aclk_cpu_src", 0, + RK2928_CLKGATE_CON(6), 0, GFLAGS), + COMPOSITE_NOMUX(0, "hclk_cpu", "aclk_cpu_src", 0, + RK2928_CLKSEL_CON(1), 8, 2, DFLAGS, + RK2928_CLKGATE_CON(6), 1, GFLAGS), + COMPOSITE_NOMUX(0, "pclk_bus_src", "aclk_cpu_src", 0, + RK2928_CLKSEL_CON(1), 12, 3, DFLAGS, + RK2928_CLKGATE_CON(6), 2, GFLAGS), + GATE(0, "pclk_cpu", "pclk_bus_src", 0, + RK2928_CLKGATE_CON(6), 3, GFLAGS), + GATE(0, "pclk_phy_pre", "pclk_bus_src", 0, + RK2928_CLKGATE_CON(6), 4, GFLAGS), + GATE(0, "pclk_ddr_pre", "pclk_bus_src", 0, + RK2928_CLKGATE_CON(6), 13, GFLAGS), + + /* PD_VIDEO */ + COMPOSITE(0, "aclk_vpu_pre", mux_pll_src_4plls_p, 0, + RK2928_CLKSEL_CON(32), 5, 2, MFLAGS, 0, 5, DFLAGS, + RK2928_CLKGATE_CON(3), 11, GFLAGS), + GATE(0, "hclk_vpu_src", "aclk_vpu_pre", 0, + RK2928_CLKGATE_CON(4), 4, GFLAGS), + + COMPOSITE(0, "aclk_rkvdec_pre", mux_pll_src_4plls_p, 0, + RK2928_CLKSEL_CON(28), 6, 2, MFLAGS, 0, 5, DFLAGS, + RK2928_CLKGATE_CON(3), 2, GFLAGS), + GATE(0, "hclk_rkvdec_src", "aclk_rkvdec_pre", 0, + RK2928_CLKGATE_CON(4), 5, GFLAGS), + + COMPOSITE(0, "sclk_vdec_cabac", mux_pll_src_4plls_p, 0, + RK2928_CLKSEL_CON(28), 14, 2, MFLAGS, 8, 5, DFLAGS, + RK2928_CLKGATE_CON(3), 3, GFLAGS), + + COMPOSITE(0, "sclk_vdec_core", mux_pll_src_4plls_p, 0, + RK2928_CLKSEL_CON(34), 13, 2, MFLAGS, 8, 5, DFLAGS, + RK2928_CLKGATE_CON(3), 4, GFLAGS), + + /* PD_VIO */ + COMPOSITE(0, "aclk_iep_pre", mux_pll_src_4plls_p, 0, + RK2928_CLKSEL_CON(31), 5, 2, MFLAGS, 0, 5, DFLAGS, + RK2928_CLKGATE_CON(3), 0, GFLAGS), + DIV(0, "hclk_vio_pre", "aclk_iep_pre", 0, + RK2928_CLKSEL_CON(2), 0, 5, DFLAGS), + + COMPOSITE(0, "aclk_hdcp_pre", mux_pll_src_4plls_p, 0, + RK2928_CLKSEL_CON(31), 13, 2, MFLAGS, 8, 5, DFLAGS, + RK2928_CLKGATE_CON(1), 4, GFLAGS), + + MUX(0, "sclk_rga_src", mux_pll_src_4plls_p, 0, + RK2928_CLKSEL_CON(33), 13, 2, MFLAGS), + COMPOSITE_NOMUX(0, "aclk_rga_pre", "sclk_rga_src", 0, + RK2928_CLKSEL_CON(33), 8, 5, DFLAGS, + RK2928_CLKGATE_CON(1), 2, GFLAGS), + COMPOSITE(0, "sclk_rga", mux_sclk_rga_p, 0, + RK2928_CLKSEL_CON(22), 5, 2, MFLAGS, 0, 5, DFLAGS, + RK2928_CLKGATE_CON(3), 6, GFLAGS), + + COMPOSITE(0, "aclk_vop_pre", mux_pll_src_4plls_p, 0, + RK2928_CLKSEL_CON(33), 5, 2, MFLAGS, 0, 5, DFLAGS, + RK2928_CLKGATE_CON(1), 1, GFLAGS), + + COMPOSITE(0, "sclk_hdcp", mux_pll_src_3plls_p, 0, + RK2928_CLKSEL_CON(23), 14, 2, MFLAGS, 8, 6, DFLAGS, + RK2928_CLKGATE_CON(3), 5, GFLAGS), + + GATE(0, "sclk_hdmi_hdcp", "xin24m", 0, + RK2928_CLKGATE_CON(3), 7, GFLAGS), + + COMPOSITE(0, "sclk_hdmi_cec", mux_sclk_hdmi_cec_p, 0, + RK2928_CLKSEL_CON(21), 14, 2, MFLAGS, 0, 14, DFLAGS, + RK2928_CLKGATE_CON(3), 8, GFLAGS), + + /* PD_PERI */ + GATE(0, "cpll_peri", "cpll", CLK_IGNORE_UNUSED, + RK2928_CLKGATE_CON(2), 0, GFLAGS), + GATE(0, "gpll_peri", "gpll", CLK_IGNORE_UNUSED, + RK2928_CLKGATE_CON(2), 0, GFLAGS), + GATE(0, "hdmiphy_peri", "hdmiphy", CLK_IGNORE_UNUSED, + RK2928_CLKGATE_CON(2), 0, GFLAGS), + COMPOSITE_NOGATE(0, "aclk_peri_src", mux_aclk_peri_src_p, 0, + RK2928_CLKSEL_CON(10), 10, 2, MFLAGS, 0, 5, DFLAGS), + COMPOSITE_NOMUX(PCLK_PERI, "pclk_peri", "aclk_peri_src", 0, + RK2928_CLKSEL_CON(10), 12, 3, DFLAGS, + RK2928_CLKGATE_CON(5), 2, GFLAGS), + COMPOSITE_NOMUX(HCLK_PERI, "hclk_peri", "aclk_peri_src", 0, + RK2928_CLKSEL_CON(10), 8, 2, DFLAGS, + RK2928_CLKGATE_CON(5), 1, GFLAGS), + GATE(ACLK_PERI, "aclk_peri", "aclk_peri_src", 0, + RK2928_CLKGATE_CON(5), 0, GFLAGS), + + GATE(SCLK_TIMER0, "sclk_timer0", "xin24m", 0, + RK2928_CLKGATE_CON(6), 5, GFLAGS), + GATE(SCLK_TIMER1, "sclk_timer1", "xin24m", 0, + RK2928_CLKGATE_CON(6), 6, GFLAGS), + GATE(SCLK_TIMER2, "sclk_timer2", "xin24m", 0, + RK2928_CLKGATE_CON(6), 7, GFLAGS), + GATE(SCLK_TIMER3, "sclk_timer3", "xin24m", 0, + RK2928_CLKGATE_CON(6), 8, GFLAGS), + GATE(SCLK_TIMER4, "sclk_timer4", "xin24m", 0, + RK2928_CLKGATE_CON(6), 9, GFLAGS), + GATE(SCLK_TIMER5, "sclk_timer5", "xin24m", 0, + RK2928_CLKGATE_CON(6), 10, GFLAGS), + + COMPOSITE(0, "sclk_crypto", mux_pll_src_2plls_p, 0, + RK2928_CLKSEL_CON(24), 5, 1, MFLAGS, 0, 5, DFLAGS, + RK2928_CLKGATE_CON(2), 7, GFLAGS), + + COMPOSITE(0, "sclk_tsp", mux_pll_src_2plls_p, 0, + RK2928_CLKSEL_CON(22), 15, 1, MFLAGS, 8, 5, DFLAGS, + RK2928_CLKGATE_CON(2), 6, GFLAGS), + + GATE(0, "sclk_hsadc", "ext_hsadc", 0, + RK3288_CLKGATE_CON(10), 12, GFLAGS), + + COMPOSITE(0, "sclk_wifi", mux_pll_src_cpll_gpll_usb480m_p, 0, + RK2928_CLKSEL_CON(23), 5, 2, MFLAGS, 0, 6, DFLAGS, + RK2928_CLKGATE_CON(2), 15, GFLAGS), + + COMPOSITE(SCLK_SDMMC, "sclk_sdmmc0", mux_mmc_src_p, 0, + RK2928_CLKSEL_CON(11), 8, 2, MFLAGS, 0, 8, DFLAGS, + RK2928_CLKGATE_CON(2), 11, GFLAGS), + + COMPOSITE_NODIV(0, "sclk_sdio_src", mux_mmc_src_p, 0, + RK2928_CLKSEL_CON(11), 10, 2, MFLAGS, + RK2928_CLKGATE_CON(2), 13, GFLAGS), + DIV(SCLK_SDIO, "sclk_sdio", "sclk_sdio_src", 0, + RK2928_CLKSEL_CON(12), 0, 8, DFLAGS), + + COMPOSITE_NODIV(0, "sclk_emmc_src", mux_mmc_src_p, 0, + RK2928_CLKSEL_CON(11), 12, 2, MFLAGS, + RK2928_CLKGATE_CON(2), 14, GFLAGS), + DIV(SCLK_EMMC, "sclk_emmc", "sclk_emmc_src", 0, + RK2928_CLKSEL_CON(12), 8, 8, DFLAGS), + + /* + * Clock-Architecture Diagram 2 + */ + + GATE(0, "gpll_vop", "gpll", 0, + RK2928_CLKGATE_CON(3), 1, GFLAGS), + GATE(0, "cpll_vop", "cpll", 0, + RK2928_CLKGATE_CON(3), 1, GFLAGS), + MUX(0, "sclk_vop_src", mux_sclk_vop_src_p, 0, + RK2928_CLKSEL_CON(27), 0, 1, MFLAGS), + DIV(0, "dclk_hdmiphy", "sclk_vop_src", 0, + RK2928_CLKSEL_CON(29), 0, 3, DFLAGS), + DIV(0, "sclk_vop_pre", "sclk_vop_src", 0, + RK2928_CLKSEL_CON(27), 8, 8, DFLAGS), + MUX(0, "dclk_vop", mux_dclk_vop_p, 0, + RK2928_CLKSEL_CON(27), 1, 1, MFLAGS), + + COMPOSITE(0, "i2s0_src", mux_pll_src_2plls_p, 0, + RK2928_CLKSEL_CON(9), 15, 1, MFLAGS, 0, 7, DFLAGS, + RK2928_CLKGATE_CON(0), 3, GFLAGS), + COMPOSITE_FRAC(0, "i2s0_frac", "i2s0_src", CLK_SET_RATE_PARENT, + RK3288_CLKSEL_CON(8), 0, + RK3288_CLKGATE_CON(0), 4, GFLAGS), + COMPOSITE_NODIV(SCLK_I2S0, "sclk_i2s0", mux_i2s0_p, 0, + RK2928_CLKSEL_CON(9), 8, 2, MFLAGS, + RK2928_CLKGATE_CON(0), 5, GFLAGS), + + COMPOSITE(0, "i2s1_src", mux_pll_src_2plls_p, 0, + RK2928_CLKSEL_CON(3), 15, 1, MFLAGS, 0, 7, DFLAGS, + RK2928_CLKGATE_CON(0), 10, GFLAGS), + COMPOSITE_FRAC(0, "i2s1_frac", "i2s1_src", CLK_SET_RATE_PARENT, + RK3288_CLKSEL_CON(7), 0, + RK3288_CLKGATE_CON(0), 11, GFLAGS), + MUX(0, "i2s1_pre", mux_i2s1_pre_p, 0, + RK2928_CLKSEL_CON(3), 8, 2, MFLAGS), + GATE(SCLK_I2S1, "sclk_i2s1", "i2s1_pre", 0, + RK2928_CLKGATE_CON(0), 14, GFLAGS), + COMPOSITE_NODIV(SCLK_I2S_OUT, "i2s_out", mux_i2s_out_p, 0, + RK2928_CLKSEL_CON(3), 12, 1, MFLAGS, + RK2928_CLKGATE_CON(0), 13, GFLAGS), + + COMPOSITE(0, "i2s2_src", mux_pll_src_2plls_p, 0, + RK2928_CLKSEL_CON(16), 15, 1, MFLAGS, 0, 7, DFLAGS, + RK2928_CLKGATE_CON(0), 7, GFLAGS), + COMPOSITE_FRAC(0, "i2s2_frac", "i2s2_src", CLK_SET_RATE_PARENT, + RK3288_CLKSEL_CON(30), 0, + RK3288_CLKGATE_CON(0), 8, GFLAGS), + COMPOSITE_NODIV(SCLK_I2S2, "sclk_i2s2", mux_i2s2_p, 0, + RK2928_CLKSEL_CON(16), 8, 2, MFLAGS, + RK2928_CLKGATE_CON(0), 9, GFLAGS), + + COMPOSITE(0, "sclk_spdif_src", mux_pll_src_2plls_p, 0, + RK2928_CLKSEL_CON(6), 15, 1, MFLAGS, 0, 7, DFLAGS, + RK2928_CLKGATE_CON(2), 10, GFLAGS), + COMPOSITE_FRAC(0, "spdif_frac", "sclk_spdif_src", CLK_SET_RATE_PARENT, + RK3288_CLKSEL_CON(20), 0, + RK3288_CLKGATE_CON(2), 12, GFLAGS), + MUX(SCLK_SPDIF, "sclk_spdif", mux_sclk_spdif_p, 0, + RK2928_CLKSEL_CON(6), 8, 2, MFLAGS), + + GATE(0, "jtag", "ext_jtag", 0, + RK2928_CLKGATE_CON(1), 3, GFLAGS), + + GATE(0, "sclk_otgphy0", "xin24m", 0, + RK2928_CLKGATE_CON(1), 5, GFLAGS), + GATE(0, "sclk_otgphy1", "xin24m", 0, + RK2928_CLKGATE_CON(1), 6, GFLAGS), + + COMPOSITE_NOMUX(0, "sclk_tsadc", "xin24m", 0, + RK2928_CLKSEL_CON(24), 6, 10, DFLAGS, + RK2928_CLKGATE_CON(2), 8, GFLAGS), + + GATE(0, "cpll_gpu", "cpll", 0, + RK2928_CLKGATE_CON(3), 13, GFLAGS), + GATE(0, "gpll_gpu", "gpll", 0, + RK2928_CLKGATE_CON(3), 13, GFLAGS), + GATE(0, "hdmiphy_gpu", "hdmiphy", 0, + RK2928_CLKGATE_CON(3), 13, GFLAGS), + GATE(0, "usb480m_gpu", "usb480m", 0, + RK2928_CLKGATE_CON(3), 13, GFLAGS), + COMPOSITE_NOGATE(0, "aclk_gpu_pre", mux_aclk_gpu_pre_p, 0, + RK2928_CLKSEL_CON(34), 5, 2, MFLAGS, 0, 5, DFLAGS), + + COMPOSITE(SCLK_SPI0, "sclk_spi0", mux_pll_src_2plls_p, 0, + RK2928_CLKSEL_CON(25), 8, 1, MFLAGS, 0, 7, DFLAGS, + RK2928_CLKGATE_CON(2), 9, GFLAGS), + + /* PD_UART */ + COMPOSITE(0, "uart0_src", mux_pll_src_cpll_gpll_usb480m_p, 0, + RK2928_CLKSEL_CON(13), 12, 2, MFLAGS, 0, 7, DFLAGS, + RK2928_CLKGATE_CON(1), 8, GFLAGS), + COMPOSITE(0, "uart1_src", mux_pll_src_cpll_gpll_usb480m_p, 0, + RK2928_CLKSEL_CON(14), 12, 2, MFLAGS, 0, 7, DFLAGS, + RK2928_CLKGATE_CON(1), 10, GFLAGS), + COMPOSITE(0, "uart2_src", mux_pll_src_cpll_gpll_usb480m_p, + 0, RK2928_CLKSEL_CON(15), 12, 2, + MFLAGS, 0, 7, DFLAGS, RK2928_CLKGATE_CON(1), 12, GFLAGS), + COMPOSITE_FRAC(0, "uart0_frac", "uart0_src", CLK_SET_RATE_PARENT, + RK2928_CLKSEL_CON(17), 0, + RK2928_CLKGATE_CON(1), 9, GFLAGS), + COMPOSITE_FRAC(0, "uart1_frac", "uart1_src", CLK_SET_RATE_PARENT, + RK2928_CLKSEL_CON(18), 0, + RK2928_CLKGATE_CON(1), 11, GFLAGS), + COMPOSITE_FRAC(0, "uart2_frac", "uart2_src", CLK_SET_RATE_PARENT, + RK2928_CLKSEL_CON(19), 0, + RK2928_CLKGATE_CON(1), 13, GFLAGS), + MUX(SCLK_UART0, "sclk_uart0", mux_uart0_p, CLK_SET_RATE_PARENT, + RK2928_CLKSEL_CON(13), 8, 2, MFLAGS), + MUX(SCLK_UART1, "sclk_uart1", mux_uart1_p, CLK_SET_RATE_PARENT, + RK2928_CLKSEL_CON(14), 8, 2, MFLAGS), + MUX(SCLK_UART2, "sclk_uart2", mux_uart2_p, CLK_SET_RATE_PARENT, + RK2928_CLKSEL_CON(15), 8, 2, MFLAGS), + + COMPOSITE(SCLK_NANDC, "sclk_nandc", mux_pll_src_2plls_p, 0, + RK2928_CLKSEL_CON(2), 14, 1, MFLAGS, 8, 5, DFLAGS, + RK2928_CLKGATE_CON(1), 0, GFLAGS), + + COMPOSITE(0, "sclk_gmac_src", mux_pll_src_2plls_p, 0, + RK2928_CLKSEL_CON(5), 7, 1, MFLAGS, 0, 5, DFLAGS, + RK2928_CLKGATE_CON(1), 7, GFLAGS), + MUX(0, "sclk_macphy_50m", mux_sclk_macphy_50m_p, 0, + RK2928_CLKSEL_CON(29), 10, 1, MFLAGS), + MUX(0, "sclk_gmac_pre", mux_sclk_gmac_pre_p, 0, + RK2928_CLKSEL_CON(5), 5, 1, MFLAGS), + GATE(0, "sclk_mac_refout", "sclk_gmac_pre", 0, + RK2928_CLKGATE_CON(5), 4, GFLAGS), + GATE(0, "sclk_mac_ref", "sclk_gmac_pre", 0, + RK2928_CLKGATE_CON(5), 3, GFLAGS), + GATE(0, "sclk_mac_rx", "sclk_gmac_pre", 0, + RK2928_CLKGATE_CON(5), 5, GFLAGS), + GATE(0, "sclk_mac_tx", "sclk_gmac_pre", 0, + RK2928_CLKGATE_CON(5), 6, GFLAGS), + COMPOSITE(0, "sclk_macphy", mux_sclk_macphy_p, 0, + RK2928_CLKSEL_CON(29), 12, 1, MFLAGS, 8, 2, DFLAGS, + RK2928_CLKGATE_CON(5), 7, GFLAGS), + COMPOSITE(0, "sclk_gmac_out", mux_pll_src_2plls_p, 0, + RK2928_CLKSEL_CON(5), 15, 1, MFLAGS, 8, 5, DFLAGS, + RK2928_CLKGATE_CON(2), 2, GFLAGS), + + /* + * Clock-Architecture Diagram 3 + */ + + /* PD_VOP */ + GATE(0, "aclk_rga", "aclk_rga_pre", 0, RK2928_CLKGATE_CON(13), 0, GFLAGS), + GATE(0, "aclk_rga_noc", "aclk_rga_pre", 0, RK2928_CLKGATE_CON(13), 11, GFLAGS), + GATE(0, "aclk_iep", "aclk_iep_pre", 0, RK2928_CLKGATE_CON(13), 2, GFLAGS), + GATE(0, "aclk_iep_noc", "aclk_iep_pre", 0, RK2928_CLKGATE_CON(13), 9, GFLAGS), + + GATE(0, "aclk_vop", "aclk_vop_pre", 0, RK2928_CLKGATE_CON(13), 5, GFLAGS), + GATE(0, "aclk_vop_noc", "aclk_vop_pre", 0, RK2928_CLKGATE_CON(13), 12, GFLAGS), + + GATE(0, "aclk_hdcp", "aclk_hdcp_pre", 0, RK2928_CLKGATE_CON(14), 10, GFLAGS), + GATE(0, "aclk_hdcp_noc", "aclk_hdcp_pre", 0, RK2928_CLKGATE_CON(13), 10, GFLAGS), + + GATE(0, "hclk_rga", "hclk_vio_pre", 0, RK2928_CLKGATE_CON(13), 1, GFLAGS), + GATE(0, "hclk_iep", "hclk_vio_pre", 0, RK2928_CLKGATE_CON(13), 3, GFLAGS), + GATE(0, "hclk_vop", "hclk_vio_pre", 0, RK2928_CLKGATE_CON(13), 6, GFLAGS), + GATE(0, "hclk_vio_ahb_arbi", "hclk_vio_pre", 0, RK2928_CLKGATE_CON(13), 7, GFLAGS), + GATE(0, "hclk_vio_noc", "hclk_vio_pre", 0, RK2928_CLKGATE_CON(13), 8, GFLAGS), + GATE(0, "hclk_vop_noc", "hclk_vio_pre", 0, RK2928_CLKGATE_CON(13), 13, GFLAGS), + GATE(0, "hclk_vio_h2p", "hclk_vio_pre", 0, RK2928_CLKGATE_CON(14), 7, GFLAGS), + GATE(0, "hclk_hdcp_mmu", "hclk_vio_pre", 0, RK2928_CLKGATE_CON(14), 12, GFLAGS), + GATE(0, "pclk_hdmi_ctrl", "hclk_vio_pre", 0, RK2928_CLKGATE_CON(14), 6, GFLAGS), + GATE(0, "pclk_vio_h2p", "hclk_vio_pre", 0, RK2928_CLKGATE_CON(14), 8, GFLAGS), + GATE(0, "pclk_hdcp", "hclk_vio_pre", 0, RK2928_CLKGATE_CON(14), 11, GFLAGS), + + /* PD_PERI */ + GATE(0, "aclk_peri_noc", "aclk_peri", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(12), 0, GFLAGS), + GATE(0, "aclk_gmac", "aclk_peri", 0, RK2928_CLKGATE_CON(11), 4, GFLAGS), + + GATE(HCLK_SDMMC, "hclk_sdmmc", "hclk_peri", 0, RK2928_CLKGATE_CON(11), 0, GFLAGS), + GATE(HCLK_SDIO, "hclk_sdio", "hclk_peri", 0, RK2928_CLKGATE_CON(11), 1, GFLAGS), + GATE(HCLK_EMMC, "hclk_emmc", "hclk_peri", 0, RK2928_CLKGATE_CON(11), 2, GFLAGS), + GATE(HCLK_NANDC, "hclk_nandc", "hclk_peri", 0, RK2928_CLKGATE_CON(11), 3, GFLAGS), + GATE(0, "hclk_host0", "hclk_peri", 0, RK2928_CLKGATE_CON(11), 6, GFLAGS), + GATE(0, "hclk_host0_arb", "hclk_peri", 0, RK2928_CLKGATE_CON(11), 7, GFLAGS), + GATE(0, "hclk_host1", "hclk_peri", 0, RK2928_CLKGATE_CON(11), 8, GFLAGS), + GATE(0, "hclk_host1_arb", "hclk_peri", 0, RK2928_CLKGATE_CON(11), 9, GFLAGS), + GATE(0, "hclk_host2", "hclk_peri", 0, RK2928_CLKGATE_CON(11), 10, GFLAGS), + GATE(0, "hclk_otg", "hclk_peri", 0, RK2928_CLKGATE_CON(11), 12, GFLAGS), + GATE(0, "hclk_otg_pmu", "hclk_peri", 0, RK2928_CLKGATE_CON(11), 13, GFLAGS), + GATE(0, "hclk_host2_arb", "hclk_peri", 0, RK2928_CLKGATE_CON(11), 14, GFLAGS), + GATE(0, "hclk_peri_noc", "hclk_peri", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(12), 1, GFLAGS), + + GATE(0, "pclk_gmac", "pclk_peri", 0, RK2928_CLKGATE_CON(11), 5, GFLAGS), + GATE(0, "pclk_peri_noc", "pclk_peri", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(12), 2, GFLAGS), + + /* PD_GPU */ + GATE(0, "aclk_gpu", "aclk_gpu_pre", 0, RK2928_CLKGATE_CON(13), 14, GFLAGS), + GATE(0, "aclk_gpu_noc", "aclk_gpu_pre", 0, RK2928_CLKGATE_CON(13), 15, GFLAGS), + + /* PD_BUS */ + GATE(0, "sclk_initmem_mbist", "aclk_cpu", 0, RK2928_CLKGATE_CON(8), 1, GFLAGS), + GATE(0, "aclk_initmem", "aclk_cpu", 0, RK2928_CLKGATE_CON(8), 0, GFLAGS), + GATE(ACLK_DMAC, "aclk_dmac_bus", "aclk_cpu", 0, RK2928_CLKGATE_CON(8), 2, GFLAGS), + GATE(0, "aclk_bus_noc", "aclk_cpu", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(10), 1, GFLAGS), + + GATE(0, "hclk_rom", "hclk_cpu", 0, RK2928_CLKGATE_CON(8), 3, GFLAGS), + GATE(0, "hclk_i2s0_8ch", "hclk_cpu", 0, RK2928_CLKGATE_CON(8), 7, GFLAGS), + GATE(0, "hclk_i2s1_8ch", "hclk_cpu", 0, RK2928_CLKGATE_CON(8), 8, GFLAGS), + GATE(0, "hclk_i2s2_2ch", "hclk_cpu", 0, RK2928_CLKGATE_CON(8), 9, GFLAGS), + GATE(0, "hclk_spdif_8ch", "hclk_cpu", 0, RK2928_CLKGATE_CON(8), 10, GFLAGS), + GATE(0, "hclk_tsp", "hclk_cpu", 0, RK2928_CLKGATE_CON(10), 11, GFLAGS), + GATE(0, "hclk_crypto_mst", "hclk_cpu", 0, RK2928_CLKGATE_CON(8), 11, GFLAGS), + GATE(0, "hclk_crypto_slv", "hclk_cpu", 0, RK2928_CLKGATE_CON(8), 12, GFLAGS), + + GATE(0, "pclk_ddrupctl", "pclk_ddr_pre", 0, RK2928_CLKGATE_CON(8), 4, GFLAGS), + GATE(0, "pclk_ddrmon", "pclk_ddr_pre", 0, RK2928_CLKGATE_CON(8), 6, GFLAGS), + GATE(0, "pclk_msch_noc", "pclk_ddr_pre", 0, RK2928_CLKGATE_CON(10), 2, GFLAGS), + + GATE(0, "pclk_efuse_1024", "pclk_cpu", 0, RK2928_CLKGATE_CON(8), 13, GFLAGS), + GATE(0, "pclk_efuse_256", "pclk_cpu", 0, RK2928_CLKGATE_CON(8), 14, GFLAGS), + GATE(PCLK_I2C0, "pclk_i2c0", "pclk_cpu", 0, RK2928_CLKGATE_CON(8), 15, GFLAGS), + GATE(PCLK_I2C1, "pclk_i2c1", "pclk_cpu", 0, RK2928_CLKGATE_CON(9), 0, GFLAGS), + GATE(PCLK_I2C2, "pclk_i2c2", "pclk_cpu", 0, RK2928_CLKGATE_CON(9), 1, GFLAGS), + GATE(PCLK_I2C3, "pclk_i2c3", "pclk_cpu", 0, RK2928_CLKGATE_CON(9), 2, GFLAGS), + GATE(PCLK_TIMER, "pclk_timer0", "pclk_cpu", 0, RK2928_CLKGATE_CON(9), 4, GFLAGS), + GATE(0, "pclk_stimer", "pclk_cpu", 0, RK2928_CLKGATE_CON(9), 5, GFLAGS), + GATE(PCLK_SPI0, "pclk_spi0", "pclk_cpu", 0, RK2928_CLKGATE_CON(9), 6, GFLAGS), + GATE(PCLK_PWM, "pclk_rk_pwm", "pclk_cpu", 0, RK2928_CLKGATE_CON(9), 7, GFLAGS), + GATE(PCLK_GPIO0, "pclk_gpio0", "pclk_cpu", 0, RK2928_CLKGATE_CON(9), 8, GFLAGS), + GATE(PCLK_GPIO1, "pclk_gpio1", "pclk_cpu", 0, RK2928_CLKGATE_CON(9), 9, GFLAGS), + GATE(PCLK_GPIO2, "pclk_gpio2", "pclk_cpu", 0, RK2928_CLKGATE_CON(9), 10, GFLAGS), + GATE(PCLK_GPIO3, "pclk_gpio3", "pclk_cpu", 0, RK2928_CLKGATE_CON(9), 11, GFLAGS), + GATE(PCLK_UART0, "pclk_uart0", "pclk_cpu", 0, RK2928_CLKGATE_CON(9), 12, GFLAGS), + GATE(PCLK_UART1, "pclk_uart1", "pclk_cpu", 0, RK2928_CLKGATE_CON(9), 13, GFLAGS), + GATE(PCLK_UART2, "pclk_uart2", "pclk_cpu", 0, RK2928_CLKGATE_CON(9), 14, GFLAGS), + GATE(0, "pclk_tsadc", "pclk_cpu", 0, RK2928_CLKGATE_CON(9), 15, GFLAGS), + GATE(PCLK_GRF, "pclk_grf", "pclk_cpu", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(10), 0, GFLAGS), + GATE(0, "pclk_cru", "pclk_cpu", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(10), 1, GFLAGS), + GATE(0, "pclk_sgrf", "pclk_cpu", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(10), 2, GFLAGS), + GATE(0, "pclk_sim", "pclk_cpu", 0, RK2928_CLKGATE_CON(10), 3, GFLAGS), + + GATE(0, "pclk_ddrphy", "pclk_phy_pre", 0, RK2928_CLKGATE_CON(10), 3, GFLAGS), + GATE(0, "pclk_acodecphy", "pclk_phy_pre", 0, RK2928_CLKGATE_CON(10), 5, GFLAGS), + GATE(0, "pclk_hdmiphy", "pclk_phy_pre", 0, RK2928_CLKGATE_CON(10), 7, GFLAGS), + GATE(0, "pclk_vdacphy", "pclk_phy_pre", 0, RK2928_CLKGATE_CON(10), 8, GFLAGS), + GATE(0, "pclk_phy_noc", "pclk_phy_pre", 0, RK2928_CLKGATE_CON(10), 9, GFLAGS), + + GATE(0, "aclk_vpu", "aclk_vpu_pre", 0, RK2928_CLKGATE_CON(15), 0, GFLAGS), + GATE(0, "aclk_vpu_noc", "aclk_vpu_pre", 0, RK2928_CLKGATE_CON(15), 4, GFLAGS), + GATE(0, "aclk_rkvdec", "aclk_rkvdec_pre", 0, RK2928_CLKGATE_CON(15), 2, GFLAGS), + GATE(0, "aclk_rkvdec_noc", "aclk_rkvdec_pre", 0, RK2928_CLKGATE_CON(15), 6, GFLAGS), + GATE(0, "hclk_vpu", "hclk_vpu_pre", 0, RK2928_CLKGATE_CON(15), 1, GFLAGS), + GATE(0, "hclk_vpu_noc", "hclk_vpu_pre", 0, RK2928_CLKGATE_CON(15), 5, GFLAGS), + GATE(0, "hclk_rkvdec", "hclk_rkvdec_pre", 0, RK2928_CLKGATE_CON(15), 3, GFLAGS), + GATE(0, "hclk_rkvdec_noc", "hclk_rkvdec_pre", 0, RK2928_CLKGATE_CON(15), 7, GFLAGS), + + /* PD_MMC */ + MMC(SCLK_SDMMC_DRV, "sdmmc_drv", "sclk_sdmmc", RK3228_SDMMC_CON0, 1), + MMC(SCLK_SDMMC_SAMPLE, "sdmmc_sample", "sclk_sdmmc", RK3228_SDMMC_CON1, 1), + + MMC(SCLK_SDIO_DRV, "sdio_drv", "sclk_sdio", RK3228_SDIO_CON0, 1), + MMC(SCLK_SDIO_SAMPLE, "sdio_sample", "sclk_sdio", RK3228_SDIO_CON1, 1), + + MMC(SCLK_EMMC_DRV, "emmc_drv", "sclk_emmc", RK3228_EMMC_CON0, 1), + MMC(SCLK_EMMC_SAMPLE, "emmc_sample", "sclk_emmc", RK3228_EMMC_CON1, 1), +}; + +static const char *const rk3228_critical_clocks[] __initconst = { + "aclk_cpu", + "aclk_peri", + "hclk_peri", + "pclk_peri", +}; + +static void __init rk3228_clk_init(struct device_node *np) +{ + void __iomem *reg_base; + struct clk *clk; + + reg_base = of_iomap(np, 0); + if (!reg_base) { + pr_err("%s: could not map cru region\n", __func__); + return; + } + + rockchip_clk_init(np, reg_base, CLK_NR_CLKS); + + /* xin12m is created by an cru-internal divider */ + clk = clk_register_fixed_factor(NULL, "xin12m", "xin24m", 0, 1, 2); + if (IS_ERR(clk)) + pr_warn("%s: could not register clock xin12m: %ld\n", + __func__, PTR_ERR(clk)); + + clk = clk_register_fixed_factor(NULL, "ddrphy_pre", "ddrphy4x", 0, 1, 4); + if (IS_ERR(clk)) + pr_warn("%s: could not register clock ddrphy_pre: %ld\n", + __func__, PTR_ERR(clk)); + + clk = clk_register_fixed_factor(NULL, "hclk_vpu_pre", + "hclk_vpu_src", 0, 1, 4); + if (IS_ERR(clk)) + pr_warn("%s: could not register clock hclk_vpu_pre: %ld\n", + __func__, PTR_ERR(clk)); + + clk = clk_register_fixed_factor(NULL, "hclk_rkvdec_pre", + "hclk_rkvdec_src", 0, 1, 4); + if (IS_ERR(clk)) + pr_warn("%s: could not register clock hclk_rkvdec_pre: %ld\n", + __func__, PTR_ERR(clk)); + + rockchip_clk_register_plls(rk3228_pll_clks, + ARRAY_SIZE(rk3228_pll_clks), + RK3228_GRF_SOC_STATUS0); + rockchip_clk_register_branches(rk3228_clk_branches, + ARRAY_SIZE(rk3228_clk_branches)); + rockchip_clk_protect_critical(rk3228_critical_clocks, + ARRAY_SIZE(rk3228_critical_clocks)); + + rockchip_clk_register_armclk(ARMCLK, "armclk", + mux_armclk_p, ARRAY_SIZE(mux_armclk_p), + &rk3228_cpuclk_data, rk3228_cpuclk_rates, + ARRAY_SIZE(rk3228_cpuclk_rates)); + + rockchip_register_softrst(np, 9, reg_base + RK2928_SOFTRST_CON(0), + ROCKCHIP_SOFTRST_HIWORD_MASK); + + rockchip_register_restart_notifier(RK3228_GLB_SRST_FST, NULL); +} +CLK_OF_DECLARE(rk3228_cru, "rockchip,rk3228-cru", rk3228_clk_init); diff --git a/drivers/clk/rockchip/clk-rk3288.c b/drivers/clk/rockchip/clk-rk3288.c index 9040878e3e2b..11b40fbc4a53 100644 --- a/drivers/clk/rockchip/clk-rk3288.c +++ b/drivers/clk/rockchip/clk-rk3288.c @@ -295,7 +295,7 @@ static struct rockchip_clk_branch rk3288_clk_branches[] __initdata = { RK3288_CLKGATE_CON(0), 4, GFLAGS), GATE(0, "c2c_host", "aclk_cpu_src", 0, RK3288_CLKGATE_CON(13), 8, GFLAGS), - COMPOSITE_NOMUX(0, "crypto", "aclk_cpu_pre", 0, + COMPOSITE_NOMUX(SCLK_CRYPTO, "crypto", "aclk_cpu_pre", 0, RK3288_CLKSEL_CON(26), 6, 2, DFLAGS, RK3288_CLKGATE_CON(5), 4, GFLAGS), GATE(0, "aclk_bus_2pmu", "aclk_cpu_pre", CLK_IGNORE_UNUSED, @@ -644,10 +644,10 @@ static struct rockchip_clk_branch rk3288_clk_branches[] __initdata = { GATE(PCLK_PUBL0, "pclk_publ0", "pclk_cpu", 0, RK3288_CLKGATE_CON(10), 15, GFLAGS), GATE(PCLK_DDRUPCTL1, "pclk_ddrupctl1", "pclk_cpu", 0, RK3288_CLKGATE_CON(11), 0, GFLAGS), GATE(PCLK_PUBL1, "pclk_publ1", "pclk_cpu", 0, RK3288_CLKGATE_CON(11), 1, GFLAGS), - GATE(0, "pclk_efuse_1024", "pclk_cpu", 0, RK3288_CLKGATE_CON(11), 2, GFLAGS), + GATE(PCLK_EFUSE1024, "pclk_efuse_1024", "pclk_cpu", 0, RK3288_CLKGATE_CON(11), 2, GFLAGS), GATE(PCLK_TZPC, "pclk_tzpc", "pclk_cpu", 0, RK3288_CLKGATE_CON(11), 3, GFLAGS), GATE(PCLK_UART2, "pclk_uart2", "pclk_cpu", 0, RK3288_CLKGATE_CON(11), 9, GFLAGS), - GATE(0, "pclk_efuse_256", "pclk_cpu", 0, RK3288_CLKGATE_CON(11), 10, GFLAGS), + GATE(PCLK_EFUSE256, "pclk_efuse_256", "pclk_cpu", 0, RK3288_CLKGATE_CON(11), 10, GFLAGS), GATE(PCLK_RKPWM, "pclk_rkpwm", "pclk_cpu", CLK_IGNORE_UNUSED, RK3288_CLKGATE_CON(11), 11, GFLAGS), /* ddrctrl [DDR Controller PHY clock] gates */ @@ -709,7 +709,7 @@ static struct rockchip_clk_branch rk3288_clk_branches[] __initdata = { GATE(SCLK_LCDC_PWM1, "sclk_lcdc_pwm1", "xin24m", 0, RK3288_CLKGATE_CON(13), 11, GFLAGS), GATE(SCLK_PVTM_CORE, "sclk_pvtm_core", "xin24m", 0, RK3288_CLKGATE_CON(5), 9, GFLAGS), GATE(SCLK_PVTM_GPU, "sclk_pvtm_gpu", "xin24m", 0, RK3288_CLKGATE_CON(5), 10, GFLAGS), - GATE(0, "sclk_mipidsi_24m", "xin24m", 0, RK3288_CLKGATE_CON(5), 15, GFLAGS), + GATE(SCLK_MIPIDSI_24M, "sclk_mipidsi_24m", "xin24m", 0, RK3288_CLKGATE_CON(5), 15, GFLAGS), /* sclk_gpu gates */ GATE(ACLK_GPU, "aclk_gpu", "sclk_gpu", 0, RK3288_CLKGATE_CON(18), 0, GFLAGS), @@ -783,10 +783,10 @@ static const char *const rk3288_critical_clocks[] __initconst = { "pclk_pd_pmu", }; -#ifdef CONFIG_PM_SLEEP static void __iomem *rk3288_cru_base; -/* Some CRU registers will be reset in maskrom when the system +/* + * Some CRU registers will be reset in maskrom when the system * wakes up from fastboot. * So save them before suspend, restore them after resume. */ @@ -840,33 +840,27 @@ static void rk3288_clk_resume(void) } } +static void rk3288_clk_shutdown(void) +{ + writel_relaxed(0xf3030000, rk3288_cru_base + RK3288_MODE_CON); +} + static struct syscore_ops rk3288_clk_syscore_ops = { .suspend = rk3288_clk_suspend, .resume = rk3288_clk_resume, }; -static void rk3288_clk_sleep_init(void __iomem *reg_base) -{ - rk3288_cru_base = reg_base; - register_syscore_ops(&rk3288_clk_syscore_ops); -} - -#else /* CONFIG_PM_SLEEP */ -static void rk3288_clk_sleep_init(void __iomem *reg_base) {} -#endif - static void __init rk3288_clk_init(struct device_node *np) { - void __iomem *reg_base; struct clk *clk; - reg_base = of_iomap(np, 0); - if (!reg_base) { + rk3288_cru_base = of_iomap(np, 0); + if (!rk3288_cru_base) { pr_err("%s: could not map cru region\n", __func__); return; } - rockchip_clk_init(np, reg_base, CLK_NR_CLKS); + rockchip_clk_init(np, rk3288_cru_base, CLK_NR_CLKS); /* xin12m is created by an cru-internal divider */ clk = clk_register_fixed_factor(NULL, "xin12m", "xin24m", 0, 1, 2); @@ -907,10 +901,12 @@ static void __init rk3288_clk_init(struct device_node *np) &rk3288_cpuclk_data, rk3288_cpuclk_rates, ARRAY_SIZE(rk3288_cpuclk_rates)); - rockchip_register_softrst(np, 12, reg_base + RK3288_SOFTRST_CON(0), + rockchip_register_softrst(np, 12, + rk3288_cru_base + RK3288_SOFTRST_CON(0), ROCKCHIP_SOFTRST_HIWORD_MASK); - rockchip_register_restart_notifier(RK3288_GLB_SRST_FST); - rk3288_clk_sleep_init(reg_base); + rockchip_register_restart_notifier(RK3288_GLB_SRST_FST, + rk3288_clk_shutdown); + register_syscore_ops(&rk3288_clk_syscore_ops); } CLK_OF_DECLARE(rk3288_cru, "rockchip,rk3288-cru", rk3288_clk_init); diff --git a/drivers/clk/rockchip/clk-rk3368.c b/drivers/clk/rockchip/clk-rk3368.c index 7e6b783e6eee..be0ede522269 100644 --- a/drivers/clk/rockchip/clk-rk3368.c +++ b/drivers/clk/rockchip/clk-rk3368.c @@ -184,13 +184,13 @@ static const struct rockchip_cpuclk_reg_data rk3368_cpuclkl_data = { #define RK3368_CLKSEL0(_offs, _aclkm) \ { \ - .reg = RK3288_CLKSEL_CON(0 + _offs), \ + .reg = RK3368_CLKSEL_CON(0 + _offs), \ .val = HIWORD_UPDATE(_aclkm, RK3368_DIV_ACLKM_MASK, \ RK3368_DIV_ACLKM_SHIFT), \ } #define RK3368_CLKSEL1(_offs, _atclk, _pdbg) \ { \ - .reg = RK3288_CLKSEL_CON(1 + _offs), \ + .reg = RK3368_CLKSEL_CON(1 + _offs), \ .val = HIWORD_UPDATE(_atclk, RK3368_DIV_ATCLK_MASK, \ RK3368_DIV_ATCLK_SHIFT) | \ HIWORD_UPDATE(_pdbg, RK3368_DIV_PCLK_DBG_MASK, \ @@ -819,6 +819,13 @@ static struct rockchip_clk_branch rk3368_clk_branches[] __initdata = { }; static const char *const rk3368_critical_clocks[] __initconst = { + "aclk_bus", + "aclk_peri", + /* + * pwm1 supplies vdd_logic on a lot of boards, is currently unhandled + * but needs to stay enabled there (including its parents) at all times. + */ + "pclk_pwm1", "pclk_pd_pmu", }; @@ -882,6 +889,6 @@ static void __init rk3368_clk_init(struct device_node *np) rockchip_register_softrst(np, 15, reg_base + RK3368_SOFTRST_CON(0), ROCKCHIP_SOFTRST_HIWORD_MASK); - rockchip_register_restart_notifier(RK3368_GLB_SRST_FST); + rockchip_register_restart_notifier(RK3368_GLB_SRST_FST, NULL); } CLK_OF_DECLARE(rk3368_cru, "rockchip,rk3368-cru", rk3368_clk_init); diff --git a/drivers/clk/rockchip/clk.c b/drivers/clk/rockchip/clk.c index be6c7fd8315d..443d6f07acad 100644 --- a/drivers/clk/rockchip/clk.c +++ b/drivers/clk/rockchip/clk.c @@ -341,9 +341,13 @@ void __init rockchip_clk_protect_critical(const char *const clocks[], } static unsigned int reg_restart; +static void (*cb_restart)(void); static int rockchip_restart_notify(struct notifier_block *this, unsigned long mode, void *cmd) { + if (cb_restart) + cb_restart(); + writel(0xfdb9, reg_base + reg_restart); return NOTIFY_DONE; } @@ -353,11 +357,12 @@ static struct notifier_block rockchip_restart_handler = { .priority = 128, }; -void __init rockchip_register_restart_notifier(unsigned int reg) +void __init rockchip_register_restart_notifier(unsigned int reg, void (*cb)(void)) { int ret; reg_restart = reg; + cb_restart = cb; ret = register_restart_handler(&rockchip_restart_handler); if (ret) pr_err("%s: cannot register restart handler, %d\n", diff --git a/drivers/clk/rockchip/clk.h b/drivers/clk/rockchip/clk.h index dc8ecb2673b7..809ef81cf63b 100644 --- a/drivers/clk/rockchip/clk.h +++ b/drivers/clk/rockchip/clk.h @@ -2,6 +2,9 @@ * Copyright (c) 2014 MundoReader S.L. * Author: Heiko Stuebner <heiko@sntech.de> * + * Copyright (c) 2015 Rockchip Electronics Co. Ltd. + * Author: Xing Zheng <zhengxing@rock-chips.com> + * * based on * * samsung/clk.h @@ -30,7 +33,7 @@ struct clk; #define HIWORD_UPDATE(val, mask, shift) \ ((val) << (shift) | (mask) << ((shift) + 16)) -/* register positions shared by RK2928, RK3066 and RK3188 */ +/* register positions shared by RK2928, RK3036, RK3066, RK3188 and RK3228 */ #define RK2928_PLL_CON(x) ((x) * 0x4) #define RK2928_MODE_CON 0x40 #define RK2928_CLKSEL_CON(x) ((x) * 0x4 + 0x44) @@ -40,6 +43,22 @@ struct clk; #define RK2928_SOFTRST_CON(x) ((x) * 0x4 + 0x110) #define RK2928_MISC_CON 0x134 +#define RK3036_SDMMC_CON0 0x144 +#define RK3036_SDMMC_CON1 0x148 +#define RK3036_SDIO_CON0 0x14c +#define RK3036_SDIO_CON1 0x150 +#define RK3036_EMMC_CON0 0x154 +#define RK3036_EMMC_CON1 0x158 + +#define RK3228_GLB_SRST_FST 0x1f0 +#define RK3228_GLB_SRST_SND 0x1f4 +#define RK3228_SDMMC_CON0 0x1c0 +#define RK3228_SDMMC_CON1 0x1c4 +#define RK3228_SDIO_CON0 0x1c8 +#define RK3228_SDIO_CON1 0x1cc +#define RK3228_EMMC_CON0 0x1d8 +#define RK3228_EMMC_CON1 0x1dc + #define RK3288_PLL_CON(x) RK2928_PLL_CON(x) #define RK3288_MODE_CON 0x50 #define RK3288_CLKSEL_CON(x) ((x) * 0x4 + 0x60) @@ -74,9 +93,22 @@ struct clk; #define RK3368_EMMC_CON1 0x41c enum rockchip_pll_type { + pll_rk3036, pll_rk3066, }; +#define RK3036_PLL_RATE(_rate, _refdiv, _fbdiv, _postdiv1, \ + _postdiv2, _dsmpd, _frac) \ +{ \ + .rate = _rate##U, \ + .fbdiv = _fbdiv, \ + .postdiv1 = _postdiv1, \ + .refdiv = _refdiv, \ + .postdiv2 = _postdiv2, \ + .dsmpd = _dsmpd, \ + .frac = _frac, \ +} + #define RK3066_PLL_RATE(_rate, _nr, _nf, _no) \ { \ .rate = _rate##U, \ @@ -101,6 +133,13 @@ struct rockchip_pll_rate_table { unsigned int nf; unsigned int no; unsigned int nb; + /* for RK3036 */ + unsigned int fbdiv; + unsigned int postdiv1; + unsigned int refdiv; + unsigned int postdiv2; + unsigned int dsmpd; + unsigned int frac; }; /** @@ -464,7 +503,7 @@ void rockchip_clk_register_armclk(unsigned int lookup_id, const char *name, const struct rockchip_cpuclk_rate_table *rates, int nrates); void rockchip_clk_protect_critical(const char *const clocks[], int nclocks); -void rockchip_register_restart_notifier(unsigned int reg); +void rockchip_register_restart_notifier(unsigned int reg, void (*cb)(void)); #define ROCKCHIP_SOFTRST_HIWORD_MASK BIT(0) diff --git a/drivers/clk/shmobile/Makefile b/drivers/clk/shmobile/Makefile index 97c71c885e4f..7e2579b30326 100644 --- a/drivers/clk/shmobile/Makefile +++ b/drivers/clk/shmobile/Makefile @@ -1,13 +1,13 @@ obj-$(CONFIG_ARCH_EMEV2) += clk-emev2.o -obj-$(CONFIG_ARCH_R7S72100) += clk-rz.o -obj-$(CONFIG_ARCH_R8A73A4) += clk-r8a73a4.o -obj-$(CONFIG_ARCH_R8A7740) += clk-r8a7740.o -obj-$(CONFIG_ARCH_R8A7778) += clk-r8a7778.o -obj-$(CONFIG_ARCH_R8A7779) += clk-r8a7779.o -obj-$(CONFIG_ARCH_R8A7790) += clk-rcar-gen2.o -obj-$(CONFIG_ARCH_R8A7791) += clk-rcar-gen2.o -obj-$(CONFIG_ARCH_R8A7793) += clk-rcar-gen2.o -obj-$(CONFIG_ARCH_R8A7794) += clk-rcar-gen2.o -obj-$(CONFIG_ARCH_SH73A0) += clk-sh73a0.o -obj-$(CONFIG_ARCH_SHMOBILE_MULTI) += clk-div6.o -obj-$(CONFIG_ARCH_SHMOBILE_MULTI) += clk-mstp.o +obj-$(CONFIG_ARCH_R7S72100) += clk-rz.o clk-mstp.o +obj-$(CONFIG_ARCH_R8A73A4) += clk-r8a73a4.o clk-mstp.o clk-div6.o +obj-$(CONFIG_ARCH_R8A7740) += clk-r8a7740.o clk-mstp.o clk-div6.o +obj-$(CONFIG_ARCH_R8A7778) += clk-r8a7778.o clk-mstp.o +obj-$(CONFIG_ARCH_R8A7779) += clk-r8a7779.o clk-mstp.o +obj-$(CONFIG_ARCH_R8A7790) += clk-rcar-gen2.o clk-mstp.o clk-div6.o +obj-$(CONFIG_ARCH_R8A7791) += clk-rcar-gen2.o clk-mstp.o clk-div6.o +obj-$(CONFIG_ARCH_R8A7793) += clk-rcar-gen2.o clk-mstp.o clk-div6.o +obj-$(CONFIG_ARCH_R8A7794) += clk-rcar-gen2.o clk-mstp.o clk-div6.o +obj-$(CONFIG_ARCH_R8A7795) += renesas-cpg-mssr.o \ + r8a7795-cpg-mssr.o clk-div6.o +obj-$(CONFIG_ARCH_SH73A0) += clk-sh73a0.o clk-mstp.o clk-div6.o diff --git a/drivers/clk/shmobile/clk-div6.c b/drivers/clk/shmobile/clk-div6.c index b4c8d6746f68..999994769450 100644 --- a/drivers/clk/shmobile/clk-div6.c +++ b/drivers/clk/shmobile/clk-div6.c @@ -18,6 +18,8 @@ #include <linux/of_address.h> #include <linux/slab.h> +#include "clk-div6.h" + #define CPG_DIV6_CKSTP BIT(8) #define CPG_DIV6_DIV(d) ((d) & 0x3f) #define CPG_DIV6_DIV_MASK 0x3f @@ -172,67 +174,44 @@ static const struct clk_ops cpg_div6_clock_ops = { .set_rate = cpg_div6_clock_set_rate, }; -static void __init cpg_div6_clock_init(struct device_node *np) + +/** + * cpg_div6_register - Register a DIV6 clock + * @name: Name of the DIV6 clock + * @num_parents: Number of parent clocks of the DIV6 clock (1, 4, or 8) + * @parent_names: Array containing the names of the parent clocks + * @reg: Mapped register used to control the DIV6 clock + */ +struct clk * __init cpg_div6_register(const char *name, + unsigned int num_parents, + const char **parent_names, + void __iomem *reg) { - unsigned int num_parents, valid_parents; - const char **parent_names; + unsigned int valid_parents; struct clk_init_data init; struct div6_clock *clock; - const char *name; struct clk *clk; unsigned int i; - int ret; clock = kzalloc(sizeof(*clock), GFP_KERNEL); if (!clock) - return; + return ERR_PTR(-ENOMEM); - num_parents = of_clk_get_parent_count(np); - if (num_parents < 1) { - pr_err("%s: no parent found for %s DIV6 clock\n", - __func__, np->name); - return; + clock->parents = kmalloc_array(num_parents, sizeof(*clock->parents), + GFP_KERNEL); + if (!clock->parents) { + clk = ERR_PTR(-ENOMEM); + goto free_clock; } - clock->parents = kmalloc_array(num_parents, sizeof(*clock->parents), - GFP_KERNEL); - parent_names = kmalloc_array(num_parents, sizeof(*parent_names), - GFP_KERNEL); - if (!parent_names) - return; + clock->reg = reg; - /* Remap the clock register and read the divisor. Disabling the - * clock overwrites the divisor, so we need to cache its value for the - * enable operation. + /* + * Read the divisor. Disabling the clock overwrites the divisor, so we + * need to cache its value for the enable operation. */ - clock->reg = of_iomap(np, 0); - if (clock->reg == NULL) { - pr_err("%s: failed to map %s DIV6 clock register\n", - __func__, np->name); - goto error; - } - clock->div = (clk_readl(clock->reg) & CPG_DIV6_DIV_MASK) + 1; - /* Parse the DT properties. */ - ret = of_property_read_string(np, "clock-output-names", &name); - if (ret < 0) { - pr_err("%s: failed to get %s DIV6 clock output name\n", - __func__, np->name); - goto error; - } - - - for (i = 0, valid_parents = 0; i < num_parents; i++) { - const char *name = of_clk_get_parent_name(np, i); - - if (name) { - parent_names[valid_parents] = name; - clock->parents[valid_parents] = i; - valid_parents++; - } - } - switch (num_parents) { case 1: /* fixed parent clock */ @@ -250,8 +229,18 @@ static void __init cpg_div6_clock_init(struct device_node *np) break; default: pr_err("%s: invalid number of parents for DIV6 clock %s\n", - __func__, np->name); - goto error; + __func__, name); + clk = ERR_PTR(-EINVAL); + goto free_parents; + } + + /* Filter out invalid parents */ + for (i = 0, valid_parents = 0; i < num_parents; i++) { + if (parent_names[i]) { + parent_names[valid_parents] = parent_names[i]; + clock->parents[valid_parents] = i; + valid_parents++; + } } /* Register the clock. */ @@ -264,6 +253,53 @@ static void __init cpg_div6_clock_init(struct device_node *np) clock->hw.init = &init; clk = clk_register(NULL, &clock->hw); + if (IS_ERR(clk)) + goto free_parents; + + return clk; + +free_parents: + kfree(clock->parents); +free_clock: + kfree(clock); + return clk; +} + +static void __init cpg_div6_clock_init(struct device_node *np) +{ + unsigned int num_parents; + const char **parent_names; + const char *clk_name = np->name; + void __iomem *reg; + struct clk *clk; + unsigned int i; + + num_parents = of_clk_get_parent_count(np); + if (num_parents < 1) { + pr_err("%s: no parent found for %s DIV6 clock\n", + __func__, np->name); + return; + } + + parent_names = kmalloc_array(num_parents, sizeof(*parent_names), + GFP_KERNEL); + if (!parent_names) + return; + + reg = of_iomap(np, 0); + if (reg == NULL) { + pr_err("%s: failed to map %s DIV6 clock register\n", + __func__, np->name); + goto error; + } + + /* Parse the DT properties. */ + of_property_read_string(np, "clock-output-names", &clk_name); + + for (i = 0; i < num_parents; i++) + parent_names[i] = of_clk_get_parent_name(np, i); + + clk = cpg_div6_register(clk_name, num_parents, parent_names, reg); if (IS_ERR(clk)) { pr_err("%s: failed to register %s DIV6 clock (%ld)\n", __func__, np->name, PTR_ERR(clk)); @@ -276,9 +312,8 @@ static void __init cpg_div6_clock_init(struct device_node *np) return; error: - if (clock->reg) - iounmap(clock->reg); + if (reg) + iounmap(reg); kfree(parent_names); - kfree(clock); } CLK_OF_DECLARE(cpg_div6_clk, "renesas,cpg-div6-clock", cpg_div6_clock_init); diff --git a/drivers/clk/shmobile/clk-div6.h b/drivers/clk/shmobile/clk-div6.h new file mode 100644 index 000000000000..9a85a95188da --- /dev/null +++ b/drivers/clk/shmobile/clk-div6.h @@ -0,0 +1,7 @@ +#ifndef __SHMOBILE_CLK_DIV6_H__ +#define __SHMOBILE_CLK_DIV6_H__ + +struct clk *cpg_div6_register(const char *name, unsigned int num_parents, + const char **parent_names, void __iomem *reg); + +#endif diff --git a/drivers/clk/shmobile/clk-rcar-gen2.c b/drivers/clk/shmobile/clk-rcar-gen2.c index 745496f7ee9c..841977240305 100644 --- a/drivers/clk/shmobile/clk-rcar-gen2.c +++ b/drivers/clk/shmobile/clk-rcar-gen2.c @@ -115,7 +115,7 @@ static int cpg_z_clk_set_rate(struct clk_hw *hw, unsigned long rate, * * Using experimental measurements, it seems that no more than * ~10 iterations are needed, independently of the CPU rate. - * Since this value might be dependant of external xtal rate, pll1 + * Since this value might be dependent on external xtal rate, pll1 * rate or even the other emulation clocks rate, use 1000 as a * "super" safe value. */ @@ -262,7 +262,7 @@ static struct clk * __init cpg_adsp_clk_register(struct rcar_gen2_cpg *cpg) * 1 1 0 30 / 2 x172/2 x208/2 x106 * 1 1 1 30 / 2 x172/2 x208/2 x88 * - * *1 : Table 7.6 indicates VCO ouput (PLLx = VCO/2) + * *1 : Table 7.6 indicates VCO output (PLLx = VCO/2) */ #define CPG_PLL_CONFIG_INDEX(md) ((((md) & BIT(14)) >> 12) | \ (((md) & BIT(13)) >> 12) | \ diff --git a/drivers/clk/shmobile/r8a7795-cpg-mssr.c b/drivers/clk/shmobile/r8a7795-cpg-mssr.c new file mode 100644 index 000000000000..57c413635d1a --- /dev/null +++ b/drivers/clk/shmobile/r8a7795-cpg-mssr.c @@ -0,0 +1,382 @@ +/* + * r8a7795 Clock Pulse Generator / Module Standby and Software Reset + * + * Copyright (C) 2015 Glider bvba + * + * Based on clk-rcar-gen3.c + * + * Copyright (C) 2015 Renesas Electronics Corp. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + */ + +#include <linux/bug.h> +#include <linux/clk-provider.h> +#include <linux/device.h> +#include <linux/err.h> +#include <linux/init.h> +#include <linux/io.h> +#include <linux/kernel.h> +#include <linux/of.h> + +#include <dt-bindings/clock/r8a7795-cpg-mssr.h> + +#include "renesas-cpg-mssr.h" + + +enum clk_ids { + /* Core Clock Outputs exported to DT */ + LAST_DT_CORE_CLK = R8A7795_CLK_OSC, + + /* External Input Clocks */ + CLK_EXTAL, + CLK_EXTALR, + + /* Internal Core Clocks */ + CLK_MAIN, + CLK_PLL0, + CLK_PLL1, + CLK_PLL2, + CLK_PLL3, + CLK_PLL4, + CLK_PLL1_DIV2, + CLK_PLL1_DIV4, + CLK_S0, + CLK_S1, + CLK_S2, + CLK_S3, + CLK_SDSRC, + CLK_SSPSRC, + + /* Module Clocks */ + MOD_CLK_BASE +}; + +enum r8a7795_clk_types { + CLK_TYPE_GEN3_MAIN = CLK_TYPE_CUSTOM, + CLK_TYPE_GEN3_PLL0, + CLK_TYPE_GEN3_PLL1, + CLK_TYPE_GEN3_PLL2, + CLK_TYPE_GEN3_PLL3, + CLK_TYPE_GEN3_PLL4, +}; + +static const struct cpg_core_clk r8a7795_core_clks[] __initconst = { + /* External Clock Inputs */ + DEF_INPUT("extal", CLK_EXTAL), + DEF_INPUT("extalr", CLK_EXTALR), + + /* Internal Core Clocks */ + DEF_BASE(".main", CLK_MAIN, CLK_TYPE_GEN3_MAIN, CLK_EXTAL), + DEF_BASE(".pll0", CLK_PLL0, CLK_TYPE_GEN3_PLL0, CLK_MAIN), + DEF_BASE(".pll1", CLK_PLL1, CLK_TYPE_GEN3_PLL1, CLK_MAIN), + DEF_BASE(".pll2", CLK_PLL2, CLK_TYPE_GEN3_PLL2, CLK_MAIN), + DEF_BASE(".pll3", CLK_PLL3, CLK_TYPE_GEN3_PLL3, CLK_MAIN), + DEF_BASE(".pll4", CLK_PLL4, CLK_TYPE_GEN3_PLL4, CLK_MAIN), + + DEF_FIXED(".pll1_div2", CLK_PLL1_DIV2, CLK_PLL1, 2, 1), + DEF_FIXED(".pll1_div4", CLK_PLL1_DIV4, CLK_PLL1_DIV2, 2, 1), + DEF_FIXED(".s0", CLK_S0, CLK_PLL1_DIV2, 2, 1), + DEF_FIXED(".s1", CLK_S1, CLK_PLL1_DIV2, 3, 1), + DEF_FIXED(".s2", CLK_S2, CLK_PLL1_DIV2, 4, 1), + DEF_FIXED(".s3", CLK_S3, CLK_PLL1_DIV2, 6, 1), + + /* Core Clock Outputs */ + 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), + DEF_FIXED("zx", R8A7795_CLK_ZX, CLK_PLL1_DIV2, 2, 1), + DEF_FIXED("s0d1", R8A7795_CLK_S0D1, CLK_S0, 1, 1), + DEF_FIXED("s0d4", R8A7795_CLK_S0D4, CLK_S0, 4, 1), + DEF_FIXED("s1d1", R8A7795_CLK_S1D1, CLK_S1, 1, 1), + DEF_FIXED("s1d2", R8A7795_CLK_S1D2, CLK_S1, 2, 1), + DEF_FIXED("s1d4", R8A7795_CLK_S1D4, CLK_S1, 4, 1), + DEF_FIXED("s2d1", R8A7795_CLK_S2D1, CLK_S2, 1, 1), + DEF_FIXED("s2d2", R8A7795_CLK_S2D2, CLK_S2, 2, 1), + DEF_FIXED("s2d4", R8A7795_CLK_S2D4, CLK_S2, 4, 1), + DEF_FIXED("s3d1", R8A7795_CLK_S3D1, CLK_S3, 1, 1), + DEF_FIXED("s3d2", R8A7795_CLK_S3D2, CLK_S3, 2, 1), + DEF_FIXED("s3d4", R8A7795_CLK_S3D4, CLK_S3, 4, 1), + DEF_FIXED("cl", R8A7795_CLK_CL, CLK_PLL1_DIV2, 48, 1), + DEF_FIXED("cp", R8A7795_CLK_CP, CLK_EXTAL, 2, 1), + + DEF_DIV6P1("mso", R8A7795_CLK_MSO, CLK_PLL1_DIV4, 0x014), + DEF_DIV6P1("hdmi", R8A7795_CLK_HDMI, CLK_PLL1_DIV2, 0x250), +}; + +static const struct mssr_mod_clk r8a7795_mod_clks[] __initconst = { + DEF_MOD("scif5", 202, R8A7795_CLK_S3D4), + DEF_MOD("scif4", 203, R8A7795_CLK_S3D4), + DEF_MOD("scif3", 204, R8A7795_CLK_S3D4), + DEF_MOD("scif1", 206, R8A7795_CLK_S3D4), + DEF_MOD("scif0", 207, R8A7795_CLK_S3D4), + DEF_MOD("msiof3", 208, R8A7795_CLK_MSO), + 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_S3D1), + DEF_MOD("sys-dmac1", 218, R8A7795_CLK_S3D1), + DEF_MOD("sys-dmac0", 219, R8A7795_CLK_S3D1), + DEF_MOD("scif2", 310, R8A7795_CLK_S3D4), + DEF_MOD("pcie1", 318, R8A7795_CLK_S3D1), + DEF_MOD("pcie0", 319, R8A7795_CLK_S3D1), + DEF_MOD("intc-ap", 408, R8A7795_CLK_S3D1), + DEF_MOD("audmac0", 502, R8A7795_CLK_S3D4), + DEF_MOD("audmac1", 501, R8A7795_CLK_S3D4), + DEF_MOD("hscif4", 516, R8A7795_CLK_S3D1), + DEF_MOD("hscif3", 517, R8A7795_CLK_S3D1), + DEF_MOD("hscif2", 518, R8A7795_CLK_S3D1), + DEF_MOD("hscif1", 519, R8A7795_CLK_S3D1), + DEF_MOD("hscif0", 520, R8A7795_CLK_S3D1), + DEF_MOD("vspd3", 620, R8A7795_CLK_S2D1), + DEF_MOD("vspd2", 621, R8A7795_CLK_S2D1), + DEF_MOD("vspd1", 622, R8A7795_CLK_S2D1), + DEF_MOD("vspd0", 623, R8A7795_CLK_S2D1), + DEF_MOD("vspbc", 624, R8A7795_CLK_S2D1), + DEF_MOD("vspbd", 626, R8A7795_CLK_S2D1), + DEF_MOD("vspi2", 629, R8A7795_CLK_S2D1), + DEF_MOD("vspi1", 630, R8A7795_CLK_S2D1), + DEF_MOD("vspi0", 631, R8A7795_CLK_S2D1), + 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("du3", 721, R8A7795_CLK_S2D1), + DEF_MOD("du2", 722, R8A7795_CLK_S2D1), + DEF_MOD("du1", 723, R8A7795_CLK_S2D1), + DEF_MOD("du0", 724, R8A7795_CLK_S2D1), + DEF_MOD("hdmi1", 728, R8A7795_CLK_HDMI), + DEF_MOD("hdmi0", 729, R8A7795_CLK_HDMI), + DEF_MOD("etheravb", 812, R8A7795_CLK_S3D2), + DEF_MOD("gpio7", 905, R8A7795_CLK_CP), + DEF_MOD("gpio6", 906, R8A7795_CLK_CP), + DEF_MOD("gpio5", 907, R8A7795_CLK_CP), + DEF_MOD("gpio4", 908, R8A7795_CLK_CP), + DEF_MOD("gpio3", 909, R8A7795_CLK_CP), + DEF_MOD("gpio2", 910, R8A7795_CLK_CP), + DEF_MOD("gpio1", 911, R8A7795_CLK_CP), + DEF_MOD("gpio0", 912, R8A7795_CLK_CP), + DEF_MOD("i2c6", 918, R8A7795_CLK_S3D2), + DEF_MOD("i2c5", 919, R8A7795_CLK_S3D2), + DEF_MOD("i2c4", 927, R8A7795_CLK_S3D2), + DEF_MOD("i2c3", 928, R8A7795_CLK_S3D2), + DEF_MOD("i2c2", 929, R8A7795_CLK_S3D2), + DEF_MOD("i2c1", 930, R8A7795_CLK_S3D2), + DEF_MOD("i2c0", 931, R8A7795_CLK_S3D2), + DEF_MOD("ssi-all", 1005, R8A7795_CLK_S3D4), + DEF_MOD("ssi9", 1006, MOD_CLK_ID(1005)), + DEF_MOD("ssi8", 1007, MOD_CLK_ID(1005)), + DEF_MOD("ssi7", 1008, MOD_CLK_ID(1005)), + DEF_MOD("ssi6", 1009, MOD_CLK_ID(1005)), + DEF_MOD("ssi5", 1010, MOD_CLK_ID(1005)), + DEF_MOD("ssi4", 1011, MOD_CLK_ID(1005)), + DEF_MOD("ssi3", 1012, MOD_CLK_ID(1005)), + DEF_MOD("ssi2", 1013, MOD_CLK_ID(1005)), + DEF_MOD("ssi1", 1014, MOD_CLK_ID(1005)), + DEF_MOD("ssi0", 1015, MOD_CLK_ID(1005)), + DEF_MOD("scu-all", 1017, R8A7795_CLK_S3D4), + DEF_MOD("scu-dvc1", 1018, MOD_CLK_ID(1017)), + DEF_MOD("scu-dvc0", 1019, MOD_CLK_ID(1017)), + DEF_MOD("scu-ctu1-mix1", 1020, MOD_CLK_ID(1017)), + DEF_MOD("scu-ctu0-mix0", 1021, MOD_CLK_ID(1017)), + DEF_MOD("scu-src9", 1022, MOD_CLK_ID(1017)), + DEF_MOD("scu-src8", 1023, MOD_CLK_ID(1017)), + DEF_MOD("scu-src7", 1024, MOD_CLK_ID(1017)), + DEF_MOD("scu-src6", 1025, MOD_CLK_ID(1017)), + DEF_MOD("scu-src5", 1026, MOD_CLK_ID(1017)), + DEF_MOD("scu-src4", 1027, MOD_CLK_ID(1017)), + DEF_MOD("scu-src3", 1028, MOD_CLK_ID(1017)), + DEF_MOD("scu-src2", 1029, MOD_CLK_ID(1017)), + DEF_MOD("scu-src1", 1030, MOD_CLK_ID(1017)), + DEF_MOD("scu-src0", 1031, MOD_CLK_ID(1017)), +}; + +static const unsigned int r8a7795_crit_mod_clks[] __initconst = { + MOD_CLK_ID(408), /* INTC-AP (GIC) */ +}; + + +#define CPG_PLL0CR 0x00d8 +#define CPG_PLL2CR 0x002c +#define CPG_PLL4CR 0x01f4 + +/* + * CPG Clock Data + */ + +/* + * MD EXTAL PLL0 PLL1 PLL2 PLL3 PLL4 + * 14 13 19 17 (MHz) + *------------------------------------------------------------------- + * 0 0 0 0 16.66 x 1 x180 x192 x144 x192 x144 + * 0 0 0 1 16.66 x 1 x180 x192 x144 x128 x144 + * 0 0 1 0 Prohibited setting + * 0 0 1 1 16.66 x 1 x180 x192 x144 x192 x144 + * 0 1 0 0 20 x 1 x150 x160 x120 x160 x120 + * 0 1 0 1 20 x 1 x150 x160 x120 x106 x120 + * 0 1 1 0 Prohibited setting + * 0 1 1 1 20 x 1 x150 x160 x120 x160 x120 + * 1 0 0 0 25 x 1 x120 x128 x96 x128 x96 + * 1 0 0 1 25 x 1 x120 x128 x96 x84 x96 + * 1 0 1 0 Prohibited setting + * 1 0 1 1 25 x 1 x120 x128 x96 x128 x96 + * 1 1 0 0 33.33 / 2 x180 x192 x144 x192 x144 + * 1 1 0 1 33.33 / 2 x180 x192 x144 x128 x144 + * 1 1 1 0 Prohibited setting + * 1 1 1 1 33.33 / 2 x180 x192 x144 x192 x144 + */ +#define CPG_PLL_CONFIG_INDEX(md) ((((md) & BIT(14)) >> 11) | \ + (((md) & BIT(13)) >> 11) | \ + (((md) & BIT(19)) >> 18) | \ + (((md) & BIT(17)) >> 17)) + +struct cpg_pll_config { + unsigned int extal_div; + unsigned int pll1_mult; + unsigned int pll3_mult; +}; + +static const struct cpg_pll_config cpg_pll_configs[16] __initconst = { + /* EXTAL div PLL1 mult PLL3 mult */ + { 1, 192, 192, }, + { 1, 192, 128, }, + { 0, /* Prohibited setting */ }, + { 1, 192, 192, }, + { 1, 160, 160, }, + { 1, 160, 106, }, + { 0, /* Prohibited setting */ }, + { 1, 160, 160, }, + { 1, 128, 128, }, + { 1, 128, 84, }, + { 0, /* Prohibited setting */ }, + { 1, 128, 128, }, + { 2, 192, 192, }, + { 2, 192, 128, }, + { 0, /* Prohibited setting */ }, + { 2, 192, 192, }, +}; + +static const struct cpg_pll_config *cpg_pll_config __initdata; + +static +struct clk * __init r8a7795_cpg_clk_register(struct device *dev, + const struct cpg_core_clk *core, + const struct cpg_mssr_info *info, + struct clk **clks, + void __iomem *base) +{ + const struct clk *parent; + unsigned int mult = 1; + unsigned int div = 1; + u32 value; + + parent = clks[core->parent]; + if (IS_ERR(parent)) + return ERR_CAST(parent); + + switch (core->type) { + case CLK_TYPE_GEN3_MAIN: + div = cpg_pll_config->extal_div; + break; + + case CLK_TYPE_GEN3_PLL0: + /* + * PLL0 is a configurable multiplier clock. Register it as a + * fixed factor clock for now as there's no generic multiplier + * clock implementation and we currently have no need to change + * the multiplier value. + */ + value = readl(base + CPG_PLL0CR); + mult = (((value >> 24) & 0x7f) + 1) * 2; + break; + + case CLK_TYPE_GEN3_PLL1: + mult = cpg_pll_config->pll1_mult; + break; + + case CLK_TYPE_GEN3_PLL2: + /* + * PLL2 is a configurable multiplier clock. Register it as a + * fixed factor clock for now as there's no generic multiplier + * clock implementation and we currently have no need to change + * the multiplier value. + */ + value = readl(base + CPG_PLL2CR); + mult = (((value >> 24) & 0x7f) + 1) * 2; + break; + + case CLK_TYPE_GEN3_PLL3: + mult = cpg_pll_config->pll3_mult; + break; + + case CLK_TYPE_GEN3_PLL4: + /* + * PLL4 is a configurable multiplier clock. Register it as a + * fixed factor clock for now as there's no generic multiplier + * clock implementation and we currently have no need to change + * the multiplier value. + */ + value = readl(base + CPG_PLL4CR); + mult = (((value >> 24) & 0x7f) + 1) * 2; + break; + + default: + return ERR_PTR(-EINVAL); + } + + return clk_register_fixed_factor(NULL, core->name, + __clk_get_name(parent), 0, mult, div); +} + +/* + * Reset register definitions. + */ +#define MODEMR 0xe6160060 + +static u32 rcar_gen3_read_mode_pins(void) +{ + void __iomem *modemr = ioremap_nocache(MODEMR, 4); + u32 mode; + + BUG_ON(!modemr); + mode = ioread32(modemr); + iounmap(modemr); + + return mode; +} + +static int __init r8a7795_cpg_mssr_init(struct device *dev) +{ + u32 cpg_mode = rcar_gen3_read_mode_pins(); + + cpg_pll_config = &cpg_pll_configs[CPG_PLL_CONFIG_INDEX(cpg_mode)]; + if (!cpg_pll_config->extal_div) { + dev_err(dev, "Prohibited setting (cpg_mode=0x%x)\n", cpg_mode); + return -EINVAL; + } + + return 0; +} + +const struct cpg_mssr_info r8a7795_cpg_mssr_info __initconst = { + /* Core Clocks */ + .core_clks = r8a7795_core_clks, + .num_core_clks = ARRAY_SIZE(r8a7795_core_clks), + .last_dt_core_clk = LAST_DT_CORE_CLK, + .num_total_core_clks = MOD_CLK_BASE, + + /* Module Clocks */ + .mod_clks = r8a7795_mod_clks, + .num_mod_clks = ARRAY_SIZE(r8a7795_mod_clks), + .num_hw_mod_clks = 12 * 32, + + /* Critical Module Clocks */ + .crit_mod_clks = r8a7795_crit_mod_clks, + .num_crit_mod_clks = ARRAY_SIZE(r8a7795_crit_mod_clks), + + /* Callbacks */ + .init = r8a7795_cpg_mssr_init, + .cpg_clk_register = r8a7795_cpg_clk_register, +}; diff --git a/drivers/clk/shmobile/renesas-cpg-mssr.c b/drivers/clk/shmobile/renesas-cpg-mssr.c new file mode 100644 index 000000000000..9a4d888164bb --- /dev/null +++ b/drivers/clk/shmobile/renesas-cpg-mssr.c @@ -0,0 +1,596 @@ +/* + * Renesas Clock Pulse Generator / Module Standby and Software Reset + * + * Copyright (C) 2015 Glider bvba + * + * Based on clk-mstp.c, clk-rcar-gen2.c, and clk-rcar-gen3.c + * + * Copyright (C) 2013 Ideas On Board SPRL + * Copyright (C) 2015 Renesas Electronics Corp. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + */ + +#include <linux/clk.h> +#include <linux/clk-provider.h> +#include <linux/device.h> +#include <linux/init.h> +#include <linux/mod_devicetable.h> +#include <linux/module.h> +#include <linux/of_address.h> +#include <linux/of_device.h> +#include <linux/platform_device.h> +#include <linux/pm_clock.h> +#include <linux/pm_domain.h> +#include <linux/slab.h> + +#include <dt-bindings/clock/renesas-cpg-mssr.h> + +#include "renesas-cpg-mssr.h" +#include "clk-div6.h" + +#ifdef DEBUG +#define WARN_DEBUG(x) do { } while (0) +#else +#define WARN_DEBUG(x) WARN_ON(x) +#endif + + +/* + * Module Standby and Software Reset register offets. + * + * If the registers exist, these are valid for SH-Mobile, R-Mobile, + * R-Car Gen 2, and R-Car Gen 3. + * These are NOT valid for R-Car Gen1 and RZ/A1! + */ + +/* + * Module Stop Status Register offsets + */ + +static const u16 mstpsr[] = { + 0x030, 0x038, 0x040, 0x048, 0x04C, 0x03C, 0x1C0, 0x1C4, + 0x9A0, 0x9A4, 0x9A8, 0x9AC, +}; + +#define MSTPSR(i) mstpsr[i] + + +/* + * System Module Stop Control Register offsets + */ + +static const u16 smstpcr[] = { + 0x130, 0x134, 0x138, 0x13C, 0x140, 0x144, 0x148, 0x14C, + 0x990, 0x994, 0x998, 0x99C, +}; + +#define SMSTPCR(i) smstpcr[i] + + +/* + * Software Reset Register offsets + */ + +static const u16 srcr[] = { + 0x0A0, 0x0A8, 0x0B0, 0x0B8, 0x0BC, 0x0C4, 0x1C8, 0x1CC, + 0x920, 0x924, 0x928, 0x92C, +}; + +#define SRCR(i) srcr[i] + + +/* Realtime Module Stop Control Register offsets */ +#define RMSTPCR(i) (smstpcr[i] - 0x20) + +/* Modem Module Stop Control Register offsets (r8a73a4) */ +#define MMSTPCR(i) (smstpcr[i] + 0x20) + +/* Software Reset Clearing Register offsets */ +#define SRSTCLR(i) (0x940 + (i) * 4) + + +/** + * Clock Pulse Generator / Module Standby and Software Reset Private Data + * + * @dev: CPG/MSSR device + * @base: CPG/MSSR register block base address + * @mstp_lock: protects writes to SMSTPCR + * @clks: Array containing all Core and Module Clocks + * @num_core_clks: Number of Core Clocks in clks[] + * @num_mod_clks: Number of Module Clocks in clks[] + * @last_dt_core_clk: ID of the last Core Clock exported to DT + */ +struct cpg_mssr_priv { + struct device *dev; + void __iomem *base; + spinlock_t mstp_lock; + + struct clk **clks; + unsigned int num_core_clks; + unsigned int num_mod_clks; + unsigned int last_dt_core_clk; +}; + + +/** + * struct mstp_clock - MSTP gating clock + * @hw: handle between common and hardware-specific interfaces + * @index: MSTP clock number + * @priv: CPG/MSSR private data + */ +struct mstp_clock { + struct clk_hw hw; + u32 index; + struct cpg_mssr_priv *priv; +}; + +#define to_mstp_clock(_hw) container_of(_hw, struct mstp_clock, hw) + +static int cpg_mstp_clock_endisable(struct clk_hw *hw, bool enable) +{ + struct mstp_clock *clock = to_mstp_clock(hw); + struct cpg_mssr_priv *priv = clock->priv; + unsigned int reg = clock->index / 32; + unsigned int bit = clock->index % 32; + struct device *dev = priv->dev; + u32 bitmask = BIT(bit); + unsigned long flags; + unsigned int i; + u32 value; + + dev_dbg(dev, "MSTP %u%02u/%pC %s\n", reg, bit, hw->clk, + enable ? "ON" : "OFF"); + spin_lock_irqsave(&priv->mstp_lock, flags); + + value = clk_readl(priv->base + SMSTPCR(reg)); + if (enable) + value &= ~bitmask; + else + value |= bitmask; + clk_writel(value, priv->base + SMSTPCR(reg)); + + spin_unlock_irqrestore(&priv->mstp_lock, flags); + + if (!enable) + return 0; + + for (i = 1000; i > 0; --i) { + if (!(clk_readl(priv->base + MSTPSR(reg)) & + bitmask)) + break; + cpu_relax(); + } + + if (!i) { + dev_err(dev, "Failed to enable SMSTP %p[%d]\n", + priv->base + SMSTPCR(reg), bit); + return -ETIMEDOUT; + } + + return 0; +} + +static int cpg_mstp_clock_enable(struct clk_hw *hw) +{ + return cpg_mstp_clock_endisable(hw, true); +} + +static void cpg_mstp_clock_disable(struct clk_hw *hw) +{ + cpg_mstp_clock_endisable(hw, false); +} + +static int cpg_mstp_clock_is_enabled(struct clk_hw *hw) +{ + struct mstp_clock *clock = to_mstp_clock(hw); + struct cpg_mssr_priv *priv = clock->priv; + u32 value; + + value = clk_readl(priv->base + MSTPSR(clock->index / 32)); + + return !(value & BIT(clock->index % 32)); +} + +static const struct clk_ops cpg_mstp_clock_ops = { + .enable = cpg_mstp_clock_enable, + .disable = cpg_mstp_clock_disable, + .is_enabled = cpg_mstp_clock_is_enabled, +}; + +static +struct clk *cpg_mssr_clk_src_twocell_get(struct of_phandle_args *clkspec, + void *data) +{ + unsigned int clkidx = clkspec->args[1]; + struct cpg_mssr_priv *priv = data; + struct device *dev = priv->dev; + unsigned int idx; + const char *type; + struct clk *clk; + + switch (clkspec->args[0]) { + case CPG_CORE: + type = "core"; + if (clkidx > priv->last_dt_core_clk) { + dev_err(dev, "Invalid %s clock index %u\n", type, + clkidx); + return ERR_PTR(-EINVAL); + } + clk = priv->clks[clkidx]; + break; + + case CPG_MOD: + type = "module"; + idx = MOD_CLK_PACK(clkidx); + if (clkidx % 100 > 31 || idx >= priv->num_mod_clks) { + dev_err(dev, "Invalid %s clock index %u\n", type, + clkidx); + return ERR_PTR(-EINVAL); + } + clk = priv->clks[priv->num_core_clks + idx]; + break; + + default: + dev_err(dev, "Invalid CPG clock type %u\n", clkspec->args[0]); + return ERR_PTR(-EINVAL); + } + + if (IS_ERR(clk)) + dev_err(dev, "Cannot get %s clock %u: %ld", type, clkidx, + PTR_ERR(clk)); + else + dev_dbg(dev, "clock (%u, %u) is %pC at %pCr Hz\n", + clkspec->args[0], clkspec->args[1], clk, clk); + return clk; +} + +static void __init cpg_mssr_register_core_clk(const struct cpg_core_clk *core, + const struct cpg_mssr_info *info, + struct cpg_mssr_priv *priv) +{ + struct clk *clk = NULL, *parent; + struct device *dev = priv->dev; + unsigned int id = core->id; + const char *parent_name; + + WARN_DEBUG(id >= priv->num_core_clks); + WARN_DEBUG(PTR_ERR(priv->clks[id]) != -ENOENT); + + switch (core->type) { + case CLK_TYPE_IN: + clk = of_clk_get_by_name(priv->dev->of_node, core->name); + break; + + case CLK_TYPE_FF: + case CLK_TYPE_DIV6P1: + WARN_DEBUG(core->parent >= priv->num_core_clks); + parent = priv->clks[core->parent]; + if (IS_ERR(parent)) { + clk = parent; + goto fail; + } + + parent_name = __clk_get_name(parent); + if (core->type == CLK_TYPE_FF) { + clk = clk_register_fixed_factor(NULL, core->name, + parent_name, 0, + core->mult, core->div); + } else { + clk = cpg_div6_register(core->name, 1, &parent_name, + priv->base + core->offset); + } + break; + + default: + if (info->cpg_clk_register) + clk = info->cpg_clk_register(dev, core, info, + priv->clks, priv->base); + else + dev_err(dev, "%s has unsupported core clock type %u\n", + core->name, core->type); + break; + } + + if (IS_ERR_OR_NULL(clk)) + goto fail; + + dev_dbg(dev, "Core clock %pC at %pCr Hz\n", clk, clk); + priv->clks[id] = clk; + return; + +fail: + dev_err(dev, "Failed to register %s clock %s: %ld\n", "core,", + core->name, PTR_ERR(clk)); +} + +static void __init cpg_mssr_register_mod_clk(const struct mssr_mod_clk *mod, + const struct cpg_mssr_info *info, + struct cpg_mssr_priv *priv) +{ + struct mstp_clock *clock = NULL; + struct device *dev = priv->dev; + unsigned int id = mod->id; + struct clk_init_data init; + struct clk *parent, *clk; + const char *parent_name; + unsigned int i; + + WARN_DEBUG(id < priv->num_core_clks); + WARN_DEBUG(id >= priv->num_core_clks + priv->num_mod_clks); + WARN_DEBUG(mod->parent >= priv->num_core_clks + priv->num_mod_clks); + WARN_DEBUG(PTR_ERR(priv->clks[id]) != -ENOENT); + + parent = priv->clks[mod->parent]; + if (IS_ERR(parent)) { + clk = parent; + goto fail; + } + + clock = kzalloc(sizeof(*clock), GFP_KERNEL); + if (!clock) { + clk = ERR_PTR(-ENOMEM); + goto fail; + } + + init.name = mod->name; + init.ops = &cpg_mstp_clock_ops; + init.flags = CLK_IS_BASIC | CLK_SET_RATE_PARENT; + for (i = 0; i < info->num_crit_mod_clks; i++) + if (id == info->crit_mod_clks[i]) { +#ifdef CLK_ENABLE_HAND_OFF + dev_dbg(dev, "MSTP %s setting CLK_ENABLE_HAND_OFF\n", + mod->name); + init.flags |= CLK_ENABLE_HAND_OFF; + break; +#else + dev_dbg(dev, "Ignoring MSTP %s to prevent disabling\n", + mod->name); + return; +#endif + } + + parent_name = __clk_get_name(parent); + init.parent_names = &parent_name; + init.num_parents = 1; + + clock->index = id - priv->num_core_clks; + clock->priv = priv; + clock->hw.init = &init; + + clk = clk_register(NULL, &clock->hw); + if (IS_ERR(clk)) + goto fail; + + dev_dbg(dev, "Module clock %pC at %pCr Hz\n", clk, clk); + priv->clks[id] = clk; + return; + +fail: + dev_err(dev, "Failed to register %s clock %s: %ld\n", "module,", + mod->name, PTR_ERR(clk)); + kfree(clock); +} + + +#ifdef CONFIG_PM_GENERIC_DOMAINS_OF +struct cpg_mssr_clk_domain { + struct generic_pm_domain genpd; + struct device_node *np; + unsigned int num_core_pm_clks; + unsigned int core_pm_clks[0]; +}; + +static bool cpg_mssr_is_pm_clk(const struct of_phandle_args *clkspec, + struct cpg_mssr_clk_domain *pd) +{ + unsigned int i; + + if (clkspec->np != pd->np || clkspec->args_count != 2) + return false; + + switch (clkspec->args[0]) { + case CPG_CORE: + for (i = 0; i < pd->num_core_pm_clks; i++) + if (clkspec->args[1] == pd->core_pm_clks[i]) + return true; + return false; + + case CPG_MOD: + return true; + + default: + return false; + } +} + +static int cpg_mssr_attach_dev(struct generic_pm_domain *genpd, + struct device *dev) +{ + struct cpg_mssr_clk_domain *pd = + container_of(genpd, struct cpg_mssr_clk_domain, genpd); + struct device_node *np = dev->of_node; + struct of_phandle_args clkspec; + struct clk *clk; + int i = 0; + int error; + + while (!of_parse_phandle_with_args(np, "clocks", "#clock-cells", i, + &clkspec)) { + if (cpg_mssr_is_pm_clk(&clkspec, pd)) + goto found; + + of_node_put(clkspec.np); + i++; + } + + return 0; + +found: + clk = of_clk_get_from_provider(&clkspec); + of_node_put(clkspec.np); + + if (IS_ERR(clk)) + return PTR_ERR(clk); + + error = pm_clk_create(dev); + if (error) { + dev_err(dev, "pm_clk_create failed %d\n", error); + goto fail_put; + } + + error = pm_clk_add_clk(dev, clk); + if (error) { + dev_err(dev, "pm_clk_add_clk %pC failed %d\n", clk, error); + goto fail_destroy; + } + + return 0; + +fail_destroy: + pm_clk_destroy(dev); +fail_put: + clk_put(clk); + return error; +} + +static void cpg_mssr_detach_dev(struct generic_pm_domain *genpd, + struct device *dev) +{ + if (!list_empty(&dev->power.subsys_data->clock_list)) + pm_clk_destroy(dev); +} + +static int __init cpg_mssr_add_clk_domain(struct device *dev, + const unsigned int *core_pm_clks, + unsigned int num_core_pm_clks) +{ + struct device_node *np = dev->of_node; + struct generic_pm_domain *genpd; + struct cpg_mssr_clk_domain *pd; + size_t pm_size = num_core_pm_clks * sizeof(core_pm_clks[0]); + + pd = devm_kzalloc(dev, sizeof(*pd) + pm_size, GFP_KERNEL); + if (!pd) + return -ENOMEM; + + pd->np = np; + pd->num_core_pm_clks = num_core_pm_clks; + memcpy(pd->core_pm_clks, core_pm_clks, pm_size); + + genpd = &pd->genpd; + genpd->name = np->name; + genpd->flags = GENPD_FLAG_PM_CLK; + pm_genpd_init(genpd, &simple_qos_governor, false); + genpd->attach_dev = cpg_mssr_attach_dev; + genpd->detach_dev = cpg_mssr_detach_dev; + + of_genpd_add_provider_simple(np, genpd); + return 0; +} +#else +static inline int cpg_mssr_add_clk_domain(struct device *dev, + const unsigned int *core_pm_clks, + unsigned int num_core_pm_clks) +{ + return 0; +} +#endif /* !CONFIG_PM_GENERIC_DOMAINS_OF */ + + +static const struct of_device_id cpg_mssr_match[] = { +#ifdef CONFIG_ARCH_R8A7795 + { + .compatible = "renesas,r8a7795-cpg-mssr", + .data = &r8a7795_cpg_mssr_info, + }, +#endif + { /* sentinel */ } +}; + +static void cpg_mssr_del_clk_provider(void *data) +{ + of_clk_del_provider(data); +} + +static int __init cpg_mssr_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct device_node *np = dev->of_node; + const struct cpg_mssr_info *info; + struct cpg_mssr_priv *priv; + unsigned int nclks, i; + struct resource *res; + struct clk **clks; + int error; + + info = of_match_node(cpg_mssr_match, np)->data; + if (info->init) { + error = info->init(dev); + if (error) + return error; + } + + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + priv->dev = dev; + spin_lock_init(&priv->mstp_lock); + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + priv->base = devm_ioremap_resource(dev, res); + if (IS_ERR(priv->base)) + return PTR_ERR(priv->base); + + nclks = info->num_total_core_clks + info->num_hw_mod_clks; + clks = devm_kmalloc_array(dev, nclks, sizeof(*clks), GFP_KERNEL); + if (!clks) + return -ENOMEM; + + priv->clks = clks; + priv->num_core_clks = info->num_total_core_clks; + priv->num_mod_clks = info->num_hw_mod_clks; + priv->last_dt_core_clk = info->last_dt_core_clk; + + for (i = 0; i < nclks; i++) + clks[i] = ERR_PTR(-ENOENT); + + for (i = 0; i < info->num_core_clks; i++) + cpg_mssr_register_core_clk(&info->core_clks[i], info, priv); + + for (i = 0; i < info->num_mod_clks; i++) + cpg_mssr_register_mod_clk(&info->mod_clks[i], info, priv); + + error = of_clk_add_provider(np, cpg_mssr_clk_src_twocell_get, priv); + if (error) + return error; + + devm_add_action(dev, cpg_mssr_del_clk_provider, np); + + error = cpg_mssr_add_clk_domain(dev, info->core_pm_clks, + info->num_core_pm_clks); + if (error) + return error; + + return 0; +} + +static struct platform_driver cpg_mssr_driver = { + .driver = { + .name = "renesas-cpg-mssr", + .of_match_table = cpg_mssr_match, + }, +}; + +static int __init cpg_mssr_init(void) +{ + return platform_driver_probe(&cpg_mssr_driver, cpg_mssr_probe); +} + +subsys_initcall(cpg_mssr_init); + +MODULE_DESCRIPTION("Renesas CPG/MSSR Driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/clk/shmobile/renesas-cpg-mssr.h b/drivers/clk/shmobile/renesas-cpg-mssr.h new file mode 100644 index 000000000000..e09f03cbf086 --- /dev/null +++ b/drivers/clk/shmobile/renesas-cpg-mssr.h @@ -0,0 +1,132 @@ +/* + * Renesas Clock Pulse Generator / Module Standby and Software Reset + * + * Copyright (C) 2015 Glider bvba + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + */ + +#ifndef __CLK_RENESAS_CPG_MSSR_H__ +#define __CLK_RENESAS_CPG_MSSR_H__ + + /* + * Definitions of CPG Core Clocks + * + * These include: + * - Clock outputs exported to DT + * - External input clocks + * - Internal CPG clocks + */ + +struct cpg_core_clk { + /* Common */ + const char *name; + unsigned int id; + unsigned int type; + /* Depending on type */ + unsigned int parent; /* Core Clocks only */ + unsigned int div; + unsigned int mult; + unsigned int offset; +}; + +enum clk_types { + /* Generic */ + CLK_TYPE_IN, /* External Clock Input */ + CLK_TYPE_FF, /* Fixed Factor Clock */ + CLK_TYPE_DIV6P1, /* DIV6 Clock with 1 parent clock */ + + /* Custom definitions start here */ + CLK_TYPE_CUSTOM, +}; + +#define DEF_TYPE(_name, _id, _type...) \ + { .name = _name, .id = _id, .type = _type } +#define DEF_BASE(_name, _id, _type, _parent...) \ + DEF_TYPE(_name, _id, _type, .parent = _parent) + +#define DEF_INPUT(_name, _id) \ + DEF_TYPE(_name, _id, CLK_TYPE_IN) +#define DEF_FIXED(_name, _id, _parent, _div, _mult) \ + DEF_BASE(_name, _id, CLK_TYPE_FF, _parent, .div = _div, .mult = _mult) +#define DEF_DIV6P1(_name, _id, _parent, _offset) \ + DEF_BASE(_name, _id, CLK_TYPE_DIV6P1, _parent, .offset = _offset) + + + /* + * Definitions of Module Clocks + */ + +struct mssr_mod_clk { + const char *name; + unsigned int id; + unsigned int parent; /* Add MOD_CLK_BASE for Module Clocks */ +}; + +/* Convert from sparse base-100 to packed index space */ +#define MOD_CLK_PACK(x) ((x) - ((x) / 100) * (100 - 32)) + +#define MOD_CLK_ID(x) (MOD_CLK_BASE + MOD_CLK_PACK(x)) + +#define DEF_MOD(_name, _mod, _parent...) \ + { .name = _name, .id = MOD_CLK_ID(_mod), .parent = _parent } + + +struct device_node; + + /** + * SoC-specific CPG/MSSR Description + * + * @core_clks: Array of Core Clock definitions + * @num_core_clks: Number of entries in core_clks[] + * @last_dt_core_clk: ID of the last Core Clock exported to DT + * @num_total_core_clks: Total number of Core Clocks (exported + internal) + * + * @mod_clks: Array of Module Clock definitions + * @num_mod_clks: Number of entries in mod_clks[] + * @num_hw_mod_clks: Number of Module Clocks supported by the hardware + * + * @crit_mod_clks: Array with Module Clock IDs of critical clocks that + * should not be disabled without a knowledgeable driver + * @num_crit_mod_clks: Number of entries in crit_mod_clks[] + * + * @core_pm_clks: Array with IDs of Core Clocks that are suitable for Power + * Management, in addition to Module Clocks + * @num_core_pm_clks: Number of entries in core_pm_clks[] + * + * @init: Optional callback to perform SoC-specific initialization + * @cpg_clk_register: Optional callback to handle special Core Clock types + */ + +struct cpg_mssr_info { + /* Core Clocks */ + const struct cpg_core_clk *core_clks; + unsigned int num_core_clks; + unsigned int last_dt_core_clk; + unsigned int num_total_core_clks; + + /* Module Clocks */ + const struct mssr_mod_clk *mod_clks; + unsigned int num_mod_clks; + unsigned int num_hw_mod_clks; + + /* Critical Module Clocks that should not be disabled */ + const unsigned int *crit_mod_clks; + unsigned int num_crit_mod_clks; + + /* Core Clocks suitable for PM, in addition to the Module Clocks */ + const unsigned int *core_pm_clks; + unsigned int num_core_pm_clks; + + /* Callbacks */ + int (*init)(struct device *dev); + struct clk *(*cpg_clk_register)(struct device *dev, + const struct cpg_core_clk *core, + const struct cpg_mssr_info *info, + struct clk **clks, void __iomem *base); +}; + +extern const struct cpg_mssr_info r8a7795_cpg_mssr_info; +#endif diff --git a/drivers/clk/st/clkgen-fsyn.c b/drivers/clk/st/clkgen-fsyn.c index 576cd0354d48..ccb324d97160 100644 --- a/drivers/clk/st/clkgen-fsyn.c +++ b/drivers/clk/st/clkgen-fsyn.c @@ -549,19 +549,20 @@ static int clk_fs660c32_vco_get_params(unsigned long input, return 0; } -static long quadfs_pll_fs660c32_round_rate(struct clk_hw *hw, unsigned long rate - , unsigned long *prate) +static long quadfs_pll_fs660c32_round_rate(struct clk_hw *hw, + unsigned long rate, + unsigned long *prate) { struct stm_fs params; - if (!clk_fs660c32_vco_get_params(*prate, rate, ¶ms)) - clk_fs660c32_vco_get_rate(*prate, ¶ms, &rate); + if (clk_fs660c32_vco_get_params(*prate, rate, ¶ms)) + return rate; - pr_debug("%s: %s new rate %ld [sdiv=0x%x,md=0x%x,pe=0x%x,nsdiv3=%u]\n", + clk_fs660c32_vco_get_rate(*prate, ¶ms, &rate); + + pr_debug("%s: %s new rate %ld [ndiv=%u]\n", __func__, clk_hw_get_name(hw), - rate, (unsigned int)params.sdiv, - (unsigned int)params.mdiv, - (unsigned int)params.pe, (unsigned int)params.nsdiv); + rate, (unsigned int)params.ndiv); return rate; } diff --git a/drivers/clk/ti/apll.c b/drivers/clk/ti/apll.c index f3eab6e79027..b336a8c11e2a 100644 --- a/drivers/clk/ti/apll.c +++ b/drivers/clk/ti/apll.c @@ -323,7 +323,7 @@ static void omap2_apll_deny_idle(struct clk_hw_omap *clk) omap2_apll_set_autoidle(clk, OMAP2_APLL_AUTOIDLE_DISABLE); } -static struct clk_hw_omap_ops omap2_apll_hwops = { +static const struct clk_hw_omap_ops omap2_apll_hwops = { .allow_idle = &omap2_apll_allow_idle, .deny_idle = &omap2_apll_deny_idle, }; diff --git a/drivers/clk/ti/dpll3xxx.c b/drivers/clk/ti/dpll3xxx.c index f4dec00fb684..1c300388782b 100644 --- a/drivers/clk/ti/dpll3xxx.c +++ b/drivers/clk/ti/dpll3xxx.c @@ -305,8 +305,9 @@ static void _lookup_sddiv(struct clk_hw_omap *clk, u8 *sd_div, u16 m, u8 n) static int omap3_noncore_dpll_program(struct clk_hw_omap *clk, u16 freqsel) { struct dpll_data *dd = clk->dpll_data; - u8 dco, sd_div; + u8 dco, sd_div, ai = 0; u32 v; + bool errata_i810; /* 3430 ES2 TRM: 4.7.6.9 DPLL Programming Sequence */ _omap3_noncore_dpll_bypass(clk); @@ -350,6 +351,25 @@ static int omap3_noncore_dpll_program(struct clk_hw_omap *clk, u16 freqsel) v |= sd_div << __ffs(dd->sddiv_mask); } + /* + * Errata i810 - DPLL controller can get stuck while transitioning + * to a power saving state. Software must ensure the DPLL can not + * transition to a low power state while changing M/N values. + * Easiest way to accomplish this is to prevent DPLL autoidle + * before doing the M/N re-program. + */ + errata_i810 = ti_clk_get_features()->flags & TI_CLK_ERRATA_I810; + + if (errata_i810) { + ai = omap3_dpll_autoidle_read(clk); + if (ai) { + omap3_dpll_deny_idle(clk); + + /* OCP barrier */ + omap3_dpll_autoidle_read(clk); + } + } + ti_clk_ll_ops->clk_writel(v, dd->mult_div1_reg); /* Set 4X multiplier and low-power mode */ @@ -379,6 +399,9 @@ static int omap3_noncore_dpll_program(struct clk_hw_omap *clk, u16 freqsel) _omap3_noncore_dpll_lock(clk); + if (errata_i810 && ai) + omap3_dpll_allow_idle(clk); + return 0; } diff --git a/drivers/clk/versatile/clk-sp810.c b/drivers/clk/versatile/clk-sp810.c index a1cdef6b0f90..e78755e0ef78 100644 --- a/drivers/clk/versatile/clk-sp810.c +++ b/drivers/clk/versatile/clk-sp810.c @@ -95,13 +95,12 @@ static void __init clk_sp810_of_setup(struct device_node *node) int i; bool deprecated; - if (!sp810) { - pr_err("Failed to allocate memory for SP810!\n"); + if (!sp810) return; - } if (of_clk_parent_fill(node, parent_names, num) != num) { pr_warn("Failed to obtain parent clocks for SP810!\n"); + kfree(sp810); return; } |