From: Stephen Boyd <stephen.boyd@linaro.org> To: linux-usb@vger.kernel.org Cc: linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, linux-arm-msm@vger.kernel.org, Andy Gross <andy.gross@linaro.org>, Bjorn Andersson <bjorn.andersson@linaro.org>, Neil Armstrong <narmstrong@baylibre.com>, Arnd Bergmann <arnd@arndb.de>, Felipe Balbi <balbi@kernel.org>, Peter Chen <peter.chen@nxp.com>, Greg Kroah-Hartman <gregkh@linuxfoundation.org>, Heikki Krogerus <heikki.krogerus@linux.intel.com> Subject: [PATCH 09/21] usb: chipidea: Add support for ULPI PHY bus Date: Sun, 26 Jun 2016 00:28:26 -0700 [thread overview] Message-ID: <20160626072838.28082-10-stephen.boyd@linaro.org> (raw) In-Reply-To: <20160626072838.28082-1-stephen.boyd@linaro.org> Some phys for the chipidea controller are controlled via the ULPI viewport. Add support for the ULPI bus so that these sorts of phys can be probed and read/written automatically without having to duplicate the viewport logic in each phy driver. Cc: Peter Chen <peter.chen@nxp.com> Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Cc: Heikki Krogerus <heikki.krogerus@linux.intel.com> Signed-off-by: Stephen Boyd <stephen.boyd@linaro.org> --- drivers/usb/chipidea/Kconfig | 7 +++ drivers/usb/chipidea/Makefile | 1 + drivers/usb/chipidea/ci.h | 20 ++++++++ drivers/usb/chipidea/core.c | 30 ++++++++--- drivers/usb/chipidea/ulpi.c | 113 ++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 165 insertions(+), 6 deletions(-) create mode 100644 drivers/usb/chipidea/ulpi.c diff --git a/drivers/usb/chipidea/Kconfig b/drivers/usb/chipidea/Kconfig index 3644a3500b70..4f8c342a8865 100644 --- a/drivers/usb/chipidea/Kconfig +++ b/drivers/usb/chipidea/Kconfig @@ -37,4 +37,11 @@ config USB_CHIPIDEA_HOST Say Y here to enable host controller functionality of the ChipIdea driver. +config USB_CHIPIDEA_ULPI + bool "ChipIdea ULPI PHY support" + depends on USB_ULPI_BUS=y || USB_ULPI_BUS=USB_CHIPIDEA + help + Say Y here if you have a ULPI PHY attached to your ChipIdea + controller. + endif diff --git a/drivers/usb/chipidea/Makefile b/drivers/usb/chipidea/Makefile index 518e445476c3..39fca5715ed3 100644 --- a/drivers/usb/chipidea/Makefile +++ b/drivers/usb/chipidea/Makefile @@ -4,6 +4,7 @@ ci_hdrc-y := core.o otg.o debug.o ci_hdrc-$(CONFIG_USB_CHIPIDEA_UDC) += udc.o ci_hdrc-$(CONFIG_USB_CHIPIDEA_HOST) += host.o ci_hdrc-$(CONFIG_USB_OTG_FSM) += otg_fsm.o +ci_hdrc-$(CONFIG_USB_CHIPIDEA_ULPI) += ulpi.o # Glue/Bridge layers go here diff --git a/drivers/usb/chipidea/ci.h b/drivers/usb/chipidea/ci.h index f87805235caa..14aa20525547 100644 --- a/drivers/usb/chipidea/ci.h +++ b/drivers/usb/chipidea/ci.h @@ -18,6 +18,8 @@ #include <linux/usb.h> #include <linux/usb/gadget.h> #include <linux/usb/otg-fsm.h> +#include <linux/usb/otg.h> +#include <linux/ulpi/interface.h> /****************************************************************************** * DEFINE @@ -52,6 +54,7 @@ enum ci_hw_regs { OP_ENDPTLISTADDR, OP_TTCTRL, OP_BURSTSIZE, + OP_ULPI_VIEWPORT, OP_PORTSC, OP_DEVLC, OP_OTGSC, @@ -187,6 +190,7 @@ struct hw_bank { * @test_mode: the selected test mode * @platdata: platform specific information supplied by parent device * @vbus_active: is VBUS active + * @ulpi: pointer to ULPI device, if any * @phy: pointer to PHY, if any * @usb_phy: pointer to USB PHY, if any and if using the USB PHY framework * @hcd: pointer to usb_hcd for ehci host driver @@ -236,6 +240,10 @@ struct ci_hdrc { struct ci_hdrc_platform_data *platdata; int vbus_active; +#ifdef CONFIG_USB_CHIPIDEA_ULPI + struct ulpi *ulpi; + struct ulpi_ops ulpi_ops; +#endif struct phy *phy; /* old usb_phy interface */ struct usb_phy *usb_phy; @@ -418,6 +426,17 @@ static inline bool ci_otg_is_fsm_mode(struct ci_hdrc *ci) #endif } +#if IS_ENABLED(CONFIG_USB_CHIPIDEA_ULPI) +int ci_ulpi_init(struct ci_hdrc *ci); +void ci_ulpi_exit(struct ci_hdrc *ci); +int ci_ulpi_resume(struct ci_hdrc *ci); +#else +static inline int ci_ulpi_init(struct ci_hdrc *ci) { return 0; } +static inline void ci_ulpi_exit(struct ci_hdrc *ci) { } +static inline int ci_ulpi_resume(struct ci_hdrc *ci) { return 0; } +#endif + + u32 hw_read_intr_enable(struct ci_hdrc *ci); u32 hw_read_intr_status(struct ci_hdrc *ci); @@ -432,6 +451,7 @@ int hw_wait_reg(struct ci_hdrc *ci, enum ci_hw_regs reg, u32 mask, u32 value, unsigned int timeout_ms); void ci_usb_phy_exit(struct ci_hdrc *ci); +void hw_phymode_configure(struct ci_hdrc *ci); int ci_platform_configure(struct ci_hdrc *ci); int dbg_create_files(struct ci_hdrc *ci); diff --git a/drivers/usb/chipidea/core.c b/drivers/usb/chipidea/core.c index a01611c7f815..ea84fc0a03a6 100644 --- a/drivers/usb/chipidea/core.c +++ b/drivers/usb/chipidea/core.c @@ -86,6 +86,7 @@ static const u8 ci_regs_nolpm[] = { [OP_ENDPTLISTADDR] = 0x18U, [OP_TTCTRL] = 0x1CU, [OP_BURSTSIZE] = 0x20U, + [OP_ULPI_VIEWPORT] = 0x30U, [OP_PORTSC] = 0x44U, [OP_DEVLC] = 0x84U, [OP_OTGSC] = 0x64U, @@ -110,6 +111,7 @@ static const u8 ci_regs_lpm[] = { [OP_ENDPTLISTADDR] = 0x18U, [OP_TTCTRL] = 0x1CU, [OP_BURSTSIZE] = 0x20U, + [OP_ULPI_VIEWPORT] = 0x30U, [OP_PORTSC] = 0x44U, [OP_DEVLC] = 0x84U, [OP_OTGSC] = 0xC4U, @@ -285,7 +287,7 @@ static int hw_device_init(struct ci_hdrc *ci, void __iomem *base) return 0; } -static void hw_phymode_configure(struct ci_hdrc *ci) +void hw_phymode_configure(struct ci_hdrc *ci) { u32 portsc, lpm, sts = 0; @@ -893,6 +895,7 @@ static int ci_hdrc_probe(struct platform_device *pdev) CI_HDRC_IMX28_WRITE_FIX); ci->supports_runtime_pm = !!(ci->platdata->flags & CI_HDRC_SUPPORTS_RUNTIME_PM); + platform_set_drvdata(pdev, ci); ret = hw_device_init(ci, base); if (ret < 0) { @@ -900,6 +903,10 @@ static int ci_hdrc_probe(struct platform_device *pdev) return -ENODEV; } + ret = ci_ulpi_init(ci); + if (ret) + return ret; + if (ci->platdata->phy) { ci->phy = ci->platdata->phy; } else if (ci->platdata->usb_phy) { @@ -910,11 +917,15 @@ static int ci_hdrc_probe(struct platform_device *pdev) /* if both generic PHY and USB PHY layers aren't enabled */ if (PTR_ERR(ci->phy) == -ENOSYS && - PTR_ERR(ci->usb_phy) == -ENXIO) - return -ENXIO; + PTR_ERR(ci->usb_phy) == -ENXIO) { + ret = -ENXIO; + goto deinit_phy; + } - if (IS_ERR(ci->phy) && IS_ERR(ci->usb_phy)) - return -EPROBE_DEFER; + if (IS_ERR(ci->phy) && IS_ERR(ci->usb_phy)) { + ret = -EPROBE_DEFER; + goto deinit_phy; + } if (IS_ERR(ci->phy)) ci->phy = NULL; @@ -993,7 +1004,6 @@ static int ci_hdrc_probe(struct platform_device *pdev) } } - platform_set_drvdata(pdev, ci); ret = devm_request_irq(dev, ci->irq, ci_irq, IRQF_SHARED, ci->platdata->name, ci); if (ret) @@ -1024,6 +1034,7 @@ static int ci_hdrc_probe(struct platform_device *pdev) stop: ci_role_destroy(ci); deinit_phy: + ci_ulpi_exit(ci); return ret; } @@ -1042,6 +1053,7 @@ static int ci_hdrc_remove(struct platform_device *pdev) ci_extcon_unregister(ci); ci_role_destroy(ci); ci_hdrc_enter_lpm(ci, true); + ci_ulpi_exit(ci); return 0; } @@ -1089,6 +1101,7 @@ static void ci_controller_suspend(struct ci_hdrc *ci) static int ci_controller_resume(struct device *dev) { struct ci_hdrc *ci = dev_get_drvdata(dev); + int ret; dev_dbg(dev, "at %s\n", __func__); @@ -1098,6 +1111,11 @@ static int ci_controller_resume(struct device *dev) } ci_hdrc_enter_lpm(ci, false); + + ret = ci_ulpi_resume(ci); + if (ret) + return ret; + if (ci->usb_phy) { usb_phy_set_suspend(ci->usb_phy, 0); usb_phy_set_wakeup(ci->usb_phy, false); diff --git a/drivers/usb/chipidea/ulpi.c b/drivers/usb/chipidea/ulpi.c new file mode 100644 index 000000000000..3962255ff687 --- /dev/null +++ b/drivers/usb/chipidea/ulpi.c @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2016 Linaro Ltd. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * 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. + */ + +#include <linux/device.h> +#include <linux/usb/chipidea.h> +#include <linux/ulpi/interface.h> + +#include "ci.h" + +#define ULPI_WAKEUP BIT(31) +#define ULPI_RUN BIT(30) +#define ULPI_WRITE BIT(29) +#define ULPI_SYNC_STATE BIT(27) +#define ULPI_ADDR(n) ((n) << 16) +#define ULPI_DATA(n) (n) + +static int ci_ulpi_wait(struct ci_hdrc *ci, u32 mask) +{ + unsigned long usec = 10000; + + while (usec--) { + if (!hw_read(ci, OP_ULPI_VIEWPORT, mask)) + return 0; + + udelay(1); + } + + return -ETIMEDOUT; +} + +static int ci_ulpi_read(struct ulpi_ops *ops, u8 addr) +{ + struct ci_hdrc *ci = dev_get_drvdata(ops->dev); + int ret; + + hw_write(ci, OP_ULPI_VIEWPORT, 0xffffffff, ULPI_WRITE | ULPI_WAKEUP); + ret = ci_ulpi_wait(ci, ULPI_WAKEUP); + if (ret) + return ret; + + hw_write(ci, OP_ULPI_VIEWPORT, 0xffffffff, ULPI_RUN | ULPI_ADDR(addr)); + ret = ci_ulpi_wait(ci, ULPI_RUN); + if (ret) + return ret; + + return hw_read(ci, OP_ULPI_VIEWPORT, GENMASK(15, 8)) >> 8; +} + +static int ci_ulpi_write(struct ulpi_ops *ops, u8 addr, u8 val) +{ + struct ci_hdrc *ci = dev_get_drvdata(ops->dev); + int ret; + + hw_write(ci, OP_ULPI_VIEWPORT, 0xffffffff, ULPI_WRITE | ULPI_WAKEUP); + ret = ci_ulpi_wait(ci, ULPI_WAKEUP); + if (ret) + return ret; + + hw_write(ci, OP_ULPI_VIEWPORT, 0xffffffff, + ULPI_RUN | ULPI_WRITE | ULPI_ADDR(addr) | val); + return ci_ulpi_wait(ci, ULPI_RUN); +} + +int ci_ulpi_init(struct ci_hdrc *ci) +{ + if (ci->platdata->phy_mode != USBPHY_INTERFACE_MODE_ULPI) + return 0; + + /* + * Set PORTSC correctly so we can read/write ULPI registers for + * identification purposes + */ + hw_phymode_configure(ci); + + ci->ulpi_ops.read = ci_ulpi_read; + ci->ulpi_ops.write = ci_ulpi_write; + ci->ulpi = ulpi_register_interface(ci->dev, &ci->ulpi_ops); + if (IS_ERR(ci->ulpi)) + dev_err(ci->dev, "failed to register ULPI interface"); + + return PTR_ERR_OR_ZERO(ci->ulpi); +} + +void ci_ulpi_exit(struct ci_hdrc *ci) +{ + if (ci->ulpi) { + ulpi_unregister_interface(ci->ulpi); + ci->ulpi = NULL; + } +} + +int ci_ulpi_resume(struct ci_hdrc *ci) +{ + int cnt = 100000; + + while (cnt-- > 0) { + if (hw_read(ci, OP_ULPI_VIEWPORT, ULPI_SYNC_STATE)) + return 0; + udelay(1); + } + + return -ETIMEDOUT; +} -- 2.9.0.rc2.8.ga28705d
WARNING: multiple messages have this Message-ID (diff)
From: stephen.boyd@linaro.org (Stephen Boyd) To: linux-arm-kernel@lists.infradead.org Subject: [PATCH 09/21] usb: chipidea: Add support for ULPI PHY bus Date: Sun, 26 Jun 2016 00:28:26 -0700 [thread overview] Message-ID: <20160626072838.28082-10-stephen.boyd@linaro.org> (raw) In-Reply-To: <20160626072838.28082-1-stephen.boyd@linaro.org> Some phys for the chipidea controller are controlled via the ULPI viewport. Add support for the ULPI bus so that these sorts of phys can be probed and read/written automatically without having to duplicate the viewport logic in each phy driver. Cc: Peter Chen <peter.chen@nxp.com> Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Cc: Heikki Krogerus <heikki.krogerus@linux.intel.com> Signed-off-by: Stephen Boyd <stephen.boyd@linaro.org> --- drivers/usb/chipidea/Kconfig | 7 +++ drivers/usb/chipidea/Makefile | 1 + drivers/usb/chipidea/ci.h | 20 ++++++++ drivers/usb/chipidea/core.c | 30 ++++++++--- drivers/usb/chipidea/ulpi.c | 113 ++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 165 insertions(+), 6 deletions(-) create mode 100644 drivers/usb/chipidea/ulpi.c diff --git a/drivers/usb/chipidea/Kconfig b/drivers/usb/chipidea/Kconfig index 3644a3500b70..4f8c342a8865 100644 --- a/drivers/usb/chipidea/Kconfig +++ b/drivers/usb/chipidea/Kconfig @@ -37,4 +37,11 @@ config USB_CHIPIDEA_HOST Say Y here to enable host controller functionality of the ChipIdea driver. +config USB_CHIPIDEA_ULPI + bool "ChipIdea ULPI PHY support" + depends on USB_ULPI_BUS=y || USB_ULPI_BUS=USB_CHIPIDEA + help + Say Y here if you have a ULPI PHY attached to your ChipIdea + controller. + endif diff --git a/drivers/usb/chipidea/Makefile b/drivers/usb/chipidea/Makefile index 518e445476c3..39fca5715ed3 100644 --- a/drivers/usb/chipidea/Makefile +++ b/drivers/usb/chipidea/Makefile @@ -4,6 +4,7 @@ ci_hdrc-y := core.o otg.o debug.o ci_hdrc-$(CONFIG_USB_CHIPIDEA_UDC) += udc.o ci_hdrc-$(CONFIG_USB_CHIPIDEA_HOST) += host.o ci_hdrc-$(CONFIG_USB_OTG_FSM) += otg_fsm.o +ci_hdrc-$(CONFIG_USB_CHIPIDEA_ULPI) += ulpi.o # Glue/Bridge layers go here diff --git a/drivers/usb/chipidea/ci.h b/drivers/usb/chipidea/ci.h index f87805235caa..14aa20525547 100644 --- a/drivers/usb/chipidea/ci.h +++ b/drivers/usb/chipidea/ci.h @@ -18,6 +18,8 @@ #include <linux/usb.h> #include <linux/usb/gadget.h> #include <linux/usb/otg-fsm.h> +#include <linux/usb/otg.h> +#include <linux/ulpi/interface.h> /****************************************************************************** * DEFINE @@ -52,6 +54,7 @@ enum ci_hw_regs { OP_ENDPTLISTADDR, OP_TTCTRL, OP_BURSTSIZE, + OP_ULPI_VIEWPORT, OP_PORTSC, OP_DEVLC, OP_OTGSC, @@ -187,6 +190,7 @@ struct hw_bank { * @test_mode: the selected test mode * @platdata: platform specific information supplied by parent device * @vbus_active: is VBUS active + * @ulpi: pointer to ULPI device, if any * @phy: pointer to PHY, if any * @usb_phy: pointer to USB PHY, if any and if using the USB PHY framework * @hcd: pointer to usb_hcd for ehci host driver @@ -236,6 +240,10 @@ struct ci_hdrc { struct ci_hdrc_platform_data *platdata; int vbus_active; +#ifdef CONFIG_USB_CHIPIDEA_ULPI + struct ulpi *ulpi; + struct ulpi_ops ulpi_ops; +#endif struct phy *phy; /* old usb_phy interface */ struct usb_phy *usb_phy; @@ -418,6 +426,17 @@ static inline bool ci_otg_is_fsm_mode(struct ci_hdrc *ci) #endif } +#if IS_ENABLED(CONFIG_USB_CHIPIDEA_ULPI) +int ci_ulpi_init(struct ci_hdrc *ci); +void ci_ulpi_exit(struct ci_hdrc *ci); +int ci_ulpi_resume(struct ci_hdrc *ci); +#else +static inline int ci_ulpi_init(struct ci_hdrc *ci) { return 0; } +static inline void ci_ulpi_exit(struct ci_hdrc *ci) { } +static inline int ci_ulpi_resume(struct ci_hdrc *ci) { return 0; } +#endif + + u32 hw_read_intr_enable(struct ci_hdrc *ci); u32 hw_read_intr_status(struct ci_hdrc *ci); @@ -432,6 +451,7 @@ int hw_wait_reg(struct ci_hdrc *ci, enum ci_hw_regs reg, u32 mask, u32 value, unsigned int timeout_ms); void ci_usb_phy_exit(struct ci_hdrc *ci); +void hw_phymode_configure(struct ci_hdrc *ci); int ci_platform_configure(struct ci_hdrc *ci); int dbg_create_files(struct ci_hdrc *ci); diff --git a/drivers/usb/chipidea/core.c b/drivers/usb/chipidea/core.c index a01611c7f815..ea84fc0a03a6 100644 --- a/drivers/usb/chipidea/core.c +++ b/drivers/usb/chipidea/core.c @@ -86,6 +86,7 @@ static const u8 ci_regs_nolpm[] = { [OP_ENDPTLISTADDR] = 0x18U, [OP_TTCTRL] = 0x1CU, [OP_BURSTSIZE] = 0x20U, + [OP_ULPI_VIEWPORT] = 0x30U, [OP_PORTSC] = 0x44U, [OP_DEVLC] = 0x84U, [OP_OTGSC] = 0x64U, @@ -110,6 +111,7 @@ static const u8 ci_regs_lpm[] = { [OP_ENDPTLISTADDR] = 0x18U, [OP_TTCTRL] = 0x1CU, [OP_BURSTSIZE] = 0x20U, + [OP_ULPI_VIEWPORT] = 0x30U, [OP_PORTSC] = 0x44U, [OP_DEVLC] = 0x84U, [OP_OTGSC] = 0xC4U, @@ -285,7 +287,7 @@ static int hw_device_init(struct ci_hdrc *ci, void __iomem *base) return 0; } -static void hw_phymode_configure(struct ci_hdrc *ci) +void hw_phymode_configure(struct ci_hdrc *ci) { u32 portsc, lpm, sts = 0; @@ -893,6 +895,7 @@ static int ci_hdrc_probe(struct platform_device *pdev) CI_HDRC_IMX28_WRITE_FIX); ci->supports_runtime_pm = !!(ci->platdata->flags & CI_HDRC_SUPPORTS_RUNTIME_PM); + platform_set_drvdata(pdev, ci); ret = hw_device_init(ci, base); if (ret < 0) { @@ -900,6 +903,10 @@ static int ci_hdrc_probe(struct platform_device *pdev) return -ENODEV; } + ret = ci_ulpi_init(ci); + if (ret) + return ret; + if (ci->platdata->phy) { ci->phy = ci->platdata->phy; } else if (ci->platdata->usb_phy) { @@ -910,11 +917,15 @@ static int ci_hdrc_probe(struct platform_device *pdev) /* if both generic PHY and USB PHY layers aren't enabled */ if (PTR_ERR(ci->phy) == -ENOSYS && - PTR_ERR(ci->usb_phy) == -ENXIO) - return -ENXIO; + PTR_ERR(ci->usb_phy) == -ENXIO) { + ret = -ENXIO; + goto deinit_phy; + } - if (IS_ERR(ci->phy) && IS_ERR(ci->usb_phy)) - return -EPROBE_DEFER; + if (IS_ERR(ci->phy) && IS_ERR(ci->usb_phy)) { + ret = -EPROBE_DEFER; + goto deinit_phy; + } if (IS_ERR(ci->phy)) ci->phy = NULL; @@ -993,7 +1004,6 @@ static int ci_hdrc_probe(struct platform_device *pdev) } } - platform_set_drvdata(pdev, ci); ret = devm_request_irq(dev, ci->irq, ci_irq, IRQF_SHARED, ci->platdata->name, ci); if (ret) @@ -1024,6 +1034,7 @@ static int ci_hdrc_probe(struct platform_device *pdev) stop: ci_role_destroy(ci); deinit_phy: + ci_ulpi_exit(ci); return ret; } @@ -1042,6 +1053,7 @@ static int ci_hdrc_remove(struct platform_device *pdev) ci_extcon_unregister(ci); ci_role_destroy(ci); ci_hdrc_enter_lpm(ci, true); + ci_ulpi_exit(ci); return 0; } @@ -1089,6 +1101,7 @@ static void ci_controller_suspend(struct ci_hdrc *ci) static int ci_controller_resume(struct device *dev) { struct ci_hdrc *ci = dev_get_drvdata(dev); + int ret; dev_dbg(dev, "at %s\n", __func__); @@ -1098,6 +1111,11 @@ static int ci_controller_resume(struct device *dev) } ci_hdrc_enter_lpm(ci, false); + + ret = ci_ulpi_resume(ci); + if (ret) + return ret; + if (ci->usb_phy) { usb_phy_set_suspend(ci->usb_phy, 0); usb_phy_set_wakeup(ci->usb_phy, false); diff --git a/drivers/usb/chipidea/ulpi.c b/drivers/usb/chipidea/ulpi.c new file mode 100644 index 000000000000..3962255ff687 --- /dev/null +++ b/drivers/usb/chipidea/ulpi.c @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2016 Linaro Ltd. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * 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. + */ + +#include <linux/device.h> +#include <linux/usb/chipidea.h> +#include <linux/ulpi/interface.h> + +#include "ci.h" + +#define ULPI_WAKEUP BIT(31) +#define ULPI_RUN BIT(30) +#define ULPI_WRITE BIT(29) +#define ULPI_SYNC_STATE BIT(27) +#define ULPI_ADDR(n) ((n) << 16) +#define ULPI_DATA(n) (n) + +static int ci_ulpi_wait(struct ci_hdrc *ci, u32 mask) +{ + unsigned long usec = 10000; + + while (usec--) { + if (!hw_read(ci, OP_ULPI_VIEWPORT, mask)) + return 0; + + udelay(1); + } + + return -ETIMEDOUT; +} + +static int ci_ulpi_read(struct ulpi_ops *ops, u8 addr) +{ + struct ci_hdrc *ci = dev_get_drvdata(ops->dev); + int ret; + + hw_write(ci, OP_ULPI_VIEWPORT, 0xffffffff, ULPI_WRITE | ULPI_WAKEUP); + ret = ci_ulpi_wait(ci, ULPI_WAKEUP); + if (ret) + return ret; + + hw_write(ci, OP_ULPI_VIEWPORT, 0xffffffff, ULPI_RUN | ULPI_ADDR(addr)); + ret = ci_ulpi_wait(ci, ULPI_RUN); + if (ret) + return ret; + + return hw_read(ci, OP_ULPI_VIEWPORT, GENMASK(15, 8)) >> 8; +} + +static int ci_ulpi_write(struct ulpi_ops *ops, u8 addr, u8 val) +{ + struct ci_hdrc *ci = dev_get_drvdata(ops->dev); + int ret; + + hw_write(ci, OP_ULPI_VIEWPORT, 0xffffffff, ULPI_WRITE | ULPI_WAKEUP); + ret = ci_ulpi_wait(ci, ULPI_WAKEUP); + if (ret) + return ret; + + hw_write(ci, OP_ULPI_VIEWPORT, 0xffffffff, + ULPI_RUN | ULPI_WRITE | ULPI_ADDR(addr) | val); + return ci_ulpi_wait(ci, ULPI_RUN); +} + +int ci_ulpi_init(struct ci_hdrc *ci) +{ + if (ci->platdata->phy_mode != USBPHY_INTERFACE_MODE_ULPI) + return 0; + + /* + * Set PORTSC correctly so we can read/write ULPI registers for + * identification purposes + */ + hw_phymode_configure(ci); + + ci->ulpi_ops.read = ci_ulpi_read; + ci->ulpi_ops.write = ci_ulpi_write; + ci->ulpi = ulpi_register_interface(ci->dev, &ci->ulpi_ops); + if (IS_ERR(ci->ulpi)) + dev_err(ci->dev, "failed to register ULPI interface"); + + return PTR_ERR_OR_ZERO(ci->ulpi); +} + +void ci_ulpi_exit(struct ci_hdrc *ci) +{ + if (ci->ulpi) { + ulpi_unregister_interface(ci->ulpi); + ci->ulpi = NULL; + } +} + +int ci_ulpi_resume(struct ci_hdrc *ci) +{ + int cnt = 100000; + + while (cnt-- > 0) { + if (hw_read(ci, OP_ULPI_VIEWPORT, ULPI_SYNC_STATE)) + return 0; + udelay(1); + } + + return -ETIMEDOUT; +} -- 2.9.0.rc2.8.ga28705d
next prev parent reply other threads:[~2016-06-26 7:28 UTC|newest] Thread overview: 214+ messages / expand[flat|nested] mbox.gz Atom feed top 2016-06-26 7:28 [PATCH 00/21] Support qcom's HSIC USB and rewrite USB2 HS phy support Stephen Boyd 2016-06-26 7:28 ` Stephen Boyd 2016-06-26 7:28 ` [PATCH 01/21] of: device: Support loading a module with OF based modalias Stephen Boyd 2016-06-26 7:28 ` Stephen Boyd 2016-06-26 7:28 ` Stephen Boyd 2016-06-28 4:17 ` Bjorn Andersson 2016-06-28 4:17 ` Bjorn Andersson 2016-06-28 4:39 ` Rob Herring [not found] ` <20160626072838.28082-1-stephen.boyd-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org> 2016-06-26 7:28 ` [PATCH 02/21] usb: ulpi: Support device discovery via DT Stephen Boyd 2016-06-26 7:28 ` Stephen Boyd 2016-06-26 7:28 ` Stephen Boyd [not found] ` <20160626072838.28082-3-stephen.boyd-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org> 2016-06-27 4:21 ` kbuild test robot 2016-06-27 4:21 ` kbuild test robot 2016-06-27 4:21 ` kbuild test robot 2016-06-27 14:34 ` Heikki Krogerus 2016-06-27 14:34 ` Heikki Krogerus 2016-06-27 22:10 ` Stephen Boyd 2016-06-27 22:10 ` Stephen Boyd 2016-06-28 11:42 ` Heikki Krogerus 2016-06-28 11:42 ` Heikki Krogerus 2016-06-28 18:27 ` Stephen Boyd 2016-06-28 18:27 ` Stephen Boyd 2016-06-29 1:53 ` Peter Chen 2016-06-29 1:53 ` Peter Chen 2016-06-28 20:56 ` Rob Herring 2016-06-28 20:56 ` Rob Herring 2016-06-28 22:09 ` Stephen Boyd 2016-06-28 22:09 ` Stephen Boyd 2016-07-01 0:59 ` Rob Herring 2016-07-01 0:59 ` Rob Herring 2016-07-01 0:59 ` Rob Herring 2016-07-06 6:16 ` Stephen Boyd 2016-07-06 6:16 ` Stephen Boyd 2016-06-26 7:28 ` [PATCH 03/21] usb: ulpi: Avoid reading/writing in device creation with OF devices Stephen Boyd 2016-06-26 7:28 ` Stephen Boyd 2016-06-26 7:28 ` Stephen Boyd 2016-06-26 7:28 ` [PATCH 14/21] usb: chipidea: msm: Add proper clk and reset support Stephen Boyd 2016-06-26 7:28 ` Stephen Boyd 2016-06-26 7:28 ` Stephen Boyd 2016-06-29 7:02 ` Peter Chen 2016-06-29 7:02 ` Peter Chen 2016-06-26 7:28 ` [PATCH 20/21] phy: Add support for Qualcomm's USB HSIC phy Stephen Boyd 2016-06-26 7:28 ` Stephen Boyd 2016-06-26 7:28 ` Stephen Boyd 2016-06-28 8:49 ` Neil Armstrong 2016-06-28 8:49 ` Neil Armstrong 2016-06-28 21:58 ` Stephen Boyd 2016-06-28 21:58 ` Stephen Boyd 2016-06-28 21:58 ` Stephen Boyd 2016-06-29 9:16 ` Neil Armstrong 2016-06-29 9:16 ` Neil Armstrong 2016-06-29 9:16 ` Neil Armstrong [not found] ` <57739203.9000601-rdvid1DuHRBWk0Htik3J/w@public.gmane.org> 2016-06-29 18:54 ` Stephen Boyd 2016-06-29 18:54 ` Stephen Boyd 2016-06-29 18:54 ` Stephen Boyd 2016-06-26 7:28 ` [PATCH 21/21] phy: Add support for Qualcomm's USB HS phy Stephen Boyd 2016-06-26 7:28 ` Stephen Boyd 2016-06-26 7:28 ` Stephen Boyd 2016-06-28 3:09 ` [PATCH 00/21] Support qcom's HSIC USB and rewrite USB2 HS phy support John Stultz 2016-06-28 3:09 ` John Stultz 2016-06-28 3:09 ` John Stultz 2016-06-28 8:34 ` Stephen Boyd 2016-06-28 8:34 ` Stephen Boyd 2016-07-02 6:03 ` John Stultz 2016-07-02 6:03 ` John Stultz 2016-07-02 6:03 ` John Stultz 2016-07-05 19:22 ` Stephen Boyd 2016-07-05 19:22 ` Stephen Boyd 2016-07-05 19:33 ` John Stultz 2016-07-05 19:33 ` John Stultz 2016-07-05 19:33 ` John Stultz 2016-06-26 7:28 ` [PATCH 04/21] usb: chipidea: Only read/write OTGSC from one place Stephen Boyd 2016-06-26 7:28 ` Stephen Boyd 2016-06-26 7:28 ` Stephen Boyd 2016-06-27 8:04 ` Jun Li 2016-06-27 8:04 ` Jun Li 2016-06-27 8:04 ` Jun Li [not found] ` <AM4PR04MB213088094DF074BB5CB3DD0689210-WOempg8NbQQzjTQnahXoOs9NdZoXdze2vxpqHgZTriW3zl9H0oFU5g@public.gmane.org> 2016-06-27 19:07 ` Stephen Boyd 2016-06-27 19:07 ` Stephen Boyd 2016-06-27 19:07 ` Stephen Boyd 2016-06-28 9:36 ` Peter Chen 2016-06-28 9:36 ` Peter Chen 2016-06-28 9:36 ` Peter Chen 2016-06-28 22:10 ` Stephen Boyd 2016-06-28 22:10 ` Stephen Boyd 2016-06-26 7:28 ` [PATCH 05/21] usb: chipidea: Handle extcon events properly Stephen Boyd 2016-06-26 7:28 ` Stephen Boyd 2016-06-26 7:28 ` Stephen Boyd 2016-06-28 10:01 ` Peter Chen 2016-06-28 10:01 ` Peter Chen 2016-06-26 7:28 ` [PATCH 06/21] usb: chipidea: Initialize and reinitialize phy later Stephen Boyd 2016-06-26 7:28 ` Stephen Boyd 2016-06-29 2:30 ` Peter Chen 2016-06-29 2:30 ` Peter Chen 2016-06-30 1:23 ` Stephen Boyd 2016-06-30 1:23 ` Stephen Boyd 2016-06-30 1:22 ` Peter Chen 2016-06-30 1:22 ` Peter Chen 2016-06-26 7:28 ` [PATCH 07/21] usb: chipidea: Notify of reset when switching into host mode Stephen Boyd 2016-06-26 7:28 ` Stephen Boyd 2016-06-26 7:28 ` Stephen Boyd 2016-06-26 7:28 ` [PATCH 08/21] usb: chipidea: Kick OTG state machine for AVVIS with vbus extcon Stephen Boyd 2016-06-26 7:28 ` Stephen Boyd [not found] ` <20160626072838.28082-9-stephen.boyd-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org> 2016-06-29 3:09 ` Peter Chen 2016-06-29 3:09 ` Peter Chen 2016-06-29 3:09 ` Peter Chen 2016-06-30 1:19 ` Stephen Boyd 2016-06-30 1:19 ` Stephen Boyd 2016-06-30 1:26 ` Peter Chen 2016-06-30 1:26 ` Peter Chen 2016-06-30 1:26 ` Peter Chen 2016-06-30 1:50 ` Jun Li 2016-06-30 1:50 ` Jun Li 2016-06-30 1:50 ` Jun Li 2016-06-26 7:28 ` Stephen Boyd [this message] 2016-06-26 7:28 ` [PATCH 09/21] usb: chipidea: Add support for ULPI PHY bus Stephen Boyd 2016-06-29 6:26 ` Peter Chen 2016-06-29 6:26 ` Peter Chen 2016-06-30 1:29 ` Stephen Boyd 2016-06-30 1:29 ` Stephen Boyd 2016-06-26 7:28 ` [PATCH 10/21] usb: chipidea: msm: Rely on core to override AHBBURST Stephen Boyd 2016-06-26 7:28 ` Stephen Boyd 2016-06-29 6:32 ` Peter Chen 2016-06-29 6:32 ` Peter Chen 2016-06-29 18:59 ` Stephen Boyd 2016-06-29 18:59 ` Stephen Boyd 2016-06-30 1:18 ` Peter Chen 2016-06-30 1:18 ` Peter Chen 2016-06-30 1:18 ` Peter Chen 2016-06-30 1:41 ` Stephen Boyd 2016-06-30 1:41 ` Stephen Boyd 2016-06-26 7:28 ` [PATCH 11/21] usb: chipidea: msm: Use hw_write_id_reg() instead of writel directly Stephen Boyd 2016-06-26 7:28 ` Stephen Boyd 2016-06-29 6:37 ` Peter Chen 2016-06-29 6:37 ` Peter Chen 2016-06-26 7:28 ` [PATCH 12/21] usb: chipidea: msm: Keep device runtime enabled Stephen Boyd 2016-06-26 7:28 ` Stephen Boyd 2016-06-29 6:46 ` Peter Chen 2016-06-29 6:46 ` Peter Chen 2016-06-30 0:43 ` Stephen Boyd 2016-06-30 0:43 ` Stephen Boyd 2016-06-30 1:39 ` Peter Chen 2016-06-30 1:39 ` Peter Chen 2016-06-30 20:30 ` Stephen Boyd 2016-06-30 20:30 ` Stephen Boyd 2016-07-01 3:20 ` Peter Chen 2016-07-01 3:20 ` Peter Chen 2016-06-26 7:28 ` [PATCH 13/21] usb: chipidea: msm: Allow core to get usb phy Stephen Boyd 2016-06-26 7:28 ` Stephen Boyd 2016-06-29 6:48 ` Peter Chen 2016-06-29 6:48 ` Peter Chen 2016-06-29 11:34 ` Peter Chen 2016-06-29 11:34 ` Peter Chen 2016-06-29 19:31 ` Stephen Boyd 2016-06-29 19:31 ` Stephen Boyd 2016-06-30 1:43 ` Peter Chen 2016-06-30 1:43 ` Peter Chen 2016-06-30 1:43 ` Peter Chen 2016-06-26 7:28 ` [PATCH 15/21] usb: chipidea: msm: Mux over secondary phy at the right time Stephen Boyd 2016-06-26 7:28 ` Stephen Boyd 2016-06-26 7:28 ` Stephen Boyd [not found] ` <20160626072838.28082-16-stephen.boyd-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org> 2016-06-28 4:51 ` Bjorn Andersson 2016-06-28 4:51 ` Bjorn Andersson 2016-06-28 4:51 ` Bjorn Andersson 2016-06-28 8:39 ` Stephen Boyd 2016-06-28 8:39 ` Stephen Boyd 2016-06-29 8:08 ` Peter Chen 2016-06-29 8:08 ` Peter Chen 2016-06-29 19:28 ` Stephen Boyd 2016-06-29 19:28 ` Stephen Boyd 2016-06-30 1:52 ` Peter Chen 2016-06-30 1:52 ` Peter Chen 2016-06-30 1:35 ` Stephen Boyd 2016-06-30 1:35 ` Stephen Boyd 2016-06-26 7:28 ` [PATCH 16/21] usb: chipidea: msm: Restore wrapper settings after reset Stephen Boyd 2016-06-26 7:28 ` Stephen Boyd 2016-06-26 7:28 ` Stephen Boyd 2016-06-29 8:26 ` Peter Chen 2016-06-29 8:26 ` Peter Chen 2016-06-29 19:13 ` Stephen Boyd 2016-06-29 19:13 ` Stephen Boyd 2016-06-30 8:54 ` Peter Chen 2016-06-30 8:54 ` Peter Chen 2016-06-30 16:24 ` Stephen Boyd 2016-06-30 16:24 ` Stephen Boyd 2016-06-30 16:24 ` Stephen Boyd 2016-06-26 7:28 ` [PATCH 17/21] usb: chipidea: msm: Make platform data driver local instead of global Stephen Boyd 2016-06-26 7:28 ` Stephen Boyd 2016-06-26 7:28 ` Stephen Boyd 2016-06-29 11:29 ` Peter Chen 2016-06-29 11:29 ` Peter Chen 2016-06-29 19:17 ` Stephen Boyd 2016-06-29 19:17 ` Stephen Boyd 2016-06-30 9:08 ` Peter Chen 2016-06-30 9:08 ` Peter Chen 2016-06-26 7:28 ` [PATCH 18/21] usb: chipidea: msm: Add reset controller for PHY POR bit Stephen Boyd 2016-06-26 7:28 ` Stephen Boyd 2016-06-27 3:41 ` kbuild test robot 2016-06-27 3:41 ` kbuild test robot 2016-06-27 4:51 ` kbuild test robot 2016-06-27 4:51 ` kbuild test robot 2016-06-27 7:50 ` kbuild test robot 2016-06-27 7:50 ` kbuild test robot 2016-06-28 1:27 ` Stephen Boyd 2016-06-28 1:27 ` Stephen Boyd 2016-06-29 11:45 ` Peter Chen 2016-06-29 11:45 ` Peter Chen 2016-06-26 7:28 ` [PATCH 19/21] usb: chipidea: msm: Be silent on probe defer errors Stephen Boyd 2016-06-26 7:28 ` Stephen Boyd 2016-06-30 1:06 ` Peter Chen 2016-06-30 1:06 ` Peter Chen 2016-06-30 1:06 ` Peter Chen 2016-06-30 1:26 ` Stephen Boyd 2016-06-30 1:26 ` Stephen Boyd
Reply instructions: You may reply publicly to this message via plain-text email using any one of the following methods: * Save the following mbox file, import it into your mail client, and reply-to-all from there: mbox Avoid top-posting and favor interleaved quoting: https://en.wikipedia.org/wiki/Posting_style#Interleaved_style * Reply using the --to, --cc, and --in-reply-to switches of git-send-email(1): git send-email \ --in-reply-to=20160626072838.28082-10-stephen.boyd@linaro.org \ --to=stephen.boyd@linaro.org \ --cc=andy.gross@linaro.org \ --cc=arnd@arndb.de \ --cc=balbi@kernel.org \ --cc=bjorn.andersson@linaro.org \ --cc=gregkh@linuxfoundation.org \ --cc=heikki.krogerus@linux.intel.com \ --cc=linux-arm-kernel@lists.infradead.org \ --cc=linux-arm-msm@vger.kernel.org \ --cc=linux-kernel@vger.kernel.org \ --cc=linux-usb@vger.kernel.org \ --cc=narmstrong@baylibre.com \ --cc=peter.chen@nxp.com \ /path/to/YOUR_REPLY https://kernel.org/pub/software/scm/git/docs/git-send-email.html * If your mail client supports setting the In-Reply-To header via mailto: links, try the mailto: linkBe sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.