| .. | .. |
|---|
| 18 | 18 | #include <linux/platform_device.h> |
|---|
| 19 | 19 | #include <linux/regmap.h> |
|---|
| 20 | 20 | #include <linux/ctype.h> |
|---|
| 21 | +#include <linux/usb.h> |
|---|
| 21 | 22 | #include <linux/usb/ch9.h> |
|---|
| 22 | 23 | #include <linux/usb/gadget.h> |
|---|
| 23 | 24 | #include <linux/delay.h> |
|---|
| .. | .. |
|---|
| 88 | 89 | size_t len, remaining, actual = 0; |
|---|
| 89 | 90 | char tmpbuf[38]; |
|---|
| 90 | 91 | |
|---|
| 91 | | - if (!access_ok(VERIFY_WRITE, buf, nbytes)) |
|---|
| 92 | + if (!access_ok(buf, nbytes)) |
|---|
| 92 | 93 | return -EFAULT; |
|---|
| 93 | 94 | |
|---|
| 94 | 95 | inode_lock(file_inode(file)); |
|---|
| .. | .. |
|---|
| 184 | 185 | return 0; |
|---|
| 185 | 186 | } |
|---|
| 186 | 187 | |
|---|
| 187 | | -const struct file_operations queue_dbg_fops = { |
|---|
| 188 | +static const struct file_operations queue_dbg_fops = { |
|---|
| 188 | 189 | .owner = THIS_MODULE, |
|---|
| 189 | 190 | .open = queue_dbg_open, |
|---|
| 190 | 191 | .llseek = no_llseek, |
|---|
| .. | .. |
|---|
| 192 | 193 | .release = queue_dbg_release, |
|---|
| 193 | 194 | }; |
|---|
| 194 | 195 | |
|---|
| 195 | | -const struct file_operations regs_dbg_fops = { |
|---|
| 196 | +static const struct file_operations regs_dbg_fops = { |
|---|
| 196 | 197 | .owner = THIS_MODULE, |
|---|
| 197 | 198 | .open = regs_dbg_open, |
|---|
| 198 | 199 | .llseek = generic_file_llseek, |
|---|
| .. | .. |
|---|
| 226 | 227 | struct dentry *root; |
|---|
| 227 | 228 | struct resource *regs_resource; |
|---|
| 228 | 229 | |
|---|
| 229 | | - root = debugfs_create_dir(udc->gadget.name, NULL); |
|---|
| 230 | + root = debugfs_create_dir(udc->gadget.name, usb_debug_root); |
|---|
| 230 | 231 | udc->debugfs_root = root; |
|---|
| 231 | 232 | |
|---|
| 232 | 233 | regs_resource = platform_get_resource(udc->pdev, IORESOURCE_MEM, |
|---|
| .. | .. |
|---|
| 327 | 328 | switch (fifo_mode) { |
|---|
| 328 | 329 | default: |
|---|
| 329 | 330 | fifo_mode = 0; |
|---|
| 331 | + fallthrough; |
|---|
| 330 | 332 | case 0: |
|---|
| 331 | 333 | udc->fifo_cfg = NULL; |
|---|
| 332 | 334 | n = 0; |
|---|
| .. | .. |
|---|
| 358 | 360 | return udc->int_enb_cache; |
|---|
| 359 | 361 | } |
|---|
| 360 | 362 | |
|---|
| 361 | | -static inline void usba_int_enb_set(struct usba_udc *udc, u32 val) |
|---|
| 363 | +static inline void usba_int_enb_set(struct usba_udc *udc, u32 mask) |
|---|
| 362 | 364 | { |
|---|
| 365 | + u32 val; |
|---|
| 366 | + |
|---|
| 367 | + val = udc->int_enb_cache | mask; |
|---|
| 368 | + usba_writel(udc, INT_ENB, val); |
|---|
| 369 | + udc->int_enb_cache = val; |
|---|
| 370 | +} |
|---|
| 371 | + |
|---|
| 372 | +static inline void usba_int_enb_clear(struct usba_udc *udc, u32 mask) |
|---|
| 373 | +{ |
|---|
| 374 | + u32 val; |
|---|
| 375 | + |
|---|
| 376 | + val = udc->int_enb_cache & ~mask; |
|---|
| 363 | 377 | usba_writel(udc, INT_ENB, val); |
|---|
| 364 | 378 | udc->int_enb_cache = val; |
|---|
| 365 | 379 | } |
|---|
| .. | .. |
|---|
| 631 | 645 | if (ep->can_dma) { |
|---|
| 632 | 646 | u32 ctrl; |
|---|
| 633 | 647 | |
|---|
| 634 | | - usba_int_enb_set(udc, usba_int_enb_get(udc) | |
|---|
| 635 | | - USBA_BF(EPT_INT, 1 << ep->index) | |
|---|
| 648 | + usba_int_enb_set(udc, USBA_BF(EPT_INT, 1 << ep->index) | |
|---|
| 636 | 649 | USBA_BF(DMA_INT, 1 << ep->index)); |
|---|
| 637 | 650 | ctrl = USBA_AUTO_VALID | USBA_INTDIS_DMA; |
|---|
| 638 | 651 | usba_ep_writel(ep, CTL_ENB, ctrl); |
|---|
| 639 | 652 | } else { |
|---|
| 640 | | - usba_int_enb_set(udc, usba_int_enb_get(udc) | |
|---|
| 641 | | - USBA_BF(EPT_INT, 1 << ep->index)); |
|---|
| 653 | + usba_int_enb_set(udc, USBA_BF(EPT_INT, 1 << ep->index)); |
|---|
| 642 | 654 | } |
|---|
| 643 | 655 | |
|---|
| 644 | 656 | spin_unlock_irqrestore(&udc->lock, flags); |
|---|
| .. | .. |
|---|
| 664 | 676 | |
|---|
| 665 | 677 | if (!ep->ep.desc) { |
|---|
| 666 | 678 | spin_unlock_irqrestore(&udc->lock, flags); |
|---|
| 667 | | - /* REVISIT because this driver disables endpoints in |
|---|
| 668 | | - * reset_all_endpoints() before calling disconnect(), |
|---|
| 669 | | - * most gadget drivers would trigger this non-error ... |
|---|
| 670 | | - */ |
|---|
| 671 | | - if (udc->gadget.speed != USB_SPEED_UNKNOWN) |
|---|
| 672 | | - DBG(DBG_ERR, "ep_disable: %s not enabled\n", |
|---|
| 673 | | - ep->ep.name); |
|---|
| 679 | + DBG(DBG_ERR, "ep_disable: %s not enabled\n", ep->ep.name); |
|---|
| 674 | 680 | return -EINVAL; |
|---|
| 675 | 681 | } |
|---|
| 676 | 682 | ep->ep.desc = NULL; |
|---|
| .. | .. |
|---|
| 682 | 688 | usba_dma_readl(ep, STATUS); |
|---|
| 683 | 689 | } |
|---|
| 684 | 690 | usba_ep_writel(ep, CTL_DIS, USBA_EPT_ENABLE); |
|---|
| 685 | | - usba_int_enb_set(udc, usba_int_enb_get(udc) & |
|---|
| 686 | | - ~USBA_BF(EPT_INT, 1 << ep->index)); |
|---|
| 691 | + usba_int_enb_clear(udc, USBA_BF(EPT_INT, 1 << ep->index)); |
|---|
| 687 | 692 | |
|---|
| 688 | 693 | request_complete_list(ep, &req_list, -ESHUTDOWN); |
|---|
| 689 | 694 | |
|---|
| .. | .. |
|---|
| 1023 | 1028 | return 0; |
|---|
| 1024 | 1029 | } |
|---|
| 1025 | 1030 | |
|---|
| 1031 | +static int atmel_usba_pullup(struct usb_gadget *gadget, int is_on); |
|---|
| 1026 | 1032 | static int atmel_usba_start(struct usb_gadget *gadget, |
|---|
| 1027 | 1033 | struct usb_gadget_driver *driver); |
|---|
| 1028 | 1034 | static int atmel_usba_stop(struct usb_gadget *gadget); |
|---|
| .. | .. |
|---|
| 1050 | 1056 | |
|---|
| 1051 | 1057 | switch (usb_endpoint_type(desc)) { |
|---|
| 1052 | 1058 | case USB_ENDPOINT_XFER_CONTROL: |
|---|
| 1059 | + ep->nr_banks = 1; |
|---|
| 1053 | 1060 | break; |
|---|
| 1054 | 1061 | |
|---|
| 1055 | 1062 | case USB_ENDPOINT_XFER_ISOC: |
|---|
| 1056 | 1063 | ep->fifo_size = 1024; |
|---|
| 1057 | | - ep->nr_banks = 2; |
|---|
| 1064 | + if (ep->udc->ep_prealloc) |
|---|
| 1065 | + ep->nr_banks = 2; |
|---|
| 1058 | 1066 | break; |
|---|
| 1059 | 1067 | |
|---|
| 1060 | 1068 | case USB_ENDPOINT_XFER_BULK: |
|---|
| 1061 | 1069 | ep->fifo_size = 512; |
|---|
| 1062 | | - ep->nr_banks = 1; |
|---|
| 1070 | + if (ep->udc->ep_prealloc) |
|---|
| 1071 | + ep->nr_banks = 1; |
|---|
| 1063 | 1072 | break; |
|---|
| 1064 | 1073 | |
|---|
| 1065 | 1074 | case USB_ENDPOINT_XFER_INT: |
|---|
| .. | .. |
|---|
| 1069 | 1078 | else |
|---|
| 1070 | 1079 | ep->fifo_size = |
|---|
| 1071 | 1080 | roundup_pow_of_two(le16_to_cpu(desc->wMaxPacketSize)); |
|---|
| 1072 | | - ep->nr_banks = 1; |
|---|
| 1081 | + if (ep->udc->ep_prealloc) |
|---|
| 1082 | + ep->nr_banks = 1; |
|---|
| 1073 | 1083 | break; |
|---|
| 1074 | 1084 | } |
|---|
| 1075 | 1085 | |
|---|
| .. | .. |
|---|
| 1085 | 1095 | USBA_BF(EPT_SIZE, fls(ep->fifo_size - 1) - 3); |
|---|
| 1086 | 1096 | |
|---|
| 1087 | 1097 | ep->ept_cfg |= USBA_BF(BK_NUMBER, ep->nr_banks); |
|---|
| 1088 | | - |
|---|
| 1089 | | - ep->udc->configured_ep++; |
|---|
| 1090 | 1098 | } |
|---|
| 1091 | 1099 | |
|---|
| 1092 | 1100 | return _ep; |
|---|
| .. | .. |
|---|
| 1096 | 1104 | .get_frame = usba_udc_get_frame, |
|---|
| 1097 | 1105 | .wakeup = usba_udc_wakeup, |
|---|
| 1098 | 1106 | .set_selfpowered = usba_udc_set_selfpowered, |
|---|
| 1107 | + .pullup = atmel_usba_pullup, |
|---|
| 1099 | 1108 | .udc_start = atmel_usba_start, |
|---|
| 1100 | 1109 | .udc_stop = atmel_usba_stop, |
|---|
| 1101 | 1110 | .match_ep = atmel_usba_match_ep, |
|---|
| .. | .. |
|---|
| 1111 | 1120 | .bInterval = 1, |
|---|
| 1112 | 1121 | }; |
|---|
| 1113 | 1122 | |
|---|
| 1114 | | -static struct usb_gadget usba_gadget_template = { |
|---|
| 1123 | +static const struct usb_gadget usba_gadget_template = { |
|---|
| 1115 | 1124 | .ops = &usba_udc_ops, |
|---|
| 1116 | 1125 | .max_speed = USB_SPEED_HIGH, |
|---|
| 1117 | 1126 | .name = "atmel_usba_udc", |
|---|
| .. | .. |
|---|
| 1696 | 1705 | } |
|---|
| 1697 | 1706 | } |
|---|
| 1698 | 1707 | |
|---|
| 1708 | +static int start_clock(struct usba_udc *udc); |
|---|
| 1709 | +static void stop_clock(struct usba_udc *udc); |
|---|
| 1710 | + |
|---|
| 1699 | 1711 | static irqreturn_t usba_udc_irq(int irq, void *devid) |
|---|
| 1700 | 1712 | { |
|---|
| 1701 | 1713 | struct usba_udc *udc = devid; |
|---|
| .. | .. |
|---|
| 1710 | 1722 | DBG(DBG_INT, "irq, status=%#08x\n", status); |
|---|
| 1711 | 1723 | |
|---|
| 1712 | 1724 | if (status & USBA_DET_SUSPEND) { |
|---|
| 1725 | + usba_writel(udc, INT_CLR, USBA_DET_SUSPEND|USBA_WAKE_UP); |
|---|
| 1726 | + usba_int_enb_set(udc, USBA_WAKE_UP); |
|---|
| 1727 | + usba_int_enb_clear(udc, USBA_DET_SUSPEND); |
|---|
| 1728 | + udc->suspended = true; |
|---|
| 1713 | 1729 | toggle_bias(udc, 0); |
|---|
| 1714 | | - usba_writel(udc, INT_CLR, USBA_DET_SUSPEND); |
|---|
| 1715 | | - usba_int_enb_set(udc, int_enb | USBA_WAKE_UP); |
|---|
| 1716 | 1730 | udc->bias_pulse_needed = true; |
|---|
| 1731 | + stop_clock(udc); |
|---|
| 1717 | 1732 | DBG(DBG_BUS, "Suspend detected\n"); |
|---|
| 1718 | 1733 | if (udc->gadget.speed != USB_SPEED_UNKNOWN |
|---|
| 1719 | 1734 | && udc->driver && udc->driver->suspend) { |
|---|
| .. | .. |
|---|
| 1724 | 1739 | } |
|---|
| 1725 | 1740 | |
|---|
| 1726 | 1741 | if (status & USBA_WAKE_UP) { |
|---|
| 1742 | + start_clock(udc); |
|---|
| 1727 | 1743 | toggle_bias(udc, 1); |
|---|
| 1728 | 1744 | usba_writel(udc, INT_CLR, USBA_WAKE_UP); |
|---|
| 1729 | | - usba_int_enb_set(udc, int_enb & ~USBA_WAKE_UP); |
|---|
| 1730 | 1745 | DBG(DBG_BUS, "Wake Up CPU detected\n"); |
|---|
| 1731 | 1746 | } |
|---|
| 1732 | 1747 | |
|---|
| 1733 | 1748 | if (status & USBA_END_OF_RESUME) { |
|---|
| 1749 | + udc->suspended = false; |
|---|
| 1734 | 1750 | usba_writel(udc, INT_CLR, USBA_END_OF_RESUME); |
|---|
| 1751 | + usba_int_enb_clear(udc, USBA_WAKE_UP); |
|---|
| 1752 | + usba_int_enb_set(udc, USBA_DET_SUSPEND); |
|---|
| 1735 | 1753 | generate_bias_pulse(udc); |
|---|
| 1736 | 1754 | DBG(DBG_BUS, "Resume detected\n"); |
|---|
| 1737 | 1755 | if (udc->gadget.speed != USB_SPEED_UNKNOWN |
|---|
| .. | .. |
|---|
| 1746 | 1764 | if (dma_status) { |
|---|
| 1747 | 1765 | int i; |
|---|
| 1748 | 1766 | |
|---|
| 1767 | + usba_int_enb_set(udc, USBA_DET_SUSPEND); |
|---|
| 1768 | + |
|---|
| 1749 | 1769 | for (i = 1; i <= USBA_NR_DMAS; i++) |
|---|
| 1750 | 1770 | if (dma_status & (1 << i)) |
|---|
| 1751 | 1771 | usba_dma_irq(udc, &udc->usba_ep[i]); |
|---|
| .. | .. |
|---|
| 1754 | 1774 | ep_status = USBA_BFEXT(EPT_INT, status); |
|---|
| 1755 | 1775 | if (ep_status) { |
|---|
| 1756 | 1776 | int i; |
|---|
| 1777 | + |
|---|
| 1778 | + usba_int_enb_set(udc, USBA_DET_SUSPEND); |
|---|
| 1757 | 1779 | |
|---|
| 1758 | 1780 | for (i = 0; i < udc->num_ep; i++) |
|---|
| 1759 | 1781 | if (ep_status & (1 << i)) { |
|---|
| .. | .. |
|---|
| 1766 | 1788 | |
|---|
| 1767 | 1789 | if (status & USBA_END_OF_RESET) { |
|---|
| 1768 | 1790 | struct usba_ep *ep0, *ep; |
|---|
| 1769 | | - int i, n; |
|---|
| 1791 | + int i; |
|---|
| 1770 | 1792 | |
|---|
| 1771 | | - usba_writel(udc, INT_CLR, USBA_END_OF_RESET); |
|---|
| 1793 | + usba_writel(udc, INT_CLR, |
|---|
| 1794 | + USBA_END_OF_RESET|USBA_END_OF_RESUME |
|---|
| 1795 | + |USBA_DET_SUSPEND|USBA_WAKE_UP); |
|---|
| 1772 | 1796 | generate_bias_pulse(udc); |
|---|
| 1773 | 1797 | reset_all_endpoints(udc); |
|---|
| 1774 | 1798 | |
|---|
| .. | .. |
|---|
| 1795 | 1819 | | USBA_BF(BK_NUMBER, USBA_BK_NUMBER_ONE))); |
|---|
| 1796 | 1820 | usba_ep_writel(ep0, CTL_ENB, |
|---|
| 1797 | 1821 | USBA_EPT_ENABLE | USBA_RX_SETUP); |
|---|
| 1798 | | - usba_int_enb_set(udc, int_enb | USBA_BF(EPT_INT, 1) | |
|---|
| 1822 | + |
|---|
| 1823 | + /* If we get reset while suspended... */ |
|---|
| 1824 | + udc->suspended = false; |
|---|
| 1825 | + usba_int_enb_clear(udc, USBA_WAKE_UP); |
|---|
| 1826 | + |
|---|
| 1827 | + usba_int_enb_set(udc, USBA_BF(EPT_INT, 1) | |
|---|
| 1799 | 1828 | USBA_DET_SUSPEND | USBA_END_OF_RESUME); |
|---|
| 1800 | 1829 | |
|---|
| 1801 | 1830 | /* |
|---|
| .. | .. |
|---|
| 1807 | 1836 | "ODD: EP0 configuration is invalid!\n"); |
|---|
| 1808 | 1837 | |
|---|
| 1809 | 1838 | /* Preallocate other endpoints */ |
|---|
| 1810 | | - n = fifo_mode ? udc->num_ep : udc->configured_ep; |
|---|
| 1811 | | - for (i = 1; i < n; i++) { |
|---|
| 1839 | + for (i = 1; i < udc->num_ep; i++) { |
|---|
| 1812 | 1840 | ep = &udc->usba_ep[i]; |
|---|
| 1813 | | - usba_ep_writel(ep, CFG, ep->ept_cfg); |
|---|
| 1814 | | - if (!(usba_ep_readl(ep, CFG) & USBA_EPT_MAPPED)) |
|---|
| 1815 | | - dev_err(&udc->pdev->dev, |
|---|
| 1816 | | - "ODD: EP%d configuration is invalid!\n", i); |
|---|
| 1841 | + if (ep->ep.claimed) { |
|---|
| 1842 | + usba_ep_writel(ep, CFG, ep->ept_cfg); |
|---|
| 1843 | + if (!(usba_ep_readl(ep, CFG) & USBA_EPT_MAPPED)) |
|---|
| 1844 | + dev_err(&udc->pdev->dev, |
|---|
| 1845 | + "ODD: EP%d configuration is invalid!\n", i); |
|---|
| 1846 | + } |
|---|
| 1817 | 1847 | } |
|---|
| 1818 | 1848 | } |
|---|
| 1819 | 1849 | |
|---|
| .. | .. |
|---|
| 1828 | 1858 | |
|---|
| 1829 | 1859 | if (udc->clocked) |
|---|
| 1830 | 1860 | return 0; |
|---|
| 1861 | + |
|---|
| 1862 | + pm_stay_awake(&udc->pdev->dev); |
|---|
| 1831 | 1863 | |
|---|
| 1832 | 1864 | ret = clk_prepare_enable(udc->pclk); |
|---|
| 1833 | 1865 | if (ret) |
|---|
| .. | .. |
|---|
| 1851 | 1883 | clk_disable_unprepare(udc->pclk); |
|---|
| 1852 | 1884 | |
|---|
| 1853 | 1885 | udc->clocked = false; |
|---|
| 1886 | + |
|---|
| 1887 | + pm_relax(&udc->pdev->dev); |
|---|
| 1854 | 1888 | } |
|---|
| 1855 | 1889 | |
|---|
| 1856 | 1890 | static int usba_start(struct usba_udc *udc) |
|---|
| .. | .. |
|---|
| 1862 | 1896 | if (ret) |
|---|
| 1863 | 1897 | return ret; |
|---|
| 1864 | 1898 | |
|---|
| 1899 | + if (udc->suspended) |
|---|
| 1900 | + return 0; |
|---|
| 1901 | + |
|---|
| 1865 | 1902 | spin_lock_irqsave(&udc->lock, flags); |
|---|
| 1866 | 1903 | toggle_bias(udc, 1); |
|---|
| 1867 | 1904 | usba_writel(udc, CTRL, USBA_ENABLE_MASK); |
|---|
| 1905 | + /* Clear all requested and pending interrupts... */ |
|---|
| 1906 | + usba_writel(udc, INT_ENB, 0); |
|---|
| 1907 | + udc->int_enb_cache = 0; |
|---|
| 1908 | + usba_writel(udc, INT_CLR, |
|---|
| 1909 | + USBA_END_OF_RESET|USBA_END_OF_RESUME |
|---|
| 1910 | + |USBA_DET_SUSPEND|USBA_WAKE_UP); |
|---|
| 1911 | + /* ...and enable just 'reset' IRQ to get us started */ |
|---|
| 1868 | 1912 | usba_int_enb_set(udc, USBA_END_OF_RESET); |
|---|
| 1869 | 1913 | spin_unlock_irqrestore(&udc->lock, flags); |
|---|
| 1870 | 1914 | |
|---|
| .. | .. |
|---|
| 1874 | 1918 | static void usba_stop(struct usba_udc *udc) |
|---|
| 1875 | 1919 | { |
|---|
| 1876 | 1920 | unsigned long flags; |
|---|
| 1921 | + |
|---|
| 1922 | + if (udc->suspended) |
|---|
| 1923 | + return; |
|---|
| 1877 | 1924 | |
|---|
| 1878 | 1925 | spin_lock_irqsave(&udc->lock, flags); |
|---|
| 1879 | 1926 | udc->gadget.speed = USB_SPEED_UNKNOWN; |
|---|
| .. | .. |
|---|
| 1902 | 1949 | if (vbus) { |
|---|
| 1903 | 1950 | usba_start(udc); |
|---|
| 1904 | 1951 | } else { |
|---|
| 1905 | | - usba_stop(udc); |
|---|
| 1906 | | - |
|---|
| 1952 | + udc->suspended = false; |
|---|
| 1907 | 1953 | if (udc->driver->disconnect) |
|---|
| 1908 | 1954 | udc->driver->disconnect(&udc->gadget); |
|---|
| 1955 | + |
|---|
| 1956 | + usba_stop(udc); |
|---|
| 1909 | 1957 | } |
|---|
| 1910 | 1958 | udc->vbus_prev = vbus; |
|---|
| 1911 | 1959 | } |
|---|
| 1912 | 1960 | |
|---|
| 1913 | 1961 | mutex_unlock(&udc->vbus_mutex); |
|---|
| 1914 | 1962 | return IRQ_HANDLED; |
|---|
| 1963 | +} |
|---|
| 1964 | + |
|---|
| 1965 | +static int atmel_usba_pullup(struct usb_gadget *gadget, int is_on) |
|---|
| 1966 | +{ |
|---|
| 1967 | + struct usba_udc *udc = container_of(gadget, struct usba_udc, gadget); |
|---|
| 1968 | + unsigned long flags; |
|---|
| 1969 | + u32 ctrl; |
|---|
| 1970 | + |
|---|
| 1971 | + spin_lock_irqsave(&udc->lock, flags); |
|---|
| 1972 | + ctrl = usba_readl(udc, CTRL); |
|---|
| 1973 | + if (is_on) |
|---|
| 1974 | + ctrl &= ~USBA_DETACH; |
|---|
| 1975 | + else |
|---|
| 1976 | + ctrl |= USBA_DETACH; |
|---|
| 1977 | + usba_writel(udc, CTRL, ctrl); |
|---|
| 1978 | + spin_unlock_irqrestore(&udc->lock, flags); |
|---|
| 1979 | + |
|---|
| 1980 | + return 0; |
|---|
| 1915 | 1981 | } |
|---|
| 1916 | 1982 | |
|---|
| 1917 | 1983 | static int atmel_usba_start(struct usb_gadget *gadget, |
|---|
| .. | .. |
|---|
| 1962 | 2028 | if (udc->vbus_pin) |
|---|
| 1963 | 2029 | disable_irq(gpiod_to_irq(udc->vbus_pin)); |
|---|
| 1964 | 2030 | |
|---|
| 1965 | | - if (fifo_mode == 0) |
|---|
| 1966 | | - udc->configured_ep = 1; |
|---|
| 1967 | | - |
|---|
| 2031 | + udc->suspended = false; |
|---|
| 1968 | 2032 | usba_stop(udc); |
|---|
| 1969 | 2033 | |
|---|
| 1970 | 2034 | udc->driver = NULL; |
|---|
| .. | .. |
|---|
| 1993 | 2057 | .pulse_bias = at91sam9g45_pulse_bias, |
|---|
| 1994 | 2058 | }; |
|---|
| 1995 | 2059 | |
|---|
| 2060 | +static const struct usba_ep_config ep_config_sam9[] __initconst = { |
|---|
| 2061 | + { .nr_banks = 1 }, /* ep 0 */ |
|---|
| 2062 | + { .nr_banks = 2, .can_dma = 1, .can_isoc = 1 }, /* ep 1 */ |
|---|
| 2063 | + { .nr_banks = 2, .can_dma = 1, .can_isoc = 1 }, /* ep 2 */ |
|---|
| 2064 | + { .nr_banks = 3, .can_dma = 1 }, /* ep 3 */ |
|---|
| 2065 | + { .nr_banks = 3, .can_dma = 1 }, /* ep 4 */ |
|---|
| 2066 | + { .nr_banks = 3, .can_dma = 1, .can_isoc = 1 }, /* ep 5 */ |
|---|
| 2067 | + { .nr_banks = 3, .can_dma = 1, .can_isoc = 1 }, /* ep 6 */ |
|---|
| 2068 | +}; |
|---|
| 2069 | + |
|---|
| 2070 | +static const struct usba_ep_config ep_config_sama5[] __initconst = { |
|---|
| 2071 | + { .nr_banks = 1 }, /* ep 0 */ |
|---|
| 2072 | + { .nr_banks = 3, .can_dma = 1, .can_isoc = 1 }, /* ep 1 */ |
|---|
| 2073 | + { .nr_banks = 3, .can_dma = 1, .can_isoc = 1 }, /* ep 2 */ |
|---|
| 2074 | + { .nr_banks = 2, .can_dma = 1, .can_isoc = 1 }, /* ep 3 */ |
|---|
| 2075 | + { .nr_banks = 2, .can_dma = 1, .can_isoc = 1 }, /* ep 4 */ |
|---|
| 2076 | + { .nr_banks = 2, .can_dma = 1, .can_isoc = 1 }, /* ep 5 */ |
|---|
| 2077 | + { .nr_banks = 2, .can_dma = 1, .can_isoc = 1 }, /* ep 6 */ |
|---|
| 2078 | + { .nr_banks = 2, .can_dma = 1, .can_isoc = 1 }, /* ep 7 */ |
|---|
| 2079 | + { .nr_banks = 2, .can_isoc = 1 }, /* ep 8 */ |
|---|
| 2080 | + { .nr_banks = 2, .can_isoc = 1 }, /* ep 9 */ |
|---|
| 2081 | + { .nr_banks = 2, .can_isoc = 1 }, /* ep 10 */ |
|---|
| 2082 | + { .nr_banks = 2, .can_isoc = 1 }, /* ep 11 */ |
|---|
| 2083 | + { .nr_banks = 2, .can_isoc = 1 }, /* ep 12 */ |
|---|
| 2084 | + { .nr_banks = 2, .can_isoc = 1 }, /* ep 13 */ |
|---|
| 2085 | + { .nr_banks = 2, .can_isoc = 1 }, /* ep 14 */ |
|---|
| 2086 | + { .nr_banks = 2, .can_isoc = 1 }, /* ep 15 */ |
|---|
| 2087 | +}; |
|---|
| 2088 | + |
|---|
| 2089 | +static const struct usba_udc_config udc_at91sam9rl_cfg = { |
|---|
| 2090 | + .errata = &at91sam9rl_errata, |
|---|
| 2091 | + .config = ep_config_sam9, |
|---|
| 2092 | + .num_ep = ARRAY_SIZE(ep_config_sam9), |
|---|
| 2093 | + .ep_prealloc = true, |
|---|
| 2094 | +}; |
|---|
| 2095 | + |
|---|
| 2096 | +static const struct usba_udc_config udc_at91sam9g45_cfg = { |
|---|
| 2097 | + .errata = &at91sam9g45_errata, |
|---|
| 2098 | + .config = ep_config_sam9, |
|---|
| 2099 | + .num_ep = ARRAY_SIZE(ep_config_sam9), |
|---|
| 2100 | + .ep_prealloc = true, |
|---|
| 2101 | +}; |
|---|
| 2102 | + |
|---|
| 2103 | +static const struct usba_udc_config udc_sama5d3_cfg = { |
|---|
| 2104 | + .config = ep_config_sama5, |
|---|
| 2105 | + .num_ep = ARRAY_SIZE(ep_config_sama5), |
|---|
| 2106 | + .ep_prealloc = true, |
|---|
| 2107 | +}; |
|---|
| 2108 | + |
|---|
| 2109 | +static const struct usba_udc_config udc_sam9x60_cfg = { |
|---|
| 2110 | + .num_ep = ARRAY_SIZE(ep_config_sam9), |
|---|
| 2111 | + .config = ep_config_sam9, |
|---|
| 2112 | + .ep_prealloc = false, |
|---|
| 2113 | +}; |
|---|
| 2114 | + |
|---|
| 1996 | 2115 | static const struct of_device_id atmel_udc_dt_ids[] = { |
|---|
| 1997 | | - { .compatible = "atmel,at91sam9rl-udc", .data = &at91sam9rl_errata }, |
|---|
| 1998 | | - { .compatible = "atmel,at91sam9g45-udc", .data = &at91sam9g45_errata }, |
|---|
| 1999 | | - { .compatible = "atmel,sama5d3-udc" }, |
|---|
| 2116 | + { .compatible = "atmel,at91sam9rl-udc", .data = &udc_at91sam9rl_cfg }, |
|---|
| 2117 | + { .compatible = "atmel,at91sam9g45-udc", .data = &udc_at91sam9g45_cfg }, |
|---|
| 2118 | + { .compatible = "atmel,sama5d3-udc", .data = &udc_sama5d3_cfg }, |
|---|
| 2119 | + { .compatible = "microchip,sam9x60-udc", .data = &udc_sam9x60_cfg }, |
|---|
| 2000 | 2120 | { /* sentinel */ } |
|---|
| 2001 | 2121 | }; |
|---|
| 2002 | 2122 | |
|---|
| 2003 | 2123 | MODULE_DEVICE_TABLE(of, atmel_udc_dt_ids); |
|---|
| 2004 | 2124 | |
|---|
| 2125 | +static const struct of_device_id atmel_pmc_dt_ids[] = { |
|---|
| 2126 | + { .compatible = "atmel,at91sam9g45-pmc" }, |
|---|
| 2127 | + { .compatible = "atmel,at91sam9rl-pmc" }, |
|---|
| 2128 | + { .compatible = "atmel,at91sam9x5-pmc" }, |
|---|
| 2129 | + { /* sentinel */ } |
|---|
| 2130 | +}; |
|---|
| 2131 | + |
|---|
| 2005 | 2132 | static struct usba_ep * atmel_udc_of_init(struct platform_device *pdev, |
|---|
| 2006 | 2133 | struct usba_udc *udc) |
|---|
| 2007 | 2134 | { |
|---|
| 2008 | | - u32 val; |
|---|
| 2009 | | - const char *name; |
|---|
| 2010 | 2135 | struct device_node *np = pdev->dev.of_node; |
|---|
| 2011 | 2136 | const struct of_device_id *match; |
|---|
| 2012 | 2137 | struct device_node *pp; |
|---|
| 2013 | 2138 | int i, ret; |
|---|
| 2014 | 2139 | struct usba_ep *eps, *ep; |
|---|
| 2140 | + const struct usba_udc_config *udc_config; |
|---|
| 2015 | 2141 | |
|---|
| 2016 | 2142 | match = of_match_node(atmel_udc_dt_ids, np); |
|---|
| 2017 | 2143 | if (!match) |
|---|
| 2018 | 2144 | return ERR_PTR(-EINVAL); |
|---|
| 2019 | 2145 | |
|---|
| 2020 | | - udc->errata = match->data; |
|---|
| 2021 | | - udc->pmc = syscon_regmap_lookup_by_compatible("atmel,at91sam9g45-pmc"); |
|---|
| 2022 | | - if (IS_ERR(udc->pmc)) |
|---|
| 2023 | | - udc->pmc = syscon_regmap_lookup_by_compatible("atmel,at91sam9rl-pmc"); |
|---|
| 2024 | | - if (IS_ERR(udc->pmc)) |
|---|
| 2025 | | - udc->pmc = syscon_regmap_lookup_by_compatible("atmel,at91sam9x5-pmc"); |
|---|
| 2026 | | - if (udc->errata && IS_ERR(udc->pmc)) |
|---|
| 2027 | | - return ERR_CAST(udc->pmc); |
|---|
| 2146 | + udc_config = match->data; |
|---|
| 2147 | + udc->ep_prealloc = udc_config->ep_prealloc; |
|---|
| 2148 | + udc->errata = udc_config->errata; |
|---|
| 2149 | + if (udc->errata) { |
|---|
| 2150 | + pp = of_find_matching_node_and_match(NULL, atmel_pmc_dt_ids, |
|---|
| 2151 | + NULL); |
|---|
| 2152 | + if (!pp) |
|---|
| 2153 | + return ERR_PTR(-ENODEV); |
|---|
| 2154 | + |
|---|
| 2155 | + udc->pmc = syscon_node_to_regmap(pp); |
|---|
| 2156 | + of_node_put(pp); |
|---|
| 2157 | + if (IS_ERR(udc->pmc)) |
|---|
| 2158 | + return ERR_CAST(udc->pmc); |
|---|
| 2159 | + } |
|---|
| 2028 | 2160 | |
|---|
| 2029 | 2161 | udc->num_ep = 0; |
|---|
| 2030 | 2162 | |
|---|
| .. | .. |
|---|
| 2032 | 2164 | GPIOD_IN); |
|---|
| 2033 | 2165 | |
|---|
| 2034 | 2166 | if (fifo_mode == 0) { |
|---|
| 2035 | | - pp = NULL; |
|---|
| 2036 | | - while ((pp = of_get_next_child(np, pp))) |
|---|
| 2037 | | - udc->num_ep++; |
|---|
| 2038 | | - udc->configured_ep = 1; |
|---|
| 2167 | + udc->num_ep = udc_config->num_ep; |
|---|
| 2039 | 2168 | } else { |
|---|
| 2040 | 2169 | udc->num_ep = usba_config_fifo_table(udc); |
|---|
| 2041 | 2170 | } |
|---|
| .. | .. |
|---|
| 2049 | 2178 | |
|---|
| 2050 | 2179 | INIT_LIST_HEAD(&eps[0].ep.ep_list); |
|---|
| 2051 | 2180 | |
|---|
| 2052 | | - pp = NULL; |
|---|
| 2053 | 2181 | i = 0; |
|---|
| 2054 | | - while ((pp = of_get_next_child(np, pp)) && i < udc->num_ep) { |
|---|
| 2182 | + while (i < udc->num_ep) { |
|---|
| 2183 | + const struct usba_ep_config *ep_cfg = &udc_config->config[i]; |
|---|
| 2184 | + |
|---|
| 2055 | 2185 | ep = &eps[i]; |
|---|
| 2056 | 2186 | |
|---|
| 2057 | | - ret = of_property_read_u32(pp, "reg", &val); |
|---|
| 2058 | | - if (ret) { |
|---|
| 2059 | | - dev_err(&pdev->dev, "of_probe: reg error(%d)\n", ret); |
|---|
| 2060 | | - goto err; |
|---|
| 2061 | | - } |
|---|
| 2062 | | - ep->index = fifo_mode ? udc->fifo_cfg[i].hw_ep_num : val; |
|---|
| 2187 | + ep->index = fifo_mode ? udc->fifo_cfg[i].hw_ep_num : i; |
|---|
| 2063 | 2188 | |
|---|
| 2064 | | - ret = of_property_read_u32(pp, "atmel,fifo-size", &val); |
|---|
| 2065 | | - if (ret) { |
|---|
| 2066 | | - dev_err(&pdev->dev, "of_probe: fifo-size error(%d)\n", ret); |
|---|
| 2067 | | - goto err; |
|---|
| 2068 | | - } |
|---|
| 2189 | + /* Only the first EP is 64 bytes */ |
|---|
| 2190 | + if (ep->index == 0) |
|---|
| 2191 | + ep->fifo_size = 64; |
|---|
| 2192 | + else |
|---|
| 2193 | + ep->fifo_size = 1024; |
|---|
| 2194 | + |
|---|
| 2069 | 2195 | if (fifo_mode) { |
|---|
| 2070 | | - if (val < udc->fifo_cfg[i].fifo_size) { |
|---|
| 2196 | + if (ep->fifo_size < udc->fifo_cfg[i].fifo_size) |
|---|
| 2071 | 2197 | dev_warn(&pdev->dev, |
|---|
| 2072 | | - "Using max fifo-size value from DT\n"); |
|---|
| 2073 | | - ep->fifo_size = val; |
|---|
| 2074 | | - } else { |
|---|
| 2198 | + "Using default max fifo-size value\n"); |
|---|
| 2199 | + else |
|---|
| 2075 | 2200 | ep->fifo_size = udc->fifo_cfg[i].fifo_size; |
|---|
| 2076 | | - } |
|---|
| 2077 | | - } else { |
|---|
| 2078 | | - ep->fifo_size = val; |
|---|
| 2079 | 2201 | } |
|---|
| 2080 | 2202 | |
|---|
| 2081 | | - ret = of_property_read_u32(pp, "atmel,nb-banks", &val); |
|---|
| 2082 | | - if (ret) { |
|---|
| 2083 | | - dev_err(&pdev->dev, "of_probe: nb-banks error(%d)\n", ret); |
|---|
| 2084 | | - goto err; |
|---|
| 2085 | | - } |
|---|
| 2203 | + ep->nr_banks = ep_cfg->nr_banks; |
|---|
| 2086 | 2204 | if (fifo_mode) { |
|---|
| 2087 | | - if (val < udc->fifo_cfg[i].nr_banks) { |
|---|
| 2205 | + if (ep->nr_banks < udc->fifo_cfg[i].nr_banks) |
|---|
| 2088 | 2206 | dev_warn(&pdev->dev, |
|---|
| 2089 | | - "Using max nb-banks value from DT\n"); |
|---|
| 2090 | | - ep->nr_banks = val; |
|---|
| 2091 | | - } else { |
|---|
| 2207 | + "Using default max nb-banks value\n"); |
|---|
| 2208 | + else |
|---|
| 2092 | 2209 | ep->nr_banks = udc->fifo_cfg[i].nr_banks; |
|---|
| 2093 | | - } |
|---|
| 2094 | | - } else { |
|---|
| 2095 | | - ep->nr_banks = val; |
|---|
| 2096 | 2210 | } |
|---|
| 2097 | 2211 | |
|---|
| 2098 | | - ep->can_dma = of_property_read_bool(pp, "atmel,can-dma"); |
|---|
| 2099 | | - ep->can_isoc = of_property_read_bool(pp, "atmel,can-isoc"); |
|---|
| 2212 | + ep->can_dma = ep_cfg->can_dma; |
|---|
| 2213 | + ep->can_isoc = ep_cfg->can_isoc; |
|---|
| 2100 | 2214 | |
|---|
| 2101 | | - ret = of_property_read_string(pp, "name", &name); |
|---|
| 2102 | | - if (ret) { |
|---|
| 2103 | | - dev_err(&pdev->dev, "of_probe: name error(%d)\n", ret); |
|---|
| 2104 | | - goto err; |
|---|
| 2105 | | - } |
|---|
| 2106 | 2215 | sprintf(ep->name, "ep%d", ep->index); |
|---|
| 2107 | 2216 | ep->ep.name = ep->name; |
|---|
| 2108 | 2217 | |
|---|
| .. | .. |
|---|
| 2284 | 2393 | mutex_lock(&udc->vbus_mutex); |
|---|
| 2285 | 2394 | |
|---|
| 2286 | 2395 | if (!device_may_wakeup(dev)) { |
|---|
| 2396 | + udc->suspended = false; |
|---|
| 2287 | 2397 | usba_stop(udc); |
|---|
| 2288 | 2398 | goto out; |
|---|
| 2289 | 2399 | } |
|---|
| .. | .. |
|---|
| 2293 | 2403 | * to request vbus irq, assuming always on. |
|---|
| 2294 | 2404 | */ |
|---|
| 2295 | 2405 | if (udc->vbus_pin) { |
|---|
| 2406 | + /* FIXME: right to stop here...??? */ |
|---|
| 2296 | 2407 | usba_stop(udc); |
|---|
| 2297 | 2408 | enable_irq_wake(gpiod_to_irq(udc->vbus_pin)); |
|---|
| 2298 | 2409 | } |
|---|
| 2410 | + |
|---|
| 2411 | + enable_irq_wake(udc->irq); |
|---|
| 2299 | 2412 | |
|---|
| 2300 | 2413 | out: |
|---|
| 2301 | 2414 | mutex_unlock(&udc->vbus_mutex); |
|---|
| .. | .. |
|---|
| 2310 | 2423 | if (!udc->driver) |
|---|
| 2311 | 2424 | return 0; |
|---|
| 2312 | 2425 | |
|---|
| 2313 | | - if (device_may_wakeup(dev) && udc->vbus_pin) |
|---|
| 2314 | | - disable_irq_wake(gpiod_to_irq(udc->vbus_pin)); |
|---|
| 2426 | + if (device_may_wakeup(dev)) { |
|---|
| 2427 | + if (udc->vbus_pin) |
|---|
| 2428 | + disable_irq_wake(gpiod_to_irq(udc->vbus_pin)); |
|---|
| 2429 | + |
|---|
| 2430 | + disable_irq_wake(udc->irq); |
|---|
| 2431 | + } |
|---|
| 2315 | 2432 | |
|---|
| 2316 | 2433 | /* If Vbus is present, enable the controller and wait for reset */ |
|---|
| 2317 | 2434 | mutex_lock(&udc->vbus_mutex); |
|---|