Re: [PATCH v2] extcon: otg_gpio: add driver for USB OTG port controlled by GPIO(s)

Linus Walleij
2015-03-19T08:18:14Z

On Mon, Mar 9, 2015 at 8:10 PM, David Cohen
<david.a.cohen@linux.intel.com> wrote:

> But at least on ACPI case, GPIO API blocks the ability to create
> children platform devices that require GPIO as platform data, despite
> we've many drivers on upstream that expect this behavior: e.g. extcon-gpio.c
>
> Are we considering those driver deprecated from the GPIO point of view?
> If yes, we need to provide an update for them (we can't let upstreamed
> drivers broken). If no, we need to provide a way to move forward the
> GPIO to children devices.

Aha OK... Let me paste this code from
arch/arm/mach-integrator/impd1.c - this is not an MFD (it would
be if we implemented it today) but you can see the idea I deploy:

for (i = 0; i < ARRAY_SIZE(impd1_devs); i++) {
struct impd1_device *idev = impd1_devs + i;
struct amba_device *d;
unsigned long pc_base;
char devname[32];
int irq1 = idev->irq[0];
int irq2 = idev->irq[1];

/* Translate IRQs to IM-PD1 local numberspace */
if (irq1)
irq1 += irq_base;
if (irq2)
irq2 += irq_base;

pc_base = dev->resource.start + idev->offset;
snprintf(devname, 32, "lm%x:%5.5lx", dev->id, idev->offset >> 12);

/* Add GPIO descriptor lookup table for the PL061 block */
if (idev->offset == 0x00400000) {
struct gpiod_lookup_table *lookup;
char *chipname;
char *mmciname;

lookup = devm_kzalloc(&dev->dev,
sizeof(*lookup) + 3 * sizeof(struct gpiod_lookup),
GFP_KERNEL);
chipname = devm_kstrdup(&dev->dev, devname, GFP_KERNEL);
mmciname = kasprintf(GFP_KERNEL, "lm%x:00700", dev->id);
lookup->dev_id = mmciname;
/*
* Offsets on GPIO block 1:
* 3 = MMC WP (write protect)
* 4 = MMC CD (card detect)
*
* Offsets on GPIO block 2:
* 0 = Up key
* 1 = Down key
* 2 = Left key
* 3 = Right key
* 4 = Key lower left
* 5 = Key lower right
*/
/* We need the two MMCI GPIO entries */
lookup->table[0].chip_label = chipname;
lookup->table[0].chip_hwnum = 3;
lookup->table[0].con_id = "wp";
lookup->table[1].chip_label = chipname;
lookup->table[1].chip_hwnum = 4;
lookup->table[1].con_id = "cd";
lookup->table[1].flags = GPIO_ACTIVE_LOW;
gpiod_add_lookup_table(lookup);
}

d = amba_ahb_device_add_res(&dev->dev, devname, pc_base, SZ_4K,
irq1, irq2,
idev->platform_data, idev->id,
&dev->resource);
if (IS_ERR(d)) {
dev_err(&dev->dev, "unable to register device: %ld\n", PTR_ERR(d));
continue;
}
}

Notice how I build a dynamic lookup table.

I don't see any problem for an MFD nexus doing this too, just need
some quirks I guess.

But I guess it's not that simple, i.e. the GPIOs are not just
"appearing" in the system like here (the devices we add has a GPIO
block going with it) but it's external GPIOs.

So I presume we are talking about the case of GPIO forwarding that
was mentioned earlier, so that GPIOs are defined for the nexus
(MFD) device and need to be forwarded to the clients so they can
issue gpiod_get() on their own struct device*?

Yours,
Linus Walleij