1
0
mirror of git://projects.qi-hardware.com/openwrt-xburst.git synced 2024-11-24 01:43:08 +02:00

[adm5120] minor usb driver cleanup

git-svn-id: svn://svn.openwrt.org/openwrt/trunk@8385 3c298f89-4303-0410-b956-a3cf2f4a3e73
This commit is contained in:
juhosg 2007-08-10 08:56:41 +00:00
parent 80886edaa0
commit 8f4b522143

View File

@ -89,7 +89,6 @@ MODULE_AUTHOR("Jeroen Vreeken (pe1rxq@amsat.org)");
#define ADMHCD_REG_PORTSTATUS1 0x7c
#define ADMHCD_REG_HOSTHEAD 0x80
#define ADMHCD_NUMPORTS 2
struct admhcd_ed {
@ -136,9 +135,9 @@ struct admhcd_td {
static int admhcd_td_err[16] = {
0, /* No */
-EREMOTEIO, /* CRC */
-EREMOTEIO, /* CRC */
-EREMOTEIO, /* bit stuff */
-EREMOTEIO, /* data toggle */
-EREMOTEIO, /* data toggle */
-EPIPE, /* stall */
-ETIMEDOUT, /* timeout */
-EPROTO, /* pid err */
@ -203,14 +202,14 @@ static void admhcd_lock(struct admhcd *ahcd)
{
spin_lock_irqsave(&ahcd->lock, ahcd->flags);
ahcd->dma_en = admhcd_reg_get(ahcd, ADMHCD_REG_HOSTCONTROL) &
ADMHCD_DMA_EN;
ADMHCD_DMA_EN;
admhcd_reg_set(ahcd, ADMHCD_REG_HOSTCONTROL, ADMHCD_STATE_OP);
}
static void admhcd_unlock(struct admhcd *ahcd)
{
admhcd_reg_set(ahcd, ADMHCD_REG_HOSTCONTROL,
ADMHCD_STATE_OP | ahcd->dma_en);
ADMHCD_STATE_OP | ahcd->dma_en);
spin_unlock_irqrestore(&ahcd->lock, ahcd->flags);
}
@ -218,12 +217,12 @@ static struct admhcd_td *admhcd_td_alloc(struct admhcd_ed *ed, struct urb *urb)
{
struct admhcd_td *tdn, *td;
tdn = kmalloc(sizeof(struct admhcd_td), GFP_ATOMIC);
tdn = kzalloc(sizeof(*tdn), GFP_ATOMIC);
if (!tdn)
return NULL;
tdn->real = tdn;
tdn = (struct admhcd_td *)KSEG1ADDR(tdn);
memset(tdn, 0, sizeof(struct admhcd_td));
if (ed->cur == NULL) {
ed->cur = tdn;
ed->head = tdn;
@ -265,7 +264,7 @@ static void admhcd_td_free(struct admhcd_ed *ed, struct urb *urb)
in the DMA chain
*/
static struct admhcd_ed *admhcd_get_ed(struct admhcd *ahcd,
struct usb_host_endpoint *ep, struct urb *urb)
struct usb_host_endpoint *ep, struct urb *urb)
{
struct admhcd_ed *hosthead;
struct admhcd_ed *found = NULL, *ed = NULL;
@ -284,10 +283,9 @@ static struct admhcd_ed *admhcd_get_ed(struct admhcd *ahcd,
}
}
if (!found) {
found = kmalloc(sizeof(struct admhcd_ed), GFP_ATOMIC);
found = kzalloc(sizeof(*found), GFP_ATOMIC);
if (!found)
goto out;
memset(found, 0, sizeof(struct admhcd_ed));
found->real = found;
found->ep = ep;
found = (struct admhcd_ed *)KSEG1ADDR(found);
@ -313,7 +311,7 @@ out:
}
static struct admhcd_td *admhcd_td_fill(u32 control, struct admhcd_td *td,
dma_addr_t data, int len)
dma_addr_t data, int len)
{
td->buffer = data;
td->buflen = len;
@ -342,7 +340,7 @@ static void admhcd_ed_start(struct admhcd *ahcd, struct admhcd_ed *ed)
ahcd->dma_en |= ADMHCD_DMA_EN;
}
static irqreturn_t adm5120hcd_irq(struct usb_hcd *hcd)
static irqreturn_t admhcd_irq(struct usb_hcd *hcd)
{
struct admhcd *ahcd = hcd_to_admhcd(hcd);
u32 intstatus;
@ -350,12 +348,14 @@ static irqreturn_t adm5120hcd_irq(struct usb_hcd *hcd)
intstatus = admhcd_reg_get(ahcd, ADMHCD_REG_INTSTATUS);
if (intstatus & ADMHCD_INT_FATAL) {
admhcd_reg_set(ahcd, ADMHCD_REG_INTSTATUS, ADMHCD_INT_FATAL);
//
/* FIXME: handle fatal interrupts */
}
if (intstatus & ADMHCD_INT_SW) {
admhcd_reg_set(ahcd, ADMHCD_REG_INTSTATUS, ADMHCD_INT_SW);
//
/* FIXME: handle software interrupts */
}
if (intstatus & ADMHCD_INT_TD) {
struct admhcd_ed *ed, *head;
@ -389,7 +389,7 @@ static irqreturn_t adm5120hcd_irq(struct usb_hcd *hcd)
}
static int admhcd_urb_enqueue(struct usb_hcd *hcd, struct usb_host_endpoint *ep,
struct urb *urb, gfp_t mem_flags)
struct urb *urb, gfp_t mem_flags)
{
struct admhcd *ahcd = hcd_to_admhcd(hcd);
struct admhcd_ed *ed;
@ -404,26 +404,26 @@ static int admhcd_urb_enqueue(struct usb_hcd *hcd, struct usb_host_endpoint *ep,
return -ENOMEM;
switch(usb_pipetype(pipe)) {
case PIPE_CONTROL:
size = 2;
case PIPE_INTERRUPT:
case PIPE_BULK:
default:
size += urb->transfer_buffer_length / 4096;
if (urb->transfer_buffer_length % 4096)
size++;
if (size == 0)
size++;
else if (urb->transfer_flags & URB_ZERO_PACKET &&
!(urb->transfer_buffer_length %
usb_maxpacket(urb->dev, pipe, usb_pipeout(pipe)))) {
size++;
zero = 1;
}
break;
case PIPE_ISOCHRONOUS:
size = urb->number_of_packets;
break;
case PIPE_CONTROL:
size = 2;
case PIPE_INTERRUPT:
case PIPE_BULK:
default:
size += urb->transfer_buffer_length / 4096;
if (urb->transfer_buffer_length % 4096)
size++;
if (size == 0)
size++;
else if (urb->transfer_flags & URB_ZERO_PACKET &&
!(urb->transfer_buffer_length %
usb_maxpacket(urb->dev, pipe, usb_pipeout(pipe)))) {
size++;
zero = 1;
}
break;
case PIPE_ISOCHRONOUS:
size = urb->number_of_packets;
break;
}
admhcd_lock(ahcd);
@ -451,52 +451,52 @@ static int admhcd_urb_enqueue(struct usb_hcd *hcd, struct usb_host_endpoint *ep,
}
switch(usb_pipetype(pipe)) {
case PIPE_CONTROL:
td = admhcd_td_fill(ADMHCD_TD_SETUP | ADMHCD_TD_DATA0,
td, (dma_addr_t)urb->setup_packet, 8);
while (data_len > 0) {
td = admhcd_td_fill(ADMHCD_TD_DATA1
| ADMHCD_TD_R |
(usb_pipeout(pipe) ?
ADMHCD_TD_OUT : ADMHCD_TD_IN), td,
data, data_len % 4097);
data_len -= 4096;
}
admhcd_td_fill(ADMHCD_TD_DATA1 | (usb_pipeout(pipe) ?
ADMHCD_TD_IN : ADMHCD_TD_OUT), td,
data, 0);
break;
case PIPE_INTERRUPT:
case PIPE_BULK:
//info ok for interrupt?
i = 0;
while(data_len > 4096) {
td = admhcd_td_fill((usb_pipeout(pipe) ?
ADMHCD_TD_OUT :
ADMHCD_TD_IN | ADMHCD_TD_R) |
(i ? ADMHCD_TD_TOGGLE : toggle), td,
data, 4096);
data += 4096;
data_len -= 4096;
i++;
}
case PIPE_CONTROL:
td = admhcd_td_fill(ADMHCD_TD_SETUP | ADMHCD_TD_DATA0,
td, (dma_addr_t)urb->setup_packet, 8);
while (data_len > 0) {
td = admhcd_td_fill(ADMHCD_TD_DATA1
| ADMHCD_TD_R |
(usb_pipeout(pipe) ?
ADMHCD_TD_OUT : ADMHCD_TD_IN), td,
data, data_len % 4097);
data_len -= 4096;
}
admhcd_td_fill(ADMHCD_TD_DATA1 | (usb_pipeout(pipe) ?
ADMHCD_TD_IN : ADMHCD_TD_OUT), td,
data, 0);
break;
case PIPE_INTERRUPT:
case PIPE_BULK:
//info ok for interrupt?
i = 0;
while(data_len > 4096) {
td = admhcd_td_fill((usb_pipeout(pipe) ?
ADMHCD_TD_OUT : ADMHCD_TD_IN) |
(i ? ADMHCD_TD_TOGGLE : toggle), td, data, data_len);
ADMHCD_TD_OUT :
ADMHCD_TD_IN | ADMHCD_TD_R) |
(i ? ADMHCD_TD_TOGGLE : toggle), td,
data, 4096);
data += 4096;
data_len -= 4096;
i++;
if (zero)
admhcd_td_fill((usb_pipeout(pipe) ?
ADMHCD_TD_OUT : ADMHCD_TD_IN) |
(i ? ADMHCD_TD_TOGGLE : toggle), td, 0, 0);
break;
case PIPE_ISOCHRONOUS:
for (i = 0; i < urb->number_of_packets; i++) {
td = admhcd_td_fill(ADMHCD_TD_ISO |
((urb->start_frame + i) & 0xffff), td,
data + urb->iso_frame_desc[i].offset,
urb->iso_frame_desc[i].length);
}
break;
}
td = admhcd_td_fill((usb_pipeout(pipe) ?
ADMHCD_TD_OUT : ADMHCD_TD_IN) |
(i ? ADMHCD_TD_TOGGLE : toggle), td, data, data_len);
i++;
if (zero)
admhcd_td_fill((usb_pipeout(pipe) ?
ADMHCD_TD_OUT : ADMHCD_TD_IN) |
(i ? ADMHCD_TD_TOGGLE : toggle), td, 0, 0);
break;
case PIPE_ISOCHRONOUS:
for (i = 0; i < urb->number_of_packets; i++) {
td = admhcd_td_fill(ADMHCD_TD_ISO |
((urb->start_frame + i) & 0xffff), td,
data + urb->iso_frame_desc[i].offset,
urb->iso_frame_desc[i].length);
}
break;
}
urb->hcpriv = ed;
admhcd_ed_start(ahcd, ed);
@ -551,6 +551,7 @@ static void admhcd_endpoint_disable(struct usb_hcd *hcd, struct usb_host_endpoin
}
for (edt = head; edt->next != ed; edt = edt->next);
edt->next = ed->next;
out_free:
kfree(ed->real);
out:
@ -591,7 +592,7 @@ static __u8 root_hub_hub_des[] = {
};
static int admhcd_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
u16 wIndex, char *buf, u16 wLength)
u16 wIndex, char *buf, u16 wLength)
{
struct admhcd *ahcd = hcd_to_admhcd(hcd);
int retval = 0, len;
@ -707,45 +708,45 @@ static int admhcd_start(struct usb_hcd *hcd)
spin_lock_irqsave(&ahcd->lock, flags);
/* Initialise the HCD registers */
admhcd_reg_set(ahcd, ADMHCD_REG_INTENABLE, 0);
mdelay(10);
/* Initialise the HCD registers */
admhcd_reg_set(ahcd, ADMHCD_REG_INTENABLE, 0);
mdelay(10);
admhcd_reg_set(ahcd, ADMHCD_REG_CONTROL, ADMHCD_SW_RESET);
admhcd_reg_set(ahcd, ADMHCD_REG_CONTROL, ADMHCD_SW_RESET);
while (admhcd_reg_get(ahcd, ADMHCD_REG_CONTROL) & ADMHCD_SW_RESET) {
while (admhcd_reg_get(ahcd, ADMHCD_REG_CONTROL) & ADMHCD_SW_RESET) {
printk(KERN_WARNING PFX "waiting for reset to complete\n");
mdelay(1);
mdelay(1);
}
hcd->uses_new_polling = 1;
/* Enable USB host mode */
admhcd_reg_set(ahcd, ADMHCD_REG_CONTROL, ADMHCD_HOST_EN);
admhcd_reg_set(ahcd, ADMHCD_REG_CONTROL, ADMHCD_HOST_EN);
/* Set host specific settings */
admhcd_reg_set(ahcd, ADMHCD_REG_HOSTHEAD, 0x00000000);
admhcd_reg_set(ahcd, ADMHCD_REG_FMINTERVAL, 0x20002edf);
admhcd_reg_set(ahcd, ADMHCD_REG_LSTHRESH, 0x628);
admhcd_reg_set(ahcd, ADMHCD_REG_HOSTHEAD, 0x00000000);
admhcd_reg_set(ahcd, ADMHCD_REG_FMINTERVAL, 0x20002edf);
admhcd_reg_set(ahcd, ADMHCD_REG_LSTHRESH, 0x628);
/* Set interrupts */
admhcd_reg_set(ahcd, ADMHCD_REG_INTENABLE,
ADMHCD_INT_ACT | ADMHCD_INT_FATAL | ADMHCD_INT_SW | ADMHCD_INT_TD);
admhcd_reg_set(ahcd, ADMHCD_REG_INTSTATUS,
ADMHCD_INT_ACT | ADMHCD_INT_FATAL | ADMHCD_INT_SW | ADMHCD_INT_TD);
admhcd_reg_set(ahcd, ADMHCD_REG_INTENABLE, ADMHCD_INT_ACT |
ADMHCD_INT_FATAL | ADMHCD_INT_SW | ADMHCD_INT_TD);
admhcd_reg_set(ahcd, ADMHCD_REG_INTSTATUS, ADMHCD_INT_ACT |
ADMHCD_INT_FATAL | ADMHCD_INT_SW | ADMHCD_INT_TD);
/* Power on all ports */
admhcd_reg_set(ahcd, ADMHCD_REG_RHDESCR, ADMHCD_NPS | ADMHCD_LPSC);
admhcd_reg_set(ahcd, ADMHCD_REG_RHDESCR, ADMHCD_NPS | ADMHCD_LPSC);
/* HCD is now operationnal */
admhcd_reg_set(ahcd, ADMHCD_REG_HOSTCONTROL, ADMHCD_STATE_OP);
admhcd_reg_set(ahcd, ADMHCD_REG_HOSTCONTROL, ADMHCD_STATE_OP);
hcd->state = HC_STATE_RUNNING;
hcd->state = HC_STATE_RUNNING;
spin_unlock_irqrestore(&ahcd->lock, flags);
printk(KERN_DEBUG PFX "returning 0 from admhcd_start\n");
return 0;
return 0;
}
static int admhcd_sw_reset(struct admhcd *ahcd)
@ -757,11 +758,11 @@ static int admhcd_sw_reset(struct admhcd *ahcd)
spin_lock_irqsave(&ahcd->lock, flags);
admhcd_reg_set(ahcd, ADMHCD_REG_INTENABLE, 0);
mdelay(10);
mdelay(10);
admhcd_reg_set(ahcd, ADMHCD_REG_CONTROL, ADMHCD_SW_RESET);
admhcd_reg_set(ahcd, ADMHCD_REG_CONTROL, ADMHCD_SW_RESET);
while (--retries) {
while (--retries) {
mdelay(1);
if (!(admhcd_reg_get(ahcd, ADMHCD_REG_CONTROL) & ADMHCD_SW_RESET))
break;
@ -777,7 +778,7 @@ static int admhcd_sw_reset(struct admhcd *ahcd)
static int admhcd_reset(struct usb_hcd *hcd)
{
struct admhcd *ahcd = hcd_to_admhcd(hcd);
u32 state = 0;
u32 state = 0;
int ret, timeout = 15; /* ms */
unsigned long t;
@ -787,32 +788,32 @@ static int admhcd_reset(struct usb_hcd *hcd)
t = jiffies + msecs_to_jiffies(timeout);
do {
spin_lock_irq(&ahcd->lock);
state = admhcd_reg_get(ahcd, ADMHCD_REG_HOSTCONTROL);
spin_unlock_irq(&ahcd->lock);
spin_lock_irq(&ahcd->lock);
state = admhcd_reg_get(ahcd, ADMHCD_REG_HOSTCONTROL);
spin_unlock_irq(&ahcd->lock);
state &= ADMHCD_STATE_MASK;
if (state == ADMHCD_STATE_RST)
break;
msleep(4);
if (state == ADMHCD_STATE_RST)
break;
msleep(4);
} while (time_before_eq(jiffies, t));
if (state != ADMHCD_STATE_RST) {
printk(KERN_WARNING "%s: device not ready after %dms\n",
if (state != ADMHCD_STATE_RST) {
printk(KERN_WARNING "%s: device not ready after %dms\n",
hcd_name, timeout);
ret = -ENODEV;
}
ret = -ENODEV;
}
return ret;
return ret;
}
static void admhcd_stop(struct usb_hcd *hcd)
{
struct admhcd *ahcd = hcd_to_admhcd(hcd);
unsigned long flags;
unsigned long flags;
u32 val;
spin_lock_irqsave(&ahcd->lock, flags);
admhcd_reg_set(ahcd, ADMHCD_REG_INTENABLE, 0);
spin_lock_irqsave(&ahcd->lock, flags);
admhcd_reg_set(ahcd, ADMHCD_REG_INTENABLE, 0);
/* Set global control of power for ports */
val = admhcd_reg_get(ahcd, ADMHCD_REG_RHDESCR);
@ -830,7 +831,7 @@ static struct hc_driver adm5120_hc_driver = {
.description = hcd_name,
.product_desc = "ADM5120 HCD",
.hcd_priv_size = sizeof(struct admhcd),
.irq = adm5120hcd_irq,
.irq = admhcd_irq,
.flags = HCD_USB11,
.urb_enqueue = admhcd_urb_enqueue,
.urb_dequeue = admhcd_urb_dequeue,
@ -847,51 +848,51 @@ static struct hc_driver adm5120_hc_driver = {
static int __init adm5120hcd_probe(struct platform_device *pdev)
{
struct usb_hcd *hcd;
struct admhcd *ahcd;
struct usb_hcd *hcd;
struct admhcd *ahcd;
struct resource *data;
void __iomem *data_reg;
int err = 0, irq;
int err = 0, irq;
if (pdev->num_resources < 2) {
printk(KERN_WARNING PFX "not enough resources\n");
err = -ENODEV;
goto out;
}
}
irq = platform_get_irq(pdev, 0);
data = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (pdev->dev.dma_mask) {
printk(KERN_DEBUG PFX "no we won't dma\n");
return -EINVAL;
}
printk(KERN_DEBUG PFX "no we won't dma\n");
return -EINVAL;
}
if (!data || irq < 0) {
printk(KERN_DEBUG PFX "either IRQ or data resource is invalid\n");
err = -ENODEV;
goto out;
}
err = -ENODEV;
goto out;
}
if (!request_mem_region(data->start, resource_len(data), hcd_name)) {
if (!request_mem_region(data->start, resource_len(data), hcd_name)) {
printk(KERN_DEBUG PFX "cannot request memory regions for the data resource\n");
err = -EBUSY;
goto out;
}
err = -EBUSY;
goto out;
}
data_reg = ioremap(data->start, resource_len(data));
if (data_reg == NULL) {
data_reg = ioremap(data->start, resource_len(data));
if (data_reg == NULL) {
printk(KERN_DEBUG PFX "unable to ioremap\n");
err = -ENOMEM;
goto out_mem;
err = -ENOMEM;
goto out_mem;
}
hcd = usb_create_hcd(&adm5120_hc_driver, &pdev->dev, pdev->dev.bus_id);
if (!hcd) {
if (!hcd) {
printk(KERN_DEBUG PFX "unable to create the hcd\n");
err = -ENOMEM;
goto out_unmap;
goto out_unmap;
}
hcd->rsrc_start = data->start;