This update for DaVinci SoC support simplifies the VBUS enable

and overcurrent handling code in DA8XX OHCI driver by modeling
 vbus GPIO as a regulator. This unifies code for all users, device
 tree and non-device-tree.
 
 The OHCI driver patches have been acked by its maintainer.
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1
 
 iQIcBAABAgAGBQJctKWDAAoJEGFBu2jqvgRN7rsP/iIM7h+mmny5r3pcEj/ALiLL
 iLo2FBgLokRYZnLSg+Ar7Rx3tNxWxwTB/N6yy1bS05Ozpbw0YD4sFoZ1h1CEa7eH
 Ez5WU2E+rcR4EtA06LDe/e0Dzhzjy9OAbV9cUsvUgWpjwlRPPKQ9Z5/yWUx4RRmc
 GsFNjYvUvxYTrydr11vnMdz/MKwXq/TRTRoGSRTgP5fUzlQSWW0sj/IEtP/54ANN
 iqH2RQlPRFzGhjpnpxym0yv1owIO81WzoxW0jat1JfnJE/KnfepSSyuBRXhW2s1d
 owWuh/0T8dSvkayGAQiPpZlfH8QjM84RJwLEDfNbnftvOx3whbP9SnwON3USmE/7
 qraIbbkEizF5tlMcd1gDHBdssuYEREm0Ea337L6pFIFv89Mos1C0BsReJCnqIwXs
 yREGYkaStNkb/QIa1VZv6EqhHlop6l03Gm7afXAt6Q887ER9GjurmcndPy58hfId
 B3F+ipzDxVMttdH5zZaL2PVcztNDRsHzRQEatd7jgn/hKHluLHsA/LHUEndXhjyZ
 uZkHomgEUwSNrrl4z3oPN536PaWHoKlJLkY33RZLeljDo9wC90pWY67DVGAHQywV
 c2Mkdqdo1WGWsNGFYncsW2M27h7y5g0N/T/DDlT3cm1J0qR2wRVH9UjnMRInPesO
 P9vjCf0LidxgJcIjLeTY
 =JFVt
 -----END PGP SIGNATURE-----

Merge tag 'davinci-for-v5.2/soc' of git://git.kernel.org/pub/scm/linux/kernel/git/nsekhar/linux-davinci into arm/soc

This update for DaVinci SoC support simplifies the VBUS enable
and overcurrent handling code in DA8XX OHCI driver by modeling
vbus GPIO as a regulator. This unifies code for all users, device
tree and non-device-tree.

The OHCI driver patches have been acked by its maintainer.

* tag 'davinci-for-v5.2/soc' of git://git.kernel.org/pub/scm/linux/kernel/git/nsekhar/linux-davinci:
  usb: ohci-da8xx: drop the vbus GPIO
  ARM: davinci: da830-evm: add a fixed regulator for ohci-da8xx
  ARM: davinci: omapl138-hawk: add a fixed regulator for ohci-da8xx
  usb: ohci-da8xx: disable the regulator if the overcurrent irq fired
  usb: ohci-da8xx: let the regulator framework keep track of use count
  ARM: davinci: add missing sentinels to GPIO lookup tables

Signed-off-by: Olof Johansson <olof@lixom.net>
This commit is contained in:
Olof Johansson 2019-04-28 23:07:37 -07:00
commit 56e49cd668
6 changed files with 112 additions and 34 deletions

View File

@ -29,6 +29,7 @@
#include <linux/platform_data/spi-davinci.h>
#include <linux/platform_data/usb-davinci.h>
#include <linux/platform_data/ti-aemif.h>
#include <linux/regulator/fixed.h>
#include <linux/regulator/machine.h>
#include <linux/nvmem-provider.h>
@ -53,14 +54,50 @@ static const short da830_evm_usb11_pins[] = {
-1
};
static struct gpiod_lookup_table da830_evm_usb_gpio_lookup = {
static struct regulator_consumer_supply da830_evm_usb_supplies[] = {
REGULATOR_SUPPLY("vbus", NULL),
};
static struct regulator_init_data da830_evm_usb_vbus_data = {
.consumer_supplies = da830_evm_usb_supplies,
.num_consumer_supplies = ARRAY_SIZE(da830_evm_usb_supplies),
};
static struct fixed_voltage_config da830_evm_usb_vbus = {
.supply_name = "vbus",
.microvolts = 33000000,
.init_data = &da830_evm_usb_vbus_data,
};
static struct platform_device da830_evm_usb_vbus_device = {
.name = "reg-fixed-voltage",
.id = 0,
.dev = {
.platform_data = &da830_evm_usb_vbus,
},
};
static struct gpiod_lookup_table da830_evm_usb_oc_gpio_lookup = {
.dev_id = "ohci-da8xx",
.table = {
GPIO_LOOKUP("davinci_gpio", ON_BD_USB_DRV, "vbus", 0),
GPIO_LOOKUP("davinci_gpio", ON_BD_USB_OVC, "oc", 0),
{ }
},
};
static struct gpiod_lookup_table da830_evm_usb_vbus_gpio_lookup = {
.dev_id = "reg-fixed-voltage.0",
.table = {
GPIO_LOOKUP("davinci_gpio", ON_BD_USB_DRV, "vbus", 0),
{ }
},
};
static struct gpiod_lookup_table *da830_evm_usb_gpio_lookups[] = {
&da830_evm_usb_oc_gpio_lookup,
&da830_evm_usb_vbus_gpio_lookup,
};
static struct da8xx_ohci_root_hub da830_evm_usb11_pdata = {
/* TPS2065 switch @ 5V */
.potpgt = (3 + 1) / 2, /* 3 ms max */
@ -75,6 +112,9 @@ static __init void da830_evm_usb_init(void)
pr_warn("%s: USB PHY CLK registration failed: %d\n",
__func__, ret);
gpiod_add_lookup_tables(da830_evm_usb_gpio_lookups,
ARRAY_SIZE(da830_evm_usb_gpio_lookups));
ret = da8xx_register_usb_phy();
if (ret)
pr_warn("%s: USB PHY registration failed: %d\n",
@ -100,7 +140,11 @@ static __init void da830_evm_usb_init(void)
return;
}
gpiod_add_lookup_table(&da830_evm_usb_gpio_lookup);
ret = platform_device_register(&da830_evm_usb_vbus_device);
if (ret) {
pr_warn("%s: Unable to register the vbus supply\n", __func__);
return;
}
ret = da8xx_register_usb11(&da830_evm_usb11_pdata);
if (ret)
@ -156,6 +200,7 @@ static struct gpiod_lookup_table mmc_gpios_table = {
GPIO_ACTIVE_LOW),
GPIO_LOOKUP("davinci_gpio", DA830_MMCSD_WP_PIN, "wp",
GPIO_ACTIVE_LOW),
{ }
},
};

View File

@ -784,6 +784,7 @@ static struct gpiod_lookup_table mmc_gpios_table = {
GPIO_ACTIVE_LOW),
GPIO_LOOKUP("davinci_gpio", DA850_MMCSD_WP_PIN, "wp",
GPIO_ACTIVE_HIGH),
{ }
},
};

View File

@ -121,6 +121,7 @@ static struct gpiod_lookup_table i2c_recovery_gpiod_table = {
GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN),
GPIO_LOOKUP("davinci_gpio", DM355_I2C_SCL_PIN, "scl",
GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN),
{ }
},
};

View File

@ -663,6 +663,7 @@ static struct gpiod_lookup_table i2c_recovery_gpiod_table = {
GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN),
GPIO_LOOKUP("davinci_gpio", DM644X_I2C_SCL_PIN, "scl",
GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN),
{ }
},
};

View File

@ -21,6 +21,7 @@
#include <linux/platform_data/mtd-davinci.h>
#include <linux/platform_data/mtd-davinci-aemif.h>
#include <linux/platform_data/ti-aemif.h>
#include <linux/regulator/fixed.h>
#include <linux/regulator/machine.h>
#include <asm/mach-types.h>
@ -298,14 +299,50 @@ static const short da850_hawk_usb11_pins[] = {
-1
};
static struct gpiod_lookup_table hawk_usb_gpio_lookup = {
static struct regulator_consumer_supply hawk_usb_supplies[] = {
REGULATOR_SUPPLY("vbus", NULL),
};
static struct regulator_init_data hawk_usb_vbus_data = {
.consumer_supplies = hawk_usb_supplies,
.num_consumer_supplies = ARRAY_SIZE(hawk_usb_supplies),
};
static struct fixed_voltage_config hawk_usb_vbus = {
.supply_name = "vbus",
.microvolts = 3300000,
.init_data = &hawk_usb_vbus_data,
};
static struct platform_device hawk_usb_vbus_device = {
.name = "reg-fixed-voltage",
.id = 0,
.dev = {
.platform_data = &hawk_usb_vbus,
},
};
static struct gpiod_lookup_table hawk_usb_oc_gpio_lookup = {
.dev_id = "ohci-da8xx",
.table = {
GPIO_LOOKUP("davinci_gpio", DA850_USB1_VBUS_PIN, "vbus", 0),
GPIO_LOOKUP("davinci_gpio", DA850_USB1_OC_PIN, "oc", 0),
{ }
},
};
static struct gpiod_lookup_table hawk_usb_vbus_gpio_lookup = {
.dev_id = "reg-fixed-voltage.0",
.table = {
GPIO_LOOKUP("davinci_gpio", DA850_USB1_VBUS_PIN, NULL, 0),
{ }
},
};
static struct gpiod_lookup_table *hawk_usb_gpio_lookups[] = {
&hawk_usb_oc_gpio_lookup,
&hawk_usb_vbus_gpio_lookup,
};
static struct da8xx_ohci_root_hub omapl138_hawk_usb11_pdata = {
/* TPS2087 switch @ 5V */
.potpgt = (3 + 1) / 2, /* 3 ms max */
@ -326,12 +363,19 @@ static __init void omapl138_hawk_usb_init(void)
pr_warn("%s: USB PHY CLK registration failed: %d\n",
__func__, ret);
gpiod_add_lookup_tables(hawk_usb_gpio_lookups,
ARRAY_SIZE(hawk_usb_gpio_lookups));
ret = da8xx_register_usb_phy();
if (ret)
pr_warn("%s: USB PHY registration failed: %d\n",
__func__, ret);
gpiod_add_lookup_table(&hawk_usb_gpio_lookup);
ret = platform_device_register(&hawk_usb_vbus_device);
if (ret) {
pr_warn("%s: Unable to register the vbus supply\n", __func__);
return;
}
ret = da8xx_register_usb11(&omapl138_hawk_usb11_pdata);
if (ret)

View File

@ -40,8 +40,6 @@ struct da8xx_ohci_hcd {
struct phy *usb11_phy;
struct regulator *vbus_reg;
struct notifier_block nb;
unsigned int reg_enabled;
struct gpio_desc *vbus_gpio;
struct gpio_desc *oc_gpio;
};
@ -92,29 +90,21 @@ static int ohci_da8xx_set_power(struct usb_hcd *hcd, int on)
struct device *dev = hcd->self.controller;
int ret;
if (da8xx_ohci->vbus_gpio) {
gpiod_set_value_cansleep(da8xx_ohci->vbus_gpio, on);
return 0;
}
if (!da8xx_ohci->vbus_reg)
return 0;
if (on && !da8xx_ohci->reg_enabled) {
if (on) {
ret = regulator_enable(da8xx_ohci->vbus_reg);
if (ret) {
dev_err(dev, "Failed to enable regulator: %d\n", ret);
return ret;
}
da8xx_ohci->reg_enabled = 1;
} else if (!on && da8xx_ohci->reg_enabled) {
} else {
ret = regulator_disable(da8xx_ohci->vbus_reg);
if (ret) {
dev_err(dev, "Failed to disable regulator: %d\n", ret);
return ret;
}
da8xx_ohci->reg_enabled = 0;
}
return 0;
@ -124,9 +114,6 @@ static int ohci_da8xx_get_power(struct usb_hcd *hcd)
{
struct da8xx_ohci_hcd *da8xx_ohci = to_da8xx_ohci(hcd);
if (da8xx_ohci->vbus_gpio)
return gpiod_get_value_cansleep(da8xx_ohci->vbus_gpio);
if (da8xx_ohci->vbus_reg)
return regulator_is_enabled(da8xx_ohci->vbus_reg);
@ -159,9 +146,6 @@ static int ohci_da8xx_has_set_power(struct usb_hcd *hcd)
{
struct da8xx_ohci_hcd *da8xx_ohci = to_da8xx_ohci(hcd);
if (da8xx_ohci->vbus_gpio)
return 1;
if (da8xx_ohci->vbus_reg)
return 1;
@ -206,12 +190,18 @@ static int ohci_da8xx_regulator_event(struct notifier_block *nb,
return 0;
}
static irqreturn_t ohci_da8xx_oc_handler(int irq, void *data)
static irqreturn_t ohci_da8xx_oc_thread(int irq, void *data)
{
struct da8xx_ohci_hcd *da8xx_ohci = data;
struct device *dev = da8xx_ohci->hcd->self.controller;
int ret;
if (gpiod_get_value(da8xx_ohci->oc_gpio))
gpiod_set_value(da8xx_ohci->vbus_gpio, 0);
if (gpiod_get_value_cansleep(da8xx_ohci->oc_gpio) &&
da8xx_ohci->vbus_reg) {
ret = regulator_disable(da8xx_ohci->vbus_reg);
if (ret)
dev_err(dev, "Failed to disable regulator: %d\n", ret);
}
return IRQ_HANDLED;
}
@ -424,11 +414,6 @@ static int ohci_da8xx_probe(struct platform_device *pdev)
}
}
da8xx_ohci->vbus_gpio = devm_gpiod_get_optional(dev, "vbus",
GPIOD_OUT_HIGH);
if (IS_ERR(da8xx_ohci->vbus_gpio))
goto err;
da8xx_ohci->oc_gpio = devm_gpiod_get_optional(dev, "oc", GPIOD_IN);
if (IS_ERR(da8xx_ohci->oc_gpio))
goto err;
@ -438,8 +423,9 @@ static int ohci_da8xx_probe(struct platform_device *pdev)
if (oc_irq < 0)
goto err;
error = devm_request_irq(dev, oc_irq, ohci_da8xx_oc_handler,
IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
error = devm_request_threaded_irq(dev, oc_irq, NULL,
ohci_da8xx_oc_thread, IRQF_TRIGGER_RISING |
IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
"OHCI over-current indicator", da8xx_ohci);
if (error)
goto err;