blob: d2af94bb6f911cf3932677215eace73a21bf499e [file] [log] [blame]
/* ==========================================================================
*
* Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
* "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
* otherwise expressly agreed to in writing between Synopsys and you.
*
* The Software IS NOT an item of Licensed Software or Licensed Product under
* any End User Software License Agreement or Agreement for Licensed Product
* with Synopsys or any supplement thereto. You are permitted to use and
* redistribute this Software in source and binary forms, with or without
* modification, provided that redistributions of source code must retain this
* notice. You may not view, use, disclose, copy or distribute this file or
* any information contained herein except pursuant to this license grant from
* Synopsys. If you do not agree with this notice, including the disclaimer
* below, then you are not authorized to use the Software.
*
* THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
* DAMAGE.
* ========================================================================== */
/** @file
*
* The diagnostic interface will provide access to the controller for
* bringing up the hardware and testing. The Linux driver attributes
* feature will be used to provide the Linux Diagnostic
* Interface. These attributes are accessed through sysfs.
*/
/** @page "Linux Module Attributes"
*
* The Linux module attributes feature is used to provide the Linux
* Diagnostic Interface. These attributes are accessed through sysfs.
* The diagnostic interface will provide access to the controller for
* bringing up the hardware and testing.
*
* Example usage:
* To get the current mode:
* cat /sys/devices/lm0/mode
*
* To power down the USB:
* echo 0 > /sys/devices/lm0/buspower
*/
#include <linux/kernel.h>
#include <linux/moduleparam.h>
#include <linux/init.h>
#include <linux/device.h>
#include <linux/errno.h>
#include <linux/types.h>
#include <linux/stat.h> /* permission constants */
#include <linux/io.h>
#include "dwc_otg_attr.h"
#include "dwc_otg_driver.h"
#include "dwc_otg_pcd.h"
#include "dwc_otg_hcd.h"
/*
* MACROs for defining sysfs attribute
*/
#define DWC_OTG_DEVICE_ATTR_BITFIELD_SHOW(_otg_attr_name_, \
_addr_, \
_mask_, \
_shift_, \
_string_) \
static ssize_t _otg_attr_name_##_show(struct device *dev, \
struct device_attribute *attr, \
char *buf) \
{ \
struct dwc_otg_device *otg_dev = dev_get_drvdata(dev);\
u32 val; \
val = dwc_read_reg32(_addr_); \
val = (val & (_mask_)) >> _shift_; \
return sprintf(buf, "%s = 0x%x\n", _string_, val); \
}
#define DWC_OTG_DEVICE_ATTR_BITFIELD_STORE(_otg_attr_name_, \
_addr_, \
_mask_, \
_shift_, \
_string_) \
static ssize_t _otg_attr_name_##_store(struct device *dev, \
struct device_attribute *attr, \
const char *buf, size_t count) \
{ \
struct dwc_otg_device *otg_dev = dev_get_drvdata(dev);\
u32 set = simple_strtoul(buf, NULL, 16); \
u32 clear = set; \
clear = ((~clear) << _shift_) & _mask_; \
set = (set << _shift_) & _mask_; \
dev_dbg(dev, "Storing Address=0x%p Set=0x%08x Clear=0x%08x\n", \
_addr_, set, clear); \
dwc_modify_reg32(_addr_, clear, set); \
return count; \
}
#define DWC_OTG_DEVICE_ATTR_BITFIELD_RW(_otg_attr_name_, \
_addr_, \
_mask_, \
_shift_, \
_string_) \
DWC_OTG_DEVICE_ATTR_BITFIELD_SHOW(_otg_attr_name_, \
_addr_, \
_mask_, \
_shift_, \
_string_) \
DWC_OTG_DEVICE_ATTR_BITFIELD_STORE(_otg_attr_name_, \
_addr_, \
_mask_, \
_shift_, \
_string_) \
DEVICE_ATTR(_otg_attr_name_, 0644, \
_otg_attr_name_##_show, _otg_attr_name_##_store);
#define DWC_OTG_DEVICE_ATTR_BITFIELD_RO(_otg_attr_name_, \
_addr_, \
_mask_, \
_shift_, \
_string_) \
DWC_OTG_DEVICE_ATTR_BITFIELD_SHOW(_otg_attr_name_, \
_addr_, \
_mask_, \
_shift_, \
_string_) \
DEVICE_ATTR(_otg_attr_name_, 0444, _otg_attr_name_##_show, NULL);
/*
* MACROs for defining sysfs attribute for 32-bit registers
*/
#define DWC_OTG_DEVICE_ATTR_REG_SHOW(_otg_attr_name_, _addr_, _string_) \
static ssize_t _otg_attr_name_##_show(struct device *dev, \
struct device_attribute *attr, char *buf) \
{ \
struct dwc_otg_device *otg_dev = dev_get_drvdata(dev);\
u32 val; \
val = dwc_read_reg32(_addr_); \
return sprintf(buf, "%s = 0x%08x\n", _string_, val); \
}
#define DWC_OTG_DEVICE_ATTR_REG_STORE(_otg_attr_name_, _addr_, _string_) \
static ssize_t _otg_attr_name_##_store(struct device *dev, \
struct device_attribute *attr, \
const char *buf, size_t count) \
{ \
struct dwc_otg_device *otg_dev = dev_get_drvdata(dev);\
u32 val = simple_strtoul(buf, NULL, 16); \
dev_dbg(dev, "Storing Address=0x%p Val=0x%08x\n", \
_addr_, val); \
dwc_write_reg32(_addr_, val); \
return count; \
}
#define DWC_OTG_DEVICE_ATTR_REG32_RW(_otg_attr_name_, _addr_, _string_) \
DWC_OTG_DEVICE_ATTR_REG_SHOW(_otg_attr_name_, _addr_, _string_) \
DWC_OTG_DEVICE_ATTR_REG_STORE(_otg_attr_name_, _addr_, _string_) \
DEVICE_ATTR(_otg_attr_name_, 0644, _otg_attr_name_##_show, \
_otg_attr_name_##_store);
#define DWC_OTG_DEVICE_ATTR_REG32_RO(_otg_attr_name_, _addr_, _string_) \
DWC_OTG_DEVICE_ATTR_REG_SHOW(_otg_attr_name_, _addr_, _string_) \
DEVICE_ATTR(_otg_attr_name_, 0444, _otg_attr_name_##_show, NULL);
/** @name Functions for Show/Store of Attributes */
/**@{*/
/**
* Show the register offset of the Register Access.
*/
static ssize_t
regoffset_show(struct device *dev, struct device_attribute *attr, char *buf)
{
struct dwc_otg_device *otg_dev = dev_get_drvdata(dev);
return snprintf(buf, sizeof("0xFFFFFFFF\n")+1, "0x%08x\n",
otg_dev->reg_offset);
}
/**
* Set the register offset for the next Register Access Read/Write
*/
#define SZ_256K 0x00040000
static ssize_t regoffset_store(struct device *dev,
struct device_attribute *attr, const char *buf,
size_t count)
{
struct dwc_otg_device *otg_dev = dev_get_drvdata(dev);
u32 offset = simple_strtoul(buf, NULL, 16);
if (offset < SZ_256K)
otg_dev->reg_offset = offset;
else
dev_err(dev, "invalid offset\n");
return count;
}
DEVICE_ATTR(regoffset, S_IRUGO|S_IWUSR, regoffset_show, regoffset_store);
/**
* Show the value of the register at the offset in the reg_offset
* attribute.
*/
static ssize_t
regvalue_show(struct device *dev, struct device_attribute *attr, char *buf)
{
struct dwc_otg_device *otg_dev = dev_get_drvdata(dev);
u32 val;
u32 __iomem *addr;
if (otg_dev->reg_offset != 0xFFFFFFFF && otg_dev->base) {
/* Calculate the address */
addr = (u32 __iomem *)(otg_dev->reg_offset +
(u8 __iomem *)otg_dev->base);
val = dwc_read_reg32(addr);
return snprintf(buf, sizeof("Reg@0xFFFFFFFF = 0xFFFFFFFF\n")+1,
"Reg@0x%06x = 0x%08x\n",
otg_dev->reg_offset, val);
} else {
dev_err(dev, "Invalid offset (0x%0x)\n",
otg_dev->reg_offset);
return sprintf(buf, "invalid offset\n");
}
}
/**
* Store the value in the register at the offset in the reg_offset
* attribute.
*
*/
static ssize_t
regvalue_store(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
struct dwc_otg_device *otg_dev = dev_get_drvdata(dev);
u32 __iomem *addr;
u32 val = simple_strtoul(buf, NULL, 16);
if (otg_dev->reg_offset != 0xFFFFFFFF && otg_dev->base) {
/* Calculate the address */
addr = (u32 __iomem *)(otg_dev->reg_offset +
(u8 __iomem *)otg_dev->base);
dwc_write_reg32(addr, val);
} else
dev_err(dev, "Invalid Register Offset (0x%08x)\n",
otg_dev->reg_offset);
return count;
}
DEVICE_ATTR(regvalue, S_IRUGO|S_IWUSR, regvalue_show, regvalue_store);
/*
* Attributes
*/
DWC_OTG_DEVICE_ATTR_BITFIELD_RO(mode,
&(otg_dev->core_if->core_global_regs->gotgctl),
(1<<20), 20, "Mode");
DWC_OTG_DEVICE_ATTR_BITFIELD_RW(hnpcapable,
&(otg_dev->core_if->core_global_regs->gusbcfg),
(1<<9), 9, "Mode");
DWC_OTG_DEVICE_ATTR_BITFIELD_RW(srpcapable,
&(otg_dev->core_if->core_global_regs->gusbcfg),
(1<<8), 8, "Mode");
DWC_OTG_DEVICE_ATTR_BITFIELD_RO(busconnected,
otg_dev->core_if->host_if->hprt0,
0x01, 0, "Bus Connected");
DWC_OTG_DEVICE_ATTR_REG32_RW(gotgctl,
&(otg_dev->core_if->core_global_regs->gotgctl),
"GOTGCTL");
DWC_OTG_DEVICE_ATTR_REG32_RW(gusbcfg,
&(otg_dev->core_if->core_global_regs->gusbcfg),
"GUSBCFG");
DWC_OTG_DEVICE_ATTR_REG32_RW(grxfsiz,
&(otg_dev->core_if->core_global_regs->grxfsiz),
"GRXFSIZ");
DWC_OTG_DEVICE_ATTR_REG32_RW(gnptxfsiz,
&(otg_dev->core_if->core_global_regs->gnptxfsiz),
"GNPTXFSIZ");
DWC_OTG_DEVICE_ATTR_REG32_RW(gpvndctl,
&(otg_dev->core_if->core_global_regs->gpvndctl),
"GPVNDCTL");
DWC_OTG_DEVICE_ATTR_REG32_RW(ggpio,
&(otg_dev->core_if->core_global_regs->ggpio),
"GGPIO");
DWC_OTG_DEVICE_ATTR_REG32_RW(guid,
&(otg_dev->core_if->core_global_regs->guid),
"GUID");
DWC_OTG_DEVICE_ATTR_REG32_RO(gsnpsid,
&(otg_dev->core_if->core_global_regs->gsnpsid),
"GSNPSID");
DWC_OTG_DEVICE_ATTR_BITFIELD_RW(devspeed,
&(otg_dev->core_if->dev_if->dev_global_regs->dcfg),
0x3, 0, "Device Speed");
DWC_OTG_DEVICE_ATTR_BITFIELD_RO(enumspeed,
&(otg_dev->core_if->dev_if->dev_global_regs->dsts),
0x6, 1, "Device Enumeration Speed");
DWC_OTG_DEVICE_ATTR_REG32_RO(hptxfsiz,
&(otg_dev->core_if->core_global_regs->hptxfsiz),
"HPTXFSIZ");
DWC_OTG_DEVICE_ATTR_REG32_RW(hprt0,
otg_dev->core_if->host_if->hprt0,
"HPRT0");
/**
* @todo Add code to initiate the HNP.
*/
/**
* Show the HNP status bit
*/
static ssize_t
hnp_show(struct device *dev, struct device_attribute *attr, char *buf)
{
struct dwc_otg_device *otg_dev = dev_get_drvdata(dev);
union gotgctl_data val;
val.d32 =
dwc_read_reg32(&(otg_dev->core_if->core_global_regs->gotgctl));
return sprintf(buf, "HstNegScs = 0x%x\n", val.b.hstnegscs);
}
/**
* Set the HNP Request bit
*/
static ssize_t
hnp_store(struct device *dev, struct device_attribute *attr, const char *buf,
size_t count)
{
struct dwc_otg_device *otg_dev = dev_get_drvdata(dev);
u32 in = simple_strtoul(buf, NULL, 16);
u32 __iomem *addr = &(otg_dev->core_if->core_global_regs->gotgctl);
union gotgctl_data mem;
mem.d32 = dwc_read_reg32(addr);
mem.b.hnpreq = in;
dev_dbg(dev, "Storing Address=0x%p Data=0x%08x\n",
addr, mem.d32);
dwc_write_reg32(addr, mem.d32);
return count;
}
DEVICE_ATTR(hnp, 0644, hnp_show, hnp_store);
/**
* @todo Add code to initiate the SRP.
*/
/**
* Show the SRP status bit
*/
static ssize_t
srp_show(struct device *dev, struct device_attribute *attr, char *buf)
{
#ifndef DWC_HOST_ONLY
struct dwc_otg_device *otg_dev = dev_get_drvdata(dev);
union gotgctl_data val;
val.d32 =
dwc_read_reg32(&(otg_dev->core_if->core_global_regs->gotgctl));
return sprintf(buf, "SesReqScs = 0x%x\n", val.b.sesreqscs);
#else
return sprintf(buf, "Host Only Mode!\n");
#endif
}
/**
* Set the SRP Request bit
*/
static ssize_t
srp_store(struct device *dev, struct device_attribute *attr, const char *buf,
size_t count)
{
#ifndef DWC_HOST_ONLY
struct dwc_otg_device *otg_dev = dev_get_drvdata(dev);
dwc_otg_pcd_initiate_srp(otg_dev->pcd);
#endif
return count;
}
DEVICE_ATTR(srp, 0644, srp_show, srp_store);
/**
* @todo Need to do more for power on/off?
*/
/**
* Show the Bus Power status
*/
static ssize_t
buspower_show(struct device *dev, struct device_attribute *attr, char *buf)
{
struct dwc_otg_device *otg_dev = dev_get_drvdata(dev);
union hprt0_data val;
val.d32 = dwc_read_reg32(otg_dev->core_if->host_if->hprt0);
return sprintf(buf, "Bus Power = 0x%x\n", val.b.prtpwr);
}
/**
* Set the Bus Power status
*/
static ssize_t
buspower_store(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
struct dwc_otg_device *otg_dev = dev_get_drvdata(dev);
u32 on = simple_strtoul(buf, NULL, 16);
u32 __iomem *addr = otg_dev->core_if->host_if->hprt0;
union hprt0_data mem;
mem.d32 = dwc_read_reg32(addr);
mem.b.prtpwr = on;
dwc_write_reg32(addr, mem.d32);
return count;
}
DEVICE_ATTR(buspower, 0644, buspower_show, buspower_store);
/**
* @todo Need to do more for suspend?
*/
/**
* Show the Bus Suspend status
*/
static ssize_t
bussuspend_show(struct device *dev, struct device_attribute *attr, char *buf)
{
struct dwc_otg_device *otg_dev = dev_get_drvdata(dev);
union hprt0_data val;
val.d32 = dwc_read_reg32(otg_dev->core_if->host_if->hprt0);
return sprintf(buf, "Bus Suspend = 0x%x\n", val.b.prtsusp);
}
/**
* Set the Bus Suspend status
*/
static ssize_t
bussuspend_store(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
struct dwc_otg_device *otg_dev = dev_get_drvdata(dev);
u32 in = simple_strtoul(buf, NULL, 16);
u32 __iomem *addr = otg_dev->core_if->host_if->hprt0;
union hprt0_data mem;
mem.d32 = dwc_read_reg32(addr);
mem.b.prtsusp = in;
dev_dbg(dev, "Storing Address=0x%p Data=0x%08x\n",
addr, mem.d32);
dwc_write_reg32(addr, mem.d32);
return count;
}
DEVICE_ATTR(bussuspend, 0644, bussuspend_show, bussuspend_store);
/**
* Show the status of Remote Wakeup.
*/
static ssize_t
remote_wakeup_show(struct device *dev, struct device_attribute *attr, char *buf)
{
#ifndef DWC_HOST_ONLY
struct dwc_otg_device *otg_dev = dev_get_drvdata(dev);
union dctl_data val;
val.d32 =
dwc_read_reg32(&otg_dev->core_if->dev_if->dev_global_regs->dctl);
return sprintf(buf, "Remote Wakeup = %d Enabled = %d\n",
val.b.rmtwkupsig, otg_dev->pcd->remote_wakeup_enable);
#else
return sprintf(buf, "Host Only Mode!\n");
#endif
}
/**
* Initiate a remote wakeup of the host. The Device control register
* Remote Wakeup Signal bit is written if the PCD Remote wakeup enable
* flag is set.
*
*/
static ssize_t
remote_wakeup_store(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
#ifndef DWC_HOST_ONLY
u32 val = simple_strtoul(buf, NULL, 16);
struct dwc_otg_device *otg_dev = dev_get_drvdata(dev);
if (val&1)
dwc_otg_pcd_remote_wakeup(otg_dev->pcd, 1);
else
dwc_otg_pcd_remote_wakeup(otg_dev->pcd, 0);
#endif
return count;
}
static DEVICE_ATTR(remote_wakeup, S_IRUGO|S_IWUSR, remote_wakeup_show,
remote_wakeup_store);
/**
* Dump global registers and either host or device registers (depending on the
* current mode of the core).
*/
static ssize_t
regdump_show(struct device *dev, struct device_attribute *attr, char *buf)
{
struct dwc_otg_device *otg_dev = dev_get_drvdata(dev);
printk(KERN_DEBUG"%s otg_dev=0x%p\n", __func__, otg_dev);
dwc_otg_dump_global_registers(otg_dev->core_if);
if (dwc_otg_is_host_mode(otg_dev->core_if))
dwc_otg_dump_host_registers(otg_dev->core_if);
else
dwc_otg_dump_dev_registers(otg_dev->core_if);
return sprintf(buf, "Register Dump\n");
}
static DEVICE_ATTR(regdump, S_IRUGO, regdump_show, NULL);
/**
* Dump the current hcd state.
*/
static ssize_t
hcddump_show(struct device *dev, struct device_attribute *attr, char *buf)
{
#ifndef DWC_DEVICE_ONLY
struct dwc_otg_device *otg_dev = dev_get_drvdata(dev);
dwc_otg_hcd_dump_state(otg_dev->hcd);
#endif
return sprintf(buf, "HCD Dump\n");
}
static DEVICE_ATTR(hcddump, S_IRUGO, hcddump_show, NULL);
/**
* Dump the average frame remaining at SOF. This can be used to
* determine average interrupt latency. Frame remaining is also shown for
* start transfer and two additional sample points.
*/
static ssize_t
hcd_frrem_show(struct device *dev, struct device_attribute *attr, char *buf)
{
#ifndef DWC_DEVICE_ONLY
/*
* struct dwc_otg_device *otg_dev = dev_get_drvdata(dev);
* TODO: expose this method from hcd:
* dwc_otg_hcd_dump_frrem(otg_dev->hcd);
*/
#endif
return sprintf(buf, "HCD Dump Frame Remaining\n");
}
static DEVICE_ATTR(hcd_frrem, S_IRUGO, hcd_frrem_show, NULL);
/**
* Displays the time required to read the GNPTXFSIZ register many times (the
* output shows the number of times the register is read).
*/
#define RW_REG_COUNT 10000000
#define MSEC_PER_JIFFIE (1000/HZ)
static ssize_t
rd_reg_test_show(struct device *dev, struct device_attribute *attr, char *buf)
{
int i;
int time;
int start_jiffies;
struct dwc_otg_device *otg_dev = dev_get_drvdata(dev);
printk(KERN_DEBUG"HZ %d, MSEC_PER_JIFFIE %d, loops_per_jiffy %lu\n",
HZ, MSEC_PER_JIFFIE, loops_per_jiffy);
start_jiffies = jiffies;
for (i = 0; i < RW_REG_COUNT; i++)
dwc_read_reg32(&otg_dev->core_if->core_global_regs->gnptxfsiz);
time = jiffies - start_jiffies;
return sprintf(buf, "Time to read GNPTXFSIZ reg %d times:"
" %d msecs (%d jiffies)\n",
RW_REG_COUNT, time * MSEC_PER_JIFFIE, time);
}
static DEVICE_ATTR(rd_reg_test, S_IRUGO, rd_reg_test_show, NULL);
/**
* Displays the time required to write the GNPTXFSIZ register many times (the
* output shows the number of times the register is written).
*/
static ssize_t
wr_reg_test_show(struct device *dev, struct device_attribute *attr, char *buf)
{
int i;
int time;
int start_jiffies;
struct dwc_otg_device *otg_dev = dev_get_drvdata(dev);
u32 reg_val;
printk(KERN_DEBUG"HZ %d, MSEC_PER_JIFFIE %d, loops_per_jiffy %lu\n",
HZ, MSEC_PER_JIFFIE, loops_per_jiffy);
reg_val =
dwc_read_reg32(&otg_dev->core_if->core_global_regs->gnptxfsiz);
start_jiffies = jiffies;
for (i = 0; i < RW_REG_COUNT; i++)
dwc_write_reg32(&otg_dev->core_if->core_global_regs->gnptxfsiz,
reg_val);
time = jiffies - start_jiffies;
return sprintf(buf, "Time to write GNPTXFSIZ reg %d times:"
" %d msecs (%d jiffies)\n",
RW_REG_COUNT, time * MSEC_PER_JIFFIE, time);
}
static DEVICE_ATTR(wr_reg_test, S_IRUGO, wr_reg_test_show, NULL);
/**
* Create the device files
*/
void dwc_otg_attr_create(struct device *dev)
{
int ret_val = 0;
ret_val = device_create_file(dev, &dev_attr_regoffset);
ret_val = device_create_file(dev, &dev_attr_regvalue);
ret_val = device_create_file(dev, &dev_attr_mode);
ret_val = device_create_file(dev, &dev_attr_hnpcapable);
ret_val = device_create_file(dev, &dev_attr_srpcapable);
ret_val = device_create_file(dev, &dev_attr_hnp);
ret_val = device_create_file(dev, &dev_attr_srp);
ret_val = device_create_file(dev, &dev_attr_buspower);
ret_val = device_create_file(dev, &dev_attr_bussuspend);
ret_val = device_create_file(dev, &dev_attr_busconnected);
ret_val = device_create_file(dev, &dev_attr_gotgctl);
ret_val = device_create_file(dev, &dev_attr_gusbcfg);
ret_val = device_create_file(dev, &dev_attr_grxfsiz);
ret_val = device_create_file(dev, &dev_attr_gnptxfsiz);
ret_val = device_create_file(dev, &dev_attr_gpvndctl);
ret_val = device_create_file(dev, &dev_attr_ggpio);
ret_val = device_create_file(dev, &dev_attr_guid);
ret_val = device_create_file(dev, &dev_attr_gsnpsid);
ret_val = device_create_file(dev, &dev_attr_devspeed);
ret_val = device_create_file(dev, &dev_attr_enumspeed);
ret_val = device_create_file(dev, &dev_attr_hptxfsiz);
ret_val = device_create_file(dev, &dev_attr_hprt0);
ret_val = device_create_file(dev, &dev_attr_remote_wakeup);
ret_val = device_create_file(dev, &dev_attr_regdump);
ret_val = device_create_file(dev, &dev_attr_hcddump);
ret_val = device_create_file(dev, &dev_attr_hcd_frrem);
ret_val = device_create_file(dev, &dev_attr_rd_reg_test);
ret_val = device_create_file(dev, &dev_attr_wr_reg_test);
}
/**
* Remove the device files
*/
void dwc_otg_attr_remove(struct device *dev)
{
device_remove_file(dev, &dev_attr_regoffset);
device_remove_file(dev, &dev_attr_regvalue);
device_remove_file(dev, &dev_attr_mode);
device_remove_file(dev, &dev_attr_hnpcapable);
device_remove_file(dev, &dev_attr_srpcapable);
device_remove_file(dev, &dev_attr_hnp);
device_remove_file(dev, &dev_attr_srp);
device_remove_file(dev, &dev_attr_buspower);
device_remove_file(dev, &dev_attr_bussuspend);
device_remove_file(dev, &dev_attr_busconnected);
device_remove_file(dev, &dev_attr_gotgctl);
device_remove_file(dev, &dev_attr_gusbcfg);
device_remove_file(dev, &dev_attr_grxfsiz);
device_remove_file(dev, &dev_attr_gnptxfsiz);
device_remove_file(dev, &dev_attr_gpvndctl);
device_remove_file(dev, &dev_attr_ggpio);
device_remove_file(dev, &dev_attr_guid);
device_remove_file(dev, &dev_attr_gsnpsid);
device_remove_file(dev, &dev_attr_devspeed);
device_remove_file(dev, &dev_attr_enumspeed);
device_remove_file(dev, &dev_attr_hptxfsiz);
device_remove_file(dev, &dev_attr_hprt0);
device_remove_file(dev, &dev_attr_remote_wakeup);
device_remove_file(dev, &dev_attr_regdump);
device_remove_file(dev, &dev_attr_hcddump);
device_remove_file(dev, &dev_attr_hcd_frrem);
device_remove_file(dev, &dev_attr_rd_reg_test);
device_remove_file(dev, &dev_attr_wr_reg_test);
}