Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 #include <linux/kernel.h>
0003 #include <linux/device.h>
0004 #include <linux/types.h>
0005 #include <linux/spinlock.h>
0006 #include <linux/debugfs.h>
0007 #include <linux/seq_file.h>
0008 #include <linux/uaccess.h>
0009 #include <linux/usb/ch9.h>
0010 #include <linux/usb/gadget.h>
0011 #include <linux/usb/phy.h>
0012 #include <linux/usb/otg.h>
0013 #include <linux/usb/otg-fsm.h>
0014 #include <linux/usb/chipidea.h>
0015 
0016 #include "ci.h"
0017 #include "udc.h"
0018 #include "bits.h"
0019 #include "otg.h"
0020 
0021 /*
0022  * ci_device_show: prints information about device capabilities and status
0023  */
0024 static int ci_device_show(struct seq_file *s, void *data)
0025 {
0026     struct ci_hdrc *ci = s->private;
0027     struct usb_gadget *gadget = &ci->gadget;
0028 
0029     seq_printf(s, "speed             = %d\n", gadget->speed);
0030     seq_printf(s, "max_speed         = %d\n", gadget->max_speed);
0031     seq_printf(s, "is_otg            = %d\n", gadget->is_otg);
0032     seq_printf(s, "is_a_peripheral   = %d\n", gadget->is_a_peripheral);
0033     seq_printf(s, "b_hnp_enable      = %d\n", gadget->b_hnp_enable);
0034     seq_printf(s, "a_hnp_support     = %d\n", gadget->a_hnp_support);
0035     seq_printf(s, "a_alt_hnp_support = %d\n", gadget->a_alt_hnp_support);
0036     seq_printf(s, "name              = %s\n",
0037            (gadget->name ? gadget->name : ""));
0038 
0039     if (!ci->driver)
0040         return 0;
0041 
0042     seq_printf(s, "gadget function   = %s\n",
0043                (ci->driver->function ? ci->driver->function : ""));
0044     seq_printf(s, "gadget max speed  = %d\n", ci->driver->max_speed);
0045 
0046     return 0;
0047 }
0048 DEFINE_SHOW_ATTRIBUTE(ci_device);
0049 
0050 /*
0051  * ci_port_test_show: reads port test mode
0052  */
0053 static int ci_port_test_show(struct seq_file *s, void *data)
0054 {
0055     struct ci_hdrc *ci = s->private;
0056     unsigned long flags;
0057     unsigned mode;
0058 
0059     pm_runtime_get_sync(ci->dev);
0060     spin_lock_irqsave(&ci->lock, flags);
0061     mode = hw_port_test_get(ci);
0062     spin_unlock_irqrestore(&ci->lock, flags);
0063     pm_runtime_put_sync(ci->dev);
0064 
0065     seq_printf(s, "mode = %u\n", mode);
0066 
0067     return 0;
0068 }
0069 
0070 /*
0071  * ci_port_test_write: writes port test mode
0072  */
0073 static ssize_t ci_port_test_write(struct file *file, const char __user *ubuf,
0074                   size_t count, loff_t *ppos)
0075 {
0076     struct seq_file *s = file->private_data;
0077     struct ci_hdrc *ci = s->private;
0078     unsigned long flags;
0079     unsigned mode;
0080     char buf[32];
0081     int ret;
0082 
0083     count = min_t(size_t, sizeof(buf) - 1, count);
0084     if (copy_from_user(buf, ubuf, count))
0085         return -EFAULT;
0086 
0087     /* sscanf requires a zero terminated string */
0088     buf[count] = '\0';
0089 
0090     if (sscanf(buf, "%u", &mode) != 1)
0091         return -EINVAL;
0092 
0093     if (mode > 255)
0094         return -EBADRQC;
0095 
0096     pm_runtime_get_sync(ci->dev);
0097     spin_lock_irqsave(&ci->lock, flags);
0098     ret = hw_port_test_set(ci, mode);
0099     spin_unlock_irqrestore(&ci->lock, flags);
0100     pm_runtime_put_sync(ci->dev);
0101 
0102     return ret ? ret : count;
0103 }
0104 
0105 static int ci_port_test_open(struct inode *inode, struct file *file)
0106 {
0107     return single_open(file, ci_port_test_show, inode->i_private);
0108 }
0109 
0110 static const struct file_operations ci_port_test_fops = {
0111     .open       = ci_port_test_open,
0112     .write      = ci_port_test_write,
0113     .read       = seq_read,
0114     .llseek     = seq_lseek,
0115     .release    = single_release,
0116 };
0117 
0118 /*
0119  * ci_qheads_show: DMA contents of all queue heads
0120  */
0121 static int ci_qheads_show(struct seq_file *s, void *data)
0122 {
0123     struct ci_hdrc *ci = s->private;
0124     unsigned long flags;
0125     unsigned i, j;
0126 
0127     if (ci->role != CI_ROLE_GADGET) {
0128         seq_printf(s, "not in gadget mode\n");
0129         return 0;
0130     }
0131 
0132     spin_lock_irqsave(&ci->lock, flags);
0133     for (i = 0; i < ci->hw_ep_max/2; i++) {
0134         struct ci_hw_ep *hweprx = &ci->ci_hw_ep[i];
0135         struct ci_hw_ep *hweptx =
0136             &ci->ci_hw_ep[i + ci->hw_ep_max/2];
0137         seq_printf(s, "EP=%02i: RX=%08X TX=%08X\n",
0138                i, (u32)hweprx->qh.dma, (u32)hweptx->qh.dma);
0139         for (j = 0; j < (sizeof(struct ci_hw_qh)/sizeof(u32)); j++)
0140             seq_printf(s, " %04X:    %08X    %08X\n", j,
0141                    *((u32 *)hweprx->qh.ptr + j),
0142                    *((u32 *)hweptx->qh.ptr + j));
0143     }
0144     spin_unlock_irqrestore(&ci->lock, flags);
0145 
0146     return 0;
0147 }
0148 DEFINE_SHOW_ATTRIBUTE(ci_qheads);
0149 
0150 /*
0151  * ci_requests_show: DMA contents of all requests currently queued (all endpts)
0152  */
0153 static int ci_requests_show(struct seq_file *s, void *data)
0154 {
0155     struct ci_hdrc *ci = s->private;
0156     unsigned long flags;
0157     struct ci_hw_req *req = NULL;
0158     struct td_node *node, *tmpnode;
0159     unsigned i, j, qsize = sizeof(struct ci_hw_td)/sizeof(u32);
0160 
0161     if (ci->role != CI_ROLE_GADGET) {
0162         seq_printf(s, "not in gadget mode\n");
0163         return 0;
0164     }
0165 
0166     spin_lock_irqsave(&ci->lock, flags);
0167     for (i = 0; i < ci->hw_ep_max; i++)
0168         list_for_each_entry(req, &ci->ci_hw_ep[i].qh.queue, queue) {
0169             list_for_each_entry_safe(node, tmpnode, &req->tds, td) {
0170                 seq_printf(s, "EP=%02i: TD=%08X %s\n",
0171                        i % (ci->hw_ep_max / 2),
0172                        (u32)node->dma,
0173                        ((i < ci->hw_ep_max/2) ?
0174                        "RX" : "TX"));
0175 
0176                 for (j = 0; j < qsize; j++)
0177                     seq_printf(s, " %04X:    %08X\n", j,
0178                            *((u32 *)node->ptr + j));
0179             }
0180         }
0181     spin_unlock_irqrestore(&ci->lock, flags);
0182 
0183     return 0;
0184 }
0185 DEFINE_SHOW_ATTRIBUTE(ci_requests);
0186 
0187 static int ci_otg_show(struct seq_file *s, void *unused)
0188 {
0189     struct ci_hdrc *ci = s->private;
0190     struct otg_fsm *fsm;
0191 
0192     if (!ci || !ci_otg_is_fsm_mode(ci))
0193         return 0;
0194 
0195     fsm = &ci->fsm;
0196 
0197     /* ------ State ----- */
0198     seq_printf(s, "OTG state: %s\n\n",
0199             usb_otg_state_string(ci->otg.state));
0200 
0201     /* ------ State Machine Variables ----- */
0202     seq_printf(s, "a_bus_drop: %d\n", fsm->a_bus_drop);
0203 
0204     seq_printf(s, "a_bus_req: %d\n", fsm->a_bus_req);
0205 
0206     seq_printf(s, "a_srp_det: %d\n", fsm->a_srp_det);
0207 
0208     seq_printf(s, "a_vbus_vld: %d\n", fsm->a_vbus_vld);
0209 
0210     seq_printf(s, "b_conn: %d\n", fsm->b_conn);
0211 
0212     seq_printf(s, "adp_change: %d\n", fsm->adp_change);
0213 
0214     seq_printf(s, "power_up: %d\n", fsm->power_up);
0215 
0216     seq_printf(s, "a_bus_resume: %d\n", fsm->a_bus_resume);
0217 
0218     seq_printf(s, "a_bus_suspend: %d\n", fsm->a_bus_suspend);
0219 
0220     seq_printf(s, "a_conn: %d\n", fsm->a_conn);
0221 
0222     seq_printf(s, "b_bus_req: %d\n", fsm->b_bus_req);
0223 
0224     seq_printf(s, "b_bus_suspend: %d\n", fsm->b_bus_suspend);
0225 
0226     seq_printf(s, "b_se0_srp: %d\n", fsm->b_se0_srp);
0227 
0228     seq_printf(s, "b_ssend_srp: %d\n", fsm->b_ssend_srp);
0229 
0230     seq_printf(s, "b_sess_vld: %d\n", fsm->b_sess_vld);
0231 
0232     seq_printf(s, "b_srp_done: %d\n", fsm->b_srp_done);
0233 
0234     seq_printf(s, "drv_vbus: %d\n", fsm->drv_vbus);
0235 
0236     seq_printf(s, "loc_conn: %d\n", fsm->loc_conn);
0237 
0238     seq_printf(s, "loc_sof: %d\n", fsm->loc_sof);
0239 
0240     seq_printf(s, "adp_prb: %d\n", fsm->adp_prb);
0241 
0242     seq_printf(s, "id: %d\n", fsm->id);
0243 
0244     seq_printf(s, "protocol: %d\n", fsm->protocol);
0245 
0246     return 0;
0247 }
0248 DEFINE_SHOW_ATTRIBUTE(ci_otg);
0249 
0250 static int ci_role_show(struct seq_file *s, void *data)
0251 {
0252     struct ci_hdrc *ci = s->private;
0253 
0254     if (ci->role != CI_ROLE_END)
0255         seq_printf(s, "%s\n", ci_role(ci)->name);
0256 
0257     return 0;
0258 }
0259 
0260 static ssize_t ci_role_write(struct file *file, const char __user *ubuf,
0261                  size_t count, loff_t *ppos)
0262 {
0263     struct seq_file *s = file->private_data;
0264     struct ci_hdrc *ci = s->private;
0265     enum ci_role role;
0266     char buf[8];
0267     int ret;
0268 
0269     if (copy_from_user(buf, ubuf, min_t(size_t, sizeof(buf) - 1, count)))
0270         return -EFAULT;
0271 
0272     for (role = CI_ROLE_HOST; role < CI_ROLE_END; role++)
0273         if (ci->roles[role] &&
0274             !strncmp(buf, ci->roles[role]->name,
0275                  strlen(ci->roles[role]->name)))
0276             break;
0277 
0278     if (role == CI_ROLE_END || role == ci->role)
0279         return -EINVAL;
0280 
0281     pm_runtime_get_sync(ci->dev);
0282     disable_irq(ci->irq);
0283     ci_role_stop(ci);
0284     ret = ci_role_start(ci, role);
0285     enable_irq(ci->irq);
0286     pm_runtime_put_sync(ci->dev);
0287 
0288     return ret ? ret : count;
0289 }
0290 
0291 static int ci_role_open(struct inode *inode, struct file *file)
0292 {
0293     return single_open(file, ci_role_show, inode->i_private);
0294 }
0295 
0296 static const struct file_operations ci_role_fops = {
0297     .open       = ci_role_open,
0298     .write      = ci_role_write,
0299     .read       = seq_read,
0300     .llseek     = seq_lseek,
0301     .release    = single_release,
0302 };
0303 
0304 static int ci_registers_show(struct seq_file *s, void *unused)
0305 {
0306     struct ci_hdrc *ci = s->private;
0307     u32 tmp_reg;
0308 
0309     if (!ci || ci->in_lpm)
0310         return -EPERM;
0311 
0312     /* ------ Registers ----- */
0313     tmp_reg = hw_read_intr_enable(ci);
0314     seq_printf(s, "USBINTR reg: %08x\n", tmp_reg);
0315 
0316     tmp_reg = hw_read_intr_status(ci);
0317     seq_printf(s, "USBSTS reg: %08x\n", tmp_reg);
0318 
0319     tmp_reg = hw_read(ci, OP_USBMODE, ~0);
0320     seq_printf(s, "USBMODE reg: %08x\n", tmp_reg);
0321 
0322     tmp_reg = hw_read(ci, OP_USBCMD, ~0);
0323     seq_printf(s, "USBCMD reg: %08x\n", tmp_reg);
0324 
0325     tmp_reg = hw_read(ci, OP_PORTSC, ~0);
0326     seq_printf(s, "PORTSC reg: %08x\n", tmp_reg);
0327 
0328     if (ci->is_otg) {
0329         tmp_reg = hw_read_otgsc(ci, ~0);
0330         seq_printf(s, "OTGSC reg: %08x\n", tmp_reg);
0331     }
0332 
0333     return 0;
0334 }
0335 DEFINE_SHOW_ATTRIBUTE(ci_registers);
0336 
0337 /**
0338  * dbg_create_files: initializes the attribute interface
0339  * @ci: device
0340  *
0341  * This function returns an error code
0342  */
0343 void dbg_create_files(struct ci_hdrc *ci)
0344 {
0345     struct dentry *dir;
0346 
0347     dir = debugfs_create_dir(dev_name(ci->dev), usb_debug_root);
0348 
0349     debugfs_create_file("device", S_IRUGO, dir, ci, &ci_device_fops);
0350     debugfs_create_file("port_test", S_IRUGO | S_IWUSR, dir, ci, &ci_port_test_fops);
0351     debugfs_create_file("qheads", S_IRUGO, dir, ci, &ci_qheads_fops);
0352     debugfs_create_file("requests", S_IRUGO, dir, ci, &ci_requests_fops);
0353 
0354     if (ci_otg_is_fsm_mode(ci))
0355         debugfs_create_file("otg", S_IRUGO, dir, ci, &ci_otg_fops);
0356 
0357     debugfs_create_file("role", S_IRUGO | S_IWUSR, dir, ci, &ci_role_fops);
0358     debugfs_create_file("registers", S_IRUGO, dir, ci, &ci_registers_fops);
0359 }
0360 
0361 /**
0362  * dbg_remove_files: destroys the attribute interface
0363  * @ci: device
0364  */
0365 void dbg_remove_files(struct ci_hdrc *ci)
0366 {
0367     debugfs_remove(debugfs_lookup(dev_name(ci->dev), usb_debug_root));
0368 }