root/drivers/mfd/da9150-core.c

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

DEFINITIONS

This source file includes following definitions.
  1. da9150_i2c_read_device
  2. da9150_i2c_write_device
  3. da9150_volatile_reg
  4. da9150_read_qif
  5. da9150_write_qif
  6. da9150_reg_read
  7. da9150_reg_write
  8. da9150_set_bits
  9. da9150_bulk_read
  10. da9150_bulk_write
  11. da9150_probe
  12. da9150_remove
  13. da9150_shutdown

   1 // SPDX-License-Identifier: GPL-2.0-or-later
   2 /*
   3  * DA9150 Core MFD Driver
   4  *
   5  * Copyright (c) 2014 Dialog Semiconductor
   6  *
   7  * Author: Adam Thomson <Adam.Thomson.Opensource@diasemi.com>
   8  */
   9 
  10 #include <linux/kernel.h>
  11 #include <linux/module.h>
  12 #include <linux/platform_device.h>
  13 #include <linux/i2c.h>
  14 #include <linux/regmap.h>
  15 #include <linux/slab.h>
  16 #include <linux/irq.h>
  17 #include <linux/interrupt.h>
  18 #include <linux/mfd/core.h>
  19 #include <linux/mfd/da9150/core.h>
  20 #include <linux/mfd/da9150/registers.h>
  21 
  22 /* Raw device access, used for QIF */
  23 static int da9150_i2c_read_device(struct i2c_client *client, u8 addr, int count,
  24                                   u8 *buf)
  25 {
  26         struct i2c_msg xfer;
  27         int ret;
  28 
  29         /*
  30          * Read is split into two transfers as device expects STOP/START rather
  31          * than repeated start to carry out this kind of access.
  32          */
  33 
  34         /* Write address */
  35         xfer.addr = client->addr;
  36         xfer.flags = 0;
  37         xfer.len = 1;
  38         xfer.buf = &addr;
  39 
  40         ret = i2c_transfer(client->adapter, &xfer, 1);
  41         if (ret != 1) {
  42                 if (ret < 0)
  43                         return ret;
  44                 else
  45                         return -EIO;
  46         }
  47 
  48         /* Read data */
  49         xfer.addr = client->addr;
  50         xfer.flags = I2C_M_RD;
  51         xfer.len = count;
  52         xfer.buf = buf;
  53 
  54         ret = i2c_transfer(client->adapter, &xfer, 1);
  55         if (ret == 1)
  56                 return 0;
  57         else if (ret < 0)
  58                 return ret;
  59         else
  60                 return -EIO;
  61 }
  62 
  63 static int da9150_i2c_write_device(struct i2c_client *client, u8 addr,
  64                                    int count, const u8 *buf)
  65 {
  66         struct i2c_msg xfer;
  67         u8 *reg_data;
  68         int ret;
  69 
  70         reg_data = kzalloc(1 + count, GFP_KERNEL);
  71         if (!reg_data)
  72                 return -ENOMEM;
  73 
  74         reg_data[0] = addr;
  75         memcpy(&reg_data[1], buf, count);
  76 
  77         /* Write address & data */
  78         xfer.addr = client->addr;
  79         xfer.flags = 0;
  80         xfer.len = 1 + count;
  81         xfer.buf = reg_data;
  82 
  83         ret = i2c_transfer(client->adapter, &xfer, 1);
  84         kfree(reg_data);
  85         if (ret == 1)
  86                 return 0;
  87         else if (ret < 0)
  88                 return ret;
  89         else
  90                 return -EIO;
  91 }
  92 
  93 static bool da9150_volatile_reg(struct device *dev, unsigned int reg)
  94 {
  95         switch (reg) {
  96         case DA9150_PAGE_CON:
  97         case DA9150_STATUS_A:
  98         case DA9150_STATUS_B:
  99         case DA9150_STATUS_C:
 100         case DA9150_STATUS_D:
 101         case DA9150_STATUS_E:
 102         case DA9150_STATUS_F:
 103         case DA9150_STATUS_G:
 104         case DA9150_STATUS_H:
 105         case DA9150_STATUS_I:
 106         case DA9150_STATUS_J:
 107         case DA9150_STATUS_K:
 108         case DA9150_STATUS_L:
 109         case DA9150_STATUS_N:
 110         case DA9150_FAULT_LOG_A:
 111         case DA9150_FAULT_LOG_B:
 112         case DA9150_EVENT_E:
 113         case DA9150_EVENT_F:
 114         case DA9150_EVENT_G:
 115         case DA9150_EVENT_H:
 116         case DA9150_CONTROL_B:
 117         case DA9150_CONTROL_C:
 118         case DA9150_GPADC_MAN:
 119         case DA9150_GPADC_RES_A:
 120         case DA9150_GPADC_RES_B:
 121         case DA9150_ADETVB_CFG_C:
 122         case DA9150_ADETD_STAT:
 123         case DA9150_ADET_CMPSTAT:
 124         case DA9150_ADET_CTRL_A:
 125         case DA9150_PPR_TCTR_B:
 126         case DA9150_COREBTLD_STAT_A:
 127         case DA9150_CORE_DATA_A:
 128         case DA9150_CORE_DATA_B:
 129         case DA9150_CORE_DATA_C:
 130         case DA9150_CORE_DATA_D:
 131         case DA9150_CORE2WIRE_STAT_A:
 132         case DA9150_FW_CTRL_C:
 133         case DA9150_FG_CTRL_B:
 134         case DA9150_FW_CTRL_B:
 135         case DA9150_GPADC_CMAN:
 136         case DA9150_GPADC_CRES_A:
 137         case DA9150_GPADC_CRES_B:
 138         case DA9150_CC_ICHG_RES_A:
 139         case DA9150_CC_ICHG_RES_B:
 140         case DA9150_CC_IAVG_RES_A:
 141         case DA9150_CC_IAVG_RES_B:
 142         case DA9150_TAUX_CTRL_A:
 143         case DA9150_TAUX_VALUE_H:
 144         case DA9150_TAUX_VALUE_L:
 145         case DA9150_TBAT_RES_A:
 146         case DA9150_TBAT_RES_B:
 147                 return true;
 148         default:
 149                 return false;
 150         }
 151 }
 152 
 153 static const struct regmap_range_cfg da9150_range_cfg[] = {
 154         {
 155                 .range_min = DA9150_PAGE_CON,
 156                 .range_max = DA9150_TBAT_RES_B,
 157                 .selector_reg = DA9150_PAGE_CON,
 158                 .selector_mask = DA9150_I2C_PAGE_MASK,
 159                 .selector_shift = DA9150_I2C_PAGE_SHIFT,
 160                 .window_start = 0,
 161                 .window_len = 256,
 162         },
 163 };
 164 
 165 static const struct regmap_config da9150_regmap_config = {
 166         .reg_bits = 8,
 167         .val_bits = 8,
 168         .ranges = da9150_range_cfg,
 169         .num_ranges = ARRAY_SIZE(da9150_range_cfg),
 170         .max_register = DA9150_TBAT_RES_B,
 171 
 172         .cache_type = REGCACHE_RBTREE,
 173 
 174         .volatile_reg = da9150_volatile_reg,
 175 };
 176 
 177 void da9150_read_qif(struct da9150 *da9150, u8 addr, int count, u8 *buf)
 178 {
 179         int ret;
 180 
 181         ret = da9150_i2c_read_device(da9150->core_qif, addr, count, buf);
 182         if (ret < 0)
 183                 dev_err(da9150->dev, "Failed to read from QIF 0x%x: %d\n",
 184                         addr, ret);
 185 }
 186 EXPORT_SYMBOL_GPL(da9150_read_qif);
 187 
 188 void da9150_write_qif(struct da9150 *da9150, u8 addr, int count, const u8 *buf)
 189 {
 190         int ret;
 191 
 192         ret = da9150_i2c_write_device(da9150->core_qif, addr, count, buf);
 193         if (ret < 0)
 194                 dev_err(da9150->dev, "Failed to write to QIF 0x%x: %d\n",
 195                         addr, ret);
 196 }
 197 EXPORT_SYMBOL_GPL(da9150_write_qif);
 198 
 199 u8 da9150_reg_read(struct da9150 *da9150, u16 reg)
 200 {
 201         int val, ret;
 202 
 203         ret = regmap_read(da9150->regmap, reg, &val);
 204         if (ret)
 205                 dev_err(da9150->dev, "Failed to read from reg 0x%x: %d\n",
 206                         reg, ret);
 207 
 208         return (u8) val;
 209 }
 210 EXPORT_SYMBOL_GPL(da9150_reg_read);
 211 
 212 void da9150_reg_write(struct da9150 *da9150, u16 reg, u8 val)
 213 {
 214         int ret;
 215 
 216         ret = regmap_write(da9150->regmap, reg, val);
 217         if (ret)
 218                 dev_err(da9150->dev, "Failed to write to reg 0x%x: %d\n",
 219                         reg, ret);
 220 }
 221 EXPORT_SYMBOL_GPL(da9150_reg_write);
 222 
 223 void da9150_set_bits(struct da9150 *da9150, u16 reg, u8 mask, u8 val)
 224 {
 225         int ret;
 226 
 227         ret = regmap_update_bits(da9150->regmap, reg, mask, val);
 228         if (ret)
 229                 dev_err(da9150->dev, "Failed to set bits in reg 0x%x: %d\n",
 230                         reg, ret);
 231 }
 232 EXPORT_SYMBOL_GPL(da9150_set_bits);
 233 
 234 void da9150_bulk_read(struct da9150 *da9150, u16 reg, int count, u8 *buf)
 235 {
 236         int ret;
 237 
 238         ret = regmap_bulk_read(da9150->regmap, reg, buf, count);
 239         if (ret)
 240                 dev_err(da9150->dev, "Failed to bulk read from reg 0x%x: %d\n",
 241                         reg, ret);
 242 }
 243 EXPORT_SYMBOL_GPL(da9150_bulk_read);
 244 
 245 void da9150_bulk_write(struct da9150 *da9150, u16 reg, int count, const u8 *buf)
 246 {
 247         int ret;
 248 
 249         ret = regmap_raw_write(da9150->regmap, reg, buf, count);
 250         if (ret)
 251                 dev_err(da9150->dev, "Failed to bulk write to reg 0x%x %d\n",
 252                         reg, ret);
 253 }
 254 EXPORT_SYMBOL_GPL(da9150_bulk_write);
 255 
 256 static const struct regmap_irq da9150_irqs[] = {
 257         [DA9150_IRQ_VBUS] = {
 258                 .reg_offset = 0,
 259                 .mask = DA9150_E_VBUS_MASK,
 260         },
 261         [DA9150_IRQ_CHG] = {
 262                 .reg_offset = 0,
 263                 .mask = DA9150_E_CHG_MASK,
 264         },
 265         [DA9150_IRQ_TCLASS] = {
 266                 .reg_offset = 0,
 267                 .mask = DA9150_E_TCLASS_MASK,
 268         },
 269         [DA9150_IRQ_TJUNC] = {
 270                 .reg_offset = 0,
 271                 .mask = DA9150_E_TJUNC_MASK,
 272         },
 273         [DA9150_IRQ_VFAULT] = {
 274                 .reg_offset = 0,
 275                 .mask = DA9150_E_VFAULT_MASK,
 276         },
 277         [DA9150_IRQ_CONF] = {
 278                 .reg_offset = 1,
 279                 .mask = DA9150_E_CONF_MASK,
 280         },
 281         [DA9150_IRQ_DAT] = {
 282                 .reg_offset = 1,
 283                 .mask = DA9150_E_DAT_MASK,
 284         },
 285         [DA9150_IRQ_DTYPE] = {
 286                 .reg_offset = 1,
 287                 .mask = DA9150_E_DTYPE_MASK,
 288         },
 289         [DA9150_IRQ_ID] = {
 290                 .reg_offset = 1,
 291                 .mask = DA9150_E_ID_MASK,
 292         },
 293         [DA9150_IRQ_ADP] = {
 294                 .reg_offset = 1,
 295                 .mask = DA9150_E_ADP_MASK,
 296         },
 297         [DA9150_IRQ_SESS_END] = {
 298                 .reg_offset = 1,
 299                 .mask = DA9150_E_SESS_END_MASK,
 300         },
 301         [DA9150_IRQ_SESS_VLD] = {
 302                 .reg_offset = 1,
 303                 .mask = DA9150_E_SESS_VLD_MASK,
 304         },
 305         [DA9150_IRQ_FG] = {
 306                 .reg_offset = 2,
 307                 .mask = DA9150_E_FG_MASK,
 308         },
 309         [DA9150_IRQ_GP] = {
 310                 .reg_offset = 2,
 311                 .mask = DA9150_E_GP_MASK,
 312         },
 313         [DA9150_IRQ_TBAT] = {
 314                 .reg_offset = 2,
 315                 .mask = DA9150_E_TBAT_MASK,
 316         },
 317         [DA9150_IRQ_GPIOA] = {
 318                 .reg_offset = 2,
 319                 .mask = DA9150_E_GPIOA_MASK,
 320         },
 321         [DA9150_IRQ_GPIOB] = {
 322                 .reg_offset = 2,
 323                 .mask = DA9150_E_GPIOB_MASK,
 324         },
 325         [DA9150_IRQ_GPIOC] = {
 326                 .reg_offset = 2,
 327                 .mask = DA9150_E_GPIOC_MASK,
 328         },
 329         [DA9150_IRQ_GPIOD] = {
 330                 .reg_offset = 2,
 331                 .mask = DA9150_E_GPIOD_MASK,
 332         },
 333         [DA9150_IRQ_GPADC] = {
 334                 .reg_offset = 2,
 335                 .mask = DA9150_E_GPADC_MASK,
 336         },
 337         [DA9150_IRQ_WKUP] = {
 338                 .reg_offset = 3,
 339                 .mask = DA9150_E_WKUP_MASK,
 340         },
 341 };
 342 
 343 static const struct regmap_irq_chip da9150_regmap_irq_chip = {
 344         .name = "da9150_irq",
 345         .status_base = DA9150_EVENT_E,
 346         .mask_base = DA9150_IRQ_MASK_E,
 347         .ack_base = DA9150_EVENT_E,
 348         .num_regs = DA9150_NUM_IRQ_REGS,
 349         .irqs = da9150_irqs,
 350         .num_irqs = ARRAY_SIZE(da9150_irqs),
 351 };
 352 
 353 static struct resource da9150_gpadc_resources[] = {
 354         DEFINE_RES_IRQ_NAMED(DA9150_IRQ_GPADC, "GPADC"),
 355 };
 356 
 357 static struct resource da9150_charger_resources[] = {
 358         DEFINE_RES_IRQ_NAMED(DA9150_IRQ_CHG, "CHG_STATUS"),
 359         DEFINE_RES_IRQ_NAMED(DA9150_IRQ_TJUNC, "CHG_TJUNC"),
 360         DEFINE_RES_IRQ_NAMED(DA9150_IRQ_VFAULT, "CHG_VFAULT"),
 361         DEFINE_RES_IRQ_NAMED(DA9150_IRQ_VBUS, "CHG_VBUS"),
 362 };
 363 
 364 static struct resource da9150_fg_resources[] = {
 365         DEFINE_RES_IRQ_NAMED(DA9150_IRQ_FG, "FG"),
 366 };
 367 
 368 enum da9150_dev_idx {
 369         DA9150_GPADC_IDX = 0,
 370         DA9150_CHARGER_IDX,
 371         DA9150_FG_IDX,
 372 };
 373 
 374 static struct mfd_cell da9150_devs[] = {
 375         [DA9150_GPADC_IDX] = {
 376                 .name = "da9150-gpadc",
 377                 .of_compatible = "dlg,da9150-gpadc",
 378                 .resources = da9150_gpadc_resources,
 379                 .num_resources = ARRAY_SIZE(da9150_gpadc_resources),
 380         },
 381         [DA9150_CHARGER_IDX] = {
 382                 .name = "da9150-charger",
 383                 .of_compatible = "dlg,da9150-charger",
 384                 .resources = da9150_charger_resources,
 385                 .num_resources = ARRAY_SIZE(da9150_charger_resources),
 386         },
 387         [DA9150_FG_IDX] = {
 388                 .name = "da9150-fuel-gauge",
 389                 .of_compatible = "dlg,da9150-fuel-gauge",
 390                 .resources = da9150_fg_resources,
 391                 .num_resources = ARRAY_SIZE(da9150_fg_resources),
 392         },
 393 };
 394 
 395 static int da9150_probe(struct i2c_client *client,
 396                         const struct i2c_device_id *id)
 397 {
 398         struct da9150 *da9150;
 399         struct da9150_pdata *pdata = dev_get_platdata(&client->dev);
 400         int qif_addr;
 401         int ret;
 402 
 403         da9150 = devm_kzalloc(&client->dev, sizeof(*da9150), GFP_KERNEL);
 404         if (!da9150)
 405                 return -ENOMEM;
 406 
 407         da9150->dev = &client->dev;
 408         da9150->irq = client->irq;
 409         i2c_set_clientdata(client, da9150);
 410 
 411         da9150->regmap = devm_regmap_init_i2c(client, &da9150_regmap_config);
 412         if (IS_ERR(da9150->regmap)) {
 413                 ret = PTR_ERR(da9150->regmap);
 414                 dev_err(da9150->dev, "Failed to allocate register map: %d\n",
 415                         ret);
 416                 return ret;
 417         }
 418 
 419         /* Setup secondary I2C interface for QIF access */
 420         qif_addr = da9150_reg_read(da9150, DA9150_CORE2WIRE_CTRL_A);
 421         qif_addr = (qif_addr & DA9150_CORE_BASE_ADDR_MASK) >> 1;
 422         qif_addr |= DA9150_QIF_I2C_ADDR_LSB;
 423         da9150->core_qif = i2c_new_dummy_device(client->adapter, qif_addr);
 424         if (IS_ERR(da9150->core_qif)) {
 425                 dev_err(da9150->dev, "Failed to attach QIF client\n");
 426                 return PTR_ERR(da9150->core_qif);
 427         }
 428 
 429         i2c_set_clientdata(da9150->core_qif, da9150);
 430 
 431         if (pdata) {
 432                 da9150->irq_base = pdata->irq_base;
 433 
 434                 da9150_devs[DA9150_FG_IDX].platform_data = pdata->fg_pdata;
 435                 da9150_devs[DA9150_FG_IDX].pdata_size =
 436                         sizeof(struct da9150_fg_pdata);
 437         } else {
 438                 da9150->irq_base = -1;
 439         }
 440 
 441         ret = regmap_add_irq_chip(da9150->regmap, da9150->irq,
 442                                   IRQF_TRIGGER_LOW | IRQF_ONESHOT,
 443                                   da9150->irq_base, &da9150_regmap_irq_chip,
 444                                   &da9150->regmap_irq_data);
 445         if (ret) {
 446                 dev_err(da9150->dev, "Failed to add regmap irq chip: %d\n",
 447                         ret);
 448                 goto regmap_irq_fail;
 449         }
 450 
 451 
 452         da9150->irq_base = regmap_irq_chip_get_base(da9150->regmap_irq_data);
 453 
 454         enable_irq_wake(da9150->irq);
 455 
 456         ret = mfd_add_devices(da9150->dev, -1, da9150_devs,
 457                               ARRAY_SIZE(da9150_devs), NULL,
 458                               da9150->irq_base, NULL);
 459         if (ret) {
 460                 dev_err(da9150->dev, "Failed to add child devices: %d\n", ret);
 461                 goto mfd_fail;
 462         }
 463 
 464         return 0;
 465 
 466 mfd_fail:
 467         regmap_del_irq_chip(da9150->irq, da9150->regmap_irq_data);
 468 regmap_irq_fail:
 469         i2c_unregister_device(da9150->core_qif);
 470 
 471         return ret;
 472 }
 473 
 474 static int da9150_remove(struct i2c_client *client)
 475 {
 476         struct da9150 *da9150 = i2c_get_clientdata(client);
 477 
 478         regmap_del_irq_chip(da9150->irq, da9150->regmap_irq_data);
 479         mfd_remove_devices(da9150->dev);
 480         i2c_unregister_device(da9150->core_qif);
 481 
 482         return 0;
 483 }
 484 
 485 static void da9150_shutdown(struct i2c_client *client)
 486 {
 487         struct da9150 *da9150 = i2c_get_clientdata(client);
 488 
 489         /* Make sure we have a wakup source for the device */
 490         da9150_set_bits(da9150, DA9150_CONFIG_D,
 491                         DA9150_WKUP_PM_EN_MASK,
 492                         DA9150_WKUP_PM_EN_MASK);
 493 
 494         /* Set device to DISABLED mode */
 495         da9150_set_bits(da9150, DA9150_CONTROL_C,
 496                         DA9150_DISABLE_MASK, DA9150_DISABLE_MASK);
 497 }
 498 
 499 static const struct i2c_device_id da9150_i2c_id[] = {
 500         { "da9150", },
 501         { }
 502 };
 503 MODULE_DEVICE_TABLE(i2c, da9150_i2c_id);
 504 
 505 static const struct of_device_id da9150_of_match[] = {
 506         { .compatible = "dlg,da9150", },
 507         { }
 508 };
 509 MODULE_DEVICE_TABLE(of, da9150_of_match);
 510 
 511 static struct i2c_driver da9150_driver = {
 512         .driver = {
 513                 .name   = "da9150",
 514                 .of_match_table = of_match_ptr(da9150_of_match),
 515         },
 516         .probe          = da9150_probe,
 517         .remove         = da9150_remove,
 518         .shutdown       = da9150_shutdown,
 519         .id_table       = da9150_i2c_id,
 520 };
 521 
 522 module_i2c_driver(da9150_driver);
 523 
 524 MODULE_DESCRIPTION("MFD Core Driver for DA9150");
 525 MODULE_AUTHOR("Adam Thomson <Adam.Thomson.Opensource@diasemi.com>");
 526 MODULE_LICENSE("GPL");

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