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