1 #include <linux/kernel.h>
\r
2 #include <linux/platform_device.h>
\r
3 #include <linux/delay.h>
\r
4 #include <linux/dma-mapping.h>
\r
5 #include <linux/clk.h>
\r
7 #include <mach/irqs.h>
\r
8 #include <mach/gpio.h>
\r
9 #include <mach/iomux.h>
\r
10 #include <mach/cru.h>
\r
12 #include "usbdev_rk.h"
\r
13 #include "dwc_otg_regs.h"
\r
14 #ifdef CONFIG_ARCH_RK2928
\r
16 #define GRF_REG_BASE RK2928_GRF_BASE
\r
17 #define USBOTG_SIZE RK2928_USBOTG20_SIZE
\r
18 #define USBGRF_SOC_STATUS0 (GRF_REG_BASE+0x14c)
\r
19 #define USBGRF_UOC0_CON5 (GRF_REG_BASE+0x17c)
\r
20 #define USBGRF_UOC1_CON5 (GRF_REG_BASE+0x194)
\r
23 int dwc_otg_check_dpdm(void)
\r
25 static uint8_t * reg_base = 0;
\r
26 volatile unsigned int * otg_dctl;
\r
27 volatile unsigned int * otg_gotgctl;
\r
28 volatile unsigned int * otg_hprt0;
\r
30 unsigned int * otg_phy_con1 = (unsigned int*)(USBGRF_UOC0_CON5);//@lyz modify UOC0_CON2 to CON5
\r
32 // softreset & clockgate //@lyz modify RK2928_CRU_BASE
\r
33 *(unsigned int*)(RK2928_CRU_BASE+0x120) = ((7<<5)<<16)|(7<<5); // otg0 phy clkgate
\r
35 *(unsigned int*)(RK2928_CRU_BASE+0x120) = ((7<<5)<<16)|(0<<5); // otg0 phy clkgate
\r
37 *(unsigned int*)(RK2928_CRU_BASE+0xd4) = ((1<<5)<<16); // otg0 phy clkgate
\r
38 *(unsigned int*)(RK2928_CRU_BASE+0xe4) = ((1<<13)<<16); // otg0 hclk clkgate
\r
39 *(unsigned int*)(RK2928_CRU_BASE+0xf4) = ((3<<10)<<16); // hclk usb clkgate//@lyz to be check
\r
41 // exit phy suspend
\r
42 *otg_phy_con1 = ((0x01<<0)<<16); // exit suspend.@lyz
\r
46 reg_base = ioremap(RK2928_USBOTG20_PHYS,USBOTG_SIZE);//@lyz
\r
53 printk("regbase %p 0x%x, otg_phy_con%p, 0x%x\n",
\r
54 reg_base, *(reg_base), otg_phy_con1, *otg_phy_con1);
\r
55 otg_dctl = (unsigned int * )(reg_base+0x804);
\r
56 otg_gotgctl = (unsigned int * )(reg_base);
\r
57 otg_hprt0 = (unsigned int * )(reg_base + DWC_OTG_HOST_PORT_REGS_OFFSET);
\r
58 if(*otg_gotgctl &(1<<19)){
\r
60 *otg_dctl &= ~(0x01<<1);//@lyz exit soft-disconnect mode
\r
61 mdelay(50); // delay about 10ms
\r
63 if((*otg_hprt0 & 0xc00)==0xc00)//@lyz check hprt[11:10]
\r
70 EXPORT_SYMBOL(dwc_otg_check_dpdm);
\r
73 #ifdef CONFIG_USB20_OTG
\r
75 static struct resource usb20_otg_resource[] = {
\r
77 .start = IRQ_USB_OTG,
\r
79 .flags = IORESOURCE_IRQ,
\r
82 .start = RK2928_USBOTG20_PHYS,
\r
83 .end = RK2928_USBOTG20_PHYS + RK2928_USBOTG20_SIZE - 1,
\r
84 .flags = IORESOURCE_MEM,
\r
89 void usb20otg_hw_init(void)
\r
91 #ifndef CONFIG_USB20_HOST
\r
92 // close USB 2.0 HOST phy and clock
\r
93 unsigned int * otg_phy_con1 = (unsigned int*)(USBGRF_UOC1_CON5);
\r
94 *otg_phy_con1 = 0x1D5 |(0x1ff<<16); // enter suspend.
\r
96 // usb phy config init
\r
98 // other hardware init
\r
99 rk30_mux_api_set(GPIO3C1_OTG_DRVVBUS_NAME, GPIO3C_OTG_DRVVBUS);
\r
101 void usb20otg_phy_suspend(void* pdata, int suspend)
\r
103 struct dwc_otg_platform_data *usbpdata=pdata;
\r
104 unsigned int * otg_phy_con1 = (unsigned int*)(USBGRF_UOC0_CON5);
\r
106 *otg_phy_con1 = 0x1D5 |(0x1ff<<16); // enter suspend.
\r
107 usbpdata->phy_status = 1;
\r
110 *otg_phy_con1 = (0x01<<16); // exit suspend.
\r
111 usbpdata->phy_status = 0;
\r
114 void usb20otg_soft_reset(void)
\r
117 cru_set_soft_reset(SOFT_RST_USBOTG0, true);
\r
118 cru_set_soft_reset(SOFT_RST_USBPHY0, true);
\r
119 cru_set_soft_reset(SOFT_RST_OTGC0, true);
\r
122 cru_set_soft_reset(SOFT_RST_USBOTG0, false);
\r
123 cru_set_soft_reset(SOFT_RST_USBPHY0, false);
\r
124 cru_set_soft_reset(SOFT_RST_OTGC0, false);
\r
128 void usb20otg_clock_init(void* pdata)
\r
130 struct dwc_otg_platform_data *usbpdata=pdata;
\r
131 struct clk* ahbclk,*phyclk;
\r
132 ahbclk = clk_get(NULL, "hclk_otg0");
\r
133 phyclk = clk_get(NULL, "otgphy0");
\r
134 usbpdata->phyclk = phyclk;
\r
135 usbpdata->ahbclk = ahbclk;
\r
137 void usb20otg_clock_enable(void* pdata, int enable)
\r
139 struct dwc_otg_platform_data *usbpdata=pdata;
\r
142 clk_enable(usbpdata->ahbclk);
\r
143 clk_enable(usbpdata->phyclk);
\r
146 // clk_disable(usbpdata->phyclk); /* otg/host20 use the same phyclk, so can't disable phyclk in case host20 is used.*/
\r
147 clk_disable(usbpdata->ahbclk);
\r
151 int usb20otg_get_status(int id)
\r
154 unsigned int usbgrf_status = *(unsigned int*)(USBGRF_SOC_STATUS0);
\r
157 case USB_STATUS_BVABLID:
\r
159 ret = (usbgrf_status &(1<<7));
\r
161 case USB_STATUS_DPDM:
\r
163 ret = (usbgrf_status &(3<<8));
\r
165 case USB_STATUS_ID:
\r
167 ret = (usbgrf_status &(1<<10));
\r
174 void usb20otg_power_enable(int enable)
\r
177 struct dwc_otg_platform_data usb20otg_pdata = {
\r
182 .hw_init=usb20otg_hw_init,
\r
183 .phy_suspend=usb20otg_phy_suspend,
\r
184 .soft_reset=usb20otg_soft_reset,
\r
185 .clock_init=usb20otg_clock_init,
\r
186 .clock_enable=usb20otg_clock_enable,
\r
187 .get_status=usb20otg_get_status,
\r
190 struct platform_device device_usb20_otg = {
\r
191 .name = "usb20_otg",
\r
193 .num_resources = ARRAY_SIZE(usb20_otg_resource),
\r
194 .resource = usb20_otg_resource,
\r
196 .platform_data = &usb20otg_pdata,
\r
200 #ifdef CONFIG_USB20_HOST
\r
201 static struct resource usb20_host_resource[] = {
\r
203 .start = IRQ_USB_HOST,
\r
204 .end = IRQ_USB_HOST,
\r
205 .flags = IORESOURCE_IRQ,
\r
208 .start = RK2928_USBHOST20_PHYS,
\r
209 .end = RK2928_USBHOST20_PHYS + RK2928_USBHOST20_SIZE - 1,
\r
210 .flags = IORESOURCE_MEM,
\r
215 void usb20host_hw_init(void)
\r
217 // usb phy config init
\r
218 *(unsigned int *)(USBGRF_UOC0_CON5+4) = 0x07e00350;
\r
219 // other haredware init
\r
222 void usb20host_phy_suspend(void* pdata, int suspend)
\r
224 struct dwc_otg_platform_data *usbpdata=pdata;
\r
225 unsigned int * otg_phy_con1 = (unsigned int*)(USBGRF_UOC1_CON5);
\r
227 *otg_phy_con1 = 0x1D5 |(0x1ff<<16); // enter suspend.
\r
228 usbpdata->phy_status = 1;
\r
231 *otg_phy_con1 = (0x01<<16); // exit suspend.
\r
232 usbpdata->phy_status = 0;
\r
235 void usb20host_soft_reset(void)
\r
238 cru_set_soft_reset(SOFT_RST_USBOTG1, true);
\r
239 cru_set_soft_reset(SOFT_RST_USBPHY1, true);
\r
240 cru_set_soft_reset(SOFT_RST_OTGC1, true);
\r
243 cru_set_soft_reset(SOFT_RST_USBOTG1, false);
\r
244 cru_set_soft_reset(SOFT_RST_USBPHY1, false);
\r
245 cru_set_soft_reset(SOFT_RST_OTGC1, false);
\r
249 void usb20host_clock_init(void* pdata)
\r
251 struct dwc_otg_platform_data *usbpdata=pdata;
\r
252 struct clk* ahbclk,*phyclk;
\r
253 ahbclk = clk_get(NULL, "hclk_otg1");
\r
254 phyclk = clk_get(NULL, "otgphy1");
\r
255 usbpdata->phyclk = phyclk;
\r
256 usbpdata->ahbclk = ahbclk;
\r
258 void usb20host_clock_enable(void* pdata, int enable)
\r
260 struct dwc_otg_platform_data *usbpdata=pdata;
\r
263 clk_enable(usbpdata->ahbclk);
\r
264 clk_enable(usbpdata->phyclk);
\r
267 clk_disable(usbpdata->phyclk);
\r
268 clk_disable(usbpdata->ahbclk);
\r
272 int usb20host_get_status(int id)
\r
275 unsigned int usbgrf_status = *(unsigned int*)(USBGRF_SOC_STATUS0);
\r
278 case USB_STATUS_BVABLID:
\r
280 ret = (usbgrf_status &(1<<12));
\r
282 case USB_STATUS_DPDM:
\r
284 ret = (usbgrf_status &(3<<13));
\r
286 case USB_STATUS_ID:
\r
295 void usb20host_power_enable(int enable)
\r
298 struct dwc_otg_platform_data usb20host_pdata = {
\r
303 .hw_init=usb20host_hw_init,
\r
304 .phy_suspend=usb20host_phy_suspend,
\r
305 .soft_reset=usb20host_soft_reset,
\r
306 .clock_init=usb20host_clock_init,
\r
307 .clock_enable=usb20host_clock_enable,
\r
308 .get_status=usb20host_get_status,
\r
311 struct platform_device device_usb20_host = {
\r
312 .name = "usb20_host",
\r
314 .num_resources = ARRAY_SIZE(usb20_host_resource),
\r
315 .resource = usb20_host_resource,
\r
317 .platform_data = &usb20host_pdata,
\r
321 static int __init usbdev_init_devices(void)
\r
323 #ifdef CONFIG_USB20_OTG
\r
324 platform_device_register(&device_usb20_otg);
\r
326 #ifdef CONFIG_USB20_HOST
\r
327 platform_device_register(&device_usb20_host);
\r
330 arch_initcall(usbdev_init_devices);
\r