#define USBDRD_UCTL_ECC 0xf0
#define USBDRD_UCTL_SPARE1 0xf8
-static DEFINE_MUTEX(dwc3_octeon_clocks_mutex);
+struct dwc3_octeon {
+ struct device *dev;
+ void __iomem *base;
+};
#ifdef CONFIG_CAVIUM_OCTEON_SOC
#include <asm/octeon/octeon.h>
static inline void dwc3_octeon_writeq(void __iomem *base, uint64_t val) { }
static inline void dwc3_octeon_config_gpio(int index, int gpio) { }
+
+static uint64_t octeon_get_io_clock_rate(void)
+{
+ return 150000000;
+}
#endif
static int dwc3_octeon_get_divider(void)
dwc3_octeon_writeq(uctl_ctl_reg, val);
}
-static int __init dwc3_octeon_device_init(void)
+static int dwc3_octeon_probe(struct platform_device *pdev)
{
- const char compat_node_name[] = "cavium,octeon-7130-usb-uctl";
- struct platform_device *pdev;
- struct device_node *node;
- struct resource *res;
- void __iomem *base;
+ struct device *dev = &pdev->dev;
+ struct device_node *node = dev->of_node;
+ struct dwc3_octeon *octeon;
+ int err;
- /*
- * There should only be three universal controllers, "uctl"
- * in the device tree. Two USB and a SATA, which we ignore.
- */
- node = NULL;
- do {
- node = of_find_node_by_name(node, "uctl");
- if (!node)
- return -ENODEV;
-
- if (of_device_is_compatible(node, compat_node_name)) {
- pdev = of_find_device_by_node(node);
- if (!pdev)
- return -ENODEV;
-
- /*
- * The code below maps in the registers necessary for
- * setting up the clocks and reseting PHYs. We must
- * release the resources so the dwc3 subsystem doesn't
- * know the difference.
- */
- base = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
- if (IS_ERR(base)) {
- put_device(&pdev->dev);
- return PTR_ERR(base);
- }
+ octeon = devm_kzalloc(dev, sizeof(*octeon), GFP_KERNEL);
+ if (!octeon)
+ return -ENOMEM;
- mutex_lock(&dwc3_octeon_clocks_mutex);
- if (dwc3_octeon_clocks_start(&pdev->dev, base) == 0)
- dev_info(&pdev->dev, "clocks initialized.\n");
- dwc3_octeon_set_endian_mode(base);
- dwc3_octeon_phy_reset(base);
- mutex_unlock(&dwc3_octeon_clocks_mutex);
- devm_iounmap(&pdev->dev, base);
- devm_release_mem_region(&pdev->dev, res->start,
- resource_size(res));
- put_device(&pdev->dev);
- }
- } while (node != NULL);
+ octeon->dev = dev;
+ octeon->base = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(octeon->base))
+ return PTR_ERR(octeon->base);
- return 0;
+ err = dwc3_octeon_clocks_start(dev, octeon->base);
+ if (err)
+ return err;
+
+ dwc3_octeon_set_endian_mode(octeon->base);
+ dwc3_octeon_phy_reset(octeon->base);
+
+ platform_set_drvdata(pdev, octeon);
+
+ return of_platform_populate(node, NULL, NULL, dev);
+}
+
+static void dwc3_octeon_remove(struct platform_device *pdev)
+{
+ struct dwc3_octeon *octeon = platform_get_drvdata(pdev);
+
+ of_platform_depopulate(octeon->dev);
+ platform_set_drvdata(pdev, NULL);
}
-device_initcall(dwc3_octeon_device_init);
+static const struct of_device_id dwc3_octeon_of_match[] = {
+ { .compatible = "cavium,octeon-7130-usb-uctl" },
+ { },
+};
+MODULE_DEVICE_TABLE(of, dwc3_octeon_of_match);
+
+static struct platform_driver dwc3_octeon_driver = {
+ .probe = dwc3_octeon_probe,
+ .remove_new = dwc3_octeon_remove,
+ .driver = {
+ .name = "dwc3-octeon",
+ .of_match_table = dwc3_octeon_of_match,
+ },
+};
+module_platform_driver(dwc3_octeon_driver);
+
+MODULE_ALIAS("platform:dwc3-octeon");
MODULE_AUTHOR("David Daney <david.daney@cavium.com>");
MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("USB driver for OCTEON III SoC");
+MODULE_DESCRIPTION("DesignWare USB3 OCTEON III Glue Layer");