12874c5fdSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later 22945fbc2SGraeme Gregory /* 32945fbc2SGraeme Gregory * TI Palmas MFD Driver 42945fbc2SGraeme Gregory * 52945fbc2SGraeme Gregory * Copyright 2011-2012 Texas Instruments Inc. 62945fbc2SGraeme Gregory * 72945fbc2SGraeme Gregory * Author: Graeme Gregory <gg@slimlogic.co.uk> 82945fbc2SGraeme Gregory */ 92945fbc2SGraeme Gregory 102945fbc2SGraeme Gregory #include <linux/module.h> 112945fbc2SGraeme Gregory #include <linux/moduleparam.h> 122945fbc2SGraeme Gregory #include <linux/init.h> 132945fbc2SGraeme Gregory #include <linux/slab.h> 142945fbc2SGraeme Gregory #include <linux/i2c.h> 152945fbc2SGraeme Gregory #include <linux/interrupt.h> 162945fbc2SGraeme Gregory #include <linux/irq.h> 172945fbc2SGraeme Gregory #include <linux/regmap.h> 182945fbc2SGraeme Gregory #include <linux/err.h> 192945fbc2SGraeme Gregory #include <linux/mfd/core.h> 202945fbc2SGraeme Gregory #include <linux/mfd/palmas.h> 211ffb0be3SJ Keerthy #include <linux/of_device.h> 222945fbc2SGraeme Gregory 232945fbc2SGraeme Gregory static const struct regmap_config palmas_regmap_config[PALMAS_NUM_CLIENTS] = { 242945fbc2SGraeme Gregory { 252945fbc2SGraeme Gregory .reg_bits = 8, 262945fbc2SGraeme Gregory .val_bits = 8, 272945fbc2SGraeme Gregory .max_register = PALMAS_BASE_TO_REG(PALMAS_PU_PD_OD_BASE, 282945fbc2SGraeme Gregory PALMAS_PRIMARY_SECONDARY_PAD3), 292945fbc2SGraeme Gregory }, 302945fbc2SGraeme Gregory { 312945fbc2SGraeme Gregory .reg_bits = 8, 322945fbc2SGraeme Gregory .val_bits = 8, 332945fbc2SGraeme Gregory .max_register = PALMAS_BASE_TO_REG(PALMAS_GPADC_BASE, 342945fbc2SGraeme Gregory PALMAS_GPADC_SMPS_VSEL_MONITORING), 352945fbc2SGraeme Gregory }, 362945fbc2SGraeme Gregory { 372945fbc2SGraeme Gregory .reg_bits = 8, 382945fbc2SGraeme Gregory .val_bits = 8, 392945fbc2SGraeme Gregory .max_register = PALMAS_BASE_TO_REG(PALMAS_TRIM_GPADC_BASE, 402945fbc2SGraeme Gregory PALMAS_GPADC_TRIM16), 412945fbc2SGraeme Gregory }, 422945fbc2SGraeme Gregory }; 432945fbc2SGraeme Gregory 441c113d83SKeerthy static const struct regmap_irq tps65917_irqs[] = { 451c113d83SKeerthy /* INT1 IRQs */ 461c113d83SKeerthy [TPS65917_RESERVED1] = { 471c113d83SKeerthy .mask = TPS65917_RESERVED, 481c113d83SKeerthy }, 491c113d83SKeerthy [TPS65917_PWRON_IRQ] = { 501c113d83SKeerthy .mask = TPS65917_INT1_STATUS_PWRON, 511c113d83SKeerthy }, 521c113d83SKeerthy [TPS65917_LONG_PRESS_KEY_IRQ] = { 531c113d83SKeerthy .mask = TPS65917_INT1_STATUS_LONG_PRESS_KEY, 541c113d83SKeerthy }, 551c113d83SKeerthy [TPS65917_RESERVED2] = { 561c113d83SKeerthy .mask = TPS65917_RESERVED, 571c113d83SKeerthy }, 581c113d83SKeerthy [TPS65917_PWRDOWN_IRQ] = { 591c113d83SKeerthy .mask = TPS65917_INT1_STATUS_PWRDOWN, 601c113d83SKeerthy }, 611c113d83SKeerthy [TPS65917_HOTDIE_IRQ] = { 621c113d83SKeerthy .mask = TPS65917_INT1_STATUS_HOTDIE, 631c113d83SKeerthy }, 641c113d83SKeerthy [TPS65917_VSYS_MON_IRQ] = { 651c113d83SKeerthy .mask = TPS65917_INT1_STATUS_VSYS_MON, 661c113d83SKeerthy }, 671c113d83SKeerthy [TPS65917_RESERVED3] = { 681c113d83SKeerthy .mask = TPS65917_RESERVED, 691c113d83SKeerthy }, 701c113d83SKeerthy /* INT2 IRQs*/ 711c113d83SKeerthy [TPS65917_RESERVED4] = { 721c113d83SKeerthy .mask = TPS65917_RESERVED, 731c113d83SKeerthy .reg_offset = 1, 741c113d83SKeerthy }, 751c113d83SKeerthy [TPS65917_OTP_ERROR_IRQ] = { 761c113d83SKeerthy .mask = TPS65917_INT2_STATUS_OTP_ERROR, 771c113d83SKeerthy .reg_offset = 1, 781c113d83SKeerthy }, 791c113d83SKeerthy [TPS65917_WDT_IRQ] = { 801c113d83SKeerthy .mask = TPS65917_INT2_STATUS_WDT, 811c113d83SKeerthy .reg_offset = 1, 821c113d83SKeerthy }, 831c113d83SKeerthy [TPS65917_RESERVED5] = { 841c113d83SKeerthy .mask = TPS65917_RESERVED, 851c113d83SKeerthy .reg_offset = 1, 861c113d83SKeerthy }, 871c113d83SKeerthy [TPS65917_RESET_IN_IRQ] = { 881c113d83SKeerthy .mask = TPS65917_INT2_STATUS_RESET_IN, 891c113d83SKeerthy .reg_offset = 1, 901c113d83SKeerthy }, 911c113d83SKeerthy [TPS65917_FSD_IRQ] = { 921c113d83SKeerthy .mask = TPS65917_INT2_STATUS_FSD, 931c113d83SKeerthy .reg_offset = 1, 941c113d83SKeerthy }, 951c113d83SKeerthy [TPS65917_SHORT_IRQ] = { 961c113d83SKeerthy .mask = TPS65917_INT2_STATUS_SHORT, 971c113d83SKeerthy .reg_offset = 1, 981c113d83SKeerthy }, 991c113d83SKeerthy [TPS65917_RESERVED6] = { 1001c113d83SKeerthy .mask = TPS65917_RESERVED, 1011c113d83SKeerthy .reg_offset = 1, 1021c113d83SKeerthy }, 1031c113d83SKeerthy /* INT3 IRQs */ 1041c113d83SKeerthy [TPS65917_GPADC_AUTO_0_IRQ] = { 1051c113d83SKeerthy .mask = TPS65917_INT3_STATUS_GPADC_AUTO_0, 1061c113d83SKeerthy .reg_offset = 2, 1071c113d83SKeerthy }, 1081c113d83SKeerthy [TPS65917_GPADC_AUTO_1_IRQ] = { 1091c113d83SKeerthy .mask = TPS65917_INT3_STATUS_GPADC_AUTO_1, 1101c113d83SKeerthy .reg_offset = 2, 1111c113d83SKeerthy }, 1121c113d83SKeerthy [TPS65917_GPADC_EOC_SW_IRQ] = { 1131c113d83SKeerthy .mask = TPS65917_INT3_STATUS_GPADC_EOC_SW, 1141c113d83SKeerthy .reg_offset = 2, 1151c113d83SKeerthy }, 1161c113d83SKeerthy [TPS65917_RESREVED6] = { 1171c113d83SKeerthy .mask = TPS65917_RESERVED6, 1181c113d83SKeerthy .reg_offset = 2, 1191c113d83SKeerthy }, 1201c113d83SKeerthy [TPS65917_RESERVED7] = { 1211c113d83SKeerthy .mask = TPS65917_RESERVED, 1221c113d83SKeerthy .reg_offset = 2, 1231c113d83SKeerthy }, 1241c113d83SKeerthy [TPS65917_RESERVED8] = { 1251c113d83SKeerthy .mask = TPS65917_RESERVED, 1261c113d83SKeerthy .reg_offset = 2, 1271c113d83SKeerthy }, 1281c113d83SKeerthy [TPS65917_RESERVED9] = { 1291c113d83SKeerthy .mask = TPS65917_RESERVED, 1301c113d83SKeerthy .reg_offset = 2, 1311c113d83SKeerthy }, 1321c113d83SKeerthy [TPS65917_VBUS_IRQ] = { 1331c113d83SKeerthy .mask = TPS65917_INT3_STATUS_VBUS, 1341c113d83SKeerthy .reg_offset = 2, 1351c113d83SKeerthy }, 1361c113d83SKeerthy /* INT4 IRQs */ 1371c113d83SKeerthy [TPS65917_GPIO_0_IRQ] = { 1381c113d83SKeerthy .mask = TPS65917_INT4_STATUS_GPIO_0, 1391c113d83SKeerthy .reg_offset = 3, 1401c113d83SKeerthy }, 1411c113d83SKeerthy [TPS65917_GPIO_1_IRQ] = { 1421c113d83SKeerthy .mask = TPS65917_INT4_STATUS_GPIO_1, 1431c113d83SKeerthy .reg_offset = 3, 1441c113d83SKeerthy }, 1451c113d83SKeerthy [TPS65917_GPIO_2_IRQ] = { 1461c113d83SKeerthy .mask = TPS65917_INT4_STATUS_GPIO_2, 1471c113d83SKeerthy .reg_offset = 3, 1481c113d83SKeerthy }, 1491c113d83SKeerthy [TPS65917_GPIO_3_IRQ] = { 1501c113d83SKeerthy .mask = TPS65917_INT4_STATUS_GPIO_3, 1511c113d83SKeerthy .reg_offset = 3, 1521c113d83SKeerthy }, 1531c113d83SKeerthy [TPS65917_GPIO_4_IRQ] = { 1541c113d83SKeerthy .mask = TPS65917_INT4_STATUS_GPIO_4, 1551c113d83SKeerthy .reg_offset = 3, 1561c113d83SKeerthy }, 1571c113d83SKeerthy [TPS65917_GPIO_5_IRQ] = { 1581c113d83SKeerthy .mask = TPS65917_INT4_STATUS_GPIO_5, 1591c113d83SKeerthy .reg_offset = 3, 1601c113d83SKeerthy }, 1611c113d83SKeerthy [TPS65917_GPIO_6_IRQ] = { 1621c113d83SKeerthy .mask = TPS65917_INT4_STATUS_GPIO_6, 1631c113d83SKeerthy .reg_offset = 3, 1641c113d83SKeerthy }, 1651c113d83SKeerthy [TPS65917_RESERVED10] = { 1661c113d83SKeerthy .mask = TPS65917_RESERVED10, 1671c113d83SKeerthy .reg_offset = 3, 1681c113d83SKeerthy }, 1691c113d83SKeerthy }; 1701c113d83SKeerthy 1712945fbc2SGraeme Gregory static const struct regmap_irq palmas_irqs[] = { 1722945fbc2SGraeme Gregory /* INT1 IRQs */ 1732945fbc2SGraeme Gregory [PALMAS_CHARG_DET_N_VBUS_OVV_IRQ] = { 1742945fbc2SGraeme Gregory .mask = PALMAS_INT1_STATUS_CHARG_DET_N_VBUS_OVV, 1752945fbc2SGraeme Gregory }, 1762945fbc2SGraeme Gregory [PALMAS_PWRON_IRQ] = { 1772945fbc2SGraeme Gregory .mask = PALMAS_INT1_STATUS_PWRON, 1782945fbc2SGraeme Gregory }, 1792945fbc2SGraeme Gregory [PALMAS_LONG_PRESS_KEY_IRQ] = { 1802945fbc2SGraeme Gregory .mask = PALMAS_INT1_STATUS_LONG_PRESS_KEY, 1812945fbc2SGraeme Gregory }, 1822945fbc2SGraeme Gregory [PALMAS_RPWRON_IRQ] = { 1832945fbc2SGraeme Gregory .mask = PALMAS_INT1_STATUS_RPWRON, 1842945fbc2SGraeme Gregory }, 1852945fbc2SGraeme Gregory [PALMAS_PWRDOWN_IRQ] = { 1862945fbc2SGraeme Gregory .mask = PALMAS_INT1_STATUS_PWRDOWN, 1872945fbc2SGraeme Gregory }, 1882945fbc2SGraeme Gregory [PALMAS_HOTDIE_IRQ] = { 1892945fbc2SGraeme Gregory .mask = PALMAS_INT1_STATUS_HOTDIE, 1902945fbc2SGraeme Gregory }, 1912945fbc2SGraeme Gregory [PALMAS_VSYS_MON_IRQ] = { 1922945fbc2SGraeme Gregory .mask = PALMAS_INT1_STATUS_VSYS_MON, 1932945fbc2SGraeme Gregory }, 1942945fbc2SGraeme Gregory [PALMAS_VBAT_MON_IRQ] = { 1952945fbc2SGraeme Gregory .mask = PALMAS_INT1_STATUS_VBAT_MON, 1962945fbc2SGraeme Gregory }, 1972945fbc2SGraeme Gregory /* INT2 IRQs*/ 1982945fbc2SGraeme Gregory [PALMAS_RTC_ALARM_IRQ] = { 1992945fbc2SGraeme Gregory .mask = PALMAS_INT2_STATUS_RTC_ALARM, 2002945fbc2SGraeme Gregory .reg_offset = 1, 2012945fbc2SGraeme Gregory }, 2022945fbc2SGraeme Gregory [PALMAS_RTC_TIMER_IRQ] = { 2032945fbc2SGraeme Gregory .mask = PALMAS_INT2_STATUS_RTC_TIMER, 2042945fbc2SGraeme Gregory .reg_offset = 1, 2052945fbc2SGraeme Gregory }, 2062945fbc2SGraeme Gregory [PALMAS_WDT_IRQ] = { 2072945fbc2SGraeme Gregory .mask = PALMAS_INT2_STATUS_WDT, 2082945fbc2SGraeme Gregory .reg_offset = 1, 2092945fbc2SGraeme Gregory }, 2102945fbc2SGraeme Gregory [PALMAS_BATREMOVAL_IRQ] = { 2112945fbc2SGraeme Gregory .mask = PALMAS_INT2_STATUS_BATREMOVAL, 2122945fbc2SGraeme Gregory .reg_offset = 1, 2132945fbc2SGraeme Gregory }, 2142945fbc2SGraeme Gregory [PALMAS_RESET_IN_IRQ] = { 2152945fbc2SGraeme Gregory .mask = PALMAS_INT2_STATUS_RESET_IN, 2162945fbc2SGraeme Gregory .reg_offset = 1, 2172945fbc2SGraeme Gregory }, 2182945fbc2SGraeme Gregory [PALMAS_FBI_BB_IRQ] = { 2192945fbc2SGraeme Gregory .mask = PALMAS_INT2_STATUS_FBI_BB, 2202945fbc2SGraeme Gregory .reg_offset = 1, 2212945fbc2SGraeme Gregory }, 2222945fbc2SGraeme Gregory [PALMAS_SHORT_IRQ] = { 2232945fbc2SGraeme Gregory .mask = PALMAS_INT2_STATUS_SHORT, 2242945fbc2SGraeme Gregory .reg_offset = 1, 2252945fbc2SGraeme Gregory }, 2262945fbc2SGraeme Gregory [PALMAS_VAC_ACOK_IRQ] = { 2272945fbc2SGraeme Gregory .mask = PALMAS_INT2_STATUS_VAC_ACOK, 2282945fbc2SGraeme Gregory .reg_offset = 1, 2292945fbc2SGraeme Gregory }, 2302945fbc2SGraeme Gregory /* INT3 IRQs */ 2312945fbc2SGraeme Gregory [PALMAS_GPADC_AUTO_0_IRQ] = { 2322945fbc2SGraeme Gregory .mask = PALMAS_INT3_STATUS_GPADC_AUTO_0, 2332945fbc2SGraeme Gregory .reg_offset = 2, 2342945fbc2SGraeme Gregory }, 2352945fbc2SGraeme Gregory [PALMAS_GPADC_AUTO_1_IRQ] = { 2362945fbc2SGraeme Gregory .mask = PALMAS_INT3_STATUS_GPADC_AUTO_1, 2372945fbc2SGraeme Gregory .reg_offset = 2, 2382945fbc2SGraeme Gregory }, 2392945fbc2SGraeme Gregory [PALMAS_GPADC_EOC_SW_IRQ] = { 2402945fbc2SGraeme Gregory .mask = PALMAS_INT3_STATUS_GPADC_EOC_SW, 2412945fbc2SGraeme Gregory .reg_offset = 2, 2422945fbc2SGraeme Gregory }, 2432945fbc2SGraeme Gregory [PALMAS_GPADC_EOC_RT_IRQ] = { 2442945fbc2SGraeme Gregory .mask = PALMAS_INT3_STATUS_GPADC_EOC_RT, 2452945fbc2SGraeme Gregory .reg_offset = 2, 2462945fbc2SGraeme Gregory }, 2472945fbc2SGraeme Gregory [PALMAS_ID_OTG_IRQ] = { 2482945fbc2SGraeme Gregory .mask = PALMAS_INT3_STATUS_ID_OTG, 2492945fbc2SGraeme Gregory .reg_offset = 2, 2502945fbc2SGraeme Gregory }, 2512945fbc2SGraeme Gregory [PALMAS_ID_IRQ] = { 2522945fbc2SGraeme Gregory .mask = PALMAS_INT3_STATUS_ID, 2532945fbc2SGraeme Gregory .reg_offset = 2, 2542945fbc2SGraeme Gregory }, 2552945fbc2SGraeme Gregory [PALMAS_VBUS_OTG_IRQ] = { 2562945fbc2SGraeme Gregory .mask = PALMAS_INT3_STATUS_VBUS_OTG, 2572945fbc2SGraeme Gregory .reg_offset = 2, 2582945fbc2SGraeme Gregory }, 2592945fbc2SGraeme Gregory [PALMAS_VBUS_IRQ] = { 2602945fbc2SGraeme Gregory .mask = PALMAS_INT3_STATUS_VBUS, 2612945fbc2SGraeme Gregory .reg_offset = 2, 2622945fbc2SGraeme Gregory }, 2632945fbc2SGraeme Gregory /* INT4 IRQs */ 2642945fbc2SGraeme Gregory [PALMAS_GPIO_0_IRQ] = { 2652945fbc2SGraeme Gregory .mask = PALMAS_INT4_STATUS_GPIO_0, 2662945fbc2SGraeme Gregory .reg_offset = 3, 2672945fbc2SGraeme Gregory }, 2682945fbc2SGraeme Gregory [PALMAS_GPIO_1_IRQ] = { 2692945fbc2SGraeme Gregory .mask = PALMAS_INT4_STATUS_GPIO_1, 2702945fbc2SGraeme Gregory .reg_offset = 3, 2712945fbc2SGraeme Gregory }, 2722945fbc2SGraeme Gregory [PALMAS_GPIO_2_IRQ] = { 2732945fbc2SGraeme Gregory .mask = PALMAS_INT4_STATUS_GPIO_2, 2742945fbc2SGraeme Gregory .reg_offset = 3, 2752945fbc2SGraeme Gregory }, 2762945fbc2SGraeme Gregory [PALMAS_GPIO_3_IRQ] = { 2772945fbc2SGraeme Gregory .mask = PALMAS_INT4_STATUS_GPIO_3, 2782945fbc2SGraeme Gregory .reg_offset = 3, 2792945fbc2SGraeme Gregory }, 2802945fbc2SGraeme Gregory [PALMAS_GPIO_4_IRQ] = { 2812945fbc2SGraeme Gregory .mask = PALMAS_INT4_STATUS_GPIO_4, 2822945fbc2SGraeme Gregory .reg_offset = 3, 2832945fbc2SGraeme Gregory }, 2842945fbc2SGraeme Gregory [PALMAS_GPIO_5_IRQ] = { 2852945fbc2SGraeme Gregory .mask = PALMAS_INT4_STATUS_GPIO_5, 2862945fbc2SGraeme Gregory .reg_offset = 3, 2872945fbc2SGraeme Gregory }, 2882945fbc2SGraeme Gregory [PALMAS_GPIO_6_IRQ] = { 2892945fbc2SGraeme Gregory .mask = PALMAS_INT4_STATUS_GPIO_6, 2902945fbc2SGraeme Gregory .reg_offset = 3, 2912945fbc2SGraeme Gregory }, 2922945fbc2SGraeme Gregory [PALMAS_GPIO_7_IRQ] = { 2932945fbc2SGraeme Gregory .mask = PALMAS_INT4_STATUS_GPIO_7, 2942945fbc2SGraeme Gregory .reg_offset = 3, 2952945fbc2SGraeme Gregory }, 2962945fbc2SGraeme Gregory }; 2972945fbc2SGraeme Gregory 2982945fbc2SGraeme Gregory static struct regmap_irq_chip palmas_irq_chip = { 2992945fbc2SGraeme Gregory .name = "palmas", 3002945fbc2SGraeme Gregory .irqs = palmas_irqs, 3012945fbc2SGraeme Gregory .num_irqs = ARRAY_SIZE(palmas_irqs), 3022945fbc2SGraeme Gregory 3032945fbc2SGraeme Gregory .num_regs = 4, 3042945fbc2SGraeme Gregory .irq_reg_stride = 5, 3052945fbc2SGraeme Gregory .status_base = PALMAS_BASE_TO_REG(PALMAS_INTERRUPT_BASE, 3062945fbc2SGraeme Gregory PALMAS_INT1_STATUS), 3072945fbc2SGraeme Gregory .mask_base = PALMAS_BASE_TO_REG(PALMAS_INTERRUPT_BASE, 3082945fbc2SGraeme Gregory PALMAS_INT1_MASK), 3092945fbc2SGraeme Gregory }; 3102945fbc2SGraeme Gregory 3111c113d83SKeerthy static struct regmap_irq_chip tps65917_irq_chip = { 3121c113d83SKeerthy .name = "tps65917", 3131c113d83SKeerthy .irqs = tps65917_irqs, 3141c113d83SKeerthy .num_irqs = ARRAY_SIZE(tps65917_irqs), 3151c113d83SKeerthy 3161c113d83SKeerthy .num_regs = 4, 3171c113d83SKeerthy .irq_reg_stride = 5, 3181c113d83SKeerthy .status_base = PALMAS_BASE_TO_REG(PALMAS_INTERRUPT_BASE, 3191c113d83SKeerthy PALMAS_INT1_STATUS), 3201c113d83SKeerthy .mask_base = PALMAS_BASE_TO_REG(PALMAS_INTERRUPT_BASE, 3211c113d83SKeerthy PALMAS_INT1_MASK), 3221c113d83SKeerthy }; 3231c113d83SKeerthy 324cc01b463SLaxman Dewangan int palmas_ext_control_req_config(struct palmas *palmas, 325cc01b463SLaxman Dewangan enum palmas_external_requestor_id id, int ext_ctrl, bool enable) 326cc01b463SLaxman Dewangan { 327cac9e916SKeerthy struct palmas_pmic_driver_data *pmic_ddata = palmas->pmic_ddata; 328cc01b463SLaxman Dewangan int preq_mask_bit = 0; 329cc01b463SLaxman Dewangan int reg_add = 0; 330cac9e916SKeerthy int bit_pos, ret; 331cc01b463SLaxman Dewangan 332cc01b463SLaxman Dewangan if (!(ext_ctrl & PALMAS_EXT_REQ)) 333cc01b463SLaxman Dewangan return 0; 334cc01b463SLaxman Dewangan 335cc01b463SLaxman Dewangan if (id >= PALMAS_EXTERNAL_REQSTR_ID_MAX) 336cc01b463SLaxman Dewangan return 0; 337cc01b463SLaxman Dewangan 338cc01b463SLaxman Dewangan if (ext_ctrl & PALMAS_EXT_CONTROL_NSLEEP) { 339cc01b463SLaxman Dewangan reg_add = PALMAS_NSLEEP_RES_ASSIGN; 340cc01b463SLaxman Dewangan preq_mask_bit = 0; 341cc01b463SLaxman Dewangan } else if (ext_ctrl & PALMAS_EXT_CONTROL_ENABLE1) { 342cc01b463SLaxman Dewangan reg_add = PALMAS_ENABLE1_RES_ASSIGN; 343cc01b463SLaxman Dewangan preq_mask_bit = 1; 344cc01b463SLaxman Dewangan } else if (ext_ctrl & PALMAS_EXT_CONTROL_ENABLE2) { 345cc01b463SLaxman Dewangan reg_add = PALMAS_ENABLE2_RES_ASSIGN; 346cc01b463SLaxman Dewangan preq_mask_bit = 2; 347cc01b463SLaxman Dewangan } 348cc01b463SLaxman Dewangan 349cac9e916SKeerthy bit_pos = pmic_ddata->sleep_req_info[id].bit_pos; 350cac9e916SKeerthy reg_add += pmic_ddata->sleep_req_info[id].reg_offset; 351cc01b463SLaxman Dewangan if (enable) 352cc01b463SLaxman Dewangan ret = palmas_update_bits(palmas, PALMAS_RESOURCE_BASE, 353cc01b463SLaxman Dewangan reg_add, BIT(bit_pos), BIT(bit_pos)); 354cc01b463SLaxman Dewangan else 355cc01b463SLaxman Dewangan ret = palmas_update_bits(palmas, PALMAS_RESOURCE_BASE, 356cc01b463SLaxman Dewangan reg_add, BIT(bit_pos), 0); 357cc01b463SLaxman Dewangan if (ret < 0) { 358cc01b463SLaxman Dewangan dev_err(palmas->dev, "Resource reg 0x%02x update failed %d\n", 359cc01b463SLaxman Dewangan reg_add, ret); 360cc01b463SLaxman Dewangan return ret; 361cc01b463SLaxman Dewangan } 362cc01b463SLaxman Dewangan 363cc01b463SLaxman Dewangan /* Unmask the PREQ */ 364cc01b463SLaxman Dewangan ret = palmas_update_bits(palmas, PALMAS_PMU_CONTROL_BASE, 365cc01b463SLaxman Dewangan PALMAS_POWER_CTRL, BIT(preq_mask_bit), 0); 366cc01b463SLaxman Dewangan if (ret < 0) { 367cc01b463SLaxman Dewangan dev_err(palmas->dev, "POWER_CTRL register update failed %d\n", 368cc01b463SLaxman Dewangan ret); 369cc01b463SLaxman Dewangan return ret; 370cc01b463SLaxman Dewangan } 371cc01b463SLaxman Dewangan return ret; 372cc01b463SLaxman Dewangan } 373cc01b463SLaxman Dewangan EXPORT_SYMBOL_GPL(palmas_ext_control_req_config); 374cc01b463SLaxman Dewangan 375df545d1cSLaxman Dewangan static int palmas_set_pdata_irq_flag(struct i2c_client *i2c, 3769c14ac33SGraeme Gregory struct palmas_platform_data *pdata) 3779c14ac33SGraeme Gregory { 378df545d1cSLaxman Dewangan struct irq_data *irq_data = irq_get_irq_data(i2c->irq); 379df545d1cSLaxman Dewangan if (!irq_data) { 380df545d1cSLaxman Dewangan dev_err(&i2c->dev, "Invalid IRQ: %d\n", i2c->irq); 381df545d1cSLaxman Dewangan return -EINVAL; 382df545d1cSLaxman Dewangan } 383df545d1cSLaxman Dewangan 384df545d1cSLaxman Dewangan pdata->irq_flags = irqd_get_trigger_type(irq_data); 385df545d1cSLaxman Dewangan dev_info(&i2c->dev, "Irq flag is 0x%08x\n", pdata->irq_flags); 386df545d1cSLaxman Dewangan return 0; 387df545d1cSLaxman Dewangan } 388df545d1cSLaxman Dewangan 389df545d1cSLaxman Dewangan static void palmas_dt_to_pdata(struct i2c_client *i2c, 390df545d1cSLaxman Dewangan struct palmas_platform_data *pdata) 391df545d1cSLaxman Dewangan { 392df545d1cSLaxman Dewangan struct device_node *node = i2c->dev.of_node; 3939c14ac33SGraeme Gregory int ret; 3949c14ac33SGraeme Gregory u32 prop; 3959c14ac33SGraeme Gregory 3962154a2b3SJ Keerthy ret = of_property_read_u32(node, "ti,mux-pad1", &prop); 3979c14ac33SGraeme Gregory if (!ret) { 3989c14ac33SGraeme Gregory pdata->mux_from_pdata = 1; 3999c14ac33SGraeme Gregory pdata->pad1 = prop; 4009c14ac33SGraeme Gregory } 4019c14ac33SGraeme Gregory 4022154a2b3SJ Keerthy ret = of_property_read_u32(node, "ti,mux-pad2", &prop); 4039c14ac33SGraeme Gregory if (!ret) { 4049c14ac33SGraeme Gregory pdata->mux_from_pdata = 1; 4059c14ac33SGraeme Gregory pdata->pad2 = prop; 4069c14ac33SGraeme Gregory } 4079c14ac33SGraeme Gregory 4089c14ac33SGraeme Gregory /* The default for this register is all masked */ 4092154a2b3SJ Keerthy ret = of_property_read_u32(node, "ti,power-ctrl", &prop); 4109c14ac33SGraeme Gregory if (!ret) 4119c14ac33SGraeme Gregory pdata->power_ctrl = prop; 4129c14ac33SGraeme Gregory else 4139c14ac33SGraeme Gregory pdata->power_ctrl = PALMAS_POWER_CTRL_NSLEEP_MASK | 4149c14ac33SGraeme Gregory PALMAS_POWER_CTRL_ENABLE1_MASK | 4159c14ac33SGraeme Gregory PALMAS_POWER_CTRL_ENABLE2_MASK; 416df545d1cSLaxman Dewangan if (i2c->irq) 417df545d1cSLaxman Dewangan palmas_set_pdata_irq_flag(i2c, pdata); 418b81eec09SBill Huang 419b81eec09SBill Huang pdata->pm_off = of_property_read_bool(node, 420b81eec09SBill Huang "ti,system-power-controller"); 421b81eec09SBill Huang } 422b81eec09SBill Huang 423b81eec09SBill Huang static struct palmas *palmas_dev; 424b81eec09SBill Huang static void palmas_power_off(void) 425b81eec09SBill Huang { 426b81eec09SBill Huang unsigned int addr; 427b81eec09SBill Huang int ret, slave; 428572ff4d5SKeerthy u8 powerhold_mask; 42985fdaf8eSKeerthy struct device_node *np = palmas_dev->dev->of_node; 43085fdaf8eSKeerthy 43185fdaf8eSKeerthy if (of_property_read_bool(np, "ti,palmas-override-powerhold")) { 43285fdaf8eSKeerthy addr = PALMAS_BASE_TO_REG(PALMAS_PU_PD_OD_BASE, 43385fdaf8eSKeerthy PALMAS_PRIMARY_SECONDARY_PAD2); 43485fdaf8eSKeerthy slave = PALMAS_BASE_TO_SLAVE(PALMAS_PU_PD_OD_BASE); 43585fdaf8eSKeerthy 436572ff4d5SKeerthy if (of_device_is_compatible(np, "ti,tps65917")) 437572ff4d5SKeerthy powerhold_mask = 438572ff4d5SKeerthy TPS65917_PRIMARY_SECONDARY_PAD2_GPIO_5_MASK; 439572ff4d5SKeerthy else 440572ff4d5SKeerthy powerhold_mask = 441572ff4d5SKeerthy PALMAS_PRIMARY_SECONDARY_PAD2_GPIO_7_MASK; 442572ff4d5SKeerthy 44385fdaf8eSKeerthy ret = regmap_update_bits(palmas_dev->regmap[slave], addr, 444572ff4d5SKeerthy powerhold_mask, 0); 44585fdaf8eSKeerthy if (ret) 44685fdaf8eSKeerthy dev_err(palmas_dev->dev, 44785fdaf8eSKeerthy "Unable to write PRIMARY_SECONDARY_PAD2 %d\n", 44885fdaf8eSKeerthy ret); 44985fdaf8eSKeerthy } 450b81eec09SBill Huang 451b81eec09SBill Huang slave = PALMAS_BASE_TO_SLAVE(PALMAS_PMU_CONTROL_BASE); 452b81eec09SBill Huang addr = PALMAS_BASE_TO_REG(PALMAS_PMU_CONTROL_BASE, PALMAS_DEV_CTRL); 453b81eec09SBill Huang 454b81eec09SBill Huang ret = regmap_update_bits( 455b81eec09SBill Huang palmas_dev->regmap[slave], 456b81eec09SBill Huang addr, 457b81eec09SBill Huang PALMAS_DEV_CTRL_DEV_ON, 458b81eec09SBill Huang 0); 459b81eec09SBill Huang 460b81eec09SBill Huang if (ret) 461b81eec09SBill Huang pr_err("%s: Unable to write to DEV_CTRL_DEV_ON: %d\n", 462b81eec09SBill Huang __func__, ret); 4639c14ac33SGraeme Gregory } 4649c14ac33SGraeme Gregory 4651ffb0be3SJ Keerthy static unsigned int palmas_features = PALMAS_PMIC_FEATURE_SMPS10_BOOST; 4664124e6e2SJ Keerthy static unsigned int tps659038_features; 4671ffb0be3SJ Keerthy 4681c113d83SKeerthy struct palmas_driver_data { 4691c113d83SKeerthy unsigned int *features; 4701c113d83SKeerthy struct regmap_irq_chip *irq_chip; 4711c113d83SKeerthy }; 4721c113d83SKeerthy 4731c113d83SKeerthy static struct palmas_driver_data palmas_data = { 4741c113d83SKeerthy .features = &palmas_features, 4751c113d83SKeerthy .irq_chip = &palmas_irq_chip, 4761c113d83SKeerthy }; 4771c113d83SKeerthy 4781c113d83SKeerthy static struct palmas_driver_data tps659038_data = { 4791c113d83SKeerthy .features = &tps659038_features, 4801c113d83SKeerthy .irq_chip = &palmas_irq_chip, 4811c113d83SKeerthy }; 4821c113d83SKeerthy 4831c113d83SKeerthy static struct palmas_driver_data tps65917_data = { 4841c113d83SKeerthy .features = &tps659038_features, 4851c113d83SKeerthy .irq_chip = &tps65917_irq_chip, 4861c113d83SKeerthy }; 4871c113d83SKeerthy 4881ffb0be3SJ Keerthy static const struct of_device_id of_palmas_match_tbl[] = { 4891ffb0be3SJ Keerthy { 4901ffb0be3SJ Keerthy .compatible = "ti,palmas", 4911c113d83SKeerthy .data = &palmas_data, 4921ffb0be3SJ Keerthy }, 4934124e6e2SJ Keerthy { 4944124e6e2SJ Keerthy .compatible = "ti,tps659038", 4951c113d83SKeerthy .data = &tps659038_data, 4961c113d83SKeerthy }, 4971c113d83SKeerthy { 4981c113d83SKeerthy .compatible = "ti,tps65917", 4991c113d83SKeerthy .data = &tps65917_data, 5004124e6e2SJ Keerthy }, 5011ffb0be3SJ Keerthy { }, 5021ffb0be3SJ Keerthy }; 5032d8edaf0SLaxman Dewangan MODULE_DEVICE_TABLE(of, of_palmas_match_tbl); 5041ffb0be3SJ Keerthy 505a5d6cbcfSUwe Kleine-König static int palmas_i2c_probe(struct i2c_client *i2c) 5062945fbc2SGraeme Gregory { 5072945fbc2SGraeme Gregory struct palmas *palmas; 5082945fbc2SGraeme Gregory struct palmas_platform_data *pdata; 5091c113d83SKeerthy struct palmas_driver_data *driver_data; 5109c14ac33SGraeme Gregory struct device_node *node = i2c->dev.of_node; 5112945fbc2SGraeme Gregory int ret = 0, i; 5121c113d83SKeerthy unsigned int reg, addr; 5132945fbc2SGraeme Gregory int slave; 5142945fbc2SGraeme Gregory 5152945fbc2SGraeme Gregory pdata = dev_get_platdata(&i2c->dev); 5169c14ac33SGraeme Gregory 5179c14ac33SGraeme Gregory if (node && !pdata) { 5189c14ac33SGraeme Gregory pdata = devm_kzalloc(&i2c->dev, sizeof(*pdata), GFP_KERNEL); 5199c14ac33SGraeme Gregory 5209c14ac33SGraeme Gregory if (!pdata) 5219c14ac33SGraeme Gregory return -ENOMEM; 5229c14ac33SGraeme Gregory 523df545d1cSLaxman Dewangan palmas_dt_to_pdata(i2c, pdata); 5249c14ac33SGraeme Gregory } 5259c14ac33SGraeme Gregory 5262945fbc2SGraeme Gregory if (!pdata) 5272945fbc2SGraeme Gregory return -EINVAL; 5282945fbc2SGraeme Gregory 5292945fbc2SGraeme Gregory palmas = devm_kzalloc(&i2c->dev, sizeof(struct palmas), GFP_KERNEL); 5302945fbc2SGraeme Gregory if (palmas == NULL) 5312945fbc2SGraeme Gregory return -ENOMEM; 5322945fbc2SGraeme Gregory 5332945fbc2SGraeme Gregory i2c_set_clientdata(i2c, palmas); 5342945fbc2SGraeme Gregory palmas->dev = &i2c->dev; 5352945fbc2SGraeme Gregory palmas->irq = i2c->irq; 5362945fbc2SGraeme Gregory 537d0871b5aSye xingchen driver_data = (struct palmas_driver_data *) device_get_match_data(&i2c->dev); 5381c113d83SKeerthy palmas->features = *driver_data->features; 5391ffb0be3SJ Keerthy 5402945fbc2SGraeme Gregory for (i = 0; i < PALMAS_NUM_CLIENTS; i++) { 5412945fbc2SGraeme Gregory if (i == 0) 5422945fbc2SGraeme Gregory palmas->i2c_clients[i] = i2c; 5432945fbc2SGraeme Gregory else { 5442945fbc2SGraeme Gregory palmas->i2c_clients[i] = 545ad9fc1f4SWolfram Sang i2c_new_dummy_device(i2c->adapter, 5462945fbc2SGraeme Gregory i2c->addr + i); 547ad9fc1f4SWolfram Sang if (IS_ERR(palmas->i2c_clients[i])) { 5482945fbc2SGraeme Gregory dev_err(palmas->dev, 5492945fbc2SGraeme Gregory "can't attach client %d\n", i); 550ad9fc1f4SWolfram Sang ret = PTR_ERR(palmas->i2c_clients[i]); 5515e172d75SLaxman Dewangan goto err_i2c; 5522945fbc2SGraeme Gregory } 553c4fbec3cSLaxman Dewangan palmas->i2c_clients[i]->dev.of_node = of_node_get(node); 5542945fbc2SGraeme Gregory } 5552945fbc2SGraeme Gregory palmas->regmap[i] = devm_regmap_init_i2c(palmas->i2c_clients[i], 5562945fbc2SGraeme Gregory &palmas_regmap_config[i]); 5572945fbc2SGraeme Gregory if (IS_ERR(palmas->regmap[i])) { 5582945fbc2SGraeme Gregory ret = PTR_ERR(palmas->regmap[i]); 5592945fbc2SGraeme Gregory dev_err(palmas->dev, 5602945fbc2SGraeme Gregory "Failed to allocate regmap %d, err: %d\n", 5612945fbc2SGraeme Gregory i, ret); 5625e172d75SLaxman Dewangan goto err_i2c; 5632945fbc2SGraeme Gregory } 5642945fbc2SGraeme Gregory } 5652945fbc2SGraeme Gregory 566ad522f4eSJ Keerthy if (!palmas->irq) { 567ad522f4eSJ Keerthy dev_warn(palmas->dev, "IRQ missing: skipping irq request\n"); 568ad522f4eSJ Keerthy goto no_irq; 569ad522f4eSJ Keerthy } 570ad522f4eSJ Keerthy 571df545d1cSLaxman Dewangan /* Change interrupt line output polarity */ 572df545d1cSLaxman Dewangan if (pdata->irq_flags & IRQ_TYPE_LEVEL_HIGH) 573df545d1cSLaxman Dewangan reg = PALMAS_POLARITY_CTRL_INT_POLARITY; 574df545d1cSLaxman Dewangan else 575df545d1cSLaxman Dewangan reg = 0; 576df545d1cSLaxman Dewangan ret = palmas_update_bits(palmas, PALMAS_PU_PD_OD_BASE, 577df545d1cSLaxman Dewangan PALMAS_POLARITY_CTRL, PALMAS_POLARITY_CTRL_INT_POLARITY, 578df545d1cSLaxman Dewangan reg); 579df545d1cSLaxman Dewangan if (ret < 0) { 580b5b086abSWillis Monroe dev_err(palmas->dev, "POLARITY_CTRL update failed: %d\n", ret); 5815e172d75SLaxman Dewangan goto err_i2c; 582df545d1cSLaxman Dewangan } 583df545d1cSLaxman Dewangan 584b330f85dSGraeme Gregory /* Change IRQ into clear on read mode for efficiency */ 585b330f85dSGraeme Gregory slave = PALMAS_BASE_TO_SLAVE(PALMAS_INTERRUPT_BASE); 586b330f85dSGraeme Gregory addr = PALMAS_BASE_TO_REG(PALMAS_INTERRUPT_BASE, PALMAS_INT_CTRL); 587b330f85dSGraeme Gregory reg = PALMAS_INT_CTRL_INT_CLEAR; 588b330f85dSGraeme Gregory 589b330f85dSGraeme Gregory regmap_write(palmas->regmap[slave], addr, reg); 590b330f85dSGraeme Gregory 591b330f85dSGraeme Gregory ret = regmap_add_irq_chip(palmas->regmap[slave], palmas->irq, 5921c113d83SKeerthy IRQF_ONESHOT | pdata->irq_flags, 0, 5931c113d83SKeerthy driver_data->irq_chip, &palmas->irq_data); 5942945fbc2SGraeme Gregory if (ret < 0) 5955e172d75SLaxman Dewangan goto err_i2c; 5962945fbc2SGraeme Gregory 597ad522f4eSJ Keerthy no_irq: 5982945fbc2SGraeme Gregory slave = PALMAS_BASE_TO_SLAVE(PALMAS_PU_PD_OD_BASE); 5992945fbc2SGraeme Gregory addr = PALMAS_BASE_TO_REG(PALMAS_PU_PD_OD_BASE, 6002945fbc2SGraeme Gregory PALMAS_PRIMARY_SECONDARY_PAD1); 6012945fbc2SGraeme Gregory 6022945fbc2SGraeme Gregory if (pdata->mux_from_pdata) { 6032945fbc2SGraeme Gregory reg = pdata->pad1; 6042945fbc2SGraeme Gregory ret = regmap_write(palmas->regmap[slave], addr, reg); 6052945fbc2SGraeme Gregory if (ret) 6063f78deccSGraeme Gregory goto err_irq; 6072945fbc2SGraeme Gregory } else { 6082945fbc2SGraeme Gregory ret = regmap_read(palmas->regmap[slave], addr, ®); 6092945fbc2SGraeme Gregory if (ret) 6103f78deccSGraeme Gregory goto err_irq; 6112945fbc2SGraeme Gregory } 6122945fbc2SGraeme Gregory 6132945fbc2SGraeme Gregory if (!(reg & PALMAS_PRIMARY_SECONDARY_PAD1_GPIO_0)) 6142945fbc2SGraeme Gregory palmas->gpio_muxed |= PALMAS_GPIO_0_MUXED; 6152945fbc2SGraeme Gregory if (!(reg & PALMAS_PRIMARY_SECONDARY_PAD1_GPIO_1_MASK)) 6162945fbc2SGraeme Gregory palmas->gpio_muxed |= PALMAS_GPIO_1_MUXED; 6172945fbc2SGraeme Gregory else if ((reg & PALMAS_PRIMARY_SECONDARY_PAD1_GPIO_1_MASK) == 6182945fbc2SGraeme Gregory (2 << PALMAS_PRIMARY_SECONDARY_PAD1_GPIO_1_SHIFT)) 6192945fbc2SGraeme Gregory palmas->led_muxed |= PALMAS_LED1_MUXED; 6202945fbc2SGraeme Gregory else if ((reg & PALMAS_PRIMARY_SECONDARY_PAD1_GPIO_1_MASK) == 6212945fbc2SGraeme Gregory (3 << PALMAS_PRIMARY_SECONDARY_PAD1_GPIO_1_SHIFT)) 6222945fbc2SGraeme Gregory palmas->pwm_muxed |= PALMAS_PWM1_MUXED; 6232945fbc2SGraeme Gregory if (!(reg & PALMAS_PRIMARY_SECONDARY_PAD1_GPIO_2_MASK)) 6242945fbc2SGraeme Gregory palmas->gpio_muxed |= PALMAS_GPIO_2_MUXED; 6252945fbc2SGraeme Gregory else if ((reg & PALMAS_PRIMARY_SECONDARY_PAD1_GPIO_2_MASK) == 6262945fbc2SGraeme Gregory (2 << PALMAS_PRIMARY_SECONDARY_PAD1_GPIO_2_SHIFT)) 6272945fbc2SGraeme Gregory palmas->led_muxed |= PALMAS_LED2_MUXED; 6282945fbc2SGraeme Gregory else if ((reg & PALMAS_PRIMARY_SECONDARY_PAD1_GPIO_2_MASK) == 6292945fbc2SGraeme Gregory (3 << PALMAS_PRIMARY_SECONDARY_PAD1_GPIO_2_SHIFT)) 6302945fbc2SGraeme Gregory palmas->pwm_muxed |= PALMAS_PWM2_MUXED; 6312945fbc2SGraeme Gregory if (!(reg & PALMAS_PRIMARY_SECONDARY_PAD1_GPIO_3)) 6322945fbc2SGraeme Gregory palmas->gpio_muxed |= PALMAS_GPIO_3_MUXED; 6332945fbc2SGraeme Gregory 6342945fbc2SGraeme Gregory addr = PALMAS_BASE_TO_REG(PALMAS_PU_PD_OD_BASE, 6352945fbc2SGraeme Gregory PALMAS_PRIMARY_SECONDARY_PAD2); 6362945fbc2SGraeme Gregory 6372945fbc2SGraeme Gregory if (pdata->mux_from_pdata) { 6382945fbc2SGraeme Gregory reg = pdata->pad2; 6392945fbc2SGraeme Gregory ret = regmap_write(palmas->regmap[slave], addr, reg); 6402945fbc2SGraeme Gregory if (ret) 6413f78deccSGraeme Gregory goto err_irq; 6422945fbc2SGraeme Gregory } else { 6432945fbc2SGraeme Gregory ret = regmap_read(palmas->regmap[slave], addr, ®); 6442945fbc2SGraeme Gregory if (ret) 6453f78deccSGraeme Gregory goto err_irq; 6462945fbc2SGraeme Gregory } 6472945fbc2SGraeme Gregory 6482945fbc2SGraeme Gregory if (!(reg & PALMAS_PRIMARY_SECONDARY_PAD2_GPIO_4)) 6492945fbc2SGraeme Gregory palmas->gpio_muxed |= PALMAS_GPIO_4_MUXED; 6502945fbc2SGraeme Gregory if (!(reg & PALMAS_PRIMARY_SECONDARY_PAD2_GPIO_5_MASK)) 6512945fbc2SGraeme Gregory palmas->gpio_muxed |= PALMAS_GPIO_5_MUXED; 6522945fbc2SGraeme Gregory if (!(reg & PALMAS_PRIMARY_SECONDARY_PAD2_GPIO_6)) 6532945fbc2SGraeme Gregory palmas->gpio_muxed |= PALMAS_GPIO_6_MUXED; 6542945fbc2SGraeme Gregory if (!(reg & PALMAS_PRIMARY_SECONDARY_PAD2_GPIO_7_MASK)) 6552945fbc2SGraeme Gregory palmas->gpio_muxed |= PALMAS_GPIO_7_MUXED; 6562945fbc2SGraeme Gregory 6572945fbc2SGraeme Gregory dev_info(palmas->dev, "Muxing GPIO %x, PWM %x, LED %x\n", 6582945fbc2SGraeme Gregory palmas->gpio_muxed, palmas->pwm_muxed, 6592945fbc2SGraeme Gregory palmas->led_muxed); 6602945fbc2SGraeme Gregory 6612945fbc2SGraeme Gregory reg = pdata->power_ctrl; 6622945fbc2SGraeme Gregory 6632945fbc2SGraeme Gregory slave = PALMAS_BASE_TO_SLAVE(PALMAS_PMU_CONTROL_BASE); 6642945fbc2SGraeme Gregory addr = PALMAS_BASE_TO_REG(PALMAS_PMU_CONTROL_BASE, PALMAS_POWER_CTRL); 6652945fbc2SGraeme Gregory 6662945fbc2SGraeme Gregory ret = regmap_write(palmas->regmap[slave], addr, reg); 6672945fbc2SGraeme Gregory if (ret) 6683f78deccSGraeme Gregory goto err_irq; 6692945fbc2SGraeme Gregory 6709c14ac33SGraeme Gregory /* 6719c14ac33SGraeme Gregory * If we are probing with DT do this the DT way and return here 6729c14ac33SGraeme Gregory * otherwise continue and add devices using mfd helpers. 6739c14ac33SGraeme Gregory */ 6749c14ac33SGraeme Gregory if (node) { 675124e9debSBenjamin Gaignard ret = devm_of_platform_populate(&i2c->dev); 676b81eec09SBill Huang if (ret < 0) { 6779c14ac33SGraeme Gregory goto err_irq; 678b81eec09SBill Huang } else if (pdata->pm_off && !pm_power_off) { 679b81eec09SBill Huang palmas_dev = palmas; 680b81eec09SBill Huang pm_power_off = palmas_power_off; 6819c14ac33SGraeme Gregory } 682b81eec09SBill Huang } 6839c14ac33SGraeme Gregory 6842945fbc2SGraeme Gregory return ret; 6852945fbc2SGraeme Gregory 6863f78deccSGraeme Gregory err_irq: 6873f78deccSGraeme Gregory regmap_del_irq_chip(palmas->irq, palmas->irq_data); 6885e172d75SLaxman Dewangan err_i2c: 6895e172d75SLaxman Dewangan for (i = 1; i < PALMAS_NUM_CLIENTS; i++) { 6905e172d75SLaxman Dewangan if (palmas->i2c_clients[i]) 6915e172d75SLaxman Dewangan i2c_unregister_device(palmas->i2c_clients[i]); 6925e172d75SLaxman Dewangan } 6932945fbc2SGraeme Gregory return ret; 6942945fbc2SGraeme Gregory } 6952945fbc2SGraeme Gregory 696ed5c2f5fSUwe Kleine-König static void palmas_i2c_remove(struct i2c_client *i2c) 6972945fbc2SGraeme Gregory { 6982945fbc2SGraeme Gregory struct palmas *palmas = i2c_get_clientdata(i2c); 6995e172d75SLaxman Dewangan int i; 7002945fbc2SGraeme Gregory 7012945fbc2SGraeme Gregory regmap_del_irq_chip(palmas->irq, palmas->irq_data); 7022945fbc2SGraeme Gregory 7035e172d75SLaxman Dewangan for (i = 1; i < PALMAS_NUM_CLIENTS; i++) { 7045e172d75SLaxman Dewangan if (palmas->i2c_clients[i]) 7055e172d75SLaxman Dewangan i2c_unregister_device(palmas->i2c_clients[i]); 7065e172d75SLaxman Dewangan } 7075e172d75SLaxman Dewangan 7087178347eSLaxman Dewangan if (palmas == palmas_dev) { 7097178347eSLaxman Dewangan pm_power_off = NULL; 7107178347eSLaxman Dewangan palmas_dev = NULL; 7117178347eSLaxman Dewangan } 7122945fbc2SGraeme Gregory } 7132945fbc2SGraeme Gregory 7142945fbc2SGraeme Gregory static const struct i2c_device_id palmas_i2c_id[] = { 7152945fbc2SGraeme Gregory { "palmas", }, 7162945fbc2SGraeme Gregory { "twl6035", }, 7172945fbc2SGraeme Gregory { "twl6037", }, 7182945fbc2SGraeme Gregory { "tps65913", }, 71900ba81c1SAxel Lin { /* end */ } 7202945fbc2SGraeme Gregory }; 7212945fbc2SGraeme Gregory MODULE_DEVICE_TABLE(i2c, palmas_i2c_id); 7222945fbc2SGraeme Gregory 7232945fbc2SGraeme Gregory static struct i2c_driver palmas_i2c_driver = { 7242945fbc2SGraeme Gregory .driver = { 7252945fbc2SGraeme Gregory .name = "palmas", 7262945fbc2SGraeme Gregory .of_match_table = of_palmas_match_tbl, 7272945fbc2SGraeme Gregory }, 728*9816d859SUwe Kleine-König .probe = palmas_i2c_probe, 7292945fbc2SGraeme Gregory .remove = palmas_i2c_remove, 7302945fbc2SGraeme Gregory .id_table = palmas_i2c_id, 7312945fbc2SGraeme Gregory }; 7322945fbc2SGraeme Gregory 7332945fbc2SGraeme Gregory static int __init palmas_i2c_init(void) 7342945fbc2SGraeme Gregory { 7352945fbc2SGraeme Gregory return i2c_add_driver(&palmas_i2c_driver); 7362945fbc2SGraeme Gregory } 7372945fbc2SGraeme Gregory /* init early so consumer devices can complete system boot */ 7382945fbc2SGraeme Gregory subsys_initcall(palmas_i2c_init); 7392945fbc2SGraeme Gregory 7402945fbc2SGraeme Gregory static void __exit palmas_i2c_exit(void) 7412945fbc2SGraeme Gregory { 7422945fbc2SGraeme Gregory i2c_del_driver(&palmas_i2c_driver); 7432945fbc2SGraeme Gregory } 7442945fbc2SGraeme Gregory module_exit(palmas_i2c_exit); 7452945fbc2SGraeme Gregory 7462945fbc2SGraeme Gregory MODULE_AUTHOR("Graeme Gregory <gg@slimlogic.co.uk>"); 7472945fbc2SGraeme Gregory MODULE_DESCRIPTION("Palmas chip family multi-function driver"); 7482945fbc2SGraeme Gregory MODULE_LICENSE("GPL"); 749