···12331233 This option enables support for on-chip GPIO found12341234 on Analog Devices ADP5520 PMICs.1235123512361236+config GPIO_ADP558512371237+ tristate "GPIO Support for ADP5585"12381238+ depends on MFD_ADP558512391239+ help12401240+ This option enables support for the GPIO function found in the Analog12411241+ Devices ADP5585.12421242+12361243config GPIO_ALTERA_A10SR12371244 tristate "Altera Arria10 System Resource GPIO"12381245 depends on MFD_ALTERA_A10SR
···11+// SPDX-License-Identifier: GPL-2.0-only22+/*33+ * Analog Devices ADP5585 GPIO driver44+ *55+ * Copyright 2022 NXP66+ * Copyright 2024 Ideas on Board Oy77+ */88+99+#include <linux/device.h>1010+#include <linux/gpio/driver.h>1111+#include <linux/mfd/adp5585.h>1212+#include <linux/module.h>1313+#include <linux/platform_device.h>1414+#include <linux/regmap.h>1515+#include <linux/types.h>1616+1717+#define ADP5585_GPIO_MAX 111818+1919+struct adp5585_gpio_dev {2020+ struct gpio_chip gpio_chip;2121+ struct regmap *regmap;2222+};2323+2424+static int adp5585_gpio_get_direction(struct gpio_chip *chip, unsigned int off)2525+{2626+ struct adp5585_gpio_dev *adp5585_gpio = gpiochip_get_data(chip);2727+ unsigned int bank = ADP5585_BANK(off);2828+ unsigned int bit = ADP5585_BIT(off);2929+ unsigned int val;3030+3131+ regmap_read(adp5585_gpio->regmap, ADP5585_GPIO_DIRECTION_A + bank, &val);3232+3333+ return val & bit ? GPIO_LINE_DIRECTION_OUT : GPIO_LINE_DIRECTION_IN;3434+}3535+3636+static int adp5585_gpio_direction_input(struct gpio_chip *chip, unsigned int off)3737+{3838+ struct adp5585_gpio_dev *adp5585_gpio = gpiochip_get_data(chip);3939+ unsigned int bank = ADP5585_BANK(off);4040+ unsigned int bit = ADP5585_BIT(off);4141+4242+ return regmap_clear_bits(adp5585_gpio->regmap,4343+ ADP5585_GPIO_DIRECTION_A + bank, bit);4444+}4545+4646+static int adp5585_gpio_direction_output(struct gpio_chip *chip, unsigned int off, int val)4747+{4848+ struct adp5585_gpio_dev *adp5585_gpio = gpiochip_get_data(chip);4949+ unsigned int bank = ADP5585_BANK(off);5050+ unsigned int bit = ADP5585_BIT(off);5151+ int ret;5252+5353+ ret = regmap_update_bits(adp5585_gpio->regmap,5454+ ADP5585_GPO_DATA_OUT_A + bank, bit,5555+ val ? bit : 0);5656+ if (ret)5757+ return ret;5858+5959+ return regmap_set_bits(adp5585_gpio->regmap,6060+ ADP5585_GPIO_DIRECTION_A + bank, bit);6161+}6262+6363+static int adp5585_gpio_get_value(struct gpio_chip *chip, unsigned int off)6464+{6565+ struct adp5585_gpio_dev *adp5585_gpio = gpiochip_get_data(chip);6666+ unsigned int bank = ADP5585_BANK(off);6767+ unsigned int bit = ADP5585_BIT(off);6868+ unsigned int reg;6969+ unsigned int val;7070+7171+ /*7272+ * The input status register doesn't reflect the pin state when the7373+ * GPIO is configured as an output. Check the direction, and read the7474+ * input status from GPI_STATUS or output value from GPO_DATA_OUT7575+ * accordingly.7676+ *7777+ * We don't need any locking, as concurrent access to the same GPIO7878+ * isn't allowed by the GPIO API, so there's no risk of the7979+ * .direction_input(), .direction_output() or .set() operations racing8080+ * with this.8181+ */8282+ regmap_read(adp5585_gpio->regmap, ADP5585_GPIO_DIRECTION_A + bank, &val);8383+ reg = val & bit ? ADP5585_GPO_DATA_OUT_A : ADP5585_GPI_STATUS_A;8484+ regmap_read(adp5585_gpio->regmap, reg + bank, &val);8585+8686+ return !!(val & bit);8787+}8888+8989+static void adp5585_gpio_set_value(struct gpio_chip *chip, unsigned int off, int val)9090+{9191+ struct adp5585_gpio_dev *adp5585_gpio = gpiochip_get_data(chip);9292+ unsigned int bank = ADP5585_BANK(off);9393+ unsigned int bit = ADP5585_BIT(off);9494+9595+ regmap_update_bits(adp5585_gpio->regmap, ADP5585_GPO_DATA_OUT_A + bank,9696+ bit, val ? bit : 0);9797+}9898+9999+static int adp5585_gpio_set_bias(struct adp5585_gpio_dev *adp5585_gpio,100100+ unsigned int off, unsigned int bias)101101+{102102+ unsigned int bit, reg, mask, val;103103+104104+ /*105105+ * The bias configuration fields are 2 bits wide and laid down in106106+ * consecutive registers ADP5585_RPULL_CONFIG_*, with a hole of 4 bits107107+ * after R5.108108+ */109109+ bit = off * 2 + (off > 5 ? 4 : 0);110110+ reg = ADP5585_RPULL_CONFIG_A + bit / 8;111111+ mask = ADP5585_Rx_PULL_CFG_MASK << (bit % 8);112112+ val = bias << (bit % 8);113113+114114+ return regmap_update_bits(adp5585_gpio->regmap, reg, mask, val);115115+}116116+117117+static int adp5585_gpio_set_drive(struct adp5585_gpio_dev *adp5585_gpio,118118+ unsigned int off, enum pin_config_param drive)119119+{120120+ unsigned int bank = ADP5585_BANK(off);121121+ unsigned int bit = ADP5585_BIT(off);122122+123123+ return regmap_update_bits(adp5585_gpio->regmap,124124+ ADP5585_GPO_OUT_MODE_A + bank, bit,125125+ drive == PIN_CONFIG_DRIVE_OPEN_DRAIN ? bit : 0);126126+}127127+128128+static int adp5585_gpio_set_debounce(struct adp5585_gpio_dev *adp5585_gpio,129129+ unsigned int off, unsigned int debounce)130130+{131131+ unsigned int bank = ADP5585_BANK(off);132132+ unsigned int bit = ADP5585_BIT(off);133133+134134+ return regmap_update_bits(adp5585_gpio->regmap,135135+ ADP5585_DEBOUNCE_DIS_A + bank, bit,136136+ debounce ? 0 : bit);137137+}138138+139139+static int adp5585_gpio_set_config(struct gpio_chip *chip, unsigned int off,140140+ unsigned long config)141141+{142142+ struct adp5585_gpio_dev *adp5585_gpio = gpiochip_get_data(chip);143143+ enum pin_config_param param = pinconf_to_config_param(config);144144+ u32 arg = pinconf_to_config_argument(config);145145+146146+ switch (param) {147147+ case PIN_CONFIG_BIAS_DISABLE:148148+ return adp5585_gpio_set_bias(adp5585_gpio, off,149149+ ADP5585_Rx_PULL_CFG_DISABLE);150150+151151+ case PIN_CONFIG_BIAS_PULL_DOWN:152152+ return adp5585_gpio_set_bias(adp5585_gpio, off, arg ?153153+ ADP5585_Rx_PULL_CFG_PD_300K :154154+ ADP5585_Rx_PULL_CFG_DISABLE);155155+156156+ case PIN_CONFIG_BIAS_PULL_UP:157157+ return adp5585_gpio_set_bias(adp5585_gpio, off, arg ?158158+ ADP5585_Rx_PULL_CFG_PU_300K :159159+ ADP5585_Rx_PULL_CFG_DISABLE);160160+161161+ case PIN_CONFIG_DRIVE_OPEN_DRAIN:162162+ case PIN_CONFIG_DRIVE_PUSH_PULL:163163+ return adp5585_gpio_set_drive(adp5585_gpio, off, param);164164+165165+ case PIN_CONFIG_INPUT_DEBOUNCE:166166+ return adp5585_gpio_set_debounce(adp5585_gpio, off, arg);167167+168168+ default:169169+ return -ENOTSUPP;170170+ };171171+}172172+173173+static int adp5585_gpio_probe(struct platform_device *pdev)174174+{175175+ struct adp5585_dev *adp5585 = dev_get_drvdata(pdev->dev.parent);176176+ struct adp5585_gpio_dev *adp5585_gpio;177177+ struct device *dev = &pdev->dev;178178+ struct gpio_chip *gc;179179+ int ret;180180+181181+ adp5585_gpio = devm_kzalloc(dev, sizeof(*adp5585_gpio), GFP_KERNEL);182182+ if (!adp5585_gpio)183183+ return -ENOMEM;184184+185185+ adp5585_gpio->regmap = adp5585->regmap;186186+187187+ device_set_of_node_from_dev(dev, dev->parent);188188+189189+ gc = &adp5585_gpio->gpio_chip;190190+ gc->parent = dev;191191+ gc->get_direction = adp5585_gpio_get_direction;192192+ gc->direction_input = adp5585_gpio_direction_input;193193+ gc->direction_output = adp5585_gpio_direction_output;194194+ gc->get = adp5585_gpio_get_value;195195+ gc->set = adp5585_gpio_set_value;196196+ gc->set_config = adp5585_gpio_set_config;197197+ gc->can_sleep = true;198198+199199+ gc->base = -1;200200+ gc->ngpio = ADP5585_GPIO_MAX;201201+ gc->label = pdev->name;202202+ gc->owner = THIS_MODULE;203203+204204+ ret = devm_gpiochip_add_data(dev, &adp5585_gpio->gpio_chip,205205+ adp5585_gpio);206206+ if (ret)207207+ return dev_err_probe(dev, ret, "failed to add GPIO chip\n");208208+209209+ return 0;210210+}211211+212212+static const struct platform_device_id adp5585_gpio_id_table[] = {213213+ { "adp5585-gpio" },214214+ { /* Sentinel */ }215215+};216216+MODULE_DEVICE_TABLE(platform, adp5585_gpio_id_table);217217+218218+static struct platform_driver adp5585_gpio_driver = {219219+ .driver = {220220+ .name = "adp5585-gpio",221221+ },222222+ .probe = adp5585_gpio_probe,223223+ .id_table = adp5585_gpio_id_table,224224+};225225+module_platform_driver(adp5585_gpio_driver);226226+227227+MODULE_AUTHOR("Haibo Chen <haibo.chen@nxp.com>");228228+MODULE_DESCRIPTION("GPIO ADP5585 Driver");229229+MODULE_LICENSE("GPL");
+12
drivers/mfd/Kconfig
···2020 This is the core driver for CS5535/CS5536 MFD functions. This is2121 necessary for using the board's GPIO and MFGPT functionality.22222323+config MFD_ADP55852424+ tristate "Analog Devices ADP5585 keypad decoder and I/O expander driver"2525+ select MFD_CORE2626+ select REGMAP_I2C2727+ depends on I2C2828+ depends on OF || COMPILE_TEST2929+ help3030+ Say yes here to add support for the Analog Devices ADP5585 GPIO3131+ expander, PWM and keypad controller. This includes the I2C driver and3232+ the core APIs _only_, you have to select individual components like3333+ the GPIO and PWM functions under the corresponding menus.3434+2335config MFD_ALTERA_A10SR2436 bool "Altera Arria10 DevKit System Resource chip"2537 depends on ARCH_INTEL_SOCFPGA && SPI_MASTER=y && OF
···4747 To compile this driver as a module, choose M here: the module4848 will be called pwm-ab8500.49495050+config PWM_ADP55855151+ tristate "ADP5585 PWM support"5252+ depends on MFD_ADP55855353+ help5454+ This option enables support for the PWM function found in the Analog5555+ Devices ADP5585.5656+5057config PWM_APPLE5158 tristate "Apple SoC PWM support"5259 depends on ARCH_APPLE || COMPILE_TEST