18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Core, IRQ and I2C device driver for DA9061 and DA9062 PMICs 48c2ecf20Sopenharmony_ci * Copyright (C) 2015-2017 Dialog Semiconductor 58c2ecf20Sopenharmony_ci */ 68c2ecf20Sopenharmony_ci 78c2ecf20Sopenharmony_ci#include <linux/kernel.h> 88c2ecf20Sopenharmony_ci#include <linux/module.h> 98c2ecf20Sopenharmony_ci#include <linux/init.h> 108c2ecf20Sopenharmony_ci#include <linux/device.h> 118c2ecf20Sopenharmony_ci#include <linux/interrupt.h> 128c2ecf20Sopenharmony_ci#include <linux/regmap.h> 138c2ecf20Sopenharmony_ci#include <linux/irq.h> 148c2ecf20Sopenharmony_ci#include <linux/mfd/core.h> 158c2ecf20Sopenharmony_ci#include <linux/i2c.h> 168c2ecf20Sopenharmony_ci#include <linux/mfd/da9062/core.h> 178c2ecf20Sopenharmony_ci#include <linux/mfd/da9062/registers.h> 188c2ecf20Sopenharmony_ci#include <linux/regulator/of_regulator.h> 198c2ecf20Sopenharmony_ci 208c2ecf20Sopenharmony_ci#define DA9062_REG_EVENT_A_OFFSET 0 218c2ecf20Sopenharmony_ci#define DA9062_REG_EVENT_B_OFFSET 1 228c2ecf20Sopenharmony_ci#define DA9062_REG_EVENT_C_OFFSET 2 238c2ecf20Sopenharmony_ci 248c2ecf20Sopenharmony_ci#define DA9062_IRQ_LOW 0 258c2ecf20Sopenharmony_ci#define DA9062_IRQ_HIGH 1 268c2ecf20Sopenharmony_ci 278c2ecf20Sopenharmony_cistatic struct regmap_irq da9061_irqs[] = { 288c2ecf20Sopenharmony_ci /* EVENT A */ 298c2ecf20Sopenharmony_ci [DA9061_IRQ_ONKEY] = { 308c2ecf20Sopenharmony_ci .reg_offset = DA9062_REG_EVENT_A_OFFSET, 318c2ecf20Sopenharmony_ci .mask = DA9062AA_M_NONKEY_MASK, 328c2ecf20Sopenharmony_ci }, 338c2ecf20Sopenharmony_ci [DA9061_IRQ_WDG_WARN] = { 348c2ecf20Sopenharmony_ci .reg_offset = DA9062_REG_EVENT_A_OFFSET, 358c2ecf20Sopenharmony_ci .mask = DA9062AA_M_WDG_WARN_MASK, 368c2ecf20Sopenharmony_ci }, 378c2ecf20Sopenharmony_ci [DA9061_IRQ_SEQ_RDY] = { 388c2ecf20Sopenharmony_ci .reg_offset = DA9062_REG_EVENT_A_OFFSET, 398c2ecf20Sopenharmony_ci .mask = DA9062AA_M_SEQ_RDY_MASK, 408c2ecf20Sopenharmony_ci }, 418c2ecf20Sopenharmony_ci /* EVENT B */ 428c2ecf20Sopenharmony_ci [DA9061_IRQ_TEMP] = { 438c2ecf20Sopenharmony_ci .reg_offset = DA9062_REG_EVENT_B_OFFSET, 448c2ecf20Sopenharmony_ci .mask = DA9062AA_M_TEMP_MASK, 458c2ecf20Sopenharmony_ci }, 468c2ecf20Sopenharmony_ci [DA9061_IRQ_LDO_LIM] = { 478c2ecf20Sopenharmony_ci .reg_offset = DA9062_REG_EVENT_B_OFFSET, 488c2ecf20Sopenharmony_ci .mask = DA9062AA_M_LDO_LIM_MASK, 498c2ecf20Sopenharmony_ci }, 508c2ecf20Sopenharmony_ci [DA9061_IRQ_DVC_RDY] = { 518c2ecf20Sopenharmony_ci .reg_offset = DA9062_REG_EVENT_B_OFFSET, 528c2ecf20Sopenharmony_ci .mask = DA9062AA_M_DVC_RDY_MASK, 538c2ecf20Sopenharmony_ci }, 548c2ecf20Sopenharmony_ci [DA9061_IRQ_VDD_WARN] = { 558c2ecf20Sopenharmony_ci .reg_offset = DA9062_REG_EVENT_B_OFFSET, 568c2ecf20Sopenharmony_ci .mask = DA9062AA_M_VDD_WARN_MASK, 578c2ecf20Sopenharmony_ci }, 588c2ecf20Sopenharmony_ci /* EVENT C */ 598c2ecf20Sopenharmony_ci [DA9061_IRQ_GPI0] = { 608c2ecf20Sopenharmony_ci .reg_offset = DA9062_REG_EVENT_C_OFFSET, 618c2ecf20Sopenharmony_ci .mask = DA9062AA_M_GPI0_MASK, 628c2ecf20Sopenharmony_ci }, 638c2ecf20Sopenharmony_ci [DA9061_IRQ_GPI1] = { 648c2ecf20Sopenharmony_ci .reg_offset = DA9062_REG_EVENT_C_OFFSET, 658c2ecf20Sopenharmony_ci .mask = DA9062AA_M_GPI1_MASK, 668c2ecf20Sopenharmony_ci }, 678c2ecf20Sopenharmony_ci [DA9061_IRQ_GPI2] = { 688c2ecf20Sopenharmony_ci .reg_offset = DA9062_REG_EVENT_C_OFFSET, 698c2ecf20Sopenharmony_ci .mask = DA9062AA_M_GPI2_MASK, 708c2ecf20Sopenharmony_ci }, 718c2ecf20Sopenharmony_ci [DA9061_IRQ_GPI3] = { 728c2ecf20Sopenharmony_ci .reg_offset = DA9062_REG_EVENT_C_OFFSET, 738c2ecf20Sopenharmony_ci .mask = DA9062AA_M_GPI3_MASK, 748c2ecf20Sopenharmony_ci }, 758c2ecf20Sopenharmony_ci [DA9061_IRQ_GPI4] = { 768c2ecf20Sopenharmony_ci .reg_offset = DA9062_REG_EVENT_C_OFFSET, 778c2ecf20Sopenharmony_ci .mask = DA9062AA_M_GPI4_MASK, 788c2ecf20Sopenharmony_ci }, 798c2ecf20Sopenharmony_ci}; 808c2ecf20Sopenharmony_ci 818c2ecf20Sopenharmony_cistatic struct regmap_irq_chip da9061_irq_chip = { 828c2ecf20Sopenharmony_ci .name = "da9061-irq", 838c2ecf20Sopenharmony_ci .irqs = da9061_irqs, 848c2ecf20Sopenharmony_ci .num_irqs = DA9061_NUM_IRQ, 858c2ecf20Sopenharmony_ci .num_regs = 3, 868c2ecf20Sopenharmony_ci .status_base = DA9062AA_EVENT_A, 878c2ecf20Sopenharmony_ci .mask_base = DA9062AA_IRQ_MASK_A, 888c2ecf20Sopenharmony_ci .ack_base = DA9062AA_EVENT_A, 898c2ecf20Sopenharmony_ci}; 908c2ecf20Sopenharmony_ci 918c2ecf20Sopenharmony_cistatic struct regmap_irq da9062_irqs[] = { 928c2ecf20Sopenharmony_ci /* EVENT A */ 938c2ecf20Sopenharmony_ci [DA9062_IRQ_ONKEY] = { 948c2ecf20Sopenharmony_ci .reg_offset = DA9062_REG_EVENT_A_OFFSET, 958c2ecf20Sopenharmony_ci .mask = DA9062AA_M_NONKEY_MASK, 968c2ecf20Sopenharmony_ci }, 978c2ecf20Sopenharmony_ci [DA9062_IRQ_ALARM] = { 988c2ecf20Sopenharmony_ci .reg_offset = DA9062_REG_EVENT_A_OFFSET, 998c2ecf20Sopenharmony_ci .mask = DA9062AA_M_ALARM_MASK, 1008c2ecf20Sopenharmony_ci }, 1018c2ecf20Sopenharmony_ci [DA9062_IRQ_TICK] = { 1028c2ecf20Sopenharmony_ci .reg_offset = DA9062_REG_EVENT_A_OFFSET, 1038c2ecf20Sopenharmony_ci .mask = DA9062AA_M_TICK_MASK, 1048c2ecf20Sopenharmony_ci }, 1058c2ecf20Sopenharmony_ci [DA9062_IRQ_WDG_WARN] = { 1068c2ecf20Sopenharmony_ci .reg_offset = DA9062_REG_EVENT_A_OFFSET, 1078c2ecf20Sopenharmony_ci .mask = DA9062AA_M_WDG_WARN_MASK, 1088c2ecf20Sopenharmony_ci }, 1098c2ecf20Sopenharmony_ci [DA9062_IRQ_SEQ_RDY] = { 1108c2ecf20Sopenharmony_ci .reg_offset = DA9062_REG_EVENT_A_OFFSET, 1118c2ecf20Sopenharmony_ci .mask = DA9062AA_M_SEQ_RDY_MASK, 1128c2ecf20Sopenharmony_ci }, 1138c2ecf20Sopenharmony_ci /* EVENT B */ 1148c2ecf20Sopenharmony_ci [DA9062_IRQ_TEMP] = { 1158c2ecf20Sopenharmony_ci .reg_offset = DA9062_REG_EVENT_B_OFFSET, 1168c2ecf20Sopenharmony_ci .mask = DA9062AA_M_TEMP_MASK, 1178c2ecf20Sopenharmony_ci }, 1188c2ecf20Sopenharmony_ci [DA9062_IRQ_LDO_LIM] = { 1198c2ecf20Sopenharmony_ci .reg_offset = DA9062_REG_EVENT_B_OFFSET, 1208c2ecf20Sopenharmony_ci .mask = DA9062AA_M_LDO_LIM_MASK, 1218c2ecf20Sopenharmony_ci }, 1228c2ecf20Sopenharmony_ci [DA9062_IRQ_DVC_RDY] = { 1238c2ecf20Sopenharmony_ci .reg_offset = DA9062_REG_EVENT_B_OFFSET, 1248c2ecf20Sopenharmony_ci .mask = DA9062AA_M_DVC_RDY_MASK, 1258c2ecf20Sopenharmony_ci }, 1268c2ecf20Sopenharmony_ci [DA9062_IRQ_VDD_WARN] = { 1278c2ecf20Sopenharmony_ci .reg_offset = DA9062_REG_EVENT_B_OFFSET, 1288c2ecf20Sopenharmony_ci .mask = DA9062AA_M_VDD_WARN_MASK, 1298c2ecf20Sopenharmony_ci }, 1308c2ecf20Sopenharmony_ci /* EVENT C */ 1318c2ecf20Sopenharmony_ci [DA9062_IRQ_GPI0] = { 1328c2ecf20Sopenharmony_ci .reg_offset = DA9062_REG_EVENT_C_OFFSET, 1338c2ecf20Sopenharmony_ci .mask = DA9062AA_M_GPI0_MASK, 1348c2ecf20Sopenharmony_ci }, 1358c2ecf20Sopenharmony_ci [DA9062_IRQ_GPI1] = { 1368c2ecf20Sopenharmony_ci .reg_offset = DA9062_REG_EVENT_C_OFFSET, 1378c2ecf20Sopenharmony_ci .mask = DA9062AA_M_GPI1_MASK, 1388c2ecf20Sopenharmony_ci }, 1398c2ecf20Sopenharmony_ci [DA9062_IRQ_GPI2] = { 1408c2ecf20Sopenharmony_ci .reg_offset = DA9062_REG_EVENT_C_OFFSET, 1418c2ecf20Sopenharmony_ci .mask = DA9062AA_M_GPI2_MASK, 1428c2ecf20Sopenharmony_ci }, 1438c2ecf20Sopenharmony_ci [DA9062_IRQ_GPI3] = { 1448c2ecf20Sopenharmony_ci .reg_offset = DA9062_REG_EVENT_C_OFFSET, 1458c2ecf20Sopenharmony_ci .mask = DA9062AA_M_GPI3_MASK, 1468c2ecf20Sopenharmony_ci }, 1478c2ecf20Sopenharmony_ci [DA9062_IRQ_GPI4] = { 1488c2ecf20Sopenharmony_ci .reg_offset = DA9062_REG_EVENT_C_OFFSET, 1498c2ecf20Sopenharmony_ci .mask = DA9062AA_M_GPI4_MASK, 1508c2ecf20Sopenharmony_ci }, 1518c2ecf20Sopenharmony_ci}; 1528c2ecf20Sopenharmony_ci 1538c2ecf20Sopenharmony_cistatic struct regmap_irq_chip da9062_irq_chip = { 1548c2ecf20Sopenharmony_ci .name = "da9062-irq", 1558c2ecf20Sopenharmony_ci .irqs = da9062_irqs, 1568c2ecf20Sopenharmony_ci .num_irqs = DA9062_NUM_IRQ, 1578c2ecf20Sopenharmony_ci .num_regs = 3, 1588c2ecf20Sopenharmony_ci .status_base = DA9062AA_EVENT_A, 1598c2ecf20Sopenharmony_ci .mask_base = DA9062AA_IRQ_MASK_A, 1608c2ecf20Sopenharmony_ci .ack_base = DA9062AA_EVENT_A, 1618c2ecf20Sopenharmony_ci}; 1628c2ecf20Sopenharmony_ci 1638c2ecf20Sopenharmony_cistatic struct resource da9061_core_resources[] = { 1648c2ecf20Sopenharmony_ci DEFINE_RES_IRQ_NAMED(DA9061_IRQ_VDD_WARN, "VDD_WARN"), 1658c2ecf20Sopenharmony_ci}; 1668c2ecf20Sopenharmony_ci 1678c2ecf20Sopenharmony_cistatic struct resource da9061_regulators_resources[] = { 1688c2ecf20Sopenharmony_ci DEFINE_RES_IRQ_NAMED(DA9061_IRQ_LDO_LIM, "LDO_LIM"), 1698c2ecf20Sopenharmony_ci}; 1708c2ecf20Sopenharmony_ci 1718c2ecf20Sopenharmony_cistatic struct resource da9061_thermal_resources[] = { 1728c2ecf20Sopenharmony_ci DEFINE_RES_IRQ_NAMED(DA9061_IRQ_TEMP, "THERMAL"), 1738c2ecf20Sopenharmony_ci}; 1748c2ecf20Sopenharmony_ci 1758c2ecf20Sopenharmony_cistatic struct resource da9061_wdt_resources[] = { 1768c2ecf20Sopenharmony_ci DEFINE_RES_IRQ_NAMED(DA9061_IRQ_WDG_WARN, "WD_WARN"), 1778c2ecf20Sopenharmony_ci}; 1788c2ecf20Sopenharmony_ci 1798c2ecf20Sopenharmony_cistatic struct resource da9061_onkey_resources[] = { 1808c2ecf20Sopenharmony_ci DEFINE_RES_IRQ_NAMED(DA9061_IRQ_ONKEY, "ONKEY"), 1818c2ecf20Sopenharmony_ci}; 1828c2ecf20Sopenharmony_ci 1838c2ecf20Sopenharmony_cistatic const struct mfd_cell da9061_devs[] = { 1848c2ecf20Sopenharmony_ci { 1858c2ecf20Sopenharmony_ci .name = "da9061-core", 1868c2ecf20Sopenharmony_ci .num_resources = ARRAY_SIZE(da9061_core_resources), 1878c2ecf20Sopenharmony_ci .resources = da9061_core_resources, 1888c2ecf20Sopenharmony_ci }, 1898c2ecf20Sopenharmony_ci { 1908c2ecf20Sopenharmony_ci .name = "da9062-regulators", 1918c2ecf20Sopenharmony_ci .num_resources = ARRAY_SIZE(da9061_regulators_resources), 1928c2ecf20Sopenharmony_ci .resources = da9061_regulators_resources, 1938c2ecf20Sopenharmony_ci }, 1948c2ecf20Sopenharmony_ci { 1958c2ecf20Sopenharmony_ci .name = "da9061-watchdog", 1968c2ecf20Sopenharmony_ci .num_resources = ARRAY_SIZE(da9061_wdt_resources), 1978c2ecf20Sopenharmony_ci .resources = da9061_wdt_resources, 1988c2ecf20Sopenharmony_ci .of_compatible = "dlg,da9061-watchdog", 1998c2ecf20Sopenharmony_ci }, 2008c2ecf20Sopenharmony_ci { 2018c2ecf20Sopenharmony_ci .name = "da9061-thermal", 2028c2ecf20Sopenharmony_ci .num_resources = ARRAY_SIZE(da9061_thermal_resources), 2038c2ecf20Sopenharmony_ci .resources = da9061_thermal_resources, 2048c2ecf20Sopenharmony_ci .of_compatible = "dlg,da9061-thermal", 2058c2ecf20Sopenharmony_ci }, 2068c2ecf20Sopenharmony_ci { 2078c2ecf20Sopenharmony_ci .name = "da9061-onkey", 2088c2ecf20Sopenharmony_ci .num_resources = ARRAY_SIZE(da9061_onkey_resources), 2098c2ecf20Sopenharmony_ci .resources = da9061_onkey_resources, 2108c2ecf20Sopenharmony_ci .of_compatible = "dlg,da9061-onkey", 2118c2ecf20Sopenharmony_ci }, 2128c2ecf20Sopenharmony_ci}; 2138c2ecf20Sopenharmony_ci 2148c2ecf20Sopenharmony_cistatic struct resource da9062_core_resources[] = { 2158c2ecf20Sopenharmony_ci DEFINE_RES_NAMED(DA9062_IRQ_VDD_WARN, 1, "VDD_WARN", IORESOURCE_IRQ), 2168c2ecf20Sopenharmony_ci}; 2178c2ecf20Sopenharmony_ci 2188c2ecf20Sopenharmony_cistatic struct resource da9062_regulators_resources[] = { 2198c2ecf20Sopenharmony_ci DEFINE_RES_NAMED(DA9062_IRQ_LDO_LIM, 1, "LDO_LIM", IORESOURCE_IRQ), 2208c2ecf20Sopenharmony_ci}; 2218c2ecf20Sopenharmony_ci 2228c2ecf20Sopenharmony_cistatic struct resource da9062_thermal_resources[] = { 2238c2ecf20Sopenharmony_ci DEFINE_RES_NAMED(DA9062_IRQ_TEMP, 1, "THERMAL", IORESOURCE_IRQ), 2248c2ecf20Sopenharmony_ci}; 2258c2ecf20Sopenharmony_ci 2268c2ecf20Sopenharmony_cistatic struct resource da9062_wdt_resources[] = { 2278c2ecf20Sopenharmony_ci DEFINE_RES_NAMED(DA9062_IRQ_WDG_WARN, 1, "WD_WARN", IORESOURCE_IRQ), 2288c2ecf20Sopenharmony_ci}; 2298c2ecf20Sopenharmony_ci 2308c2ecf20Sopenharmony_cistatic struct resource da9062_rtc_resources[] = { 2318c2ecf20Sopenharmony_ci DEFINE_RES_NAMED(DA9062_IRQ_ALARM, 1, "ALARM", IORESOURCE_IRQ), 2328c2ecf20Sopenharmony_ci DEFINE_RES_NAMED(DA9062_IRQ_TICK, 1, "TICK", IORESOURCE_IRQ), 2338c2ecf20Sopenharmony_ci}; 2348c2ecf20Sopenharmony_ci 2358c2ecf20Sopenharmony_cistatic struct resource da9062_onkey_resources[] = { 2368c2ecf20Sopenharmony_ci DEFINE_RES_NAMED(DA9062_IRQ_ONKEY, 1, "ONKEY", IORESOURCE_IRQ), 2378c2ecf20Sopenharmony_ci}; 2388c2ecf20Sopenharmony_ci 2398c2ecf20Sopenharmony_cistatic struct resource da9062_gpio_resources[] = { 2408c2ecf20Sopenharmony_ci DEFINE_RES_NAMED(DA9062_IRQ_GPI0, 1, "GPI0", IORESOURCE_IRQ), 2418c2ecf20Sopenharmony_ci DEFINE_RES_NAMED(DA9062_IRQ_GPI1, 1, "GPI1", IORESOURCE_IRQ), 2428c2ecf20Sopenharmony_ci DEFINE_RES_NAMED(DA9062_IRQ_GPI2, 1, "GPI2", IORESOURCE_IRQ), 2438c2ecf20Sopenharmony_ci DEFINE_RES_NAMED(DA9062_IRQ_GPI3, 1, "GPI3", IORESOURCE_IRQ), 2448c2ecf20Sopenharmony_ci DEFINE_RES_NAMED(DA9062_IRQ_GPI4, 1, "GPI4", IORESOURCE_IRQ), 2458c2ecf20Sopenharmony_ci}; 2468c2ecf20Sopenharmony_ci 2478c2ecf20Sopenharmony_cistatic const struct mfd_cell da9062_devs[] = { 2488c2ecf20Sopenharmony_ci { 2498c2ecf20Sopenharmony_ci .name = "da9062-core", 2508c2ecf20Sopenharmony_ci .num_resources = ARRAY_SIZE(da9062_core_resources), 2518c2ecf20Sopenharmony_ci .resources = da9062_core_resources, 2528c2ecf20Sopenharmony_ci }, 2538c2ecf20Sopenharmony_ci { 2548c2ecf20Sopenharmony_ci .name = "da9062-regulators", 2558c2ecf20Sopenharmony_ci .num_resources = ARRAY_SIZE(da9062_regulators_resources), 2568c2ecf20Sopenharmony_ci .resources = da9062_regulators_resources, 2578c2ecf20Sopenharmony_ci }, 2588c2ecf20Sopenharmony_ci { 2598c2ecf20Sopenharmony_ci .name = "da9062-watchdog", 2608c2ecf20Sopenharmony_ci .num_resources = ARRAY_SIZE(da9062_wdt_resources), 2618c2ecf20Sopenharmony_ci .resources = da9062_wdt_resources, 2628c2ecf20Sopenharmony_ci .of_compatible = "dlg,da9062-watchdog", 2638c2ecf20Sopenharmony_ci }, 2648c2ecf20Sopenharmony_ci { 2658c2ecf20Sopenharmony_ci .name = "da9062-thermal", 2668c2ecf20Sopenharmony_ci .num_resources = ARRAY_SIZE(da9062_thermal_resources), 2678c2ecf20Sopenharmony_ci .resources = da9062_thermal_resources, 2688c2ecf20Sopenharmony_ci .of_compatible = "dlg,da9062-thermal", 2698c2ecf20Sopenharmony_ci }, 2708c2ecf20Sopenharmony_ci { 2718c2ecf20Sopenharmony_ci .name = "da9062-rtc", 2728c2ecf20Sopenharmony_ci .num_resources = ARRAY_SIZE(da9062_rtc_resources), 2738c2ecf20Sopenharmony_ci .resources = da9062_rtc_resources, 2748c2ecf20Sopenharmony_ci .of_compatible = "dlg,da9062-rtc", 2758c2ecf20Sopenharmony_ci }, 2768c2ecf20Sopenharmony_ci { 2778c2ecf20Sopenharmony_ci .name = "da9062-onkey", 2788c2ecf20Sopenharmony_ci .num_resources = ARRAY_SIZE(da9062_onkey_resources), 2798c2ecf20Sopenharmony_ci .resources = da9062_onkey_resources, 2808c2ecf20Sopenharmony_ci .of_compatible = "dlg,da9062-onkey", 2818c2ecf20Sopenharmony_ci }, 2828c2ecf20Sopenharmony_ci { 2838c2ecf20Sopenharmony_ci .name = "da9062-gpio", 2848c2ecf20Sopenharmony_ci .num_resources = ARRAY_SIZE(da9062_gpio_resources), 2858c2ecf20Sopenharmony_ci .resources = da9062_gpio_resources, 2868c2ecf20Sopenharmony_ci .of_compatible = "dlg,da9062-gpio", 2878c2ecf20Sopenharmony_ci }, 2888c2ecf20Sopenharmony_ci}; 2898c2ecf20Sopenharmony_ci 2908c2ecf20Sopenharmony_cistatic int da9062_clear_fault_log(struct da9062 *chip) 2918c2ecf20Sopenharmony_ci{ 2928c2ecf20Sopenharmony_ci int ret; 2938c2ecf20Sopenharmony_ci int fault_log; 2948c2ecf20Sopenharmony_ci 2958c2ecf20Sopenharmony_ci ret = regmap_read(chip->regmap, DA9062AA_FAULT_LOG, &fault_log); 2968c2ecf20Sopenharmony_ci if (ret < 0) 2978c2ecf20Sopenharmony_ci return ret; 2988c2ecf20Sopenharmony_ci 2998c2ecf20Sopenharmony_ci if (fault_log) { 3008c2ecf20Sopenharmony_ci if (fault_log & DA9062AA_TWD_ERROR_MASK) 3018c2ecf20Sopenharmony_ci dev_dbg(chip->dev, "Fault log entry detected: TWD_ERROR\n"); 3028c2ecf20Sopenharmony_ci if (fault_log & DA9062AA_POR_MASK) 3038c2ecf20Sopenharmony_ci dev_dbg(chip->dev, "Fault log entry detected: POR\n"); 3048c2ecf20Sopenharmony_ci if (fault_log & DA9062AA_VDD_FAULT_MASK) 3058c2ecf20Sopenharmony_ci dev_dbg(chip->dev, "Fault log entry detected: VDD_FAULT\n"); 3068c2ecf20Sopenharmony_ci if (fault_log & DA9062AA_VDD_START_MASK) 3078c2ecf20Sopenharmony_ci dev_dbg(chip->dev, "Fault log entry detected: VDD_START\n"); 3088c2ecf20Sopenharmony_ci if (fault_log & DA9062AA_TEMP_CRIT_MASK) 3098c2ecf20Sopenharmony_ci dev_dbg(chip->dev, "Fault log entry detected: TEMP_CRIT\n"); 3108c2ecf20Sopenharmony_ci if (fault_log & DA9062AA_KEY_RESET_MASK) 3118c2ecf20Sopenharmony_ci dev_dbg(chip->dev, "Fault log entry detected: KEY_RESET\n"); 3128c2ecf20Sopenharmony_ci if (fault_log & DA9062AA_NSHUTDOWN_MASK) 3138c2ecf20Sopenharmony_ci dev_dbg(chip->dev, "Fault log entry detected: NSHUTDOWN\n"); 3148c2ecf20Sopenharmony_ci if (fault_log & DA9062AA_WAIT_SHUT_MASK) 3158c2ecf20Sopenharmony_ci dev_dbg(chip->dev, "Fault log entry detected: WAIT_SHUT\n"); 3168c2ecf20Sopenharmony_ci 3178c2ecf20Sopenharmony_ci ret = regmap_write(chip->regmap, DA9062AA_FAULT_LOG, 3188c2ecf20Sopenharmony_ci fault_log); 3198c2ecf20Sopenharmony_ci } 3208c2ecf20Sopenharmony_ci 3218c2ecf20Sopenharmony_ci return ret; 3228c2ecf20Sopenharmony_ci} 3238c2ecf20Sopenharmony_ci 3248c2ecf20Sopenharmony_cistatic int da9062_get_device_type(struct da9062 *chip) 3258c2ecf20Sopenharmony_ci{ 3268c2ecf20Sopenharmony_ci int device_id, variant_id, variant_mrc, variant_vrc; 3278c2ecf20Sopenharmony_ci char *type; 3288c2ecf20Sopenharmony_ci int ret; 3298c2ecf20Sopenharmony_ci 3308c2ecf20Sopenharmony_ci ret = regmap_read(chip->regmap, DA9062AA_DEVICE_ID, &device_id); 3318c2ecf20Sopenharmony_ci if (ret < 0) { 3328c2ecf20Sopenharmony_ci dev_err(chip->dev, "Cannot read chip ID.\n"); 3338c2ecf20Sopenharmony_ci return -EIO; 3348c2ecf20Sopenharmony_ci } 3358c2ecf20Sopenharmony_ci if (device_id != DA9062_PMIC_DEVICE_ID) { 3368c2ecf20Sopenharmony_ci dev_err(chip->dev, "Invalid device ID: 0x%02x\n", device_id); 3378c2ecf20Sopenharmony_ci return -ENODEV; 3388c2ecf20Sopenharmony_ci } 3398c2ecf20Sopenharmony_ci 3408c2ecf20Sopenharmony_ci ret = regmap_read(chip->regmap, DA9062AA_VARIANT_ID, &variant_id); 3418c2ecf20Sopenharmony_ci if (ret < 0) { 3428c2ecf20Sopenharmony_ci dev_err(chip->dev, "Cannot read chip variant id.\n"); 3438c2ecf20Sopenharmony_ci return -EIO; 3448c2ecf20Sopenharmony_ci } 3458c2ecf20Sopenharmony_ci 3468c2ecf20Sopenharmony_ci variant_vrc = (variant_id & DA9062AA_VRC_MASK) >> DA9062AA_VRC_SHIFT; 3478c2ecf20Sopenharmony_ci 3488c2ecf20Sopenharmony_ci switch (variant_vrc) { 3498c2ecf20Sopenharmony_ci case DA9062_PMIC_VARIANT_VRC_DA9061: 3508c2ecf20Sopenharmony_ci type = "DA9061"; 3518c2ecf20Sopenharmony_ci break; 3528c2ecf20Sopenharmony_ci case DA9062_PMIC_VARIANT_VRC_DA9062: 3538c2ecf20Sopenharmony_ci type = "DA9062"; 3548c2ecf20Sopenharmony_ci break; 3558c2ecf20Sopenharmony_ci default: 3568c2ecf20Sopenharmony_ci type = "Unknown"; 3578c2ecf20Sopenharmony_ci break; 3588c2ecf20Sopenharmony_ci } 3598c2ecf20Sopenharmony_ci 3608c2ecf20Sopenharmony_ci dev_info(chip->dev, 3618c2ecf20Sopenharmony_ci "Device detected (device-ID: 0x%02X, var-ID: 0x%02X, %s)\n", 3628c2ecf20Sopenharmony_ci device_id, variant_id, type); 3638c2ecf20Sopenharmony_ci 3648c2ecf20Sopenharmony_ci variant_mrc = (variant_id & DA9062AA_MRC_MASK) >> DA9062AA_MRC_SHIFT; 3658c2ecf20Sopenharmony_ci 3668c2ecf20Sopenharmony_ci if (variant_mrc < DA9062_PMIC_VARIANT_MRC_AA) { 3678c2ecf20Sopenharmony_ci dev_err(chip->dev, 3688c2ecf20Sopenharmony_ci "Cannot support variant MRC: 0x%02X\n", variant_mrc); 3698c2ecf20Sopenharmony_ci return -ENODEV; 3708c2ecf20Sopenharmony_ci } 3718c2ecf20Sopenharmony_ci 3728c2ecf20Sopenharmony_ci return ret; 3738c2ecf20Sopenharmony_ci} 3748c2ecf20Sopenharmony_ci 3758c2ecf20Sopenharmony_cistatic u32 da9062_configure_irq_type(struct da9062 *chip, int irq, u32 *trigger) 3768c2ecf20Sopenharmony_ci{ 3778c2ecf20Sopenharmony_ci u32 irq_type = 0; 3788c2ecf20Sopenharmony_ci struct irq_data *irq_data = irq_get_irq_data(irq); 3798c2ecf20Sopenharmony_ci 3808c2ecf20Sopenharmony_ci if (!irq_data) { 3818c2ecf20Sopenharmony_ci dev_err(chip->dev, "Invalid IRQ: %d\n", irq); 3828c2ecf20Sopenharmony_ci return -EINVAL; 3838c2ecf20Sopenharmony_ci } 3848c2ecf20Sopenharmony_ci *trigger = irqd_get_trigger_type(irq_data); 3858c2ecf20Sopenharmony_ci 3868c2ecf20Sopenharmony_ci switch (*trigger) { 3878c2ecf20Sopenharmony_ci case IRQ_TYPE_LEVEL_HIGH: 3888c2ecf20Sopenharmony_ci irq_type = DA9062_IRQ_HIGH; 3898c2ecf20Sopenharmony_ci break; 3908c2ecf20Sopenharmony_ci case IRQ_TYPE_LEVEL_LOW: 3918c2ecf20Sopenharmony_ci irq_type = DA9062_IRQ_LOW; 3928c2ecf20Sopenharmony_ci break; 3938c2ecf20Sopenharmony_ci default: 3948c2ecf20Sopenharmony_ci dev_warn(chip->dev, "Unsupported IRQ type: %d\n", *trigger); 3958c2ecf20Sopenharmony_ci return -EINVAL; 3968c2ecf20Sopenharmony_ci } 3978c2ecf20Sopenharmony_ci return regmap_update_bits(chip->regmap, DA9062AA_CONFIG_A, 3988c2ecf20Sopenharmony_ci DA9062AA_IRQ_TYPE_MASK, 3998c2ecf20Sopenharmony_ci irq_type << DA9062AA_IRQ_TYPE_SHIFT); 4008c2ecf20Sopenharmony_ci} 4018c2ecf20Sopenharmony_ci 4028c2ecf20Sopenharmony_cistatic const struct regmap_range da9061_aa_readable_ranges[] = { 4038c2ecf20Sopenharmony_ci regmap_reg_range(DA9062AA_PAGE_CON, DA9062AA_STATUS_B), 4048c2ecf20Sopenharmony_ci regmap_reg_range(DA9062AA_STATUS_D, DA9062AA_EVENT_C), 4058c2ecf20Sopenharmony_ci regmap_reg_range(DA9062AA_IRQ_MASK_A, DA9062AA_IRQ_MASK_C), 4068c2ecf20Sopenharmony_ci regmap_reg_range(DA9062AA_CONTROL_A, DA9062AA_GPIO_4), 4078c2ecf20Sopenharmony_ci regmap_reg_range(DA9062AA_GPIO_WKUP_MODE, DA9062AA_GPIO_OUT3_4), 4088c2ecf20Sopenharmony_ci regmap_reg_range(DA9062AA_BUCK1_CONT, DA9062AA_BUCK4_CONT), 4098c2ecf20Sopenharmony_ci regmap_reg_range(DA9062AA_BUCK3_CONT, DA9062AA_BUCK3_CONT), 4108c2ecf20Sopenharmony_ci regmap_reg_range(DA9062AA_LDO1_CONT, DA9062AA_LDO4_CONT), 4118c2ecf20Sopenharmony_ci regmap_reg_range(DA9062AA_DVC_1, DA9062AA_DVC_1), 4128c2ecf20Sopenharmony_ci regmap_reg_range(DA9062AA_SEQ, DA9062AA_ID_4_3), 4138c2ecf20Sopenharmony_ci regmap_reg_range(DA9062AA_ID_12_11, DA9062AA_ID_16_15), 4148c2ecf20Sopenharmony_ci regmap_reg_range(DA9062AA_ID_22_21, DA9062AA_ID_32_31), 4158c2ecf20Sopenharmony_ci regmap_reg_range(DA9062AA_SEQ_A, DA9062AA_WAIT), 4168c2ecf20Sopenharmony_ci regmap_reg_range(DA9062AA_RESET, DA9062AA_BUCK_ILIM_C), 4178c2ecf20Sopenharmony_ci regmap_reg_range(DA9062AA_BUCK1_CFG, DA9062AA_BUCK3_CFG), 4188c2ecf20Sopenharmony_ci regmap_reg_range(DA9062AA_VBUCK1_A, DA9062AA_VBUCK4_A), 4198c2ecf20Sopenharmony_ci regmap_reg_range(DA9062AA_VBUCK3_A, DA9062AA_VBUCK3_A), 4208c2ecf20Sopenharmony_ci regmap_reg_range(DA9062AA_VLDO1_A, DA9062AA_VLDO4_A), 4218c2ecf20Sopenharmony_ci regmap_reg_range(DA9062AA_CONFIG_A, DA9062AA_CONFIG_A), 4228c2ecf20Sopenharmony_ci regmap_reg_range(DA9062AA_VBUCK1_B, DA9062AA_VBUCK4_B), 4238c2ecf20Sopenharmony_ci regmap_reg_range(DA9062AA_VBUCK3_B, DA9062AA_VBUCK3_B), 4248c2ecf20Sopenharmony_ci regmap_reg_range(DA9062AA_VLDO1_B, DA9062AA_VLDO4_B), 4258c2ecf20Sopenharmony_ci regmap_reg_range(DA9062AA_INTERFACE, DA9062AA_CONFIG_E), 4268c2ecf20Sopenharmony_ci regmap_reg_range(DA9062AA_CONFIG_G, DA9062AA_CONFIG_K), 4278c2ecf20Sopenharmony_ci regmap_reg_range(DA9062AA_CONFIG_M, DA9062AA_CONFIG_M), 4288c2ecf20Sopenharmony_ci regmap_reg_range(DA9062AA_GP_ID_0, DA9062AA_GP_ID_19), 4298c2ecf20Sopenharmony_ci regmap_reg_range(DA9062AA_DEVICE_ID, DA9062AA_CONFIG_ID), 4308c2ecf20Sopenharmony_ci}; 4318c2ecf20Sopenharmony_ci 4328c2ecf20Sopenharmony_cistatic const struct regmap_range da9061_aa_writeable_ranges[] = { 4338c2ecf20Sopenharmony_ci regmap_reg_range(DA9062AA_PAGE_CON, DA9062AA_PAGE_CON), 4348c2ecf20Sopenharmony_ci regmap_reg_range(DA9062AA_FAULT_LOG, DA9062AA_EVENT_C), 4358c2ecf20Sopenharmony_ci regmap_reg_range(DA9062AA_IRQ_MASK_A, DA9062AA_IRQ_MASK_C), 4368c2ecf20Sopenharmony_ci regmap_reg_range(DA9062AA_CONTROL_A, DA9062AA_GPIO_4), 4378c2ecf20Sopenharmony_ci regmap_reg_range(DA9062AA_GPIO_WKUP_MODE, DA9062AA_GPIO_OUT3_4), 4388c2ecf20Sopenharmony_ci regmap_reg_range(DA9062AA_BUCK1_CONT, DA9062AA_BUCK4_CONT), 4398c2ecf20Sopenharmony_ci regmap_reg_range(DA9062AA_BUCK3_CONT, DA9062AA_BUCK3_CONT), 4408c2ecf20Sopenharmony_ci regmap_reg_range(DA9062AA_LDO1_CONT, DA9062AA_LDO4_CONT), 4418c2ecf20Sopenharmony_ci regmap_reg_range(DA9062AA_DVC_1, DA9062AA_DVC_1), 4428c2ecf20Sopenharmony_ci regmap_reg_range(DA9062AA_SEQ, DA9062AA_ID_4_3), 4438c2ecf20Sopenharmony_ci regmap_reg_range(DA9062AA_ID_12_11, DA9062AA_ID_16_15), 4448c2ecf20Sopenharmony_ci regmap_reg_range(DA9062AA_ID_22_21, DA9062AA_ID_32_31), 4458c2ecf20Sopenharmony_ci regmap_reg_range(DA9062AA_SEQ_A, DA9062AA_WAIT), 4468c2ecf20Sopenharmony_ci regmap_reg_range(DA9062AA_RESET, DA9062AA_BUCK_ILIM_C), 4478c2ecf20Sopenharmony_ci regmap_reg_range(DA9062AA_BUCK1_CFG, DA9062AA_BUCK3_CFG), 4488c2ecf20Sopenharmony_ci regmap_reg_range(DA9062AA_VBUCK1_A, DA9062AA_VBUCK4_A), 4498c2ecf20Sopenharmony_ci regmap_reg_range(DA9062AA_VBUCK3_A, DA9062AA_VBUCK3_A), 4508c2ecf20Sopenharmony_ci regmap_reg_range(DA9062AA_VLDO1_A, DA9062AA_VLDO4_A), 4518c2ecf20Sopenharmony_ci regmap_reg_range(DA9062AA_CONFIG_A, DA9062AA_CONFIG_A), 4528c2ecf20Sopenharmony_ci regmap_reg_range(DA9062AA_VBUCK1_B, DA9062AA_VBUCK4_B), 4538c2ecf20Sopenharmony_ci regmap_reg_range(DA9062AA_VBUCK3_B, DA9062AA_VBUCK3_B), 4548c2ecf20Sopenharmony_ci regmap_reg_range(DA9062AA_VLDO1_B, DA9062AA_VLDO4_B), 4558c2ecf20Sopenharmony_ci regmap_reg_range(DA9062AA_GP_ID_0, DA9062AA_GP_ID_19), 4568c2ecf20Sopenharmony_ci}; 4578c2ecf20Sopenharmony_ci 4588c2ecf20Sopenharmony_cistatic const struct regmap_range da9061_aa_volatile_ranges[] = { 4598c2ecf20Sopenharmony_ci regmap_reg_range(DA9062AA_PAGE_CON, DA9062AA_STATUS_B), 4608c2ecf20Sopenharmony_ci regmap_reg_range(DA9062AA_STATUS_D, DA9062AA_EVENT_C), 4618c2ecf20Sopenharmony_ci regmap_reg_range(DA9062AA_CONTROL_A, DA9062AA_CONTROL_B), 4628c2ecf20Sopenharmony_ci regmap_reg_range(DA9062AA_CONTROL_E, DA9062AA_CONTROL_F), 4638c2ecf20Sopenharmony_ci regmap_reg_range(DA9062AA_BUCK1_CONT, DA9062AA_BUCK4_CONT), 4648c2ecf20Sopenharmony_ci regmap_reg_range(DA9062AA_BUCK3_CONT, DA9062AA_BUCK3_CONT), 4658c2ecf20Sopenharmony_ci regmap_reg_range(DA9062AA_LDO1_CONT, DA9062AA_LDO4_CONT), 4668c2ecf20Sopenharmony_ci regmap_reg_range(DA9062AA_DVC_1, DA9062AA_DVC_1), 4678c2ecf20Sopenharmony_ci regmap_reg_range(DA9062AA_SEQ, DA9062AA_SEQ), 4688c2ecf20Sopenharmony_ci}; 4698c2ecf20Sopenharmony_ci 4708c2ecf20Sopenharmony_cistatic const struct regmap_access_table da9061_aa_readable_table = { 4718c2ecf20Sopenharmony_ci .yes_ranges = da9061_aa_readable_ranges, 4728c2ecf20Sopenharmony_ci .n_yes_ranges = ARRAY_SIZE(da9061_aa_readable_ranges), 4738c2ecf20Sopenharmony_ci}; 4748c2ecf20Sopenharmony_ci 4758c2ecf20Sopenharmony_cistatic const struct regmap_access_table da9061_aa_writeable_table = { 4768c2ecf20Sopenharmony_ci .yes_ranges = da9061_aa_writeable_ranges, 4778c2ecf20Sopenharmony_ci .n_yes_ranges = ARRAY_SIZE(da9061_aa_writeable_ranges), 4788c2ecf20Sopenharmony_ci}; 4798c2ecf20Sopenharmony_ci 4808c2ecf20Sopenharmony_cistatic const struct regmap_access_table da9061_aa_volatile_table = { 4818c2ecf20Sopenharmony_ci .yes_ranges = da9061_aa_volatile_ranges, 4828c2ecf20Sopenharmony_ci .n_yes_ranges = ARRAY_SIZE(da9061_aa_volatile_ranges), 4838c2ecf20Sopenharmony_ci}; 4848c2ecf20Sopenharmony_ci 4858c2ecf20Sopenharmony_cistatic const struct regmap_range_cfg da9061_range_cfg[] = { 4868c2ecf20Sopenharmony_ci { 4878c2ecf20Sopenharmony_ci .range_min = DA9062AA_PAGE_CON, 4888c2ecf20Sopenharmony_ci .range_max = DA9062AA_CONFIG_ID, 4898c2ecf20Sopenharmony_ci .selector_reg = DA9062AA_PAGE_CON, 4908c2ecf20Sopenharmony_ci .selector_mask = 1 << DA9062_I2C_PAGE_SEL_SHIFT, 4918c2ecf20Sopenharmony_ci .selector_shift = DA9062_I2C_PAGE_SEL_SHIFT, 4928c2ecf20Sopenharmony_ci .window_start = 0, 4938c2ecf20Sopenharmony_ci .window_len = 256, 4948c2ecf20Sopenharmony_ci } 4958c2ecf20Sopenharmony_ci}; 4968c2ecf20Sopenharmony_ci 4978c2ecf20Sopenharmony_cistatic struct regmap_config da9061_regmap_config = { 4988c2ecf20Sopenharmony_ci .reg_bits = 8, 4998c2ecf20Sopenharmony_ci .val_bits = 8, 5008c2ecf20Sopenharmony_ci .ranges = da9061_range_cfg, 5018c2ecf20Sopenharmony_ci .num_ranges = ARRAY_SIZE(da9061_range_cfg), 5028c2ecf20Sopenharmony_ci .max_register = DA9062AA_CONFIG_ID, 5038c2ecf20Sopenharmony_ci .cache_type = REGCACHE_RBTREE, 5048c2ecf20Sopenharmony_ci .rd_table = &da9061_aa_readable_table, 5058c2ecf20Sopenharmony_ci .wr_table = &da9061_aa_writeable_table, 5068c2ecf20Sopenharmony_ci .volatile_table = &da9061_aa_volatile_table, 5078c2ecf20Sopenharmony_ci}; 5088c2ecf20Sopenharmony_ci 5098c2ecf20Sopenharmony_cistatic const struct regmap_range da9062_aa_readable_ranges[] = { 5108c2ecf20Sopenharmony_ci regmap_reg_range(DA9062AA_PAGE_CON, DA9062AA_STATUS_B), 5118c2ecf20Sopenharmony_ci regmap_reg_range(DA9062AA_STATUS_D, DA9062AA_EVENT_C), 5128c2ecf20Sopenharmony_ci regmap_reg_range(DA9062AA_IRQ_MASK_A, DA9062AA_IRQ_MASK_C), 5138c2ecf20Sopenharmony_ci regmap_reg_range(DA9062AA_CONTROL_A, DA9062AA_GPIO_4), 5148c2ecf20Sopenharmony_ci regmap_reg_range(DA9062AA_GPIO_WKUP_MODE, DA9062AA_BUCK4_CONT), 5158c2ecf20Sopenharmony_ci regmap_reg_range(DA9062AA_BUCK3_CONT, DA9062AA_BUCK3_CONT), 5168c2ecf20Sopenharmony_ci regmap_reg_range(DA9062AA_LDO1_CONT, DA9062AA_LDO4_CONT), 5178c2ecf20Sopenharmony_ci regmap_reg_range(DA9062AA_DVC_1, DA9062AA_DVC_1), 5188c2ecf20Sopenharmony_ci regmap_reg_range(DA9062AA_COUNT_S, DA9062AA_SECOND_D), 5198c2ecf20Sopenharmony_ci regmap_reg_range(DA9062AA_SEQ, DA9062AA_ID_4_3), 5208c2ecf20Sopenharmony_ci regmap_reg_range(DA9062AA_ID_12_11, DA9062AA_ID_16_15), 5218c2ecf20Sopenharmony_ci regmap_reg_range(DA9062AA_ID_22_21, DA9062AA_ID_32_31), 5228c2ecf20Sopenharmony_ci regmap_reg_range(DA9062AA_SEQ_A, DA9062AA_BUCK3_CFG), 5238c2ecf20Sopenharmony_ci regmap_reg_range(DA9062AA_VBUCK2_A, DA9062AA_VBUCK4_A), 5248c2ecf20Sopenharmony_ci regmap_reg_range(DA9062AA_VBUCK3_A, DA9062AA_VBUCK3_A), 5258c2ecf20Sopenharmony_ci regmap_reg_range(DA9062AA_VLDO1_A, DA9062AA_VLDO4_A), 5268c2ecf20Sopenharmony_ci regmap_reg_range(DA9062AA_VBUCK2_B, DA9062AA_VBUCK4_B), 5278c2ecf20Sopenharmony_ci regmap_reg_range(DA9062AA_VBUCK3_B, DA9062AA_VBUCK3_B), 5288c2ecf20Sopenharmony_ci regmap_reg_range(DA9062AA_VLDO1_B, DA9062AA_VLDO4_B), 5298c2ecf20Sopenharmony_ci regmap_reg_range(DA9062AA_BBAT_CONT, DA9062AA_BBAT_CONT), 5308c2ecf20Sopenharmony_ci regmap_reg_range(DA9062AA_INTERFACE, DA9062AA_CONFIG_E), 5318c2ecf20Sopenharmony_ci regmap_reg_range(DA9062AA_CONFIG_G, DA9062AA_CONFIG_K), 5328c2ecf20Sopenharmony_ci regmap_reg_range(DA9062AA_CONFIG_M, DA9062AA_CONFIG_M), 5338c2ecf20Sopenharmony_ci regmap_reg_range(DA9062AA_TRIM_CLDR, DA9062AA_GP_ID_19), 5348c2ecf20Sopenharmony_ci regmap_reg_range(DA9062AA_DEVICE_ID, DA9062AA_CONFIG_ID), 5358c2ecf20Sopenharmony_ci}; 5368c2ecf20Sopenharmony_ci 5378c2ecf20Sopenharmony_cistatic const struct regmap_range da9062_aa_writeable_ranges[] = { 5388c2ecf20Sopenharmony_ci regmap_reg_range(DA9062AA_PAGE_CON, DA9062AA_PAGE_CON), 5398c2ecf20Sopenharmony_ci regmap_reg_range(DA9062AA_FAULT_LOG, DA9062AA_EVENT_C), 5408c2ecf20Sopenharmony_ci regmap_reg_range(DA9062AA_IRQ_MASK_A, DA9062AA_IRQ_MASK_C), 5418c2ecf20Sopenharmony_ci regmap_reg_range(DA9062AA_CONTROL_A, DA9062AA_GPIO_4), 5428c2ecf20Sopenharmony_ci regmap_reg_range(DA9062AA_GPIO_WKUP_MODE, DA9062AA_BUCK4_CONT), 5438c2ecf20Sopenharmony_ci regmap_reg_range(DA9062AA_BUCK3_CONT, DA9062AA_BUCK3_CONT), 5448c2ecf20Sopenharmony_ci regmap_reg_range(DA9062AA_LDO1_CONT, DA9062AA_LDO4_CONT), 5458c2ecf20Sopenharmony_ci regmap_reg_range(DA9062AA_DVC_1, DA9062AA_DVC_1), 5468c2ecf20Sopenharmony_ci regmap_reg_range(DA9062AA_COUNT_S, DA9062AA_ALARM_Y), 5478c2ecf20Sopenharmony_ci regmap_reg_range(DA9062AA_SEQ, DA9062AA_ID_4_3), 5488c2ecf20Sopenharmony_ci regmap_reg_range(DA9062AA_ID_12_11, DA9062AA_ID_16_15), 5498c2ecf20Sopenharmony_ci regmap_reg_range(DA9062AA_ID_22_21, DA9062AA_ID_32_31), 5508c2ecf20Sopenharmony_ci regmap_reg_range(DA9062AA_SEQ_A, DA9062AA_BUCK3_CFG), 5518c2ecf20Sopenharmony_ci regmap_reg_range(DA9062AA_VBUCK2_A, DA9062AA_VBUCK4_A), 5528c2ecf20Sopenharmony_ci regmap_reg_range(DA9062AA_VBUCK3_A, DA9062AA_VBUCK3_A), 5538c2ecf20Sopenharmony_ci regmap_reg_range(DA9062AA_VLDO1_A, DA9062AA_VLDO4_A), 5548c2ecf20Sopenharmony_ci regmap_reg_range(DA9062AA_VBUCK2_B, DA9062AA_VBUCK4_B), 5558c2ecf20Sopenharmony_ci regmap_reg_range(DA9062AA_VBUCK3_B, DA9062AA_VBUCK3_B), 5568c2ecf20Sopenharmony_ci regmap_reg_range(DA9062AA_VLDO1_B, DA9062AA_VLDO4_B), 5578c2ecf20Sopenharmony_ci regmap_reg_range(DA9062AA_BBAT_CONT, DA9062AA_BBAT_CONT), 5588c2ecf20Sopenharmony_ci regmap_reg_range(DA9062AA_GP_ID_0, DA9062AA_GP_ID_19), 5598c2ecf20Sopenharmony_ci}; 5608c2ecf20Sopenharmony_ci 5618c2ecf20Sopenharmony_cistatic const struct regmap_range da9062_aa_volatile_ranges[] = { 5628c2ecf20Sopenharmony_ci regmap_reg_range(DA9062AA_PAGE_CON, DA9062AA_STATUS_B), 5638c2ecf20Sopenharmony_ci regmap_reg_range(DA9062AA_STATUS_D, DA9062AA_EVENT_C), 5648c2ecf20Sopenharmony_ci regmap_reg_range(DA9062AA_CONTROL_A, DA9062AA_CONTROL_B), 5658c2ecf20Sopenharmony_ci regmap_reg_range(DA9062AA_CONTROL_E, DA9062AA_CONTROL_F), 5668c2ecf20Sopenharmony_ci regmap_reg_range(DA9062AA_BUCK2_CONT, DA9062AA_BUCK4_CONT), 5678c2ecf20Sopenharmony_ci regmap_reg_range(DA9062AA_BUCK3_CONT, DA9062AA_BUCK3_CONT), 5688c2ecf20Sopenharmony_ci regmap_reg_range(DA9062AA_LDO1_CONT, DA9062AA_LDO4_CONT), 5698c2ecf20Sopenharmony_ci regmap_reg_range(DA9062AA_DVC_1, DA9062AA_DVC_1), 5708c2ecf20Sopenharmony_ci regmap_reg_range(DA9062AA_COUNT_S, DA9062AA_SECOND_D), 5718c2ecf20Sopenharmony_ci regmap_reg_range(DA9062AA_SEQ, DA9062AA_SEQ), 5728c2ecf20Sopenharmony_ci regmap_reg_range(DA9062AA_EN_32K, DA9062AA_EN_32K), 5738c2ecf20Sopenharmony_ci}; 5748c2ecf20Sopenharmony_ci 5758c2ecf20Sopenharmony_cistatic const struct regmap_access_table da9062_aa_readable_table = { 5768c2ecf20Sopenharmony_ci .yes_ranges = da9062_aa_readable_ranges, 5778c2ecf20Sopenharmony_ci .n_yes_ranges = ARRAY_SIZE(da9062_aa_readable_ranges), 5788c2ecf20Sopenharmony_ci}; 5798c2ecf20Sopenharmony_ci 5808c2ecf20Sopenharmony_cistatic const struct regmap_access_table da9062_aa_writeable_table = { 5818c2ecf20Sopenharmony_ci .yes_ranges = da9062_aa_writeable_ranges, 5828c2ecf20Sopenharmony_ci .n_yes_ranges = ARRAY_SIZE(da9062_aa_writeable_ranges), 5838c2ecf20Sopenharmony_ci}; 5848c2ecf20Sopenharmony_ci 5858c2ecf20Sopenharmony_cistatic const struct regmap_access_table da9062_aa_volatile_table = { 5868c2ecf20Sopenharmony_ci .yes_ranges = da9062_aa_volatile_ranges, 5878c2ecf20Sopenharmony_ci .n_yes_ranges = ARRAY_SIZE(da9062_aa_volatile_ranges), 5888c2ecf20Sopenharmony_ci}; 5898c2ecf20Sopenharmony_ci 5908c2ecf20Sopenharmony_cistatic const struct regmap_range_cfg da9062_range_cfg[] = { 5918c2ecf20Sopenharmony_ci { 5928c2ecf20Sopenharmony_ci .range_min = DA9062AA_PAGE_CON, 5938c2ecf20Sopenharmony_ci .range_max = DA9062AA_CONFIG_ID, 5948c2ecf20Sopenharmony_ci .selector_reg = DA9062AA_PAGE_CON, 5958c2ecf20Sopenharmony_ci .selector_mask = 1 << DA9062_I2C_PAGE_SEL_SHIFT, 5968c2ecf20Sopenharmony_ci .selector_shift = DA9062_I2C_PAGE_SEL_SHIFT, 5978c2ecf20Sopenharmony_ci .window_start = 0, 5988c2ecf20Sopenharmony_ci .window_len = 256, 5998c2ecf20Sopenharmony_ci } 6008c2ecf20Sopenharmony_ci}; 6018c2ecf20Sopenharmony_ci 6028c2ecf20Sopenharmony_cistatic struct regmap_config da9062_regmap_config = { 6038c2ecf20Sopenharmony_ci .reg_bits = 8, 6048c2ecf20Sopenharmony_ci .val_bits = 8, 6058c2ecf20Sopenharmony_ci .ranges = da9062_range_cfg, 6068c2ecf20Sopenharmony_ci .num_ranges = ARRAY_SIZE(da9062_range_cfg), 6078c2ecf20Sopenharmony_ci .max_register = DA9062AA_CONFIG_ID, 6088c2ecf20Sopenharmony_ci .cache_type = REGCACHE_RBTREE, 6098c2ecf20Sopenharmony_ci .rd_table = &da9062_aa_readable_table, 6108c2ecf20Sopenharmony_ci .wr_table = &da9062_aa_writeable_table, 6118c2ecf20Sopenharmony_ci .volatile_table = &da9062_aa_volatile_table, 6128c2ecf20Sopenharmony_ci}; 6138c2ecf20Sopenharmony_ci 6148c2ecf20Sopenharmony_cistatic const struct of_device_id da9062_dt_ids[] = { 6158c2ecf20Sopenharmony_ci { .compatible = "dlg,da9061", .data = (void *)COMPAT_TYPE_DA9061, }, 6168c2ecf20Sopenharmony_ci { .compatible = "dlg,da9062", .data = (void *)COMPAT_TYPE_DA9062, }, 6178c2ecf20Sopenharmony_ci { } 6188c2ecf20Sopenharmony_ci}; 6198c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(of, da9062_dt_ids); 6208c2ecf20Sopenharmony_ci 6218c2ecf20Sopenharmony_cistatic int da9062_i2c_probe(struct i2c_client *i2c, 6228c2ecf20Sopenharmony_ci const struct i2c_device_id *id) 6238c2ecf20Sopenharmony_ci{ 6248c2ecf20Sopenharmony_ci struct da9062 *chip; 6258c2ecf20Sopenharmony_ci const struct of_device_id *match; 6268c2ecf20Sopenharmony_ci unsigned int irq_base; 6278c2ecf20Sopenharmony_ci const struct mfd_cell *cell; 6288c2ecf20Sopenharmony_ci const struct regmap_irq_chip *irq_chip; 6298c2ecf20Sopenharmony_ci const struct regmap_config *config; 6308c2ecf20Sopenharmony_ci int cell_num; 6318c2ecf20Sopenharmony_ci u32 trigger_type = 0; 6328c2ecf20Sopenharmony_ci int ret; 6338c2ecf20Sopenharmony_ci 6348c2ecf20Sopenharmony_ci chip = devm_kzalloc(&i2c->dev, sizeof(*chip), GFP_KERNEL); 6358c2ecf20Sopenharmony_ci if (!chip) 6368c2ecf20Sopenharmony_ci return -ENOMEM; 6378c2ecf20Sopenharmony_ci 6388c2ecf20Sopenharmony_ci if (i2c->dev.of_node) { 6398c2ecf20Sopenharmony_ci match = of_match_node(da9062_dt_ids, i2c->dev.of_node); 6408c2ecf20Sopenharmony_ci if (!match) 6418c2ecf20Sopenharmony_ci return -EINVAL; 6428c2ecf20Sopenharmony_ci 6438c2ecf20Sopenharmony_ci chip->chip_type = (uintptr_t)match->data; 6448c2ecf20Sopenharmony_ci } else { 6458c2ecf20Sopenharmony_ci chip->chip_type = id->driver_data; 6468c2ecf20Sopenharmony_ci } 6478c2ecf20Sopenharmony_ci 6488c2ecf20Sopenharmony_ci i2c_set_clientdata(i2c, chip); 6498c2ecf20Sopenharmony_ci chip->dev = &i2c->dev; 6508c2ecf20Sopenharmony_ci 6518c2ecf20Sopenharmony_ci if (!i2c->irq) { 6528c2ecf20Sopenharmony_ci dev_err(chip->dev, "No IRQ configured\n"); 6538c2ecf20Sopenharmony_ci return -EINVAL; 6548c2ecf20Sopenharmony_ci } 6558c2ecf20Sopenharmony_ci 6568c2ecf20Sopenharmony_ci switch (chip->chip_type) { 6578c2ecf20Sopenharmony_ci case COMPAT_TYPE_DA9061: 6588c2ecf20Sopenharmony_ci cell = da9061_devs; 6598c2ecf20Sopenharmony_ci cell_num = ARRAY_SIZE(da9061_devs); 6608c2ecf20Sopenharmony_ci irq_chip = &da9061_irq_chip; 6618c2ecf20Sopenharmony_ci config = &da9061_regmap_config; 6628c2ecf20Sopenharmony_ci break; 6638c2ecf20Sopenharmony_ci case COMPAT_TYPE_DA9062: 6648c2ecf20Sopenharmony_ci cell = da9062_devs; 6658c2ecf20Sopenharmony_ci cell_num = ARRAY_SIZE(da9062_devs); 6668c2ecf20Sopenharmony_ci irq_chip = &da9062_irq_chip; 6678c2ecf20Sopenharmony_ci config = &da9062_regmap_config; 6688c2ecf20Sopenharmony_ci break; 6698c2ecf20Sopenharmony_ci default: 6708c2ecf20Sopenharmony_ci dev_err(chip->dev, "Unrecognised chip type\n"); 6718c2ecf20Sopenharmony_ci return -ENODEV; 6728c2ecf20Sopenharmony_ci } 6738c2ecf20Sopenharmony_ci 6748c2ecf20Sopenharmony_ci chip->regmap = devm_regmap_init_i2c(i2c, config); 6758c2ecf20Sopenharmony_ci if (IS_ERR(chip->regmap)) { 6768c2ecf20Sopenharmony_ci ret = PTR_ERR(chip->regmap); 6778c2ecf20Sopenharmony_ci dev_err(chip->dev, "Failed to allocate register map: %d\n", 6788c2ecf20Sopenharmony_ci ret); 6798c2ecf20Sopenharmony_ci return ret; 6808c2ecf20Sopenharmony_ci } 6818c2ecf20Sopenharmony_ci 6828c2ecf20Sopenharmony_ci ret = da9062_clear_fault_log(chip); 6838c2ecf20Sopenharmony_ci if (ret < 0) 6848c2ecf20Sopenharmony_ci dev_warn(chip->dev, "Cannot clear fault log\n"); 6858c2ecf20Sopenharmony_ci 6868c2ecf20Sopenharmony_ci ret = da9062_get_device_type(chip); 6878c2ecf20Sopenharmony_ci if (ret) 6888c2ecf20Sopenharmony_ci return ret; 6898c2ecf20Sopenharmony_ci 6908c2ecf20Sopenharmony_ci ret = da9062_configure_irq_type(chip, i2c->irq, &trigger_type); 6918c2ecf20Sopenharmony_ci if (ret < 0) { 6928c2ecf20Sopenharmony_ci dev_err(chip->dev, "Failed to configure IRQ type\n"); 6938c2ecf20Sopenharmony_ci return ret; 6948c2ecf20Sopenharmony_ci } 6958c2ecf20Sopenharmony_ci 6968c2ecf20Sopenharmony_ci ret = regmap_add_irq_chip(chip->regmap, i2c->irq, 6978c2ecf20Sopenharmony_ci trigger_type | IRQF_SHARED | IRQF_ONESHOT, 6988c2ecf20Sopenharmony_ci -1, irq_chip, &chip->regmap_irq); 6998c2ecf20Sopenharmony_ci if (ret) { 7008c2ecf20Sopenharmony_ci dev_err(chip->dev, "Failed to request IRQ %d: %d\n", 7018c2ecf20Sopenharmony_ci i2c->irq, ret); 7028c2ecf20Sopenharmony_ci return ret; 7038c2ecf20Sopenharmony_ci } 7048c2ecf20Sopenharmony_ci 7058c2ecf20Sopenharmony_ci irq_base = regmap_irq_chip_get_base(chip->regmap_irq); 7068c2ecf20Sopenharmony_ci 7078c2ecf20Sopenharmony_ci ret = mfd_add_devices(chip->dev, PLATFORM_DEVID_NONE, cell, 7088c2ecf20Sopenharmony_ci cell_num, NULL, irq_base, 7098c2ecf20Sopenharmony_ci NULL); 7108c2ecf20Sopenharmony_ci if (ret) { 7118c2ecf20Sopenharmony_ci dev_err(chip->dev, "Cannot register child devices\n"); 7128c2ecf20Sopenharmony_ci regmap_del_irq_chip(i2c->irq, chip->regmap_irq); 7138c2ecf20Sopenharmony_ci return ret; 7148c2ecf20Sopenharmony_ci } 7158c2ecf20Sopenharmony_ci 7168c2ecf20Sopenharmony_ci return ret; 7178c2ecf20Sopenharmony_ci} 7188c2ecf20Sopenharmony_ci 7198c2ecf20Sopenharmony_cistatic int da9062_i2c_remove(struct i2c_client *i2c) 7208c2ecf20Sopenharmony_ci{ 7218c2ecf20Sopenharmony_ci struct da9062 *chip = i2c_get_clientdata(i2c); 7228c2ecf20Sopenharmony_ci 7238c2ecf20Sopenharmony_ci mfd_remove_devices(chip->dev); 7248c2ecf20Sopenharmony_ci regmap_del_irq_chip(i2c->irq, chip->regmap_irq); 7258c2ecf20Sopenharmony_ci 7268c2ecf20Sopenharmony_ci return 0; 7278c2ecf20Sopenharmony_ci} 7288c2ecf20Sopenharmony_ci 7298c2ecf20Sopenharmony_cistatic const struct i2c_device_id da9062_i2c_id[] = { 7308c2ecf20Sopenharmony_ci { "da9061", COMPAT_TYPE_DA9061 }, 7318c2ecf20Sopenharmony_ci { "da9062", COMPAT_TYPE_DA9062 }, 7328c2ecf20Sopenharmony_ci { }, 7338c2ecf20Sopenharmony_ci}; 7348c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(i2c, da9062_i2c_id); 7358c2ecf20Sopenharmony_ci 7368c2ecf20Sopenharmony_cistatic struct i2c_driver da9062_i2c_driver = { 7378c2ecf20Sopenharmony_ci .driver = { 7388c2ecf20Sopenharmony_ci .name = "da9062", 7398c2ecf20Sopenharmony_ci .of_match_table = of_match_ptr(da9062_dt_ids), 7408c2ecf20Sopenharmony_ci }, 7418c2ecf20Sopenharmony_ci .probe = da9062_i2c_probe, 7428c2ecf20Sopenharmony_ci .remove = da9062_i2c_remove, 7438c2ecf20Sopenharmony_ci .id_table = da9062_i2c_id, 7448c2ecf20Sopenharmony_ci}; 7458c2ecf20Sopenharmony_ci 7468c2ecf20Sopenharmony_cimodule_i2c_driver(da9062_i2c_driver); 7478c2ecf20Sopenharmony_ci 7488c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("Core device driver for Dialog DA9061 and DA9062"); 7498c2ecf20Sopenharmony_ciMODULE_AUTHOR("Steve Twiss <stwiss.opensource@diasemi.com>"); 7508c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL"); 751