162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Base driver for Maxim MAX8925 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright (C) 2009-2010 Marvell International Ltd. 662306a36Sopenharmony_ci * Haojian Zhuang <haojian.zhuang@marvell.com> 762306a36Sopenharmony_ci */ 862306a36Sopenharmony_ci 962306a36Sopenharmony_ci#include <linux/kernel.h> 1062306a36Sopenharmony_ci#include <linux/init.h> 1162306a36Sopenharmony_ci#include <linux/i2c.h> 1262306a36Sopenharmony_ci#include <linux/irq.h> 1362306a36Sopenharmony_ci#include <linux/interrupt.h> 1462306a36Sopenharmony_ci#include <linux/irqdomain.h> 1562306a36Sopenharmony_ci#include <linux/platform_device.h> 1662306a36Sopenharmony_ci#include <linux/regulator/machine.h> 1762306a36Sopenharmony_ci#include <linux/mfd/core.h> 1862306a36Sopenharmony_ci#include <linux/mfd/max8925.h> 1962306a36Sopenharmony_ci#include <linux/of.h> 2062306a36Sopenharmony_ci 2162306a36Sopenharmony_cistatic const struct resource bk_resources[] = { 2262306a36Sopenharmony_ci { 0x84, 0x84, "mode control", IORESOURCE_REG, }, 2362306a36Sopenharmony_ci { 0x85, 0x85, "control", IORESOURCE_REG, }, 2462306a36Sopenharmony_ci}; 2562306a36Sopenharmony_ci 2662306a36Sopenharmony_cistatic struct mfd_cell bk_devs[] = { 2762306a36Sopenharmony_ci { 2862306a36Sopenharmony_ci .name = "max8925-backlight", 2962306a36Sopenharmony_ci .num_resources = ARRAY_SIZE(bk_resources), 3062306a36Sopenharmony_ci .resources = &bk_resources[0], 3162306a36Sopenharmony_ci .id = -1, 3262306a36Sopenharmony_ci }, 3362306a36Sopenharmony_ci}; 3462306a36Sopenharmony_ci 3562306a36Sopenharmony_cistatic const struct resource touch_resources[] = { 3662306a36Sopenharmony_ci { 3762306a36Sopenharmony_ci .name = "max8925-tsc", 3862306a36Sopenharmony_ci .start = MAX8925_TSC_IRQ, 3962306a36Sopenharmony_ci .end = MAX8925_ADC_RES_END, 4062306a36Sopenharmony_ci .flags = IORESOURCE_REG, 4162306a36Sopenharmony_ci }, 4262306a36Sopenharmony_ci}; 4362306a36Sopenharmony_ci 4462306a36Sopenharmony_cistatic const struct mfd_cell touch_devs[] = { 4562306a36Sopenharmony_ci { 4662306a36Sopenharmony_ci .name = "max8925-touch", 4762306a36Sopenharmony_ci .num_resources = 1, 4862306a36Sopenharmony_ci .resources = &touch_resources[0], 4962306a36Sopenharmony_ci .id = -1, 5062306a36Sopenharmony_ci }, 5162306a36Sopenharmony_ci}; 5262306a36Sopenharmony_ci 5362306a36Sopenharmony_cistatic const struct resource power_supply_resources[] = { 5462306a36Sopenharmony_ci { 5562306a36Sopenharmony_ci .name = "max8925-power", 5662306a36Sopenharmony_ci .start = MAX8925_CHG_IRQ1, 5762306a36Sopenharmony_ci .end = MAX8925_CHG_IRQ1_MASK, 5862306a36Sopenharmony_ci .flags = IORESOURCE_REG, 5962306a36Sopenharmony_ci }, 6062306a36Sopenharmony_ci}; 6162306a36Sopenharmony_ci 6262306a36Sopenharmony_cistatic const struct mfd_cell power_devs[] = { 6362306a36Sopenharmony_ci { 6462306a36Sopenharmony_ci .name = "max8925-power", 6562306a36Sopenharmony_ci .num_resources = 1, 6662306a36Sopenharmony_ci .resources = &power_supply_resources[0], 6762306a36Sopenharmony_ci .id = -1, 6862306a36Sopenharmony_ci }, 6962306a36Sopenharmony_ci}; 7062306a36Sopenharmony_ci 7162306a36Sopenharmony_cistatic const struct resource rtc_resources[] = { 7262306a36Sopenharmony_ci { 7362306a36Sopenharmony_ci .name = "max8925-rtc", 7462306a36Sopenharmony_ci .start = MAX8925_IRQ_RTC_ALARM0, 7562306a36Sopenharmony_ci .end = MAX8925_IRQ_RTC_ALARM0, 7662306a36Sopenharmony_ci .flags = IORESOURCE_IRQ, 7762306a36Sopenharmony_ci }, 7862306a36Sopenharmony_ci}; 7962306a36Sopenharmony_ci 8062306a36Sopenharmony_cistatic const struct mfd_cell rtc_devs[] = { 8162306a36Sopenharmony_ci { 8262306a36Sopenharmony_ci .name = "max8925-rtc", 8362306a36Sopenharmony_ci .num_resources = 1, 8462306a36Sopenharmony_ci .resources = &rtc_resources[0], 8562306a36Sopenharmony_ci .id = -1, 8662306a36Sopenharmony_ci }, 8762306a36Sopenharmony_ci}; 8862306a36Sopenharmony_ci 8962306a36Sopenharmony_cistatic const struct resource onkey_resources[] = { 9062306a36Sopenharmony_ci { 9162306a36Sopenharmony_ci .name = "max8925-onkey", 9262306a36Sopenharmony_ci .start = MAX8925_IRQ_GPM_SW_R, 9362306a36Sopenharmony_ci .end = MAX8925_IRQ_GPM_SW_R, 9462306a36Sopenharmony_ci .flags = IORESOURCE_IRQ, 9562306a36Sopenharmony_ci }, { 9662306a36Sopenharmony_ci .name = "max8925-onkey", 9762306a36Sopenharmony_ci .start = MAX8925_IRQ_GPM_SW_F, 9862306a36Sopenharmony_ci .end = MAX8925_IRQ_GPM_SW_F, 9962306a36Sopenharmony_ci .flags = IORESOURCE_IRQ, 10062306a36Sopenharmony_ci }, 10162306a36Sopenharmony_ci}; 10262306a36Sopenharmony_ci 10362306a36Sopenharmony_cistatic const struct mfd_cell onkey_devs[] = { 10462306a36Sopenharmony_ci { 10562306a36Sopenharmony_ci .name = "max8925-onkey", 10662306a36Sopenharmony_ci .num_resources = 2, 10762306a36Sopenharmony_ci .resources = &onkey_resources[0], 10862306a36Sopenharmony_ci .id = -1, 10962306a36Sopenharmony_ci }, 11062306a36Sopenharmony_ci}; 11162306a36Sopenharmony_ci 11262306a36Sopenharmony_cistatic const struct resource sd1_resources[] = { 11362306a36Sopenharmony_ci {0x06, 0x06, "sdv", IORESOURCE_REG, }, 11462306a36Sopenharmony_ci}; 11562306a36Sopenharmony_ci 11662306a36Sopenharmony_cistatic const struct resource sd2_resources[] = { 11762306a36Sopenharmony_ci {0x09, 0x09, "sdv", IORESOURCE_REG, }, 11862306a36Sopenharmony_ci}; 11962306a36Sopenharmony_ci 12062306a36Sopenharmony_cistatic const struct resource sd3_resources[] = { 12162306a36Sopenharmony_ci {0x0c, 0x0c, "sdv", IORESOURCE_REG, }, 12262306a36Sopenharmony_ci}; 12362306a36Sopenharmony_ci 12462306a36Sopenharmony_cistatic const struct resource ldo1_resources[] = { 12562306a36Sopenharmony_ci {0x1a, 0x1a, "ldov", IORESOURCE_REG, }, 12662306a36Sopenharmony_ci}; 12762306a36Sopenharmony_ci 12862306a36Sopenharmony_cistatic const struct resource ldo2_resources[] = { 12962306a36Sopenharmony_ci {0x1e, 0x1e, "ldov", IORESOURCE_REG, }, 13062306a36Sopenharmony_ci}; 13162306a36Sopenharmony_ci 13262306a36Sopenharmony_cistatic const struct resource ldo3_resources[] = { 13362306a36Sopenharmony_ci {0x22, 0x22, "ldov", IORESOURCE_REG, }, 13462306a36Sopenharmony_ci}; 13562306a36Sopenharmony_ci 13662306a36Sopenharmony_cistatic const struct resource ldo4_resources[] = { 13762306a36Sopenharmony_ci {0x26, 0x26, "ldov", IORESOURCE_REG, }, 13862306a36Sopenharmony_ci}; 13962306a36Sopenharmony_ci 14062306a36Sopenharmony_cistatic const struct resource ldo5_resources[] = { 14162306a36Sopenharmony_ci {0x2a, 0x2a, "ldov", IORESOURCE_REG, }, 14262306a36Sopenharmony_ci}; 14362306a36Sopenharmony_ci 14462306a36Sopenharmony_cistatic const struct resource ldo6_resources[] = { 14562306a36Sopenharmony_ci {0x2e, 0x2e, "ldov", IORESOURCE_REG, }, 14662306a36Sopenharmony_ci}; 14762306a36Sopenharmony_ci 14862306a36Sopenharmony_cistatic const struct resource ldo7_resources[] = { 14962306a36Sopenharmony_ci {0x32, 0x32, "ldov", IORESOURCE_REG, }, 15062306a36Sopenharmony_ci}; 15162306a36Sopenharmony_ci 15262306a36Sopenharmony_cistatic const struct resource ldo8_resources[] = { 15362306a36Sopenharmony_ci {0x36, 0x36, "ldov", IORESOURCE_REG, }, 15462306a36Sopenharmony_ci}; 15562306a36Sopenharmony_ci 15662306a36Sopenharmony_cistatic const struct resource ldo9_resources[] = { 15762306a36Sopenharmony_ci {0x3a, 0x3a, "ldov", IORESOURCE_REG, }, 15862306a36Sopenharmony_ci}; 15962306a36Sopenharmony_ci 16062306a36Sopenharmony_cistatic const struct resource ldo10_resources[] = { 16162306a36Sopenharmony_ci {0x3e, 0x3e, "ldov", IORESOURCE_REG, }, 16262306a36Sopenharmony_ci}; 16362306a36Sopenharmony_ci 16462306a36Sopenharmony_cistatic const struct resource ldo11_resources[] = { 16562306a36Sopenharmony_ci {0x42, 0x42, "ldov", IORESOURCE_REG, }, 16662306a36Sopenharmony_ci}; 16762306a36Sopenharmony_ci 16862306a36Sopenharmony_cistatic const struct resource ldo12_resources[] = { 16962306a36Sopenharmony_ci {0x46, 0x46, "ldov", IORESOURCE_REG, }, 17062306a36Sopenharmony_ci}; 17162306a36Sopenharmony_ci 17262306a36Sopenharmony_cistatic const struct resource ldo13_resources[] = { 17362306a36Sopenharmony_ci {0x4a, 0x4a, "ldov", IORESOURCE_REG, }, 17462306a36Sopenharmony_ci}; 17562306a36Sopenharmony_ci 17662306a36Sopenharmony_cistatic const struct resource ldo14_resources[] = { 17762306a36Sopenharmony_ci {0x4e, 0x4e, "ldov", IORESOURCE_REG, }, 17862306a36Sopenharmony_ci}; 17962306a36Sopenharmony_ci 18062306a36Sopenharmony_cistatic const struct resource ldo15_resources[] = { 18162306a36Sopenharmony_ci {0x52, 0x52, "ldov", IORESOURCE_REG, }, 18262306a36Sopenharmony_ci}; 18362306a36Sopenharmony_ci 18462306a36Sopenharmony_cistatic const struct resource ldo16_resources[] = { 18562306a36Sopenharmony_ci {0x12, 0x12, "ldov", IORESOURCE_REG, }, 18662306a36Sopenharmony_ci}; 18762306a36Sopenharmony_ci 18862306a36Sopenharmony_cistatic const struct resource ldo17_resources[] = { 18962306a36Sopenharmony_ci {0x16, 0x16, "ldov", IORESOURCE_REG, }, 19062306a36Sopenharmony_ci}; 19162306a36Sopenharmony_ci 19262306a36Sopenharmony_cistatic const struct resource ldo18_resources[] = { 19362306a36Sopenharmony_ci {0x74, 0x74, "ldov", IORESOURCE_REG, }, 19462306a36Sopenharmony_ci}; 19562306a36Sopenharmony_ci 19662306a36Sopenharmony_cistatic const struct resource ldo19_resources[] = { 19762306a36Sopenharmony_ci {0x5e, 0x5e, "ldov", IORESOURCE_REG, }, 19862306a36Sopenharmony_ci}; 19962306a36Sopenharmony_ci 20062306a36Sopenharmony_cistatic const struct resource ldo20_resources[] = { 20162306a36Sopenharmony_ci {0x9e, 0x9e, "ldov", IORESOURCE_REG, }, 20262306a36Sopenharmony_ci}; 20362306a36Sopenharmony_ci 20462306a36Sopenharmony_cistatic struct mfd_cell reg_devs[] = { 20562306a36Sopenharmony_ci { 20662306a36Sopenharmony_ci .name = "max8925-regulator", 20762306a36Sopenharmony_ci .id = 0, 20862306a36Sopenharmony_ci .num_resources = ARRAY_SIZE(sd1_resources), 20962306a36Sopenharmony_ci .resources = sd1_resources, 21062306a36Sopenharmony_ci }, { 21162306a36Sopenharmony_ci .name = "max8925-regulator", 21262306a36Sopenharmony_ci .id = 1, 21362306a36Sopenharmony_ci .num_resources = ARRAY_SIZE(sd2_resources), 21462306a36Sopenharmony_ci .resources = sd2_resources, 21562306a36Sopenharmony_ci }, { 21662306a36Sopenharmony_ci .name = "max8925-regulator", 21762306a36Sopenharmony_ci .id = 2, 21862306a36Sopenharmony_ci .num_resources = ARRAY_SIZE(sd3_resources), 21962306a36Sopenharmony_ci .resources = sd3_resources, 22062306a36Sopenharmony_ci }, { 22162306a36Sopenharmony_ci .name = "max8925-regulator", 22262306a36Sopenharmony_ci .id = 3, 22362306a36Sopenharmony_ci .num_resources = ARRAY_SIZE(ldo1_resources), 22462306a36Sopenharmony_ci .resources = ldo1_resources, 22562306a36Sopenharmony_ci }, { 22662306a36Sopenharmony_ci .name = "max8925-regulator", 22762306a36Sopenharmony_ci .id = 4, 22862306a36Sopenharmony_ci .num_resources = ARRAY_SIZE(ldo2_resources), 22962306a36Sopenharmony_ci .resources = ldo2_resources, 23062306a36Sopenharmony_ci }, { 23162306a36Sopenharmony_ci .name = "max8925-regulator", 23262306a36Sopenharmony_ci .id = 5, 23362306a36Sopenharmony_ci .num_resources = ARRAY_SIZE(ldo3_resources), 23462306a36Sopenharmony_ci .resources = ldo3_resources, 23562306a36Sopenharmony_ci }, { 23662306a36Sopenharmony_ci .name = "max8925-regulator", 23762306a36Sopenharmony_ci .id = 6, 23862306a36Sopenharmony_ci .num_resources = ARRAY_SIZE(ldo4_resources), 23962306a36Sopenharmony_ci .resources = ldo4_resources, 24062306a36Sopenharmony_ci }, { 24162306a36Sopenharmony_ci .name = "max8925-regulator", 24262306a36Sopenharmony_ci .id = 7, 24362306a36Sopenharmony_ci .num_resources = ARRAY_SIZE(ldo5_resources), 24462306a36Sopenharmony_ci .resources = ldo5_resources, 24562306a36Sopenharmony_ci }, { 24662306a36Sopenharmony_ci .name = "max8925-regulator", 24762306a36Sopenharmony_ci .id = 8, 24862306a36Sopenharmony_ci .num_resources = ARRAY_SIZE(ldo6_resources), 24962306a36Sopenharmony_ci .resources = ldo6_resources, 25062306a36Sopenharmony_ci }, { 25162306a36Sopenharmony_ci .name = "max8925-regulator", 25262306a36Sopenharmony_ci .id = 9, 25362306a36Sopenharmony_ci .num_resources = ARRAY_SIZE(ldo7_resources), 25462306a36Sopenharmony_ci .resources = ldo7_resources, 25562306a36Sopenharmony_ci }, { 25662306a36Sopenharmony_ci .name = "max8925-regulator", 25762306a36Sopenharmony_ci .id = 10, 25862306a36Sopenharmony_ci .num_resources = ARRAY_SIZE(ldo8_resources), 25962306a36Sopenharmony_ci .resources = ldo8_resources, 26062306a36Sopenharmony_ci }, { 26162306a36Sopenharmony_ci .name = "max8925-regulator", 26262306a36Sopenharmony_ci .id = 11, 26362306a36Sopenharmony_ci .num_resources = ARRAY_SIZE(ldo9_resources), 26462306a36Sopenharmony_ci .resources = ldo9_resources, 26562306a36Sopenharmony_ci }, { 26662306a36Sopenharmony_ci .name = "max8925-regulator", 26762306a36Sopenharmony_ci .id = 12, 26862306a36Sopenharmony_ci .num_resources = ARRAY_SIZE(ldo10_resources), 26962306a36Sopenharmony_ci .resources = ldo10_resources, 27062306a36Sopenharmony_ci }, { 27162306a36Sopenharmony_ci .name = "max8925-regulator", 27262306a36Sopenharmony_ci .id = 13, 27362306a36Sopenharmony_ci .num_resources = ARRAY_SIZE(ldo11_resources), 27462306a36Sopenharmony_ci .resources = ldo11_resources, 27562306a36Sopenharmony_ci }, { 27662306a36Sopenharmony_ci .name = "max8925-regulator", 27762306a36Sopenharmony_ci .id = 14, 27862306a36Sopenharmony_ci .num_resources = ARRAY_SIZE(ldo12_resources), 27962306a36Sopenharmony_ci .resources = ldo12_resources, 28062306a36Sopenharmony_ci }, { 28162306a36Sopenharmony_ci .name = "max8925-regulator", 28262306a36Sopenharmony_ci .id = 15, 28362306a36Sopenharmony_ci .num_resources = ARRAY_SIZE(ldo13_resources), 28462306a36Sopenharmony_ci .resources = ldo13_resources, 28562306a36Sopenharmony_ci }, { 28662306a36Sopenharmony_ci .name = "max8925-regulator", 28762306a36Sopenharmony_ci .id = 16, 28862306a36Sopenharmony_ci .num_resources = ARRAY_SIZE(ldo14_resources), 28962306a36Sopenharmony_ci .resources = ldo14_resources, 29062306a36Sopenharmony_ci }, { 29162306a36Sopenharmony_ci .name = "max8925-regulator", 29262306a36Sopenharmony_ci .id = 17, 29362306a36Sopenharmony_ci .num_resources = ARRAY_SIZE(ldo15_resources), 29462306a36Sopenharmony_ci .resources = ldo15_resources, 29562306a36Sopenharmony_ci }, { 29662306a36Sopenharmony_ci .name = "max8925-regulator", 29762306a36Sopenharmony_ci .id = 18, 29862306a36Sopenharmony_ci .num_resources = ARRAY_SIZE(ldo16_resources), 29962306a36Sopenharmony_ci .resources = ldo16_resources, 30062306a36Sopenharmony_ci }, { 30162306a36Sopenharmony_ci .name = "max8925-regulator", 30262306a36Sopenharmony_ci .id = 19, 30362306a36Sopenharmony_ci .num_resources = ARRAY_SIZE(ldo17_resources), 30462306a36Sopenharmony_ci .resources = ldo17_resources, 30562306a36Sopenharmony_ci }, { 30662306a36Sopenharmony_ci .name = "max8925-regulator", 30762306a36Sopenharmony_ci .id = 20, 30862306a36Sopenharmony_ci .num_resources = ARRAY_SIZE(ldo18_resources), 30962306a36Sopenharmony_ci .resources = ldo18_resources, 31062306a36Sopenharmony_ci }, { 31162306a36Sopenharmony_ci .name = "max8925-regulator", 31262306a36Sopenharmony_ci .id = 21, 31362306a36Sopenharmony_ci .num_resources = ARRAY_SIZE(ldo19_resources), 31462306a36Sopenharmony_ci .resources = ldo19_resources, 31562306a36Sopenharmony_ci }, { 31662306a36Sopenharmony_ci .name = "max8925-regulator", 31762306a36Sopenharmony_ci .id = 22, 31862306a36Sopenharmony_ci .num_resources = ARRAY_SIZE(ldo20_resources), 31962306a36Sopenharmony_ci .resources = ldo20_resources, 32062306a36Sopenharmony_ci }, 32162306a36Sopenharmony_ci}; 32262306a36Sopenharmony_ci 32362306a36Sopenharmony_cienum { 32462306a36Sopenharmony_ci FLAGS_ADC = 1, /* register in ADC component */ 32562306a36Sopenharmony_ci FLAGS_RTC, /* register in RTC component */ 32662306a36Sopenharmony_ci}; 32762306a36Sopenharmony_ci 32862306a36Sopenharmony_cistruct max8925_irq_data { 32962306a36Sopenharmony_ci int reg; 33062306a36Sopenharmony_ci int mask_reg; 33162306a36Sopenharmony_ci int enable; /* enable or not */ 33262306a36Sopenharmony_ci int offs; /* bit offset in mask register */ 33362306a36Sopenharmony_ci int flags; 33462306a36Sopenharmony_ci int tsc_irq; 33562306a36Sopenharmony_ci}; 33662306a36Sopenharmony_ci 33762306a36Sopenharmony_cistatic struct max8925_irq_data max8925_irqs[] = { 33862306a36Sopenharmony_ci [MAX8925_IRQ_VCHG_DC_OVP] = { 33962306a36Sopenharmony_ci .reg = MAX8925_CHG_IRQ1, 34062306a36Sopenharmony_ci .mask_reg = MAX8925_CHG_IRQ1_MASK, 34162306a36Sopenharmony_ci .offs = 1 << 0, 34262306a36Sopenharmony_ci }, 34362306a36Sopenharmony_ci [MAX8925_IRQ_VCHG_DC_F] = { 34462306a36Sopenharmony_ci .reg = MAX8925_CHG_IRQ1, 34562306a36Sopenharmony_ci .mask_reg = MAX8925_CHG_IRQ1_MASK, 34662306a36Sopenharmony_ci .offs = 1 << 1, 34762306a36Sopenharmony_ci }, 34862306a36Sopenharmony_ci [MAX8925_IRQ_VCHG_DC_R] = { 34962306a36Sopenharmony_ci .reg = MAX8925_CHG_IRQ1, 35062306a36Sopenharmony_ci .mask_reg = MAX8925_CHG_IRQ1_MASK, 35162306a36Sopenharmony_ci .offs = 1 << 2, 35262306a36Sopenharmony_ci }, 35362306a36Sopenharmony_ci [MAX8925_IRQ_VCHG_THM_OK_R] = { 35462306a36Sopenharmony_ci .reg = MAX8925_CHG_IRQ2, 35562306a36Sopenharmony_ci .mask_reg = MAX8925_CHG_IRQ2_MASK, 35662306a36Sopenharmony_ci .offs = 1 << 0, 35762306a36Sopenharmony_ci }, 35862306a36Sopenharmony_ci [MAX8925_IRQ_VCHG_THM_OK_F] = { 35962306a36Sopenharmony_ci .reg = MAX8925_CHG_IRQ2, 36062306a36Sopenharmony_ci .mask_reg = MAX8925_CHG_IRQ2_MASK, 36162306a36Sopenharmony_ci .offs = 1 << 1, 36262306a36Sopenharmony_ci }, 36362306a36Sopenharmony_ci [MAX8925_IRQ_VCHG_SYSLOW_F] = { 36462306a36Sopenharmony_ci .reg = MAX8925_CHG_IRQ2, 36562306a36Sopenharmony_ci .mask_reg = MAX8925_CHG_IRQ2_MASK, 36662306a36Sopenharmony_ci .offs = 1 << 2, 36762306a36Sopenharmony_ci }, 36862306a36Sopenharmony_ci [MAX8925_IRQ_VCHG_SYSLOW_R] = { 36962306a36Sopenharmony_ci .reg = MAX8925_CHG_IRQ2, 37062306a36Sopenharmony_ci .mask_reg = MAX8925_CHG_IRQ2_MASK, 37162306a36Sopenharmony_ci .offs = 1 << 3, 37262306a36Sopenharmony_ci }, 37362306a36Sopenharmony_ci [MAX8925_IRQ_VCHG_RST] = { 37462306a36Sopenharmony_ci .reg = MAX8925_CHG_IRQ2, 37562306a36Sopenharmony_ci .mask_reg = MAX8925_CHG_IRQ2_MASK, 37662306a36Sopenharmony_ci .offs = 1 << 4, 37762306a36Sopenharmony_ci }, 37862306a36Sopenharmony_ci [MAX8925_IRQ_VCHG_DONE] = { 37962306a36Sopenharmony_ci .reg = MAX8925_CHG_IRQ2, 38062306a36Sopenharmony_ci .mask_reg = MAX8925_CHG_IRQ2_MASK, 38162306a36Sopenharmony_ci .offs = 1 << 5, 38262306a36Sopenharmony_ci }, 38362306a36Sopenharmony_ci [MAX8925_IRQ_VCHG_TOPOFF] = { 38462306a36Sopenharmony_ci .reg = MAX8925_CHG_IRQ2, 38562306a36Sopenharmony_ci .mask_reg = MAX8925_CHG_IRQ2_MASK, 38662306a36Sopenharmony_ci .offs = 1 << 6, 38762306a36Sopenharmony_ci }, 38862306a36Sopenharmony_ci [MAX8925_IRQ_VCHG_TMR_FAULT] = { 38962306a36Sopenharmony_ci .reg = MAX8925_CHG_IRQ2, 39062306a36Sopenharmony_ci .mask_reg = MAX8925_CHG_IRQ2_MASK, 39162306a36Sopenharmony_ci .offs = 1 << 7, 39262306a36Sopenharmony_ci }, 39362306a36Sopenharmony_ci [MAX8925_IRQ_GPM_RSTIN] = { 39462306a36Sopenharmony_ci .reg = MAX8925_ON_OFF_IRQ1, 39562306a36Sopenharmony_ci .mask_reg = MAX8925_ON_OFF_IRQ1_MASK, 39662306a36Sopenharmony_ci .offs = 1 << 0, 39762306a36Sopenharmony_ci }, 39862306a36Sopenharmony_ci [MAX8925_IRQ_GPM_MPL] = { 39962306a36Sopenharmony_ci .reg = MAX8925_ON_OFF_IRQ1, 40062306a36Sopenharmony_ci .mask_reg = MAX8925_ON_OFF_IRQ1_MASK, 40162306a36Sopenharmony_ci .offs = 1 << 1, 40262306a36Sopenharmony_ci }, 40362306a36Sopenharmony_ci [MAX8925_IRQ_GPM_SW_3SEC] = { 40462306a36Sopenharmony_ci .reg = MAX8925_ON_OFF_IRQ1, 40562306a36Sopenharmony_ci .mask_reg = MAX8925_ON_OFF_IRQ1_MASK, 40662306a36Sopenharmony_ci .offs = 1 << 2, 40762306a36Sopenharmony_ci }, 40862306a36Sopenharmony_ci [MAX8925_IRQ_GPM_EXTON_F] = { 40962306a36Sopenharmony_ci .reg = MAX8925_ON_OFF_IRQ1, 41062306a36Sopenharmony_ci .mask_reg = MAX8925_ON_OFF_IRQ1_MASK, 41162306a36Sopenharmony_ci .offs = 1 << 3, 41262306a36Sopenharmony_ci }, 41362306a36Sopenharmony_ci [MAX8925_IRQ_GPM_EXTON_R] = { 41462306a36Sopenharmony_ci .reg = MAX8925_ON_OFF_IRQ1, 41562306a36Sopenharmony_ci .mask_reg = MAX8925_ON_OFF_IRQ1_MASK, 41662306a36Sopenharmony_ci .offs = 1 << 4, 41762306a36Sopenharmony_ci }, 41862306a36Sopenharmony_ci [MAX8925_IRQ_GPM_SW_1SEC] = { 41962306a36Sopenharmony_ci .reg = MAX8925_ON_OFF_IRQ1, 42062306a36Sopenharmony_ci .mask_reg = MAX8925_ON_OFF_IRQ1_MASK, 42162306a36Sopenharmony_ci .offs = 1 << 5, 42262306a36Sopenharmony_ci }, 42362306a36Sopenharmony_ci [MAX8925_IRQ_GPM_SW_F] = { 42462306a36Sopenharmony_ci .reg = MAX8925_ON_OFF_IRQ1, 42562306a36Sopenharmony_ci .mask_reg = MAX8925_ON_OFF_IRQ1_MASK, 42662306a36Sopenharmony_ci .offs = 1 << 6, 42762306a36Sopenharmony_ci }, 42862306a36Sopenharmony_ci [MAX8925_IRQ_GPM_SW_R] = { 42962306a36Sopenharmony_ci .reg = MAX8925_ON_OFF_IRQ1, 43062306a36Sopenharmony_ci .mask_reg = MAX8925_ON_OFF_IRQ1_MASK, 43162306a36Sopenharmony_ci .offs = 1 << 7, 43262306a36Sopenharmony_ci }, 43362306a36Sopenharmony_ci [MAX8925_IRQ_GPM_SYSCKEN_F] = { 43462306a36Sopenharmony_ci .reg = MAX8925_ON_OFF_IRQ2, 43562306a36Sopenharmony_ci .mask_reg = MAX8925_ON_OFF_IRQ2_MASK, 43662306a36Sopenharmony_ci .offs = 1 << 0, 43762306a36Sopenharmony_ci }, 43862306a36Sopenharmony_ci [MAX8925_IRQ_GPM_SYSCKEN_R] = { 43962306a36Sopenharmony_ci .reg = MAX8925_ON_OFF_IRQ2, 44062306a36Sopenharmony_ci .mask_reg = MAX8925_ON_OFF_IRQ2_MASK, 44162306a36Sopenharmony_ci .offs = 1 << 1, 44262306a36Sopenharmony_ci }, 44362306a36Sopenharmony_ci [MAX8925_IRQ_RTC_ALARM1] = { 44462306a36Sopenharmony_ci .reg = MAX8925_RTC_IRQ, 44562306a36Sopenharmony_ci .mask_reg = MAX8925_RTC_IRQ_MASK, 44662306a36Sopenharmony_ci .offs = 1 << 2, 44762306a36Sopenharmony_ci .flags = FLAGS_RTC, 44862306a36Sopenharmony_ci }, 44962306a36Sopenharmony_ci [MAX8925_IRQ_RTC_ALARM0] = { 45062306a36Sopenharmony_ci .reg = MAX8925_RTC_IRQ, 45162306a36Sopenharmony_ci .mask_reg = MAX8925_RTC_IRQ_MASK, 45262306a36Sopenharmony_ci .offs = 1 << 3, 45362306a36Sopenharmony_ci .flags = FLAGS_RTC, 45462306a36Sopenharmony_ci }, 45562306a36Sopenharmony_ci [MAX8925_IRQ_TSC_STICK] = { 45662306a36Sopenharmony_ci .reg = MAX8925_TSC_IRQ, 45762306a36Sopenharmony_ci .mask_reg = MAX8925_TSC_IRQ_MASK, 45862306a36Sopenharmony_ci .offs = 1 << 0, 45962306a36Sopenharmony_ci .flags = FLAGS_ADC, 46062306a36Sopenharmony_ci .tsc_irq = 1, 46162306a36Sopenharmony_ci }, 46262306a36Sopenharmony_ci [MAX8925_IRQ_TSC_NSTICK] = { 46362306a36Sopenharmony_ci .reg = MAX8925_TSC_IRQ, 46462306a36Sopenharmony_ci .mask_reg = MAX8925_TSC_IRQ_MASK, 46562306a36Sopenharmony_ci .offs = 1 << 1, 46662306a36Sopenharmony_ci .flags = FLAGS_ADC, 46762306a36Sopenharmony_ci .tsc_irq = 1, 46862306a36Sopenharmony_ci }, 46962306a36Sopenharmony_ci}; 47062306a36Sopenharmony_ci 47162306a36Sopenharmony_cistatic irqreturn_t max8925_irq(int irq, void *data) 47262306a36Sopenharmony_ci{ 47362306a36Sopenharmony_ci struct max8925_chip *chip = data; 47462306a36Sopenharmony_ci struct max8925_irq_data *irq_data; 47562306a36Sopenharmony_ci struct i2c_client *i2c; 47662306a36Sopenharmony_ci int read_reg = -1, value = 0; 47762306a36Sopenharmony_ci int i; 47862306a36Sopenharmony_ci 47962306a36Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(max8925_irqs); i++) { 48062306a36Sopenharmony_ci irq_data = &max8925_irqs[i]; 48162306a36Sopenharmony_ci /* TSC IRQ should be serviced in max8925_tsc_irq() */ 48262306a36Sopenharmony_ci if (irq_data->tsc_irq) 48362306a36Sopenharmony_ci continue; 48462306a36Sopenharmony_ci if (irq_data->flags == FLAGS_RTC) 48562306a36Sopenharmony_ci i2c = chip->rtc; 48662306a36Sopenharmony_ci else if (irq_data->flags == FLAGS_ADC) 48762306a36Sopenharmony_ci i2c = chip->adc; 48862306a36Sopenharmony_ci else 48962306a36Sopenharmony_ci i2c = chip->i2c; 49062306a36Sopenharmony_ci if (read_reg != irq_data->reg) { 49162306a36Sopenharmony_ci read_reg = irq_data->reg; 49262306a36Sopenharmony_ci value = max8925_reg_read(i2c, irq_data->reg); 49362306a36Sopenharmony_ci } 49462306a36Sopenharmony_ci if (value & irq_data->enable) 49562306a36Sopenharmony_ci handle_nested_irq(chip->irq_base + i); 49662306a36Sopenharmony_ci } 49762306a36Sopenharmony_ci return IRQ_HANDLED; 49862306a36Sopenharmony_ci} 49962306a36Sopenharmony_ci 50062306a36Sopenharmony_cistatic irqreturn_t max8925_tsc_irq(int irq, void *data) 50162306a36Sopenharmony_ci{ 50262306a36Sopenharmony_ci struct max8925_chip *chip = data; 50362306a36Sopenharmony_ci struct max8925_irq_data *irq_data; 50462306a36Sopenharmony_ci struct i2c_client *i2c; 50562306a36Sopenharmony_ci int read_reg = -1, value = 0; 50662306a36Sopenharmony_ci int i; 50762306a36Sopenharmony_ci 50862306a36Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(max8925_irqs); i++) { 50962306a36Sopenharmony_ci irq_data = &max8925_irqs[i]; 51062306a36Sopenharmony_ci /* non TSC IRQ should be serviced in max8925_irq() */ 51162306a36Sopenharmony_ci if (!irq_data->tsc_irq) 51262306a36Sopenharmony_ci continue; 51362306a36Sopenharmony_ci if (irq_data->flags == FLAGS_RTC) 51462306a36Sopenharmony_ci i2c = chip->rtc; 51562306a36Sopenharmony_ci else if (irq_data->flags == FLAGS_ADC) 51662306a36Sopenharmony_ci i2c = chip->adc; 51762306a36Sopenharmony_ci else 51862306a36Sopenharmony_ci i2c = chip->i2c; 51962306a36Sopenharmony_ci if (read_reg != irq_data->reg) { 52062306a36Sopenharmony_ci read_reg = irq_data->reg; 52162306a36Sopenharmony_ci value = max8925_reg_read(i2c, irq_data->reg); 52262306a36Sopenharmony_ci } 52362306a36Sopenharmony_ci if (value & irq_data->enable) 52462306a36Sopenharmony_ci handle_nested_irq(chip->irq_base + i); 52562306a36Sopenharmony_ci } 52662306a36Sopenharmony_ci return IRQ_HANDLED; 52762306a36Sopenharmony_ci} 52862306a36Sopenharmony_ci 52962306a36Sopenharmony_cistatic void max8925_irq_lock(struct irq_data *data) 53062306a36Sopenharmony_ci{ 53162306a36Sopenharmony_ci struct max8925_chip *chip = irq_data_get_irq_chip_data(data); 53262306a36Sopenharmony_ci 53362306a36Sopenharmony_ci mutex_lock(&chip->irq_lock); 53462306a36Sopenharmony_ci} 53562306a36Sopenharmony_ci 53662306a36Sopenharmony_cistatic void max8925_irq_sync_unlock(struct irq_data *data) 53762306a36Sopenharmony_ci{ 53862306a36Sopenharmony_ci struct max8925_chip *chip = irq_data_get_irq_chip_data(data); 53962306a36Sopenharmony_ci struct max8925_irq_data *irq_data; 54062306a36Sopenharmony_ci static unsigned char cache_chg[2] = {0xff, 0xff}; 54162306a36Sopenharmony_ci static unsigned char cache_on[2] = {0xff, 0xff}; 54262306a36Sopenharmony_ci static unsigned char cache_rtc = 0xff, cache_tsc = 0xff; 54362306a36Sopenharmony_ci unsigned char irq_chg[2], irq_on[2]; 54462306a36Sopenharmony_ci unsigned char irq_rtc, irq_tsc; 54562306a36Sopenharmony_ci int i; 54662306a36Sopenharmony_ci 54762306a36Sopenharmony_ci /* Load cached value. In initial, all IRQs are masked */ 54862306a36Sopenharmony_ci irq_chg[0] = cache_chg[0]; 54962306a36Sopenharmony_ci irq_chg[1] = cache_chg[1]; 55062306a36Sopenharmony_ci irq_on[0] = cache_on[0]; 55162306a36Sopenharmony_ci irq_on[1] = cache_on[1]; 55262306a36Sopenharmony_ci irq_rtc = cache_rtc; 55362306a36Sopenharmony_ci irq_tsc = cache_tsc; 55462306a36Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(max8925_irqs); i++) { 55562306a36Sopenharmony_ci irq_data = &max8925_irqs[i]; 55662306a36Sopenharmony_ci /* 1 -- disable, 0 -- enable */ 55762306a36Sopenharmony_ci switch (irq_data->mask_reg) { 55862306a36Sopenharmony_ci case MAX8925_CHG_IRQ1_MASK: 55962306a36Sopenharmony_ci irq_chg[0] &= ~irq_data->enable; 56062306a36Sopenharmony_ci break; 56162306a36Sopenharmony_ci case MAX8925_CHG_IRQ2_MASK: 56262306a36Sopenharmony_ci irq_chg[1] &= ~irq_data->enable; 56362306a36Sopenharmony_ci break; 56462306a36Sopenharmony_ci case MAX8925_ON_OFF_IRQ1_MASK: 56562306a36Sopenharmony_ci irq_on[0] &= ~irq_data->enable; 56662306a36Sopenharmony_ci break; 56762306a36Sopenharmony_ci case MAX8925_ON_OFF_IRQ2_MASK: 56862306a36Sopenharmony_ci irq_on[1] &= ~irq_data->enable; 56962306a36Sopenharmony_ci break; 57062306a36Sopenharmony_ci case MAX8925_RTC_IRQ_MASK: 57162306a36Sopenharmony_ci irq_rtc &= ~irq_data->enable; 57262306a36Sopenharmony_ci break; 57362306a36Sopenharmony_ci case MAX8925_TSC_IRQ_MASK: 57462306a36Sopenharmony_ci irq_tsc &= ~irq_data->enable; 57562306a36Sopenharmony_ci break; 57662306a36Sopenharmony_ci default: 57762306a36Sopenharmony_ci dev_err(chip->dev, "wrong IRQ\n"); 57862306a36Sopenharmony_ci break; 57962306a36Sopenharmony_ci } 58062306a36Sopenharmony_ci } 58162306a36Sopenharmony_ci /* update mask into registers */ 58262306a36Sopenharmony_ci if (cache_chg[0] != irq_chg[0]) { 58362306a36Sopenharmony_ci cache_chg[0] = irq_chg[0]; 58462306a36Sopenharmony_ci max8925_reg_write(chip->i2c, MAX8925_CHG_IRQ1_MASK, 58562306a36Sopenharmony_ci irq_chg[0]); 58662306a36Sopenharmony_ci } 58762306a36Sopenharmony_ci if (cache_chg[1] != irq_chg[1]) { 58862306a36Sopenharmony_ci cache_chg[1] = irq_chg[1]; 58962306a36Sopenharmony_ci max8925_reg_write(chip->i2c, MAX8925_CHG_IRQ2_MASK, 59062306a36Sopenharmony_ci irq_chg[1]); 59162306a36Sopenharmony_ci } 59262306a36Sopenharmony_ci if (cache_on[0] != irq_on[0]) { 59362306a36Sopenharmony_ci cache_on[0] = irq_on[0]; 59462306a36Sopenharmony_ci max8925_reg_write(chip->i2c, MAX8925_ON_OFF_IRQ1_MASK, 59562306a36Sopenharmony_ci irq_on[0]); 59662306a36Sopenharmony_ci } 59762306a36Sopenharmony_ci if (cache_on[1] != irq_on[1]) { 59862306a36Sopenharmony_ci cache_on[1] = irq_on[1]; 59962306a36Sopenharmony_ci max8925_reg_write(chip->i2c, MAX8925_ON_OFF_IRQ2_MASK, 60062306a36Sopenharmony_ci irq_on[1]); 60162306a36Sopenharmony_ci } 60262306a36Sopenharmony_ci if (cache_rtc != irq_rtc) { 60362306a36Sopenharmony_ci cache_rtc = irq_rtc; 60462306a36Sopenharmony_ci max8925_reg_write(chip->rtc, MAX8925_RTC_IRQ_MASK, irq_rtc); 60562306a36Sopenharmony_ci } 60662306a36Sopenharmony_ci if (cache_tsc != irq_tsc) { 60762306a36Sopenharmony_ci cache_tsc = irq_tsc; 60862306a36Sopenharmony_ci max8925_reg_write(chip->adc, MAX8925_TSC_IRQ_MASK, irq_tsc); 60962306a36Sopenharmony_ci } 61062306a36Sopenharmony_ci 61162306a36Sopenharmony_ci mutex_unlock(&chip->irq_lock); 61262306a36Sopenharmony_ci} 61362306a36Sopenharmony_ci 61462306a36Sopenharmony_cistatic void max8925_irq_enable(struct irq_data *data) 61562306a36Sopenharmony_ci{ 61662306a36Sopenharmony_ci struct max8925_chip *chip = irq_data_get_irq_chip_data(data); 61762306a36Sopenharmony_ci 61862306a36Sopenharmony_ci max8925_irqs[data->irq - chip->irq_base].enable 61962306a36Sopenharmony_ci = max8925_irqs[data->irq - chip->irq_base].offs; 62062306a36Sopenharmony_ci} 62162306a36Sopenharmony_ci 62262306a36Sopenharmony_cistatic void max8925_irq_disable(struct irq_data *data) 62362306a36Sopenharmony_ci{ 62462306a36Sopenharmony_ci struct max8925_chip *chip = irq_data_get_irq_chip_data(data); 62562306a36Sopenharmony_ci 62662306a36Sopenharmony_ci max8925_irqs[data->irq - chip->irq_base].enable = 0; 62762306a36Sopenharmony_ci} 62862306a36Sopenharmony_ci 62962306a36Sopenharmony_cistatic struct irq_chip max8925_irq_chip = { 63062306a36Sopenharmony_ci .name = "max8925", 63162306a36Sopenharmony_ci .irq_bus_lock = max8925_irq_lock, 63262306a36Sopenharmony_ci .irq_bus_sync_unlock = max8925_irq_sync_unlock, 63362306a36Sopenharmony_ci .irq_enable = max8925_irq_enable, 63462306a36Sopenharmony_ci .irq_disable = max8925_irq_disable, 63562306a36Sopenharmony_ci}; 63662306a36Sopenharmony_ci 63762306a36Sopenharmony_cistatic int max8925_irq_domain_map(struct irq_domain *d, unsigned int virq, 63862306a36Sopenharmony_ci irq_hw_number_t hw) 63962306a36Sopenharmony_ci{ 64062306a36Sopenharmony_ci irq_set_chip_data(virq, d->host_data); 64162306a36Sopenharmony_ci irq_set_chip_and_handler(virq, &max8925_irq_chip, handle_edge_irq); 64262306a36Sopenharmony_ci irq_set_nested_thread(virq, 1); 64362306a36Sopenharmony_ci irq_set_noprobe(virq); 64462306a36Sopenharmony_ci 64562306a36Sopenharmony_ci return 0; 64662306a36Sopenharmony_ci} 64762306a36Sopenharmony_ci 64862306a36Sopenharmony_cistatic const struct irq_domain_ops max8925_irq_domain_ops = { 64962306a36Sopenharmony_ci .map = max8925_irq_domain_map, 65062306a36Sopenharmony_ci .xlate = irq_domain_xlate_onetwocell, 65162306a36Sopenharmony_ci}; 65262306a36Sopenharmony_ci 65362306a36Sopenharmony_ci 65462306a36Sopenharmony_cistatic int max8925_irq_init(struct max8925_chip *chip, int irq, 65562306a36Sopenharmony_ci struct max8925_platform_data *pdata) 65662306a36Sopenharmony_ci{ 65762306a36Sopenharmony_ci unsigned long flags = IRQF_TRIGGER_FALLING | IRQF_ONESHOT; 65862306a36Sopenharmony_ci int ret; 65962306a36Sopenharmony_ci struct device_node *node = chip->dev->of_node; 66062306a36Sopenharmony_ci 66162306a36Sopenharmony_ci /* clear all interrupts */ 66262306a36Sopenharmony_ci max8925_reg_read(chip->i2c, MAX8925_CHG_IRQ1); 66362306a36Sopenharmony_ci max8925_reg_read(chip->i2c, MAX8925_CHG_IRQ2); 66462306a36Sopenharmony_ci max8925_reg_read(chip->i2c, MAX8925_ON_OFF_IRQ1); 66562306a36Sopenharmony_ci max8925_reg_read(chip->i2c, MAX8925_ON_OFF_IRQ2); 66662306a36Sopenharmony_ci max8925_reg_read(chip->rtc, MAX8925_RTC_IRQ); 66762306a36Sopenharmony_ci max8925_reg_read(chip->adc, MAX8925_TSC_IRQ); 66862306a36Sopenharmony_ci /* mask all interrupts except for TSC */ 66962306a36Sopenharmony_ci max8925_reg_write(chip->rtc, MAX8925_ALARM0_CNTL, 0); 67062306a36Sopenharmony_ci max8925_reg_write(chip->rtc, MAX8925_ALARM1_CNTL, 0); 67162306a36Sopenharmony_ci max8925_reg_write(chip->i2c, MAX8925_CHG_IRQ1_MASK, 0xff); 67262306a36Sopenharmony_ci max8925_reg_write(chip->i2c, MAX8925_CHG_IRQ2_MASK, 0xff); 67362306a36Sopenharmony_ci max8925_reg_write(chip->i2c, MAX8925_ON_OFF_IRQ1_MASK, 0xff); 67462306a36Sopenharmony_ci max8925_reg_write(chip->i2c, MAX8925_ON_OFF_IRQ2_MASK, 0xff); 67562306a36Sopenharmony_ci max8925_reg_write(chip->rtc, MAX8925_RTC_IRQ_MASK, 0xff); 67662306a36Sopenharmony_ci 67762306a36Sopenharmony_ci mutex_init(&chip->irq_lock); 67862306a36Sopenharmony_ci chip->irq_base = irq_alloc_descs(-1, 0, MAX8925_NR_IRQS, 0); 67962306a36Sopenharmony_ci if (chip->irq_base < 0) { 68062306a36Sopenharmony_ci dev_err(chip->dev, "Failed to allocate interrupts, ret:%d\n", 68162306a36Sopenharmony_ci chip->irq_base); 68262306a36Sopenharmony_ci return -EBUSY; 68362306a36Sopenharmony_ci } 68462306a36Sopenharmony_ci 68562306a36Sopenharmony_ci irq_domain_add_legacy(node, MAX8925_NR_IRQS, chip->irq_base, 0, 68662306a36Sopenharmony_ci &max8925_irq_domain_ops, chip); 68762306a36Sopenharmony_ci 68862306a36Sopenharmony_ci /* request irq handler for pmic main irq*/ 68962306a36Sopenharmony_ci chip->core_irq = irq; 69062306a36Sopenharmony_ci if (!chip->core_irq) 69162306a36Sopenharmony_ci return -EBUSY; 69262306a36Sopenharmony_ci ret = request_threaded_irq(irq, NULL, max8925_irq, flags | IRQF_ONESHOT, 69362306a36Sopenharmony_ci "max8925", chip); 69462306a36Sopenharmony_ci if (ret) { 69562306a36Sopenharmony_ci dev_err(chip->dev, "Failed to request core IRQ: %d\n", ret); 69662306a36Sopenharmony_ci chip->core_irq = 0; 69762306a36Sopenharmony_ci return -EBUSY; 69862306a36Sopenharmony_ci } 69962306a36Sopenharmony_ci 70062306a36Sopenharmony_ci /* request irq handler for pmic tsc irq*/ 70162306a36Sopenharmony_ci 70262306a36Sopenharmony_ci /* mask TSC interrupt */ 70362306a36Sopenharmony_ci max8925_reg_write(chip->adc, MAX8925_TSC_IRQ_MASK, 0x0f); 70462306a36Sopenharmony_ci 70562306a36Sopenharmony_ci if (!pdata->tsc_irq) { 70662306a36Sopenharmony_ci dev_warn(chip->dev, "No interrupt support on TSC IRQ\n"); 70762306a36Sopenharmony_ci return 0; 70862306a36Sopenharmony_ci } 70962306a36Sopenharmony_ci chip->tsc_irq = pdata->tsc_irq; 71062306a36Sopenharmony_ci ret = request_threaded_irq(chip->tsc_irq, NULL, max8925_tsc_irq, 71162306a36Sopenharmony_ci flags | IRQF_ONESHOT, "max8925-tsc", chip); 71262306a36Sopenharmony_ci if (ret) { 71362306a36Sopenharmony_ci dev_err(chip->dev, "Failed to request TSC IRQ: %d\n", ret); 71462306a36Sopenharmony_ci chip->tsc_irq = 0; 71562306a36Sopenharmony_ci } 71662306a36Sopenharmony_ci return 0; 71762306a36Sopenharmony_ci} 71862306a36Sopenharmony_ci 71962306a36Sopenharmony_cistatic void init_regulator(struct max8925_chip *chip, 72062306a36Sopenharmony_ci struct max8925_platform_data *pdata) 72162306a36Sopenharmony_ci{ 72262306a36Sopenharmony_ci int ret; 72362306a36Sopenharmony_ci 72462306a36Sopenharmony_ci if (!pdata) 72562306a36Sopenharmony_ci return; 72662306a36Sopenharmony_ci if (pdata->sd1) { 72762306a36Sopenharmony_ci reg_devs[0].platform_data = pdata->sd1; 72862306a36Sopenharmony_ci reg_devs[0].pdata_size = sizeof(struct regulator_init_data); 72962306a36Sopenharmony_ci } 73062306a36Sopenharmony_ci if (pdata->sd2) { 73162306a36Sopenharmony_ci reg_devs[1].platform_data = pdata->sd2; 73262306a36Sopenharmony_ci reg_devs[1].pdata_size = sizeof(struct regulator_init_data); 73362306a36Sopenharmony_ci } 73462306a36Sopenharmony_ci if (pdata->sd3) { 73562306a36Sopenharmony_ci reg_devs[2].platform_data = pdata->sd3; 73662306a36Sopenharmony_ci reg_devs[2].pdata_size = sizeof(struct regulator_init_data); 73762306a36Sopenharmony_ci } 73862306a36Sopenharmony_ci if (pdata->ldo1) { 73962306a36Sopenharmony_ci reg_devs[3].platform_data = pdata->ldo1; 74062306a36Sopenharmony_ci reg_devs[3].pdata_size = sizeof(struct regulator_init_data); 74162306a36Sopenharmony_ci } 74262306a36Sopenharmony_ci if (pdata->ldo2) { 74362306a36Sopenharmony_ci reg_devs[4].platform_data = pdata->ldo2; 74462306a36Sopenharmony_ci reg_devs[4].pdata_size = sizeof(struct regulator_init_data); 74562306a36Sopenharmony_ci } 74662306a36Sopenharmony_ci if (pdata->ldo3) { 74762306a36Sopenharmony_ci reg_devs[5].platform_data = pdata->ldo3; 74862306a36Sopenharmony_ci reg_devs[5].pdata_size = sizeof(struct regulator_init_data); 74962306a36Sopenharmony_ci } 75062306a36Sopenharmony_ci if (pdata->ldo4) { 75162306a36Sopenharmony_ci reg_devs[6].platform_data = pdata->ldo4; 75262306a36Sopenharmony_ci reg_devs[6].pdata_size = sizeof(struct regulator_init_data); 75362306a36Sopenharmony_ci } 75462306a36Sopenharmony_ci if (pdata->ldo5) { 75562306a36Sopenharmony_ci reg_devs[7].platform_data = pdata->ldo5; 75662306a36Sopenharmony_ci reg_devs[7].pdata_size = sizeof(struct regulator_init_data); 75762306a36Sopenharmony_ci } 75862306a36Sopenharmony_ci if (pdata->ldo6) { 75962306a36Sopenharmony_ci reg_devs[8].platform_data = pdata->ldo6; 76062306a36Sopenharmony_ci reg_devs[8].pdata_size = sizeof(struct regulator_init_data); 76162306a36Sopenharmony_ci } 76262306a36Sopenharmony_ci if (pdata->ldo7) { 76362306a36Sopenharmony_ci reg_devs[9].platform_data = pdata->ldo7; 76462306a36Sopenharmony_ci reg_devs[9].pdata_size = sizeof(struct regulator_init_data); 76562306a36Sopenharmony_ci } 76662306a36Sopenharmony_ci if (pdata->ldo8) { 76762306a36Sopenharmony_ci reg_devs[10].platform_data = pdata->ldo8; 76862306a36Sopenharmony_ci reg_devs[10].pdata_size = sizeof(struct regulator_init_data); 76962306a36Sopenharmony_ci } 77062306a36Sopenharmony_ci if (pdata->ldo9) { 77162306a36Sopenharmony_ci reg_devs[11].platform_data = pdata->ldo9; 77262306a36Sopenharmony_ci reg_devs[11].pdata_size = sizeof(struct regulator_init_data); 77362306a36Sopenharmony_ci } 77462306a36Sopenharmony_ci if (pdata->ldo10) { 77562306a36Sopenharmony_ci reg_devs[12].platform_data = pdata->ldo10; 77662306a36Sopenharmony_ci reg_devs[12].pdata_size = sizeof(struct regulator_init_data); 77762306a36Sopenharmony_ci } 77862306a36Sopenharmony_ci if (pdata->ldo11) { 77962306a36Sopenharmony_ci reg_devs[13].platform_data = pdata->ldo11; 78062306a36Sopenharmony_ci reg_devs[13].pdata_size = sizeof(struct regulator_init_data); 78162306a36Sopenharmony_ci } 78262306a36Sopenharmony_ci if (pdata->ldo12) { 78362306a36Sopenharmony_ci reg_devs[14].platform_data = pdata->ldo12; 78462306a36Sopenharmony_ci reg_devs[14].pdata_size = sizeof(struct regulator_init_data); 78562306a36Sopenharmony_ci } 78662306a36Sopenharmony_ci if (pdata->ldo13) { 78762306a36Sopenharmony_ci reg_devs[15].platform_data = pdata->ldo13; 78862306a36Sopenharmony_ci reg_devs[15].pdata_size = sizeof(struct regulator_init_data); 78962306a36Sopenharmony_ci } 79062306a36Sopenharmony_ci if (pdata->ldo14) { 79162306a36Sopenharmony_ci reg_devs[16].platform_data = pdata->ldo14; 79262306a36Sopenharmony_ci reg_devs[16].pdata_size = sizeof(struct regulator_init_data); 79362306a36Sopenharmony_ci } 79462306a36Sopenharmony_ci if (pdata->ldo15) { 79562306a36Sopenharmony_ci reg_devs[17].platform_data = pdata->ldo15; 79662306a36Sopenharmony_ci reg_devs[17].pdata_size = sizeof(struct regulator_init_data); 79762306a36Sopenharmony_ci } 79862306a36Sopenharmony_ci if (pdata->ldo16) { 79962306a36Sopenharmony_ci reg_devs[18].platform_data = pdata->ldo16; 80062306a36Sopenharmony_ci reg_devs[18].pdata_size = sizeof(struct regulator_init_data); 80162306a36Sopenharmony_ci } 80262306a36Sopenharmony_ci if (pdata->ldo17) { 80362306a36Sopenharmony_ci reg_devs[19].platform_data = pdata->ldo17; 80462306a36Sopenharmony_ci reg_devs[19].pdata_size = sizeof(struct regulator_init_data); 80562306a36Sopenharmony_ci } 80662306a36Sopenharmony_ci if (pdata->ldo18) { 80762306a36Sopenharmony_ci reg_devs[20].platform_data = pdata->ldo18; 80862306a36Sopenharmony_ci reg_devs[20].pdata_size = sizeof(struct regulator_init_data); 80962306a36Sopenharmony_ci } 81062306a36Sopenharmony_ci if (pdata->ldo19) { 81162306a36Sopenharmony_ci reg_devs[21].platform_data = pdata->ldo19; 81262306a36Sopenharmony_ci reg_devs[21].pdata_size = sizeof(struct regulator_init_data); 81362306a36Sopenharmony_ci } 81462306a36Sopenharmony_ci if (pdata->ldo20) { 81562306a36Sopenharmony_ci reg_devs[22].platform_data = pdata->ldo20; 81662306a36Sopenharmony_ci reg_devs[22].pdata_size = sizeof(struct regulator_init_data); 81762306a36Sopenharmony_ci } 81862306a36Sopenharmony_ci ret = mfd_add_devices(chip->dev, 0, reg_devs, ARRAY_SIZE(reg_devs), 81962306a36Sopenharmony_ci NULL, 0, NULL); 82062306a36Sopenharmony_ci if (ret < 0) { 82162306a36Sopenharmony_ci dev_err(chip->dev, "Failed to add regulator subdev\n"); 82262306a36Sopenharmony_ci return; 82362306a36Sopenharmony_ci } 82462306a36Sopenharmony_ci} 82562306a36Sopenharmony_ci 82662306a36Sopenharmony_ciint max8925_device_init(struct max8925_chip *chip, 82762306a36Sopenharmony_ci struct max8925_platform_data *pdata) 82862306a36Sopenharmony_ci{ 82962306a36Sopenharmony_ci int ret; 83062306a36Sopenharmony_ci 83162306a36Sopenharmony_ci max8925_irq_init(chip, chip->i2c->irq, pdata); 83262306a36Sopenharmony_ci 83362306a36Sopenharmony_ci if (pdata && (pdata->power || pdata->touch)) { 83462306a36Sopenharmony_ci /* enable ADC to control internal reference */ 83562306a36Sopenharmony_ci max8925_set_bits(chip->i2c, MAX8925_RESET_CNFG, 1, 1); 83662306a36Sopenharmony_ci /* enable internal reference for ADC */ 83762306a36Sopenharmony_ci max8925_set_bits(chip->adc, MAX8925_TSC_CNFG1, 3, 2); 83862306a36Sopenharmony_ci /* check for internal reference IRQ */ 83962306a36Sopenharmony_ci do { 84062306a36Sopenharmony_ci ret = max8925_reg_read(chip->adc, MAX8925_TSC_IRQ); 84162306a36Sopenharmony_ci } while (ret & MAX8925_NREF_OK); 84262306a36Sopenharmony_ci /* enaable ADC scheduler, interval is 1 second */ 84362306a36Sopenharmony_ci max8925_set_bits(chip->adc, MAX8925_ADC_SCHED, 3, 2); 84462306a36Sopenharmony_ci } 84562306a36Sopenharmony_ci 84662306a36Sopenharmony_ci /* enable Momentary Power Loss */ 84762306a36Sopenharmony_ci max8925_set_bits(chip->rtc, MAX8925_MPL_CNTL, 1 << 4, 1 << 4); 84862306a36Sopenharmony_ci 84962306a36Sopenharmony_ci ret = mfd_add_devices(chip->dev, 0, &rtc_devs[0], 85062306a36Sopenharmony_ci ARRAY_SIZE(rtc_devs), 85162306a36Sopenharmony_ci NULL, chip->irq_base, NULL); 85262306a36Sopenharmony_ci if (ret < 0) { 85362306a36Sopenharmony_ci dev_err(chip->dev, "Failed to add rtc subdev\n"); 85462306a36Sopenharmony_ci goto out; 85562306a36Sopenharmony_ci } 85662306a36Sopenharmony_ci 85762306a36Sopenharmony_ci ret = mfd_add_devices(chip->dev, 0, &onkey_devs[0], 85862306a36Sopenharmony_ci ARRAY_SIZE(onkey_devs), 85962306a36Sopenharmony_ci NULL, chip->irq_base, NULL); 86062306a36Sopenharmony_ci if (ret < 0) { 86162306a36Sopenharmony_ci dev_err(chip->dev, "Failed to add onkey subdev\n"); 86262306a36Sopenharmony_ci goto out_dev; 86362306a36Sopenharmony_ci } 86462306a36Sopenharmony_ci 86562306a36Sopenharmony_ci init_regulator(chip, pdata); 86662306a36Sopenharmony_ci 86762306a36Sopenharmony_ci if (pdata && pdata->backlight) { 86862306a36Sopenharmony_ci bk_devs[0].platform_data = &pdata->backlight; 86962306a36Sopenharmony_ci bk_devs[0].pdata_size = sizeof(struct max8925_backlight_pdata); 87062306a36Sopenharmony_ci } 87162306a36Sopenharmony_ci ret = mfd_add_devices(chip->dev, 0, bk_devs, ARRAY_SIZE(bk_devs), 87262306a36Sopenharmony_ci NULL, 0, NULL); 87362306a36Sopenharmony_ci if (ret < 0) { 87462306a36Sopenharmony_ci dev_err(chip->dev, "Failed to add backlight subdev\n"); 87562306a36Sopenharmony_ci goto out_dev; 87662306a36Sopenharmony_ci } 87762306a36Sopenharmony_ci 87862306a36Sopenharmony_ci ret = mfd_add_devices(chip->dev, 0, &power_devs[0], 87962306a36Sopenharmony_ci ARRAY_SIZE(power_devs), 88062306a36Sopenharmony_ci NULL, 0, NULL); 88162306a36Sopenharmony_ci if (ret < 0) { 88262306a36Sopenharmony_ci dev_err(chip->dev, 88362306a36Sopenharmony_ci "Failed to add power supply subdev, err = %d\n", ret); 88462306a36Sopenharmony_ci goto out_dev; 88562306a36Sopenharmony_ci } 88662306a36Sopenharmony_ci 88762306a36Sopenharmony_ci if (pdata && pdata->touch) { 88862306a36Sopenharmony_ci ret = mfd_add_devices(chip->dev, 0, &touch_devs[0], 88962306a36Sopenharmony_ci ARRAY_SIZE(touch_devs), 89062306a36Sopenharmony_ci NULL, chip->tsc_irq, NULL); 89162306a36Sopenharmony_ci if (ret < 0) { 89262306a36Sopenharmony_ci dev_err(chip->dev, "Failed to add touch subdev\n"); 89362306a36Sopenharmony_ci goto out_dev; 89462306a36Sopenharmony_ci } 89562306a36Sopenharmony_ci } 89662306a36Sopenharmony_ci 89762306a36Sopenharmony_ci return 0; 89862306a36Sopenharmony_ciout_dev: 89962306a36Sopenharmony_ci mfd_remove_devices(chip->dev); 90062306a36Sopenharmony_ciout: 90162306a36Sopenharmony_ci return ret; 90262306a36Sopenharmony_ci} 90362306a36Sopenharmony_ci 90462306a36Sopenharmony_civoid max8925_device_exit(struct max8925_chip *chip) 90562306a36Sopenharmony_ci{ 90662306a36Sopenharmony_ci if (chip->core_irq) 90762306a36Sopenharmony_ci free_irq(chip->core_irq, chip); 90862306a36Sopenharmony_ci if (chip->tsc_irq) 90962306a36Sopenharmony_ci free_irq(chip->tsc_irq, chip); 91062306a36Sopenharmony_ci mfd_remove_devices(chip->dev); 91162306a36Sopenharmony_ci} 912