root/drivers/mfd/tps65218.c

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

DEFINITIONS

This source file includes following definitions.
  1. tps65218_reg_write
  2. tps65218_update_bits
  3. tps65218_set_bits
  4. tps65218_clear_bits
  5. tps65218_voltage_set_strict
  6. tps65218_voltage_set_uv_hyst
  7. tps65218_voltage_set_uvlo
  8. tps65218_probe

   1 /*
   2  * Driver for TPS65218 Integrated power management chipsets
   3  *
   4  * Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/
   5  *
   6  * This program is free software; you can redistribute it and/or
   7  * modify it under the terms of the GNU General Public License version 2 as
   8  * published by the Free Software Foundation.
   9  *
  10  * This program is distributed "as is" WITHOUT ANY WARRANTY of any
  11  * kind, whether expressed or implied; without even the implied warranty
  12  * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13  * GNU General Public License version 2 for more details.
  14  */
  15 
  16 #include <linux/kernel.h>
  17 #include <linux/device.h>
  18 #include <linux/module.h>
  19 #include <linux/platform_device.h>
  20 #include <linux/init.h>
  21 #include <linux/i2c.h>
  22 #include <linux/slab.h>
  23 #include <linux/regmap.h>
  24 #include <linux/err.h>
  25 #include <linux/of.h>
  26 #include <linux/of_device.h>
  27 #include <linux/irq.h>
  28 #include <linux/interrupt.h>
  29 #include <linux/mutex.h>
  30 
  31 #include <linux/mfd/core.h>
  32 #include <linux/mfd/tps65218.h>
  33 
  34 #define TPS65218_PASSWORD_REGS_UNLOCK   0x7D
  35 
  36 static const struct mfd_cell tps65218_cells[] = {
  37         {
  38                 .name = "tps65218-pwrbutton",
  39                 .of_compatible = "ti,tps65218-pwrbutton",
  40         },
  41         {
  42                 .name = "tps65218-gpio",
  43                 .of_compatible = "ti,tps65218-gpio",
  44         },
  45         { .name = "tps65218-regulator", },
  46 };
  47 
  48 /**
  49  * tps65218_reg_write: Write a single tps65218 register.
  50  *
  51  * @tps65218: Device to write to.
  52  * @reg: Register to write to.
  53  * @val: Value to write.
  54  * @level: Password protected level
  55  */
  56 int tps65218_reg_write(struct tps65218 *tps, unsigned int reg,
  57                         unsigned int val, unsigned int level)
  58 {
  59         int ret;
  60         unsigned int xor_reg_val;
  61 
  62         switch (level) {
  63         case TPS65218_PROTECT_NONE:
  64                 return regmap_write(tps->regmap, reg, val);
  65         case TPS65218_PROTECT_L1:
  66                 xor_reg_val = reg ^ TPS65218_PASSWORD_REGS_UNLOCK;
  67                 ret = regmap_write(tps->regmap, TPS65218_REG_PASSWORD,
  68                                                         xor_reg_val);
  69                 if (ret < 0)
  70                         return ret;
  71 
  72                 return regmap_write(tps->regmap, reg, val);
  73         default:
  74                 return -EINVAL;
  75         }
  76 }
  77 EXPORT_SYMBOL_GPL(tps65218_reg_write);
  78 
  79 /**
  80  * tps65218_update_bits: Modify bits w.r.t mask, val and level.
  81  *
  82  * @tps65218: Device to write to.
  83  * @reg: Register to read-write to.
  84  * @mask: Mask.
  85  * @val: Value to write.
  86  * @level: Password protected level
  87  */
  88 static int tps65218_update_bits(struct tps65218 *tps, unsigned int reg,
  89                 unsigned int mask, unsigned int val, unsigned int level)
  90 {
  91         int ret;
  92         unsigned int data;
  93 
  94         ret = regmap_read(tps->regmap, reg, &data);
  95         if (ret) {
  96                 dev_err(tps->dev, "Read from reg 0x%x failed\n", reg);
  97                 return ret;
  98         }
  99 
 100         data &= ~mask;
 101         data |= val & mask;
 102 
 103         mutex_lock(&tps->tps_lock);
 104         ret = tps65218_reg_write(tps, reg, data, level);
 105         if (ret)
 106                 dev_err(tps->dev, "Write for reg 0x%x failed\n", reg);
 107         mutex_unlock(&tps->tps_lock);
 108 
 109         return ret;
 110 }
 111 
 112 int tps65218_set_bits(struct tps65218 *tps, unsigned int reg,
 113                 unsigned int mask, unsigned int val, unsigned int level)
 114 {
 115         return tps65218_update_bits(tps, reg, mask, val, level);
 116 }
 117 EXPORT_SYMBOL_GPL(tps65218_set_bits);
 118 
 119 int tps65218_clear_bits(struct tps65218 *tps, unsigned int reg,
 120                 unsigned int mask, unsigned int level)
 121 {
 122         return tps65218_update_bits(tps, reg, mask, 0, level);
 123 }
 124 EXPORT_SYMBOL_GPL(tps65218_clear_bits);
 125 
 126 static const struct regmap_range tps65218_yes_ranges[] = {
 127         regmap_reg_range(TPS65218_REG_INT1, TPS65218_REG_INT2),
 128         regmap_reg_range(TPS65218_REG_STATUS, TPS65218_REG_STATUS),
 129 };
 130 
 131 static const struct regmap_access_table tps65218_volatile_table = {
 132         .yes_ranges = tps65218_yes_ranges,
 133         .n_yes_ranges = ARRAY_SIZE(tps65218_yes_ranges),
 134 };
 135 
 136 static const struct regmap_config tps65218_regmap_config = {
 137         .reg_bits = 8,
 138         .val_bits = 8,
 139         .cache_type = REGCACHE_RBTREE,
 140         .volatile_table = &tps65218_volatile_table,
 141 };
 142 
 143 static const struct regmap_irq tps65218_irqs[] = {
 144         /* INT1 IRQs */
 145         [TPS65218_PRGC_IRQ] = {
 146                 .mask = TPS65218_INT1_PRGC,
 147         },
 148         [TPS65218_CC_AQC_IRQ] = {
 149                 .mask = TPS65218_INT1_CC_AQC,
 150         },
 151         [TPS65218_HOT_IRQ] = {
 152                 .mask = TPS65218_INT1_HOT,
 153         },
 154         [TPS65218_PB_IRQ] = {
 155                 .mask = TPS65218_INT1_PB,
 156         },
 157         [TPS65218_AC_IRQ] = {
 158                 .mask = TPS65218_INT1_AC,
 159         },
 160         [TPS65218_VPRG_IRQ] = {
 161                 .mask = TPS65218_INT1_VPRG,
 162         },
 163         [TPS65218_INVALID1_IRQ] = {
 164         },
 165         [TPS65218_INVALID2_IRQ] = {
 166         },
 167         /* INT2 IRQs*/
 168         [TPS65218_LS1_I_IRQ] = {
 169                 .mask = TPS65218_INT2_LS1_I,
 170                 .reg_offset = 1,
 171         },
 172         [TPS65218_LS2_I_IRQ] = {
 173                 .mask = TPS65218_INT2_LS2_I,
 174                 .reg_offset = 1,
 175         },
 176         [TPS65218_LS3_I_IRQ] = {
 177                 .mask = TPS65218_INT2_LS3_I,
 178                 .reg_offset = 1,
 179         },
 180         [TPS65218_LS1_F_IRQ] = {
 181                 .mask = TPS65218_INT2_LS1_F,
 182                 .reg_offset = 1,
 183         },
 184         [TPS65218_LS2_F_IRQ] = {
 185                 .mask = TPS65218_INT2_LS2_F,
 186                 .reg_offset = 1,
 187         },
 188         [TPS65218_LS3_F_IRQ] = {
 189                 .mask = TPS65218_INT2_LS3_F,
 190                 .reg_offset = 1,
 191         },
 192         [TPS65218_INVALID3_IRQ] = {
 193         },
 194         [TPS65218_INVALID4_IRQ] = {
 195         },
 196 };
 197 
 198 static struct regmap_irq_chip tps65218_irq_chip = {
 199         .name = "tps65218",
 200         .irqs = tps65218_irqs,
 201         .num_irqs = ARRAY_SIZE(tps65218_irqs),
 202 
 203         .num_regs = 2,
 204         .mask_base = TPS65218_REG_INT_MASK1,
 205         .status_base = TPS65218_REG_INT1,
 206 };
 207 
 208 static const struct of_device_id of_tps65218_match_table[] = {
 209         { .compatible = "ti,tps65218", },
 210         {}
 211 };
 212 MODULE_DEVICE_TABLE(of, of_tps65218_match_table);
 213 
 214 static int tps65218_voltage_set_strict(struct tps65218 *tps)
 215 {
 216         u32 strict;
 217 
 218         if (of_property_read_u32(tps->dev->of_node,
 219                                  "ti,strict-supply-voltage-supervision",
 220                                  &strict))
 221                 return 0;
 222 
 223         if (strict != 0 && strict != 1) {
 224                 dev_err(tps->dev,
 225                         "Invalid ti,strict-supply-voltage-supervision value\n");
 226                 return -EINVAL;
 227         }
 228 
 229         tps65218_update_bits(tps, TPS65218_REG_CONFIG1,
 230                              TPS65218_CONFIG1_STRICT,
 231                              strict ? TPS65218_CONFIG1_STRICT : 0,
 232                              TPS65218_PROTECT_L1);
 233         return 0;
 234 }
 235 
 236 static int tps65218_voltage_set_uv_hyst(struct tps65218 *tps)
 237 {
 238         u32 hyst;
 239 
 240         if (of_property_read_u32(tps->dev->of_node,
 241                                  "ti,under-voltage-hyst-microvolt", &hyst))
 242                 return 0;
 243 
 244         if (hyst != 400000 && hyst != 200000) {
 245                 dev_err(tps->dev,
 246                         "Invalid ti,under-voltage-hyst-microvolt value\n");
 247                 return -EINVAL;
 248         }
 249 
 250         tps65218_update_bits(tps, TPS65218_REG_CONFIG2,
 251                              TPS65218_CONFIG2_UVLOHYS,
 252                              hyst == 400000 ? TPS65218_CONFIG2_UVLOHYS : 0,
 253                              TPS65218_PROTECT_L1);
 254         return 0;
 255 }
 256 
 257 static int tps65218_voltage_set_uvlo(struct tps65218 *tps)
 258 {
 259         u32 uvlo;
 260         int uvloval;
 261 
 262         if (of_property_read_u32(tps->dev->of_node,
 263                                  "ti,under-voltage-limit-microvolt", &uvlo))
 264                 return 0;
 265 
 266         switch (uvlo) {
 267         case 2750000:
 268                 uvloval = TPS65218_CONFIG1_UVLO_2750000;
 269                 break;
 270         case 2950000:
 271                 uvloval = TPS65218_CONFIG1_UVLO_2950000;
 272                 break;
 273         case 3250000:
 274                 uvloval = TPS65218_CONFIG1_UVLO_3250000;
 275                 break;
 276         case 3350000:
 277                 uvloval = TPS65218_CONFIG1_UVLO_3350000;
 278                 break;
 279         default:
 280                 dev_err(tps->dev,
 281                         "Invalid ti,under-voltage-limit-microvolt value\n");
 282                 return -EINVAL;
 283         }
 284 
 285         tps65218_update_bits(tps, TPS65218_REG_CONFIG1,
 286                              TPS65218_CONFIG1_UVLO_MASK, uvloval,
 287                              TPS65218_PROTECT_L1);
 288         return 0;
 289 }
 290 
 291 static int tps65218_probe(struct i2c_client *client,
 292                                 const struct i2c_device_id *ids)
 293 {
 294         struct tps65218 *tps;
 295         int ret;
 296         unsigned int chipid;
 297 
 298         tps = devm_kzalloc(&client->dev, sizeof(*tps), GFP_KERNEL);
 299         if (!tps)
 300                 return -ENOMEM;
 301 
 302         i2c_set_clientdata(client, tps);
 303         tps->dev = &client->dev;
 304         tps->irq = client->irq;
 305         tps->regmap = devm_regmap_init_i2c(client, &tps65218_regmap_config);
 306         if (IS_ERR(tps->regmap)) {
 307                 ret = PTR_ERR(tps->regmap);
 308                 dev_err(tps->dev, "Failed to allocate register map: %d\n",
 309                         ret);
 310                 return ret;
 311         }
 312 
 313         mutex_init(&tps->tps_lock);
 314 
 315         ret = devm_regmap_add_irq_chip(&client->dev, tps->regmap, tps->irq,
 316                                        IRQF_ONESHOT, 0, &tps65218_irq_chip,
 317                                        &tps->irq_data);
 318         if (ret < 0)
 319                 return ret;
 320 
 321         ret = regmap_read(tps->regmap, TPS65218_REG_CHIPID, &chipid);
 322         if (ret) {
 323                 dev_err(tps->dev, "Failed to read chipid: %d\n", ret);
 324                 return ret;
 325         }
 326 
 327         tps->rev = chipid & TPS65218_CHIPID_REV_MASK;
 328 
 329         ret = tps65218_voltage_set_strict(tps);
 330         if (ret)
 331                 return ret;
 332 
 333         ret = tps65218_voltage_set_uvlo(tps);
 334         if (ret)
 335                 return ret;
 336 
 337         ret = tps65218_voltage_set_uv_hyst(tps);
 338         if (ret)
 339                 return ret;
 340 
 341         ret = mfd_add_devices(tps->dev, PLATFORM_DEVID_AUTO, tps65218_cells,
 342                               ARRAY_SIZE(tps65218_cells), NULL, 0,
 343                               regmap_irq_get_domain(tps->irq_data));
 344 
 345         return ret;
 346 }
 347 
 348 static const struct i2c_device_id tps65218_id_table[] = {
 349         { "tps65218", TPS65218 },
 350         { },
 351 };
 352 MODULE_DEVICE_TABLE(i2c, tps65218_id_table);
 353 
 354 static struct i2c_driver tps65218_driver = {
 355         .driver         = {
 356                 .name   = "tps65218",
 357                 .of_match_table = of_tps65218_match_table,
 358         },
 359         .probe          = tps65218_probe,
 360         .id_table       = tps65218_id_table,
 361 };
 362 
 363 module_i2c_driver(tps65218_driver);
 364 
 365 MODULE_AUTHOR("J Keerthy <j-keerthy@ti.com>");
 366 MODULE_DESCRIPTION("TPS65218 chip family multi-function driver");
 367 MODULE_LICENSE("GPL v2");

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