19b40b030SS Twiss /* 29b40b030SS Twiss * Core, IRQ and I2C device driver for DA9062 PMIC 39b40b030SS Twiss * Copyright (C) 2015 Dialog Semiconductor Ltd. 49b40b030SS Twiss * 59b40b030SS Twiss * This program is free software; you can redistribute it and/or 69b40b030SS Twiss * modify it under the terms of the GNU General Public License 79b40b030SS Twiss * as published by the Free Software Foundation; either version 2 89b40b030SS Twiss * of the License, or (at your option) any later version. 99b40b030SS Twiss * 109b40b030SS Twiss * This program is distributed in the hope that it will be useful, 119b40b030SS Twiss * but WITHOUT ANY WARRANTY; without even the implied warranty of 129b40b030SS Twiss * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 139b40b030SS Twiss * GNU General Public License for more details. 149b40b030SS Twiss */ 159b40b030SS Twiss 169b40b030SS Twiss #include <linux/kernel.h> 179b40b030SS Twiss #include <linux/module.h> 189b40b030SS Twiss #include <linux/init.h> 199b40b030SS Twiss #include <linux/device.h> 209b40b030SS Twiss #include <linux/interrupt.h> 219b40b030SS Twiss #include <linux/regmap.h> 229b40b030SS Twiss #include <linux/irq.h> 239b40b030SS Twiss #include <linux/mfd/core.h> 249b40b030SS Twiss #include <linux/i2c.h> 259b40b030SS Twiss #include <linux/mfd/da9062/core.h> 269b40b030SS Twiss #include <linux/mfd/da9062/registers.h> 279b40b030SS Twiss #include <linux/regulator/of_regulator.h> 289b40b030SS Twiss 299b40b030SS Twiss #define DA9062_REG_EVENT_A_OFFSET 0 309b40b030SS Twiss #define DA9062_REG_EVENT_B_OFFSET 1 319b40b030SS Twiss #define DA9062_REG_EVENT_C_OFFSET 2 329b40b030SS Twiss 339b40b030SS Twiss static struct regmap_irq da9062_irqs[] = { 349b40b030SS Twiss /* EVENT A */ 359b40b030SS Twiss [DA9062_IRQ_ONKEY] = { 369b40b030SS Twiss .reg_offset = DA9062_REG_EVENT_A_OFFSET, 379b40b030SS Twiss .mask = DA9062AA_M_NONKEY_MASK, 389b40b030SS Twiss }, 399b40b030SS Twiss [DA9062_IRQ_ALARM] = { 409b40b030SS Twiss .reg_offset = DA9062_REG_EVENT_A_OFFSET, 419b40b030SS Twiss .mask = DA9062AA_M_ALARM_MASK, 429b40b030SS Twiss }, 439b40b030SS Twiss [DA9062_IRQ_TICK] = { 449b40b030SS Twiss .reg_offset = DA9062_REG_EVENT_A_OFFSET, 459b40b030SS Twiss .mask = DA9062AA_M_TICK_MASK, 469b40b030SS Twiss }, 479b40b030SS Twiss [DA9062_IRQ_WDG_WARN] = { 489b40b030SS Twiss .reg_offset = DA9062_REG_EVENT_A_OFFSET, 499b40b030SS Twiss .mask = DA9062AA_M_WDG_WARN_MASK, 509b40b030SS Twiss }, 519b40b030SS Twiss [DA9062_IRQ_SEQ_RDY] = { 529b40b030SS Twiss .reg_offset = DA9062_REG_EVENT_A_OFFSET, 539b40b030SS Twiss .mask = DA9062AA_M_SEQ_RDY_MASK, 549b40b030SS Twiss }, 559b40b030SS Twiss /* EVENT B */ 569b40b030SS Twiss [DA9062_IRQ_TEMP] = { 579b40b030SS Twiss .reg_offset = DA9062_REG_EVENT_B_OFFSET, 589b40b030SS Twiss .mask = DA9062AA_M_TEMP_MASK, 599b40b030SS Twiss }, 609b40b030SS Twiss [DA9062_IRQ_LDO_LIM] = { 619b40b030SS Twiss .reg_offset = DA9062_REG_EVENT_B_OFFSET, 629b40b030SS Twiss .mask = DA9062AA_M_LDO_LIM_MASK, 639b40b030SS Twiss }, 649b40b030SS Twiss [DA9062_IRQ_DVC_RDY] = { 659b40b030SS Twiss .reg_offset = DA9062_REG_EVENT_B_OFFSET, 669b40b030SS Twiss .mask = DA9062AA_M_DVC_RDY_MASK, 679b40b030SS Twiss }, 689b40b030SS Twiss [DA9062_IRQ_VDD_WARN] = { 699b40b030SS Twiss .reg_offset = DA9062_REG_EVENT_B_OFFSET, 709b40b030SS Twiss .mask = DA9062AA_M_VDD_WARN_MASK, 719b40b030SS Twiss }, 729b40b030SS Twiss /* EVENT C */ 739b40b030SS Twiss [DA9062_IRQ_GPI0] = { 749b40b030SS Twiss .reg_offset = DA9062_REG_EVENT_C_OFFSET, 759b40b030SS Twiss .mask = DA9062AA_M_GPI0_MASK, 769b40b030SS Twiss }, 779b40b030SS Twiss [DA9062_IRQ_GPI1] = { 789b40b030SS Twiss .reg_offset = DA9062_REG_EVENT_C_OFFSET, 799b40b030SS Twiss .mask = DA9062AA_M_GPI1_MASK, 809b40b030SS Twiss }, 819b40b030SS Twiss [DA9062_IRQ_GPI2] = { 829b40b030SS Twiss .reg_offset = DA9062_REG_EVENT_C_OFFSET, 839b40b030SS Twiss .mask = DA9062AA_M_GPI2_MASK, 849b40b030SS Twiss }, 859b40b030SS Twiss [DA9062_IRQ_GPI3] = { 869b40b030SS Twiss .reg_offset = DA9062_REG_EVENT_C_OFFSET, 879b40b030SS Twiss .mask = DA9062AA_M_GPI3_MASK, 889b40b030SS Twiss }, 899b40b030SS Twiss [DA9062_IRQ_GPI4] = { 909b40b030SS Twiss .reg_offset = DA9062_REG_EVENT_C_OFFSET, 919b40b030SS Twiss .mask = DA9062AA_M_GPI4_MASK, 929b40b030SS Twiss }, 939b40b030SS Twiss }; 949b40b030SS Twiss 959b40b030SS Twiss static struct regmap_irq_chip da9062_irq_chip = { 969b40b030SS Twiss .name = "da9062-irq", 979b40b030SS Twiss .irqs = da9062_irqs, 989b40b030SS Twiss .num_irqs = DA9062_NUM_IRQ, 999b40b030SS Twiss .num_regs = 3, 1009b40b030SS Twiss .status_base = DA9062AA_EVENT_A, 1019b40b030SS Twiss .mask_base = DA9062AA_IRQ_MASK_A, 1029b40b030SS Twiss .ack_base = DA9062AA_EVENT_A, 1039b40b030SS Twiss }; 1049b40b030SS Twiss 1059b40b030SS Twiss static struct resource da9062_core_resources[] = { 1069b40b030SS Twiss DEFINE_RES_NAMED(DA9062_IRQ_VDD_WARN, 1, "VDD_WARN", IORESOURCE_IRQ), 1079b40b030SS Twiss }; 1089b40b030SS Twiss 1099b40b030SS Twiss static struct resource da9062_regulators_resources[] = { 1109b40b030SS Twiss DEFINE_RES_NAMED(DA9062_IRQ_LDO_LIM, 1, "LDO_LIM", IORESOURCE_IRQ), 1119b40b030SS Twiss }; 1129b40b030SS Twiss 1139b40b030SS Twiss static struct resource da9062_thermal_resources[] = { 1149b40b030SS Twiss DEFINE_RES_NAMED(DA9062_IRQ_TEMP, 1, "THERMAL", IORESOURCE_IRQ), 1159b40b030SS Twiss }; 1169b40b030SS Twiss 1179b40b030SS Twiss static struct resource da9062_wdt_resources[] = { 1189b40b030SS Twiss DEFINE_RES_NAMED(DA9062_IRQ_WDG_WARN, 1, "WD_WARN", IORESOURCE_IRQ), 1199b40b030SS Twiss }; 1209b40b030SS Twiss 121ca1ce176SS Twiss static struct resource da9062_rtc_resources[] = { 122ca1ce176SS Twiss DEFINE_RES_NAMED(DA9062_IRQ_ALARM, 1, "ALARM", IORESOURCE_IRQ), 123ca1ce176SS Twiss DEFINE_RES_NAMED(DA9062_IRQ_TICK, 1, "TICK", IORESOURCE_IRQ), 124ca1ce176SS Twiss }; 125ca1ce176SS Twiss 12668b6fd02SS Twiss static struct resource da9062_onkey_resources[] = { 12768b6fd02SS Twiss DEFINE_RES_NAMED(DA9062_IRQ_ONKEY, 1, "ONKEY", IORESOURCE_IRQ), 12868b6fd02SS Twiss }; 12968b6fd02SS Twiss 1309b40b030SS Twiss static const struct mfd_cell da9062_devs[] = { 1319b40b030SS Twiss { 1329b40b030SS Twiss .name = "da9062-core", 1339b40b030SS Twiss .num_resources = ARRAY_SIZE(da9062_core_resources), 1349b40b030SS Twiss .resources = da9062_core_resources, 1359b40b030SS Twiss }, 1369b40b030SS Twiss { 1379b40b030SS Twiss .name = "da9062-regulators", 1389b40b030SS Twiss .num_resources = ARRAY_SIZE(da9062_regulators_resources), 1399b40b030SS Twiss .resources = da9062_regulators_resources, 1409b40b030SS Twiss }, 1419b40b030SS Twiss { 1429b40b030SS Twiss .name = "da9062-watchdog", 1439b40b030SS Twiss .num_resources = ARRAY_SIZE(da9062_wdt_resources), 1449b40b030SS Twiss .resources = da9062_wdt_resources, 1459b40b030SS Twiss .of_compatible = "dlg,da9062-wdt", 1469b40b030SS Twiss }, 1479b40b030SS Twiss { 1489b40b030SS Twiss .name = "da9062-thermal", 1499b40b030SS Twiss .num_resources = ARRAY_SIZE(da9062_thermal_resources), 1509b40b030SS Twiss .resources = da9062_thermal_resources, 1519b40b030SS Twiss .of_compatible = "dlg,da9062-thermal", 1529b40b030SS Twiss }, 153ca1ce176SS Twiss { 154ca1ce176SS Twiss .name = "da9062-rtc", 155ca1ce176SS Twiss .num_resources = ARRAY_SIZE(da9062_rtc_resources), 156ca1ce176SS Twiss .resources = da9062_rtc_resources, 157ca1ce176SS Twiss .of_compatible = "dlg,da9062-rtc", 158ca1ce176SS Twiss }, 15968b6fd02SS Twiss { 16068b6fd02SS Twiss .name = "da9062-onkey", 16168b6fd02SS Twiss .num_resources = ARRAY_SIZE(da9062_onkey_resources), 16268b6fd02SS Twiss .resources = da9062_onkey_resources, 16368b6fd02SS Twiss .of_compatible = "dlg,da9062-onkey", 16468b6fd02SS Twiss }, 1659b40b030SS Twiss }; 1669b40b030SS Twiss 1679b40b030SS Twiss static int da9062_clear_fault_log(struct da9062 *chip) 1689b40b030SS Twiss { 1699b40b030SS Twiss int ret; 1709b40b030SS Twiss int fault_log; 1719b40b030SS Twiss 1729b40b030SS Twiss ret = regmap_read(chip->regmap, DA9062AA_FAULT_LOG, &fault_log); 1739b40b030SS Twiss if (ret < 0) 1749b40b030SS Twiss return ret; 1759b40b030SS Twiss 1769b40b030SS Twiss if (fault_log) { 1779b40b030SS Twiss if (fault_log & DA9062AA_TWD_ERROR_MASK) 1789b40b030SS Twiss dev_dbg(chip->dev, "Fault log entry detected: TWD_ERROR\n"); 1799b40b030SS Twiss if (fault_log & DA9062AA_POR_MASK) 1809b40b030SS Twiss dev_dbg(chip->dev, "Fault log entry detected: POR\n"); 1819b40b030SS Twiss if (fault_log & DA9062AA_VDD_FAULT_MASK) 1829b40b030SS Twiss dev_dbg(chip->dev, "Fault log entry detected: VDD_FAULT\n"); 1839b40b030SS Twiss if (fault_log & DA9062AA_VDD_START_MASK) 1849b40b030SS Twiss dev_dbg(chip->dev, "Fault log entry detected: VDD_START\n"); 1859b40b030SS Twiss if (fault_log & DA9062AA_TEMP_CRIT_MASK) 1869b40b030SS Twiss dev_dbg(chip->dev, "Fault log entry detected: TEMP_CRIT\n"); 1879b40b030SS Twiss if (fault_log & DA9062AA_KEY_RESET_MASK) 1889b40b030SS Twiss dev_dbg(chip->dev, "Fault log entry detected: KEY_RESET\n"); 1899b40b030SS Twiss if (fault_log & DA9062AA_NSHUTDOWN_MASK) 1909b40b030SS Twiss dev_dbg(chip->dev, "Fault log entry detected: NSHUTDOWN\n"); 1919b40b030SS Twiss if (fault_log & DA9062AA_WAIT_SHUT_MASK) 1929b40b030SS Twiss dev_dbg(chip->dev, "Fault log entry detected: WAIT_SHUT\n"); 1939b40b030SS Twiss 1949b40b030SS Twiss ret = regmap_write(chip->regmap, DA9062AA_FAULT_LOG, 1959b40b030SS Twiss fault_log); 1969b40b030SS Twiss } 1979b40b030SS Twiss 1989b40b030SS Twiss return ret; 1999b40b030SS Twiss } 2009b40b030SS Twiss 2016f44b148SAxel Lin static int da9062_get_device_type(struct da9062 *chip) 2029b40b030SS Twiss { 2039b40b030SS Twiss int device_id, variant_id, variant_mrc; 2049b40b030SS Twiss int ret; 2059b40b030SS Twiss 2069b40b030SS Twiss ret = regmap_read(chip->regmap, DA9062AA_DEVICE_ID, &device_id); 2079b40b030SS Twiss if (ret < 0) { 2089b40b030SS Twiss dev_err(chip->dev, "Cannot read chip ID.\n"); 2099b40b030SS Twiss return -EIO; 2109b40b030SS Twiss } 2119b40b030SS Twiss if (device_id != DA9062_PMIC_DEVICE_ID) { 2129b40b030SS Twiss dev_err(chip->dev, "Invalid device ID: 0x%02x\n", device_id); 2139b40b030SS Twiss return -ENODEV; 2149b40b030SS Twiss } 2159b40b030SS Twiss 2169b40b030SS Twiss ret = regmap_read(chip->regmap, DA9062AA_VARIANT_ID, &variant_id); 2179b40b030SS Twiss if (ret < 0) { 2189b40b030SS Twiss dev_err(chip->dev, "Cannot read chip variant id.\n"); 2199b40b030SS Twiss return -EIO; 2209b40b030SS Twiss } 2219b40b030SS Twiss 2229b40b030SS Twiss dev_info(chip->dev, 2239b40b030SS Twiss "Device detected (device-ID: 0x%02X, var-ID: 0x%02X)\n", 2249b40b030SS Twiss device_id, variant_id); 2259b40b030SS Twiss 2269b40b030SS Twiss variant_mrc = (variant_id & DA9062AA_MRC_MASK) >> DA9062AA_MRC_SHIFT; 2279b40b030SS Twiss 2289b40b030SS Twiss if (variant_mrc < DA9062_PMIC_VARIANT_MRC_AA) { 2299b40b030SS Twiss dev_err(chip->dev, 2309b40b030SS Twiss "Cannot support variant MRC: 0x%02X\n", variant_mrc); 2319b40b030SS Twiss return -ENODEV; 2329b40b030SS Twiss } 2339b40b030SS Twiss 2349b40b030SS Twiss return ret; 2359b40b030SS Twiss } 2369b40b030SS Twiss 2379b40b030SS Twiss static const struct regmap_range da9062_aa_readable_ranges[] = { 2389b40b030SS Twiss { 2399b40b030SS Twiss .range_min = DA9062AA_PAGE_CON, 2409b40b030SS Twiss .range_max = DA9062AA_STATUS_B, 2419b40b030SS Twiss }, { 2429b40b030SS Twiss .range_min = DA9062AA_STATUS_D, 2439b40b030SS Twiss .range_max = DA9062AA_EVENT_C, 2449b40b030SS Twiss }, { 2459b40b030SS Twiss .range_min = DA9062AA_IRQ_MASK_A, 2469b40b030SS Twiss .range_max = DA9062AA_IRQ_MASK_C, 2479b40b030SS Twiss }, { 2489b40b030SS Twiss .range_min = DA9062AA_CONTROL_A, 2499b40b030SS Twiss .range_max = DA9062AA_GPIO_4, 2509b40b030SS Twiss }, { 2519b40b030SS Twiss .range_min = DA9062AA_GPIO_WKUP_MODE, 2529b40b030SS Twiss .range_max = DA9062AA_BUCK4_CONT, 2539b40b030SS Twiss }, { 2549b40b030SS Twiss .range_min = DA9062AA_BUCK3_CONT, 2559b40b030SS Twiss .range_max = DA9062AA_BUCK3_CONT, 2569b40b030SS Twiss }, { 2579b40b030SS Twiss .range_min = DA9062AA_LDO1_CONT, 2589b40b030SS Twiss .range_max = DA9062AA_LDO4_CONT, 2599b40b030SS Twiss }, { 2609b40b030SS Twiss .range_min = DA9062AA_DVC_1, 2619b40b030SS Twiss .range_max = DA9062AA_DVC_1, 2629b40b030SS Twiss }, { 2639b40b030SS Twiss .range_min = DA9062AA_COUNT_S, 2649b40b030SS Twiss .range_max = DA9062AA_SECOND_D, 2659b40b030SS Twiss }, { 2669b40b030SS Twiss .range_min = DA9062AA_SEQ, 2679b40b030SS Twiss .range_max = DA9062AA_ID_4_3, 2689b40b030SS Twiss }, { 2699b40b030SS Twiss .range_min = DA9062AA_ID_12_11, 2709b40b030SS Twiss .range_max = DA9062AA_ID_16_15, 2719b40b030SS Twiss }, { 2729b40b030SS Twiss .range_min = DA9062AA_ID_22_21, 2739b40b030SS Twiss .range_max = DA9062AA_ID_32_31, 2749b40b030SS Twiss }, { 2759b40b030SS Twiss .range_min = DA9062AA_SEQ_A, 2769b40b030SS Twiss .range_max = DA9062AA_BUCK3_CFG, 2779b40b030SS Twiss }, { 2789b40b030SS Twiss .range_min = DA9062AA_VBUCK2_A, 2799b40b030SS Twiss .range_max = DA9062AA_VBUCK4_A, 2809b40b030SS Twiss }, { 2819b40b030SS Twiss .range_min = DA9062AA_VBUCK3_A, 2829b40b030SS Twiss .range_max = DA9062AA_VBUCK3_A, 2839b40b030SS Twiss }, { 2849b40b030SS Twiss .range_min = DA9062AA_VLDO1_A, 2859b40b030SS Twiss .range_max = DA9062AA_VLDO4_A, 2869b40b030SS Twiss }, { 2879b40b030SS Twiss .range_min = DA9062AA_VBUCK2_B, 2889b40b030SS Twiss .range_max = DA9062AA_VBUCK4_B, 2899b40b030SS Twiss }, { 2909b40b030SS Twiss .range_min = DA9062AA_VBUCK3_B, 2919b40b030SS Twiss .range_max = DA9062AA_VBUCK3_B, 2929b40b030SS Twiss }, { 2939b40b030SS Twiss .range_min = DA9062AA_VLDO1_B, 2949b40b030SS Twiss .range_max = DA9062AA_VLDO4_B, 2959b40b030SS Twiss }, { 2969b40b030SS Twiss .range_min = DA9062AA_BBAT_CONT, 2979b40b030SS Twiss .range_max = DA9062AA_BBAT_CONT, 2989b40b030SS Twiss }, { 2999b40b030SS Twiss .range_min = DA9062AA_INTERFACE, 3009b40b030SS Twiss .range_max = DA9062AA_CONFIG_E, 3019b40b030SS Twiss }, { 3029b40b030SS Twiss .range_min = DA9062AA_CONFIG_G, 3039b40b030SS Twiss .range_max = DA9062AA_CONFIG_K, 3049b40b030SS Twiss }, { 3059b40b030SS Twiss .range_min = DA9062AA_CONFIG_M, 3069b40b030SS Twiss .range_max = DA9062AA_CONFIG_M, 3079b40b030SS Twiss }, { 3089b40b030SS Twiss .range_min = DA9062AA_TRIM_CLDR, 3099b40b030SS Twiss .range_max = DA9062AA_GP_ID_19, 3109b40b030SS Twiss }, { 3119b40b030SS Twiss .range_min = DA9062AA_DEVICE_ID, 3129b40b030SS Twiss .range_max = DA9062AA_CONFIG_ID, 3139b40b030SS Twiss }, 3149b40b030SS Twiss }; 3159b40b030SS Twiss 3169b40b030SS Twiss static const struct regmap_range da9062_aa_writeable_ranges[] = { 3179b40b030SS Twiss { 3189b40b030SS Twiss .range_min = DA9062AA_PAGE_CON, 3199b40b030SS Twiss .range_max = DA9062AA_PAGE_CON, 3209b40b030SS Twiss }, { 3219b40b030SS Twiss .range_min = DA9062AA_FAULT_LOG, 3229b40b030SS Twiss .range_max = DA9062AA_EVENT_C, 3239b40b030SS Twiss }, { 3249b40b030SS Twiss .range_min = DA9062AA_IRQ_MASK_A, 3259b40b030SS Twiss .range_max = DA9062AA_IRQ_MASK_C, 3269b40b030SS Twiss }, { 3279b40b030SS Twiss .range_min = DA9062AA_CONTROL_A, 3289b40b030SS Twiss .range_max = DA9062AA_GPIO_4, 3299b40b030SS Twiss }, { 3309b40b030SS Twiss .range_min = DA9062AA_GPIO_WKUP_MODE, 3319b40b030SS Twiss .range_max = DA9062AA_BUCK4_CONT, 3329b40b030SS Twiss }, { 3339b40b030SS Twiss .range_min = DA9062AA_BUCK3_CONT, 3349b40b030SS Twiss .range_max = DA9062AA_BUCK3_CONT, 3359b40b030SS Twiss }, { 3369b40b030SS Twiss .range_min = DA9062AA_LDO1_CONT, 3379b40b030SS Twiss .range_max = DA9062AA_LDO4_CONT, 3389b40b030SS Twiss }, { 3399b40b030SS Twiss .range_min = DA9062AA_DVC_1, 3409b40b030SS Twiss .range_max = DA9062AA_DVC_1, 3419b40b030SS Twiss }, { 3429b40b030SS Twiss .range_min = DA9062AA_COUNT_S, 3439b40b030SS Twiss .range_max = DA9062AA_ALARM_Y, 3449b40b030SS Twiss }, { 3459b40b030SS Twiss .range_min = DA9062AA_SEQ, 3469b40b030SS Twiss .range_max = DA9062AA_ID_4_3, 3479b40b030SS Twiss }, { 3489b40b030SS Twiss .range_min = DA9062AA_ID_12_11, 3499b40b030SS Twiss .range_max = DA9062AA_ID_16_15, 3509b40b030SS Twiss }, { 3519b40b030SS Twiss .range_min = DA9062AA_ID_22_21, 3529b40b030SS Twiss .range_max = DA9062AA_ID_32_31, 3539b40b030SS Twiss }, { 3549b40b030SS Twiss .range_min = DA9062AA_SEQ_A, 3559b40b030SS Twiss .range_max = DA9062AA_BUCK3_CFG, 3569b40b030SS Twiss }, { 3579b40b030SS Twiss .range_min = DA9062AA_VBUCK2_A, 3589b40b030SS Twiss .range_max = DA9062AA_VBUCK4_A, 3599b40b030SS Twiss }, { 3609b40b030SS Twiss .range_min = DA9062AA_VBUCK3_A, 3619b40b030SS Twiss .range_max = DA9062AA_VBUCK3_A, 3629b40b030SS Twiss }, { 3639b40b030SS Twiss .range_min = DA9062AA_VLDO1_A, 3649b40b030SS Twiss .range_max = DA9062AA_VLDO4_A, 3659b40b030SS Twiss }, { 3669b40b030SS Twiss .range_min = DA9062AA_VBUCK2_B, 3679b40b030SS Twiss .range_max = DA9062AA_VBUCK4_B, 3689b40b030SS Twiss }, { 3699b40b030SS Twiss .range_min = DA9062AA_VBUCK3_B, 3709b40b030SS Twiss .range_max = DA9062AA_VBUCK3_B, 3719b40b030SS Twiss }, { 3729b40b030SS Twiss .range_min = DA9062AA_VLDO1_B, 3739b40b030SS Twiss .range_max = DA9062AA_VLDO4_B, 3749b40b030SS Twiss }, { 3759b40b030SS Twiss .range_min = DA9062AA_BBAT_CONT, 3769b40b030SS Twiss .range_max = DA9062AA_BBAT_CONT, 3779b40b030SS Twiss }, { 3789b40b030SS Twiss .range_min = DA9062AA_GP_ID_0, 3799b40b030SS Twiss .range_max = DA9062AA_GP_ID_19, 3809b40b030SS Twiss }, 3819b40b030SS Twiss }; 3829b40b030SS Twiss 3839b40b030SS Twiss static const struct regmap_range da9062_aa_volatile_ranges[] = { 3849b40b030SS Twiss { 3859b40b030SS Twiss .range_min = DA9062AA_PAGE_CON, 3869b40b030SS Twiss .range_max = DA9062AA_STATUS_B, 3879b40b030SS Twiss }, { 3889b40b030SS Twiss .range_min = DA9062AA_STATUS_D, 3899b40b030SS Twiss .range_max = DA9062AA_EVENT_C, 3909b40b030SS Twiss }, { 3919b40b030SS Twiss .range_min = DA9062AA_CONTROL_F, 3929b40b030SS Twiss .range_max = DA9062AA_CONTROL_F, 3939b40b030SS Twiss }, { 3949b40b030SS Twiss .range_min = DA9062AA_COUNT_S, 3959b40b030SS Twiss .range_max = DA9062AA_SECOND_D, 3969b40b030SS Twiss }, 3979b40b030SS Twiss }; 3989b40b030SS Twiss 3999b40b030SS Twiss static const struct regmap_access_table da9062_aa_readable_table = { 4009b40b030SS Twiss .yes_ranges = da9062_aa_readable_ranges, 4019b40b030SS Twiss .n_yes_ranges = ARRAY_SIZE(da9062_aa_readable_ranges), 4029b40b030SS Twiss }; 4039b40b030SS Twiss 4049b40b030SS Twiss static const struct regmap_access_table da9062_aa_writeable_table = { 4059b40b030SS Twiss .yes_ranges = da9062_aa_writeable_ranges, 4069b40b030SS Twiss .n_yes_ranges = ARRAY_SIZE(da9062_aa_writeable_ranges), 4079b40b030SS Twiss }; 4089b40b030SS Twiss 4099b40b030SS Twiss static const struct regmap_access_table da9062_aa_volatile_table = { 4109b40b030SS Twiss .yes_ranges = da9062_aa_volatile_ranges, 4119b40b030SS Twiss .n_yes_ranges = ARRAY_SIZE(da9062_aa_volatile_ranges), 4129b40b030SS Twiss }; 4139b40b030SS Twiss 4149b40b030SS Twiss static const struct regmap_range_cfg da9062_range_cfg[] = { 4159b40b030SS Twiss { 4169b40b030SS Twiss .range_min = DA9062AA_PAGE_CON, 4179b40b030SS Twiss .range_max = DA9062AA_CONFIG_ID, 4189b40b030SS Twiss .selector_reg = DA9062AA_PAGE_CON, 4199b40b030SS Twiss .selector_mask = 1 << DA9062_I2C_PAGE_SEL_SHIFT, 4209b40b030SS Twiss .selector_shift = DA9062_I2C_PAGE_SEL_SHIFT, 4219b40b030SS Twiss .window_start = 0, 4229b40b030SS Twiss .window_len = 256, 4239b40b030SS Twiss } 4249b40b030SS Twiss }; 4259b40b030SS Twiss 4269b40b030SS Twiss static struct regmap_config da9062_regmap_config = { 4279b40b030SS Twiss .reg_bits = 8, 4289b40b030SS Twiss .val_bits = 8, 4299b40b030SS Twiss .ranges = da9062_range_cfg, 4309b40b030SS Twiss .num_ranges = ARRAY_SIZE(da9062_range_cfg), 4319b40b030SS Twiss .max_register = DA9062AA_CONFIG_ID, 4329b40b030SS Twiss .cache_type = REGCACHE_RBTREE, 4339b40b030SS Twiss .rd_table = &da9062_aa_readable_table, 4349b40b030SS Twiss .wr_table = &da9062_aa_writeable_table, 4359b40b030SS Twiss .volatile_table = &da9062_aa_volatile_table, 4369b40b030SS Twiss }; 4379b40b030SS Twiss 4389b40b030SS Twiss static int da9062_i2c_probe(struct i2c_client *i2c, 4399b40b030SS Twiss const struct i2c_device_id *id) 4409b40b030SS Twiss { 4419b40b030SS Twiss struct da9062 *chip; 4429b40b030SS Twiss unsigned int irq_base; 4439b40b030SS Twiss int ret; 4449b40b030SS Twiss 4459b40b030SS Twiss chip = devm_kzalloc(&i2c->dev, sizeof(*chip), GFP_KERNEL); 4469b40b030SS Twiss if (!chip) 4479b40b030SS Twiss return -ENOMEM; 4489b40b030SS Twiss 4499b40b030SS Twiss i2c_set_clientdata(i2c, chip); 4509b40b030SS Twiss chip->dev = &i2c->dev; 4519b40b030SS Twiss 4529b40b030SS Twiss if (!i2c->irq) { 4539b40b030SS Twiss dev_err(chip->dev, "No IRQ configured\n"); 4549b40b030SS Twiss return -EINVAL; 4559b40b030SS Twiss } 4569b40b030SS Twiss 4579b40b030SS Twiss chip->regmap = devm_regmap_init_i2c(i2c, &da9062_regmap_config); 4589b40b030SS Twiss if (IS_ERR(chip->regmap)) { 4599b40b030SS Twiss ret = PTR_ERR(chip->regmap); 4609b40b030SS Twiss dev_err(chip->dev, "Failed to allocate register map: %d\n", 4619b40b030SS Twiss ret); 4629b40b030SS Twiss return ret; 4639b40b030SS Twiss } 4649b40b030SS Twiss 4659b40b030SS Twiss ret = da9062_clear_fault_log(chip); 4669b40b030SS Twiss if (ret < 0) 4679b40b030SS Twiss dev_warn(chip->dev, "Cannot clear fault log\n"); 4689b40b030SS Twiss 4696f44b148SAxel Lin ret = da9062_get_device_type(chip); 4709b40b030SS Twiss if (ret) 4719b40b030SS Twiss return ret; 4729b40b030SS Twiss 4739b40b030SS Twiss ret = regmap_add_irq_chip(chip->regmap, i2c->irq, 4749b40b030SS Twiss IRQF_TRIGGER_LOW | IRQF_ONESHOT | IRQF_SHARED, 4759b40b030SS Twiss -1, &da9062_irq_chip, 4769b40b030SS Twiss &chip->regmap_irq); 4779b40b030SS Twiss if (ret) { 4789b40b030SS Twiss dev_err(chip->dev, "Failed to request IRQ %d: %d\n", 4799b40b030SS Twiss i2c->irq, ret); 4809b40b030SS Twiss return ret; 4819b40b030SS Twiss } 4829b40b030SS Twiss 4839b40b030SS Twiss irq_base = regmap_irq_chip_get_base(chip->regmap_irq); 4849b40b030SS Twiss 4859b40b030SS Twiss ret = mfd_add_devices(chip->dev, PLATFORM_DEVID_NONE, da9062_devs, 4869b40b030SS Twiss ARRAY_SIZE(da9062_devs), NULL, irq_base, 4879b40b030SS Twiss NULL); 4889b40b030SS Twiss if (ret) { 4899b40b030SS Twiss dev_err(chip->dev, "Cannot register child devices\n"); 4909b40b030SS Twiss regmap_del_irq_chip(i2c->irq, chip->regmap_irq); 4919b40b030SS Twiss return ret; 4929b40b030SS Twiss } 4939b40b030SS Twiss 4949b40b030SS Twiss return ret; 4959b40b030SS Twiss } 4969b40b030SS Twiss 4979b40b030SS Twiss static int da9062_i2c_remove(struct i2c_client *i2c) 4989b40b030SS Twiss { 4999b40b030SS Twiss struct da9062 *chip = i2c_get_clientdata(i2c); 5009b40b030SS Twiss 5019b40b030SS Twiss mfd_remove_devices(chip->dev); 5029b40b030SS Twiss regmap_del_irq_chip(i2c->irq, chip->regmap_irq); 5039b40b030SS Twiss 5049b40b030SS Twiss return 0; 5059b40b030SS Twiss } 5069b40b030SS Twiss 5079b40b030SS Twiss static const struct i2c_device_id da9062_i2c_id[] = { 5089b40b030SS Twiss { "da9062", 0 }, 5099b40b030SS Twiss { }, 5109b40b030SS Twiss }; 5119b40b030SS Twiss MODULE_DEVICE_TABLE(i2c, da9062_i2c_id); 5129b40b030SS Twiss 5139b40b030SS Twiss static const struct of_device_id da9062_dt_ids[] = { 5149b40b030SS Twiss { .compatible = "dlg,da9062", }, 5159b40b030SS Twiss { } 5169b40b030SS Twiss }; 5179b40b030SS Twiss MODULE_DEVICE_TABLE(of, da9062_dt_ids); 5189b40b030SS Twiss 5199b40b030SS Twiss static struct i2c_driver da9062_i2c_driver = { 5209b40b030SS Twiss .driver = { 5219b40b030SS Twiss .name = "da9062", 5229b40b030SS Twiss .of_match_table = of_match_ptr(da9062_dt_ids), 5239b40b030SS Twiss }, 5249b40b030SS Twiss .probe = da9062_i2c_probe, 5259b40b030SS Twiss .remove = da9062_i2c_remove, 5269b40b030SS Twiss .id_table = da9062_i2c_id, 5279b40b030SS Twiss }; 5289b40b030SS Twiss 5299b40b030SS Twiss module_i2c_driver(da9062_i2c_driver); 5309b40b030SS Twiss 5319b40b030SS Twiss MODULE_DESCRIPTION("Core device driver for Dialog DA9062"); 5329b40b030SS Twiss MODULE_AUTHOR("Steve Twiss <stwiss.opensource@diasemi.com>"); 5339b40b030SS Twiss MODULE_LICENSE("GPL"); 534