diff options
author | Boris Brezillon <boris.brezillon@free-electrons.com> | 2015-01-14 11:22:02 -0500 |
---|---|---|
committer | Nicolas Ferre <nicolas.ferre@atmel.com> | 2015-01-15 08:52:07 -0500 |
commit | f0bceab4e3b528e799aba8fda8d2936fcfd41f1f (patch) | |
tree | 7093239025b63922fa6efff9f10834c9fcb8912d | |
parent | 422cde259ab62fcddcb3e50f44f761cf26982c1e (diff) |
usb: gadget: at91_udc: Rework for multi-platform kernel support
cpu_is_at91xxx are a set of macros defined in mach/cpu.h and are here used
to detect the SoC we are booting on.
Use compatible string + a caps structure to replace those cpu_is_xxx tests.
Remove all mach and asm headers (which are now unused).
Signed-off-by: Boris Brezillon <boris.brezillon@free-electrons.com>
Acked-by: Alexandre Belloni <alexandre.belloni@free-electrons.com>
Acked-by: Felipe Balbi <balbi@ti.com>
Signed-off-by: Nicolas Ferre <nicolas.ferre@atmel.com>
-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) |