1 #include <linux/kernel.h>
2 #include <linux/module.h>
3 #include <linux/init.h>
4 #include <linux/platform_device.h>
5 #include <linux/dma-mapping.h>
6 #include "musbfsh_core.h"
7 #include "musbfsh_mt65xx.h"
8 #include "mach/emi_mpu.h"
11 bool musbfsh_power
= false;
12 // unsigned char __iomem *usb11_phy_addr = (unsigned char __iomem*)USB11_PHY_ADDR;
14 struct mt_usb11_glue
{
16 struct platform_device
*musbfsh
;
19 void usb11_hs_slew_rate_cal(void){
24 unsigned long start_time
, timeout
;
25 unsigned int timeout_flag
= 0;
26 //4 s1:enable usb ring oscillator.
27 USB11PHY_WRITE8(0x15,0x80);
32 //4 s3:enable free run clock
33 USB11PHY_WRITE8 (0xf00-0x900+0x11,0x01);
34 //4 s4:setting cyclecnt.
35 USB11PHY_WRITE8 (0xf00-0x900+0x01,0x04);
36 //4 s5:enable frequency meter
37 USB11PHY_SET8 (0xf00-0x900+0x03,0x05);
39 //4 s6:wait for frequency valid.
41 timeout
= jiffies
+ 3 * HZ
;
42 while(!(USB11PHY_READ8(0xf00-0x900+0x10)&0x1)){
43 if(time_after(jiffies
, timeout
)){
51 printk("[USBPHY] Slew Rate Calibration: Timeout\n");
55 data
= USB11PHY_READ32 (0xf00-0x900+0x0c);
56 x
= ((1024*FRA
*PARA
)/data
);
57 value
= (unsigned char)(x
/1000);
58 if((x
-value
*1000)/100>=5)
60 // printk("[USB11PHY]slew calibration:FM_OUT =%d, x=%d,value=%d\n",data,x,value);
63 //4 s8: disable Frequency and run clock.
64 USB11PHY_CLR8 (0xf00-0x900+0x03,0x05);//disable frequency meter
65 USB11PHY_CLR8 (0xf00-0x900+0x11,0x01);//disable free run clock
68 USB11PHY_WRITE8(0x15,value
<<4);
70 //4 s10:disable usb ring oscillator.
71 USB11PHY_CLR8(0x15,0x80);
75 void mt65xx_usb11_phy_poweron(void)
77 INFO("mt65xx_usb11_phy_poweron++\r\n");
79 enable_pll(UNIVPLL
, "USB11");
80 //udelay(100); // PHY power stable time
82 /* reverse preloader's sin @mt6575_usbphy.c */
83 USB11PHY_CLR8(U1PHTCR2
+3, force_usb11_avalid
| force_usb11_bvalid
| force_usb11_sessend
| force_usb11_vbusvalid
);
84 USB11PHY_CLR8(U1PHTCR2
+2, RG_USB11_AVALID
| RG_USB11_BVALID
| RG_USB11_SESSEND
| RG_USB11_VBUSVALID
);
85 USB11PHY_CLR8(U1PHYCR1
+2, force_usb11_en_fs_ls_rcv
| force_usb11_en_fs_ls_tx
);
86 /**************************************/
88 USB11PHY_SET8(U1PHYCR0
+1, RG_USB11_FSLS_ENBGRI
);
90 USB11PHY_SET8(U1PHTCR2
+3, force_usb11_avalid
| force_usb11_sessend
| force_usb11_vbusvalid
);
91 USB11PHY_SET8(U1PHTCR2
+2, RG_USB11_AVALID
| RG_USB11_VBUSVALID
);
92 USB11PHY_CLR8(U1PHTCR2
+2, RG_USB11_SESSEND
);
97 //HQA LOOPBACK TEST. <FS>
98 USB11PHY_CLR8(0x1a, 0x80);
99 USB11PHY_CLR8(0x68, 0x08);
101 USB11PHY_CLR8(0x68, 0x03);
102 USB11PHY_SET8(0x68, 0x10);
104 USB11PHY_SET8(0x68, 0x04);
105 USB11PHY_CLR8(0x69, 0x03);
106 USB11PHY_CLR8(0x69, 0x3C);
108 USB11PHY_SET8(0x68, 0x80);
110 USB11PHY_SET8(0x6a, 0x04);
111 USB11PHY_SET8(0x6a, 0x01);
112 USB11PHY_SET8(0x6a, 0x08);
113 USB11PHY_SET8(0x6a, 0x02);
115 USB11PHY_SET8(0x6a, 0x40);
116 USB11PHY_SET8(0x6a, 0x80);
117 USB11PHY_SET8(0x6a, 0x30);
119 USB11PHY_SET8(0x68, 0x08);
122 USB11PHY_SET8(0x63, 0x02);
125 USB11PHY_SET8(0x63, 0x02);
126 USB11PHY_SET8(0x63, 0x04);
127 USB11PHY_CLR8(0x63, 0x08);
134 //HQA LOOPBACK TEST. <HS>
135 USB11PHY_CLR8(0x1a, 0x80);
136 USB11PHY_CLR8(0x68, 0x08);
138 USB11PHY_CLR8(0x68, 0x03);
139 USB11PHY_CLR8(0x68, 0x30);
141 USB11PHY_CLR8(0x68, 0x04);
142 USB11PHY_CLR8(0x69, 0x03);
143 USB11PHY_CLR8(0x69, 0x3C);
145 USB11PHY_CLR8(0x68, 0xC0);
147 USB11PHY_SET8(0x6a, 0x04);
148 USB11PHY_SET8(0x6a, 0x01);
149 USB11PHY_SET8(0x6a, 0x08);
150 USB11PHY_SET8(0x6a, 0x02);
152 USB11PHY_SET8(0x6a, 0x40);
153 USB11PHY_SET8(0x6a, 0x80);
154 USB11PHY_SET8(0x6a, 0x30);
156 USB11PHY_SET8(0x68, 0x08);
159 USB11PHY_SET8(0x63, 0x02);
162 USB11PHY_SET8(0x63, 0x02);
163 USB11PHY_SET8(0x63, 0x04);
164 USB11PHY_CLR8(0x63, 0x08);
166 usb11_hs_slew_rate_cal();
172 USB11PHY_CLR8(0x6b, 0x04);
173 USB11PHY_CLR8(0x6e, 0x01);
175 USB11PHY_CLR8(0x1a, 0x80);
177 /* remove in MT6588 ?????
178 USBPHY_CLR8(0x02, 0x7f);
179 USBPHY_SET8(0x02, 0x09);
180 USBPHY_CLR8(0x22, 0x03);
183 USB11PHY_CLR8(0x6a, 0x04);
184 //USBPHY_SET8(0x1b, 0x08);
187 USB11PHY_SET8(0x6C, 0x2C);
188 USB11PHY_SET8(0x6D, 0x3C);
190 /* VBUSVALID=0, AVALID=0, BVALID=0, SESSEND=1, IDDIG=X */
191 USB11PHY_SET8(0x6c, 0x10);
192 USB11PHY_CLR8(0x6c, 0x2e);
193 USB11PHY_SET8(0x6d, 0x3e);
197 /* restart session */
199 /* USB MAC ONand Host Mode*/
200 /* VBUSVALID=1, AVALID=1, BVALID=1, SESSEND=0, IDDIG=0 */
201 USB11PHY_CLR8(0x6c, 0x10);
202 USB11PHY_SET8(0x6c, 0x2c);
203 USB11PHY_SET8(0x6d, 0x3e);
209 void mt65xx_usb11_phy_savecurrent(void)
211 INFO("mt65xx_usb11_phy_savecurrent++\r\n");
214 USB11PHY_SET8(U1PHTCR2
+3, force_usb11_avalid
| force_usb11_sessend
| force_usb11_vbusvalid
);
215 USB11PHY_CLR8(U1PHTCR2
+2, RG_USB11_AVALID
| RG_USB11_VBUSVALID
);
216 USB11PHY_SET8(U1PHTCR2
+2, RG_USB11_SESSEND
);
218 USB11PHY_CLR8(U1PHYCR0
+1, RG_USB11_FSLS_ENBGRI
);
220 USB11PHY_SET8(U1PHYCR1
+2, force_usb11_en_fs_ls_rcv
| force_usb11_en_fs_ls_tx
);
221 USB11PHY_CLR8(U1PHYCR1
+3, RG_USB11_EN_FS_LS_RCV
| RG_USB11_EN_FS_LS_TX
);
224 //4 1. swtich to USB function. (system register, force ip into usb mode.
225 USB11PHY_CLR8(0x6b, 0x04);
226 USB11PHY_CLR8(0x6e, 0x01);
228 //4 2. release force suspendm.
229 USB11PHY_CLR8(0x6a, 0x04);
230 //4 3. RG_DPPULLDOWN./RG_DMPULLDOWN.
231 USB11PHY_SET8(0x68, 0xc0);
232 //4 4. RG_XCVRSEL[1:0] =2'b01.
233 USB11PHY_CLR8(0x68, 0x30);
234 USB11PHY_SET8(0x68, 0x10);
235 //4 5. RG_TERMSEL = 1'b1
236 USB11PHY_SET8(0x68, 0x04);
237 //4 6. RG_DATAIN[3:0]=4'b0000
238 USB11PHY_CLR8(0x69, 0x3c);
239 //4 7.force_dp_pulldown, force_dm_pulldown, force_xcversel,force_termsel.
240 USB11PHY_SET8(0x6a, 0xba);
242 //4 8.RG_USB20_BC11_SW_EN 1'b0
243 USB11PHY_CLR8(0x1a, 0x80);
244 //4 9.RG_USB20_OTG_VBUSSCMP_EN 1'b0
245 USB11PHY_CLR8(0x1a, 0x10);
248 //4 11. rg_usb20_pll_stable = 1
249 USB11PHY_SET8(0x63, 0x02);
252 //4 12. force suspendm = 1.
253 USB11PHY_SET8(0x6a, 0x04);
255 USB11PHY_CLR8(0x6C, 0x2C);
256 USB11PHY_SET8(0x6C, 0x10);
257 USB11PHY_CLR8(0x6D, 0x3C);
261 //4 14. turn off internal 48Mhz PLL.
262 disable_pll(UNIVPLL
, "USB11");
265 void mt65xx_usb11_phy_recover(void)
267 INFO("mt65xx_usb11_phy_recover++\r\n");
269 //4 1. turn on USB reference clock.
270 enable_pll(UNIVPLL
, "USB11");
273 USB11PHY_SET8(U1PHTCR2
+3, force_usb11_avalid
| force_usb11_sessend
| force_usb11_vbusvalid
);
274 USB11PHY_SET8(U1PHTCR2
+2, RG_USB11_AVALID
| RG_USB11_VBUSVALID
);
275 USB11PHY_CLR8(U1PHTCR2
+2, RG_USB11_SESSEND
);
277 USB11PHY_CLR8(U1PHYCR1
+2, force_usb11_en_fs_ls_rcv
| force_usb11_en_fs_ls_tx
);
278 USB11PHY_CLR8(U1PHYCR1
+3, RG_USB11_EN_FS_LS_RCV
| RG_USB11_EN_FS_LS_TX
);
280 USB11PHY_SET8(U1PHYCR0
+1, RG_USB11_FSLS_ENBGRI
);
287 //4 3. force_uart_en = 1'b0
288 USB11PHY_CLR8(0x6b, 0x04);
289 //4 4. RG_UART_EN = 1'b0
290 USB11PHY_CLR8(0x6e, 0x1);
291 //4 5. force_uart_en = 1'b0
292 USB11PHY_CLR8(0x6a, 0x04);
294 //4 6. RG_DPPULLDOWN = 1'b0
295 USB11PHY_CLR8(0x68, 0x40);
296 //4 7. RG_DMPULLDOWN = 1'b0
297 USB11PHY_CLR8(0x68, 0x80);
298 //4 8. RG_XCVRSEL = 2'b00
299 USB11PHY_CLR8(0x68, 0x30);
300 //4 9. RG_TERMSEL = 1'b0
301 USB11PHY_CLR8(0x68, 0x04);
302 //4 10. RG_DATAIN[3:0] = 4'b0000
303 USB11PHY_CLR8(0x69, 0x3c);
305 //4 11. force_dp_pulldown = 1b'0
306 USB11PHY_CLR8(0x6a, 0x10);
307 //4 12. force_dm_pulldown = 1b'0
308 USB11PHY_CLR8(0x6a, 0x20);
309 //4 13. force_xcversel = 1b'0
310 USB11PHY_CLR8(0x6a, 0x08);
311 //4 14. force_termsel = 1b'0
312 USB11PHY_CLR8(0x6a, 0x02);
313 //4 15. force_datain = 1b'0
314 USB11PHY_CLR8(0x6a, 0x80);
316 //4 16. RG_USB20_BC11_SW_EN 1'b0
317 USB11PHY_CLR8(0x1a, 0x80);
318 //4 17. RG_USB20_OTG_VBUSSCMP_EN 1'b1
319 USB11PHY_SET8(0x1a, 0x10);
321 USB11PHY_SET8(0x6C, 0x2C);
322 USB11PHY_SET8(0x6D, 0x3C);
323 //<4> 18. wait 800 usec.
326 usb11_hs_slew_rate_cal();
329 static bool clock_enabled
= false;
331 void mt65xx_usb11_clock_enable(bool enable
)
333 INFO("mt65xx_usb11_clock_enable++\r\n");
335 if(clock_enabled
)//already enable
338 enable_clock(MT_CG_PERI_USB0
, "PERI_USB"); //mt8127 PERI_USB1 dependence PERI_USB0
339 enable_clock (MT_CG_PERI_USB1
, "USB11");
340 clock_enabled
= true;
344 if(!clock_enabled
)//already disabled.
347 disable_clock (MT_CG_PERI_USB1
, "USB11");
348 disable_clock (MT_CG_PERI_USB0
, "PERI_USB"); //mt8127 PERI_USB1 dependence PERI_USB0
349 clock_enabled
= false;
356 void mt_usb11_poweron(struct musbfsh
*musbfsh
,int on
){
357 static bool recover
= false;
358 INFO("mt65xx_usb11_poweron++\r\n");
363 mt65xx_usb11_clock_enable (true);
365 //mt65xx_usb11_phy_poweron();
366 mt65xx_usb11_phy_recover();
369 mt65xx_usb11_phy_recover();
371 musbfsh_power
= true;
377 mt65xx_usb11_phy_savecurrent();
378 mt65xx_usb11_clock_enable(false);
379 musbfsh_power
= false;
385 void mt_usb11_set_vbus(struct musbfsh
*musbfsh
, int is_on
)
387 INFO("is_on=%d\n",is_on
);
389 // mt_set_gpio_mode(GPIO67,0);//should set GPIO_OTG_DRVVBUS_PIN as gpio mode.
390 mt_set_gpio_dir(GPIO_OTG_DRVVBUS_PIN
,GPIO_DIR_OUT
);
395 mt_set_gpio_out(GPIO_OTG_DRVVBUS_PIN
,GPIO_OUT_ONE
);
402 mt_set_gpio_out(GPIO_OTG_DRVVBUS_PIN
,GPIO_OUT_ZERO
);
409 void musbfs_check_mpu_violation(u32 addr
, int wr_vio
)
411 void __iomem
*mregs
= (void *)USB_BASE
;
413 printk(KERN_CRIT
"MUSB checks EMI MPU violation.\n");
414 printk(KERN_CRIT
"addr = 0x%x, %s violation.\n", addr
, wr_vio
? "Write": "Read");
415 printk(KERN_CRIT
"POWER = 0x%x,DEVCTL= 0x%x.\n", musbfsh_readb(mregs
, MUSBFSH_POWER
),musbfsh_readb((void __iomem
*)USB11_BASE
,MUSBFSH_DEVCTL
));
416 printk(KERN_CRIT
"DMA_CNTLch0 0x%04x,DMA_ADDRch0 0x%08x,DMA_COUNTch0 0x%08x \n",musbfsh_readw(mregs
, 0x204),musbfsh_readl(mregs
,0x208),musbfsh_readl(mregs
,0x20C));
417 printk(KERN_CRIT
"DMA_CNTLch1 0x%04x,DMA_ADDRch1 0x%08x,DMA_COUNTch1 0x%08x \n",musbfsh_readw(mregs
, 0x214),musbfsh_readl(mregs
,0x218),musbfsh_readl(mregs
,0x21C));
418 printk(KERN_CRIT
"DMA_CNTLch2 0x%04x,DMA_ADDRch2 0x%08x,DMA_COUNTch2 0x%08x \n",musbfsh_readw(mregs
, 0x224),musbfsh_readl(mregs
,0x228),musbfsh_readl(mregs
,0x22C));
419 printk(KERN_CRIT
"DMA_CNTLch3 0x%04x,DMA_ADDRch3 0x%08x,DMA_COUNTch3 0x%08x \n",musbfsh_readw(mregs
, 0x234),musbfsh_readl(mregs
,0x238),musbfsh_readl(mregs
,0x23C));
420 printk(KERN_CRIT
"DMA_CNTLch4 0x%04x,DMA_ADDRch4 0x%08x,DMA_COUNTch4 0x%08x \n",musbfsh_readw(mregs
, 0x244),musbfsh_readl(mregs
,0x248),musbfsh_readl(mregs
,0x24C));
421 printk(KERN_CRIT
"DMA_CNTLch5 0x%04x,DMA_ADDRch5 0x%08x,DMA_COUNTch5 0x%08x \n",musbfsh_readw(mregs
, 0x254),musbfsh_readl(mregs
,0x258),musbfsh_readl(mregs
,0x25C));
422 printk(KERN_CRIT
"DMA_CNTLch6 0x%04x,DMA_ADDRch6 0x%08x,DMA_COUNTch6 0x%08x \n",musbfsh_readw(mregs
, 0x264),musbfsh_readl(mregs
,0x268),musbfsh_readl(mregs
,0x26C));
423 printk(KERN_CRIT
"DMA_CNTLch7 0x%04x,DMA_ADDRch7 0x%08x,DMA_COUNTch7 0x%08x \n",musbfsh_readw(mregs
, 0x274),musbfsh_readl(mregs
,0x278),musbfsh_readl(mregs
,0x27C));
426 int mt_usb11_init(struct musbfsh
*musbfsh
)
430 ERR("musbfsh_platform_init,error,musbfsh is NULL");
433 hwPowerOn(MT65XX_POWER_LDO_VUSB
, VOL_3300
, "USB11"); // don't need to power on PHY for every resume
434 mt_usb11_poweron(musbfsh
,true);
435 // emi_mpu_notifier_register(MST_ID_MMPERI_2, musbfs_check_mpu_violation);
439 int mt_usb11_exit(struct musbfsh
*musbfsh
)
442 mt_usb11_poweron(musbfsh
,false);
443 // put it here because we can't shutdown PHY power during suspend
444 hwPowerDown(MT65XX_POWER_LDO_VUSB
, "USB11");
448 void musbfsh_hcd_release (struct device
*dev
)
450 INFO("musbfsh_hcd_release++,dev = 0x%08X.\n", (uint32_t)dev
);
453 static const struct musbfsh_platform_ops mt_usb11_ops
= {
454 .init
= mt_usb11_init
,
455 .exit
= mt_usb11_exit
,
456 .set_vbus
= mt_usb11_set_vbus
,
457 .set_power
= mt_usb11_poweron
,
460 static u64 mt_usb11_dmamask
= DMA_BIT_MASK(32);
462 static int __init
mt_usb11_probe(struct platform_device
*pdev
)
464 struct musbfsh_hdrc_platform_data
*pdata
= pdev
->dev
.platform_data
;
465 struct platform_device
*musbfsh
;
466 struct mt_usb11_glue
*glue
;
470 glue
= kzalloc(sizeof(*glue
), GFP_KERNEL
);
472 dev_err(&pdev
->dev
, "failed to allocate glue context\n");
476 /* get the musbfsh id */
477 musbfshid
= musbfsh_get_id(&pdev
->dev
, GFP_KERNEL
);
479 dev_err(&pdev
->dev
, "failed to allocate musbfsh id\n");
484 musbfsh
= platform_device_alloc("musbfsh-hdrc", musbfshid
);
486 dev_err(&pdev
->dev
, "failed to allocate musb device\n");
490 musbfsh
->id
= musbfshid
;
491 musbfsh
->dev
.parent
= &pdev
->dev
;
492 musbfsh
->dev
.dma_mask
= &mt_usb11_dmamask
;
493 musbfsh
->dev
.coherent_dma_mask
= mt_usb11_dmamask
;
495 glue
->dev
= &pdev
->dev
;
496 glue
->musbfsh
= musbfsh
;
498 pdata
->platform_ops
= &mt_usb11_ops
;
500 platform_set_drvdata(pdev
, glue
);
502 ret
= platform_device_add_resources(musbfsh
, pdev
->resource
,
503 pdev
->num_resources
);
505 dev_err(&pdev
->dev
, "failed to add resources\n");
509 ret
= platform_device_add_data(musbfsh
, pdata
, sizeof(*pdata
));
511 dev_err(&pdev
->dev
, "failed to add platform_data\n");
515 ret
= platform_device_add(musbfsh
);
518 dev_err(&pdev
->dev
, "failed to register musbfsh device\n");
525 platform_device_put(musbfsh
);
528 musbfsh_put_id(&pdev
->dev
, musbfshid
);
537 static int __exit
mt_usb_remove(struct platform_device
*pdev
)
539 struct mt_usb11_glue
*glue
= platform_get_drvdata(pdev
);
541 musbfsh_put_id(&pdev
->dev
, glue
->musbfsh
->id
);
542 platform_device_del(glue
->musbfsh
);
543 platform_device_put(glue
->musbfsh
);
549 static struct platform_driver mt_usb11_driver
= {
550 .remove
= __exit_p(mt_usb_remove
),
551 .probe
= mt_usb11_probe
,
557 static int __init
usb11_init(void)
559 return platform_driver_register(&mt_usb11_driver
);
561 subsys_initcall(usb11_init
);
563 static void __exit
usb11_exit(void)
565 platform_driver_unregister(&mt_usb11_driver
);
567 module_exit(usb11_exit
)