Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  * Device access for Dialog DA9055 PMICs.
0004  *
0005  * Copyright(c) 2012 Dialog Semiconductor Ltd.
0006  *
0007  * Author: David Dajun Chen <dchen@diasemi.com>
0008  */
0009 
0010 #include <linux/module.h>
0011 #include <linux/device.h>
0012 #include <linux/input.h>
0013 #include <linux/irq.h>
0014 #include <linux/mutex.h>
0015 
0016 #include <linux/mfd/core.h>
0017 #include <linux/mfd/da9055/core.h>
0018 #include <linux/mfd/da9055/pdata.h>
0019 #include <linux/mfd/da9055/reg.h>
0020 
0021 #define DA9055_IRQ_NONKEY_MASK      0x01
0022 #define DA9055_IRQ_ALM_MASK     0x02
0023 #define DA9055_IRQ_TICK_MASK        0x04
0024 #define DA9055_IRQ_ADC_MASK     0x08
0025 #define DA9055_IRQ_BUCK_ILIM_MASK   0x08
0026 
0027 static bool da9055_register_readable(struct device *dev, unsigned int reg)
0028 {
0029     switch (reg) {
0030     case DA9055_REG_STATUS_A:
0031     case DA9055_REG_STATUS_B:
0032     case DA9055_REG_EVENT_A:
0033     case DA9055_REG_EVENT_B:
0034     case DA9055_REG_EVENT_C:
0035     case DA9055_REG_IRQ_MASK_A:
0036     case DA9055_REG_IRQ_MASK_B:
0037     case DA9055_REG_IRQ_MASK_C:
0038 
0039     case DA9055_REG_CONTROL_A:
0040     case DA9055_REG_CONTROL_B:
0041     case DA9055_REG_CONTROL_C:
0042     case DA9055_REG_CONTROL_D:
0043     case DA9055_REG_CONTROL_E:
0044 
0045     case DA9055_REG_ADC_MAN:
0046     case DA9055_REG_ADC_CONT:
0047     case DA9055_REG_VSYS_MON:
0048     case DA9055_REG_ADC_RES_L:
0049     case DA9055_REG_ADC_RES_H:
0050     case DA9055_REG_VSYS_RES:
0051     case DA9055_REG_ADCIN1_RES:
0052     case DA9055_REG_ADCIN2_RES:
0053     case DA9055_REG_ADCIN3_RES:
0054 
0055     case DA9055_REG_COUNT_S:
0056     case DA9055_REG_COUNT_MI:
0057     case DA9055_REG_COUNT_H:
0058     case DA9055_REG_COUNT_D:
0059     case DA9055_REG_COUNT_MO:
0060     case DA9055_REG_COUNT_Y:
0061     case DA9055_REG_ALARM_H:
0062     case DA9055_REG_ALARM_D:
0063     case DA9055_REG_ALARM_MI:
0064     case DA9055_REG_ALARM_MO:
0065     case DA9055_REG_ALARM_Y:
0066 
0067     case DA9055_REG_GPIO0_1:
0068     case DA9055_REG_GPIO2:
0069     case DA9055_REG_GPIO_MODE0_2:
0070 
0071     case DA9055_REG_BCORE_CONT:
0072     case DA9055_REG_BMEM_CONT:
0073     case DA9055_REG_LDO1_CONT:
0074     case DA9055_REG_LDO2_CONT:
0075     case DA9055_REG_LDO3_CONT:
0076     case DA9055_REG_LDO4_CONT:
0077     case DA9055_REG_LDO5_CONT:
0078     case DA9055_REG_LDO6_CONT:
0079     case DA9055_REG_BUCK_LIM:
0080     case DA9055_REG_BCORE_MODE:
0081     case DA9055_REG_VBCORE_A:
0082     case DA9055_REG_VBMEM_A:
0083     case DA9055_REG_VLDO1_A:
0084     case DA9055_REG_VLDO2_A:
0085     case DA9055_REG_VLDO3_A:
0086     case DA9055_REG_VLDO4_A:
0087     case DA9055_REG_VLDO5_A:
0088     case DA9055_REG_VLDO6_A:
0089     case DA9055_REG_VBCORE_B:
0090     case DA9055_REG_VBMEM_B:
0091     case DA9055_REG_VLDO1_B:
0092     case DA9055_REG_VLDO2_B:
0093     case DA9055_REG_VLDO3_B:
0094     case DA9055_REG_VLDO4_B:
0095     case DA9055_REG_VLDO5_B:
0096     case DA9055_REG_VLDO6_B:
0097         return true;
0098     default:
0099         return false;
0100     }
0101 }
0102 
0103 static bool da9055_register_writeable(struct device *dev, unsigned int reg)
0104 {
0105     switch (reg) {
0106     case DA9055_REG_STATUS_A:
0107     case DA9055_REG_STATUS_B:
0108     case DA9055_REG_EVENT_A:
0109     case DA9055_REG_EVENT_B:
0110     case DA9055_REG_EVENT_C:
0111     case DA9055_REG_IRQ_MASK_A:
0112     case DA9055_REG_IRQ_MASK_B:
0113     case DA9055_REG_IRQ_MASK_C:
0114 
0115     case DA9055_REG_CONTROL_A:
0116     case DA9055_REG_CONTROL_B:
0117     case DA9055_REG_CONTROL_C:
0118     case DA9055_REG_CONTROL_D:
0119     case DA9055_REG_CONTROL_E:
0120 
0121     case DA9055_REG_ADC_MAN:
0122     case DA9055_REG_ADC_CONT:
0123     case DA9055_REG_VSYS_MON:
0124     case DA9055_REG_ADC_RES_L:
0125     case DA9055_REG_ADC_RES_H:
0126     case DA9055_REG_VSYS_RES:
0127     case DA9055_REG_ADCIN1_RES:
0128     case DA9055_REG_ADCIN2_RES:
0129     case DA9055_REG_ADCIN3_RES:
0130 
0131     case DA9055_REG_COUNT_S:
0132     case DA9055_REG_COUNT_MI:
0133     case DA9055_REG_COUNT_H:
0134     case DA9055_REG_COUNT_D:
0135     case DA9055_REG_COUNT_MO:
0136     case DA9055_REG_COUNT_Y:
0137     case DA9055_REG_ALARM_H:
0138     case DA9055_REG_ALARM_D:
0139     case DA9055_REG_ALARM_MI:
0140     case DA9055_REG_ALARM_MO:
0141     case DA9055_REG_ALARM_Y:
0142 
0143     case DA9055_REG_GPIO0_1:
0144     case DA9055_REG_GPIO2:
0145     case DA9055_REG_GPIO_MODE0_2:
0146 
0147     case DA9055_REG_BCORE_CONT:
0148     case DA9055_REG_BMEM_CONT:
0149     case DA9055_REG_LDO1_CONT:
0150     case DA9055_REG_LDO2_CONT:
0151     case DA9055_REG_LDO3_CONT:
0152     case DA9055_REG_LDO4_CONT:
0153     case DA9055_REG_LDO5_CONT:
0154     case DA9055_REG_LDO6_CONT:
0155     case DA9055_REG_BUCK_LIM:
0156     case DA9055_REG_BCORE_MODE:
0157     case DA9055_REG_VBCORE_A:
0158     case DA9055_REG_VBMEM_A:
0159     case DA9055_REG_VLDO1_A:
0160     case DA9055_REG_VLDO2_A:
0161     case DA9055_REG_VLDO3_A:
0162     case DA9055_REG_VLDO4_A:
0163     case DA9055_REG_VLDO5_A:
0164     case DA9055_REG_VLDO6_A:
0165     case DA9055_REG_VBCORE_B:
0166     case DA9055_REG_VBMEM_B:
0167     case DA9055_REG_VLDO1_B:
0168     case DA9055_REG_VLDO2_B:
0169     case DA9055_REG_VLDO3_B:
0170     case DA9055_REG_VLDO4_B:
0171     case DA9055_REG_VLDO5_B:
0172     case DA9055_REG_VLDO6_B:
0173         return true;
0174     default:
0175         return false;
0176     }
0177 }
0178 
0179 static bool da9055_register_volatile(struct device *dev, unsigned int reg)
0180 {
0181     switch (reg) {
0182     case DA9055_REG_STATUS_A:
0183     case DA9055_REG_STATUS_B:
0184     case DA9055_REG_EVENT_A:
0185     case DA9055_REG_EVENT_B:
0186     case DA9055_REG_EVENT_C:
0187 
0188     case DA9055_REG_CONTROL_A:
0189     case DA9055_REG_CONTROL_E:
0190 
0191     case DA9055_REG_ADC_MAN:
0192     case DA9055_REG_ADC_RES_L:
0193     case DA9055_REG_ADC_RES_H:
0194     case DA9055_REG_VSYS_RES:
0195     case DA9055_REG_ADCIN1_RES:
0196     case DA9055_REG_ADCIN2_RES:
0197     case DA9055_REG_ADCIN3_RES:
0198 
0199     case DA9055_REG_COUNT_S:
0200     case DA9055_REG_COUNT_MI:
0201     case DA9055_REG_COUNT_H:
0202     case DA9055_REG_COUNT_D:
0203     case DA9055_REG_COUNT_MO:
0204     case DA9055_REG_COUNT_Y:
0205     case DA9055_REG_ALARM_MI:
0206 
0207     case DA9055_REG_BCORE_CONT:
0208     case DA9055_REG_BMEM_CONT:
0209     case DA9055_REG_LDO1_CONT:
0210     case DA9055_REG_LDO2_CONT:
0211     case DA9055_REG_LDO3_CONT:
0212     case DA9055_REG_LDO4_CONT:
0213     case DA9055_REG_LDO5_CONT:
0214     case DA9055_REG_LDO6_CONT:
0215         return true;
0216     default:
0217         return false;
0218     }
0219 }
0220 
0221 static const struct regmap_irq da9055_irqs[] = {
0222     [DA9055_IRQ_NONKEY] = {
0223         .reg_offset = 0,
0224         .mask = DA9055_IRQ_NONKEY_MASK,
0225     },
0226     [DA9055_IRQ_ALARM] = {
0227         .reg_offset = 0,
0228         .mask = DA9055_IRQ_ALM_MASK,
0229     },
0230     [DA9055_IRQ_TICK] = {
0231         .reg_offset = 0,
0232         .mask = DA9055_IRQ_TICK_MASK,
0233     },
0234     [DA9055_IRQ_HWMON] = {
0235         .reg_offset = 0,
0236         .mask = DA9055_IRQ_ADC_MASK,
0237     },
0238     [DA9055_IRQ_REGULATOR] = {
0239         .reg_offset = 1,
0240         .mask = DA9055_IRQ_BUCK_ILIM_MASK,
0241     },
0242 };
0243 
0244 const struct regmap_config da9055_regmap_config = {
0245     .reg_bits = 8,
0246     .val_bits = 8,
0247 
0248     .cache_type = REGCACHE_RBTREE,
0249 
0250     .max_register = DA9055_MAX_REGISTER_CNT,
0251     .readable_reg = da9055_register_readable,
0252     .writeable_reg = da9055_register_writeable,
0253     .volatile_reg = da9055_register_volatile,
0254 };
0255 EXPORT_SYMBOL_GPL(da9055_regmap_config);
0256 
0257 static const struct resource da9055_onkey_resource =
0258     DEFINE_RES_IRQ_NAMED(DA9055_IRQ_NONKEY, "ONKEY");
0259 
0260 static const struct resource da9055_rtc_resource[] = {
0261     DEFINE_RES_IRQ_NAMED(DA9055_IRQ_ALARM, "ALM"),
0262     DEFINE_RES_IRQ_NAMED(DA9055_IRQ_TICK, "TICK"),
0263 };
0264 
0265 static const struct resource da9055_hwmon_resource =
0266     DEFINE_RES_IRQ_NAMED(DA9055_IRQ_HWMON, "HWMON");
0267 
0268 static const struct resource da9055_ld05_6_resource =
0269     DEFINE_RES_IRQ_NAMED(DA9055_IRQ_REGULATOR, "REGULATOR");
0270 
0271 static const struct mfd_cell da9055_devs[] = {
0272     {
0273         .of_compatible = "dlg,da9055-gpio",
0274         .name = "da9055-gpio",
0275     },
0276     {
0277         .of_compatible = "dlg,da9055-regulator",
0278         .name = "da9055-regulator",
0279         .id = 1,
0280     },
0281     {
0282         .of_compatible = "dlg,da9055-regulator",
0283         .name = "da9055-regulator",
0284         .id = 2,
0285     },
0286     {
0287         .of_compatible = "dlg,da9055-regulator",
0288         .name = "da9055-regulator",
0289         .id = 3,
0290     },
0291     {
0292         .of_compatible = "dlg,da9055-regulator",
0293         .name = "da9055-regulator",
0294         .id = 4,
0295     },
0296     {
0297         .of_compatible = "dlg,da9055-regulator",
0298         .name = "da9055-regulator",
0299         .id = 5,
0300     },
0301     {
0302         .of_compatible = "dlg,da9055-regulator",
0303         .name = "da9055-regulator",
0304         .id = 6,
0305     },
0306     {
0307         .of_compatible = "dlg,da9055-regulator",
0308         .name = "da9055-regulator",
0309         .id = 7,
0310         .resources = &da9055_ld05_6_resource,
0311         .num_resources = 1,
0312     },
0313     {
0314         .of_compatible = "dlg,da9055-regulator",
0315         .name = "da9055-regulator",
0316         .resources = &da9055_ld05_6_resource,
0317         .num_resources = 1,
0318         .id = 8,
0319     },
0320     {
0321         .of_compatible = "dlg,da9055-onkey",
0322         .name = "da9055-onkey",
0323         .resources = &da9055_onkey_resource,
0324         .num_resources = 1,
0325     },
0326     {
0327         .of_compatible = "dlg,da9055-rtc",
0328         .name = "da9055-rtc",
0329         .resources = da9055_rtc_resource,
0330         .num_resources = ARRAY_SIZE(da9055_rtc_resource),
0331     },
0332     {
0333         .of_compatible = "dlg,da9055-hwmon",
0334         .name = "da9055-hwmon",
0335         .resources = &da9055_hwmon_resource,
0336         .num_resources = 1,
0337     },
0338     {
0339         .of_compatible = "dlg,da9055-watchdog",
0340         .name = "da9055-watchdog",
0341     },
0342 };
0343 
0344 static const struct regmap_irq_chip da9055_regmap_irq_chip = {
0345     .name = "da9055_irq",
0346     .status_base = DA9055_REG_EVENT_A,
0347     .mask_base = DA9055_REG_IRQ_MASK_A,
0348     .ack_base = DA9055_REG_EVENT_A,
0349     .num_regs = 3,
0350     .irqs = da9055_irqs,
0351     .num_irqs = ARRAY_SIZE(da9055_irqs),
0352 };
0353 
0354 int da9055_device_init(struct da9055 *da9055)
0355 {
0356     struct da9055_pdata *pdata = dev_get_platdata(da9055->dev);
0357     int ret;
0358     uint8_t clear_events[3] = {0xFF, 0xFF, 0xFF};
0359 
0360     if (pdata && pdata->init != NULL)
0361         pdata->init(da9055);
0362 
0363     if (!pdata || !pdata->irq_base)
0364         da9055->irq_base = -1;
0365     else
0366         da9055->irq_base = pdata->irq_base;
0367 
0368     ret = da9055_group_write(da9055, DA9055_REG_EVENT_A, 3, clear_events);
0369     if (ret < 0)
0370         return ret;
0371 
0372     ret = regmap_add_irq_chip(da9055->regmap, da9055->chip_irq,
0373                   IRQF_TRIGGER_LOW | IRQF_ONESHOT,
0374                   da9055->irq_base, &da9055_regmap_irq_chip,
0375                   &da9055->irq_data);
0376     if (ret < 0)
0377         return ret;
0378 
0379     da9055->irq_base = regmap_irq_chip_get_base(da9055->irq_data);
0380 
0381     ret = mfd_add_devices(da9055->dev, -1,
0382                   da9055_devs, ARRAY_SIZE(da9055_devs),
0383                   NULL, da9055->irq_base, NULL);
0384     if (ret)
0385         goto err;
0386 
0387     return 0;
0388 
0389 err:
0390     mfd_remove_devices(da9055->dev);
0391     return ret;
0392 }
0393 
0394 void da9055_device_exit(struct da9055 *da9055)
0395 {
0396     regmap_del_irq_chip(da9055->chip_irq, da9055->irq_data);
0397     mfd_remove_devices(da9055->dev);
0398 }
0399 
0400 MODULE_DESCRIPTION("Core support for the DA9055 PMIC");
0401 MODULE_LICENSE("GPL");
0402 MODULE_AUTHOR("David Dajun Chen <dchen@diasemi.com>");