diff options
49 files changed, 1800 insertions, 259 deletions
diff --git a/Documentation/devicetree/bindings/clock/allwinner,sun8i-a83t-de2-clk.yaml b/Documentation/devicetree/bindings/clock/allwinner,sun8i-a83t-de2-clk.yaml index 3f995d2b30eb..e79eeac5f086 100644 --- a/Documentation/devicetree/bindings/clock/allwinner,sun8i-a83t-de2-clk.yaml +++ b/Documentation/devicetree/bindings/clock/allwinner,sun8i-a83t-de2-clk.yaml @@ -24,7 +24,7 @@ properties: - const: allwinner,sun8i-v3s-de2-clk - const: allwinner,sun50i-a64-de2-clk - const: allwinner,sun50i-h5-de2-clk - - const: allwinner,sun50i-h6-de2-clk + - const: allwinner,sun50i-h6-de3-clk - items: - const: allwinner,sun8i-r40-de2-clk - const: allwinner,sun8i-h3-de2-clk diff --git a/Documentation/devicetree/bindings/clock/samsung,exynos850-clock.yaml b/Documentation/devicetree/bindings/clock/samsung,exynos850-clock.yaml new file mode 100644 index 000000000000..7f8c91a29b91 --- /dev/null +++ b/Documentation/devicetree/bindings/clock/samsung,exynos850-clock.yaml @@ -0,0 +1,185 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/clock/samsung,exynos850-clock.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Samsung Exynos850 SoC clock controller + +maintainers: + - Sam Protsenko <semen.protsenko@linaro.org> + - Chanwoo Choi <cw00.choi@samsung.com> + - Krzysztof Kozlowski <krzysztof.kozlowski@canonical.com> + - Sylwester Nawrocki <s.nawrocki@samsung.com> + - Tomasz Figa <tomasz.figa@gmail.com> + +description: | + Exynos850 clock controller is comprised of several CMU units, generating + clocks for different domains. Those CMU units are modeled as separate device + tree nodes, and might depend on each other. Root clocks in that clock tree are + two external clocks:: OSCCLK (26 MHz) and RTCCLK (32768 Hz). Those external + clocks must be defined as fixed-rate clocks in dts. + + CMU_TOP is a top-level CMU, where all base clocks are prepared using PLLs and + dividers; all other leaf clocks (other CMUs) are usually derived from CMU_TOP. + + Each clock is assigned an identifier and client nodes can use this identifier + to specify the clock which they consume. All clocks available for usage + in clock consumer nodes are defined as preprocessor macros in + 'dt-bindings/clock/exynos850.h' header. + +properties: + compatible: + enum: + - samsung,exynos850-cmu-top + - samsung,exynos850-cmu-core + - samsung,exynos850-cmu-dpu + - samsung,exynos850-cmu-hsi + - samsung,exynos850-cmu-peri + + clocks: + minItems: 1 + maxItems: 5 + + clock-names: + minItems: 1 + maxItems: 5 + + "#clock-cells": + const: 1 + + reg: + maxItems: 1 + +allOf: + - if: + properties: + compatible: + contains: + const: samsung,exynos850-cmu-top + + then: + properties: + clocks: + items: + - description: External reference clock (26 MHz) + + clock-names: + items: + - const: oscclk + + - if: + properties: + compatible: + contains: + const: samsung,exynos850-cmu-core + + then: + properties: + clocks: + items: + - description: External reference clock (26 MHz) + - description: CMU_CORE bus clock (from CMU_TOP) + - description: CCI clock (from CMU_TOP) + - description: eMMC clock (from CMU_TOP) + - description: SSS clock (from CMU_TOP) + + clock-names: + items: + - const: oscclk + - const: dout_core_bus + - const: dout_core_cci + - const: dout_core_mmc_embd + - const: dout_core_sss + + - if: + properties: + compatible: + contains: + const: samsung,exynos850-cmu-dpu + + then: + properties: + clocks: + items: + - description: External reference clock (26 MHz) + - description: DPU clock (from CMU_TOP) + + clock-names: + items: + - const: oscclk + - const: dout_dpu + + - if: + properties: + compatible: + contains: + const: samsung,exynos850-cmu-hsi + + then: + properties: + clocks: + items: + - description: External reference clock (26 MHz) + - description: External RTC clock (32768 Hz) + - description: CMU_HSI bus clock (from CMU_TOP) + - description: SD card clock (from CMU_TOP) + - description: "USB 2.0 DRD clock (from CMU_TOP)" + + clock-names: + items: + - const: oscclk + - const: rtcclk + - const: dout_hsi_bus + - const: dout_hsi_mmc_card + - const: dout_hsi_usb20drd + + - if: + properties: + compatible: + contains: + const: samsung,exynos850-cmu-peri + + then: + properties: + clocks: + items: + - description: External reference clock (26 MHz) + - description: CMU_PERI bus clock (from CMU_TOP) + - description: UART clock (from CMU_TOP) + - description: Parent clock for HSI2C and SPI (from CMU_TOP) + + clock-names: + items: + - const: oscclk + - const: dout_peri_bus + - const: dout_peri_uart + - const: dout_peri_ip + +required: + - compatible + - "#clock-cells" + - clocks + - clock-names + - reg + +additionalProperties: false + +examples: + # Clock controller node for CMU_PERI + - | + #include <dt-bindings/clock/exynos850.h> + + cmu_peri: clock-controller@10030000 { + compatible = "samsung,exynos850-cmu-peri"; + reg = <0x10030000 0x8000>; + #clock-cells = <1>; + + clocks = <&oscclk>, <&cmu_top CLK_DOUT_PERI_BUS>, + <&cmu_top CLK_DOUT_PERI_UART>, + <&cmu_top CLK_DOUT_PERI_IP>; + clock-names = "oscclk", "dout_peri_bus", + "dout_peri_uart", "dout_peri_ip"; + }; + +... diff --git a/drivers/clk/clk-composite.c b/drivers/clk/clk-composite.c index c7b97fb0051b..c04ae0e7e4b4 100644 --- a/drivers/clk/clk-composite.c +++ b/drivers/clk/clk-composite.c @@ -42,6 +42,29 @@ static unsigned long clk_composite_recalc_rate(struct clk_hw *hw, return rate_ops->recalc_rate(rate_hw, parent_rate); } +static int clk_composite_determine_rate_for_parent(struct clk_hw *rate_hw, + struct clk_rate_request *req, + struct clk_hw *parent_hw, + const struct clk_ops *rate_ops) +{ + long rate; + + req->best_parent_hw = parent_hw; + req->best_parent_rate = clk_hw_get_rate(parent_hw); + + if (rate_ops->determine_rate) + return rate_ops->determine_rate(rate_hw, req); + + rate = rate_ops->round_rate(rate_hw, req->rate, + &req->best_parent_rate); + if (rate < 0) + return rate; + + req->rate = rate; + + return 0; +} + static int clk_composite_determine_rate(struct clk_hw *hw, struct clk_rate_request *req) { @@ -51,54 +74,56 @@ static int clk_composite_determine_rate(struct clk_hw *hw, struct clk_hw *rate_hw = composite->rate_hw; struct clk_hw *mux_hw = composite->mux_hw; struct clk_hw *parent; - unsigned long parent_rate; - long tmp_rate, best_rate = 0; unsigned long rate_diff; unsigned long best_rate_diff = ULONG_MAX; - long rate; - int i; + unsigned long best_rate = 0; + int i, ret; - if (rate_hw && rate_ops && rate_ops->determine_rate) { - __clk_hw_set_clk(rate_hw, hw); - return rate_ops->determine_rate(rate_hw, req); - } else if (rate_hw && rate_ops && rate_ops->round_rate && - mux_hw && mux_ops && mux_ops->set_parent) { + if (rate_hw && rate_ops && + (rate_ops->determine_rate || rate_ops->round_rate) && + mux_hw && mux_ops && mux_ops->set_parent) { req->best_parent_hw = NULL; if (clk_hw_get_flags(hw) & CLK_SET_RATE_NO_REPARENT) { + struct clk_rate_request tmp_req = *req; + parent = clk_hw_get_parent(mux_hw); - req->best_parent_hw = parent; - req->best_parent_rate = clk_hw_get_rate(parent); - rate = rate_ops->round_rate(rate_hw, req->rate, - &req->best_parent_rate); - if (rate < 0) - return rate; + ret = clk_composite_determine_rate_for_parent(rate_hw, + &tmp_req, + parent, + rate_ops); + if (ret) + return ret; + + req->rate = tmp_req.rate; + req->best_parent_rate = tmp_req.best_parent_rate; - req->rate = rate; return 0; } for (i = 0; i < clk_hw_get_num_parents(mux_hw); i++) { + struct clk_rate_request tmp_req = *req; + parent = clk_hw_get_parent_by_index(mux_hw, i); if (!parent) continue; - parent_rate = clk_hw_get_rate(parent); - - tmp_rate = rate_ops->round_rate(rate_hw, req->rate, - &parent_rate); - if (tmp_rate < 0) + ret = clk_composite_determine_rate_for_parent(rate_hw, + &tmp_req, + parent, + rate_ops); + if (ret) continue; - rate_diff = abs(req->rate - tmp_rate); + rate_diff = abs(req->rate - tmp_req.rate); if (!rate_diff || !req->best_parent_hw || best_rate_diff > rate_diff) { req->best_parent_hw = parent; - req->best_parent_rate = parent_rate; + req->best_parent_rate = tmp_req.best_parent_rate; best_rate_diff = rate_diff; - best_rate = tmp_rate; + best_rate = tmp_req.rate; } if (!rate_diff) @@ -107,6 +132,9 @@ static int clk_composite_determine_rate(struct clk_hw *hw, req->rate = best_rate; return 0; + } else if (rate_hw && rate_ops && rate_ops->determine_rate) { + __clk_hw_set_clk(rate_hw, hw); + return rate_ops->determine_rate(rate_hw, req); } else if (mux_hw && mux_ops && mux_ops->determine_rate) { __clk_hw_set_clk(mux_hw, hw); return mux_ops->determine_rate(mux_hw, req); diff --git a/drivers/clk/meson/meson8b.c b/drivers/clk/meson/meson8b.c index a844d35b553a..cd0f5bae24d4 100644 --- a/drivers/clk/meson/meson8b.c +++ b/drivers/clk/meson/meson8b.c @@ -118,6 +118,56 @@ static struct clk_regmap meson8b_fixed_pll = { }, }; +static struct clk_fixed_factor hdmi_pll_dco_in = { + .mult = 2, + .div = 1, + .hw.init = &(struct clk_init_data){ + .name = "hdmi_pll_dco_in", + .ops = &clk_fixed_factor_ops, + .parent_data = &(const struct clk_parent_data) { + .fw_name = "xtal", + .index = -1, + }, + .num_parents = 1, + }, +}; + +/* + * Taken from the vendor driver for the 2970/2975MHz (both only differ in the + * FRAC part in HHI_VID_PLL_CNTL2) where these values are identical for Meson8, + * Meson8b and Meson8m2. This doubles the input (or output - it's not clear + * which one but the result is the same) clock. The vendor driver additionally + * has the following comment about: "optimise HPLL VCO 2.97GHz performance". + */ +static const struct reg_sequence meson8b_hdmi_pll_init_regs[] = { + { .reg = HHI_VID_PLL_CNTL2, .def = 0x69c84000 }, + { .reg = HHI_VID_PLL_CNTL3, .def = 0x8a46c023 }, + { .reg = HHI_VID_PLL_CNTL4, .def = 0x4123b100 }, + { .reg = HHI_VID_PLL_CNTL5, .def = 0x00012385 }, + { .reg = HHI_VID2_PLL_CNTL2, .def = 0x0430a800 }, +}; + +static const struct pll_params_table hdmi_pll_params_table[] = { + PLL_PARAMS(40, 1), + PLL_PARAMS(42, 1), + PLL_PARAMS(44, 1), + PLL_PARAMS(45, 1), + PLL_PARAMS(49, 1), + PLL_PARAMS(52, 1), + PLL_PARAMS(54, 1), + PLL_PARAMS(56, 1), + PLL_PARAMS(59, 1), + PLL_PARAMS(60, 1), + PLL_PARAMS(61, 1), + PLL_PARAMS(62, 1), + PLL_PARAMS(64, 1), + PLL_PARAMS(66, 1), + PLL_PARAMS(68, 1), + PLL_PARAMS(71, 1), + PLL_PARAMS(82, 1), + { /* sentinel */ } +}; + static struct clk_regmap meson8b_hdmi_pll_dco = { .data = &(struct meson_clk_pll_data){ .en = { @@ -150,15 +200,16 @@ static struct clk_regmap meson8b_hdmi_pll_dco = { .shift = 29, .width = 1, }, + .table = hdmi_pll_params_table, + .init_regs = meson8b_hdmi_pll_init_regs, + .init_count = ARRAY_SIZE(meson8b_hdmi_pll_init_regs), }, .hw.init = &(struct clk_init_data){ /* sometimes also called "HPLL" or "HPLL PLL" */ .name = "hdmi_pll_dco", - .ops = &meson_clk_pll_ro_ops, - .parent_data = &(const struct clk_parent_data) { - .fw_name = "xtal", - .name = "xtal", - .index = -1, + .ops = &meson_clk_pll_ops, + .parent_hws = (const struct clk_hw *[]) { + &hdmi_pll_dco_in.hw }, .num_parents = 1, }, @@ -173,7 +224,7 @@ static struct clk_regmap meson8b_hdmi_pll_lvds_out = { }, .hw.init = &(struct clk_init_data){ .name = "hdmi_pll_lvds_out", - .ops = &clk_regmap_divider_ro_ops, + .ops = &clk_regmap_divider_ops, .parent_hws = (const struct clk_hw *[]) { &meson8b_hdmi_pll_dco.hw }, @@ -191,7 +242,7 @@ static struct clk_regmap meson8b_hdmi_pll_hdmi_out = { }, .hw.init = &(struct clk_init_data){ .name = "hdmi_pll_hdmi_out", - .ops = &clk_regmap_divider_ro_ops, + .ops = &clk_regmap_divider_ops, .parent_hws = (const struct clk_hw *[]) { &meson8b_hdmi_pll_dco.hw }, @@ -1045,6 +1096,23 @@ static struct clk_regmap meson8b_l2_dram_clk_gate = { }, }; +/* also called LVDS_CLK_EN */ +static struct clk_regmap meson8b_vid_pll_lvds_en = { + .data = &(struct clk_regmap_gate_data){ + .offset = HHI_VID_DIVIDER_CNTL, + .bit_idx = 11, + }, + .hw.init = &(struct clk_init_data){ + .name = "vid_pll_lvds_en", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &meson8b_hdmi_pll_lvds_out.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + static struct clk_regmap meson8b_vid_pll_in_sel = { .data = &(struct clk_regmap_mux_data){ .offset = HHI_VID_DIVIDER_CNTL, @@ -1053,7 +1121,7 @@ static struct clk_regmap meson8b_vid_pll_in_sel = { }, .hw.init = &(struct clk_init_data){ .name = "vid_pll_in_sel", - .ops = &clk_regmap_mux_ro_ops, + .ops = &clk_regmap_mux_ops, /* * TODO: depending on the SoC there is also a second parent: * Meson8: unknown @@ -1061,7 +1129,7 @@ static struct clk_regmap meson8b_vid_pll_in_sel = { * Meson8m2: vid2_pll */ .parent_hws = (const struct clk_hw *[]) { - &meson8b_hdmi_pll_lvds_out.hw + &meson8b_vid_pll_lvds_en.hw }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT, @@ -1075,7 +1143,7 @@ static struct clk_regmap meson8b_vid_pll_in_en = { }, .hw.init = &(struct clk_init_data){ .name = "vid_pll_in_en", - .ops = &clk_regmap_gate_ro_ops, + .ops = &clk_regmap_gate_ops, .parent_hws = (const struct clk_hw *[]) { &meson8b_vid_pll_in_sel.hw }, @@ -1092,7 +1160,7 @@ static struct clk_regmap meson8b_vid_pll_pre_div = { }, .hw.init = &(struct clk_init_data){ .name = "vid_pll_pre_div", - .ops = &clk_regmap_divider_ro_ops, + .ops = &clk_regmap_divider_ops, .parent_hws = (const struct clk_hw *[]) { &meson8b_vid_pll_in_en.hw }, @@ -1109,7 +1177,7 @@ static struct clk_regmap meson8b_vid_pll_post_div = { }, .hw.init = &(struct clk_init_data){ .name = "vid_pll_post_div", - .ops = &clk_regmap_divider_ro_ops, + .ops = &clk_regmap_divider_ops, .parent_hws = (const struct clk_hw *[]) { &meson8b_vid_pll_pre_div.hw }, @@ -1126,7 +1194,7 @@ static struct clk_regmap meson8b_vid_pll = { }, .hw.init = &(struct clk_init_data){ .name = "vid_pll", - .ops = &clk_regmap_mux_ro_ops, + .ops = &clk_regmap_mux_ops, /* TODO: parent 0x2 is vid_pll_pre_div_mult7_div2 */ .parent_hws = (const struct clk_hw *[]) { &meson8b_vid_pll_pre_div.hw, @@ -1145,7 +1213,7 @@ static struct clk_regmap meson8b_vid_pll_final_div = { }, .hw.init = &(struct clk_init_data){ .name = "vid_pll_final_div", - .ops = &clk_regmap_divider_ro_ops, + .ops = &clk_regmap_divider_ops, .parent_hws = (const struct clk_hw *[]) { &meson8b_vid_pll.hw }, @@ -1172,10 +1240,10 @@ static struct clk_regmap meson8b_vclk_in_sel = { }, .hw.init = &(struct clk_init_data){ .name = "vclk_in_sel", - .ops = &clk_regmap_mux_ro_ops, + .ops = &clk_regmap_mux_ops, .parent_hws = meson8b_vclk_mux_parent_hws, .num_parents = ARRAY_SIZE(meson8b_vclk_mux_parent_hws), - .flags = CLK_SET_RATE_PARENT, + .flags = CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT, }, }; @@ -1186,7 +1254,7 @@ static struct clk_regmap meson8b_vclk_in_en = { }, .hw.init = &(struct clk_init_data){ .name = "vclk_in_en", - .ops = &clk_regmap_gate_ro_ops, + .ops = &clk_regmap_gate_ops, .parent_hws = (const struct clk_hw *[]) { &meson8b_vclk_in_sel.hw }, @@ -1202,7 +1270,7 @@ static struct clk_regmap meson8b_vclk_en = { }, .hw.init = &(struct clk_init_data){ .name = "vclk_en", - .ops = &clk_regmap_gate_ro_ops, + .ops = &clk_regmap_gate_ops, .parent_hws = (const struct clk_hw *[]) { &meson8b_vclk_in_en.hw }, @@ -1218,7 +1286,7 @@ static struct clk_regmap meson8b_vclk_div1_gate = { }, .hw.init = &(struct clk_init_data){ .name = "vclk_div1_en", - .ops = &clk_regmap_gate_ro_ops, + .ops = &clk_regmap_gate_ops, .parent_hws = (const struct clk_hw *[]) { &meson8b_vclk_en.hw }, @@ -1248,7 +1316,7 @@ static struct clk_regmap meson8b_vclk_div2_div_gate = { }, .hw.init = &(struct clk_init_data){ .name = "vclk_div2_en", - .ops = &clk_regmap_gate_ro_ops, + .ops = &clk_regmap_gate_ops, .parent_hws = (const struct clk_hw *[]) { &meson8b_vclk_div2_div.hw }, @@ -1278,7 +1346,7 @@ static struct clk_regmap meson8b_vclk_div4_div_gate = { }, .hw.init = &(struct clk_init_data){ .name = "vclk_div4_en", - .ops = &clk_regmap_gate_ro_ops, + .ops = &clk_regmap_gate_ops, .parent_hws = (const struct clk_hw *[]) { &meson8b_vclk_div4_div.hw }, @@ -1308,7 +1376,7 @@ static struct clk_regmap meson8b_vclk_div6_div_gate = { }, .hw.init = &(struct clk_init_data){ .name = "vclk_div6_en", - .ops = &clk_regmap_gate_ro_ops, + .ops = &clk_regmap_gate_ops, .parent_hws = (const struct clk_hw *[]) { &meson8b_vclk_div6_div.hw }, @@ -1338,7 +1406,7 @@ static struct clk_regmap meson8b_vclk_div12_div_gate = { }, .hw.init = &(struct clk_init_data){ .name = "vclk_div12_en", - .ops = &clk_regmap_gate_ro_ops, + .ops = &clk_regmap_gate_ops, .parent_hws = (const struct clk_hw *[]) { &meson8b_vclk_div12_div.hw }, @@ -1355,10 +1423,10 @@ static struct clk_regmap meson8b_vclk2_in_sel = { }, .hw.init = &(struct clk_init_data){ .name = "vclk2_in_sel", - .ops = &clk_regmap_mux_ro_ops, + .ops = &clk_regmap_mux_ops, .parent_hws = meson8b_vclk_mux_parent_hws, .num_parents = ARRAY_SIZE(meson8b_vclk_mux_parent_hws), - .flags = CLK_SET_RATE_PARENT, + .flags = CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT, }, }; @@ -1369,7 +1437,7 @@ static struct clk_regmap meson8b_vclk2_clk_in_en = { }, .hw.init = &(struct clk_init_data){ .name = "vclk2_in_en", - .ops = &clk_regmap_gate_ro_ops, + .ops = &clk_regmap_gate_ops, .parent_hws = (const struct clk_hw *[]) { &meson8b_vclk2_in_sel.hw }, @@ -1385,7 +1453,7 @@ static struct clk_regmap meson8b_vclk2_clk_en = { }, .hw.init = &(struct clk_init_data){ .name = "vclk2_en", - .ops = &clk_regmap_gate_ro_ops, + .ops = &clk_regmap_gate_ops, .parent_hws = (const struct clk_hw *[]) { &meson8b_vclk2_clk_in_en.hw }, @@ -1401,7 +1469,7 @@ static struct clk_regmap meson8b_vclk2_div1_gate = { }, .hw.init = &(struct clk_init_data){ .name = "vclk2_div1_en", - .ops = &clk_regmap_gate_ro_ops, + .ops = &clk_regmap_gate_ops, .parent_hws = (const struct clk_hw *[]) { &meson8b_vclk2_clk_en.hw }, @@ -1431,7 +1499,7 @@ static struct clk_regmap meson8b_vclk2_div2_div_gate = { }, .hw.init = &(struct clk_init_data){ .name = "vclk2_div2_en", - .ops = &clk_regmap_gate_ro_ops, + .ops = &clk_regmap_gate_ops, .parent_hws = (const struct clk_hw *[]) { &meson8b_vclk2_div2_div.hw }, @@ -1461,7 +1529,7 @@ static struct clk_regmap meson8b_vclk2_div4_div_gate = { }, .hw.init = &(struct clk_init_data){ .name = "vclk2_div4_en", - .ops = &clk_regmap_gate_ro_ops, + .ops = &clk_regmap_gate_ops, .parent_hws = (const struct clk_hw *[]) { &meson8b_vclk2_div4_div.hw }, @@ -1491,7 +1559,7 @@ static struct clk_regmap meson8b_vclk2_div6_div_gate = { }, .hw.init = &(struct clk_init_data){ .name = "vclk2_div6_en", - .ops = &clk_regmap_gate_ro_ops, + .ops = &clk_regmap_gate_ops, .parent_hws = (const struct clk_hw *[]) { &meson8b_vclk2_div6_div.hw }, @@ -1521,7 +1589,7 @@ static struct clk_regmap meson8b_vclk2_div12_div_gate = { }, .hw.init = &(struct clk_init_data){ .name = "vclk2_div12_en", - .ops = &clk_regmap_gate_ro_ops, + .ops = &clk_regmap_gate_ops, .parent_hws = (const struct clk_hw *[]) { &meson8b_vclk2_div12_div.hw }, @@ -1546,7 +1614,7 @@ static struct clk_regmap meson8b_cts_enct_sel = { }, .hw.init = &(struct clk_init_data){ .name = "cts_enct_sel", - .ops = &clk_regmap_mux_ro_ops, + .ops = &clk_regmap_mux_ops, .parent_hws = meson8b_vclk_enc_mux_parent_hws, .num_parents = ARRAY_SIZE(meson8b_vclk_enc_mux_parent_hws), .flags = CLK_SET_RATE_PARENT, @@ -1560,7 +1628,7 @@ static struct clk_regmap meson8b_cts_enct = { }, .hw.init = &(struct clk_init_data){ .name = "cts_enct", - .ops = &clk_regmap_gate_ro_ops, + .ops = &clk_regmap_gate_ops, .parent_hws = (const struct clk_hw *[]) { &meson8b_cts_enct_sel.hw }, @@ -1577,7 +1645,7 @@ static struct clk_regmap meson8b_cts_encp_sel = { }, .hw.init = &(struct clk_init_data){ .name = "cts_encp_sel", - .ops = &clk_regmap_mux_ro_ops, + .ops = &clk_regmap_mux_ops, .parent_hws = meson8b_vclk_enc_mux_parent_hws, .num_parents = ARRAY_SIZE(meson8b_vclk_enc_mux_parent_hws), .flags = CLK_SET_RATE_PARENT, @@ -1591,7 +1659,7 @@ static struct clk_regmap meson8b_cts_encp = { }, .hw.init = &(struct clk_init_data){ .name = "cts_encp", - .ops = &clk_regmap_gate_ro_ops, + .ops = &clk_regmap_gate_ops, .parent_hws = (const struct clk_hw *[]) { &meson8b_cts_encp_sel.hw }, @@ -1608,7 +1676,7 @@ static struct clk_regmap meson8b_cts_enci_sel = { }, .hw.init = &(struct clk_init_data){ .name = "cts_enci_sel", - .ops = &clk_regmap_mux_ro_ops, + .ops = &clk_regmap_mux_ops, .parent_hws = meson8b_vclk_enc_mux_parent_hws, .num_parents = ARRAY_SIZE(meson8b_vclk_enc_mux_parent_hws), .flags = CLK_SET_RATE_PARENT, @@ -1622,7 +1690,7 @@ static struct clk_regmap meson8b_cts_enci = { }, .hw.init = &(struct clk_init_data){ .name = "cts_enci", - .ops = &clk_regmap_gate_ro_ops, + .ops = &clk_regmap_gate_ops, .parent_hws = (const struct clk_hw *[]) { &meson8b_cts_enci_sel.hw }, @@ -1639,7 +1707,7 @@ static struct clk_regmap meson8b_hdmi_tx_pixel_sel = { }, .hw.init = &(struct clk_init_data){ .name = "hdmi_tx_pixel_sel", - .ops = &clk_regmap_mux_ro_ops, + .ops = &clk_regmap_mux_ops, .parent_hws = meson8b_vclk_enc_mux_parent_hws, .num_parents = ARRAY_SIZE(meson8b_vclk_enc_mux_parent_hws), .flags = CLK_SET_RATE_PARENT, @@ -1653,7 +1721,7 @@ static struct clk_regmap meson8b_hdmi_tx_pixel = { }, .hw.init = &(struct clk_init_data){ .name = "hdmi_tx_pixel", - .ops = &clk_regmap_gate_ro_ops, + .ops = &clk_regmap_gate_ops, .parent_hws = (const struct clk_hw *[]) { &meson8b_hdmi_tx_pixel_sel.hw }, @@ -1678,7 +1746,7 @@ static struct clk_regmap meson8b_cts_encl_sel = { }, .hw.init = &(struct clk_init_data){ .name = "cts_encl_sel", - .ops = &clk_regmap_mux_ro_ops, + .ops = &clk_regmap_mux_ops, .parent_hws = meson8b_vclk2_enc_mux_parent_hws, .num_parents = ARRAY_SIZE(meson8b_vclk2_enc_mux_parent_hws), .flags = CLK_SET_RATE_PARENT, @@ -1692,7 +1760,7 @@ static struct clk_regmap meson8b_cts_encl = { }, .hw.init = &(struct clk_init_data){ .name = "cts_encl", - .ops = &clk_regmap_gate_ro_ops, + .ops = &clk_regmap_gate_ops, .parent_hws = (const struct clk_hw *[]) { &meson8b_cts_encl_sel.hw }, @@ -1709,7 +1777,7 @@ static struct clk_regmap meson8b_cts_vdac0_sel = { }, .hw.init = &(struct clk_init_data){ .name = "cts_vdac0_sel", - .ops = &clk_regmap_mux_ro_ops, + .ops = &clk_regmap_mux_ops, .parent_hws = meson8b_vclk2_enc_mux_parent_hws, .num_parents = ARRAY_SIZE(meson8b_vclk2_enc_mux_parent_hws), .flags = CLK_SET_RATE_PARENT, @@ -1723,7 +1791,7 @@ static struct clk_regmap meson8b_cts_vdac0 = { }, .hw.init = &(struct clk_init_data){ .name = "cts_vdac0", - .ops = &clk_regmap_gate_ro_ops, + .ops = &clk_regmap_gate_ops, .parent_hws = (const struct clk_hw *[]) { &meson8b_cts_vdac0_sel.hw }, @@ -2905,6 +2973,8 @@ static struct clk_hw_onecell_data meson8_hw_onecell_data = { [CLKID_CTS_MCLK_I958_DIV] = &meson8b_cts_mclk_i958_div.hw, [CLKID_CTS_MCLK_I958] = &meson8b_cts_mclk_i958.hw, [CLKID_CTS_I958] = &meson8b_cts_i958.hw, + [CLKID_VID_PLL_LVDS_EN] = &meson8b_vid_pll_lvds_en.hw, + [CLKID_HDMI_PLL_DCO_IN] = &hdmi_pll_dco_in.hw, [CLK_NR_CLKS] = NULL, }, .num = CLK_NR_CLKS, @@ -3122,6 +3192,8 @@ static struct clk_hw_onecell_data meson8b_hw_onecell_data = { [CLKID_CTS_MCLK_I958_DIV] = &meson8b_cts_mclk_i958_div.hw, [CLKID_CTS_MCLK_I958] = &meson8b_cts_mclk_i958.hw, [CLKID_CTS_I958] = &meson8b_cts_i958.hw, + [CLKID_VID_PLL_LVDS_EN] = &meson8b_vid_pll_lvds_en.hw, + [CLKID_HDMI_PLL_DCO_IN] = &hdmi_pll_dco_in.hw, [CLK_NR_CLKS] = NULL, }, .num = CLK_NR_CLKS, @@ -3341,6 +3413,8 @@ static struct clk_hw_onecell_data meson8m2_hw_onecell_data = { [CLKID_CTS_MCLK_I958_DIV] = &meson8b_cts_mclk_i958_div.hw, [CLKID_CTS_MCLK_I958] = &meson8b_cts_mclk_i958.hw, [CLKID_CTS_I958] = &meson8b_cts_i958.hw, + [CLKID_VID_PLL_LVDS_EN] = &meson8b_vid_pll_lvds_en.hw, + [CLKID_HDMI_PLL_DCO_IN] = &hdmi_pll_dco_in.hw, [CLK_NR_CLKS] = NULL, }, .num = CLK_NR_CLKS, @@ -3539,6 +3613,7 @@ static struct clk_regmap *const meson8b_clk_regmaps[] = { &meson8b_cts_mclk_i958_div, &meson8b_cts_mclk_i958, &meson8b_cts_i958, + &meson8b_vid_pll_lvds_en, }; static const struct meson8b_clk_reset_line { diff --git a/drivers/clk/meson/meson8b.h b/drivers/clk/meson/meson8b.h index b1a5074cf148..ce62ed47cbfc 100644 --- a/drivers/clk/meson/meson8b.h +++ b/drivers/clk/meson/meson8b.h @@ -51,6 +51,16 @@ #define HHI_SYS_PLL_CNTL 0x300 /* 0xc0 offset in data sheet */ #define HHI_VID_PLL_CNTL 0x320 /* 0xc8 offset in data sheet */ #define HHI_VID_PLL_CNTL2 0x324 /* 0xc9 offset in data sheet */ +#define HHI_VID_PLL_CNTL3 0x328 /* 0xca offset in data sheet */ +#define HHI_VID_PLL_CNTL4 0x32c /* 0xcb offset in data sheet */ +#define HHI_VID_PLL_CNTL5 0x330 /* 0xcc offset in data sheet */ +#define HHI_VID_PLL_CNTL6 0x334 /* 0xcd offset in data sheet */ +#define HHI_VID2_PLL_CNTL 0x380 /* 0xe0 offset in data sheet */ +#define HHI_VID2_PLL_CNTL2 0x384 /* 0xe1 offset in data sheet */ +#define HHI_VID2_PLL_CNTL3 0x388 /* 0xe2 offset in data sheet */ +#define HHI_VID2_PLL_CNTL4 0x38c /* 0xe3 offset in data sheet */ +#define HHI_VID2_PLL_CNTL5 0x390 /* 0xe4 offset in data sheet */ +#define HHI_VID2_PLL_CNTL6 0x394 /* 0xe5 offset in data sheet */ /* * MPLL register offeset taken from the S905 datasheet. Vendor kernel source @@ -107,14 +117,11 @@ #define CLKID_PERIPH_SEL 125 #define CLKID_AXI_SEL 127 #define CLKID_L2_DRAM_SEL 129 -#define CLKID_HDMI_PLL_LVDS_OUT 131 -#define CLKID_HDMI_PLL_HDMI_OUT 132 +#define CLKID_HDMI_PLL_LVDS_OUT 131 #define CLKID_VID_PLL_IN_SEL 133 #define CLKID_VID_PLL_IN_EN 134 #define CLKID_VID_PLL_PRE_DIV 135 #define CLKID_VID_PLL_POST_DIV 136 -#define CLKID_VID_PLL_FINAL_DIV 137 -#define CLKID_VCLK_IN_SEL 138 #define CLKID_VCLK_IN_EN 139 #define CLKID_VCLK_DIV1 140 #define CLKID_VCLK_DIV2_DIV 141 @@ -125,7 +132,6 @@ #define CLKID_VCLK_DIV6 146 #define CLKID_VCLK_DIV12_DIV 147 #define CLKID_VCLK_DIV12 148 -#define CLKID_VCLK2_IN_SEL 149 #define CLKID_VCLK2_IN_EN 150 #define CLKID_VCLK2_DIV1 151 #define CLKID_VCLK2_DIV2_DIV 152 @@ -137,17 +143,11 @@ #define CLKID_VCLK2_DIV12_DIV 158 #define CLKID_VCLK2_DIV12 159 #define CLKID_CTS_ENCT_SEL 160 -#define CLKID_CTS_ENCT 161 #define CLKID_CTS_ENCP_SEL 162 -#define CLKID_CTS_ENCP 163 #define CLKID_CTS_ENCI_SEL 164 -#define CLKID_CTS_ENCI 165 #define CLKID_HDMI_TX_PIXEL_SEL 166 -#define CLKID_HDMI_TX_PIXEL 167 #define CLKID_CTS_ENCL_SEL 168 -#define CLKID_CTS_ENCL 169 #define CLKID_CTS_VDAC0_SEL 170 -#define CLKID_CTS_VDAC0 171 #define CLKID_HDMI_SYS_SEL 172 #define CLKID_HDMI_SYS_DIV 173 #define CLKID_MALI_0_SEL 175 @@ -182,8 +182,10 @@ #define CLKID_CTS_MCLK_I958_DIV 211 #define CLKID_VCLK_EN 214 #define CLKID_VCLK2_EN 215 +#define CLKID_VID_PLL_LVDS_EN 216 +#define CLKID_HDMI_PLL_DCO_IN 217 -#define CLK_NR_CLKS 216 +#define CLK_NR_CLKS 218 /* * include the CLKID and RESETID that have diff --git a/drivers/clk/samsung/Kconfig b/drivers/clk/samsung/Kconfig index 0441c4f73ac9..0e18d6ff2916 100644 --- a/drivers/clk/samsung/Kconfig +++ b/drivers/clk/samsung/Kconfig @@ -67,7 +67,8 @@ config EXYNOS_5420_COMMON_CLK depends on COMMON_CLK_SAMSUNG help Support for the clock controller present on the Samsung - Exynos5420 SoCs. Choose Y here only if you build for this SoC. + Exynos5420/Exynos5422/Exynos5800 SoCs. Choose Y here only if you + build for this SoC. config EXYNOS_ARM64_COMMON_CLK bool "Samsung Exynos ARMv8-family clock controller support" if COMPILE_TEST @@ -79,38 +80,47 @@ config EXYNOS_AUDSS_CLK_CON default y if ARCH_EXYNOS help Support for the Audio Subsystem CLKCON clock controller present - on some Exynos SoC variants. Choose M or Y here if you want to - use audio devices such as I2S, PCM, etc. + on some Samsung Exynos SoC variants. Choose M or Y here if you want + to use audio devices such as I2S, PCM, etc. config EXYNOS_CLKOUT tristate "Samsung Exynos clock output driver" depends on COMMON_CLK_SAMSUNG default y if ARCH_EXYNOS help - Support for the clock output (XCLKOUT) present on some of Exynos SoC - variants. Usually the XCLKOUT is used to monitor the status of the - certains clocks from SoC, but it could also be tied to other devices - as an input clock. + Support for the clock output (XCLKOUT) present on some of Samsung + Exynos SoC variants. Usually the XCLKOUT is used to monitor the + status of the certains clocks from SoC, but it could also be tied to + other devices as an input clock. # For S3C24XX platforms, select following symbols: config S3C2410_COMMON_CLK bool "Samsung S3C2410 clock controller support" if COMPILE_TEST select COMMON_CLK_SAMSUNG help - Build the s3c2410 clock driver based on the common clock framework. + Support for the clock controller present on the Samsung + S3C2410/S3C2440/S3C2442 SoCs. Choose Y here only if you build for + this SoC. config S3C2410_COMMON_DCLK bool select COMMON_CLK_SAMSUNG select REGMAP_MMIO help - Temporary symbol to build the dclk driver based on the common clock - framework. + Support for the dclk clock controller present on the Samsung + S3C2410/S3C2412/S3C2440/S3C2443 SoCs. Choose Y here only if you build + for this SoC. config S3C2412_COMMON_CLK bool "Samsung S3C2412 clock controller support" if COMPILE_TEST select COMMON_CLK_SAMSUNG + help + Support for the clock controller present on the Samsung S3C2412 SoCs. + Choose Y here only if you build for this SoC. config S3C2443_COMMON_CLK bool "Samsung S3C2443 clock controller support" if COMPILE_TEST select COMMON_CLK_SAMSUNG + help + Support for the clock controller present on the Samsung + S3C2416/S3C2443 SoCs. Choose Y here only if you build for this SoC. diff --git a/drivers/clk/samsung/Makefile b/drivers/clk/samsung/Makefile index 028b2e27a37e..c46cf11e4d0b 100644 --- a/drivers/clk/samsung/Makefile +++ b/drivers/clk/samsung/Makefile @@ -17,6 +17,7 @@ obj-$(CONFIG_EXYNOS_ARM64_COMMON_CLK) += clk-exynos5433.o obj-$(CONFIG_EXYNOS_AUDSS_CLK_CON) += clk-exynos-audss.o obj-$(CONFIG_EXYNOS_CLKOUT) += clk-exynos-clkout.o obj-$(CONFIG_EXYNOS_ARM64_COMMON_CLK) += clk-exynos7.o +obj-$(CONFIG_EXYNOS_ARM64_COMMON_CLK) += clk-exynos850.o obj-$(CONFIG_S3C2410_COMMON_CLK)+= clk-s3c2410.o obj-$(CONFIG_S3C2410_COMMON_DCLK)+= clk-s3c2410-dclk.o obj-$(CONFIG_S3C2412_COMMON_CLK)+= clk-s3c2412.o diff --git a/drivers/clk/samsung/clk-cpu.c b/drivers/clk/samsung/clk-cpu.c index 00ef4d1b0888..7f20d9aedaa9 100644 --- a/drivers/clk/samsung/clk-cpu.c +++ b/drivers/clk/samsung/clk-cpu.c @@ -469,3 +469,21 @@ free_cpuclk: kfree(cpuclk); return ret; } + +void __init samsung_clk_register_cpu(struct samsung_clk_provider *ctx, + const struct samsung_cpu_clock *list, unsigned int nr_clk) +{ + unsigned int idx; + unsigned int num_cfgs; + struct clk_hw **hws = ctx->clk_data.hws; + + for (idx = 0; idx < nr_clk; idx++, list++) { + /* find count of configuration rates in cfg */ + for (num_cfgs = 0; list->cfg[num_cfgs].prate != 0; ) + num_cfgs++; + + exynos_register_cpu_clock(ctx, list->id, list->name, hws[list->parent_id], + hws[list->alt_parent_id], list->offset, list->cfg, num_cfgs, + list->flags); + } +} diff --git a/drivers/clk/samsung/clk-exynos-audss.c b/drivers/clk/samsung/clk-exynos-audss.c index 42b5d32c6cc7..9cc127a162ad 100644 --- a/drivers/clk/samsung/clk-exynos-audss.c +++ b/drivers/clk/samsung/clk-exynos-audss.c @@ -129,7 +129,6 @@ static int exynos_audss_clk_probe(struct platform_device *pdev) struct clk *pll_ref, *pll_in, *cdclk, *sclk_audio, *sclk_pcm_in; const struct exynos_audss_clk_drvdata *variant; struct clk_hw **clk_table; - struct resource *res; struct device *dev = &pdev->dev; int i, ret = 0; @@ -137,8 +136,7 @@ static int exynos_audss_clk_probe(struct platform_device *pdev) if (!variant) return -EINVAL; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - reg_base = devm_ioremap_resource(dev, res); + reg_base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(reg_base)) return PTR_ERR(reg_base); diff --git a/drivers/clk/samsung/clk-exynos4412-isp.c b/drivers/clk/samsung/clk-exynos4412-isp.c index b69e381b8c0c..471a6fb82670 100644 --- a/drivers/clk/samsung/clk-exynos4412-isp.c +++ b/drivers/clk/samsung/clk-exynos4412-isp.c @@ -110,11 +110,9 @@ static int __init exynos4x12_isp_clk_probe(struct platform_device *pdev) struct samsung_clk_provider *ctx; struct device *dev = &pdev->dev; struct device_node *np = dev->of_node; - struct resource *res; void __iomem *reg_base; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - reg_base = devm_ioremap_resource(dev, res); + reg_base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(reg_base)) return PTR_ERR(reg_base); diff --git a/drivers/clk/samsung/clk-exynos5433.c b/drivers/clk/samsung/clk-exynos5433.c index f203074d858b..f9daae20f393 100644 --- a/drivers/clk/samsung/clk-exynos5433.c +++ b/drivers/clk/samsung/clk-exynos5433.c @@ -3675,44 +3675,32 @@ static const struct exynos_cpuclk_cfg_data exynos5433_apolloclk_d[] __initconst { 0 }, }; +static const struct samsung_cpu_clock apollo_cpu_clks[] __initconst = { + CPU_CLK(CLK_SCLK_APOLLO, "apolloclk", CLK_MOUT_APOLLO_PLL, + CLK_MOUT_BUS_PLL_APOLLO_USER, + CLK_CPU_HAS_E5433_REGS_LAYOUT, 0x200, + exynos5433_apolloclk_d), +}; + +static const struct samsung_cmu_info apollo_cmu_info __initconst = { + .pll_clks = apollo_pll_clks, + .nr_pll_clks = ARRAY_SIZE(apollo_pll_clks), + .mux_clks = apollo_mux_clks, + .nr_mux_clks = ARRAY_SIZE(apollo_mux_clks), + .div_clks = apollo_div_clks, + .nr_div_clks = ARRAY_SIZE(apollo_div_clks), + .gate_clks = apollo_gate_clks, + .nr_gate_clks = ARRAY_SIZE(apollo_gate_clks), + .cpu_clks = apollo_cpu_clks, + .nr_cpu_clks = ARRAY_SIZE(apollo_cpu_clks), + .nr_clk_ids = APOLLO_NR_CLK, + .clk_regs = apollo_clk_regs, + .nr_clk_regs = ARRAY_SIZE(apollo_clk_regs), +}; + static void __init exynos5433_cmu_apollo_init(struct device_node *np) { - void __iomem *reg_base; - struct samsung_clk_provider *ctx; - struct clk_hw **hws; - - reg_base = of_iomap(np, 0); - if (!reg_base) { - panic("%s: failed to map registers\n", __func__); - return; - } - - ctx = samsung_clk_init(np, reg_base, APOLLO_NR_CLK); - if (!ctx) { - panic("%s: unable to allocate ctx\n", __func__); - return; - } - - samsung_clk_register_pll(ctx, apollo_pll_clks, - ARRAY_SIZE(apollo_pll_clks), reg_base); - samsung_clk_register_mux(ctx, apollo_mux_clks, - ARRAY_SIZE(apollo_mux_clks)); - samsung_clk_register_div(ctx, apollo_div_clks, - ARRAY_SIZE(apollo_div_clks)); - samsung_clk_register_gate(ctx, apollo_gate_clks, - ARRAY_SIZE(apollo_gate_clks)); - - hws = ctx->clk_data.hws; - - exynos_register_cpu_clock(ctx, CLK_SCLK_APOLLO, "apolloclk", - hws[CLK_MOUT_APOLLO_PLL], hws[CLK_MOUT_BUS_PLL_APOLLO_USER], 0x200, - exynos5433_apolloclk_d, ARRAY_SIZE(exynos5433_apolloclk_d), - CLK_CPU_HAS_E5433_REGS_LAYOUT); - - samsung_clk_sleep_init(reg_base, apollo_clk_regs, - ARRAY_SIZE(apollo_clk_regs)); - - samsung_clk_of_add_provider(np, ctx); + samsung_cmu_register_one(np, &apollo_cmu_info); } CLK_OF_DECLARE(exynos5433_cmu_apollo, "samsung,exynos5433-cmu-apollo", exynos5433_cmu_apollo_init); @@ -3932,44 +3920,32 @@ static const struct exynos_cpuclk_cfg_data exynos5433_atlasclk_d[] __initconst = { 0 }, }; -static void __init exynos5433_cmu_atlas_init(struct device_node *np) -{ - void __iomem *reg_base; - struct samsung_clk_provider *ctx; - struct clk_hw **hws; - - reg_base = of_iomap(np, 0); - if (!reg_base) { - panic("%s: failed to map registers\n", __func__); - return; - } - - ctx = samsung_clk_init(np, reg_base, ATLAS_NR_CLK); - if (!ctx) { - panic("%s: unable to allocate ctx\n", __func__); - return; - } - - samsung_clk_register_pll(ctx, atlas_pll_clks, - ARRAY_SIZE(atlas_pll_clks), reg_base); - samsung_clk_register_mux(ctx, atlas_mux_clks, - ARRAY_SIZE(atlas_mux_clks)); - samsung_clk_register_div(ctx, atlas_div_clks, - ARRAY_SIZE(atlas_div_clks)); - samsung_clk_register_gate(ctx, atlas_gate_clks, - ARRAY_SIZE(atlas_gate_clks)); - - hws = ctx->clk_data.hws; - - exynos_register_cpu_clock(ctx, CLK_SCLK_ATLAS, "atlasclk", - hws[CLK_MOUT_ATLAS_PLL], hws[CLK_MOUT_BUS_PLL_ATLAS_USER], 0x200, - exynos5433_atlasclk_d, ARRAY_SIZE(exynos5433_atlasclk_d), - CLK_CPU_HAS_E5433_REGS_LAYOUT); +static const struct samsung_cpu_clock atlas_cpu_clks[] __initconst = { + CPU_CLK(CLK_SCLK_ATLAS, "atlasclk", CLK_MOUT_ATLAS_PLL, + CLK_MOUT_BUS_PLL_ATLAS_USER, + CLK_CPU_HAS_E5433_REGS_LAYOUT, 0x200, + exynos5433_atlasclk_d), +}; - samsung_clk_sleep_init(reg_base, atlas_clk_regs, - ARRAY_SIZE(atlas_clk_regs)); +static const struct samsung_cmu_info atlas_cmu_info __initconst = { + .pll_clks = atlas_pll_clks, + .nr_pll_clks = ARRAY_SIZE(atlas_pll_clks), + .mux_clks = atlas_mux_clks, + .nr_mux_clks = ARRAY_SIZE(atlas_mux_clks), + .div_clks = atlas_div_clks, + .nr_div_clks = ARRAY_SIZE(atlas_div_clks), + .gate_clks = atlas_gate_clks, + .nr_gate_clks = ARRAY_SIZE(atlas_gate_clks), + .cpu_clks = atlas_cpu_clks, + .nr_cpu_clks = ARRAY_SIZE(atlas_cpu_clks), + .nr_clk_ids = ATLAS_NR_CLK, + .clk_regs = atlas_clk_regs, + .nr_clk_regs = ARRAY_SIZE(atlas_clk_regs), +}; - samsung_clk_of_add_provider(np, ctx); +static void __init exynos5433_cmu_atlas_init(struct device_node *np) +{ + samsung_cmu_register_one(np, &atlas_cmu_info); } CLK_OF_DECLARE(exynos5433_cmu_atlas, "samsung,exynos5433-cmu-atlas", exynos5433_cmu_atlas_init); @@ -5564,7 +5540,6 @@ static int __init exynos5433_cmu_probe(struct platform_device *pdev) struct exynos5433_cmu_data *data; struct samsung_clk_provider *ctx; struct device *dev = &pdev->dev; - struct resource *res; void __iomem *reg_base; int i; @@ -5577,8 +5552,7 @@ static int __init exynos5433_cmu_probe(struct platform_device *pdev) return -ENOMEM; ctx = &data->ctx; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - reg_base = devm_ioremap_resource(dev, res); + reg_base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(reg_base)) return PTR_ERR(reg_base); diff --git a/drivers/clk/samsung/clk-exynos850.c b/drivers/clk/samsung/clk-exynos850.c new file mode 100644 index 000000000000..2294989e244c --- /dev/null +++ b/drivers/clk/samsung/clk-exynos850.c @@ -0,0 +1,835 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (C) 2021 Linaro Ltd. + * Author: Sam Protsenko <semen.protsenko@linaro.org> + * + * Common Clock Framework support for Exynos850 SoC. + */ + +#include <linux/clk.h> +#include <linux/clk-provider.h> +#include <linux/of.h> +#include <linux/of_address.h> +#include <linux/of_device.h> +#include <linux/platform_device.h> + +#include <dt-bindings/clock/exynos850.h> + +#include "clk.h" + +/* Gate register bits */ +#define GATE_MANUAL BIT(20) +#define GATE_ENABLE_HWACG BIT(28) + +/* Gate register offsets range */ +#define GATE_OFF_START 0x2000 +#define GATE_OFF_END 0x2fff + +/** + * exynos850_init_clocks - Set clocks initial configuration + * @np: CMU device tree node with "reg" property (CMU addr) + * @reg_offs: Register offsets array for clocks to init + * @reg_offs_len: Number of register offsets in reg_offs array + * + * Set manual control mode for all gate clocks. + */ +static void __init exynos850_init_clocks(struct device_node *np, + const unsigned long *reg_offs, size_t reg_offs_len) +{ + void __iomem *reg_base; + size_t i; + + reg_base = of_iomap(np, 0); + if (!reg_base) + panic("%s: failed to map registers\n", __func__); + + for (i = 0; i < reg_offs_len; ++i) { + void __iomem *reg = reg_base + reg_offs[i]; + u32 val; + + /* Modify only gate clock registers */ + if (reg_offs[i] < GATE_OFF_START || reg_offs[i] > GATE_OFF_END) + continue; + + val = readl(reg); + val |= GATE_MANUAL; + val &= ~GATE_ENABLE_HWACG; + writel(val, reg); + } + + iounmap(reg_base); +} + +/* ---- CMU_TOP ------------------------------------------------------------- */ + +/* Register Offset definitions for CMU_TOP (0x120e0000) */ +#define PLL_LOCKTIME_PLL_MMC 0x0000 +#define PLL_LOCKTIME_PLL_SHARED0 0x0004 +#define PLL_LOCKTIME_PLL_SHARED1 0x0008 +#define PLL_CON0_PLL_MMC 0x0100 +#define PLL_CON3_PLL_MMC 0x010c +#define PLL_CON0_PLL_SHARED0 0x0140 +#define PLL_CON3_PLL_SHARED0 0x014c +#define PLL_CON0_PLL_SHARED1 0x0180 +#define PLL_CON3_PLL_SHARED1 0x018c +#define CLK_CON_MUX_MUX_CLKCMU_CORE_BUS 0x1014 +#define CLK_CON_MUX_MUX_CLKCMU_CORE_CCI 0x1018 +#define CLK_CON_MUX_MUX_CLKCMU_CORE_MMC_EMBD 0x101c +#define CLK_CON_MUX_MUX_CLKCMU_CORE_SSS 0x1020 +#define CLK_CON_MUX_MUX_CLKCMU_DPU 0x1034 +#define CLK_CON_MUX_MUX_CLKCMU_HSI_BUS 0x103c +#define CLK_CON_MUX_MUX_CLKCMU_HSI_MMC_CARD 0x1040 +#define CLK_CON_MUX_MUX_CLKCMU_HSI_USB20DRD 0x1044 +#define CLK_CON_MUX_MUX_CLKCMU_PERI_BUS 0x1070 +#define CLK_CON_MUX_MUX_CLKCMU_PERI_IP 0x1074 +#define CLK_CON_MUX_MUX_CLKCMU_PERI_UART 0x1078 +#define CLK_CON_DIV_CLKCMU_CORE_BUS 0x1820 +#define CLK_CON_DIV_CLKCMU_CORE_CCI 0x1824 +#define CLK_CON_DIV_CLKCMU_CORE_MMC_EMBD 0x1828 +#define CLK_CON_DIV_CLKCMU_CORE_SSS 0x182c +#define CLK_CON_DIV_CLKCMU_DPU 0x1840 +#define CLK_CON_DIV_CLKCMU_HSI_BUS 0x1848 +#define CLK_CON_DIV_CLKCMU_HSI_MMC_CARD 0x184c +#define CLK_CON_DIV_CLKCMU_HSI_USB20DRD 0x1850 +#define CLK_CON_DIV_CLKCMU_PERI_BUS 0x187c +#define CLK_CON_DIV_CLKCMU_PERI_IP 0x1880 +#define CLK_CON_DIV_CLKCMU_PERI_UART 0x1884 +#define CLK_CON_DIV_PLL_SHARED0_DIV2 0x188c +#define CLK_CON_DIV_PLL_SHARED0_DIV3 0x1890 +#define CLK_CON_DIV_PLL_SHARED0_DIV4 0x1894 +#define CLK_CON_DIV_PLL_SHARED1_DIV2 0x1898 +#define CLK_CON_DIV_PLL_SHARED1_DIV3 0x189c +#define CLK_CON_DIV_PLL_SHARED1_DIV4 0x18a0 +#define CLK_CON_GAT_GATE_CLKCMU_CORE_BUS 0x201c +#define CLK_CON_GAT_GATE_CLKCMU_CORE_CCI 0x2020 +#define CLK_CON_GAT_GATE_CLKCMU_CORE_MMC_EMBD 0x2024 +#define CLK_CON_GAT_GATE_CLKCMU_CORE_SSS 0x2028 +#define CLK_CON_GAT_GATE_CLKCMU_DPU 0x203c +#define CLK_CON_GAT_GATE_CLKCMU_HSI_BUS 0x2044 +#define CLK_CON_GAT_GATE_CLKCMU_HSI_MMC_CARD 0x2048 +#define CLK_CON_GAT_GATE_CLKCMU_HSI_USB20DRD 0x204c +#define CLK_CON_GAT_GATE_CLKCMU_PERI_BUS 0x2080 +#define CLK_CON_GAT_GATE_CLKCMU_PERI_IP 0x2084 +#define CLK_CON_GAT_GATE_CLKCMU_PERI_UART 0x2088 + +static const unsigned long top_clk_regs[] __initconst = { + PLL_LOCKTIME_PLL_MMC, + PLL_LOCKTIME_PLL_SHARED0, + PLL_LOCKTIME_PLL_SHARED1, + PLL_CON0_PLL_MMC, + PLL_CON3_PLL_MMC, + PLL_CON0_PLL_SHARED0, + PLL_CON3_PLL_SHARED0, + PLL_CON0_PLL_SHARED1, + PLL_CON3_PLL_SHARED1, + CLK_CON_MUX_MUX_CLKCMU_CORE_BUS, + CLK_CON_MUX_MUX_CLKCMU_CORE_CCI, + CLK_CON_MUX_MUX_CLKCMU_CORE_MMC_EMBD, + CLK_CON_MUX_MUX_CLKCMU_CORE_SSS, + CLK_CON_MUX_MUX_CLKCMU_DPU, + CLK_CON_MUX_MUX_CLKCMU_HSI_BUS, + CLK_CON_MUX_MUX_CLKCMU_HSI_MMC_CARD, + CLK_CON_MUX_MUX_CLKCMU_HSI_USB20DRD, + CLK_CON_MUX_MUX_CLKCMU_PERI_BUS, + CLK_CON_MUX_MUX_CLKCMU_PERI_IP, + CLK_CON_MUX_MUX_CLKCMU_PERI_UART, + CLK_CON_DIV_CLKCMU_CORE_BUS, + CLK_CON_DIV_CLKCMU_CORE_CCI, + CLK_CON_DIV_CLKCMU_CORE_MMC_EMBD, + CLK_CON_DIV_CLKCMU_CORE_SSS, + CLK_CON_DIV_CLKCMU_DPU, + CLK_CON_DIV_CLKCMU_HSI_BUS, + CLK_CON_DIV_CLKCMU_HSI_MMC_CARD, + CLK_CON_DIV_CLKCMU_HSI_USB20DRD, + CLK_CON_DIV_CLKCMU_PERI_BUS, + CLK_CON_DIV_CLKCMU_PERI_IP, + CLK_CON_DIV_CLKCMU_PERI_UART, + CLK_CON_DIV_PLL_SHARED0_DIV2, + CLK_CON_DIV_PLL_SHARED0_DIV3, + CLK_CON_DIV_PLL_SHARED0_DIV4, + CLK_CON_DIV_PLL_SHARED1_DIV2, + CLK_CON_DIV_PLL_SHARED1_DIV3, + CLK_CON_DIV_PLL_SHARED1_DIV4, + CLK_CON_GAT_GATE_CLKCMU_CORE_BUS, + CLK_CON_GAT_GATE_CLKCMU_CORE_CCI, + CLK_CON_GAT_GATE_CLKCMU_CORE_MMC_EMBD, + CLK_CON_GAT_GATE_CLKCMU_CORE_SSS, + CLK_CON_GAT_GATE_CLKCMU_DPU, + CLK_CON_GAT_GATE_CLKCMU_HSI_BUS, + CLK_CON_GAT_GATE_CLKCMU_HSI_MMC_CARD, + CLK_CON_GAT_GATE_CLKCMU_HSI_USB20DRD, + CLK_CON_GAT_GATE_CLKCMU_PERI_BUS, + CLK_CON_GAT_GATE_CLKCMU_PERI_IP, + CLK_CON_GAT_GATE_CLKCMU_PERI_UART, +}; + +/* + * Do not provide PLL tables to core PLLs, as MANUAL_PLL_CTRL bit is not set + * for those PLLs by default, so set_rate operation would fail. + */ +static const struct samsung_pll_clock top_pll_clks[] __initconst = { + /* CMU_TOP_PURECLKCOMP */ + PLL(pll_0822x, CLK_FOUT_SHARED0_PLL, "fout_shared0_pll", "oscclk", + PLL_LOCKTIME_PLL_SHARED0, PLL_CON3_PLL_SHARED0, + NULL), + PLL(pll_0822x, CLK_FOUT_SHARED1_PLL, "fout_shared1_pll", "oscclk", + PLL_LOCKTIME_PLL_SHARED1, PLL_CON3_PLL_SHARED1, + NULL), + PLL(pll_0831x, CLK_FOUT_MMC_PLL, "fout_mmc_pll", "oscclk", + PLL_LOCKTIME_PLL_MMC, PLL_CON3_PLL_MMC, NULL), +}; + +/* List of parent clocks for Muxes in CMU_TOP */ +PNAME(mout_shared0_pll_p) = { "oscclk", "fout_shared0_pll" }; +PNAME(mout_shared1_pll_p) = { "oscclk", "fout_shared1_pll" }; +PNAME(mout_mmc_pll_p) = { "oscclk", "fout_mmc_pll" }; +/* List of parent clocks for Muxes in CMU_TOP: for CMU_CORE */ +PNAME(mout_core_bus_p) = { "dout_shared1_div2", "dout_shared0_div3", + "dout_shared1_div3", "dout_shared0_div4" }; +PNAME(mout_core_cci_p) = { "dout_shared0_div2", "dout_shared1_div2", + "dout_shared0_div3", "dout_shared1_div3" }; +PNAME(mout_core_mmc_embd_p) = { "oscclk", "dout_shared0_div2", + "dout_shared1_div2", "dout_shared0_div3", + "dout_shared1_div3", "mout_mmc_pll", + "oscclk", "oscclk" }; +PNAME(mout_core_sss_p) = { "dout_shared0_div3", "dout_shared1_div3", + "dout_shared0_div4", "dout_shared1_div4" }; +/* List of parent clocks for Muxes in CMU_TOP: for CMU_HSI */ +PNAME(mout_hsi_bus_p) = { "dout_shared0_div2", "dout_shared1_div2" }; +PNAME(mout_hsi_mmc_card_p) = { "oscclk", "dout_shared0_div2", + "dout_shared1_div2", "dout_shared0_div3", + "dout_shared1_div3", "mout_mmc_pll", + "oscclk", "oscclk" }; +PNAME(mout_hsi_usb20drd_p) = { "oscclk", "dout_shared0_div4", + "dout_shared1_div4", "oscclk" }; +/* List of parent clocks for Muxes in CMU_TOP: for CMU_PERI */ +PNAME(mout_peri_bus_p) = { "dout_shared0_div4", "dout_shared1_div4" }; +PNAME(mout_peri_uart_p) = { "oscclk", "dout_shared0_div4", + "dout_shared1_div4", "oscclk" }; +PNAME(mout_peri_ip_p) = { "oscclk", "dout_shared0_div4", + "dout_shared1_div4", "oscclk" }; + +/* List of parent clocks for Muxes in CMU_TOP: for CMU_DPU */ +PNAME(mout_dpu_p) = { "dout_shared0_div3", "dout_shared1_div3", + "dout_shared0_div4", "dout_shared1_div4" }; + +static const struct samsung_mux_clock top_mux_clks[] __initconst = { + /* CMU_TOP_PURECLKCOMP */ + MUX(CLK_MOUT_SHARED0_PLL, "mout_shared0_pll", mout_shared0_pll_p, + PLL_CON0_PLL_SHARED0, 4, 1), + MUX(CLK_MOUT_SHARED1_PLL, "mout_shared1_pll", mout_shared1_pll_p, + PLL_CON0_PLL_SHARED1, 4, 1), + MUX(CLK_MOUT_MMC_PLL, "mout_mmc_pll", mout_mmc_pll_p, + PLL_CON0_PLL_MMC, 4, 1), + + /* CORE */ + MUX(CLK_MOUT_CORE_BUS, "mout_core_bus", mout_core_bus_p, + CLK_CON_MUX_MUX_CLKCMU_CORE_BUS, 0, 2), + MUX(CLK_MOUT_CORE_CCI, "mout_core_cci", mout_core_cci_p, + CLK_CON_MUX_MUX_CLKCMU_CORE_CCI, 0, 2), + MUX(CLK_MOUT_CORE_MMC_EMBD, "mout_core_mmc_embd", mout_core_mmc_embd_p, + CLK_CON_MUX_MUX_CLKCMU_CORE_MMC_EMBD, 0, 3), + MUX(CLK_MOUT_CORE_SSS, "mout_core_sss", mout_core_sss_p, + CLK_CON_MUX_MUX_CLKCMU_CORE_SSS, 0, 2), + + /* DPU */ + MUX(CLK_MOUT_DPU, "mout_dpu", mout_dpu_p, + CLK_CON_MUX_MUX_CLKCMU_DPU, 0, 2), + + /* HSI */ + MUX(CLK_MOUT_HSI_BUS, "mout_hsi_bus", mout_hsi_bus_p, + CLK_CON_MUX_MUX_CLKCMU_HSI_BUS, 0, 1), + MUX(CLK_MOUT_HSI_MMC_CARD, "mout_hsi_mmc_card", mout_hsi_mmc_card_p, + CLK_CON_MUX_MUX_CLKCMU_HSI_MMC_CARD, 0, 3), + MUX(CLK_MOUT_HSI_USB20DRD, "mout_hsi_usb20drd", mout_hsi_usb20drd_p, + CLK_CON_MUX_MUX_CLKCMU_HSI_USB20DRD, 0, 2), + + /* PERI */ + MUX(CLK_MOUT_PERI_BUS, "mout_peri_bus", mout_peri_bus_p, + CLK_CON_MUX_MUX_CLKCMU_PERI_BUS, 0, 1), + MUX(CLK_MOUT_PERI_UART, "mout_peri_uart", mout_peri_uart_p, + CLK_CON_MUX_MUX_CLKCMU_PERI_UART, 0, 2), + MUX(CLK_MOUT_PERI_IP, "mout_peri_ip", mout_peri_ip_p, + CLK_CON_MUX_MUX_CLKCMU_PERI_IP, 0, 2), +}; + +static const struct samsung_div_clock top_div_clks[] __initconst = { + /* CMU_TOP_PURECLKCOMP */ + DIV(CLK_DOUT_SHARED0_DIV3, "dout_shared0_div3", "mout_shared0_pll", + CLK_CON_DIV_PLL_SHARED0_DIV3, 0, 2), + DIV(CLK_DOUT_SHARED0_DIV2, "dout_shared0_div2", "mout_shared0_pll", + CLK_CON_DIV_PLL_SHARED0_DIV2, 0, 1), + DIV(CLK_DOUT_SHARED1_DIV3, "dout_shared1_div3", "mout_shared1_pll", + CLK_CON_DIV_PLL_SHARED1_DIV3, 0, 2), + DIV(CLK_DOUT_SHARED1_DIV2, "dout_shared1_div2", "mout_shared1_pll", + CLK_CON_DIV_PLL_SHARED1_DIV2, 0, 1), + DIV(CLK_DOUT_SHARED0_DIV4, "dout_shared0_div4", "dout_shared0_div2", + CLK_CON_DIV_PLL_SHARED0_DIV4, 0, 1), + DIV(CLK_DOUT_SHARED1_DIV4, "dout_shared1_div4", "dout_shared1_div2", + CLK_CON_DIV_PLL_SHARED1_DIV4, 0, 1), + + /* CORE */ + DIV(CLK_DOUT_CORE_BUS, "dout_core_bus", "gout_core_bus", + CLK_CON_DIV_CLKCMU_CORE_BUS, 0, 4), + DIV(CLK_DOUT_CORE_CCI, "dout_core_cci", "gout_core_cci", + CLK_CON_DIV_CLKCMU_CORE_CCI, 0, 4), + DIV(CLK_DOUT_CORE_MMC_EMBD, "dout_core_mmc_embd", "gout_core_mmc_embd", + CLK_CON_DIV_CLKCMU_CORE_MMC_EMBD, 0, 9), + DIV(CLK_DOUT_CORE_SSS, "dout_core_sss", "gout_core_sss", + CLK_CON_DIV_CLKCMU_CORE_SSS, 0, 4), + + /* DPU */ + DIV(CLK_DOUT_DPU, "dout_dpu", "gout_dpu", + CLK_CON_DIV_CLKCMU_DPU, 0, 4), + + /* HSI */ + DIV(CLK_DOUT_HSI_BUS, "dout_hsi_bus", "gout_hsi_bus", + CLK_CON_DIV_CLKCMU_HSI_BUS, 0, 4), + DIV(CLK_DOUT_HSI_MMC_CARD, "dout_hsi_mmc_card", "gout_hsi_mmc_card", + CLK_CON_DIV_CLKCMU_HSI_MMC_CARD, 0, 9), + DIV(CLK_DOUT_HSI_USB20DRD, "dout_hsi_usb20drd", "gout_hsi_usb20drd", + CLK_CON_DIV_CLKCMU_HSI_USB20DRD, 0, 4), + + /* PERI */ + DIV(CLK_DOUT_PERI_BUS, "dout_peri_bus", "gout_peri_bus", + CLK_CON_DIV_CLKCMU_PERI_BUS, 0, 4), + DIV(CLK_DOUT_PERI_UART, "dout_peri_uart", "gout_peri_uart", + CLK_CON_DIV_CLKCMU_PERI_UART, 0, 4), + DIV(CLK_DOUT_PERI_IP, "dout_peri_ip", "gout_peri_ip", + CLK_CON_DIV_CLKCMU_PERI_IP, 0, 4), +}; + +static const struct samsung_gate_clock top_gate_clks[] __initconst = { + /* CORE */ + GATE(CLK_GOUT_CORE_BUS, "gout_core_bus", "mout_core_bus", + CLK_CON_GAT_GATE_CLKCMU_CORE_BUS, 21, 0, 0), + GATE(CLK_GOUT_CORE_CCI, "gout_core_cci", "mout_core_cci", + CLK_CON_GAT_GATE_CLKCMU_CORE_CCI, 21, 0, 0), + GATE(CLK_GOUT_CORE_MMC_EMBD, "gout_core_mmc_embd", "mout_core_mmc_embd", + CLK_CON_GAT_GATE_CLKCMU_CORE_MMC_EMBD, 21, 0, 0), + GATE(CLK_GOUT_CORE_SSS, "gout_core_sss", "mout_core_sss", + CLK_CON_GAT_GATE_CLKCMU_CORE_SSS, 21, 0, 0), + + /* DPU */ + GATE(CLK_GOUT_DPU, "gout_dpu", "mout_dpu", + CLK_CON_GAT_GATE_CLKCMU_DPU, 21, 0, 0), + + /* HSI */ + GATE(CLK_GOUT_HSI_BUS, "gout_hsi_bus", "mout_hsi_bus", + CLK_CON_GAT_GATE_CLKCMU_HSI_BUS, 21, 0, 0), + GATE(CLK_GOUT_HSI_MMC_CARD, "gout_hsi_mmc_card", "mout_hsi_mmc_card", + CLK_CON_GAT_GATE_CLKCMU_HSI_MMC_CARD, 21, 0, 0), + GATE(CLK_GOUT_HSI_USB20DRD, "gout_hsi_usb20drd", "mout_hsi_usb20drd", + CLK_CON_GAT_GATE_CLKCMU_HSI_USB20DRD, 21, 0, 0), + + /* PERI */ + GATE(CLK_GOUT_PERI_BUS, "gout_peri_bus", "mout_peri_bus", + CLK_CON_GAT_GATE_CLKCMU_PERI_BUS, 21, 0, 0), + GATE(CLK_GOUT_PERI_UART, "gout_peri_uart", "mout_peri_uart", + CLK_CON_GAT_GATE_CLKCMU_PERI_UART, 21, 0, 0), + GATE(CLK_GOUT_PERI_IP, "gout_peri_ip", "mout_peri_ip", + CLK_CON_GAT_GATE_CLKCMU_PERI_IP, 21, 0, 0), +}; + +static const struct samsung_cmu_info top_cmu_info __initconst = { + .pll_clks = top_pll_clks, + .nr_pll_clks = ARRAY_SIZE(top_pll_clks), + .mux_clks = top_mux_clks, + .nr_mux_clks = ARRAY_SIZE(top_mux_clks), + .div_clks = top_div_clks, + .nr_div_clks = ARRAY_SIZE(top_div_clks), + .gate_clks = top_gate_clks, + .nr_gate_clks = ARRAY_SIZE(top_gate_clks), + .nr_clk_ids = TOP_NR_CLK, + .clk_regs = top_clk_regs, + .nr_clk_regs = ARRAY_SIZE(top_clk_regs), +}; + +static void __init exynos850_cmu_top_init(struct device_node *np) +{ + exynos850_init_clocks(np, top_clk_regs, ARRAY_SIZE(top_clk_regs)); + samsung_cmu_register_one(np, &top_cmu_info); +} + +CLK_OF_DECLARE(exynos850_cmu_top, "samsung,exynos850-cmu-top", + exynos850_cmu_top_init); + +/* ---- CMU_HSI ------------------------------------------------------------- */ + +/* Register Offset definitions for CMU_HSI (0x13400000) */ +#define PLL_CON0_MUX_CLKCMU_HSI_BUS_USER 0x0600 +#define PLL_CON0_MUX_CLKCMU_HSI_MMC_CARD_USER 0x0610 +#define PLL_CON0_MUX_CLKCMU_HSI_USB20DRD_USER 0x0620 +#define CLK_CON_MUX_MUX_CLK_HSI_RTC 0x1000 +#define CLK_CON_GAT_HSI_USB20DRD_TOP_I_RTC_CLK__ALV 0x2008 +#define CLK_CON_GAT_HSI_USB20DRD_TOP_I_REF_CLK_50 0x200c +#define CLK_CON_GAT_HSI_USB20DRD_TOP_I_PHY_REFCLK_26 0x2010 +#define CLK_CON_GAT_GOUT_HSI_GPIO_HSI_PCLK 0x2018 +#define CLK_CON_GAT_GOUT_HSI_MMC_CARD_I_ACLK 0x2024 +#define CLK_CON_GAT_GOUT_HSI_MMC_CARD_SDCLKIN 0x2028 +#define CLK_CON_GAT_GOUT_HSI_SYSREG_HSI_PCLK 0x2038 +#define CLK_CON_GAT_GOUT_HSI_USB20DRD_TOP_ACLK_PHYCTRL_20 0x203c +#define CLK_CON_GAT_GOUT_HSI_USB20DRD_TOP_BUS_CLK_EARLY 0x2040 + +static const unsigned long hsi_clk_regs[] __initconst = { + PLL_CON0_MUX_CLKCMU_HSI_BUS_USER, + PLL_CON0_MUX_CLKCMU_HSI_MMC_CARD_USER, + PLL_CON0_MUX_CLKCMU_HSI_USB20DRD_USER, + CLK_CON_MUX_MUX_CLK_HSI_RTC, + CLK_CON_GAT_HSI_USB20DRD_TOP_I_RTC_CLK__ALV, + CLK_CON_GAT_HSI_USB20DRD_TOP_I_REF_CLK_50, + CLK_CON_GAT_HSI_USB20DRD_TOP_I_PHY_REFCLK_26, + CLK_CON_GAT_GOUT_HSI_GPIO_HSI_PCLK, + CLK_CON_GAT_GOUT_HSI_MMC_CARD_I_ACLK, + CLK_CON_GAT_GOUT_HSI_MMC_CARD_SDCLKIN, + CLK_CON_GAT_GOUT_HSI_SYSREG_HSI_PCLK, + CLK_CON_GAT_GOUT_HSI_USB20DRD_TOP_ACLK_PHYCTRL_20, + CLK_CON_GAT_GOUT_HSI_USB20DRD_TOP_BUS_CLK_EARLY, +}; + +/* List of parent clocks for Muxes in CMU_PERI */ +PNAME(mout_hsi_bus_user_p) = { "oscclk", "dout_hsi_bus" }; +PNAME(mout_hsi_mmc_card_user_p) = { "oscclk", "dout_hsi_mmc_card" }; +PNAME(mout_hsi_usb20drd_user_p) = { "oscclk", "dout_hsi_usb20drd" }; +PNAME(mout_hsi_rtc_p) = { "rtcclk", "oscclk" }; + +static const struct samsung_mux_clock hsi_mux_clks[] __initconst = { + MUX(CLK_MOUT_HSI_BUS_USER, "mout_hsi_bus_user", mout_hsi_bus_user_p, + PLL_CON0_MUX_CLKCMU_HSI_BUS_USER, 4, 1), + MUX_F(CLK_MOUT_HSI_MMC_CARD_USER, "mout_hsi_mmc_card_user", + mout_hsi_mmc_card_user_p, PLL_CON0_MUX_CLKCMU_HSI_MMC_CARD_USER, + 4, 1, CLK_SET_RATE_PARENT, 0), + MUX(CLK_MOUT_HSI_USB20DRD_USER, "mout_hsi_usb20drd_user", + mout_hsi_usb20drd_user_p, PLL_CON0_MUX_CLKCMU_HSI_USB20DRD_USER, + 4, 1), + MUX(CLK_MOUT_HSI_RTC, "mout_hsi_rtc", mout_hsi_rtc_p, + CLK_CON_MUX_MUX_CLK_HSI_RTC, 0, 1), +}; + +static const struct samsung_gate_clock hsi_gate_clks[] __initconst = { + GATE(CLK_GOUT_USB_RTC_CLK, "gout_usb_rtc", "mout_hsi_rtc", + CLK_CON_GAT_HSI_USB20DRD_TOP_I_RTC_CLK__ALV, 21, 0, 0), + GATE(CLK_GOUT_USB_REF_CLK, "gout_usb_ref", "mout_hsi_usb20drd_user", + CLK_CON_GAT_HSI_USB20DRD_TOP_I_REF_CLK_50, 21, 0, 0), + GATE(CLK_GOUT_USB_PHY_REF_CLK, "gout_usb_phy_ref", "oscclk", + CLK_CON_GAT_HSI_USB20DRD_TOP_I_PHY_REFCLK_26, 21, 0, 0), + GATE(CLK_GOUT_GPIO_HSI_PCLK, "gout_gpio_hsi_pclk", "mout_hsi_bus_user", + CLK_CON_GAT_GOUT_HSI_GPIO_HSI_PCLK, 21, 0, 0), + GATE(CLK_GOUT_MMC_CARD_ACLK, "gout_mmc_card_aclk", "mout_hsi_bus_user", + CLK_CON_GAT_GOUT_HSI_MMC_CARD_I_ACLK, 21, 0, 0), + GATE(CLK_GOUT_MMC_CARD_SDCLKIN, "gout_mmc_card_sdclkin", + "mout_hsi_mmc_card_user", + CLK_CON_GAT_GOUT_HSI_MMC_CARD_SDCLKIN, 21, CLK_SET_RATE_PARENT, 0), + GATE(CLK_GOUT_SYSREG_HSI_PCLK, "gout_sysreg_hsi_pclk", + "mout_hsi_bus_user", + CLK_CON_GAT_GOUT_HSI_SYSREG_HSI_PCLK, 21, 0, 0), + GATE(CLK_GOUT_USB_PHY_ACLK, "gout_usb_phy_aclk", "mout_hsi_bus_user", + CLK_CON_GAT_GOUT_HSI_USB20DRD_TOP_ACLK_PHYCTRL_20, 21, 0, 0), + GATE(CLK_GOUT_USB_BUS_EARLY_CLK, "gout_usb_bus_early", + "mout_hsi_bus_user", + CLK_CON_GAT_GOUT_HSI_USB20DRD_TOP_BUS_CLK_EARLY, 21, 0, 0), +}; + +static const struct samsung_cmu_info hsi_cmu_info __initconst = { + .mux_clks = hsi_mux_clks, + .nr_mux_clks = ARRAY_SIZE(hsi_mux_clks), + .gate_clks = hsi_gate_clks, + .nr_gate_clks = ARRAY_SIZE(hsi_gate_clks), + .nr_clk_ids = HSI_NR_CLK, + .clk_regs = hsi_clk_regs, + .nr_clk_regs = ARRAY_SIZE(hsi_clk_regs), + .clk_name = "dout_hsi_bus", +}; + +/* ---- CMU_PERI ------------------------------------------------------------ */ + +/* Register Offset definitions for CMU_PERI (0x10030000) */ +#define PLL_CON0_MUX_CLKCMU_PERI_BUS_USER 0x0600 +#define PLL_CON0_MUX_CLKCMU_PERI_HSI2C_USER 0x0610 +#define PLL_CON0_MUX_CLKCMU_PERI_SPI_USER 0x0620 +#define PLL_CON0_MUX_CLKCMU_PERI_UART_USER 0x0630 +#define CLK_CON_DIV_DIV_CLK_PERI_HSI2C_0 0x1800 +#define CLK_CON_DIV_DIV_CLK_PERI_HSI2C_1 0x1804 +#define CLK_CON_DIV_DIV_CLK_PERI_HSI2C_2 0x1808 +#define CLK_CON_DIV_DIV_CLK_PERI_SPI_0 0x180c +#define CLK_CON_GAT_GATE_CLK_PERI_HSI2C_0 0x200c +#define CLK_CON_GAT_GATE_CLK_PERI_HSI2C_1 0x2010 +#define CLK_CON_GAT_GATE_CLK_PERI_HSI2C_2 0x2014 +#define CLK_CON_GAT_GOUT_PERI_GPIO_PERI_PCLK 0x2020 +#define CLK_CON_GAT_GOUT_PERI_HSI2C_0_IPCLK 0x2024 +#define CLK_CON_GAT_GOUT_PERI_HSI2C_0_PCLK 0x2028 +#define CLK_CON_GAT_GOUT_PERI_HSI2C_1_IPCLK 0x202c +#define CLK_CON_GAT_GOUT_PERI_HSI2C_1_PCLK 0x2030 +#define CLK_CON_GAT_GOUT_PERI_HSI2C_2_IPCLK 0x2034 +#define CLK_CON_GAT_GOUT_PERI_HSI2C_2_PCLK 0x2038 +#define CLK_CON_GAT_GOUT_PERI_I2C_0_PCLK 0x203c +#define CLK_CON_GAT_GOUT_PERI_I2C_1_PCLK 0x2040 +#define CLK_CON_GAT_GOUT_PERI_I2C_2_PCLK 0x2044 +#define CLK_CON_GAT_GOUT_PERI_I2C_3_PCLK 0x2048 +#define CLK_CON_GAT_GOUT_PERI_I2C_4_PCLK 0x204c +#define CLK_CON_GAT_GOUT_PERI_I2C_5_PCLK 0x2050 +#define CLK_CON_GAT_GOUT_PERI_I2C_6_PCLK 0x2054 +#define CLK_CON_GAT_GOUT_PERI_MCT_PCLK 0x205c +#define CLK_CON_GAT_GOUT_PERI_PWM_MOTOR_PCLK 0x2064 +#define CLK_CON_GAT_GOUT_PERI_SPI_0_IPCLK 0x209c +#define CLK_CON_GAT_GOUT_PERI_SPI_0_PCLK 0x20a0 +#define CLK_CON_GAT_GOUT_PERI_SYSREG_PERI_PCLK 0x20a4 +#define CLK_CON_GAT_GOUT_PERI_UART_IPCLK 0x20a8 +#define CLK_CON_GAT_GOUT_PERI_UART_PCLK 0x20ac +#define CLK_CON_GAT_GOUT_PERI_WDT_0_PCLK 0x20b0 +#define CLK_CON_GAT_GOUT_PERI_WDT_1_PCLK 0x20b4 + +static const unsigned long peri_clk_regs[] __initconst = { + PLL_CON0_MUX_CLKCMU_PERI_BUS_USER, + PLL_CON0_MUX_CLKCMU_PERI_HSI2C_USER, + PLL_CON0_MUX_CLKCMU_PERI_SPI_USER, + PLL_CON0_MUX_CLKCMU_PERI_UART_USER, + CLK_CON_DIV_DIV_CLK_PERI_HSI2C_0, + CLK_CON_DIV_DIV_CLK_PERI_HSI2C_1, + CLK_CON_DIV_DIV_CLK_PERI_HSI2C_2, + CLK_CON_DIV_DIV_CLK_PERI_SPI_0, + CLK_CON_GAT_GATE_CLK_PERI_HSI2C_0, + CLK_CON_GAT_GATE_CLK_PERI_HSI2C_1, + CLK_CON_GAT_GATE_CLK_PERI_HSI2C_2, + CLK_CON_GAT_GOUT_PERI_GPIO_PERI_PCLK, + CLK_CON_GAT_GOUT_PERI_HSI2C_0_IPCLK, + CLK_CON_GAT_GOUT_PERI_HSI2C_0_PCLK, + CLK_CON_GAT_GOUT_PERI_HSI2C_1_IPCLK, + CLK_CON_GAT_GOUT_PERI_HSI2C_1_PCLK, + CLK_CON_GAT_GOUT_PERI_HSI2C_2_IPCLK, + CLK_CON_GAT_GOUT_PERI_HSI2C_2_PCLK, + CLK_CON_GAT_GOUT_PERI_I2C_0_PCLK, + CLK_CON_GAT_GOUT_PERI_I2C_1_PCLK, + CLK_CON_GAT_GOUT_PERI_I2C_2_PCLK, + CLK_CON_GAT_GOUT_PERI_I2C_3_PCLK, + CLK_CON_GAT_GOUT_PERI_I2C_4_PCLK, + CLK_CON_GAT_GOUT_PERI_I2C_5_PCLK, + CLK_CON_GAT_GOUT_PERI_I2C_6_PCLK, + CLK_CON_GAT_GOUT_PERI_MCT_PCLK, + CLK_CON_GAT_GOUT_PERI_PWM_MOTOR_PCLK, + CLK_CON_GAT_GOUT_PERI_SPI_0_IPCLK, + CLK_CON_GAT_GOUT_PERI_SPI_0_PCLK, + CLK_CON_GAT_GOUT_PERI_SYSREG_PERI_PCLK, + CLK_CON_GAT_GOUT_PERI_UART_IPCLK, + CLK_CON_GAT_GOUT_PERI_UART_PCLK, + CLK_CON_GAT_GOUT_PERI_WDT_0_PCLK, + CLK_CON_GAT_GOUT_PERI_WDT_1_PCLK, +}; + +/* List of parent clocks for Muxes in CMU_PERI */ +PNAME(mout_peri_bus_user_p) = { "oscclk", "dout_peri_bus" }; +PNAME(mout_peri_uart_user_p) = { "oscclk", "dout_peri_uart" }; +PNAME(mout_peri_hsi2c_user_p) = { "oscclk", "dout_peri_ip" }; +PNAME(mout_peri_spi_user_p) = { "oscclk", "dout_peri_ip" }; + +static const struct samsung_mux_clock peri_mux_clks[] __initconst = { + MUX(CLK_MOUT_PERI_BUS_USER, "mout_peri_bus_user", mout_peri_bus_user_p, + PLL_CON0_MUX_CLKCMU_PERI_BUS_USER, 4, 1), + MUX(CLK_MOUT_PERI_UART_USER, "mout_peri_uart_user", + mout_peri_uart_user_p, PLL_CON0_MUX_CLKCMU_PERI_UART_USER, 4, 1), + MUX(CLK_MOUT_PERI_HSI2C_USER, "mout_peri_hsi2c_user", + mout_peri_hsi2c_user_p, PLL_CON0_MUX_CLKCMU_PERI_HSI2C_USER, 4, 1), + MUX(CLK_MOUT_PERI_SPI_USER, "mout_peri_spi_user", mout_peri_spi_user_p, + PLL_CON0_MUX_CLKCMU_PERI_SPI_USER, 4, 1), +}; + +static const struct samsung_div_clock peri_div_clks[] __initconst = { + DIV(CLK_DOUT_PERI_HSI2C0, "dout_peri_hsi2c0", "gout_peri_hsi2c0", + CLK_CON_DIV_DIV_CLK_PERI_HSI2C_0, 0, 5), + DIV(CLK_DOUT_PERI_HSI2C1, "dout_peri_hsi2c1", "gout_peri_hsi2c1", + CLK_CON_DIV_DIV_CLK_PERI_HSI2C_1, 0, 5), + DIV(CLK_DOUT_PERI_HSI2C2, "dout_peri_hsi2c2", "gout_peri_hsi2c2", + CLK_CON_DIV_DIV_CLK_PERI_HSI2C_2, 0, 5), + DIV(CLK_DOUT_PERI_SPI0, "dout_peri_spi0", "mout_peri_spi_user", + CLK_CON_DIV_DIV_CLK_PERI_SPI_0, 0, 5), +}; + +static const struct samsung_gate_clock peri_gate_clks[] __initconst = { + GATE(CLK_GOUT_PERI_HSI2C0, "gout_peri_hsi2c0", "mout_peri_hsi2c_user", + CLK_CON_GAT_GATE_CLK_PERI_HSI2C_0, 21, 0, 0), + GATE(CLK_GOUT_PERI_HSI2C1, "gout_peri_hsi2c1", "mout_peri_hsi2c_user", + CLK_CON_GAT_GATE_CLK_PERI_HSI2C_1, 21, 0, 0), + GATE(CLK_GOUT_PERI_HSI2C2, "gout_peri_hsi2c2", "mout_peri_hsi2c_user", + CLK_CON_GAT_GATE_CLK_PERI_HSI2C_2, 21, 0, 0), + GATE(CLK_GOUT_HSI2C0_IPCLK, "gout_hsi2c0_ipclk", "dout_peri_hsi2c0", + CLK_CON_GAT_GOUT_PERI_HSI2C_0_IPCLK, 21, 0, 0), + GATE(CLK_GOUT_HSI2C0_PCLK, "gout_hsi2c0_pclk", "mout_peri_bus_user", + CLK_CON_GAT_GOUT_PERI_HSI2C_0_PCLK, 21, 0, 0), + GATE(CLK_GOUT_HSI2C1_IPCLK, "gout_hsi2c1_ipclk", "dout_peri_hsi2c1", + CLK_CON_GAT_GOUT_PERI_HSI2C_1_IPCLK, 21, 0, 0), + GATE(CLK_GOUT_HSI2C1_PCLK, "gout_hsi2c1_pclk", "mout_peri_bus_user", + CLK_CON_GAT_GOUT_PERI_HSI2C_1_PCLK, 21, 0, 0), + GATE(CLK_GOUT_HSI2C2_IPCLK, "gout_hsi2c2_ipclk", "dout_peri_hsi2c2", + CLK_CON_GAT_GOUT_PERI_HSI2C_2_IPCLK, 21, 0, 0), + GATE(CLK_GOUT_HSI2C2_PCLK, "gout_hsi2c2_pclk", "mout_peri_bus_user", + CLK_CON_GAT_GOUT_PERI_HSI2C_2_PCLK, 21, 0, 0), + GATE(CLK_GOUT_I2C0_PCLK, "gout_i2c0_pclk", "mout_peri_bus_user", + CLK_CON_GAT_GOUT_PERI_I2C_0_PCLK, 21, 0, 0), + GATE(CLK_GOUT_I2C1_PCLK, "gout_i2c1_pclk", "mout_peri_bus_user", + CLK_CON_GAT_GOUT_PERI_I2C_1_PCLK, 21, 0, 0), + GATE(CLK_GOUT_I2C2_PCLK, "gout_i2c2_pclk", "mout_peri_bus_user", + CLK_CON_GAT_GOUT_PERI_I2C_2_PCLK, 21, 0, 0), + GATE(CLK_GOUT_I2C3_PCLK, "gout_i2c3_pclk", "mout_peri_bus_user", + CLK_CON_GAT_GOUT_PERI_I2C_3_PCLK, 21, 0, 0), + GATE(CLK_GOUT_I2C4_PCLK, "gout_i2c4_pclk", "mout_peri_bus_user", + CLK_CON_GAT_GOUT_PERI_I2C_4_PCLK, 21, 0, 0), + GATE(CLK_GOUT_I2C5_PCLK, "gout_i2c5_pclk", "mout_peri_bus_user", + CLK_CON_GAT_GOUT_PERI_I2C_5_PCLK, 21, 0, 0), + GATE(CLK_GOUT_I2C6_PCLK, "gout_i2c6_pclk", "mout_peri_bus_user", + CLK_CON_GAT_GOUT_PERI_I2C_6_PCLK, 21, 0, 0), + GATE(CLK_GOUT_MCT_PCLK, "gout_mct_pclk", "mout_peri_bus_user", + CLK_CON_GAT_GOUT_PERI_MCT_PCLK, 21, 0, 0), + GATE(CLK_GOUT_PWM_MOTOR_PCLK, "gout_pwm_motor_pclk", + "mout_peri_bus_user", + CLK_CON_GAT_GOUT_PERI_PWM_MOTOR_PCLK, 21, 0, 0), + GATE(CLK_GOUT_SPI0_IPCLK, "gout_spi0_ipclk", "dout_peri_spi0", + CLK_CON_GAT_GOUT_PERI_SPI_0_IPCLK, 21, 0, 0), + GATE(CLK_GOUT_SPI0_PCLK, "gout_spi0_pclk", "mout_peri_bus_user", + CLK_CON_GAT_GOUT_PERI_SPI_0_PCLK, 21, 0, 0), + GATE(CLK_GOUT_SYSREG_PERI_PCLK, "gout_sysreg_peri_pclk", + "mout_peri_bus_user", + CLK_CON_GAT_GOUT_PERI_SYSREG_PERI_PCLK, 21, 0, 0), + GATE(CLK_GOUT_UART_IPCLK, "gout_uart_ipclk", "mout_peri_uart_user", + CLK_CON_GAT_GOUT_PERI_UART_IPCLK, 21, 0, 0), + GATE(CLK_GOUT_UART_PCLK, "gout_uart_pclk", "mout_peri_bus_user", + CLK_CON_GAT_GOUT_PERI_UART_PCLK, 21, 0, 0), + GATE(CLK_GOUT_WDT0_PCLK, "gout_wdt0_pclk", "mout_peri_bus_user", + CLK_CON_GAT_GOUT_PERI_WDT_0_PCLK, 21, 0, 0), + GATE(CLK_GOUT_WDT1_PCLK, "gout_wdt1_pclk", "mout_peri_bus_user", + CLK_CON_GAT_GOUT_PERI_WDT_1_PCLK, 21, 0, 0), + GATE(CLK_GOUT_GPIO_PERI_PCLK, "gout_gpio_peri_pclk", + "mout_peri_bus_user", + CLK_CON_GAT_GOUT_PERI_GPIO_PERI_PCLK, 21, 0, 0), +}; + +static const struct samsung_cmu_info peri_cmu_info __initconst = { + .mux_clks = peri_mux_clks, + .nr_mux_clks = ARRAY_SIZE(peri_mux_clks), + .div_clks = peri_div_clks, + .nr_div_clks = ARRAY_SIZE(peri_div_clks), + .gate_clks = peri_gate_clks, + .nr_gate_clks = ARRAY_SIZE(peri_gate_clks), + .nr_clk_ids = PERI_NR_CLK, + .clk_regs = peri_clk_regs, + .nr_clk_regs = ARRAY_SIZE(peri_clk_regs), + .clk_name = "dout_peri_bus", +}; + +/* ---- CMU_CORE ------------------------------------------------------------ */ + +/* Register Offset definitions for CMU_CORE (0x12000000) */ +#define PLL_CON0_MUX_CLKCMU_CORE_BUS_USER 0x0600 +#define PLL_CON0_MUX_CLKCMU_CORE_CCI_USER 0x0610 +#define PLL_CON0_MUX_CLKCMU_CORE_MMC_EMBD_USER 0x0620 +#define PLL_CON0_MUX_CLKCMU_CORE_SSS_USER 0x0630 +#define CLK_CON_MUX_MUX_CLK_CORE_GIC 0x1000 +#define CLK_CON_DIV_DIV_CLK_CORE_BUSP 0x1800 +#define CLK_CON_GAT_GOUT_CORE_CCI_550_ACLK 0x2038 +#define CLK_CON_GAT_GOUT_CORE_GIC_CLK 0x2040 +#define CLK_CON_GAT_GOUT_CORE_MMC_EMBD_I_ACLK 0x20e8 +#define CLK_CON_GAT_GOUT_CORE_MMC_EMBD_SDCLKIN 0x20ec +#define CLK_CON_GAT_GOUT_CORE_SSS_I_ACLK 0x2128 +#define CLK_CON_GAT_GOUT_CORE_SSS_I_PCLK 0x212c + +static const unsigned long core_clk_regs[] __initconst = { + PLL_CON0_MUX_CLKCMU_CORE_BUS_USER, + PLL_CON0_MUX_CLKCMU_CORE_CCI_USER, + PLL_CON0_MUX_CLKCMU_CORE_MMC_EMBD_USER, + PLL_CON0_MUX_CLKCMU_CORE_SSS_USER, + CLK_CON_MUX_MUX_CLK_CORE_GIC, + CLK_CON_DIV_DIV_CLK_CORE_BUSP, + CLK_CON_GAT_GOUT_CORE_CCI_550_ACLK, + CLK_CON_GAT_GOUT_CORE_GIC_CLK, + CLK_CON_GAT_GOUT_CORE_MMC_EMBD_I_ACLK, + CLK_CON_GAT_GOUT_CORE_MMC_EMBD_SDCLKIN, + CLK_CON_GAT_GOUT_CORE_SSS_I_ACLK, + CLK_CON_GAT_GOUT_CORE_SSS_I_PCLK, +}; + +/* List of parent clocks for Muxes in CMU_CORE */ +PNAME(mout_core_bus_user_p) = { "oscclk", "dout_core_bus" }; +PNAME(mout_core_cci_user_p) = { "oscclk", "dout_core_cci" }; +PNAME(mout_core_mmc_embd_user_p) = { "oscclk", "dout_core_mmc_embd" }; +PNAME(mout_core_sss_user_p) = { "oscclk", "dout_core_sss" }; +PNAME(mout_core_gic_p) = { "dout_core_busp", "oscclk" }; + +static const struct samsung_mux_clock core_mux_clks[] __initconst = { + MUX(CLK_MOUT_CORE_BUS_USER, "mout_core_bus_user", mout_core_bus_user_p, + PLL_CON0_MUX_CLKCMU_CORE_BUS_USER, 4, 1), + MUX(CLK_MOUT_CORE_CCI_USER, "mout_core_cci_user", mout_core_cci_user_p, + PLL_CON0_MUX_CLKCMU_CORE_CCI_USER, 4, 1), + MUX_F(CLK_MOUT_CORE_MMC_EMBD_USER, "mout_core_mmc_embd_user", + mout_core_mmc_embd_user_p, PLL_CON0_MUX_CLKCMU_CORE_MMC_EMBD_USER, + 4, 1, CLK_SET_RATE_PARENT, 0), + MUX(CLK_MOUT_CORE_SSS_USER, "mout_core_sss_user", mout_core_sss_user_p, + PLL_CON0_MUX_CLKCMU_CORE_SSS_USER, 4, 1), + MUX(CLK_MOUT_CORE_GIC, "mout_core_gic", mout_core_gic_p, + CLK_CON_MUX_MUX_CLK_CORE_GIC, 0, 1), +}; + +static const struct samsung_div_clock core_div_clks[] __initconst = { + DIV(CLK_DOUT_CORE_BUSP, "dout_core_busp", "mout_core_bus_user", + CLK_CON_DIV_DIV_CLK_CORE_BUSP, 0, 2), +}; + +static const struct samsung_gate_clock core_gate_clks[] __initconst = { + GATE(CLK_GOUT_CCI_ACLK, "gout_cci_aclk", "mout_core_cci_user", + CLK_CON_GAT_GOUT_CORE_CCI_550_ACLK, 21, 0, 0), + GATE(CLK_GOUT_GIC_CLK, "gout_gic_clk", "mout_core_gic", + CLK_CON_GAT_GOUT_CORE_GIC_CLK, 21, 0, 0), + GATE(CLK_GOUT_MMC_EMBD_ACLK, "gout_mmc_embd_aclk", "dout_core_busp", + CLK_CON_GAT_GOUT_CORE_MMC_EMBD_I_ACLK, 21, 0, 0), + GATE(CLK_GOUT_MMC_EMBD_SDCLKIN, "gout_mmc_embd_sdclkin", + "mout_core_mmc_embd_user", CLK_CON_GAT_GOUT_CORE_MMC_EMBD_SDCLKIN, + 21, CLK_SET_RATE_PARENT, 0), + GATE(CLK_GOUT_SSS_ACLK, "gout_sss_aclk", "mout_core_sss_user", + CLK_CON_GAT_GOUT_CORE_SSS_I_ACLK, 21, 0, 0), + GATE(CLK_GOUT_SSS_PCLK, "gout_sss_pclk", "dout_core_busp", + CLK_CON_GAT_GOUT_CORE_SSS_I_PCLK, 21, 0, 0), +}; + +static const struct samsung_cmu_info core_cmu_info __initconst = { + .mux_clks = core_mux_clks, + .nr_mux_clks = ARRAY_SIZE(core_mux_clks), + .div_clks = core_div_clks, + .nr_div_clks = ARRAY_SIZE(core_div_clks), + .gate_clks = core_gate_clks, + .nr_gate_clks = ARRAY_SIZE(core_gate_clks), + .nr_clk_ids = CORE_NR_CLK, + .clk_regs = core_clk_regs, + .nr_clk_regs = ARRAY_SIZE(core_clk_regs), + .clk_name = "dout_core_bus", +}; + +/* ---- CMU_DPU ------------------------------------------------------------- */ + +/* Register Offset definitions for CMU_DPU (0x13000000) */ +#define PLL_CON0_MUX_CLKCMU_DPU_USER 0x0600 +#define CLK_CON_DIV_DIV_CLK_DPU_BUSP 0x1800 +#define CLK_CON_GAT_CLK_DPU_CMU_DPU_PCLK 0x2004 +#define CLK_CON_GAT_GOUT_DPU_ACLK_DECON0 0x2010 +#define CLK_CON_GAT_GOUT_DPU_ACLK_DMA 0x2014 +#define CLK_CON_GAT_GOUT_DPU_ACLK_DPP 0x2018 +#define CLK_CON_GAT_GOUT_DPU_PPMU_ACLK 0x2028 +#define CLK_CON_GAT_GOUT_DPU_PPMU_PCLK 0x202c +#define CLK_CON_GAT_GOUT_DPU_SMMU_CLK 0x2038 +#define CLK_CON_GAT_GOUT_DPU_SYSREG_PCLK 0x203c + +static const unsigned long dpu_clk_regs[] __initconst = { + PLL_CON0_MUX_CLKCMU_DPU_USER, + CLK_CON_DIV_DIV_CLK_DPU_BUSP, + CLK_CON_GAT_CLK_DPU_CMU_DPU_PCLK, + CLK_CON_GAT_GOUT_DPU_ACLK_DECON0, + CLK_CON_GAT_GOUT_DPU_ACLK_DMA, + CLK_CON_GAT_GOUT_DPU_ACLK_DPP, + CLK_CON_GAT_GOUT_DPU_PPMU_ACLK, + CLK_CON_GAT_GOUT_DPU_PPMU_PCLK, + CLK_CON_GAT_GOUT_DPU_SMMU_CLK, + CLK_CON_GAT_GOUT_DPU_SYSREG_PCLK, +}; + +/* List of parent clocks for Muxes in CMU_CORE */ +PNAME(mout_dpu_user_p) = { "oscclk", "dout_dpu" }; + +static const struct samsung_mux_clock dpu_mux_clks[] __initconst = { + MUX(CLK_MOUT_DPU_USER, "mout_dpu_user", mout_dpu_user_p, + PLL_CON0_MUX_CLKCMU_DPU_USER, 4, 1), +}; + +static const struct samsung_div_clock dpu_div_clks[] __initconst = { + DIV(CLK_DOUT_DPU_BUSP, "dout_dpu_busp", "mout_dpu_user", + CLK_CON_DIV_DIV_CLK_DPU_BUSP, 0, 3), +}; + +static const struct samsung_gate_clock dpu_gate_clks[] __initconst = { + GATE(CLK_GOUT_DPU_CMU_DPU_PCLK, "gout_dpu_cmu_dpu_pclk", + "dout_dpu_busp", CLK_CON_GAT_CLK_DPU_CMU_DPU_PCLK, 21, 0, 0), + GATE(CLK_GOUT_DPU_DECON0_ACLK, "gout_dpu_decon0_aclk", "mout_dpu_user", + CLK_CON_GAT_GOUT_DPU_ACLK_DECON0, 21, 0, 0), + GATE(CLK_GOUT_DPU_DMA_ACLK, "gout_dpu_dma_aclk", "mout_dpu_user", + CLK_CON_GAT_GOUT_DPU_ACLK_DMA, 21, 0, 0), + GATE(CLK_GOUT_DPU_DPP_ACLK, "gout_dpu_dpp_aclk", "mout_dpu_user", + CLK_CON_GAT_GOUT_DPU_ACLK_DPP, 21, 0, 0), + GATE(CLK_GOUT_DPU_PPMU_ACLK, "gout_dpu_ppmu_aclk", "mout_dpu_user", + CLK_CON_GAT_GOUT_DPU_PPMU_ACLK, 21, 0, 0), + GATE(CLK_GOUT_DPU_PPMU_PCLK, "gout_dpu_ppmu_pclk", "dout_dpu_busp", + CLK_CON_GAT_GOUT_DPU_PPMU_PCLK, 21, 0, 0), + GATE(CLK_GOUT_DPU_SMMU_CLK, "gout_dpu_smmu_clk", "mout_dpu_user", + CLK_CON_GAT_GOUT_DPU_SMMU_CLK, 21, 0, 0), + GATE(CLK_GOUT_DPU_SYSREG_PCLK, "gout_dpu_sysreg_pclk", "dout_dpu_busp", + CLK_CON_GAT_GOUT_DPU_SYSREG_PCLK, 21, 0, 0), +}; + +static const struct samsung_cmu_info dpu_cmu_info __initconst = { + .mux_clks = dpu_mux_clks, + .nr_mux_clks = ARRAY_SIZE(dpu_mux_clks), + .div_clks = dpu_div_clks, + .nr_div_clks = ARRAY_SIZE(dpu_div_clks), + .gate_clks = dpu_gate_clks, + .nr_gate_clks = ARRAY_SIZE(dpu_gate_clks), + .nr_clk_ids = DPU_NR_CLK, + .clk_regs = dpu_clk_regs, + .nr_clk_regs = ARRAY_SIZE(dpu_clk_regs), + .clk_name = "dout_dpu", +}; + +/* ---- platform_driver ----------------------------------------------------- */ + +static int __init exynos850_cmu_probe(struct platform_device *pdev) +{ + const struct samsung_cmu_info *info; + struct device *dev = &pdev->dev; + struct device_node *np = dev->of_node; + + info = of_device_get_match_data(dev); + exynos850_init_clocks(np, info->clk_regs, info->nr_clk_regs); + samsung_cmu_register_one(np, info); + + /* Keep bus clock running, so it's possible to access CMU registers */ + if (info->clk_name) { + struct clk *bus_clk; + + bus_clk = clk_get(dev, info->clk_name); + if (IS_ERR(bus_clk)) { + pr_err("%s: could not find bus clock %s; err = %ld\n", + __func__, info->clk_name, PTR_ERR(bus_clk)); + } else { + clk_prepare_enable(bus_clk); + } + } + + return 0; +} + +/* CMUs which belong to Power Domains and need runtime PM to be implemented */ +static const struct of_device_id exynos850_cmu_of_match[] = { + { + .compatible = "samsung,exynos850-cmu-hsi", + .data = &hsi_cmu_info, + }, { + .compatible = "samsung,exynos850-cmu-peri", + .data = &peri_cmu_info, + }, { + .compatible = "samsung,exynos850-cmu-core", + .data = &core_cmu_info, + }, { + .compatible = "samsung,exynos850-cmu-dpu", + .data = &dpu_cmu_info, + }, { + }, +}; + +static struct platform_driver exynos850_cmu_driver __refdata = { + .driver = { + .name = "exynos850-cmu", + .of_match_table = exynos850_cmu_of_match, + .suppress_bind_attrs = true, + }, + .probe = exynos850_cmu_probe, +}; + +static int __init exynos850_cmu_init(void) +{ + return platform_driver_register(&exynos850_cmu_driver); +} +core_initcall(exynos850_cmu_init); diff --git a/drivers/clk/samsung/clk-pll.c b/drivers/clk/samsung/clk-pll.c index 5873a9354b50..83d1b03647db 100644 --- a/drivers/clk/samsung/clk-pll.c +++ b/drivers/clk/samsung/clk-pll.c @@ -416,6 +416,186 @@ static const struct clk_ops samsung_pll36xx_clk_min_ops = { }; /* + * PLL0822x Clock Type + */ +/* Maximum lock time can be 150 * PDIV cycles */ +#define PLL0822X_LOCK_FACTOR (150) + +#define PLL0822X_MDIV_MASK (0x3FF) +#define PLL0822X_PDIV_MASK (0x3F) +#define PLL0822X_SDIV_MASK (0x7) +#define PLL0822X_MDIV_SHIFT (16) +#define PLL0822X_PDIV_SHIFT (8) +#define PLL0822X_SDIV_SHIFT (0) +#define PLL0822X_LOCK_STAT_SHIFT (29) +#define PLL0822X_ENABLE_SHIFT (31) + +static unsigned long samsung_pll0822x_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + struct samsung_clk_pll *pll = to_clk_pll(hw); + u32 mdiv, pdiv, sdiv, pll_con3; + u64 fvco = parent_rate; + + pll_con3 = readl_relaxed(pll->con_reg); + mdiv = (pll_con3 >> PLL0822X_MDIV_SHIFT) & PLL0822X_MDIV_MASK; + pdiv = (pll_con3 >> PLL0822X_PDIV_SHIFT) & PLL0822X_PDIV_MASK; + sdiv = (pll_con3 >> PLL0822X_SDIV_SHIFT) & PLL0822X_SDIV_MASK; + + fvco *= mdiv; + do_div(fvco, (pdiv << sdiv)); + + return (unsigned long)fvco; +} + +static int samsung_pll0822x_set_rate(struct clk_hw *hw, unsigned long drate, + unsigned long prate) +{ + const struct samsung_pll_rate_table *rate; + struct samsung_clk_pll *pll = to_clk_pll(hw); + u32 pll_con3; + + /* Get required rate settings from table */ + rate = samsung_get_pll_settings(pll, drate); + if (!rate) { + pr_err("%s: Invalid rate : %lu for pll clk %s\n", __func__, + drate, clk_hw_get_name(hw)); + return -EINVAL; + } + + /* Change PLL PMS values */ + pll_con3 = readl_relaxed(pll->con_reg); + pll_con3 &= ~((PLL0822X_MDIV_MASK << PLL0822X_MDIV_SHIFT) | + (PLL0822X_PDIV_MASK << PLL0822X_PDIV_SHIFT) | + (PLL0822X_SDIV_MASK << PLL0822X_SDIV_SHIFT)); + pll_con3 |= (rate->mdiv << PLL0822X_MDIV_SHIFT) | + (rate->pdiv << PLL0822X_PDIV_SHIFT) | + (rate->sdiv << PLL0822X_SDIV_SHIFT); + + /* Set PLL lock time */ + writel_relaxed(rate->pdiv * PLL0822X_LOCK_FACTOR, + pll->lock_reg); + + /* Write PMS values */ + writel_relaxed(pll_con3, pll->con_reg); + + /* Wait for PLL lock if the PLL is enabled */ + if (pll_con3 & BIT(pll->enable_offs)) + return samsung_pll_lock_wait(pll, BIT(pll->lock_offs)); + + return 0; +} + +static const struct clk_ops samsung_pll0822x_clk_ops = { + .recalc_rate = samsung_pll0822x_recalc_rate, + .round_rate = samsung_pll_round_rate, + .set_rate = samsung_pll0822x_set_rate, + .enable = samsung_pll3xxx_enable, + .disable = samsung_pll3xxx_disable, +}; + +static const struct clk_ops samsung_pll0822x_clk_min_ops = { + .recalc_rate = samsung_pll0822x_recalc_rate, +}; + +/* + * PLL0831x Clock Type + */ +/* Maximum lock time can be 500 * PDIV cycles */ +#define PLL0831X_LOCK_FACTOR (500) + +#define PLL0831X_KDIV_MASK (0xFFFF) +#define PLL0831X_MDIV_MASK (0x1FF) +#define PLL0831X_PDIV_MASK (0x3F) +#define PLL0831X_SDIV_MASK (0x7) +#define PLL0831X_MDIV_SHIFT (16) +#define PLL0831X_PDIV_SHIFT (8) +#define PLL0831X_SDIV_SHIFT (0) +#define PLL0831X_KDIV_SHIFT (0) +#define PLL0831X_LOCK_STAT_SHIFT (29) +#define PLL0831X_ENABLE_SHIFT (31) + +static unsigned long samsung_pll0831x_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + struct samsung_clk_pll *pll = to_clk_pll(hw); + u32 mdiv, pdiv, sdiv, pll_con3, pll_con5; + s16 kdiv; + u64 fvco = parent_rate; + + pll_con3 = readl_relaxed(pll->con_reg); + pll_con5 = readl_relaxed(pll->con_reg + 8); + mdiv = (pll_con3 >> PLL0831X_MDIV_SHIFT) & PLL0831X_MDIV_MASK; + pdiv = (pll_con3 >> PLL0831X_PDIV_SHIFT) & PLL0831X_PDIV_MASK; + sdiv = (pll_con3 >> PLL0831X_SDIV_SHIFT) & PLL0831X_SDIV_MASK; + kdiv = (s16)((pll_con5 >> PLL0831X_KDIV_SHIFT) & PLL0831X_KDIV_MASK); + + fvco *= (mdiv << 16) + kdiv; + do_div(fvco, (pdiv << sdiv)); + fvco >>= 16; + + return (unsigned long)fvco; +} + +static int samsung_pll0831x_set_rate(struct clk_hw *hw, unsigned long drate, + unsigned long parent_rate) +{ + const struct samsung_pll_rate_table *rate; + struct samsung_clk_pll *pll = to_clk_pll(hw); + u32 pll_con3, pll_con5; + + /* Get required rate settings from table */ + rate = samsung_get_pll_settings(pll, drate); + if (!rate) { + pr_err("%s: Invalid rate : %lu for pll clk %s\n", __func__, + drate, clk_hw_get_name(hw)); + return -EINVAL; + } + + pll_con3 = readl_relaxed(pll->con_reg); + pll_con5 = readl_relaxed(pll->con_reg + 8); + + /* Change PLL PMSK values */ + pll_con3 &= ~((PLL0831X_MDIV_MASK << PLL0831X_MDIV_SHIFT) | + (PLL0831X_PDIV_MASK << PLL0831X_PDIV_SHIFT) | + (PLL0831X_SDIV_MASK << PLL0831X_SDIV_SHIFT)); + pll_con3 |= (rate->mdiv << PLL0831X_MDIV_SHIFT) | + (rate->pdiv << PLL0831X_PDIV_SHIFT) | + (rate->sdiv << PLL0831X_SDIV_SHIFT); + pll_con5 &= ~(PLL0831X_KDIV_MASK << PLL0831X_KDIV_SHIFT); + /* + * kdiv is 16-bit 2's complement (s16), but stored as unsigned int. + * Cast it to u16 to avoid leading 0xffff's in case of negative value. + */ + pll_con5 |= ((u16)rate->kdiv << PLL0831X_KDIV_SHIFT); + + /* Set PLL lock time */ + writel_relaxed(rate->pdiv * PLL0831X_LOCK_FACTOR, pll->lock_reg); + + /* Write PMSK values */ + writel_relaxed(pll_con3, pll->con_reg); + writel_relaxed(pll_con5, pll->con_reg + 8); + + /* Wait for PLL lock if the PLL is enabled */ + if (pll_con3 & BIT(pll->enable_offs)) + return samsung_pll_lock_wait(pll, BIT(pll->lock_offs)); + + return 0; +} + +static const struct clk_ops samsung_pll0831x_clk_ops = { + .recalc_rate = samsung_pll0831x_recalc_rate, + .set_rate = samsung_pll0831x_set_rate, + .round_rate = samsung_pll_round_rate, + .enable = samsung_pll3xxx_enable, + .disable = samsung_pll3xxx_disable, +}; + +static const struct clk_ops samsung_pll0831x_clk_min_ops = { + .recalc_rate = samsung_pll0831x_recalc_rate, +}; + +/* * PLL45xx Clock Type */ #define PLL4502_LOCK_FACTOR 400 @@ -1296,6 +1476,14 @@ static void __init _samsung_clk_register_pll(struct samsung_clk_provider *ctx, else init.ops = &samsung_pll35xx_clk_ops; break; + case pll_0822x: + pll->enable_offs = PLL0822X_ENABLE_SHIFT; + pll->lock_offs = PLL0822X_LOCK_STAT_SHIFT; + if (!pll->rate_table) + init.ops = &samsung_pll0822x_clk_min_ops; + else + init.ops = &samsung_pll0822x_clk_ops; + break; case pll_4500: init.ops = &samsung_pll45xx_clk_min_ops; break; @@ -1316,6 +1504,14 @@ static void __init _samsung_clk_register_pll(struct samsung_clk_provider *ctx, else init.ops = &samsung_pll36xx_clk_ops; break; + case pll_0831x: + pll->enable_offs = PLL0831X_ENABLE_SHIFT; + pll->lock_offs = PLL0831X_LOCK_STAT_SHIFT; + if (!pll->rate_table) + init.ops = &samsung_pll0831x_clk_min_ops; + else + init.ops = &samsung_pll0831x_clk_ops; + break; case pll_6552: case pll_6552_s3c2416: init.ops = &samsung_pll6552_clk_ops; diff --git a/drivers/clk/samsung/clk-pll.h b/drivers/clk/samsung/clk-pll.h index 79e41c226b90..a739f2b7ae80 100644 --- a/drivers/clk/samsung/clk-pll.h +++ b/drivers/clk/samsung/clk-pll.h @@ -36,6 +36,8 @@ enum samsung_pll_type { pll_1451x, pll_1452x, pll_1460x, + pll_0822x, + pll_0831x, }; #define PLL_RATE(_fin, _m, _p, _s, _k, _ks) \ diff --git a/drivers/clk/samsung/clk-s5pv210-audss.c b/drivers/clk/samsung/clk-s5pv210-audss.c index a7827a120695..b31c00ea331f 100644 --- a/drivers/clk/samsung/clk-s5pv210-audss.c +++ b/drivers/clk/samsung/clk-s5pv210-audss.c @@ -63,15 +63,13 @@ static struct syscore_ops s5pv210_audss_clk_syscore_ops = { static int s5pv210_audss_clk_probe(struct platform_device *pdev) { int i, ret = 0; - struct resource *res; const char *mout_audss_p[2]; const char *mout_i2s_p[3]; const char *hclk_p; struct clk_hw **clk_table; struct clk *hclk, *pll_ref, *pll_in, *cdclk, *sclk_audio; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - reg_base = devm_ioremap_resource(&pdev->dev, res); + reg_base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(reg_base)) return PTR_ERR(reg_base); diff --git a/drivers/clk/samsung/clk.c b/drivers/clk/samsung/clk.c index 1949ae7851b2..336243c6f120 100644 --- a/drivers/clk/samsung/clk.c +++ b/drivers/clk/samsung/clk.c @@ -378,6 +378,8 @@ struct samsung_clk_provider * __init samsung_cmu_register_one( samsung_clk_extended_sleep_init(reg_base, cmu->clk_regs, cmu->nr_clk_regs, cmu->suspend_regs, cmu->nr_suspend_regs); + if (cmu->cpu_clks) + samsung_clk_register_cpu(ctx, cmu->cpu_clks, cmu->nr_cpu_clks); samsung_clk_of_add_provider(np, ctx); diff --git a/drivers/clk/samsung/clk.h b/drivers/clk/samsung/clk.h index c1e1a6b2f499..26499e97275b 100644 --- a/drivers/clk/samsung/clk.h +++ b/drivers/clk/samsung/clk.h @@ -271,6 +271,27 @@ struct samsung_pll_clock { __PLL(_typ, _id, _name, _pname, CLK_GET_RATE_NOCACHE, _lock, \ _con, _rtable) +struct samsung_cpu_clock { + unsigned int id; + const char *name; + unsigned int parent_id; + unsigned int alt_parent_id; + unsigned long flags; + int offset; + const struct exynos_cpuclk_cfg_data *cfg; +}; + +#define CPU_CLK(_id, _name, _pid, _apid, _flags, _offset, _cfg) \ + { \ + .id = _id, \ + .name = _name, \ + .parent_id = _pid, \ + .alt_parent_id = _apid, \ + .flags = _flags, \ + .offset = _offset, \ + .cfg = _cfg, \ + } + struct samsung_clock_reg_cache { struct list_head node; void __iomem *reg_base; @@ -301,6 +322,9 @@ struct samsung_cmu_info { unsigned int nr_fixed_factor_clks; /* total number of clocks with IDs assigned*/ unsigned int nr_clk_ids; + /* list of cpu clocks and respective count */ + const struct samsung_cpu_clock *cpu_clks; + unsigned int nr_cpu_clks; /* list and number of clocks registers */ const unsigned long *clk_regs; @@ -350,6 +374,8 @@ extern void __init samsung_clk_register_gate(struct samsung_clk_provider *ctx, extern void __init samsung_clk_register_pll(struct samsung_clk_provider *ctx, const struct samsung_pll_clock *pll_list, unsigned int nr_clk, void __iomem *base); +extern void samsung_clk_register_cpu(struct samsung_clk_provider *ctx, + const struct samsung_cpu_clock *list, unsigned int nr_clk); extern struct samsung_clk_provider __init *samsung_cmu_register_one( struct device_node *, diff --git a/drivers/clk/sunxi-ng/Kconfig b/drivers/clk/sunxi-ng/Kconfig index cd46d8853876..e76e1676f0f0 100644 --- a/drivers/clk/sunxi-ng/Kconfig +++ b/drivers/clk/sunxi-ng/Kconfig @@ -71,6 +71,7 @@ config SUN8I_A33_CCU config SUN8I_A83T_CCU bool "Support for the Allwinner A83T CCU" default MACH_SUN8I + depends on MACH_SUN8I || COMPILE_TEST config SUN8I_H3_CCU bool "Support for the Allwinner H3 CCU" diff --git a/drivers/clk/sunxi-ng/ccu-sun4i-a10.c b/drivers/clk/sunxi-ng/ccu-sun4i-a10.c index f32366d9336e..bd9a8782fec3 100644 --- a/drivers/clk/sunxi-ng/ccu-sun4i-a10.c +++ b/drivers/clk/sunxi-ng/ccu-sun4i-a10.c @@ -1464,7 +1464,7 @@ static void __init sun4i_ccu_init(struct device_node *node, val &= ~GENMASK(7, 6); writel(val | (2 << 6), reg + SUN4I_AHB_REG); - sunxi_ccu_probe(node, reg, desc); + of_sunxi_ccu_probe(node, reg, desc); } static void __init sun4i_a10_ccu_setup(struct device_node *node) diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-a100-r.c b/drivers/clk/sunxi-ng/ccu-sun50i-a100-r.c index a56142b90993..804729e0a208 100644 --- a/drivers/clk/sunxi-ng/ccu-sun50i-a100-r.c +++ b/drivers/clk/sunxi-ng/ccu-sun50i-a100-r.c @@ -196,7 +196,7 @@ static int sun50i_a100_r_ccu_probe(struct platform_device *pdev) if (IS_ERR(reg)) return PTR_ERR(reg); - return sunxi_ccu_probe(pdev->dev.of_node, reg, &sun50i_a100_r_ccu_desc); + return devm_sunxi_ccu_probe(&pdev->dev, reg, &sun50i_a100_r_ccu_desc); } static const struct of_device_id sun50i_a100_r_ccu_ids[] = { @@ -208,6 +208,7 @@ static struct platform_driver sun50i_a100_r_ccu_driver = { .probe = sun50i_a100_r_ccu_probe, .driver = { .name = "sun50i-a100-r-ccu", + .suppress_bind_attrs = true, .of_match_table = sun50i_a100_r_ccu_ids, }, }; diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-a100.c b/drivers/clk/sunxi-ng/ccu-sun50i-a100.c index 81b48c73d389..1d475d5a3d91 100644 --- a/drivers/clk/sunxi-ng/ccu-sun50i-a100.c +++ b/drivers/clk/sunxi-ng/ccu-sun50i-a100.c @@ -1247,7 +1247,7 @@ static int sun50i_a100_ccu_probe(struct platform_device *pdev) writel(val, reg + sun50i_a100_usb2_clk_regs[i]); } - ret = sunxi_ccu_probe(pdev->dev.of_node, reg, &sun50i_a100_ccu_desc); + ret = devm_sunxi_ccu_probe(&pdev->dev, reg, &sun50i_a100_ccu_desc); if (ret) return ret; @@ -1270,6 +1270,7 @@ static struct platform_driver sun50i_a100_ccu_driver = { .probe = sun50i_a100_ccu_probe, .driver = { .name = "sun50i-a100-ccu", + .suppress_bind_attrs = true, .of_match_table = sun50i_a100_ccu_ids, }, }; diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-a64.c b/drivers/clk/sunxi-ng/ccu-sun50i-a64.c index 149cfde817cb..a8c5a92b7d0c 100644 --- a/drivers/clk/sunxi-ng/ccu-sun50i-a64.c +++ b/drivers/clk/sunxi-ng/ccu-sun50i-a64.c @@ -938,13 +938,11 @@ static struct ccu_mux_nb sun50i_a64_cpu_nb = { static int sun50i_a64_ccu_probe(struct platform_device *pdev) { - struct resource *res; void __iomem *reg; u32 val; int ret; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - reg = devm_ioremap_resource(&pdev->dev, res); + reg = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(reg)) return PTR_ERR(reg); @@ -955,7 +953,7 @@ static int sun50i_a64_ccu_probe(struct platform_device *pdev) writel(0x515, reg + SUN50I_A64_PLL_MIPI_REG); - ret = sunxi_ccu_probe(pdev->dev.of_node, reg, &sun50i_a64_ccu_desc); + ret = devm_sunxi_ccu_probe(&pdev->dev, reg, &sun50i_a64_ccu_desc); if (ret) return ret; @@ -978,6 +976,7 @@ static struct platform_driver sun50i_a64_ccu_driver = { .probe = sun50i_a64_ccu_probe, .driver = { .name = "sun50i-a64-ccu", + .suppress_bind_attrs = true, .of_match_table = sun50i_a64_ccu_ids, }, }; diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-h6-r.c b/drivers/clk/sunxi-ng/ccu-sun50i-h6-r.c index f8909a7ed553..f30d7eb5424d 100644 --- a/drivers/clk/sunxi-ng/ccu-sun50i-h6-r.c +++ b/drivers/clk/sunxi-ng/ccu-sun50i-h6-r.c @@ -232,7 +232,7 @@ static void __init sunxi_r_ccu_init(struct device_node *node, return; } - sunxi_ccu_probe(node, reg, desc); + of_sunxi_ccu_probe(node, reg, desc); } static void __init sun50i_h6_r_ccu_setup(struct device_node *node) diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-h6.c b/drivers/clk/sunxi-ng/ccu-sun50i-h6.c index bff446b78290..e5672c10d065 100644 --- a/drivers/clk/sunxi-ng/ccu-sun50i-h6.c +++ b/drivers/clk/sunxi-ng/ccu-sun50i-h6.c @@ -1183,13 +1183,11 @@ static const u32 usb2_clk_regs[] = { static int sun50i_h6_ccu_probe(struct platform_device *pdev) { - struct resource *res; void __iomem *reg; u32 val; int i; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - reg = devm_ioremap_resource(&pdev->dev, res); + reg = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(reg)) return PTR_ERR(reg); @@ -1240,7 +1238,7 @@ static int sun50i_h6_ccu_probe(struct platform_device *pdev) val |= BIT(24); writel(val, reg + SUN50I_H6_HDMI_CEC_CLK_REG); - return sunxi_ccu_probe(pdev->dev.of_node, reg, &sun50i_h6_ccu_desc); + return devm_sunxi_ccu_probe(&pdev->dev, reg, &sun50i_h6_ccu_desc); } static const struct of_device_id sun50i_h6_ccu_ids[] = { @@ -1252,6 +1250,7 @@ static struct platform_driver sun50i_h6_ccu_driver = { .probe = sun50i_h6_ccu_probe, .driver = { .name = "sun50i-h6-ccu", + .suppress_bind_attrs = true, .of_match_table = sun50i_h6_ccu_ids, }, }; diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-h616.c b/drivers/clk/sunxi-ng/ccu-sun50i-h616.c index 225307305880..22eb18079a15 100644 --- a/drivers/clk/sunxi-ng/ccu-sun50i-h616.c +++ b/drivers/clk/sunxi-ng/ccu-sun50i-h616.c @@ -1141,9 +1141,7 @@ static void __init sun50i_h616_ccu_setup(struct device_node *node) val |= BIT(24); writel(val, reg + SUN50I_H616_HDMI_CEC_CLK_REG); - i = sunxi_ccu_probe(node, reg, &sun50i_h616_ccu_desc); - if (i) - pr_err("%pOF: probing clocks fails: %d\n", node, i); + of_sunxi_ccu_probe(node, reg, &sun50i_h616_ccu_desc); } CLK_OF_DECLARE(sun50i_h616_ccu, "allwinner,sun50i-h616-ccu", diff --git a/drivers/clk/sunxi-ng/ccu-sun5i.c b/drivers/clk/sunxi-ng/ccu-sun5i.c index b78e9b507c1c..1f4bc0e773a7 100644 --- a/drivers/clk/sunxi-ng/ccu-sun5i.c +++ b/drivers/clk/sunxi-ng/ccu-sun5i.c @@ -1012,7 +1012,7 @@ static void __init sun5i_ccu_init(struct device_node *node, val &= ~GENMASK(7, 6); writel(val | (2 << 6), reg + SUN5I_AHB_REG); - sunxi_ccu_probe(node, reg, desc); + of_sunxi_ccu_probe(node, reg, desc); } static void __init sun5i_a10s_ccu_setup(struct device_node *node) diff --git a/drivers/clk/sunxi-ng/ccu-sun6i-a31.c b/drivers/clk/sunxi-ng/ccu-sun6i-a31.c index 9b40d53266a3..3df5c0b41580 100644 --- a/drivers/clk/sunxi-ng/ccu-sun6i-a31.c +++ b/drivers/clk/sunxi-ng/ccu-sun6i-a31.c @@ -1257,7 +1257,7 @@ static void __init sun6i_a31_ccu_setup(struct device_node *node) val |= 0x3 << 12; writel(val, reg + SUN6I_A31_AHB1_REG); - sunxi_ccu_probe(node, reg, &sun6i_a31_ccu_desc); + of_sunxi_ccu_probe(node, reg, &sun6i_a31_ccu_desc); ccu_mux_notifier_register(pll_cpu_clk.common.hw.clk, &sun6i_a31_cpu_nb); diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-a23.c b/drivers/clk/sunxi-ng/ccu-sun8i-a23.c index 103aa504f6c8..577bb235d658 100644 --- a/drivers/clk/sunxi-ng/ccu-sun8i-a23.c +++ b/drivers/clk/sunxi-ng/ccu-sun8i-a23.c @@ -745,7 +745,7 @@ static void __init sun8i_a23_ccu_setup(struct device_node *node) val &= ~BIT(16); writel(val, reg + SUN8I_A23_PLL_MIPI_REG); - sunxi_ccu_probe(node, reg, &sun8i_a23_ccu_desc); + of_sunxi_ccu_probe(node, reg, &sun8i_a23_ccu_desc); } CLK_OF_DECLARE(sun8i_a23_ccu, "allwinner,sun8i-a23-ccu", sun8i_a23_ccu_setup); diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-a33.c b/drivers/clk/sunxi-ng/ccu-sun8i-a33.c index 91838cd11037..8f65cd03f5ac 100644 --- a/drivers/clk/sunxi-ng/ccu-sun8i-a33.c +++ b/drivers/clk/sunxi-ng/ccu-sun8i-a33.c @@ -805,7 +805,7 @@ static void __init sun8i_a33_ccu_setup(struct device_node *node) val &= ~BIT(16); writel(val, reg + SUN8I_A33_PLL_MIPI_REG); - sunxi_ccu_probe(node, reg, &sun8i_a33_ccu_desc); + of_sunxi_ccu_probe(node, reg, &sun8i_a33_ccu_desc); /* Gate then ungate PLL CPU after any rate changes */ ccu_pll_notifier_register(&sun8i_a33_pll_cpu_nb); diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-a83t.c b/drivers/clk/sunxi-ng/ccu-sun8i-a83t.c index 2b434521c5cc..3c310aea8cfa 100644 --- a/drivers/clk/sunxi-ng/ccu-sun8i-a83t.c +++ b/drivers/clk/sunxi-ng/ccu-sun8i-a83t.c @@ -887,12 +887,10 @@ static void sun8i_a83t_cpu_pll_fixup(void __iomem *reg) static int sun8i_a83t_ccu_probe(struct platform_device *pdev) { - struct resource *res; void __iomem *reg; u32 val; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - reg = devm_ioremap_resource(&pdev->dev, res); + reg = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(reg)) return PTR_ERR(reg); @@ -906,7 +904,7 @@ static int sun8i_a83t_ccu_probe(struct platform_device *pdev) sun8i_a83t_cpu_pll_fixup(reg + SUN8I_A83T_PLL_C0CPUX_REG); sun8i_a83t_cpu_pll_fixup(reg + SUN8I_A83T_PLL_C1CPUX_REG); - return sunxi_ccu_probe(pdev->dev.of_node, reg, &sun8i_a83t_ccu_desc); + return devm_sunxi_ccu_probe(&pdev->dev, reg, &sun8i_a83t_ccu_desc); } static const struct of_device_id sun8i_a83t_ccu_ids[] = { @@ -918,6 +916,7 @@ static struct platform_driver sun8i_a83t_ccu_driver = { .probe = sun8i_a83t_ccu_probe, .driver = { .name = "sun8i-a83t-ccu", + .suppress_bind_attrs = true, .of_match_table = sun8i_a83t_ccu_ids, }, }; diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-de2.c b/drivers/clk/sunxi-ng/ccu-sun8i-de2.c index 524f33275bc7..573b5051d305 100644 --- a/drivers/clk/sunxi-ng/ccu-sun8i-de2.c +++ b/drivers/clk/sunxi-ng/ccu-sun8i-de2.c @@ -280,7 +280,6 @@ static const struct sunxi_ccu_desc sun50i_h5_de2_clk_desc = { static int sunxi_de2_clk_probe(struct platform_device *pdev) { - struct resource *res; struct clk *bus_clk, *mod_clk; struct reset_control *rstc; void __iomem *reg; @@ -291,8 +290,7 @@ static int sunxi_de2_clk_probe(struct platform_device *pdev) if (!ccu_desc) return -EINVAL; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - reg = devm_ioremap_resource(&pdev->dev, res); + reg = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(reg)) return PTR_ERR(reg); @@ -342,7 +340,7 @@ static int sunxi_de2_clk_probe(struct platform_device *pdev) goto err_disable_mod_clk; } - ret = sunxi_ccu_probe(pdev->dev.of_node, reg, ccu_desc); + ret = devm_sunxi_ccu_probe(&pdev->dev, reg, ccu_desc); if (ret) goto err_assert_reset; diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-h3.c b/drivers/clk/sunxi-ng/ccu-sun8i-h3.c index 7e629a4493af..d2fc2903787d 100644 --- a/drivers/clk/sunxi-ng/ccu-sun8i-h3.c +++ b/drivers/clk/sunxi-ng/ccu-sun8i-h3.c @@ -1154,7 +1154,7 @@ static void __init sunxi_h3_h5_ccu_init(struct device_node *node, val &= ~GENMASK(19, 16); writel(val | (0 << 16), reg + SUN8I_H3_PLL_AUDIO_REG); - sunxi_ccu_probe(node, reg, desc); + of_sunxi_ccu_probe(node, reg, desc); /* Gate then ungate PLL CPU after any rate changes */ ccu_pll_notifier_register(&sun8i_h3_pll_cpu_nb); diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-r.c b/drivers/clk/sunxi-ng/ccu-sun8i-r.c index 4c8c491b87c2..9e754d1f754a 100644 --- a/drivers/clk/sunxi-ng/ccu-sun8i-r.c +++ b/drivers/clk/sunxi-ng/ccu-sun8i-r.c @@ -265,7 +265,7 @@ static void __init sunxi_r_ccu_init(struct device_node *node, return; } - sunxi_ccu_probe(node, reg, desc); + of_sunxi_ccu_probe(node, reg, desc); } static void __init sun8i_a83t_r_ccu_setup(struct device_node *node) diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-r40.c b/drivers/clk/sunxi-ng/ccu-sun8i-r40.c index 84153418453f..8bb18d9add05 100644 --- a/drivers/clk/sunxi-ng/ccu-sun8i-r40.c +++ b/drivers/clk/sunxi-ng/ccu-sun8i-r40.c @@ -1307,14 +1307,12 @@ static struct regmap_config sun8i_r40_ccu_regmap_config = { static int sun8i_r40_ccu_probe(struct platform_device *pdev) { - struct resource *res; struct regmap *regmap; void __iomem *reg; u32 val; int ret; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - reg = devm_ioremap_resource(&pdev->dev, res); + reg = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(reg)) return PTR_ERR(reg); @@ -1346,7 +1344,7 @@ static int sun8i_r40_ccu_probe(struct platform_device *pdev) if (IS_ERR(regmap)) return PTR_ERR(regmap); - ret = sunxi_ccu_probe(pdev->dev.of_node, reg, &sun8i_r40_ccu_desc); + ret = devm_sunxi_ccu_probe(&pdev->dev, reg, &sun8i_r40_ccu_desc); if (ret) return ret; @@ -1369,6 +1367,7 @@ static struct platform_driver sun8i_r40_ccu_driver = { .probe = sun8i_r40_ccu_probe, .driver = { .name = "sun8i-r40-ccu", + .suppress_bind_attrs = true, .of_match_table = sun8i_r40_ccu_ids, }, }; diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-v3s.c b/drivers/clk/sunxi-ng/ccu-sun8i-v3s.c index f49724a22540..ce150f83ab54 100644 --- a/drivers/clk/sunxi-ng/ccu-sun8i-v3s.c +++ b/drivers/clk/sunxi-ng/ccu-sun8i-v3s.c @@ -822,7 +822,7 @@ static void __init sun8i_v3_v3s_ccu_init(struct device_node *node, val &= ~GENMASK(19, 16); writel(val, reg + SUN8I_V3S_PLL_AUDIO_REG); - sunxi_ccu_probe(node, reg, ccu_desc); + of_sunxi_ccu_probe(node, reg, ccu_desc); } static void __init sun8i_v3s_ccu_setup(struct device_node *node) diff --git a/drivers/clk/sunxi-ng/ccu-sun9i-a80-de.c b/drivers/clk/sunxi-ng/ccu-sun9i-a80-de.c index 6616e8114f62..3cde2610f467 100644 --- a/drivers/clk/sunxi-ng/ccu-sun9i-a80-de.c +++ b/drivers/clk/sunxi-ng/ccu-sun9i-a80-de.c @@ -203,14 +203,12 @@ static const struct sunxi_ccu_desc sun9i_a80_de_clk_desc = { static int sun9i_a80_de_clk_probe(struct platform_device *pdev) { - struct resource *res; struct clk *bus_clk; struct reset_control *rstc; void __iomem *reg; int ret; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - reg = devm_ioremap_resource(&pdev->dev, res); + reg = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(reg)) return PTR_ERR(reg); @@ -246,8 +244,7 @@ static int sun9i_a80_de_clk_probe(struct platform_device *pdev) goto err_disable_clk; } - ret = sunxi_ccu_probe(pdev->dev.of_node, reg, - &sun9i_a80_de_clk_desc); + ret = devm_sunxi_ccu_probe(&pdev->dev, reg, &sun9i_a80_de_clk_desc); if (ret) goto err_assert_reset; @@ -269,6 +266,7 @@ static struct platform_driver sun9i_a80_de_clk_driver = { .probe = sun9i_a80_de_clk_probe, .driver = { .name = "sun9i-a80-de-clks", + .suppress_bind_attrs = true, .of_match_table = sun9i_a80_de_clk_ids, }, }; diff --git a/drivers/clk/sunxi-ng/ccu-sun9i-a80-usb.c b/drivers/clk/sunxi-ng/ccu-sun9i-a80-usb.c index 4b4a507d04ed..0740e8978ae8 100644 --- a/drivers/clk/sunxi-ng/ccu-sun9i-a80-usb.c +++ b/drivers/clk/sunxi-ng/ccu-sun9i-a80-usb.c @@ -92,13 +92,11 @@ static const struct sunxi_ccu_desc sun9i_a80_usb_clk_desc = { static int sun9i_a80_usb_clk_probe(struct platform_device *pdev) { - struct resource *res; struct clk *bus_clk; void __iomem *reg; int ret; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - reg = devm_ioremap_resource(&pdev->dev, res); + reg = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(reg)) return PTR_ERR(reg); @@ -117,8 +115,7 @@ static int sun9i_a80_usb_clk_probe(struct platform_device *pdev) return ret; } - ret = sunxi_ccu_probe(pdev->dev.of_node, reg, - &sun9i_a80_usb_clk_desc); + ret = devm_sunxi_ccu_probe(&pdev->dev, reg, &sun9i_a80_usb_clk_desc); if (ret) goto err_disable_clk; diff --git a/drivers/clk/sunxi-ng/ccu-sun9i-a80.c b/drivers/clk/sunxi-ng/ccu-sun9i-a80.c index ef29582676f6..d416af29e0d3 100644 --- a/drivers/clk/sunxi-ng/ccu-sun9i-a80.c +++ b/drivers/clk/sunxi-ng/ccu-sun9i-a80.c @@ -1213,12 +1213,10 @@ static void sun9i_a80_cpu_pll_fixup(void __iomem *reg) static int sun9i_a80_ccu_probe(struct platform_device *pdev) { - struct resource *res; void __iomem *reg; u32 val; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - reg = devm_ioremap_resource(&pdev->dev, res); + reg = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(reg)) return PTR_ERR(reg); @@ -1231,7 +1229,7 @@ static int sun9i_a80_ccu_probe(struct platform_device *pdev) sun9i_a80_cpu_pll_fixup(reg + SUN9I_A80_PLL_C0CPUX_REG); sun9i_a80_cpu_pll_fixup(reg + SUN9I_A80_PLL_C1CPUX_REG); - return sunxi_ccu_probe(pdev->dev.of_node, reg, &sun9i_a80_ccu_desc); + return devm_sunxi_ccu_probe(&pdev->dev, reg, &sun9i_a80_ccu_desc); } static const struct of_device_id sun9i_a80_ccu_ids[] = { @@ -1243,6 +1241,7 @@ static struct platform_driver sun9i_a80_ccu_driver = { .probe = sun9i_a80_ccu_probe, .driver = { .name = "sun9i-a80-ccu", + .suppress_bind_attrs = true, .of_match_table = sun9i_a80_ccu_ids, }, }; diff --git a/drivers/clk/sunxi-ng/ccu-suniv-f1c100s.c b/drivers/clk/sunxi-ng/ccu-suniv-f1c100s.c index 7ecc3a5a5b5e..61ad7ee91c11 100644 --- a/drivers/clk/sunxi-ng/ccu-suniv-f1c100s.c +++ b/drivers/clk/sunxi-ng/ccu-suniv-f1c100s.c @@ -538,7 +538,7 @@ static void __init suniv_f1c100s_ccu_setup(struct device_node *node) val &= ~GENMASK(19, 16); writel(val | (3 << 16), reg + SUNIV_PLL_AUDIO_REG); - sunxi_ccu_probe(node, reg, &suniv_ccu_desc); + of_sunxi_ccu_probe(node, reg, &suniv_ccu_desc); /* Gate then ungate PLL CPU after any rate changes */ ccu_pll_notifier_register(&suniv_pll_cpu_nb); diff --git a/drivers/clk/sunxi-ng/ccu_common.c b/drivers/clk/sunxi-ng/ccu_common.c index 2e20e650b6c0..31af8b6b5286 100644 --- a/drivers/clk/sunxi-ng/ccu_common.c +++ b/drivers/clk/sunxi-ng/ccu_common.c @@ -7,6 +7,7 @@ #include <linux/clk.h> #include <linux/clk-provider.h> +#include <linux/device.h> #include <linux/iopoll.h> #include <linux/slab.h> @@ -14,7 +15,11 @@ #include "ccu_gate.h" #include "ccu_reset.h" -static DEFINE_SPINLOCK(ccu_lock); +struct sunxi_ccu { + const struct sunxi_ccu_desc *desc; + spinlock_t lock; + struct ccu_reset reset; +}; void ccu_helper_wait_for_lock(struct ccu_common *common, u32 lock) { @@ -79,12 +84,17 @@ int ccu_pll_notifier_register(struct ccu_pll_nb *pll_nb) &pll_nb->clk_nb); } -int sunxi_ccu_probe(struct device_node *node, void __iomem *reg, - const struct sunxi_ccu_desc *desc) +static int sunxi_ccu_probe(struct sunxi_ccu *ccu, struct device *dev, + struct device_node *node, void __iomem *reg, + const struct sunxi_ccu_desc *desc) { struct ccu_reset *reset; int i, ret; + ccu->desc = desc; + + spin_lock_init(&ccu->lock); + for (i = 0; i < desc->num_ccu_clks; i++) { struct ccu_common *cclk = desc->ccu_clks[i]; @@ -92,7 +102,7 @@ int sunxi_ccu_probe(struct device_node *node, void __iomem *reg, continue; cclk->base = reg; - cclk->lock = &ccu_lock; + cclk->lock = &ccu->lock; } for (i = 0; i < desc->hw_clks->num ; i++) { @@ -103,7 +113,10 @@ int sunxi_ccu_probe(struct device_node *node, void __iomem *reg, continue; name = hw->init->name; - ret = of_clk_hw_register(node, hw); + if (dev) + ret = clk_hw_register(dev, hw); + else + ret = of_clk_hw_register(node, hw); if (ret) { pr_err("Couldn't register clock %d - %s\n", i, name); goto err_clk_unreg; @@ -115,29 +128,22 @@ int sunxi_ccu_probe(struct device_node *node, void __iomem *reg, if (ret) goto err_clk_unreg; - reset = kzalloc(sizeof(*reset), GFP_KERNEL); - if (!reset) { - ret = -ENOMEM; - goto err_alloc_reset; - } - + reset = &ccu->reset; reset->rcdev.of_node = node; reset->rcdev.ops = &ccu_reset_ops; - reset->rcdev.owner = THIS_MODULE; + reset->rcdev.owner = dev ? dev->driver->owner : THIS_MODULE; reset->rcdev.nr_resets = desc->num_resets; reset->base = reg; - reset->lock = &ccu_lock; + reset->lock = &ccu->lock; reset->reset_map = desc->resets; ret = reset_controller_register(&reset->rcdev); if (ret) - goto err_of_clk_unreg; + goto err_del_provider; return 0; -err_of_clk_unreg: - kfree(reset); -err_alloc_reset: +err_del_provider: of_clk_del_provider(node); err_clk_unreg: while (--i >= 0) { @@ -149,3 +155,59 @@ err_clk_unreg: } return ret; } + +static void devm_sunxi_ccu_release(struct device *dev, void *res) +{ + struct sunxi_ccu *ccu = res; + const struct sunxi_ccu_desc *desc = ccu->desc; + int i; + + reset_controller_unregister(&ccu->reset.rcdev); + of_clk_del_provider(dev->of_node); + + for (i = 0; i < desc->hw_clks->num; i++) { + struct clk_hw *hw = desc->hw_clks->hws[i]; + + if (!hw) + continue; + clk_hw_unregister(hw); + } +} + +int devm_sunxi_ccu_probe(struct device *dev, void __iomem *reg, + const struct sunxi_ccu_desc *desc) +{ + struct sunxi_ccu *ccu; + int ret; + + ccu = devres_alloc(devm_sunxi_ccu_release, sizeof(*ccu), GFP_KERNEL); + if (!ccu) + return -ENOMEM; + + ret = sunxi_ccu_probe(ccu, dev, dev->of_node, reg, desc); + if (ret) { + devres_free(ccu); + return ret; + } + + devres_add(dev, ccu); + + return 0; +} + +void of_sunxi_ccu_probe(struct device_node *node, void __iomem *reg, + const struct sunxi_ccu_desc *desc) +{ + struct sunxi_ccu *ccu; + int ret; + + ccu = kzalloc(sizeof(*ccu), GFP_KERNEL); + if (!ccu) + return; + + ret = sunxi_ccu_probe(ccu, NULL, node, reg, desc); + if (ret) { + pr_err("%pOF: probing clocks failed: %d\n", node, ret); + kfree(ccu); + } +} diff --git a/drivers/clk/sunxi-ng/ccu_common.h b/drivers/clk/sunxi-ng/ccu_common.h index 04e7a12200a2..98a1834b58bb 100644 --- a/drivers/clk/sunxi-ng/ccu_common.h +++ b/drivers/clk/sunxi-ng/ccu_common.h @@ -63,7 +63,9 @@ struct ccu_pll_nb { int ccu_pll_notifier_register(struct ccu_pll_nb *pll_nb); -int sunxi_ccu_probe(struct device_node *node, void __iomem *reg, - const struct sunxi_ccu_desc *desc); +int devm_sunxi_ccu_probe(struct device *dev, void __iomem *reg, + const struct sunxi_ccu_desc *desc); +void of_sunxi_ccu_probe(struct device_node *node, void __iomem *reg, + const struct sunxi_ccu_desc *desc); #endif /* _COMMON_H_ */ diff --git a/drivers/clk/sunxi-ng/ccu_mux.h b/drivers/clk/sunxi-ng/ccu_mux.h index f165395effb5..e31efc509b3d 100644 --- a/drivers/clk/sunxi-ng/ccu_mux.h +++ b/drivers/clk/sunxi-ng/ccu_mux.h @@ -40,7 +40,6 @@ struct ccu_mux_internal { _SUNXI_CCU_MUX_TABLE(_shift, _width, NULL) struct ccu_mux { - u16 reg; u32 enable; struct ccu_mux_internal mux; diff --git a/drivers/clk/sunxi/clk-mod0.c b/drivers/clk/sunxi/clk-mod0.c index f9d715ec9908..51800289ada9 100644 --- a/drivers/clk/sunxi/clk-mod0.c +++ b/drivers/clk/sunxi/clk-mod0.c @@ -88,14 +88,12 @@ CLK_OF_DECLARE_DRIVER(sun4i_a10_mod0, "allwinner,sun4i-a10-mod0-clk", static int sun4i_a10_mod0_clk_probe(struct platform_device *pdev) { struct device_node *np = pdev->dev.of_node; - struct resource *r; void __iomem *reg; if (!np) return -ENODEV; - r = platform_get_resource(pdev, IORESOURCE_MEM, 0); - reg = devm_ioremap_resource(&pdev->dev, r); + reg = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(reg)) return PTR_ERR(reg); diff --git a/drivers/clk/sunxi/clk-sun6i-apb0-gates.c b/drivers/clk/sunxi/clk-sun6i-apb0-gates.c index 4c75b0770c74..e4cf1180b088 100644 --- a/drivers/clk/sunxi/clk-sun6i-apb0-gates.c +++ b/drivers/clk/sunxi/clk-sun6i-apb0-gates.c @@ -40,7 +40,6 @@ static int sun6i_a31_apb0_gates_clk_probe(struct platform_device *pdev) const struct gates_data *data; const char *clk_parent; const char *clk_name; - struct resource *r; void __iomem *reg; int ngates; int i; @@ -53,8 +52,7 @@ static int sun6i_a31_apb0_gates_clk_probe(struct platform_device *pdev) if (!data) return -ENODEV; - r = platform_get_resource(pdev, IORESOURCE_MEM, 0); - reg = devm_ioremap_resource(&pdev->dev, r); + reg = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(reg)) return PTR_ERR(reg); diff --git a/drivers/clk/sunxi/clk-sun6i-apb0.c b/drivers/clk/sunxi/clk-sun6i-apb0.c index 10f70c35c265..f80c67bafe38 100644 --- a/drivers/clk/sunxi/clk-sun6i-apb0.c +++ b/drivers/clk/sunxi/clk-sun6i-apb0.c @@ -32,12 +32,10 @@ static int sun6i_a31_apb0_clk_probe(struct platform_device *pdev) struct device_node *np = pdev->dev.of_node; const char *clk_name = np->name; const char *clk_parent; - struct resource *r; void __iomem *reg; struct clk *clk; - r = platform_get_resource(pdev, IORESOURCE_MEM, 0); - reg = devm_ioremap_resource(&pdev->dev, r); + reg = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(reg)) return PTR_ERR(reg); diff --git a/drivers/clk/sunxi/clk-sun6i-ar100.c b/drivers/clk/sunxi/clk-sun6i-ar100.c index 54babc2b4b9e..9f9a2cf54f41 100644 --- a/drivers/clk/sunxi/clk-sun6i-ar100.c +++ b/drivers/clk/sunxi/clk-sun6i-ar100.c @@ -71,12 +71,10 @@ static DEFINE_SPINLOCK(sun6i_ar100_lock); static int sun6i_a31_ar100_clk_probe(struct platform_device *pdev) { struct device_node *np = pdev->dev.of_node; - struct resource *r; void __iomem *reg; struct clk *clk; - r = platform_get_resource(pdev, IORESOURCE_MEM, 0); - reg = devm_ioremap_resource(&pdev->dev, r); + reg = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(reg)) return PTR_ERR(reg); diff --git a/drivers/clk/sunxi/clk-sun8i-apb0.c b/drivers/clk/sunxi/clk-sun8i-apb0.c index fc5d6e3b77d1..f605ecca879f 100644 --- a/drivers/clk/sunxi/clk-sun8i-apb0.c +++ b/drivers/clk/sunxi/clk-sun8i-apb0.c @@ -87,12 +87,10 @@ CLK_OF_DECLARE_DRIVER(sun8i_a23_apb0, "allwinner,sun8i-a23-apb0-clk", static int sun8i_a23_apb0_clk_probe(struct platform_device *pdev) { struct device_node *np = pdev->dev.of_node; - struct resource *r; void __iomem *reg; struct clk *clk; - r = platform_get_resource(pdev, IORESOURCE_MEM, 0); - reg = devm_ioremap_resource(&pdev->dev, r); + reg = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(reg)) return PTR_ERR(reg); diff --git a/include/dt-bindings/clock/exynos850.h b/include/dt-bindings/clock/exynos850.h new file mode 100644 index 000000000000..8999184f94a2 --- /dev/null +++ b/include/dt-bindings/clock/exynos850.h @@ -0,0 +1,141 @@ +/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */ +/* + * Copyright (C) 2021 Linaro Ltd. + * Author: Sam Protsenko <semen.protsenko@linaro.org> + * + * Device Tree binding constants for Exynos850 clock controller. + */ + +#ifndef _DT_BINDINGS_CLOCK_EXYNOS_850_H +#define _DT_BINDINGS_CLOCK_EXYNOS_850_H + +/* CMU_TOP */ +#define CLK_FOUT_SHARED0_PLL 1 +#define CLK_FOUT_SHARED1_PLL 2 +#define CLK_FOUT_MMC_PLL 3 +#define CLK_MOUT_SHARED0_PLL 4 +#define CLK_MOUT_SHARED1_PLL 5 +#define CLK_MOUT_MMC_PLL 6 +#define CLK_MOUT_CORE_BUS 7 +#define CLK_MOUT_CORE_CCI 8 +#define CLK_MOUT_CORE_MMC_EMBD 9 +#define CLK_MOUT_CORE_SSS 10 +#define CLK_MOUT_DPU 11 +#define CLK_MOUT_HSI_BUS 12 +#define CLK_MOUT_HSI_MMC_CARD 13 +#define CLK_MOUT_HSI_USB20DRD 14 +#define CLK_MOUT_PERI_BUS 15 +#define CLK_MOUT_PERI_UART 16 +#define CLK_MOUT_PERI_IP 17 +#define CLK_DOUT_SHARED0_DIV3 18 +#define CLK_DOUT_SHARED0_DIV2 19 +#define CLK_DOUT_SHARED1_DIV3 20 +#define CLK_DOUT_SHARED1_DIV2 21 +#define CLK_DOUT_SHARED0_DIV4 22 +#define CLK_DOUT_SHARED1_DIV4 23 +#define CLK_DOUT_CORE_BUS 24 +#define CLK_DOUT_CORE_CCI 25 +#define CLK_DOUT_CORE_MMC_EMBD 26 +#define CLK_DOUT_CORE_SSS 27 +#define CLK_DOUT_DPU 28 +#define CLK_DOUT_HSI_BUS 29 +#define CLK_DOUT_HSI_MMC_CARD 30 +#define CLK_DOUT_HSI_USB20DRD 31 +#define CLK_DOUT_PERI_BUS 32 +#define CLK_DOUT_PERI_UART 33 +#define CLK_DOUT_PERI_IP 34 +#define CLK_GOUT_CORE_BUS 35 +#define CLK_GOUT_CORE_CCI 36 +#define CLK_GOUT_CORE_MMC_EMBD 37 +#define CLK_GOUT_CORE_SSS 38 +#define CLK_GOUT_DPU 39 +#define CLK_GOUT_HSI_BUS 40 +#define CLK_GOUT_HSI_MMC_CARD 41 +#define CLK_GOUT_HSI_USB20DRD 42 +#define CLK_GOUT_PERI_BUS 43 +#define CLK_GOUT_PERI_UART 44 +#define CLK_GOUT_PERI_IP 45 +#define TOP_NR_CLK 46 + +/* CMU_HSI */ +#define CLK_MOUT_HSI_BUS_USER 1 +#define CLK_MOUT_HSI_MMC_CARD_USER 2 +#define CLK_MOUT_HSI_USB20DRD_USER 3 +#define CLK_MOUT_HSI_RTC 4 +#define CLK_GOUT_USB_RTC_CLK 5 +#define CLK_GOUT_USB_REF_CLK 6 +#define CLK_GOUT_USB_PHY_REF_CLK 7 +#define CLK_GOUT_USB_PHY_ACLK 8 +#define CLK_GOUT_USB_BUS_EARLY_CLK 9 +#define CLK_GOUT_GPIO_HSI_PCLK 10 +#define CLK_GOUT_MMC_CARD_ACLK 11 +#define CLK_GOUT_MMC_CARD_SDCLKIN 12 +#define CLK_GOUT_SYSREG_HSI_PCLK 13 +#define HSI_NR_CLK 14 + +/* CMU_PERI */ +#define CLK_MOUT_PERI_BUS_USER 1 +#define CLK_MOUT_PERI_UART_USER 2 +#define CLK_MOUT_PERI_HSI2C_USER 3 +#define CLK_MOUT_PERI_SPI_USER 4 +#define CLK_DOUT_PERI_HSI2C0 5 +#define CLK_DOUT_PERI_HSI2C1 6 +#define CLK_DOUT_PERI_HSI2C2 7 +#define CLK_DOUT_PERI_SPI0 8 +#define CLK_GOUT_PERI_HSI2C0 9 +#define CLK_GOUT_PERI_HSI2C1 10 +#define CLK_GOUT_PERI_HSI2C2 11 +#define CLK_GOUT_GPIO_PERI_PCLK 12 +#define CLK_GOUT_HSI2C0_IPCLK 13 +#define CLK_GOUT_HSI2C0_PCLK 14 +#define CLK_GOUT_HSI2C1_IPCLK 15 +#define CLK_GOUT_HSI2C1_PCLK 16 +#define CLK_GOUT_HSI2C2_IPCLK 17 +#define CLK_GOUT_HSI2C2_PCLK 18 +#define CLK_GOUT_I2C0_PCLK 19 +#define CLK_GOUT_I2C1_PCLK 20 +#define CLK_GOUT_I2C2_PCLK 21 +#define CLK_GOUT_I2C3_PCLK 22 +#define CLK_GOUT_I2C4_PCLK 23 +#define CLK_GOUT_I2C5_PCLK 24 +#define CLK_GOUT_I2C6_PCLK 25 +#define CLK_GOUT_MCT_PCLK 26 +#define CLK_GOUT_PWM_MOTOR_PCLK 27 +#define CLK_GOUT_SPI0_IPCLK 28 +#define CLK_GOUT_SPI0_PCLK 29 +#define CLK_GOUT_SYSREG_PERI_PCLK 30 +#define CLK_GOUT_UART_IPCLK 31 +#define CLK_GOUT_UART_PCLK 32 +#define CLK_GOUT_WDT0_PCLK 33 +#define CLK_GOUT_WDT1_PCLK 34 +#define PERI_NR_CLK 35 + +/* CMU_CORE */ +#define CLK_MOUT_CORE_BUS_USER 1 +#define CLK_MOUT_CORE_CCI_USER 2 +#define CLK_MOUT_CORE_MMC_EMBD_USER 3 +#define CLK_MOUT_CORE_SSS_USER 4 +#define CLK_MOUT_CORE_GIC 5 +#define CLK_DOUT_CORE_BUSP 6 +#define CLK_GOUT_CCI_ACLK 7 +#define CLK_GOUT_GIC_CLK 8 +#define CLK_GOUT_MMC_EMBD_ACLK 9 +#define CLK_GOUT_MMC_EMBD_SDCLKIN 10 +#define CLK_GOUT_SSS_ACLK 11 +#define CLK_GOUT_SSS_PCLK 12 +#define CORE_NR_CLK 13 + +/* CMU_DPU */ +#define CLK_MOUT_DPU_USER 1 +#define CLK_DOUT_DPU_BUSP 2 +#define CLK_GOUT_DPU_CMU_DPU_PCLK 3 +#define CLK_GOUT_DPU_DECON0_ACLK 4 +#define CLK_GOUT_DPU_DMA_ACLK 5 +#define CLK_GOUT_DPU_DPP_ACLK 6 +#define CLK_GOUT_DPU_PPMU_ACLK 7 +#define CLK_GOUT_DPU_PPMU_PCLK 8 +#define CLK_GOUT_DPU_SMMU_CLK 9 +#define CLK_GOUT_DPU_SYSREG_PCLK 10 +#define DPU_NR_CLK 11 + +#endif /* _DT_BINDINGS_CLOCK_EXYNOS_850_H */ diff --git a/include/dt-bindings/clock/meson8b-clkc.h b/include/dt-bindings/clock/meson8b-clkc.h index f33781338eda..78aa07fd7cc0 100644 --- a/include/dt-bindings/clock/meson8b-clkc.h +++ b/include/dt-bindings/clock/meson8b-clkc.h @@ -105,6 +105,16 @@ #define CLKID_PERIPH 126 #define CLKID_AXI 128 #define CLKID_L2_DRAM 130 +#define CLKID_HDMI_PLL_HDMI_OUT 132 +#define CLKID_VID_PLL_FINAL_DIV 137 +#define CLKID_VCLK_IN_SEL 138 +#define CLKID_VCLK2_IN_SEL 149 +#define CLKID_CTS_ENCT 161 +#define CLKID_CTS_ENCP 163 +#define CLKID_CTS_ENCI 165 +#define CLKID_HDMI_TX_PIXEL 167 +#define CLKID_CTS_ENCL 169 +#define CLKID_CTS_VDAC0 171 #define CLKID_HDMI_SYS 174 #define CLKID_VPU 190 #define CLKID_VDEC_1 196 |