Merge branches 'ib-mfd-gpio-i2c-3.19', 'ib-mfd-iio-3.19' and 'ib-mfd-regulator-v3...
authorLee Jones <lee.jones@linaro.org>
Tue, 25 Nov 2014 16:18:03 +0000 (16:18 +0000)
committerLee Jones <lee.jones@linaro.org>
Tue, 25 Nov 2014 16:18:03 +0000 (16:18 +0000)
Immutable branch between MFD, Regulator and Clk, due for v3.19

1  2  3  4  5 
drivers/iio/adc/Kconfig
drivers/iio/adc/Makefile
drivers/mfd/Kconfig
drivers/mfd/axp20x.c

diff --combined drivers/iio/adc/Kconfig
@@@@@@ -127,9 -127,9 -127,17 -127,9 -127,9 +127,17 @@@@@@ config AT91_AD
        help
          Say yes here to build support for Atmel AT91 ADC.
     
++ ++config AXP288_ADC
++ ++   tristate "X-Powers AXP288 ADC driver"
++ ++   depends on MFD_AXP20X
++ ++   help
++ ++     Say yes here to have support for X-Powers power management IC (PMIC) ADC
++ ++     device. Depending on platform configuration, this general purpose ADC can
++ ++     be used for sampling sensors such as thermal resistors.
++ ++
     config EXYNOS_ADC
        tristate "Exynos ADC driver support"
  -     depends on ARCH_EXYNOS || (OF && COMPILE_TEST)
  +     depends on ARCH_EXYNOS || ARCH_S3C24XX || ARCH_S3C64XX || (OF && COMPILE_TEST)
        help
          Core support for the ADC block found in the Samsung EXYNOS series
          of SoCs for drivers such as the touchscreen and hwmon to use to share
@@@@@@ -206,16 -206,16 -214,6 -206,16 -206,16 +214,16 @@@@@@ config NAU780
          To compile this driver as a module, choose M here: the
          module will be called nau7802.
     
  +  config ROCKCHIP_SARADC
  +     tristate "Rockchip SARADC driver"
  +     depends on ARCH_ROCKCHIP || (ARM && COMPILE_TEST)
  +     help
  +       Say yes here to build support for the SARADC found in SoCs from
  +       Rockchip.
  +  
  +       To compile this driver as a module, choose M here: the
  +       module will be called rockchip_saradc.
  +  
     config TI_ADC081C
        tristate "Texas Instruments ADC081C021/027"
        depends on I2C
          This driver can also be built as a module. If so, the module will be
          called ti-adc081c.
     
  +  config TI_ADC128S052
  +     tristate "Texas Instruments ADC128S052"
  +     depends on SPI
  +     help
  +       If you say yes here you get support for Texas Instruments ADC128S052
  +       chip.
  +  
  +       This driver can also be built as a module. If so, the module will be
  +       called ti-adc128s052.
  +  
     config TI_AM335X_ADC
        tristate "TI's AM335X ADC driver"
        depends on MFD_TI_AM335X_TSCADC
diff --combined drivers/iio/adc/Makefile
@@@@@@ -14,6 -14,6 -14,7 -14,6 -14,6 +14,7 @@@@@@ obj-$(CONFIG_AD7793) += ad7793.
     obj-$(CONFIG_AD7887) += ad7887.o
     obj-$(CONFIG_AD799X) += ad799x.o
     obj-$(CONFIG_AT91_ADC) += at91_adc.o
++ ++obj-$(CONFIG_AXP288_ADC) += axp288_adc.o
     obj-$(CONFIG_EXYNOS_ADC) += exynos_adc.o
     obj-$(CONFIG_LP8788_ADC) += lp8788_adc.o
     obj-$(CONFIG_MAX1027) += max1027.o
@@@@@@ -22,9 -22,9 -23,7 -22,9 -22,9 +23,9 @@@@@@ obj-$(CONFIG_MCP320X) += mcp320x.
     obj-$(CONFIG_MCP3422) += mcp3422.o
     obj-$(CONFIG_MEN_Z188_ADC) += men_z188_adc.o
     obj-$(CONFIG_NAU7802) += nau7802.o
  +  obj-$(CONFIG_ROCKCHIP_SARADC) += rockchip_saradc.o
     obj-$(CONFIG_TI_ADC081C) += ti-adc081c.o
  +  obj-$(CONFIG_TI_ADC128S052) += ti-adc128s052.o
     obj-$(CONFIG_TI_AM335X_ADC) += ti_am335x_adc.o
     obj-$(CONFIG_TWL4030_MADC) += twl4030-madc.o
     obj-$(CONFIG_TWL6030_GPADC) += twl6030-gpadc.o
diff --combined drivers/mfd/Kconfig
@@@@@@ -74,7 -74,7 -74,8 -74,7 -74,7 +74,8 @@@@@@ config MFD_AXP20
        select REGMAP_IRQ
        depends on I2C=y
        help
-- --     If you say Y here you get support for the X-Powers AXP202 and AXP209.
++ ++     If you say Y here you get support for the X-Powers AXP202, AXP209 and
++ ++     AXP288 power management IC (PMIC).
          This driver include only the core APIs. You have to select individual
          components like regulators or the PEK (Power Enable Key) under the
          corresponding menus.
@@@@@@ -183,6 -183,16 -184,6 -183,6 -183,6 +184,16 @@@@@@ config MFD_DA906
          Additional drivers must be enabled in order to use the functionality
          of the device.
     
+ +++config MFD_DLN2
+ +++   tristate "Diolan DLN2 support"
+ +++   select MFD_CORE
+ +++   depends on USB
+ +++   help
+ +++     This adds support for Diolan USB-I2C/SPI/GPIO Master Adapter
+ +++     DLN-2. Additional drivers such as I2C_DLN2, GPIO_DLN2,
+ +++     etc. must be enabled in order to use the functionality of
+ +++     the device.
+ +++
     config MFD_MC13XXX
        tristate
        depends on (SPI_MASTER || I2C)
@@@@@@ -210,19 -220,19 -211,6 -210,19 -210,19 +221,19 @@@@@@ config MFD_MC13XXX_I2
        help
          Select this if your MC13xxx is connected via an I2C bus.
     
  +  config MFD_HI6421_PMIC
  +     tristate "HiSilicon Hi6421 PMU/Codec IC"
  +     depends on OF
  +     select MFD_CORE
  +     select REGMAP_MMIO
  +     help
  +       Add support for HiSilicon Hi6421 PMIC. Hi6421 includes multi-
  +       functions, such as regulators, RTC, codec, Coulomb counter, etc.
  +       This driver includes core APIs _only_. You have to select
  +       individul components like voltage regulators under corresponding
  +       menus in order to enable them.
  +       We communicate with the Hi6421 via memory-mapped I/O.
  +  
     config HTC_EGPIO
        bool "HTC EGPIO support"
        depends on GPIOLIB && ARM
@@@@@@ -467,21 -477,21 -455,6 -467,21 -467,21 +478,21 @@@@@@ config MFD_MAX899
          additional drivers must be enabled in order to use the functionality
          of the device.
     
  +  config MFD_MENF21BMC
  +     tristate "MEN 14F021P00 Board Management Controller Support"
  +     depends on I2C
  +     select MFD_CORE
  +     help
  +       Say yes here to add support for the MEN 14F021P00 BMC
  +       which is a Board Management Controller connected to the I2C bus.
  +       The device supports multiple sub-devices like LED, HWMON and WDT.
  +       This driver provides common support for accessing the devices;
  +       additional drivers must be enabled in order to use the
  +       functionality of the BMC device.
  +  
  +       This driver can also be built as a module. If so the module
  +       will be called menf21bmc.
  +  
     config EZX_PCAP
        bool "Motorola EZXPCAP Support"
        depends on SPI_MASTER
@@@@@@ -567,21 -577,21 -540,6 -567,21 -567,21 +578,21 @@@@@@ config MFD_PM8921_COR
          Say M here if you want to include support for PM8921 chip as a module.
          This will build a module called "pm8921-core".
     
  +  config MFD_SPMI_PMIC
  +     tristate "Qualcomm SPMI PMICs"
  +     depends on ARCH_QCOM || COMPILE_TEST
  +     depends on OF
  +     depends on SPMI
  +     select REGMAP_SPMI
  +     help
  +       This enables support for the Qualcomm SPMI PMICs.
  +       These PMICs are currently used with the Snapdragon 800 series of
  +       SoCs.  Note, that this will only be useful paired with descriptions
  +       of the independent functions as children nodes in the device tree.
  +  
  +       Say M here if you want to include support for the SPMI PMIC
  +       series as a module.  The module will be called "qcom-spmi-pmic".
  +  
     config MFD_RDC321X
        tristate "RDC R-321x southbridge"
        select MFD_CORE
@@@@@@ -625,30 -635,30 -583,6 -625,30 -625,30 +636,30 @@@@@@ config MFD_RC5T58
          Additional drivers must be enabled in order to use the
          different functionality of the device.
     
  +  config MFD_RK808
  +     tristate "Rockchip RK808 Power Management chip"
  +     depends on I2C && OF
  +     select MFD_CORE
  +     select REGMAP_I2C
  +     select REGMAP_IRQ
  +     help
  +       If you say yes here you get support for the RK808
  +       Power Management chips.
  +       This driver provides common support for accessing the device
  +       through I2C interface. The device supports multiple sub-devices
  +       including interrupts, RTC, LDO & DCDC regulators, and onkey.
  +  
  +  config MFD_RN5T618
  +     tristate "Ricoh RN5T5618 PMIC"
  +     depends on I2C
  +     select MFD_CORE
  +     select REGMAP_I2C
  +     help
  +       Say yes here to add support for the Ricoh RN5T618 PMIC. This
  +       driver provides common support for accessing the device,
  +       additional drivers must be enabled in order to use the
  +       functionality of the device.
  +  
     config MFD_SEC_CORE
        bool "SAMSUNG Electronics PMIC Series Support"
        depends on I2C=y
@@@@@@ -1295,11 -1305,11 -1229,11 -1295,11 -1295,11 +1306,11 @@@@@@ config MFD_WM8350_I2
          selected to enable support for the functionality of the chip.
     
     config MFD_WM8994
  -     bool "Wolfson Microelectronics WM8994"
  +     tristate "Wolfson Microelectronics WM8994"
        select MFD_CORE
        select REGMAP_I2C
        select REGMAP_IRQ
  -     depends on I2C=y
  +     depends on I2C
        help
          The WM8994 is a highly integrated hi-fi CODEC designed for
          smartphone applicatiosn.  As well as audio functionality it
diff --combined drivers/mfd/axp20x.c
@@@@@@ -1,9 -1,9 -1,9 -1,9 -1,9 +1,9 @@@@@@
     /*
-- -- * axp20x.c - MFD core driver for the X-Powers AXP202 and AXP209
++ ++ * axp20x.c - MFD core driver for the X-Powers' Power Management ICs
      *
-- -- * AXP20x comprises an adaptive USB-Compatible PWM charger, 2 BUCK DC-DC
-- -- * converters, LDOs, multiple 12-bit ADCs of voltage, current and temperature
-- -- * as well as configurable GPIOs.
++ ++ * AXP20x typically comprises an adaptive USB-Compatible PWM charger, BUCK DC-DC
++ ++ * converters, LDOs, multiple 12-bit ADCs of voltage, current and temperature
++ ++ * as well as configurable GPIOs.
      *
      * Author: Carlo Caione <carlo@caione.org>
      *
     #include <linux/mfd/core.h>
     #include <linux/of_device.h>
     #include <linux/of_irq.h>
++ ++#include <linux/acpi.h>
     
     #define AXP20X_OFF 0x80
     
++ ++static const char const *axp20x_model_names[] = {
++ ++   "AXP202",
++ ++   "AXP209",
++ ++   "AXP288",
++ ++};
++ ++
     static const struct regmap_range axp20x_writeable_ranges[] = {
        regmap_reg_range(AXP20X_DATACACHE(0), AXP20X_IRQ5_STATE),
        regmap_reg_range(AXP20X_DCDC_MODE, AXP20X_FG_RES),
@@@@@@ -47,6 -47,6 -54,25 -47,6 -47,6 +54,25 @@@@@@ static const struct regmap_access_tabl
        .n_yes_ranges   = ARRAY_SIZE(axp20x_volatile_ranges),
     };
     
++ ++static const struct regmap_range axp288_writeable_ranges[] = {
++ ++   regmap_reg_range(AXP20X_DATACACHE(0), AXP20X_IRQ6_STATE),
++ ++   regmap_reg_range(AXP20X_DCDC_MODE, AXP288_FG_TUNE5),
++ ++};
++ ++
++ ++static const struct regmap_range axp288_volatile_ranges[] = {
++ ++   regmap_reg_range(AXP20X_IRQ1_EN, AXP20X_IPSOUT_V_HIGH_L),
++ ++};
++ ++
++ ++static const struct regmap_access_table axp288_writeable_table = {
++ ++   .yes_ranges     = axp288_writeable_ranges,
++ ++   .n_yes_ranges   = ARRAY_SIZE(axp288_writeable_ranges),
++ ++};
++ ++
++ ++static const struct regmap_access_table axp288_volatile_table = {
++ ++   .yes_ranges     = axp288_volatile_ranges,
++ ++   .n_yes_ranges   = ARRAY_SIZE(axp288_volatile_ranges),
++ ++};
++ ++
     static struct resource axp20x_pek_resources[] = {
        {
                .name   = "PEK_DBR",
        },
     };
     
++ ++static struct resource axp288_battery_resources[] = {
++ ++   {
++ ++           .start = AXP288_IRQ_QWBTU,
++ ++           .end   = AXP288_IRQ_QWBTU,
++ ++           .flags = IORESOURCE_IRQ,
++ ++   },
++ ++   {
++ ++           .start = AXP288_IRQ_WBTU,
++ ++           .end   = AXP288_IRQ_WBTU,
++ ++           .flags = IORESOURCE_IRQ,
++ ++   },
++ ++   {
++ ++           .start = AXP288_IRQ_QWBTO,
++ ++           .end   = AXP288_IRQ_QWBTO,
++ ++           .flags = IORESOURCE_IRQ,
++ ++   },
++ ++   {
++ ++           .start = AXP288_IRQ_WBTO,
++ ++           .end   = AXP288_IRQ_WBTO,
++ ++           .flags = IORESOURCE_IRQ,
++ ++   },
++ ++   {
++ ++           .start = AXP288_IRQ_WL2,
++ ++           .end   = AXP288_IRQ_WL2,
++ ++           .flags = IORESOURCE_IRQ,
++ ++   },
++ ++   {
++ ++           .start = AXP288_IRQ_WL1,
++ ++           .end   = AXP288_IRQ_WL1,
++ ++           .flags = IORESOURCE_IRQ,
++ ++   },
++ ++};
++ ++
     static const struct regmap_config axp20x_regmap_config = {
        .reg_bits       = 8,
        .val_bits       = 8,
        .cache_type     = REGCACHE_RBTREE,
     };
     
-- --#define AXP20X_IRQ(_irq, _off, _mask) \
-- --   [AXP20X_IRQ_##_irq] = { .reg_offset = (_off), .mask = BIT(_mask) }
++ ++static const struct regmap_config axp288_regmap_config = {
++ ++   .reg_bits       = 8,
++ ++   .val_bits       = 8,
++ ++   .wr_table       = &axp288_writeable_table,
++ ++   .volatile_table = &axp288_volatile_table,
++ ++   .max_register   = AXP288_FG_TUNE5,
++ ++   .cache_type     = REGCACHE_RBTREE,
++ ++};
++ ++
++ ++#define INIT_REGMAP_IRQ(_variant, _irq, _off, _mask)                       \
++ ++   [_variant##_IRQ_##_irq] = { .reg_offset = (_off), .mask = BIT(_mask) }
     
     static const struct regmap_irq axp20x_regmap_irqs[] = {
-- --   AXP20X_IRQ(ACIN_OVER_V,         0, 7),
-- --   AXP20X_IRQ(ACIN_PLUGIN,         0, 6),
-- --   AXP20X_IRQ(ACIN_REMOVAL,        0, 5),
-- --   AXP20X_IRQ(VBUS_OVER_V,         0, 4),
-- --   AXP20X_IRQ(VBUS_PLUGIN,         0, 3),
-- --   AXP20X_IRQ(VBUS_REMOVAL,        0, 2),
-- --   AXP20X_IRQ(VBUS_V_LOW,          0, 1),
-- --   AXP20X_IRQ(BATT_PLUGIN,         1, 7),
-- --   AXP20X_IRQ(BATT_REMOVAL,        1, 6),
-- --   AXP20X_IRQ(BATT_ENT_ACT_MODE,   1, 5),
-- --   AXP20X_IRQ(BATT_EXIT_ACT_MODE,  1, 4),
-- --   AXP20X_IRQ(CHARG,               1, 3),
-- --   AXP20X_IRQ(CHARG_DONE,          1, 2),
-- --   AXP20X_IRQ(BATT_TEMP_HIGH,      1, 1),
-- --   AXP20X_IRQ(BATT_TEMP_LOW,       1, 0),
-- --   AXP20X_IRQ(DIE_TEMP_HIGH,       2, 7),
-- --   AXP20X_IRQ(CHARG_I_LOW,         2, 6),
-- --   AXP20X_IRQ(DCDC1_V_LONG,        2, 5),
-- --   AXP20X_IRQ(DCDC2_V_LONG,        2, 4),
-- --   AXP20X_IRQ(DCDC3_V_LONG,        2, 3),
-- --   AXP20X_IRQ(PEK_SHORT,           2, 1),
-- --   AXP20X_IRQ(PEK_LONG,            2, 0),
-- --   AXP20X_IRQ(N_OE_PWR_ON,         3, 7),
-- --   AXP20X_IRQ(N_OE_PWR_OFF,        3, 6),
-- --   AXP20X_IRQ(VBUS_VALID,          3, 5),
-- --   AXP20X_IRQ(VBUS_NOT_VALID,      3, 4),
-- --   AXP20X_IRQ(VBUS_SESS_VALID,     3, 3),
-- --   AXP20X_IRQ(VBUS_SESS_END,       3, 2),
-- --   AXP20X_IRQ(LOW_PWR_LVL1,        3, 1),
-- --   AXP20X_IRQ(LOW_PWR_LVL2,        3, 0),
-- --   AXP20X_IRQ(TIMER,               4, 7),
-- --   AXP20X_IRQ(PEK_RIS_EDGE,        4, 6),
-- --   AXP20X_IRQ(PEK_FAL_EDGE,        4, 5),
-- --   AXP20X_IRQ(GPIO3_INPUT,         4, 3),
-- --   AXP20X_IRQ(GPIO2_INPUT,         4, 2),
-- --   AXP20X_IRQ(GPIO1_INPUT,         4, 1),
-- --   AXP20X_IRQ(GPIO0_INPUT,         4, 0),
++ ++   INIT_REGMAP_IRQ(AXP20X, ACIN_OVER_V,            0, 7),
++ ++   INIT_REGMAP_IRQ(AXP20X, ACIN_PLUGIN,            0, 6),
++ ++   INIT_REGMAP_IRQ(AXP20X, ACIN_REMOVAL,           0, 5),
++ ++   INIT_REGMAP_IRQ(AXP20X, VBUS_OVER_V,            0, 4),
++ ++   INIT_REGMAP_IRQ(AXP20X, VBUS_PLUGIN,            0, 3),
++ ++   INIT_REGMAP_IRQ(AXP20X, VBUS_REMOVAL,           0, 2),
++ ++   INIT_REGMAP_IRQ(AXP20X, VBUS_V_LOW,             0, 1),
++ ++   INIT_REGMAP_IRQ(AXP20X, BATT_PLUGIN,            1, 7),
++ ++   INIT_REGMAP_IRQ(AXP20X, BATT_REMOVAL,           1, 6),
++ ++   INIT_REGMAP_IRQ(AXP20X, BATT_ENT_ACT_MODE,      1, 5),
++ ++   INIT_REGMAP_IRQ(AXP20X, BATT_EXIT_ACT_MODE,     1, 4),
++ ++   INIT_REGMAP_IRQ(AXP20X, CHARG,                  1, 3),
++ ++   INIT_REGMAP_IRQ(AXP20X, CHARG_DONE,             1, 2),
++ ++   INIT_REGMAP_IRQ(AXP20X, BATT_TEMP_HIGH,         1, 1),
++ ++   INIT_REGMAP_IRQ(AXP20X, BATT_TEMP_LOW,          1, 0),
++ ++   INIT_REGMAP_IRQ(AXP20X, DIE_TEMP_HIGH,          2, 7),
++ ++   INIT_REGMAP_IRQ(AXP20X, CHARG_I_LOW,            2, 6),
++ ++   INIT_REGMAP_IRQ(AXP20X, DCDC1_V_LONG,           2, 5),
++ ++   INIT_REGMAP_IRQ(AXP20X, DCDC2_V_LONG,           2, 4),
++ ++   INIT_REGMAP_IRQ(AXP20X, DCDC3_V_LONG,           2, 3),
++ ++   INIT_REGMAP_IRQ(AXP20X, PEK_SHORT,              2, 1),
++ ++   INIT_REGMAP_IRQ(AXP20X, PEK_LONG,               2, 0),
++ ++   INIT_REGMAP_IRQ(AXP20X, N_OE_PWR_ON,            3, 7),
++ ++   INIT_REGMAP_IRQ(AXP20X, N_OE_PWR_OFF,           3, 6),
++ ++   INIT_REGMAP_IRQ(AXP20X, VBUS_VALID,             3, 5),
++ ++   INIT_REGMAP_IRQ(AXP20X, VBUS_NOT_VALID,         3, 4),
++ ++   INIT_REGMAP_IRQ(AXP20X, VBUS_SESS_VALID,        3, 3),
++ ++   INIT_REGMAP_IRQ(AXP20X, VBUS_SESS_END,          3, 2),
++ ++   INIT_REGMAP_IRQ(AXP20X, LOW_PWR_LVL1,           3, 1),
++ ++   INIT_REGMAP_IRQ(AXP20X, LOW_PWR_LVL2,           3, 0),
++ ++   INIT_REGMAP_IRQ(AXP20X, TIMER,                  4, 7),
++ ++   INIT_REGMAP_IRQ(AXP20X, PEK_RIS_EDGE,           4, 6),
++ ++   INIT_REGMAP_IRQ(AXP20X, PEK_FAL_EDGE,           4, 5),
++ ++   INIT_REGMAP_IRQ(AXP20X, GPIO3_INPUT,            4, 3),
++ ++   INIT_REGMAP_IRQ(AXP20X, GPIO2_INPUT,            4, 2),
++ ++   INIT_REGMAP_IRQ(AXP20X, GPIO1_INPUT,            4, 1),
++ ++   INIT_REGMAP_IRQ(AXP20X, GPIO0_INPUT,            4, 0),
++ ++};
++ ++
++ ++/* some IRQs are compatible with axp20x models */
++ ++static const struct regmap_irq axp288_regmap_irqs[] = {
++ ++   INIT_REGMAP_IRQ(AXP288, VBUS_FALL,              0, 2),
++ ++   INIT_REGMAP_IRQ(AXP288, VBUS_RISE,              0, 3),
++ ++   INIT_REGMAP_IRQ(AXP288, OV,                     0, 4),
++ ++
++ ++   INIT_REGMAP_IRQ(AXP288, DONE,                   1, 2),
++ ++   INIT_REGMAP_IRQ(AXP288, CHARGING,               1, 3),
++ ++   INIT_REGMAP_IRQ(AXP288, SAFE_QUIT,              1, 4),
++ ++   INIT_REGMAP_IRQ(AXP288, SAFE_ENTER,             1, 5),
++ ++   INIT_REGMAP_IRQ(AXP288, ABSENT,                 1, 6),
++ ++   INIT_REGMAP_IRQ(AXP288, APPEND,                 1, 7),
++ ++
++ ++   INIT_REGMAP_IRQ(AXP288, QWBTU,                  2, 0),
++ ++   INIT_REGMAP_IRQ(AXP288, WBTU,                   2, 1),
++ ++   INIT_REGMAP_IRQ(AXP288, QWBTO,                  2, 2),
++ ++   INIT_REGMAP_IRQ(AXP288, WBTO,                   2, 3),
++ ++   INIT_REGMAP_IRQ(AXP288, QCBTU,                  2, 4),
++ ++   INIT_REGMAP_IRQ(AXP288, CBTU,                   2, 5),
++ ++   INIT_REGMAP_IRQ(AXP288, QCBTO,                  2, 6),
++ ++   INIT_REGMAP_IRQ(AXP288, CBTO,                   2, 7),
++ ++
++ ++   INIT_REGMAP_IRQ(AXP288, WL2,                    3, 0),
++ ++   INIT_REGMAP_IRQ(AXP288, WL1,                    3, 1),
++ ++   INIT_REGMAP_IRQ(AXP288, GPADC,                  3, 2),
++ ++   INIT_REGMAP_IRQ(AXP288, OT,                     3, 7),
++ ++
++ ++   INIT_REGMAP_IRQ(AXP288, GPIO0,                  4, 0),
++ ++   INIT_REGMAP_IRQ(AXP288, GPIO1,                  4, 1),
++ ++   INIT_REGMAP_IRQ(AXP288, POKO,                   4, 2),
++ ++   INIT_REGMAP_IRQ(AXP288, POKL,                   4, 3),
++ ++   INIT_REGMAP_IRQ(AXP288, POKS,                   4, 4),
++ ++   INIT_REGMAP_IRQ(AXP288, POKN,                   4, 5),
++ ++   INIT_REGMAP_IRQ(AXP288, POKP,                   4, 6),
++ ++   INIT_REGMAP_IRQ(AXP288, TIMER,                  4, 7),
++ ++
++ ++   INIT_REGMAP_IRQ(AXP288, MV_CHNG,                5, 0),
++ ++   INIT_REGMAP_IRQ(AXP288, BC_USB_CHNG,            5, 1),
     };
     
     static const struct of_device_id axp20x_of_match[] = {
@@@@@@ -128,18 -128,18 -236,50 -128,18 -128,18 +236,41 @@@@@@ static const struct i2c_device_id axp20
     };
     MODULE_DEVICE_TABLE(i2c, axp20x_i2c_id);
     
++ ++static struct acpi_device_id axp20x_acpi_match[] = {
++ ++   {
++ ++           .id = "INT33F4",
++ ++           .driver_data = AXP288_ID,
++ ++   },
++ ++   { },
++ ++};
++ ++MODULE_DEVICE_TABLE(acpi, axp20x_acpi_match);
++ ++
     static const struct regmap_irq_chip axp20x_regmap_irq_chip = {
        .name                   = "axp20x_irq_chip",
        .status_base            = AXP20X_IRQ1_STATE,
        .ack_base               = AXP20X_IRQ1_STATE,
        .mask_base              = AXP20X_IRQ1_EN,
-- --   .num_regs               = 5,
++ ++   .mask_invert            = true,
++ ++   .init_ack_masked        = true,
        .irqs                   = axp20x_regmap_irqs,
        .num_irqs               = ARRAY_SIZE(axp20x_regmap_irqs),
++ ++   .num_regs               = 5,
++ ++
++ ++};
++ ++
++ ++static const struct regmap_irq_chip axp288_regmap_irq_chip = {
++ ++   .name                   = "axp288_irq_chip",
++ ++   .status_base            = AXP20X_IRQ1_STATE,
++ ++   .ack_base               = AXP20X_IRQ1_STATE,
++ ++   .mask_base              = AXP20X_IRQ1_EN,
        .mask_invert            = true,
        .init_ack_masked        = true,
++ ++   .irqs                   = axp288_regmap_irqs,
++ ++   .num_irqs               = ARRAY_SIZE(axp288_regmap_irqs),
++ ++   .num_regs               = 6,
++ ++
     };
     
  -  static const char * const axp20x_supplies[] = {
  -     "acin",
  -     "vin2",
  -     "vin3",
  -     "ldo24in",
  -     "ldo3in",
  -     "ldo5in",
  -  };
  -  
     static struct mfd_cell axp20x_cells[] = {
        {
                .name                   = "axp20x-pek",
                .resources              = axp20x_pek_resources,
        }, {
                .name                   = "axp20x-regulator",
  -             .parent_supplies        = axp20x_supplies,
  -             .num_parent_supplies    = ARRAY_SIZE(axp20x_supplies),
        },
     };
     
++ ++static struct resource axp288_adc_resources[] = {
++ ++   {
++ ++           .name  = "GPADC",
++ ++           .start = AXP288_IRQ_GPADC,
++ ++           .end   = AXP288_IRQ_GPADC,
++ ++           .flags = IORESOURCE_IRQ,
++ ++   },
++ ++};
++ ++
++ ++static struct resource axp288_charger_resources[] = {
++ ++   {
++ ++           .start = AXP288_IRQ_OV,
++ ++           .end   = AXP288_IRQ_OV,
++ ++           .flags = IORESOURCE_IRQ,
++ ++   },
++ ++   {
++ ++           .start = AXP288_IRQ_DONE,
++ ++           .end   = AXP288_IRQ_DONE,
++ ++           .flags = IORESOURCE_IRQ,
++ ++   },
++ ++   {
++ ++           .start = AXP288_IRQ_CHARGING,
++ ++           .end   = AXP288_IRQ_CHARGING,
++ ++           .flags = IORESOURCE_IRQ,
++ ++   },
++ ++   {
++ ++           .start = AXP288_IRQ_SAFE_QUIT,
++ ++           .end   = AXP288_IRQ_SAFE_QUIT,
++ ++           .flags = IORESOURCE_IRQ,
++ ++   },
++ ++   {
++ ++           .start = AXP288_IRQ_SAFE_ENTER,
++ ++           .end   = AXP288_IRQ_SAFE_ENTER,
++ ++           .flags = IORESOURCE_IRQ,
++ ++   },
++ ++   {
++ ++           .start = AXP288_IRQ_QCBTU,
++ ++           .end   = AXP288_IRQ_QCBTU,
++ ++           .flags = IORESOURCE_IRQ,
++ ++   },
++ ++   {
++ ++           .start = AXP288_IRQ_CBTU,
++ ++           .end   = AXP288_IRQ_CBTU,
++ ++           .flags = IORESOURCE_IRQ,
++ ++   },
++ ++   {
++ ++           .start = AXP288_IRQ_QCBTO,
++ ++           .end   = AXP288_IRQ_QCBTO,
++ ++           .flags = IORESOURCE_IRQ,
++ ++   },
++ ++   {
++ ++           .start = AXP288_IRQ_CBTO,
++ ++           .end   = AXP288_IRQ_CBTO,
++ ++           .flags = IORESOURCE_IRQ,
++ ++   },
++ ++};
++ ++
++ ++static struct mfd_cell axp288_cells[] = {
++ ++   {
++ ++           .name = "axp288_adc",
++ ++           .num_resources = ARRAY_SIZE(axp288_adc_resources),
++ ++           .resources = axp288_adc_resources,
++ ++   },
++ ++   {
++ ++           .name = "axp288_charger",
++ ++           .num_resources = ARRAY_SIZE(axp288_charger_resources),
++ ++           .resources = axp288_charger_resources,
++ ++   },
++ ++   {
++ ++           .name = "axp288_battery",
++ ++           .num_resources = ARRAY_SIZE(axp288_battery_resources),
++ ++           .resources = axp288_battery_resources,
++ ++   },
++ ++};
++ ++
     static struct axp20x_dev *axp20x_pm_power_off;
     static void axp20x_power_off(void)
     {
++ ++   if (axp20x_pm_power_off->variant == AXP288_ID)
++ ++           return;
++ ++
        regmap_write(axp20x_pm_power_off->regmap, AXP20X_OFF_CTRL,
                     AXP20X_OFF);
     }
     
++ ++static int axp20x_match_device(struct axp20x_dev *axp20x, struct device *dev)
++ ++{
++ ++   const struct acpi_device_id *acpi_id;
++ ++   const struct of_device_id *of_id;
++ ++
++ ++   if (dev->of_node) {
++ ++           of_id = of_match_device(axp20x_of_match, dev);
++ ++           if (!of_id) {
++ ++                   dev_err(dev, "Unable to match OF ID\n");
++ ++                   return -ENODEV;
++ ++           }
++ ++           axp20x->variant = (long) of_id->data;
++ ++   } else {
++ ++           acpi_id = acpi_match_device(dev->driver->acpi_match_table, dev);
++ ++           if (!acpi_id || !acpi_id->driver_data) {
++ ++                   dev_err(dev, "Unable to match ACPI ID and data\n");
++ ++                   return -ENODEV;
++ ++           }
++ ++           axp20x->variant = (long) acpi_id->driver_data;
++ ++   }
++ ++
++ ++   switch (axp20x->variant) {
++ ++   case AXP202_ID:
++ ++   case AXP209_ID:
++ ++           axp20x->nr_cells = ARRAY_SIZE(axp20x_cells);
++ ++           axp20x->cells = axp20x_cells;
++ ++           axp20x->regmap_cfg = &axp20x_regmap_config;
++ ++           axp20x->regmap_irq_chip = &axp20x_regmap_irq_chip;
++ ++           break;
++ ++   case AXP288_ID:
++ ++           axp20x->cells = axp288_cells;
++ ++           axp20x->nr_cells = ARRAY_SIZE(axp288_cells);
++ ++           axp20x->regmap_cfg = &axp288_regmap_config;
++ ++           axp20x->regmap_irq_chip = &axp288_regmap_irq_chip;
++ ++           break;
++ ++   default:
++ ++           dev_err(dev, "unsupported AXP20X ID %lu\n", axp20x->variant);
++ ++           return -EINVAL;
++ ++   }
++ ++   dev_info(dev, "AXP20x variant %s found\n",
++ ++           axp20x_model_names[axp20x->variant]);
++ ++
++ ++   return 0;
++ ++}
++ ++
     static int axp20x_i2c_probe(struct i2c_client *i2c,
                         const struct i2c_device_id *id)
     {
        struct axp20x_dev *axp20x;
-- --   const struct of_device_id *of_id;
        int ret;
     
        axp20x = devm_kzalloc(&i2c->dev, sizeof(*axp20x), GFP_KERNEL);
        if (!axp20x)
                return -ENOMEM;
     
-- --   of_id = of_match_device(axp20x_of_match, &i2c->dev);
-- --   if (!of_id) {
-- --           dev_err(&i2c->dev, "Unable to setup AXP20X data\n");
-- --           return -ENODEV;
-- --   }
-- --   axp20x->variant = (long) of_id->data;
++ ++   ret = axp20x_match_device(axp20x, &i2c->dev);
++ ++   if (ret)
++ ++           return ret;
     
        axp20x->i2c_client = i2c;
        axp20x->dev = &i2c->dev;
        dev_set_drvdata(axp20x->dev, axp20x);
     
-- --   axp20x->regmap = devm_regmap_init_i2c(i2c, &axp20x_regmap_config);
++ ++   axp20x->regmap = devm_regmap_init_i2c(i2c, axp20x->regmap_cfg);
        if (IS_ERR(axp20x->regmap)) {
                ret = PTR_ERR(axp20x->regmap);
                dev_err(&i2c->dev, "regmap init failed: %d\n", ret);
     
        ret = regmap_add_irq_chip(axp20x->regmap, i2c->irq,
                                  IRQF_ONESHOT | IRQF_SHARED, -1,
-- --                             &axp20x_regmap_irq_chip,
++ ++                             axp20x->regmap_irq_chip,
                                  &axp20x->regmap_irqc);
        if (ret) {
                dev_err(&i2c->dev, "failed to add irq chip: %d\n", ret);
                return ret;
        }
     
-- --   ret = mfd_add_devices(axp20x->dev, -1, axp20x_cells,
-- --                         ARRAY_SIZE(axp20x_cells), NULL, 0, NULL);
++ ++   ret = mfd_add_devices(axp20x->dev, -1, axp20x->cells,
++ ++                   axp20x->nr_cells, NULL, 0, NULL);
     
        if (ret) {
                dev_err(&i2c->dev, "failed to add MFD devices: %d\n", ret);
@@@@@@ -234,6 -234,6 -495,7 -234,6 -234,6 +484,7 @@@@@@ static struct i2c_driver axp20x_i2c_dri
                .name   = "axp20x",
                .owner  = THIS_MODULE,
                .of_match_table = of_match_ptr(axp20x_of_match),
++ ++           .acpi_match_table = ACPI_PTR(axp20x_acpi_match),
        },
        .probe          = axp20x_i2c_probe,
        .remove         = axp20x_i2c_remove,