summaryrefslogtreecommitdiff
path: root/drivers/usb/phy
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/phy')
-rw-r--r--drivers/usb/phy/Kconfig12
-rw-r--r--drivers/usb/phy/Makefile1
-rw-r--r--drivers/usb/phy/phy-fsl-usb.c5
-rw-r--r--drivers/usb/phy/phy-fsl-usb.h2
-rw-r--r--drivers/usb/phy/phy-generic.c74
-rw-r--r--drivers/usb/phy/phy-isp1301.c9
-rw-r--r--drivers/usb/phy/phy-mv-usb.c881
-rw-r--r--drivers/usb/phy/phy-mxs-usb.c8
-rw-r--r--drivers/usb/phy/phy-tegra-usb.c386
-rw-r--r--drivers/usb/phy/phy-twl6030-usb.c3
-rw-r--r--drivers/usb/phy/phy-ulpi.c23
-rw-r--r--drivers/usb/phy/phy.c4
12 files changed, 312 insertions, 1096 deletions
diff --git a/drivers/usb/phy/Kconfig b/drivers/usb/phy/Kconfig
index 5f629d7cad64..b7acf3966cd7 100644
--- a/drivers/usb/phy/Kconfig
+++ b/drivers/usb/phy/Kconfig
@@ -126,18 +126,6 @@ config USB_ISP1301
To compile this driver as a module, choose M here: the
module will be called phy-isp1301.
-config USB_MV_OTG
- tristate "Marvell USB OTG support"
- depends on USB_EHCI_MV && USB_MV_UDC && PM && USB_OTG
- depends on USB_GADGET || !USB_GADGET # if USB_GADGET=m, this can't be 'y'
- select USB_PHY
- help
- Say Y here if you want to build Marvell USB OTG transceiver
- driver in kernel (including PXA and MMP series). This driver
- implements role switch between EHCI host driver and gadget driver.
-
- To compile this driver as a module, choose M here.
-
config USB_MXS_PHY
tristate "Freescale MXS USB PHY support"
depends on ARCH_MXC || ARCH_MXS
diff --git a/drivers/usb/phy/Makefile b/drivers/usb/phy/Makefile
index e5d619b4d8f6..ceae46c5341d 100644
--- a/drivers/usb/phy/Makefile
+++ b/drivers/usb/phy/Makefile
@@ -18,7 +18,6 @@ obj-$(CONFIG_TWL6030_USB) += phy-twl6030-usb.o
obj-$(CONFIG_USB_TEGRA_PHY) += phy-tegra-usb.o
obj-$(CONFIG_USB_GPIO_VBUS) += phy-gpio-vbus-usb.o
obj-$(CONFIG_USB_ISP1301) += phy-isp1301.o
-obj-$(CONFIG_USB_MV_OTG) += phy-mv-usb.o
obj-$(CONFIG_USB_MXS_PHY) += phy-mxs-usb.o
obj-$(CONFIG_USB_ULPI) += phy-ulpi.o
obj-$(CONFIG_USB_ULPI_VIEWPORT) += phy-ulpi-viewport.o
diff --git a/drivers/usb/phy/phy-fsl-usb.c b/drivers/usb/phy/phy-fsl-usb.c
index 40ac68e52cee..35d79f11b03d 100644
--- a/drivers/usb/phy/phy-fsl-usb.c
+++ b/drivers/usb/phy/phy-fsl-usb.c
@@ -779,11 +779,11 @@ static int fsl_otg_conf(struct platform_device *pdev)
return 0;
/* allocate space to fsl otg device */
- fsl_otg_tc = kzalloc(sizeof(struct fsl_otg), GFP_KERNEL);
+ fsl_otg_tc = kzalloc_obj(struct fsl_otg);
if (!fsl_otg_tc)
return -ENOMEM;
- fsl_otg_tc->phy.otg = kzalloc(sizeof(struct usb_otg), GFP_KERNEL);
+ fsl_otg_tc->phy.otg = kzalloc_obj(struct usb_otg);
if (!fsl_otg_tc->phy.otg) {
kfree(fsl_otg_tc);
return -ENOMEM;
@@ -988,6 +988,7 @@ static void fsl_otg_remove(struct platform_device *pdev)
{
struct fsl_usb2_platform_data *pdata = dev_get_platdata(&pdev->dev);
+ disable_delayed_work_sync(&fsl_otg_dev->otg_event);
usb_remove_phy(&fsl_otg_dev->phy);
free_irq(fsl_otg_dev->irq, fsl_otg_dev);
diff --git a/drivers/usb/phy/phy-fsl-usb.h b/drivers/usb/phy/phy-fsl-usb.h
index d70341ae5a92..95bfe7f1b83a 100644
--- a/drivers/usb/phy/phy-fsl-usb.h
+++ b/drivers/usb/phy/phy-fsl-usb.h
@@ -345,7 +345,7 @@ inline struct fsl_otg_timer *otg_timer_initializer
{
struct fsl_otg_timer *timer;
- timer = kmalloc(sizeof(struct fsl_otg_timer), GFP_KERNEL);
+ timer = kmalloc_obj(struct fsl_otg_timer);
if (!timer)
return NULL;
timer->function = function;
diff --git a/drivers/usb/phy/phy-generic.c b/drivers/usb/phy/phy-generic.c
index 8423be59ec0f..de26b302334d 100644
--- a/drivers/usb/phy/phy-generic.c
+++ b/drivers/usb/phy/phy-generic.c
@@ -20,7 +20,7 @@
#include <linux/slab.h>
#include <linux/clk.h>
#include <linux/regulator/consumer.h>
-#include <linux/of.h>
+#include <linux/property.h>
#include <linux/gpio/consumer.h>
#include <linux/delay.h>
@@ -49,15 +49,13 @@ static int nop_set_suspend(struct usb_phy *x, int suspend)
int ret = 0;
if (suspend) {
- if (!IS_ERR(nop->clk))
- clk_disable_unprepare(nop->clk);
+ clk_disable_unprepare(nop->clk);
if (!IS_ERR(nop->vcc) && !device_may_wakeup(x->dev))
ret = regulator_disable(nop->vcc);
} else {
if (!IS_ERR(nop->vcc) && !device_may_wakeup(x->dev))
ret = regulator_enable(nop->vcc);
- if (!IS_ERR(nop->clk))
- clk_prepare_enable(nop->clk);
+ clk_prepare_enable(nop->clk);
}
return ret;
@@ -137,11 +135,9 @@ int usb_gen_phy_init(struct usb_phy *phy)
dev_err(phy->dev, "Failed to enable power\n");
}
- if (!IS_ERR(nop->clk)) {
- ret = clk_prepare_enable(nop->clk);
- if (ret)
- return ret;
- }
+ ret = clk_prepare_enable(nop->clk);
+ if (ret)
+ return ret;
nop_reset(nop);
@@ -155,8 +151,7 @@ void usb_gen_phy_shutdown(struct usb_phy *phy)
gpiod_set_value_cansleep(nop->gpiod_reset, 1);
- if (!IS_ERR(nop->clk))
- clk_disable_unprepare(nop->clk);
+ clk_disable_unprepare(nop->clk);
if (!IS_ERR(nop->vcc)) {
if (regulator_disable(nop->vcc))
@@ -202,18 +197,9 @@ int usb_phy_gen_create_phy(struct device *dev, struct usb_phy_generic *nop)
{
enum usb_phy_type type = USB_PHY_TYPE_USB2;
int err = 0;
-
u32 clk_rate = 0;
- bool needs_clk = false;
-
- if (dev->of_node) {
- struct device_node *node = dev->of_node;
-
- if (of_property_read_u32(node, "clock-frequency", &clk_rate))
- clk_rate = 0;
- needs_clk = of_property_present(node, "clocks");
- }
+ device_property_read_u32(dev, "clock-frequency", &clk_rate);
nop->gpiod_reset = devm_gpiod_get_optional(dev, "reset",
GPIOD_ASIS);
err = PTR_ERR_OR_ZERO(nop->gpiod_reset);
@@ -235,20 +221,16 @@ int usb_phy_gen_create_phy(struct device *dev, struct usb_phy_generic *nop)
if (!nop->phy.otg)
return -ENOMEM;
- nop->clk = devm_clk_get(dev, "main_clk");
- if (IS_ERR(nop->clk)) {
- dev_dbg(dev, "Can't get phy clock: %ld\n",
- PTR_ERR(nop->clk));
- if (needs_clk)
- return PTR_ERR(nop->clk);
- }
+ nop->clk = devm_clk_get_optional(dev, "main_clk");
+ if (IS_ERR(nop->clk))
+ return dev_err_probe(dev, PTR_ERR(nop->clk),
+ "Can't get phy clock\n");
- if (!IS_ERR(nop->clk) && clk_rate) {
+ if (clk_rate) {
err = clk_set_rate(nop->clk, clk_rate);
- if (err) {
- dev_err(dev, "Error setting clock rate\n");
- return err;
- }
+ if (err)
+ return dev_err_probe(dev, err,
+ "Error setting clock rate\n");
}
nop->vcc = devm_regulator_get_optional(dev, "vcc");
@@ -282,7 +264,6 @@ EXPORT_SYMBOL_GPL(usb_phy_gen_create_phy);
static int usb_phy_generic_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
- struct device_node *dn = dev->of_node;
struct usb_phy_generic *nop;
int err;
@@ -293,17 +274,17 @@ static int usb_phy_generic_probe(struct platform_device *pdev)
err = usb_phy_gen_create_phy(dev, nop);
if (err)
return err;
+
if (nop->gpiod_vbus) {
- err = devm_request_threaded_irq(&pdev->dev,
+ err = devm_request_threaded_irq(dev,
gpiod_to_irq(nop->gpiod_vbus),
NULL, nop_gpio_vbus_thread,
VBUS_IRQ_FLAGS, "vbus_detect",
nop);
- if (err) {
- dev_err(&pdev->dev, "can't request irq %i, err: %d\n",
- gpiod_to_irq(nop->gpiod_vbus), err);
- return err;
- }
+ if (err)
+ return dev_err_probe(dev, err, "can't request irq %i\n",
+ gpiod_to_irq(nop->gpiod_vbus));
+
nop->phy.otg->state = gpiod_get_value(nop->gpiod_vbus) ?
OTG_STATE_B_PERIPHERAL : OTG_STATE_B_IDLE;
}
@@ -312,16 +293,13 @@ static int usb_phy_generic_probe(struct platform_device *pdev)
nop->phy.shutdown = usb_gen_phy_shutdown;
err = usb_add_phy_dev(&nop->phy);
- if (err) {
- dev_err(&pdev->dev, "can't register transceiver, err: %d\n",
- err);
- return err;
- }
+ if (err)
+ return dev_err_probe(dev, err, "can't register transceiver\n");
platform_set_drvdata(pdev, nop);
- device_set_wakeup_capable(&pdev->dev,
- of_property_read_bool(dn, "wakeup-source"));
+ device_set_wakeup_capable(dev,
+ device_property_read_bool(dev, "wakeup-source"));
return 0;
}
diff --git a/drivers/usb/phy/phy-isp1301.c b/drivers/usb/phy/phy-isp1301.c
index f9b5c411aee4..73cc70e958de 100644
--- a/drivers/usb/phy/phy-isp1301.c
+++ b/drivers/usb/phy/phy-isp1301.c
@@ -25,7 +25,7 @@ struct isp1301 {
#define phy_to_isp(p) (container_of((p), struct isp1301, phy))
static const struct i2c_device_id isp1301_id[] = {
- { "isp1301" },
+ { .name = "isp1301" },
{ }
};
MODULE_DEVICE_TABLE(i2c, isp1301_id);
@@ -149,7 +149,12 @@ struct i2c_client *isp1301_get_client(struct device_node *node)
return client;
/* non-DT: only one ISP1301 chip supported */
- return isp1301_i2c_client;
+ if (isp1301_i2c_client) {
+ get_device(&isp1301_i2c_client->dev);
+ return isp1301_i2c_client;
+ }
+
+ return NULL;
}
EXPORT_SYMBOL_GPL(isp1301_get_client);
diff --git a/drivers/usb/phy/phy-mv-usb.c b/drivers/usb/phy/phy-mv-usb.c
deleted file mode 100644
index 30d6c8840a5e..000000000000
--- a/drivers/usb/phy/phy-mv-usb.c
+++ /dev/null
@@ -1,881 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-/*
- * Copyright (C) 2011 Marvell International Ltd. All rights reserved.
- * Author: Chao Xie <chao.xie@marvell.com>
- * Neil Zhang <zhangwm@marvell.com>
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/io.h>
-#include <linux/iopoll.h>
-#include <linux/uaccess.h>
-#include <linux/device.h>
-#include <linux/proc_fs.h>
-#include <linux/clk.h>
-#include <linux/workqueue.h>
-#include <linux/platform_device.h>
-#include <linux/string_choices.h>
-
-#include <linux/usb.h>
-#include <linux/usb/ch9.h>
-#include <linux/usb/otg.h>
-#include <linux/usb/gadget.h>
-#include <linux/usb/hcd.h>
-#include <linux/platform_data/mv_usb.h>
-
-#include "phy-mv-usb.h"
-
-#define DRIVER_DESC "Marvell USB OTG transceiver driver"
-
-MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_LICENSE("GPL");
-
-static const char driver_name[] = "mv-otg";
-
-static char *state_string[] = {
- "undefined",
- "b_idle",
- "b_srp_init",
- "b_peripheral",
- "b_wait_acon",
- "b_host",
- "a_idle",
- "a_wait_vrise",
- "a_wait_bcon",
- "a_host",
- "a_suspend",
- "a_peripheral",
- "a_wait_vfall",
- "a_vbus_err"
-};
-
-static int mv_otg_set_vbus(struct usb_otg *otg, bool on)
-{
- struct mv_otg *mvotg = container_of(otg->usb_phy, struct mv_otg, phy);
- if (mvotg->pdata->set_vbus == NULL)
- return -ENODEV;
-
- return mvotg->pdata->set_vbus(on);
-}
-
-static int mv_otg_set_host(struct usb_otg *otg,
- struct usb_bus *host)
-{
- otg->host = host;
-
- return 0;
-}
-
-static int mv_otg_set_peripheral(struct usb_otg *otg,
- struct usb_gadget *gadget)
-{
- otg->gadget = gadget;
-
- return 0;
-}
-
-static void mv_otg_run_state_machine(struct mv_otg *mvotg,
- unsigned long delay)
-{
- dev_dbg(&mvotg->pdev->dev, "transceiver is updated\n");
- if (!mvotg->qwork)
- return;
-
- queue_delayed_work(mvotg->qwork, &mvotg->work, delay);
-}
-
-static void mv_otg_timer_await_bcon(struct timer_list *t)
-{
- struct mv_otg *mvotg = from_timer(mvotg, t,
- otg_ctrl.timer[A_WAIT_BCON_TIMER]);
-
- mvotg->otg_ctrl.a_wait_bcon_timeout = 1;
-
- dev_info(&mvotg->pdev->dev, "B Device No Response!\n");
-
- if (spin_trylock(&mvotg->wq_lock)) {
- mv_otg_run_state_machine(mvotg, 0);
- spin_unlock(&mvotg->wq_lock);
- }
-}
-
-static int mv_otg_cancel_timer(struct mv_otg *mvotg, unsigned int id)
-{
- struct timer_list *timer;
-
- if (id >= OTG_TIMER_NUM)
- return -EINVAL;
-
- timer = &mvotg->otg_ctrl.timer[id];
-
- if (timer_pending(timer))
- del_timer(timer);
-
- return 0;
-}
-
-static int mv_otg_set_timer(struct mv_otg *mvotg, unsigned int id,
- unsigned long interval)
-{
- struct timer_list *timer;
-
- if (id >= OTG_TIMER_NUM)
- return -EINVAL;
-
- timer = &mvotg->otg_ctrl.timer[id];
- if (timer_pending(timer)) {
- dev_err(&mvotg->pdev->dev, "Timer%d is already running\n", id);
- return -EBUSY;
- }
-
- timer->expires = jiffies + interval;
- add_timer(timer);
-
- return 0;
-}
-
-static int mv_otg_reset(struct mv_otg *mvotg)
-{
- u32 tmp;
- int ret;
-
- /* Stop the controller */
- tmp = readl(&mvotg->op_regs->usbcmd);
- tmp &= ~USBCMD_RUN_STOP;
- writel(tmp, &mvotg->op_regs->usbcmd);
-
- /* Reset the controller to get default values */
- writel(USBCMD_CTRL_RESET, &mvotg->op_regs->usbcmd);
-
- ret = readl_poll_timeout_atomic(&mvotg->op_regs->usbcmd, tmp,
- (tmp & USBCMD_CTRL_RESET), 10, 10000);
- if (ret < 0) {
- dev_err(&mvotg->pdev->dev,
- "Wait for RESET completed TIMEOUT\n");
- return ret;
- }
-
- writel(0x0, &mvotg->op_regs->usbintr);
- tmp = readl(&mvotg->op_regs->usbsts);
- writel(tmp, &mvotg->op_regs->usbsts);
-
- return 0;
-}
-
-static void mv_otg_init_irq(struct mv_otg *mvotg)
-{
- u32 otgsc;
-
- mvotg->irq_en = OTGSC_INTR_A_SESSION_VALID
- | OTGSC_INTR_A_VBUS_VALID;
- mvotg->irq_status = OTGSC_INTSTS_A_SESSION_VALID
- | OTGSC_INTSTS_A_VBUS_VALID;
-
- if (mvotg->pdata->vbus == NULL) {
- mvotg->irq_en |= OTGSC_INTR_B_SESSION_VALID
- | OTGSC_INTR_B_SESSION_END;
- mvotg->irq_status |= OTGSC_INTSTS_B_SESSION_VALID
- | OTGSC_INTSTS_B_SESSION_END;
- }
-
- if (mvotg->pdata->id == NULL) {
- mvotg->irq_en |= OTGSC_INTR_USB_ID;
- mvotg->irq_status |= OTGSC_INTSTS_USB_ID;
- }
-
- otgsc = readl(&mvotg->op_regs->otgsc);
- otgsc |= mvotg->irq_en;
- writel(otgsc, &mvotg->op_regs->otgsc);
-}
-
-static void mv_otg_start_host(struct mv_otg *mvotg, int on)
-{
-#ifdef CONFIG_USB
- struct usb_otg *otg = mvotg->phy.otg;
- struct usb_hcd *hcd;
-
- if (!otg->host)
- return;
-
- dev_info(&mvotg->pdev->dev, "%s host\n", on ? "start" : "stop");
-
- hcd = bus_to_hcd(otg->host);
-
- if (on) {
- usb_add_hcd(hcd, hcd->irq, IRQF_SHARED);
- device_wakeup_enable(hcd->self.controller);
- } else {
- usb_remove_hcd(hcd);
- }
-#endif /* CONFIG_USB */
-}
-
-static void mv_otg_start_periphrals(struct mv_otg *mvotg, int on)
-{
- struct usb_otg *otg = mvotg->phy.otg;
-
- if (!otg->gadget)
- return;
-
- dev_info(mvotg->phy.dev, "gadget %s\n", str_on_off(on));
-
- if (on)
- usb_gadget_vbus_connect(otg->gadget);
- else
- usb_gadget_vbus_disconnect(otg->gadget);
-}
-
-static void otg_clock_enable(struct mv_otg *mvotg)
-{
- clk_prepare_enable(mvotg->clk);
-}
-
-static void otg_clock_disable(struct mv_otg *mvotg)
-{
- clk_disable_unprepare(mvotg->clk);
-}
-
-static int mv_otg_enable_internal(struct mv_otg *mvotg)
-{
- int retval = 0;
-
- if (mvotg->active)
- return 0;
-
- dev_dbg(&mvotg->pdev->dev, "otg enabled\n");
-
- otg_clock_enable(mvotg);
- if (mvotg->pdata->phy_init) {
- retval = mvotg->pdata->phy_init(mvotg->phy_regs);
- if (retval) {
- dev_err(&mvotg->pdev->dev,
- "init phy error %d\n", retval);
- otg_clock_disable(mvotg);
- return retval;
- }
- }
- mvotg->active = 1;
-
- return 0;
-
-}
-
-static int mv_otg_enable(struct mv_otg *mvotg)
-{
- if (mvotg->clock_gating)
- return mv_otg_enable_internal(mvotg);
-
- return 0;
-}
-
-static void mv_otg_disable_internal(struct mv_otg *mvotg)
-{
- if (mvotg->active) {
- dev_dbg(&mvotg->pdev->dev, "otg disabled\n");
- if (mvotg->pdata->phy_deinit)
- mvotg->pdata->phy_deinit(mvotg->phy_regs);
- otg_clock_disable(mvotg);
- mvotg->active = 0;
- }
-}
-
-static void mv_otg_disable(struct mv_otg *mvotg)
-{
- if (mvotg->clock_gating)
- mv_otg_disable_internal(mvotg);
-}
-
-static void mv_otg_update_inputs(struct mv_otg *mvotg)
-{
- struct mv_otg_ctrl *otg_ctrl = &mvotg->otg_ctrl;
- u32 otgsc;
-
- otgsc = readl(&mvotg->op_regs->otgsc);
-
- if (mvotg->pdata->vbus) {
- if (mvotg->pdata->vbus->poll() == VBUS_HIGH) {
- otg_ctrl->b_sess_vld = 1;
- otg_ctrl->b_sess_end = 0;
- } else {
- otg_ctrl->b_sess_vld = 0;
- otg_ctrl->b_sess_end = 1;
- }
- } else {
- otg_ctrl->b_sess_vld = !!(otgsc & OTGSC_STS_B_SESSION_VALID);
- otg_ctrl->b_sess_end = !!(otgsc & OTGSC_STS_B_SESSION_END);
- }
-
- if (mvotg->pdata->id)
- otg_ctrl->id = !!mvotg->pdata->id->poll();
- else
- otg_ctrl->id = !!(otgsc & OTGSC_STS_USB_ID);
-
- if (mvotg->pdata->otg_force_a_bus_req && !otg_ctrl->id)
- otg_ctrl->a_bus_req = 1;
-
- otg_ctrl->a_sess_vld = !!(otgsc & OTGSC_STS_A_SESSION_VALID);
- otg_ctrl->a_vbus_vld = !!(otgsc & OTGSC_STS_A_VBUS_VALID);
-
- dev_dbg(&mvotg->pdev->dev, "%s: ", __func__);
- dev_dbg(&mvotg->pdev->dev, "id %d\n", otg_ctrl->id);
- dev_dbg(&mvotg->pdev->dev, "b_sess_vld %d\n", otg_ctrl->b_sess_vld);
- dev_dbg(&mvotg->pdev->dev, "b_sess_end %d\n", otg_ctrl->b_sess_end);
- dev_dbg(&mvotg->pdev->dev, "a_vbus_vld %d\n", otg_ctrl->a_vbus_vld);
- dev_dbg(&mvotg->pdev->dev, "a_sess_vld %d\n", otg_ctrl->a_sess_vld);
-}
-
-static void mv_otg_update_state(struct mv_otg *mvotg)
-{
- struct mv_otg_ctrl *otg_ctrl = &mvotg->otg_ctrl;
- int old_state = mvotg->phy.otg->state;
-
- switch (old_state) {
- case OTG_STATE_UNDEFINED:
- mvotg->phy.otg->state = OTG_STATE_B_IDLE;
- fallthrough;
- case OTG_STATE_B_IDLE:
- if (otg_ctrl->id == 0)
- mvotg->phy.otg->state = OTG_STATE_A_IDLE;
- else if (otg_ctrl->b_sess_vld)
- mvotg->phy.otg->state = OTG_STATE_B_PERIPHERAL;
- break;
- case OTG_STATE_B_PERIPHERAL:
- if (!otg_ctrl->b_sess_vld || otg_ctrl->id == 0)
- mvotg->phy.otg->state = OTG_STATE_B_IDLE;
- break;
- case OTG_STATE_A_IDLE:
- if (otg_ctrl->id)
- mvotg->phy.otg->state = OTG_STATE_B_IDLE;
- else if (!(otg_ctrl->a_bus_drop) &&
- (otg_ctrl->a_bus_req || otg_ctrl->a_srp_det))
- mvotg->phy.otg->state = OTG_STATE_A_WAIT_VRISE;
- break;
- case OTG_STATE_A_WAIT_VRISE:
- if (otg_ctrl->a_vbus_vld)
- mvotg->phy.otg->state = OTG_STATE_A_WAIT_BCON;
- break;
- case OTG_STATE_A_WAIT_BCON:
- if (otg_ctrl->id || otg_ctrl->a_bus_drop
- || otg_ctrl->a_wait_bcon_timeout) {
- mv_otg_cancel_timer(mvotg, A_WAIT_BCON_TIMER);
- mvotg->otg_ctrl.a_wait_bcon_timeout = 0;
- mvotg->phy.otg->state = OTG_STATE_A_WAIT_VFALL;
- otg_ctrl->a_bus_req = 0;
- } else if (!otg_ctrl->a_vbus_vld) {
- mv_otg_cancel_timer(mvotg, A_WAIT_BCON_TIMER);
- mvotg->otg_ctrl.a_wait_bcon_timeout = 0;
- mvotg->phy.otg->state = OTG_STATE_A_VBUS_ERR;
- } else if (otg_ctrl->b_conn) {
- mv_otg_cancel_timer(mvotg, A_WAIT_BCON_TIMER);
- mvotg->otg_ctrl.a_wait_bcon_timeout = 0;
- mvotg->phy.otg->state = OTG_STATE_A_HOST;
- }
- break;
- case OTG_STATE_A_HOST:
- if (otg_ctrl->id || !otg_ctrl->b_conn
- || otg_ctrl->a_bus_drop)
- mvotg->phy.otg->state = OTG_STATE_A_WAIT_BCON;
- else if (!otg_ctrl->a_vbus_vld)
- mvotg->phy.otg->state = OTG_STATE_A_VBUS_ERR;
- break;
- case OTG_STATE_A_WAIT_VFALL:
- if (otg_ctrl->id
- || (!otg_ctrl->b_conn && otg_ctrl->a_sess_vld)
- || otg_ctrl->a_bus_req)
- mvotg->phy.otg->state = OTG_STATE_A_IDLE;
- break;
- case OTG_STATE_A_VBUS_ERR:
- if (otg_ctrl->id || otg_ctrl->a_clr_err
- || otg_ctrl->a_bus_drop) {
- otg_ctrl->a_clr_err = 0;
- mvotg->phy.otg->state = OTG_STATE_A_WAIT_VFALL;
- }
- break;
- default:
- break;
- }
-}
-
-static void mv_otg_work(struct work_struct *work)
-{
- struct mv_otg *mvotg;
- struct usb_otg *otg;
- int old_state;
-
- mvotg = container_of(to_delayed_work(work), struct mv_otg, work);
-
-run:
- /* work queue is single thread, or we need spin_lock to protect */
- otg = mvotg->phy.otg;
- old_state = otg->state;
-
- if (!mvotg->active)
- return;
-
- mv_otg_update_inputs(mvotg);
- mv_otg_update_state(mvotg);
-
- if (old_state != mvotg->phy.otg->state) {
- dev_info(&mvotg->pdev->dev, "change from state %s to %s\n",
- state_string[old_state],
- state_string[mvotg->phy.otg->state]);
-
- switch (mvotg->phy.otg->state) {
- case OTG_STATE_B_IDLE:
- otg->default_a = 0;
- if (old_state == OTG_STATE_B_PERIPHERAL)
- mv_otg_start_periphrals(mvotg, 0);
- mv_otg_reset(mvotg);
- mv_otg_disable(mvotg);
- usb_phy_set_event(&mvotg->phy, USB_EVENT_NONE);
- break;
- case OTG_STATE_B_PERIPHERAL:
- mv_otg_enable(mvotg);
- mv_otg_start_periphrals(mvotg, 1);
- usb_phy_set_event(&mvotg->phy, USB_EVENT_ENUMERATED);
- break;
- case OTG_STATE_A_IDLE:
- otg->default_a = 1;
- mv_otg_enable(mvotg);
- if (old_state == OTG_STATE_A_WAIT_VFALL)
- mv_otg_start_host(mvotg, 0);
- mv_otg_reset(mvotg);
- break;
- case OTG_STATE_A_WAIT_VRISE:
- mv_otg_set_vbus(otg, 1);
- break;
- case OTG_STATE_A_WAIT_BCON:
- if (old_state != OTG_STATE_A_HOST)
- mv_otg_start_host(mvotg, 1);
- mv_otg_set_timer(mvotg, A_WAIT_BCON_TIMER,
- T_A_WAIT_BCON);
- /*
- * Now, we directly enter A_HOST. So set b_conn = 1
- * here. In fact, it need host driver to notify us.
- */
- mvotg->otg_ctrl.b_conn = 1;
- break;
- case OTG_STATE_A_HOST:
- break;
- case OTG_STATE_A_WAIT_VFALL:
- /*
- * Now, we has exited A_HOST. So set b_conn = 0
- * here. In fact, it need host driver to notify us.
- */
- mvotg->otg_ctrl.b_conn = 0;
- mv_otg_set_vbus(otg, 0);
- break;
- case OTG_STATE_A_VBUS_ERR:
- break;
- default:
- break;
- }
- goto run;
- }
-}
-
-static irqreturn_t mv_otg_irq(int irq, void *dev)
-{
- struct mv_otg *mvotg = dev;
- u32 otgsc;
-
- otgsc = readl(&mvotg->op_regs->otgsc);
- writel(otgsc, &mvotg->op_regs->otgsc);
-
- /*
- * if we have vbus, then the vbus detection for B-device
- * will be done by mv_otg_inputs_irq().
- */
- if (mvotg->pdata->vbus)
- if ((otgsc & OTGSC_STS_USB_ID) &&
- !(otgsc & OTGSC_INTSTS_USB_ID))
- return IRQ_NONE;
-
- if ((otgsc & mvotg->irq_status) == 0)
- return IRQ_NONE;
-
- mv_otg_run_state_machine(mvotg, 0);
-
- return IRQ_HANDLED;
-}
-
-static irqreturn_t mv_otg_inputs_irq(int irq, void *dev)
-{
- struct mv_otg *mvotg = dev;
-
- /* The clock may disabled at this time */
- if (!mvotg->active) {
- mv_otg_enable(mvotg);
- mv_otg_init_irq(mvotg);
- }
-
- mv_otg_run_state_machine(mvotg, 0);
-
- return IRQ_HANDLED;
-}
-
-static ssize_t
-a_bus_req_show(struct device *dev, struct device_attribute *attr, char *buf)
-{
- struct mv_otg *mvotg = dev_get_drvdata(dev);
- return scnprintf(buf, PAGE_SIZE, "%d\n",
- mvotg->otg_ctrl.a_bus_req);
-}
-
-static ssize_t
-a_bus_req_store(struct device *dev, struct device_attribute *attr,
- const char *buf, size_t count)
-{
- struct mv_otg *mvotg = dev_get_drvdata(dev);
-
- if (count > 2)
- return -1;
-
- /* We will use this interface to change to A device */
- if (mvotg->phy.otg->state != OTG_STATE_B_IDLE
- && mvotg->phy.otg->state != OTG_STATE_A_IDLE)
- return -1;
-
- /* The clock may disabled and we need to set irq for ID detected */
- mv_otg_enable(mvotg);
- mv_otg_init_irq(mvotg);
-
- if (buf[0] == '1') {
- mvotg->otg_ctrl.a_bus_req = 1;
- mvotg->otg_ctrl.a_bus_drop = 0;
- dev_dbg(&mvotg->pdev->dev,
- "User request: a_bus_req = 1\n");
-
- if (spin_trylock(&mvotg->wq_lock)) {
- mv_otg_run_state_machine(mvotg, 0);
- spin_unlock(&mvotg->wq_lock);
- }
- }
-
- return count;
-}
-
-static DEVICE_ATTR_RW(a_bus_req);
-
-static ssize_t
-a_clr_err_store(struct device *dev, struct device_attribute *attr,
- const char *buf, size_t count)
-{
- struct mv_otg *mvotg = dev_get_drvdata(dev);
- if (!mvotg->phy.otg->default_a)
- return -1;
-
- if (count > 2)
- return -1;
-
- if (buf[0] == '1') {
- mvotg->otg_ctrl.a_clr_err = 1;
- dev_dbg(&mvotg->pdev->dev,
- "User request: a_clr_err = 1\n");
- }
-
- if (spin_trylock(&mvotg->wq_lock)) {
- mv_otg_run_state_machine(mvotg, 0);
- spin_unlock(&mvotg->wq_lock);
- }
-
- return count;
-}
-
-static DEVICE_ATTR_WO(a_clr_err);
-
-static ssize_t
-a_bus_drop_show(struct device *dev, struct device_attribute *attr,
- char *buf)
-{
- struct mv_otg *mvotg = dev_get_drvdata(dev);
- return scnprintf(buf, PAGE_SIZE, "%d\n",
- mvotg->otg_ctrl.a_bus_drop);
-}
-
-static ssize_t
-a_bus_drop_store(struct device *dev, struct device_attribute *attr,
- const char *buf, size_t count)
-{
- struct mv_otg *mvotg = dev_get_drvdata(dev);
- if (!mvotg->phy.otg->default_a)
- return -1;
-
- if (count > 2)
- return -1;
-
- if (buf[0] == '0') {
- mvotg->otg_ctrl.a_bus_drop = 0;
- dev_dbg(&mvotg->pdev->dev,
- "User request: a_bus_drop = 0\n");
- } else if (buf[0] == '1') {
- mvotg->otg_ctrl.a_bus_drop = 1;
- mvotg->otg_ctrl.a_bus_req = 0;
- dev_dbg(&mvotg->pdev->dev,
- "User request: a_bus_drop = 1\n");
- dev_dbg(&mvotg->pdev->dev,
- "User request: and a_bus_req = 0\n");
- }
-
- if (spin_trylock(&mvotg->wq_lock)) {
- mv_otg_run_state_machine(mvotg, 0);
- spin_unlock(&mvotg->wq_lock);
- }
-
- return count;
-}
-
-static DEVICE_ATTR_RW(a_bus_drop);
-
-static struct attribute *inputs_attrs[] = {
- &dev_attr_a_bus_req.attr,
- &dev_attr_a_clr_err.attr,
- &dev_attr_a_bus_drop.attr,
- NULL,
-};
-
-static const struct attribute_group inputs_attr_group = {
- .name = "inputs",
- .attrs = inputs_attrs,
-};
-
-static const struct attribute_group *mv_otg_groups[] = {
- &inputs_attr_group,
- NULL,
-};
-
-static void mv_otg_remove(struct platform_device *pdev)
-{
- struct mv_otg *mvotg = platform_get_drvdata(pdev);
-
- if (mvotg->qwork)
- destroy_workqueue(mvotg->qwork);
-
- mv_otg_disable(mvotg);
-
- usb_remove_phy(&mvotg->phy);
-}
-
-static int mv_otg_probe(struct platform_device *pdev)
-{
- struct mv_usb_platform_data *pdata = dev_get_platdata(&pdev->dev);
- struct mv_otg *mvotg;
- struct usb_otg *otg;
- struct resource *r;
- int retval = 0, i;
-
- if (pdata == NULL) {
- dev_err(&pdev->dev, "failed to get platform data\n");
- return -ENODEV;
- }
-
- mvotg = devm_kzalloc(&pdev->dev, sizeof(*mvotg), GFP_KERNEL);
- if (!mvotg)
- return -ENOMEM;
-
- otg = devm_kzalloc(&pdev->dev, sizeof(*otg), GFP_KERNEL);
- if (!otg)
- return -ENOMEM;
-
- platform_set_drvdata(pdev, mvotg);
-
- mvotg->pdev = pdev;
- mvotg->pdata = pdata;
-
- mvotg->clk = devm_clk_get(&pdev->dev, NULL);
- if (IS_ERR(mvotg->clk))
- return PTR_ERR(mvotg->clk);
-
- mvotg->qwork = create_singlethread_workqueue("mv_otg_queue");
- if (!mvotg->qwork) {
- dev_dbg(&pdev->dev, "cannot create workqueue for OTG\n");
- return -ENOMEM;
- }
-
- INIT_DELAYED_WORK(&mvotg->work, mv_otg_work);
-
- /* OTG common part */
- mvotg->pdev = pdev;
- mvotg->phy.dev = &pdev->dev;
- mvotg->phy.otg = otg;
- mvotg->phy.label = driver_name;
-
- otg->state = OTG_STATE_UNDEFINED;
- otg->usb_phy = &mvotg->phy;
- otg->set_host = mv_otg_set_host;
- otg->set_peripheral = mv_otg_set_peripheral;
- otg->set_vbus = mv_otg_set_vbus;
-
- for (i = 0; i < OTG_TIMER_NUM; i++)
- timer_setup(&mvotg->otg_ctrl.timer[i],
- mv_otg_timer_await_bcon, 0);
-
- r = platform_get_resource_byname(mvotg->pdev,
- IORESOURCE_MEM, "phyregs");
- if (r == NULL) {
- dev_err(&pdev->dev, "no phy I/O memory resource defined\n");
- retval = -ENODEV;
- goto err_destroy_workqueue;
- }
-
- mvotg->phy_regs = devm_ioremap(&pdev->dev, r->start, resource_size(r));
- if (mvotg->phy_regs == NULL) {
- dev_err(&pdev->dev, "failed to map phy I/O memory\n");
- retval = -EFAULT;
- goto err_destroy_workqueue;
- }
-
- r = platform_get_resource_byname(mvotg->pdev,
- IORESOURCE_MEM, "capregs");
- if (r == NULL) {
- dev_err(&pdev->dev, "no I/O memory resource defined\n");
- retval = -ENODEV;
- goto err_destroy_workqueue;
- }
-
- mvotg->cap_regs = devm_ioremap(&pdev->dev, r->start, resource_size(r));
- if (mvotg->cap_regs == NULL) {
- dev_err(&pdev->dev, "failed to map I/O memory\n");
- retval = -EFAULT;
- goto err_destroy_workqueue;
- }
-
- /* we will acces controller register, so enable the udc controller */
- retval = mv_otg_enable_internal(mvotg);
- if (retval) {
- dev_err(&pdev->dev, "mv otg enable error %d\n", retval);
- goto err_destroy_workqueue;
- }
-
- mvotg->op_regs =
- (struct mv_otg_regs __iomem *) ((unsigned long) mvotg->cap_regs
- + (readl(mvotg->cap_regs) & CAPLENGTH_MASK));
-
- if (pdata->id) {
- retval = devm_request_threaded_irq(&pdev->dev, pdata->id->irq,
- NULL, mv_otg_inputs_irq,
- IRQF_ONESHOT, "id", mvotg);
- if (retval) {
- dev_info(&pdev->dev,
- "Failed to request irq for ID\n");
- pdata->id = NULL;
- }
- }
-
- if (pdata->vbus) {
- mvotg->clock_gating = 1;
- retval = devm_request_threaded_irq(&pdev->dev, pdata->vbus->irq,
- NULL, mv_otg_inputs_irq,
- IRQF_ONESHOT, "vbus", mvotg);
- if (retval) {
- dev_info(&pdev->dev,
- "Failed to request irq for VBUS, "
- "disable clock gating\n");
- mvotg->clock_gating = 0;
- pdata->vbus = NULL;
- }
- }
-
- if (pdata->disable_otg_clock_gating)
- mvotg->clock_gating = 0;
-
- mv_otg_reset(mvotg);
- mv_otg_init_irq(mvotg);
-
- r = platform_get_resource(mvotg->pdev, IORESOURCE_IRQ, 0);
- if (r == NULL) {
- dev_err(&pdev->dev, "no IRQ resource defined\n");
- retval = -ENODEV;
- goto err_disable_clk;
- }
-
- mvotg->irq = r->start;
- if (devm_request_irq(&pdev->dev, mvotg->irq, mv_otg_irq, IRQF_SHARED,
- driver_name, mvotg)) {
- dev_err(&pdev->dev, "Request irq %d for OTG failed\n",
- mvotg->irq);
- mvotg->irq = 0;
- retval = -ENODEV;
- goto err_disable_clk;
- }
-
- retval = usb_add_phy(&mvotg->phy, USB_PHY_TYPE_USB2);
- if (retval < 0) {
- dev_err(&pdev->dev, "can't register transceiver, %d\n",
- retval);
- goto err_disable_clk;
- }
-
- spin_lock_init(&mvotg->wq_lock);
- if (spin_trylock(&mvotg->wq_lock)) {
- mv_otg_run_state_machine(mvotg, 2 * HZ);
- spin_unlock(&mvotg->wq_lock);
- }
-
- dev_info(&pdev->dev,
- "successful probe OTG device %s clock gating.\n",
- mvotg->clock_gating ? "with" : "without");
-
- return 0;
-
-err_disable_clk:
- mv_otg_disable_internal(mvotg);
-err_destroy_workqueue:
- destroy_workqueue(mvotg->qwork);
-
- return retval;
-}
-
-#ifdef CONFIG_PM
-static int mv_otg_suspend(struct platform_device *pdev, pm_message_t state)
-{
- struct mv_otg *mvotg = platform_get_drvdata(pdev);
-
- if (mvotg->phy.otg->state != OTG_STATE_B_IDLE) {
- dev_info(&pdev->dev,
- "OTG state is not B_IDLE, it is %d!\n",
- mvotg->phy.otg->state);
- return -EAGAIN;
- }
-
- if (!mvotg->clock_gating)
- mv_otg_disable_internal(mvotg);
-
- return 0;
-}
-
-static int mv_otg_resume(struct platform_device *pdev)
-{
- struct mv_otg *mvotg = platform_get_drvdata(pdev);
- u32 otgsc;
-
- if (!mvotg->clock_gating) {
- mv_otg_enable_internal(mvotg);
-
- otgsc = readl(&mvotg->op_regs->otgsc);
- otgsc |= mvotg->irq_en;
- writel(otgsc, &mvotg->op_regs->otgsc);
-
- if (spin_trylock(&mvotg->wq_lock)) {
- mv_otg_run_state_machine(mvotg, 0);
- spin_unlock(&mvotg->wq_lock);
- }
- }
- return 0;
-}
-#endif
-
-static struct platform_driver mv_otg_driver = {
- .probe = mv_otg_probe,
- .remove = mv_otg_remove,
- .driver = {
- .name = driver_name,
- .dev_groups = mv_otg_groups,
- },
-#ifdef CONFIG_PM
- .suspend = mv_otg_suspend,
- .resume = mv_otg_resume,
-#endif
-};
-module_platform_driver(mv_otg_driver);
diff --git a/drivers/usb/phy/phy-mxs-usb.c b/drivers/usb/phy/phy-mxs-usb.c
index 7490f1798b46..7069dd3f4d0d 100644
--- a/drivers/usb/phy/phy-mxs-usb.c
+++ b/drivers/usb/phy/phy-mxs-usb.c
@@ -769,11 +769,9 @@ static int mxs_phy_probe(struct platform_device *pdev)
return PTR_ERR(base);
clk = devm_clk_get(&pdev->dev, NULL);
- if (IS_ERR(clk)) {
- dev_err(&pdev->dev,
- "can't get the clock, err=%ld", PTR_ERR(clk));
- return PTR_ERR(clk);
- }
+ if (IS_ERR(clk))
+ return dev_err_probe(&pdev->dev, PTR_ERR(clk),
+ "can't get the clock\n");
mxs_phy = devm_kzalloc(&pdev->dev, sizeof(*mxs_phy), GFP_KERNEL);
if (!mxs_phy)
diff --git a/drivers/usb/phy/phy-tegra-usb.c b/drivers/usb/phy/phy-tegra-usb.c
index bee222967f6b..00443a7beaeb 100644
--- a/drivers/usb/phy/phy-tegra-usb.c
+++ b/drivers/usb/phy/phy-tegra-usb.c
@@ -29,17 +29,26 @@
#include <linux/usb/tegra_usb_phy.h>
#include <linux/usb/ulpi.h>
+#define USB_TXFILLTUNING 0x154
+#define USB_FIFO_TXFILL_THRES(x) (((x) & 0x1f) << 16)
+#define USB_FIFO_TXFILL_MASK 0x1f0000
+
#define ULPI_VIEWPORT 0x170
/* PORTSC PTS/PHCD bits, Tegra20 only */
#define TEGRA_USB_PORTSC1 0x184
-#define TEGRA_USB_PORTSC1_PTS(x) (((x) & 0x3) << 30)
-#define TEGRA_USB_PORTSC1_PHCD BIT(23)
+#define TEGRA_USB_PORTSC1_PTS(x) (((x) & 0x3) << 30)
+#define TEGRA_USB_PORTSC1_PHCD BIT(23)
+#define TEGRA_USB_PORTSC1_WKOC BIT(22)
+#define TEGRA_USB_PORTSC1_WKDS BIT(21)
+#define TEGRA_USB_PORTSC1_WKCN BIT(20)
/* HOSTPC1 PTS/PHCD bits, Tegra30 and above */
+#define TEGRA30_USB_PORTSC1 0x174
#define TEGRA_USB_HOSTPC1_DEVLC 0x1b4
-#define TEGRA_USB_HOSTPC1_DEVLC_PTS(x) (((x) & 0x7) << 29)
-#define TEGRA_USB_HOSTPC1_DEVLC_PHCD BIT(22)
+#define TEGRA_USB_HOSTPC1_DEVLC_PTS(x) (((x) & 0x7) << 29)
+#define TEGRA_USB_HOSTPC1_DEVLC_PHCD BIT(22)
+#define TEGRA_USB_HOSTPC1_DEVLC_PTS_HSIC 4
/* Bits of PORTSC1, which will get cleared by writing 1 into them */
#define TEGRA_PORTSC1_RWC_BITS (PORT_CSC | PORT_PEC | PORT_OCC)
@@ -51,11 +60,12 @@
#define USB_SUSP_CLR BIT(5)
#define USB_PHY_CLK_VALID BIT(7)
#define UTMIP_RESET BIT(11)
-#define UHSIC_RESET BIT(11)
#define UTMIP_PHY_ENABLE BIT(12)
#define ULPI_PHY_ENABLE BIT(13)
#define USB_SUSP_SET BIT(14)
+#define UHSIC_RESET BIT(14)
#define USB_WAKEUP_DEBOUNCE_COUNT(x) (((x) & 0x7) << 16)
+#define UHSIC_PHY_ENABLE BIT(19)
#define USB_PHY_VBUS_SENSORS 0x404
#define B_SESS_VLD_WAKEUP_EN BIT(14)
@@ -156,6 +166,58 @@
#define UTMIP_BIAS_CFG1 0x83c
#define UTMIP_BIAS_PDTRK_COUNT(x) (((x) & 0x1f) << 3)
+/*
+ * Tegra20 has no UTMIP registers on PHY2 and UHSIC registers start from 0x800
+ * just where UTMIP registers should have been. This is the case only with Tegra20
+ * Tegra30+ have UTMIP registers at 0x800 and UHSIC registers are shifted by 0x400
+ * to 0xc00, but register layout is preserved.
+ */
+#define UHSIC_PLL_CFG1 0x804
+#define UHSIC_XTAL_FREQ_COUNT(x) (((x) & 0xfff) << 0)
+#define UHSIC_PLLU_ENABLE_DLY_COUNT(x) (((x) & 0x1f) << 14)
+
+#define UHSIC_HSRX_CFG0 0x808
+#define UHSIC_ELASTIC_UNDERRUN_LIMIT(x) (((x) & 0x1f) << 2)
+#define UHSIC_ELASTIC_OVERRUN_LIMIT(x) (((x) & 0x1f) << 8)
+#define UHSIC_IDLE_WAIT(x) (((x) & 0x1f) << 13)
+
+#define UHSIC_HSRX_CFG1 0x80c
+#define UHSIC_HS_SYNC_START_DLY(x) (((x) & 0x1f) << 1)
+
+#define UHSIC_TX_CFG0 0x810
+#define UHSIC_HS_READY_WAIT_FOR_VALID BIT(9)
+
+#define UHSIC_MISC_CFG0 0x814
+#define UHSIC_SUSPEND_EXIT_ON_EDGE BIT(7)
+#define UHSIC_DETECT_SHORT_CONNECT BIT(8)
+#define UHSIC_FORCE_XCVR_MODE BIT(15)
+#define UHSIC_DISABLE_BUSRESET BIT(20)
+
+#define UHSIC_MISC_CFG1 0x818
+#define UHSIC_PLLU_STABLE_COUNT(x) (((x) & 0xfff) << 2)
+
+#define UHSIC_PADS_CFG0 0x81c
+#define UHSIC_TX_RTUNEN 0xf000
+#define UHSIC_TX_RTUNE(x) (((x) & 0xf) << 12)
+
+#define UHSIC_PADS_CFG1 0x820
+#define UHSIC_PD_BG BIT(2)
+#define UHSIC_PD_TX BIT(3)
+#define UHSIC_PD_TRK BIT(4)
+#define UHSIC_PD_RX BIT(5)
+#define UHSIC_PD_ZI BIT(6)
+#define UHSIC_RX_SEL BIT(7)
+#define UHSIC_RPD_DATA BIT(9)
+#define UHSIC_RPD_STROBE BIT(10)
+#define UHSIC_RPU_DATA BIT(11)
+#define UHSIC_RPU_STROBE BIT(12)
+
+#define UHSIC_CMD_CFG0 0x824
+#define UHSIC_PRETEND_CONNECT_DETECT BIT(5)
+
+#define UHSIC_STAT_CFG0 0x828
+#define UHSIC_CONNECT_DETECT BIT(0)
+
/* For Tegra30 and above only, the address is different in Tegra20 */
#define USB_USBMODE 0x1f8
#define USB_USBMODE_MASK (3 << 0)
@@ -174,7 +236,8 @@ struct tegra_xtal_freq {
u8 enable_delay;
u8 stable_count;
u8 active_delay;
- u8 xtal_freq_count;
+ u8 utmi_xtal_freq_count;
+ u16 hsic_xtal_freq_count;
u16 debounce;
};
@@ -184,7 +247,8 @@ static const struct tegra_xtal_freq tegra_freq_table[] = {
.enable_delay = 0x02,
.stable_count = 0x2F,
.active_delay = 0x04,
- .xtal_freq_count = 0x76,
+ .utmi_xtal_freq_count = 0x76,
+ .hsic_xtal_freq_count = 0x1CA,
.debounce = 0x7530,
},
{
@@ -192,7 +256,8 @@ static const struct tegra_xtal_freq tegra_freq_table[] = {
.enable_delay = 0x02,
.stable_count = 0x33,
.active_delay = 0x05,
- .xtal_freq_count = 0x7F,
+ .utmi_xtal_freq_count = 0x7F,
+ .hsic_xtal_freq_count = 0x1F0,
.debounce = 0x7EF4,
},
{
@@ -200,7 +265,8 @@ static const struct tegra_xtal_freq tegra_freq_table[] = {
.enable_delay = 0x03,
.stable_count = 0x4B,
.active_delay = 0x06,
- .xtal_freq_count = 0xBB,
+ .utmi_xtal_freq_count = 0xBB,
+ .hsic_xtal_freq_count = 0x2DD,
.debounce = 0xBB80,
},
{
@@ -208,7 +274,8 @@ static const struct tegra_xtal_freq tegra_freq_table[] = {
.enable_delay = 0x04,
.stable_count = 0x66,
.active_delay = 0x09,
- .xtal_freq_count = 0xFE,
+ .utmi_xtal_freq_count = 0xFE,
+ .hsic_xtal_freq_count = 0x3E0,
.debounce = 0xFDE8,
},
};
@@ -532,7 +599,7 @@ static int utmi_phy_power_on(struct tegra_usb_phy *phy)
val = readl_relaxed(base + UTMIP_PLL_CFG1);
val &= ~(UTMIP_XTAL_FREQ_COUNT(~0) |
UTMIP_PLLU_ENABLE_DLY_COUNT(~0));
- val |= UTMIP_XTAL_FREQ_COUNT(phy->freq->xtal_freq_count) |
+ val |= UTMIP_XTAL_FREQ_COUNT(phy->freq->utmi_xtal_freq_count) |
UTMIP_PLLU_ENABLE_DLY_COUNT(phy->freq->enable_delay);
writel_relaxed(val, base + UTMIP_PLL_CFG1);
}
@@ -711,58 +778,6 @@ static int utmi_phy_power_off(struct tegra_usb_phy *phy)
return utmip_pad_power_off(phy);
}
-static void utmi_phy_preresume(struct tegra_usb_phy *phy)
-{
- void __iomem *base = phy->regs;
- u32 val;
-
- val = readl_relaxed(base + UTMIP_TX_CFG0);
- val |= UTMIP_HS_DISCON_DISABLE;
- writel_relaxed(val, base + UTMIP_TX_CFG0);
-}
-
-static void utmi_phy_postresume(struct tegra_usb_phy *phy)
-{
- void __iomem *base = phy->regs;
- u32 val;
-
- val = readl_relaxed(base + UTMIP_TX_CFG0);
- val &= ~UTMIP_HS_DISCON_DISABLE;
- writel_relaxed(val, base + UTMIP_TX_CFG0);
-}
-
-static void utmi_phy_restore_start(struct tegra_usb_phy *phy,
- enum tegra_usb_phy_port_speed port_speed)
-{
- void __iomem *base = phy->regs;
- u32 val;
-
- val = readl_relaxed(base + UTMIP_MISC_CFG0);
- val &= ~UTMIP_DPDM_OBSERVE_SEL(~0);
- if (port_speed == TEGRA_USB_PHY_PORT_SPEED_LOW)
- val |= UTMIP_DPDM_OBSERVE_SEL_FS_K;
- else
- val |= UTMIP_DPDM_OBSERVE_SEL_FS_J;
- writel_relaxed(val, base + UTMIP_MISC_CFG0);
- usleep_range(1, 10);
-
- val = readl_relaxed(base + UTMIP_MISC_CFG0);
- val |= UTMIP_DPDM_OBSERVE;
- writel_relaxed(val, base + UTMIP_MISC_CFG0);
- usleep_range(10, 100);
-}
-
-static void utmi_phy_restore_end(struct tegra_usb_phy *phy)
-{
- void __iomem *base = phy->regs;
- u32 val;
-
- val = readl_relaxed(base + UTMIP_MISC_CFG0);
- val &= ~UTMIP_DPDM_OBSERVE;
- writel_relaxed(val, base + UTMIP_MISC_CFG0);
- usleep_range(10, 100);
-}
-
static int ulpi_phy_power_on(struct tegra_usb_phy *phy)
{
void __iomem *base = phy->regs;
@@ -855,17 +870,170 @@ static int ulpi_phy_power_off(struct tegra_usb_phy *phy)
return 0;
}
+static u32 tegra_hsic_readl(struct tegra_usb_phy *phy, u32 reg)
+{
+ void __iomem *base = phy->regs;
+ u32 shift = phy->soc_config->uhsic_registers_offset;
+
+ return readl_relaxed(base + shift + reg);
+}
+
+static void tegra_hsic_writel(struct tegra_usb_phy *phy, u32 reg, u32 value)
+{
+ void __iomem *base = phy->regs;
+ u32 shift = phy->soc_config->uhsic_registers_offset;
+
+ writel_relaxed(value, base + shift + reg);
+}
+
+static int uhsic_phy_power_on(struct tegra_usb_phy *phy)
+{
+ struct tegra_utmip_config *config = phy->config;
+ void __iomem *base = phy->regs;
+ u32 val;
+ int err = 0;
+
+ val = tegra_hsic_readl(phy, UHSIC_PADS_CFG1);
+ val &= ~(UHSIC_PD_BG | UHSIC_PD_TX | UHSIC_PD_TRK | UHSIC_PD_RX |
+ UHSIC_PD_ZI | UHSIC_RPD_DATA | UHSIC_RPD_STROBE);
+ val |= UHSIC_RX_SEL;
+ tegra_hsic_writel(phy, UHSIC_PADS_CFG1, val);
+
+ udelay(2);
+
+ val = readl_relaxed(base + USB_SUSP_CTRL);
+ val |= UHSIC_RESET;
+ writel_relaxed(val, base + USB_SUSP_CTRL);
+
+ udelay(30);
+
+ val = readl_relaxed(base + USB_SUSP_CTRL);
+ val |= UHSIC_PHY_ENABLE;
+ writel_relaxed(val, base + USB_SUSP_CTRL);
+
+ val = tegra_hsic_readl(phy, UHSIC_HSRX_CFG0);
+ val &= ~(UHSIC_IDLE_WAIT(~0) |
+ UHSIC_ELASTIC_UNDERRUN_LIMIT(~0) |
+ UHSIC_ELASTIC_OVERRUN_LIMIT(~0));
+ val |= UHSIC_IDLE_WAIT(config->idle_wait_delay) |
+ UHSIC_ELASTIC_UNDERRUN_LIMIT(config->elastic_limit) |
+ UHSIC_ELASTIC_OVERRUN_LIMIT(config->elastic_limit);
+ tegra_hsic_writel(phy, UHSIC_HSRX_CFG0, val);
+
+ val = tegra_hsic_readl(phy, UHSIC_HSRX_CFG1);
+ val &= ~UHSIC_HS_SYNC_START_DLY(~0);
+ val |= UHSIC_HS_SYNC_START_DLY(config->hssync_start_delay);
+ tegra_hsic_writel(phy, UHSIC_HSRX_CFG1, val);
+
+ val = tegra_hsic_readl(phy, UHSIC_MISC_CFG0);
+ val |= UHSIC_SUSPEND_EXIT_ON_EDGE;
+ tegra_hsic_writel(phy, UHSIC_MISC_CFG0, val);
+
+ val = tegra_hsic_readl(phy, UHSIC_MISC_CFG1);
+ val &= ~UHSIC_PLLU_STABLE_COUNT(~0);
+ val |= UHSIC_PLLU_STABLE_COUNT(phy->freq->stable_count);
+ tegra_hsic_writel(phy, UHSIC_MISC_CFG1, val);
+
+ val = tegra_hsic_readl(phy, UHSIC_PLL_CFG1);
+ val &= ~(UHSIC_XTAL_FREQ_COUNT(~0) |
+ UHSIC_PLLU_ENABLE_DLY_COUNT(~0));
+ val |= UHSIC_XTAL_FREQ_COUNT(phy->freq->hsic_xtal_freq_count) |
+ UHSIC_PLLU_ENABLE_DLY_COUNT(phy->freq->enable_delay);
+ tegra_hsic_writel(phy, UHSIC_PLL_CFG1, val);
+
+ val = readl_relaxed(base + USB_SUSP_CTRL);
+ val &= ~UHSIC_RESET;
+ writel_relaxed(val, base + USB_SUSP_CTRL);
+
+ udelay(2);
+
+ if (phy->soc_config->requires_usbmode_setup) {
+ val = readl_relaxed(base + USB_USBMODE);
+ val &= ~USB_USBMODE_MASK;
+ if (phy->mode == USB_DR_MODE_HOST)
+ val |= USB_USBMODE_HOST;
+ else
+ val |= USB_USBMODE_DEVICE;
+ writel_relaxed(val, base + USB_USBMODE);
+ }
+
+ set_pts(phy, phy->soc_config->uhsic_pts_value);
+
+ val = readl_relaxed(base + USB_TXFILLTUNING);
+ if ((val & USB_FIFO_TXFILL_MASK) != USB_FIFO_TXFILL_THRES(0x10)) {
+ val = USB_FIFO_TXFILL_THRES(0x10);
+ writel_relaxed(val, base + USB_TXFILLTUNING);
+ }
+
+ val = readl_relaxed(base + phy->soc_config->portsc1_offset);
+ val &= ~(TEGRA_USB_PORTSC1_WKOC | TEGRA_USB_PORTSC1_WKDS |
+ TEGRA_USB_PORTSC1_WKCN);
+ writel_relaxed(val, base + phy->soc_config->portsc1_offset);
+
+ val = tegra_hsic_readl(phy, UHSIC_PADS_CFG0);
+ val &= ~UHSIC_TX_RTUNEN;
+ val |= UHSIC_TX_RTUNE(phy->soc_config->uhsic_tx_rtune);
+ tegra_hsic_writel(phy, UHSIC_PADS_CFG0, val);
+
+ err = utmi_wait_register(base + USB_SUSP_CTRL, USB_PHY_CLK_VALID,
+ USB_PHY_CLK_VALID);
+
+ if (err)
+ dev_err(phy->u_phy.dev,
+ "Timeout waiting for PHY to stabilize on enable (HSIC)\n");
+
+ return err;
+}
+
+static int uhsic_phy_power_off(struct tegra_usb_phy *phy)
+{
+ void __iomem *base = phy->regs;
+ u32 val;
+
+ set_phcd(phy, true);
+
+ val = tegra_hsic_readl(phy, UHSIC_PADS_CFG1);
+ val |= (UHSIC_PD_BG | UHSIC_PD_TX | UHSIC_PD_TRK | UHSIC_PD_RX |
+ UHSIC_PD_ZI | UHSIC_RPD_DATA | UHSIC_RPD_STROBE);
+ tegra_hsic_writel(phy, UHSIC_PADS_CFG1, val);
+
+ val = readl_relaxed(base + USB_SUSP_CTRL);
+ val |= UHSIC_RESET;
+ writel_relaxed(val, base + USB_SUSP_CTRL);
+
+ udelay(30);
+
+ val = readl_relaxed(base + USB_SUSP_CTRL);
+ val &= ~UHSIC_PHY_ENABLE;
+ writel_relaxed(val, base + USB_SUSP_CTRL);
+
+ return 0;
+}
+
static int tegra_usb_phy_power_on(struct tegra_usb_phy *phy)
{
- int err;
+ int err = 0;
if (phy->powered_on)
return 0;
- if (phy->is_ulpi_phy)
- err = ulpi_phy_power_on(phy);
- else
+ switch (phy->phy_type) {
+ case USBPHY_INTERFACE_MODE_UTMI:
err = utmi_phy_power_on(phy);
+ break;
+
+ case USBPHY_INTERFACE_MODE_ULPI:
+ err = ulpi_phy_power_on(phy);
+ break;
+
+ case USBPHY_INTERFACE_MODE_HSIC:
+ err = uhsic_phy_power_on(phy);
+ break;
+
+ default:
+ break;
+ }
+
if (err)
return err;
@@ -879,15 +1047,28 @@ static int tegra_usb_phy_power_on(struct tegra_usb_phy *phy)
static int tegra_usb_phy_power_off(struct tegra_usb_phy *phy)
{
- int err;
+ int err = 0;
if (!phy->powered_on)
return 0;
- if (phy->is_ulpi_phy)
- err = ulpi_phy_power_off(phy);
- else
+ switch (phy->phy_type) {
+ case USBPHY_INTERFACE_MODE_UTMI:
err = utmi_phy_power_off(phy);
+ break;
+
+ case USBPHY_INTERFACE_MODE_ULPI:
+ err = ulpi_phy_power_off(phy);
+ break;
+
+ case USBPHY_INTERFACE_MODE_HSIC:
+ err = uhsic_phy_power_off(phy);
+ break;
+
+ default:
+ break;
+ }
+
if (err)
return err;
@@ -906,7 +1087,7 @@ static void tegra_usb_phy_shutdown(struct usb_phy *u_phy)
usb_phy_set_wakeup(u_phy, false);
tegra_usb_phy_power_off(phy);
- if (!phy->is_ulpi_phy)
+ if (phy->phy_type == USBPHY_INTERFACE_MODE_UTMI)
utmip_pad_close(phy);
regulator_disable(phy->vbus);
@@ -1092,7 +1273,7 @@ static int tegra_usb_phy_init(struct usb_phy *u_phy)
goto disable_clk;
}
- if (!phy->is_ulpi_phy) {
+ if (phy->phy_type == USBPHY_INTERFACE_MODE_UTMI) {
err = utmip_pad_open(phy);
if (err)
goto disable_vbus;
@@ -1109,7 +1290,7 @@ static int tegra_usb_phy_init(struct usb_phy *u_phy)
return 0;
close_phy:
- if (!phy->is_ulpi_phy)
+ if (phy->phy_type == USBPHY_INTERFACE_MODE_UTMI)
utmip_pad_close(phy);
disable_vbus:
@@ -1123,43 +1304,6 @@ disable_clk:
return err;
}
-void tegra_usb_phy_preresume(struct usb_phy *u_phy)
-{
- struct tegra_usb_phy *phy = to_tegra_usb_phy(u_phy);
-
- if (!phy->is_ulpi_phy)
- utmi_phy_preresume(phy);
-}
-EXPORT_SYMBOL_GPL(tegra_usb_phy_preresume);
-
-void tegra_usb_phy_postresume(struct usb_phy *u_phy)
-{
- struct tegra_usb_phy *phy = to_tegra_usb_phy(u_phy);
-
- if (!phy->is_ulpi_phy)
- utmi_phy_postresume(phy);
-}
-EXPORT_SYMBOL_GPL(tegra_usb_phy_postresume);
-
-void tegra_ehci_phy_restore_start(struct usb_phy *u_phy,
- enum tegra_usb_phy_port_speed port_speed)
-{
- struct tegra_usb_phy *phy = to_tegra_usb_phy(u_phy);
-
- if (!phy->is_ulpi_phy)
- utmi_phy_restore_start(phy, port_speed);
-}
-EXPORT_SYMBOL_GPL(tegra_ehci_phy_restore_start);
-
-void tegra_ehci_phy_restore_end(struct usb_phy *u_phy)
-{
- struct tegra_usb_phy *phy = to_tegra_usb_phy(u_phy);
-
- if (!phy->is_ulpi_phy)
- utmi_phy_restore_end(phy);
-}
-EXPORT_SYMBOL_GPL(tegra_ehci_phy_restore_end);
-
static int read_utmi_param(struct platform_device *pdev, const char *param,
u8 *dest)
{
@@ -1184,8 +1328,6 @@ static int utmi_phy_probe(struct tegra_usb_phy *tegra_phy,
struct resource *res;
int err;
- tegra_phy->is_ulpi_phy = false;
-
res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
if (!res) {
dev_err(&pdev->dev, "Failed to get UTMI pad regs\n");
@@ -1320,6 +1462,10 @@ static const struct tegra_phy_soc_config tegra20_soc_config = {
.requires_usbmode_setup = false,
.requires_extra_tuning_parameters = false,
.requires_pmc_ao_power_up = false,
+ .uhsic_registers_offset = 0,
+ .uhsic_tx_rtune = 0, /* 40 ohm */
+ .uhsic_pts_value = 0, /* UTMI */
+ .portsc1_offset = TEGRA_USB_PORTSC1,
};
static const struct tegra_phy_soc_config tegra30_soc_config = {
@@ -1328,6 +1474,10 @@ static const struct tegra_phy_soc_config tegra30_soc_config = {
.requires_usbmode_setup = true,
.requires_extra_tuning_parameters = true,
.requires_pmc_ao_power_up = true,
+ .uhsic_registers_offset = 0x400,
+ .uhsic_tx_rtune = 8, /* 50 ohm */
+ .uhsic_pts_value = TEGRA_USB_HOSTPC1_DEVLC_PTS_HSIC,
+ .portsc1_offset = TEGRA30_USB_PORTSC1,
};
static const struct of_device_id tegra_usb_phy_id_table[] = {
@@ -1341,7 +1491,6 @@ static int tegra_usb_phy_probe(struct platform_device *pdev)
{
struct device_node *np = pdev->dev.of_node;
struct tegra_usb_phy *tegra_phy;
- enum usb_phy_interface phy_type;
struct reset_control *reset;
struct gpio_desc *gpiod;
struct resource *res;
@@ -1403,9 +1552,10 @@ static int tegra_usb_phy_probe(struct platform_device *pdev)
return err;
}
- phy_type = of_usb_get_phy_mode(np);
- switch (phy_type) {
+ tegra_phy->phy_type = of_usb_get_phy_mode(np);
+ switch (tegra_phy->phy_type) {
case USBPHY_INTERFACE_MODE_UTMI:
+ case USBPHY_INTERFACE_MODE_HSIC:
err = utmi_phy_probe(tegra_phy, pdev);
if (err)
return err;
@@ -1430,8 +1580,6 @@ static int tegra_usb_phy_probe(struct platform_device *pdev)
break;
case USBPHY_INTERFACE_MODE_ULPI:
- tegra_phy->is_ulpi_phy = true;
-
tegra_phy->clk = devm_clk_get(&pdev->dev, "ulpi-link");
err = PTR_ERR_OR_ZERO(tegra_phy->clk);
if (err) {
@@ -1471,7 +1619,7 @@ static int tegra_usb_phy_probe(struct platform_device *pdev)
default:
dev_err(&pdev->dev, "phy_type %u is invalid or unsupported\n",
- phy_type);
+ tegra_phy->phy_type);
return -EINVAL;
}
diff --git a/drivers/usb/phy/phy-twl6030-usb.c b/drivers/usb/phy/phy-twl6030-usb.c
index 49d79c1257f3..8c09db750bfd 100644
--- a/drivers/usb/phy/phy-twl6030-usb.c
+++ b/drivers/usb/phy/phy-twl6030-usb.c
@@ -328,9 +328,8 @@ static int twl6030_set_vbus(struct phy_companion *comparator, bool enabled)
static int twl6030_usb_probe(struct platform_device *pdev)
{
- u32 ret;
struct twl6030_usb *twl;
- int status, err;
+ int status, err, ret;
struct device_node *np = pdev->dev.of_node;
struct device *dev = &pdev->dev;
diff --git a/drivers/usb/phy/phy-ulpi.c b/drivers/usb/phy/phy-ulpi.c
index e683a37e3a7a..4df63e67bb37 100644
--- a/drivers/usb/phy/phy-ulpi.c
+++ b/drivers/usb/phy/phy-ulpi.c
@@ -256,29 +256,6 @@ static void otg_ulpi_init(struct usb_phy *phy, struct usb_otg *otg,
}
struct usb_phy *
-otg_ulpi_create(struct usb_phy_io_ops *ops,
- unsigned int flags)
-{
- struct usb_phy *phy;
- struct usb_otg *otg;
-
- phy = kzalloc(sizeof(*phy), GFP_KERNEL);
- if (!phy)
- return NULL;
-
- otg = kzalloc(sizeof(*otg), GFP_KERNEL);
- if (!otg) {
- kfree(phy);
- return NULL;
- }
-
- otg_ulpi_init(phy, otg, ops, flags);
-
- return phy;
-}
-EXPORT_SYMBOL_GPL(otg_ulpi_create);
-
-struct usb_phy *
devm_otg_ulpi_create(struct device *dev,
struct usb_phy_io_ops *ops,
unsigned int flags)
diff --git a/drivers/usb/phy/phy.c b/drivers/usb/phy/phy.c
index e1435bc59662..5a9b9353f343 100644
--- a/drivers/usb/phy/phy.c
+++ b/drivers/usb/phy/phy.c
@@ -646,6 +646,8 @@ int usb_add_phy(struct usb_phy *x, enum usb_phy_type type)
return -EINVAL;
}
+ INIT_LIST_HEAD(&x->head);
+
usb_charger_init(x);
ret = usb_add_extcon(x);
if (ret)
@@ -696,6 +698,8 @@ int usb_add_phy_dev(struct usb_phy *x)
return -EINVAL;
}
+ INIT_LIST_HEAD(&x->head);
+
usb_charger_init(x);
ret = usb_add_extcon(x);
if (ret)