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_determine_rate()
456 unsigned long best_parent = req->rate / mult; in clk_apb_mul_determine_rate()
458 req->best_parent_rate = clk_hw_round_rate(clk_hw_get_parent(hw), best_parent); in clk_apb_mul_determine_rate()
461 req->rate = req->best_parent_rate * mult; in clk_apb_mul_determine_rate()
494 return ERR_PTR(-ENOMEM); in clk_register_apb_mul()
496 am->bit_idx = bit_idx; in clk_register_apb_mul()
497 am->hw.init = &init; in clk_register_apb_mul()
505 clk = clk_register(dev, &am->hw); in clk_register_apb_mul()
576 { "vco-i2s", STM32F4_RCC_PLLI2SCFGR, 26, 27 },
577 { "vco-sai", STM32F4_RCC_PLLSAICFGR, 28, 29 },
587 { CLK_I2SQ_PDIV, PLL_VCO_I2S, "plli2s-q-div", "plli2s-q",
590 { CLK_SAIQ_PDIV, PLL_VCO_SAI, "pllsai-q-div", "pllsai-q",
593 { NO_IDX, PLL_VCO_SAI, "pllsai-r-div", "pllsai-r", CLK_SET_RATE_PARENT,
619 { PLL_I2S, 192, { NULL, "plli2s-q", "plli2s-r" } },
620 { PLL_SAI, 49, { NULL, "pllsai-q", "pllsai-r" } },
624 { PLL, 50, { "pll", "pll-q", "pll-r" } },
625 { PLL_I2S, 50, { "plli2s-p", "plli2s-q", "plli2s-r" } },
626 { PLL_SAI, 50, { "pllsai-p", "pllsai-q", "pllsai-r" } },
649 bit_status = !(readl(gate->reg) & BIT(pll->bit_rdy_idx)); in stm32f4_pll_enable()
651 } while (bit_status && --timeout); in stm32f4_pll_enable()
669 val = readl(base + pll->offset); in stm32f4_pll_recalc()
682 n = req->rate / req->best_parent_rate; in stm32f4_pll_determine_rate()
684 if (n < pll->n_start) in stm32f4_pll_determine_rate()
685 n = pll->n_start; in stm32f4_pll_determine_rate()
689 req->rate = req->best_parent_rate * n; in stm32f4_pll_determine_rate()
699 struct stm32f4_pll_ssc *ssc = &pll->ssc_conf; in stm32f4_pll_set_ssc()
707 modeper = DIV_ROUND_CLOSEST(parent_rate, 4 * ssc->mod_freq); in stm32f4_pll_set_ssc()
708 incstep = DIV_ROUND_CLOSEST(((1 << 15) - 1) * ssc->mod_depth * ndiv, in stm32f4_pll_set_ssc()
714 if (ssc->mod_type) in stm32f4_pll_set_ssc()
737 val = readl(base + pll->offset) & ~STM32F4_RCC_PLLCFGR_N_MASK; in stm32f4_pll_set_rate()
740 writel(val, base + pll->offset); in stm32f4_pll_set_rate()
742 if (pll->ssc_enable) in stm32f4_pll_set_rate()
787 pll_state = stm32f4_pll_is_enabled(pll_div->hw_pll); in stm32f4_pll_div_set_rate()
790 stm32f4_pll_disable(pll_div->hw_pll); in stm32f4_pll_div_set_rate()
795 stm32f4_pll_enable(pll_div->hw_pll); in stm32f4_pll_div_set_rate()
820 return ERR_PTR(-ENOMEM); in clk_register_pll_div()
829 pll_div->div.reg = reg; in clk_register_pll_div()
830 pll_div->div.shift = shift; in clk_register_pll_div()
831 pll_div->div.width = width; in clk_register_pll_div()
832 pll_div->div.flags = clk_divider_flags; in clk_register_pll_div()
833 pll_div->div.lock = lock; in clk_register_pll_div()
834 pll_div->div.table = table; in clk_register_pll_div()
835 pll_div->div.hw.init = &init; in clk_register_pll_div()
837 pll_div->hw_pll = pll_hw; in clk_register_pll_div()
840 hw = &pll_div->div.hw; in clk_register_pll_div()
863 return -ENODEV; in stm32f4_pll_init_ssc()
868 pll->ssc_enable = true; in stm32f4_pll_init_ssc()
869 memcpy(&pll->ssc_conf, conf, sizeof(pll->ssc_conf)); in stm32f4_pll_init_ssc()
876 val = readl(base + pll->offset); in stm32f4_pll_init_ssc()
879 pr_debug("%s: pll: %s, parent: %s, parent-rate: %lu, n: %lu\n", in stm32f4_pll_init_ssc()
897 return -EINVAL; in stm32f4_pll_ssc_parse_dt()
899 ret = of_property_read_u32(np, "st,ssc-modfreq-hz", &conf->mod_freq); in stm32f4_pll_ssc_parse_dt()
903 ret = of_property_read_u32(np, "st,ssc-moddepth-permyriad", in stm32f4_pll_ssc_parse_dt()
904 &conf->mod_depth); in stm32f4_pll_ssc_parse_dt()
906 pr_err("%pOF: missing st,ssc-moddepth-permyriad\n", np); in stm32f4_pll_ssc_parse_dt()
911 "st,ssc-modmethod", in stm32f4_pll_ssc_parse_dt()
915 pr_err("%pOF: failed to get st,ssc-modmethod\n", np); in stm32f4_pll_ssc_parse_dt()
919 conf->mod_type = ret; in stm32f4_pll_ssc_parse_dt()
922 np, conf->mod_freq, conf->mod_depth, in stm32f4_pll_ssc_parse_dt()
923 stm32f4_ssc_mod_methods[ret], conf->mod_type); in stm32f4_pll_ssc_parse_dt()
942 return ERR_PTR(-ENOMEM); in stm32f4_rcc_register_pll()
944 vco = &vco_data[data->pll_num]; in stm32f4_rcc_register_pll()
946 init.name = vco->vco_name; in stm32f4_rcc_register_pll()
952 pll->gate.lock = lock; in stm32f4_rcc_register_pll()
953 pll->gate.reg = base + STM32F4_RCC_CR; in stm32f4_rcc_register_pll()
954 pll->gate.bit_idx = vco->bit_idx; in stm32f4_rcc_register_pll()
955 pll->gate.hw.init = &init; in stm32f4_rcc_register_pll()
957 pll->offset = vco->offset; in stm32f4_rcc_register_pll()
958 pll->n_start = data->n_start; in stm32f4_rcc_register_pll()
959 pll->bit_rdy_idx = vco->bit_rdy_idx; in stm32f4_rcc_register_pll()
960 pll->status = (readl(base + STM32F4_RCC_CR) >> vco->bit_idx) & 0x1; in stm32f4_rcc_register_pll()
962 reg = base + pll->offset; in stm32f4_rcc_register_pll()
964 pll_hw = &pll->gate.hw; in stm32f4_rcc_register_pll()
972 if (data->div_name[i]) in stm32f4_rcc_register_pll()
973 clk_register_pll_div(data->div_name[i], in stm32f4_rcc_register_pll()
974 vco->vco_name, in stm32f4_rcc_register_pll()
996 return -EINVAL; in stm32f4_rcc_lookup_clk_idx()
1006 return -EINVAL; in stm32f4_rcc_lookup_clk_idx()
1012 return stm32fx_end_primary_clk - 1 + hweight64(table[0]) + in stm32f4_rcc_lookup_clk_idx()
1020 int i = stm32f4_rcc_lookup_clk_idx(clkspec->args[0], clkspec->args[1]); in stm32f4_rcc_lookup_clk()
1023 return ERR_PTR(-EINVAL); in stm32f4_rcc_lookup_clk()
1073 bit_status = !(readl(gate->reg) & BIT(rgate->bit_rdy_idx)); in rgclk_enable()
1077 } while (bit_status && --timeout); in rgclk_enable()
1112 return ERR_PTR(-ENOMEM); in clk_register_rgate()
1120 rgate->bit_rdy_idx = bit_rdy_idx; in clk_register_rgate()
1122 rgate->gate.lock = lock; in clk_register_rgate()
1123 rgate->gate.reg = reg; in clk_register_rgate()
1124 rgate->gate.bit_idx = bit_idx; in clk_register_rgate()
1125 rgate->gate.hw.init = &init; in clk_register_rgate()
1127 hw = &rgate->gate.hw; in clk_register_rgate()
1207 hw = ERR_PTR(-EINVAL); in stm32_register_cclk()
1214 hw = ERR_PTR(-EINVAL); in stm32_register_cclk()
1218 gate->reg = reg; in stm32_register_cclk()
1219 gate->bit_idx = bit_idx; in stm32_register_cclk()
1220 gate->flags = 0; in stm32_register_cclk()
1221 gate->lock = lock; in stm32_register_cclk()
1223 mux->reg = reg; in stm32_register_cclk()
1224 mux->shift = shift; in stm32_register_cclk()
1225 mux->mask = 3; in stm32_register_cclk()
1226 mux->flags = 0; in stm32_register_cclk()
1229 &mux->hw, &cclk_mux_ops, in stm32_register_cclk()
1231 &gate->hw, &cclk_gate_ops, in stm32_register_cclk()
1260 "no-clock", "lse", "lsi", "hse-rtc"
1263 static const char *pll_src = "pll-src";
1267 static const char *dsi_parent[2] = { NULL, "pll-r" };
1269 static const char *lcd_parent[1] = { "pllsai-r-div" };
1271 static const char *i2s_parents[2] = { "plli2s-r", NULL };
1273 static const char *sai_parents[4] = { "pllsai-q-div", "plli2s-q-div", NULL,
1274 "no-clock" };
1276 static const char *pll48_parents[2] = { "pll-q", "pllsai-p" };
1282 static const char *spdif_parent[1] = { "plli2s-p" };
1289 static const char *i2c_parents[4] = { "apb1_div", "sys", "hsi", "no-clock" };
1319 CLK_LCD, "lcd-tft", lcd_parent, ARRAY_SIZE(lcd_parent),
1331 CLK_SAI1, "sai1-a", sai_parents, ARRAY_SIZE(sai_parents),
1337 CLK_SAI2, "sai1-b", sai_parents, ARRAY_SIZE(sai_parents),
1346 CLK_LCD, "lcd-tft", lcd_parent, ARRAY_SIZE(lcd_parent),
1358 CLK_SAI1, "sai1-a", sai_parents, ARRAY_SIZE(sai_parents),
1364 CLK_SAI2, "sai1-b", sai_parents, ARRAY_SIZE(sai_parents),
1391 CLK_LCD, "lcd-tft", lcd_parent, ARRAY_SIZE(lcd_parent),
1427 CLK_HDMI_CEC, "hdmi-cec",
1434 CLK_SPDIF, "spdif-rx",
1537 CLK_LCD, "lcd-tft", lcd_parent, ARRAY_SIZE(lcd_parent),
1579 CLK_HDMI_CEC, "hdmi-cec",
1586 CLK_SPDIF, "spdif-rx",
1748 .compatible = "st,stm32f42xx-rcc",
1752 .compatible = "st,stm32f469-rcc",
1756 .compatible = "st,stm32f746-rcc",
1760 .compatible = "st,stm32f769-rcc",
1781 hw = ERR_PTR(-EINVAL); in stm32_register_aux_clk()
1785 gate->reg = base + offset_gate; in stm32_register_aux_clk()
1786 gate->bit_idx = bit_idx; in stm32_register_aux_clk()
1787 gate->flags = 0; in stm32_register_aux_clk()
1788 gate->lock = lock; in stm32_register_aux_clk()
1789 gate_hw = &gate->hw; in stm32_register_aux_clk()
1796 hw = ERR_PTR(-EINVAL); in stm32_register_aux_clk()
1800 mux->reg = base + offset_mux; in stm32_register_aux_clk()
1801 mux->shift = shift; in stm32_register_aux_clk()
1802 mux->mask = mask; in stm32_register_aux_clk()
1803 mux->flags = 0; in stm32_register_aux_clk()
1804 mux_hw = &mux->hw; in stm32_register_aux_clk()
1809 hw = ERR_PTR(-EINVAL); in stm32_register_aux_clk()
1854 data = match->data; in stm32f4_rcc_init()
1856 stm32fx_end_primary_clk = data->end_primary; in stm32f4_rcc_init()
1858 clks = kmalloc_array(data->gates_num + stm32fx_end_primary_clk, in stm32f4_rcc_init()
1863 stm32f4_gate_map = data->gates_map; in stm32f4_rcc_init()
1874 if (of_device_is_compatible(np, "st,stm32f769-rcc")) { in stm32f4_rcc_init()
1895 pll_vco_hw = stm32f4_rcc_register_pll("vco_in", &data->pll_data[0], in stm32f4_rcc_init()
1899 &data->pll_data[1], &stm32f4_clk_lock); in stm32f4_rcc_init()
1902 &data->pll_data[2], &stm32f4_clk_lock); in stm32f4_rcc_init()
1910 hw = clk_register_pll_div(post_div->name, in stm32f4_rcc_init()
1911 post_div->parent, in stm32f4_rcc_init()
1912 post_div->flag, in stm32f4_rcc_init()
1913 base + post_div->offset, in stm32f4_rcc_init()
1914 post_div->shift, in stm32f4_rcc_init()
1915 post_div->width, in stm32f4_rcc_init()
1916 post_div->flag_div, in stm32f4_rcc_init()
1917 post_div->div_table, in stm32f4_rcc_init()
1918 clks[post_div->pll_idx], in stm32f4_rcc_init()
1921 if (post_div->idx != NO_IDX) in stm32f4_rcc_init()
1922 clks[post_div->idx] = hw; in stm32f4_rcc_init()
1952 for (n = 0; n < data->gates_num; n++) { in stm32f4_rcc_init()
1957 gd = &data->gates_data[n]; in stm32f4_rcc_init()
1958 secondary = 8 * (gd->offset - STM32F4_RCC_AHB1ENR) + in stm32f4_rcc_init()
1959 gd->bit_idx; in stm32f4_rcc_init()
1966 NULL, gd->name, gd->parent_name, gd->flags, in stm32f4_rcc_init()
1967 base + gd->offset, gd->bit_idx, 0, &stm32f4_clk_lock); in stm32f4_rcc_init()
1971 np, gd->name); in stm32f4_rcc_init()
1976 clks[CLK_LSI] = clk_register_rgate(NULL, "lsi", "clk-lsi", 0, in stm32f4_rcc_init()
1984 clks[CLK_LSE] = clk_register_rgate(NULL, "lse", "clk-lse", 0, in stm32f4_rcc_init()
1992 clks[CLK_HSE_RTC] = clk_hw_register_divider(NULL, "hse-rtc", "clk-hse", in stm32f4_rcc_init()
1997 pr_err("Unable to register hse-rtc clock\n"); in stm32f4_rcc_init()
2009 for (n = 0; n < data->aux_clk_num; n++) { in stm32f4_rcc_init()
2013 aux_clk = &data->aux_clk[n]; in stm32f4_rcc_init()
2015 hw = stm32_register_aux_clk(aux_clk->name, in stm32f4_rcc_init()
2016 aux_clk->parent_names, aux_clk->num_parents, in stm32f4_rcc_init()
2017 aux_clk->offset_mux, aux_clk->shift, in stm32f4_rcc_init()
2018 aux_clk->mask, aux_clk->offset_gate, in stm32f4_rcc_init()
2019 aux_clk->bit_idx, aux_clk->flags, in stm32f4_rcc_init()
2023 pr_warn("Unable to register %s clk\n", aux_clk->name); in stm32f4_rcc_init()
2027 if (aux_clk->idx != NO_IDX) in stm32f4_rcc_init()
2028 clks[aux_clk->idx] = hw; in stm32f4_rcc_init()
2031 if (of_device_is_compatible(np, "st,stm32f746-rcc")) { in stm32f4_rcc_init()
2049 CLK_OF_DECLARE_DRIVER(stm32f42xx_rcc, "st,stm32f42xx-rcc", stm32f4_rcc_init);
2050 CLK_OF_DECLARE_DRIVER(stm32f46xx_rcc, "st,stm32f469-rcc", stm32f4_rcc_init);
2051 CLK_OF_DECLARE_DRIVER(stm32f746_rcc, "st,stm32f746-rcc", stm32f4_rcc_init);
2052 CLK_OF_DECLARE_DRIVER(stm32f769_rcc, "st,stm32f769-rcc", stm32f4_rcc_init);