diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2020-12-15 22:54:56 +0100 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2020-12-15 22:54:56 +0100 |
commit | 0cee54c890a40051928991072e5d1cd279611dfd (patch) | |
tree | e4e24223c697b8935a1b24b906f60831d1dc7c71 /drivers/usb/misc | |
parent | Merge tag 'sound-5.11-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/t... (diff) | |
parent | usb: phy: convert comma to semicolon (diff) | |
download | linux-0cee54c890a40051928991072e5d1cd279611dfd.tar.xz linux-0cee54c890a40051928991072e5d1cd279611dfd.zip |
Merge tag 'usb-5.11-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb
Pull USB / Thunderbolt updates from Greg KH:
"Here is the big USB and thunderbolt pull request for 5.11-rc1.
Nothing major in here, just the grind of constant development to
support new hardware and fix old issues:
- thunderbolt updates for new USB4 hardware
- cdns3 major driver updates
- lots of typec updates and additions as more hardware is available
- usb serial driver updates and fixes
- other tiny USB driver updates
All have been in linux-next with no reported issues"
* tag 'usb-5.11-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb: (172 commits)
usb: phy: convert comma to semicolon
usb: ucsi: convert comma to semicolon
usb: typec: tcpm: convert comma to semicolon
usb: typec: tcpm: Update vbus_vsafe0v on init
usb: typec: tcpci: Enable bleed discharge when auto discharge is enabled
usb: typec: Add class for plug alt mode device
USB: typec: tcpci: Add Bleed discharge to POWER_CONTROL definition
USB: typec: tcpm: Add a 30ms room for tPSSourceOn in PR_SWAP
USB: typec: tcpm: Fix PR_SWAP error handling
USB: typec: tcpm: Hard Reset after not receiving a Request
USB: gadget: f_fs: remove likely/unlikely
usb: gadget: f_fs: Re-use SS descriptors for SuperSpeedPlus
USB: gadget: f_midi: setup SuperSpeed Plus descriptors
USB: gadget: f_acm: add support for SuperSpeed Plus
USB: gadget: f_rndis: fix bitrate for SuperSpeed and above
usb: typec: intel_pmc_mux: Configure cable generation value for USB4
MAINTAINERS: Add myself as a reviewer for CADENCE USB3 DRD IP DRIVER
usb: chipidea: ci_hdrc_imx: Use of_device_get_match_data()
usb: chipidea: usbmisc_imx: Use of_device_get_match_data()
usb: cdns3: fix NULL pointer dereference on no platform data
...
Diffstat (limited to 'drivers/usb/misc')
-rw-r--r-- | drivers/usb/misc/Kconfig | 9 | ||||
-rw-r--r-- | drivers/usb/misc/Makefile | 1 | ||||
-rw-r--r-- | drivers/usb/misc/apple-mfi-fastcharge.c | 13 | ||||
-rw-r--r-- | drivers/usb/misc/brcmstb-usb-pinmap.c | 351 | ||||
-rw-r--r-- | drivers/usb/misc/iowarrior.c | 3 | ||||
-rw-r--r-- | drivers/usb/misc/legousbtower.c | 2 | ||||
-rw-r--r-- | drivers/usb/misc/sisusbvga/Kconfig | 2 | ||||
-rw-r--r-- | drivers/usb/misc/yurex.c | 1 |
8 files changed, 368 insertions, 14 deletions
diff --git a/drivers/usb/misc/Kconfig b/drivers/usb/misc/Kconfig index 6818ea689cd9..8f1144359012 100644 --- a/drivers/usb/misc/Kconfig +++ b/drivers/usb/misc/Kconfig @@ -275,3 +275,12 @@ config USB_CHAOSKEY To compile this driver as a module, choose M here: the module will be called chaoskey. + +config BRCM_USB_PINMAP + tristate "Broadcom pinmap driver support" + depends on (ARCH_BRCMSTB && PHY_BRCM_USB) || COMPILE_TEST + default ARCH_BRCMSTB && PHY_BRCM_USB + help + This option enables support for remapping some USB external + signals, which are typically on dedicated pins on the chip, + to any gpio. diff --git a/drivers/usb/misc/Makefile b/drivers/usb/misc/Makefile index da39bddb0604..5f4e598573ab 100644 --- a/drivers/usb/misc/Makefile +++ b/drivers/usb/misc/Makefile @@ -31,3 +31,4 @@ obj-$(CONFIG_USB_CHAOSKEY) += chaoskey.o obj-$(CONFIG_USB_SISUSBVGA) += sisusbvga/ obj-$(CONFIG_USB_LINK_LAYER_TEST) += lvstest.o +obj-$(CONFIG_BRCM_USB_PINMAP) += brcmstb-usb-pinmap.o diff --git a/drivers/usb/misc/apple-mfi-fastcharge.c b/drivers/usb/misc/apple-mfi-fastcharge.c index 9de0171b5177..ac8695195c13 100644 --- a/drivers/usb/misc/apple-mfi-fastcharge.c +++ b/drivers/usb/misc/apple-mfi-fastcharge.c @@ -184,10 +184,8 @@ static int mfi_fc_probe(struct usb_device *udev) return -ENODEV; mfi = kzalloc(sizeof(struct mfi_device), GFP_KERNEL); - if (!mfi) { - err = -ENOMEM; - goto error; - } + if (!mfi) + return -ENOMEM; battery_cfg.drv_data = mfi; @@ -198,17 +196,14 @@ static int mfi_fc_probe(struct usb_device *udev) if (IS_ERR(mfi->battery)) { dev_err(&udev->dev, "Can't register battery\n"); err = PTR_ERR(mfi->battery); - goto error; + kfree(mfi); + return err; } mfi->udev = usb_get_dev(udev); dev_set_drvdata(&udev->dev, mfi); return 0; - -error: - kfree(mfi); - return err; } static void mfi_fc_disconnect(struct usb_device *udev) diff --git a/drivers/usb/misc/brcmstb-usb-pinmap.c b/drivers/usb/misc/brcmstb-usb-pinmap.c new file mode 100644 index 000000000000..b3cfe8666ea7 --- /dev/null +++ b/drivers/usb/misc/brcmstb-usb-pinmap.c @@ -0,0 +1,351 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright (c) 2020, Broadcom */ + +#include <linux/init.h> +#include <linux/types.h> +#include <linux/module.h> +#include <linux/platform_device.h> +#include <linux/interrupt.h> +#include <linux/io.h> +#include <linux/device.h> +#include <linux/of.h> +#include <linux/kernel.h> +#include <linux/kdebug.h> +#include <linux/gpio/consumer.h> + +struct out_pin { + u32 enable_mask; + u32 value_mask; + u32 changed_mask; + u32 clr_changed_mask; + struct gpio_desc *gpiod; + const char *name; +}; + +struct in_pin { + u32 enable_mask; + u32 value_mask; + struct gpio_desc *gpiod; + const char *name; + struct brcmstb_usb_pinmap_data *pdata; +}; + +struct brcmstb_usb_pinmap_data { + void __iomem *regs; + int in_count; + struct in_pin *in_pins; + int out_count; + struct out_pin *out_pins; +}; + + +static void pinmap_set(void __iomem *reg, u32 mask) +{ + u32 val; + + val = readl(reg); + val |= mask; + writel(val, reg); +} + +static void pinmap_unset(void __iomem *reg, u32 mask) +{ + u32 val; + + val = readl(reg); + val &= ~mask; + writel(val, reg); +} + +static void sync_in_pin(struct in_pin *pin) +{ + u32 val; + + val = gpiod_get_value(pin->gpiod); + if (val) + pinmap_set(pin->pdata->regs, pin->value_mask); + else + pinmap_unset(pin->pdata->regs, pin->value_mask); +} + +/* + * Interrupt from override register, propagate from override bit + * to GPIO. + */ +static irqreturn_t brcmstb_usb_pinmap_ovr_isr(int irq, void *dev_id) +{ + struct brcmstb_usb_pinmap_data *pdata = dev_id; + struct out_pin *pout; + u32 val; + u32 bit; + int x; + + pr_debug("%s: reg: 0x%x\n", __func__, readl(pdata->regs)); + pout = pdata->out_pins; + for (x = 0; x < pdata->out_count; x++) { + val = readl(pdata->regs); + if (val & pout->changed_mask) { + pinmap_set(pdata->regs, pout->clr_changed_mask); + pinmap_unset(pdata->regs, pout->clr_changed_mask); + bit = val & pout->value_mask; + gpiod_set_value(pout->gpiod, bit ? 1 : 0); + pr_debug("%s: %s bit changed state to %d\n", + __func__, pout->name, bit ? 1 : 0); + } + } + return IRQ_HANDLED; +} + +/* + * Interrupt from GPIO, propagate from GPIO to override bit. + */ +static irqreturn_t brcmstb_usb_pinmap_gpio_isr(int irq, void *dev_id) +{ + struct in_pin *pin = dev_id; + + pr_debug("%s: %s pin changed state\n", __func__, pin->name); + sync_in_pin(pin); + return IRQ_HANDLED; +} + + +static void get_pin_counts(struct device_node *dn, int *in_count, + int *out_count) +{ + int in; + int out; + + *in_count = 0; + *out_count = 0; + in = of_property_count_strings(dn, "brcm,in-functions"); + if (in < 0) + return; + out = of_property_count_strings(dn, "brcm,out-functions"); + if (out < 0) + return; + *in_count = in; + *out_count = out; +} + +static int parse_pins(struct device *dev, struct device_node *dn, + struct brcmstb_usb_pinmap_data *pdata) +{ + struct out_pin *pout; + struct in_pin *pin; + int index; + int res; + int x; + + pin = pdata->in_pins; + for (x = 0, index = 0; x < pdata->in_count; x++) { + pin->gpiod = devm_gpiod_get_index(dev, "in", x, GPIOD_IN); + if (IS_ERR(pin->gpiod)) { + dev_err(dev, "Error getting gpio %s\n", pin->name); + return PTR_ERR(pin->gpiod); + + } + res = of_property_read_string_index(dn, "brcm,in-functions", x, + &pin->name); + if (res < 0) { + dev_err(dev, "Error getting brcm,in-functions for %s\n", + pin->name); + return res; + } + res = of_property_read_u32_index(dn, "brcm,in-masks", index++, + &pin->enable_mask); + if (res < 0) { + dev_err(dev, "Error getting 1st brcm,in-masks for %s\n", + pin->name); + return res; + } + res = of_property_read_u32_index(dn, "brcm,in-masks", index++, + &pin->value_mask); + if (res < 0) { + dev_err(dev, "Error getting 2nd brcm,in-masks for %s\n", + pin->name); + return res; + } + pin->pdata = pdata; + pin++; + } + pout = pdata->out_pins; + for (x = 0, index = 0; x < pdata->out_count; x++) { + pout->gpiod = devm_gpiod_get_index(dev, "out", x, + GPIOD_OUT_HIGH); + if (IS_ERR(pout->gpiod)) { + dev_err(dev, "Error getting gpio %s\n", pin->name); + return PTR_ERR(pout->gpiod); + } + res = of_property_read_string_index(dn, "brcm,out-functions", x, + &pout->name); + if (res < 0) { + dev_err(dev, "Error getting brcm,out-functions for %s\n", + pout->name); + return res; + } + res = of_property_read_u32_index(dn, "brcm,out-masks", index++, + &pout->enable_mask); + if (res < 0) { + dev_err(dev, "Error getting 1st brcm,out-masks for %s\n", + pout->name); + return res; + } + res = of_property_read_u32_index(dn, "brcm,out-masks", index++, + &pout->value_mask); + if (res < 0) { + dev_err(dev, "Error getting 2nd brcm,out-masks for %s\n", + pout->name); + return res; + } + res = of_property_read_u32_index(dn, "brcm,out-masks", index++, + &pout->changed_mask); + if (res < 0) { + dev_err(dev, "Error getting 3rd brcm,out-masks for %s\n", + pout->name); + return res; + } + res = of_property_read_u32_index(dn, "brcm,out-masks", index++, + &pout->clr_changed_mask); + if (res < 0) { + dev_err(dev, "Error getting 4th out-masks for %s\n", + pout->name); + return res; + } + pout++; + } + return 0; +} + +static void sync_all_pins(struct brcmstb_usb_pinmap_data *pdata) +{ + struct out_pin *pout; + struct in_pin *pin; + int val; + int x; + + /* + * Enable the override, clear any changed condition and + * propagate the state to the GPIO for all out pins. + */ + pout = pdata->out_pins; + for (x = 0; x < pdata->out_count; x++) { + pinmap_set(pdata->regs, pout->enable_mask); + pinmap_set(pdata->regs, pout->clr_changed_mask); + pinmap_unset(pdata->regs, pout->clr_changed_mask); + val = readl(pdata->regs) & pout->value_mask; + gpiod_set_value(pout->gpiod, val ? 1 : 0); + pout++; + } + + /* sync and enable all in pins. */ + pin = pdata->in_pins; + for (x = 0; x < pdata->in_count; x++) { + sync_in_pin(pin); + pinmap_set(pdata->regs, pin->enable_mask); + pin++; + } +} + +static int __init brcmstb_usb_pinmap_probe(struct platform_device *pdev) +{ + struct device_node *dn = pdev->dev.of_node; + struct brcmstb_usb_pinmap_data *pdata; + struct in_pin *pin; + struct resource *r; + int out_count; + int in_count; + int err; + int irq; + int x; + + get_pin_counts(dn, &in_count, &out_count); + if ((in_count + out_count) == 0) + return -EINVAL; + + r = platform_get_resource(pdev, IORESOURCE_MEM, 0); + + pdata = devm_kzalloc(&pdev->dev, + sizeof(*pdata) + + (sizeof(struct in_pin) * in_count) + + (sizeof(struct out_pin) * out_count), GFP_KERNEL); + if (!pdata) + return -ENOMEM; + + pdata->in_count = in_count; + pdata->out_count = out_count; + pdata->in_pins = (struct in_pin *)(pdata + 1); + pdata->out_pins = (struct out_pin *)(pdata->in_pins + in_count); + + pdata->regs = devm_ioremap(&pdev->dev, r->start, resource_size(r)); + if (!pdata->regs) + return -ENOMEM; + platform_set_drvdata(pdev, pdata); + + err = parse_pins(&pdev->dev, dn, pdata); + if (err) + return err; + + sync_all_pins(pdata); + + if (out_count) { + + /* Enable interrupt for out pins */ + irq = platform_get_irq(pdev, 0); + err = devm_request_irq(&pdev->dev, irq, + brcmstb_usb_pinmap_ovr_isr, + IRQF_TRIGGER_RISING, + pdev->name, pdata); + if (err < 0) { + dev_err(&pdev->dev, "Error requesting IRQ\n"); + return err; + } + } + + for (x = 0, pin = pdata->in_pins; x < pdata->in_count; x++, pin++) { + irq = gpiod_to_irq(pin->gpiod); + if (irq < 0) { + dev_err(&pdev->dev, "Error getting IRQ for %s pin\n", + pin->name); + return irq; + } + err = devm_request_irq(&pdev->dev, irq, + brcmstb_usb_pinmap_gpio_isr, + IRQF_SHARED | IRQF_TRIGGER_RISING | + IRQF_TRIGGER_FALLING, + pdev->name, pin); + if (err < 0) { + dev_err(&pdev->dev, "Error requesting IRQ for %s pin\n", + pin->name); + return err; + } + } + + dev_dbg(&pdev->dev, "Driver probe succeeded\n"); + dev_dbg(&pdev->dev, "In pin count: %d, out pin count: %d\n", + pdata->in_count, pdata->out_count); + return 0; +} + + +static const struct of_device_id brcmstb_usb_pinmap_of_match[] = { + { .compatible = "brcm,usb-pinmap" }, + { }, +}; + +static struct platform_driver brcmstb_usb_pinmap_driver = { + .driver = { + .name = "brcm-usb-pinmap", + .of_match_table = brcmstb_usb_pinmap_of_match, + }, +}; + +static int __init brcmstb_usb_pinmap_init(void) +{ + return platform_driver_probe(&brcmstb_usb_pinmap_driver, + brcmstb_usb_pinmap_probe); +} + +module_init(brcmstb_usb_pinmap_init); +MODULE_AUTHOR("Al Cooper <alcooperx@gmail.com>"); +MODULE_DESCRIPTION("Broadcom USB Pinmap Driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/usb/misc/iowarrior.c b/drivers/usb/misc/iowarrior.c index 70ec29681526..efbd317f2f25 100644 --- a/drivers/usb/misc/iowarrior.c +++ b/drivers/usb/misc/iowarrior.c @@ -384,7 +384,6 @@ static ssize_t iowarrior_write(struct file *file, retval = usb_set_report(dev->interface, 2, 0, buf, count); kfree(buf); goto exit; - break; case USB_DEVICE_ID_CODEMERCS_IOW56: case USB_DEVICE_ID_CODEMERCS_IOW56AM: case USB_DEVICE_ID_CODEMERCS_IOW28: @@ -454,14 +453,12 @@ static ssize_t iowarrior_write(struct file *file, retval = count; usb_free_urb(int_out_urb); goto exit; - break; default: /* what do we have here ? An unsupported Product-ID ? */ dev_err(&dev->interface->dev, "%s - not supported for product=0x%x\n", __func__, dev->product_id); retval = -EFAULT; goto exit; - break; } error: usb_free_coherent(dev->udev, dev->report_size, buf, diff --git a/drivers/usb/misc/legousbtower.c b/drivers/usb/misc/legousbtower.c index ba655b4af4fc..1c9e09138c10 100644 --- a/drivers/usb/misc/legousbtower.c +++ b/drivers/usb/misc/legousbtower.c @@ -797,7 +797,7 @@ static int tower_probe(struct usb_interface *interface, const struct usb_device_ &get_version_reply, sizeof(get_version_reply), 1000, GFP_KERNEL); - if (!result) { + if (result) { dev_err(idev, "get version request failed: %d\n", result); retval = result; goto error; diff --git a/drivers/usb/misc/sisusbvga/Kconfig b/drivers/usb/misc/sisusbvga/Kconfig index 655d9cb0651a..c12cdd015410 100644 --- a/drivers/usb/misc/sisusbvga/Kconfig +++ b/drivers/usb/misc/sisusbvga/Kconfig @@ -16,7 +16,7 @@ config USB_SISUSBVGA config USB_SISUSBVGA_CON bool "Text console and mode switching support" if USB_SISUSBVGA - depends on VT + depends on VT && BROKEN select FONT_8x16 help Say Y here if you want a VGA text console via the USB dongle or diff --git a/drivers/usb/misc/yurex.c b/drivers/usb/misc/yurex.c index e3165d79b5f6..73ebfa6e9715 100644 --- a/drivers/usb/misc/yurex.c +++ b/drivers/usb/misc/yurex.c @@ -137,6 +137,7 @@ static void yurex_interrupt(struct urb *urb) dev_err(&dev->interface->dev, "%s - overflow with length %d, actual length is %d\n", __func__, YUREX_BUF_SIZE, dev->urb->actual_length); + return; case -ECONNRESET: case -ENOENT: case -ESHUTDOWN: |