summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSam Ravnborg <sam@ravnborg.org>2017-07-20 22:05:21 +0200
committerSascha Hauer <s.hauer@pengutronix.de>2017-09-06 14:21:24 +0200
commitc854c4de8f3a112ae802998c3b1fd22f2c12ffb5 (patch)
treea62fc4eb3067ffe7c19d63a7af8ec9d585904d6f
parente272a2b1090efe3efd1c2bdaeb1f2ce4d6abd386 (diff)
downloadbarebox-c854c4de8f3a112ae802998c3b1fd22f2c12ffb5.tar.gz
barebox-c854c4de8f3a112ae802998c3b1fd22f2c12ffb5.tar.xz
at91_udc: add DT support
Based on the linux kernel version of the same driver. Needs to adjust clock names as the clock names used in the device tree does not match the clocknames used in platform_data. The clocknames in the device tree are not unique, so it was not an option to rename the clocks. It boots and the driver is discovered - no further testing done. $ devinfo fff78000.gadget Resources: num: 0 name: /ahb/apb/gadget@fff78000 start: 0xfff78000 size: 0x00004000 Driver: at91_udc Bus: platform Parameters: vbus: 1 (type: bool) Device node: /ahb/apb/gadget@fff78000 gadget@fff78000 { compatible = "atmel,at91sam9263-udc"; reg = <0xfff78000 0x4000>; interrupts = <0x18 0x4 0x2>; clocks = <0x26 0x27>; clock-names = "pclk", "hclk"; status = "okay"; atmel,vbus-gpio = <0x28 0x19 0x0>; }; Signed-off-by: Sam Ravnborg <sam@ravnborg.org> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
-rw-r--r--drivers/usb/gadget/at91_udc.c56
1 files changed, 45 insertions, 11 deletions
diff --git a/drivers/usb/gadget/at91_udc.c b/drivers/usb/gadget/at91_udc.c
index 5f6bebc733..18427114d1 100644
--- a/drivers/usb/gadget/at91_udc.c
+++ b/drivers/usb/gadget/at91_udc.c
@@ -21,7 +21,7 @@
#include <clock.h>
#include <usb/ch9.h>
#include <usb/gadget.h>
-#include <gpio.h>
+#include <of_gpio.h>
#include <linux/list.h>
#include <linux/clk.h>
@@ -1375,6 +1375,22 @@ static void at91_udc_gadget_poll(struct usb_gadget *gadget)
at91_udc_irq(udc);
}
+static void __init at91udc_of_init(struct at91_udc *udc, struct device_node *np)
+{
+ enum of_gpio_flags flags;
+ struct at91_udc_data *board;
+
+ board = &udc->board;
+
+ board->vbus_pin = of_get_named_gpio_flags(np, "atmel,vbus-gpio", 0,
+ &flags);
+ board->vbus_active_low = (flags & OF_GPIO_ACTIVE_LOW) ? 1 : 0;
+
+ board->pullup_pin = of_get_named_gpio_flags(np, "atmel,pullup-gpio", 0,
+ &flags);
+ board->pullup_active_low = (flags & OF_GPIO_ACTIVE_LOW) ? 1 : 0;
+}
+
/*-------------------------------------------------------------------------*/
static int __init at91udc_probe(struct device_d *dev)
@@ -1382,18 +1398,29 @@ static int __init at91udc_probe(struct device_d *dev)
struct resource *iores;
struct at91_udc *udc = &controller;
int retval;
-
- if (!dev->platform_data) {
- /* small (so we copy it) but critical! */
- DBG(udc, "missing platform_data\n");
- return -ENODEV;
- }
+ const char *iclk_name;
+ const char *fclk_name;
/* init software state */
udc->dev = dev;
- udc->board = *(struct at91_udc_data *) dev->platform_data;
udc->enabled = 0;
+ if (dev->platform_data) {
+ /* small (so we copy it) */
+ udc->board = *(struct at91_udc_data *)dev->platform_data;
+ iclk_name = "udc_clk";
+ fclk_name = "udpck";
+ } else {
+ if (!IS_ENABLED(CONFIG_OFDEVICE) || !dev->device_node) {
+ dev_err(dev, "no DT and no platform_data\n");
+ return -ENODEV;
+ }
+
+ at91udc_of_init(udc, dev->device_node);
+ iclk_name = "pclk";
+ fclk_name = "hclk";
+ }
+
/* rm9200 needs manual D+ pullup; off by default */
if (cpu_is_at91rm9200()) {
if (udc->board.pullup_pin <= 0) {
@@ -1435,8 +1462,8 @@ static int __init at91udc_probe(struct device_d *dev)
udc_reinit(udc);
/* get interface and function clocks */
- udc->iclk = clk_get(dev, "udc_clk");
- udc->fclk = clk_get(dev, "udpck");
+ udc->iclk = clk_get(dev, iclk_name);
+ udc->fclk = clk_get(dev, fclk_name);
if (IS_ERR(udc->iclk) || IS_ERR(udc->fclk)) {
DBG(udc, "clocks missing\n");
retval = -ENODEV;
@@ -1491,10 +1518,17 @@ fail0:
DBG(udc, "%s probe failed, %d\n", driver_name, retval);
return retval;
}
-
+static const struct of_device_id at91_udc_dt_ids[] = {
+ { .compatible = "atmel,at91rm9200-udc" },
+ { .compatible = "atmel,at91sam9260-udc" },
+ { .compatible = "atmel,at91sam9261-udc" },
+ { .compatible = "atmel,at91sam9263-udc" },
+ { /* sentinel */ }
+};
static struct driver_d at91_udc_driver = {
.name = driver_name,
.probe = at91udc_probe,
+ .of_compatible = DRV_OF_COMPAT(at91_udc_dt_ids),
};
device_platform_driver(at91_udc_driver);