as3722.c (12304B)
1// SPDX-License-Identifier: GPL-2.0-or-later 2/* 3 * Core driver for ams AS3722 PMICs 4 * 5 * Copyright (C) 2013 AMS AG 6 * Copyright (c) 2013, NVIDIA Corporation. All rights reserved. 7 * 8 * Author: Florian Lobmaier <florian.lobmaier@ams.com> 9 * Author: Laxman Dewangan <ldewangan@nvidia.com> 10 */ 11 12#include <linux/err.h> 13#include <linux/i2c.h> 14#include <linux/interrupt.h> 15#include <linux/irq.h> 16#include <linux/kernel.h> 17#include <linux/module.h> 18#include <linux/mfd/core.h> 19#include <linux/mfd/as3722.h> 20#include <linux/of.h> 21#include <linux/regmap.h> 22#include <linux/slab.h> 23 24#define AS3722_DEVICE_ID 0x0C 25 26static const struct resource as3722_rtc_resource[] = { 27 DEFINE_RES_IRQ_NAMED(AS3722_IRQ_RTC_ALARM, "as3722-rtc-alarm"), 28}; 29 30static const struct resource as3722_adc_resource[] = { 31 DEFINE_RES_IRQ_NAMED(AS3722_IRQ_ADC, "as3722-adc"), 32}; 33 34static const struct mfd_cell as3722_devs[] = { 35 { 36 .name = "as3722-pinctrl", 37 }, 38 { 39 .name = "as3722-regulator", 40 }, 41 { 42 .name = "as3722-rtc", 43 .num_resources = ARRAY_SIZE(as3722_rtc_resource), 44 .resources = as3722_rtc_resource, 45 }, 46 { 47 .name = "as3722-adc", 48 .num_resources = ARRAY_SIZE(as3722_adc_resource), 49 .resources = as3722_adc_resource, 50 }, 51 { 52 .name = "as3722-power-off", 53 }, 54 { 55 .name = "as3722-wdt", 56 }, 57}; 58 59static const struct regmap_irq as3722_irqs[] = { 60 /* INT1 IRQs */ 61 [AS3722_IRQ_LID] = { 62 .mask = AS3722_INTERRUPT_MASK1_LID, 63 }, 64 [AS3722_IRQ_ACOK] = { 65 .mask = AS3722_INTERRUPT_MASK1_ACOK, 66 }, 67 [AS3722_IRQ_ENABLE1] = { 68 .mask = AS3722_INTERRUPT_MASK1_ENABLE1, 69 }, 70 [AS3722_IRQ_OCCUR_ALARM_SD0] = { 71 .mask = AS3722_INTERRUPT_MASK1_OCURR_ALARM_SD0, 72 }, 73 [AS3722_IRQ_ONKEY_LONG_PRESS] = { 74 .mask = AS3722_INTERRUPT_MASK1_ONKEY_LONG, 75 }, 76 [AS3722_IRQ_ONKEY] = { 77 .mask = AS3722_INTERRUPT_MASK1_ONKEY, 78 }, 79 [AS3722_IRQ_OVTMP] = { 80 .mask = AS3722_INTERRUPT_MASK1_OVTMP, 81 }, 82 [AS3722_IRQ_LOWBAT] = { 83 .mask = AS3722_INTERRUPT_MASK1_LOWBAT, 84 }, 85 86 /* INT2 IRQs */ 87 [AS3722_IRQ_SD0_LV] = { 88 .mask = AS3722_INTERRUPT_MASK2_SD0_LV, 89 .reg_offset = 1, 90 }, 91 [AS3722_IRQ_SD1_LV] = { 92 .mask = AS3722_INTERRUPT_MASK2_SD1_LV, 93 .reg_offset = 1, 94 }, 95 [AS3722_IRQ_SD2_LV] = { 96 .mask = AS3722_INTERRUPT_MASK2_SD2345_LV, 97 .reg_offset = 1, 98 }, 99 [AS3722_IRQ_PWM1_OV_PROT] = { 100 .mask = AS3722_INTERRUPT_MASK2_PWM1_OV_PROT, 101 .reg_offset = 1, 102 }, 103 [AS3722_IRQ_PWM2_OV_PROT] = { 104 .mask = AS3722_INTERRUPT_MASK2_PWM2_OV_PROT, 105 .reg_offset = 1, 106 }, 107 [AS3722_IRQ_ENABLE2] = { 108 .mask = AS3722_INTERRUPT_MASK2_ENABLE2, 109 .reg_offset = 1, 110 }, 111 [AS3722_IRQ_SD6_LV] = { 112 .mask = AS3722_INTERRUPT_MASK2_SD6_LV, 113 .reg_offset = 1, 114 }, 115 [AS3722_IRQ_RTC_REP] = { 116 .mask = AS3722_INTERRUPT_MASK2_RTC_REP, 117 .reg_offset = 1, 118 }, 119 120 /* INT3 IRQs */ 121 [AS3722_IRQ_RTC_ALARM] = { 122 .mask = AS3722_INTERRUPT_MASK3_RTC_ALARM, 123 .reg_offset = 2, 124 }, 125 [AS3722_IRQ_GPIO1] = { 126 .mask = AS3722_INTERRUPT_MASK3_GPIO1, 127 .reg_offset = 2, 128 }, 129 [AS3722_IRQ_GPIO2] = { 130 .mask = AS3722_INTERRUPT_MASK3_GPIO2, 131 .reg_offset = 2, 132 }, 133 [AS3722_IRQ_GPIO3] = { 134 .mask = AS3722_INTERRUPT_MASK3_GPIO3, 135 .reg_offset = 2, 136 }, 137 [AS3722_IRQ_GPIO4] = { 138 .mask = AS3722_INTERRUPT_MASK3_GPIO4, 139 .reg_offset = 2, 140 }, 141 [AS3722_IRQ_GPIO5] = { 142 .mask = AS3722_INTERRUPT_MASK3_GPIO5, 143 .reg_offset = 2, 144 }, 145 [AS3722_IRQ_WATCHDOG] = { 146 .mask = AS3722_INTERRUPT_MASK3_WATCHDOG, 147 .reg_offset = 2, 148 }, 149 [AS3722_IRQ_ENABLE3] = { 150 .mask = AS3722_INTERRUPT_MASK3_ENABLE3, 151 .reg_offset = 2, 152 }, 153 154 /* INT4 IRQs */ 155 [AS3722_IRQ_TEMP_SD0_SHUTDOWN] = { 156 .mask = AS3722_INTERRUPT_MASK4_TEMP_SD0_SHUTDOWN, 157 .reg_offset = 3, 158 }, 159 [AS3722_IRQ_TEMP_SD1_SHUTDOWN] = { 160 .mask = AS3722_INTERRUPT_MASK4_TEMP_SD1_SHUTDOWN, 161 .reg_offset = 3, 162 }, 163 [AS3722_IRQ_TEMP_SD2_SHUTDOWN] = { 164 .mask = AS3722_INTERRUPT_MASK4_TEMP_SD6_SHUTDOWN, 165 .reg_offset = 3, 166 }, 167 [AS3722_IRQ_TEMP_SD0_ALARM] = { 168 .mask = AS3722_INTERRUPT_MASK4_TEMP_SD0_ALARM, 169 .reg_offset = 3, 170 }, 171 [AS3722_IRQ_TEMP_SD1_ALARM] = { 172 .mask = AS3722_INTERRUPT_MASK4_TEMP_SD1_ALARM, 173 .reg_offset = 3, 174 }, 175 [AS3722_IRQ_TEMP_SD6_ALARM] = { 176 .mask = AS3722_INTERRUPT_MASK4_TEMP_SD6_ALARM, 177 .reg_offset = 3, 178 }, 179 [AS3722_IRQ_OCCUR_ALARM_SD6] = { 180 .mask = AS3722_INTERRUPT_MASK4_OCCUR_ALARM_SD6, 181 .reg_offset = 3, 182 }, 183 [AS3722_IRQ_ADC] = { 184 .mask = AS3722_INTERRUPT_MASK4_ADC, 185 .reg_offset = 3, 186 }, 187}; 188 189static const struct regmap_irq_chip as3722_irq_chip = { 190 .name = "as3722", 191 .irqs = as3722_irqs, 192 .num_irqs = ARRAY_SIZE(as3722_irqs), 193 .num_regs = 4, 194 .status_base = AS3722_INTERRUPT_STATUS1_REG, 195 .mask_base = AS3722_INTERRUPT_MASK1_REG, 196}; 197 198static int as3722_check_device_id(struct as3722 *as3722) 199{ 200 u32 val; 201 int ret; 202 203 /* Check that this is actually a AS3722 */ 204 ret = as3722_read(as3722, AS3722_ASIC_ID1_REG, &val); 205 if (ret < 0) { 206 dev_err(as3722->dev, "ASIC_ID1 read failed: %d\n", ret); 207 return ret; 208 } 209 210 if (val != AS3722_DEVICE_ID) { 211 dev_err(as3722->dev, "Device is not AS3722, ID is 0x%x\n", val); 212 return -ENODEV; 213 } 214 215 ret = as3722_read(as3722, AS3722_ASIC_ID2_REG, &val); 216 if (ret < 0) { 217 dev_err(as3722->dev, "ASIC_ID2 read failed: %d\n", ret); 218 return ret; 219 } 220 221 dev_info(as3722->dev, "AS3722 with revision 0x%x found\n", val); 222 return 0; 223} 224 225static int as3722_configure_pullups(struct as3722 *as3722) 226{ 227 int ret; 228 u32 val = 0; 229 230 if (as3722->en_intern_int_pullup) 231 val |= AS3722_INT_PULL_UP; 232 if (as3722->en_intern_i2c_pullup) 233 val |= AS3722_I2C_PULL_UP; 234 235 ret = as3722_update_bits(as3722, AS3722_IOVOLTAGE_REG, 236 AS3722_INT_PULL_UP | AS3722_I2C_PULL_UP, val); 237 if (ret < 0) 238 dev_err(as3722->dev, "IOVOLTAGE_REG update failed: %d\n", ret); 239 return ret; 240} 241 242static const struct regmap_range as3722_readable_ranges[] = { 243 regmap_reg_range(AS3722_SD0_VOLTAGE_REG, AS3722_SD6_VOLTAGE_REG), 244 regmap_reg_range(AS3722_GPIO0_CONTROL_REG, AS3722_LDO7_VOLTAGE_REG), 245 regmap_reg_range(AS3722_LDO9_VOLTAGE_REG, AS3722_REG_SEQU_MOD3_REG), 246 regmap_reg_range(AS3722_SD_PHSW_CTRL_REG, AS3722_PWM_CONTROL_H_REG), 247 regmap_reg_range(AS3722_WATCHDOG_TIMER_REG, AS3722_WATCHDOG_TIMER_REG), 248 regmap_reg_range(AS3722_WATCHDOG_SOFTWARE_SIGNAL_REG, 249 AS3722_BATTERY_VOLTAGE_MONITOR2_REG), 250 regmap_reg_range(AS3722_SD_CONTROL_REG, AS3722_PWM_VCONTROL4_REG), 251 regmap_reg_range(AS3722_BB_CHARGER_REG, AS3722_SRAM_REG), 252 regmap_reg_range(AS3722_RTC_ACCESS_REG, AS3722_RTC_ACCESS_REG), 253 regmap_reg_range(AS3722_RTC_STATUS_REG, AS3722_TEMP_STATUS_REG), 254 regmap_reg_range(AS3722_ADC0_CONTROL_REG, AS3722_ADC_CONFIGURATION_REG), 255 regmap_reg_range(AS3722_ASIC_ID1_REG, AS3722_ASIC_ID2_REG), 256 regmap_reg_range(AS3722_LOCK_REG, AS3722_LOCK_REG), 257 regmap_reg_range(AS3722_FUSE7_REG, AS3722_FUSE7_REG), 258}; 259 260static const struct regmap_access_table as3722_readable_table = { 261 .yes_ranges = as3722_readable_ranges, 262 .n_yes_ranges = ARRAY_SIZE(as3722_readable_ranges), 263}; 264 265static const struct regmap_range as3722_writable_ranges[] = { 266 regmap_reg_range(AS3722_SD0_VOLTAGE_REG, AS3722_SD6_VOLTAGE_REG), 267 regmap_reg_range(AS3722_GPIO0_CONTROL_REG, AS3722_LDO7_VOLTAGE_REG), 268 regmap_reg_range(AS3722_LDO9_VOLTAGE_REG, AS3722_GPIO_SIGNAL_OUT_REG), 269 regmap_reg_range(AS3722_REG_SEQU_MOD1_REG, AS3722_REG_SEQU_MOD3_REG), 270 regmap_reg_range(AS3722_SD_PHSW_CTRL_REG, AS3722_PWM_CONTROL_H_REG), 271 regmap_reg_range(AS3722_WATCHDOG_TIMER_REG, AS3722_WATCHDOG_TIMER_REG), 272 regmap_reg_range(AS3722_WATCHDOG_SOFTWARE_SIGNAL_REG, 273 AS3722_BATTERY_VOLTAGE_MONITOR2_REG), 274 regmap_reg_range(AS3722_SD_CONTROL_REG, AS3722_PWM_VCONTROL4_REG), 275 regmap_reg_range(AS3722_BB_CHARGER_REG, AS3722_SRAM_REG), 276 regmap_reg_range(AS3722_INTERRUPT_MASK1_REG, AS3722_TEMP_STATUS_REG), 277 regmap_reg_range(AS3722_ADC0_CONTROL_REG, AS3722_ADC1_CONTROL_REG), 278 regmap_reg_range(AS3722_ADC1_THRESHOLD_HI_MSB_REG, 279 AS3722_ADC_CONFIGURATION_REG), 280 regmap_reg_range(AS3722_LOCK_REG, AS3722_LOCK_REG), 281}; 282 283static const struct regmap_access_table as3722_writable_table = { 284 .yes_ranges = as3722_writable_ranges, 285 .n_yes_ranges = ARRAY_SIZE(as3722_writable_ranges), 286}; 287 288static const struct regmap_range as3722_cacheable_ranges[] = { 289 regmap_reg_range(AS3722_SD0_VOLTAGE_REG, AS3722_LDO11_VOLTAGE_REG), 290 regmap_reg_range(AS3722_SD_CONTROL_REG, AS3722_LDOCONTROL1_REG), 291}; 292 293static const struct regmap_access_table as3722_volatile_table = { 294 .no_ranges = as3722_cacheable_ranges, 295 .n_no_ranges = ARRAY_SIZE(as3722_cacheable_ranges), 296}; 297 298static const struct regmap_config as3722_regmap_config = { 299 .reg_bits = 8, 300 .val_bits = 8, 301 .max_register = AS3722_MAX_REGISTER, 302 .cache_type = REGCACHE_RBTREE, 303 .rd_table = &as3722_readable_table, 304 .wr_table = &as3722_writable_table, 305 .volatile_table = &as3722_volatile_table, 306}; 307 308static int as3722_i2c_of_probe(struct i2c_client *i2c, 309 struct as3722 *as3722) 310{ 311 struct device_node *np = i2c->dev.of_node; 312 struct irq_data *irq_data; 313 314 if (!np) { 315 dev_err(&i2c->dev, "Device Tree not found\n"); 316 return -EINVAL; 317 } 318 319 irq_data = irq_get_irq_data(i2c->irq); 320 if (!irq_data) { 321 dev_err(&i2c->dev, "Invalid IRQ: %d\n", i2c->irq); 322 return -EINVAL; 323 } 324 325 as3722->en_intern_int_pullup = of_property_read_bool(np, 326 "ams,enable-internal-int-pullup"); 327 as3722->en_intern_i2c_pullup = of_property_read_bool(np, 328 "ams,enable-internal-i2c-pullup"); 329 as3722->en_ac_ok_pwr_on = of_property_read_bool(np, 330 "ams,enable-ac-ok-power-on"); 331 as3722->irq_flags = irqd_get_trigger_type(irq_data); 332 dev_dbg(&i2c->dev, "IRQ flags are 0x%08lx\n", as3722->irq_flags); 333 return 0; 334} 335 336static int as3722_i2c_probe(struct i2c_client *i2c, 337 const struct i2c_device_id *id) 338{ 339 struct as3722 *as3722; 340 unsigned long irq_flags; 341 int ret; 342 u8 val = 0; 343 344 as3722 = devm_kzalloc(&i2c->dev, sizeof(struct as3722), GFP_KERNEL); 345 if (!as3722) 346 return -ENOMEM; 347 348 as3722->dev = &i2c->dev; 349 as3722->chip_irq = i2c->irq; 350 i2c_set_clientdata(i2c, as3722); 351 352 ret = as3722_i2c_of_probe(i2c, as3722); 353 if (ret < 0) 354 return ret; 355 356 as3722->regmap = devm_regmap_init_i2c(i2c, &as3722_regmap_config); 357 if (IS_ERR(as3722->regmap)) { 358 ret = PTR_ERR(as3722->regmap); 359 dev_err(&i2c->dev, "regmap init failed: %d\n", ret); 360 return ret; 361 } 362 363 ret = as3722_check_device_id(as3722); 364 if (ret < 0) 365 return ret; 366 367 irq_flags = as3722->irq_flags | IRQF_ONESHOT; 368 ret = devm_regmap_add_irq_chip(as3722->dev, as3722->regmap, 369 as3722->chip_irq, 370 irq_flags, -1, &as3722_irq_chip, 371 &as3722->irq_data); 372 if (ret < 0) { 373 dev_err(as3722->dev, "Failed to add regmap irq: %d\n", ret); 374 return ret; 375 } 376 377 ret = as3722_configure_pullups(as3722); 378 if (ret < 0) 379 return ret; 380 381 if (as3722->en_ac_ok_pwr_on) 382 val = AS3722_CTRL_SEQU1_AC_OK_PWR_ON; 383 ret = as3722_update_bits(as3722, AS3722_CTRL_SEQU1_REG, 384 AS3722_CTRL_SEQU1_AC_OK_PWR_ON, val); 385 if (ret < 0) { 386 dev_err(as3722->dev, "CTRLsequ1 update failed: %d\n", ret); 387 return ret; 388 } 389 390 ret = devm_mfd_add_devices(&i2c->dev, -1, as3722_devs, 391 ARRAY_SIZE(as3722_devs), NULL, 0, 392 regmap_irq_get_domain(as3722->irq_data)); 393 if (ret) { 394 dev_err(as3722->dev, "Failed to add MFD devices: %d\n", ret); 395 return ret; 396 } 397 398 device_init_wakeup(as3722->dev, true); 399 400 dev_dbg(as3722->dev, "AS3722 core driver initialized successfully\n"); 401 return 0; 402} 403 404static int __maybe_unused as3722_i2c_suspend(struct device *dev) 405{ 406 struct as3722 *as3722 = dev_get_drvdata(dev); 407 408 if (device_may_wakeup(dev)) 409 enable_irq_wake(as3722->chip_irq); 410 disable_irq(as3722->chip_irq); 411 412 return 0; 413} 414 415static int __maybe_unused as3722_i2c_resume(struct device *dev) 416{ 417 struct as3722 *as3722 = dev_get_drvdata(dev); 418 419 enable_irq(as3722->chip_irq); 420 421 if (device_may_wakeup(dev)) 422 disable_irq_wake(as3722->chip_irq); 423 424 return 0; 425} 426 427static const struct of_device_id as3722_of_match[] = { 428 { .compatible = "ams,as3722", }, 429 {}, 430}; 431MODULE_DEVICE_TABLE(of, as3722_of_match); 432 433static const struct i2c_device_id as3722_i2c_id[] = { 434 { "as3722", 0 }, 435 {}, 436}; 437MODULE_DEVICE_TABLE(i2c, as3722_i2c_id); 438 439static const struct dev_pm_ops as3722_pm_ops = { 440 SET_SYSTEM_SLEEP_PM_OPS(as3722_i2c_suspend, as3722_i2c_resume) 441}; 442 443static struct i2c_driver as3722_i2c_driver = { 444 .driver = { 445 .name = "as3722", 446 .of_match_table = as3722_of_match, 447 .pm = &as3722_pm_ops, 448 }, 449 .probe = as3722_i2c_probe, 450 .id_table = as3722_i2c_id, 451}; 452 453module_i2c_driver(as3722_i2c_driver); 454 455MODULE_DESCRIPTION("I2C support for AS3722 PMICs"); 456MODULE_AUTHOR("Florian Lobmaier <florian.lobmaier@ams.com>"); 457MODULE_AUTHOR("Laxman Dewangan <ldewangan@nvidia.com>"); 458MODULE_LICENSE("GPL");