Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * Device access for Dollar Cove TI PMIC
0004  *
0005  * Copyright (c) 2014, Intel Corporation.
0006  *   Author: Ramakrishna Pallala <ramakrishna.pallala@intel.com>
0007  *
0008  * Cleanup and forward-ported
0009  *   Copyright (c) 2017 Takashi Iwai <tiwai@suse.de>
0010  */
0011 
0012 #include <linux/acpi.h>
0013 #include <linux/interrupt.h>
0014 #include <linux/i2c.h>
0015 #include <linux/mfd/core.h>
0016 #include <linux/mfd/intel_soc_pmic.h>
0017 #include <linux/module.h>
0018 #include <linux/regmap.h>
0019 
0020 #define CHTDC_TI_IRQLVL1    0x01
0021 #define CHTDC_TI_MASK_IRQLVL1   0x02
0022 
0023 /* Level 1 IRQs */
0024 enum {
0025     CHTDC_TI_PWRBTN = 0,    /* power button */
0026     CHTDC_TI_DIETMPWARN,    /* thermal */
0027     CHTDC_TI_ADCCMPL,   /* ADC */
0028     /* No IRQ 3 */
0029     CHTDC_TI_VBATLOW = 4,   /* battery */
0030     CHTDC_TI_VBUSDET,   /* power source */
0031     /* No IRQ 6 */
0032     CHTDC_TI_CCEOCAL = 7,   /* battery */
0033 };
0034 
0035 static const struct resource power_button_resources[] = {
0036     DEFINE_RES_IRQ(CHTDC_TI_PWRBTN),
0037 };
0038 
0039 static const struct resource thermal_resources[] = {
0040     DEFINE_RES_IRQ(CHTDC_TI_DIETMPWARN),
0041 };
0042 
0043 static const struct resource adc_resources[] = {
0044     DEFINE_RES_IRQ(CHTDC_TI_ADCCMPL),
0045 };
0046 
0047 static const struct resource pwrsrc_resources[] = {
0048     DEFINE_RES_IRQ(CHTDC_TI_VBUSDET),
0049 };
0050 
0051 static const struct resource battery_resources[] = {
0052     DEFINE_RES_IRQ(CHTDC_TI_VBATLOW),
0053     DEFINE_RES_IRQ(CHTDC_TI_CCEOCAL),
0054 };
0055 
0056 static struct mfd_cell chtdc_ti_dev[] = {
0057     {
0058         .name = "chtdc_ti_pwrbtn",
0059         .num_resources = ARRAY_SIZE(power_button_resources),
0060         .resources = power_button_resources,
0061     }, {
0062         .name = "chtdc_ti_adc",
0063         .num_resources = ARRAY_SIZE(adc_resources),
0064         .resources = adc_resources,
0065     }, {
0066         .name = "chtdc_ti_thermal",
0067         .num_resources = ARRAY_SIZE(thermal_resources),
0068         .resources = thermal_resources,
0069     }, {
0070         .name = "chtdc_ti_pwrsrc",
0071         .num_resources = ARRAY_SIZE(pwrsrc_resources),
0072         .resources = pwrsrc_resources,
0073     }, {
0074         .name = "chtdc_ti_battery",
0075         .num_resources = ARRAY_SIZE(battery_resources),
0076         .resources = battery_resources,
0077     },
0078     {   .name = "chtdc_ti_region", },
0079 };
0080 
0081 static const struct regmap_config chtdc_ti_regmap_config = {
0082     .reg_bits = 8,
0083     .val_bits = 8,
0084     .max_register = 128,
0085     .cache_type = REGCACHE_NONE,
0086 };
0087 
0088 static const struct regmap_irq chtdc_ti_irqs[] = {
0089     REGMAP_IRQ_REG(CHTDC_TI_PWRBTN, 0, BIT(CHTDC_TI_PWRBTN)),
0090     REGMAP_IRQ_REG(CHTDC_TI_DIETMPWARN, 0, BIT(CHTDC_TI_DIETMPWARN)),
0091     REGMAP_IRQ_REG(CHTDC_TI_ADCCMPL, 0, BIT(CHTDC_TI_ADCCMPL)),
0092     REGMAP_IRQ_REG(CHTDC_TI_VBATLOW, 0, BIT(CHTDC_TI_VBATLOW)),
0093     REGMAP_IRQ_REG(CHTDC_TI_VBUSDET, 0, BIT(CHTDC_TI_VBUSDET)),
0094     REGMAP_IRQ_REG(CHTDC_TI_CCEOCAL, 0, BIT(CHTDC_TI_CCEOCAL)),
0095 };
0096 
0097 static const struct regmap_irq_chip chtdc_ti_irq_chip = {
0098     .name = KBUILD_MODNAME,
0099     .irqs = chtdc_ti_irqs,
0100     .num_irqs = ARRAY_SIZE(chtdc_ti_irqs),
0101     .num_regs = 1,
0102     .status_base = CHTDC_TI_IRQLVL1,
0103     .mask_base = CHTDC_TI_MASK_IRQLVL1,
0104     .ack_base = CHTDC_TI_IRQLVL1,
0105 };
0106 
0107 static int chtdc_ti_probe(struct i2c_client *i2c)
0108 {
0109     struct device *dev = &i2c->dev;
0110     struct intel_soc_pmic *pmic;
0111     int ret;
0112 
0113     pmic = devm_kzalloc(dev, sizeof(*pmic), GFP_KERNEL);
0114     if (!pmic)
0115         return -ENOMEM;
0116 
0117     i2c_set_clientdata(i2c, pmic);
0118 
0119     pmic->regmap = devm_regmap_init_i2c(i2c, &chtdc_ti_regmap_config);
0120     if (IS_ERR(pmic->regmap))
0121         return PTR_ERR(pmic->regmap);
0122     pmic->irq = i2c->irq;
0123 
0124     ret = devm_regmap_add_irq_chip(dev, pmic->regmap, pmic->irq,
0125                        IRQF_ONESHOT, 0,
0126                        &chtdc_ti_irq_chip,
0127                        &pmic->irq_chip_data);
0128     if (ret)
0129         return ret;
0130 
0131     return devm_mfd_add_devices(dev, PLATFORM_DEVID_NONE, chtdc_ti_dev,
0132                     ARRAY_SIZE(chtdc_ti_dev), NULL, 0,
0133                     regmap_irq_get_domain(pmic->irq_chip_data));
0134 }
0135 
0136 static void chtdc_ti_shutdown(struct i2c_client *i2c)
0137 {
0138     struct intel_soc_pmic *pmic = i2c_get_clientdata(i2c);
0139 
0140     disable_irq(pmic->irq);
0141 }
0142 
0143 static int __maybe_unused chtdc_ti_suspend(struct device *dev)
0144 {
0145     struct intel_soc_pmic *pmic = dev_get_drvdata(dev);
0146 
0147     disable_irq(pmic->irq);
0148 
0149     return 0;
0150 }
0151 
0152 static int __maybe_unused chtdc_ti_resume(struct device *dev)
0153 {
0154     struct intel_soc_pmic *pmic = dev_get_drvdata(dev);
0155 
0156     enable_irq(pmic->irq);
0157 
0158     return 0;
0159 }
0160 
0161 static SIMPLE_DEV_PM_OPS(chtdc_ti_pm_ops, chtdc_ti_suspend, chtdc_ti_resume);
0162 
0163 static const struct acpi_device_id chtdc_ti_acpi_ids[] = {
0164     { "INT33F5" },
0165     { },
0166 };
0167 MODULE_DEVICE_TABLE(acpi, chtdc_ti_acpi_ids);
0168 
0169 static struct i2c_driver chtdc_ti_i2c_driver = {
0170     .driver = {
0171         .name = "intel_soc_pmic_chtdc_ti",
0172         .pm = &chtdc_ti_pm_ops,
0173         .acpi_match_table = chtdc_ti_acpi_ids,
0174     },
0175     .probe_new = chtdc_ti_probe,
0176     .shutdown = chtdc_ti_shutdown,
0177 };
0178 module_i2c_driver(chtdc_ti_i2c_driver);
0179 
0180 MODULE_DESCRIPTION("I2C driver for Intel SoC Dollar Cove TI PMIC");
0181 MODULE_LICENSE("GPL v2");