diff options
author | Colin Cross <ccross@android.com> | 2010-10-14 16:22:51 -0700 |
---|---|---|
committer | Colin Cross <ccross@android.com> | 2010-10-14 16:22:51 -0700 |
commit | 40ab482b699f7d2807d2678ced16ba6b512ff54a (patch) | |
tree | 19898818297dde93c9d35db4ab50b717b0b5e19c /drivers | |
parent | 3d533ce331337e58f16b25e5de9a57f1665c4a73 (diff) | |
parent | 43ca7cdda2e511be7d19c3bdbc437e471b7e8f7e (diff) |
Merge branch 'linux-tegra-2.6.36' into android-tegra-2.6.36
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/serial/tegra_hsuart.c | 10 | ||||
-rw-r--r-- | drivers/spi/spi_tegra.c | 9 | ||||
-rw-r--r-- | drivers/usb/gadget/fsl_udc_core.c | 162 | ||||
-rw-r--r-- | drivers/video/tegra/fb.c | 1 |
4 files changed, 158 insertions, 24 deletions
diff --git a/drivers/serial/tegra_hsuart.c b/drivers/serial/tegra_hsuart.c index d992d36bbd29..a8e3a5c93812 100644 --- a/drivers/serial/tegra_hsuart.c +++ b/drivers/serial/tegra_hsuart.c @@ -213,7 +213,7 @@ static void tegra_start_next_tx(struct tegra_uart_port *t) if (count == 0) goto out; - if (TX_FORCE_PIO || count < TEGRA_UART_MIN_DMA) + if (!t->use_tx_dma || count < TEGRA_UART_MIN_DMA) tegra_start_pio_tx(t, count); else if (BYTES_TO_ALIGN(tail) > 0) tegra_start_pio_tx(t, BYTES_TO_ALIGN(tail)); @@ -666,8 +666,10 @@ static int tegra_uart_init_rx_dma(struct tegra_uart_port *t) void *rx_dma_virt; t->rx_dma = tegra_dma_allocate_channel(TEGRA_DMA_MODE_CONTINUOUS); - if (!t->rx_dma) + if (!t->rx_dma) { + pr_err("%s: failed to allocate RX DMA.\n", __func__); return -ENODEV; + } memset(&t->rx_dma_req, 0, sizeof(t->rx_dma_req)); @@ -712,6 +714,8 @@ static int tegra_startup(struct uart_port *u) t->tx_dma = tegra_dma_allocate_channel(TEGRA_DMA_MODE_ONESHOT); if (t->tx_dma) t->use_tx_dma = true; + else + pr_err("%s: failed to allocate TX DMA.\n", __func__); } if (t->use_tx_dma) { t->tx_dma_req.instance = u->line; @@ -733,7 +737,7 @@ static int tegra_startup(struct uart_port *u) t->tx_in_progress = 0; t->use_rx_dma = false; - if (!TX_FORCE_PIO) { + if (!RX_FORCE_PIO) { if (!tegra_uart_init_rx_dma(t)) t->use_rx_dma = true; } diff --git a/drivers/spi/spi_tegra.c b/drivers/spi/spi_tegra.c index 3709d5dccd76..33226408b447 100644 --- a/drivers/spi/spi_tegra.c +++ b/drivers/spi/spi_tegra.c @@ -473,11 +473,6 @@ static int spi_tegra_transfer(struct spi_device *spi, struct spi_message *m) return 0; } -static void spi_tegra_cleanup(struct spi_device *spi) -{ - dev_dbg(&spi->dev, "cleanup\n"); -} - static int __init spi_tegra_probe(struct platform_device *pdev) { struct spi_master *master; @@ -494,12 +489,10 @@ static int __init spi_tegra_probe(struct platform_device *pdev) /* the spi->mode bits understood by this driver: */ master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH; - if (pdev->id != -1) - master->bus_num = pdev->id; + master->bus_num = pdev->id; master->setup = spi_tegra_setup; master->transfer = spi_tegra_transfer; - master->cleanup = spi_tegra_cleanup; master->num_chipselect = 4; dev_set_drvdata(&pdev->dev, master); diff --git a/drivers/usb/gadget/fsl_udc_core.c b/drivers/usb/gadget/fsl_udc_core.c index 68715f5183be..20fab22cc13b 100644 --- a/drivers/usb/gadget/fsl_udc_core.c +++ b/drivers/usb/gadget/fsl_udc_core.c @@ -94,6 +94,25 @@ static int reset_queues(struct fsl_udc *udc); #define fsl_writel(val32, addr) writel(val32, addr) #endif +/* + * High speed test mode packet(53 bytes). + * See USB 2.0 spec, section 7.1.20. + */ +static const u8 fsl_udc_test_packet[53] = { + /* JKJKJKJK x9 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* JJKKJJKK x8 */ + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + /* JJJJKKKK x8 */ + 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, + /* JJJJJJJKKKKKKK x8 */ + 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + /* JJJJJJJK x8 */ + 0x7f, 0xbf, 0xdf, 0xef, 0xf7, 0xfb, 0xfd, + /* JKKKKKKK x10, JK */ + 0xfc, 0x7e, 0xbf, 0xdf, 0xef, 0xf7, 0xfb, 0xfd, 0x7e +}; + /******************************************************************** * Internal Used Function ********************************************************************/ @@ -730,7 +749,7 @@ out: * @is_last: return flag if it is the last dTD of the request * return: pointer to the built dTD */ static struct ep_td_struct *fsl_build_dtd(struct fsl_req *req, unsigned *length, - dma_addr_t *dma, int *is_last) + dma_addr_t *dma, int *is_last, gfp_t gfp_flags) { u32 swap_temp; struct ep_td_struct *dtd; @@ -739,7 +758,7 @@ static struct ep_td_struct *fsl_build_dtd(struct fsl_req *req, unsigned *length, *length = min(req->req.length - req->req.actual, (unsigned)EP_MAX_LENGTH_TRANSFER); - dtd = dma_pool_alloc(udc_controller->td_pool, GFP_KERNEL, dma); + dtd = dma_pool_alloc(udc_controller->td_pool, gfp_flags, dma); if (dtd == NULL) return dtd; @@ -789,7 +808,7 @@ static struct ep_td_struct *fsl_build_dtd(struct fsl_req *req, unsigned *length, } /* Generate dtd chain for a request */ -static int fsl_req_to_dtd(struct fsl_req *req) +static int fsl_req_to_dtd(struct fsl_req *req, gfp_t gfp_flags) { unsigned count; int is_last; @@ -798,7 +817,7 @@ static int fsl_req_to_dtd(struct fsl_req *req) dma_addr_t dma; do { - dtd = fsl_build_dtd(req, &count, &dma, &is_last); + dtd = fsl_build_dtd(req, &count, &dma, &is_last, gfp_flags); if (dtd == NULL) return -ENOMEM; @@ -874,15 +893,13 @@ fsl_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags) req->req.actual = 0; req->dtd_count = 0; - spin_lock_irqsave(&udc->lock, flags); /* build dtds and push them to device queue */ - if (!fsl_req_to_dtd(req)) { - fsl_queue_td(ep, req); - } else { - spin_unlock_irqrestore(&udc->lock, flags); + if (fsl_req_to_dtd(req, gfp_flags)) return -ENOMEM; - } + + spin_lock_irqsave(&udc->lock, flags); + fsl_queue_td(ep, req); /* Update ep0 state */ if ((ep_index(ep) == 0)) @@ -1254,7 +1271,7 @@ static int ep0_prime_status(struct fsl_udc *udc, int direction) req->req.complete = NULL; req->dtd_count = 0; - if (fsl_req_to_dtd(req) == 0) + if (fsl_req_to_dtd(req, GFP_ATOMIC) == 0) fsl_queue_td(ep, req); else return -ENOMEM; @@ -1332,7 +1349,7 @@ static void ch9getstatus(struct fsl_udc *udc, u8 request_type, u16 value, req->dtd_count = 0; /* prime the data phase */ - if ((fsl_req_to_dtd(req) == 0)) + if ((fsl_req_to_dtd(req, GFP_ATOMIC) == 0)) fsl_queue_td(ep, req); else /* no mem */ goto stall; @@ -1344,6 +1361,107 @@ stall: ep0stall(udc); } +static void udc_test_mode(struct fsl_udc *udc, u32 test_mode) +{ + struct fsl_req *req; + struct fsl_ep *ep; + u32 portsc, bitmask; + unsigned long timeout; + + /* Ack the ep0 IN */ + if (ep0_prime_status(udc, EP_DIR_IN)) + ep0stall(udc); + + /* get the ep0 */ + ep = &udc->eps[0]; + bitmask = ep_is_in(ep) + ? (1 << (ep_index(ep) + 16)) + : (1 << (ep_index(ep))); + + timeout = jiffies + HZ; + /* Wait until ep0 IN endpoint txfr is complete */ + while (!(fsl_readl(&dr_regs->endptcomplete) & bitmask)) { + if (time_after(jiffies, timeout)) { + pr_err("Timeout for Ep0 IN Ack\n"); + break; + } + cpu_relax(); + } + + switch (test_mode << PORTSCX_PTC_BIT_POS) { + case PORTSCX_PTC_JSTATE: + VDBG("TEST_J\n"); + break; + case PORTSCX_PTC_KSTATE: + VDBG("TEST_K\n"); + break; + case PORTSCX_PTC_SEQNAK: + VDBG("TEST_SE0_NAK\n"); + break; + case PORTSCX_PTC_PACKET: + VDBG("TEST_PACKET\n"); + + /* get the ep and configure for IN direction */ + ep = &udc->eps[0]; + udc->ep0_dir = USB_DIR_IN; + + /* Initialize ep0 status request structure */ + req = container_of(fsl_alloc_request(NULL, GFP_ATOMIC), + struct fsl_req, req); + /* allocate a small amount of memory to get valid address */ + req->req.buf = kmalloc(sizeof(fsl_udc_test_packet), GFP_ATOMIC); + req->req.dma = virt_to_phys(req->req.buf); + + /* Fill in the reqest structure */ + memcpy(req->req.buf, fsl_udc_test_packet, sizeof(fsl_udc_test_packet)); + req->ep = ep; + req->req.length = sizeof(fsl_udc_test_packet); + req->req.status = -EINPROGRESS; + req->req.actual = 0; + req->req.complete = NULL; + req->dtd_count = 0; + req->mapped = 0; + + dma_sync_single_for_device(ep->udc->gadget.dev.parent, + req->req.dma, req->req.length, + ep_is_in(ep) + ? DMA_TO_DEVICE + : DMA_FROM_DEVICE); + + /* prime the data phase */ + if ((fsl_req_to_dtd(req, GFP_ATOMIC) == 0)) + fsl_queue_td(ep, req); + else /* no mem */ + goto stall; + + list_add_tail(&req->queue, &ep->queue); + udc->ep0_state = DATA_STATE_XMIT; + break; + case PORTSCX_PTC_FORCE_EN: + VDBG("TEST_FORCE_EN\n"); + break; + default: + ERR("udc unknown test mode[%d]!\n", test_mode); + goto stall; + } + + /* read the portsc register */ + portsc = fsl_readl(&dr_regs->portsc1); + /* set the test mode selector */ + portsc |= test_mode << PORTSCX_PTC_BIT_POS; + fsl_writel(portsc, &dr_regs->portsc1); + + /* + * The device must have its power cycled to exit test mode. + * See USB 2.0 spec, section 9.4.9 for test modes operation in "Set Feature" + * See USB 2.0 spec, section 7.1.20 for test modes. + */ + pr_info("udc entering the test mode, power cycle to exit test mode\n"); + return; +stall: + ep0stall(udc); +} + static void setup_received_irq(struct fsl_udc *udc, struct usb_ctrlrequest *setup) { @@ -1377,7 +1495,17 @@ static void setup_received_irq(struct fsl_udc *udc, { int rc = -EOPNOTSUPP; - if ((setup->bRequestType & (USB_RECIP_MASK | USB_TYPE_MASK)) + if (setup->bRequestType == USB_RECIP_DEVICE && + wValue == USB_DEVICE_TEST_MODE) { + /* + * If the feature selector is TEST_MODE, then the most + * significant byte of wIndex is used to specify the specific + * test mode and the lower byte of wIndex must be zero. + */ + udc_test_mode(udc, wIndex >> 8); + return; + + } else if ((setup->bRequestType & (USB_RECIP_MASK | USB_TYPE_MASK)) == (USB_RECIP_ENDPOINT | USB_TYPE_STANDARD)) { int pipe = get_pipe_by_windex(wIndex); struct fsl_ep *ep; @@ -2604,6 +2732,10 @@ static int __exit fsl_udc_remove(struct platform_device *pdev) -----------------------------------------------------------------*/ static int fsl_udc_suspend(struct platform_device *pdev, pm_message_t state) { + if (udc_controller->transceiver && + udc_controller->transceiver->state != OTG_STATE_B_PERIPHERAL) + return 0; + dr_controller_stop(udc_controller); return 0; } @@ -2614,6 +2746,10 @@ static int fsl_udc_suspend(struct platform_device *pdev, pm_message_t state) *-----------------------------------------------------------------*/ static int fsl_udc_resume(struct platform_device *pdev) { + if (udc_controller->transceiver && + udc_controller->transceiver->state != OTG_STATE_B_PERIPHERAL) + return 0; + /* Enable DR irq reg and set controller Run */ if (udc_controller->stopped) { dr_controller_setup(udc_controller); diff --git a/drivers/video/tegra/fb.c b/drivers/video/tegra/fb.c index 87ba58b06cd1..746ea532661c 100644 --- a/drivers/video/tegra/fb.c +++ b/drivers/video/tegra/fb.c @@ -149,6 +149,7 @@ static int tegra_fb_set_par(struct fb_info *info) return -EINVAL; } info->fix.line_length = var->xres * var->bits_per_pixel / 8; + tegra_fb->win->stride = info->fix.line_length; if (var->pixclock) { struct tegra_dc_mode mode; |