477 lines · c
1// SPDX-License-Identifier: GPL-2.0+2/* I2C support for Dialog DA90633 *4 * Copyright 2012 Dialog Semiconductor Ltd.5 * Copyright 2013 Philipp Zabel, Pengutronix6 *7 * Author: Krystian Garbaciak, Dialog Semiconductor8 */9 10#include <linux/kernel.h>11#include <linux/module.h>12#include <linux/i2c.h>13#include <linux/regmap.h>14#include <linux/delay.h>15#include <linux/slab.h>16#include <linux/err.h>17 18#include <linux/mfd/core.h>19#include <linux/mfd/da9063/core.h>20#include <linux/mfd/da9063/registers.h>21 22#include <linux/of.h>23#include <linux/regulator/of_regulator.h>24 25/*26 * Raw I2C access required for just accessing chip and variant info before we27 * know which device is present. The info read from the device using this28 * approach is then used to select the correct regmap tables.29 */30 31#define DA9063_REG_PAGE_SIZE 0x10032#define DA9063_REG_PAGED_ADDR_MASK 0xFF33 34enum da9063_page_sel_buf_fmt {35 DA9063_PAGE_SEL_BUF_PAGE_REG = 0,36 DA9063_PAGE_SEL_BUF_PAGE_VAL,37 DA9063_PAGE_SEL_BUF_SIZE,38};39 40enum da9063_paged_read_msgs {41 DA9063_PAGED_READ_MSG_PAGE_SEL = 0,42 DA9063_PAGED_READ_MSG_REG_SEL,43 DA9063_PAGED_READ_MSG_DATA,44 DA9063_PAGED_READ_MSG_CNT,45};46 47static int da9063_i2c_blockreg_read(struct i2c_client *client, u16 addr,48 u8 *buf, int count)49{50 struct i2c_msg xfer[DA9063_PAGED_READ_MSG_CNT];51 u8 page_sel_buf[DA9063_PAGE_SEL_BUF_SIZE];52 u8 page_num, paged_addr;53 int ret;54 55 /* Determine page info based on register address */56 page_num = (addr / DA9063_REG_PAGE_SIZE);57 if (page_num > 1) {58 dev_err(&client->dev, "Invalid register address provided\n");59 return -EINVAL;60 }61 62 paged_addr = (addr % DA9063_REG_PAGE_SIZE) & DA9063_REG_PAGED_ADDR_MASK;63 page_sel_buf[DA9063_PAGE_SEL_BUF_PAGE_REG] = DA9063_REG_PAGE_CON;64 page_sel_buf[DA9063_PAGE_SEL_BUF_PAGE_VAL] =65 (page_num << DA9063_I2C_PAGE_SEL_SHIFT) & DA9063_REG_PAGE_MASK;66 67 /* Write reg address, page selection */68 xfer[DA9063_PAGED_READ_MSG_PAGE_SEL].addr = client->addr;69 xfer[DA9063_PAGED_READ_MSG_PAGE_SEL].flags = 0;70 xfer[DA9063_PAGED_READ_MSG_PAGE_SEL].len = DA9063_PAGE_SEL_BUF_SIZE;71 xfer[DA9063_PAGED_READ_MSG_PAGE_SEL].buf = page_sel_buf;72 73 /* Select register address */74 xfer[DA9063_PAGED_READ_MSG_REG_SEL].addr = client->addr;75 xfer[DA9063_PAGED_READ_MSG_REG_SEL].flags = 0;76 xfer[DA9063_PAGED_READ_MSG_REG_SEL].len = sizeof(paged_addr);77 xfer[DA9063_PAGED_READ_MSG_REG_SEL].buf = &paged_addr;78 79 /* Read data */80 xfer[DA9063_PAGED_READ_MSG_DATA].addr = client->addr;81 xfer[DA9063_PAGED_READ_MSG_DATA].flags = I2C_M_RD;82 xfer[DA9063_PAGED_READ_MSG_DATA].len = count;83 xfer[DA9063_PAGED_READ_MSG_DATA].buf = buf;84 85 ret = i2c_transfer(client->adapter, xfer, DA9063_PAGED_READ_MSG_CNT);86 if (ret < 0) {87 dev_err(&client->dev, "Paged block read failed: %d\n", ret);88 return ret;89 }90 91 if (ret != DA9063_PAGED_READ_MSG_CNT) {92 dev_err(&client->dev, "Paged block read failed to complete\n");93 return -EIO;94 }95 96 return 0;97}98 99enum {100 DA9063_DEV_ID_REG = 0,101 DA9063_VAR_ID_REG,102 DA9063_CHIP_ID_REGS,103};104 105static int da9063_get_device_type(struct i2c_client *i2c, struct da9063 *da9063)106{107 u8 buf[DA9063_CHIP_ID_REGS];108 int ret;109 110 ret = da9063_i2c_blockreg_read(i2c, DA9063_REG_DEVICE_ID, buf,111 DA9063_CHIP_ID_REGS);112 if (ret)113 return ret;114 115 if (buf[DA9063_DEV_ID_REG] != PMIC_CHIP_ID_DA9063) {116 dev_err(da9063->dev,117 "Invalid chip device ID: 0x%02x\n",118 buf[DA9063_DEV_ID_REG]);119 return -ENODEV;120 }121 122 dev_info(da9063->dev,123 "Device detected (chip-ID: 0x%02X, var-ID: 0x%02X)\n",124 buf[DA9063_DEV_ID_REG], buf[DA9063_VAR_ID_REG]);125 126 da9063->variant_code =127 (buf[DA9063_VAR_ID_REG] & DA9063_VARIANT_ID_MRC_MASK)128 >> DA9063_VARIANT_ID_MRC_SHIFT;129 130 return 0;131}132 133/*134 * Variant specific regmap configs135 */136 137static const struct regmap_range da9063_ad_readable_ranges[] = {138 regmap_reg_range(DA9063_REG_PAGE_CON, DA9063_AD_REG_SECOND_D),139 regmap_reg_range(DA9063_REG_SEQ, DA9063_REG_ID_32_31),140 regmap_reg_range(DA9063_REG_SEQ_A, DA9063_REG_AUTO3_LOW),141 regmap_reg_range(DA9063_REG_T_OFFSET, DA9063_AD_REG_GP_ID_19),142 regmap_reg_range(DA9063_REG_DEVICE_ID, DA9063_REG_VARIANT_ID),143};144 145static const struct regmap_range da9063_ad_writeable_ranges[] = {146 regmap_reg_range(DA9063_REG_PAGE_CON, DA9063_REG_PAGE_CON),147 regmap_reg_range(DA9063_REG_FAULT_LOG, DA9063_REG_VSYS_MON),148 regmap_reg_range(DA9063_REG_COUNT_S, DA9063_AD_REG_ALARM_Y),149 regmap_reg_range(DA9063_REG_SEQ, DA9063_REG_ID_32_31),150 regmap_reg_range(DA9063_REG_SEQ_A, DA9063_REG_AUTO3_LOW),151 regmap_reg_range(DA9063_REG_CONFIG_I, DA9063_AD_REG_MON_REG_4),152 regmap_reg_range(DA9063_AD_REG_GP_ID_0, DA9063_AD_REG_GP_ID_19),153};154 155static const struct regmap_range da9063_ad_volatile_ranges[] = {156 regmap_reg_range(DA9063_REG_PAGE_CON, DA9063_REG_EVENT_D),157 regmap_reg_range(DA9063_REG_CONTROL_A, DA9063_REG_CONTROL_B),158 regmap_reg_range(DA9063_REG_CONTROL_E, DA9063_REG_CONTROL_F),159 regmap_reg_range(DA9063_REG_BCORE2_CONT, DA9063_REG_LDO11_CONT),160 regmap_reg_range(DA9063_REG_DVC_1, DA9063_REG_ADC_MAN),161 regmap_reg_range(DA9063_REG_ADC_RES_L, DA9063_AD_REG_SECOND_D),162 regmap_reg_range(DA9063_REG_SEQ, DA9063_REG_SEQ),163 regmap_reg_range(DA9063_REG_EN_32K, DA9063_REG_EN_32K),164 regmap_reg_range(DA9063_AD_REG_MON_REG_5, DA9063_AD_REG_MON_REG_6),165};166 167static const struct regmap_access_table da9063_ad_readable_table = {168 .yes_ranges = da9063_ad_readable_ranges,169 .n_yes_ranges = ARRAY_SIZE(da9063_ad_readable_ranges),170};171 172static const struct regmap_access_table da9063_ad_writeable_table = {173 .yes_ranges = da9063_ad_writeable_ranges,174 .n_yes_ranges = ARRAY_SIZE(da9063_ad_writeable_ranges),175};176 177static const struct regmap_access_table da9063_ad_volatile_table = {178 .yes_ranges = da9063_ad_volatile_ranges,179 .n_yes_ranges = ARRAY_SIZE(da9063_ad_volatile_ranges),180};181 182static const struct regmap_range da9063_bb_readable_ranges[] = {183 regmap_reg_range(DA9063_REG_PAGE_CON, DA9063_BB_REG_SECOND_D),184 regmap_reg_range(DA9063_REG_SEQ, DA9063_REG_ID_32_31),185 regmap_reg_range(DA9063_REG_SEQ_A, DA9063_REG_AUTO3_LOW),186 regmap_reg_range(DA9063_REG_T_OFFSET, DA9063_BB_REG_GP_ID_19),187 regmap_reg_range(DA9063_REG_DEVICE_ID, DA9063_REG_VARIANT_ID),188};189 190static const struct regmap_range da9063_bb_writeable_ranges[] = {191 regmap_reg_range(DA9063_REG_PAGE_CON, DA9063_REG_PAGE_CON),192 regmap_reg_range(DA9063_REG_FAULT_LOG, DA9063_REG_VSYS_MON),193 regmap_reg_range(DA9063_REG_COUNT_S, DA9063_BB_REG_ALARM_Y),194 regmap_reg_range(DA9063_REG_SEQ, DA9063_REG_ID_32_31),195 regmap_reg_range(DA9063_REG_SEQ_A, DA9063_REG_AUTO3_LOW),196 regmap_reg_range(DA9063_REG_CONFIG_I, DA9063_BB_REG_MON_REG_4),197 regmap_reg_range(DA9063_BB_REG_GP_ID_0, DA9063_BB_REG_GP_ID_19),198};199 200static const struct regmap_range da9063_bb_da_volatile_ranges[] = {201 regmap_reg_range(DA9063_REG_PAGE_CON, DA9063_REG_EVENT_D),202 regmap_reg_range(DA9063_REG_CONTROL_A, DA9063_REG_CONTROL_B),203 regmap_reg_range(DA9063_REG_CONTROL_E, DA9063_REG_CONTROL_F),204 regmap_reg_range(DA9063_REG_BCORE2_CONT, DA9063_REG_LDO11_CONT),205 regmap_reg_range(DA9063_REG_DVC_1, DA9063_REG_ADC_MAN),206 regmap_reg_range(DA9063_REG_ADC_RES_L, DA9063_BB_REG_SECOND_D),207 regmap_reg_range(DA9063_REG_SEQ, DA9063_REG_SEQ),208 regmap_reg_range(DA9063_REG_EN_32K, DA9063_REG_EN_32K),209 regmap_reg_range(DA9063_BB_REG_MON_REG_5, DA9063_BB_REG_MON_REG_6),210};211 212static const struct regmap_access_table da9063_bb_readable_table = {213 .yes_ranges = da9063_bb_readable_ranges,214 .n_yes_ranges = ARRAY_SIZE(da9063_bb_readable_ranges),215};216 217static const struct regmap_access_table da9063_bb_writeable_table = {218 .yes_ranges = da9063_bb_writeable_ranges,219 .n_yes_ranges = ARRAY_SIZE(da9063_bb_writeable_ranges),220};221 222static const struct regmap_access_table da9063_bb_da_volatile_table = {223 .yes_ranges = da9063_bb_da_volatile_ranges,224 .n_yes_ranges = ARRAY_SIZE(da9063_bb_da_volatile_ranges),225};226 227static const struct regmap_range da9063l_bb_readable_ranges[] = {228 regmap_reg_range(DA9063_REG_PAGE_CON, DA9063_REG_MON_A10_RES),229 regmap_reg_range(DA9063_REG_SEQ, DA9063_REG_ID_32_31),230 regmap_reg_range(DA9063_REG_SEQ_A, DA9063_REG_AUTO3_LOW),231 regmap_reg_range(DA9063_REG_T_OFFSET, DA9063_BB_REG_GP_ID_19),232 regmap_reg_range(DA9063_REG_DEVICE_ID, DA9063_REG_VARIANT_ID),233};234 235static const struct regmap_range da9063l_bb_writeable_ranges[] = {236 regmap_reg_range(DA9063_REG_PAGE_CON, DA9063_REG_PAGE_CON),237 regmap_reg_range(DA9063_REG_FAULT_LOG, DA9063_REG_VSYS_MON),238 regmap_reg_range(DA9063_REG_SEQ, DA9063_REG_ID_32_31),239 regmap_reg_range(DA9063_REG_SEQ_A, DA9063_REG_AUTO3_LOW),240 regmap_reg_range(DA9063_REG_CONFIG_I, DA9063_BB_REG_MON_REG_4),241 regmap_reg_range(DA9063_BB_REG_GP_ID_0, DA9063_BB_REG_GP_ID_19),242};243 244static const struct regmap_range da9063l_bb_da_volatile_ranges[] = {245 regmap_reg_range(DA9063_REG_PAGE_CON, DA9063_REG_EVENT_D),246 regmap_reg_range(DA9063_REG_CONTROL_A, DA9063_REG_CONTROL_B),247 regmap_reg_range(DA9063_REG_CONTROL_E, DA9063_REG_CONTROL_F),248 regmap_reg_range(DA9063_REG_BCORE2_CONT, DA9063_REG_LDO11_CONT),249 regmap_reg_range(DA9063_REG_DVC_1, DA9063_REG_ADC_MAN),250 regmap_reg_range(DA9063_REG_ADC_RES_L, DA9063_REG_MON_A10_RES),251 regmap_reg_range(DA9063_REG_SEQ, DA9063_REG_SEQ),252 regmap_reg_range(DA9063_REG_EN_32K, DA9063_REG_EN_32K),253 regmap_reg_range(DA9063_BB_REG_MON_REG_5, DA9063_BB_REG_MON_REG_6),254};255 256static const struct regmap_access_table da9063l_bb_readable_table = {257 .yes_ranges = da9063l_bb_readable_ranges,258 .n_yes_ranges = ARRAY_SIZE(da9063l_bb_readable_ranges),259};260 261static const struct regmap_access_table da9063l_bb_writeable_table = {262 .yes_ranges = da9063l_bb_writeable_ranges,263 .n_yes_ranges = ARRAY_SIZE(da9063l_bb_writeable_ranges),264};265 266static const struct regmap_access_table da9063l_bb_da_volatile_table = {267 .yes_ranges = da9063l_bb_da_volatile_ranges,268 .n_yes_ranges = ARRAY_SIZE(da9063l_bb_da_volatile_ranges),269};270 271static const struct regmap_range da9063_da_readable_ranges[] = {272 regmap_reg_range(DA9063_REG_PAGE_CON, DA9063_BB_REG_SECOND_D),273 regmap_reg_range(DA9063_REG_SEQ, DA9063_REG_ID_32_31),274 regmap_reg_range(DA9063_REG_SEQ_A, DA9063_REG_AUTO3_LOW),275 regmap_reg_range(DA9063_REG_T_OFFSET, DA9063_BB_REG_GP_ID_11),276 regmap_reg_range(DA9063_REG_DEVICE_ID, DA9063_REG_VARIANT_ID),277};278 279static const struct regmap_range da9063_da_writeable_ranges[] = {280 regmap_reg_range(DA9063_REG_PAGE_CON, DA9063_REG_PAGE_CON),281 regmap_reg_range(DA9063_REG_FAULT_LOG, DA9063_REG_VSYS_MON),282 regmap_reg_range(DA9063_REG_COUNT_S, DA9063_BB_REG_ALARM_Y),283 regmap_reg_range(DA9063_REG_SEQ, DA9063_REG_ID_32_31),284 regmap_reg_range(DA9063_REG_SEQ_A, DA9063_REG_AUTO3_LOW),285 regmap_reg_range(DA9063_REG_CONFIG_I, DA9063_BB_REG_MON_REG_4),286 regmap_reg_range(DA9063_BB_REG_GP_ID_0, DA9063_BB_REG_GP_ID_11),287};288 289static const struct regmap_access_table da9063_da_readable_table = {290 .yes_ranges = da9063_da_readable_ranges,291 .n_yes_ranges = ARRAY_SIZE(da9063_da_readable_ranges),292};293 294static const struct regmap_access_table da9063_da_writeable_table = {295 .yes_ranges = da9063_da_writeable_ranges,296 .n_yes_ranges = ARRAY_SIZE(da9063_da_writeable_ranges),297};298 299static const struct regmap_range da9063l_da_readable_ranges[] = {300 regmap_reg_range(DA9063_REG_PAGE_CON, DA9063_REG_MON_A10_RES),301 regmap_reg_range(DA9063_REG_SEQ, DA9063_REG_ID_32_31),302 regmap_reg_range(DA9063_REG_SEQ_A, DA9063_REG_AUTO3_LOW),303 regmap_reg_range(DA9063_REG_T_OFFSET, DA9063_BB_REG_GP_ID_11),304 regmap_reg_range(DA9063_REG_DEVICE_ID, DA9063_REG_VARIANT_ID),305};306 307static const struct regmap_range da9063l_da_writeable_ranges[] = {308 regmap_reg_range(DA9063_REG_PAGE_CON, DA9063_REG_PAGE_CON),309 regmap_reg_range(DA9063_REG_FAULT_LOG, DA9063_REG_VSYS_MON),310 regmap_reg_range(DA9063_REG_SEQ, DA9063_REG_ID_32_31),311 regmap_reg_range(DA9063_REG_SEQ_A, DA9063_REG_AUTO3_LOW),312 regmap_reg_range(DA9063_REG_CONFIG_I, DA9063_BB_REG_MON_REG_4),313 regmap_reg_range(DA9063_BB_REG_GP_ID_0, DA9063_BB_REG_GP_ID_11),314};315 316static const struct regmap_access_table da9063l_da_readable_table = {317 .yes_ranges = da9063l_da_readable_ranges,318 .n_yes_ranges = ARRAY_SIZE(da9063l_da_readable_ranges),319};320 321static const struct regmap_access_table da9063l_da_writeable_table = {322 .yes_ranges = da9063l_da_writeable_ranges,323 .n_yes_ranges = ARRAY_SIZE(da9063l_da_writeable_ranges),324};325 326static const struct regmap_range_cfg da9063_range_cfg[] = {327 {328 .range_min = DA9063_REG_PAGE_CON,329 .range_max = DA9063_REG_CONFIG_ID,330 .selector_reg = DA9063_REG_PAGE_CON,331 .selector_mask = 1 << DA9063_I2C_PAGE_SEL_SHIFT,332 .selector_shift = DA9063_I2C_PAGE_SEL_SHIFT,333 .window_start = 0,334 .window_len = 256,335 }336};337 338static struct regmap_config da9063_regmap_config = {339 .reg_bits = 8,340 .val_bits = 8,341 .ranges = da9063_range_cfg,342 .num_ranges = ARRAY_SIZE(da9063_range_cfg),343 .max_register = DA9063_REG_CONFIG_ID,344 345 .cache_type = REGCACHE_MAPLE,346};347 348static const struct of_device_id da9063_dt_ids[] = {349 { .compatible = "dlg,da9063", },350 { .compatible = "dlg,da9063l", },351 { }352};353MODULE_DEVICE_TABLE(of, da9063_dt_ids);354static int da9063_i2c_probe(struct i2c_client *i2c)355{356 const struct i2c_device_id *id = i2c_client_get_device_id(i2c);357 struct da9063 *da9063;358 int ret;359 360 da9063 = devm_kzalloc(&i2c->dev, sizeof(struct da9063), GFP_KERNEL);361 if (da9063 == NULL)362 return -ENOMEM;363 364 i2c_set_clientdata(i2c, da9063);365 da9063->dev = &i2c->dev;366 da9063->chip_irq = i2c->irq;367 da9063->type = id->driver_data;368 369 ret = da9063_get_device_type(i2c, da9063);370 if (ret)371 return ret;372 373 switch (da9063->type) {374 case PMIC_TYPE_DA9063:375 switch (da9063->variant_code) {376 case PMIC_DA9063_AD:377 da9063_regmap_config.rd_table =378 &da9063_ad_readable_table;379 da9063_regmap_config.wr_table =380 &da9063_ad_writeable_table;381 da9063_regmap_config.volatile_table =382 &da9063_ad_volatile_table;383 break;384 case PMIC_DA9063_BB:385 case PMIC_DA9063_CA:386 da9063_regmap_config.rd_table =387 &da9063_bb_readable_table;388 da9063_regmap_config.wr_table =389 &da9063_bb_writeable_table;390 da9063_regmap_config.volatile_table =391 &da9063_bb_da_volatile_table;392 break;393 case PMIC_DA9063_DA:394 case PMIC_DA9063_EA:395 da9063_regmap_config.rd_table =396 &da9063_da_readable_table;397 da9063_regmap_config.wr_table =398 &da9063_da_writeable_table;399 da9063_regmap_config.volatile_table =400 &da9063_bb_da_volatile_table;401 break;402 default:403 dev_err(da9063->dev,404 "Chip variant not supported for DA9063\n");405 return -ENODEV;406 }407 break;408 case PMIC_TYPE_DA9063L:409 switch (da9063->variant_code) {410 case PMIC_DA9063_BB:411 case PMIC_DA9063_CA:412 da9063_regmap_config.rd_table =413 &da9063l_bb_readable_table;414 da9063_regmap_config.wr_table =415 &da9063l_bb_writeable_table;416 da9063_regmap_config.volatile_table =417 &da9063l_bb_da_volatile_table;418 break;419 case PMIC_DA9063_DA:420 case PMIC_DA9063_EA:421 da9063_regmap_config.rd_table =422 &da9063l_da_readable_table;423 da9063_regmap_config.wr_table =424 &da9063l_da_writeable_table;425 da9063_regmap_config.volatile_table =426 &da9063l_bb_da_volatile_table;427 break;428 default:429 dev_err(da9063->dev,430 "Chip variant not supported for DA9063L\n");431 return -ENODEV;432 }433 break;434 default:435 dev_err(da9063->dev, "Chip type not supported\n");436 return -ENODEV;437 }438 439 da9063->regmap = devm_regmap_init_i2c(i2c, &da9063_regmap_config);440 if (IS_ERR(da9063->regmap)) {441 ret = PTR_ERR(da9063->regmap);442 dev_err(da9063->dev, "Failed to allocate register map: %d\n",443 ret);444 return ret;445 }446 447 /* If SMBus is not available and only I2C is possible, enter I2C mode */448 if (i2c_check_functionality(i2c->adapter, I2C_FUNC_I2C)) {449 ret = regmap_clear_bits(da9063->regmap, DA9063_REG_CONFIG_J,450 DA9063_TWOWIRE_TO);451 if (ret < 0) {452 dev_err(da9063->dev, "Failed to set Two-Wire Bus Mode.\n");453 return ret;454 }455 }456 457 return da9063_device_init(da9063, i2c->irq);458}459 460static const struct i2c_device_id da9063_i2c_id[] = {461 { "da9063", PMIC_TYPE_DA9063 },462 { "da9063l", PMIC_TYPE_DA9063L },463 {},464};465MODULE_DEVICE_TABLE(i2c, da9063_i2c_id);466 467static struct i2c_driver da9063_i2c_driver = {468 .driver = {469 .name = "da9063",470 .of_match_table = da9063_dt_ids,471 },472 .probe = da9063_i2c_probe,473 .id_table = da9063_i2c_id,474};475 476module_i2c_driver(da9063_i2c_driver);477