1 // SPDX-License-Identifier: GPL-2.0-only 2 // 3 // Copyright (C) 2019 ROHM Semiconductors 4 // 5 // ROHM BD71828 PMIC driver 6 7 #include <linux/gpio_keys.h> 8 #include <linux/i2c.h> 9 #include <linux/input.h> 10 #include <linux/interrupt.h> 11 #include <linux/ioport.h> 12 #include <linux/irq.h> 13 #include <linux/mfd/core.h> 14 #include <linux/mfd/rohm-bd71828.h> 15 #include <linux/module.h> 16 #include <linux/of_device.h> 17 #include <linux/regmap.h> 18 #include <linux/types.h> 19 20 static struct gpio_keys_button button = { 21 .code = KEY_POWER, 22 .gpio = -1, 23 .type = EV_KEY, 24 }; 25 26 static struct gpio_keys_platform_data bd71828_powerkey_data = { 27 .buttons = &button, 28 .nbuttons = 1, 29 .name = "bd71828-pwrkey", 30 }; 31 32 static const struct resource rtc_irqs[] = { 33 DEFINE_RES_IRQ_NAMED(BD71828_INT_RTC0, "bd71828-rtc-alm-0"), 34 DEFINE_RES_IRQ_NAMED(BD71828_INT_RTC1, "bd71828-rtc-alm-1"), 35 DEFINE_RES_IRQ_NAMED(BD71828_INT_RTC2, "bd71828-rtc-alm-2"), 36 }; 37 38 static struct mfd_cell bd71828_mfd_cells[] = { 39 { .name = "bd71828-pmic", }, 40 { .name = "bd71828-gpio", }, 41 { .name = "bd71828-led", .of_compatible = "rohm,bd71828-leds" }, 42 /* 43 * We use BD71837 driver to drive the clock block. Only differences to 44 * BD70528 clock gate are the register address and mask. 45 */ 46 { .name = "bd71828-clk", }, 47 { .name = "bd71827-power", }, 48 { 49 .name = "bd71828-rtc", 50 .resources = rtc_irqs, 51 .num_resources = ARRAY_SIZE(rtc_irqs), 52 }, { 53 .name = "gpio-keys", 54 .platform_data = &bd71828_powerkey_data, 55 .pdata_size = sizeof(bd71828_powerkey_data), 56 }, 57 }; 58 59 static const struct regmap_range volatile_ranges[] = { 60 { 61 .range_min = BD71828_REG_PS_CTRL_1, 62 .range_max = BD71828_REG_PS_CTRL_1, 63 }, { 64 .range_min = BD71828_REG_PS_CTRL_3, 65 .range_max = BD71828_REG_PS_CTRL_3, 66 }, { 67 .range_min = BD71828_REG_RTC_SEC, 68 .range_max = BD71828_REG_RTC_YEAR, 69 }, { 70 /* 71 * For now make all charger registers volatile because many 72 * needs to be and because the charger block is not that 73 * performance critical. 74 */ 75 .range_min = BD71828_REG_CHG_STATE, 76 .range_max = BD71828_REG_CHG_FULL, 77 }, { 78 .range_min = BD71828_REG_INT_MAIN, 79 .range_max = BD71828_REG_IO_STAT, 80 }, 81 }; 82 83 static const struct regmap_access_table volatile_regs = { 84 .yes_ranges = &volatile_ranges[0], 85 .n_yes_ranges = ARRAY_SIZE(volatile_ranges), 86 }; 87 88 static struct regmap_config bd71828_regmap = { 89 .reg_bits = 8, 90 .val_bits = 8, 91 .volatile_table = &volatile_regs, 92 .max_register = BD71828_MAX_REGISTER, 93 .cache_type = REGCACHE_RBTREE, 94 }; 95 96 /* 97 * Mapping of main IRQ register bits to sub-IRQ register offsets so that we can 98 * access corect sub-IRQ registers based on bits that are set in main IRQ 99 * register. 100 */ 101 102 static unsigned int bit0_offsets[] = {11}; /* RTC IRQ */ 103 static unsigned int bit1_offsets[] = {10}; /* TEMP IRQ */ 104 static unsigned int bit2_offsets[] = {6, 7, 8, 9}; /* BAT MON IRQ */ 105 static unsigned int bit3_offsets[] = {5}; /* BAT IRQ */ 106 static unsigned int bit4_offsets[] = {4}; /* CHG IRQ */ 107 static unsigned int bit5_offsets[] = {3}; /* VSYS IRQ */ 108 static unsigned int bit6_offsets[] = {1, 2}; /* DCIN IRQ */ 109 static unsigned int bit7_offsets[] = {0}; /* BUCK IRQ */ 110 111 static struct regmap_irq_sub_irq_map bd71828_sub_irq_offsets[] = { 112 REGMAP_IRQ_MAIN_REG_OFFSET(bit0_offsets), 113 REGMAP_IRQ_MAIN_REG_OFFSET(bit1_offsets), 114 REGMAP_IRQ_MAIN_REG_OFFSET(bit2_offsets), 115 REGMAP_IRQ_MAIN_REG_OFFSET(bit3_offsets), 116 REGMAP_IRQ_MAIN_REG_OFFSET(bit4_offsets), 117 REGMAP_IRQ_MAIN_REG_OFFSET(bit5_offsets), 118 REGMAP_IRQ_MAIN_REG_OFFSET(bit6_offsets), 119 REGMAP_IRQ_MAIN_REG_OFFSET(bit7_offsets), 120 }; 121 122 static struct regmap_irq bd71828_irqs[] = { 123 REGMAP_IRQ_REG(BD71828_INT_BUCK1_OCP, 0, BD71828_INT_BUCK1_OCP_MASK), 124 REGMAP_IRQ_REG(BD71828_INT_BUCK2_OCP, 0, BD71828_INT_BUCK2_OCP_MASK), 125 REGMAP_IRQ_REG(BD71828_INT_BUCK3_OCP, 0, BD71828_INT_BUCK3_OCP_MASK), 126 REGMAP_IRQ_REG(BD71828_INT_BUCK4_OCP, 0, BD71828_INT_BUCK4_OCP_MASK), 127 REGMAP_IRQ_REG(BD71828_INT_BUCK5_OCP, 0, BD71828_INT_BUCK5_OCP_MASK), 128 REGMAP_IRQ_REG(BD71828_INT_BUCK6_OCP, 0, BD71828_INT_BUCK6_OCP_MASK), 129 REGMAP_IRQ_REG(BD71828_INT_BUCK7_OCP, 0, BD71828_INT_BUCK7_OCP_MASK), 130 REGMAP_IRQ_REG(BD71828_INT_PGFAULT, 0, BD71828_INT_PGFAULT_MASK), 131 /* DCIN1 interrupts */ 132 REGMAP_IRQ_REG(BD71828_INT_DCIN_DET, 1, BD71828_INT_DCIN_DET_MASK), 133 REGMAP_IRQ_REG(BD71828_INT_DCIN_RMV, 1, BD71828_INT_DCIN_RMV_MASK), 134 REGMAP_IRQ_REG(BD71828_INT_CLPS_OUT, 1, BD71828_INT_CLPS_OUT_MASK), 135 REGMAP_IRQ_REG(BD71828_INT_CLPS_IN, 1, BD71828_INT_CLPS_IN_MASK), 136 /* DCIN2 interrupts */ 137 REGMAP_IRQ_REG(BD71828_INT_DCIN_MON_RES, 2, 138 BD71828_INT_DCIN_MON_RES_MASK), 139 REGMAP_IRQ_REG(BD71828_INT_DCIN_MON_DET, 2, 140 BD71828_INT_DCIN_MON_DET_MASK), 141 REGMAP_IRQ_REG(BD71828_INT_LONGPUSH, 2, BD71828_INT_LONGPUSH_MASK), 142 REGMAP_IRQ_REG(BD71828_INT_MIDPUSH, 2, BD71828_INT_MIDPUSH_MASK), 143 REGMAP_IRQ_REG(BD71828_INT_SHORTPUSH, 2, BD71828_INT_SHORTPUSH_MASK), 144 REGMAP_IRQ_REG(BD71828_INT_PUSH, 2, BD71828_INT_PUSH_MASK), 145 REGMAP_IRQ_REG(BD71828_INT_WDOG, 2, BD71828_INT_WDOG_MASK), 146 REGMAP_IRQ_REG(BD71828_INT_SWRESET, 2, BD71828_INT_SWRESET_MASK), 147 /* Vsys */ 148 REGMAP_IRQ_REG(BD71828_INT_VSYS_UV_RES, 3, 149 BD71828_INT_VSYS_UV_RES_MASK), 150 REGMAP_IRQ_REG(BD71828_INT_VSYS_UV_DET, 3, 151 BD71828_INT_VSYS_UV_DET_MASK), 152 REGMAP_IRQ_REG(BD71828_INT_VSYS_LOW_RES, 3, 153 BD71828_INT_VSYS_LOW_RES_MASK), 154 REGMAP_IRQ_REG(BD71828_INT_VSYS_LOW_DET, 3, 155 BD71828_INT_VSYS_LOW_DET_MASK), 156 REGMAP_IRQ_REG(BD71828_INT_VSYS_HALL_IN, 3, 157 BD71828_INT_VSYS_HALL_IN_MASK), 158 REGMAP_IRQ_REG(BD71828_INT_VSYS_HALL_TOGGLE, 3, 159 BD71828_INT_VSYS_HALL_TOGGLE_MASK), 160 REGMAP_IRQ_REG(BD71828_INT_VSYS_MON_RES, 3, 161 BD71828_INT_VSYS_MON_RES_MASK), 162 REGMAP_IRQ_REG(BD71828_INT_VSYS_MON_DET, 3, 163 BD71828_INT_VSYS_MON_DET_MASK), 164 /* Charger */ 165 REGMAP_IRQ_REG(BD71828_INT_CHG_DCIN_ILIM, 4, 166 BD71828_INT_CHG_DCIN_ILIM_MASK), 167 REGMAP_IRQ_REG(BD71828_INT_CHG_TOPOFF_TO_DONE, 4, 168 BD71828_INT_CHG_TOPOFF_TO_DONE_MASK), 169 REGMAP_IRQ_REG(BD71828_INT_CHG_WDG_TEMP, 4, 170 BD71828_INT_CHG_WDG_TEMP_MASK), 171 REGMAP_IRQ_REG(BD71828_INT_CHG_WDG_TIME, 4, 172 BD71828_INT_CHG_WDG_TIME_MASK), 173 REGMAP_IRQ_REG(BD71828_INT_CHG_RECHARGE_RES, 4, 174 BD71828_INT_CHG_RECHARGE_RES_MASK), 175 REGMAP_IRQ_REG(BD71828_INT_CHG_RECHARGE_DET, 4, 176 BD71828_INT_CHG_RECHARGE_DET_MASK), 177 REGMAP_IRQ_REG(BD71828_INT_CHG_RANGED_TEMP_TRANSITION, 4, 178 BD71828_INT_CHG_RANGED_TEMP_TRANSITION_MASK), 179 REGMAP_IRQ_REG(BD71828_INT_CHG_STATE_TRANSITION, 4, 180 BD71828_INT_CHG_STATE_TRANSITION_MASK), 181 /* Battery */ 182 REGMAP_IRQ_REG(BD71828_INT_BAT_TEMP_NORMAL, 5, 183 BD71828_INT_BAT_TEMP_NORMAL_MASK), 184 REGMAP_IRQ_REG(BD71828_INT_BAT_TEMP_ERANGE, 5, 185 BD71828_INT_BAT_TEMP_ERANGE_MASK), 186 REGMAP_IRQ_REG(BD71828_INT_BAT_TEMP_WARN, 5, 187 BD71828_INT_BAT_TEMP_WARN_MASK), 188 REGMAP_IRQ_REG(BD71828_INT_BAT_REMOVED, 5, 189 BD71828_INT_BAT_REMOVED_MASK), 190 REGMAP_IRQ_REG(BD71828_INT_BAT_DETECTED, 5, 191 BD71828_INT_BAT_DETECTED_MASK), 192 REGMAP_IRQ_REG(BD71828_INT_THERM_REMOVED, 5, 193 BD71828_INT_THERM_REMOVED_MASK), 194 REGMAP_IRQ_REG(BD71828_INT_THERM_DETECTED, 5, 195 BD71828_INT_THERM_DETECTED_MASK), 196 /* Battery Mon 1 */ 197 REGMAP_IRQ_REG(BD71828_INT_BAT_DEAD, 6, BD71828_INT_BAT_DEAD_MASK), 198 REGMAP_IRQ_REG(BD71828_INT_BAT_SHORTC_RES, 6, 199 BD71828_INT_BAT_SHORTC_RES_MASK), 200 REGMAP_IRQ_REG(BD71828_INT_BAT_SHORTC_DET, 6, 201 BD71828_INT_BAT_SHORTC_DET_MASK), 202 REGMAP_IRQ_REG(BD71828_INT_BAT_LOW_VOLT_RES, 6, 203 BD71828_INT_BAT_LOW_VOLT_RES_MASK), 204 REGMAP_IRQ_REG(BD71828_INT_BAT_LOW_VOLT_DET, 6, 205 BD71828_INT_BAT_LOW_VOLT_DET_MASK), 206 REGMAP_IRQ_REG(BD71828_INT_BAT_OVER_VOLT_RES, 6, 207 BD71828_INT_BAT_OVER_VOLT_RES_MASK), 208 REGMAP_IRQ_REG(BD71828_INT_BAT_OVER_VOLT_DET, 6, 209 BD71828_INT_BAT_OVER_VOLT_DET_MASK), 210 /* Battery Mon 2 */ 211 REGMAP_IRQ_REG(BD71828_INT_BAT_MON_RES, 7, 212 BD71828_INT_BAT_MON_RES_MASK), 213 REGMAP_IRQ_REG(BD71828_INT_BAT_MON_DET, 7, 214 BD71828_INT_BAT_MON_DET_MASK), 215 /* Battery Mon 3 (Coulomb counter) */ 216 REGMAP_IRQ_REG(BD71828_INT_BAT_CC_MON1, 8, 217 BD71828_INT_BAT_CC_MON1_MASK), 218 REGMAP_IRQ_REG(BD71828_INT_BAT_CC_MON2, 8, 219 BD71828_INT_BAT_CC_MON2_MASK), 220 REGMAP_IRQ_REG(BD71828_INT_BAT_CC_MON3, 8, 221 BD71828_INT_BAT_CC_MON3_MASK), 222 /* Battery Mon 4 */ 223 REGMAP_IRQ_REG(BD71828_INT_BAT_OVER_CURR_1_RES, 9, 224 BD71828_INT_BAT_OVER_CURR_1_RES_MASK), 225 REGMAP_IRQ_REG(BD71828_INT_BAT_OVER_CURR_1_DET, 9, 226 BD71828_INT_BAT_OVER_CURR_1_DET_MASK), 227 REGMAP_IRQ_REG(BD71828_INT_BAT_OVER_CURR_2_RES, 9, 228 BD71828_INT_BAT_OVER_CURR_2_RES_MASK), 229 REGMAP_IRQ_REG(BD71828_INT_BAT_OVER_CURR_2_DET, 9, 230 BD71828_INT_BAT_OVER_CURR_2_DET_MASK), 231 REGMAP_IRQ_REG(BD71828_INT_BAT_OVER_CURR_3_RES, 9, 232 BD71828_INT_BAT_OVER_CURR_3_RES_MASK), 233 REGMAP_IRQ_REG(BD71828_INT_BAT_OVER_CURR_3_DET, 9, 234 BD71828_INT_BAT_OVER_CURR_3_DET_MASK), 235 /* Temperature */ 236 REGMAP_IRQ_REG(BD71828_INT_TEMP_BAT_LOW_RES, 10, 237 BD71828_INT_TEMP_BAT_LOW_RES_MASK), 238 REGMAP_IRQ_REG(BD71828_INT_TEMP_BAT_LOW_DET, 10, 239 BD71828_INT_TEMP_BAT_LOW_DET_MASK), 240 REGMAP_IRQ_REG(BD71828_INT_TEMP_BAT_HI_RES, 10, 241 BD71828_INT_TEMP_BAT_HI_RES_MASK), 242 REGMAP_IRQ_REG(BD71828_INT_TEMP_BAT_HI_DET, 10, 243 BD71828_INT_TEMP_BAT_HI_DET_MASK), 244 REGMAP_IRQ_REG(BD71828_INT_TEMP_CHIP_OVER_125_RES, 10, 245 BD71828_INT_TEMP_CHIP_OVER_125_RES_MASK), 246 REGMAP_IRQ_REG(BD71828_INT_TEMP_CHIP_OVER_125_DET, 10, 247 BD71828_INT_TEMP_CHIP_OVER_125_DET_MASK), 248 REGMAP_IRQ_REG(BD71828_INT_TEMP_CHIP_OVER_VF_DET, 10, 249 BD71828_INT_TEMP_CHIP_OVER_VF_DET_MASK), 250 REGMAP_IRQ_REG(BD71828_INT_TEMP_CHIP_OVER_VF_RES, 10, 251 BD71828_INT_TEMP_CHIP_OVER_VF_RES_MASK), 252 /* RTC Alarm */ 253 REGMAP_IRQ_REG(BD71828_INT_RTC0, 11, BD71828_INT_RTC0_MASK), 254 REGMAP_IRQ_REG(BD71828_INT_RTC1, 11, BD71828_INT_RTC1_MASK), 255 REGMAP_IRQ_REG(BD71828_INT_RTC2, 11, BD71828_INT_RTC2_MASK), 256 }; 257 258 static struct regmap_irq_chip bd71828_irq_chip = { 259 .name = "bd71828_irq", 260 .main_status = BD71828_REG_INT_MAIN, 261 .irqs = &bd71828_irqs[0], 262 .num_irqs = ARRAY_SIZE(bd71828_irqs), 263 .status_base = BD71828_REG_INT_BUCK, 264 .mask_base = BD71828_REG_INT_MASK_BUCK, 265 .ack_base = BD71828_REG_INT_BUCK, 266 .mask_invert = true, 267 .init_ack_masked = true, 268 .num_regs = 12, 269 .num_main_regs = 1, 270 .sub_reg_offsets = &bd71828_sub_irq_offsets[0], 271 .num_main_status_bits = 8, 272 .irq_reg_stride = 1, 273 }; 274 275 static int bd71828_i2c_probe(struct i2c_client *i2c) 276 { 277 struct rohm_regmap_dev *chip; 278 struct regmap_irq_chip_data *irq_data; 279 int ret; 280 281 if (!i2c->irq) { 282 dev_err(&i2c->dev, "No IRQ configured\n"); 283 return -EINVAL; 284 } 285 286 chip = devm_kzalloc(&i2c->dev, sizeof(*chip), GFP_KERNEL); 287 if (!chip) 288 return -ENOMEM; 289 290 dev_set_drvdata(&i2c->dev, chip); 291 292 chip->regmap = devm_regmap_init_i2c(i2c, &bd71828_regmap); 293 if (IS_ERR(chip->regmap)) { 294 dev_err(&i2c->dev, "Failed to initialize Regmap\n"); 295 return PTR_ERR(chip->regmap); 296 } 297 298 ret = devm_regmap_add_irq_chip(&i2c->dev, chip->regmap, 299 i2c->irq, IRQF_ONESHOT, 0, 300 &bd71828_irq_chip, &irq_data); 301 if (ret) { 302 dev_err(&i2c->dev, "Failed to add IRQ chip\n"); 303 return ret; 304 } 305 306 dev_dbg(&i2c->dev, "Registered %d IRQs for chip\n", 307 bd71828_irq_chip.num_irqs); 308 309 ret = regmap_irq_get_virq(irq_data, BD71828_INT_SHORTPUSH); 310 if (ret < 0) { 311 dev_err(&i2c->dev, "Failed to get the power-key IRQ\n"); 312 return ret; 313 } 314 315 button.irq = ret; 316 317 ret = devm_mfd_add_devices(&i2c->dev, PLATFORM_DEVID_AUTO, 318 bd71828_mfd_cells, 319 ARRAY_SIZE(bd71828_mfd_cells), NULL, 0, 320 regmap_irq_get_domain(irq_data)); 321 if (ret) 322 dev_err(&i2c->dev, "Failed to create subdevices\n"); 323 324 return ret; 325 } 326 327 static const struct of_device_id bd71828_of_match[] = { 328 { .compatible = "rohm,bd71828", }, 329 { }, 330 }; 331 MODULE_DEVICE_TABLE(of, bd71828_of_match); 332 333 static struct i2c_driver bd71828_drv = { 334 .driver = { 335 .name = "rohm-bd71828", 336 .of_match_table = bd71828_of_match, 337 }, 338 .probe_new = &bd71828_i2c_probe, 339 }; 340 module_i2c_driver(bd71828_drv); 341 342 MODULE_AUTHOR("Matti Vaittinen <matti.vaittinen@fi.rohmeurope.com>"); 343 MODULE_DESCRIPTION("ROHM BD71828 Power Management IC driver"); 344 MODULE_LICENSE("GPL"); 345