oxnas: reboot target
[openwrt/openwrt.git] / target / linux / oxnas / files / drivers / usb / host / ehci-oxnas.c
index 23c5061ec57b182378e5971114a30d46d90d45f4..79c4fa3a950a44dca4f289733f129d63c2021ba7 100644 (file)
 #include <linux/of.h>
 #include <linux/of_address.h>
 #include <linux/of_irq.h>
+#include <linux/mfd/syscon.h>
 #include <linux/usb.h>
 #include <linux/usb/hcd.h>
 #include <linux/dma-mapping.h>
 #include <linux/clk.h>
+#include <linux/regmap.h>
 #include <linux/reset.h>
-#include <mach/hardware.h>
-#include <mach/utils.h>
+
+#define USBHSMPH_CTRL_REGOFFSET                0x40
+#define USBHSMPH_STAT_REGOFFSET                0x44
+#define REF300_DIV_REGOFFSET           0xF8
+#define USBHSPHY_CTRL_REGOFFSET                0x84
+#define USB_CTRL_REGOFFSET             0x90
+#define PLLB_DIV_CTRL_REGOFFSET                0x1000F8
+#define USBHSPHY_SUSPENDM_MANUAL_ENABLE                16
+#define USBHSPHY_SUSPENDM_MANUAL_STATE         15
+#define USBHSPHY_ATE_ESET                      14
+#define USBHSPHY_TEST_DIN                      6
+#define USBHSPHY_TEST_ADD                      2
+#define USBHSPHY_TEST_DOUT_SEL                 1
+#define USBHSPHY_TEST_CLK                      0
+
+#define USB_CTRL_USBAPHY_CKSEL_SHIFT   5
+#define USB_CLK_XTAL0_XTAL1            (0 << USB_CTRL_USBAPHY_CKSEL_SHIFT)
+#define USB_CLK_XTAL0                  (1 << USB_CTRL_USBAPHY_CKSEL_SHIFT)
+#define USB_CLK_INTERNAL               (2 << USB_CTRL_USBAPHY_CKSEL_SHIFT)
+
+#define USBAMUX_DEVICE                 BIT(4)
+
+#define USBPHY_REFCLKDIV_SHIFT         2
+#define USB_PHY_REF_12MHZ              (0 << USBPHY_REFCLKDIV_SHIFT)
+#define USB_PHY_REF_24MHZ              (1 << USBPHY_REFCLKDIV_SHIFT)
+#define USB_PHY_REF_48MHZ              (2 << USBPHY_REFCLKDIV_SHIFT)
+
+#define USB_CTRL_USB_CKO_SEL_BIT       0
+
+#define USB_INT_CLK_XTAL               0
+#define USB_INT_CLK_REF300             2
+#define USB_INT_CLK_PLLB               3
+
+#define REF300_DIV_INT_SHIFT            8
+#define REF300_DIV_FRAC_SHIFT           0
+#define REF300_DIV_INT(val)             ((val) << REF300_DIV_INT_SHIFT)
+#define REF300_DIV_FRAC(val)            ((val) << REF300_DIV_FRAC_SHIFT)
+
+#define PLLB_BYPASS                     1
+#define PLLB_ENSAT                      3
+#define PLLB_OUTDIV                     4
+#define PLLB_REFDIV                     8
+#define PLLB_DIV_INT_SHIFT              8
+#define PLLB_DIV_FRAC_SHIFT             0
+#define PLLB_DIV_INT(val)               ((val) << PLLB_DIV_INT_SHIFT)
+#define PLLB_DIV_FRAC(val)              ((val) << PLLB_DIV_FRAC_SHIFT)
 
 #include "ehci.h"
 
@@ -33,6 +79,7 @@ struct oxnas_hcd {
        struct reset_control *rst_host;
        struct reset_control *rst_phya;
        struct reset_control *rst_phyb;
+       struct regmap *syscon;
 };
 
 #define DRIVER_DESC "Oxnas On-Chip EHCI Host Controller"
@@ -41,21 +88,16 @@ static struct hc_driver __read_mostly oxnas_hc_driver;
 
 static void start_oxnas_usb_ehci(struct oxnas_hcd *oxnas)
 {
-       u32 reg;
-
        if (oxnas->use_pllb) {
                /* enable pllb */
                clk_prepare_enable(oxnas->refsrc);
                /* enable ref600 */
                clk_prepare_enable(oxnas->phyref);
                /* 600MHz pllb divider for 12MHz */
-               writel(PLLB_DIV_INT(50) | PLLB_DIV_FRAC(0),
-                       SEC_CTRL_PLLB_DIV_CTRL);
-
+               regmap_write_bits(oxnas->syscon, PLLB_DIV_CTRL_REGOFFSET, 0xffff, PLLB_DIV_INT(50) | PLLB_DIV_FRAC(0));
        } else {
                /* ref 300 divider for 12MHz */
-               writel(REF300_DIV_INT(25) | REF300_DIV_FRAC(0),
-                       SYS_CTRL_REF300_DIV);
+               regmap_write_bits(oxnas->syscon, REF300_DIV_REGOFFSET, 0xffff, REF300_DIV_INT(25) | REF300_DIV_FRAC(0));
        }
 
        /* Ensure the USB block is properly reset */
@@ -65,31 +107,34 @@ static void start_oxnas_usb_ehci(struct oxnas_hcd *oxnas)
 
        /* Force the high speed clock to be generated all the time, via serial
         programming of the USB HS PHY */
-       writel((2UL << USBHSPHY_TEST_ADD) |
-                  (0xe0UL << USBHSPHY_TEST_DIN), SYS_CTRL_USBHSPHY_CTRL);
+       regmap_write_bits(oxnas->syscon, USBHSPHY_CTRL_REGOFFSET, 0xffff,
+                         (2UL << USBHSPHY_TEST_ADD) |
+                         (0xe0UL << USBHSPHY_TEST_DIN));
 
-       writel((1UL << USBHSPHY_TEST_CLK) |
-                  (2UL << USBHSPHY_TEST_ADD) |
-                  (0xe0UL << USBHSPHY_TEST_DIN), SYS_CTRL_USBHSPHY_CTRL);
+       regmap_write_bits(oxnas->syscon, USBHSPHY_CTRL_REGOFFSET, 0xffff,
+                         (1UL << USBHSPHY_TEST_CLK) |
+                         (2UL << USBHSPHY_TEST_ADD) |
+                         (0xe0UL << USBHSPHY_TEST_DIN));
 
-       writel((0xfUL << USBHSPHY_TEST_ADD) |
-                  (0xaaUL << USBHSPHY_TEST_DIN), SYS_CTRL_USBHSPHY_CTRL);
+       regmap_write_bits(oxnas->syscon, USBHSPHY_CTRL_REGOFFSET, 0xffff,
+                         (0xfUL << USBHSPHY_TEST_ADD) |
+                         (0xaaUL << USBHSPHY_TEST_DIN));
 
-       writel((1UL << USBHSPHY_TEST_CLK) |
-                  (0xfUL << USBHSPHY_TEST_ADD) |
-                  (0xaaUL << USBHSPHY_TEST_DIN), SYS_CTRL_USBHSPHY_CTRL);
+       regmap_write_bits(oxnas->syscon, USBHSPHY_CTRL_REGOFFSET, 0xffff,
+                         (1UL << USBHSPHY_TEST_CLK) |
+                         (0xfUL << USBHSPHY_TEST_ADD) |
+                         (0xaaUL << USBHSPHY_TEST_DIN));
 
        if (oxnas->use_pllb) /* use pllb clock */
-               writel(USB_CLK_INTERNAL | USB_INT_CLK_PLLB, SYS_CTRL_USB_CTRL);
+               regmap_write_bits(oxnas->syscon, USB_CTRL_REGOFFSET, 0xffff,
+                                 USB_CLK_INTERNAL | USB_INT_CLK_PLLB);
        else /* use ref300 derived clock */
-               writel(USB_CLK_INTERNAL | USB_INT_CLK_REF300,
-                       SYS_CTRL_USB_CTRL);
+               regmap_write_bits(oxnas->syscon, USB_CTRL_REGOFFSET, 0xffff,
+                                 USB_CLK_INTERNAL | USB_INT_CLK_REF300);
 
        if (oxnas->use_phya) {
                /* Configure USB PHYA as a host */
-               reg = readl(SYS_CTRL_USB_CTRL);
-               reg &= ~USBAMUX_DEVICE;
-               writel(reg, SYS_CTRL_USB_CTRL);
+               regmap_update_bits(oxnas->syscon, USB_CTRL_REGOFFSET, USBAMUX_DEVICE, 0);
        }
 
        /* Enable the clock to the USB block */
@@ -172,8 +217,14 @@ static int ehci_oxnas_drv_probe(struct platform_device *ofdev)
 
        oxnas = (struct oxnas_hcd *)hcd_to_ehci(hcd)->priv;
 
-       oxnas->use_pllb = of_property_read_bool(np, "plxtch,ehci_use_pllb");
-       oxnas->use_phya = of_property_read_bool(np, "plxtch,ehci_use_phya");
+       oxnas->use_pllb = of_property_read_bool(np, "oxsemi,ehci_use_pllb");
+       oxnas->use_phya = of_property_read_bool(np, "oxsemi,ehci_use_phya");
+
+       oxnas->syscon = syscon_regmap_lookup_by_phandle(np, "oxsemi,sys-ctrl");
+       if (IS_ERR(oxnas->syscon)) {
+               err = PTR_ERR(oxnas->syscon);
+               goto err_syscon;
+       }
 
        oxnas->clk = of_clk_get_by_name(np, "usb");
        if (IS_ERR(oxnas->clk)) {
@@ -232,7 +283,7 @@ static int ehci_oxnas_drv_probe(struct platform_device *ofdev)
 
        start_oxnas_usb_ehci(oxnas);
 
-       err = usb_add_hcd(hcd, irq, IRQF_SHARED | IRQF_DISABLED);
+       err = usb_add_hcd(hcd, irq, IRQF_SHARED);
        if (err)
                goto err_hcd;
 
@@ -249,6 +300,7 @@ err_phyref:
                clk_put(oxnas->refsrc);
 err_refsrc:
        clk_put(oxnas->clk);
+err_syscon:
 err_clk:
 err_ioremap:
 err_res:
@@ -276,7 +328,7 @@ static int ehci_oxnas_drv_remove(struct platform_device *pdev)
 }
 
 static const struct of_device_id oxnas_ehci_dt_ids[] = {
-       { .compatible = "plxtch,nas782x-ehci" },
+       { .compatible = "plxtech,nas782x-ehci" },
        { /* sentinel */ }
 };