diff options
| -rw-r--r-- | drivers/usb/gadget/udc/at91_udc.c | 288 | ||||
| -rw-r--r-- | drivers/usb/gadget/udc/at91_udc.h | 7 |
2 files changed, 218 insertions, 77 deletions
diff --git a/drivers/usb/gadget/udc/at91_udc.c b/drivers/usb/gadget/udc/at91_udc.c index 4dba2c65dfd4..c0abb9bc76a9 100644 --- a/drivers/usb/gadget/udc/at91_udc.c +++ b/drivers/usb/gadget/udc/at91_udc.c | |||
| @@ -31,16 +31,9 @@ | |||
| 31 | #include <linux/of.h> | 31 | #include <linux/of.h> |
| 32 | #include <linux/of_gpio.h> | 32 | #include <linux/of_gpio.h> |
| 33 | #include <linux/platform_data/atmel.h> | 33 | #include <linux/platform_data/atmel.h> |
| 34 | 34 | #include <linux/regmap.h> | |
| 35 | #include <asm/byteorder.h> | 35 | #include <linux/mfd/syscon.h> |
| 36 | #include <mach/hardware.h> | 36 | #include <linux/mfd/syscon/atmel-matrix.h> |
| 37 | #include <asm/io.h> | ||
| 38 | #include <asm/irq.h> | ||
| 39 | #include <asm/gpio.h> | ||
| 40 | |||
| 41 | #include <mach/cpu.h> | ||
| 42 | #include <mach/at91sam9261_matrix.h> | ||
| 43 | #include <mach/at91_matrix.h> | ||
| 44 | 37 | ||
| 45 | #include "at91_udc.h" | 38 | #include "at91_udc.h" |
| 46 | 39 | ||
| @@ -915,8 +908,6 @@ static void clk_off(struct at91_udc *udc) | |||
| 915 | */ | 908 | */ |
| 916 | static void pullup(struct at91_udc *udc, int is_on) | 909 | static void pullup(struct at91_udc *udc, int is_on) |
| 917 | { | 910 | { |
| 918 | int active = !udc->board.pullup_active_low; | ||
| 919 | |||
| 920 | if (!udc->enabled || !udc->vbus) | 911 | if (!udc->enabled || !udc->vbus) |
| 921 | is_on = 0; | 912 | is_on = 0; |
| 922 | DBG("%sactive\n", is_on ? "" : "in"); | 913 | DBG("%sactive\n", is_on ? "" : "in"); |
| @@ -925,40 +916,15 @@ static void pullup(struct at91_udc *udc, int is_on) | |||
| 925 | clk_on(udc); | 916 | clk_on(udc); |
| 926 | at91_udp_write(udc, AT91_UDP_ICR, AT91_UDP_RXRSM); | 917 | at91_udp_write(udc, AT91_UDP_ICR, AT91_UDP_RXRSM); |
| 927 | at91_udp_write(udc, AT91_UDP_TXVC, 0); | 918 | at91_udp_write(udc, AT91_UDP_TXVC, 0); |
| 928 | if (cpu_is_at91rm9200()) | ||
| 929 | gpio_set_value(udc->board.pullup_pin, active); | ||
| 930 | else if (cpu_is_at91sam9260() || cpu_is_at91sam9263() || cpu_is_at91sam9g20()) { | ||
| 931 | u32 txvc = at91_udp_read(udc, AT91_UDP_TXVC); | ||
| 932 | |||
| 933 | txvc |= AT91_UDP_TXVC_PUON; | ||
| 934 | at91_udp_write(udc, AT91_UDP_TXVC, txvc); | ||
| 935 | } else if (cpu_is_at91sam9261() || cpu_is_at91sam9g10()) { | ||
| 936 | u32 usbpucr; | ||
| 937 | |||
| 938 | usbpucr = at91_matrix_read(AT91_MATRIX_USBPUCR); | ||
| 939 | usbpucr |= AT91_MATRIX_USBPUCR_PUON; | ||
| 940 | at91_matrix_write(AT91_MATRIX_USBPUCR, usbpucr); | ||
| 941 | } | ||
| 942 | } else { | 919 | } else { |
| 943 | stop_activity(udc); | 920 | stop_activity(udc); |
| 944 | at91_udp_write(udc, AT91_UDP_IDR, AT91_UDP_RXRSM); | 921 | at91_udp_write(udc, AT91_UDP_IDR, AT91_UDP_RXRSM); |
| 945 | at91_udp_write(udc, AT91_UDP_TXVC, AT91_UDP_TXVC_TXVDIS); | 922 | at91_udp_write(udc, AT91_UDP_TXVC, AT91_UDP_TXVC_TXVDIS); |
| 946 | if (cpu_is_at91rm9200()) | ||
| 947 | gpio_set_value(udc->board.pullup_pin, !active); | ||
| 948 | else if (cpu_is_at91sam9260() || cpu_is_at91sam9263() || cpu_is_at91sam9g20()) { | ||
| 949 | u32 txvc = at91_udp_read(udc, AT91_UDP_TXVC); | ||
| 950 | |||
| 951 | txvc &= ~AT91_UDP_TXVC_PUON; | ||
| 952 | at91_udp_write(udc, AT91_UDP_TXVC, txvc); | ||
| 953 | } else if (cpu_is_at91sam9261() || cpu_is_at91sam9g10()) { | ||
| 954 | u32 usbpucr; | ||
| 955 | |||
| 956 | usbpucr = at91_matrix_read(AT91_MATRIX_USBPUCR); | ||
| 957 | usbpucr &= ~AT91_MATRIX_USBPUCR_PUON; | ||
| 958 | at91_matrix_write(AT91_MATRIX_USBPUCR, usbpucr); | ||
| 959 | } | ||
| 960 | clk_off(udc); | 923 | clk_off(udc); |
| 961 | } | 924 | } |
| 925 | |||
| 926 | if (udc->caps && udc->caps->pullup) | ||
| 927 | udc->caps->pullup(udc, is_on); | ||
| 962 | } | 928 | } |
| 963 | 929 | ||
| 964 | /* vbus is here! turn everything on that's ready */ | 930 | /* vbus is here! turn everything on that's ready */ |
| @@ -1683,12 +1649,202 @@ static void at91udc_shutdown(struct platform_device *dev) | |||
| 1683 | spin_unlock_irqrestore(&udc->lock, flags); | 1649 | spin_unlock_irqrestore(&udc->lock, flags); |
| 1684 | } | 1650 | } |
| 1685 | 1651 | ||
| 1686 | static void at91udc_of_init(struct at91_udc *udc, | 1652 | static int at91rm9200_udc_init(struct at91_udc *udc) |
| 1687 | struct device_node *np) | 1653 | { |
| 1654 | struct at91_ep *ep; | ||
| 1655 | int ret; | ||
| 1656 | int i; | ||
| 1657 | |||
| 1658 | for (i = 0; i < NUM_ENDPOINTS; i++) { | ||
| 1659 | ep = &udc->ep[i]; | ||
| 1660 | |||
| 1661 | switch (i) { | ||
| 1662 | case 0: | ||
| 1663 | case 3: | ||
| 1664 | ep->maxpacket = 8; | ||
| 1665 | break; | ||
| 1666 | case 1 ... 2: | ||
| 1667 | ep->maxpacket = 64; | ||
| 1668 | break; | ||
| 1669 | case 4 ... 5: | ||
| 1670 | ep->maxpacket = 256; | ||
| 1671 | break; | ||
| 1672 | } | ||
| 1673 | } | ||
| 1674 | |||
| 1675 | if (!gpio_is_valid(udc->board.pullup_pin)) { | ||
| 1676 | DBG("no D+ pullup?\n"); | ||
| 1677 | return -ENODEV; | ||
| 1678 | } | ||
| 1679 | |||
| 1680 | ret = devm_gpio_request(&udc->pdev->dev, udc->board.pullup_pin, | ||
| 1681 | "udc_pullup"); | ||
| 1682 | if (ret) { | ||
| 1683 | DBG("D+ pullup is busy\n"); | ||
| 1684 | return ret; | ||
| 1685 | } | ||
| 1686 | |||
| 1687 | gpio_direction_output(udc->board.pullup_pin, | ||
| 1688 | udc->board.pullup_active_low); | ||
| 1689 | |||
| 1690 | return 0; | ||
| 1691 | } | ||
| 1692 | |||
| 1693 | static void at91rm9200_udc_pullup(struct at91_udc *udc, int is_on) | ||
| 1694 | { | ||
| 1695 | int active = !udc->board.pullup_active_low; | ||
| 1696 | |||
| 1697 | if (is_on) | ||
| 1698 | gpio_set_value(udc->board.pullup_pin, active); | ||
| 1699 | else | ||
| 1700 | gpio_set_value(udc->board.pullup_pin, !active); | ||
| 1701 | } | ||
| 1702 | |||
| 1703 | static const struct at91_udc_caps at91rm9200_udc_caps = { | ||
| 1704 | .init = at91rm9200_udc_init, | ||
| 1705 | .pullup = at91rm9200_udc_pullup, | ||
| 1706 | }; | ||
| 1707 | |||
| 1708 | static int at91sam9260_udc_init(struct at91_udc *udc) | ||
| 1709 | { | ||
| 1710 | struct at91_ep *ep; | ||
| 1711 | int i; | ||
| 1712 | |||
| 1713 | for (i = 0; i < NUM_ENDPOINTS; i++) { | ||
| 1714 | ep = &udc->ep[i]; | ||
| 1715 | |||
| 1716 | switch (i) { | ||
| 1717 | case 0 ... 3: | ||
| 1718 | ep->maxpacket = 64; | ||
| 1719 | break; | ||
| 1720 | case 4 ... 5: | ||
| 1721 | ep->maxpacket = 512; | ||
| 1722 | break; | ||
| 1723 | } | ||
| 1724 | } | ||
| 1725 | |||
| 1726 | return 0; | ||
| 1727 | } | ||
| 1728 | |||
| 1729 | static void at91sam9260_udc_pullup(struct at91_udc *udc, int is_on) | ||
| 1730 | { | ||
| 1731 | u32 txvc = at91_udp_read(udc, AT91_UDP_TXVC); | ||
| 1732 | |||
| 1733 | if (is_on) | ||
| 1734 | txvc |= AT91_UDP_TXVC_PUON; | ||
| 1735 | else | ||
| 1736 | txvc &= ~AT91_UDP_TXVC_PUON; | ||
| 1737 | |||
| 1738 | at91_udp_write(udc, AT91_UDP_TXVC, txvc); | ||
| 1739 | } | ||
| 1740 | |||
| 1741 | static const struct at91_udc_caps at91sam9260_udc_caps = { | ||
| 1742 | .init = at91sam9260_udc_init, | ||
| 1743 | .pullup = at91sam9260_udc_pullup, | ||
| 1744 | }; | ||
| 1745 | |||
| 1746 | static int at91sam9261_udc_init(struct at91_udc *udc) | ||
| 1747 | { | ||
| 1748 | struct at91_ep *ep; | ||
| 1749 | int i; | ||
| 1750 | |||
| 1751 | for (i = 0; i < NUM_ENDPOINTS; i++) { | ||
| 1752 | ep = &udc->ep[i]; | ||
| 1753 | |||
| 1754 | switch (i) { | ||
| 1755 | case 0: | ||
| 1756 | ep->maxpacket = 8; | ||
| 1757 | break; | ||
| 1758 | case 1 ... 3: | ||
| 1759 | ep->maxpacket = 64; | ||
| 1760 | break; | ||
| 1761 | case 4 ... 5: | ||
| 1762 | ep->maxpacket = 256; | ||
| 1763 | break; | ||
| 1764 | } | ||
| 1765 | } | ||
| 1766 | |||
| 1767 | udc->matrix = syscon_regmap_lookup_by_phandle(udc->pdev->dev.of_node, | ||
| 1768 | "atmel,matrix"); | ||
| 1769 | if (IS_ERR(udc->matrix)) | ||
| 1770 | return PTR_ERR(udc->matrix); | ||
| 1771 | |||
| 1772 | return 0; | ||
| 1773 | } | ||
| 1774 | |||
| 1775 | static void at91sam9261_udc_pullup(struct at91_udc *udc, int is_on) | ||
| 1776 | { | ||
| 1777 | u32 usbpucr = 0; | ||
| 1778 | |||
| 1779 | if (is_on) | ||
| 1780 | usbpucr = AT91_MATRIX_USBPUCR_PUON; | ||
| 1781 | |||
| 1782 | regmap_update_bits(udc->matrix, AT91SAM9261_MATRIX_USBPUCR, | ||
| 1783 | AT91_MATRIX_USBPUCR_PUON, usbpucr); | ||
| 1784 | } | ||
| 1785 | |||
| 1786 | static const struct at91_udc_caps at91sam9261_udc_caps = { | ||
| 1787 | .init = at91sam9261_udc_init, | ||
| 1788 | .pullup = at91sam9261_udc_pullup, | ||
| 1789 | }; | ||
| 1790 | |||
| 1791 | static int at91sam9263_udc_init(struct at91_udc *udc) | ||
| 1792 | { | ||
| 1793 | struct at91_ep *ep; | ||
| 1794 | int i; | ||
| 1795 | |||
| 1796 | for (i = 0; i < NUM_ENDPOINTS; i++) { | ||
| 1797 | ep = &udc->ep[i]; | ||
| 1798 | |||
| 1799 | switch (i) { | ||
| 1800 | case 0: | ||
| 1801 | case 1: | ||
| 1802 | case 2: | ||
| 1803 | case 3: | ||
| 1804 | ep->maxpacket = 64; | ||
| 1805 | break; | ||
| 1806 | case 4: | ||
| 1807 | case 5: | ||
| 1808 | ep->maxpacket = 256; | ||
| 1809 | break; | ||
| 1810 | } | ||
| 1811 | } | ||
| 1812 | |||
| 1813 | return 0; | ||
| 1814 | } | ||
| 1815 | |||
| 1816 | static const struct at91_udc_caps at91sam9263_udc_caps = { | ||
| 1817 | .init = at91sam9263_udc_init, | ||
| 1818 | .pullup = at91sam9260_udc_pullup, | ||
| 1819 | }; | ||
| 1820 | |||
| 1821 | static const struct of_device_id at91_udc_dt_ids[] = { | ||
| 1822 | { | ||
| 1823 | .compatible = "atmel,at91rm9200-udc", | ||
| 1824 | .data = &at91rm9200_udc_caps, | ||
| 1825 | }, | ||
| 1826 | { | ||
| 1827 | .compatible = "atmel,at91sam9260-udc", | ||
| 1828 | .data = &at91sam9260_udc_caps, | ||
| 1829 | }, | ||
| 1830 | { | ||
| 1831 | .compatible = "atmel,at91sam9261-udc", | ||
| 1832 | .data = &at91sam9261_udc_caps, | ||
| 1833 | }, | ||
| 1834 | { | ||
| 1835 | .compatible = "atmel,at91sam9263-udc", | ||
| 1836 | .data = &at91sam9263_udc_caps, | ||
| 1837 | }, | ||
| 1838 | { /* sentinel */ } | ||
| 1839 | }; | ||
| 1840 | MODULE_DEVICE_TABLE(of, at91_udc_dt_ids); | ||
| 1841 | |||
| 1842 | static void at91udc_of_init(struct at91_udc *udc, struct device_node *np) | ||
| 1688 | { | 1843 | { |
| 1689 | struct at91_udc_data *board = &udc->board; | 1844 | struct at91_udc_data *board = &udc->board; |
| 1690 | u32 val; | 1845 | const struct of_device_id *match; |
| 1691 | enum of_gpio_flags flags; | 1846 | enum of_gpio_flags flags; |
| 1847 | u32 val; | ||
| 1692 | 1848 | ||
| 1693 | if (of_property_read_u32(np, "atmel,vbus-polled", &val) == 0) | 1849 | if (of_property_read_u32(np, "atmel,vbus-polled", &val) == 0) |
| 1694 | board->vbus_polled = 1; | 1850 | board->vbus_polled = 1; |
| @@ -1701,6 +1857,10 @@ static void at91udc_of_init(struct at91_udc *udc, | |||
| 1701 | &flags); | 1857 | &flags); |
| 1702 | 1858 | ||
| 1703 | board->pullup_active_low = (flags & OF_GPIO_ACTIVE_LOW) ? 1 : 0; | 1859 | board->pullup_active_low = (flags & OF_GPIO_ACTIVE_LOW) ? 1 : 0; |
| 1860 | |||
| 1861 | match = of_match_node(at91_udc_dt_ids, np); | ||
| 1862 | if (match) | ||
| 1863 | udc->caps = match->data; | ||
| 1704 | } | 1864 | } |
| 1705 | 1865 | ||
| 1706 | static int at91udc_probe(struct platform_device *pdev) | 1866 | static int at91udc_probe(struct platform_device *pdev) |
| @@ -1709,6 +1869,8 @@ static int at91udc_probe(struct platform_device *pdev) | |||
| 1709 | struct at91_udc *udc; | 1869 | struct at91_udc *udc; |
| 1710 | int retval; | 1870 | int retval; |
| 1711 | struct resource *res; | 1871 | struct resource *res; |
| 1872 | struct at91_ep *ep; | ||
| 1873 | int i; | ||
| 1712 | 1874 | ||
| 1713 | /* init software state */ | 1875 | /* init software state */ |
| 1714 | udc = &controller; | 1876 | udc = &controller; |
| @@ -1718,40 +1880,19 @@ static int at91udc_probe(struct platform_device *pdev) | |||
| 1718 | udc->enabled = 0; | 1880 | udc->enabled = 0; |
| 1719 | spin_lock_init(&udc->lock); | 1881 | spin_lock_init(&udc->lock); |
| 1720 | 1882 | ||
| 1721 | /* rm9200 needs manual D+ pullup; off by default */ | ||
| 1722 | if (cpu_is_at91rm9200()) { | ||
| 1723 | if (!gpio_is_valid(udc->board.pullup_pin)) { | ||
| 1724 | DBG("no D+ pullup?\n"); | ||
| 1725 | return -ENODEV; | ||
| 1726 | } | ||
| 1727 | retval = devm_gpio_request(dev, udc->board.pullup_pin, | ||
| 1728 | "udc_pullup"); | ||
| 1729 | if (retval) { | ||
| 1730 | DBG("D+ pullup is busy\n"); | ||
| 1731 | return retval; | ||
| 1732 | } | ||
| 1733 | gpio_direction_output(udc->board.pullup_pin, | ||
| 1734 | udc->board.pullup_active_low); | ||
| 1735 | } | ||
| 1736 | 1883 | ||
| 1737 | /* newer chips have more FIFO memory than rm9200 */ | ||
| 1738 | if (cpu_is_at91sam9260() || cpu_is_at91sam9g20()) { | ||
| 1739 | udc->ep[0].maxpacket = 64; | ||
| 1740 | udc->ep[3].maxpacket = 64; | ||
| 1741 | udc->ep[4].maxpacket = 512; | ||
| 1742 | udc->ep[5].maxpacket = 512; | ||
| 1743 | } else if (cpu_is_at91sam9261() || cpu_is_at91sam9g10()) { | ||
| 1744 | udc->ep[3].maxpacket = 64; | ||
| 1745 | } else if (cpu_is_at91sam9263()) { | ||
| 1746 | udc->ep[0].maxpacket = 64; | ||
| 1747 | udc->ep[3].maxpacket = 64; | ||
| 1748 | } | ||
| 1749 | 1884 | ||
| 1750 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 1885 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
| 1751 | udc->udp_baseaddr = devm_ioremap_resource(dev, res); | 1886 | udc->udp_baseaddr = devm_ioremap_resource(dev, res); |
| 1752 | if (IS_ERR(udc->udp_baseaddr)) | 1887 | if (IS_ERR(udc->udp_baseaddr)) |
| 1753 | return PTR_ERR(udc->udp_baseaddr); | 1888 | return PTR_ERR(udc->udp_baseaddr); |
| 1754 | 1889 | ||
| 1890 | if (udc->caps && udc->caps->init) { | ||
| 1891 | retval = udc->caps->init(udc); | ||
| 1892 | if (retval) | ||
| 1893 | return retval; | ||
| 1894 | } | ||
| 1895 | |||
| 1755 | udc_reinit(udc); | 1896 | udc_reinit(udc); |
| 1756 | 1897 | ||
| 1757 | /* get interface and function clocks */ | 1898 | /* get interface and function clocks */ |
| @@ -1920,13 +2061,6 @@ static int at91udc_resume(struct platform_device *pdev) | |||
| 1920 | #define at91udc_resume NULL | 2061 | #define at91udc_resume NULL |
| 1921 | #endif | 2062 | #endif |
| 1922 | 2063 | ||
| 1923 | static const struct of_device_id at91_udc_dt_ids[] = { | ||
| 1924 | { .compatible = "atmel,at91rm9200-udc" }, | ||
| 1925 | { /* sentinel */ } | ||
| 1926 | }; | ||
| 1927 | |||
| 1928 | MODULE_DEVICE_TABLE(of, at91_udc_dt_ids); | ||
| 1929 | |||
| 1930 | static struct platform_driver at91_udc_driver = { | 2064 | static struct platform_driver at91_udc_driver = { |
| 1931 | .remove = __exit_p(at91udc_remove), | 2065 | .remove = __exit_p(at91udc_remove), |
| 1932 | .shutdown = at91udc_shutdown, | 2066 | .shutdown = at91udc_shutdown, |
diff --git a/drivers/usb/gadget/udc/at91_udc.h b/drivers/usb/gadget/udc/at91_udc.h index e647d1c2ada4..4fc0daa6587f 100644 --- a/drivers/usb/gadget/udc/at91_udc.h +++ b/drivers/usb/gadget/udc/at91_udc.h | |||
| @@ -107,6 +107,11 @@ struct at91_ep { | |||
| 107 | unsigned fifo_bank:1; | 107 | unsigned fifo_bank:1; |
| 108 | }; | 108 | }; |
| 109 | 109 | ||
| 110 | struct at91_udc_caps { | ||
| 111 | int (*init)(struct at91_udc *udc); | ||
| 112 | void (*pullup)(struct at91_udc *udc, int is_on); | ||
| 113 | }; | ||
| 114 | |||
| 110 | /* | 115 | /* |
| 111 | * driver is non-SMP, and just blocks IRQs whenever it needs | 116 | * driver is non-SMP, and just blocks IRQs whenever it needs |
| 112 | * access protection for chip registers or driver state | 117 | * access protection for chip registers or driver state |
| @@ -115,6 +120,7 @@ struct at91_udc { | |||
| 115 | struct usb_gadget gadget; | 120 | struct usb_gadget gadget; |
| 116 | struct at91_ep ep[NUM_ENDPOINTS]; | 121 | struct at91_ep ep[NUM_ENDPOINTS]; |
| 117 | struct usb_gadget_driver *driver; | 122 | struct usb_gadget_driver *driver; |
| 123 | const struct at91_udc_caps *caps; | ||
| 118 | unsigned vbus:1; | 124 | unsigned vbus:1; |
| 119 | unsigned enabled:1; | 125 | unsigned enabled:1; |
| 120 | unsigned clocked:1; | 126 | unsigned clocked:1; |
| @@ -134,6 +140,7 @@ struct at91_udc { | |||
| 134 | spinlock_t lock; | 140 | spinlock_t lock; |
| 135 | struct timer_list vbus_timer; | 141 | struct timer_list vbus_timer; |
| 136 | struct work_struct vbus_timer_work; | 142 | struct work_struct vbus_timer_work; |
| 143 | struct regmap *matrix; | ||
| 137 | }; | 144 | }; |
| 138 | 145 | ||
| 139 | static inline struct at91_udc *to_udc(struct usb_gadget *g) | 146 | static inline struct at91_udc *to_udc(struct usb_gadget *g) |
