1 // SPDX-License-Identifier: GPL-2.0+
6 #include <dt-bindings/clock/imx8ulp-clock.h>
9 #include <linux/module.h>
11 #include <linux/platform_device.h>
12 #include <linux/reset-controller.h>
13 #include <linux/slab.h>
17 static const char * const pll_pre_sels
[] = { "sosc", "frosc", };
18 static const char * const a35_sels
[] = { "frosc", "spll2", "sosc", "lvds", };
19 static const char * const nic_sels
[] = { "frosc", "spll3_pfd0", "sosc", "lvds", };
20 static const char * const pcc3_periph_bus_sels
[] = { "dummy", "lposc", "sosc_div2",
21 "frosc_div2", "xbar_divbus", "spll3_pfd1_div1",
22 "spll3_pfd0_div2", "spll3_pfd0_div1", };
23 static const char * const pcc4_periph_bus_sels
[] = { "dummy", "dummy", "lposc",
24 "sosc_div2", "frosc_div2", "xbar_divbus",
25 "spll3_vcodiv", "spll3_pfd0_div1", };
26 static const char * const pcc4_periph_plat_sels
[] = { "dummy", "sosc_div1", "frosc_div1",
27 "spll3_pfd3_div2", "spll3_pfd3_div1",
28 "spll3_pfd2_div2", "spll3_pfd2_div1",
30 static const char * const pcc5_periph_bus_sels
[] = { "dummy", "dummy", "lposc",
31 "sosc_div2", "frosc_div2", "lpav_bus_clk",
32 "pll4_vcodiv", "pll4_pfd3_div1", };
33 static const char * const pcc5_periph_plat_sels
[] = { "dummy", "pll4_pfd3_div2", "pll4_pfd2_div2",
34 "pll4_pfd2_div1", "pll4_pfd1_div2",
35 "pll4_pfd1_div1", "pll4_pfd0_div2",
37 static const char * const hifi_sels
[] = { "frosc", "pll4", "pll4_pfd0", "sosc",
38 "lvds", "dummy", "dummy", "dummy", };
39 static const char * const ddr_sels
[] = { "frosc", "pll4_pfd1", "sosc", "lvds",
40 "pll4", "pll4", "pll4", "pll4", };
41 static const char * const lpav_sels
[] = { "frosc", "pll4_pfd1", "sosc", "lvds", };
42 static const char * const sai45_sels
[] = { "spll3_pfd1_div1", "aud_clk1", "aud_clk2", "sosc", };
43 static const char * const sai67_sels
[] = { "spll1_pfd2_div", "spll3_pfd1_div1", "aud_clk0", "aud_clk1", "aud_clk2", "sosc", "dummy", "dummy", };
44 static const char * const aud_clk1_sels
[] = { "ext_aud_mclk2", "sai4_rx_bclk", "sai4_tx_bclk", "sai5_rx_bclk", "sai5_tx_bclk", "dummy", "dummy", "dummy", };
45 static const char * const aud_clk2_sels
[] = { "ext_aud_mclk3", "sai6_rx_bclk", "sai6_tx_bclk", "sai7_rx_bclk", "sai7_tx_bclk", "spdif_rx", "dummy", "dummy", };
46 static const char * const enet_ts_sels
[] = { "ext_rmii_clk", "ext_ts_clk", "rosc", "ext_aud_mclk", "sosc", "dummy", "dummy", "dummy"};
47 static const char * const xbar_divbus
[] = { "xbar_divbus" };
48 static const char * const nic_per_divplat
[] = { "nic_per_divplat" };
49 static const char * const lpav_axi_div
[] = { "lpav_axi_div" };
50 static const char * const lpav_bus_div
[] = { "lpav_bus_div" };
52 struct pcc_reset_dev
{
54 struct reset_controller_dev rcdev
;
56 /* Set to imx_ccm_lock to protect register access shared with clock control */
60 #define PCC_SW_RST BIT(28)
61 #define to_pcc_reset_dev(_rcdev) container_of(_rcdev, struct pcc_reset_dev, rcdev)
63 static const u32 pcc3_resets
[] = {
64 0xa8, 0xac, 0xc8, 0xcc, 0xd0,
65 0xd4, 0xd8, 0xdc, 0xe0, 0xe4,
69 static const u32 pcc4_resets
[] = {
70 0x4, 0x8, 0xc, 0x10, 0x14,
71 0x18, 0x1c, 0x20, 0x24, 0x34,
72 0x38, 0x3c, 0x40, 0x44, 0x48,
76 static const u32 pcc5_resets
[] = {
77 0xa0, 0xa4, 0xa8, 0xac, 0xb0,
78 0xb4, 0xbc, 0xc0, 0xc8, 0xcc,
79 0xd0, 0xf0, 0xf4, 0xf8
82 static int imx8ulp_pcc_assert(struct reset_controller_dev
*rcdev
, unsigned long id
)
84 struct pcc_reset_dev
*pcc_reset
= to_pcc_reset_dev(rcdev
);
85 u32 offset
= pcc_reset
->resets
[id
];
89 spin_lock_irqsave(pcc_reset
->lock
, flags
);
91 val
= readl(pcc_reset
->base
+ offset
);
93 writel(val
, pcc_reset
->base
+ offset
);
95 spin_unlock_irqrestore(pcc_reset
->lock
, flags
);
100 static int imx8ulp_pcc_deassert(struct reset_controller_dev
*rcdev
, unsigned long id
)
102 struct pcc_reset_dev
*pcc_reset
= to_pcc_reset_dev(rcdev
);
103 u32 offset
= pcc_reset
->resets
[id
];
107 spin_lock_irqsave(pcc_reset
->lock
, flags
);
109 val
= readl(pcc_reset
->base
+ offset
);
111 writel(val
, pcc_reset
->base
+ offset
);
113 spin_unlock_irqrestore(pcc_reset
->lock
, flags
);
118 static const struct reset_control_ops imx8ulp_pcc_reset_ops
= {
119 .assert = imx8ulp_pcc_assert
,
120 .deassert
= imx8ulp_pcc_deassert
,
123 static int imx8ulp_pcc_reset_init(struct platform_device
*pdev
, void __iomem
*base
,
124 const u32
*resets
, unsigned int nr_resets
)
126 struct device_node
*np
= pdev
->dev
.of_node
;
127 struct device
*dev
= &pdev
->dev
;
128 struct pcc_reset_dev
*pcc_reset
;
130 pcc_reset
= devm_kzalloc(dev
, sizeof(*pcc_reset
), GFP_KERNEL
);
134 pcc_reset
->base
= base
;
135 pcc_reset
->lock
= &imx_ccm_lock
;
136 pcc_reset
->resets
= resets
;
137 pcc_reset
->rcdev
.owner
= THIS_MODULE
;
138 pcc_reset
->rcdev
.nr_resets
= nr_resets
;
139 pcc_reset
->rcdev
.ops
= &imx8ulp_pcc_reset_ops
;
140 pcc_reset
->rcdev
.of_node
= np
;
142 return devm_reset_controller_register(dev
, &pcc_reset
->rcdev
);
145 static int imx8ulp_clk_cgc1_init(struct platform_device
*pdev
)
147 struct device
*dev
= &pdev
->dev
;
148 struct clk_hw_onecell_data
*clk_data
;
149 struct clk_hw
**clks
;
152 clk_data
= devm_kzalloc(dev
, struct_size(clk_data
, hws
, IMX8ULP_CLK_CGC1_END
),
157 clk_data
->num
= IMX8ULP_CLK_CGC1_END
;
158 clks
= clk_data
->hws
;
160 clks
[IMX8ULP_CLK_DUMMY
] = imx_clk_hw_fixed("dummy", 0);
163 base
= devm_platform_ioremap_resource(pdev
, 0);
164 if (WARN_ON(IS_ERR(base
)))
165 return PTR_ERR(base
);
167 clks
[IMX8ULP_CLK_SPLL2_PRE_SEL
] = imx_clk_hw_mux_flags("spll2_pre_sel", base
+ 0x510, 0, 1, pll_pre_sels
, ARRAY_SIZE(pll_pre_sels
), CLK_SET_PARENT_GATE
);
168 clks
[IMX8ULP_CLK_SPLL3_PRE_SEL
] = imx_clk_hw_mux_flags("spll3_pre_sel", base
+ 0x610, 0, 1, pll_pre_sels
, ARRAY_SIZE(pll_pre_sels
), CLK_SET_PARENT_GATE
);
170 clks
[IMX8ULP_CLK_SPLL2
] = imx_clk_hw_pllv4(IMX_PLLV4_IMX8ULP_1GHZ
, "spll2", "spll2_pre_sel", base
+ 0x500);
171 clks
[IMX8ULP_CLK_SPLL3
] = imx_clk_hw_pllv4(IMX_PLLV4_IMX8ULP
, "spll3", "spll3_pre_sel", base
+ 0x600);
172 clks
[IMX8ULP_CLK_SPLL3_VCODIV
] = imx_clk_hw_divider("spll3_vcodiv", "spll3", base
+ 0x604, 0, 6);
174 clks
[IMX8ULP_CLK_SPLL3_PFD0
] = imx_clk_hw_pfdv2(IMX_PFDV2_IMX8ULP
, "spll3_pfd0", "spll3_vcodiv", base
+ 0x614, 0);
175 clks
[IMX8ULP_CLK_SPLL3_PFD1
] = imx_clk_hw_pfdv2(IMX_PFDV2_IMX8ULP
, "spll3_pfd1", "spll3_vcodiv", base
+ 0x614, 1);
176 clks
[IMX8ULP_CLK_SPLL3_PFD2
] = imx_clk_hw_pfdv2(IMX_PFDV2_IMX8ULP
, "spll3_pfd2", "spll3_vcodiv", base
+ 0x614, 2);
177 clks
[IMX8ULP_CLK_SPLL3_PFD3
] = imx_clk_hw_pfdv2(IMX_PFDV2_IMX8ULP
, "spll3_pfd3", "spll3_vcodiv", base
+ 0x614, 3);
179 clks
[IMX8ULP_CLK_SPLL3_PFD0_DIV1_GATE
] = imx_clk_hw_gate_dis("spll3_pfd0_div1_gate", "spll3_pfd0", base
+ 0x608, 7);
180 clks
[IMX8ULP_CLK_SPLL3_PFD0_DIV2_GATE
] = imx_clk_hw_gate_dis("spll3_pfd0_div2_gate", "spll3_pfd0", base
+ 0x608, 15);
181 clks
[IMX8ULP_CLK_SPLL3_PFD1_DIV1_GATE
] = imx_clk_hw_gate_dis("spll3_pfd1_div1_gate", "spll3_pfd1", base
+ 0x608, 23);
182 clks
[IMX8ULP_CLK_SPLL3_PFD1_DIV2_GATE
] = imx_clk_hw_gate_dis("spll3_pfd1_div2_gate", "spll3_pfd1", base
+ 0x608, 31);
183 clks
[IMX8ULP_CLK_SPLL3_PFD2_DIV1_GATE
] = imx_clk_hw_gate_dis("spll3_pfd2_div1_gate", "spll3_pfd2", base
+ 0x60c, 7);
184 clks
[IMX8ULP_CLK_SPLL3_PFD2_DIV2_GATE
] = imx_clk_hw_gate_dis("spll3_pfd2_div2_gate", "spll3_pfd2", base
+ 0x60c, 15);
185 clks
[IMX8ULP_CLK_SPLL3_PFD3_DIV1_GATE
] = imx_clk_hw_gate_dis("spll3_pfd3_div1_gate", "spll3_pfd3", base
+ 0x60c, 23);
186 clks
[IMX8ULP_CLK_SPLL3_PFD3_DIV2_GATE
] = imx_clk_hw_gate_dis("spll3_pfd3_div2_gate", "spll3_pfd3", base
+ 0x60c, 31);
187 clks
[IMX8ULP_CLK_SPLL3_PFD0_DIV1
] = imx_clk_hw_divider("spll3_pfd0_div1", "spll3_pfd0_div1_gate", base
+ 0x608, 0, 6);
188 clks
[IMX8ULP_CLK_SPLL3_PFD0_DIV2
] = imx_clk_hw_divider("spll3_pfd0_div2", "spll3_pfd0_div2_gate", base
+ 0x608, 8, 6);
189 clks
[IMX8ULP_CLK_SPLL3_PFD1_DIV1
] = imx_clk_hw_divider("spll3_pfd1_div1", "spll3_pfd1_div1_gate", base
+ 0x608, 16, 6);
190 clks
[IMX8ULP_CLK_SPLL3_PFD1_DIV2
] = imx_clk_hw_divider("spll3_pfd1_div2", "spll3_pfd1_div2_gate", base
+ 0x608, 24, 6);
191 clks
[IMX8ULP_CLK_SPLL3_PFD2_DIV1
] = imx_clk_hw_divider("spll3_pfd2_div1", "spll3_pfd2_div1_gate", base
+ 0x60c, 0, 6);
192 clks
[IMX8ULP_CLK_SPLL3_PFD2_DIV2
] = imx_clk_hw_divider("spll3_pfd2_div2", "spll3_pfd2_div2_gate", base
+ 0x60c, 8, 6);
193 clks
[IMX8ULP_CLK_SPLL3_PFD3_DIV1
] = imx_clk_hw_divider("spll3_pfd3_div1", "spll3_pfd3_div1_gate", base
+ 0x60c, 16, 6);
194 clks
[IMX8ULP_CLK_SPLL3_PFD3_DIV2
] = imx_clk_hw_divider("spll3_pfd3_div2", "spll3_pfd3_div2_gate", base
+ 0x60c, 24, 6);
196 clks
[IMX8ULP_CLK_A35_SEL
] = imx_clk_hw_mux2("a35_sel", base
+ 0x14, 28, 2, a35_sels
, ARRAY_SIZE(a35_sels
));
197 clks
[IMX8ULP_CLK_A35_DIV
] = imx_clk_hw_divider_flags("a35_div", "a35_sel", base
+ 0x14, 21, 6, CLK_SET_RATE_PARENT
| CLK_IS_CRITICAL
);
199 clks
[IMX8ULP_CLK_NIC_SEL
] = imx_clk_hw_mux2("nic_sel", base
+ 0x34, 28, 2, nic_sels
, ARRAY_SIZE(nic_sels
));
200 clks
[IMX8ULP_CLK_NIC_AD_DIVPLAT
] = imx_clk_hw_divider_flags("nic_ad_divplat", "nic_sel", base
+ 0x34, 21, 6, CLK_SET_RATE_PARENT
| CLK_IS_CRITICAL
);
201 clks
[IMX8ULP_CLK_NIC_PER_DIVPLAT
] = imx_clk_hw_divider_flags("nic_per_divplat", "nic_ad_divplat", base
+ 0x34, 14, 6, CLK_SET_RATE_PARENT
);
202 clks
[IMX8ULP_CLK_XBAR_AD_DIVPLAT
] = imx_clk_hw_divider_flags("xbar_ad_divplat", "nic_ad_divplat", base
+ 0x38, 14, 6, CLK_SET_RATE_PARENT
);
203 clks
[IMX8ULP_CLK_XBAR_DIVBUS
] = imx_clk_hw_divider_flags("xbar_divbus", "xbar_ad_divplat", base
+ 0x38, 7, 6, CLK_SET_RATE_PARENT
);
204 clks
[IMX8ULP_CLK_XBAR_AD_SLOW
] = imx_clk_hw_divider_flags("xbar_ad_slow", "xbar_divbus", base
+ 0x38, 0, 6, CLK_SET_RATE_PARENT
);
206 clks
[IMX8ULP_CLK_SOSC_DIV1_GATE
] = imx_clk_hw_gate_dis("sosc_div1_gate", "sosc", base
+ 0x108, 7);
207 clks
[IMX8ULP_CLK_SOSC_DIV2_GATE
] = imx_clk_hw_gate_dis("sosc_div2_gate", "sosc", base
+ 0x108, 15);
208 clks
[IMX8ULP_CLK_SOSC_DIV3_GATE
] = imx_clk_hw_gate_dis("sosc_div3_gate", "sosc", base
+ 0x108, 23);
209 clks
[IMX8ULP_CLK_SOSC_DIV1
] = imx_clk_hw_divider("sosc_div1", "sosc_div1_gate", base
+ 0x108, 0, 6);
210 clks
[IMX8ULP_CLK_SOSC_DIV2
] = imx_clk_hw_divider("sosc_div2", "sosc_div2_gate", base
+ 0x108, 8, 6);
211 clks
[IMX8ULP_CLK_SOSC_DIV3
] = imx_clk_hw_divider("sosc_div3", "sosc_div3_gate", base
+ 0x108, 16, 6);
213 clks
[IMX8ULP_CLK_FROSC_DIV1_GATE
] = imx_clk_hw_gate_dis("frosc_div1_gate", "frosc", base
+ 0x208, 7);
214 clks
[IMX8ULP_CLK_FROSC_DIV2_GATE
] = imx_clk_hw_gate_dis("frosc_div2_gate", "frosc", base
+ 0x208, 15);
215 clks
[IMX8ULP_CLK_FROSC_DIV3_GATE
] = imx_clk_hw_gate_dis("frosc_div3_gate", "frosc", base
+ 0x208, 23);
216 clks
[IMX8ULP_CLK_FROSC_DIV1
] = imx_clk_hw_divider("frosc_div1", "frosc_div1_gate", base
+ 0x208, 0, 6);
217 clks
[IMX8ULP_CLK_FROSC_DIV2
] = imx_clk_hw_divider("frosc_div2", "frosc_div2_gate", base
+ 0x208, 8, 6);
218 clks
[IMX8ULP_CLK_FROSC_DIV3
] = imx_clk_hw_divider("frosc_div3", "frosc_div3_gate", base
+ 0x208, 16, 6);
219 clks
[IMX8ULP_CLK_AUD_CLK1
] = imx_clk_hw_mux2("aud_clk1", base
+ 0x900, 0, 3, aud_clk1_sels
, ARRAY_SIZE(aud_clk1_sels
));
220 clks
[IMX8ULP_CLK_SAI4_SEL
] = imx_clk_hw_mux2("sai4_sel", base
+ 0x904, 0, 2, sai45_sels
, ARRAY_SIZE(sai45_sels
));
221 clks
[IMX8ULP_CLK_SAI5_SEL
] = imx_clk_hw_mux2("sai5_sel", base
+ 0x904, 8, 2, sai45_sels
, ARRAY_SIZE(sai45_sels
));
222 clks
[IMX8ULP_CLK_ENET_TS_SEL
] = imx_clk_hw_mux2("enet_ts", base
+ 0x700, 24, 3, enet_ts_sels
, ARRAY_SIZE(enet_ts_sels
));
224 imx_check_clk_hws(clks
, clk_data
->num
);
226 return devm_of_clk_add_hw_provider(dev
, of_clk_hw_onecell_get
, clk_data
);
229 static int imx8ulp_clk_cgc2_init(struct platform_device
*pdev
)
231 struct device
*dev
= &pdev
->dev
;
232 struct clk_hw_onecell_data
*clk_data
;
233 struct clk_hw
**clks
;
236 clk_data
= devm_kzalloc(dev
, struct_size(clk_data
, hws
, IMX8ULP_CLK_CGC2_END
),
241 clk_data
->num
= IMX8ULP_CLK_CGC2_END
;
242 clks
= clk_data
->hws
;
245 base
= devm_platform_ioremap_resource(pdev
, 0);
246 if (WARN_ON(IS_ERR(base
)))
247 return PTR_ERR(base
);
249 clks
[IMX8ULP_CLK_PLL4_PRE_SEL
] = imx_clk_hw_mux_flags("pll4_pre_sel", base
+ 0x610, 0, 1, pll_pre_sels
, ARRAY_SIZE(pll_pre_sels
), CLK_SET_PARENT_GATE
);
251 clks
[IMX8ULP_CLK_PLL4
] = imx_clk_hw_pllv4(IMX_PLLV4_IMX8ULP
, "pll4", "pll4_pre_sel", base
+ 0x600);
252 clks
[IMX8ULP_CLK_PLL4_VCODIV
] = imx_clk_hw_divider("pll4_vcodiv", "pll4", base
+ 0x604, 0, 6);
254 clks
[IMX8ULP_CLK_HIFI_SEL
] = imx_clk_hw_mux_flags("hifi_sel", base
+ 0x14, 28, 3, hifi_sels
, ARRAY_SIZE(hifi_sels
), CLK_SET_PARENT_GATE
);
255 clks
[IMX8ULP_CLK_HIFI_DIVCORE
] = imx_clk_hw_divider("hifi_core_div", "hifi_sel", base
+ 0x14, 21, 6);
256 clks
[IMX8ULP_CLK_HIFI_DIVPLAT
] = imx_clk_hw_divider("hifi_plat_div", "hifi_core_div", base
+ 0x14, 14, 6);
258 clks
[IMX8ULP_CLK_DDR_SEL
] = imx_clk_hw_mux_flags("ddr_sel", base
+ 0x40, 28, 3, ddr_sels
, ARRAY_SIZE(ddr_sels
), CLK_GET_RATE_NOCACHE
);
259 clks
[IMX8ULP_CLK_DDR_DIV
] = imx_clk_hw_divider_flags("ddr_div", "ddr_sel", base
+ 0x40, 21, 6, CLK_IS_CRITICAL
| CLK_GET_RATE_NOCACHE
);
260 clks
[IMX8ULP_CLK_LPAV_AXI_SEL
] = imx_clk_hw_mux2("lpav_sel", base
+ 0x3c, 28, 2, lpav_sels
, ARRAY_SIZE(lpav_sels
));
261 clks
[IMX8ULP_CLK_LPAV_AXI_DIV
] = imx_clk_hw_divider_flags("lpav_axi_div", "lpav_sel", base
+ 0x3c, 21, 6, CLK_IS_CRITICAL
);
262 clks
[IMX8ULP_CLK_LPAV_AHB_DIV
] = imx_clk_hw_divider_flags("lpav_ahb_div", "lpav_axi_div", base
+ 0x3c, 14, 6, CLK_IS_CRITICAL
);
263 clks
[IMX8ULP_CLK_LPAV_BUS_DIV
] = imx_clk_hw_divider_flags("lpav_bus_div", "lpav_axi_div", base
+ 0x3c, 7, 6, CLK_IS_CRITICAL
);
265 clks
[IMX8ULP_CLK_PLL4_PFD0
] = imx_clk_hw_pfdv2(IMX_PFDV2_IMX8ULP
, "pll4_pfd0", "pll4_vcodiv", base
+ 0x614, 0);
266 clks
[IMX8ULP_CLK_PLL4_PFD1
] = imx_clk_hw_pfdv2(IMX_PFDV2_IMX8ULP
, "pll4_pfd1", "pll4_vcodiv", base
+ 0x614, 1);
267 clks
[IMX8ULP_CLK_PLL4_PFD2
] = imx_clk_hw_pfdv2(IMX_PFDV2_IMX8ULP
, "pll4_pfd2", "pll4_vcodiv", base
+ 0x614, 2);
268 clks
[IMX8ULP_CLK_PLL4_PFD3
] = imx_clk_hw_pfdv2(IMX_PFDV2_IMX8ULP
, "pll4_pfd3", "pll4_vcodiv", base
+ 0x614, 3);
270 clks
[IMX8ULP_CLK_PLL4_PFD0_DIV1_GATE
] = imx_clk_hw_gate_dis("pll4_pfd0_div1_gate", "pll4_pfd0", base
+ 0x608, 7);
271 clks
[IMX8ULP_CLK_PLL4_PFD0_DIV2_GATE
] = imx_clk_hw_gate_dis("pll4_pfd0_div2_gate", "pll4_pfd0", base
+ 0x608, 15);
272 clks
[IMX8ULP_CLK_PLL4_PFD1_DIV1_GATE
] = imx_clk_hw_gate_dis("pll4_pfd1_div1_gate", "pll4_pfd1", base
+ 0x608, 23);
273 clks
[IMX8ULP_CLK_PLL4_PFD1_DIV2_GATE
] = imx_clk_hw_gate_dis("pll4_pfd1_div2_gate", "pll4_pfd1", base
+ 0x608, 31);
274 clks
[IMX8ULP_CLK_PLL4_PFD2_DIV1_GATE
] = imx_clk_hw_gate_dis("pll4_pfd2_div1_gate", "pll4_pfd2", base
+ 0x60c, 7);
275 clks
[IMX8ULP_CLK_PLL4_PFD2_DIV2_GATE
] = imx_clk_hw_gate_dis("pll4_pfd2_div2_gate", "pll4_pfd2", base
+ 0x60c, 15);
276 clks
[IMX8ULP_CLK_PLL4_PFD3_DIV1_GATE
] = imx_clk_hw_gate_dis("pll4_pfd3_div1_gate", "pll4_pfd3", base
+ 0x60c, 23);
277 clks
[IMX8ULP_CLK_PLL4_PFD3_DIV2_GATE
] = imx_clk_hw_gate_dis("pll4_pfd3_div2_gate", "pll4_pfd3", base
+ 0x60c, 31);
278 clks
[IMX8ULP_CLK_PLL4_PFD0_DIV1
] = imx_clk_hw_divider_closest("pll4_pfd0_div1", "pll4_pfd0_div1_gate", base
+ 0x608, 0, 6);
279 clks
[IMX8ULP_CLK_PLL4_PFD0_DIV2
] = imx_clk_hw_divider_closest("pll4_pfd0_div2", "pll4_pfd0_div2_gate", base
+ 0x608, 8, 6);
280 clks
[IMX8ULP_CLK_PLL4_PFD1_DIV1
] = imx_clk_hw_divider_closest("pll4_pfd1_div1", "pll4_pfd1_div1_gate", base
+ 0x608, 16, 6);
281 clks
[IMX8ULP_CLK_PLL4_PFD1_DIV2
] = imx_clk_hw_divider_closest("pll4_pfd1_div2", "pll4_pfd1_div2_gate", base
+ 0x608, 24, 6);
282 clks
[IMX8ULP_CLK_PLL4_PFD2_DIV1
] = imx_clk_hw_divider_closest("pll4_pfd2_div1", "pll4_pfd2_div1_gate", base
+ 0x60c, 0, 6);
283 clks
[IMX8ULP_CLK_PLL4_PFD2_DIV2
] = imx_clk_hw_divider_closest("pll4_pfd2_div2", "pll4_pfd2_div2_gate", base
+ 0x60c, 8, 6);
284 clks
[IMX8ULP_CLK_PLL4_PFD3_DIV1
] = imx_clk_hw_divider_closest("pll4_pfd3_div1", "pll4_pfd3_div1_gate", base
+ 0x60c, 16, 6);
285 clks
[IMX8ULP_CLK_PLL4_PFD3_DIV2
] = imx_clk_hw_divider_closest("pll4_pfd3_div2", "pll4_pfd3_div2_gate", base
+ 0x60c, 24, 6);
287 clks
[IMX8ULP_CLK_CGC2_SOSC_DIV1_GATE
] = imx_clk_hw_gate_dis("cgc2_sosc_div1_gate", "sosc", base
+ 0x108, 7);
288 clks
[IMX8ULP_CLK_CGC2_SOSC_DIV2_GATE
] = imx_clk_hw_gate_dis("cgc2_sosc_div2_gate", "sosc", base
+ 0x108, 15);
289 clks
[IMX8ULP_CLK_CGC2_SOSC_DIV3_GATE
] = imx_clk_hw_gate_dis("cgc2_sosc_div3_gate", "sosc", base
+ 0x108, 23);
290 clks
[IMX8ULP_CLK_CGC2_SOSC_DIV1
] = imx_clk_hw_divider("cgc2_sosc_div1", "cgc2_sosc_div1_gate", base
+ 0x108, 0, 6);
291 clks
[IMX8ULP_CLK_CGC2_SOSC_DIV2
] = imx_clk_hw_divider("cgc2_sosc_div2", "cgc2_sosc_div2_gate", base
+ 0x108, 8, 6);
292 clks
[IMX8ULP_CLK_CGC2_SOSC_DIV3
] = imx_clk_hw_divider("cgc2_sosc_div3", "cgc2_sosc_div3_gate", base
+ 0x108, 16, 6);
294 clks
[IMX8ULP_CLK_CGC2_FROSC_DIV1_GATE
] = imx_clk_hw_gate_dis("cgc2_frosc_div1_gate", "frosc", base
+ 0x208, 7);
295 clks
[IMX8ULP_CLK_CGC2_FROSC_DIV2_GATE
] = imx_clk_hw_gate_dis("cgc2_frosc_div2_gate", "frosc", base
+ 0x208, 15);
296 clks
[IMX8ULP_CLK_CGC2_FROSC_DIV3_GATE
] = imx_clk_hw_gate_dis("cgc2_frosc_div3_gate", "frosc", base
+ 0x208, 23);
297 clks
[IMX8ULP_CLK_CGC2_FROSC_DIV1
] = imx_clk_hw_divider("cgc2_frosc_div1", "cgc2_frosc_div1_gate", base
+ 0x208, 0, 6);
298 clks
[IMX8ULP_CLK_CGC2_FROSC_DIV2
] = imx_clk_hw_divider("cgc2_frosc_div2", "cgc2_frosc_div2_gate", base
+ 0x208, 8, 6);
299 clks
[IMX8ULP_CLK_CGC2_FROSC_DIV3
] = imx_clk_hw_divider("cgc2_frosc_div3", "cgc2_frosc_div3_gate", base
+ 0x208, 16, 6);
300 clks
[IMX8ULP_CLK_AUD_CLK2
] = imx_clk_hw_mux2("aud_clk2", base
+ 0x900, 0, 3, aud_clk2_sels
, ARRAY_SIZE(aud_clk2_sels
));
301 clks
[IMX8ULP_CLK_SAI6_SEL
] = imx_clk_hw_mux2("sai6_sel", base
+ 0x904, 0, 3, sai67_sels
, ARRAY_SIZE(sai67_sels
));
302 clks
[IMX8ULP_CLK_SAI7_SEL
] = imx_clk_hw_mux2("sai7_sel", base
+ 0x904, 8, 3, sai67_sels
, ARRAY_SIZE(sai67_sels
));
303 clks
[IMX8ULP_CLK_SPDIF_SEL
] = imx_clk_hw_mux2("spdif_sel", base
+ 0x910, 0, 3, sai67_sels
, ARRAY_SIZE(sai67_sels
));
304 clks
[IMX8ULP_CLK_DSI_PHY_REF
] = imx_clk_hw_fixed("dsi_phy_ref", 24000000);
306 imx_check_clk_hws(clks
, clk_data
->num
);
308 return devm_of_clk_add_hw_provider(dev
, of_clk_hw_onecell_get
, clk_data
);
311 static int imx8ulp_clk_pcc3_init(struct platform_device
*pdev
)
313 struct device
*dev
= &pdev
->dev
;
314 struct clk_hw_onecell_data
*clk_data
;
315 struct clk_hw
**clks
;
319 clk_data
= devm_kzalloc(dev
, struct_size(clk_data
, hws
, IMX8ULP_CLK_PCC3_END
),
324 clk_data
->num
= IMX8ULP_CLK_PCC3_END
;
325 clks
= clk_data
->hws
;
328 base
= devm_platform_ioremap_resource(pdev
, 0);
329 if (WARN_ON(IS_ERR(base
)))
330 return PTR_ERR(base
);
332 clks
[IMX8ULP_CLK_WDOG3
] = imx8ulp_clk_hw_composite("wdog3", pcc3_periph_bus_sels
, ARRAY_SIZE(pcc3_periph_bus_sels
), true, true, true, base
+ 0xa8, 1);
333 clks
[IMX8ULP_CLK_WDOG4
] = imx8ulp_clk_hw_composite("wdog4", pcc3_periph_bus_sels
, ARRAY_SIZE(pcc3_periph_bus_sels
), true, true, true, base
+ 0xac, 1);
334 clks
[IMX8ULP_CLK_LPIT1
] = imx8ulp_clk_hw_composite("lpit1", pcc3_periph_bus_sels
, ARRAY_SIZE(pcc3_periph_bus_sels
), true, true, true, base
+ 0xc8, 1);
335 clks
[IMX8ULP_CLK_TPM4
] = imx8ulp_clk_hw_composite("tpm4", pcc3_periph_bus_sels
, ARRAY_SIZE(pcc3_periph_bus_sels
), true, true, true, base
+ 0xcc, 1);
336 clks
[IMX8ULP_CLK_FLEXIO1
] = imx8ulp_clk_hw_composite("flexio1", pcc3_periph_bus_sels
, ARRAY_SIZE(pcc3_periph_bus_sels
), true, true, true, base
+ 0xd4, 1);
337 clks
[IMX8ULP_CLK_I3C2
] = imx8ulp_clk_hw_composite("i3c2", pcc3_periph_bus_sels
, ARRAY_SIZE(pcc3_periph_bus_sels
), true, true, true, base
+ 0xd8, 1);
338 clks
[IMX8ULP_CLK_LPI2C4
] = imx8ulp_clk_hw_composite("lpi2c4", pcc3_periph_bus_sels
, ARRAY_SIZE(pcc3_periph_bus_sels
), true, true, true, base
+ 0xdc, 1);
339 clks
[IMX8ULP_CLK_LPI2C5
] = imx8ulp_clk_hw_composite("lpi2c5", pcc3_periph_bus_sels
, ARRAY_SIZE(pcc3_periph_bus_sels
), true, true, true, base
+ 0xe0, 1);
340 clks
[IMX8ULP_CLK_LPUART4
] = imx8ulp_clk_hw_composite("lpuart4", pcc3_periph_bus_sels
, ARRAY_SIZE(pcc3_periph_bus_sels
), true, true, true, base
+ 0xe4, 1);
341 clks
[IMX8ULP_CLK_LPUART5
] = imx8ulp_clk_hw_composite("lpuart5", pcc3_periph_bus_sels
, ARRAY_SIZE(pcc3_periph_bus_sels
), true, true, true, base
+ 0xe8, 1);
342 clks
[IMX8ULP_CLK_LPSPI4
] = imx8ulp_clk_hw_composite("lpspi4", pcc3_periph_bus_sels
, ARRAY_SIZE(pcc3_periph_bus_sels
), true, true, true, base
+ 0xec, 1);
343 clks
[IMX8ULP_CLK_LPSPI5
] = imx8ulp_clk_hw_composite("lpspi5", pcc3_periph_bus_sels
, ARRAY_SIZE(pcc3_periph_bus_sels
), true, true, true, base
+ 0xf0, 1);
345 clks
[IMX8ULP_CLK_DMA1_MP
] = imx_clk_hw_gate("pcc_dma1_mp", "xbar_ad_divplat", base
+ 0x4, 30);
346 clks
[IMX8ULP_CLK_DMA1_CH0
] = imx_clk_hw_gate("pcc_dma1_ch0", "xbar_ad_divplat", base
+ 0x8, 30);
347 clks
[IMX8ULP_CLK_DMA1_CH1
] = imx_clk_hw_gate("pcc_dma1_ch1", "xbar_ad_divplat", base
+ 0xc, 30);
348 clks
[IMX8ULP_CLK_DMA1_CH2
] = imx_clk_hw_gate("pcc_dma1_ch2", "xbar_ad_divplat", base
+ 0x10, 30);
349 clks
[IMX8ULP_CLK_DMA1_CH3
] = imx_clk_hw_gate("pcc_dma1_ch3", "xbar_ad_divplat", base
+ 0x14, 30);
350 clks
[IMX8ULP_CLK_DMA1_CH4
] = imx_clk_hw_gate("pcc_dma1_ch4", "xbar_ad_divplat", base
+ 0x18, 30);
351 clks
[IMX8ULP_CLK_DMA1_CH5
] = imx_clk_hw_gate("pcc_dma1_ch5", "xbar_ad_divplat", base
+ 0x1c, 30);
352 clks
[IMX8ULP_CLK_DMA1_CH6
] = imx_clk_hw_gate("pcc_dma1_ch6", "xbar_ad_divplat", base
+ 0x20, 30);
353 clks
[IMX8ULP_CLK_DMA1_CH7
] = imx_clk_hw_gate("pcc_dma1_ch7", "xbar_ad_divplat", base
+ 0x24, 30);
354 clks
[IMX8ULP_CLK_DMA1_CH8
] = imx_clk_hw_gate("pcc_dma1_ch8", "xbar_ad_divplat", base
+ 0x28, 30);
355 clks
[IMX8ULP_CLK_DMA1_CH9
] = imx_clk_hw_gate("pcc_dma1_ch9", "xbar_ad_divplat", base
+ 0x2c, 30);
356 clks
[IMX8ULP_CLK_DMA1_CH10
] = imx_clk_hw_gate("pcc_dma1_ch10", "xbar_ad_divplat", base
+ 0x30, 30);
357 clks
[IMX8ULP_CLK_DMA1_CH11
] = imx_clk_hw_gate("pcc_dma1_ch11", "xbar_ad_divplat", base
+ 0x34, 30);
358 clks
[IMX8ULP_CLK_DMA1_CH12
] = imx_clk_hw_gate("pcc_dma1_ch12", "xbar_ad_divplat", base
+ 0x38, 30);
359 clks
[IMX8ULP_CLK_DMA1_CH13
] = imx_clk_hw_gate("pcc_dma1_ch13", "xbar_ad_divplat", base
+ 0x3c, 30);
360 clks
[IMX8ULP_CLK_DMA1_CH14
] = imx_clk_hw_gate("pcc_dma1_ch14", "xbar_ad_divplat", base
+ 0x40, 30);
361 clks
[IMX8ULP_CLK_DMA1_CH15
] = imx_clk_hw_gate("pcc_dma1_ch15", "xbar_ad_divplat", base
+ 0x44, 30);
362 clks
[IMX8ULP_CLK_DMA1_CH16
] = imx_clk_hw_gate("pcc_dma1_ch16", "xbar_ad_divplat", base
+ 0x48, 30);
363 clks
[IMX8ULP_CLK_DMA1_CH17
] = imx_clk_hw_gate("pcc_dma1_ch17", "xbar_ad_divplat", base
+ 0x4c, 30);
364 clks
[IMX8ULP_CLK_DMA1_CH18
] = imx_clk_hw_gate("pcc_dma1_ch18", "xbar_ad_divplat", base
+ 0x50, 30);
365 clks
[IMX8ULP_CLK_DMA1_CH19
] = imx_clk_hw_gate("pcc_dma1_ch19", "xbar_ad_divplat", base
+ 0x54, 30);
366 clks
[IMX8ULP_CLK_DMA1_CH20
] = imx_clk_hw_gate("pcc_dma1_ch20", "xbar_ad_divplat", base
+ 0x58, 30);
367 clks
[IMX8ULP_CLK_DMA1_CH21
] = imx_clk_hw_gate("pcc_dma1_ch21", "xbar_ad_divplat", base
+ 0x5c, 30);
368 clks
[IMX8ULP_CLK_DMA1_CH22
] = imx_clk_hw_gate("pcc_dma1_ch22", "xbar_ad_divplat", base
+ 0x60, 30);
369 clks
[IMX8ULP_CLK_DMA1_CH23
] = imx_clk_hw_gate("pcc_dma1_ch23", "xbar_ad_divplat", base
+ 0x64, 30);
370 clks
[IMX8ULP_CLK_DMA1_CH24
] = imx_clk_hw_gate("pcc_dma1_ch24", "xbar_ad_divplat", base
+ 0x68, 30);
371 clks
[IMX8ULP_CLK_DMA1_CH25
] = imx_clk_hw_gate("pcc_dma1_ch25", "xbar_ad_divplat", base
+ 0x6c, 30);
372 clks
[IMX8ULP_CLK_DMA1_CH26
] = imx_clk_hw_gate("pcc_dma1_ch26", "xbar_ad_divplat", base
+ 0x70, 30);
373 clks
[IMX8ULP_CLK_DMA1_CH27
] = imx_clk_hw_gate("pcc_dma1_ch27", "xbar_ad_divplat", base
+ 0x74, 30);
374 clks
[IMX8ULP_CLK_DMA1_CH28
] = imx_clk_hw_gate("pcc_dma1_ch28", "xbar_ad_divplat", base
+ 0x78, 30);
375 clks
[IMX8ULP_CLK_DMA1_CH29
] = imx_clk_hw_gate("pcc_dma1_ch29", "xbar_ad_divplat", base
+ 0x7c, 30);
376 clks
[IMX8ULP_CLK_DMA1_CH30
] = imx_clk_hw_gate("pcc_dma1_ch30", "xbar_ad_divplat", base
+ 0x80, 30);
377 clks
[IMX8ULP_CLK_DMA1_CH31
] = imx_clk_hw_gate("pcc_dma1_ch31", "xbar_ad_divplat", base
+ 0x84, 30);
378 clks
[IMX8ULP_CLK_MU0_B
] = imx_clk_hw_gate_flags("mu0_b", "xbar_ad_divplat", base
+ 0x88, 30, CLK_IS_CRITICAL
);
379 clks
[IMX8ULP_CLK_MU3_A
] = imx_clk_hw_gate("mu3_a", "xbar_ad_divplat", base
+ 0x8c, 30);
380 clks
[IMX8ULP_CLK_TPM5
] = imx_clk_hw_gate_flags("tpm5", "sosc_div2", base
+ 0xd0, 30, CLK_IS_CRITICAL
);
382 imx_check_clk_hws(clks
, clk_data
->num
);
384 ret
= devm_of_clk_add_hw_provider(dev
, of_clk_hw_onecell_get
, clk_data
);
388 imx_register_uart_clocks();
390 /* register the pcc3 reset controller */
391 return imx8ulp_pcc_reset_init(pdev
, base
, pcc3_resets
, ARRAY_SIZE(pcc3_resets
));
394 static int imx8ulp_clk_pcc4_init(struct platform_device
*pdev
)
396 struct device
*dev
= &pdev
->dev
;
397 struct clk_hw_onecell_data
*clk_data
;
398 struct clk_hw
**clks
;
402 clk_data
= devm_kzalloc(dev
, struct_size(clk_data
, hws
, IMX8ULP_CLK_PCC4_END
),
407 clk_data
->num
= IMX8ULP_CLK_PCC4_END
;
408 clks
= clk_data
->hws
;
411 base
= devm_platform_ioremap_resource(pdev
, 0);
412 if (WARN_ON(IS_ERR(base
)))
413 return PTR_ERR(base
);
415 clks
[IMX8ULP_CLK_FLEXSPI2
] = imx8ulp_clk_hw_composite("flexspi2", pcc4_periph_plat_sels
, ARRAY_SIZE(pcc4_periph_plat_sels
), true, true, true, base
+ 0x4, 1);
416 clks
[IMX8ULP_CLK_TPM6
] = imx8ulp_clk_hw_composite("tpm6", pcc4_periph_bus_sels
, ARRAY_SIZE(pcc4_periph_bus_sels
), true, true, true, base
+ 0x8, 1);
417 clks
[IMX8ULP_CLK_TPM7
] = imx8ulp_clk_hw_composite("tpm7", pcc4_periph_bus_sels
, ARRAY_SIZE(pcc4_periph_bus_sels
), true, true, true, base
+ 0xc, 1);
418 clks
[IMX8ULP_CLK_LPI2C6
] = imx8ulp_clk_hw_composite("lpi2c6", pcc4_periph_bus_sels
, ARRAY_SIZE(pcc4_periph_bus_sels
), true, true, true, base
+ 0x10, 1);
419 clks
[IMX8ULP_CLK_LPI2C7
] = imx8ulp_clk_hw_composite("lpi2c7", pcc4_periph_bus_sels
, ARRAY_SIZE(pcc4_periph_bus_sels
), true, true, true, base
+ 0x14, 1);
420 clks
[IMX8ULP_CLK_LPUART6
] = imx8ulp_clk_hw_composite("lpuart6", pcc4_periph_bus_sels
, ARRAY_SIZE(pcc4_periph_bus_sels
), true, true, true, base
+ 0x18, 1);
421 clks
[IMX8ULP_CLK_LPUART7
] = imx8ulp_clk_hw_composite("lpuart7", pcc4_periph_bus_sels
, ARRAY_SIZE(pcc4_periph_bus_sels
), true, true, true, base
+ 0x1c, 1);
422 clks
[IMX8ULP_CLK_SAI4
] = imx8ulp_clk_hw_composite("sai4", xbar_divbus
, 1, false, false, true, base
+ 0x20, 1); /* sai ipg, NOT from sai sel */
423 clks
[IMX8ULP_CLK_SAI5
] = imx8ulp_clk_hw_composite("sai5", xbar_divbus
, 1, false, false, true, base
+ 0x24, 1); /* sai ipg */
424 clks
[IMX8ULP_CLK_PCTLE
] = imx_clk_hw_gate("pctle", "xbar_divbus", base
+ 0x28, 30);
425 clks
[IMX8ULP_CLK_PCTLF
] = imx_clk_hw_gate("pctlf", "xbar_divbus", base
+ 0x2c, 30);
426 clks
[IMX8ULP_CLK_USDHC0
] = imx8ulp_clk_hw_composite("usdhc0", pcc4_periph_plat_sels
, ARRAY_SIZE(pcc4_periph_plat_sels
), true, false, true, base
+ 0x34, 1);
427 clks
[IMX8ULP_CLK_USDHC1
] = imx8ulp_clk_hw_composite("usdhc1", pcc4_periph_plat_sels
, ARRAY_SIZE(pcc4_periph_plat_sels
), true, false, true, base
+ 0x38, 1);
428 clks
[IMX8ULP_CLK_USDHC2
] = imx8ulp_clk_hw_composite("usdhc2", pcc4_periph_plat_sels
, ARRAY_SIZE(pcc4_periph_plat_sels
), true, false, true, base
+ 0x3c, 1);
429 clks
[IMX8ULP_CLK_USB0
] = imx8ulp_clk_hw_composite("usb0", nic_per_divplat
, 1, false, false, true, base
+ 0x40, 1);
430 clks
[IMX8ULP_CLK_USB0_PHY
] = imx8ulp_clk_hw_composite("usb0_phy", xbar_divbus
, 1, false, false, true, base
+ 0x44, 1);
431 clks
[IMX8ULP_CLK_USB1
] = imx8ulp_clk_hw_composite("usb1", nic_per_divplat
, 1, false, false, true, base
+ 0x48, 1);
432 clks
[IMX8ULP_CLK_USB1_PHY
] = imx8ulp_clk_hw_composite("usb1_phy", xbar_divbus
, 1, false, false, true, base
+ 0x4c, 1);
433 clks
[IMX8ULP_CLK_USB_XBAR
] = imx_clk_hw_gate("usb_xbar", "xbar_divbus", base
+ 0x50, 30);
434 clks
[IMX8ULP_CLK_ENET
] = imx8ulp_clk_hw_composite("enet", nic_per_divplat
, 1, false, false, true, base
+ 0x54, 1);
435 clks
[IMX8ULP_CLK_RGPIOE
] = imx_clk_hw_gate("rgpioe", "nic_per_divplat", base
+ 0x78, 30);
436 clks
[IMX8ULP_CLK_RGPIOF
] = imx_clk_hw_gate("rgpiof", "nic_per_divplat", base
+ 0x7c, 30);
438 imx_check_clk_hws(clks
, clk_data
->num
);
440 ret
= devm_of_clk_add_hw_provider(dev
, of_clk_hw_onecell_get
, clk_data
);
444 /* register the pcc4 reset controller */
445 return imx8ulp_pcc_reset_init(pdev
, base
, pcc4_resets
, ARRAY_SIZE(pcc4_resets
));
449 static int imx8ulp_clk_pcc5_init(struct platform_device
*pdev
)
451 struct device
*dev
= &pdev
->dev
;
452 struct clk_hw_onecell_data
*clk_data
;
453 struct clk_hw
**clks
;
457 clk_data
= devm_kzalloc(dev
, struct_size(clk_data
, hws
, IMX8ULP_CLK_PCC5_END
),
462 clk_data
->num
= IMX8ULP_CLK_PCC5_END
;
463 clks
= clk_data
->hws
;
466 base
= devm_platform_ioremap_resource(pdev
, 0);
467 if (WARN_ON(IS_ERR(base
)))
468 return PTR_ERR(base
);
470 clks
[IMX8ULP_CLK_DMA2_MP
] = imx_clk_hw_gate("pcc_dma2_mp", "lpav_axi_div", base
+ 0x0, 30);
471 clks
[IMX8ULP_CLK_DMA2_CH0
] = imx_clk_hw_gate("pcc_dma2_ch0", "lpav_axi_div", base
+ 0x4, 30);
472 clks
[IMX8ULP_CLK_DMA2_CH1
] = imx_clk_hw_gate("pcc_dma2_ch1", "lpav_axi_div", base
+ 0x8, 30);
473 clks
[IMX8ULP_CLK_DMA2_CH2
] = imx_clk_hw_gate("pcc_dma2_ch2", "lpav_axi_div", base
+ 0xc, 30);
474 clks
[IMX8ULP_CLK_DMA2_CH3
] = imx_clk_hw_gate("pcc_dma2_ch3", "lpav_axi_div", base
+ 0x10, 30);
475 clks
[IMX8ULP_CLK_DMA2_CH4
] = imx_clk_hw_gate("pcc_dma2_ch4", "lpav_axi_div", base
+ 0x14, 30);
476 clks
[IMX8ULP_CLK_DMA2_CH5
] = imx_clk_hw_gate("pcc_dma2_ch5", "lpav_axi_div", base
+ 0x18, 30);
477 clks
[IMX8ULP_CLK_DMA2_CH6
] = imx_clk_hw_gate("pcc_dma2_ch6", "lpav_axi_div", base
+ 0x1c, 30);
478 clks
[IMX8ULP_CLK_DMA2_CH7
] = imx_clk_hw_gate("pcc_dma2_ch7", "lpav_axi_div", base
+ 0x20, 30);
479 clks
[IMX8ULP_CLK_DMA2_CH8
] = imx_clk_hw_gate("pcc_dma2_ch8", "lpav_axi_div", base
+ 0x24, 30);
480 clks
[IMX8ULP_CLK_DMA2_CH9
] = imx_clk_hw_gate("pcc_dma2_ch9", "lpav_axi_div", base
+ 0x28, 30);
481 clks
[IMX8ULP_CLK_DMA2_CH10
] = imx_clk_hw_gate("pcc_dma2_ch10", "lpav_axi_div", base
+ 0x2c, 30);
482 clks
[IMX8ULP_CLK_DMA2_CH11
] = imx_clk_hw_gate("pcc_dma2_ch11", "lpav_axi_div", base
+ 0x30, 30);
483 clks
[IMX8ULP_CLK_DMA2_CH12
] = imx_clk_hw_gate("pcc_dma2_ch12", "lpav_axi_div", base
+ 0x34, 30);
484 clks
[IMX8ULP_CLK_DMA2_CH13
] = imx_clk_hw_gate("pcc_dma2_ch13", "lpav_axi_div", base
+ 0x38, 30);
485 clks
[IMX8ULP_CLK_DMA2_CH14
] = imx_clk_hw_gate("pcc_dma2_ch14", "lpav_axi_div", base
+ 0x3c, 30);
486 clks
[IMX8ULP_CLK_DMA2_CH15
] = imx_clk_hw_gate("pcc_dma2_ch15", "lpav_axi_div", base
+ 0x40, 30);
487 clks
[IMX8ULP_CLK_DMA2_CH16
] = imx_clk_hw_gate("pcc_dma2_ch16", "lpav_axi_div", base
+ 0x44, 30);
488 clks
[IMX8ULP_CLK_DMA2_CH17
] = imx_clk_hw_gate("pcc_dma2_ch17", "lpav_axi_div", base
+ 0x48, 30);
489 clks
[IMX8ULP_CLK_DMA2_CH18
] = imx_clk_hw_gate("pcc_dma2_ch18", "lpav_axi_div", base
+ 0x4c, 30);
490 clks
[IMX8ULP_CLK_DMA2_CH19
] = imx_clk_hw_gate("pcc_dma2_ch19", "lpav_axi_div", base
+ 0x50, 30);
491 clks
[IMX8ULP_CLK_DMA2_CH20
] = imx_clk_hw_gate("pcc_dma2_ch20", "lpav_axi_div", base
+ 0x54, 30);
492 clks
[IMX8ULP_CLK_DMA2_CH21
] = imx_clk_hw_gate("pcc_dma2_ch21", "lpav_axi_div", base
+ 0x58, 30);
493 clks
[IMX8ULP_CLK_DMA2_CH22
] = imx_clk_hw_gate("pcc_dma2_ch22", "lpav_axi_div", base
+ 0x5c, 30);
494 clks
[IMX8ULP_CLK_DMA2_CH23
] = imx_clk_hw_gate("pcc_dma2_ch23", "lpav_axi_div", base
+ 0x60, 30);
495 clks
[IMX8ULP_CLK_DMA2_CH24
] = imx_clk_hw_gate("pcc_dma2_ch24", "lpav_axi_div", base
+ 0x64, 30);
496 clks
[IMX8ULP_CLK_DMA2_CH25
] = imx_clk_hw_gate("pcc_dma2_ch25", "lpav_axi_div", base
+ 0x68, 30);
497 clks
[IMX8ULP_CLK_DMA2_CH26
] = imx_clk_hw_gate("pcc_dma2_ch26", "lpav_axi_div", base
+ 0x6c, 30);
498 clks
[IMX8ULP_CLK_DMA2_CH27
] = imx_clk_hw_gate("pcc_dma2_ch27", "lpav_axi_div", base
+ 0x70, 30);
499 clks
[IMX8ULP_CLK_DMA2_CH28
] = imx_clk_hw_gate("pcc_dma2_ch28", "lpav_axi_div", base
+ 0x74, 30);
500 clks
[IMX8ULP_CLK_DMA2_CH29
] = imx_clk_hw_gate("pcc_dma2_ch29", "lpav_axi_div", base
+ 0x78, 30);
501 clks
[IMX8ULP_CLK_DMA2_CH30
] = imx_clk_hw_gate("pcc_dma2_ch30", "lpav_axi_div", base
+ 0x7c, 30);
502 clks
[IMX8ULP_CLK_DMA2_CH31
] = imx_clk_hw_gate("pcc_dma2_ch31", "lpav_axi_div", base
+ 0x80, 30);
504 clks
[IMX8ULP_CLK_AVD_SIM
] = imx_clk_hw_gate("avd_sim", "lpav_bus_div", base
+ 0x94, 30);
505 clks
[IMX8ULP_CLK_TPM8
] = imx8ulp_clk_hw_composite("tpm8", pcc5_periph_bus_sels
, ARRAY_SIZE(pcc5_periph_bus_sels
), true, true, true, base
+ 0xa0, 1);
506 clks
[IMX8ULP_CLK_MU2_B
] = imx_clk_hw_gate("mu2_b", "lpav_bus_div", base
+ 0x84, 30);
507 clks
[IMX8ULP_CLK_MU3_B
] = imx_clk_hw_gate("mu3_b", "lpav_bus_div", base
+ 0x88, 30);
508 clks
[IMX8ULP_CLK_SAI6
] = imx8ulp_clk_hw_composite("sai6", lpav_bus_div
, 1, false, false, true, base
+ 0xa4, 1);
509 clks
[IMX8ULP_CLK_SAI7
] = imx8ulp_clk_hw_composite("sai7", lpav_bus_div
, 1, false, false, true, base
+ 0xa8, 1);
510 clks
[IMX8ULP_CLK_SPDIF
] = imx8ulp_clk_hw_composite("spdif", lpav_bus_div
, 1, false, false, true, base
+ 0xac, 1);
511 clks
[IMX8ULP_CLK_ISI
] = imx8ulp_clk_hw_composite("isi", lpav_axi_div
, 1, false, false, true, base
+ 0xb0, 1);
512 clks
[IMX8ULP_CLK_CSI_REGS
] = imx8ulp_clk_hw_composite("csi_regs", lpav_bus_div
, 1, false, false, true, base
+ 0xb4, 1);
513 clks
[IMX8ULP_CLK_CSI
] = imx8ulp_clk_hw_composite("csi", pcc5_periph_plat_sels
, ARRAY_SIZE(pcc5_periph_plat_sels
), true, true, true, base
+ 0xbc, 1);
514 clks
[IMX8ULP_CLK_DSI
] = imx8ulp_clk_hw_composite("dsi", pcc5_periph_plat_sels
, ARRAY_SIZE(pcc5_periph_plat_sels
), true, true, true, base
+ 0xc0, 1);
515 clks
[IMX8ULP_CLK_WDOG5
] = imx8ulp_clk_hw_composite("wdog5", pcc5_periph_bus_sels
, ARRAY_SIZE(pcc5_periph_bus_sels
), true, true, true, base
+ 0xc8, 1);
516 clks
[IMX8ULP_CLK_EPDC
] = imx8ulp_clk_hw_composite("epdc", pcc5_periph_plat_sels
, ARRAY_SIZE(pcc5_periph_plat_sels
), true, true, true, base
+ 0xcc, 1);
517 clks
[IMX8ULP_CLK_PXP
] = imx8ulp_clk_hw_composite("pxp", lpav_axi_div
, 1, false, false, true, base
+ 0xd0, 1);
518 clks
[IMX8ULP_CLK_GPU2D
] = imx8ulp_clk_hw_composite("gpu2d", pcc5_periph_plat_sels
, ARRAY_SIZE(pcc5_periph_plat_sels
), true, true, true, base
+ 0xf0, 1);
519 clks
[IMX8ULP_CLK_GPU3D
] = imx8ulp_clk_hw_composite("gpu3d", pcc5_periph_plat_sels
, ARRAY_SIZE(pcc5_periph_plat_sels
), true, true, true, base
+ 0xf4, 1);
520 clks
[IMX8ULP_CLK_DC_NANO
] = imx8ulp_clk_hw_composite("dc_nano", pcc5_periph_plat_sels
, ARRAY_SIZE(pcc5_periph_plat_sels
), true, true, true, base
+ 0xf8, 1);
521 clks
[IMX8ULP_CLK_CSI_CLK_UI
] = imx8ulp_clk_hw_composite("csi_clk_ui", pcc5_periph_plat_sels
, ARRAY_SIZE(pcc5_periph_plat_sels
), true, true, true, base
+ 0x10c, 1);
522 clks
[IMX8ULP_CLK_CSI_CLK_ESC
] = imx8ulp_clk_hw_composite("csi_clk_esc", pcc5_periph_plat_sels
, ARRAY_SIZE(pcc5_periph_plat_sels
), true, true, true, base
+ 0x110, 1);
523 clks
[IMX8ULP_CLK_RGPIOD
] = imx_clk_hw_gate("rgpiod", "lpav_axi_div", base
+ 0x114, 30);
524 clks
[IMX8ULP_CLK_DSI_TX_ESC
] = imx_clk_hw_fixed_factor("mipi_dsi_tx_esc", "dsi", 1, 4);
526 imx_check_clk_hws(clks
, clk_data
->num
);
528 ret
= devm_of_clk_add_hw_provider(dev
, of_clk_hw_onecell_get
, clk_data
);
532 /* register the pcc5 reset controller */
533 return imx8ulp_pcc_reset_init(pdev
, base
, pcc5_resets
, ARRAY_SIZE(pcc5_resets
));
536 static int imx8ulp_clk_probe(struct platform_device
*pdev
)
538 int (*probe
)(struct platform_device
*pdev
);
540 probe
= of_device_get_match_data(&pdev
->dev
);
548 static const struct of_device_id imx8ulp_clk_dt_ids
[] = {
549 { .compatible
= "fsl,imx8ulp-pcc3", .data
= imx8ulp_clk_pcc3_init
},
550 { .compatible
= "fsl,imx8ulp-pcc4", .data
= imx8ulp_clk_pcc4_init
},
551 { .compatible
= "fsl,imx8ulp-pcc5", .data
= imx8ulp_clk_pcc5_init
},
552 { .compatible
= "fsl,imx8ulp-cgc2", .data
= imx8ulp_clk_cgc2_init
},
553 { .compatible
= "fsl,imx8ulp-cgc1", .data
= imx8ulp_clk_cgc1_init
},
556 MODULE_DEVICE_TABLE(of
, imx8ulp_clk_dt_ids
);
558 static struct platform_driver imx8ulp_clk_driver
= {
559 .probe
= imx8ulp_clk_probe
,
561 .name
= KBUILD_MODNAME
,
562 .suppress_bind_attrs
= true,
563 .of_match_table
= imx8ulp_clk_dt_ids
,
566 module_platform_driver(imx8ulp_clk_driver
);
568 MODULE_AUTHOR("Peng Fan <peng.fan@nxp.com>");
569 MODULE_DESCRIPTION("NXP i.MX8ULP clock driver");
570 MODULE_LICENSE("GPL v2");