1012 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * Copyright (c) 2012-2014, The Linux Foundation. All rights reserved.4 */5 6#include <linux/gpio/driver.h>7#include <linux/module.h>8#include <linux/of.h>9#include <linux/of_irq.h>10#include <linux/platform_device.h>11#include <linux/regmap.h>12#include <linux/seq_file.h>13#include <linux/slab.h>14#include <linux/types.h>15 16#include <linux/pinctrl/pinconf-generic.h>17#include <linux/pinctrl/pinconf.h>18#include <linux/pinctrl/pinmux.h>19 20#include <dt-bindings/pinctrl/qcom,pmic-mpp.h>21 22#include "../core.h"23#include "../pinctrl-utils.h"24 25#define PMIC_MPP_ADDRESS_RANGE 0x10026 27/*28 * Pull Up Values - it indicates whether a pull-up should be29 * applied for bidirectional mode only. The hardware ignores the30 * configuration when operating in other modes.31 */32#define PMIC_MPP_PULL_UP_0P6KOHM 033#define PMIC_MPP_PULL_UP_10KOHM 134#define PMIC_MPP_PULL_UP_30KOHM 235#define PMIC_MPP_PULL_UP_OPEN 336 37/* type registers base address bases */38#define PMIC_MPP_REG_TYPE 0x439#define PMIC_MPP_REG_SUBTYPE 0x540 41/* mpp peripheral type and subtype values */42#define PMIC_MPP_TYPE 0x1143#define PMIC_MPP_SUBTYPE_4CH_NO_ANA_OUT 0x344#define PMIC_MPP_SUBTYPE_ULT_4CH_NO_ANA_OUT 0x445#define PMIC_MPP_SUBTYPE_4CH_NO_SINK 0x546#define PMIC_MPP_SUBTYPE_ULT_4CH_NO_SINK 0x647#define PMIC_MPP_SUBTYPE_4CH_FULL_FUNC 0x748#define PMIC_MPP_SUBTYPE_8CH_FULL_FUNC 0xf49 50#define PMIC_MPP_REG_RT_STS 0x1051#define PMIC_MPP_REG_RT_STS_VAL_MASK 0x152 53/* control register base address bases */54#define PMIC_MPP_REG_MODE_CTL 0x4055#define PMIC_MPP_REG_DIG_VIN_CTL 0x4156#define PMIC_MPP_REG_DIG_PULL_CTL 0x4257#define PMIC_MPP_REG_DIG_IN_CTL 0x4358#define PMIC_MPP_REG_EN_CTL 0x4659#define PMIC_MPP_REG_AOUT_CTL 0x4860#define PMIC_MPP_REG_AIN_CTL 0x4a61#define PMIC_MPP_REG_SINK_CTL 0x4c62 63/* PMIC_MPP_REG_MODE_CTL */64#define PMIC_MPP_REG_MODE_VALUE_MASK 0x165#define PMIC_MPP_REG_MODE_FUNCTION_SHIFT 166#define PMIC_MPP_REG_MODE_FUNCTION_MASK 0x767#define PMIC_MPP_REG_MODE_DIR_SHIFT 468#define PMIC_MPP_REG_MODE_DIR_MASK 0x769 70/* PMIC_MPP_REG_DIG_VIN_CTL */71#define PMIC_MPP_REG_VIN_SHIFT 072#define PMIC_MPP_REG_VIN_MASK 0x773 74/* PMIC_MPP_REG_DIG_PULL_CTL */75#define PMIC_MPP_REG_PULL_SHIFT 076#define PMIC_MPP_REG_PULL_MASK 0x777 78/* PMIC_MPP_REG_EN_CTL */79#define PMIC_MPP_REG_MASTER_EN_SHIFT 780 81/* PMIC_MPP_REG_AIN_CTL */82#define PMIC_MPP_REG_AIN_ROUTE_SHIFT 083#define PMIC_MPP_REG_AIN_ROUTE_MASK 0x784 85#define PMIC_MPP_MODE_DIGITAL_INPUT 086#define PMIC_MPP_MODE_DIGITAL_OUTPUT 187#define PMIC_MPP_MODE_DIGITAL_BIDIR 288#define PMIC_MPP_MODE_ANALOG_BIDIR 389#define PMIC_MPP_MODE_ANALOG_INPUT 490#define PMIC_MPP_MODE_ANALOG_OUTPUT 591#define PMIC_MPP_MODE_CURRENT_SINK 692 93#define PMIC_MPP_SELECTOR_NORMAL 094#define PMIC_MPP_SELECTOR_PAIRED 195#define PMIC_MPP_SELECTOR_DTEST_FIRST 496 97#define PMIC_MPP_PHYSICAL_OFFSET 198 99/* Qualcomm specific pin configurations */100#define PMIC_MPP_CONF_AMUX_ROUTE (PIN_CONFIG_END + 1)101#define PMIC_MPP_CONF_ANALOG_LEVEL (PIN_CONFIG_END + 2)102#define PMIC_MPP_CONF_DTEST_SELECTOR (PIN_CONFIG_END + 3)103#define PMIC_MPP_CONF_PAIRED (PIN_CONFIG_END + 4)104 105/**106 * struct pmic_mpp_pad - keep current MPP settings107 * @base: Address base in SPMI device.108 * @is_enabled: Set to false when MPP should be put in high Z state.109 * @out_value: Cached pin output value.110 * @output_enabled: Set to true if MPP output logic is enabled.111 * @input_enabled: Set to true if MPP input buffer logic is enabled.112 * @paired: Pin operates in paired mode113 * @has_pullup: Pin has support to configure pullup114 * @num_sources: Number of power-sources supported by this MPP.115 * @power_source: Current power-source used.116 * @amux_input: Set the source for analog input.117 * @aout_level: Analog output level118 * @pullup: Pullup resistor value. Valid in Bidirectional mode only.119 * @function: See pmic_mpp_functions[].120 * @drive_strength: Amount of current in sink mode121 * @dtest: DTEST route selector122 */123struct pmic_mpp_pad {124 u16 base;125 bool is_enabled;126 bool out_value;127 bool output_enabled;128 bool input_enabled;129 bool paired;130 bool has_pullup;131 unsigned int num_sources;132 unsigned int power_source;133 unsigned int amux_input;134 unsigned int aout_level;135 unsigned int pullup;136 unsigned int function;137 unsigned int drive_strength;138 unsigned int dtest;139};140 141struct pmic_mpp_state {142 struct device *dev;143 struct regmap *map;144 struct pinctrl_dev *ctrl;145 struct gpio_chip chip;146};147 148static const struct pinconf_generic_params pmic_mpp_bindings[] = {149 {"qcom,amux-route", PMIC_MPP_CONF_AMUX_ROUTE, 0},150 {"qcom,analog-level", PMIC_MPP_CONF_ANALOG_LEVEL, 0},151 {"qcom,dtest", PMIC_MPP_CONF_DTEST_SELECTOR, 0},152 {"qcom,paired", PMIC_MPP_CONF_PAIRED, 0},153};154 155#ifdef CONFIG_DEBUG_FS156static const struct pin_config_item pmic_conf_items[] = {157 PCONFDUMP(PMIC_MPP_CONF_AMUX_ROUTE, "analog mux", NULL, true),158 PCONFDUMP(PMIC_MPP_CONF_ANALOG_LEVEL, "analog level", NULL, true),159 PCONFDUMP(PMIC_MPP_CONF_DTEST_SELECTOR, "dtest", NULL, true),160 PCONFDUMP(PMIC_MPP_CONF_PAIRED, "paired", NULL, false),161};162#endif163 164static const char *const pmic_mpp_groups[] = {165 "mpp1", "mpp2", "mpp3", "mpp4", "mpp5", "mpp6", "mpp7", "mpp8",166};167 168#define PMIC_MPP_DIGITAL 0169#define PMIC_MPP_ANALOG 1170#define PMIC_MPP_SINK 2171 172static const char *const pmic_mpp_functions[] = {173 "digital", "analog", "sink"174};175 176static int pmic_mpp_read(struct pmic_mpp_state *state,177 struct pmic_mpp_pad *pad, unsigned int addr)178{179 unsigned int val;180 int ret;181 182 ret = regmap_read(state->map, pad->base + addr, &val);183 if (ret < 0)184 dev_err(state->dev, "read 0x%x failed\n", addr);185 else186 ret = val;187 188 return ret;189}190 191static int pmic_mpp_write(struct pmic_mpp_state *state,192 struct pmic_mpp_pad *pad, unsigned int addr,193 unsigned int val)194{195 int ret;196 197 ret = regmap_write(state->map, pad->base + addr, val);198 if (ret < 0)199 dev_err(state->dev, "write 0x%x failed\n", addr);200 201 return ret;202}203 204static int pmic_mpp_get_groups_count(struct pinctrl_dev *pctldev)205{206 /* Every PIN is a group */207 return pctldev->desc->npins;208}209 210static const char *pmic_mpp_get_group_name(struct pinctrl_dev *pctldev,211 unsigned pin)212{213 return pctldev->desc->pins[pin].name;214}215 216static int pmic_mpp_get_group_pins(struct pinctrl_dev *pctldev,217 unsigned pin,218 const unsigned **pins, unsigned *num_pins)219{220 *pins = &pctldev->desc->pins[pin].number;221 *num_pins = 1;222 return 0;223}224 225static const struct pinctrl_ops pmic_mpp_pinctrl_ops = {226 .get_groups_count = pmic_mpp_get_groups_count,227 .get_group_name = pmic_mpp_get_group_name,228 .get_group_pins = pmic_mpp_get_group_pins,229 .dt_node_to_map = pinconf_generic_dt_node_to_map_group,230 .dt_free_map = pinctrl_utils_free_map,231};232 233static int pmic_mpp_get_functions_count(struct pinctrl_dev *pctldev)234{235 return ARRAY_SIZE(pmic_mpp_functions);236}237 238static const char *pmic_mpp_get_function_name(struct pinctrl_dev *pctldev,239 unsigned function)240{241 return pmic_mpp_functions[function];242}243 244static int pmic_mpp_get_function_groups(struct pinctrl_dev *pctldev,245 unsigned function,246 const char *const **groups,247 unsigned *const num_qgroups)248{249 *groups = pmic_mpp_groups;250 *num_qgroups = pctldev->desc->npins;251 return 0;252}253 254static int pmic_mpp_write_mode_ctl(struct pmic_mpp_state *state,255 struct pmic_mpp_pad *pad)256{257 unsigned int mode;258 unsigned int sel;259 unsigned int val;260 unsigned int en;261 262 switch (pad->function) {263 case PMIC_MPP_ANALOG:264 if (pad->input_enabled && pad->output_enabled)265 mode = PMIC_MPP_MODE_ANALOG_BIDIR;266 else if (pad->input_enabled)267 mode = PMIC_MPP_MODE_ANALOG_INPUT;268 else269 mode = PMIC_MPP_MODE_ANALOG_OUTPUT;270 break;271 case PMIC_MPP_DIGITAL:272 if (pad->input_enabled && pad->output_enabled)273 mode = PMIC_MPP_MODE_DIGITAL_BIDIR;274 else if (pad->input_enabled)275 mode = PMIC_MPP_MODE_DIGITAL_INPUT;276 else277 mode = PMIC_MPP_MODE_DIGITAL_OUTPUT;278 break;279 case PMIC_MPP_SINK:280 default:281 mode = PMIC_MPP_MODE_CURRENT_SINK;282 break;283 }284 285 if (pad->dtest)286 sel = PMIC_MPP_SELECTOR_DTEST_FIRST + pad->dtest - 1;287 else if (pad->paired)288 sel = PMIC_MPP_SELECTOR_PAIRED;289 else290 sel = PMIC_MPP_SELECTOR_NORMAL;291 292 en = !!pad->out_value;293 294 val = mode << PMIC_MPP_REG_MODE_DIR_SHIFT |295 sel << PMIC_MPP_REG_MODE_FUNCTION_SHIFT |296 en;297 298 return pmic_mpp_write(state, pad, PMIC_MPP_REG_MODE_CTL, val);299}300 301static int pmic_mpp_set_mux(struct pinctrl_dev *pctldev, unsigned function,302 unsigned pin)303{304 struct pmic_mpp_state *state = pinctrl_dev_get_drvdata(pctldev);305 struct pmic_mpp_pad *pad;306 unsigned int val;307 int ret;308 309 pad = pctldev->desc->pins[pin].drv_data;310 311 pad->function = function;312 313 ret = pmic_mpp_write_mode_ctl(state, pad);314 if (ret < 0)315 return ret;316 317 val = pad->is_enabled << PMIC_MPP_REG_MASTER_EN_SHIFT;318 319 return pmic_mpp_write(state, pad, PMIC_MPP_REG_EN_CTL, val);320}321 322static const struct pinmux_ops pmic_mpp_pinmux_ops = {323 .get_functions_count = pmic_mpp_get_functions_count,324 .get_function_name = pmic_mpp_get_function_name,325 .get_function_groups = pmic_mpp_get_function_groups,326 .set_mux = pmic_mpp_set_mux,327};328 329static int pmic_mpp_config_get(struct pinctrl_dev *pctldev,330 unsigned int pin, unsigned long *config)331{332 unsigned param = pinconf_to_config_param(*config);333 struct pmic_mpp_pad *pad;334 unsigned arg = 0;335 336 pad = pctldev->desc->pins[pin].drv_data;337 338 switch (param) {339 case PIN_CONFIG_BIAS_DISABLE:340 if (pad->pullup != PMIC_MPP_PULL_UP_OPEN)341 return -EINVAL;342 arg = 1;343 break;344 case PIN_CONFIG_BIAS_PULL_UP:345 switch (pad->pullup) {346 case PMIC_MPP_PULL_UP_0P6KOHM:347 arg = 600;348 break;349 case PMIC_MPP_PULL_UP_10KOHM:350 arg = 10000;351 break;352 case PMIC_MPP_PULL_UP_30KOHM:353 arg = 30000;354 break;355 default:356 return -EINVAL;357 }358 break;359 case PIN_CONFIG_BIAS_HIGH_IMPEDANCE:360 if (pad->is_enabled)361 return -EINVAL;362 arg = 1;363 break;364 case PIN_CONFIG_POWER_SOURCE:365 arg = pad->power_source;366 break;367 case PIN_CONFIG_INPUT_ENABLE:368 if (!pad->input_enabled)369 return -EINVAL;370 arg = 1;371 break;372 case PIN_CONFIG_OUTPUT:373 arg = pad->out_value;374 break;375 case PMIC_MPP_CONF_DTEST_SELECTOR:376 arg = pad->dtest;377 break;378 case PMIC_MPP_CONF_AMUX_ROUTE:379 arg = pad->amux_input;380 break;381 case PMIC_MPP_CONF_PAIRED:382 if (!pad->paired)383 return -EINVAL;384 arg = 1;385 break;386 case PIN_CONFIG_DRIVE_STRENGTH:387 arg = pad->drive_strength;388 break;389 case PMIC_MPP_CONF_ANALOG_LEVEL:390 arg = pad->aout_level;391 break;392 default:393 return -EINVAL;394 }395 396 /* Convert register value to pinconf value */397 *config = pinconf_to_config_packed(param, arg);398 return 0;399}400 401static int pmic_mpp_config_set(struct pinctrl_dev *pctldev, unsigned int pin,402 unsigned long *configs, unsigned nconfs)403{404 struct pmic_mpp_state *state = pinctrl_dev_get_drvdata(pctldev);405 struct pmic_mpp_pad *pad;406 unsigned param, arg;407 unsigned int val;408 int i, ret;409 410 pad = pctldev->desc->pins[pin].drv_data;411 412 /* Make it possible to enable the pin, by not setting high impedance */413 pad->is_enabled = true;414 415 for (i = 0; i < nconfs; i++) {416 param = pinconf_to_config_param(configs[i]);417 arg = pinconf_to_config_argument(configs[i]);418 419 switch (param) {420 case PIN_CONFIG_BIAS_DISABLE:421 pad->pullup = PMIC_MPP_PULL_UP_OPEN;422 break;423 case PIN_CONFIG_BIAS_PULL_UP:424 switch (arg) {425 case 600:426 pad->pullup = PMIC_MPP_PULL_UP_0P6KOHM;427 break;428 case 10000:429 pad->pullup = PMIC_MPP_PULL_UP_10KOHM;430 break;431 case 30000:432 pad->pullup = PMIC_MPP_PULL_UP_30KOHM;433 break;434 default:435 return -EINVAL;436 }437 break;438 case PIN_CONFIG_BIAS_HIGH_IMPEDANCE:439 pad->is_enabled = false;440 break;441 case PIN_CONFIG_POWER_SOURCE:442 if (arg >= pad->num_sources)443 return -EINVAL;444 pad->power_source = arg;445 break;446 case PIN_CONFIG_INPUT_ENABLE:447 pad->input_enabled = arg ? true : false;448 break;449 case PIN_CONFIG_OUTPUT:450 pad->output_enabled = true;451 pad->out_value = arg;452 break;453 case PMIC_MPP_CONF_DTEST_SELECTOR:454 pad->dtest = arg;455 break;456 case PIN_CONFIG_DRIVE_STRENGTH:457 pad->drive_strength = arg;458 break;459 case PMIC_MPP_CONF_AMUX_ROUTE:460 if (arg >= PMIC_MPP_AMUX_ROUTE_ABUS4)461 return -EINVAL;462 pad->amux_input = arg;463 break;464 case PMIC_MPP_CONF_ANALOG_LEVEL:465 pad->aout_level = arg;466 break;467 case PMIC_MPP_CONF_PAIRED:468 pad->paired = !!arg;469 break;470 default:471 return -EINVAL;472 }473 }474 475 val = pad->power_source << PMIC_MPP_REG_VIN_SHIFT;476 477 ret = pmic_mpp_write(state, pad, PMIC_MPP_REG_DIG_VIN_CTL, val);478 if (ret < 0)479 return ret;480 481 if (pad->has_pullup) {482 val = pad->pullup << PMIC_MPP_REG_PULL_SHIFT;483 484 ret = pmic_mpp_write(state, pad, PMIC_MPP_REG_DIG_PULL_CTL,485 val);486 if (ret < 0)487 return ret;488 }489 490 val = pad->amux_input & PMIC_MPP_REG_AIN_ROUTE_MASK;491 492 ret = pmic_mpp_write(state, pad, PMIC_MPP_REG_AIN_CTL, val);493 if (ret < 0)494 return ret;495 496 ret = pmic_mpp_write(state, pad, PMIC_MPP_REG_AOUT_CTL, pad->aout_level);497 if (ret < 0)498 return ret;499 500 ret = pmic_mpp_write_mode_ctl(state, pad);501 if (ret < 0)502 return ret;503 504 ret = pmic_mpp_write(state, pad, PMIC_MPP_REG_SINK_CTL, pad->drive_strength);505 if (ret < 0)506 return ret;507 508 val = pad->is_enabled << PMIC_MPP_REG_MASTER_EN_SHIFT;509 510 return pmic_mpp_write(state, pad, PMIC_MPP_REG_EN_CTL, val);511}512 513static void pmic_mpp_config_dbg_show(struct pinctrl_dev *pctldev,514 struct seq_file *s, unsigned pin)515{516 struct pmic_mpp_state *state = pinctrl_dev_get_drvdata(pctldev);517 struct pmic_mpp_pad *pad;518 int ret;519 520 static const char *const biases[] = {521 "0.6kOhm", "10kOhm", "30kOhm", "Disabled"522 };523 524 pad = pctldev->desc->pins[pin].drv_data;525 526 seq_printf(s, " mpp%-2d:", pin + PMIC_MPP_PHYSICAL_OFFSET);527 528 if (!pad->is_enabled) {529 seq_puts(s, " ---");530 } else {531 532 if (pad->input_enabled) {533 ret = pmic_mpp_read(state, pad, PMIC_MPP_REG_RT_STS);534 if (ret < 0)535 return;536 537 ret &= PMIC_MPP_REG_RT_STS_VAL_MASK;538 pad->out_value = ret;539 }540 541 seq_printf(s, " %-4s", pad->output_enabled ? "out" : "in");542 seq_printf(s, " %-7s", pmic_mpp_functions[pad->function]);543 seq_printf(s, " vin-%d", pad->power_source);544 seq_printf(s, " %d", pad->aout_level);545 if (pad->has_pullup)546 seq_printf(s, " %-8s", biases[pad->pullup]);547 seq_printf(s, " %-4s", pad->out_value ? "high" : "low");548 if (pad->dtest)549 seq_printf(s, " dtest%d", pad->dtest);550 if (pad->paired)551 seq_puts(s, " paired");552 }553}554 555static const struct pinconf_ops pmic_mpp_pinconf_ops = {556 .is_generic = true,557 .pin_config_group_get = pmic_mpp_config_get,558 .pin_config_group_set = pmic_mpp_config_set,559 .pin_config_group_dbg_show = pmic_mpp_config_dbg_show,560};561 562static int pmic_mpp_direction_input(struct gpio_chip *chip, unsigned pin)563{564 struct pmic_mpp_state *state = gpiochip_get_data(chip);565 unsigned long config;566 567 config = pinconf_to_config_packed(PIN_CONFIG_INPUT_ENABLE, 1);568 569 return pmic_mpp_config_set(state->ctrl, pin, &config, 1);570}571 572static int pmic_mpp_direction_output(struct gpio_chip *chip,573 unsigned pin, int val)574{575 struct pmic_mpp_state *state = gpiochip_get_data(chip);576 unsigned long config;577 578 config = pinconf_to_config_packed(PIN_CONFIG_OUTPUT, val);579 580 return pmic_mpp_config_set(state->ctrl, pin, &config, 1);581}582 583static int pmic_mpp_get(struct gpio_chip *chip, unsigned pin)584{585 struct pmic_mpp_state *state = gpiochip_get_data(chip);586 struct pmic_mpp_pad *pad;587 int ret;588 589 pad = state->ctrl->desc->pins[pin].drv_data;590 591 if (pad->input_enabled) {592 ret = pmic_mpp_read(state, pad, PMIC_MPP_REG_RT_STS);593 if (ret < 0)594 return ret;595 596 pad->out_value = ret & PMIC_MPP_REG_RT_STS_VAL_MASK;597 }598 599 return !!pad->out_value;600}601 602static void pmic_mpp_set(struct gpio_chip *chip, unsigned pin, int value)603{604 struct pmic_mpp_state *state = gpiochip_get_data(chip);605 unsigned long config;606 607 config = pinconf_to_config_packed(PIN_CONFIG_OUTPUT, value);608 609 pmic_mpp_config_set(state->ctrl, pin, &config, 1);610}611 612static int pmic_mpp_of_xlate(struct gpio_chip *chip,613 const struct of_phandle_args *gpio_desc,614 u32 *flags)615{616 if (chip->of_gpio_n_cells < 2)617 return -EINVAL;618 619 if (flags)620 *flags = gpio_desc->args[1];621 622 return gpio_desc->args[0] - PMIC_MPP_PHYSICAL_OFFSET;623}624 625static void pmic_mpp_dbg_show(struct seq_file *s, struct gpio_chip *chip)626{627 struct pmic_mpp_state *state = gpiochip_get_data(chip);628 unsigned i;629 630 for (i = 0; i < chip->ngpio; i++) {631 pmic_mpp_config_dbg_show(state->ctrl, s, i);632 seq_puts(s, "\n");633 }634}635 636static const struct gpio_chip pmic_mpp_gpio_template = {637 .direction_input = pmic_mpp_direction_input,638 .direction_output = pmic_mpp_direction_output,639 .get = pmic_mpp_get,640 .set = pmic_mpp_set,641 .request = gpiochip_generic_request,642 .free = gpiochip_generic_free,643 .of_xlate = pmic_mpp_of_xlate,644 .dbg_show = pmic_mpp_dbg_show,645};646 647static int pmic_mpp_populate(struct pmic_mpp_state *state,648 struct pmic_mpp_pad *pad)649{650 int type, subtype, val, dir;651 unsigned int sel;652 653 type = pmic_mpp_read(state, pad, PMIC_MPP_REG_TYPE);654 if (type < 0)655 return type;656 657 if (type != PMIC_MPP_TYPE) {658 dev_err(state->dev, "incorrect block type 0x%x at 0x%x\n",659 type, pad->base);660 return -ENODEV;661 }662 663 subtype = pmic_mpp_read(state, pad, PMIC_MPP_REG_SUBTYPE);664 if (subtype < 0)665 return subtype;666 667 switch (subtype) {668 case PMIC_MPP_SUBTYPE_4CH_NO_ANA_OUT:669 case PMIC_MPP_SUBTYPE_ULT_4CH_NO_ANA_OUT:670 case PMIC_MPP_SUBTYPE_4CH_NO_SINK:671 case PMIC_MPP_SUBTYPE_ULT_4CH_NO_SINK:672 case PMIC_MPP_SUBTYPE_4CH_FULL_FUNC:673 pad->num_sources = 4;674 break;675 case PMIC_MPP_SUBTYPE_8CH_FULL_FUNC:676 pad->num_sources = 8;677 break;678 default:679 dev_err(state->dev, "unknown MPP type 0x%x at 0x%x\n",680 subtype, pad->base);681 return -ENODEV;682 }683 684 val = pmic_mpp_read(state, pad, PMIC_MPP_REG_MODE_CTL);685 if (val < 0)686 return val;687 688 pad->out_value = val & PMIC_MPP_REG_MODE_VALUE_MASK;689 690 dir = val >> PMIC_MPP_REG_MODE_DIR_SHIFT;691 dir &= PMIC_MPP_REG_MODE_DIR_MASK;692 693 switch (dir) {694 case PMIC_MPP_MODE_DIGITAL_INPUT:695 pad->input_enabled = true;696 pad->output_enabled = false;697 pad->function = PMIC_MPP_DIGITAL;698 break;699 case PMIC_MPP_MODE_DIGITAL_OUTPUT:700 pad->input_enabled = false;701 pad->output_enabled = true;702 pad->function = PMIC_MPP_DIGITAL;703 break;704 case PMIC_MPP_MODE_DIGITAL_BIDIR:705 pad->input_enabled = true;706 pad->output_enabled = true;707 pad->function = PMIC_MPP_DIGITAL;708 break;709 case PMIC_MPP_MODE_ANALOG_BIDIR:710 pad->input_enabled = true;711 pad->output_enabled = true;712 pad->function = PMIC_MPP_ANALOG;713 break;714 case PMIC_MPP_MODE_ANALOG_INPUT:715 pad->input_enabled = true;716 pad->output_enabled = false;717 pad->function = PMIC_MPP_ANALOG;718 break;719 case PMIC_MPP_MODE_ANALOG_OUTPUT:720 pad->input_enabled = false;721 pad->output_enabled = true;722 pad->function = PMIC_MPP_ANALOG;723 break;724 case PMIC_MPP_MODE_CURRENT_SINK:725 pad->input_enabled = false;726 pad->output_enabled = true;727 pad->function = PMIC_MPP_SINK;728 break;729 default:730 dev_err(state->dev, "unknown MPP direction\n");731 return -ENODEV;732 }733 734 sel = val >> PMIC_MPP_REG_MODE_FUNCTION_SHIFT;735 sel &= PMIC_MPP_REG_MODE_FUNCTION_MASK;736 737 if (sel >= PMIC_MPP_SELECTOR_DTEST_FIRST)738 pad->dtest = sel + 1;739 else if (sel == PMIC_MPP_SELECTOR_PAIRED)740 pad->paired = true;741 742 val = pmic_mpp_read(state, pad, PMIC_MPP_REG_DIG_VIN_CTL);743 if (val < 0)744 return val;745 746 pad->power_source = val >> PMIC_MPP_REG_VIN_SHIFT;747 pad->power_source &= PMIC_MPP_REG_VIN_MASK;748 749 if (subtype != PMIC_MPP_SUBTYPE_ULT_4CH_NO_ANA_OUT &&750 subtype != PMIC_MPP_SUBTYPE_ULT_4CH_NO_SINK) {751 val = pmic_mpp_read(state, pad, PMIC_MPP_REG_DIG_PULL_CTL);752 if (val < 0)753 return val;754 755 pad->pullup = val >> PMIC_MPP_REG_PULL_SHIFT;756 pad->pullup &= PMIC_MPP_REG_PULL_MASK;757 pad->has_pullup = true;758 }759 760 val = pmic_mpp_read(state, pad, PMIC_MPP_REG_AIN_CTL);761 if (val < 0)762 return val;763 764 pad->amux_input = val >> PMIC_MPP_REG_AIN_ROUTE_SHIFT;765 pad->amux_input &= PMIC_MPP_REG_AIN_ROUTE_MASK;766 767 val = pmic_mpp_read(state, pad, PMIC_MPP_REG_SINK_CTL);768 if (val < 0)769 return val;770 771 pad->drive_strength = val;772 773 val = pmic_mpp_read(state, pad, PMIC_MPP_REG_AOUT_CTL);774 if (val < 0)775 return val;776 777 pad->aout_level = val;778 779 val = pmic_mpp_read(state, pad, PMIC_MPP_REG_EN_CTL);780 if (val < 0)781 return val;782 783 pad->is_enabled = !!val;784 785 return 0;786}787 788static int pmic_mpp_domain_translate(struct irq_domain *domain,789 struct irq_fwspec *fwspec,790 unsigned long *hwirq,791 unsigned int *type)792{793 struct pmic_mpp_state *state = container_of(domain->host_data,794 struct pmic_mpp_state,795 chip);796 797 if (fwspec->param_count != 2 ||798 fwspec->param[0] < 1 || fwspec->param[0] > state->chip.ngpio)799 return -EINVAL;800 801 *hwirq = fwspec->param[0] - PMIC_MPP_PHYSICAL_OFFSET;802 *type = fwspec->param[1];803 804 return 0;805}806 807static unsigned int pmic_mpp_child_offset_to_irq(struct gpio_chip *chip,808 unsigned int offset)809{810 return offset + PMIC_MPP_PHYSICAL_OFFSET;811}812 813static int pmic_mpp_child_to_parent_hwirq(struct gpio_chip *chip,814 unsigned int child_hwirq,815 unsigned int child_type,816 unsigned int *parent_hwirq,817 unsigned int *parent_type)818{819 *parent_hwirq = child_hwirq + 0xc0;820 *parent_type = child_type;821 822 return 0;823}824 825static void pmic_mpp_irq_mask(struct irq_data *d)826{827 struct gpio_chip *gc = irq_data_get_irq_chip_data(d);828 829 irq_chip_mask_parent(d);830 gpiochip_disable_irq(gc, irqd_to_hwirq(d));831}832 833static void pmic_mpp_irq_unmask(struct irq_data *d)834{835 struct gpio_chip *gc = irq_data_get_irq_chip_data(d);836 837 gpiochip_enable_irq(gc, irqd_to_hwirq(d));838 irq_chip_unmask_parent(d);839}840 841static const struct irq_chip pmic_mpp_irq_chip = {842 .name = "spmi-mpp",843 .irq_ack = irq_chip_ack_parent,844 .irq_mask = pmic_mpp_irq_mask,845 .irq_unmask = pmic_mpp_irq_unmask,846 .irq_set_type = irq_chip_set_type_parent,847 .irq_set_wake = irq_chip_set_wake_parent,848 .flags = IRQCHIP_MASK_ON_SUSPEND | IRQCHIP_IMMUTABLE,849 GPIOCHIP_IRQ_RESOURCE_HELPERS,850};851 852static int pmic_mpp_probe(struct platform_device *pdev)853{854 struct irq_domain *parent_domain;855 struct device_node *parent_node;856 struct device *dev = &pdev->dev;857 struct pinctrl_pin_desc *pindesc;858 struct pinctrl_desc *pctrldesc;859 struct pmic_mpp_pad *pad, *pads;860 struct pmic_mpp_state *state;861 struct gpio_irq_chip *girq;862 int ret, npins, i;863 u32 reg;864 865 ret = of_property_read_u32(dev->of_node, "reg", ®);866 if (ret < 0) {867 dev_err(dev, "missing base address");868 return ret;869 }870 871 npins = (uintptr_t) device_get_match_data(&pdev->dev);872 873 BUG_ON(npins > ARRAY_SIZE(pmic_mpp_groups));874 875 state = devm_kzalloc(dev, sizeof(*state), GFP_KERNEL);876 if (!state)877 return -ENOMEM;878 879 platform_set_drvdata(pdev, state);880 881 state->dev = &pdev->dev;882 state->map = dev_get_regmap(dev->parent, NULL);883 884 pindesc = devm_kcalloc(dev, npins, sizeof(*pindesc), GFP_KERNEL);885 if (!pindesc)886 return -ENOMEM;887 888 pads = devm_kcalloc(dev, npins, sizeof(*pads), GFP_KERNEL);889 if (!pads)890 return -ENOMEM;891 892 pctrldesc = devm_kzalloc(dev, sizeof(*pctrldesc), GFP_KERNEL);893 if (!pctrldesc)894 return -ENOMEM;895 896 pctrldesc->pctlops = &pmic_mpp_pinctrl_ops;897 pctrldesc->pmxops = &pmic_mpp_pinmux_ops;898 pctrldesc->confops = &pmic_mpp_pinconf_ops;899 pctrldesc->owner = THIS_MODULE;900 pctrldesc->name = dev_name(dev);901 pctrldesc->pins = pindesc;902 pctrldesc->npins = npins;903 904 pctrldesc->num_custom_params = ARRAY_SIZE(pmic_mpp_bindings);905 pctrldesc->custom_params = pmic_mpp_bindings;906#ifdef CONFIG_DEBUG_FS907 pctrldesc->custom_conf_items = pmic_conf_items;908#endif909 910 for (i = 0; i < npins; i++, pindesc++) {911 pad = &pads[i];912 pindesc->drv_data = pad;913 pindesc->number = i;914 pindesc->name = pmic_mpp_groups[i];915 916 pad->base = reg + i * PMIC_MPP_ADDRESS_RANGE;917 918 ret = pmic_mpp_populate(state, pad);919 if (ret < 0)920 return ret;921 }922 923 state->chip = pmic_mpp_gpio_template;924 state->chip.parent = dev;925 state->chip.base = -1;926 state->chip.ngpio = npins;927 state->chip.label = dev_name(dev);928 state->chip.of_gpio_n_cells = 2;929 state->chip.can_sleep = false;930 931 state->ctrl = devm_pinctrl_register(dev, pctrldesc, state);932 if (IS_ERR(state->ctrl))933 return PTR_ERR(state->ctrl);934 935 parent_node = of_irq_find_parent(state->dev->of_node);936 if (!parent_node)937 return -ENXIO;938 939 parent_domain = irq_find_host(parent_node);940 of_node_put(parent_node);941 if (!parent_domain)942 return -ENXIO;943 944 girq = &state->chip.irq;945 gpio_irq_chip_set_chip(girq, &pmic_mpp_irq_chip);946 girq->default_type = IRQ_TYPE_NONE;947 girq->handler = handle_level_irq;948 girq->fwnode = dev_fwnode(state->dev);949 girq->parent_domain = parent_domain;950 girq->child_to_parent_hwirq = pmic_mpp_child_to_parent_hwirq;951 girq->populate_parent_alloc_arg = gpiochip_populate_parent_fwspec_fourcell;952 girq->child_offset_to_irq = pmic_mpp_child_offset_to_irq;953 girq->child_irq_domain_ops.translate = pmic_mpp_domain_translate;954 955 ret = gpiochip_add_data(&state->chip, state);956 if (ret) {957 dev_err(state->dev, "can't add gpio chip\n");958 return ret;959 }960 961 ret = gpiochip_add_pin_range(&state->chip, dev_name(dev), 0, 0, npins);962 if (ret) {963 dev_err(dev, "failed to add pin range\n");964 goto err_range;965 }966 967 return 0;968 969err_range:970 gpiochip_remove(&state->chip);971 return ret;972}973 974static void pmic_mpp_remove(struct platform_device *pdev)975{976 struct pmic_mpp_state *state = platform_get_drvdata(pdev);977 978 gpiochip_remove(&state->chip);979}980 981static const struct of_device_id pmic_mpp_of_match[] = {982 { .compatible = "qcom,pm8019-mpp", .data = (void *) 6 },983 { .compatible = "qcom,pm8226-mpp", .data = (void *) 8 },984 { .compatible = "qcom,pm8841-mpp", .data = (void *) 4 },985 { .compatible = "qcom,pm8916-mpp", .data = (void *) 4 },986 { .compatible = "qcom,pm8941-mpp", .data = (void *) 8 },987 { .compatible = "qcom,pm8950-mpp", .data = (void *) 4 },988 { .compatible = "qcom,pmi8950-mpp", .data = (void *) 4 },989 { .compatible = "qcom,pm8994-mpp", .data = (void *) 8 },990 { .compatible = "qcom,pma8084-mpp", .data = (void *) 8 },991 { .compatible = "qcom,pmi8994-mpp", .data = (void *) 4 },992 { },993};994 995MODULE_DEVICE_TABLE(of, pmic_mpp_of_match);996 997static struct platform_driver pmic_mpp_driver = {998 .driver = {999 .name = "qcom-spmi-mpp",1000 .of_match_table = pmic_mpp_of_match,1001 },1002 .probe = pmic_mpp_probe,1003 .remove_new = pmic_mpp_remove,1004};1005 1006module_platform_driver(pmic_mpp_driver);1007 1008MODULE_AUTHOR("Ivan T. Ivanov <iivanov@mm-sol.com>");1009MODULE_DESCRIPTION("Qualcomm SPMI PMIC MPP pin control driver");1010MODULE_ALIAS("platform:qcom-spmi-mpp");1011MODULE_LICENSE("GPL v2");1012