root/drivers/mfd/max77650.c

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

DEFINITIONS

This source file includes following definitions.
  1. max77650_i2c_probe

   1 // SPDX-License-Identifier: GPL-2.0
   2 //
   3 // Copyright (C) 2018 BayLibre SAS
   4 // Author: Bartosz Golaszewski <bgolaszewski@baylibre.com>
   5 //
   6 // Core MFD driver for MAXIM 77650/77651 charger/power-supply.
   7 // Programming manual: https://pdfserv.maximintegrated.com/en/an/AN6428.pdf
   8 
   9 #include <linux/i2c.h>
  10 #include <linux/interrupt.h>
  11 #include <linux/irq.h>
  12 #include <linux/mfd/core.h>
  13 #include <linux/mfd/max77650.h>
  14 #include <linux/module.h>
  15 #include <linux/of.h>
  16 #include <linux/regmap.h>
  17 
  18 #define MAX77650_INT_GPI_F_MSK          BIT(0)
  19 #define MAX77650_INT_GPI_R_MSK          BIT(1)
  20 #define MAX77650_INT_GPI_MSK \
  21                         (MAX77650_INT_GPI_F_MSK | MAX77650_INT_GPI_R_MSK)
  22 #define MAX77650_INT_nEN_F_MSK          BIT(2)
  23 #define MAX77650_INT_nEN_R_MSK          BIT(3)
  24 #define MAX77650_INT_TJAL1_R_MSK        BIT(4)
  25 #define MAX77650_INT_TJAL2_R_MSK        BIT(5)
  26 #define MAX77650_INT_DOD_R_MSK          BIT(6)
  27 
  28 #define MAX77650_INT_THM_MSK            BIT(0)
  29 #define MAX77650_INT_CHG_MSK            BIT(1)
  30 #define MAX77650_INT_CHGIN_MSK          BIT(2)
  31 #define MAX77650_INT_TJ_REG_MSK         BIT(3)
  32 #define MAX77650_INT_CHGIN_CTRL_MSK     BIT(4)
  33 #define MAX77650_INT_SYS_CTRL_MSK       BIT(5)
  34 #define MAX77650_INT_SYS_CNFG_MSK       BIT(6)
  35 
  36 #define MAX77650_INT_GLBL_OFFSET        0
  37 #define MAX77650_INT_CHG_OFFSET         1
  38 
  39 #define MAX77650_SBIA_LPM_MASK          BIT(5)
  40 #define MAX77650_SBIA_LPM_DISABLED      0x00
  41 
  42 enum {
  43         MAX77650_INT_GPI,
  44         MAX77650_INT_nEN_F,
  45         MAX77650_INT_nEN_R,
  46         MAX77650_INT_TJAL1_R,
  47         MAX77650_INT_TJAL2_R,
  48         MAX77650_INT_DOD_R,
  49         MAX77650_INT_THM,
  50         MAX77650_INT_CHG,
  51         MAX77650_INT_CHGIN,
  52         MAX77650_INT_TJ_REG,
  53         MAX77650_INT_CHGIN_CTRL,
  54         MAX77650_INT_SYS_CTRL,
  55         MAX77650_INT_SYS_CNFG,
  56 };
  57 
  58 static const struct resource max77650_charger_resources[] = {
  59         DEFINE_RES_IRQ_NAMED(MAX77650_INT_CHG, "CHG"),
  60         DEFINE_RES_IRQ_NAMED(MAX77650_INT_CHGIN, "CHGIN"),
  61 };
  62 
  63 static const struct resource max77650_gpio_resources[] = {
  64         DEFINE_RES_IRQ_NAMED(MAX77650_INT_GPI, "GPI"),
  65 };
  66 
  67 static const struct resource max77650_onkey_resources[] = {
  68         DEFINE_RES_IRQ_NAMED(MAX77650_INT_nEN_F, "nEN_F"),
  69         DEFINE_RES_IRQ_NAMED(MAX77650_INT_nEN_R, "nEN_R"),
  70 };
  71 
  72 static const struct mfd_cell max77650_cells[] = {
  73         {
  74                 .name           = "max77650-regulator",
  75                 .of_compatible  = "maxim,max77650-regulator",
  76         }, {
  77                 .name           = "max77650-charger",
  78                 .of_compatible  = "maxim,max77650-charger",
  79                 .resources      = max77650_charger_resources,
  80                 .num_resources  = ARRAY_SIZE(max77650_charger_resources),
  81         }, {
  82                 .name           = "max77650-gpio",
  83                 .of_compatible  = "maxim,max77650-gpio",
  84                 .resources      = max77650_gpio_resources,
  85                 .num_resources  = ARRAY_SIZE(max77650_gpio_resources),
  86         }, {
  87                 .name           = "max77650-led",
  88                 .of_compatible  = "maxim,max77650-led",
  89         }, {
  90                 .name           = "max77650-onkey",
  91                 .of_compatible  = "maxim,max77650-onkey",
  92                 .resources      = max77650_onkey_resources,
  93                 .num_resources  = ARRAY_SIZE(max77650_onkey_resources),
  94         },
  95 };
  96 
  97 static const struct regmap_irq max77650_irqs[] = {
  98         [MAX77650_INT_GPI] = {
  99                 .reg_offset = MAX77650_INT_GLBL_OFFSET,
 100                 .mask = MAX77650_INT_GPI_MSK,
 101                 .type = {
 102                         .type_falling_val = MAX77650_INT_GPI_F_MSK,
 103                         .type_rising_val = MAX77650_INT_GPI_R_MSK,
 104                         .types_supported = IRQ_TYPE_EDGE_BOTH,
 105                 },
 106         },
 107         REGMAP_IRQ_REG(MAX77650_INT_nEN_F,
 108                        MAX77650_INT_GLBL_OFFSET, MAX77650_INT_nEN_F_MSK),
 109         REGMAP_IRQ_REG(MAX77650_INT_nEN_R,
 110                        MAX77650_INT_GLBL_OFFSET, MAX77650_INT_nEN_R_MSK),
 111         REGMAP_IRQ_REG(MAX77650_INT_TJAL1_R,
 112                        MAX77650_INT_GLBL_OFFSET, MAX77650_INT_TJAL1_R_MSK),
 113         REGMAP_IRQ_REG(MAX77650_INT_TJAL2_R,
 114                        MAX77650_INT_GLBL_OFFSET, MAX77650_INT_TJAL2_R_MSK),
 115         REGMAP_IRQ_REG(MAX77650_INT_DOD_R,
 116                        MAX77650_INT_GLBL_OFFSET, MAX77650_INT_DOD_R_MSK),
 117         REGMAP_IRQ_REG(MAX77650_INT_THM,
 118                        MAX77650_INT_CHG_OFFSET, MAX77650_INT_THM_MSK),
 119         REGMAP_IRQ_REG(MAX77650_INT_CHG,
 120                        MAX77650_INT_CHG_OFFSET, MAX77650_INT_CHG_MSK),
 121         REGMAP_IRQ_REG(MAX77650_INT_CHGIN,
 122                        MAX77650_INT_CHG_OFFSET, MAX77650_INT_CHGIN_MSK),
 123         REGMAP_IRQ_REG(MAX77650_INT_TJ_REG,
 124                        MAX77650_INT_CHG_OFFSET, MAX77650_INT_TJ_REG_MSK),
 125         REGMAP_IRQ_REG(MAX77650_INT_CHGIN_CTRL,
 126                        MAX77650_INT_CHG_OFFSET, MAX77650_INT_CHGIN_CTRL_MSK),
 127         REGMAP_IRQ_REG(MAX77650_INT_SYS_CTRL,
 128                        MAX77650_INT_CHG_OFFSET, MAX77650_INT_SYS_CTRL_MSK),
 129         REGMAP_IRQ_REG(MAX77650_INT_SYS_CNFG,
 130                        MAX77650_INT_CHG_OFFSET, MAX77650_INT_SYS_CNFG_MSK),
 131 };
 132 
 133 static const struct regmap_irq_chip max77650_irq_chip = {
 134         .name                   = "max77650-irq",
 135         .irqs                   = max77650_irqs,
 136         .num_irqs               = ARRAY_SIZE(max77650_irqs),
 137         .num_regs               = 2,
 138         .status_base            = MAX77650_REG_INT_GLBL,
 139         .mask_base              = MAX77650_REG_INTM_GLBL,
 140         .type_in_mask           = true,
 141         .type_invert            = true,
 142         .init_ack_masked        = true,
 143         .clear_on_unmask        = true,
 144 };
 145 
 146 static const struct regmap_config max77650_regmap_config = {
 147         .name           = "max77650",
 148         .reg_bits       = 8,
 149         .val_bits       = 8,
 150 };
 151 
 152 static int max77650_i2c_probe(struct i2c_client *i2c)
 153 {
 154         struct regmap_irq_chip_data *irq_data;
 155         struct device *dev = &i2c->dev;
 156         struct irq_domain *domain;
 157         struct regmap *map;
 158         unsigned int val;
 159         int rv, id;
 160 
 161         map = devm_regmap_init_i2c(i2c, &max77650_regmap_config);
 162         if (IS_ERR(map)) {
 163                 dev_err(dev, "Unable to initialise I2C Regmap\n");
 164                 return PTR_ERR(map);
 165         }
 166 
 167         rv = regmap_read(map, MAX77650_REG_CID, &val);
 168         if (rv) {
 169                 dev_err(dev, "Unable to read Chip ID\n");
 170                 return rv;
 171         }
 172 
 173         id = MAX77650_CID_BITS(val);
 174         switch (id) {
 175         case MAX77650_CID_77650A:
 176         case MAX77650_CID_77650C:
 177         case MAX77650_CID_77651A:
 178         case MAX77650_CID_77651B:
 179                 break;
 180         default:
 181                 dev_err(dev, "Chip not supported - ID: 0x%02x\n", id);
 182                 return -ENODEV;
 183         }
 184 
 185         /*
 186          * This IC has a low-power mode which reduces the quiescent current
 187          * consumption to ~5.6uA but is only suitable for systems consuming
 188          * less than ~2mA. Since this is not likely the case even on
 189          * linux-based wearables - keep the chip in normal power mode.
 190          */
 191         rv = regmap_update_bits(map,
 192                                 MAX77650_REG_CNFG_GLBL,
 193                                 MAX77650_SBIA_LPM_MASK,
 194                                 MAX77650_SBIA_LPM_DISABLED);
 195         if (rv) {
 196                 dev_err(dev, "Unable to change the power mode\n");
 197                 return rv;
 198         }
 199 
 200         rv = devm_regmap_add_irq_chip(dev, map, i2c->irq,
 201                                       IRQF_ONESHOT | IRQF_SHARED, 0,
 202                                       &max77650_irq_chip, &irq_data);
 203         if (rv) {
 204                 dev_err(dev, "Unable to add Regmap IRQ chip\n");
 205                 return rv;
 206         }
 207 
 208         domain = regmap_irq_get_domain(irq_data);
 209 
 210         return devm_mfd_add_devices(dev, PLATFORM_DEVID_NONE,
 211                                     max77650_cells, ARRAY_SIZE(max77650_cells),
 212                                     NULL, 0, domain);
 213 }
 214 
 215 static const struct of_device_id max77650_of_match[] = {
 216         { .compatible = "maxim,max77650" },
 217         { }
 218 };
 219 MODULE_DEVICE_TABLE(of, max77650_of_match);
 220 
 221 static struct i2c_driver max77650_i2c_driver = {
 222         .driver = {
 223                 .name = "max77650",
 224                 .of_match_table = of_match_ptr(max77650_of_match),
 225         },
 226         .probe_new = max77650_i2c_probe,
 227 };
 228 module_i2c_driver(max77650_i2c_driver);
 229 
 230 MODULE_DESCRIPTION("MAXIM 77650/77651 multi-function core driver");
 231 MODULE_AUTHOR("Bartosz Golaszewski <bgolaszewski@baylibre.com>");
 232 MODULE_LICENSE("GPL v2");

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