Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 248773
b: refs/heads/master
c: 09ba0de
h: refs/heads/master
i:
  248771: 17a5c2e
v: v3
  • Loading branch information
Anatolij Gustschin authored and Greg Kroah-Hartman committed May 2, 2011
1 parent 7fe0e7a commit 2c92017
Show file tree
Hide file tree
Showing 3 changed files with 101 additions and 26 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: b703e47ec0d16ccaf2895e2069b6c83a92c51efc
refs/heads/master: 09ba0def9aefc16c1c8a6d166f024c9d704f0ab0
123 changes: 98 additions & 25 deletions trunk/drivers/usb/gadget/fsl_udc_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -77,12 +77,64 @@ fsl_ep0_desc = {
static void fsl_ep_fifo_flush(struct usb_ep *_ep);

#ifdef CONFIG_PPC32
#define fsl_readl(addr) in_le32(addr)
#define fsl_writel(val32, addr) out_le32(addr, val32)
#else
/*
* On some SoCs, the USB controller registers can be big or little endian,
* depending on the version of the chip. In order to be able to run the
* same kernel binary on 2 different versions of an SoC, the BE/LE decision
* must be made at run time. _fsl_readl and fsl_writel are pointers to the
* BE or LE readl() and writel() functions, and fsl_readl() and fsl_writel()
* call through those pointers. Platform code for SoCs that have BE USB
* registers should set pdata->big_endian_mmio flag.
*
* This also applies to controller-to-cpu accessors for the USB descriptors,
* since their endianness is also SoC dependant. Platform code for SoCs that
* have BE USB descriptors should set pdata->big_endian_desc flag.
*/
static u32 _fsl_readl_be(const unsigned __iomem *p)
{
return in_be32(p);
}

static u32 _fsl_readl_le(const unsigned __iomem *p)
{
return in_le32(p);
}

static void _fsl_writel_be(u32 v, unsigned __iomem *p)
{
out_be32(p, v);
}

static void _fsl_writel_le(u32 v, unsigned __iomem *p)
{
out_le32(p, v);
}

static u32 (*_fsl_readl)(const unsigned __iomem *p);
static void (*_fsl_writel)(u32 v, unsigned __iomem *p);

#define fsl_readl(p) (*_fsl_readl)((p))
#define fsl_writel(v, p) (*_fsl_writel)((v), (p))

static inline u32 cpu_to_hc32(const u32 x)
{
return udc_controller->pdata->big_endian_desc
? (__force u32)cpu_to_be32(x)
: (__force u32)cpu_to_le32(x);
}

static inline u32 hc32_to_cpu(const u32 x)
{
return udc_controller->pdata->big_endian_desc
? be32_to_cpu((__force __be32)x)
: le32_to_cpu((__force __le32)x);
}
#else /* !CONFIG_PPC32 */
#define fsl_readl(addr) readl(addr)
#define fsl_writel(val32, addr) writel(val32, addr)
#endif
#define cpu_to_hc32(x) cpu_to_le32(x)
#define hc32_to_cpu(x) le32_to_cpu(x)
#endif /* CONFIG_PPC32 */

/********************************************************************
* Internal Used Function
Expand Down Expand Up @@ -409,7 +461,7 @@ static void struct_ep_qh_setup(struct fsl_udc *udc, unsigned char ep_num,
if (zlt)
tmp |= EP_QUEUE_HEAD_ZLT_SEL;

p_QH->max_pkt_length = cpu_to_le32(tmp);
p_QH->max_pkt_length = cpu_to_hc32(tmp);
p_QH->next_dtd_ptr = 1;
p_QH->size_ioc_int_sts = 0;
}
Expand Down Expand Up @@ -616,7 +668,7 @@ static void fsl_queue_td(struct fsl_ep *ep, struct fsl_req *req)
struct fsl_req *lastreq;
lastreq = list_entry(ep->queue.prev, struct fsl_req, queue);
lastreq->tail->next_td_ptr =
cpu_to_le32(req->head->td_dma & DTD_ADDR_MASK);
cpu_to_hc32(req->head->td_dma & DTD_ADDR_MASK);
/* Read prime bit, if 1 goto done */
if (fsl_readl(&dr_regs->endpointprime) & bitmask)
goto out;
Expand All @@ -641,10 +693,10 @@ static void fsl_queue_td(struct fsl_ep *ep, struct fsl_req *req)

/* Write dQH next pointer and terminate bit to 0 */
temp = req->head->td_dma & EP_QUEUE_HEAD_NEXT_POINTER_MASK;
dQH->next_dtd_ptr = cpu_to_le32(temp);
dQH->next_dtd_ptr = cpu_to_hc32(temp);

/* Clear active and halt bit */
temp = cpu_to_le32(~(EP_QUEUE_HEAD_STATUS_ACTIVE
temp = cpu_to_hc32(~(EP_QUEUE_HEAD_STATUS_ACTIVE
| EP_QUEUE_HEAD_STATUS_HALT));
dQH->size_ioc_int_sts &= temp;

Expand Down Expand Up @@ -682,17 +734,17 @@ static struct ep_td_struct *fsl_build_dtd(struct fsl_req *req, unsigned *length,

dtd->td_dma = *dma;
/* Clear reserved field */
swap_temp = cpu_to_le32(dtd->size_ioc_sts);
swap_temp = hc32_to_cpu(dtd->size_ioc_sts);
swap_temp &= ~DTD_RESERVED_FIELDS;
dtd->size_ioc_sts = cpu_to_le32(swap_temp);
dtd->size_ioc_sts = cpu_to_hc32(swap_temp);

/* Init all of buffer page pointers */
swap_temp = (u32) (req->req.dma + req->req.actual);
dtd->buff_ptr0 = cpu_to_le32(swap_temp);
dtd->buff_ptr1 = cpu_to_le32(swap_temp + 0x1000);
dtd->buff_ptr2 = cpu_to_le32(swap_temp + 0x2000);
dtd->buff_ptr3 = cpu_to_le32(swap_temp + 0x3000);
dtd->buff_ptr4 = cpu_to_le32(swap_temp + 0x4000);
dtd->buff_ptr0 = cpu_to_hc32(swap_temp);
dtd->buff_ptr1 = cpu_to_hc32(swap_temp + 0x1000);
dtd->buff_ptr2 = cpu_to_hc32(swap_temp + 0x2000);
dtd->buff_ptr3 = cpu_to_hc32(swap_temp + 0x3000);
dtd->buff_ptr4 = cpu_to_hc32(swap_temp + 0x4000);

req->req.actual += *length;

Expand All @@ -716,7 +768,7 @@ static struct ep_td_struct *fsl_build_dtd(struct fsl_req *req, unsigned *length,
if (*is_last && !req->req.no_interrupt)
swap_temp |= DTD_IOC;

dtd->size_ioc_sts = cpu_to_le32(swap_temp);
dtd->size_ioc_sts = cpu_to_hc32(swap_temp);

mb();

Expand All @@ -743,15 +795,15 @@ static int fsl_req_to_dtd(struct fsl_req *req)
is_first = 0;
req->head = dtd;
} else {
last_dtd->next_td_ptr = cpu_to_le32(dma);
last_dtd->next_td_ptr = cpu_to_hc32(dma);
last_dtd->next_td_virt = dtd;
}
last_dtd = dtd;

req->dtd_count++;
} while (!is_last);

dtd->next_td_ptr = cpu_to_le32(DTD_NEXT_TERMINATE);
dtd->next_td_ptr = cpu_to_hc32(DTD_NEXT_TERMINATE);

req->tail = dtd;

Expand Down Expand Up @@ -1394,6 +1446,7 @@ static void tripwire_handler(struct fsl_udc *udc, u8 ep_num, u8 *buffer_ptr)
{
u32 temp;
struct ep_queue_head *qh;
struct fsl_usb2_platform_data *pdata = udc->pdata;

qh = &udc->ep_qh[ep_num * 2 + EP_DIR_OUT];

Expand All @@ -1408,7 +1461,16 @@ static void tripwire_handler(struct fsl_udc *udc, u8 ep_num, u8 *buffer_ptr)
fsl_writel(temp | USB_CMD_SUTW, &dr_regs->usbcmd);

/* Copy the setup packet to local buffer */
memcpy(buffer_ptr, (u8 *) qh->setup_buffer, 8);
if (pdata->le_setup_buf) {
u32 *p = (u32 *)buffer_ptr;
u32 *s = (u32 *)qh->setup_buffer;

/* Convert little endian setup buffer to CPU endian */
*p++ = le32_to_cpu(*s++);
*p = le32_to_cpu(*s);
} else {
memcpy(buffer_ptr, (u8 *) qh->setup_buffer, 8);
}
} while (!(fsl_readl(&dr_regs->usbcmd) & USB_CMD_SUTW));

/* Clear Setup Tripwire */
Expand All @@ -1432,19 +1494,19 @@ static int process_ep_req(struct fsl_udc *udc, int pipe,
actual = curr_req->req.length;

for (j = 0; j < curr_req->dtd_count; j++) {
remaining_length = (le32_to_cpu(curr_td->size_ioc_sts)
remaining_length = (hc32_to_cpu(curr_td->size_ioc_sts)
& DTD_PACKET_SIZE)
>> DTD_LENGTH_BIT_POS;
actual -= remaining_length;

if ((errors = le32_to_cpu(curr_td->size_ioc_sts) &
DTD_ERROR_MASK)) {
errors = hc32_to_cpu(curr_td->size_ioc_sts);
if (errors & DTD_ERROR_MASK) {
if (errors & DTD_STATUS_HALTED) {
ERR("dTD error %08x QH=%d\n", errors, pipe);
/* Clear the errors and Halt condition */
tmp = le32_to_cpu(curr_qh->size_ioc_int_sts);
tmp = hc32_to_cpu(curr_qh->size_ioc_int_sts);
tmp &= ~errors;
curr_qh->size_ioc_int_sts = cpu_to_le32(tmp);
curr_qh->size_ioc_int_sts = cpu_to_hc32(tmp);
status = -EPIPE;
/* FIXME: continue with next queued TD? */

Expand All @@ -1462,7 +1524,7 @@ static int process_ep_req(struct fsl_udc *udc, int pipe,
ERR("Unknown error has occurred (0x%x)!\n",
errors);

} else if (le32_to_cpu(curr_td->size_ioc_sts)
} else if (hc32_to_cpu(curr_td->size_ioc_sts)
& DTD_STATUS_ACTIVE) {
VDBG("Request not complete");
status = REQ_UNCOMPLETE;
Expand Down Expand Up @@ -2233,6 +2295,7 @@ static int __init struct_ep_setup(struct fsl_udc *udc, unsigned char index,
*/
static int __init fsl_udc_probe(struct platform_device *pdev)
{
struct fsl_usb2_platform_data *pdata;
struct resource *res;
int ret = -ENODEV;
unsigned int i;
Expand All @@ -2249,6 +2312,8 @@ static int __init fsl_udc_probe(struct platform_device *pdev)
return -ENOMEM;
}

pdata = pdev->dev.platform_data;
udc_controller->pdata = pdata;
spin_lock_init(&udc_controller->lock);
udc_controller->stopped = 1;

Expand All @@ -2271,6 +2336,14 @@ static int __init fsl_udc_probe(struct platform_device *pdev)
goto err_release_mem_region;
}

if (pdata->big_endian_mmio) {
_fsl_readl = _fsl_readl_be;
_fsl_writel = _fsl_writel_be;
} else {
_fsl_readl = _fsl_readl_le;
_fsl_writel = _fsl_writel_le;
}

#ifndef CONFIG_ARCH_MXC
usb_sys_regs = (struct usb_sys_interface *)
((u32)dr_regs + USB_DR_SYS_OFFSET);
Expand Down
2 changes: 2 additions & 0 deletions trunk/drivers/usb/gadget/fsl_usb2_udc.h
Original file line number Diff line number Diff line change
Expand Up @@ -461,6 +461,7 @@ struct fsl_ep {
struct fsl_udc {
struct usb_gadget gadget;
struct usb_gadget_driver *driver;
struct fsl_usb2_platform_data *pdata;
struct completion *done; /* to make sure release() is done */
struct fsl_ep *eps;
unsigned int max_ep;
Expand All @@ -473,6 +474,7 @@ struct fsl_udc {
unsigned vbus_active:1;
unsigned stopped:1;
unsigned remote_wakeup:1;
unsigned big_endian_desc:1;

struct ep_queue_head *ep_qh; /* Endpoints Queue-Head */
struct fsl_req *status_req; /* ep0 status request */
Expand Down

0 comments on commit 2c92017

Please sign in to comment.