Skip to content
Advertisement

Why do my calls to gpiod_set_value return an “invalid GPIO” error?

I am attempting to write a driver for an OV2680 camera sensor. I want to turn on some GPIO pins as one of the steps in its ->probe() function. Those GpioIo() pins are declared in the DSDT tables like so (for a device upon which the OV2680 is dependent; see full DSDT table:

JavaScript

Note absence of a _DSD segment, meaning I have to explicitly declare them in the driver code according to the documentation. That’s no problem; I have the struct acpi_device for this ACPI device (by scraping the dependents of the OV2680 device that the driver matches to), so I can do that and add them with acpi_dev_add_driver_gpios() as the documentation instructs. My question comes in the Getting GPIO Descriptor stage; the documentation says to use gpiod_get_index(), which function calls for a struct device rather than a struct acpi_device. I’ve tried to fulfill this by passing the struct acpi_device::dev member, but although I don’t receive any error messages upon doing so, nothing actually seems to happen when I set the GPIO pins live, so I don’t think that it’s working.

Given this is hardware specific I’m not sure a MRE is useful, but here’s a driver that should compile and be inserted successfully:

JavaScript

dmesg reports no problems in adding the pins or anything, but the calls to gpiod_set_value_cansleep() throw an error there:

[4840.774633] gpiod_set_value_cansleep: invalid GPIO (errorpointer)

This transpires to be because the calls to gpiod_get_index() have failed, and thus the GPIO descriptors are invalid.

Questions:

  1. Is my use of &int3472->device as a parameter to gpiod_get_index() the correct approach?
  2. If so, what might cause the calls to gpiod_get_index() to fail?

EDITS:

Output of grep -H 15 /sys/bus/acpi/devices/*/status

JavaScript

Advertisement

Answer

(Gathering the answer based on comments I have given earlier)

For sake of the clarification I have to say, that from your DSDT we can get the following information. There are 3 groups of PMICs, i.e. DSCx, CLPx and PMIx. I believe they are based on the model, like Desktop, Laptop, 2-in-1. And in each case all PMICs in the same group have different _UID. From the provided output of the grep -H 15 ... we have only 2 out of 10 enumerated with the instances INT3472:08 and INT3472:09 (exactly two last defined in DSDT). And they are PMIx, you may check this by grep -H . /sys/bus/acpi/devices/INT3472:*/path.

Your interest is the PMI1 which consumes three GPIO lines from Intel GPIO driver, i.e. pins 121, 122 and 143 (you may decode them as Community #2, Group #5 or GPP_F, relative to the group pins 1, 2 and 23, this may help you to understand _INI method that touches these lines via other methods in DSDT), and provides 3 + 7 = 10 pins according to its driver.

Now to the code. The _DEP ACPI method is used solely for linking power resources, and Linux kernel has other means how to hijack resources from other device, because what you are trying to do is to use the resource which is not related to the device you are creating driver for.

The method is to find device by ACPI HID:

JavaScript

Hackish way to simplify this (since you know bus type and exact name of the device instance, but Linux does not guarantee it is kept the same over boots) is:

JavaScript

Side notes:

  1. There is already existing driver for OV2680 camera sensor, it makes sense to extend it instead of creating a specific fork for ACPI case.
  2. The proper method is to use resources where they can be consumed without any hacks, i.e. in the PMIC MFD driver.
User contributions licensed under: CC BY-SA
2 People found this is helpful
Advertisement