1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Device access for Dollar Cove TI PMIC 4 * 5 * Copyright (c) 2014, Intel Corporation. 6 * Author: Ramakrishna Pallala <ramakrishna.pallala@intel.com> 7 * 8 * Cleanup and forward-ported 9 * Copyright (c) 2017 Takashi Iwai <tiwai@suse.de> 10 */ 11 12 #include <linux/acpi.h> 13 #include <linux/interrupt.h> 14 #include <linux/i2c.h> 15 #include <linux/mfd/core.h> 16 #include <linux/mfd/intel_soc_pmic.h> 17 #include <linux/module.h> 18 #include <linux/regmap.h> 19 20 #define CHTDC_TI_IRQLVL1 0x01 21 #define CHTDC_TI_MASK_IRQLVL1 0x02 22 23 /* Level 1 IRQs */ 24 enum { 25 CHTDC_TI_PWRBTN = 0, /* power button */ 26 CHTDC_TI_DIETMPWARN, /* thermal */ 27 CHTDC_TI_ADCCMPL, /* ADC */ 28 /* No IRQ 3 */ 29 CHTDC_TI_VBATLOW = 4, /* battery */ 30 CHTDC_TI_VBUSDET, /* power source */ 31 /* No IRQ 6 */ 32 CHTDC_TI_CCEOCAL = 7, /* battery */ 33 }; 34 35 static const struct resource power_button_resources[] = { 36 DEFINE_RES_IRQ(CHTDC_TI_PWRBTN), 37 }; 38 39 static const struct resource thermal_resources[] = { 40 DEFINE_RES_IRQ(CHTDC_TI_DIETMPWARN), 41 }; 42 43 static const struct resource adc_resources[] = { 44 DEFINE_RES_IRQ(CHTDC_TI_ADCCMPL), 45 }; 46 47 static const struct resource pwrsrc_resources[] = { 48 DEFINE_RES_IRQ(CHTDC_TI_VBUSDET), 49 }; 50 51 static const struct resource battery_resources[] = { 52 DEFINE_RES_IRQ(CHTDC_TI_VBATLOW), 53 DEFINE_RES_IRQ(CHTDC_TI_CCEOCAL), 54 }; 55 56 static struct mfd_cell chtdc_ti_dev[] = { 57 { 58 .name = "chtdc_ti_pwrbtn", 59 .num_resources = ARRAY_SIZE(power_button_resources), 60 .resources = power_button_resources, 61 }, { 62 .name = "chtdc_ti_adc", 63 .num_resources = ARRAY_SIZE(adc_resources), 64 .resources = adc_resources, 65 }, { 66 .name = "chtdc_ti_thermal", 67 .num_resources = ARRAY_SIZE(thermal_resources), 68 .resources = thermal_resources, 69 }, { 70 .name = "chtdc_ti_pwrsrc", 71 .num_resources = ARRAY_SIZE(pwrsrc_resources), 72 .resources = pwrsrc_resources, 73 }, { 74 .name = "chtdc_ti_battery", 75 .num_resources = ARRAY_SIZE(battery_resources), 76 .resources = battery_resources, 77 }, 78 { .name = "chtdc_ti_region", }, 79 }; 80 81 static const struct regmap_config chtdc_ti_regmap_config = { 82 .reg_bits = 8, 83 .val_bits = 8, 84 .max_register = 0xff, 85 }; 86 87 static const struct regmap_irq chtdc_ti_irqs[] = { 88 REGMAP_IRQ_REG(CHTDC_TI_PWRBTN, 0, BIT(CHTDC_TI_PWRBTN)), 89 REGMAP_IRQ_REG(CHTDC_TI_DIETMPWARN, 0, BIT(CHTDC_TI_DIETMPWARN)), 90 REGMAP_IRQ_REG(CHTDC_TI_ADCCMPL, 0, BIT(CHTDC_TI_ADCCMPL)), 91 REGMAP_IRQ_REG(CHTDC_TI_VBATLOW, 0, BIT(CHTDC_TI_VBATLOW)), 92 REGMAP_IRQ_REG(CHTDC_TI_VBUSDET, 0, BIT(CHTDC_TI_VBUSDET)), 93 REGMAP_IRQ_REG(CHTDC_TI_CCEOCAL, 0, BIT(CHTDC_TI_CCEOCAL)), 94 }; 95 96 static const struct regmap_irq_chip chtdc_ti_irq_chip = { 97 .name = KBUILD_MODNAME, 98 .irqs = chtdc_ti_irqs, 99 .num_irqs = ARRAY_SIZE(chtdc_ti_irqs), 100 .num_regs = 1, 101 .status_base = CHTDC_TI_IRQLVL1, 102 .mask_base = CHTDC_TI_MASK_IRQLVL1, 103 .ack_base = CHTDC_TI_IRQLVL1, 104 }; 105 106 static int chtdc_ti_probe(struct i2c_client *i2c) 107 { 108 struct device *dev = &i2c->dev; 109 struct intel_soc_pmic *pmic; 110 int ret; 111 112 pmic = devm_kzalloc(dev, sizeof(*pmic), GFP_KERNEL); 113 if (!pmic) 114 return -ENOMEM; 115 116 i2c_set_clientdata(i2c, pmic); 117 118 pmic->regmap = devm_regmap_init_i2c(i2c, &chtdc_ti_regmap_config); 119 if (IS_ERR(pmic->regmap)) 120 return PTR_ERR(pmic->regmap); 121 pmic->irq = i2c->irq; 122 123 ret = devm_regmap_add_irq_chip(dev, pmic->regmap, pmic->irq, 124 IRQF_ONESHOT, 0, 125 &chtdc_ti_irq_chip, 126 &pmic->irq_chip_data); 127 if (ret) 128 return ret; 129 130 return devm_mfd_add_devices(dev, PLATFORM_DEVID_NONE, chtdc_ti_dev, 131 ARRAY_SIZE(chtdc_ti_dev), NULL, 0, 132 regmap_irq_get_domain(pmic->irq_chip_data)); 133 } 134 135 static void chtdc_ti_shutdown(struct i2c_client *i2c) 136 { 137 struct intel_soc_pmic *pmic = i2c_get_clientdata(i2c); 138 139 disable_irq(pmic->irq); 140 } 141 142 static int chtdc_ti_suspend(struct device *dev) 143 { 144 struct intel_soc_pmic *pmic = dev_get_drvdata(dev); 145 146 disable_irq(pmic->irq); 147 148 return 0; 149 } 150 151 static int chtdc_ti_resume(struct device *dev) 152 { 153 struct intel_soc_pmic *pmic = dev_get_drvdata(dev); 154 155 enable_irq(pmic->irq); 156 157 return 0; 158 } 159 160 static DEFINE_SIMPLE_DEV_PM_OPS(chtdc_ti_pm_ops, chtdc_ti_suspend, chtdc_ti_resume); 161 162 static const struct acpi_device_id chtdc_ti_acpi_ids[] = { 163 { "INT33F5" }, 164 { }, 165 }; 166 MODULE_DEVICE_TABLE(acpi, chtdc_ti_acpi_ids); 167 168 static struct i2c_driver chtdc_ti_i2c_driver = { 169 .driver = { 170 .name = "intel_soc_pmic_chtdc_ti", 171 .pm = pm_sleep_ptr(&chtdc_ti_pm_ops), 172 .acpi_match_table = chtdc_ti_acpi_ids, 173 }, 174 .probe = chtdc_ti_probe, 175 .shutdown = chtdc_ti_shutdown, 176 }; 177 module_i2c_driver(chtdc_ti_i2c_driver); 178 179 MODULE_DESCRIPTION("I2C driver for Intel SoC Dollar Cove TI PMIC"); 180 MODULE_LICENSE("GPL v2"); 181