#undef ISP1362_DEBUG
#undef BUGGY_PXA2XX_UDC_USBTEST
#undef PTD_TRACE
#undef URB_TRACE
#undef VERBOSE
#undef REGISTERS
#undef CHIP_BUFFER_TEST
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/kernel.h>
#include <linux/delay.h>
#include <linux/ioport.h>
#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/errno.h>
#include <linux/list.h>
#include <linux/interrupt.h>
#include <linux/usb.h>
#include <linux/usb/isp1362.h>
#include <linux/usb/hcd.h>
#include <linux/platform_device.h>
#include <linux/pm.h>
#include <linux/io.h>
#include <linux/bitmap.h>
#include <linux/prefetch.h>
#include <linux/debugfs.h>
#include <linux/seq_file.h>
#include <asm/irq.h>
#include <asm/byteorder.h>
#include <asm/unaligned.h>
static int dbg_level;
#ifdef ISP1362_DEBUG
module_param(dbg_level, int, 0644);
#else
module_param(dbg_level, int, 0);
#endif
#include "../core/usb.h"
#include "isp1362.h"
#define DRIVER_VERSION …
#define DRIVER_DESC …
MODULE_DESCRIPTION(…);
MODULE_LICENSE(…) …;
static const char hcd_name[] = …;
static void isp1362_hc_stop(struct usb_hcd *hcd);
static int isp1362_hc_start(struct usb_hcd *hcd);
static inline void isp1362_enable_int(struct isp1362_hcd *isp1362_hcd, u16 mask)
{ … }
static inline struct isp1362_ep_queue *get_ptd_queue(struct isp1362_hcd *isp1362_hcd,
u16 offset)
{ … }
static inline int get_ptd_offset(struct isp1362_ep_queue *epq, u8 index)
{ … }
static inline u16 max_transfer_size(struct isp1362_ep_queue *epq, size_t size,
int mps)
{ … }
static int claim_ptd_buffers(struct isp1362_ep_queue *epq,
struct isp1362_ep *ep, u16 len)
{ … }
static inline void release_ptd_buffers(struct isp1362_ep_queue *epq, struct isp1362_ep *ep)
{ … }
static void prepare_ptd(struct isp1362_hcd *isp1362_hcd, struct urb *urb,
struct isp1362_ep *ep, struct isp1362_ep_queue *epq,
u16 fno)
{ … }
static void isp1362_write_ptd(struct isp1362_hcd *isp1362_hcd, struct isp1362_ep *ep,
struct isp1362_ep_queue *epq)
{ … }
static void isp1362_read_ptd(struct isp1362_hcd *isp1362_hcd, struct isp1362_ep *ep,
struct isp1362_ep_queue *epq)
{ … }
static void remove_ptd(struct isp1362_hcd *isp1362_hcd, struct isp1362_ep *ep)
{ … }
static void finish_request(struct isp1362_hcd *isp1362_hcd, struct isp1362_ep *ep,
struct urb *urb, int status)
__releases(isp1362_hcd->lock)
__acquires(isp1362_hcd->lock)
{ … }
static void postproc_ep(struct isp1362_hcd *isp1362_hcd, struct isp1362_ep *ep)
{ … }
static void finish_unlinks(struct isp1362_hcd *isp1362_hcd)
{ … }
static inline void enable_atl_transfers(struct isp1362_hcd *isp1362_hcd, int count)
{ … }
static inline void enable_intl_transfers(struct isp1362_hcd *isp1362_hcd)
{ … }
static inline void enable_istl_transfers(struct isp1362_hcd *isp1362_hcd, int flip)
{ … }
static int submit_req(struct isp1362_hcd *isp1362_hcd, struct urb *urb,
struct isp1362_ep *ep, struct isp1362_ep_queue *epq)
{ … }
static void start_atl_transfers(struct isp1362_hcd *isp1362_hcd)
{ … }
static void start_intl_transfers(struct isp1362_hcd *isp1362_hcd)
{ … }
static inline int next_ptd(struct isp1362_ep_queue *epq, struct isp1362_ep *ep)
{ … }
static void start_iso_transfers(struct isp1362_hcd *isp1362_hcd)
{ … }
static void finish_transfers(struct isp1362_hcd *isp1362_hcd, unsigned long done_map,
struct isp1362_ep_queue *epq)
{ … }
static void finish_iso_transfers(struct isp1362_hcd *isp1362_hcd, struct isp1362_ep_queue *epq)
{ … }
static irqreturn_t isp1362_irq(struct usb_hcd *hcd)
{ … }
#define MAX_PERIODIC_LOAD …
static int balance(struct isp1362_hcd *isp1362_hcd, u16 interval, u16 load)
{ … }
static int isp1362_urb_enqueue(struct usb_hcd *hcd,
struct urb *urb,
gfp_t mem_flags)
{ … }
static int isp1362_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
{ … }
static void isp1362_endpoint_disable(struct usb_hcd *hcd, struct usb_host_endpoint *hep)
{ … }
static int isp1362_get_frame(struct usb_hcd *hcd)
{ … }
static int isp1362_hub_status_data(struct usb_hcd *hcd, char *buf)
{ … }
static void isp1362_hub_descriptor(struct isp1362_hcd *isp1362_hcd,
struct usb_hub_descriptor *desc)
{ … }
static int isp1362_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
u16 wIndex, char *buf, u16 wLength)
{ … }
#ifdef CONFIG_PM
static int isp1362_bus_suspend(struct usb_hcd *hcd)
{ … }
static int isp1362_bus_resume(struct usb_hcd *hcd)
{ … }
#else
#define isp1362_bus_suspend …
#define isp1362_bus_resume …
#endif
static void dump_irq(struct seq_file *s, char *label, u16 mask)
{ … }
static void dump_int(struct seq_file *s, char *label, u32 mask)
{ … }
static void dump_ctrl(struct seq_file *s, char *label, u32 mask)
{ … }
static void dump_regs(struct seq_file *s, struct isp1362_hcd *isp1362_hcd)
{ … }
static int isp1362_show(struct seq_file *s, void *unused)
{ … }
DEFINE_SHOW_ATTRIBUTE(…);
static void create_debug_file(struct isp1362_hcd *isp1362_hcd)
{ … }
static void remove_debug_file(struct isp1362_hcd *isp1362_hcd)
{ … }
static void __isp1362_sw_reset(struct isp1362_hcd *isp1362_hcd)
{ … }
static void isp1362_sw_reset(struct isp1362_hcd *isp1362_hcd)
{ … }
static int isp1362_mem_config(struct usb_hcd *hcd)
{ … }
static int isp1362_hc_reset(struct usb_hcd *hcd)
{ … }
static void isp1362_hc_stop(struct usb_hcd *hcd)
{ … }
#ifdef CHIP_BUFFER_TEST
static int isp1362_chip_test(struct isp1362_hcd *isp1362_hcd)
{
int ret = 0;
u16 *ref;
unsigned long flags;
ref = kmalloc(2 * ISP1362_BUF_SIZE, GFP_KERNEL);
if (ref) {
int offset;
u16 *tst = &ref[ISP1362_BUF_SIZE / 2];
for (offset = 0; offset < ISP1362_BUF_SIZE / 2; offset++) {
ref[offset] = ~offset;
tst[offset] = offset;
}
for (offset = 0; offset < 4; offset++) {
int j;
for (j = 0; j < 8; j++) {
spin_lock_irqsave(&isp1362_hcd->lock, flags);
isp1362_write_buffer(isp1362_hcd, (u8 *)ref + offset, 0, j);
isp1362_read_buffer(isp1362_hcd, (u8 *)tst + offset, 0, j);
spin_unlock_irqrestore(&isp1362_hcd->lock, flags);
if (memcmp(ref, tst, j)) {
ret = -ENODEV;
pr_err("%s: memory check with %d byte offset %d failed\n",
__func__, j, offset);
dump_data((u8 *)ref + offset, j);
dump_data((u8 *)tst + offset, j);
}
}
}
spin_lock_irqsave(&isp1362_hcd->lock, flags);
isp1362_write_buffer(isp1362_hcd, ref, 0, ISP1362_BUF_SIZE);
isp1362_read_buffer(isp1362_hcd, tst, 0, ISP1362_BUF_SIZE);
spin_unlock_irqrestore(&isp1362_hcd->lock, flags);
if (memcmp(ref, tst, ISP1362_BUF_SIZE)) {
ret = -ENODEV;
pr_err("%s: memory check failed\n", __func__);
dump_data((u8 *)tst, ISP1362_BUF_SIZE / 2);
}
for (offset = 0; offset < 256; offset++) {
int test_size = 0;
yield();
memset(tst, 0, ISP1362_BUF_SIZE);
spin_lock_irqsave(&isp1362_hcd->lock, flags);
isp1362_write_buffer(isp1362_hcd, tst, 0, ISP1362_BUF_SIZE);
isp1362_read_buffer(isp1362_hcd, tst, 0, ISP1362_BUF_SIZE);
spin_unlock_irqrestore(&isp1362_hcd->lock, flags);
if (memcmp(tst, tst + (ISP1362_BUF_SIZE / (2 * sizeof(*tst))),
ISP1362_BUF_SIZE / 2)) {
pr_err("%s: Failed to clear buffer\n", __func__);
dump_data((u8 *)tst, ISP1362_BUF_SIZE);
break;
}
spin_lock_irqsave(&isp1362_hcd->lock, flags);
isp1362_write_buffer(isp1362_hcd, ref, offset * 2, PTD_HEADER_SIZE);
isp1362_write_buffer(isp1362_hcd, ref + PTD_HEADER_SIZE / sizeof(*ref),
offset * 2 + PTD_HEADER_SIZE, test_size);
isp1362_read_buffer(isp1362_hcd, tst, offset * 2,
PTD_HEADER_SIZE + test_size);
spin_unlock_irqrestore(&isp1362_hcd->lock, flags);
if (memcmp(ref, tst, PTD_HEADER_SIZE + test_size)) {
dump_data(((u8 *)ref) + offset, PTD_HEADER_SIZE + test_size);
dump_data((u8 *)tst, PTD_HEADER_SIZE + test_size);
spin_lock_irqsave(&isp1362_hcd->lock, flags);
isp1362_read_buffer(isp1362_hcd, tst, offset * 2,
PTD_HEADER_SIZE + test_size);
spin_unlock_irqrestore(&isp1362_hcd->lock, flags);
if (memcmp(ref, tst, PTD_HEADER_SIZE + test_size)) {
ret = -ENODEV;
pr_err("%s: memory check with offset %02x failed\n",
__func__, offset);
break;
}
pr_warn("%s: memory check with offset %02x ok after second read\n",
__func__, offset);
}
}
kfree(ref);
}
return ret;
}
#endif
static int isp1362_hc_start(struct usb_hcd *hcd)
{ … }
static const struct hc_driver isp1362_hc_driver = …;
static void isp1362_remove(struct platform_device *pdev)
{ … }
static int isp1362_probe(struct platform_device *pdev)
{ … }
#ifdef CONFIG_PM
static int isp1362_suspend(struct platform_device *pdev, pm_message_t state)
{ … }
static int isp1362_resume(struct platform_device *pdev)
{ … }
#else
#define isp1362_suspend …
#define isp1362_resume …
#endif
static struct platform_driver isp1362_driver = …;
module_platform_driver(…) …;