diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2017-11-14 08:14:07 +0300 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2017-11-14 08:14:07 +0300 |
commit | 894025f24bd028942da3e602b87d9f7223109b14 (patch) | |
tree | 57f23d2bcdd59aaa6a3e7e26e175e678bfa9a5f4 /drivers/usb/host/max3421-hcd.c | |
parent | fb0255fb2941ef6f21742b2bc146d6b9aef4fedc (diff) | |
parent | cdafb6d8b8da7fde266f79b3287ac221aa841879 (diff) | |
download | linux-894025f24bd028942da3e602b87d9f7223109b14.tar.xz |
Merge tag 'usb-4.15-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb
Pull USB/PHY updates from Greg KH:
"Here is the big set of USB and PHY driver updates for 4.15-rc1.
There is the usual amount of gadget and xhci driver updates, along
with phy and chipidea enhancements. There's also a lot of SPDX tags
and license boilerplate cleanups as well, which provide some churn in
the diffstat.
Other major thing is the typec code that moved out of staging and into
the "real" part of the drivers/usb/ tree, which was nice to see
happen.
All of these have been in linux-next with no reported issues for a
while"
* tag 'usb-4.15-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb: (263 commits)
usb: gadget: f_fs: Fix use-after-free in ffs_free_inst
USB: usbfs: compute urb->actual_length for isochronous
usb: core: message: remember to reset 'ret' to 0 when necessary
USB: typec: Remove remaining redundant license text
USB: typec: add SPDX identifiers to some files
USB: renesas_usbhs: rcar?.h: add SPDX tags
USB: chipidea: ci_hdrc_tegra.c: add SPDX line
USB: host: xhci-debugfs: add SPDX lines
USB: add SPDX identifiers to all remaining Makefiles
usb: host: isp1362-hcd: remove a couple of redundant assignments
USB: adutux: remove redundant variable minor
usb: core: add a new usb_get_ptm_status() helper
usb: core: add a 'type' parameter to usb_get_status()
usb: core: introduce a new usb_get_std_status() helper
usb: core: rename usb_get_status() 'type' argument to 'recip'
usb: core: add Status Type definitions
USB: gadget: Remove redundant license text
USB: gadget: function: Remove redundant license text
USB: gadget: udc: Remove redundant license text
USB: gadget: legacy: Remove redundant license text
...
Diffstat (limited to 'drivers/usb/host/max3421-hcd.c')
-rw-r--r-- | drivers/usb/host/max3421-hcd.c | 81 |
1 files changed, 78 insertions, 3 deletions
diff --git a/drivers/usb/host/max3421-hcd.c b/drivers/usb/host/max3421-hcd.c index 0ece9a9341e5..afa321ab55fc 100644 --- a/drivers/usb/host/max3421-hcd.c +++ b/drivers/usb/host/max3421-hcd.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0 /* * MAX3421 Host Controller driver for USB. * @@ -60,6 +61,7 @@ #include <linux/spi/spi.h> #include <linux/usb.h> #include <linux/usb/hcd.h> +#include <linux/of.h> #include <linux/platform_data/max3421-hcd.h> @@ -85,6 +87,8 @@ USB_PORT_STAT_C_OVERCURRENT | \ USB_PORT_STAT_C_RESET) << 16) +#define MAX3421_GPOUT_COUNT 8 + enum max3421_rh_state { MAX3421_RH_RESET, MAX3421_RH_SUSPENDED, @@ -1672,7 +1676,7 @@ max3421_gpout_set_value(struct usb_hcd *hcd, u8 pin_number, u8 value) u8 mask, idx; --pin_number; - if (pin_number > 7) + if (pin_number >= MAX3421_GPOUT_COUNT) return; mask = 1u << (pin_number % 4); @@ -1696,10 +1700,10 @@ max3421_hub_control(struct usb_hcd *hcd, u16 type_req, u16 value, u16 index, unsigned long flags; int retval = 0; - spin_lock_irqsave(&max3421_hcd->lock, flags); - pdata = spi->dev.platform_data; + spin_lock_irqsave(&max3421_hcd->lock, flags); + switch (type_req) { case ClearHubFeature: break; @@ -1832,10 +1836,34 @@ static const struct hc_driver max3421_hcd_desc = { }; static int +max3421_of_vbus_en_pin(struct device *dev, struct max3421_hcd_platform_data *pdata) +{ + int retval; + uint32_t value[2]; + + if (!pdata) + return -EINVAL; + + retval = of_property_read_u32_array(dev->of_node, "maxim,vbus-en-pin", value, 2); + if (retval) { + dev_err(dev, "device tree node property 'maxim,vbus-en-pin' is missing\n"); + return retval; + } + dev_info(dev, "property 'maxim,vbus-en-pin' value is <%d %d>\n", value[0], value[1]); + + pdata->vbus_gpout = value[0]; + pdata->vbus_active_level = value[1]; + + return 0; +} + +static int max3421_probe(struct spi_device *spi) { + struct device *dev = &spi->dev; struct max3421_hcd *max3421_hcd; struct usb_hcd *hcd = NULL; + struct max3421_hcd_platform_data *pdata = NULL; int retval = -ENOMEM; if (spi_setup(spi) < 0) { @@ -1843,6 +1871,41 @@ max3421_probe(struct spi_device *spi) return -EFAULT; } + if (!spi->irq) { + dev_err(dev, "Failed to get SPI IRQ"); + return -EFAULT; + } + + if (IS_ENABLED(CONFIG_OF) && dev->of_node) { + pdata = devm_kzalloc(&spi->dev, sizeof(*pdata), GFP_KERNEL); + if (!pdata) { + retval = -ENOMEM; + goto error; + } + retval = max3421_of_vbus_en_pin(dev, pdata); + if (retval) + goto error; + + spi->dev.platform_data = pdata; + } + + pdata = spi->dev.platform_data; + if (!pdata) { + dev_err(&spi->dev, "driver configuration data is not provided\n"); + retval = -EFAULT; + goto error; + } + if (pdata->vbus_active_level > 1) { + dev_err(&spi->dev, "vbus active level value %d is out of range (0/1)\n", pdata->vbus_active_level); + retval = -EINVAL; + goto error; + } + if (pdata->vbus_gpout < 1 || pdata->vbus_gpout > MAX3421_GPOUT_COUNT) { + dev_err(&spi->dev, "vbus gpout value %d is out of range (1..8)\n", pdata->vbus_gpout); + retval = -EINVAL; + goto error; + } + hcd = usb_create_hcd(&max3421_hcd_desc, &spi->dev, dev_name(&spi->dev)); if (!hcd) { @@ -1885,6 +1948,11 @@ max3421_probe(struct spi_device *spi) return 0; error: + if (IS_ENABLED(CONFIG_OF) && dev->of_node && pdata) { + devm_kfree(&spi->dev, pdata); + spi->dev.platform_data = NULL; + } + if (hcd) { kfree(max3421_hcd->tx); kfree(max3421_hcd->rx); @@ -1929,11 +1997,18 @@ max3421_remove(struct spi_device *spi) return 0; } +static const struct of_device_id max3421_of_match_table[] = { + { .compatible = "maxim,max3421", }, + {}, +}; +MODULE_DEVICE_TABLE(of, max3421_of_match_table); + static struct spi_driver max3421_driver = { .probe = max3421_probe, .remove = max3421_remove, .driver = { .name = "max3421-hcd", + .of_match_table = of_match_ptr(max3421_of_match_table), }, }; |