diff options
Diffstat (limited to 'drivers/usb/phy')
-rw-r--r-- | drivers/usb/phy/phy-ab8500-usb.c | 8 | ||||
-rw-r--r-- | drivers/usb/phy/phy-generic.c | 9 | ||||
-rw-r--r-- | drivers/usb/phy/phy-mxs-usb.c | 61 |
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); |