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