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

1/* ==========================================================================
2 * $File: //dwh/usb_iip/dev/software/otg_ipmate/linux/drivers/dwc_otg_attr.c $
3 * $Revision: 1.1.1.1 $
4 * $Date: 2009-04-17 06:15:34 $
5 * $Change: 537387 $
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> hcddump </td>
210 <td> Dumps the current HCD state.</td>
211 <td> Read</td>
212 </tr>
213 
214 <tr>
215 <td> hcd_frrem </td>
216 <td> Shows the average value of the Frame Remaining
217 field in the Host Frame Number/Frame Remaining register when an SOF interrupt
218 occurs. This can be used to determine the average interrupt latency. Also
219 shows the average Frame Remaining value for start_transfer and the "a" and
220 "b" sample points. The "a" and "b" sample points may be used during debugging
221 bto determine how long it takes to execute a section of the HCD code.</td>
222 <td> Read</td>
223 </tr>
224 
225 <tr>
226 <td> rd_reg_test </td>
227 <td> Displays the time required to read the GNPTXFSIZ register many times
228 (the output shows the number of times the register is read).
229 <td> Read</td>
230 </tr>
231 
232 <tr>
233 <td> wr_reg_test </td>
234 <td> Displays the time required to write the GNPTXFSIZ register many times
235 (the output shows the number of times the register is written).
236 <td> Read</td>
237 </tr>
238 
239 </table>
240 
241 Example usage:
242 To get the current mode:
243 cat /sys/devices/lm0/mode
244 
245 To power down the USB:
246 echo 0 > /sys/devices/lm0/buspower
247 */
248#include <linux/kernel.h>
249#include <linux/module.h>
250#include <linux/moduleparam.h>
251#include <linux/init.h>
252#include <linux/device.h>
253#include <linux/errno.h>
254#include <linux/types.h>
255#include <linux/stat.h> /* permission constants */
256
257#include <asm/io.h>
258
259#include "dwc_otg_plat.h"
260#include "dwc_otg_attr.h"
261#include "dwc_otg_driver.h"
262// #include "dwc_otg_pcd.h"
263#include "dwc_otg_hcd.h"
264
265// 20070316, winder added.
266#ifndef SZ_256K
267#define SZ_256K 0x00040000
268#endif
269
270/*
271 * MACROs for defining sysfs attribute
272 */
273#define DWC_OTG_DEVICE_ATTR_BITFIELD_SHOW(_otg_attr_name_,_addr_,_mask_,_shift_,_string_) \
274static ssize_t _otg_attr_name_##_show (struct device *_dev, struct device_attribute *attr, char *buf) \
275{ \
276        dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev);\
277    uint32_t val; \
278    val = dwc_read_reg32 (_addr_); \
279    val = (val & (_mask_)) >> _shift_; \
280    return sprintf (buf, "%s = 0x%x\n", _string_, val); \
281}
282#define DWC_OTG_DEVICE_ATTR_BITFIELD_STORE(_otg_attr_name_,_addr_,_mask_,_shift_,_string_) \
283static ssize_t _otg_attr_name_##_store (struct device *_dev, struct device_attribute *attr, const char *buf, size_t count) \
284{ \
285        dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev);\
286    uint32_t set = simple_strtoul(buf, NULL, 16); \
287    uint32_t clear = set; \
288    clear = ((~clear) << _shift_) & _mask_; \
289    set = (set << _shift_) & _mask_; \
290    dev_dbg(_dev, "Storing Address=0x%08x Set=0x%08x Clear=0x%08x\n", (uint32_t)_addr_, set, clear); \
291    dwc_modify_reg32(_addr_, clear, set); \
292    return count; \
293}
294
295#define DWC_OTG_DEVICE_ATTR_BITFIELD_RW(_otg_attr_name_,_addr_,_mask_,_shift_,_string_) \
296DWC_OTG_DEVICE_ATTR_BITFIELD_SHOW(_otg_attr_name_,_addr_,_mask_,_shift_,_string_) \
297DWC_OTG_DEVICE_ATTR_BITFIELD_STORE(_otg_attr_name_,_addr_,_mask_,_shift_,_string_) \
298DEVICE_ATTR(_otg_attr_name_,0644,_otg_attr_name_##_show,_otg_attr_name_##_store);
299
300#define DWC_OTG_DEVICE_ATTR_BITFIELD_RO(_otg_attr_name_,_addr_,_mask_,_shift_,_string_) \
301DWC_OTG_DEVICE_ATTR_BITFIELD_SHOW(_otg_attr_name_,_addr_,_mask_,_shift_,_string_) \
302DEVICE_ATTR(_otg_attr_name_,0444,_otg_attr_name_##_show,NULL);
303
304/*
305 * MACROs for defining sysfs attribute for 32-bit registers
306 */
307#define DWC_OTG_DEVICE_ATTR_REG_SHOW(_otg_attr_name_,_addr_,_string_) \
308static ssize_t _otg_attr_name_##_show (struct device *_dev, struct device_attribute *attr, char *buf) \
309{ \
310        dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev);\
311    uint32_t val; \
312    val = dwc_read_reg32 (_addr_); \
313    return sprintf (buf, "%s = 0x%08x\n", _string_, val); \
314}
315#define DWC_OTG_DEVICE_ATTR_REG_STORE(_otg_attr_name_,_addr_,_string_) \
316static ssize_t _otg_attr_name_##_store (struct device *_dev, struct device_attribute *attr, const char *buf, size_t count) \
317{ \
318        dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev);\
319    uint32_t val = simple_strtoul(buf, NULL, 16); \
320    dev_dbg(_dev, "Storing Address=0x%08x Val=0x%08x\n", (uint32_t)_addr_, val); \
321    dwc_write_reg32(_addr_, val); \
322    return count; \
323}
324
325#define DWC_OTG_DEVICE_ATTR_REG32_RW(_otg_attr_name_,_addr_,_string_) \
326DWC_OTG_DEVICE_ATTR_REG_SHOW(_otg_attr_name_,_addr_,_string_) \
327DWC_OTG_DEVICE_ATTR_REG_STORE(_otg_attr_name_,_addr_,_string_) \
328DEVICE_ATTR(_otg_attr_name_,0644,_otg_attr_name_##_show,_otg_attr_name_##_store);
329
330#define DWC_OTG_DEVICE_ATTR_REG32_RO(_otg_attr_name_,_addr_,_string_) \
331DWC_OTG_DEVICE_ATTR_REG_SHOW(_otg_attr_name_,_addr_,_string_) \
332DEVICE_ATTR(_otg_attr_name_,0444,_otg_attr_name_##_show,NULL);
333
334
335/** @name Functions for Show/Store of Attributes */
336/**@{*/
337
338/**
339 * Show the register offset of the Register Access.
340 */
341static ssize_t regoffset_show( struct device *_dev, struct device_attribute *attr, char *buf)
342{
343        dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev);
344    return snprintf(buf, sizeof("0xFFFFFFFF\n")+1,"0x%08x\n", otg_dev->reg_offset);
345}
346
347/**
348 * Set the register offset for the next Register Access Read/Write
349 */
350static ssize_t regoffset_store( struct device *_dev, struct device_attribute *attr, const char *buf,
351                                size_t count )
352{
353        dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev);
354    uint32_t offset = simple_strtoul(buf, NULL, 16);
355    //dev_dbg(_dev, "Offset=0x%08x\n", offset);
356    if (offset < SZ_256K ) {
357        otg_dev->reg_offset = offset;
358    }
359    else {
360        dev_err( _dev, "invalid offset\n" );
361    }
362
363    return count;
364}
365DEVICE_ATTR(regoffset, S_IRUGO|S_IWUSR, regoffset_show, regoffset_store);
366
367/**
368 * Show the value of the register at the offset in the reg_offset
369 * attribute.
370 */
371static ssize_t regvalue_show( struct device *_dev, struct device_attribute *attr, char *buf)
372{
373    dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev);
374    uint32_t val;
375    volatile uint32_t *addr;
376        
377    if (otg_dev->reg_offset != 0xFFFFFFFF && 0 != otg_dev->base) {
378        /* Calculate the address */
379        addr = (uint32_t*)(otg_dev->reg_offset +
380                   (uint8_t*)otg_dev->base);
381        //dev_dbg(_dev, "@0x%08x\n", (unsigned)addr);
382        val = dwc_read_reg32( addr );
383        return snprintf(buf, sizeof("Reg@0xFFFFFFFF = 0xFFFFFFFF\n")+1,
384                "Reg@0x%06x = 0x%08x\n",
385                otg_dev->reg_offset, val);
386    }
387    else {
388        dev_err(_dev, "Invalid offset (0x%0x)\n",
389            otg_dev->reg_offset);
390        return sprintf(buf, "invalid offset\n" );
391    }
392}
393
394/**
395 * Store the value in the register at the offset in the reg_offset
396 * attribute.
397 *
398 */
399static ssize_t regvalue_store( struct device *_dev, struct device_attribute *attr, const char *buf,
400                               size_t count )
401{
402        dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev);
403    volatile uint32_t * addr;
404    uint32_t val = simple_strtoul(buf, NULL, 16);
405    //dev_dbg(_dev, "Offset=0x%08x Val=0x%08x\n", otg_dev->reg_offset, val);
406    if (otg_dev->reg_offset != 0xFFFFFFFF && 0 != otg_dev->base) {
407        /* Calculate the address */
408        addr = (uint32_t*)(otg_dev->reg_offset +
409                   (uint8_t*)otg_dev->base);
410        //dev_dbg(_dev, "@0x%08x\n", (unsigned)addr);
411        dwc_write_reg32( addr, val );
412    }
413    else {
414        dev_err(_dev, "Invalid Register Offset (0x%08x)\n",
415            otg_dev->reg_offset);
416    }
417    return count;
418}
419DEVICE_ATTR(regvalue, S_IRUGO|S_IWUSR, regvalue_show, regvalue_store);
420
421/*
422 * Attributes
423 */
424DWC_OTG_DEVICE_ATTR_BITFIELD_RO(mode,&(otg_dev->core_if->core_global_regs->gotgctl),(1<<20),20,"Mode");
425DWC_OTG_DEVICE_ATTR_BITFIELD_RW(hnpcapable,&(otg_dev->core_if->core_global_regs->gusbcfg),(1<<9),9,"Mode");
426DWC_OTG_DEVICE_ATTR_BITFIELD_RW(srpcapable,&(otg_dev->core_if->core_global_regs->gusbcfg),(1<<8),8,"Mode");
427
428//DWC_OTG_DEVICE_ATTR_BITFIELD_RW(buspower,&(otg_dev->core_if->core_global_regs->gotgctl),(1<<8),8,"Mode");
429//DWC_OTG_DEVICE_ATTR_BITFIELD_RW(bussuspend,&(otg_dev->core_if->core_global_regs->gotgctl),(1<<8),8,"Mode");
430DWC_OTG_DEVICE_ATTR_BITFIELD_RO(busconnected,otg_dev->core_if->host_if->hprt0,0x01,0,"Bus Connected");
431
432DWC_OTG_DEVICE_ATTR_REG32_RW(gotgctl,&(otg_dev->core_if->core_global_regs->gotgctl),"GOTGCTL");
433DWC_OTG_DEVICE_ATTR_REG32_RW(gusbcfg,&(otg_dev->core_if->core_global_regs->gusbcfg),"GUSBCFG");
434DWC_OTG_DEVICE_ATTR_REG32_RW(grxfsiz,&(otg_dev->core_if->core_global_regs->grxfsiz),"GRXFSIZ");
435DWC_OTG_DEVICE_ATTR_REG32_RW(gnptxfsiz,&(otg_dev->core_if->core_global_regs->gnptxfsiz),"GNPTXFSIZ");
436DWC_OTG_DEVICE_ATTR_REG32_RW(gpvndctl,&(otg_dev->core_if->core_global_regs->gpvndctl),"GPVNDCTL");
437DWC_OTG_DEVICE_ATTR_REG32_RW(ggpio,&(otg_dev->core_if->core_global_regs->ggpio),"GGPIO");
438DWC_OTG_DEVICE_ATTR_REG32_RW(guid,&(otg_dev->core_if->core_global_regs->guid),"GUID");
439DWC_OTG_DEVICE_ATTR_REG32_RO(gsnpsid,&(otg_dev->core_if->core_global_regs->gsnpsid),"GSNPSID");
440DWC_OTG_DEVICE_ATTR_BITFIELD_RW(devspeed,&(otg_dev->core_if->dev_if->dev_global_regs->dcfg),0x3,0,"Device Speed");
441DWC_OTG_DEVICE_ATTR_BITFIELD_RO(enumspeed,&(otg_dev->core_if->dev_if->dev_global_regs->dsts),0x6,1,"Device Enumeration Speed");
442
443DWC_OTG_DEVICE_ATTR_REG32_RO(hptxfsiz,&(otg_dev->core_if->core_global_regs->hptxfsiz),"HPTXFSIZ");
444DWC_OTG_DEVICE_ATTR_REG32_RW(hprt0,otg_dev->core_if->host_if->hprt0,"HPRT0");
445
446
447/**
448 * @todo Add code to initiate the HNP.
449 */
450/**
451 * Show the HNP status bit
452 */
453static ssize_t hnp_show( struct device *_dev, struct device_attribute *attr, char *buf)
454{
455        dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev);
456    gotgctl_data_t val;
457    val.d32 = dwc_read_reg32 (&(otg_dev->core_if->core_global_regs->gotgctl));
458    return sprintf (buf, "HstNegScs = 0x%x\n", val.b.hstnegscs);
459}
460
461/**
462 * Set the HNP Request bit
463 */
464static ssize_t hnp_store( struct device *_dev, struct device_attribute *attr, const char *buf,
465              size_t count )
466{
467        dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev);
468    uint32_t in = simple_strtoul(buf, NULL, 16);
469    uint32_t *addr = (uint32_t *)&(otg_dev->core_if->core_global_regs->gotgctl);
470    gotgctl_data_t mem;
471    mem.d32 = dwc_read_reg32(addr);
472    mem.b.hnpreq = in;
473    dev_dbg(_dev, "Storing Address=0x%08x Data=0x%08x\n", (uint32_t)addr, mem.d32);
474    dwc_write_reg32(addr, mem.d32);
475    return count;
476}
477DEVICE_ATTR(hnp, 0644, hnp_show, hnp_store);
478
479/**
480 * @todo Add code to initiate the SRP.
481 */
482/**
483 * Show the SRP status bit
484 */
485static ssize_t srp_show( struct device *_dev, struct device_attribute *attr, char *buf)
486{
487#ifndef DWC_HOST_ONLY
488        dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev);
489    gotgctl_data_t val;
490    val.d32 = dwc_read_reg32 (&(otg_dev->core_if->core_global_regs->gotgctl));
491    return sprintf (buf, "SesReqScs = 0x%x\n", val.b.sesreqscs);
492#else
493    return sprintf(buf, "Host Only Mode!\n");
494#endif
495}
496
497/**
498 * Set the SRP Request bit
499 */
500static ssize_t srp_store( struct device *_dev, struct device_attribute *attr, const char *buf,
501              size_t count )
502{
503#ifndef DWC_HOST_ONLY
504        dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev);
505    dwc_otg_pcd_initiate_srp(otg_dev->pcd);
506#endif
507    return count;
508}
509DEVICE_ATTR(srp, 0644, srp_show, srp_store);
510
511/**
512 * @todo Need to do more for power on/off?
513 */
514/**
515 * Show the Bus Power status
516 */
517static ssize_t buspower_show( struct device *_dev, struct device_attribute *attr, char *buf)
518{
519        dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev);
520    hprt0_data_t val;
521    val.d32 = dwc_read_reg32 (otg_dev->core_if->host_if->hprt0);
522    return sprintf (buf, "Bus Power = 0x%x\n", val.b.prtpwr);
523}
524
525
526/**
527 * Set the Bus Power status
528 */
529static ssize_t buspower_store( struct device *_dev, struct device_attribute *attr, const char *buf,
530                               size_t count )
531{
532        dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev);
533    uint32_t on = simple_strtoul(buf, NULL, 16);
534    uint32_t *addr = (uint32_t *)otg_dev->core_if->host_if->hprt0;
535    hprt0_data_t mem;
536
537    mem.d32 = dwc_read_reg32(addr);
538    mem.b.prtpwr = on;
539
540    //dev_dbg(_dev, "Storing Address=0x%08x Data=0x%08x\n", (uint32_t)addr, mem.d32);
541    dwc_write_reg32(addr, mem.d32);
542
543    return count;
544}
545DEVICE_ATTR(buspower, 0644, buspower_show, buspower_store);
546
547/**
548 * @todo Need to do more for suspend?
549 */
550/**
551 * Show the Bus Suspend status
552 */
553static ssize_t bussuspend_show( struct device *_dev, struct device_attribute *attr, char *buf)
554{
555        dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev);
556    hprt0_data_t val;
557    val.d32 = dwc_read_reg32 (otg_dev->core_if->host_if->hprt0);
558    return sprintf (buf, "Bus Suspend = 0x%x\n", val.b.prtsusp);
559}
560
561/**
562 * Set the Bus Suspend status
563 */
564static ssize_t bussuspend_store( struct device *_dev, struct device_attribute *attr, const char *buf,
565                                 size_t count )
566{
567        dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev);
568    uint32_t in = simple_strtoul(buf, NULL, 16);
569    uint32_t *addr = (uint32_t *)otg_dev->core_if->host_if->hprt0;
570    hprt0_data_t mem;
571    mem.d32 = dwc_read_reg32(addr);
572    mem.b.prtsusp = in;
573    dev_dbg(_dev, "Storing Address=0x%08x Data=0x%08x\n", (uint32_t)addr, mem.d32);
574    dwc_write_reg32(addr, mem.d32);
575    return count;
576}
577DEVICE_ATTR(bussuspend, 0644, bussuspend_show, bussuspend_store);
578
579/**
580 * Show the status of Remote Wakeup.
581 */
582static ssize_t remote_wakeup_show( struct device *_dev, struct device_attribute *attr, char *buf)
583{
584#ifndef DWC_HOST_ONLY
585        dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev);
586    dctl_data_t val;
587    val.d32 = dwc_read_reg32( &otg_dev->core_if->dev_if->dev_global_regs->dctl);
588    return sprintf( buf, "Remote Wakeup = %d Enabled = %d\n",
589                        val.b.rmtwkupsig, otg_dev->pcd->remote_wakeup_enable);
590#else
591    return sprintf(buf, "Host Only Mode!\n");
592#endif
593}
594
595/**
596 * Initiate a remote wakeup of the host. The Device control register
597 * Remote Wakeup Signal bit is written if the PCD Remote wakeup enable
598 * flag is set.
599 *
600 */
601static ssize_t remote_wakeup_store( struct device *_dev, struct device_attribute *attr, const char *buf,
602                                    size_t count )
603{
604#ifndef DWC_HOST_ONLY
605        uint32_t val = simple_strtoul(buf, NULL, 16);
606    dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev);
607    if (val&1) {
608        dwc_otg_pcd_remote_wakeup(otg_dev->pcd, 1);
609    }
610    else {
611        dwc_otg_pcd_remote_wakeup(otg_dev->pcd, 0);
612    }
613#endif
614    return count;
615}
616DEVICE_ATTR(remote_wakeup, S_IRUGO|S_IWUSR, remote_wakeup_show,
617            remote_wakeup_store);
618
619/**
620 * Dump global registers and either host or device registers (depending on the
621 * current mode of the core).
622 */
623static ssize_t regdump_show( struct device *_dev, struct device_attribute *attr, char *buf)
624{
625#ifdef DEBUG
626    dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev);
627    printk("%s otg_dev=0x%p\n", __FUNCTION__, otg_dev);
628
629        dwc_otg_dump_global_registers( otg_dev->core_if);
630        if (dwc_otg_is_host_mode(otg_dev->core_if)) {
631                dwc_otg_dump_host_registers( otg_dev->core_if);
632        } else {
633                dwc_otg_dump_dev_registers( otg_dev->core_if);
634        }
635#endif
636
637       return sprintf( buf, "Register Dump\n" );
638}
639
640DEVICE_ATTR(regdump, S_IRUGO|S_IWUSR, regdump_show, 0);
641
642/**
643 * Dump the current hcd state.
644 */
645static ssize_t hcddump_show( struct device *_dev, struct device_attribute *attr, char *buf)
646{
647#ifndef DWC_DEVICE_ONLY
648        dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev);
649    dwc_otg_hcd_dump_state(otg_dev->hcd);
650#endif
651       return sprintf( buf, "HCD Dump\n" );
652}
653
654DEVICE_ATTR(hcddump, S_IRUGO|S_IWUSR, hcddump_show, 0);
655
656/**
657 * Dump the average frame remaining at SOF. This can be used to
658 * determine average interrupt latency. Frame remaining is also shown for
659 * start transfer and two additional sample points.
660 */
661static ssize_t hcd_frrem_show( struct device *_dev, struct device_attribute *attr, char *buf)
662{
663#ifndef DWC_DEVICE_ONLY
664        dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev);
665    dwc_otg_hcd_dump_frrem(otg_dev->hcd);
666#endif
667       return sprintf( buf, "HCD Dump Frame Remaining\n" );
668}
669
670DEVICE_ATTR(hcd_frrem, S_IRUGO|S_IWUSR, hcd_frrem_show, 0);
671
672/**
673 * Displays the time required to read the GNPTXFSIZ register many times (the
674 * output shows the number of times the register is read).
675 */
676#define RW_REG_COUNT 10000000
677#define MSEC_PER_JIFFIE 1000/HZ
678static ssize_t rd_reg_test_show( struct device *_dev, struct device_attribute *attr, char *buf)
679{
680    int i;
681    int time;
682    int start_jiffies;
683        dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev);
684
685    printk("HZ %d, MSEC_PER_JIFFIE %d, loops_per_jiffy %lu\n",
686           HZ, MSEC_PER_JIFFIE, loops_per_jiffy);
687    start_jiffies = jiffies;
688    for (i = 0; i < RW_REG_COUNT; i++) {
689        dwc_read_reg32(&otg_dev->core_if->core_global_regs->gnptxfsiz);
690    }
691    time = jiffies - start_jiffies;
692       return sprintf( buf, "Time to read GNPTXFSIZ reg %d times: %d msecs (%d jiffies)\n",
693            RW_REG_COUNT, time * MSEC_PER_JIFFIE, time );
694}
695
696DEVICE_ATTR(rd_reg_test, S_IRUGO|S_IWUSR, rd_reg_test_show, 0);
697
698/**
699 * Displays the time required to write the GNPTXFSIZ register many times (the
700 * output shows the number of times the register is written).
701 */
702static ssize_t wr_reg_test_show( struct device *_dev, struct device_attribute *attr, char *buf)
703{
704    int i;
705    int time;
706    int start_jiffies;
707        dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev);
708    uint32_t reg_val;
709
710    printk("HZ %d, MSEC_PER_JIFFIE %d, loops_per_jiffy %lu\n",
711           HZ, MSEC_PER_JIFFIE, loops_per_jiffy);
712    reg_val = dwc_read_reg32(&otg_dev->core_if->core_global_regs->gnptxfsiz);
713    start_jiffies = jiffies;
714    for (i = 0; i < RW_REG_COUNT; i++) {
715        dwc_write_reg32(&otg_dev->core_if->core_global_regs->gnptxfsiz, reg_val);
716    }
717    time = jiffies - start_jiffies;
718       return sprintf( buf, "Time to write GNPTXFSIZ reg %d times: %d msecs (%d jiffies)\n",
719            RW_REG_COUNT, time * MSEC_PER_JIFFIE, time);
720}
721
722DEVICE_ATTR(wr_reg_test, S_IRUGO|S_IWUSR, wr_reg_test_show, 0);
723/**@}*/
724
725/**
726 * Create the device files
727 */
728void dwc_otg_attr_create (struct device *_dev)
729{
730    int retval;
731    
732    retval = device_create_file(_dev, &dev_attr_regoffset);
733    retval += device_create_file(_dev, &dev_attr_regvalue);
734    retval += device_create_file(_dev, &dev_attr_mode);
735    retval += device_create_file(_dev, &dev_attr_hnpcapable);
736    retval += device_create_file(_dev, &dev_attr_srpcapable);
737    retval += device_create_file(_dev, &dev_attr_hnp);
738    retval += device_create_file(_dev, &dev_attr_srp);
739    retval += device_create_file(_dev, &dev_attr_buspower);
740    retval += device_create_file(_dev, &dev_attr_bussuspend);
741    retval += device_create_file(_dev, &dev_attr_busconnected);
742    retval += device_create_file(_dev, &dev_attr_gotgctl);
743    retval += device_create_file(_dev, &dev_attr_gusbcfg);
744    retval += device_create_file(_dev, &dev_attr_grxfsiz);
745    retval += device_create_file(_dev, &dev_attr_gnptxfsiz);
746    retval += device_create_file(_dev, &dev_attr_gpvndctl);
747    retval += device_create_file(_dev, &dev_attr_ggpio);
748    retval += device_create_file(_dev, &dev_attr_guid);
749    retval += device_create_file(_dev, &dev_attr_gsnpsid);
750    retval += device_create_file(_dev, &dev_attr_devspeed);
751    retval += device_create_file(_dev, &dev_attr_enumspeed);
752    retval += device_create_file(_dev, &dev_attr_hptxfsiz);
753    retval += device_create_file(_dev, &dev_attr_hprt0);
754    retval += device_create_file(_dev, &dev_attr_remote_wakeup);
755    retval += device_create_file(_dev, &dev_attr_regdump);
756    retval += device_create_file(_dev, &dev_attr_hcddump);
757    retval += device_create_file(_dev, &dev_attr_hcd_frrem);
758    retval += device_create_file(_dev, &dev_attr_rd_reg_test);
759    retval += device_create_file(_dev, &dev_attr_wr_reg_test);
760
761    if(retval != 0)
762    {
763        DWC_PRINT("cannot create sysfs device files.\n");
764        // DWC_PRINT("killing own sysfs device files!\n");
765        dwc_otg_attr_remove(_dev);
766    }
767}
768
769/**
770 * Remove the device files
771 */
772void dwc_otg_attr_remove (struct device *_dev)
773{
774    device_remove_file(_dev, &dev_attr_regoffset);
775    device_remove_file(_dev, &dev_attr_regvalue);
776    device_remove_file(_dev, &dev_attr_mode);
777    device_remove_file(_dev, &dev_attr_hnpcapable);
778    device_remove_file(_dev, &dev_attr_srpcapable);
779    device_remove_file(_dev, &dev_attr_hnp);
780    device_remove_file(_dev, &dev_attr_srp);
781    device_remove_file(_dev, &dev_attr_buspower);
782    device_remove_file(_dev, &dev_attr_bussuspend);
783    device_remove_file(_dev, &dev_attr_busconnected);
784    device_remove_file(_dev, &dev_attr_gotgctl);
785    device_remove_file(_dev, &dev_attr_gusbcfg);
786    device_remove_file(_dev, &dev_attr_grxfsiz);
787    device_remove_file(_dev, &dev_attr_gnptxfsiz);
788    device_remove_file(_dev, &dev_attr_gpvndctl);
789    device_remove_file(_dev, &dev_attr_ggpio);
790    device_remove_file(_dev, &dev_attr_guid);
791    device_remove_file(_dev, &dev_attr_gsnpsid);
792    device_remove_file(_dev, &dev_attr_devspeed);
793    device_remove_file(_dev, &dev_attr_enumspeed);
794    device_remove_file(_dev, &dev_attr_hptxfsiz);
795    device_remove_file(_dev, &dev_attr_hprt0);
796    device_remove_file(_dev, &dev_attr_remote_wakeup);
797    device_remove_file(_dev, &dev_attr_regdump);
798    device_remove_file(_dev, &dev_attr_hcddump);
799    device_remove_file(_dev, &dev_attr_hcd_frrem);
800    device_remove_file(_dev, &dev_attr_rd_reg_test);
801    device_remove_file(_dev, &dev_attr_wr_reg_test);
802}
803

Archive Download this file



interactive