Merge "msm: ipa3: aggregate transfers completions" into msm-4.9
diff --git a/Documentation/devicetree/bindings/pinctrl/qcom,pmic-gpio.txt b/Documentation/devicetree/bindings/pinctrl/qcom,pmic-gpio.txt
index 521c783..c01036d 100644
--- a/Documentation/devicetree/bindings/pinctrl/qcom,pmic-gpio.txt
+++ b/Documentation/devicetree/bindings/pinctrl/qcom,pmic-gpio.txt
@@ -43,6 +43,17 @@
the first cell will be used to define gpio number and the
second denotes the flags for this gpio
+- qcom,gpios-disallowed:
+ Usage: optional
+ Value type: <prop-encoded-array>
+ Definition: Array of the GPIO hardware numbers corresponding to GPIOs
+ which the APSS processor is not allowed to configure.
+ The hardware numbers are indexed from 1.
+ The interrupt resources for these GPIOs must not be defined
+ in "interrupts" and "interrupt-names" properties.
+ GPIOs defined in this array won't be registered as pins
+ in the pinctrl device or gpios in the gpio chip.
+
Please refer to ../gpio/gpio.txt and ../interrupt-controller/interrupts.txt for
a general description of GPIO and interrupt bindings.
@@ -233,6 +244,7 @@
gpio-controller;
#gpio-cells = <2>;
+ qcom,gpios-disallowed = <1 20>;
pm8921_gpio_keys: gpio-keys {
volume-keys {
diff --git a/arch/arm64/boot/dts/qcom/pm8005.dtsi b/arch/arm64/boot/dts/qcom/pm8005.dtsi
index 241864f..1f8d20e 100644
--- a/arch/arm64/boot/dts/qcom/pm8005.dtsi
+++ b/arch/arm64/boot/dts/qcom/pm8005.dtsi
@@ -32,37 +32,15 @@
label = "pm8005_tz";
};
- pm8005_gpios: gpios {
- compatible = "qcom,qpnp-pin";
+ pm8005_gpios: pinctrl@c000 {
+ compatible = "qcom,spmi-gpio";
+ reg = <0xc000 0x400>;
+ interrupts = <0x4 0xc0 0 IRQ_TYPE_NONE>,
+ <0x4 0xc1 0 IRQ_TYPE_NONE>;
+ interrupt-names = "pm8005_gpio1", "pm8005_gpio2";
gpio-controller;
#gpio-cells = <2>;
- #address-cells = <1>;
- #size-cells = <1>;
- label = "pm8005-gpio";
-
- gpio@c000 {
- reg = <0xc000 0x100>;
- qcom,pin-num = <1>;
- status = "disabled";
- };
-
- gpio@c100 {
- reg = <0xc100 0x100>;
- qcom,pin-num = <2>;
- status = "disabled";
- };
-
- gpio@c200 {
- reg = <0xc200 0x100>;
- qcom,pin-num = <3>;
- status = "disabled";
- };
-
- gpio@c300 {
- reg = <0xc300 0x100>;
- qcom,pin-num = <4>;
- status = "disabled";
- };
+ qcom,gpios-disallowed = <3 4>;
};
};
diff --git a/arch/arm64/boot/dts/qcom/pm8998.dtsi b/arch/arm64/boot/dts/qcom/pm8998.dtsi
index ed4fdde..5290f46 100644
--- a/arch/arm64/boot/dts/qcom/pm8998.dtsi
+++ b/arch/arm64/boot/dts/qcom/pm8998.dtsi
@@ -72,169 +72,41 @@
label = "pm8998_tz";
};
- pm8998_gpios: gpios {
- compatible = "qcom,qpnp-pin";
+ pm8998_gpios: pinctrl@c000 {
+ compatible = "qcom,spmi-gpio";
+ reg = <0xc000 0x1a00>;
+ interrupts = <0x0 0xc0 0 IRQ_TYPE_NONE>,
+ <0x0 0xc1 0 IRQ_TYPE_NONE>,
+ <0x0 0xc3 0 IRQ_TYPE_NONE>,
+ <0x0 0xc4 0 IRQ_TYPE_NONE>,
+ <0x0 0xc5 0 IRQ_TYPE_NONE>,
+ <0x0 0xc6 0 IRQ_TYPE_NONE>,
+ <0x0 0xc7 0 IRQ_TYPE_NONE>,
+ <0x0 0xc8 0 IRQ_TYPE_NONE>,
+ <0x0 0xc9 0 IRQ_TYPE_NONE>,
+ <0x0 0xca 0 IRQ_TYPE_NONE>,
+ <0x0 0xcb 0 IRQ_TYPE_NONE>,
+ <0x0 0xcc 0 IRQ_TYPE_NONE>,
+ <0x0 0xcd 0 IRQ_TYPE_NONE>,
+ <0x0 0xcf 0 IRQ_TYPE_NONE>,
+ <0x0 0xd0 0 IRQ_TYPE_NONE>,
+ <0x0 0xd1 0 IRQ_TYPE_NONE>,
+ <0x0 0xd2 0 IRQ_TYPE_NONE>,
+ <0x0 0xd4 0 IRQ_TYPE_NONE>,
+ <0x0 0xd6 0 IRQ_TYPE_NONE>;
+ interrupt-names = "pm8998_gpio1", "pm8998_gpio2",
+ "pm8998_gpio4", "pm8998_gpio5",
+ "pm8998_gpio6", "pm8998_gpio7",
+ "pm8998_gpio8", "pm8998_gpio9",
+ "pm8998_gpio10", "pm8998_gpio11",
+ "pm8998_gpio12", "pm8998_gpio13",
+ "pm8998_gpio14", "pm8998_gpio16",
+ "pm8998_gpio17", "pm8998_gpio18",
+ "pm8998_gpio19", "pm8998_gpio21",
+ "pm8998_gpio23";
gpio-controller;
#gpio-cells = <2>;
- #address-cells = <1>;
- #size-cells = <1>;
- label = "pm8998-gpio";
-
- gpio@c000 {
- reg = <0xc000 0x100>;
- qcom,pin-num = <1>;
- status = "disabled";
- };
-
- gpio@c100 {
- reg = <0xc100 0x100>;
- qcom,pin-num = <2>;
- status = "disabled";
- };
-
- gpio@c200 {
- reg = <0xc200 0x100>;
- qcom,pin-num = <3>;
- status = "disabled";
- };
-
- gpio@c300 {
- reg = <0xc300 0x100>;
- qcom,pin-num = <4>;
- status = "disabled";
- };
-
- gpio@c400 {
- reg = <0xc400 0x100>;
- qcom,pin-num = <5>;
- status = "disabled";
- };
-
- gpio@c500 {
- reg = <0xc500 0x100>;
- qcom,pin-num = <6>;
- status = "disabled";
- };
-
- gpio@c600 {
- reg = <0xc600 0x100>;
- qcom,pin-num = <7>;
- status = "disabled";
- };
-
- gpio@c700 {
- reg = <0xc700 0x100>;
- qcom,pin-num = <8>;
- status = "disabled";
- };
-
- gpio@c800 {
- reg = <0xc800 0x100>;
- qcom,pin-num = <9>;
- status = "disabled";
- };
-
- gpio@c900 {
- reg = <0xc900 0x100>;
- qcom,pin-num = <10>;
- status = "disabled";
- };
-
- gpio@ca00 {
- reg = <0xca00 0x100>;
- qcom,pin-num = <11>;
- status = "disabled";
- };
-
- gpio@cb00 {
- reg = <0xcb00 0x100>;
- qcom,pin-num = <12>;
- status = "disabled";
- };
-
- gpio@cc00 {
- reg = <0xcc00 0x100>;
- qcom,pin-num = <13>;
- status = "disabled";
- };
-
- gpio@cd00 {
- reg = <0xcd00 0x100>;
- qcom,pin-num = <14>;
- status = "disabled";
- };
-
- gpio@ce00 {
- reg = <0xce00 0x100>;
- qcom,pin-num = <15>;
- status = "disabled";
- };
-
- gpio@cf00 {
- reg = <0xcf00 0x100>;
- qcom,pin-num = <16>;
- status = "disabled";
- };
-
- gpio@d000 {
- reg = <0xd000 0x100>;
- qcom,pin-num = <17>;
- status = "disabled";
- };
-
- gpio@d100 {
- reg = <0xd100 0x100>;
- qcom,pin-num = <18>;
- status = "disabled";
- };
-
- gpio@d200 {
- reg = <0xd200 0x100>;
- qcom,pin-num = <19>;
- status = "disabled";
- };
-
- gpio@d300 {
- reg = <0xd300 0x100>;
- qcom,pin-num = <20>;
- status = "disabled";
- };
-
- gpio@d400 {
- reg = <0xd400 0x100>;
- qcom,pin-num = <21>;
- status = "disabled";
- };
-
- gpio@d500 {
- reg = <0xd500 0x100>;
- qcom,pin-num = <22>;
- status = "disabled";
- };
-
- gpio@d600 {
- reg = <0xd600 0x100>;
- qcom,pin-num = <23>;
- status = "disabled";
- };
-
- gpio@d700 {
- reg = <0xd700 0x100>;
- qcom,pin-num = <24>;
- status = "disabled";
- };
-
- gpio@d800 {
- reg = <0xd800 0x100>;
- qcom,pin-num = <25>;
- status = "disabled";
- };
-
- gpio@d900 {
- reg = <0xd900 0x100>;
- qcom,pin-num = <26>;
- status = "disabled";
- };
+ qcom,gpios-disallowed = <3 15 20 22 24 25 26>;
};
pm8998_coincell: qcom,coincell@2800 {
diff --git a/arch/arm64/boot/dts/qcom/pmi8998.dtsi b/arch/arm64/boot/dts/qcom/pmi8998.dtsi
index 1659706..1f27b21 100644
--- a/arch/arm64/boot/dts/qcom/pmi8998.dtsi
+++ b/arch/arm64/boot/dts/qcom/pmi8998.dtsi
@@ -38,97 +38,29 @@
label = "pmi8998_tz";
};
- pmi8998_gpios: gpios {
- compatible = "qcom,qpnp-pin";
+ pmi8998_gpios: pinctrl@c000 {
+ compatible = "qcom,spmi-gpio";
+ reg = <0xc000 0xe00>;
+ interrupts = <0x2 0xc0 0 IRQ_TYPE_NONE>,
+ <0x2 0xc1 0 IRQ_TYPE_NONE>,
+ <0x2 0xc2 0 IRQ_TYPE_NONE>,
+ <0x2 0xc4 0 IRQ_TYPE_NONE>,
+ <0x2 0xc5 0 IRQ_TYPE_NONE>,
+ <0x2 0xc7 0 IRQ_TYPE_NONE>,
+ <0x2 0xc8 0 IRQ_TYPE_NONE>,
+ <0x2 0xc9 0 IRQ_TYPE_NONE>,
+ <0x2 0xca 0 IRQ_TYPE_NONE>,
+ <0x2 0xcb 0 IRQ_TYPE_NONE>,
+ <0x2 0xcd 0 IRQ_TYPE_NONE>;
+ interrupt-names = "pmi8998_gpio1", "pmi8998_gpio2",
+ "pmi8998_gpio3", "pmi8998_gpio5",
+ "pmi8998_gpio6", "pmi8998_gpio8",
+ "pmi8998_gpio9", "pmi8998_gpio10",
+ "pmi8998_gpio11", "pmi8998_gpio12",
+ "pmi8998_gpio14";
gpio-controller;
#gpio-cells = <2>;
- #address-cells = <1>;
- #size-cells = <1>;
- label = "pmi8998-gpio";
-
- gpio@c000 {
- reg = <0xc000 0x100>;
- qcom,pin-num = <1>;
- status = "disabled";
- };
-
- gpio@c100 {
- reg = <0xc100 0x100>;
- qcom,pin-num = <2>;
- status = "disabled";
- };
-
- gpio@c200 {
- reg = <0xc200 0x100>;
- qcom,pin-num = <3>;
- status = "disabled";
- };
-
- gpio@c300 {
- reg = <0xc300 0x100>;
- qcom,pin-num = <4>;
- status = "disabled";
- };
-
- gpio@c400 {
- reg = <0xc400 0x100>;
- qcom,pin-num = <5>;
- status = "disabled";
- };
-
- gpio@c500 {
- reg = <0xc500 0x100>;
- qcom,pin-num = <6>;
- status = "disabled";
- };
-
- gpio@c600 {
- reg = <0xc600 0x100>;
- qcom,pin-num = <7>;
- status = "disabled";
- };
-
- gpio@c700 {
- reg = <0xc700 0x100>;
- qcom,pin-num = <8>;
- status = "disabled";
- };
-
- gpio@c800 {
- reg = <0xc800 0x100>;
- qcom,pin-num = <9>;
- status = "disabled";
- };
-
- gpio@c900 {
- reg = <0xc900 0x100>;
- qcom,pin-num = <10>;
- status = "disabled";
- };
-
- gpio@ca00 {
- reg = <0xca00 0x100>;
- qcom,pin-num = <11>;
- status = "disabled";
- };
-
- gpio@cb00 {
- reg = <0xcb00 0x100>;
- qcom,pin-num = <12>;
- status = "disabled";
- };
-
- gpio@cc00 {
- reg = <0xcc00 0x100>;
- qcom,pin-num = <13>;
- status = "disabled";
- };
-
- gpio@cd00 {
- reg = <0xcd00 0x100>;
- qcom,pin-num = <14>;
- status = "disabled";
- };
+ qcom,gpios-disallowed = <4 7 13>;
};
pmi8998_rradc: rradc@4500 {
@@ -372,7 +304,7 @@
qcom,en-ext-pfet-sc-pro;
qcom,pmic-revid = <&pmi8998_revid>;
qcom,loop-auto-gm-en;
- status = "okay";
+ status = "disabled";
};
flash_led: qcom,leds@d300 {
diff --git a/arch/arm64/boot/dts/qcom/sdm845-cdp.dtsi b/arch/arm64/boot/dts/qcom/sdm845-cdp.dtsi
index d47dd36..663ff3a4 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-cdp.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-cdp.dtsi
@@ -10,8 +10,61 @@
* GNU General Public License for more details.
*/
+#include <dt-bindings/gpio/gpio.h>
+
&soc {
sound-tavil {
qcom,us-euro-gpios = <&tavil_us_euro_sw>;
};
+
+ gpio_keys {
+ compatible = "gpio-keys";
+ label = "gpio-keys";
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&key_home_default
+ &key_vol_up_default
+ &key_cam_snapshot_default
+ &key_cam_focus_default>;
+
+ home {
+ label = "home";
+ gpios = <&pm8998_gpios 5 GPIO_ACTIVE_LOW>;
+ linux,input-type = <1>;
+ linux,code = <102>;
+ gpio-key,wakeup;
+ debounce-interval = <15>;
+ linux,can-disable;
+ };
+
+ vol_up {
+ label = "volume_up";
+ gpios = <&pm8998_gpios 6 GPIO_ACTIVE_LOW>;
+ linux,input-type = <1>;
+ linux,code = <115>;
+ gpio-key,wakeup;
+ debounce-interval = <15>;
+ linux,can-disable;
+ };
+
+ cam_snapshot {
+ label = "cam_snapshot";
+ gpios = <&pm8998_gpios 7 GPIO_ACTIVE_LOW>;
+ linux,input-type = <1>;
+ linux,code = <766>;
+ gpio-key,wakeup;
+ debounce-interval = <15>;
+ linux,can-disable;
+ };
+
+ cam_focus {
+ label = "cam_focus";
+ gpios = <&pm8998_gpios 8 GPIO_ACTIVE_LOW>;
+ linux,input-type = <1>;
+ linux,code = <528>;
+ gpio-key,wakeup;
+ debounce-interval = <15>;
+ linux,can-disable;
+ };
+ };
};
diff --git a/arch/arm64/boot/dts/qcom/sdm845-mtp.dtsi b/arch/arm64/boot/dts/qcom/sdm845-mtp.dtsi
index cfba6f4..edc1f23 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-mtp.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-mtp.dtsi
@@ -9,3 +9,47 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
+
+#include <dt-bindings/gpio/gpio.h>
+
+&soc {
+ gpio_keys {
+ compatible = "gpio-keys";
+ label = "gpio-keys";
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&key_vol_up_default
+ &key_cam_snapshot_default
+ &key_cam_focus_default>;
+
+ vol_up {
+ label = "volume_up";
+ gpios = <&pm8998_gpios 6 GPIO_ACTIVE_LOW>;
+ linux,input-type = <1>;
+ linux,code = <115>;
+ gpio-key,wakeup;
+ debounce-interval = <15>;
+ linux,can-disable;
+ };
+
+ cam_snapshot {
+ label = "cam_snapshot";
+ gpios = <&pm8998_gpios 7 GPIO_ACTIVE_LOW>;
+ linux,input-type = <1>;
+ linux,code = <766>;
+ gpio-key,wakeup;
+ debounce-interval = <15>;
+ linux,can-disable;
+ };
+
+ cam_focus {
+ label = "cam_focus";
+ gpios = <&pm8998_gpios 8 GPIO_ACTIVE_LOW>;
+ linux,input-type = <1>;
+ linux,code = <528>;
+ gpio-key,wakeup;
+ debounce-interval = <15>;
+ linux,can-disable;
+ };
+ };
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm845-pinctrl.dtsi b/arch/arm64/boot/dts/qcom/sdm845-pinctrl.dtsi
index c5b53b8..04e3f22 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-pinctrl.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-pinctrl.dtsi
@@ -1113,3 +1113,45 @@
};
};
};
+
+&pm8998_gpios {
+ key_home {
+ key_home_default: key_home_default {
+ pins = "gpio5";
+ function = "normal";
+ input-enable;
+ bias-pull-up;
+ power-source = <0>;
+ };
+ };
+
+ key_vol_up {
+ key_vol_up_default: key_vol_up_default {
+ pins = "gpio6";
+ function = "normal";
+ input-enable;
+ bias-pull-up;
+ power-source = <0>;
+ };
+ };
+
+ key_cam_snapshot {
+ key_cam_snapshot_default: key_cam_snapshot_default {
+ pins = "gpio7";
+ function = "normal";
+ input-enable;
+ bias-pull-up;
+ power-source = <0>;
+ };
+ };
+
+ key_cam_focus {
+ key_cam_focus_default: key_cam_focus_default {
+ pins = "gpio8";
+ function = "normal";
+ input-enable;
+ bias-pull-up;
+ power-source = <0>;
+ };
+ };
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm845-sde-display.dtsi b/arch/arm64/boot/dts/qcom/sdm845-sde-display.dtsi
index 1b697fb..2983358 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-sde-display.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-sde-display.dtsi
@@ -23,7 +23,6 @@
#include "dsi-panel-sharp-1080p-cmd.dtsi"
#include "dsi-panel-sharp-dualmipi-1080p-120hz.dtsi"
#include "dsi-panel-s6e3ha3-amoled-dualmipi-wqhd-cmd.dtsi"
-#include "sdm845-pinctrl.dtsi"
&soc {
dsi_panel_pwr_supply: dsi_panel_pwr_supply {
diff --git a/arch/arm64/configs/sdm845-perf_defconfig b/arch/arm64/configs/sdm845-perf_defconfig
index bf8082e..4a08eda 100644
--- a/arch/arm64/configs/sdm845-perf_defconfig
+++ b/arch/arm64/configs/sdm845-perf_defconfig
@@ -280,9 +280,9 @@
CONFIG_SPMI=y
CONFIG_PINCTRL_SDM845=y
CONFIG_PINCTRL_SDM830=y
+CONFIG_PINCTRL_QCOM_SPMI_PMIC=y
CONFIG_GPIOLIB=y
CONFIG_GPIO_SYSFS=y
-CONFIG_GPIO_QPNP_PIN=y
CONFIG_POWER_RESET_QCOM=y
CONFIG_POWER_RESET_XGENE=y
CONFIG_POWER_RESET_SYSCON=y
diff --git a/arch/arm64/configs/sdm845_defconfig b/arch/arm64/configs/sdm845_defconfig
index 4b73772..f870903 100644
--- a/arch/arm64/configs/sdm845_defconfig
+++ b/arch/arm64/configs/sdm845_defconfig
@@ -292,9 +292,9 @@
CONFIG_SPMI=y
CONFIG_PINCTRL_SDM845=y
CONFIG_PINCTRL_SDM830=y
+CONFIG_PINCTRL_QCOM_SPMI_PMIC=y
CONFIG_GPIOLIB=y
CONFIG_GPIO_SYSFS=y
-CONFIG_GPIO_QPNP_PIN=y
CONFIG_POWER_RESET_QCOM=y
CONFIG_POWER_RESET_XGENE=y
CONFIG_POWER_RESET_SYSCON=y
diff --git a/drivers/pinctrl/qcom/pinctrl-spmi-gpio.c b/drivers/pinctrl/qcom/pinctrl-spmi-gpio.c
index 77e9dd7..f06fb1f 100644
--- a/drivers/pinctrl/qcom/pinctrl-spmi-gpio.c
+++ b/drivers/pinctrl/qcom/pinctrl-spmi-gpio.c
@@ -138,6 +138,7 @@
* struct pmic_gpio_pad - keep current GPIO settings
* @base: Address base in SPMI device.
* @irq: IRQ number which this GPIO generate.
+ * @gpio_idx: The index in GPIO's hardware number space (1-based)
* @is_enabled: Set to false when GPIO should be put in high Z state.
* @out_value: Cached pin output value
* @have_buffer: Set to true if GPIO output could be configured in push-pull,
@@ -158,6 +159,7 @@
struct pmic_gpio_pad {
u16 base;
int irq;
+ int gpio_idx;
bool is_enabled;
bool out_value;
bool have_buffer;
@@ -179,6 +181,7 @@
struct regmap *map;
struct pinctrl_dev *ctrl;
struct gpio_chip chip;
+ const char **gpio_groups;
};
static const struct pinconf_generic_params pmic_gpio_bindings[] = {
@@ -297,7 +300,9 @@
const char *const **groups,
unsigned *const num_qgroups)
{
- *groups = pmic_gpio_groups;
+ struct pmic_gpio_state *state = pinctrl_dev_get_drvdata(pctldev);
+
+ *groups = state->gpio_groups;
*num_qgroups = pctldev->desc->npins;
return 0;
}
@@ -637,7 +642,7 @@
pad = pctldev->desc->pins[pin].drv_data;
- seq_printf(s, " gpio%-2d:", pin + PMIC_GPIO_PHYSICAL_OFFSET);
+ seq_printf(s, " gpio%-2d:", pad->gpio_idx);
val = pmic_gpio_read(state, pad, PMIC_GPIO_REG_EN_CTL);
@@ -742,13 +747,29 @@
const struct of_phandle_args *gpio_desc,
u32 *flags)
{
+ int i;
+ struct pmic_gpio_state *state = gpiochip_get_data(chip);
+ struct pinctrl_desc *desc = state->ctrl->desc;
+ struct pmic_gpio_pad *pad;
+
if (chip->of_gpio_n_cells < 2)
return -EINVAL;
if (flags)
*flags = gpio_desc->args[1];
- return gpio_desc->args[0] - PMIC_GPIO_PHYSICAL_OFFSET;
+ for (i = 0; i < chip->ngpio; i++) {
+ pad = desc->pins[i].drv_data;
+ if (pad->gpio_idx == gpio_desc->args[0]) {
+ dev_dbg(state->dev, "gpio%-2d xlate to pin%-2d\n",
+ gpio_desc->args[0], i);
+ return i;
+ }
+ }
+
+ dev_err(state->dev, "Couldn't find pin for gpio %d\n",
+ gpio_desc->args[0]);
+ return -ENODEV;
}
static int pmic_gpio_to_irq(struct gpio_chip *chip, unsigned pin)
@@ -934,43 +955,124 @@
struct pinctrl_desc *pctrldesc;
struct pmic_gpio_pad *pad, *pads;
struct pmic_gpio_state *state;
- int ret, npins, i;
- u32 reg;
+ int ret, npins, ngpios, i, j, pin_idx;
+ int disallowed_count = 0;
+ u32 reg[2], start, size;
+ u32 *disallowed = NULL;
- ret = of_property_read_u32(dev->of_node, "reg", ®);
+ ret = of_property_read_u32_array(dev->of_node, "reg", reg, 2);
if (ret < 0) {
- dev_err(dev, "missing base address");
+ dev_err(dev, "reg property reading failed\n");
return ret;
}
+ start = reg[0];
+ size = reg[1];
- npins = platform_irq_count(pdev);
- if (!npins)
+ ngpios = size / PMIC_GPIO_ADDRESS_RANGE;
+ if (ngpios == 0) {
+ dev_err(dev, "no gpios assigned\n");
+ return -ENODEV;
+ }
+
+ if (ngpios > ARRAY_SIZE(pmic_gpio_groups)) {
+ dev_err(dev, "reg property defines %d gpios, but only %d are allowed\n",
+ ngpios, (int)ARRAY_SIZE(pmic_gpio_groups));
return -EINVAL;
- if (npins < 0)
- return npins;
+ }
- BUG_ON(npins > ARRAY_SIZE(pmic_gpio_groups));
+ if (of_find_property(dev->of_node, "qcom,gpios-disallowed",
+ &disallowed_count)) {
+ disallowed_count /= sizeof(u32);
+ if (disallowed_count == 0) {
+ dev_err(dev, "No data in gpios-disallowed\n");
+ return -EINVAL;
+ }
+
+ disallowed = kcalloc(disallowed_count, sizeof(u32), GFP_KERNEL);
+ if (disallowed == NULL)
+ return -ENOMEM;
+
+ ret = of_property_read_u32_array(dev->of_node,
+ "qcom,gpios-disallowed",
+ disallowed, disallowed_count);
+ if (ret < 0) {
+ dev_err(dev, "qcom,gpios-disallowed property reading failed, ret=%d\n",
+ ret);
+ goto err_free;
+ }
+
+ for (i = 0; i < disallowed_count; i++) {
+ if (disallowed[i] >= ngpios + PMIC_GPIO_PHYSICAL_OFFSET
+ || disallowed[i] < PMIC_GPIO_PHYSICAL_OFFSET) {
+ dev_err(dev, "invalid gpio = %d specified in qcom,gpios-disallowed, supported values: %d to %d\n",
+ disallowed[i],
+ PMIC_GPIO_PHYSICAL_OFFSET,
+ ngpios - 1 + PMIC_GPIO_PHYSICAL_OFFSET);
+ ret = -EINVAL;
+ goto err_free;
+ }
+ for (j = 0; j < i; j++) {
+ if (disallowed[i] == disallowed[j]) {
+ dev_err(dev, "duplicate gpio = %d listed in qcom,gpios-disallowed\n",
+ disallowed[i]);
+ ret = -EINVAL;
+ goto err_free;
+ }
+ }
+ dev_dbg(dev, "gpio %d NOT supported\n", disallowed[i]);
+ }
+ } else {
+ disallowed_count = 0;
+ }
+
+ npins = ngpios - disallowed_count;
+ if (npins <= 0) {
+ dev_err(dev, "No pins assigned\n");
+ ret = -ENODEV;
+ goto err_free;
+ }
+ if (platform_irq_count(pdev) != npins) {
+ dev_err(dev, "%d IRQs defined but %d expected\n",
+ platform_irq_count(pdev), npins);
+ ret = -EINVAL;
+ goto err_free;
+ }
state = devm_kzalloc(dev, sizeof(*state), GFP_KERNEL);
- if (!state)
- return -ENOMEM;
+ if (!state) {
+ ret = -ENOMEM;
+ goto err_free;
+ }
platform_set_drvdata(pdev, state);
state->dev = &pdev->dev;
state->map = dev_get_regmap(dev->parent, NULL);
+ state->gpio_groups = devm_kcalloc(dev, sizeof(*state->gpio_groups),
+ npins, GFP_KERNEL);
+ if (!state->gpio_groups) {
+ ret = -ENOMEM;
+ goto err_free;
+ }
+
pindesc = devm_kcalloc(dev, npins, sizeof(*pindesc), GFP_KERNEL);
- if (!pindesc)
- return -ENOMEM;
+ if (!pindesc) {
+ ret = -ENOMEM;
+ goto err_free;
+ }
pads = devm_kcalloc(dev, npins, sizeof(*pads), GFP_KERNEL);
- if (!pads)
- return -ENOMEM;
+ if (!pads) {
+ ret = -ENOMEM;
+ goto err_free;
+ }
pctrldesc = devm_kzalloc(dev, sizeof(*pctrldesc), GFP_KERNEL);
- if (!pctrldesc)
- return -ENOMEM;
+ if (!pctrldesc) {
+ ret = -ENOMEM;
+ goto err_free;
+ }
pctrldesc->pctlops = &pmic_gpio_pinctrl_ops;
pctrldesc->pmxops = &pmic_gpio_pinmux_ops;
@@ -984,22 +1086,42 @@
#ifdef CONFIG_DEBUG_FS
pctrldesc->custom_conf_items = pmic_conf_items;
#endif
+ for (pin_idx = 0, i = 0; i < ngpios; i++) {
+ for (j = 0; j < disallowed_count; j++) {
+ if (i + PMIC_GPIO_PHYSICAL_OFFSET == disallowed[j])
+ break;
+ }
+ if (j != disallowed_count)
+ continue;
- for (i = 0; i < npins; i++, pindesc++) {
- pad = &pads[i];
+ pad = &pads[pin_idx];
pindesc->drv_data = pad;
- pindesc->number = i;
+ pindesc->number = pin_idx;
pindesc->name = pmic_gpio_groups[i];
- pad->irq = platform_get_irq(pdev, i);
- if (pad->irq < 0)
- return pad->irq;
+ pad->gpio_idx = i + PMIC_GPIO_PHYSICAL_OFFSET;
+ pad->irq = platform_get_irq(pdev, pin_idx);
+ if (pad->irq < 0) {
+ dev_err(state->dev,
+ "failed to get irq for gpio %d (pin %d), ret=%d\n",
+ pad->gpio_idx, pin_idx, pad->irq);
+ ret = pad->irq;
+ goto err_free;
+ }
+ /* Every pin is a group */
+ state->gpio_groups[pin_idx] = pmic_gpio_groups[i];
- pad->base = reg + i * PMIC_GPIO_ADDRESS_RANGE;
+ pad->base = start + i * PMIC_GPIO_ADDRESS_RANGE;
ret = pmic_gpio_populate(state, pad);
- if (ret < 0)
- return ret;
+ if (ret < 0) {
+ dev_err(state->dev,
+ "failed to populate gpio %d, ret=%d\n",
+ i, ret);
+ goto err_free;
+ }
+ pindesc++;
+ pin_idx++;
}
state->chip = pmic_gpio_gpio_template;
@@ -1011,25 +1133,29 @@
state->chip.can_sleep = false;
state->ctrl = devm_pinctrl_register(dev, pctrldesc, state);
- if (IS_ERR(state->ctrl))
- return PTR_ERR(state->ctrl);
+ if (IS_ERR(state->ctrl)) {
+ ret = PTR_ERR(state->ctrl);
+ dev_err(state->dev, "failed to register pinctrl device, ret=%d\n",
+ ret);
+ goto err_free;
+ }
ret = gpiochip_add_data(&state->chip, state);
if (ret) {
- dev_err(state->dev, "can't add gpio chip\n");
- return ret;
+ dev_err(state->dev, "can't add gpio chip, ret=%d\n", ret);
+ goto err_free;
}
ret = gpiochip_add_pin_range(&state->chip, dev_name(dev), 0, 0, npins);
if (ret) {
- dev_err(dev, "failed to add pin range\n");
- goto err_range;
+ dev_err(dev, "failed to add pin range\n, ret=%d\n", ret);
+ gpiochip_remove(&state->chip);
+ goto err_free;
}
- return 0;
+err_free:
+ kfree(disallowed);
-err_range:
- gpiochip_remove(&state->chip);
return ret;
}