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

pinctrl: qcom: ssbi: Family A gpio & mpp drivers

This introduces pinctrl drivers for gpio and mpp blocks found in family A
PMICs.

Tested-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
Signed-off-by: Bjorn Andersson <bjorn.andersson@sonymobile.com>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>

authored by

Bjorn Andersson and committed by
Linus Walleij
b4c45fe9 eb5c144c

+1743
+5
Documentation/devicetree/bindings/pinctrl/qcom,pmic-mpp.txt
··· 7 7 Usage: required 8 8 Value type: <string> 9 9 Definition: Should contain one of: 10 + "qcom,pm8018-mpp", 11 + "qcom,pm8038-mpp", 12 + "qcom,pm8821-mpp", 10 13 "qcom,pm8841-mpp", 11 14 "qcom,pm8916-mpp", 15 + "qcom,pm8917-mpp", 16 + "qcom,pm8921-mpp", 12 17 "qcom,pm8941-mpp", 13 18 "qcom,pma8084-mpp", 14 19
+12
drivers/pinctrl/qcom/Kconfig
··· 76 76 which are using SPMI for communication with SoC. Example PMIC's 77 77 devices are pm8841, pm8941 and pma8084. 78 78 79 + config PINCTRL_QCOM_SSBI_PMIC 80 + tristate "Qualcomm SSBI PMIC pin controller driver" 81 + depends on GPIOLIB && OF 82 + select PINMUX 83 + select PINCONF 84 + select GENERIC_PINCONF 85 + help 86 + This is the pinctrl, pinmux, pinconf and gpiolib driver for the 87 + Qualcomm GPIO and MPP blocks found in the Qualcomm PMIC's chips, 88 + which are using SSBI for communication with SoC. Example PMIC's 89 + devices are pm8058 and pm8921. 90 + 79 91 endif
+2
drivers/pinctrl/qcom/Makefile
··· 9 9 obj-$(CONFIG_PINCTRL_MSM8916) += pinctrl-msm8916.o 10 10 obj-$(CONFIG_PINCTRL_QCOM_SPMI_PMIC) += pinctrl-spmi-gpio.o 11 11 obj-$(CONFIG_PINCTRL_QCOM_SPMI_PMIC) += pinctrl-spmi-mpp.o 12 + obj-$(CONFIG_PINCTRL_QCOM_SSBI_PMIC) += pinctrl-ssbi-gpio.o 13 + obj-$(CONFIG_PINCTRL_QCOM_SSBI_PMIC) += pinctrl-ssbi-mpp.o
+791
drivers/pinctrl/qcom/pinctrl-ssbi-gpio.c
··· 1 + /* 2 + * Copyright (c) 2015, Sony Mobile Communications AB. 3 + * Copyright (c) 2013, The Linux Foundation. All rights reserved. 4 + * 5 + * This program is free software; you can redistribute it and/or modify 6 + * it under the terms of the GNU General Public License version 2 and 7 + * only version 2 as published by the Free Software Foundation. 8 + * 9 + * This program is distributed in the hope that it will be useful, 10 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 + * GNU General Public License for more details. 13 + */ 14 + 15 + #include <linux/module.h> 16 + #include <linux/platform_device.h> 17 + #include <linux/pinctrl/pinctrl.h> 18 + #include <linux/pinctrl/pinmux.h> 19 + #include <linux/pinctrl/pinconf.h> 20 + #include <linux/pinctrl/pinconf-generic.h> 21 + #include <linux/slab.h> 22 + #include <linux/regmap.h> 23 + #include <linux/gpio.h> 24 + #include <linux/interrupt.h> 25 + #include <linux/of_device.h> 26 + 27 + #include <dt-bindings/pinctrl/qcom,pmic-gpio.h> 28 + 29 + #include "../core.h" 30 + #include "../pinctrl-utils.h" 31 + 32 + /* mode */ 33 + #define PM8XXX_GPIO_MODE_ENABLED BIT(0) 34 + #define PM8XXX_GPIO_MODE_INPUT 0 35 + #define PM8XXX_GPIO_MODE_OUTPUT 2 36 + 37 + /* output buffer */ 38 + #define PM8XXX_GPIO_PUSH_PULL 0 39 + #define PM8XXX_GPIO_OPEN_DRAIN 1 40 + 41 + /* bias */ 42 + #define PM8XXX_GPIO_BIAS_PU_30 0 43 + #define PM8XXX_GPIO_BIAS_PU_1P5 1 44 + #define PM8XXX_GPIO_BIAS_PU_31P5 2 45 + #define PM8XXX_GPIO_BIAS_PU_1P5_30 3 46 + #define PM8XXX_GPIO_BIAS_PD 4 47 + #define PM8XXX_GPIO_BIAS_NP 5 48 + 49 + /* GPIO registers */ 50 + #define SSBI_REG_ADDR_GPIO_BASE 0x150 51 + #define SSBI_REG_ADDR_GPIO(n) (SSBI_REG_ADDR_GPIO_BASE + n) 52 + 53 + #define PM8XXX_BANK_WRITE BIT(7) 54 + 55 + #define PM8XXX_MAX_GPIOS 44 56 + 57 + /* custom pinconf parameters */ 58 + #define PM8XXX_QCOM_DRIVE_STRENGH (PIN_CONFIG_END + 1) 59 + #define PM8XXX_QCOM_PULL_UP_STRENGTH (PIN_CONFIG_END + 2) 60 + 61 + /** 62 + * struct pm8xxx_pin_data - dynamic configuration for a pin 63 + * @reg: address of the control register 64 + * @irq: IRQ from the PMIC interrupt controller 65 + * @power_source: logical selected voltage source, mapping in static data 66 + * is used translate to register values 67 + * @mode: operating mode for the pin (input/output) 68 + * @open_drain: output buffer configured as open-drain (vs push-pull) 69 + * @output_value: configured output value 70 + * @bias: register view of configured bias 71 + * @pull_up_strength: placeholder for selected pull up strength 72 + * only used to configure bias when pull up is selected 73 + * @output_strength: selector of output-strength 74 + * @disable: pin disabled / configured as tristate 75 + * @function: pinmux selector 76 + * @inverted: pin logic is inverted 77 + */ 78 + struct pm8xxx_pin_data { 79 + unsigned reg; 80 + int irq; 81 + u8 power_source; 82 + u8 mode; 83 + bool open_drain; 84 + bool output_value; 85 + u8 bias; 86 + u8 pull_up_strength; 87 + u8 output_strength; 88 + bool disable; 89 + u8 function; 90 + bool inverted; 91 + }; 92 + 93 + struct pm8xxx_gpio { 94 + struct device *dev; 95 + struct regmap *regmap; 96 + struct pinctrl_dev *pctrl; 97 + struct gpio_chip chip; 98 + 99 + struct pinctrl_desc desc; 100 + unsigned npins; 101 + }; 102 + 103 + static const struct pinconf_generic_params pm8xxx_gpio_bindings[] = { 104 + {"qcom,drive-strength", PM8XXX_QCOM_DRIVE_STRENGH, 0}, 105 + {"qcom,pull-up-strength", PM8XXX_QCOM_PULL_UP_STRENGTH, 0}, 106 + }; 107 + 108 + #ifdef CONFIG_DEBUG_FS 109 + static const struct pin_config_item pm8xxx_conf_items[ARRAY_SIZE(pm8xxx_gpio_bindings)] = { 110 + PCONFDUMP(PM8XXX_QCOM_DRIVE_STRENGH, "drive-strength", NULL, true), 111 + PCONFDUMP(PM8XXX_QCOM_PULL_UP_STRENGTH, "pull up strength", NULL, true), 112 + }; 113 + #endif 114 + 115 + static const char * const pm8xxx_groups[PM8XXX_MAX_GPIOS] = { 116 + "gpio1", "gpio2", "gpio3", "gpio4", "gpio5", "gpio6", "gpio7", "gpio8", 117 + "gpio9", "gpio10", "gpio11", "gpio12", "gpio13", "gpio14", "gpio15", 118 + "gpio16", "gpio17", "gpio18", "gpio19", "gpio20", "gpio21", "gpio22", 119 + "gpio23", "gpio24", "gpio25", "gpio26", "gpio27", "gpio28", "gpio29", 120 + "gpio30", "gpio31", "gpio32", "gpio33", "gpio34", "gpio35", "gpio36", 121 + "gpio37", "gpio38", "gpio39", "gpio40", "gpio41", "gpio42", "gpio43", 122 + "gpio44", 123 + }; 124 + 125 + static const char * const pm8xxx_gpio_functions[] = { 126 + PMIC_GPIO_FUNC_NORMAL, PMIC_GPIO_FUNC_PAIRED, 127 + PMIC_GPIO_FUNC_FUNC1, PMIC_GPIO_FUNC_FUNC2, 128 + PMIC_GPIO_FUNC_DTEST1, PMIC_GPIO_FUNC_DTEST2, 129 + PMIC_GPIO_FUNC_DTEST3, PMIC_GPIO_FUNC_DTEST4, 130 + }; 131 + 132 + static int pm8xxx_read_bank(struct pm8xxx_gpio *pctrl, 133 + struct pm8xxx_pin_data *pin, int bank) 134 + { 135 + unsigned int val = bank << 4; 136 + int ret; 137 + 138 + ret = regmap_write(pctrl->regmap, pin->reg, val); 139 + if (ret) { 140 + dev_err(pctrl->dev, "failed to select bank %d\n", bank); 141 + return ret; 142 + } 143 + 144 + ret = regmap_read(pctrl->regmap, pin->reg, &val); 145 + if (ret) { 146 + dev_err(pctrl->dev, "failed to read register %d\n", bank); 147 + return ret; 148 + } 149 + 150 + return val; 151 + } 152 + 153 + static int pm8xxx_write_bank(struct pm8xxx_gpio *pctrl, 154 + struct pm8xxx_pin_data *pin, 155 + int bank, 156 + u8 val) 157 + { 158 + int ret; 159 + 160 + val |= PM8XXX_BANK_WRITE; 161 + val |= bank << 4; 162 + 163 + ret = regmap_write(pctrl->regmap, pin->reg, val); 164 + if (ret) 165 + dev_err(pctrl->dev, "failed to write register\n"); 166 + 167 + return ret; 168 + } 169 + 170 + static int pm8xxx_get_groups_count(struct pinctrl_dev *pctldev) 171 + { 172 + struct pm8xxx_gpio *pctrl = pinctrl_dev_get_drvdata(pctldev); 173 + 174 + return pctrl->npins; 175 + } 176 + 177 + static const char *pm8xxx_get_group_name(struct pinctrl_dev *pctldev, 178 + unsigned group) 179 + { 180 + return pm8xxx_groups[group]; 181 + } 182 + 183 + 184 + static int pm8xxx_get_group_pins(struct pinctrl_dev *pctldev, 185 + unsigned group, 186 + const unsigned **pins, 187 + unsigned *num_pins) 188 + { 189 + struct pm8xxx_gpio *pctrl = pinctrl_dev_get_drvdata(pctldev); 190 + 191 + *pins = &pctrl->desc.pins[group].number; 192 + *num_pins = 1; 193 + 194 + return 0; 195 + } 196 + 197 + static const struct pinctrl_ops pm8xxx_pinctrl_ops = { 198 + .get_groups_count = pm8xxx_get_groups_count, 199 + .get_group_name = pm8xxx_get_group_name, 200 + .get_group_pins = pm8xxx_get_group_pins, 201 + .dt_node_to_map = pinconf_generic_dt_node_to_map_group, 202 + .dt_free_map = pinctrl_utils_dt_free_map, 203 + }; 204 + 205 + static int pm8xxx_get_functions_count(struct pinctrl_dev *pctldev) 206 + { 207 + return ARRAY_SIZE(pm8xxx_gpio_functions); 208 + } 209 + 210 + static const char *pm8xxx_get_function_name(struct pinctrl_dev *pctldev, 211 + unsigned function) 212 + { 213 + return pm8xxx_gpio_functions[function]; 214 + } 215 + 216 + static int pm8xxx_get_function_groups(struct pinctrl_dev *pctldev, 217 + unsigned function, 218 + const char * const **groups, 219 + unsigned * const num_groups) 220 + { 221 + struct pm8xxx_gpio *pctrl = pinctrl_dev_get_drvdata(pctldev); 222 + 223 + *groups = pm8xxx_groups; 224 + *num_groups = pctrl->npins; 225 + return 0; 226 + } 227 + 228 + static int pm8xxx_pinmux_set_mux(struct pinctrl_dev *pctldev, 229 + unsigned function, 230 + unsigned group) 231 + { 232 + struct pm8xxx_gpio *pctrl = pinctrl_dev_get_drvdata(pctldev); 233 + struct pm8xxx_pin_data *pin = pctrl->desc.pins[group].drv_data; 234 + u8 val; 235 + 236 + pin->function = function; 237 + val = pin->function << 1; 238 + 239 + pm8xxx_write_bank(pctrl, pin, 4, val); 240 + 241 + return 0; 242 + } 243 + 244 + static const struct pinmux_ops pm8xxx_pinmux_ops = { 245 + .get_functions_count = pm8xxx_get_functions_count, 246 + .get_function_name = pm8xxx_get_function_name, 247 + .get_function_groups = pm8xxx_get_function_groups, 248 + .set_mux = pm8xxx_pinmux_set_mux, 249 + }; 250 + 251 + static int pm8xxx_pin_config_get(struct pinctrl_dev *pctldev, 252 + unsigned int offset, 253 + unsigned long *config) 254 + { 255 + struct pm8xxx_gpio *pctrl = pinctrl_dev_get_drvdata(pctldev); 256 + struct pm8xxx_pin_data *pin = pctrl->desc.pins[offset].drv_data; 257 + unsigned param = pinconf_to_config_param(*config); 258 + unsigned arg; 259 + 260 + switch (param) { 261 + case PIN_CONFIG_BIAS_DISABLE: 262 + arg = pin->bias == PM8XXX_GPIO_BIAS_NP; 263 + break; 264 + case PIN_CONFIG_BIAS_PULL_DOWN: 265 + arg = pin->bias == PM8XXX_GPIO_BIAS_PD; 266 + break; 267 + case PIN_CONFIG_BIAS_PULL_UP: 268 + arg = pin->bias <= PM8XXX_GPIO_BIAS_PU_1P5_30; 269 + break; 270 + case PM8XXX_QCOM_PULL_UP_STRENGTH: 271 + arg = pin->pull_up_strength; 272 + break; 273 + case PIN_CONFIG_BIAS_HIGH_IMPEDANCE: 274 + arg = pin->disable; 275 + break; 276 + case PIN_CONFIG_INPUT_ENABLE: 277 + arg = pin->mode == PM8XXX_GPIO_MODE_INPUT; 278 + break; 279 + case PIN_CONFIG_OUTPUT: 280 + if (pin->mode & PM8XXX_GPIO_MODE_OUTPUT) 281 + arg = pin->output_value; 282 + else 283 + arg = 0; 284 + break; 285 + case PIN_CONFIG_POWER_SOURCE: 286 + arg = pin->power_source; 287 + break; 288 + case PM8XXX_QCOM_DRIVE_STRENGH: 289 + arg = pin->output_strength; 290 + break; 291 + case PIN_CONFIG_DRIVE_PUSH_PULL: 292 + arg = !pin->open_drain; 293 + break; 294 + case PIN_CONFIG_DRIVE_OPEN_DRAIN: 295 + arg = pin->open_drain; 296 + break; 297 + default: 298 + return -EINVAL; 299 + } 300 + 301 + *config = pinconf_to_config_packed(param, arg); 302 + 303 + return 0; 304 + } 305 + 306 + static int pm8xxx_pin_config_set(struct pinctrl_dev *pctldev, 307 + unsigned int offset, 308 + unsigned long *configs, 309 + unsigned num_configs) 310 + { 311 + struct pm8xxx_gpio *pctrl = pinctrl_dev_get_drvdata(pctldev); 312 + struct pm8xxx_pin_data *pin = pctrl->desc.pins[offset].drv_data; 313 + unsigned param; 314 + unsigned arg; 315 + unsigned i; 316 + u8 banks = 0; 317 + u8 val; 318 + 319 + for (i = 0; i < num_configs; i++) { 320 + param = pinconf_to_config_param(configs[i]); 321 + arg = pinconf_to_config_argument(configs[i]); 322 + 323 + switch (param) { 324 + case PIN_CONFIG_BIAS_DISABLE: 325 + pin->bias = PM8XXX_GPIO_BIAS_NP; 326 + banks |= BIT(2); 327 + pin->disable = 0; 328 + banks |= BIT(3); 329 + break; 330 + case PIN_CONFIG_BIAS_PULL_DOWN: 331 + pin->bias = PM8XXX_GPIO_BIAS_PD; 332 + banks |= BIT(2); 333 + pin->disable = 0; 334 + banks |= BIT(3); 335 + break; 336 + case PM8XXX_QCOM_PULL_UP_STRENGTH: 337 + if (arg > PM8XXX_GPIO_BIAS_PU_1P5_30) { 338 + dev_err(pctrl->dev, "invalid pull-up strength\n"); 339 + return -EINVAL; 340 + } 341 + pin->pull_up_strength = arg; 342 + /* FALLTHROUGH */ 343 + case PIN_CONFIG_BIAS_PULL_UP: 344 + pin->bias = pin->pull_up_strength; 345 + banks |= BIT(2); 346 + pin->disable = 0; 347 + banks |= BIT(3); 348 + break; 349 + case PIN_CONFIG_BIAS_HIGH_IMPEDANCE: 350 + pin->disable = 1; 351 + banks |= BIT(3); 352 + break; 353 + case PIN_CONFIG_INPUT_ENABLE: 354 + pin->mode = PM8XXX_GPIO_MODE_INPUT; 355 + banks |= BIT(0) | BIT(1); 356 + break; 357 + case PIN_CONFIG_OUTPUT: 358 + pin->mode = PM8XXX_GPIO_MODE_OUTPUT; 359 + pin->output_value = !!arg; 360 + banks |= BIT(0) | BIT(1); 361 + break; 362 + case PIN_CONFIG_POWER_SOURCE: 363 + pin->power_source = arg; 364 + banks |= BIT(0); 365 + break; 366 + case PM8XXX_QCOM_DRIVE_STRENGH: 367 + if (arg > PMIC_GPIO_STRENGTH_LOW) { 368 + dev_err(pctrl->dev, "invalid drive strength\n"); 369 + return -EINVAL; 370 + } 371 + pin->output_strength = arg; 372 + banks |= BIT(3); 373 + break; 374 + case PIN_CONFIG_DRIVE_PUSH_PULL: 375 + pin->open_drain = 0; 376 + banks |= BIT(1); 377 + break; 378 + case PIN_CONFIG_DRIVE_OPEN_DRAIN: 379 + pin->open_drain = 1; 380 + banks |= BIT(1); 381 + break; 382 + default: 383 + dev_err(pctrl->dev, 384 + "unsupported config parameter: %x\n", 385 + param); 386 + return -EINVAL; 387 + } 388 + } 389 + 390 + if (banks & BIT(0)) { 391 + val = pin->power_source << 1; 392 + val |= PM8XXX_GPIO_MODE_ENABLED; 393 + pm8xxx_write_bank(pctrl, pin, 0, val); 394 + } 395 + 396 + if (banks & BIT(1)) { 397 + val = pin->mode << 2; 398 + val |= pin->open_drain << 1; 399 + val |= pin->output_value; 400 + pm8xxx_write_bank(pctrl, pin, 1, val); 401 + } 402 + 403 + if (banks & BIT(2)) { 404 + val = pin->bias << 1; 405 + pm8xxx_write_bank(pctrl, pin, 2, val); 406 + } 407 + 408 + if (banks & BIT(3)) { 409 + val = pin->output_strength << 2; 410 + val |= pin->disable; 411 + pm8xxx_write_bank(pctrl, pin, 3, val); 412 + } 413 + 414 + if (banks & BIT(4)) { 415 + val = pin->function << 1; 416 + pm8xxx_write_bank(pctrl, pin, 4, val); 417 + } 418 + 419 + if (banks & BIT(5)) { 420 + val = 0; 421 + if (!pin->inverted) 422 + val |= BIT(3); 423 + pm8xxx_write_bank(pctrl, pin, 5, val); 424 + } 425 + 426 + return 0; 427 + } 428 + 429 + static const struct pinconf_ops pm8xxx_pinconf_ops = { 430 + .is_generic = true, 431 + .pin_config_group_get = pm8xxx_pin_config_get, 432 + .pin_config_group_set = pm8xxx_pin_config_set, 433 + }; 434 + 435 + static struct pinctrl_desc pm8xxx_pinctrl_desc = { 436 + .name = "pm8xxx_gpio", 437 + .pctlops = &pm8xxx_pinctrl_ops, 438 + .pmxops = &pm8xxx_pinmux_ops, 439 + .confops = &pm8xxx_pinconf_ops, 440 + .owner = THIS_MODULE, 441 + }; 442 + 443 + static int pm8xxx_gpio_direction_input(struct gpio_chip *chip, 444 + unsigned offset) 445 + { 446 + struct pm8xxx_gpio *pctrl = container_of(chip, struct pm8xxx_gpio, chip); 447 + struct pm8xxx_pin_data *pin = pctrl->desc.pins[offset].drv_data; 448 + u8 val; 449 + 450 + pin->mode = PM8XXX_GPIO_MODE_INPUT; 451 + val = pin->mode << 2; 452 + 453 + pm8xxx_write_bank(pctrl, pin, 1, val); 454 + 455 + return 0; 456 + } 457 + 458 + static int pm8xxx_gpio_direction_output(struct gpio_chip *chip, 459 + unsigned offset, 460 + int value) 461 + { 462 + struct pm8xxx_gpio *pctrl = container_of(chip, struct pm8xxx_gpio, chip); 463 + struct pm8xxx_pin_data *pin = pctrl->desc.pins[offset].drv_data; 464 + u8 val; 465 + 466 + pin->mode = PM8XXX_GPIO_MODE_OUTPUT; 467 + pin->output_value = !!value; 468 + 469 + val = pin->mode << 2; 470 + val |= pin->open_drain << 1; 471 + val |= pin->output_value; 472 + 473 + pm8xxx_write_bank(pctrl, pin, 1, val); 474 + 475 + return 0; 476 + } 477 + 478 + static int pm8xxx_gpio_get(struct gpio_chip *chip, unsigned offset) 479 + { 480 + struct pm8xxx_gpio *pctrl = container_of(chip, struct pm8xxx_gpio, chip); 481 + struct pm8xxx_pin_data *pin = pctrl->desc.pins[offset].drv_data; 482 + bool state; 483 + int ret; 484 + 485 + if (pin->mode == PM8XXX_GPIO_MODE_OUTPUT) { 486 + ret = pin->output_value; 487 + } else { 488 + ret = irq_get_irqchip_state(pin->irq, IRQCHIP_STATE_LINE_LEVEL, &state); 489 + if (!ret) 490 + ret = !!state; 491 + } 492 + 493 + return ret; 494 + } 495 + 496 + static void pm8xxx_gpio_set(struct gpio_chip *chip, unsigned offset, int value) 497 + { 498 + struct pm8xxx_gpio *pctrl = container_of(chip, struct pm8xxx_gpio, chip); 499 + struct pm8xxx_pin_data *pin = pctrl->desc.pins[offset].drv_data; 500 + u8 val; 501 + 502 + pin->output_value = !!value; 503 + 504 + val = pin->mode << 2; 505 + val |= pin->open_drain << 1; 506 + val |= pin->output_value; 507 + 508 + pm8xxx_write_bank(pctrl, pin, 1, val); 509 + } 510 + 511 + static int pm8xxx_gpio_of_xlate(struct gpio_chip *chip, 512 + const struct of_phandle_args *gpio_desc, 513 + u32 *flags) 514 + { 515 + if (chip->of_gpio_n_cells < 2) 516 + return -EINVAL; 517 + 518 + if (flags) 519 + *flags = gpio_desc->args[1]; 520 + 521 + return gpio_desc->args[0] - 1; 522 + } 523 + 524 + 525 + static int pm8xxx_gpio_to_irq(struct gpio_chip *chip, unsigned offset) 526 + { 527 + struct pm8xxx_gpio *pctrl = container_of(chip, struct pm8xxx_gpio, chip); 528 + struct pm8xxx_pin_data *pin = pctrl->desc.pins[offset].drv_data; 529 + 530 + return pin->irq; 531 + } 532 + 533 + #ifdef CONFIG_DEBUG_FS 534 + #include <linux/seq_file.h> 535 + 536 + static void pm8xxx_gpio_dbg_show_one(struct seq_file *s, 537 + struct pinctrl_dev *pctldev, 538 + struct gpio_chip *chip, 539 + unsigned offset, 540 + unsigned gpio) 541 + { 542 + struct pm8xxx_gpio *pctrl = container_of(chip, struct pm8xxx_gpio, chip); 543 + struct pm8xxx_pin_data *pin = pctrl->desc.pins[offset].drv_data; 544 + 545 + static const char * const modes[] = { 546 + "in", "both", "out", "off" 547 + }; 548 + static const char * const biases[] = { 549 + "pull-up 30uA", "pull-up 1.5uA", "pull-up 31.5uA", 550 + "pull-up 1.5uA + 30uA boost", "pull-down 10uA", "no pull" 551 + }; 552 + static const char * const buffer_types[] = { 553 + "push-pull", "open-drain" 554 + }; 555 + static const char * const strengths[] = { 556 + "no", "high", "medium", "low" 557 + }; 558 + 559 + seq_printf(s, " gpio%-2d:", offset + 1); 560 + if (pin->disable) { 561 + seq_puts(s, " ---"); 562 + } else { 563 + seq_printf(s, " %-4s", modes[pin->mode]); 564 + seq_printf(s, " %-7s", pm8xxx_gpio_functions[pin->function]); 565 + seq_printf(s, " VIN%d", pin->power_source); 566 + seq_printf(s, " %-27s", biases[pin->bias]); 567 + seq_printf(s, " %-10s", buffer_types[pin->open_drain]); 568 + seq_printf(s, " %-4s", pin->output_value ? "high" : "low"); 569 + seq_printf(s, " %-7s", strengths[pin->output_strength]); 570 + if (pin->inverted) 571 + seq_puts(s, " inverted"); 572 + } 573 + } 574 + 575 + static void pm8xxx_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip) 576 + { 577 + unsigned gpio = chip->base; 578 + unsigned i; 579 + 580 + for (i = 0; i < chip->ngpio; i++, gpio++) { 581 + pm8xxx_gpio_dbg_show_one(s, NULL, chip, i, gpio); 582 + seq_puts(s, "\n"); 583 + } 584 + } 585 + 586 + #else 587 + #define msm_gpio_dbg_show NULL 588 + #endif 589 + 590 + static struct gpio_chip pm8xxx_gpio_template = { 591 + .direction_input = pm8xxx_gpio_direction_input, 592 + .direction_output = pm8xxx_gpio_direction_output, 593 + .get = pm8xxx_gpio_get, 594 + .set = pm8xxx_gpio_set, 595 + .of_xlate = pm8xxx_gpio_of_xlate, 596 + .to_irq = pm8xxx_gpio_to_irq, 597 + .dbg_show = pm8xxx_gpio_dbg_show, 598 + .owner = THIS_MODULE, 599 + }; 600 + 601 + static int pm8xxx_pin_populate(struct pm8xxx_gpio *pctrl, 602 + struct pm8xxx_pin_data *pin) 603 + { 604 + int val; 605 + 606 + val = pm8xxx_read_bank(pctrl, pin, 0); 607 + if (val < 0) 608 + return val; 609 + 610 + pin->power_source = (val >> 1) & 0x7; 611 + 612 + val = pm8xxx_read_bank(pctrl, pin, 1); 613 + if (val < 0) 614 + return val; 615 + 616 + pin->mode = (val >> 2) & 0x3; 617 + pin->open_drain = !!(val & BIT(1)); 618 + pin->output_value = val & BIT(0); 619 + 620 + val = pm8xxx_read_bank(pctrl, pin, 2); 621 + if (val < 0) 622 + return val; 623 + 624 + pin->bias = (val >> 1) & 0x7; 625 + if (pin->bias <= PM8XXX_GPIO_BIAS_PU_1P5_30) 626 + pin->pull_up_strength = pin->bias; 627 + else 628 + pin->pull_up_strength = PM8XXX_GPIO_BIAS_PU_30; 629 + 630 + val = pm8xxx_read_bank(pctrl, pin, 3); 631 + if (val < 0) 632 + return val; 633 + 634 + pin->output_strength = (val >> 2) & 0x3; 635 + pin->disable = val & BIT(0); 636 + 637 + val = pm8xxx_read_bank(pctrl, pin, 4); 638 + if (val < 0) 639 + return val; 640 + 641 + pin->function = (val >> 1) & 0x7; 642 + 643 + val = pm8xxx_read_bank(pctrl, pin, 5); 644 + if (val < 0) 645 + return val; 646 + 647 + pin->inverted = !(val & BIT(3)); 648 + 649 + return 0; 650 + } 651 + 652 + static const struct of_device_id pm8xxx_gpio_of_match[] = { 653 + { .compatible = "qcom,pm8018-gpio", .data = (void *)6 }, 654 + { .compatible = "qcom,pm8038-gpio", .data = (void *)12 }, 655 + { .compatible = "qcom,pm8058-gpio", .data = (void *)40 }, 656 + { .compatible = "qcom,pm8917-gpio", .data = (void *)38 }, 657 + { .compatible = "qcom,pm8921-gpio", .data = (void *)44 }, 658 + { }, 659 + }; 660 + MODULE_DEVICE_TABLE(of, pm8xxx_gpio_of_match); 661 + 662 + static int pm8xxx_gpio_probe(struct platform_device *pdev) 663 + { 664 + struct pm8xxx_pin_data *pin_data; 665 + struct pinctrl_pin_desc *pins; 666 + struct pm8xxx_gpio *pctrl; 667 + int ret; 668 + int i; 669 + 670 + pctrl = devm_kzalloc(&pdev->dev, sizeof(*pctrl), GFP_KERNEL); 671 + if (!pctrl) 672 + return -ENOMEM; 673 + 674 + pctrl->dev = &pdev->dev; 675 + pctrl->npins = (unsigned)of_device_get_match_data(&pdev->dev); 676 + 677 + pctrl->regmap = dev_get_regmap(pdev->dev.parent, NULL); 678 + if (!pctrl->regmap) { 679 + dev_err(&pdev->dev, "parent regmap unavailable\n"); 680 + return -ENXIO; 681 + } 682 + 683 + pctrl->desc = pm8xxx_pinctrl_desc; 684 + pctrl->desc.npins = pctrl->npins; 685 + 686 + pins = devm_kcalloc(&pdev->dev, 687 + pctrl->desc.npins, 688 + sizeof(struct pinctrl_pin_desc), 689 + GFP_KERNEL); 690 + if (!pins) 691 + return -ENOMEM; 692 + 693 + pin_data = devm_kcalloc(&pdev->dev, 694 + pctrl->desc.npins, 695 + sizeof(struct pm8xxx_pin_data), 696 + GFP_KERNEL); 697 + if (!pin_data) 698 + return -ENOMEM; 699 + 700 + for (i = 0; i < pctrl->desc.npins; i++) { 701 + pin_data[i].reg = SSBI_REG_ADDR_GPIO(i); 702 + pin_data[i].irq = platform_get_irq(pdev, i); 703 + if (pin_data[i].irq < 0) { 704 + dev_err(&pdev->dev, 705 + "missing interrupts for pin %d\n", i); 706 + return pin_data[i].irq; 707 + } 708 + 709 + ret = pm8xxx_pin_populate(pctrl, &pin_data[i]); 710 + if (ret) 711 + return ret; 712 + 713 + pins[i].number = i; 714 + pins[i].name = pm8xxx_groups[i]; 715 + pins[i].drv_data = &pin_data[i]; 716 + } 717 + pctrl->desc.pins = pins; 718 + 719 + pctrl->desc.num_custom_params = ARRAY_SIZE(pm8xxx_gpio_bindings); 720 + pctrl->desc.custom_params = pm8xxx_gpio_bindings; 721 + #ifdef CONFIG_DEBUG_FS 722 + pctrl->desc.custom_conf_items = pm8xxx_conf_items; 723 + #endif 724 + 725 + pctrl->pctrl = pinctrl_register(&pctrl->desc, &pdev->dev, pctrl); 726 + if (!pctrl->pctrl) { 727 + dev_err(&pdev->dev, "couldn't register pm8xxx gpio driver\n"); 728 + return -ENODEV; 729 + } 730 + 731 + pctrl->chip = pm8xxx_gpio_template; 732 + pctrl->chip.base = -1; 733 + pctrl->chip.dev = &pdev->dev; 734 + pctrl->chip.of_node = pdev->dev.of_node; 735 + pctrl->chip.of_gpio_n_cells = 2; 736 + pctrl->chip.label = dev_name(pctrl->dev); 737 + pctrl->chip.ngpio = pctrl->npins; 738 + ret = gpiochip_add(&pctrl->chip); 739 + if (ret) { 740 + dev_err(&pdev->dev, "failed register gpiochip\n"); 741 + goto unregister_pinctrl; 742 + } 743 + 744 + ret = gpiochip_add_pin_range(&pctrl->chip, 745 + dev_name(pctrl->dev), 746 + 0, 0, pctrl->chip.ngpio); 747 + if (ret) { 748 + dev_err(pctrl->dev, "failed to add pin range\n"); 749 + goto unregister_gpiochip; 750 + } 751 + 752 + platform_set_drvdata(pdev, pctrl); 753 + 754 + dev_dbg(&pdev->dev, "Qualcomm pm8xxx gpio driver probed\n"); 755 + 756 + return 0; 757 + 758 + unregister_gpiochip: 759 + gpiochip_remove(&pctrl->chip); 760 + 761 + unregister_pinctrl: 762 + pinctrl_unregister(pctrl->pctrl); 763 + 764 + return ret; 765 + } 766 + 767 + static int pm8xxx_gpio_remove(struct platform_device *pdev) 768 + { 769 + struct pm8xxx_gpio *pctrl = platform_get_drvdata(pdev); 770 + 771 + gpiochip_remove(&pctrl->chip); 772 + 773 + pinctrl_unregister(pctrl->pctrl); 774 + 775 + return 0; 776 + } 777 + 778 + static struct platform_driver pm8xxx_gpio_driver = { 779 + .driver = { 780 + .name = "qcom-ssbi-gpio", 781 + .of_match_table = pm8xxx_gpio_of_match, 782 + }, 783 + .probe = pm8xxx_gpio_probe, 784 + .remove = pm8xxx_gpio_remove, 785 + }; 786 + 787 + module_platform_driver(pm8xxx_gpio_driver); 788 + 789 + MODULE_AUTHOR("Bjorn Andersson <bjorn.andersson@sonymobile.com>"); 790 + MODULE_DESCRIPTION("Qualcomm PM8xxx GPIO driver"); 791 + MODULE_LICENSE("GPL v2");
+882
drivers/pinctrl/qcom/pinctrl-ssbi-mpp.c
··· 1 + /* 2 + * Copyright (c) 2015, Sony Mobile Communications AB. 3 + * Copyright (c) 2013, The Linux Foundation. All rights reserved. 4 + * 5 + * This program is free software; you can redistribute it and/or modify 6 + * it under the terms of the GNU General Public License version 2 and 7 + * only version 2 as published by the Free Software Foundation. 8 + * 9 + * This program is distributed in the hope that it will be useful, 10 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 + * GNU General Public License for more details. 13 + */ 14 + 15 + #include <linux/module.h> 16 + #include <linux/platform_device.h> 17 + #include <linux/pinctrl/pinctrl.h> 18 + #include <linux/pinctrl/pinmux.h> 19 + #include <linux/pinctrl/pinconf.h> 20 + #include <linux/pinctrl/pinconf-generic.h> 21 + #include <linux/slab.h> 22 + #include <linux/regmap.h> 23 + #include <linux/gpio.h> 24 + #include <linux/interrupt.h> 25 + #include <linux/of_device.h> 26 + 27 + #include <dt-bindings/pinctrl/qcom,pmic-mpp.h> 28 + 29 + #include "../core.h" 30 + #include "../pinctrl-utils.h" 31 + 32 + /* MPP registers */ 33 + #define SSBI_REG_ADDR_MPP_BASE 0x50 34 + #define SSBI_REG_ADDR_MPP(n) (SSBI_REG_ADDR_MPP_BASE + n) 35 + 36 + /* MPP Type: type */ 37 + #define PM8XXX_MPP_TYPE_D_INPUT 0 38 + #define PM8XXX_MPP_TYPE_D_OUTPUT 1 39 + #define PM8XXX_MPP_TYPE_D_BI_DIR 2 40 + #define PM8XXX_MPP_TYPE_A_INPUT 3 41 + #define PM8XXX_MPP_TYPE_A_OUTPUT 4 42 + #define PM8XXX_MPP_TYPE_SINK 5 43 + #define PM8XXX_MPP_TYPE_DTEST_SINK 6 44 + #define PM8XXX_MPP_TYPE_DTEST_OUTPUT 7 45 + 46 + /* Digital Input: control */ 47 + #define PM8XXX_MPP_DIN_TO_INT 0 48 + #define PM8XXX_MPP_DIN_TO_DBUS1 1 49 + #define PM8XXX_MPP_DIN_TO_DBUS2 2 50 + #define PM8XXX_MPP_DIN_TO_DBUS3 3 51 + 52 + /* Digital Output: control */ 53 + #define PM8XXX_MPP_DOUT_CTRL_LOW 0 54 + #define PM8XXX_MPP_DOUT_CTRL_HIGH 1 55 + #define PM8XXX_MPP_DOUT_CTRL_MPP 2 56 + #define PM8XXX_MPP_DOUT_CTRL_INV_MPP 3 57 + 58 + /* Bidirectional: control */ 59 + #define PM8XXX_MPP_BI_PULLUP_1KOHM 0 60 + #define PM8XXX_MPP_BI_PULLUP_OPEN 1 61 + #define PM8XXX_MPP_BI_PULLUP_10KOHM 2 62 + #define PM8XXX_MPP_BI_PULLUP_30KOHM 3 63 + 64 + /* Analog Output: control */ 65 + #define PM8XXX_MPP_AOUT_CTRL_DISABLE 0 66 + #define PM8XXX_MPP_AOUT_CTRL_ENABLE 1 67 + #define PM8XXX_MPP_AOUT_CTRL_MPP_HIGH_EN 2 68 + #define PM8XXX_MPP_AOUT_CTRL_MPP_LOW_EN 3 69 + 70 + /* Current Sink: control */ 71 + #define PM8XXX_MPP_CS_CTRL_DISABLE 0 72 + #define PM8XXX_MPP_CS_CTRL_ENABLE 1 73 + #define PM8XXX_MPP_CS_CTRL_MPP_HIGH_EN 2 74 + #define PM8XXX_MPP_CS_CTRL_MPP_LOW_EN 3 75 + 76 + /* DTEST Current Sink: control */ 77 + #define PM8XXX_MPP_DTEST_CS_CTRL_EN1 0 78 + #define PM8XXX_MPP_DTEST_CS_CTRL_EN2 1 79 + #define PM8XXX_MPP_DTEST_CS_CTRL_EN3 2 80 + #define PM8XXX_MPP_DTEST_CS_CTRL_EN4 3 81 + 82 + /* DTEST Digital Output: control */ 83 + #define PM8XXX_MPP_DTEST_DBUS1 0 84 + #define PM8XXX_MPP_DTEST_DBUS2 1 85 + #define PM8XXX_MPP_DTEST_DBUS3 2 86 + #define PM8XXX_MPP_DTEST_DBUS4 3 87 + 88 + /* custom pinconf parameters */ 89 + #define PM8XXX_CONFIG_AMUX (PIN_CONFIG_END + 1) 90 + #define PM8XXX_CONFIG_DTEST_SELECTOR (PIN_CONFIG_END + 2) 91 + #define PM8XXX_CONFIG_ALEVEL (PIN_CONFIG_END + 3) 92 + #define PM8XXX_CONFIG_PAIRED (PIN_CONFIG_END + 4) 93 + 94 + /** 95 + * struct pm8xxx_pin_data - dynamic configuration for a pin 96 + * @reg: address of the control register 97 + * @irq: IRQ from the PMIC interrupt controller 98 + * @mode: operating mode for the pin (digital, analog or current sink) 99 + * @input: pin is input 100 + * @output: pin is output 101 + * @high_z: pin is floating 102 + * @paired: mpp operates in paired mode 103 + * @output_value: logical output value of the mpp 104 + * @power_source: selected power source 105 + * @dtest: DTEST route selector 106 + * @amux: input muxing in analog mode 107 + * @aout_level: selector of the output in analog mode 108 + * @drive_strength: drive strength of the current sink 109 + * @pullup: pull up value, when in digital bidirectional mode 110 + */ 111 + struct pm8xxx_pin_data { 112 + unsigned reg; 113 + int irq; 114 + 115 + u8 mode; 116 + 117 + bool input; 118 + bool output; 119 + bool high_z; 120 + bool paired; 121 + bool output_value; 122 + 123 + u8 power_source; 124 + u8 dtest; 125 + u8 amux; 126 + u8 aout_level; 127 + u8 drive_strength; 128 + unsigned pullup; 129 + }; 130 + 131 + struct pm8xxx_mpp { 132 + struct device *dev; 133 + struct regmap *regmap; 134 + struct pinctrl_dev *pctrl; 135 + struct gpio_chip chip; 136 + 137 + struct pinctrl_desc desc; 138 + unsigned npins; 139 + }; 140 + 141 + static const struct pinconf_generic_params pm8xxx_mpp_bindings[] = { 142 + {"qcom,amux-route", PM8XXX_CONFIG_AMUX, 0}, 143 + {"qcom,analog-level", PM8XXX_CONFIG_ALEVEL, 0}, 144 + {"qcom,dtest", PM8XXX_CONFIG_DTEST_SELECTOR, 0}, 145 + {"qcom,paired", PM8XXX_CONFIG_PAIRED, 0}, 146 + }; 147 + 148 + #ifdef CONFIG_DEBUG_FS 149 + static const struct pin_config_item pm8xxx_conf_items[] = { 150 + PCONFDUMP(PM8XXX_CONFIG_AMUX, "analog mux", NULL, true), 151 + PCONFDUMP(PM8XXX_CONFIG_ALEVEL, "analog level", NULL, true), 152 + PCONFDUMP(PM8XXX_CONFIG_DTEST_SELECTOR, "dtest", NULL, true), 153 + PCONFDUMP(PM8XXX_CONFIG_PAIRED, "paired", NULL, false), 154 + }; 155 + #endif 156 + 157 + #define PM8XXX_MAX_MPPS 12 158 + static const char * const pm8xxx_groups[PM8XXX_MAX_MPPS] = { 159 + "mpp1", "mpp2", "mpp3", "mpp4", "mpp5", "mpp6", "mpp7", "mpp8", 160 + "mpp9", "mpp10", "mpp11", "mpp12", 161 + }; 162 + 163 + #define PM8XXX_MPP_DIGITAL 0 164 + #define PM8XXX_MPP_ANALOG 1 165 + #define PM8XXX_MPP_SINK 2 166 + 167 + static const char * const pm8xxx_mpp_functions[] = { 168 + "digital", "analog", "sink", 169 + }; 170 + 171 + static int pm8xxx_mpp_update(struct pm8xxx_mpp *pctrl, 172 + struct pm8xxx_pin_data *pin) 173 + { 174 + unsigned level; 175 + unsigned ctrl; 176 + unsigned type; 177 + int ret; 178 + u8 val; 179 + 180 + switch (pin->mode) { 181 + case PM8XXX_MPP_DIGITAL: 182 + if (pin->dtest) { 183 + type = PM8XXX_MPP_TYPE_DTEST_OUTPUT; 184 + ctrl = pin->dtest - 1; 185 + } else if (pin->input && pin->output) { 186 + type = PM8XXX_MPP_TYPE_D_BI_DIR; 187 + if (pin->high_z) 188 + ctrl = PM8XXX_MPP_BI_PULLUP_OPEN; 189 + else if (pin->pullup == 600) 190 + ctrl = PM8XXX_MPP_BI_PULLUP_1KOHM; 191 + else if (pin->pullup == 10000) 192 + ctrl = PM8XXX_MPP_BI_PULLUP_10KOHM; 193 + else 194 + ctrl = PM8XXX_MPP_BI_PULLUP_30KOHM; 195 + } else if (pin->input) { 196 + type = PM8XXX_MPP_TYPE_D_INPUT; 197 + if (pin->dtest) 198 + ctrl = pin->dtest; 199 + else 200 + ctrl = PM8XXX_MPP_DIN_TO_INT; 201 + } else { 202 + type = PM8XXX_MPP_TYPE_D_OUTPUT; 203 + ctrl = !!pin->output_value; 204 + if (pin->paired) 205 + ctrl |= BIT(1); 206 + } 207 + 208 + level = pin->power_source; 209 + break; 210 + case PM8XXX_MPP_ANALOG: 211 + if (pin->output) { 212 + type = PM8XXX_MPP_TYPE_A_OUTPUT; 213 + level = pin->aout_level; 214 + ctrl = pin->output_value; 215 + if (pin->paired) 216 + ctrl |= BIT(1); 217 + } else { 218 + type = PM8XXX_MPP_TYPE_A_INPUT; 219 + level = pin->amux; 220 + ctrl = 0; 221 + } 222 + break; 223 + case PM8XXX_MPP_SINK: 224 + level = (pin->drive_strength / 5) - 1; 225 + if (pin->dtest) { 226 + type = PM8XXX_MPP_TYPE_DTEST_SINK; 227 + ctrl = pin->dtest - 1; 228 + } else { 229 + type = PM8XXX_MPP_TYPE_SINK; 230 + ctrl = pin->output_value; 231 + if (pin->paired) 232 + ctrl |= BIT(1); 233 + } 234 + break; 235 + default: 236 + return -EINVAL; 237 + } 238 + 239 + val = type << 5 | level << 2 | ctrl; 240 + ret = regmap_write(pctrl->regmap, pin->reg, val); 241 + if (ret) 242 + dev_err(pctrl->dev, "failed to write register\n"); 243 + 244 + return ret; 245 + } 246 + 247 + static int pm8xxx_get_groups_count(struct pinctrl_dev *pctldev) 248 + { 249 + struct pm8xxx_mpp *pctrl = pinctrl_dev_get_drvdata(pctldev); 250 + 251 + return pctrl->npins; 252 + } 253 + 254 + static const char *pm8xxx_get_group_name(struct pinctrl_dev *pctldev, 255 + unsigned group) 256 + { 257 + return pm8xxx_groups[group]; 258 + } 259 + 260 + 261 + static int pm8xxx_get_group_pins(struct pinctrl_dev *pctldev, 262 + unsigned group, 263 + const unsigned **pins, 264 + unsigned *num_pins) 265 + { 266 + struct pm8xxx_mpp *pctrl = pinctrl_dev_get_drvdata(pctldev); 267 + 268 + *pins = &pctrl->desc.pins[group].number; 269 + *num_pins = 1; 270 + 271 + return 0; 272 + } 273 + 274 + static const struct pinctrl_ops pm8xxx_pinctrl_ops = { 275 + .get_groups_count = pm8xxx_get_groups_count, 276 + .get_group_name = pm8xxx_get_group_name, 277 + .get_group_pins = pm8xxx_get_group_pins, 278 + .dt_node_to_map = pinconf_generic_dt_node_to_map_group, 279 + .dt_free_map = pinctrl_utils_dt_free_map, 280 + }; 281 + 282 + static int pm8xxx_get_functions_count(struct pinctrl_dev *pctldev) 283 + { 284 + return ARRAY_SIZE(pm8xxx_mpp_functions); 285 + } 286 + 287 + static const char *pm8xxx_get_function_name(struct pinctrl_dev *pctldev, 288 + unsigned function) 289 + { 290 + return pm8xxx_mpp_functions[function]; 291 + } 292 + 293 + static int pm8xxx_get_function_groups(struct pinctrl_dev *pctldev, 294 + unsigned function, 295 + const char * const **groups, 296 + unsigned * const num_groups) 297 + { 298 + struct pm8xxx_mpp *pctrl = pinctrl_dev_get_drvdata(pctldev); 299 + 300 + *groups = pm8xxx_groups; 301 + *num_groups = pctrl->npins; 302 + return 0; 303 + } 304 + 305 + static int pm8xxx_pinmux_set_mux(struct pinctrl_dev *pctldev, 306 + unsigned function, 307 + unsigned group) 308 + { 309 + struct pm8xxx_mpp *pctrl = pinctrl_dev_get_drvdata(pctldev); 310 + struct pm8xxx_pin_data *pin = pctrl->desc.pins[group].drv_data; 311 + 312 + pin->mode = function; 313 + pm8xxx_mpp_update(pctrl, pin); 314 + 315 + return 0; 316 + } 317 + 318 + static const struct pinmux_ops pm8xxx_pinmux_ops = { 319 + .get_functions_count = pm8xxx_get_functions_count, 320 + .get_function_name = pm8xxx_get_function_name, 321 + .get_function_groups = pm8xxx_get_function_groups, 322 + .set_mux = pm8xxx_pinmux_set_mux, 323 + }; 324 + 325 + static int pm8xxx_pin_config_get(struct pinctrl_dev *pctldev, 326 + unsigned int offset, 327 + unsigned long *config) 328 + { 329 + struct pm8xxx_mpp *pctrl = pinctrl_dev_get_drvdata(pctldev); 330 + struct pm8xxx_pin_data *pin = pctrl->desc.pins[offset].drv_data; 331 + unsigned param = pinconf_to_config_param(*config); 332 + unsigned arg; 333 + 334 + switch (param) { 335 + case PIN_CONFIG_BIAS_PULL_UP: 336 + arg = pin->pullup; 337 + break; 338 + case PIN_CONFIG_BIAS_HIGH_IMPEDANCE: 339 + arg = pin->high_z; 340 + break; 341 + case PIN_CONFIG_INPUT_ENABLE: 342 + arg = pin->input; 343 + break; 344 + case PIN_CONFIG_OUTPUT: 345 + arg = pin->output_value; 346 + break; 347 + case PIN_CONFIG_POWER_SOURCE: 348 + arg = pin->power_source; 349 + break; 350 + case PIN_CONFIG_DRIVE_STRENGTH: 351 + arg = pin->drive_strength; 352 + break; 353 + case PM8XXX_CONFIG_DTEST_SELECTOR: 354 + arg = pin->dtest; 355 + break; 356 + case PM8XXX_CONFIG_AMUX: 357 + arg = pin->amux; 358 + break; 359 + case PM8XXX_CONFIG_ALEVEL: 360 + arg = pin->aout_level; 361 + break; 362 + case PM8XXX_CONFIG_PAIRED: 363 + arg = pin->paired; 364 + break; 365 + default: 366 + return -EINVAL; 367 + } 368 + 369 + *config = pinconf_to_config_packed(param, arg); 370 + 371 + return 0; 372 + } 373 + 374 + static int pm8xxx_pin_config_set(struct pinctrl_dev *pctldev, 375 + unsigned int offset, 376 + unsigned long *configs, 377 + unsigned num_configs) 378 + { 379 + struct pm8xxx_mpp *pctrl = pinctrl_dev_get_drvdata(pctldev); 380 + struct pm8xxx_pin_data *pin = pctrl->desc.pins[offset].drv_data; 381 + unsigned param; 382 + unsigned arg; 383 + unsigned i; 384 + 385 + for (i = 0; i < num_configs; i++) { 386 + param = pinconf_to_config_param(configs[i]); 387 + arg = pinconf_to_config_argument(configs[i]); 388 + 389 + switch (param) { 390 + case PIN_CONFIG_BIAS_PULL_UP: 391 + pin->pullup = arg; 392 + break; 393 + case PIN_CONFIG_BIAS_HIGH_IMPEDANCE: 394 + pin->high_z = true; 395 + break; 396 + case PIN_CONFIG_INPUT_ENABLE: 397 + pin->input = true; 398 + break; 399 + case PIN_CONFIG_OUTPUT: 400 + pin->output = true; 401 + pin->output_value = !!arg; 402 + break; 403 + case PIN_CONFIG_POWER_SOURCE: 404 + pin->power_source = arg; 405 + break; 406 + case PIN_CONFIG_DRIVE_STRENGTH: 407 + pin->drive_strength = arg; 408 + break; 409 + case PM8XXX_CONFIG_DTEST_SELECTOR: 410 + pin->dtest = arg; 411 + break; 412 + case PM8XXX_CONFIG_AMUX: 413 + pin->amux = arg; 414 + break; 415 + case PM8XXX_CONFIG_ALEVEL: 416 + pin->aout_level = arg; 417 + break; 418 + case PM8XXX_CONFIG_PAIRED: 419 + pin->paired = !!arg; 420 + break; 421 + default: 422 + dev_err(pctrl->dev, 423 + "unsupported config parameter: %x\n", 424 + param); 425 + return -EINVAL; 426 + } 427 + } 428 + 429 + pm8xxx_mpp_update(pctrl, pin); 430 + 431 + return 0; 432 + } 433 + 434 + static const struct pinconf_ops pm8xxx_pinconf_ops = { 435 + .is_generic = true, 436 + .pin_config_group_get = pm8xxx_pin_config_get, 437 + .pin_config_group_set = pm8xxx_pin_config_set, 438 + }; 439 + 440 + static struct pinctrl_desc pm8xxx_pinctrl_desc = { 441 + .name = "pm8xxx_mpp", 442 + .pctlops = &pm8xxx_pinctrl_ops, 443 + .pmxops = &pm8xxx_pinmux_ops, 444 + .confops = &pm8xxx_pinconf_ops, 445 + .owner = THIS_MODULE, 446 + }; 447 + 448 + static int pm8xxx_mpp_direction_input(struct gpio_chip *chip, 449 + unsigned offset) 450 + { 451 + struct pm8xxx_mpp *pctrl = container_of(chip, struct pm8xxx_mpp, chip); 452 + struct pm8xxx_pin_data *pin = pctrl->desc.pins[offset].drv_data; 453 + 454 + switch (pin->mode) { 455 + case PM8XXX_MPP_DIGITAL: 456 + pin->input = true; 457 + break; 458 + case PM8XXX_MPP_ANALOG: 459 + pin->input = true; 460 + pin->output = true; 461 + break; 462 + case PM8XXX_MPP_SINK: 463 + return -EINVAL; 464 + } 465 + 466 + pm8xxx_mpp_update(pctrl, pin); 467 + 468 + return 0; 469 + } 470 + 471 + static int pm8xxx_mpp_direction_output(struct gpio_chip *chip, 472 + unsigned offset, 473 + int value) 474 + { 475 + struct pm8xxx_mpp *pctrl = container_of(chip, struct pm8xxx_mpp, chip); 476 + struct pm8xxx_pin_data *pin = pctrl->desc.pins[offset].drv_data; 477 + 478 + switch (pin->mode) { 479 + case PM8XXX_MPP_DIGITAL: 480 + pin->output = true; 481 + break; 482 + case PM8XXX_MPP_ANALOG: 483 + pin->input = false; 484 + pin->output = true; 485 + break; 486 + case PM8XXX_MPP_SINK: 487 + pin->input = false; 488 + pin->output = true; 489 + break; 490 + } 491 + 492 + pm8xxx_mpp_update(pctrl, pin); 493 + 494 + return 0; 495 + } 496 + 497 + static int pm8xxx_mpp_get(struct gpio_chip *chip, unsigned offset) 498 + { 499 + struct pm8xxx_mpp *pctrl = container_of(chip, struct pm8xxx_mpp, chip); 500 + struct pm8xxx_pin_data *pin = pctrl->desc.pins[offset].drv_data; 501 + bool state; 502 + int ret; 503 + 504 + if (!pin->input) 505 + return pin->output_value; 506 + 507 + ret = irq_get_irqchip_state(pin->irq, IRQCHIP_STATE_LINE_LEVEL, &state); 508 + if (!ret) 509 + ret = !!state; 510 + 511 + return ret; 512 + } 513 + 514 + static void pm8xxx_mpp_set(struct gpio_chip *chip, unsigned offset, int value) 515 + { 516 + struct pm8xxx_mpp *pctrl = container_of(chip, struct pm8xxx_mpp, chip); 517 + struct pm8xxx_pin_data *pin = pctrl->desc.pins[offset].drv_data; 518 + 519 + pin->output_value = !!value; 520 + 521 + pm8xxx_mpp_update(pctrl, pin); 522 + } 523 + 524 + static int pm8xxx_mpp_of_xlate(struct gpio_chip *chip, 525 + const struct of_phandle_args *gpio_desc, 526 + u32 *flags) 527 + { 528 + if (chip->of_gpio_n_cells < 2) 529 + return -EINVAL; 530 + 531 + if (flags) 532 + *flags = gpio_desc->args[1]; 533 + 534 + return gpio_desc->args[0] - 1; 535 + } 536 + 537 + 538 + static int pm8xxx_mpp_to_irq(struct gpio_chip *chip, unsigned offset) 539 + { 540 + struct pm8xxx_mpp *pctrl = container_of(chip, struct pm8xxx_mpp, chip); 541 + struct pm8xxx_pin_data *pin = pctrl->desc.pins[offset].drv_data; 542 + 543 + return pin->irq; 544 + } 545 + 546 + #ifdef CONFIG_DEBUG_FS 547 + #include <linux/seq_file.h> 548 + 549 + static void pm8xxx_mpp_dbg_show_one(struct seq_file *s, 550 + struct pinctrl_dev *pctldev, 551 + struct gpio_chip *chip, 552 + unsigned offset, 553 + unsigned gpio) 554 + { 555 + struct pm8xxx_mpp *pctrl = container_of(chip, struct pm8xxx_mpp, chip); 556 + struct pm8xxx_pin_data *pin = pctrl->desc.pins[offset].drv_data; 557 + 558 + static const char * const aout_lvls[] = { 559 + "1v25", "1v25_2", "0v625", "0v3125", "mpp", "abus1", "abus2", 560 + "abus3" 561 + }; 562 + 563 + static const char * const amuxs[] = { 564 + "amux5", "amux6", "amux7", "amux8", "amux9", "abus1", "abus2", 565 + "abus3", 566 + }; 567 + 568 + seq_printf(s, " mpp%-2d:", offset + 1); 569 + 570 + switch (pin->mode) { 571 + case PM8XXX_MPP_DIGITAL: 572 + seq_puts(s, " digital "); 573 + if (pin->dtest) { 574 + seq_printf(s, "dtest%d\n", pin->dtest); 575 + } else if (pin->input && pin->output) { 576 + if (pin->high_z) 577 + seq_puts(s, "bi-dir high-z"); 578 + else 579 + seq_printf(s, "bi-dir %dOhm", pin->pullup); 580 + } else if (pin->input) { 581 + if (pin->dtest) 582 + seq_printf(s, "in dtest%d", pin->dtest); 583 + else 584 + seq_puts(s, "in gpio"); 585 + } else if (pin->output) { 586 + seq_puts(s, "out "); 587 + 588 + if (!pin->paired) { 589 + seq_puts(s, pin->output_value ? 590 + "high" : "low"); 591 + } else { 592 + seq_puts(s, pin->output_value ? 593 + "inverted" : "follow"); 594 + } 595 + } 596 + break; 597 + case PM8XXX_MPP_ANALOG: 598 + seq_puts(s, " analog "); 599 + if (pin->output) { 600 + seq_printf(s, "out %s ", aout_lvls[pin->aout_level]); 601 + if (!pin->paired) { 602 + seq_puts(s, pin->output_value ? 603 + "high" : "low"); 604 + } else { 605 + seq_puts(s, pin->output_value ? 606 + "inverted" : "follow"); 607 + } 608 + } else { 609 + seq_printf(s, "input mux %s", amuxs[pin->amux]); 610 + } 611 + break; 612 + case PM8XXX_MPP_SINK: 613 + seq_printf(s, " sink %dmA ", pin->drive_strength); 614 + if (pin->dtest) { 615 + seq_printf(s, "dtest%d", pin->dtest); 616 + } else { 617 + if (!pin->paired) { 618 + seq_puts(s, pin->output_value ? 619 + "high" : "low"); 620 + } else { 621 + seq_puts(s, pin->output_value ? 622 + "inverted" : "follow"); 623 + } 624 + } 625 + break; 626 + } 627 + 628 + } 629 + 630 + static void pm8xxx_mpp_dbg_show(struct seq_file *s, struct gpio_chip *chip) 631 + { 632 + unsigned gpio = chip->base; 633 + unsigned i; 634 + 635 + for (i = 0; i < chip->ngpio; i++, gpio++) { 636 + pm8xxx_mpp_dbg_show_one(s, NULL, chip, i, gpio); 637 + seq_puts(s, "\n"); 638 + } 639 + } 640 + 641 + #else 642 + #define msm_mpp_dbg_show NULL 643 + #endif 644 + 645 + static struct gpio_chip pm8xxx_mpp_template = { 646 + .direction_input = pm8xxx_mpp_direction_input, 647 + .direction_output = pm8xxx_mpp_direction_output, 648 + .get = pm8xxx_mpp_get, 649 + .set = pm8xxx_mpp_set, 650 + .of_xlate = pm8xxx_mpp_of_xlate, 651 + .to_irq = pm8xxx_mpp_to_irq, 652 + .dbg_show = pm8xxx_mpp_dbg_show, 653 + .owner = THIS_MODULE, 654 + }; 655 + 656 + static int pm8xxx_pin_populate(struct pm8xxx_mpp *pctrl, 657 + struct pm8xxx_pin_data *pin) 658 + { 659 + unsigned int val; 660 + unsigned level; 661 + unsigned ctrl; 662 + unsigned type; 663 + int ret; 664 + 665 + ret = regmap_read(pctrl->regmap, pin->reg, &val); 666 + if (ret) { 667 + dev_err(pctrl->dev, "failed to read register\n"); 668 + return ret; 669 + } 670 + 671 + type = (val >> 5) & 7; 672 + level = (val >> 2) & 7; 673 + ctrl = (val) & 3; 674 + 675 + switch (type) { 676 + case PM8XXX_MPP_TYPE_D_INPUT: 677 + pin->mode = PM8XXX_MPP_DIGITAL; 678 + pin->input = true; 679 + pin->power_source = level; 680 + pin->dtest = ctrl; 681 + break; 682 + case PM8XXX_MPP_TYPE_D_OUTPUT: 683 + pin->mode = PM8XXX_MPP_DIGITAL; 684 + pin->output = true; 685 + pin->power_source = level; 686 + pin->output_value = !!(ctrl & BIT(0)); 687 + pin->paired = !!(ctrl & BIT(1)); 688 + break; 689 + case PM8XXX_MPP_TYPE_D_BI_DIR: 690 + pin->mode = PM8XXX_MPP_DIGITAL; 691 + pin->input = true; 692 + pin->output = true; 693 + pin->power_source = level; 694 + switch (ctrl) { 695 + case PM8XXX_MPP_BI_PULLUP_1KOHM: 696 + pin->pullup = 600; 697 + break; 698 + case PM8XXX_MPP_BI_PULLUP_OPEN: 699 + pin->high_z = true; 700 + break; 701 + case PM8XXX_MPP_BI_PULLUP_10KOHM: 702 + pin->pullup = 10000; 703 + break; 704 + case PM8XXX_MPP_BI_PULLUP_30KOHM: 705 + pin->pullup = 30000; 706 + break; 707 + } 708 + break; 709 + case PM8XXX_MPP_TYPE_A_INPUT: 710 + pin->mode = PM8XXX_MPP_ANALOG; 711 + pin->input = true; 712 + pin->amux = level; 713 + break; 714 + case PM8XXX_MPP_TYPE_A_OUTPUT: 715 + pin->mode = PM8XXX_MPP_ANALOG; 716 + pin->output = true; 717 + pin->aout_level = level; 718 + pin->output_value = !!(ctrl & BIT(0)); 719 + pin->paired = !!(ctrl & BIT(1)); 720 + break; 721 + case PM8XXX_MPP_TYPE_SINK: 722 + pin->mode = PM8XXX_MPP_SINK; 723 + pin->drive_strength = 5 * (level + 1); 724 + pin->output_value = !!(ctrl & BIT(0)); 725 + pin->paired = !!(ctrl & BIT(1)); 726 + break; 727 + case PM8XXX_MPP_TYPE_DTEST_SINK: 728 + pin->mode = PM8XXX_MPP_SINK; 729 + pin->dtest = ctrl + 1; 730 + pin->drive_strength = 5 * (level + 1); 731 + break; 732 + case PM8XXX_MPP_TYPE_DTEST_OUTPUT: 733 + pin->mode = PM8XXX_MPP_DIGITAL; 734 + pin->power_source = level; 735 + if (ctrl >= 1) 736 + pin->dtest = ctrl; 737 + break; 738 + } 739 + 740 + return 0; 741 + } 742 + 743 + static const struct of_device_id pm8xxx_mpp_of_match[] = { 744 + { .compatible = "qcom,pm8018-mpp", .data = (void *)6 }, 745 + { .compatible = "qcom,pm8038-mpp", .data = (void *)6 }, 746 + { .compatible = "qcom,pm8917-mpp", .data = (void *)10 }, 747 + { .compatible = "qcom,pm8821-mpp", .data = (void *)4 }, 748 + { .compatible = "qcom,pm8921-mpp", .data = (void *)12 }, 749 + { }, 750 + }; 751 + MODULE_DEVICE_TABLE(of, pm8xxx_mpp_of_match); 752 + 753 + static int pm8xxx_mpp_probe(struct platform_device *pdev) 754 + { 755 + struct pm8xxx_pin_data *pin_data; 756 + struct pinctrl_pin_desc *pins; 757 + struct pm8xxx_mpp *pctrl; 758 + int ret; 759 + int i; 760 + 761 + pctrl = devm_kzalloc(&pdev->dev, sizeof(*pctrl), GFP_KERNEL); 762 + if (!pctrl) 763 + return -ENOMEM; 764 + 765 + pctrl->dev = &pdev->dev; 766 + pctrl->npins = (unsigned)of_device_get_match_data(&pdev->dev); 767 + 768 + pctrl->regmap = dev_get_regmap(pdev->dev.parent, NULL); 769 + if (!pctrl->regmap) { 770 + dev_err(&pdev->dev, "parent regmap unavailable\n"); 771 + return -ENXIO; 772 + } 773 + 774 + pctrl->desc = pm8xxx_pinctrl_desc; 775 + pctrl->desc.npins = pctrl->npins; 776 + 777 + pins = devm_kcalloc(&pdev->dev, 778 + pctrl->desc.npins, 779 + sizeof(struct pinctrl_pin_desc), 780 + GFP_KERNEL); 781 + if (!pins) 782 + return -ENOMEM; 783 + 784 + pin_data = devm_kcalloc(&pdev->dev, 785 + pctrl->desc.npins, 786 + sizeof(struct pm8xxx_pin_data), 787 + GFP_KERNEL); 788 + if (!pin_data) 789 + return -ENOMEM; 790 + 791 + for (i = 0; i < pctrl->desc.npins; i++) { 792 + pin_data[i].reg = SSBI_REG_ADDR_MPP(i); 793 + pin_data[i].irq = platform_get_irq(pdev, i); 794 + if (pin_data[i].irq < 0) { 795 + dev_err(&pdev->dev, 796 + "missing interrupts for pin %d\n", i); 797 + return pin_data[i].irq; 798 + } 799 + 800 + ret = pm8xxx_pin_populate(pctrl, &pin_data[i]); 801 + if (ret) 802 + return ret; 803 + 804 + pins[i].number = i; 805 + pins[i].name = pm8xxx_groups[i]; 806 + pins[i].drv_data = &pin_data[i]; 807 + } 808 + pctrl->desc.pins = pins; 809 + 810 + pctrl->desc.num_custom_params = ARRAY_SIZE(pm8xxx_mpp_bindings); 811 + pctrl->desc.custom_params = pm8xxx_mpp_bindings; 812 + #ifdef CONFIG_DEBUG_FS 813 + pctrl->desc.custom_conf_items = pm8xxx_conf_items; 814 + #endif 815 + 816 + pctrl->pctrl = pinctrl_register(&pctrl->desc, &pdev->dev, pctrl); 817 + if (!pctrl->pctrl) { 818 + dev_err(&pdev->dev, "couldn't register pm8xxx mpp driver\n"); 819 + return -ENODEV; 820 + } 821 + 822 + pctrl->chip = pm8xxx_mpp_template; 823 + pctrl->chip.base = -1; 824 + pctrl->chip.dev = &pdev->dev; 825 + pctrl->chip.of_node = pdev->dev.of_node; 826 + pctrl->chip.of_gpio_n_cells = 2; 827 + pctrl->chip.label = dev_name(pctrl->dev); 828 + pctrl->chip.ngpio = pctrl->npins; 829 + ret = gpiochip_add(&pctrl->chip); 830 + if (ret) { 831 + dev_err(&pdev->dev, "failed register gpiochip\n"); 832 + goto unregister_pinctrl; 833 + } 834 + 835 + ret = gpiochip_add_pin_range(&pctrl->chip, 836 + dev_name(pctrl->dev), 837 + 0, 0, pctrl->chip.ngpio); 838 + if (ret) { 839 + dev_err(pctrl->dev, "failed to add pin range\n"); 840 + goto unregister_gpiochip; 841 + } 842 + 843 + platform_set_drvdata(pdev, pctrl); 844 + 845 + dev_dbg(&pdev->dev, "Qualcomm pm8xxx mpp driver probed\n"); 846 + 847 + return 0; 848 + 849 + unregister_gpiochip: 850 + gpiochip_remove(&pctrl->chip); 851 + 852 + unregister_pinctrl: 853 + pinctrl_unregister(pctrl->pctrl); 854 + 855 + return ret; 856 + } 857 + 858 + static int pm8xxx_mpp_remove(struct platform_device *pdev) 859 + { 860 + struct pm8xxx_mpp *pctrl = platform_get_drvdata(pdev); 861 + 862 + gpiochip_remove(&pctrl->chip); 863 + 864 + pinctrl_unregister(pctrl->pctrl); 865 + 866 + return 0; 867 + } 868 + 869 + static struct platform_driver pm8xxx_mpp_driver = { 870 + .driver = { 871 + .name = "qcom-ssbi-mpp", 872 + .of_match_table = pm8xxx_mpp_of_match, 873 + }, 874 + .probe = pm8xxx_mpp_probe, 875 + .remove = pm8xxx_mpp_remove, 876 + }; 877 + 878 + module_platform_driver(pm8xxx_mpp_driver); 879 + 880 + MODULE_AUTHOR("Bjorn Andersson <bjorn.andersson@sonymobile.com>"); 881 + MODULE_DESCRIPTION("Qualcomm PM8xxx MPP driver"); 882 + MODULE_LICENSE("GPL v2");
+51
include/dt-bindings/pinctrl/qcom,pmic-mpp.h
··· 7 7 #define _DT_BINDINGS_PINCTRL_QCOM_PMIC_MPP_H 8 8 9 9 /* power-source */ 10 + 11 + /* Digital Input/Output: level [PM8058] */ 12 + #define PM8058_MPP_VPH 0 13 + #define PM8058_MPP_S3 1 14 + #define PM8058_MPP_L2 2 15 + #define PM8058_MPP_L3 3 16 + 17 + /* Digital Input/Output: level [PM8901] */ 18 + #define PM8901_MPP_MSMIO 0 19 + #define PM8901_MPP_DIG 1 20 + #define PM8901_MPP_L5 2 21 + #define PM8901_MPP_S4 3 22 + #define PM8901_MPP_VPH 4 23 + 24 + /* Digital Input/Output: level [PM8921] */ 25 + #define PM8921_MPP_S4 1 26 + #define PM8921_MPP_L15 3 27 + #define PM8921_MPP_L17 4 28 + #define PM8921_MPP_VPH 7 29 + 30 + /* Digital Input/Output: level [PM8821] */ 31 + #define PM8821_MPP_1P8 0 32 + #define PM8821_MPP_VPH 7 33 + 34 + /* Digital Input/Output: level [PM8018] */ 35 + #define PM8018_MPP_L4 0 36 + #define PM8018_MPP_L14 1 37 + #define PM8018_MPP_S3 2 38 + #define PM8018_MPP_L6 3 39 + #define PM8018_MPP_L2 4 40 + #define PM8018_MPP_L5 5 41 + #define PM8018_MPP_VPH 7 42 + 43 + /* Digital Input/Output: level [PM8038] */ 44 + #define PM8038_MPP_L20 0 45 + #define PM8038_MPP_L11 1 46 + #define PM8038_MPP_L5 2 47 + #define PM8038_MPP_L15 3 48 + #define PM8038_MPP_L17 4 49 + #define PM8038_MPP_VPH 7 50 + 10 51 #define PM8841_MPP_VPH 0 11 52 #define PM8841_MPP_S3 2 12 53 ··· 77 36 #define PMIC_MPP_AMUX_ROUTE_ABUS2 5 78 37 #define PMIC_MPP_AMUX_ROUTE_ABUS3 6 79 38 #define PMIC_MPP_AMUX_ROUTE_ABUS4 7 39 + 40 + /* Analog Output: level */ 41 + #define PMIC_MPP_AOUT_LVL_1V25 0 42 + #define PMIC_MPP_AOUT_LVL_1V25_2 1 43 + #define PMIC_MPP_AOUT_LVL_0V625 2 44 + #define PMIC_MPP_AOUT_LVL_0V3125 3 45 + #define PMIC_MPP_AOUT_LVL_MPP 4 46 + #define PMIC_MPP_AOUT_LVL_ABUS1 5 47 + #define PMIC_MPP_AOUT_LVL_ABUS2 6 48 + #define PMIC_MPP_AOUT_LVL_ABUS3 7 80 49 81 50 /* To be used with "function" */ 82 51 #define PMIC_MPP_FUNC_NORMAL "normal"