458 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * Core driver for ams AS3722 PMICs4 *5 * Copyright (C) 2013 AMS AG6 * 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 0x0C25 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_MAPLE,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{338 struct as3722 *as3722;339 unsigned long irq_flags;340 int ret;341 u8 val = 0;342 343 as3722 = devm_kzalloc(&i2c->dev, sizeof(struct as3722), GFP_KERNEL);344 if (!as3722)345 return -ENOMEM;346 347 as3722->dev = &i2c->dev;348 as3722->chip_irq = i2c->irq;349 i2c_set_clientdata(i2c, as3722);350 351 ret = as3722_i2c_of_probe(i2c, as3722);352 if (ret < 0)353 return ret;354 355 as3722->regmap = devm_regmap_init_i2c(i2c, &as3722_regmap_config);356 if (IS_ERR(as3722->regmap)) {357 ret = PTR_ERR(as3722->regmap);358 dev_err(&i2c->dev, "regmap init failed: %d\n", ret);359 return ret;360 }361 362 ret = as3722_check_device_id(as3722);363 if (ret < 0)364 return ret;365 366 irq_flags = as3722->irq_flags | IRQF_ONESHOT;367 ret = devm_regmap_add_irq_chip(as3722->dev, as3722->regmap,368 as3722->chip_irq,369 irq_flags, -1, &as3722_irq_chip,370 &as3722->irq_data);371 if (ret < 0) {372 dev_err(as3722->dev, "Failed to add regmap irq: %d\n", ret);373 return ret;374 }375 376 ret = as3722_configure_pullups(as3722);377 if (ret < 0)378 return ret;379 380 if (as3722->en_ac_ok_pwr_on)381 val = AS3722_CTRL_SEQU1_AC_OK_PWR_ON;382 ret = as3722_update_bits(as3722, AS3722_CTRL_SEQU1_REG,383 AS3722_CTRL_SEQU1_AC_OK_PWR_ON, val);384 if (ret < 0) {385 dev_err(as3722->dev, "CTRLsequ1 update failed: %d\n", ret);386 return ret;387 }388 389 ret = devm_mfd_add_devices(&i2c->dev, -1, as3722_devs,390 ARRAY_SIZE(as3722_devs), NULL, 0,391 regmap_irq_get_domain(as3722->irq_data));392 if (ret) {393 dev_err(as3722->dev, "Failed to add MFD devices: %d\n", ret);394 return ret;395 }396 397 device_init_wakeup(as3722->dev, true);398 399 dev_dbg(as3722->dev, "AS3722 core driver initialized successfully\n");400 return 0;401}402 403static int __maybe_unused as3722_i2c_suspend(struct device *dev)404{405 struct as3722 *as3722 = dev_get_drvdata(dev);406 407 if (device_may_wakeup(dev))408 enable_irq_wake(as3722->chip_irq);409 disable_irq(as3722->chip_irq);410 411 return 0;412}413 414static int __maybe_unused as3722_i2c_resume(struct device *dev)415{416 struct as3722 *as3722 = dev_get_drvdata(dev);417 418 enable_irq(as3722->chip_irq);419 420 if (device_may_wakeup(dev))421 disable_irq_wake(as3722->chip_irq);422 423 return 0;424}425 426static const struct of_device_id as3722_of_match[] = {427 { .compatible = "ams,as3722", },428 {},429};430MODULE_DEVICE_TABLE(of, as3722_of_match);431 432static const struct i2c_device_id as3722_i2c_id[] = {433 { "as3722" },434 {}435};436MODULE_DEVICE_TABLE(i2c, as3722_i2c_id);437 438static const struct dev_pm_ops as3722_pm_ops = {439 SET_SYSTEM_SLEEP_PM_OPS(as3722_i2c_suspend, as3722_i2c_resume)440};441 442static struct i2c_driver as3722_i2c_driver = {443 .driver = {444 .name = "as3722",445 .of_match_table = as3722_of_match,446 .pm = &as3722_pm_ops,447 },448 .probe = as3722_i2c_probe,449 .id_table = as3722_i2c_id,450};451 452module_i2c_driver(as3722_i2c_driver);453 454MODULE_DESCRIPTION("I2C support for AS3722 PMICs");455MODULE_AUTHOR("Florian Lobmaier <florian.lobmaier@ams.com>");456MODULE_AUTHOR("Laxman Dewangan <ldewangan@nvidia.com>");457MODULE_LICENSE("GPL");458