lkml.org 
[lkml]   [2019]   [Oct]   [17]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    /
    From
    SubjectRE: [PATCH 2/2] usb: cdns3: Add TI specific wrapper driver
    Date
    Hi Roger,

    >The J721e platform comes with 2 Cadence USB3 controller
    >
    >instances. This driver supports the TI specific wrapper
    >
    >on this platform.
    >
    >
    >
    >Signed-off-by: Roger Quadros <rogerq@ti.com>
    >
    >Signed-off-by: Sekhar Nori <nsekhar@ti.com>
    >
    >---
    >
    > drivers/usb/cdns3/Kconfig | 10 ++
    >
    > drivers/usb/cdns3/Makefile | 1 +
    >
    > drivers/usb/cdns3/cdns3-ti.c | 244 +++++++++++++++++++++++++++++++++++
    >
    > 3 files changed, 255 insertions(+)
    >
    > create mode 100644 drivers/usb/cdns3/cdns3-ti.c
    >
    >
    >
    >diff --git a/drivers/usb/cdns3/Kconfig b/drivers/usb/cdns3/Kconfig
    >
    >index d0331613a355..2a1e89d12ed9 100644
    >
    >--- a/drivers/usb/cdns3/Kconfig
    >
    >+++ b/drivers/usb/cdns3/Kconfig
    >
    >@@ -43,4 +43,14 @@ config USB_CDNS3_PCI_WRAP
    >
    > If you choose to build this driver as module it will
    >
    > be dynamically linked and module will be called cdns3-pci.ko
    >
    >
    >
    >+config USB_CDNS3_TI
    >
    >+ tristate "Cadence USB3 support on TI platforms"
    >
    >+ depends on ARCH_K3 || COMPILE_TEST
    >
    >+ default USB_CDNS3
    >
    >+ help
    >
    >+ Say 'Y' or 'M' here if you are building for Texas Instruments
    >
    >+ platforms that contain Cadence USB3 controller core.
    >
    >+
    >
    >+ e.g. J721e.
    >
    >+
    >
    > endif
    >
    >diff --git a/drivers/usb/cdns3/Makefile b/drivers/usb/cdns3/Makefile
    >
    >index a703547350bb..948e6b88d1a9 100644
    >
    >--- a/drivers/usb/cdns3/Makefile
    >
    >+++ b/drivers/usb/cdns3/Makefile
    >
    >@@ -14,3 +14,4 @@ endif
    >
    > cdns3-$(CONFIG_USB_CDNS3_HOST) += host.o
    >
    >
    >
    > obj-$(CONFIG_USB_CDNS3_PCI_WRAP) += cdns3-pci-wrap.o
    >
    >+obj-$(CONFIG_USB_CDNS3_TI) += cdns3-ti.o
    >
    >diff --git a/drivers/usb/cdns3/cdns3-ti.c b/drivers/usb/cdns3/cdns3-ti.c
    >
    >new file mode 100644
    >
    >index 000000000000..7447f5fcbe64
    >
    >--- /dev/null
    >
    >+++ b/drivers/usb/cdns3/cdns3-ti.c
    >
    >@@ -0,0 +1,244 @@
    >
    >+// SPDX-License-Identifier: GPL-2.0
    >
    >+/**
    >
    >+ * cdns_ti-ti.c - TI specific Glue layer for Cadence USB Controller
    >
    >+ *
    >
    >+ * Copyright (C) 2019 Texas Instruments Incorporated - https://urldefense.proofpoint.com/v2/url?u=http-
    >3A__www.ti.com&d=DwIBAg&c=aUq983L2pue2FqKFoP6PGHMJQyoJ7kl3s3GZ-_haXqY&r=e1OgxfvkL0qo9XO6fX1gscva-
    >w03uSYC1nIyxl89-
    >rI&m=cRVMFQ8EW2o1zPxOk40aNbOduH3ZSMTGs3Gjr6j7DIw&s=CX3YTCKJekxIRkpi36cPmm8eEH1NK7Ipaag0MVAL4cc&e=
    >
    >+ */
    >
    >+
    >
    >+#include <linux/bits.h>
    >
    >+#include <linux/clk.h>
    >
    >+#include <linux/module.h>
    >
    >+#include <linux/kernel.h>
    >
    >+#include <linux/interrupt.h>
    >
    >+#include <linux/platform_device.h>
    >
    >+#include <linux/dma-mapping.h>
    >
    >+#include <linux/io.h>
    >
    >+#include <linux/of_platform.h>
    >
    >+#include <linux/pm_runtime.h>
    >
    >+
    >
    >+/* USB Wrapper register offsets */
    >
    >+#define USBSS_PID 0x0
    >
    >+#define USBSS_W1 0x4
    >
    >+#define USBSS_STATIC_CONFIG 0x8
    >
    >+#define USBSS_PHY_TEST 0xc
    >
    >+#define USBSS_DEBUG_CTRL 0x10
    >
    >+#define USBSS_DEBUG_INFO 0x14
    >
    >+#define USBSS_DEBUG_LINK_STATE 0x18
    >
    >+#define USBSS_DEVICE_CTRL 0x1c
    >
    >+
    >
    >+/* Wrapper 1 register bits */
    >
    >+#define USBSS_W1_PWRUP_RST BIT(0)
    >
    >+#define USBSS_W1_OVERCURRENT_SEL BIT(8)
    >
    >+#define USBSS_W1_MODESTRAP_SEL BIT(9)
    >
    >+#define USBSS_W1_OVERCURRENT BIT(16)
    >
    >+#define USBSS_W1_MODESTRAP_MASK GENMASK(18, 17)
    >
    >+#define USBSS_W1_MODESTRAP_SHIFT 17
    >
    >+#define USBSS_W1_USB2_ONLY BIT(19)
    >
    >+
    >
    >+/* Static config register bits */
    >
    >+#define USBSS1_STATIC_PLL_REF_SEL_MASK GENMASK(8, 5)
    >
    >+#define USBSS1_STATIC_PLL_REF_SEL_SHIFT 5
    >
    >+#define USBSS1_STATIC_LOOPBACK_MODE_MASK GENMASK(4, 3)
    >
    >+#define USBSS1_STATIC_LOOPBACK_MODE_SHIFT 3
    >
    >+#define USBSS1_STATIC_VBUS_SEL_MASK GENMASK(2, 1)
    >
    >+#define USBSS1_STATIC_VBUS_SEL_SHIFT 1
    >
    >+#define USBSS1_STATIC_LANE_REVERSE BIT(0)
    >
    >+
    >
    >+/* Modestrap modes */
    >
    >+enum modestrap_mode { USBSS_MODESTRAP_MODE_NONE,
    >
    >+ USBSS_MODESTRAP_MODE_HOST,
    >
    >+ USBSS_MODESTRAP_MODE_PERIPHERAL};
    >
    >+
    >
    >+struct cdns_ti {
    >
    >+ struct device *dev;
    >
    >+ void __iomem *usbss;
    >
    >+ int usb2_only:1;
    >
    >+ int vbus_divider:1;
    >
    >+ struct clk *usb2_refclk;
    >
    >+ struct clk *lpm_clk;
    >
    >+};
    >
    >+
    >
    >+static const int cdns_ti_rate_table[] = { /* in KHZ */
    >
    >+ 9600,
    >
    >+ 10000,
    >
    >+ 12000,
    >
    >+ 19200,
    >
    >+ 20000,
    >
    >+ 24000,
    >
    >+ 25000,
    >
    >+ 26000,
    >
    >+ 38400,
    >
    >+ 40000,
    >
    >+ 58000,
    >
    >+ 50000,
    >
    >+ 52000,
    >
    >+};
    >
    >+
    >
    >+static inline u32 cdns_ti_readl(struct cdns_ti *data, u32 offset)
    >
    >+{
    >
    >+ return readl(data->usbss + offset);
    >
    >+}
    >
    >+
    >
    >+static inline void cdns_ti_writel(struct cdns_ti *data, u32 offset, u32 value)
    >
    >+{
    >
    >+ writel(value, data->usbss + offset);
    >
    >+}
    >
    >+
    >
    >+static int cdns_ti_probe(struct platform_device *pdev)
    >
    >+{
    >
    >+ struct device *dev = &pdev->dev;
    >
    >+ struct device_node *node = pdev->dev.of_node;
    >
    >+ struct cdns_ti *data;
    >
    >+ struct resource *res;
    >
    >+ int error;
    >
    >+ u32 reg;
    >
    >+ int modestrap_mode;
    >
    >+ int rate_code, i;
    >
    >+ unsigned long rate;
    >
    >+
    >
    >+ data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
    >
    >+ if (!data)
    >
    >+ return -ENOMEM;
    >
    >+
    >
    >+ platform_set_drvdata(pdev, data);
    >
    >+
    >
    >+ data->dev = dev;
    >
    >+
    >
    >+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
    >
    >+ data->usbss = devm_ioremap_resource(dev, res);
    >
    >+ if (IS_ERR(data->usbss))
    >
    >+ return PTR_ERR(data->usbss);
    >
    >+
    >
    >+ data->usb2_refclk = devm_clk_get(dev, "usb2_refclk");
    >
    >+ if (IS_ERR(data->usb2_refclk)) {
    >
    >+ dev_err(dev, "can't get usb2_refclk\n");
    >
    >+ return PTR_ERR(data->usb2_refclk);
    >
    >+ }
    >
    >+
    >
    >+ data->lpm_clk = devm_clk_get(dev, "lpm_clk");
    >
    >+ if (IS_ERR(data->lpm_clk)) {
    >
    >+ dev_err(dev, "can't get lpm_clk\n");
    >
    >+ return PTR_ERR(data->lpm_clk);
    >
    >+ }
    >
    >+
    >
    >+ rate = clk_get_rate(data->usb2_refclk);
    >
    >+ rate /= 1000; /* To KHz */
    >
    >+ for (i = 0; i < ARRAY_SIZE(cdns_ti_rate_table); i++) {
    >
    >+ if (cdns_ti_rate_table[i] == rate)
    >
    >+ break;
    >
    >+ }
    >
    >+
    >
    >+ if (i == ARRAY_SIZE(cdns_ti_rate_table)) {
    >
    >+ dev_err(dev, "unsupported usb2_refclk rate: %lu KHz\n", rate);
    >
    >+ return -EINVAL;
    >
    >+ }
    >
    >+
    >
    >+ rate_code = i;
    >
    >+
    >
    >+ pm_runtime_enable(dev);
    >
    >+ error = pm_runtime_get_sync(dev);
    >
    >+ if (error < 0) {
    >
    >+ dev_err(dev, "pm_runtime_get_sync failed: %d\n", error);
    >
    >+ goto err_get;
    >
    >+ }
    >
    >+
    >
    >+ /* assert RESET */
    >
    >+ reg = cdns_ti_readl(data, USBSS_W1);
    >
    >+ reg &= ~USBSS_W1_PWRUP_RST;
    >
    >+ cdns_ti_writel(data, USBSS_W1, reg);
    >
    >+
    >
    >+ /* set static config */
    >
    >+ reg = cdns_ti_readl(data, USBSS_STATIC_CONFIG);
    >
    >+ reg &= ~USBSS1_STATIC_PLL_REF_SEL_MASK;
    >
    >+ reg |= rate_code << USBSS1_STATIC_PLL_REF_SEL_SHIFT;
    >
    >+
    >
    >+ reg &= ~USBSS1_STATIC_VBUS_SEL_MASK;
    >
    >+ data->vbus_divider = device_property_read_bool(dev, "ti,vbus-divider");
    >
    >+ if (data->vbus_divider)
    >
    >+ reg |= 1 << USBSS1_STATIC_VBUS_SEL_SHIFT;
    >
    >+
    >
    >+ cdns_ti_writel(data, USBSS_STATIC_CONFIG, reg);
    >
    >+ reg = cdns_ti_readl(data, USBSS_STATIC_CONFIG);
    >
    >+
    >
    >+ /* set USB2_ONLY mode if requested */
    >
    >+ reg = cdns_ti_readl(data, USBSS_W1);
    >
    >+ data->usb2_only = device_property_read_bool(dev, "ti,usb2-only");
    >
    >+ if (data->usb2_only)
    >
    >+ reg |= USBSS_W1_USB2_ONLY;
    >
    >+
    >
    >+ /* set modestrap */
    >
    >+ if (device_property_read_bool(dev, "ti,modestrap-host"))
    >
    >+ modestrap_mode = USBSS_MODESTRAP_MODE_HOST;
    >
    >+ else if (device_property_read_bool(dev, "ti,modestrap-peripheral"))
    >
    >+ modestrap_mode = USBSS_MODESTRAP_MODE_PERIPHERAL;
    >
    >+ else
    >
    >+ modestrap_mode = USBSS_MODESTRAP_MODE_NONE;
    >
    >+
    >
    >+ reg |= USBSS_W1_MODESTRAP_SEL;
    >
    >+ reg &= ~USBSS_W1_MODESTRAP_MASK;
    >
    >+ reg |= modestrap_mode << USBSS_W1_MODESTRAP_SHIFT;
    >
    >+ cdns_ti_writel(data, USBSS_W1, reg);
    >
    >+
    >
    >+ /* de-assert RESET */
    >
    >+ reg |= USBSS_W1_PWRUP_RST;
    >
    >+ cdns_ti_writel(data, USBSS_W1, reg);
    >
    >+
    >
    >+ error = of_platform_populate(node, NULL, NULL, dev);
    >
    >+ if (error) {
    >
    >+ dev_err(dev, "failed to create children: %d\n", error);
    >
    >+ goto err;
    >
    >+ }
    >
    >+
    >
    >+ return 0;
    >
    >+
    >
    >+err:
    >
    >+ pm_runtime_put_sync(data->dev);
    >
    >+err_get:
    >
    >+ pm_runtime_disable(data->dev);
    >
    >+
    >
    >+ return error;
    >
    >+}
    >
    >+
    >
    >+static int cdns_ti_remove_core(struct device *dev, void *c)
    >
    >+{
    >
    >+ struct platform_device *pdev = to_platform_device(dev);
    >
    >+
    >
    >+ platform_device_unregister(pdev);
    >
    >+
    >
    >+ return 0;
    >
    >+}
    >
    >+
    >
    >+static int cdns_ti_remove(struct platform_device *pdev)
    >
    >+{
    >
    >+ struct device *dev = &pdev->dev;
    >
    >+
    >
    >+ device_for_each_child(dev, NULL, cdns_ti_remove_core);
    >
    >+ pm_runtime_put_sync(dev);
    >
    >+ pm_runtime_disable(dev);
    >
    >+
    >
    >+ platform_set_drvdata(pdev, NULL);
    >
    >+
    >
    >+ return 0;
    >
    >+}
    >
    >+
    >
    >+static const struct of_device_id cdns_ti_of_match[] = {
    >
    >+ { .compatible = "ti,j721e-usb", },
    >
    >+ {},
    >
    >+};
    >
    >+MODULE_DEVICE_TABLE(of, cdns_ti_of_match);
    >
    >+
    >
    >+static struct platform_driver cdns_ti_driver = {
    >
    >+ .probe = cdns_ti_probe,
    >
    >+ .remove = cdns_ti_remove,
    >
    >+ .driver = {
    >
    >+ .name = "cdns3-ti",
    >
    >+ .of_match_table = cdns_ti_of_match,
    >
    >+ },
    >
    >+};
    >
    >+
    >
    >+module_platform_driver(cdns_ti_driver);
    >
    >+
    >
    >+MODULE_ALIAS("platform:cdns3-ti");
    >
    >+MODULE_AUTHOR("Roger Quadros <rogerq@ti.com>");
    >
    >+MODULE_LICENSE("GPL v2");
    >
    >+MODULE_DESCRIPTION("Cadence USB3 TI Glue Layer");
    >


    Reviewed-by: Pawel Laszczak <pawell@cadence.com>

    Regards,
    Pawel

    >--
    >
    >Texas Instruments Finland Oy, Porkkalankatu 22, 00180 Helsinki.
    >
    >Y-tunnus/Business ID: 0615521-4. Kotipaikka/Domicile: Helsinki
    >
    >

    \
     
     \ /
      Last update: 2019-10-17 06:12    [W:4.018 / U:0.012 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site