1d50f8f33SHaojian Zhuang /* 2d50f8f33SHaojian Zhuang * Base driver for Maxim MAX8925 3d50f8f33SHaojian Zhuang * 41f1cf8f9SHaojian Zhuang * Copyright (C) 2009-2010 Marvell International Ltd. 5d50f8f33SHaojian Zhuang * Haojian Zhuang <haojian.zhuang@marvell.com> 6d50f8f33SHaojian Zhuang * 7d50f8f33SHaojian Zhuang * This program is free software; you can redistribute it and/or modify 8d50f8f33SHaojian Zhuang * it under the terms of the GNU General Public License version 2 as 9d50f8f33SHaojian Zhuang * published by the Free Software Foundation. 10d50f8f33SHaojian Zhuang */ 11d50f8f33SHaojian Zhuang 12d50f8f33SHaojian Zhuang #include <linux/kernel.h> 13d50f8f33SHaojian Zhuang #include <linux/module.h> 14d50f8f33SHaojian Zhuang #include <linux/i2c.h> 151f1cf8f9SHaojian Zhuang #include <linux/irq.h> 16d50f8f33SHaojian Zhuang #include <linux/interrupt.h> 17d50f8f33SHaojian Zhuang #include <linux/platform_device.h> 18d50f8f33SHaojian Zhuang #include <linux/mfd/core.h> 19d50f8f33SHaojian Zhuang #include <linux/mfd/max8925.h> 20d50f8f33SHaojian Zhuang 211ad99893SHaojian Zhuang static struct resource backlight_resources[] = { 221ad99893SHaojian Zhuang { 231ad99893SHaojian Zhuang .name = "max8925-backlight", 241ad99893SHaojian Zhuang .start = MAX8925_WLED_MODE_CNTL, 251ad99893SHaojian Zhuang .end = MAX8925_WLED_CNTL, 261ad99893SHaojian Zhuang .flags = IORESOURCE_IO, 271ad99893SHaojian Zhuang }, 281ad99893SHaojian Zhuang }; 291ad99893SHaojian Zhuang 301ad99893SHaojian Zhuang static struct mfd_cell backlight_devs[] = { 311ad99893SHaojian Zhuang { 321ad99893SHaojian Zhuang .name = "max8925-backlight", 331ad99893SHaojian Zhuang .num_resources = 1, 341ad99893SHaojian Zhuang .resources = &backlight_resources[0], 351ad99893SHaojian Zhuang .id = -1, 361ad99893SHaojian Zhuang }, 371ad99893SHaojian Zhuang }; 381ad99893SHaojian Zhuang 391ad99893SHaojian Zhuang static struct resource touch_resources[] = { 401ad99893SHaojian Zhuang { 411ad99893SHaojian Zhuang .name = "max8925-tsc", 421ad99893SHaojian Zhuang .start = MAX8925_TSC_IRQ, 431ad99893SHaojian Zhuang .end = MAX8925_ADC_RES_END, 441ad99893SHaojian Zhuang .flags = IORESOURCE_IO, 451ad99893SHaojian Zhuang }, 461ad99893SHaojian Zhuang }; 471ad99893SHaojian Zhuang 481ad99893SHaojian Zhuang static struct mfd_cell touch_devs[] = { 491ad99893SHaojian Zhuang { 501ad99893SHaojian Zhuang .name = "max8925-touch", 511ad99893SHaojian Zhuang .num_resources = 1, 521ad99893SHaojian Zhuang .resources = &touch_resources[0], 531ad99893SHaojian Zhuang .id = -1, 541ad99893SHaojian Zhuang }, 551ad99893SHaojian Zhuang }; 561ad99893SHaojian Zhuang 571f1cf8f9SHaojian Zhuang static struct resource power_supply_resources[] = { 581f1cf8f9SHaojian Zhuang { 591f1cf8f9SHaojian Zhuang .name = "max8925-power", 601f1cf8f9SHaojian Zhuang .start = MAX8925_CHG_IRQ1, 611f1cf8f9SHaojian Zhuang .end = MAX8925_CHG_IRQ1_MASK, 621f1cf8f9SHaojian Zhuang .flags = IORESOURCE_IO, 631f1cf8f9SHaojian Zhuang }, 641f1cf8f9SHaojian Zhuang }; 651f1cf8f9SHaojian Zhuang 661f1cf8f9SHaojian Zhuang static struct mfd_cell power_devs[] = { 671f1cf8f9SHaojian Zhuang { 681f1cf8f9SHaojian Zhuang .name = "max8925-power", 691f1cf8f9SHaojian Zhuang .num_resources = 1, 701f1cf8f9SHaojian Zhuang .resources = &power_supply_resources[0], 711f1cf8f9SHaojian Zhuang .id = -1, 721f1cf8f9SHaojian Zhuang }, 731f1cf8f9SHaojian Zhuang }; 741f1cf8f9SHaojian Zhuang 751f1cf8f9SHaojian Zhuang static struct resource rtc_resources[] = { 761f1cf8f9SHaojian Zhuang { 771f1cf8f9SHaojian Zhuang .name = "max8925-rtc", 781f1cf8f9SHaojian Zhuang .start = MAX8925_RTC_IRQ, 791f1cf8f9SHaojian Zhuang .end = MAX8925_RTC_IRQ_MASK, 801f1cf8f9SHaojian Zhuang .flags = IORESOURCE_IO, 811f1cf8f9SHaojian Zhuang }, 821f1cf8f9SHaojian Zhuang }; 831f1cf8f9SHaojian Zhuang 841f1cf8f9SHaojian Zhuang static struct mfd_cell rtc_devs[] = { 851f1cf8f9SHaojian Zhuang { 861f1cf8f9SHaojian Zhuang .name = "max8925-rtc", 871f1cf8f9SHaojian Zhuang .num_resources = 1, 881f1cf8f9SHaojian Zhuang .resources = &rtc_resources[0], 891f1cf8f9SHaojian Zhuang .id = -1, 901f1cf8f9SHaojian Zhuang }, 911f1cf8f9SHaojian Zhuang }; 921f1cf8f9SHaojian Zhuang 93d0f7a6d6SHaojian Zhuang static struct resource onkey_resources[] = { 94d0f7a6d6SHaojian Zhuang { 95d0f7a6d6SHaojian Zhuang .name = "max8925-onkey", 962d95ae3bSHaojian Zhuang .start = MAX8925_IRQ_GPM_SW_R, 972d95ae3bSHaojian Zhuang .end = MAX8925_IRQ_GPM_SW_R, 982d95ae3bSHaojian Zhuang .flags = IORESOURCE_IRQ, 992d95ae3bSHaojian Zhuang }, { 1002d95ae3bSHaojian Zhuang .name = "max8925-onkey", 1012d95ae3bSHaojian Zhuang .start = MAX8925_IRQ_GPM_SW_F, 1022d95ae3bSHaojian Zhuang .end = MAX8925_IRQ_GPM_SW_F, 103d0f7a6d6SHaojian Zhuang .flags = IORESOURCE_IRQ, 104d0f7a6d6SHaojian Zhuang }, 105d0f7a6d6SHaojian Zhuang }; 106d0f7a6d6SHaojian Zhuang 107d0f7a6d6SHaojian Zhuang static struct mfd_cell onkey_devs[] = { 108d0f7a6d6SHaojian Zhuang { 109d0f7a6d6SHaojian Zhuang .name = "max8925-onkey", 1102d95ae3bSHaojian Zhuang .num_resources = 2, 111d0f7a6d6SHaojian Zhuang .resources = &onkey_resources[0], 112d0f7a6d6SHaojian Zhuang .id = -1, 113d0f7a6d6SHaojian Zhuang }, 114d0f7a6d6SHaojian Zhuang }; 115d0f7a6d6SHaojian Zhuang 1161ad99893SHaojian Zhuang #define MAX8925_REG_RESOURCE(_start, _end) \ 1171ad99893SHaojian Zhuang { \ 1181ad99893SHaojian Zhuang .start = MAX8925_##_start, \ 1191ad99893SHaojian Zhuang .end = MAX8925_##_end, \ 1201ad99893SHaojian Zhuang .flags = IORESOURCE_IO, \ 1211ad99893SHaojian Zhuang } 1221ad99893SHaojian Zhuang 1231ad99893SHaojian Zhuang static struct resource regulator_resources[] = { 1241ad99893SHaojian Zhuang MAX8925_REG_RESOURCE(SDCTL1, SDCTL1), 1251ad99893SHaojian Zhuang MAX8925_REG_RESOURCE(SDCTL2, SDCTL2), 1261ad99893SHaojian Zhuang MAX8925_REG_RESOURCE(SDCTL3, SDCTL3), 1271ad99893SHaojian Zhuang MAX8925_REG_RESOURCE(LDOCTL1, LDOCTL1), 1281ad99893SHaojian Zhuang MAX8925_REG_RESOURCE(LDOCTL2, LDOCTL2), 1291ad99893SHaojian Zhuang MAX8925_REG_RESOURCE(LDOCTL3, LDOCTL3), 1301ad99893SHaojian Zhuang MAX8925_REG_RESOURCE(LDOCTL4, LDOCTL4), 1311ad99893SHaojian Zhuang MAX8925_REG_RESOURCE(LDOCTL5, LDOCTL5), 1321ad99893SHaojian Zhuang MAX8925_REG_RESOURCE(LDOCTL6, LDOCTL6), 1331ad99893SHaojian Zhuang MAX8925_REG_RESOURCE(LDOCTL7, LDOCTL7), 1341ad99893SHaojian Zhuang MAX8925_REG_RESOURCE(LDOCTL8, LDOCTL8), 1351ad99893SHaojian Zhuang MAX8925_REG_RESOURCE(LDOCTL9, LDOCTL9), 1361ad99893SHaojian Zhuang MAX8925_REG_RESOURCE(LDOCTL10, LDOCTL10), 1371ad99893SHaojian Zhuang MAX8925_REG_RESOURCE(LDOCTL11, LDOCTL11), 1381ad99893SHaojian Zhuang MAX8925_REG_RESOURCE(LDOCTL12, LDOCTL12), 1391ad99893SHaojian Zhuang MAX8925_REG_RESOURCE(LDOCTL13, LDOCTL13), 1401ad99893SHaojian Zhuang MAX8925_REG_RESOURCE(LDOCTL14, LDOCTL14), 1411ad99893SHaojian Zhuang MAX8925_REG_RESOURCE(LDOCTL15, LDOCTL15), 1421ad99893SHaojian Zhuang MAX8925_REG_RESOURCE(LDOCTL16, LDOCTL16), 1431ad99893SHaojian Zhuang MAX8925_REG_RESOURCE(LDOCTL17, LDOCTL17), 1441ad99893SHaojian Zhuang MAX8925_REG_RESOURCE(LDOCTL18, LDOCTL18), 1451ad99893SHaojian Zhuang MAX8925_REG_RESOURCE(LDOCTL19, LDOCTL19), 1461ad99893SHaojian Zhuang MAX8925_REG_RESOURCE(LDOCTL20, LDOCTL20), 1471ad99893SHaojian Zhuang }; 1481ad99893SHaojian Zhuang 1491ad99893SHaojian Zhuang #define MAX8925_REG_DEVS(_id) \ 1501ad99893SHaojian Zhuang { \ 1511ad99893SHaojian Zhuang .name = "max8925-regulator", \ 1521ad99893SHaojian Zhuang .num_resources = 1, \ 1531ad99893SHaojian Zhuang .resources = ®ulator_resources[MAX8925_ID_##_id], \ 1541ad99893SHaojian Zhuang .id = MAX8925_ID_##_id, \ 1551ad99893SHaojian Zhuang } 1561ad99893SHaojian Zhuang 1571ad99893SHaojian Zhuang static struct mfd_cell regulator_devs[] = { 1581ad99893SHaojian Zhuang MAX8925_REG_DEVS(SD1), 1591ad99893SHaojian Zhuang MAX8925_REG_DEVS(SD2), 1601ad99893SHaojian Zhuang MAX8925_REG_DEVS(SD3), 1611ad99893SHaojian Zhuang MAX8925_REG_DEVS(LDO1), 1621ad99893SHaojian Zhuang MAX8925_REG_DEVS(LDO2), 1631ad99893SHaojian Zhuang MAX8925_REG_DEVS(LDO3), 1641ad99893SHaojian Zhuang MAX8925_REG_DEVS(LDO4), 1651ad99893SHaojian Zhuang MAX8925_REG_DEVS(LDO5), 1661ad99893SHaojian Zhuang MAX8925_REG_DEVS(LDO6), 1671ad99893SHaojian Zhuang MAX8925_REG_DEVS(LDO7), 1681ad99893SHaojian Zhuang MAX8925_REG_DEVS(LDO8), 1691ad99893SHaojian Zhuang MAX8925_REG_DEVS(LDO9), 1701ad99893SHaojian Zhuang MAX8925_REG_DEVS(LDO10), 1711ad99893SHaojian Zhuang MAX8925_REG_DEVS(LDO11), 1721ad99893SHaojian Zhuang MAX8925_REG_DEVS(LDO12), 1731ad99893SHaojian Zhuang MAX8925_REG_DEVS(LDO13), 1741ad99893SHaojian Zhuang MAX8925_REG_DEVS(LDO14), 1751ad99893SHaojian Zhuang MAX8925_REG_DEVS(LDO15), 1761ad99893SHaojian Zhuang MAX8925_REG_DEVS(LDO16), 1771ad99893SHaojian Zhuang MAX8925_REG_DEVS(LDO17), 1781ad99893SHaojian Zhuang MAX8925_REG_DEVS(LDO18), 1791ad99893SHaojian Zhuang MAX8925_REG_DEVS(LDO19), 1801ad99893SHaojian Zhuang MAX8925_REG_DEVS(LDO20), 1811ad99893SHaojian Zhuang }; 1821ad99893SHaojian Zhuang 1831f1cf8f9SHaojian Zhuang enum { 1841f1cf8f9SHaojian Zhuang FLAGS_ADC = 1, /* register in ADC component */ 1851f1cf8f9SHaojian Zhuang FLAGS_RTC, /* register in RTC component */ 1861f1cf8f9SHaojian Zhuang }; 1871f1cf8f9SHaojian Zhuang 1881f1cf8f9SHaojian Zhuang struct max8925_irq_data { 1891f1cf8f9SHaojian Zhuang int reg; 1901f1cf8f9SHaojian Zhuang int mask_reg; 1911f1cf8f9SHaojian Zhuang int enable; /* enable or not */ 1921f1cf8f9SHaojian Zhuang int offs; /* bit offset in mask register */ 1931f1cf8f9SHaojian Zhuang int flags; 1941f1cf8f9SHaojian Zhuang int tsc_irq; 1951f1cf8f9SHaojian Zhuang }; 1961f1cf8f9SHaojian Zhuang 1971f1cf8f9SHaojian Zhuang static struct max8925_irq_data max8925_irqs[] = { 1981f1cf8f9SHaojian Zhuang [MAX8925_IRQ_VCHG_DC_OVP] = { 1991f1cf8f9SHaojian Zhuang .reg = MAX8925_CHG_IRQ1, 2001f1cf8f9SHaojian Zhuang .mask_reg = MAX8925_CHG_IRQ1_MASK, 2011f1cf8f9SHaojian Zhuang .offs = 1 << 0, 2021f1cf8f9SHaojian Zhuang }, 2031f1cf8f9SHaojian Zhuang [MAX8925_IRQ_VCHG_DC_F] = { 2041f1cf8f9SHaojian Zhuang .reg = MAX8925_CHG_IRQ1, 2051f1cf8f9SHaojian Zhuang .mask_reg = MAX8925_CHG_IRQ1_MASK, 2061f1cf8f9SHaojian Zhuang .offs = 1 << 1, 2071f1cf8f9SHaojian Zhuang }, 2081f1cf8f9SHaojian Zhuang [MAX8925_IRQ_VCHG_DC_R] = { 2091f1cf8f9SHaojian Zhuang .reg = MAX8925_CHG_IRQ1, 2101f1cf8f9SHaojian Zhuang .mask_reg = MAX8925_CHG_IRQ1_MASK, 2111f1cf8f9SHaojian Zhuang .offs = 1 << 2, 2121f1cf8f9SHaojian Zhuang }, 2131f1cf8f9SHaojian Zhuang [MAX8925_IRQ_VCHG_USB_OVP] = { 2141f1cf8f9SHaojian Zhuang .reg = MAX8925_CHG_IRQ1, 2151f1cf8f9SHaojian Zhuang .mask_reg = MAX8925_CHG_IRQ1_MASK, 2161f1cf8f9SHaojian Zhuang .offs = 1 << 3, 2171f1cf8f9SHaojian Zhuang }, 2181f1cf8f9SHaojian Zhuang [MAX8925_IRQ_VCHG_USB_F] = { 2191f1cf8f9SHaojian Zhuang .reg = MAX8925_CHG_IRQ1, 2201f1cf8f9SHaojian Zhuang .mask_reg = MAX8925_CHG_IRQ1_MASK, 2211f1cf8f9SHaojian Zhuang .offs = 1 << 4, 2221f1cf8f9SHaojian Zhuang }, 2231f1cf8f9SHaojian Zhuang [MAX8925_IRQ_VCHG_USB_R] = { 2241f1cf8f9SHaojian Zhuang .reg = MAX8925_CHG_IRQ1, 2251f1cf8f9SHaojian Zhuang .mask_reg = MAX8925_CHG_IRQ1_MASK, 2261f1cf8f9SHaojian Zhuang .offs = 1 << 5, 2271f1cf8f9SHaojian Zhuang }, 2281f1cf8f9SHaojian Zhuang [MAX8925_IRQ_VCHG_THM_OK_R] = { 2291f1cf8f9SHaojian Zhuang .reg = MAX8925_CHG_IRQ2, 2301f1cf8f9SHaojian Zhuang .mask_reg = MAX8925_CHG_IRQ2_MASK, 2311f1cf8f9SHaojian Zhuang .offs = 1 << 0, 2321f1cf8f9SHaojian Zhuang }, 2331f1cf8f9SHaojian Zhuang [MAX8925_IRQ_VCHG_THM_OK_F] = { 2341f1cf8f9SHaojian Zhuang .reg = MAX8925_CHG_IRQ2, 2351f1cf8f9SHaojian Zhuang .mask_reg = MAX8925_CHG_IRQ2_MASK, 2361f1cf8f9SHaojian Zhuang .offs = 1 << 1, 2371f1cf8f9SHaojian Zhuang }, 2381f1cf8f9SHaojian Zhuang [MAX8925_IRQ_VCHG_SYSLOW_F] = { 2391f1cf8f9SHaojian Zhuang .reg = MAX8925_CHG_IRQ2, 2401f1cf8f9SHaojian Zhuang .mask_reg = MAX8925_CHG_IRQ2_MASK, 2411f1cf8f9SHaojian Zhuang .offs = 1 << 2, 2421f1cf8f9SHaojian Zhuang }, 2431f1cf8f9SHaojian Zhuang [MAX8925_IRQ_VCHG_SYSLOW_R] = { 2441f1cf8f9SHaojian Zhuang .reg = MAX8925_CHG_IRQ2, 2451f1cf8f9SHaojian Zhuang .mask_reg = MAX8925_CHG_IRQ2_MASK, 2461f1cf8f9SHaojian Zhuang .offs = 1 << 3, 2471f1cf8f9SHaojian Zhuang }, 2481f1cf8f9SHaojian Zhuang [MAX8925_IRQ_VCHG_RST] = { 2491f1cf8f9SHaojian Zhuang .reg = MAX8925_CHG_IRQ2, 2501f1cf8f9SHaojian Zhuang .mask_reg = MAX8925_CHG_IRQ2_MASK, 2511f1cf8f9SHaojian Zhuang .offs = 1 << 4, 2521f1cf8f9SHaojian Zhuang }, 2531f1cf8f9SHaojian Zhuang [MAX8925_IRQ_VCHG_DONE] = { 2541f1cf8f9SHaojian Zhuang .reg = MAX8925_CHG_IRQ2, 2551f1cf8f9SHaojian Zhuang .mask_reg = MAX8925_CHG_IRQ2_MASK, 2561f1cf8f9SHaojian Zhuang .offs = 1 << 5, 2571f1cf8f9SHaojian Zhuang }, 2581f1cf8f9SHaojian Zhuang [MAX8925_IRQ_VCHG_TOPOFF] = { 2591f1cf8f9SHaojian Zhuang .reg = MAX8925_CHG_IRQ2, 2601f1cf8f9SHaojian Zhuang .mask_reg = MAX8925_CHG_IRQ2_MASK, 2611f1cf8f9SHaojian Zhuang .offs = 1 << 6, 2621f1cf8f9SHaojian Zhuang }, 2631f1cf8f9SHaojian Zhuang [MAX8925_IRQ_VCHG_TMR_FAULT] = { 2641f1cf8f9SHaojian Zhuang .reg = MAX8925_CHG_IRQ2, 2651f1cf8f9SHaojian Zhuang .mask_reg = MAX8925_CHG_IRQ2_MASK, 2661f1cf8f9SHaojian Zhuang .offs = 1 << 7, 2671f1cf8f9SHaojian Zhuang }, 2681f1cf8f9SHaojian Zhuang [MAX8925_IRQ_GPM_RSTIN] = { 2691f1cf8f9SHaojian Zhuang .reg = MAX8925_ON_OFF_IRQ1, 2701f1cf8f9SHaojian Zhuang .mask_reg = MAX8925_ON_OFF_IRQ1_MASK, 2711f1cf8f9SHaojian Zhuang .offs = 1 << 0, 2721f1cf8f9SHaojian Zhuang }, 2731f1cf8f9SHaojian Zhuang [MAX8925_IRQ_GPM_MPL] = { 2741f1cf8f9SHaojian Zhuang .reg = MAX8925_ON_OFF_IRQ1, 2751f1cf8f9SHaojian Zhuang .mask_reg = MAX8925_ON_OFF_IRQ1_MASK, 2761f1cf8f9SHaojian Zhuang .offs = 1 << 1, 2771f1cf8f9SHaojian Zhuang }, 2781f1cf8f9SHaojian Zhuang [MAX8925_IRQ_GPM_SW_3SEC] = { 2791f1cf8f9SHaojian Zhuang .reg = MAX8925_ON_OFF_IRQ1, 2801f1cf8f9SHaojian Zhuang .mask_reg = MAX8925_ON_OFF_IRQ1_MASK, 2811f1cf8f9SHaojian Zhuang .offs = 1 << 2, 2821f1cf8f9SHaojian Zhuang }, 2831f1cf8f9SHaojian Zhuang [MAX8925_IRQ_GPM_EXTON_F] = { 2841f1cf8f9SHaojian Zhuang .reg = MAX8925_ON_OFF_IRQ1, 2851f1cf8f9SHaojian Zhuang .mask_reg = MAX8925_ON_OFF_IRQ1_MASK, 2861f1cf8f9SHaojian Zhuang .offs = 1 << 3, 2871f1cf8f9SHaojian Zhuang }, 2881f1cf8f9SHaojian Zhuang [MAX8925_IRQ_GPM_EXTON_R] = { 2891f1cf8f9SHaojian Zhuang .reg = MAX8925_ON_OFF_IRQ1, 2901f1cf8f9SHaojian Zhuang .mask_reg = MAX8925_ON_OFF_IRQ1_MASK, 2911f1cf8f9SHaojian Zhuang .offs = 1 << 4, 2921f1cf8f9SHaojian Zhuang }, 2931f1cf8f9SHaojian Zhuang [MAX8925_IRQ_GPM_SW_1SEC] = { 2941f1cf8f9SHaojian Zhuang .reg = MAX8925_ON_OFF_IRQ1, 2951f1cf8f9SHaojian Zhuang .mask_reg = MAX8925_ON_OFF_IRQ1_MASK, 2961f1cf8f9SHaojian Zhuang .offs = 1 << 5, 2971f1cf8f9SHaojian Zhuang }, 2981f1cf8f9SHaojian Zhuang [MAX8925_IRQ_GPM_SW_F] = { 2991f1cf8f9SHaojian Zhuang .reg = MAX8925_ON_OFF_IRQ1, 3001f1cf8f9SHaojian Zhuang .mask_reg = MAX8925_ON_OFF_IRQ1_MASK, 3011f1cf8f9SHaojian Zhuang .offs = 1 << 6, 3021f1cf8f9SHaojian Zhuang }, 3031f1cf8f9SHaojian Zhuang [MAX8925_IRQ_GPM_SW_R] = { 3041f1cf8f9SHaojian Zhuang .reg = MAX8925_ON_OFF_IRQ1, 3051f1cf8f9SHaojian Zhuang .mask_reg = MAX8925_ON_OFF_IRQ1_MASK, 3061f1cf8f9SHaojian Zhuang .offs = 1 << 7, 3071f1cf8f9SHaojian Zhuang }, 3081f1cf8f9SHaojian Zhuang [MAX8925_IRQ_GPM_SYSCKEN_F] = { 3091f1cf8f9SHaojian Zhuang .reg = MAX8925_ON_OFF_IRQ2, 3101f1cf8f9SHaojian Zhuang .mask_reg = MAX8925_ON_OFF_IRQ2_MASK, 3111f1cf8f9SHaojian Zhuang .offs = 1 << 0, 3121f1cf8f9SHaojian Zhuang }, 3131f1cf8f9SHaojian Zhuang [MAX8925_IRQ_GPM_SYSCKEN_R] = { 3141f1cf8f9SHaojian Zhuang .reg = MAX8925_ON_OFF_IRQ2, 3151f1cf8f9SHaojian Zhuang .mask_reg = MAX8925_ON_OFF_IRQ2_MASK, 3161f1cf8f9SHaojian Zhuang .offs = 1 << 1, 3171f1cf8f9SHaojian Zhuang }, 3181f1cf8f9SHaojian Zhuang [MAX8925_IRQ_RTC_ALARM1] = { 3191f1cf8f9SHaojian Zhuang .reg = MAX8925_RTC_IRQ, 3201f1cf8f9SHaojian Zhuang .mask_reg = MAX8925_RTC_IRQ_MASK, 3211f1cf8f9SHaojian Zhuang .offs = 1 << 2, 3221f1cf8f9SHaojian Zhuang .flags = FLAGS_RTC, 3231f1cf8f9SHaojian Zhuang }, 3241f1cf8f9SHaojian Zhuang [MAX8925_IRQ_RTC_ALARM0] = { 3251f1cf8f9SHaojian Zhuang .reg = MAX8925_RTC_IRQ, 3261f1cf8f9SHaojian Zhuang .mask_reg = MAX8925_RTC_IRQ_MASK, 3271f1cf8f9SHaojian Zhuang .offs = 1 << 3, 3281f1cf8f9SHaojian Zhuang .flags = FLAGS_RTC, 3291f1cf8f9SHaojian Zhuang }, 3301f1cf8f9SHaojian Zhuang [MAX8925_IRQ_TSC_STICK] = { 3311f1cf8f9SHaojian Zhuang .reg = MAX8925_TSC_IRQ, 3321f1cf8f9SHaojian Zhuang .mask_reg = MAX8925_TSC_IRQ_MASK, 3331f1cf8f9SHaojian Zhuang .offs = 1 << 0, 3341f1cf8f9SHaojian Zhuang .flags = FLAGS_ADC, 3351f1cf8f9SHaojian Zhuang .tsc_irq = 1, 3361f1cf8f9SHaojian Zhuang }, 3371f1cf8f9SHaojian Zhuang [MAX8925_IRQ_TSC_NSTICK] = { 3381f1cf8f9SHaojian Zhuang .reg = MAX8925_TSC_IRQ, 3391f1cf8f9SHaojian Zhuang .mask_reg = MAX8925_TSC_IRQ_MASK, 3401f1cf8f9SHaojian Zhuang .offs = 1 << 1, 3411f1cf8f9SHaojian Zhuang .flags = FLAGS_ADC, 3421f1cf8f9SHaojian Zhuang .tsc_irq = 1, 3431f1cf8f9SHaojian Zhuang }, 3441f1cf8f9SHaojian Zhuang }; 3451f1cf8f9SHaojian Zhuang 3461f1cf8f9SHaojian Zhuang static inline struct max8925_irq_data *irq_to_max8925(struct max8925_chip *chip, 3471f1cf8f9SHaojian Zhuang int irq) 348d50f8f33SHaojian Zhuang { 3491f1cf8f9SHaojian Zhuang return &max8925_irqs[irq - chip->irq_base]; 350d50f8f33SHaojian Zhuang } 351d50f8f33SHaojian Zhuang 3521f1cf8f9SHaojian Zhuang static irqreturn_t max8925_irq(int irq, void *data) 353d50f8f33SHaojian Zhuang { 354d50f8f33SHaojian Zhuang struct max8925_chip *chip = data; 3551f1cf8f9SHaojian Zhuang struct max8925_irq_data *irq_data; 3561f1cf8f9SHaojian Zhuang struct i2c_client *i2c; 3571f1cf8f9SHaojian Zhuang int read_reg = -1, value = 0; 3581f1cf8f9SHaojian Zhuang int i; 359d50f8f33SHaojian Zhuang 3601f1cf8f9SHaojian Zhuang for (i = 0; i < ARRAY_SIZE(max8925_irqs); i++) { 3611f1cf8f9SHaojian Zhuang irq_data = &max8925_irqs[i]; 3621f1cf8f9SHaojian Zhuang /* TSC IRQ should be serviced in max8925_tsc_irq() */ 3631f1cf8f9SHaojian Zhuang if (irq_data->tsc_irq) 3641f1cf8f9SHaojian Zhuang continue; 3651f1cf8f9SHaojian Zhuang if (irq_data->flags == FLAGS_RTC) 3661f1cf8f9SHaojian Zhuang i2c = chip->rtc; 3671f1cf8f9SHaojian Zhuang else if (irq_data->flags == FLAGS_ADC) 3681f1cf8f9SHaojian Zhuang i2c = chip->adc; 3691f1cf8f9SHaojian Zhuang else 3701f1cf8f9SHaojian Zhuang i2c = chip->i2c; 3711f1cf8f9SHaojian Zhuang if (read_reg != irq_data->reg) { 3721f1cf8f9SHaojian Zhuang read_reg = irq_data->reg; 3731f1cf8f9SHaojian Zhuang value = max8925_reg_read(i2c, irq_data->reg); 374d50f8f33SHaojian Zhuang } 3751f1cf8f9SHaojian Zhuang if (value & irq_data->enable) 3761f1cf8f9SHaojian Zhuang handle_nested_irq(chip->irq_base + i); 377d50f8f33SHaojian Zhuang } 378d50f8f33SHaojian Zhuang return IRQ_HANDLED; 379d50f8f33SHaojian Zhuang } 380d50f8f33SHaojian Zhuang 3811f1cf8f9SHaojian Zhuang static irqreturn_t max8925_tsc_irq(int irq, void *data) 382d50f8f33SHaojian Zhuang { 3831f1cf8f9SHaojian Zhuang struct max8925_chip *chip = data; 3841f1cf8f9SHaojian Zhuang struct max8925_irq_data *irq_data; 3851f1cf8f9SHaojian Zhuang struct i2c_client *i2c; 3861f1cf8f9SHaojian Zhuang int read_reg = -1, value = 0; 3871f1cf8f9SHaojian Zhuang int i; 3881f1cf8f9SHaojian Zhuang 3891f1cf8f9SHaojian Zhuang for (i = 0; i < ARRAY_SIZE(max8925_irqs); i++) { 3901f1cf8f9SHaojian Zhuang irq_data = &max8925_irqs[i]; 3911f1cf8f9SHaojian Zhuang /* non TSC IRQ should be serviced in max8925_irq() */ 3921f1cf8f9SHaojian Zhuang if (!irq_data->tsc_irq) 3931f1cf8f9SHaojian Zhuang continue; 3941f1cf8f9SHaojian Zhuang if (irq_data->flags == FLAGS_RTC) 3951f1cf8f9SHaojian Zhuang i2c = chip->rtc; 3961f1cf8f9SHaojian Zhuang else if (irq_data->flags == FLAGS_ADC) 3971f1cf8f9SHaojian Zhuang i2c = chip->adc; 3981f1cf8f9SHaojian Zhuang else 3991f1cf8f9SHaojian Zhuang i2c = chip->i2c; 4001f1cf8f9SHaojian Zhuang if (read_reg != irq_data->reg) { 4011f1cf8f9SHaojian Zhuang read_reg = irq_data->reg; 4021f1cf8f9SHaojian Zhuang value = max8925_reg_read(i2c, irq_data->reg); 4031f1cf8f9SHaojian Zhuang } 4041f1cf8f9SHaojian Zhuang if (value & irq_data->enable) 4051f1cf8f9SHaojian Zhuang handle_nested_irq(chip->irq_base + i); 4061f1cf8f9SHaojian Zhuang } 4071f1cf8f9SHaojian Zhuang return IRQ_HANDLED; 4081f1cf8f9SHaojian Zhuang } 4091f1cf8f9SHaojian Zhuang 41098d9bc13SMark Brown static void max8925_irq_lock(struct irq_data *data) 4111f1cf8f9SHaojian Zhuang { 41298d9bc13SMark Brown struct max8925_chip *chip = irq_data_get_irq_chip_data(data); 413d50f8f33SHaojian Zhuang 414d50f8f33SHaojian Zhuang mutex_lock(&chip->irq_lock); 415d50f8f33SHaojian Zhuang } 416d50f8f33SHaojian Zhuang 41798d9bc13SMark Brown static void max8925_irq_sync_unlock(struct irq_data *data) 418d50f8f33SHaojian Zhuang { 41998d9bc13SMark Brown struct max8925_chip *chip = irq_data_get_irq_chip_data(data); 4201f1cf8f9SHaojian Zhuang struct max8925_irq_data *irq_data; 4211f1cf8f9SHaojian Zhuang static unsigned char cache_chg[2] = {0xff, 0xff}; 4221f1cf8f9SHaojian Zhuang static unsigned char cache_on[2] = {0xff, 0xff}; 4231f1cf8f9SHaojian Zhuang static unsigned char cache_rtc = 0xff, cache_tsc = 0xff; 4241f1cf8f9SHaojian Zhuang unsigned char irq_chg[2], irq_on[2]; 4251f1cf8f9SHaojian Zhuang unsigned char irq_rtc, irq_tsc; 4261f1cf8f9SHaojian Zhuang int i; 427d50f8f33SHaojian Zhuang 4281f1cf8f9SHaojian Zhuang /* Load cached value. In initial, all IRQs are masked */ 4291f1cf8f9SHaojian Zhuang irq_chg[0] = cache_chg[0]; 4301f1cf8f9SHaojian Zhuang irq_chg[1] = cache_chg[1]; 4311f1cf8f9SHaojian Zhuang irq_on[0] = cache_on[0]; 4321f1cf8f9SHaojian Zhuang irq_on[1] = cache_on[1]; 4331f1cf8f9SHaojian Zhuang irq_rtc = cache_rtc; 4341f1cf8f9SHaojian Zhuang irq_tsc = cache_tsc; 4351f1cf8f9SHaojian Zhuang for (i = 0; i < ARRAY_SIZE(max8925_irqs); i++) { 4361f1cf8f9SHaojian Zhuang irq_data = &max8925_irqs[i]; 43790182317SKevin Liu /* 1 -- disable, 0 -- enable */ 4381f1cf8f9SHaojian Zhuang switch (irq_data->mask_reg) { 4391f1cf8f9SHaojian Zhuang case MAX8925_CHG_IRQ1_MASK: 44090182317SKevin Liu irq_chg[0] &= ~irq_data->enable; 4411f1cf8f9SHaojian Zhuang break; 4421f1cf8f9SHaojian Zhuang case MAX8925_CHG_IRQ2_MASK: 44390182317SKevin Liu irq_chg[1] &= ~irq_data->enable; 4441f1cf8f9SHaojian Zhuang break; 4451f1cf8f9SHaojian Zhuang case MAX8925_ON_OFF_IRQ1_MASK: 44690182317SKevin Liu irq_on[0] &= ~irq_data->enable; 4471f1cf8f9SHaojian Zhuang break; 4481f1cf8f9SHaojian Zhuang case MAX8925_ON_OFF_IRQ2_MASK: 44990182317SKevin Liu irq_on[1] &= ~irq_data->enable; 4501f1cf8f9SHaojian Zhuang break; 4511f1cf8f9SHaojian Zhuang case MAX8925_RTC_IRQ_MASK: 45290182317SKevin Liu irq_rtc &= ~irq_data->enable; 4531f1cf8f9SHaojian Zhuang break; 4541f1cf8f9SHaojian Zhuang case MAX8925_TSC_IRQ_MASK: 45590182317SKevin Liu irq_tsc &= ~irq_data->enable; 4561f1cf8f9SHaojian Zhuang break; 4571f1cf8f9SHaojian Zhuang default: 4581f1cf8f9SHaojian Zhuang dev_err(chip->dev, "wrong IRQ\n"); 4591f1cf8f9SHaojian Zhuang break; 4601f1cf8f9SHaojian Zhuang } 4611f1cf8f9SHaojian Zhuang } 4621f1cf8f9SHaojian Zhuang /* update mask into registers */ 4631f1cf8f9SHaojian Zhuang if (cache_chg[0] != irq_chg[0]) { 4641f1cf8f9SHaojian Zhuang cache_chg[0] = irq_chg[0]; 4651f1cf8f9SHaojian Zhuang max8925_reg_write(chip->i2c, MAX8925_CHG_IRQ1_MASK, 4661f1cf8f9SHaojian Zhuang irq_chg[0]); 4671f1cf8f9SHaojian Zhuang } 4681f1cf8f9SHaojian Zhuang if (cache_chg[1] != irq_chg[1]) { 4691f1cf8f9SHaojian Zhuang cache_chg[1] = irq_chg[1]; 4701f1cf8f9SHaojian Zhuang max8925_reg_write(chip->i2c, MAX8925_CHG_IRQ2_MASK, 4711f1cf8f9SHaojian Zhuang irq_chg[1]); 4721f1cf8f9SHaojian Zhuang } 4731f1cf8f9SHaojian Zhuang if (cache_on[0] != irq_on[0]) { 4741f1cf8f9SHaojian Zhuang cache_on[0] = irq_on[0]; 4751f1cf8f9SHaojian Zhuang max8925_reg_write(chip->i2c, MAX8925_ON_OFF_IRQ1_MASK, 4761f1cf8f9SHaojian Zhuang irq_on[0]); 4771f1cf8f9SHaojian Zhuang } 4781f1cf8f9SHaojian Zhuang if (cache_on[1] != irq_on[1]) { 4791f1cf8f9SHaojian Zhuang cache_on[1] = irq_on[1]; 4801f1cf8f9SHaojian Zhuang max8925_reg_write(chip->i2c, MAX8925_ON_OFF_IRQ2_MASK, 4811f1cf8f9SHaojian Zhuang irq_on[1]); 4821f1cf8f9SHaojian Zhuang } 4831f1cf8f9SHaojian Zhuang if (cache_rtc != irq_rtc) { 4841f1cf8f9SHaojian Zhuang cache_rtc = irq_rtc; 4851f1cf8f9SHaojian Zhuang max8925_reg_write(chip->rtc, MAX8925_RTC_IRQ_MASK, irq_rtc); 4861f1cf8f9SHaojian Zhuang } 4871f1cf8f9SHaojian Zhuang if (cache_tsc != irq_tsc) { 4881f1cf8f9SHaojian Zhuang cache_tsc = irq_tsc; 4891f1cf8f9SHaojian Zhuang max8925_reg_write(chip->adc, MAX8925_TSC_IRQ_MASK, irq_tsc); 4901f1cf8f9SHaojian Zhuang } 4911f1cf8f9SHaojian Zhuang 492d50f8f33SHaojian Zhuang mutex_unlock(&chip->irq_lock); 4931f1cf8f9SHaojian Zhuang } 4941f1cf8f9SHaojian Zhuang 49598d9bc13SMark Brown static void max8925_irq_enable(struct irq_data *data) 4961f1cf8f9SHaojian Zhuang { 49798d9bc13SMark Brown struct max8925_chip *chip = irq_data_get_irq_chip_data(data); 49898d9bc13SMark Brown max8925_irqs[data->irq - chip->irq_base].enable 49998d9bc13SMark Brown = max8925_irqs[data->irq - chip->irq_base].offs; 5001f1cf8f9SHaojian Zhuang } 5011f1cf8f9SHaojian Zhuang 50298d9bc13SMark Brown static void max8925_irq_disable(struct irq_data *data) 5031f1cf8f9SHaojian Zhuang { 50498d9bc13SMark Brown struct max8925_chip *chip = irq_data_get_irq_chip_data(data); 50598d9bc13SMark Brown max8925_irqs[data->irq - chip->irq_base].enable = 0; 5061f1cf8f9SHaojian Zhuang } 5071f1cf8f9SHaojian Zhuang 5081f1cf8f9SHaojian Zhuang static struct irq_chip max8925_irq_chip = { 5091f1cf8f9SHaojian Zhuang .name = "max8925", 51098d9bc13SMark Brown .irq_bus_lock = max8925_irq_lock, 51198d9bc13SMark Brown .irq_bus_sync_unlock = max8925_irq_sync_unlock, 51298d9bc13SMark Brown .irq_enable = max8925_irq_enable, 51398d9bc13SMark Brown .irq_disable = max8925_irq_disable, 5141f1cf8f9SHaojian Zhuang }; 5151f1cf8f9SHaojian Zhuang 5161f1cf8f9SHaojian Zhuang static int max8925_irq_init(struct max8925_chip *chip, int irq, 5171f1cf8f9SHaojian Zhuang struct max8925_platform_data *pdata) 5181f1cf8f9SHaojian Zhuang { 5191f1cf8f9SHaojian Zhuang unsigned long flags = IRQF_TRIGGER_FALLING | IRQF_ONESHOT; 5201f1cf8f9SHaojian Zhuang struct irq_desc *desc; 5211f1cf8f9SHaojian Zhuang int i, ret; 5221f1cf8f9SHaojian Zhuang int __irq; 5231f1cf8f9SHaojian Zhuang 5241f1cf8f9SHaojian Zhuang if (!pdata || !pdata->irq_base) { 5251f1cf8f9SHaojian Zhuang dev_warn(chip->dev, "No interrupt support on IRQ base\n"); 5261f1cf8f9SHaojian Zhuang return -EINVAL; 5271f1cf8f9SHaojian Zhuang } 5281f1cf8f9SHaojian Zhuang /* clear all interrupts */ 5291f1cf8f9SHaojian Zhuang max8925_reg_read(chip->i2c, MAX8925_CHG_IRQ1); 5301f1cf8f9SHaojian Zhuang max8925_reg_read(chip->i2c, MAX8925_CHG_IRQ2); 5311f1cf8f9SHaojian Zhuang max8925_reg_read(chip->i2c, MAX8925_ON_OFF_IRQ1); 5321f1cf8f9SHaojian Zhuang max8925_reg_read(chip->i2c, MAX8925_ON_OFF_IRQ2); 5331f1cf8f9SHaojian Zhuang max8925_reg_read(chip->rtc, MAX8925_RTC_IRQ); 5341f1cf8f9SHaojian Zhuang max8925_reg_read(chip->adc, MAX8925_TSC_IRQ); 53568e488d9SHaojian Zhuang /* mask all interrupts except for TSC */ 5361f1cf8f9SHaojian Zhuang max8925_reg_write(chip->rtc, MAX8925_ALARM0_CNTL, 0); 5371f1cf8f9SHaojian Zhuang max8925_reg_write(chip->rtc, MAX8925_ALARM1_CNTL, 0); 5381f1cf8f9SHaojian Zhuang max8925_reg_write(chip->i2c, MAX8925_CHG_IRQ1_MASK, 0xff); 5391f1cf8f9SHaojian Zhuang max8925_reg_write(chip->i2c, MAX8925_CHG_IRQ2_MASK, 0xff); 5401f1cf8f9SHaojian Zhuang max8925_reg_write(chip->i2c, MAX8925_ON_OFF_IRQ1_MASK, 0xff); 5411f1cf8f9SHaojian Zhuang max8925_reg_write(chip->i2c, MAX8925_ON_OFF_IRQ2_MASK, 0xff); 5421f1cf8f9SHaojian Zhuang max8925_reg_write(chip->rtc, MAX8925_RTC_IRQ_MASK, 0xff); 5431f1cf8f9SHaojian Zhuang 5441f1cf8f9SHaojian Zhuang mutex_init(&chip->irq_lock); 5451f1cf8f9SHaojian Zhuang chip->core_irq = irq; 5461f1cf8f9SHaojian Zhuang chip->irq_base = pdata->irq_base; 5471f1cf8f9SHaojian Zhuang desc = irq_to_desc(chip->core_irq); 5481f1cf8f9SHaojian Zhuang 5491f1cf8f9SHaojian Zhuang /* register with genirq */ 5501f1cf8f9SHaojian Zhuang for (i = 0; i < ARRAY_SIZE(max8925_irqs); i++) { 5511f1cf8f9SHaojian Zhuang __irq = i + chip->irq_base; 5521f1cf8f9SHaojian Zhuang set_irq_chip_data(__irq, chip); 5531f1cf8f9SHaojian Zhuang set_irq_chip_and_handler(__irq, &max8925_irq_chip, 5541f1cf8f9SHaojian Zhuang handle_edge_irq); 5551f1cf8f9SHaojian Zhuang set_irq_nested_thread(__irq, 1); 5561f1cf8f9SHaojian Zhuang #ifdef CONFIG_ARM 5571f1cf8f9SHaojian Zhuang set_irq_flags(__irq, IRQF_VALID); 5581f1cf8f9SHaojian Zhuang #else 5591f1cf8f9SHaojian Zhuang set_irq_noprobe(__irq); 5601f1cf8f9SHaojian Zhuang #endif 5611f1cf8f9SHaojian Zhuang } 5621f1cf8f9SHaojian Zhuang if (!irq) { 5631f1cf8f9SHaojian Zhuang dev_warn(chip->dev, "No interrupt support on core IRQ\n"); 5641f1cf8f9SHaojian Zhuang goto tsc_irq; 5651f1cf8f9SHaojian Zhuang } 5661f1cf8f9SHaojian Zhuang 5671f1cf8f9SHaojian Zhuang ret = request_threaded_irq(irq, NULL, max8925_irq, flags, 5681f1cf8f9SHaojian Zhuang "max8925", chip); 5691f1cf8f9SHaojian Zhuang if (ret) { 5701f1cf8f9SHaojian Zhuang dev_err(chip->dev, "Failed to request core IRQ: %d\n", ret); 5711f1cf8f9SHaojian Zhuang chip->core_irq = 0; 5721f1cf8f9SHaojian Zhuang } 57368e488d9SHaojian Zhuang 5741f1cf8f9SHaojian Zhuang tsc_irq: 57568e488d9SHaojian Zhuang /* mask TSC interrupt */ 57668e488d9SHaojian Zhuang max8925_reg_write(chip->adc, MAX8925_TSC_IRQ_MASK, 0x0f); 57768e488d9SHaojian Zhuang 5781f1cf8f9SHaojian Zhuang if (!pdata->tsc_irq) { 5791f1cf8f9SHaojian Zhuang dev_warn(chip->dev, "No interrupt support on TSC IRQ\n"); 580d50f8f33SHaojian Zhuang return 0; 581d50f8f33SHaojian Zhuang } 5821f1cf8f9SHaojian Zhuang chip->tsc_irq = pdata->tsc_irq; 583d50f8f33SHaojian Zhuang 5841f1cf8f9SHaojian Zhuang ret = request_threaded_irq(chip->tsc_irq, NULL, max8925_tsc_irq, 5851f1cf8f9SHaojian Zhuang flags, "max8925-tsc", chip); 5861f1cf8f9SHaojian Zhuang if (ret) { 5871f1cf8f9SHaojian Zhuang dev_err(chip->dev, "Failed to request TSC IRQ: %d\n", ret); 5881f1cf8f9SHaojian Zhuang chip->tsc_irq = 0; 5891f1cf8f9SHaojian Zhuang } 5901f1cf8f9SHaojian Zhuang return 0; 5911f1cf8f9SHaojian Zhuang } 5921f1cf8f9SHaojian Zhuang 5931f1cf8f9SHaojian Zhuang int __devinit max8925_device_init(struct max8925_chip *chip, 594d50f8f33SHaojian Zhuang struct max8925_platform_data *pdata) 595d50f8f33SHaojian Zhuang { 596d50f8f33SHaojian Zhuang int ret; 597d50f8f33SHaojian Zhuang 5981f1cf8f9SHaojian Zhuang max8925_irq_init(chip, chip->i2c->irq, pdata); 599d50f8f33SHaojian Zhuang 6001f1cf8f9SHaojian Zhuang if (pdata && (pdata->power || pdata->touch)) { 6011f1cf8f9SHaojian Zhuang /* enable ADC to control internal reference */ 6021f1cf8f9SHaojian Zhuang max8925_set_bits(chip->i2c, MAX8925_RESET_CNFG, 1, 1); 6031f1cf8f9SHaojian Zhuang /* enable internal reference for ADC */ 6041f1cf8f9SHaojian Zhuang max8925_set_bits(chip->adc, MAX8925_TSC_CNFG1, 3, 2); 6051f1cf8f9SHaojian Zhuang /* check for internal reference IRQ */ 6061f1cf8f9SHaojian Zhuang do { 6071f1cf8f9SHaojian Zhuang ret = max8925_reg_read(chip->adc, MAX8925_TSC_IRQ); 6081f1cf8f9SHaojian Zhuang } while (ret & MAX8925_NREF_OK); 6091f1cf8f9SHaojian Zhuang /* enaable ADC scheduler, interval is 1 second */ 6101f1cf8f9SHaojian Zhuang max8925_set_bits(chip->adc, MAX8925_ADC_SCHED, 3, 2); 6111f1cf8f9SHaojian Zhuang } 6121f1cf8f9SHaojian Zhuang 6131f1cf8f9SHaojian Zhuang /* enable Momentary Power Loss */ 6141f1cf8f9SHaojian Zhuang max8925_set_bits(chip->rtc, MAX8925_MPL_CNTL, 1 << 4, 1 << 4); 6151f1cf8f9SHaojian Zhuang 6161f1cf8f9SHaojian Zhuang ret = mfd_add_devices(chip->dev, 0, &rtc_devs[0], 6171f1cf8f9SHaojian Zhuang ARRAY_SIZE(rtc_devs), 6181f1cf8f9SHaojian Zhuang &rtc_resources[0], 0); 619d50f8f33SHaojian Zhuang if (ret < 0) { 6201f1cf8f9SHaojian Zhuang dev_err(chip->dev, "Failed to add rtc subdev\n"); 621d50f8f33SHaojian Zhuang goto out; 622d50f8f33SHaojian Zhuang } 623d0f7a6d6SHaojian Zhuang 624d0f7a6d6SHaojian Zhuang ret = mfd_add_devices(chip->dev, 0, &onkey_devs[0], 625d0f7a6d6SHaojian Zhuang ARRAY_SIZE(onkey_devs), 626d0f7a6d6SHaojian Zhuang &onkey_resources[0], 0); 627d0f7a6d6SHaojian Zhuang if (ret < 0) { 628d0f7a6d6SHaojian Zhuang dev_err(chip->dev, "Failed to add onkey subdev\n"); 629d0f7a6d6SHaojian Zhuang goto out_dev; 630d0f7a6d6SHaojian Zhuang } 631d0f7a6d6SHaojian Zhuang 6321f1cf8f9SHaojian Zhuang if (pdata && pdata->regulator[0]) { 6331ad99893SHaojian Zhuang ret = mfd_add_devices(chip->dev, 0, ®ulator_devs[0], 6341ad99893SHaojian Zhuang ARRAY_SIZE(regulator_devs), 6351ad99893SHaojian Zhuang ®ulator_resources[0], 0); 6361ad99893SHaojian Zhuang if (ret < 0) { 6371ad99893SHaojian Zhuang dev_err(chip->dev, "Failed to add regulator subdev\n"); 6381f1cf8f9SHaojian Zhuang goto out_dev; 6391f1cf8f9SHaojian Zhuang } 6401ad99893SHaojian Zhuang } 6411ad99893SHaojian Zhuang 6421ad99893SHaojian Zhuang if (pdata && pdata->backlight) { 6431ad99893SHaojian Zhuang ret = mfd_add_devices(chip->dev, 0, &backlight_devs[0], 6441ad99893SHaojian Zhuang ARRAY_SIZE(backlight_devs), 6451ad99893SHaojian Zhuang &backlight_resources[0], 0); 6461ad99893SHaojian Zhuang if (ret < 0) { 6471ad99893SHaojian Zhuang dev_err(chip->dev, "Failed to add backlight subdev\n"); 6481ad99893SHaojian Zhuang goto out_dev; 6491ad99893SHaojian Zhuang } 6501ad99893SHaojian Zhuang } 651d50f8f33SHaojian Zhuang 6521f1cf8f9SHaojian Zhuang if (pdata && pdata->power) { 6531f1cf8f9SHaojian Zhuang ret = mfd_add_devices(chip->dev, 0, &power_devs[0], 6541f1cf8f9SHaojian Zhuang ARRAY_SIZE(power_devs), 6551f1cf8f9SHaojian Zhuang &power_supply_resources[0], 0); 656d50f8f33SHaojian Zhuang if (ret < 0) { 6571f1cf8f9SHaojian Zhuang dev_err(chip->dev, "Failed to add power supply " 6581f1cf8f9SHaojian Zhuang "subdev\n"); 6591f1cf8f9SHaojian Zhuang goto out_dev; 660d50f8f33SHaojian Zhuang } 6611f1cf8f9SHaojian Zhuang } 6621ad99893SHaojian Zhuang 6631ad99893SHaojian Zhuang if (pdata && pdata->touch) { 6641ad99893SHaojian Zhuang ret = mfd_add_devices(chip->dev, 0, &touch_devs[0], 6651ad99893SHaojian Zhuang ARRAY_SIZE(touch_devs), 6661ad99893SHaojian Zhuang &touch_resources[0], 0); 6671ad99893SHaojian Zhuang if (ret < 0) { 6681ad99893SHaojian Zhuang dev_err(chip->dev, "Failed to add touch subdev\n"); 6691f1cf8f9SHaojian Zhuang goto out_dev; 6701ad99893SHaojian Zhuang } 6711ad99893SHaojian Zhuang } 6721f1cf8f9SHaojian Zhuang 6731ad99893SHaojian Zhuang return 0; 6741f1cf8f9SHaojian Zhuang out_dev: 6751f1cf8f9SHaojian Zhuang mfd_remove_devices(chip->dev); 676d50f8f33SHaojian Zhuang out: 677d50f8f33SHaojian Zhuang return ret; 678d50f8f33SHaojian Zhuang } 679d50f8f33SHaojian Zhuang 6801f1cf8f9SHaojian Zhuang void __devexit max8925_device_exit(struct max8925_chip *chip) 681d50f8f33SHaojian Zhuang { 6821f1cf8f9SHaojian Zhuang if (chip->core_irq) 6831f1cf8f9SHaojian Zhuang free_irq(chip->core_irq, chip); 6841f1cf8f9SHaojian Zhuang if (chip->tsc_irq) 6851f1cf8f9SHaojian Zhuang free_irq(chip->tsc_irq, chip); 6861ad99893SHaojian Zhuang mfd_remove_devices(chip->dev); 687d50f8f33SHaojian Zhuang } 688d50f8f33SHaojian Zhuang 6891f1cf8f9SHaojian Zhuang 690d50f8f33SHaojian Zhuang MODULE_DESCRIPTION("PMIC Driver for Maxim MAX8925"); 691d50f8f33SHaojian Zhuang MODULE_AUTHOR("Haojian Zhuang <haojian.zhuang@marvell.com"); 692d50f8f33SHaojian Zhuang MODULE_LICENSE("GPL"); 693