aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/oxnas/files/drivers/usb/host/ehci-oxnas.c
diff options
context:
space:
mode:
Diffstat (limited to 'target/linux/oxnas/files/drivers/usb/host/ehci-oxnas.c')
-rw-r--r--target/linux/oxnas/files/drivers/usb/host/ehci-oxnas.c106
1 files changed, 79 insertions, 27 deletions
diff --git a/target/linux/oxnas/files/drivers/usb/host/ehci-oxnas.c b/target/linux/oxnas/files/drivers/usb/host/ehci-oxnas.c
index 15578a3027..79c4fa3a95 100644
--- a/target/linux/oxnas/files/drivers/usb/host/ehci-oxnas.c
+++ b/target/linux/oxnas/files/drivers/usb/host/ehci-oxnas.c
@@ -14,13 +14,59 @@
#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, "plxtech,ehci_use_pllb");
- oxnas->use_phya = of_property_read_bool(np, "plxtech,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)) {
@@ -249,6 +300,7 @@ err_phyref:
clk_put(oxnas->refsrc);
err_refsrc:
clk_put(oxnas->clk);
+err_syscon:
err_clk:
err_ioremap:
err_res: