Linux Audio

Check our new training course

Loading...
v5.9
  1// SPDX-License-Identifier: GPL-2.0
  2#include <linux/kernel.h>
  3#include <linux/device.h>
  4#include <linux/types.h>
  5#include <linux/spinlock.h>
  6#include <linux/debugfs.h>
  7#include <linux/seq_file.h>
  8#include <linux/uaccess.h>
 
 
 
 
 
 
  9#include <linux/usb/ch9.h>
 10#include <linux/usb/gadget.h>
 11#include <linux/usb/phy.h>
 12#include <linux/usb/otg.h>
 13#include <linux/usb/otg-fsm.h>
 14#include <linux/usb/chipidea.h>
 15
 16#include "ci.h"
 17#include "udc.h"
 18#include "bits.h"
 19#include "otg.h"
 20
 21/*
 22 * ci_device_show: prints information about device capabilities and status
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 23 */
 24static int ci_device_show(struct seq_file *s, void *data)
 25{
 26	struct ci_hdrc *ci = s->private;
 27	struct usb_gadget *gadget = &ci->gadget;
 28
 29	seq_printf(s, "speed             = %d\n", gadget->speed);
 30	seq_printf(s, "max_speed         = %d\n", gadget->max_speed);
 31	seq_printf(s, "is_otg            = %d\n", gadget->is_otg);
 32	seq_printf(s, "is_a_peripheral   = %d\n", gadget->is_a_peripheral);
 33	seq_printf(s, "b_hnp_enable      = %d\n", gadget->b_hnp_enable);
 34	seq_printf(s, "a_hnp_support     = %d\n", gadget->a_hnp_support);
 35	seq_printf(s, "a_alt_hnp_support = %d\n", gadget->a_alt_hnp_support);
 36	seq_printf(s, "name              = %s\n",
 37		   (gadget->name ? gadget->name : ""));
 38
 39	if (!ci->driver)
 40		return 0;
 
 
 
 41
 42	seq_printf(s, "gadget function   = %s\n",
 43		       (ci->driver->function ? ci->driver->function : ""));
 44	seq_printf(s, "gadget max speed  = %d\n", ci->driver->max_speed);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 45
 
 46	return 0;
 47}
 48DEFINE_SHOW_ATTRIBUTE(ci_device);
 49
 50/*
 51 * ci_port_test_show: reads port test mode
 
 
 
 
 52 */
 53static int ci_port_test_show(struct seq_file *s, void *data)
 54{
 55	struct ci_hdrc *ci = s->private;
 56	unsigned long flags;
 57	unsigned mode;
 58
 59	pm_runtime_get_sync(ci->dev);
 60	spin_lock_irqsave(&ci->lock, flags);
 61	mode = hw_port_test_get(ci);
 62	spin_unlock_irqrestore(&ci->lock, flags);
 63	pm_runtime_put_sync(ci->dev);
 64
 65	seq_printf(s, "mode = %u\n", mode);
 
 
 
 
 
 
 
 
 
 
 66
 
 
 
 
 67	return 0;
 68}
 69
 70/*
 71 * ci_port_test_write: writes port test mode
 
 
 72 */
 73static ssize_t ci_port_test_write(struct file *file, const char __user *ubuf,
 74				  size_t count, loff_t *ppos)
 75{
 76	struct seq_file *s = file->private_data;
 77	struct ci_hdrc *ci = s->private;
 78	unsigned long flags;
 79	unsigned mode;
 80	char buf[32];
 81	int ret;
 82
 83	count = min_t(size_t, sizeof(buf) - 1, count);
 84	if (copy_from_user(buf, ubuf, count))
 85		return -EFAULT;
 
 86
 87	/* sscanf requires a zero terminated string */
 88	buf[count] = '\0';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 89
 90	if (sscanf(buf, "%u", &mode) != 1)
 91		return -EINVAL;
 
 
 
 
 
 
 
 
 
 
 
 
 
 92
 93	if (mode > 255)
 94		return -EBADRQC;
 
 
 95
 96	pm_runtime_get_sync(ci->dev);
 97	spin_lock_irqsave(&ci->lock, flags);
 98	ret = hw_port_test_set(ci, mode);
 99	spin_unlock_irqrestore(&ci->lock, flags);
100	pm_runtime_put_sync(ci->dev);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
101
102	return ret ? ret : count;
 
 
 
 
 
 
103}
104
105static int ci_port_test_open(struct inode *inode, struct file *file)
 
 
 
 
106{
107	return single_open(file, ci_port_test_show, inode->i_private);
108}
109
110static const struct file_operations ci_port_test_fops = {
111	.open		= ci_port_test_open,
112	.write		= ci_port_test_write,
113	.read		= seq_read,
114	.llseek		= seq_lseek,
115	.release	= single_release,
116};
117
118/*
119 * ci_qheads_show: DMA contents of all queue heads
120 */
121static int ci_qheads_show(struct seq_file *s, void *data)
122{
123	struct ci_hdrc *ci = s->private;
 
124	unsigned long flags;
125	unsigned i, j;
126
127	if (ci->role != CI_ROLE_GADGET) {
128		seq_printf(s, "not in gadget mode\n");
129		return 0;
130	}
131
132	spin_lock_irqsave(&ci->lock, flags);
133	for (i = 0; i < ci->hw_ep_max/2; i++) {
134		struct ci_hw_ep *hweprx = &ci->ci_hw_ep[i];
135		struct ci_hw_ep *hweptx =
136			&ci->ci_hw_ep[i + ci->hw_ep_max/2];
137		seq_printf(s, "EP=%02i: RX=%08X TX=%08X\n",
138			   i, (u32)hweprx->qh.dma, (u32)hweptx->qh.dma);
139		for (j = 0; j < (sizeof(struct ci_hw_qh)/sizeof(u32)); j++)
140			seq_printf(s, " %04X:    %08X    %08X\n", j,
141				   *((u32 *)hweprx->qh.ptr + j),
142				   *((u32 *)hweptx->qh.ptr + j));
143	}
144	spin_unlock_irqrestore(&ci->lock, flags);
145
146	return 0;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
147}
148DEFINE_SHOW_ATTRIBUTE(ci_qheads);
149
150/*
151 * ci_requests_show: DMA contents of all requests currently queued (all endpts)
 
 
 
152 */
153static int ci_requests_show(struct seq_file *s, void *data)
154{
155	struct ci_hdrc *ci = s->private;
156	unsigned long flags;
157	struct ci_hw_req *req = NULL;
158	struct td_node *node, *tmpnode;
159	unsigned i, j, qsize = sizeof(struct ci_hw_td)/sizeof(u32);
160
161	if (ci->role != CI_ROLE_GADGET) {
162		seq_printf(s, "not in gadget mode\n");
163		return 0;
 
164	}
 
165
166	spin_lock_irqsave(&ci->lock, flags);
167	for (i = 0; i < ci->hw_ep_max; i++)
168		list_for_each_entry(req, &ci->ci_hw_ep[i].qh.queue, queue) {
169			list_for_each_entry_safe(node, tmpnode, &req->tds, td) {
170				seq_printf(s, "EP=%02i: TD=%08X %s\n",
171					   i % (ci->hw_ep_max / 2),
172					   (u32)node->dma,
173					   ((i < ci->hw_ep_max/2) ?
174					   "RX" : "TX"));
175
176				for (j = 0; j < qsize; j++)
177					seq_printf(s, " %04X:    %08X\n", j,
178						   *((u32 *)node->ptr + j));
179			}
180		}
181	spin_unlock_irqrestore(&ci->lock, flags);
182
183	return 0;
 
 
 
 
 
 
184}
185DEFINE_SHOW_ATTRIBUTE(ci_requests);
186
187static int ci_otg_show(struct seq_file *s, void *unused)
 
 
 
 
 
 
188{
189	struct ci_hdrc *ci = s->private;
190	struct otg_fsm *fsm;
191
192	if (!ci || !ci_otg_is_fsm_mode(ci))
 
193		return 0;
 
194
195	fsm = &ci->fsm;
196
197	/* ------ State ----- */
198	seq_printf(s, "OTG state: %s\n\n",
199			usb_otg_state_string(ci->otg.state));
200
201	/* ------ State Machine Variables ----- */
202	seq_printf(s, "a_bus_drop: %d\n", fsm->a_bus_drop);
 
 
 
 
 
 
 
 
 
203
204	seq_printf(s, "a_bus_req: %d\n", fsm->a_bus_req);
205
206	seq_printf(s, "a_srp_det: %d\n", fsm->a_srp_det);
 
207
208	seq_printf(s, "a_vbus_vld: %d\n", fsm->a_vbus_vld);
 
 
 
 
 
 
 
 
209
210	seq_printf(s, "b_conn: %d\n", fsm->b_conn);
 
 
 
211
212	seq_printf(s, "adp_change: %d\n", fsm->adp_change);
 
 
 
213
214	seq_printf(s, "power_up: %d\n", fsm->power_up);
 
215
216	seq_printf(s, "a_bus_resume: %d\n", fsm->a_bus_resume);
 
 
 
217
218	seq_printf(s, "a_bus_suspend: %d\n", fsm->a_bus_suspend);
 
 
 
 
 
 
 
 
 
 
 
219
220	seq_printf(s, "a_conn: %d\n", fsm->a_conn);
 
 
 
221
222	seq_printf(s, "b_bus_req: %d\n", fsm->b_bus_req);
223
224	seq_printf(s, "b_bus_suspend: %d\n", fsm->b_bus_suspend);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
225
226	seq_printf(s, "b_se0_srp: %d\n", fsm->b_se0_srp);
227
228	seq_printf(s, "b_ssend_srp: %d\n", fsm->b_ssend_srp);
 
229
230	seq_printf(s, "b_sess_vld: %d\n", fsm->b_sess_vld);
 
 
 
 
 
 
 
 
 
 
 
231
232	seq_printf(s, "b_srp_done: %d\n", fsm->b_srp_done);
 
 
 
233
234	seq_printf(s, "drv_vbus: %d\n", fsm->drv_vbus);
 
 
 
235
236	seq_printf(s, "loc_conn: %d\n", fsm->loc_conn);
 
 
 
 
 
 
 
 
 
 
237
238	seq_printf(s, "loc_sof: %d\n", fsm->loc_sof);
 
 
 
239
240	seq_printf(s, "adp_prb: %d\n", fsm->adp_prb);
 
 
 
 
 
 
 
 
 
 
241
242	seq_printf(s, "id: %d\n", fsm->id);
 
 
 
243
244	seq_printf(s, "protocol: %d\n", fsm->protocol);
 
 
245
246	return 0;
247}
248DEFINE_SHOW_ATTRIBUTE(ci_otg);
249
250static int ci_role_show(struct seq_file *s, void *data)
 
 
 
 
 
 
 
251{
252	struct ci_hdrc *ci = s->private;
 
 
253
254	if (ci->role != CI_ROLE_END)
255		seq_printf(s, "%s\n", ci_role(ci)->name);
 
 
256
257	return 0;
 
 
 
 
 
 
 
 
 
 
 
258}
 
 
259
260static ssize_t ci_role_write(struct file *file, const char __user *ubuf,
261			     size_t count, loff_t *ppos)
 
 
 
 
 
262{
263	struct seq_file *s = file->private_data;
264	struct ci_hdrc *ci = s->private;
265	enum ci_role role;
266	char buf[8];
267	int ret;
268
269	if (copy_from_user(buf, ubuf, min_t(size_t, sizeof(buf) - 1, count)))
270		return -EFAULT;
271
272	for (role = CI_ROLE_HOST; role < CI_ROLE_END; role++)
273		if (ci->roles[role] &&
274		    !strncmp(buf, ci->roles[role]->name,
275			     strlen(ci->roles[role]->name)))
276			break;
277
278	if (role == CI_ROLE_END || role == ci->role)
279		return -EINVAL;
 
 
280
281	pm_runtime_get_sync(ci->dev);
282	disable_irq(ci->irq);
283	ci_role_stop(ci);
284	ret = ci_role_start(ci, role);
285	enable_irq(ci->irq);
286	pm_runtime_put_sync(ci->dev);
 
 
 
 
 
 
 
 
 
 
287
288	return ret ? ret : count;
289}
 
290
291static int ci_role_open(struct inode *inode, struct file *file)
 
 
 
 
 
 
 
292{
293	return single_open(file, ci_role_show, inode->i_private);
294}
 
 
295
296static const struct file_operations ci_role_fops = {
297	.open		= ci_role_open,
298	.write		= ci_role_write,
299	.read		= seq_read,
300	.llseek		= seq_lseek,
301	.release	= single_release,
302};
303
304static int ci_registers_show(struct seq_file *s, void *unused)
305{
306	struct ci_hdrc *ci = s->private;
307	u32 tmp_reg;
 
308
309	if (!ci || ci->in_lpm)
310		return -EPERM;
 
 
 
 
 
 
 
 
311
312	/* ------ Registers ----- */
313	tmp_reg = hw_read_intr_enable(ci);
314	seq_printf(s, "USBINTR reg: %08x\n", tmp_reg);
315
316	tmp_reg = hw_read_intr_status(ci);
317	seq_printf(s, "USBSTS reg: %08x\n", tmp_reg);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
318
319	tmp_reg = hw_read(ci, OP_USBMODE, ~0);
320	seq_printf(s, "USBMODE reg: %08x\n", tmp_reg);
 
 
321
322	tmp_reg = hw_read(ci, OP_USBCMD, ~0);
323	seq_printf(s, "USBCMD reg: %08x\n", tmp_reg);
 
 
 
324
325	tmp_reg = hw_read(ci, OP_PORTSC, ~0);
326	seq_printf(s, "PORTSC reg: %08x\n", tmp_reg);
 
 
 
 
 
 
 
 
 
 
 
327
328	if (ci->is_otg) {
329		tmp_reg = hw_read_otgsc(ci, ~0);
330		seq_printf(s, "OTGSC reg: %08x\n", tmp_reg);
331	}
332
333	return 0;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
334}
335DEFINE_SHOW_ATTRIBUTE(ci_registers);
336
337/**
338 * dbg_create_files: initializes the attribute interface
339 * @ci: device
340 *
341 * This function returns an error code
342 */
343void dbg_create_files(struct ci_hdrc *ci)
344{
345	ci->debugfs = debugfs_create_dir(dev_name(ci->dev), usb_debug_root);
346
347	debugfs_create_file("device", S_IRUGO, ci->debugfs, ci,
348			    &ci_device_fops);
349	debugfs_create_file("port_test", S_IRUGO | S_IWUSR, ci->debugfs, ci,
350			    &ci_port_test_fops);
351	debugfs_create_file("qheads", S_IRUGO, ci->debugfs, ci,
352			    &ci_qheads_fops);
353	debugfs_create_file("requests", S_IRUGO, ci->debugfs, ci,
354			    &ci_requests_fops);
355
356	if (ci_otg_is_fsm_mode(ci)) {
357		debugfs_create_file("otg", S_IRUGO, ci->debugfs, ci,
358				    &ci_otg_fops);
359	}
360
361	debugfs_create_file("role", S_IRUGO | S_IWUSR, ci->debugfs, ci,
362			    &ci_role_fops);
363	debugfs_create_file("registers", S_IRUGO, ci->debugfs, ci,
364			    &ci_registers_fops);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
365}
366
367/**
368 * dbg_remove_files: destroys the attribute interface
369 * @ci: device
 
 
370 */
371void dbg_remove_files(struct ci_hdrc *ci)
372{
373	debugfs_remove_recursive(ci->debugfs);
 
 
 
 
 
 
 
 
 
 
374}
v3.5.6
  1#include <linux/delay.h>
 
  2#include <linux/device.h>
  3#include <linux/dmapool.h>
  4#include <linux/dma-mapping.h>
  5#include <linux/init.h>
  6#include <linux/platform_device.h>
  7#include <linux/module.h>
  8#include <linux/interrupt.h>
  9#include <linux/io.h>
 10#include <linux/irq.h>
 11#include <linux/kernel.h>
 12#include <linux/slab.h>
 13#include <linux/pm_runtime.h>
 14#include <linux/usb/ch9.h>
 15#include <linux/usb/gadget.h>
 
 16#include <linux/usb/otg.h>
 
 17#include <linux/usb/chipidea.h>
 18
 19#include "ci.h"
 20#include "udc.h"
 21#include "bits.h"
 22#include "debug.h"
 23
 24/* Interrupt statistics */
 25#define ISR_MASK   0x1F
 26static struct isr_statistics {
 27	u32 test;
 28	u32 ui;
 29	u32 uei;
 30	u32 pci;
 31	u32 uri;
 32	u32 sli;
 33	u32 none;
 34	struct {
 35		u32 cnt;
 36		u32 buf[ISR_MASK+1];
 37		u32 idx;
 38	} hndl;
 39} isr_statistics;
 40
 41void dbg_interrupt(u32 intmask)
 42{
 43	if (!intmask) {
 44		isr_statistics.none++;
 45		return;
 46	}
 47
 48	isr_statistics.hndl.buf[isr_statistics.hndl.idx++] = intmask;
 49	isr_statistics.hndl.idx &= ISR_MASK;
 50	isr_statistics.hndl.cnt++;
 51
 52	if (USBi_URI & intmask)
 53		isr_statistics.uri++;
 54	if (USBi_PCI & intmask)
 55		isr_statistics.pci++;
 56	if (USBi_UEI & intmask)
 57		isr_statistics.uei++;
 58	if (USBi_UI  & intmask)
 59		isr_statistics.ui++;
 60	if (USBi_SLI & intmask)
 61		isr_statistics.sli++;
 62}
 63
 64/**
 65 * hw_register_read: reads all device registers (execute without interruption)
 66 * @buf:  destination buffer
 67 * @size: buffer size
 68 *
 69 * This function returns number of registers read
 70 */
 71static size_t hw_register_read(struct ci13xxx *udc, u32 *buf, size_t size)
 72{
 73	unsigned i;
 
 74
 75	if (size > udc->hw_bank.size)
 76		size = udc->hw_bank.size;
 
 
 
 
 
 
 
 77
 78	for (i = 0; i < size; i++)
 79		buf[i] = hw_read(udc, i * sizeof(u32), ~0);
 80
 81	return size;
 82}
 83
 84/**
 85 * hw_register_write: writes to register
 86 * @addr: register address
 87 * @data: register value
 88 *
 89 * This function returns an error code
 90 */
 91static int hw_register_write(struct ci13xxx *udc, u16 addr, u32 data)
 92{
 93	/* align */
 94	addr /= sizeof(u32);
 95
 96	if (addr >= udc->hw_bank.size)
 97		return -EINVAL;
 98
 99	/* align */
100	addr *= sizeof(u32);
101
102	hw_write(udc, addr, ~0, data);
103	return 0;
104}
 
105
106/**
107 * hw_intr_clear: disables interrupt & clears interrupt status (execute without
108 *                interruption)
109 * @n: interrupt bit
110 *
111 * This function returns an error code
112 */
113static int hw_intr_clear(struct ci13xxx *udc, int n)
114{
115	if (n >= REG_BITS)
116		return -EINVAL;
 
117
118	hw_write(udc, OP_USBINTR, BIT(n), 0);
119	hw_write(udc, OP_USBSTS,  BIT(n), BIT(n));
120	return 0;
121}
 
122
123/**
124 * hw_intr_force: enables interrupt & forces interrupt status (execute without
125 *                interruption)
126 * @n: interrupt bit
127 *
128 * This function returns an error code
129 */
130static int hw_intr_force(struct ci13xxx *udc, int n)
131{
132	if (n >= REG_BITS)
133		return -EINVAL;
134
135	hw_write(udc, CAP_TESTMODE, TESTMODE_FORCE, TESTMODE_FORCE);
136	hw_write(udc, OP_USBINTR,  BIT(n), BIT(n));
137	hw_write(udc, OP_USBSTS,   BIT(n), BIT(n));
138	hw_write(udc, CAP_TESTMODE, TESTMODE_FORCE, 0);
139	return 0;
140}
141
142/**
143 * show_device: prints information about device capabilities and status
144 *
145 * Check "device.h" for details
146 */
147static ssize_t show_device(struct device *dev, struct device_attribute *attr,
148			   char *buf)
149{
150	struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev);
151	struct usb_gadget *gadget = &udc->gadget;
152	int n = 0;
 
 
 
153
154	if (attr == NULL || buf == NULL) {
155		dev_err(udc->dev, "[%s] EINVAL\n", __func__);
156		return 0;
157	}
158
159	n += scnprintf(buf + n, PAGE_SIZE - n, "speed             = %d\n",
160		       gadget->speed);
161	n += scnprintf(buf + n, PAGE_SIZE - n, "max_speed         = %d\n",
162		       gadget->max_speed);
163	/* TODO: Scheduled for removal in 3.8. */
164	n += scnprintf(buf + n, PAGE_SIZE - n, "is_dualspeed      = %d\n",
165		       gadget_is_dualspeed(gadget));
166	n += scnprintf(buf + n, PAGE_SIZE - n, "is_otg            = %d\n",
167		       gadget->is_otg);
168	n += scnprintf(buf + n, PAGE_SIZE - n, "is_a_peripheral   = %d\n",
169		       gadget->is_a_peripheral);
170	n += scnprintf(buf + n, PAGE_SIZE - n, "b_hnp_enable      = %d\n",
171		       gadget->b_hnp_enable);
172	n += scnprintf(buf + n, PAGE_SIZE - n, "a_hnp_support     = %d\n",
173		       gadget->a_hnp_support);
174	n += scnprintf(buf + n, PAGE_SIZE - n, "a_alt_hnp_support = %d\n",
175		       gadget->a_alt_hnp_support);
176	n += scnprintf(buf + n, PAGE_SIZE - n, "name              = %s\n",
177		       (gadget->name ? gadget->name : ""));
178
179	return n;
180}
181static DEVICE_ATTR(device, S_IRUSR, show_device, NULL);
182
183/**
184 * show_driver: prints information about attached gadget (if any)
185 *
186 * Check "device.h" for details
187 */
188static ssize_t show_driver(struct device *dev, struct device_attribute *attr,
189			   char *buf)
190{
191	struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev);
192	struct usb_gadget_driver *driver = udc->driver;
193	int n = 0;
194
195	if (attr == NULL || buf == NULL) {
196		dev_err(dev, "[%s] EINVAL\n", __func__);
197		return 0;
198	}
199
200	if (driver == NULL)
201		return scnprintf(buf, PAGE_SIZE,
202				 "There is no gadget attached!\n");
203
204	n += scnprintf(buf + n, PAGE_SIZE - n, "function  = %s\n",
205		       (driver->function ? driver->function : ""));
206	n += scnprintf(buf + n, PAGE_SIZE - n, "max speed = %d\n",
207		       driver->max_speed);
208
209	return n;
210}
211static DEVICE_ATTR(driver, S_IRUSR, show_driver, NULL);
212
213/* Maximum event message length */
214#define DBG_DATA_MSG   64UL
215
216/* Maximum event messages */
217#define DBG_DATA_MAX   128UL
218
219/* Event buffer descriptor */
220static struct {
221	char     (buf[DBG_DATA_MAX])[DBG_DATA_MSG];   /* buffer */
222	unsigned idx;   /* index */
223	unsigned tty;   /* print to console? */
224	rwlock_t lck;   /* lock */
225} dbg_data = {
226	.idx = 0,
227	.tty = 0,
228	.lck = __RW_LOCK_UNLOCKED(lck)
229};
230
231/**
232 * dbg_dec: decrements debug event index
233 * @idx: buffer index
234 */
235static void dbg_dec(unsigned *idx)
236{
237	*idx = (*idx - 1) & (DBG_DATA_MAX-1);
238}
239
240/**
241 * dbg_inc: increments debug event index
242 * @idx: buffer index
243 */
244static void dbg_inc(unsigned *idx)
245{
246	*idx = (*idx + 1) & (DBG_DATA_MAX-1);
247}
248
249/**
250 * dbg_print:  prints the common part of the event
251 * @addr:   endpoint address
252 * @name:   event name
253 * @status: status
254 * @extra:  extra information
 
 
 
 
255 */
256static void dbg_print(u8 addr, const char *name, int status, const char *extra)
257{
258	struct timeval tval;
259	unsigned int stamp;
260	unsigned long flags;
 
261
262	write_lock_irqsave(&dbg_data.lck, flags);
 
 
 
263
264	do_gettimeofday(&tval);
265	stamp = tval.tv_sec & 0xFFFF;	/* 2^32 = 4294967296. Limit to 4096s */
266	stamp = stamp * 1000000 + tval.tv_usec;
 
 
 
 
 
 
 
 
 
 
267
268	scnprintf(dbg_data.buf[dbg_data.idx], DBG_DATA_MSG,
269		  "%04X\t? %02X %-7.7s %4i ?\t%s\n",
270		  stamp, addr, name, status, extra);
271
272	dbg_inc(&dbg_data.idx);
273
274	write_unlock_irqrestore(&dbg_data.lck, flags);
275
276	if (dbg_data.tty != 0)
277		pr_notice("%04X\t? %02X %-7.7s %4i ?\t%s\n",
278			  stamp, addr, name, status, extra);
279}
280
281/**
282 * dbg_done: prints a DONE event
283 * @addr:   endpoint address
284 * @td:     transfer descriptor
285 * @status: status
286 */
287void dbg_done(u8 addr, const u32 token, int status)
288{
289	char msg[DBG_DATA_MSG];
290
291	scnprintf(msg, sizeof(msg), "%d %02X",
292		  (int)(token & TD_TOTAL_BYTES) >> ffs_nr(TD_TOTAL_BYTES),
293		  (int)(token & TD_STATUS)      >> ffs_nr(TD_STATUS));
294	dbg_print(addr, "DONE", status, msg);
295}
296
297/**
298 * dbg_event: prints a generic event
299 * @addr:   endpoint address
300 * @name:   event name
301 * @status: status
302 */
303void dbg_event(u8 addr, const char *name, int status)
304{
305	if (name != NULL)
306		dbg_print(addr, name, status, "");
307}
 
308
309/*
310 * dbg_queue: prints a QUEUE event
311 * @addr:   endpoint address
312 * @req:    USB request
313 * @status: status
314 */
315void dbg_queue(u8 addr, const struct usb_request *req, int status)
316{
317	char msg[DBG_DATA_MSG];
 
 
 
 
318
319	if (req != NULL) {
320		scnprintf(msg, sizeof(msg),
321			  "%d %d", !req->no_interrupt, req->length);
322		dbg_print(addr, "QUEUE", status, msg);
323	}
324}
325
326/**
327 * dbg_setup: prints a SETUP event
328 * @addr: endpoint address
329 * @req:  setup request
330 */
331void dbg_setup(u8 addr, const struct usb_ctrlrequest *req)
332{
333	char msg[DBG_DATA_MSG];
 
 
 
 
 
 
 
 
334
335	if (req != NULL) {
336		scnprintf(msg, sizeof(msg),
337			  "%02X %02X %04X %04X %d", req->bRequestType,
338			  req->bRequest, le16_to_cpu(req->wValue),
339			  le16_to_cpu(req->wIndex), le16_to_cpu(req->wLength));
340		dbg_print(addr, "SETUP", 0, msg);
341	}
342}
 
343
344/**
345 * show_events: displays the event buffer
346 *
347 * Check "device.h" for details
348 */
349static ssize_t show_events(struct device *dev, struct device_attribute *attr,
350			   char *buf)
351{
352	unsigned long flags;
353	unsigned i, j, n = 0;
354
355	if (attr == NULL || buf == NULL) {
356		dev_err(dev->parent, "[%s] EINVAL\n", __func__);
357		return 0;
358	}
359
360	read_lock_irqsave(&dbg_data.lck, flags);
 
 
 
 
361
362	i = dbg_data.idx;
363	for (dbg_dec(&i); i != dbg_data.idx; dbg_dec(&i)) {
364		n += strlen(dbg_data.buf[i]);
365		if (n >= PAGE_SIZE) {
366			n -= strlen(dbg_data.buf[i]);
367			break;
368		}
369	}
370	for (j = 0, dbg_inc(&i); j < n; dbg_inc(&i))
371		j += scnprintf(buf + j, PAGE_SIZE - j,
372			       "%s", dbg_data.buf[i]);
373
374	read_unlock_irqrestore(&dbg_data.lck, flags);
375
376	return n;
377}
378
379/**
380 * store_events: configure if events are going to be also printed to console
381 *
382 * Check "device.h" for details
383 */
384static ssize_t store_events(struct device *dev, struct device_attribute *attr,
385			    const char *buf, size_t count)
386{
387	unsigned tty;
388
389	if (attr == NULL || buf == NULL) {
390		dev_err(dev, "[%s] EINVAL\n", __func__);
391		goto done;
392	}
393
394	if (sscanf(buf, "%u", &tty) != 1 || tty > 1) {
395		dev_err(dev, "<1|0>: enable|disable console log\n");
396		goto done;
397	}
398
399	dbg_data.tty = tty;
400	dev_info(dev, "tty = %u", dbg_data.tty);
401
402 done:
403	return count;
404}
405static DEVICE_ATTR(events, S_IRUSR | S_IWUSR, show_events, store_events);
406
407/**
408 * show_inters: interrupt status, enable status and historic
409 *
410 * Check "device.h" for details
411 */
412static ssize_t show_inters(struct device *dev, struct device_attribute *attr,
413			   char *buf)
414{
415	struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev);
416	unsigned long flags;
417	u32 intr;
418	unsigned i, j, n = 0;
419
420	if (attr == NULL || buf == NULL) {
421		dev_err(udc->dev, "[%s] EINVAL\n", __func__);
422		return 0;
423	}
424
425	spin_lock_irqsave(&udc->lock, flags);
426
427	/*n += scnprintf(buf + n, PAGE_SIZE - n,
428		       "status = %08x\n", hw_read_intr_status(udc));
429	n += scnprintf(buf + n, PAGE_SIZE - n,
430	"enable = %08x\n", hw_read_intr_enable(udc));*/
431
432	n += scnprintf(buf + n, PAGE_SIZE - n, "*test = %d\n",
433		       isr_statistics.test);
434	n += scnprintf(buf + n, PAGE_SIZE - n, "? ui  = %d\n",
435		       isr_statistics.ui);
436	n += scnprintf(buf + n, PAGE_SIZE - n, "? uei = %d\n",
437		       isr_statistics.uei);
438	n += scnprintf(buf + n, PAGE_SIZE - n, "? pci = %d\n",
439		       isr_statistics.pci);
440	n += scnprintf(buf + n, PAGE_SIZE - n, "? uri = %d\n",
441		       isr_statistics.uri);
442	n += scnprintf(buf + n, PAGE_SIZE - n, "? sli = %d\n",
443		       isr_statistics.sli);
444	n += scnprintf(buf + n, PAGE_SIZE - n, "*none = %d\n",
445		       isr_statistics.none);
446	n += scnprintf(buf + n, PAGE_SIZE - n, "*hndl = %d\n",
447		       isr_statistics.hndl.cnt);
448
449	for (i = isr_statistics.hndl.idx, j = 0; j <= ISR_MASK; j++, i++) {
450		i   &= ISR_MASK;
451		intr = isr_statistics.hndl.buf[i];
452
453		if (USBi_UI  & intr)
454			n += scnprintf(buf + n, PAGE_SIZE - n, "ui  ");
455		intr &= ~USBi_UI;
456		if (USBi_UEI & intr)
457			n += scnprintf(buf + n, PAGE_SIZE - n, "uei ");
458		intr &= ~USBi_UEI;
459		if (USBi_PCI & intr)
460			n += scnprintf(buf + n, PAGE_SIZE - n, "pci ");
461		intr &= ~USBi_PCI;
462		if (USBi_URI & intr)
463			n += scnprintf(buf + n, PAGE_SIZE - n, "uri ");
464		intr &= ~USBi_URI;
465		if (USBi_SLI & intr)
466			n += scnprintf(buf + n, PAGE_SIZE - n, "sli ");
467		intr &= ~USBi_SLI;
468		if (intr)
469			n += scnprintf(buf + n, PAGE_SIZE - n, "??? ");
470		if (isr_statistics.hndl.buf[i])
471			n += scnprintf(buf + n, PAGE_SIZE - n, "\n");
472	}
473
474	spin_unlock_irqrestore(&udc->lock, flags);
475
476	return n;
477}
478
479/**
480 * store_inters: enable & force or disable an individual interrutps
481 *                   (to be used for test purposes only)
482 *
483 * Check "device.h" for details
484 */
485static ssize_t store_inters(struct device *dev, struct device_attribute *attr,
486			    const char *buf, size_t count)
487{
488	struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev);
489	unsigned long flags;
490	unsigned en, bit;
491
492	if (attr == NULL || buf == NULL) {
493		dev_err(udc->dev, "EINVAL\n");
494		goto done;
495	}
496
497	if (sscanf(buf, "%u %u", &en, &bit) != 2 || en > 1) {
498		dev_err(udc->dev, "<1|0> <bit>: enable|disable interrupt\n");
499		goto done;
500	}
501
502	spin_lock_irqsave(&udc->lock, flags);
503	if (en) {
504		if (hw_intr_force(udc, bit))
505			dev_err(dev, "invalid bit number\n");
506		else
507			isr_statistics.test++;
508	} else {
509		if (hw_intr_clear(udc, bit))
510			dev_err(dev, "invalid bit number\n");
511	}
512	spin_unlock_irqrestore(&udc->lock, flags);
513
514 done:
515	return count;
516}
517static DEVICE_ATTR(inters, S_IRUSR | S_IWUSR, show_inters, store_inters);
518
519/**
520 * show_port_test: reads port test mode
521 *
522 * Check "device.h" for details
523 */
524static ssize_t show_port_test(struct device *dev,
525			      struct device_attribute *attr, char *buf)
526{
527	struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev);
528	unsigned long flags;
529	unsigned mode;
530
531	if (attr == NULL || buf == NULL) {
532		dev_err(udc->dev, "EINVAL\n");
533		return 0;
534	}
535
536	spin_lock_irqsave(&udc->lock, flags);
537	mode = hw_port_test_get(udc);
538	spin_unlock_irqrestore(&udc->lock, flags);
539
540	return scnprintf(buf, PAGE_SIZE, "mode = %u\n", mode);
541}
 
542
543/**
544 * store_port_test: writes port test mode
545 *
546 * Check "device.h" for details
547 */
548static ssize_t store_port_test(struct device *dev,
549			       struct device_attribute *attr,
550			       const char *buf, size_t count)
551{
552	struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev);
553	unsigned long flags;
554	unsigned mode;
555
556	if (attr == NULL || buf == NULL) {
557		dev_err(udc->dev, "[%s] EINVAL\n", __func__);
558		goto done;
559	}
560
561	if (sscanf(buf, "%u", &mode) != 1) {
562		dev_err(udc->dev, "<mode>: set port test mode");
563		goto done;
564	}
565
566	spin_lock_irqsave(&udc->lock, flags);
567	if (hw_port_test_set(udc, mode))
568		dev_err(udc->dev, "invalid mode\n");
569	spin_unlock_irqrestore(&udc->lock, flags);
570
571 done:
572	return count;
573}
574static DEVICE_ATTR(port_test, S_IRUSR | S_IWUSR,
575		   show_port_test, store_port_test);
576
577/**
578 * show_qheads: DMA contents of all queue heads
579 *
580 * Check "device.h" for details
581 */
582static ssize_t show_qheads(struct device *dev, struct device_attribute *attr,
583			   char *buf)
584{
585	struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev);
586	unsigned long flags;
587	unsigned i, j, n = 0;
 
 
 
 
 
 
 
 
 
 
 
588
589	if (attr == NULL || buf == NULL) {
590		dev_err(udc->dev, "[%s] EINVAL\n", __func__);
591		return 0;
592	}
593
594	spin_lock_irqsave(&udc->lock, flags);
595	for (i = 0; i < udc->hw_ep_max/2; i++) {
596		struct ci13xxx_ep *mEpRx = &udc->ci13xxx_ep[i];
597		struct ci13xxx_ep *mEpTx =
598			&udc->ci13xxx_ep[i + udc->hw_ep_max/2];
599		n += scnprintf(buf + n, PAGE_SIZE - n,
600			       "EP=%02i: RX=%08X TX=%08X\n",
601			       i, (u32)mEpRx->qh.dma, (u32)mEpTx->qh.dma);
602		for (j = 0; j < (sizeof(struct ci13xxx_qh)/sizeof(u32)); j++) {
603			n += scnprintf(buf + n, PAGE_SIZE - n,
604				       " %04X:    %08X    %08X\n", j,
605				       *((u32 *)mEpRx->qh.ptr + j),
606				       *((u32 *)mEpTx->qh.ptr + j));
607		}
608	}
609	spin_unlock_irqrestore(&udc->lock, flags);
610
611	return n;
612}
613static DEVICE_ATTR(qheads, S_IRUSR, show_qheads, NULL);
614
615/**
616 * show_registers: dumps all registers
617 *
618 * Check "device.h" for details
619 */
620#define DUMP_ENTRIES	512
621static ssize_t show_registers(struct device *dev,
622			      struct device_attribute *attr, char *buf)
623{
624	struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev);
625	unsigned long flags;
626	u32 *dump;
627	unsigned i, k, n = 0;
628
629	if (attr == NULL || buf == NULL) {
630		dev_err(udc->dev, "[%s] EINVAL\n", __func__);
631		return 0;
632	}
 
 
 
633
634	dump = kmalloc(sizeof(u32) * DUMP_ENTRIES, GFP_KERNEL);
635	if (!dump) {
636		dev_err(udc->dev, "%s: out of memory\n", __func__);
637		return 0;
638	}
639
640	spin_lock_irqsave(&udc->lock, flags);
641	k = hw_register_read(udc, dump, DUMP_ENTRIES);
642	spin_unlock_irqrestore(&udc->lock, flags);
643
644	for (i = 0; i < k; i++) {
645		n += scnprintf(buf + n, PAGE_SIZE - n,
646			       "reg[0x%04X] = 0x%08X\n",
647			       i * (unsigned)sizeof(u32), dump[i]);
648	}
649	kfree(dump);
650
651	return n;
652}
 
653
654/**
655 * store_registers: writes value to register address
656 *
657 * Check "device.h" for details
658 */
659static ssize_t store_registers(struct device *dev,
660			       struct device_attribute *attr,
661			       const char *buf, size_t count)
662{
663	struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev);
664	unsigned long addr, data, flags;
665
666	if (attr == NULL || buf == NULL) {
667		dev_err(udc->dev, "[%s] EINVAL\n", __func__);
668		goto done;
669	}
670
671	if (sscanf(buf, "%li %li", &addr, &data) != 2) {
672		dev_err(udc->dev,
673			"<addr> <data>: write data to register address\n");
674		goto done;
675	}
676
677	spin_lock_irqsave(&udc->lock, flags);
678	if (hw_register_write(udc, addr, data))
679		dev_err(udc->dev, "invalid address range\n");
680	spin_unlock_irqrestore(&udc->lock, flags);
681
682 done:
683	return count;
684}
685static DEVICE_ATTR(registers, S_IRUSR | S_IWUSR,
686		   show_registers, store_registers);
687
688/**
689 * show_requests: DMA contents of all requests currently queued (all endpts)
690 *
691 * Check "device.h" for details
692 */
693static ssize_t show_requests(struct device *dev, struct device_attribute *attr,
694			     char *buf)
695{
696	struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev);
697	unsigned long flags;
698	struct list_head   *ptr = NULL;
699	struct ci13xxx_req *req = NULL;
700	unsigned i, j, n = 0, qSize = sizeof(struct ci13xxx_td)/sizeof(u32);
701
702	if (attr == NULL || buf == NULL) {
703		dev_err(udc->dev, "[%s] EINVAL\n", __func__);
704		return 0;
705	}
706
707	spin_lock_irqsave(&udc->lock, flags);
708	for (i = 0; i < udc->hw_ep_max; i++)
709		list_for_each(ptr, &udc->ci13xxx_ep[i].qh.queue)
710		{
711			req = list_entry(ptr, struct ci13xxx_req, queue);
712
713			n += scnprintf(buf + n, PAGE_SIZE - n,
714					"EP=%02i: TD=%08X %s\n",
715					i % udc->hw_ep_max/2, (u32)req->dma,
716					((i < udc->hw_ep_max/2) ? "RX" : "TX"));
717
718			for (j = 0; j < qSize; j++)
719				n += scnprintf(buf + n, PAGE_SIZE - n,
720						" %04X:    %08X\n", j,
721						*((u32 *)req->ptr + j));
722		}
723	spin_unlock_irqrestore(&udc->lock, flags);
724
725	return n;
726}
727static DEVICE_ATTR(requests, S_IRUSR, show_requests, NULL);
728
729/**
730 * dbg_create_files: initializes the attribute interface
731 * @dev: device
732 *
733 * This function returns an error code
734 */
735int dbg_create_files(struct device *dev)
736{
737	int retval = 0;
738
739	if (dev == NULL)
740		return -EINVAL;
741	retval = device_create_file(dev, &dev_attr_device);
742	if (retval)
743		goto done;
744	retval = device_create_file(dev, &dev_attr_driver);
745	if (retval)
746		goto rm_device;
747	retval = device_create_file(dev, &dev_attr_events);
748	if (retval)
749		goto rm_driver;
750	retval = device_create_file(dev, &dev_attr_inters);
751	if (retval)
752		goto rm_events;
753	retval = device_create_file(dev, &dev_attr_port_test);
754	if (retval)
755		goto rm_inters;
756	retval = device_create_file(dev, &dev_attr_qheads);
757	if (retval)
758		goto rm_port_test;
759	retval = device_create_file(dev, &dev_attr_registers);
760	if (retval)
761		goto rm_qheads;
762	retval = device_create_file(dev, &dev_attr_requests);
763	if (retval)
764		goto rm_registers;
765	return 0;
766
767 rm_registers:
768	device_remove_file(dev, &dev_attr_registers);
769 rm_qheads:
770	device_remove_file(dev, &dev_attr_qheads);
771 rm_port_test:
772	device_remove_file(dev, &dev_attr_port_test);
773 rm_inters:
774	device_remove_file(dev, &dev_attr_inters);
775 rm_events:
776	device_remove_file(dev, &dev_attr_events);
777 rm_driver:
778	device_remove_file(dev, &dev_attr_driver);
779 rm_device:
780	device_remove_file(dev, &dev_attr_device);
781 done:
782	return retval;
783}
784
785/**
786 * dbg_remove_files: destroys the attribute interface
787 * @dev: device
788 *
789 * This function returns an error code
790 */
791int dbg_remove_files(struct device *dev)
792{
793	if (dev == NULL)
794		return -EINVAL;
795	device_remove_file(dev, &dev_attr_requests);
796	device_remove_file(dev, &dev_attr_registers);
797	device_remove_file(dev, &dev_attr_qheads);
798	device_remove_file(dev, &dev_attr_port_test);
799	device_remove_file(dev, &dev_attr_inters);
800	device_remove_file(dev, &dev_attr_events);
801	device_remove_file(dev, &dev_attr_driver);
802	device_remove_file(dev, &dev_attr_device);
803	return 0;
804}