diff --git a/Documentation/devicetree/bindings/gpio/gpio-eic-sprd.txt b/Documentation/devicetree/bindings/gpio/gpio-eic-sprd.txt new file mode 100644 index 0000000000000000000000000000000000000000..93d98d09d92b18ebbbdb89804419e052e60c89c3 --- /dev/null +++ b/Documentation/devicetree/bindings/gpio/gpio-eic-sprd.txt @@ -0,0 +1,97 @@ +Spreadtrum EIC controller bindings + +The EIC is the abbreviation of external interrupt controller, which can +be used only in input mode. The Spreadtrum platform has 2 EIC controllers, +one is in digital chip, and another one is in PMIC. The digital chip EIC +controller contains 4 sub-modules: EIC-debounce, EIC-latch, EIC-async and +EIC-sync. But the PMIC EIC controller contains only one EIC-debounce sub- +module. + +The EIC-debounce sub-module provides up to 8 source input signal +connections. A debounce mechanism is used to capture the input signals' +stable status (millisecond resolution) and a single-trigger mechanism +is introduced into this sub-module to enhance the input event detection +reliability. In addition, this sub-module's clock can be shut off +automatically to reduce power dissipation. Moreover the debounce range +is from 1ms to 4s with a step size of 1ms. The input signal will be +ignored if it is asserted for less than 1 ms. + +The EIC-latch sub-module is used to latch some special power down signals +and generate interrupts, since the EIC-latch does not depend on the APB +clock to capture signals. + +The EIC-async sub-module uses a 32kHz clock to capture the short signals +(microsecond resolution) to generate interrupts by level or edge trigger. + +The EIC-sync is similar with GPIO's input function, which is a synchronized +signal input register. It can generate interrupts by level or edge trigger +when detecting input signals. + +Required properties: +- compatible: Should be one of the following: + "sprd,sc9860-eic-debounce", + "sprd,sc9860-eic-latch", + "sprd,sc9860-eic-async", + "sprd,sc9860-eic-sync", + "sprd,sc27xx-eic". +- reg: Define the base and range of the I/O address space containing + the GPIO controller registers. +- gpio-controller: Marks the device node as a GPIO controller. +- #gpio-cells: Should be <2>. The first cell is the gpio number and + the second cell is used to specify optional parameters. +- interrupt-controller: Marks the device node as an interrupt controller. +- #interrupt-cells: Should be <2>. Specifies the number of cells needed + to encode interrupt source. +- interrupts: Should be the port interrupt shared by all the gpios. + +Example: + eic_debounce: gpio@40210000 { + compatible = "sprd,sc9860-eic-debounce"; + reg = <0 0x40210000 0 0x80>; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + interrupts = ; + }; + + eic_latch: gpio@40210080 { + compatible = "sprd,sc9860-eic-latch"; + reg = <0 0x40210080 0 0x20>; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + interrupts = ; + }; + + eic_async: gpio@402100a0 { + compatible = "sprd,sc9860-eic-async"; + reg = <0 0x402100a0 0 0x20>; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + interrupts = ; + }; + + eic_sync: gpio@402100c0 { + compatible = "sprd,sc9860-eic-sync"; + reg = <0 0x402100c0 0 0x20>; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + interrupts = ; + }; + + pmic_eic: gpio@300 { + compatible = "sprd,sc27xx-eic"; + reg = <0x300>; + interrupt-parent = <&sc2731_pmic>; + interrupts = <5 IRQ_TYPE_LEVEL_HIGH>; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + }; diff --git a/Documentation/devicetree/bindings/gpio/gpio-pca953x.txt b/Documentation/devicetree/bindings/gpio/gpio-pca953x.txt index 0d0158728f897bd9fbeaa41e884955445ca1f062..d2a9376828369b33aaa4108ac5def0343f669409 100644 --- a/Documentation/devicetree/bindings/gpio/gpio-pca953x.txt +++ b/Documentation/devicetree/bindings/gpio/gpio-pca953x.txt @@ -16,6 +16,8 @@ Required properties: nxp,pca9574 nxp,pca9575 nxp,pca9698 + nxp,pcal6524 + nxp,pcal9555a maxim,max7310 maxim,max7312 maxim,max7313 diff --git a/Documentation/devicetree/bindings/gpio/gpio-sprd.txt b/Documentation/devicetree/bindings/gpio/gpio-sprd.txt new file mode 100644 index 0000000000000000000000000000000000000000..eca97d45388f574048a3c24be719822754e9755c --- /dev/null +++ b/Documentation/devicetree/bindings/gpio/gpio-sprd.txt @@ -0,0 +1,28 @@ +Spreadtrum GPIO controller bindings + +The controller's registers are organized as sets of sixteen 16-bit +registers with each set controlling a bank of up to 16 pins. A single +interrupt is shared for all of the banks handled by the controller. + +Required properties: +- compatible: Should be "sprd,sc9860-gpio". +- reg: Define the base and range of the I/O address space containing +the GPIO controller registers. +- gpio-controller: Marks the device node as a GPIO controller. +- #gpio-cells: Should be <2>. The first cell is the gpio number and +the second cell is used to specify optional parameters. +- interrupt-controller: Marks the device node as an interrupt controller. +- #interrupt-cells: Should be <2>. Specifies the number of cells needed +to encode interrupt source. +- interrupts: Should be the port interrupt shared by all the gpios. + +Example: + ap_gpio: gpio@40280000 { + compatible = "sprd,sc9860-gpio"; + reg = <0 0x40280000 0 0x1000>; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + interrupts = ; + }; diff --git a/Documentation/devicetree/bindings/gpio/gpio-tz1090-pdc.txt b/Documentation/devicetree/bindings/gpio/gpio-tz1090-pdc.txt deleted file mode 100644 index 528f5ef5a8932edcd05b0ccf5ad40971d410ca9a..0000000000000000000000000000000000000000 --- a/Documentation/devicetree/bindings/gpio/gpio-tz1090-pdc.txt +++ /dev/null @@ -1,45 +0,0 @@ -ImgTec TZ1090 PDC GPIO Controller - -Required properties: -- compatible: Compatible property value should be "img,tz1090-pdc-gpio". - -- reg: Physical base address of the controller and length of memory mapped - region. This starts at and cover the SOC_GPIO_CONTROL registers. - -- gpio-controller: Specifies that the node is a gpio controller. - -- #gpio-cells: Should be 2. The syntax of the gpio specifier used by client - nodes should have the following values. - <[phandle of the gpio controller node] - [PDC gpio number] - [gpio flags]> - - Values for gpio specifier: - - GPIO number: a value in the range 0 to 6. - - GPIO flags: bit field of flags, as defined in . - Only the following flags are supported: - GPIO_ACTIVE_HIGH - GPIO_ACTIVE_LOW - -Optional properties: -- gpio-ranges: Mapping to pin controller pins (as described in - Documentation/devicetree/bindings/gpio/gpio.txt) - -- interrupts: Individual syswake interrupts (other GPIOs cannot interrupt) - - -Example: - - pdc_gpios: gpio-controller@2006500 { - gpio-controller; - #gpio-cells = <2>; - - compatible = "img,tz1090-pdc-gpio"; - reg = <0x02006500 0x100>; - - interrupt-parent = <&pdc>; - interrupts = <8 IRQ_TYPE_NONE>, /* Syswake 0 */ - <9 IRQ_TYPE_NONE>, /* Syswake 1 */ - <10 IRQ_TYPE_NONE>; /* Syswake 2 */ - gpio-ranges = <&pdc_pinctrl 0 0 7>; - }; diff --git a/Documentation/devicetree/bindings/gpio/gpio-tz1090.txt b/Documentation/devicetree/bindings/gpio/gpio-tz1090.txt deleted file mode 100644 index b05a90e0ab2939652b91ac5dc42145a99832df38..0000000000000000000000000000000000000000 --- a/Documentation/devicetree/bindings/gpio/gpio-tz1090.txt +++ /dev/null @@ -1,88 +0,0 @@ -ImgTec TZ1090 GPIO Controller - -Required properties: -- compatible: Compatible property value should be "img,tz1090-gpio". - -- reg: Physical base address of the controller and length of memory mapped - region. - -- #address-cells: Should be 1 (for bank subnodes) - -- #size-cells: Should be 0 (for bank subnodes) - -- Each bank of GPIOs should have a subnode to represent it. - - Bank subnode required properties: - - reg: Index of bank in the range 0 to 2. - - - gpio-controller: Specifies that the node is a gpio controller. - - - #gpio-cells: Should be 2. The syntax of the gpio specifier used by client - nodes should have the following values. - <[phandle of the gpio controller node] - [gpio number within the gpio bank] - [gpio flags]> - - Values for gpio specifier: - - GPIO number: a value in the range 0 to 29. - - GPIO flags: bit field of flags, as defined in . - Only the following flags are supported: - GPIO_ACTIVE_HIGH - GPIO_ACTIVE_LOW - - Bank subnode optional properties: - - gpio-ranges: Mapping to pin controller pins (as described in - Documentation/devicetree/bindings/gpio/gpio.txt) - - - interrupts: Interrupt for the entire bank - - - interrupt-controller: Specifies that the node is an interrupt controller - - - #interrupt-cells: Should be 2. The syntax of the interrupt specifier used by - client nodes should have the following values. - <[phandle of the interurupt controller] - [gpio number within the gpio bank] - [irq flags]> - - Values for irq specifier: - - GPIO number: a value in the range 0 to 29 - - IRQ flags: value to describe edge and level triggering, as defined in - . Only the following flags are - supported: - IRQ_TYPE_EDGE_RISING - IRQ_TYPE_EDGE_FALLING - IRQ_TYPE_EDGE_BOTH - IRQ_TYPE_LEVEL_HIGH - IRQ_TYPE_LEVEL_LOW - - - -Example: - - gpios: gpio-controller@2005800 { - #address-cells = <1>; - #size-cells = <0>; - compatible = "img,tz1090-gpio"; - reg = <0x02005800 0x90>; - - /* bank 0 with an interrupt */ - gpios0: bank@0 { - #gpio-cells = <2>; - #interrupt-cells = <2>; - reg = <0>; - interrupts = <13 IRQ_TYPE_LEVEL_HIGH>; - gpio-controller; - gpio-ranges = <&pinctrl 0 0 30>; - interrupt-controller; - }; - - /* bank 2 without interrupt */ - gpios2: bank@2 { - #gpio-cells = <2>; - reg = <2>; - gpio-controller; - gpio-ranges = <&pinctrl 0 60 30>; - }; - }; - - diff --git a/Documentation/devicetree/bindings/gpio/gpio.txt b/Documentation/devicetree/bindings/gpio/gpio.txt index b5de08e3b1a2f1ad3526610468189991c08c0052..a7c31de2936202aa2fa9370934e6982ce5222deb 100644 --- a/Documentation/devicetree/bindings/gpio/gpio.txt +++ b/Documentation/devicetree/bindings/gpio/gpio.txt @@ -151,9 +151,9 @@ in a lot of designs, some using all 32 bits, some using 18 and some using first 18 GPIOs, at local offset 0 .. 17, are in use. If these GPIOs do not happen to be the first N GPIOs at offset 0...N-1, an -additional bitmask is needed to specify which GPIOs are actually in use, -and which are dummies. The bindings for this case has not yet been -specified, but should be specified if/when such hardware appears. +additional set of tuples is needed to specify which GPIOs are unusable, with +the gpio-reserved-ranges binding. This property indicates the start and size +of the GPIOs that can't be used. Optionally, a GPIO controller may have a "gpio-line-names" property. This is an array of strings defining the names of the GPIO lines going out of the @@ -178,6 +178,7 @@ gpio-controller@00000000 { gpio-controller; #gpio-cells = <2>; ngpios = <18>; + gpio-reserved-ranges = <0 4>, <12 2>; gpio-line-names = "MMC-CD", "MMC-WP", "VDD eth", "RST eth", "LED R", "LED G", "LED B", "Col A", "Col B", "Col C", "Col D", "Row A", "Row B", "Row C", "Row D", "NMI button", diff --git a/Documentation/devicetree/bindings/gpio/nintendo,hollywood-gpio.txt b/Documentation/devicetree/bindings/gpio/nintendo,hollywood-gpio.txt new file mode 100644 index 0000000000000000000000000000000000000000..20fc72d9e61e5721e56e0aeb0479682f921fd154 --- /dev/null +++ b/Documentation/devicetree/bindings/gpio/nintendo,hollywood-gpio.txt @@ -0,0 +1,27 @@ +Nintendo Wii (Hollywood) GPIO controller + +Required properties: +- compatible: "nintendo,hollywood-gpio +- reg: Physical base address and length of the controller's registers. +- gpio-controller: Marks the device node as a GPIO controller. +- #gpio-cells: Should be <2>. The first cell is the pin number and the + second cell is used to specify optional parameters: + - bit 0 specifies polarity (0 for normal, 1 for inverted). + +Optional properties: +- ngpios: see Documentation/devicetree/bindings/gpio/gpio.txt +- interrupt-controller: Marks the device node as an interrupt controller. +- #interrupt-cells: Should be two. +- interrupts: Interrupt specifier for the controller's Broadway (PowerPC) + interrupt. +- interrupt-parent: phandle of the parent interrupt controller. + +Example: + + GPIO: gpio@d8000c0 { + #gpio-cells = <2>; + compatible = "nintendo,hollywood-gpio"; + reg = <0x0d8000c0 0x40>; + gpio-controller; + ngpios = <24>; + } diff --git a/Documentation/devicetree/bindings/gpio/raspberrypi,firmware-gpio.txt b/Documentation/devicetree/bindings/gpio/raspberrypi,firmware-gpio.txt new file mode 100644 index 0000000000000000000000000000000000000000..ce97265e23ba6764adedde12b2fc1256fbd91d88 --- /dev/null +++ b/Documentation/devicetree/bindings/gpio/raspberrypi,firmware-gpio.txt @@ -0,0 +1,30 @@ +Raspberry Pi GPIO expander + +The Raspberry Pi 3 GPIO expander is controlled by the VC4 firmware. The +firmware exposes a mailbox interface that allows the ARM core to control the +GPIO lines on the expander. + +The Raspberry Pi GPIO expander node must be a child node of the Raspberry Pi +firmware node. + +Required properties: + +- compatible : Should be "raspberrypi,firmware-gpio" +- gpio-controller : Marks the device node as a gpio controller +- #gpio-cells : Should be two. The first cell is the pin number, and + the second cell is used to specify the gpio polarity: + 0 = active high + 1 = active low + +Example: + +firmware: firmware-rpi { + compatible = "raspberrypi,bcm2835-firmware"; + mboxes = <&mailbox>; + + expgpio: gpio { + compatible = "raspberrypi,firmware-gpio"; + gpio-controller; + #gpio-cells = <2>; + }; +}; diff --git a/Documentation/devicetree/bindings/powerpc/nintendo/wii.txt b/Documentation/devicetree/bindings/powerpc/nintendo/wii.txt index 36afa322b04be0b5a9e41a070ebecb38ed2c64c5..a3dc4b9fa11ae1297c45bfb0f0a5afba9cb534b6 100644 --- a/Documentation/devicetree/bindings/powerpc/nintendo/wii.txt +++ b/Documentation/devicetree/bindings/powerpc/nintendo/wii.txt @@ -152,14 +152,7 @@ Nintendo Wii device tree 1.l) The General Purpose I/O (GPIO) controller node - Represents the dual access 32 GPIO controller interface. - - Required properties: - - - #gpio-cells : <2> - - compatible : should be "nintendo,hollywood-gpio" - - reg : should contain the IPC registers location and length - - gpio-controller + see Documentation/devicetree/bindings/gpio/nintendo,hollywood-gpio.txt 1.m) The control node diff --git a/Documentation/gpio/board.txt b/Documentation/driver-api/gpio/board.rst similarity index 88% rename from Documentation/gpio/board.txt rename to Documentation/driver-api/gpio/board.rst index 659bb19f5b3c7affb6edbcd2eee76f09396876ca..25d62b2e9fd0b26968bbadcebf780d7d70c0a6a8 100644 --- a/Documentation/gpio/board.txt +++ b/Documentation/driver-api/gpio/board.rst @@ -1,3 +1,4 @@ +============= GPIO Mappings ============= @@ -23,7 +24,7 @@ device tree bindings for your controller. GPIOs mappings are defined in the consumer device's node, in a property named -gpios, where is the function the driver will request -through gpiod_get(). For example: +through gpiod_get(). For example:: foo_device { compatible = "acme,foo"; @@ -40,7 +41,7 @@ it but are only supported for compatibility reasons and should not be used for newer bindings since it has been deprecated. This property will make GPIOs 15, 16 and 17 available to the driver under the -"led" function, and GPIO 1 as the "power" GPIO: +"led" function, and GPIO 1 as the "power" GPIO:: struct gpio_desc *red, *green, *blue, *power; @@ -60,13 +61,13 @@ looked up by the gpiod functions internally) used in the device tree. With above Internally, the GPIO subsystem prefixes the GPIO suffix ("gpios" or "gpio") with the string passed in con_id to get the resulting string -(snprintf(... "%s-%s", con_id, gpio_suffixes[]). +(``snprintf(... "%s-%s", con_id, gpio_suffixes[]``). ACPI ---- ACPI also supports function names for GPIOs in a similar fashion to DT. The above DT example can be converted to an equivalent ACPI description -with the help of _DSD (Device Specific Data), introduced in ACPI 5.1: +with the help of _DSD (Device Specific Data), introduced in ACPI 5.1:: Device (FOO) { Name (_CRS, ResourceTemplate () { @@ -105,12 +106,12 @@ Documentation/acpi/gpio-properties.txt. Platform Data ------------- Finally, GPIOs can be bound to devices and functions using platform data. Board -files that desire to do so need to include the following header: +files that desire to do so need to include the following header:: #include GPIOs are mapped by the means of tables of lookups, containing instances of the -gpiod_lookup structure. Two macros are defined to help declaring such mappings: +gpiod_lookup structure. Two macros are defined to help declaring such mappings:: GPIO_LOOKUP(chip_label, chip_hwnum, con_id, flags) GPIO_LOOKUP_IDX(chip_label, chip_hwnum, con_id, idx, flags) @@ -141,22 +142,24 @@ end. The 'dev_id' field of the table is the identifier of the device that will make use of these GPIOs. It can be NULL, in which case it will be matched for calls to gpiod_get() with a NULL device. -struct gpiod_lookup_table gpios_table = { - .dev_id = "foo.0", - .table = { - GPIO_LOOKUP_IDX("gpio.0", 15, "led", 0, GPIO_ACTIVE_HIGH), - GPIO_LOOKUP_IDX("gpio.0", 16, "led", 1, GPIO_ACTIVE_HIGH), - GPIO_LOOKUP_IDX("gpio.0", 17, "led", 2, GPIO_ACTIVE_HIGH), - GPIO_LOOKUP("gpio.0", 1, "power", GPIO_ACTIVE_LOW), - { }, - }, -}; +.. code-block:: c + + struct gpiod_lookup_table gpios_table = { + .dev_id = "foo.0", + .table = { + GPIO_LOOKUP_IDX("gpio.0", 15, "led", 0, GPIO_ACTIVE_HIGH), + GPIO_LOOKUP_IDX("gpio.0", 16, "led", 1, GPIO_ACTIVE_HIGH), + GPIO_LOOKUP_IDX("gpio.0", 17, "led", 2, GPIO_ACTIVE_HIGH), + GPIO_LOOKUP("gpio.0", 1, "power", GPIO_ACTIVE_LOW), + { }, + }, + }; -And the table can be added by the board code as follows: +And the table can be added by the board code as follows:: gpiod_add_lookup_table(&gpios_table); -The driver controlling "foo.0" will then be able to obtain its GPIOs as follows: +The driver controlling "foo.0" will then be able to obtain its GPIOs as follows:: struct gpio_desc *red, *green, *blue, *power; diff --git a/Documentation/gpio/consumer.txt b/Documentation/driver-api/gpio/consumer.rst similarity index 89% rename from Documentation/gpio/consumer.txt rename to Documentation/driver-api/gpio/consumer.rst index d53e5b5cfc9cb65040f35631d23fc36f7f166f89..c71a50d85b50170dcfbb0323f24c29a0494d1648 100644 --- a/Documentation/gpio/consumer.txt +++ b/Documentation/driver-api/gpio/consumer.rst @@ -1,3 +1,4 @@ +================================== GPIO Descriptor Consumer Interface ================================== @@ -30,10 +31,10 @@ warnings. These stubs are used for two use cases: be met with console warnings that may be perceived as intimidating. All the functions that work with the descriptor-based GPIO interface are -prefixed with gpiod_. The gpio_ prefix is used for the legacy interface. No -other function in the kernel should use these prefixes. The use of the legacy -functions is strongly discouraged, new code should use -and descriptors exclusively. +prefixed with ``gpiod_``. The ``gpio_`` prefix is used for the legacy +interface. No other function in the kernel should use these prefixes. The use +of the legacy functions is strongly discouraged, new code should use + and descriptors exclusively. Obtaining and Disposing GPIOs @@ -43,13 +44,13 @@ With the descriptor-based interface, GPIOs are identified with an opaque, non-forgeable handler that must be obtained through a call to one of the gpiod_get() functions. Like many other kernel subsystems, gpiod_get() takes the device that will use the GPIO and the function the requested GPIO is supposed to -fulfill: +fulfill:: struct gpio_desc *gpiod_get(struct device *dev, const char *con_id, enum gpiod_flags flags) If a function is implemented by using several GPIOs together (e.g. a simple LED -device that displays digits), an additional index argument can be specified: +device that displays digits), an additional index argument can be specified:: struct gpio_desc *gpiod_get_index(struct device *dev, const char *con_id, unsigned int idx, @@ -84,7 +85,7 @@ occurred while trying to acquire it. This is useful to discriminate between mere errors and an absence of GPIO for optional GPIO parameters. For the common pattern where a GPIO is optional, the gpiod_get_optional() and gpiod_get_index_optional() functions can be used. These functions return NULL -instead of -ENOENT if no GPIO has been assigned to the requested function: +instead of -ENOENT if no GPIO has been assigned to the requested function:: struct gpio_desc *gpiod_get_optional(struct device *dev, const char *con_id, @@ -101,14 +102,14 @@ This is helpful to driver authors, since they do not need to special case -ENOSYS return codes. System integrators should however be careful to enable gpiolib on systems that need it. -For a function using multiple GPIOs all of those can be obtained with one call: +For a function using multiple GPIOs all of those can be obtained with one call:: struct gpio_descs *gpiod_get_array(struct device *dev, const char *con_id, enum gpiod_flags flags) This function returns a struct gpio_descs which contains an array of -descriptors: +descriptors:: struct gpio_descs { unsigned int ndescs; @@ -116,13 +117,13 @@ descriptors: } The following function returns NULL instead of -ENOENT if no GPIOs have been -assigned to the requested function: +assigned to the requested function:: struct gpio_descs *gpiod_get_array_optional(struct device *dev, const char *con_id, enum gpiod_flags flags) -Device-managed variants of these functions are also defined: +Device-managed variants of these functions are also defined:: struct gpio_desc *devm_gpiod_get(struct device *dev, const char *con_id, enum gpiod_flags flags) @@ -149,11 +150,11 @@ Device-managed variants of these functions are also defined: const char *con_id, enum gpiod_flags flags) -A GPIO descriptor can be disposed of using the gpiod_put() function: +A GPIO descriptor can be disposed of using the gpiod_put() function:: void gpiod_put(struct gpio_desc *desc) -For an array of GPIOs this function can be used: +For an array of GPIOs this function can be used:: void gpiod_put_array(struct gpio_descs *descs) @@ -161,7 +162,7 @@ It is strictly forbidden to use a descriptor after calling these functions. It is also not allowed to individually release descriptors (using gpiod_put()) from an array acquired with gpiod_get_array(). -The device-managed variants are, unsurprisingly: +The device-managed variants are, unsurprisingly:: void devm_gpiod_put(struct device *dev, struct gpio_desc *desc) @@ -175,7 +176,7 @@ Setting Direction ----------------- The first thing a driver must do with a GPIO is setting its direction. If no direction-setting flags have been given to gpiod_get*(), this is done by -invoking one of the gpiod_direction_*() functions: +invoking one of the gpiod_direction_*() functions:: int gpiod_direction_input(struct gpio_desc *desc) int gpiod_direction_output(struct gpio_desc *desc, int value) @@ -189,7 +190,7 @@ of early board setup. For output GPIOs, the value provided becomes the initial output value. This helps avoid signal glitching during system startup. -A driver can also query the current direction of a GPIO: +A driver can also query the current direction of a GPIO:: int gpiod_get_direction(const struct gpio_desc *desc) @@ -206,7 +207,7 @@ Most GPIO controllers can be accessed with memory read/write instructions. Those don't need to sleep, and can safely be done from inside hard (non-threaded) IRQ handlers and similar contexts. -Use the following calls to access GPIOs from an atomic context: +Use the following calls to access GPIOs from an atomic context:: int gpiod_get_value(const struct gpio_desc *desc); void gpiod_set_value(struct gpio_desc *desc, int value); @@ -231,11 +232,11 @@ head of a queue to transmit a command and get its response. This requires sleeping, which can't be done from inside IRQ handlers. Platforms that support this type of GPIO distinguish them from other GPIOs by -returning nonzero from this call: +returning nonzero from this call:: int gpiod_cansleep(const struct gpio_desc *desc) -To access such GPIOs, a different set of accessors is defined: +To access such GPIOs, a different set of accessors is defined:: int gpiod_get_value_cansleep(const struct gpio_desc *desc) void gpiod_set_value_cansleep(struct gpio_desc *desc, int value) @@ -271,23 +272,23 @@ As an example, if the active low property for a dedicated GPIO is set, and the gpiod_set_(array)_value_xxx() passes "asserted" ("1"), the physical line level will be driven low. -To summarize: - -Function (example) line property physical line -gpiod_set_raw_value(desc, 0); don't care low -gpiod_set_raw_value(desc, 1); don't care high -gpiod_set_value(desc, 0); default (active high) low -gpiod_set_value(desc, 1); default (active high) high -gpiod_set_value(desc, 0); active low high -gpiod_set_value(desc, 1); active low low -gpiod_set_value(desc, 0); default (active high) low -gpiod_set_value(desc, 1); default (active high) high -gpiod_set_value(desc, 0); open drain low -gpiod_set_value(desc, 1); open drain high impedance -gpiod_set_value(desc, 0); open source high impedance -gpiod_set_value(desc, 1); open source high - -It is possible to override these semantics using the *set_raw/'get_raw functions +To summarize:: + + Function (example) line property physical line + gpiod_set_raw_value(desc, 0); don't care low + gpiod_set_raw_value(desc, 1); don't care high + gpiod_set_value(desc, 0); default (active high) low + gpiod_set_value(desc, 1); default (active high) high + gpiod_set_value(desc, 0); active low high + gpiod_set_value(desc, 1); active low low + gpiod_set_value(desc, 0); default (active high) low + gpiod_set_value(desc, 1); default (active high) high + gpiod_set_value(desc, 0); open drain low + gpiod_set_value(desc, 1); open drain high impedance + gpiod_set_value(desc, 0); open source high impedance + gpiod_set_value(desc, 1); open source high + +It is possible to override these semantics using the set_raw/get_raw functions but it should be avoided as much as possible, especially by system-agnostic drivers which should not need to care about the actual physical line level and worry about the logical value instead. @@ -300,7 +301,7 @@ their device will actually receive, no matter what lies between it and the GPIO line. The following set of calls ignore the active-low or open drain property of a GPIO and -work on the raw line value: +work on the raw line value:: int gpiod_get_raw_value(const struct gpio_desc *desc) void gpiod_set_raw_value(struct gpio_desc *desc, int value) @@ -308,7 +309,7 @@ work on the raw line value: void gpiod_set_raw_value_cansleep(struct gpio_desc *desc, int value) int gpiod_direction_output_raw(struct gpio_desc *desc, int value) -The active low state of a GPIO can also be queried using the following call: +The active low state of a GPIO can also be queried using the following call:: int gpiod_is_active_low(const struct gpio_desc *desc) @@ -318,7 +319,7 @@ should not have to care about the physical line level or open drain semantics. Access multiple GPIOs with a single function call ------------------------------------------------- -The following functions get or set the values of an array of GPIOs: +The following functions get or set the values of an array of GPIOs:: int gpiod_get_array_value(unsigned int array_size, struct gpio_desc **desc_array, @@ -361,7 +362,7 @@ The functions take three arguments: The descriptor array can be obtained using the gpiod_get_array() function or one of its variants. If the group of descriptors returned by that function matches the desired group of GPIOs, those GPIOs can be accessed by simply using -the struct gpio_descs returned by gpiod_get_array(): +the struct gpio_descs returned by gpiod_get_array():: struct gpio_descs *my_gpio_descs = gpiod_get_array(...); gpiod_set_array_value(my_gpio_descs->ndescs, my_gpio_descs->desc, @@ -384,7 +385,7 @@ values are stored in value_array rather than passed back as return value. GPIOs mapped to IRQs -------------------- GPIO lines can quite often be used as IRQs. You can get the IRQ number -corresponding to a given GPIO using the following call: +corresponding to a given GPIO using the following call:: int gpiod_to_irq(const struct gpio_desc *desc) @@ -424,7 +425,7 @@ Interacting With the Legacy GPIO Subsystem Many kernel subsystems still handle GPIOs using the legacy integer-based interface. Although it is strongly encouraged to upgrade them to the safer descriptor-based API, the following two functions allow you to convert a GPIO -descriptor into the GPIO integer namespace and vice-versa: +descriptor into the GPIO integer namespace and vice-versa:: int desc_to_gpio(const struct gpio_desc *desc) struct gpio_desc *gpio_to_desc(unsigned gpio) diff --git a/Documentation/gpio/driver.txt b/Documentation/driver-api/gpio/driver.rst similarity index 93% rename from Documentation/gpio/driver.txt rename to Documentation/driver-api/gpio/driver.rst index 3392a0fd4c23c817758bd94b763022ff9cf3e309..505ee906d7d9590d68484890cebf753a40ec22be 100644 --- a/Documentation/gpio/driver.txt +++ b/Documentation/driver-api/gpio/driver.rst @@ -1,3 +1,4 @@ +================================ GPIO Descriptor Driver Interface ================================ @@ -53,9 +54,9 @@ common to each controller of that type: The code implementing a gpio_chip should support multiple instances of the controller, possibly using the driver model. That code will configure each -gpio_chip and issue gpiochip_add[_data]() or devm_gpiochip_add_data(). -Removing a GPIO controller should be rare; use [devm_]gpiochip_remove() when -it is unavoidable. +gpio_chip and issue ``gpiochip_add[_data]()`` or ``devm_gpiochip_add_data()``. +Removing a GPIO controller should be rare; use ``[devm_]gpiochip_remove()`` +when it is unavoidable. Often a gpio_chip is part of an instance-specific structure with states not exposed by the GPIO interfaces, such as addressing, power management, and more. @@ -115,7 +116,7 @@ GPIOs with open drain/source support Open drain (CMOS) or open collector (TTL) means the line is not actively driven high: instead you provide the drain/collector as output, so when the transistor -is not open, it will present a high-impedance (tristate) to the external rail. +is not open, it will present a high-impedance (tristate) to the external rail:: CMOS CONFIGURATION TTL CONFIGURATION @@ -148,19 +149,19 @@ level-shift to the higher VDD. Integrated electronics often have an output driver stage in the form of a CMOS "totem-pole" with one N-MOS and one P-MOS transistor where one of them drives the line high and one of them drives the line low. This is called a push-pull -output. The "totem-pole" looks like so: - - VDD - | - OD ||--+ - +--/ ---o|| P-MOS-FET - | ||--+ -IN --+ +----- out - | ||--+ - +--/ ----|| N-MOS-FET - OS ||--+ - | - GND +output. The "totem-pole" looks like so:: + + VDD + | + OD ||--+ + +--/ ---o|| P-MOS-FET + | ||--+ + IN --+ +----- out + | ||--+ + +--/ ----|| N-MOS-FET + OS ||--+ + | + GND The desired output signal (e.g. coming directly from some GPIO output register) arrives at IN. The switches named "OD" and "OS" are normally closed, creating @@ -219,8 +220,9 @@ systems simultaneously: gpio and irq. RT_FULL: a realtime compliant GPIO driver should not use spinlock_t or any sleepable APIs (like PM runtime) as part of its irq_chip implementation. -- spinlock_t should be replaced with raw_spinlock_t [1]. -- If sleepable APIs have to be used, these can be done from the .irq_bus_lock() + +* spinlock_t should be replaced with raw_spinlock_t [1]. +* If sleepable APIs have to be used, these can be done from the .irq_bus_lock() and .irq_bus_unlock() callbacks, as these are the only slowpath callbacks on an irqchip. Create the callbacks if needed [2]. @@ -232,12 +234,12 @@ GPIO irqchips usually fall in one of two categories: system interrupt controller. This means that the GPIO irqchip handler will be called immediately from the parent irqchip, while holding the IRQs disabled. The GPIO irqchip will then end up calling something like this - sequence in its interrupt handler: + sequence in its interrupt handler:: - static irqreturn_t foo_gpio_irq(int irq, void *data) - chained_irq_enter(...); - generic_handle_irq(...); - chained_irq_exit(...); + static irqreturn_t foo_gpio_irq(int irq, void *data) + chained_irq_enter(...); + generic_handle_irq(...); + chained_irq_exit(...); Chained GPIO irqchips typically can NOT set the .can_sleep flag on struct gpio_chip, as everything happens directly in the callbacks: no @@ -252,7 +254,7 @@ GPIO irqchips usually fall in one of two categories: (for example, see [3]). Know W/A: The generic_handle_irq() is expected to be called with IRQ disabled, so the IRQ core will complain if it is called from an IRQ handler which is - forced to a thread. The "fake?" raw lock can be used to W/A this problem: + forced to a thread. The "fake?" raw lock can be used to W/A this problem:: raw_spinlock_t wa_lock; static irqreturn_t omap_gpio_irq_handler(int irq, void *gpiobank) @@ -265,11 +267,11 @@ GPIO irqchips usually fall in one of two categories: but chained IRQ handlers are not used. Instead GPIO IRQs dispatching is performed by generic IRQ handler which is configured using request_irq(). The GPIO irqchip will then end up calling something like this sequence in - its interrupt handler: + its interrupt handler:: - static irqreturn_t gpio_rcar_irq_handler(int irq, void *dev_id) - for each detected GPIO IRQ - generic_handle_irq(...); + static irqreturn_t gpio_rcar_irq_handler(int irq, void *dev_id) + for each detected GPIO IRQ + generic_handle_irq(...); RT_FULL: Such kind of handlers will be forced threaded on -RT, as result IRQ core will complain that generic_handle_irq() is called with IRQ enabled and @@ -282,11 +284,11 @@ GPIO irqchips usually fall in one of two categories: in a quick IRQ handler with IRQs disabled. Instead they need to spawn a thread and then mask the parent IRQ line until the interrupt is handled by the driver. The hallmark of this driver is to call something like - this in its interrupt handler: + this in its interrupt handler:: - static irqreturn_t foo_gpio_irq(int irq, void *data) - ... - handle_nested_irq(irq); + static irqreturn_t foo_gpio_irq(int irq, void *data) + ... + handle_nested_irq(irq); The hallmark of threaded GPIO irqchips is that they set the .can_sleep flag on struct gpio_chip to true, indicating that this chip may sleep @@ -359,12 +361,12 @@ below exists. Locking IRQ usage ----------------- Input GPIOs can be used as IRQ signals. When this happens, a driver is requested -to mark the GPIO as being used as an IRQ: +to mark the GPIO as being used as an IRQ:: int gpiochip_lock_as_irq(struct gpio_chip *chip, unsigned int offset) This will prevent the use of non-irq related GPIO APIs until the GPIO IRQ lock -is released: +is released:: void gpiochip_unlock_as_irq(struct gpio_chip *chip, unsigned int offset) @@ -408,7 +410,7 @@ Sometimes it is useful to allow a GPIO chip driver to request its own GPIO descriptors through the gpiolib API. Using gpio_request() for this purpose does not help since it pins the module to the kernel forever (it calls try_module_get()). A GPIO driver can use the following functions instead -to request and free descriptors without being pinned to the kernel forever. +to request and free descriptors without being pinned to the kernel forever:: struct gpio_desc *gpiochip_request_own_desc(struct gpio_desc *desc, const char *label) @@ -422,6 +424,6 @@ These functions must be used with care since they do not affect module use count. Do not use the functions to request gpio descriptors not owned by the calling driver. -[1] http://www.spinics.net/lists/linux-omap/msg120425.html -[2] https://lkml.org/lkml/2015/9/25/494 -[3] https://lkml.org/lkml/2015/9/25/495 +* [1] http://www.spinics.net/lists/linux-omap/msg120425.html +* [2] https://lkml.org/lkml/2015/9/25/494 +* [3] https://lkml.org/lkml/2015/9/25/495 diff --git a/Documentation/gpio/drivers-on-gpio.txt b/Documentation/driver-api/gpio/drivers-on-gpio.rst similarity index 99% rename from Documentation/gpio/drivers-on-gpio.txt rename to Documentation/driver-api/gpio/drivers-on-gpio.rst index a2ccbab12eb7a6cc7b5107fc9142175a09dbffd7..019483868977887a4f9b43d0e1c426af6ee7687b 100644 --- a/Documentation/gpio/drivers-on-gpio.txt +++ b/Documentation/driver-api/gpio/drivers-on-gpio.rst @@ -1,3 +1,4 @@ +============================ Subsystem drivers using GPIO ============================ diff --git a/Documentation/driver-api/gpio.rst b/Documentation/driver-api/gpio/index.rst similarity index 74% rename from Documentation/driver-api/gpio.rst rename to Documentation/driver-api/gpio/index.rst index 6dd4aa647f27d6297dd5496be5f5695d2f11c639..6a374ded1287d91a209607fcd82d559aadfecb5c 100644 --- a/Documentation/driver-api/gpio.rst +++ b/Documentation/driver-api/gpio/index.rst @@ -2,6 +2,18 @@ General Purpose Input/Output (GPIO) =================================== +Contents: + +.. toctree:: + :maxdepth: 2 + + intro + driver + consumer + board + drivers-on-gpio + legacy + Core ==== @@ -11,15 +23,6 @@ Core .. kernel-doc:: drivers/gpio/gpiolib.c :export: -Legacy API -========== - -The functions listed in this section are deprecated. The GPIO descriptor based -API described above should be used in new code. - -.. kernel-doc:: drivers/gpio/gpiolib-legacy.c - :export: - ACPI support ============ diff --git a/Documentation/gpio/gpio.txt b/Documentation/driver-api/gpio/intro.rst similarity index 96% rename from Documentation/gpio/gpio.txt rename to Documentation/driver-api/gpio/intro.rst index cd9b356e88cdc82d776775c83e3c87514bee8875..74591489d0b55f677d0371b7f21b2345be58b92f 100644 --- a/Documentation/gpio/gpio.txt +++ b/Documentation/driver-api/gpio/intro.rst @@ -1,3 +1,8 @@ +============ +Introduction +============ + + GPIO Interfaces =============== @@ -9,9 +14,9 @@ Due to the history of GPIO interfaces in the kernel, there are two different ways to obtain and use GPIOs: - The descriptor-based interface is the preferred way to manipulate GPIOs, -and is described by all the files in this directory excepted gpio-legacy.txt. + and is described by all the files in this directory excepted gpio-legacy.txt. - The legacy integer-based interface which is considered deprecated (but still -usable for compatibility reasons) is documented in gpio-legacy.txt. + usable for compatibility reasons) is documented in gpio-legacy.txt. The remainder of this document applies to the new descriptor-based interface. gpio-legacy.txt contains the same information applied to the legacy diff --git a/Documentation/gpio/gpio-legacy.txt b/Documentation/driver-api/gpio/legacy.rst similarity index 96% rename from Documentation/gpio/gpio-legacy.txt rename to Documentation/driver-api/gpio/legacy.rst index 8356d0e78f679c66bc69af8420eac2c4ace27f41..5e9421e05f1d5e39bb65ceafc4049ee7fd08476b 100644 --- a/Documentation/gpio/gpio-legacy.txt +++ b/Documentation/driver-api/gpio/legacy.rst @@ -1,4 +1,6 @@ -GPIO Interfaces +====================== +Legacy GPIO Interfaces +====================== This provides an overview of GPIO access conventions on Linux. @@ -129,7 +131,7 @@ The first thing a system should do with a GPIO is allocate it, using the gpio_request() call; see later. One of the next things to do with a GPIO, often in board setup code when -setting up a platform_device using the GPIO, is mark its direction: +setting up a platform_device using the GPIO, is mark its direction:: /* set as input or output, returning 0 or negative errno */ int gpio_direction_input(unsigned gpio); @@ -164,7 +166,7 @@ Those don't need to sleep, and can safely be done from inside hard (nonthreaded) IRQ handlers and similar contexts. Use the following calls to access such GPIOs, -for which gpio_cansleep() will always return false (see below): +for which gpio_cansleep() will always return false (see below):: /* GPIO INPUT: return zero or nonzero */ int gpio_get_value(unsigned gpio); @@ -201,11 +203,11 @@ This requires sleeping, which can't be done from inside IRQ handlers. Platforms that support this type of GPIO distinguish them from other GPIOs by returning nonzero from this call (which requires a valid GPIO number, -which should have been previously allocated with gpio_request): +which should have been previously allocated with gpio_request):: int gpio_cansleep(unsigned gpio); -To access such GPIOs, a different set of accessors is defined: +To access such GPIOs, a different set of accessors is defined:: /* GPIO INPUT: return zero or nonzero, might sleep */ int gpio_get_value_cansleep(unsigned gpio); @@ -222,27 +224,27 @@ Other than the fact that these accessors might sleep, and will work on GPIOs that can't be accessed from hardIRQ handlers, these calls act the same as the spinlock-safe calls. - ** IN ADDITION ** calls to setup and configure such GPIOs must be made +**IN ADDITION** calls to setup and configure such GPIOs must be made from contexts which may sleep, since they may need to access the GPIO -controller chip too: (These setup calls are usually made from board -setup or driver probe/teardown code, so this is an easy constraint.) +controller chip too (These setup calls are usually made from board +setup or driver probe/teardown code, so this is an easy constraint.):: - gpio_direction_input() - gpio_direction_output() - gpio_request() + gpio_direction_input() + gpio_direction_output() + gpio_request() -## gpio_request_one() -## gpio_request_array() -## gpio_free_array() + ## gpio_request_one() + ## gpio_request_array() + ## gpio_free_array() - gpio_free() - gpio_set_debounce() + gpio_free() + gpio_set_debounce() Claiming and Releasing GPIOs ---------------------------- -To help catch system configuration errors, two calls are defined. +To help catch system configuration errors, two calls are defined:: /* request GPIO, returning 0 or negative errno. * non-null labels may be useful for diagnostics. @@ -296,7 +298,7 @@ Also note that it's your responsibility to have stopped using a GPIO before you free it. Considering in most cases GPIOs are actually configured right after they -are claimed, three additional calls are defined: +are claimed, three additional calls are defined:: /* request a single GPIO, with initial configuration specified by * 'flags', identical to gpio_request() wrt other arguments and @@ -347,7 +349,7 @@ to make the pin LOW. The pin is make to HIGH by driving value 1 in output mode. In the future, these flags can be extended to support more properties. Further more, to ease the claim/release of multiple GPIOs, 'struct gpio' is -introduced to encapsulate all three fields as: +introduced to encapsulate all three fields as:: struct gpio { unsigned gpio; @@ -355,7 +357,7 @@ introduced to encapsulate all three fields as: const char *label; }; -A typical example of usage: +A typical example of usage:: static struct gpio leds_gpios[] = { { 32, GPIOF_OUT_INIT_HIGH, "Power LED" }, /* default to ON */ @@ -380,7 +382,7 @@ GPIOs mapped to IRQs -------------------- GPIO numbers are unsigned integers; so are IRQ numbers. These make up two logically distinct namespaces (GPIO 0 need not use IRQ 0). You can -map between them using calls like: +map between them using calls like:: /* map GPIO numbers to IRQ numbers */ int gpio_to_irq(unsigned gpio); @@ -446,12 +448,12 @@ A GPIO controller on a SOC might be tightly coupled with the pinctrl subsystem, in the sense that the pins can be used by other functions together with an optional gpio feature. We have already covered the case where e.g. a GPIO controller need to reserve a pin or set the -direction of a pin by calling any of: +direction of a pin by calling any of:: -pinctrl_gpio_request() -pinctrl_gpio_free() -pinctrl_gpio_direction_input() -pinctrl_gpio_direction_output() + pinctrl_gpio_request() + pinctrl_gpio_free() + pinctrl_gpio_direction_input() + pinctrl_gpio_direction_output() But how does the pin control subsystem cross-correlate the GPIO numbers (which are a global business) to a certain pin on a certain @@ -565,7 +567,7 @@ If neither of these options are selected, the platform does not support GPIOs through GPIO-lib and the code cannot be enabled by the user. Trivial implementations of those functions can directly use framework -code, which always dispatches through the gpio_chip: +code, which always dispatches through the gpio_chip:: #define gpio_get_value __gpio_get_value #define gpio_set_value __gpio_set_value @@ -731,7 +733,7 @@ the correct GPIO number to use for a given signal. Exporting from Kernel code -------------------------- Kernel code can explicitly manage exports of GPIOs which have already been -requested using gpio_request(): +requested using gpio_request():: /* export the GPIO to userspace */ int gpio_export(unsigned gpio, bool direction_may_change); @@ -756,3 +758,13 @@ After the GPIO has been exported, gpio_export_link() allows creating symlinks from elsewhere in sysfs to the GPIO sysfs node. Drivers can use this to provide the interface under their own device in sysfs with a descriptive name. + + +API Reference +============= + +The functions listed in this section are deprecated. The GPIO descriptor based +API should be used in new code. + +.. kernel-doc:: drivers/gpio/gpiolib-legacy.c + :export: diff --git a/Documentation/driver-api/index.rst b/Documentation/driver-api/index.rst index e9b41b1634f3124a91bfda73ae5d67630adecc2b..6d8352c0f3547a9f63fa7db614e1466f2b822616 100644 --- a/Documentation/driver-api/index.rst +++ b/Documentation/driver-api/index.rst @@ -44,7 +44,7 @@ available subsections can be seen below. uio-howto firmware/index pinctl - gpio + gpio/index misc_devices dmaengine/index slimbus diff --git a/Documentation/gpio/00-INDEX b/Documentation/gpio/00-INDEX index 179beb234f989ea17f0dba1e5f5b6d5e4fe07235..17e19a68058f083f899a956a2bcee65b7359818c 100644 --- a/Documentation/gpio/00-INDEX +++ b/Documentation/gpio/00-INDEX @@ -1,17 +1,4 @@ 00-INDEX - This file -gpio.txt - - Introduction to GPIOs and their kernel interfaces -consumer.txt - - How to obtain and use GPIOs in a driver -driver.txt - - How to write a GPIO driver -drivers-on-gpio.txt: - - Drivers in other subsystems that can use GPIO to provide more - complex functionality. -board.txt - - How to assign GPIOs to a consumer device and a function sysfs.txt - Information about the GPIO sysfs interface -gpio-legacy.txt - - Historical documentation of the deprecated GPIO integer interface diff --git a/Documentation/gpio/sysfs.txt b/Documentation/gpio/sysfs.txt index 6cdeab8650cdbd20a75fed859ef1b7f9f942fdf0..58eeab81f349062fc8628135e1af900493669b56 100644 --- a/Documentation/gpio/sysfs.txt +++ b/Documentation/gpio/sysfs.txt @@ -32,9 +32,8 @@ standard kernels won't know about. And for some tasks, simple userspace GPIO drivers could be all that the system really needs. DO NOT ABUSE SYSFS TO CONTROL HARDWARE THAT HAS PROPER KERNEL DRIVERS. -PLEASE READ THE DOCUMENT NAMED "drivers-on-gpio.txt" IN THIS DOCUMENTATION -DIRECTORY TO AVOID REINVENTING KERNEL WHEELS IN USERSPACE. I MEAN IT. -REALLY. +PLEASE READ THE DOCUMENT AT Documentation/driver-api/gpio/drivers-on-gpio.rst +TO AVOID REINVENTING KERNEL WHEELS IN USERSPACE. I MEAN IT. REALLY. Paths in Sysfs -------------- diff --git a/MAINTAINERS b/MAINTAINERS index 89fd8040e29521f37487317c16650ed2c4cad172..954ba16a39ede82f949ad5580d7c445c812801d4 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -5984,7 +5984,7 @@ S: Maintained F: drivers/media/rc/gpio-ir-tx.c GPIO MOCKUP DRIVER -M: Bamvor Jian Zhang +M: Bamvor Jian Zhang R: Bartosz Golaszewski L: linux-gpio@vger.kernel.org S: Maintained @@ -5997,6 +5997,7 @@ L: linux-gpio@vger.kernel.org T: git git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-gpio.git S: Maintained F: Documentation/devicetree/bindings/gpio/ +F: Documentation/driver-api/gpio/ F: Documentation/gpio/ F: Documentation/ABI/testing/gpio-cdev F: Documentation/ABI/obsolete/sysfs-gpio diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 27fede43895957b762274f0205eaefbd5d86c131..f69e689d609bf178c50fa77878fa4c15e473ddb4 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -2665,11 +2665,13 @@ config PCI_CNB20LE_QUIRK source "drivers/pci/Kconfig" config ISA_BUS - bool "ISA-style bus support on modern systems" if EXPERT - select ISA_BUS_API + bool "ISA bus support on modern systems" if EXPERT help - Enables ISA-style drivers on modern systems. This is necessary to - support PC/104 devices on X86_64 platforms. + Expose ISA bus device drivers and options available for selection and + configuration. Enable this option if your target machine has an ISA + bus. ISA is an older system, displaced by PCI and newer bus + architectures -- if your target machine is modern, it probably does + not have an ISA bus. If unsure, say N. diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 68d812b38be783f196f2580e1d03a476c852c070..b960f6f35abd37c2b61d68e85e2c5290c5211245 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -122,6 +122,17 @@ config GPIO_ATH79 Select this option to enable GPIO driver for Atheros AR71XX/AR724X/AR913X SoC devices. +config GPIO_RASPBERRYPI_EXP + tristate "Raspberry Pi 3 GPIO Expander" + default RASPBERRYPI_FIRMWARE + depends on OF_GPIO + # Make sure not 'y' when RASPBERRYPI_FIRMWARE is 'm'. This can only + # happen when COMPILE_TEST=y, hence the added !RASPBERRYPI_FIRMWARE. + depends on (ARCH_BCM2835 && RASPBERRYPI_FIRMWARE) || (COMPILE_TEST && !RASPBERRYPI_FIRMWARE) + help + Turn on GPIO support for the expander on Raspberry Pi 3 boards, using + the firmware mailbox to communicate with VideoCore on BCM283x chips. + config GPIO_BCM_KONA bool "Broadcom Kona GPIO" depends on OF_GPIO && (ARCH_BCM_MOBILE || COMPILE_TEST) @@ -159,6 +170,14 @@ config GPIO_DWAPB Say Y or M here to build support for the Synopsys DesignWare APB GPIO block. +config GPIO_EIC_SPRD + tristate "Spreadtrum EIC support" + depends on ARCH_SPRD || COMPILE_TEST + depends on OF_GPIO + select GPIOLIB_IRQCHIP + help + Say yes here to support Spreadtrum EIC device. + config GPIO_EM tristate "Emma Mobile GPIO" depends on (ARCH_EMEV2 || COMPILE_TEST) && OF_GPIO @@ -214,6 +233,15 @@ config GPIO_GRGPIO Select this to support Aeroflex Gaisler GRGPIO cores from the GRLIB VHDL IP core library. +config GPIO_HLWD + tristate "Nintendo Wii (Hollywood) GPIO" + depends on OF_GPIO + select GPIO_GENERIC + help + Select this to support the GPIO controller of the Nintendo Wii. + + If unsure, say N. + config GPIO_ICH tristate "Intel ICH GPIO" depends on PCI && X86 @@ -363,6 +391,14 @@ config GPIO_PL061 help Say yes here to support the PrimeCell PL061 GPIO device +config GPIO_PMIC_EIC_SPRD + tristate "Spreadtrum PMIC EIC support" + depends on MFD_SC27XX_PMIC || COMPILE_TEST + depends on OF_GPIO + select GPIOLIB_IRQCHIP + help + Say yes here to support Spreadtrum PMIC EIC device. + config GPIO_PXA bool "PXA GPIO support" depends on ARCH_PXA || ARCH_MMP @@ -389,6 +425,14 @@ config GPIO_SPEAR_SPICS help Say yes here to support ST SPEAr SPI Chip Select as GPIO device +config GPIO_SPRD + tristate "Spreadtrum GPIO support" + depends on ARCH_SPRD || COMPILE_TEST + depends on OF_GPIO + select GPIOLIB_IRQCHIP + help + Say yes here to support Spreadtrum GPIO device. + config GPIO_STA2X11 bool "STA2x11/ConneXt GPIO support" depends on MFD_STA2X11 @@ -453,21 +497,6 @@ config GPIO_THUNDERX Say yes here to support the on-chip GPIO lines on the ThunderX and OCTEON-TX families of SoCs. -config GPIO_TZ1090 - bool "Toumaz Xenif TZ1090 GPIO support" - depends on SOC_TZ1090 - select GENERIC_IRQ_CHIP - default y - help - Say yes here to support Toumaz Xenif TZ1090 GPIOs. - -config GPIO_TZ1090_PDC - bool "Toumaz Xenif TZ1090 PDC GPIO support" - depends on SOC_TZ1090 - default y - help - Say yes here to support Toumaz Xenif TZ1090 PDC GPIOs. - config GPIO_UNIPHIER tristate "UniPhier GPIO support" depends on ARCH_UNIPHIER || COMPILE_TEST @@ -581,7 +610,8 @@ menu "Port-mapped I/O GPIO drivers" config GPIO_104_DIO_48E tristate "ACCES 104-DIO-48E GPIO support" - depends on PC104 && ISA_BUS_API + depends on PC104 + select ISA_BUS_API select GPIOLIB_IRQCHIP help Enables GPIO support for the ACCES 104-DIO-48E series (104-DIO-48E, @@ -591,7 +621,8 @@ config GPIO_104_DIO_48E config GPIO_104_IDIO_16 tristate "ACCES 104-IDIO-16 GPIO support" - depends on PC104 && ISA_BUS_API + depends on PC104 + select ISA_BUS_API select GPIOLIB_IRQCHIP help Enables GPIO support for the ACCES 104-IDIO-16 family (104-IDIO-16, @@ -602,7 +633,8 @@ config GPIO_104_IDIO_16 config GPIO_104_IDI_48 tristate "ACCES 104-IDI-48 GPIO support" - depends on PC104 && ISA_BUS_API + depends on PC104 + select ISA_BUS_API select GPIOLIB_IRQCHIP help Enables GPIO support for the ACCES 104-IDI-48 family (104-IDI-48A, @@ -622,7 +654,8 @@ config GPIO_F7188X config GPIO_GPIO_MM tristate "Diamond Systems GPIO-MM GPIO support" - depends on PC104 && ISA_BUS_API + depends on PC104 + select ISA_BUS_API help Enables GPIO support for the Diamond Systems GPIO-MM and GPIO-MM-12. @@ -691,7 +724,7 @@ config GPIO_TS5500 config GPIO_WINBOND tristate "Winbond Super I/O GPIO support" - depends on ISA_BUS_API + select ISA_BUS_API help This option enables support for GPIOs found on Winbond Super I/O chips. @@ -707,7 +740,7 @@ config GPIO_WINBOND config GPIO_WS16C48 tristate "WinSystems WS16C48 GPIO support" - depends on ISA_BUS_API + select ISA_BUS_API select GPIOLIB_IRQCHIP help Enables GPIO support for the WinSystems WS16C48. The base port diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index db8c9d4ea2effbda9ed32632a1bdcdee3c62d244..1324c8f966a79db1609ab6aa5aedb30415260741 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -32,6 +32,7 @@ obj-$(CONFIG_GPIO_AMDPT) += gpio-amdpt.o obj-$(CONFIG_GPIO_ARIZONA) += gpio-arizona.o obj-$(CONFIG_GPIO_ATH79) += gpio-ath79.o obj-$(CONFIG_GPIO_ASPEED) += gpio-aspeed.o +obj-$(CONFIG_GPIO_RASPBERRYPI_EXP) += gpio-raspberrypi-exp.o obj-$(CONFIG_GPIO_BCM_KONA) += gpio-bcm-kona.o obj-$(CONFIG_GPIO_BD9571MWV) += gpio-bd9571mwv.o obj-$(CONFIG_GPIO_BRCMSTB) += gpio-brcmstb.o @@ -44,6 +45,7 @@ obj-$(CONFIG_GPIO_DA9055) += gpio-da9055.o obj-$(CONFIG_GPIO_DAVINCI) += gpio-davinci.o obj-$(CONFIG_GPIO_DLN2) += gpio-dln2.o obj-$(CONFIG_GPIO_DWAPB) += gpio-dwapb.o +obj-$(CONFIG_GPIO_EIC_SPRD) += gpio-eic-sprd.o obj-$(CONFIG_GPIO_EM) += gpio-em.o obj-$(CONFIG_GPIO_EP93XX) += gpio-ep93xx.o obj-$(CONFIG_GPIO_EXAR) += gpio-exar.o @@ -52,6 +54,7 @@ obj-$(CONFIG_GPIO_FTGPIO010) += gpio-ftgpio010.o obj-$(CONFIG_GPIO_GE_FPGA) += gpio-ge.o obj-$(CONFIG_GPIO_GPIO_MM) += gpio-gpio-mm.o obj-$(CONFIG_GPIO_GRGPIO) += gpio-grgpio.o +obj-$(CONFIG_GPIO_HLWD) += gpio-hlwd.o obj-$(CONFIG_HTC_EGPIO) += gpio-htc-egpio.o obj-$(CONFIG_GPIO_ICH) += gpio-ich.o obj-$(CONFIG_GPIO_INGENIC) += gpio-ingenic.o @@ -97,6 +100,7 @@ obj-$(CONFIG_GPIO_PCI_IDIO_16) += gpio-pci-idio-16.o obj-$(CONFIG_GPIO_PCIE_IDIO_24) += gpio-pcie-idio-24.o obj-$(CONFIG_GPIO_PISOSR) += gpio-pisosr.o obj-$(CONFIG_GPIO_PL061) += gpio-pl061.o +obj-$(CONFIG_GPIO_PMIC_EIC_SPRD) += gpio-pmic-eic-sprd.o obj-$(CONFIG_GPIO_PXA) += gpio-pxa.o obj-$(CONFIG_GPIO_RC5T583) += gpio-rc5t583.o obj-$(CONFIG_GPIO_RDC321X) += gpio-rdc321x.o @@ -107,6 +111,7 @@ obj-$(CONFIG_GPIO_SCH) += gpio-sch.o obj-$(CONFIG_GPIO_SCH311X) += gpio-sch311x.o obj-$(CONFIG_GPIO_SODAVILLE) += gpio-sodaville.o obj-$(CONFIG_GPIO_SPEAR_SPICS) += gpio-spear-spics.o +obj-$(CONFIG_GPIO_SPRD) += gpio-sprd.o obj-$(CONFIG_GPIO_STA2X11) += gpio-sta2x11.o obj-$(CONFIG_GPIO_STMPE) += gpio-stmpe.o obj-$(CONFIG_GPIO_STP_XWAY) += gpio-stp-xway.o @@ -130,8 +135,6 @@ obj-$(CONFIG_GPIO_TS4900) += gpio-ts4900.o obj-$(CONFIG_GPIO_TS5500) += gpio-ts5500.o obj-$(CONFIG_GPIO_TWL4030) += gpio-twl4030.o obj-$(CONFIG_GPIO_TWL6040) += gpio-twl6040.o -obj-$(CONFIG_GPIO_TZ1090) += gpio-tz1090.o -obj-$(CONFIG_GPIO_TZ1090_PDC) += gpio-tz1090-pdc.o obj-$(CONFIG_GPIO_UCB1400) += gpio-ucb1400.o obj-$(CONFIG_GPIO_UNIPHIER) += gpio-uniphier.o obj-$(CONFIG_GPIO_VF610) += gpio-vf610.o diff --git a/drivers/gpio/gpio-104-dio-48e.c b/drivers/gpio/gpio-104-dio-48e.c index bab3b94c5cbc1a6462080c4f53d1e38f7b8356a8..31e22c93e84484d6fbbd2269d02b76c55a26d885 100644 --- a/drivers/gpio/gpio-104-dio-48e.c +++ b/drivers/gpio/gpio-104-dio-48e.c @@ -14,6 +14,7 @@ * This driver supports the following ACCES devices: 104-DIO-48E and * 104-DIO-24E. */ +#include #include #include #include @@ -182,6 +183,51 @@ static int dio48e_gpio_get(struct gpio_chip *chip, unsigned offset) return !!(port_state & mask); } +static int dio48e_gpio_get_multiple(struct gpio_chip *chip, unsigned long *mask, + unsigned long *bits) +{ + struct dio48e_gpio *const dio48egpio = gpiochip_get_data(chip); + size_t i; + const size_t ports[] = { 0, 1, 2, 4, 5, 6 }; + const unsigned int gpio_reg_size = 8; + unsigned int bits_offset; + size_t word_index; + unsigned int word_offset; + unsigned long word_mask; + const unsigned long port_mask = GENMASK(gpio_reg_size - 1, 0); + unsigned long port_state; + + /* clear bits array to a clean slate */ + bitmap_zero(bits, chip->ngpio); + + /* get bits are evaluated a gpio port register at a time */ + for (i = 0; i < ARRAY_SIZE(ports); i++) { + /* gpio offset in bits array */ + bits_offset = i * gpio_reg_size; + + /* word index for bits array */ + word_index = BIT_WORD(bits_offset); + + /* gpio offset within current word of bits array */ + word_offset = bits_offset % BITS_PER_LONG; + + /* mask of get bits for current gpio within current word */ + word_mask = mask[word_index] & (port_mask << word_offset); + if (!word_mask) { + /* no get bits in this port so skip to next one */ + continue; + } + + /* read bits from current gpio port */ + port_state = inb(dio48egpio->base + ports[i]); + + /* store acquired bits at respective bits array offset */ + bits[word_index] |= port_state << word_offset; + } + + return 0; +} + static void dio48e_gpio_set(struct gpio_chip *chip, unsigned offset, int value) { struct dio48e_gpio *const dio48egpio = gpiochip_get_data(chip); @@ -384,6 +430,7 @@ static int dio48e_probe(struct device *dev, unsigned int id) dio48egpio->chip.direction_input = dio48e_gpio_direction_input; dio48egpio->chip.direction_output = dio48e_gpio_direction_output; dio48egpio->chip.get = dio48e_gpio_get; + dio48egpio->chip.get_multiple = dio48e_gpio_get_multiple; dio48egpio->chip.set = dio48e_gpio_set; dio48egpio->chip.set_multiple = dio48e_gpio_set_multiple; dio48egpio->base = base[id]; diff --git a/drivers/gpio/gpio-104-idi-48.c b/drivers/gpio/gpio-104-idi-48.c index add859d59766006d45a5d5153cf805feea17e4fc..f35632609379432440e9ca1df167f88dab1422a0 100644 --- a/drivers/gpio/gpio-104-idi-48.c +++ b/drivers/gpio/gpio-104-idi-48.c @@ -14,6 +14,7 @@ * This driver supports the following ACCES devices: 104-IDI-48A, * 104-IDI-48AC, 104-IDI-48B, and 104-IDI-48BC. */ +#include #include #include #include @@ -88,6 +89,51 @@ static int idi_48_gpio_get(struct gpio_chip *chip, unsigned offset) return 0; } +static int idi_48_gpio_get_multiple(struct gpio_chip *chip, unsigned long *mask, + unsigned long *bits) +{ + struct idi_48_gpio *const idi48gpio = gpiochip_get_data(chip); + size_t i; + const size_t ports[] = { 0, 1, 2, 4, 5, 6 }; + const unsigned int gpio_reg_size = 8; + unsigned int bits_offset; + size_t word_index; + unsigned int word_offset; + unsigned long word_mask; + const unsigned long port_mask = GENMASK(gpio_reg_size - 1, 0); + unsigned long port_state; + + /* clear bits array to a clean slate */ + bitmap_zero(bits, chip->ngpio); + + /* get bits are evaluated a gpio port register at a time */ + for (i = 0; i < ARRAY_SIZE(ports); i++) { + /* gpio offset in bits array */ + bits_offset = i * gpio_reg_size; + + /* word index for bits array */ + word_index = BIT_WORD(bits_offset); + + /* gpio offset within current word of bits array */ + word_offset = bits_offset % BITS_PER_LONG; + + /* mask of get bits for current gpio within current word */ + word_mask = mask[word_index] & (port_mask << word_offset); + if (!word_mask) { + /* no get bits in this port so skip to next one */ + continue; + } + + /* read bits from current gpio port */ + port_state = inb(idi48gpio->base + ports[i]); + + /* store acquired bits at respective bits array offset */ + bits[word_index] |= port_state << word_offset; + } + + return 0; +} + static void idi_48_irq_ack(struct irq_data *data) { } @@ -256,6 +302,7 @@ static int idi_48_probe(struct device *dev, unsigned int id) idi48gpio->chip.get_direction = idi_48_gpio_get_direction; idi48gpio->chip.direction_input = idi_48_gpio_direction_input; idi48gpio->chip.get = idi_48_gpio_get; + idi48gpio->chip.get_multiple = idi_48_gpio_get_multiple; idi48gpio->base = base[id]; raw_spin_lock_init(&idi48gpio->lock); diff --git a/drivers/gpio/gpio-104-idio-16.c b/drivers/gpio/gpio-104-idio-16.c index 2f16638a05896631f7a133a3b8bddb667b328cc3..96700308c1e380f76b694a55f198c9267afb7781 100644 --- a/drivers/gpio/gpio-104-idio-16.c +++ b/drivers/gpio/gpio-104-idio-16.c @@ -90,6 +90,20 @@ static int idio_16_gpio_get(struct gpio_chip *chip, unsigned offset) return !!(inb(idio16gpio->base + 5) & (mask>>8)); } +static int idio_16_gpio_get_multiple(struct gpio_chip *chip, + unsigned long *mask, unsigned long *bits) +{ + struct idio_16_gpio *const idio16gpio = gpiochip_get_data(chip); + + *bits = 0; + if (*mask & GENMASK(23, 16)) + *bits |= (unsigned long)inb(idio16gpio->base + 1) << 16; + if (*mask & GENMASK(31, 24)) + *bits |= (unsigned long)inb(idio16gpio->base + 5) << 24; + + return 0; +} + static void idio_16_gpio_set(struct gpio_chip *chip, unsigned offset, int value) { struct idio_16_gpio *const idio16gpio = gpiochip_get_data(chip); @@ -244,6 +258,7 @@ static int idio_16_probe(struct device *dev, unsigned int id) idio16gpio->chip.direction_input = idio_16_gpio_direction_input; idio16gpio->chip.direction_output = idio_16_gpio_direction_output; idio16gpio->chip.get = idio_16_gpio_get; + idio16gpio->chip.get_multiple = idio_16_gpio_get_multiple; idio16gpio->chip.set = idio_16_gpio_set; idio16gpio->chip.set_multiple = idio_16_gpio_set_multiple; idio16gpio->base = base[id]; diff --git a/drivers/gpio/gpio-ath79.c b/drivers/gpio/gpio-ath79.c index 3ae7c1876bf4c0ad64a4a5392c11999c585a2e21..684e9d6d6623d6f56b38321c935464cdd9dc1434 100644 --- a/drivers/gpio/gpio-ath79.c +++ b/drivers/gpio/gpio-ath79.c @@ -258,6 +258,8 @@ static int ath79_gpio_probe(struct platform_device *pdev) } res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) + return -EINVAL; ctrl->base = devm_ioremap_nocache( &pdev->dev, res->start, resource_size(res)); if (!ctrl->base) diff --git a/drivers/gpio/gpio-davinci.c b/drivers/gpio/gpio-davinci.c index 0b951ca78ec40c529b3df803249152d251d1e823..987126c4c6f611630d35222e6577d1bc80c10281 100644 --- a/drivers/gpio/gpio-davinci.c +++ b/drivers/gpio/gpio-davinci.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -225,6 +226,11 @@ static int davinci_gpio_probe(struct platform_device *pdev) chips->chip.of_gpio_n_cells = 2; chips->chip.parent = dev; chips->chip.of_node = dev->of_node; + + if (of_property_read_bool(dev->of_node, "gpio-ranges")) { + chips->chip.request = gpiochip_generic_request; + chips->chip.free = gpiochip_generic_free; + } #endif spin_lock_init(&chips->lock); bank_base += ngpio; diff --git a/drivers/gpio/gpio-dln2.c b/drivers/gpio/gpio-dln2.c index 1dada68b9a27ab7b022cb309f7fb5ba9ac0b4f41..c4e7953c093ed016b5429d2528781b03a5a92421 100644 --- a/drivers/gpio/gpio-dln2.c +++ b/drivers/gpio/gpio-dln2.c @@ -15,7 +15,6 @@ #include #include #include -#include #include #include #include @@ -204,9 +203,9 @@ static int dln2_gpio_get_direction(struct gpio_chip *chip, unsigned offset) struct dln2_gpio *dln2 = gpiochip_get_data(chip); if (test_bit(offset, dln2->output_enabled)) - return GPIOF_DIR_OUT; + return 0; - return GPIOF_DIR_IN; + return 1; } static int dln2_gpio_get(struct gpio_chip *chip, unsigned int offset) @@ -218,7 +217,7 @@ static int dln2_gpio_get(struct gpio_chip *chip, unsigned int offset) if (dir < 0) return dir; - if (dir == GPIOF_DIR_IN) + if (dir == 1) return dln2_gpio_pin_get_in_val(dln2, offset); return dln2_gpio_pin_get_out_val(dln2, offset); diff --git a/drivers/gpio/gpio-dwapb.c b/drivers/gpio/gpio-dwapb.c index 6730c6642ce315c3da38c13a10fcae1c01601f32..226977f78482a842a79bde8bad43e40db7ddf261 100644 --- a/drivers/gpio/gpio-dwapb.c +++ b/drivers/gpio/gpio-dwapb.c @@ -8,10 +8,9 @@ * All enquiries to support@picochip.com */ #include -#include -/* FIXME: for gpio_get_value(), replace this with direct register read */ -#include +#include #include +#include #include #include #include @@ -53,9 +52,9 @@ #define GPIO_EXT_PORTD 0x5c #define DWAPB_MAX_PORTS 4 -#define GPIO_EXT_PORT_SIZE (GPIO_EXT_PORTB - GPIO_EXT_PORTA) -#define GPIO_SWPORT_DR_SIZE (GPIO_SWPORTB_DR - GPIO_SWPORTA_DR) -#define GPIO_SWPORT_DDR_SIZE (GPIO_SWPORTB_DDR - GPIO_SWPORTA_DDR) +#define GPIO_EXT_PORT_STRIDE 0x04 /* register stride 32 bits */ +#define GPIO_SWPORT_DR_STRIDE 0x0c /* register stride 3*32 bits */ +#define GPIO_SWPORT_DDR_STRIDE 0x0c /* register stride 3*32 bits */ #define GPIO_REG_OFFSET_V2 1 @@ -100,6 +99,7 @@ struct dwapb_gpio { struct irq_domain *domain; unsigned int flags; struct reset_control *rst; + struct clk *clk; }; static inline u32 gpio_reg_v2_convert(unsigned int offset) @@ -153,16 +153,40 @@ static int dwapb_gpio_to_irq(struct gpio_chip *gc, unsigned offset) return irq_find_mapping(gpio->domain, offset); } +static struct dwapb_gpio_port *dwapb_offs_to_port(struct dwapb_gpio *gpio, unsigned int offs) +{ + struct dwapb_gpio_port *port; + int i; + + for (i = 0; i < gpio->nr_ports; i++) { + port = &gpio->ports[i]; + if (port->idx == offs / 32) + return port; + } + + return NULL; +} + static void dwapb_toggle_trigger(struct dwapb_gpio *gpio, unsigned int offs) { - u32 v = dwapb_read(gpio, GPIO_INT_POLARITY); + struct dwapb_gpio_port *port = dwapb_offs_to_port(gpio, offs); + struct gpio_chip *gc; + u32 pol; + int val; + + if (!port) + return; + gc = &port->gc; - if (gpio_get_value(gpio->ports[0].gc.base + offs)) - v &= ~BIT(offs); + pol = dwapb_read(gpio, GPIO_INT_POLARITY); + /* Just read the current value right out of the data register */ + val = gc->get(gc, offs % 32); + if (val) + pol &= ~BIT(offs); else - v |= BIT(offs); + pol |= BIT(offs); - dwapb_write(gpio, GPIO_INT_POLARITY, v); + dwapb_write(gpio, GPIO_INT_POLARITY, pol); } static u32 dwapb_do_irq(struct dwapb_gpio *gpio) @@ -476,11 +500,12 @@ static int dwapb_gpio_add_port(struct dwapb_gpio *gpio, return -ENOMEM; #endif - dat = gpio->regs + GPIO_EXT_PORTA + (pp->idx * GPIO_EXT_PORT_SIZE); - set = gpio->regs + GPIO_SWPORTA_DR + (pp->idx * GPIO_SWPORT_DR_SIZE); + dat = gpio->regs + GPIO_EXT_PORTA + (pp->idx * GPIO_EXT_PORT_STRIDE); + set = gpio->regs + GPIO_SWPORTA_DR + (pp->idx * GPIO_SWPORT_DR_STRIDE); dirout = gpio->regs + GPIO_SWPORTA_DDR + - (pp->idx * GPIO_SWPORT_DDR_SIZE); + (pp->idx * GPIO_SWPORT_DDR_STRIDE); + /* This registers 32 GPIO lines per port */ err = bgpio_init(&port->gc, gpio->dev, 4, dat, set, NULL, dirout, NULL, 0); if (err) { @@ -647,6 +672,16 @@ static int dwapb_gpio_probe(struct platform_device *pdev) if (IS_ERR(gpio->regs)) return PTR_ERR(gpio->regs); + /* Optional bus clock */ + gpio->clk = devm_clk_get(&pdev->dev, "bus"); + if (!IS_ERR(gpio->clk)) { + err = clk_prepare_enable(gpio->clk); + if (err) { + dev_info(&pdev->dev, "Cannot enable clock\n"); + return err; + } + } + gpio->flags = 0; if (dev->of_node) { const struct of_device_id *of_devid; @@ -689,6 +724,7 @@ static int dwapb_gpio_remove(struct platform_device *pdev) dwapb_gpio_unregister(gpio); dwapb_irq_teardown(gpio); reset_control_assert(gpio->rst); + clk_disable_unprepare(gpio->clk); return 0; } @@ -710,13 +746,13 @@ static int dwapb_gpio_suspend(struct device *dev) BUG_ON(!ctx); - offset = GPIO_SWPORTA_DDR + idx * GPIO_SWPORT_DDR_SIZE; + offset = GPIO_SWPORTA_DDR + idx * GPIO_SWPORT_DDR_STRIDE; ctx->dir = dwapb_read(gpio, offset); - offset = GPIO_SWPORTA_DR + idx * GPIO_SWPORT_DR_SIZE; + offset = GPIO_SWPORTA_DR + idx * GPIO_SWPORT_DR_STRIDE; ctx->data = dwapb_read(gpio, offset); - offset = GPIO_EXT_PORTA + idx * GPIO_EXT_PORT_SIZE; + offset = GPIO_EXT_PORTA + idx * GPIO_EXT_PORT_STRIDE; ctx->ext = dwapb_read(gpio, offset); /* Only port A can provide interrupts */ @@ -734,6 +770,8 @@ static int dwapb_gpio_suspend(struct device *dev) } spin_unlock_irqrestore(&gc->bgpio_lock, flags); + clk_disable_unprepare(gpio->clk); + return 0; } @@ -745,6 +783,9 @@ static int dwapb_gpio_resume(struct device *dev) unsigned long flags; int i; + if (!IS_ERR(gpio->clk)) + clk_prepare_enable(gpio->clk); + spin_lock_irqsave(&gc->bgpio_lock, flags); for (i = 0; i < gpio->nr_ports; i++) { unsigned int offset; @@ -753,13 +794,13 @@ static int dwapb_gpio_resume(struct device *dev) BUG_ON(!ctx); - offset = GPIO_SWPORTA_DR + idx * GPIO_SWPORT_DR_SIZE; + offset = GPIO_SWPORTA_DR + idx * GPIO_SWPORT_DR_STRIDE; dwapb_write(gpio, offset, ctx->data); - offset = GPIO_SWPORTA_DDR + idx * GPIO_SWPORT_DDR_SIZE; + offset = GPIO_SWPORTA_DDR + idx * GPIO_SWPORT_DDR_STRIDE; dwapb_write(gpio, offset, ctx->dir); - offset = GPIO_EXT_PORTA + idx * GPIO_EXT_PORT_SIZE; + offset = GPIO_EXT_PORTA + idx * GPIO_EXT_PORT_STRIDE; dwapb_write(gpio, offset, ctx->ext); /* Only port A can provide interrupts */ diff --git a/drivers/gpio/gpio-eic-sprd.c b/drivers/gpio/gpio-eic-sprd.c new file mode 100644 index 0000000000000000000000000000000000000000..de7dd939c04314bc54debf94c3c5943fe06debae --- /dev/null +++ b/drivers/gpio/gpio-eic-sprd.c @@ -0,0 +1,606 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2018 Spreadtrum Communications Inc. + * Copyright (C) 2018 Linaro Ltd. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +/* EIC registers definition */ +#define SPRD_EIC_DBNC_DATA 0x0 +#define SPRD_EIC_DBNC_DMSK 0x4 +#define SPRD_EIC_DBNC_IEV 0x14 +#define SPRD_EIC_DBNC_IE 0x18 +#define SPRD_EIC_DBNC_RIS 0x1c +#define SPRD_EIC_DBNC_MIS 0x20 +#define SPRD_EIC_DBNC_IC 0x24 +#define SPRD_EIC_DBNC_TRIG 0x28 +#define SPRD_EIC_DBNC_CTRL0 0x40 + +#define SPRD_EIC_LATCH_INTEN 0x0 +#define SPRD_EIC_LATCH_INTRAW 0x4 +#define SPRD_EIC_LATCH_INTMSK 0x8 +#define SPRD_EIC_LATCH_INTCLR 0xc +#define SPRD_EIC_LATCH_INTPOL 0x10 +#define SPRD_EIC_LATCH_INTMODE 0x14 + +#define SPRD_EIC_ASYNC_INTIE 0x0 +#define SPRD_EIC_ASYNC_INTRAW 0x4 +#define SPRD_EIC_ASYNC_INTMSK 0x8 +#define SPRD_EIC_ASYNC_INTCLR 0xc +#define SPRD_EIC_ASYNC_INTMODE 0x10 +#define SPRD_EIC_ASYNC_INTBOTH 0x14 +#define SPRD_EIC_ASYNC_INTPOL 0x18 +#define SPRD_EIC_ASYNC_DATA 0x1c + +#define SPRD_EIC_SYNC_INTIE 0x0 +#define SPRD_EIC_SYNC_INTRAW 0x4 +#define SPRD_EIC_SYNC_INTMSK 0x8 +#define SPRD_EIC_SYNC_INTCLR 0xc +#define SPRD_EIC_SYNC_INTMODE 0x10 +#define SPRD_EIC_SYNC_INTBOTH 0x14 +#define SPRD_EIC_SYNC_INTPOL 0x18 +#define SPRD_EIC_SYNC_DATA 0x1c + +/* + * The digital-chip EIC controller can support maximum 3 banks, and each bank + * contains 8 EICs. + */ +#define SPRD_EIC_MAX_BANK 3 +#define SPRD_EIC_PER_BANK_NR 8 +#define SPRD_EIC_DATA_MASK GENMASK(7, 0) +#define SPRD_EIC_BIT(x) ((x) & (SPRD_EIC_PER_BANK_NR - 1)) +#define SPRD_EIC_DBNC_MASK GENMASK(11, 0) + +/* + * The Spreadtrum EIC (external interrupt controller) can be used only in + * input mode to generate interrupts if detecting input signals. + * + * The Spreadtrum digital-chip EIC controller contains 4 sub-modules: + * debounce EIC, latch EIC, async EIC and sync EIC, + * + * The debounce EIC is used to capture the input signals' stable status + * (millisecond resolution) and a single-trigger mechanism is introduced + * into this sub-module to enhance the input event detection reliability. + * The debounce range is from 1ms to 4s with a step size of 1ms. + * + * The latch EIC is used to latch some special power down signals and + * generate interrupts, since the latch EIC does not depend on the APB clock + * to capture signals. + * + * The async EIC uses a 32k clock to capture the short signals (microsecond + * resolution) to generate interrupts by level or edge trigger. + * + * The EIC-sync is similar with GPIO's input function, which is a synchronized + * signal input register. + */ +enum sprd_eic_type { + SPRD_EIC_DEBOUNCE, + SPRD_EIC_LATCH, + SPRD_EIC_ASYNC, + SPRD_EIC_SYNC, + SPRD_EIC_MAX, +}; + +struct sprd_eic { + struct gpio_chip chip; + struct irq_chip intc; + void __iomem *base[SPRD_EIC_MAX_BANK]; + enum sprd_eic_type type; + spinlock_t lock; + int irq; +}; + +struct sprd_eic_variant_data { + enum sprd_eic_type type; + u32 num_eics; +}; + +static const char *sprd_eic_label_name[SPRD_EIC_MAX] = { + "eic-debounce", "eic-latch", "eic-async", + "eic-sync", +}; + +static const struct sprd_eic_variant_data sc9860_eic_dbnc_data = { + .type = SPRD_EIC_DEBOUNCE, + .num_eics = 8, +}; + +static const struct sprd_eic_variant_data sc9860_eic_latch_data = { + .type = SPRD_EIC_LATCH, + .num_eics = 8, +}; + +static const struct sprd_eic_variant_data sc9860_eic_async_data = { + .type = SPRD_EIC_ASYNC, + .num_eics = 8, +}; + +static const struct sprd_eic_variant_data sc9860_eic_sync_data = { + .type = SPRD_EIC_SYNC, + .num_eics = 8, +}; + +static inline void __iomem *sprd_eic_offset_base(struct sprd_eic *sprd_eic, + unsigned int bank) +{ + if (bank >= SPRD_EIC_MAX_BANK) + return NULL; + + return sprd_eic->base[bank]; +} + +static void sprd_eic_update(struct gpio_chip *chip, unsigned int offset, + u16 reg, unsigned int val) +{ + struct sprd_eic *sprd_eic = gpiochip_get_data(chip); + void __iomem *base = + sprd_eic_offset_base(sprd_eic, offset / SPRD_EIC_PER_BANK_NR); + unsigned long flags; + u32 tmp; + + spin_lock_irqsave(&sprd_eic->lock, flags); + tmp = readl_relaxed(base + reg); + + if (val) + tmp |= BIT(SPRD_EIC_BIT(offset)); + else + tmp &= ~BIT(SPRD_EIC_BIT(offset)); + + writel_relaxed(tmp, base + reg); + spin_unlock_irqrestore(&sprd_eic->lock, flags); +} + +static int sprd_eic_read(struct gpio_chip *chip, unsigned int offset, u16 reg) +{ + struct sprd_eic *sprd_eic = gpiochip_get_data(chip); + void __iomem *base = + sprd_eic_offset_base(sprd_eic, offset / SPRD_EIC_PER_BANK_NR); + + return !!(readl_relaxed(base + reg) & BIT(SPRD_EIC_BIT(offset))); +} + +static int sprd_eic_request(struct gpio_chip *chip, unsigned int offset) +{ + sprd_eic_update(chip, offset, SPRD_EIC_DBNC_DMSK, 1); + return 0; +} + +static void sprd_eic_free(struct gpio_chip *chip, unsigned int offset) +{ + sprd_eic_update(chip, offset, SPRD_EIC_DBNC_DMSK, 0); +} + +static int sprd_eic_get(struct gpio_chip *chip, unsigned int offset) +{ + return sprd_eic_read(chip, offset, SPRD_EIC_DBNC_DATA); +} + +static int sprd_eic_direction_input(struct gpio_chip *chip, unsigned int offset) +{ + /* EICs are always input, nothing need to do here. */ + return 0; +} + +static void sprd_eic_set(struct gpio_chip *chip, unsigned int offset, int value) +{ + /* EICs are always input, nothing need to do here. */ +} + +static int sprd_eic_set_debounce(struct gpio_chip *chip, unsigned int offset, + unsigned int debounce) +{ + struct sprd_eic *sprd_eic = gpiochip_get_data(chip); + void __iomem *base = + sprd_eic_offset_base(sprd_eic, offset / SPRD_EIC_PER_BANK_NR); + u32 reg = SPRD_EIC_DBNC_CTRL0 + SPRD_EIC_BIT(offset) * 0x4; + u32 value = readl_relaxed(base + reg) & ~SPRD_EIC_DBNC_MASK; + + value |= (debounce / 1000) & SPRD_EIC_DBNC_MASK; + writel_relaxed(value, base + reg); + + return 0; +} + +static int sprd_eic_set_config(struct gpio_chip *chip, unsigned int offset, + unsigned long config) +{ + unsigned long param = pinconf_to_config_param(config); + u32 arg = pinconf_to_config_argument(config); + + if (param == PIN_CONFIG_INPUT_DEBOUNCE) + return sprd_eic_set_debounce(chip, offset, arg); + + return -ENOTSUPP; +} + +static void sprd_eic_irq_mask(struct irq_data *data) +{ + struct gpio_chip *chip = irq_data_get_irq_chip_data(data); + struct sprd_eic *sprd_eic = gpiochip_get_data(chip); + u32 offset = irqd_to_hwirq(data); + + switch (sprd_eic->type) { + case SPRD_EIC_DEBOUNCE: + sprd_eic_update(chip, offset, SPRD_EIC_DBNC_IE, 0); + sprd_eic_update(chip, offset, SPRD_EIC_DBNC_TRIG, 0); + break; + case SPRD_EIC_LATCH: + sprd_eic_update(chip, offset, SPRD_EIC_LATCH_INTEN, 0); + break; + case SPRD_EIC_ASYNC: + sprd_eic_update(chip, offset, SPRD_EIC_ASYNC_INTIE, 0); + break; + case SPRD_EIC_SYNC: + sprd_eic_update(chip, offset, SPRD_EIC_SYNC_INTIE, 0); + break; + default: + dev_err(chip->parent, "Unsupported EIC type.\n"); + } +} + +static void sprd_eic_irq_unmask(struct irq_data *data) +{ + struct gpio_chip *chip = irq_data_get_irq_chip_data(data); + struct sprd_eic *sprd_eic = gpiochip_get_data(chip); + u32 offset = irqd_to_hwirq(data); + + switch (sprd_eic->type) { + case SPRD_EIC_DEBOUNCE: + sprd_eic_update(chip, offset, SPRD_EIC_DBNC_IE, 1); + sprd_eic_update(chip, offset, SPRD_EIC_DBNC_TRIG, 1); + break; + case SPRD_EIC_LATCH: + sprd_eic_update(chip, offset, SPRD_EIC_LATCH_INTEN, 1); + break; + case SPRD_EIC_ASYNC: + sprd_eic_update(chip, offset, SPRD_EIC_ASYNC_INTIE, 1); + break; + case SPRD_EIC_SYNC: + sprd_eic_update(chip, offset, SPRD_EIC_SYNC_INTIE, 1); + break; + default: + dev_err(chip->parent, "Unsupported EIC type.\n"); + } +} + +static void sprd_eic_irq_ack(struct irq_data *data) +{ + struct gpio_chip *chip = irq_data_get_irq_chip_data(data); + struct sprd_eic *sprd_eic = gpiochip_get_data(chip); + u32 offset = irqd_to_hwirq(data); + + switch (sprd_eic->type) { + case SPRD_EIC_DEBOUNCE: + sprd_eic_update(chip, offset, SPRD_EIC_DBNC_IC, 1); + break; + case SPRD_EIC_LATCH: + sprd_eic_update(chip, offset, SPRD_EIC_LATCH_INTCLR, 1); + break; + case SPRD_EIC_ASYNC: + sprd_eic_update(chip, offset, SPRD_EIC_ASYNC_INTCLR, 1); + break; + case SPRD_EIC_SYNC: + sprd_eic_update(chip, offset, SPRD_EIC_SYNC_INTCLR, 1); + break; + default: + dev_err(chip->parent, "Unsupported EIC type.\n"); + } +} + +static int sprd_eic_irq_set_type(struct irq_data *data, unsigned int flow_type) +{ + struct gpio_chip *chip = irq_data_get_irq_chip_data(data); + struct sprd_eic *sprd_eic = gpiochip_get_data(chip); + u32 offset = irqd_to_hwirq(data); + + switch (sprd_eic->type) { + case SPRD_EIC_DEBOUNCE: + switch (flow_type) { + case IRQ_TYPE_LEVEL_HIGH: + sprd_eic_update(chip, offset, SPRD_EIC_DBNC_IEV, 1); + break; + case IRQ_TYPE_LEVEL_LOW: + sprd_eic_update(chip, offset, SPRD_EIC_DBNC_IEV, 0); + break; + default: + return -ENOTSUPP; + } + + irq_set_handler_locked(data, handle_level_irq); + break; + case SPRD_EIC_LATCH: + switch (flow_type) { + case IRQ_TYPE_LEVEL_HIGH: + sprd_eic_update(chip, offset, SPRD_EIC_LATCH_INTPOL, 0); + break; + case IRQ_TYPE_LEVEL_LOW: + sprd_eic_update(chip, offset, SPRD_EIC_LATCH_INTPOL, 1); + break; + default: + return -ENOTSUPP; + } + + irq_set_handler_locked(data, handle_level_irq); + break; + case SPRD_EIC_ASYNC: + switch (flow_type) { + case IRQ_TYPE_EDGE_RISING: + sprd_eic_update(chip, offset, SPRD_EIC_ASYNC_INTBOTH, 0); + sprd_eic_update(chip, offset, SPRD_EIC_ASYNC_INTMODE, 0); + sprd_eic_update(chip, offset, SPRD_EIC_ASYNC_INTPOL, 1); + irq_set_handler_locked(data, handle_edge_irq); + break; + case IRQ_TYPE_EDGE_FALLING: + sprd_eic_update(chip, offset, SPRD_EIC_ASYNC_INTBOTH, 0); + sprd_eic_update(chip, offset, SPRD_EIC_ASYNC_INTMODE, 0); + sprd_eic_update(chip, offset, SPRD_EIC_ASYNC_INTPOL, 0); + irq_set_handler_locked(data, handle_edge_irq); + break; + case IRQ_TYPE_EDGE_BOTH: + sprd_eic_update(chip, offset, SPRD_EIC_ASYNC_INTBOTH, 1); + irq_set_handler_locked(data, handle_edge_irq); + break; + case IRQ_TYPE_LEVEL_HIGH: + sprd_eic_update(chip, offset, SPRD_EIC_ASYNC_INTBOTH, 0); + sprd_eic_update(chip, offset, SPRD_EIC_ASYNC_INTMODE, 1); + sprd_eic_update(chip, offset, SPRD_EIC_ASYNC_INTPOL, 1); + irq_set_handler_locked(data, handle_level_irq); + break; + case IRQ_TYPE_LEVEL_LOW: + sprd_eic_update(chip, offset, SPRD_EIC_ASYNC_INTBOTH, 0); + sprd_eic_update(chip, offset, SPRD_EIC_ASYNC_INTMODE, 1); + sprd_eic_update(chip, offset, SPRD_EIC_ASYNC_INTPOL, 0); + irq_set_handler_locked(data, handle_level_irq); + break; + default: + return -ENOTSUPP; + } + break; + case SPRD_EIC_SYNC: + switch (flow_type) { + case IRQ_TYPE_EDGE_RISING: + sprd_eic_update(chip, offset, SPRD_EIC_SYNC_INTBOTH, 0); + sprd_eic_update(chip, offset, SPRD_EIC_SYNC_INTMODE, 0); + sprd_eic_update(chip, offset, SPRD_EIC_SYNC_INTPOL, 1); + irq_set_handler_locked(data, handle_edge_irq); + break; + case IRQ_TYPE_EDGE_FALLING: + sprd_eic_update(chip, offset, SPRD_EIC_SYNC_INTBOTH, 0); + sprd_eic_update(chip, offset, SPRD_EIC_SYNC_INTMODE, 0); + sprd_eic_update(chip, offset, SPRD_EIC_SYNC_INTPOL, 0); + irq_set_handler_locked(data, handle_edge_irq); + break; + case IRQ_TYPE_EDGE_BOTH: + sprd_eic_update(chip, offset, SPRD_EIC_SYNC_INTBOTH, 1); + irq_set_handler_locked(data, handle_edge_irq); + break; + case IRQ_TYPE_LEVEL_HIGH: + sprd_eic_update(chip, offset, SPRD_EIC_SYNC_INTBOTH, 0); + sprd_eic_update(chip, offset, SPRD_EIC_SYNC_INTMODE, 1); + sprd_eic_update(chip, offset, SPRD_EIC_SYNC_INTPOL, 1); + irq_set_handler_locked(data, handle_level_irq); + break; + case IRQ_TYPE_LEVEL_LOW: + sprd_eic_update(chip, offset, SPRD_EIC_SYNC_INTBOTH, 0); + sprd_eic_update(chip, offset, SPRD_EIC_SYNC_INTMODE, 1); + sprd_eic_update(chip, offset, SPRD_EIC_SYNC_INTPOL, 0); + irq_set_handler_locked(data, handle_level_irq); + break; + default: + return -ENOTSUPP; + } + default: + dev_err(chip->parent, "Unsupported EIC type.\n"); + return -ENOTSUPP; + } + + return 0; +} + +static int sprd_eic_match_chip_by_type(struct gpio_chip *chip, void *data) +{ + enum sprd_eic_type type = *(enum sprd_eic_type *)data; + + return !strcmp(chip->label, sprd_eic_label_name[type]); +} + +static void sprd_eic_handle_one_type(struct gpio_chip *chip) +{ + struct sprd_eic *sprd_eic = gpiochip_get_data(chip); + u32 bank, n, girq; + + for (bank = 0; bank * SPRD_EIC_PER_BANK_NR < chip->ngpio; bank++) { + void __iomem *base = sprd_eic_offset_base(sprd_eic, bank); + unsigned long reg; + + switch (sprd_eic->type) { + case SPRD_EIC_DEBOUNCE: + reg = readl_relaxed(base + SPRD_EIC_DBNC_MIS) & + SPRD_EIC_DATA_MASK; + break; + case SPRD_EIC_LATCH: + reg = readl_relaxed(base + SPRD_EIC_LATCH_INTMSK) & + SPRD_EIC_DATA_MASK; + break; + case SPRD_EIC_ASYNC: + reg = readl_relaxed(base + SPRD_EIC_ASYNC_INTMSK) & + SPRD_EIC_DATA_MASK; + break; + case SPRD_EIC_SYNC: + reg = readl_relaxed(base + SPRD_EIC_SYNC_INTMSK) & + SPRD_EIC_DATA_MASK; + break; + default: + dev_err(chip->parent, "Unsupported EIC type.\n"); + return; + } + + for_each_set_bit(n, ®, SPRD_EIC_PER_BANK_NR) { + girq = irq_find_mapping(chip->irq.domain, + bank * SPRD_EIC_PER_BANK_NR + n); + + generic_handle_irq(girq); + } + } +} + +static void sprd_eic_irq_handler(struct irq_desc *desc) +{ + struct irq_chip *ic = irq_desc_get_chip(desc); + struct gpio_chip *chip; + enum sprd_eic_type type; + + chained_irq_enter(ic, desc); + + /* + * Since the digital-chip EIC 4 sub-modules (debounce, latch, async + * and sync) share one same interrupt line, we should iterate each + * EIC module to check if there are EIC interrupts were triggered. + */ + for (type = SPRD_EIC_DEBOUNCE; type < SPRD_EIC_MAX; type++) { + chip = gpiochip_find(&type, sprd_eic_match_chip_by_type); + if (!chip) + continue; + + sprd_eic_handle_one_type(chip); + } + + chained_irq_exit(ic, desc); +} + +static int sprd_eic_probe(struct platform_device *pdev) +{ + const struct sprd_eic_variant_data *pdata; + struct gpio_irq_chip *irq; + struct sprd_eic *sprd_eic; + struct resource *res; + int ret, i; + + pdata = of_device_get_match_data(&pdev->dev); + if (!pdata) { + dev_err(&pdev->dev, "No matching driver data found.\n"); + return -EINVAL; + } + + sprd_eic = devm_kzalloc(&pdev->dev, sizeof(*sprd_eic), GFP_KERNEL); + if (!sprd_eic) + return -ENOMEM; + + spin_lock_init(&sprd_eic->lock); + sprd_eic->type = pdata->type; + + sprd_eic->irq = platform_get_irq(pdev, 0); + if (sprd_eic->irq < 0) { + dev_err(&pdev->dev, "Failed to get EIC interrupt.\n"); + return sprd_eic->irq; + } + + for (i = 0; i < SPRD_EIC_MAX_BANK; i++) { + /* + * We can have maximum 3 banks EICs, and each EIC has + * its own base address. But some platform maybe only + * have one bank EIC, thus base[1] and base[2] can be + * optional. + */ + res = platform_get_resource(pdev, IORESOURCE_MEM, i); + if (!res) + continue; + + sprd_eic->base[i] = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(sprd_eic->base[i])) + return PTR_ERR(sprd_eic->base[i]); + } + + sprd_eic->chip.label = sprd_eic_label_name[sprd_eic->type]; + sprd_eic->chip.ngpio = pdata->num_eics; + sprd_eic->chip.base = -1; + sprd_eic->chip.parent = &pdev->dev; + sprd_eic->chip.of_node = pdev->dev.of_node; + sprd_eic->chip.direction_input = sprd_eic_direction_input; + switch (sprd_eic->type) { + case SPRD_EIC_DEBOUNCE: + sprd_eic->chip.request = sprd_eic_request; + sprd_eic->chip.free = sprd_eic_free; + sprd_eic->chip.set_config = sprd_eic_set_config; + sprd_eic->chip.set = sprd_eic_set; + /* fall-through */ + case SPRD_EIC_ASYNC: + /* fall-through */ + case SPRD_EIC_SYNC: + sprd_eic->chip.get = sprd_eic_get; + break; + case SPRD_EIC_LATCH: + /* fall-through */ + default: + break; + } + + sprd_eic->intc.name = dev_name(&pdev->dev); + sprd_eic->intc.irq_ack = sprd_eic_irq_ack; + sprd_eic->intc.irq_mask = sprd_eic_irq_mask; + sprd_eic->intc.irq_unmask = sprd_eic_irq_unmask; + sprd_eic->intc.irq_set_type = sprd_eic_irq_set_type; + sprd_eic->intc.flags = IRQCHIP_SKIP_SET_WAKE; + + irq = &sprd_eic->chip.irq; + irq->chip = &sprd_eic->intc; + irq->handler = handle_bad_irq; + irq->default_type = IRQ_TYPE_NONE; + irq->parent_handler = sprd_eic_irq_handler; + irq->parent_handler_data = sprd_eic; + irq->num_parents = 1; + irq->parents = &sprd_eic->irq; + + ret = devm_gpiochip_add_data(&pdev->dev, &sprd_eic->chip, sprd_eic); + if (ret < 0) { + dev_err(&pdev->dev, "Could not register gpiochip %d.\n", ret); + return ret; + } + + platform_set_drvdata(pdev, sprd_eic); + return 0; +} + +static const struct of_device_id sprd_eic_of_match[] = { + { + .compatible = "sprd,sc9860-eic-debounce", + .data = &sc9860_eic_dbnc_data, + }, + { + .compatible = "sprd,sc9860-eic-latch", + .data = &sc9860_eic_latch_data, + }, + { + .compatible = "sprd,sc9860-eic-async", + .data = &sc9860_eic_async_data, + }, + { + .compatible = "sprd,sc9860-eic-sync", + .data = &sc9860_eic_sync_data, + }, + { + /* end of list */ + } +}; +MODULE_DEVICE_TABLE(of, sprd_eic_of_match); + +static struct platform_driver sprd_eic_driver = { + .probe = sprd_eic_probe, + .driver = { + .name = "sprd-eic", + .of_match_table = sprd_eic_of_match, + }, +}; + +module_platform_driver(sprd_eic_driver); + +MODULE_DESCRIPTION("Spreadtrum EIC driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/gpio/gpio-em.c b/drivers/gpio/gpio-em.c index b86e09e1b13b64c8ee3ac750cda326b3ea290be0..2b466b80e70ac0745747f26af76cb74a75c889ff 100644 --- a/drivers/gpio/gpio-em.c +++ b/drivers/gpio/gpio-em.c @@ -27,7 +27,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/drivers/gpio/gpio-ftgpio010.c b/drivers/gpio/gpio-ftgpio010.c index b7a3a2db699b76c6abb2df04a6e28e23b3875d88..868bf8501560de42c863959886178a3baf74c138 100644 --- a/drivers/gpio/gpio-ftgpio010.c +++ b/drivers/gpio/gpio-ftgpio010.c @@ -14,19 +14,20 @@ #include #include #include -#include #include /* GPIO registers definition */ #define GPIO_DATA_OUT 0x00 #define GPIO_DATA_IN 0x04 #define GPIO_DIR 0x08 +#define GPIO_BYPASS_IN 0x0C #define GPIO_DATA_SET 0x10 #define GPIO_DATA_CLR 0x14 #define GPIO_PULL_EN 0x18 #define GPIO_PULL_TYPE 0x1C #define GPIO_INT_EN 0x20 -#define GPIO_INT_STAT 0x24 +#define GPIO_INT_STAT_RAW 0x24 +#define GPIO_INT_STAT_MASKED 0x28 #define GPIO_INT_MASK 0x2C #define GPIO_INT_CLR 0x30 #define GPIO_INT_TYPE 0x34 @@ -147,7 +148,7 @@ static void ftgpio_gpio_irq_handler(struct irq_desc *desc) chained_irq_enter(irqchip, desc); - stat = readl(g->base + GPIO_INT_STAT); + stat = readl(g->base + GPIO_INT_STAT_RAW); if (stat) for_each_set_bit(offset, &stat, gc->ngpio) generic_handle_irq(irq_find_mapping(gc->irq.domain, diff --git a/drivers/gpio/gpio-ge.c b/drivers/gpio/gpio-ge.c index 6f5a7fe9787d2f66bd7b3015a84fc16ac92b473b..1fe2d3418f2f3464b359a4d1ecde4f355f715505 100644 --- a/drivers/gpio/gpio-ge.c +++ b/drivers/gpio/gpio-ge.c @@ -21,7 +21,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/gpio/gpio-gpio-mm.c b/drivers/gpio/gpio-gpio-mm.c index 11ade5b288f8547e817336ce8d2c35ca002ecfc8..d496cc56c2a2d03d60321980caae64fda6f5fe2a 100644 --- a/drivers/gpio/gpio-gpio-mm.c +++ b/drivers/gpio/gpio-gpio-mm.c @@ -14,6 +14,7 @@ * This driver supports the following Diamond Systems devices: GPIO-MM and * GPIO-MM-12. */ +#include #include #include #include @@ -171,6 +172,51 @@ static int gpiomm_gpio_get(struct gpio_chip *chip, unsigned int offset) return !!(port_state & mask); } +static int gpiomm_gpio_get_multiple(struct gpio_chip *chip, unsigned long *mask, + unsigned long *bits) +{ + struct gpiomm_gpio *const gpiommgpio = gpiochip_get_data(chip); + size_t i; + const size_t ports[] = { 0, 1, 2, 4, 5, 6 }; + const unsigned int gpio_reg_size = 8; + unsigned int bits_offset; + size_t word_index; + unsigned int word_offset; + unsigned long word_mask; + const unsigned long port_mask = GENMASK(gpio_reg_size - 1, 0); + unsigned long port_state; + + /* clear bits array to a clean slate */ + bitmap_zero(bits, chip->ngpio); + + /* get bits are evaluated a gpio port register at a time */ + for (i = 0; i < ARRAY_SIZE(ports); i++) { + /* gpio offset in bits array */ + bits_offset = i * gpio_reg_size; + + /* word index for bits array */ + word_index = BIT_WORD(bits_offset); + + /* gpio offset within current word of bits array */ + word_offset = bits_offset % BITS_PER_LONG; + + /* mask of get bits for current gpio within current word */ + word_mask = mask[word_index] & (port_mask << word_offset); + if (!word_mask) { + /* no get bits in this port so skip to next one */ + continue; + } + + /* read bits from current gpio port */ + port_state = inb(gpiommgpio->base + ports[i]); + + /* store acquired bits at respective bits array offset */ + bits[word_index] |= port_state << word_offset; + } + + return 0; +} + static void gpiomm_gpio_set(struct gpio_chip *chip, unsigned int offset, int value) { @@ -268,6 +314,7 @@ static int gpiomm_probe(struct device *dev, unsigned int id) gpiommgpio->chip.direction_input = gpiomm_gpio_direction_input; gpiommgpio->chip.direction_output = gpiomm_gpio_direction_output; gpiommgpio->chip.get = gpiomm_gpio_get; + gpiommgpio->chip.get_multiple = gpiomm_gpio_get_multiple; gpiommgpio->chip.set = gpiomm_gpio_set; gpiommgpio->chip.set_multiple = gpiomm_gpio_set_multiple; gpiommgpio->base = base[id]; diff --git a/drivers/gpio/gpio-grgpio.c b/drivers/gpio/gpio-grgpio.c index e2fc561f4315a9abf84cd03cf87347ffacd346f5..60a1556c570a45610c5abb99181452ea3782da95 100644 --- a/drivers/gpio/gpio-grgpio.c +++ b/drivers/gpio/gpio-grgpio.c @@ -26,9 +26,8 @@ #include #include #include -#include #include -#include +#include #include #include #include diff --git a/drivers/gpio/gpio-hlwd.c b/drivers/gpio/gpio-hlwd.c new file mode 100644 index 0000000000000000000000000000000000000000..a63136a68ba3c9ef3353c9acaa5b4cdd091297e2 --- /dev/null +++ b/drivers/gpio/gpio-hlwd.c @@ -0,0 +1,115 @@ +// SPDX-License-Identifier: GPL-2.0+ +// Copyright (C) 2008-2009 The GameCube Linux Team +// Copyright (C) 2008,2009 Albert Herranz +// Copyright (C) 2017-2018 Jonathan Neuschäfer +// +// Nintendo Wii (Hollywood) GPIO driver + +#include +#include +#include +#include +#include +#include +#include + +/* + * Register names and offsets courtesy of WiiBrew: + * https://wiibrew.org/wiki/Hardware/Hollywood_GPIOs + * + * Note that for most registers, there are two versions: + * - HW_GPIOB_* Is always accessible by the Broadway PowerPC core, but does + * always give access to all GPIO lines + * - HW_GPIO_* Is only accessible by the Broadway PowerPC code if the memory + * firewall (AHBPROT) in the Hollywood chipset has been configured to allow + * such access. + * + * The ownership of each GPIO line can be configured in the HW_GPIO_OWNER + * register: A one bit configures the line for access via the HW_GPIOB_* + * registers, a zero bit indicates access via HW_GPIO_*. This driver uses + * HW_GPIOB_*. + */ +#define HW_GPIOB_OUT 0x00 +#define HW_GPIOB_DIR 0x04 +#define HW_GPIOB_IN 0x08 +#define HW_GPIOB_INTLVL 0x0c +#define HW_GPIOB_INTFLAG 0x10 +#define HW_GPIOB_INTMASK 0x14 +#define HW_GPIOB_INMIR 0x18 +#define HW_GPIO_ENABLE 0x1c +#define HW_GPIO_OUT 0x20 +#define HW_GPIO_DIR 0x24 +#define HW_GPIO_IN 0x28 +#define HW_GPIO_INTLVL 0x2c +#define HW_GPIO_INTFLAG 0x30 +#define HW_GPIO_INTMASK 0x34 +#define HW_GPIO_INMIR 0x38 +#define HW_GPIO_OWNER 0x3c + +struct hlwd_gpio { + struct gpio_chip gpioc; + void __iomem *regs; +}; + +static int hlwd_gpio_probe(struct platform_device *pdev) +{ + struct hlwd_gpio *hlwd; + struct resource *regs_resource; + u32 ngpios; + int res; + + hlwd = devm_kzalloc(&pdev->dev, sizeof(*hlwd), GFP_KERNEL); + if (!hlwd) + return -ENOMEM; + + regs_resource = platform_get_resource(pdev, IORESOURCE_MEM, 0); + hlwd->regs = devm_ioremap_resource(&pdev->dev, regs_resource); + if (IS_ERR(hlwd->regs)) + return PTR_ERR(hlwd->regs); + + /* + * Claim all GPIOs using the OWNER register. This will not work on + * systems where the AHBPROT memory firewall hasn't been configured to + * permit PPC access to HW_GPIO_*. + * + * Note that this has to happen before bgpio_init reads the + * HW_GPIOB_OUT and HW_GPIOB_DIR, because otherwise it reads the wrong + * values. + */ + iowrite32be(0xffffffff, hlwd->regs + HW_GPIO_OWNER); + + res = bgpio_init(&hlwd->gpioc, &pdev->dev, 4, + hlwd->regs + HW_GPIOB_IN, hlwd->regs + HW_GPIOB_OUT, + NULL, hlwd->regs + HW_GPIOB_DIR, NULL, + BGPIOF_BIG_ENDIAN_BYTE_ORDER); + if (res < 0) { + dev_warn(&pdev->dev, "bgpio_init failed: %d\n", res); + return res; + } + + res = of_property_read_u32(pdev->dev.of_node, "ngpios", &ngpios); + if (res) + ngpios = 32; + hlwd->gpioc.ngpio = ngpios; + + return devm_gpiochip_add_data(&pdev->dev, &hlwd->gpioc, hlwd); +} + +static const struct of_device_id hlwd_gpio_match[] = { + { .compatible = "nintendo,hollywood-gpio", }, + {}, +}; +MODULE_DEVICE_TABLE(of, hlwd_gpio_match); + +static struct platform_driver hlwd_gpio_driver = { + .driver = { + .name = "gpio-hlwd", + .of_match_table = hlwd_gpio_match, + }, + .probe = hlwd_gpio_probe, +}; +module_platform_driver(hlwd_gpio_driver); + +MODULE_AUTHOR("Jonathan Neuschäfer "); +MODULE_DESCRIPTION("Nintendo Wii GPIO driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/gpio/gpio-htc-egpio.c b/drivers/gpio/gpio-htc-egpio.c index 271356effb2e0ed7b84f52dabcfca812f10df9f9..5163839349453115708eea5346d842d6a526ed81 100644 --- a/drivers/gpio/gpio-htc-egpio.c +++ b/drivers/gpio/gpio-htc-egpio.c @@ -18,6 +18,7 @@ #include #include #include +#include struct egpio_chip { int reg_start; diff --git a/drivers/gpio/gpio-ich.c b/drivers/gpio/gpio-ich.c index 4f6d643516b748d8f3f2ced5dd67deab3cda4295..dba3922210424a082a840f26cb2124db80f852de 100644 --- a/drivers/gpio/gpio-ich.c +++ b/drivers/gpio/gpio-ich.c @@ -23,9 +23,10 @@ #include #include #include -#include +#include #include #include +#include #define DRV_NAME "gpio_ich" @@ -131,9 +132,9 @@ static int ichx_write_bit(int reg, unsigned nr, int val, int verify) ichx_priv.gpio_base); if (val) - data |= 1 << bit; + data |= BIT(bit); else - data &= ~(1 << bit); + data &= ~BIT(bit); ICHX_WRITE(data, ichx_priv.desc->regs[reg][reg_nr], ichx_priv.gpio_base); if (reg == GPIO_LVL && ichx_priv.desc->use_outlvl_cache) @@ -166,17 +167,17 @@ static int ichx_read_bit(int reg, unsigned nr) spin_unlock_irqrestore(&ichx_priv.lock, flags); - return data & (1 << bit) ? 1 : 0; + return !!(data & BIT(bit)); } static bool ichx_gpio_check_available(struct gpio_chip *gpio, unsigned nr) { - return !!(ichx_priv.use_gpio & (1 << (nr / 32))); + return !!(ichx_priv.use_gpio & BIT(nr / 32)); } static int ichx_gpio_get_direction(struct gpio_chip *gpio, unsigned nr) { - return ichx_read_bit(GPIO_IO_SEL, nr) ? GPIOF_DIR_IN : GPIOF_DIR_OUT; + return ichx_read_bit(GPIO_IO_SEL, nr); } static int ichx_gpio_direction_input(struct gpio_chip *gpio, unsigned nr) @@ -232,12 +233,12 @@ static int ich6_gpio_get(struct gpio_chip *chip, unsigned nr) spin_lock_irqsave(&ichx_priv.lock, flags); /* GPI 0 - 15 are latched, write 1 to clear*/ - ICHX_WRITE(1 << (16 + nr), 0, ichx_priv.pm_base); + ICHX_WRITE(BIT(16 + nr), 0, ichx_priv.pm_base); data = ICHX_READ(0, ichx_priv.pm_base); spin_unlock_irqrestore(&ichx_priv.lock, flags); - return (data >> 16) & (1 << nr) ? 1 : 0; + return !!((data >> 16) & BIT(nr)); } else { return ichx_gpio_get(chip, nr); } @@ -254,7 +255,7 @@ static int ichx_gpio_request(struct gpio_chip *chip, unsigned nr) * the chipset's USE value can be trusted for this specific bit. * If it can't be trusted, assume that the pin can be used as a GPIO. */ - if (ichx_priv.desc->use_sel_ignore[nr / 32] & (1 << (nr & 0x1f))) + if (ichx_priv.desc->use_sel_ignore[nr / 32] & BIT(nr & 0x1f)) return 0; return ichx_read_bit(GPIO_USE_SEL, nr) ? 0 : -ENODEV; @@ -394,7 +395,7 @@ static int ichx_gpio_request_regions(struct device *dev, return -ENODEV; for (i = 0; i < ARRAY_SIZE(ichx_priv.desc->regs[0]); i++) { - if (!(use_gpio & (1 << i))) + if (!(use_gpio & BIT(i))) continue; if (!devm_request_region(dev, res_base->start + ichx_priv.desc->regs[0][i], diff --git a/drivers/gpio/gpio-intel-mid.c b/drivers/gpio/gpio-intel-mid.c index 629575ea46a02f688dea05ebbcf153911b216a08..028d64c2cb1e4ff1226fb9e170280433b71b73fa 100644 --- a/drivers/gpio/gpio-intel-mid.c +++ b/drivers/gpio/gpio-intel-mid.c @@ -361,10 +361,8 @@ static int intel_gpio_probe(struct pci_dev *pdev, pcim_iounmap_regions(pdev, 1 << 1); priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); - if (!priv) { - dev_err(&pdev->dev, "can't allocate chip data\n"); + if (!priv) return -ENOMEM; - } priv->reg_base = pcim_iomap_table(pdev)[0]; priv->chip.label = dev_name(&pdev->dev); diff --git a/drivers/gpio/gpio-it87.c b/drivers/gpio/gpio-it87.c index efb46edff81fb2e5c9225195017160c2ebfbf7dd..7cad14d3f1270593c811af78240dd0a6db97c611 100644 --- a/drivers/gpio/gpio-it87.c +++ b/drivers/gpio/gpio-it87.c @@ -31,7 +31,7 @@ #include #include #include -#include +#include /* Chip Id numbers */ #define NO_DEV_ID 0xffff diff --git a/drivers/gpio/gpio-janz-ttl.c b/drivers/gpio/gpio-janz-ttl.c index a8d0a6b8025a60f820a62674e6780b6b92bb0334..6b9bf8b7bf1668881f4640e6a300cd113382ce48 100644 --- a/drivers/gpio/gpio-janz-ttl.c +++ b/drivers/gpio/gpio-janz-ttl.c @@ -16,8 +16,9 @@ #include #include #include -#include +#include #include +#include #include @@ -33,9 +34,9 @@ #define MASTER_INT_CTL 0x00 #define MASTER_CONF_CTL 0x01 -#define CONF_PAE (1 << 2) -#define CONF_PBE (1 << 7) -#define CONF_PCE (1 << 4) +#define CONF_PAE BIT(2) +#define CONF_PBE BIT(7) +#define CONF_PCE BIT(4) struct ttl_control_regs { __be16 portc; @@ -74,7 +75,7 @@ static int ttl_get_value(struct gpio_chip *gpio, unsigned offset) } spin_lock(&mod->lock); - ret = *shadow & (1 << offset); + ret = *shadow & BIT(offset); spin_unlock(&mod->lock); return !!ret; } @@ -100,9 +101,9 @@ static void ttl_set_value(struct gpio_chip *gpio, unsigned offset, int value) spin_lock(&mod->lock); if (value) - *shadow |= (1 << offset); + *shadow |= BIT(offset); else - *shadow &= ~(1 << offset); + *shadow &= ~BIT(offset); iowrite16be(*shadow, port); spin_unlock(&mod->lock); diff --git a/drivers/gpio/gpio-kempld.c b/drivers/gpio/gpio-kempld.c index 701f1510328c1144f2725e8acfa379cd39ab73b0..7bb96f48ef76159ed7d02a431017dc0d0c7463f4 100644 --- a/drivers/gpio/gpio-kempld.c +++ b/drivers/gpio/gpio-kempld.c @@ -20,7 +20,7 @@ #include #include #include -#include +#include #include #define KEMPLD_GPIO_MAX_NUM 16 diff --git a/drivers/gpio/gpio-ks8695.c b/drivers/gpio/gpio-ks8695.c index 179723d02f55928df447955c898db4ec1e8de10f..55d562e1278ec5a71d1d2a588f507e9613fc1833 100644 --- a/drivers/gpio/gpio-ks8695.c +++ b/drivers/gpio/gpio-ks8695.c @@ -18,7 +18,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include +#include #include #include #include diff --git a/drivers/gpio/gpio-max3191x.c b/drivers/gpio/gpio-max3191x.c index f74b1072e84b68f36c54af8cdb1dc74812bb62ca..b5b9cb1fda5090780302a0a5074f8bc7972894c6 100644 --- a/drivers/gpio/gpio-max3191x.c +++ b/drivers/gpio/gpio-max3191x.c @@ -315,12 +315,17 @@ static void gpiod_set_array_single_value_cansleep(unsigned int ndescs, struct gpio_desc **desc, int value) { - int i, values[ndescs]; + int i, *values; + + values = kmalloc_array(ndescs, sizeof(*values), GFP_KERNEL); + if (!values) + return; for (i = 0; i < ndescs; i++) values[i] = value; gpiod_set_array_value_cansleep(ndescs, desc, values); + kfree(values); } static struct gpio_descs *devm_gpiod_get_array_optional_count( diff --git a/drivers/gpio/gpio-merrifield.c b/drivers/gpio/gpio-merrifield.c index c38624ea0251d690830a18bd711f5fd8908d2bea..97421bd4a60f979b14121eb0ca3f0d3f08bc7587 100644 --- a/drivers/gpio/gpio-merrifield.c +++ b/drivers/gpio/gpio-merrifield.c @@ -416,10 +416,8 @@ static int mrfld_gpio_probe(struct pci_dev *pdev, const struct pci_device_id *id pcim_iounmap_regions(pdev, BIT(1)); priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); - if (!priv) { - dev_err(&pdev->dev, "can't allocate chip data\n"); + if (!priv) return -ENOMEM; - } priv->dev = &pdev->dev; priv->reg_base = pcim_iomap_table(pdev)[0]; diff --git a/drivers/gpio/gpio-ml-ioh.c b/drivers/gpio/gpio-ml-ioh.c index 4b80e996d976524398e6ad484dd2f552bcdbed65..b3678bd1c120c8d18daff31f5489ba7909688dcb 100644 --- a/drivers/gpio/gpio-ml-ioh.c +++ b/drivers/gpio/gpio-ml-ioh.c @@ -445,7 +445,6 @@ static int ioh_gpio_probe(struct pci_dev *pdev, chip_save = kzalloc(sizeof(*chip) * 8, GFP_KERNEL); if (chip_save == NULL) { - dev_err(&pdev->dev, "%s : kzalloc failed", __func__); ret = -ENOMEM; goto err_kzalloc; } diff --git a/drivers/gpio/gpio-mockup.c b/drivers/gpio/gpio-mockup.c index 3a545ad1781744ac3b92f2dc49a161ec479740e1..76c2fe91a901dcd1f9b4154e3e31858a9f5e2a9a 100644 --- a/drivers/gpio/gpio-mockup.c +++ b/drivers/gpio/gpio-mockup.c @@ -2,7 +2,7 @@ * GPIO Testing Device Driver * * Copyright (C) 2014 Kamlakant Patel - * Copyright (C) 2015-2016 Bamvor Jian Zhang + * Copyright (C) 2015-2016 Bamvor Jian Zhang * Copyright (C) 2017 Bartosz Golaszewski * * This program is free software; you can redistribute it and/or modify it @@ -314,7 +314,7 @@ static int gpio_mockup_probe(struct platform_device *pdev) if (rv) return rv; - if (gpio_mockup_dbg_dir) + if (!IS_ERR_OR_NULL(gpio_mockup_dbg_dir)) gpio_mockup_debugfs_setup(dev, chip); return 0; @@ -411,7 +411,7 @@ module_init(gpio_mockup_init); module_exit(gpio_mockup_exit); MODULE_AUTHOR("Kamlakant Patel "); -MODULE_AUTHOR("Bamvor Jian Zhang "); +MODULE_AUTHOR("Bamvor Jian Zhang "); MODULE_AUTHOR("Bartosz Golaszewski "); MODULE_DESCRIPTION("GPIO Testing driver"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/gpio/gpio-omap.c b/drivers/gpio/gpio-omap.c index ab5035b968866ef8d6892d67816292582557bfe5..35971a341c402e6fad3b7886b1aa497284b5df3f 100644 --- a/drivers/gpio/gpio-omap.c +++ b/drivers/gpio/gpio-omap.c @@ -1157,11 +1157,9 @@ static int omap_gpio_probe(struct platform_device *pdev) if (!pdata) return -EINVAL; - bank = devm_kzalloc(dev, sizeof(struct gpio_bank), GFP_KERNEL); - if (!bank) { - dev_err(dev, "Memory alloc failed\n"); + bank = devm_kzalloc(dev, sizeof(*bank), GFP_KERNEL); + if (!bank) return -ENOMEM; - } irqc = devm_kzalloc(dev, sizeof(*irqc), GFP_KERNEL); if (!irqc) diff --git a/drivers/gpio/gpio-pca953x.c b/drivers/gpio/gpio-pca953x.c index a0a5f9730aa77b92ea5bc520c22f64b386edb583..d2ead4b1cf610745350171dff45c62542f1b7ff2 100644 --- a/drivers/gpio/gpio-pca953x.c +++ b/drivers/gpio/gpio-pca953x.c @@ -70,6 +70,7 @@ static const struct i2c_device_id pca953x_id[] = { { "pca9575", 16 | PCA957X_TYPE | PCA_INT, }, { "pca9698", 40 | PCA953X_TYPE, }, + { "pcal6524", 24 | PCA953X_TYPE | PCA_INT | PCA_PCAL, }, { "pcal9555a", 16 | PCA953X_TYPE | PCA_INT | PCA_PCAL, }, { "max7310", 8 | PCA953X_TYPE, }, @@ -935,6 +936,9 @@ static const struct of_device_id pca953x_dt_ids[] = { { .compatible = "nxp,pca9575", .data = OF_957X(16, PCA_INT), }, { .compatible = "nxp,pca9698", .data = OF_953X(40, 0), }, + { .compatible = "nxp,pcal6524", .data = OF_953X(24, PCA_INT), }, + { .compatible = "nxp,pcal9555a", .data = OF_953X(16, PCA_INT), }, + { .compatible = "maxim,max7310", .data = OF_953X( 8, 0), }, { .compatible = "maxim,max7312", .data = OF_953X(16, PCA_INT), }, { .compatible = "maxim,max7313", .data = OF_953X(16, PCA_INT), }, diff --git a/drivers/gpio/gpio-pci-idio-16.c b/drivers/gpio/gpio-pci-idio-16.c index 57d1b7fbf07b6035ae20be08791acb1f7e6fd02e..1948724d8c369df7baab3e889138408c1e860db8 100644 --- a/drivers/gpio/gpio-pci-idio-16.c +++ b/drivers/gpio/gpio-pci-idio-16.c @@ -11,6 +11,7 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. */ +#include #include #include #include @@ -103,6 +104,54 @@ static int idio_16_gpio_get(struct gpio_chip *chip, unsigned int offset) return !!(ioread8(&idio16gpio->reg->in8_15) & (mask >> 24)); } +static int idio_16_gpio_get_multiple(struct gpio_chip *chip, + unsigned long *mask, unsigned long *bits) +{ + struct idio_16_gpio *const idio16gpio = gpiochip_get_data(chip); + size_t i; + const unsigned int gpio_reg_size = 8; + unsigned int bits_offset; + size_t word_index; + unsigned int word_offset; + unsigned long word_mask; + const unsigned long port_mask = GENMASK(gpio_reg_size - 1, 0); + unsigned long port_state; + u8 __iomem ports[] = { + idio16gpio->reg->out0_7, idio16gpio->reg->out8_15, + idio16gpio->reg->in0_7, idio16gpio->reg->in8_15, + }; + + /* clear bits array to a clean slate */ + bitmap_zero(bits, chip->ngpio); + + /* get bits are evaluated a gpio port register at a time */ + for (i = 0; i < ARRAY_SIZE(ports); i++) { + /* gpio offset in bits array */ + bits_offset = i * gpio_reg_size; + + /* word index for bits array */ + word_index = BIT_WORD(bits_offset); + + /* gpio offset within current word of bits array */ + word_offset = bits_offset % BITS_PER_LONG; + + /* mask of get bits for current gpio within current word */ + word_mask = mask[word_index] & (port_mask << word_offset); + if (!word_mask) { + /* no get bits in this port so skip to next one */ + continue; + } + + /* read bits from current gpio port */ + port_state = ioread8(ports + i); + + /* store acquired bits at respective bits array offset */ + bits[word_index] |= port_state << word_offset; + } + + return 0; +} + static void idio_16_gpio_set(struct gpio_chip *chip, unsigned int offset, int value) { @@ -299,6 +348,7 @@ static int idio_16_probe(struct pci_dev *pdev, const struct pci_device_id *id) idio16gpio->chip.direction_input = idio_16_gpio_direction_input; idio16gpio->chip.direction_output = idio_16_gpio_direction_output; idio16gpio->chip.get = idio_16_gpio_get; + idio16gpio->chip.get_multiple = idio_16_gpio_get_multiple; idio16gpio->chip.set = idio_16_gpio_set; idio16gpio->chip.set_multiple = idio_16_gpio_set_multiple; diff --git a/drivers/gpio/gpio-pcie-idio-24.c b/drivers/gpio/gpio-pcie-idio-24.c index f666e2e69074cc382ddf5eb1319b9fc455a7a5be..835607ecf658efc95af727767f81caaaf9180d9c 100644 --- a/drivers/gpio/gpio-pcie-idio-24.c +++ b/drivers/gpio/gpio-pcie-idio-24.c @@ -15,6 +15,7 @@ * This driver supports the following ACCES devices: PCIe-IDIO-24, * PCIe-IDI-24, PCIe-IDO-24, and PCIe-IDIO-12. */ +#include #include #include #include @@ -193,6 +194,61 @@ static int idio_24_gpio_get(struct gpio_chip *chip, unsigned int offset) return !!(ioread8(&idio24gpio->reg->ttl_in0_7) & offset_mask); } +static int idio_24_gpio_get_multiple(struct gpio_chip *chip, + unsigned long *mask, unsigned long *bits) +{ + struct idio_24_gpio *const idio24gpio = gpiochip_get_data(chip); + size_t i; + const unsigned int gpio_reg_size = 8; + unsigned int bits_offset; + size_t word_index; + unsigned int word_offset; + unsigned long word_mask; + const unsigned long port_mask = GENMASK(gpio_reg_size - 1, 0); + unsigned long port_state; + u8 __iomem ports[] = { + idio24gpio->reg->out0_7, idio24gpio->reg->out8_15, + idio24gpio->reg->out16_23, idio24gpio->reg->in0_7, + idio24gpio->reg->in8_15, idio24gpio->reg->in16_23, + }; + const unsigned long out_mode_mask = BIT(1); + + /* clear bits array to a clean slate */ + bitmap_zero(bits, chip->ngpio); + + /* get bits are evaluated a gpio port register at a time */ + for (i = 0; i < ARRAY_SIZE(ports); i++) { + /* gpio offset in bits array */ + bits_offset = i * gpio_reg_size; + + /* word index for bits array */ + word_index = BIT_WORD(bits_offset); + + /* gpio offset within current word of bits array */ + word_offset = bits_offset % BITS_PER_LONG; + + /* mask of get bits for current gpio within current word */ + word_mask = mask[word_index] & (port_mask << word_offset); + if (!word_mask) { + /* no get bits in this port so skip to next one */ + continue; + } + + /* read bits from current gpio port (port 6 is TTL GPIO) */ + if (i < 6) + port_state = ioread8(ports + i); + else if (ioread8(&idio24gpio->reg->ctl) & out_mode_mask) + port_state = ioread8(&idio24gpio->reg->ttl_out0_7); + else + port_state = ioread8(&idio24gpio->reg->ttl_in0_7); + + /* store acquired bits at respective bits array offset */ + bits[word_index] |= port_state << word_offset; + } + + return 0; +} + static void idio_24_gpio_set(struct gpio_chip *chip, unsigned int offset, int value) { @@ -234,6 +290,65 @@ static void idio_24_gpio_set(struct gpio_chip *chip, unsigned int offset, raw_spin_unlock_irqrestore(&idio24gpio->lock, flags); } +static void idio_24_gpio_set_multiple(struct gpio_chip *chip, + unsigned long *mask, unsigned long *bits) +{ + struct idio_24_gpio *const idio24gpio = gpiochip_get_data(chip); + size_t i; + unsigned long bits_offset; + unsigned long gpio_mask; + const unsigned int gpio_reg_size = 8; + const unsigned long port_mask = GENMASK(gpio_reg_size, 0); + unsigned long flags; + unsigned int out_state; + u8 __iomem ports[] = { + idio24gpio->reg->out0_7, idio24gpio->reg->out8_15, + idio24gpio->reg->out16_23 + }; + const unsigned long out_mode_mask = BIT(1); + const unsigned int ttl_offset = 48; + const size_t ttl_i = BIT_WORD(ttl_offset); + const unsigned int word_offset = ttl_offset % BITS_PER_LONG; + const unsigned long ttl_mask = (mask[ttl_i] >> word_offset) & port_mask; + const unsigned long ttl_bits = (bits[ttl_i] >> word_offset) & ttl_mask; + + /* set bits are processed a gpio port register at a time */ + for (i = 0; i < ARRAY_SIZE(ports); i++) { + /* gpio offset in bits array */ + bits_offset = i * gpio_reg_size; + + /* check if any set bits for current port */ + gpio_mask = (*mask >> bits_offset) & port_mask; + if (!gpio_mask) { + /* no set bits for this port so move on to next port */ + continue; + } + + raw_spin_lock_irqsave(&idio24gpio->lock, flags); + + /* process output lines */ + out_state = ioread8(ports + i) & ~gpio_mask; + out_state |= (*bits >> bits_offset) & gpio_mask; + iowrite8(out_state, ports + i); + + raw_spin_unlock_irqrestore(&idio24gpio->lock, flags); + } + + /* check if setting TTL lines and if they are in output mode */ + if (!ttl_mask || !(ioread8(&idio24gpio->reg->ctl) & out_mode_mask)) + return; + + /* handle TTL output */ + raw_spin_lock_irqsave(&idio24gpio->lock, flags); + + /* process output lines */ + out_state = ioread8(&idio24gpio->reg->ttl_out0_7) & ~ttl_mask; + out_state |= ttl_bits; + iowrite8(out_state, &idio24gpio->reg->ttl_out0_7); + + raw_spin_unlock_irqrestore(&idio24gpio->lock, flags); +} + static void idio_24_irq_ack(struct irq_data *data) { } @@ -397,7 +512,9 @@ static int idio_24_probe(struct pci_dev *pdev, const struct pci_device_id *id) idio24gpio->chip.direction_input = idio_24_gpio_direction_input; idio24gpio->chip.direction_output = idio_24_gpio_direction_output; idio24gpio->chip.get = idio_24_gpio_get; + idio24gpio->chip.get_multiple = idio_24_gpio_get_multiple; idio24gpio->chip.set = idio_24_gpio_set; + idio24gpio->chip.set_multiple = idio_24_gpio_set_multiple; raw_spin_lock_init(&idio24gpio->lock); diff --git a/drivers/gpio/gpio-pmic-eic-sprd.c b/drivers/gpio/gpio-pmic-eic-sprd.c new file mode 100644 index 0000000000000000000000000000000000000000..66d68d99116255afd9bf46f90d4eab995157b0ab --- /dev/null +++ b/drivers/gpio/gpio-pmic-eic-sprd.c @@ -0,0 +1,330 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2018 Spreadtrum Communications Inc. + * Copyright (C) 2018 Linaro Ltd. + */ + +#include +#include +#include +#include +#include +#include +#include + +/* EIC registers definition */ +#define SPRD_PMIC_EIC_DATA 0x0 +#define SPRD_PMIC_EIC_DMSK 0x4 +#define SPRD_PMIC_EIC_IEV 0x14 +#define SPRD_PMIC_EIC_IE 0x18 +#define SPRD_PMIC_EIC_RIS 0x1c +#define SPRD_PMIC_EIC_MIS 0x20 +#define SPRD_PMIC_EIC_IC 0x24 +#define SPRD_PMIC_EIC_TRIG 0x28 +#define SPRD_PMIC_EIC_CTRL0 0x40 + +/* + * The PMIC EIC controller only has one bank, and each bank now can contain + * 16 EICs. + */ +#define SPRD_PMIC_EIC_PER_BANK_NR 16 +#define SPRD_PMIC_EIC_NR SPRD_PMIC_EIC_PER_BANK_NR +#define SPRD_PMIC_EIC_DATA_MASK GENMASK(15, 0) +#define SPRD_PMIC_EIC_BIT(x) ((x) & (SPRD_PMIC_EIC_PER_BANK_NR - 1)) +#define SPRD_PMIC_EIC_DBNC_MASK GENMASK(11, 0) + +/* + * These registers are modified under the irq bus lock and cached to avoid + * unnecessary writes in bus_sync_unlock. + */ +enum { + REG_IEV, + REG_IE, + REG_TRIG, + CACHE_NR_REGS +}; + +/** + * struct sprd_pmic_eic - PMIC EIC controller + * @chip: the gpio_chip structure. + * @intc: the irq_chip structure. + * @regmap: the regmap from the parent device. + * @offset: the EIC controller's offset address of the PMIC. + * @reg: the array to cache the EIC registers. + * @buslock: for bus lock/sync and unlock. + * @irq: the interrupt number of the PMIC EIC conteroller. + */ +struct sprd_pmic_eic { + struct gpio_chip chip; + struct irq_chip intc; + struct regmap *map; + u32 offset; + u8 reg[CACHE_NR_REGS]; + struct mutex buslock; + int irq; +}; + +static void sprd_pmic_eic_update(struct gpio_chip *chip, unsigned int offset, + u16 reg, unsigned int val) +{ + struct sprd_pmic_eic *pmic_eic = gpiochip_get_data(chip); + u32 shift = SPRD_PMIC_EIC_BIT(offset); + + regmap_update_bits(pmic_eic->map, pmic_eic->offset + reg, + BIT(shift), val << shift); +} + +static int sprd_pmic_eic_read(struct gpio_chip *chip, unsigned int offset, + u16 reg) +{ + struct sprd_pmic_eic *pmic_eic = gpiochip_get_data(chip); + u32 value; + int ret; + + ret = regmap_read(pmic_eic->map, pmic_eic->offset + reg, &value); + if (ret) + return ret; + + return !!(value & BIT(SPRD_PMIC_EIC_BIT(offset))); +} + +static int sprd_pmic_eic_request(struct gpio_chip *chip, unsigned int offset) +{ + sprd_pmic_eic_update(chip, offset, SPRD_PMIC_EIC_DMSK, 1); + return 0; +} + +static void sprd_pmic_eic_free(struct gpio_chip *chip, unsigned int offset) +{ + sprd_pmic_eic_update(chip, offset, SPRD_PMIC_EIC_DMSK, 0); +} + +static int sprd_pmic_eic_get(struct gpio_chip *chip, unsigned int offset) +{ + return sprd_pmic_eic_read(chip, offset, SPRD_PMIC_EIC_DATA); +} + +static int sprd_pmic_eic_direction_input(struct gpio_chip *chip, + unsigned int offset) +{ + /* EICs are always input, nothing need to do here. */ + return 0; +} + +static void sprd_pmic_eic_set(struct gpio_chip *chip, unsigned int offset, + int value) +{ + /* EICs are always input, nothing need to do here. */ +} + +static int sprd_pmic_eic_set_debounce(struct gpio_chip *chip, + unsigned int offset, + unsigned int debounce) +{ + struct sprd_pmic_eic *pmic_eic = gpiochip_get_data(chip); + u32 reg, value; + int ret; + + reg = SPRD_PMIC_EIC_CTRL0 + SPRD_PMIC_EIC_BIT(offset) * 0x4; + ret = regmap_read(pmic_eic->map, pmic_eic->offset + reg, &value); + if (ret) + return ret; + + value &= ~SPRD_PMIC_EIC_DBNC_MASK; + value |= (debounce / 1000) & SPRD_PMIC_EIC_DBNC_MASK; + return regmap_write(pmic_eic->map, pmic_eic->offset + reg, value); +} + +static int sprd_pmic_eic_set_config(struct gpio_chip *chip, unsigned int offset, + unsigned long config) +{ + unsigned long param = pinconf_to_config_param(config); + u32 arg = pinconf_to_config_argument(config); + + if (param == PIN_CONFIG_INPUT_DEBOUNCE) + return sprd_pmic_eic_set_debounce(chip, offset, arg); + + return -ENOTSUPP; +} + +static void sprd_pmic_eic_irq_mask(struct irq_data *data) +{ + struct gpio_chip *chip = irq_data_get_irq_chip_data(data); + struct sprd_pmic_eic *pmic_eic = gpiochip_get_data(chip); + + pmic_eic->reg[REG_IE] = 0; + pmic_eic->reg[REG_TRIG] = 0; +} + +static void sprd_pmic_eic_irq_unmask(struct irq_data *data) +{ + struct gpio_chip *chip = irq_data_get_irq_chip_data(data); + struct sprd_pmic_eic *pmic_eic = gpiochip_get_data(chip); + + pmic_eic->reg[REG_IE] = 1; + pmic_eic->reg[REG_TRIG] = 1; +} + +static int sprd_pmic_eic_irq_set_type(struct irq_data *data, + unsigned int flow_type) +{ + struct gpio_chip *chip = irq_data_get_irq_chip_data(data); + struct sprd_pmic_eic *pmic_eic = gpiochip_get_data(chip); + + switch (flow_type) { + case IRQ_TYPE_LEVEL_HIGH: + pmic_eic->reg[REG_IEV] = 1; + break; + case IRQ_TYPE_LEVEL_LOW: + pmic_eic->reg[REG_IEV] = 0; + break; + default: + return -ENOTSUPP; + } + + return 0; +} + +static void sprd_pmic_eic_bus_lock(struct irq_data *data) +{ + struct gpio_chip *chip = irq_data_get_irq_chip_data(data); + struct sprd_pmic_eic *pmic_eic = gpiochip_get_data(chip); + + mutex_lock(&pmic_eic->buslock); +} + +static void sprd_pmic_eic_bus_sync_unlock(struct irq_data *data) +{ + struct gpio_chip *chip = irq_data_get_irq_chip_data(data); + struct sprd_pmic_eic *pmic_eic = gpiochip_get_data(chip); + u32 offset = irqd_to_hwirq(data); + + /* Set irq type */ + sprd_pmic_eic_update(chip, offset, SPRD_PMIC_EIC_IEV, + pmic_eic->reg[REG_IEV]); + /* Set irq unmask */ + sprd_pmic_eic_update(chip, offset, SPRD_PMIC_EIC_IE, + pmic_eic->reg[REG_IE]); + /* Generate trigger start pulse for debounce EIC */ + sprd_pmic_eic_update(chip, offset, SPRD_PMIC_EIC_TRIG, + pmic_eic->reg[REG_TRIG]); + + mutex_unlock(&pmic_eic->buslock); +} + +static irqreturn_t sprd_pmic_eic_irq_handler(int irq, void *data) +{ + struct sprd_pmic_eic *pmic_eic = data; + struct gpio_chip *chip = &pmic_eic->chip; + unsigned long status; + u32 n, girq, val; + int ret; + + ret = regmap_read(pmic_eic->map, pmic_eic->offset + SPRD_PMIC_EIC_MIS, + &val); + if (ret) + return IRQ_RETVAL(ret); + + status = val & SPRD_PMIC_EIC_DATA_MASK; + + for_each_set_bit(n, &status, chip->ngpio) { + /* Clear the interrupt */ + sprd_pmic_eic_update(chip, n, SPRD_PMIC_EIC_IC, 1); + + girq = irq_find_mapping(chip->irq.domain, n); + handle_nested_irq(girq); + } + + return IRQ_HANDLED; +} + +static int sprd_pmic_eic_probe(struct platform_device *pdev) +{ + struct gpio_irq_chip *irq; + struct sprd_pmic_eic *pmic_eic; + int ret; + + pmic_eic = devm_kzalloc(&pdev->dev, sizeof(*pmic_eic), GFP_KERNEL); + if (!pmic_eic) + return -ENOMEM; + + mutex_init(&pmic_eic->buslock); + + pmic_eic->irq = platform_get_irq(pdev, 0); + if (pmic_eic->irq < 0) { + dev_err(&pdev->dev, "Failed to get PMIC EIC interrupt.\n"); + return pmic_eic->irq; + } + + pmic_eic->map = dev_get_regmap(pdev->dev.parent, NULL); + if (!pmic_eic->map) + return -ENODEV; + + ret = of_property_read_u32(pdev->dev.of_node, "reg", &pmic_eic->offset); + if (ret) { + dev_err(&pdev->dev, "Failed to get PMIC EIC base address.\n"); + return ret; + } + + ret = devm_request_threaded_irq(&pdev->dev, pmic_eic->irq, NULL, + sprd_pmic_eic_irq_handler, + IRQF_TRIGGER_LOW | + IRQF_ONESHOT | IRQF_NO_SUSPEND, + dev_name(&pdev->dev), pmic_eic); + if (ret) { + dev_err(&pdev->dev, "Failed to request PMIC EIC IRQ.\n"); + return ret; + } + + pmic_eic->chip.label = dev_name(&pdev->dev); + pmic_eic->chip.ngpio = SPRD_PMIC_EIC_NR; + pmic_eic->chip.base = -1; + pmic_eic->chip.parent = &pdev->dev; + pmic_eic->chip.of_node = pdev->dev.of_node; + pmic_eic->chip.direction_input = sprd_pmic_eic_direction_input; + pmic_eic->chip.request = sprd_pmic_eic_request; + pmic_eic->chip.free = sprd_pmic_eic_free; + pmic_eic->chip.set_config = sprd_pmic_eic_set_config; + pmic_eic->chip.set = sprd_pmic_eic_set; + pmic_eic->chip.get = sprd_pmic_eic_get; + + pmic_eic->intc.name = dev_name(&pdev->dev); + pmic_eic->intc.irq_mask = sprd_pmic_eic_irq_mask; + pmic_eic->intc.irq_unmask = sprd_pmic_eic_irq_unmask; + pmic_eic->intc.irq_set_type = sprd_pmic_eic_irq_set_type; + pmic_eic->intc.irq_bus_lock = sprd_pmic_eic_bus_lock; + pmic_eic->intc.irq_bus_sync_unlock = sprd_pmic_eic_bus_sync_unlock; + pmic_eic->intc.flags = IRQCHIP_SKIP_SET_WAKE; + + irq = &pmic_eic->chip.irq; + irq->chip = &pmic_eic->intc; + irq->threaded = true; + + ret = devm_gpiochip_add_data(&pdev->dev, &pmic_eic->chip, pmic_eic); + if (ret < 0) { + dev_err(&pdev->dev, "Could not register gpiochip %d.\n", ret); + return ret; + } + + platform_set_drvdata(pdev, pmic_eic); + return 0; +} + +static const struct of_device_id sprd_pmic_eic_of_match[] = { + { .compatible = "sprd,sc27xx-eic", }, + { /* end of list */ } +}; +MODULE_DEVICE_TABLE(of, sprd_pmic_eic_of_match); + +static struct platform_driver sprd_pmic_eic_driver = { + .probe = sprd_pmic_eic_probe, + .driver = { + .name = "sprd-pmic-eic", + .of_match_table = sprd_pmic_eic_of_match, + }, +}; + +module_platform_driver(sprd_pmic_eic_driver); + +MODULE_DESCRIPTION("Spreadtrum PMIC EIC driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/gpio/gpio-raspberrypi-exp.c b/drivers/gpio/gpio-raspberrypi-exp.c new file mode 100644 index 0000000000000000000000000000000000000000..d6d36d537e3736955881944cbf2aae53326841bf --- /dev/null +++ b/drivers/gpio/gpio-raspberrypi-exp.c @@ -0,0 +1,252 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Raspberry Pi 3 expander GPIO driver + * + * Uses the firmware mailbox service to communicate with the + * GPIO expander on the VPU. + * + * Copyright (C) 2017 Raspberry Pi Trading Ltd. + */ + +#include +#include +#include +#include +#include + +#define MODULE_NAME "raspberrypi-exp-gpio" +#define NUM_GPIO 8 + +#define RPI_EXP_GPIO_BASE 128 + +#define RPI_EXP_GPIO_DIR_IN 0 +#define RPI_EXP_GPIO_DIR_OUT 1 + +struct rpi_exp_gpio { + struct gpio_chip gc; + struct rpi_firmware *fw; +}; + +/* VC4 firmware mailbox interface data structures */ + +struct gpio_set_config { + u32 gpio; + u32 direction; + u32 polarity; + u32 term_en; + u32 term_pull_up; + u32 state; +}; + +struct gpio_get_config { + u32 gpio; + u32 direction; + u32 polarity; + u32 term_en; + u32 term_pull_up; +}; + +struct gpio_get_set_state { + u32 gpio; + u32 state; +}; + +static int rpi_exp_gpio_get_polarity(struct gpio_chip *gc, unsigned int off) +{ + struct rpi_exp_gpio *gpio; + struct gpio_get_config get; + int ret; + + gpio = gpiochip_get_data(gc); + + get.gpio = off + RPI_EXP_GPIO_BASE; /* GPIO to update */ + + ret = rpi_firmware_property(gpio->fw, RPI_FIRMWARE_GET_GPIO_CONFIG, + &get, sizeof(get)); + if (ret || get.gpio != 0) { + dev_err(gc->parent, "Failed to get GPIO %u config (%d %x)\n", + off, ret, get.gpio); + return ret ? ret : -EIO; + } + return get.polarity; +} + +static int rpi_exp_gpio_dir_in(struct gpio_chip *gc, unsigned int off) +{ + struct rpi_exp_gpio *gpio; + struct gpio_set_config set_in; + int ret; + + gpio = gpiochip_get_data(gc); + + set_in.gpio = off + RPI_EXP_GPIO_BASE; /* GPIO to update */ + set_in.direction = RPI_EXP_GPIO_DIR_IN; + set_in.term_en = 0; /* termination disabled */ + set_in.term_pull_up = 0; /* n/a as termination disabled */ + set_in.state = 0; /* n/a as configured as an input */ + + ret = rpi_exp_gpio_get_polarity(gc, off); + if (ret < 0) + return ret; + set_in.polarity = ret; /* Retain existing setting */ + + ret = rpi_firmware_property(gpio->fw, RPI_FIRMWARE_SET_GPIO_CONFIG, + &set_in, sizeof(set_in)); + if (ret || set_in.gpio != 0) { + dev_err(gc->parent, "Failed to set GPIO %u to input (%d %x)\n", + off, ret, set_in.gpio); + return ret ? ret : -EIO; + } + return 0; +} + +static int rpi_exp_gpio_dir_out(struct gpio_chip *gc, unsigned int off, int val) +{ + struct rpi_exp_gpio *gpio; + struct gpio_set_config set_out; + int ret; + + gpio = gpiochip_get_data(gc); + + set_out.gpio = off + RPI_EXP_GPIO_BASE; /* GPIO to update */ + set_out.direction = RPI_EXP_GPIO_DIR_OUT; + set_out.term_en = 0; /* n/a as an output */ + set_out.term_pull_up = 0; /* n/a as termination disabled */ + set_out.state = val; /* Output state */ + + ret = rpi_exp_gpio_get_polarity(gc, off); + if (ret < 0) + return ret; + set_out.polarity = ret; /* Retain existing setting */ + + ret = rpi_firmware_property(gpio->fw, RPI_FIRMWARE_SET_GPIO_CONFIG, + &set_out, sizeof(set_out)); + if (ret || set_out.gpio != 0) { + dev_err(gc->parent, "Failed to set GPIO %u to output (%d %x)\n", + off, ret, set_out.gpio); + return ret ? ret : -EIO; + } + return 0; +} + +static int rpi_exp_gpio_get_direction(struct gpio_chip *gc, unsigned int off) +{ + struct rpi_exp_gpio *gpio; + struct gpio_get_config get; + int ret; + + gpio = gpiochip_get_data(gc); + + get.gpio = off + RPI_EXP_GPIO_BASE; /* GPIO to update */ + + ret = rpi_firmware_property(gpio->fw, RPI_FIRMWARE_GET_GPIO_CONFIG, + &get, sizeof(get)); + if (ret || get.gpio != 0) { + dev_err(gc->parent, + "Failed to get GPIO %u config (%d %x)\n", off, ret, + get.gpio); + return ret ? ret : -EIO; + } + return !get.direction; +} + +static int rpi_exp_gpio_get(struct gpio_chip *gc, unsigned int off) +{ + struct rpi_exp_gpio *gpio; + struct gpio_get_set_state get; + int ret; + + gpio = gpiochip_get_data(gc); + + get.gpio = off + RPI_EXP_GPIO_BASE; /* GPIO to update */ + get.state = 0; /* storage for returned value */ + + ret = rpi_firmware_property(gpio->fw, RPI_FIRMWARE_GET_GPIO_STATE, + &get, sizeof(get)); + if (ret || get.gpio != 0) { + dev_err(gc->parent, + "Failed to get GPIO %u state (%d %x)\n", off, ret, + get.gpio); + return ret ? ret : -EIO; + } + return !!get.state; +} + +static void rpi_exp_gpio_set(struct gpio_chip *gc, unsigned int off, int val) +{ + struct rpi_exp_gpio *gpio; + struct gpio_get_set_state set; + int ret; + + gpio = gpiochip_get_data(gc); + + set.gpio = off + RPI_EXP_GPIO_BASE; /* GPIO to update */ + set.state = val; /* Output state */ + + ret = rpi_firmware_property(gpio->fw, RPI_FIRMWARE_SET_GPIO_STATE, + &set, sizeof(set)); + if (ret || set.gpio != 0) + dev_err(gc->parent, + "Failed to set GPIO %u state (%d %x)\n", off, ret, + set.gpio); +} + +static int rpi_exp_gpio_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct device_node *np = dev->of_node; + struct device_node *fw_node; + struct rpi_firmware *fw; + struct rpi_exp_gpio *rpi_gpio; + + fw_node = of_get_parent(np); + if (!fw_node) { + dev_err(dev, "Missing firmware node\n"); + return -ENOENT; + } + + fw = rpi_firmware_get(fw_node); + if (!fw) + return -EPROBE_DEFER; + + rpi_gpio = devm_kzalloc(dev, sizeof(*rpi_gpio), GFP_KERNEL); + if (!rpi_gpio) + return -ENOMEM; + + rpi_gpio->fw = fw; + rpi_gpio->gc.parent = dev; + rpi_gpio->gc.label = MODULE_NAME; + rpi_gpio->gc.owner = THIS_MODULE; + rpi_gpio->gc.of_node = np; + rpi_gpio->gc.base = -1; + rpi_gpio->gc.ngpio = NUM_GPIO; + + rpi_gpio->gc.direction_input = rpi_exp_gpio_dir_in; + rpi_gpio->gc.direction_output = rpi_exp_gpio_dir_out; + rpi_gpio->gc.get_direction = rpi_exp_gpio_get_direction; + rpi_gpio->gc.get = rpi_exp_gpio_get; + rpi_gpio->gc.set = rpi_exp_gpio_set; + rpi_gpio->gc.can_sleep = true; + + return devm_gpiochip_add_data(dev, &rpi_gpio->gc, rpi_gpio); +} + +static const struct of_device_id rpi_exp_gpio_ids[] = { + { .compatible = "raspberrypi,firmware-gpio" }, + { } +}; +MODULE_DEVICE_TABLE(of, rpi_exp_gpio_ids); + +static struct platform_driver rpi_exp_gpio_driver = { + .driver = { + .name = MODULE_NAME, + .of_match_table = of_match_ptr(rpi_exp_gpio_ids), + }, + .probe = rpi_exp_gpio_probe, +}; +module_platform_driver(rpi_exp_gpio_driver); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Dave Stevenson "); +MODULE_DESCRIPTION("Raspberry Pi 3 expander GPIO driver"); +MODULE_ALIAS("platform:rpi-exp-gpio"); diff --git a/drivers/gpio/gpio-rcar.c b/drivers/gpio/gpio-rcar.c index ebaea8b1594b7fc4919a71fdac7ed9ef8418df7b..350390c0b29098904acd0e9510b7640095f95cce 100644 --- a/drivers/gpio/gpio-rcar.c +++ b/drivers/gpio/gpio-rcar.c @@ -30,6 +30,16 @@ #include #include +struct gpio_rcar_bank_info { + u32 iointsel; + u32 inoutsel; + u32 outdt; + u32 posneg; + u32 edglevel; + u32 bothedge; + u32 intmsk; +}; + struct gpio_rcar_priv { void __iomem *base; spinlock_t lock; @@ -39,6 +49,7 @@ struct gpio_rcar_priv { unsigned int irq_parent; atomic_t wakeup_path; bool has_both_edge_trigger; + struct gpio_rcar_bank_info bank_info; }; #define IOINTSEL 0x00 /* General IO/Interrupt Switching Register */ @@ -512,17 +523,62 @@ static int gpio_rcar_remove(struct platform_device *pdev) return 0; } -static int __maybe_unused gpio_rcar_suspend(struct device *dev) +#ifdef CONFIG_PM_SLEEP +static int gpio_rcar_suspend(struct device *dev) { struct gpio_rcar_priv *p = dev_get_drvdata(dev); + p->bank_info.iointsel = gpio_rcar_read(p, IOINTSEL); + p->bank_info.inoutsel = gpio_rcar_read(p, INOUTSEL); + p->bank_info.outdt = gpio_rcar_read(p, OUTDT); + p->bank_info.intmsk = gpio_rcar_read(p, INTMSK); + p->bank_info.posneg = gpio_rcar_read(p, POSNEG); + p->bank_info.edglevel = gpio_rcar_read(p, EDGLEVEL); + if (p->has_both_edge_trigger) + p->bank_info.bothedge = gpio_rcar_read(p, BOTHEDGE); + if (atomic_read(&p->wakeup_path)) device_set_wakeup_path(dev); return 0; } -static SIMPLE_DEV_PM_OPS(gpio_rcar_pm_ops, gpio_rcar_suspend, NULL); +static int gpio_rcar_resume(struct device *dev) +{ + struct gpio_rcar_priv *p = dev_get_drvdata(dev); + unsigned int offset; + u32 mask; + + for (offset = 0; offset < p->gpio_chip.ngpio; offset++) { + mask = BIT(offset); + /* I/O pin */ + if (!(p->bank_info.iointsel & mask)) { + if (p->bank_info.inoutsel & mask) + gpio_rcar_direction_output( + &p->gpio_chip, offset, + !!(p->bank_info.outdt & mask)); + else + gpio_rcar_direction_input(&p->gpio_chip, + offset); + } else { + /* Interrupt pin */ + gpio_rcar_config_interrupt_input_mode( + p, + offset, + !(p->bank_info.posneg & mask), + !(p->bank_info.edglevel & mask), + !!(p->bank_info.bothedge & mask)); + + if (p->bank_info.intmsk & mask) + gpio_rcar_write(p, MSKCLR, mask); + } + } + + return 0; +} +#endif /* CONFIG_PM_SLEEP*/ + +static SIMPLE_DEV_PM_OPS(gpio_rcar_pm_ops, gpio_rcar_suspend, gpio_rcar_resume); static struct platform_driver gpio_rcar_device_driver = { .probe = gpio_rcar_probe, diff --git a/drivers/gpio/gpio-sprd.c b/drivers/gpio/gpio-sprd.c new file mode 100644 index 0000000000000000000000000000000000000000..55072d2b367fad89ffb099dc20abfa32381f5804 --- /dev/null +++ b/drivers/gpio/gpio-sprd.c @@ -0,0 +1,290 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2018 Spreadtrum Communications Inc. + * Copyright (C) 2018 Linaro Ltd. + */ + +#include +#include +#include +#include +#include +#include +#include + +/* GPIO registers definition */ +#define SPRD_GPIO_DATA 0x0 +#define SPRD_GPIO_DMSK 0x4 +#define SPRD_GPIO_DIR 0x8 +#define SPRD_GPIO_IS 0xc +#define SPRD_GPIO_IBE 0x10 +#define SPRD_GPIO_IEV 0x14 +#define SPRD_GPIO_IE 0x18 +#define SPRD_GPIO_RIS 0x1c +#define SPRD_GPIO_MIS 0x20 +#define SPRD_GPIO_IC 0x24 +#define SPRD_GPIO_INEN 0x28 + +/* We have 16 banks GPIOs and each bank contain 16 GPIOs */ +#define SPRD_GPIO_BANK_NR 16 +#define SPRD_GPIO_NR 256 +#define SPRD_GPIO_BANK_SIZE 0x80 +#define SPRD_GPIO_BANK_MASK GENMASK(15, 0) +#define SPRD_GPIO_BIT(x) ((x) & (SPRD_GPIO_BANK_NR - 1)) + +struct sprd_gpio { + struct gpio_chip chip; + void __iomem *base; + spinlock_t lock; + int irq; +}; + +static inline void __iomem *sprd_gpio_bank_base(struct sprd_gpio *sprd_gpio, + unsigned int bank) +{ + return sprd_gpio->base + SPRD_GPIO_BANK_SIZE * bank; +} + +static void sprd_gpio_update(struct gpio_chip *chip, unsigned int offset, + u16 reg, int val) +{ + struct sprd_gpio *sprd_gpio = gpiochip_get_data(chip); + void __iomem *base = sprd_gpio_bank_base(sprd_gpio, + offset / SPRD_GPIO_BANK_NR); + unsigned long flags; + u32 tmp; + + spin_lock_irqsave(&sprd_gpio->lock, flags); + tmp = readl_relaxed(base + reg); + + if (val) + tmp |= BIT(SPRD_GPIO_BIT(offset)); + else + tmp &= ~BIT(SPRD_GPIO_BIT(offset)); + + writel_relaxed(tmp, base + reg); + spin_unlock_irqrestore(&sprd_gpio->lock, flags); +} + +static int sprd_gpio_read(struct gpio_chip *chip, unsigned int offset, u16 reg) +{ + struct sprd_gpio *sprd_gpio = gpiochip_get_data(chip); + void __iomem *base = sprd_gpio_bank_base(sprd_gpio, + offset / SPRD_GPIO_BANK_NR); + + return !!(readl_relaxed(base + reg) & BIT(SPRD_GPIO_BIT(offset))); +} + +static int sprd_gpio_request(struct gpio_chip *chip, unsigned int offset) +{ + sprd_gpio_update(chip, offset, SPRD_GPIO_DMSK, 1); + return 0; +} + +static void sprd_gpio_free(struct gpio_chip *chip, unsigned int offset) +{ + sprd_gpio_update(chip, offset, SPRD_GPIO_DMSK, 0); +} + +static int sprd_gpio_direction_input(struct gpio_chip *chip, + unsigned int offset) +{ + sprd_gpio_update(chip, offset, SPRD_GPIO_DIR, 0); + sprd_gpio_update(chip, offset, SPRD_GPIO_INEN, 1); + return 0; +} + +static int sprd_gpio_direction_output(struct gpio_chip *chip, + unsigned int offset, int value) +{ + sprd_gpio_update(chip, offset, SPRD_GPIO_DIR, 1); + sprd_gpio_update(chip, offset, SPRD_GPIO_INEN, 0); + sprd_gpio_update(chip, offset, SPRD_GPIO_DATA, value); + return 0; +} + +static int sprd_gpio_get(struct gpio_chip *chip, unsigned int offset) +{ + return sprd_gpio_read(chip, offset, SPRD_GPIO_DATA); +} + +static void sprd_gpio_set(struct gpio_chip *chip, unsigned int offset, + int value) +{ + sprd_gpio_update(chip, offset, SPRD_GPIO_DATA, value); +} + +static void sprd_gpio_irq_mask(struct irq_data *data) +{ + struct gpio_chip *chip = irq_data_get_irq_chip_data(data); + u32 offset = irqd_to_hwirq(data); + + sprd_gpio_update(chip, offset, SPRD_GPIO_IE, 0); +} + +static void sprd_gpio_irq_ack(struct irq_data *data) +{ + struct gpio_chip *chip = irq_data_get_irq_chip_data(data); + u32 offset = irqd_to_hwirq(data); + + sprd_gpio_update(chip, offset, SPRD_GPIO_IC, 1); +} + +static void sprd_gpio_irq_unmask(struct irq_data *data) +{ + struct gpio_chip *chip = irq_data_get_irq_chip_data(data); + u32 offset = irqd_to_hwirq(data); + + sprd_gpio_update(chip, offset, SPRD_GPIO_IE, 1); +} + +static int sprd_gpio_irq_set_type(struct irq_data *data, + unsigned int flow_type) +{ + struct gpio_chip *chip = irq_data_get_irq_chip_data(data); + u32 offset = irqd_to_hwirq(data); + + switch (flow_type) { + case IRQ_TYPE_EDGE_RISING: + sprd_gpio_update(chip, offset, SPRD_GPIO_IS, 0); + sprd_gpio_update(chip, offset, SPRD_GPIO_IBE, 0); + sprd_gpio_update(chip, offset, SPRD_GPIO_IEV, 1); + irq_set_handler_locked(data, handle_edge_irq); + break; + case IRQ_TYPE_EDGE_FALLING: + sprd_gpio_update(chip, offset, SPRD_GPIO_IS, 0); + sprd_gpio_update(chip, offset, SPRD_GPIO_IBE, 0); + sprd_gpio_update(chip, offset, SPRD_GPIO_IEV, 0); + irq_set_handler_locked(data, handle_edge_irq); + break; + case IRQ_TYPE_EDGE_BOTH: + sprd_gpio_update(chip, offset, SPRD_GPIO_IS, 0); + sprd_gpio_update(chip, offset, SPRD_GPIO_IBE, 1); + irq_set_handler_locked(data, handle_edge_irq); + break; + case IRQ_TYPE_LEVEL_HIGH: + sprd_gpio_update(chip, offset, SPRD_GPIO_IS, 1); + sprd_gpio_update(chip, offset, SPRD_GPIO_IBE, 0); + sprd_gpio_update(chip, offset, SPRD_GPIO_IEV, 1); + irq_set_handler_locked(data, handle_level_irq); + break; + case IRQ_TYPE_LEVEL_LOW: + sprd_gpio_update(chip, offset, SPRD_GPIO_IS, 1); + sprd_gpio_update(chip, offset, SPRD_GPIO_IBE, 0); + sprd_gpio_update(chip, offset, SPRD_GPIO_IEV, 0); + irq_set_handler_locked(data, handle_level_irq); + break; + default: + return -EINVAL; + } + + return 0; +} + +static void sprd_gpio_irq_handler(struct irq_desc *desc) +{ + struct gpio_chip *chip = irq_desc_get_handler_data(desc); + struct irq_chip *ic = irq_desc_get_chip(desc); + struct sprd_gpio *sprd_gpio = gpiochip_get_data(chip); + u32 bank, n, girq; + + chained_irq_enter(ic, desc); + + for (bank = 0; bank * SPRD_GPIO_BANK_NR < chip->ngpio; bank++) { + void __iomem *base = sprd_gpio_bank_base(sprd_gpio, bank); + unsigned long reg = readl_relaxed(base + SPRD_GPIO_MIS) & + SPRD_GPIO_BANK_MASK; + + for_each_set_bit(n, ®, SPRD_GPIO_BANK_NR) { + girq = irq_find_mapping(chip->irq.domain, + bank * SPRD_GPIO_BANK_NR + n); + + generic_handle_irq(girq); + } + + } + chained_irq_exit(ic, desc); +} + +static struct irq_chip sprd_gpio_irqchip = { + .name = "sprd-gpio", + .irq_ack = sprd_gpio_irq_ack, + .irq_mask = sprd_gpio_irq_mask, + .irq_unmask = sprd_gpio_irq_unmask, + .irq_set_type = sprd_gpio_irq_set_type, + .flags = IRQCHIP_SKIP_SET_WAKE, +}; + +static int sprd_gpio_probe(struct platform_device *pdev) +{ + struct gpio_irq_chip *irq; + struct sprd_gpio *sprd_gpio; + struct resource *res; + int ret; + + sprd_gpio = devm_kzalloc(&pdev->dev, sizeof(*sprd_gpio), GFP_KERNEL); + if (!sprd_gpio) + return -ENOMEM; + + sprd_gpio->irq = platform_get_irq(pdev, 0); + if (sprd_gpio->irq < 0) { + dev_err(&pdev->dev, "Failed to get GPIO interrupt.\n"); + return sprd_gpio->irq; + } + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + sprd_gpio->base = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(sprd_gpio->base)) + return PTR_ERR(sprd_gpio->base); + + spin_lock_init(&sprd_gpio->lock); + + sprd_gpio->chip.label = dev_name(&pdev->dev); + sprd_gpio->chip.ngpio = SPRD_GPIO_NR; + sprd_gpio->chip.base = -1; + sprd_gpio->chip.parent = &pdev->dev; + sprd_gpio->chip.of_node = pdev->dev.of_node; + sprd_gpio->chip.request = sprd_gpio_request; + sprd_gpio->chip.free = sprd_gpio_free; + sprd_gpio->chip.get = sprd_gpio_get; + sprd_gpio->chip.set = sprd_gpio_set; + sprd_gpio->chip.direction_input = sprd_gpio_direction_input; + sprd_gpio->chip.direction_output = sprd_gpio_direction_output; + + irq = &sprd_gpio->chip.irq; + irq->chip = &sprd_gpio_irqchip; + irq->handler = handle_bad_irq; + irq->default_type = IRQ_TYPE_NONE; + irq->parent_handler = sprd_gpio_irq_handler; + irq->parent_handler_data = sprd_gpio; + irq->num_parents = 1; + irq->parents = &sprd_gpio->irq; + + ret = devm_gpiochip_add_data(&pdev->dev, &sprd_gpio->chip, sprd_gpio); + if (ret < 0) { + dev_err(&pdev->dev, "Could not register gpiochip %d\n", ret); + return ret; + } + + platform_set_drvdata(pdev, sprd_gpio); + return 0; +} + +static const struct of_device_id sprd_gpio_of_match[] = { + { .compatible = "sprd,sc9860-gpio", }, + { /* end of list */ } +}; +MODULE_DEVICE_TABLE(of, sprd_gpio_of_match); + +static struct platform_driver sprd_gpio_driver = { + .probe = sprd_gpio_probe, + .driver = { + .name = "sprd-gpio", + .of_match_table = sprd_gpio_of_match, + }, +}; + +module_platform_driver_probe(sprd_gpio_driver, sprd_gpio_probe); + +MODULE_DESCRIPTION("Spreadtrum GPIO driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/gpio/gpio-tegra.c b/drivers/gpio/gpio-tegra.c index 02fa8fe2292a13608e332d6247e9c0b55870ae98..94396caaca753e5d8a6d33c8c0ab26057980aca9 100644 --- a/drivers/gpio/gpio-tegra.c +++ b/drivers/gpio/gpio-tegra.c @@ -506,7 +506,7 @@ static int tegra_gpio_irq_set_wake(struct irq_data *d, unsigned int enable) #include #include -static int dbg_gpio_show(struct seq_file *s, void *unused) +static int tegra_dbg_gpio_show(struct seq_file *s, void *unused) { struct tegra_gpio_info *tgi = s->private; unsigned int i, j; @@ -530,22 +530,12 @@ static int dbg_gpio_show(struct seq_file *s, void *unused) return 0; } -static int dbg_gpio_open(struct inode *inode, struct file *file) -{ - return single_open(file, dbg_gpio_show, inode->i_private); -} - -static const struct file_operations debug_fops = { - .open = dbg_gpio_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; +DEFINE_SHOW_ATTRIBUTE(tegra_dbg_gpio); static void tegra_gpio_debuginit(struct tegra_gpio_info *tgi) { (void) debugfs_create_file("tegra_gpio", 0444, - NULL, tgi, &debug_fops); + NULL, tgi, &tegra_dbg_gpio_fops); } #else diff --git a/drivers/gpio/gpio-timberdale.c b/drivers/gpio/gpio-timberdale.c index 181f86ce00cd46417b717edfdcdfddfee3053db1..6520a847591068642e149e1b165d0d510ef72c65 100644 --- a/drivers/gpio/gpio-timberdale.c +++ b/drivers/gpio/gpio-timberdale.c @@ -238,11 +238,10 @@ static int timbgpio_probe(struct platform_device *pdev) return -EINVAL; } - tgpio = devm_kzalloc(dev, sizeof(struct timbgpio), GFP_KERNEL); - if (!tgpio) { - dev_err(dev, "Memory alloc failed\n"); + tgpio = devm_kzalloc(dev, sizeof(*tgpio), GFP_KERNEL); + if (!tgpio) return -EINVAL; - } + tgpio->irq_base = pdata->irq_base; spin_lock_init(&tgpio->lock); diff --git a/drivers/gpio/gpio-tps68470.c b/drivers/gpio/gpio-tps68470.c index fa2662f8b0268519868b5e18bede8923214996fd..aff6e504c6668f80feca4dc2e7cd38dc4238374e 100644 --- a/drivers/gpio/gpio-tps68470.c +++ b/drivers/gpio/gpio-tps68470.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0 /* * GPIO driver for TPS68470 PMIC * @@ -8,15 +9,6 @@ * Tianshu Qiu * Jian Xu Zheng * Yuning Pu - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation version 2. - * - * This program is distributed "as is" WITHOUT ANY WARRANTY of any - * kind, whether express or implied; without even the implied warranty - * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. */ #include diff --git a/drivers/gpio/gpio-tz1090-pdc.c b/drivers/gpio/gpio-tz1090-pdc.c deleted file mode 100644 index 5b7781741ee9a56b48a0749edee3cc00e28ee08d..0000000000000000000000000000000000000000 --- a/drivers/gpio/gpio-tz1090-pdc.c +++ /dev/null @@ -1,231 +0,0 @@ -/* - * Toumaz Xenif TZ1090 PDC GPIO handling. - * - * Copyright (C) 2012-2013 Imagination Technologies Ltd. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* Register offsets from SOC_GPIO_CONTROL0 */ -#define REG_SOC_GPIO_CONTROL0 0x00 -#define REG_SOC_GPIO_CONTROL1 0x04 -#define REG_SOC_GPIO_CONTROL2 0x08 -#define REG_SOC_GPIO_CONTROL3 0x0c -#define REG_SOC_GPIO_STATUS 0x80 - -/* PDC GPIOs go after normal GPIOs */ -#define GPIO_PDC_BASE 90 -#define GPIO_PDC_NGPIO 7 - -/* Out of PDC gpios, only syswakes have irqs */ -#define GPIO_PDC_IRQ_FIRST 2 -#define GPIO_PDC_NIRQ 3 - -/** - * struct tz1090_pdc_gpio - GPIO bank private data - * @chip: Generic GPIO chip for GPIO bank - * @reg: Base of registers, offset for this GPIO bank - * @irq: IRQ numbers for Syswake GPIOs - * - * This is the main private data for the PDC GPIO driver. It encapsulates a - * gpio_chip, and the callbacks for the gpio_chip can access the private data - * with the to_pdc() macro below. - */ -struct tz1090_pdc_gpio { - struct gpio_chip chip; - void __iomem *reg; - int irq[GPIO_PDC_NIRQ]; -}; - -/* Register accesses into the PDC MMIO area */ - -static inline void pdc_write(struct tz1090_pdc_gpio *priv, unsigned int reg_offs, - unsigned int data) -{ - writel(data, priv->reg + reg_offs); -} - -static inline unsigned int pdc_read(struct tz1090_pdc_gpio *priv, - unsigned int reg_offs) -{ - return readl(priv->reg + reg_offs); -} - -/* Generic GPIO interface */ - -static int tz1090_pdc_gpio_direction_input(struct gpio_chip *chip, - unsigned int offset) -{ - struct tz1090_pdc_gpio *priv = gpiochip_get_data(chip); - u32 value; - int lstat; - - __global_lock2(lstat); - value = pdc_read(priv, REG_SOC_GPIO_CONTROL1); - value |= BIT(offset); - pdc_write(priv, REG_SOC_GPIO_CONTROL1, value); - __global_unlock2(lstat); - - return 0; -} - -static int tz1090_pdc_gpio_direction_output(struct gpio_chip *chip, - unsigned int offset, - int output_value) -{ - struct tz1090_pdc_gpio *priv = gpiochip_get_data(chip); - u32 value; - int lstat; - - __global_lock2(lstat); - /* EXT_POWER doesn't seem to have an output value bit */ - if (offset < 6) { - value = pdc_read(priv, REG_SOC_GPIO_CONTROL0); - if (output_value) - value |= BIT(offset); - else - value &= ~BIT(offset); - pdc_write(priv, REG_SOC_GPIO_CONTROL0, value); - } - - value = pdc_read(priv, REG_SOC_GPIO_CONTROL1); - value &= ~BIT(offset); - pdc_write(priv, REG_SOC_GPIO_CONTROL1, value); - __global_unlock2(lstat); - - return 0; -} - -static int tz1090_pdc_gpio_get(struct gpio_chip *chip, unsigned int offset) -{ - struct tz1090_pdc_gpio *priv = gpiochip_get_data(chip); - return !!(pdc_read(priv, REG_SOC_GPIO_STATUS) & BIT(offset)); -} - -static void tz1090_pdc_gpio_set(struct gpio_chip *chip, unsigned int offset, - int output_value) -{ - struct tz1090_pdc_gpio *priv = gpiochip_get_data(chip); - u32 value; - int lstat; - - /* EXT_POWER doesn't seem to have an output value bit */ - if (offset >= 6) - return; - - __global_lock2(lstat); - value = pdc_read(priv, REG_SOC_GPIO_CONTROL0); - if (output_value) - value |= BIT(offset); - else - value &= ~BIT(offset); - pdc_write(priv, REG_SOC_GPIO_CONTROL0, value); - __global_unlock2(lstat); -} - -static int tz1090_pdc_gpio_to_irq(struct gpio_chip *chip, unsigned int offset) -{ - struct tz1090_pdc_gpio *priv = gpiochip_get_data(chip); - unsigned int syswake = offset - GPIO_PDC_IRQ_FIRST; - int irq; - - /* only syswakes have irqs */ - if (syswake >= GPIO_PDC_NIRQ) - return -EINVAL; - - irq = priv->irq[syswake]; - if (!irq) - return -EINVAL; - - return irq; -} - -static int tz1090_pdc_gpio_probe(struct platform_device *pdev) -{ - struct device_node *np = pdev->dev.of_node; - struct resource *res_regs; - struct tz1090_pdc_gpio *priv; - unsigned int i; - - if (!np) { - dev_err(&pdev->dev, "must be instantiated via devicetree\n"); - return -ENOENT; - } - - res_regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res_regs) { - dev_err(&pdev->dev, "cannot find registers resource\n"); - return -ENOENT; - } - - priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); - if (!priv) { - dev_err(&pdev->dev, "unable to allocate driver data\n"); - return -ENOMEM; - } - - /* Ioremap the registers */ - priv->reg = devm_ioremap(&pdev->dev, res_regs->start, - resource_size(res_regs)); - if (!priv->reg) { - dev_err(&pdev->dev, "unable to ioremap registers\n"); - return -ENOMEM; - } - - /* Set up GPIO chip */ - priv->chip.label = "tz1090-pdc-gpio"; - priv->chip.parent = &pdev->dev; - priv->chip.direction_input = tz1090_pdc_gpio_direction_input; - priv->chip.direction_output = tz1090_pdc_gpio_direction_output; - priv->chip.get = tz1090_pdc_gpio_get; - priv->chip.set = tz1090_pdc_gpio_set; - priv->chip.free = gpiochip_generic_free; - priv->chip.request = gpiochip_generic_request; - priv->chip.to_irq = tz1090_pdc_gpio_to_irq; - priv->chip.of_node = np; - - /* GPIO numbering */ - priv->chip.base = GPIO_PDC_BASE; - priv->chip.ngpio = GPIO_PDC_NGPIO; - - /* Map the syswake irqs */ - for (i = 0; i < GPIO_PDC_NIRQ; ++i) - priv->irq[i] = irq_of_parse_and_map(np, i); - - /* Add the GPIO bank */ - gpiochip_add_data(&priv->chip, priv); - - return 0; -} - -static struct of_device_id tz1090_pdc_gpio_of_match[] = { - { .compatible = "img,tz1090-pdc-gpio" }, - { }, -}; - -static struct platform_driver tz1090_pdc_gpio_driver = { - .driver = { - .name = "tz1090-pdc-gpio", - .of_match_table = tz1090_pdc_gpio_of_match, - }, - .probe = tz1090_pdc_gpio_probe, -}; - -static int __init tz1090_pdc_gpio_init(void) -{ - return platform_driver_register(&tz1090_pdc_gpio_driver); -} -subsys_initcall(tz1090_pdc_gpio_init); diff --git a/drivers/gpio/gpio-tz1090.c b/drivers/gpio/gpio-tz1090.c deleted file mode 100644 index 0bb9bb58388992967671e5487acd44c626b5d62c..0000000000000000000000000000000000000000 --- a/drivers/gpio/gpio-tz1090.c +++ /dev/null @@ -1,602 +0,0 @@ -/* - * Toumaz Xenif TZ1090 GPIO handling. - * - * Copyright (C) 2008-2013 Imagination Technologies Ltd. - * - * Based on ARM PXA code and others. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* Register offsets from bank base address */ -#define REG_GPIO_DIR 0x00 -#define REG_GPIO_IRQ_PLRT 0x20 -#define REG_GPIO_IRQ_TYPE 0x30 -#define REG_GPIO_IRQ_EN 0x40 -#define REG_GPIO_IRQ_STS 0x50 -#define REG_GPIO_BIT_EN 0x60 -#define REG_GPIO_DIN 0x70 -#define REG_GPIO_DOUT 0x80 - -/* REG_GPIO_IRQ_PLRT */ -#define REG_GPIO_IRQ_PLRT_LOW 0 -#define REG_GPIO_IRQ_PLRT_HIGH 1 - -/* REG_GPIO_IRQ_TYPE */ -#define REG_GPIO_IRQ_TYPE_LEVEL 0 -#define REG_GPIO_IRQ_TYPE_EDGE 1 - -/** - * struct tz1090_gpio_bank - GPIO bank private data - * @chip: Generic GPIO chip for GPIO bank - * @domain: IRQ domain for GPIO bank (may be NULL) - * @reg: Base of registers, offset for this GPIO bank - * @irq: IRQ number for GPIO bank - * @label: Debug GPIO bank label, used for storage of chip->label - * - * This is the main private data for a GPIO bank. It encapsulates a gpio_chip, - * and the callbacks for the gpio_chip can access the private data with the - * to_bank() macro below. - */ -struct tz1090_gpio_bank { - struct gpio_chip chip; - struct irq_domain *domain; - void __iomem *reg; - int irq; - char label[16]; -}; - -/** - * struct tz1090_gpio - Overall GPIO device private data - * @dev: Device (from platform device) - * @reg: Base of GPIO registers - * - * Represents the overall GPIO device. This structure is actually only - * temporary, and used during init. - */ -struct tz1090_gpio { - struct device *dev; - void __iomem *reg; -}; - -/** - * struct tz1090_gpio_bank_info - Temporary registration info for GPIO bank - * @priv: Overall GPIO device private data - * @node: Device tree node specific to this GPIO bank - * @index: Index of bank in range 0-2 - */ -struct tz1090_gpio_bank_info { - struct tz1090_gpio *priv; - struct device_node *node; - unsigned int index; -}; - -/* Convenience register accessors */ -static inline void tz1090_gpio_write(struct tz1090_gpio_bank *bank, - unsigned int reg_offs, u32 data) -{ - iowrite32(data, bank->reg + reg_offs); -} - -static inline u32 tz1090_gpio_read(struct tz1090_gpio_bank *bank, - unsigned int reg_offs) -{ - return ioread32(bank->reg + reg_offs); -} - -/* caller must hold LOCK2 */ -static inline void _tz1090_gpio_clear_bit(struct tz1090_gpio_bank *bank, - unsigned int reg_offs, - unsigned int offset) -{ - u32 value; - - value = tz1090_gpio_read(bank, reg_offs); - value &= ~BIT(offset); - tz1090_gpio_write(bank, reg_offs, value); -} - -static void tz1090_gpio_clear_bit(struct tz1090_gpio_bank *bank, - unsigned int reg_offs, - unsigned int offset) -{ - int lstat; - - __global_lock2(lstat); - _tz1090_gpio_clear_bit(bank, reg_offs, offset); - __global_unlock2(lstat); -} - -/* caller must hold LOCK2 */ -static inline void _tz1090_gpio_set_bit(struct tz1090_gpio_bank *bank, - unsigned int reg_offs, - unsigned int offset) -{ - u32 value; - - value = tz1090_gpio_read(bank, reg_offs); - value |= BIT(offset); - tz1090_gpio_write(bank, reg_offs, value); -} - -static void tz1090_gpio_set_bit(struct tz1090_gpio_bank *bank, - unsigned int reg_offs, - unsigned int offset) -{ - int lstat; - - __global_lock2(lstat); - _tz1090_gpio_set_bit(bank, reg_offs, offset); - __global_unlock2(lstat); -} - -/* caller must hold LOCK2 */ -static inline void _tz1090_gpio_mod_bit(struct tz1090_gpio_bank *bank, - unsigned int reg_offs, - unsigned int offset, - bool val) -{ - u32 value; - - value = tz1090_gpio_read(bank, reg_offs); - value &= ~BIT(offset); - if (val) - value |= BIT(offset); - tz1090_gpio_write(bank, reg_offs, value); -} - -static void tz1090_gpio_mod_bit(struct tz1090_gpio_bank *bank, - unsigned int reg_offs, - unsigned int offset, - bool val) -{ - int lstat; - - __global_lock2(lstat); - _tz1090_gpio_mod_bit(bank, reg_offs, offset, val); - __global_unlock2(lstat); -} - -static inline int tz1090_gpio_read_bit(struct tz1090_gpio_bank *bank, - unsigned int reg_offs, - unsigned int offset) -{ - return tz1090_gpio_read(bank, reg_offs) & BIT(offset); -} - -/* GPIO chip callbacks */ - -static int tz1090_gpio_direction_input(struct gpio_chip *chip, - unsigned int offset) -{ - struct tz1090_gpio_bank *bank = gpiochip_get_data(chip); - tz1090_gpio_set_bit(bank, REG_GPIO_DIR, offset); - - return 0; -} - -static int tz1090_gpio_direction_output(struct gpio_chip *chip, - unsigned int offset, int output_value) -{ - struct tz1090_gpio_bank *bank = gpiochip_get_data(chip); - int lstat; - - __global_lock2(lstat); - _tz1090_gpio_mod_bit(bank, REG_GPIO_DOUT, offset, output_value); - _tz1090_gpio_clear_bit(bank, REG_GPIO_DIR, offset); - __global_unlock2(lstat); - - return 0; -} - -/* - * Return GPIO level - */ -static int tz1090_gpio_get(struct gpio_chip *chip, unsigned int offset) -{ - struct tz1090_gpio_bank *bank = gpiochip_get_data(chip); - - return !!tz1090_gpio_read_bit(bank, REG_GPIO_DIN, offset); -} - -/* - * Set output GPIO level - */ -static void tz1090_gpio_set(struct gpio_chip *chip, unsigned int offset, - int output_value) -{ - struct tz1090_gpio_bank *bank = gpiochip_get_data(chip); - - tz1090_gpio_mod_bit(bank, REG_GPIO_DOUT, offset, output_value); -} - -static int tz1090_gpio_request(struct gpio_chip *chip, unsigned int offset) -{ - struct tz1090_gpio_bank *bank = gpiochip_get_data(chip); - int ret; - - ret = pinctrl_gpio_request(chip->base + offset); - if (ret) - return ret; - - tz1090_gpio_set_bit(bank, REG_GPIO_DIR, offset); - tz1090_gpio_set_bit(bank, REG_GPIO_BIT_EN, offset); - - return 0; -} - -static void tz1090_gpio_free(struct gpio_chip *chip, unsigned int offset) -{ - struct tz1090_gpio_bank *bank = gpiochip_get_data(chip); - - pinctrl_gpio_free(chip->base + offset); - - tz1090_gpio_clear_bit(bank, REG_GPIO_BIT_EN, offset); -} - -static int tz1090_gpio_to_irq(struct gpio_chip *chip, unsigned int offset) -{ - struct tz1090_gpio_bank *bank = gpiochip_get_data(chip); - - if (!bank->domain) - return -EINVAL; - - return irq_create_mapping(bank->domain, offset); -} - -/* IRQ chip handlers */ - -/* Get TZ1090 GPIO chip from irq data provided to generic IRQ callbacks */ -static inline struct tz1090_gpio_bank *irqd_to_gpio_bank(struct irq_data *data) -{ - return (struct tz1090_gpio_bank *)data->domain->host_data; -} - -static void tz1090_gpio_irq_polarity(struct tz1090_gpio_bank *bank, - unsigned int offset, unsigned int polarity) -{ - tz1090_gpio_mod_bit(bank, REG_GPIO_IRQ_PLRT, offset, polarity); -} - -static void tz1090_gpio_irq_type(struct tz1090_gpio_bank *bank, - unsigned int offset, unsigned int type) -{ - tz1090_gpio_mod_bit(bank, REG_GPIO_IRQ_TYPE, offset, type); -} - -/* set polarity to trigger on next edge, whether rising or falling */ -static void tz1090_gpio_irq_next_edge(struct tz1090_gpio_bank *bank, - unsigned int offset) -{ - unsigned int value_p, value_i; - int lstat; - - /* - * Set the GPIO's interrupt polarity to the opposite of the current - * input value so that the next edge triggers an interrupt. - */ - __global_lock2(lstat); - value_i = ~tz1090_gpio_read(bank, REG_GPIO_DIN); - value_p = tz1090_gpio_read(bank, REG_GPIO_IRQ_PLRT); - value_p &= ~BIT(offset); - value_p |= value_i & BIT(offset); - tz1090_gpio_write(bank, REG_GPIO_IRQ_PLRT, value_p); - __global_unlock2(lstat); -} - -static unsigned int gpio_startup_irq(struct irq_data *data) -{ - /* - * This warning indicates that the type of the irq hasn't been set - * before enabling the irq. This would normally be done by passing some - * trigger flags to request_irq(). - */ - WARN(irqd_get_trigger_type(data) == IRQ_TYPE_NONE, - "irq type not set before enabling gpio irq %d", data->irq); - - irq_gc_ack_clr_bit(data); - irq_gc_mask_set_bit(data); - return 0; -} - -static int gpio_set_irq_type(struct irq_data *data, unsigned int flow_type) -{ - struct tz1090_gpio_bank *bank = irqd_to_gpio_bank(data); - unsigned int type; - unsigned int polarity; - - switch (flow_type) { - case IRQ_TYPE_EDGE_BOTH: - type = REG_GPIO_IRQ_TYPE_EDGE; - polarity = REG_GPIO_IRQ_PLRT_LOW; - break; - case IRQ_TYPE_EDGE_RISING: - type = REG_GPIO_IRQ_TYPE_EDGE; - polarity = REG_GPIO_IRQ_PLRT_HIGH; - break; - case IRQ_TYPE_EDGE_FALLING: - type = REG_GPIO_IRQ_TYPE_EDGE; - polarity = REG_GPIO_IRQ_PLRT_LOW; - break; - case IRQ_TYPE_LEVEL_HIGH: - type = REG_GPIO_IRQ_TYPE_LEVEL; - polarity = REG_GPIO_IRQ_PLRT_HIGH; - break; - case IRQ_TYPE_LEVEL_LOW: - type = REG_GPIO_IRQ_TYPE_LEVEL; - polarity = REG_GPIO_IRQ_PLRT_LOW; - break; - default: - return -EINVAL; - } - - tz1090_gpio_irq_type(bank, data->hwirq, type); - irq_setup_alt_chip(data, flow_type); - - if (flow_type == IRQ_TYPE_EDGE_BOTH) - tz1090_gpio_irq_next_edge(bank, data->hwirq); - else - tz1090_gpio_irq_polarity(bank, data->hwirq, polarity); - - return 0; -} - -#ifdef CONFIG_SUSPEND -static int gpio_set_irq_wake(struct irq_data *data, unsigned int on) -{ - struct tz1090_gpio_bank *bank = irqd_to_gpio_bank(data); - -#ifdef CONFIG_PM_DEBUG - pr_info("irq_wake irq%d state:%d\n", data->irq, on); -#endif - - /* wake on gpio block interrupt */ - return irq_set_irq_wake(bank->irq, on); -} -#else -#define gpio_set_irq_wake NULL -#endif - -static void tz1090_gpio_irq_handler(struct irq_desc *desc) -{ - irq_hw_number_t hw; - unsigned int irq_stat, irq_no; - struct tz1090_gpio_bank *bank; - struct irq_desc *child_desc; - - bank = (struct tz1090_gpio_bank *)irq_desc_get_handler_data(desc); - irq_stat = tz1090_gpio_read(bank, REG_GPIO_DIR) & - tz1090_gpio_read(bank, REG_GPIO_IRQ_STS) & - tz1090_gpio_read(bank, REG_GPIO_IRQ_EN) & - 0x3FFFFFFF; /* 30 bits only */ - - for (hw = 0; irq_stat; irq_stat >>= 1, ++hw) { - if (!(irq_stat & 1)) - continue; - - irq_no = irq_linear_revmap(bank->domain, hw); - child_desc = irq_to_desc(irq_no); - - /* Toggle edge for pin with both edges triggering enabled */ - if (irqd_get_trigger_type(&child_desc->irq_data) - == IRQ_TYPE_EDGE_BOTH) - tz1090_gpio_irq_next_edge(bank, hw); - - generic_handle_irq_desc(child_desc); - } -} - -static int tz1090_gpio_bank_probe(struct tz1090_gpio_bank_info *info) -{ - struct device_node *np = info->node; - struct device *dev = info->priv->dev; - struct tz1090_gpio_bank *bank; - struct irq_chip_generic *gc; - int err; - - bank = devm_kzalloc(dev, sizeof(*bank), GFP_KERNEL); - if (!bank) { - dev_err(dev, "unable to allocate driver data\n"); - return -ENOMEM; - } - - /* Offset the main registers to the first register in this bank */ - bank->reg = info->priv->reg + info->index * 4; - - /* Set up GPIO chip */ - snprintf(bank->label, sizeof(bank->label), "tz1090-gpio-%u", - info->index); - bank->chip.label = bank->label; - bank->chip.parent = dev; - bank->chip.direction_input = tz1090_gpio_direction_input; - bank->chip.direction_output = tz1090_gpio_direction_output; - bank->chip.get = tz1090_gpio_get; - bank->chip.set = tz1090_gpio_set; - bank->chip.free = tz1090_gpio_free; - bank->chip.request = tz1090_gpio_request; - bank->chip.to_irq = tz1090_gpio_to_irq; - bank->chip.of_node = np; - - /* GPIO numbering from 0 */ - bank->chip.base = info->index * 30; - bank->chip.ngpio = 30; - - /* Add the GPIO bank */ - gpiochip_add_data(&bank->chip, bank); - - /* Get the GPIO bank IRQ if provided */ - bank->irq = irq_of_parse_and_map(np, 0); - - /* The interrupt is optional (it may be used by another core on chip) */ - if (!bank->irq) { - dev_info(dev, "IRQ not provided for bank %u, IRQs disabled\n", - info->index); - return 0; - } - - dev_info(dev, "Setting up IRQs for GPIO bank %u\n", - info->index); - - /* - * Initialise all interrupts to disabled so we don't get - * spurious ones on a dirty boot and hit the BUG_ON in the - * handler. - */ - tz1090_gpio_write(bank, REG_GPIO_IRQ_EN, 0); - - /* Add a virtual IRQ for each GPIO */ - bank->domain = irq_domain_add_linear(np, - bank->chip.ngpio, - &irq_generic_chip_ops, - bank); - - /* Set up a generic irq chip with 2 chip types (level and edge) */ - err = irq_alloc_domain_generic_chips(bank->domain, bank->chip.ngpio, 2, - bank->label, handle_bad_irq, 0, 0, - IRQ_GC_INIT_NESTED_LOCK); - if (err) { - dev_info(dev, - "irq_alloc_domain_generic_chips failed for bank %u, IRQs disabled\n", - info->index); - irq_domain_remove(bank->domain); - return 0; - } - - gc = irq_get_domain_generic_chip(bank->domain, 0); - gc->reg_base = bank->reg; - - /* level chip type */ - gc->chip_types[0].type = IRQ_TYPE_LEVEL_MASK; - gc->chip_types[0].handler = handle_level_irq; - gc->chip_types[0].regs.ack = REG_GPIO_IRQ_STS; - gc->chip_types[0].regs.mask = REG_GPIO_IRQ_EN; - gc->chip_types[0].chip.irq_startup = gpio_startup_irq; - gc->chip_types[0].chip.irq_ack = irq_gc_ack_clr_bit; - gc->chip_types[0].chip.irq_mask = irq_gc_mask_clr_bit; - gc->chip_types[0].chip.irq_unmask = irq_gc_mask_set_bit; - gc->chip_types[0].chip.irq_set_type = gpio_set_irq_type; - gc->chip_types[0].chip.irq_set_wake = gpio_set_irq_wake; - gc->chip_types[0].chip.flags = IRQCHIP_MASK_ON_SUSPEND; - - /* edge chip type */ - gc->chip_types[1].type = IRQ_TYPE_EDGE_BOTH; - gc->chip_types[1].handler = handle_edge_irq; - gc->chip_types[1].regs.ack = REG_GPIO_IRQ_STS; - gc->chip_types[1].regs.mask = REG_GPIO_IRQ_EN; - gc->chip_types[1].chip.irq_startup = gpio_startup_irq; - gc->chip_types[1].chip.irq_ack = irq_gc_ack_clr_bit; - gc->chip_types[1].chip.irq_mask = irq_gc_mask_clr_bit; - gc->chip_types[1].chip.irq_unmask = irq_gc_mask_set_bit; - gc->chip_types[1].chip.irq_set_type = gpio_set_irq_type; - gc->chip_types[1].chip.irq_set_wake = gpio_set_irq_wake; - gc->chip_types[1].chip.flags = IRQCHIP_MASK_ON_SUSPEND; - - /* Setup chained handler for this GPIO bank */ - irq_set_chained_handler_and_data(bank->irq, tz1090_gpio_irq_handler, - bank); - - return 0; -} - -static void tz1090_gpio_register_banks(struct tz1090_gpio *priv) -{ - struct device_node *np = priv->dev->of_node; - struct device_node *node; - - for_each_available_child_of_node(np, node) { - struct tz1090_gpio_bank_info info; - u32 addr; - int ret; - - ret = of_property_read_u32(node, "reg", &addr); - if (ret) { - dev_err(priv->dev, "invalid reg on %pOF\n", node); - continue; - } - if (addr >= 3) { - dev_err(priv->dev, "index %u in %pOF out of range\n", - addr, node); - continue; - } - - info.index = addr; - info.node = of_node_get(node); - info.priv = priv; - - ret = tz1090_gpio_bank_probe(&info); - if (ret) { - dev_err(priv->dev, "failure registering %pOF\n", node); - of_node_put(node); - continue; - } - } -} - -static int tz1090_gpio_probe(struct platform_device *pdev) -{ - struct device_node *np = pdev->dev.of_node; - struct resource *res_regs; - struct tz1090_gpio priv; - - if (!np) { - dev_err(&pdev->dev, "must be instantiated via devicetree\n"); - return -ENOENT; - } - - res_regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res_regs) { - dev_err(&pdev->dev, "cannot find registers resource\n"); - return -ENOENT; - } - - priv.dev = &pdev->dev; - - /* Ioremap the registers */ - priv.reg = devm_ioremap(&pdev->dev, res_regs->start, - resource_size(res_regs)); - if (!priv.reg) { - dev_err(&pdev->dev, "unable to ioremap registers\n"); - return -ENOMEM; - } - - /* Look for banks */ - tz1090_gpio_register_banks(&priv); - - return 0; -} - -static struct of_device_id tz1090_gpio_of_match[] = { - { .compatible = "img,tz1090-gpio" }, - { }, -}; - -static struct platform_driver tz1090_gpio_driver = { - .driver = { - .name = "tz1090-gpio", - .of_match_table = tz1090_gpio_of_match, - }, - .probe = tz1090_gpio_probe, -}; - -static int __init tz1090_gpio_init(void) -{ - return platform_driver_register(&tz1090_gpio_driver); -} -subsys_initcall(tz1090_gpio_init); diff --git a/drivers/gpio/gpio-wm831x.c b/drivers/gpio/gpio-wm831x.c index 938bbe3f831ca0b6511ba913267ae62dbc903301..324813e8304e586bf02786ef16d9dcb41e9ba52c 100644 --- a/drivers/gpio/gpio-wm831x.c +++ b/drivers/gpio/gpio-wm831x.c @@ -182,7 +182,7 @@ static void wm831x_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip) dev_err(wm831x->dev, "GPIO control %d read failed: %d\n", gpio, reg); - seq_printf(s, "\n"); + seq_putc(s, '\n'); continue; } diff --git a/drivers/gpio/gpio-ws16c48.c b/drivers/gpio/gpio-ws16c48.c index 746648244bf322aecf0ca5143a3ce47f739f723b..c7028eb0b8e11e07af454b7be6118160fbb012de 100644 --- a/drivers/gpio/gpio-ws16c48.c +++ b/drivers/gpio/gpio-ws16c48.c @@ -11,6 +11,7 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. */ +#include #include #include #include @@ -129,6 +130,51 @@ static int ws16c48_gpio_get(struct gpio_chip *chip, unsigned offset) return !!(port_state & mask); } +static int ws16c48_gpio_get_multiple(struct gpio_chip *chip, + unsigned long *mask, unsigned long *bits) +{ + struct ws16c48_gpio *const ws16c48gpio = gpiochip_get_data(chip); + const unsigned int gpio_reg_size = 8; + size_t i; + const size_t num_ports = chip->ngpio / gpio_reg_size; + unsigned int bits_offset; + size_t word_index; + unsigned int word_offset; + unsigned long word_mask; + const unsigned long port_mask = GENMASK(gpio_reg_size - 1, 0); + unsigned long port_state; + + /* clear bits array to a clean slate */ + bitmap_zero(bits, chip->ngpio); + + /* get bits are evaluated a gpio port register at a time */ + for (i = 0; i < num_ports; i++) { + /* gpio offset in bits array */ + bits_offset = i * gpio_reg_size; + + /* word index for bits array */ + word_index = BIT_WORD(bits_offset); + + /* gpio offset within current word of bits array */ + word_offset = bits_offset % BITS_PER_LONG; + + /* mask of get bits for current gpio within current word */ + word_mask = mask[word_index] & (port_mask << word_offset); + if (!word_mask) { + /* no get bits in this port so skip to next one */ + continue; + } + + /* read bits from current gpio port */ + port_state = inb(ws16c48gpio->base + i); + + /* store acquired bits at respective bits array offset */ + bits[word_index] |= port_state << word_offset; + } + + return 0; +} + static void ws16c48_gpio_set(struct gpio_chip *chip, unsigned offset, int value) { struct ws16c48_gpio *const ws16c48gpio = gpiochip_get_data(chip); @@ -383,6 +429,7 @@ static int ws16c48_probe(struct device *dev, unsigned int id) ws16c48gpio->chip.direction_input = ws16c48_gpio_direction_input; ws16c48gpio->chip.direction_output = ws16c48_gpio_direction_output; ws16c48gpio->chip.get = ws16c48_gpio_get; + ws16c48gpio->chip.get_multiple = ws16c48_gpio_get_multiple; ws16c48gpio->chip.set = ws16c48_gpio_set; ws16c48gpio->chip.set_multiple = ws16c48_gpio_set_multiple; ws16c48gpio->base = base[id]; diff --git a/drivers/gpio/gpio-xra1403.c b/drivers/gpio/gpio-xra1403.c index 0230e4b7a2fb48d5d77532eede829e4e2660fd1e..8d4c8e99b251968a4ece65012a97b72ac0ec6e40 100644 --- a/drivers/gpio/gpio-xra1403.c +++ b/drivers/gpio/gpio-xra1403.c @@ -126,11 +126,16 @@ static void xra1403_dbg_show(struct seq_file *s, struct gpio_chip *chip) { int reg; struct xra1403 *xra = gpiochip_get_data(chip); - int value[xra1403_regmap_cfg.max_register]; + int *value; int i; unsigned int gcr; unsigned int gsr; + value = kmalloc_array(xra1403_regmap_cfg.max_register, sizeof(*value), + GFP_KERNEL); + if (!value) + return; + seq_puts(s, "xra reg:"); for (reg = 0; reg <= xra1403_regmap_cfg.max_register; reg++) seq_printf(s, " %2.2x", reg); @@ -154,6 +159,7 @@ static void xra1403_dbg_show(struct seq_file *s, struct gpio_chip *chip) (gcr & BIT(i)) ? "in" : "out", (gsr & BIT(i)) ? "hi" : "lo"); } + kfree(value); } #else #define xra1403_dbg_show NULL diff --git a/drivers/gpio/gpiolib-of.c b/drivers/gpio/gpiolib-of.c index 84e5a9df234433b430fc950a04d80dc9cd43bad8..ed81d9a6316f4b9f588498e22ffb7a534b976a10 100644 --- a/drivers/gpio/gpiolib-of.c +++ b/drivers/gpio/gpiolib-of.c @@ -511,6 +511,28 @@ void of_mm_gpiochip_remove(struct of_mm_gpio_chip *mm_gc) } EXPORT_SYMBOL(of_mm_gpiochip_remove); +static void of_gpiochip_init_valid_mask(struct gpio_chip *chip) +{ + int len, i; + u32 start, count; + struct device_node *np = chip->of_node; + + len = of_property_count_u32_elems(np, "gpio-reserved-ranges"); + if (len < 0 || len % 2 != 0) + return; + + for (i = 0; i < len; i += 2) { + of_property_read_u32_index(np, "gpio-reserved-ranges", + i, &start); + of_property_read_u32_index(np, "gpio-reserved-ranges", + i + 1, &count); + if (start >= chip->ngpio || start + count >= chip->ngpio) + continue; + + bitmap_clear(chip->valid_mask, start, count); + } +}; + #ifdef CONFIG_PINCTRL static int of_gpiochip_add_pin_range(struct gpio_chip *chip) { @@ -615,6 +637,8 @@ int of_gpiochip_add(struct gpio_chip *chip) if (chip->of_gpio_n_cells > MAX_PHANDLE_ARGS) return -EINVAL; + of_gpiochip_init_valid_mask(chip); + status = of_gpiochip_add_pin_range(chip); if (status) return status; diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index d66de67ef307cef79a03fae9fb586fb3f55be0bf..43aeb07343ec76fe3eeef0283d8d52327530bfdf 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -337,6 +337,57 @@ static int gpiochip_set_desc_names(struct gpio_chip *gc) return 0; } +static unsigned long *gpiochip_allocate_mask(struct gpio_chip *chip) +{ + unsigned long *p; + + p = kmalloc_array(BITS_TO_LONGS(chip->ngpio), sizeof(*p), GFP_KERNEL); + if (!p) + return NULL; + + /* Assume by default all GPIOs are valid */ + bitmap_fill(p, chip->ngpio); + + return p; +} + +static int gpiochip_init_valid_mask(struct gpio_chip *gpiochip) +{ +#ifdef CONFIG_OF_GPIO + int size; + struct device_node *np = gpiochip->of_node; + + size = of_property_count_u32_elems(np, "gpio-reserved-ranges"); + if (size > 0 && size % 2 == 0) + gpiochip->need_valid_mask = true; +#endif + + if (!gpiochip->need_valid_mask) + return 0; + + gpiochip->valid_mask = gpiochip_allocate_mask(gpiochip); + if (!gpiochip->valid_mask) + return -ENOMEM; + + return 0; +} + +static void gpiochip_free_valid_mask(struct gpio_chip *gpiochip) +{ + kfree(gpiochip->valid_mask); + gpiochip->valid_mask = NULL; +} + +bool gpiochip_line_is_valid(const struct gpio_chip *gpiochip, + unsigned int offset) +{ + /* No mask means all valid */ + if (likely(!gpiochip->valid_mask)) + return true; + return test_bit(offset, gpiochip->valid_mask); +} +EXPORT_SYMBOL_GPL(gpiochip_line_is_valid); + /* * GPIO line handle management */ @@ -1261,6 +1312,10 @@ int gpiochip_add_data_with_key(struct gpio_chip *chip, void *data, if (status) goto err_remove_from_list; + status = gpiochip_init_valid_mask(chip); + if (status) + goto err_remove_irqchip_mask; + status = gpiochip_add_irqchip(chip, lock_key, request_key); if (status) goto err_remove_chip; @@ -1290,6 +1345,8 @@ int gpiochip_add_data_with_key(struct gpio_chip *chip, void *data, acpi_gpiochip_remove(chip); gpiochip_free_hogs(chip); of_gpiochip_remove(chip); + gpiochip_free_valid_mask(chip); +err_remove_irqchip_mask: gpiochip_irqchip_free_valid_mask(chip); err_remove_from_list: spin_lock_irqsave(&gpio_lock, flags); @@ -1346,6 +1403,7 @@ void gpiochip_remove(struct gpio_chip *chip) acpi_gpiochip_remove(chip); gpiochip_remove_pin_ranges(chip); of_gpiochip_remove(chip); + gpiochip_free_valid_mask(chip); /* * We accept no more calls into the driver from this point, so * NULL the driver data pointer @@ -1506,14 +1564,10 @@ static int gpiochip_irqchip_init_valid_mask(struct gpio_chip *gpiochip) if (!gpiochip->irq.need_valid_mask) return 0; - gpiochip->irq.valid_mask = kcalloc(BITS_TO_LONGS(gpiochip->ngpio), - sizeof(long), GFP_KERNEL); + gpiochip->irq.valid_mask = gpiochip_allocate_mask(gpiochip); if (!gpiochip->irq.valid_mask) return -ENOMEM; - /* Assume by default all GPIOs are valid */ - bitmap_fill(gpiochip->irq.valid_mask, gpiochip->ngpio); - return 0; } @@ -1526,6 +1580,8 @@ static void gpiochip_irqchip_free_valid_mask(struct gpio_chip *gpiochip) bool gpiochip_irqchip_irq_valid(const struct gpio_chip *gpiochip, unsigned int offset) { + if (!gpiochip_line_is_valid(gpiochip, offset)) + return false; /* No mask means all valid */ if (likely(!gpiochip->irq.valid_mask)) return true; @@ -3689,7 +3745,7 @@ struct gpio_desc *__must_check gpiod_get_index(struct device *dev, } if (IS_ERR(desc)) { - dev_dbg(dev, "lookup for GPIO %s failed\n", con_id); + dev_dbg(dev, "No GPIO consumer %s found\n", con_id); return desc; } diff --git a/drivers/gpio/gpiolib.h b/drivers/gpio/gpiolib.h index b17ec6795c81e921460b4b33fd5c2889ebbf797b..ad456b6f9d8b5e3ea9859e8cef73eacee431705b 100644 --- a/drivers/gpio/gpiolib.h +++ b/drivers/gpio/gpiolib.h @@ -13,13 +13,13 @@ #define GPIOLIB_H #include +#include /* for enum gpiod_flags */ #include #include #include #include enum of_gpio_flags; -enum gpiod_flags; enum gpio_lookup_flags; struct acpi_device; diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig index 914b6f849a298b7bc244b81f646539105b73e724..15606f237480dacbd00a151d6a76d86e0107e5e9 100644 --- a/drivers/iio/adc/Kconfig +++ b/drivers/iio/adc/Kconfig @@ -697,7 +697,8 @@ config STM32_DFSDM_ADC config STX104 tristate "Apex Embedded Systems STX104 driver" - depends on PC104 && X86 && ISA_BUS_API + depends on PC104 && X86 + select ISA_BUS_API select GPIOLIB help Say yes here to build support for the Apex Embedded Systems STX104 diff --git a/drivers/iio/counter/Kconfig b/drivers/iio/counter/Kconfig index 474e1ac4e7c0b8bdc908f2fd88d0768b46126dee..bf1e559ad7cd278b9dfa65b0c83eb3a8eb9e4552 100644 --- a/drivers/iio/counter/Kconfig +++ b/drivers/iio/counter/Kconfig @@ -7,7 +7,8 @@ menu "Counters" config 104_QUAD_8 tristate "ACCES 104-QUAD-8 driver" - depends on PC104 && X86 && ISA_BUS_API + depends on PC104 && X86 + select ISA_BUS_API help Say yes here to build support for the ACCES 104-QUAD-8 quadrature encoder counter/interface device family (104-QUAD-8, 104-QUAD-4). diff --git a/drivers/iio/dac/Kconfig b/drivers/iio/dac/Kconfig index 965d5c0d24683982cdc82fa78e11f2e3044bb76f..76db0768e4542af29343c985997cb836be414f33 100644 --- a/drivers/iio/dac/Kconfig +++ b/drivers/iio/dac/Kconfig @@ -195,7 +195,8 @@ config AD7303 config CIO_DAC tristate "Measurement Computing CIO-DAC IIO driver" - depends on X86 && ISA_BUS_API + depends on X86 && (ISA_BUS || PC104) + select ISA_BUS_API help Say yes here to build support for the Measurement Computing CIO-DAC analog output device family (CIO-DAC16, CIO-DAC08, PC104-DAC06). The diff --git a/drivers/pinctrl/qcom/pinctrl-msm.c b/drivers/pinctrl/qcom/pinctrl-msm.c index 95e5c5ea40af212a271fe62155687743198c4518..ad80a17c9990d76efe1cb725bd26a38f310967c3 100644 --- a/drivers/pinctrl/qcom/pinctrl-msm.c +++ b/drivers/pinctrl/qcom/pinctrl-msm.c @@ -105,6 +105,14 @@ static const struct pinctrl_ops msm_pinctrl_ops = { .dt_free_map = pinctrl_utils_free_map, }; +static int msm_pinmux_request(struct pinctrl_dev *pctldev, unsigned offset) +{ + struct msm_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev); + struct gpio_chip *chip = &pctrl->chip; + + return gpiochip_line_is_valid(chip, offset) ? 0 : -EINVAL; +} + static int msm_get_functions_count(struct pinctrl_dev *pctldev) { struct msm_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev); @@ -166,6 +174,7 @@ static int msm_pinmux_set_mux(struct pinctrl_dev *pctldev, } static const struct pinmux_ops msm_pinmux_ops = { + .request = msm_pinmux_request, .get_functions_count = msm_get_functions_count, .get_function_name = msm_get_function_name, .get_function_groups = msm_get_function_groups, @@ -506,6 +515,9 @@ static void msm_gpio_dbg_show_one(struct seq_file *s, "pull up" }; + if (!gpiochip_line_is_valid(chip, offset)) + return; + g = &pctrl->soc->groups[offset]; ctl_reg = readl(pctrl->regs + g->ctl_reg); @@ -517,6 +529,7 @@ static void msm_gpio_dbg_show_one(struct seq_file *s, seq_printf(s, " %-8s: %-3s %d", g->name, is_out ? "out" : "in", func); seq_printf(s, " %dmA", msm_regval_to_drive(drive)); seq_printf(s, " %s", pulls[pull]); + seq_puts(s, "\n"); } static void msm_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip) @@ -524,10 +537,8 @@ static void msm_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip) unsigned gpio = chip->base; unsigned i; - for (i = 0; i < chip->ngpio; i++, gpio++) { + for (i = 0; i < chip->ngpio; i++, gpio++) msm_gpio_dbg_show_one(s, NULL, chip, i, gpio); - seq_puts(s, "\n"); - } } #else @@ -808,6 +819,46 @@ static void msm_gpio_irq_handler(struct irq_desc *desc) chained_irq_exit(chip, desc); } +static int msm_gpio_init_valid_mask(struct gpio_chip *chip, + struct msm_pinctrl *pctrl) +{ + int ret; + unsigned int len, i; + unsigned int max_gpios = pctrl->soc->ngpios; + u16 *tmp; + + /* The number of GPIOs in the ACPI tables */ + len = ret = device_property_read_u16_array(pctrl->dev, "gpios", NULL, 0); + if (ret < 0) + return 0; + + if (ret > max_gpios) + return -EINVAL; + + tmp = kmalloc_array(len, sizeof(*tmp), GFP_KERNEL); + if (!tmp) + return -ENOMEM; + + ret = device_property_read_u16_array(pctrl->dev, "gpios", tmp, len); + if (ret < 0) { + dev_err(pctrl->dev, "could not read list of GPIOs\n"); + goto out; + } + + bitmap_zero(chip->valid_mask, max_gpios); + for (i = 0; i < len; i++) + set_bit(tmp[i], chip->valid_mask); + +out: + kfree(tmp); + return ret; +} + +static bool msm_gpio_needs_valid_mask(struct msm_pinctrl *pctrl) +{ + return device_property_read_u16_array(pctrl->dev, "gpios", NULL, 0) > 0; +} + static int msm_gpio_init(struct msm_pinctrl *pctrl) { struct gpio_chip *chip; @@ -824,6 +875,7 @@ static int msm_gpio_init(struct msm_pinctrl *pctrl) chip->parent = pctrl->dev; chip->owner = THIS_MODULE; chip->of_node = pctrl->dev->of_node; + chip->need_valid_mask = msm_gpio_needs_valid_mask(pctrl); ret = gpiochip_add_data(&pctrl->chip, pctrl); if (ret) { @@ -831,6 +883,13 @@ static int msm_gpio_init(struct msm_pinctrl *pctrl) return ret; } + ret = msm_gpio_init_valid_mask(chip, pctrl); + if (ret) { + dev_err(pctrl->dev, "Failed to setup irq valid bits\n"); + gpiochip_remove(&pctrl->chip); + return ret; + } + ret = gpiochip_add_pin_range(&pctrl->chip, dev_name(pctrl->dev), 0, 0, chip->ngpio); if (ret) { dev_err(pctrl->dev, "Failed to add pin range\n"); diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index de6847d7b4e38d7d0d23f6f62fc18cdc30dddde7..66a7f5a2f474e1848b127c2c310979ef7a04c06f 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig @@ -866,7 +866,8 @@ config ALIM7101_WDT config EBC_C384_WDT tristate "WinSystems EBC-C384 Watchdog Timer" - depends on X86 && ISA_BUS_API + depends on X86 + select ISA_BUS_API select WATCHDOG_CORE help Enables watchdog timer support for the watchdog timer on the diff --git a/include/linux/gpio/driver.h b/include/linux/gpio/driver.h index 1ba9a331ec515d5a26d994eb512fa712db3f6b15..5382b5183b7e1c39147100588b5602bc721ee47e 100644 --- a/include/linux/gpio/driver.h +++ b/include/linux/gpio/driver.h @@ -288,6 +288,21 @@ struct gpio_chip { struct gpio_irq_chip irq; #endif + /** + * @need_valid_mask: + * + * If set core allocates @valid_mask with all bits set to one. + */ + bool need_valid_mask; + + /** + * @valid_mask: + * + * If not %NULL holds bitmask of GPIOs which are valid to be used + * from the chip. + */ + unsigned long *valid_mask; + #if defined(CONFIG_OF_GPIO) /* * If CONFIG_OF is enabled, then all GPIO controllers described in the @@ -384,6 +399,7 @@ bool gpiochip_line_is_open_source(struct gpio_chip *chip, unsigned int offset); /* Sleep persistence inquiry for drivers */ bool gpiochip_line_is_persistent(struct gpio_chip *chip, unsigned int offset); +bool gpiochip_line_is_valid(const struct gpio_chip *chip, unsigned int offset); /* get driver data */ void *gpiochip_get_data(struct gpio_chip *chip); diff --git a/include/linux/platform_data/gpio-htc-egpio.h b/include/linux/platform_data/gpio-htc-egpio.h index b7baf1e42c55aae43901e82207f718961c2f25b3..9a3e78082883f366922e318a0794baf393bd74bb 100644 --- a/include/linux/platform_data/gpio-htc-egpio.h +++ b/include/linux/platform_data/gpio-htc-egpio.h @@ -6,8 +6,6 @@ #ifndef __HTC_EGPIO_H__ #define __HTC_EGPIO_H__ -#include - /* Descriptive values for all-in or all-out htc_egpio_chip descriptors. */ #define HTC_EGPIO_OUTPUT (~0) #define HTC_EGPIO_INPUT 0 diff --git a/include/soc/bcm2835/raspberrypi-firmware.h b/include/soc/bcm2835/raspberrypi-firmware.h index cb979ad90401e299344dd5fae38d09c489d8bd58..50df5b28d2c9df6eb0cffb217104cdf8ee59e9ed 100644 --- a/include/soc/bcm2835/raspberrypi-firmware.h +++ b/include/soc/bcm2835/raspberrypi-firmware.h @@ -63,6 +63,7 @@ enum rpi_firmware_property_tag { RPI_FIRMWARE_GET_MIN_VOLTAGE = 0x00030008, RPI_FIRMWARE_GET_TURBO = 0x00030009, RPI_FIRMWARE_GET_MAX_TEMPERATURE = 0x0003000a, + RPI_FIRMWARE_GET_STC = 0x0003000b, RPI_FIRMWARE_ALLOCATE_MEMORY = 0x0003000c, RPI_FIRMWARE_LOCK_MEMORY = 0x0003000d, RPI_FIRMWARE_UNLOCK_MEMORY = 0x0003000e, @@ -72,12 +73,22 @@ enum rpi_firmware_property_tag { RPI_FIRMWARE_SET_ENABLE_QPU = 0x00030012, RPI_FIRMWARE_GET_DISPMANX_RESOURCE_MEM_HANDLE = 0x00030014, RPI_FIRMWARE_GET_EDID_BLOCK = 0x00030020, + RPI_FIRMWARE_GET_CUSTOMER_OTP = 0x00030021, RPI_FIRMWARE_GET_DOMAIN_STATE = 0x00030030, RPI_FIRMWARE_SET_CLOCK_STATE = 0x00038001, RPI_FIRMWARE_SET_CLOCK_RATE = 0x00038002, RPI_FIRMWARE_SET_VOLTAGE = 0x00038003, RPI_FIRMWARE_SET_TURBO = 0x00038009, + RPI_FIRMWARE_SET_CUSTOMER_OTP = 0x00038021, RPI_FIRMWARE_SET_DOMAIN_STATE = 0x00038030, + RPI_FIRMWARE_GET_GPIO_STATE = 0x00030041, + RPI_FIRMWARE_SET_GPIO_STATE = 0x00038041, + RPI_FIRMWARE_SET_SDHOST_CLOCK = 0x00038042, + RPI_FIRMWARE_GET_GPIO_CONFIG = 0x00030043, + RPI_FIRMWARE_SET_GPIO_CONFIG = 0x00038043, + RPI_FIRMWARE_GET_PERIPH_REG = 0x00030045, + RPI_FIRMWARE_SET_PERIPH_REG = 0x00038045, + /* Dispmanx TAGS */ RPI_FIRMWARE_FRAMEBUFFER_ALLOCATE = 0x00040001, @@ -91,6 +102,8 @@ enum rpi_firmware_property_tag { RPI_FIRMWARE_FRAMEBUFFER_GET_VIRTUAL_OFFSET = 0x00040009, RPI_FIRMWARE_FRAMEBUFFER_GET_OVERSCAN = 0x0004000a, RPI_FIRMWARE_FRAMEBUFFER_GET_PALETTE = 0x0004000b, + RPI_FIRMWARE_FRAMEBUFFER_GET_TOUCHBUF = 0x0004000f, + RPI_FIRMWARE_FRAMEBUFFER_GET_GPIOVIRTBUF = 0x00040010, RPI_FIRMWARE_FRAMEBUFFER_RELEASE = 0x00048001, RPI_FIRMWARE_FRAMEBUFFER_TEST_PHYSICAL_WIDTH_HEIGHT = 0x00044003, RPI_FIRMWARE_FRAMEBUFFER_TEST_VIRTUAL_WIDTH_HEIGHT = 0x00044004, @@ -100,6 +113,7 @@ enum rpi_firmware_property_tag { RPI_FIRMWARE_FRAMEBUFFER_TEST_VIRTUAL_OFFSET = 0x00044009, RPI_FIRMWARE_FRAMEBUFFER_TEST_OVERSCAN = 0x0004400a, RPI_FIRMWARE_FRAMEBUFFER_TEST_PALETTE = 0x0004400b, + RPI_FIRMWARE_FRAMEBUFFER_TEST_VSYNC = 0x0004400e, RPI_FIRMWARE_FRAMEBUFFER_SET_PHYSICAL_WIDTH_HEIGHT = 0x00048003, RPI_FIRMWARE_FRAMEBUFFER_SET_VIRTUAL_WIDTH_HEIGHT = 0x00048004, RPI_FIRMWARE_FRAMEBUFFER_SET_DEPTH = 0x00048005, @@ -108,6 +122,10 @@ enum rpi_firmware_property_tag { RPI_FIRMWARE_FRAMEBUFFER_SET_VIRTUAL_OFFSET = 0x00048009, RPI_FIRMWARE_FRAMEBUFFER_SET_OVERSCAN = 0x0004800a, RPI_FIRMWARE_FRAMEBUFFER_SET_PALETTE = 0x0004800b, + RPI_FIRMWARE_FRAMEBUFFER_SET_TOUCHBUF = 0x0004801f, + RPI_FIRMWARE_FRAMEBUFFER_SET_GPIOVIRTBUF = 0x00048020, + RPI_FIRMWARE_FRAMEBUFFER_SET_VSYNC = 0x0004800e, + RPI_FIRMWARE_FRAMEBUFFER_SET_BACKLIGHT = 0x0004800f, RPI_FIRMWARE_VCHIQ_INIT = 0x00048010, diff --git a/init/Kconfig b/init/Kconfig index 2852692d7c9ccaecccc7e6bef9d7d05fcf083aae..9d167a5b4a947512c12c855ab99439806e19478e 100644 --- a/init/Kconfig +++ b/init/Kconfig @@ -1437,7 +1437,7 @@ config PERF_USE_VMALLOC See tools/perf/design.txt for details config PC104 - bool "PC/104 support" + bool "PC/104 support" if EXPERT help Expose PC/104 form factor device drivers and options available for selection and configuration. Enable this option if your target diff --git a/tools/gpio/gpio-event-mon.c b/tools/gpio/gpio-event-mon.c index dac4d4131d9b250cec8d724bc919a58da554ab61..c864544efe059b5c5b0d9126a391a5fcad2ac614 100644 --- a/tools/gpio/gpio-event-mon.c +++ b/tools/gpio/gpio-event-mon.c @@ -99,7 +99,7 @@ int monitor_device(const char *device_name, ret = -EIO; break; } - fprintf(stdout, "GPIO EVENT %" PRIu64 ": ", event.timestamp); + fprintf(stdout, "GPIO EVENT %llu: ", event.timestamp); switch (event.id) { case GPIOEVENT_EVENT_RISING_EDGE: fprintf(stdout, "rising edge");