9
0
Fork 0

Merge branch 'work/usb' into next

This commit is contained in:
Sascha Hauer 2012-04-13 10:46:52 +02:00
commit ed921b0401
4 changed files with 65 additions and 73 deletions

View File

@ -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());

View File

@ -154,10 +154,15 @@ void imx53_init_lowlevel(unsigned int cpufreq_mhz)
writel(0x00016154, ccm + MX5_CCM_CBCMR);
/* change uart clk parent to pll2 */
r = readl(ccm + MX5_CCM_CSCMR1);
r &= ~(3 << 24);
r |= (1 << 24);
/* change uart clk parent to pll2 */
r &= ~MX5_CCM_CSCMR1_UART_CLK_SEL_MASK;
r |= 1 << MX5_CCM_CSCMR1_UART_CLK_SEL_OFFSET;
/* USB phy clock from osc */
r &= ~(1 << MX5_CCM_CSCMR1_USB_PHY_CLK_SEL_OFFSET);
writel(r, ccm + MX5_CCM_CSCMR1);
/* make sure change is effective */
@ -187,6 +192,12 @@ void imx53_init_lowlevel(unsigned int cpufreq_mhz)
r &= ~MX5_CCM_CSCDR1_ESDHC3_MX53_CLK_PODF_MASK;
r |= 1 << MX5_CCM_CSCDR1_ESDHC3_MX53_CLK_PODF_OFFSET;
r &= ~MX5_CCM_CSCDR1_USBOH3_CLK_PRED_MASK;
r &= ~MX5_CCM_CSCDR1_USBOH3_CLK_PODF_MASK;
r |= 3 << MX5_CCM_CSCDR1_USBOH3_CLK_PRED_OFFSET;
r |= 1 << MX5_CCM_CSCDR1_USBOH3_CLK_PODF_OFFSET;
writel(r, ccm + MX5_CCM_CSCDR1);
/* Restore the default values in the Gate registers */

View File

@ -934,8 +934,8 @@ static void usb_hub_power_on(struct usb_hub_device *hub)
for (i = 0; i < dev->maxchild; i++) {
usb_set_port_feature(dev, i + 1, USB_PORT_FEAT_POWER);
USB_HUB_PRINTF("port %d returns %lX\n", i + 1, dev->status);
wait_ms(hub->desc.bPwrOn2PwrGood * 2);
}
mdelay(20);
}
#define MAX_TRIES 5

View File

@ -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;
@ -61,7 +64,7 @@ static struct descriptor {
0x29, /* bDescriptorType: hub descriptor */
2, /* bNrPorts -- runtime modified */
0, /* wHubCharacteristics */
0xff, /* bPwrOn2PwrGood */
10, /* bPwrOn2PwrGood */
0, /* bHubCntrCurrent */
{}, /* Device removable */
{} /* at most 7 ports! XXX */
@ -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);
int i;
flush_invalidate(ehci->qh_list, sizeof(struct QH) * NUM_QH, flush);
flush_invalidate(ehci->td, sizeof(struct qTD) * NUM_TD, flush);
for (i = 0; i < NUM_TD; i ++)
cache_qtd(&ehci->td[i], flush);
}
static void cache_qh(struct QH *qh, int flush)
static inline void ehci_flush_dcache(struct ehci_priv *ehci)
{
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);
/*
* 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;
/*
* 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;
}
cache_qh(ehci, 1);
}
static inline void ehci_flush_dcache(struct QH *qh)
static inline void ehci_invalidate_dcache(struct ehci_priv *ehci)
{
cache_qh(qh, 1);
}
static inline void ehci_invalidate_dcache(struct QH *qh)
{
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;