Root/target/linux/ramips/files/drivers/usb/dwc_otg/dwc_otg_attr.c

1/* ==========================================================================
2 * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_attr.c $
3 * $Revision: 1.2 $
4 * $Date: 2008-11-21 05:39:15 $
5 * $Change: 1064918 $
6 *
7 * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
8 * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
9 * otherwise expressly agreed to in writing between Synopsys and you.
10 *
11 * The Software IS NOT an item of Licensed Software or Licensed Product under
12 * any End User Software License Agreement or Agreement for Licensed Product
13 * with Synopsys or any supplement thereto. You are permitted to use and
14 * redistribute this Software in source and binary forms, with or without
15 * modification, provided that redistributions of source code must retain this
16 * notice. You may not view, use, disclose, copy or distribute this file or
17 * any information contained herein except pursuant to this license grant from
18 * Synopsys. If you do not agree with this notice, including the disclaimer
19 * below, then you are not authorized to use the Software.
20 *
21 * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
22 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
25 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
28 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
31 * DAMAGE.
32 * ========================================================================== */
33
34/** @file
35 *
36 * The diagnostic interface will provide access to the controller for
37 * bringing up the hardware and testing. The Linux driver attributes
38 * feature will be used to provide the Linux Diagnostic
39 * Interface. These attributes are accessed through sysfs.
40 */
41
42/** @page "Linux Module Attributes"
43 *
44 * The Linux module attributes feature is used to provide the Linux
45 * Diagnostic Interface. These attributes are accessed through sysfs.
46 * The diagnostic interface will provide access to the controller for
47 * bringing up the hardware and testing.
48
49
50 The following table shows the attributes.
51 <table>
52 <tr>
53 <td><b> Name</b></td>
54 <td><b> Description</b></td>
55 <td><b> Access</b></td>
56 </tr>
57
58 <tr>
59 <td> mode </td>
60 <td> Returns the current mode: 0 for device mode, 1 for host mode</td>
61 <td> Read</td>
62 </tr>
63
64 <tr>
65 <td> hnpcapable </td>
66 <td> Gets or sets the "HNP-capable" bit in the Core USB Configuraton Register.
67 Read returns the current value.</td>
68 <td> Read/Write</td>
69 </tr>
70
71 <tr>
72 <td> srpcapable </td>
73 <td> Gets or sets the "SRP-capable" bit in the Core USB Configuraton Register.
74 Read returns the current value.</td>
75 <td> Read/Write</td>
76 </tr>
77
78 <tr>
79 <td> hnp </td>
80 <td> Initiates the Host Negotiation Protocol. Read returns the status.</td>
81 <td> Read/Write</td>
82 </tr>
83
84 <tr>
85 <td> srp </td>
86 <td> Initiates the Session Request Protocol. Read returns the status.</td>
87 <td> Read/Write</td>
88 </tr>
89
90 <tr>
91 <td> buspower </td>
92 <td> Gets or sets the Power State of the bus (0 - Off or 1 - On)</td>
93 <td> Read/Write</td>
94 </tr>
95
96 <tr>
97 <td> bussuspend </td>
98 <td> Suspends the USB bus.</td>
99 <td> Read/Write</td>
100 </tr>
101
102 <tr>
103 <td> busconnected </td>
104 <td> Gets the connection status of the bus</td>
105 <td> Read</td>
106 </tr>
107
108 <tr>
109 <td> gotgctl </td>
110 <td> Gets or sets the Core Control Status Register.</td>
111 <td> Read/Write</td>
112 </tr>
113
114 <tr>
115 <td> gusbcfg </td>
116 <td> Gets or sets the Core USB Configuration Register</td>
117 <td> Read/Write</td>
118 </tr>
119
120 <tr>
121 <td> grxfsiz </td>
122 <td> Gets or sets the Receive FIFO Size Register</td>
123 <td> Read/Write</td>
124 </tr>
125
126 <tr>
127 <td> gnptxfsiz </td>
128 <td> Gets or sets the non-periodic Transmit Size Register</td>
129 <td> Read/Write</td>
130 </tr>
131
132 <tr>
133 <td> gpvndctl </td>
134 <td> Gets or sets the PHY Vendor Control Register</td>
135 <td> Read/Write</td>
136 </tr>
137
138 <tr>
139 <td> ggpio </td>
140 <td> Gets the value in the lower 16-bits of the General Purpose IO Register
141 or sets the upper 16 bits.</td>
142 <td> Read/Write</td>
143 </tr>
144
145 <tr>
146 <td> guid </td>
147 <td> Gets or sets the value of the User ID Register</td>
148 <td> Read/Write</td>
149 </tr>
150
151 <tr>
152 <td> gsnpsid </td>
153 <td> Gets the value of the Synopsys ID Regester</td>
154 <td> Read</td>
155 </tr>
156
157 <tr>
158 <td> devspeed </td>
159 <td> Gets or sets the device speed setting in the DCFG register</td>
160 <td> Read/Write</td>
161 </tr>
162
163 <tr>
164 <td> enumspeed </td>
165 <td> Gets the device enumeration Speed.</td>
166 <td> Read</td>
167 </tr>
168
169 <tr>
170 <td> hptxfsiz </td>
171 <td> Gets the value of the Host Periodic Transmit FIFO</td>
172 <td> Read</td>
173 </tr>
174
175 <tr>
176 <td> hprt0 </td>
177 <td> Gets or sets the value in the Host Port Control and Status Register</td>
178 <td> Read/Write</td>
179 </tr>
180
181 <tr>
182 <td> regoffset </td>
183 <td> Sets the register offset for the next Register Access</td>
184 <td> Read/Write</td>
185 </tr>
186
187 <tr>
188 <td> regvalue </td>
189 <td> Gets or sets the value of the register at the offset in the regoffset attribute.</td>
190 <td> Read/Write</td>
191 </tr>
192
193 <tr>
194 <td> remote_wakeup </td>
195 <td> On read, shows the status of Remote Wakeup. On write, initiates a remote
196 wakeup of the host. When bit 0 is 1 and Remote Wakeup is enabled, the Remote
197 Wakeup signalling bit in the Device Control Register is set for 1
198 milli-second.</td>
199 <td> Read/Write</td>
200 </tr>
201
202 <tr>
203 <td> regdump </td>
204 <td> Dumps the contents of core registers.</td>
205 <td> Read</td>
206 </tr>
207
208 <tr>
209 <td> spramdump </td>
210 <td> Dumps the contents of core registers.</td>
211 <td> Read</td>
212 </tr>
213
214 <tr>
215 <td> hcddump </td>
216 <td> Dumps the current HCD state.</td>
217 <td> Read</td>
218 </tr>
219
220 <tr>
221 <td> hcd_frrem </td>
222 <td> Shows the average value of the Frame Remaining
223 field in the Host Frame Number/Frame Remaining register when an SOF interrupt
224 occurs. This can be used to determine the average interrupt latency. Also
225 shows the average Frame Remaining value for start_transfer and the "a" and
226 "b" sample points. The "a" and "b" sample points may be used during debugging
227 bto determine how long it takes to execute a section of the HCD code.</td>
228 <td> Read</td>
229 </tr>
230
231 <tr>
232 <td> rd_reg_test </td>
233 <td> Displays the time required to read the GNPTXFSIZ register many times
234 (the output shows the number of times the register is read).
235 <td> Read</td>
236 </tr>
237
238 <tr>
239 <td> wr_reg_test </td>
240 <td> Displays the time required to write the GNPTXFSIZ register many times
241 (the output shows the number of times the register is written).
242 <td> Read</td>
243 </tr>
244
245 </table>
246
247 Example usage:
248 To get the current mode:
249 cat /sys/devices/lm0/mode
250
251 To power down the USB:
252 echo 0 > /sys/devices/lm0/buspower
253 */
254
255#include <linux/kernel.h>
256#include <linux/module.h>
257#include <linux/moduleparam.h>
258#include <linux/init.h>
259#include <linux/device.h>
260#include <linux/errno.h>
261#include <linux/types.h>
262#include <linux/stat.h> /* permission constants */
263#include <linux/version.h>
264
265#include <asm/io.h>
266
267#include "linux/dwc_otg_plat.h"
268#include "dwc_otg_attr.h"
269#include "dwc_otg_driver.h"
270#include "dwc_otg_pcd.h"
271#include "dwc_otg_hcd.h"
272
273#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)
274/*
275 * MACROs for defining sysfs attribute
276 */
277#define DWC_OTG_DEVICE_ATTR_BITFIELD_SHOW(_otg_attr_name_,_addr_,_mask_,_shift_,_string_) \
278static ssize_t _otg_attr_name_##_show (struct device *_dev, struct device_attribute *attr, char *buf) \
279{ \
280    dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev); \
281    uint32_t val; \
282    val = dwc_read_reg32 (_addr_); \
283    val = (val & (_mask_)) >> _shift_; \
284    return sprintf (buf, "%s = 0x%x\n", _string_, val); \
285}
286#define DWC_OTG_DEVICE_ATTR_BITFIELD_STORE(_otg_attr_name_,_addr_,_mask_,_shift_,_string_) \
287static ssize_t _otg_attr_name_##_store (struct device *_dev, struct device_attribute *attr, \
288                    const char *buf, size_t count) \
289{ \
290    dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev); \
291    uint32_t set = simple_strtoul(buf, NULL, 16); \
292    uint32_t clear = set; \
293    clear = ((~clear) << _shift_) & _mask_; \
294    set = (set << _shift_) & _mask_; \
295    dev_dbg(_dev, "Storing Address=0x%08x Set=0x%08x Clear=0x%08x\n", (uint32_t)_addr_, set, clear); \
296    dwc_modify_reg32(_addr_, clear, set); \
297    return count; \
298}
299
300/*
301 * MACROs for defining sysfs attribute for 32-bit registers
302 */
303#define DWC_OTG_DEVICE_ATTR_REG_SHOW(_otg_attr_name_,_addr_,_string_) \
304static ssize_t _otg_attr_name_##_show (struct device *_dev, struct device_attribute *attr, char *buf) \
305{ \
306    dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev); \
307    uint32_t val; \
308    val = dwc_read_reg32 (_addr_); \
309    return sprintf (buf, "%s = 0x%08x\n", _string_, val); \
310}
311#define DWC_OTG_DEVICE_ATTR_REG_STORE(_otg_attr_name_,_addr_,_string_) \
312static ssize_t _otg_attr_name_##_store (struct device *_dev, struct device_attribute *attr, \
313                    const char *buf, size_t count) \
314{ \
315    dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev); \
316    uint32_t val = simple_strtoul(buf, NULL, 16); \
317    dev_dbg(_dev, "Storing Address=0x%08x Val=0x%08x\n", (uint32_t)_addr_, val); \
318    dwc_write_reg32(_addr_, val); \
319    return count; \
320}
321
322#else
323
324/*
325 * MACROs for defining sysfs attribute
326 */
327#define DWC_OTG_DEVICE_ATTR_BITFIELD_SHOW(_otg_attr_name_,_addr_,_mask_,_shift_,_string_) \
328static ssize_t _otg_attr_name_##_show (struct device *_dev, char *buf) \
329{ \
330    dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev);\
331    uint32_t val; \
332    val = dwc_read_reg32 (_addr_); \
333    val = (val & (_mask_)) >> _shift_; \
334    return sprintf (buf, "%s = 0x%x\n", _string_, val); \
335}
336#define DWC_OTG_DEVICE_ATTR_BITFIELD_STORE(_otg_attr_name_,_addr_,_mask_,_shift_,_string_) \
337static ssize_t _otg_attr_name_##_store (struct device *_dev, const char *buf, size_t count) \
338{ \
339    dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev);\
340    uint32_t set = simple_strtoul(buf, NULL, 16); \
341    uint32_t clear = set; \
342    clear = ((~clear) << _shift_) & _mask_; \
343    set = (set << _shift_) & _mask_; \
344    dev_dbg(_dev, "Storing Address=0x%08x Set=0x%08x Clear=0x%08x\n", (uint32_t)_addr_, set, clear); \
345    dwc_modify_reg32(_addr_, clear, set); \
346    return count; \
347}
348
349/*
350 * MACROs for defining sysfs attribute for 32-bit registers
351 */
352#define DWC_OTG_DEVICE_ATTR_REG_SHOW(_otg_attr_name_,_addr_,_string_) \
353static ssize_t _otg_attr_name_##_show (struct device *_dev, char *buf) \
354{ \
355    dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev);\
356    uint32_t val; \
357    val = dwc_read_reg32 (_addr_); \
358    return sprintf (buf, "%s = 0x%08x\n", _string_, val); \
359}
360#define DWC_OTG_DEVICE_ATTR_REG_STORE(_otg_attr_name_,_addr_,_string_) \
361static ssize_t _otg_attr_name_##_store (struct device *_dev, const char *buf, size_t count) \
362{ \
363    dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev);\
364    uint32_t val = simple_strtoul(buf, NULL, 16); \
365    dev_dbg(_dev, "Storing Address=0x%08x Val=0x%08x\n", (uint32_t)_addr_, val); \
366    dwc_write_reg32(_addr_, val); \
367    return count; \
368}
369
370#endif
371
372#define DWC_OTG_DEVICE_ATTR_BITFIELD_RW(_otg_attr_name_,_addr_,_mask_,_shift_,_string_) \
373DWC_OTG_DEVICE_ATTR_BITFIELD_SHOW(_otg_attr_name_,_addr_,_mask_,_shift_,_string_) \
374DWC_OTG_DEVICE_ATTR_BITFIELD_STORE(_otg_attr_name_,_addr_,_mask_,_shift_,_string_) \
375DEVICE_ATTR(_otg_attr_name_,0644,_otg_attr_name_##_show,_otg_attr_name_##_store);
376
377#define DWC_OTG_DEVICE_ATTR_BITFIELD_RO(_otg_attr_name_,_addr_,_mask_,_shift_,_string_) \
378DWC_OTG_DEVICE_ATTR_BITFIELD_SHOW(_otg_attr_name_,_addr_,_mask_,_shift_,_string_) \
379DEVICE_ATTR(_otg_attr_name_,0444,_otg_attr_name_##_show,NULL);
380
381#define DWC_OTG_DEVICE_ATTR_REG32_RW(_otg_attr_name_,_addr_,_string_) \
382DWC_OTG_DEVICE_ATTR_REG_SHOW(_otg_attr_name_,_addr_,_string_) \
383DWC_OTG_DEVICE_ATTR_REG_STORE(_otg_attr_name_,_addr_,_string_) \
384DEVICE_ATTR(_otg_attr_name_,0644,_otg_attr_name_##_show,_otg_attr_name_##_store);
385
386#define DWC_OTG_DEVICE_ATTR_REG32_RO(_otg_attr_name_,_addr_,_string_) \
387DWC_OTG_DEVICE_ATTR_REG_SHOW(_otg_attr_name_,_addr_,_string_) \
388DEVICE_ATTR(_otg_attr_name_,0444,_otg_attr_name_##_show,NULL);
389
390
391/** @name Functions for Show/Store of Attributes */
392/**@{*/
393
394/**
395 * Show the register offset of the Register Access.
396 */
397static ssize_t regoffset_show( struct device *_dev,
398#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)
399                   struct device_attribute *attr,
400#endif
401                   char *buf)
402{
403    dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev);
404    return snprintf(buf, sizeof("0xFFFFFFFF\n")+1,"0x%08x\n", otg_dev->reg_offset);
405}
406
407/**
408 * Set the register offset for the next Register Access Read/Write
409 */
410static ssize_t regoffset_store( struct device *_dev,
411#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)
412                struct device_attribute *attr,
413#endif
414                const char *buf,
415                size_t count )
416{
417    dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev);
418
419    uint32_t offset = simple_strtoul(buf, NULL, 16);
420    //dev_dbg(_dev, "Offset=0x%08x\n", offset);
421    if (offset < 0x00040000 ) {
422        otg_dev->reg_offset = offset;
423    }
424    else {
425        dev_err( _dev, "invalid offset\n" );
426    }
427
428    return count;
429}
430DEVICE_ATTR(regoffset, S_IRUGO|S_IWUSR, (void *)regoffset_show, regoffset_store);
431
432
433/**
434 * Show the value of the register at the offset in the reg_offset
435 * attribute.
436 */
437static ssize_t regvalue_show( struct device *_dev,
438#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)
439                  struct device_attribute *attr,
440#endif
441                  char *buf)
442{
443    dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev);
444
445    uint32_t val;
446    volatile uint32_t *addr;
447
448    if (otg_dev->reg_offset != 0xFFFFFFFF &&
449        0 != otg_dev->base) {
450        /* Calculate the address */
451        addr = (uint32_t*)(otg_dev->reg_offset +
452                   (uint8_t*)otg_dev->base);
453        //dev_dbg(_dev, "@0x%08x\n", (unsigned)addr);
454        val = dwc_read_reg32( addr );
455        return snprintf(buf, sizeof("Reg@0xFFFFFFFF = 0xFFFFFFFF\n")+1,
456                "Reg@0x%06x = 0x%08x\n",
457                otg_dev->reg_offset, val);
458    }
459    else {
460        dev_err(_dev, "Invalid offset (0x%0x)\n",
461            otg_dev->reg_offset);
462        return sprintf(buf, "invalid offset\n" );
463    }
464}
465
466/**
467 * Store the value in the register at the offset in the reg_offset
468 * attribute.
469 *
470 */
471static ssize_t regvalue_store( struct device *_dev,
472#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)
473                   struct device_attribute *attr,
474#endif
475                   const char *buf,
476                   size_t count )
477{
478    dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev);
479
480    volatile uint32_t * addr;
481    uint32_t val = simple_strtoul(buf, NULL, 16);
482    //dev_dbg(_dev, "Offset=0x%08x Val=0x%08x\n", otg_dev->reg_offset, val);
483    if (otg_dev->reg_offset != 0xFFFFFFFF && 0 != otg_dev->base) {
484        /* Calculate the address */
485        addr = (uint32_t*)(otg_dev->reg_offset +
486                   (uint8_t*)otg_dev->base);
487        //dev_dbg(_dev, "@0x%08x\n", (unsigned)addr);
488        dwc_write_reg32( addr, val );
489    }
490    else {
491        dev_err(_dev, "Invalid Register Offset (0x%08x)\n",
492            otg_dev->reg_offset);
493    }
494    return count;
495}
496DEVICE_ATTR(regvalue, S_IRUGO|S_IWUSR, regvalue_show, regvalue_store);
497
498/*
499 * Attributes
500 */
501DWC_OTG_DEVICE_ATTR_BITFIELD_RO(mode,&(otg_dev->core_if->core_global_regs->gotgctl),(1<<20),20,"Mode");
502DWC_OTG_DEVICE_ATTR_BITFIELD_RW(hnpcapable,&(otg_dev->core_if->core_global_regs->gusbcfg),(1<<9),9,"Mode");
503DWC_OTG_DEVICE_ATTR_BITFIELD_RW(srpcapable,&(otg_dev->core_if->core_global_regs->gusbcfg),(1<<8),8,"Mode");
504
505//DWC_OTG_DEVICE_ATTR_BITFIELD_RW(buspower,&(otg_dev->core_if->core_global_regs->gotgctl),(1<<8),8,"Mode");
506//DWC_OTG_DEVICE_ATTR_BITFIELD_RW(bussuspend,&(otg_dev->core_if->core_global_regs->gotgctl),(1<<8),8,"Mode");
507DWC_OTG_DEVICE_ATTR_BITFIELD_RO(busconnected,otg_dev->core_if->host_if->hprt0,0x01,0,"Bus Connected");
508
509DWC_OTG_DEVICE_ATTR_REG32_RW(gotgctl,&(otg_dev->core_if->core_global_regs->gotgctl),"GOTGCTL");
510DWC_OTG_DEVICE_ATTR_REG32_RW(gusbcfg,&(otg_dev->core_if->core_global_regs->gusbcfg),"GUSBCFG");
511DWC_OTG_DEVICE_ATTR_REG32_RW(grxfsiz,&(otg_dev->core_if->core_global_regs->grxfsiz),"GRXFSIZ");
512DWC_OTG_DEVICE_ATTR_REG32_RW(gnptxfsiz,&(otg_dev->core_if->core_global_regs->gnptxfsiz),"GNPTXFSIZ");
513DWC_OTG_DEVICE_ATTR_REG32_RW(gpvndctl,&(otg_dev->core_if->core_global_regs->gpvndctl),"GPVNDCTL");
514DWC_OTG_DEVICE_ATTR_REG32_RW(ggpio,&(otg_dev->core_if->core_global_regs->ggpio),"GGPIO");
515DWC_OTG_DEVICE_ATTR_REG32_RW(guid,&(otg_dev->core_if->core_global_regs->guid),"GUID");
516DWC_OTG_DEVICE_ATTR_REG32_RO(gsnpsid,&(otg_dev->core_if->core_global_regs->gsnpsid),"GSNPSID");
517DWC_OTG_DEVICE_ATTR_BITFIELD_RW(devspeed,&(otg_dev->core_if->dev_if->dev_global_regs->dcfg),0x3,0,"Device Speed");
518DWC_OTG_DEVICE_ATTR_BITFIELD_RO(enumspeed,&(otg_dev->core_if->dev_if->dev_global_regs->dsts),0x6,1,"Device Enumeration Speed");
519
520DWC_OTG_DEVICE_ATTR_REG32_RO(hptxfsiz,&(otg_dev->core_if->core_global_regs->hptxfsiz),"HPTXFSIZ");
521DWC_OTG_DEVICE_ATTR_REG32_RW(hprt0,otg_dev->core_if->host_if->hprt0,"HPRT0");
522
523
524/**
525 * @todo Add code to initiate the HNP.
526 */
527/**
528 * Show the HNP status bit
529 */
530static ssize_t hnp_show( struct device *_dev,
531#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)
532             struct device_attribute *attr,
533#endif
534             char *buf)
535{
536    dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev);
537
538    gotgctl_data_t val;
539    val.d32 = dwc_read_reg32 (&(otg_dev->core_if->core_global_regs->gotgctl));
540    return sprintf (buf, "HstNegScs = 0x%x\n", val.b.hstnegscs);
541}
542
543/**
544 * Set the HNP Request bit
545 */
546static ssize_t hnp_store( struct device *_dev,
547#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)
548              struct device_attribute *attr,
549#endif
550              const char *buf,
551              size_t count )
552{
553    dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev);
554
555    uint32_t in = simple_strtoul(buf, NULL, 16);
556    uint32_t *addr = (uint32_t *)&(otg_dev->core_if->core_global_regs->gotgctl);
557    gotgctl_data_t mem;
558    mem.d32 = dwc_read_reg32(addr);
559    mem.b.hnpreq = in;
560    dev_dbg(_dev, "Storing Address=0x%08x Data=0x%08x\n", (uint32_t)addr, mem.d32);
561    dwc_write_reg32(addr, mem.d32);
562    return count;
563}
564DEVICE_ATTR(hnp, 0644, hnp_show, hnp_store);
565
566/**
567 * @todo Add code to initiate the SRP.
568 */
569/**
570 * Show the SRP status bit
571 */
572static ssize_t srp_show( struct device *_dev,
573#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)
574             struct device_attribute *attr,
575#endif
576             char *buf)
577{
578#ifndef DWC_HOST_ONLY
579    dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev);
580
581    gotgctl_data_t val;
582    val.d32 = dwc_read_reg32 (&(otg_dev->core_if->core_global_regs->gotgctl));
583    return sprintf (buf, "SesReqScs = 0x%x\n", val.b.sesreqscs);
584#else
585    return sprintf(buf, "Host Only Mode!\n");
586#endif
587}
588
589
590
591/**
592 * Set the SRP Request bit
593 */
594static ssize_t srp_store( struct device *_dev,
595#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)
596              struct device_attribute *attr,
597#endif
598              const char *buf,
599              size_t count )
600{
601#ifndef DWC_HOST_ONLY
602    dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev);
603
604    dwc_otg_pcd_initiate_srp(otg_dev->pcd);
605#endif
606    return count;
607}
608DEVICE_ATTR(srp, 0644, srp_show, srp_store);
609
610/**
611 * @todo Need to do more for power on/off?
612 */
613/**
614 * Show the Bus Power status
615 */
616static ssize_t buspower_show( struct device *_dev,
617#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)
618                  struct device_attribute *attr,
619#endif
620                  char *buf)
621{
622    dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev);
623
624    hprt0_data_t val;
625    val.d32 = dwc_read_reg32 (otg_dev->core_if->host_if->hprt0);
626    return sprintf (buf, "Bus Power = 0x%x\n", val.b.prtpwr);
627}
628
629
630/**
631 * Set the Bus Power status
632 */
633static ssize_t buspower_store( struct device *_dev,
634#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)
635                   struct device_attribute *attr,
636#endif
637                   const char *buf,
638                   size_t count )
639{
640    dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev);
641
642    uint32_t on = simple_strtoul(buf, NULL, 16);
643    uint32_t *addr = (uint32_t *)otg_dev->core_if->host_if->hprt0;
644    hprt0_data_t mem;
645
646    mem.d32 = dwc_read_reg32(addr);
647    mem.b.prtpwr = on;
648
649    //dev_dbg(_dev, "Storing Address=0x%08x Data=0x%08x\n", (uint32_t)addr, mem.d32);
650    dwc_write_reg32(addr, mem.d32);
651
652    return count;
653}
654DEVICE_ATTR(buspower, 0644, buspower_show, buspower_store);
655
656/**
657 * @todo Need to do more for suspend?
658 */
659/**
660 * Show the Bus Suspend status
661 */
662static ssize_t bussuspend_show( struct device *_dev,
663#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)
664                struct device_attribute *attr,
665#endif
666                char *buf)
667{
668    dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev);
669
670    hprt0_data_t val;
671    val.d32 = dwc_read_reg32 (otg_dev->core_if->host_if->hprt0);
672    return sprintf (buf, "Bus Suspend = 0x%x\n", val.b.prtsusp);
673}
674
675/**
676 * Set the Bus Suspend status
677 */
678static ssize_t bussuspend_store( struct device *_dev,
679#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)
680                 struct device_attribute *attr,
681#endif
682                 const char *buf,
683                 size_t count )
684{
685    dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev);
686
687    uint32_t in = simple_strtoul(buf, NULL, 16);
688    uint32_t *addr = (uint32_t *)otg_dev->core_if->host_if->hprt0;
689    hprt0_data_t mem;
690    mem.d32 = dwc_read_reg32(addr);
691    mem.b.prtsusp = in;
692    dev_dbg(_dev, "Storing Address=0x%08x Data=0x%08x\n", (uint32_t)addr, mem.d32);
693    dwc_write_reg32(addr, mem.d32);
694    return count;
695}
696DEVICE_ATTR(bussuspend, 0644, bussuspend_show, bussuspend_store);
697
698/**
699 * Show the status of Remote Wakeup.
700 */
701static ssize_t remote_wakeup_show( struct device *_dev,
702#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)
703                   struct device_attribute *attr,
704#endif
705                   char *buf)
706{
707#ifndef DWC_HOST_ONLY
708    dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev);
709
710    dctl_data_t val;
711    val.d32 =
712        dwc_read_reg32( &otg_dev->core_if->dev_if->dev_global_regs->dctl);
713    return sprintf( buf, "Remote Wakeup = %d Enabled = %d\n",
714            val.b.rmtwkupsig, otg_dev->pcd->remote_wakeup_enable);
715#else
716    return sprintf(buf, "Host Only Mode!\n");
717#endif
718}
719/**
720 * Initiate a remote wakeup of the host. The Device control register
721 * Remote Wakeup Signal bit is written if the PCD Remote wakeup enable
722 * flag is set.
723 *
724 */
725static ssize_t remote_wakeup_store( struct device *_dev,
726#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)
727                    struct device_attribute *attr,
728#endif
729                    const char *buf,
730                    size_t count )
731{
732#ifndef DWC_HOST_ONLY
733    dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev);
734
735    uint32_t val = simple_strtoul(buf, NULL, 16);
736    if (val&1) {
737        dwc_otg_pcd_remote_wakeup(otg_dev->pcd, 1);
738    }
739    else {
740        dwc_otg_pcd_remote_wakeup(otg_dev->pcd, 0);
741    }
742#endif
743    return count;
744}
745DEVICE_ATTR(remote_wakeup, S_IRUGO|S_IWUSR, remote_wakeup_show,
746        remote_wakeup_store);
747
748/**
749 * Dump global registers and either host or device registers (depending on the
750 * current mode of the core).
751 */
752static ssize_t regdump_show( struct device *_dev,
753#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)
754                 struct device_attribute *attr,
755#endif
756                 char *buf)
757{
758    dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev);
759
760        dwc_otg_dump_global_registers( otg_dev->core_if);
761        if (dwc_otg_is_host_mode(otg_dev->core_if)) {
762                dwc_otg_dump_host_registers( otg_dev->core_if);
763        } else {
764                dwc_otg_dump_dev_registers( otg_dev->core_if);
765
766        }
767       return sprintf( buf, "Register Dump\n" );
768}
769
770DEVICE_ATTR(regdump, S_IRUGO|S_IWUSR, regdump_show, 0);
771
772/**
773 * Dump global registers and either host or device registers (depending on the
774 * current mode of the core).
775 */
776static ssize_t spramdump_show( struct device *_dev,
777#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)
778                   struct device_attribute *attr,
779#endif
780                   char *buf)
781{
782    dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev);
783
784        dwc_otg_dump_spram( otg_dev->core_if);
785
786        return sprintf( buf, "SPRAM Dump\n" );
787}
788
789DEVICE_ATTR(spramdump, S_IRUGO|S_IWUSR, spramdump_show, 0);
790
791/**
792 * Dump the current hcd state.
793 */
794static ssize_t hcddump_show( struct device *_dev,
795#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)
796                 struct device_attribute *attr,
797#endif
798                 char *buf)
799{
800#ifndef DWC_DEVICE_ONLY
801    dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev);
802
803    dwc_otg_hcd_dump_state(otg_dev->hcd);
804#endif
805       return sprintf( buf, "HCD Dump\n" );
806}
807
808DEVICE_ATTR(hcddump, S_IRUGO|S_IWUSR, hcddump_show, 0);
809
810/**
811 * Dump the average frame remaining at SOF. This can be used to
812 * determine average interrupt latency. Frame remaining is also shown for
813 * start transfer and two additional sample points.
814 */
815static ssize_t hcd_frrem_show( struct device *_dev,
816#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)
817                   struct device_attribute *attr,
818#endif
819                   char *buf)
820{
821#ifndef DWC_DEVICE_ONLY
822    dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev);
823
824    dwc_otg_hcd_dump_frrem(otg_dev->hcd);
825#endif
826       return sprintf( buf, "HCD Dump Frame Remaining\n" );
827}
828
829DEVICE_ATTR(hcd_frrem, S_IRUGO|S_IWUSR, hcd_frrem_show, 0);
830
831/**
832 * Displays the time required to read the GNPTXFSIZ register many times (the
833 * output shows the number of times the register is read).
834 */
835#define RW_REG_COUNT 10000000
836#define MSEC_PER_JIFFIE 1000/HZ
837static ssize_t rd_reg_test_show( struct device *_dev,
838#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)
839                 struct device_attribute *attr,
840#endif
841                 char *buf)
842{
843    dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev);
844
845    int i;
846    int time;
847    int start_jiffies;
848
849    printk("HZ %d, MSEC_PER_JIFFIE %d, loops_per_jiffy %lu\n",
850           HZ, MSEC_PER_JIFFIE, loops_per_jiffy);
851    start_jiffies = jiffies;
852    for (i = 0; i < RW_REG_COUNT; i++) {
853        dwc_read_reg32(&otg_dev->core_if->core_global_regs->gnptxfsiz);
854    }
855    time = jiffies - start_jiffies;
856       return sprintf( buf, "Time to read GNPTXFSIZ reg %d times: %d msecs (%d jiffies)\n",
857            RW_REG_COUNT, time * MSEC_PER_JIFFIE, time );
858}
859
860DEVICE_ATTR(rd_reg_test, S_IRUGO|S_IWUSR, rd_reg_test_show, 0);
861
862/**
863 * Displays the time required to write the GNPTXFSIZ register many times (the
864 * output shows the number of times the register is written).
865 */
866static ssize_t wr_reg_test_show( struct device *_dev,
867#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)
868                 struct device_attribute *attr,
869#endif
870                 char *buf)
871{
872    dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev);
873
874    uint32_t reg_val;
875    int i;
876    int time;
877    int start_jiffies;
878
879    printk("HZ %d, MSEC_PER_JIFFIE %d, loops_per_jiffy %lu\n",
880           HZ, MSEC_PER_JIFFIE, loops_per_jiffy);
881    reg_val = dwc_read_reg32(&otg_dev->core_if->core_global_regs->gnptxfsiz);
882    start_jiffies = jiffies;
883    for (i = 0; i < RW_REG_COUNT; i++) {
884        dwc_write_reg32(&otg_dev->core_if->core_global_regs->gnptxfsiz, reg_val);
885    }
886    time = jiffies - start_jiffies;
887       return sprintf( buf, "Time to write GNPTXFSIZ reg %d times: %d msecs (%d jiffies)\n",
888            RW_REG_COUNT, time * MSEC_PER_JIFFIE, time);
889}
890
891DEVICE_ATTR(wr_reg_test, S_IRUGO|S_IWUSR, wr_reg_test_show, 0);
892/**@}*/
893
894/**
895 * Create the device files
896 */
897void dwc_otg_attr_create (struct device *dev)
898{
899    int error;
900
901    error = device_create_file(dev, &dev_attr_regoffset);
902    error = device_create_file(dev, &dev_attr_regvalue);
903    error = device_create_file(dev, &dev_attr_mode);
904    error = device_create_file(dev, &dev_attr_hnpcapable);
905    error = device_create_file(dev, &dev_attr_srpcapable);
906    error = device_create_file(dev, &dev_attr_hnp);
907    error = device_create_file(dev, &dev_attr_srp);
908    error = device_create_file(dev, &dev_attr_buspower);
909    error = device_create_file(dev, &dev_attr_bussuspend);
910    error = device_create_file(dev, &dev_attr_busconnected);
911    error = device_create_file(dev, &dev_attr_gotgctl);
912    error = device_create_file(dev, &dev_attr_gusbcfg);
913    error = device_create_file(dev, &dev_attr_grxfsiz);
914    error = device_create_file(dev, &dev_attr_gnptxfsiz);
915    error = device_create_file(dev, &dev_attr_gpvndctl);
916    error = device_create_file(dev, &dev_attr_ggpio);
917    error = device_create_file(dev, &dev_attr_guid);
918    error = device_create_file(dev, &dev_attr_gsnpsid);
919    error = device_create_file(dev, &dev_attr_devspeed);
920    error = device_create_file(dev, &dev_attr_enumspeed);
921    error = device_create_file(dev, &dev_attr_hptxfsiz);
922    error = device_create_file(dev, &dev_attr_hprt0);
923    error = device_create_file(dev, &dev_attr_remote_wakeup);
924    error = device_create_file(dev, &dev_attr_regdump);
925    error = device_create_file(dev, &dev_attr_spramdump);
926    error = device_create_file(dev, &dev_attr_hcddump);
927    error = device_create_file(dev, &dev_attr_hcd_frrem);
928    error = device_create_file(dev, &dev_attr_rd_reg_test);
929    error = device_create_file(dev, &dev_attr_wr_reg_test);
930}
931
932/**
933 * Remove the device files
934 */
935void dwc_otg_attr_remove (struct device *dev)
936{
937    device_remove_file(dev, &dev_attr_regoffset);
938    device_remove_file(dev, &dev_attr_regvalue);
939    device_remove_file(dev, &dev_attr_mode);
940    device_remove_file(dev, &dev_attr_hnpcapable);
941    device_remove_file(dev, &dev_attr_srpcapable);
942    device_remove_file(dev, &dev_attr_hnp);
943    device_remove_file(dev, &dev_attr_srp);
944    device_remove_file(dev, &dev_attr_buspower);
945    device_remove_file(dev, &dev_attr_bussuspend);
946    device_remove_file(dev, &dev_attr_busconnected);
947    device_remove_file(dev, &dev_attr_gotgctl);
948    device_remove_file(dev, &dev_attr_gusbcfg);
949    device_remove_file(dev, &dev_attr_grxfsiz);
950    device_remove_file(dev, &dev_attr_gnptxfsiz);
951    device_remove_file(dev, &dev_attr_gpvndctl);
952    device_remove_file(dev, &dev_attr_ggpio);
953    device_remove_file(dev, &dev_attr_guid);
954    device_remove_file(dev, &dev_attr_gsnpsid);
955    device_remove_file(dev, &dev_attr_devspeed);
956    device_remove_file(dev, &dev_attr_enumspeed);
957    device_remove_file(dev, &dev_attr_hptxfsiz);
958    device_remove_file(dev, &dev_attr_hprt0);
959    device_remove_file(dev, &dev_attr_remote_wakeup);
960    device_remove_file(dev, &dev_attr_regdump);
961    device_remove_file(dev, &dev_attr_spramdump);
962    device_remove_file(dev, &dev_attr_hcddump);
963    device_remove_file(dev, &dev_attr_hcd_frrem);
964    device_remove_file(dev, &dev_attr_rd_reg_test);
965    device_remove_file(dev, &dev_attr_wr_reg_test);
966}
967

Archive Download this file



interactive