1 // SPDX-License-Identifier: GPL-2.0
3 * cdns3-imx.c - NXP i.MX specific Glue layer for Cadence USB Controller
5 * Copyright (C) 2019 NXP
8 #include <linux/bits.h>
10 #include <linux/module.h>
11 #include <linux/kernel.h>
12 #include <linux/interrupt.h>
13 #include <linux/platform_device.h>
14 #include <linux/dma-mapping.h>
16 #include <linux/of_platform.h>
17 #include <linux/iopoll.h>
18 #include <linux/pm_runtime.h>
21 #define USB3_CORE_CTRL1 0x00
22 #define USB3_CORE_CTRL2 0x04
23 #define USB3_INT_REG 0x08
24 #define USB3_CORE_STATUS 0x0c
25 #define XHCI_DEBUG_LINK_ST 0x10
26 #define XHCI_DEBUG_BUS 0x14
27 #define USB3_SSPHY_CTRL1 0x40
28 #define USB3_SSPHY_CTRL2 0x44
29 #define USB3_SSPHY_STATUS 0x4c
30 #define USB2_PHY_CTRL1 0x50
31 #define USB2_PHY_CTRL2 0x54
32 #define USB2_PHY_STATUS 0x5c
34 /* Register bits definition */
37 #define SW_RESET_MASK GENMASK(31, 26)
38 #define PWR_SW_RESET BIT(31)
39 #define APB_SW_RESET BIT(30)
40 #define AXI_SW_RESET BIT(29)
41 #define RW_SW_RESET BIT(28)
42 #define PHY_SW_RESET BIT(27)
43 #define PHYAHB_SW_RESET BIT(26)
44 #define ALL_SW_RESET (PWR_SW_RESET | APB_SW_RESET | AXI_SW_RESET | \
45 RW_SW_RESET | PHY_SW_RESET | PHYAHB_SW_RESET)
46 #define OC_DISABLE BIT(9)
47 #define MDCTRL_CLK_SEL BIT(7)
48 #define MODE_STRAP_MASK (0x7)
49 #define DEV_MODE (1 << 2)
50 #define HOST_MODE (1 << 1)
51 #define OTG_MODE (1 << 0)
54 #define CLK_125_REQ BIT(29)
55 #define LPM_CLK_REQ BIT(28)
56 #define DEVU3_WAEKUP_EN BIT(14)
57 #define OTG_WAKEUP_EN BIT(12)
58 #define DEV_INT_EN (3 << 8) /* DEV INT b9:8 */
59 #define HOST_INT1_EN (1 << 0) /* HOST INT b7:0 */
61 /* USB3_CORE_STATUS */
62 #define MDCTRL_CLK_STATUS BIT(15)
63 #define DEV_POWER_ON_READY BIT(13)
64 #define HOST_POWER_ON_READY BIT(12)
66 /* USB3_SSPHY_STATUS */
67 #define CLK_VALID_MASK (0x3f << 26)
68 #define CLK_VALID_COMPARE_BITS (0xf << 28)
69 #define PHY_REFCLK_REQ (1 << 0)
71 /* OTG registers definition */
74 #define OTG_NRDY BIT(11)
76 /* xHCI registers definition */
77 #define XECP_PM_PMCSR 0x8018
78 #define XECP_AUX_CTRL_REG1 0x8120
80 /* Register bits definition */
81 /* XECP_AUX_CTRL_REG1 */
82 #define CFG_RXDET_P3_EN BIT(15)
85 #define PS_MASK GENMASK(1, 0)
91 void __iomem
*noncore
;
92 struct clk_bulk_data
*clks
;
94 struct platform_device
*cdns3_pdev
;
97 static inline u32
cdns_imx_readl(struct cdns_imx
*data
, u32 offset
)
99 return readl(data
->noncore
+ offset
);
102 static inline void cdns_imx_writel(struct cdns_imx
*data
, u32 offset
, u32 value
)
104 writel(value
, data
->noncore
+ offset
);
107 static const struct clk_bulk_data imx_cdns3_core_clks
[] = {
108 { .id
= "usb3_lpm_clk" },
109 { .id
= "usb3_bus_clk" },
110 { .id
= "usb3_aclk" },
111 { .id
= "usb3_ipg_clk" },
112 { .id
= "usb3_core_pclk" },
115 static int cdns_imx_noncore_init(struct cdns_imx
*data
)
119 struct device
*dev
= data
->dev
;
121 cdns_imx_writel(data
, USB3_SSPHY_STATUS
, CLK_VALID_MASK
);
123 ret
= readl_poll_timeout(data
->noncore
+ USB3_SSPHY_STATUS
, value
,
124 (value
& CLK_VALID_COMPARE_BITS
) == CLK_VALID_COMPARE_BITS
,
127 dev_err(dev
, "wait clkvld timeout\n");
131 value
= cdns_imx_readl(data
, USB3_CORE_CTRL1
);
132 value
|= ALL_SW_RESET
;
133 cdns_imx_writel(data
, USB3_CORE_CTRL1
, value
);
136 value
= cdns_imx_readl(data
, USB3_CORE_CTRL1
);
137 value
= (value
& ~MODE_STRAP_MASK
) | OTG_MODE
| OC_DISABLE
;
138 cdns_imx_writel(data
, USB3_CORE_CTRL1
, value
);
140 value
= cdns_imx_readl(data
, USB3_INT_REG
);
141 value
|= HOST_INT1_EN
| DEV_INT_EN
;
142 cdns_imx_writel(data
, USB3_INT_REG
, value
);
144 value
= cdns_imx_readl(data
, USB3_CORE_CTRL1
);
145 value
&= ~ALL_SW_RESET
;
146 cdns_imx_writel(data
, USB3_CORE_CTRL1
, value
);
150 static int cdns_imx_platform_suspend(struct device
*dev
,
151 bool suspend
, bool wakeup
);
152 static struct cdns3_platform_data cdns_imx_pdata
= {
153 .platform_suspend
= cdns_imx_platform_suspend
,
154 .quirks
= CDNS3_DEFAULT_PM_RUNTIME_ALLOW
,
157 static const struct of_dev_auxdata cdns_imx_auxdata
[] = {
159 .compatible
= "cdns,usb3",
160 .platform_data
= &cdns_imx_pdata
,
165 static int cdns_imx_probe(struct platform_device
*pdev
)
167 struct device
*dev
= &pdev
->dev
;
168 struct device_node
*node
= dev
->of_node
;
169 struct cdns_imx
*data
;
175 data
= devm_kzalloc(dev
, sizeof(*data
), GFP_KERNEL
);
179 platform_set_drvdata(pdev
, data
);
181 data
->noncore
= devm_platform_ioremap_resource(pdev
, 0);
182 if (IS_ERR(data
->noncore
)) {
183 dev_err(dev
, "can't map IOMEM resource\n");
184 return PTR_ERR(data
->noncore
);
187 data
->num_clks
= ARRAY_SIZE(imx_cdns3_core_clks
);
188 data
->clks
= (struct clk_bulk_data
*)imx_cdns3_core_clks
;
189 ret
= devm_clk_bulk_get(dev
, data
->num_clks
, data
->clks
);
193 ret
= clk_bulk_prepare_enable(data
->num_clks
, data
->clks
);
197 ret
= cdns_imx_noncore_init(data
);
201 ret
= of_platform_populate(node
, NULL
, cdns_imx_auxdata
, dev
);
203 dev_err(dev
, "failed to create children: %d\n", ret
);
207 device_set_wakeup_capable(dev
, true);
208 pm_runtime_set_active(dev
);
209 pm_runtime_enable(dev
);
213 clk_bulk_disable_unprepare(data
->num_clks
, data
->clks
);
217 static int cdns_imx_remove_core(struct device
*dev
, void *data
)
219 struct platform_device
*pdev
= to_platform_device(dev
);
221 platform_device_unregister(pdev
);
226 static int cdns_imx_remove(struct platform_device
*pdev
)
228 struct device
*dev
= &pdev
->dev
;
230 device_for_each_child(dev
, NULL
, cdns_imx_remove_core
);
231 platform_set_drvdata(pdev
, NULL
);
237 static void cdns3_set_wakeup(struct cdns_imx
*data
, bool enable
)
241 value
= cdns_imx_readl(data
, USB3_INT_REG
);
243 value
|= OTG_WAKEUP_EN
| DEVU3_WAEKUP_EN
;
245 value
&= ~(OTG_WAKEUP_EN
| DEVU3_WAEKUP_EN
);
247 cdns_imx_writel(data
, USB3_INT_REG
, value
);
250 static int cdns_imx_platform_suspend(struct device
*dev
,
251 bool suspend
, bool wakeup
)
253 struct cdns3
*cdns
= dev_get_drvdata(dev
);
254 struct device
*parent
= dev
->parent
;
255 struct cdns_imx
*data
= dev_get_drvdata(parent
);
256 void __iomem
*otg_regs
= (void __iomem
*)(cdns
->otg_regs
);
257 void __iomem
*xhci_regs
= cdns
->xhci_regs
;
261 if (cdns
->role
!= USB_ROLE_HOST
)
265 /* SW request low power when all usb ports allow to it ??? */
266 value
= readl(xhci_regs
+ XECP_PM_PMCSR
);
269 writel(value
, xhci_regs
+ XECP_PM_PMCSR
);
272 value
= cdns_imx_readl(data
, USB3_CORE_CTRL1
);
273 value
|= MDCTRL_CLK_SEL
;
274 cdns_imx_writel(data
, USB3_CORE_CTRL1
, value
);
276 /* wait for mdctrl_clk_status */
277 value
= cdns_imx_readl(data
, USB3_CORE_STATUS
);
278 ret
= readl_poll_timeout(data
->noncore
+ USB3_CORE_STATUS
, value
,
279 (value
& MDCTRL_CLK_STATUS
) == MDCTRL_CLK_STATUS
,
282 dev_warn(parent
, "wait mdctrl_clk_status timeout\n");
284 /* wait lpm_clk_req to be 0 */
285 value
= cdns_imx_readl(data
, USB3_INT_REG
);
286 ret
= readl_poll_timeout(data
->noncore
+ USB3_INT_REG
, value
,
287 (value
& LPM_CLK_REQ
) != LPM_CLK_REQ
,
290 dev_warn(parent
, "wait lpm_clk_req timeout\n");
292 /* wait phy_refclk_req to be 0 */
293 value
= cdns_imx_readl(data
, USB3_SSPHY_STATUS
);
294 ret
= readl_poll_timeout(data
->noncore
+ USB3_SSPHY_STATUS
, value
,
295 (value
& PHY_REFCLK_REQ
) != PHY_REFCLK_REQ
,
298 dev_warn(parent
, "wait phy_refclk_req timeout\n");
300 cdns3_set_wakeup(data
, wakeup
);
302 cdns3_set_wakeup(data
, false);
305 value
= readl(xhci_regs
+ XECP_PM_PMCSR
);
308 writel(value
, xhci_regs
+ XECP_PM_PMCSR
);
310 /* clr CFG_RXDET_P3_EN */
311 value
= readl(xhci_regs
+ XECP_AUX_CTRL_REG1
);
312 value
&= ~CFG_RXDET_P3_EN
;
313 writel(value
, xhci_regs
+ XECP_AUX_CTRL_REG1
);
315 /* clear mdctrl_clk_sel */
316 value
= cdns_imx_readl(data
, USB3_CORE_CTRL1
);
317 value
&= ~MDCTRL_CLK_SEL
;
318 cdns_imx_writel(data
, USB3_CORE_CTRL1
, value
);
320 /* wait CLK_125_REQ to be 1 */
321 value
= cdns_imx_readl(data
, USB3_INT_REG
);
322 ret
= readl_poll_timeout(data
->noncore
+ USB3_INT_REG
, value
,
323 (value
& CLK_125_REQ
) == CLK_125_REQ
,
326 dev_warn(parent
, "wait CLK_125_REQ timeout\n");
328 /* wait for mdctrl_clk_status is cleared */
329 value
= cdns_imx_readl(data
, USB3_CORE_STATUS
);
330 ret
= readl_poll_timeout(data
->noncore
+ USB3_CORE_STATUS
, value
,
331 (value
& MDCTRL_CLK_STATUS
) != MDCTRL_CLK_STATUS
,
334 dev_warn(parent
, "wait mdctrl_clk_status cleared timeout\n");
336 /* Wait until OTG_NRDY is 0 */
337 value
= readl(otg_regs
+ OTGSTS
);
338 ret
= readl_poll_timeout(otg_regs
+ OTGSTS
, value
,
339 (value
& OTG_NRDY
) != OTG_NRDY
,
342 dev_warn(parent
, "wait OTG ready timeout\n");
349 static int cdns_imx_resume(struct device
*dev
)
351 struct cdns_imx
*data
= dev_get_drvdata(dev
);
353 return clk_bulk_prepare_enable(data
->num_clks
, data
->clks
);
356 static int cdns_imx_suspend(struct device
*dev
)
358 struct cdns_imx
*data
= dev_get_drvdata(dev
);
360 clk_bulk_disable_unprepare(data
->num_clks
, data
->clks
);
365 static int cdns_imx_platform_suspend(struct device
*dev
,
366 bool suspend
, bool wakeup
)
371 #endif /* CONFIG_PM */
373 static const struct dev_pm_ops cdns_imx_pm_ops
= {
374 SET_RUNTIME_PM_OPS(cdns_imx_suspend
, cdns_imx_resume
, NULL
)
377 static const struct of_device_id cdns_imx_of_match
[] = {
378 { .compatible
= "fsl,imx8qm-usb3", },
381 MODULE_DEVICE_TABLE(of
, cdns_imx_of_match
);
383 static struct platform_driver cdns_imx_driver
= {
384 .probe
= cdns_imx_probe
,
385 .remove
= cdns_imx_remove
,
388 .of_match_table
= cdns_imx_of_match
,
389 .pm
= &cdns_imx_pm_ops
,
392 module_platform_driver(cdns_imx_driver
);
394 MODULE_ALIAS("platform:cdns3-imx");
395 MODULE_AUTHOR("Peter Chen <peter.chen@nxp.com>");
396 MODULE_LICENSE("GPL v2");
397 MODULE_DESCRIPTION("Cadence USB3 i.MX Glue Layer");