* [PATCH 1/4] USB ehci: make cache handling simpler
2012-04-12 19:40 ehci patches Sascha Hauer
@ 2012-04-12 19:40 ` Sascha Hauer
2012-04-12 19:40 ` [PATCH 2/4] USB ehci: speed up initialization Sascha Hauer
` (2 subsequent siblings)
3 siblings, 0 replies; 5+ messages in thread
From: Sascha Hauer @ 2012-04-12 19:40 UTC (permalink / raw)
To: barebox
for chache handling the ehci driver iterates over the hardware lists
of QHs/TDs. As we have a fixed number of maximum entries in this lists
we can allocate them as arrays and and clean/invalidate the arrays
instead which is much simpler. While at it, move the allocation to
ehci_probe so that we do not lose memory each time ehci_init is called.
Also, use memalign to allocate the QHs/TDs.
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
drivers/usb/host/ehci-hcd.c | 96 ++++++++++++++-----------------------------
1 file changed, 30 insertions(+), 66 deletions(-)
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index 81e3a42..505d919 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -42,13 +42,16 @@ struct ehci_priv {
struct ehci_hcor *hcor;
struct usb_host host;
struct QH *qh_list;
- void *qhp;
+ struct qTD *td;
int portreset;
unsigned long flags;
};
#define to_ehci(ptr) container_of(ptr, struct ehci_priv, host)
+#define NUM_QH 2
+#define NUM_TD 3
+
static struct descriptor {
struct usb_hub_descriptor hub;
struct usb_device_descriptor device;
@@ -125,10 +128,11 @@ static struct descriptor {
*/
static void flush_invalidate(void *addr, int size, int flush)
{
- if (flush)
+ if (flush) {
dma_flush_range((unsigned long)addr, (unsigned long)(addr + size));
- else
+ } else {
dma_inv_range((unsigned long)addr, (unsigned long)(addr + size));
+ }
}
static void cache_qtd(struct qTD *qtd, int flush)
@@ -136,76 +140,39 @@ static void cache_qtd(struct qTD *qtd, int flush)
u32 *ptr = (u32 *)qtd->qt_buffer[0];
int len = (qtd->qt_token & 0x7fff0000) >> 16;
- flush_invalidate(qtd, sizeof(struct qTD), flush);
if (ptr && len)
flush_invalidate(ptr, len, flush);
}
-
-static inline struct QH *qh_addr(struct QH *qh)
+static void cache_qh(struct ehci_priv *ehci, int flush)
{
- return (struct QH *)((u32)qh & 0xffffffe0);
-}
-
-static void cache_qh(struct QH *qh, int flush)
-{
- struct qTD *qtd;
- struct qTD *next;
- static struct qTD *first_qtd;
-
- /*
- * Walk the QH list and flush/invalidate all entries
- */
- while (1) {
- flush_invalidate(qh_addr(qh), sizeof(struct QH), flush);
- if ((u32)qh & QH_LINK_TYPE_QH)
- break;
- qh = qh_addr(qh);
- qh = (struct QH *)qh->qh_link;
- }
- qh = qh_addr(qh);
+ int i;
- /*
- * Save first qTD pointer, needed for invalidating pass on this QH
- */
- if (flush)
- first_qtd = qtd = (struct qTD *)(*(u32 *)&qh->qh_overlay &
- 0xffffffe0);
- else
- qtd = first_qtd;
+ flush_invalidate(ehci->qh_list, sizeof(struct QH) * NUM_QH, flush);
+ flush_invalidate(ehci->td, sizeof(struct qTD) * NUM_TD, flush);
- /*
- * Walk the qTD list and flush/invalidate all entries
- */
- while (1) {
- if (qtd == NULL)
- break;
- cache_qtd(qtd, flush);
- next = (struct qTD *)((u32)qtd->qt_next & 0xffffffe0);
- if (next == qtd)
- break;
- qtd = next;
- }
+ for (i = 0; i < NUM_TD; i ++)
+ cache_qtd(&ehci->td[i], flush);
}
-static inline void ehci_flush_dcache(struct QH *qh)
+static inline void ehci_flush_dcache(struct ehci_priv *ehci)
{
- cache_qh(qh, 1);
+ cache_qh(ehci, 1);
}
-static inline void ehci_invalidate_dcache(struct QH *qh)
+static inline void ehci_invalidate_dcache(struct ehci_priv *ehci)
{
- cache_qh(qh, 0);
+ cache_qh(ehci, 0);
}
#else /* CONFIG_MMU */
/*
*
*/
-static inline void ehci_flush_dcache(struct QH *qh)
+static inline void ehci_flush_dcache(struct ehci_priv *ehci)
{
}
-static inline void ehci_invalidate_dcache(struct QH *qh)
+static inline void ehci_invalidate_dcache(struct ehci_priv *ehci)
{
}
#endif /* CONFIG_MMU */
@@ -299,8 +266,6 @@ ehci_submit_async(struct usb_device *dev, unsigned long pipe, void *buffer,
uint32_t cmd;
int ret = 0;
uint64_t start, timeout_val;
- static struct QH __qh __attribute__((aligned(32)));
- static struct qTD __td[3] __attribute__((aligned(32)));
debug("dev=%p, pipe=%lx, buffer=%p, length=%d, req=%p\n", dev, pipe,
buffer, length, req);
@@ -311,10 +276,10 @@ ehci_submit_async(struct usb_device *dev, unsigned long pipe, void *buffer,
le16_to_cpu(req->value), le16_to_cpu(req->value),
le16_to_cpu(req->index));
- memset(&__qh, 0, sizeof(struct QH));
- memset(&__td, 0, sizeof(struct qTD) * 3);
+ memset(&ehci->qh_list[1], 0, sizeof(struct QH));
+ memset(ehci->td, 0, sizeof(struct qTD) * NUM_TD);
- qh = &__qh;
+ qh = &ehci->qh_list[1];
qh->qh_link = cpu_to_hc32((uint32_t)ehci->qh_list | QH_LINK_TYPE_QH);
c = (usb_pipespeed(pipe) != USB_SPEED_HIGH &&
usb_pipeendpoint(pipe) == 0) ? 1 : 0;
@@ -341,7 +306,7 @@ ehci_submit_async(struct usb_device *dev, unsigned long pipe, void *buffer,
usb_gettoggle(dev, usb_pipeendpoint(pipe), usb_pipeout(pipe));
if (req != NULL) {
- td = &__td[0];
+ td = &ehci->td[0];
td->qt_next = cpu_to_hc32(QT_NEXT_TERMINATE);
td->qt_altnext = cpu_to_hc32(QT_NEXT_TERMINATE);
@@ -360,7 +325,7 @@ ehci_submit_async(struct usb_device *dev, unsigned long pipe, void *buffer,
}
if (length > 0 || req == NULL) {
- td = &__td[1];
+ td = &ehci->td[1];
td->qt_next = cpu_to_hc32(QT_NEXT_TERMINATE);
td->qt_altnext = cpu_to_hc32(QT_NEXT_TERMINATE);
@@ -380,7 +345,7 @@ ehci_submit_async(struct usb_device *dev, unsigned long pipe, void *buffer,
}
if (req) {
- td = &__td[2];
+ td = &ehci->td[2];
td->qt_next = cpu_to_hc32(QT_NEXT_TERMINATE);
td->qt_altnext = cpu_to_hc32(QT_NEXT_TERMINATE);
@@ -398,7 +363,7 @@ ehci_submit_async(struct usb_device *dev, unsigned long pipe, void *buffer,
ehci->qh_list->qh_link = cpu_to_hc32((uint32_t) qh | QH_LINK_TYPE_QH);
/* Flush dcache */
- ehci_flush_dcache(ehci->qh_list);
+ ehci_flush_dcache(ehci);
usbsts = ehci_readl(&ehci->hcor->or_usbsts);
ehci_writel(&ehci->hcor->or_usbsts, (usbsts & 0x3f));
@@ -420,7 +385,7 @@ ehci_submit_async(struct usb_device *dev, unsigned long pipe, void *buffer,
vtd = td;
do {
/* Invalidate dcache */
- ehci_invalidate_dcache(ehci->qh_list);
+ ehci_invalidate_dcache(ehci);
token = hc32_to_cpu(vtd->qt_token);
if (is_timeout(start, timeout_val)) {
/* Disable async schedule. */
@@ -802,10 +767,6 @@ static int ehci_init(struct usb_host *host)
if (ehci_reset(ehci) != 0)
return -1;
- /* Set head of reclaim list */
- ehci->qhp = xzalloc(sizeof(struct QH) + 32);
- ehci->qh_list = (struct QH *)(((unsigned long)ehci->qhp + 32) & ~31);
-
ehci->qh_list->qh_link = cpu_to_hc32((uint32_t)ehci->qh_list | QH_LINK_TYPE_QH);
ehci->qh_list->qh_endpt1 = cpu_to_hc32((1 << 15) | (USB_SPEED_HIGH << 12));
ehci->qh_list->qh_curtd = cpu_to_hc32(QT_NEXT_TERMINATE);
@@ -917,6 +878,9 @@ static int ehci_probe(struct device_d *dev)
ehci->hccr = dev_request_mem_region(dev, 0);
ehci->hcor = dev_request_mem_region(dev, 1);
+ ehci->qh_list = xmemalign(32, sizeof(struct QH) * NUM_QH);
+ ehci->td = xmemalign(32, sizeof(struct qTD) * NUM_TD);
+
host->init = ehci_init;
host->submit_int_msg = submit_int_msg;
host->submit_control_msg = submit_control_msg;
--
1.7.10
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH 4/4] ARM i.MX53 LOCO: Add USB support
2012-04-12 19:40 ehci patches Sascha Hauer
` (2 preceding siblings ...)
2012-04-12 19:40 ` [PATCH 3/4] ARM i.MX53: Setup USB clocks Sascha Hauer
@ 2012-04-12 19:40 ` Sascha Hauer
3 siblings, 0 replies; 5+ messages in thread
From: Sascha Hauer @ 2012-04-12 19:40 UTC (permalink / raw)
To: barebox
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
arch/arm/boards/freescale-mx53-loco/board.c | 17 +++++++++++++++++
1 file changed, 17 insertions(+)
diff --git a/arch/arm/boards/freescale-mx53-loco/board.c b/arch/arm/boards/freescale-mx53-loco/board.c
index 6ae597a..78e8f9a 100644
--- a/arch/arm/boards/freescale-mx53-loco/board.c
+++ b/arch/arm/boards/freescale-mx53-loco/board.c
@@ -95,6 +95,8 @@ static struct pad_desc loco_pads[] = {
/* I2C0 */
MX53_PAD_CSI0_DAT8__I2C1_SDA,
MX53_PAD_CSI0_DAT9__I2C1_SCL,
+
+ MX53_PAD_PATA_DA_2__GPIO7_8,
};
static struct i2c_board_info i2c_devices[] = {
@@ -149,6 +151,7 @@ static void loco_fec_reset(void)
#define LOCO_SD3_CD IMX_GPIO_NR(3, 11)
#define LOCO_SD3_WP IMX_GPIO_NR(3, 12)
#define LOCO_SD1_CD IMX_GPIO_NR(3, 13)
+#define MX53_LOCO_USB_PWREN IMX_GPIO_NR(7, 8)
static struct esdhc_platform_data loco_sd1_data = {
.cd_gpio = LOCO_SD1_CD,
@@ -163,8 +166,19 @@ static struct esdhc_platform_data loco_sd3_data = {
.wp_type = ESDHC_WP_GPIO,
};
+static void loco_ehci_init(void)
+{
+ /* USB PWR enable */
+ gpio_direction_output(MX53_LOCO_USB_PWREN, 0);
+ gpio_set_value(MX53_LOCO_USB_PWREN, 1);
+
+ writel(0, MX53_OTG_BASE_ADDR + 0x384); /* setup portsc */
+ add_generic_usb_ehci_device(1, MX53_OTG_BASE_ADDR + 0x200, NULL);
+}
+
static int loco_devices_init(void)
{
+
imx53_iim_register_fec_ethaddr();
imx53_add_fec(&fec_info);
imx53_add_mmc0(&loco_sd1_data);
@@ -172,6 +186,9 @@ static int loco_devices_init(void)
i2c_register_board_info(0, i2c_devices, ARRAY_SIZE(i2c_devices));
imx53_add_i2c0(NULL);
+ if (IS_ENABLED(CONFIG_USB_EHCI))
+ loco_ehci_init();
+
loco_fec_reset();
set_silicon_rev(imx_silicon_revision());
--
1.7.10
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 5+ messages in thread