Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

usb: gadget: pch_udc: Convert to use GPIO descriptors

This switches the PCH UDC driver to use GPIO descriptors. The way
this is supposed to be used is confusing. The code contains the
following:

/* GPIO port for VBUS detecting */
static int vbus_gpio_port = -1; /* GPIO port number (-1:Not used) */

So a hardcoded GPIO number in the code. Further the probe() path
very clearly will exit if the GPIO is not found, so this driver
can only be configured by editing the code, hard-coding a GPIO
number into this variable.

This is simply not how we do things. My guess is that this is
used in products by patching a GPIO number into this variable and
shipping a kernel that is compile-time tailored for the target
system.

I switched this mechanism to using a GPIO descriptor associated
with the parent PCI device. This can be added by using the 16bit
subsystem ID or similar to identify which exact machine we are
running on and what GPIO is present on that machine, and then
add a GPIO descriptor using gpiod_add_lookup_table() from
<linux/gpio/machine.h>. Since I don't have any target systems
I cannot add this but I'm happy to help. I put in a FIXME so
the people actually using this driver knows what to do.

Cc: Felipe Balbi <balbi@kernel.org>
Tested-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: Felipe Balbi <balbi@kernel.org>

authored by

Linus Walleij and committed by
Felipe Balbi
e20849a8 ff6d6e6c

+22 -33
+22 -33
drivers/usb/gadget/udc/pch_udc.c
··· 12 12 #include <linux/interrupt.h> 13 13 #include <linux/usb/ch9.h> 14 14 #include <linux/usb/gadget.h> 15 - #include <linux/gpio.h> 15 + #include <linux/gpio/consumer.h> 16 16 #include <linux/irq.h> 17 - 18 - /* GPIO port for VBUS detecting */ 19 - static int vbus_gpio_port = -1; /* GPIO port number (-1:Not used) */ 20 17 21 18 #define PCH_VBUS_PERIOD 3000 /* VBUS polling period (msec) */ 22 19 #define PCH_VBUS_INTERVAL 10 /* VBUS polling interval (msec) */ ··· 298 301 /** 299 302 * struct pch_vbus_gpio_data - Structure holding GPIO informaton 300 303 * for detecting VBUS 301 - * @port: gpio port number 304 + * @port: gpio descriptor for the VBUS GPIO 302 305 * @intr: gpio interrupt number 303 306 * @irq_work_fall: Structure for WorkQueue 304 307 * @irq_work_rise: Structure for WorkQueue 305 308 */ 306 309 struct pch_vbus_gpio_data { 307 - int port; 310 + struct gpio_desc *port; 308 311 int intr; 309 312 struct work_struct irq_work_fall; 310 313 struct work_struct irq_work_rise; ··· 1251 1254 int vbus = 0; 1252 1255 1253 1256 if (dev->vbus_gpio.port) 1254 - vbus = gpio_get_value(dev->vbus_gpio.port) ? 1 : 0; 1257 + vbus = gpiod_get_value(dev->vbus_gpio.port) ? 1 : 0; 1255 1258 else 1256 1259 vbus = -1; 1257 1260 ··· 1353 1356 /** 1354 1357 * pch_vbus_gpio_init() - This API initializes GPIO port detecting VBUS. 1355 1358 * @dev: Reference to the driver structure 1356 - * @vbus_gpio_port: Number of GPIO port to detect gpio 1357 1359 * 1358 1360 * Return codes: 1359 1361 * 0: Success 1360 1362 * -EINVAL: GPIO port is invalid or can't be initialized. 1361 1363 */ 1362 - static int pch_vbus_gpio_init(struct pch_udc_dev *dev, int vbus_gpio_port) 1364 + static int pch_vbus_gpio_init(struct pch_udc_dev *dev) 1363 1365 { 1364 1366 int err; 1365 1367 int irq_num = 0; 1368 + struct gpio_desc *gpiod; 1366 1369 1367 - dev->vbus_gpio.port = 0; 1370 + dev->vbus_gpio.port = NULL; 1368 1371 dev->vbus_gpio.intr = 0; 1369 1372 1370 - if (vbus_gpio_port <= -1) 1371 - return -EINVAL; 1373 + /* Retrieve the GPIO line from the USB gadget device */ 1374 + gpiod = devm_gpiod_get(dev->gadget.dev.parent, NULL, GPIOD_IN); 1375 + if (IS_ERR(gpiod)) 1376 + return PTR_ERR(gpiod); 1377 + gpiod_set_consumer_name(gpiod, "pch_vbus"); 1372 1378 1373 - err = gpio_is_valid(vbus_gpio_port); 1374 - if (!err) { 1375 - pr_err("%s: gpio port %d is invalid\n", 1376 - __func__, vbus_gpio_port); 1377 - return -EINVAL; 1378 - } 1379 - 1380 - err = gpio_request(vbus_gpio_port, "pch_vbus"); 1381 - if (err) { 1382 - pr_err("%s: can't request gpio port %d, err: %d\n", 1383 - __func__, vbus_gpio_port, err); 1384 - return -EINVAL; 1385 - } 1386 - 1387 - dev->vbus_gpio.port = vbus_gpio_port; 1388 - gpio_direction_input(vbus_gpio_port); 1379 + dev->vbus_gpio.port = gpiod; 1389 1380 INIT_WORK(&dev->vbus_gpio.irq_work_fall, pch_vbus_gpio_work_fall); 1390 1381 1391 - irq_num = gpio_to_irq(vbus_gpio_port); 1382 + irq_num = gpiod_to_irq(gpiod); 1392 1383 if (irq_num > 0) { 1393 1384 irq_set_irq_type(irq_num, IRQ_TYPE_EDGE_BOTH); 1394 1385 err = request_irq(irq_num, pch_vbus_gpio_irq, 0, ··· 1402 1417 { 1403 1418 if (dev->vbus_gpio.intr) 1404 1419 free_irq(dev->vbus_gpio.intr, dev); 1405 - 1406 - if (dev->vbus_gpio.port) 1407 - gpio_free(dev->vbus_gpio.port); 1408 1420 } 1409 1421 1410 1422 /** ··· 2876 2894 { 2877 2895 pch_udc_init(dev); 2878 2896 pch_udc_pcd_reinit(dev); 2879 - pch_vbus_gpio_init(dev, vbus_gpio_port); 2897 + pch_vbus_gpio_init(dev); 2880 2898 return 0; 2881 2899 } 2882 2900 ··· 3077 3095 return retval; 3078 3096 3079 3097 dev->base_addr = pcim_iomap_table(pdev)[bar]; 3098 + 3099 + /* 3100 + * FIXME: add a GPIO descriptor table to pdev.dev using 3101 + * gpiod_add_descriptor_table() from <linux/gpio/machine.h> based on 3102 + * the PCI subsystem ID. The system-dependent GPIO is necessary for 3103 + * VBUS operation. 3104 + */ 3080 3105 3081 3106 /* initialize the hardware */ 3082 3107 if (pch_udc_pcd_init(dev))