root/drivers/mfd/da9063-core.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. da9063_clear_fault_log
  2. da9063_device_init

   1 // SPDX-License-Identifier: GPL-2.0+
   2 /*
   3  * Device access for Dialog DA9063 modules
   4  *
   5  * Copyright 2012 Dialog Semiconductors Ltd.
   6  * Copyright 2013 Philipp Zabel, Pengutronix
   7  *
   8  * Author: Krystian Garbaciak, Dialog Semiconductor
   9  * Author: Michal Hajduk, Dialog Semiconductor
  10  *
  11  */
  12 
  13 #include <linux/kernel.h>
  14 #include <linux/module.h>
  15 #include <linux/init.h>
  16 #include <linux/slab.h>
  17 #include <linux/device.h>
  18 #include <linux/delay.h>
  19 #include <linux/interrupt.h>
  20 #include <linux/mutex.h>
  21 #include <linux/mfd/core.h>
  22 #include <linux/regmap.h>
  23 
  24 #include <linux/mfd/da9063/core.h>
  25 #include <linux/mfd/da9063/registers.h>
  26 
  27 #include <linux/proc_fs.h>
  28 #include <linux/kthread.h>
  29 #include <linux/uaccess.h>
  30 
  31 
  32 static struct resource da9063_regulators_resources[] = {
  33         {
  34                 .name   = "LDO_LIM",
  35                 .start  = DA9063_IRQ_LDO_LIM,
  36                 .end    = DA9063_IRQ_LDO_LIM,
  37                 .flags  = IORESOURCE_IRQ,
  38         },
  39 };
  40 
  41 static struct resource da9063_rtc_resources[] = {
  42         {
  43                 .name   = "ALARM",
  44                 .start  = DA9063_IRQ_ALARM,
  45                 .end    = DA9063_IRQ_ALARM,
  46                 .flags  = IORESOURCE_IRQ,
  47         },
  48         {
  49                 .name   = "TICK",
  50                 .start  = DA9063_IRQ_TICK,
  51                 .end    = DA9063_IRQ_TICK,
  52                 .flags  = IORESOURCE_IRQ,
  53         }
  54 };
  55 
  56 static struct resource da9063_onkey_resources[] = {
  57         {
  58                 .name   = "ONKEY",
  59                 .start  = DA9063_IRQ_ONKEY,
  60                 .end    = DA9063_IRQ_ONKEY,
  61                 .flags  = IORESOURCE_IRQ,
  62         },
  63 };
  64 
  65 static struct resource da9063_hwmon_resources[] = {
  66         {
  67                 .start  = DA9063_IRQ_ADC_RDY,
  68                 .end    = DA9063_IRQ_ADC_RDY,
  69                 .flags  = IORESOURCE_IRQ,
  70         },
  71 };
  72 
  73 
  74 static const struct mfd_cell da9063_common_devs[] = {
  75         {
  76                 .name           = DA9063_DRVNAME_REGULATORS,
  77                 .num_resources  = ARRAY_SIZE(da9063_regulators_resources),
  78                 .resources      = da9063_regulators_resources,
  79         },
  80         {
  81                 .name           = DA9063_DRVNAME_LEDS,
  82         },
  83         {
  84                 .name           = DA9063_DRVNAME_WATCHDOG,
  85                 .of_compatible  = "dlg,da9063-watchdog",
  86         },
  87         {
  88                 .name           = DA9063_DRVNAME_HWMON,
  89                 .num_resources  = ARRAY_SIZE(da9063_hwmon_resources),
  90                 .resources      = da9063_hwmon_resources,
  91         },
  92         {
  93                 .name           = DA9063_DRVNAME_ONKEY,
  94                 .num_resources  = ARRAY_SIZE(da9063_onkey_resources),
  95                 .resources      = da9063_onkey_resources,
  96                 .of_compatible = "dlg,da9063-onkey",
  97         },
  98         {
  99                 .name           = DA9063_DRVNAME_VIBRATION,
 100         },
 101 };
 102 
 103 /* Only present on DA9063 , not on DA9063L */
 104 static const struct mfd_cell da9063_devs[] = {
 105         {
 106                 .name           = DA9063_DRVNAME_RTC,
 107                 .num_resources  = ARRAY_SIZE(da9063_rtc_resources),
 108                 .resources      = da9063_rtc_resources,
 109                 .of_compatible  = "dlg,da9063-rtc",
 110         },
 111 };
 112 
 113 static int da9063_clear_fault_log(struct da9063 *da9063)
 114 {
 115         int ret = 0;
 116         int fault_log = 0;
 117 
 118         ret = regmap_read(da9063->regmap, DA9063_REG_FAULT_LOG, &fault_log);
 119         if (ret < 0) {
 120                 dev_err(da9063->dev, "Cannot read FAULT_LOG.\n");
 121                 return -EIO;
 122         }
 123 
 124         if (fault_log) {
 125                 if (fault_log & DA9063_TWD_ERROR)
 126                         dev_dbg(da9063->dev,
 127                                 "Fault log entry detected: DA9063_TWD_ERROR\n");
 128                 if (fault_log & DA9063_POR)
 129                         dev_dbg(da9063->dev,
 130                                 "Fault log entry detected: DA9063_POR\n");
 131                 if (fault_log & DA9063_VDD_FAULT)
 132                         dev_dbg(da9063->dev,
 133                                 "Fault log entry detected: DA9063_VDD_FAULT\n");
 134                 if (fault_log & DA9063_VDD_START)
 135                         dev_dbg(da9063->dev,
 136                                 "Fault log entry detected: DA9063_VDD_START\n");
 137                 if (fault_log & DA9063_TEMP_CRIT)
 138                         dev_dbg(da9063->dev,
 139                                 "Fault log entry detected: DA9063_TEMP_CRIT\n");
 140                 if (fault_log & DA9063_KEY_RESET)
 141                         dev_dbg(da9063->dev,
 142                                 "Fault log entry detected: DA9063_KEY_RESET\n");
 143                 if (fault_log & DA9063_NSHUTDOWN)
 144                         dev_dbg(da9063->dev,
 145                                 "Fault log entry detected: DA9063_NSHUTDOWN\n");
 146                 if (fault_log & DA9063_WAIT_SHUT)
 147                         dev_dbg(da9063->dev,
 148                                 "Fault log entry detected: DA9063_WAIT_SHUT\n");
 149         }
 150 
 151         ret = regmap_write(da9063->regmap,
 152                            DA9063_REG_FAULT_LOG,
 153                            fault_log);
 154         if (ret < 0)
 155                 dev_err(da9063->dev,
 156                         "Cannot reset FAULT_LOG values %d\n", ret);
 157 
 158         return ret;
 159 }
 160 
 161 int da9063_device_init(struct da9063 *da9063, unsigned int irq)
 162 {
 163         int model, variant_id, variant_code;
 164         int ret;
 165 
 166         ret = da9063_clear_fault_log(da9063);
 167         if (ret < 0)
 168                 dev_err(da9063->dev, "Cannot clear fault log\n");
 169 
 170         da9063->flags = 0;
 171         da9063->irq_base = -1;
 172         da9063->chip_irq = irq;
 173 
 174         ret = regmap_read(da9063->regmap, DA9063_REG_CHIP_ID, &model);
 175         if (ret < 0) {
 176                 dev_err(da9063->dev, "Cannot read chip model id.\n");
 177                 return -EIO;
 178         }
 179         if (model != PMIC_CHIP_ID_DA9063) {
 180                 dev_err(da9063->dev, "Invalid chip model id: 0x%02x\n", model);
 181                 return -ENODEV;
 182         }
 183 
 184         ret = regmap_read(da9063->regmap, DA9063_REG_CHIP_VARIANT, &variant_id);
 185         if (ret < 0) {
 186                 dev_err(da9063->dev, "Cannot read chip variant id.\n");
 187                 return -EIO;
 188         }
 189 
 190         variant_code = variant_id >> DA9063_CHIP_VARIANT_SHIFT;
 191 
 192         dev_info(da9063->dev,
 193                  "Device detected (chip-ID: 0x%02X, var-ID: 0x%02X)\n",
 194                  model, variant_id);
 195 
 196         if (variant_code < PMIC_DA9063_BB && variant_code != PMIC_DA9063_AD) {
 197                 dev_err(da9063->dev,
 198                         "Cannot support variant code: 0x%02X\n", variant_code);
 199                 return -ENODEV;
 200         }
 201 
 202         da9063->variant_code = variant_code;
 203 
 204         ret = da9063_irq_init(da9063);
 205         if (ret) {
 206                 dev_err(da9063->dev, "Cannot initialize interrupts.\n");
 207                 return ret;
 208         }
 209 
 210         da9063->irq_base = regmap_irq_chip_get_base(da9063->regmap_irq);
 211 
 212         ret = devm_mfd_add_devices(da9063->dev, PLATFORM_DEVID_NONE,
 213                                    da9063_common_devs,
 214                                    ARRAY_SIZE(da9063_common_devs),
 215                                    NULL, da9063->irq_base, NULL);
 216         if (ret) {
 217                 dev_err(da9063->dev, "Failed to add child devices\n");
 218                 return ret;
 219         }
 220 
 221         if (da9063->type == PMIC_TYPE_DA9063) {
 222                 ret = devm_mfd_add_devices(da9063->dev, PLATFORM_DEVID_NONE,
 223                                            da9063_devs, ARRAY_SIZE(da9063_devs),
 224                                            NULL, da9063->irq_base, NULL);
 225                 if (ret) {
 226                         dev_err(da9063->dev, "Failed to add child devices\n");
 227                         return ret;
 228                 }
 229         }
 230 
 231         return ret;
 232 }
 233 
 234 MODULE_DESCRIPTION("PMIC driver for Dialog DA9063");
 235 MODULE_AUTHOR("Krystian Garbaciak");
 236 MODULE_AUTHOR("Michal Hajduk");
 237 MODULE_LICENSE("GPL");

/* [<][>][^][v][top][bottom][index][help] */