diff options
Diffstat (limited to 'drivers/clk/tegra')
-rw-r--r-- | drivers/clk/tegra/Makefile | 1 | ||||
-rw-r--r-- | drivers/clk/tegra/clk-divider.c | 4 | ||||
-rw-r--r-- | drivers/clk/tegra/clk-emc.c | 6 | ||||
-rw-r--r-- | drivers/clk/tegra/clk-id.h | 76 | ||||
-rw-r--r-- | drivers/clk/tegra/clk-pll.c | 864 | ||||
-rw-r--r-- | drivers/clk/tegra/clk-tegra-periph.c | 372 | ||||
-rw-r--r-- | drivers/clk/tegra/clk-tegra-super-gen4.c | 142 | ||||
-rw-r--r-- | drivers/clk/tegra/clk-tegra114.c | 339 | ||||
-rw-r--r-- | drivers/clk/tegra/clk-tegra124.c | 453 | ||||
-rw-r--r-- | drivers/clk/tegra/clk-tegra20.c | 314 | ||||
-rw-r--r-- | drivers/clk/tegra/clk-tegra210.c | 2840 | ||||
-rw-r--r-- | drivers/clk/tegra/clk-tegra30.c | 426 | ||||
-rw-r--r-- | drivers/clk/tegra/clk.h | 101 |
13 files changed, 4998 insertions, 940 deletions
diff --git a/drivers/clk/tegra/Makefile b/drivers/clk/tegra/Makefile index 826c325dc..97984c503 100644 --- a/drivers/clk/tegra/Makefile +++ b/drivers/clk/tegra/Makefile @@ -20,3 +20,4 @@ obj-$(CONFIG_ARCH_TEGRA_124_SOC) += clk-tegra124.o obj-$(CONFIG_ARCH_TEGRA_124_SOC) += clk-tegra124-dfll-fcpu.o obj-$(CONFIG_ARCH_TEGRA_132_SOC) += clk-tegra124.o obj-y += cvb.o +obj-$(CONFIG_ARCH_TEGRA_210_SOC) += clk-tegra210.o diff --git a/drivers/clk/tegra/clk-divider.c b/drivers/clk/tegra/clk-divider.c index 48c83efda..16e0aee14 100644 --- a/drivers/clk/tegra/clk-divider.c +++ b/drivers/clk/tegra/clk-divider.c @@ -32,7 +32,7 @@ static int get_div(struct tegra_clk_frac_div *divider, unsigned long rate, unsigned long parent_rate) { - s64 divider_ux1 = parent_rate; + u64 divider_ux1 = parent_rate; u8 flags = divider->flags; int mul; @@ -54,7 +54,7 @@ static int get_div(struct tegra_clk_frac_div *divider, unsigned long rate, divider_ux1 -= mul; - if (divider_ux1 < 0) + if ((s64)divider_ux1 < 0) return 0; if (divider_ux1 > get_max_div(divider)) diff --git a/drivers/clk/tegra/clk-emc.c b/drivers/clk/tegra/clk-emc.c index e1fe8f35d..74e7544f8 100644 --- a/drivers/clk/tegra/clk-emc.c +++ b/drivers/clk/tegra/clk-emc.c @@ -450,8 +450,10 @@ static int load_timings_from_dt(struct tegra_clk_emc *tegra, struct emc_timing *timing = tegra->timings + (i++); err = load_one_timing_from_dt(tegra, timing, child); - if (err) + if (err) { + of_node_put(child); return err; + } timing->ram_code = ram_code; } @@ -499,9 +501,9 @@ struct clk *tegra_clk_register_emc(void __iomem *base, struct device_node *np, * fuses until the apbmisc driver is loaded. */ err = load_timings_from_dt(tegra, node, node_ram_code); + of_node_put(node); if (err) return ERR_PTR(err); - of_node_put(node); break; } diff --git a/drivers/clk/tegra/clk-id.h b/drivers/clk/tegra/clk-id.h index 60738cc95..62ea38187 100644 --- a/drivers/clk/tegra/clk-id.h +++ b/drivers/clk/tegra/clk-id.h @@ -11,8 +11,10 @@ enum clk_id { tegra_clk_afi, tegra_clk_amx, tegra_clk_amx1, + tegra_clk_apb2ape, tegra_clk_apbdma, tegra_clk_apbif, + tegra_clk_ape, tegra_clk_audio0, tegra_clk_audio0_2x, tegra_clk_audio0_mux, @@ -38,6 +40,7 @@ enum clk_id { tegra_clk_cile, tegra_clk_clk_32k, tegra_clk_clk72Mhz, + tegra_clk_clk72Mhz_8, tegra_clk_clk_m, tegra_clk_clk_m_div2, tegra_clk_clk_m_div4, @@ -51,17 +54,21 @@ enum clk_id { tegra_clk_cml1, tegra_clk_csi, tegra_clk_csite, + tegra_clk_csite_8, tegra_clk_csus, tegra_clk_cve, tegra_clk_dam0, tegra_clk_dam1, tegra_clk_dam2, tegra_clk_d_audio, + tegra_clk_dbgapb, tegra_clk_dds, tegra_clk_dfll_ref, tegra_clk_dfll_soc, tegra_clk_disp1, + tegra_clk_disp1_8, tegra_clk_disp2, + tegra_clk_disp2_8, tegra_clk_dp2, tegra_clk_dpaux, tegra_clk_dsialp, @@ -71,6 +78,7 @@ enum clk_id { tegra_clk_dtv, tegra_clk_emc, tegra_clk_entropy, + tegra_clk_entropy_8, tegra_clk_epp, tegra_clk_epp_8, tegra_clk_extern1, @@ -85,12 +93,16 @@ enum clk_id { tegra_clk_gr3d_8, tegra_clk_hclk, tegra_clk_hda, + tegra_clk_hda_8, tegra_clk_hda2codec_2x, + tegra_clk_hda2codec_2x_8, tegra_clk_hda2hdmi, tegra_clk_hdmi, tegra_clk_hdmi_audio, tegra_clk_host1x, tegra_clk_host1x_8, + tegra_clk_host1x_9, + tegra_clk_hsic_trk, tegra_clk_i2c1, tegra_clk_i2c2, tegra_clk_i2c3, @@ -110,11 +122,14 @@ enum clk_id { tegra_clk_i2s4_sync, tegra_clk_isp, tegra_clk_isp_8, + tegra_clk_isp_9, tegra_clk_ispb, tegra_clk_kbc, tegra_clk_kfuse, tegra_clk_la, + tegra_clk_maud, tegra_clk_mipi, + tegra_clk_mipibif, tegra_clk_mipi_cal, tegra_clk_mpe, tegra_clk_mselect, @@ -124,15 +139,24 @@ enum clk_id { tegra_clk_ndspeed, tegra_clk_ndspeed_8, tegra_clk_nor, + tegra_clk_nvdec, + tegra_clk_nvenc, + tegra_clk_nvjpg, tegra_clk_owr, + tegra_clk_owr_8, tegra_clk_pcie, tegra_clk_pclk, tegra_clk_pll_a, tegra_clk_pll_a_out0, + tegra_clk_pll_a1, tegra_clk_pll_c, tegra_clk_pll_c2, tegra_clk_pll_c3, tegra_clk_pll_c4, + tegra_clk_pll_c4_out0, + tegra_clk_pll_c4_out1, + tegra_clk_pll_c4_out2, + tegra_clk_pll_c4_out3, tegra_clk_pll_c_out1, tegra_clk_pll_d, tegra_clk_pll_d2, @@ -140,19 +164,29 @@ enum clk_id { tegra_clk_pll_d_out0, tegra_clk_pll_dp, tegra_clk_pll_e_out0, + tegra_clk_pll_g_ref, tegra_clk_pll_m, tegra_clk_pll_m_out1, + tegra_clk_pll_mb, tegra_clk_pll_p, tegra_clk_pll_p_out1, tegra_clk_pll_p_out2, tegra_clk_pll_p_out2_int, tegra_clk_pll_p_out3, tegra_clk_pll_p_out4, + tegra_clk_pll_p_out4_cpu, tegra_clk_pll_p_out5, + tegra_clk_pll_p_out_hsio, + tegra_clk_pll_p_out_xusb, + tegra_clk_pll_p_out_cpu, + tegra_clk_pll_p_out_adsp, tegra_clk_pll_ref, tegra_clk_pll_re_out, tegra_clk_pll_re_vco, tegra_clk_pll_u, + tegra_clk_pll_u_out, + tegra_clk_pll_u_out1, + tegra_clk_pll_u_out2, tegra_clk_pll_u_12m, tegra_clk_pll_u_480m, tegra_clk_pll_u_48m, @@ -160,53 +194,80 @@ enum clk_id { tegra_clk_pll_x, tegra_clk_pll_x_out0, tegra_clk_pwm, + tegra_clk_qspi, tegra_clk_rtc, tegra_clk_sata, + tegra_clk_sata_8, tegra_clk_sata_cold, tegra_clk_sata_oob, + tegra_clk_sata_oob_8, tegra_clk_sbc1, tegra_clk_sbc1_8, + tegra_clk_sbc1_9, tegra_clk_sbc2, tegra_clk_sbc2_8, + tegra_clk_sbc2_9, tegra_clk_sbc3, tegra_clk_sbc3_8, + tegra_clk_sbc3_9, tegra_clk_sbc4, tegra_clk_sbc4_8, + tegra_clk_sbc4_9, tegra_clk_sbc5, tegra_clk_sbc5_8, tegra_clk_sbc6, tegra_clk_sbc6_8, tegra_clk_sclk, + tegra_clk_sdmmc_legacy, tegra_clk_sdmmc1, tegra_clk_sdmmc1_8, + tegra_clk_sdmmc1_9, tegra_clk_sdmmc2, tegra_clk_sdmmc2_8, + tegra_clk_sdmmc2_9, tegra_clk_sdmmc3, tegra_clk_sdmmc3_8, + tegra_clk_sdmmc3_9, tegra_clk_sdmmc4, tegra_clk_sdmmc4_8, + tegra_clk_sdmmc4_9, tegra_clk_se, tegra_clk_soc_therm, + tegra_clk_soc_therm_8, tegra_clk_sor0, tegra_clk_sor0_lvds, + tegra_clk_sor1, + tegra_clk_sor1_brick, + tegra_clk_sor1_src, tegra_clk_spdif, tegra_clk_spdif_2x, tegra_clk_spdif_in, + tegra_clk_spdif_in_8, tegra_clk_spdif_in_sync, tegra_clk_spdif_mux, tegra_clk_spdif_out, tegra_clk_timer, tegra_clk_trace, tegra_clk_tsec, + tegra_clk_tsec_8, + tegra_clk_tsecb, tegra_clk_tsensor, tegra_clk_tvdac, tegra_clk_tvo, tegra_clk_uarta, + tegra_clk_uarta_8, tegra_clk_uartb, + tegra_clk_uartb_8, tegra_clk_uartc, + tegra_clk_uartc_8, tegra_clk_uartd, + tegra_clk_uartd_8, tegra_clk_uarte, + tegra_clk_uarte_8, + tegra_clk_uartape, tegra_clk_usb2, + tegra_clk_usb2_hsic_trk, + tegra_clk_usb2_trk, tegra_clk_usb3, tegra_clk_usbd, tegra_clk_vcp, @@ -216,22 +277,35 @@ enum clk_id { tegra_clk_vi, tegra_clk_vi_8, tegra_clk_vi_9, + tegra_clk_vi_10, + tegra_clk_vi_i2c, tegra_clk_vic03, + tegra_clk_vic03_8, tegra_clk_vim2_clk, tegra_clk_vimclk_sync, tegra_clk_vi_sensor, - tegra_clk_vi_sensor2, tegra_clk_vi_sensor_8, + tegra_clk_vi_sensor_9, + tegra_clk_vi_sensor2, + tegra_clk_vi_sensor2_8, tegra_clk_xusb_dev, tegra_clk_xusb_dev_src, + tegra_clk_xusb_dev_src_8, tegra_clk_xusb_falcon_src, + tegra_clk_xusb_falcon_src_8, tegra_clk_xusb_fs_src, + tegra_clk_xusb_gate, tegra_clk_xusb_host, tegra_clk_xusb_host_src, + tegra_clk_xusb_host_src_8, tegra_clk_xusb_hs_src, + tegra_clk_xusb_hs_src_4, tegra_clk_xusb_ss, tegra_clk_xusb_ss_src, + tegra_clk_xusb_ss_src_8, tegra_clk_xusb_ss_div2, + tegra_clk_xusb_ssp_src, + tegra_clk_sclk_mux, tegra_clk_max, }; diff --git a/drivers/clk/tegra/clk-pll.c b/drivers/clk/tegra/clk-pll.c index d6d4ecb88..6ac3f843e 100644 --- a/drivers/clk/tegra/clk-pll.c +++ b/drivers/clk/tegra/clk-pll.c @@ -65,6 +65,7 @@ #define PLLE_BASE_DIVN_WIDTH 8 #define PLLE_BASE_DIVM_SHIFT 0 #define PLLE_BASE_DIVM_WIDTH 8 +#define PLLE_BASE_ENABLE BIT(31) #define PLLE_MISC_SETUP_BASE_SHIFT 16 #define PLLE_MISC_SETUP_BASE_MASK (0xffff << PLLE_MISC_SETUP_BASE_SHIFT) @@ -85,15 +86,21 @@ #define PLLE_SS_DISABLE (PLLE_SS_CNTL_BYPASS_SS | PLLE_SS_CNTL_INTERP_RESET |\ PLLE_SS_CNTL_SSC_BYP) #define PLLE_SS_MAX_MASK 0x1ff -#define PLLE_SS_MAX_VAL 0x25 +#define PLLE_SS_MAX_VAL_TEGRA114 0x25 +#define PLLE_SS_MAX_VAL_TEGRA210 0x21 #define PLLE_SS_INC_MASK (0xff << 16) #define PLLE_SS_INC_VAL (0x1 << 16) #define PLLE_SS_INCINTRV_MASK (0x3f << 24) -#define PLLE_SS_INCINTRV_VAL (0x20 << 24) +#define PLLE_SS_INCINTRV_VAL_TEGRA114 (0x20 << 24) +#define PLLE_SS_INCINTRV_VAL_TEGRA210 (0x23 << 24) #define PLLE_SS_COEFFICIENTS_MASK \ (PLLE_SS_MAX_MASK | PLLE_SS_INC_MASK | PLLE_SS_INCINTRV_MASK) -#define PLLE_SS_COEFFICIENTS_VAL \ - (PLLE_SS_MAX_VAL | PLLE_SS_INC_VAL | PLLE_SS_INCINTRV_VAL) +#define PLLE_SS_COEFFICIENTS_VAL_TEGRA114 \ + (PLLE_SS_MAX_VAL_TEGRA114 | PLLE_SS_INC_VAL |\ + PLLE_SS_INCINTRV_VAL_TEGRA114) +#define PLLE_SS_COEFFICIENTS_VAL_TEGRA210 \ + (PLLE_SS_MAX_VAL_TEGRA210 | PLLE_SS_INC_VAL |\ + PLLE_SS_INCINTRV_VAL_TEGRA210) #define PLLE_AUX_PLLP_SEL BIT(2) #define PLLE_AUX_USE_LOCKDET BIT(3) @@ -102,6 +109,7 @@ #define PLLE_AUX_SEQ_ENABLE BIT(24) #define PLLE_AUX_SEQ_START_STATE BIT(25) #define PLLE_AUX_PLLRE_SEL BIT(28) +#define PLLE_AUX_SS_SEQ_INCLUDE BIT(31) #define XUSBIO_PLL_CFG0 0x51c #define XUSBIO_PLL_CFG0_PADPLL_RESET_SWCTL BIT(0) @@ -187,17 +195,23 @@ #define pll_readl_base(p) pll_readl(p->params->base_reg, p) #define pll_readl_misc(p) pll_readl(p->params->misc_reg, p) #define pll_override_readl(offset, p) readl_relaxed(p->pmc + offset) +#define pll_readl_sdm_din(p) pll_readl(p->params->sdm_din_reg, p) +#define pll_readl_sdm_ctrl(p) pll_readl(p->params->sdm_ctrl_reg, p) #define pll_writel(val, offset, p) writel_relaxed(val, p->clk_base + offset) #define pll_writel_base(val, p) pll_writel(val, p->params->base_reg, p) #define pll_writel_misc(val, p) pll_writel(val, p->params->misc_reg, p) #define pll_override_writel(val, offset, p) writel(val, p->pmc + offset) +#define pll_writel_sdm_din(val, p) pll_writel(val, p->params->sdm_din_reg, p) +#define pll_writel_sdm_ctrl(val, p) pll_writel(val, p->params->sdm_ctrl_reg, p) #define mask(w) ((1 << (w)) - 1) #define divm_mask(p) mask(p->params->div_nmp->divm_width) #define divn_mask(p) mask(p->params->div_nmp->divn_width) #define divp_mask(p) (p->params->flags & TEGRA_PLLU ? PLLU_POST_DIVP_MASK :\ mask(p->params->div_nmp->divp_width)) +#define sdm_din_mask(p) p->params->sdm_din_mask +#define sdm_en_mask(p) p->params->sdm_ctrl_en_mask #define divm_shift(p) (p)->params->div_nmp->divm_shift #define divn_shift(p) (p)->params->div_nmp->divn_shift @@ -211,6 +225,9 @@ #define divn_max(p) (divn_mask(p)) #define divp_max(p) (1 << (divp_mask(p))) +#define sdin_din_to_data(din) ((u16)((din) ? : 0xFFFFU)) +#define sdin_data_to_din(dat) (((dat) == 0xFFFFU) ? 0 : (s16)dat) + static struct div_nmp default_nmp = { .divn_shift = PLL_BASE_DIVN_SHIFT, .divn_width = PLL_BASE_DIVN_WIDTH, @@ -269,6 +286,11 @@ static int clk_pll_wait_for_lock(struct tegra_clk_pll *pll) return -1; } +int tegra_pll_wait_for_lock(struct tegra_clk_pll *pll) +{ + return clk_pll_wait_for_lock(pll); +} + static int clk_pll_is_enabled(struct clk_hw *hw) { struct tegra_clk_pll *pll = to_clk_pll(hw); @@ -290,6 +312,19 @@ static void _clk_pll_enable(struct clk_hw *hw) struct tegra_clk_pll *pll = to_clk_pll(hw); u32 val; + if (pll->params->iddq_reg) { + val = pll_readl(pll->params->iddq_reg, pll); + val &= ~BIT(pll->params->iddq_bit_idx); + pll_writel(val, pll->params->iddq_reg, pll); + udelay(2); + } + + if (pll->params->reset_reg) { + val = pll_readl(pll->params->reset_reg, pll); + val &= ~BIT(pll->params->reset_bit_idx); + pll_writel(val, pll->params->reset_reg, pll); + } + clk_pll_enable_lock(pll); val = pll_readl_base(pll); @@ -321,6 +356,19 @@ static void _clk_pll_disable(struct clk_hw *hw) val &= ~PMC_PLLP_WB0_OVERRIDE_PLLM_ENABLE; writel_relaxed(val, pll->pmc + PMC_PLLP_WB0_OVERRIDE); } + + if (pll->params->reset_reg) { + val = pll_readl(pll->params->reset_reg, pll); + val |= BIT(pll->params->reset_bit_idx); + pll_writel(val, pll->params->reset_reg, pll); + } + + if (pll->params->iddq_reg) { + val = pll_readl(pll->params->iddq_reg, pll); + val |= BIT(pll->params->iddq_bit_idx); + pll_writel(val, pll->params->iddq_reg, pll); + udelay(2); + } } static int clk_pll_enable(struct clk_hw *hw) @@ -359,7 +407,7 @@ static void clk_pll_disable(struct clk_hw *hw) static int _p_div_to_hw(struct clk_hw *hw, u8 p_div) { struct tegra_clk_pll *pll = to_clk_pll(hw); - struct pdiv_map *p_tohw = pll->params->pdiv_tohw; + const struct pdiv_map *p_tohw = pll->params->pdiv_tohw; if (p_tohw) { while (p_tohw->pdiv) { @@ -372,10 +420,15 @@ static int _p_div_to_hw(struct clk_hw *hw, u8 p_div) return -EINVAL; } +int tegra_pll_p_div_to_hw(struct tegra_clk_pll *pll, u8 p_div) +{ + return _p_div_to_hw(&pll->hw, p_div); +} + static int _hw_to_p_div(struct clk_hw *hw, u8 p_div_hw) { struct tegra_clk_pll *pll = to_clk_pll(hw); - struct pdiv_map *p_tohw = pll->params->pdiv_tohw; + const struct pdiv_map *p_tohw = pll->params->pdiv_tohw; if (p_tohw) { while (p_tohw->pdiv) { @@ -395,6 +448,7 @@ static int _get_table_rate(struct clk_hw *hw, { struct tegra_clk_pll *pll = to_clk_pll(hw); struct tegra_clk_pll_freq_table *sel; + int p; for (sel = pll->params->freq_table; sel->input_rate != 0; sel++) if (sel->input_rate == parent_rate && @@ -404,12 +458,21 @@ static int _get_table_rate(struct clk_hw *hw, if (sel->input_rate == 0) return -EINVAL; + if (pll->params->pdiv_tohw) { + p = _p_div_to_hw(hw, sel->p); + if (p < 0) + return p; + } else { + p = ilog2(sel->p); + } + cfg->input_rate = sel->input_rate; cfg->output_rate = sel->output_rate; cfg->m = sel->m; cfg->n = sel->n; - cfg->p = sel->p; + cfg->p = p; cfg->cpcon = sel->cpcon; + cfg->sdm_data = sel->sdm_data; return 0; } @@ -439,7 +502,7 @@ static int _calc_rate(struct clk_hw *hw, struct tegra_clk_pll_freq_table *cfg, /* * PLL_P_OUT1 rate is not listed in PLLA table */ - cfreq = parent_rate/(parent_rate/1000000); + cfreq = parent_rate / (parent_rate / 1000000); break; default: pr_err("%s Unexpected reference rate %lu\n", @@ -476,6 +539,42 @@ static int _calc_rate(struct clk_hw *hw, struct tegra_clk_pll_freq_table *cfg, return 0; } +/* + * SDM (Sigma Delta Modulator) divisor is 16-bit 2's complement signed number + * within (-2^12 ... 2^12-1) range. Represented in PLL data structure as + * unsigned 16-bit value, with "0" divisor mapped to 0xFFFF. Data "0" is used + * to indicate that SDM is disabled. + * + * Effective ndiv value when SDM is enabled: ndiv + 1/2 + sdm_din/2^13 + */ +static void clk_pll_set_sdm_data(struct clk_hw *hw, + struct tegra_clk_pll_freq_table *cfg) +{ + struct tegra_clk_pll *pll = to_clk_pll(hw); + u32 val; + bool enabled; + + if (!pll->params->sdm_din_reg) + return; + + if (cfg->sdm_data) { + val = pll_readl_sdm_din(pll) & (~sdm_din_mask(pll)); + val |= sdin_data_to_din(cfg->sdm_data) & sdm_din_mask(pll); + pll_writel_sdm_din(val, pll); + } + + val = pll_readl_sdm_ctrl(pll); + enabled = (val & sdm_en_mask(pll)); + + if (cfg->sdm_data == 0 && enabled) + val &= ~pll->params->sdm_ctrl_en_mask; + + if (cfg->sdm_data != 0 && !enabled) + val |= pll->params->sdm_ctrl_en_mask; + + pll_writel_sdm_ctrl(val, pll); +} + static void _update_pll_mnp(struct tegra_clk_pll *pll, struct tegra_clk_pll_freq_table *cfg) { @@ -483,7 +582,7 @@ static void _update_pll_mnp(struct tegra_clk_pll *pll, struct tegra_clk_pll_params *params = pll->params; struct div_nmp *div_nmp = params->div_nmp; - if ((params->flags & TEGRA_PLLM) && + if ((params->flags & (TEGRA_PLLM | TEGRA_PLLMB)) && (pll_override_readl(PMC_PLLP_WB0_OVERRIDE, pll) & PMC_PLLP_WB0_OVERRIDE_PLLM_OVERRIDE)) { val = pll_override_readl(params->pmc_divp_reg, pll); @@ -508,6 +607,8 @@ static void _update_pll_mnp(struct tegra_clk_pll *pll, (cfg->p << divp_shift(pll)); pll_writel_base(val, pll); + + clk_pll_set_sdm_data(&pll->hw, cfg); } } @@ -518,7 +619,7 @@ static void _get_pll_mnp(struct tegra_clk_pll *pll, struct tegra_clk_pll_params *params = pll->params; struct div_nmp *div_nmp = params->div_nmp; - if ((params->flags & TEGRA_PLLM) && + if ((params->flags & (TEGRA_PLLM | TEGRA_PLLMB)) && (pll_override_readl(PMC_PLLP_WB0_OVERRIDE, pll) & PMC_PLLP_WB0_OVERRIDE_PLLM_OVERRIDE)) { val = pll_override_readl(params->pmc_divp_reg, pll); @@ -533,6 +634,14 @@ static void _get_pll_mnp(struct tegra_clk_pll *pll, cfg->m = (val >> div_nmp->divm_shift) & divm_mask(pll); cfg->n = (val >> div_nmp->divn_shift) & divn_mask(pll); cfg->p = (val >> div_nmp->divp_shift) & divp_mask(pll); + + if (pll->params->sdm_din_reg) { + if (sdm_en_mask(pll) & pll_readl_sdm_ctrl(pll)) { + val = pll_readl_sdm_din(pll); + val &= sdm_din_mask(pll); + cfg->sdm_data = sdin_din_to_data(val); + } + } } } @@ -560,16 +669,51 @@ static void _update_pll_cpcon(struct tegra_clk_pll *pll, pll_writel_misc(val, pll); } +static void pll_clk_start_ss(struct tegra_clk_pll *pll) +{ + if (pll->params->defaults_set && pll->params->ssc_ctrl_reg) { + u32 val = pll_readl(pll->params->ssc_ctrl_reg, pll); + + val |= pll->params->ssc_ctrl_en_mask; + pll_writel(val, pll->params->ssc_ctrl_reg, pll); + } +} + +static void pll_clk_stop_ss(struct tegra_clk_pll *pll) +{ + if (pll->params->defaults_set && pll->params->ssc_ctrl_reg) { + u32 val = pll_readl(pll->params->ssc_ctrl_reg, pll); + + val &= ~pll->params->ssc_ctrl_en_mask; + pll_writel(val, pll->params->ssc_ctrl_reg, pll); + } +} + static int _program_pll(struct clk_hw *hw, struct tegra_clk_pll_freq_table *cfg, unsigned long rate) { struct tegra_clk_pll *pll = to_clk_pll(hw); + struct tegra_clk_pll_freq_table old_cfg; int state, ret = 0; state = clk_pll_is_enabled(hw); - if (state) + _get_pll_mnp(pll, &old_cfg); + + if (state && pll->params->defaults_set && pll->params->dyn_ramp && + (cfg->m == old_cfg.m) && (cfg->p == old_cfg.p)) { + ret = pll->params->dyn_ramp(pll, cfg); + if (!ret) + return 0; + } + + if (state) { + pll_clk_stop_ss(pll); _clk_pll_disable(hw); + } + + if (!pll->params->defaults_set && pll->params->set_defaults) + pll->params->set_defaults(pll); _update_pll_mnp(pll, cfg); @@ -579,6 +723,7 @@ static int _program_pll(struct clk_hw *hw, struct tegra_clk_pll_freq_table *cfg, if (state) { _clk_pll_enable(hw); ret = clk_pll_wait_for_lock(pll); + pll_clk_start_ss(pll); } return ret; @@ -603,7 +748,7 @@ static int clk_pll_set_rate(struct clk_hw *hw, unsigned long rate, } if (_get_table_rate(hw, &cfg, rate, parent_rate) && - _calc_rate(hw, &cfg, rate, parent_rate)) { + pll->params->calc_rate(hw, &cfg, rate, parent_rate)) { pr_err("%s: Failed to set %s rate %lu\n", __func__, clk_hw_get_name(hw), rate); WARN_ON(1); @@ -613,8 +758,11 @@ static int clk_pll_set_rate(struct clk_hw *hw, unsigned long rate, spin_lock_irqsave(pll->lock, flags); _get_pll_mnp(pll, &old_cfg); + if (pll->params->flags & TEGRA_PLL_VCO_OUT) + cfg.p = old_cfg.p; - if (old_cfg.m != cfg.m || old_cfg.n != cfg.n || old_cfg.p != cfg.p) + if (old_cfg.m != cfg.m || old_cfg.n != cfg.n || old_cfg.p != cfg.p || + old_cfg.sdm_data != cfg.sdm_data) ret = _program_pll(hw, &cfg, rate); if (pll->lock) @@ -629,15 +777,15 @@ static long clk_pll_round_rate(struct clk_hw *hw, unsigned long rate, struct tegra_clk_pll *pll = to_clk_pll(hw); struct tegra_clk_pll_freq_table cfg; - if (pll->params->flags & TEGRA_PLL_FIXED) + if (pll->params->flags & TEGRA_PLL_FIXED) { + /* PLLM/MB are used for memory; we do not change rate */ + if (pll->params->flags & (TEGRA_PLLM | TEGRA_PLLMB)) + return clk_hw_get_rate(hw); return pll->params->fixed_rate; - - /* PLLM is used for memory; we do not change rate */ - if (pll->params->flags & TEGRA_PLLM) - return clk_hw_get_rate(hw); + } if (_get_table_rate(hw, &cfg, rate, *prate) && - _calc_rate(hw, &cfg, rate, *prate)) + pll->params->calc_rate(hw, &cfg, rate, *prate)) return -EINVAL; return cfg.output_rate; @@ -658,6 +806,7 @@ static unsigned long clk_pll_recalc_rate(struct clk_hw *hw, return parent_rate; if ((pll->params->flags & TEGRA_PLL_FIXED) && + !(pll->params->flags & (TEGRA_PLLM | TEGRA_PLLMB)) && !(val & PLL_BASE_OVERRIDE)) { struct tegra_clk_pll_freq_table sel; if (_get_table_rate(hw, &sel, pll->params->fixed_rate, @@ -671,12 +820,20 @@ static unsigned long clk_pll_recalc_rate(struct clk_hw *hw, _get_pll_mnp(pll, &cfg); - pdiv = _hw_to_p_div(hw, cfg.p); - if (pdiv < 0) { - WARN_ON(1); + if (pll->params->flags & TEGRA_PLL_VCO_OUT) { pdiv = 1; + } else { + pdiv = _hw_to_p_div(hw, cfg.p); + if (pdiv < 0) { + WARN(1, "Clock %s has invalid pdiv value : 0x%x\n", + clk_hw_get_name(hw), cfg.p); + pdiv = 1; + } } + if (pll->params->set_gain) + pll->params->set_gain(&cfg); + cfg.m *= pdiv; rate *= cfg.n; @@ -729,7 +886,7 @@ static int clk_plle_training(struct tegra_clk_pll *pll) static int clk_plle_enable(struct clk_hw *hw) { struct tegra_clk_pll *pll = to_clk_pll(hw); - unsigned long input_rate = clk_get_rate(clk_get_parent(hw->clk)); + unsigned long input_rate = clk_hw_get_rate(clk_hw_get_parent(hw)); struct tegra_clk_pll_freq_table sel; u32 val; int err; @@ -816,19 +973,65 @@ const struct clk_ops tegra_clk_plle_ops = { .enable = clk_plle_enable, }; -#if defined(CONFIG_ARCH_TEGRA_114_SOC) || \ - defined(CONFIG_ARCH_TEGRA_124_SOC) || \ - defined(CONFIG_ARCH_TEGRA_132_SOC) - static int _pll_fixed_mdiv(struct tegra_clk_pll_params *pll_params, unsigned long parent_rate) { + u16 mdiv = parent_rate / pll_params->cf_min; + + if (pll_params->flags & TEGRA_MDIV_NEW) + return (!pll_params->mdiv_default ? mdiv : + min(mdiv, pll_params->mdiv_default)); + + if (pll_params->mdiv_default) + return pll_params->mdiv_default; + if (parent_rate > pll_params->cf_max) return 2; else return 1; } +static int _calc_dynamic_ramp_rate(struct clk_hw *hw, + struct tegra_clk_pll_freq_table *cfg, + unsigned long rate, unsigned long parent_rate) +{ + struct tegra_clk_pll *pll = to_clk_pll(hw); + unsigned int p; + int p_div; + + if (!rate) + return -EINVAL; + + p = DIV_ROUND_UP(pll->params->vco_min, rate); + cfg->m = _pll_fixed_mdiv(pll->params, parent_rate); + cfg->output_rate = rate * p; + cfg->n = cfg->output_rate * cfg->m / parent_rate; + cfg->input_rate = parent_rate; + + p_div = _p_div_to_hw(hw, p); + if (p_div < 0) + return p_div; + + cfg->p = p_div; + + if (cfg->n > divn_max(pll) || cfg->output_rate > pll->params->vco_max) + return -EINVAL; + + return 0; +} + +#if defined(CONFIG_ARCH_TEGRA_114_SOC) || \ + defined(CONFIG_ARCH_TEGRA_124_SOC) || \ + defined(CONFIG_ARCH_TEGRA_132_SOC) || \ + defined(CONFIG_ARCH_TEGRA_210_SOC) + +u16 tegra_pll_get_fixed_mdiv(struct clk_hw *hw, unsigned long input_rate) +{ + struct tegra_clk_pll *pll = to_clk_pll(hw); + + return (u16)_pll_fixed_mdiv(pll->params, input_rate); +} + static unsigned long _clip_vco_min(unsigned long vco_min, unsigned long parent_rate) { @@ -871,86 +1074,12 @@ static int _setup_dynamic_ramp(struct tegra_clk_pll_params *pll_params, return 0; } -static int clk_pll_iddq_enable(struct clk_hw *hw) -{ - struct tegra_clk_pll *pll = to_clk_pll(hw); - unsigned long flags = 0; - - u32 val; - int ret; - - if (pll->lock) - spin_lock_irqsave(pll->lock, flags); - - val = pll_readl(pll->params->iddq_reg, pll); - val &= ~BIT(pll->params->iddq_bit_idx); - pll_writel(val, pll->params->iddq_reg, pll); - udelay(2); - - _clk_pll_enable(hw); - - ret = clk_pll_wait_for_lock(pll); - - if (pll->lock) - spin_unlock_irqrestore(pll->lock, flags); - - return 0; -} - -static void clk_pll_iddq_disable(struct clk_hw *hw) -{ - struct tegra_clk_pll *pll = to_clk_pll(hw); - unsigned long flags = 0; - u32 val; - - if (pll->lock) - spin_lock_irqsave(pll->lock, flags); - - _clk_pll_disable(hw); - - val = pll_readl(pll->params->iddq_reg, pll); - val |= BIT(pll->params->iddq_bit_idx); - pll_writel(val, pll->params->iddq_reg, pll); - udelay(2); - - if (pll->lock) - spin_unlock_irqrestore(pll->lock, flags); -} - -static int _calc_dynamic_ramp_rate(struct clk_hw *hw, - struct tegra_clk_pll_freq_table *cfg, - unsigned long rate, unsigned long parent_rate) -{ - struct tegra_clk_pll *pll = to_clk_pll(hw); - unsigned int p; - int p_div; - - if (!rate) - return -EINVAL; - - p = DIV_ROUND_UP(pll->params->vco_min, rate); - cfg->m = _pll_fixed_mdiv(pll->params, parent_rate); - cfg->output_rate = rate * p; - cfg->n = cfg->output_rate * cfg->m / parent_rate; - - p_div = _p_div_to_hw(hw, p); - if (p_div < 0) - return p_div; - else - cfg->p = p_div; - - if (cfg->n > divn_max(pll) || cfg->output_rate > pll->params->vco_max) - return -EINVAL; - - return 0; -} - static int _pll_ramp_calc_pll(struct clk_hw *hw, struct tegra_clk_pll_freq_table *cfg, unsigned long rate, unsigned long parent_rate) { struct tegra_clk_pll *pll = to_clk_pll(hw); - int err = 0, p_div; + int err = 0; err = _get_table_rate(hw, cfg, rate, parent_rate); if (err < 0) @@ -961,11 +1090,6 @@ static int _pll_ramp_calc_pll(struct clk_hw *hw, err = -EINVAL; goto out; } - p_div = _p_div_to_hw(hw, cfg->p); - if (p_div < 0) - return p_div; - else - cfg->p = p_div; } if (cfg->p > pll->params->max_p) @@ -991,6 +1115,8 @@ static int clk_pllxc_set_rate(struct clk_hw *hw, unsigned long rate, spin_lock_irqsave(pll->lock, flags); _get_pll_mnp(pll, &old_cfg); + if (pll->params->flags & TEGRA_PLL_VCO_OUT) + cfg.p = old_cfg.p; if (old_cfg.m != cfg.m || old_cfg.n != cfg.n || old_cfg.p != cfg.p) ret = _program_pll(hw, &cfg, rate); @@ -1004,6 +1130,7 @@ static int clk_pllxc_set_rate(struct clk_hw *hw, unsigned long rate, static long clk_pll_ramp_round_rate(struct clk_hw *hw, unsigned long rate, unsigned long *prate) { + struct tegra_clk_pll *pll = to_clk_pll(hw); struct tegra_clk_pll_freq_table cfg; int ret, p_div; u64 output_rate = *prate; @@ -1016,46 +1143,15 @@ static long clk_pll_ramp_round_rate(struct clk_hw *hw, unsigned long rate, if (p_div < 0) return p_div; + if (pll->params->set_gain) + pll->params->set_gain(&cfg); + output_rate *= cfg.n; do_div(output_rate, cfg.m * p_div); return output_rate; } -static int clk_pllm_set_rate(struct clk_hw *hw, unsigned long rate, - unsigned long parent_rate) -{ - struct tegra_clk_pll_freq_table cfg; - struct tegra_clk_pll *pll = to_clk_pll(hw); - unsigned long flags = 0; - int state, ret = 0; - - if (pll->lock) - spin_lock_irqsave(pll->lock, flags); - - state = clk_pll_is_enabled(hw); - if (state) { - if (rate != clk_get_rate(hw->clk)) { - pr_err("%s: Cannot change active PLLM\n", __func__); - ret = -EINVAL; - goto out; - } - goto out; - } - - ret = _pll_ramp_calc_pll(hw, &cfg, rate, parent_rate); - if (ret < 0) - goto out; - - _update_pll_mnp(pll, &cfg); - -out: - if (pll->lock) - spin_unlock_irqrestore(pll->lock, flags); - - return ret; -} - static void _pllcx_strobe(struct tegra_clk_pll *pll) { u32 val; @@ -1288,7 +1384,7 @@ static int clk_plle_tegra114_enable(struct clk_hw *hw) u32 val; int ret; unsigned long flags = 0; - unsigned long input_rate = clk_get_rate(clk_get_parent(hw->clk)); + unsigned long input_rate = clk_hw_get_rate(clk_hw_get_parent(hw)); if (_get_table_rate(hw, &sel, pll->params->fixed_rate, input_rate)) return -EINVAL; @@ -1311,7 +1407,7 @@ static int clk_plle_tegra114_enable(struct clk_hw *hw) val |= PLLE_MISC_IDDQ_SW_CTRL; val &= ~PLLE_MISC_IDDQ_SW_VALUE; val |= PLLE_MISC_PLLE_PTS; - val |= PLLE_MISC_VREG_BG_CTRL_MASK | PLLE_MISC_VREG_CTRL_MASK; + val &= ~(PLLE_MISC_VREG_BG_CTRL_MASK | PLLE_MISC_VREG_CTRL_MASK); pll_writel_misc(val, pll); udelay(5); @@ -1338,7 +1434,7 @@ static int clk_plle_tegra114_enable(struct clk_hw *hw) val = pll_readl(PLLE_SS_CTRL, pll); val &= ~(PLLE_SS_CNTL_CENTER | PLLE_SS_CNTL_INVERT); val &= ~PLLE_SS_COEFFICIENTS_MASK; - val |= PLLE_SS_COEFFICIENTS_VAL; + val |= PLLE_SS_COEFFICIENTS_VAL_TEGRA114; pll_writel(val, PLLE_SS_CTRL, pll); val &= ~(PLLE_SS_CNTL_SSC_BYP | PLLE_SS_CNTL_BYPASS_SS); pll_writel(val, PLLE_SS_CTRL, pll); @@ -1445,6 +1541,17 @@ static struct clk *_tegra_clk_register_pll(struct tegra_clk_pll *pll, init.parent_names = (parent_name ? &parent_name : NULL); init.num_parents = (parent_name ? 1 : 0); + /* Default to _calc_rate if unspecified */ + if (!pll->params->calc_rate) { + if (pll->params->flags & TEGRA_PLLM) + pll->params->calc_rate = _calc_dynamic_ramp_rate; + else + pll->params->calc_rate = _calc_rate; + } + + if (pll->params->set_defaults) + pll->params->set_defaults(pll); + /* Data in .init is copied by clk_register(), so stack variable OK */ pll->hw.init = &init; @@ -1460,7 +1567,7 @@ struct clk *tegra_clk_register_pll(const char *name, const char *parent_name, struct clk *clk; pll_params->flags |= TEGRA_PLL_BYPASS; - pll_params->flags |= TEGRA_PLL_HAS_LOCK_ENABLE; + pll = _tegra_init_pll(clk_base, pmc, pll_params, lock); if (IS_ERR(pll)) return ERR_CAST(pll); @@ -1490,8 +1597,7 @@ struct clk *tegra_clk_register_plle(const char *name, const char *parent_name, struct tegra_clk_pll *pll; struct clk *clk; - pll_params->flags |= TEGRA_PLL_LOCK_MISC | TEGRA_PLL_BYPASS; - pll_params->flags |= TEGRA_PLL_HAS_LOCK_ENABLE; + pll_params->flags |= TEGRA_PLL_BYPASS; if (!pll_params->div_nmp) pll_params->div_nmp = &pll_e_nmp; @@ -1510,25 +1616,17 @@ struct clk *tegra_clk_register_plle(const char *name, const char *parent_name, #if defined(CONFIG_ARCH_TEGRA_114_SOC) || \ defined(CONFIG_ARCH_TEGRA_124_SOC) || \ - defined(CONFIG_ARCH_TEGRA_132_SOC) + defined(CONFIG_ARCH_TEGRA_132_SOC) || \ + defined(CONFIG_ARCH_TEGRA_210_SOC) static const struct clk_ops tegra_clk_pllxc_ops = { .is_enabled = clk_pll_is_enabled, - .enable = clk_pll_iddq_enable, - .disable = clk_pll_iddq_disable, + .enable = clk_pll_enable, + .disable = clk_pll_disable, .recalc_rate = clk_pll_recalc_rate, .round_rate = clk_pll_ramp_round_rate, .set_rate = clk_pllxc_set_rate, }; -static const struct clk_ops tegra_clk_pllm_ops = { - .is_enabled = clk_pll_is_enabled, - .enable = clk_pll_iddq_enable, - .disable = clk_pll_iddq_disable, - .recalc_rate = clk_pll_recalc_rate, - .round_rate = clk_pll_ramp_round_rate, - .set_rate = clk_pllm_set_rate, -}; - static const struct clk_ops tegra_clk_pllc_ops = { .is_enabled = clk_pll_is_enabled, .enable = clk_pllc_enable, @@ -1540,8 +1638,8 @@ static const struct clk_ops tegra_clk_pllc_ops = { static const struct clk_ops tegra_clk_pllre_ops = { .is_enabled = clk_pll_is_enabled, - .enable = clk_pll_iddq_enable, - .disable = clk_pll_iddq_disable, + .enable = clk_pll_enable, + .disable = clk_pll_disable, .recalc_rate = clk_pllre_recalc_rate, .round_rate = clk_pllre_round_rate, .set_rate = clk_pllre_set_rate, @@ -1564,7 +1662,6 @@ struct clk *tegra_clk_register_pllxc(const char *name, const char *parent_name, struct tegra_clk_pll *pll; struct clk *clk, *parent; unsigned long parent_rate; - int err; u32 val, val_iddq; parent = __clk_lookup(parent_name); @@ -1581,21 +1678,33 @@ struct clk *tegra_clk_register_pllxc(const char *name, const char *parent_name, pll_params->vco_min = _clip_vco_min(pll_params->vco_min, parent_rate); - err = _setup_dynamic_ramp(pll_params, clk_base, parent_rate); - if (err) - return ERR_PTR(err); + if (pll_params->adjust_vco) + pll_params->vco_min = pll_params->adjust_vco(pll_params, + parent_rate); - val = readl_relaxed(clk_base + pll_params->base_reg); - val_iddq = readl_relaxed(clk_base + pll_params->iddq_reg); + /* + * If the pll has a set_defaults callback, it will take care of + * configuring dynamic ramping and setting IDDQ in that path. + */ + if (!pll_params->set_defaults) { + int err; - if (val & PLL_BASE_ENABLE) - WARN_ON(val_iddq & BIT(pll_params->iddq_bit_idx)); - else { - val_iddq |= BIT(pll_params->iddq_bit_idx); - writel_relaxed(val_iddq, clk_base + pll_params->iddq_reg); + err = _setup_dynamic_ramp(pll_params, clk_base, parent_rate); + if (err) + return ERR_PTR(err); + + val = readl_relaxed(clk_base + pll_params->base_reg); + val_iddq = readl_relaxed(clk_base + pll_params->iddq_reg); + + if (val & PLL_BASE_ENABLE) + WARN_ON(val_iddq & BIT(pll_params->iddq_bit_idx)); + else { + val_iddq |= BIT(pll_params->iddq_bit_idx); + writel_relaxed(val_iddq, + clk_base + pll_params->iddq_reg); + } } - pll_params->flags |= TEGRA_PLL_HAS_LOCK_ENABLE; pll = _tegra_init_pll(clk_base, pmc, pll_params, lock); if (IS_ERR(pll)) return ERR_CAST(pll); @@ -1618,10 +1727,12 @@ struct clk *tegra_clk_register_pllre(const char *name, const char *parent_name, struct tegra_clk_pll *pll; struct clk *clk; - pll_params->flags |= TEGRA_PLL_HAS_LOCK_ENABLE | TEGRA_PLL_LOCK_MISC; - pll_params->vco_min = _clip_vco_min(pll_params->vco_min, parent_rate); + if (pll_params->adjust_vco) + pll_params->vco_min = pll_params->adjust_vco(pll_params, + parent_rate); + pll = _tegra_init_pll(clk_base, pmc, pll_params, lock); if (IS_ERR(pll)) return ERR_CAST(pll); @@ -1630,7 +1741,8 @@ struct clk *tegra_clk_register_pllre(const char *name, const char *parent_name, val = pll_readl_base(pll); if (val & PLL_BASE_ENABLE) - WARN_ON(val & pll_params->iddq_bit_idx); + WARN_ON(readl_relaxed(clk_base + pll_params->iddq_reg) & + BIT(pll_params->iddq_bit_idx)); else { int m; @@ -1678,15 +1790,18 @@ struct clk *tegra_clk_register_pllm(const char *name, const char *parent_name, pll_params->vco_min = _clip_vco_min(pll_params->vco_min, parent_rate); + if (pll_params->adjust_vco) + pll_params->vco_min = pll_params->adjust_vco(pll_params, + parent_rate); + pll_params->flags |= TEGRA_PLL_BYPASS; - pll_params->flags |= TEGRA_PLL_HAS_LOCK_ENABLE; pll_params->flags |= TEGRA_PLLM; pll = _tegra_init_pll(clk_base, pmc, pll_params, lock); if (IS_ERR(pll)) return ERR_CAST(pll); clk = _tegra_clk_register_pll(pll, name, parent_name, flags, - &tegra_clk_pllm_ops); + &tegra_clk_pll_ops); if (IS_ERR(clk)) kfree(pll); @@ -1700,7 +1815,7 @@ struct clk *tegra_clk_register_pllc(const char *name, const char *parent_name, spinlock_t *lock) { struct clk *parent, *clk; - struct pdiv_map *p_tohw = pll_params->pdiv_tohw; + const struct pdiv_map *p_tohw = pll_params->pdiv_tohw; struct tegra_clk_pll *pll; struct tegra_clk_pll_freq_table cfg; unsigned long parent_rate; @@ -1777,7 +1892,6 @@ struct clk *tegra_clk_register_plle_tegra114(const char *name, struct clk *clk; u32 val, val_aux; - pll_params->flags |= TEGRA_PLL_HAS_LOCK_ENABLE; pll = _tegra_init_pll(clk_base, NULL, pll_params, lock); if (IS_ERR(pll)) return ERR_CAST(pll); @@ -1810,8 +1924,8 @@ struct clk *tegra_clk_register_plle_tegra114(const char *name, #if defined(CONFIG_ARCH_TEGRA_124_SOC) || defined(CONFIG_ARCH_TEGRA_132_SOC) static const struct clk_ops tegra_clk_pllss_ops = { .is_enabled = clk_pll_is_enabled, - .enable = clk_pll_iddq_enable, - .disable = clk_pll_iddq_disable, + .enable = clk_pll_enable, + .disable = clk_pll_disable, .recalc_rate = clk_pll_recalc_rate, .round_rate = clk_pll_ramp_round_rate, .set_rate = clk_pllxc_set_rate, @@ -1826,7 +1940,7 @@ struct clk *tegra_clk_register_pllss(const char *name, const char *parent_name, struct clk *clk, *parent; struct tegra_clk_pll_freq_table cfg; unsigned long parent_rate; - u32 val; + u32 val, val_iddq; int i; if (!pll_params->div_nmp) @@ -1839,7 +1953,6 @@ struct clk *tegra_clk_register_pllss(const char *name, const char *parent_name, return ERR_PTR(-EINVAL); } - pll_params->flags = TEGRA_PLL_HAS_LOCK_ENABLE | TEGRA_PLL_USE_LOCK; pll = _tegra_init_pll(clk_base, NULL, pll_params, lock); if (IS_ERR(pll)) return ERR_CAST(pll); @@ -1874,6 +1987,345 @@ struct clk *tegra_clk_register_pllss(const char *name, const char *parent_name, pll_writel(PLLSS_CTRL1_DEFAULT, pll_params->ext_misc_reg[2], pll); val = pll_readl_base(pll); + val_iddq = readl_relaxed(clk_base + pll_params->iddq_reg); + if (val & PLL_BASE_ENABLE) { + if (val_iddq & BIT(pll_params->iddq_bit_idx)) { + WARN(1, "%s is on but IDDQ set\n", name); + kfree(pll); + return ERR_PTR(-EINVAL); + } + } else { + val_iddq |= BIT(pll_params->iddq_bit_idx); + writel_relaxed(val_iddq, clk_base + pll_params->iddq_reg); + } + + val &= ~PLLSS_LOCK_OVERRIDE; + pll_writel_base(val, pll); + + clk = _tegra_clk_register_pll(pll, name, parent_name, flags, + &tegra_clk_pllss_ops); + + if (IS_ERR(clk)) + kfree(pll); + + return clk; +} +#endif + +#if defined(CONFIG_ARCH_TEGRA_210_SOC) +static int clk_plle_tegra210_enable(struct clk_hw *hw) +{ + struct tegra_clk_pll *pll = to_clk_pll(hw); + struct tegra_clk_pll_freq_table sel; + u32 val; + int ret = 0; + unsigned long flags = 0; + unsigned long input_rate = clk_hw_get_rate(clk_hw_get_parent(hw)); + + if (_get_table_rate(hw, &sel, pll->params->fixed_rate, input_rate)) + return -EINVAL; + + if (pll->lock) + spin_lock_irqsave(pll->lock, flags); + + val = pll_readl(pll->params->aux_reg, pll); + if (val & PLLE_AUX_SEQ_ENABLE) + goto out; + + val = pll_readl_base(pll); + val &= ~BIT(30); /* Disable lock override */ + pll_writel_base(val, pll); + + val = pll_readl_misc(pll); + val |= PLLE_MISC_LOCK_ENABLE; + val |= PLLE_MISC_IDDQ_SW_CTRL; + val &= ~PLLE_MISC_IDDQ_SW_VALUE; + val |= PLLE_MISC_PLLE_PTS; + val &= ~(PLLE_MISC_VREG_BG_CTRL_MASK | PLLE_MISC_VREG_CTRL_MASK); + pll_writel_misc(val, pll); + udelay(5); + + val = pll_readl(PLLE_SS_CTRL, pll); + val |= PLLE_SS_DISABLE; + pll_writel(val, PLLE_SS_CTRL, pll); + + val = pll_readl_base(pll); + val &= ~(divp_mask_shifted(pll) | divn_mask_shifted(pll) | + divm_mask_shifted(pll)); + val &= ~(PLLE_BASE_DIVCML_MASK << PLLE_BASE_DIVCML_SHIFT); + val |= sel.m << divm_shift(pll); + val |= sel.n << divn_shift(pll); + val |= sel.cpcon << PLLE_BASE_DIVCML_SHIFT; + pll_writel_base(val, pll); + udelay(1); + + val = pll_readl_base(pll); + val |= PLLE_BASE_ENABLE; + pll_writel_base(val, pll); + + ret = clk_pll_wait_for_lock(pll); + + if (ret < 0) + goto out; + + val = pll_readl(PLLE_SS_CTRL, pll); + val &= ~(PLLE_SS_CNTL_CENTER | PLLE_SS_CNTL_INVERT); + val &= ~PLLE_SS_COEFFICIENTS_MASK; + val |= PLLE_SS_COEFFICIENTS_VAL_TEGRA210; + pll_writel(val, PLLE_SS_CTRL, pll); + val &= ~(PLLE_SS_CNTL_SSC_BYP | PLLE_SS_CNTL_BYPASS_SS); + pll_writel(val, PLLE_SS_CTRL, pll); + udelay(1); + val &= ~PLLE_SS_CNTL_INTERP_RESET; + pll_writel(val, PLLE_SS_CTRL, pll); + udelay(1); + + val = pll_readl_misc(pll); + val &= ~PLLE_MISC_IDDQ_SW_CTRL; + pll_writel_misc(val, pll); + + val = pll_readl(pll->params->aux_reg, pll); + val |= (PLLE_AUX_USE_LOCKDET | PLLE_AUX_SS_SEQ_INCLUDE); + val &= ~(PLLE_AUX_ENABLE_SWCTL | PLLE_AUX_SS_SWCTL); + pll_writel(val, pll->params->aux_reg, pll); + udelay(1); + val |= PLLE_AUX_SEQ_ENABLE; + pll_writel(val, pll->params->aux_reg, pll); + +out: + if (pll->lock) + spin_unlock_irqrestore(pll->lock, flags); + + return ret; +} + +static void clk_plle_tegra210_disable(struct clk_hw *hw) +{ + struct tegra_clk_pll *pll = to_clk_pll(hw); + unsigned long flags = 0; + u32 val; + + if (pll->lock) + spin_lock_irqsave(pll->lock, flags); + + /* If PLLE HW sequencer is enabled, SW should not disable PLLE */ + val = pll_readl(pll->params->aux_reg, pll); + if (val & PLLE_AUX_SEQ_ENABLE) + goto out; + + val = pll_readl_base(pll); + val &= ~PLLE_BASE_ENABLE; + pll_writel_base(val, pll); + + val = pll_readl(pll->params->aux_reg, pll); + val |= PLLE_AUX_ENABLE_SWCTL | PLLE_AUX_SS_SWCTL; + pll_writel(val, pll->params->aux_reg, pll); + + val = pll_readl_misc(pll); + val |= PLLE_MISC_IDDQ_SW_CTRL | PLLE_MISC_IDDQ_SW_VALUE; + pll_writel_misc(val, pll); + udelay(1); + +out: + if (pll->lock) + spin_unlock_irqrestore(pll->lock, flags); +} + +static int clk_plle_tegra210_is_enabled(struct clk_hw *hw) +{ + struct tegra_clk_pll *pll = to_clk_pll(hw); + u32 val; + + val = pll_readl_base(pll); + + return val & PLLE_BASE_ENABLE ? 1 : 0; +} + +static const struct clk_ops tegra_clk_plle_tegra210_ops = { + .is_enabled = clk_plle_tegra210_is_enabled, + .enable = clk_plle_tegra210_enable, + .disable = clk_plle_tegra210_disable, + .recalc_rate = clk_pll_recalc_rate, +}; + +struct clk *tegra_clk_register_plle_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; + u32 val, val_aux; + + pll = _tegra_init_pll(clk_base, NULL, pll_params, lock); + if (IS_ERR(pll)) + return ERR_CAST(pll); + + /* ensure parent is set to pll_re_vco */ + + val = pll_readl_base(pll); + val_aux = pll_readl(pll_params->aux_reg, pll); + + if (val & PLLE_BASE_ENABLE) { + if ((val_aux & PLLE_AUX_PLLRE_SEL) || + (val_aux & PLLE_AUX_PLLP_SEL)) + WARN(1, "pll_e enabled with unsupported parent %s\n", + (val_aux & PLLE_AUX_PLLP_SEL) ? "pllp_out0" : + "pll_re_vco"); + } else { + val_aux &= ~(PLLE_AUX_PLLRE_SEL | PLLE_AUX_PLLP_SEL); + pll_writel(val_aux, pll_params->aux_reg, pll); + } + + clk = _tegra_clk_register_pll(pll, name, parent_name, flags, + &tegra_clk_plle_tegra210_ops); + if (IS_ERR(clk)) + kfree(pll); + + return clk; +} + +struct clk *tegra_clk_register_pllc_tegra210(const char *name, + const char *parent_name, void __iomem *clk_base, + void __iomem *pmc, unsigned long flags, + struct tegra_clk_pll_params *pll_params, + spinlock_t *lock) +{ + struct clk *parent, *clk; + const struct pdiv_map *p_tohw = pll_params->pdiv_tohw; + struct tegra_clk_pll *pll; + unsigned long parent_rate; + + if (!p_tohw) + return ERR_PTR(-EINVAL); + + parent = __clk_lookup(parent_name); + if (!parent) { + WARN(1, "parent clk %s of %s must be registered first\n", + name, parent_name); + return ERR_PTR(-EINVAL); + } + + parent_rate = clk_get_rate(parent); + + pll_params->vco_min = _clip_vco_min(pll_params->vco_min, parent_rate); + + if (pll_params->adjust_vco) + pll_params->vco_min = pll_params->adjust_vco(pll_params, + parent_rate); + + pll_params->flags |= TEGRA_PLL_BYPASS; + pll = _tegra_init_pll(clk_base, pmc, pll_params, lock); + if (IS_ERR(pll)) + return ERR_CAST(pll); + + clk = _tegra_clk_register_pll(pll, name, parent_name, flags, + &tegra_clk_pll_ops); + if (IS_ERR(clk)) + kfree(pll); + + return clk; +} + +struct clk *tegra_clk_register_pllxc_tegra210(const char *name, + const char *parent_name, void __iomem *clk_base, + void __iomem *pmc, unsigned long flags, + struct tegra_clk_pll_params *pll_params, + spinlock_t *lock) +{ + struct tegra_clk_pll *pll; + struct clk *clk, *parent; + unsigned long parent_rate; + + parent = __clk_lookup(parent_name); + if (!parent) { + WARN(1, "parent clk %s of %s must be registered first\n", + name, parent_name); + return ERR_PTR(-EINVAL); + } + + if (!pll_params->pdiv_tohw) + return ERR_PTR(-EINVAL); + + parent_rate = clk_get_rate(parent); + + pll_params->vco_min = _clip_vco_min(pll_params->vco_min, parent_rate); + + if (pll_params->adjust_vco) + pll_params->vco_min = pll_params->adjust_vco(pll_params, + parent_rate); + + pll = _tegra_init_pll(clk_base, pmc, pll_params, lock); + if (IS_ERR(pll)) + return ERR_CAST(pll); + + clk = _tegra_clk_register_pll(pll, name, parent_name, flags, + &tegra_clk_pll_ops); + if (IS_ERR(clk)) + kfree(pll); + + return clk; +} + +struct clk *tegra_clk_register_pllss_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, *parent; + struct tegra_clk_pll_freq_table cfg; + unsigned long parent_rate; + u32 val; + int i; + + if (!pll_params->div_nmp) + return ERR_PTR(-EINVAL); + + parent = __clk_lookup(parent_name); + if (!parent) { + WARN(1, "parent clk %s of %s must be registered first\n", + name, parent_name); + return ERR_PTR(-EINVAL); + } + + pll = _tegra_init_pll(clk_base, NULL, pll_params, lock); + if (IS_ERR(pll)) + return ERR_CAST(pll); + + val = pll_readl_base(pll); + val &= ~PLLSS_REF_SRC_SEL_MASK; + pll_writel_base(val, pll); + + parent_rate = clk_get_rate(parent); + + pll_params->vco_min = _clip_vco_min(pll_params->vco_min, parent_rate); + + if (pll_params->adjust_vco) + pll_params->vco_min = pll_params->adjust_vco(pll_params, + parent_rate); + + /* initialize PLL to minimum rate */ + + cfg.m = _pll_fixed_mdiv(pll_params, parent_rate); + cfg.n = cfg.m * pll_params->vco_min / parent_rate; + + for (i = 0; pll_params->pdiv_tohw[i].pdiv; i++) + ; + if (!i) { + kfree(pll); + return ERR_PTR(-EINVAL); + } + + cfg.p = pll_params->pdiv_tohw[i-1].hw_val; + + _update_pll_mnp(pll, &cfg); + + pll_writel_misc(PLLSS_MISC_DEFAULT, pll); + + val = pll_readl_base(pll); if (val & PLL_BASE_ENABLE) { if (val & BIT(pll_params->iddq_bit_idx)) { WARN(1, "%s is on but IDDQ set\n", name); @@ -1887,8 +2339,50 @@ struct clk *tegra_clk_register_pllss(const char *name, const char *parent_name, pll_writel_base(val, pll); clk = _tegra_clk_register_pll(pll, name, parent_name, flags, - &tegra_clk_pllss_ops); + &tegra_clk_pll_ops); + + if (IS_ERR(clk)) + kfree(pll); + + return clk; +} + +struct clk *tegra_clk_register_pllmb(const char *name, const char *parent_name, + void __iomem *clk_base, void __iomem *pmc, + unsigned long flags, + struct tegra_clk_pll_params *pll_params, + spinlock_t *lock) +{ + struct tegra_clk_pll *pll; + struct clk *clk, *parent; + unsigned long parent_rate; + if (!pll_params->pdiv_tohw) + return ERR_PTR(-EINVAL); + + parent = __clk_lookup(parent_name); + if (!parent) { + WARN(1, "parent clk %s of %s must be registered first\n", + parent_name, name); + return ERR_PTR(-EINVAL); + } + + parent_rate = clk_get_rate(parent); + + pll_params->vco_min = _clip_vco_min(pll_params->vco_min, parent_rate); + + if (pll_params->adjust_vco) + pll_params->vco_min = pll_params->adjust_vco(pll_params, + parent_rate); + + pll_params->flags |= TEGRA_PLL_BYPASS; + pll_params->flags |= TEGRA_PLLMB; + pll = _tegra_init_pll(clk_base, pmc, pll_params, lock); + if (IS_ERR(pll)) + return ERR_CAST(pll); + + clk = _tegra_clk_register_pll(pll, name, parent_name, flags, + &tegra_clk_pll_ops); if (IS_ERR(clk)) kfree(pll); diff --git a/drivers/clk/tegra/clk-tegra-periph.c b/drivers/clk/tegra/clk-tegra-periph.c index cb6ab8309..ea2b9cbf9 100644 --- a/drivers/clk/tegra/clk-tegra-periph.c +++ b/drivers/clk/tegra/clk-tegra-periph.c @@ -124,6 +124,20 @@ #define CLK_SOURCE_HDMI_AUDIO 0x668 #define CLK_SOURCE_VIC03 0x678 #define CLK_SOURCE_CLK72MHZ 0x66c +#define CLK_SOURCE_DBGAPB 0x718 +#define CLK_SOURCE_NVENC 0x6a0 +#define CLK_SOURCE_NVDEC 0x698 +#define CLK_SOURCE_NVJPG 0x69c +#define CLK_SOURCE_APE 0x6c0 +#define CLK_SOURCE_SOR1 0x410 +#define CLK_SOURCE_SDMMC_LEGACY 0x694 +#define CLK_SOURCE_QSPI 0x6c4 +#define CLK_SOURCE_VI_I2C 0x6c8 +#define CLK_SOURCE_MIPIBIF 0x660 +#define CLK_SOURCE_UARTAPE 0x710 +#define CLK_SOURCE_TSECB 0x6d8 +#define CLK_SOURCE_MAUD 0x6d4 +#define CLK_SOURCE_USB2_HSIC_TRK 0x6cc #define MASK(x) (BIT(x) - 1) @@ -182,6 +196,13 @@ TEGRA_DIVIDER_ROUND_UP, _clk_num, 0, _clk_id,\ _parents##_idx, 0, NULL) +#define UART8(_name, _parents, _offset,\ + _clk_num, _clk_id) \ + TEGRA_INIT_DATA_TABLE(_name, NULL, NULL, _parents, _offset,\ + 29, MASK(3), 0, 0, 16, 1, TEGRA_DIVIDER_UART| \ + TEGRA_DIVIDER_ROUND_UP, _clk_num, 0, _clk_id,\ + _parents##_idx, 0, NULL) + #define I2C(_name, _parents, _offset,\ _clk_num, _clk_id) \ TEGRA_INIT_DATA_TABLE(_name, NULL, NULL, _parents, _offset,\ @@ -221,8 +242,21 @@ .flags = _flags \ } +#define DIV8(_name, _parent_name, _offset, _clk_id, _flags) \ + { \ + .name = _name, \ + .clk_id = _clk_id, \ + .p.parent_name = _parent_name, \ + .periph = TEGRA_CLK_PERIPH(0, 0, 0, 0, 8, 1, \ + TEGRA_DIVIDER_ROUND_UP, 0, 0, \ + NULL, NULL), \ + .offset = _offset, \ + .flags = _flags, \ + } + #define PLLP_BASE 0xa0 #define PLLP_MISC 0xac +#define PLLP_MISC1 0x680 #define PLLP_OUTA 0xa4 #define PLLP_OUTB 0xa8 #define PLLP_OUTC 0x67c @@ -234,6 +268,7 @@ static DEFINE_SPINLOCK(PLLP_OUTA_lock); static DEFINE_SPINLOCK(PLLP_OUTB_lock); static DEFINE_SPINLOCK(PLLP_OUTC_lock); static DEFINE_SPINLOCK(sor0_lock); +static DEFINE_SPINLOCK(sor1_lock); #define MUX_I2S_SPDIF(_id) \ static const char *mux_pllaout0_##_id##_2x_pllp_clkm[] = { "pll_a_out0", \ @@ -285,6 +320,68 @@ static u32 mux_pllp_clkm_idx[] = { [0] = 0, [1] = 3, }; +static const char *mux_pllp_clkm_2[] = { + "pll_p", "clk_m" +}; +static u32 mux_pllp_clkm_2_idx[] = { + [0] = 2, [1] = 6, +}; + +static const char *mux_pllc2_c_c3_pllp_plla1_clkm[] = { + "pll_c2", "pll_c", "pll_c3", "pll_p", "pll_a1", "clk_m" +}; +static u32 mux_pllc2_c_c3_pllp_plla1_clkm_idx[] = { + [0] = 1, [1] = 2, [2] = 3, [3] = 4, [4] = 6, [5] = 7, +}; + +static const char * +mux_pllc4_out1_pllc_pllc4_out2_pllp_clkm_plla_pllc4_out0[] = { + "pll_c4_out1", "pll_c", "pll_c4_out2", "pll_p", "clk_m", + "pll_a_out0", "pll_c4_out0" +}; +static u32 mux_pllc4_out1_pllc_pllc4_out2_pllp_clkm_plla_pllc4_out0_idx[] = { + [0] = 0, [1] = 2, [2] = 3, [3] = 4, [4] = 5, [5] = 6, [6] = 7, +}; + +static const char *mux_pllc_pllp_plla[] = { + "pll_c", "pll_p", "pll_a_out0" +}; +static u32 mux_pllc_pllp_plla_idx[] = { + [0] = 1, [1] = 2, [2] = 3, +}; + +static const char *mux_clkm_pllc_pllp_plla[] = { + "clk_m", "pll_c", "pll_p", "pll_a_out0" +}; +#define mux_clkm_pllc_pllp_plla_idx NULL + +static const char *mux_pllc_pllp_plla1_pllc2_c3_clkm[] = { + "pll_c", "pll_p", "pll_a1", "pll_c2", "pll_c3", "clk_m" +}; +static u32 mux_pllc_pllp_plla1_pllc2_c3_clkm_idx[] = { + [0] = 1, [1] = 2, [2] = 3, [3] = 4, [4] = 5, [5] = 6, +}; + +static const char *mux_pllc2_c_c3_pllp_clkm_plla1_pllc4[] = { + "pll_c2", "pll_c", "pll_c3", "pll_p", "clk_m", "pll_a1", "pll_c4_out0", +}; +static u32 mux_pllc2_c_c3_pllp_clkm_plla1_pllc4_idx[] = { + [0] = 1, [1] = 2, [2] = 3, [3] = 4, [4] = 5, [5] = 6, [6] = 7, +}; + +static const char *mux_pllc_pllp_plla1_pllc2_c3_clkm_pllc4[] = { + "pll_c", "pll_p", "pll_a1", "pll_c2", "pll_c3", "clk_m", "pll_c4_out0", +}; +#define mux_pllc_pllp_plla1_pllc2_c3_clkm_pllc4_idx \ + mux_pllc2_c_c3_pllp_clkm_plla1_pllc4_idx + +static const char * +mux_plla_pllc4_out0_pllc_pllc4_out1_pllp_pllc4_out2_clkm[] = { + "pll_a_out0", "pll_c4_out0", "pll_c", "pll_c4_out1", "pll_p", + "pll_c4_out2", "clk_m" +}; +#define mux_plla_pllc4_out0_pllc_pllc4_out1_pllp_pllc4_out2_clkm_idx NULL + static const char *mux_pllm_pllc2_c_c3_pllp_plla[] = { "pll_m", "pll_c2", "pll_c", "pll_c3", "pll_p", "pll_a_out0" }; @@ -302,12 +399,93 @@ static const char *mux_pllm_pllc_pllp_plla[] = { #define mux_pllm_pllc_pllp_plla_idx mux_pllp_pllc_pllm_clkm_idx static const char *mux_pllp_pllc_clkm[] = { - "pll_p", "pll_c", "pll_m" + "pll_p", "pll_c", "clk_m" }; static u32 mux_pllp_pllc_clkm_idx[] = { [0] = 0, [1] = 1, [2] = 3, }; +static const char *mux_pllp_pllc_clkm_1[] = { + "pll_p", "pll_c", "clk_m" +}; +static u32 mux_pllp_pllc_clkm_1_idx[] = { + [0] = 0, [1] = 2, [2] = 5, +}; + +static const char *mux_pllp_pllc_plla_clkm[] = { + "pll_p", "pll_c", "pll_a_out0", "clk_m" +}; +static u32 mux_pllp_pllc_plla_clkm_idx[] = { + [0] = 0, [1] = 2, [2] = 4, [3] = 6, +}; + +static const char *mux_pllp_pllc_pllc4_out0_pllc4_out1_clkm_pllc4_out2[] = { + "pll_p", "pll_c", "pll_c4_out0", "pll_c4_out1", "clk_m", "pll_c4_out2" +}; +static u32 mux_pllp_pllc_pllc4_out0_pllc4_out1_clkm_pllc4_out2_idx[] = { + [0] = 0, [1] = 2, [2] = 3, [3] = 5, [4] = 6, [5] = 7, +}; + +static const char * +mux_pllp_pllc_pllc_out1_pllc4_out2_pllc4_out1_clkm_pllc4_out0[] = { + "pll_p", "pll_c_out1", "pll_c", "pll_c4_out2", "pll_c4_out1", + "clk_m", "pll_c4_out0" +}; +static u32 +mux_pllp_pllc_pllc_out1_pllc4_out2_pllc4_out1_clkm_pllc4_out0_idx[] = { + [0] = 0, [1] = 1, [2] = 2, [3] = 4, [4] = 5, [5] = 6, [6] = 7, +}; + +static const char *mux_pllp_pllc4_out2_pllc4_out1_clkm_pllc4_out0[] = { + "pll_p", "pll_c4_out2", "pll_c4_out1", "clk_m", "pll_c4_out0" +}; +static u32 mux_pllp_pllc4_out2_pllc4_out1_clkm_pllc4_out0_idx[] = { + [0] = 0, [1] = 3, [2] = 4, [3] = 6, [4] = 7, +}; + +static const char *mux_pllp_clkm_pllc4_out2_out1_out0_lj[] = { + "pll_p", + "pll_c4_out2", "pll_c4_out0", /* LJ input */ + "pll_c4_out2", "pll_c4_out1", + "pll_c4_out1", /* LJ input */ + "clk_m", "pll_c4_out0" +}; +#define mux_pllp_clkm_pllc4_out2_out1_out0_lj_idx NULL + +static const char *mux_pllp_pllc2_c_c3_clkm[] = { + "pll_p", "pll_c2", "pll_c", "pll_c3", "clk_m" +}; +static u32 mux_pllp_pllc2_c_c3_clkm_idx[] = { + [0] = 0, [1] = 1, [2] = 2, [3] = 3, [4] = 6, +}; + +static const char *mux_pllp_clkm_clk32_plle[] = { + "pll_p", "clk_m", "clk_32k", "pll_e" +}; +static u32 mux_pllp_clkm_clk32_plle_idx[] = { + [0] = 0, [1] = 2, [2] = 4, [3] = 6, +}; + +static const char *mux_pllp_pllp_out3_clkm_clk32k_plla[] = { + "pll_p", "pll_p_out3", "clk_m", "clk_32k", "pll_a_out0" +}; +#define mux_pllp_pllp_out3_clkm_clk32k_plla_idx NULL + +static const char *mux_pllp_out3_clkm_pllp_pllc4[] = { + "pll_p_out3", "clk_m", "pll_p", "pll_c4_out0", "pll_c4_out1", + "pll_c4_out2" +}; +static u32 mux_pllp_out3_clkm_pllp_pllc4_idx[] = { + [0] = 0, [1] = 3, [2] = 4, [3] = 5, [4] = 6, [5] = 7, +}; + +static const char *mux_clkm_pllp_pllre[] = { + "clk_m", "pll_p_out_xusb", "pll_re_out" +}; +static u32 mux_clkm_pllp_pllre_idx[] = { + [0] = 0, [1] = 1, [2] = 5, +}; + static const char *mux_pllp_pllc_clkm_clk32[] = { "pll_p", "pll_c", "clk_m", "clk_32k" }; @@ -332,6 +510,11 @@ static u32 mux_clkm_48M_pllp_480M_idx[] = { [0] = 0, [1] = 2, [2] = 4, [3] = 6, }; +static const char *mux_clkm_pllre_clk32_480M[] = { + "clk_m", "pll_re_out", "clk_32k", "pll_u_480M" +}; +#define mux_clkm_pllre_clk32_480M_idx NULL + static const char *mux_clkm_pllre_clk32_480M_pllc_ref[] = { "clk_m", "pll_re_out", "clk_32k", "pll_u_480M", "pll_c", "pll_ref" }; @@ -339,10 +522,27 @@ static u32 mux_clkm_pllre_clk32_480M_pllc_ref_idx[] = { [0] = 0, [1] = 1, [2] = 3, [3] = 3, [4] = 4, [5] = 7, }; -static const char *mux_ss_60M[] = { +static const char *mux_pllp_out3_pllp_pllc_clkm[] = { + "pll_p_out3", "pll_p", "pll_c", "clk_m" +}; +static u32 mux_pllp_out3_pllp_pllc_clkm_idx[] = { + [0] = 0, [1] = 1, [2] = 2, [3] = 6, +}; + +static const char *mux_ss_div2_60M[] = { "xusb_ss_div2", "pll_u_60M" }; -#define mux_ss_60M_idx NULL +#define mux_ss_div2_60M_idx NULL + +static const char *mux_ss_div2_60M_ss[] = { + "xusb_ss_div2", "pll_u_60M", "xusb_ss_src" +}; +#define mux_ss_div2_60M_ss_idx NULL + +static const char *mux_ss_clkm[] = { + "xusb_ss_src", "clk_m" +}; +#define mux_ss_clkm_idx NULL static const char *mux_d_audio_clk[] = { "pll_a_out0", "pll_p", "clk_m", "spdif_in_sync", "i2s0_sync", @@ -386,6 +586,32 @@ static u32 mux_pllm_pllc2_c_c3_pllp_plla_pllc4_idx[] = { [0] = 0, [1] = 1, [2] = 2, [3] = 3, [4] = 4, [5] = 6, [6] = 7, }; +/* SOR1 mux'es */ +static const char *mux_pllp_plld_plld2_clkm[] = { + "pll_p", "pll_d_out0", "pll_d2_out0", "clk_m" +}; +static u32 mux_pllp_plld_plld2_clkm_idx[] = { + [0] = 0, [1] = 2, [2] = 5, [3] = 6 +}; + +static const char *mux_plldp_sor1_src[] = { + "pll_dp", "clk_sor1_src" +}; +#define mux_plldp_sor1_src_idx NULL + +static const char *mux_clkm_sor1_brick_sor1_src[] = { + "clk_m", "sor1_brick", "sor1_src", "sor1_brick" +}; +#define mux_clkm_sor1_brick_sor1_src_idx NULL + +static const char *mux_pllp_pllre_clkm[] = { + "pll_p", "pll_re_out1", "clk_m" +}; + +static u32 mux_pllp_pllre_clkm_idx[] = { + [0] = 0, [1] = 2, [2] = 3, +}; + static const char *mux_clkm_plldp_sor0lvds[] = { "clk_m", "pll_dp", "sor0_lvds", }; @@ -401,6 +627,7 @@ static struct tegra_periph_init_data periph_clks[] = { I2C("i2c3", mux_pllp_clkm, CLK_SOURCE_I2C3, 67, tegra_clk_i2c3), I2C("i2c4", mux_pllp_clkm, CLK_SOURCE_I2C4, 103, tegra_clk_i2c4), I2C("i2c5", mux_pllp_clkm, CLK_SOURCE_I2C5, 47, tegra_clk_i2c5), + I2C("i2c6", mux_pllp_clkm, CLK_SOURCE_I2C6, 166, tegra_clk_i2c6), INT("vde", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_VDE, 61, 0, tegra_clk_vde), INT("vi", mux_pllm_pllc_pllp_plla, CLK_SOURCE_VI, 20, 0, tegra_clk_vi), INT("epp", mux_pllm_pllc_pllp_plla, CLK_SOURCE_EPP, 19, 0, tegra_clk_epp), @@ -411,14 +638,19 @@ static struct tegra_periph_init_data periph_clks[] = { INT8("vde", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_VDE, 61, 0, tegra_clk_vde_8), INT8("vi", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_VI, 20, 0, tegra_clk_vi_8), INT8("vi", mux_pllm_pllc2_c_c3_pllp_plla_pllc4, CLK_SOURCE_VI, 20, 0, tegra_clk_vi_9), + INT8("vi", mux_pllc2_c_c3_pllp_clkm_plla1_pllc4, CLK_SOURCE_VI, 20, 0, tegra_clk_vi_10), INT8("epp", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_EPP, 19, 0, tegra_clk_epp_8), INT8("msenc", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_MSENC, 91, TEGRA_PERIPH_WAR_1005168, tegra_clk_msenc), INT8("tsec", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_TSEC, 83, 0, tegra_clk_tsec), + INT("tsec", mux_pllp_pllc_clkm, CLK_SOURCE_TSEC, 83, 0, tegra_clk_tsec_8), INT8("host1x", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_HOST1X, 28, 0, tegra_clk_host1x_8), + INT8("host1x", mux_pllc4_out1_pllc_pllc4_out2_pllp_clkm_plla_pllc4_out0, CLK_SOURCE_HOST1X, 28, 0, tegra_clk_host1x_9), INT8("se", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_SE, 127, TEGRA_PERIPH_ON_APB, tegra_clk_se), + INT8("se", mux_pllp_pllc2_c_c3_clkm, CLK_SOURCE_SE, 127, TEGRA_PERIPH_ON_APB, tegra_clk_se), INT8("2d", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_2D, 21, 0, tegra_clk_gr2d_8), INT8("3d", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_3D, 24, 0, tegra_clk_gr3d_8), INT8("vic03", mux_pllm_pllc_pllp_plla_pllc2_c3_clkm, CLK_SOURCE_VIC03, 178, 0, tegra_clk_vic03), + INT8("vic03", mux_pllc_pllp_plla1_pllc2_c3_clkm, CLK_SOURCE_VIC03, 178, 0, tegra_clk_vic03_8), INT_FLAGS("mselect", mux_pllp_clkm, CLK_SOURCE_MSELECT, 99, 0, tegra_clk_mselect, CLK_IGNORE_UNUSED), MUX("i2s0", mux_pllaout0_audio0_2x_pllp_clkm, CLK_SOURCE_I2S0, 30, TEGRA_PERIPH_ON_APB, tegra_clk_i2s0), MUX("i2s1", mux_pllaout0_audio1_2x_pllp_clkm, CLK_SOURCE_I2S1, 11, TEGRA_PERIPH_ON_APB, tegra_clk_i2s1), @@ -427,22 +659,31 @@ static struct tegra_periph_init_data periph_clks[] = { MUX("i2s4", mux_pllaout0_audio4_2x_pllp_clkm, CLK_SOURCE_I2S4, 102, TEGRA_PERIPH_ON_APB, tegra_clk_i2s4), MUX("spdif_out", mux_pllaout0_audio_2x_pllp_clkm, CLK_SOURCE_SPDIF_OUT, 10, TEGRA_PERIPH_ON_APB, tegra_clk_spdif_out), MUX("spdif_in", mux_pllp_pllc_pllm, CLK_SOURCE_SPDIF_IN, 10, TEGRA_PERIPH_ON_APB, tegra_clk_spdif_in), + MUX8("spdif_in", mux_pllp_pllc_clkm_1, CLK_SOURCE_SPDIF_IN, 10, TEGRA_PERIPH_ON_APB, tegra_clk_spdif_in_8), MUX("pwm", mux_pllp_pllc_clk32_clkm, CLK_SOURCE_PWM, 17, TEGRA_PERIPH_ON_APB, tegra_clk_pwm), MUX("adx", mux_plla_pllc_pllp_clkm, CLK_SOURCE_ADX, 154, TEGRA_PERIPH_ON_APB, tegra_clk_adx), MUX("amx", mux_plla_pllc_pllp_clkm, CLK_SOURCE_AMX, 153, TEGRA_PERIPH_ON_APB, tegra_clk_amx), MUX("hda", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_HDA, 125, TEGRA_PERIPH_ON_APB, tegra_clk_hda), + MUX("hda", mux_pllp_pllc_clkm, CLK_SOURCE_HDA, 125, TEGRA_PERIPH_ON_APB, tegra_clk_hda_8), MUX("hda2codec_2x", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_HDA2CODEC_2X, 111, TEGRA_PERIPH_ON_APB, tegra_clk_hda2codec_2x), + MUX8("hda2codec_2x", mux_pllp_pllc_plla_clkm, CLK_SOURCE_HDA2CODEC_2X, 111, TEGRA_PERIPH_ON_APB, tegra_clk_hda2codec_2x_8), MUX("vfir", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_VFIR, 7, TEGRA_PERIPH_ON_APB, tegra_clk_vfir), MUX("sdmmc1", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_SDMMC1, 14, TEGRA_PERIPH_ON_APB, tegra_clk_sdmmc1), MUX("sdmmc2", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_SDMMC2, 9, TEGRA_PERIPH_ON_APB, tegra_clk_sdmmc2), MUX("sdmmc3", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_SDMMC3, 69, TEGRA_PERIPH_ON_APB, tegra_clk_sdmmc3), MUX("sdmmc4", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_SDMMC4, 15, TEGRA_PERIPH_ON_APB, tegra_clk_sdmmc4), + MUX8("sdmmc1", mux_pllp_pllc4_out2_pllc4_out1_clkm_pllc4_out0, CLK_SOURCE_SDMMC1, 14, TEGRA_PERIPH_ON_APB, tegra_clk_sdmmc1_9), + MUX8("sdmmc2", mux_pllp_clkm_pllc4_out2_out1_out0_lj, CLK_SOURCE_SDMMC2, 9, TEGRA_PERIPH_ON_APB, tegra_clk_sdmmc2_9), + MUX8("sdmmc3", mux_pllp_pllc4_out2_pllc4_out1_clkm_pllc4_out0, CLK_SOURCE_SDMMC3, 69, TEGRA_PERIPH_ON_APB, tegra_clk_sdmmc3_9), + MUX8("sdmmc4", mux_pllp_clkm_pllc4_out2_out1_out0_lj, CLK_SOURCE_SDMMC4, 15, TEGRA_PERIPH_ON_APB, tegra_clk_sdmmc4_9), MUX("la", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_LA, 76, TEGRA_PERIPH_ON_APB, tegra_clk_la), MUX("trace", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_TRACE, 77, TEGRA_PERIPH_ON_APB, tegra_clk_trace), MUX("owr", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_OWR, 71, TEGRA_PERIPH_ON_APB, tegra_clk_owr), + MUX("owr", mux_pllp_pllc_clkm, CLK_SOURCE_OWR, 71, TEGRA_PERIPH_ON_APB, tegra_clk_owr_8), MUX("nor", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_NOR, 42, 0, tegra_clk_nor), MUX("mipi", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_MIPI, 50, TEGRA_PERIPH_ON_APB, tegra_clk_mipi), MUX("vi_sensor", mux_pllm_pllc_pllp_plla, CLK_SOURCE_VI_SENSOR, 20, TEGRA_PERIPH_NO_RESET, tegra_clk_vi_sensor), + MUX("vi_sensor", mux_pllc_pllp_plla, CLK_SOURCE_VI_SENSOR, 20, TEGRA_PERIPH_NO_RESET, tegra_clk_vi_sensor_9), MUX("cilab", mux_pllp_pllc_clkm, CLK_SOURCE_CILAB, 144, 0, tegra_clk_cilab), MUX("cilcd", mux_pllp_pllc_clkm, CLK_SOURCE_CILCD, 145, 0, tegra_clk_cilcd), MUX("cile", mux_pllp_pllc_clkm, CLK_SOURCE_CILE, 146, 0, tegra_clk_cile), @@ -465,10 +706,13 @@ static struct tegra_periph_init_data periph_clks[] = { MUX("ndflash", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_NDFLASH, 13, TEGRA_PERIPH_ON_APB, tegra_clk_ndflash), MUX("ndspeed", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_NDSPEED, 80, TEGRA_PERIPH_ON_APB, tegra_clk_ndspeed), MUX("sata_oob", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_SATA_OOB, 123, TEGRA_PERIPH_ON_APB, tegra_clk_sata_oob), + MUX("sata_oob", mux_pllp_pllc_clkm, CLK_SOURCE_SATA_OOB, 123, TEGRA_PERIPH_ON_APB, tegra_clk_sata_oob_8), MUX("sata", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_SATA, 124, TEGRA_PERIPH_ON_APB, tegra_clk_sata), + MUX("sata", mux_pllp_pllc_clkm, CLK_SOURCE_SATA, 124, TEGRA_PERIPH_ON_APB, tegra_clk_sata_8), MUX("adx1", mux_plla_pllc_pllp_clkm, CLK_SOURCE_ADX1, 180, TEGRA_PERIPH_ON_APB, tegra_clk_adx1), MUX("amx1", mux_plla_pllc_pllp_clkm, CLK_SOURCE_AMX1, 185, TEGRA_PERIPH_ON_APB, tegra_clk_amx1), MUX("vi_sensor2", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_VI_SENSOR2, 165, TEGRA_PERIPH_NO_RESET, tegra_clk_vi_sensor2), + MUX("vi_sensor2", mux_pllc_pllp_plla, CLK_SOURCE_VI_SENSOR2, 165, TEGRA_PERIPH_NO_RESET, tegra_clk_vi_sensor2_8), MUX8("sdmmc1", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_SDMMC1, 14, TEGRA_PERIPH_ON_APB, tegra_clk_sdmmc1_8), MUX8("sdmmc2", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_SDMMC2, 9, TEGRA_PERIPH_ON_APB, tegra_clk_sdmmc2_8), MUX8("sdmmc3", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_SDMMC3, 69, TEGRA_PERIPH_ON_APB, tegra_clk_sdmmc3_8), @@ -479,6 +723,10 @@ static struct tegra_periph_init_data periph_clks[] = { MUX8("sbc4", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_SBC4, 68, TEGRA_PERIPH_ON_APB, tegra_clk_sbc4_8), MUX8("sbc5", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_SBC5, 104, TEGRA_PERIPH_ON_APB, tegra_clk_sbc5_8), MUX8("sbc6", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_SBC6, 105, TEGRA_PERIPH_ON_APB, tegra_clk_sbc6_8), + MUX("sbc1", mux_pllp_pllc_clkm, CLK_SOURCE_SBC1, 41, TEGRA_PERIPH_ON_APB, tegra_clk_sbc1_9), + MUX("sbc2", mux_pllp_pllc_clkm, CLK_SOURCE_SBC2, 44, TEGRA_PERIPH_ON_APB, tegra_clk_sbc2_9), + MUX("sbc3", mux_pllp_pllc_clkm, CLK_SOURCE_SBC3, 46, TEGRA_PERIPH_ON_APB, tegra_clk_sbc3_9), + MUX("sbc4", mux_pllp_pllc_clkm, CLK_SOURCE_SBC4, 68, TEGRA_PERIPH_ON_APB, tegra_clk_sbc4_9), MUX8("ndflash", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_NDFLASH, 13, TEGRA_PERIPH_ON_APB, tegra_clk_ndflash_8), MUX8("ndspeed", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_NDSPEED, 80, TEGRA_PERIPH_ON_APB, tegra_clk_ndspeed_8), MUX8("hdmi", mux_pllp_pllm_plld_plla_pllc_plld2_clkm, CLK_SOURCE_HDMI, 51, 0, tegra_clk_hdmi), @@ -486,27 +734,59 @@ static struct tegra_periph_init_data periph_clks[] = { MUX8("extern2", mux_plla_clk32_pllp_clkm_plle, CLK_SOURCE_EXTERN2, 121, 0, tegra_clk_extern2), MUX8("extern3", mux_plla_clk32_pllp_clkm_plle, CLK_SOURCE_EXTERN3, 122, 0, tegra_clk_extern3), MUX8("soc_therm", mux_pllm_pllc_pllp_plla, CLK_SOURCE_SOC_THERM, 78, TEGRA_PERIPH_ON_APB, tegra_clk_soc_therm), + 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("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), MUX8("clk72mhz", mux_pllp3_pllc_clkm, CLK_SOURCE_CLK72MHZ, 177, TEGRA_PERIPH_NO_RESET, tegra_clk_clk72Mhz), + MUX8("clk72mhz", mux_pllp_out3_pllp_pllc_clkm, CLK_SOURCE_CLK72MHZ, 177, TEGRA_PERIPH_NO_RESET, tegra_clk_clk72Mhz_8), MUX8_NOGATE_LOCK("sor0_lvds", mux_pllp_pllm_plld_plla_pllc_plld2_clkm, CLK_SOURCE_SOR0, tegra_clk_sor0_lvds, &sor0_lock), MUX_FLAGS("csite", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_CSITE, 73, TEGRA_PERIPH_ON_APB, tegra_clk_csite, CLK_IGNORE_UNUSED), + MUX_FLAGS("csite", mux_pllp_pllre_clkm, CLK_SOURCE_CSITE, 73, TEGRA_PERIPH_ON_APB, tegra_clk_csite_8, CLK_IGNORE_UNUSED), NODIV("disp1", mux_pllp_pllm_plld_plla_pllc_plld2_clkm, CLK_SOURCE_DISP1, 29, 7, 27, 0, tegra_clk_disp1, NULL), + NODIV("disp1", mux_pllp_plld_plld2_clkm, CLK_SOURCE_DISP1, 29, 7, 27, 0, tegra_clk_disp1_8, NULL), NODIV("disp2", mux_pllp_pllm_plld_plla_pllc_plld2_clkm, CLK_SOURCE_DISP2, 29, 7, 26, 0, tegra_clk_disp2, NULL), + NODIV("disp2", mux_pllp_plld_plld2_clkm, CLK_SOURCE_DISP2, 29, 7, 26, 0, tegra_clk_disp2_8, NULL), NODIV("sor0", mux_clkm_plldp_sor0lvds, CLK_SOURCE_SOR0, 14, 3, 182, 0, tegra_clk_sor0, &sor0_lock), UART("uarta", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_UARTA, 6, tegra_clk_uarta), UART("uartb", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_UARTB, 7, tegra_clk_uartb), UART("uartc", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_UARTC, 55, tegra_clk_uartc), UART("uartd", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_UARTD, 65, tegra_clk_uartd), UART("uarte", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_UARTE, 66, tegra_clk_uarte), + UART8("uarta", mux_pllp_pllc_pllc4_out0_pllc4_out1_clkm_pllc4_out2, CLK_SOURCE_UARTA, 6, tegra_clk_uarta_8), + UART8("uartb", mux_pllp_pllc_pllc4_out0_pllc4_out1_clkm_pllc4_out2, CLK_SOURCE_UARTB, 7, tegra_clk_uartb_8), + UART8("uartc", mux_pllp_pllc_pllc4_out0_pllc4_out1_clkm_pllc4_out2, CLK_SOURCE_UARTC, 55, tegra_clk_uartc_8), + UART8("uartd", mux_pllp_pllc_pllc4_out0_pllc4_out1_clkm_pllc4_out2, CLK_SOURCE_UARTD, 65, tegra_clk_uartd_8), XUSB("xusb_host_src", mux_clkm_pllp_pllc_pllre, CLK_SOURCE_XUSB_HOST_SRC, 143, TEGRA_PERIPH_ON_APB | TEGRA_PERIPH_NO_RESET, tegra_clk_xusb_host_src), + XUSB("xusb_host_src", mux_clkm_pllp_pllre, CLK_SOURCE_XUSB_HOST_SRC, 143, TEGRA_PERIPH_ON_APB | TEGRA_PERIPH_NO_RESET, tegra_clk_xusb_host_src_8), XUSB("xusb_falcon_src", mux_clkm_pllp_pllc_pllre, CLK_SOURCE_XUSB_FALCON_SRC, 143, TEGRA_PERIPH_NO_RESET, tegra_clk_xusb_falcon_src), + XUSB("xusb_falcon_src", mux_clkm_pllp_pllre, CLK_SOURCE_XUSB_FALCON_SRC, 143, TEGRA_PERIPH_NO_RESET, tegra_clk_xusb_falcon_src_8), XUSB("xusb_fs_src", mux_clkm_48M_pllp_480M, CLK_SOURCE_XUSB_FS_SRC, 143, TEGRA_PERIPH_NO_RESET, tegra_clk_xusb_fs_src), XUSB("xusb_ss_src", mux_clkm_pllre_clk32_480M_pllc_ref, CLK_SOURCE_XUSB_SS_SRC, 143, TEGRA_PERIPH_NO_RESET, tegra_clk_xusb_ss_src), - NODIV("xusb_hs_src", mux_ss_60M, CLK_SOURCE_XUSB_SS_SRC, 25, MASK(1), 143, TEGRA_PERIPH_NO_RESET, tegra_clk_xusb_hs_src, NULL), + XUSB("xusb_ss_src", mux_clkm_pllre_clk32_480M, CLK_SOURCE_XUSB_SS_SRC, 143, TEGRA_PERIPH_NO_RESET, tegra_clk_xusb_ss_src_8), + NODIV("xusb_hs_src", mux_ss_div2_60M, CLK_SOURCE_XUSB_SS_SRC, 25, MASK(1), 143, TEGRA_PERIPH_NO_RESET, tegra_clk_xusb_hs_src, NULL), + NODIV("xusb_hs_src", mux_ss_div2_60M_ss, CLK_SOURCE_XUSB_SS_SRC, 25, MASK(2), 143, TEGRA_PERIPH_NO_RESET, tegra_clk_xusb_hs_src_4, NULL), + NODIV("xusb_ssp_src", mux_ss_clkm, CLK_SOURCE_XUSB_SS_SRC, 24, MASK(1), 143, TEGRA_PERIPH_NO_RESET, tegra_clk_xusb_ssp_src, NULL), XUSB("xusb_dev_src", mux_clkm_pllp_pllc_pllre, CLK_SOURCE_XUSB_DEV_SRC, 95, TEGRA_PERIPH_ON_APB | TEGRA_PERIPH_NO_RESET, tegra_clk_xusb_dev_src), + XUSB("xusb_dev_src", mux_clkm_pllp_pllre, CLK_SOURCE_XUSB_DEV_SRC, 95, TEGRA_PERIPH_ON_APB | TEGRA_PERIPH_NO_RESET, tegra_clk_xusb_dev_src_8), + MUX8("dbgapb", mux_pllp_clkm_2, CLK_SOURCE_DBGAPB, 185, TEGRA_PERIPH_NO_RESET, tegra_clk_dbgapb), + MUX8("nvenc", mux_pllc2_c_c3_pllp_plla1_clkm, CLK_SOURCE_NVENC, 219, 0, tegra_clk_nvenc), + MUX8("nvdec", mux_pllc2_c_c3_pllp_plla1_clkm, CLK_SOURCE_NVDEC, 194, 0, tegra_clk_nvdec), + MUX8("nvjpg", mux_pllc2_c_c3_pllp_plla1_clkm, CLK_SOURCE_NVJPG, 195, 0, tegra_clk_nvjpg), + MUX8("ape", mux_plla_pllc4_out0_pllc_pllc4_out1_pllp_pllc4_out2_clkm, CLK_SOURCE_APE, 198, TEGRA_PERIPH_ON_APB, tegra_clk_ape), + MUX8_NOGATE_LOCK("sor1_src", mux_pllp_plld_plld2_clkm, CLK_SOURCE_SOR1, tegra_clk_sor1_src, &sor1_lock), + NODIV("sor1_brick", mux_plldp_sor1_src, CLK_SOURCE_SOR1, 14, MASK(1), 183, 0, tegra_clk_sor1_brick, &sor1_lock), + NODIV("sor1", mux_clkm_sor1_brick_sor1_src, CLK_SOURCE_SOR1, 15, MASK(1), 183, 0, tegra_clk_sor1, &sor1_lock), + MUX8("sdmmc_legacy", mux_pllp_out3_clkm_pllp_pllc4, CLK_SOURCE_SDMMC_LEGACY, 193, TEGRA_PERIPH_ON_APB | TEGRA_PERIPH_NO_RESET, tegra_clk_sdmmc_legacy), + MUX8("qspi", mux_pllp_pllc_pllc_out1_pllc4_out2_pllc4_out1_clkm_pllc4_out0, CLK_SOURCE_QSPI, 211, TEGRA_PERIPH_ON_APB, tegra_clk_qspi), + I2C("vii2c", mux_pllp_pllc_clkm, CLK_SOURCE_VI_I2C, 208, tegra_clk_vi_i2c), + MUX("mipibif", mux_pllp_clkm, CLK_SOURCE_MIPIBIF, 173, TEGRA_PERIPH_ON_APB, tegra_clk_mipibif), + 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), }; static struct tegra_periph_init_data gate_clks[] = { @@ -543,6 +823,17 @@ static struct tegra_periph_init_data gate_clks[] = { GATE("pcie", "clk_m", 70, 0, tegra_clk_pcie, 0), GATE("dpaux", "clk_m", 181, 0, tegra_clk_dpaux, 0), GATE("gpu", "pll_ref", 184, 0, tegra_clk_gpu, 0), + GATE("pllg_ref", "pll_ref", 189, 0, tegra_clk_pll_g_ref, 0), + GATE("hsic_trk", "usb2_hsic_trk", 209, TEGRA_PERIPH_NO_RESET, tegra_clk_hsic_trk, 0), + GATE("usb2_trk", "usb2_hsic_trk", 210, TEGRA_PERIPH_NO_RESET, tegra_clk_usb2_trk, 0), + GATE("xusb_gate", "osc", 143, 0, tegra_clk_xusb_gate, 0), + 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), +}; + +static struct tegra_periph_init_data div_clks[] = { + DIV8("usb2_hsic_trk", "osc", CLK_SOURCE_USB2_HSIC_TRK, tegra_clk_usb2_hsic_trk, 0), }; struct pll_out_data { @@ -633,6 +924,33 @@ static void __init gate_clk_init(void __iomem *clk_base, } } +static void __init div_clk_init(void __iomem *clk_base, + struct tegra_clk *tegra_clks) +{ + int i; + struct clk *clk; + struct clk **dt_clk; + + for (i = 0; i < ARRAY_SIZE(div_clks); i++) { + struct tegra_periph_init_data *data; + + data = div_clks + i; + + dt_clk = tegra_lookup_dt_id(data->clk_id, tegra_clks); + if (!dt_clk) + continue; + + clk = tegra_clk_register_divider(data->name, + data->p.parent_name, clk_base + data->offset, + data->flags, data->periph.divider.flags, + data->periph.divider.shift, + data->periph.divider.width, + data->periph.divider.frac_width, + data->periph.divider.lock); + *dt_clk = clk; + } +} + static void __init init_pllp(void __iomem *clk_base, void __iomem *pmc_base, struct tegra_clk *tegra_clks, struct tegra_clk_pll_params *pll_params) @@ -669,6 +987,51 @@ static void __init init_pllp(void __iomem *clk_base, void __iomem *pmc_base, data->lock); *dt_clk = clk; } + + dt_clk = tegra_lookup_dt_id(tegra_clk_pll_p_out_cpu, + tegra_clks); + if (dt_clk) { + /* + * Tegra210 has control on enabling/disabling PLLP branches to + * CPU, register a gate clock "pll_p_out_cpu" for this gating + * function and parent "pll_p_out4" to it, so when we are + * re-parenting CPU off from "pll_p_out4" the PLLP branching to + * CPU can be disabled automatically. + */ + clk = tegra_clk_register_divider("pll_p_out4_div", + "pll_p_out_cpu", clk_base + PLLP_OUTB, 0, 0, 24, + 8, 1, &PLLP_OUTB_lock); + + dt_clk = tegra_lookup_dt_id(tegra_clk_pll_p_out4_cpu, tegra_clks); + if (dt_clk) { + clk = tegra_clk_register_pll_out("pll_p_out4", + "pll_p_out4_div", clk_base + PLLP_OUTB, + 17, 16, CLK_IGNORE_UNUSED | + CLK_SET_RATE_PARENT, 0, + &PLLP_OUTB_lock); + *dt_clk = clk; + } + } + + dt_clk = tegra_lookup_dt_id(tegra_clk_pll_p_out_hsio, tegra_clks); + if (dt_clk) { + /* PLLP_OUT_HSIO */ + clk = clk_register_gate(NULL, "pll_p_out_hsio", "pll_p", + CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, + clk_base + PLLP_MISC1, 29, 0, NULL); + *dt_clk = clk; + } + + dt_clk = tegra_lookup_dt_id(tegra_clk_pll_p_out_xusb, tegra_clks); + if (dt_clk) { + /* PLLP_OUT_XUSB */ + clk = clk_register_gate(NULL, "pll_p_out_xusb", + "pll_p_out_hsio", CLK_SET_RATE_PARENT | + CLK_IGNORE_UNUSED, clk_base + PLLP_MISC1, 28, 0, + NULL); + clk_register_clkdev(clk, "pll_p_out_xusb", NULL); + *dt_clk = clk; + } } void __init tegra_periph_clk_init(void __iomem *clk_base, @@ -678,4 +1041,5 @@ void __init tegra_periph_clk_init(void __iomem *clk_base, init_pllp(clk_base, pmc_base, tegra_clks, pll_params); periph_clk_init(clk_base, tegra_clks); gate_clk_init(clk_base, tegra_clks); + div_clk_init(clk_base, tegra_clks); } diff --git a/drivers/clk/tegra/clk-tegra-super-gen4.c b/drivers/clk/tegra/clk-tegra-super-gen4.c index 5b1d72393..474de0f0c 100644 --- a/drivers/clk/tegra/clk-tegra-super-gen4.c +++ b/drivers/clk/tegra/clk-tegra-super-gen4.c @@ -34,9 +34,25 @@ #define CCLKLP_BURST_POLICY 0x370 #define SCLK_BURST_POLICY 0x028 #define SYSTEM_CLK_RATE 0x030 +#define SCLK_DIVIDER 0x2c static DEFINE_SPINLOCK(sysrate_lock); +enum tegra_super_gen { + gen4 = 4, + gen5, +}; + +struct tegra_super_gen_info { + enum tegra_super_gen gen; + const char **sclk_parents; + const char **cclk_g_parents; + const char **cclk_lp_parents; + int num_sclk_parents; + int num_cclk_g_parents; + int num_cclk_lp_parents; +}; + static const char *sclk_parents[] = { "clk_m", "pll_c_out1", "pll_p_out4", "pll_p", "pll_p_out2", "unused", "clk_32k", "pll_m_out1" }; @@ -51,21 +67,81 @@ static const char *cclk_lp_parents[] = { "clk_m", "pll_c", "clk_32k", "pll_m", "pll_p", "pll_p_out4", "unused", "unused", "pll_x", "pll_x_out0" }; +static const struct tegra_super_gen_info tegra_super_gen_info_gen4 = { + .gen = gen4, + .sclk_parents = sclk_parents, + .cclk_g_parents = cclk_g_parents, + .cclk_lp_parents = cclk_lp_parents, + .num_sclk_parents = ARRAY_SIZE(sclk_parents), + .num_cclk_g_parents = ARRAY_SIZE(cclk_g_parents), + .num_cclk_lp_parents = ARRAY_SIZE(cclk_lp_parents), +}; + +static const char *sclk_parents_gen5[] = { "clk_m", "pll_c_out1", "pll_c4_out3", + "pll_p", "pll_p_out2", "pll_c4_out1", + "clk_32k", "pll_c4_out2" }; + +static const char *cclk_g_parents_gen5[] = { "clk_m", "unused", "clk_32k", "unused", + "pll_p", "pll_p_out4", "unused", + "unused", "pll_x", "unused", "unused", + "unused", "unused", "unused", "unused", + "dfllCPU_out" }; + +static const char *cclk_lp_parents_gen5[] = { "clk_m", "unused", "clk_32k", "unused", + "pll_p", "pll_p_out4", "unused", + "unused", "pll_x", "unused", "unused", + "unused", "unused", "unused", "unused", + "dfllCPU_out" }; + +static const struct tegra_super_gen_info tegra_super_gen_info_gen5 = { + .gen = gen5, + .sclk_parents = sclk_parents_gen5, + .cclk_g_parents = cclk_g_parents_gen5, + .cclk_lp_parents = cclk_lp_parents_gen5, + .num_sclk_parents = ARRAY_SIZE(sclk_parents_gen5), + .num_cclk_g_parents = ARRAY_SIZE(cclk_g_parents_gen5), + .num_cclk_lp_parents = ARRAY_SIZE(cclk_lp_parents_gen5), +}; + static void __init tegra_sclk_init(void __iomem *clk_base, - struct tegra_clk *tegra_clks) + struct tegra_clk *tegra_clks, + const struct tegra_super_gen_info *gen_info) { struct clk *clk; struct clk **dt_clk; - /* SCLK */ - dt_clk = tegra_lookup_dt_id(tegra_clk_sclk, tegra_clks); + /* SCLK_MUX */ + dt_clk = tegra_lookup_dt_id(tegra_clk_sclk_mux, tegra_clks); if (dt_clk) { - clk = tegra_clk_register_super_mux("sclk", sclk_parents, - ARRAY_SIZE(sclk_parents), + clk = tegra_clk_register_super_mux("sclk_mux", + gen_info->sclk_parents, + gen_info->num_sclk_parents, CLK_SET_RATE_PARENT, clk_base + SCLK_BURST_POLICY, 0, 4, 0, 0, NULL); *dt_clk = clk; + + + /* SCLK */ + dt_clk = tegra_lookup_dt_id(tegra_clk_sclk, tegra_clks); + if (dt_clk) { + clk = clk_register_divider(NULL, "sclk", "sclk_mux", 0, + clk_base + SCLK_DIVIDER, 0, 8, + 0, &sysrate_lock); + *dt_clk = clk; + } + } else { + /* SCLK */ + dt_clk = tegra_lookup_dt_id(tegra_clk_sclk, tegra_clks); + if (dt_clk) { + clk = tegra_clk_register_super_mux("sclk", + gen_info->sclk_parents, + gen_info->num_sclk_parents, + CLK_SET_RATE_PARENT, + clk_base + SCLK_BURST_POLICY, + 0, 4, 0, 0, NULL); + *dt_clk = clk; + } } /* HCLK */ @@ -95,10 +171,11 @@ static void __init tegra_sclk_init(void __iomem *clk_base, *dt_clk = clk; } -void __init tegra_super_clk_gen4_init(void __iomem *clk_base, +static void __init tegra_super_clk_init(void __iomem *clk_base, void __iomem *pmc_base, struct tegra_clk *tegra_clks, - struct tegra_clk_pll_params *params) + struct tegra_clk_pll_params *params, + const struct tegra_super_gen_info *gen_info) { struct clk *clk; struct clk **dt_clk; @@ -106,28 +183,50 @@ void __init tegra_super_clk_gen4_init(void __iomem *clk_base, /* CCLKG */ dt_clk = tegra_lookup_dt_id(tegra_clk_cclk_g, tegra_clks); if (dt_clk) { - clk = tegra_clk_register_super_mux("cclk_g", cclk_g_parents, - ARRAY_SIZE(cclk_g_parents), + if (gen_info->gen == gen5) { + clk = tegra_clk_register_super_mux("cclk_g", + gen_info->cclk_g_parents, + gen_info->num_cclk_g_parents, + CLK_SET_RATE_PARENT, + clk_base + CCLKG_BURST_POLICY, + 0, 4, 8, 0, NULL); + } else { + clk = tegra_clk_register_super_mux("cclk_g", + gen_info->cclk_g_parents, + gen_info->num_cclk_g_parents, CLK_SET_RATE_PARENT, clk_base + CCLKG_BURST_POLICY, 0, 4, 0, 0, NULL); + } *dt_clk = clk; } /* CCLKLP */ dt_clk = tegra_lookup_dt_id(tegra_clk_cclk_lp, tegra_clks); if (dt_clk) { - clk = tegra_clk_register_super_mux("cclk_lp", cclk_lp_parents, - ARRAY_SIZE(cclk_lp_parents), + if (gen_info->gen == gen5) { + clk = tegra_clk_register_super_mux("cclk_lp", + gen_info->cclk_lp_parents, + gen_info->num_cclk_lp_parents, + CLK_SET_RATE_PARENT, + clk_base + CCLKLP_BURST_POLICY, + 0, 4, 8, 0, NULL); + } else { + clk = tegra_clk_register_super_mux("cclk_lp", + gen_info->cclk_lp_parents, + gen_info->num_cclk_lp_parents, CLK_SET_RATE_PARENT, clk_base + CCLKLP_BURST_POLICY, TEGRA_DIVIDER_2, 4, 8, 9, NULL); + } *dt_clk = clk; } - tegra_sclk_init(clk_base, tegra_clks); + tegra_sclk_init(clk_base, tegra_clks, gen_info); -#if defined(CONFIG_ARCH_TEGRA_114_SOC) || defined(CONFIG_ARCH_TEGRA_124_SOC) +#if defined(CONFIG_ARCH_TEGRA_114_SOC) || \ + defined(CONFIG_ARCH_TEGRA_124_SOC) || \ + defined(CONFIG_ARCH_TEGRA_210_SOC) /* PLLX */ dt_clk = tegra_lookup_dt_id(tegra_clk_pll_x, tegra_clks); if (!dt_clk) @@ -148,3 +247,20 @@ void __init tegra_super_clk_gen4_init(void __iomem *clk_base, #endif } +void __init tegra_super_clk_gen4_init(void __iomem *clk_base, + void __iomem *pmc_base, + struct tegra_clk *tegra_clks, + struct tegra_clk_pll_params *params) +{ + tegra_super_clk_init(clk_base, pmc_base, tegra_clks, params, + &tegra_super_gen_info_gen4); +} + +void __init tegra_super_clk_gen5_init(void __iomem *clk_base, + void __iomem *pmc_base, + struct tegra_clk *tegra_clks, + struct tegra_clk_pll_params *params) +{ + tegra_super_clk_init(clk_base, pmc_base, tegra_clks, params, + &tegra_super_gen_info_gen5); +} diff --git a/drivers/clk/tegra/clk-tegra114.c b/drivers/clk/tegra/clk-tegra114.c index b7d03e9ad..4a24aa4bb 100644 --- a/drivers/clk/tegra/clk-tegra114.c +++ b/drivers/clk/tegra/clk-tegra114.c @@ -182,40 +182,40 @@ static struct div_nmp pllxc_nmp = { .divp_width = 4, }; -static struct pdiv_map pllxc_p[] = { - { .pdiv = 1, .hw_val = 0 }, - { .pdiv = 2, .hw_val = 1 }, - { .pdiv = 3, .hw_val = 2 }, - { .pdiv = 4, .hw_val = 3 }, - { .pdiv = 5, .hw_val = 4 }, - { .pdiv = 6, .hw_val = 5 }, - { .pdiv = 8, .hw_val = 6 }, - { .pdiv = 10, .hw_val = 7 }, - { .pdiv = 12, .hw_val = 8 }, - { .pdiv = 16, .hw_val = 9 }, +static const struct pdiv_map pllxc_p[] = { + { .pdiv = 1, .hw_val = 0 }, + { .pdiv = 2, .hw_val = 1 }, + { .pdiv = 3, .hw_val = 2 }, + { .pdiv = 4, .hw_val = 3 }, + { .pdiv = 5, .hw_val = 4 }, + { .pdiv = 6, .hw_val = 5 }, + { .pdiv = 8, .hw_val = 6 }, + { .pdiv = 10, .hw_val = 7 }, + { .pdiv = 12, .hw_val = 8 }, + { .pdiv = 16, .hw_val = 9 }, { .pdiv = 12, .hw_val = 10 }, { .pdiv = 16, .hw_val = 11 }, { .pdiv = 20, .hw_val = 12 }, { .pdiv = 24, .hw_val = 13 }, { .pdiv = 32, .hw_val = 14 }, - { .pdiv = 0, .hw_val = 0 }, + { .pdiv = 0, .hw_val = 0 }, }; static struct tegra_clk_pll_freq_table pll_c_freq_table[] = { - { 12000000, 624000000, 104, 0, 2}, - { 12000000, 600000000, 100, 0, 2}, - { 13000000, 600000000, 92, 0, 2}, /* actual: 598.0 MHz */ - { 16800000, 600000000, 71, 0, 2}, /* actual: 596.4 MHz */ - { 19200000, 600000000, 62, 0, 2}, /* actual: 595.2 MHz */ - { 26000000, 600000000, 92, 1, 2}, /* actual: 598.0 MHz */ - { 0, 0, 0, 0, 0, 0 }, + { 12000000, 624000000, 104, 1, 2, 0 }, + { 12000000, 600000000, 100, 1, 2, 0 }, + { 13000000, 600000000, 92, 1, 2, 0 }, /* actual: 598.0 MHz */ + { 16800000, 600000000, 71, 1, 2, 0 }, /* actual: 596.4 MHz */ + { 19200000, 600000000, 62, 1, 2, 0 }, /* actual: 595.2 MHz */ + { 26000000, 600000000, 92, 2, 2, 0 }, /* actual: 598.0 MHz */ + { 0, 0, 0, 0, 0, 0 }, }; static struct tegra_clk_pll_params pll_c_params = { .input_min = 12000000, .input_max = 800000000, .cf_min = 12000000, - .cf_max = 19200000, /* s/w policy, h/w capability 50 MHz */ + .cf_max = 19200000, /* s/w policy, h/w capability 50 MHz */ .vco_min = 600000000, .vco_max = 1400000000, .base_reg = PLLC_BASE, @@ -232,7 +232,7 @@ static struct tegra_clk_pll_params pll_c_params = { .pdiv_tohw = pllxc_p, .div_nmp = &pllxc_nmp, .freq_table = pll_c_freq_table, - .flags = TEGRA_PLL_USE_LOCK, + .flags = TEGRA_PLL_USE_LOCK | TEGRA_PLL_HAS_LOCK_ENABLE, }; static struct div_nmp pllcx_nmp = { @@ -244,22 +244,22 @@ static struct div_nmp pllcx_nmp = { .divp_width = 3, }; -static struct pdiv_map pllc_p[] = { - { .pdiv = 1, .hw_val = 0 }, - { .pdiv = 2, .hw_val = 1 }, - { .pdiv = 4, .hw_val = 3 }, - { .pdiv = 8, .hw_val = 5 }, +static const struct pdiv_map pllc_p[] = { + { .pdiv = 1, .hw_val = 0 }, + { .pdiv = 2, .hw_val = 1 }, + { .pdiv = 4, .hw_val = 3 }, + { .pdiv = 8, .hw_val = 5 }, { .pdiv = 16, .hw_val = 7 }, - { .pdiv = 0, .hw_val = 0 }, + { .pdiv = 0, .hw_val = 0 }, }; static struct tegra_clk_pll_freq_table pll_cx_freq_table[] = { - {12000000, 600000000, 100, 0, 2}, - {13000000, 600000000, 92, 0, 2}, /* actual: 598.0 MHz */ - {16800000, 600000000, 71, 0, 2}, /* actual: 596.4 MHz */ - {19200000, 600000000, 62, 0, 2}, /* actual: 595.2 MHz */ - {26000000, 600000000, 92, 1, 2}, /* actual: 598.0 MHz */ - {0, 0, 0, 0, 0, 0}, + { 12000000, 600000000, 100, 1, 2, 0 }, + { 13000000, 600000000, 92, 1, 2, 0 }, /* actual: 598.0 MHz */ + { 16800000, 600000000, 71, 1, 2, 0 }, /* actual: 596.4 MHz */ + { 19200000, 600000000, 62, 1, 2, 0 }, /* actual: 595.2 MHz */ + { 26000000, 600000000, 92, 2, 2, 0 }, /* actual: 598.0 MHz */ + { 0, 0, 0, 0, 0, 0 }, }; static struct tegra_clk_pll_params pll_c2_params = { @@ -318,26 +318,26 @@ static struct div_nmp pllm_nmp = { .override_divp_shift = 27, }; -static struct pdiv_map pllm_p[] = { +static const struct pdiv_map pllm_p[] = { { .pdiv = 1, .hw_val = 0 }, { .pdiv = 2, .hw_val = 1 }, { .pdiv = 0, .hw_val = 0 }, }; static struct tegra_clk_pll_freq_table pll_m_freq_table[] = { - {12000000, 800000000, 66, 0, 1}, /* actual: 792.0 MHz */ - {13000000, 800000000, 61, 0, 1}, /* actual: 793.0 MHz */ - {16800000, 800000000, 47, 0, 1}, /* actual: 789.6 MHz */ - {19200000, 800000000, 41, 0, 1}, /* actual: 787.2 MHz */ - {26000000, 800000000, 61, 1, 1}, /* actual: 793.0 MHz */ - {0, 0, 0, 0, 0, 0}, + { 12000000, 800000000, 66, 1, 1, 0 }, /* actual: 792.0 MHz */ + { 13000000, 800000000, 61, 1, 1, 0 }, /* actual: 793.0 MHz */ + { 16800000, 800000000, 47, 1, 1, 0 }, /* actual: 789.6 MHz */ + { 19200000, 800000000, 41, 1, 1, 0 }, /* actual: 787.2 MHz */ + { 26000000, 800000000, 61, 2, 1, 0 }, /* actual: 793.0 MHz */ + { 0, 0, 0, 0, 0, 0 }, }; static struct tegra_clk_pll_params pll_m_params = { .input_min = 12000000, .input_max = 500000000, .cf_min = 12000000, - .cf_max = 19200000, /* s/w policy, h/w capability 50 MHz */ + .cf_max = 19200000, /* s/w policy, h/w capability 50 MHz */ .vco_min = 400000000, .vco_max = 1066000000, .base_reg = PLLM_BASE, @@ -351,7 +351,8 @@ static struct tegra_clk_pll_params pll_m_params = { .pmc_divnm_reg = PMC_PLLM_WB0_OVERRIDE, .pmc_divp_reg = PMC_PLLM_WB0_OVERRIDE_2, .freq_table = pll_m_freq_table, - .flags = TEGRA_PLL_USE_LOCK, + .flags = TEGRA_PLL_USE_LOCK | TEGRA_PLL_HAS_LOCK_ENABLE | + TEGRA_PLL_FIXED, }; static struct div_nmp pllp_nmp = { @@ -364,12 +365,12 @@ static struct div_nmp pllp_nmp = { }; static struct tegra_clk_pll_freq_table pll_p_freq_table[] = { - {12000000, 216000000, 432, 12, 1, 8}, - {13000000, 216000000, 432, 13, 1, 8}, - {16800000, 216000000, 360, 14, 1, 8}, - {19200000, 216000000, 360, 16, 1, 8}, - {26000000, 216000000, 432, 26, 1, 8}, - {0, 0, 0, 0, 0, 0}, + { 12000000, 216000000, 432, 12, 2, 8 }, + { 13000000, 216000000, 432, 13, 2, 8 }, + { 16800000, 216000000, 360, 14, 2, 8 }, + { 19200000, 216000000, 360, 16, 2, 8 }, + { 26000000, 216000000, 432, 26, 2, 8 }, + { 0, 0, 0, 0, 0, 0 }, }; static struct tegra_clk_pll_params pll_p_params = { @@ -386,19 +387,19 @@ static struct tegra_clk_pll_params pll_p_params = { .lock_delay = 300, .div_nmp = &pllp_nmp, .freq_table = pll_p_freq_table, - .flags = TEGRA_PLL_FIXED | TEGRA_PLL_USE_LOCK, + .flags = TEGRA_PLL_FIXED | TEGRA_PLL_USE_LOCK | + TEGRA_PLL_HAS_LOCK_ENABLE, .fixed_rate = 408000000, }; static struct tegra_clk_pll_freq_table pll_a_freq_table[] = { - {9600000, 282240000, 147, 5, 0, 4}, - {9600000, 368640000, 192, 5, 0, 4}, - {9600000, 240000000, 200, 8, 0, 8}, - - {28800000, 282240000, 245, 25, 0, 8}, - {28800000, 368640000, 320, 25, 0, 8}, - {28800000, 240000000, 200, 24, 0, 8}, - {0, 0, 0, 0, 0, 0}, + { 9600000, 282240000, 147, 5, 1, 4 }, + { 9600000, 368640000, 192, 5, 1, 4 }, + { 9600000, 240000000, 200, 8, 1, 8 }, + { 28800000, 282240000, 245, 25, 1, 8 }, + { 28800000, 368640000, 320, 25, 1, 8 }, + { 28800000, 240000000, 200, 24, 1, 8 }, + { 0, 0, 0, 0, 0, 0 }, }; @@ -416,28 +417,26 @@ static struct tegra_clk_pll_params pll_a_params = { .lock_delay = 300, .div_nmp = &pllp_nmp, .freq_table = pll_a_freq_table, - .flags = TEGRA_PLL_HAS_CPCON | TEGRA_PLL_USE_LOCK, + .flags = TEGRA_PLL_HAS_CPCON | TEGRA_PLL_USE_LOCK | + TEGRA_PLL_HAS_LOCK_ENABLE, }; static struct tegra_clk_pll_freq_table pll_d_freq_table[] = { - {12000000, 216000000, 864, 12, 2, 12}, - {13000000, 216000000, 864, 13, 2, 12}, - {16800000, 216000000, 720, 14, 2, 12}, - {19200000, 216000000, 720, 16, 2, 12}, - {26000000, 216000000, 864, 26, 2, 12}, - - {12000000, 594000000, 594, 12, 0, 12}, - {13000000, 594000000, 594, 13, 0, 12}, - {16800000, 594000000, 495, 14, 0, 12}, - {19200000, 594000000, 495, 16, 0, 12}, - {26000000, 594000000, 594, 26, 0, 12}, - - {12000000, 1000000000, 1000, 12, 0, 12}, - {13000000, 1000000000, 1000, 13, 0, 12}, - {19200000, 1000000000, 625, 12, 0, 12}, - {26000000, 1000000000, 1000, 26, 0, 12}, - - {0, 0, 0, 0, 0, 0}, + { 12000000, 216000000, 864, 12, 4, 12 }, + { 13000000, 216000000, 864, 13, 4, 12 }, + { 16800000, 216000000, 720, 14, 4, 12 }, + { 19200000, 216000000, 720, 16, 4, 12 }, + { 26000000, 216000000, 864, 26, 4, 12 }, + { 12000000, 594000000, 594, 12, 1, 12 }, + { 13000000, 594000000, 594, 13, 1, 12 }, + { 16800000, 594000000, 495, 14, 1, 12 }, + { 19200000, 594000000, 495, 16, 1, 12 }, + { 26000000, 594000000, 594, 26, 1, 12 }, + { 12000000, 1000000000, 1000, 12, 1, 12 }, + { 13000000, 1000000000, 1000, 13, 1, 12 }, + { 19200000, 1000000000, 625, 12, 1, 12 }, + { 26000000, 1000000000, 1000, 26, 1, 12 }, + { 0, 0, 0, 0, 0, 0 }, }; static struct tegra_clk_pll_params pll_d_params = { @@ -455,7 +454,7 @@ static struct tegra_clk_pll_params pll_d_params = { .div_nmp = &pllp_nmp, .freq_table = pll_d_freq_table, .flags = TEGRA_PLL_HAS_CPCON | TEGRA_PLL_SET_LFCON | - TEGRA_PLL_USE_LOCK, + TEGRA_PLL_USE_LOCK | TEGRA_PLL_HAS_LOCK_ENABLE, }; static struct tegra_clk_pll_params pll_d2_params = { @@ -473,10 +472,10 @@ static struct tegra_clk_pll_params pll_d2_params = { .div_nmp = &pllp_nmp, .freq_table = pll_d_freq_table, .flags = TEGRA_PLL_HAS_CPCON | TEGRA_PLL_SET_LFCON | - TEGRA_PLL_USE_LOCK, + TEGRA_PLL_USE_LOCK | TEGRA_PLL_HAS_LOCK_ENABLE, }; -static struct pdiv_map pllu_p[] = { +static const struct pdiv_map pllu_p[] = { { .pdiv = 1, .hw_val = 1 }, { .pdiv = 2, .hw_val = 0 }, { .pdiv = 0, .hw_val = 0 }, @@ -492,12 +491,12 @@ static struct div_nmp pllu_nmp = { }; static struct tegra_clk_pll_freq_table pll_u_freq_table[] = { - {12000000, 480000000, 960, 12, 0, 12}, - {13000000, 480000000, 960, 13, 0, 12}, - {16800000, 480000000, 400, 7, 0, 5}, - {19200000, 480000000, 200, 4, 0, 3}, - {26000000, 480000000, 960, 26, 0, 12}, - {0, 0, 0, 0, 0, 0}, + { 12000000, 480000000, 960, 12, 2, 12 }, + { 13000000, 480000000, 960, 13, 2, 12 }, + { 16800000, 480000000, 400, 7, 2, 5 }, + { 19200000, 480000000, 200, 4, 2, 3 }, + { 26000000, 480000000, 960, 26, 2, 12 }, + { 0, 0, 0, 0, 0, 0 }, }; static struct tegra_clk_pll_params pll_u_params = { @@ -516,25 +515,24 @@ static struct tegra_clk_pll_params pll_u_params = { .div_nmp = &pllu_nmp, .freq_table = pll_u_freq_table, .flags = TEGRA_PLLU | TEGRA_PLL_HAS_CPCON | TEGRA_PLL_SET_LFCON | - TEGRA_PLL_USE_LOCK, + TEGRA_PLL_USE_LOCK | TEGRA_PLL_HAS_LOCK_ENABLE, }; static struct tegra_clk_pll_freq_table pll_x_freq_table[] = { /* 1 GHz */ - {12000000, 1000000000, 83, 0, 1}, /* actual: 996.0 MHz */ - {13000000, 1000000000, 76, 0, 1}, /* actual: 988.0 MHz */ - {16800000, 1000000000, 59, 0, 1}, /* actual: 991.2 MHz */ - {19200000, 1000000000, 52, 0, 1}, /* actual: 998.4 MHz */ - {26000000, 1000000000, 76, 1, 1}, /* actual: 988.0 MHz */ - - {0, 0, 0, 0, 0, 0}, + { 12000000, 1000000000, 83, 1, 1, 0 }, /* actual: 996.0 MHz */ + { 13000000, 1000000000, 76, 1, 1, 0 }, /* actual: 988.0 MHz */ + { 16800000, 1000000000, 59, 1, 1, 0 }, /* actual: 991.2 MHz */ + { 19200000, 1000000000, 52, 1, 1, 0 }, /* actual: 998.4 MHz */ + { 26000000, 1000000000, 76, 2, 1, 0 }, /* actual: 988.0 MHz */ + { 0, 0, 0, 0, 0, 0 }, }; static struct tegra_clk_pll_params pll_x_params = { .input_min = 12000000, .input_max = 800000000, .cf_min = 12000000, - .cf_max = 19200000, /* s/w policy, h/w capability 50 MHz */ + .cf_max = 19200000, /* s/w policy, h/w capability 50 MHz */ .vco_min = 700000000, .vco_max = 2400000000U, .base_reg = PLLX_BASE, @@ -551,15 +549,34 @@ static struct tegra_clk_pll_params pll_x_params = { .pdiv_tohw = pllxc_p, .div_nmp = &pllxc_nmp, .freq_table = pll_x_freq_table, - .flags = TEGRA_PLL_USE_LOCK, + .flags = TEGRA_PLL_USE_LOCK | TEGRA_PLL_HAS_LOCK_ENABLE, }; static struct tegra_clk_pll_freq_table pll_e_freq_table[] = { /* PLLE special case: use cpcon field to store cml divider value */ - {336000000, 100000000, 100, 21, 16, 11}, - {312000000, 100000000, 200, 26, 24, 13}, - {12000000, 100000000, 200, 1, 24, 13}, - {0, 0, 0, 0, 0, 0}, + { 336000000, 100000000, 100, 21, 16, 11 }, + { 312000000, 100000000, 200, 26, 24, 13 }, + { 12000000, 100000000, 200, 1, 24, 13 }, + { 0, 0, 0, 0, 0, 0 }, +}; + +static const struct pdiv_map plle_p[] = { + { .pdiv = 1, .hw_val = 0 }, + { .pdiv = 2, .hw_val = 1 }, + { .pdiv = 3, .hw_val = 2 }, + { .pdiv = 4, .hw_val = 3 }, + { .pdiv = 5, .hw_val = 4 }, + { .pdiv = 6, .hw_val = 5 }, + { .pdiv = 8, .hw_val = 6 }, + { .pdiv = 10, .hw_val = 7 }, + { .pdiv = 12, .hw_val = 8 }, + { .pdiv = 16, .hw_val = 9 }, + { .pdiv = 12, .hw_val = 10 }, + { .pdiv = 16, .hw_val = 11 }, + { .pdiv = 20, .hw_val = 12 }, + { .pdiv = 24, .hw_val = 13 }, + { .pdiv = 32, .hw_val = 14 }, + { .pdiv = 0, .hw_val = 0 } }; static struct div_nmp plle_nmp = { @@ -584,9 +601,10 @@ static struct tegra_clk_pll_params pll_e_params = { .lock_mask = PLLE_MISC_LOCK, .lock_enable_bit_idx = PLLE_MISC_LOCK_ENABLE, .lock_delay = 300, + .pdiv_tohw = plle_p, .div_nmp = &plle_nmp, .freq_table = pll_e_freq_table, - .flags = TEGRA_PLL_FIXED, + .flags = TEGRA_PLL_FIXED | TEGRA_PLL_HAS_LOCK_ENABLE, .fixed_rate = 100000000, }; @@ -614,18 +632,19 @@ static struct tegra_clk_pll_params pll_re_vco_params = { .iddq_reg = PLLRE_MISC, .iddq_bit_idx = PLLRE_IDDQ_BIT, .div_nmp = &pllre_nmp, - .flags = TEGRA_PLL_USE_LOCK, + .flags = TEGRA_PLL_USE_LOCK | TEGRA_PLL_HAS_LOCK_ENABLE | + TEGRA_PLL_LOCK_MISC, }; /* possible OSC frequencies in Hz */ static unsigned long tegra114_input_freq[] = { - [0] = 13000000, - [1] = 16800000, - [4] = 19200000, - [5] = 38400000, - [8] = 12000000, - [9] = 48000000, - [12] = 260000000, + [ 0] = 13000000, + [ 1] = 16800000, + [ 4] = 19200000, + [ 5] = 38400000, + [ 8] = 12000000, + [ 9] = 48000000, + [12] = 26000000, }; #define MASK(x) (BIT(x) - 1) @@ -644,21 +663,27 @@ struct utmi_clk_param { }; static const struct utmi_clk_param utmi_parameters[] = { - {.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 = 0x04, - .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}, + { + .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 = 0x04, + .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 + }, }; /* peripheral mux definitions */ @@ -965,8 +990,8 @@ static void __init tegra114_fixed_clk_init(void __iomem *clk_base) static __init void tegra114_utmi_param_configure(void __iomem *clk_base) { + unsigned int i; u32 reg; - int i; for (i = 0; i < ARRAY_SIZE(utmi_parameters); i++) { if (osc_freq == utmi_parameters[i].osc_frequency) @@ -1173,7 +1198,7 @@ static __init void tegra114_periph_clk_init(void __iomem *clk_base, { struct clk *clk; struct tegra_periph_init_data *data; - int i; + unsigned int i; /* xusb_ss_div2 */ clk = clk_register_fixed_factor(NULL, "xusb_ss_div2", "xusb_ss_src", 0, @@ -1278,7 +1303,7 @@ static struct tegra_cpu_car_ops tegra114_cpu_car_ops = { static const struct of_device_id pmc_match[] __initconst = { { .compatible = "nvidia,tegra114-pmc" }, - {}, + { }, }; /* @@ -1286,37 +1311,37 @@ static const struct of_device_id pmc_match[] __initconst = { * breaks */ static struct tegra_clk_init_table init_table[] __initdata = { - {TEGRA114_CLK_UARTA, TEGRA114_CLK_PLL_P, 408000000, 0}, - {TEGRA114_CLK_UARTB, TEGRA114_CLK_PLL_P, 408000000, 0}, - {TEGRA114_CLK_UARTC, TEGRA114_CLK_PLL_P, 408000000, 0}, - {TEGRA114_CLK_UARTD, TEGRA114_CLK_PLL_P, 408000000, 0}, - {TEGRA114_CLK_PLL_A, TEGRA114_CLK_CLK_MAX, 564480000, 1}, - {TEGRA114_CLK_PLL_A_OUT0, TEGRA114_CLK_CLK_MAX, 11289600, 1}, - {TEGRA114_CLK_EXTERN1, TEGRA114_CLK_PLL_A_OUT0, 0, 1}, - {TEGRA114_CLK_CLK_OUT_1_MUX, TEGRA114_CLK_EXTERN1, 0, 1}, - {TEGRA114_CLK_CLK_OUT_1, TEGRA114_CLK_CLK_MAX, 0, 1}, - {TEGRA114_CLK_I2S0, TEGRA114_CLK_PLL_A_OUT0, 11289600, 0}, - {TEGRA114_CLK_I2S1, TEGRA114_CLK_PLL_A_OUT0, 11289600, 0}, - {TEGRA114_CLK_I2S2, TEGRA114_CLK_PLL_A_OUT0, 11289600, 0}, - {TEGRA114_CLK_I2S3, TEGRA114_CLK_PLL_A_OUT0, 11289600, 0}, - {TEGRA114_CLK_I2S4, TEGRA114_CLK_PLL_A_OUT0, 11289600, 0}, - {TEGRA114_CLK_HOST1X, TEGRA114_CLK_PLL_P, 136000000, 0}, - {TEGRA114_CLK_DFLL_SOC, TEGRA114_CLK_PLL_P, 51000000, 1}, - {TEGRA114_CLK_DFLL_REF, TEGRA114_CLK_PLL_P, 51000000, 1}, - {TEGRA114_CLK_DISP1, TEGRA114_CLK_PLL_P, 0, 0}, - {TEGRA114_CLK_DISP2, TEGRA114_CLK_PLL_P, 0, 0}, - {TEGRA114_CLK_GR2D, TEGRA114_CLK_PLL_C2, 300000000, 0}, - {TEGRA114_CLK_GR3D, TEGRA114_CLK_PLL_C2, 300000000, 0}, - {TEGRA114_CLK_DSIALP, TEGRA114_CLK_PLL_P, 68000000, 0}, - {TEGRA114_CLK_DSIBLP, TEGRA114_CLK_PLL_P, 68000000, 0}, - {TEGRA114_CLK_PLL_RE_VCO, TEGRA114_CLK_CLK_MAX, 612000000, 0}, - {TEGRA114_CLK_XUSB_SS_SRC, TEGRA114_CLK_PLL_RE_OUT, 122400000, 0}, - {TEGRA114_CLK_XUSB_FS_SRC, TEGRA114_CLK_PLL_U_48M, 48000000, 0}, - {TEGRA114_CLK_XUSB_HS_SRC, TEGRA114_CLK_XUSB_SS_DIV2, 61200000, 0}, - {TEGRA114_CLK_XUSB_FALCON_SRC, TEGRA114_CLK_PLL_P, 204000000, 0}, - {TEGRA114_CLK_XUSB_HOST_SRC, TEGRA114_CLK_PLL_P, 102000000, 0}, - /* This MUST be the last entry. */ - {TEGRA114_CLK_CLK_MAX, TEGRA114_CLK_CLK_MAX, 0, 0}, + { TEGRA114_CLK_UARTA, TEGRA114_CLK_PLL_P, 408000000, 0 }, + { TEGRA114_CLK_UARTB, TEGRA114_CLK_PLL_P, 408000000, 0 }, + { TEGRA114_CLK_UARTC, TEGRA114_CLK_PLL_P, 408000000, 0 }, + { TEGRA114_CLK_UARTD, TEGRA114_CLK_PLL_P, 408000000, 0 }, + { TEGRA114_CLK_PLL_A, TEGRA114_CLK_CLK_MAX, 564480000, 1 }, + { TEGRA114_CLK_PLL_A_OUT0, TEGRA114_CLK_CLK_MAX, 11289600, 1 }, + { TEGRA114_CLK_EXTERN1, TEGRA114_CLK_PLL_A_OUT0, 0, 1 }, + { TEGRA114_CLK_CLK_OUT_1_MUX, TEGRA114_CLK_EXTERN1, 0, 1 }, + { TEGRA114_CLK_CLK_OUT_1, TEGRA114_CLK_CLK_MAX, 0, 1 }, + { TEGRA114_CLK_I2S0, TEGRA114_CLK_PLL_A_OUT0, 11289600, 0 }, + { TEGRA114_CLK_I2S1, TEGRA114_CLK_PLL_A_OUT0, 11289600, 0 }, + { TEGRA114_CLK_I2S2, TEGRA114_CLK_PLL_A_OUT0, 11289600, 0 }, + { TEGRA114_CLK_I2S3, TEGRA114_CLK_PLL_A_OUT0, 11289600, 0 }, + { TEGRA114_CLK_I2S4, TEGRA114_CLK_PLL_A_OUT0, 11289600, 0 }, + { TEGRA114_CLK_HOST1X, TEGRA114_CLK_PLL_P, 136000000, 0 }, + { TEGRA114_CLK_DFLL_SOC, TEGRA114_CLK_PLL_P, 51000000, 1 }, + { TEGRA114_CLK_DFLL_REF, TEGRA114_CLK_PLL_P, 51000000, 1 }, + { TEGRA114_CLK_DISP1, TEGRA114_CLK_PLL_P, 0, 0 }, + { TEGRA114_CLK_DISP2, TEGRA114_CLK_PLL_P, 0, 0 }, + { TEGRA114_CLK_GR2D, TEGRA114_CLK_PLL_C2, 300000000, 0 }, + { TEGRA114_CLK_GR3D, TEGRA114_CLK_PLL_C2, 300000000, 0 }, + { TEGRA114_CLK_DSIALP, TEGRA114_CLK_PLL_P, 68000000, 0 }, + { TEGRA114_CLK_DSIBLP, TEGRA114_CLK_PLL_P, 68000000, 0 }, + { TEGRA114_CLK_PLL_RE_VCO, TEGRA114_CLK_CLK_MAX, 612000000, 0 }, + { TEGRA114_CLK_XUSB_SS_SRC, TEGRA114_CLK_PLL_RE_OUT, 122400000, 0 }, + { TEGRA114_CLK_XUSB_FS_SRC, TEGRA114_CLK_PLL_U_48M, 48000000, 0 }, + { TEGRA114_CLK_XUSB_HS_SRC, TEGRA114_CLK_XUSB_SS_DIV2, 61200000, 0 }, + { TEGRA114_CLK_XUSB_FALCON_SRC, TEGRA114_CLK_PLL_P, 204000000, 0 }, + { TEGRA114_CLK_XUSB_HOST_SRC, TEGRA114_CLK_PLL_P, 102000000, 0 }, + /* must be the last entry */ + { TEGRA114_CLK_CLK_MAX, TEGRA114_CLK_CLK_MAX, 0, 0 }, }; static void __init tegra114_clock_apply_init_table(void) diff --git a/drivers/clk/tegra/clk-tegra124.c b/drivers/clk/tegra/clk-tegra124.c index 87975f7ad..162725829 100644 --- a/drivers/clk/tegra/clk-tegra124.c +++ b/drivers/clk/tegra/clk-tegra124.c @@ -150,13 +150,13 @@ static DEFINE_SPINLOCK(emc_lock); /* possible OSC frequencies in Hz */ static unsigned long tegra124_input_freq[] = { - [0] = 13000000, - [1] = 16800000, - [4] = 19200000, - [5] = 38400000, - [8] = 12000000, - [9] = 48000000, - [12] = 260000000, + [ 0] = 13000000, + [ 1] = 16800000, + [ 4] = 19200000, + [ 5] = 38400000, + [ 8] = 12000000, + [ 9] = 48000000, + [12] = 26000000, }; static struct div_nmp pllxc_nmp = { @@ -168,33 +168,33 @@ static struct div_nmp pllxc_nmp = { .divp_width = 4, }; -static struct pdiv_map pllxc_p[] = { - { .pdiv = 1, .hw_val = 0 }, - { .pdiv = 2, .hw_val = 1 }, - { .pdiv = 3, .hw_val = 2 }, - { .pdiv = 4, .hw_val = 3 }, - { .pdiv = 5, .hw_val = 4 }, - { .pdiv = 6, .hw_val = 5 }, - { .pdiv = 8, .hw_val = 6 }, - { .pdiv = 10, .hw_val = 7 }, - { .pdiv = 12, .hw_val = 8 }, - { .pdiv = 16, .hw_val = 9 }, +static const struct pdiv_map pllxc_p[] = { + { .pdiv = 1, .hw_val = 0 }, + { .pdiv = 2, .hw_val = 1 }, + { .pdiv = 3, .hw_val = 2 }, + { .pdiv = 4, .hw_val = 3 }, + { .pdiv = 5, .hw_val = 4 }, + { .pdiv = 6, .hw_val = 5 }, + { .pdiv = 8, .hw_val = 6 }, + { .pdiv = 10, .hw_val = 7 }, + { .pdiv = 12, .hw_val = 8 }, + { .pdiv = 16, .hw_val = 9 }, { .pdiv = 12, .hw_val = 10 }, { .pdiv = 16, .hw_val = 11 }, { .pdiv = 20, .hw_val = 12 }, { .pdiv = 24, .hw_val = 13 }, { .pdiv = 32, .hw_val = 14 }, - { .pdiv = 0, .hw_val = 0 }, + { .pdiv = 0, .hw_val = 0 }, }; static struct tegra_clk_pll_freq_table pll_x_freq_table[] = { /* 1 GHz */ - {12000000, 1000000000, 83, 0, 1}, /* actual: 996.0 MHz */ - {13000000, 1000000000, 76, 0, 1}, /* actual: 988.0 MHz */ - {16800000, 1000000000, 59, 0, 1}, /* actual: 991.2 MHz */ - {19200000, 1000000000, 52, 0, 1}, /* actual: 998.4 MHz */ - {26000000, 1000000000, 76, 1, 1}, /* actual: 988.0 MHz */ - {0, 0, 0, 0, 0, 0}, + { 12000000, 1000000000, 83, 1, 1, 0 }, /* actual: 996.0 MHz */ + { 13000000, 1000000000, 76, 1, 1, 0 }, /* actual: 988.0 MHz */ + { 16800000, 1000000000, 59, 1, 1, 0 }, /* actual: 991.2 MHz */ + { 19200000, 1000000000, 52, 1, 1, 0 }, /* actual: 998.4 MHz */ + { 26000000, 1000000000, 76, 2, 1, 0 }, /* actual: 988.0 MHz */ + { 0, 0, 0, 0, 0, 0 }, }; static struct tegra_clk_pll_params pll_x_params = { @@ -218,24 +218,24 @@ static struct tegra_clk_pll_params pll_x_params = { .pdiv_tohw = pllxc_p, .div_nmp = &pllxc_nmp, .freq_table = pll_x_freq_table, - .flags = TEGRA_PLL_USE_LOCK, + .flags = TEGRA_PLL_USE_LOCK | TEGRA_PLL_HAS_LOCK_ENABLE, }; static struct tegra_clk_pll_freq_table pll_c_freq_table[] = { - { 12000000, 624000000, 104, 1, 2}, - { 12000000, 600000000, 100, 1, 2}, - { 13000000, 600000000, 92, 1, 2}, /* actual: 598.0 MHz */ - { 16800000, 600000000, 71, 1, 2}, /* actual: 596.4 MHz */ - { 19200000, 600000000, 62, 1, 2}, /* actual: 595.2 MHz */ - { 26000000, 600000000, 92, 2, 2}, /* actual: 598.0 MHz */ - { 0, 0, 0, 0, 0, 0 }, + { 12000000, 624000000, 104, 1, 2, 0 }, + { 12000000, 600000000, 100, 1, 2, 0 }, + { 13000000, 600000000, 92, 1, 2, 0 }, /* actual: 598.0 MHz */ + { 16800000, 600000000, 71, 1, 2, 0 }, /* actual: 596.4 MHz */ + { 19200000, 600000000, 62, 1, 2, 0 }, /* actual: 595.2 MHz */ + { 26000000, 600000000, 92, 2, 2, 0 }, /* actual: 598.0 MHz */ + { 0, 0, 0, 0, 0, 0 }, }; static struct tegra_clk_pll_params pll_c_params = { .input_min = 12000000, .input_max = 800000000, .cf_min = 12000000, - .cf_max = 19200000, /* s/w policy, h/w capability 50 MHz */ + .cf_max = 19200000, /* s/w policy, h/w capability 50 MHz */ .vco_min = 600000000, .vco_max = 1400000000, .base_reg = PLLC_BASE, @@ -252,7 +252,7 @@ static struct tegra_clk_pll_params pll_c_params = { .pdiv_tohw = pllxc_p, .div_nmp = &pllxc_nmp, .freq_table = pll_c_freq_table, - .flags = TEGRA_PLL_USE_LOCK, + .flags = TEGRA_PLL_USE_LOCK | TEGRA_PLL_HAS_LOCK_ENABLE, }; static struct div_nmp pllcx_nmp = { @@ -264,25 +264,25 @@ static struct div_nmp pllcx_nmp = { .divp_width = 3, }; -static struct pdiv_map pllc_p[] = { - { .pdiv = 1, .hw_val = 0 }, - { .pdiv = 2, .hw_val = 1 }, - { .pdiv = 3, .hw_val = 2 }, - { .pdiv = 4, .hw_val = 3 }, - { .pdiv = 6, .hw_val = 4 }, - { .pdiv = 8, .hw_val = 5 }, +static const struct pdiv_map pllc_p[] = { + { .pdiv = 1, .hw_val = 0 }, + { .pdiv = 2, .hw_val = 1 }, + { .pdiv = 3, .hw_val = 2 }, + { .pdiv = 4, .hw_val = 3 }, + { .pdiv = 6, .hw_val = 4 }, + { .pdiv = 8, .hw_val = 5 }, { .pdiv = 12, .hw_val = 6 }, { .pdiv = 16, .hw_val = 7 }, - { .pdiv = 0, .hw_val = 0 }, + { .pdiv = 0, .hw_val = 0 }, }; static struct tegra_clk_pll_freq_table pll_cx_freq_table[] = { - {12000000, 600000000, 100, 1, 2}, - {13000000, 600000000, 92, 1, 2}, /* actual: 598.0 MHz */ - {16800000, 600000000, 71, 1, 2}, /* actual: 596.4 MHz */ - {19200000, 600000000, 62, 1, 2}, /* actual: 595.2 MHz */ - {26000000, 600000000, 92, 2, 2}, /* actual: 598.0 MHz */ - {0, 0, 0, 0, 0, 0}, + { 12000000, 600000000, 100, 1, 2, 0 }, + { 13000000, 600000000, 92, 1, 2, 0 }, /* actual: 598.0 MHz */ + { 16800000, 600000000, 71, 1, 2, 0 }, /* actual: 596.4 MHz */ + { 19200000, 600000000, 62, 1, 2, 0 }, /* actual: 595.2 MHz */ + { 26000000, 600000000, 92, 2, 2, 0 }, /* actual: 598.0 MHz */ + { 0, 0, 0, 0, 0, 0 }, }; static struct tegra_clk_pll_params pll_c2_params = { @@ -338,32 +338,32 @@ static struct div_nmp pllss_nmp = { .divp_width = 4, }; -static struct pdiv_map pll12g_ssd_esd_p[] = { - { .pdiv = 1, .hw_val = 0 }, - { .pdiv = 2, .hw_val = 1 }, - { .pdiv = 3, .hw_val = 2 }, - { .pdiv = 4, .hw_val = 3 }, - { .pdiv = 5, .hw_val = 4 }, - { .pdiv = 6, .hw_val = 5 }, - { .pdiv = 8, .hw_val = 6 }, - { .pdiv = 10, .hw_val = 7 }, - { .pdiv = 12, .hw_val = 8 }, - { .pdiv = 16, .hw_val = 9 }, +static const struct pdiv_map pll12g_ssd_esd_p[] = { + { .pdiv = 1, .hw_val = 0 }, + { .pdiv = 2, .hw_val = 1 }, + { .pdiv = 3, .hw_val = 2 }, + { .pdiv = 4, .hw_val = 3 }, + { .pdiv = 5, .hw_val = 4 }, + { .pdiv = 6, .hw_val = 5 }, + { .pdiv = 8, .hw_val = 6 }, + { .pdiv = 10, .hw_val = 7 }, + { .pdiv = 12, .hw_val = 8 }, + { .pdiv = 16, .hw_val = 9 }, { .pdiv = 12, .hw_val = 10 }, { .pdiv = 16, .hw_val = 11 }, { .pdiv = 20, .hw_val = 12 }, { .pdiv = 24, .hw_val = 13 }, { .pdiv = 32, .hw_val = 14 }, - { .pdiv = 0, .hw_val = 0 }, + { .pdiv = 0, .hw_val = 0 }, }; static struct tegra_clk_pll_freq_table pll_c4_freq_table[] = { - { 12000000, 600000000, 100, 1, 1}, - { 13000000, 600000000, 92, 1, 1}, /* actual: 598.0 MHz */ - { 16800000, 600000000, 71, 1, 1}, /* actual: 596.4 MHz */ - { 19200000, 600000000, 62, 1, 1}, /* actual: 595.2 MHz */ - { 26000000, 600000000, 92, 2, 1}, /* actual: 598.0 MHz */ - { 0, 0, 0, 0, 0, 0 }, + { 12000000, 600000000, 100, 1, 2, 0 }, + { 13000000, 600000000, 92, 1, 2, 0 }, /* actual: 598.0 MHz */ + { 16800000, 600000000, 71, 1, 2, 0 }, /* actual: 596.4 MHz */ + { 19200000, 600000000, 62, 1, 2, 0 }, /* actual: 595.2 MHz */ + { 26000000, 600000000, 92, 2, 2, 0 }, /* actual: 598.0 MHz */ + { 0, 0, 0, 0, 0, 0 }, }; static struct tegra_clk_pll_params pll_c4_params = { @@ -386,21 +386,35 @@ static struct tegra_clk_pll_params pll_c4_params = { .ext_misc_reg[1] = 0x5b0, .ext_misc_reg[2] = 0x5b4, .freq_table = pll_c4_freq_table, + .flags = TEGRA_PLL_USE_LOCK | TEGRA_PLL_HAS_LOCK_ENABLE, }; -static struct pdiv_map pllm_p[] = { - { .pdiv = 1, .hw_val = 0 }, - { .pdiv = 2, .hw_val = 1 }, - { .pdiv = 0, .hw_val = 0 }, +static const struct pdiv_map pllm_p[] = { + { .pdiv = 1, .hw_val = 0 }, + { .pdiv = 2, .hw_val = 1 }, + { .pdiv = 3, .hw_val = 2 }, + { .pdiv = 4, .hw_val = 3 }, + { .pdiv = 5, .hw_val = 4 }, + { .pdiv = 6, .hw_val = 5 }, + { .pdiv = 8, .hw_val = 6 }, + { .pdiv = 10, .hw_val = 7 }, + { .pdiv = 12, .hw_val = 8 }, + { .pdiv = 16, .hw_val = 9 }, + { .pdiv = 12, .hw_val = 10 }, + { .pdiv = 16, .hw_val = 11 }, + { .pdiv = 20, .hw_val = 12 }, + { .pdiv = 24, .hw_val = 13 }, + { .pdiv = 32, .hw_val = 14 }, + { .pdiv = 0, .hw_val = 0 }, }; static struct tegra_clk_pll_freq_table pll_m_freq_table[] = { - {12000000, 800000000, 66, 1, 1}, /* actual: 792.0 MHz */ - {13000000, 800000000, 61, 1, 1}, /* actual: 793.0 MHz */ - {16800000, 800000000, 47, 1, 1}, /* actual: 789.6 MHz */ - {19200000, 800000000, 41, 1, 1}, /* actual: 787.2 MHz */ - {26000000, 800000000, 61, 2, 1}, /* actual: 793.0 MHz */ - {0, 0, 0, 0, 0, 0}, + { 12000000, 800000000, 66, 1, 1, 0 }, /* actual: 792.0 MHz */ + { 13000000, 800000000, 61, 1, 1, 0 }, /* actual: 793.0 MHz */ + { 16800000, 800000000, 47, 1, 1, 0 }, /* actual: 789.6 MHz */ + { 19200000, 800000000, 41, 1, 1, 0 }, /* actual: 787.2 MHz */ + { 26000000, 800000000, 61, 2, 1, 0 }, /* actual: 793.0 MHz */ + { 0, 0, 0, 0, 0, 0}, }; static struct div_nmp pllm_nmp = { @@ -427,22 +441,41 @@ static struct tegra_clk_pll_params pll_m_params = { .lock_mask = PLL_BASE_LOCK, .lock_enable_bit_idx = PLL_MISC_LOCK_ENABLE, .lock_delay = 300, - .max_p = 2, + .max_p = 5, .pdiv_tohw = pllm_p, .div_nmp = &pllm_nmp, .pmc_divnm_reg = PMC_PLLM_WB0_OVERRIDE, .pmc_divp_reg = PMC_PLLM_WB0_OVERRIDE_2, .freq_table = pll_m_freq_table, - .flags = TEGRA_PLL_USE_LOCK, + .flags = TEGRA_PLL_USE_LOCK | TEGRA_PLL_HAS_LOCK_ENABLE, }; static struct tegra_clk_pll_freq_table pll_e_freq_table[] = { /* PLLE special case: use cpcon field to store cml divider value */ - {336000000, 100000000, 100, 21, 16, 11}, - {312000000, 100000000, 200, 26, 24, 13}, - {13000000, 100000000, 200, 1, 26, 13}, - {12000000, 100000000, 200, 1, 24, 13}, - {0, 0, 0, 0, 0, 0}, + { 336000000, 100000000, 100, 21, 16, 11 }, + { 312000000, 100000000, 200, 26, 24, 13 }, + { 13000000, 100000000, 200, 1, 26, 13 }, + { 12000000, 100000000, 200, 1, 24, 13 }, + { 0, 0, 0, 0, 0, 0 }, +}; + +static const struct pdiv_map plle_p[] = { + { .pdiv = 1, .hw_val = 0 }, + { .pdiv = 2, .hw_val = 1 }, + { .pdiv = 3, .hw_val = 2 }, + { .pdiv = 4, .hw_val = 3 }, + { .pdiv = 5, .hw_val = 4 }, + { .pdiv = 6, .hw_val = 5 }, + { .pdiv = 8, .hw_val = 6 }, + { .pdiv = 10, .hw_val = 7 }, + { .pdiv = 12, .hw_val = 8 }, + { .pdiv = 16, .hw_val = 9 }, + { .pdiv = 12, .hw_val = 10 }, + { .pdiv = 16, .hw_val = 11 }, + { .pdiv = 20, .hw_val = 12 }, + { .pdiv = 24, .hw_val = 13 }, + { .pdiv = 32, .hw_val = 14 }, + { .pdiv = 1, .hw_val = 0 }, }; static struct div_nmp plle_nmp = { @@ -467,9 +500,10 @@ static struct tegra_clk_pll_params pll_e_params = { .lock_mask = PLLE_MISC_LOCK, .lock_enable_bit_idx = PLLE_MISC_LOCK_ENABLE, .lock_delay = 300, + .pdiv_tohw = plle_p, .div_nmp = &plle_nmp, .freq_table = pll_e_freq_table, - .flags = TEGRA_PLL_FIXED, + .flags = TEGRA_PLL_FIXED | TEGRA_PLL_HAS_LOCK_ENABLE, .fixed_rate = 100000000, }; @@ -507,7 +541,8 @@ static struct tegra_clk_pll_params pll_re_vco_params = { .iddq_reg = PLLRE_MISC, .iddq_bit_idx = PLLRE_IDDQ_BIT, .div_nmp = &pllre_nmp, - .flags = TEGRA_PLL_USE_LOCK, + .flags = TEGRA_PLL_USE_LOCK | TEGRA_PLL_HAS_LOCK_ENABLE | + TEGRA_PLL_LOCK_MISC, }; static struct div_nmp pllp_nmp = { @@ -520,12 +555,12 @@ static struct div_nmp pllp_nmp = { }; static struct tegra_clk_pll_freq_table pll_p_freq_table[] = { - {12000000, 408000000, 408, 12, 0, 8}, - {13000000, 408000000, 408, 13, 0, 8}, - {16800000, 408000000, 340, 14, 0, 8}, - {19200000, 408000000, 340, 16, 0, 8}, - {26000000, 408000000, 408, 26, 0, 8}, - {0, 0, 0, 0, 0, 0}, + { 12000000, 408000000, 408, 12, 1, 8 }, + { 13000000, 408000000, 408, 13, 1, 8 }, + { 16800000, 408000000, 340, 14, 1, 8 }, + { 19200000, 408000000, 340, 16, 1, 8 }, + { 26000000, 408000000, 408, 26, 1, 8 }, + { 0, 0, 0, 0, 0, 0 }, }; static struct tegra_clk_pll_params pll_p_params = { @@ -543,18 +578,18 @@ static struct tegra_clk_pll_params pll_p_params = { .div_nmp = &pllp_nmp, .freq_table = pll_p_freq_table, .fixed_rate = 408000000, - .flags = TEGRA_PLL_FIXED | TEGRA_PLL_USE_LOCK, + .flags = TEGRA_PLL_FIXED | TEGRA_PLL_USE_LOCK | + TEGRA_PLL_HAS_LOCK_ENABLE, }; static struct tegra_clk_pll_freq_table pll_a_freq_table[] = { - {9600000, 282240000, 147, 5, 0, 4}, - {9600000, 368640000, 192, 5, 0, 4}, - {9600000, 240000000, 200, 8, 0, 8}, - - {28800000, 282240000, 245, 25, 0, 8}, - {28800000, 368640000, 320, 25, 0, 8}, - {28800000, 240000000, 200, 24, 0, 8}, - {0, 0, 0, 0, 0, 0}, + { 9600000, 282240000, 147, 5, 1, 4 }, + { 9600000, 368640000, 192, 5, 1, 4 }, + { 9600000, 240000000, 200, 8, 1, 8 }, + { 28800000, 282240000, 245, 25, 1, 8 }, + { 28800000, 368640000, 320, 25, 1, 8 }, + { 28800000, 240000000, 200, 24, 1, 8 }, + { 0, 0, 0, 0, 0, 0 }, }; static struct tegra_clk_pll_params pll_a_params = { @@ -571,7 +606,8 @@ static struct tegra_clk_pll_params pll_a_params = { .lock_delay = 300, .div_nmp = &pllp_nmp, .freq_table = pll_a_freq_table, - .flags = TEGRA_PLL_HAS_CPCON | TEGRA_PLL_USE_LOCK, + .flags = TEGRA_PLL_HAS_CPCON | TEGRA_PLL_USE_LOCK | + TEGRA_PLL_HAS_LOCK_ENABLE, }; static struct div_nmp plld_nmp = { @@ -584,24 +620,21 @@ static struct div_nmp plld_nmp = { }; static struct tegra_clk_pll_freq_table pll_d_freq_table[] = { - {12000000, 216000000, 864, 12, 4, 12}, - {13000000, 216000000, 864, 13, 4, 12}, - {16800000, 216000000, 720, 14, 4, 12}, - {19200000, 216000000, 720, 16, 4, 12}, - {26000000, 216000000, 864, 26, 4, 12}, - - {12000000, 594000000, 594, 12, 1, 12}, - {13000000, 594000000, 594, 13, 1, 12}, - {16800000, 594000000, 495, 14, 1, 12}, - {19200000, 594000000, 495, 16, 1, 12}, - {26000000, 594000000, 594, 26, 1, 12}, - - {12000000, 1000000000, 1000, 12, 1, 12}, - {13000000, 1000000000, 1000, 13, 1, 12}, - {19200000, 1000000000, 625, 12, 1, 12}, - {26000000, 1000000000, 1000, 26, 1, 12}, - - {0, 0, 0, 0, 0, 0}, + { 12000000, 216000000, 864, 12, 4, 12 }, + { 13000000, 216000000, 864, 13, 4, 12 }, + { 16800000, 216000000, 720, 14, 4, 12 }, + { 19200000, 216000000, 720, 16, 4, 12 }, + { 26000000, 216000000, 864, 26, 4, 12 }, + { 12000000, 594000000, 594, 12, 1, 12 }, + { 13000000, 594000000, 594, 13, 1, 12 }, + { 16800000, 594000000, 495, 14, 1, 12 }, + { 19200000, 594000000, 495, 16, 1, 12 }, + { 26000000, 594000000, 594, 26, 1, 12 }, + { 12000000, 1000000000, 1000, 12, 1, 12 }, + { 13000000, 1000000000, 1000, 13, 1, 12 }, + { 19200000, 1000000000, 625, 12, 1, 12 }, + { 26000000, 1000000000, 1000, 26, 1, 12 }, + { 0, 0, 0, 0, 0, 0 }, }; static struct tegra_clk_pll_params pll_d_params = { @@ -619,16 +652,16 @@ static struct tegra_clk_pll_params pll_d_params = { .div_nmp = &plld_nmp, .freq_table = pll_d_freq_table, .flags = TEGRA_PLL_HAS_CPCON | TEGRA_PLL_SET_LFCON | - TEGRA_PLL_USE_LOCK, + TEGRA_PLL_USE_LOCK | TEGRA_PLL_HAS_LOCK_ENABLE, }; static struct tegra_clk_pll_freq_table tegra124_pll_d2_freq_table[] = { - { 12000000, 594000000, 99, 1, 2}, - { 13000000, 594000000, 91, 1, 2}, /* actual: 591.5 MHz */ - { 16800000, 594000000, 71, 1, 2}, /* actual: 596.4 MHz */ - { 19200000, 594000000, 62, 1, 2}, /* actual: 595.2 MHz */ - { 26000000, 594000000, 91, 2, 2}, /* actual: 591.5 MHz */ - { 0, 0, 0, 0, 0, 0 }, + { 12000000, 594000000, 99, 1, 2, 0 }, + { 13000000, 594000000, 91, 1, 2, 0 }, /* actual: 591.5 MHz */ + { 16800000, 594000000, 71, 1, 2, 0 }, /* actual: 596.4 MHz */ + { 19200000, 594000000, 62, 1, 2, 0 }, /* actual: 595.2 MHz */ + { 26000000, 594000000, 91, 2, 2, 0 }, /* actual: 591.5 MHz */ + { 0, 0, 0, 0, 0, 0 }, }; static struct tegra_clk_pll_params tegra124_pll_d2_params = { @@ -652,15 +685,16 @@ static struct tegra_clk_pll_params tegra124_pll_d2_params = { .ext_misc_reg[2] = 0x578, .max_p = 15, .freq_table = tegra124_pll_d2_freq_table, + .flags = TEGRA_PLL_USE_LOCK | TEGRA_PLL_HAS_LOCK_ENABLE, }; static struct tegra_clk_pll_freq_table pll_dp_freq_table[] = { - { 12000000, 600000000, 100, 1, 1}, - { 13000000, 600000000, 92, 1, 1}, /* actual: 598.0 MHz */ - { 16800000, 600000000, 71, 1, 1}, /* actual: 596.4 MHz */ - { 19200000, 600000000, 62, 1, 1}, /* actual: 595.2 MHz */ - { 26000000, 600000000, 92, 2, 1}, /* actual: 598.0 MHz */ - { 0, 0, 0, 0, 0, 0 }, + { 12000000, 600000000, 100, 1, 2, 0 }, + { 13000000, 600000000, 92, 1, 2, 0 }, /* actual: 598.0 MHz */ + { 16800000, 600000000, 71, 1, 2, 0 }, /* actual: 596.4 MHz */ + { 19200000, 600000000, 62, 1, 2, 0 }, /* actual: 595.2 MHz */ + { 26000000, 600000000, 92, 2, 2, 0 }, /* actual: 598.0 MHz */ + { 0, 0, 0, 0, 0, 0 }, }; static struct tegra_clk_pll_params pll_dp_params = { @@ -684,9 +718,10 @@ static struct tegra_clk_pll_params pll_dp_params = { .ext_misc_reg[2] = 0x5a0, .max_p = 5, .freq_table = pll_dp_freq_table, + .flags = TEGRA_PLL_USE_LOCK | TEGRA_PLL_HAS_LOCK_ENABLE, }; -static struct pdiv_map pllu_p[] = { +static const struct pdiv_map pllu_p[] = { { .pdiv = 1, .hw_val = 1 }, { .pdiv = 2, .hw_val = 0 }, { .pdiv = 0, .hw_val = 0 }, @@ -702,12 +737,12 @@ static struct div_nmp pllu_nmp = { }; static struct tegra_clk_pll_freq_table pll_u_freq_table[] = { - {12000000, 480000000, 960, 12, 2, 12}, - {13000000, 480000000, 960, 13, 2, 12}, - {16800000, 480000000, 400, 7, 2, 5}, - {19200000, 480000000, 200, 4, 2, 3}, - {26000000, 480000000, 960, 26, 2, 12}, - {0, 0, 0, 0, 0, 0}, + { 12000000, 480000000, 960, 12, 2, 12 }, + { 13000000, 480000000, 960, 13, 2, 12 }, + { 16800000, 480000000, 400, 7, 2, 5 }, + { 19200000, 480000000, 200, 4, 2, 3 }, + { 26000000, 480000000, 960, 26, 2, 12 }, + { 0, 0, 0, 0, 0, 0 }, }; static struct tegra_clk_pll_params pll_u_params = { @@ -726,7 +761,7 @@ static struct tegra_clk_pll_params pll_u_params = { .div_nmp = &pllu_nmp, .freq_table = pll_u_freq_table, .flags = TEGRA_PLLU | TEGRA_PLL_HAS_CPCON | TEGRA_PLL_SET_LFCON | - TEGRA_PLL_USE_LOCK, + TEGRA_PLL_USE_LOCK | TEGRA_PLL_HAS_LOCK_ENABLE, }; struct utmi_clk_param { @@ -743,21 +778,27 @@ struct utmi_clk_param { }; static const struct utmi_clk_param utmi_parameters[] = { - {.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 = 0x04, - .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}, + { + .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 = 0x04, + .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 tegra124_clks[tegra_clk_max] __initdata = { @@ -1024,8 +1065,8 @@ static struct clk **clks; static void tegra124_utmi_param_configure(void __iomem *clk_base) { + unsigned int i; u32 reg; - int i; for (i = 0; i < ARRAY_SIZE(utmi_parameters); i++) { if (osc_freq == utmi_parameters[i].osc_frequency) @@ -1356,65 +1397,65 @@ static struct tegra_cpu_car_ops tegra124_cpu_car_ops = { static const struct of_device_id pmc_match[] __initconst = { { .compatible = "nvidia,tegra124-pmc" }, - {}, + { }, }; static struct tegra_clk_init_table common_init_table[] __initdata = { - {TEGRA124_CLK_UARTA, TEGRA124_CLK_PLL_P, 408000000, 0}, - {TEGRA124_CLK_UARTB, TEGRA124_CLK_PLL_P, 408000000, 0}, - {TEGRA124_CLK_UARTC, TEGRA124_CLK_PLL_P, 408000000, 0}, - {TEGRA124_CLK_UARTD, TEGRA124_CLK_PLL_P, 408000000, 0}, - {TEGRA124_CLK_PLL_A, TEGRA124_CLK_CLK_MAX, 564480000, 1}, - {TEGRA124_CLK_PLL_A_OUT0, TEGRA124_CLK_CLK_MAX, 11289600, 1}, - {TEGRA124_CLK_EXTERN1, TEGRA124_CLK_PLL_A_OUT0, 0, 1}, - {TEGRA124_CLK_CLK_OUT_1_MUX, TEGRA124_CLK_EXTERN1, 0, 1}, - {TEGRA124_CLK_CLK_OUT_1, TEGRA124_CLK_CLK_MAX, 0, 1}, - {TEGRA124_CLK_I2S0, TEGRA124_CLK_PLL_A_OUT0, 11289600, 0}, - {TEGRA124_CLK_I2S1, TEGRA124_CLK_PLL_A_OUT0, 11289600, 0}, - {TEGRA124_CLK_I2S2, TEGRA124_CLK_PLL_A_OUT0, 11289600, 0}, - {TEGRA124_CLK_I2S3, TEGRA124_CLK_PLL_A_OUT0, 11289600, 0}, - {TEGRA124_CLK_I2S4, TEGRA124_CLK_PLL_A_OUT0, 11289600, 0}, - {TEGRA124_CLK_VDE, TEGRA124_CLK_PLL_P, 0, 0}, - {TEGRA124_CLK_HOST1X, TEGRA124_CLK_PLL_P, 136000000, 1}, - {TEGRA124_CLK_DSIALP, TEGRA124_CLK_PLL_P, 68000000, 0}, - {TEGRA124_CLK_DSIBLP, TEGRA124_CLK_PLL_P, 68000000, 0}, - {TEGRA124_CLK_SCLK, TEGRA124_CLK_PLL_P_OUT2, 102000000, 1}, - {TEGRA124_CLK_DFLL_SOC, TEGRA124_CLK_PLL_P, 51000000, 1}, - {TEGRA124_CLK_DFLL_REF, TEGRA124_CLK_PLL_P, 51000000, 1}, - {TEGRA124_CLK_PLL_C, TEGRA124_CLK_CLK_MAX, 768000000, 0}, - {TEGRA124_CLK_PLL_C_OUT1, TEGRA124_CLK_CLK_MAX, 100000000, 0}, - {TEGRA124_CLK_SBC4, TEGRA124_CLK_PLL_P, 12000000, 1}, - {TEGRA124_CLK_TSEC, TEGRA124_CLK_PLL_C3, 0, 0}, - {TEGRA124_CLK_MSENC, TEGRA124_CLK_PLL_C3, 0, 0}, - {TEGRA124_CLK_PLL_RE_VCO, TEGRA124_CLK_CLK_MAX, 672000000, 0}, - {TEGRA124_CLK_XUSB_SS_SRC, TEGRA124_CLK_PLL_U_480M, 120000000, 0}, - {TEGRA124_CLK_XUSB_FS_SRC, TEGRA124_CLK_PLL_U_48M, 48000000, 0}, - {TEGRA124_CLK_XUSB_HS_SRC, TEGRA124_CLK_PLL_U_60M, 60000000, 0}, - {TEGRA124_CLK_XUSB_FALCON_SRC, TEGRA124_CLK_PLL_RE_OUT, 224000000, 0}, - {TEGRA124_CLK_XUSB_HOST_SRC, TEGRA124_CLK_PLL_RE_OUT, 112000000, 0}, - {TEGRA124_CLK_SATA, TEGRA124_CLK_PLL_P, 104000000, 0}, - {TEGRA124_CLK_SATA_OOB, TEGRA124_CLK_PLL_P, 204000000, 0}, - {TEGRA124_CLK_MSELECT, TEGRA124_CLK_CLK_MAX, 0, 1}, - {TEGRA124_CLK_CSITE, TEGRA124_CLK_CLK_MAX, 0, 1}, - {TEGRA124_CLK_TSENSOR, TEGRA124_CLK_CLK_M, 400000, 0}, - /* This MUST be the last entry. */ - {TEGRA124_CLK_CLK_MAX, TEGRA124_CLK_CLK_MAX, 0, 0}, + { TEGRA124_CLK_UARTA, TEGRA124_CLK_PLL_P, 408000000, 0 }, + { TEGRA124_CLK_UARTB, TEGRA124_CLK_PLL_P, 408000000, 0 }, + { TEGRA124_CLK_UARTC, TEGRA124_CLK_PLL_P, 408000000, 0 }, + { TEGRA124_CLK_UARTD, TEGRA124_CLK_PLL_P, 408000000, 0 }, + { TEGRA124_CLK_PLL_A, TEGRA124_CLK_CLK_MAX, 564480000, 1 }, + { TEGRA124_CLK_PLL_A_OUT0, TEGRA124_CLK_CLK_MAX, 11289600, 1 }, + { TEGRA124_CLK_EXTERN1, TEGRA124_CLK_PLL_A_OUT0, 0, 1 }, + { TEGRA124_CLK_CLK_OUT_1_MUX, TEGRA124_CLK_EXTERN1, 0, 1 }, + { TEGRA124_CLK_CLK_OUT_1, TEGRA124_CLK_CLK_MAX, 0, 1 }, + { TEGRA124_CLK_I2S0, TEGRA124_CLK_PLL_A_OUT0, 11289600, 0 }, + { TEGRA124_CLK_I2S1, TEGRA124_CLK_PLL_A_OUT0, 11289600, 0 }, + { TEGRA124_CLK_I2S2, TEGRA124_CLK_PLL_A_OUT0, 11289600, 0 }, + { TEGRA124_CLK_I2S3, TEGRA124_CLK_PLL_A_OUT0, 11289600, 0 }, + { TEGRA124_CLK_I2S4, TEGRA124_CLK_PLL_A_OUT0, 11289600, 0 }, + { TEGRA124_CLK_VDE, TEGRA124_CLK_PLL_P, 0, 0 }, + { TEGRA124_CLK_HOST1X, TEGRA124_CLK_PLL_P, 136000000, 1 }, + { TEGRA124_CLK_DSIALP, TEGRA124_CLK_PLL_P, 68000000, 0 }, + { TEGRA124_CLK_DSIBLP, TEGRA124_CLK_PLL_P, 68000000, 0 }, + { TEGRA124_CLK_SCLK, TEGRA124_CLK_PLL_P_OUT2, 102000000, 1 }, + { TEGRA124_CLK_DFLL_SOC, TEGRA124_CLK_PLL_P, 51000000, 1 }, + { TEGRA124_CLK_DFLL_REF, TEGRA124_CLK_PLL_P, 51000000, 1 }, + { TEGRA124_CLK_PLL_C, TEGRA124_CLK_CLK_MAX, 768000000, 0 }, + { TEGRA124_CLK_PLL_C_OUT1, TEGRA124_CLK_CLK_MAX, 100000000, 0 }, + { TEGRA124_CLK_SBC4, TEGRA124_CLK_PLL_P, 12000000, 1 }, + { TEGRA124_CLK_TSEC, TEGRA124_CLK_PLL_C3, 0, 0 }, + { TEGRA124_CLK_MSENC, TEGRA124_CLK_PLL_C3, 0, 0 }, + { TEGRA124_CLK_PLL_RE_VCO, TEGRA124_CLK_CLK_MAX, 672000000, 0 }, + { TEGRA124_CLK_XUSB_SS_SRC, TEGRA124_CLK_PLL_U_480M, 120000000, 0 }, + { TEGRA124_CLK_XUSB_FS_SRC, TEGRA124_CLK_PLL_U_48M, 48000000, 0 }, + { TEGRA124_CLK_XUSB_HS_SRC, TEGRA124_CLK_PLL_U_60M, 60000000, 0 }, + { TEGRA124_CLK_XUSB_FALCON_SRC, TEGRA124_CLK_PLL_RE_OUT, 224000000, 0 }, + { TEGRA124_CLK_XUSB_HOST_SRC, TEGRA124_CLK_PLL_RE_OUT, 112000000, 0 }, + { TEGRA124_CLK_SATA, TEGRA124_CLK_PLL_P, 104000000, 0 }, + { TEGRA124_CLK_SATA_OOB, TEGRA124_CLK_PLL_P, 204000000, 0 }, + { TEGRA124_CLK_MSELECT, TEGRA124_CLK_CLK_MAX, 0, 1 }, + { TEGRA124_CLK_CSITE, TEGRA124_CLK_CLK_MAX, 0, 1 }, + { TEGRA124_CLK_TSENSOR, TEGRA124_CLK_CLK_M, 400000, 0 }, + /* must be the last entry */ + { TEGRA124_CLK_CLK_MAX, TEGRA124_CLK_CLK_MAX, 0, 0 }, }; static struct tegra_clk_init_table tegra124_init_table[] __initdata = { - {TEGRA124_CLK_SOC_THERM, TEGRA124_CLK_PLL_P, 51000000, 0}, - {TEGRA124_CLK_CCLK_G, TEGRA124_CLK_CLK_MAX, 0, 1}, - {TEGRA124_CLK_HDA, TEGRA124_CLK_PLL_P, 102000000, 0}, - {TEGRA124_CLK_HDA2CODEC_2X, TEGRA124_CLK_PLL_P, 48000000, 0}, - /* This MUST be the last entry. */ - {TEGRA124_CLK_CLK_MAX, TEGRA124_CLK_CLK_MAX, 0, 0}, + { TEGRA124_CLK_SOC_THERM, TEGRA124_CLK_PLL_P, 51000000, 0 }, + { TEGRA124_CLK_CCLK_G, TEGRA124_CLK_CLK_MAX, 0, 1 }, + { TEGRA124_CLK_HDA, TEGRA124_CLK_PLL_P, 102000000, 0 }, + { TEGRA124_CLK_HDA2CODEC_2X, TEGRA124_CLK_PLL_P, 48000000, 0 }, + /* must be the last entry */ + { TEGRA124_CLK_CLK_MAX, TEGRA124_CLK_CLK_MAX, 0, 0 }, }; /* Tegra132 requires the SOC_THERM clock to remain active */ static struct tegra_clk_init_table tegra132_init_table[] __initdata = { - {TEGRA124_CLK_SOC_THERM, TEGRA124_CLK_PLL_P, 51000000, 1}, - /* This MUST be the last entry. */ - {TEGRA124_CLK_CLK_MAX, TEGRA124_CLK_CLK_MAX, 0, 0}, + { TEGRA124_CLK_SOC_THERM, TEGRA124_CLK_PLL_P, 51000000, 1 }, + /* must be the last entry */ + { TEGRA124_CLK_CLK_MAX, TEGRA124_CLK_CLK_MAX, 0, 0 }, }; static struct tegra_audio_clk_info tegra124_audio_plls[] = { diff --git a/drivers/clk/tegra/clk-tegra20.c b/drivers/clk/tegra/clk-tegra20.c index bf004f0e4..7a48e986c 100644 --- a/drivers/clk/tegra/clk-tegra20.c +++ b/drivers/clk/tegra/clk-tegra20.c @@ -166,126 +166,120 @@ static DEFINE_SPINLOCK(emc_lock); static struct clk **clks; static struct tegra_clk_pll_freq_table pll_c_freq_table[] = { - { 12000000, 600000000, 600, 12, 0, 8 }, - { 13000000, 600000000, 600, 13, 0, 8 }, - { 19200000, 600000000, 500, 16, 0, 6 }, - { 26000000, 600000000, 600, 26, 0, 8 }, - { 0, 0, 0, 0, 0, 0 }, + { 12000000, 600000000, 600, 12, 1, 8 }, + { 13000000, 600000000, 600, 13, 1, 8 }, + { 19200000, 600000000, 500, 16, 1, 6 }, + { 26000000, 600000000, 600, 26, 1, 8 }, + { 0, 0, 0, 0, 0, 0 }, }; static struct tegra_clk_pll_freq_table pll_m_freq_table[] = { - { 12000000, 666000000, 666, 12, 0, 8}, - { 13000000, 666000000, 666, 13, 0, 8}, - { 19200000, 666000000, 555, 16, 0, 8}, - { 26000000, 666000000, 666, 26, 0, 8}, - { 12000000, 600000000, 600, 12, 0, 8}, - { 13000000, 600000000, 600, 13, 0, 8}, - { 19200000, 600000000, 375, 12, 0, 6}, - { 26000000, 600000000, 600, 26, 0, 8}, - { 0, 0, 0, 0, 0, 0 }, + { 12000000, 666000000, 666, 12, 1, 8 }, + { 13000000, 666000000, 666, 13, 1, 8 }, + { 19200000, 666000000, 555, 16, 1, 8 }, + { 26000000, 666000000, 666, 26, 1, 8 }, + { 12000000, 600000000, 600, 12, 1, 8 }, + { 13000000, 600000000, 600, 13, 1, 8 }, + { 19200000, 600000000, 375, 12, 1, 6 }, + { 26000000, 600000000, 600, 26, 1, 8 }, + { 0, 0, 0, 0, 0, 0 }, }; static struct tegra_clk_pll_freq_table pll_p_freq_table[] = { - { 12000000, 216000000, 432, 12, 1, 8}, - { 13000000, 216000000, 432, 13, 1, 8}, - { 19200000, 216000000, 90, 4, 1, 1}, - { 26000000, 216000000, 432, 26, 1, 8}, - { 12000000, 432000000, 432, 12, 0, 8}, - { 13000000, 432000000, 432, 13, 0, 8}, - { 19200000, 432000000, 90, 4, 0, 1}, - { 26000000, 432000000, 432, 26, 0, 8}, - { 0, 0, 0, 0, 0, 0 }, + { 12000000, 216000000, 432, 12, 2, 8 }, + { 13000000, 216000000, 432, 13, 2, 8 }, + { 19200000, 216000000, 90, 4, 2, 1 }, + { 26000000, 216000000, 432, 26, 2, 8 }, + { 12000000, 432000000, 432, 12, 1, 8 }, + { 13000000, 432000000, 432, 13, 1, 8 }, + { 19200000, 432000000, 90, 4, 1, 1 }, + { 26000000, 432000000, 432, 26, 1, 8 }, + { 0, 0, 0, 0, 0, 0 }, }; static struct tegra_clk_pll_freq_table pll_a_freq_table[] = { - { 28800000, 56448000, 49, 25, 0, 1}, - { 28800000, 73728000, 64, 25, 0, 1}, - { 28800000, 24000000, 5, 6, 0, 1}, - { 0, 0, 0, 0, 0, 0 }, + { 28800000, 56448000, 49, 25, 1, 1 }, + { 28800000, 73728000, 64, 25, 1, 1 }, + { 28800000, 24000000, 5, 6, 1, 1 }, + { 0, 0, 0, 0, 0, 0 }, }; static struct tegra_clk_pll_freq_table pll_d_freq_table[] = { - { 12000000, 216000000, 216, 12, 0, 4}, - { 13000000, 216000000, 216, 13, 0, 4}, - { 19200000, 216000000, 135, 12, 0, 3}, - { 26000000, 216000000, 216, 26, 0, 4}, - - { 12000000, 594000000, 594, 12, 0, 8}, - { 13000000, 594000000, 594, 13, 0, 8}, - { 19200000, 594000000, 495, 16, 0, 8}, - { 26000000, 594000000, 594, 26, 0, 8}, - - { 12000000, 1000000000, 1000, 12, 0, 12}, - { 13000000, 1000000000, 1000, 13, 0, 12}, - { 19200000, 1000000000, 625, 12, 0, 8}, - { 26000000, 1000000000, 1000, 26, 0, 12}, - - { 0, 0, 0, 0, 0, 0 }, + { 12000000, 216000000, 216, 12, 1, 4 }, + { 13000000, 216000000, 216, 13, 1, 4 }, + { 19200000, 216000000, 135, 12, 1, 3 }, + { 26000000, 216000000, 216, 26, 1, 4 }, + { 12000000, 594000000, 594, 12, 1, 8 }, + { 13000000, 594000000, 594, 13, 1, 8 }, + { 19200000, 594000000, 495, 16, 1, 8 }, + { 26000000, 594000000, 594, 26, 1, 8 }, + { 12000000, 1000000000, 1000, 12, 1, 12 }, + { 13000000, 1000000000, 1000, 13, 1, 12 }, + { 19200000, 1000000000, 625, 12, 1, 8 }, + { 26000000, 1000000000, 1000, 26, 1, 12 }, + { 0, 0, 0, 0, 0, 0 }, }; static struct tegra_clk_pll_freq_table pll_u_freq_table[] = { - { 12000000, 480000000, 960, 12, 0, 0}, - { 13000000, 480000000, 960, 13, 0, 0}, - { 19200000, 480000000, 200, 4, 0, 0}, - { 26000000, 480000000, 960, 26, 0, 0}, - { 0, 0, 0, 0, 0, 0 }, + { 12000000, 480000000, 960, 12, 1, 0 }, + { 13000000, 480000000, 960, 13, 1, 0 }, + { 19200000, 480000000, 200, 4, 1, 0 }, + { 26000000, 480000000, 960, 26, 1, 0 }, + { 0, 0, 0, 0, 0, 0 }, }; static struct tegra_clk_pll_freq_table pll_x_freq_table[] = { /* 1 GHz */ - { 12000000, 1000000000, 1000, 12, 0, 12}, - { 13000000, 1000000000, 1000, 13, 0, 12}, - { 19200000, 1000000000, 625, 12, 0, 8}, - { 26000000, 1000000000, 1000, 26, 0, 12}, - + { 12000000, 1000000000, 1000, 12, 1, 12 }, + { 13000000, 1000000000, 1000, 13, 1, 12 }, + { 19200000, 1000000000, 625, 12, 1, 8 }, + { 26000000, 1000000000, 1000, 26, 1, 12 }, /* 912 MHz */ - { 12000000, 912000000, 912, 12, 0, 12}, - { 13000000, 912000000, 912, 13, 0, 12}, - { 19200000, 912000000, 760, 16, 0, 8}, - { 26000000, 912000000, 912, 26, 0, 12}, - + { 12000000, 912000000, 912, 12, 1, 12 }, + { 13000000, 912000000, 912, 13, 1, 12 }, + { 19200000, 912000000, 760, 16, 1, 8 }, + { 26000000, 912000000, 912, 26, 1, 12 }, /* 816 MHz */ - { 12000000, 816000000, 816, 12, 0, 12}, - { 13000000, 816000000, 816, 13, 0, 12}, - { 19200000, 816000000, 680, 16, 0, 8}, - { 26000000, 816000000, 816, 26, 0, 12}, - + { 12000000, 816000000, 816, 12, 1, 12 }, + { 13000000, 816000000, 816, 13, 1, 12 }, + { 19200000, 816000000, 680, 16, 1, 8 }, + { 26000000, 816000000, 816, 26, 1, 12 }, /* 760 MHz */ - { 12000000, 760000000, 760, 12, 0, 12}, - { 13000000, 760000000, 760, 13, 0, 12}, - { 19200000, 760000000, 950, 24, 0, 8}, - { 26000000, 760000000, 760, 26, 0, 12}, - + { 12000000, 760000000, 760, 12, 1, 12 }, + { 13000000, 760000000, 760, 13, 1, 12 }, + { 19200000, 760000000, 950, 24, 1, 8 }, + { 26000000, 760000000, 760, 26, 1, 12 }, /* 750 MHz */ - { 12000000, 750000000, 750, 12, 0, 12}, - { 13000000, 750000000, 750, 13, 0, 12}, - { 19200000, 750000000, 625, 16, 0, 8}, - { 26000000, 750000000, 750, 26, 0, 12}, - + { 12000000, 750000000, 750, 12, 1, 12 }, + { 13000000, 750000000, 750, 13, 1, 12 }, + { 19200000, 750000000, 625, 16, 1, 8 }, + { 26000000, 750000000, 750, 26, 1, 12 }, /* 608 MHz */ - { 12000000, 608000000, 608, 12, 0, 12}, - { 13000000, 608000000, 608, 13, 0, 12}, - { 19200000, 608000000, 380, 12, 0, 8}, - { 26000000, 608000000, 608, 26, 0, 12}, - + { 12000000, 608000000, 608, 12, 1, 12 }, + { 13000000, 608000000, 608, 13, 1, 12 }, + { 19200000, 608000000, 380, 12, 1, 8 }, + { 26000000, 608000000, 608, 26, 1, 12 }, /* 456 MHz */ - { 12000000, 456000000, 456, 12, 0, 12}, - { 13000000, 456000000, 456, 13, 0, 12}, - { 19200000, 456000000, 380, 16, 0, 8}, - { 26000000, 456000000, 456, 26, 0, 12}, - + { 12000000, 456000000, 456, 12, 1, 12 }, + { 13000000, 456000000, 456, 13, 1, 12 }, + { 19200000, 456000000, 380, 16, 1, 8 }, + { 26000000, 456000000, 456, 26, 1, 12 }, /* 312 MHz */ - { 12000000, 312000000, 312, 12, 0, 12}, - { 13000000, 312000000, 312, 13, 0, 12}, - { 19200000, 312000000, 260, 16, 0, 8}, - { 26000000, 312000000, 312, 26, 0, 12}, + { 12000000, 312000000, 312, 12, 1, 12 }, + { 13000000, 312000000, 312, 13, 1, 12 }, + { 19200000, 312000000, 260, 16, 1, 8 }, + { 26000000, 312000000, 312, 26, 1, 12 }, + { 0, 0, 0, 0, 0, 0 }, +}; - { 0, 0, 0, 0, 0, 0 }, +static const struct pdiv_map plle_p[] = { + { .pdiv = 1, .hw_val = 1 }, + { .pdiv = 0, .hw_val = 0 }, }; static struct tegra_clk_pll_freq_table pll_e_freq_table[] = { - { 12000000, 100000000, 200, 24, 0, 0 }, - { 0, 0, 0, 0, 0, 0 }, + { 12000000, 100000000, 200, 24, 1, 0 }, + { 0, 0, 0, 0, 0, 0 }, }; /* PLL parameters */ @@ -302,7 +296,7 @@ static struct tegra_clk_pll_params pll_c_params = { .lock_enable_bit_idx = PLL_MISC_LOCK_ENABLE, .lock_delay = 300, .freq_table = pll_c_freq_table, - .flags = TEGRA_PLL_HAS_CPCON, + .flags = TEGRA_PLL_HAS_CPCON | TEGRA_PLL_HAS_LOCK_ENABLE, }; static struct tegra_clk_pll_params pll_m_params = { @@ -318,7 +312,7 @@ static struct tegra_clk_pll_params pll_m_params = { .lock_enable_bit_idx = PLL_MISC_LOCK_ENABLE, .lock_delay = 300, .freq_table = pll_m_freq_table, - .flags = TEGRA_PLL_HAS_CPCON, + .flags = TEGRA_PLL_HAS_CPCON | TEGRA_PLL_HAS_LOCK_ENABLE, }; static struct tegra_clk_pll_params pll_p_params = { @@ -334,7 +328,8 @@ static struct tegra_clk_pll_params pll_p_params = { .lock_enable_bit_idx = PLL_MISC_LOCK_ENABLE, .lock_delay = 300, .freq_table = pll_p_freq_table, - .flags = TEGRA_PLL_FIXED | TEGRA_PLL_HAS_CPCON, + .flags = TEGRA_PLL_FIXED | TEGRA_PLL_HAS_CPCON | + TEGRA_PLL_HAS_LOCK_ENABLE, .fixed_rate = 216000000, }; @@ -351,7 +346,7 @@ static struct tegra_clk_pll_params pll_a_params = { .lock_enable_bit_idx = PLL_MISC_LOCK_ENABLE, .lock_delay = 300, .freq_table = pll_a_freq_table, - .flags = TEGRA_PLL_HAS_CPCON, + .flags = TEGRA_PLL_HAS_CPCON | TEGRA_PLL_HAS_LOCK_ENABLE, }; static struct tegra_clk_pll_params pll_d_params = { @@ -367,10 +362,10 @@ static struct tegra_clk_pll_params pll_d_params = { .lock_enable_bit_idx = PLLDU_MISC_LOCK_ENABLE, .lock_delay = 1000, .freq_table = pll_d_freq_table, - .flags = TEGRA_PLL_HAS_CPCON, + .flags = TEGRA_PLL_HAS_CPCON | TEGRA_PLL_HAS_LOCK_ENABLE, }; -static struct pdiv_map pllu_p[] = { +static const struct pdiv_map pllu_p[] = { { .pdiv = 1, .hw_val = 1 }, { .pdiv = 2, .hw_val = 0 }, { .pdiv = 0, .hw_val = 0 }, @@ -390,7 +385,7 @@ static struct tegra_clk_pll_params pll_u_params = { .lock_delay = 1000, .pdiv_tohw = pllu_p, .freq_table = pll_u_freq_table, - .flags = TEGRA_PLLU | TEGRA_PLL_HAS_CPCON, + .flags = TEGRA_PLLU | TEGRA_PLL_HAS_CPCON | TEGRA_PLL_HAS_LOCK_ENABLE, }; static struct tegra_clk_pll_params pll_x_params = { @@ -406,7 +401,7 @@ static struct tegra_clk_pll_params pll_x_params = { .lock_enable_bit_idx = PLL_MISC_LOCK_ENABLE, .lock_delay = 300, .freq_table = pll_x_freq_table, - .flags = TEGRA_PLL_HAS_CPCON, + .flags = TEGRA_PLL_HAS_CPCON | TEGRA_PLL_HAS_LOCK_ENABLE, }; static struct tegra_clk_pll_params pll_e_params = { @@ -421,8 +416,10 @@ static struct tegra_clk_pll_params pll_e_params = { .lock_mask = PLLE_MISC_LOCK, .lock_enable_bit_idx = PLLE_MISC_LOCK_ENABLE, .lock_delay = 0, + .pdiv_tohw = plle_p, .freq_table = pll_e_freq_table, - .flags = TEGRA_PLL_FIXED, + .flags = TEGRA_PLL_FIXED | TEGRA_PLL_LOCK_MISC | + TEGRA_PLL_HAS_LOCK_ENABLE, .fixed_rate = 100000000, }; @@ -733,9 +730,9 @@ static void tegra20_super_clk_init(void) clks[TEGRA20_CLK_TWD] = clk; } -static const char *audio_parents[] = {"spdif_in", "i2s1", "i2s2", "unused", - "pll_a_out0", "unused", "unused", - "unused"}; +static const char *audio_parents[] = { "spdif_in", "i2s1", "i2s2", "unused", + "pll_a_out0", "unused", "unused", + "unused" }; static void __init tegra20_audio_clk_init(void) { @@ -759,19 +756,18 @@ static void __init tegra20_audio_clk_init(void) CLK_SET_RATE_PARENT, 89, periph_clk_enb_refcnt); clks[TEGRA20_CLK_AUDIO_2X] = clk; - } -static const char *i2s1_parents[] = {"pll_a_out0", "audio_2x", "pll_p", - "clk_m"}; -static const char *i2s2_parents[] = {"pll_a_out0", "audio_2x", "pll_p", - "clk_m"}; -static const char *pwm_parents[] = {"pll_p", "pll_c", "audio", "clk_m", - "clk_32k"}; -static const char *mux_pllpcm_clkm[] = {"pll_p", "pll_c", "pll_m", "clk_m"}; -static const char *mux_pllpdc_clkm[] = {"pll_p", "pll_d_out0", "pll_c", - "clk_m"}; -static const char *mux_pllmcp_clkm[] = {"pll_m", "pll_c", "pll_p", "clk_m"}; +static const char *i2s1_parents[] = { "pll_a_out0", "audio_2x", "pll_p", + "clk_m" }; +static const char *i2s2_parents[] = { "pll_a_out0", "audio_2x", "pll_p", + "clk_m" }; +static const char *pwm_parents[] = { "pll_p", "pll_c", "audio", "clk_m", + "clk_32k" }; +static const char *mux_pllpcm_clkm[] = { "pll_p", "pll_c", "pll_m", "clk_m" }; +static const char *mux_pllpdc_clkm[] = { "pll_p", "pll_d_out0", "pll_c", + "clk_m" }; +static const char *mux_pllmcp_clkm[] = { "pll_m", "pll_c", "pll_p", "clk_m" }; static struct tegra_periph_init_data tegra_periph_clk_list[] = { TEGRA_INIT_DATA_MUX("i2s1", i2s1_parents, CLK_SOURCE_I2S1, 11, TEGRA_PERIPH_ON_APB, TEGRA20_CLK_I2S1), @@ -802,7 +798,7 @@ static void __init tegra20_periph_clk_init(void) { struct tegra_periph_init_data *data; struct clk *clk; - int i; + unsigned int i; /* ac97 */ clk = tegra_clk_register_periph_gate("ac97", "pll_a_out0", @@ -1025,44 +1021,45 @@ static struct tegra_cpu_car_ops tegra20_cpu_car_ops = { }; static struct tegra_clk_init_table init_table[] __initdata = { - {TEGRA20_CLK_PLL_P, TEGRA20_CLK_CLK_MAX, 216000000, 1}, - {TEGRA20_CLK_PLL_P_OUT1, TEGRA20_CLK_CLK_MAX, 28800000, 1}, - {TEGRA20_CLK_PLL_P_OUT2, TEGRA20_CLK_CLK_MAX, 48000000, 1}, - {TEGRA20_CLK_PLL_P_OUT3, TEGRA20_CLK_CLK_MAX, 72000000, 1}, - {TEGRA20_CLK_PLL_P_OUT4, TEGRA20_CLK_CLK_MAX, 24000000, 1}, - {TEGRA20_CLK_PLL_C, TEGRA20_CLK_CLK_MAX, 600000000, 1}, - {TEGRA20_CLK_PLL_C_OUT1, TEGRA20_CLK_CLK_MAX, 120000000, 1}, - {TEGRA20_CLK_SCLK, TEGRA20_CLK_PLL_C_OUT1, 0, 1}, - {TEGRA20_CLK_HCLK, TEGRA20_CLK_CLK_MAX, 0, 1}, - {TEGRA20_CLK_PCLK, TEGRA20_CLK_CLK_MAX, 60000000, 1}, - {TEGRA20_CLK_CSITE, TEGRA20_CLK_CLK_MAX, 0, 1}, - {TEGRA20_CLK_EMC, TEGRA20_CLK_CLK_MAX, 0, 1}, - {TEGRA20_CLK_CCLK, TEGRA20_CLK_CLK_MAX, 0, 1}, - {TEGRA20_CLK_UARTA, TEGRA20_CLK_PLL_P, 0, 0}, - {TEGRA20_CLK_UARTB, TEGRA20_CLK_PLL_P, 0, 0}, - {TEGRA20_CLK_UARTC, TEGRA20_CLK_PLL_P, 0, 0}, - {TEGRA20_CLK_UARTD, TEGRA20_CLK_PLL_P, 0, 0}, - {TEGRA20_CLK_UARTE, TEGRA20_CLK_PLL_P, 0, 0}, - {TEGRA20_CLK_PLL_A, TEGRA20_CLK_CLK_MAX, 56448000, 1}, - {TEGRA20_CLK_PLL_A_OUT0, TEGRA20_CLK_CLK_MAX, 11289600, 1}, - {TEGRA20_CLK_CDEV1, TEGRA20_CLK_CLK_MAX, 0, 1}, - {TEGRA20_CLK_BLINK, TEGRA20_CLK_CLK_MAX, 32768, 1}, - {TEGRA20_CLK_I2S1, TEGRA20_CLK_PLL_A_OUT0, 11289600, 0}, - {TEGRA20_CLK_I2S2, TEGRA20_CLK_PLL_A_OUT0, 11289600, 0}, - {TEGRA20_CLK_SDMMC1, TEGRA20_CLK_PLL_P, 48000000, 0}, - {TEGRA20_CLK_SDMMC3, TEGRA20_CLK_PLL_P, 48000000, 0}, - {TEGRA20_CLK_SDMMC4, TEGRA20_CLK_PLL_P, 48000000, 0}, - {TEGRA20_CLK_SPI, TEGRA20_CLK_PLL_P, 20000000, 0}, - {TEGRA20_CLK_SBC1, TEGRA20_CLK_PLL_P, 100000000, 0}, - {TEGRA20_CLK_SBC2, TEGRA20_CLK_PLL_P, 100000000, 0}, - {TEGRA20_CLK_SBC3, TEGRA20_CLK_PLL_P, 100000000, 0}, - {TEGRA20_CLK_SBC4, TEGRA20_CLK_PLL_P, 100000000, 0}, - {TEGRA20_CLK_HOST1X, TEGRA20_CLK_PLL_C, 150000000, 0}, - {TEGRA20_CLK_DISP1, TEGRA20_CLK_PLL_P, 600000000, 0}, - {TEGRA20_CLK_DISP2, TEGRA20_CLK_PLL_P, 600000000, 0}, - {TEGRA20_CLK_GR2D, TEGRA20_CLK_PLL_C, 300000000, 0}, - {TEGRA20_CLK_GR3D, TEGRA20_CLK_PLL_C, 300000000, 0}, - {TEGRA20_CLK_CLK_MAX, TEGRA20_CLK_CLK_MAX, 0, 0}, /* This MUST be the last entry */ + { TEGRA20_CLK_PLL_P, TEGRA20_CLK_CLK_MAX, 216000000, 1 }, + { TEGRA20_CLK_PLL_P_OUT1, TEGRA20_CLK_CLK_MAX, 28800000, 1 }, + { TEGRA20_CLK_PLL_P_OUT2, TEGRA20_CLK_CLK_MAX, 48000000, 1 }, + { TEGRA20_CLK_PLL_P_OUT3, TEGRA20_CLK_CLK_MAX, 72000000, 1 }, + { TEGRA20_CLK_PLL_P_OUT4, TEGRA20_CLK_CLK_MAX, 24000000, 1 }, + { TEGRA20_CLK_PLL_C, TEGRA20_CLK_CLK_MAX, 600000000, 1 }, + { TEGRA20_CLK_PLL_C_OUT1, TEGRA20_CLK_CLK_MAX, 120000000, 1 }, + { TEGRA20_CLK_SCLK, TEGRA20_CLK_PLL_C_OUT1, 0, 1 }, + { TEGRA20_CLK_HCLK, TEGRA20_CLK_CLK_MAX, 0, 1 }, + { TEGRA20_CLK_PCLK, TEGRA20_CLK_CLK_MAX, 60000000, 1 }, + { TEGRA20_CLK_CSITE, TEGRA20_CLK_CLK_MAX, 0, 1 }, + { TEGRA20_CLK_EMC, TEGRA20_CLK_CLK_MAX, 0, 1 }, + { TEGRA20_CLK_CCLK, TEGRA20_CLK_CLK_MAX, 0, 1 }, + { TEGRA20_CLK_UARTA, TEGRA20_CLK_PLL_P, 0, 0 }, + { TEGRA20_CLK_UARTB, TEGRA20_CLK_PLL_P, 0, 0 }, + { TEGRA20_CLK_UARTC, TEGRA20_CLK_PLL_P, 0, 0 }, + { TEGRA20_CLK_UARTD, TEGRA20_CLK_PLL_P, 0, 0 }, + { TEGRA20_CLK_UARTE, TEGRA20_CLK_PLL_P, 0, 0 }, + { TEGRA20_CLK_PLL_A, TEGRA20_CLK_CLK_MAX, 56448000, 1 }, + { TEGRA20_CLK_PLL_A_OUT0, TEGRA20_CLK_CLK_MAX, 11289600, 1 }, + { TEGRA20_CLK_CDEV1, TEGRA20_CLK_CLK_MAX, 0, 1 }, + { TEGRA20_CLK_BLINK, TEGRA20_CLK_CLK_MAX, 32768, 1 }, + { TEGRA20_CLK_I2S1, TEGRA20_CLK_PLL_A_OUT0, 11289600, 0 }, + { TEGRA20_CLK_I2S2, TEGRA20_CLK_PLL_A_OUT0, 11289600, 0 }, + { TEGRA20_CLK_SDMMC1, TEGRA20_CLK_PLL_P, 48000000, 0 }, + { TEGRA20_CLK_SDMMC3, TEGRA20_CLK_PLL_P, 48000000, 0 }, + { TEGRA20_CLK_SDMMC4, TEGRA20_CLK_PLL_P, 48000000, 0 }, + { TEGRA20_CLK_SPI, TEGRA20_CLK_PLL_P, 20000000, 0 }, + { TEGRA20_CLK_SBC1, TEGRA20_CLK_PLL_P, 100000000, 0 }, + { TEGRA20_CLK_SBC2, TEGRA20_CLK_PLL_P, 100000000, 0 }, + { TEGRA20_CLK_SBC3, TEGRA20_CLK_PLL_P, 100000000, 0 }, + { TEGRA20_CLK_SBC4, TEGRA20_CLK_PLL_P, 100000000, 0 }, + { TEGRA20_CLK_HOST1X, TEGRA20_CLK_PLL_C, 150000000, 0 }, + { TEGRA20_CLK_DISP1, TEGRA20_CLK_PLL_P, 600000000, 0 }, + { TEGRA20_CLK_DISP2, TEGRA20_CLK_PLL_P, 600000000, 0 }, + { TEGRA20_CLK_GR2D, TEGRA20_CLK_PLL_C, 300000000, 0 }, + { TEGRA20_CLK_GR3D, TEGRA20_CLK_PLL_C, 300000000, 0 }, + /* must be the last entry */ + { TEGRA20_CLK_CLK_MAX, TEGRA20_CLK_CLK_MAX, 0, 0 }, }; static void __init tegra20_clock_apply_init_table(void) @@ -1076,16 +1073,17 @@ static void __init tegra20_clock_apply_init_table(void) * table under two names. */ static struct tegra_clk_duplicate tegra_clk_duplicates[] = { - TEGRA_CLK_DUPLICATE(TEGRA20_CLK_USBD, "utmip-pad", NULL), - TEGRA_CLK_DUPLICATE(TEGRA20_CLK_USBD, "tegra-ehci.0", NULL), - TEGRA_CLK_DUPLICATE(TEGRA20_CLK_USBD, "tegra-otg", NULL), - TEGRA_CLK_DUPLICATE(TEGRA20_CLK_CCLK, NULL, "cpu"), - TEGRA_CLK_DUPLICATE(TEGRA20_CLK_CLK_MAX, NULL, NULL), /* Must be the last entry */ + TEGRA_CLK_DUPLICATE(TEGRA20_CLK_USBD, "utmip-pad", NULL), + TEGRA_CLK_DUPLICATE(TEGRA20_CLK_USBD, "tegra-ehci.0", NULL), + TEGRA_CLK_DUPLICATE(TEGRA20_CLK_USBD, "tegra-otg", NULL), + TEGRA_CLK_DUPLICATE(TEGRA20_CLK_CCLK, NULL, "cpu"), + /* must be the last entry */ + TEGRA_CLK_DUPLICATE(TEGRA20_CLK_CLK_MAX, NULL, NULL), }; static const struct of_device_id pmc_match[] __initconst = { { .compatible = "nvidia,tegra20-pmc" }, - {}, + { }, }; static void __init tegra20_clock_init(struct device_node *np) diff --git a/drivers/clk/tegra/clk-tegra210.c b/drivers/clk/tegra/clk-tegra210.c new file mode 100644 index 000000000..637041fd5 --- /dev/null +++ b/drivers/clk/tegra/clk-tegra210.c @@ -0,0 +1,2840 @@ +/* + * Copyright (c) 2012-2014 NVIDIA CORPORATION. All rights reserved. + * + * 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/>. + */ + +#include <linux/io.h> +#include <linux/clk.h> +#include <linux/clk-provider.h> +#include <linux/clkdev.h> +#include <linux/of.h> +#include <linux/of_address.h> +#include <linux/delay.h> +#include <linux/export.h> +#include <linux/clk/tegra.h> +#include <dt-bindings/clock/tegra210-car.h> + +#include "clk.h" +#include "clk-id.h" + +/* + * TEGRA210_CAR_BANK_COUNT: the number of peripheral clock register + * banks present in the Tegra210 CAR IP block. The banks are + * identified by single letters, e.g.: L, H, U, V, W, X, Y. See + * periph_regs[] in drivers/clk/tegra/clk.c + */ +#define TEGRA210_CAR_BANK_COUNT 7 + +#define CLK_SOURCE_CSITE 0x1d4 +#define CLK_SOURCE_EMC 0x19c + +#define PLLC_BASE 0x80 +#define PLLC_OUT 0x84 +#define PLLC_MISC0 0x88 +#define PLLC_MISC1 0x8c +#define PLLC_MISC2 0x5d0 +#define PLLC_MISC3 0x5d4 + +#define PLLC2_BASE 0x4e8 +#define PLLC2_MISC0 0x4ec +#define PLLC2_MISC1 0x4f0 +#define PLLC2_MISC2 0x4f4 +#define PLLC2_MISC3 0x4f8 + +#define PLLC3_BASE 0x4fc +#define PLLC3_MISC0 0x500 +#define PLLC3_MISC1 0x504 +#define PLLC3_MISC2 0x508 +#define PLLC3_MISC3 0x50c + +#define PLLM_BASE 0x90 +#define PLLM_MISC1 0x98 +#define PLLM_MISC2 0x9c +#define PLLP_BASE 0xa0 +#define PLLP_MISC0 0xac +#define PLLP_MISC1 0x680 +#define PLLA_BASE 0xb0 +#define PLLA_MISC0 0xbc +#define PLLA_MISC1 0xb8 +#define PLLA_MISC2 0x5d8 +#define PLLD_BASE 0xd0 +#define PLLD_MISC0 0xdc +#define PLLD_MISC1 0xd8 +#define PLLU_BASE 0xc0 +#define PLLU_OUTA 0xc4 +#define PLLU_MISC0 0xcc +#define PLLU_MISC1 0xc8 +#define PLLX_BASE 0xe0 +#define PLLX_MISC0 0xe4 +#define PLLX_MISC1 0x510 +#define PLLX_MISC2 0x514 +#define PLLX_MISC3 0x518 +#define PLLX_MISC4 0x5f0 +#define PLLX_MISC5 0x5f4 +#define PLLE_BASE 0xe8 +#define PLLE_MISC0 0xec +#define PLLD2_BASE 0x4b8 +#define PLLD2_MISC0 0x4bc +#define PLLD2_MISC1 0x570 +#define PLLD2_MISC2 0x574 +#define PLLD2_MISC3 0x578 +#define PLLE_AUX 0x48c +#define PLLRE_BASE 0x4c4 +#define PLLRE_MISC0 0x4c8 +#define PLLDP_BASE 0x590 +#define PLLDP_MISC 0x594 + +#define PLLC4_BASE 0x5a4 +#define PLLC4_MISC0 0x5a8 +#define PLLC4_OUT 0x5e4 +#define PLLMB_BASE 0x5e8 +#define PLLMB_MISC1 0x5ec +#define PLLA1_BASE 0x6a4 +#define PLLA1_MISC0 0x6a8 +#define PLLA1_MISC1 0x6ac +#define PLLA1_MISC2 0x6b0 +#define PLLA1_MISC3 0x6b4 + +#define PLLU_IDDQ_BIT 31 +#define PLLCX_IDDQ_BIT 27 +#define PLLRE_IDDQ_BIT 24 +#define PLLA_IDDQ_BIT 25 +#define PLLD_IDDQ_BIT 20 +#define PLLSS_IDDQ_BIT 18 +#define PLLM_IDDQ_BIT 5 +#define PLLMB_IDDQ_BIT 17 +#define PLLXP_IDDQ_BIT 3 + +#define PLLCX_RESET_BIT 30 + +#define PLL_BASE_LOCK BIT(27) +#define PLLCX_BASE_LOCK BIT(26) +#define PLLE_MISC_LOCK BIT(11) +#define PLLRE_MISC_LOCK BIT(27) + +#define PLL_MISC_LOCK_ENABLE 18 +#define PLLC_MISC_LOCK_ENABLE 24 +#define PLLDU_MISC_LOCK_ENABLE 22 +#define PLLU_MISC_LOCK_ENABLE 29 +#define PLLE_MISC_LOCK_ENABLE 9 +#define PLLRE_MISC_LOCK_ENABLE 30 +#define PLLSS_MISC_LOCK_ENABLE 30 +#define PLLP_MISC_LOCK_ENABLE 18 +#define PLLM_MISC_LOCK_ENABLE 4 +#define PLLMB_MISC_LOCK_ENABLE 16 +#define PLLA_MISC_LOCK_ENABLE 28 +#define PLLU_MISC_LOCK_ENABLE 29 +#define PLLD_MISC_LOCK_ENABLE 18 + +#define PLLA_SDM_DIN_MASK 0xffff +#define PLLA_SDM_EN_MASK BIT(26) + +#define PLLD_SDM_EN_MASK BIT(16) + +#define PLLD2_SDM_EN_MASK BIT(31) +#define PLLD2_SSC_EN_MASK BIT(30) + +#define PLLDP_SS_CFG 0x598 +#define PLLDP_SDM_EN_MASK BIT(31) +#define PLLDP_SSC_EN_MASK BIT(30) +#define PLLDP_SS_CTRL1 0x59c +#define PLLDP_SS_CTRL2 0x5a0 + +#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 UTMIPLL_HW_PWRDN_CFG0 0x52c +#define UTMIPLL_HW_PWRDN_CFG0_UTMIPLL_LOCK BIT(31) +#define UTMIPLL_HW_PWRDN_CFG0_SEQ_START_STATE BIT(25) +#define UTMIPLL_HW_PWRDN_CFG0_SEQ_ENABLE BIT(24) +#define UTMIPLL_HW_PWRDN_CFG0_IDDQ_PD_INCLUDE BIT(7) +#define UTMIPLL_HW_PWRDN_CFG0_USE_LOCKDET BIT(6) +#define UTMIPLL_HW_PWRDN_CFG0_SEQ_RESET_INPUT_VALUE BIT(5) +#define UTMIPLL_HW_PWRDN_CFG0_SEQ_IN_SWCTL BIT(4) +#define UTMIPLL_HW_PWRDN_CFG0_CLK_ENABLE_SWCTL BIT(2) +#define UTMIPLL_HW_PWRDN_CFG0_IDDQ_OVERRIDE BIT(1) +#define UTMIPLL_HW_PWRDN_CFG0_IDDQ_SWCTL BIT(0) + +#define PLLU_HW_PWRDN_CFG0 0x530 +#define PLLU_HW_PWRDN_CFG0_IDDQ_PD_INCLUDE BIT(28) +#define PLLU_HW_PWRDN_CFG0_SEQ_ENABLE BIT(24) +#define PLLU_HW_PWRDN_CFG0_USE_SWITCH_DETECT BIT(7) +#define PLLU_HW_PWRDN_CFG0_USE_LOCKDET BIT(6) +#define PLLU_HW_PWRDN_CFG0_CLK_ENABLE_SWCTL BIT(2) +#define PLLU_HW_PWRDN_CFG0_CLK_SWITCH_SWCTL BIT(0) + +#define XUSB_PLL_CFG0 0x534 +#define XUSB_PLL_CFG0_UTMIPLL_LOCK_DLY 0x3ff +#define XUSB_PLL_CFG0_PLLU_LOCK_DLY_MASK (0x3ff << 14) + +#define SPARE_REG0 0x55c +#define CLK_M_DIVISOR_SHIFT 2 +#define CLK_M_DIVISOR_MASK 0x3 + +/* + * 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 + * 16-bit value, with "0" divisor mapped to 0xFFFF. Data "0" is used to + * indicate that SDM is disabled. + * + * Effective ndiv value when SDM is enabled: ndiv + 1/2 + sdm_din/2^13 + */ +#define PLL_SDM_COEFF BIT(13) +#define sdin_din_to_data(din) ((u16)((din) ? : 0xFFFFU)) +#define sdin_data_to_din(dat) (((dat) == 0xFFFFU) ? 0 : (s16)dat) + +/* Tegra CPU clock and reset control regs */ +#define CLK_RST_CONTROLLER_CPU_CMPLX_STATUS 0x470 + +#ifdef CONFIG_PM_SLEEP +static struct cpu_clk_suspend_context { + u32 clk_csite_src; +} tegra210_cpu_clk_sctx; +#endif + +static void __iomem *clk_base; +static void __iomem *pmc_base; + +static unsigned long osc_freq; +static unsigned long pll_ref_freq; + +static DEFINE_SPINLOCK(pll_d_lock); +static DEFINE_SPINLOCK(pll_e_lock); +static DEFINE_SPINLOCK(pll_re_lock); +static DEFINE_SPINLOCK(pll_u_lock); +static DEFINE_SPINLOCK(emc_lock); + +/* possible OSC frequencies in Hz */ +static unsigned long tegra210_input_freq[] = { + [5] = 38400000, + [8] = 12000000, +}; + +static const char *mux_pllmcp_clkm[] = { + "pll_m", "pll_c", "pll_p", "clk_m", "pll_m_ud", "pll_mb", "pll_mb", + "pll_p", +}; +#define mux_pllmcp_clkm_idx NULL + +#define PLL_ENABLE (1 << 30) + +#define PLLCX_MISC1_IDDQ (1 << 27) +#define PLLCX_MISC0_RESET (1 << 30) + +#define PLLCX_MISC0_DEFAULT_VALUE 0x40080000 +#define PLLCX_MISC0_WRITE_MASK 0x400ffffb +#define PLLCX_MISC1_DEFAULT_VALUE 0x08000000 +#define PLLCX_MISC1_WRITE_MASK 0x08003cff +#define PLLCX_MISC2_DEFAULT_VALUE 0x1f720f05 +#define PLLCX_MISC2_WRITE_MASK 0xffffff17 +#define PLLCX_MISC3_DEFAULT_VALUE 0x000000c4 +#define PLLCX_MISC3_WRITE_MASK 0x00ffffff + +/* PLLA */ +#define PLLA_BASE_IDDQ (1 << 25) +#define PLLA_BASE_LOCK (1 << 27) + +#define PLLA_MISC0_LOCK_ENABLE (1 << 28) +#define PLLA_MISC0_LOCK_OVERRIDE (1 << 27) + +#define PLLA_MISC2_EN_SDM (1 << 26) +#define PLLA_MISC2_EN_DYNRAMP (1 << 25) + +#define PLLA_MISC0_DEFAULT_VALUE 0x12000020 +#define PLLA_MISC0_WRITE_MASK 0x7fffffff +#define PLLA_MISC2_DEFAULT_VALUE 0x0 +#define PLLA_MISC2_WRITE_MASK 0x06ffffff + +/* PLLD */ +#define PLLD_MISC0_EN_SDM (1 << 16) +#define PLLD_MISC0_LOCK_OVERRIDE (1 << 17) +#define PLLD_MISC0_LOCK_ENABLE (1 << 18) +#define PLLD_MISC0_IDDQ (1 << 20) +#define PLLD_MISC0_DSI_CLKENABLE (1 << 21) + +#define PLLD_MISC0_DEFAULT_VALUE 0x00140000 +#define PLLD_MISC0_WRITE_MASK 0x3ff7ffff +#define PLLD_MISC1_DEFAULT_VALUE 0x20 +#define PLLD_MISC1_WRITE_MASK 0x00ffffff + +/* PLLD2 and PLLDP and PLLC4 */ +#define PLLDSS_BASE_LOCK (1 << 27) +#define PLLDSS_BASE_LOCK_OVERRIDE (1 << 24) +#define PLLDSS_BASE_IDDQ (1 << 18) +#define PLLDSS_BASE_REF_SEL_SHIFT 25 +#define PLLDSS_BASE_REF_SEL_MASK (0x3 << PLLDSS_BASE_REF_SEL_SHIFT) + +#define PLLDSS_MISC0_LOCK_ENABLE (1 << 30) + +#define PLLDSS_MISC1_CFG_EN_SDM (1 << 31) +#define PLLDSS_MISC1_CFG_EN_SSC (1 << 30) + +#define PLLD2_MISC0_DEFAULT_VALUE 0x40000020 +#define PLLD2_MISC1_CFG_DEFAULT_VALUE 0x10000000 +#define PLLD2_MISC2_CTRL1_DEFAULT_VALUE 0x0 +#define PLLD2_MISC3_CTRL2_DEFAULT_VALUE 0x0 + +#define PLLDP_MISC0_DEFAULT_VALUE 0x40000020 +#define PLLDP_MISC1_CFG_DEFAULT_VALUE 0xc0000000 +#define PLLDP_MISC2_CTRL1_DEFAULT_VALUE 0xf400f0da +#define PLLDP_MISC3_CTRL2_DEFAULT_VALUE 0x2004f400 + +#define PLLDSS_MISC0_WRITE_MASK 0x47ffffff +#define PLLDSS_MISC1_CFG_WRITE_MASK 0xf8000000 +#define PLLDSS_MISC2_CTRL1_WRITE_MASK 0xffffffff +#define PLLDSS_MISC3_CTRL2_WRITE_MASK 0xffffffff + +#define PLLC4_MISC0_DEFAULT_VALUE 0x40000000 + +/* PLLRE */ +#define PLLRE_MISC0_LOCK_ENABLE (1 << 30) +#define PLLRE_MISC0_LOCK_OVERRIDE (1 << 29) +#define PLLRE_MISC0_LOCK (1 << 27) +#define PLLRE_MISC0_IDDQ (1 << 24) + +#define PLLRE_BASE_DEFAULT_VALUE 0x0 +#define PLLRE_MISC0_DEFAULT_VALUE 0x41000000 + +#define PLLRE_BASE_DEFAULT_MASK 0x1c000000 +#define PLLRE_MISC0_WRITE_MASK 0x67ffffff + +/* PLLX */ +#define PLLX_USE_DYN_RAMP 1 +#define PLLX_BASE_LOCK (1 << 27) + +#define PLLX_MISC0_FO_G_DISABLE (0x1 << 28) +#define PLLX_MISC0_LOCK_ENABLE (0x1 << 18) + +#define PLLX_MISC2_DYNRAMP_STEPB_SHIFT 24 +#define PLLX_MISC2_DYNRAMP_STEPB_MASK (0xFF << PLLX_MISC2_DYNRAMP_STEPB_SHIFT) +#define PLLX_MISC2_DYNRAMP_STEPA_SHIFT 16 +#define PLLX_MISC2_DYNRAMP_STEPA_MASK (0xFF << PLLX_MISC2_DYNRAMP_STEPA_SHIFT) +#define PLLX_MISC2_NDIV_NEW_SHIFT 8 +#define PLLX_MISC2_NDIV_NEW_MASK (0xFF << PLLX_MISC2_NDIV_NEW_SHIFT) +#define PLLX_MISC2_LOCK_OVERRIDE (0x1 << 4) +#define PLLX_MISC2_DYNRAMP_DONE (0x1 << 2) +#define PLLX_MISC2_EN_DYNRAMP (0x1 << 0) + +#define PLLX_MISC3_IDDQ (0x1 << 3) + +#define PLLX_MISC0_DEFAULT_VALUE PLLX_MISC0_LOCK_ENABLE +#define PLLX_MISC0_WRITE_MASK 0x10c40000 +#define PLLX_MISC1_DEFAULT_VALUE 0x20 +#define PLLX_MISC1_WRITE_MASK 0x00ffffff +#define PLLX_MISC2_DEFAULT_VALUE 0x0 +#define PLLX_MISC2_WRITE_MASK 0xffffff11 +#define PLLX_MISC3_DEFAULT_VALUE PLLX_MISC3_IDDQ +#define PLLX_MISC3_WRITE_MASK 0x01ff0f0f +#define PLLX_MISC4_DEFAULT_VALUE 0x0 +#define PLLX_MISC4_WRITE_MASK 0x8000ffff +#define PLLX_MISC5_DEFAULT_VALUE 0x0 +#define PLLX_MISC5_WRITE_MASK 0x0000ffff + +#define PLLX_HW_CTRL_CFG 0x548 +#define PLLX_HW_CTRL_CFG_SWCTRL (0x1 << 0) + +/* PLLMB */ +#define PLLMB_BASE_LOCK (1 << 27) + +#define PLLMB_MISC1_LOCK_OVERRIDE (1 << 18) +#define PLLMB_MISC1_IDDQ (1 << 17) +#define PLLMB_MISC1_LOCK_ENABLE (1 << 16) + +#define PLLMB_MISC1_DEFAULT_VALUE 0x00030000 +#define PLLMB_MISC1_WRITE_MASK 0x0007ffff + +/* PLLP */ +#define PLLP_BASE_OVERRIDE (1 << 28) +#define PLLP_BASE_LOCK (1 << 27) + +#define PLLP_MISC0_LOCK_ENABLE (1 << 18) +#define PLLP_MISC0_LOCK_OVERRIDE (1 << 17) +#define PLLP_MISC0_IDDQ (1 << 3) + +#define PLLP_MISC1_HSIO_EN_SHIFT 29 +#define PLLP_MISC1_HSIO_EN (1 << PLLP_MISC1_HSIO_EN_SHIFT) +#define PLLP_MISC1_XUSB_EN_SHIFT 28 +#define PLLP_MISC1_XUSB_EN (1 << PLLP_MISC1_XUSB_EN_SHIFT) + +#define PLLP_MISC0_DEFAULT_VALUE 0x00040008 +#define PLLP_MISC1_DEFAULT_VALUE 0x0 + +#define PLLP_MISC0_WRITE_MASK 0xdc6000f +#define PLLP_MISC1_WRITE_MASK 0x70ffffff + +/* PLLU */ +#define PLLU_BASE_LOCK (1 << 27) +#define PLLU_BASE_OVERRIDE (1 << 24) +#define PLLU_BASE_CLKENABLE_USB (1 << 21) +#define PLLU_BASE_CLKENABLE_HSIC (1 << 22) +#define PLLU_BASE_CLKENABLE_ICUSB (1 << 23) +#define PLLU_BASE_CLKENABLE_48M (1 << 25) +#define PLLU_BASE_CLKENABLE_ALL (PLLU_BASE_CLKENABLE_USB |\ + PLLU_BASE_CLKENABLE_HSIC |\ + PLLU_BASE_CLKENABLE_ICUSB |\ + PLLU_BASE_CLKENABLE_48M) + +#define PLLU_MISC0_IDDQ (1 << 31) +#define PLLU_MISC0_LOCK_ENABLE (1 << 29) +#define PLLU_MISC1_LOCK_OVERRIDE (1 << 0) + +#define PLLU_MISC0_DEFAULT_VALUE 0xa0000000 +#define PLLU_MISC1_DEFAULT_VALUE 0x0 + +#define PLLU_MISC0_WRITE_MASK 0xbfffffff +#define PLLU_MISC1_WRITE_MASK 0x00000007 + +static inline void _pll_misc_chk_default(void __iomem *base, + struct tegra_clk_pll_params *params, + u8 misc_num, u32 default_val, u32 mask) +{ + u32 boot_val = readl_relaxed(base + params->ext_misc_reg[misc_num]); + + boot_val &= mask; + default_val &= mask; + if (boot_val != default_val) { + pr_warn("boot misc%d 0x%x: expected 0x%x\n", + misc_num, boot_val, default_val); + pr_warn(" (comparison mask = 0x%x)\n", mask); + params->defaults_set = false; + } +} + +/* + * PLLCX: PLLC, PLLC2, PLLC3, PLLA1 + * Hybrid PLLs with dynamic ramp. Dynamic ramp is allowed for any transition + * that changes NDIV only, while PLL is already locked. + */ +static void pllcx_check_defaults(struct tegra_clk_pll_params *params) +{ + u32 default_val; + + default_val = PLLCX_MISC0_DEFAULT_VALUE & (~PLLCX_MISC0_RESET); + _pll_misc_chk_default(clk_base, params, 0, default_val, + PLLCX_MISC0_WRITE_MASK); + + default_val = PLLCX_MISC1_DEFAULT_VALUE & (~PLLCX_MISC1_IDDQ); + _pll_misc_chk_default(clk_base, params, 1, default_val, + PLLCX_MISC1_WRITE_MASK); + + default_val = PLLCX_MISC2_DEFAULT_VALUE; + _pll_misc_chk_default(clk_base, params, 2, default_val, + PLLCX_MISC2_WRITE_MASK); + + default_val = PLLCX_MISC3_DEFAULT_VALUE; + _pll_misc_chk_default(clk_base, params, 3, default_val, + PLLCX_MISC3_WRITE_MASK); +} + +static void tegra210_pllcx_set_defaults(const char *name, + struct tegra_clk_pll *pllcx) +{ + pllcx->params->defaults_set = true; + + 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); + return; + } + + /* Defaults assert PLL reset, and set IDDQ */ + writel_relaxed(PLLCX_MISC0_DEFAULT_VALUE, + clk_base + pllcx->params->ext_misc_reg[0]); + writel_relaxed(PLLCX_MISC1_DEFAULT_VALUE, + clk_base + pllcx->params->ext_misc_reg[1]); + writel_relaxed(PLLCX_MISC2_DEFAULT_VALUE, + clk_base + pllcx->params->ext_misc_reg[2]); + writel_relaxed(PLLCX_MISC3_DEFAULT_VALUE, + clk_base + pllcx->params->ext_misc_reg[3]); + udelay(1); +} + +static void _pllc_set_defaults(struct tegra_clk_pll *pllcx) +{ + tegra210_pllcx_set_defaults("PLL_C", pllcx); +} + +static void _pllc2_set_defaults(struct tegra_clk_pll *pllcx) +{ + tegra210_pllcx_set_defaults("PLL_C2", pllcx); +} + +static void _pllc3_set_defaults(struct tegra_clk_pll *pllcx) +{ + tegra210_pllcx_set_defaults("PLL_C3", pllcx); +} + +static void _plla1_set_defaults(struct tegra_clk_pll *pllcx) +{ + tegra210_pllcx_set_defaults("PLL_A1", pllcx); +} + +/* + * PLLA + * PLL with dynamic ramp and fractional SDM. Dynamic ramp is not used. + * Fractional SDM is allowed to provide exact audio rates. + */ +static void tegra210_plla_set_defaults(struct tegra_clk_pll *plla) +{ + u32 mask; + u32 val = readl_relaxed(clk_base + plla->params->base_reg); + + plla->params->defaults_set = true; + + if (val & PLL_ENABLE) { + /* + * PLL is ON: check if defaults already set, then set those + * that can be updated in flight. + */ + if (val & PLLA_BASE_IDDQ) { + pr_warn("PLL_A boot enabled with IDDQ set\n"); + plla->params->defaults_set = false; + } + + pr_warn("PLL_A already enabled. Postponing set full defaults\n"); + + val = PLLA_MISC0_DEFAULT_VALUE; /* ignore lock enable */ + mask = PLLA_MISC0_LOCK_ENABLE | PLLA_MISC0_LOCK_OVERRIDE; + _pll_misc_chk_default(clk_base, plla->params, 0, val, + ~mask & PLLA_MISC0_WRITE_MASK); + + val = PLLA_MISC2_DEFAULT_VALUE; /* ignore all but control bit */ + _pll_misc_chk_default(clk_base, plla->params, 2, val, + PLLA_MISC2_EN_DYNRAMP); + + /* Enable lock detect */ + val = readl_relaxed(clk_base + plla->params->ext_misc_reg[0]); + val &= ~mask; + val |= PLLA_MISC0_DEFAULT_VALUE & mask; + writel_relaxed(val, clk_base + plla->params->ext_misc_reg[0]); + udelay(1); + + return; + } + + /* set IDDQ, enable lock detect, disable dynamic ramp and SDM */ + val |= PLLA_BASE_IDDQ; + writel_relaxed(val, clk_base + plla->params->base_reg); + writel_relaxed(PLLA_MISC0_DEFAULT_VALUE, + clk_base + plla->params->ext_misc_reg[0]); + writel_relaxed(PLLA_MISC2_DEFAULT_VALUE, + clk_base + plla->params->ext_misc_reg[2]); + udelay(1); +} + +/* + * PLLD + * PLL with fractional SDM. + */ +static void tegra210_plld_set_defaults(struct tegra_clk_pll *plld) +{ + u32 val; + u32 mask = 0xffff; + + plld->params->defaults_set = true; + + 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 + * that can be updated in flight. + */ + val = PLLD_MISC1_DEFAULT_VALUE; + _pll_misc_chk_default(clk_base, plld->params, 1, + val, PLLD_MISC1_WRITE_MASK); + + /* ignore lock, DSI and SDM controls, make sure IDDQ not set */ + val = PLLD_MISC0_DEFAULT_VALUE & (~PLLD_MISC0_IDDQ); + mask |= PLLD_MISC0_DSI_CLKENABLE | PLLD_MISC0_LOCK_ENABLE | + PLLD_MISC0_LOCK_OVERRIDE | PLLD_MISC0_EN_SDM; + _pll_misc_chk_default(clk_base, plld->params, 0, val, + ~mask & PLLD_MISC0_WRITE_MASK); + + /* Enable lock detect */ + mask = PLLD_MISC0_LOCK_ENABLE | PLLD_MISC0_LOCK_OVERRIDE; + val = readl_relaxed(clk_base + plld->params->ext_misc_reg[0]); + val &= ~mask; + val |= PLLD_MISC0_DEFAULT_VALUE & mask; + writel_relaxed(val, clk_base + plld->params->ext_misc_reg[0]); + udelay(1); + + return; + } + + val = readl_relaxed(clk_base + plld->params->ext_misc_reg[0]); + val &= PLLD_MISC0_DSI_CLKENABLE; + val |= PLLD_MISC0_DEFAULT_VALUE; + /* set IDDQ, enable lock detect, disable SDM */ + writel_relaxed(val, clk_base + plld->params->ext_misc_reg[0]); + writel_relaxed(PLLD_MISC1_DEFAULT_VALUE, clk_base + + plld->params->ext_misc_reg[1]); + udelay(1); +} + +/* + * PLLD2, PLLDP + * PLL with fractional SDM and Spread Spectrum (SDM is a must if SSC is used). + */ +static void plldss_defaults(const char *pll_name, struct tegra_clk_pll *plldss, + u32 misc0_val, u32 misc1_val, u32 misc2_val, u32 misc3_val) +{ + u32 default_val; + u32 val = readl_relaxed(clk_base + plldss->params->base_reg); + + plldss->params->defaults_set = true; + + if (val & PLL_ENABLE) { + pr_warn("%s already enabled. Postponing set full defaults\n", + pll_name); + + /* + * PLL is ON: check if defaults already set, then set those + * that can be updated in flight. + */ + if (val & PLLDSS_BASE_IDDQ) { + pr_warn("plldss boot enabled with IDDQ set\n"); + plldss->params->defaults_set = false; + } + + /* ignore lock enable */ + default_val = misc0_val; + _pll_misc_chk_default(clk_base, plldss->params, 0, default_val, + PLLDSS_MISC0_WRITE_MASK & + (~PLLDSS_MISC0_LOCK_ENABLE)); + + /* + * If SSC is used, check all settings, otherwise just confirm + * that SSC is not used on boot as well. Do nothing when using + * this function for PLLC4 that has only MISC0. + */ + if (plldss->params->ssc_ctrl_en_mask) { + default_val = misc1_val; + _pll_misc_chk_default(clk_base, plldss->params, 1, + default_val, PLLDSS_MISC1_CFG_WRITE_MASK); + default_val = misc2_val; + _pll_misc_chk_default(clk_base, plldss->params, 2, + default_val, PLLDSS_MISC2_CTRL1_WRITE_MASK); + default_val = misc3_val; + _pll_misc_chk_default(clk_base, plldss->params, 3, + default_val, PLLDSS_MISC3_CTRL2_WRITE_MASK); + } else if (plldss->params->ext_misc_reg[1]) { + default_val = misc1_val; + _pll_misc_chk_default(clk_base, plldss->params, 1, + default_val, PLLDSS_MISC1_CFG_WRITE_MASK & + (~PLLDSS_MISC1_CFG_EN_SDM)); + } + + /* Enable lock detect */ + if (val & PLLDSS_BASE_LOCK_OVERRIDE) { + val &= ~PLLDSS_BASE_LOCK_OVERRIDE; + writel_relaxed(val, clk_base + + plldss->params->base_reg); + } + + val = readl_relaxed(clk_base + plldss->params->ext_misc_reg[0]); + val &= ~PLLDSS_MISC0_LOCK_ENABLE; + val |= misc0_val & PLLDSS_MISC0_LOCK_ENABLE; + writel_relaxed(val, clk_base + plldss->params->ext_misc_reg[0]); + udelay(1); + + return; + } + + /* set IDDQ, enable lock detect, configure SDM/SSC */ + val |= PLLDSS_BASE_IDDQ; + val &= ~PLLDSS_BASE_LOCK_OVERRIDE; + writel_relaxed(val, clk_base + plldss->params->base_reg); + + /* When using this function for PLLC4 exit here */ + if (!plldss->params->ext_misc_reg[1]) { + writel_relaxed(misc0_val, clk_base + + plldss->params->ext_misc_reg[0]); + udelay(1); + return; + } + + writel_relaxed(misc0_val, clk_base + + plldss->params->ext_misc_reg[0]); + /* if SSC used set by 1st enable */ + writel_relaxed(misc1_val & (~PLLDSS_MISC1_CFG_EN_SSC), + clk_base + plldss->params->ext_misc_reg[1]); + writel_relaxed(misc2_val, clk_base + plldss->params->ext_misc_reg[2]); + writel_relaxed(misc3_val, clk_base + plldss->params->ext_misc_reg[3]); + udelay(1); +} + +static void tegra210_plld2_set_defaults(struct tegra_clk_pll *plld2) +{ + plldss_defaults("PLL_D2", plld2, PLLD2_MISC0_DEFAULT_VALUE, + PLLD2_MISC1_CFG_DEFAULT_VALUE, + PLLD2_MISC2_CTRL1_DEFAULT_VALUE, + PLLD2_MISC3_CTRL2_DEFAULT_VALUE); +} + +static void tegra210_plldp_set_defaults(struct tegra_clk_pll *plldp) +{ + plldss_defaults("PLL_DP", plldp, PLLDP_MISC0_DEFAULT_VALUE, + PLLDP_MISC1_CFG_DEFAULT_VALUE, + PLLDP_MISC2_CTRL1_DEFAULT_VALUE, + PLLDP_MISC3_CTRL2_DEFAULT_VALUE); +} + +/* + * PLLC4 + * Base and misc0 layout is the same as PLLD2/PLLDP, but no SDM/SSC support. + * VCO is exposed to the clock tree via fixed 1/3 and 1/5 dividers. + */ +static void tegra210_pllc4_set_defaults(struct tegra_clk_pll *pllc4) +{ + plldss_defaults("PLL_C4", pllc4, PLLC4_MISC0_DEFAULT_VALUE, 0, 0, 0); +} + +/* + * PLLRE + * VCO is exposed to the clock tree directly along with post-divider output + */ +static void tegra210_pllre_set_defaults(struct tegra_clk_pll *pllre) +{ + u32 mask; + u32 val = readl_relaxed(clk_base + pllre->params->base_reg); + + pllre->params->defaults_set = true; + + if (val & PLL_ENABLE) { + pr_warn("PLL_RE already enabled. Postponing set full defaults\n"); + + /* + * PLL is ON: check if defaults already set, then set those + * that can be updated in flight. + */ + val &= PLLRE_BASE_DEFAULT_MASK; + if (val != PLLRE_BASE_DEFAULT_VALUE) { + pr_warn("pllre boot base 0x%x : expected 0x%x\n", + val, PLLRE_BASE_DEFAULT_VALUE); + pr_warn("(comparison mask = 0x%x)\n", + PLLRE_BASE_DEFAULT_MASK); + pllre->params->defaults_set = false; + } + + /* Ignore lock enable */ + val = PLLRE_MISC0_DEFAULT_VALUE & (~PLLRE_MISC0_IDDQ); + mask = PLLRE_MISC0_LOCK_ENABLE | PLLRE_MISC0_LOCK_OVERRIDE; + _pll_misc_chk_default(clk_base, pllre->params, 0, val, + ~mask & PLLRE_MISC0_WRITE_MASK); + + /* Enable lock detect */ + val = readl_relaxed(clk_base + pllre->params->ext_misc_reg[0]); + val &= ~mask; + val |= PLLRE_MISC0_DEFAULT_VALUE & mask; + writel_relaxed(val, clk_base + pllre->params->ext_misc_reg[0]); + udelay(1); + + return; + } + + /* set IDDQ, enable lock detect */ + val &= ~PLLRE_BASE_DEFAULT_MASK; + val |= PLLRE_BASE_DEFAULT_VALUE & PLLRE_BASE_DEFAULT_MASK; + writel_relaxed(val, clk_base + pllre->params->base_reg); + writel_relaxed(PLLRE_MISC0_DEFAULT_VALUE, + clk_base + pllre->params->ext_misc_reg[0]); + udelay(1); +} + +static void pllx_get_dyn_steps(struct clk_hw *hw, u32 *step_a, u32 *step_b) +{ + unsigned long input_rate; + + /* cf rate */ + if (!IS_ERR_OR_NULL(hw->clk)) + input_rate = clk_hw_get_rate(clk_hw_get_parent(hw)); + else + input_rate = 38400000; + + input_rate /= tegra_pll_get_fixed_mdiv(hw, input_rate); + + switch (input_rate) { + case 12000000: + case 12800000: + case 13000000: + *step_a = 0x2B; + *step_b = 0x0B; + return; + case 19200000: + *step_a = 0x12; + *step_b = 0x08; + return; + case 38400000: + *step_a = 0x04; + *step_b = 0x05; + return; + default: + pr_err("%s: Unexpected reference rate %lu\n", + __func__, input_rate); + BUG(); + } +} + +static void pllx_check_defaults(struct tegra_clk_pll *pll) +{ + u32 default_val; + + default_val = PLLX_MISC0_DEFAULT_VALUE; + /* ignore lock enable */ + _pll_misc_chk_default(clk_base, pll->params, 0, default_val, + PLLX_MISC0_WRITE_MASK & (~PLLX_MISC0_LOCK_ENABLE)); + + default_val = PLLX_MISC1_DEFAULT_VALUE; + _pll_misc_chk_default(clk_base, pll->params, 1, default_val, + PLLX_MISC1_WRITE_MASK); + + /* ignore all but control bit */ + default_val = PLLX_MISC2_DEFAULT_VALUE; + _pll_misc_chk_default(clk_base, pll->params, 2, + default_val, PLLX_MISC2_EN_DYNRAMP); + + default_val = PLLX_MISC3_DEFAULT_VALUE & (~PLLX_MISC3_IDDQ); + _pll_misc_chk_default(clk_base, pll->params, 3, default_val, + PLLX_MISC3_WRITE_MASK); + + default_val = PLLX_MISC4_DEFAULT_VALUE; + _pll_misc_chk_default(clk_base, pll->params, 4, default_val, + PLLX_MISC4_WRITE_MASK); + + default_val = PLLX_MISC5_DEFAULT_VALUE; + _pll_misc_chk_default(clk_base, pll->params, 5, default_val, + PLLX_MISC5_WRITE_MASK); +} + +static void tegra210_pllx_set_defaults(struct tegra_clk_pll *pllx) +{ + u32 val; + u32 step_a, step_b; + + pllx->params->defaults_set = true; + + /* Get ready dyn ramp state machine settings */ + pllx_get_dyn_steps(&pllx->hw, &step_a, &step_b); + val = PLLX_MISC2_DEFAULT_VALUE & (~PLLX_MISC2_DYNRAMP_STEPA_MASK) & + (~PLLX_MISC2_DYNRAMP_STEPB_MASK); + val |= step_a << PLLX_MISC2_DYNRAMP_STEPA_SHIFT; + 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 + * that can be updated in flight. + */ + pllx_check_defaults(pllx); + + /* Configure dyn ramp, disable lock override */ + writel_relaxed(val, clk_base + pllx->params->ext_misc_reg[2]); + + /* Enable lock detect */ + val = readl_relaxed(clk_base + pllx->params->ext_misc_reg[0]); + val &= ~PLLX_MISC0_LOCK_ENABLE; + val |= PLLX_MISC0_DEFAULT_VALUE & PLLX_MISC0_LOCK_ENABLE; + writel_relaxed(val, clk_base + pllx->params->ext_misc_reg[0]); + udelay(1); + + return; + } + + /* Enable lock detect and CPU output */ + writel_relaxed(PLLX_MISC0_DEFAULT_VALUE, clk_base + + pllx->params->ext_misc_reg[0]); + + /* Setup */ + writel_relaxed(PLLX_MISC1_DEFAULT_VALUE, clk_base + + pllx->params->ext_misc_reg[1]); + + /* Configure dyn ramp state machine, disable lock override */ + writel_relaxed(val, clk_base + pllx->params->ext_misc_reg[2]); + + /* Set IDDQ */ + writel_relaxed(PLLX_MISC3_DEFAULT_VALUE, clk_base + + pllx->params->ext_misc_reg[3]); + + /* Disable SDM */ + writel_relaxed(PLLX_MISC4_DEFAULT_VALUE, clk_base + + pllx->params->ext_misc_reg[4]); + writel_relaxed(PLLX_MISC5_DEFAULT_VALUE, clk_base + + pllx->params->ext_misc_reg[5]); + udelay(1); +} + +/* PLLMB */ +static void tegra210_pllmb_set_defaults(struct tegra_clk_pll *pllmb) +{ + u32 mask, val = readl_relaxed(clk_base + pllmb->params->base_reg); + + 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 + * that can be updated in flight. + */ + val = PLLMB_MISC1_DEFAULT_VALUE & (~PLLMB_MISC1_IDDQ); + mask = PLLMB_MISC1_LOCK_ENABLE | PLLMB_MISC1_LOCK_OVERRIDE; + _pll_misc_chk_default(clk_base, pllmb->params, 0, val, + ~mask & PLLMB_MISC1_WRITE_MASK); + + /* Enable lock detect */ + val = readl_relaxed(clk_base + pllmb->params->ext_misc_reg[0]); + val &= ~mask; + val |= PLLMB_MISC1_DEFAULT_VALUE & mask; + writel_relaxed(val, clk_base + pllmb->params->ext_misc_reg[0]); + udelay(1); + + return; + } + + /* set IDDQ, enable lock detect */ + writel_relaxed(PLLMB_MISC1_DEFAULT_VALUE, + clk_base + pllmb->params->ext_misc_reg[0]); + udelay(1); +} + +/* + * PLLP + * VCO is exposed to the clock tree directly along with post-divider output. + * Both VCO and post-divider output rates are fixed at 408MHz and 204MHz, + * respectively. + */ +static void pllp_check_defaults(struct tegra_clk_pll *pll, bool enabled) +{ + u32 val, mask; + + /* Ignore lock enable (will be set), make sure not in IDDQ if enabled */ + val = PLLP_MISC0_DEFAULT_VALUE & (~PLLP_MISC0_IDDQ); + mask = PLLP_MISC0_LOCK_ENABLE | PLLP_MISC0_LOCK_OVERRIDE; + if (!enabled) + mask |= PLLP_MISC0_IDDQ; + _pll_misc_chk_default(clk_base, pll->params, 0, val, + ~mask & PLLP_MISC0_WRITE_MASK); + + /* Ignore branch controls */ + val = PLLP_MISC1_DEFAULT_VALUE; + mask = PLLP_MISC1_HSIO_EN | PLLP_MISC1_XUSB_EN; + _pll_misc_chk_default(clk_base, pll->params, 1, val, + ~mask & PLLP_MISC1_WRITE_MASK); +} + +static void tegra210_pllp_set_defaults(struct tegra_clk_pll *pllp) +{ + u32 mask; + u32 val = readl_relaxed(clk_base + pllp->params->base_reg); + + 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); + + /* Enable lock detect */ + val = readl_relaxed(clk_base + pllp->params->ext_misc_reg[0]); + mask = PLLP_MISC0_LOCK_ENABLE | PLLP_MISC0_LOCK_OVERRIDE; + val &= ~mask; + val |= PLLP_MISC0_DEFAULT_VALUE & mask; + writel_relaxed(val, clk_base + pllp->params->ext_misc_reg[0]); + udelay(1); + + return; + } + + /* set IDDQ, enable lock detect */ + writel_relaxed(PLLP_MISC0_DEFAULT_VALUE, + clk_base + pllp->params->ext_misc_reg[0]); + + /* Preserve branch control */ + val = readl_relaxed(clk_base + pllp->params->ext_misc_reg[1]); + mask = PLLP_MISC1_HSIO_EN | PLLP_MISC1_XUSB_EN; + val &= mask; + val |= ~mask & PLLP_MISC1_DEFAULT_VALUE; + writel_relaxed(val, clk_base + pllp->params->ext_misc_reg[1]); + udelay(1); +} + +/* + * PLLU + * VCO is exposed to the clock tree directly along with post-divider output. + * 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) +{ + 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, + ~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, + ~mask & PLLU_MISC1_WRITE_MASK); +} + +static void tegra210_pllu_set_defaults(struct tegra_clk_pll *pllu) +{ + u32 val = readl_relaxed(clk_base + pllu->params->base_reg); + + pllu->params->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); + + /* Enable lock detect */ + val = readl_relaxed(clk_base + pllu->params->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]); + + val = readl_relaxed(clk_base + pllu->params->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]); + udelay(1); + + return; + } + + /* set IDDQ, enable lock detect */ + writel_relaxed(PLLU_MISC0_DEFAULT_VALUE, + clk_base + pllu->params->ext_misc_reg[0]); + writel_relaxed(PLLU_MISC1_DEFAULT_VALUE, + clk_base + pllu->params->ext_misc_reg[1]); + udelay(1); +} + +#define mask(w) ((1 << (w)) - 1) +#define divm_mask(p) mask(p->params->div_nmp->divm_width) +#define divn_mask(p) mask(p->params->div_nmp->divn_width) +#define divp_mask(p) (p->params->flags & TEGRA_PLLU ? PLLU_POST_DIVP_MASK :\ + mask(p->params->div_nmp->divp_width)) + +#define divm_shift(p) ((p)->params->div_nmp->divm_shift) +#define divn_shift(p) ((p)->params->div_nmp->divn_shift) +#define divp_shift(p) ((p)->params->div_nmp->divp_shift) + +#define divm_mask_shifted(p) (divm_mask(p) << divm_shift(p)) +#define divn_mask_shifted(p) (divn_mask(p) << divn_shift(p)) +#define divp_mask_shifted(p) (divp_mask(p) << divp_shift(p)) + +#define PLL_LOCKDET_DELAY 2 /* Lock detection safety delays */ +static int tegra210_wait_for_mask(struct tegra_clk_pll *pll, + u32 reg, u32 mask) +{ + int i; + u32 val = 0; + + for (i = 0; i < pll->params->lock_delay / PLL_LOCKDET_DELAY + 1; i++) { + udelay(PLL_LOCKDET_DELAY); + val = readl_relaxed(clk_base + reg); + if ((val & mask) == mask) { + udelay(PLL_LOCKDET_DELAY); + return 0; + } + } + return -ETIMEDOUT; +} + +static int tegra210_pllx_dyn_ramp(struct tegra_clk_pll *pllx, + struct tegra_clk_pll_freq_table *cfg) +{ + u32 val, base, ndiv_new_mask; + + ndiv_new_mask = (divn_mask(pllx) >> pllx->params->div_nmp->divn_shift) + << PLLX_MISC2_NDIV_NEW_SHIFT; + + val = readl_relaxed(clk_base + pllx->params->ext_misc_reg[2]); + val &= (~ndiv_new_mask); + val |= cfg->n << PLLX_MISC2_NDIV_NEW_SHIFT; + writel_relaxed(val, clk_base + pllx->params->ext_misc_reg[2]); + udelay(1); + + val = readl_relaxed(clk_base + pllx->params->ext_misc_reg[2]); + val |= PLLX_MISC2_EN_DYNRAMP; + writel_relaxed(val, clk_base + pllx->params->ext_misc_reg[2]); + udelay(1); + + tegra210_wait_for_mask(pllx, pllx->params->ext_misc_reg[2], + PLLX_MISC2_DYNRAMP_DONE); + + base = readl_relaxed(clk_base + pllx->params->base_reg) & + (~divn_mask_shifted(pllx)); + base |= cfg->n << pllx->params->div_nmp->divn_shift; + writel_relaxed(base, clk_base + pllx->params->base_reg); + udelay(1); + + val &= ~PLLX_MISC2_EN_DYNRAMP; + writel_relaxed(val, clk_base + pllx->params->ext_misc_reg[2]); + udelay(1); + + pr_debug("%s: dynamic ramp to m = %u n = %u p = %u, Fout = %lu kHz\n", + __clk_get_name(pllx->hw.clk), cfg->m, cfg->n, cfg->p, + cfg->input_rate / cfg->m * cfg->n / + pllx->params->pdiv_tohw[cfg->p].pdiv / 1000); + + return 0; +} + +/* + * Common configuration for PLLs with fixed input divider policy: + * - always set fixed M-value based on the reference rate + * - always set P-value value 1:1 for output rates above VCO minimum, and + * choose minimum necessary P-value for output rates below VCO maximum + * - calculate N-value based on selected M and P + * - calculate SDM_DIN fractional part + */ +static int tegra210_pll_fixed_mdiv_cfg(struct clk_hw *hw, + struct tegra_clk_pll_freq_table *cfg, + unsigned long rate, unsigned long input_rate) +{ + struct tegra_clk_pll *pll = to_clk_pll(hw); + struct tegra_clk_pll_params *params = pll->params; + int p; + unsigned long cf, p_rate; + u32 pdiv; + + if (!rate) + return -EINVAL; + + if (!(params->flags & TEGRA_PLL_VCO_OUT)) { + p = DIV_ROUND_UP(params->vco_min, rate); + p = params->round_p_to_pdiv(p, &pdiv); + } else { + p = rate >= params->vco_min ? 1 : -EINVAL; + } + + if (IS_ERR_VALUE(p)) + return -EINVAL; + + cfg->m = tegra_pll_get_fixed_mdiv(hw, input_rate); + cfg->p = p; + + /* Store P as HW value, as that is what is expected */ + cfg->p = tegra_pll_p_div_to_hw(pll, cfg->p); + + p_rate = rate * p; + if (p_rate > params->vco_max) + p_rate = params->vco_max; + cf = input_rate / cfg->m; + cfg->n = p_rate / cf; + + cfg->sdm_data = 0; + 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 */ + if (rem || params->ssc_ctrl_reg) { + u64 s = rem * PLL_SDM_COEFF; + + do_div(s, cf); + s -= PLL_SDM_COEFF / 2; + cfg->sdm_data = sdin_din_to_data(s); + } + } + + cfg->input_rate = input_rate; + cfg->output_rate = rate; + + return 0; +} + +/* + * clk_pll_set_gain - set gain to m, n to calculate correct VCO rate + * + * @cfg: struct tegra_clk_pll_freq_table * cfg + * + * For Normal mode: + * Fvco = Fref * NDIV / MDIV + * + * For fractional mode: + * Fvco = Fref * (NDIV + 0.5 + SDM_DIN / PLL_SDM_COEFF) / MDIV + */ +static void tegra210_clk_pll_set_gain(struct tegra_clk_pll_freq_table *cfg) +{ + cfg->n = cfg->n * PLL_SDM_COEFF + PLL_SDM_COEFF/2 + + sdin_data_to_din(cfg->sdm_data); + cfg->m *= PLL_SDM_COEFF; +} + +static unsigned long +tegra210_clk_adjust_vco_min(struct tegra_clk_pll_params *params, + unsigned long parent_rate) +{ + unsigned long vco_min = params->vco_min; + + params->vco_min += DIV_ROUND_UP(parent_rate, PLL_SDM_COEFF); + vco_min = min(vco_min, params->vco_min); + + return vco_min; +} + +static struct div_nmp pllx_nmp = { + .divm_shift = 0, + .divm_width = 8, + .divn_shift = 8, + .divn_width = 8, + .divp_shift = 20, + .divp_width = 5, +}; +/* + * PLL post divider maps - two types: quasi-linear and exponential + * post divider. + */ +#define PLL_QLIN_PDIV_MAX 16 +static const struct pdiv_map pll_qlin_pdiv_to_hw[] = { + { .pdiv = 1, .hw_val = 0 }, + { .pdiv = 2, .hw_val = 1 }, + { .pdiv = 3, .hw_val = 2 }, + { .pdiv = 4, .hw_val = 3 }, + { .pdiv = 5, .hw_val = 4 }, + { .pdiv = 6, .hw_val = 5 }, + { .pdiv = 8, .hw_val = 6 }, + { .pdiv = 9, .hw_val = 7 }, + { .pdiv = 10, .hw_val = 8 }, + { .pdiv = 12, .hw_val = 9 }, + { .pdiv = 15, .hw_val = 10 }, + { .pdiv = 16, .hw_val = 11 }, + { .pdiv = 18, .hw_val = 12 }, + { .pdiv = 20, .hw_val = 13 }, + { .pdiv = 24, .hw_val = 14 }, + { .pdiv = 30, .hw_val = 15 }, + { .pdiv = 32, .hw_val = 16 }, +}; + +static u32 pll_qlin_p_to_pdiv(u32 p, u32 *pdiv) +{ + int i; + + if (p) { + for (i = 0; i <= PLL_QLIN_PDIV_MAX; i++) { + if (p <= pll_qlin_pdiv_to_hw[i].pdiv) { + if (pdiv) + *pdiv = i; + return pll_qlin_pdiv_to_hw[i].pdiv; + } + } + } + + return -EINVAL; +} + +#define PLL_EXPO_PDIV_MAX 7 +static const struct pdiv_map pll_expo_pdiv_to_hw[] = { + { .pdiv = 1, .hw_val = 0 }, + { .pdiv = 2, .hw_val = 1 }, + { .pdiv = 4, .hw_val = 2 }, + { .pdiv = 8, .hw_val = 3 }, + { .pdiv = 16, .hw_val = 4 }, + { .pdiv = 32, .hw_val = 5 }, + { .pdiv = 64, .hw_val = 6 }, + { .pdiv = 128, .hw_val = 7 }, +}; + +static u32 pll_expo_p_to_pdiv(u32 p, u32 *pdiv) +{ + if (p) { + u32 i = fls(p); + + if (i == ffs(p)) + i--; + + if (i <= PLL_EXPO_PDIV_MAX) { + if (pdiv) + *pdiv = i; + return 1 << i; + } + } + return -EINVAL; +} + +static struct tegra_clk_pll_freq_table pll_x_freq_table[] = { + /* 1 GHz */ + { 12000000, 1000000000, 166, 1, 1, 0 }, /* actual: 996.0 MHz */ + { 13000000, 1000000000, 153, 1, 1, 0 }, /* actual: 994.0 MHz */ + { 38400000, 1000000000, 156, 3, 1, 0 }, /* actual: 998.4 MHz */ + { 0, 0, 0, 0, 0, 0 }, +}; + +static struct tegra_clk_pll_params pll_x_params = { + .input_min = 12000000, + .input_max = 800000000, + .cf_min = 12000000, + .cf_max = 38400000, + .vco_min = 1350000000, + .vco_max = 3000000000UL, + .base_reg = PLLX_BASE, + .misc_reg = PLLX_MISC0, + .lock_mask = PLL_BASE_LOCK, + .lock_enable_bit_idx = PLL_MISC_LOCK_ENABLE, + .lock_delay = 300, + .ext_misc_reg[0] = PLLX_MISC0, + .ext_misc_reg[1] = PLLX_MISC1, + .ext_misc_reg[2] = PLLX_MISC2, + .ext_misc_reg[3] = PLLX_MISC3, + .ext_misc_reg[4] = PLLX_MISC4, + .ext_misc_reg[5] = PLLX_MISC5, + .iddq_reg = PLLX_MISC3, + .iddq_bit_idx = PLLXP_IDDQ_BIT, + .max_p = PLL_QLIN_PDIV_MAX, + .mdiv_default = 2, + .dyn_ramp_reg = PLLX_MISC2, + .stepa_shift = 16, + .stepb_shift = 24, + .round_p_to_pdiv = pll_qlin_p_to_pdiv, + .pdiv_tohw = pll_qlin_pdiv_to_hw, + .div_nmp = &pllx_nmp, + .freq_table = pll_x_freq_table, + .flags = TEGRA_PLL_USE_LOCK | TEGRA_PLL_HAS_LOCK_ENABLE, + .dyn_ramp = tegra210_pllx_dyn_ramp, + .set_defaults = tegra210_pllx_set_defaults, + .calc_rate = tegra210_pll_fixed_mdiv_cfg, +}; + +static struct div_nmp pllc_nmp = { + .divm_shift = 0, + .divm_width = 8, + .divn_shift = 10, + .divn_width = 8, + .divp_shift = 20, + .divp_width = 5, +}; + +static struct tegra_clk_pll_freq_table pll_cx_freq_table[] = { + { 12000000, 510000000, 85, 1, 1, 0 }, + { 13000000, 510000000, 78, 1, 1, 0 }, /* actual: 507.0 MHz */ + { 38400000, 510000000, 79, 3, 1, 0 }, /* actual: 505.6 MHz */ + { 0, 0, 0, 0, 0, 0 }, +}; + +static struct tegra_clk_pll_params pll_c_params = { + .input_min = 12000000, + .input_max = 700000000, + .cf_min = 12000000, + .cf_max = 50000000, + .vco_min = 600000000, + .vco_max = 1200000000, + .base_reg = PLLC_BASE, + .misc_reg = PLLC_MISC0, + .lock_mask = PLL_BASE_LOCK, + .lock_delay = 300, + .iddq_reg = PLLC_MISC1, + .iddq_bit_idx = PLLCX_IDDQ_BIT, + .reset_reg = PLLC_MISC0, + .reset_bit_idx = PLLCX_RESET_BIT, + .max_p = PLL_QLIN_PDIV_MAX, + .ext_misc_reg[0] = PLLC_MISC0, + .ext_misc_reg[1] = PLLC_MISC1, + .ext_misc_reg[2] = PLLC_MISC2, + .ext_misc_reg[3] = PLLC_MISC3, + .round_p_to_pdiv = pll_qlin_p_to_pdiv, + .pdiv_tohw = pll_qlin_pdiv_to_hw, + .mdiv_default = 3, + .div_nmp = &pllc_nmp, + .freq_table = pll_cx_freq_table, + .flags = TEGRA_PLL_USE_LOCK, + .set_defaults = _pllc_set_defaults, + .calc_rate = tegra210_pll_fixed_mdiv_cfg, +}; + +static struct div_nmp pllcx_nmp = { + .divm_shift = 0, + .divm_width = 8, + .divn_shift = 10, + .divn_width = 8, + .divp_shift = 20, + .divp_width = 5, +}; + +static struct tegra_clk_pll_params pll_c2_params = { + .input_min = 12000000, + .input_max = 700000000, + .cf_min = 12000000, + .cf_max = 50000000, + .vco_min = 600000000, + .vco_max = 1200000000, + .base_reg = PLLC2_BASE, + .misc_reg = PLLC2_MISC0, + .iddq_reg = PLLC2_MISC1, + .iddq_bit_idx = PLLCX_IDDQ_BIT, + .reset_reg = PLLC2_MISC0, + .reset_bit_idx = PLLCX_RESET_BIT, + .lock_mask = PLLCX_BASE_LOCK, + .lock_delay = 300, + .round_p_to_pdiv = pll_qlin_p_to_pdiv, + .pdiv_tohw = pll_qlin_pdiv_to_hw, + .mdiv_default = 3, + .div_nmp = &pllcx_nmp, + .max_p = PLL_QLIN_PDIV_MAX, + .ext_misc_reg[0] = PLLC2_MISC0, + .ext_misc_reg[1] = PLLC2_MISC1, + .ext_misc_reg[2] = PLLC2_MISC2, + .ext_misc_reg[3] = PLLC2_MISC3, + .freq_table = pll_cx_freq_table, + .flags = TEGRA_PLL_USE_LOCK, + .set_defaults = _pllc2_set_defaults, + .calc_rate = tegra210_pll_fixed_mdiv_cfg, +}; + +static struct tegra_clk_pll_params pll_c3_params = { + .input_min = 12000000, + .input_max = 700000000, + .cf_min = 12000000, + .cf_max = 50000000, + .vco_min = 600000000, + .vco_max = 1200000000, + .base_reg = PLLC3_BASE, + .misc_reg = PLLC3_MISC0, + .lock_mask = PLLCX_BASE_LOCK, + .lock_delay = 300, + .iddq_reg = PLLC3_MISC1, + .iddq_bit_idx = PLLCX_IDDQ_BIT, + .reset_reg = PLLC3_MISC0, + .reset_bit_idx = PLLCX_RESET_BIT, + .round_p_to_pdiv = pll_qlin_p_to_pdiv, + .pdiv_tohw = pll_qlin_pdiv_to_hw, + .mdiv_default = 3, + .div_nmp = &pllcx_nmp, + .max_p = PLL_QLIN_PDIV_MAX, + .ext_misc_reg[0] = PLLC3_MISC0, + .ext_misc_reg[1] = PLLC3_MISC1, + .ext_misc_reg[2] = PLLC3_MISC2, + .ext_misc_reg[3] = PLLC3_MISC3, + .freq_table = pll_cx_freq_table, + .flags = TEGRA_PLL_USE_LOCK, + .set_defaults = _pllc3_set_defaults, + .calc_rate = tegra210_pll_fixed_mdiv_cfg, +}; + +static struct div_nmp pllss_nmp = { + .divm_shift = 0, + .divm_width = 8, + .divn_shift = 8, + .divn_width = 8, + .divp_shift = 19, + .divp_width = 5, +}; + +static struct tegra_clk_pll_freq_table pll_c4_vco_freq_table[] = { + { 12000000, 600000000, 50, 1, 0, 0 }, + { 13000000, 600000000, 46, 1, 0, 0 }, /* actual: 598.0 MHz */ + { 38400000, 600000000, 62, 4, 0, 0 }, /* actual: 595.2 MHz */ + { 0, 0, 0, 0, 0, 0 }, +}; + +static const struct clk_div_table pll_vco_post_div_table[] = { + { .val = 0, .div = 1 }, + { .val = 1, .div = 2 }, + { .val = 2, .div = 3 }, + { .val = 3, .div = 4 }, + { .val = 4, .div = 5 }, + { .val = 5, .div = 6 }, + { .val = 6, .div = 8 }, + { .val = 7, .div = 10 }, + { .val = 8, .div = 12 }, + { .val = 9, .div = 16 }, + { .val = 10, .div = 12 }, + { .val = 11, .div = 16 }, + { .val = 12, .div = 20 }, + { .val = 13, .div = 24 }, + { .val = 14, .div = 32 }, + { .val = 0, .div = 0 }, +}; + +static struct tegra_clk_pll_params pll_c4_vco_params = { + .input_min = 9600000, + .input_max = 800000000, + .cf_min = 9600000, + .cf_max = 19200000, + .vco_min = 500000000, + .vco_max = 1080000000, + .base_reg = PLLC4_BASE, + .misc_reg = PLLC4_MISC0, + .lock_mask = PLL_BASE_LOCK, + .lock_delay = 300, + .max_p = PLL_QLIN_PDIV_MAX, + .ext_misc_reg[0] = PLLC4_MISC0, + .iddq_reg = PLLC4_BASE, + .iddq_bit_idx = PLLSS_IDDQ_BIT, + .round_p_to_pdiv = pll_qlin_p_to_pdiv, + .pdiv_tohw = pll_qlin_pdiv_to_hw, + .mdiv_default = 3, + .div_nmp = &pllss_nmp, + .freq_table = pll_c4_vco_freq_table, + .set_defaults = tegra210_pllc4_set_defaults, + .flags = TEGRA_PLL_USE_LOCK | TEGRA_PLL_VCO_OUT, + .calc_rate = tegra210_pll_fixed_mdiv_cfg, +}; + +static struct tegra_clk_pll_freq_table pll_m_freq_table[] = { + { 12000000, 800000000, 66, 1, 0, 0 }, /* actual: 792.0 MHz */ + { 13000000, 800000000, 61, 1, 0, 0 }, /* actual: 793.0 MHz */ + { 38400000, 297600000, 93, 4, 2, 0 }, + { 38400000, 400000000, 125, 4, 2, 0 }, + { 38400000, 532800000, 111, 4, 1, 0 }, + { 38400000, 665600000, 104, 3, 1, 0 }, + { 38400000, 800000000, 125, 3, 1, 0 }, + { 38400000, 931200000, 97, 4, 0, 0 }, + { 38400000, 1065600000, 111, 4, 0, 0 }, + { 38400000, 1200000000, 125, 4, 0, 0 }, + { 38400000, 1331200000, 104, 3, 0, 0 }, + { 38400000, 1459200000, 76, 2, 0, 0 }, + { 38400000, 1600000000, 125, 3, 0, 0 }, + { 0, 0, 0, 0, 0, 0 }, +}; + +static struct div_nmp pllm_nmp = { + .divm_shift = 0, + .divm_width = 8, + .override_divm_shift = 0, + .divn_shift = 8, + .divn_width = 8, + .override_divn_shift = 8, + .divp_shift = 20, + .divp_width = 5, + .override_divp_shift = 27, +}; + +static struct tegra_clk_pll_params pll_m_params = { + .input_min = 9600000, + .input_max = 500000000, + .cf_min = 9600000, + .cf_max = 19200000, + .vco_min = 800000000, + .vco_max = 1866000000, + .base_reg = PLLM_BASE, + .misc_reg = PLLM_MISC2, + .lock_mask = PLL_BASE_LOCK, + .lock_enable_bit_idx = PLLM_MISC_LOCK_ENABLE, + .lock_delay = 300, + .iddq_reg = PLLM_MISC2, + .iddq_bit_idx = PLLM_IDDQ_BIT, + .max_p = PLL_QLIN_PDIV_MAX, + .ext_misc_reg[0] = PLLM_MISC2, + .ext_misc_reg[1] = PLLM_MISC1, + .round_p_to_pdiv = pll_qlin_p_to_pdiv, + .pdiv_tohw = pll_qlin_pdiv_to_hw, + .div_nmp = &pllm_nmp, + .pmc_divnm_reg = PMC_PLLM_WB0_OVERRIDE, + .pmc_divp_reg = PMC_PLLM_WB0_OVERRIDE_2, + .freq_table = pll_m_freq_table, + .flags = TEGRA_PLL_USE_LOCK | TEGRA_PLL_HAS_LOCK_ENABLE, + .calc_rate = tegra210_pll_fixed_mdiv_cfg, +}; + +static struct tegra_clk_pll_params pll_mb_params = { + .input_min = 9600000, + .input_max = 500000000, + .cf_min = 9600000, + .cf_max = 19200000, + .vco_min = 800000000, + .vco_max = 1866000000, + .base_reg = PLLMB_BASE, + .misc_reg = PLLMB_MISC1, + .lock_mask = PLL_BASE_LOCK, + .lock_delay = 300, + .iddq_reg = PLLMB_MISC1, + .iddq_bit_idx = PLLMB_IDDQ_BIT, + .max_p = PLL_QLIN_PDIV_MAX, + .ext_misc_reg[0] = PLLMB_MISC1, + .round_p_to_pdiv = pll_qlin_p_to_pdiv, + .pdiv_tohw = pll_qlin_pdiv_to_hw, + .div_nmp = &pllm_nmp, + .freq_table = pll_m_freq_table, + .flags = TEGRA_PLL_USE_LOCK, + .set_defaults = tegra210_pllmb_set_defaults, + .calc_rate = tegra210_pll_fixed_mdiv_cfg, +}; + + +static struct tegra_clk_pll_freq_table pll_e_freq_table[] = { + /* PLLE special case: use cpcon field to store cml divider value */ + { 672000000, 100000000, 125, 42, 0, 13 }, + { 624000000, 100000000, 125, 39, 0, 13 }, + { 336000000, 100000000, 125, 21, 0, 13 }, + { 312000000, 100000000, 200, 26, 0, 14 }, + { 38400000, 100000000, 125, 2, 0, 14 }, + { 12000000, 100000000, 200, 1, 0, 14 }, + { 0, 0, 0, 0, 0, 0 }, +}; + +static struct div_nmp plle_nmp = { + .divm_shift = 0, + .divm_width = 8, + .divn_shift = 8, + .divn_width = 8, + .divp_shift = 24, + .divp_width = 5, +}; + +static struct tegra_clk_pll_params pll_e_params = { + .input_min = 12000000, + .input_max = 800000000, + .cf_min = 12000000, + .cf_max = 38400000, + .vco_min = 1600000000, + .vco_max = 2500000000U, + .base_reg = PLLE_BASE, + .misc_reg = PLLE_MISC0, + .aux_reg = PLLE_AUX, + .lock_mask = PLLE_MISC_LOCK, + .lock_enable_bit_idx = PLLE_MISC_LOCK_ENABLE, + .lock_delay = 300, + .div_nmp = &plle_nmp, + .freq_table = pll_e_freq_table, + .flags = TEGRA_PLL_FIXED | TEGRA_PLL_LOCK_MISC | TEGRA_PLL_USE_LOCK | + TEGRA_PLL_HAS_LOCK_ENABLE, + .fixed_rate = 100000000, + .calc_rate = tegra210_pll_fixed_mdiv_cfg, +}; + +static struct tegra_clk_pll_freq_table pll_re_vco_freq_table[] = { + { 12000000, 672000000, 56, 1, 0, 0 }, + { 13000000, 672000000, 51, 1, 0, 0 }, /* actual: 663.0 MHz */ + { 38400000, 672000000, 70, 4, 0, 0 }, + { 0, 0, 0, 0, 0, 0 }, +}; + +static struct div_nmp pllre_nmp = { + .divm_shift = 0, + .divm_width = 8, + .divn_shift = 8, + .divn_width = 8, + .divp_shift = 16, + .divp_width = 5, +}; + +static struct tegra_clk_pll_params pll_re_vco_params = { + .input_min = 9600000, + .input_max = 800000000, + .cf_min = 9600000, + .cf_max = 19200000, + .vco_min = 350000000, + .vco_max = 700000000, + .base_reg = PLLRE_BASE, + .misc_reg = PLLRE_MISC0, + .lock_mask = PLLRE_MISC_LOCK, + .lock_delay = 300, + .max_p = PLL_QLIN_PDIV_MAX, + .ext_misc_reg[0] = PLLRE_MISC0, + .iddq_reg = PLLRE_MISC0, + .iddq_bit_idx = PLLRE_IDDQ_BIT, + .round_p_to_pdiv = pll_qlin_p_to_pdiv, + .pdiv_tohw = pll_qlin_pdiv_to_hw, + .div_nmp = &pllre_nmp, + .freq_table = pll_re_vco_freq_table, + .flags = TEGRA_PLL_USE_LOCK | TEGRA_PLL_LOCK_MISC | TEGRA_PLL_VCO_OUT, + .set_defaults = tegra210_pllre_set_defaults, + .calc_rate = tegra210_pll_fixed_mdiv_cfg, +}; + +static struct div_nmp pllp_nmp = { + .divm_shift = 0, + .divm_width = 8, + .divn_shift = 10, + .divn_width = 8, + .divp_shift = 20, + .divp_width = 5, +}; + +static struct tegra_clk_pll_freq_table pll_p_freq_table[] = { + { 12000000, 408000000, 34, 1, 0, 0 }, + { 38400000, 408000000, 85, 8, 0, 0 }, /* cf = 4.8MHz, allowed exception */ + { 0, 0, 0, 0, 0, 0 }, +}; + +static struct tegra_clk_pll_params pll_p_params = { + .input_min = 9600000, + .input_max = 800000000, + .cf_min = 9600000, + .cf_max = 19200000, + .vco_min = 350000000, + .vco_max = 700000000, + .base_reg = PLLP_BASE, + .misc_reg = PLLP_MISC0, + .lock_mask = PLL_BASE_LOCK, + .lock_delay = 300, + .iddq_reg = PLLP_MISC0, + .iddq_bit_idx = PLLXP_IDDQ_BIT, + .ext_misc_reg[0] = PLLP_MISC0, + .ext_misc_reg[1] = PLLP_MISC1, + .div_nmp = &pllp_nmp, + .freq_table = pll_p_freq_table, + .fixed_rate = 408000000, + .flags = TEGRA_PLL_FIXED | TEGRA_PLL_USE_LOCK | TEGRA_PLL_VCO_OUT, + .set_defaults = tegra210_pllp_set_defaults, + .calc_rate = tegra210_pll_fixed_mdiv_cfg, +}; + +static struct tegra_clk_pll_params pll_a1_params = { + .input_min = 12000000, + .input_max = 700000000, + .cf_min = 12000000, + .cf_max = 50000000, + .vco_min = 600000000, + .vco_max = 1200000000, + .base_reg = PLLA1_BASE, + .misc_reg = PLLA1_MISC0, + .lock_mask = PLLCX_BASE_LOCK, + .lock_delay = 300, + .iddq_reg = PLLA1_MISC0, + .iddq_bit_idx = PLLCX_IDDQ_BIT, + .reset_reg = PLLA1_MISC0, + .reset_bit_idx = PLLCX_RESET_BIT, + .round_p_to_pdiv = pll_qlin_p_to_pdiv, + .pdiv_tohw = pll_qlin_pdiv_to_hw, + .div_nmp = &pllc_nmp, + .ext_misc_reg[0] = PLLA1_MISC0, + .ext_misc_reg[1] = PLLA1_MISC1, + .ext_misc_reg[2] = PLLA1_MISC2, + .ext_misc_reg[3] = PLLA1_MISC3, + .freq_table = pll_cx_freq_table, + .flags = TEGRA_PLL_USE_LOCK, + .set_defaults = _plla1_set_defaults, + .calc_rate = tegra210_pll_fixed_mdiv_cfg, +}; + +static struct div_nmp plla_nmp = { + .divm_shift = 0, + .divm_width = 8, + .divn_shift = 8, + .divn_width = 8, + .divp_shift = 20, + .divp_width = 5, +}; + +static struct tegra_clk_pll_freq_table pll_a_freq_table[] = { + { 12000000, 282240000, 47, 1, 1, 1, 0xf148 }, /* actual: 282240234 */ + { 12000000, 368640000, 61, 1, 1, 1, 0xfe15 }, /* actual: 368640381 */ + { 12000000, 240000000, 60, 1, 2, 1, 0 }, + { 13000000, 282240000, 43, 1, 1, 1, 0xfd7d }, /* actual: 282239807 */ + { 13000000, 368640000, 56, 1, 1, 1, 0x06d8 }, /* actual: 368640137 */ + { 13000000, 240000000, 55, 1, 2, 1, 0 }, /* actual: 238.3 MHz */ + { 38400000, 282240000, 44, 3, 1, 1, 0xf333 }, /* actual: 282239844 */ + { 38400000, 368640000, 57, 3, 1, 1, 0x0333 }, /* actual: 368639844 */ + { 38400000, 240000000, 75, 3, 3, 1, 0 }, + { 0, 0, 0, 0, 0, 0, 0 }, +}; + +static struct tegra_clk_pll_params pll_a_params = { + .input_min = 12000000, + .input_max = 800000000, + .cf_min = 12000000, + .cf_max = 19200000, + .vco_min = 500000000, + .vco_max = 1000000000, + .base_reg = PLLA_BASE, + .misc_reg = PLLA_MISC0, + .lock_mask = PLL_BASE_LOCK, + .lock_delay = 300, + .round_p_to_pdiv = pll_qlin_p_to_pdiv, + .pdiv_tohw = pll_qlin_pdiv_to_hw, + .iddq_reg = PLLA_BASE, + .iddq_bit_idx = PLLA_IDDQ_BIT, + .div_nmp = &plla_nmp, + .sdm_din_reg = PLLA_MISC1, + .sdm_din_mask = PLLA_SDM_DIN_MASK, + .sdm_ctrl_reg = PLLA_MISC2, + .sdm_ctrl_en_mask = PLLA_SDM_EN_MASK, + .ext_misc_reg[0] = PLLA_MISC0, + .ext_misc_reg[1] = PLLA_MISC1, + .ext_misc_reg[2] = PLLA_MISC2, + .freq_table = pll_a_freq_table, + .flags = TEGRA_PLL_USE_LOCK | TEGRA_MDIV_NEW, + .set_defaults = tegra210_plla_set_defaults, + .calc_rate = tegra210_pll_fixed_mdiv_cfg, + .set_gain = tegra210_clk_pll_set_gain, + .adjust_vco = tegra210_clk_adjust_vco_min, +}; + +static struct div_nmp plld_nmp = { + .divm_shift = 0, + .divm_width = 8, + .divn_shift = 11, + .divn_width = 8, + .divp_shift = 20, + .divp_width = 3, +}; + +static struct tegra_clk_pll_freq_table pll_d_freq_table[] = { + { 12000000, 594000000, 99, 1, 1, 0, 0 }, + { 13000000, 594000000, 91, 1, 1, 0, 0xfc4f }, /* actual: 594000183 */ + { 38400000, 594000000, 30, 1, 1, 0, 0x0e00 }, + { 0, 0, 0, 0, 0, 0, 0 }, +}; + +static struct tegra_clk_pll_params pll_d_params = { + .input_min = 12000000, + .input_max = 800000000, + .cf_min = 12000000, + .cf_max = 38400000, + .vco_min = 750000000, + .vco_max = 1500000000, + .base_reg = PLLD_BASE, + .misc_reg = PLLD_MISC0, + .lock_mask = PLL_BASE_LOCK, + .lock_delay = 1000, + .iddq_reg = PLLD_MISC0, + .iddq_bit_idx = PLLD_IDDQ_BIT, + .round_p_to_pdiv = pll_expo_p_to_pdiv, + .pdiv_tohw = pll_expo_pdiv_to_hw, + .div_nmp = &plld_nmp, + .sdm_din_reg = PLLD_MISC0, + .sdm_din_mask = PLLA_SDM_DIN_MASK, + .sdm_ctrl_reg = PLLD_MISC0, + .sdm_ctrl_en_mask = PLLD_SDM_EN_MASK, + .ext_misc_reg[0] = PLLD_MISC0, + .ext_misc_reg[1] = PLLD_MISC1, + .freq_table = pll_d_freq_table, + .flags = TEGRA_PLL_USE_LOCK, + .mdiv_default = 1, + .set_defaults = tegra210_plld_set_defaults, + .calc_rate = tegra210_pll_fixed_mdiv_cfg, + .set_gain = tegra210_clk_pll_set_gain, + .adjust_vco = tegra210_clk_adjust_vco_min, +}; + +static struct tegra_clk_pll_freq_table tegra210_pll_d2_freq_table[] = { + { 12000000, 594000000, 99, 1, 1, 0, 0xf000 }, + { 13000000, 594000000, 91, 1, 1, 0, 0xfc4f }, /* actual: 594000183 */ + { 38400000, 594000000, 30, 1, 1, 0, 0x0e00 }, + { 0, 0, 0, 0, 0, 0, 0 }, +}; + +/* s/w policy, always tegra_pll_ref */ +static struct tegra_clk_pll_params pll_d2_params = { + .input_min = 12000000, + .input_max = 800000000, + .cf_min = 12000000, + .cf_max = 38400000, + .vco_min = 750000000, + .vco_max = 1500000000, + .base_reg = PLLD2_BASE, + .misc_reg = PLLD2_MISC0, + .lock_mask = PLL_BASE_LOCK, + .lock_delay = 300, + .iddq_reg = PLLD2_BASE, + .iddq_bit_idx = PLLSS_IDDQ_BIT, + .sdm_din_reg = PLLD2_MISC3, + .sdm_din_mask = PLLA_SDM_DIN_MASK, + .sdm_ctrl_reg = PLLD2_MISC1, + .sdm_ctrl_en_mask = PLLD2_SDM_EN_MASK, + .ssc_ctrl_reg = PLLD2_MISC1, + .ssc_ctrl_en_mask = PLLD2_SSC_EN_MASK, + .round_p_to_pdiv = pll_qlin_p_to_pdiv, + .pdiv_tohw = pll_qlin_pdiv_to_hw, + .div_nmp = &pllss_nmp, + .ext_misc_reg[0] = PLLD2_MISC0, + .ext_misc_reg[1] = PLLD2_MISC1, + .ext_misc_reg[2] = PLLD2_MISC2, + .ext_misc_reg[3] = PLLD2_MISC3, + .max_p = PLL_QLIN_PDIV_MAX, + .mdiv_default = 1, + .freq_table = tegra210_pll_d2_freq_table, + .set_defaults = tegra210_plld2_set_defaults, + .flags = TEGRA_PLL_USE_LOCK, + .calc_rate = tegra210_pll_fixed_mdiv_cfg, + .set_gain = tegra210_clk_pll_set_gain, + .adjust_vco = tegra210_clk_adjust_vco_min, +}; + +static struct tegra_clk_pll_freq_table pll_dp_freq_table[] = { + { 12000000, 270000000, 90, 1, 3, 0, 0xf000 }, + { 13000000, 270000000, 83, 1, 3, 0, 0xf000 }, /* actual: 269.8 MHz */ + { 38400000, 270000000, 28, 1, 3, 0, 0xf400 }, + { 0, 0, 0, 0, 0, 0, 0 }, +}; + +static struct tegra_clk_pll_params pll_dp_params = { + .input_min = 12000000, + .input_max = 800000000, + .cf_min = 12000000, + .cf_max = 38400000, + .vco_min = 750000000, + .vco_max = 1500000000, + .base_reg = PLLDP_BASE, + .misc_reg = PLLDP_MISC, + .lock_mask = PLL_BASE_LOCK, + .lock_delay = 300, + .iddq_reg = PLLDP_BASE, + .iddq_bit_idx = PLLSS_IDDQ_BIT, + .sdm_din_reg = PLLDP_SS_CTRL2, + .sdm_din_mask = PLLA_SDM_DIN_MASK, + .sdm_ctrl_reg = PLLDP_SS_CFG, + .sdm_ctrl_en_mask = PLLDP_SDM_EN_MASK, + .ssc_ctrl_reg = PLLDP_SS_CFG, + .ssc_ctrl_en_mask = PLLDP_SSC_EN_MASK, + .round_p_to_pdiv = pll_qlin_p_to_pdiv, + .pdiv_tohw = pll_qlin_pdiv_to_hw, + .div_nmp = &pllss_nmp, + .ext_misc_reg[0] = PLLDP_MISC, + .ext_misc_reg[1] = PLLDP_SS_CFG, + .ext_misc_reg[2] = PLLDP_SS_CTRL1, + .ext_misc_reg[3] = PLLDP_SS_CTRL2, + .max_p = PLL_QLIN_PDIV_MAX, + .mdiv_default = 1, + .freq_table = pll_dp_freq_table, + .set_defaults = tegra210_plldp_set_defaults, + .flags = TEGRA_PLL_USE_LOCK, + .calc_rate = tegra210_pll_fixed_mdiv_cfg, + .set_gain = tegra210_clk_pll_set_gain, + .adjust_vco = tegra210_clk_adjust_vco_min, +}; + +static struct div_nmp pllu_nmp = { + .divm_shift = 0, + .divm_width = 8, + .divn_shift = 8, + .divn_width = 8, + .divp_shift = 16, + .divp_width = 5, +}; + +static struct tegra_clk_pll_freq_table pll_u_freq_table[] = { + { 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 }, +}; + +static struct tegra_clk_pll_params pll_u_vco_params = { + .input_min = 9600000, + .input_max = 800000000, + .cf_min = 9600000, + .cf_max = 19200000, + .vco_min = 350000000, + .vco_max = 700000000, + .base_reg = PLLU_BASE, + .misc_reg = PLLU_MISC0, + .lock_mask = PLL_BASE_LOCK, + .lock_delay = 1000, + .iddq_reg = PLLU_MISC0, + .iddq_bit_idx = PLLU_IDDQ_BIT, + .ext_misc_reg[0] = PLLU_MISC0, + .ext_misc_reg[1] = PLLU_MISC1, + .round_p_to_pdiv = pll_qlin_p_to_pdiv, + .pdiv_tohw = pll_qlin_pdiv_to_hw, + .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 = { + [tegra_clk_ispb] = { .dt_id = TEGRA210_CLK_ISPB, .present = true }, + [tegra_clk_rtc] = { .dt_id = TEGRA210_CLK_RTC, .present = true }, + [tegra_clk_timer] = { .dt_id = TEGRA210_CLK_TIMER, .present = true }, + [tegra_clk_uarta_8] = { .dt_id = TEGRA210_CLK_UARTA, .present = true }, + [tegra_clk_sdmmc2_9] = { .dt_id = TEGRA210_CLK_SDMMC2, .present = true }, + [tegra_clk_i2s1] = { .dt_id = TEGRA210_CLK_I2S1, .present = true }, + [tegra_clk_i2c1] = { .dt_id = TEGRA210_CLK_I2C1, .present = true }, + [tegra_clk_sdmmc1_9] = { .dt_id = TEGRA210_CLK_SDMMC1, .present = true }, + [tegra_clk_sdmmc4_9] = { .dt_id = TEGRA210_CLK_SDMMC4, .present = true }, + [tegra_clk_pwm] = { .dt_id = TEGRA210_CLK_PWM, .present = true }, + [tegra_clk_i2s2] = { .dt_id = TEGRA210_CLK_I2S2, .present = true }, + [tegra_clk_usbd] = { .dt_id = TEGRA210_CLK_USBD, .present = true }, + [tegra_clk_isp_9] = { .dt_id = TEGRA210_CLK_ISP, .present = true }, + [tegra_clk_disp2_8] = { .dt_id = TEGRA210_CLK_DISP2, .present = true }, + [tegra_clk_disp1_8] = { .dt_id = TEGRA210_CLK_DISP1, .present = true }, + [tegra_clk_host1x_9] = { .dt_id = TEGRA210_CLK_HOST1X, .present = true }, + [tegra_clk_i2s0] = { .dt_id = TEGRA210_CLK_I2S0, .present = true }, + [tegra_clk_apbdma] = { .dt_id = TEGRA210_CLK_APBDMA, .present = true }, + [tegra_clk_kfuse] = { .dt_id = TEGRA210_CLK_KFUSE, .present = true }, + [tegra_clk_sbc1_9] = { .dt_id = TEGRA210_CLK_SBC1, .present = true }, + [tegra_clk_sbc2_9] = { .dt_id = TEGRA210_CLK_SBC2, .present = true }, + [tegra_clk_sbc3_9] = { .dt_id = TEGRA210_CLK_SBC3, .present = true }, + [tegra_clk_i2c5] = { .dt_id = TEGRA210_CLK_I2C5, .present = true }, + [tegra_clk_csi] = { .dt_id = TEGRA210_CLK_CSI, .present = true }, + [tegra_clk_i2c2] = { .dt_id = TEGRA210_CLK_I2C2, .present = true }, + [tegra_clk_uartc_8] = { .dt_id = TEGRA210_CLK_UARTC, .present = true }, + [tegra_clk_mipi_cal] = { .dt_id = TEGRA210_CLK_MIPI_CAL, .present = true }, + [tegra_clk_emc] = { .dt_id = TEGRA210_CLK_EMC, .present = true }, + [tegra_clk_usb2] = { .dt_id = TEGRA210_CLK_USB2, .present = true }, + [tegra_clk_bsev] = { .dt_id = TEGRA210_CLK_BSEV, .present = true }, + [tegra_clk_uartd_8] = { .dt_id = TEGRA210_CLK_UARTD, .present = true }, + [tegra_clk_i2c3] = { .dt_id = TEGRA210_CLK_I2C3, .present = true }, + [tegra_clk_sbc4_9] = { .dt_id = TEGRA210_CLK_SBC4, .present = true }, + [tegra_clk_sdmmc3_9] = { .dt_id = TEGRA210_CLK_SDMMC3, .present = true }, + [tegra_clk_pcie] = { .dt_id = TEGRA210_CLK_PCIE, .present = true }, + [tegra_clk_owr_8] = { .dt_id = TEGRA210_CLK_OWR, .present = true }, + [tegra_clk_afi] = { .dt_id = TEGRA210_CLK_AFI, .present = true }, + [tegra_clk_csite_8] = { .dt_id = TEGRA210_CLK_CSITE, .present = true }, + [tegra_clk_soc_therm_8] = { .dt_id = TEGRA210_CLK_SOC_THERM, .present = true }, + [tegra_clk_dtv] = { .dt_id = TEGRA210_CLK_DTV, .present = true }, + [tegra_clk_i2cslow] = { .dt_id = TEGRA210_CLK_I2CSLOW, .present = true }, + [tegra_clk_tsec_8] = { .dt_id = TEGRA210_CLK_TSEC, .present = true }, + [tegra_clk_xusb_host] = { .dt_id = TEGRA210_CLK_XUSB_HOST, .present = true }, + [tegra_clk_csus] = { .dt_id = TEGRA210_CLK_CSUS, .present = true }, + [tegra_clk_mselect] = { .dt_id = TEGRA210_CLK_MSELECT, .present = true }, + [tegra_clk_tsensor] = { .dt_id = TEGRA210_CLK_TSENSOR, .present = true }, + [tegra_clk_i2s3] = { .dt_id = TEGRA210_CLK_I2S3, .present = true }, + [tegra_clk_i2s4] = { .dt_id = TEGRA210_CLK_I2S4, .present = true }, + [tegra_clk_i2c4] = { .dt_id = TEGRA210_CLK_I2C4, .present = true }, + [tegra_clk_d_audio] = { .dt_id = TEGRA210_CLK_D_AUDIO, .present = true }, + [tegra_clk_hda2codec_2x_8] = { .dt_id = TEGRA210_CLK_HDA2CODEC_2X, .present = true }, + [tegra_clk_spdif_2x] = { .dt_id = TEGRA210_CLK_SPDIF_2X, .present = true }, + [tegra_clk_actmon] = { .dt_id = TEGRA210_CLK_ACTMON, .present = true }, + [tegra_clk_extern1] = { .dt_id = TEGRA210_CLK_EXTERN1, .present = true }, + [tegra_clk_extern2] = { .dt_id = TEGRA210_CLK_EXTERN2, .present = true }, + [tegra_clk_extern3] = { .dt_id = TEGRA210_CLK_EXTERN3, .present = true }, + [tegra_clk_sata_oob_8] = { .dt_id = TEGRA210_CLK_SATA_OOB, .present = true }, + [tegra_clk_sata_8] = { .dt_id = TEGRA210_CLK_SATA, .present = true }, + [tegra_clk_hda_8] = { .dt_id = TEGRA210_CLK_HDA, .present = true }, + [tegra_clk_hda2hdmi] = { .dt_id = TEGRA210_CLK_HDA2HDMI, .present = true }, + [tegra_clk_cilab] = { .dt_id = TEGRA210_CLK_CILAB, .present = true }, + [tegra_clk_cilcd] = { .dt_id = TEGRA210_CLK_CILCD, .present = true }, + [tegra_clk_cile] = { .dt_id = TEGRA210_CLK_CILE, .present = true }, + [tegra_clk_dsialp] = { .dt_id = TEGRA210_CLK_DSIALP, .present = true }, + [tegra_clk_dsiblp] = { .dt_id = TEGRA210_CLK_DSIBLP, .present = true }, + [tegra_clk_entropy_8] = { .dt_id = TEGRA210_CLK_ENTROPY, .present = true }, + [tegra_clk_xusb_ss] = { .dt_id = TEGRA210_CLK_XUSB_SS, .present = true }, + [tegra_clk_i2c6] = { .dt_id = TEGRA210_CLK_I2C6, .present = true }, + [tegra_clk_vim2_clk] = { .dt_id = TEGRA210_CLK_VIM2_CLK, .present = true }, + [tegra_clk_clk72Mhz_8] = { .dt_id = TEGRA210_CLK_CLK72MHZ, .present = true }, + [tegra_clk_vic03_8] = { .dt_id = TEGRA210_CLK_VIC03, .present = true }, + [tegra_clk_dpaux] = { .dt_id = TEGRA210_CLK_DPAUX, .present = true }, + [tegra_clk_sor0] = { .dt_id = TEGRA210_CLK_SOR0, .present = true }, + [tegra_clk_sor0_lvds] = { .dt_id = TEGRA210_CLK_SOR0_LVDS, .present = true }, + [tegra_clk_gpu] = { .dt_id = TEGRA210_CLK_GPU, .present = true }, + [tegra_clk_pll_g_ref] = { .dt_id = TEGRA210_CLK_PLL_G_REF, .present = true, }, + [tegra_clk_uartb_8] = { .dt_id = TEGRA210_CLK_UARTB, .present = true }, + [tegra_clk_vfir] = { .dt_id = TEGRA210_CLK_VFIR, .present = true }, + [tegra_clk_spdif_in_8] = { .dt_id = TEGRA210_CLK_SPDIF_IN, .present = true }, + [tegra_clk_spdif_out] = { .dt_id = TEGRA210_CLK_SPDIF_OUT, .present = true }, + [tegra_clk_vi_10] = { .dt_id = TEGRA210_CLK_VI, .present = true }, + [tegra_clk_vi_sensor_8] = { .dt_id = TEGRA210_CLK_VI_SENSOR, .present = true }, + [tegra_clk_fuse] = { .dt_id = TEGRA210_CLK_FUSE, .present = true }, + [tegra_clk_fuse_burn] = { .dt_id = TEGRA210_CLK_FUSE_BURN, .present = true }, + [tegra_clk_clk_32k] = { .dt_id = TEGRA210_CLK_CLK_32K, .present = true }, + [tegra_clk_clk_m] = { .dt_id = TEGRA210_CLK_CLK_M, .present = true }, + [tegra_clk_clk_m_div2] = { .dt_id = TEGRA210_CLK_CLK_M_DIV2, .present = true }, + [tegra_clk_clk_m_div4] = { .dt_id = TEGRA210_CLK_CLK_M_DIV4, .present = true }, + [tegra_clk_pll_ref] = { .dt_id = TEGRA210_CLK_PLL_REF, .present = true }, + [tegra_clk_pll_c] = { .dt_id = TEGRA210_CLK_PLL_C, .present = true }, + [tegra_clk_pll_c_out1] = { .dt_id = TEGRA210_CLK_PLL_C_OUT1, .present = true }, + [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 }, + [tegra_clk_pll_p_out4_cpu] = { .dt_id = TEGRA210_CLK_PLL_P_OUT4, .present = true }, + [tegra_clk_pll_p_out_hsio] = { .dt_id = TEGRA210_CLK_PLL_P_OUT_HSIO, .present = true }, + [tegra_clk_pll_p_out_xusb] = { .dt_id = TEGRA210_CLK_PLL_P_OUT_XUSB, .present = true }, + [tegra_clk_pll_p_out_cpu] = { .dt_id = TEGRA210_CLK_PLL_P_OUT_CPU, .present = true }, + [tegra_clk_pll_p_out_adsp] = { .dt_id = TEGRA210_CLK_PLL_P_OUT_ADSP, .present = true }, + [tegra_clk_pll_a] = { .dt_id = TEGRA210_CLK_PLL_A, .present = true }, + [tegra_clk_pll_a_out0] = { .dt_id = TEGRA210_CLK_PLL_A_OUT0, .present = true }, + [tegra_clk_pll_d] = { .dt_id = TEGRA210_CLK_PLL_D, .present = true }, + [tegra_clk_pll_d_out0] = { .dt_id = TEGRA210_CLK_PLL_D_OUT0, .present = true }, + [tegra_clk_pll_d2] = { .dt_id = TEGRA210_CLK_PLL_D2, .present = true }, + [tegra_clk_pll_d2_out0] = { .dt_id = TEGRA210_CLK_PLL_D2_OUT0, .present = true }, + [tegra_clk_pll_u] = { .dt_id = TEGRA210_CLK_PLL_U, .present = true }, + [tegra_clk_pll_u_out] = { .dt_id = TEGRA210_CLK_PLL_U_OUT, .present = true }, + [tegra_clk_pll_u_out1] = { .dt_id = TEGRA210_CLK_PLL_U_OUT1, .present = true }, + [tegra_clk_pll_u_out2] = { .dt_id = TEGRA210_CLK_PLL_U_OUT2, .present = true }, + [tegra_clk_pll_u_480m] = { .dt_id = TEGRA210_CLK_PLL_U_480M, .present = true }, + [tegra_clk_pll_u_60m] = { .dt_id = TEGRA210_CLK_PLL_U_60M, .present = true }, + [tegra_clk_pll_u_48m] = { .dt_id = TEGRA210_CLK_PLL_U_48M, .present = true }, + [tegra_clk_pll_x] = { .dt_id = TEGRA210_CLK_PLL_X, .present = true }, + [tegra_clk_pll_x_out0] = { .dt_id = TEGRA210_CLK_PLL_X_OUT0, .present = true }, + [tegra_clk_pll_re_vco] = { .dt_id = TEGRA210_CLK_PLL_RE_VCO, .present = true }, + [tegra_clk_pll_re_out] = { .dt_id = TEGRA210_CLK_PLL_RE_OUT, .present = true }, + [tegra_clk_spdif_in_sync] = { .dt_id = TEGRA210_CLK_SPDIF_IN_SYNC, .present = true }, + [tegra_clk_i2s0_sync] = { .dt_id = TEGRA210_CLK_I2S0_SYNC, .present = true }, + [tegra_clk_i2s1_sync] = { .dt_id = TEGRA210_CLK_I2S1_SYNC, .present = true }, + [tegra_clk_i2s2_sync] = { .dt_id = TEGRA210_CLK_I2S2_SYNC, .present = true }, + [tegra_clk_i2s3_sync] = { .dt_id = TEGRA210_CLK_I2S3_SYNC, .present = true }, + [tegra_clk_i2s4_sync] = { .dt_id = TEGRA210_CLK_I2S4_SYNC, .present = true }, + [tegra_clk_vimclk_sync] = { .dt_id = TEGRA210_CLK_VIMCLK_SYNC, .present = true }, + [tegra_clk_audio0] = { .dt_id = TEGRA210_CLK_AUDIO0, .present = true }, + [tegra_clk_audio1] = { .dt_id = TEGRA210_CLK_AUDIO1, .present = true }, + [tegra_clk_audio2] = { .dt_id = TEGRA210_CLK_AUDIO2, .present = true }, + [tegra_clk_audio3] = { .dt_id = TEGRA210_CLK_AUDIO3, .present = true }, + [tegra_clk_audio4] = { .dt_id = TEGRA210_CLK_AUDIO4, .present = true }, + [tegra_clk_spdif] = { .dt_id = TEGRA210_CLK_SPDIF, .present = true }, + [tegra_clk_clk_out_1] = { .dt_id = TEGRA210_CLK_CLK_OUT_1, .present = true }, + [tegra_clk_clk_out_2] = { .dt_id = TEGRA210_CLK_CLK_OUT_2, .present = true }, + [tegra_clk_clk_out_3] = { .dt_id = TEGRA210_CLK_CLK_OUT_3, .present = true }, + [tegra_clk_blink] = { .dt_id = TEGRA210_CLK_BLINK, .present = true }, + [tegra_clk_xusb_gate] = { .dt_id = TEGRA210_CLK_XUSB_GATE, .present = true }, + [tegra_clk_xusb_host_src_8] = { .dt_id = TEGRA210_CLK_XUSB_HOST_SRC, .present = true }, + [tegra_clk_xusb_falcon_src_8] = { .dt_id = TEGRA210_CLK_XUSB_FALCON_SRC, .present = true }, + [tegra_clk_xusb_fs_src] = { .dt_id = TEGRA210_CLK_XUSB_FS_SRC, .present = true }, + [tegra_clk_xusb_ss_src_8] = { .dt_id = TEGRA210_CLK_XUSB_SS_SRC, .present = true }, + [tegra_clk_xusb_ss_div2] = { .dt_id = TEGRA210_CLK_XUSB_SS_DIV2, .present = true }, + [tegra_clk_xusb_dev_src_8] = { .dt_id = TEGRA210_CLK_XUSB_DEV_SRC, .present = true }, + [tegra_clk_xusb_dev] = { .dt_id = TEGRA210_CLK_XUSB_DEV, .present = true }, + [tegra_clk_xusb_hs_src_4] = { .dt_id = TEGRA210_CLK_XUSB_HS_SRC, .present = true }, + [tegra_clk_xusb_ssp_src] = { .dt_id = TEGRA210_CLK_XUSB_SSP_SRC, .present = true }, + [tegra_clk_usb2_hsic_trk] = { .dt_id = TEGRA210_CLK_USB2_HSIC_TRK, .present = true }, + [tegra_clk_hsic_trk] = { .dt_id = TEGRA210_CLK_HSIC_TRK, .present = true }, + [tegra_clk_usb2_trk] = { .dt_id = TEGRA210_CLK_USB2_TRK, .present = true }, + [tegra_clk_sclk] = { .dt_id = TEGRA210_CLK_SCLK, .present = true }, + [tegra_clk_sclk_mux] = { .dt_id = TEGRA210_CLK_SCLK_MUX, .present = true }, + [tegra_clk_hclk] = { .dt_id = TEGRA210_CLK_HCLK, .present = true }, + [tegra_clk_pclk] = { .dt_id = TEGRA210_CLK_PCLK, .present = true }, + [tegra_clk_cclk_g] = { .dt_id = TEGRA210_CLK_CCLK_G, .present = true }, + [tegra_clk_cclk_lp] = { .dt_id = TEGRA210_CLK_CCLK_LP, .present = true }, + [tegra_clk_dfll_ref] = { .dt_id = TEGRA210_CLK_DFLL_REF, .present = true }, + [tegra_clk_dfll_soc] = { .dt_id = TEGRA210_CLK_DFLL_SOC, .present = true }, + [tegra_clk_vi_sensor2_8] = { .dt_id = TEGRA210_CLK_VI_SENSOR2, .present = true }, + [tegra_clk_pll_p_out5] = { .dt_id = TEGRA210_CLK_PLL_P_OUT5, .present = true }, + [tegra_clk_pll_c4] = { .dt_id = TEGRA210_CLK_PLL_C4, .present = true }, + [tegra_clk_pll_dp] = { .dt_id = TEGRA210_CLK_PLL_DP, .present = true }, + [tegra_clk_audio0_mux] = { .dt_id = TEGRA210_CLK_AUDIO0_MUX, .present = true }, + [tegra_clk_audio1_mux] = { .dt_id = TEGRA210_CLK_AUDIO1_MUX, .present = true }, + [tegra_clk_audio2_mux] = { .dt_id = TEGRA210_CLK_AUDIO2_MUX, .present = true }, + [tegra_clk_audio3_mux] = { .dt_id = TEGRA210_CLK_AUDIO3_MUX, .present = true }, + [tegra_clk_audio4_mux] = { .dt_id = TEGRA210_CLK_AUDIO4_MUX, .present = true }, + [tegra_clk_spdif_mux] = { .dt_id = TEGRA210_CLK_SPDIF_MUX, .present = true }, + [tegra_clk_clk_out_1_mux] = { .dt_id = TEGRA210_CLK_CLK_OUT_1_MUX, .present = true }, + [tegra_clk_clk_out_2_mux] = { .dt_id = TEGRA210_CLK_CLK_OUT_2_MUX, .present = true }, + [tegra_clk_clk_out_3_mux] = { .dt_id = TEGRA210_CLK_CLK_OUT_3_MUX, .present = true }, + [tegra_clk_maud] = { .dt_id = TEGRA210_CLK_MAUD, .present = true }, + [tegra_clk_mipibif] = { .dt_id = TEGRA210_CLK_MIPIBIF, .present = true }, + [tegra_clk_qspi] = { .dt_id = TEGRA210_CLK_QSPI, .present = true }, + [tegra_clk_sdmmc_legacy] = { .dt_id = TEGRA210_CLK_SDMMC_LEGACY, .present = true }, + [tegra_clk_tsecb] = { .dt_id = TEGRA210_CLK_TSECB, .present = true }, + [tegra_clk_uartape] = { .dt_id = TEGRA210_CLK_UARTAPE, .present = true }, + [tegra_clk_vi_i2c] = { .dt_id = TEGRA210_CLK_VI_I2C, .present = true }, + [tegra_clk_ape] = { .dt_id = TEGRA210_CLK_APE, .present = true }, + [tegra_clk_dbgapb] = { .dt_id = TEGRA210_CLK_DBGAPB, .present = true }, + [tegra_clk_nvdec] = { .dt_id = TEGRA210_CLK_NVDEC, .present = true }, + [tegra_clk_nvenc] = { .dt_id = TEGRA210_CLK_NVENC, .present = true }, + [tegra_clk_nvjpg] = { .dt_id = TEGRA210_CLK_NVJPG, .present = true }, + [tegra_clk_pll_c4_out0] = { .dt_id = TEGRA210_CLK_PLL_C4_OUT0, .present = true }, + [tegra_clk_pll_c4_out1] = { .dt_id = TEGRA210_CLK_PLL_C4_OUT1, .present = true }, + [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 }, +}; + +static struct tegra_devclk devclks[] __initdata = { + { .con_id = "clk_m", .dt_id = TEGRA210_CLK_CLK_M }, + { .con_id = "pll_ref", .dt_id = TEGRA210_CLK_PLL_REF }, + { .con_id = "clk_32k", .dt_id = TEGRA210_CLK_CLK_32K }, + { .con_id = "clk_m_div2", .dt_id = TEGRA210_CLK_CLK_M_DIV2 }, + { .con_id = "clk_m_div4", .dt_id = TEGRA210_CLK_CLK_M_DIV4 }, + { .con_id = "pll_c", .dt_id = TEGRA210_CLK_PLL_C }, + { .con_id = "pll_c_out1", .dt_id = TEGRA210_CLK_PLL_C_OUT1 }, + { .con_id = "pll_c2", .dt_id = TEGRA210_CLK_PLL_C2 }, + { .con_id = "pll_c3", .dt_id = TEGRA210_CLK_PLL_C3 }, + { .con_id = "pll_p", .dt_id = TEGRA210_CLK_PLL_P }, + { .con_id = "pll_p_out1", .dt_id = TEGRA210_CLK_PLL_P_OUT1 }, + { .con_id = "pll_p_out2", .dt_id = TEGRA210_CLK_PLL_P_OUT2 }, + { .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 }, + { .con_id = "pll_u_out", .dt_id = TEGRA210_CLK_PLL_U_OUT }, + { .con_id = "pll_u_out1", .dt_id = TEGRA210_CLK_PLL_U_OUT1 }, + { .con_id = "pll_u_out2", .dt_id = TEGRA210_CLK_PLL_U_OUT2 }, + { .con_id = "pll_u_480M", .dt_id = TEGRA210_CLK_PLL_U_480M }, + { .con_id = "pll_u_60M", .dt_id = TEGRA210_CLK_PLL_U_60M }, + { .con_id = "pll_u_48M", .dt_id = TEGRA210_CLK_PLL_U_48M }, + { .con_id = "pll_d", .dt_id = TEGRA210_CLK_PLL_D }, + { .con_id = "pll_d_out0", .dt_id = TEGRA210_CLK_PLL_D_OUT0 }, + { .con_id = "pll_d2", .dt_id = TEGRA210_CLK_PLL_D2 }, + { .con_id = "pll_d2_out0", .dt_id = TEGRA210_CLK_PLL_D2_OUT0 }, + { .con_id = "pll_a", .dt_id = TEGRA210_CLK_PLL_A }, + { .con_id = "pll_a_out0", .dt_id = TEGRA210_CLK_PLL_A_OUT0 }, + { .con_id = "pll_re_vco", .dt_id = TEGRA210_CLK_PLL_RE_VCO }, + { .con_id = "pll_re_out", .dt_id = TEGRA210_CLK_PLL_RE_OUT }, + { .con_id = "spdif_in_sync", .dt_id = TEGRA210_CLK_SPDIF_IN_SYNC }, + { .con_id = "i2s0_sync", .dt_id = TEGRA210_CLK_I2S0_SYNC }, + { .con_id = "i2s1_sync", .dt_id = TEGRA210_CLK_I2S1_SYNC }, + { .con_id = "i2s2_sync", .dt_id = TEGRA210_CLK_I2S2_SYNC }, + { .con_id = "i2s3_sync", .dt_id = TEGRA210_CLK_I2S3_SYNC }, + { .con_id = "i2s4_sync", .dt_id = TEGRA210_CLK_I2S4_SYNC }, + { .con_id = "vimclk_sync", .dt_id = TEGRA210_CLK_VIMCLK_SYNC }, + { .con_id = "audio0", .dt_id = TEGRA210_CLK_AUDIO0 }, + { .con_id = "audio1", .dt_id = TEGRA210_CLK_AUDIO1 }, + { .con_id = "audio2", .dt_id = TEGRA210_CLK_AUDIO2 }, + { .con_id = "audio3", .dt_id = TEGRA210_CLK_AUDIO3 }, + { .con_id = "audio4", .dt_id = TEGRA210_CLK_AUDIO4 }, + { .con_id = "spdif", .dt_id = TEGRA210_CLK_SPDIF }, + { .con_id = "spdif_2x", .dt_id = TEGRA210_CLK_SPDIF_2X }, + { .con_id = "extern1", .dev_id = "clk_out_1", .dt_id = TEGRA210_CLK_EXTERN1 }, + { .con_id = "extern2", .dev_id = "clk_out_2", .dt_id = TEGRA210_CLK_EXTERN2 }, + { .con_id = "extern3", .dev_id = "clk_out_3", .dt_id = TEGRA210_CLK_EXTERN3 }, + { .con_id = "blink", .dt_id = TEGRA210_CLK_BLINK }, + { .con_id = "cclk_g", .dt_id = TEGRA210_CLK_CCLK_G }, + { .con_id = "cclk_lp", .dt_id = TEGRA210_CLK_CCLK_LP }, + { .con_id = "sclk", .dt_id = TEGRA210_CLK_SCLK }, + { .con_id = "hclk", .dt_id = TEGRA210_CLK_HCLK }, + { .con_id = "pclk", .dt_id = TEGRA210_CLK_PCLK }, + { .con_id = "fuse", .dt_id = TEGRA210_CLK_FUSE }, + { .dev_id = "rtc-tegra", .dt_id = TEGRA210_CLK_RTC }, + { .dev_id = "timer", .dt_id = TEGRA210_CLK_TIMER }, + { .con_id = "pll_c4_out0", .dt_id = TEGRA210_CLK_PLL_C4_OUT0 }, + { .con_id = "pll_c4_out1", .dt_id = TEGRA210_CLK_PLL_C4_OUT1 }, + { .con_id = "pll_c4_out2", .dt_id = TEGRA210_CLK_PLL_C4_OUT2 }, + { .con_id = "pll_c4_out3", .dt_id = TEGRA210_CLK_PLL_C4_OUT3 }, + { .con_id = "dpaux", .dt_id = TEGRA210_CLK_DPAUX }, + { .con_id = "sor0", .dt_id = TEGRA210_CLK_SOR0 }, +}; + +static struct tegra_audio_clk_info tegra210_audio_plls[] = { + { "pll_a", &pll_a_params, tegra_clk_pll_a, "pll_ref" }, + { "pll_a1", &pll_a1_params, tegra_clk_pll_a1, "pll_ref" }, +}; + +static struct clk **clks; + +static void tegra210_utmi_param_configure(void __iomem *clk_base) +{ + 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 + 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 + 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); + + 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 __init void tegra210_periph_clk_init(void __iomem *clk_base, + void __iomem *pmc_base) +{ + struct clk *clk; + + /* xusb_ss_div2 */ + clk = clk_register_fixed_factor(NULL, "xusb_ss_div2", "xusb_ss_src", 0, + 1, 2); + clks[TEGRA210_CLK_XUSB_SS_DIV2] = clk; + + /* pll_d_dsi_out */ + clk = clk_register_gate(NULL, "pll_d_dsi_out", "pll_d_out0", 0, + clk_base + PLLD_MISC0, 21, 0, &pll_d_lock); + clks[TEGRA210_CLK_PLL_D_DSI_OUT] = clk; + + /* dsia */ + clk = tegra_clk_register_periph_gate("dsia", "pll_d_dsi_out", 0, + clk_base, 0, 48, + periph_clk_enb_refcnt); + clks[TEGRA210_CLK_DSIA] = clk; + + /* dsib */ + clk = tegra_clk_register_periph_gate("dsib", "pll_d_dsi_out", 0, + clk_base, 0, 82, + periph_clk_enb_refcnt); + clks[TEGRA210_CLK_DSIB] = clk; + + /* emc mux */ + clk = clk_register_mux(NULL, "emc_mux", mux_pllmcp_clkm, + ARRAY_SIZE(mux_pllmcp_clkm), 0, + clk_base + CLK_SOURCE_EMC, + 29, 3, 0, &emc_lock); + + clk = tegra_clk_register_mc("mc", "emc_mux", clk_base + CLK_SOURCE_EMC, + &emc_lock); + clks[TEGRA210_CLK_MC] = clk; + + /* cml0 */ + clk = clk_register_gate(NULL, "cml0", "pll_e", 0, clk_base + PLLE_AUX, + 0, 0, &pll_e_lock); + clk_register_clkdev(clk, "cml0", NULL); + clks[TEGRA210_CLK_CML0] = clk; + + /* cml1 */ + clk = clk_register_gate(NULL, "cml1", "pll_e", 0, clk_base + PLLE_AUX, + 1, 0, &pll_e_lock); + clk_register_clkdev(clk, "cml1", NULL); + clks[TEGRA210_CLK_CML1] = clk; + + tegra_periph_clk_init(clk_base, pmc_base, tegra210_clks, &pll_p_params); +} + +static void __init tegra210_pll_init(void __iomem *clk_base, + void __iomem *pmc) +{ + u32 val; + struct clk *clk; + + /* PLLC */ + clk = tegra_clk_register_pllxc_tegra210("pll_c", "pll_ref", clk_base, + pmc, 0, &pll_c_params, NULL); + if (!WARN_ON(IS_ERR(clk))) + clk_register_clkdev(clk, "pll_c", NULL); + clks[TEGRA210_CLK_PLL_C] = clk; + + /* PLLC_OUT1 */ + clk = tegra_clk_register_divider("pll_c_out1_div", "pll_c", + clk_base + PLLC_OUT, 0, TEGRA_DIVIDER_ROUND_UP, + 8, 8, 1, NULL); + clk = tegra_clk_register_pll_out("pll_c_out1", "pll_c_out1_div", + clk_base + PLLC_OUT, 1, 0, + CLK_SET_RATE_PARENT, 0, NULL); + clk_register_clkdev(clk, "pll_c_out1", NULL); + clks[TEGRA210_CLK_PLL_C_OUT1] = clk; + + /* PLLC_UD */ + clk = clk_register_fixed_factor(NULL, "pll_c_ud", "pll_c", + CLK_SET_RATE_PARENT, 1, 1); + clk_register_clkdev(clk, "pll_c_ud", NULL); + clks[TEGRA210_CLK_PLL_C_UD] = clk; + + /* PLLC2 */ + clk = tegra_clk_register_pllc_tegra210("pll_c2", "pll_ref", clk_base, + pmc, 0, &pll_c2_params, NULL); + clk_register_clkdev(clk, "pll_c2", NULL); + clks[TEGRA210_CLK_PLL_C2] = clk; + + /* PLLC3 */ + clk = tegra_clk_register_pllc_tegra210("pll_c3", "pll_ref", clk_base, + pmc, 0, &pll_c3_params, NULL); + clk_register_clkdev(clk, "pll_c3", NULL); + clks[TEGRA210_CLK_PLL_C3] = clk; + + /* PLLM */ + clk = tegra_clk_register_pllm("pll_m", "osc", clk_base, pmc, + CLK_SET_RATE_GATE, &pll_m_params, NULL); + clk_register_clkdev(clk, "pll_m", NULL); + clks[TEGRA210_CLK_PLL_M] = clk; + + /* PLLMB */ + clk = tegra_clk_register_pllmb("pll_mb", "osc", clk_base, pmc, + CLK_SET_RATE_GATE, &pll_mb_params, NULL); + 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); + clk_register_clkdev(clk, "pll_m_ud", NULL); + clks[TEGRA210_CLK_PLL_M_UD] = clk; + + /* PLLU_VCO */ + val = readl(clk_base + pll_u_vco_params.base_reg); + val &= ~PLLU_BASE_OVERRIDE; /* disable PLLU_OVERRIDE */ + writel(val, clk_base + pll_u_vco_params.base_reg); + + clk = tegra_clk_register_pllre("pll_u_vco", "pll_ref", clk_base, pmc, + 0, &pll_u_vco_params, &pll_u_lock, pll_ref_freq); + 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, + clk_base + PLLU_BASE, 16, 4, 0, + pll_vco_post_div_table, NULL); + clk_register_clkdev(clk, "pll_u_out", NULL); + clks[TEGRA210_CLK_PLL_U_OUT] = clk; + + /* PLLU_OUT1 */ + clk = tegra_clk_register_divider("pll_u_out1_div", "pll_u_out", + clk_base + PLLU_OUTA, 0, + TEGRA_DIVIDER_ROUND_UP, + 8, 8, 1, &pll_u_lock); + clk = tegra_clk_register_pll_out("pll_u_out1", "pll_u_out1_div", + clk_base + PLLU_OUTA, 1, 0, + CLK_SET_RATE_PARENT, 0, &pll_u_lock); + clk_register_clkdev(clk, "pll_u_out1", NULL); + clks[TEGRA210_CLK_PLL_U_OUT1] = clk; + + /* PLLU_OUT2 */ + clk = tegra_clk_register_divider("pll_u_out2_div", "pll_u_out", + clk_base + PLLU_OUTA, 0, + TEGRA_DIVIDER_ROUND_UP, + 24, 8, 1, &pll_u_lock); + clk = tegra_clk_register_pll_out("pll_u_out2", "pll_u_out2_div", + clk_base + PLLU_OUTA, 17, 16, + CLK_SET_RATE_PARENT, 0, &pll_u_lock); + clk_register_clkdev(clk, "pll_u_out2", NULL); + clks[TEGRA210_CLK_PLL_U_OUT2] = clk; + + tegra210_utmi_param_configure(clk_base); + + /* PLLU_480M */ + clk = clk_register_gate(NULL, "pll_u_480M", "pll_u_vco", + CLK_SET_RATE_PARENT, clk_base + PLLU_BASE, + 22, 0, &pll_u_lock); + clk_register_clkdev(clk, "pll_u_480M", NULL); + clks[TEGRA210_CLK_PLL_U_480M] = clk; + + /* PLLU_60M */ + clk = clk_register_gate(NULL, "pll_u_60M", "pll_u_out2", + CLK_SET_RATE_PARENT, clk_base + PLLU_BASE, + 23, 0, NULL); + clk_register_clkdev(clk, "pll_u_60M", NULL); + clks[TEGRA210_CLK_PLL_U_60M] = clk; + + /* PLLU_48M */ + clk = clk_register_gate(NULL, "pll_u_48M", "pll_u_out1", + CLK_SET_RATE_PARENT, clk_base + PLLU_BASE, + 25, 0, NULL); + clk_register_clkdev(clk, "pll_u_48M", NULL); + clks[TEGRA210_CLK_PLL_U_48M] = clk; + + /* PLLD */ + clk = tegra_clk_register_pll("pll_d", "pll_ref", clk_base, pmc, 0, + &pll_d_params, &pll_d_lock); + clk_register_clkdev(clk, "pll_d", NULL); + clks[TEGRA210_CLK_PLL_D] = clk; + + /* PLLD_OUT0 */ + clk = clk_register_fixed_factor(NULL, "pll_d_out0", "pll_d", + CLK_SET_RATE_PARENT, 1, 2); + clk_register_clkdev(clk, "pll_d_out0", NULL); + clks[TEGRA210_CLK_PLL_D_OUT0] = clk; + + /* PLLRE */ + clk = tegra_clk_register_pllre("pll_re_vco", "pll_ref", clk_base, pmc, + 0, &pll_re_vco_params, &pll_re_lock, pll_ref_freq); + clk_register_clkdev(clk, "pll_re_vco", NULL); + clks[TEGRA210_CLK_PLL_RE_VCO] = clk; + + clk = clk_register_divider_table(NULL, "pll_re_out", "pll_re_vco", 0, + clk_base + PLLRE_BASE, 16, 5, 0, + pll_vco_post_div_table, &pll_re_lock); + clk_register_clkdev(clk, "pll_re_out", NULL); + clks[TEGRA210_CLK_PLL_RE_OUT] = clk; + + /* PLLE */ + clk = tegra_clk_register_plle_tegra210("pll_e", "pll_ref", + clk_base, 0, &pll_e_params, NULL); + clk_register_clkdev(clk, "pll_e", NULL); + clks[TEGRA210_CLK_PLL_E] = clk; + + /* PLLC4 */ + clk = tegra_clk_register_pllre("pll_c4_vco", "pll_ref", clk_base, pmc, + 0, &pll_c4_vco_params, NULL, pll_ref_freq); + clk_register_clkdev(clk, "pll_c4_vco", NULL); + clks[TEGRA210_CLK_PLL_C4] = clk; + + /* PLLC4_OUT0 */ + clk = clk_register_divider_table(NULL, "pll_c4_out0", "pll_c4_vco", 0, + clk_base + PLLC4_BASE, 19, 4, 0, + pll_vco_post_div_table, NULL); + clk_register_clkdev(clk, "pll_c4_out0", NULL); + clks[TEGRA210_CLK_PLL_C4_OUT0] = clk; + + /* PLLC4_OUT1 */ + clk = clk_register_fixed_factor(NULL, "pll_c4_out1", "pll_c4_vco", + CLK_SET_RATE_PARENT, 1, 3); + clk_register_clkdev(clk, "pll_c4_out1", NULL); + clks[TEGRA210_CLK_PLL_C4_OUT1] = clk; + + /* PLLC4_OUT2 */ + clk = clk_register_fixed_factor(NULL, "pll_c4_out2", "pll_c4_vco", + CLK_SET_RATE_PARENT, 1, 5); + clk_register_clkdev(clk, "pll_c4_out2", NULL); + clks[TEGRA210_CLK_PLL_C4_OUT2] = clk; + + /* PLLC4_OUT3 */ + clk = tegra_clk_register_divider("pll_c4_out3_div", "pll_c4_out0", + clk_base + PLLC4_OUT, 0, TEGRA_DIVIDER_ROUND_UP, + 8, 8, 1, NULL); + clk = tegra_clk_register_pll_out("pll_c4_out3", "pll_c4_out3_div", + clk_base + PLLC4_OUT, 1, 0, + CLK_SET_RATE_PARENT, 0, NULL); + clk_register_clkdev(clk, "pll_c4_out3", NULL); + clks[TEGRA210_CLK_PLL_C4_OUT3] = clk; + + /* PLLDP */ + clk = tegra_clk_register_pllss_tegra210("pll_dp", "pll_ref", clk_base, + 0, &pll_dp_params, NULL); + clk_register_clkdev(clk, "pll_dp", NULL); + clks[TEGRA210_CLK_PLL_DP] = clk; + + /* PLLD2 */ + clk = tegra_clk_register_pllss_tegra210("pll_d2", "pll_ref", clk_base, + 0, &pll_d2_params, NULL); + clk_register_clkdev(clk, "pll_d2", NULL); + clks[TEGRA210_CLK_PLL_D2] = clk; + + /* PLLD2_OUT0 */ + clk = clk_register_fixed_factor(NULL, "pll_d2_out0", "pll_d2", + CLK_SET_RATE_PARENT, 1, 1); + clk_register_clkdev(clk, "pll_d2_out0", NULL); + clks[TEGRA210_CLK_PLL_D2_OUT0] = clk; + + /* PLLP_OUT2 */ + clk = clk_register_fixed_factor(NULL, "pll_p_out2", "pll_p", + CLK_SET_RATE_PARENT, 1, 2); + clk_register_clkdev(clk, "pll_p_out2", NULL); + clks[TEGRA210_CLK_PLL_P_OUT2] = clk; + +} + +/* Tegra210 CPU clock and reset control functions */ +static void tegra210_wait_cpu_in_reset(u32 cpu) +{ + unsigned int reg; + + do { + reg = readl(clk_base + CLK_RST_CONTROLLER_CPU_CMPLX_STATUS); + cpu_relax(); + } while (!(reg & (1 << cpu))); /* check CPU been reset or not */ +} + +static void tegra210_disable_cpu_clock(u32 cpu) +{ + /* flow controller would take care in the power sequence. */ +} + +#ifdef CONFIG_PM_SLEEP +static void tegra210_cpu_clock_suspend(void) +{ + /* switch coresite to clk_m, save off original source */ + tegra210_cpu_clk_sctx.clk_csite_src = + readl(clk_base + CLK_SOURCE_CSITE); + writel(3 << 30, clk_base + CLK_SOURCE_CSITE); +} + +static void tegra210_cpu_clock_resume(void) +{ + writel(tegra210_cpu_clk_sctx.clk_csite_src, + clk_base + CLK_SOURCE_CSITE); +} +#endif + +static struct tegra_cpu_car_ops tegra210_cpu_car_ops = { + .wait_for_reset = tegra210_wait_cpu_in_reset, + .disable_clock = tegra210_disable_cpu_clock, +#ifdef CONFIG_PM_SLEEP + .suspend = tegra210_cpu_clock_suspend, + .resume = tegra210_cpu_clock_resume, +#endif +}; + +static const struct of_device_id pmc_match[] __initconst = { + { .compatible = "nvidia,tegra210-pmc" }, + { }, +}; + +static struct tegra_clk_init_table init_table[] __initdata = { + { TEGRA210_CLK_UARTA, TEGRA210_CLK_PLL_P, 408000000, 0 }, + { TEGRA210_CLK_UARTB, TEGRA210_CLK_PLL_P, 408000000, 0 }, + { TEGRA210_CLK_UARTC, TEGRA210_CLK_PLL_P, 408000000, 0 }, + { TEGRA210_CLK_UARTD, TEGRA210_CLK_PLL_P, 408000000, 0 }, + { TEGRA210_CLK_PLL_A, TEGRA210_CLK_CLK_MAX, 564480000, 1 }, + { TEGRA210_CLK_PLL_A_OUT0, TEGRA210_CLK_CLK_MAX, 11289600, 1 }, + { TEGRA210_CLK_EXTERN1, TEGRA210_CLK_PLL_A_OUT0, 0, 1 }, + { TEGRA210_CLK_CLK_OUT_1_MUX, TEGRA210_CLK_EXTERN1, 0, 1 }, + { TEGRA210_CLK_CLK_OUT_1, TEGRA210_CLK_CLK_MAX, 0, 1 }, + { TEGRA210_CLK_I2S0, TEGRA210_CLK_PLL_A_OUT0, 11289600, 0 }, + { TEGRA210_CLK_I2S1, TEGRA210_CLK_PLL_A_OUT0, 11289600, 0 }, + { TEGRA210_CLK_I2S2, TEGRA210_CLK_PLL_A_OUT0, 11289600, 0 }, + { TEGRA210_CLK_I2S3, TEGRA210_CLK_PLL_A_OUT0, 11289600, 0 }, + { TEGRA210_CLK_I2S4, TEGRA210_CLK_PLL_A_OUT0, 11289600, 0 }, + { TEGRA210_CLK_HOST1X, TEGRA210_CLK_PLL_P, 136000000, 1 }, + { TEGRA210_CLK_SCLK_MUX, TEGRA210_CLK_PLL_P, 0, 1 }, + { TEGRA210_CLK_SCLK, TEGRA210_CLK_CLK_MAX, 102000000, 1 }, + { TEGRA210_CLK_DFLL_SOC, TEGRA210_CLK_PLL_P, 51000000, 1 }, + { TEGRA210_CLK_DFLL_REF, TEGRA210_CLK_PLL_P, 51000000, 1 }, + { TEGRA210_CLK_SBC4, TEGRA210_CLK_PLL_P, 12000000, 1 }, + { TEGRA210_CLK_PLL_RE_VCO, TEGRA210_CLK_CLK_MAX, 672000000, 1 }, + { TEGRA210_CLK_XUSB_GATE, TEGRA210_CLK_CLK_MAX, 0, 1 }, + { TEGRA210_CLK_XUSB_SS_SRC, TEGRA210_CLK_PLL_U_480M, 120000000, 0 }, + { TEGRA210_CLK_XUSB_FS_SRC, TEGRA210_CLK_PLL_U_48M, 48000000, 0 }, + { TEGRA210_CLK_XUSB_HS_SRC, TEGRA210_CLK_XUSB_SS_SRC, 120000000, 0 }, + { TEGRA210_CLK_XUSB_SSP_SRC, TEGRA210_CLK_XUSB_SS_SRC, 120000000, 0 }, + { TEGRA210_CLK_XUSB_FALCON_SRC, TEGRA210_CLK_PLL_P_OUT_XUSB, 204000000, 0 }, + { TEGRA210_CLK_XUSB_HOST_SRC, TEGRA210_CLK_PLL_P_OUT_XUSB, 102000000, 0 }, + { TEGRA210_CLK_XUSB_DEV_SRC, TEGRA210_CLK_PLL_P_OUT_XUSB, 102000000, 0 }, + { TEGRA210_CLK_SATA, TEGRA210_CLK_PLL_P, 104000000, 0 }, + { TEGRA210_CLK_SATA_OOB, TEGRA210_CLK_PLL_P, 204000000, 0 }, + { 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 }, + { 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 }, + { TEGRA210_CLK_I2C3, TEGRA210_CLK_PLL_P, 0, 0 }, + { TEGRA210_CLK_I2C4, TEGRA210_CLK_PLL_P, 0, 0 }, + { TEGRA210_CLK_I2C5, TEGRA210_CLK_PLL_P, 0, 0 }, + { TEGRA210_CLK_I2C6, TEGRA210_CLK_PLL_P, 0, 0 }, + { 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 }, + /* This MUST be the last entry. */ + { TEGRA210_CLK_CLK_MAX, TEGRA210_CLK_CLK_MAX, 0, 0 }, +}; + +/** + * tegra210_clock_apply_init_table - initialize clocks on Tegra210 SoCs + * + * Program an initial clock rate and enable or disable clocks needed + * by the rest of the kernel, for Tegra210 SoCs. It is intended to be + * called by assigning a pointer to it to tegra_clk_apply_init_table - + * this will be called as an arch_initcall. No return value. + */ +static void __init tegra210_clock_apply_init_table(void) +{ + tegra_init_from_table(init_table, clks, TEGRA210_CLK_CLK_MAX); +} + +/** + * tegra210_clock_init - Tegra210-specific clock initialization + * @np: struct device_node * of the DT node for the SoC CAR IP block + * + * Register most SoC clocks for the Tegra210 system-on-chip. Intended + * to be called by the OF init code when a DT node with the + * "nvidia,tegra210-car" string is encountered, and declared with + * CLK_OF_DECLARE. No return value. + */ +static void __init tegra210_clock_init(struct device_node *np) +{ + struct device_node *node; + u32 value, clk_m_div; + + clk_base = of_iomap(np, 0); + if (!clk_base) { + pr_err("ioremap tegra210 CAR failed\n"); + return; + } + + node = of_find_matching_node(NULL, pmc_match); + if (!node) { + pr_err("Failed to find pmc node\n"); + WARN_ON(1); + return; + } + + pmc_base = of_iomap(node, 0); + if (!pmc_base) { + pr_err("Can't map pmc registers\n"); + WARN_ON(1); + return; + } + + clks = tegra_clk_init(clk_base, TEGRA210_CLK_CLK_MAX, + TEGRA210_CAR_BANK_COUNT); + if (!clks) + return; + + value = clk_readl(clk_base + SPARE_REG0) >> CLK_M_DIVISOR_SHIFT; + clk_m_div = (value & CLK_M_DIVISOR_MASK) + 1; + + if (tegra_osc_clk_init(clk_base, tegra210_clks, tegra210_input_freq, + ARRAY_SIZE(tegra210_input_freq), clk_m_div, + &osc_freq, &pll_ref_freq) < 0) + return; + + tegra_fixed_clk_init(tegra210_clks); + tegra210_pll_init(clk_base, pmc_base); + tegra210_periph_clk_init(clk_base, pmc_base); + tegra_audio_clk_init(clk_base, pmc_base, tegra210_clks, + tegra210_audio_plls, + ARRAY_SIZE(tegra210_audio_plls)); + tegra_pmc_clk_init(pmc_base, tegra210_clks); + + /* For Tegra210, PLLD is the only source for DSIA & DSIB */ + value = clk_readl(clk_base + PLLD_BASE); + value &= ~BIT(25); + clk_writel(value, clk_base + PLLD_BASE); + + tegra_clk_apply_init_table = tegra210_clock_apply_init_table; + + tegra_super_clk_gen5_init(clk_base, pmc_base, tegra210_clks, + &pll_x_params); + tegra_add_of_provider(np); + tegra_register_devclks(devclks, ARRAY_SIZE(devclks)); + + tegra_cpu_car_ops = &tegra210_cpu_car_ops; +} +CLK_OF_DECLARE(tegra210, "nvidia,tegra210-car", tegra210_clock_init); diff --git a/drivers/clk/tegra/clk-tegra30.c b/drivers/clk/tegra/clk-tegra30.c index b90db615c..0478565cf 100644 --- a/drivers/clk/tegra/clk-tegra30.c +++ b/drivers/clk/tegra/clk-tegra30.c @@ -224,188 +224,192 @@ struct utmi_clk_param { }; static const struct utmi_clk_param utmi_parameters[] = { -/* OSC_FREQUENCY, ENABLE_DLY, STABLE_CNT, ACTIVE_DLY, XTAL_FREQ_CNT */ - {13000000, 0x02, 0x33, 0x05, 0x7F}, - {19200000, 0x03, 0x4B, 0x06, 0xBB}, - {12000000, 0x02, 0x2F, 0x04, 0x76}, - {26000000, 0x04, 0x66, 0x09, 0xFE}, - {16800000, 0x03, 0x41, 0x0A, 0xA4}, + { + .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 = 0x04, + .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_pll_freq_table pll_c_freq_table[] = { - { 12000000, 1040000000, 520, 6, 0, 8}, - { 13000000, 1040000000, 480, 6, 0, 8}, - { 16800000, 1040000000, 495, 8, 0, 8}, /* actual: 1039.5 MHz */ - { 19200000, 1040000000, 325, 6, 0, 6}, - { 26000000, 1040000000, 520, 13, 0, 8}, - - { 12000000, 832000000, 416, 6, 0, 8}, - { 13000000, 832000000, 832, 13, 0, 8}, - { 16800000, 832000000, 396, 8, 0, 8}, /* actual: 831.6 MHz */ - { 19200000, 832000000, 260, 6, 0, 8}, - { 26000000, 832000000, 416, 13, 0, 8}, - - { 12000000, 624000000, 624, 12, 0, 8}, - { 13000000, 624000000, 624, 13, 0, 8}, - { 16800000, 600000000, 520, 14, 0, 8}, - { 19200000, 624000000, 520, 16, 0, 8}, - { 26000000, 624000000, 624, 26, 0, 8}, - - { 12000000, 600000000, 600, 12, 0, 8}, - { 13000000, 600000000, 600, 13, 0, 8}, - { 16800000, 600000000, 500, 14, 0, 8}, - { 19200000, 600000000, 375, 12, 0, 6}, - { 26000000, 600000000, 600, 26, 0, 8}, - - { 12000000, 520000000, 520, 12, 0, 8}, - { 13000000, 520000000, 520, 13, 0, 8}, - { 16800000, 520000000, 495, 16, 0, 8}, /* actual: 519.75 MHz */ - { 19200000, 520000000, 325, 12, 0, 6}, - { 26000000, 520000000, 520, 26, 0, 8}, - - { 12000000, 416000000, 416, 12, 0, 8}, - { 13000000, 416000000, 416, 13, 0, 8}, - { 16800000, 416000000, 396, 16, 0, 8}, /* actual: 415.8 MHz */ - { 19200000, 416000000, 260, 12, 0, 6}, - { 26000000, 416000000, 416, 26, 0, 8}, - { 0, 0, 0, 0, 0, 0 }, + { 12000000, 1040000000, 520, 6, 1, 8 }, + { 13000000, 1040000000, 480, 6, 1, 8 }, + { 16800000, 1040000000, 495, 8, 1, 8 }, /* actual: 1039.5 MHz */ + { 19200000, 1040000000, 325, 6, 1, 6 }, + { 26000000, 1040000000, 520, 13, 1, 8 }, + { 12000000, 832000000, 416, 6, 1, 8 }, + { 13000000, 832000000, 832, 13, 1, 8 }, + { 16800000, 832000000, 396, 8, 1, 8 }, /* actual: 831.6 MHz */ + { 19200000, 832000000, 260, 6, 1, 8 }, + { 26000000, 832000000, 416, 13, 1, 8 }, + { 12000000, 624000000, 624, 12, 1, 8 }, + { 13000000, 624000000, 624, 13, 1, 8 }, + { 16800000, 600000000, 520, 14, 1, 8 }, + { 19200000, 624000000, 520, 16, 1, 8 }, + { 26000000, 624000000, 624, 26, 1, 8 }, + { 12000000, 600000000, 600, 12, 1, 8 }, + { 13000000, 600000000, 600, 13, 1, 8 }, + { 16800000, 600000000, 500, 14, 1, 8 }, + { 19200000, 600000000, 375, 12, 1, 6 }, + { 26000000, 600000000, 600, 26, 1, 8 }, + { 12000000, 520000000, 520, 12, 1, 8 }, + { 13000000, 520000000, 520, 13, 1, 8 }, + { 16800000, 520000000, 495, 16, 1, 8 }, /* actual: 519.75 MHz */ + { 19200000, 520000000, 325, 12, 1, 6 }, + { 26000000, 520000000, 520, 26, 1, 8 }, + { 12000000, 416000000, 416, 12, 1, 8 }, + { 13000000, 416000000, 416, 13, 1, 8 }, + { 16800000, 416000000, 396, 16, 1, 8 }, /* actual: 415.8 MHz */ + { 19200000, 416000000, 260, 12, 1, 6 }, + { 26000000, 416000000, 416, 26, 1, 8 }, + { 0, 0, 0, 0, 0, 0 }, }; static struct tegra_clk_pll_freq_table pll_m_freq_table[] = { - { 12000000, 666000000, 666, 12, 0, 8}, - { 13000000, 666000000, 666, 13, 0, 8}, - { 16800000, 666000000, 555, 14, 0, 8}, - { 19200000, 666000000, 555, 16, 0, 8}, - { 26000000, 666000000, 666, 26, 0, 8}, - { 12000000, 600000000, 600, 12, 0, 8}, - { 13000000, 600000000, 600, 13, 0, 8}, - { 16800000, 600000000, 500, 14, 0, 8}, - { 19200000, 600000000, 375, 12, 0, 6}, - { 26000000, 600000000, 600, 26, 0, 8}, - { 0, 0, 0, 0, 0, 0 }, + { 12000000, 666000000, 666, 12, 1, 8 }, + { 13000000, 666000000, 666, 13, 1, 8 }, + { 16800000, 666000000, 555, 14, 1, 8 }, + { 19200000, 666000000, 555, 16, 1, 8 }, + { 26000000, 666000000, 666, 26, 1, 8 }, + { 12000000, 600000000, 600, 12, 1, 8 }, + { 13000000, 600000000, 600, 13, 1, 8 }, + { 16800000, 600000000, 500, 14, 1, 8 }, + { 19200000, 600000000, 375, 12, 1, 6 }, + { 26000000, 600000000, 600, 26, 1, 8 }, + { 0, 0, 0, 0, 0, 0 }, }; static struct tegra_clk_pll_freq_table pll_p_freq_table[] = { - { 12000000, 216000000, 432, 12, 1, 8}, - { 13000000, 216000000, 432, 13, 1, 8}, - { 16800000, 216000000, 360, 14, 1, 8}, - { 19200000, 216000000, 360, 16, 1, 8}, - { 26000000, 216000000, 432, 26, 1, 8}, - { 0, 0, 0, 0, 0, 0 }, + { 12000000, 216000000, 432, 12, 2, 8 }, + { 13000000, 216000000, 432, 13, 2, 8 }, + { 16800000, 216000000, 360, 14, 2, 8 }, + { 19200000, 216000000, 360, 16, 2, 8 }, + { 26000000, 216000000, 432, 26, 2, 8 }, + { 0, 0, 0, 0, 0, 0 }, }; static struct tegra_clk_pll_freq_table pll_a_freq_table[] = { - { 9600000, 564480000, 294, 5, 0, 4}, - { 9600000, 552960000, 288, 5, 0, 4}, - { 9600000, 24000000, 5, 2, 0, 1}, - - { 28800000, 56448000, 49, 25, 0, 1}, - { 28800000, 73728000, 64, 25, 0, 1}, - { 28800000, 24000000, 5, 6, 0, 1}, - { 0, 0, 0, 0, 0, 0 }, + { 9600000, 564480000, 294, 5, 1, 4 }, + { 9600000, 552960000, 288, 5, 1, 4 }, + { 9600000, 24000000, 5, 2, 1, 1 }, + { 28800000, 56448000, 49, 25, 1, 1 }, + { 28800000, 73728000, 64, 25, 1, 1 }, + { 28800000, 24000000, 5, 6, 1, 1 }, + { 0, 0, 0, 0, 0, 0 }, }; static struct tegra_clk_pll_freq_table pll_d_freq_table[] = { - { 12000000, 216000000, 216, 12, 0, 4}, - { 13000000, 216000000, 216, 13, 0, 4}, - { 16800000, 216000000, 180, 14, 0, 4}, - { 19200000, 216000000, 180, 16, 0, 4}, - { 26000000, 216000000, 216, 26, 0, 4}, - - { 12000000, 594000000, 594, 12, 0, 8}, - { 13000000, 594000000, 594, 13, 0, 8}, - { 16800000, 594000000, 495, 14, 0, 8}, - { 19200000, 594000000, 495, 16, 0, 8}, - { 26000000, 594000000, 594, 26, 0, 8}, - - { 12000000, 1000000000, 1000, 12, 0, 12}, - { 13000000, 1000000000, 1000, 13, 0, 12}, - { 19200000, 1000000000, 625, 12, 0, 8}, - { 26000000, 1000000000, 1000, 26, 0, 12}, - - { 0, 0, 0, 0, 0, 0 }, + { 12000000, 216000000, 216, 12, 1, 4 }, + { 13000000, 216000000, 216, 13, 1, 4 }, + { 16800000, 216000000, 180, 14, 1, 4 }, + { 19200000, 216000000, 180, 16, 1, 4 }, + { 26000000, 216000000, 216, 26, 1, 4 }, + { 12000000, 594000000, 594, 12, 1, 8 }, + { 13000000, 594000000, 594, 13, 1, 8 }, + { 16800000, 594000000, 495, 14, 1, 8 }, + { 19200000, 594000000, 495, 16, 1, 8 }, + { 26000000, 594000000, 594, 26, 1, 8 }, + { 12000000, 1000000000, 1000, 12, 1, 12 }, + { 13000000, 1000000000, 1000, 13, 1, 12 }, + { 19200000, 1000000000, 625, 12, 1, 8 }, + { 26000000, 1000000000, 1000, 26, 1, 12 }, + { 0, 0, 0, 0, 0, 0 }, }; -static struct pdiv_map pllu_p[] = { +static const struct pdiv_map pllu_p[] = { { .pdiv = 1, .hw_val = 1 }, { .pdiv = 2, .hw_val = 0 }, { .pdiv = 0, .hw_val = 0 }, }; static struct tegra_clk_pll_freq_table pll_u_freq_table[] = { - { 12000000, 480000000, 960, 12, 0, 12}, - { 13000000, 480000000, 960, 13, 0, 12}, - { 16800000, 480000000, 400, 7, 0, 5}, - { 19200000, 480000000, 200, 4, 0, 3}, - { 26000000, 480000000, 960, 26, 0, 12}, - { 0, 0, 0, 0, 0, 0 }, + { 12000000, 480000000, 960, 12, 1, 12 }, + { 13000000, 480000000, 960, 13, 1, 12 }, + { 16800000, 480000000, 400, 7, 1, 5 }, + { 19200000, 480000000, 200, 4, 1, 3 }, + { 26000000, 480000000, 960, 26, 1, 12 }, + { 0, 0, 0, 0, 0, 0 }, }; static struct tegra_clk_pll_freq_table pll_x_freq_table[] = { /* 1.7 GHz */ - { 12000000, 1700000000, 850, 6, 0, 8}, - { 13000000, 1700000000, 915, 7, 0, 8}, /* actual: 1699.2 MHz */ - { 16800000, 1700000000, 708, 7, 0, 8}, /* actual: 1699.2 MHz */ - { 19200000, 1700000000, 885, 10, 0, 8}, /* actual: 1699.2 MHz */ - { 26000000, 1700000000, 850, 13, 0, 8}, - + { 12000000, 1700000000, 850, 6, 1, 8 }, + { 13000000, 1700000000, 915, 7, 1, 8 }, /* actual: 1699.2 MHz */ + { 16800000, 1700000000, 708, 7, 1, 8 }, /* actual: 1699.2 MHz */ + { 19200000, 1700000000, 885, 10, 1, 8 }, /* actual: 1699.2 MHz */ + { 26000000, 1700000000, 850, 13, 1, 8 }, /* 1.6 GHz */ - { 12000000, 1600000000, 800, 6, 0, 8}, - { 13000000, 1600000000, 738, 6, 0, 8}, /* actual: 1599.0 MHz */ - { 16800000, 1600000000, 857, 9, 0, 8}, /* actual: 1599.7 MHz */ - { 19200000, 1600000000, 500, 6, 0, 8}, - { 26000000, 1600000000, 800, 13, 0, 8}, - + { 12000000, 1600000000, 800, 6, 1, 8 }, + { 13000000, 1600000000, 738, 6, 1, 8 }, /* actual: 1599.0 MHz */ + { 16800000, 1600000000, 857, 9, 1, 8 }, /* actual: 1599.7 MHz */ + { 19200000, 1600000000, 500, 6, 1, 8 }, + { 26000000, 1600000000, 800, 13, 1, 8 }, /* 1.5 GHz */ - { 12000000, 1500000000, 750, 6, 0, 8}, - { 13000000, 1500000000, 923, 8, 0, 8}, /* actual: 1499.8 MHz */ - { 16800000, 1500000000, 625, 7, 0, 8}, - { 19200000, 1500000000, 625, 8, 0, 8}, - { 26000000, 1500000000, 750, 13, 0, 8}, - + { 12000000, 1500000000, 750, 6, 1, 8 }, + { 13000000, 1500000000, 923, 8, 1, 8 }, /* actual: 1499.8 MHz */ + { 16800000, 1500000000, 625, 7, 1, 8 }, + { 19200000, 1500000000, 625, 8, 1, 8 }, + { 26000000, 1500000000, 750, 13, 1, 8 }, /* 1.4 GHz */ - { 12000000, 1400000000, 700, 6, 0, 8}, - { 13000000, 1400000000, 969, 9, 0, 8}, /* actual: 1399.7 MHz */ - { 16800000, 1400000000, 1000, 12, 0, 8}, - { 19200000, 1400000000, 875, 12, 0, 8}, - { 26000000, 1400000000, 700, 13, 0, 8}, - + { 12000000, 1400000000, 700, 6, 1, 8 }, + { 13000000, 1400000000, 969, 9, 1, 8 }, /* actual: 1399.7 MHz */ + { 16800000, 1400000000, 1000, 12, 1, 8 }, + { 19200000, 1400000000, 875, 12, 1, 8 }, + { 26000000, 1400000000, 700, 13, 1, 8 }, /* 1.3 GHz */ - { 12000000, 1300000000, 975, 9, 0, 8}, - { 13000000, 1300000000, 1000, 10, 0, 8}, - { 16800000, 1300000000, 928, 12, 0, 8}, /* actual: 1299.2 MHz */ - { 19200000, 1300000000, 812, 12, 0, 8}, /* actual: 1299.2 MHz */ - { 26000000, 1300000000, 650, 13, 0, 8}, - + { 12000000, 1300000000, 975, 9, 1, 8 }, + { 13000000, 1300000000, 1000, 10, 1, 8 }, + { 16800000, 1300000000, 928, 12, 1, 8 }, /* actual: 1299.2 MHz */ + { 19200000, 1300000000, 812, 12, 1, 8 }, /* actual: 1299.2 MHz */ + { 26000000, 1300000000, 650, 13, 1, 8 }, /* 1.2 GHz */ - { 12000000, 1200000000, 1000, 10, 0, 8}, - { 13000000, 1200000000, 923, 10, 0, 8}, /* actual: 1199.9 MHz */ - { 16800000, 1200000000, 1000, 14, 0, 8}, - { 19200000, 1200000000, 1000, 16, 0, 8}, - { 26000000, 1200000000, 600, 13, 0, 8}, - + { 12000000, 1200000000, 1000, 10, 1, 8 }, + { 13000000, 1200000000, 923, 10, 1, 8 }, /* actual: 1199.9 MHz */ + { 16800000, 1200000000, 1000, 14, 1, 8 }, + { 19200000, 1200000000, 1000, 16, 1, 8 }, + { 26000000, 1200000000, 600, 13, 1, 8 }, /* 1.1 GHz */ - { 12000000, 1100000000, 825, 9, 0, 8}, - { 13000000, 1100000000, 846, 10, 0, 8}, /* actual: 1099.8 MHz */ - { 16800000, 1100000000, 982, 15, 0, 8}, /* actual: 1099.8 MHz */ - { 19200000, 1100000000, 859, 15, 0, 8}, /* actual: 1099.5 MHz */ - { 26000000, 1100000000, 550, 13, 0, 8}, - + { 12000000, 1100000000, 825, 9, 1, 8 }, + { 13000000, 1100000000, 846, 10, 1, 8 }, /* actual: 1099.8 MHz */ + { 16800000, 1100000000, 982, 15, 1, 8 }, /* actual: 1099.8 MHz */ + { 19200000, 1100000000, 859, 15, 1, 8 }, /* actual: 1099.5 MHz */ + { 26000000, 1100000000, 550, 13, 1, 8 }, /* 1 GHz */ - { 12000000, 1000000000, 1000, 12, 0, 8}, - { 13000000, 1000000000, 1000, 13, 0, 8}, - { 16800000, 1000000000, 833, 14, 0, 8}, /* actual: 999.6 MHz */ - { 19200000, 1000000000, 625, 12, 0, 8}, - { 26000000, 1000000000, 1000, 26, 0, 8}, + { 12000000, 1000000000, 1000, 12, 1, 8 }, + { 13000000, 1000000000, 1000, 13, 1, 8 }, + { 16800000, 1000000000, 833, 14, 1, 8 }, /* actual: 999.6 MHz */ + { 19200000, 1000000000, 625, 12, 1, 8 }, + { 26000000, 1000000000, 1000, 26, 1, 8 }, + { 0, 0, 0, 0, 0, 0 }, +}; - { 0, 0, 0, 0, 0, 0 }, +static const struct pdiv_map plle_p[] = { + { .pdiv = 18, .hw_val = 18 }, + { .pdiv = 24, .hw_val = 24 }, + { .pdiv = 0, .hw_val = 0 }, }; static struct tegra_clk_pll_freq_table pll_e_freq_table[] = { /* PLLE special case: use cpcon field to store cml divider value */ - { 12000000, 100000000, 150, 1, 18, 11}, - { 216000000, 100000000, 200, 18, 24, 13}, - { 0, 0, 0, 0, 0, 0 }, + { 12000000, 100000000, 150, 1, 18, 11 }, + { 216000000, 100000000, 200, 18, 24, 13 }, + { 0, 0, 0, 0, 0, 0 }, }; /* PLL parameters */ @@ -422,7 +426,8 @@ static struct tegra_clk_pll_params pll_c_params = { .lock_enable_bit_idx = PLL_MISC_LOCK_ENABLE, .lock_delay = 300, .freq_table = pll_c_freq_table, - .flags = TEGRA_PLL_HAS_CPCON | TEGRA_PLL_USE_LOCK, + .flags = TEGRA_PLL_HAS_CPCON | TEGRA_PLL_USE_LOCK | + TEGRA_PLL_HAS_LOCK_ENABLE, }; static struct div_nmp pllm_nmp = { @@ -454,7 +459,8 @@ static struct tegra_clk_pll_params pll_m_params = { .pmc_divp_reg = PMC_PLLM_WB0_OVERRIDE, .freq_table = pll_m_freq_table, .flags = TEGRA_PLLM | TEGRA_PLL_HAS_CPCON | - TEGRA_PLL_SET_DCCON | TEGRA_PLL_USE_LOCK, + TEGRA_PLL_SET_DCCON | TEGRA_PLL_USE_LOCK | + TEGRA_PLL_HAS_LOCK_ENABLE | TEGRA_PLL_FIXED, }; static struct tegra_clk_pll_params pll_p_params = { @@ -470,7 +476,8 @@ static struct tegra_clk_pll_params pll_p_params = { .lock_enable_bit_idx = PLL_MISC_LOCK_ENABLE, .lock_delay = 300, .freq_table = pll_p_freq_table, - .flags = TEGRA_PLL_FIXED | TEGRA_PLL_HAS_CPCON | TEGRA_PLL_USE_LOCK, + .flags = TEGRA_PLL_FIXED | TEGRA_PLL_HAS_CPCON | TEGRA_PLL_USE_LOCK | + TEGRA_PLL_HAS_LOCK_ENABLE, .fixed_rate = 408000000, }; @@ -487,7 +494,8 @@ static struct tegra_clk_pll_params pll_a_params = { .lock_enable_bit_idx = PLL_MISC_LOCK_ENABLE, .lock_delay = 300, .freq_table = pll_a_freq_table, - .flags = TEGRA_PLL_HAS_CPCON | TEGRA_PLL_USE_LOCK, + .flags = TEGRA_PLL_HAS_CPCON | TEGRA_PLL_USE_LOCK | + TEGRA_PLL_HAS_LOCK_ENABLE, }; static struct tegra_clk_pll_params pll_d_params = { @@ -504,8 +512,7 @@ static struct tegra_clk_pll_params pll_d_params = { .lock_delay = 1000, .freq_table = pll_d_freq_table, .flags = TEGRA_PLL_HAS_CPCON | TEGRA_PLL_SET_LFCON | - TEGRA_PLL_USE_LOCK, - + TEGRA_PLL_USE_LOCK | TEGRA_PLL_HAS_LOCK_ENABLE, }; static struct tegra_clk_pll_params pll_d2_params = { @@ -522,7 +529,7 @@ static struct tegra_clk_pll_params pll_d2_params = { .lock_delay = 1000, .freq_table = pll_d_freq_table, .flags = TEGRA_PLL_HAS_CPCON | TEGRA_PLL_SET_LFCON | - TEGRA_PLL_USE_LOCK, + TEGRA_PLL_USE_LOCK | TEGRA_PLL_HAS_LOCK_ENABLE, }; static struct tegra_clk_pll_params pll_u_params = { @@ -539,7 +546,8 @@ static struct tegra_clk_pll_params pll_u_params = { .lock_delay = 1000, .pdiv_tohw = pllu_p, .freq_table = pll_u_freq_table, - .flags = TEGRA_PLLU | TEGRA_PLL_HAS_CPCON | TEGRA_PLL_SET_LFCON, + .flags = TEGRA_PLLU | TEGRA_PLL_HAS_CPCON | TEGRA_PLL_SET_LFCON | + TEGRA_PLL_HAS_LOCK_ENABLE, }; static struct tegra_clk_pll_params pll_x_params = { @@ -556,7 +564,7 @@ static struct tegra_clk_pll_params pll_x_params = { .lock_delay = 300, .freq_table = pll_x_freq_table, .flags = TEGRA_PLL_HAS_CPCON | TEGRA_PLL_SET_DCCON | - TEGRA_PLL_USE_LOCK, + TEGRA_PLL_USE_LOCK | TEGRA_PLL_HAS_LOCK_ENABLE, }; static struct tegra_clk_pll_params pll_e_params = { @@ -571,19 +579,21 @@ static struct tegra_clk_pll_params pll_e_params = { .lock_mask = PLLE_MISC_LOCK, .lock_enable_bit_idx = PLLE_MISC_LOCK_ENABLE, .lock_delay = 300, + .pdiv_tohw = plle_p, .freq_table = pll_e_freq_table, - .flags = TEGRA_PLLE_CONFIGURE | TEGRA_PLL_FIXED, + .flags = TEGRA_PLLE_CONFIGURE | TEGRA_PLL_FIXED | + TEGRA_PLL_HAS_LOCK_ENABLE | TEGRA_PLL_LOCK_MISC, .fixed_rate = 100000000, }; static unsigned long tegra30_input_freq[] = { - [0] = 13000000, - [1] = 16800000, - [4] = 19200000, - [5] = 38400000, - [8] = 12000000, - [9] = 48000000, - [12] = 260000000, + [ 0] = 13000000, + [ 1] = 16800000, + [ 4] = 19200000, + [ 5] = 38400000, + [ 8] = 12000000, + [ 9] = 48000000, + [12] = 26000000, }; static struct tegra_devclk devclks[] __initdata = { @@ -861,13 +871,12 @@ 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 }, - }; static void tegra30_utmi_param_configure(void) { + unsigned int i; u32 reg; - int i; for (i = 0; i < ARRAY_SIZE(utmi_parameters); i++) { if (input_freq == utmi_parameters[i].osc_frequency) @@ -917,7 +926,7 @@ static void tegra30_utmi_param_configure(void) writel_relaxed(reg, clk_base + UTMIP_PLL_CFG1); } -static const char *pll_e_parents[] = {"pll_ref", "pll_p"}; +static const char *pll_e_parents[] = { "pll_ref", "pll_p" }; static void __init tegra30_pll_init(void) { @@ -925,7 +934,7 @@ static void __init tegra30_pll_init(void) /* PLLC */ clk = tegra_clk_register_pll("pll_c", "pll_ref", clk_base, pmc_base, 0, - &pll_c_params, NULL); + &pll_c_params, NULL); clks[TEGRA30_CLK_PLL_C] = clk; /* PLLC_OUT1 */ @@ -1135,7 +1144,7 @@ static void __init tegra30_periph_clk_init(void) { struct tegra_periph_init_data *data; struct clk *clk; - int i; + unsigned int i; /* dsia */ clk = tegra_clk_register_periph_gate("dsia", "pll_d_out0", 0, clk_base, @@ -1224,7 +1233,6 @@ static void tegra30_cpu_out_of_reset(u32 cpu) wmb(); } - static void tegra30_enable_cpu_clock(u32 cpu) { unsigned int reg; @@ -1237,7 +1245,6 @@ static void tegra30_enable_cpu_clock(u32 cpu) static void tegra30_disable_cpu_clock(u32 cpu) { - unsigned int reg; reg = readl(clk_base + TEGRA_CLK_RST_CONTROLLER_CLK_CPU_CMPLX); @@ -1268,7 +1275,7 @@ static void tegra30_cpu_clock_suspend(void) /* switch coresite to clk_m, save off original source */ tegra30_cpu_clk_sctx.clk_csite_src = readl(clk_base + CLK_RESET_SOURCE_CSITE); - writel(3<<30, clk_base + CLK_RESET_SOURCE_CSITE); + writel(3 << 30, clk_base + CLK_RESET_SOURCE_CSITE); tegra30_cpu_clk_sctx.cpu_burst = readl(clk_base + CLK_RESET_CCLK_BURST); @@ -1335,44 +1342,45 @@ static struct tegra_cpu_car_ops tegra30_cpu_car_ops = { }; static struct tegra_clk_init_table init_table[] __initdata = { - {TEGRA30_CLK_UARTA, TEGRA30_CLK_PLL_P, 408000000, 0}, - {TEGRA30_CLK_UARTB, TEGRA30_CLK_PLL_P, 408000000, 0}, - {TEGRA30_CLK_UARTC, TEGRA30_CLK_PLL_P, 408000000, 0}, - {TEGRA30_CLK_UARTD, TEGRA30_CLK_PLL_P, 408000000, 0}, - {TEGRA30_CLK_UARTE, TEGRA30_CLK_PLL_P, 408000000, 0}, - {TEGRA30_CLK_PLL_A, TEGRA30_CLK_CLK_MAX, 564480000, 1}, - {TEGRA30_CLK_PLL_A_OUT0, TEGRA30_CLK_CLK_MAX, 11289600, 1}, - {TEGRA30_CLK_EXTERN1, TEGRA30_CLK_PLL_A_OUT0, 0, 1}, - {TEGRA30_CLK_CLK_OUT_1_MUX, TEGRA30_CLK_EXTERN1, 0, 0}, - {TEGRA30_CLK_CLK_OUT_1, TEGRA30_CLK_CLK_MAX, 0, 1}, - {TEGRA30_CLK_BLINK, TEGRA30_CLK_CLK_MAX, 0, 1}, - {TEGRA30_CLK_I2S0, TEGRA30_CLK_PLL_A_OUT0, 11289600, 0}, - {TEGRA30_CLK_I2S1, TEGRA30_CLK_PLL_A_OUT0, 11289600, 0}, - {TEGRA30_CLK_I2S2, TEGRA30_CLK_PLL_A_OUT0, 11289600, 0}, - {TEGRA30_CLK_I2S3, TEGRA30_CLK_PLL_A_OUT0, 11289600, 0}, - {TEGRA30_CLK_I2S4, TEGRA30_CLK_PLL_A_OUT0, 11289600, 0}, - {TEGRA30_CLK_SDMMC1, TEGRA30_CLK_PLL_P, 48000000, 0}, - {TEGRA30_CLK_SDMMC2, TEGRA30_CLK_PLL_P, 48000000, 0}, - {TEGRA30_CLK_SDMMC3, TEGRA30_CLK_PLL_P, 48000000, 0}, - {TEGRA30_CLK_PLL_M, TEGRA30_CLK_CLK_MAX, 0, 1}, - {TEGRA30_CLK_PCLK, TEGRA30_CLK_CLK_MAX, 0, 1}, - {TEGRA30_CLK_CSITE, TEGRA30_CLK_CLK_MAX, 0, 1}, - {TEGRA30_CLK_EMC, TEGRA30_CLK_CLK_MAX, 0, 1}, - {TEGRA30_CLK_MSELECT, TEGRA30_CLK_CLK_MAX, 0, 1}, - {TEGRA30_CLK_SBC1, TEGRA30_CLK_PLL_P, 100000000, 0}, - {TEGRA30_CLK_SBC2, TEGRA30_CLK_PLL_P, 100000000, 0}, - {TEGRA30_CLK_SBC3, TEGRA30_CLK_PLL_P, 100000000, 0}, - {TEGRA30_CLK_SBC4, TEGRA30_CLK_PLL_P, 100000000, 0}, - {TEGRA30_CLK_SBC5, TEGRA30_CLK_PLL_P, 100000000, 0}, - {TEGRA30_CLK_SBC6, TEGRA30_CLK_PLL_P, 100000000, 0}, - {TEGRA30_CLK_HOST1X, TEGRA30_CLK_PLL_C, 150000000, 0}, - {TEGRA30_CLK_DISP1, TEGRA30_CLK_PLL_P, 600000000, 0}, - {TEGRA30_CLK_DISP2, TEGRA30_CLK_PLL_P, 600000000, 0}, - {TEGRA30_CLK_TWD, TEGRA30_CLK_CLK_MAX, 0, 1}, - {TEGRA30_CLK_GR2D, TEGRA30_CLK_PLL_C, 300000000, 0}, - {TEGRA30_CLK_GR3D, TEGRA30_CLK_PLL_C, 300000000, 0}, - {TEGRA30_CLK_GR3D2, TEGRA30_CLK_PLL_C, 300000000, 0}, - {TEGRA30_CLK_CLK_MAX, TEGRA30_CLK_CLK_MAX, 0, 0}, /* This MUST be the last entry. */ + { TEGRA30_CLK_UARTA, TEGRA30_CLK_PLL_P, 408000000, 0 }, + { TEGRA30_CLK_UARTB, TEGRA30_CLK_PLL_P, 408000000, 0 }, + { TEGRA30_CLK_UARTC, TEGRA30_CLK_PLL_P, 408000000, 0 }, + { TEGRA30_CLK_UARTD, TEGRA30_CLK_PLL_P, 408000000, 0 }, + { TEGRA30_CLK_UARTE, TEGRA30_CLK_PLL_P, 408000000, 0 }, + { TEGRA30_CLK_PLL_A, TEGRA30_CLK_CLK_MAX, 564480000, 1 }, + { TEGRA30_CLK_PLL_A_OUT0, TEGRA30_CLK_CLK_MAX, 11289600, 1 }, + { TEGRA30_CLK_EXTERN1, TEGRA30_CLK_PLL_A_OUT0, 0, 1 }, + { TEGRA30_CLK_CLK_OUT_1_MUX, TEGRA30_CLK_EXTERN1, 0, 0 }, + { TEGRA30_CLK_CLK_OUT_1, TEGRA30_CLK_CLK_MAX, 0, 1 }, + { TEGRA30_CLK_BLINK, TEGRA30_CLK_CLK_MAX, 0, 1 }, + { TEGRA30_CLK_I2S0, TEGRA30_CLK_PLL_A_OUT0, 11289600, 0 }, + { TEGRA30_CLK_I2S1, TEGRA30_CLK_PLL_A_OUT0, 11289600, 0 }, + { TEGRA30_CLK_I2S2, TEGRA30_CLK_PLL_A_OUT0, 11289600, 0 }, + { TEGRA30_CLK_I2S3, TEGRA30_CLK_PLL_A_OUT0, 11289600, 0 }, + { TEGRA30_CLK_I2S4, TEGRA30_CLK_PLL_A_OUT0, 11289600, 0 }, + { TEGRA30_CLK_SDMMC1, TEGRA30_CLK_PLL_P, 48000000, 0 }, + { TEGRA30_CLK_SDMMC2, TEGRA30_CLK_PLL_P, 48000000, 0 }, + { TEGRA30_CLK_SDMMC3, TEGRA30_CLK_PLL_P, 48000000, 0 }, + { TEGRA30_CLK_PLL_M, TEGRA30_CLK_CLK_MAX, 0, 1 }, + { TEGRA30_CLK_PCLK, TEGRA30_CLK_CLK_MAX, 0, 1 }, + { TEGRA30_CLK_CSITE, TEGRA30_CLK_CLK_MAX, 0, 1 }, + { TEGRA30_CLK_EMC, TEGRA30_CLK_CLK_MAX, 0, 1 }, + { TEGRA30_CLK_MSELECT, TEGRA30_CLK_CLK_MAX, 0, 1 }, + { TEGRA30_CLK_SBC1, TEGRA30_CLK_PLL_P, 100000000, 0 }, + { TEGRA30_CLK_SBC2, TEGRA30_CLK_PLL_P, 100000000, 0 }, + { TEGRA30_CLK_SBC3, TEGRA30_CLK_PLL_P, 100000000, 0 }, + { TEGRA30_CLK_SBC4, TEGRA30_CLK_PLL_P, 100000000, 0 }, + { TEGRA30_CLK_SBC5, TEGRA30_CLK_PLL_P, 100000000, 0 }, + { TEGRA30_CLK_SBC6, TEGRA30_CLK_PLL_P, 100000000, 0 }, + { TEGRA30_CLK_HOST1X, TEGRA30_CLK_PLL_C, 150000000, 0 }, + { TEGRA30_CLK_DISP1, TEGRA30_CLK_PLL_P, 600000000, 0 }, + { TEGRA30_CLK_DISP2, TEGRA30_CLK_PLL_P, 600000000, 0 }, + { TEGRA30_CLK_TWD, TEGRA30_CLK_CLK_MAX, 0, 1 }, + { TEGRA30_CLK_GR2D, TEGRA30_CLK_PLL_C, 300000000, 0 }, + { TEGRA30_CLK_GR3D, TEGRA30_CLK_PLL_C, 300000000, 0 }, + { TEGRA30_CLK_GR3D2, TEGRA30_CLK_PLL_C, 300000000, 0 }, + /* must be the last entry */ + { TEGRA30_CLK_CLK_MAX, TEGRA30_CLK_CLK_MAX, 0, 0 }, }; static void __init tegra30_clock_apply_init_table(void) @@ -1397,12 +1405,13 @@ static struct tegra_clk_duplicate tegra_clk_duplicates[] = { TEGRA_CLK_DUPLICATE(TEGRA30_CLK_CML1, "tegra_sata_cml", NULL), TEGRA_CLK_DUPLICATE(TEGRA30_CLK_CML0, "tegra_pcie", "cml"), TEGRA_CLK_DUPLICATE(TEGRA30_CLK_VCP, "nvavp", "vcp"), - TEGRA_CLK_DUPLICATE(TEGRA30_CLK_CLK_MAX, NULL, NULL), /* MUST be the last entry */ + /* must be the last entry */ + TEGRA_CLK_DUPLICATE(TEGRA30_CLK_CLK_MAX, NULL, NULL), }; static const struct of_device_id pmc_match[] __initconst = { { .compatible = "nvidia,tegra30-pmc" }, - {}, + { }, }; static struct tegra_audio_clk_info tegra30_audio_plls[] = { @@ -1441,7 +1450,6 @@ static void __init tegra30_clock_init(struct device_node *np) NULL) < 0) return; - tegra_fixed_clk_init(tegra30_clks); tegra30_pll_init(); tegra30_super_clk_init(); diff --git a/drivers/clk/tegra/clk.h b/drivers/clk/tegra/clk.h index 5d2678914..4dbcfaec5 100644 --- a/drivers/clk/tegra/clk.h +++ b/drivers/clk/tegra/clk.h @@ -110,14 +110,16 @@ struct clk *tegra_clk_register_mc(const char *name, const char *parent_name, * @m: input divider * @p: post divider * @cpcon: charge pump current + * @sdm_data: fraction divider setting (0 = disabled) */ struct tegra_clk_pll_freq_table { unsigned long input_rate; unsigned long output_rate; - u16 n; + u32 n; u16 m; u8 p; u8 cpcon; + u16 sdm_data; }; /** @@ -156,6 +158,10 @@ struct div_nmp { u8 override_divp_shift; }; +#define MAX_PLL_MISC_REG_COUNT 6 + +struct tegra_clk_pll; + /** * struct tegra_clk_pll_params - PLL parameters * @@ -172,6 +178,14 @@ struct div_nmp { * @lock_enable_bit_idx: Bit index to enable PLL lock * @iddq_reg: PLL IDDQ register offset * @iddq_bit_idx: Bit index to enable PLL IDDQ + * @reset_reg: Register offset of where RESET bit is + * @reset_bit_idx: Shift of reset bit in reset_reg + * @sdm_din_reg: Register offset where SDM settings are + * @sdm_din_mask: Mask of SDM divider bits + * @sdm_ctrl_reg: Register offset where SDM enable is + * @sdm_ctrl_en_mask: Mask of SDM enable bit + * @ssc_ctrl_reg: Register offset where SSC settings are + * @ssc_ctrl_en_mask: Mask of SSC enable bit * @aux_reg: AUX register offset * @dyn_ramp_reg: Dynamic ramp control register offset * @ext_misc_reg: Miscellaneous control register offsets @@ -182,10 +196,27 @@ struct div_nmp { * @stepb_shift: Dynamic ramp step B field shift * @lock_delay: Delay in us if PLL lock is not used * @max_p: maximum value for the p divider + * @defaults_set: Boolean signaling all reg defaults for PLL set. * @pdiv_tohw: mapping of p divider to register values * @div_nmp: offsets and widths on n, m and p fields * @freq_table: array of frequencies supported by PLL * @fixed_rate: PLL rate if it is fixed + * @mdiv_default: Default value for fixed mdiv for this PLL + * @round_p_to_pdiv: Callback used to round p to the closed pdiv + * @set_gain: Callback to adjust N div for SDM enabled + * PLL's based on fractional divider value. + * @calc_rate: Callback used to change how out of table + * rates (dividers and multipler) are calculated. + * @adjust_vco: Callback to adjust the programming range of the + * divider range (if SDM is present) + * @set_defaults: Callback which will try to initialize PLL + * registers to sane default values. This is first + * tried during PLL registration, but if the PLL + * is already enabled, it will be done the first + * time the rate is changed while the PLL is + * disabled. + * @dyn_ramp: Callback which can be used to define a custom + * dynamic ramp function for a given PLL. * * Flags: * TEGRA_PLL_USE_LOCK - This flag indicated to use lock bits for @@ -207,6 +238,11 @@ struct div_nmp { * base register. * TEGRA_PLL_BYPASS - PLL has bypass bit * TEGRA_PLL_HAS_LOCK_ENABLE - PLL has bit to enable lock monitoring + * TEGRA_MDIV_NEW - Switch to new method for calculating fixed mdiv + * it may be more accurate (especially if SDM present) + * TEGRA_PLLMB - PLLMB has should be treated similar to PLLM. This + * flag indicated that it is PLLMB. + * TEGRA_PLL_VCO_OUT - Used to indicate that the PLL has a VCO output */ struct tegra_clk_pll_params { unsigned long input_min; @@ -223,9 +259,17 @@ struct tegra_clk_pll_params { u32 lock_enable_bit_idx; u32 iddq_reg; u32 iddq_bit_idx; + u32 reset_reg; + u32 reset_bit_idx; + u32 sdm_din_reg; + u32 sdm_din_mask; + u32 sdm_ctrl_reg; + u32 sdm_ctrl_en_mask; + u32 ssc_ctrl_reg; + u32 ssc_ctrl_en_mask; u32 aux_reg; u32 dyn_ramp_reg; - u32 ext_misc_reg[3]; + u32 ext_misc_reg[MAX_PLL_MISC_REG_COUNT]; u32 pmc_divnm_reg; u32 pmc_divp_reg; u32 flags; @@ -233,10 +277,22 @@ struct tegra_clk_pll_params { int stepb_shift; int lock_delay; int max_p; - struct pdiv_map *pdiv_tohw; + bool defaults_set; + const struct pdiv_map *pdiv_tohw; struct div_nmp *div_nmp; struct tegra_clk_pll_freq_table *freq_table; unsigned long fixed_rate; + u16 mdiv_default; + u32 (*round_p_to_pdiv)(u32 p, u32 *pdiv); + void (*set_gain)(struct tegra_clk_pll_freq_table *cfg); + int (*calc_rate)(struct clk_hw *hw, + struct tegra_clk_pll_freq_table *cfg, + unsigned long rate, unsigned long parent_rate); + unsigned long (*adjust_vco)(struct tegra_clk_pll_params *pll_params, + unsigned long parent_rate); + void (*set_defaults)(struct tegra_clk_pll *pll); + int (*dyn_ramp)(struct tegra_clk_pll *pll, + struct tegra_clk_pll_freq_table *cfg); }; #define TEGRA_PLL_USE_LOCK BIT(0) @@ -250,6 +306,9 @@ struct tegra_clk_pll_params { #define TEGRA_PLL_LOCK_MISC BIT(8) #define TEGRA_PLL_BYPASS BIT(9) #define TEGRA_PLL_HAS_LOCK_ENABLE BIT(10) +#define TEGRA_MDIV_NEW BIT(11) +#define TEGRA_PLLMB BIT(12) +#define TEGRA_PLL_VCO_OUT BIT(13) /** * struct tegra_clk_pll - Tegra PLL clock @@ -303,6 +362,12 @@ struct clk *tegra_clk_register_pllxc(const char *name, const char *parent_name, struct tegra_clk_pll_params *pll_params, spinlock_t *lock); +struct clk *tegra_clk_register_pllxc_tegra210(const char *name, + const char *parent_name, void __iomem *clk_base, + void __iomem *pmc, unsigned long flags, + struct tegra_clk_pll_params *pll_params, + spinlock_t *lock); + struct clk *tegra_clk_register_pllm(const char *name, const char *parent_name, void __iomem *clk_base, void __iomem *pmc, unsigned long flags, @@ -327,11 +392,35 @@ struct clk *tegra_clk_register_plle_tegra114(const char *name, struct tegra_clk_pll_params *pll_params, spinlock_t *lock); +struct clk *tegra_clk_register_plle_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 clk *tegra_clk_register_pllc_tegra210(const char *name, + const char *parent_name, void __iomem *clk_base, + void __iomem *pmc, unsigned long flags, + struct tegra_clk_pll_params *pll_params, + spinlock_t *lock); + +struct clk *tegra_clk_register_pllss_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 clk *tegra_clk_register_pllss(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 clk *tegra_clk_register_pllmb(const char *name, const char *parent_name, + void __iomem *clk_base, void __iomem *pmc, + unsigned long flags, + struct tegra_clk_pll_params *pll_params, + spinlock_t *lock); + /** * struct tegra_clk_pll_out - PLL divider down clock * @@ -653,6 +742,9 @@ int tegra_osc_clk_init(void __iomem *clk_base, struct tegra_clk *clks, void tegra_super_clk_gen4_init(void __iomem *clk_base, void __iomem *pmc_base, struct tegra_clk *tegra_clks, struct tegra_clk_pll_params *pll_params); +void tegra_super_clk_gen5_init(void __iomem *clk_base, + void __iomem *pmc_base, struct tegra_clk *tegra_clks, + struct tegra_clk_pll_params *pll_params); #ifdef CONFIG_TEGRA_CLK_EMC struct clk *tegra_clk_register_emc(void __iomem *base, struct device_node *np, @@ -674,5 +766,8 @@ void tegra114_clock_deassert_dfll_dvco_reset(void); typedef void (*tegra_clk_apply_init_table_func)(void); extern tegra_clk_apply_init_table_func tegra_clk_apply_init_table; +int tegra_pll_wait_for_lock(struct tegra_clk_pll *pll); +u16 tegra_pll_get_fixed_mdiv(struct clk_hw *hw, unsigned long input_rate); +int tegra_pll_p_div_to_hw(struct tegra_clk_pll *pll, u8 p_div); #endif /* TEGRA_CLK_H */ |