summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSascha Hauer <s.hauer@pengutronix.de>2019-06-11 11:33:35 +0200
committerSascha Hauer <s.hauer@pengutronix.de>2019-06-11 11:33:35 +0200
commita667fd0009dc9b3e984ae5d45462fc79cfc9684e (patch)
treee87efe40dccae393e054a73ac7257e9dada3f536
parent9cd032ac943aa00964ad853236358837dfa093c2 (diff)
parent3505a33d692026f0b48dfb7fab7c33327b24471f (diff)
downloadbarebox-a667fd0009dc9b3e984ae5d45462fc79cfc9684e.tar.gz
barebox-a667fd0009dc9b3e984ae5d45462fc79cfc9684e.tar.xz
Merge branch 'for-next/usb-phy'
-rw-r--r--arch/arm/mach-imx/Makefile2
-rw-r--r--arch/arm/mach-imx/include/mach/usb.h3
-rw-r--r--arch/arm/mach-imx/usb-imx6.c111
-rw-r--r--drivers/usb/imx/Kconfig1
-rw-r--r--drivers/usb/imx/imx-usb-phy.c87
5 files changed, 63 insertions, 141 deletions
diff --git a/arch/arm/mach-imx/Makefile b/arch/arm/mach-imx/Makefile
index 2b817e5dd8..fae81e109b 100644
--- a/arch/arm/mach-imx/Makefile
+++ b/arch/arm/mach-imx/Makefile
@@ -10,7 +10,7 @@ obj-$(CONFIG_ARCH_IMX51) += imx51.o imx5.o
pbl-$(CONFIG_ARCH_IMX51) += imx51.o imx5.o
obj-$(CONFIG_ARCH_IMX53) += imx53.o imx5.o esdctl-v4.o
pbl-$(CONFIG_ARCH_IMX53) += imx53.o imx5.o esdctl-v4.o
-obj-$(CONFIG_ARCH_IMX6) += imx6.o usb-imx6.o
+obj-$(CONFIG_ARCH_IMX6) += imx6.o
CFLAGS_imx6.o := -march=armv7-a
lwl-$(CONFIG_ARCH_IMX6) += imx6-mmdc.o
obj-$(CONFIG_ARCH_IMX7) += imx7.o
diff --git a/arch/arm/mach-imx/include/mach/usb.h b/arch/arm/mach-imx/include/mach/usb.h
index 3b5e24d1cc..3209bf9095 100644
--- a/arch/arm/mach-imx/include/mach/usb.h
+++ b/arch/arm/mach-imx/include/mach/usb.h
@@ -11,9 +11,6 @@
#define MX35_H1_USBTE_BIT (1 << 4)
#define MXC_EHCI_INTERFACE_SINGLE_UNI (2 << 0)
-int imx6_usb_phy2_disable_oc(void);
-int imx6_usb_phy2_enable(void);
-
#define USBCMD 0x140
#define USB_CMD_RESET 0x00000002
diff --git a/arch/arm/mach-imx/usb-imx6.c b/arch/arm/mach-imx/usb-imx6.c
deleted file mode 100644
index 4236bcb772..0000000000
--- a/arch/arm/mach-imx/usb-imx6.c
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- * Copyright (C) 2012 Steffen Trumtrar, Pengutronix
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of
- * the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation.
- *
- */
-
-#include <common.h>
-#include <io.h>
-#include <mach/imx6-regs.h>
-#include <mach/usb.h>
-
-#define SET 0x4
-#define CLR 0x8
-
-#define USBPHY_CTRL 0x30
-#define USB_OTG_CTRL 0x800
-#define USB_UH1_CTRL 0x804
-#define USB_UH2_CTRL 0x808
-#define USB_UH3_CTRL 0x80c
-
-#define USB_UH1_USBCMD 0x340
-
-#define USB_CMD_RUNSTOP (1 << 0)
-
-#define USB_OVER_CUR_DIS (1 << 7)
-#define USBPHY_CTRL_SFTRST (1 << 31)
-#define USBPHY_CTRL_CLKGATE (1 << 30)
-#define USBPHY_CTRL_ENUTMILEVEL3 (1 << 15)
-#define USBPHY_CTRL_ENUTMILEVEL2 (1 << 14)
-
-#define USBPHY1_PLL_480_CTRL_EN (1 << 13)
-#define USBPHY1_PLL_480_CTRL_POWER (1 << 12)
-#define USBPHY1_PLL_480_CTRL_EN_USB_CLK (1 << 6)
-#define USBPHY1_PLL_480_CTRL_BYPASS (1 << 16)
-
-int imx6_usb_phy2_disable_oc(void)
-{
- int val;
-
- /* disable over current detection */
- val = readl(MX6_USBOH3_USB_BASE_ADDR + USB_UH1_CTRL);
- val |= USB_OVER_CUR_DIS;
- writel(val, MX6_USBOH3_USB_BASE_ADDR + USB_UH1_CTRL);
- val = readl(MX6_USBOH3_USB_BASE_ADDR + USB_UH2_CTRL);
- val |= USB_OVER_CUR_DIS;
- writel(val, MX6_USBOH3_USB_BASE_ADDR + USB_UH2_CTRL);
- val = readl(MX6_USBOH3_USB_BASE_ADDR + USB_UH3_CTRL);
- val |= USB_OVER_CUR_DIS;
- writel(val, MX6_USBOH3_USB_BASE_ADDR + USB_UH3_CTRL);
-
- return 0;
-}
-
-int imx6_usb_phy2_enable(void)
-{
- int val;
-
- /* disable external charger detector or DP will be poor */
- writel(0x00180000, MX6_ANATOP_BASE_ADDR + 0x1b0);
- writel(0x00180000, MX6_ANATOP_BASE_ADDR + 0x210);
-
- /* enable usb pll */
- writel(USBPHY1_PLL_480_CTRL_EN |
- USBPHY1_PLL_480_CTRL_POWER |
- USBPHY1_PLL_480_CTRL_EN_USB_CLK, MX6_ANATOP_BASE_ADDR + 0x24);
-
- /* turn OFF clk bypass */
- /* at least on imx6 v1.0 this essential for usb to work */
- /* FIXME: test on v1.1. Datasheet declares bit as reserved */
- writel(USBPHY1_PLL_480_CTRL_BYPASS, MX6_ANATOP_BASE_ADDR + 0x28);
-
- /* stop then reset */
- val = readl(MX6_USBOH3_USB_BASE_ADDR + USB_UH1_USBCMD);
- val &= ~USB_CMD_RUNSTOP;
- writel(val, MX6_USBOH3_USB_BASE_ADDR + USB_UH1_USBCMD);
- while (readl(MX6_USBOH3_USB_BASE_ADDR + USB_UH1_USBCMD) & USB_CMD_RUNSTOP);
-
- val = readl(MX6_USBOH3_USB_BASE_ADDR + USB_UH1_USBCMD);
- val |= USB_CMD_RESET;
- writel(val, MX6_USBOH3_USB_BASE_ADDR + USB_UH1_USBCMD);
- while (readl(MX6_USBOH3_USB_BASE_ADDR + USB_UH1_USBCMD) & USB_CMD_RESET);
-
- /* reset usbphy */
- writel(USBPHY_CTRL_SFTRST, MX6_USBPHY2_BASE_ADDR + USBPHY_CTRL + SET);
- udelay(10);
- /* clr reset and clkgate */
- writel(USBPHY_CTRL_SFTRST | USBPHY_CTRL_CLKGATE, MX6_USBPHY2_BASE_ADDR + USBPHY_CTRL + CLR);
-
- /* clr all pwd bits => power up phy */
- writel(0xffffffff, MX6_USBPHY2_BASE_ADDR + CLR);
-
- /* set utmilvl2/3 */
- val = readl(MX6_USBPHY2_BASE_ADDR + USBPHY_CTRL);
- val |= USBPHY_CTRL_ENUTMILEVEL3 | USBPHY_CTRL_ENUTMILEVEL2;
- writel(val, MX6_USBPHY2_BASE_ADDR + USBPHY_CTRL + SET);
-
- return 0;
-}
diff --git a/drivers/usb/imx/Kconfig b/drivers/usb/imx/Kconfig
index 8e6f3156a1..07ca41b63a 100644
--- a/drivers/usb/imx/Kconfig
+++ b/drivers/usb/imx/Kconfig
@@ -17,3 +17,4 @@ config USB_IMX_CHIPIDEA
config USB_IMX_PHY
bool
default y if (ARCH_IMX6 || ARCH_VF610) && GENERIC_PHY
+ select STMP_DEVICE
diff --git a/drivers/usb/imx/imx-usb-phy.c b/drivers/usb/imx/imx-usb-phy.c
index 274153bd58..d4562285c0 100644
--- a/drivers/usb/imx/imx-usb-phy.c
+++ b/drivers/usb/imx/imx-usb-phy.c
@@ -23,47 +23,64 @@
#include <linux/phy/phy.h>
#include <linux/clk.h>
#include <linux/err.h>
+#include <stmp-device.h>
+#include <mfd/syscon.h>
-#define SET 0x4
-#define CLR 0x8
+#define HW_USBPHY_PWD 0x00
+#define HW_USBPHY_TX 0x10
+#define HW_USBPHY_CTRL 0x30
+#define HW_USBPHY_CTRL_SET 0x34
+#define HW_USBPHY_CTRL_CLR 0x38
-#define USBPHY_CTRL 0x30
+#define BM_USBPHY_CTRL_ENUTMILEVEL3 BIT(15)
+#define BM_USBPHY_CTRL_ENUTMILEVEL2 BIT(14)
+#define BM_USBPHY_CTRL_ENHOSTDISCONDETECT BIT(1)
-#define USBPHY_CTRL_SFTRST (1 << 31)
-#define USBPHY_CTRL_CLKGATE (1 << 30)
-#define USBPHY_CTRL_ENUTMILEVEL3 (1 << 15)
-#define USBPHY_CTRL_ENUTMILEVEL2 (1 << 14)
-#define USBPHY_CTRL_ENHOSTDISCONDETECT (1 << 1)
+#define ANADIG_USB1_CHRG_DETECT_SET 0x1b4
+#define ANADIG_USB2_CHRG_DETECT_SET 0x214
+#define ANADIG_USB1_CHRG_DETECT_EN_B BIT(20)
+#define ANADIG_USB1_CHRG_DETECT_CHK_CHRG_B BIT(19)
struct imx_usbphy {
struct usb_phy usb_phy;
struct phy *phy;
void __iomem *base;
+ void __iomem *anatop;
struct clk *clk;
struct phy_provider *provider;
+ int port_id;
};
static int imx_usbphy_phy_init(struct phy *phy)
{
struct imx_usbphy *imxphy = phy_get_drvdata(phy);
+ int ret;
clk_enable(imxphy->clk);
- /* reset usbphy */
- writel(USBPHY_CTRL_SFTRST, imxphy->base + USBPHY_CTRL + SET);
-
- udelay(10);
+ ret = stmp_reset_block(imxphy->base + HW_USBPHY_CTRL, false);
+ if (ret)
+ return ret;
- /* clr reset and clkgate */
- writel(USBPHY_CTRL_SFTRST | USBPHY_CTRL_CLKGATE,
- imxphy->base + USBPHY_CTRL + CLR);
-
- /* clr all pwd bits => power up phy */
- writel(0xffffffff, imxphy->base + CLR);
+ /* Power up the PHY */
+ writel(0, imxphy->base + HW_USBPHY_PWD);
/* set utmilvl2/3 */
- writel(USBPHY_CTRL_ENUTMILEVEL3 | USBPHY_CTRL_ENUTMILEVEL2,
- imxphy->base + USBPHY_CTRL + SET);
+ writel(BM_USBPHY_CTRL_ENUTMILEVEL3 | BM_USBPHY_CTRL_ENUTMILEVEL2,
+ imxphy->base + HW_USBPHY_CTRL_SET);
+
+ if (imxphy->anatop) {
+ unsigned int reg = imxphy->port_id ?
+ ANADIG_USB1_CHRG_DETECT_SET :
+ ANADIG_USB2_CHRG_DETECT_SET;
+ /*
+ * The external charger detector needs to be disabled,
+ * or the signal at DP will be poor
+ */
+ writel(ANADIG_USB1_CHRG_DETECT_EN_B |
+ ANADIG_USB1_CHRG_DETECT_CHK_CHRG_B,
+ imxphy->anatop + reg);
+ }
return 0;
}
@@ -71,11 +88,12 @@ static int imx_usbphy_phy_init(struct phy *phy)
static int imx_usbphy_notify_connect(struct usb_phy *phy,
enum usb_device_speed speed)
{
- struct imx_usbphy *imxphy = container_of(phy, struct imx_usbphy, usb_phy);
+ struct imx_usbphy *imxphy = container_of(phy, struct imx_usbphy,
+ usb_phy);
if (speed == USB_SPEED_HIGH) {
- writel(USBPHY_CTRL_ENHOSTDISCONDETECT,
- imxphy->base + USBPHY_CTRL + SET);
+ writel(BM_USBPHY_CTRL_ENHOSTDISCONDETECT,
+ imxphy->base + HW_USBPHY_CTRL_SET);
}
return 0;
@@ -84,10 +102,11 @@ static int imx_usbphy_notify_connect(struct usb_phy *phy,
static int imx_usbphy_notify_disconnect(struct usb_phy *phy,
enum usb_device_speed speed)
{
- struct imx_usbphy *imxphy = container_of(phy, struct imx_usbphy, usb_phy);
+ struct imx_usbphy *imxphy = container_of(phy, struct imx_usbphy,
+ usb_phy);
- writel(USBPHY_CTRL_ENHOSTDISCONDETECT,
- imxphy->base + USBPHY_CTRL + CLR);
+ writel(BM_USBPHY_CTRL_ENHOSTDISCONDETECT,
+ imxphy->base + HW_USBPHY_CTRL_CLR);
return 0;
}
@@ -115,11 +134,27 @@ static const struct phy_ops imx_phy_ops = {
static int imx_usbphy_probe(struct device_d *dev)
{
struct resource *iores;
+ struct device_node *np = dev->device_node;
int ret;
struct imx_usbphy *imxphy;
imxphy = xzalloc(sizeof(*imxphy));
+ ret = of_alias_get_id(np, "usbphy");
+ if (ret < 0) {
+ dev_dbg(dev, "failed to get alias id, errno %d\n", ret);
+ goto err_free;
+ }
+ imxphy->port_id = ret;
+
+ if (of_get_property(np, "fsl,anatop", NULL)) {
+ imxphy->anatop =
+ syscon_base_lookup_by_phandle(np, "fsl,anatop");
+ ret = PTR_ERR_OR_ZERO(imxphy->anatop);
+ if (ret)
+ goto err_free;
+ }
+
iores = dev_request_mem_resource(dev, 0);
if (IS_ERR(iores)) {
ret = PTR_ERR(iores);