diff options
Diffstat (limited to 'drivers/clk')
73 files changed, 3152 insertions, 1188 deletions
diff --git a/drivers/clk/bcm/clk-iproc-pll.c b/drivers/clk/bcm/clk-iproc-pll.c index e04634c46395..2d61893da024 100644 --- a/drivers/clk/bcm/clk-iproc-pll.c +++ b/drivers/clk/bcm/clk-iproc-pll.c @@ -277,7 +277,7 @@ static int pll_set_rate(struct iproc_clk *clk, unsigned int rate_index, if (rate >= VCO_LOW && rate < VCO_HIGH) { ki = 4; kp_index = KP_BAND_MID; - } else if (rate >= VCO_HIGH && rate && rate < VCO_HIGH_HIGH) { + } else if (rate >= VCO_HIGH && rate < VCO_HIGH_HIGH) { ki = 3; kp_index = KP_BAND_HIGH; } else if (rate >= VCO_HIGH_HIGH && rate < VCO_MAX) { diff --git a/drivers/clk/clk-cs2000-cp.c b/drivers/clk/clk-cs2000-cp.c index 3fca0526d940..4df38c5ff96c 100644 --- a/drivers/clk/clk-cs2000-cp.c +++ b/drivers/clk/clk-cs2000-cp.c @@ -36,15 +36,27 @@ /* DEVICE_CTRL */ #define PLL_UNLOCK (1 << 7) +#define AUXOUTDIS (1 << 1) +#define CLKOUTDIS (1 << 0) /* DEVICE_CFG1 */ #define RSEL(x) (((x) & 0x3) << 3) #define RSEL_MASK RSEL(0x3) #define ENDEV1 (0x1) +/* DEVICE_CFG2 */ +#define AUTORMOD (1 << 3) +#define LOCKCLK(x) (((x) & 0x3) << 1) +#define LOCKCLK_MASK LOCKCLK(0x3) +#define FRACNSRC (1 << 0) + /* GLOBAL_CFG */ #define ENDEV2 (0x1) +/* FUNC_CFG1 */ +#define REFCLKDIV(x) (((x) & 0x3) << 3) +#define REFCLKDIV_MASK REFCLKDIV(0x3) + #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) @@ -127,7 +139,9 @@ static int cs2000_clk_in_bound_rate(struct cs2000_priv *priv, else return -EINVAL; - return cs2000_bset(priv, FUNC_CFG1, 0x3 << 3, val << 3); + return cs2000_bset(priv, FUNC_CFG1, + REFCLKDIV_MASK, + REFCLKDIV(val)); } static int cs2000_wait_pll_lock(struct cs2000_priv *priv) @@ -153,7 +167,10 @@ static int cs2000_wait_pll_lock(struct cs2000_priv *priv) 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); + return cs2000_bset(priv, DEVICE_CTRL, + (AUXOUTDIS | CLKOUTDIS), + enable ? 0 : + (AUXOUTDIS | CLKOUTDIS)); } static u32 cs2000_rate_to_ratio(u32 rate_in, u32 rate_out) @@ -243,7 +260,9 @@ static int cs2000_ratio_select(struct cs2000_priv *priv, int ch) if (ret < 0) return ret; - ret = cs2000_write(priv, DEVICE_CFG2, 0x0); + ret = cs2000_bset(priv, DEVICE_CFG2, + (AUTORMOD | LOCKCLK_MASK | FRACNSRC), + 0); if (ret < 0) return ret; @@ -351,8 +370,7 @@ static const struct clk_ops cs2000_ops = { static int cs2000_clk_get(struct cs2000_priv *priv) { - struct i2c_client *client = priv_to_client(priv); - struct device *dev = &client->dev; + struct device *dev = priv_to_dev(priv); struct clk *clk_in, *ref_clk; clk_in = devm_clk_get(dev, "clk_in"); @@ -420,8 +438,7 @@ static int cs2000_clk_register(struct cs2000_priv *priv) static int cs2000_version_print(struct cs2000_priv *priv) { - struct i2c_client *client = priv_to_client(priv); - struct device *dev = &client->dev; + struct device *dev = priv_to_dev(priv); s32 val; const char *revision; @@ -452,7 +469,7 @@ static int cs2000_version_print(struct cs2000_priv *priv) static int cs2000_remove(struct i2c_client *client) { struct cs2000_priv *priv = i2c_get_clientdata(client); - struct device *dev = &client->dev; + struct device *dev = priv_to_dev(priv); struct device_node *np = dev->of_node; of_clk_del_provider(np); diff --git a/drivers/clk/clk-stm32f4.c b/drivers/clk/clk-stm32f4.c index ab609a76706f..68e2a4e499f1 100644 --- a/drivers/clk/clk-stm32f4.c +++ b/drivers/clk/clk-stm32f4.c @@ -429,6 +429,13 @@ static const struct clk_div_table pll_divp_table[] = { { 0, 2 }, { 1, 4 }, { 2, 6 }, { 3, 8 }, { 0 } }; +static const struct clk_div_table pll_divq_table[] = { + { 2, 2 }, { 3, 3 }, { 4, 4 }, { 5, 5 }, { 6, 6 }, { 7, 7 }, + { 8, 8 }, { 9, 9 }, { 10, 10 }, { 11, 11 }, { 12, 12 }, { 13, 13 }, + { 14, 14 }, { 15, 15 }, + { 0 } +}; + static const struct clk_div_table pll_divr_table[] = { { 2, 2 }, { 3, 3 }, { 4, 4 }, { 5, 5 }, { 6, 6 }, { 7, 7 }, { 0 } }; @@ -496,9 +503,9 @@ struct stm32f4_div_data { #define MAX_PLL_DIV 3 static const struct stm32f4_div_data div_data[MAX_PLL_DIV] = { - { 16, 2, 0, pll_divp_table }, - { 24, 4, CLK_DIVIDER_ONE_BASED, NULL }, - { 28, 3, 0, pll_divr_table }, + { 16, 2, 0, pll_divp_table }, + { 24, 4, 0, pll_divq_table }, + { 28, 3, 0, pll_divr_table }, }; struct stm32f4_pll_data { @@ -524,19 +531,26 @@ static int stm32f4_pll_is_enabled(struct clk_hw *hw) return clk_gate_ops.is_enabled(hw); } +#define PLL_TIMEOUT 10000 + static int stm32f4_pll_enable(struct clk_hw *hw) { struct clk_gate *gate = to_clk_gate(hw); struct stm32f4_pll *pll = to_stm32f4_pll(gate); - int ret = 0; - unsigned long reg; + int bit_status; + unsigned int timeout = PLL_TIMEOUT; - ret = clk_gate_ops.enable(hw); + if (clk_gate_ops.is_enabled(hw)) + return 0; - ret = readl_relaxed_poll_timeout_atomic(base + STM32F4_RCC_CR, reg, - reg & (1 << pll->bit_rdy_idx), 0, 10000); + clk_gate_ops.enable(hw); - return ret; + do { + bit_status = !(readl(gate->reg) & BIT(pll->bit_rdy_idx)); + + } while (bit_status && --timeout); + + return bit_status; } static void stm32f4_pll_disable(struct clk_hw *hw) @@ -827,24 +841,32 @@ struct stm32_rgate { u8 bit_rdy_idx; }; -#define RTC_TIMEOUT 1000000 +#define RGATE_TIMEOUT 50000 static int rgclk_enable(struct clk_hw *hw) { struct clk_gate *gate = to_clk_gate(hw); struct stm32_rgate *rgate = to_rgclk(gate); - u32 reg; - int ret; + int bit_status; + unsigned int timeout = RGATE_TIMEOUT; + + if (clk_gate_ops.is_enabled(hw)) + return 0; disable_power_domain_write_protection(); clk_gate_ops.enable(hw); - ret = readl_relaxed_poll_timeout_atomic(gate->reg, reg, - reg & rgate->bit_rdy_idx, 1000, RTC_TIMEOUT); + do { + bit_status = !(readl(gate->reg) & BIT(rgate->bit_rdy_idx)); + if (bit_status) + udelay(100); + + } while (bit_status && --timeout); enable_power_domain_write_protection(); - return ret; + + return bit_status; } static void rgclk_disable(struct clk_hw *hw) @@ -1526,7 +1548,7 @@ static void __init stm32f4_rcc_init(struct device_node *np) } clks[CLK_LSI] = clk_register_rgate(NULL, "lsi", "clk-lsi", 0, - base + STM32F4_RCC_CSR, 0, 2, 0, &stm32f4_clk_lock); + base + STM32F4_RCC_CSR, 0, 1, 0, &stm32f4_clk_lock); if (IS_ERR(clks[CLK_LSI])) { pr_err("Unable to register lsi clock\n"); @@ -1534,7 +1556,7 @@ static void __init stm32f4_rcc_init(struct device_node *np) } clks[CLK_LSE] = clk_register_rgate(NULL, "lse", "clk-lse", 0, - base + STM32F4_RCC_BDCR, 0, 2, 0, &stm32f4_clk_lock); + base + STM32F4_RCC_BDCR, 0, 1, 0, &stm32f4_clk_lock); if (IS_ERR(clks[CLK_LSE])) { pr_err("Unable to register lse clock\n"); diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index 0fb39fe217d1..cddddbe46d9d 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -966,6 +966,8 @@ static int __clk_notify(struct clk_core *core, unsigned long msg, cnd.clk = cn->clk; ret = srcu_notifier_call_chain(&cn->notifier_head, msg, &cnd); + if (ret & NOTIFY_STOP_MASK) + return ret; } } @@ -2126,6 +2128,31 @@ static const struct file_operations clk_dump_fops = { .release = single_release, }; +static int possible_parents_dump(struct seq_file *s, void *data) +{ + struct clk_core *core = s->private; + int i; + + for (i = 0; i < core->num_parents - 1; i++) + seq_printf(s, "%s ", core->parent_names[i]); + + seq_printf(s, "%s\n", core->parent_names[i]); + + return 0; +} + +static int possible_parents_open(struct inode *inode, struct file *file) +{ + return single_open(file, possible_parents_dump, inode->i_private); +} + +static const struct file_operations possible_parents_fops = { + .open = possible_parents_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + static int clk_debug_create_one(struct clk_core *core, struct dentry *pdentry) { struct dentry *d; @@ -2177,6 +2204,13 @@ static int clk_debug_create_one(struct clk_core *core, struct dentry *pdentry) if (!d) goto err_out; + if (core->num_parents > 1) { + d = debugfs_create_file("clk_possible_parents", S_IRUGO, + core->dentry, core, &possible_parents_fops); + if (!d) + goto err_out; + } + if (core->ops->debug_init) { ret = core->ops->debug_init(core->hw, core->dentry); if (ret) @@ -2502,7 +2536,7 @@ struct clk *__clk_create_clk(struct clk_hw *hw, const char *dev_id, clk->core = hw->core; clk->dev_id = dev_id; - clk->con_id = con_id; + clk->con_id = kstrdup_const(con_id, GFP_KERNEL); clk->max_rate = ULONG_MAX; clk_prepare_lock(); @@ -2518,6 +2552,7 @@ void __clk_free_clk(struct clk *clk) hlist_del(&clk->clks_node); clk_prepare_unlock(); + kfree_const(clk->con_id); kfree(clk); } diff --git a/drivers/clk/hisilicon/clk-hi6220.c b/drivers/clk/hisilicon/clk-hi6220.c index c0e8e1f196aa..2ae151ce623a 100644 --- a/drivers/clk/hisilicon/clk-hi6220.c +++ b/drivers/clk/hisilicon/clk-hi6220.c @@ -134,6 +134,7 @@ static struct hisi_gate_clock hi6220_separated_gate_clks_sys[] __initdata = { { HI6220_UART4_PCLK, "uart4_pclk", "uart4_src", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x230, 8, 0, }, { HI6220_SPI_CLK, "spi_clk", "clk_150m", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x230, 9, 0, }, { HI6220_TSENSOR_CLK, "tsensor_clk", "clk_bus", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x230, 12, 0, }, + { HI6220_DAPB_CLK, "dapb_clk", "cs_dapb", CLK_SET_RATE_PARENT|CLK_IS_CRITICAL, 0x230, 18, 0, }, { HI6220_MMU_CLK, "mmu_clk", "ddrc_axi1", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x240, 11, 0, }, { HI6220_HIFI_SEL, "hifi_sel", "hifi_src", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x270, 0, 0, }, { HI6220_MMC0_SYSPLL, "mmc0_syspll", "syspll", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x270, 1, 0, }, diff --git a/drivers/clk/imx/clk-imx6ul.c b/drivers/clk/imx/clk-imx6ul.c index 75c35fb12b60..b4e0dff3c8c2 100644 --- a/drivers/clk/imx/clk-imx6ul.c +++ b/drivers/clk/imx/clk-imx6ul.c @@ -73,7 +73,7 @@ static struct clk *clks[IMX6UL_CLK_END]; static struct clk_onecell_data clk_data; static int const clks_init_on[] __initconst = { - IMX6UL_CLK_AIPSTZ1, IMX6UL_CLK_AIPSTZ2, IMX6UL_CLK_AIPSTZ3, + IMX6UL_CLK_AIPSTZ1, IMX6UL_CLK_AIPSTZ2, IMX6UL_CLK_AXI, IMX6UL_CLK_ARM, IMX6UL_CLK_ROM, IMX6UL_CLK_MMDC_P0_FAST, IMX6UL_CLK_MMDC_P0_IPG, }; @@ -341,9 +341,7 @@ static void __init imx6ul_clocks_init(struct device_node *ccm_node) clks[IMX6UL_CLK_GPT2_SERIAL] = imx_clk_gate2("gpt2_serial", "perclk", base + 0x68, 26); clks[IMX6UL_CLK_UART2_IPG] = imx_clk_gate2("uart2_ipg", "ipg", base + 0x68, 28); clks[IMX6UL_CLK_UART2_SERIAL] = imx_clk_gate2("uart2_serial", "uart_podf", base + 0x68, 28); - if (clk_on_imx6ul()) - clks[IMX6UL_CLK_AIPSTZ3] = imx_clk_gate2("aips_tz3", "ahb", base + 0x68, 30); - else if (clk_on_imx6ull()) + if (clk_on_imx6ull()) clks[IMX6UL_CLK_AIPSTZ3] = imx_clk_gate2("aips_tz3", "ahb", base + 0x80, 18); /* CCGR1 */ @@ -360,7 +358,7 @@ static void __init imx6ul_clocks_init(struct device_node *ccm_node) clks[IMX6UL_CLK_GPT1_BUS] = imx_clk_gate2("gpt1_bus", "perclk", base + 0x6c, 20); clks[IMX6UL_CLK_GPT1_SERIAL] = imx_clk_gate2("gpt1_serial", "perclk", base + 0x6c, 22); clks[IMX6UL_CLK_UART4_IPG] = imx_clk_gate2("uart4_ipg", "ipg", base + 0x6c, 24); - clks[IMX6UL_CLK_UART4_SERIAL] = imx_clk_gate2("uart4_serail", "uart_podf", base + 0x6c, 24); + clks[IMX6UL_CLK_UART4_SERIAL] = imx_clk_gate2("uart4_serial", "uart_podf", base + 0x6c, 24); /* CCGR2 */ if (clk_on_imx6ull()) { @@ -482,6 +480,9 @@ static void __init imx6ul_clocks_init(struct device_node *ccm_node) for (i = 0; i < ARRAY_SIZE(clks_init_on); i++) clk_prepare_enable(clks[clks_init_on[i]]); + if (clk_on_imx6ull()) + clk_prepare_enable(clks[IMX6UL_CLK_AIPSTZ3]); + if (IS_ENABLED(CONFIG_USB_MXS_PHY)) { clk_prepare_enable(clks[IMX6UL_CLK_USBPHY1_GATE]); clk_prepare_enable(clks[IMX6UL_CLK_USBPHY2_GATE]); diff --git a/drivers/clk/meson/Makefile b/drivers/clk/meson/Makefile index 349583405b7c..83b6d9d65aa1 100644 --- a/drivers/clk/meson/Makefile +++ b/drivers/clk/meson/Makefile @@ -2,6 +2,6 @@ # Makefile for Meson specific clk # -obj-$(CONFIG_COMMON_CLK_AMLOGIC) += clk-pll.o clk-cpu.o clk-mpll.o +obj-$(CONFIG_COMMON_CLK_AMLOGIC) += clk-pll.o clk-cpu.o clk-mpll.o clk-audio-divider.o obj-$(CONFIG_COMMON_CLK_MESON8B) += meson8b.o obj-$(CONFIG_COMMON_CLK_GXBB) += gxbb.o gxbb-aoclk.o diff --git a/drivers/clk/meson/clk-audio-divider.c b/drivers/clk/meson/clk-audio-divider.c new file mode 100644 index 000000000000..6c07db06642d --- /dev/null +++ b/drivers/clk/meson/clk-audio-divider.c @@ -0,0 +1,144 @@ +/* + * Copyright (c) 2017 AmLogic, Inc. + * Author: Jerome Brunet <jbrunet@baylibre.com> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope 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. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see <http://www.gnu.org/licenses/>. + */ + +/* + * i2s master clock divider: The algorithm of the generic clk-divider used with + * a very precise clock parent such as the mpll tends to select a low divider + * factor. This gives poor results with this particular divider, especially with + * high frequencies (> 100 MHz) + * + * This driver try to select the maximum possible divider with the rate the + * upstream clock can provide. + */ + +#include <linux/clk-provider.h> +#include "clkc.h" + +#define to_meson_clk_audio_divider(_hw) container_of(_hw, \ + struct meson_clk_audio_divider, hw) + +static int _div_round(unsigned long parent_rate, unsigned long rate, + unsigned long flags) +{ + if (flags & CLK_DIVIDER_ROUND_CLOSEST) + return DIV_ROUND_CLOSEST_ULL((u64)parent_rate, rate); + + return DIV_ROUND_UP_ULL((u64)parent_rate, rate); +} + +static int _get_val(unsigned long parent_rate, unsigned long rate) +{ + return DIV_ROUND_UP_ULL((u64)parent_rate, rate) - 1; +} + +static int _valid_divider(struct clk_hw *hw, int divider) +{ + struct meson_clk_audio_divider *adiv = + to_meson_clk_audio_divider(hw); + int max_divider; + u8 width; + + width = adiv->div.width; + max_divider = 1 << width; + + return clamp(divider, 1, max_divider); +} + +static unsigned long audio_divider_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + struct meson_clk_audio_divider *adiv = + to_meson_clk_audio_divider(hw); + struct parm *p; + unsigned long reg, divider; + + p = &adiv->div; + reg = readl(adiv->base + p->reg_off); + divider = PARM_GET(p->width, p->shift, reg) + 1; + + return DIV_ROUND_UP_ULL((u64)parent_rate, divider); +} + +static long audio_divider_round_rate(struct clk_hw *hw, + unsigned long rate, + unsigned long *parent_rate) +{ + struct meson_clk_audio_divider *adiv = + to_meson_clk_audio_divider(hw); + unsigned long max_prate; + int divider; + + if (!(clk_hw_get_flags(hw) & CLK_SET_RATE_PARENT)) { + divider = _div_round(*parent_rate, rate, adiv->flags); + divider = _valid_divider(hw, divider); + return DIV_ROUND_UP_ULL((u64)*parent_rate, divider); + } + + /* Get the maximum parent rate */ + max_prate = clk_hw_round_rate(clk_hw_get_parent(hw), ULONG_MAX); + + /* Get the corresponding rounded down divider */ + divider = max_prate / rate; + divider = _valid_divider(hw, divider); + + /* Get actual rate of the parent */ + *parent_rate = clk_hw_round_rate(clk_hw_get_parent(hw), + divider * rate); + + return DIV_ROUND_UP_ULL((u64)*parent_rate, divider); +} + +static int audio_divider_set_rate(struct clk_hw *hw, + unsigned long rate, + unsigned long parent_rate) +{ + struct meson_clk_audio_divider *adiv = + to_meson_clk_audio_divider(hw); + struct parm *p; + unsigned long reg, flags = 0; + int val; + + val = _get_val(parent_rate, rate); + + if (adiv->lock) + spin_lock_irqsave(adiv->lock, flags); + else + __acquire(adiv->lock); + + p = &adiv->div; + reg = readl(adiv->base + p->reg_off); + reg = PARM_SET(p->width, p->shift, reg, val); + writel(reg, adiv->base + p->reg_off); + + if (adiv->lock) + spin_unlock_irqrestore(adiv->lock, flags); + else + __release(adiv->lock); + + return 0; +} + +const struct clk_ops meson_clk_audio_divider_ro_ops = { + .recalc_rate = audio_divider_recalc_rate, + .round_rate = audio_divider_round_rate, +}; + +const struct clk_ops meson_clk_audio_divider_ops = { + .recalc_rate = audio_divider_recalc_rate, + .round_rate = audio_divider_round_rate, + .set_rate = audio_divider_set_rate, +}; diff --git a/drivers/clk/meson/clk-mpll.c b/drivers/clk/meson/clk-mpll.c index 03af79005ddb..39eab69fe51a 100644 --- a/drivers/clk/meson/clk-mpll.c +++ b/drivers/clk/meson/clk-mpll.c @@ -64,17 +64,51 @@ #include <linux/clk-provider.h> #include "clkc.h" -#define SDM_MAX 16384 +#define SDM_DEN 16384 +#define N2_MIN 4 +#define N2_MAX 511 #define to_meson_clk_mpll(_hw) container_of(_hw, struct meson_clk_mpll, hw) +static long rate_from_params(unsigned long parent_rate, + unsigned long sdm, + unsigned long n2) +{ + unsigned long divisor = (SDM_DEN * n2) + sdm; + + if (n2 < N2_MIN) + return -EINVAL; + + return DIV_ROUND_UP_ULL((u64)parent_rate * SDM_DEN, divisor); +} + +static void params_from_rate(unsigned long requested_rate, + unsigned long parent_rate, + unsigned long *sdm, + unsigned long *n2) +{ + uint64_t div = parent_rate; + unsigned long rem = do_div(div, requested_rate); + + if (div < N2_MIN) { + *n2 = N2_MIN; + *sdm = 0; + } else if (div > N2_MAX) { + *n2 = N2_MAX; + *sdm = SDM_DEN - 1; + } else { + *n2 = div; + *sdm = DIV_ROUND_UP(rem * SDM_DEN, requested_rate); + } +} + static unsigned long mpll_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) { struct meson_clk_mpll *mpll = to_meson_clk_mpll(hw); struct parm *p; - unsigned long rate = 0; unsigned long reg, sdm, n2; + long rate; p = &mpll->sdm; reg = readl(mpll->base + p->reg_off); @@ -84,11 +118,123 @@ static unsigned long mpll_recalc_rate(struct clk_hw *hw, reg = readl(mpll->base + p->reg_off); n2 = PARM_GET(p->width, p->shift, reg); - rate = (parent_rate * SDM_MAX) / ((SDM_MAX * n2) + sdm); + rate = rate_from_params(parent_rate, sdm, n2); + if (rate < 0) + return 0; return rate; } +static long mpll_round_rate(struct clk_hw *hw, + unsigned long rate, + unsigned long *parent_rate) +{ + unsigned long sdm, n2; + + params_from_rate(rate, *parent_rate, &sdm, &n2); + return rate_from_params(*parent_rate, sdm, n2); +} + +static int mpll_set_rate(struct clk_hw *hw, + unsigned long rate, + unsigned long parent_rate) +{ + struct meson_clk_mpll *mpll = to_meson_clk_mpll(hw); + struct parm *p; + unsigned long reg, sdm, n2; + unsigned long flags = 0; + + params_from_rate(rate, parent_rate, &sdm, &n2); + + if (mpll->lock) + spin_lock_irqsave(mpll->lock, flags); + else + __acquire(mpll->lock); + + p = &mpll->sdm; + reg = readl(mpll->base + p->reg_off); + reg = PARM_SET(p->width, p->shift, reg, sdm); + writel(reg, mpll->base + p->reg_off); + + p = &mpll->sdm_en; + reg = readl(mpll->base + p->reg_off); + reg = PARM_SET(p->width, p->shift, reg, 1); + writel(reg, mpll->base + p->reg_off); + + p = &mpll->n2; + reg = readl(mpll->base + p->reg_off); + reg = PARM_SET(p->width, p->shift, reg, n2); + writel(reg, mpll->base + p->reg_off); + + if (mpll->lock) + spin_unlock_irqrestore(mpll->lock, flags); + else + __release(mpll->lock); + + return 0; +} + +static void mpll_enable_core(struct clk_hw *hw, int enable) +{ + struct meson_clk_mpll *mpll = to_meson_clk_mpll(hw); + struct parm *p; + unsigned long reg; + unsigned long flags = 0; + + if (mpll->lock) + spin_lock_irqsave(mpll->lock, flags); + else + __acquire(mpll->lock); + + p = &mpll->en; + reg = readl(mpll->base + p->reg_off); + reg = PARM_SET(p->width, p->shift, reg, enable ? 1 : 0); + writel(reg, mpll->base + p->reg_off); + + if (mpll->lock) + spin_unlock_irqrestore(mpll->lock, flags); + else + __release(mpll->lock); +} + + +static int mpll_enable(struct clk_hw *hw) +{ + mpll_enable_core(hw, 1); + + return 0; +} + +static void mpll_disable(struct clk_hw *hw) +{ + mpll_enable_core(hw, 0); +} + +static int mpll_is_enabled(struct clk_hw *hw) +{ + struct meson_clk_mpll *mpll = to_meson_clk_mpll(hw); + struct parm *p; + unsigned long reg; + int en; + + p = &mpll->en; + reg = readl(mpll->base + p->reg_off); + en = PARM_GET(p->width, p->shift, reg); + + return en; +} + const struct clk_ops meson_clk_mpll_ro_ops = { - .recalc_rate = mpll_recalc_rate, + .recalc_rate = mpll_recalc_rate, + .round_rate = mpll_round_rate, + .is_enabled = mpll_is_enabled, +}; + +const struct clk_ops meson_clk_mpll_ops = { + .recalc_rate = mpll_recalc_rate, + .round_rate = mpll_round_rate, + .set_rate = mpll_set_rate, + .enable = mpll_enable, + .disable = mpll_disable, + .is_enabled = mpll_is_enabled, }; diff --git a/drivers/clk/meson/clk-pll.c b/drivers/clk/meson/clk-pll.c index 4adc1e89212c..01341553f50b 100644 --- a/drivers/clk/meson/clk-pll.c +++ b/drivers/clk/meson/clk-pll.c @@ -116,6 +116,30 @@ static const struct pll_rate_table *meson_clk_get_pll_settings(struct meson_clk_ return NULL; } +/* Specific wait loop for GXL/GXM GP0 PLL */ +static int meson_clk_pll_wait_lock_reset(struct meson_clk_pll *pll, + struct parm *p_n) +{ + int delay = 100; + u32 reg; + + while (delay > 0) { + reg = readl(pll->base + p_n->reg_off); + writel(reg | MESON_PLL_RESET, pll->base + p_n->reg_off); + udelay(10); + writel(reg & ~MESON_PLL_RESET, pll->base + p_n->reg_off); + + /* This delay comes from AMLogic tree clk-gp0-gxl driver */ + mdelay(1); + + reg = readl(pll->base + p_n->reg_off); + if (reg & MESON_PLL_LOCK) + return 0; + delay--; + } + return -ETIMEDOUT; +} + static int meson_clk_pll_wait_lock(struct meson_clk_pll *pll, struct parm *p_n) { @@ -132,6 +156,15 @@ static int meson_clk_pll_wait_lock(struct meson_clk_pll *pll, return -ETIMEDOUT; } +static void meson_clk_pll_init_params(struct meson_clk_pll *pll) +{ + int i; + + for (i = 0 ; i < pll->params.params_count ; ++i) + writel(pll->params.params_table[i].value, + pll->base + pll->params.params_table[i].reg_off); +} + static int meson_clk_pll_set_rate(struct clk_hw *hw, unsigned long rate, unsigned long parent_rate) { @@ -151,10 +184,16 @@ static int meson_clk_pll_set_rate(struct clk_hw *hw, unsigned long rate, if (!rate_set) return -EINVAL; + /* Initialize the PLL in a clean state if specified */ + if (pll->params.params_count) + meson_clk_pll_init_params(pll); + /* PLL reset */ p = &pll->n; reg = readl(pll->base + p->reg_off); - writel(reg | MESON_PLL_RESET, pll->base + p->reg_off); + /* If no_init_reset is provided, avoid resetting at this point */ + if (!pll->params.no_init_reset) + writel(reg | MESON_PLL_RESET, pll->base + p->reg_off); reg = PARM_SET(p->width, p->shift, reg, rate_set->n); writel(reg, pll->base + p->reg_off); @@ -184,7 +223,17 @@ static int meson_clk_pll_set_rate(struct clk_hw *hw, unsigned long rate, } p = &pll->n; - ret = meson_clk_pll_wait_lock(pll, p); + /* If clear_reset_for_lock is provided, remove the reset bit here */ + if (pll->params.clear_reset_for_lock) { + reg = readl(pll->base + p->reg_off); + writel(reg & ~MESON_PLL_RESET, pll->base + p->reg_off); + } + + /* If reset_lock_loop, use a special loop including resetting */ + if (pll->params.reset_lock_loop) + ret = meson_clk_pll_wait_lock_reset(pll, p); + else + ret = meson_clk_pll_wait_lock(pll, p); if (ret) { pr_warn("%s: pll did not lock, trying to restore old rate %lu\n", __func__, old_rate); diff --git a/drivers/clk/meson/clkc.h b/drivers/clk/meson/clkc.h index 9bb70e7a7d6a..d6feafe8bd6c 100644 --- a/drivers/clk/meson/clkc.h +++ b/drivers/clk/meson/clkc.h @@ -25,7 +25,7 @@ #define PARM_GET(width, shift, reg) \ (((reg) & SETPMASK(width, shift)) >> (shift)) #define PARM_SET(width, shift, reg, val) \ - (((reg) & CLRPMASK(width, shift)) | (val << (shift))) + (((reg) & CLRPMASK(width, shift)) | ((val) << (shift))) #define MESON_PARM_APPLICABLE(p) (!!((p)->width)) @@ -62,6 +62,28 @@ struct pll_rate_table { .frac = (_frac), \ } \ +struct pll_params_table { + unsigned int reg_off; + unsigned int value; +}; + +#define PLL_PARAM(_reg, _val) \ + { \ + .reg_off = (_reg), \ + .value = (_val), \ + } + +struct pll_setup_params { + struct pll_params_table *params_table; + unsigned int params_count; + /* Workaround for GP0, do not reset before configuring */ + bool no_init_reset; + /* Workaround for GP0, unreset right before checking for lock */ + bool clear_reset_for_lock; + /* Workaround for GXL GP0, reset in the lock checking loop */ + bool reset_lock_loop; +}; + struct meson_clk_pll { struct clk_hw hw; void __iomem *base; @@ -70,6 +92,7 @@ struct meson_clk_pll { struct parm frac; struct parm od; struct parm od2; + const struct pll_setup_params params; const struct pll_rate_table *rate_table; unsigned int rate_count; spinlock_t *lock; @@ -92,8 +115,17 @@ struct meson_clk_mpll { struct clk_hw hw; void __iomem *base; struct parm sdm; + struct parm sdm_en; struct parm n2; - /* FIXME ssen gate control? */ + struct parm en; + spinlock_t *lock; +}; + +struct meson_clk_audio_divider { + struct clk_hw hw; + void __iomem *base; + struct parm div; + u8 flags; spinlock_t *lock; }; @@ -116,5 +148,8 @@ extern const struct clk_ops meson_clk_pll_ro_ops; extern const struct clk_ops meson_clk_pll_ops; extern const struct clk_ops meson_clk_cpu_ops; extern const struct clk_ops meson_clk_mpll_ro_ops; +extern const struct clk_ops meson_clk_mpll_ops; +extern const struct clk_ops meson_clk_audio_divider_ro_ops; +extern const struct clk_ops meson_clk_audio_divider_ops; #endif /* __CLKC_H */ diff --git a/drivers/clk/meson/gxbb.c b/drivers/clk/meson/gxbb.c index 1c1ec137a3cc..ad5f027af1a2 100644 --- a/drivers/clk/meson/gxbb.c +++ b/drivers/clk/meson/gxbb.c @@ -20,6 +20,7 @@ #include <linux/clk.h> #include <linux/clk-provider.h> #include <linux/of_address.h> +#include <linux/of_device.h> #include <linux/platform_device.h> #include <linux/init.h> @@ -120,7 +121,7 @@ static const struct pll_rate_table sys_pll_rate_table[] = { { /* sentinel */ }, }; -static const struct pll_rate_table gp0_pll_rate_table[] = { +static const struct pll_rate_table gxbb_gp0_pll_rate_table[] = { PLL_RATE(96000000, 32, 1, 3), PLL_RATE(99000000, 33, 1, 3), PLL_RATE(102000000, 34, 1, 3), @@ -248,6 +249,35 @@ static const struct pll_rate_table gp0_pll_rate_table[] = { { /* sentinel */ }, }; +static const struct pll_rate_table gxl_gp0_pll_rate_table[] = { + PLL_RATE(504000000, 42, 1, 1), + PLL_RATE(516000000, 43, 1, 1), + PLL_RATE(528000000, 44, 1, 1), + PLL_RATE(540000000, 45, 1, 1), + PLL_RATE(552000000, 46, 1, 1), + PLL_RATE(564000000, 47, 1, 1), + PLL_RATE(576000000, 48, 1, 1), + PLL_RATE(588000000, 49, 1, 1), + PLL_RATE(600000000, 50, 1, 1), + PLL_RATE(612000000, 51, 1, 1), + PLL_RATE(624000000, 52, 1, 1), + PLL_RATE(636000000, 53, 1, 1), + PLL_RATE(648000000, 54, 1, 1), + PLL_RATE(660000000, 55, 1, 1), + PLL_RATE(672000000, 56, 1, 1), + PLL_RATE(684000000, 57, 1, 1), + PLL_RATE(696000000, 58, 1, 1), + PLL_RATE(708000000, 59, 1, 1), + PLL_RATE(720000000, 60, 1, 1), + PLL_RATE(732000000, 61, 1, 1), + PLL_RATE(744000000, 62, 1, 1), + PLL_RATE(756000000, 63, 1, 1), + PLL_RATE(768000000, 64, 1, 1), + PLL_RATE(780000000, 65, 1, 1), + PLL_RATE(792000000, 66, 1, 1), + { /* sentinel */ }, +}; + static const struct clk_div_table cpu_div_table[] = { { .val = 1, .div = 1 }, { .val = 2, .div = 2 }, @@ -352,6 +382,13 @@ static struct meson_clk_pll gxbb_sys_pll = { }, }; +struct pll_params_table gxbb_gp0_params_table[] = { + PLL_PARAM(HHI_GP0_PLL_CNTL, 0x6a000228), + PLL_PARAM(HHI_GP0_PLL_CNTL2, 0x69c80000), + PLL_PARAM(HHI_GP0_PLL_CNTL3, 0x0a5590c4), + PLL_PARAM(HHI_GP0_PLL_CNTL4, 0x0000500d), +}; + static struct meson_clk_pll gxbb_gp0_pll = { .m = { .reg_off = HHI_GP0_PLL_CNTL, @@ -368,8 +405,57 @@ static struct meson_clk_pll gxbb_gp0_pll = { .shift = 16, .width = 2, }, - .rate_table = gp0_pll_rate_table, - .rate_count = ARRAY_SIZE(gp0_pll_rate_table), + .params = { + .params_table = gxbb_gp0_params_table, + .params_count = ARRAY_SIZE(gxbb_gp0_params_table), + .no_init_reset = true, + .clear_reset_for_lock = true, + }, + .rate_table = gxbb_gp0_pll_rate_table, + .rate_count = ARRAY_SIZE(gxbb_gp0_pll_rate_table), + .lock = &clk_lock, + .hw.init = &(struct clk_init_data){ + .name = "gp0_pll", + .ops = &meson_clk_pll_ops, + .parent_names = (const char *[]){ "xtal" }, + .num_parents = 1, + .flags = CLK_GET_RATE_NOCACHE, + }, +}; + +struct pll_params_table gxl_gp0_params_table[] = { + PLL_PARAM(HHI_GP0_PLL_CNTL, 0x40010250), + PLL_PARAM(HHI_GP0_PLL_CNTL1, 0xc084a000), + PLL_PARAM(HHI_GP0_PLL_CNTL2, 0xb75020be), + PLL_PARAM(HHI_GP0_PLL_CNTL3, 0x0a59a288), + PLL_PARAM(HHI_GP0_PLL_CNTL4, 0xc000004d), + PLL_PARAM(HHI_GP0_PLL_CNTL5, 0x00078000), +}; + +static struct meson_clk_pll gxl_gp0_pll = { + .m = { + .reg_off = HHI_GP0_PLL_CNTL, + .shift = 0, + .width = 9, + }, + .n = { + .reg_off = HHI_GP0_PLL_CNTL, + .shift = 9, + .width = 5, + }, + .od = { + .reg_off = HHI_GP0_PLL_CNTL, + .shift = 16, + .width = 2, + }, + .params = { + .params_table = gxl_gp0_params_table, + .params_count = ARRAY_SIZE(gxl_gp0_params_table), + .no_init_reset = true, + .reset_lock_loop = true, + }, + .rate_table = gxl_gp0_pll_rate_table, + .rate_count = ARRAY_SIZE(gxl_gp0_pll_rate_table), .lock = &clk_lock, .hw.init = &(struct clk_init_data){ .name = "gp0_pll", @@ -441,15 +527,25 @@ static struct meson_clk_mpll gxbb_mpll0 = { .shift = 0, .width = 14, }, + .sdm_en = { + .reg_off = HHI_MPLL_CNTL7, + .shift = 15, + .width = 1, + }, .n2 = { .reg_off = HHI_MPLL_CNTL7, .shift = 16, .width = 9, }, + .en = { + .reg_off = HHI_MPLL_CNTL7, + .shift = 14, + .width = 1, + }, .lock = &clk_lock, .hw.init = &(struct clk_init_data){ .name = "mpll0", - .ops = &meson_clk_mpll_ro_ops, + .ops = &meson_clk_mpll_ops, .parent_names = (const char *[]){ "fixed_pll" }, .num_parents = 1, }, @@ -461,15 +557,25 @@ static struct meson_clk_mpll gxbb_mpll1 = { .shift = 0, .width = 14, }, + .sdm_en = { + .reg_off = HHI_MPLL_CNTL8, + .shift = 15, + .width = 1, + }, .n2 = { .reg_off = HHI_MPLL_CNTL8, .shift = 16, .width = 9, }, + .en = { + .reg_off = HHI_MPLL_CNTL8, + .shift = 14, + .width = 1, + }, .lock = &clk_lock, .hw.init = &(struct clk_init_data){ .name = "mpll1", - .ops = &meson_clk_mpll_ro_ops, + .ops = &meson_clk_mpll_ops, .parent_names = (const char *[]){ "fixed_pll" }, .num_parents = 1, }, @@ -481,15 +587,25 @@ static struct meson_clk_mpll gxbb_mpll2 = { .shift = 0, .width = 14, }, + .sdm_en = { + .reg_off = HHI_MPLL_CNTL9, + .shift = 15, + .width = 1, + }, .n2 = { .reg_off = HHI_MPLL_CNTL9, .shift = 16, .width = 9, }, + .en = { + .reg_off = HHI_MPLL_CNTL9, + .shift = 14, + .width = 1, + }, .lock = &clk_lock, .hw.init = &(struct clk_init_data){ .name = "mpll2", - .ops = &meson_clk_mpll_ro_ops, + .ops = &meson_clk_mpll_ops, .parent_names = (const char *[]){ "fixed_pll" }, .num_parents = 1, }, @@ -604,6 +720,237 @@ static struct clk_gate gxbb_sar_adc_clk = { }, }; +/* + * The MALI IP is clocked by two identical clocks (mali_0 and mali_1) + * muxed by a glitch-free switch. + */ + +static u32 mux_table_mali_0_1[] = {0, 1, 2, 3, 4, 5, 6, 7}; +static const char *gxbb_mali_0_1_parent_names[] = { + "xtal", "gp0_pll", "mpll2", "mpll1", "fclk_div7", + "fclk_div4", "fclk_div3", "fclk_div5" +}; + +static struct clk_mux gxbb_mali_0_sel = { + .reg = (void *)HHI_MALI_CLK_CNTL, + .mask = 0x7, + .shift = 9, + .table = mux_table_mali_0_1, + .lock = &clk_lock, + .hw.init = &(struct clk_init_data){ + .name = "mali_0_sel", + .ops = &clk_mux_ops, + /* + * bits 10:9 selects from 8 possible parents: + * xtal, gp0_pll, mpll2, mpll1, fclk_div7, + * fclk_div4, fclk_div3, fclk_div5 + */ + .parent_names = gxbb_mali_0_1_parent_names, + .num_parents = 8, + .flags = CLK_SET_RATE_NO_REPARENT, + }, +}; + +static struct clk_divider gxbb_mali_0_div = { + .reg = (void *)HHI_MALI_CLK_CNTL, + .shift = 0, + .width = 7, + .lock = &clk_lock, + .hw.init = &(struct clk_init_data){ + .name = "mali_0_div", + .ops = &clk_divider_ops, + .parent_names = (const char *[]){ "mali_0_sel" }, + .num_parents = 1, + .flags = CLK_SET_RATE_NO_REPARENT, + }, +}; + +static struct clk_gate gxbb_mali_0 = { + .reg = (void *)HHI_MALI_CLK_CNTL, + .bit_idx = 8, + .lock = &clk_lock, + .hw.init = &(struct clk_init_data){ + .name = "mali_0", + .ops = &clk_gate_ops, + .parent_names = (const char *[]){ "mali_0_div" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_mux gxbb_mali_1_sel = { + .reg = (void *)HHI_MALI_CLK_CNTL, + .mask = 0x7, + .shift = 25, + .table = mux_table_mali_0_1, + .lock = &clk_lock, + .hw.init = &(struct clk_init_data){ + .name = "mali_1_sel", + .ops = &clk_mux_ops, + /* + * bits 10:9 selects from 8 possible parents: + * xtal, gp0_pll, mpll2, mpll1, fclk_div7, + * fclk_div4, fclk_div3, fclk_div5 + */ + .parent_names = gxbb_mali_0_1_parent_names, + .num_parents = 8, + .flags = CLK_SET_RATE_NO_REPARENT, + }, +}; + +static struct clk_divider gxbb_mali_1_div = { + .reg = (void *)HHI_MALI_CLK_CNTL, + .shift = 16, + .width = 7, + .lock = &clk_lock, + .hw.init = &(struct clk_init_data){ + .name = "mali_1_div", + .ops = &clk_divider_ops, + .parent_names = (const char *[]){ "mali_1_sel" }, + .num_parents = 1, + .flags = CLK_SET_RATE_NO_REPARENT, + }, +}; + +static struct clk_gate gxbb_mali_1 = { + .reg = (void *)HHI_MALI_CLK_CNTL, + .bit_idx = 24, + .lock = &clk_lock, + .hw.init = &(struct clk_init_data){ + .name = "mali_1", + .ops = &clk_gate_ops, + .parent_names = (const char *[]){ "mali_1_div" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static u32 mux_table_mali[] = {0, 1}; +static const char *gxbb_mali_parent_names[] = { + "mali_0", "mali_1" +}; + +static struct clk_mux gxbb_mali = { + .reg = (void *)HHI_MALI_CLK_CNTL, + .mask = 1, + .shift = 31, + .table = mux_table_mali, + .lock = &clk_lock, + .hw.init = &(struct clk_init_data){ + .name = "mali", + .ops = &clk_mux_ops, + .parent_names = gxbb_mali_parent_names, + .num_parents = 2, + .flags = CLK_SET_RATE_NO_REPARENT, + }, +}; + +static struct clk_mux gxbb_cts_amclk_sel = { + .reg = (void *) HHI_AUD_CLK_CNTL, + .mask = 0x3, + .shift = 9, + /* Default parent unknown (register reset value: 0) */ + .table = (u32[]){ 1, 2, 3 }, + .lock = &clk_lock, + .hw.init = &(struct clk_init_data){ + .name = "cts_amclk_sel", + .ops = &clk_mux_ops, + .parent_names = (const char *[]){ "mpll0", "mpll1", "mpll2" }, + .num_parents = 3, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct meson_clk_audio_divider gxbb_cts_amclk_div = { + .div = { + .reg_off = HHI_AUD_CLK_CNTL, + .shift = 0, + .width = 8, + }, + .lock = &clk_lock, + .hw.init = &(struct clk_init_data){ + .name = "cts_amclk_div", + .ops = &meson_clk_audio_divider_ops, + .parent_names = (const char *[]){ "cts_amclk_sel" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT | CLK_DIVIDER_ROUND_CLOSEST, + }, +}; + +static struct clk_gate gxbb_cts_amclk = { + .reg = (void *) HHI_AUD_CLK_CNTL, + .bit_idx = 8, + .lock = &clk_lock, + .hw.init = &(struct clk_init_data){ + .name = "cts_amclk", + .ops = &clk_gate_ops, + .parent_names = (const char *[]){ "cts_amclk_div" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_mux gxbb_cts_mclk_i958_sel = { + .reg = (void *)HHI_AUD_CLK_CNTL2, + .mask = 0x3, + .shift = 25, + /* Default parent unknown (register reset value: 0) */ + .table = (u32[]){ 1, 2, 3 }, + .lock = &clk_lock, + .hw.init = &(struct clk_init_data){ + .name = "cts_mclk_i958_sel", + .ops = &clk_mux_ops, + .parent_names = (const char *[]){ "mpll0", "mpll1", "mpll2" }, + .num_parents = 3, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_divider gxbb_cts_mclk_i958_div = { + .reg = (void *)HHI_AUD_CLK_CNTL2, + .shift = 16, + .width = 8, + .lock = &clk_lock, + .hw.init = &(struct clk_init_data){ + .name = "cts_mclk_i958_div", + .ops = &clk_divider_ops, + .parent_names = (const char *[]){ "cts_mclk_i958_sel" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT | CLK_DIVIDER_ROUND_CLOSEST, + }, +}; + +static struct clk_gate gxbb_cts_mclk_i958 = { + .reg = (void *)HHI_AUD_CLK_CNTL2, + .bit_idx = 24, + .lock = &clk_lock, + .hw.init = &(struct clk_init_data){ + .name = "cts_mclk_i958", + .ops = &clk_gate_ops, + .parent_names = (const char *[]){ "cts_mclk_i958_div" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_mux gxbb_cts_i958 = { + .reg = (void *)HHI_AUD_CLK_CNTL2, + .mask = 0x1, + .shift = 27, + .lock = &clk_lock, + .hw.init = &(struct clk_init_data){ + .name = "cts_i958", + .ops = &clk_mux_ops, + .parent_names = (const char *[]){ "cts_amclk", "cts_mclk_i958" }, + .num_parents = 2, + /* + *The parent is specific to origin of the audio data. Let the + * consumer choose the appropriate parent + */ + .flags = CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT, + }, +}; + /* Everything Else (EE) domain gates */ static MESON_GATE(gxbb_ddr, HHI_GCLK_MPEG0, 0); static MESON_GATE(gxbb_dos, HHI_GCLK_MPEG0, 1); @@ -797,6 +1144,140 @@ static struct clk_hw_onecell_data gxbb_hw_onecell_data = { [CLKID_SAR_ADC_CLK] = &gxbb_sar_adc_clk.hw, [CLKID_SAR_ADC_SEL] = &gxbb_sar_adc_clk_sel.hw, [CLKID_SAR_ADC_DIV] = &gxbb_sar_adc_clk_div.hw, + [CLKID_MALI_0_SEL] = &gxbb_mali_0_sel.hw, + [CLKID_MALI_0_DIV] = &gxbb_mali_0_div.hw, + [CLKID_MALI_0] = &gxbb_mali_0.hw, + [CLKID_MALI_1_SEL] = &gxbb_mali_1_sel.hw, + [CLKID_MALI_1_DIV] = &gxbb_mali_1_div.hw, + [CLKID_MALI_1] = &gxbb_mali_1.hw, + [CLKID_MALI] = &gxbb_mali.hw, + [CLKID_CTS_AMCLK] = &gxbb_cts_amclk.hw, + [CLKID_CTS_AMCLK_SEL] = &gxbb_cts_amclk_sel.hw, + [CLKID_CTS_AMCLK_DIV] = &gxbb_cts_amclk_div.hw, + [CLKID_CTS_MCLK_I958] = &gxbb_cts_mclk_i958.hw, + [CLKID_CTS_MCLK_I958_SEL] = &gxbb_cts_mclk_i958_sel.hw, + [CLKID_CTS_MCLK_I958_DIV] = &gxbb_cts_mclk_i958_div.hw, + [CLKID_CTS_I958] = &gxbb_cts_i958.hw, + }, + .num = NR_CLKS, +}; + +static struct clk_hw_onecell_data gxl_hw_onecell_data = { + .hws = { + [CLKID_SYS_PLL] = &gxbb_sys_pll.hw, + [CLKID_CPUCLK] = &gxbb_cpu_clk.hw, + [CLKID_HDMI_PLL] = &gxbb_hdmi_pll.hw, + [CLKID_FIXED_PLL] = &gxbb_fixed_pll.hw, + [CLKID_FCLK_DIV2] = &gxbb_fclk_div2.hw, + [CLKID_FCLK_DIV3] = &gxbb_fclk_div3.hw, + [CLKID_FCLK_DIV4] = &gxbb_fclk_div4.hw, + [CLKID_FCLK_DIV5] = &gxbb_fclk_div5.hw, + [CLKID_FCLK_DIV7] = &gxbb_fclk_div7.hw, + [CLKID_GP0_PLL] = &gxl_gp0_pll.hw, + [CLKID_MPEG_SEL] = &gxbb_mpeg_clk_sel.hw, + [CLKID_MPEG_DIV] = &gxbb_mpeg_clk_div.hw, + [CLKID_CLK81] = &gxbb_clk81.hw, + [CLKID_MPLL0] = &gxbb_mpll0.hw, + [CLKID_MPLL1] = &gxbb_mpll1.hw, + [CLKID_MPLL2] = &gxbb_mpll2.hw, + [CLKID_DDR] = &gxbb_ddr.hw, + [CLKID_DOS] = &gxbb_dos.hw, + [CLKID_ISA] = &gxbb_isa.hw, + [CLKID_PL301] = &gxbb_pl301.hw, + [CLKID_PERIPHS] = &gxbb_periphs.hw, + [CLKID_SPICC] = &gxbb_spicc.hw, + [CLKID_I2C] = &gxbb_i2c.hw, + [CLKID_SAR_ADC] = &gxbb_sar_adc.hw, + [CLKID_SMART_CARD] = &gxbb_smart_card.hw, + [CLKID_RNG0] = &gxbb_rng0.hw, + [CLKID_UART0] = &gxbb_uart0.hw, + [CLKID_SDHC] = &gxbb_sdhc.hw, + [CLKID_STREAM] = &gxbb_stream.hw, + [CLKID_ASYNC_FIFO] = &gxbb_async_fifo.hw, + [CLKID_SDIO] = &gxbb_sdio.hw, + [CLKID_ABUF] = &gxbb_abuf.hw, + [CLKID_HIU_IFACE] = &gxbb_hiu_iface.hw, + [CLKID_ASSIST_MISC] = &gxbb_assist_misc.hw, + [CLKID_SPI] = &gxbb_spi.hw, + [CLKID_I2S_SPDIF] = &gxbb_i2s_spdif.hw, + [CLKID_ETH] = &gxbb_eth.hw, + [CLKID_DEMUX] = &gxbb_demux.hw, + [CLKID_AIU_GLUE] = &gxbb_aiu_glue.hw, + [CLKID_IEC958] = &gxbb_iec958.hw, + [CLKID_I2S_OUT] = &gxbb_i2s_out.hw, + [CLKID_AMCLK] = &gxbb_amclk.hw, + [CLKID_AIFIFO2] = &gxbb_aififo2.hw, + [CLKID_MIXER] = &gxbb_mixer.hw, + [CLKID_MIXER_IFACE] = &gxbb_mixer_iface.hw, + [CLKID_ADC] = &gxbb_adc.hw, + [CLKID_BLKMV] = &gxbb_blkmv.hw, + [CLKID_AIU] = &gxbb_aiu.hw, + [CLKID_UART1] = &gxbb_uart1.hw, + [CLKID_G2D] = &gxbb_g2d.hw, + [CLKID_USB0] = &gxbb_usb0.hw, + [CLKID_USB1] = &gxbb_usb1.hw, + [CLKID_RESET] = &gxbb_reset.hw, + [CLKID_NAND] = &gxbb_nand.hw, + [CLKID_DOS_PARSER] = &gxbb_dos_parser.hw, + [CLKID_USB] = &gxbb_usb.hw, + [CLKID_VDIN1] = &gxbb_vdin1.hw, + [CLKID_AHB_ARB0] = &gxbb_ahb_arb0.hw, + [CLKID_EFUSE] = &gxbb_efuse.hw, + [CLKID_BOOT_ROM] = &gxbb_boot_rom.hw, + [CLKID_AHB_DATA_BUS] = &gxbb_ahb_data_bus.hw, + [CLKID_AHB_CTRL_BUS] = &gxbb_ahb_ctrl_bus.hw, + [CLKID_HDMI_INTR_SYNC] = &gxbb_hdmi_intr_sync.hw, + [CLKID_HDMI_PCLK] = &gxbb_hdmi_pclk.hw, + [CLKID_USB1_DDR_BRIDGE] = &gxbb_usb1_ddr_bridge.hw, + [CLKID_USB0_DDR_BRIDGE] = &gxbb_usb0_ddr_bridge.hw, + [CLKID_MMC_PCLK] = &gxbb_mmc_pclk.hw, + [CLKID_DVIN] = &gxbb_dvin.hw, + [CLKID_UART2] = &gxbb_uart2.hw, + [CLKID_SANA] = &gxbb_sana.hw, + [CLKID_VPU_INTR] = &gxbb_vpu_intr.hw, + [CLKID_SEC_AHB_AHB3_BRIDGE] = &gxbb_sec_ahb_ahb3_bridge.hw, + [CLKID_CLK81_A53] = &gxbb_clk81_a53.hw, + [CLKID_VCLK2_VENCI0] = &gxbb_vclk2_venci0.hw, + [CLKID_VCLK2_VENCI1] = &gxbb_vclk2_venci1.hw, + [CLKID_VCLK2_VENCP0] = &gxbb_vclk2_vencp0.hw, + [CLKID_VCLK2_VENCP1] = &gxbb_vclk2_vencp1.hw, + [CLKID_GCLK_VENCI_INT0] = &gxbb_gclk_venci_int0.hw, + [CLKID_GCLK_VENCI_INT] = &gxbb_gclk_vencp_int.hw, + [CLKID_DAC_CLK] = &gxbb_dac_clk.hw, + [CLKID_AOCLK_GATE] = &gxbb_aoclk_gate.hw, + [CLKID_IEC958_GATE] = &gxbb_iec958_gate.hw, + [CLKID_ENC480P] = &gxbb_enc480p.hw, + [CLKID_RNG1] = &gxbb_rng1.hw, + [CLKID_GCLK_VENCI_INT1] = &gxbb_gclk_venci_int1.hw, + [CLKID_VCLK2_VENCLMCC] = &gxbb_vclk2_venclmcc.hw, + [CLKID_VCLK2_VENCL] = &gxbb_vclk2_vencl.hw, + [CLKID_VCLK_OTHER] = &gxbb_vclk_other.hw, + [CLKID_EDP] = &gxbb_edp.hw, + [CLKID_AO_MEDIA_CPU] = &gxbb_ao_media_cpu.hw, + [CLKID_AO_AHB_SRAM] = &gxbb_ao_ahb_sram.hw, + [CLKID_AO_AHB_BUS] = &gxbb_ao_ahb_bus.hw, + [CLKID_AO_IFACE] = &gxbb_ao_iface.hw, + [CLKID_AO_I2C] = &gxbb_ao_i2c.hw, + [CLKID_SD_EMMC_A] = &gxbb_emmc_a.hw, + [CLKID_SD_EMMC_B] = &gxbb_emmc_b.hw, + [CLKID_SD_EMMC_C] = &gxbb_emmc_c.hw, + [CLKID_SAR_ADC_CLK] = &gxbb_sar_adc_clk.hw, + [CLKID_SAR_ADC_SEL] = &gxbb_sar_adc_clk_sel.hw, + [CLKID_SAR_ADC_DIV] = &gxbb_sar_adc_clk_div.hw, + [CLKID_MALI_0_SEL] = &gxbb_mali_0_sel.hw, + [CLKID_MALI_0_DIV] = &gxbb_mali_0_div.hw, + [CLKID_MALI_0] = &gxbb_mali_0.hw, + [CLKID_MALI_1_SEL] = &gxbb_mali_1_sel.hw, + [CLKID_MALI_1_DIV] = &gxbb_mali_1_div.hw, + [CLKID_MALI_1] = &gxbb_mali_1.hw, + [CLKID_MALI] = &gxbb_mali.hw, + [CLKID_CTS_AMCLK] = &gxbb_cts_amclk.hw, + [CLKID_CTS_AMCLK_SEL] = &gxbb_cts_amclk_sel.hw, + [CLKID_CTS_AMCLK_DIV] = &gxbb_cts_amclk_div.hw, + [CLKID_CTS_MCLK_I958] = &gxbb_cts_mclk_i958.hw, + [CLKID_CTS_MCLK_I958_SEL] = &gxbb_cts_mclk_i958_sel.hw, + [CLKID_CTS_MCLK_I958_DIV] = &gxbb_cts_mclk_i958_div.hw, + [CLKID_CTS_I958] = &gxbb_cts_i958.hw, }, .num = NR_CLKS, }; @@ -810,13 +1291,20 @@ static struct meson_clk_pll *const gxbb_clk_plls[] = { &gxbb_gp0_pll, }; +static struct meson_clk_pll *const gxl_clk_plls[] = { + &gxbb_fixed_pll, + &gxbb_hdmi_pll, + &gxbb_sys_pll, + &gxl_gp0_pll, +}; + static struct meson_clk_mpll *const gxbb_clk_mplls[] = { &gxbb_mpll0, &gxbb_mpll1, &gxbb_mpll2, }; -static struct clk_gate *gxbb_clk_gates[] = { +static struct clk_gate *const gxbb_clk_gates[] = { &gxbb_clk81, &gxbb_ddr, &gxbb_dos, @@ -900,16 +1388,105 @@ static struct clk_gate *gxbb_clk_gates[] = { &gxbb_emmc_b, &gxbb_emmc_c, &gxbb_sar_adc_clk, + &gxbb_mali_0, + &gxbb_mali_1, + &gxbb_cts_amclk, + &gxbb_cts_mclk_i958, +}; + +static struct clk_mux *const gxbb_clk_muxes[] = { + &gxbb_mpeg_clk_sel, + &gxbb_sar_adc_clk_sel, + &gxbb_mali_0_sel, + &gxbb_mali_1_sel, + &gxbb_mali, + &gxbb_cts_amclk_sel, + &gxbb_cts_mclk_i958_sel, + &gxbb_cts_i958, +}; + +static struct clk_divider *const gxbb_clk_dividers[] = { + &gxbb_mpeg_clk_div, + &gxbb_sar_adc_clk_div, + &gxbb_mali_0_div, + &gxbb_mali_1_div, + &gxbb_cts_mclk_i958_div, +}; + +static struct meson_clk_audio_divider *const gxbb_audio_dividers[] = { + &gxbb_cts_amclk_div, +}; + +struct clkc_data { + struct clk_gate *const *clk_gates; + unsigned int clk_gates_count; + struct meson_clk_mpll *const *clk_mplls; + unsigned int clk_mplls_count; + struct meson_clk_pll *const *clk_plls; + unsigned int clk_plls_count; + struct clk_mux *const *clk_muxes; + unsigned int clk_muxes_count; + struct clk_divider *const *clk_dividers; + unsigned int clk_dividers_count; + struct meson_clk_audio_divider *const *clk_audio_dividers; + unsigned int clk_audio_dividers_count; + struct meson_clk_cpu *cpu_clk; + struct clk_hw_onecell_data *hw_onecell_data; +}; + +static const struct clkc_data gxbb_clkc_data = { + .clk_gates = gxbb_clk_gates, + .clk_gates_count = ARRAY_SIZE(gxbb_clk_gates), + .clk_mplls = gxbb_clk_mplls, + .clk_mplls_count = ARRAY_SIZE(gxbb_clk_mplls), + .clk_plls = gxbb_clk_plls, + .clk_plls_count = ARRAY_SIZE(gxbb_clk_plls), + .clk_muxes = gxbb_clk_muxes, + .clk_muxes_count = ARRAY_SIZE(gxbb_clk_muxes), + .clk_dividers = gxbb_clk_dividers, + .clk_dividers_count = ARRAY_SIZE(gxbb_clk_dividers), + .clk_audio_dividers = gxbb_audio_dividers, + .clk_audio_dividers_count = ARRAY_SIZE(gxbb_audio_dividers), + .cpu_clk = &gxbb_cpu_clk, + .hw_onecell_data = &gxbb_hw_onecell_data, +}; + +static const struct clkc_data gxl_clkc_data = { + .clk_gates = gxbb_clk_gates, + .clk_gates_count = ARRAY_SIZE(gxbb_clk_gates), + .clk_mplls = gxbb_clk_mplls, + .clk_mplls_count = ARRAY_SIZE(gxbb_clk_mplls), + .clk_plls = gxl_clk_plls, + .clk_plls_count = ARRAY_SIZE(gxl_clk_plls), + .clk_muxes = gxbb_clk_muxes, + .clk_muxes_count = ARRAY_SIZE(gxbb_clk_muxes), + .clk_dividers = gxbb_clk_dividers, + .clk_dividers_count = ARRAY_SIZE(gxbb_clk_dividers), + .clk_audio_dividers = gxbb_audio_dividers, + .clk_audio_dividers_count = ARRAY_SIZE(gxbb_audio_dividers), + .cpu_clk = &gxbb_cpu_clk, + .hw_onecell_data = &gxl_hw_onecell_data, +}; + +static const struct of_device_id clkc_match_table[] = { + { .compatible = "amlogic,gxbb-clkc", .data = &gxbb_clkc_data }, + { .compatible = "amlogic,gxl-clkc", .data = &gxl_clkc_data }, + {}, }; static int gxbb_clkc_probe(struct platform_device *pdev) { + const struct clkc_data *clkc_data; void __iomem *clk_base; int ret, clkid, i; struct clk_hw *parent_hw; struct clk *parent_clk; struct device *dev = &pdev->dev; + clkc_data = of_device_get_match_data(&pdev->dev); + if (!clkc_data) + return -EINVAL; + /* Generic clocks and PLLs */ clk_base = of_iomap(dev->of_node, 0); if (!clk_base) { @@ -918,34 +1495,45 @@ static int gxbb_clkc_probe(struct platform_device *pdev) } /* Populate base address for PLLs */ - for (i = 0; i < ARRAY_SIZE(gxbb_clk_plls); i++) - gxbb_clk_plls[i]->base = clk_base; + for (i = 0; i < clkc_data->clk_plls_count; i++) + clkc_data->clk_plls[i]->base = clk_base; /* Populate base address for MPLLs */ - for (i = 0; i < ARRAY_SIZE(gxbb_clk_mplls); i++) - gxbb_clk_mplls[i]->base = clk_base; + for (i = 0; i < clkc_data->clk_mplls_count; i++) + clkc_data->clk_mplls[i]->base = clk_base; /* Populate the base address for CPU clk */ - gxbb_cpu_clk.base = clk_base; + clkc_data->cpu_clk->base = clk_base; + + /* Populate base address for gates */ + for (i = 0; i < clkc_data->clk_gates_count; i++) + clkc_data->clk_gates[i]->reg = clk_base + + (u64)clkc_data->clk_gates[i]->reg; - /* Populate the base address for the MPEG clks */ - gxbb_mpeg_clk_sel.reg = clk_base + (u64)gxbb_mpeg_clk_sel.reg; - gxbb_mpeg_clk_div.reg = clk_base + (u64)gxbb_mpeg_clk_div.reg; + /* Populate base address for muxes */ + for (i = 0; i < clkc_data->clk_muxes_count; i++) + clkc_data->clk_muxes[i]->reg = clk_base + + (u64)clkc_data->clk_muxes[i]->reg; - /* Populate the base address for the SAR ADC clks */ - gxbb_sar_adc_clk_sel.reg = clk_base + (u64)gxbb_sar_adc_clk_sel.reg; - gxbb_sar_adc_clk_div.reg = clk_base + (u64)gxbb_sar_adc_clk_div.reg; + /* Populate base address for dividers */ + for (i = 0; i < clkc_data->clk_dividers_count; i++) + clkc_data->clk_dividers[i]->reg = clk_base + + (u64)clkc_data->clk_dividers[i]->reg; - /* Populate base address for gates */ - for (i = 0; i < ARRAY_SIZE(gxbb_clk_gates); i++) - gxbb_clk_gates[i]->reg = clk_base + - (u64)gxbb_clk_gates[i]->reg; + /* Populate base address for the audio dividers */ + for (i = 0; i < clkc_data->clk_audio_dividers_count; i++) + clkc_data->clk_audio_dividers[i]->base = clk_base; /* * register all clks */ - for (clkid = 0; clkid < NR_CLKS; clkid++) { - ret = devm_clk_hw_register(dev, gxbb_hw_onecell_data.hws[clkid]); + for (clkid = 0; clkid < clkc_data->hw_onecell_data->num; clkid++) { + /* array might be sparse */ + if (!clkc_data->hw_onecell_data->hws[clkid]) + continue; + + ret = devm_clk_hw_register(dev, + clkc_data->hw_onecell_data->hws[clkid]); if (ret) goto iounmap; } @@ -964,9 +1552,9 @@ static int gxbb_clkc_probe(struct platform_device *pdev) * a new clk_hw, and this hack will no longer work. Releasing the ccr * feature before that time solves the problem :-) */ - parent_hw = clk_hw_get_parent(&gxbb_cpu_clk.hw); + parent_hw = clk_hw_get_parent(&clkc_data->cpu_clk->hw); parent_clk = parent_hw->clk; - ret = clk_notifier_register(parent_clk, &gxbb_cpu_clk.clk_nb); + ret = clk_notifier_register(parent_clk, &clkc_data->cpu_clk->clk_nb); if (ret) { pr_err("%s: failed to register clock notifier for cpu_clk\n", __func__); @@ -974,23 +1562,18 @@ static int gxbb_clkc_probe(struct platform_device *pdev) } return of_clk_add_hw_provider(dev->of_node, of_clk_hw_onecell_get, - &gxbb_hw_onecell_data); + clkc_data->hw_onecell_data); iounmap: iounmap(clk_base); return ret; } -static const struct of_device_id gxbb_clkc_match_table[] = { - { .compatible = "amlogic,gxbb-clkc" }, - { } -}; - static struct platform_driver gxbb_driver = { .probe = gxbb_clkc_probe, .driver = { .name = "gxbb-clkc", - .of_match_table = gxbb_clkc_match_table, + .of_match_table = clkc_match_table, }, }; diff --git a/drivers/clk/meson/gxbb.h b/drivers/clk/meson/gxbb.h index 8ee2022ce5d5..1d8d13f5e813 100644 --- a/drivers/clk/meson/gxbb.h +++ b/drivers/clk/meson/gxbb.h @@ -71,6 +71,8 @@ #define HHI_GP0_PLL_CNTL2 0x44 /* 0x11 offset in data sheet */ #define HHI_GP0_PLL_CNTL3 0x48 /* 0x12 offset in data sheet */ #define HHI_GP0_PLL_CNTL4 0x4c /* 0x13 offset in data sheet */ +#define HHI_GP0_PLL_CNTL5 0x50 /* 0x14 offset in data sheet */ +#define HHI_GP0_PLL_CNTL1 0x58 /* 0x16 offset in data sheet */ #define HHI_XTAL_DIVN_CNTL 0xbc /* 0x2f offset in data sheet */ #define HHI_TIMER90K 0xec /* 0x3b offset in data sheet */ @@ -177,7 +179,7 @@ /* CLKID_FCLK_DIV4 */ #define CLKID_FCLK_DIV5 7 #define CLKID_FCLK_DIV7 8 -#define CLKID_GP0_PLL 9 +/* CLKID_GP0_PLL */ #define CLKID_MPEG_SEL 10 #define CLKID_MPEG_DIV 11 /* CLKID_CLK81 */ @@ -206,16 +208,16 @@ #define CLKID_I2S_SPDIF 35 /* CLKID_ETH */ #define CLKID_DEMUX 37 -#define CLKID_AIU_GLUE 38 +/* CLKID_AIU_GLUE */ #define CLKID_IEC958 39 -#define CLKID_I2S_OUT 40 +/* CLKID_I2S_OUT */ #define CLKID_AMCLK 41 #define CLKID_AIFIFO2 42 #define CLKID_MIXER 43 -#define CLKID_MIXER_IFACE 44 +/* CLKID_MIXER_IFACE */ #define CLKID_ADC 45 #define CLKID_BLKMV 46 -#define CLKID_AIU 47 +/* CLKID_AIU */ #define CLKID_UART1 48 #define CLKID_G2D 49 /* CLKID_USB0 */ @@ -248,7 +250,7 @@ /* CLKID_GCLK_VENCI_INT0 */ #define CLKID_GCLK_VENCI_INT 78 #define CLKID_DAC_CLK 79 -#define CLKID_AOCLK_GATE 80 +/* CLKID_AOCLK_GATE */ #define CLKID_IEC958_GATE 81 #define CLKID_ENC480P 82 #define CLKID_RNG1 83 @@ -268,8 +270,22 @@ /* CLKID_SAR_ADC_CLK */ /* CLKID_SAR_ADC_SEL */ #define CLKID_SAR_ADC_DIV 99 +/* CLKID_MALI_0_SEL */ +#define CLKID_MALI_0_DIV 101 +/* CLKID_MALI_0 */ +/* CLKID_MALI_1_SEL */ +#define CLKID_MALI_1_DIV 104 +/* CLKID_MALI_1 */ +/* CLKID_MALI */ +#define CLKID_CTS_AMCLK 107 +#define CLKID_CTS_AMCLK_SEL 108 +#define CLKID_CTS_AMCLK_DIV 109 +#define CLKID_CTS_MCLK_I958 110 +#define CLKID_CTS_MCLK_I958_SEL 111 +#define CLKID_CTS_MCLK_I958_DIV 112 +#define CLKID_CTS_I958 113 -#define NR_CLKS 100 +#define NR_CLKS 114 /* include the CLKIDs that have been made part of the stable DT binding */ #include <dt-bindings/clock/gxbb-clkc.h> diff --git a/drivers/clk/meson/meson8b.c b/drivers/clk/meson/meson8b.c index 888494d4fb8a..e9985503165c 100644 --- a/drivers/clk/meson/meson8b.c +++ b/drivers/clk/meson/meson8b.c @@ -245,6 +245,96 @@ static struct clk_fixed_factor meson8b_fclk_div7 = { }, }; +static struct meson_clk_mpll meson8b_mpll0 = { + .sdm = { + .reg_off = HHI_MPLL_CNTL7, + .shift = 0, + .width = 14, + }, + .sdm_en = { + .reg_off = HHI_MPLL_CNTL7, + .shift = 15, + .width = 1, + }, + .n2 = { + .reg_off = HHI_MPLL_CNTL7, + .shift = 16, + .width = 9, + }, + .en = { + .reg_off = HHI_MPLL_CNTL7, + .shift = 14, + .width = 1, + }, + .lock = &clk_lock, + .hw.init = &(struct clk_init_data){ + .name = "mpll0", + .ops = &meson_clk_mpll_ops, + .parent_names = (const char *[]){ "fixed_pll" }, + .num_parents = 1, + }, +}; + +static struct meson_clk_mpll meson8b_mpll1 = { + .sdm = { + .reg_off = HHI_MPLL_CNTL8, + .shift = 0, + .width = 14, + }, + .sdm_en = { + .reg_off = HHI_MPLL_CNTL8, + .shift = 15, + .width = 1, + }, + .n2 = { + .reg_off = HHI_MPLL_CNTL8, + .shift = 16, + .width = 9, + }, + .en = { + .reg_off = HHI_MPLL_CNTL8, + .shift = 14, + .width = 1, + }, + .lock = &clk_lock, + .hw.init = &(struct clk_init_data){ + .name = "mpll1", + .ops = &meson_clk_mpll_ops, + .parent_names = (const char *[]){ "fixed_pll" }, + .num_parents = 1, + }, +}; + +static struct meson_clk_mpll meson8b_mpll2 = { + .sdm = { + .reg_off = HHI_MPLL_CNTL9, + .shift = 0, + .width = 14, + }, + .sdm_en = { + .reg_off = HHI_MPLL_CNTL9, + .shift = 15, + .width = 1, + }, + .n2 = { + .reg_off = HHI_MPLL_CNTL9, + .shift = 16, + .width = 9, + }, + .en = { + .reg_off = HHI_MPLL_CNTL9, + .shift = 14, + .width = 1, + }, + .lock = &clk_lock, + .hw.init = &(struct clk_init_data){ + .name = "mpll2", + .ops = &meson_clk_mpll_ops, + .parent_names = (const char *[]){ "fixed_pll" }, + .num_parents = 1, + }, +}; + /* * FIXME cpu clocks and the legacy composite clocks (e.g. clk81) are both PLL * post-dividers and should be modeled with their respective PLLs via the @@ -491,6 +581,9 @@ static struct clk_hw_onecell_data meson8b_hw_onecell_data = { [CLKID_AO_AHB_SRAM] = &meson8b_ao_ahb_sram.hw, [CLKID_AO_AHB_BUS] = &meson8b_ao_ahb_bus.hw, [CLKID_AO_IFACE] = &meson8b_ao_iface.hw, + [CLKID_MPLL0] = &meson8b_mpll0.hw, + [CLKID_MPLL1] = &meson8b_mpll1.hw, + [CLKID_MPLL2] = &meson8b_mpll2.hw, }, .num = CLK_NR_CLKS, }; @@ -501,7 +594,13 @@ static struct meson_clk_pll *const meson8b_clk_plls[] = { &meson8b_sys_pll, }; -static struct clk_gate *meson8b_clk_gates[] = { +static struct meson_clk_mpll *const meson8b_clk_mplls[] = { + &meson8b_mpll0, + &meson8b_mpll1, + &meson8b_mpll2, +}; + +static struct clk_gate *const meson8b_clk_gates[] = { &meson8b_clk81, &meson8b_ddr, &meson8b_dos, @@ -582,6 +681,14 @@ static struct clk_gate *meson8b_clk_gates[] = { &meson8b_ao_iface, }; +static struct clk_mux *const meson8b_clk_muxes[] = { + &meson8b_mpeg_clk_sel, +}; + +static struct clk_divider *const meson8b_clk_dividers[] = { + &meson8b_mpeg_clk_div, +}; + static int meson8b_clkc_probe(struct platform_device *pdev) { void __iomem *clk_base; @@ -601,18 +708,28 @@ static int meson8b_clkc_probe(struct platform_device *pdev) for (i = 0; i < ARRAY_SIZE(meson8b_clk_plls); i++) meson8b_clk_plls[i]->base = clk_base; + /* Populate base address for MPLLs */ + for (i = 0; i < ARRAY_SIZE(meson8b_clk_mplls); i++) + meson8b_clk_mplls[i]->base = clk_base; + /* Populate the base address for CPU clk */ meson8b_cpu_clk.base = clk_base; - /* Populate the base address for the MPEG clks */ - meson8b_mpeg_clk_sel.reg = clk_base + (u32)meson8b_mpeg_clk_sel.reg; - meson8b_mpeg_clk_div.reg = clk_base + (u32)meson8b_mpeg_clk_div.reg; - /* Populate base address for gates */ for (i = 0; i < ARRAY_SIZE(meson8b_clk_gates); i++) meson8b_clk_gates[i]->reg = clk_base + (u32)meson8b_clk_gates[i]->reg; + /* Populate base address for muxes */ + for (i = 0; i < ARRAY_SIZE(meson8b_clk_muxes); i++) + meson8b_clk_muxes[i]->reg = clk_base + + (u32)meson8b_clk_muxes[i]->reg; + + /* Populate base address for dividers */ + for (i = 0; i < ARRAY_SIZE(meson8b_clk_dividers); i++) + meson8b_clk_dividers[i]->reg = clk_base + + (u32)meson8b_clk_dividers[i]->reg; + /* * register all clks * CLKID_UNUSED = 0, so skip it and start with CLKID_XTAL = 1 diff --git a/drivers/clk/meson/meson8b.h b/drivers/clk/meson/meson8b.h index 010e9582888d..3881defc8644 100644 --- a/drivers/clk/meson/meson8b.h +++ b/drivers/clk/meson/meson8b.h @@ -42,6 +42,21 @@ #define HHI_VID_PLL_CNTL 0x320 /* 0xc8 offset in data sheet */ /* + * MPLL register offeset taken from the S905 datasheet. Vendor kernel source + * confirm these are the same for the S805. + */ +#define HHI_MPLL_CNTL 0x280 /* 0xa0 offset in data sheet */ +#define HHI_MPLL_CNTL2 0x284 /* 0xa1 offset in data sheet */ +#define HHI_MPLL_CNTL3 0x288 /* 0xa2 offset in data sheet */ +#define HHI_MPLL_CNTL4 0x28C /* 0xa3 offset in data sheet */ +#define HHI_MPLL_CNTL5 0x290 /* 0xa4 offset in data sheet */ +#define HHI_MPLL_CNTL6 0x294 /* 0xa5 offset in data sheet */ +#define HHI_MPLL_CNTL7 0x298 /* 0xa6 offset in data sheet */ +#define HHI_MPLL_CNTL8 0x29C /* 0xa7 offset in data sheet */ +#define HHI_MPLL_CNTL9 0x2A0 /* 0xa8 offset in data sheet */ +#define HHI_MPLL_CNTL10 0x2A4 /* 0xa9 offset in data sheet */ + +/* * CLKID index values * * These indices are entirely contrived and do not map onto the hardware. @@ -142,8 +157,11 @@ #define CLKID_AO_AHB_SRAM 90 #define CLKID_AO_AHB_BUS 91 #define CLKID_AO_IFACE 92 +#define CLKID_MPLL0 93 +#define CLKID_MPLL1 94 +#define CLKID_MPLL2 95 -#define CLK_NR_CLKS 93 +#define CLK_NR_CLKS 96 /* include the CLKIDs that have been made part of the stable DT binding */ #include <dt-bindings/clock/meson8b-clkc.h> diff --git a/drivers/clk/qcom/mmcc-msm8996.c b/drivers/clk/qcom/mmcc-msm8996.c index 9b97246287a7..20d8fea32a99 100644 --- a/drivers/clk/qcom/mmcc-msm8996.c +++ b/drivers/clk/qcom/mmcc-msm8996.c @@ -2986,7 +2986,7 @@ static struct gdsc vfe1_gdsc = { .cxcs = (unsigned int []){ 0x36ac }, .cxc_count = 1, .pd = { - .name = "vfe0", + .name = "vfe1", }, .parent = &camss_gdsc.pd, .pwrsts = PWRSTS_OFF_ON, diff --git a/drivers/clk/renesas/r8a7795-cpg-mssr.c b/drivers/clk/renesas/r8a7795-cpg-mssr.c index bfffdb00df97..eaa98b488f01 100644 --- a/drivers/clk/renesas/r8a7795-cpg-mssr.c +++ b/drivers/clk/renesas/r8a7795-cpg-mssr.c @@ -16,6 +16,7 @@ #include <linux/init.h> #include <linux/kernel.h> #include <linux/soc/renesas/rcar-rst.h> +#include <linux/sys_soc.h> #include <dt-bindings/clock/r8a7795-cpg-mssr.h> @@ -24,7 +25,7 @@ enum clk_ids { /* Core Clock Outputs exported to DT */ - LAST_DT_CORE_CLK = R8A7795_CLK_OSC, + LAST_DT_CORE_CLK = R8A7795_CLK_S0D12, /* External Input Clocks */ CLK_EXTAL, @@ -51,10 +52,10 @@ enum clk_ids { MOD_CLK_BASE }; -static const struct cpg_core_clk r8a7795_core_clks[] __initconst = { +static struct cpg_core_clk r8a7795_core_clks[] __initdata = { /* External Clock Inputs */ - DEF_INPUT("extal", CLK_EXTAL), - DEF_INPUT("extalr", CLK_EXTALR), + DEF_INPUT("extal", CLK_EXTAL), + DEF_INPUT("extalr", CLK_EXTALR), /* Internal Core Clocks */ DEF_BASE(".main", CLK_MAIN, CLK_TYPE_GEN3_MAIN, CLK_EXTAL), @@ -78,7 +79,12 @@ static const struct cpg_core_clk r8a7795_core_clks[] __initconst = { 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("s0d2", R8A7795_CLK_S0D2, CLK_S0, 2, 1), + DEF_FIXED("s0d3", R8A7795_CLK_S0D3, CLK_S0, 3, 1), DEF_FIXED("s0d4", R8A7795_CLK_S0D4, CLK_S0, 4, 1), + DEF_FIXED("s0d6", R8A7795_CLK_S0D6, CLK_S0, 6, 1), + DEF_FIXED("s0d8", R8A7795_CLK_S0D8, CLK_S0, 8, 1), + DEF_FIXED("s0d12", R8A7795_CLK_S0D12, CLK_S0, 12, 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), @@ -89,29 +95,29 @@ static const struct cpg_core_clk r8a7795_core_clks[] __initconst = { DEF_FIXED("s3d2", R8A7795_CLK_S3D2, CLK_S3, 2, 1), DEF_FIXED("s3d4", R8A7795_CLK_S3D4, CLK_S3, 4, 1), - DEF_GEN3_SD("sd0", R8A7795_CLK_SD0, CLK_SDSRC, 0x0074), - DEF_GEN3_SD("sd1", R8A7795_CLK_SD1, CLK_SDSRC, 0x0078), - DEF_GEN3_SD("sd2", R8A7795_CLK_SD2, CLK_SDSRC, 0x0268), - DEF_GEN3_SD("sd3", R8A7795_CLK_SD3, CLK_SDSRC, 0x026c), + DEF_GEN3_SD("sd0", R8A7795_CLK_SD0, CLK_SDSRC, 0x074), + DEF_GEN3_SD("sd1", R8A7795_CLK_SD1, CLK_SDSRC, 0x078), + DEF_GEN3_SD("sd2", R8A7795_CLK_SD2, CLK_SDSRC, 0x268), + DEF_GEN3_SD("sd3", R8A7795_CLK_SD3, CLK_SDSRC, 0x26c), 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_DIV4, 0x250), DEF_DIV6P1("canfd", R8A7795_CLK_CANFD, CLK_PLL1_DIV4, 0x244), DEF_DIV6P1("csi0", R8A7795_CLK_CSI0, CLK_PLL1_DIV4, 0x00c), + DEF_DIV6P1("mso", R8A7795_CLK_MSO, CLK_PLL1_DIV4, 0x014), + DEF_DIV6P1("hdmi", R8A7795_CLK_HDMI, CLK_PLL1_DIV4, 0x250), - DEF_DIV6_RO("osc", R8A7795_CLK_OSC, CLK_EXTAL, CPG_RCKCR, 8), + DEF_DIV6_RO("osc", R8A7795_CLK_OSC, CLK_EXTAL, CPG_RCKCR, 8), DEF_DIV6_RO("r_int", CLK_RINT, CLK_EXTAL, CPG_RCKCR, 32), - DEF_BASE("r", R8A7795_CLK_R, CLK_TYPE_GEN3_R, CLK_RINT), + DEF_BASE("r", R8A7795_CLK_R, CLK_TYPE_GEN3_R, CLK_RINT), }; -static const struct mssr_mod_clk r8a7795_mod_clks[] __initconst = { - DEF_MOD("fdp1-2", 117, R8A7795_CLK_S2D1), - DEF_MOD("fdp1-1", 118, R8A7795_CLK_S2D1), - DEF_MOD("fdp1-0", 119, R8A7795_CLK_S2D1), +static struct mssr_mod_clk r8a7795_mod_clks[] __initdata = { + DEF_MOD("fdp1-2", 117, R8A7795_CLK_S2D1), /* ES1.x */ + DEF_MOD("fdp1-1", 118, R8A7795_CLK_S0D1), + DEF_MOD("fdp1-0", 119, R8A7795_CLK_S0D1), DEF_MOD("scif5", 202, R8A7795_CLK_S3D4), DEF_MOD("scif4", 203, R8A7795_CLK_S3D4), DEF_MOD("scif3", 204, R8A7795_CLK_S3D4), @@ -121,9 +127,9 @@ static const struct mssr_mod_clk r8a7795_mod_clks[] __initconst = { 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("sys-dmac2", 217, R8A7795_CLK_S0D3), + DEF_MOD("sys-dmac1", 218, R8A7795_CLK_S0D3), + DEF_MOD("sys-dmac0", 219, R8A7795_CLK_S0D3), DEF_MOD("cmt3", 300, R8A7795_CLK_R), DEF_MOD("cmt2", 301, R8A7795_CLK_R), DEF_MOD("cmt1", 302, R8A7795_CLK_R), @@ -135,15 +141,15 @@ static const struct mssr_mod_clk r8a7795_mod_clks[] __initconst = { DEF_MOD("sdif0", 314, R8A7795_CLK_SD0), DEF_MOD("pcie1", 318, R8A7795_CLK_S3D1), DEF_MOD("pcie0", 319, R8A7795_CLK_S3D1), - DEF_MOD("usb3-if1", 327, R8A7795_CLK_S3D1), + DEF_MOD("usb3-if1", 327, R8A7795_CLK_S3D1), /* ES1.x */ DEF_MOD("usb3-if0", 328, R8A7795_CLK_S3D1), DEF_MOD("usb-dmac0", 330, R8A7795_CLK_S3D1), DEF_MOD("usb-dmac1", 331, R8A7795_CLK_S3D1), - DEF_MOD("rwdt0", 402, R8A7795_CLK_R), + DEF_MOD("rwdt", 402, R8A7795_CLK_R), DEF_MOD("intc-ex", 407, R8A7795_CLK_CP), DEF_MOD("intc-ap", 408, R8A7795_CLK_S3D1), - DEF_MOD("audmac0", 502, R8A7795_CLK_S3D4), - DEF_MOD("audmac1", 501, R8A7795_CLK_S3D4), + DEF_MOD("audmac1", 501, R8A7795_CLK_S0D3), + DEF_MOD("audmac0", 502, R8A7795_CLK_S0D3), DEF_MOD("drif7", 508, R8A7795_CLK_S3D2), DEF_MOD("drif6", 509, R8A7795_CLK_S3D2), DEF_MOD("drif5", 510, R8A7795_CLK_S3D2), @@ -159,35 +165,35 @@ static const struct mssr_mod_clk r8a7795_mod_clks[] __initconst = { DEF_MOD("hscif0", 520, R8A7795_CLK_S3D1), DEF_MOD("thermal", 522, R8A7795_CLK_CP), DEF_MOD("pwm", 523, R8A7795_CLK_S3D4), - DEF_MOD("fcpvd3", 600, R8A7795_CLK_S2D1), - DEF_MOD("fcpvd2", 601, R8A7795_CLK_S2D1), - DEF_MOD("fcpvd1", 602, R8A7795_CLK_S2D1), - DEF_MOD("fcpvd0", 603, R8A7795_CLK_S2D1), - DEF_MOD("fcpvb1", 606, R8A7795_CLK_S2D1), - DEF_MOD("fcpvb0", 607, R8A7795_CLK_S2D1), - DEF_MOD("fcpvi2", 609, R8A7795_CLK_S2D1), - DEF_MOD("fcpvi1", 610, R8A7795_CLK_S2D1), - DEF_MOD("fcpvi0", 611, R8A7795_CLK_S2D1), - DEF_MOD("fcpf2", 613, R8A7795_CLK_S2D1), - DEF_MOD("fcpf1", 614, R8A7795_CLK_S2D1), - DEF_MOD("fcpf0", 615, R8A7795_CLK_S2D1), - DEF_MOD("fcpci1", 616, R8A7795_CLK_S2D1), - DEF_MOD("fcpci0", 617, R8A7795_CLK_S2D1), - DEF_MOD("fcpcs", 619, R8A7795_CLK_S2D1), - 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("fcpvd3", 600, R8A7795_CLK_S2D1), /* ES1.x */ + DEF_MOD("fcpvd2", 601, R8A7795_CLK_S0D2), + DEF_MOD("fcpvd1", 602, R8A7795_CLK_S0D2), + DEF_MOD("fcpvd0", 603, R8A7795_CLK_S0D2), + DEF_MOD("fcpvb1", 606, R8A7795_CLK_S0D1), + DEF_MOD("fcpvb0", 607, R8A7795_CLK_S0D1), + DEF_MOD("fcpvi2", 609, R8A7795_CLK_S2D1), /* ES1.x */ + DEF_MOD("fcpvi1", 610, R8A7795_CLK_S0D1), + DEF_MOD("fcpvi0", 611, R8A7795_CLK_S0D1), + DEF_MOD("fcpf2", 613, R8A7795_CLK_S2D1), /* ES1.x */ + DEF_MOD("fcpf1", 614, R8A7795_CLK_S0D1), + DEF_MOD("fcpf0", 615, R8A7795_CLK_S0D1), + DEF_MOD("fcpci1", 616, R8A7795_CLK_S2D1), /* ES1.x */ + DEF_MOD("fcpci0", 617, R8A7795_CLK_S2D1), /* ES1.x */ + DEF_MOD("fcpcs", 619, R8A7795_CLK_S0D1), + DEF_MOD("vspd3", 620, R8A7795_CLK_S2D1), /* ES1.x */ + DEF_MOD("vspd2", 621, R8A7795_CLK_S0D2), + DEF_MOD("vspd1", 622, R8A7795_CLK_S0D2), + DEF_MOD("vspd0", 623, R8A7795_CLK_S0D2), + DEF_MOD("vspbc", 624, R8A7795_CLK_S0D1), + DEF_MOD("vspbd", 626, R8A7795_CLK_S0D1), + DEF_MOD("vspi2", 629, R8A7795_CLK_S2D1), /* ES1.x */ + DEF_MOD("vspi1", 630, R8A7795_CLK_S0D1), + DEF_MOD("vspi0", 631, R8A7795_CLK_S0D1), DEF_MOD("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("csi21", 713, R8A7795_CLK_CSI0), + DEF_MOD("csi21", 713, R8A7795_CLK_CSI0), /* ES1.x */ DEF_MOD("csi20", 714, R8A7795_CLK_CSI0), DEF_MOD("csi41", 715, R8A7795_CLK_CSI0), DEF_MOD("csi40", 716, R8A7795_CLK_CSI0), @@ -198,16 +204,20 @@ static const struct mssr_mod_clk r8a7795_mod_clks[] __initconst = { DEF_MOD("lvds", 727, R8A7795_CLK_S0D4), DEF_MOD("hdmi1", 728, R8A7795_CLK_HDMI), DEF_MOD("hdmi0", 729, R8A7795_CLK_HDMI), - DEF_MOD("vin7", 804, R8A7795_CLK_S2D1), - DEF_MOD("vin6", 805, R8A7795_CLK_S2D1), - DEF_MOD("vin5", 806, R8A7795_CLK_S2D1), - DEF_MOD("vin4", 807, R8A7795_CLK_S2D1), - DEF_MOD("vin3", 808, R8A7795_CLK_S2D1), - DEF_MOD("vin2", 809, R8A7795_CLK_S2D1), - DEF_MOD("vin1", 810, R8A7795_CLK_S2D1), - DEF_MOD("vin0", 811, R8A7795_CLK_S2D1), - DEF_MOD("etheravb", 812, R8A7795_CLK_S3D2), + DEF_MOD("vin7", 804, R8A7795_CLK_S0D2), + DEF_MOD("vin6", 805, R8A7795_CLK_S0D2), + DEF_MOD("vin5", 806, R8A7795_CLK_S0D2), + DEF_MOD("vin4", 807, R8A7795_CLK_S0D2), + DEF_MOD("vin3", 808, R8A7795_CLK_S0D2), + DEF_MOD("vin2", 809, R8A7795_CLK_S0D2), + DEF_MOD("vin1", 810, R8A7795_CLK_S0D2), + DEF_MOD("vin0", 811, R8A7795_CLK_S0D2), + DEF_MOD("etheravb", 812, R8A7795_CLK_S0D6), DEF_MOD("sata0", 815, R8A7795_CLK_S3D2), + DEF_MOD("imr3", 820, R8A7795_CLK_S0D2), + DEF_MOD("imr2", 821, R8A7795_CLK_S0D2), + DEF_MOD("imr1", 822, R8A7795_CLK_S0D2), + DEF_MOD("imr0", 823, R8A7795_CLK_S0D2), DEF_MOD("gpio7", 905, R8A7795_CLK_CP), DEF_MOD("gpio6", 906, R8A7795_CLK_CP), DEF_MOD("gpio5", 907, R8A7795_CLK_CP), @@ -310,6 +320,82 @@ static const struct rcar_gen3_cpg_pll_config cpg_pll_configs[16] __initconst = { { 2, 192, 192, }, }; +static const struct soc_device_attribute r8a7795es1[] __initconst = { + { .soc_id = "r8a7795", .revision = "ES1.*" }, + { /* sentinel */ } +}; + + + /* + * Fixups for R-Car H3 ES1.x + */ + +static const unsigned int r8a7795es1_mod_nullify[] __initconst = { + MOD_CLK_ID(326), /* USB-DMAC3-0 */ + MOD_CLK_ID(329), /* USB-DMAC3-1 */ + MOD_CLK_ID(700), /* EHCI/OHCI3 */ + MOD_CLK_ID(705), /* HS-USB-IF3 */ + +}; + +static const struct mssr_mod_reparent r8a7795es1_mod_reparent[] __initconst = { + { MOD_CLK_ID(118), R8A7795_CLK_S2D1 }, /* FDP1-1 */ + { MOD_CLK_ID(119), R8A7795_CLK_S2D1 }, /* FDP1-0 */ + { MOD_CLK_ID(217), R8A7795_CLK_S3D1 }, /* SYS-DMAC2 */ + { MOD_CLK_ID(218), R8A7795_CLK_S3D1 }, /* SYS-DMAC1 */ + { MOD_CLK_ID(219), R8A7795_CLK_S3D1 }, /* SYS-DMAC0 */ + { MOD_CLK_ID(501), R8A7795_CLK_S3D1 }, /* AUDMAC1 */ + { MOD_CLK_ID(502), R8A7795_CLK_S3D1 }, /* AUDMAC0 */ + { MOD_CLK_ID(601), R8A7795_CLK_S2D1 }, /* FCPVD2 */ + { MOD_CLK_ID(602), R8A7795_CLK_S2D1 }, /* FCPVD1 */ + { MOD_CLK_ID(603), R8A7795_CLK_S2D1 }, /* FCPVD0 */ + { MOD_CLK_ID(606), R8A7795_CLK_S2D1 }, /* FCPVB1 */ + { MOD_CLK_ID(607), R8A7795_CLK_S2D1 }, /* FCPVB0 */ + { MOD_CLK_ID(610), R8A7795_CLK_S2D1 }, /* FCPVI1 */ + { MOD_CLK_ID(611), R8A7795_CLK_S2D1 }, /* FCPVI0 */ + { MOD_CLK_ID(614), R8A7795_CLK_S2D1 }, /* FCPF1 */ + { MOD_CLK_ID(615), R8A7795_CLK_S2D1 }, /* FCPF0 */ + { MOD_CLK_ID(619), R8A7795_CLK_S2D1 }, /* FCPCS */ + { MOD_CLK_ID(621), R8A7795_CLK_S2D1 }, /* VSPD2 */ + { MOD_CLK_ID(622), R8A7795_CLK_S2D1 }, /* VSPD1 */ + { MOD_CLK_ID(623), R8A7795_CLK_S2D1 }, /* VSPD0 */ + { MOD_CLK_ID(624), R8A7795_CLK_S2D1 }, /* VSPBC */ + { MOD_CLK_ID(626), R8A7795_CLK_S2D1 }, /* VSPBD */ + { MOD_CLK_ID(630), R8A7795_CLK_S2D1 }, /* VSPI1 */ + { MOD_CLK_ID(631), R8A7795_CLK_S2D1 }, /* VSPI0 */ + { MOD_CLK_ID(804), R8A7795_CLK_S2D1 }, /* VIN7 */ + { MOD_CLK_ID(805), R8A7795_CLK_S2D1 }, /* VIN6 */ + { MOD_CLK_ID(806), R8A7795_CLK_S2D1 }, /* VIN5 */ + { MOD_CLK_ID(807), R8A7795_CLK_S2D1 }, /* VIN4 */ + { MOD_CLK_ID(808), R8A7795_CLK_S2D1 }, /* VIN3 */ + { MOD_CLK_ID(809), R8A7795_CLK_S2D1 }, /* VIN2 */ + { MOD_CLK_ID(810), R8A7795_CLK_S2D1 }, /* VIN1 */ + { MOD_CLK_ID(811), R8A7795_CLK_S2D1 }, /* VIN0 */ + { MOD_CLK_ID(812), R8A7795_CLK_S3D2 }, /* EAVB-IF */ + { MOD_CLK_ID(820), R8A7795_CLK_S2D1 }, /* IMR3 */ + { MOD_CLK_ID(821), R8A7795_CLK_S2D1 }, /* IMR2 */ + { MOD_CLK_ID(822), R8A7795_CLK_S2D1 }, /* IMR1 */ + { MOD_CLK_ID(823), R8A7795_CLK_S2D1 }, /* IMR0 */ +}; + + + /* + * Fixups for R-Car H3 ES2.x + */ + +static const unsigned int r8a7795es2_mod_nullify[] __initconst = { + MOD_CLK_ID(117), /* FDP1-2 */ + MOD_CLK_ID(327), /* USB3-IF1 */ + MOD_CLK_ID(600), /* FCPVD3 */ + MOD_CLK_ID(609), /* FCPVI2 */ + MOD_CLK_ID(613), /* FCPF2 */ + MOD_CLK_ID(616), /* FCPCI1 */ + MOD_CLK_ID(617), /* FCPCI0 */ + MOD_CLK_ID(620), /* VSPD3 */ + MOD_CLK_ID(629), /* VSPI2 */ + MOD_CLK_ID(713), /* CSI21 */ +}; + static int __init r8a7795_cpg_mssr_init(struct device *dev) { const struct rcar_gen3_cpg_pll_config *cpg_pll_config; @@ -326,7 +412,26 @@ static int __init r8a7795_cpg_mssr_init(struct device *dev) return -EINVAL; } - return rcar_gen3_cpg_init(cpg_pll_config, CLK_EXTALR); + if (soc_device_match(r8a7795es1)) { + cpg_core_nullify_range(r8a7795_core_clks, + ARRAY_SIZE(r8a7795_core_clks), + R8A7795_CLK_S0D2, R8A7795_CLK_S0D12); + mssr_mod_nullify(r8a7795_mod_clks, + ARRAY_SIZE(r8a7795_mod_clks), + r8a7795es1_mod_nullify, + ARRAY_SIZE(r8a7795es1_mod_nullify)); + mssr_mod_reparent(r8a7795_mod_clks, + ARRAY_SIZE(r8a7795_mod_clks), + r8a7795es1_mod_reparent, + ARRAY_SIZE(r8a7795es1_mod_reparent)); + } else { + mssr_mod_nullify(r8a7795_mod_clks, + ARRAY_SIZE(r8a7795_mod_clks), + r8a7795es2_mod_nullify, + ARRAY_SIZE(r8a7795es2_mod_nullify)); + } + + return rcar_gen3_cpg_init(cpg_pll_config, CLK_EXTALR, cpg_mode); } const struct cpg_mssr_info r8a7795_cpg_mssr_info __initconst = { diff --git a/drivers/clk/renesas/r8a7796-cpg-mssr.c b/drivers/clk/renesas/r8a7796-cpg-mssr.c index 11e084a56b0d..9d114b31b073 100644 --- a/drivers/clk/renesas/r8a7796-cpg-mssr.c +++ b/drivers/clk/renesas/r8a7796-cpg-mssr.c @@ -54,8 +54,8 @@ enum clk_ids { static const struct cpg_core_clk r8a7796_core_clks[] __initconst = { /* External Clock Inputs */ - DEF_INPUT("extal", CLK_EXTAL), - DEF_INPUT("extalr", CLK_EXTALR), + DEF_INPUT("extal", CLK_EXTAL), + DEF_INPUT("extalr", CLK_EXTALR), /* Internal Core Clocks */ DEF_BASE(".main", CLK_MAIN, CLK_TYPE_GEN3_MAIN, CLK_EXTAL), @@ -95,10 +95,10 @@ static const struct cpg_core_clk r8a7796_core_clks[] __initconst = { DEF_FIXED("s3d2", R8A7796_CLK_S3D2, CLK_S3, 2, 1), DEF_FIXED("s3d4", R8A7796_CLK_S3D4, CLK_S3, 4, 1), - DEF_GEN3_SD("sd0", R8A7796_CLK_SD0, CLK_SDSRC, 0x0074), - DEF_GEN3_SD("sd1", R8A7796_CLK_SD1, CLK_SDSRC, 0x0078), - DEF_GEN3_SD("sd2", R8A7796_CLK_SD2, CLK_SDSRC, 0x0268), - DEF_GEN3_SD("sd3", R8A7796_CLK_SD3, CLK_SDSRC, 0x026c), + DEF_GEN3_SD("sd0", R8A7796_CLK_SD0, CLK_SDSRC, 0x074), + DEF_GEN3_SD("sd1", R8A7796_CLK_SD1, CLK_SDSRC, 0x078), + DEF_GEN3_SD("sd2", R8A7796_CLK_SD2, CLK_SDSRC, 0x268), + DEF_GEN3_SD("sd3", R8A7796_CLK_SD3, CLK_SDSRC, 0x26c), DEF_FIXED("cl", R8A7796_CLK_CL, CLK_PLL1_DIV2, 48, 1), DEF_FIXED("cp", R8A7796_CLK_CP, CLK_EXTAL, 2, 1), @@ -135,7 +135,7 @@ static const struct mssr_mod_clk r8a7796_mod_clks[] __initconst = { DEF_MOD("sdif2", 312, R8A7796_CLK_SD2), DEF_MOD("sdif1", 313, R8A7796_CLK_SD1), DEF_MOD("sdif0", 314, R8A7796_CLK_SD0), - DEF_MOD("rwdt0", 402, R8A7796_CLK_R), + DEF_MOD("rwdt", 402, R8A7796_CLK_R), DEF_MOD("intc-ap", 408, R8A7796_CLK_S3D1), DEF_MOD("drif7", 508, R8A7796_CLK_S3D2), DEF_MOD("drif6", 509, R8A7796_CLK_S3D2), @@ -179,6 +179,8 @@ static const struct mssr_mod_clk r8a7796_mod_clks[] __initconst = { DEF_MOD("vin1", 810, R8A7796_CLK_S0D2), DEF_MOD("vin0", 811, R8A7796_CLK_S0D2), DEF_MOD("etheravb", 812, R8A7796_CLK_S0D6), + DEF_MOD("imr1", 822, R8A7796_CLK_S0D2), + DEF_MOD("imr0", 823, R8A7796_CLK_S0D2), DEF_MOD("gpio7", 905, R8A7796_CLK_S3D4), DEF_MOD("gpio6", 906, R8A7796_CLK_S3D4), DEF_MOD("gpio5", 907, R8A7796_CLK_S3D4), @@ -271,7 +273,7 @@ static int __init r8a7796_cpg_mssr_init(struct device *dev) return -EINVAL; } - return rcar_gen3_cpg_init(cpg_pll_config, CLK_EXTALR); + return rcar_gen3_cpg_init(cpg_pll_config, CLK_EXTALR, cpg_mode); } const struct cpg_mssr_info r8a7796_cpg_mssr_info __initconst = { diff --git a/drivers/clk/renesas/rcar-gen3-cpg.c b/drivers/clk/renesas/rcar-gen3-cpg.c index 742f6dc7c156..3dee900522b7 100644 --- a/drivers/clk/renesas/rcar-gen3-cpg.c +++ b/drivers/clk/renesas/rcar-gen3-cpg.c @@ -20,6 +20,7 @@ #include <linux/init.h> #include <linux/io.h> #include <linux/slab.h> +#include <linux/sys_soc.h> #include "renesas-cpg-mssr.h" #include "rcar-gen3-cpg.h" @@ -247,6 +248,27 @@ static struct clk * __init cpg_sd_clk_register(const struct cpg_core_clk *core, static const struct rcar_gen3_cpg_pll_config *cpg_pll_config __initdata; static unsigned int cpg_clk_extalr __initdata; +static u32 cpg_mode __initdata; +static u32 cpg_quirks __initdata; + +#define PLL_ERRATA BIT(0) /* Missing PLL0/2/4 post-divider */ +#define RCKCR_CKSEL BIT(1) /* Manual RCLK parent selection */ + +static const struct soc_device_attribute cpg_quirks_match[] __initconst = { + { + .soc_id = "r8a7795", .revision = "ES1.0", + .data = (void *)(PLL_ERRATA | RCKCR_CKSEL), + }, + { + .soc_id = "r8a7795", .revision = "ES1.*", + .data = (void *)RCKCR_CKSEL, + }, + { + .soc_id = "r8a7796", .revision = "ES1.0", + .data = (void *)RCKCR_CKSEL, + }, + { /* sentinel */ } +}; struct clk * __init rcar_gen3_cpg_clk_register(struct device *dev, const struct cpg_core_clk *core, const struct cpg_mssr_info *info, @@ -275,6 +297,8 @@ struct clk * __init rcar_gen3_cpg_clk_register(struct device *dev, */ value = readl(base + CPG_PLL0CR); mult = (((value >> 24) & 0x7f) + 1) * 2; + if (cpg_quirks & PLL_ERRATA) + mult *= 2; break; case CLK_TYPE_GEN3_PLL1: @@ -290,6 +314,8 @@ struct clk * __init rcar_gen3_cpg_clk_register(struct device *dev, */ value = readl(base + CPG_PLL2CR); mult = (((value >> 24) & 0x7f) + 1) * 2; + if (cpg_quirks & PLL_ERRATA) + mult *= 2; break; case CLK_TYPE_GEN3_PLL3: @@ -305,24 +331,33 @@ struct clk * __init rcar_gen3_cpg_clk_register(struct device *dev, */ value = readl(base + CPG_PLL4CR); mult = (((value >> 24) & 0x7f) + 1) * 2; + if (cpg_quirks & PLL_ERRATA) + mult *= 2; break; case CLK_TYPE_GEN3_SD: return cpg_sd_clk_register(core, base, __clk_get_name(parent)); case CLK_TYPE_GEN3_R: - /* - * RINT is default. - * Only if EXTALR is populated, we switch to it. - */ - value = readl(base + CPG_RCKCR) & 0x3f; - - if (clk_get_rate(clks[cpg_clk_extalr])) { - parent = clks[cpg_clk_extalr]; - value |= BIT(15); + if (cpg_quirks & RCKCR_CKSEL) { + /* + * RINT is default. + * Only if EXTALR is populated, we switch to it. + */ + value = readl(base + CPG_RCKCR) & 0x3f; + + if (clk_get_rate(clks[cpg_clk_extalr])) { + parent = clks[cpg_clk_extalr]; + value |= BIT(15); + } + + writel(value, base + CPG_RCKCR); + break; } - writel(value, base + CPG_RCKCR); + /* Select parent clock of RCLK by MD28 */ + if (cpg_mode & BIT(28)) + parent = clks[cpg_clk_extalr]; break; default: @@ -334,9 +369,16 @@ struct clk * __init rcar_gen3_cpg_clk_register(struct device *dev, } int __init rcar_gen3_cpg_init(const struct rcar_gen3_cpg_pll_config *config, - unsigned int clk_extalr) + unsigned int clk_extalr, u32 mode) { + const struct soc_device_attribute *attr; + cpg_pll_config = config; cpg_clk_extalr = clk_extalr; + cpg_mode = mode; + attr = soc_device_match(cpg_quirks_match); + if (attr) + cpg_quirks = (uintptr_t)attr->data; + pr_debug("%s: mode = 0x%x quirks = 0x%x\n", __func__, mode, cpg_quirks); return 0; } diff --git a/drivers/clk/renesas/rcar-gen3-cpg.h b/drivers/clk/renesas/rcar-gen3-cpg.h index f788f481dd42..073be54b5d03 100644 --- a/drivers/clk/renesas/rcar-gen3-cpg.h +++ b/drivers/clk/renesas/rcar-gen3-cpg.h @@ -37,6 +37,6 @@ struct clk *rcar_gen3_cpg_clk_register(struct device *dev, const struct cpg_core_clk *core, const struct cpg_mssr_info *info, struct clk **clks, void __iomem *base); int rcar_gen3_cpg_init(const struct rcar_gen3_cpg_pll_config *config, - unsigned int clk_extalr); + unsigned int clk_extalr, u32 mode); #endif diff --git a/drivers/clk/renesas/renesas-cpg-mssr.c b/drivers/clk/renesas/renesas-cpg-mssr.c index eadcbd43ff88..99eeec6f24ec 100644 --- a/drivers/clk/renesas/renesas-cpg-mssr.c +++ b/drivers/clk/renesas/renesas-cpg-mssr.c @@ -265,6 +265,11 @@ static void __init cpg_mssr_register_core_clk(const struct cpg_core_clk *core, WARN_DEBUG(id >= priv->num_core_clks); WARN_DEBUG(PTR_ERR(priv->clks[id]) != -ENOENT); + if (!core->name) { + /* Skip NULLified clock */ + return; + } + switch (core->type) { case CLK_TYPE_IN: clk = of_clk_get_by_name(priv->dev->of_node, core->name); @@ -335,6 +340,11 @@ static void __init cpg_mssr_register_mod_clk(const struct mssr_mod_clk *mod, WARN_DEBUG(mod->parent >= priv->num_core_clks + priv->num_mod_clks); WARN_DEBUG(PTR_ERR(priv->clks[id]) != -ENOENT); + if (!mod->name) { + /* Skip NULLified clock */ + return; + } + parent = priv->clks[mod->parent]; if (IS_ERR(parent)) { clk = parent; @@ -734,5 +744,45 @@ static int __init cpg_mssr_init(void) subsys_initcall(cpg_mssr_init); +void __init cpg_core_nullify_range(struct cpg_core_clk *core_clks, + unsigned int num_core_clks, + unsigned int first_clk, + unsigned int last_clk) +{ + unsigned int i; + + for (i = 0; i < num_core_clks; i++) + if (core_clks[i].id >= first_clk && + core_clks[i].id <= last_clk) + core_clks[i].name = NULL; +} + +void __init mssr_mod_nullify(struct mssr_mod_clk *mod_clks, + unsigned int num_mod_clks, + const unsigned int *clks, unsigned int n) +{ + unsigned int i, j; + + for (i = 0, j = 0; i < num_mod_clks && j < n; i++) + if (mod_clks[i].id == clks[j]) { + mod_clks[i].name = NULL; + j++; + } +} + +void __init mssr_mod_reparent(struct mssr_mod_clk *mod_clks, + unsigned int num_mod_clks, + const struct mssr_mod_reparent *clks, + unsigned int n) +{ + unsigned int i, j; + + for (i = 0, j = 0; i < num_mod_clks && j < n; i++) + if (mod_clks[i].id == clks[j].clk) { + mod_clks[i].parent = clks[j].parent; + j++; + } +} + MODULE_DESCRIPTION("Renesas CPG/MSSR Driver"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/clk/renesas/renesas-cpg-mssr.h b/drivers/clk/renesas/renesas-cpg-mssr.h index 4bb7a80c6469..148f4f0aa2a4 100644 --- a/drivers/clk/renesas/renesas-cpg-mssr.h +++ b/drivers/clk/renesas/renesas-cpg-mssr.h @@ -134,4 +134,26 @@ extern const struct cpg_mssr_info r8a7743_cpg_mssr_info; extern const struct cpg_mssr_info r8a7745_cpg_mssr_info; extern const struct cpg_mssr_info r8a7795_cpg_mssr_info; extern const struct cpg_mssr_info r8a7796_cpg_mssr_info; + + + /* + * Helpers for fixing up clock tables depending on SoC revision + */ + +struct mssr_mod_reparent { + unsigned int clk, parent; +}; + + +extern void cpg_core_nullify_range(struct cpg_core_clk *core_clks, + unsigned int num_core_clks, + unsigned int first_clk, + unsigned int last_clk); +extern void mssr_mod_nullify(struct mssr_mod_clk *mod_clks, + unsigned int num_mod_clks, + const unsigned int *clks, unsigned int n); +extern void mssr_mod_reparent(struct mssr_mod_clk *mod_clks, + unsigned int num_mod_clks, + const struct mssr_mod_reparent *clks, + unsigned int n); #endif diff --git a/drivers/clk/rockchip/Makefile b/drivers/clk/rockchip/Makefile index 141971488f40..26b220c988b2 100644 --- a/drivers/clk/rockchip/Makefile +++ b/drivers/clk/rockchip/Makefile @@ -12,7 +12,7 @@ obj-y += clk-muxgrf.o obj-y += clk-ddr.o obj-$(CONFIG_RESET_CONTROLLER) += softrst.o -obj-y += clk-rk1108.o +obj-y += clk-rv1108.o obj-y += clk-rk3036.o obj-y += clk-rk3188.o obj-y += clk-rk3228.o diff --git a/drivers/clk/rockchip/clk-pll.c b/drivers/clk/rockchip/clk-pll.c index eec51893a7e6..dd0433d4753e 100644 --- a/drivers/clk/rockchip/clk-pll.c +++ b/drivers/clk/rockchip/clk-pll.c @@ -269,6 +269,7 @@ static int rockchip_rk3036_pll_enable(struct clk_hw *hw) writel(HIWORD_UPDATE(0, RK3036_PLLCON1_PWRDOWN, 0), pll->reg_base + RK3036_PLLCON(1)); + rockchip_pll_wait_lock(pll); return 0; } @@ -501,6 +502,7 @@ static int rockchip_rk3066_pll_enable(struct clk_hw *hw) writel(HIWORD_UPDATE(0, RK3066_PLLCON3_PWRDOWN, 0), pll->reg_base + RK3066_PLLCON(3)); + rockchip_pll_wait_lock(pll); return 0; } @@ -746,6 +748,7 @@ static int rockchip_rk3399_pll_enable(struct clk_hw *hw) writel(HIWORD_UPDATE(0, RK3399_PLLCON3_PWRDOWN, 0), pll->reg_base + RK3399_PLLCON(3)); + rockchip_rk3399_pll_wait_lock(pll); return 0; } diff --git a/drivers/clk/rockchip/clk-rk3036.c b/drivers/clk/rockchip/clk-rk3036.c index 924f560dcf80..00d4150e33c3 100644 --- a/drivers/clk/rockchip/clk-rk3036.c +++ b/drivers/clk/rockchip/clk-rk3036.c @@ -127,7 +127,7 @@ 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_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" }; @@ -450,6 +450,13 @@ static void __init rk3036_clk_init(struct device_node *np) return; } + /* + * Make uart_pll_clk a child of the gpll, as all other sources are + * not that usable / stable. + */ + writel_relaxed(HIWORD_UPDATE(0x2, 0x3, 10), + reg_base + RK2928_CLKSEL_CON(13)); + ctx = rockchip_clk_init(np, reg_base, CLK_NR_CLKS); if (IS_ERR(ctx)) { pr_err("%s: rockchip clk init failed\n", __func__); diff --git a/drivers/clk/rockchip/clk-rk3328.c b/drivers/clk/rockchip/clk-rk3328.c index 1e384e143504..b04f29774ee7 100644 --- a/drivers/clk/rockchip/clk-rk3328.c +++ b/drivers/clk/rockchip/clk-rk3328.c @@ -20,6 +20,7 @@ #include <dt-bindings/clock/rk3328-cru.h> #include "clk.h" +#define RK3328_GRF_SOC_CON4 0x410 #define RK3328_GRF_SOC_STATUS0 0x480 #define RK3328_GRF_MAC_CON1 0x904 #define RK3328_GRF_MAC_CON2 0x908 @@ -214,6 +215,8 @@ PNAME(mux_mac2io_src_p) = { "clk_mac2io_src", "gmac_clkin" }; PNAME(mux_mac2phy_src_p) = { "clk_mac2phy_src", "phy_50m_out" }; +PNAME(mux_mac2io_ext_p) = { "clk_mac2io", + "gmac_clkin" }; static struct rockchip_pll_clock rk3328_pll_clks[] __initdata = { [apll] = PLL(pll_rk3328, PLL_APLL, "apll", mux_pll_p, @@ -680,6 +683,10 @@ static struct rockchip_clk_branch rk3328_clk_branches[] __initdata = { COMPOSITE(SCLK_MAC2IO_OUT, "clk_mac2io_out", mux_2plls_p, 0, RK3328_CLKSEL_CON(27), 15, 1, MFLAGS, 8, 5, DFLAGS, RK3328_CLKGATE_CON(3), 5, GFLAGS), + MUXGRF(SCLK_MAC2IO, "clk_mac2io", mux_mac2io_src_p, CLK_SET_RATE_NO_REPARENT, + RK3328_GRF_MAC_CON1, 10, 1, MFLAGS), + MUXGRF(SCLK_MAC2IO_EXT, "clk_mac2io_ext", mux_mac2io_ext_p, CLK_SET_RATE_NO_REPARENT, + RK3328_GRF_SOC_CON4, 14, 1, MFLAGS), COMPOSITE(SCLK_MAC2PHY_SRC, "clk_mac2phy_src", mux_2plls_p, 0, RK3328_CLKSEL_CON(26), 7, 1, MFLAGS, 0, 5, DFLAGS, @@ -691,6 +698,8 @@ static struct rockchip_clk_branch rk3328_clk_branches[] __initdata = { COMPOSITE_NOMUX(SCLK_MAC2PHY_OUT, "clk_mac2phy_out", "clk_mac2phy", 0, RK3328_CLKSEL_CON(26), 8, 2, DFLAGS, RK3328_CLKGATE_CON(9), 2, GFLAGS), + MUXGRF(SCLK_MAC2PHY, "clk_mac2phy", mux_mac2phy_src_p, CLK_SET_RATE_NO_REPARENT, + RK3328_GRF_MAC_CON2, 10, 1, MFLAGS), FACTOR(0, "xin12m", "xin24m", 0, 1, 2), diff --git a/drivers/clk/rockchip/clk-rk3368.c b/drivers/clk/rockchip/clk-rk3368.c index 6cb474c593e7..024762d3214d 100644 --- a/drivers/clk/rockchip/clk-rk3368.c +++ b/drivers/clk/rockchip/clk-rk3368.c @@ -835,18 +835,18 @@ static struct rockchip_clk_branch rk3368_clk_branches[] __initdata = { GATE(PCLK_PMU, "pclk_pmu", "pclk_pd_pmu", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(23), 0, GFLAGS), /* timer gates */ - GATE(0, "sclk_timer15", "xin24m", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(24), 11, GFLAGS), - GATE(0, "sclk_timer14", "xin24m", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(24), 10, GFLAGS), - GATE(0, "sclk_timer13", "xin24m", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(24), 9, GFLAGS), - GATE(0, "sclk_timer12", "xin24m", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(24), 8, GFLAGS), - GATE(0, "sclk_timer11", "xin24m", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(24), 7, GFLAGS), - GATE(0, "sclk_timer10", "xin24m", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(24), 6, GFLAGS), - GATE(0, "sclk_timer05", "xin24m", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(24), 5, GFLAGS), - GATE(0, "sclk_timer04", "xin24m", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(24), 4, GFLAGS), - GATE(0, "sclk_timer03", "xin24m", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(24), 3, GFLAGS), - GATE(0, "sclk_timer02", "xin24m", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(24), 2, GFLAGS), - GATE(0, "sclk_timer01", "xin24m", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(24), 1, GFLAGS), - GATE(0, "sclk_timer00", "xin24m", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(24), 0, GFLAGS), + GATE(SCLK_TIMER15, "sclk_timer15", "xin24m", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(24), 11, GFLAGS), + GATE(SCLK_TIMER14, "sclk_timer14", "xin24m", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(24), 10, GFLAGS), + GATE(SCLK_TIMER13, "sclk_timer13", "xin24m", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(24), 9, GFLAGS), + GATE(SCLK_TIMER12, "sclk_timer12", "xin24m", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(24), 8, GFLAGS), + GATE(SCLK_TIMER11, "sclk_timer11", "xin24m", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(24), 7, GFLAGS), + GATE(SCLK_TIMER10, "sclk_timer10", "xin24m", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(24), 6, GFLAGS), + GATE(SCLK_TIMER05, "sclk_timer05", "xin24m", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(24), 5, GFLAGS), + GATE(SCLK_TIMER04, "sclk_timer04", "xin24m", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(24), 4, GFLAGS), + GATE(SCLK_TIMER03, "sclk_timer03", "xin24m", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(24), 3, GFLAGS), + GATE(SCLK_TIMER02, "sclk_timer02", "xin24m", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(24), 2, GFLAGS), + GATE(SCLK_TIMER01, "sclk_timer01", "xin24m", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(24), 1, GFLAGS), + GATE(SCLK_TIMER00, "sclk_timer00", "xin24m", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(24), 0, GFLAGS), }; static const char *const rk3368_critical_clocks[] __initconst = { @@ -858,6 +858,9 @@ static const char *const rk3368_critical_clocks[] __initconst = { */ "pclk_pwm1", "pclk_pd_pmu", + "pclk_pd_alive", + "pclk_peri", + "hclk_peri", }; static void __init rk3368_clk_init(struct device_node *np) diff --git a/drivers/clk/rockchip/clk-rk3399.c b/drivers/clk/rockchip/clk-rk3399.c index 73121b144634..fa3cbef08776 100644 --- a/drivers/clk/rockchip/clk-rk3399.c +++ b/drivers/clk/rockchip/clk-rk3399.c @@ -1477,10 +1477,10 @@ static struct rockchip_clk_branch rk3399_clk_pmu_branches[] __initdata = { GATE(PCLK_UART4_PMU, "pclk_uart4_pmu", "pclk_pmu_src", 0, RK3399_PMU_CLKGATE_CON(1), 14, GFLAGS), GATE(PCLK_WDT_M0_PMU, "pclk_wdt_m0_pmu", "pclk_pmu_src", 0, RK3399_PMU_CLKGATE_CON(1), 15, GFLAGS), - GATE(FCLK_CM0S_PMU, "fclk_cm0s_pmu", "fclk_cm0s_src_pmu", 0, RK3399_PMU_CLKGATE_CON(2), 0, GFLAGS), - GATE(SCLK_CM0S_PMU, "sclk_cm0s_pmu", "fclk_cm0s_src_pmu", 0, RK3399_PMU_CLKGATE_CON(2), 1, GFLAGS), - GATE(HCLK_CM0S_PMU, "hclk_cm0s_pmu", "fclk_cm0s_src_pmu", 0, RK3399_PMU_CLKGATE_CON(2), 2, GFLAGS), - GATE(DCLK_CM0S_PMU, "dclk_cm0s_pmu", "fclk_cm0s_src_pmu", 0, RK3399_PMU_CLKGATE_CON(2), 3, GFLAGS), + GATE(FCLK_CM0S_PMU, "fclk_cm0s_pmu", "fclk_cm0s_src_pmu", CLK_IGNORE_UNUSED, RK3399_PMU_CLKGATE_CON(2), 0, GFLAGS), + GATE(SCLK_CM0S_PMU, "sclk_cm0s_pmu", "fclk_cm0s_src_pmu", CLK_IGNORE_UNUSED, RK3399_PMU_CLKGATE_CON(2), 1, GFLAGS), + GATE(HCLK_CM0S_PMU, "hclk_cm0s_pmu", "fclk_cm0s_src_pmu", CLK_IGNORE_UNUSED, RK3399_PMU_CLKGATE_CON(2), 2, GFLAGS), + GATE(DCLK_CM0S_PMU, "dclk_cm0s_pmu", "fclk_cm0s_src_pmu", CLK_IGNORE_UNUSED, RK3399_PMU_CLKGATE_CON(2), 3, GFLAGS), GATE(HCLK_NOC_PMU, "hclk_noc_pmu", "fclk_cm0s_src_pmu", CLK_IGNORE_UNUSED, RK3399_PMU_CLKGATE_CON(2), 5, GFLAGS), }; diff --git a/drivers/clk/rockchip/clk-rk1108.c b/drivers/clk/rockchip/clk-rv1108.c index 92750d798e5d..7c05ab366348 100644 --- a/drivers/clk/rockchip/clk-rk1108.c +++ b/drivers/clk/rockchip/clk-rv1108.c @@ -18,16 +18,16 @@ #include <linux/of.h> #include <linux/of_address.h> #include <linux/syscore_ops.h> -#include <dt-bindings/clock/rk1108-cru.h> +#include <dt-bindings/clock/rv1108-cru.h> #include "clk.h" -#define RK1108_GRF_SOC_STATUS0 0x480 +#define RV1108_GRF_SOC_STATUS0 0x480 -enum rk1108_plls { +enum rv1108_plls { apll, dpll, gpll, }; -static struct rockchip_pll_rate_table rk1108_pll_rates[] = { +static struct rockchip_pll_rate_table rv1108_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), @@ -74,32 +74,32 @@ static struct rockchip_pll_rate_table rk1108_pll_rates[] = { { /* sentinel */ }, }; -#define RK1108_DIV_CORE_MASK 0xf -#define RK1108_DIV_CORE_SHIFT 4 +#define RV1108_DIV_CORE_MASK 0xf +#define RV1108_DIV_CORE_SHIFT 4 -#define RK1108_CLKSEL0(_core_peri_div) \ +#define RV1108_CLKSEL0(_core_peri_div) \ { \ - .reg = RK1108_CLKSEL_CON(1), \ - .val = HIWORD_UPDATE(_core_peri_div, RK1108_DIV_CORE_MASK,\ - RK1108_DIV_CORE_SHIFT) \ + .reg = RV1108_CLKSEL_CON(1), \ + .val = HIWORD_UPDATE(_core_peri_div, RV1108_DIV_CORE_MASK,\ + RV1108_DIV_CORE_SHIFT) \ } -#define RK1108_CPUCLK_RATE(_prate, _core_peri_div) \ +#define RV1108_CPUCLK_RATE(_prate, _core_peri_div) \ { \ .prate = _prate, \ .divs = { \ - RK1108_CLKSEL0(_core_peri_div), \ + RV1108_CLKSEL0(_core_peri_div), \ }, \ } -static struct rockchip_cpuclk_rate_table rk1108_cpuclk_rates[] __initdata = { - RK1108_CPUCLK_RATE(816000000, 4), - RK1108_CPUCLK_RATE(600000000, 4), - RK1108_CPUCLK_RATE(312000000, 4), +static struct rockchip_cpuclk_rate_table rv1108_cpuclk_rates[] __initdata = { + RV1108_CPUCLK_RATE(816000000, 4), + RV1108_CPUCLK_RATE(600000000, 4), + RV1108_CPUCLK_RATE(312000000, 4), }; -static const struct rockchip_cpuclk_reg_data rk1108_cpuclk_data = { - .core_reg = RK1108_CLKSEL_CON(0), +static const struct rockchip_cpuclk_reg_data rv1108_cpuclk_data = { + .core_reg = RV1108_CLKSEL_CON(0), .div_core_shift = 0, .div_core_mask = 0x1f, .mux_core_alt = 1, @@ -131,13 +131,13 @@ PNAME(mux_i2s_out_p) = { "i2s0_pre", "xin12m" }; PNAME(mux_i2s1_p) = { "i2s1_src", "i2s1_frac", "xin12m" }; PNAME(mux_i2s2_p) = { "i2s2_src", "i2s2_frac", "xin12m" }; -static struct rockchip_pll_clock rk1108_pll_clks[] __initdata = { - [apll] = PLL(pll_rk3399, PLL_APLL, "apll", mux_pll_p, 0, RK1108_PLL_CON(0), - RK1108_PLL_CON(3), 8, 31, 0, rk1108_pll_rates), - [dpll] = PLL(pll_rk3399, PLL_DPLL, "dpll", mux_pll_p, 0, RK1108_PLL_CON(8), - RK1108_PLL_CON(11), 8, 31, 0, NULL), - [gpll] = PLL(pll_rk3399, PLL_GPLL, "gpll", mux_pll_p, 0, RK1108_PLL_CON(16), - RK1108_PLL_CON(19), 8, 31, ROCKCHIP_PLL_SYNC_RATE, rk1108_pll_rates), +static struct rockchip_pll_clock rv1108_pll_clks[] __initdata = { + [apll] = PLL(pll_rk3399, PLL_APLL, "apll", mux_pll_p, 0, RV1108_PLL_CON(0), + RV1108_PLL_CON(3), 8, 31, 0, rv1108_pll_rates), + [dpll] = PLL(pll_rk3399, PLL_DPLL, "dpll", mux_pll_p, 0, RV1108_PLL_CON(8), + RV1108_PLL_CON(11), 8, 31, 0, NULL), + [gpll] = PLL(pll_rk3399, PLL_GPLL, "gpll", mux_pll_p, 0, RV1108_PLL_CON(16), + RV1108_PLL_CON(19), 8, 31, ROCKCHIP_PLL_SYNC_RATE, rv1108_pll_rates), }; #define MFLAGS CLK_MUX_HIWORD_MASK @@ -145,56 +145,56 @@ static struct rockchip_pll_clock rk1108_pll_clks[] __initdata = { #define GFLAGS (CLK_GATE_HIWORD_MASK | CLK_GATE_SET_TO_DISABLE) #define IFLAGS ROCKCHIP_INVERTER_HIWORD_MASK -static struct rockchip_clk_branch rk1108_uart0_fracmux __initdata = +static struct rockchip_clk_branch rv1108_uart0_fracmux __initdata = MUX(SCLK_UART0, "sclk_uart0", mux_uart0_p, CLK_SET_RATE_PARENT, - RK1108_CLKSEL_CON(13), 8, 2, MFLAGS); + RV1108_CLKSEL_CON(13), 8, 2, MFLAGS); -static struct rockchip_clk_branch rk1108_uart1_fracmux __initdata = +static struct rockchip_clk_branch rv1108_uart1_fracmux __initdata = MUX(SCLK_UART1, "sclk_uart1", mux_uart1_p, CLK_SET_RATE_PARENT, - RK1108_CLKSEL_CON(14), 8, 2, MFLAGS); + RV1108_CLKSEL_CON(14), 8, 2, MFLAGS); -static struct rockchip_clk_branch rk1108_uart2_fracmux __initdata = +static struct rockchip_clk_branch rv1108_uart2_fracmux __initdata = MUX(SCLK_UART2, "sclk_uart2", mux_uart2_p, CLK_SET_RATE_PARENT, - RK1108_CLKSEL_CON(15), 8, 2, MFLAGS); + RV1108_CLKSEL_CON(15), 8, 2, MFLAGS); -static struct rockchip_clk_branch rk1108_i2s0_fracmux __initdata = +static struct rockchip_clk_branch rv1108_i2s0_fracmux __initdata = MUX(0, "i2s0_pre", mux_i2s0_pre_p, CLK_SET_RATE_PARENT, - RK1108_CLKSEL_CON(5), 12, 2, MFLAGS); + RV1108_CLKSEL_CON(5), 12, 2, MFLAGS); -static struct rockchip_clk_branch rk1108_i2s1_fracmux __initdata = +static struct rockchip_clk_branch rv1108_i2s1_fracmux __initdata = MUX(0, "i2s1_pre", mux_i2s1_p, CLK_SET_RATE_PARENT, - RK1108_CLKSEL_CON(6), 12, 2, MFLAGS); + RV1108_CLKSEL_CON(6), 12, 2, MFLAGS); -static struct rockchip_clk_branch rk1108_i2s2_fracmux __initdata = +static struct rockchip_clk_branch rv1108_i2s2_fracmux __initdata = MUX(0, "i2s2_pre", mux_i2s2_p, CLK_SET_RATE_PARENT, - RK1108_CLKSEL_CON(7), 12, 2, MFLAGS); + RV1108_CLKSEL_CON(7), 12, 2, MFLAGS); -static struct rockchip_clk_branch rk1108_clk_branches[] __initdata = { +static struct rockchip_clk_branch rv1108_clk_branches[] __initdata = { MUX(0, "hdmi_phy", mux_hdmiphy_phy_p, CLK_SET_RATE_PARENT, - RK1108_MISC_CON, 13, 2, MFLAGS), + RV1108_MISC_CON, 13, 2, MFLAGS), MUX(0, "usb480m", mux_usb480m_pre_p, CLK_SET_RATE_PARENT, - RK1108_MISC_CON, 15, 2, MFLAGS), + RV1108_MISC_CON, 15, 2, MFLAGS), /* * Clock-Architecture Diagram 2 */ /* PD_CORE */ GATE(0, "dpll_core", "dpll", CLK_IGNORE_UNUSED, - RK1108_CLKGATE_CON(0), 1, GFLAGS), + RV1108_CLKGATE_CON(0), 1, GFLAGS), GATE(0, "apll_core", "apll", CLK_IGNORE_UNUSED, - RK1108_CLKGATE_CON(0), 0, GFLAGS), + RV1108_CLKGATE_CON(0), 0, GFLAGS), GATE(0, "gpll_core", "gpll", CLK_IGNORE_UNUSED, - RK1108_CLKGATE_CON(0), 2, GFLAGS), + RV1108_CLKGATE_CON(0), 2, GFLAGS), COMPOSITE_NOMUX(0, "pclken_dbg", "armclk", CLK_IGNORE_UNUSED, - RK1108_CLKSEL_CON(1), 4, 4, DFLAGS | CLK_DIVIDER_READ_ONLY, - RK1108_CLKGATE_CON(0), 5, GFLAGS), + RV1108_CLKSEL_CON(1), 4, 4, DFLAGS | CLK_DIVIDER_READ_ONLY, + RV1108_CLKGATE_CON(0), 5, GFLAGS), COMPOSITE_NOMUX(ACLK_ENMCORE, "aclkenm_core", "armclk", CLK_IGNORE_UNUSED, - RK1108_CLKSEL_CON(1), 0, 3, DFLAGS | CLK_DIVIDER_READ_ONLY, - RK1108_CLKGATE_CON(0), 4, GFLAGS), + RV1108_CLKSEL_CON(1), 0, 3, DFLAGS | CLK_DIVIDER_READ_ONLY, + RV1108_CLKGATE_CON(0), 4, GFLAGS), GATE(ACLK_CORE, "aclk_core", "aclkenm_core", CLK_IGNORE_UNUSED, - RK1108_CLKGATE_CON(11), 0, GFLAGS), + RV1108_CLKGATE_CON(11), 0, GFLAGS), GATE(0, "pclk_dbg", "pclken_dbg", CLK_IGNORE_UNUSED, - RK1108_CLKGATE_CON(11), 1, GFLAGS), + RV1108_CLKGATE_CON(11), 1, GFLAGS), /* PD_RKVENC */ @@ -202,58 +202,58 @@ static struct rockchip_clk_branch rk1108_clk_branches[] __initdata = { /* PD_PMU_wrapper */ COMPOSITE_NOMUX(0, "pmu_24m_ena", "gpll", CLK_IGNORE_UNUSED, - RK1108_CLKSEL_CON(38), 0, 5, DFLAGS, - RK1108_CLKGATE_CON(8), 12, GFLAGS), + RV1108_CLKSEL_CON(38), 0, 5, DFLAGS, + RV1108_CLKGATE_CON(8), 12, GFLAGS), GATE(0, "pmu", "pmu_24m_ena", CLK_IGNORE_UNUSED, - RK1108_CLKGATE_CON(10), 0, GFLAGS), + RV1108_CLKGATE_CON(10), 0, GFLAGS), GATE(0, "intmem1", "pmu_24m_ena", CLK_IGNORE_UNUSED, - RK1108_CLKGATE_CON(10), 1, GFLAGS), + RV1108_CLKGATE_CON(10), 1, GFLAGS), GATE(0, "gpio0_pmu", "pmu_24m_ena", CLK_IGNORE_UNUSED, - RK1108_CLKGATE_CON(10), 2, GFLAGS), + RV1108_CLKGATE_CON(10), 2, GFLAGS), GATE(0, "pmugrf", "pmu_24m_ena", CLK_IGNORE_UNUSED, - RK1108_CLKGATE_CON(10), 3, GFLAGS), + RV1108_CLKGATE_CON(10), 3, GFLAGS), GATE(0, "pmu_noc", "pmu_24m_ena", CLK_IGNORE_UNUSED, - RK1108_CLKGATE_CON(10), 4, GFLAGS), + RV1108_CLKGATE_CON(10), 4, GFLAGS), GATE(0, "i2c0_pmu_pclk", "pmu_24m_ena", CLK_IGNORE_UNUSED, - RK1108_CLKGATE_CON(10), 5, GFLAGS), + RV1108_CLKGATE_CON(10), 5, GFLAGS), GATE(0, "pwm0_pmu_pclk", "pmu_24m_ena", CLK_IGNORE_UNUSED, - RK1108_CLKGATE_CON(10), 6, GFLAGS), + RV1108_CLKGATE_CON(10), 6, GFLAGS), COMPOSITE(0, "pwm0_pmu_clk", mux_pll_src_2plls_p, CLK_IGNORE_UNUSED, - RK1108_CLKSEL_CON(12), 7, 1, MFLAGS, 0, 7, DFLAGS, - RK1108_CLKGATE_CON(8), 15, GFLAGS), + RV1108_CLKSEL_CON(12), 7, 1, MFLAGS, 0, 7, DFLAGS, + RV1108_CLKGATE_CON(8), 15, GFLAGS), COMPOSITE(0, "i2c0_pmu_clk", mux_pll_src_2plls_p, CLK_IGNORE_UNUSED, - RK1108_CLKSEL_CON(19), 7, 1, MFLAGS, 0, 7, DFLAGS, - RK1108_CLKGATE_CON(8), 14, GFLAGS), + RV1108_CLKSEL_CON(19), 7, 1, MFLAGS, 0, 7, DFLAGS, + RV1108_CLKGATE_CON(8), 14, GFLAGS), GATE(0, "pvtm_pmu", "xin24m", CLK_IGNORE_UNUSED, - RK1108_CLKGATE_CON(8), 13, GFLAGS), + RV1108_CLKGATE_CON(8), 13, GFLAGS), /* * Clock-Architecture Diagram 4 */ COMPOSITE(0, "aclk_vio0_2wrap_occ", mux_pll_src_4plls_p, CLK_IGNORE_UNUSED, - RK1108_CLKSEL_CON(28), 6, 2, MFLAGS, 0, 5, DFLAGS, - RK1108_CLKGATE_CON(6), 0, GFLAGS), + RV1108_CLKSEL_CON(28), 6, 2, MFLAGS, 0, 5, DFLAGS, + RV1108_CLKGATE_CON(6), 0, GFLAGS), GATE(0, "aclk_vio0_pre", "aclk_vio0_2wrap_occ", CLK_IGNORE_UNUSED, - RK1108_CLKGATE_CON(17), 0, GFLAGS), + RV1108_CLKGATE_CON(17), 0, GFLAGS), COMPOSITE_NOMUX(0, "hclk_vio_pre", "aclk_vio0_pre", 0, - RK1108_CLKSEL_CON(29), 0, 5, DFLAGS, - RK1108_CLKGATE_CON(7), 2, GFLAGS), + RV1108_CLKSEL_CON(29), 0, 5, DFLAGS, + RV1108_CLKGATE_CON(7), 2, GFLAGS), COMPOSITE_NOMUX(0, "pclk_vio_pre", "aclk_vio0_pre", 0, - RK1108_CLKSEL_CON(29), 8, 5, DFLAGS, - RK1108_CLKGATE_CON(7), 3, GFLAGS), + RV1108_CLKSEL_CON(29), 8, 5, DFLAGS, + RV1108_CLKGATE_CON(7), 3, GFLAGS), INVERTER(0, "pclk_vip", "ext_vip", - RK1108_CLKSEL_CON(31), 8, IFLAGS), + RV1108_CLKSEL_CON(31), 8, IFLAGS), GATE(0, "pclk_isp_pre", "pclk_vip", CLK_IGNORE_UNUSED, - RK1108_CLKGATE_CON(7), 6, GFLAGS), + RV1108_CLKGATE_CON(7), 6, GFLAGS), GATE(0, "pclk_isp", "pclk_isp_pre", CLK_IGNORE_UNUSED, - RK1108_CLKGATE_CON(18), 10, GFLAGS), + RV1108_CLKGATE_CON(18), 10, GFLAGS), GATE(0, "dclk_hdmiphy_src_gpll", "gpll", CLK_IGNORE_UNUSED, - RK1108_CLKGATE_CON(6), 5, GFLAGS), + RV1108_CLKGATE_CON(6), 5, GFLAGS), GATE(0, "dclk_hdmiphy_src_dpll", "dpll", CLK_IGNORE_UNUSED, - RK1108_CLKGATE_CON(6), 4, GFLAGS), + RV1108_CLKGATE_CON(6), 4, GFLAGS), COMPOSITE_NOGATE(0, "dclk_hdmiphy", mux_dclk_hdmiphy_pre_p, 0, - RK1108_CLKSEL_CON(32), 6, 2, MFLAGS, 8, 6, DFLAGS), + RV1108_CLKSEL_CON(32), 6, 2, MFLAGS, 8, 6, DFLAGS), /* * Clock-Architecture Diagram 5 @@ -262,153 +262,153 @@ static struct rockchip_clk_branch rk1108_clk_branches[] __initdata = { FACTOR(0, "xin12m", "xin24m", 0, 1, 2), COMPOSITE(0, "i2s0_src", mux_pll_src_2plls_p, 0, - RK1108_CLKSEL_CON(5), 8, 1, MFLAGS, 0, 7, DFLAGS, - RK1108_CLKGATE_CON(2), 0, GFLAGS), + RV1108_CLKSEL_CON(5), 8, 1, MFLAGS, 0, 7, DFLAGS, + RV1108_CLKGATE_CON(2), 0, GFLAGS), COMPOSITE_FRACMUX(0, "i2s1_frac", "i2s1_src", CLK_SET_RATE_PARENT, - RK1108_CLKSEL_CON(8), 0, - RK1108_CLKGATE_CON(2), 1, GFLAGS, - &rk1108_i2s0_fracmux), + RV1108_CLKSEL_CON(8), 0, + RV1108_CLKGATE_CON(2), 1, GFLAGS, + &rv1108_i2s0_fracmux), GATE(SCLK_I2S0, "sclk_i2s0", "i2s0_pre", CLK_SET_RATE_PARENT, - RK1108_CLKGATE_CON(2), 2, GFLAGS), + RV1108_CLKGATE_CON(2), 2, GFLAGS), COMPOSITE_NODIV(0, "i2s_out", mux_i2s_out_p, 0, - RK1108_CLKSEL_CON(5), 15, 1, MFLAGS, - RK1108_CLKGATE_CON(2), 3, GFLAGS), + RV1108_CLKSEL_CON(5), 15, 1, MFLAGS, + RV1108_CLKGATE_CON(2), 3, GFLAGS), COMPOSITE(0, "i2s1_src", mux_pll_src_2plls_p, 0, - RK1108_CLKSEL_CON(6), 8, 1, MFLAGS, 0, 7, DFLAGS, - RK1108_CLKGATE_CON(2), 4, GFLAGS), + RV1108_CLKSEL_CON(6), 8, 1, MFLAGS, 0, 7, DFLAGS, + RV1108_CLKGATE_CON(2), 4, GFLAGS), COMPOSITE_FRACMUX(0, "i2s1_frac", "i2s1_src", CLK_SET_RATE_PARENT, RK2928_CLKSEL_CON(9), 0, RK2928_CLKGATE_CON(2), 5, GFLAGS, - &rk1108_i2s1_fracmux), + &rv1108_i2s1_fracmux), GATE(SCLK_I2S1, "sclk_i2s1", "i2s1_pre", CLK_SET_RATE_PARENT, - RK1108_CLKGATE_CON(2), 6, GFLAGS), + RV1108_CLKGATE_CON(2), 6, GFLAGS), COMPOSITE(0, "i2s2_src", mux_pll_src_2plls_p, 0, - RK1108_CLKSEL_CON(7), 8, 1, MFLAGS, 0, 7, DFLAGS, - RK1108_CLKGATE_CON(3), 8, GFLAGS), + RV1108_CLKSEL_CON(7), 8, 1, MFLAGS, 0, 7, DFLAGS, + RV1108_CLKGATE_CON(3), 8, GFLAGS), COMPOSITE_FRACMUX(0, "i2s2_frac", "i2s2_src", CLK_SET_RATE_PARENT, - RK1108_CLKSEL_CON(10), 0, - RK1108_CLKGATE_CON(2), 9, GFLAGS, - &rk1108_i2s2_fracmux), + RV1108_CLKSEL_CON(10), 0, + RV1108_CLKGATE_CON(2), 9, GFLAGS, + &rv1108_i2s2_fracmux), GATE(SCLK_I2S2, "sclk_i2s2", "i2s2_pre", CLK_SET_RATE_PARENT, - RK1108_CLKGATE_CON(2), 10, GFLAGS), + RV1108_CLKGATE_CON(2), 10, GFLAGS), /* PD_BUS */ GATE(0, "aclk_bus_src_gpll", "gpll", CLK_IGNORE_UNUSED, - RK1108_CLKGATE_CON(1), 0, GFLAGS), + RV1108_CLKGATE_CON(1), 0, GFLAGS), GATE(0, "aclk_bus_src_apll", "apll", CLK_IGNORE_UNUSED, - RK1108_CLKGATE_CON(1), 1, GFLAGS), + RV1108_CLKGATE_CON(1), 1, GFLAGS), GATE(0, "aclk_bus_src_dpll", "dpll", CLK_IGNORE_UNUSED, - RK1108_CLKGATE_CON(1), 2, GFLAGS), + RV1108_CLKGATE_CON(1), 2, GFLAGS), COMPOSITE_NOGATE(ACLK_PRE, "aclk_bus_pre", mux_aclk_bus_src_p, 0, - RK1108_CLKSEL_CON(2), 8, 2, MFLAGS, 0, 5, DFLAGS), + RV1108_CLKSEL_CON(2), 8, 2, MFLAGS, 0, 5, DFLAGS), COMPOSITE_NOMUX(0, "hclk_bus_pre", "aclk_bus_2wrap_occ", 0, - RK1108_CLKSEL_CON(3), 0, 5, DFLAGS, - RK1108_CLKGATE_CON(1), 4, GFLAGS), + RV1108_CLKSEL_CON(3), 0, 5, DFLAGS, + RV1108_CLKGATE_CON(1), 4, GFLAGS), COMPOSITE_NOMUX(0, "pclken_bus", "aclk_bus_2wrap_occ", 0, - RK1108_CLKSEL_CON(3), 8, 5, DFLAGS, - RK1108_CLKGATE_CON(1), 5, GFLAGS), + RV1108_CLKSEL_CON(3), 8, 5, DFLAGS, + RV1108_CLKGATE_CON(1), 5, GFLAGS), GATE(0, "pclk_bus_pre", "pclken_bus", CLK_IGNORE_UNUSED, - RK1108_CLKGATE_CON(1), 6, GFLAGS), + RV1108_CLKGATE_CON(1), 6, GFLAGS), GATE(0, "pclk_top_pre", "pclken_bus", CLK_IGNORE_UNUSED, - RK1108_CLKGATE_CON(1), 7, GFLAGS), + RV1108_CLKGATE_CON(1), 7, GFLAGS), GATE(0, "pclk_ddr_pre", "pclken_bus", CLK_IGNORE_UNUSED, - RK1108_CLKGATE_CON(1), 8, GFLAGS), + RV1108_CLKGATE_CON(1), 8, GFLAGS), GATE(0, "clk_timer0", "mux_pll_p", CLK_IGNORE_UNUSED, - RK1108_CLKGATE_CON(1), 9, GFLAGS), + RV1108_CLKGATE_CON(1), 9, GFLAGS), GATE(0, "clk_timer1", "mux_pll_p", CLK_IGNORE_UNUSED, - RK1108_CLKGATE_CON(1), 10, GFLAGS), + RV1108_CLKGATE_CON(1), 10, GFLAGS), GATE(0, "pclk_timer", "pclk_bus_pre", CLK_IGNORE_UNUSED, - RK1108_CLKGATE_CON(13), 4, GFLAGS), + RV1108_CLKGATE_CON(13), 4, GFLAGS), COMPOSITE(0, "uart0_src", mux_pll_src_dpll_gpll_usb480m_p, CLK_IGNORE_UNUSED, - RK1108_CLKSEL_CON(13), 12, 2, MFLAGS, 0, 7, DFLAGS, - RK1108_CLKGATE_CON(3), 1, GFLAGS), + RV1108_CLKSEL_CON(13), 12, 2, MFLAGS, 0, 7, DFLAGS, + RV1108_CLKGATE_CON(3), 1, GFLAGS), COMPOSITE(0, "uart1_src", mux_pll_src_dpll_gpll_usb480m_p, CLK_IGNORE_UNUSED, - RK1108_CLKSEL_CON(14), 12, 2, MFLAGS, 0, 7, DFLAGS, - RK1108_CLKGATE_CON(3), 3, GFLAGS), + RV1108_CLKSEL_CON(14), 12, 2, MFLAGS, 0, 7, DFLAGS, + RV1108_CLKGATE_CON(3), 3, GFLAGS), COMPOSITE(0, "uart21_src", mux_pll_src_dpll_gpll_usb480m_p, CLK_IGNORE_UNUSED, - RK1108_CLKSEL_CON(15), 12, 2, MFLAGS, 0, 7, DFLAGS, - RK1108_CLKGATE_CON(3), 5, GFLAGS), + RV1108_CLKSEL_CON(15), 12, 2, MFLAGS, 0, 7, DFLAGS, + RV1108_CLKGATE_CON(3), 5, GFLAGS), COMPOSITE_FRACMUX(0, "uart0_frac", "uart0_src", CLK_SET_RATE_PARENT, - RK1108_CLKSEL_CON(16), 0, - RK1108_CLKGATE_CON(3), 2, GFLAGS, - &rk1108_uart0_fracmux), + RV1108_CLKSEL_CON(16), 0, + RV1108_CLKGATE_CON(3), 2, GFLAGS, + &rv1108_uart0_fracmux), COMPOSITE_FRACMUX(0, "uart1_frac", "uart1_src", CLK_SET_RATE_PARENT, - RK1108_CLKSEL_CON(17), 0, - RK1108_CLKGATE_CON(3), 4, GFLAGS, - &rk1108_uart1_fracmux), + RV1108_CLKSEL_CON(17), 0, + RV1108_CLKGATE_CON(3), 4, GFLAGS, + &rv1108_uart1_fracmux), COMPOSITE_FRACMUX(0, "uart2_frac", "uart2_src", CLK_SET_RATE_PARENT, - RK1108_CLKSEL_CON(18), 0, - RK1108_CLKGATE_CON(3), 6, GFLAGS, - &rk1108_uart2_fracmux), + RV1108_CLKSEL_CON(18), 0, + RV1108_CLKGATE_CON(3), 6, GFLAGS, + &rv1108_uart2_fracmux), GATE(PCLK_UART0, "pclk_uart0", "pclk_bus_pre", CLK_IGNORE_UNUSED, - RK1108_CLKGATE_CON(13), 10, GFLAGS), + RV1108_CLKGATE_CON(13), 10, GFLAGS), GATE(PCLK_UART1, "pclk_uart1", "pclk_bus_pre", CLK_IGNORE_UNUSED, - RK1108_CLKGATE_CON(13), 11, GFLAGS), + RV1108_CLKGATE_CON(13), 11, GFLAGS), GATE(PCLK_UART2, "pclk_uart2", "pclk_bus_pre", CLK_IGNORE_UNUSED, - RK1108_CLKGATE_CON(13), 12, GFLAGS), + RV1108_CLKGATE_CON(13), 12, GFLAGS), COMPOSITE(0, "clk_i2c1", mux_pll_src_2plls_p, CLK_IGNORE_UNUSED, - RK1108_CLKSEL_CON(19), 15, 2, MFLAGS, 8, 7, DFLAGS, - RK1108_CLKGATE_CON(3), 7, GFLAGS), + RV1108_CLKSEL_CON(19), 15, 2, MFLAGS, 8, 7, DFLAGS, + RV1108_CLKGATE_CON(3), 7, GFLAGS), COMPOSITE(0, "clk_i2c2", mux_pll_src_2plls_p, CLK_IGNORE_UNUSED, - RK1108_CLKSEL_CON(20), 7, 2, MFLAGS, 0, 7, DFLAGS, - RK1108_CLKGATE_CON(3), 8, GFLAGS), + RV1108_CLKSEL_CON(20), 7, 2, MFLAGS, 0, 7, DFLAGS, + RV1108_CLKGATE_CON(3), 8, GFLAGS), COMPOSITE(0, "clk_i2c3", mux_pll_src_2plls_p, CLK_IGNORE_UNUSED, - RK1108_CLKSEL_CON(20), 15, 2, MFLAGS, 8, 7, DFLAGS, - RK1108_CLKGATE_CON(3), 9, GFLAGS), + RV1108_CLKSEL_CON(20), 15, 2, MFLAGS, 8, 7, DFLAGS, + RV1108_CLKGATE_CON(3), 9, GFLAGS), GATE(0, "pclk_i2c1", "pclk_bus_pre", CLK_IGNORE_UNUSED, - RK1108_CLKGATE_CON(13), 0, GFLAGS), + RV1108_CLKGATE_CON(13), 0, GFLAGS), GATE(0, "pclk_i2c2", "pclk_bus_pre", CLK_IGNORE_UNUSED, - RK1108_CLKGATE_CON(13), 1, GFLAGS), + RV1108_CLKGATE_CON(13), 1, GFLAGS), GATE(0, "pclk_i2c3", "pclk_bus_pre", CLK_IGNORE_UNUSED, - RK1108_CLKGATE_CON(13), 2, GFLAGS), + RV1108_CLKGATE_CON(13), 2, GFLAGS), COMPOSITE(0, "clk_pwm1", mux_pll_src_2plls_p, CLK_IGNORE_UNUSED, - RK1108_CLKSEL_CON(12), 15, 2, MFLAGS, 8, 7, DFLAGS, - RK1108_CLKGATE_CON(3), 10, GFLAGS), + RV1108_CLKSEL_CON(12), 15, 2, MFLAGS, 8, 7, DFLAGS, + RV1108_CLKGATE_CON(3), 10, GFLAGS), GATE(0, "pclk_pwm1", "pclk_bus_pre", CLK_IGNORE_UNUSED, - RK1108_CLKGATE_CON(13), 6, GFLAGS), + RV1108_CLKGATE_CON(13), 6, GFLAGS), GATE(0, "pclk_wdt", "pclk_bus_pre", CLK_IGNORE_UNUSED, - RK1108_CLKGATE_CON(13), 3, GFLAGS), + RV1108_CLKGATE_CON(13), 3, GFLAGS), GATE(0, "pclk_gpio1", "pclk_bus_pre", CLK_IGNORE_UNUSED, - RK1108_CLKGATE_CON(13), 7, GFLAGS), + RV1108_CLKGATE_CON(13), 7, GFLAGS), GATE(0, "pclk_gpio2", "pclk_bus_pre", CLK_IGNORE_UNUSED, - RK1108_CLKGATE_CON(13), 8, GFLAGS), + RV1108_CLKGATE_CON(13), 8, GFLAGS), GATE(0, "pclk_gpio3", "pclk_bus_pre", CLK_IGNORE_UNUSED, - RK1108_CLKGATE_CON(13), 9, GFLAGS), + RV1108_CLKGATE_CON(13), 9, GFLAGS), GATE(0, "pclk_grf", "pclk_bus_pre", CLK_IGNORE_UNUSED, - RK1108_CLKGATE_CON(14), 0, GFLAGS), + RV1108_CLKGATE_CON(14), 0, GFLAGS), GATE(ACLK_DMAC, "aclk_dmac", "aclk_bus_pre", 0, - RK1108_CLKGATE_CON(12), 2, GFLAGS), + RV1108_CLKGATE_CON(12), 2, GFLAGS), GATE(0, "hclk_rom", "hclk_bus_pre", CLK_IGNORE_UNUSED, - RK1108_CLKGATE_CON(12), 3, GFLAGS), + RV1108_CLKGATE_CON(12), 3, GFLAGS), GATE(0, "aclk_intmem", "aclk_bus_pre", CLK_IGNORE_UNUSED, - RK1108_CLKGATE_CON(12), 1, GFLAGS), + RV1108_CLKGATE_CON(12), 1, GFLAGS), /* PD_DDR */ GATE(0, "apll_ddr", "apll", CLK_IGNORE_UNUSED, - RK1108_CLKGATE_CON(0), 8, GFLAGS), + RV1108_CLKGATE_CON(0), 8, GFLAGS), GATE(0, "dpll_ddr", "dpll", CLK_IGNORE_UNUSED, - RK1108_CLKGATE_CON(0), 9, GFLAGS), + RV1108_CLKGATE_CON(0), 9, GFLAGS), GATE(0, "gpll_ddr", "gpll", CLK_IGNORE_UNUSED, - RK1108_CLKGATE_CON(0), 10, GFLAGS), + RV1108_CLKGATE_CON(0), 10, GFLAGS), COMPOSITE(0, "ddrphy4x", mux_ddrphy_p, CLK_IGNORE_UNUSED, - RK1108_CLKSEL_CON(4), 8, 2, MFLAGS, 0, 3, + RV1108_CLKSEL_CON(4), 8, 2, MFLAGS, 0, 3, DFLAGS | CLK_DIVIDER_POWER_OF_TWO, - RK1108_CLKGATE_CON(10), 9, GFLAGS), + RV1108_CLKGATE_CON(10), 9, GFLAGS), GATE(0, "ddrupctl", "ddrphy_pre", CLK_IGNORE_UNUSED, - RK1108_CLKGATE_CON(12), 4, GFLAGS), + RV1108_CLKGATE_CON(12), 4, GFLAGS), GATE(0, "ddrc", "ddrphy", CLK_IGNORE_UNUSED, - RK1108_CLKGATE_CON(12), 5, GFLAGS), + RV1108_CLKGATE_CON(12), 5, GFLAGS), GATE(0, "ddrmon", "ddrphy_pre", CLK_IGNORE_UNUSED, - RK1108_CLKGATE_CON(12), 6, GFLAGS), + RV1108_CLKGATE_CON(12), 6, GFLAGS), GATE(0, "timer_clk", "xin24m", CLK_IGNORE_UNUSED, - RK1108_CLKGATE_CON(0), 11, GFLAGS), + RV1108_CLKGATE_CON(0), 11, GFLAGS), /* * Clock-Architecture Diagram 6 @@ -416,73 +416,73 @@ static struct rockchip_clk_branch rk1108_clk_branches[] __initdata = { /* PD_PERI */ COMPOSITE_NOMUX(0, "pclk_periph_pre", "gpll", 0, - RK1108_CLKSEL_CON(23), 10, 5, DFLAGS, - RK1108_CLKGATE_CON(4), 5, GFLAGS), + RV1108_CLKSEL_CON(23), 10, 5, DFLAGS, + RV1108_CLKGATE_CON(4), 5, GFLAGS), GATE(0, "pclk_periph", "pclk_periph_pre", CLK_IGNORE_UNUSED, - RK1108_CLKGATE_CON(15), 13, GFLAGS), + RV1108_CLKGATE_CON(15), 13, GFLAGS), COMPOSITE_NOMUX(0, "hclk_periph_pre", "gpll", 0, - RK1108_CLKSEL_CON(23), 5, 5, DFLAGS, - RK1108_CLKGATE_CON(4), 4, GFLAGS), + RV1108_CLKSEL_CON(23), 5, 5, DFLAGS, + RV1108_CLKGATE_CON(4), 4, GFLAGS), GATE(0, "hclk_periph", "hclk_periph_pre", CLK_IGNORE_UNUSED, - RK1108_CLKGATE_CON(15), 12, GFLAGS), + RV1108_CLKGATE_CON(15), 12, GFLAGS), GATE(0, "aclk_peri_src_dpll", "dpll", CLK_IGNORE_UNUSED, - RK1108_CLKGATE_CON(4), 1, GFLAGS), + RV1108_CLKGATE_CON(4), 1, GFLAGS), GATE(0, "aclk_peri_src_gpll", "gpll", CLK_IGNORE_UNUSED, - RK1108_CLKGATE_CON(4), 2, GFLAGS), + RV1108_CLKGATE_CON(4), 2, GFLAGS), COMPOSITE(0, "aclk_periph", mux_aclk_peri_src_p, CLK_IGNORE_UNUSED, - RK1108_CLKSEL_CON(23), 15, 2, MFLAGS, 0, 5, DFLAGS, - RK1108_CLKGATE_CON(15), 11, GFLAGS), + RV1108_CLKSEL_CON(23), 15, 2, MFLAGS, 0, 5, DFLAGS, + RV1108_CLKGATE_CON(15), 11, GFLAGS), COMPOSITE(SCLK_SDMMC, "sclk_sdmmc0", mux_mmc_src_p, 0, - RK1108_CLKSEL_CON(25), 8, 2, MFLAGS, 0, 8, DFLAGS, - RK1108_CLKGATE_CON(5), 0, GFLAGS), + RV1108_CLKSEL_CON(25), 8, 2, MFLAGS, 0, 8, DFLAGS, + RV1108_CLKGATE_CON(5), 0, GFLAGS), COMPOSITE_NODIV(0, "sclk_sdio_src", mux_mmc_src_p, 0, - RK1108_CLKSEL_CON(25), 10, 2, MFLAGS, - RK1108_CLKGATE_CON(5), 2, GFLAGS), + RV1108_CLKSEL_CON(25), 10, 2, MFLAGS, + RV1108_CLKGATE_CON(5), 2, GFLAGS), DIV(SCLK_SDIO, "sclk_sdio", "sclk_sdio_src", 0, - RK1108_CLKSEL_CON(26), 0, 8, DFLAGS), + RV1108_CLKSEL_CON(26), 0, 8, DFLAGS), COMPOSITE_NODIV(0, "sclk_emmc_src", mux_mmc_src_p, 0, - RK1108_CLKSEL_CON(25), 12, 2, MFLAGS, - RK1108_CLKGATE_CON(5), 1, GFLAGS), + RV1108_CLKSEL_CON(25), 12, 2, MFLAGS, + RV1108_CLKGATE_CON(5), 1, GFLAGS), DIV(SCLK_EMMC, "sclk_emmc", "sclk_emmc_src", 0, RK2928_CLKSEL_CON(26), 8, 8, DFLAGS), - GATE(HCLK_SDMMC, "hclk_sdmmc", "hclk_periph", 0, RK1108_CLKGATE_CON(15), 0, GFLAGS), - GATE(HCLK_SDIO, "hclk_sdio", "hclk_periph", 0, RK1108_CLKGATE_CON(15), 1, GFLAGS), - GATE(HCLK_EMMC, "hclk_emmc", "hclk_periph", 0, RK1108_CLKGATE_CON(15), 2, GFLAGS), + GATE(HCLK_SDMMC, "hclk_sdmmc", "hclk_periph", 0, RV1108_CLKGATE_CON(15), 0, GFLAGS), + GATE(HCLK_SDIO, "hclk_sdio", "hclk_periph", 0, RV1108_CLKGATE_CON(15), 1, GFLAGS), + GATE(HCLK_EMMC, "hclk_emmc", "hclk_periph", 0, RV1108_CLKGATE_CON(15), 2, GFLAGS), COMPOSITE(SCLK_NANDC, "sclk_nandc", mux_pll_src_2plls_p, 0, - RK1108_CLKSEL_CON(27), 14, 2, MFLAGS, 8, 5, DFLAGS, - RK1108_CLKGATE_CON(5), 3, GFLAGS), - GATE(HCLK_NANDC, "hclk_nandc", "hclk_periph", 0, RK1108_CLKGATE_CON(15), 3, GFLAGS), + RV1108_CLKSEL_CON(27), 14, 2, MFLAGS, 8, 5, DFLAGS, + RV1108_CLKGATE_CON(5), 3, GFLAGS), + GATE(HCLK_NANDC, "hclk_nandc", "hclk_periph", 0, RV1108_CLKGATE_CON(15), 3, GFLAGS), COMPOSITE(SCLK_SFC, "sclk_sfc", mux_pll_src_2plls_p, 0, - RK1108_CLKSEL_CON(27), 7, 2, MFLAGS, 0, 7, DFLAGS, - RK1108_CLKGATE_CON(5), 4, GFLAGS), - GATE(HCLK_SFC, "hclk_sfc", "hclk_periph", 0, RK1108_CLKGATE_CON(15), 10, GFLAGS), + RV1108_CLKSEL_CON(27), 7, 2, MFLAGS, 0, 7, DFLAGS, + RV1108_CLKGATE_CON(5), 4, GFLAGS), + GATE(HCLK_SFC, "hclk_sfc", "hclk_periph", 0, RV1108_CLKGATE_CON(15), 10, GFLAGS), COMPOSITE(0, "sclk_macphy_pre", mux_pll_src_apll_gpll_p, 0, - RK1108_CLKSEL_CON(24), 12, 2, MFLAGS, 0, 5, DFLAGS, - RK1108_CLKGATE_CON(4), 10, GFLAGS), + RV1108_CLKSEL_CON(24), 12, 2, MFLAGS, 0, 5, DFLAGS, + RV1108_CLKGATE_CON(4), 10, GFLAGS), MUX(0, "sclk_macphy", mux_sclk_macphy_p, CLK_SET_RATE_PARENT, - RK1108_CLKSEL_CON(24), 8, 2, MFLAGS), - GATE(0, "sclk_macphy_rx", "sclk_macphy", 0, RK1108_CLKGATE_CON(4), 8, GFLAGS), - GATE(0, "sclk_mac_ref", "sclk_macphy", 0, RK1108_CLKGATE_CON(4), 6, GFLAGS), - GATE(0, "sclk_mac_refout", "sclk_macphy", 0, RK1108_CLKGATE_CON(4), 7, GFLAGS), + RV1108_CLKSEL_CON(24), 8, 2, MFLAGS), + GATE(0, "sclk_macphy_rx", "sclk_macphy", 0, RV1108_CLKGATE_CON(4), 8, GFLAGS), + GATE(0, "sclk_mac_ref", "sclk_macphy", 0, RV1108_CLKGATE_CON(4), 6, GFLAGS), + GATE(0, "sclk_mac_refout", "sclk_macphy", 0, RV1108_CLKGATE_CON(4), 7, GFLAGS), - MMC(SCLK_SDMMC_DRV, "sdmmc_drv", "sclk_sdmmc", RK1108_SDMMC_CON0, 1), - MMC(SCLK_SDMMC_SAMPLE, "sdmmc_sample", "sclk_sdmmc", RK1108_SDMMC_CON1, 1), + MMC(SCLK_SDMMC_DRV, "sdmmc_drv", "sclk_sdmmc", RV1108_SDMMC_CON0, 1), + MMC(SCLK_SDMMC_SAMPLE, "sdmmc_sample", "sclk_sdmmc", RV1108_SDMMC_CON1, 1), - MMC(SCLK_SDIO_DRV, "sdio_drv", "sclk_sdio", RK1108_SDIO_CON0, 1), - MMC(SCLK_SDIO_SAMPLE, "sdio_sample", "sclk_sdio", RK1108_SDIO_CON1, 1), + MMC(SCLK_SDIO_DRV, "sdio_drv", "sclk_sdio", RV1108_SDIO_CON0, 1), + MMC(SCLK_SDIO_SAMPLE, "sdio_sample", "sclk_sdio", RV1108_SDIO_CON1, 1), - MMC(SCLK_EMMC_DRV, "emmc_drv", "sclk_emmc", RK1108_EMMC_CON0, 1), - MMC(SCLK_EMMC_SAMPLE, "emmc_sample", "sclk_emmc", RK1108_EMMC_CON1, 1), + MMC(SCLK_EMMC_DRV, "emmc_drv", "sclk_emmc", RV1108_EMMC_CON0, 1), + MMC(SCLK_EMMC_SAMPLE, "emmc_sample", "sclk_emmc", RV1108_EMMC_CON1, 1), }; -static const char *const rk1108_critical_clocks[] __initconst = { +static const char *const rv1108_critical_clocks[] __initconst = { "aclk_core", "aclk_bus_src_gpll", "aclk_periph", @@ -490,7 +490,7 @@ static const char *const rk1108_critical_clocks[] __initconst = { "pclk_periph", }; -static void __init rk1108_clk_init(struct device_node *np) +static void __init rv1108_clk_init(struct device_node *np) { struct rockchip_clk_provider *ctx; void __iomem *reg_base; @@ -508,24 +508,24 @@ static void __init rk1108_clk_init(struct device_node *np) return; } - rockchip_clk_register_plls(ctx, rk1108_pll_clks, - ARRAY_SIZE(rk1108_pll_clks), - RK1108_GRF_SOC_STATUS0); - rockchip_clk_register_branches(ctx, rk1108_clk_branches, - ARRAY_SIZE(rk1108_clk_branches)); - rockchip_clk_protect_critical(rk1108_critical_clocks, - ARRAY_SIZE(rk1108_critical_clocks)); + rockchip_clk_register_plls(ctx, rv1108_pll_clks, + ARRAY_SIZE(rv1108_pll_clks), + RV1108_GRF_SOC_STATUS0); + rockchip_clk_register_branches(ctx, rv1108_clk_branches, + ARRAY_SIZE(rv1108_clk_branches)); + rockchip_clk_protect_critical(rv1108_critical_clocks, + ARRAY_SIZE(rv1108_critical_clocks)); rockchip_clk_register_armclk(ctx, ARMCLK, "armclk", mux_armclk_p, ARRAY_SIZE(mux_armclk_p), - &rk1108_cpuclk_data, rk1108_cpuclk_rates, - ARRAY_SIZE(rk1108_cpuclk_rates)); + &rv1108_cpuclk_data, rv1108_cpuclk_rates, + ARRAY_SIZE(rv1108_cpuclk_rates)); - rockchip_register_softrst(np, 13, reg_base + RK1108_SOFTRST_CON(0), + rockchip_register_softrst(np, 13, reg_base + RV1108_SOFTRST_CON(0), ROCKCHIP_SOFTRST_HIWORD_MASK); - rockchip_register_restart_notifier(ctx, RK1108_GLB_SRST_FST, NULL); + rockchip_register_restart_notifier(ctx, RV1108_GLB_SRST_FST, NULL); rockchip_clk_of_add_provider(np, ctx); } -CLK_OF_DECLARE(rk1108_cru, "rockchip,rk1108-cru", rk1108_clk_init); +CLK_OF_DECLARE(rv1108_cru, "rockchip,rv1108-cru", rv1108_clk_init); diff --git a/drivers/clk/rockchip/clk.h b/drivers/clk/rockchip/clk.h index 7c15473ea72b..ef601dded32c 100644 --- a/drivers/clk/rockchip/clk.h +++ b/drivers/clk/rockchip/clk.h @@ -34,20 +34,20 @@ struct clk; #define HIWORD_UPDATE(val, mask, shift) \ ((val) << (shift) | (mask) << ((shift) + 16)) -/* register positions shared by RK1108, RK2928, RK3036, RK3066, RK3188 and RK3228 */ -#define RK1108_PLL_CON(x) ((x) * 0x4) -#define RK1108_CLKSEL_CON(x) ((x) * 0x4 + 0x60) -#define RK1108_CLKGATE_CON(x) ((x) * 0x4 + 0x120) -#define RK1108_SOFTRST_CON(x) ((x) * 0x4 + 0x180) -#define RK1108_GLB_SRST_FST 0x1c0 -#define RK1108_GLB_SRST_SND 0x1c4 -#define RK1108_MISC_CON 0x1cc -#define RK1108_SDMMC_CON0 0x1d8 -#define RK1108_SDMMC_CON1 0x1dc -#define RK1108_SDIO_CON0 0x1e0 -#define RK1108_SDIO_CON1 0x1e4 -#define RK1108_EMMC_CON0 0x1e8 -#define RK1108_EMMC_CON1 0x1ec +/* register positions shared by RV1108, RK2928, RK3036, RK3066, RK3188 and RK3228 */ +#define RV1108_PLL_CON(x) ((x) * 0x4) +#define RV1108_CLKSEL_CON(x) ((x) * 0x4 + 0x60) +#define RV1108_CLKGATE_CON(x) ((x) * 0x4 + 0x120) +#define RV1108_SOFTRST_CON(x) ((x) * 0x4 + 0x180) +#define RV1108_GLB_SRST_FST 0x1c0 +#define RV1108_GLB_SRST_SND 0x1c4 +#define RV1108_MISC_CON 0x1cc +#define RV1108_SDMMC_CON0 0x1d8 +#define RV1108_SDMMC_CON1 0x1dc +#define RV1108_SDIO_CON0 0x1e0 +#define RV1108_SDIO_CON1 0x1e4 +#define RV1108_EMMC_CON0 0x1e8 +#define RV1108_EMMC_CON1 0x1ec #define RK2928_PLL_CON(x) ((x) * 0x4) #define RK2928_MODE_CON 0x40 diff --git a/drivers/clk/sunxi-ng/Kconfig b/drivers/clk/sunxi-ng/Kconfig index 056752317aee..64088e599404 100644 --- a/drivers/clk/sunxi-ng/Kconfig +++ b/drivers/clk/sunxi-ng/Kconfig @@ -1,6 +1,7 @@ config SUNXI_CCU bool "Clock support for Allwinner SoCs" depends on ARCH_SUNXI || COMPILE_TEST + select RESET_CONTROLLER default ARCH_SUNXI if SUNXI_CCU @@ -142,6 +143,7 @@ config SUN8I_V3S_CCU config SUN9I_A80_CCU bool "Support for the Allwinner A80 CCU" select SUNXI_CCU_DIV + select SUNXI_CCU_MULT select SUNXI_CCU_GATE select SUNXI_CCU_NKMP select SUNXI_CCU_NM diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-a64.c b/drivers/clk/sunxi-ng/ccu-sun50i-a64.c index e3c084cc6da5..f54114c607df 100644 --- a/drivers/clk/sunxi-ng/ccu-sun50i-a64.c +++ b/drivers/clk/sunxi-ng/ccu-sun50i-a64.c @@ -566,7 +566,7 @@ static SUNXI_CCU_M_WITH_GATE(gpu_clk, "gpu", "pll-gpu", 0x1a0, 0, 3, BIT(31), CLK_SET_RATE_PARENT); /* Fixed Factor clocks */ -static CLK_FIXED_FACTOR(osc12M_clk, "osc12M", "osc24M", 1, 2, 0); +static CLK_FIXED_FACTOR(osc12M_clk, "osc12M", "osc24M", 2, 1, 0); /* We hardcode the divider to 4 for now */ static CLK_FIXED_FACTOR(pll_audio_clk, "pll-audio", diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-a33.c b/drivers/clk/sunxi-ng/ccu-sun8i-a33.c index 56370c2c7f98..8d38e6510e29 100644 --- a/drivers/clk/sunxi-ng/ccu-sun8i-a33.c +++ b/drivers/clk/sunxi-ng/ccu-sun8i-a33.c @@ -756,6 +756,13 @@ static const struct sunxi_ccu_desc sun8i_a33_ccu_desc = { .num_resets = ARRAY_SIZE(sun8i_a33_ccu_resets), }; +static struct ccu_pll_nb sun8i_a33_pll_cpu_nb = { + .common = &pll_cpux_clk.common, + /* copy from pll_cpux_clk */ + .enable = BIT(31), + .lock = BIT(28), +}; + static struct ccu_mux_nb sun8i_a33_cpu_nb = { .common = &cpux_clk.common, .cm = &cpux_clk.mux, @@ -787,6 +794,10 @@ static void __init sun8i_a33_ccu_setup(struct device_node *node) sunxi_ccu_probe(node, reg, &sun8i_a33_ccu_desc); + /* Gate then ungate PLL CPU after any rate changes */ + ccu_pll_notifier_register(&sun8i_a33_pll_cpu_nb); + + /* Reparent CPU during PLL CPU rate changes */ ccu_mux_notifier_register(pll_cpux_clk.common.hw.clk, &sun8i_a33_cpu_nb); } diff --git a/drivers/clk/sunxi-ng/ccu_common.c b/drivers/clk/sunxi-ng/ccu_common.c index 188fa50d0380..40aac316128f 100644 --- a/drivers/clk/sunxi-ng/ccu_common.c +++ b/drivers/clk/sunxi-ng/ccu_common.c @@ -14,11 +14,13 @@ * GNU General Public License for more details. */ +#include <linux/clk.h> #include <linux/clk-provider.h> #include <linux/iopoll.h> #include <linux/slab.h> #include "ccu_common.h" +#include "ccu_gate.h" #include "ccu_reset.h" static DEFINE_SPINLOCK(ccu_lock); @@ -39,6 +41,53 @@ void ccu_helper_wait_for_lock(struct ccu_common *common, u32 lock) WARN_ON(readl_relaxed_poll_timeout(addr, reg, reg & lock, 100, 70000)); } +/* + * This clock notifier is called when the frequency of a PLL clock is + * changed. In common PLL designs, changes to the dividers take effect + * almost immediately, while changes to the multipliers (implemented + * as dividers in the feedback loop) take a few cycles to work into + * the feedback loop for the PLL to stablize. + * + * Sometimes when the PLL clock rate is changed, the decrease in the + * divider is too much for the decrease in the multiplier to catch up. + * The PLL clock rate will spike, and in some cases, might lock up + * completely. + * + * This notifier callback will gate and then ungate the clock, + * effectively resetting it, so it proceeds to work. Care must be + * taken to reparent consumers to other temporary clocks during the + * rate change, and that this notifier callback must be the first + * to be registered. + */ +static int ccu_pll_notifier_cb(struct notifier_block *nb, + unsigned long event, void *data) +{ + struct ccu_pll_nb *pll = to_ccu_pll_nb(nb); + int ret = 0; + + if (event != POST_RATE_CHANGE) + goto out; + + ccu_gate_helper_disable(pll->common, pll->enable); + + ret = ccu_gate_helper_enable(pll->common, pll->enable); + if (ret) + goto out; + + ccu_helper_wait_for_lock(pll->common, pll->lock); + +out: + return notifier_from_errno(ret); +} + +int ccu_pll_notifier_register(struct ccu_pll_nb *pll_nb) +{ + pll_nb->clk_nb.notifier_call = ccu_pll_notifier_cb; + + return clk_notifier_register(pll_nb->common->hw.clk, + &pll_nb->clk_nb); +} + int sunxi_ccu_probe(struct device_node *node, void __iomem *reg, const struct sunxi_ccu_desc *desc) { diff --git a/drivers/clk/sunxi-ng/ccu_common.h b/drivers/clk/sunxi-ng/ccu_common.h index 73d81dc58fc5..d6fdd7a789aa 100644 --- a/drivers/clk/sunxi-ng/ccu_common.h +++ b/drivers/clk/sunxi-ng/ccu_common.h @@ -83,6 +83,18 @@ struct sunxi_ccu_desc { void ccu_helper_wait_for_lock(struct ccu_common *common, u32 lock); +struct ccu_pll_nb { + struct notifier_block clk_nb; + struct ccu_common *common; + + u32 enable; + u32 lock; +}; + +#define to_ccu_pll_nb(_nb) container_of(_nb, struct ccu_pll_nb, clk_nb) + +int ccu_pll_notifier_register(struct ccu_pll_nb *pll_nb); + int sunxi_ccu_probe(struct device_node *node, void __iomem *reg, const struct sunxi_ccu_desc *desc); diff --git a/drivers/clk/sunxi-ng/ccu_nkmp.c b/drivers/clk/sunxi-ng/ccu_nkmp.c index a2b40a000157..488055ed944f 100644 --- a/drivers/clk/sunxi-ng/ccu_nkmp.c +++ b/drivers/clk/sunxi-ng/ccu_nkmp.c @@ -107,7 +107,7 @@ static unsigned long ccu_nkmp_recalc_rate(struct clk_hw *hw, p = reg >> nkmp->p.shift; p &= (1 << nkmp->p.width) - 1; - return parent_rate * n * k >> p / m; + return (parent_rate * n * k >> p) / m; } static long ccu_nkmp_round_rate(struct clk_hw *hw, unsigned long rate, diff --git a/drivers/clk/tegra/clk-id.h b/drivers/clk/tegra/clk-id.h index 5738635c5274..689f344377a7 100644 --- a/drivers/clk/tegra/clk-id.h +++ b/drivers/clk/tegra/clk-id.h @@ -307,6 +307,23 @@ enum clk_id { tegra_clk_xusb_ssp_src, tegra_clk_sclk_mux, tegra_clk_sor_safe, + tegra_clk_cec, + tegra_clk_ispa, + tegra_clk_dmic1, + tegra_clk_dmic2, + tegra_clk_dmic3, + tegra_clk_dmic1_sync_clk, + tegra_clk_dmic2_sync_clk, + tegra_clk_dmic3_sync_clk, + tegra_clk_dmic1_sync_clk_mux, + tegra_clk_dmic2_sync_clk_mux, + tegra_clk_dmic3_sync_clk_mux, + tegra_clk_iqc1, + tegra_clk_iqc2, + tegra_clk_pll_a_out_adsp, + tegra_clk_pll_a_out0_out_adsp, + tegra_clk_adsp, + tegra_clk_adsp_neon, tegra_clk_max, }; diff --git a/drivers/clk/tegra/clk-periph-gate.c b/drivers/clk/tegra/clk-periph-gate.c index 88127828befe..303ef32ee3f1 100644 --- a/drivers/clk/tegra/clk-periph-gate.c +++ b/drivers/clk/tegra/clk-periph-gate.c @@ -159,6 +159,9 @@ struct clk *tegra_clk_register_periph_gate(const char *name, gate->enable_refcnt = enable_refcnt; gate->regs = pregs; + if (read_enb(gate) & periph_clk_to_bit(gate)) + enable_refcnt[clk_num]++; + /* Data in .init is copied by clk_register(), so stack variable OK */ gate->hw.init = &init; diff --git a/drivers/clk/tegra/clk-periph.c b/drivers/clk/tegra/clk-periph.c index a17ca6d7f649..cf80831de79d 100644 --- a/drivers/clk/tegra/clk-periph.c +++ b/drivers/clk/tegra/clk-periph.c @@ -138,7 +138,7 @@ static const struct clk_ops tegra_clk_periph_no_gate_ops = { }; static struct clk *_tegra_clk_register_periph(const char *name, - const char **parent_names, int num_parents, + const char * const *parent_names, int num_parents, struct tegra_clk_periph *periph, void __iomem *clk_base, u32 offset, unsigned long flags) @@ -186,7 +186,7 @@ static struct clk *_tegra_clk_register_periph(const char *name, } struct clk *tegra_clk_register_periph(const char *name, - const char **parent_names, int num_parents, + const char * const *parent_names, int num_parents, struct tegra_clk_periph *periph, void __iomem *clk_base, u32 offset, unsigned long flags) { @@ -195,7 +195,7 @@ struct clk *tegra_clk_register_periph(const char *name, } struct clk *tegra_clk_register_periph_nodiv(const char *name, - const char **parent_names, int num_parents, + const char * const *parent_names, int num_parents, struct tegra_clk_periph *periph, void __iomem *clk_base, u32 offset) { diff --git a/drivers/clk/tegra/clk-pll.c b/drivers/clk/tegra/clk-pll.c index b3855360d6bc..159a854779e6 100644 --- a/drivers/clk/tegra/clk-pll.c +++ b/drivers/clk/tegra/clk-pll.c @@ -2517,152 +2517,6 @@ static int clk_plle_tegra210_is_enabled(struct clk_hw *hw) return val & PLLE_BASE_ENABLE ? 1 : 0; } -static int clk_pllu_tegra210_enable(struct clk_hw *hw) -{ - struct tegra_clk_pll *pll = to_clk_pll(hw); - struct clk_hw *pll_ref = clk_hw_get_parent(hw); - struct clk_hw *osc = clk_hw_get_parent(pll_ref); - const struct utmi_clk_param *params = NULL; - unsigned long flags = 0, input_rate; - unsigned int i; - int ret = 0; - u32 value; - - if (!osc) { - pr_err("%s: failed to get OSC clock\n", __func__); - return -EINVAL; - } - - input_rate = clk_hw_get_rate(osc); - - if (pll->lock) - spin_lock_irqsave(pll->lock, flags); - - _clk_pll_enable(hw); - - ret = clk_pll_wait_for_lock(pll); - if (ret < 0) - goto out; - - for (i = 0; i < ARRAY_SIZE(utmi_parameters); i++) { - if (input_rate == utmi_parameters[i].osc_frequency) { - params = &utmi_parameters[i]; - break; - } - } - - if (!params) { - pr_err("%s: unexpected input rate %lu Hz\n", __func__, - input_rate); - ret = -EINVAL; - goto out; - } - - value = pll_readl_base(pll); - value &= ~PLLU_BASE_OVERRIDE; - pll_writel_base(value, pll); - - /* Put PLLU under HW control */ - value = readl_relaxed(pll->clk_base + PLLU_HW_PWRDN_CFG0); - value |= PLLU_HW_PWRDN_CFG0_IDDQ_PD_INCLUDE | - PLLU_HW_PWRDN_CFG0_USE_SWITCH_DETECT | - PLLU_HW_PWRDN_CFG0_USE_LOCKDET; - value &= ~(PLLU_HW_PWRDN_CFG0_CLK_ENABLE_SWCTL | - PLLU_HW_PWRDN_CFG0_CLK_SWITCH_SWCTL); - writel_relaxed(value, pll->clk_base + PLLU_HW_PWRDN_CFG0); - - value = readl_relaxed(pll->clk_base + XUSB_PLL_CFG0); - value &= ~XUSB_PLL_CFG0_PLLU_LOCK_DLY; - writel_relaxed(value, pll->clk_base + XUSB_PLL_CFG0); - - udelay(1); - - value = readl_relaxed(pll->clk_base + PLLU_HW_PWRDN_CFG0); - value |= PLLU_HW_PWRDN_CFG0_SEQ_ENABLE; - writel_relaxed(value, pll->clk_base + PLLU_HW_PWRDN_CFG0); - - udelay(1); - - /* Disable PLLU clock branch to UTMIPLL since it uses OSC */ - value = pll_readl_base(pll); - value &= ~PLLU_BASE_CLKENABLE_USB; - pll_writel_base(value, pll); - - value = readl_relaxed(pll->clk_base + UTMIPLL_HW_PWRDN_CFG0); - if (value & UTMIPLL_HW_PWRDN_CFG0_SEQ_ENABLE) { - pr_debug("UTMIPLL already enabled\n"); - goto out; - } - - value &= ~UTMIPLL_HW_PWRDN_CFG0_IDDQ_OVERRIDE; - writel_relaxed(value, pll->clk_base + UTMIPLL_HW_PWRDN_CFG0); - - /* Program UTMIP PLL stable and active counts */ - value = readl_relaxed(pll->clk_base + UTMIP_PLL_CFG2); - value &= ~UTMIP_PLL_CFG2_STABLE_COUNT(~0); - value |= UTMIP_PLL_CFG2_STABLE_COUNT(params->stable_count); - value &= ~UTMIP_PLL_CFG2_ACTIVE_DLY_COUNT(~0); - value |= UTMIP_PLL_CFG2_ACTIVE_DLY_COUNT(params->active_delay_count); - value |= UTMIP_PLL_CFG2_PHY_XTAL_CLOCKEN; - writel_relaxed(value, pll->clk_base + UTMIP_PLL_CFG2); - - /* Program UTMIP PLL delay and oscillator frequency counts */ - value = readl_relaxed(pll->clk_base + UTMIP_PLL_CFG1); - value &= ~UTMIP_PLL_CFG1_ENABLE_DLY_COUNT(~0); - value |= UTMIP_PLL_CFG1_ENABLE_DLY_COUNT(params->enable_delay_count); - value &= ~UTMIP_PLL_CFG1_XTAL_FREQ_COUNT(~0); - value |= UTMIP_PLL_CFG1_XTAL_FREQ_COUNT(params->xtal_freq_count); - writel_relaxed(value, pll->clk_base + UTMIP_PLL_CFG1); - - /* Remove power downs from UTMIP PLL control bits */ - value = readl_relaxed(pll->clk_base + UTMIP_PLL_CFG1); - value &= ~UTMIP_PLL_CFG1_FORCE_PLL_ENABLE_POWERDOWN; - value |= UTMIP_PLL_CFG1_FORCE_PLL_ENABLE_POWERUP; - writel(value, pll->clk_base + UTMIP_PLL_CFG1); - - udelay(1); - - /* Enable samplers for SNPS, XUSB_HOST, XUSB_DEV */ - value = readl_relaxed(pll->clk_base + UTMIP_PLL_CFG2); - value |= UTMIP_PLL_CFG2_FORCE_PD_SAMP_A_POWERUP; - value |= UTMIP_PLL_CFG2_FORCE_PD_SAMP_B_POWERUP; - value |= UTMIP_PLL_CFG2_FORCE_PD_SAMP_D_POWERUP; - value &= ~UTMIP_PLL_CFG2_FORCE_PD_SAMP_A_POWERDOWN; - value &= ~UTMIP_PLL_CFG2_FORCE_PD_SAMP_B_POWERDOWN; - value &= ~UTMIP_PLL_CFG2_FORCE_PD_SAMP_D_POWERDOWN; - writel_relaxed(value, pll->clk_base + UTMIP_PLL_CFG2); - - /* Setup HW control of UTMIPLL */ - value = readl_relaxed(pll->clk_base + UTMIP_PLL_CFG1); - value &= ~UTMIP_PLL_CFG1_FORCE_PLL_ENABLE_POWERUP; - value &= ~UTMIP_PLL_CFG1_FORCE_PLL_ENABLE_POWERDOWN; - writel_relaxed(value, pll->clk_base + UTMIP_PLL_CFG1); - - value = readl_relaxed(pll->clk_base + UTMIPLL_HW_PWRDN_CFG0); - value |= UTMIPLL_HW_PWRDN_CFG0_USE_LOCKDET; - value &= ~UTMIPLL_HW_PWRDN_CFG0_CLK_ENABLE_SWCTL; - writel_relaxed(value, pll->clk_base + UTMIPLL_HW_PWRDN_CFG0); - - udelay(1); - - value = readl_relaxed(pll->clk_base + XUSB_PLL_CFG0); - value &= ~XUSB_PLL_CFG0_UTMIPLL_LOCK_DLY; - writel_relaxed(value, pll->clk_base + XUSB_PLL_CFG0); - - udelay(1); - - /* Enable HW control of UTMIPLL */ - value = readl_relaxed(pll->clk_base + UTMIPLL_HW_PWRDN_CFG0); - value |= UTMIPLL_HW_PWRDN_CFG0_SEQ_ENABLE; - writel_relaxed(value, pll->clk_base + UTMIPLL_HW_PWRDN_CFG0); - -out: - if (pll->lock) - spin_unlock_irqrestore(pll->lock, flags); - - return ret; -} - static const struct clk_ops tegra_clk_plle_tegra210_ops = { .is_enabled = clk_plle_tegra210_is_enabled, .enable = clk_plle_tegra210_enable, @@ -2670,13 +2524,6 @@ static const struct clk_ops tegra_clk_plle_tegra210_ops = { .recalc_rate = clk_pll_recalc_rate, }; -static const struct clk_ops tegra_clk_pllu_tegra210_ops = { - .is_enabled = clk_pll_is_enabled, - .enable = clk_pllu_tegra210_enable, - .disable = clk_pll_disable, - .recalc_rate = clk_pllre_recalc_rate, -}; - struct clk *tegra_clk_register_plle_tegra210(const char *name, const char *parent_name, void __iomem *clk_base, unsigned long flags, @@ -2918,25 +2765,4 @@ struct clk *tegra_clk_register_pllmb(const char *name, const char *parent_name, return clk; } -struct clk *tegra_clk_register_pllu_tegra210(const char *name, - const char *parent_name, void __iomem *clk_base, - unsigned long flags, struct tegra_clk_pll_params *pll_params, - spinlock_t *lock) -{ - struct tegra_clk_pll *pll; - struct clk *clk; - - pll_params->flags |= TEGRA_PLLU; - - pll = _tegra_init_pll(clk_base, NULL, pll_params, lock); - if (IS_ERR(pll)) - return ERR_CAST(pll); - - clk = _tegra_clk_register_pll(pll, name, parent_name, flags, - &tegra_clk_pllu_tegra210_ops); - if (IS_ERR(clk)) - kfree(pll); - - return clk; -} #endif diff --git a/drivers/clk/tegra/clk-super.c b/drivers/clk/tegra/clk-super.c index 131d1b5085e2..84267cfc4433 100644 --- a/drivers/clk/tegra/clk-super.c +++ b/drivers/clk/tegra/clk-super.c @@ -121,9 +121,50 @@ out: return err; } +const struct clk_ops tegra_clk_super_mux_ops = { + .get_parent = clk_super_get_parent, + .set_parent = clk_super_set_parent, +}; + +static long clk_super_round_rate(struct clk_hw *hw, unsigned long rate, + unsigned long *parent_rate) +{ + struct tegra_clk_super_mux *super = to_clk_super_mux(hw); + struct clk_hw *div_hw = &super->frac_div.hw; + + __clk_hw_set_clk(div_hw, hw); + + return super->div_ops->round_rate(div_hw, rate, parent_rate); +} + +static unsigned long clk_super_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + struct tegra_clk_super_mux *super = to_clk_super_mux(hw); + struct clk_hw *div_hw = &super->frac_div.hw; + + __clk_hw_set_clk(div_hw, hw); + + return super->div_ops->recalc_rate(div_hw, parent_rate); +} + +static int clk_super_set_rate(struct clk_hw *hw, unsigned long rate, + unsigned long parent_rate) +{ + struct tegra_clk_super_mux *super = to_clk_super_mux(hw); + struct clk_hw *div_hw = &super->frac_div.hw; + + __clk_hw_set_clk(div_hw, hw); + + return super->div_ops->set_rate(div_hw, rate, parent_rate); +} + const struct clk_ops tegra_clk_super_ops = { .get_parent = clk_super_get_parent, .set_parent = clk_super_set_parent, + .set_rate = clk_super_set_rate, + .round_rate = clk_super_round_rate, + .recalc_rate = clk_super_recalc_rate, }; struct clk *tegra_clk_register_super_mux(const char *name, @@ -136,13 +177,11 @@ struct clk *tegra_clk_register_super_mux(const char *name, struct clk_init_data init; super = kzalloc(sizeof(*super), GFP_KERNEL); - if (!super) { - pr_err("%s: could not allocate super clk\n", __func__); + if (!super) return ERR_PTR(-ENOMEM); - } init.name = name; - init.ops = &tegra_clk_super_ops; + init.ops = &tegra_clk_super_mux_ops; init.flags = flags; init.parent_names = parent_names; init.num_parents = num_parents; @@ -163,3 +202,43 @@ struct clk *tegra_clk_register_super_mux(const char *name, return clk; } + +struct clk *tegra_clk_register_super_clk(const char *name, + const char * const *parent_names, u8 num_parents, + unsigned long flags, void __iomem *reg, u8 clk_super_flags, + spinlock_t *lock) +{ + struct tegra_clk_super_mux *super; + struct clk *clk; + struct clk_init_data init; + + super = kzalloc(sizeof(*super), GFP_KERNEL); + if (!super) + return ERR_PTR(-ENOMEM); + + init.name = name; + init.ops = &tegra_clk_super_ops; + init.flags = flags; + init.parent_names = parent_names; + init.num_parents = num_parents; + + super->reg = reg; + super->lock = lock; + super->width = 4; + super->flags = clk_super_flags; + super->frac_div.reg = reg + 4; + super->frac_div.shift = 16; + super->frac_div.width = 8; + super->frac_div.frac_width = 1; + super->frac_div.lock = lock; + super->div_ops = &tegra_clk_frac_div_ops; + + /* Data in .init is copied by clk_register(), so stack variable OK */ + super->hw.init = &init; + + clk = clk_register(NULL, &super->hw); + if (IS_ERR(clk)) + kfree(super); + + return clk; +} diff --git a/drivers/clk/tegra/clk-tegra-audio.c b/drivers/clk/tegra/clk-tegra-audio.c index e2bfa9b368f6..b37cae7af26d 100644 --- a/drivers/clk/tegra/clk-tegra-audio.c +++ b/drivers/clk/tegra/clk-tegra-audio.c @@ -31,6 +31,9 @@ #define AUDIO_SYNC_CLK_I2S3 0x4ac #define AUDIO_SYNC_CLK_I2S4 0x4b0 #define AUDIO_SYNC_CLK_SPDIF 0x4b4 +#define AUDIO_SYNC_CLK_DMIC1 0x560 +#define AUDIO_SYNC_CLK_DMIC2 0x564 +#define AUDIO_SYNC_CLK_DMIC3 0x6b8 #define AUDIO_SYNC_DOUBLER 0x49c @@ -91,8 +94,14 @@ struct tegra_audio2x_clk_initdata { static DEFINE_SPINLOCK(clk_doubler_lock); -static const char *mux_audio_sync_clk[] = { "spdif_in_sync", "i2s0_sync", - "i2s1_sync", "i2s2_sync", "i2s3_sync", "i2s4_sync", "vimclk_sync", +static const char * const mux_audio_sync_clk[] = { "spdif_in_sync", + "i2s0_sync", "i2s1_sync", "i2s2_sync", "i2s3_sync", "i2s4_sync", + "pll_a_out0", "vimclk_sync", +}; + +static const char * const mux_dmic_sync_clk[] = { "unused", "i2s0_sync", + "i2s1_sync", "i2s2_sync", "i2s3_sync", "i2s4_sync", "pll_a_out0", + "vimclk_sync", }; static struct tegra_sync_source_initdata sync_source_clks[] __initdata = { @@ -114,6 +123,12 @@ static struct tegra_audio_clk_initdata audio_clks[] = { AUDIO(spdif, AUDIO_SYNC_CLK_SPDIF), }; +static struct tegra_audio_clk_initdata dmic_clks[] = { + AUDIO(dmic1_sync_clk, AUDIO_SYNC_CLK_DMIC1), + AUDIO(dmic2_sync_clk, AUDIO_SYNC_CLK_DMIC2), + AUDIO(dmic3_sync_clk, AUDIO_SYNC_CLK_DMIC3), +}; + static struct tegra_audio2x_clk_initdata audio2x_clks[] = { AUDIO2X(audio0, 113, 24), AUDIO2X(audio1, 114, 25), @@ -123,6 +138,41 @@ static struct tegra_audio2x_clk_initdata audio2x_clks[] = { AUDIO2X(spdif, 118, 29), }; +static void __init tegra_audio_sync_clk_init(void __iomem *clk_base, + struct tegra_clk *tegra_clks, + struct tegra_audio_clk_initdata *sync, + int num_sync_clks, + const char * const *mux_names, + int num_mux_inputs) +{ + struct clk *clk; + struct clk **dt_clk; + struct tegra_audio_clk_initdata *data; + int i; + + for (i = 0, data = sync; i < num_sync_clks; i++, data++) { + dt_clk = tegra_lookup_dt_id(data->mux_clk_id, tegra_clks); + if (!dt_clk) + continue; + + clk = clk_register_mux(NULL, data->mux_name, mux_names, + num_mux_inputs, + CLK_SET_RATE_NO_REPARENT, + clk_base + data->offset, 0, 3, 0, + NULL); + *dt_clk = clk; + + dt_clk = tegra_lookup_dt_id(data->gate_clk_id, tegra_clks); + if (!dt_clk) + continue; + + clk = clk_register_gate(NULL, data->gate_name, data->mux_name, + 0, clk_base + data->offset, 4, + CLK_GATE_SET_TO_DISABLE, NULL); + *dt_clk = clk; + } +} + void __init tegra_audio_clk_init(void __iomem *clk_base, void __iomem *pmc_base, struct tegra_clk *tegra_clks, struct tegra_audio_clk_info *audio_info, @@ -176,30 +226,17 @@ void __init tegra_audio_clk_init(void __iomem *clk_base, *dt_clk = clk; } - for (i = 0; i < ARRAY_SIZE(audio_clks); i++) { - struct tegra_audio_clk_initdata *data; + tegra_audio_sync_clk_init(clk_base, tegra_clks, audio_clks, + ARRAY_SIZE(audio_clks), mux_audio_sync_clk, + ARRAY_SIZE(mux_audio_sync_clk)); - data = &audio_clks[i]; - dt_clk = tegra_lookup_dt_id(data->mux_clk_id, tegra_clks); + /* make sure the DMIC sync clocks have a valid parent */ + for (i = 0; i < ARRAY_SIZE(dmic_clks); i++) + writel_relaxed(1, clk_base + dmic_clks[i].offset); - if (!dt_clk) - continue; - clk = clk_register_mux(NULL, data->mux_name, mux_audio_sync_clk, - ARRAY_SIZE(mux_audio_sync_clk), - CLK_SET_RATE_NO_REPARENT, - clk_base + data->offset, 0, 3, 0, - NULL); - *dt_clk = clk; - - dt_clk = tegra_lookup_dt_id(data->gate_clk_id, tegra_clks); - if (!dt_clk) - continue; - - clk = clk_register_gate(NULL, data->gate_name, data->mux_name, - 0, clk_base + data->offset, 4, - CLK_GATE_SET_TO_DISABLE, NULL); - *dt_clk = clk; - } + tegra_audio_sync_clk_init(clk_base, tegra_clks, dmic_clks, + ARRAY_SIZE(dmic_clks), mux_dmic_sync_clk, + ARRAY_SIZE(mux_dmic_sync_clk)); for (i = 0; i < ARRAY_SIZE(audio2x_clks); i++) { struct tegra_audio2x_clk_initdata *data; diff --git a/drivers/clk/tegra/clk-tegra-periph.c b/drivers/clk/tegra/clk-tegra-periph.c index 4ce4e7fb1124..294bfe40a4f5 100644 --- a/drivers/clk/tegra/clk-tegra-periph.c +++ b/drivers/clk/tegra/clk-tegra-periph.c @@ -138,6 +138,9 @@ #define CLK_SOURCE_TSECB 0x6d8 #define CLK_SOURCE_MAUD 0x6d4 #define CLK_SOURCE_USB2_HSIC_TRK 0x6cc +#define CLK_SOURCE_DMIC1 0x64c +#define CLK_SOURCE_DMIC2 0x650 +#define CLK_SOURCE_DMIC3 0x6bc #define MASK(x) (BIT(x) - 1) @@ -168,6 +171,12 @@ 0, TEGRA_PERIPH_NO_GATE, _clk_id,\ _parents##_idx, 0, _lock) +#define MUX8_NOGATE(_name, _parents, _offset, _clk_id) \ + TEGRA_INIT_DATA_TABLE(_name, NULL, NULL, _parents, _offset, \ + 29, MASK(3), 0, 0, 8, 1, TEGRA_DIVIDER_ROUND_UP,\ + 0, TEGRA_PERIPH_NO_GATE, _clk_id,\ + _parents##_idx, 0, NULL) + #define INT(_name, _parents, _offset, \ _clk_num, _gate_flags, _clk_id) \ TEGRA_INIT_DATA_TABLE(_name, NULL, NULL, _parents, _offset,\ @@ -619,6 +628,21 @@ static const char *mux_clkm_plldp_sor0lvds[] = { }; #define mux_clkm_plldp_sor0lvds_idx NULL +static const char * const mux_dmic1[] = { + "pll_a_out0", "dmic1_sync_clk", "pll_p", "clk_m" +}; +#define mux_dmic1_idx NULL + +static const char * const mux_dmic2[] = { + "pll_a_out0", "dmic2_sync_clk", "pll_p", "clk_m" +}; +#define mux_dmic2_idx NULL + +static const char * const mux_dmic3[] = { + "pll_a_out0", "dmic3_sync_clk", "pll_p", "clk_m" +}; +#define mux_dmic3_idx NULL + static struct tegra_periph_init_data periph_clks[] = { AUDIO("d_audio", CLK_SOURCE_D_AUDIO, 106, TEGRA_PERIPH_ON_APB, tegra_clk_d_audio), AUDIO("dam0", CLK_SOURCE_DAM0, 108, TEGRA_PERIPH_ON_APB, tegra_clk_dam0), @@ -739,7 +763,7 @@ static struct tegra_periph_init_data periph_clks[] = { MUX8("soc_therm", mux_clkm_pllc_pllp_plla, CLK_SOURCE_SOC_THERM, 78, TEGRA_PERIPH_ON_APB, tegra_clk_soc_therm_8), MUX8("vi_sensor", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_VI_SENSOR, 164, TEGRA_PERIPH_NO_RESET, tegra_clk_vi_sensor_8), MUX8("isp", mux_pllm_pllc_pllp_plla_clkm_pllc4, CLK_SOURCE_ISP, 23, TEGRA_PERIPH_ON_APB, tegra_clk_isp_8), - MUX8("isp", mux_pllc_pllp_plla1_pllc2_c3_clkm_pllc4, CLK_SOURCE_ISP, 23, TEGRA_PERIPH_ON_APB, tegra_clk_isp_9), + MUX8_NOGATE("isp", mux_pllc_pllp_plla1_pllc2_c3_clkm_pllc4, CLK_SOURCE_ISP, tegra_clk_isp_9), MUX8("entropy", mux_pllp_clkm1, CLK_SOURCE_ENTROPY, 149, 0, tegra_clk_entropy), MUX8("entropy", mux_pllp_clkm_clk32_plle, CLK_SOURCE_ENTROPY, 149, 0, tegra_clk_entropy_8), MUX8("hdmi_audio", mux_pllp3_pllc_clkm, CLK_SOURCE_HDMI_AUDIO, 176, TEGRA_PERIPH_NO_RESET, tegra_clk_hdmi_audio), @@ -788,6 +812,9 @@ static struct tegra_periph_init_data periph_clks[] = { MUX("uartape", mux_pllp_pllc_clkm, CLK_SOURCE_UARTAPE, 212, TEGRA_PERIPH_ON_APB | TEGRA_PERIPH_NO_RESET, tegra_clk_uartape), MUX8("tsecb", mux_pllp_pllc2_c_c3_clkm, CLK_SOURCE_TSECB, 206, 0, tegra_clk_tsecb), MUX8("maud", mux_pllp_pllp_out3_clkm_clk32k_plla, CLK_SOURCE_MAUD, 202, TEGRA_PERIPH_ON_APB | TEGRA_PERIPH_NO_RESET, tegra_clk_maud), + MUX8("dmic1", mux_dmic1, CLK_SOURCE_DMIC1, 161, TEGRA_PERIPH_ON_APB | TEGRA_PERIPH_NO_RESET, tegra_clk_dmic1), + MUX8("dmic2", mux_dmic2, CLK_SOURCE_DMIC2, 162, TEGRA_PERIPH_ON_APB | TEGRA_PERIPH_NO_RESET, tegra_clk_dmic2), + MUX8("dmic3", mux_dmic3, CLK_SOURCE_DMIC3, 197, TEGRA_PERIPH_ON_APB | TEGRA_PERIPH_NO_RESET, tegra_clk_dmic3), }; static struct tegra_periph_init_data gate_clks[] = { @@ -809,7 +836,7 @@ static struct tegra_periph_init_data gate_clks[] = { GATE("usb2", "clk_m", 58, 0, tegra_clk_usb2, 0), GATE("usb3", "clk_m", 59, 0, tegra_clk_usb3, 0), GATE("csi", "pll_p_out3", 52, 0, tegra_clk_csi, 0), - GATE("afi", "clk_m", 72, 0, tegra_clk_afi, 0), + GATE("afi", "mselect", 72, 0, tegra_clk_afi, 0), GATE("csus", "clk_m", 92, TEGRA_PERIPH_NO_RESET, tegra_clk_csus, 0), GATE("dds", "clk_m", 150, TEGRA_PERIPH_ON_APB, tegra_clk_dds, 0), GATE("dp2", "clk_m", 152, TEGRA_PERIPH_ON_APB, tegra_clk_dp2, 0), @@ -819,7 +846,8 @@ static struct tegra_periph_init_data gate_clks[] = { GATE("xusb_dev", "xusb_dev_src", 95, 0, tegra_clk_xusb_dev, 0), GATE("emc", "emc_mux", 57, 0, tegra_clk_emc, CLK_IGNORE_UNUSED), GATE("sata_cold", "clk_m", 129, TEGRA_PERIPH_ON_APB, tegra_clk_sata_cold, 0), - GATE("ispb", "clk_m", 3, 0, tegra_clk_ispb, 0), + GATE("ispa", "isp", 23, 0, tegra_clk_ispa, 0), + GATE("ispb", "isp", 3, 0, tegra_clk_ispb, 0), GATE("vim2_clk", "clk_m", 11, 0, tegra_clk_vim2_clk, 0), GATE("pcie", "clk_m", 70, 0, tegra_clk_pcie, 0), GATE("gpu", "pll_ref", 184, 0, tegra_clk_gpu, 0), @@ -830,6 +858,13 @@ static struct tegra_periph_init_data gate_clks[] = { GATE("pll_p_out_cpu", "pll_p", 223, 0, tegra_clk_pll_p_out_cpu, 0), GATE("pll_p_out_adsp", "pll_p", 187, 0, tegra_clk_pll_p_out_adsp, 0), GATE("apb2ape", "clk_m", 107, 0, tegra_clk_apb2ape, 0), + GATE("cec", "pclk", 136, 0, tegra_clk_cec, 0), + GATE("iqc1", "clk_m", 221, 0, tegra_clk_iqc1, 0), + GATE("iqc2", "clk_m", 220, 0, tegra_clk_iqc1, 0), + GATE("pll_a_out_adsp", "pll_a", 188, 0, tegra_clk_pll_a_out_adsp, 0), + GATE("pll_a_out0_out_adsp", "pll_a", 188, 0, tegra_clk_pll_a_out0_out_adsp, 0), + GATE("adsp", "aclk", 199, 0, tegra_clk_adsp, 0), + GATE("adsp_neon", "aclk", 218, 0, tegra_clk_adsp_neon, 0), }; static struct tegra_periph_init_data div_clks[] = { diff --git a/drivers/clk/tegra/clk-tegra-pmc.c b/drivers/clk/tegra/clk-tegra-pmc.c index 91377abfefa1..a35579a3f884 100644 --- a/drivers/clk/tegra/clk-tegra-pmc.c +++ b/drivers/clk/tegra/clk-tegra-pmc.c @@ -95,7 +95,8 @@ void __init tegra_pmc_clk_init(void __iomem *pmc_base, continue; clk = clk_register_mux(NULL, data->mux_name, data->parents, - data->num_parents, CLK_SET_RATE_NO_REPARENT, + data->num_parents, + CLK_SET_RATE_NO_REPARENT | CLK_SET_RATE_PARENT, pmc_base + PMC_CLK_OUT_CNTRL, data->mux_shift, 3, 0, &clk_out_lock); *dt_clk = clk; @@ -106,7 +107,8 @@ void __init tegra_pmc_clk_init(void __iomem *pmc_base, continue; clk = clk_register_gate(NULL, data->gate_name, data->mux_name, - 0, pmc_base + PMC_CLK_OUT_CNTRL, + CLK_SET_RATE_PARENT, + pmc_base + PMC_CLK_OUT_CNTRL, data->gate_shift, 0, &clk_out_lock); *dt_clk = clk; clk_register_clkdev(clk, data->dev_name, data->gate_name); diff --git a/drivers/clk/tegra/clk-tegra114.c b/drivers/clk/tegra/clk-tegra114.c index 933b5dd698b8..fd1a99c05c2d 100644 --- a/drivers/clk/tegra/clk-tegra114.c +++ b/drivers/clk/tegra/clk-tegra114.c @@ -819,6 +819,7 @@ static struct tegra_clk tegra114_clks[tegra_clk_max] __initdata = { [tegra_clk_clk_out_3_mux] = { .dt_id = TEGRA114_CLK_CLK_OUT_3_MUX, .present = true }, [tegra_clk_dsia_mux] = { .dt_id = TEGRA114_CLK_DSIA_MUX, .present = true }, [tegra_clk_dsib_mux] = { .dt_id = TEGRA114_CLK_DSIB_MUX, .present = true }, + [tegra_clk_cec] = { .dt_id = TEGRA114_CLK_CEC, .present = true }, }; static struct tegra_devclk devclks[] __initdata = { diff --git a/drivers/clk/tegra/clk-tegra124.c b/drivers/clk/tegra/clk-tegra124.c index a112d3d2bff1..e81ea5b11577 100644 --- a/drivers/clk/tegra/clk-tegra124.c +++ b/drivers/clk/tegra/clk-tegra124.c @@ -928,6 +928,7 @@ static struct tegra_clk tegra124_clks[tegra_clk_max] __initdata = { [tegra_clk_clk_out_1_mux] = { .dt_id = TEGRA124_CLK_CLK_OUT_1_MUX, .present = true }, [tegra_clk_clk_out_2_mux] = { .dt_id = TEGRA124_CLK_CLK_OUT_2_MUX, .present = true }, [tegra_clk_clk_out_3_mux] = { .dt_id = TEGRA124_CLK_CLK_OUT_3_MUX, .present = true }, + [tegra_clk_cec] = { .dt_id = TEGRA124_CLK_CEC, .present = true }, }; static struct tegra_devclk devclks[] __initdata = { diff --git a/drivers/clk/tegra/clk-tegra210.c b/drivers/clk/tegra/clk-tegra210.c index 2896d2e783ce..1024e853ea65 100644 --- a/drivers/clk/tegra/clk-tegra210.c +++ b/drivers/clk/tegra/clk-tegra210.c @@ -24,6 +24,8 @@ #include <linux/export.h> #include <linux/clk/tegra.h> #include <dt-bindings/clock/tegra210-car.h> +#include <dt-bindings/reset/tegra210-car.h> +#include <linux/iopoll.h> #include "clk.h" #include "clk-id.h" @@ -155,9 +157,35 @@ #define PMC_PLLM_WB0_OVERRIDE 0x1dc #define PMC_PLLM_WB0_OVERRIDE_2 0x2b0 +#define UTMIP_PLL_CFG2 0x488 +#define UTMIP_PLL_CFG2_STABLE_COUNT(x) (((x) & 0xfff) << 6) +#define UTMIP_PLL_CFG2_ACTIVE_DLY_COUNT(x) (((x) & 0x3f) << 18) +#define UTMIP_PLL_CFG2_FORCE_PD_SAMP_A_POWERDOWN BIT(0) +#define UTMIP_PLL_CFG2_FORCE_PD_SAMP_A_POWERUP BIT(1) +#define UTMIP_PLL_CFG2_FORCE_PD_SAMP_B_POWERDOWN BIT(2) +#define UTMIP_PLL_CFG2_FORCE_PD_SAMP_B_POWERUP BIT(3) +#define UTMIP_PLL_CFG2_FORCE_PD_SAMP_C_POWERDOWN BIT(4) +#define UTMIP_PLL_CFG2_FORCE_PD_SAMP_C_POWERUP BIT(5) +#define UTMIP_PLL_CFG2_FORCE_PD_SAMP_D_POWERDOWN BIT(24) +#define UTMIP_PLL_CFG2_FORCE_PD_SAMP_D_POWERUP BIT(25) + +#define UTMIP_PLL_CFG1 0x484 +#define UTMIP_PLL_CFG1_ENABLE_DLY_COUNT(x) (((x) & 0x1f) << 27) +#define UTMIP_PLL_CFG1_XTAL_FREQ_COUNT(x) (((x) & 0xfff) << 0) +#define UTMIP_PLL_CFG1_FORCE_PLLU_POWERUP BIT(17) +#define UTMIP_PLL_CFG1_FORCE_PLLU_POWERDOWN BIT(16) +#define UTMIP_PLL_CFG1_FORCE_PLL_ENABLE_POWERUP BIT(15) +#define UTMIP_PLL_CFG1_FORCE_PLL_ENABLE_POWERDOWN BIT(14) +#define UTMIP_PLL_CFG1_FORCE_PLL_ACTIVE_POWERDOWN BIT(12) + #define SATA_PLL_CFG0 0x490 #define SATA_PLL_CFG0_PADPLL_RESET_SWCTL BIT(0) #define SATA_PLL_CFG0_PADPLL_USE_LOCKDET BIT(2) +#define SATA_PLL_CFG0_SATA_SEQ_IN_SWCTL BIT(4) +#define SATA_PLL_CFG0_SATA_SEQ_RESET_INPUT_VALUE BIT(5) +#define SATA_PLL_CFG0_SATA_SEQ_LANE_PD_INPUT_VALUE BIT(6) +#define SATA_PLL_CFG0_SATA_SEQ_PADPLL_PD_INPUT_VALUE BIT(7) + #define SATA_PLL_CFG0_PADPLL_SLEEP_IDDQ BIT(13) #define SATA_PLL_CFG0_SEQ_ENABLE BIT(24) @@ -196,6 +224,12 @@ #define CLK_M_DIVISOR_SHIFT 2 #define CLK_M_DIVISOR_MASK 0x3 +#define RST_DFLL_DVCO 0x2f4 +#define DVFS_DFLL_RESET_SHIFT 0 + +#define CLK_RST_CONTROLLER_RST_DEV_Y_SET 0x2a8 +#define CLK_RST_CONTROLLER_RST_DEV_Y_CLR 0x2ac + /* * SDM fractional divisor is 16-bit 2's complement signed number within * (-2^12 ... 2^12-1) range. Represented in PLL data structure as unsigned @@ -454,6 +488,26 @@ void tegra210_sata_pll_hw_sequence_start(void) } EXPORT_SYMBOL_GPL(tegra210_sata_pll_hw_sequence_start); +void tegra210_set_sata_pll_seq_sw(bool state) +{ + u32 val; + + val = readl_relaxed(clk_base + SATA_PLL_CFG0); + if (state) { + val |= SATA_PLL_CFG0_SATA_SEQ_IN_SWCTL; + val |= SATA_PLL_CFG0_SATA_SEQ_RESET_INPUT_VALUE; + val |= SATA_PLL_CFG0_SATA_SEQ_LANE_PD_INPUT_VALUE; + val |= SATA_PLL_CFG0_SATA_SEQ_PADPLL_PD_INPUT_VALUE; + } else { + val &= ~SATA_PLL_CFG0_SATA_SEQ_IN_SWCTL; + val &= ~SATA_PLL_CFG0_SATA_SEQ_RESET_INPUT_VALUE; + val &= ~SATA_PLL_CFG0_SATA_SEQ_LANE_PD_INPUT_VALUE; + val &= ~SATA_PLL_CFG0_SATA_SEQ_PADPLL_PD_INPUT_VALUE; + } + writel_relaxed(val, clk_base + SATA_PLL_CFG0); +} +EXPORT_SYMBOL_GPL(tegra210_set_sata_pll_seq_sw); + static inline void _pll_misc_chk_default(void __iomem *base, struct tegra_clk_pll_params *params, u8 misc_num, u32 default_val, u32 mask) @@ -501,12 +555,12 @@ static void tegra210_pllcx_set_defaults(const char *name, { pllcx->params->defaults_set = true; - if (readl_relaxed(clk_base + pllcx->params->base_reg) & - PLL_ENABLE) { + if (readl_relaxed(clk_base + pllcx->params->base_reg) & PLL_ENABLE) { /* PLL is ON: only check if defaults already set */ pllcx_check_defaults(pllcx->params); - pr_warn("%s already enabled. Postponing set full defaults\n", - name); + if (!pllcx->params->defaults_set) + pr_warn("%s already enabled. Postponing set full defaults\n", + name); return; } @@ -608,7 +662,6 @@ static void tegra210_plld_set_defaults(struct tegra_clk_pll *plld) if (readl_relaxed(clk_base + plld->params->base_reg) & PLL_ENABLE) { - pr_warn("PLL_D already enabled. Postponing set full defaults\n"); /* * PLL is ON: check if defaults already set, then set those @@ -625,6 +678,9 @@ static void tegra210_plld_set_defaults(struct tegra_clk_pll *plld) _pll_misc_chk_default(clk_base, plld->params, 0, val, ~mask & PLLD_MISC0_WRITE_MASK); + if (!plld->params->defaults_set) + pr_warn("PLL_D already enabled. Postponing set full defaults\n"); + /* Enable lock detect */ mask = PLLD_MISC0_LOCK_ENABLE | PLLD_MISC0_LOCK_OVERRIDE; val = readl_relaxed(clk_base + plld->params->ext_misc_reg[0]); @@ -896,7 +952,6 @@ static void tegra210_pllx_set_defaults(struct tegra_clk_pll *pllx) val |= step_b << PLLX_MISC2_DYNRAMP_STEPB_SHIFT; if (readl_relaxed(clk_base + pllx->params->base_reg) & PLL_ENABLE) { - pr_warn("PLL_X already enabled. Postponing set full defaults\n"); /* * PLL is ON: check if defaults already set, then set those @@ -904,6 +959,8 @@ static void tegra210_pllx_set_defaults(struct tegra_clk_pll *pllx) */ pllx_check_defaults(pllx); + if (!pllx->params->defaults_set) + pr_warn("PLL_X already enabled. Postponing set full defaults\n"); /* Configure dyn ramp, disable lock override */ writel_relaxed(val, clk_base + pllx->params->ext_misc_reg[2]); @@ -948,7 +1005,6 @@ static void tegra210_pllmb_set_defaults(struct tegra_clk_pll *pllmb) pllmb->params->defaults_set = true; if (val & PLL_ENABLE) { - pr_warn("PLL_MB already enabled. Postponing set full defaults\n"); /* * PLL is ON: check if defaults already set, then set those @@ -959,6 +1015,8 @@ static void tegra210_pllmb_set_defaults(struct tegra_clk_pll *pllmb) _pll_misc_chk_default(clk_base, pllmb->params, 0, val, ~mask & PLLMB_MISC1_WRITE_MASK); + if (!pllmb->params->defaults_set) + pr_warn("PLL_MB already enabled. Postponing set full defaults\n"); /* Enable lock detect */ val = readl_relaxed(clk_base + pllmb->params->ext_misc_reg[0]); val &= ~mask; @@ -1008,13 +1066,14 @@ static void tegra210_pllp_set_defaults(struct tegra_clk_pll *pllp) pllp->params->defaults_set = true; if (val & PLL_ENABLE) { - pr_warn("PLL_P already enabled. Postponing set full defaults\n"); /* * PLL is ON: check if defaults already set, then set those * that can be updated in flight. */ pllp_check_defaults(pllp, true); + if (!pllp->params->defaults_set) + pr_warn("PLL_P already enabled. Postponing set full defaults\n"); /* Enable lock detect */ val = readl_relaxed(clk_base + pllp->params->ext_misc_reg[0]); @@ -1046,47 +1105,49 @@ static void tegra210_pllp_set_defaults(struct tegra_clk_pll *pllp) * Both VCO and post-divider output rates are fixed at 480MHz and 240MHz, * respectively. */ -static void pllu_check_defaults(struct tegra_clk_pll *pll, bool hw_control) +static void pllu_check_defaults(struct tegra_clk_pll_params *params, + bool hw_control) { u32 val, mask; /* Ignore lock enable (will be set) and IDDQ if under h/w control */ val = PLLU_MISC0_DEFAULT_VALUE & (~PLLU_MISC0_IDDQ); mask = PLLU_MISC0_LOCK_ENABLE | (hw_control ? PLLU_MISC0_IDDQ : 0); - _pll_misc_chk_default(clk_base, pll->params, 0, val, + _pll_misc_chk_default(clk_base, params, 0, val, ~mask & PLLU_MISC0_WRITE_MASK); val = PLLU_MISC1_DEFAULT_VALUE; mask = PLLU_MISC1_LOCK_OVERRIDE; - _pll_misc_chk_default(clk_base, pll->params, 1, val, + _pll_misc_chk_default(clk_base, params, 1, val, ~mask & PLLU_MISC1_WRITE_MASK); } -static void tegra210_pllu_set_defaults(struct tegra_clk_pll *pllu) +static void tegra210_pllu_set_defaults(struct tegra_clk_pll_params *pllu) { - u32 val = readl_relaxed(clk_base + pllu->params->base_reg); + u32 val = readl_relaxed(clk_base + pllu->base_reg); - pllu->params->defaults_set = true; + pllu->defaults_set = true; if (val & PLL_ENABLE) { - pr_warn("PLL_U already enabled. Postponing set full defaults\n"); /* * PLL is ON: check if defaults already set, then set those * that can be updated in flight. */ pllu_check_defaults(pllu, false); + if (!pllu->defaults_set) + pr_warn("PLL_U already enabled. Postponing set full defaults\n"); /* Enable lock detect */ - val = readl_relaxed(clk_base + pllu->params->ext_misc_reg[0]); + val = readl_relaxed(clk_base + pllu->ext_misc_reg[0]); val &= ~PLLU_MISC0_LOCK_ENABLE; val |= PLLU_MISC0_DEFAULT_VALUE & PLLU_MISC0_LOCK_ENABLE; - writel_relaxed(val, clk_base + pllu->params->ext_misc_reg[0]); + writel_relaxed(val, clk_base + pllu->ext_misc_reg[0]); - val = readl_relaxed(clk_base + pllu->params->ext_misc_reg[1]); + val = readl_relaxed(clk_base + pllu->ext_misc_reg[1]); val &= ~PLLU_MISC1_LOCK_OVERRIDE; val |= PLLU_MISC1_DEFAULT_VALUE & PLLU_MISC1_LOCK_OVERRIDE; - writel_relaxed(val, clk_base + pllu->params->ext_misc_reg[1]); + writel_relaxed(val, clk_base + pllu->ext_misc_reg[1]); udelay(1); return; @@ -1094,9 +1155,9 @@ static void tegra210_pllu_set_defaults(struct tegra_clk_pll *pllu) /* set IDDQ, enable lock detect */ writel_relaxed(PLLU_MISC0_DEFAULT_VALUE, - clk_base + pllu->params->ext_misc_reg[0]); + clk_base + pllu->ext_misc_reg[0]); writel_relaxed(PLLU_MISC1_DEFAULT_VALUE, - clk_base + pllu->params->ext_misc_reg[1]); + clk_base + pllu->ext_misc_reg[1]); udelay(1); } @@ -1216,6 +1277,7 @@ static int tegra210_pll_fixed_mdiv_cfg(struct clk_hw *hw, cfg->n = p_rate / cf; cfg->sdm_data = 0; + cfg->output_rate = input_rate; if (params->sdm_ctrl_reg) { unsigned long rem = p_rate - cf * cfg->n; /* If ssc is enabled SDM enabled as well, even for integer n */ @@ -1226,10 +1288,15 @@ static int tegra210_pll_fixed_mdiv_cfg(struct clk_hw *hw, s -= PLL_SDM_COEFF / 2; cfg->sdm_data = sdin_din_to_data(s); } + cfg->output_rate *= cfg->n * PLL_SDM_COEFF + PLL_SDM_COEFF/2 + + sdin_data_to_din(cfg->sdm_data); + cfg->output_rate /= p * cfg->m * PLL_SDM_COEFF; + } else { + cfg->output_rate *= cfg->n; + cfg->output_rate /= p * cfg->m; } cfg->input_rate = input_rate; - cfg->output_rate = rate; return 0; } @@ -1772,7 +1839,7 @@ static struct tegra_clk_pll_params pll_a1_params = { .misc_reg = PLLA1_MISC0, .lock_mask = PLLCX_BASE_LOCK, .lock_delay = 300, - .iddq_reg = PLLA1_MISC0, + .iddq_reg = PLLA1_MISC1, .iddq_bit_idx = PLLCX_IDDQ_BIT, .reset_reg = PLLA1_MISC0, .reset_bit_idx = PLLCX_RESET_BIT, @@ -1987,9 +2054,9 @@ static struct div_nmp pllu_nmp = { }; static struct tegra_clk_pll_freq_table pll_u_freq_table[] = { - { 12000000, 480000000, 40, 1, 1, 0 }, - { 13000000, 480000000, 36, 1, 1, 0 }, /* actual: 468.0 MHz */ - { 38400000, 480000000, 25, 2, 1, 0 }, + { 12000000, 480000000, 40, 1, 0, 0 }, + { 13000000, 480000000, 36, 1, 0, 0 }, /* actual: 468.0 MHz */ + { 38400000, 480000000, 25, 2, 0, 0 }, { 0, 0, 0, 0, 0, 0 }, }; @@ -2013,8 +2080,47 @@ static struct tegra_clk_pll_params pll_u_vco_params = { .div_nmp = &pllu_nmp, .freq_table = pll_u_freq_table, .flags = TEGRA_PLLU | TEGRA_PLL_USE_LOCK | TEGRA_PLL_VCO_OUT, - .set_defaults = tegra210_pllu_set_defaults, - .calc_rate = tegra210_pll_fixed_mdiv_cfg, +}; + +struct utmi_clk_param { + /* Oscillator Frequency in KHz */ + u32 osc_frequency; + /* UTMIP PLL Enable Delay Count */ + u8 enable_delay_count; + /* UTMIP PLL Stable count */ + u16 stable_count; + /* UTMIP PLL Active delay count */ + u8 active_delay_count; + /* UTMIP PLL Xtal frequency count */ + u16 xtal_freq_count; +}; + +static const struct utmi_clk_param utmi_parameters[] = { + { + .osc_frequency = 38400000, .enable_delay_count = 0x0, + .stable_count = 0x0, .active_delay_count = 0x6, + .xtal_freq_count = 0x80 + }, { + .osc_frequency = 13000000, .enable_delay_count = 0x02, + .stable_count = 0x33, .active_delay_count = 0x05, + .xtal_freq_count = 0x7f + }, { + .osc_frequency = 19200000, .enable_delay_count = 0x03, + .stable_count = 0x4b, .active_delay_count = 0x06, + .xtal_freq_count = 0xbb + }, { + .osc_frequency = 12000000, .enable_delay_count = 0x02, + .stable_count = 0x2f, .active_delay_count = 0x08, + .xtal_freq_count = 0x76 + }, { + .osc_frequency = 26000000, .enable_delay_count = 0x04, + .stable_count = 0x66, .active_delay_count = 0x09, + .xtal_freq_count = 0xfe + }, { + .osc_frequency = 16800000, .enable_delay_count = 0x03, + .stable_count = 0x41, .active_delay_count = 0x0a, + .xtal_freq_count = 0xa4 + }, }; static struct tegra_clk tegra210_clks[tegra_clk_max] __initdata = { @@ -2115,7 +2221,6 @@ static struct tegra_clk tegra210_clks[tegra_clk_max] __initdata = { [tegra_clk_pll_c2] = { .dt_id = TEGRA210_CLK_PLL_C2, .present = true }, [tegra_clk_pll_c3] = { .dt_id = TEGRA210_CLK_PLL_C3, .present = true }, [tegra_clk_pll_m] = { .dt_id = TEGRA210_CLK_PLL_M, .present = true }, - [tegra_clk_pll_m_out1] = { .dt_id = TEGRA210_CLK_PLL_M_OUT1, .present = true }, [tegra_clk_pll_p] = { .dt_id = TEGRA210_CLK_PLL_P, .present = true }, [tegra_clk_pll_p_out1] = { .dt_id = TEGRA210_CLK_PLL_P_OUT1, .present = true }, [tegra_clk_pll_p_out3] = { .dt_id = TEGRA210_CLK_PLL_P_OUT3, .present = true }, @@ -2209,6 +2314,25 @@ static struct tegra_clk tegra210_clks[tegra_clk_max] __initdata = { [tegra_clk_pll_c4_out2] = { .dt_id = TEGRA210_CLK_PLL_C4_OUT2, .present = true }, [tegra_clk_pll_c4_out3] = { .dt_id = TEGRA210_CLK_PLL_C4_OUT3, .present = true }, [tegra_clk_apb2ape] = { .dt_id = TEGRA210_CLK_APB2APE, .present = true }, + [tegra_clk_pll_a1] = { .dt_id = TEGRA210_CLK_PLL_A1, .present = true }, + [tegra_clk_ispa] = { .dt_id = TEGRA210_CLK_ISPA, .present = true }, + [tegra_clk_cec] = { .dt_id = TEGRA210_CLK_CEC, .present = true }, + [tegra_clk_dmic1] = { .dt_id = TEGRA210_CLK_DMIC1, .present = true }, + [tegra_clk_dmic2] = { .dt_id = TEGRA210_CLK_DMIC2, .present = true }, + [tegra_clk_dmic3] = { .dt_id = TEGRA210_CLK_DMIC3, .present = true }, + [tegra_clk_dmic1_sync_clk] = { .dt_id = TEGRA210_CLK_DMIC1_SYNC_CLK, .present = true }, + [tegra_clk_dmic2_sync_clk] = { .dt_id = TEGRA210_CLK_DMIC2_SYNC_CLK, .present = true }, + [tegra_clk_dmic3_sync_clk] = { .dt_id = TEGRA210_CLK_DMIC3_SYNC_CLK, .present = true }, + [tegra_clk_dmic1_sync_clk_mux] = { .dt_id = TEGRA210_CLK_DMIC1_SYNC_CLK_MUX, .present = true }, + [tegra_clk_dmic2_sync_clk_mux] = { .dt_id = TEGRA210_CLK_DMIC2_SYNC_CLK_MUX, .present = true }, + [tegra_clk_dmic3_sync_clk_mux] = { .dt_id = TEGRA210_CLK_DMIC3_SYNC_CLK_MUX, .present = true }, + [tegra_clk_dp2] = { .dt_id = TEGRA210_CLK_DP2, .present = true }, + [tegra_clk_iqc1] = { .dt_id = TEGRA210_CLK_IQC1, .present = true }, + [tegra_clk_iqc2] = { .dt_id = TEGRA210_CLK_IQC2, .present = true }, + [tegra_clk_pll_a_out_adsp] = { .dt_id = TEGRA210_CLK_PLL_A_OUT_ADSP, .present = true }, + [tegra_clk_pll_a_out0_out_adsp] = { .dt_id = TEGRA210_CLK_PLL_A_OUT0_OUT_ADSP, .present = true }, + [tegra_clk_adsp] = { .dt_id = TEGRA210_CLK_ADSP, .present = true }, + [tegra_clk_adsp_neon] = { .dt_id = TEGRA210_CLK_ADSP_NEON, .present = true }, }; static struct tegra_devclk devclks[] __initdata = { @@ -2227,7 +2351,6 @@ static struct tegra_devclk devclks[] __initdata = { { .con_id = "pll_p_out3", .dt_id = TEGRA210_CLK_PLL_P_OUT3 }, { .con_id = "pll_p_out4", .dt_id = TEGRA210_CLK_PLL_P_OUT4 }, { .con_id = "pll_m", .dt_id = TEGRA210_CLK_PLL_M }, - { .con_id = "pll_m_out1", .dt_id = TEGRA210_CLK_PLL_M_OUT1 }, { .con_id = "pll_x", .dt_id = TEGRA210_CLK_PLL_X }, { .con_id = "pll_x_out0", .dt_id = TEGRA210_CLK_PLL_X_OUT0 }, { .con_id = "pll_u", .dt_id = TEGRA210_CLK_PLL_U }, @@ -2286,6 +2409,221 @@ static struct tegra_audio_clk_info tegra210_audio_plls[] = { static struct clk **clks; +static const char * const aclk_parents[] = { + "pll_a1", "pll_c", "pll_p", "pll_a_out0", "pll_c2", "pll_c3", + "clk_m" +}; + +void tegra210_put_utmipll_in_iddq(void) +{ + u32 reg; + + reg = readl_relaxed(clk_base + UTMIPLL_HW_PWRDN_CFG0); + + if (reg & UTMIPLL_HW_PWRDN_CFG0_UTMIPLL_LOCK) { + pr_err("trying to assert IDDQ while UTMIPLL is locked\n"); + return; + } + + reg |= UTMIPLL_HW_PWRDN_CFG0_IDDQ_OVERRIDE; + writel_relaxed(reg, clk_base + UTMIPLL_HW_PWRDN_CFG0); +} +EXPORT_SYMBOL_GPL(tegra210_put_utmipll_in_iddq); + +void tegra210_put_utmipll_out_iddq(void) +{ + u32 reg; + + reg = readl_relaxed(clk_base + UTMIPLL_HW_PWRDN_CFG0); + reg &= ~UTMIPLL_HW_PWRDN_CFG0_IDDQ_OVERRIDE; + writel_relaxed(reg, clk_base + UTMIPLL_HW_PWRDN_CFG0); +} +EXPORT_SYMBOL_GPL(tegra210_put_utmipll_out_iddq); + +static void tegra210_utmi_param_configure(void) +{ + u32 reg; + int i; + + for (i = 0; i < ARRAY_SIZE(utmi_parameters); i++) { + if (osc_freq == utmi_parameters[i].osc_frequency) + break; + } + + if (i >= ARRAY_SIZE(utmi_parameters)) { + pr_err("%s: Unexpected oscillator freq %lu\n", __func__, + osc_freq); + return; + } + + reg = readl_relaxed(clk_base + UTMIPLL_HW_PWRDN_CFG0); + reg &= ~UTMIPLL_HW_PWRDN_CFG0_IDDQ_OVERRIDE; + writel_relaxed(reg, clk_base + UTMIPLL_HW_PWRDN_CFG0); + + udelay(10); + + reg = readl_relaxed(clk_base + UTMIP_PLL_CFG2); + + /* Program UTMIP PLL stable and active counts */ + /* [FIXME] arclk_rst.h says WRONG! This should be 1ms -> 0x50 Check! */ + reg &= ~UTMIP_PLL_CFG2_STABLE_COUNT(~0); + reg |= UTMIP_PLL_CFG2_STABLE_COUNT(utmi_parameters[i].stable_count); + + reg &= ~UTMIP_PLL_CFG2_ACTIVE_DLY_COUNT(~0); + + reg |= + UTMIP_PLL_CFG2_ACTIVE_DLY_COUNT(utmi_parameters[i].active_delay_count); + writel_relaxed(reg, clk_base + UTMIP_PLL_CFG2); + + /* Program UTMIP PLL delay and oscillator frequency counts */ + reg = readl_relaxed(clk_base + UTMIP_PLL_CFG1); + reg &= ~UTMIP_PLL_CFG1_ENABLE_DLY_COUNT(~0); + + reg |= + UTMIP_PLL_CFG1_ENABLE_DLY_COUNT(utmi_parameters[i].enable_delay_count); + + reg &= ~UTMIP_PLL_CFG1_XTAL_FREQ_COUNT(~0); + reg |= + UTMIP_PLL_CFG1_XTAL_FREQ_COUNT(utmi_parameters[i].xtal_freq_count); + + reg |= UTMIP_PLL_CFG1_FORCE_PLLU_POWERDOWN; + writel_relaxed(reg, clk_base + UTMIP_PLL_CFG1); + + /* Remove power downs from UTMIP PLL control bits */ + reg = readl_relaxed(clk_base + UTMIP_PLL_CFG1); + reg &= ~UTMIP_PLL_CFG1_FORCE_PLL_ENABLE_POWERDOWN; + reg |= UTMIP_PLL_CFG1_FORCE_PLL_ENABLE_POWERUP; + writel_relaxed(reg, clk_base + UTMIP_PLL_CFG1); + udelay(1); + + /* Enable samplers for SNPS, XUSB_HOST, XUSB_DEV */ + reg = readl_relaxed(clk_base + UTMIP_PLL_CFG2); + reg |= UTMIP_PLL_CFG2_FORCE_PD_SAMP_A_POWERUP; + reg |= UTMIP_PLL_CFG2_FORCE_PD_SAMP_B_POWERUP; + reg |= UTMIP_PLL_CFG2_FORCE_PD_SAMP_D_POWERUP; + reg &= ~UTMIP_PLL_CFG2_FORCE_PD_SAMP_A_POWERDOWN; + reg &= ~UTMIP_PLL_CFG2_FORCE_PD_SAMP_B_POWERDOWN; + reg &= ~UTMIP_PLL_CFG2_FORCE_PD_SAMP_D_POWERDOWN; + writel_relaxed(reg, clk_base + UTMIP_PLL_CFG2); + + /* Setup HW control of UTMIPLL */ + reg = readl_relaxed(clk_base + UTMIP_PLL_CFG1); + reg &= ~UTMIP_PLL_CFG1_FORCE_PLL_ENABLE_POWERDOWN; + reg &= ~UTMIP_PLL_CFG1_FORCE_PLL_ENABLE_POWERUP; + writel_relaxed(reg, clk_base + UTMIP_PLL_CFG1); + + reg = readl_relaxed(clk_base + UTMIPLL_HW_PWRDN_CFG0); + reg |= UTMIPLL_HW_PWRDN_CFG0_USE_LOCKDET; + reg &= ~UTMIPLL_HW_PWRDN_CFG0_CLK_ENABLE_SWCTL; + writel_relaxed(reg, clk_base + UTMIPLL_HW_PWRDN_CFG0); + + udelay(1); + + reg = readl_relaxed(clk_base + XUSB_PLL_CFG0); + reg &= ~XUSB_PLL_CFG0_UTMIPLL_LOCK_DLY; + writel_relaxed(reg, clk_base + XUSB_PLL_CFG0); + + udelay(1); + + /* Enable HW control UTMIPLL */ + reg = readl_relaxed(clk_base + UTMIPLL_HW_PWRDN_CFG0); + reg |= UTMIPLL_HW_PWRDN_CFG0_SEQ_ENABLE; + writel_relaxed(reg, clk_base + UTMIPLL_HW_PWRDN_CFG0); +} + +static int tegra210_enable_pllu(void) +{ + struct tegra_clk_pll_freq_table *fentry; + struct tegra_clk_pll pllu; + u32 reg; + + for (fentry = pll_u_freq_table; fentry->input_rate; fentry++) { + if (fentry->input_rate == pll_ref_freq) + break; + } + + if (!fentry->input_rate) { + pr_err("Unknown PLL_U reference frequency %lu\n", pll_ref_freq); + return -EINVAL; + } + + /* clear IDDQ bit */ + pllu.params = &pll_u_vco_params; + reg = readl_relaxed(clk_base + pllu.params->ext_misc_reg[0]); + reg &= ~BIT(pllu.params->iddq_bit_idx); + writel_relaxed(reg, clk_base + pllu.params->ext_misc_reg[0]); + + reg = readl_relaxed(clk_base + PLLU_BASE); + reg &= ~GENMASK(20, 0); + reg |= fentry->m; + reg |= fentry->n << 8; + reg |= fentry->p << 16; + writel(reg, clk_base + PLLU_BASE); + reg |= PLL_ENABLE; + writel(reg, clk_base + PLLU_BASE); + + readl_relaxed_poll_timeout(clk_base + PLLU_BASE, reg, + reg & PLL_BASE_LOCK, 2, 1000); + if (!(reg & PLL_BASE_LOCK)) { + pr_err("Timed out waiting for PLL_U to lock\n"); + return -ETIMEDOUT; + } + + return 0; +} + +static int tegra210_init_pllu(void) +{ + u32 reg; + int err; + + tegra210_pllu_set_defaults(&pll_u_vco_params); + /* skip initialization when pllu is in hw controlled mode */ + reg = readl_relaxed(clk_base + PLLU_BASE); + if (reg & PLLU_BASE_OVERRIDE) { + if (!(reg & PLL_ENABLE)) { + err = tegra210_enable_pllu(); + if (err < 0) { + WARN_ON(1); + return err; + } + } + /* enable hw controlled mode */ + reg = readl_relaxed(clk_base + PLLU_BASE); + reg &= ~PLLU_BASE_OVERRIDE; + writel(reg, clk_base + PLLU_BASE); + + reg = readl_relaxed(clk_base + PLLU_HW_PWRDN_CFG0); + reg |= PLLU_HW_PWRDN_CFG0_IDDQ_PD_INCLUDE | + PLLU_HW_PWRDN_CFG0_USE_SWITCH_DETECT | + PLLU_HW_PWRDN_CFG0_USE_LOCKDET; + reg &= ~(PLLU_HW_PWRDN_CFG0_CLK_ENABLE_SWCTL | + PLLU_HW_PWRDN_CFG0_CLK_SWITCH_SWCTL); + writel_relaxed(reg, clk_base + PLLU_HW_PWRDN_CFG0); + + reg = readl_relaxed(clk_base + XUSB_PLL_CFG0); + reg &= ~XUSB_PLL_CFG0_PLLU_LOCK_DLY_MASK; + writel_relaxed(reg, clk_base + XUSB_PLL_CFG0); + udelay(1); + + reg = readl_relaxed(clk_base + PLLU_HW_PWRDN_CFG0); + reg |= PLLU_HW_PWRDN_CFG0_SEQ_ENABLE; + writel_relaxed(reg, clk_base + PLLU_HW_PWRDN_CFG0); + udelay(1); + + reg = readl_relaxed(clk_base + PLLU_BASE); + reg &= ~PLLU_BASE_CLKENABLE_USB; + writel_relaxed(reg, clk_base + PLLU_BASE); + } + + /* enable UTMIPLL hw control if not yet done by the bootloader */ + reg = readl_relaxed(clk_base + UTMIPLL_HW_PWRDN_CFG0); + if (!(reg & UTMIPLL_HW_PWRDN_CFG0_SEQ_ENABLE)) + tegra210_utmi_param_configure(); + + return 0; +} + static __init void tegra210_periph_clk_init(void __iomem *clk_base, void __iomem *pmc_base) { @@ -2347,6 +2685,11 @@ static __init void tegra210_periph_clk_init(void __iomem *clk_base, clk_register_clkdev(clk, "cml1", NULL); clks[TEGRA210_CLK_CML1] = clk; + clk = tegra_clk_register_super_clk("aclk", aclk_parents, + ARRAY_SIZE(aclk_parents), 0, clk_base + 0x6e0, + 0, NULL); + clks[TEGRA210_CLK_ACLK] = clk; + tegra_periph_clk_init(clk_base, pmc_base, tegra210_clks, &pll_p_params); } @@ -2402,9 +2745,6 @@ static void __init tegra210_pll_init(void __iomem *clk_base, clk_register_clkdev(clk, "pll_mb", NULL); clks[TEGRA210_CLK_PLL_MB] = clk; - clk_register_clkdev(clk, "pll_m_out1", NULL); - clks[TEGRA210_CLK_PLL_M_OUT1] = clk; - /* PLLM_UD */ clk = clk_register_fixed_factor(NULL, "pll_m_ud", "pll_m", CLK_SET_RATE_PARENT, 1, 1); @@ -2412,11 +2752,12 @@ static void __init tegra210_pll_init(void __iomem *clk_base, clks[TEGRA210_CLK_PLL_M_UD] = clk; /* PLLU_VCO */ - clk = tegra_clk_register_pllu_tegra210("pll_u_vco", "pll_ref", - clk_base, 0, &pll_u_vco_params, - &pll_u_lock); - clk_register_clkdev(clk, "pll_u_vco", NULL); - clks[TEGRA210_CLK_PLL_U] = clk; + if (!tegra210_init_pllu()) { + clk = clk_register_fixed_rate(NULL, "pll_u_vco", "pll_ref", 0, + 480*1000*1000); + clk_register_clkdev(clk, "pll_u_vco", NULL); + clks[TEGRA210_CLK_PLL_U] = clk; + } /* PLLU_OUT */ clk = clk_register_divider_table(NULL, "pll_u_out", "pll_u_vco", 0, @@ -2651,6 +2992,8 @@ static struct tegra_clk_init_table init_table[] __initdata = { { TEGRA210_CLK_EMC, TEGRA210_CLK_CLK_MAX, 0, 1 }, { TEGRA210_CLK_MSELECT, TEGRA210_CLK_CLK_MAX, 0, 1 }, { TEGRA210_CLK_CSITE, TEGRA210_CLK_CLK_MAX, 0, 1 }, + /* TODO find a way to enable this on-demand */ + { TEGRA210_CLK_DBGAPB, TEGRA210_CLK_CLK_MAX, 0, 1 }, { TEGRA210_CLK_TSENSOR, TEGRA210_CLK_CLK_M, 400000, 0 }, { TEGRA210_CLK_I2C1, TEGRA210_CLK_PLL_P, 0, 0 }, { TEGRA210_CLK_I2C2, TEGRA210_CLK_PLL_P, 0, 0 }, @@ -2661,6 +3004,8 @@ static struct tegra_clk_init_table init_table[] __initdata = { { TEGRA210_CLK_PLL_DP, TEGRA210_CLK_CLK_MAX, 270000000, 0 }, { TEGRA210_CLK_SOC_THERM, TEGRA210_CLK_PLL_P, 51000000, 0 }, { TEGRA210_CLK_CCLK_G, TEGRA210_CLK_CLK_MAX, 0, 1 }, + { TEGRA210_CLK_PLL_U_OUT1, TEGRA210_CLK_CLK_MAX, 48000000, 1 }, + { TEGRA210_CLK_PLL_U_OUT2, TEGRA210_CLK_CLK_MAX, 60000000, 1 }, /* This MUST be the last entry. */ { TEGRA210_CLK_CLK_MAX, TEGRA210_CLK_CLK_MAX, 0, 0 }, }; @@ -2679,6 +3024,81 @@ static void __init tegra210_clock_apply_init_table(void) } /** + * tegra210_car_barrier - wait for pending writes to the CAR to complete + * + * Wait for any outstanding writes to the CAR MMIO space from this CPU + * to complete before continuing execution. No return value. + */ +static void tegra210_car_barrier(void) +{ + readl_relaxed(clk_base + RST_DFLL_DVCO); +} + +/** + * tegra210_clock_assert_dfll_dvco_reset - assert the DFLL's DVCO reset + * + * Assert the reset line of the DFLL's DVCO. No return value. + */ +static void tegra210_clock_assert_dfll_dvco_reset(void) +{ + u32 v; + + v = readl_relaxed(clk_base + RST_DFLL_DVCO); + v |= (1 << DVFS_DFLL_RESET_SHIFT); + writel_relaxed(v, clk_base + RST_DFLL_DVCO); + tegra210_car_barrier(); +} + +/** + * tegra210_clock_deassert_dfll_dvco_reset - deassert the DFLL's DVCO reset + * + * Deassert the reset line of the DFLL's DVCO, allowing the DVCO to + * operate. No return value. + */ +static void tegra210_clock_deassert_dfll_dvco_reset(void) +{ + u32 v; + + v = readl_relaxed(clk_base + RST_DFLL_DVCO); + v &= ~(1 << DVFS_DFLL_RESET_SHIFT); + writel_relaxed(v, clk_base + RST_DFLL_DVCO); + tegra210_car_barrier(); +} + +static int tegra210_reset_assert(unsigned long id) +{ + if (id == TEGRA210_RST_DFLL_DVCO) + tegra210_clock_assert_dfll_dvco_reset(); + else if (id == TEGRA210_RST_ADSP) + writel(GENMASK(26, 21) | BIT(7), + clk_base + CLK_RST_CONTROLLER_RST_DEV_Y_SET); + else + return -EINVAL; + + return 0; +} + +static int tegra210_reset_deassert(unsigned long id) +{ + if (id == TEGRA210_RST_DFLL_DVCO) + tegra210_clock_deassert_dfll_dvco_reset(); + else if (id == TEGRA210_RST_ADSP) { + writel(BIT(21), clk_base + CLK_RST_CONTROLLER_RST_DEV_Y_CLR); + /* + * Considering adsp cpu clock (min: 12.5MHZ, max: 1GHz) + * a delay of 5us ensures that it's at least + * 6 * adsp_cpu_cycle_period long. + */ + udelay(5); + writel(GENMASK(26, 22) | BIT(7), + clk_base + CLK_RST_CONTROLLER_RST_DEV_Y_CLR); + } else + return -EINVAL; + + return 0; +} + +/** * tegra210_clock_init - Tegra210-specific clock initialization * @np: struct device_node * of the DT node for the SoC CAR IP block * @@ -2742,6 +3162,9 @@ static void __init tegra210_clock_init(struct device_node *np) tegra_super_clk_gen5_init(clk_base, pmc_base, tegra210_clks, &pll_x_params); + tegra_init_special_resets(2, tegra210_reset_assert, + tegra210_reset_deassert); + tegra_add_of_provider(np); tegra_register_devclks(devclks, ARRAY_SIZE(devclks)); diff --git a/drivers/clk/tegra/clk-tegra30.c b/drivers/clk/tegra/clk-tegra30.c index 8e2db5ead8da..a2d163f759b4 100644 --- a/drivers/clk/tegra/clk-tegra30.c +++ b/drivers/clk/tegra/clk-tegra30.c @@ -817,6 +817,7 @@ static struct tegra_clk tegra30_clks[tegra_clk_max] __initdata = { [tegra_clk_pll_p_out4] = { .dt_id = TEGRA30_CLK_PLL_P_OUT4, .present = true }, [tegra_clk_pll_a] = { .dt_id = TEGRA30_CLK_PLL_A, .present = true }, [tegra_clk_pll_a_out0] = { .dt_id = TEGRA30_CLK_PLL_A_OUT0, .present = true }, + [tegra_clk_cec] = { .dt_id = TEGRA30_CLK_CEC, .present = true }, }; static const char *pll_e_parents[] = { "pll_ref", "pll_p" }; diff --git a/drivers/clk/tegra/clk.c b/drivers/clk/tegra/clk.c index b2cdd9a235f4..ba923f0d5953 100644 --- a/drivers/clk/tegra/clk.c +++ b/drivers/clk/tegra/clk.c @@ -17,6 +17,7 @@ #include <linux/clkdev.h> #include <linux/clk.h> #include <linux/clk-provider.h> +#include <linux/delay.h> #include <linux/of.h> #include <linux/clk/tegra.h> #include <linux/reset-controller.h> @@ -182,6 +183,20 @@ static int tegra_clk_rst_deassert(struct reset_controller_dev *rcdev, return -EINVAL; } +static int tegra_clk_rst_reset(struct reset_controller_dev *rcdev, + unsigned long id) +{ + int err; + + err = tegra_clk_rst_assert(rcdev, id); + if (err) + return err; + + udelay(1); + + return tegra_clk_rst_deassert(rcdev, id); +} + const struct tegra_clk_periph_regs *get_reg_bank(int clkid) { int reg_bank = clkid / 32; @@ -274,6 +289,7 @@ void __init tegra_init_from_table(struct tegra_clk_init_table *tbl, static const struct reset_control_ops rst_ops = { .assert = tegra_clk_rst_assert, .deassert = tegra_clk_rst_deassert, + .reset = tegra_clk_rst_reset, }; static struct reset_controller_dev rst_ctlr = { diff --git a/drivers/clk/tegra/clk.h b/drivers/clk/tegra/clk.h index 6ba82ecffd4d..945b07093afa 100644 --- a/drivers/clk/tegra/clk.h +++ b/drivers/clk/tegra/clk.h @@ -116,7 +116,7 @@ struct tegra_clk_pll_freq_table { unsigned long input_rate; unsigned long output_rate; u32 n; - u16 m; + u32 m; u8 p; u8 cpcon; u16 sdm_data; @@ -586,11 +586,11 @@ struct tegra_clk_periph { extern const struct clk_ops tegra_clk_periph_ops; struct clk *tegra_clk_register_periph(const char *name, - const char **parent_names, int num_parents, + const char * const *parent_names, int num_parents, struct tegra_clk_periph *periph, void __iomem *clk_base, u32 offset, unsigned long flags); struct clk *tegra_clk_register_periph_nodiv(const char *name, - const char **parent_names, int num_parents, + const char * const *parent_names, int num_parents, struct tegra_clk_periph *periph, void __iomem *clk_base, u32 offset); @@ -626,7 +626,7 @@ struct tegra_periph_init_data { const char *name; int clk_id; union { - const char **parent_names; + const char *const *parent_names; const char *parent_name; } p; int num_parents; @@ -686,6 +686,8 @@ struct tegra_periph_init_data { struct tegra_clk_super_mux { struct clk_hw hw; void __iomem *reg; + struct tegra_clk_frac_div frac_div; + const struct clk_ops *div_ops; u8 width; u8 flags; u8 div2_index; @@ -702,7 +704,10 @@ struct clk *tegra_clk_register_super_mux(const char *name, const char **parent_names, u8 num_parents, unsigned long flags, void __iomem *reg, u8 clk_super_flags, u8 width, u8 pllx_index, u8 div2_index, spinlock_t *lock); - +struct clk *tegra_clk_register_super_clk(const char *name, + const char * const *parent_names, u8 num_parents, + unsigned long flags, void __iomem *reg, u8 clk_super_flags, + spinlock_t *lock); /** * struct clk_init_table - clock initialization table * @clk_id: clock id as mentioned in device tree bindings diff --git a/drivers/clk/ti/apll.c b/drivers/clk/ti/apll.c index 6411e132faa2..06f486b3488c 100644 --- a/drivers/clk/ti/apll.c +++ b/drivers/clk/ti/apll.c @@ -55,20 +55,20 @@ static int dra7_apll_enable(struct clk_hw *hw) state <<= __ffs(ad->idlest_mask); /* Check is already locked */ - v = ti_clk_ll_ops->clk_readl(ad->idlest_reg); + v = ti_clk_ll_ops->clk_readl(&ad->idlest_reg); if ((v & ad->idlest_mask) == state) return r; - v = ti_clk_ll_ops->clk_readl(ad->control_reg); + v = ti_clk_ll_ops->clk_readl(&ad->control_reg); v &= ~ad->enable_mask; v |= APLL_FORCE_LOCK << __ffs(ad->enable_mask); - ti_clk_ll_ops->clk_writel(v, ad->control_reg); + ti_clk_ll_ops->clk_writel(v, &ad->control_reg); state <<= __ffs(ad->idlest_mask); while (1) { - v = ti_clk_ll_ops->clk_readl(ad->idlest_reg); + v = ti_clk_ll_ops->clk_readl(&ad->idlest_reg); if ((v & ad->idlest_mask) == state) break; if (i > MAX_APLL_WAIT_TRIES) @@ -99,10 +99,10 @@ static void dra7_apll_disable(struct clk_hw *hw) state <<= __ffs(ad->idlest_mask); - v = ti_clk_ll_ops->clk_readl(ad->control_reg); + v = ti_clk_ll_ops->clk_readl(&ad->control_reg); v &= ~ad->enable_mask; v |= APLL_AUTO_IDLE << __ffs(ad->enable_mask); - ti_clk_ll_ops->clk_writel(v, ad->control_reg); + ti_clk_ll_ops->clk_writel(v, &ad->control_reg); } static int dra7_apll_is_enabled(struct clk_hw *hw) @@ -113,7 +113,7 @@ static int dra7_apll_is_enabled(struct clk_hw *hw) ad = clk->dpll_data; - v = ti_clk_ll_ops->clk_readl(ad->control_reg); + v = ti_clk_ll_ops->clk_readl(&ad->control_reg); v &= ad->enable_mask; v >>= __ffs(ad->enable_mask); @@ -164,7 +164,7 @@ static void __init omap_clk_register_apll(struct clk_hw *hw, ad->clk_bypass = __clk_get_hw(clk); - clk = clk_register(NULL, &clk_hw->hw); + clk = ti_clk_register(NULL, &clk_hw->hw, node->name); if (!IS_ERR(clk)) { of_clk_add_provider(node, of_clk_src_simple_get, clk); kfree(clk_hw->hw.init->parent_names); @@ -185,6 +185,7 @@ static void __init of_dra7_apll_setup(struct device_node *node) struct clk_hw_omap *clk_hw = NULL; struct clk_init_data *init = NULL; const char **parent_names = NULL; + int ret; ad = kzalloc(sizeof(*ad), GFP_KERNEL); clk_hw = kzalloc(sizeof(*clk_hw), GFP_KERNEL); @@ -194,7 +195,6 @@ static void __init of_dra7_apll_setup(struct device_node *node) clk_hw->dpll_data = ad; clk_hw->hw.init = init; - clk_hw->flags = MEMMAP_ADDRESSING; init->name = node->name; init->ops = &apll_ck_ops; @@ -213,10 +213,10 @@ static void __init of_dra7_apll_setup(struct device_node *node) init->parent_names = parent_names; - ad->control_reg = ti_clk_get_reg_addr(node, 0); - ad->idlest_reg = ti_clk_get_reg_addr(node, 1); + ret = ti_clk_get_reg_addr(node, 0, &ad->control_reg); + ret |= ti_clk_get_reg_addr(node, 1, &ad->idlest_reg); - if (IS_ERR(ad->control_reg) || IS_ERR(ad->idlest_reg)) + if (ret) goto cleanup; ad->idlest_mask = 0x1; @@ -242,7 +242,7 @@ static int omap2_apll_is_enabled(struct clk_hw *hw) struct dpll_data *ad = clk->dpll_data; u32 v; - v = ti_clk_ll_ops->clk_readl(ad->control_reg); + v = ti_clk_ll_ops->clk_readl(&ad->control_reg); v &= ad->enable_mask; v >>= __ffs(ad->enable_mask); @@ -268,13 +268,13 @@ static int omap2_apll_enable(struct clk_hw *hw) u32 v; int i = 0; - v = ti_clk_ll_ops->clk_readl(ad->control_reg); + v = ti_clk_ll_ops->clk_readl(&ad->control_reg); v &= ~ad->enable_mask; v |= OMAP2_EN_APLL_LOCKED << __ffs(ad->enable_mask); - ti_clk_ll_ops->clk_writel(v, ad->control_reg); + ti_clk_ll_ops->clk_writel(v, &ad->control_reg); while (1) { - v = ti_clk_ll_ops->clk_readl(ad->idlest_reg); + v = ti_clk_ll_ops->clk_readl(&ad->idlest_reg); if (v & ad->idlest_mask) break; if (i > MAX_APLL_WAIT_TRIES) @@ -298,10 +298,10 @@ static void omap2_apll_disable(struct clk_hw *hw) struct dpll_data *ad = clk->dpll_data; u32 v; - v = ti_clk_ll_ops->clk_readl(ad->control_reg); + v = ti_clk_ll_ops->clk_readl(&ad->control_reg); v &= ~ad->enable_mask; v |= OMAP2_EN_APLL_STOPPED << __ffs(ad->enable_mask); - ti_clk_ll_ops->clk_writel(v, ad->control_reg); + ti_clk_ll_ops->clk_writel(v, &ad->control_reg); } static struct clk_ops omap2_apll_ops = { @@ -316,10 +316,10 @@ static void omap2_apll_set_autoidle(struct clk_hw_omap *clk, u32 val) struct dpll_data *ad = clk->dpll_data; u32 v; - v = ti_clk_ll_ops->clk_readl(ad->autoidle_reg); + v = ti_clk_ll_ops->clk_readl(&ad->autoidle_reg); v &= ~ad->autoidle_mask; v |= val << __ffs(ad->autoidle_mask); - ti_clk_ll_ops->clk_writel(v, ad->control_reg); + ti_clk_ll_ops->clk_writel(v, &ad->control_reg); } #define OMAP2_APLL_AUTOIDLE_LOW_POWER_STOP 0x3 @@ -348,6 +348,7 @@ static void __init of_omap2_apll_setup(struct device_node *node) struct clk *clk; const char *parent_name; u32 val; + int ret; ad = kzalloc(sizeof(*ad), GFP_KERNEL); clk_hw = kzalloc(sizeof(*clk_hw), GFP_KERNEL); @@ -393,12 +394,11 @@ static void __init of_omap2_apll_setup(struct device_node *node) ad->idlest_mask = 1 << val; - ad->control_reg = ti_clk_get_reg_addr(node, 0); - ad->autoidle_reg = ti_clk_get_reg_addr(node, 1); - ad->idlest_reg = ti_clk_get_reg_addr(node, 2); + ret = ti_clk_get_reg_addr(node, 0, &ad->control_reg); + ret |= ti_clk_get_reg_addr(node, 1, &ad->autoidle_reg); + ret |= ti_clk_get_reg_addr(node, 2, &ad->idlest_reg); - if (IS_ERR(ad->control_reg) || IS_ERR(ad->autoidle_reg) || - IS_ERR(ad->idlest_reg)) + if (ret) goto cleanup; clk = clk_register(NULL, &clk_hw->hw); diff --git a/drivers/clk/ti/autoidle.c b/drivers/clk/ti/autoidle.c index 345af43465f0..7bb9afbe4058 100644 --- a/drivers/clk/ti/autoidle.c +++ b/drivers/clk/ti/autoidle.c @@ -25,7 +25,7 @@ #include "clock.h" struct clk_ti_autoidle { - void __iomem *reg; + struct clk_omap_reg reg; u8 shift; u8 flags; const char *name; @@ -73,28 +73,28 @@ static void _allow_autoidle(struct clk_ti_autoidle *clk) { u32 val; - val = ti_clk_ll_ops->clk_readl(clk->reg); + val = ti_clk_ll_ops->clk_readl(&clk->reg); if (clk->flags & AUTOIDLE_LOW) val &= ~(1 << clk->shift); else val |= (1 << clk->shift); - ti_clk_ll_ops->clk_writel(val, clk->reg); + ti_clk_ll_ops->clk_writel(val, &clk->reg); } static void _deny_autoidle(struct clk_ti_autoidle *clk) { u32 val; - val = ti_clk_ll_ops->clk_readl(clk->reg); + val = ti_clk_ll_ops->clk_readl(&clk->reg); if (clk->flags & AUTOIDLE_LOW) val |= (1 << clk->shift); else val &= ~(1 << clk->shift); - ti_clk_ll_ops->clk_writel(val, clk->reg); + ti_clk_ll_ops->clk_writel(val, &clk->reg); } /** @@ -140,6 +140,7 @@ int __init of_ti_clk_autoidle_setup(struct device_node *node) { u32 shift; struct clk_ti_autoidle *clk; + int ret; /* Check if this clock has autoidle support or not */ if (of_property_read_u32(node, "ti,autoidle-shift", &shift)) @@ -152,11 +153,10 @@ int __init of_ti_clk_autoidle_setup(struct device_node *node) clk->shift = shift; clk->name = node->name; - clk->reg = ti_clk_get_reg_addr(node, 0); - - if (IS_ERR(clk->reg)) { + ret = ti_clk_get_reg_addr(node, 0, &clk->reg); + if (ret) { kfree(clk); - return -EINVAL; + return ret; } if (of_property_read_bool(node, "ti,invert-autoidle-bit")) diff --git a/drivers/clk/ti/clk-3xxx.c b/drivers/clk/ti/clk-3xxx.c index 11d8aa3ec186..b1251cae98b8 100644 --- a/drivers/clk/ti/clk-3xxx.c +++ b/drivers/clk/ti/clk-3xxx.c @@ -52,14 +52,13 @@ * @idlest_reg and @idlest_bit. No return value. */ static void omap3430es2_clk_ssi_find_idlest(struct clk_hw_omap *clk, - void __iomem **idlest_reg, + struct clk_omap_reg *idlest_reg, u8 *idlest_bit, u8 *idlest_val) { - u32 r; - - r = (((__force u32)clk->enable_reg & ~0xf0) | 0x20); - *idlest_reg = (__force void __iomem *)r; + memcpy(idlest_reg, &clk->enable_reg, sizeof(*idlest_reg)); + idlest_reg->offset &= ~0xf0; + idlest_reg->offset |= 0x20; *idlest_bit = OMAP3430ES2_ST_SSI_IDLE_SHIFT; *idlest_val = OMAP34XX_CM_IDLEST_VAL; } @@ -85,15 +84,15 @@ const struct clk_hw_omap_ops clkhwops_omap3430es2_iclk_ssi_wait = { * default find_idlest code assumes that they are at the same * position.) No return value. */ -static void omap3430es2_clk_dss_usbhost_find_idlest(struct clk_hw_omap *clk, - void __iomem **idlest_reg, - u8 *idlest_bit, - u8 *idlest_val) +static void +omap3430es2_clk_dss_usbhost_find_idlest(struct clk_hw_omap *clk, + struct clk_omap_reg *idlest_reg, + u8 *idlest_bit, u8 *idlest_val) { - u32 r; + memcpy(idlest_reg, &clk->enable_reg, sizeof(*idlest_reg)); - r = (((__force u32)clk->enable_reg & ~0xf0) | 0x20); - *idlest_reg = (__force void __iomem *)r; + idlest_reg->offset &= ~0xf0; + idlest_reg->offset |= 0x20; /* USBHOST_IDLE has same shift */ *idlest_bit = OMAP3430ES2_ST_DSS_IDLE_SHIFT; *idlest_val = OMAP34XX_CM_IDLEST_VAL; @@ -122,15 +121,15 @@ const struct clk_hw_omap_ops clkhwops_omap3430es2_iclk_dss_usbhost_wait = { * shift from the CM_{I,F}CLKEN bit. Pass back the correct info via * @idlest_reg and @idlest_bit. No return value. */ -static void omap3430es2_clk_hsotgusb_find_idlest(struct clk_hw_omap *clk, - void __iomem **idlest_reg, - u8 *idlest_bit, - u8 *idlest_val) +static void +omap3430es2_clk_hsotgusb_find_idlest(struct clk_hw_omap *clk, + struct clk_omap_reg *idlest_reg, + u8 *idlest_bit, + u8 *idlest_val) { - u32 r; - - r = (((__force u32)clk->enable_reg & ~0xf0) | 0x20); - *idlest_reg = (__force void __iomem *)r; + memcpy(idlest_reg, &clk->enable_reg, sizeof(*idlest_reg)); + idlest_reg->offset &= ~0xf0; + idlest_reg->offset |= 0x20; *idlest_bit = OMAP3430ES2_ST_HSOTGUSB_IDLE_SHIFT; *idlest_val = OMAP34XX_CM_IDLEST_VAL; } @@ -154,11 +153,11 @@ const struct clk_hw_omap_ops clkhwops_omap3430es2_iclk_hsotgusb_wait = { * bit. A value of 1 indicates that clock is enabled. */ static void am35xx_clk_find_idlest(struct clk_hw_omap *clk, - void __iomem **idlest_reg, + struct clk_omap_reg *idlest_reg, u8 *idlest_bit, u8 *idlest_val) { - *idlest_reg = (__force void __iomem *)(clk->enable_reg); + memcpy(idlest_reg, &clk->enable_reg, sizeof(*idlest_reg)); *idlest_bit = clk->enable_bit + AM35XX_IPSS_ICK_EN_ACK_OFFSET; *idlest_val = AM35XX_IPSS_CLK_IDLEST_VAL; } @@ -178,10 +177,10 @@ static void am35xx_clk_find_idlest(struct clk_hw_omap *clk, * avoid this issue, and remove the casts. No return value. */ static void am35xx_clk_find_companion(struct clk_hw_omap *clk, - void __iomem **other_reg, + struct clk_omap_reg *other_reg, u8 *other_bit) { - *other_reg = (__force void __iomem *)(clk->enable_reg); + memcpy(other_reg, &clk->enable_reg, sizeof(*other_reg)); if (clk->enable_bit & AM35XX_IPSS_ICK_MASK) *other_bit = clk->enable_bit + AM35XX_IPSS_ICK_FCK_OFFSET; else @@ -205,14 +204,14 @@ const struct clk_hw_omap_ops clkhwops_am35xx_ipss_module_wait = { * and @idlest_bit. No return value. */ static void am35xx_clk_ipss_find_idlest(struct clk_hw_omap *clk, - void __iomem **idlest_reg, + struct clk_omap_reg *idlest_reg, u8 *idlest_bit, u8 *idlest_val) { - u32 r; + memcpy(idlest_reg, &clk->enable_reg, sizeof(*idlest_reg)); - r = (((__force u32)clk->enable_reg & ~0xf0) | 0x20); - *idlest_reg = (__force void __iomem *)r; + idlest_reg->offset &= ~0xf0; + idlest_reg->offset |= 0x20; *idlest_bit = AM35XX_ST_IPSS_SHIFT; *idlest_val = OMAP34XX_CM_IDLEST_VAL; } diff --git a/drivers/clk/ti/clk-44xx.c b/drivers/clk/ti/clk-44xx.c index 7a8b51b35f9f..1c8bb83003bf 100644 --- a/drivers/clk/ti/clk-44xx.c +++ b/drivers/clk/ti/clk-44xx.c @@ -34,196 +34,13 @@ #define OMAP4_DPLL_USB_DEFFREQ 960000000 static struct ti_dt_clk omap44xx_clks[] = { - DT_CLK(NULL, "extalt_clkin_ck", "extalt_clkin_ck"), - DT_CLK(NULL, "pad_clks_src_ck", "pad_clks_src_ck"), - DT_CLK(NULL, "pad_clks_ck", "pad_clks_ck"), - DT_CLK(NULL, "pad_slimbus_core_clks_ck", "pad_slimbus_core_clks_ck"), - DT_CLK(NULL, "secure_32k_clk_src_ck", "secure_32k_clk_src_ck"), - DT_CLK(NULL, "slimbus_src_clk", "slimbus_src_clk"), - DT_CLK(NULL, "slimbus_clk", "slimbus_clk"), - DT_CLK(NULL, "sys_32k_ck", "sys_32k_ck"), - DT_CLK(NULL, "virt_12000000_ck", "virt_12000000_ck"), - DT_CLK(NULL, "virt_13000000_ck", "virt_13000000_ck"), - DT_CLK(NULL, "virt_16800000_ck", "virt_16800000_ck"), - DT_CLK(NULL, "virt_19200000_ck", "virt_19200000_ck"), - DT_CLK(NULL, "virt_26000000_ck", "virt_26000000_ck"), - DT_CLK(NULL, "virt_27000000_ck", "virt_27000000_ck"), - DT_CLK(NULL, "virt_38400000_ck", "virt_38400000_ck"), - DT_CLK(NULL, "sys_clkin_ck", "sys_clkin_ck"), - DT_CLK(NULL, "tie_low_clock_ck", "tie_low_clock_ck"), - DT_CLK(NULL, "utmi_phy_clkout_ck", "utmi_phy_clkout_ck"), - DT_CLK(NULL, "xclk60mhsp1_ck", "xclk60mhsp1_ck"), - DT_CLK(NULL, "xclk60mhsp2_ck", "xclk60mhsp2_ck"), - DT_CLK(NULL, "xclk60motg_ck", "xclk60motg_ck"), - DT_CLK(NULL, "abe_dpll_bypass_clk_mux_ck", "abe_dpll_bypass_clk_mux_ck"), - DT_CLK(NULL, "abe_dpll_refclk_mux_ck", "abe_dpll_refclk_mux_ck"), - DT_CLK(NULL, "dpll_abe_ck", "dpll_abe_ck"), - DT_CLK(NULL, "dpll_abe_x2_ck", "dpll_abe_x2_ck"), - DT_CLK(NULL, "dpll_abe_m2x2_ck", "dpll_abe_m2x2_ck"), - DT_CLK(NULL, "abe_24m_fclk", "abe_24m_fclk"), - DT_CLK(NULL, "abe_clk", "abe_clk"), - DT_CLK(NULL, "aess_fclk", "aess_fclk"), - DT_CLK(NULL, "dpll_abe_m3x2_ck", "dpll_abe_m3x2_ck"), - DT_CLK(NULL, "core_hsd_byp_clk_mux_ck", "core_hsd_byp_clk_mux_ck"), - DT_CLK(NULL, "dpll_core_ck", "dpll_core_ck"), - DT_CLK(NULL, "dpll_core_x2_ck", "dpll_core_x2_ck"), - DT_CLK(NULL, "dpll_core_m6x2_ck", "dpll_core_m6x2_ck"), - DT_CLK(NULL, "dbgclk_mux_ck", "dbgclk_mux_ck"), - DT_CLK(NULL, "dpll_core_m2_ck", "dpll_core_m2_ck"), - DT_CLK(NULL, "ddrphy_ck", "ddrphy_ck"), - DT_CLK(NULL, "dpll_core_m5x2_ck", "dpll_core_m5x2_ck"), - DT_CLK(NULL, "div_core_ck", "div_core_ck"), - DT_CLK(NULL, "div_iva_hs_clk", "div_iva_hs_clk"), - DT_CLK(NULL, "div_mpu_hs_clk", "div_mpu_hs_clk"), - DT_CLK(NULL, "dpll_core_m4x2_ck", "dpll_core_m4x2_ck"), - DT_CLK(NULL, "dll_clk_div_ck", "dll_clk_div_ck"), - DT_CLK(NULL, "dpll_abe_m2_ck", "dpll_abe_m2_ck"), - DT_CLK(NULL, "dpll_core_m3x2_ck", "dpll_core_m3x2_ck"), - DT_CLK(NULL, "dpll_core_m7x2_ck", "dpll_core_m7x2_ck"), - DT_CLK(NULL, "iva_hsd_byp_clk_mux_ck", "iva_hsd_byp_clk_mux_ck"), - DT_CLK(NULL, "dpll_iva_ck", "dpll_iva_ck"), - DT_CLK(NULL, "dpll_iva_x2_ck", "dpll_iva_x2_ck"), - DT_CLK(NULL, "dpll_iva_m4x2_ck", "dpll_iva_m4x2_ck"), - DT_CLK(NULL, "dpll_iva_m5x2_ck", "dpll_iva_m5x2_ck"), - DT_CLK(NULL, "dpll_mpu_ck", "dpll_mpu_ck"), - DT_CLK(NULL, "dpll_mpu_m2_ck", "dpll_mpu_m2_ck"), - DT_CLK(NULL, "per_hs_clk_div_ck", "per_hs_clk_div_ck"), - DT_CLK(NULL, "per_hsd_byp_clk_mux_ck", "per_hsd_byp_clk_mux_ck"), - DT_CLK(NULL, "dpll_per_ck", "dpll_per_ck"), - DT_CLK(NULL, "dpll_per_m2_ck", "dpll_per_m2_ck"), - DT_CLK(NULL, "dpll_per_x2_ck", "dpll_per_x2_ck"), - DT_CLK(NULL, "dpll_per_m2x2_ck", "dpll_per_m2x2_ck"), - DT_CLK(NULL, "dpll_per_m3x2_ck", "dpll_per_m3x2_ck"), - DT_CLK(NULL, "dpll_per_m4x2_ck", "dpll_per_m4x2_ck"), - DT_CLK(NULL, "dpll_per_m5x2_ck", "dpll_per_m5x2_ck"), - DT_CLK(NULL, "dpll_per_m6x2_ck", "dpll_per_m6x2_ck"), - DT_CLK(NULL, "dpll_per_m7x2_ck", "dpll_per_m7x2_ck"), - DT_CLK(NULL, "usb_hs_clk_div_ck", "usb_hs_clk_div_ck"), - DT_CLK(NULL, "dpll_usb_ck", "dpll_usb_ck"), - DT_CLK(NULL, "dpll_usb_clkdcoldo_ck", "dpll_usb_clkdcoldo_ck"), - DT_CLK(NULL, "dpll_usb_m2_ck", "dpll_usb_m2_ck"), - DT_CLK(NULL, "ducati_clk_mux_ck", "ducati_clk_mux_ck"), - DT_CLK(NULL, "func_12m_fclk", "func_12m_fclk"), - DT_CLK(NULL, "func_24m_clk", "func_24m_clk"), - DT_CLK(NULL, "func_24mc_fclk", "func_24mc_fclk"), - DT_CLK(NULL, "func_48m_fclk", "func_48m_fclk"), - DT_CLK(NULL, "func_48mc_fclk", "func_48mc_fclk"), - DT_CLK(NULL, "func_64m_fclk", "func_64m_fclk"), - DT_CLK(NULL, "func_96m_fclk", "func_96m_fclk"), - DT_CLK(NULL, "init_60m_fclk", "init_60m_fclk"), - DT_CLK(NULL, "l3_div_ck", "l3_div_ck"), - DT_CLK(NULL, "l4_div_ck", "l4_div_ck"), - DT_CLK(NULL, "lp_clk_div_ck", "lp_clk_div_ck"), - DT_CLK(NULL, "l4_wkup_clk_mux_ck", "l4_wkup_clk_mux_ck"), DT_CLK("smp_twd", NULL, "mpu_periphclk"), - DT_CLK(NULL, "ocp_abe_iclk", "ocp_abe_iclk"), - DT_CLK(NULL, "per_abe_24m_fclk", "per_abe_24m_fclk"), - DT_CLK(NULL, "per_abe_nc_fclk", "per_abe_nc_fclk"), - DT_CLK(NULL, "syc_clk_div_ck", "syc_clk_div_ck"), - DT_CLK(NULL, "aes1_fck", "aes1_fck"), - DT_CLK(NULL, "aes2_fck", "aes2_fck"), - DT_CLK(NULL, "dmic_sync_mux_ck", "dmic_sync_mux_ck"), - DT_CLK(NULL, "func_dmic_abe_gfclk", "func_dmic_abe_gfclk"), - DT_CLK(NULL, "dss_sys_clk", "dss_sys_clk"), - DT_CLK(NULL, "dss_tv_clk", "dss_tv_clk"), - DT_CLK(NULL, "dss_dss_clk", "dss_dss_clk"), - DT_CLK(NULL, "dss_48mhz_clk", "dss_48mhz_clk"), - DT_CLK(NULL, "dss_fck", "dss_fck"), DT_CLK("omapdss_dss", "ick", "dss_fck"), - DT_CLK(NULL, "fdif_fck", "fdif_fck"), - DT_CLK(NULL, "gpio1_dbclk", "gpio1_dbclk"), - DT_CLK(NULL, "gpio2_dbclk", "gpio2_dbclk"), - DT_CLK(NULL, "gpio3_dbclk", "gpio3_dbclk"), - DT_CLK(NULL, "gpio4_dbclk", "gpio4_dbclk"), - DT_CLK(NULL, "gpio5_dbclk", "gpio5_dbclk"), - DT_CLK(NULL, "gpio6_dbclk", "gpio6_dbclk"), - DT_CLK(NULL, "sgx_clk_mux", "sgx_clk_mux"), - DT_CLK(NULL, "hsi_fck", "hsi_fck"), - DT_CLK(NULL, "iss_ctrlclk", "iss_ctrlclk"), - DT_CLK(NULL, "mcasp_sync_mux_ck", "mcasp_sync_mux_ck"), - DT_CLK(NULL, "func_mcasp_abe_gfclk", "func_mcasp_abe_gfclk"), - DT_CLK(NULL, "mcbsp1_sync_mux_ck", "mcbsp1_sync_mux_ck"), - DT_CLK(NULL, "func_mcbsp1_gfclk", "func_mcbsp1_gfclk"), - DT_CLK(NULL, "mcbsp2_sync_mux_ck", "mcbsp2_sync_mux_ck"), - DT_CLK(NULL, "func_mcbsp2_gfclk", "func_mcbsp2_gfclk"), - DT_CLK(NULL, "mcbsp3_sync_mux_ck", "mcbsp3_sync_mux_ck"), - DT_CLK(NULL, "func_mcbsp3_gfclk", "func_mcbsp3_gfclk"), - DT_CLK(NULL, "mcbsp4_sync_mux_ck", "mcbsp4_sync_mux_ck"), - DT_CLK(NULL, "per_mcbsp4_gfclk", "per_mcbsp4_gfclk"), - DT_CLK(NULL, "hsmmc1_fclk", "hsmmc1_fclk"), - DT_CLK(NULL, "hsmmc2_fclk", "hsmmc2_fclk"), - DT_CLK(NULL, "ocp2scp_usb_phy_phy_48m", "ocp2scp_usb_phy_phy_48m"), - DT_CLK(NULL, "sha2md5_fck", "sha2md5_fck"), - DT_CLK(NULL, "slimbus1_fclk_1", "slimbus1_fclk_1"), - DT_CLK(NULL, "slimbus1_fclk_0", "slimbus1_fclk_0"), - DT_CLK(NULL, "slimbus1_fclk_2", "slimbus1_fclk_2"), - DT_CLK(NULL, "slimbus1_slimbus_clk", "slimbus1_slimbus_clk"), - DT_CLK(NULL, "slimbus2_fclk_1", "slimbus2_fclk_1"), - DT_CLK(NULL, "slimbus2_fclk_0", "slimbus2_fclk_0"), - DT_CLK(NULL, "slimbus2_slimbus_clk", "slimbus2_slimbus_clk"), - DT_CLK(NULL, "smartreflex_core_fck", "smartreflex_core_fck"), - DT_CLK(NULL, "smartreflex_iva_fck", "smartreflex_iva_fck"), - DT_CLK(NULL, "smartreflex_mpu_fck", "smartreflex_mpu_fck"), - DT_CLK(NULL, "dmt1_clk_mux", "dmt1_clk_mux"), - DT_CLK(NULL, "cm2_dm10_mux", "cm2_dm10_mux"), - DT_CLK(NULL, "cm2_dm11_mux", "cm2_dm11_mux"), - DT_CLK(NULL, "cm2_dm2_mux", "cm2_dm2_mux"), - DT_CLK(NULL, "cm2_dm3_mux", "cm2_dm3_mux"), - DT_CLK(NULL, "cm2_dm4_mux", "cm2_dm4_mux"), - DT_CLK(NULL, "timer5_sync_mux", "timer5_sync_mux"), - DT_CLK(NULL, "timer6_sync_mux", "timer6_sync_mux"), - DT_CLK(NULL, "timer7_sync_mux", "timer7_sync_mux"), - DT_CLK(NULL, "timer8_sync_mux", "timer8_sync_mux"), - DT_CLK(NULL, "cm2_dm9_mux", "cm2_dm9_mux"), - DT_CLK(NULL, "usb_host_fs_fck", "usb_host_fs_fck"), DT_CLK("usbhs_omap", "fs_fck", "usb_host_fs_fck"), - DT_CLK(NULL, "utmi_p1_gfclk", "utmi_p1_gfclk"), - DT_CLK(NULL, "usb_host_hs_utmi_p1_clk", "usb_host_hs_utmi_p1_clk"), - DT_CLK(NULL, "utmi_p2_gfclk", "utmi_p2_gfclk"), - DT_CLK(NULL, "usb_host_hs_utmi_p2_clk", "usb_host_hs_utmi_p2_clk"), - DT_CLK(NULL, "usb_host_hs_utmi_p3_clk", "usb_host_hs_utmi_p3_clk"), - DT_CLK(NULL, "usb_host_hs_hsic480m_p1_clk", "usb_host_hs_hsic480m_p1_clk"), - DT_CLK(NULL, "usb_host_hs_hsic60m_p1_clk", "usb_host_hs_hsic60m_p1_clk"), - DT_CLK(NULL, "usb_host_hs_hsic60m_p2_clk", "usb_host_hs_hsic60m_p2_clk"), - DT_CLK(NULL, "usb_host_hs_hsic480m_p2_clk", "usb_host_hs_hsic480m_p2_clk"), - DT_CLK(NULL, "usb_host_hs_func48mclk", "usb_host_hs_func48mclk"), - DT_CLK(NULL, "usb_host_hs_fck", "usb_host_hs_fck"), DT_CLK("usbhs_omap", "hs_fck", "usb_host_hs_fck"), - DT_CLK(NULL, "otg_60m_gfclk", "otg_60m_gfclk"), - DT_CLK(NULL, "usb_otg_hs_xclk", "usb_otg_hs_xclk"), - DT_CLK(NULL, "usb_otg_hs_ick", "usb_otg_hs_ick"), DT_CLK("musb-omap2430", "ick", "usb_otg_hs_ick"), - DT_CLK(NULL, "usb_phy_cm_clk32k", "usb_phy_cm_clk32k"), - DT_CLK(NULL, "usb_tll_hs_usb_ch2_clk", "usb_tll_hs_usb_ch2_clk"), - DT_CLK(NULL, "usb_tll_hs_usb_ch0_clk", "usb_tll_hs_usb_ch0_clk"), - DT_CLK(NULL, "usb_tll_hs_usb_ch1_clk", "usb_tll_hs_usb_ch1_clk"), - DT_CLK(NULL, "usb_tll_hs_ick", "usb_tll_hs_ick"), DT_CLK("usbhs_omap", "usbtll_ick", "usb_tll_hs_ick"), DT_CLK("usbhs_tll", "usbtll_ick", "usb_tll_hs_ick"), - DT_CLK(NULL, "usim_ck", "usim_ck"), - DT_CLK(NULL, "usim_fclk", "usim_fclk"), - DT_CLK(NULL, "pmd_stm_clock_mux_ck", "pmd_stm_clock_mux_ck"), - DT_CLK(NULL, "pmd_trace_clk_mux_ck", "pmd_trace_clk_mux_ck"), - DT_CLK(NULL, "stm_clk_div_ck", "stm_clk_div_ck"), - DT_CLK(NULL, "trace_clk_div_ck", "trace_clk_div_ck"), - DT_CLK(NULL, "auxclk0_src_ck", "auxclk0_src_ck"), - DT_CLK(NULL, "auxclk0_ck", "auxclk0_ck"), - DT_CLK(NULL, "auxclkreq0_ck", "auxclkreq0_ck"), - DT_CLK(NULL, "auxclk1_src_ck", "auxclk1_src_ck"), - DT_CLK(NULL, "auxclk1_ck", "auxclk1_ck"), - DT_CLK(NULL, "auxclkreq1_ck", "auxclkreq1_ck"), - DT_CLK(NULL, "auxclk2_src_ck", "auxclk2_src_ck"), - DT_CLK(NULL, "auxclk2_ck", "auxclk2_ck"), - DT_CLK(NULL, "auxclkreq2_ck", "auxclkreq2_ck"), - DT_CLK(NULL, "auxclk3_src_ck", "auxclk3_src_ck"), - DT_CLK(NULL, "auxclk3_ck", "auxclk3_ck"), - DT_CLK(NULL, "auxclkreq3_ck", "auxclkreq3_ck"), - DT_CLK(NULL, "auxclk4_src_ck", "auxclk4_src_ck"), - DT_CLK(NULL, "auxclk4_ck", "auxclk4_ck"), - DT_CLK(NULL, "auxclkreq4_ck", "auxclkreq4_ck"), - DT_CLK(NULL, "auxclk5_src_ck", "auxclk5_src_ck"), - DT_CLK(NULL, "auxclk5_ck", "auxclk5_ck"), - DT_CLK(NULL, "auxclkreq5_ck", "auxclkreq5_ck"), DT_CLK("omap_i2c.1", "ick", "dummy_ck"), DT_CLK("omap_i2c.2", "ick", "dummy_ck"), DT_CLK("omap_i2c.3", "ick", "dummy_ck"), @@ -263,9 +80,6 @@ static struct ti_dt_clk omap44xx_clks[] = { DT_CLK("4013c000.timer", "timer_sys_ck", "syc_clk_div_ck"), DT_CLK("4013e000.timer", "timer_sys_ck", "syc_clk_div_ck"), DT_CLK(NULL, "cpufreq_ck", "dpll_mpu_ck"), - DT_CLK(NULL, "bandgap_fclk", "bandgap_fclk"), - DT_CLK(NULL, "div_ts_ck", "div_ts_ck"), - DT_CLK(NULL, "bandgap_ts_fclk", "bandgap_ts_fclk"), { .node_name = NULL }, }; @@ -278,6 +92,8 @@ int __init omap4xxx_dt_clk_init(void) omap2_clk_disable_autoidle_all(); + ti_clk_add_aliases(); + /* * Lock USB DPLL on OMAP4 devices so that the L3INIT power * domain can transition to retention state when not in use. diff --git a/drivers/clk/ti/clk-dra7-atl.c b/drivers/clk/ti/clk-dra7-atl.c index 45d05339d583..13eb04f72389 100644 --- a/drivers/clk/ti/clk-dra7-atl.c +++ b/drivers/clk/ti/clk-dra7-atl.c @@ -24,6 +24,9 @@ #include <linux/of_address.h> #include <linux/platform_device.h> #include <linux/pm_runtime.h> +#include <linux/clk/ti.h> + +#include "clock.h" #define DRA7_ATL_INSTANCES 4 @@ -171,6 +174,7 @@ static void __init of_dra7_atl_clock_setup(struct device_node *node) struct clk_init_data init = { NULL }; const char **parent_names = NULL; struct clk *clk; + int ret; clk_hw = kzalloc(sizeof(*clk_hw), GFP_KERNEL); if (!clk_hw) { @@ -200,9 +204,14 @@ static void __init of_dra7_atl_clock_setup(struct device_node *node) init.parent_names = parent_names; - clk = clk_register(NULL, &clk_hw->hw); + clk = ti_clk_register(NULL, &clk_hw->hw, node->name); if (!IS_ERR(clk)) { + ret = ti_clk_add_alias(NULL, clk, node->name); + if (ret) { + clk_unregister(clk); + goto cleanup; + } of_clk_add_provider(node, of_clk_src_simple_get, clk); kfree(parent_names); return; diff --git a/drivers/clk/ti/clk.c b/drivers/clk/ti/clk.c index 5fcf247759ac..ddbad7e8d7c9 100644 --- a/drivers/clk/ti/clk.c +++ b/drivers/clk/ti/clk.c @@ -24,6 +24,7 @@ #include <linux/list.h> #include <linux/regmap.h> #include <linux/bootmem.h> +#include <linux/device.h> #include "clock.h" @@ -42,27 +43,29 @@ struct clk_iomap { static struct clk_iomap *clk_memmaps[CLK_MAX_MEMMAPS]; -static void clk_memmap_writel(u32 val, void __iomem *reg) +static void clk_memmap_writel(u32 val, const struct clk_omap_reg *reg) { - struct clk_omap_reg *r = (struct clk_omap_reg *)® - struct clk_iomap *io = clk_memmaps[r->index]; + struct clk_iomap *io = clk_memmaps[reg->index]; - if (io->regmap) - regmap_write(io->regmap, r->offset, val); + if (reg->ptr) + writel_relaxed(val, reg->ptr); + else if (io->regmap) + regmap_write(io->regmap, reg->offset, val); else - writel_relaxed(val, io->mem + r->offset); + writel_relaxed(val, io->mem + reg->offset); } -static u32 clk_memmap_readl(void __iomem *reg) +static u32 clk_memmap_readl(const struct clk_omap_reg *reg) { u32 val; - struct clk_omap_reg *r = (struct clk_omap_reg *)® - struct clk_iomap *io = clk_memmaps[r->index]; + struct clk_iomap *io = clk_memmaps[reg->index]; - if (io->regmap) - regmap_read(io->regmap, r->offset, &val); + if (reg->ptr) + val = readl_relaxed(reg->ptr); + else if (io->regmap) + regmap_read(io->regmap, reg->offset, &val); else - val = readl_relaxed(io->mem + r->offset); + val = readl_relaxed(io->mem + reg->offset); return val; } @@ -161,20 +164,18 @@ int __init ti_clk_retry_init(struct device_node *node, struct clk_hw *hw, * ti_clk_get_reg_addr - get register address for a clock register * @node: device node for the clock * @index: register index from the clock node + * @reg: pointer to target register struct * - * Builds clock register address from device tree information. This - * is a struct of type clk_omap_reg. Returns a pointer to the register - * address, or a pointer error value in failure. + * Builds clock register address from device tree information, and returns + * the data via the provided output pointer @reg. Returns 0 on success, + * negative error value on failure. */ -void __iomem *ti_clk_get_reg_addr(struct device_node *node, int index) +int ti_clk_get_reg_addr(struct device_node *node, int index, + struct clk_omap_reg *reg) { - struct clk_omap_reg *reg; u32 val; - u32 tmp; int i; - reg = (struct clk_omap_reg *)&tmp; - for (i = 0; i < CLK_MAX_MEMMAPS; i++) { if (clocks_node_ptr[i] == node->parent) break; @@ -182,19 +183,20 @@ void __iomem *ti_clk_get_reg_addr(struct device_node *node, int index) if (i == CLK_MAX_MEMMAPS) { pr_err("clk-provider not found for %s!\n", node->name); - return IOMEM_ERR_PTR(-ENOENT); + return -ENOENT; } reg->index = i; if (of_property_read_u32_index(node, "reg", index, &val)) { pr_err("%s must have reg[%d]!\n", node->name, index); - return IOMEM_ERR_PTR(-EINVAL); + return -EINVAL; } reg->offset = val; + reg->ptr = NULL; - return (__force void __iomem *)tmp; + return 0; } /** @@ -297,6 +299,7 @@ struct clk __init *ti_clk_register_clk(struct ti_clk *setup) struct ti_clk_fixed *fixed; struct ti_clk_fixed_factor *fixed_factor; struct clk_hw *clk_hw; + int ret; if (setup->clk) return setup->clk; @@ -307,6 +310,13 @@ struct clk __init *ti_clk_register_clk(struct ti_clk *setup) clk = clk_register_fixed_rate(NULL, setup->name, NULL, 0, fixed->frequency); + if (!IS_ERR(clk)) { + ret = ti_clk_add_alias(NULL, clk, setup->name); + if (ret) { + clk_unregister(clk); + clk = ERR_PTR(ret); + } + } break; case TI_CLK_MUX: clk = ti_clk_register_mux(setup); @@ -324,6 +334,13 @@ struct clk __init *ti_clk_register_clk(struct ti_clk *setup) fixed_factor->parent, 0, fixed_factor->mult, fixed_factor->div); + if (!IS_ERR(clk)) { + ret = ti_clk_add_alias(NULL, clk, setup->name); + if (ret) { + clk_unregister(clk); + clk = ERR_PTR(ret); + } + } break; case TI_CLK_GATE: clk = ti_clk_register_gate(setup); @@ -354,6 +371,12 @@ struct clk __init *ti_clk_register_clk(struct ti_clk *setup) return clk; } +static const struct of_device_id simple_clk_match_table[] __initconst = { + { .compatible = "fixed-clock" }, + { .compatible = "fixed-factor-clock" }, + { } +}; + int __init ti_clk_register_legacy_clks(struct ti_clk_alias *clks) { struct clk *clk; @@ -371,9 +394,6 @@ int __init ti_clk_register_legacy_clks(struct ti_clk_alias *clks) clks->clk->name, PTR_ERR(clk)); return PTR_ERR(clk); } - } else { - clks->lk.clk = clk; - clkdev_add(&clks->lk); } clks++; } @@ -396,8 +416,6 @@ int __init ti_clk_register_legacy_clks(struct ti_clk_alias *clks) } } else { retry = true; - retry_clk->lk.clk = clk; - clkdev_add(&retry_clk->lk); list_del(&retry_clk->link); } } @@ -408,6 +426,26 @@ int __init ti_clk_register_legacy_clks(struct ti_clk_alias *clks) #endif /** + * ti_clk_add_aliases - setup clock aliases + * + * Sets up any missing clock aliases. No return value. + */ +void __init ti_clk_add_aliases(void) +{ + struct device_node *np; + struct clk *clk; + + for_each_matching_node(np, simple_clk_match_table) { + struct of_phandle_args clkspec; + + clkspec.np = np; + clk = of_clk_get_from_provider(&clkspec); + + ti_clk_add_alias(NULL, clk, np->name); + } +} + +/** * ti_clk_setup_features - setup clock features flags * @features: features definition to use * @@ -453,3 +491,66 @@ void omap2_clk_enable_init_clocks(const char **clk_names, u8 num_clocks) clk_prepare_enable(init_clk); } } + +/** + * ti_clk_add_alias - add a clock alias for a TI clock + * @dev: device alias for this clock + * @clk: clock handle to create alias for + * @con: connection ID for this clock + * + * Creates a clock alias for a TI clock. Allocates the clock lookup entry + * and assigns the data to it. Returns 0 if successful, negative error + * value otherwise. + */ +int ti_clk_add_alias(struct device *dev, struct clk *clk, const char *con) +{ + struct clk_lookup *cl; + + if (!clk) + return 0; + + if (IS_ERR(clk)) + return PTR_ERR(clk); + + cl = kzalloc(sizeof(*cl), GFP_KERNEL); + if (!cl) + return -ENOMEM; + + if (dev) + cl->dev_id = dev_name(dev); + cl->con_id = con; + cl->clk = clk; + + clkdev_add(cl); + + return 0; +} + +/** + * ti_clk_register - register a TI clock to the common clock framework + * @dev: device for this clock + * @hw: hardware clock handle + * @con: connection ID for this clock + * + * Registers a TI clock to the common clock framework, and adds a clock + * alias for it. Returns a handle to the registered clock if successful, + * ERR_PTR value in failure. + */ +struct clk *ti_clk_register(struct device *dev, struct clk_hw *hw, + const char *con) +{ + struct clk *clk; + int ret; + + clk = clk_register(dev, hw); + if (IS_ERR(clk)) + return clk; + + ret = ti_clk_add_alias(dev, clk, con); + if (ret) { + clk_unregister(clk); + return ERR_PTR(ret); + } + + return clk; +} diff --git a/drivers/clk/ti/clkt_dflt.c b/drivers/clk/ti/clkt_dflt.c index c6ae563801d7..91751dd26b16 100644 --- a/drivers/clk/ti/clkt_dflt.c +++ b/drivers/clk/ti/clkt_dflt.c @@ -55,7 +55,8 @@ * elapsed. XXX Deprecated - should be moved into drivers for the * individual IP block that the IDLEST register exists in. */ -static int _wait_idlest_generic(struct clk_hw_omap *clk, void __iomem *reg, +static int _wait_idlest_generic(struct clk_hw_omap *clk, + struct clk_omap_reg *reg, u32 mask, u8 idlest, const char *name) { int i = 0, ena = 0; @@ -91,7 +92,7 @@ static int _wait_idlest_generic(struct clk_hw_omap *clk, void __iomem *reg, */ static void _omap2_module_wait_ready(struct clk_hw_omap *clk) { - void __iomem *companion_reg, *idlest_reg; + struct clk_omap_reg companion_reg, idlest_reg; u8 other_bit, idlest_bit, idlest_val, idlest_reg_id; s16 prcm_mod; int r; @@ -99,17 +100,17 @@ static void _omap2_module_wait_ready(struct clk_hw_omap *clk) /* Not all modules have multiple clocks that their IDLEST depends on */ if (clk->ops->find_companion) { clk->ops->find_companion(clk, &companion_reg, &other_bit); - if (!(ti_clk_ll_ops->clk_readl(companion_reg) & + if (!(ti_clk_ll_ops->clk_readl(&companion_reg) & (1 << other_bit))) return; } clk->ops->find_idlest(clk, &idlest_reg, &idlest_bit, &idlest_val); - r = ti_clk_ll_ops->cm_split_idlest_reg(idlest_reg, &prcm_mod, + r = ti_clk_ll_ops->cm_split_idlest_reg(&idlest_reg, &prcm_mod, &idlest_reg_id); if (r) { /* IDLEST register not in the CM module */ - _wait_idlest_generic(clk, idlest_reg, (1 << idlest_bit), + _wait_idlest_generic(clk, &idlest_reg, (1 << idlest_bit), idlest_val, clk_hw_get_name(&clk->hw)); } else { ti_clk_ll_ops->cm_wait_module_ready(0, prcm_mod, idlest_reg_id, @@ -139,17 +140,17 @@ static void _omap2_module_wait_ready(struct clk_hw_omap *clk) * avoid this issue, and remove the casts. No return value. */ void omap2_clk_dflt_find_companion(struct clk_hw_omap *clk, - void __iomem **other_reg, u8 *other_bit) + struct clk_omap_reg *other_reg, + u8 *other_bit) { - u32 r; + memcpy(other_reg, &clk->enable_reg, sizeof(*other_reg)); /* * Convert CM_ICLKEN* <-> CM_FCLKEN*. This conversion assumes * it's just a matter of XORing the bits. */ - r = ((__force u32)clk->enable_reg ^ (CM_FCLKEN ^ CM_ICLKEN)); + other_reg->offset ^= (CM_FCLKEN ^ CM_ICLKEN); - *other_reg = (__force void __iomem *)r; *other_bit = clk->enable_bit; } @@ -168,13 +169,14 @@ void omap2_clk_dflt_find_companion(struct clk_hw_omap *clk, * CM_IDLEST2). This is not true for all modules. No return value. */ void omap2_clk_dflt_find_idlest(struct clk_hw_omap *clk, - void __iomem **idlest_reg, u8 *idlest_bit, + struct clk_omap_reg *idlest_reg, u8 *idlest_bit, u8 *idlest_val) { - u32 r; + memcpy(idlest_reg, &clk->enable_reg, sizeof(*idlest_reg)); + + idlest_reg->offset &= ~0xf0; + idlest_reg->offset |= 0x20; - r = (((__force u32)clk->enable_reg & ~0xf0) | 0x20); - *idlest_reg = (__force void __iomem *)r; *idlest_bit = clk->enable_bit; /* @@ -222,31 +224,19 @@ int omap2_dflt_clk_enable(struct clk_hw *hw) } } - if (IS_ERR(clk->enable_reg)) { - pr_err("%s: %s missing enable_reg\n", __func__, - clk_hw_get_name(hw)); - ret = -EINVAL; - goto err; - } - /* FIXME should not have INVERT_ENABLE bit here */ - v = ti_clk_ll_ops->clk_readl(clk->enable_reg); + v = ti_clk_ll_ops->clk_readl(&clk->enable_reg); if (clk->flags & INVERT_ENABLE) v &= ~(1 << clk->enable_bit); else v |= (1 << clk->enable_bit); - ti_clk_ll_ops->clk_writel(v, clk->enable_reg); - v = ti_clk_ll_ops->clk_readl(clk->enable_reg); /* OCP barrier */ + ti_clk_ll_ops->clk_writel(v, &clk->enable_reg); + v = ti_clk_ll_ops->clk_readl(&clk->enable_reg); /* OCP barrier */ if (clk->ops && clk->ops->find_idlest) _omap2_module_wait_ready(clk); return 0; - -err: - if (clkdm_control && clk->clkdm) - ti_clk_ll_ops->clkdm_clk_disable(clk->clkdm, hw->clk); - return ret; } /** @@ -264,22 +254,13 @@ void omap2_dflt_clk_disable(struct clk_hw *hw) u32 v; clk = to_clk_hw_omap(hw); - if (IS_ERR(clk->enable_reg)) { - /* - * 'independent' here refers to a clock which is not - * controlled by its parent. - */ - pr_err("%s: independent clock %s has no enable_reg\n", - __func__, clk_hw_get_name(hw)); - return; - } - v = ti_clk_ll_ops->clk_readl(clk->enable_reg); + v = ti_clk_ll_ops->clk_readl(&clk->enable_reg); if (clk->flags & INVERT_ENABLE) v |= (1 << clk->enable_bit); else v &= ~(1 << clk->enable_bit); - ti_clk_ll_ops->clk_writel(v, clk->enable_reg); + ti_clk_ll_ops->clk_writel(v, &clk->enable_reg); /* No OCP barrier needed here since it is a disable operation */ if (!(ti_clk_get_features()->flags & TI_CLK_DISABLE_CLKDM_CONTROL) && @@ -300,7 +281,7 @@ int omap2_dflt_clk_is_enabled(struct clk_hw *hw) struct clk_hw_omap *clk = to_clk_hw_omap(hw); u32 v; - v = ti_clk_ll_ops->clk_readl(clk->enable_reg); + v = ti_clk_ll_ops->clk_readl(&clk->enable_reg); if (clk->flags & INVERT_ENABLE) v ^= BIT(clk->enable_bit); diff --git a/drivers/clk/ti/clkt_dpll.c b/drivers/clk/ti/clkt_dpll.c index b919fdfe8256..ce98da2c10be 100644 --- a/drivers/clk/ti/clkt_dpll.c +++ b/drivers/clk/ti/clkt_dpll.c @@ -213,7 +213,7 @@ u8 omap2_init_dpll_parent(struct clk_hw *hw) if (!dd) return -EINVAL; - v = ti_clk_ll_ops->clk_readl(dd->control_reg); + v = ti_clk_ll_ops->clk_readl(&dd->control_reg); v &= dd->enable_mask; v >>= __ffs(dd->enable_mask); @@ -249,14 +249,14 @@ unsigned long omap2_get_dpll_rate(struct clk_hw_omap *clk) return 0; /* Return bypass rate if DPLL is bypassed */ - v = ti_clk_ll_ops->clk_readl(dd->control_reg); + v = ti_clk_ll_ops->clk_readl(&dd->control_reg); v &= dd->enable_mask; v >>= __ffs(dd->enable_mask); if (_omap2_dpll_is_in_bypass(v)) return clk_hw_get_rate(dd->clk_bypass); - v = ti_clk_ll_ops->clk_readl(dd->mult_div1_reg); + v = ti_clk_ll_ops->clk_readl(&dd->mult_div1_reg); dpll_mult = v & dd->mult_mask; dpll_mult >>= __ffs(dd->mult_mask); dpll_div = v & dd->div1_mask; diff --git a/drivers/clk/ti/clkt_iclk.c b/drivers/clk/ti/clkt_iclk.c index 38c36908cf88..60b583d7db33 100644 --- a/drivers/clk/ti/clkt_iclk.c +++ b/drivers/clk/ti/clkt_iclk.c @@ -31,28 +31,29 @@ void omap2_clkt_iclk_allow_idle(struct clk_hw_omap *clk) { u32 v; - void __iomem *r; + struct clk_omap_reg r; - r = (__force void __iomem *) - ((__force u32)clk->enable_reg ^ (CM_AUTOIDLE ^ CM_ICLKEN)); + memcpy(&r, &clk->enable_reg, sizeof(r)); + r.offset ^= (CM_AUTOIDLE ^ CM_ICLKEN); - v = ti_clk_ll_ops->clk_readl(r); + v = ti_clk_ll_ops->clk_readl(&r); v |= (1 << clk->enable_bit); - ti_clk_ll_ops->clk_writel(v, r); + ti_clk_ll_ops->clk_writel(v, &r); } /* XXX */ void omap2_clkt_iclk_deny_idle(struct clk_hw_omap *clk) { u32 v; - void __iomem *r; + struct clk_omap_reg r; - r = (__force void __iomem *) - ((__force u32)clk->enable_reg ^ (CM_AUTOIDLE ^ CM_ICLKEN)); + memcpy(&r, &clk->enable_reg, sizeof(r)); - v = ti_clk_ll_ops->clk_readl(r); + r.offset ^= (CM_AUTOIDLE ^ CM_ICLKEN); + + v = ti_clk_ll_ops->clk_readl(&r); v &= ~(1 << clk->enable_bit); - ti_clk_ll_ops->clk_writel(v, r); + ti_clk_ll_ops->clk_writel(v, &r); } /** @@ -68,14 +69,12 @@ void omap2_clkt_iclk_deny_idle(struct clk_hw_omap *clk) * modules. No return value. */ static void omap2430_clk_i2chs_find_idlest(struct clk_hw_omap *clk, - void __iomem **idlest_reg, + struct clk_omap_reg *idlest_reg, u8 *idlest_bit, u8 *idlest_val) { - u32 r; - - r = ((__force u32)clk->enable_reg ^ (OMAP24XX_CM_FCLKEN2 ^ CM_IDLEST)); - *idlest_reg = (__force void __iomem *)r; + memcpy(idlest_reg, &clk->enable_reg, sizeof(*idlest_reg)); + idlest_reg->offset ^= (OMAP24XX_CM_FCLKEN2 ^ CM_IDLEST); *idlest_bit = clk->enable_bit; *idlest_val = OMAP24XX_CM_IDLEST_VAL; } diff --git a/drivers/clk/ti/clock.h b/drivers/clk/ti/clock.h index 13c37f48d9d6..3f7b26540be8 100644 --- a/drivers/clk/ti/clock.h +++ b/drivers/clk/ti/clock.h @@ -16,6 +16,28 @@ #ifndef __DRIVERS_CLK_TI_CLOCK__ #define __DRIVERS_CLK_TI_CLOCK__ +struct clk_omap_divider { + struct clk_hw hw; + struct clk_omap_reg reg; + u8 shift; + u8 width; + u8 flags; + const struct clk_div_table *table; +}; + +#define to_clk_omap_divider(_hw) container_of(_hw, struct clk_omap_divider, hw) + +struct clk_omap_mux { + struct clk_hw hw; + struct clk_omap_reg reg; + u32 *table; + u32 mask; + u8 shift; + u8 flags; +}; + +#define to_clk_omap_mux(_hw) container_of(_hw, struct clk_omap_mux, hw) + enum { TI_CLK_FIXED, TI_CLK_MUX, @@ -86,7 +108,7 @@ struct ti_clk_mux { int num_parents; u16 reg; u8 module; - const char **parents; + const char * const *parents; u16 flags; }; @@ -189,16 +211,25 @@ struct clk *ti_clk_register_mux(struct ti_clk *setup); struct clk *ti_clk_register_divider(struct ti_clk *setup); struct clk *ti_clk_register_composite(struct ti_clk *setup); struct clk *ti_clk_register_dpll(struct ti_clk *setup); +struct clk *ti_clk_register(struct device *dev, struct clk_hw *hw, + const char *con); +int ti_clk_add_alias(struct device *dev, struct clk *clk, const char *con); +void ti_clk_add_aliases(void); struct clk_hw *ti_clk_build_component_div(struct ti_clk_divider *setup); struct clk_hw *ti_clk_build_component_gate(struct ti_clk_gate *setup); struct clk_hw *ti_clk_build_component_mux(struct ti_clk_mux *setup); +int ti_clk_parse_divider_data(int *div_table, int num_dividers, int max_div, + u8 flags, u8 *width, + const struct clk_div_table **table); + void ti_clk_patch_legacy_clks(struct ti_clk **patch); struct clk *ti_clk_register_clk(struct ti_clk *setup); int ti_clk_register_legacy_clks(struct ti_clk_alias *clks); -void __iomem *ti_clk_get_reg_addr(struct device_node *node, int index); +int ti_clk_get_reg_addr(struct device_node *node, int index, + struct clk_omap_reg *reg); void ti_dt_clocks_register(struct ti_dt_clk *oclks); int ti_clk_retry_init(struct device_node *node, struct clk_hw *hw, ti_of_clk_init_cb_t func); @@ -223,7 +254,9 @@ extern const struct clk_hw_omap_ops clkhwops_am35xx_ipss_wait; extern const struct clk_ops ti_clk_divider_ops; extern const struct clk_ops ti_clk_mux_ops; +extern const struct clk_ops omap_gate_clk_ops; +void omap2_init_clk_clkdm(struct clk_hw *hw); int omap2_clkops_enable_clkdm(struct clk_hw *hw); void omap2_clkops_disable_clkdm(struct clk_hw *hw); @@ -231,10 +264,10 @@ int omap2_dflt_clk_enable(struct clk_hw *hw); void omap2_dflt_clk_disable(struct clk_hw *hw); int omap2_dflt_clk_is_enabled(struct clk_hw *hw); void omap2_clk_dflt_find_companion(struct clk_hw_omap *clk, - void __iomem **other_reg, + struct clk_omap_reg *other_reg, u8 *other_bit); void omap2_clk_dflt_find_idlest(struct clk_hw_omap *clk, - void __iomem **idlest_reg, + struct clk_omap_reg *idlest_reg, u8 *idlest_bit, u8 *idlest_val); void omap2_clkt_iclk_allow_idle(struct clk_hw_omap *clk); diff --git a/drivers/clk/ti/clockdomain.c b/drivers/clk/ti/clockdomain.c index 6cf9dd189a92..fbedc6a9fed0 100644 --- a/drivers/clk/ti/clockdomain.c +++ b/drivers/clk/ti/clockdomain.c @@ -52,10 +52,6 @@ int omap2_clkops_enable_clkdm(struct clk_hw *hw) return -EINVAL; } - if (unlikely(clk->enable_reg)) - pr_err("%s: %s: should use dflt_clk_enable ?!\n", __func__, - clk_hw_get_name(hw)); - if (ti_clk_get_features()->flags & TI_CLK_DISABLE_CLKDM_CONTROL) { pr_err("%s: %s: clkfw-based clockdomain control disabled ?!\n", __func__, clk_hw_get_name(hw)); @@ -90,10 +86,6 @@ void omap2_clkops_disable_clkdm(struct clk_hw *hw) return; } - if (unlikely(clk->enable_reg)) - pr_err("%s: %s: should use dflt_clk_disable ?!\n", __func__, - clk_hw_get_name(hw)); - if (ti_clk_get_features()->flags & TI_CLK_DISABLE_CLKDM_CONTROL) { pr_err("%s: %s: clkfw-based clockdomain control disabled ?!\n", __func__, clk_hw_get_name(hw)); @@ -103,6 +95,36 @@ void omap2_clkops_disable_clkdm(struct clk_hw *hw) ti_clk_ll_ops->clkdm_clk_disable(clk->clkdm, hw->clk); } +/** + * omap2_init_clk_clkdm - look up a clockdomain name, store pointer in clk + * @clk: OMAP clock struct ptr to use + * + * Convert a clockdomain name stored in a struct clk 'clk' into a + * clockdomain pointer, and save it into the struct clk. Intended to be + * called during clk_register(). No return value. + */ +void omap2_init_clk_clkdm(struct clk_hw *hw) +{ + struct clk_hw_omap *clk = to_clk_hw_omap(hw); + struct clockdomain *clkdm; + const char *clk_name; + + if (!clk->clkdm_name) + return; + + clk_name = __clk_get_name(hw->clk); + + clkdm = ti_clk_ll_ops->clkdm_lookup(clk->clkdm_name); + if (clkdm) { + pr_debug("clock: associated clk %s to clkdm %s\n", + clk_name, clk->clkdm_name); + clk->clkdm = clkdm; + } else { + pr_debug("clock: could not associate clk %s to clkdm %s\n", + clk_name, clk->clkdm_name); + } +} + static void __init of_ti_clockdomain_setup(struct device_node *node) { struct clk *clk; diff --git a/drivers/clk/ti/composite.c b/drivers/clk/ti/composite.c index 1cf70f452e1e..beea89463ca2 100644 --- a/drivers/clk/ti/composite.c +++ b/drivers/clk/ti/composite.c @@ -124,8 +124,9 @@ struct clk *ti_clk_register_composite(struct ti_clk *setup) struct clk_hw *mux; struct clk_hw *div; int num_parents = 1; - const char **parent_names = NULL; + const char * const *parent_names = NULL; struct clk *clk; + int ret; comp = setup->data; @@ -150,6 +151,12 @@ struct clk *ti_clk_register_composite(struct ti_clk *setup) &ti_composite_divider_ops, gate, &ti_composite_gate_ops, 0); + ret = ti_clk_add_alias(NULL, clk, setup->name); + if (ret) { + clk_unregister(clk); + return ERR_PTR(ret); + } + return clk; } #endif @@ -163,6 +170,7 @@ static void __init _register_composite(struct clk_hw *hw, int num_parents = 0; const char **parent_names = NULL; int i; + int ret; /* Check for presence of each component clock */ for (i = 0; i < CLK_COMPONENT_TYPE_MAX; i++) { @@ -217,8 +225,14 @@ static void __init _register_composite(struct clk_hw *hw, _get_hw(cclk, CLK_COMPONENT_TYPE_GATE), &ti_composite_gate_ops, 0); - if (!IS_ERR(clk)) + if (!IS_ERR(clk)) { + ret = ti_clk_add_alias(NULL, clk, node->name); + if (ret) { + clk_unregister(clk); + goto cleanup; + } of_clk_add_provider(node, of_clk_src_simple_get, clk); + } cleanup: /* Free component clock list entries */ diff --git a/drivers/clk/ti/divider.c b/drivers/clk/ti/divider.c index 6bb87784a0d6..d6dcb283b72b 100644 --- a/drivers/clk/ti/divider.c +++ b/drivers/clk/ti/divider.c @@ -39,7 +39,7 @@ static unsigned int _get_table_maxdiv(const struct clk_div_table *table) return maxdiv; } -static unsigned int _get_maxdiv(struct clk_divider *divider) +static unsigned int _get_maxdiv(struct clk_omap_divider *divider) { if (divider->flags & CLK_DIVIDER_ONE_BASED) return div_mask(divider); @@ -61,7 +61,7 @@ static unsigned int _get_table_div(const struct clk_div_table *table, return 0; } -static unsigned int _get_div(struct clk_divider *divider, unsigned int val) +static unsigned int _get_div(struct clk_omap_divider *divider, unsigned int val) { if (divider->flags & CLK_DIVIDER_ONE_BASED) return val; @@ -83,7 +83,7 @@ static unsigned int _get_table_val(const struct clk_div_table *table, return 0; } -static unsigned int _get_val(struct clk_divider *divider, u8 div) +static unsigned int _get_val(struct clk_omap_divider *divider, u8 div) { if (divider->flags & CLK_DIVIDER_ONE_BASED) return div; @@ -97,10 +97,10 @@ static unsigned int _get_val(struct clk_divider *divider, u8 div) static unsigned long ti_clk_divider_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) { - struct clk_divider *divider = to_clk_divider(hw); + struct clk_omap_divider *divider = to_clk_omap_divider(hw); unsigned int div, val; - val = ti_clk_ll_ops->clk_readl(divider->reg) >> divider->shift; + val = ti_clk_ll_ops->clk_readl(÷r->reg) >> divider->shift; val &= div_mask(divider); div = _get_div(divider, val); @@ -131,7 +131,7 @@ static bool _is_valid_table_div(const struct clk_div_table *table, return false; } -static bool _is_valid_div(struct clk_divider *divider, unsigned int div) +static bool _is_valid_div(struct clk_omap_divider *divider, unsigned int div) { if (divider->flags & CLK_DIVIDER_POWER_OF_TWO) return is_power_of_2(div); @@ -172,7 +172,7 @@ static int _div_round(const struct clk_div_table *table, static int ti_clk_divider_bestdiv(struct clk_hw *hw, unsigned long rate, unsigned long *best_parent_rate) { - struct clk_divider *divider = to_clk_divider(hw); + struct clk_omap_divider *divider = to_clk_omap_divider(hw); int i, bestdiv = 0; unsigned long parent_rate, best = 0, now, maxdiv; unsigned long parent_rate_saved = *best_parent_rate; @@ -239,14 +239,14 @@ static long ti_clk_divider_round_rate(struct clk_hw *hw, unsigned long rate, static int ti_clk_divider_set_rate(struct clk_hw *hw, unsigned long rate, unsigned long parent_rate) { - struct clk_divider *divider; + struct clk_omap_divider *divider; unsigned int div, value; u32 val; if (!hw || !rate) return -EINVAL; - divider = to_clk_divider(hw); + divider = to_clk_omap_divider(hw); div = DIV_ROUND_UP(parent_rate, rate); value = _get_val(divider, div); @@ -257,11 +257,11 @@ static int ti_clk_divider_set_rate(struct clk_hw *hw, unsigned long rate, if (divider->flags & CLK_DIVIDER_HIWORD_MASK) { val = div_mask(divider) << (divider->shift + 16); } else { - val = ti_clk_ll_ops->clk_readl(divider->reg); + val = ti_clk_ll_ops->clk_readl(÷r->reg); val &= ~(div_mask(divider) << divider->shift); } val |= value << divider->shift; - ti_clk_ll_ops->clk_writel(val, divider->reg); + ti_clk_ll_ops->clk_writel(val, ÷r->reg); return 0; } @@ -274,11 +274,12 @@ const struct clk_ops ti_clk_divider_ops = { static struct clk *_register_divider(struct device *dev, const char *name, const char *parent_name, - unsigned long flags, void __iomem *reg, + unsigned long flags, + struct clk_omap_reg *reg, u8 shift, u8 width, u8 clk_divider_flags, const struct clk_div_table *table) { - struct clk_divider *div; + struct clk_omap_divider *div; struct clk *clk; struct clk_init_data init; @@ -303,7 +304,7 @@ static struct clk *_register_divider(struct device *dev, const char *name, init.num_parents = (parent_name ? 1 : 0); /* struct clk_divider assignments */ - div->reg = reg; + memcpy(&div->reg, reg, sizeof(*reg)); div->shift = shift; div->width = width; div->flags = clk_divider_flags; @@ -311,7 +312,7 @@ static struct clk *_register_divider(struct device *dev, const char *name, div->table = table; /* register the clock */ - clk = clk_register(dev, &div->hw); + clk = ti_clk_register(dev, &div->hw, name); if (IS_ERR(clk)) kfree(div); @@ -319,20 +320,17 @@ static struct clk *_register_divider(struct device *dev, const char *name, return clk; } -static struct clk_div_table * -_get_div_table_from_setup(struct ti_clk_divider *setup, u8 *width) +int ti_clk_parse_divider_data(int *div_table, int num_dividers, int max_div, + u8 flags, u8 *width, + const struct clk_div_table **table) { int valid_div = 0; - struct clk_div_table *table; - int i; - int div; u32 val; - u8 flags; - - if (!setup->num_dividers) { - /* Clk divider table not provided, determine min/max divs */ - flags = setup->flags; + int div; + int i; + struct clk_div_table *tmp; + if (!div_table) { if (flags & CLKF_INDEX_STARTS_AT_ONE) val = 1; else @@ -340,7 +338,7 @@ _get_div_table_from_setup(struct ti_clk_divider *setup, u8 *width) div = 1; - while (div < setup->max_div) { + while (div < max_div) { if (flags & CLKF_INDEX_POWER_OF_TWO) div <<= 1; else @@ -349,37 +347,59 @@ _get_div_table_from_setup(struct ti_clk_divider *setup, u8 *width) } *width = fls(val); + *table = NULL; - return NULL; + return 0; } - for (i = 0; i < setup->num_dividers; i++) - if (setup->dividers[i]) + i = 0; + + while (!num_dividers || i < num_dividers) { + if (div_table[i] == -1) + break; + if (div_table[i]) valid_div++; + i++; + } - table = kzalloc(sizeof(*table) * (valid_div + 1), GFP_KERNEL); - if (!table) - return ERR_PTR(-ENOMEM); + num_dividers = i; + + tmp = kzalloc(sizeof(*tmp) * (valid_div + 1), GFP_KERNEL); + if (!tmp) + return -ENOMEM; valid_div = 0; *width = 0; - for (i = 0; i < setup->num_dividers; i++) - if (setup->dividers[i]) { - table[valid_div].div = setup->dividers[i]; - table[valid_div].val = i; + for (i = 0; i < num_dividers; i++) + if (div_table[i] > 0) { + tmp[valid_div].div = div_table[i]; + tmp[valid_div].val = i; valid_div++; *width = i; } *width = fls(*width); + *table = tmp; + + return 0; +} + +static const struct clk_div_table * +_get_div_table_from_setup(struct ti_clk_divider *setup, u8 *width) +{ + const struct clk_div_table *table = NULL; + + ti_clk_parse_divider_data(setup->dividers, setup->num_dividers, + setup->max_div, setup->flags, width, + &table); return table; } struct clk_hw *ti_clk_build_component_div(struct ti_clk_divider *setup) { - struct clk_divider *div; + struct clk_omap_divider *div; struct clk_omap_reg *reg; if (!setup) @@ -414,7 +434,7 @@ struct clk *ti_clk_register_divider(struct ti_clk *setup) u8 width; u32 flags = 0; u8 div_flags = 0; - struct clk_div_table *table; + const struct clk_div_table *table; struct clk *clk; div = setup->data; @@ -542,14 +562,15 @@ static int _get_divider_width(struct device_node *node, } static int __init ti_clk_divider_populate(struct device_node *node, - void __iomem **reg, const struct clk_div_table **table, + struct clk_omap_reg *reg, const struct clk_div_table **table, u32 *flags, u8 *div_flags, u8 *width, u8 *shift) { u32 val; + int ret; - *reg = ti_clk_get_reg_addr(node, 0); - if (IS_ERR(*reg)) - return PTR_ERR(*reg); + ret = ti_clk_get_reg_addr(node, 0, reg); + if (ret) + return ret; if (!of_property_read_u32(node, "ti,bit-shift", &val)) *shift = val; @@ -588,7 +609,7 @@ static void __init of_ti_divider_clk_setup(struct device_node *node) { struct clk *clk; const char *parent_name; - void __iomem *reg; + struct clk_omap_reg reg; u8 clk_divider_flags = 0; u8 width = 0; u8 shift = 0; @@ -601,7 +622,7 @@ static void __init of_ti_divider_clk_setup(struct device_node *node) &clk_divider_flags, &width, &shift)) goto cleanup; - clk = _register_divider(NULL, node->name, parent_name, flags, reg, + clk = _register_divider(NULL, node->name, parent_name, flags, ®, shift, width, clk_divider_flags, table); if (!IS_ERR(clk)) { @@ -617,7 +638,7 @@ CLK_OF_DECLARE(divider_clk, "ti,divider-clock", of_ti_divider_clk_setup); static void __init of_ti_composite_divider_clk_setup(struct device_node *node) { - struct clk_divider *div; + struct clk_omap_divider *div; u32 val; div = kzalloc(sizeof(*div), GFP_KERNEL); diff --git a/drivers/clk/ti/dpll.c b/drivers/clk/ti/dpll.c index 4b9a419d8e14..96d84888c6c5 100644 --- a/drivers/clk/ti/dpll.c +++ b/drivers/clk/ti/dpll.c @@ -185,7 +185,7 @@ static void __init _register_dpll(struct clk_hw *hw, dd->clk_bypass = __clk_get_hw(clk); /* register the clock */ - clk = clk_register(NULL, &clk_hw->hw); + clk = ti_clk_register(NULL, &clk_hw->hw, node->name); if (!IS_ERR(clk)) { omap2_init_clk_hw_omap_clocks(&clk_hw->hw); @@ -203,17 +203,10 @@ cleanup: } #if defined(CONFIG_ARCH_OMAP3) && defined(CONFIG_ATAGS) -static void __iomem *_get_reg(u8 module, u16 offset) +void _get_reg(u8 module, u16 offset, struct clk_omap_reg *reg) { - u32 reg; - struct clk_omap_reg *reg_setup; - - reg_setup = (struct clk_omap_reg *)® - - reg_setup->index = module; - reg_setup->offset = offset; - - return (void __iomem *)reg; + reg->index = module; + reg->offset = offset; } struct clk *ti_clk_register_dpll(struct ti_clk *setup) @@ -248,7 +241,6 @@ struct clk *ti_clk_register_dpll(struct ti_clk *setup) clk_hw->dpll_data = dd; clk_hw->ops = &clkhwops_omap3_dpll; clk_hw->hw.init = &init; - clk_hw->flags = MEMMAP_ADDRESSING; init.name = setup->name; init.ops = ops; @@ -256,10 +248,10 @@ struct clk *ti_clk_register_dpll(struct ti_clk *setup) init.num_parents = dpll->num_parents; init.parent_names = dpll->parents; - dd->control_reg = _get_reg(dpll->module, dpll->control_reg); - dd->idlest_reg = _get_reg(dpll->module, dpll->idlest_reg); - dd->mult_div1_reg = _get_reg(dpll->module, dpll->mult_div1_reg); - dd->autoidle_reg = _get_reg(dpll->module, dpll->autoidle_reg); + _get_reg(dpll->module, dpll->control_reg, &dd->control_reg); + _get_reg(dpll->module, dpll->idlest_reg, &dd->idlest_reg); + _get_reg(dpll->module, dpll->mult_div1_reg, &dd->mult_div1_reg); + _get_reg(dpll->module, dpll->autoidle_reg, &dd->autoidle_reg); dd->modes = dpll->modes; dd->div1_mask = dpll->div1_mask; @@ -288,7 +280,7 @@ struct clk *ti_clk_register_dpll(struct ti_clk *setup) if (dpll->flags & CLKF_J_TYPE) dd->flags |= DPLL_J_TYPE; - clk = clk_register(NULL, &clk_hw->hw); + clk = ti_clk_register(NULL, &clk_hw->hw, setup->name); if (!IS_ERR(clk)) return clk; @@ -320,6 +312,7 @@ static void _register_dpll_x2(struct device_node *node, struct clk_hw_omap *clk_hw; const char *name = node->name; const char *parent_name; + int ret; parent_name = of_clk_get_parent_name(node, 0); if (!parent_name) { @@ -339,8 +332,19 @@ static void _register_dpll_x2(struct device_node *node, init.parent_names = &parent_name; init.num_parents = 1; + if (hw_ops == &clkhwops_omap4_dpllmx) { + /* Check if register defined, if not, drop hw-ops */ + ret = of_property_count_elems_of_size(node, "reg", 1); + if (ret <= 0) { + hw_ops = NULL; + } else if (ti_clk_get_reg_addr(node, 0, &clk_hw->clksel_reg)) { + kfree(clk_hw); + return; + } + } + /* register the clock */ - clk = clk_register(NULL, &clk_hw->hw); + clk = ti_clk_register(NULL, &clk_hw->hw, name); if (IS_ERR(clk)) { kfree(clk_hw); @@ -380,7 +384,6 @@ static void __init of_ti_dpll_setup(struct device_node *node, clk_hw->dpll_data = dd; clk_hw->ops = &clkhwops_omap3_dpll; clk_hw->hw.init = init; - clk_hw->flags = MEMMAP_ADDRESSING; init->name = node->name; init->ops = ops; @@ -399,7 +402,8 @@ static void __init of_ti_dpll_setup(struct device_node *node, init->parent_names = parent_names; - dd->control_reg = ti_clk_get_reg_addr(node, 0); + if (ti_clk_get_reg_addr(node, 0, &dd->control_reg)) + goto cleanup; /* * Special case for OMAP2 DPLL, register order is different due to @@ -407,25 +411,22 @@ static void __init of_ti_dpll_setup(struct device_node *node, * missing idlest_mask. */ if (!dd->idlest_mask) { - dd->mult_div1_reg = ti_clk_get_reg_addr(node, 1); + if (ti_clk_get_reg_addr(node, 1, &dd->mult_div1_reg)) + goto cleanup; #ifdef CONFIG_ARCH_OMAP2 clk_hw->ops = &clkhwops_omap2xxx_dpll; omap2xxx_clkt_dpllcore_init(&clk_hw->hw); #endif } else { - dd->idlest_reg = ti_clk_get_reg_addr(node, 1); - if (IS_ERR(dd->idlest_reg)) + if (ti_clk_get_reg_addr(node, 1, &dd->idlest_reg)) goto cleanup; - dd->mult_div1_reg = ti_clk_get_reg_addr(node, 2); + if (ti_clk_get_reg_addr(node, 2, &dd->mult_div1_reg)) + goto cleanup; } - if (IS_ERR(dd->control_reg) || IS_ERR(dd->mult_div1_reg)) - goto cleanup; - if (dd->autoidle_mask) { - dd->autoidle_reg = ti_clk_get_reg_addr(node, 3); - if (IS_ERR(dd->autoidle_reg)) + if (ti_clk_get_reg_addr(node, 3, &dd->autoidle_reg)) goto cleanup; } diff --git a/drivers/clk/ti/dpll3xxx.c b/drivers/clk/ti/dpll3xxx.c index 4cdd28a25584..4534de2ef455 100644 --- a/drivers/clk/ti/dpll3xxx.c +++ b/drivers/clk/ti/dpll3xxx.c @@ -54,10 +54,10 @@ static void _omap3_dpll_write_clken(struct clk_hw_omap *clk, u8 clken_bits) dd = clk->dpll_data; - v = ti_clk_ll_ops->clk_readl(dd->control_reg); + v = ti_clk_ll_ops->clk_readl(&dd->control_reg); v &= ~dd->enable_mask; v |= clken_bits << __ffs(dd->enable_mask); - ti_clk_ll_ops->clk_writel(v, dd->control_reg); + ti_clk_ll_ops->clk_writel(v, &dd->control_reg); } /* _omap3_wait_dpll_status: wait for a DPLL to enter a specific state */ @@ -73,7 +73,7 @@ static int _omap3_wait_dpll_status(struct clk_hw_omap *clk, u8 state) state <<= __ffs(dd->idlest_mask); - while (((ti_clk_ll_ops->clk_readl(dd->idlest_reg) & dd->idlest_mask) + while (((ti_clk_ll_ops->clk_readl(&dd->idlest_reg) & dd->idlest_mask) != state) && i < MAX_DPLL_WAIT_TRIES) { i++; udelay(1); @@ -151,7 +151,7 @@ static int _omap3_noncore_dpll_lock(struct clk_hw_omap *clk) state <<= __ffs(dd->idlest_mask); /* Check if already locked */ - if ((ti_clk_ll_ops->clk_readl(dd->idlest_reg) & dd->idlest_mask) == + if ((ti_clk_ll_ops->clk_readl(&dd->idlest_reg) & dd->idlest_mask) == state) goto done; @@ -317,14 +317,14 @@ static int omap3_noncore_dpll_program(struct clk_hw_omap *clk, u16 freqsel) * only since freqsel field is no longer present on other devices. */ if (ti_clk_get_features()->flags & TI_CLK_DPLL_HAS_FREQSEL) { - v = ti_clk_ll_ops->clk_readl(dd->control_reg); + v = ti_clk_ll_ops->clk_readl(&dd->control_reg); v &= ~dd->freqsel_mask; v |= freqsel << __ffs(dd->freqsel_mask); - ti_clk_ll_ops->clk_writel(v, dd->control_reg); + ti_clk_ll_ops->clk_writel(v, &dd->control_reg); } /* Set DPLL multiplier, divider */ - v = ti_clk_ll_ops->clk_readl(dd->mult_div1_reg); + v = ti_clk_ll_ops->clk_readl(&dd->mult_div1_reg); /* Handle Duty Cycle Correction */ if (dd->dcc_mask) { @@ -370,11 +370,11 @@ static int omap3_noncore_dpll_program(struct clk_hw_omap *clk, u16 freqsel) } } - ti_clk_ll_ops->clk_writel(v, dd->mult_div1_reg); + ti_clk_ll_ops->clk_writel(v, &dd->mult_div1_reg); /* Set 4X multiplier and low-power mode */ if (dd->m4xen_mask || dd->lpmode_mask) { - v = ti_clk_ll_ops->clk_readl(dd->control_reg); + v = ti_clk_ll_ops->clk_readl(&dd->control_reg); if (dd->m4xen_mask) { if (dd->last_rounded_m4xen) @@ -390,7 +390,7 @@ static int omap3_noncore_dpll_program(struct clk_hw_omap *clk, u16 freqsel) v &= ~dd->lpmode_mask; } - ti_clk_ll_ops->clk_writel(v, dd->control_reg); + ti_clk_ll_ops->clk_writel(v, &dd->control_reg); } /* We let the clock framework set the other output dividers later */ @@ -652,10 +652,10 @@ static u32 omap3_dpll_autoidle_read(struct clk_hw_omap *clk) dd = clk->dpll_data; - if (!dd->autoidle_reg) + if (!dd->autoidle_mask) return -EINVAL; - v = ti_clk_ll_ops->clk_readl(dd->autoidle_reg); + v = ti_clk_ll_ops->clk_readl(&dd->autoidle_reg); v &= dd->autoidle_mask; v >>= __ffs(dd->autoidle_mask); @@ -681,7 +681,7 @@ static void omap3_dpll_allow_idle(struct clk_hw_omap *clk) dd = clk->dpll_data; - if (!dd->autoidle_reg) + if (!dd->autoidle_mask) return; /* @@ -689,10 +689,10 @@ static void omap3_dpll_allow_idle(struct clk_hw_omap *clk) * by writing 0x5 instead of 0x1. Add some mechanism to * optionally enter this mode. */ - v = ti_clk_ll_ops->clk_readl(dd->autoidle_reg); + v = ti_clk_ll_ops->clk_readl(&dd->autoidle_reg); v &= ~dd->autoidle_mask; v |= DPLL_AUTOIDLE_LOW_POWER_STOP << __ffs(dd->autoidle_mask); - ti_clk_ll_ops->clk_writel(v, dd->autoidle_reg); + ti_clk_ll_ops->clk_writel(v, &dd->autoidle_reg); } /** @@ -711,13 +711,13 @@ static void omap3_dpll_deny_idle(struct clk_hw_omap *clk) dd = clk->dpll_data; - if (!dd->autoidle_reg) + if (!dd->autoidle_mask) return; - v = ti_clk_ll_ops->clk_readl(dd->autoidle_reg); + v = ti_clk_ll_ops->clk_readl(&dd->autoidle_reg); v &= ~dd->autoidle_mask; v |= DPLL_AUTOIDLE_DISABLE << __ffs(dd->autoidle_mask); - ti_clk_ll_ops->clk_writel(v, dd->autoidle_reg); + ti_clk_ll_ops->clk_writel(v, &dd->autoidle_reg); } /* Clock control for DPLL outputs */ @@ -773,7 +773,7 @@ unsigned long omap3_clkoutx2_recalc(struct clk_hw *hw, WARN_ON(!dd->enable_mask); - v = ti_clk_ll_ops->clk_readl(dd->control_reg) & dd->enable_mask; + v = ti_clk_ll_ops->clk_readl(&dd->control_reg) & dd->enable_mask; v >>= __ffs(dd->enable_mask); if ((v != OMAP3XXX_EN_DPLL_LOCKED) || (dd->flags & DPLL_J_TYPE)) rate = parent_rate; diff --git a/drivers/clk/ti/dpll44xx.c b/drivers/clk/ti/dpll44xx.c index 82c05b55a7be..d7a3f7ec8d77 100644 --- a/drivers/clk/ti/dpll44xx.c +++ b/drivers/clk/ti/dpll44xx.c @@ -42,17 +42,17 @@ static void omap4_dpllmx_allow_gatectrl(struct clk_hw_omap *clk) u32 v; u32 mask; - if (!clk || !clk->clksel_reg) + if (!clk) return; mask = clk->flags & CLOCK_CLKOUTX2 ? OMAP4430_DPLL_CLKOUTX2_GATE_CTRL_MASK : OMAP4430_DPLL_CLKOUT_GATE_CTRL_MASK; - v = ti_clk_ll_ops->clk_readl(clk->clksel_reg); + v = ti_clk_ll_ops->clk_readl(&clk->clksel_reg); /* Clear the bit to allow gatectrl */ v &= ~mask; - ti_clk_ll_ops->clk_writel(v, clk->clksel_reg); + ti_clk_ll_ops->clk_writel(v, &clk->clksel_reg); } static void omap4_dpllmx_deny_gatectrl(struct clk_hw_omap *clk) @@ -60,17 +60,17 @@ static void omap4_dpllmx_deny_gatectrl(struct clk_hw_omap *clk) u32 v; u32 mask; - if (!clk || !clk->clksel_reg) + if (!clk) return; mask = clk->flags & CLOCK_CLKOUTX2 ? OMAP4430_DPLL_CLKOUTX2_GATE_CTRL_MASK : OMAP4430_DPLL_CLKOUT_GATE_CTRL_MASK; - v = ti_clk_ll_ops->clk_readl(clk->clksel_reg); + v = ti_clk_ll_ops->clk_readl(&clk->clksel_reg); /* Set the bit to deny gatectrl */ v |= mask; - ti_clk_ll_ops->clk_writel(v, clk->clksel_reg); + ti_clk_ll_ops->clk_writel(v, &clk->clksel_reg); } const struct clk_hw_omap_ops clkhwops_omap4_dpllmx = { @@ -128,7 +128,7 @@ unsigned long omap4_dpll_regm4xen_recalc(struct clk_hw *hw, rate = omap2_get_dpll_rate(clk); /* regm4xen adds a multiplier of 4 to DPLL calculations */ - v = ti_clk_ll_ops->clk_readl(dd->control_reg); + v = ti_clk_ll_ops->clk_readl(&dd->control_reg); if (v & OMAP4430_DPLL_REGM4XEN_MASK) rate *= OMAP4430_REGM4XEN_MULT; diff --git a/drivers/clk/ti/fixed-factor.c b/drivers/clk/ti/fixed-factor.c index 3cd406768909..0174a51a4ba6 100644 --- a/drivers/clk/ti/fixed-factor.c +++ b/drivers/clk/ti/fixed-factor.c @@ -62,6 +62,7 @@ static void __init of_ti_fixed_factor_clk_setup(struct device_node *node) if (!IS_ERR(clk)) { of_clk_add_provider(node, of_clk_src_simple_get, clk); of_ti_clk_autoidle_setup(node); + ti_clk_add_alias(NULL, clk, clk_name); } } CLK_OF_DECLARE(ti_fixed_factor_clk, "ti,fixed-factor-clock", diff --git a/drivers/clk/ti/gate.c b/drivers/clk/ti/gate.c index bc05f276f32b..7151ec3a1b07 100644 --- a/drivers/clk/ti/gate.c +++ b/drivers/clk/ti/gate.c @@ -35,7 +35,7 @@ static const struct clk_ops omap_gate_clkdm_clk_ops = { .disable = &omap2_clkops_disable_clkdm, }; -static const struct clk_ops omap_gate_clk_ops = { +const struct clk_ops omap_gate_clk_ops = { .init = &omap2_init_clk_clkdm, .enable = &omap2_dflt_clk_enable, .disable = &omap2_dflt_clk_disable, @@ -62,7 +62,7 @@ static const struct clk_ops omap_gate_clk_hsdiv_restore_ops = { */ static int omap36xx_gate_clk_enable_with_hsdiv_restore(struct clk_hw *hw) { - struct clk_divider *parent; + struct clk_omap_divider *parent; struct clk_hw *parent_hw; u32 dummy_v, orig_v; int ret; @@ -72,19 +72,19 @@ static int omap36xx_gate_clk_enable_with_hsdiv_restore(struct clk_hw *hw) /* Parent is the x2 node, get parent of parent for the m2 div */ parent_hw = clk_hw_get_parent(clk_hw_get_parent(hw)); - parent = to_clk_divider(parent_hw); + parent = to_clk_omap_divider(parent_hw); /* Restore the dividers */ if (!ret) { - orig_v = ti_clk_ll_ops->clk_readl(parent->reg); + orig_v = ti_clk_ll_ops->clk_readl(&parent->reg); dummy_v = orig_v; /* Write any other value different from the Read value */ dummy_v ^= (1 << parent->shift); - ti_clk_ll_ops->clk_writel(dummy_v, parent->reg); + ti_clk_ll_ops->clk_writel(dummy_v, &parent->reg); /* Write the original divider */ - ti_clk_ll_ops->clk_writel(orig_v, parent->reg); + ti_clk_ll_ops->clk_writel(orig_v, &parent->reg); } return ret; @@ -92,7 +92,7 @@ static int omap36xx_gate_clk_enable_with_hsdiv_restore(struct clk_hw *hw) static struct clk *_register_gate(struct device *dev, const char *name, const char *parent_name, unsigned long flags, - void __iomem *reg, u8 bit_idx, + struct clk_omap_reg *reg, u8 bit_idx, u8 clk_gate_flags, const struct clk_ops *ops, const struct clk_hw_omap_ops *hw_ops) { @@ -109,18 +109,18 @@ static struct clk *_register_gate(struct device *dev, const char *name, init.name = name; init.ops = ops; - clk_hw->enable_reg = reg; + memcpy(&clk_hw->enable_reg, reg, sizeof(*reg)); clk_hw->enable_bit = bit_idx; clk_hw->ops = hw_ops; - clk_hw->flags = MEMMAP_ADDRESSING | clk_gate_flags; + clk_hw->flags = clk_gate_flags; init.parent_names = &parent_name; init.num_parents = 1; init.flags = flags; - clk = clk_register(NULL, &clk_hw->hw); + clk = ti_clk_register(NULL, &clk_hw->hw, name); if (IS_ERR(clk)) kfree(clk_hw); @@ -133,8 +133,7 @@ struct clk *ti_clk_register_gate(struct ti_clk *setup) { const struct clk_ops *ops = &omap_gate_clk_ops; const struct clk_hw_omap_ops *hw_ops = NULL; - u32 reg; - struct clk_omap_reg *reg_setup; + struct clk_omap_reg reg; u32 flags = 0; u8 clk_gate_flags = 0; struct ti_clk_gate *gate; @@ -144,8 +143,6 @@ struct clk *ti_clk_register_gate(struct ti_clk *setup) if (gate->flags & CLKF_INTERFACE) return ti_clk_register_interface(setup); - reg_setup = (struct clk_omap_reg *)® - if (gate->flags & CLKF_SET_RATE_PARENT) flags |= CLK_SET_RATE_PARENT; @@ -169,11 +166,12 @@ struct clk *ti_clk_register_gate(struct ti_clk *setup) if (gate->flags & CLKF_AM35XX) hw_ops = &clkhwops_am35xx_ipss_module_wait; - reg_setup->index = gate->module; - reg_setup->offset = gate->reg; + reg.index = gate->module; + reg.offset = gate->reg; + reg.ptr = NULL; return _register_gate(NULL, setup->name, gate->parent, flags, - (void __iomem *)reg, gate->bit_shift, + ®, gate->bit_shift, clk_gate_flags, ops, hw_ops); } @@ -203,7 +201,6 @@ struct clk_hw *ti_clk_build_component_gate(struct ti_clk_gate *setup) ops = &clkhwops_iclk_wait; gate->ops = ops; - gate->flags = MEMMAP_ADDRESSING; return &gate->hw; } @@ -215,15 +212,14 @@ static void __init _of_ti_gate_clk_setup(struct device_node *node, { struct clk *clk; const char *parent_name; - void __iomem *reg = NULL; + struct clk_omap_reg reg; u8 enable_bit = 0; u32 val; u32 flags = 0; u8 clk_gate_flags = 0; if (ops != &omap_gate_clkdm_clk_ops) { - reg = ti_clk_get_reg_addr(node, 0); - if (IS_ERR(reg)) + if (ti_clk_get_reg_addr(node, 0, ®)) return; if (!of_property_read_u32(node, "ti,bit-shift", &val)) @@ -243,7 +239,7 @@ static void __init _of_ti_gate_clk_setup(struct device_node *node, if (of_property_read_bool(node, "ti,set-bit-to-disable")) clk_gate_flags |= INVERT_ENABLE; - clk = _register_gate(NULL, node->name, parent_name, flags, reg, + clk = _register_gate(NULL, node->name, parent_name, flags, ®, enable_bit, clk_gate_flags, ops, hw_ops); if (!IS_ERR(clk)) @@ -261,15 +257,13 @@ _of_ti_composite_gate_clk_setup(struct device_node *node, if (!gate) return; - gate->enable_reg = ti_clk_get_reg_addr(node, 0); - if (IS_ERR(gate->enable_reg)) + if (ti_clk_get_reg_addr(node, 0, &gate->enable_reg)) goto cleanup; of_property_read_u32(node, "ti,bit-shift", &val); gate->enable_bit = val; gate->ops = hw_ops; - gate->flags = MEMMAP_ADDRESSING; if (!ti_clk_add_component(node, &gate->hw, CLK_COMPONENT_TYPE_GATE)) return; diff --git a/drivers/clk/ti/interface.c b/drivers/clk/ti/interface.c index e505e6f8228d..62cf50c1e1e3 100644 --- a/drivers/clk/ti/interface.c +++ b/drivers/clk/ti/interface.c @@ -34,7 +34,7 @@ static const struct clk_ops ti_interface_clk_ops = { static struct clk *_register_interface(struct device *dev, const char *name, const char *parent_name, - void __iomem *reg, u8 bit_idx, + struct clk_omap_reg *reg, u8 bit_idx, const struct clk_hw_omap_ops *ops) { struct clk_init_data init = { NULL }; @@ -47,8 +47,7 @@ static struct clk *_register_interface(struct device *dev, const char *name, clk_hw->hw.init = &init; clk_hw->ops = ops; - clk_hw->flags = MEMMAP_ADDRESSING; - clk_hw->enable_reg = reg; + memcpy(&clk_hw->enable_reg, reg, sizeof(*reg)); clk_hw->enable_bit = bit_idx; init.name = name; @@ -58,7 +57,7 @@ static struct clk *_register_interface(struct device *dev, const char *name, init.num_parents = 1; init.parent_names = &parent_name; - clk = clk_register(NULL, &clk_hw->hw); + clk = ti_clk_register(NULL, &clk_hw->hw, name); if (IS_ERR(clk)) kfree(clk_hw); @@ -72,14 +71,13 @@ static struct clk *_register_interface(struct device *dev, const char *name, struct clk *ti_clk_register_interface(struct ti_clk *setup) { const struct clk_hw_omap_ops *ops = &clkhwops_iclk_wait; - u32 reg; - struct clk_omap_reg *reg_setup; + struct clk_omap_reg reg; struct ti_clk_gate *gate; gate = setup->data; - reg_setup = (struct clk_omap_reg *)® - reg_setup->index = gate->module; - reg_setup->offset = gate->reg; + reg.index = gate->module; + reg.offset = gate->reg; + reg.ptr = NULL; if (gate->flags & CLKF_NO_WAIT) ops = &clkhwops_iclk; @@ -97,7 +95,7 @@ struct clk *ti_clk_register_interface(struct ti_clk *setup) ops = &clkhwops_am35xx_ipss_wait; return _register_interface(NULL, setup->name, gate->parent, - (void __iomem *)reg, gate->bit_shift, ops); + ®, gate->bit_shift, ops); } #endif @@ -106,12 +104,11 @@ static void __init _of_ti_interface_clk_setup(struct device_node *node, { struct clk *clk; const char *parent_name; - void __iomem *reg; + struct clk_omap_reg reg; u8 enable_bit = 0; u32 val; - reg = ti_clk_get_reg_addr(node, 0); - if (IS_ERR(reg)) + if (ti_clk_get_reg_addr(node, 0, ®)) return; if (!of_property_read_u32(node, "ti,bit-shift", &val)) @@ -123,7 +120,7 @@ static void __init _of_ti_interface_clk_setup(struct device_node *node, return; } - clk = _register_interface(NULL, node->name, parent_name, reg, + clk = _register_interface(NULL, node->name, parent_name, ®, enable_bit, ops); if (!IS_ERR(clk)) diff --git a/drivers/clk/ti/mux.c b/drivers/clk/ti/mux.c index 44777ab6fdeb..18c267b38461 100644 --- a/drivers/clk/ti/mux.c +++ b/drivers/clk/ti/mux.c @@ -28,7 +28,7 @@ static u8 ti_clk_mux_get_parent(struct clk_hw *hw) { - struct clk_mux *mux = to_clk_mux(hw); + struct clk_omap_mux *mux = to_clk_omap_mux(hw); int num_parents = clk_hw_get_num_parents(hw); u32 val; @@ -39,7 +39,7 @@ static u8 ti_clk_mux_get_parent(struct clk_hw *hw) * OTOH, pmd_trace_clk_mux_ck uses a separate bit for each clock, so * val = 0x4 really means "bit 2, index starts at bit 0" */ - val = ti_clk_ll_ops->clk_readl(mux->reg) >> mux->shift; + val = ti_clk_ll_ops->clk_readl(&mux->reg) >> mux->shift; val &= mux->mask; if (mux->table) { @@ -65,7 +65,7 @@ static u8 ti_clk_mux_get_parent(struct clk_hw *hw) static int ti_clk_mux_set_parent(struct clk_hw *hw, u8 index) { - struct clk_mux *mux = to_clk_mux(hw); + struct clk_omap_mux *mux = to_clk_omap_mux(hw); u32 val; if (mux->table) { @@ -81,11 +81,11 @@ static int ti_clk_mux_set_parent(struct clk_hw *hw, u8 index) if (mux->flags & CLK_MUX_HIWORD_MASK) { val = mux->mask << (mux->shift + 16); } else { - val = ti_clk_ll_ops->clk_readl(mux->reg); + val = ti_clk_ll_ops->clk_readl(&mux->reg); val &= ~(mux->mask << mux->shift); } val |= index << mux->shift; - ti_clk_ll_ops->clk_writel(val, mux->reg); + ti_clk_ll_ops->clk_writel(val, &mux->reg); return 0; } @@ -97,12 +97,12 @@ const struct clk_ops ti_clk_mux_ops = { }; static struct clk *_register_mux(struct device *dev, const char *name, - const char **parent_names, u8 num_parents, - unsigned long flags, void __iomem *reg, - u8 shift, u32 mask, u8 clk_mux_flags, - u32 *table) + const char * const *parent_names, + u8 num_parents, unsigned long flags, + struct clk_omap_reg *reg, u8 shift, u32 mask, + u8 clk_mux_flags, u32 *table) { - struct clk_mux *mux; + struct clk_omap_mux *mux; struct clk *clk; struct clk_init_data init; @@ -120,14 +120,14 @@ static struct clk *_register_mux(struct device *dev, const char *name, init.num_parents = num_parents; /* struct clk_mux assignments */ - mux->reg = reg; + memcpy(&mux->reg, reg, sizeof(*reg)); mux->shift = shift; mux->mask = mask; mux->flags = clk_mux_flags; mux->table = table; mux->hw.init = &init; - clk = clk_register(dev, &mux->hw); + clk = ti_clk_register(dev, &mux->hw, name); if (IS_ERR(clk)) kfree(mux); @@ -140,12 +140,9 @@ struct clk *ti_clk_register_mux(struct ti_clk *setup) struct ti_clk_mux *mux; u32 flags; u8 mux_flags = 0; - struct clk_omap_reg *reg_setup; - u32 reg; + struct clk_omap_reg reg; u32 mask; - reg_setup = (struct clk_omap_reg *)® - mux = setup->data; flags = CLK_SET_RATE_NO_REPARENT; @@ -154,8 +151,9 @@ struct clk *ti_clk_register_mux(struct ti_clk *setup) mask--; mask = (1 << fls(mask)) - 1; - reg_setup->index = mux->module; - reg_setup->offset = mux->reg; + reg.index = mux->module; + reg.offset = mux->reg; + reg.ptr = NULL; if (mux->flags & CLKF_INDEX_STARTS_AT_ONE) mux_flags |= CLK_MUX_INDEX_ONE; @@ -164,7 +162,7 @@ struct clk *ti_clk_register_mux(struct ti_clk *setup) flags |= CLK_SET_RATE_PARENT; return _register_mux(NULL, setup->name, mux->parents, mux->num_parents, - flags, (void __iomem *)reg, mux->bit_shift, mask, + flags, ®, mux->bit_shift, mask, mux_flags, NULL); } @@ -177,7 +175,7 @@ struct clk *ti_clk_register_mux(struct ti_clk *setup) static void of_mux_clk_setup(struct device_node *node) { struct clk *clk; - void __iomem *reg; + struct clk_omap_reg reg; unsigned int num_parents; const char **parent_names; u8 clk_mux_flags = 0; @@ -196,9 +194,7 @@ static void of_mux_clk_setup(struct device_node *node) of_clk_parent_fill(node, parent_names, num_parents); - reg = ti_clk_get_reg_addr(node, 0); - - if (IS_ERR(reg)) + if (ti_clk_get_reg_addr(node, 0, ®)) goto cleanup; of_property_read_u32(node, "ti,bit-shift", &shift); @@ -217,7 +213,7 @@ static void of_mux_clk_setup(struct device_node *node) mask = (1 << fls(mask)) - 1; clk = _register_mux(NULL, node->name, parent_names, num_parents, - flags, reg, shift, mask, clk_mux_flags, NULL); + flags, ®, shift, mask, clk_mux_flags, NULL); if (!IS_ERR(clk)) of_clk_add_provider(node, of_clk_src_simple_get, clk); @@ -229,8 +225,7 @@ CLK_OF_DECLARE(mux_clk, "ti,mux-clock", of_mux_clk_setup); struct clk_hw *ti_clk_build_component_mux(struct ti_clk_mux *setup) { - struct clk_mux *mux; - struct clk_omap_reg *reg; + struct clk_omap_mux *mux; int num_parents; if (!setup) @@ -240,12 +235,10 @@ struct clk_hw *ti_clk_build_component_mux(struct ti_clk_mux *setup) if (!mux) return ERR_PTR(-ENOMEM); - reg = (struct clk_omap_reg *)&mux->reg; - mux->shift = setup->bit_shift; - reg->index = setup->module; - reg->offset = setup->reg; + mux->reg.index = setup->module; + mux->reg.offset = setup->reg; if (setup->flags & CLKF_INDEX_STARTS_AT_ONE) mux->flags |= CLK_MUX_INDEX_ONE; @@ -260,7 +253,7 @@ struct clk_hw *ti_clk_build_component_mux(struct ti_clk_mux *setup) static void __init of_ti_composite_mux_clk_setup(struct device_node *node) { - struct clk_mux *mux; + struct clk_omap_mux *mux; unsigned int num_parents; u32 val; @@ -268,9 +261,7 @@ static void __init of_ti_composite_mux_clk_setup(struct device_node *node) if (!mux) return; - mux->reg = ti_clk_get_reg_addr(node, 0); - - if (IS_ERR(mux->reg)) + if (ti_clk_get_reg_addr(node, 0, &mux->reg)) goto cleanup; if (!of_property_read_u32(node, "ti,bit-shift", &val)) diff --git a/drivers/clk/zte/clk-zx296718.c b/drivers/clk/zte/clk-zx296718.c index 2f7c668643fe..a10962988ba8 100644 --- a/drivers/clk/zte/clk-zx296718.c +++ b/drivers/clk/zte/clk-zx296718.c @@ -94,13 +94,36 @@ static DEFINE_SPINLOCK(clk_lock); -static struct zx_pll_config pll_cpu_table[] = { +static const struct zx_pll_config pll_cpu_table[] = { PLL_RATE(1312000000, 0x00103621, 0x04aaaaaa), PLL_RATE(1407000000, 0x00103a21, 0x04aaaaaa), PLL_RATE(1503000000, 0x00103e21, 0x04aaaaaa), PLL_RATE(1600000000, 0x00104221, 0x04aaaaaa), }; +static const struct zx_pll_config pll_vga_table[] = { + PLL_RATE(36000000, 0x00102464, 0x04000000), /* 800x600@56 */ + PLL_RATE(40000000, 0x00102864, 0x04000000), /* 800x600@60 */ + PLL_RATE(49500000, 0x00103164, 0x04800000), /* 800x600@75 */ + PLL_RATE(50000000, 0x00103264, 0x04000000), /* 800x600@72 */ + PLL_RATE(56250000, 0x00103864, 0x04400000), /* 800x600@85 */ + PLL_RATE(65000000, 0x00104164, 0x04000000), /* 1024x768@60 */ + PLL_RATE(74375000, 0x00104a64, 0x04600000), /* 1280x720@60 */ + PLL_RATE(75000000, 0x00104b64, 0x04800000), /* 1024x768@70 */ + PLL_RATE(78750000, 0x00104e64, 0x04c00000), /* 1024x768@75 */ + PLL_RATE(85500000, 0x00105564, 0x04800000), /* 1360x768@60 */ + PLL_RATE(106500000, 0x00106a64, 0x04800000), /* 1440x900@60 */ + PLL_RATE(108000000, 0x00106c64, 0x04000000), /* 1280x1024@60 */ + PLL_RATE(110000000, 0x00106e64, 0x04000000), /* 1024x768@85 */ + PLL_RATE(135000000, 0x00105a44, 0x04000000), /* 1280x1024@75 */ + PLL_RATE(136750000, 0x00104462, 0x04600000), /* 1440x900@75 */ + PLL_RATE(148500000, 0x00104a62, 0x04400000), /* 1920x1080@60 */ + PLL_RATE(157000000, 0x00104e62, 0x04800000), /* 1440x900@85 */ + PLL_RATE(157500000, 0x00104e62, 0x04c00000), /* 1280x1024@85 */ + PLL_RATE(162000000, 0x00105162, 0x04000000), /* 1600x1200@60 */ + PLL_RATE(193250000, 0x00106062, 0x04a00000), /* 1920x1200@60 */ +}; + PNAME(osc) = { "osc24m", "osc32k", @@ -369,6 +392,7 @@ PNAME(wdt_ares_p) = { static struct clk_zx_pll zx296718_pll_clk[] = { ZX296718_PLL("pll_cpu", "osc24m", PLL_CPU_REG, pll_cpu_table), + ZX296718_PLL("pll_vga", "osc24m", PLL_VGA_REG, pll_vga_table), }; static struct zx_clk_fixed_factor top_ffactor_clk[] = { @@ -409,7 +433,7 @@ static struct zx_clk_fixed_factor top_ffactor_clk[] = { FFACTOR(0, "clk54m", "pll_mm1", 1, 24, 0), /* vga */ FFACTOR(0, "pll_vga_1800m", "pll_vga", 1, 1, 0), - FFACTOR(0, "clk_vga", "pll_vga", 1, 2, 0), + FFACTOR(0, "clk_vga", "pll_vga", 1, 1, CLK_SET_RATE_PARENT), /* pll ddr */ FFACTOR(0, "clk466m", "pll_ddr", 1, 2, 0), @@ -458,8 +482,8 @@ static struct zx_clk_mux top_mux_clk[] = { MUX(0, "sappu_a_mux", sappu_aclk_p, TOP_CLK_MUX5, 4, 2), MUX(0, "sappu_w_mux", sappu_wclk_p, TOP_CLK_MUX5, 8, 3), MUX(0, "vou_a_mux", vou_aclk_p, TOP_CLK_MUX7, 0, 3), - MUX(0, "vou_main_w_mux", vou_main_wclk_p, TOP_CLK_MUX7, 4, 3), - MUX(0, "vou_aux_w_mux", vou_aux_wclk_p, TOP_CLK_MUX7, 8, 3), + MUX_F(0, "vou_main_w_mux", vou_main_wclk_p, TOP_CLK_MUX7, 4, 3, CLK_SET_RATE_PARENT, 0), + MUX_F(0, "vou_aux_w_mux", vou_aux_wclk_p, TOP_CLK_MUX7, 8, 3, CLK_SET_RATE_PARENT, 0), MUX(0, "vou_ppu_w_mux", vou_ppu_wclk_p, TOP_CLK_MUX7, 12, 3), MUX(0, "vga_i2c_mux", vga_i2c_wclk_p, TOP_CLK_MUX7, 16, 1), MUX(0, "viu_m0_a_mux", viu_m0_aclk_p, TOP_CLK_MUX6, 0, 3), diff --git a/drivers/clk/zte/clk.c b/drivers/clk/zte/clk.c index 878d879b23ff..b82031766ffa 100644 --- a/drivers/clk/zte/clk.c +++ b/drivers/clk/zte/clk.c @@ -52,7 +52,10 @@ static int hw_to_idx(struct clk_zx_pll *zx_pll) /* For matching the value in lookup table */ hw_cfg0 &= ~BIT(zx_pll->lock_bit); - hw_cfg0 |= BIT(zx_pll->pd_bit); + + /* Check availability of pd_bit */ + if (zx_pll->pd_bit < 32) + hw_cfg0 |= BIT(zx_pll->pd_bit); for (i = 0; i < zx_pll->count; i++) { if (hw_cfg0 == config[i].cfg0 && hw_cfg1 == config[i].cfg1) @@ -108,6 +111,10 @@ static int zx_pll_enable(struct clk_hw *hw) struct clk_zx_pll *zx_pll = to_clk_zx_pll(hw); u32 reg; + /* If pd_bit is not available, simply return success. */ + if (zx_pll->pd_bit > 31) + return 0; + reg = readl_relaxed(zx_pll->reg_base); writel_relaxed(reg & ~BIT(zx_pll->pd_bit), zx_pll->reg_base); @@ -120,6 +127,9 @@ static void zx_pll_disable(struct clk_hw *hw) struct clk_zx_pll *zx_pll = to_clk_zx_pll(hw); u32 reg; + if (zx_pll->pd_bit > 31) + return; + reg = readl_relaxed(zx_pll->reg_base); writel_relaxed(reg | BIT(zx_pll->pd_bit), zx_pll->reg_base); } diff --git a/drivers/clk/zte/clk.h b/drivers/clk/zte/clk.h index 84a55a3e2bd4..4df0f121b56d 100644 --- a/drivers/clk/zte/clk.h +++ b/drivers/clk/zte/clk.h @@ -66,8 +66,12 @@ struct clk_zx_pll { CLK_GET_RATE_NOCACHE), \ } +/* + * The pd_bit is not available on ZX296718, so let's pass something + * bigger than 31, e.g. 0xff, to indicate that. + */ #define ZX296718_PLL(_name, _parent, _reg, _table) \ -ZX_PLL(_name, _parent, _reg, _table, 0, 30) +ZX_PLL(_name, _parent, _reg, _table, 0xff, 30) struct zx_clk_gate { struct clk_gate gate; |