summaryrefslogtreecommitdiff
path: root/drivers/usb/phy
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/phy')
-rw-r--r--drivers/usb/phy/phy-ab8500-usb.c8
-rw-r--r--drivers/usb/phy/phy-generic.c9
-rw-r--r--drivers/usb/phy/phy-mxs-usb.c61
3 files changed, 69 insertions, 9 deletions
diff --git a/drivers/usb/phy/phy-ab8500-usb.c b/drivers/usb/phy/phy-ab8500-usb.c
index 0c912d3950a5..a03caf4b1327 100644
--- a/drivers/usb/phy/phy-ab8500-usb.c
+++ b/drivers/usb/phy/phy-ab8500-usb.c
@@ -1248,7 +1248,7 @@ static void ab8500_usb_set_ab8500_tuning_values(struct ab8500_usb *ab)
err = abx500_set_register_interruptible(ab->dev,
AB8500_DEBUG, AB8500_USB_PHY_TUNE3, 0x78);
if (err < 0)
- dev_err(ab->dev, "Failed to set PHY_TUNE3 regester err=%d\n",
+ dev_err(ab->dev, "Failed to set PHY_TUNE3 register err=%d\n",
err);
/* Switch to normal mode/disable Bank 0x12 access */
@@ -1290,7 +1290,7 @@ static void ab8500_usb_set_ab8505_tuning_values(struct ab8500_usb *ab)
0xFC, 0x80);
if (err < 0)
- dev_err(ab->dev, "Failed to set PHY_TUNE3 regester err=%d\n",
+ dev_err(ab->dev, "Failed to set PHY_TUNE3 register err=%d\n",
err);
/* Switch to normal mode/disable Bank 0x12 access */
@@ -1321,7 +1321,7 @@ static void ab8500_usb_set_ab8540_tuning_values(struct ab8500_usb *ab)
err = abx500_set_register_interruptible(ab->dev,
AB8540_DEBUG, AB8500_USB_PHY_TUNE3, 0x90);
if (err < 0)
- dev_err(ab->dev, "Failed to set PHY_TUNE3 regester ret=%d\n",
+ dev_err(ab->dev, "Failed to set PHY_TUNE3 register ret=%d\n",
err);
}
@@ -1351,7 +1351,7 @@ static void ab8500_usb_set_ab9540_tuning_values(struct ab8500_usb *ab)
err = abx500_set_register_interruptible(ab->dev,
AB8500_DEBUG, AB8500_USB_PHY_TUNE3, 0x80);
if (err < 0)
- dev_err(ab->dev, "Failed to set PHY_TUNE3 regester err=%d\n",
+ dev_err(ab->dev, "Failed to set PHY_TUNE3 register err=%d\n",
err);
/* Switch to normal mode/disable Bank 0x12 access */
diff --git a/drivers/usb/phy/phy-generic.c b/drivers/usb/phy/phy-generic.c
index 427efb5eebae..8311ba2968cd 100644
--- a/drivers/usb/phy/phy-generic.c
+++ b/drivers/usb/phy/phy-generic.c
@@ -118,8 +118,6 @@ static irqreturn_t nop_gpio_vbus_thread(int irq, void *data)
status = USB_EVENT_VBUS;
otg->state = OTG_STATE_B_PERIPHERAL;
nop->phy.last_event = status;
- if (otg->gadget)
- usb_gadget_vbus_connect(otg->gadget);
/* drawing a "unit load" is *always* OK, except for OTG */
nop_set_vbus_draw(nop, 100);
@@ -129,8 +127,6 @@ static irqreturn_t nop_gpio_vbus_thread(int irq, void *data)
} else {
nop_set_vbus_draw(nop, 0);
- if (otg->gadget)
- usb_gadget_vbus_disconnect(otg->gadget);
status = USB_EVENT_NONE;
otg->state = OTG_STATE_B_IDLE;
nop->phy.last_event = status;
@@ -191,7 +187,8 @@ static int nop_set_peripheral(struct usb_otg *otg, struct usb_gadget *gadget)
otg->gadget = gadget;
if (otg->state == OTG_STATE_B_PERIPHERAL)
- usb_gadget_vbus_connect(gadget);
+ atomic_notifier_call_chain(&otg->usb_phy->notifier,
+ USB_EVENT_VBUS, otg->gadget);
else
otg->state = OTG_STATE_B_IDLE;
return 0;
@@ -326,6 +323,8 @@ static int usb_phy_generic_probe(struct platform_device *pdev)
gpiod_to_irq(nop->gpiod_vbus), err);
return err;
}
+ nop->phy.otg->state = gpiod_get_value(nop->gpiod_vbus) ?
+ OTG_STATE_B_PERIPHERAL : OTG_STATE_B_IDLE;
}
nop->phy.init = usb_gen_phy_init;
diff --git a/drivers/usb/phy/phy-mxs-usb.c b/drivers/usb/phy/phy-mxs-usb.c
index 00bfea01be65..0e2f1a36d315 100644
--- a/drivers/usb/phy/phy-mxs-usb.c
+++ b/drivers/usb/phy/phy-mxs-usb.c
@@ -27,6 +27,7 @@
#define DRIVER_NAME "mxs_phy"
#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
@@ -38,6 +39,10 @@
#define HW_USBPHY_IP_SET 0x94
#define HW_USBPHY_IP_CLR 0x98
+#define GM_USBPHY_TX_TXCAL45DP(x) (((x) & 0xf) << 16)
+#define GM_USBPHY_TX_TXCAL45DN(x) (((x) & 0xf) << 8)
+#define GM_USBPHY_TX_D_CAL(x) (((x) & 0xf) << 0)
+
#define BM_USBPHY_CTRL_SFTRST BIT(31)
#define BM_USBPHY_CTRL_CLKGATE BIT(30)
#define BM_USBPHY_CTRL_OTG_ID_VALUE BIT(27)
@@ -115,6 +120,12 @@
*/
#define MXS_PHY_NEED_IP_FIX BIT(3)
+/* Minimum and maximum values for device tree entries */
+#define MXS_PHY_TX_CAL45_MIN 30
+#define MXS_PHY_TX_CAL45_MAX 55
+#define MXS_PHY_TX_D_CAL_MIN 79
+#define MXS_PHY_TX_D_CAL_MAX 119
+
struct mxs_phy_data {
unsigned int flags;
};
@@ -164,6 +175,8 @@ struct mxs_phy {
const struct mxs_phy_data *data;
struct regmap *regmap_anatop;
int port_id;
+ u32 tx_reg_set;
+ u32 tx_reg_mask;
};
static inline bool is_imx6q_phy(struct mxs_phy *mxs_phy)
@@ -185,6 +198,20 @@ static void mxs_phy_clock_switch_delay(void)
usleep_range(300, 400);
}
+static void mxs_phy_tx_init(struct mxs_phy *mxs_phy)
+{
+ void __iomem *base = mxs_phy->phy.io_priv;
+ u32 phytx;
+
+ /* Update TX register if there is anything to write */
+ if (mxs_phy->tx_reg_mask) {
+ phytx = readl(base + HW_USBPHY_TX);
+ phytx &= ~mxs_phy->tx_reg_mask;
+ phytx |= mxs_phy->tx_reg_set;
+ writel(phytx, base + HW_USBPHY_TX);
+ }
+}
+
static int mxs_phy_hw_init(struct mxs_phy *mxs_phy)
{
int ret;
@@ -214,6 +241,8 @@ static int mxs_phy_hw_init(struct mxs_phy *mxs_phy)
if (mxs_phy->data->flags & MXS_PHY_NEED_IP_FIX)
writel(BM_USBPHY_IP_FIX, base + HW_USBPHY_IP_SET);
+ mxs_phy_tx_init(mxs_phy);
+
return 0;
}
@@ -459,6 +488,7 @@ static int mxs_phy_probe(struct platform_device *pdev)
int ret;
const struct of_device_id *of_id;
struct device_node *np = pdev->dev.of_node;
+ u32 val;
of_id = of_match_device(mxs_phy_dt_ids, &pdev->dev);
if (!of_id)
@@ -491,6 +521,37 @@ static int mxs_phy_probe(struct platform_device *pdev)
}
}
+ /* Precompute which bits of the TX register are to be updated, if any */
+ if (!of_property_read_u32(np, "fsl,tx-cal-45-dn-ohms", &val) &&
+ val >= MXS_PHY_TX_CAL45_MIN && val <= MXS_PHY_TX_CAL45_MAX) {
+ /* Scale to a 4-bit value */
+ val = (MXS_PHY_TX_CAL45_MAX - val) * 0xF
+ / (MXS_PHY_TX_CAL45_MAX - MXS_PHY_TX_CAL45_MIN);
+ mxs_phy->tx_reg_mask |= GM_USBPHY_TX_TXCAL45DN(~0);
+ mxs_phy->tx_reg_set |= GM_USBPHY_TX_TXCAL45DN(val);
+ }
+
+ if (!of_property_read_u32(np, "fsl,tx-cal-45-dp-ohms", &val) &&
+ val >= MXS_PHY_TX_CAL45_MIN && val <= MXS_PHY_TX_CAL45_MAX) {
+ /* Scale to a 4-bit value. */
+ val = (MXS_PHY_TX_CAL45_MAX - val) * 0xF
+ / (MXS_PHY_TX_CAL45_MAX - MXS_PHY_TX_CAL45_MIN);
+ mxs_phy->tx_reg_mask |= GM_USBPHY_TX_TXCAL45DP(~0);
+ mxs_phy->tx_reg_set |= GM_USBPHY_TX_TXCAL45DP(val);
+ }
+
+ if (!of_property_read_u32(np, "fsl,tx-d-cal", &val) &&
+ val >= MXS_PHY_TX_D_CAL_MIN && val <= MXS_PHY_TX_D_CAL_MAX) {
+ /* Scale to a 4-bit value. Round up the values and heavily
+ * weight the rounding by adding 2/3 of the denominator.
+ */
+ val = ((MXS_PHY_TX_D_CAL_MAX - val) * 0xF
+ + (MXS_PHY_TX_D_CAL_MAX - MXS_PHY_TX_D_CAL_MIN) * 2/3)
+ / (MXS_PHY_TX_D_CAL_MAX - MXS_PHY_TX_D_CAL_MIN);
+ mxs_phy->tx_reg_mask |= GM_USBPHY_TX_D_CAL(~0);
+ mxs_phy->tx_reg_set |= GM_USBPHY_TX_D_CAL(val);
+ }
+
ret = of_alias_get_id(np, "usbphy");
if (ret < 0)
dev_dbg(&pdev->dev, "failed to get alias id, errno %d\n", ret);