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 /* The hardware does not support reading multiple registers at once */ 86 .use_single_read = true, 87 }; 88 89 static const struct regmap_irq chtdc_ti_irqs[] = { 90 REGMAP_IRQ_REG(CHTDC_TI_PWRBTN, 0, BIT(CHTDC_TI_PWRBTN)), 91 REGMAP_IRQ_REG(CHTDC_TI_DIETMPWARN, 0, BIT(CHTDC_TI_DIETMPWARN)), 92 REGMAP_IRQ_REG(CHTDC_TI_ADCCMPL, 0, BIT(CHTDC_TI_ADCCMPL)), 93 REGMAP_IRQ_REG(CHTDC_TI_VBATLOW, 0, BIT(CHTDC_TI_VBATLOW)), 94 REGMAP_IRQ_REG(CHTDC_TI_VBUSDET, 0, BIT(CHTDC_TI_VBUSDET)), 95 REGMAP_IRQ_REG(CHTDC_TI_CCEOCAL, 0, BIT(CHTDC_TI_CCEOCAL)), 96 }; 97 98 static const struct regmap_irq_chip chtdc_ti_irq_chip = { 99 .name = KBUILD_MODNAME, 100 .irqs = chtdc_ti_irqs, 101 .num_irqs = ARRAY_SIZE(chtdc_ti_irqs), 102 .num_regs = 1, 103 .status_base = CHTDC_TI_IRQLVL1, 104 .mask_base = CHTDC_TI_MASK_IRQLVL1, 105 .ack_base = CHTDC_TI_IRQLVL1, 106 }; 107 108 static int chtdc_ti_probe(struct i2c_client *i2c) 109 { 110 struct device *dev = &i2c->dev; 111 struct intel_soc_pmic *pmic; 112 int ret; 113 114 pmic = devm_kzalloc(dev, sizeof(*pmic), GFP_KERNEL); 115 if (!pmic) 116 return -ENOMEM; 117 118 i2c_set_clientdata(i2c, pmic); 119 120 pmic->regmap = devm_regmap_init_i2c(i2c, &chtdc_ti_regmap_config); 121 if (IS_ERR(pmic->regmap)) 122 return PTR_ERR(pmic->regmap); 123 pmic->irq = i2c->irq; 124 125 ret = devm_regmap_add_irq_chip(dev, pmic->regmap, pmic->irq, 126 IRQF_ONESHOT, 0, 127 &chtdc_ti_irq_chip, 128 &pmic->irq_chip_data); 129 if (ret) 130 return ret; 131 132 return devm_mfd_add_devices(dev, PLATFORM_DEVID_NONE, chtdc_ti_dev, 133 ARRAY_SIZE(chtdc_ti_dev), NULL, 0, 134 regmap_irq_get_domain(pmic->irq_chip_data)); 135 } 136 137 static void chtdc_ti_shutdown(struct i2c_client *i2c) 138 { 139 struct intel_soc_pmic *pmic = i2c_get_clientdata(i2c); 140 141 disable_irq(pmic->irq); 142 } 143 144 static int chtdc_ti_suspend(struct device *dev) 145 { 146 struct intel_soc_pmic *pmic = dev_get_drvdata(dev); 147 148 disable_irq(pmic->irq); 149 150 return 0; 151 } 152 153 static int chtdc_ti_resume(struct device *dev) 154 { 155 struct intel_soc_pmic *pmic = dev_get_drvdata(dev); 156 157 enable_irq(pmic->irq); 158 159 return 0; 160 } 161 162 static DEFINE_SIMPLE_DEV_PM_OPS(chtdc_ti_pm_ops, chtdc_ti_suspend, chtdc_ti_resume); 163 164 static const struct acpi_device_id chtdc_ti_acpi_ids[] = { 165 { "INT33F5" }, 166 { }, 167 }; 168 MODULE_DEVICE_TABLE(acpi, chtdc_ti_acpi_ids); 169 170 static struct i2c_driver chtdc_ti_i2c_driver = { 171 .driver = { 172 .name = "intel_soc_pmic_chtdc_ti", 173 .pm = pm_sleep_ptr(&chtdc_ti_pm_ops), 174 .acpi_match_table = chtdc_ti_acpi_ids, 175 }, 176 .probe = chtdc_ti_probe, 177 .shutdown = chtdc_ti_shutdown, 178 }; 179 module_i2c_driver(chtdc_ti_i2c_driver); 180 181 MODULE_DESCRIPTION("I2C driver for Intel SoC Dollar Cove TI PMIC"); 182 MODULE_LICENSE("GPL v2"); 183