Lines Matching +full:stm32f42xx +full:- +full:rcc
1 // SPDX-License-Identifier: GPL-2.0-only
5 * Inspired by clk-asm9260.c .
9 #include <linux/clk-provider.h>
26 #include <dt-bindings/clock/stm32fx-clock.h>
52 #define NONE -1
383 [STM32F4_PLL_SSC_DOWN_SPREAD] = "down-spread",
384 [STM32F4_PLL_SSC_CENTER_SPREAD] = "center-spread",
423 * The APBx dividers are power-of-two dividers and, if *not* running in 1:1
440 if (readl(base + STM32F4_RCC_CFGR) & BIT(am->bit_idx)) in clk_apb_mul_recalc_rate()
452 if (readl(base + STM32F4_RCC_CFGR) & BIT(am->bit_idx)) in clk_apb_mul_round_rate()
492 return ERR_PTR(-ENOMEM); in clk_register_apb_mul()
494 am->bit_idx = bit_idx; in clk_register_apb_mul()
495 am->hw.init = &init; in clk_register_apb_mul()
503 clk = clk_register(dev, &am->hw); in clk_register_apb_mul()
574 { "vco-i2s", STM32F4_RCC_PLLI2SCFGR, 26, 27 },
575 { "vco-sai", STM32F4_RCC_PLLSAICFGR, 28, 29 },
585 { CLK_I2SQ_PDIV, PLL_VCO_I2S, "plli2s-q-div", "plli2s-q",
588 { CLK_SAIQ_PDIV, PLL_VCO_SAI, "pllsai-q-div", "pllsai-q",
591 { NO_IDX, PLL_VCO_SAI, "pllsai-r-div", "pllsai-r", CLK_SET_RATE_PARENT,
617 { PLL_I2S, 192, { NULL, "plli2s-q", "plli2s-r" } },
618 { PLL_SAI, 49, { NULL, "pllsai-q", "pllsai-r" } },
622 { PLL, 50, { "pll", "pll-q", "pll-r" } },
623 { PLL_I2S, 50, { "plli2s-p", "plli2s-q", "plli2s-r" } },
624 { PLL_SAI, 50, { "pllsai-p", "pllsai-q", "pllsai-r" } },
647 bit_status = !(readl(gate->reg) & BIT(pll->bit_rdy_idx)); in stm32f4_pll_enable()
649 } while (bit_status && --timeout); in stm32f4_pll_enable()
667 val = readl(base + pll->offset); in stm32f4_pll_recalc()
682 if (n < pll->n_start) in stm32f4_pll_round_rate()
683 n = pll->n_start; in stm32f4_pll_round_rate()
695 struct stm32f4_pll_ssc *ssc = &pll->ssc_conf; in stm32f4_pll_set_ssc()
703 modeper = DIV_ROUND_CLOSEST(parent_rate, 4 * ssc->mod_freq); in stm32f4_pll_set_ssc()
704 incstep = DIV_ROUND_CLOSEST(((1 << 15) - 1) * ssc->mod_depth * ndiv, in stm32f4_pll_set_ssc()
710 if (ssc->mod_type) in stm32f4_pll_set_ssc()
733 val = readl(base + pll->offset) & ~STM32F4_RCC_PLLCFGR_N_MASK; in stm32f4_pll_set_rate()
736 writel(val, base + pll->offset); in stm32f4_pll_set_rate()
738 if (pll->ssc_enable) in stm32f4_pll_set_rate()
783 pll_state = stm32f4_pll_is_enabled(pll_div->hw_pll); in stm32f4_pll_div_set_rate()
786 stm32f4_pll_disable(pll_div->hw_pll); in stm32f4_pll_div_set_rate()
791 stm32f4_pll_enable(pll_div->hw_pll); in stm32f4_pll_div_set_rate()
816 return ERR_PTR(-ENOMEM); in clk_register_pll_div()
825 pll_div->div.reg = reg; in clk_register_pll_div()
826 pll_div->div.shift = shift; in clk_register_pll_div()
827 pll_div->div.width = width; in clk_register_pll_div()
828 pll_div->div.flags = clk_divider_flags; in clk_register_pll_div()
829 pll_div->div.lock = lock; in clk_register_pll_div()
830 pll_div->div.table = table; in clk_register_pll_div()
831 pll_div->div.hw.init = &init; in clk_register_pll_div()
833 pll_div->hw_pll = pll_hw; in clk_register_pll_div()
836 hw = &pll_div->div.hw; in clk_register_pll_div()
859 return -ENODEV; in stm32f4_pll_init_ssc()
864 pll->ssc_enable = true; in stm32f4_pll_init_ssc()
865 memcpy(&pll->ssc_conf, conf, sizeof(pll->ssc_conf)); in stm32f4_pll_init_ssc()
872 val = readl(base + pll->offset); in stm32f4_pll_init_ssc()
875 pr_debug("%s: pll: %s, parent: %s, parent-rate: %lu, n: %lu\n", in stm32f4_pll_init_ssc()
893 return -EINVAL; in stm32f4_pll_ssc_parse_dt()
895 ret = of_property_read_u32(np, "st,ssc-modfreq-hz", &conf->mod_freq); in stm32f4_pll_ssc_parse_dt()
899 ret = of_property_read_u32(np, "st,ssc-moddepth-permyriad", in stm32f4_pll_ssc_parse_dt()
900 &conf->mod_depth); in stm32f4_pll_ssc_parse_dt()
902 pr_err("%pOF: missing st,ssc-moddepth-permyriad\n", np); in stm32f4_pll_ssc_parse_dt()
907 "st,ssc-modmethod", in stm32f4_pll_ssc_parse_dt()
911 pr_err("%pOF: failed to get st,ssc-modmethod\n", np); in stm32f4_pll_ssc_parse_dt()
915 conf->mod_type = ret; in stm32f4_pll_ssc_parse_dt()
918 np, conf->mod_freq, conf->mod_depth, in stm32f4_pll_ssc_parse_dt()
919 stm32f4_ssc_mod_methods[ret], conf->mod_type); in stm32f4_pll_ssc_parse_dt()
938 return ERR_PTR(-ENOMEM); in stm32f4_rcc_register_pll()
940 vco = &vco_data[data->pll_num]; in stm32f4_rcc_register_pll()
942 init.name = vco->vco_name; in stm32f4_rcc_register_pll()
948 pll->gate.lock = lock; in stm32f4_rcc_register_pll()
949 pll->gate.reg = base + STM32F4_RCC_CR; in stm32f4_rcc_register_pll()
950 pll->gate.bit_idx = vco->bit_idx; in stm32f4_rcc_register_pll()
951 pll->gate.hw.init = &init; in stm32f4_rcc_register_pll()
953 pll->offset = vco->offset; in stm32f4_rcc_register_pll()
954 pll->n_start = data->n_start; in stm32f4_rcc_register_pll()
955 pll->bit_rdy_idx = vco->bit_rdy_idx; in stm32f4_rcc_register_pll()
956 pll->status = (readl(base + STM32F4_RCC_CR) >> vco->bit_idx) & 0x1; in stm32f4_rcc_register_pll()
958 reg = base + pll->offset; in stm32f4_rcc_register_pll()
960 pll_hw = &pll->gate.hw; in stm32f4_rcc_register_pll()
968 if (data->div_name[i]) in stm32f4_rcc_register_pll()
969 clk_register_pll_div(data->div_name[i], in stm32f4_rcc_register_pll()
970 vco->vco_name, in stm32f4_rcc_register_pll()
992 return -EINVAL; in stm32f4_rcc_lookup_clk_idx()
1002 return -EINVAL; in stm32f4_rcc_lookup_clk_idx()
1008 return stm32fx_end_primary_clk - 1 + hweight64(table[0]) + in stm32f4_rcc_lookup_clk_idx()
1016 int i = stm32f4_rcc_lookup_clk_idx(clkspec->args[0], clkspec->args[1]); in stm32f4_rcc_lookup_clk()
1019 return ERR_PTR(-EINVAL); in stm32f4_rcc_lookup_clk()
1069 bit_status = !(readl(gate->reg) & BIT(rgate->bit_rdy_idx)); in rgclk_enable()
1073 } while (bit_status && --timeout); in rgclk_enable()
1108 return ERR_PTR(-ENOMEM); in clk_register_rgate()
1116 rgate->bit_rdy_idx = bit_rdy_idx; in clk_register_rgate()
1118 rgate->gate.lock = lock; in clk_register_rgate()
1119 rgate->gate.reg = reg; in clk_register_rgate()
1120 rgate->gate.bit_idx = bit_idx; in clk_register_rgate()
1121 rgate->gate.hw.init = &init; in clk_register_rgate()
1123 hw = &rgate->gate.hw; in clk_register_rgate()
1203 hw = ERR_PTR(-EINVAL); in stm32_register_cclk()
1210 hw = ERR_PTR(-EINVAL); in stm32_register_cclk()
1214 gate->reg = reg; in stm32_register_cclk()
1215 gate->bit_idx = bit_idx; in stm32_register_cclk()
1216 gate->flags = 0; in stm32_register_cclk()
1217 gate->lock = lock; in stm32_register_cclk()
1219 mux->reg = reg; in stm32_register_cclk()
1220 mux->shift = shift; in stm32_register_cclk()
1221 mux->mask = 3; in stm32_register_cclk()
1222 mux->flags = 0; in stm32_register_cclk()
1225 &mux->hw, &cclk_mux_ops, in stm32_register_cclk()
1227 &gate->hw, &cclk_gate_ops, in stm32_register_cclk()
1256 "no-clock", "lse", "lsi", "hse-rtc"
1259 static const char *pll_src = "pll-src";
1263 static const char *dsi_parent[2] = { NULL, "pll-r" };
1265 static const char *lcd_parent[1] = { "pllsai-r-div" };
1267 static const char *i2s_parents[2] = { "plli2s-r", NULL };
1269 static const char *sai_parents[4] = { "pllsai-q-div", "plli2s-q-div", NULL,
1270 "no-clock" };
1272 static const char *pll48_parents[2] = { "pll-q", "pllsai-p" };
1278 static const char *spdif_parent[1] = { "plli2s-p" };
1285 static const char *i2c_parents[4] = { "apb1_div", "sys", "hsi", "no-clock" };
1315 CLK_LCD, "lcd-tft", lcd_parent, ARRAY_SIZE(lcd_parent),
1327 CLK_SAI1, "sai1-a", sai_parents, ARRAY_SIZE(sai_parents),
1333 CLK_SAI2, "sai1-b", sai_parents, ARRAY_SIZE(sai_parents),
1342 CLK_LCD, "lcd-tft", lcd_parent, ARRAY_SIZE(lcd_parent),
1354 CLK_SAI1, "sai1-a", sai_parents, ARRAY_SIZE(sai_parents),
1360 CLK_SAI2, "sai1-b", sai_parents, ARRAY_SIZE(sai_parents),
1387 CLK_LCD, "lcd-tft", lcd_parent, ARRAY_SIZE(lcd_parent),
1423 CLK_HDMI_CEC, "hdmi-cec",
1430 CLK_SPDIF, "spdif-rx",
1533 CLK_LCD, "lcd-tft", lcd_parent, ARRAY_SIZE(lcd_parent),
1575 CLK_HDMI_CEC, "hdmi-cec",
1582 CLK_SPDIF, "spdif-rx",
1744 .compatible = "st,stm32f42xx-rcc",
1748 .compatible = "st,stm32f469-rcc",
1752 .compatible = "st,stm32f746-rcc",
1756 .compatible = "st,stm32f769-rcc",
1777 hw = ERR_PTR(-EINVAL); in stm32_register_aux_clk()
1781 gate->reg = base + offset_gate; in stm32_register_aux_clk()
1782 gate->bit_idx = bit_idx; in stm32_register_aux_clk()
1783 gate->flags = 0; in stm32_register_aux_clk()
1784 gate->lock = lock; in stm32_register_aux_clk()
1785 gate_hw = &gate->hw; in stm32_register_aux_clk()
1792 hw = ERR_PTR(-EINVAL); in stm32_register_aux_clk()
1796 mux->reg = base + offset_mux; in stm32_register_aux_clk()
1797 mux->shift = shift; in stm32_register_aux_clk()
1798 mux->mask = mask; in stm32_register_aux_clk()
1799 mux->flags = 0; in stm32_register_aux_clk()
1800 mux_hw = &mux->hw; in stm32_register_aux_clk()
1805 hw = ERR_PTR(-EINVAL); in stm32_register_aux_clk()
1850 data = match->data; in stm32f4_rcc_init()
1852 stm32fx_end_primary_clk = data->end_primary; in stm32f4_rcc_init()
1854 clks = kmalloc_array(data->gates_num + stm32fx_end_primary_clk, in stm32f4_rcc_init()
1859 stm32f4_gate_map = data->gates_map; in stm32f4_rcc_init()
1870 if (of_device_is_compatible(np, "st,stm32f769-rcc")) { in stm32f4_rcc_init()
1891 pll_vco_hw = stm32f4_rcc_register_pll("vco_in", &data->pll_data[0], in stm32f4_rcc_init()
1895 &data->pll_data[1], &stm32f4_clk_lock); in stm32f4_rcc_init()
1898 &data->pll_data[2], &stm32f4_clk_lock); in stm32f4_rcc_init()
1906 hw = clk_register_pll_div(post_div->name, in stm32f4_rcc_init()
1907 post_div->parent, in stm32f4_rcc_init()
1908 post_div->flag, in stm32f4_rcc_init()
1909 base + post_div->offset, in stm32f4_rcc_init()
1910 post_div->shift, in stm32f4_rcc_init()
1911 post_div->width, in stm32f4_rcc_init()
1912 post_div->flag_div, in stm32f4_rcc_init()
1913 post_div->div_table, in stm32f4_rcc_init()
1914 clks[post_div->pll_idx], in stm32f4_rcc_init()
1917 if (post_div->idx != NO_IDX) in stm32f4_rcc_init()
1918 clks[post_div->idx] = hw; in stm32f4_rcc_init()
1948 for (n = 0; n < data->gates_num; n++) { in stm32f4_rcc_init()
1953 gd = &data->gates_data[n]; in stm32f4_rcc_init()
1954 secondary = 8 * (gd->offset - STM32F4_RCC_AHB1ENR) + in stm32f4_rcc_init()
1955 gd->bit_idx; in stm32f4_rcc_init()
1962 NULL, gd->name, gd->parent_name, gd->flags, in stm32f4_rcc_init()
1963 base + gd->offset, gd->bit_idx, 0, &stm32f4_clk_lock); in stm32f4_rcc_init()
1967 np, gd->name); in stm32f4_rcc_init()
1972 clks[CLK_LSI] = clk_register_rgate(NULL, "lsi", "clk-lsi", 0, in stm32f4_rcc_init()
1980 clks[CLK_LSE] = clk_register_rgate(NULL, "lse", "clk-lse", 0, in stm32f4_rcc_init()
1988 clks[CLK_HSE_RTC] = clk_hw_register_divider(NULL, "hse-rtc", "clk-hse", in stm32f4_rcc_init()
1993 pr_err("Unable to register hse-rtc clock\n"); in stm32f4_rcc_init()
2005 for (n = 0; n < data->aux_clk_num; n++) { in stm32f4_rcc_init()
2009 aux_clk = &data->aux_clk[n]; in stm32f4_rcc_init()
2011 hw = stm32_register_aux_clk(aux_clk->name, in stm32f4_rcc_init()
2012 aux_clk->parent_names, aux_clk->num_parents, in stm32f4_rcc_init()
2013 aux_clk->offset_mux, aux_clk->shift, in stm32f4_rcc_init()
2014 aux_clk->mask, aux_clk->offset_gate, in stm32f4_rcc_init()
2015 aux_clk->bit_idx, aux_clk->flags, in stm32f4_rcc_init()
2019 pr_warn("Unable to register %s clk\n", aux_clk->name); in stm32f4_rcc_init()
2023 if (aux_clk->idx != NO_IDX) in stm32f4_rcc_init()
2024 clks[aux_clk->idx] = hw; in stm32f4_rcc_init()
2027 if (of_device_is_compatible(np, "st,stm32f746-rcc")) { in stm32f4_rcc_init()
2045 CLK_OF_DECLARE_DRIVER(stm32f42xx_rcc, "st,stm32f42xx-rcc", stm32f4_rcc_init);
2046 CLK_OF_DECLARE_DRIVER(stm32f46xx_rcc, "st,stm32f469-rcc", stm32f4_rcc_init);
2047 CLK_OF_DECLARE_DRIVER(stm32f746_rcc, "st,stm32f746-rcc", stm32f4_rcc_init);
2048 CLK_OF_DECLARE_DRIVER(stm32f769_rcc, "st,stm32f769-rcc", stm32f4_rcc_init);