162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0+ 262306a36Sopenharmony_ci/* I2C support for Dialog DA9063 362306a36Sopenharmony_ci * 462306a36Sopenharmony_ci * Copyright 2012 Dialog Semiconductor Ltd. 562306a36Sopenharmony_ci * Copyright 2013 Philipp Zabel, Pengutronix 662306a36Sopenharmony_ci * 762306a36Sopenharmony_ci * Author: Krystian Garbaciak, Dialog Semiconductor 862306a36Sopenharmony_ci */ 962306a36Sopenharmony_ci 1062306a36Sopenharmony_ci#include <linux/kernel.h> 1162306a36Sopenharmony_ci#include <linux/module.h> 1262306a36Sopenharmony_ci#include <linux/i2c.h> 1362306a36Sopenharmony_ci#include <linux/regmap.h> 1462306a36Sopenharmony_ci#include <linux/delay.h> 1562306a36Sopenharmony_ci#include <linux/slab.h> 1662306a36Sopenharmony_ci#include <linux/err.h> 1762306a36Sopenharmony_ci 1862306a36Sopenharmony_ci#include <linux/mfd/core.h> 1962306a36Sopenharmony_ci#include <linux/mfd/da9063/core.h> 2062306a36Sopenharmony_ci#include <linux/mfd/da9063/registers.h> 2162306a36Sopenharmony_ci 2262306a36Sopenharmony_ci#include <linux/of.h> 2362306a36Sopenharmony_ci#include <linux/regulator/of_regulator.h> 2462306a36Sopenharmony_ci 2562306a36Sopenharmony_ci/* 2662306a36Sopenharmony_ci * Raw I2C access required for just accessing chip and variant info before we 2762306a36Sopenharmony_ci * know which device is present. The info read from the device using this 2862306a36Sopenharmony_ci * approach is then used to select the correct regmap tables. 2962306a36Sopenharmony_ci */ 3062306a36Sopenharmony_ci 3162306a36Sopenharmony_ci#define DA9063_REG_PAGE_SIZE 0x100 3262306a36Sopenharmony_ci#define DA9063_REG_PAGED_ADDR_MASK 0xFF 3362306a36Sopenharmony_ci 3462306a36Sopenharmony_cienum da9063_page_sel_buf_fmt { 3562306a36Sopenharmony_ci DA9063_PAGE_SEL_BUF_PAGE_REG = 0, 3662306a36Sopenharmony_ci DA9063_PAGE_SEL_BUF_PAGE_VAL, 3762306a36Sopenharmony_ci DA9063_PAGE_SEL_BUF_SIZE, 3862306a36Sopenharmony_ci}; 3962306a36Sopenharmony_ci 4062306a36Sopenharmony_cienum da9063_paged_read_msgs { 4162306a36Sopenharmony_ci DA9063_PAGED_READ_MSG_PAGE_SEL = 0, 4262306a36Sopenharmony_ci DA9063_PAGED_READ_MSG_REG_SEL, 4362306a36Sopenharmony_ci DA9063_PAGED_READ_MSG_DATA, 4462306a36Sopenharmony_ci DA9063_PAGED_READ_MSG_CNT, 4562306a36Sopenharmony_ci}; 4662306a36Sopenharmony_ci 4762306a36Sopenharmony_cistatic int da9063_i2c_blockreg_read(struct i2c_client *client, u16 addr, 4862306a36Sopenharmony_ci u8 *buf, int count) 4962306a36Sopenharmony_ci{ 5062306a36Sopenharmony_ci struct i2c_msg xfer[DA9063_PAGED_READ_MSG_CNT]; 5162306a36Sopenharmony_ci u8 page_sel_buf[DA9063_PAGE_SEL_BUF_SIZE]; 5262306a36Sopenharmony_ci u8 page_num, paged_addr; 5362306a36Sopenharmony_ci int ret; 5462306a36Sopenharmony_ci 5562306a36Sopenharmony_ci /* Determine page info based on register address */ 5662306a36Sopenharmony_ci page_num = (addr / DA9063_REG_PAGE_SIZE); 5762306a36Sopenharmony_ci if (page_num > 1) { 5862306a36Sopenharmony_ci dev_err(&client->dev, "Invalid register address provided\n"); 5962306a36Sopenharmony_ci return -EINVAL; 6062306a36Sopenharmony_ci } 6162306a36Sopenharmony_ci 6262306a36Sopenharmony_ci paged_addr = (addr % DA9063_REG_PAGE_SIZE) & DA9063_REG_PAGED_ADDR_MASK; 6362306a36Sopenharmony_ci page_sel_buf[DA9063_PAGE_SEL_BUF_PAGE_REG] = DA9063_REG_PAGE_CON; 6462306a36Sopenharmony_ci page_sel_buf[DA9063_PAGE_SEL_BUF_PAGE_VAL] = 6562306a36Sopenharmony_ci (page_num << DA9063_I2C_PAGE_SEL_SHIFT) & DA9063_REG_PAGE_MASK; 6662306a36Sopenharmony_ci 6762306a36Sopenharmony_ci /* Write reg address, page selection */ 6862306a36Sopenharmony_ci xfer[DA9063_PAGED_READ_MSG_PAGE_SEL].addr = client->addr; 6962306a36Sopenharmony_ci xfer[DA9063_PAGED_READ_MSG_PAGE_SEL].flags = 0; 7062306a36Sopenharmony_ci xfer[DA9063_PAGED_READ_MSG_PAGE_SEL].len = DA9063_PAGE_SEL_BUF_SIZE; 7162306a36Sopenharmony_ci xfer[DA9063_PAGED_READ_MSG_PAGE_SEL].buf = page_sel_buf; 7262306a36Sopenharmony_ci 7362306a36Sopenharmony_ci /* Select register address */ 7462306a36Sopenharmony_ci xfer[DA9063_PAGED_READ_MSG_REG_SEL].addr = client->addr; 7562306a36Sopenharmony_ci xfer[DA9063_PAGED_READ_MSG_REG_SEL].flags = 0; 7662306a36Sopenharmony_ci xfer[DA9063_PAGED_READ_MSG_REG_SEL].len = sizeof(paged_addr); 7762306a36Sopenharmony_ci xfer[DA9063_PAGED_READ_MSG_REG_SEL].buf = &paged_addr; 7862306a36Sopenharmony_ci 7962306a36Sopenharmony_ci /* Read data */ 8062306a36Sopenharmony_ci xfer[DA9063_PAGED_READ_MSG_DATA].addr = client->addr; 8162306a36Sopenharmony_ci xfer[DA9063_PAGED_READ_MSG_DATA].flags = I2C_M_RD; 8262306a36Sopenharmony_ci xfer[DA9063_PAGED_READ_MSG_DATA].len = count; 8362306a36Sopenharmony_ci xfer[DA9063_PAGED_READ_MSG_DATA].buf = buf; 8462306a36Sopenharmony_ci 8562306a36Sopenharmony_ci ret = i2c_transfer(client->adapter, xfer, DA9063_PAGED_READ_MSG_CNT); 8662306a36Sopenharmony_ci if (ret < 0) { 8762306a36Sopenharmony_ci dev_err(&client->dev, "Paged block read failed: %d\n", ret); 8862306a36Sopenharmony_ci return ret; 8962306a36Sopenharmony_ci } 9062306a36Sopenharmony_ci 9162306a36Sopenharmony_ci if (ret != DA9063_PAGED_READ_MSG_CNT) { 9262306a36Sopenharmony_ci dev_err(&client->dev, "Paged block read failed to complete\n"); 9362306a36Sopenharmony_ci return -EIO; 9462306a36Sopenharmony_ci } 9562306a36Sopenharmony_ci 9662306a36Sopenharmony_ci return 0; 9762306a36Sopenharmony_ci} 9862306a36Sopenharmony_ci 9962306a36Sopenharmony_cienum { 10062306a36Sopenharmony_ci DA9063_DEV_ID_REG = 0, 10162306a36Sopenharmony_ci DA9063_VAR_ID_REG, 10262306a36Sopenharmony_ci DA9063_CHIP_ID_REGS, 10362306a36Sopenharmony_ci}; 10462306a36Sopenharmony_ci 10562306a36Sopenharmony_cistatic int da9063_get_device_type(struct i2c_client *i2c, struct da9063 *da9063) 10662306a36Sopenharmony_ci{ 10762306a36Sopenharmony_ci u8 buf[DA9063_CHIP_ID_REGS]; 10862306a36Sopenharmony_ci int ret; 10962306a36Sopenharmony_ci 11062306a36Sopenharmony_ci ret = da9063_i2c_blockreg_read(i2c, DA9063_REG_DEVICE_ID, buf, 11162306a36Sopenharmony_ci DA9063_CHIP_ID_REGS); 11262306a36Sopenharmony_ci if (ret) 11362306a36Sopenharmony_ci return ret; 11462306a36Sopenharmony_ci 11562306a36Sopenharmony_ci if (buf[DA9063_DEV_ID_REG] != PMIC_CHIP_ID_DA9063) { 11662306a36Sopenharmony_ci dev_err(da9063->dev, 11762306a36Sopenharmony_ci "Invalid chip device ID: 0x%02x\n", 11862306a36Sopenharmony_ci buf[DA9063_DEV_ID_REG]); 11962306a36Sopenharmony_ci return -ENODEV; 12062306a36Sopenharmony_ci } 12162306a36Sopenharmony_ci 12262306a36Sopenharmony_ci dev_info(da9063->dev, 12362306a36Sopenharmony_ci "Device detected (chip-ID: 0x%02X, var-ID: 0x%02X)\n", 12462306a36Sopenharmony_ci buf[DA9063_DEV_ID_REG], buf[DA9063_VAR_ID_REG]); 12562306a36Sopenharmony_ci 12662306a36Sopenharmony_ci da9063->variant_code = 12762306a36Sopenharmony_ci (buf[DA9063_VAR_ID_REG] & DA9063_VARIANT_ID_MRC_MASK) 12862306a36Sopenharmony_ci >> DA9063_VARIANT_ID_MRC_SHIFT; 12962306a36Sopenharmony_ci 13062306a36Sopenharmony_ci return 0; 13162306a36Sopenharmony_ci} 13262306a36Sopenharmony_ci 13362306a36Sopenharmony_ci/* 13462306a36Sopenharmony_ci * Variant specific regmap configs 13562306a36Sopenharmony_ci */ 13662306a36Sopenharmony_ci 13762306a36Sopenharmony_cistatic const struct regmap_range da9063_ad_readable_ranges[] = { 13862306a36Sopenharmony_ci regmap_reg_range(DA9063_REG_PAGE_CON, DA9063_AD_REG_SECOND_D), 13962306a36Sopenharmony_ci regmap_reg_range(DA9063_REG_SEQ, DA9063_REG_ID_32_31), 14062306a36Sopenharmony_ci regmap_reg_range(DA9063_REG_SEQ_A, DA9063_REG_AUTO3_LOW), 14162306a36Sopenharmony_ci regmap_reg_range(DA9063_REG_T_OFFSET, DA9063_AD_REG_GP_ID_19), 14262306a36Sopenharmony_ci regmap_reg_range(DA9063_REG_DEVICE_ID, DA9063_REG_VARIANT_ID), 14362306a36Sopenharmony_ci}; 14462306a36Sopenharmony_ci 14562306a36Sopenharmony_cistatic const struct regmap_range da9063_ad_writeable_ranges[] = { 14662306a36Sopenharmony_ci regmap_reg_range(DA9063_REG_PAGE_CON, DA9063_REG_PAGE_CON), 14762306a36Sopenharmony_ci regmap_reg_range(DA9063_REG_FAULT_LOG, DA9063_REG_VSYS_MON), 14862306a36Sopenharmony_ci regmap_reg_range(DA9063_REG_COUNT_S, DA9063_AD_REG_ALARM_Y), 14962306a36Sopenharmony_ci regmap_reg_range(DA9063_REG_SEQ, DA9063_REG_ID_32_31), 15062306a36Sopenharmony_ci regmap_reg_range(DA9063_REG_SEQ_A, DA9063_REG_AUTO3_LOW), 15162306a36Sopenharmony_ci regmap_reg_range(DA9063_REG_CONFIG_I, DA9063_AD_REG_MON_REG_4), 15262306a36Sopenharmony_ci regmap_reg_range(DA9063_AD_REG_GP_ID_0, DA9063_AD_REG_GP_ID_19), 15362306a36Sopenharmony_ci}; 15462306a36Sopenharmony_ci 15562306a36Sopenharmony_cistatic const struct regmap_range da9063_ad_volatile_ranges[] = { 15662306a36Sopenharmony_ci regmap_reg_range(DA9063_REG_PAGE_CON, DA9063_REG_EVENT_D), 15762306a36Sopenharmony_ci regmap_reg_range(DA9063_REG_CONTROL_A, DA9063_REG_CONTROL_B), 15862306a36Sopenharmony_ci regmap_reg_range(DA9063_REG_CONTROL_E, DA9063_REG_CONTROL_F), 15962306a36Sopenharmony_ci regmap_reg_range(DA9063_REG_BCORE2_CONT, DA9063_REG_LDO11_CONT), 16062306a36Sopenharmony_ci regmap_reg_range(DA9063_REG_DVC_1, DA9063_REG_ADC_MAN), 16162306a36Sopenharmony_ci regmap_reg_range(DA9063_REG_ADC_RES_L, DA9063_AD_REG_SECOND_D), 16262306a36Sopenharmony_ci regmap_reg_range(DA9063_REG_SEQ, DA9063_REG_SEQ), 16362306a36Sopenharmony_ci regmap_reg_range(DA9063_REG_EN_32K, DA9063_REG_EN_32K), 16462306a36Sopenharmony_ci regmap_reg_range(DA9063_AD_REG_MON_REG_5, DA9063_AD_REG_MON_REG_6), 16562306a36Sopenharmony_ci}; 16662306a36Sopenharmony_ci 16762306a36Sopenharmony_cistatic const struct regmap_access_table da9063_ad_readable_table = { 16862306a36Sopenharmony_ci .yes_ranges = da9063_ad_readable_ranges, 16962306a36Sopenharmony_ci .n_yes_ranges = ARRAY_SIZE(da9063_ad_readable_ranges), 17062306a36Sopenharmony_ci}; 17162306a36Sopenharmony_ci 17262306a36Sopenharmony_cistatic const struct regmap_access_table da9063_ad_writeable_table = { 17362306a36Sopenharmony_ci .yes_ranges = da9063_ad_writeable_ranges, 17462306a36Sopenharmony_ci .n_yes_ranges = ARRAY_SIZE(da9063_ad_writeable_ranges), 17562306a36Sopenharmony_ci}; 17662306a36Sopenharmony_ci 17762306a36Sopenharmony_cistatic const struct regmap_access_table da9063_ad_volatile_table = { 17862306a36Sopenharmony_ci .yes_ranges = da9063_ad_volatile_ranges, 17962306a36Sopenharmony_ci .n_yes_ranges = ARRAY_SIZE(da9063_ad_volatile_ranges), 18062306a36Sopenharmony_ci}; 18162306a36Sopenharmony_ci 18262306a36Sopenharmony_cistatic const struct regmap_range da9063_bb_readable_ranges[] = { 18362306a36Sopenharmony_ci regmap_reg_range(DA9063_REG_PAGE_CON, DA9063_BB_REG_SECOND_D), 18462306a36Sopenharmony_ci regmap_reg_range(DA9063_REG_SEQ, DA9063_REG_ID_32_31), 18562306a36Sopenharmony_ci regmap_reg_range(DA9063_REG_SEQ_A, DA9063_REG_AUTO3_LOW), 18662306a36Sopenharmony_ci regmap_reg_range(DA9063_REG_T_OFFSET, DA9063_BB_REG_GP_ID_19), 18762306a36Sopenharmony_ci regmap_reg_range(DA9063_REG_DEVICE_ID, DA9063_REG_VARIANT_ID), 18862306a36Sopenharmony_ci}; 18962306a36Sopenharmony_ci 19062306a36Sopenharmony_cistatic const struct regmap_range da9063_bb_writeable_ranges[] = { 19162306a36Sopenharmony_ci regmap_reg_range(DA9063_REG_PAGE_CON, DA9063_REG_PAGE_CON), 19262306a36Sopenharmony_ci regmap_reg_range(DA9063_REG_FAULT_LOG, DA9063_REG_VSYS_MON), 19362306a36Sopenharmony_ci regmap_reg_range(DA9063_REG_COUNT_S, DA9063_BB_REG_ALARM_Y), 19462306a36Sopenharmony_ci regmap_reg_range(DA9063_REG_SEQ, DA9063_REG_ID_32_31), 19562306a36Sopenharmony_ci regmap_reg_range(DA9063_REG_SEQ_A, DA9063_REG_AUTO3_LOW), 19662306a36Sopenharmony_ci regmap_reg_range(DA9063_REG_CONFIG_I, DA9063_BB_REG_MON_REG_4), 19762306a36Sopenharmony_ci regmap_reg_range(DA9063_BB_REG_GP_ID_0, DA9063_BB_REG_GP_ID_19), 19862306a36Sopenharmony_ci}; 19962306a36Sopenharmony_ci 20062306a36Sopenharmony_cistatic const struct regmap_range da9063_bb_da_volatile_ranges[] = { 20162306a36Sopenharmony_ci regmap_reg_range(DA9063_REG_PAGE_CON, DA9063_REG_EVENT_D), 20262306a36Sopenharmony_ci regmap_reg_range(DA9063_REG_CONTROL_A, DA9063_REG_CONTROL_B), 20362306a36Sopenharmony_ci regmap_reg_range(DA9063_REG_CONTROL_E, DA9063_REG_CONTROL_F), 20462306a36Sopenharmony_ci regmap_reg_range(DA9063_REG_BCORE2_CONT, DA9063_REG_LDO11_CONT), 20562306a36Sopenharmony_ci regmap_reg_range(DA9063_REG_DVC_1, DA9063_REG_ADC_MAN), 20662306a36Sopenharmony_ci regmap_reg_range(DA9063_REG_ADC_RES_L, DA9063_BB_REG_SECOND_D), 20762306a36Sopenharmony_ci regmap_reg_range(DA9063_REG_SEQ, DA9063_REG_SEQ), 20862306a36Sopenharmony_ci regmap_reg_range(DA9063_REG_EN_32K, DA9063_REG_EN_32K), 20962306a36Sopenharmony_ci regmap_reg_range(DA9063_BB_REG_MON_REG_5, DA9063_BB_REG_MON_REG_6), 21062306a36Sopenharmony_ci}; 21162306a36Sopenharmony_ci 21262306a36Sopenharmony_cistatic const struct regmap_access_table da9063_bb_readable_table = { 21362306a36Sopenharmony_ci .yes_ranges = da9063_bb_readable_ranges, 21462306a36Sopenharmony_ci .n_yes_ranges = ARRAY_SIZE(da9063_bb_readable_ranges), 21562306a36Sopenharmony_ci}; 21662306a36Sopenharmony_ci 21762306a36Sopenharmony_cistatic const struct regmap_access_table da9063_bb_writeable_table = { 21862306a36Sopenharmony_ci .yes_ranges = da9063_bb_writeable_ranges, 21962306a36Sopenharmony_ci .n_yes_ranges = ARRAY_SIZE(da9063_bb_writeable_ranges), 22062306a36Sopenharmony_ci}; 22162306a36Sopenharmony_ci 22262306a36Sopenharmony_cistatic const struct regmap_access_table da9063_bb_da_volatile_table = { 22362306a36Sopenharmony_ci .yes_ranges = da9063_bb_da_volatile_ranges, 22462306a36Sopenharmony_ci .n_yes_ranges = ARRAY_SIZE(da9063_bb_da_volatile_ranges), 22562306a36Sopenharmony_ci}; 22662306a36Sopenharmony_ci 22762306a36Sopenharmony_cistatic const struct regmap_range da9063l_bb_readable_ranges[] = { 22862306a36Sopenharmony_ci regmap_reg_range(DA9063_REG_PAGE_CON, DA9063_REG_MON_A10_RES), 22962306a36Sopenharmony_ci regmap_reg_range(DA9063_REG_SEQ, DA9063_REG_ID_32_31), 23062306a36Sopenharmony_ci regmap_reg_range(DA9063_REG_SEQ_A, DA9063_REG_AUTO3_LOW), 23162306a36Sopenharmony_ci regmap_reg_range(DA9063_REG_T_OFFSET, DA9063_BB_REG_GP_ID_19), 23262306a36Sopenharmony_ci regmap_reg_range(DA9063_REG_DEVICE_ID, DA9063_REG_VARIANT_ID), 23362306a36Sopenharmony_ci}; 23462306a36Sopenharmony_ci 23562306a36Sopenharmony_cistatic const struct regmap_range da9063l_bb_writeable_ranges[] = { 23662306a36Sopenharmony_ci regmap_reg_range(DA9063_REG_PAGE_CON, DA9063_REG_PAGE_CON), 23762306a36Sopenharmony_ci regmap_reg_range(DA9063_REG_FAULT_LOG, DA9063_REG_VSYS_MON), 23862306a36Sopenharmony_ci regmap_reg_range(DA9063_REG_SEQ, DA9063_REG_ID_32_31), 23962306a36Sopenharmony_ci regmap_reg_range(DA9063_REG_SEQ_A, DA9063_REG_AUTO3_LOW), 24062306a36Sopenharmony_ci regmap_reg_range(DA9063_REG_CONFIG_I, DA9063_BB_REG_MON_REG_4), 24162306a36Sopenharmony_ci regmap_reg_range(DA9063_BB_REG_GP_ID_0, DA9063_BB_REG_GP_ID_19), 24262306a36Sopenharmony_ci}; 24362306a36Sopenharmony_ci 24462306a36Sopenharmony_cistatic const struct regmap_range da9063l_bb_da_volatile_ranges[] = { 24562306a36Sopenharmony_ci regmap_reg_range(DA9063_REG_PAGE_CON, DA9063_REG_EVENT_D), 24662306a36Sopenharmony_ci regmap_reg_range(DA9063_REG_CONTROL_A, DA9063_REG_CONTROL_B), 24762306a36Sopenharmony_ci regmap_reg_range(DA9063_REG_CONTROL_E, DA9063_REG_CONTROL_F), 24862306a36Sopenharmony_ci regmap_reg_range(DA9063_REG_BCORE2_CONT, DA9063_REG_LDO11_CONT), 24962306a36Sopenharmony_ci regmap_reg_range(DA9063_REG_DVC_1, DA9063_REG_ADC_MAN), 25062306a36Sopenharmony_ci regmap_reg_range(DA9063_REG_ADC_RES_L, DA9063_REG_MON_A10_RES), 25162306a36Sopenharmony_ci regmap_reg_range(DA9063_REG_SEQ, DA9063_REG_SEQ), 25262306a36Sopenharmony_ci regmap_reg_range(DA9063_REG_EN_32K, DA9063_REG_EN_32K), 25362306a36Sopenharmony_ci regmap_reg_range(DA9063_BB_REG_MON_REG_5, DA9063_BB_REG_MON_REG_6), 25462306a36Sopenharmony_ci}; 25562306a36Sopenharmony_ci 25662306a36Sopenharmony_cistatic const struct regmap_access_table da9063l_bb_readable_table = { 25762306a36Sopenharmony_ci .yes_ranges = da9063l_bb_readable_ranges, 25862306a36Sopenharmony_ci .n_yes_ranges = ARRAY_SIZE(da9063l_bb_readable_ranges), 25962306a36Sopenharmony_ci}; 26062306a36Sopenharmony_ci 26162306a36Sopenharmony_cistatic const struct regmap_access_table da9063l_bb_writeable_table = { 26262306a36Sopenharmony_ci .yes_ranges = da9063l_bb_writeable_ranges, 26362306a36Sopenharmony_ci .n_yes_ranges = ARRAY_SIZE(da9063l_bb_writeable_ranges), 26462306a36Sopenharmony_ci}; 26562306a36Sopenharmony_ci 26662306a36Sopenharmony_cistatic const struct regmap_access_table da9063l_bb_da_volatile_table = { 26762306a36Sopenharmony_ci .yes_ranges = da9063l_bb_da_volatile_ranges, 26862306a36Sopenharmony_ci .n_yes_ranges = ARRAY_SIZE(da9063l_bb_da_volatile_ranges), 26962306a36Sopenharmony_ci}; 27062306a36Sopenharmony_ci 27162306a36Sopenharmony_cistatic const struct regmap_range da9063_da_readable_ranges[] = { 27262306a36Sopenharmony_ci regmap_reg_range(DA9063_REG_PAGE_CON, DA9063_BB_REG_SECOND_D), 27362306a36Sopenharmony_ci regmap_reg_range(DA9063_REG_SEQ, DA9063_REG_ID_32_31), 27462306a36Sopenharmony_ci regmap_reg_range(DA9063_REG_SEQ_A, DA9063_REG_AUTO3_LOW), 27562306a36Sopenharmony_ci regmap_reg_range(DA9063_REG_T_OFFSET, DA9063_BB_REG_GP_ID_11), 27662306a36Sopenharmony_ci regmap_reg_range(DA9063_REG_DEVICE_ID, DA9063_REG_VARIANT_ID), 27762306a36Sopenharmony_ci}; 27862306a36Sopenharmony_ci 27962306a36Sopenharmony_cistatic const struct regmap_range da9063_da_writeable_ranges[] = { 28062306a36Sopenharmony_ci regmap_reg_range(DA9063_REG_PAGE_CON, DA9063_REG_PAGE_CON), 28162306a36Sopenharmony_ci regmap_reg_range(DA9063_REG_FAULT_LOG, DA9063_REG_VSYS_MON), 28262306a36Sopenharmony_ci regmap_reg_range(DA9063_REG_COUNT_S, DA9063_BB_REG_ALARM_Y), 28362306a36Sopenharmony_ci regmap_reg_range(DA9063_REG_SEQ, DA9063_REG_ID_32_31), 28462306a36Sopenharmony_ci regmap_reg_range(DA9063_REG_SEQ_A, DA9063_REG_AUTO3_LOW), 28562306a36Sopenharmony_ci regmap_reg_range(DA9063_REG_CONFIG_I, DA9063_BB_REG_MON_REG_4), 28662306a36Sopenharmony_ci regmap_reg_range(DA9063_BB_REG_GP_ID_0, DA9063_BB_REG_GP_ID_11), 28762306a36Sopenharmony_ci}; 28862306a36Sopenharmony_ci 28962306a36Sopenharmony_cistatic const struct regmap_access_table da9063_da_readable_table = { 29062306a36Sopenharmony_ci .yes_ranges = da9063_da_readable_ranges, 29162306a36Sopenharmony_ci .n_yes_ranges = ARRAY_SIZE(da9063_da_readable_ranges), 29262306a36Sopenharmony_ci}; 29362306a36Sopenharmony_ci 29462306a36Sopenharmony_cistatic const struct regmap_access_table da9063_da_writeable_table = { 29562306a36Sopenharmony_ci .yes_ranges = da9063_da_writeable_ranges, 29662306a36Sopenharmony_ci .n_yes_ranges = ARRAY_SIZE(da9063_da_writeable_ranges), 29762306a36Sopenharmony_ci}; 29862306a36Sopenharmony_ci 29962306a36Sopenharmony_cistatic const struct regmap_range da9063l_da_readable_ranges[] = { 30062306a36Sopenharmony_ci regmap_reg_range(DA9063_REG_PAGE_CON, DA9063_REG_MON_A10_RES), 30162306a36Sopenharmony_ci regmap_reg_range(DA9063_REG_SEQ, DA9063_REG_ID_32_31), 30262306a36Sopenharmony_ci regmap_reg_range(DA9063_REG_SEQ_A, DA9063_REG_AUTO3_LOW), 30362306a36Sopenharmony_ci regmap_reg_range(DA9063_REG_T_OFFSET, DA9063_BB_REG_GP_ID_11), 30462306a36Sopenharmony_ci regmap_reg_range(DA9063_REG_DEVICE_ID, DA9063_REG_VARIANT_ID), 30562306a36Sopenharmony_ci}; 30662306a36Sopenharmony_ci 30762306a36Sopenharmony_cistatic const struct regmap_range da9063l_da_writeable_ranges[] = { 30862306a36Sopenharmony_ci regmap_reg_range(DA9063_REG_PAGE_CON, DA9063_REG_PAGE_CON), 30962306a36Sopenharmony_ci regmap_reg_range(DA9063_REG_FAULT_LOG, DA9063_REG_VSYS_MON), 31062306a36Sopenharmony_ci regmap_reg_range(DA9063_REG_SEQ, DA9063_REG_ID_32_31), 31162306a36Sopenharmony_ci regmap_reg_range(DA9063_REG_SEQ_A, DA9063_REG_AUTO3_LOW), 31262306a36Sopenharmony_ci regmap_reg_range(DA9063_REG_CONFIG_I, DA9063_BB_REG_MON_REG_4), 31362306a36Sopenharmony_ci regmap_reg_range(DA9063_BB_REG_GP_ID_0, DA9063_BB_REG_GP_ID_11), 31462306a36Sopenharmony_ci}; 31562306a36Sopenharmony_ci 31662306a36Sopenharmony_cistatic const struct regmap_access_table da9063l_da_readable_table = { 31762306a36Sopenharmony_ci .yes_ranges = da9063l_da_readable_ranges, 31862306a36Sopenharmony_ci .n_yes_ranges = ARRAY_SIZE(da9063l_da_readable_ranges), 31962306a36Sopenharmony_ci}; 32062306a36Sopenharmony_ci 32162306a36Sopenharmony_cistatic const struct regmap_access_table da9063l_da_writeable_table = { 32262306a36Sopenharmony_ci .yes_ranges = da9063l_da_writeable_ranges, 32362306a36Sopenharmony_ci .n_yes_ranges = ARRAY_SIZE(da9063l_da_writeable_ranges), 32462306a36Sopenharmony_ci}; 32562306a36Sopenharmony_ci 32662306a36Sopenharmony_cistatic const struct regmap_range_cfg da9063_range_cfg[] = { 32762306a36Sopenharmony_ci { 32862306a36Sopenharmony_ci .range_min = DA9063_REG_PAGE_CON, 32962306a36Sopenharmony_ci .range_max = DA9063_REG_CONFIG_ID, 33062306a36Sopenharmony_ci .selector_reg = DA9063_REG_PAGE_CON, 33162306a36Sopenharmony_ci .selector_mask = 1 << DA9063_I2C_PAGE_SEL_SHIFT, 33262306a36Sopenharmony_ci .selector_shift = DA9063_I2C_PAGE_SEL_SHIFT, 33362306a36Sopenharmony_ci .window_start = 0, 33462306a36Sopenharmony_ci .window_len = 256, 33562306a36Sopenharmony_ci } 33662306a36Sopenharmony_ci}; 33762306a36Sopenharmony_ci 33862306a36Sopenharmony_cistatic struct regmap_config da9063_regmap_config = { 33962306a36Sopenharmony_ci .reg_bits = 8, 34062306a36Sopenharmony_ci .val_bits = 8, 34162306a36Sopenharmony_ci .ranges = da9063_range_cfg, 34262306a36Sopenharmony_ci .num_ranges = ARRAY_SIZE(da9063_range_cfg), 34362306a36Sopenharmony_ci .max_register = DA9063_REG_CONFIG_ID, 34462306a36Sopenharmony_ci 34562306a36Sopenharmony_ci .cache_type = REGCACHE_RBTREE, 34662306a36Sopenharmony_ci}; 34762306a36Sopenharmony_ci 34862306a36Sopenharmony_cistatic const struct of_device_id da9063_dt_ids[] = { 34962306a36Sopenharmony_ci { .compatible = "dlg,da9063", }, 35062306a36Sopenharmony_ci { .compatible = "dlg,da9063l", }, 35162306a36Sopenharmony_ci { } 35262306a36Sopenharmony_ci}; 35362306a36Sopenharmony_ciMODULE_DEVICE_TABLE(of, da9063_dt_ids); 35462306a36Sopenharmony_cistatic int da9063_i2c_probe(struct i2c_client *i2c) 35562306a36Sopenharmony_ci{ 35662306a36Sopenharmony_ci const struct i2c_device_id *id = i2c_client_get_device_id(i2c); 35762306a36Sopenharmony_ci struct da9063 *da9063; 35862306a36Sopenharmony_ci int ret; 35962306a36Sopenharmony_ci 36062306a36Sopenharmony_ci da9063 = devm_kzalloc(&i2c->dev, sizeof(struct da9063), GFP_KERNEL); 36162306a36Sopenharmony_ci if (da9063 == NULL) 36262306a36Sopenharmony_ci return -ENOMEM; 36362306a36Sopenharmony_ci 36462306a36Sopenharmony_ci i2c_set_clientdata(i2c, da9063); 36562306a36Sopenharmony_ci da9063->dev = &i2c->dev; 36662306a36Sopenharmony_ci da9063->chip_irq = i2c->irq; 36762306a36Sopenharmony_ci da9063->type = id->driver_data; 36862306a36Sopenharmony_ci 36962306a36Sopenharmony_ci ret = da9063_get_device_type(i2c, da9063); 37062306a36Sopenharmony_ci if (ret) 37162306a36Sopenharmony_ci return ret; 37262306a36Sopenharmony_ci 37362306a36Sopenharmony_ci switch (da9063->type) { 37462306a36Sopenharmony_ci case PMIC_TYPE_DA9063: 37562306a36Sopenharmony_ci switch (da9063->variant_code) { 37662306a36Sopenharmony_ci case PMIC_DA9063_AD: 37762306a36Sopenharmony_ci da9063_regmap_config.rd_table = 37862306a36Sopenharmony_ci &da9063_ad_readable_table; 37962306a36Sopenharmony_ci da9063_regmap_config.wr_table = 38062306a36Sopenharmony_ci &da9063_ad_writeable_table; 38162306a36Sopenharmony_ci da9063_regmap_config.volatile_table = 38262306a36Sopenharmony_ci &da9063_ad_volatile_table; 38362306a36Sopenharmony_ci break; 38462306a36Sopenharmony_ci case PMIC_DA9063_BB: 38562306a36Sopenharmony_ci case PMIC_DA9063_CA: 38662306a36Sopenharmony_ci da9063_regmap_config.rd_table = 38762306a36Sopenharmony_ci &da9063_bb_readable_table; 38862306a36Sopenharmony_ci da9063_regmap_config.wr_table = 38962306a36Sopenharmony_ci &da9063_bb_writeable_table; 39062306a36Sopenharmony_ci da9063_regmap_config.volatile_table = 39162306a36Sopenharmony_ci &da9063_bb_da_volatile_table; 39262306a36Sopenharmony_ci break; 39362306a36Sopenharmony_ci case PMIC_DA9063_DA: 39462306a36Sopenharmony_ci case PMIC_DA9063_EA: 39562306a36Sopenharmony_ci da9063_regmap_config.rd_table = 39662306a36Sopenharmony_ci &da9063_da_readable_table; 39762306a36Sopenharmony_ci da9063_regmap_config.wr_table = 39862306a36Sopenharmony_ci &da9063_da_writeable_table; 39962306a36Sopenharmony_ci da9063_regmap_config.volatile_table = 40062306a36Sopenharmony_ci &da9063_bb_da_volatile_table; 40162306a36Sopenharmony_ci break; 40262306a36Sopenharmony_ci default: 40362306a36Sopenharmony_ci dev_err(da9063->dev, 40462306a36Sopenharmony_ci "Chip variant not supported for DA9063\n"); 40562306a36Sopenharmony_ci return -ENODEV; 40662306a36Sopenharmony_ci } 40762306a36Sopenharmony_ci break; 40862306a36Sopenharmony_ci case PMIC_TYPE_DA9063L: 40962306a36Sopenharmony_ci switch (da9063->variant_code) { 41062306a36Sopenharmony_ci case PMIC_DA9063_BB: 41162306a36Sopenharmony_ci case PMIC_DA9063_CA: 41262306a36Sopenharmony_ci da9063_regmap_config.rd_table = 41362306a36Sopenharmony_ci &da9063l_bb_readable_table; 41462306a36Sopenharmony_ci da9063_regmap_config.wr_table = 41562306a36Sopenharmony_ci &da9063l_bb_writeable_table; 41662306a36Sopenharmony_ci da9063_regmap_config.volatile_table = 41762306a36Sopenharmony_ci &da9063l_bb_da_volatile_table; 41862306a36Sopenharmony_ci break; 41962306a36Sopenharmony_ci case PMIC_DA9063_DA: 42062306a36Sopenharmony_ci case PMIC_DA9063_EA: 42162306a36Sopenharmony_ci da9063_regmap_config.rd_table = 42262306a36Sopenharmony_ci &da9063l_da_readable_table; 42362306a36Sopenharmony_ci da9063_regmap_config.wr_table = 42462306a36Sopenharmony_ci &da9063l_da_writeable_table; 42562306a36Sopenharmony_ci da9063_regmap_config.volatile_table = 42662306a36Sopenharmony_ci &da9063l_bb_da_volatile_table; 42762306a36Sopenharmony_ci break; 42862306a36Sopenharmony_ci default: 42962306a36Sopenharmony_ci dev_err(da9063->dev, 43062306a36Sopenharmony_ci "Chip variant not supported for DA9063L\n"); 43162306a36Sopenharmony_ci return -ENODEV; 43262306a36Sopenharmony_ci } 43362306a36Sopenharmony_ci break; 43462306a36Sopenharmony_ci default: 43562306a36Sopenharmony_ci dev_err(da9063->dev, "Chip type not supported\n"); 43662306a36Sopenharmony_ci return -ENODEV; 43762306a36Sopenharmony_ci } 43862306a36Sopenharmony_ci 43962306a36Sopenharmony_ci da9063->regmap = devm_regmap_init_i2c(i2c, &da9063_regmap_config); 44062306a36Sopenharmony_ci if (IS_ERR(da9063->regmap)) { 44162306a36Sopenharmony_ci ret = PTR_ERR(da9063->regmap); 44262306a36Sopenharmony_ci dev_err(da9063->dev, "Failed to allocate register map: %d\n", 44362306a36Sopenharmony_ci ret); 44462306a36Sopenharmony_ci return ret; 44562306a36Sopenharmony_ci } 44662306a36Sopenharmony_ci 44762306a36Sopenharmony_ci /* If SMBus is not available and only I2C is possible, enter I2C mode */ 44862306a36Sopenharmony_ci if (i2c_check_functionality(i2c->adapter, I2C_FUNC_I2C)) { 44962306a36Sopenharmony_ci ret = regmap_clear_bits(da9063->regmap, DA9063_REG_CONFIG_J, 45062306a36Sopenharmony_ci DA9063_TWOWIRE_TO); 45162306a36Sopenharmony_ci if (ret < 0) { 45262306a36Sopenharmony_ci dev_err(da9063->dev, "Failed to set Two-Wire Bus Mode.\n"); 45362306a36Sopenharmony_ci return ret; 45462306a36Sopenharmony_ci } 45562306a36Sopenharmony_ci } 45662306a36Sopenharmony_ci 45762306a36Sopenharmony_ci return da9063_device_init(da9063, i2c->irq); 45862306a36Sopenharmony_ci} 45962306a36Sopenharmony_ci 46062306a36Sopenharmony_cistatic const struct i2c_device_id da9063_i2c_id[] = { 46162306a36Sopenharmony_ci { "da9063", PMIC_TYPE_DA9063 }, 46262306a36Sopenharmony_ci { "da9063l", PMIC_TYPE_DA9063L }, 46362306a36Sopenharmony_ci {}, 46462306a36Sopenharmony_ci}; 46562306a36Sopenharmony_ciMODULE_DEVICE_TABLE(i2c, da9063_i2c_id); 46662306a36Sopenharmony_ci 46762306a36Sopenharmony_cistatic struct i2c_driver da9063_i2c_driver = { 46862306a36Sopenharmony_ci .driver = { 46962306a36Sopenharmony_ci .name = "da9063", 47062306a36Sopenharmony_ci .of_match_table = da9063_dt_ids, 47162306a36Sopenharmony_ci }, 47262306a36Sopenharmony_ci .probe = da9063_i2c_probe, 47362306a36Sopenharmony_ci .id_table = da9063_i2c_id, 47462306a36Sopenharmony_ci}; 47562306a36Sopenharmony_ci 47662306a36Sopenharmony_cimodule_i2c_driver(da9063_i2c_driver); 477