diff options
Diffstat (limited to 'drivers/usb/gadget/udc/atmel_usba_udc.c')
| -rw-r--r-- | drivers/usb/gadget/udc/atmel_usba_udc.c | 348 |
1 files changed, 236 insertions, 112 deletions
diff --git a/drivers/usb/gadget/udc/atmel_usba_udc.c b/drivers/usb/gadget/udc/atmel_usba_udc.c index 660712e0bf98..0c6f2ad81d37 100644 --- a/drivers/usb/gadget/udc/atmel_usba_udc.c +++ b/drivers/usb/gadget/udc/atmel_usba_udc.c @@ -18,6 +18,7 @@ #include <linux/platform_device.h> #include <linux/regmap.h> #include <linux/ctype.h> +#include <linux/usb.h> #include <linux/usb/ch9.h> #include <linux/usb/gadget.h> #include <linux/delay.h> @@ -93,7 +94,7 @@ static ssize_t queue_dbg_read(struct file *file, char __user *buf, inode_lock(file_inode(file)); list_for_each_entry_safe(req, tmp_req, queue, queue) { - len = snprintf(tmpbuf, sizeof(tmpbuf), + len = scnprintf(tmpbuf, sizeof(tmpbuf), "%8p %08x %c%c%c %5d %c%c%c\n", req->req.buf, req->req.length, req->req.no_interrupt ? 'i' : 'I', @@ -103,7 +104,6 @@ static ssize_t queue_dbg_read(struct file *file, char __user *buf, req->submitted ? 'F' : 'f', req->using_dma ? 'D' : 'd', req->last_transaction ? 'L' : 'l'); - len = min(len, sizeof(tmpbuf)); if (len > nbytes) break; @@ -184,15 +184,14 @@ static int regs_dbg_release(struct inode *inode, struct file *file) return 0; } -const struct file_operations queue_dbg_fops = { +static const struct file_operations queue_dbg_fops = { .owner = THIS_MODULE, .open = queue_dbg_open, - .llseek = no_llseek, .read = queue_dbg_read, .release = queue_dbg_release, }; -const struct file_operations regs_dbg_fops = { +static const struct file_operations regs_dbg_fops = { .owner = THIS_MODULE, .open = regs_dbg_open, .llseek = generic_file_llseek, @@ -226,7 +225,7 @@ static void usba_init_debugfs(struct usba_udc *udc) struct dentry *root; struct resource *regs_resource; - root = debugfs_create_dir(udc->gadget.name, NULL); + root = debugfs_create_dir(udc->gadget.name, usb_debug_root); udc->debugfs_root = root; regs_resource = platform_get_resource(udc->pdev, IORESOURCE_MEM, @@ -327,6 +326,7 @@ static int usba_config_fifo_table(struct usba_udc *udc) switch (fifo_mode) { default: fifo_mode = 0; + fallthrough; case 0: udc->fifo_cfg = NULL; n = 0; @@ -358,8 +358,20 @@ static inline u32 usba_int_enb_get(struct usba_udc *udc) return udc->int_enb_cache; } -static inline void usba_int_enb_set(struct usba_udc *udc, u32 val) +static inline void usba_int_enb_set(struct usba_udc *udc, u32 mask) { + u32 val; + + val = udc->int_enb_cache | mask; + usba_writel(udc, INT_ENB, val); + udc->int_enb_cache = val; +} + +static inline void usba_int_enb_clear(struct usba_udc *udc, u32 mask) +{ + u32 val; + + val = udc->int_enb_cache & ~mask; usba_writel(udc, INT_ENB, val); udc->int_enb_cache = val; } @@ -436,9 +448,11 @@ static void submit_request(struct usba_ep *ep, struct usba_request *req) next_fifo_transaction(ep, req); if (req->last_transaction) { usba_ep_writel(ep, CTL_DIS, USBA_TX_PK_RDY); - usba_ep_writel(ep, CTL_ENB, USBA_TX_COMPLETE); + if (ep_is_control(ep)) + usba_ep_writel(ep, CTL_ENB, USBA_TX_COMPLETE); } else { - usba_ep_writel(ep, CTL_DIS, USBA_TX_COMPLETE); + if (ep_is_control(ep)) + usba_ep_writel(ep, CTL_DIS, USBA_TX_COMPLETE); usba_ep_writel(ep, CTL_ENB, USBA_TX_PK_RDY); } } @@ -629,14 +643,12 @@ usba_ep_enable(struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc) if (ep->can_dma) { u32 ctrl; - usba_int_enb_set(udc, usba_int_enb_get(udc) | - USBA_BF(EPT_INT, 1 << ep->index) | + usba_int_enb_set(udc, USBA_BF(EPT_INT, 1 << ep->index) | USBA_BF(DMA_INT, 1 << ep->index)); ctrl = USBA_AUTO_VALID | USBA_INTDIS_DMA; usba_ep_writel(ep, CTL_ENB, ctrl); } else { - usba_int_enb_set(udc, usba_int_enb_get(udc) | - USBA_BF(EPT_INT, 1 << ep->index)); + usba_int_enb_set(udc, USBA_BF(EPT_INT, 1 << ep->index)); } spin_unlock_irqrestore(&udc->lock, flags); @@ -662,13 +674,7 @@ static int usba_ep_disable(struct usb_ep *_ep) if (!ep->ep.desc) { spin_unlock_irqrestore(&udc->lock, flags); - /* REVISIT because this driver disables endpoints in - * reset_all_endpoints() before calling disconnect(), - * most gadget drivers would trigger this non-error ... - */ - if (udc->gadget.speed != USB_SPEED_UNKNOWN) - DBG(DBG_ERR, "ep_disable: %s not enabled\n", - ep->ep.name); + DBG(DBG_ERR, "ep_disable: %s not enabled\n", ep->ep.name); return -EINVAL; } ep->ep.desc = NULL; @@ -680,8 +686,7 @@ static int usba_ep_disable(struct usb_ep *_ep) usba_dma_readl(ep, STATUS); } usba_ep_writel(ep, CTL_DIS, USBA_EPT_ENABLE); - usba_int_enb_set(udc, usba_int_enb_get(udc) & - ~USBA_BF(EPT_INT, 1 << ep->index)); + usba_int_enb_clear(udc, USBA_BF(EPT_INT, 1 << ep->index)); request_complete_list(ep, &req_list, -ESHUTDOWN); @@ -853,21 +858,24 @@ static int usba_ep_dequeue(struct usb_ep *_ep, struct usb_request *_req) { struct usba_ep *ep = to_usba_ep(_ep); struct usba_udc *udc = ep->udc; - struct usba_request *req; + struct usba_request *req = NULL; + struct usba_request *iter; unsigned long flags; u32 status; DBG(DBG_GADGET | DBG_QUEUE, "ep_dequeue: %s, req %p\n", - ep->ep.name, req); + ep->ep.name, _req); spin_lock_irqsave(&udc->lock, flags); - list_for_each_entry(req, &ep->queue, queue) { - if (&req->req == _req) - break; + list_for_each_entry(iter, &ep->queue, queue) { + if (&iter->req != _req) + continue; + req = iter; + break; } - if (&req->req != _req) { + if (!req) { spin_unlock_irqrestore(&udc->lock, flags); return -EINVAL; } @@ -1021,6 +1029,7 @@ usba_udc_set_selfpowered(struct usb_gadget *gadget, int is_selfpowered) return 0; } +static int atmel_usba_pullup(struct usb_gadget *gadget, int is_on); static int atmel_usba_start(struct usb_gadget *gadget, struct usb_gadget_driver *driver); static int atmel_usba_stop(struct usb_gadget *gadget); @@ -1048,16 +1057,19 @@ found_ep: switch (usb_endpoint_type(desc)) { case USB_ENDPOINT_XFER_CONTROL: + ep->nr_banks = 1; break; case USB_ENDPOINT_XFER_ISOC: ep->fifo_size = 1024; - ep->nr_banks = 2; + if (ep->udc->ep_prealloc) + ep->nr_banks = 2; break; case USB_ENDPOINT_XFER_BULK: ep->fifo_size = 512; - ep->nr_banks = 1; + if (ep->udc->ep_prealloc) + ep->nr_banks = 1; break; case USB_ENDPOINT_XFER_INT: @@ -1067,7 +1079,8 @@ found_ep: else ep->fifo_size = roundup_pow_of_two(le16_to_cpu(desc->wMaxPacketSize)); - ep->nr_banks = 1; + if (ep->udc->ep_prealloc) + ep->nr_banks = 1; break; } @@ -1083,8 +1096,6 @@ found_ep: USBA_BF(EPT_SIZE, fls(ep->fifo_size - 1) - 3); ep->ept_cfg |= USBA_BF(BK_NUMBER, ep->nr_banks); - - ep->udc->configured_ep++; } return _ep; @@ -1094,6 +1105,7 @@ static const struct usb_gadget_ops usba_udc_ops = { .get_frame = usba_udc_get_frame, .wakeup = usba_udc_wakeup, .set_selfpowered = usba_udc_set_selfpowered, + .pullup = atmel_usba_pullup, .udc_start = atmel_usba_start, .udc_stop = atmel_usba_stop, .match_ep = atmel_usba_match_ep, @@ -1109,7 +1121,7 @@ static struct usb_endpoint_descriptor usba_ep0_desc = { .bInterval = 1, }; -static struct usb_gadget usba_gadget_template = { +static const struct usb_gadget usba_gadget_template = { .ops = &usba_udc_ops, .max_speed = USB_SPEED_HIGH, .name = "atmel_usba_udc", @@ -1694,6 +1706,9 @@ static void usba_dma_irq(struct usba_udc *udc, struct usba_ep *ep) } } +static int start_clock(struct usba_udc *udc); +static void stop_clock(struct usba_udc *udc); + static irqreturn_t usba_udc_irq(int irq, void *devid) { struct usba_udc *udc = devid; @@ -1708,10 +1723,13 @@ static irqreturn_t usba_udc_irq(int irq, void *devid) DBG(DBG_INT, "irq, status=%#08x\n", status); if (status & USBA_DET_SUSPEND) { + usba_writel(udc, INT_CLR, USBA_DET_SUSPEND|USBA_WAKE_UP); + usba_int_enb_set(udc, USBA_WAKE_UP); + usba_int_enb_clear(udc, USBA_DET_SUSPEND); + udc->suspended = true; toggle_bias(udc, 0); - usba_writel(udc, INT_CLR, USBA_DET_SUSPEND); - usba_int_enb_set(udc, int_enb | USBA_WAKE_UP); udc->bias_pulse_needed = true; + stop_clock(udc); DBG(DBG_BUS, "Suspend detected\n"); if (udc->gadget.speed != USB_SPEED_UNKNOWN && udc->driver && udc->driver->suspend) { @@ -1722,14 +1740,17 @@ static irqreturn_t usba_udc_irq(int irq, void *devid) } if (status & USBA_WAKE_UP) { + start_clock(udc); toggle_bias(udc, 1); usba_writel(udc, INT_CLR, USBA_WAKE_UP); - usba_int_enb_set(udc, int_enb & ~USBA_WAKE_UP); DBG(DBG_BUS, "Wake Up CPU detected\n"); } if (status & USBA_END_OF_RESUME) { + udc->suspended = false; usba_writel(udc, INT_CLR, USBA_END_OF_RESUME); + usba_int_enb_clear(udc, USBA_WAKE_UP); + usba_int_enb_set(udc, USBA_DET_SUSPEND); generate_bias_pulse(udc); DBG(DBG_BUS, "Resume detected\n"); if (udc->gadget.speed != USB_SPEED_UNKNOWN @@ -1744,6 +1765,8 @@ static irqreturn_t usba_udc_irq(int irq, void *devid) if (dma_status) { int i; + usba_int_enb_set(udc, USBA_DET_SUSPEND); + for (i = 1; i <= USBA_NR_DMAS; i++) if (dma_status & (1 << i)) usba_dma_irq(udc, &udc->usba_ep[i]); @@ -1753,6 +1776,8 @@ static irqreturn_t usba_udc_irq(int irq, void *devid) if (ep_status) { int i; + usba_int_enb_set(udc, USBA_DET_SUSPEND); + for (i = 0; i < udc->num_ep; i++) if (ep_status & (1 << i)) { if (ep_is_control(&udc->usba_ep[i])) @@ -1764,9 +1789,11 @@ static irqreturn_t usba_udc_irq(int irq, void *devid) if (status & USBA_END_OF_RESET) { struct usba_ep *ep0, *ep; - int i, n; + int i; - usba_writel(udc, INT_CLR, USBA_END_OF_RESET); + usba_writel(udc, INT_CLR, + USBA_END_OF_RESET|USBA_END_OF_RESUME + |USBA_DET_SUSPEND|USBA_WAKE_UP); generate_bias_pulse(udc); reset_all_endpoints(udc); @@ -1793,7 +1820,12 @@ static irqreturn_t usba_udc_irq(int irq, void *devid) | USBA_BF(BK_NUMBER, USBA_BK_NUMBER_ONE))); usba_ep_writel(ep0, CTL_ENB, USBA_EPT_ENABLE | USBA_RX_SETUP); - usba_int_enb_set(udc, int_enb | USBA_BF(EPT_INT, 1) | + + /* If we get reset while suspended... */ + udc->suspended = false; + usba_int_enb_clear(udc, USBA_WAKE_UP); + + usba_int_enb_set(udc, USBA_BF(EPT_INT, 1) | USBA_DET_SUSPEND | USBA_END_OF_RESUME); /* @@ -1805,13 +1837,14 @@ static irqreturn_t usba_udc_irq(int irq, void *devid) "ODD: EP0 configuration is invalid!\n"); /* Preallocate other endpoints */ - n = fifo_mode ? udc->num_ep : udc->configured_ep; - for (i = 1; i < n; i++) { + for (i = 1; i < udc->num_ep; i++) { ep = &udc->usba_ep[i]; - usba_ep_writel(ep, CFG, ep->ept_cfg); - if (!(usba_ep_readl(ep, CFG) & USBA_EPT_MAPPED)) - dev_err(&udc->pdev->dev, - "ODD: EP%d configuration is invalid!\n", i); + if (ep->ep.claimed) { + usba_ep_writel(ep, CFG, ep->ept_cfg); + if (!(usba_ep_readl(ep, CFG) & USBA_EPT_MAPPED)) + dev_err(&udc->pdev->dev, + "ODD: EP%d configuration is invalid!\n", i); + } } } @@ -1827,6 +1860,8 @@ static int start_clock(struct usba_udc *udc) if (udc->clocked) return 0; + pm_stay_awake(&udc->pdev->dev); + ret = clk_prepare_enable(udc->pclk); if (ret) return ret; @@ -1849,6 +1884,8 @@ static void stop_clock(struct usba_udc *udc) clk_disable_unprepare(udc->pclk); udc->clocked = false; + + pm_relax(&udc->pdev->dev); } static int usba_start(struct usba_udc *udc) @@ -1860,9 +1897,19 @@ static int usba_start(struct usba_udc *udc) if (ret) return ret; + if (udc->suspended) + return 0; + spin_lock_irqsave(&udc->lock, flags); toggle_bias(udc, 1); usba_writel(udc, CTRL, USBA_ENABLE_MASK); + /* Clear all requested and pending interrupts... */ + usba_writel(udc, INT_ENB, 0); + udc->int_enb_cache = 0; + usba_writel(udc, INT_CLR, + USBA_END_OF_RESET|USBA_END_OF_RESUME + |USBA_DET_SUSPEND|USBA_WAKE_UP); + /* ...and enable just 'reset' IRQ to get us started */ usba_int_enb_set(udc, USBA_END_OF_RESET); spin_unlock_irqrestore(&udc->lock, flags); @@ -1873,6 +1920,9 @@ static void usba_stop(struct usba_udc *udc) { unsigned long flags; + if (udc->suspended) + return; + spin_lock_irqsave(&udc->lock, flags); udc->gadget.speed = USB_SPEED_UNKNOWN; reset_all_endpoints(udc); @@ -1900,10 +1950,11 @@ static irqreturn_t usba_vbus_irq_thread(int irq, void *devid) if (vbus) { usba_start(udc); } else { - usba_stop(udc); - + udc->suspended = false; if (udc->driver->disconnect) udc->driver->disconnect(&udc->gadget); + + usba_stop(udc); } udc->vbus_prev = vbus; } @@ -1912,6 +1963,24 @@ static irqreturn_t usba_vbus_irq_thread(int irq, void *devid) return IRQ_HANDLED; } +static int atmel_usba_pullup(struct usb_gadget *gadget, int is_on) +{ + struct usba_udc *udc = container_of(gadget, struct usba_udc, gadget); + unsigned long flags; + u32 ctrl; + + spin_lock_irqsave(&udc->lock, flags); + ctrl = usba_readl(udc, CTRL); + if (is_on) + ctrl &= ~USBA_DETACH; + else + ctrl |= USBA_DETACH; + usba_writel(udc, CTRL, ctrl); + spin_unlock_irqrestore(&udc->lock, flags); + + return 0; +} + static int atmel_usba_start(struct usb_gadget *gadget, struct usb_gadget_driver *driver) { @@ -1960,9 +2029,7 @@ static int atmel_usba_stop(struct usb_gadget *gadget) if (udc->vbus_pin) disable_irq(gpiod_to_irq(udc->vbus_pin)); - if (fifo_mode == 0) - udc->configured_ep = 1; - + udc->suspended = false; usba_stop(udc); udc->driver = NULL; @@ -1991,48 +2058,116 @@ static const struct usba_udc_errata at91sam9g45_errata = { .pulse_bias = at91sam9g45_pulse_bias, }; +static const struct usba_ep_config ep_config_sam9[] = { + { .nr_banks = 1 }, /* ep 0 */ + { .nr_banks = 2, .can_dma = 1, .can_isoc = 1 }, /* ep 1 */ + { .nr_banks = 2, .can_dma = 1, .can_isoc = 1 }, /* ep 2 */ + { .nr_banks = 3, .can_dma = 1 }, /* ep 3 */ + { .nr_banks = 3, .can_dma = 1 }, /* ep 4 */ + { .nr_banks = 3, .can_dma = 1, .can_isoc = 1 }, /* ep 5 */ + { .nr_banks = 3, .can_dma = 1, .can_isoc = 1 }, /* ep 6 */ +}; + +static const struct usba_ep_config ep_config_sama5[] = { + { .nr_banks = 1 }, /* ep 0 */ + { .nr_banks = 3, .can_dma = 1, .can_isoc = 1 }, /* ep 1 */ + { .nr_banks = 3, .can_dma = 1, .can_isoc = 1 }, /* ep 2 */ + { .nr_banks = 2, .can_dma = 1, .can_isoc = 1 }, /* ep 3 */ + { .nr_banks = 2, .can_dma = 1, .can_isoc = 1 }, /* ep 4 */ + { .nr_banks = 2, .can_dma = 1, .can_isoc = 1 }, /* ep 5 */ + { .nr_banks = 2, .can_dma = 1, .can_isoc = 1 }, /* ep 6 */ + { .nr_banks = 2, .can_dma = 1, .can_isoc = 1 }, /* ep 7 */ + { .nr_banks = 2, .can_isoc = 1 }, /* ep 8 */ + { .nr_banks = 2, .can_isoc = 1 }, /* ep 9 */ + { .nr_banks = 2, .can_isoc = 1 }, /* ep 10 */ + { .nr_banks = 2, .can_isoc = 1 }, /* ep 11 */ + { .nr_banks = 2, .can_isoc = 1 }, /* ep 12 */ + { .nr_banks = 2, .can_isoc = 1 }, /* ep 13 */ + { .nr_banks = 2, .can_isoc = 1 }, /* ep 14 */ + { .nr_banks = 2, .can_isoc = 1 }, /* ep 15 */ +}; + +static const struct usba_udc_config udc_at91sam9rl_cfg = { + .errata = &at91sam9rl_errata, + .config = ep_config_sam9, + .num_ep = ARRAY_SIZE(ep_config_sam9), + .ep_prealloc = true, +}; + +static const struct usba_udc_config udc_at91sam9g45_cfg = { + .errata = &at91sam9g45_errata, + .config = ep_config_sam9, + .num_ep = ARRAY_SIZE(ep_config_sam9), + .ep_prealloc = true, +}; + +static const struct usba_udc_config udc_sama5d3_cfg = { + .config = ep_config_sama5, + .num_ep = ARRAY_SIZE(ep_config_sama5), + .ep_prealloc = true, +}; + +static const struct usba_udc_config udc_sam9x60_cfg = { + .num_ep = ARRAY_SIZE(ep_config_sam9), + .config = ep_config_sam9, + .ep_prealloc = false, +}; + static const struct of_device_id atmel_udc_dt_ids[] = { - { .compatible = "atmel,at91sam9rl-udc", .data = &at91sam9rl_errata }, - { .compatible = "atmel,at91sam9g45-udc", .data = &at91sam9g45_errata }, - { .compatible = "atmel,sama5d3-udc" }, + { .compatible = "atmel,at91sam9rl-udc", .data = &udc_at91sam9rl_cfg }, + { .compatible = "atmel,at91sam9g45-udc", .data = &udc_at91sam9g45_cfg }, + { .compatible = "atmel,sama5d3-udc", .data = &udc_sama5d3_cfg }, + { .compatible = "microchip,sam9x60-udc", .data = &udc_sam9x60_cfg }, { /* sentinel */ } }; MODULE_DEVICE_TABLE(of, atmel_udc_dt_ids); +static const struct of_device_id atmel_pmc_dt_ids[] = { + { .compatible = "atmel,at91sam9g45-pmc" }, + { .compatible = "atmel,at91sam9rl-pmc" }, + { .compatible = "atmel,at91sam9x5-pmc" }, + { /* sentinel */ } +}; + static struct usba_ep * atmel_udc_of_init(struct platform_device *pdev, struct usba_udc *udc) { - u32 val; struct device_node *np = pdev->dev.of_node; const struct of_device_id *match; struct device_node *pp; int i, ret; struct usba_ep *eps, *ep; + const struct usba_udc_config *udc_config; match = of_match_node(atmel_udc_dt_ids, np); if (!match) return ERR_PTR(-EINVAL); - udc->errata = match->data; - udc->pmc = syscon_regmap_lookup_by_compatible("atmel,at91sam9g45-pmc"); - if (IS_ERR(udc->pmc)) - udc->pmc = syscon_regmap_lookup_by_compatible("atmel,at91sam9rl-pmc"); - if (IS_ERR(udc->pmc)) - udc->pmc = syscon_regmap_lookup_by_compatible("atmel,at91sam9x5-pmc"); - if (udc->errata && IS_ERR(udc->pmc)) - return ERR_CAST(udc->pmc); + udc_config = match->data; + udc->ep_prealloc = udc_config->ep_prealloc; + udc->errata = udc_config->errata; + if (udc->errata) { + pp = of_find_matching_node_and_match(NULL, atmel_pmc_dt_ids, + NULL); + if (!pp) + return ERR_PTR(-ENODEV); + + udc->pmc = syscon_node_to_regmap(pp); + of_node_put(pp); + if (IS_ERR(udc->pmc)) + return ERR_CAST(udc->pmc); + } udc->num_ep = 0; udc->vbus_pin = devm_gpiod_get_optional(&pdev->dev, "atmel,vbus", GPIOD_IN); + if (IS_ERR(udc->vbus_pin)) + return ERR_CAST(udc->vbus_pin); if (fifo_mode == 0) { - pp = NULL; - while ((pp = of_get_next_child(np, pp))) - udc->num_ep++; - udc->configured_ep = 1; + udc->num_ep = udc_config->num_ep; } else { udc->num_ep = usba_config_fifo_table(udc); } @@ -2046,54 +2181,39 @@ static struct usba_ep * atmel_udc_of_init(struct platform_device *pdev, INIT_LIST_HEAD(&eps[0].ep.ep_list); - pp = NULL; i = 0; - while ((pp = of_get_next_child(np, pp)) && i < udc->num_ep) { + while (i < udc->num_ep) { + const struct usba_ep_config *ep_cfg = &udc_config->config[i]; + ep = &eps[i]; - ret = of_property_read_u32(pp, "reg", &val); - if (ret) { - dev_err(&pdev->dev, "of_probe: reg error(%d)\n", ret); - goto err; - } - ep->index = fifo_mode ? udc->fifo_cfg[i].hw_ep_num : val; + ep->index = fifo_mode ? udc->fifo_cfg[i].hw_ep_num : i; + + /* Only the first EP is 64 bytes */ + if (ep->index == 0) + ep->fifo_size = 64; + else + ep->fifo_size = 1024; - ret = of_property_read_u32(pp, "atmel,fifo-size", &val); - if (ret) { - dev_err(&pdev->dev, "of_probe: fifo-size error(%d)\n", ret); - goto err; - } if (fifo_mode) { - if (val < udc->fifo_cfg[i].fifo_size) { + if (ep->fifo_size < udc->fifo_cfg[i].fifo_size) dev_warn(&pdev->dev, - "Using max fifo-size value from DT\n"); - ep->fifo_size = val; - } else { + "Using default max fifo-size value\n"); + else ep->fifo_size = udc->fifo_cfg[i].fifo_size; - } - } else { - ep->fifo_size = val; } - ret = of_property_read_u32(pp, "atmel,nb-banks", &val); - if (ret) { - dev_err(&pdev->dev, "of_probe: nb-banks error(%d)\n", ret); - goto err; - } + ep->nr_banks = ep_cfg->nr_banks; if (fifo_mode) { - if (val < udc->fifo_cfg[i].nr_banks) { + if (ep->nr_banks < udc->fifo_cfg[i].nr_banks) dev_warn(&pdev->dev, - "Using max nb-banks value from DT\n"); - ep->nr_banks = val; - } else { + "Using default max nb-banks value\n"); + else ep->nr_banks = udc->fifo_cfg[i].nr_banks; - } - } else { - ep->nr_banks = val; } - ep->can_dma = of_property_read_bool(pp, "atmel,can-dma"); - ep->can_isoc = of_property_read_bool(pp, "atmel,can-isoc"); + ep->can_dma = ep_cfg->can_dma; + ep->can_isoc = ep_cfg->can_isoc; sprintf(ep->name, "ep%d", ep->index); ep->ep.name = ep->name; @@ -2163,15 +2283,13 @@ static int usba_udc_probe(struct platform_device *pdev) udc->gadget = usba_gadget_template; INIT_LIST_HEAD(&udc->gadget.ep_list); - res = platform_get_resource(pdev, IORESOURCE_MEM, CTRL_IOMEM_ID); - udc->regs = devm_ioremap_resource(&pdev->dev, res); + udc->regs = devm_platform_get_and_ioremap_resource(pdev, CTRL_IOMEM_ID, &res); if (IS_ERR(udc->regs)) return PTR_ERR(udc->regs); dev_info(&pdev->dev, "MMIO registers at %pR mapped at %p\n", res, udc->regs); - res = platform_get_resource(pdev, IORESOURCE_MEM, FIFO_IOMEM_ID); - udc->fifo = devm_ioremap_resource(&pdev->dev, res); + udc->fifo = devm_platform_get_and_ioremap_resource(pdev, FIFO_IOMEM_ID, &res); if (IS_ERR(udc->fifo)) return PTR_ERR(udc->fifo); dev_info(&pdev->dev, "FIFO at %pR mapped at %p\n", res, udc->fifo); @@ -2247,7 +2365,7 @@ static int usba_udc_probe(struct platform_device *pdev) return 0; } -static int usba_udc_remove(struct platform_device *pdev) +static void usba_udc_remove(struct platform_device *pdev) { struct usba_udc *udc; int i; @@ -2260,8 +2378,6 @@ static int usba_udc_remove(struct platform_device *pdev) for (i = 1; i < udc->num_ep; i++) usba_ep_cleanup_debugfs(&udc->usba_ep[i]); usba_cleanup_debugfs(udc); - - return 0; } #ifdef CONFIG_PM_SLEEP @@ -2276,6 +2392,7 @@ static int usba_udc_suspend(struct device *dev) mutex_lock(&udc->vbus_mutex); if (!device_may_wakeup(dev)) { + udc->suspended = false; usba_stop(udc); goto out; } @@ -2285,10 +2402,13 @@ static int usba_udc_suspend(struct device *dev) * to request vbus irq, assuming always on. */ if (udc->vbus_pin) { + /* FIXME: right to stop here...??? */ usba_stop(udc); enable_irq_wake(gpiod_to_irq(udc->vbus_pin)); } + enable_irq_wake(udc->irq); + out: mutex_unlock(&udc->vbus_mutex); return 0; @@ -2302,8 +2422,12 @@ static int usba_udc_resume(struct device *dev) if (!udc->driver) return 0; - if (device_may_wakeup(dev) && udc->vbus_pin) - disable_irq_wake(gpiod_to_irq(udc->vbus_pin)); + if (device_may_wakeup(dev)) { + if (udc->vbus_pin) + disable_irq_wake(gpiod_to_irq(udc->vbus_pin)); + + disable_irq_wake(udc->irq); + } /* If Vbus is present, enable the controller and wait for reset */ mutex_lock(&udc->vbus_mutex); @@ -2319,6 +2443,7 @@ static int usba_udc_resume(struct device *dev) static SIMPLE_DEV_PM_OPS(usba_udc_pm_ops, usba_udc_suspend, usba_udc_resume); static struct platform_driver udc_driver = { + .probe = usba_udc_probe, .remove = usba_udc_remove, .driver = { .name = "atmel_usba_udc", @@ -2326,8 +2451,7 @@ static struct platform_driver udc_driver = { .of_match_table = atmel_udc_dt_ids, }, }; - -module_platform_driver_probe(udc_driver, usba_udc_probe); +module_platform_driver(udc_driver); MODULE_DESCRIPTION("Atmel USBA UDC driver"); MODULE_AUTHOR("Haavard Skinnemoen (Atmel)"); |
