960 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * Copyright (c) 2015, Sony Mobile Communications AB.4 * Copyright (c) 2013, The Linux Foundation. All rights reserved.5 */6 7#include <linux/gpio/driver.h>8#include <linux/interrupt.h>9#include <linux/module.h>10#include <linux/of.h>11#include <linux/of_irq.h>12#include <linux/platform_device.h>13#include <linux/regmap.h>14#include <linux/seq_file.h>15#include <linux/slab.h>16 17#include <linux/pinctrl/pinconf-generic.h>18#include <linux/pinctrl/pinconf.h>19#include <linux/pinctrl/pinctrl.h>20#include <linux/pinctrl/pinmux.h>21 22#include <dt-bindings/pinctrl/qcom,pmic-mpp.h>23 24#include "../core.h"25#include "../pinctrl-utils.h"26 27/* MPP registers */28#define SSBI_REG_ADDR_MPP_BASE 0x5029#define SSBI_REG_ADDR_MPP(n) (SSBI_REG_ADDR_MPP_BASE + n)30 31/* MPP Type: type */32#define PM8XXX_MPP_TYPE_D_INPUT 033#define PM8XXX_MPP_TYPE_D_OUTPUT 134#define PM8XXX_MPP_TYPE_D_BI_DIR 235#define PM8XXX_MPP_TYPE_A_INPUT 336#define PM8XXX_MPP_TYPE_A_OUTPUT 437#define PM8XXX_MPP_TYPE_SINK 538#define PM8XXX_MPP_TYPE_DTEST_SINK 639#define PM8XXX_MPP_TYPE_DTEST_OUTPUT 740 41/* Digital Input: control */42#define PM8XXX_MPP_DIN_TO_INT 043#define PM8XXX_MPP_DIN_TO_DBUS1 144#define PM8XXX_MPP_DIN_TO_DBUS2 245#define PM8XXX_MPP_DIN_TO_DBUS3 346 47/* Digital Output: control */48#define PM8XXX_MPP_DOUT_CTRL_LOW 049#define PM8XXX_MPP_DOUT_CTRL_HIGH 150#define PM8XXX_MPP_DOUT_CTRL_MPP 251#define PM8XXX_MPP_DOUT_CTRL_INV_MPP 352 53/* Bidirectional: control */54#define PM8XXX_MPP_BI_PULLUP_1KOHM 055#define PM8XXX_MPP_BI_PULLUP_OPEN 156#define PM8XXX_MPP_BI_PULLUP_10KOHM 257#define PM8XXX_MPP_BI_PULLUP_30KOHM 358 59/* Analog Output: control */60#define PM8XXX_MPP_AOUT_CTRL_DISABLE 061#define PM8XXX_MPP_AOUT_CTRL_ENABLE 162#define PM8XXX_MPP_AOUT_CTRL_MPP_HIGH_EN 263#define PM8XXX_MPP_AOUT_CTRL_MPP_LOW_EN 364 65/* Current Sink: control */66#define PM8XXX_MPP_CS_CTRL_DISABLE 067#define PM8XXX_MPP_CS_CTRL_ENABLE 168#define PM8XXX_MPP_CS_CTRL_MPP_HIGH_EN 269#define PM8XXX_MPP_CS_CTRL_MPP_LOW_EN 370 71/* DTEST Current Sink: control */72#define PM8XXX_MPP_DTEST_CS_CTRL_EN1 073#define PM8XXX_MPP_DTEST_CS_CTRL_EN2 174#define PM8XXX_MPP_DTEST_CS_CTRL_EN3 275#define PM8XXX_MPP_DTEST_CS_CTRL_EN4 376 77/* DTEST Digital Output: control */78#define PM8XXX_MPP_DTEST_DBUS1 079#define PM8XXX_MPP_DTEST_DBUS2 180#define PM8XXX_MPP_DTEST_DBUS3 281#define PM8XXX_MPP_DTEST_DBUS4 382 83/* custom pinconf parameters */84#define PM8XXX_CONFIG_AMUX (PIN_CONFIG_END + 1)85#define PM8XXX_CONFIG_DTEST_SELECTOR (PIN_CONFIG_END + 2)86#define PM8XXX_CONFIG_ALEVEL (PIN_CONFIG_END + 3)87#define PM8XXX_CONFIG_PAIRED (PIN_CONFIG_END + 4)88 89/**90 * struct pm8xxx_pin_data - dynamic configuration for a pin91 * @reg: address of the control register92 * @mode: operating mode for the pin (digital, analog or current sink)93 * @input: pin is input94 * @output: pin is output95 * @high_z: pin is floating96 * @paired: mpp operates in paired mode97 * @output_value: logical output value of the mpp98 * @power_source: selected power source99 * @dtest: DTEST route selector100 * @amux: input muxing in analog mode101 * @aout_level: selector of the output in analog mode102 * @drive_strength: drive strength of the current sink103 * @pullup: pull up value, when in digital bidirectional mode104 */105struct pm8xxx_pin_data {106 unsigned reg;107 108 u8 mode;109 110 bool input;111 bool output;112 bool high_z;113 bool paired;114 bool output_value;115 116 u8 power_source;117 u8 dtest;118 u8 amux;119 u8 aout_level;120 u8 drive_strength;121 unsigned pullup;122};123 124struct pm8xxx_mpp {125 struct device *dev;126 struct regmap *regmap;127 struct pinctrl_dev *pctrl;128 struct gpio_chip chip;129 130 struct pinctrl_desc desc;131 unsigned npins;132};133 134static const struct pinconf_generic_params pm8xxx_mpp_bindings[] = {135 {"qcom,amux-route", PM8XXX_CONFIG_AMUX, 0},136 {"qcom,analog-level", PM8XXX_CONFIG_ALEVEL, 0},137 {"qcom,dtest", PM8XXX_CONFIG_DTEST_SELECTOR, 0},138 {"qcom,paired", PM8XXX_CONFIG_PAIRED, 0},139};140 141#ifdef CONFIG_DEBUG_FS142static const struct pin_config_item pm8xxx_conf_items[] = {143 PCONFDUMP(PM8XXX_CONFIG_AMUX, "analog mux", NULL, true),144 PCONFDUMP(PM8XXX_CONFIG_ALEVEL, "analog level", NULL, true),145 PCONFDUMP(PM8XXX_CONFIG_DTEST_SELECTOR, "dtest", NULL, true),146 PCONFDUMP(PM8XXX_CONFIG_PAIRED, "paired", NULL, false),147};148#endif149 150#define PM8XXX_MAX_MPPS 12151#define PM8XXX_MPP_PHYSICAL_OFFSET 1152 153static const char * const pm8xxx_groups[PM8XXX_MAX_MPPS] = {154 "mpp1", "mpp2", "mpp3", "mpp4", "mpp5", "mpp6", "mpp7", "mpp8",155 "mpp9", "mpp10", "mpp11", "mpp12",156};157 158#define PM8XXX_MPP_DIGITAL 0159#define PM8XXX_MPP_ANALOG 1160#define PM8XXX_MPP_SINK 2161 162static const char * const pm8xxx_mpp_functions[] = {163 "digital", "analog", "sink",164};165 166static int pm8xxx_mpp_update(struct pm8xxx_mpp *pctrl,167 struct pm8xxx_pin_data *pin)168{169 unsigned level;170 unsigned ctrl;171 unsigned type;172 int ret;173 u8 val;174 175 switch (pin->mode) {176 case PM8XXX_MPP_DIGITAL:177 if (pin->dtest) {178 type = PM8XXX_MPP_TYPE_DTEST_OUTPUT;179 ctrl = pin->dtest - 1;180 } else if (pin->input && pin->output) {181 type = PM8XXX_MPP_TYPE_D_BI_DIR;182 if (pin->high_z)183 ctrl = PM8XXX_MPP_BI_PULLUP_OPEN;184 else if (pin->pullup == 600)185 ctrl = PM8XXX_MPP_BI_PULLUP_1KOHM;186 else if (pin->pullup == 10000)187 ctrl = PM8XXX_MPP_BI_PULLUP_10KOHM;188 else189 ctrl = PM8XXX_MPP_BI_PULLUP_30KOHM;190 } else if (pin->input) {191 type = PM8XXX_MPP_TYPE_D_INPUT;192 if (pin->dtest)193 ctrl = pin->dtest;194 else195 ctrl = PM8XXX_MPP_DIN_TO_INT;196 } else {197 type = PM8XXX_MPP_TYPE_D_OUTPUT;198 ctrl = !!pin->output_value;199 if (pin->paired)200 ctrl |= BIT(1);201 }202 203 level = pin->power_source;204 break;205 case PM8XXX_MPP_ANALOG:206 if (pin->output) {207 type = PM8XXX_MPP_TYPE_A_OUTPUT;208 level = pin->aout_level;209 ctrl = pin->output_value;210 if (pin->paired)211 ctrl |= BIT(1);212 } else {213 type = PM8XXX_MPP_TYPE_A_INPUT;214 level = pin->amux;215 ctrl = 0;216 }217 break;218 case PM8XXX_MPP_SINK:219 level = (pin->drive_strength / 5) - 1;220 if (pin->dtest) {221 type = PM8XXX_MPP_TYPE_DTEST_SINK;222 ctrl = pin->dtest - 1;223 } else {224 type = PM8XXX_MPP_TYPE_SINK;225 ctrl = pin->output_value;226 if (pin->paired)227 ctrl |= BIT(1);228 }229 break;230 default:231 return -EINVAL;232 }233 234 val = type << 5 | level << 2 | ctrl;235 ret = regmap_write(pctrl->regmap, pin->reg, val);236 if (ret)237 dev_err(pctrl->dev, "failed to write register\n");238 239 return ret;240}241 242static int pm8xxx_get_groups_count(struct pinctrl_dev *pctldev)243{244 struct pm8xxx_mpp *pctrl = pinctrl_dev_get_drvdata(pctldev);245 246 return pctrl->npins;247}248 249static const char *pm8xxx_get_group_name(struct pinctrl_dev *pctldev,250 unsigned group)251{252 return pm8xxx_groups[group];253}254 255 256static int pm8xxx_get_group_pins(struct pinctrl_dev *pctldev,257 unsigned group,258 const unsigned **pins,259 unsigned *num_pins)260{261 struct pm8xxx_mpp *pctrl = pinctrl_dev_get_drvdata(pctldev);262 263 *pins = &pctrl->desc.pins[group].number;264 *num_pins = 1;265 266 return 0;267}268 269static const struct pinctrl_ops pm8xxx_pinctrl_ops = {270 .get_groups_count = pm8xxx_get_groups_count,271 .get_group_name = pm8xxx_get_group_name,272 .get_group_pins = pm8xxx_get_group_pins,273 .dt_node_to_map = pinconf_generic_dt_node_to_map_group,274 .dt_free_map = pinctrl_utils_free_map,275};276 277static int pm8xxx_get_functions_count(struct pinctrl_dev *pctldev)278{279 return ARRAY_SIZE(pm8xxx_mpp_functions);280}281 282static const char *pm8xxx_get_function_name(struct pinctrl_dev *pctldev,283 unsigned function)284{285 return pm8xxx_mpp_functions[function];286}287 288static int pm8xxx_get_function_groups(struct pinctrl_dev *pctldev,289 unsigned function,290 const char * const **groups,291 unsigned * const num_groups)292{293 struct pm8xxx_mpp *pctrl = pinctrl_dev_get_drvdata(pctldev);294 295 *groups = pm8xxx_groups;296 *num_groups = pctrl->npins;297 return 0;298}299 300static int pm8xxx_pinmux_set_mux(struct pinctrl_dev *pctldev,301 unsigned function,302 unsigned group)303{304 struct pm8xxx_mpp *pctrl = pinctrl_dev_get_drvdata(pctldev);305 struct pm8xxx_pin_data *pin = pctrl->desc.pins[group].drv_data;306 307 pin->mode = function;308 pm8xxx_mpp_update(pctrl, pin);309 310 return 0;311}312 313static const struct pinmux_ops pm8xxx_pinmux_ops = {314 .get_functions_count = pm8xxx_get_functions_count,315 .get_function_name = pm8xxx_get_function_name,316 .get_function_groups = pm8xxx_get_function_groups,317 .set_mux = pm8xxx_pinmux_set_mux,318};319 320static int pm8xxx_pin_config_get(struct pinctrl_dev *pctldev,321 unsigned int offset,322 unsigned long *config)323{324 struct pm8xxx_mpp *pctrl = pinctrl_dev_get_drvdata(pctldev);325 struct pm8xxx_pin_data *pin = pctrl->desc.pins[offset].drv_data;326 unsigned param = pinconf_to_config_param(*config);327 unsigned arg;328 329 switch (param) {330 case PIN_CONFIG_BIAS_PULL_UP:331 arg = pin->pullup;332 break;333 case PIN_CONFIG_BIAS_HIGH_IMPEDANCE:334 arg = pin->high_z;335 break;336 case PIN_CONFIG_INPUT_ENABLE:337 arg = pin->input;338 break;339 case PIN_CONFIG_OUTPUT:340 arg = pin->output_value;341 break;342 case PIN_CONFIG_POWER_SOURCE:343 arg = pin->power_source;344 break;345 case PIN_CONFIG_DRIVE_STRENGTH:346 arg = pin->drive_strength;347 break;348 case PM8XXX_CONFIG_DTEST_SELECTOR:349 arg = pin->dtest;350 break;351 case PM8XXX_CONFIG_AMUX:352 arg = pin->amux;353 break;354 case PM8XXX_CONFIG_ALEVEL:355 arg = pin->aout_level;356 break;357 case PM8XXX_CONFIG_PAIRED:358 arg = pin->paired;359 break;360 default:361 return -EINVAL;362 }363 364 *config = pinconf_to_config_packed(param, arg);365 366 return 0;367}368 369static int pm8xxx_pin_config_set(struct pinctrl_dev *pctldev,370 unsigned int offset,371 unsigned long *configs,372 unsigned num_configs)373{374 struct pm8xxx_mpp *pctrl = pinctrl_dev_get_drvdata(pctldev);375 struct pm8xxx_pin_data *pin = pctrl->desc.pins[offset].drv_data;376 unsigned param;377 unsigned arg;378 unsigned i;379 380 for (i = 0; i < num_configs; i++) {381 param = pinconf_to_config_param(configs[i]);382 arg = pinconf_to_config_argument(configs[i]);383 384 switch (param) {385 case PIN_CONFIG_BIAS_PULL_UP:386 pin->pullup = arg;387 break;388 case PIN_CONFIG_BIAS_HIGH_IMPEDANCE:389 pin->high_z = true;390 break;391 case PIN_CONFIG_INPUT_ENABLE:392 pin->input = true;393 break;394 case PIN_CONFIG_OUTPUT:395 pin->output = true;396 pin->output_value = !!arg;397 break;398 case PIN_CONFIG_POWER_SOURCE:399 pin->power_source = arg;400 break;401 case PIN_CONFIG_DRIVE_STRENGTH:402 pin->drive_strength = arg;403 break;404 case PM8XXX_CONFIG_DTEST_SELECTOR:405 pin->dtest = arg;406 break;407 case PM8XXX_CONFIG_AMUX:408 pin->amux = arg;409 break;410 case PM8XXX_CONFIG_ALEVEL:411 pin->aout_level = arg;412 break;413 case PM8XXX_CONFIG_PAIRED:414 pin->paired = !!arg;415 break;416 default:417 dev_err(pctrl->dev,418 "unsupported config parameter: %x\n",419 param);420 return -EINVAL;421 }422 }423 424 pm8xxx_mpp_update(pctrl, pin);425 426 return 0;427}428 429static 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 435static const struct pinctrl_desc pm8xxx_pinctrl_desc = {436 .name = "pm8xxx_mpp",437 .pctlops = &pm8xxx_pinctrl_ops,438 .pmxops = &pm8xxx_pinmux_ops,439 .confops = &pm8xxx_pinconf_ops,440 .owner = THIS_MODULE,441};442 443static int pm8xxx_mpp_direction_input(struct gpio_chip *chip,444 unsigned offset)445{446 struct pm8xxx_mpp *pctrl = gpiochip_get_data(chip);447 struct pm8xxx_pin_data *pin = pctrl->desc.pins[offset].drv_data;448 449 switch (pin->mode) {450 case PM8XXX_MPP_DIGITAL:451 pin->input = true;452 break;453 case PM8XXX_MPP_ANALOG:454 pin->input = true;455 pin->output = true;456 break;457 case PM8XXX_MPP_SINK:458 return -EINVAL;459 }460 461 pm8xxx_mpp_update(pctrl, pin);462 463 return 0;464}465 466static int pm8xxx_mpp_direction_output(struct gpio_chip *chip,467 unsigned offset,468 int value)469{470 struct pm8xxx_mpp *pctrl = gpiochip_get_data(chip);471 struct pm8xxx_pin_data *pin = pctrl->desc.pins[offset].drv_data;472 473 switch (pin->mode) {474 case PM8XXX_MPP_DIGITAL:475 pin->output = true;476 break;477 case PM8XXX_MPP_ANALOG:478 pin->input = false;479 pin->output = true;480 break;481 case PM8XXX_MPP_SINK:482 pin->input = false;483 pin->output = true;484 break;485 }486 487 pm8xxx_mpp_update(pctrl, pin);488 489 return 0;490}491 492static int pm8xxx_mpp_get(struct gpio_chip *chip, unsigned offset)493{494 struct pm8xxx_mpp *pctrl = gpiochip_get_data(chip);495 struct pm8xxx_pin_data *pin = pctrl->desc.pins[offset].drv_data;496 bool state;497 int ret, irq;498 499 if (!pin->input)500 return !!pin->output_value;501 502 irq = chip->to_irq(chip, offset);503 if (irq < 0)504 return irq;505 506 ret = irq_get_irqchip_state(irq, IRQCHIP_STATE_LINE_LEVEL, &state);507 if (!ret)508 ret = !!state;509 510 return ret;511}512 513static void pm8xxx_mpp_set(struct gpio_chip *chip, unsigned offset, int value)514{515 struct pm8xxx_mpp *pctrl = gpiochip_get_data(chip);516 struct pm8xxx_pin_data *pin = pctrl->desc.pins[offset].drv_data;517 518 pin->output_value = !!value;519 520 pm8xxx_mpp_update(pctrl, pin);521}522 523static int pm8xxx_mpp_of_xlate(struct gpio_chip *chip,524 const struct of_phandle_args *gpio_desc,525 u32 *flags)526{527 if (chip->of_gpio_n_cells < 2)528 return -EINVAL;529 530 if (flags)531 *flags = gpio_desc->args[1];532 533 return gpio_desc->args[0] - PM8XXX_MPP_PHYSICAL_OFFSET;534}535 536 537#ifdef CONFIG_DEBUG_FS538 539static void pm8xxx_mpp_dbg_show_one(struct seq_file *s,540 struct pinctrl_dev *pctldev,541 struct gpio_chip *chip,542 unsigned offset,543 unsigned gpio)544{545 struct pm8xxx_mpp *pctrl = gpiochip_get_data(chip);546 struct pm8xxx_pin_data *pin = pctrl->desc.pins[offset].drv_data;547 548 static const char * const aout_lvls[] = {549 "1v25", "1v25_2", "0v625", "0v3125", "mpp", "abus1", "abus2",550 "abus3"551 };552 553 static const char * const amuxs[] = {554 "amux5", "amux6", "amux7", "amux8", "amux9", "abus1", "abus2",555 "abus3",556 };557 558 seq_printf(s, " mpp%-2d:", offset + PM8XXX_MPP_PHYSICAL_OFFSET);559 560 switch (pin->mode) {561 case PM8XXX_MPP_DIGITAL:562 seq_puts(s, " digital ");563 if (pin->dtest) {564 seq_printf(s, "dtest%d\n", pin->dtest);565 } else if (pin->input && pin->output) {566 if (pin->high_z)567 seq_puts(s, "bi-dir high-z");568 else569 seq_printf(s, "bi-dir %dOhm", pin->pullup);570 } else if (pin->input) {571 if (pin->dtest)572 seq_printf(s, "in dtest%d", pin->dtest);573 else574 seq_puts(s, "in gpio");575 } else if (pin->output) {576 seq_puts(s, "out ");577 578 if (!pin->paired) {579 seq_puts(s, pin->output_value ?580 "high" : "low");581 } else {582 seq_puts(s, pin->output_value ?583 "inverted" : "follow");584 }585 }586 break;587 case PM8XXX_MPP_ANALOG:588 seq_puts(s, " analog ");589 if (pin->output) {590 seq_printf(s, "out %s ", aout_lvls[pin->aout_level]);591 if (!pin->paired) {592 seq_puts(s, pin->output_value ?593 "high" : "low");594 } else {595 seq_puts(s, pin->output_value ?596 "inverted" : "follow");597 }598 } else {599 seq_printf(s, "input mux %s", amuxs[pin->amux]);600 }601 break;602 case PM8XXX_MPP_SINK:603 seq_printf(s, " sink %dmA ", pin->drive_strength);604 if (pin->dtest) {605 seq_printf(s, "dtest%d", pin->dtest);606 } else {607 if (!pin->paired) {608 seq_puts(s, pin->output_value ?609 "high" : "low");610 } else {611 seq_puts(s, pin->output_value ?612 "inverted" : "follow");613 }614 }615 break;616 }617}618 619static void pm8xxx_mpp_dbg_show(struct seq_file *s, struct gpio_chip *chip)620{621 unsigned gpio = chip->base;622 unsigned i;623 624 for (i = 0; i < chip->ngpio; i++, gpio++) {625 pm8xxx_mpp_dbg_show_one(s, NULL, chip, i, gpio);626 seq_puts(s, "\n");627 }628}629 630#else631#define pm8xxx_mpp_dbg_show NULL632#endif633 634static const struct gpio_chip pm8xxx_mpp_template = {635 .direction_input = pm8xxx_mpp_direction_input,636 .direction_output = pm8xxx_mpp_direction_output,637 .get = pm8xxx_mpp_get,638 .set = pm8xxx_mpp_set,639 .of_xlate = pm8xxx_mpp_of_xlate,640 .dbg_show = pm8xxx_mpp_dbg_show,641 .owner = THIS_MODULE,642};643 644static int pm8xxx_pin_populate(struct pm8xxx_mpp *pctrl,645 struct pm8xxx_pin_data *pin)646{647 unsigned int val;648 unsigned level;649 unsigned ctrl;650 unsigned type;651 int ret;652 653 ret = regmap_read(pctrl->regmap, pin->reg, &val);654 if (ret) {655 dev_err(pctrl->dev, "failed to read register\n");656 return ret;657 }658 659 type = (val >> 5) & 7;660 level = (val >> 2) & 7;661 ctrl = (val) & 3;662 663 switch (type) {664 case PM8XXX_MPP_TYPE_D_INPUT:665 pin->mode = PM8XXX_MPP_DIGITAL;666 pin->input = true;667 pin->power_source = level;668 pin->dtest = ctrl;669 break;670 case PM8XXX_MPP_TYPE_D_OUTPUT:671 pin->mode = PM8XXX_MPP_DIGITAL;672 pin->output = true;673 pin->power_source = level;674 pin->output_value = !!(ctrl & BIT(0));675 pin->paired = !!(ctrl & BIT(1));676 break;677 case PM8XXX_MPP_TYPE_D_BI_DIR:678 pin->mode = PM8XXX_MPP_DIGITAL;679 pin->input = true;680 pin->output = true;681 pin->power_source = level;682 switch (ctrl) {683 case PM8XXX_MPP_BI_PULLUP_1KOHM:684 pin->pullup = 600;685 break;686 case PM8XXX_MPP_BI_PULLUP_OPEN:687 pin->high_z = true;688 break;689 case PM8XXX_MPP_BI_PULLUP_10KOHM:690 pin->pullup = 10000;691 break;692 case PM8XXX_MPP_BI_PULLUP_30KOHM:693 pin->pullup = 30000;694 break;695 }696 break;697 case PM8XXX_MPP_TYPE_A_INPUT:698 pin->mode = PM8XXX_MPP_ANALOG;699 pin->input = true;700 pin->amux = level;701 break;702 case PM8XXX_MPP_TYPE_A_OUTPUT:703 pin->mode = PM8XXX_MPP_ANALOG;704 pin->output = true;705 pin->aout_level = level;706 pin->output_value = !!(ctrl & BIT(0));707 pin->paired = !!(ctrl & BIT(1));708 break;709 case PM8XXX_MPP_TYPE_SINK:710 pin->mode = PM8XXX_MPP_SINK;711 pin->drive_strength = 5 * (level + 1);712 pin->output_value = !!(ctrl & BIT(0));713 pin->paired = !!(ctrl & BIT(1));714 break;715 case PM8XXX_MPP_TYPE_DTEST_SINK:716 pin->mode = PM8XXX_MPP_SINK;717 pin->dtest = ctrl + 1;718 pin->drive_strength = 5 * (level + 1);719 break;720 case PM8XXX_MPP_TYPE_DTEST_OUTPUT:721 pin->mode = PM8XXX_MPP_DIGITAL;722 pin->power_source = level;723 if (ctrl >= 1)724 pin->dtest = ctrl;725 break;726 }727 728 return 0;729}730 731static int pm8xxx_mpp_domain_translate(struct irq_domain *domain,732 struct irq_fwspec *fwspec,733 unsigned long *hwirq,734 unsigned int *type)735{736 struct pm8xxx_mpp *pctrl = container_of(domain->host_data,737 struct pm8xxx_mpp, chip);738 739 if (fwspec->param_count != 2 ||740 fwspec->param[0] < PM8XXX_MPP_PHYSICAL_OFFSET ||741 fwspec->param[0] > pctrl->chip.ngpio)742 return -EINVAL;743 744 *hwirq = fwspec->param[0] - PM8XXX_MPP_PHYSICAL_OFFSET;745 *type = fwspec->param[1];746 747 return 0;748}749 750static unsigned int pm8xxx_mpp_child_offset_to_irq(struct gpio_chip *chip,751 unsigned int offset)752{753 return offset + PM8XXX_MPP_PHYSICAL_OFFSET;754}755 756static int pm8821_mpp_child_to_parent_hwirq(struct gpio_chip *chip,757 unsigned int child_hwirq,758 unsigned int child_type,759 unsigned int *parent_hwirq,760 unsigned int *parent_type)761{762 *parent_hwirq = child_hwirq + 24;763 *parent_type = child_type;764 765 return 0;766}767 768static int pm8xxx_mpp_child_to_parent_hwirq(struct gpio_chip *chip,769 unsigned int child_hwirq,770 unsigned int child_type,771 unsigned int *parent_hwirq,772 unsigned int *parent_type)773{774 *parent_hwirq = child_hwirq + 0x80;775 *parent_type = child_type;776 777 return 0;778}779 780static void pm8xxx_mpp_irq_disable(struct irq_data *d)781{782 struct gpio_chip *gc = irq_data_get_irq_chip_data(d);783 784 gpiochip_disable_irq(gc, irqd_to_hwirq(d));785}786 787static void pm8xxx_mpp_irq_enable(struct irq_data *d)788{789 struct gpio_chip *gc = irq_data_get_irq_chip_data(d);790 791 gpiochip_enable_irq(gc, irqd_to_hwirq(d));792}793 794static const struct irq_chip pm8xxx_mpp_irq_chip = {795 .name = "ssbi-mpp",796 .irq_mask_ack = irq_chip_mask_ack_parent,797 .irq_unmask = irq_chip_unmask_parent,798 .irq_disable = pm8xxx_mpp_irq_disable,799 .irq_enable = pm8xxx_mpp_irq_enable,800 .irq_set_type = irq_chip_set_type_parent,801 .flags = IRQCHIP_MASK_ON_SUSPEND | IRQCHIP_SKIP_SET_WAKE |802 IRQCHIP_IMMUTABLE,803 GPIOCHIP_IRQ_RESOURCE_HELPERS,804};805 806static const struct of_device_id pm8xxx_mpp_of_match[] = {807 { .compatible = "qcom,pm8018-mpp", .data = (void *) 6 },808 { .compatible = "qcom,pm8038-mpp", .data = (void *) 6 },809 { .compatible = "qcom,pm8058-mpp", .data = (void *) 12 },810 { .compatible = "qcom,pm8821-mpp", .data = (void *) 4 },811 { .compatible = "qcom,pm8917-mpp", .data = (void *) 10 },812 { .compatible = "qcom,pm8921-mpp", .data = (void *) 12 },813 { },814};815MODULE_DEVICE_TABLE(of, pm8xxx_mpp_of_match);816 817static int pm8xxx_mpp_probe(struct platform_device *pdev)818{819 struct pm8xxx_pin_data *pin_data;820 struct irq_domain *parent_domain;821 struct device_node *parent_node;822 struct pinctrl_pin_desc *pins;823 struct gpio_irq_chip *girq;824 struct pm8xxx_mpp *pctrl;825 int ret;826 int i;827 828 pctrl = devm_kzalloc(&pdev->dev, sizeof(*pctrl), GFP_KERNEL);829 if (!pctrl)830 return -ENOMEM;831 832 pctrl->dev = &pdev->dev;833 pctrl->npins = (uintptr_t) device_get_match_data(&pdev->dev);834 835 pctrl->regmap = dev_get_regmap(pdev->dev.parent, NULL);836 if (!pctrl->regmap) {837 dev_err(&pdev->dev, "parent regmap unavailable\n");838 return -ENXIO;839 }840 841 pctrl->desc = pm8xxx_pinctrl_desc;842 pctrl->desc.npins = pctrl->npins;843 844 pins = devm_kcalloc(&pdev->dev,845 pctrl->desc.npins,846 sizeof(struct pinctrl_pin_desc),847 GFP_KERNEL);848 if (!pins)849 return -ENOMEM;850 851 pin_data = devm_kcalloc(&pdev->dev,852 pctrl->desc.npins,853 sizeof(struct pm8xxx_pin_data),854 GFP_KERNEL);855 if (!pin_data)856 return -ENOMEM;857 858 for (i = 0; i < pctrl->desc.npins; i++) {859 pin_data[i].reg = SSBI_REG_ADDR_MPP(i);860 861 ret = pm8xxx_pin_populate(pctrl, &pin_data[i]);862 if (ret)863 return ret;864 865 pins[i].number = i;866 pins[i].name = pm8xxx_groups[i];867 pins[i].drv_data = &pin_data[i];868 }869 pctrl->desc.pins = pins;870 871 pctrl->desc.num_custom_params = ARRAY_SIZE(pm8xxx_mpp_bindings);872 pctrl->desc.custom_params = pm8xxx_mpp_bindings;873#ifdef CONFIG_DEBUG_FS874 pctrl->desc.custom_conf_items = pm8xxx_conf_items;875#endif876 877 pctrl->pctrl = devm_pinctrl_register(&pdev->dev, &pctrl->desc, pctrl);878 if (IS_ERR(pctrl->pctrl)) {879 dev_err(&pdev->dev, "couldn't register pm8xxx mpp driver\n");880 return PTR_ERR(pctrl->pctrl);881 }882 883 pctrl->chip = pm8xxx_mpp_template;884 pctrl->chip.base = -1;885 pctrl->chip.parent = &pdev->dev;886 pctrl->chip.of_gpio_n_cells = 2;887 pctrl->chip.label = dev_name(pctrl->dev);888 pctrl->chip.ngpio = pctrl->npins;889 890 parent_node = of_irq_find_parent(pctrl->dev->of_node);891 if (!parent_node)892 return -ENXIO;893 894 parent_domain = irq_find_host(parent_node);895 of_node_put(parent_node);896 if (!parent_domain)897 return -ENXIO;898 899 girq = &pctrl->chip.irq;900 gpio_irq_chip_set_chip(girq, &pm8xxx_mpp_irq_chip);901 girq->default_type = IRQ_TYPE_NONE;902 girq->handler = handle_level_irq;903 girq->fwnode = dev_fwnode(pctrl->dev);904 girq->parent_domain = parent_domain;905 if (of_device_is_compatible(pdev->dev.of_node, "qcom,pm8821-mpp"))906 girq->child_to_parent_hwirq = pm8821_mpp_child_to_parent_hwirq;907 else908 girq->child_to_parent_hwirq = pm8xxx_mpp_child_to_parent_hwirq;909 girq->populate_parent_alloc_arg = gpiochip_populate_parent_fwspec_twocell;910 girq->child_offset_to_irq = pm8xxx_mpp_child_offset_to_irq;911 girq->child_irq_domain_ops.translate = pm8xxx_mpp_domain_translate;912 913 ret = gpiochip_add_data(&pctrl->chip, pctrl);914 if (ret) {915 dev_err(&pdev->dev, "failed register gpiochip\n");916 return ret;917 }918 919 ret = gpiochip_add_pin_range(&pctrl->chip,920 dev_name(pctrl->dev),921 0, 0, pctrl->chip.ngpio);922 if (ret) {923 dev_err(pctrl->dev, "failed to add pin range\n");924 goto unregister_gpiochip;925 }926 927 platform_set_drvdata(pdev, pctrl);928 929 dev_dbg(&pdev->dev, "Qualcomm pm8xxx mpp driver probed\n");930 931 return 0;932 933unregister_gpiochip:934 gpiochip_remove(&pctrl->chip);935 936 return ret;937}938 939static void pm8xxx_mpp_remove(struct platform_device *pdev)940{941 struct pm8xxx_mpp *pctrl = platform_get_drvdata(pdev);942 943 gpiochip_remove(&pctrl->chip);944}945 946static struct platform_driver pm8xxx_mpp_driver = {947 .driver = {948 .name = "qcom-ssbi-mpp",949 .of_match_table = pm8xxx_mpp_of_match,950 },951 .probe = pm8xxx_mpp_probe,952 .remove_new = pm8xxx_mpp_remove,953};954 955module_platform_driver(pm8xxx_mpp_driver);956 957MODULE_AUTHOR("Bjorn Andersson <bjorn.andersson@sonymobile.com>");958MODULE_DESCRIPTION("Qualcomm PM8xxx MPP driver");959MODULE_LICENSE("GPL v2");960