linux/drivers/mfd/da9062-core.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2/*
   3 * Core, IRQ and I2C device driver for DA9061 and DA9062 PMICs
   4 * Copyright (C) 2015-2017  Dialog Semiconductor
   5 */
   6
   7#include <linux/kernel.h>
   8#include <linux/module.h>
   9#include <linux/init.h>
  10#include <linux/device.h>
  11#include <linux/interrupt.h>
  12#include <linux/of_device.h>
  13#include <linux/regmap.h>
  14#include <linux/irq.h>
  15#include <linux/mfd/core.h>
  16#include <linux/i2c.h>
  17#include <linux/mfd/da9062/core.h>
  18#include <linux/mfd/da9062/registers.h>
  19#include <linux/regulator/of_regulator.h>
  20
  21#define DA9062_REG_EVENT_A_OFFSET       0
  22#define DA9062_REG_EVENT_B_OFFSET       1
  23#define DA9062_REG_EVENT_C_OFFSET       2
  24
  25#define DA9062_IRQ_LOW  0
  26#define DA9062_IRQ_HIGH 1
  27
  28static struct regmap_irq da9061_irqs[] = {
  29        /* EVENT A */
  30        [DA9061_IRQ_ONKEY] = {
  31                .reg_offset = DA9062_REG_EVENT_A_OFFSET,
  32                .mask = DA9062AA_M_NONKEY_MASK,
  33        },
  34        [DA9061_IRQ_WDG_WARN] = {
  35                .reg_offset = DA9062_REG_EVENT_A_OFFSET,
  36                .mask = DA9062AA_M_WDG_WARN_MASK,
  37        },
  38        [DA9061_IRQ_SEQ_RDY] = {
  39                .reg_offset = DA9062_REG_EVENT_A_OFFSET,
  40                .mask = DA9062AA_M_SEQ_RDY_MASK,
  41        },
  42        /* EVENT B */
  43        [DA9061_IRQ_TEMP] = {
  44                .reg_offset = DA9062_REG_EVENT_B_OFFSET,
  45                .mask = DA9062AA_M_TEMP_MASK,
  46        },
  47        [DA9061_IRQ_LDO_LIM] = {
  48                .reg_offset = DA9062_REG_EVENT_B_OFFSET,
  49                .mask = DA9062AA_M_LDO_LIM_MASK,
  50        },
  51        [DA9061_IRQ_DVC_RDY] = {
  52                .reg_offset = DA9062_REG_EVENT_B_OFFSET,
  53                .mask = DA9062AA_M_DVC_RDY_MASK,
  54        },
  55        [DA9061_IRQ_VDD_WARN] = {
  56                .reg_offset = DA9062_REG_EVENT_B_OFFSET,
  57                .mask = DA9062AA_M_VDD_WARN_MASK,
  58        },
  59        /* EVENT C */
  60        [DA9061_IRQ_GPI0] = {
  61                .reg_offset = DA9062_REG_EVENT_C_OFFSET,
  62                .mask = DA9062AA_M_GPI0_MASK,
  63        },
  64        [DA9061_IRQ_GPI1] = {
  65                .reg_offset = DA9062_REG_EVENT_C_OFFSET,
  66                .mask = DA9062AA_M_GPI1_MASK,
  67        },
  68        [DA9061_IRQ_GPI2] = {
  69                .reg_offset = DA9062_REG_EVENT_C_OFFSET,
  70                .mask = DA9062AA_M_GPI2_MASK,
  71        },
  72        [DA9061_IRQ_GPI3] = {
  73                .reg_offset = DA9062_REG_EVENT_C_OFFSET,
  74                .mask = DA9062AA_M_GPI3_MASK,
  75        },
  76        [DA9061_IRQ_GPI4] = {
  77                .reg_offset = DA9062_REG_EVENT_C_OFFSET,
  78                .mask = DA9062AA_M_GPI4_MASK,
  79        },
  80};
  81
  82static struct regmap_irq_chip da9061_irq_chip = {
  83        .name = "da9061-irq",
  84        .irqs = da9061_irqs,
  85        .num_irqs = DA9061_NUM_IRQ,
  86        .num_regs = 3,
  87        .status_base = DA9062AA_EVENT_A,
  88        .mask_base = DA9062AA_IRQ_MASK_A,
  89        .ack_base = DA9062AA_EVENT_A,
  90};
  91
  92static struct regmap_irq da9062_irqs[] = {
  93        /* EVENT A */
  94        [DA9062_IRQ_ONKEY] = {
  95                .reg_offset = DA9062_REG_EVENT_A_OFFSET,
  96                .mask = DA9062AA_M_NONKEY_MASK,
  97        },
  98        [DA9062_IRQ_ALARM] = {
  99                .reg_offset = DA9062_REG_EVENT_A_OFFSET,
 100                .mask = DA9062AA_M_ALARM_MASK,
 101        },
 102        [DA9062_IRQ_TICK] = {
 103                .reg_offset = DA9062_REG_EVENT_A_OFFSET,
 104                .mask = DA9062AA_M_TICK_MASK,
 105        },
 106        [DA9062_IRQ_WDG_WARN] = {
 107                .reg_offset = DA9062_REG_EVENT_A_OFFSET,
 108                .mask = DA9062AA_M_WDG_WARN_MASK,
 109        },
 110        [DA9062_IRQ_SEQ_RDY] = {
 111                .reg_offset = DA9062_REG_EVENT_A_OFFSET,
 112                .mask = DA9062AA_M_SEQ_RDY_MASK,
 113        },
 114        /* EVENT B */
 115        [DA9062_IRQ_TEMP] = {
 116                .reg_offset = DA9062_REG_EVENT_B_OFFSET,
 117                .mask = DA9062AA_M_TEMP_MASK,
 118        },
 119        [DA9062_IRQ_LDO_LIM] = {
 120                .reg_offset = DA9062_REG_EVENT_B_OFFSET,
 121                .mask = DA9062AA_M_LDO_LIM_MASK,
 122        },
 123        [DA9062_IRQ_DVC_RDY] = {
 124                .reg_offset = DA9062_REG_EVENT_B_OFFSET,
 125                .mask = DA9062AA_M_DVC_RDY_MASK,
 126        },
 127        [DA9062_IRQ_VDD_WARN] = {
 128                .reg_offset = DA9062_REG_EVENT_B_OFFSET,
 129                .mask = DA9062AA_M_VDD_WARN_MASK,
 130        },
 131        /* EVENT C */
 132        [DA9062_IRQ_GPI0] = {
 133                .reg_offset = DA9062_REG_EVENT_C_OFFSET,
 134                .mask = DA9062AA_M_GPI0_MASK,
 135        },
 136        [DA9062_IRQ_GPI1] = {
 137                .reg_offset = DA9062_REG_EVENT_C_OFFSET,
 138                .mask = DA9062AA_M_GPI1_MASK,
 139        },
 140        [DA9062_IRQ_GPI2] = {
 141                .reg_offset = DA9062_REG_EVENT_C_OFFSET,
 142                .mask = DA9062AA_M_GPI2_MASK,
 143        },
 144        [DA9062_IRQ_GPI3] = {
 145                .reg_offset = DA9062_REG_EVENT_C_OFFSET,
 146                .mask = DA9062AA_M_GPI3_MASK,
 147        },
 148        [DA9062_IRQ_GPI4] = {
 149                .reg_offset = DA9062_REG_EVENT_C_OFFSET,
 150                .mask = DA9062AA_M_GPI4_MASK,
 151        },
 152};
 153
 154static struct regmap_irq_chip da9062_irq_chip = {
 155        .name = "da9062-irq",
 156        .irqs = da9062_irqs,
 157        .num_irqs = DA9062_NUM_IRQ,
 158        .num_regs = 3,
 159        .status_base = DA9062AA_EVENT_A,
 160        .mask_base = DA9062AA_IRQ_MASK_A,
 161        .ack_base = DA9062AA_EVENT_A,
 162};
 163
 164static const struct resource da9061_core_resources[] = {
 165        DEFINE_RES_IRQ_NAMED(DA9061_IRQ_VDD_WARN, "VDD_WARN"),
 166};
 167
 168static const struct resource da9061_regulators_resources[] = {
 169        DEFINE_RES_IRQ_NAMED(DA9061_IRQ_LDO_LIM, "LDO_LIM"),
 170};
 171
 172static const struct resource da9061_thermal_resources[] = {
 173        DEFINE_RES_IRQ_NAMED(DA9061_IRQ_TEMP, "THERMAL"),
 174};
 175
 176static const struct resource da9061_wdt_resources[] = {
 177        DEFINE_RES_IRQ_NAMED(DA9061_IRQ_WDG_WARN, "WD_WARN"),
 178};
 179
 180static const struct resource da9061_onkey_resources[] = {
 181        DEFINE_RES_IRQ_NAMED(DA9061_IRQ_ONKEY, "ONKEY"),
 182};
 183
 184static const struct mfd_cell da9061_devs[] = {
 185        {
 186                .name           = "da9061-core",
 187                .num_resources  = ARRAY_SIZE(da9061_core_resources),
 188                .resources      = da9061_core_resources,
 189        },
 190        {
 191                .name           = "da9062-regulators",
 192                .num_resources  = ARRAY_SIZE(da9061_regulators_resources),
 193                .resources      = da9061_regulators_resources,
 194        },
 195        {
 196                .name           = "da9061-watchdog",
 197                .num_resources  = ARRAY_SIZE(da9061_wdt_resources),
 198                .resources      = da9061_wdt_resources,
 199                .of_compatible  = "dlg,da9061-watchdog",
 200        },
 201        {
 202                .name           = "da9061-thermal",
 203                .num_resources  = ARRAY_SIZE(da9061_thermal_resources),
 204                .resources      = da9061_thermal_resources,
 205                .of_compatible  = "dlg,da9061-thermal",
 206        },
 207        {
 208                .name           = "da9061-onkey",
 209                .num_resources  = ARRAY_SIZE(da9061_onkey_resources),
 210                .resources      = da9061_onkey_resources,
 211                .of_compatible = "dlg,da9061-onkey",
 212        },
 213};
 214
 215static const struct resource da9062_core_resources[] = {
 216        DEFINE_RES_NAMED(DA9062_IRQ_VDD_WARN, 1, "VDD_WARN", IORESOURCE_IRQ),
 217};
 218
 219static const struct resource da9062_regulators_resources[] = {
 220        DEFINE_RES_NAMED(DA9062_IRQ_LDO_LIM, 1, "LDO_LIM", IORESOURCE_IRQ),
 221};
 222
 223static const struct resource da9062_thermal_resources[] = {
 224        DEFINE_RES_NAMED(DA9062_IRQ_TEMP, 1, "THERMAL", IORESOURCE_IRQ),
 225};
 226
 227static const struct resource da9062_wdt_resources[] = {
 228        DEFINE_RES_NAMED(DA9062_IRQ_WDG_WARN, 1, "WD_WARN", IORESOURCE_IRQ),
 229};
 230
 231static const struct resource da9062_rtc_resources[] = {
 232        DEFINE_RES_NAMED(DA9062_IRQ_ALARM, 1, "ALARM", IORESOURCE_IRQ),
 233        DEFINE_RES_NAMED(DA9062_IRQ_TICK, 1, "TICK", IORESOURCE_IRQ),
 234};
 235
 236static const struct resource da9062_onkey_resources[] = {
 237        DEFINE_RES_NAMED(DA9062_IRQ_ONKEY, 1, "ONKEY", IORESOURCE_IRQ),
 238};
 239
 240static const struct resource da9062_gpio_resources[] = {
 241        DEFINE_RES_NAMED(DA9062_IRQ_GPI0, 1, "GPI0", IORESOURCE_IRQ),
 242        DEFINE_RES_NAMED(DA9062_IRQ_GPI1, 1, "GPI1", IORESOURCE_IRQ),
 243        DEFINE_RES_NAMED(DA9062_IRQ_GPI2, 1, "GPI2", IORESOURCE_IRQ),
 244        DEFINE_RES_NAMED(DA9062_IRQ_GPI3, 1, "GPI3", IORESOURCE_IRQ),
 245        DEFINE_RES_NAMED(DA9062_IRQ_GPI4, 1, "GPI4", IORESOURCE_IRQ),
 246};
 247
 248static const struct mfd_cell da9062_devs[] = {
 249        {
 250                .name           = "da9062-core",
 251                .num_resources  = ARRAY_SIZE(da9062_core_resources),
 252                .resources      = da9062_core_resources,
 253        },
 254        {
 255                .name           = "da9062-regulators",
 256                .num_resources  = ARRAY_SIZE(da9062_regulators_resources),
 257                .resources      = da9062_regulators_resources,
 258        },
 259        {
 260                .name           = "da9062-watchdog",
 261                .num_resources  = ARRAY_SIZE(da9062_wdt_resources),
 262                .resources      = da9062_wdt_resources,
 263                .of_compatible  = "dlg,da9062-watchdog",
 264        },
 265        {
 266                .name           = "da9062-thermal",
 267                .num_resources  = ARRAY_SIZE(da9062_thermal_resources),
 268                .resources      = da9062_thermal_resources,
 269                .of_compatible  = "dlg,da9062-thermal",
 270        },
 271        {
 272                .name           = "da9062-rtc",
 273                .num_resources  = ARRAY_SIZE(da9062_rtc_resources),
 274                .resources      = da9062_rtc_resources,
 275                .of_compatible  = "dlg,da9062-rtc",
 276        },
 277        {
 278                .name           = "da9062-onkey",
 279                .num_resources  = ARRAY_SIZE(da9062_onkey_resources),
 280                .resources      = da9062_onkey_resources,
 281                .of_compatible  = "dlg,da9062-onkey",
 282        },
 283        {
 284                .name           = "da9062-gpio",
 285                .num_resources  = ARRAY_SIZE(da9062_gpio_resources),
 286                .resources      = da9062_gpio_resources,
 287                .of_compatible  = "dlg,da9062-gpio",
 288        },
 289};
 290
 291static int da9062_clear_fault_log(struct da9062 *chip)
 292{
 293        int ret;
 294        int fault_log;
 295
 296        ret = regmap_read(chip->regmap, DA9062AA_FAULT_LOG, &fault_log);
 297        if (ret < 0)
 298                return ret;
 299
 300        if (fault_log) {
 301                if (fault_log & DA9062AA_TWD_ERROR_MASK)
 302                        dev_dbg(chip->dev, "Fault log entry detected: TWD_ERROR\n");
 303                if (fault_log & DA9062AA_POR_MASK)
 304                        dev_dbg(chip->dev, "Fault log entry detected: POR\n");
 305                if (fault_log & DA9062AA_VDD_FAULT_MASK)
 306                        dev_dbg(chip->dev, "Fault log entry detected: VDD_FAULT\n");
 307                if (fault_log & DA9062AA_VDD_START_MASK)
 308                        dev_dbg(chip->dev, "Fault log entry detected: VDD_START\n");
 309                if (fault_log & DA9062AA_TEMP_CRIT_MASK)
 310                        dev_dbg(chip->dev, "Fault log entry detected: TEMP_CRIT\n");
 311                if (fault_log & DA9062AA_KEY_RESET_MASK)
 312                        dev_dbg(chip->dev, "Fault log entry detected: KEY_RESET\n");
 313                if (fault_log & DA9062AA_NSHUTDOWN_MASK)
 314                        dev_dbg(chip->dev, "Fault log entry detected: NSHUTDOWN\n");
 315                if (fault_log & DA9062AA_WAIT_SHUT_MASK)
 316                        dev_dbg(chip->dev, "Fault log entry detected: WAIT_SHUT\n");
 317
 318                ret = regmap_write(chip->regmap, DA9062AA_FAULT_LOG,
 319                                   fault_log);
 320        }
 321
 322        return ret;
 323}
 324
 325static int da9062_get_device_type(struct da9062 *chip)
 326{
 327        int device_id, variant_id, variant_mrc, variant_vrc;
 328        char *type;
 329        int ret;
 330
 331        ret = regmap_read(chip->regmap, DA9062AA_DEVICE_ID, &device_id);
 332        if (ret < 0) {
 333                dev_err(chip->dev, "Cannot read chip ID.\n");
 334                return -EIO;
 335        }
 336        if (device_id != DA9062_PMIC_DEVICE_ID) {
 337                dev_err(chip->dev, "Invalid device ID: 0x%02x\n", device_id);
 338                return -ENODEV;
 339        }
 340
 341        ret = regmap_read(chip->regmap, DA9062AA_VARIANT_ID, &variant_id);
 342        if (ret < 0) {
 343                dev_err(chip->dev, "Cannot read chip variant id.\n");
 344                return -EIO;
 345        }
 346
 347        variant_vrc = (variant_id & DA9062AA_VRC_MASK) >> DA9062AA_VRC_SHIFT;
 348
 349        switch (variant_vrc) {
 350        case DA9062_PMIC_VARIANT_VRC_DA9061:
 351                type = "DA9061";
 352                break;
 353        case DA9062_PMIC_VARIANT_VRC_DA9062:
 354                type = "DA9062";
 355                break;
 356        default:
 357                type = "Unknown";
 358                break;
 359        }
 360
 361        dev_info(chip->dev,
 362                 "Device detected (device-ID: 0x%02X, var-ID: 0x%02X, %s)\n",
 363                 device_id, variant_id, type);
 364
 365        variant_mrc = (variant_id & DA9062AA_MRC_MASK) >> DA9062AA_MRC_SHIFT;
 366
 367        if (variant_mrc < DA9062_PMIC_VARIANT_MRC_AA) {
 368                dev_err(chip->dev,
 369                        "Cannot support variant MRC: 0x%02X\n", variant_mrc);
 370                return -ENODEV;
 371        }
 372
 373        return ret;
 374}
 375
 376static u32 da9062_configure_irq_type(struct da9062 *chip, int irq, u32 *trigger)
 377{
 378        u32 irq_type = 0;
 379        struct irq_data *irq_data = irq_get_irq_data(irq);
 380
 381        if (!irq_data) {
 382                dev_err(chip->dev, "Invalid IRQ: %d\n", irq);
 383                return -EINVAL;
 384        }
 385        *trigger = irqd_get_trigger_type(irq_data);
 386
 387        switch (*trigger) {
 388        case IRQ_TYPE_LEVEL_HIGH:
 389                irq_type = DA9062_IRQ_HIGH;
 390                break;
 391        case IRQ_TYPE_LEVEL_LOW:
 392                irq_type = DA9062_IRQ_LOW;
 393                break;
 394        default:
 395                dev_warn(chip->dev, "Unsupported IRQ type: %d\n", *trigger);
 396                return -EINVAL;
 397        }
 398        return regmap_update_bits(chip->regmap, DA9062AA_CONFIG_A,
 399                        DA9062AA_IRQ_TYPE_MASK,
 400                        irq_type << DA9062AA_IRQ_TYPE_SHIFT);
 401}
 402
 403static const struct regmap_range da9061_aa_readable_ranges[] = {
 404        regmap_reg_range(DA9062AA_PAGE_CON, DA9062AA_STATUS_B),
 405        regmap_reg_range(DA9062AA_STATUS_D, DA9062AA_EVENT_C),
 406        regmap_reg_range(DA9062AA_IRQ_MASK_A, DA9062AA_IRQ_MASK_C),
 407        regmap_reg_range(DA9062AA_CONTROL_A, DA9062AA_GPIO_4),
 408        regmap_reg_range(DA9062AA_GPIO_WKUP_MODE, DA9062AA_GPIO_OUT3_4),
 409        regmap_reg_range(DA9062AA_BUCK1_CONT, DA9062AA_BUCK4_CONT),
 410        regmap_reg_range(DA9062AA_BUCK3_CONT, DA9062AA_BUCK3_CONT),
 411        regmap_reg_range(DA9062AA_LDO1_CONT, DA9062AA_LDO4_CONT),
 412        regmap_reg_range(DA9062AA_DVC_1, DA9062AA_DVC_1),
 413        regmap_reg_range(DA9062AA_SEQ, DA9062AA_ID_4_3),
 414        regmap_reg_range(DA9062AA_ID_12_11, DA9062AA_ID_16_15),
 415        regmap_reg_range(DA9062AA_ID_22_21, DA9062AA_ID_32_31),
 416        regmap_reg_range(DA9062AA_SEQ_A, DA9062AA_WAIT),
 417        regmap_reg_range(DA9062AA_RESET, DA9062AA_BUCK_ILIM_C),
 418        regmap_reg_range(DA9062AA_BUCK1_CFG, DA9062AA_BUCK3_CFG),
 419        regmap_reg_range(DA9062AA_VBUCK1_A, DA9062AA_VBUCK4_A),
 420        regmap_reg_range(DA9062AA_VBUCK3_A, DA9062AA_VBUCK3_A),
 421        regmap_reg_range(DA9062AA_VLDO1_A, DA9062AA_VLDO4_A),
 422        regmap_reg_range(DA9062AA_CONFIG_A, DA9062AA_CONFIG_A),
 423        regmap_reg_range(DA9062AA_VBUCK1_B, DA9062AA_VBUCK4_B),
 424        regmap_reg_range(DA9062AA_VBUCK3_B, DA9062AA_VBUCK3_B),
 425        regmap_reg_range(DA9062AA_VLDO1_B, DA9062AA_VLDO4_B),
 426        regmap_reg_range(DA9062AA_INTERFACE, DA9062AA_CONFIG_E),
 427        regmap_reg_range(DA9062AA_CONFIG_G, DA9062AA_CONFIG_K),
 428        regmap_reg_range(DA9062AA_CONFIG_M, DA9062AA_CONFIG_M),
 429        regmap_reg_range(DA9062AA_GP_ID_0, DA9062AA_GP_ID_19),
 430        regmap_reg_range(DA9062AA_DEVICE_ID, DA9062AA_CONFIG_ID),
 431};
 432
 433static const struct regmap_range da9061_aa_writeable_ranges[] = {
 434        regmap_reg_range(DA9062AA_PAGE_CON, DA9062AA_PAGE_CON),
 435        regmap_reg_range(DA9062AA_FAULT_LOG, DA9062AA_EVENT_C),
 436        regmap_reg_range(DA9062AA_IRQ_MASK_A, DA9062AA_IRQ_MASK_C),
 437        regmap_reg_range(DA9062AA_CONTROL_A, DA9062AA_GPIO_4),
 438        regmap_reg_range(DA9062AA_GPIO_WKUP_MODE, DA9062AA_GPIO_OUT3_4),
 439        regmap_reg_range(DA9062AA_BUCK1_CONT, DA9062AA_BUCK4_CONT),
 440        regmap_reg_range(DA9062AA_BUCK3_CONT, DA9062AA_BUCK3_CONT),
 441        regmap_reg_range(DA9062AA_LDO1_CONT, DA9062AA_LDO4_CONT),
 442        regmap_reg_range(DA9062AA_DVC_1, DA9062AA_DVC_1),
 443        regmap_reg_range(DA9062AA_SEQ, DA9062AA_ID_4_3),
 444        regmap_reg_range(DA9062AA_ID_12_11, DA9062AA_ID_16_15),
 445        regmap_reg_range(DA9062AA_ID_22_21, DA9062AA_ID_32_31),
 446        regmap_reg_range(DA9062AA_SEQ_A, DA9062AA_WAIT),
 447        regmap_reg_range(DA9062AA_RESET, DA9062AA_BUCK_ILIM_C),
 448        regmap_reg_range(DA9062AA_BUCK1_CFG, DA9062AA_BUCK3_CFG),
 449        regmap_reg_range(DA9062AA_VBUCK1_A, DA9062AA_VBUCK4_A),
 450        regmap_reg_range(DA9062AA_VBUCK3_A, DA9062AA_VBUCK3_A),
 451        regmap_reg_range(DA9062AA_VLDO1_A, DA9062AA_VLDO4_A),
 452        regmap_reg_range(DA9062AA_CONFIG_A, DA9062AA_CONFIG_A),
 453        regmap_reg_range(DA9062AA_VBUCK1_B, DA9062AA_VBUCK4_B),
 454        regmap_reg_range(DA9062AA_VBUCK3_B, DA9062AA_VBUCK3_B),
 455        regmap_reg_range(DA9062AA_VLDO1_B, DA9062AA_VLDO4_B),
 456        regmap_reg_range(DA9062AA_GP_ID_0, DA9062AA_GP_ID_19),
 457};
 458
 459static const struct regmap_range da9061_aa_volatile_ranges[] = {
 460        regmap_reg_range(DA9062AA_PAGE_CON, DA9062AA_STATUS_B),
 461        regmap_reg_range(DA9062AA_STATUS_D, DA9062AA_EVENT_C),
 462        regmap_reg_range(DA9062AA_CONTROL_A, DA9062AA_CONTROL_B),
 463        regmap_reg_range(DA9062AA_CONTROL_E, DA9062AA_CONTROL_F),
 464        regmap_reg_range(DA9062AA_BUCK1_CONT, DA9062AA_BUCK4_CONT),
 465        regmap_reg_range(DA9062AA_BUCK3_CONT, DA9062AA_BUCK3_CONT),
 466        regmap_reg_range(DA9062AA_LDO1_CONT, DA9062AA_LDO4_CONT),
 467        regmap_reg_range(DA9062AA_DVC_1, DA9062AA_DVC_1),
 468        regmap_reg_range(DA9062AA_SEQ, DA9062AA_SEQ),
 469};
 470
 471static const struct regmap_access_table da9061_aa_readable_table = {
 472        .yes_ranges = da9061_aa_readable_ranges,
 473        .n_yes_ranges = ARRAY_SIZE(da9061_aa_readable_ranges),
 474};
 475
 476static const struct regmap_access_table da9061_aa_writeable_table = {
 477        .yes_ranges = da9061_aa_writeable_ranges,
 478        .n_yes_ranges = ARRAY_SIZE(da9061_aa_writeable_ranges),
 479};
 480
 481static const struct regmap_access_table da9061_aa_volatile_table = {
 482        .yes_ranges = da9061_aa_volatile_ranges,
 483        .n_yes_ranges = ARRAY_SIZE(da9061_aa_volatile_ranges),
 484};
 485
 486static const struct regmap_range_cfg da9061_range_cfg[] = {
 487        {
 488                .range_min = DA9062AA_PAGE_CON,
 489                .range_max = DA9062AA_CONFIG_ID,
 490                .selector_reg = DA9062AA_PAGE_CON,
 491                .selector_mask = 1 << DA9062_I2C_PAGE_SEL_SHIFT,
 492                .selector_shift = DA9062_I2C_PAGE_SEL_SHIFT,
 493                .window_start = 0,
 494                .window_len = 256,
 495        }
 496};
 497
 498static struct regmap_config da9061_regmap_config = {
 499        .reg_bits = 8,
 500        .val_bits = 8,
 501        .ranges = da9061_range_cfg,
 502        .num_ranges = ARRAY_SIZE(da9061_range_cfg),
 503        .max_register = DA9062AA_CONFIG_ID,
 504        .cache_type = REGCACHE_RBTREE,
 505        .rd_table = &da9061_aa_readable_table,
 506        .wr_table = &da9061_aa_writeable_table,
 507        .volatile_table = &da9061_aa_volatile_table,
 508};
 509
 510static const struct regmap_range da9062_aa_readable_ranges[] = {
 511        regmap_reg_range(DA9062AA_PAGE_CON, DA9062AA_STATUS_B),
 512        regmap_reg_range(DA9062AA_STATUS_D, DA9062AA_EVENT_C),
 513        regmap_reg_range(DA9062AA_IRQ_MASK_A, DA9062AA_IRQ_MASK_C),
 514        regmap_reg_range(DA9062AA_CONTROL_A, DA9062AA_GPIO_4),
 515        regmap_reg_range(DA9062AA_GPIO_WKUP_MODE, DA9062AA_BUCK4_CONT),
 516        regmap_reg_range(DA9062AA_BUCK3_CONT, DA9062AA_BUCK3_CONT),
 517        regmap_reg_range(DA9062AA_LDO1_CONT, DA9062AA_LDO4_CONT),
 518        regmap_reg_range(DA9062AA_DVC_1, DA9062AA_DVC_1),
 519        regmap_reg_range(DA9062AA_COUNT_S, DA9062AA_SECOND_D),
 520        regmap_reg_range(DA9062AA_SEQ, DA9062AA_ID_4_3),
 521        regmap_reg_range(DA9062AA_ID_12_11, DA9062AA_ID_16_15),
 522        regmap_reg_range(DA9062AA_ID_22_21, DA9062AA_ID_32_31),
 523        regmap_reg_range(DA9062AA_SEQ_A, DA9062AA_BUCK3_CFG),
 524        regmap_reg_range(DA9062AA_VBUCK2_A, DA9062AA_VBUCK4_A),
 525        regmap_reg_range(DA9062AA_VBUCK3_A, DA9062AA_VBUCK3_A),
 526        regmap_reg_range(DA9062AA_VLDO1_A, DA9062AA_VLDO4_A),
 527        regmap_reg_range(DA9062AA_VBUCK2_B, DA9062AA_VBUCK4_B),
 528        regmap_reg_range(DA9062AA_VBUCK3_B, DA9062AA_VBUCK3_B),
 529        regmap_reg_range(DA9062AA_VLDO1_B, DA9062AA_VLDO4_B),
 530        regmap_reg_range(DA9062AA_BBAT_CONT, DA9062AA_BBAT_CONT),
 531        regmap_reg_range(DA9062AA_INTERFACE, DA9062AA_CONFIG_E),
 532        regmap_reg_range(DA9062AA_CONFIG_G, DA9062AA_CONFIG_K),
 533        regmap_reg_range(DA9062AA_CONFIG_M, DA9062AA_CONFIG_M),
 534        regmap_reg_range(DA9062AA_TRIM_CLDR, DA9062AA_GP_ID_19),
 535        regmap_reg_range(DA9062AA_DEVICE_ID, DA9062AA_CONFIG_ID),
 536};
 537
 538static const struct regmap_range da9062_aa_writeable_ranges[] = {
 539        regmap_reg_range(DA9062AA_PAGE_CON, DA9062AA_PAGE_CON),
 540        regmap_reg_range(DA9062AA_FAULT_LOG, DA9062AA_EVENT_C),
 541        regmap_reg_range(DA9062AA_IRQ_MASK_A, DA9062AA_IRQ_MASK_C),
 542        regmap_reg_range(DA9062AA_CONTROL_A, DA9062AA_GPIO_4),
 543        regmap_reg_range(DA9062AA_GPIO_WKUP_MODE, DA9062AA_BUCK4_CONT),
 544        regmap_reg_range(DA9062AA_BUCK3_CONT, DA9062AA_BUCK3_CONT),
 545        regmap_reg_range(DA9062AA_LDO1_CONT, DA9062AA_LDO4_CONT),
 546        regmap_reg_range(DA9062AA_DVC_1, DA9062AA_DVC_1),
 547        regmap_reg_range(DA9062AA_COUNT_S, DA9062AA_ALARM_Y),
 548        regmap_reg_range(DA9062AA_SEQ, DA9062AA_ID_4_3),
 549        regmap_reg_range(DA9062AA_ID_12_11, DA9062AA_ID_16_15),
 550        regmap_reg_range(DA9062AA_ID_22_21, DA9062AA_ID_32_31),
 551        regmap_reg_range(DA9062AA_SEQ_A, DA9062AA_BUCK3_CFG),
 552        regmap_reg_range(DA9062AA_VBUCK2_A, DA9062AA_VBUCK4_A),
 553        regmap_reg_range(DA9062AA_VBUCK3_A, DA9062AA_VBUCK3_A),
 554        regmap_reg_range(DA9062AA_VLDO1_A, DA9062AA_VLDO4_A),
 555        regmap_reg_range(DA9062AA_VBUCK2_B, DA9062AA_VBUCK4_B),
 556        regmap_reg_range(DA9062AA_VBUCK3_B, DA9062AA_VBUCK3_B),
 557        regmap_reg_range(DA9062AA_VLDO1_B, DA9062AA_VLDO4_B),
 558        regmap_reg_range(DA9062AA_BBAT_CONT, DA9062AA_BBAT_CONT),
 559        regmap_reg_range(DA9062AA_GP_ID_0, DA9062AA_GP_ID_19),
 560};
 561
 562static const struct regmap_range da9062_aa_volatile_ranges[] = {
 563        regmap_reg_range(DA9062AA_PAGE_CON, DA9062AA_STATUS_B),
 564        regmap_reg_range(DA9062AA_STATUS_D, DA9062AA_EVENT_C),
 565        regmap_reg_range(DA9062AA_CONTROL_A, DA9062AA_CONTROL_B),
 566        regmap_reg_range(DA9062AA_CONTROL_E, DA9062AA_CONTROL_F),
 567        regmap_reg_range(DA9062AA_BUCK2_CONT, DA9062AA_BUCK4_CONT),
 568        regmap_reg_range(DA9062AA_BUCK3_CONT, DA9062AA_BUCK3_CONT),
 569        regmap_reg_range(DA9062AA_LDO1_CONT, DA9062AA_LDO4_CONT),
 570        regmap_reg_range(DA9062AA_DVC_1, DA9062AA_DVC_1),
 571        regmap_reg_range(DA9062AA_COUNT_S, DA9062AA_SECOND_D),
 572        regmap_reg_range(DA9062AA_SEQ, DA9062AA_SEQ),
 573        regmap_reg_range(DA9062AA_EN_32K, DA9062AA_EN_32K),
 574};
 575
 576static const struct regmap_access_table da9062_aa_readable_table = {
 577        .yes_ranges = da9062_aa_readable_ranges,
 578        .n_yes_ranges = ARRAY_SIZE(da9062_aa_readable_ranges),
 579};
 580
 581static const struct regmap_access_table da9062_aa_writeable_table = {
 582        .yes_ranges = da9062_aa_writeable_ranges,
 583        .n_yes_ranges = ARRAY_SIZE(da9062_aa_writeable_ranges),
 584};
 585
 586static const struct regmap_access_table da9062_aa_volatile_table = {
 587        .yes_ranges = da9062_aa_volatile_ranges,
 588        .n_yes_ranges = ARRAY_SIZE(da9062_aa_volatile_ranges),
 589};
 590
 591static const struct regmap_range_cfg da9062_range_cfg[] = {
 592        {
 593                .range_min = DA9062AA_PAGE_CON,
 594                .range_max = DA9062AA_CONFIG_ID,
 595                .selector_reg = DA9062AA_PAGE_CON,
 596                .selector_mask = 1 << DA9062_I2C_PAGE_SEL_SHIFT,
 597                .selector_shift = DA9062_I2C_PAGE_SEL_SHIFT,
 598                .window_start = 0,
 599                .window_len = 256,
 600        }
 601};
 602
 603static struct regmap_config da9062_regmap_config = {
 604        .reg_bits = 8,
 605        .val_bits = 8,
 606        .ranges = da9062_range_cfg,
 607        .num_ranges = ARRAY_SIZE(da9062_range_cfg),
 608        .max_register = DA9062AA_CONFIG_ID,
 609        .cache_type = REGCACHE_RBTREE,
 610        .rd_table = &da9062_aa_readable_table,
 611        .wr_table = &da9062_aa_writeable_table,
 612        .volatile_table = &da9062_aa_volatile_table,
 613};
 614
 615static const struct of_device_id da9062_dt_ids[] = {
 616        { .compatible = "dlg,da9061", .data = (void *)COMPAT_TYPE_DA9061, },
 617        { .compatible = "dlg,da9062", .data = (void *)COMPAT_TYPE_DA9062, },
 618        { }
 619};
 620MODULE_DEVICE_TABLE(of, da9062_dt_ids);
 621
 622static int da9062_i2c_probe(struct i2c_client *i2c,
 623        const struct i2c_device_id *id)
 624{
 625        struct da9062 *chip;
 626        unsigned int irq_base;
 627        const struct mfd_cell *cell;
 628        const struct regmap_irq_chip *irq_chip;
 629        const struct regmap_config *config;
 630        int cell_num;
 631        u32 trigger_type = 0;
 632        int ret;
 633
 634        chip = devm_kzalloc(&i2c->dev, sizeof(*chip), GFP_KERNEL);
 635        if (!chip)
 636                return -ENOMEM;
 637
 638        if (i2c->dev.of_node)
 639                chip->chip_type = (uintptr_t)of_device_get_match_data(&i2c->dev);
 640        else
 641                chip->chip_type = id->driver_data;
 642
 643        i2c_set_clientdata(i2c, chip);
 644        chip->dev = &i2c->dev;
 645
 646        if (!i2c->irq) {
 647                dev_err(chip->dev, "No IRQ configured\n");
 648                return -EINVAL;
 649        }
 650
 651        switch (chip->chip_type) {
 652        case COMPAT_TYPE_DA9061:
 653                cell = da9061_devs;
 654                cell_num = ARRAY_SIZE(da9061_devs);
 655                irq_chip = &da9061_irq_chip;
 656                config = &da9061_regmap_config;
 657                break;
 658        case COMPAT_TYPE_DA9062:
 659                cell = da9062_devs;
 660                cell_num = ARRAY_SIZE(da9062_devs);
 661                irq_chip = &da9062_irq_chip;
 662                config = &da9062_regmap_config;
 663                break;
 664        default:
 665                dev_err(chip->dev, "Unrecognised chip type\n");
 666                return -ENODEV;
 667        }
 668
 669        chip->regmap = devm_regmap_init_i2c(i2c, config);
 670        if (IS_ERR(chip->regmap)) {
 671                ret = PTR_ERR(chip->regmap);
 672                dev_err(chip->dev, "Failed to allocate register map: %d\n",
 673                        ret);
 674                return ret;
 675        }
 676
 677        ret = da9062_clear_fault_log(chip);
 678        if (ret < 0)
 679                dev_warn(chip->dev, "Cannot clear fault log\n");
 680
 681        ret = da9062_get_device_type(chip);
 682        if (ret)
 683                return ret;
 684
 685        ret = da9062_configure_irq_type(chip, i2c->irq, &trigger_type);
 686        if (ret < 0) {
 687                dev_err(chip->dev, "Failed to configure IRQ type\n");
 688                return ret;
 689        }
 690
 691        ret = regmap_add_irq_chip(chip->regmap, i2c->irq,
 692                        trigger_type | IRQF_SHARED | IRQF_ONESHOT,
 693                        -1, irq_chip, &chip->regmap_irq);
 694        if (ret) {
 695                dev_err(chip->dev, "Failed to request IRQ %d: %d\n",
 696                        i2c->irq, ret);
 697                return ret;
 698        }
 699
 700        irq_base = regmap_irq_chip_get_base(chip->regmap_irq);
 701
 702        ret = mfd_add_devices(chip->dev, PLATFORM_DEVID_NONE, cell,
 703                              cell_num, NULL, irq_base,
 704                              NULL);
 705        if (ret) {
 706                dev_err(chip->dev, "Cannot register child devices\n");
 707                regmap_del_irq_chip(i2c->irq, chip->regmap_irq);
 708                return ret;
 709        }
 710
 711        return ret;
 712}
 713
 714static int da9062_i2c_remove(struct i2c_client *i2c)
 715{
 716        struct da9062 *chip = i2c_get_clientdata(i2c);
 717
 718        mfd_remove_devices(chip->dev);
 719        regmap_del_irq_chip(i2c->irq, chip->regmap_irq);
 720
 721        return 0;
 722}
 723
 724static const struct i2c_device_id da9062_i2c_id[] = {
 725        { "da9061", COMPAT_TYPE_DA9061 },
 726        { "da9062", COMPAT_TYPE_DA9062 },
 727        { },
 728};
 729MODULE_DEVICE_TABLE(i2c, da9062_i2c_id);
 730
 731static struct i2c_driver da9062_i2c_driver = {
 732        .driver = {
 733                .name = "da9062",
 734                .of_match_table = da9062_dt_ids,
 735        },
 736        .probe    = da9062_i2c_probe,
 737        .remove   = da9062_i2c_remove,
 738        .id_table = da9062_i2c_id,
 739};
 740
 741module_i2c_driver(da9062_i2c_driver);
 742
 743MODULE_DESCRIPTION("Core device driver for Dialog DA9061 and DA9062");
 744MODULE_AUTHOR("Steve Twiss <stwiss.opensource@diasemi.com>");
 745MODULE_LICENSE("GPL");
 746