diff options
author | John Crispin <john@openwrt.org> | 2014-01-19 17:27:13 +0000 |
---|---|---|
committer | John Crispin <john@openwrt.org> | 2014-01-19 17:27:13 +0000 |
commit | a75b69255725501082bb3cbd89d8579f199dafbf (patch) | |
tree | 3d808ec9345e90800bf952708864bf59580620d3 /target/linux/ramips/files/drivers/usb/host/xhci-mtk.c | |
parent | 2f5f49896988770df916a0c00e6cb96b05d03151 (diff) | |
download | upstream-a75b69255725501082bb3cbd89d8579f199dafbf.tar.gz upstream-a75b69255725501082bb3cbd89d8579f199dafbf.tar.bz2 upstream-a75b69255725501082bb3cbd89d8579f199dafbf.zip |
ralink: add xhci driver
Signed-off-by: John Crispin <blogic@openwrt.org>
SVN-Revision: 39328
Diffstat (limited to 'target/linux/ramips/files/drivers/usb/host/xhci-mtk.c')
-rw-r--r-- | target/linux/ramips/files/drivers/usb/host/xhci-mtk.c | 265 |
1 files changed, 265 insertions, 0 deletions
diff --git a/target/linux/ramips/files/drivers/usb/host/xhci-mtk.c b/target/linux/ramips/files/drivers/usb/host/xhci-mtk.c new file mode 100644 index 0000000000..2eed0a174a --- /dev/null +++ b/target/linux/ramips/files/drivers/usb/host/xhci-mtk.c @@ -0,0 +1,265 @@ +#include "xhci-mtk.h" +#include "xhci-mtk-power.h" +#include "xhci.h" +#include "mtk-phy.h" +#ifdef CONFIG_C60802_SUPPORT +#include "mtk-phy-c60802.h" +#endif +#include "xhci-mtk-scheduler.h" +#include <linux/kernel.h> /* printk() */ +#include <linux/slab.h> +#include <linux/delay.h> +#include <asm/uaccess.h> +#include <linux/dma-mapping.h> +#include <linux/platform_device.h> + +void setInitialReg(void ) +{ + __u32 __iomem *addr; + u32 temp; + + /* set SSUSB DMA burst size to 128B */ + addr = SSUSB_U3_XHCI_BASE + SSUSB_HDMA_CFG; + temp = SSUSB_HDMA_CFG_MT7621_VALUE; + writel(temp, addr); + + /* extend U3 LTSSM Polling.LFPS timeout value */ + addr = SSUSB_U3_XHCI_BASE + U3_LTSSM_TIMING_PARAMETER3; + temp = U3_LTSSM_TIMING_PARAMETER3_VALUE; + writel(temp, addr); + + /* EOF */ + addr = SSUSB_U3_XHCI_BASE + SYNC_HS_EOF; + temp = SYNC_HS_EOF_VALUE; + writel(temp, addr); + +#if defined (CONFIG_PERIODIC_ENP) + /* HSCH_CFG1: SCH2_FIFO_DEPTH */ + addr = SSUSB_U3_XHCI_BASE + HSCH_CFG1; + temp = readl(addr); + temp &= ~(0x3 << SCH2_FIFO_DEPTH_OFFSET); + writel(temp, addr); +#endif + + /* Doorbell handling */ + addr = SIFSLV_IPPC + SSUSB_IP_SPAR0; + temp = 0x1; + writel(temp, addr); + + /* Set SW PLL Stable mode to 1 for U2 LPM device remote wakeup */ + /* Port 0 */ + addr = U2_PHY_BASE + U2_PHYD_CR1; + temp = readl(addr); + temp &= ~(0x3 << 18); + temp |= (1 << 18); + writel(temp, addr); + + /* Port 1 */ + addr = U2_PHY_BASE_P1 + U2_PHYD_CR1; + temp = readl(addr); + temp &= ~(0x3 << 18); + temp |= (1 << 18); + writel(temp, addr); +} + + +void setLatchSel(void){ + __u32 __iomem *latch_sel_addr; + u32 latch_sel_value; + latch_sel_addr = U3_PIPE_LATCH_SEL_ADD; + latch_sel_value = ((U3_PIPE_LATCH_TX)<<2) | (U3_PIPE_LATCH_RX); + writel(latch_sel_value, latch_sel_addr); +} + +void reinitIP(void){ + __u32 __iomem *ip_reset_addr; + u32 ip_reset_value; + + enableAllClockPower(); + mtk_xhci_scheduler_init(); +} + +void dbg_prb_out(void){ + mtk_probe_init(0x0f0f0f0f); + mtk_probe_out(0xffffffff); + mtk_probe_out(0x01010101); + mtk_probe_out(0x02020202); + mtk_probe_out(0x04040404); + mtk_probe_out(0x08080808); + mtk_probe_out(0x10101010); + mtk_probe_out(0x20202020); + mtk_probe_out(0x40404040); + mtk_probe_out(0x80808080); + mtk_probe_out(0x55555555); + mtk_probe_out(0xaaaaaaaa); +} + + + +/////////////////////////////////////////////////////////////////////////////// + +#define RET_SUCCESS 0 +#define RET_FAIL 1 + +static int dbg_u3w(int argc, char**argv) +{ + int u4TimingValue; + char u1TimingValue; + int u4TimingAddress; + + if (argc<3) + { + printk(KERN_ERR "Arg: address value\n"); + return RET_FAIL; + } + u3phy_init(); + + u4TimingAddress = (int)simple_strtol(argv[1], &argv[1], 16); + u4TimingValue = (int)simple_strtol(argv[2], &argv[2], 16); + u1TimingValue = u4TimingValue & 0xff; + /* access MMIO directly */ + writel(u1TimingValue, u4TimingAddress); + printk(KERN_ERR "Write done\n"); + return RET_SUCCESS; + +} + +static int dbg_u3r(int argc, char**argv) +{ + char u1ReadTimingValue; + int u4TimingAddress; + if (argc<2) + { + printk(KERN_ERR "Arg: address\n"); + return 0; + } + u3phy_init(); + mdelay(500); + u4TimingAddress = (int)simple_strtol(argv[1], &argv[1], 16); + /* access MMIO directly */ + u1ReadTimingValue = readl(u4TimingAddress); + printk(KERN_ERR "Value = 0x%x\n", u1ReadTimingValue); + return 0; +} + +static int dbg_u3init(int argc, char**argv) +{ + int ret; + ret = u3phy_init(); + printk(KERN_ERR "phy registers and operations initial done\n"); + if(u3phy_ops->u2_slew_rate_calibration){ + u3phy_ops->u2_slew_rate_calibration(u3phy); + } + else{ + printk(KERN_ERR "WARN: PHY doesn't implement u2 slew rate calibration function\n"); + } + if(u3phy_ops->init(u3phy) == PHY_TRUE) + return RET_SUCCESS; + return RET_FAIL; +} + +void dbg_setU1U2(int argc, char**argv){ + struct xhci_hcd *xhci; + int u1_value; + int u2_value; + u32 port_id, temp; + u32 __iomem *addr; + + if (argc<3) + { + printk(KERN_ERR "Arg: u1value u2value\n"); + return RET_FAIL; + } + + u1_value = (int)simple_strtol(argv[1], &argv[1], 10); + u2_value = (int)simple_strtol(argv[2], &argv[2], 10); + addr = (SSUSB_U3_XHCI_BASE + 0x424); + temp = readl(addr); + temp = temp & (~(0x0000ffff)); + temp = temp | u1_value | (u2_value<<8); + writel(temp, addr); +} +/////////////////////////////////////////////////////////////////////////////// + +int call_function(char *buf) +{ + int i; + int argc; + char *argv[80]; + + argc = 0; + do + { + argv[argc] = strsep(&buf, " "); + printk(KERN_DEBUG "[%d] %s\r\n", argc, argv[argc]); + argc++; + } while (buf); + if (!strcmp("dbg.r", argv[0])) + dbg_prb_out(); + else if (!strcmp("dbg.u3w", argv[0])) + dbg_u3w(argc, argv); + else if (!strcmp("dbg.u3r", argv[0])) + dbg_u3r(argc, argv); + else if (!strcmp("dbg.u3i", argv[0])) + dbg_u3init(argc, argv); + else if (!strcmp("pw.u1u2", argv[0])) + dbg_setU1U2(argc, argv); + return 0; +} + +long xhci_mtk_test_unlock_ioctl(struct file *file, unsigned int cmd, unsigned long arg) +{ + char w_buf[200]; + char r_buf[200] = "this is a test"; + int len = 200; + + switch (cmd) { + case IOCTL_READ: + copy_to_user((char *) arg, r_buf, len); + printk(KERN_DEBUG "IOCTL_READ: %s\r\n", r_buf); + break; + case IOCTL_WRITE: + copy_from_user(w_buf, (char *) arg, len); + printk(KERN_DEBUG "IOCTL_WRITE: %s\r\n", w_buf); + + //invoke function + return call_function(w_buf); + break; + default: + return -ENOTTY; + } + + return len; +} + +int xhci_mtk_test_open(struct inode *inode, struct file *file) +{ + + printk(KERN_DEBUG "xhci_mtk_test open: successful\n"); + return 0; +} + +int xhci_mtk_test_release(struct inode *inode, struct file *file) +{ + + printk(KERN_DEBUG "xhci_mtk_test release: successful\n"); + return 0; +} + +ssize_t xhci_mtk_test_read(struct file *file, char *buf, size_t count, loff_t *ptr) +{ + + printk(KERN_DEBUG "xhci_mtk_test read: returning zero bytes\n"); + return 0; +} + +ssize_t xhci_mtk_test_write(struct file *file, const char *buf, size_t count, loff_t * ppos) +{ + + printk(KERN_DEBUG "xhci_mtk_test write: accepting zero bytes\n"); + return 0; +} + + + + |