2 * Copyright 2012 Freescale Semiconductor, Inc.
4 * The code contained herein is licensed under the GNU General Public
5 * License. You may obtain a copy of the GNU General Public License
6 * Version 2 or later at the following locations:
8 * http://www.opensource.org/licenses/gpl-license.html
9 * http://www.gnu.org/copyleft/gpl.html
12 #include <linux/module.h>
13 #include <linux/of_platform.h>
14 #include <linux/clk.h>
15 #include <linux/err.h>
18 #include "ci13xxx_imx.h"
22 #define MX53_USB_OTG_PHY_CTRL_0_OFFSET 0x08
23 #define MX53_USB_UH2_CTRL_OFFSET 0x14
24 #define MX53_USB_UH3_CTRL_OFFSET 0x18
25 #define MX53_BM_OVER_CUR_DIS_H1 BIT(5)
26 #define MX53_BM_OVER_CUR_DIS_OTG BIT(8)
27 #define MX53_BM_OVER_CUR_DIS_UHx BIT(30)
29 #define MX6_BM_OVER_CUR_DIS BIT(7)
35 struct usbmisc_usb_device usbdev
[USB_DEV_MAX
];
36 const struct usbmisc_ops
*ops
;
39 static struct imx_usbmisc
*usbmisc
;
41 static struct usbmisc_usb_device
*get_usbdev(struct device
*dev
)
45 for (i
= 0; i
< USB_DEV_MAX
; i
++) {
46 if (usbmisc
->usbdev
[i
].dev
== dev
)
47 return &usbmisc
->usbdev
[i
];
48 else if (!usbmisc
->usbdev
[i
].dev
)
53 return ERR_PTR(-EBUSY
);
55 ret
= usbmisc_get_init_data(dev
, &usbmisc
->usbdev
[i
]);
59 return &usbmisc
->usbdev
[i
];
62 static int usbmisc_imx53_init(struct device
*dev
)
64 struct usbmisc_usb_device
*usbdev
;
65 void __iomem
*reg
= NULL
;
69 usbdev
= get_usbdev(dev
);
71 return PTR_ERR(usbdev
);
73 if (usbdev
->disable_oc
) {
74 spin_lock_irqsave(&usbmisc
->lock
, flags
);
75 switch (usbdev
->index
) {
77 reg
= usbmisc
->base
+ MX53_USB_OTG_PHY_CTRL_0_OFFSET
;
78 val
= readl(reg
) | MX53_BM_OVER_CUR_DIS_OTG
;
81 reg
= usbmisc
->base
+ MX53_USB_OTG_PHY_CTRL_0_OFFSET
;
82 val
= readl(reg
) | MX53_BM_OVER_CUR_DIS_H1
;
85 reg
= usbmisc
->base
+ MX53_USB_UH2_CTRL_OFFSET
;
86 val
= readl(reg
) | MX53_BM_OVER_CUR_DIS_UHx
;
89 reg
= usbmisc
->base
+ MX53_USB_UH3_CTRL_OFFSET
;
90 val
= readl(reg
) | MX53_BM_OVER_CUR_DIS_UHx
;
95 spin_unlock_irqrestore(&usbmisc
->lock
, flags
);
101 static int usbmisc_imx6q_init(struct device
*dev
)
104 struct usbmisc_usb_device
*usbdev
;
108 usbdev
= get_usbdev(dev
);
110 return PTR_ERR(usbdev
);
112 if (usbdev
->disable_oc
) {
113 spin_lock_irqsave(&usbmisc
->lock
, flags
);
114 reg
= readl(usbmisc
->base
+ usbdev
->index
* 4);
115 writel(reg
| MX6_BM_OVER_CUR_DIS
,
116 usbmisc
->base
+ usbdev
->index
* 4);
117 spin_unlock_irqrestore(&usbmisc
->lock
, flags
);
123 static const struct usbmisc_ops imx53_usbmisc_ops
= {
124 .init
= usbmisc_imx53_init
,
127 static const struct usbmisc_ops imx6q_usbmisc_ops
= {
128 .init
= usbmisc_imx6q_init
,
131 static const struct of_device_id usbmisc_imx_dt_ids
[] = {
133 .compatible
= "fsl,imx53-usbmisc",
134 .data
= &imx53_usbmisc_ops
,
137 .compatible
= "fsl,imx6q-usbmisc",
138 .data
= &imx6q_usbmisc_ops
,
143 static int usbmisc_imx_probe(struct platform_device
*pdev
)
145 struct resource
*res
;
146 struct imx_usbmisc
*data
;
148 struct of_device_id
*tmp_dev
;
153 data
= devm_kzalloc(&pdev
->dev
, sizeof(*data
), GFP_KERNEL
);
157 spin_lock_init(&data
->lock
);
159 res
= platform_get_resource(pdev
, IORESOURCE_MEM
, 0);
160 data
->base
= devm_ioremap_resource(&pdev
->dev
, res
);
161 if (IS_ERR(data
->base
))
162 return PTR_ERR(data
->base
);
164 data
->clk
= devm_clk_get(&pdev
->dev
, NULL
);
165 if (IS_ERR(data
->clk
)) {
167 "failed to get clock, err=%ld\n", PTR_ERR(data
->clk
));
168 return PTR_ERR(data
->clk
);
171 ret
= clk_prepare_enable(data
->clk
);
174 "clk_prepare_enable failed, err=%d\n", ret
);
178 tmp_dev
= (struct of_device_id
*)
179 of_match_device(usbmisc_imx_dt_ids
, &pdev
->dev
);
180 data
->ops
= (const struct usbmisc_ops
*)tmp_dev
->data
;
182 ret
= usbmisc_set_ops(data
->ops
);
185 clk_disable_unprepare(data
->clk
);
192 static int usbmisc_imx_remove(struct platform_device
*pdev
)
194 usbmisc_unset_ops(usbmisc
->ops
);
195 clk_disable_unprepare(usbmisc
->clk
);
200 static struct platform_driver usbmisc_imx_driver
= {
201 .probe
= usbmisc_imx_probe
,
202 .remove
= usbmisc_imx_remove
,
204 .name
= "usbmisc_imx",
205 .owner
= THIS_MODULE
,
206 .of_match_table
= usbmisc_imx_dt_ids
,
210 int usbmisc_imx_drv_init(void)
212 return platform_driver_register(&usbmisc_imx_driver
);
214 subsys_initcall(usbmisc_imx_drv_init
);
216 void usbmisc_imx_drv_exit(void)
218 platform_driver_unregister(&usbmisc_imx_driver
);
220 module_exit(usbmisc_imx_drv_exit
);
222 MODULE_ALIAS("platform:usbmisc-imx");
223 MODULE_LICENSE("GPL v2");
224 MODULE_DESCRIPTION("driver for imx usb non-core registers");
225 MODULE_AUTHOR("Richard Zhao <richard.zhao@freescale.com>");