#include <linux/init.h> #include <linux/version.h> #include <linux/module.h> #include <linux/kernel.h> #include <linux/cdev.h> #include <linux/proc_fs.h> #include <linux/seq_file.h> #include <linux/spinlock.h> #include <linux/gpio.h> #include <linux/delay.h> #include <bspchip.h> #include <bspgpio.h> #include <rtl_usb_phy.h> extern struct proc_dir_entry *realtek_proc; static void show_usage(void){ //printk("echo [command] [arg...] > /proc/realtek/rtk_usb_phy\n"); //printk("command : \n"); //printk(" help : show controlling commands\n"); printk(" w [reg] [value] : write [value] to [reg] of port1 (value should be 8 bits, reg should be in [E0-E7], [F0-F6])\n"); //printk("cat /proc/realtek/rtk_usb_phy\n"); //printk(" dump all usb phy's registers to console\n"); } static ssize_t usb_proc_write(struct file * file, const char __user * userbuf, size_t count, loff_t * off) { char buf[32]; int len; u8 reg; u16 val; struct rtk_usb_phy *phy = PDE_DATA(file_inode(file)); len = min(sizeof(buf), count); if (copy_from_user(buf, userbuf, len)) return -E2BIG; if (strncmp(buf, "help", 4) == 0) { show_usage(); } else if (strncmp(buf, "w ", 2) == 0) { if(2==sscanf(buf, "w %hhx %hx", ®, &val)){ //printk("EHCI: write %hhx to phy port %d, phy(%hhx)\n", val, PHY_PORT, reg); //ehci_phy_write(PHY_PORT, reg, val); if (phy->phy_write(phy, phy->port, reg, val)) return -EINVAL; } else{ goto ERROR_PARA; } } else if (strncmp(buf, "r ", 2) == 0) { if(1==sscanf(buf, "r %hhx", ®)){ if (phy->phy_read(phy, phy->port, reg, &val)) return -EINVAL; printk("%02x = %02x\n", reg, val); } } else { goto ERROR_PARA; } return count; ERROR_PARA: printk("error parameter...\n"); show_usage(); return -EPERM; } #define ITEM_PER_LINE 4 static int rtk_usb_phy_show(struct seq_file *s, void *v) { struct rtk_usb_phy *phy = s->private; int reg = -1, n = 0; u16 data; while (0==phy->phy_get_next(phy, phy->port, ®)) { n++; if (0==phy->phy_read(phy, phy->port, reg, &data)) seq_printf(s, "%02x: %4x ", reg, data); else seq_printf(s, "%02x: err ", reg); if ((n%ITEM_PER_LINE)==0) seq_printf(s, "\n"); } seq_printf(s, "\n"); return 0; } static int rtk_usb_phy_open(struct inode *inode, struct file *file) { return(single_open(file, rtk_usb_phy_show, PDE_DATA(inode))); } static const struct file_operations fops_rtk_usb_phy = { .open = rtk_usb_phy_open, .write = usb_proc_write, .read = seq_read, .llseek = seq_lseek, .release = single_release, }; int rtk_usb_phy_register(struct rtk_usb_phy *phy) { struct proc_dir_entry *e; if (phy->phy_init) phy->phy_init(phy); e = proc_create_data(phy->name, S_IRUGO | S_IWUSR, realtek_proc, &fops_rtk_usb_phy, phy); if (!e) { printk("Failed to register USB_PHY %s\n", phy->name); return -EINVAL; } return 0; } EXPORT_SYMBOL(rtk_usb_phy_register); MODULE_DESCRIPTION("Realtek USB proc module"); MODULE_AUTHOR("Scott Wu <scott27585206@realtek.com>"); MODULE_LICENSE("GPL");