Merge branches 'ib-mfd-for-iio-power-6.12' and 'ib-mfd-gpio-pwm-6.12' into ibs-for-mfd-merged
This commit is contained in:
commit
03bd36838e
92
Documentation/devicetree/bindings/mfd/adi,adp5585.yaml
Normal file
92
Documentation/devicetree/bindings/mfd/adi,adp5585.yaml
Normal file
@ -0,0 +1,92 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/mfd/adi,adp5585.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Analog Devices ADP5585 Keypad Decoder and I/O Expansion
|
||||
|
||||
maintainers:
|
||||
- Laurent Pinchart <laurent.pinchart@ideasonboard.com>
|
||||
|
||||
description:
|
||||
The ADP5585 is a 10/11 input/output port expander with a built in keypad
|
||||
matrix decoder, programmable logic, reset generator, and PWM generator.
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
items:
|
||||
- enum:
|
||||
- adi,adp5585-00 # Default
|
||||
- adi,adp5585-01 # 11 GPIOs
|
||||
- adi,adp5585-02 # No pull-up resistors by default on special pins
|
||||
- adi,adp5585-03 # Alternate I2C address
|
||||
- adi,adp5585-04 # Pull-down resistors on all pins by default
|
||||
- const: adi,adp5585
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
|
||||
vdd-supply: true
|
||||
|
||||
gpio-controller: true
|
||||
|
||||
'#gpio-cells':
|
||||
const: 2
|
||||
|
||||
gpio-reserved-ranges: true
|
||||
|
||||
"#pwm-cells":
|
||||
const: 3
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- gpio-controller
|
||||
- "#gpio-cells"
|
||||
- "#pwm-cells"
|
||||
|
||||
allOf:
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
const: adi,adp5585-01
|
||||
then:
|
||||
properties:
|
||||
gpio-reserved-ranges: false
|
||||
else:
|
||||
properties:
|
||||
gpio-reserved-ranges:
|
||||
maxItems: 1
|
||||
items:
|
||||
items:
|
||||
- const: 5
|
||||
- const: 1
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
i2c {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
io-expander@34 {
|
||||
compatible = "adi,adp5585-00", "adi,adp5585";
|
||||
reg = <0x34>;
|
||||
|
||||
vdd-supply = <®_3v3>;
|
||||
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
gpio-reserved-ranges = <5 1>;
|
||||
|
||||
#pwm-cells = <3>;
|
||||
};
|
||||
};
|
||||
|
||||
...
|
@ -38,10 +38,6 @@ properties:
|
||||
- ad,adm9240
|
||||
# AD5110 - Nonvolatile Digital Potentiometer
|
||||
- adi,ad5110
|
||||
# Analog Devices ADP5585 Keypad Decoder and I/O Expansion
|
||||
- adi,adp5585
|
||||
# Analog Devices ADP5585 Keypad Decoder and I/O Expansion with support for Row5
|
||||
- adi,adp5585-02
|
||||
# Analog Devices ADP5589 Keypad Decoder and I/O Expansion
|
||||
- adi,adp5589
|
||||
# Analog Devices LT7182S Dual Channel 6A, 20V PolyPhase Step-Down Silent Switcher
|
||||
|
11
MAINTAINERS
11
MAINTAINERS
@ -537,6 +537,17 @@ F: drivers/leds/leds-adp5520.c
|
||||
F: drivers/mfd/adp5520.c
|
||||
F: drivers/video/backlight/adp5520_bl.c
|
||||
|
||||
ADP5585 GPIO EXPANDER, PWM AND KEYPAD CONTROLLER DRIVER
|
||||
M: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
|
||||
L: linux-gpio@vger.kernel.org
|
||||
L: linux-pwm@vger.kernel.org
|
||||
S: Maintained
|
||||
F: Documentation/devicetree/bindings/*/adi,adp5585*.yaml
|
||||
F: drivers/gpio/gpio-adp5585.c
|
||||
F: drivers/mfd/adp5585.c
|
||||
F: drivers/pwm/pwm-adp5585.c
|
||||
F: include/linux/mfd/adp5585.h
|
||||
|
||||
ADP5588 QWERTY KEYPAD AND IO EXPANDER DRIVER (ADP5588/ADP5587)
|
||||
M: Michael Hennerich <michael.hennerich@analog.com>
|
||||
S: Supported
|
||||
|
@ -1233,6 +1233,13 @@ config GPIO_ADP5520
|
||||
This option enables support for on-chip GPIO found
|
||||
on Analog Devices ADP5520 PMICs.
|
||||
|
||||
config GPIO_ADP5585
|
||||
tristate "GPIO Support for ADP5585"
|
||||
depends on MFD_ADP5585
|
||||
help
|
||||
This option enables support for the GPIO function found in the Analog
|
||||
Devices ADP5585.
|
||||
|
||||
config GPIO_ALTERA_A10SR
|
||||
tristate "Altera Arria10 System Resource GPIO"
|
||||
depends on MFD_ALTERA_A10SR
|
||||
|
@ -26,6 +26,7 @@ obj-$(CONFIG_GPIO_74X164) += gpio-74x164.o
|
||||
obj-$(CONFIG_GPIO_74XX_MMIO) += gpio-74xx-mmio.o
|
||||
obj-$(CONFIG_GPIO_ADNP) += gpio-adnp.o
|
||||
obj-$(CONFIG_GPIO_ADP5520) += gpio-adp5520.o
|
||||
obj-$(CONFIG_GPIO_ADP5585) += gpio-adp5585.o
|
||||
obj-$(CONFIG_GPIO_AGGREGATOR) += gpio-aggregator.o
|
||||
obj-$(CONFIG_GPIO_ALTERA_A10SR) += gpio-altera-a10sr.o
|
||||
obj-$(CONFIG_GPIO_ALTERA) += gpio-altera.o
|
||||
|
229
drivers/gpio/gpio-adp5585.c
Normal file
229
drivers/gpio/gpio-adp5585.c
Normal file
@ -0,0 +1,229 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Analog Devices ADP5585 GPIO driver
|
||||
*
|
||||
* Copyright 2022 NXP
|
||||
* Copyright 2024 Ideas on Board Oy
|
||||
*/
|
||||
|
||||
#include <linux/device.h>
|
||||
#include <linux/gpio/driver.h>
|
||||
#include <linux/mfd/adp5585.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/types.h>
|
||||
|
||||
#define ADP5585_GPIO_MAX 11
|
||||
|
||||
struct adp5585_gpio_dev {
|
||||
struct gpio_chip gpio_chip;
|
||||
struct regmap *regmap;
|
||||
};
|
||||
|
||||
static int adp5585_gpio_get_direction(struct gpio_chip *chip, unsigned int off)
|
||||
{
|
||||
struct adp5585_gpio_dev *adp5585_gpio = gpiochip_get_data(chip);
|
||||
unsigned int bank = ADP5585_BANK(off);
|
||||
unsigned int bit = ADP5585_BIT(off);
|
||||
unsigned int val;
|
||||
|
||||
regmap_read(adp5585_gpio->regmap, ADP5585_GPIO_DIRECTION_A + bank, &val);
|
||||
|
||||
return val & bit ? GPIO_LINE_DIRECTION_OUT : GPIO_LINE_DIRECTION_IN;
|
||||
}
|
||||
|
||||
static int adp5585_gpio_direction_input(struct gpio_chip *chip, unsigned int off)
|
||||
{
|
||||
struct adp5585_gpio_dev *adp5585_gpio = gpiochip_get_data(chip);
|
||||
unsigned int bank = ADP5585_BANK(off);
|
||||
unsigned int bit = ADP5585_BIT(off);
|
||||
|
||||
return regmap_clear_bits(adp5585_gpio->regmap,
|
||||
ADP5585_GPIO_DIRECTION_A + bank, bit);
|
||||
}
|
||||
|
||||
static int adp5585_gpio_direction_output(struct gpio_chip *chip, unsigned int off, int val)
|
||||
{
|
||||
struct adp5585_gpio_dev *adp5585_gpio = gpiochip_get_data(chip);
|
||||
unsigned int bank = ADP5585_BANK(off);
|
||||
unsigned int bit = ADP5585_BIT(off);
|
||||
int ret;
|
||||
|
||||
ret = regmap_update_bits(adp5585_gpio->regmap,
|
||||
ADP5585_GPO_DATA_OUT_A + bank, bit,
|
||||
val ? bit : 0);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return regmap_set_bits(adp5585_gpio->regmap,
|
||||
ADP5585_GPIO_DIRECTION_A + bank, bit);
|
||||
}
|
||||
|
||||
static int adp5585_gpio_get_value(struct gpio_chip *chip, unsigned int off)
|
||||
{
|
||||
struct adp5585_gpio_dev *adp5585_gpio = gpiochip_get_data(chip);
|
||||
unsigned int bank = ADP5585_BANK(off);
|
||||
unsigned int bit = ADP5585_BIT(off);
|
||||
unsigned int reg;
|
||||
unsigned int val;
|
||||
|
||||
/*
|
||||
* The input status register doesn't reflect the pin state when the
|
||||
* GPIO is configured as an output. Check the direction, and read the
|
||||
* input status from GPI_STATUS or output value from GPO_DATA_OUT
|
||||
* accordingly.
|
||||
*
|
||||
* We don't need any locking, as concurrent access to the same GPIO
|
||||
* isn't allowed by the GPIO API, so there's no risk of the
|
||||
* .direction_input(), .direction_output() or .set() operations racing
|
||||
* with this.
|
||||
*/
|
||||
regmap_read(adp5585_gpio->regmap, ADP5585_GPIO_DIRECTION_A + bank, &val);
|
||||
reg = val & bit ? ADP5585_GPO_DATA_OUT_A : ADP5585_GPI_STATUS_A;
|
||||
regmap_read(adp5585_gpio->regmap, reg + bank, &val);
|
||||
|
||||
return !!(val & bit);
|
||||
}
|
||||
|
||||
static void adp5585_gpio_set_value(struct gpio_chip *chip, unsigned int off, int val)
|
||||
{
|
||||
struct adp5585_gpio_dev *adp5585_gpio = gpiochip_get_data(chip);
|
||||
unsigned int bank = ADP5585_BANK(off);
|
||||
unsigned int bit = ADP5585_BIT(off);
|
||||
|
||||
regmap_update_bits(adp5585_gpio->regmap, ADP5585_GPO_DATA_OUT_A + bank,
|
||||
bit, val ? bit : 0);
|
||||
}
|
||||
|
||||
static int adp5585_gpio_set_bias(struct adp5585_gpio_dev *adp5585_gpio,
|
||||
unsigned int off, unsigned int bias)
|
||||
{
|
||||
unsigned int bit, reg, mask, val;
|
||||
|
||||
/*
|
||||
* The bias configuration fields are 2 bits wide and laid down in
|
||||
* consecutive registers ADP5585_RPULL_CONFIG_*, with a hole of 4 bits
|
||||
* after R5.
|
||||
*/
|
||||
bit = off * 2 + (off > 5 ? 4 : 0);
|
||||
reg = ADP5585_RPULL_CONFIG_A + bit / 8;
|
||||
mask = ADP5585_Rx_PULL_CFG_MASK << (bit % 8);
|
||||
val = bias << (bit % 8);
|
||||
|
||||
return regmap_update_bits(adp5585_gpio->regmap, reg, mask, val);
|
||||
}
|
||||
|
||||
static int adp5585_gpio_set_drive(struct adp5585_gpio_dev *adp5585_gpio,
|
||||
unsigned int off, enum pin_config_param drive)
|
||||
{
|
||||
unsigned int bank = ADP5585_BANK(off);
|
||||
unsigned int bit = ADP5585_BIT(off);
|
||||
|
||||
return regmap_update_bits(adp5585_gpio->regmap,
|
||||
ADP5585_GPO_OUT_MODE_A + bank, bit,
|
||||
drive == PIN_CONFIG_DRIVE_OPEN_DRAIN ? bit : 0);
|
||||
}
|
||||
|
||||
static int adp5585_gpio_set_debounce(struct adp5585_gpio_dev *adp5585_gpio,
|
||||
unsigned int off, unsigned int debounce)
|
||||
{
|
||||
unsigned int bank = ADP5585_BANK(off);
|
||||
unsigned int bit = ADP5585_BIT(off);
|
||||
|
||||
return regmap_update_bits(adp5585_gpio->regmap,
|
||||
ADP5585_DEBOUNCE_DIS_A + bank, bit,
|
||||
debounce ? 0 : bit);
|
||||
}
|
||||
|
||||
static int adp5585_gpio_set_config(struct gpio_chip *chip, unsigned int off,
|
||||
unsigned long config)
|
||||
{
|
||||
struct adp5585_gpio_dev *adp5585_gpio = gpiochip_get_data(chip);
|
||||
enum pin_config_param param = pinconf_to_config_param(config);
|
||||
u32 arg = pinconf_to_config_argument(config);
|
||||
|
||||
switch (param) {
|
||||
case PIN_CONFIG_BIAS_DISABLE:
|
||||
return adp5585_gpio_set_bias(adp5585_gpio, off,
|
||||
ADP5585_Rx_PULL_CFG_DISABLE);
|
||||
|
||||
case PIN_CONFIG_BIAS_PULL_DOWN:
|
||||
return adp5585_gpio_set_bias(adp5585_gpio, off, arg ?
|
||||
ADP5585_Rx_PULL_CFG_PD_300K :
|
||||
ADP5585_Rx_PULL_CFG_DISABLE);
|
||||
|
||||
case PIN_CONFIG_BIAS_PULL_UP:
|
||||
return adp5585_gpio_set_bias(adp5585_gpio, off, arg ?
|
||||
ADP5585_Rx_PULL_CFG_PU_300K :
|
||||
ADP5585_Rx_PULL_CFG_DISABLE);
|
||||
|
||||
case PIN_CONFIG_DRIVE_OPEN_DRAIN:
|
||||
case PIN_CONFIG_DRIVE_PUSH_PULL:
|
||||
return adp5585_gpio_set_drive(adp5585_gpio, off, param);
|
||||
|
||||
case PIN_CONFIG_INPUT_DEBOUNCE:
|
||||
return adp5585_gpio_set_debounce(adp5585_gpio, off, arg);
|
||||
|
||||
default:
|
||||
return -ENOTSUPP;
|
||||
};
|
||||
}
|
||||
|
||||
static int adp5585_gpio_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct adp5585_dev *adp5585 = dev_get_drvdata(pdev->dev.parent);
|
||||
struct adp5585_gpio_dev *adp5585_gpio;
|
||||
struct device *dev = &pdev->dev;
|
||||
struct gpio_chip *gc;
|
||||
int ret;
|
||||
|
||||
adp5585_gpio = devm_kzalloc(dev, sizeof(*adp5585_gpio), GFP_KERNEL);
|
||||
if (!adp5585_gpio)
|
||||
return -ENOMEM;
|
||||
|
||||
adp5585_gpio->regmap = adp5585->regmap;
|
||||
|
||||
device_set_of_node_from_dev(dev, dev->parent);
|
||||
|
||||
gc = &adp5585_gpio->gpio_chip;
|
||||
gc->parent = dev;
|
||||
gc->get_direction = adp5585_gpio_get_direction;
|
||||
gc->direction_input = adp5585_gpio_direction_input;
|
||||
gc->direction_output = adp5585_gpio_direction_output;
|
||||
gc->get = adp5585_gpio_get_value;
|
||||
gc->set = adp5585_gpio_set_value;
|
||||
gc->set_config = adp5585_gpio_set_config;
|
||||
gc->can_sleep = true;
|
||||
|
||||
gc->base = -1;
|
||||
gc->ngpio = ADP5585_GPIO_MAX;
|
||||
gc->label = pdev->name;
|
||||
gc->owner = THIS_MODULE;
|
||||
|
||||
ret = devm_gpiochip_add_data(dev, &adp5585_gpio->gpio_chip,
|
||||
adp5585_gpio);
|
||||
if (ret)
|
||||
return dev_err_probe(dev, ret, "failed to add GPIO chip\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct platform_device_id adp5585_gpio_id_table[] = {
|
||||
{ "adp5585-gpio" },
|
||||
{ /* Sentinel */ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(platform, adp5585_gpio_id_table);
|
||||
|
||||
static struct platform_driver adp5585_gpio_driver = {
|
||||
.driver = {
|
||||
.name = "adp5585-gpio",
|
||||
},
|
||||
.probe = adp5585_gpio_probe,
|
||||
.id_table = adp5585_gpio_id_table,
|
||||
};
|
||||
module_platform_driver(adp5585_gpio_driver);
|
||||
|
||||
MODULE_AUTHOR("Haibo Chen <haibo.chen@nxp.com>");
|
||||
MODULE_DESCRIPTION("GPIO ADP5585 Driver");
|
||||
MODULE_LICENSE("GPL");
|
@ -20,6 +20,18 @@ config MFD_CS5535
|
||||
This is the core driver for CS5535/CS5536 MFD functions. This is
|
||||
necessary for using the board's GPIO and MFGPT functionality.
|
||||
|
||||
config MFD_ADP5585
|
||||
tristate "Analog Devices ADP5585 keypad decoder and I/O expander driver"
|
||||
select MFD_CORE
|
||||
select REGMAP_I2C
|
||||
depends on I2C
|
||||
depends on OF || COMPILE_TEST
|
||||
help
|
||||
Say yes here to add support for the Analog Devices ADP5585 GPIO
|
||||
expander, PWM and keypad controller. This includes the I2C driver and
|
||||
the core APIs _only_, you have to select individual components like
|
||||
the GPIO and PWM functions under the corresponding menus.
|
||||
|
||||
config MFD_ALTERA_A10SR
|
||||
bool "Altera Arria10 DevKit System Resource chip"
|
||||
depends on ARCH_INTEL_SOCFPGA && SPI_MASTER=y && OF
|
||||
|
@ -193,6 +193,7 @@ obj-$(CONFIG_MFD_DB8500_PRCMU) += db8500-prcmu.o
|
||||
obj-$(CONFIG_AB8500_CORE) += ab8500-core.o ab8500-sysctrl.o
|
||||
obj-$(CONFIG_MFD_TIMBERDALE) += timberdale.o
|
||||
obj-$(CONFIG_PMIC_ADP5520) += adp5520.o
|
||||
obj-$(CONFIG_MFD_ADP5585) += adp5585.o
|
||||
obj-$(CONFIG_MFD_KEMPLD) += kempld-core.o
|
||||
obj-$(CONFIG_MFD_INTEL_QUARK_I2C_GPIO) += intel_quark_i2c_gpio.o
|
||||
obj-$(CONFIG_LPC_SCH) += lpc_sch.o
|
||||
|
205
drivers/mfd/adp5585.c
Normal file
205
drivers/mfd/adp5585.c
Normal file
@ -0,0 +1,205 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Analog Devices ADP5585 I/O expander, PWM controller and keypad controller
|
||||
*
|
||||
* Copyright 2022 NXP
|
||||
* Copyright 2024 Ideas on Board Oy
|
||||
*/
|
||||
|
||||
#include <linux/array_size.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/mfd/adp5585.h>
|
||||
#include <linux/mfd/core.h>
|
||||
#include <linux/mod_devicetable.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/types.h>
|
||||
|
||||
static const struct mfd_cell adp5585_devs[] = {
|
||||
{ .name = "adp5585-gpio", },
|
||||
{ .name = "adp5585-pwm", },
|
||||
};
|
||||
|
||||
static const struct regmap_range adp5585_volatile_ranges[] = {
|
||||
regmap_reg_range(ADP5585_ID, ADP5585_GPI_STATUS_B),
|
||||
};
|
||||
|
||||
static const struct regmap_access_table adp5585_volatile_regs = {
|
||||
.yes_ranges = adp5585_volatile_ranges,
|
||||
.n_yes_ranges = ARRAY_SIZE(adp5585_volatile_ranges),
|
||||
};
|
||||
|
||||
/*
|
||||
* Chip variants differ in the default configuration of pull-up and pull-down
|
||||
* resistors, and therefore have different default register values:
|
||||
*
|
||||
* - The -00, -01 and -03 variants (collectively referred to as
|
||||
* ADP5585_REGMAP_00) have pull-up on all GPIO pins by default.
|
||||
* - The -02 variant has no default pull-up or pull-down resistors.
|
||||
* - The -04 variant has default pull-down resistors on all GPIO pins.
|
||||
*/
|
||||
|
||||
static const u8 adp5585_regmap_defaults_00[ADP5585_MAX_REG + 1] = {
|
||||
/* 0x00 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
/* 0x08 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
/* 0x10 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
/* 0x18 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
/* 0x20 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
/* 0x28 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
/* 0x30 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
/* 0x38 */ 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
};
|
||||
|
||||
static const u8 adp5585_regmap_defaults_02[ADP5585_MAX_REG + 1] = {
|
||||
/* 0x00 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
/* 0x08 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
/* 0x10 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3,
|
||||
/* 0x18 */ 0x03, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
/* 0x20 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
/* 0x28 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
/* 0x30 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
/* 0x38 */ 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
};
|
||||
|
||||
static const u8 adp5585_regmap_defaults_04[ADP5585_MAX_REG + 1] = {
|
||||
/* 0x00 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
/* 0x08 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
/* 0x10 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55,
|
||||
/* 0x18 */ 0x05, 0x55, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
/* 0x20 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
/* 0x28 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
/* 0x30 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
/* 0x38 */ 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
};
|
||||
|
||||
enum adp5585_regmap_type {
|
||||
ADP5585_REGMAP_00,
|
||||
ADP5585_REGMAP_02,
|
||||
ADP5585_REGMAP_04,
|
||||
};
|
||||
|
||||
static const struct regmap_config adp5585_regmap_configs[] = {
|
||||
[ADP5585_REGMAP_00] = {
|
||||
.reg_bits = 8,
|
||||
.val_bits = 8,
|
||||
.max_register = ADP5585_MAX_REG,
|
||||
.volatile_table = &adp5585_volatile_regs,
|
||||
.cache_type = REGCACHE_MAPLE,
|
||||
.reg_defaults_raw = adp5585_regmap_defaults_00,
|
||||
.num_reg_defaults_raw = sizeof(adp5585_regmap_defaults_00),
|
||||
},
|
||||
[ADP5585_REGMAP_02] = {
|
||||
.reg_bits = 8,
|
||||
.val_bits = 8,
|
||||
.max_register = ADP5585_MAX_REG,
|
||||
.volatile_table = &adp5585_volatile_regs,
|
||||
.cache_type = REGCACHE_MAPLE,
|
||||
.reg_defaults_raw = adp5585_regmap_defaults_02,
|
||||
.num_reg_defaults_raw = sizeof(adp5585_regmap_defaults_02),
|
||||
},
|
||||
[ADP5585_REGMAP_04] = {
|
||||
.reg_bits = 8,
|
||||
.val_bits = 8,
|
||||
.max_register = ADP5585_MAX_REG,
|
||||
.volatile_table = &adp5585_volatile_regs,
|
||||
.cache_type = REGCACHE_MAPLE,
|
||||
.reg_defaults_raw = adp5585_regmap_defaults_04,
|
||||
.num_reg_defaults_raw = sizeof(adp5585_regmap_defaults_04),
|
||||
},
|
||||
};
|
||||
|
||||
static int adp5585_i2c_probe(struct i2c_client *i2c)
|
||||
{
|
||||
const struct regmap_config *regmap_config;
|
||||
struct adp5585_dev *adp5585;
|
||||
unsigned int id;
|
||||
int ret;
|
||||
|
||||
adp5585 = devm_kzalloc(&i2c->dev, sizeof(*adp5585), GFP_KERNEL);
|
||||
if (!adp5585)
|
||||
return -ENOMEM;
|
||||
|
||||
i2c_set_clientdata(i2c, adp5585);
|
||||
|
||||
regmap_config = i2c_get_match_data(i2c);
|
||||
adp5585->regmap = devm_regmap_init_i2c(i2c, regmap_config);
|
||||
if (IS_ERR(adp5585->regmap))
|
||||
return dev_err_probe(&i2c->dev, PTR_ERR(adp5585->regmap),
|
||||
"Failed to initialize register map\n");
|
||||
|
||||
ret = regmap_read(adp5585->regmap, ADP5585_ID, &id);
|
||||
if (ret)
|
||||
return dev_err_probe(&i2c->dev, ret,
|
||||
"Failed to read device ID\n");
|
||||
|
||||
if ((id & ADP5585_MAN_ID_MASK) != ADP5585_MAN_ID_VALUE)
|
||||
return dev_err_probe(&i2c->dev, -ENODEV,
|
||||
"Invalid device ID 0x%02x\n", id);
|
||||
|
||||
ret = devm_mfd_add_devices(&i2c->dev, PLATFORM_DEVID_AUTO,
|
||||
adp5585_devs, ARRAY_SIZE(adp5585_devs),
|
||||
NULL, 0, NULL);
|
||||
if (ret)
|
||||
return dev_err_probe(&i2c->dev, ret,
|
||||
"Failed to add child devices\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int adp5585_suspend(struct device *dev)
|
||||
{
|
||||
struct adp5585_dev *adp5585 = dev_get_drvdata(dev);
|
||||
|
||||
regcache_cache_only(adp5585->regmap, true);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int adp5585_resume(struct device *dev)
|
||||
{
|
||||
struct adp5585_dev *adp5585 = dev_get_drvdata(dev);
|
||||
|
||||
regcache_cache_only(adp5585->regmap, false);
|
||||
regcache_mark_dirty(adp5585->regmap);
|
||||
|
||||
return regcache_sync(adp5585->regmap);
|
||||
}
|
||||
|
||||
static DEFINE_SIMPLE_DEV_PM_OPS(adp5585_pm, adp5585_suspend, adp5585_resume);
|
||||
|
||||
static const struct of_device_id adp5585_of_match[] = {
|
||||
{
|
||||
.compatible = "adi,adp5585-00",
|
||||
.data = &adp5585_regmap_configs[ADP5585_REGMAP_00],
|
||||
}, {
|
||||
.compatible = "adi,adp5585-01",
|
||||
.data = &adp5585_regmap_configs[ADP5585_REGMAP_00],
|
||||
}, {
|
||||
.compatible = "adi,adp5585-02",
|
||||
.data = &adp5585_regmap_configs[ADP5585_REGMAP_02],
|
||||
}, {
|
||||
.compatible = "adi,adp5585-03",
|
||||
.data = &adp5585_regmap_configs[ADP5585_REGMAP_00],
|
||||
}, {
|
||||
.compatible = "adi,adp5585-04",
|
||||
.data = &adp5585_regmap_configs[ADP5585_REGMAP_04],
|
||||
},
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, adp5585_of_match);
|
||||
|
||||
static struct i2c_driver adp5585_i2c_driver = {
|
||||
.driver = {
|
||||
.name = "adp5585",
|
||||
.of_match_table = adp5585_of_match,
|
||||
.pm = pm_sleep_ptr(&adp5585_pm),
|
||||
},
|
||||
.probe = adp5585_i2c_probe,
|
||||
};
|
||||
module_i2c_driver(adp5585_i2c_driver);
|
||||
|
||||
MODULE_DESCRIPTION("ADP5585 core driver");
|
||||
MODULE_AUTHOR("Haibo Chen <haibo.chen@nxp.com>");
|
||||
MODULE_LICENSE("GPL");
|
@ -47,6 +47,13 @@ config PWM_AB8500
|
||||
To compile this driver as a module, choose M here: the module
|
||||
will be called pwm-ab8500.
|
||||
|
||||
config PWM_ADP5585
|
||||
tristate "ADP5585 PWM support"
|
||||
depends on MFD_ADP5585
|
||||
help
|
||||
This option enables support for the PWM function found in the Analog
|
||||
Devices ADP5585.
|
||||
|
||||
config PWM_APPLE
|
||||
tristate "Apple SoC PWM support"
|
||||
depends on ARCH_APPLE || COMPILE_TEST
|
||||
|
@ -1,6 +1,7 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
obj-$(CONFIG_PWM) += core.o
|
||||
obj-$(CONFIG_PWM_AB8500) += pwm-ab8500.o
|
||||
obj-$(CONFIG_PWM_ADP5585) += pwm-adp5585.o
|
||||
obj-$(CONFIG_PWM_APPLE) += pwm-apple.o
|
||||
obj-$(CONFIG_PWM_ATMEL) += pwm-atmel.o
|
||||
obj-$(CONFIG_PWM_ATMEL_HLCDC_PWM) += pwm-atmel-hlcdc.o
|
||||
|
184
drivers/pwm/pwm-adp5585.c
Normal file
184
drivers/pwm/pwm-adp5585.c
Normal file
@ -0,0 +1,184 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Analog Devices ADP5585 PWM driver
|
||||
*
|
||||
* Copyright 2022 NXP
|
||||
* Copyright 2024 Ideas on Board Oy
|
||||
*
|
||||
* Limitations:
|
||||
* - The .apply() operation executes atomically, but may not wait for the
|
||||
* period to complete (this is not documented and would need to be tested).
|
||||
* - Disabling the PWM drives the output pin to a low level immediately.
|
||||
* - The hardware can only generate normal polarity output.
|
||||
*/
|
||||
|
||||
#include <asm/byteorder.h>
|
||||
|
||||
#include <linux/device.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/math64.h>
|
||||
#include <linux/mfd/adp5585.h>
|
||||
#include <linux/minmax.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/pwm.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/time.h>
|
||||
#include <linux/types.h>
|
||||
|
||||
#define ADP5585_PWM_CHAN_NUM 1
|
||||
|
||||
#define ADP5585_PWM_OSC_FREQ_HZ 1000000U
|
||||
#define ADP5585_PWM_MIN_PERIOD_NS (2ULL * NSEC_PER_SEC / ADP5585_PWM_OSC_FREQ_HZ)
|
||||
#define ADP5585_PWM_MAX_PERIOD_NS (2ULL * 0xffff * NSEC_PER_SEC / ADP5585_PWM_OSC_FREQ_HZ)
|
||||
|
||||
static int pwm_adp5585_request(struct pwm_chip *chip, struct pwm_device *pwm)
|
||||
{
|
||||
struct regmap *regmap = pwmchip_get_drvdata(chip);
|
||||
|
||||
/* Configure the R3 pin as PWM output. */
|
||||
return regmap_update_bits(regmap, ADP5585_PIN_CONFIG_C,
|
||||
ADP5585_R3_EXTEND_CFG_MASK,
|
||||
ADP5585_R3_EXTEND_CFG_PWM_OUT);
|
||||
}
|
||||
|
||||
static void pwm_adp5585_free(struct pwm_chip *chip, struct pwm_device *pwm)
|
||||
{
|
||||
struct regmap *regmap = pwmchip_get_drvdata(chip);
|
||||
|
||||
regmap_update_bits(regmap, ADP5585_PIN_CONFIG_C,
|
||||
ADP5585_R3_EXTEND_CFG_MASK,
|
||||
ADP5585_R3_EXTEND_CFG_GPIO4);
|
||||
}
|
||||
|
||||
static int pwm_adp5585_apply(struct pwm_chip *chip,
|
||||
struct pwm_device *pwm,
|
||||
const struct pwm_state *state)
|
||||
{
|
||||
struct regmap *regmap = pwmchip_get_drvdata(chip);
|
||||
u64 period, duty_cycle;
|
||||
u32 on, off;
|
||||
__le16 val;
|
||||
int ret;
|
||||
|
||||
if (!state->enabled) {
|
||||
regmap_clear_bits(regmap, ADP5585_GENERAL_CFG, ADP5585_OSC_EN);
|
||||
regmap_clear_bits(regmap, ADP5585_PWM_CFG, ADP5585_PWM_EN);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (state->polarity != PWM_POLARITY_NORMAL)
|
||||
return -EINVAL;
|
||||
|
||||
if (state->period < ADP5585_PWM_MIN_PERIOD_NS)
|
||||
return -EINVAL;
|
||||
|
||||
period = min(state->period, ADP5585_PWM_MAX_PERIOD_NS);
|
||||
duty_cycle = min(state->duty_cycle, period);
|
||||
|
||||
/*
|
||||
* Compute the on and off time. As the internal oscillator frequency is
|
||||
* 1MHz, the calculation can be simplified without loss of precision.
|
||||
*/
|
||||
on = div_u64(duty_cycle, NSEC_PER_SEC / ADP5585_PWM_OSC_FREQ_HZ);
|
||||
off = div_u64(period, NSEC_PER_SEC / ADP5585_PWM_OSC_FREQ_HZ) - on;
|
||||
|
||||
val = cpu_to_le16(off);
|
||||
ret = regmap_bulk_write(regmap, ADP5585_PWM_OFFT_LOW, &val, 2);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
val = cpu_to_le16(on);
|
||||
ret = regmap_bulk_write(regmap, ADP5585_PWM_ONT_LOW, &val, 2);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Enable PWM in continuous mode and no external AND'ing. */
|
||||
ret = regmap_update_bits(regmap, ADP5585_PWM_CFG,
|
||||
ADP5585_PWM_IN_AND | ADP5585_PWM_MODE |
|
||||
ADP5585_PWM_EN, ADP5585_PWM_EN);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return regmap_set_bits(regmap, ADP5585_PWM_CFG, ADP5585_PWM_EN);
|
||||
}
|
||||
|
||||
static int pwm_adp5585_get_state(struct pwm_chip *chip,
|
||||
struct pwm_device *pwm,
|
||||
struct pwm_state *state)
|
||||
{
|
||||
struct regmap *regmap = pwmchip_get_drvdata(chip);
|
||||
unsigned int on, off;
|
||||
unsigned int val;
|
||||
__le16 on_off;
|
||||
int ret;
|
||||
|
||||
ret = regmap_bulk_read(regmap, ADP5585_PWM_OFFT_LOW, &on_off, 2);
|
||||
if (ret)
|
||||
return ret;
|
||||
off = le16_to_cpu(on_off);
|
||||
|
||||
ret = regmap_bulk_read(regmap, ADP5585_PWM_ONT_LOW, &on_off, 2);
|
||||
if (ret)
|
||||
return ret;
|
||||
on = le16_to_cpu(on_off);
|
||||
|
||||
state->duty_cycle = on * (NSEC_PER_SEC / ADP5585_PWM_OSC_FREQ_HZ);
|
||||
state->period = (on + off) * (NSEC_PER_SEC / ADP5585_PWM_OSC_FREQ_HZ);
|
||||
|
||||
state->polarity = PWM_POLARITY_NORMAL;
|
||||
|
||||
regmap_read(regmap, ADP5585_PWM_CFG, &val);
|
||||
state->enabled = !!(val & ADP5585_PWM_EN);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct pwm_ops adp5585_pwm_ops = {
|
||||
.request = pwm_adp5585_request,
|
||||
.free = pwm_adp5585_free,
|
||||
.apply = pwm_adp5585_apply,
|
||||
.get_state = pwm_adp5585_get_state,
|
||||
};
|
||||
|
||||
static int adp5585_pwm_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
struct adp5585_dev *adp5585 = dev_get_drvdata(dev->parent);
|
||||
struct pwm_chip *chip;
|
||||
int ret;
|
||||
|
||||
chip = devm_pwmchip_alloc(dev, ADP5585_PWM_CHAN_NUM, 0);
|
||||
if (IS_ERR(chip))
|
||||
return PTR_ERR(chip);
|
||||
|
||||
device_set_of_node_from_dev(dev, dev->parent);
|
||||
|
||||
pwmchip_set_drvdata(chip, adp5585->regmap);
|
||||
chip->ops = &adp5585_pwm_ops;
|
||||
|
||||
ret = devm_pwmchip_add(dev, chip);
|
||||
if (ret)
|
||||
return dev_err_probe(dev, ret, "failed to add PWM chip\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct platform_device_id adp5585_pwm_id_table[] = {
|
||||
{ "adp5585-pwm" },
|
||||
{ /* Sentinel */ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(platform, adp5585_pwm_id_table);
|
||||
|
||||
static struct platform_driver adp5585_pwm_driver = {
|
||||
.driver = {
|
||||
.name = "adp5585-pwm",
|
||||
},
|
||||
.probe = adp5585_pwm_probe,
|
||||
.id_table = adp5585_pwm_id_table,
|
||||
};
|
||||
module_platform_driver(adp5585_pwm_driver);
|
||||
|
||||
MODULE_AUTHOR("Xiaoning Wang <xiaoning.wang@nxp.com>");
|
||||
MODULE_DESCRIPTION("ADP5585 PWM Driver");
|
||||
MODULE_LICENSE("GPL");
|
126
include/linux/mfd/adp5585.h
Normal file
126
include/linux/mfd/adp5585.h
Normal file
@ -0,0 +1,126 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Analog Devices ADP5585 I/O expander, PWM controller and keypad controller
|
||||
*
|
||||
* Copyright 2022 NXP
|
||||
* Copyright 2024 Ideas on Board Oy
|
||||
*/
|
||||
|
||||
#ifndef __MFD_ADP5585_H_
|
||||
#define __MFD_ADP5585_H_
|
||||
|
||||
#include <linux/bits.h>
|
||||
|
||||
#define ADP5585_ID 0x00
|
||||
#define ADP5585_MAN_ID_VALUE 0x20
|
||||
#define ADP5585_MAN_ID_MASK GENMASK(7, 4)
|
||||
#define ADP5585_INT_STATUS 0x01
|
||||
#define ADP5585_STATUS 0x02
|
||||
#define ADP5585_FIFO_1 0x03
|
||||
#define ADP5585_FIFO_2 0x04
|
||||
#define ADP5585_FIFO_3 0x05
|
||||
#define ADP5585_FIFO_4 0x06
|
||||
#define ADP5585_FIFO_5 0x07
|
||||
#define ADP5585_FIFO_6 0x08
|
||||
#define ADP5585_FIFO_7 0x09
|
||||
#define ADP5585_FIFO_8 0x0a
|
||||
#define ADP5585_FIFO_9 0x0b
|
||||
#define ADP5585_FIFO_10 0x0c
|
||||
#define ADP5585_FIFO_11 0x0d
|
||||
#define ADP5585_FIFO_12 0x0e
|
||||
#define ADP5585_FIFO_13 0x0f
|
||||
#define ADP5585_FIFO_14 0x10
|
||||
#define ADP5585_FIFO_15 0x11
|
||||
#define ADP5585_FIFO_16 0x12
|
||||
#define ADP5585_GPI_INT_STAT_A 0x13
|
||||
#define ADP5585_GPI_INT_STAT_B 0x14
|
||||
#define ADP5585_GPI_STATUS_A 0x15
|
||||
#define ADP5585_GPI_STATUS_B 0x16
|
||||
#define ADP5585_RPULL_CONFIG_A 0x17
|
||||
#define ADP5585_RPULL_CONFIG_B 0x18
|
||||
#define ADP5585_RPULL_CONFIG_C 0x19
|
||||
#define ADP5585_RPULL_CONFIG_D 0x1a
|
||||
#define ADP5585_Rx_PULL_CFG_PU_300K 0
|
||||
#define ADP5585_Rx_PULL_CFG_PD_300K 1
|
||||
#define ADP5585_Rx_PULL_CFG_PU_100K 2
|
||||
#define ADP5585_Rx_PULL_CFG_DISABLE 3
|
||||
#define ADP5585_Rx_PULL_CFG_MASK 3
|
||||
#define ADP5585_GPI_INT_LEVEL_A 0x1b
|
||||
#define ADP5585_GPI_INT_LEVEL_B 0x1c
|
||||
#define ADP5585_GPI_EVENT_EN_A 0x1d
|
||||
#define ADP5585_GPI_EVENT_EN_B 0x1e
|
||||
#define ADP5585_GPI_INTERRUPT_EN_A 0x1f
|
||||
#define ADP5585_GPI_INTERRUPT_EN_B 0x20
|
||||
#define ADP5585_DEBOUNCE_DIS_A 0x21
|
||||
#define ADP5585_DEBOUNCE_DIS_B 0x22
|
||||
#define ADP5585_GPO_DATA_OUT_A 0x23
|
||||
#define ADP5585_GPO_DATA_OUT_B 0x24
|
||||
#define ADP5585_GPO_OUT_MODE_A 0x25
|
||||
#define ADP5585_GPO_OUT_MODE_B 0x26
|
||||
#define ADP5585_GPIO_DIRECTION_A 0x27
|
||||
#define ADP5585_GPIO_DIRECTION_B 0x28
|
||||
#define ADP5585_RESET1_EVENT_A 0x29
|
||||
#define ADP5585_RESET1_EVENT_B 0x2a
|
||||
#define ADP5585_RESET1_EVENT_C 0x2b
|
||||
#define ADP5585_RESET2_EVENT_A 0x2c
|
||||
#define ADP5585_RESET2_EVENT_B 0x2d
|
||||
#define ADP5585_RESET_CFG 0x2e
|
||||
#define ADP5585_PWM_OFFT_LOW 0x2f
|
||||
#define ADP5585_PWM_OFFT_HIGH 0x30
|
||||
#define ADP5585_PWM_ONT_LOW 0x31
|
||||
#define ADP5585_PWM_ONT_HIGH 0x32
|
||||
#define ADP5585_PWM_CFG 0x33
|
||||
#define ADP5585_PWM_IN_AND BIT(2)
|
||||
#define ADP5585_PWM_MODE BIT(1)
|
||||
#define ADP5585_PWM_EN BIT(0)
|
||||
#define ADP5585_LOGIC_CFG 0x34
|
||||
#define ADP5585_LOGIC_FF_CFG 0x35
|
||||
#define ADP5585_LOGIC_INT_EVENT_EN 0x36
|
||||
#define ADP5585_POLL_PTIME_CFG 0x37
|
||||
#define ADP5585_PIN_CONFIG_A 0x38
|
||||
#define ADP5585_PIN_CONFIG_B 0x39
|
||||
#define ADP5585_PIN_CONFIG_C 0x3a
|
||||
#define ADP5585_PULL_SELECT BIT(7)
|
||||
#define ADP5585_C4_EXTEND_CFG_GPIO11 (0U << 6)
|
||||
#define ADP5585_C4_EXTEND_CFG_RESET2 (1U << 6)
|
||||
#define ADP5585_C4_EXTEND_CFG_MASK GENMASK(6, 6)
|
||||
#define ADP5585_R4_EXTEND_CFG_GPIO5 (0U << 5)
|
||||
#define ADP5585_R4_EXTEND_CFG_RESET1 (1U << 5)
|
||||
#define ADP5585_R4_EXTEND_CFG_MASK GENMASK(5, 5)
|
||||
#define ADP5585_R3_EXTEND_CFG_GPIO4 (0U << 2)
|
||||
#define ADP5585_R3_EXTEND_CFG_LC (1U << 2)
|
||||
#define ADP5585_R3_EXTEND_CFG_PWM_OUT (2U << 2)
|
||||
#define ADP5585_R3_EXTEND_CFG_MASK GENMASK(3, 2)
|
||||
#define ADP5585_R0_EXTEND_CFG_GPIO1 (0U << 0)
|
||||
#define ADP5585_R0_EXTEND_CFG_LY (1U << 0)
|
||||
#define ADP5585_R0_EXTEND_CFG_MASK GENMASK(0, 0)
|
||||
#define ADP5585_GENERAL_CFG 0x3b
|
||||
#define ADP5585_OSC_EN BIT(7)
|
||||
#define ADP5585_OSC_FREQ_50KHZ (0U << 5)
|
||||
#define ADP5585_OSC_FREQ_100KHZ (1U << 5)
|
||||
#define ADP5585_OSC_FREQ_200KHZ (2U << 5)
|
||||
#define ADP5585_OSC_FREQ_500KHZ (3U << 5)
|
||||
#define ADP5585_OSC_FREQ_MASK GENMASK(6, 5)
|
||||
#define ADP5585_INT_CFG BIT(1)
|
||||
#define ADP5585_RST_CFG BIT(0)
|
||||
#define ADP5585_INT_EN 0x3c
|
||||
|
||||
#define ADP5585_MAX_REG ADP5585_INT_EN
|
||||
|
||||
/*
|
||||
* Bank 0 covers pins "GPIO 1/R0" to "GPIO 6/R5", numbered 0 to 5 by the
|
||||
* driver, and bank 1 covers pins "GPIO 7/C0" to "GPIO 11/C4", numbered 6 to
|
||||
* 10. Some variants of the ADP5585 don't support "GPIO 6/R5". As the driver
|
||||
* uses identical GPIO numbering for all variants to avoid confusion, GPIO 5 is
|
||||
* marked as reserved in the device tree for variants that don't support it.
|
||||
*/
|
||||
#define ADP5585_BANK(n) ((n) >= 6 ? 1 : 0)
|
||||
#define ADP5585_BIT(n) ((n) >= 6 ? BIT((n) - 6) : BIT(n))
|
||||
|
||||
struct regmap;
|
||||
|
||||
struct adp5585_dev {
|
||||
struct regmap *regmap;
|
||||
};
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue
Block a user