18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Base driver for Maxim MAX8925 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright (C) 2009-2010 Marvell International Ltd. 68c2ecf20Sopenharmony_ci * Haojian Zhuang <haojian.zhuang@marvell.com> 78c2ecf20Sopenharmony_ci */ 88c2ecf20Sopenharmony_ci 98c2ecf20Sopenharmony_ci#include <linux/kernel.h> 108c2ecf20Sopenharmony_ci#include <linux/init.h> 118c2ecf20Sopenharmony_ci#include <linux/i2c.h> 128c2ecf20Sopenharmony_ci#include <linux/irq.h> 138c2ecf20Sopenharmony_ci#include <linux/interrupt.h> 148c2ecf20Sopenharmony_ci#include <linux/irqdomain.h> 158c2ecf20Sopenharmony_ci#include <linux/platform_device.h> 168c2ecf20Sopenharmony_ci#include <linux/regulator/machine.h> 178c2ecf20Sopenharmony_ci#include <linux/mfd/core.h> 188c2ecf20Sopenharmony_ci#include <linux/mfd/max8925.h> 198c2ecf20Sopenharmony_ci#include <linux/of.h> 208c2ecf20Sopenharmony_ci#include <linux/of_platform.h> 218c2ecf20Sopenharmony_ci 228c2ecf20Sopenharmony_cistatic struct resource bk_resources[] = { 238c2ecf20Sopenharmony_ci { 0x84, 0x84, "mode control", IORESOURCE_REG, }, 248c2ecf20Sopenharmony_ci { 0x85, 0x85, "control", IORESOURCE_REG, }, 258c2ecf20Sopenharmony_ci}; 268c2ecf20Sopenharmony_ci 278c2ecf20Sopenharmony_cistatic struct mfd_cell bk_devs[] = { 288c2ecf20Sopenharmony_ci { 298c2ecf20Sopenharmony_ci .name = "max8925-backlight", 308c2ecf20Sopenharmony_ci .num_resources = ARRAY_SIZE(bk_resources), 318c2ecf20Sopenharmony_ci .resources = &bk_resources[0], 328c2ecf20Sopenharmony_ci .id = -1, 338c2ecf20Sopenharmony_ci }, 348c2ecf20Sopenharmony_ci}; 358c2ecf20Sopenharmony_ci 368c2ecf20Sopenharmony_cistatic struct resource touch_resources[] = { 378c2ecf20Sopenharmony_ci { 388c2ecf20Sopenharmony_ci .name = "max8925-tsc", 398c2ecf20Sopenharmony_ci .start = MAX8925_TSC_IRQ, 408c2ecf20Sopenharmony_ci .end = MAX8925_ADC_RES_END, 418c2ecf20Sopenharmony_ci .flags = IORESOURCE_REG, 428c2ecf20Sopenharmony_ci }, 438c2ecf20Sopenharmony_ci}; 448c2ecf20Sopenharmony_ci 458c2ecf20Sopenharmony_cistatic const struct mfd_cell touch_devs[] = { 468c2ecf20Sopenharmony_ci { 478c2ecf20Sopenharmony_ci .name = "max8925-touch", 488c2ecf20Sopenharmony_ci .num_resources = 1, 498c2ecf20Sopenharmony_ci .resources = &touch_resources[0], 508c2ecf20Sopenharmony_ci .id = -1, 518c2ecf20Sopenharmony_ci }, 528c2ecf20Sopenharmony_ci}; 538c2ecf20Sopenharmony_ci 548c2ecf20Sopenharmony_cistatic struct resource power_supply_resources[] = { 558c2ecf20Sopenharmony_ci { 568c2ecf20Sopenharmony_ci .name = "max8925-power", 578c2ecf20Sopenharmony_ci .start = MAX8925_CHG_IRQ1, 588c2ecf20Sopenharmony_ci .end = MAX8925_CHG_IRQ1_MASK, 598c2ecf20Sopenharmony_ci .flags = IORESOURCE_REG, 608c2ecf20Sopenharmony_ci }, 618c2ecf20Sopenharmony_ci}; 628c2ecf20Sopenharmony_ci 638c2ecf20Sopenharmony_cistatic const struct mfd_cell power_devs[] = { 648c2ecf20Sopenharmony_ci { 658c2ecf20Sopenharmony_ci .name = "max8925-power", 668c2ecf20Sopenharmony_ci .num_resources = 1, 678c2ecf20Sopenharmony_ci .resources = &power_supply_resources[0], 688c2ecf20Sopenharmony_ci .id = -1, 698c2ecf20Sopenharmony_ci }, 708c2ecf20Sopenharmony_ci}; 718c2ecf20Sopenharmony_ci 728c2ecf20Sopenharmony_cistatic struct resource rtc_resources[] = { 738c2ecf20Sopenharmony_ci { 748c2ecf20Sopenharmony_ci .name = "max8925-rtc", 758c2ecf20Sopenharmony_ci .start = MAX8925_IRQ_RTC_ALARM0, 768c2ecf20Sopenharmony_ci .end = MAX8925_IRQ_RTC_ALARM0, 778c2ecf20Sopenharmony_ci .flags = IORESOURCE_IRQ, 788c2ecf20Sopenharmony_ci }, 798c2ecf20Sopenharmony_ci}; 808c2ecf20Sopenharmony_ci 818c2ecf20Sopenharmony_cistatic const struct mfd_cell rtc_devs[] = { 828c2ecf20Sopenharmony_ci { 838c2ecf20Sopenharmony_ci .name = "max8925-rtc", 848c2ecf20Sopenharmony_ci .num_resources = 1, 858c2ecf20Sopenharmony_ci .resources = &rtc_resources[0], 868c2ecf20Sopenharmony_ci .id = -1, 878c2ecf20Sopenharmony_ci }, 888c2ecf20Sopenharmony_ci}; 898c2ecf20Sopenharmony_ci 908c2ecf20Sopenharmony_cistatic struct resource onkey_resources[] = { 918c2ecf20Sopenharmony_ci { 928c2ecf20Sopenharmony_ci .name = "max8925-onkey", 938c2ecf20Sopenharmony_ci .start = MAX8925_IRQ_GPM_SW_R, 948c2ecf20Sopenharmony_ci .end = MAX8925_IRQ_GPM_SW_R, 958c2ecf20Sopenharmony_ci .flags = IORESOURCE_IRQ, 968c2ecf20Sopenharmony_ci }, { 978c2ecf20Sopenharmony_ci .name = "max8925-onkey", 988c2ecf20Sopenharmony_ci .start = MAX8925_IRQ_GPM_SW_F, 998c2ecf20Sopenharmony_ci .end = MAX8925_IRQ_GPM_SW_F, 1008c2ecf20Sopenharmony_ci .flags = IORESOURCE_IRQ, 1018c2ecf20Sopenharmony_ci }, 1028c2ecf20Sopenharmony_ci}; 1038c2ecf20Sopenharmony_ci 1048c2ecf20Sopenharmony_cistatic const struct mfd_cell onkey_devs[] = { 1058c2ecf20Sopenharmony_ci { 1068c2ecf20Sopenharmony_ci .name = "max8925-onkey", 1078c2ecf20Sopenharmony_ci .num_resources = 2, 1088c2ecf20Sopenharmony_ci .resources = &onkey_resources[0], 1098c2ecf20Sopenharmony_ci .id = -1, 1108c2ecf20Sopenharmony_ci }, 1118c2ecf20Sopenharmony_ci}; 1128c2ecf20Sopenharmony_ci 1138c2ecf20Sopenharmony_cistatic struct resource sd1_resources[] = { 1148c2ecf20Sopenharmony_ci {0x06, 0x06, "sdv", IORESOURCE_REG, }, 1158c2ecf20Sopenharmony_ci}; 1168c2ecf20Sopenharmony_ci 1178c2ecf20Sopenharmony_cistatic struct resource sd2_resources[] = { 1188c2ecf20Sopenharmony_ci {0x09, 0x09, "sdv", IORESOURCE_REG, }, 1198c2ecf20Sopenharmony_ci}; 1208c2ecf20Sopenharmony_ci 1218c2ecf20Sopenharmony_cistatic struct resource sd3_resources[] = { 1228c2ecf20Sopenharmony_ci {0x0c, 0x0c, "sdv", IORESOURCE_REG, }, 1238c2ecf20Sopenharmony_ci}; 1248c2ecf20Sopenharmony_ci 1258c2ecf20Sopenharmony_cistatic struct resource ldo1_resources[] = { 1268c2ecf20Sopenharmony_ci {0x1a, 0x1a, "ldov", IORESOURCE_REG, }, 1278c2ecf20Sopenharmony_ci}; 1288c2ecf20Sopenharmony_ci 1298c2ecf20Sopenharmony_cistatic struct resource ldo2_resources[] = { 1308c2ecf20Sopenharmony_ci {0x1e, 0x1e, "ldov", IORESOURCE_REG, }, 1318c2ecf20Sopenharmony_ci}; 1328c2ecf20Sopenharmony_ci 1338c2ecf20Sopenharmony_cistatic struct resource ldo3_resources[] = { 1348c2ecf20Sopenharmony_ci {0x22, 0x22, "ldov", IORESOURCE_REG, }, 1358c2ecf20Sopenharmony_ci}; 1368c2ecf20Sopenharmony_ci 1378c2ecf20Sopenharmony_cistatic struct resource ldo4_resources[] = { 1388c2ecf20Sopenharmony_ci {0x26, 0x26, "ldov", IORESOURCE_REG, }, 1398c2ecf20Sopenharmony_ci}; 1408c2ecf20Sopenharmony_ci 1418c2ecf20Sopenharmony_cistatic struct resource ldo5_resources[] = { 1428c2ecf20Sopenharmony_ci {0x2a, 0x2a, "ldov", IORESOURCE_REG, }, 1438c2ecf20Sopenharmony_ci}; 1448c2ecf20Sopenharmony_ci 1458c2ecf20Sopenharmony_cistatic struct resource ldo6_resources[] = { 1468c2ecf20Sopenharmony_ci {0x2e, 0x2e, "ldov", IORESOURCE_REG, }, 1478c2ecf20Sopenharmony_ci}; 1488c2ecf20Sopenharmony_ci 1498c2ecf20Sopenharmony_cistatic struct resource ldo7_resources[] = { 1508c2ecf20Sopenharmony_ci {0x32, 0x32, "ldov", IORESOURCE_REG, }, 1518c2ecf20Sopenharmony_ci}; 1528c2ecf20Sopenharmony_ci 1538c2ecf20Sopenharmony_cistatic struct resource ldo8_resources[] = { 1548c2ecf20Sopenharmony_ci {0x36, 0x36, "ldov", IORESOURCE_REG, }, 1558c2ecf20Sopenharmony_ci}; 1568c2ecf20Sopenharmony_ci 1578c2ecf20Sopenharmony_cistatic struct resource ldo9_resources[] = { 1588c2ecf20Sopenharmony_ci {0x3a, 0x3a, "ldov", IORESOURCE_REG, }, 1598c2ecf20Sopenharmony_ci}; 1608c2ecf20Sopenharmony_ci 1618c2ecf20Sopenharmony_cistatic struct resource ldo10_resources[] = { 1628c2ecf20Sopenharmony_ci {0x3e, 0x3e, "ldov", IORESOURCE_REG, }, 1638c2ecf20Sopenharmony_ci}; 1648c2ecf20Sopenharmony_ci 1658c2ecf20Sopenharmony_cistatic struct resource ldo11_resources[] = { 1668c2ecf20Sopenharmony_ci {0x42, 0x42, "ldov", IORESOURCE_REG, }, 1678c2ecf20Sopenharmony_ci}; 1688c2ecf20Sopenharmony_ci 1698c2ecf20Sopenharmony_cistatic struct resource ldo12_resources[] = { 1708c2ecf20Sopenharmony_ci {0x46, 0x46, "ldov", IORESOURCE_REG, }, 1718c2ecf20Sopenharmony_ci}; 1728c2ecf20Sopenharmony_ci 1738c2ecf20Sopenharmony_cistatic struct resource ldo13_resources[] = { 1748c2ecf20Sopenharmony_ci {0x4a, 0x4a, "ldov", IORESOURCE_REG, }, 1758c2ecf20Sopenharmony_ci}; 1768c2ecf20Sopenharmony_ci 1778c2ecf20Sopenharmony_cistatic struct resource ldo14_resources[] = { 1788c2ecf20Sopenharmony_ci {0x4e, 0x4e, "ldov", IORESOURCE_REG, }, 1798c2ecf20Sopenharmony_ci}; 1808c2ecf20Sopenharmony_ci 1818c2ecf20Sopenharmony_cistatic struct resource ldo15_resources[] = { 1828c2ecf20Sopenharmony_ci {0x52, 0x52, "ldov", IORESOURCE_REG, }, 1838c2ecf20Sopenharmony_ci}; 1848c2ecf20Sopenharmony_ci 1858c2ecf20Sopenharmony_cistatic struct resource ldo16_resources[] = { 1868c2ecf20Sopenharmony_ci {0x12, 0x12, "ldov", IORESOURCE_REG, }, 1878c2ecf20Sopenharmony_ci}; 1888c2ecf20Sopenharmony_ci 1898c2ecf20Sopenharmony_cistatic struct resource ldo17_resources[] = { 1908c2ecf20Sopenharmony_ci {0x16, 0x16, "ldov", IORESOURCE_REG, }, 1918c2ecf20Sopenharmony_ci}; 1928c2ecf20Sopenharmony_ci 1938c2ecf20Sopenharmony_cistatic struct resource ldo18_resources[] = { 1948c2ecf20Sopenharmony_ci {0x74, 0x74, "ldov", IORESOURCE_REG, }, 1958c2ecf20Sopenharmony_ci}; 1968c2ecf20Sopenharmony_ci 1978c2ecf20Sopenharmony_cistatic struct resource ldo19_resources[] = { 1988c2ecf20Sopenharmony_ci {0x5e, 0x5e, "ldov", IORESOURCE_REG, }, 1998c2ecf20Sopenharmony_ci}; 2008c2ecf20Sopenharmony_ci 2018c2ecf20Sopenharmony_cistatic struct resource ldo20_resources[] = { 2028c2ecf20Sopenharmony_ci {0x9e, 0x9e, "ldov", IORESOURCE_REG, }, 2038c2ecf20Sopenharmony_ci}; 2048c2ecf20Sopenharmony_ci 2058c2ecf20Sopenharmony_cistatic struct mfd_cell reg_devs[] = { 2068c2ecf20Sopenharmony_ci { 2078c2ecf20Sopenharmony_ci .name = "max8925-regulator", 2088c2ecf20Sopenharmony_ci .id = 0, 2098c2ecf20Sopenharmony_ci .num_resources = ARRAY_SIZE(sd1_resources), 2108c2ecf20Sopenharmony_ci .resources = sd1_resources, 2118c2ecf20Sopenharmony_ci }, { 2128c2ecf20Sopenharmony_ci .name = "max8925-regulator", 2138c2ecf20Sopenharmony_ci .id = 1, 2148c2ecf20Sopenharmony_ci .num_resources = ARRAY_SIZE(sd2_resources), 2158c2ecf20Sopenharmony_ci .resources = sd2_resources, 2168c2ecf20Sopenharmony_ci }, { 2178c2ecf20Sopenharmony_ci .name = "max8925-regulator", 2188c2ecf20Sopenharmony_ci .id = 2, 2198c2ecf20Sopenharmony_ci .num_resources = ARRAY_SIZE(sd3_resources), 2208c2ecf20Sopenharmony_ci .resources = sd3_resources, 2218c2ecf20Sopenharmony_ci }, { 2228c2ecf20Sopenharmony_ci .name = "max8925-regulator", 2238c2ecf20Sopenharmony_ci .id = 3, 2248c2ecf20Sopenharmony_ci .num_resources = ARRAY_SIZE(ldo1_resources), 2258c2ecf20Sopenharmony_ci .resources = ldo1_resources, 2268c2ecf20Sopenharmony_ci }, { 2278c2ecf20Sopenharmony_ci .name = "max8925-regulator", 2288c2ecf20Sopenharmony_ci .id = 4, 2298c2ecf20Sopenharmony_ci .num_resources = ARRAY_SIZE(ldo2_resources), 2308c2ecf20Sopenharmony_ci .resources = ldo2_resources, 2318c2ecf20Sopenharmony_ci }, { 2328c2ecf20Sopenharmony_ci .name = "max8925-regulator", 2338c2ecf20Sopenharmony_ci .id = 5, 2348c2ecf20Sopenharmony_ci .num_resources = ARRAY_SIZE(ldo3_resources), 2358c2ecf20Sopenharmony_ci .resources = ldo3_resources, 2368c2ecf20Sopenharmony_ci }, { 2378c2ecf20Sopenharmony_ci .name = "max8925-regulator", 2388c2ecf20Sopenharmony_ci .id = 6, 2398c2ecf20Sopenharmony_ci .num_resources = ARRAY_SIZE(ldo4_resources), 2408c2ecf20Sopenharmony_ci .resources = ldo4_resources, 2418c2ecf20Sopenharmony_ci }, { 2428c2ecf20Sopenharmony_ci .name = "max8925-regulator", 2438c2ecf20Sopenharmony_ci .id = 7, 2448c2ecf20Sopenharmony_ci .num_resources = ARRAY_SIZE(ldo5_resources), 2458c2ecf20Sopenharmony_ci .resources = ldo5_resources, 2468c2ecf20Sopenharmony_ci }, { 2478c2ecf20Sopenharmony_ci .name = "max8925-regulator", 2488c2ecf20Sopenharmony_ci .id = 8, 2498c2ecf20Sopenharmony_ci .num_resources = ARRAY_SIZE(ldo6_resources), 2508c2ecf20Sopenharmony_ci .resources = ldo6_resources, 2518c2ecf20Sopenharmony_ci }, { 2528c2ecf20Sopenharmony_ci .name = "max8925-regulator", 2538c2ecf20Sopenharmony_ci .id = 9, 2548c2ecf20Sopenharmony_ci .num_resources = ARRAY_SIZE(ldo7_resources), 2558c2ecf20Sopenharmony_ci .resources = ldo7_resources, 2568c2ecf20Sopenharmony_ci }, { 2578c2ecf20Sopenharmony_ci .name = "max8925-regulator", 2588c2ecf20Sopenharmony_ci .id = 10, 2598c2ecf20Sopenharmony_ci .num_resources = ARRAY_SIZE(ldo8_resources), 2608c2ecf20Sopenharmony_ci .resources = ldo8_resources, 2618c2ecf20Sopenharmony_ci }, { 2628c2ecf20Sopenharmony_ci .name = "max8925-regulator", 2638c2ecf20Sopenharmony_ci .id = 11, 2648c2ecf20Sopenharmony_ci .num_resources = ARRAY_SIZE(ldo9_resources), 2658c2ecf20Sopenharmony_ci .resources = ldo9_resources, 2668c2ecf20Sopenharmony_ci }, { 2678c2ecf20Sopenharmony_ci .name = "max8925-regulator", 2688c2ecf20Sopenharmony_ci .id = 12, 2698c2ecf20Sopenharmony_ci .num_resources = ARRAY_SIZE(ldo10_resources), 2708c2ecf20Sopenharmony_ci .resources = ldo10_resources, 2718c2ecf20Sopenharmony_ci }, { 2728c2ecf20Sopenharmony_ci .name = "max8925-regulator", 2738c2ecf20Sopenharmony_ci .id = 13, 2748c2ecf20Sopenharmony_ci .num_resources = ARRAY_SIZE(ldo11_resources), 2758c2ecf20Sopenharmony_ci .resources = ldo11_resources, 2768c2ecf20Sopenharmony_ci }, { 2778c2ecf20Sopenharmony_ci .name = "max8925-regulator", 2788c2ecf20Sopenharmony_ci .id = 14, 2798c2ecf20Sopenharmony_ci .num_resources = ARRAY_SIZE(ldo12_resources), 2808c2ecf20Sopenharmony_ci .resources = ldo12_resources, 2818c2ecf20Sopenharmony_ci }, { 2828c2ecf20Sopenharmony_ci .name = "max8925-regulator", 2838c2ecf20Sopenharmony_ci .id = 15, 2848c2ecf20Sopenharmony_ci .num_resources = ARRAY_SIZE(ldo13_resources), 2858c2ecf20Sopenharmony_ci .resources = ldo13_resources, 2868c2ecf20Sopenharmony_ci }, { 2878c2ecf20Sopenharmony_ci .name = "max8925-regulator", 2888c2ecf20Sopenharmony_ci .id = 16, 2898c2ecf20Sopenharmony_ci .num_resources = ARRAY_SIZE(ldo14_resources), 2908c2ecf20Sopenharmony_ci .resources = ldo14_resources, 2918c2ecf20Sopenharmony_ci }, { 2928c2ecf20Sopenharmony_ci .name = "max8925-regulator", 2938c2ecf20Sopenharmony_ci .id = 17, 2948c2ecf20Sopenharmony_ci .num_resources = ARRAY_SIZE(ldo15_resources), 2958c2ecf20Sopenharmony_ci .resources = ldo15_resources, 2968c2ecf20Sopenharmony_ci }, { 2978c2ecf20Sopenharmony_ci .name = "max8925-regulator", 2988c2ecf20Sopenharmony_ci .id = 18, 2998c2ecf20Sopenharmony_ci .num_resources = ARRAY_SIZE(ldo16_resources), 3008c2ecf20Sopenharmony_ci .resources = ldo16_resources, 3018c2ecf20Sopenharmony_ci }, { 3028c2ecf20Sopenharmony_ci .name = "max8925-regulator", 3038c2ecf20Sopenharmony_ci .id = 19, 3048c2ecf20Sopenharmony_ci .num_resources = ARRAY_SIZE(ldo17_resources), 3058c2ecf20Sopenharmony_ci .resources = ldo17_resources, 3068c2ecf20Sopenharmony_ci }, { 3078c2ecf20Sopenharmony_ci .name = "max8925-regulator", 3088c2ecf20Sopenharmony_ci .id = 20, 3098c2ecf20Sopenharmony_ci .num_resources = ARRAY_SIZE(ldo18_resources), 3108c2ecf20Sopenharmony_ci .resources = ldo18_resources, 3118c2ecf20Sopenharmony_ci }, { 3128c2ecf20Sopenharmony_ci .name = "max8925-regulator", 3138c2ecf20Sopenharmony_ci .id = 21, 3148c2ecf20Sopenharmony_ci .num_resources = ARRAY_SIZE(ldo19_resources), 3158c2ecf20Sopenharmony_ci .resources = ldo19_resources, 3168c2ecf20Sopenharmony_ci }, { 3178c2ecf20Sopenharmony_ci .name = "max8925-regulator", 3188c2ecf20Sopenharmony_ci .id = 22, 3198c2ecf20Sopenharmony_ci .num_resources = ARRAY_SIZE(ldo20_resources), 3208c2ecf20Sopenharmony_ci .resources = ldo20_resources, 3218c2ecf20Sopenharmony_ci }, 3228c2ecf20Sopenharmony_ci}; 3238c2ecf20Sopenharmony_ci 3248c2ecf20Sopenharmony_cienum { 3258c2ecf20Sopenharmony_ci FLAGS_ADC = 1, /* register in ADC component */ 3268c2ecf20Sopenharmony_ci FLAGS_RTC, /* register in RTC component */ 3278c2ecf20Sopenharmony_ci}; 3288c2ecf20Sopenharmony_ci 3298c2ecf20Sopenharmony_cistruct max8925_irq_data { 3308c2ecf20Sopenharmony_ci int reg; 3318c2ecf20Sopenharmony_ci int mask_reg; 3328c2ecf20Sopenharmony_ci int enable; /* enable or not */ 3338c2ecf20Sopenharmony_ci int offs; /* bit offset in mask register */ 3348c2ecf20Sopenharmony_ci int flags; 3358c2ecf20Sopenharmony_ci int tsc_irq; 3368c2ecf20Sopenharmony_ci}; 3378c2ecf20Sopenharmony_ci 3388c2ecf20Sopenharmony_cistatic struct max8925_irq_data max8925_irqs[] = { 3398c2ecf20Sopenharmony_ci [MAX8925_IRQ_VCHG_DC_OVP] = { 3408c2ecf20Sopenharmony_ci .reg = MAX8925_CHG_IRQ1, 3418c2ecf20Sopenharmony_ci .mask_reg = MAX8925_CHG_IRQ1_MASK, 3428c2ecf20Sopenharmony_ci .offs = 1 << 0, 3438c2ecf20Sopenharmony_ci }, 3448c2ecf20Sopenharmony_ci [MAX8925_IRQ_VCHG_DC_F] = { 3458c2ecf20Sopenharmony_ci .reg = MAX8925_CHG_IRQ1, 3468c2ecf20Sopenharmony_ci .mask_reg = MAX8925_CHG_IRQ1_MASK, 3478c2ecf20Sopenharmony_ci .offs = 1 << 1, 3488c2ecf20Sopenharmony_ci }, 3498c2ecf20Sopenharmony_ci [MAX8925_IRQ_VCHG_DC_R] = { 3508c2ecf20Sopenharmony_ci .reg = MAX8925_CHG_IRQ1, 3518c2ecf20Sopenharmony_ci .mask_reg = MAX8925_CHG_IRQ1_MASK, 3528c2ecf20Sopenharmony_ci .offs = 1 << 2, 3538c2ecf20Sopenharmony_ci }, 3548c2ecf20Sopenharmony_ci [MAX8925_IRQ_VCHG_THM_OK_R] = { 3558c2ecf20Sopenharmony_ci .reg = MAX8925_CHG_IRQ2, 3568c2ecf20Sopenharmony_ci .mask_reg = MAX8925_CHG_IRQ2_MASK, 3578c2ecf20Sopenharmony_ci .offs = 1 << 0, 3588c2ecf20Sopenharmony_ci }, 3598c2ecf20Sopenharmony_ci [MAX8925_IRQ_VCHG_THM_OK_F] = { 3608c2ecf20Sopenharmony_ci .reg = MAX8925_CHG_IRQ2, 3618c2ecf20Sopenharmony_ci .mask_reg = MAX8925_CHG_IRQ2_MASK, 3628c2ecf20Sopenharmony_ci .offs = 1 << 1, 3638c2ecf20Sopenharmony_ci }, 3648c2ecf20Sopenharmony_ci [MAX8925_IRQ_VCHG_SYSLOW_F] = { 3658c2ecf20Sopenharmony_ci .reg = MAX8925_CHG_IRQ2, 3668c2ecf20Sopenharmony_ci .mask_reg = MAX8925_CHG_IRQ2_MASK, 3678c2ecf20Sopenharmony_ci .offs = 1 << 2, 3688c2ecf20Sopenharmony_ci }, 3698c2ecf20Sopenharmony_ci [MAX8925_IRQ_VCHG_SYSLOW_R] = { 3708c2ecf20Sopenharmony_ci .reg = MAX8925_CHG_IRQ2, 3718c2ecf20Sopenharmony_ci .mask_reg = MAX8925_CHG_IRQ2_MASK, 3728c2ecf20Sopenharmony_ci .offs = 1 << 3, 3738c2ecf20Sopenharmony_ci }, 3748c2ecf20Sopenharmony_ci [MAX8925_IRQ_VCHG_RST] = { 3758c2ecf20Sopenharmony_ci .reg = MAX8925_CHG_IRQ2, 3768c2ecf20Sopenharmony_ci .mask_reg = MAX8925_CHG_IRQ2_MASK, 3778c2ecf20Sopenharmony_ci .offs = 1 << 4, 3788c2ecf20Sopenharmony_ci }, 3798c2ecf20Sopenharmony_ci [MAX8925_IRQ_VCHG_DONE] = { 3808c2ecf20Sopenharmony_ci .reg = MAX8925_CHG_IRQ2, 3818c2ecf20Sopenharmony_ci .mask_reg = MAX8925_CHG_IRQ2_MASK, 3828c2ecf20Sopenharmony_ci .offs = 1 << 5, 3838c2ecf20Sopenharmony_ci }, 3848c2ecf20Sopenharmony_ci [MAX8925_IRQ_VCHG_TOPOFF] = { 3858c2ecf20Sopenharmony_ci .reg = MAX8925_CHG_IRQ2, 3868c2ecf20Sopenharmony_ci .mask_reg = MAX8925_CHG_IRQ2_MASK, 3878c2ecf20Sopenharmony_ci .offs = 1 << 6, 3888c2ecf20Sopenharmony_ci }, 3898c2ecf20Sopenharmony_ci [MAX8925_IRQ_VCHG_TMR_FAULT] = { 3908c2ecf20Sopenharmony_ci .reg = MAX8925_CHG_IRQ2, 3918c2ecf20Sopenharmony_ci .mask_reg = MAX8925_CHG_IRQ2_MASK, 3928c2ecf20Sopenharmony_ci .offs = 1 << 7, 3938c2ecf20Sopenharmony_ci }, 3948c2ecf20Sopenharmony_ci [MAX8925_IRQ_GPM_RSTIN] = { 3958c2ecf20Sopenharmony_ci .reg = MAX8925_ON_OFF_IRQ1, 3968c2ecf20Sopenharmony_ci .mask_reg = MAX8925_ON_OFF_IRQ1_MASK, 3978c2ecf20Sopenharmony_ci .offs = 1 << 0, 3988c2ecf20Sopenharmony_ci }, 3998c2ecf20Sopenharmony_ci [MAX8925_IRQ_GPM_MPL] = { 4008c2ecf20Sopenharmony_ci .reg = MAX8925_ON_OFF_IRQ1, 4018c2ecf20Sopenharmony_ci .mask_reg = MAX8925_ON_OFF_IRQ1_MASK, 4028c2ecf20Sopenharmony_ci .offs = 1 << 1, 4038c2ecf20Sopenharmony_ci }, 4048c2ecf20Sopenharmony_ci [MAX8925_IRQ_GPM_SW_3SEC] = { 4058c2ecf20Sopenharmony_ci .reg = MAX8925_ON_OFF_IRQ1, 4068c2ecf20Sopenharmony_ci .mask_reg = MAX8925_ON_OFF_IRQ1_MASK, 4078c2ecf20Sopenharmony_ci .offs = 1 << 2, 4088c2ecf20Sopenharmony_ci }, 4098c2ecf20Sopenharmony_ci [MAX8925_IRQ_GPM_EXTON_F] = { 4108c2ecf20Sopenharmony_ci .reg = MAX8925_ON_OFF_IRQ1, 4118c2ecf20Sopenharmony_ci .mask_reg = MAX8925_ON_OFF_IRQ1_MASK, 4128c2ecf20Sopenharmony_ci .offs = 1 << 3, 4138c2ecf20Sopenharmony_ci }, 4148c2ecf20Sopenharmony_ci [MAX8925_IRQ_GPM_EXTON_R] = { 4158c2ecf20Sopenharmony_ci .reg = MAX8925_ON_OFF_IRQ1, 4168c2ecf20Sopenharmony_ci .mask_reg = MAX8925_ON_OFF_IRQ1_MASK, 4178c2ecf20Sopenharmony_ci .offs = 1 << 4, 4188c2ecf20Sopenharmony_ci }, 4198c2ecf20Sopenharmony_ci [MAX8925_IRQ_GPM_SW_1SEC] = { 4208c2ecf20Sopenharmony_ci .reg = MAX8925_ON_OFF_IRQ1, 4218c2ecf20Sopenharmony_ci .mask_reg = MAX8925_ON_OFF_IRQ1_MASK, 4228c2ecf20Sopenharmony_ci .offs = 1 << 5, 4238c2ecf20Sopenharmony_ci }, 4248c2ecf20Sopenharmony_ci [MAX8925_IRQ_GPM_SW_F] = { 4258c2ecf20Sopenharmony_ci .reg = MAX8925_ON_OFF_IRQ1, 4268c2ecf20Sopenharmony_ci .mask_reg = MAX8925_ON_OFF_IRQ1_MASK, 4278c2ecf20Sopenharmony_ci .offs = 1 << 6, 4288c2ecf20Sopenharmony_ci }, 4298c2ecf20Sopenharmony_ci [MAX8925_IRQ_GPM_SW_R] = { 4308c2ecf20Sopenharmony_ci .reg = MAX8925_ON_OFF_IRQ1, 4318c2ecf20Sopenharmony_ci .mask_reg = MAX8925_ON_OFF_IRQ1_MASK, 4328c2ecf20Sopenharmony_ci .offs = 1 << 7, 4338c2ecf20Sopenharmony_ci }, 4348c2ecf20Sopenharmony_ci [MAX8925_IRQ_GPM_SYSCKEN_F] = { 4358c2ecf20Sopenharmony_ci .reg = MAX8925_ON_OFF_IRQ2, 4368c2ecf20Sopenharmony_ci .mask_reg = MAX8925_ON_OFF_IRQ2_MASK, 4378c2ecf20Sopenharmony_ci .offs = 1 << 0, 4388c2ecf20Sopenharmony_ci }, 4398c2ecf20Sopenharmony_ci [MAX8925_IRQ_GPM_SYSCKEN_R] = { 4408c2ecf20Sopenharmony_ci .reg = MAX8925_ON_OFF_IRQ2, 4418c2ecf20Sopenharmony_ci .mask_reg = MAX8925_ON_OFF_IRQ2_MASK, 4428c2ecf20Sopenharmony_ci .offs = 1 << 1, 4438c2ecf20Sopenharmony_ci }, 4448c2ecf20Sopenharmony_ci [MAX8925_IRQ_RTC_ALARM1] = { 4458c2ecf20Sopenharmony_ci .reg = MAX8925_RTC_IRQ, 4468c2ecf20Sopenharmony_ci .mask_reg = MAX8925_RTC_IRQ_MASK, 4478c2ecf20Sopenharmony_ci .offs = 1 << 2, 4488c2ecf20Sopenharmony_ci .flags = FLAGS_RTC, 4498c2ecf20Sopenharmony_ci }, 4508c2ecf20Sopenharmony_ci [MAX8925_IRQ_RTC_ALARM0] = { 4518c2ecf20Sopenharmony_ci .reg = MAX8925_RTC_IRQ, 4528c2ecf20Sopenharmony_ci .mask_reg = MAX8925_RTC_IRQ_MASK, 4538c2ecf20Sopenharmony_ci .offs = 1 << 3, 4548c2ecf20Sopenharmony_ci .flags = FLAGS_RTC, 4558c2ecf20Sopenharmony_ci }, 4568c2ecf20Sopenharmony_ci [MAX8925_IRQ_TSC_STICK] = { 4578c2ecf20Sopenharmony_ci .reg = MAX8925_TSC_IRQ, 4588c2ecf20Sopenharmony_ci .mask_reg = MAX8925_TSC_IRQ_MASK, 4598c2ecf20Sopenharmony_ci .offs = 1 << 0, 4608c2ecf20Sopenharmony_ci .flags = FLAGS_ADC, 4618c2ecf20Sopenharmony_ci .tsc_irq = 1, 4628c2ecf20Sopenharmony_ci }, 4638c2ecf20Sopenharmony_ci [MAX8925_IRQ_TSC_NSTICK] = { 4648c2ecf20Sopenharmony_ci .reg = MAX8925_TSC_IRQ, 4658c2ecf20Sopenharmony_ci .mask_reg = MAX8925_TSC_IRQ_MASK, 4668c2ecf20Sopenharmony_ci .offs = 1 << 1, 4678c2ecf20Sopenharmony_ci .flags = FLAGS_ADC, 4688c2ecf20Sopenharmony_ci .tsc_irq = 1, 4698c2ecf20Sopenharmony_ci }, 4708c2ecf20Sopenharmony_ci}; 4718c2ecf20Sopenharmony_ci 4728c2ecf20Sopenharmony_cistatic inline struct max8925_irq_data *irq_to_max8925(struct max8925_chip *chip, 4738c2ecf20Sopenharmony_ci int irq) 4748c2ecf20Sopenharmony_ci{ 4758c2ecf20Sopenharmony_ci return &max8925_irqs[irq - chip->irq_base]; 4768c2ecf20Sopenharmony_ci} 4778c2ecf20Sopenharmony_ci 4788c2ecf20Sopenharmony_cistatic irqreturn_t max8925_irq(int irq, void *data) 4798c2ecf20Sopenharmony_ci{ 4808c2ecf20Sopenharmony_ci struct max8925_chip *chip = data; 4818c2ecf20Sopenharmony_ci struct max8925_irq_data *irq_data; 4828c2ecf20Sopenharmony_ci struct i2c_client *i2c; 4838c2ecf20Sopenharmony_ci int read_reg = -1, value = 0; 4848c2ecf20Sopenharmony_ci int i; 4858c2ecf20Sopenharmony_ci 4868c2ecf20Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(max8925_irqs); i++) { 4878c2ecf20Sopenharmony_ci irq_data = &max8925_irqs[i]; 4888c2ecf20Sopenharmony_ci /* TSC IRQ should be serviced in max8925_tsc_irq() */ 4898c2ecf20Sopenharmony_ci if (irq_data->tsc_irq) 4908c2ecf20Sopenharmony_ci continue; 4918c2ecf20Sopenharmony_ci if (irq_data->flags == FLAGS_RTC) 4928c2ecf20Sopenharmony_ci i2c = chip->rtc; 4938c2ecf20Sopenharmony_ci else if (irq_data->flags == FLAGS_ADC) 4948c2ecf20Sopenharmony_ci i2c = chip->adc; 4958c2ecf20Sopenharmony_ci else 4968c2ecf20Sopenharmony_ci i2c = chip->i2c; 4978c2ecf20Sopenharmony_ci if (read_reg != irq_data->reg) { 4988c2ecf20Sopenharmony_ci read_reg = irq_data->reg; 4998c2ecf20Sopenharmony_ci value = max8925_reg_read(i2c, irq_data->reg); 5008c2ecf20Sopenharmony_ci } 5018c2ecf20Sopenharmony_ci if (value & irq_data->enable) 5028c2ecf20Sopenharmony_ci handle_nested_irq(chip->irq_base + i); 5038c2ecf20Sopenharmony_ci } 5048c2ecf20Sopenharmony_ci return IRQ_HANDLED; 5058c2ecf20Sopenharmony_ci} 5068c2ecf20Sopenharmony_ci 5078c2ecf20Sopenharmony_cistatic irqreturn_t max8925_tsc_irq(int irq, void *data) 5088c2ecf20Sopenharmony_ci{ 5098c2ecf20Sopenharmony_ci struct max8925_chip *chip = data; 5108c2ecf20Sopenharmony_ci struct max8925_irq_data *irq_data; 5118c2ecf20Sopenharmony_ci struct i2c_client *i2c; 5128c2ecf20Sopenharmony_ci int read_reg = -1, value = 0; 5138c2ecf20Sopenharmony_ci int i; 5148c2ecf20Sopenharmony_ci 5158c2ecf20Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(max8925_irqs); i++) { 5168c2ecf20Sopenharmony_ci irq_data = &max8925_irqs[i]; 5178c2ecf20Sopenharmony_ci /* non TSC IRQ should be serviced in max8925_irq() */ 5188c2ecf20Sopenharmony_ci if (!irq_data->tsc_irq) 5198c2ecf20Sopenharmony_ci continue; 5208c2ecf20Sopenharmony_ci if (irq_data->flags == FLAGS_RTC) 5218c2ecf20Sopenharmony_ci i2c = chip->rtc; 5228c2ecf20Sopenharmony_ci else if (irq_data->flags == FLAGS_ADC) 5238c2ecf20Sopenharmony_ci i2c = chip->adc; 5248c2ecf20Sopenharmony_ci else 5258c2ecf20Sopenharmony_ci i2c = chip->i2c; 5268c2ecf20Sopenharmony_ci if (read_reg != irq_data->reg) { 5278c2ecf20Sopenharmony_ci read_reg = irq_data->reg; 5288c2ecf20Sopenharmony_ci value = max8925_reg_read(i2c, irq_data->reg); 5298c2ecf20Sopenharmony_ci } 5308c2ecf20Sopenharmony_ci if (value & irq_data->enable) 5318c2ecf20Sopenharmony_ci handle_nested_irq(chip->irq_base + i); 5328c2ecf20Sopenharmony_ci } 5338c2ecf20Sopenharmony_ci return IRQ_HANDLED; 5348c2ecf20Sopenharmony_ci} 5358c2ecf20Sopenharmony_ci 5368c2ecf20Sopenharmony_cistatic void max8925_irq_lock(struct irq_data *data) 5378c2ecf20Sopenharmony_ci{ 5388c2ecf20Sopenharmony_ci struct max8925_chip *chip = irq_data_get_irq_chip_data(data); 5398c2ecf20Sopenharmony_ci 5408c2ecf20Sopenharmony_ci mutex_lock(&chip->irq_lock); 5418c2ecf20Sopenharmony_ci} 5428c2ecf20Sopenharmony_ci 5438c2ecf20Sopenharmony_cistatic void max8925_irq_sync_unlock(struct irq_data *data) 5448c2ecf20Sopenharmony_ci{ 5458c2ecf20Sopenharmony_ci struct max8925_chip *chip = irq_data_get_irq_chip_data(data); 5468c2ecf20Sopenharmony_ci struct max8925_irq_data *irq_data; 5478c2ecf20Sopenharmony_ci static unsigned char cache_chg[2] = {0xff, 0xff}; 5488c2ecf20Sopenharmony_ci static unsigned char cache_on[2] = {0xff, 0xff}; 5498c2ecf20Sopenharmony_ci static unsigned char cache_rtc = 0xff, cache_tsc = 0xff; 5508c2ecf20Sopenharmony_ci unsigned char irq_chg[2], irq_on[2]; 5518c2ecf20Sopenharmony_ci unsigned char irq_rtc, irq_tsc; 5528c2ecf20Sopenharmony_ci int i; 5538c2ecf20Sopenharmony_ci 5548c2ecf20Sopenharmony_ci /* Load cached value. In initial, all IRQs are masked */ 5558c2ecf20Sopenharmony_ci irq_chg[0] = cache_chg[0]; 5568c2ecf20Sopenharmony_ci irq_chg[1] = cache_chg[1]; 5578c2ecf20Sopenharmony_ci irq_on[0] = cache_on[0]; 5588c2ecf20Sopenharmony_ci irq_on[1] = cache_on[1]; 5598c2ecf20Sopenharmony_ci irq_rtc = cache_rtc; 5608c2ecf20Sopenharmony_ci irq_tsc = cache_tsc; 5618c2ecf20Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(max8925_irqs); i++) { 5628c2ecf20Sopenharmony_ci irq_data = &max8925_irqs[i]; 5638c2ecf20Sopenharmony_ci /* 1 -- disable, 0 -- enable */ 5648c2ecf20Sopenharmony_ci switch (irq_data->mask_reg) { 5658c2ecf20Sopenharmony_ci case MAX8925_CHG_IRQ1_MASK: 5668c2ecf20Sopenharmony_ci irq_chg[0] &= ~irq_data->enable; 5678c2ecf20Sopenharmony_ci break; 5688c2ecf20Sopenharmony_ci case MAX8925_CHG_IRQ2_MASK: 5698c2ecf20Sopenharmony_ci irq_chg[1] &= ~irq_data->enable; 5708c2ecf20Sopenharmony_ci break; 5718c2ecf20Sopenharmony_ci case MAX8925_ON_OFF_IRQ1_MASK: 5728c2ecf20Sopenharmony_ci irq_on[0] &= ~irq_data->enable; 5738c2ecf20Sopenharmony_ci break; 5748c2ecf20Sopenharmony_ci case MAX8925_ON_OFF_IRQ2_MASK: 5758c2ecf20Sopenharmony_ci irq_on[1] &= ~irq_data->enable; 5768c2ecf20Sopenharmony_ci break; 5778c2ecf20Sopenharmony_ci case MAX8925_RTC_IRQ_MASK: 5788c2ecf20Sopenharmony_ci irq_rtc &= ~irq_data->enable; 5798c2ecf20Sopenharmony_ci break; 5808c2ecf20Sopenharmony_ci case MAX8925_TSC_IRQ_MASK: 5818c2ecf20Sopenharmony_ci irq_tsc &= ~irq_data->enable; 5828c2ecf20Sopenharmony_ci break; 5838c2ecf20Sopenharmony_ci default: 5848c2ecf20Sopenharmony_ci dev_err(chip->dev, "wrong IRQ\n"); 5858c2ecf20Sopenharmony_ci break; 5868c2ecf20Sopenharmony_ci } 5878c2ecf20Sopenharmony_ci } 5888c2ecf20Sopenharmony_ci /* update mask into registers */ 5898c2ecf20Sopenharmony_ci if (cache_chg[0] != irq_chg[0]) { 5908c2ecf20Sopenharmony_ci cache_chg[0] = irq_chg[0]; 5918c2ecf20Sopenharmony_ci max8925_reg_write(chip->i2c, MAX8925_CHG_IRQ1_MASK, 5928c2ecf20Sopenharmony_ci irq_chg[0]); 5938c2ecf20Sopenharmony_ci } 5948c2ecf20Sopenharmony_ci if (cache_chg[1] != irq_chg[1]) { 5958c2ecf20Sopenharmony_ci cache_chg[1] = irq_chg[1]; 5968c2ecf20Sopenharmony_ci max8925_reg_write(chip->i2c, MAX8925_CHG_IRQ2_MASK, 5978c2ecf20Sopenharmony_ci irq_chg[1]); 5988c2ecf20Sopenharmony_ci } 5998c2ecf20Sopenharmony_ci if (cache_on[0] != irq_on[0]) { 6008c2ecf20Sopenharmony_ci cache_on[0] = irq_on[0]; 6018c2ecf20Sopenharmony_ci max8925_reg_write(chip->i2c, MAX8925_ON_OFF_IRQ1_MASK, 6028c2ecf20Sopenharmony_ci irq_on[0]); 6038c2ecf20Sopenharmony_ci } 6048c2ecf20Sopenharmony_ci if (cache_on[1] != irq_on[1]) { 6058c2ecf20Sopenharmony_ci cache_on[1] = irq_on[1]; 6068c2ecf20Sopenharmony_ci max8925_reg_write(chip->i2c, MAX8925_ON_OFF_IRQ2_MASK, 6078c2ecf20Sopenharmony_ci irq_on[1]); 6088c2ecf20Sopenharmony_ci } 6098c2ecf20Sopenharmony_ci if (cache_rtc != irq_rtc) { 6108c2ecf20Sopenharmony_ci cache_rtc = irq_rtc; 6118c2ecf20Sopenharmony_ci max8925_reg_write(chip->rtc, MAX8925_RTC_IRQ_MASK, irq_rtc); 6128c2ecf20Sopenharmony_ci } 6138c2ecf20Sopenharmony_ci if (cache_tsc != irq_tsc) { 6148c2ecf20Sopenharmony_ci cache_tsc = irq_tsc; 6158c2ecf20Sopenharmony_ci max8925_reg_write(chip->adc, MAX8925_TSC_IRQ_MASK, irq_tsc); 6168c2ecf20Sopenharmony_ci } 6178c2ecf20Sopenharmony_ci 6188c2ecf20Sopenharmony_ci mutex_unlock(&chip->irq_lock); 6198c2ecf20Sopenharmony_ci} 6208c2ecf20Sopenharmony_ci 6218c2ecf20Sopenharmony_cistatic void max8925_irq_enable(struct irq_data *data) 6228c2ecf20Sopenharmony_ci{ 6238c2ecf20Sopenharmony_ci struct max8925_chip *chip = irq_data_get_irq_chip_data(data); 6248c2ecf20Sopenharmony_ci 6258c2ecf20Sopenharmony_ci max8925_irqs[data->irq - chip->irq_base].enable 6268c2ecf20Sopenharmony_ci = max8925_irqs[data->irq - chip->irq_base].offs; 6278c2ecf20Sopenharmony_ci} 6288c2ecf20Sopenharmony_ci 6298c2ecf20Sopenharmony_cistatic void max8925_irq_disable(struct irq_data *data) 6308c2ecf20Sopenharmony_ci{ 6318c2ecf20Sopenharmony_ci struct max8925_chip *chip = irq_data_get_irq_chip_data(data); 6328c2ecf20Sopenharmony_ci 6338c2ecf20Sopenharmony_ci max8925_irqs[data->irq - chip->irq_base].enable = 0; 6348c2ecf20Sopenharmony_ci} 6358c2ecf20Sopenharmony_ci 6368c2ecf20Sopenharmony_cistatic struct irq_chip max8925_irq_chip = { 6378c2ecf20Sopenharmony_ci .name = "max8925", 6388c2ecf20Sopenharmony_ci .irq_bus_lock = max8925_irq_lock, 6398c2ecf20Sopenharmony_ci .irq_bus_sync_unlock = max8925_irq_sync_unlock, 6408c2ecf20Sopenharmony_ci .irq_enable = max8925_irq_enable, 6418c2ecf20Sopenharmony_ci .irq_disable = max8925_irq_disable, 6428c2ecf20Sopenharmony_ci}; 6438c2ecf20Sopenharmony_ci 6448c2ecf20Sopenharmony_cistatic int max8925_irq_domain_map(struct irq_domain *d, unsigned int virq, 6458c2ecf20Sopenharmony_ci irq_hw_number_t hw) 6468c2ecf20Sopenharmony_ci{ 6478c2ecf20Sopenharmony_ci irq_set_chip_data(virq, d->host_data); 6488c2ecf20Sopenharmony_ci irq_set_chip_and_handler(virq, &max8925_irq_chip, handle_edge_irq); 6498c2ecf20Sopenharmony_ci irq_set_nested_thread(virq, 1); 6508c2ecf20Sopenharmony_ci irq_set_noprobe(virq); 6518c2ecf20Sopenharmony_ci 6528c2ecf20Sopenharmony_ci return 0; 6538c2ecf20Sopenharmony_ci} 6548c2ecf20Sopenharmony_ci 6558c2ecf20Sopenharmony_cistatic const struct irq_domain_ops max8925_irq_domain_ops = { 6568c2ecf20Sopenharmony_ci .map = max8925_irq_domain_map, 6578c2ecf20Sopenharmony_ci .xlate = irq_domain_xlate_onetwocell, 6588c2ecf20Sopenharmony_ci}; 6598c2ecf20Sopenharmony_ci 6608c2ecf20Sopenharmony_ci 6618c2ecf20Sopenharmony_cistatic int max8925_irq_init(struct max8925_chip *chip, int irq, 6628c2ecf20Sopenharmony_ci struct max8925_platform_data *pdata) 6638c2ecf20Sopenharmony_ci{ 6648c2ecf20Sopenharmony_ci unsigned long flags = IRQF_TRIGGER_FALLING | IRQF_ONESHOT; 6658c2ecf20Sopenharmony_ci int ret; 6668c2ecf20Sopenharmony_ci struct device_node *node = chip->dev->of_node; 6678c2ecf20Sopenharmony_ci 6688c2ecf20Sopenharmony_ci /* clear all interrupts */ 6698c2ecf20Sopenharmony_ci max8925_reg_read(chip->i2c, MAX8925_CHG_IRQ1); 6708c2ecf20Sopenharmony_ci max8925_reg_read(chip->i2c, MAX8925_CHG_IRQ2); 6718c2ecf20Sopenharmony_ci max8925_reg_read(chip->i2c, MAX8925_ON_OFF_IRQ1); 6728c2ecf20Sopenharmony_ci max8925_reg_read(chip->i2c, MAX8925_ON_OFF_IRQ2); 6738c2ecf20Sopenharmony_ci max8925_reg_read(chip->rtc, MAX8925_RTC_IRQ); 6748c2ecf20Sopenharmony_ci max8925_reg_read(chip->adc, MAX8925_TSC_IRQ); 6758c2ecf20Sopenharmony_ci /* mask all interrupts except for TSC */ 6768c2ecf20Sopenharmony_ci max8925_reg_write(chip->rtc, MAX8925_ALARM0_CNTL, 0); 6778c2ecf20Sopenharmony_ci max8925_reg_write(chip->rtc, MAX8925_ALARM1_CNTL, 0); 6788c2ecf20Sopenharmony_ci max8925_reg_write(chip->i2c, MAX8925_CHG_IRQ1_MASK, 0xff); 6798c2ecf20Sopenharmony_ci max8925_reg_write(chip->i2c, MAX8925_CHG_IRQ2_MASK, 0xff); 6808c2ecf20Sopenharmony_ci max8925_reg_write(chip->i2c, MAX8925_ON_OFF_IRQ1_MASK, 0xff); 6818c2ecf20Sopenharmony_ci max8925_reg_write(chip->i2c, MAX8925_ON_OFF_IRQ2_MASK, 0xff); 6828c2ecf20Sopenharmony_ci max8925_reg_write(chip->rtc, MAX8925_RTC_IRQ_MASK, 0xff); 6838c2ecf20Sopenharmony_ci 6848c2ecf20Sopenharmony_ci mutex_init(&chip->irq_lock); 6858c2ecf20Sopenharmony_ci chip->irq_base = irq_alloc_descs(-1, 0, MAX8925_NR_IRQS, 0); 6868c2ecf20Sopenharmony_ci if (chip->irq_base < 0) { 6878c2ecf20Sopenharmony_ci dev_err(chip->dev, "Failed to allocate interrupts, ret:%d\n", 6888c2ecf20Sopenharmony_ci chip->irq_base); 6898c2ecf20Sopenharmony_ci return -EBUSY; 6908c2ecf20Sopenharmony_ci } 6918c2ecf20Sopenharmony_ci 6928c2ecf20Sopenharmony_ci irq_domain_add_legacy(node, MAX8925_NR_IRQS, chip->irq_base, 0, 6938c2ecf20Sopenharmony_ci &max8925_irq_domain_ops, chip); 6948c2ecf20Sopenharmony_ci 6958c2ecf20Sopenharmony_ci /* request irq handler for pmic main irq*/ 6968c2ecf20Sopenharmony_ci chip->core_irq = irq; 6978c2ecf20Sopenharmony_ci if (!chip->core_irq) 6988c2ecf20Sopenharmony_ci return -EBUSY; 6998c2ecf20Sopenharmony_ci ret = request_threaded_irq(irq, NULL, max8925_irq, flags | IRQF_ONESHOT, 7008c2ecf20Sopenharmony_ci "max8925", chip); 7018c2ecf20Sopenharmony_ci if (ret) { 7028c2ecf20Sopenharmony_ci dev_err(chip->dev, "Failed to request core IRQ: %d\n", ret); 7038c2ecf20Sopenharmony_ci chip->core_irq = 0; 7048c2ecf20Sopenharmony_ci return -EBUSY; 7058c2ecf20Sopenharmony_ci } 7068c2ecf20Sopenharmony_ci 7078c2ecf20Sopenharmony_ci /* request irq handler for pmic tsc irq*/ 7088c2ecf20Sopenharmony_ci 7098c2ecf20Sopenharmony_ci /* mask TSC interrupt */ 7108c2ecf20Sopenharmony_ci max8925_reg_write(chip->adc, MAX8925_TSC_IRQ_MASK, 0x0f); 7118c2ecf20Sopenharmony_ci 7128c2ecf20Sopenharmony_ci if (!pdata->tsc_irq) { 7138c2ecf20Sopenharmony_ci dev_warn(chip->dev, "No interrupt support on TSC IRQ\n"); 7148c2ecf20Sopenharmony_ci return 0; 7158c2ecf20Sopenharmony_ci } 7168c2ecf20Sopenharmony_ci chip->tsc_irq = pdata->tsc_irq; 7178c2ecf20Sopenharmony_ci ret = request_threaded_irq(chip->tsc_irq, NULL, max8925_tsc_irq, 7188c2ecf20Sopenharmony_ci flags | IRQF_ONESHOT, "max8925-tsc", chip); 7198c2ecf20Sopenharmony_ci if (ret) { 7208c2ecf20Sopenharmony_ci dev_err(chip->dev, "Failed to request TSC IRQ: %d\n", ret); 7218c2ecf20Sopenharmony_ci chip->tsc_irq = 0; 7228c2ecf20Sopenharmony_ci } 7238c2ecf20Sopenharmony_ci return 0; 7248c2ecf20Sopenharmony_ci} 7258c2ecf20Sopenharmony_ci 7268c2ecf20Sopenharmony_cistatic void init_regulator(struct max8925_chip *chip, 7278c2ecf20Sopenharmony_ci struct max8925_platform_data *pdata) 7288c2ecf20Sopenharmony_ci{ 7298c2ecf20Sopenharmony_ci int ret; 7308c2ecf20Sopenharmony_ci 7318c2ecf20Sopenharmony_ci if (!pdata) 7328c2ecf20Sopenharmony_ci return; 7338c2ecf20Sopenharmony_ci if (pdata->sd1) { 7348c2ecf20Sopenharmony_ci reg_devs[0].platform_data = pdata->sd1; 7358c2ecf20Sopenharmony_ci reg_devs[0].pdata_size = sizeof(struct regulator_init_data); 7368c2ecf20Sopenharmony_ci } 7378c2ecf20Sopenharmony_ci if (pdata->sd2) { 7388c2ecf20Sopenharmony_ci reg_devs[1].platform_data = pdata->sd2; 7398c2ecf20Sopenharmony_ci reg_devs[1].pdata_size = sizeof(struct regulator_init_data); 7408c2ecf20Sopenharmony_ci } 7418c2ecf20Sopenharmony_ci if (pdata->sd3) { 7428c2ecf20Sopenharmony_ci reg_devs[2].platform_data = pdata->sd3; 7438c2ecf20Sopenharmony_ci reg_devs[2].pdata_size = sizeof(struct regulator_init_data); 7448c2ecf20Sopenharmony_ci } 7458c2ecf20Sopenharmony_ci if (pdata->ldo1) { 7468c2ecf20Sopenharmony_ci reg_devs[3].platform_data = pdata->ldo1; 7478c2ecf20Sopenharmony_ci reg_devs[3].pdata_size = sizeof(struct regulator_init_data); 7488c2ecf20Sopenharmony_ci } 7498c2ecf20Sopenharmony_ci if (pdata->ldo2) { 7508c2ecf20Sopenharmony_ci reg_devs[4].platform_data = pdata->ldo2; 7518c2ecf20Sopenharmony_ci reg_devs[4].pdata_size = sizeof(struct regulator_init_data); 7528c2ecf20Sopenharmony_ci } 7538c2ecf20Sopenharmony_ci if (pdata->ldo3) { 7548c2ecf20Sopenharmony_ci reg_devs[5].platform_data = pdata->ldo3; 7558c2ecf20Sopenharmony_ci reg_devs[5].pdata_size = sizeof(struct regulator_init_data); 7568c2ecf20Sopenharmony_ci } 7578c2ecf20Sopenharmony_ci if (pdata->ldo4) { 7588c2ecf20Sopenharmony_ci reg_devs[6].platform_data = pdata->ldo4; 7598c2ecf20Sopenharmony_ci reg_devs[6].pdata_size = sizeof(struct regulator_init_data); 7608c2ecf20Sopenharmony_ci } 7618c2ecf20Sopenharmony_ci if (pdata->ldo5) { 7628c2ecf20Sopenharmony_ci reg_devs[7].platform_data = pdata->ldo5; 7638c2ecf20Sopenharmony_ci reg_devs[7].pdata_size = sizeof(struct regulator_init_data); 7648c2ecf20Sopenharmony_ci } 7658c2ecf20Sopenharmony_ci if (pdata->ldo6) { 7668c2ecf20Sopenharmony_ci reg_devs[8].platform_data = pdata->ldo6; 7678c2ecf20Sopenharmony_ci reg_devs[8].pdata_size = sizeof(struct regulator_init_data); 7688c2ecf20Sopenharmony_ci } 7698c2ecf20Sopenharmony_ci if (pdata->ldo7) { 7708c2ecf20Sopenharmony_ci reg_devs[9].platform_data = pdata->ldo7; 7718c2ecf20Sopenharmony_ci reg_devs[9].pdata_size = sizeof(struct regulator_init_data); 7728c2ecf20Sopenharmony_ci } 7738c2ecf20Sopenharmony_ci if (pdata->ldo8) { 7748c2ecf20Sopenharmony_ci reg_devs[10].platform_data = pdata->ldo8; 7758c2ecf20Sopenharmony_ci reg_devs[10].pdata_size = sizeof(struct regulator_init_data); 7768c2ecf20Sopenharmony_ci } 7778c2ecf20Sopenharmony_ci if (pdata->ldo9) { 7788c2ecf20Sopenharmony_ci reg_devs[11].platform_data = pdata->ldo9; 7798c2ecf20Sopenharmony_ci reg_devs[11].pdata_size = sizeof(struct regulator_init_data); 7808c2ecf20Sopenharmony_ci } 7818c2ecf20Sopenharmony_ci if (pdata->ldo10) { 7828c2ecf20Sopenharmony_ci reg_devs[12].platform_data = pdata->ldo10; 7838c2ecf20Sopenharmony_ci reg_devs[12].pdata_size = sizeof(struct regulator_init_data); 7848c2ecf20Sopenharmony_ci } 7858c2ecf20Sopenharmony_ci if (pdata->ldo11) { 7868c2ecf20Sopenharmony_ci reg_devs[13].platform_data = pdata->ldo11; 7878c2ecf20Sopenharmony_ci reg_devs[13].pdata_size = sizeof(struct regulator_init_data); 7888c2ecf20Sopenharmony_ci } 7898c2ecf20Sopenharmony_ci if (pdata->ldo12) { 7908c2ecf20Sopenharmony_ci reg_devs[14].platform_data = pdata->ldo12; 7918c2ecf20Sopenharmony_ci reg_devs[14].pdata_size = sizeof(struct regulator_init_data); 7928c2ecf20Sopenharmony_ci } 7938c2ecf20Sopenharmony_ci if (pdata->ldo13) { 7948c2ecf20Sopenharmony_ci reg_devs[15].platform_data = pdata->ldo13; 7958c2ecf20Sopenharmony_ci reg_devs[15].pdata_size = sizeof(struct regulator_init_data); 7968c2ecf20Sopenharmony_ci } 7978c2ecf20Sopenharmony_ci if (pdata->ldo14) { 7988c2ecf20Sopenharmony_ci reg_devs[16].platform_data = pdata->ldo14; 7998c2ecf20Sopenharmony_ci reg_devs[16].pdata_size = sizeof(struct regulator_init_data); 8008c2ecf20Sopenharmony_ci } 8018c2ecf20Sopenharmony_ci if (pdata->ldo15) { 8028c2ecf20Sopenharmony_ci reg_devs[17].platform_data = pdata->ldo15; 8038c2ecf20Sopenharmony_ci reg_devs[17].pdata_size = sizeof(struct regulator_init_data); 8048c2ecf20Sopenharmony_ci } 8058c2ecf20Sopenharmony_ci if (pdata->ldo16) { 8068c2ecf20Sopenharmony_ci reg_devs[18].platform_data = pdata->ldo16; 8078c2ecf20Sopenharmony_ci reg_devs[18].pdata_size = sizeof(struct regulator_init_data); 8088c2ecf20Sopenharmony_ci } 8098c2ecf20Sopenharmony_ci if (pdata->ldo17) { 8108c2ecf20Sopenharmony_ci reg_devs[19].platform_data = pdata->ldo17; 8118c2ecf20Sopenharmony_ci reg_devs[19].pdata_size = sizeof(struct regulator_init_data); 8128c2ecf20Sopenharmony_ci } 8138c2ecf20Sopenharmony_ci if (pdata->ldo18) { 8148c2ecf20Sopenharmony_ci reg_devs[20].platform_data = pdata->ldo18; 8158c2ecf20Sopenharmony_ci reg_devs[20].pdata_size = sizeof(struct regulator_init_data); 8168c2ecf20Sopenharmony_ci } 8178c2ecf20Sopenharmony_ci if (pdata->ldo19) { 8188c2ecf20Sopenharmony_ci reg_devs[21].platform_data = pdata->ldo19; 8198c2ecf20Sopenharmony_ci reg_devs[21].pdata_size = sizeof(struct regulator_init_data); 8208c2ecf20Sopenharmony_ci } 8218c2ecf20Sopenharmony_ci if (pdata->ldo20) { 8228c2ecf20Sopenharmony_ci reg_devs[22].platform_data = pdata->ldo20; 8238c2ecf20Sopenharmony_ci reg_devs[22].pdata_size = sizeof(struct regulator_init_data); 8248c2ecf20Sopenharmony_ci } 8258c2ecf20Sopenharmony_ci ret = mfd_add_devices(chip->dev, 0, reg_devs, ARRAY_SIZE(reg_devs), 8268c2ecf20Sopenharmony_ci NULL, 0, NULL); 8278c2ecf20Sopenharmony_ci if (ret < 0) { 8288c2ecf20Sopenharmony_ci dev_err(chip->dev, "Failed to add regulator subdev\n"); 8298c2ecf20Sopenharmony_ci return; 8308c2ecf20Sopenharmony_ci } 8318c2ecf20Sopenharmony_ci} 8328c2ecf20Sopenharmony_ci 8338c2ecf20Sopenharmony_ciint max8925_device_init(struct max8925_chip *chip, 8348c2ecf20Sopenharmony_ci struct max8925_platform_data *pdata) 8358c2ecf20Sopenharmony_ci{ 8368c2ecf20Sopenharmony_ci int ret; 8378c2ecf20Sopenharmony_ci 8388c2ecf20Sopenharmony_ci max8925_irq_init(chip, chip->i2c->irq, pdata); 8398c2ecf20Sopenharmony_ci 8408c2ecf20Sopenharmony_ci if (pdata && (pdata->power || pdata->touch)) { 8418c2ecf20Sopenharmony_ci /* enable ADC to control internal reference */ 8428c2ecf20Sopenharmony_ci max8925_set_bits(chip->i2c, MAX8925_RESET_CNFG, 1, 1); 8438c2ecf20Sopenharmony_ci /* enable internal reference for ADC */ 8448c2ecf20Sopenharmony_ci max8925_set_bits(chip->adc, MAX8925_TSC_CNFG1, 3, 2); 8458c2ecf20Sopenharmony_ci /* check for internal reference IRQ */ 8468c2ecf20Sopenharmony_ci do { 8478c2ecf20Sopenharmony_ci ret = max8925_reg_read(chip->adc, MAX8925_TSC_IRQ); 8488c2ecf20Sopenharmony_ci } while (ret & MAX8925_NREF_OK); 8498c2ecf20Sopenharmony_ci /* enaable ADC scheduler, interval is 1 second */ 8508c2ecf20Sopenharmony_ci max8925_set_bits(chip->adc, MAX8925_ADC_SCHED, 3, 2); 8518c2ecf20Sopenharmony_ci } 8528c2ecf20Sopenharmony_ci 8538c2ecf20Sopenharmony_ci /* enable Momentary Power Loss */ 8548c2ecf20Sopenharmony_ci max8925_set_bits(chip->rtc, MAX8925_MPL_CNTL, 1 << 4, 1 << 4); 8558c2ecf20Sopenharmony_ci 8568c2ecf20Sopenharmony_ci ret = mfd_add_devices(chip->dev, 0, &rtc_devs[0], 8578c2ecf20Sopenharmony_ci ARRAY_SIZE(rtc_devs), 8588c2ecf20Sopenharmony_ci NULL, chip->irq_base, NULL); 8598c2ecf20Sopenharmony_ci if (ret < 0) { 8608c2ecf20Sopenharmony_ci dev_err(chip->dev, "Failed to add rtc subdev\n"); 8618c2ecf20Sopenharmony_ci goto out; 8628c2ecf20Sopenharmony_ci } 8638c2ecf20Sopenharmony_ci 8648c2ecf20Sopenharmony_ci ret = mfd_add_devices(chip->dev, 0, &onkey_devs[0], 8658c2ecf20Sopenharmony_ci ARRAY_SIZE(onkey_devs), 8668c2ecf20Sopenharmony_ci NULL, chip->irq_base, NULL); 8678c2ecf20Sopenharmony_ci if (ret < 0) { 8688c2ecf20Sopenharmony_ci dev_err(chip->dev, "Failed to add onkey subdev\n"); 8698c2ecf20Sopenharmony_ci goto out_dev; 8708c2ecf20Sopenharmony_ci } 8718c2ecf20Sopenharmony_ci 8728c2ecf20Sopenharmony_ci init_regulator(chip, pdata); 8738c2ecf20Sopenharmony_ci 8748c2ecf20Sopenharmony_ci if (pdata && pdata->backlight) { 8758c2ecf20Sopenharmony_ci bk_devs[0].platform_data = &pdata->backlight; 8768c2ecf20Sopenharmony_ci bk_devs[0].pdata_size = sizeof(struct max8925_backlight_pdata); 8778c2ecf20Sopenharmony_ci } 8788c2ecf20Sopenharmony_ci ret = mfd_add_devices(chip->dev, 0, bk_devs, ARRAY_SIZE(bk_devs), 8798c2ecf20Sopenharmony_ci NULL, 0, NULL); 8808c2ecf20Sopenharmony_ci if (ret < 0) { 8818c2ecf20Sopenharmony_ci dev_err(chip->dev, "Failed to add backlight subdev\n"); 8828c2ecf20Sopenharmony_ci goto out_dev; 8838c2ecf20Sopenharmony_ci } 8848c2ecf20Sopenharmony_ci 8858c2ecf20Sopenharmony_ci ret = mfd_add_devices(chip->dev, 0, &power_devs[0], 8868c2ecf20Sopenharmony_ci ARRAY_SIZE(power_devs), 8878c2ecf20Sopenharmony_ci NULL, 0, NULL); 8888c2ecf20Sopenharmony_ci if (ret < 0) { 8898c2ecf20Sopenharmony_ci dev_err(chip->dev, 8908c2ecf20Sopenharmony_ci "Failed to add power supply subdev, err = %d\n", ret); 8918c2ecf20Sopenharmony_ci goto out_dev; 8928c2ecf20Sopenharmony_ci } 8938c2ecf20Sopenharmony_ci 8948c2ecf20Sopenharmony_ci if (pdata && pdata->touch) { 8958c2ecf20Sopenharmony_ci ret = mfd_add_devices(chip->dev, 0, &touch_devs[0], 8968c2ecf20Sopenharmony_ci ARRAY_SIZE(touch_devs), 8978c2ecf20Sopenharmony_ci NULL, chip->tsc_irq, NULL); 8988c2ecf20Sopenharmony_ci if (ret < 0) { 8998c2ecf20Sopenharmony_ci dev_err(chip->dev, "Failed to add touch subdev\n"); 9008c2ecf20Sopenharmony_ci goto out_dev; 9018c2ecf20Sopenharmony_ci } 9028c2ecf20Sopenharmony_ci } 9038c2ecf20Sopenharmony_ci 9048c2ecf20Sopenharmony_ci return 0; 9058c2ecf20Sopenharmony_ciout_dev: 9068c2ecf20Sopenharmony_ci mfd_remove_devices(chip->dev); 9078c2ecf20Sopenharmony_ciout: 9088c2ecf20Sopenharmony_ci return ret; 9098c2ecf20Sopenharmony_ci} 9108c2ecf20Sopenharmony_ci 9118c2ecf20Sopenharmony_civoid max8925_device_exit(struct max8925_chip *chip) 9128c2ecf20Sopenharmony_ci{ 9138c2ecf20Sopenharmony_ci if (chip->core_irq) 9148c2ecf20Sopenharmony_ci free_irq(chip->core_irq, chip); 9158c2ecf20Sopenharmony_ci if (chip->tsc_irq) 9168c2ecf20Sopenharmony_ci free_irq(chip->tsc_irq, chip); 9178c2ecf20Sopenharmony_ci mfd_remove_devices(chip->dev); 9188c2ecf20Sopenharmony_ci} 919