Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

mfd: da9063: Fix revision handling to correctly select reg tables

The current implementation performs checking in the i2c_probe()
function of the variant_code but does this immediately after the
containing struct has been initialised as all zero. This means the
check for variant code will always default to using the BB tables
and will never select AD. The variant code is subsequently set
by device_init() and later used by the RTC so really it's a little
fortunate this mismatch works.

This update adds raw I2C read access functionality to read the chip
and variant/revision information (common to all revisions) so that
it can subsequently correctly choose the proper regmap tables for
real initialisation.

Signed-off-by: Adam Thomson <Adam.Thomson.Opensource@diasemi.com>
Signed-off-by: Lee Jones <lee.jones@linaro.org>

authored by

Adam Thomson and committed by
Lee Jones
091c6110 a3f673d0

+177 -53
-31
drivers/mfd/da9063-core.c
··· 160 160 161 161 int da9063_device_init(struct da9063 *da9063, unsigned int irq) 162 162 { 163 - int model, variant_id, variant_code; 164 163 int ret; 165 164 166 165 ret = da9063_clear_fault_log(da9063); ··· 169 170 da9063->flags = 0; 170 171 da9063->irq_base = -1; 171 172 da9063->chip_irq = irq; 172 - 173 - ret = regmap_read(da9063->regmap, DA9063_REG_CHIP_ID, &model); 174 - if (ret < 0) { 175 - dev_err(da9063->dev, "Cannot read chip model id.\n"); 176 - return -EIO; 177 - } 178 - if (model != PMIC_CHIP_ID_DA9063) { 179 - dev_err(da9063->dev, "Invalid chip model id: 0x%02x\n", model); 180 - return -ENODEV; 181 - } 182 - 183 - ret = regmap_read(da9063->regmap, DA9063_REG_CHIP_VARIANT, &variant_id); 184 - if (ret < 0) { 185 - dev_err(da9063->dev, "Cannot read chip variant id.\n"); 186 - return -EIO; 187 - } 188 - 189 - variant_code = variant_id >> DA9063_CHIP_VARIANT_SHIFT; 190 - 191 - dev_info(da9063->dev, 192 - "Device detected (chip-ID: 0x%02X, var-ID: 0x%02X)\n", 193 - model, variant_id); 194 - 195 - if (variant_code < PMIC_DA9063_BB && variant_code != PMIC_DA9063_AD) { 196 - dev_err(da9063->dev, 197 - "Cannot support variant code: 0x%02X\n", variant_code); 198 - return -ENODEV; 199 - } 200 - 201 - da9063->variant_code = variant_code; 202 173 203 174 ret = da9063_irq_init(da9063); 204 175 if (ret) {
+167 -17
drivers/mfd/da9063-i2c.c
··· 22 22 #include <linux/of.h> 23 23 #include <linux/regulator/of_regulator.h> 24 24 25 + /* 26 + * Raw I2C access required for just accessing chip and variant info before we 27 + * know which device is present. The info read from the device using this 28 + * approach is then used to select the correct regmap tables. 29 + */ 30 + 31 + #define DA9063_REG_PAGE_SIZE 0x100 32 + #define DA9063_REG_PAGED_ADDR_MASK 0xFF 33 + 34 + enum 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 + 40 + enum 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 + 47 + static 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 + 99 + enum { 100 + DA9063_DEV_ID_REG = 0, 101 + DA9063_VAR_ID_REG, 102 + DA9063_CHIP_ID_REGS, 103 + }; 104 + 105 + static 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 configs 135 + */ 136 + 25 137 static const struct regmap_range da9063_ad_readable_ranges[] = { 26 138 regmap_reg_range(DA9063_REG_PAGE_CON, DA9063_AD_REG_SECOND_D), 27 139 regmap_reg_range(DA9063_REG_SEQ, DA9063_REG_ID_32_31), 28 140 regmap_reg_range(DA9063_REG_SEQ_A, DA9063_REG_AUTO3_LOW), 29 141 regmap_reg_range(DA9063_REG_T_OFFSET, DA9063_AD_REG_GP_ID_19), 30 - regmap_reg_range(DA9063_REG_CHIP_ID, DA9063_REG_CHIP_VARIANT), 142 + regmap_reg_range(DA9063_REG_DEVICE_ID, DA9063_REG_VARIANT_ID), 31 143 }; 32 144 33 145 static const struct regmap_range da9063_ad_writeable_ranges[] = { ··· 184 72 regmap_reg_range(DA9063_REG_SEQ, DA9063_REG_ID_32_31), 185 73 regmap_reg_range(DA9063_REG_SEQ_A, DA9063_REG_AUTO3_LOW), 186 74 regmap_reg_range(DA9063_REG_T_OFFSET, DA9063_BB_REG_GP_ID_19), 187 - regmap_reg_range(DA9063_REG_CHIP_ID, DA9063_REG_CHIP_VARIANT), 75 + regmap_reg_range(DA9063_REG_DEVICE_ID, DA9063_REG_VARIANT_ID), 188 76 }; 189 77 190 78 static const struct regmap_range da9063_bb_writeable_ranges[] = { ··· 229 117 regmap_reg_range(DA9063_REG_SEQ, DA9063_REG_ID_32_31), 230 118 regmap_reg_range(DA9063_REG_SEQ_A, DA9063_REG_AUTO3_LOW), 231 119 regmap_reg_range(DA9063_REG_T_OFFSET, DA9063_BB_REG_GP_ID_19), 232 - regmap_reg_range(DA9063_REG_CHIP_ID, DA9063_REG_CHIP_VARIANT), 120 + regmap_reg_range(DA9063_REG_DEVICE_ID, DA9063_REG_VARIANT_ID), 233 121 }; 234 122 235 123 static const struct regmap_range da9063l_bb_writeable_ranges[] = { ··· 271 159 static const struct regmap_range_cfg da9063_range_cfg[] = { 272 160 { 273 161 .range_min = DA9063_REG_PAGE_CON, 274 - .range_max = DA9063_REG_CHIP_VARIANT, 162 + .range_max = DA9063_REG_CONFIG_ID, 275 163 .selector_reg = DA9063_REG_PAGE_CON, 276 164 .selector_mask = 1 << DA9063_I2C_PAGE_SEL_SHIFT, 277 165 .selector_shift = DA9063_I2C_PAGE_SEL_SHIFT, ··· 285 173 .val_bits = 8, 286 174 .ranges = da9063_range_cfg, 287 175 .num_ranges = ARRAY_SIZE(da9063_range_cfg), 288 - .max_register = DA9063_REG_CHIP_VARIANT, 176 + .max_register = DA9063_REG_CONFIG_ID, 289 177 290 178 .cache_type = REGCACHE_RBTREE, 291 179 }; ··· 311 199 da9063->chip_irq = i2c->irq; 312 200 da9063->type = id->driver_data; 313 201 314 - if (da9063->variant_code == PMIC_DA9063_AD) { 315 - da9063_regmap_config.rd_table = &da9063_ad_readable_table; 316 - da9063_regmap_config.wr_table = &da9063_ad_writeable_table; 317 - da9063_regmap_config.volatile_table = &da9063_ad_volatile_table; 318 - } else if (da9063->type == PMIC_TYPE_DA9063L) { 319 - da9063_regmap_config.rd_table = &da9063l_bb_readable_table; 320 - da9063_regmap_config.wr_table = &da9063l_bb_writeable_table; 321 - da9063_regmap_config.volatile_table = &da9063l_bb_volatile_table; 322 - } else { 323 - da9063_regmap_config.rd_table = &da9063_bb_readable_table; 324 - da9063_regmap_config.wr_table = &da9063_bb_writeable_table; 325 - da9063_regmap_config.volatile_table = &da9063_bb_volatile_table; 202 + ret = da9063_get_device_type(i2c, da9063); 203 + if (ret) 204 + return ret; 205 + 206 + switch (da9063->type) { 207 + case PMIC_TYPE_DA9063: 208 + switch (da9063->variant_code) { 209 + case PMIC_DA9063_AD: 210 + da9063_regmap_config.rd_table = 211 + &da9063_ad_readable_table; 212 + da9063_regmap_config.wr_table = 213 + &da9063_ad_writeable_table; 214 + da9063_regmap_config.volatile_table = 215 + &da9063_ad_volatile_table; 216 + break; 217 + case PMIC_DA9063_BB: 218 + case PMIC_DA9063_CA: 219 + da9063_regmap_config.rd_table = 220 + &da9063_bb_readable_table; 221 + da9063_regmap_config.wr_table = 222 + &da9063_bb_writeable_table; 223 + da9063_regmap_config.volatile_table = 224 + &da9063_bb_volatile_table; 225 + break; 226 + default: 227 + dev_err(da9063->dev, 228 + "Chip variant not supported for DA9063\n"); 229 + return -ENODEV; 230 + } 231 + break; 232 + case PMIC_TYPE_DA9063L: 233 + switch (da9063->variant_code) { 234 + case PMIC_DA9063_BB: 235 + case PMIC_DA9063_CA: 236 + da9063_regmap_config.rd_table = 237 + &da9063l_bb_readable_table; 238 + da9063_regmap_config.wr_table = 239 + &da9063l_bb_writeable_table; 240 + da9063_regmap_config.volatile_table = 241 + &da9063l_bb_volatile_table; 242 + break; 243 + default: 244 + dev_err(da9063->dev, 245 + "Chip variant not supported for DA9063L\n"); 246 + return -ENODEV; 247 + } 248 + break; 249 + default: 250 + dev_err(da9063->dev, "Chip type not supported\n"); 251 + return -ENODEV; 326 252 } 327 253 328 254 da9063->regmap = devm_regmap_init_i2c(i2c, &da9063_regmap_config);
+10 -5
include/linux/mfd/da9063/registers.h
··· 292 292 #define DA9063_BB_REG_GP_ID_19 0x134 293 293 294 294 /* Chip ID and variant */ 295 - #define DA9063_REG_CHIP_ID 0x181 296 - #define DA9063_REG_CHIP_VARIANT 0x182 295 + #define DA9063_REG_DEVICE_ID 0x181 296 + #define DA9063_REG_VARIANT_ID 0x182 297 + #define DA9063_REG_CUSTOMER_ID 0x183 298 + #define DA9063_REG_CONFIG_ID 0x184 297 299 298 300 /* 299 301 * PMIC registers bits ··· 931 929 #define DA9063_RTC_CLOCK 0x40 932 930 #define DA9063_OUT_32K_EN 0x80 933 931 934 - /* DA9063_REG_CHIP_VARIANT */ 935 - #define DA9063_CHIP_VARIANT_SHIFT 4 936 - 937 932 /* DA9063_REG_BUCK_ILIM_A (addr=0x9A) */ 938 933 #define DA9063_BIO_ILIM_MASK 0x0F 939 934 #define DA9063_BMEM_ILIM_MASK 0xF0 ··· 1063 1064 #define DA9063_MON_A10_IDX_LDO8 0x03 1064 1065 #define DA9063_MON_A10_IDX_LDO9 0x04 1065 1066 #define DA9063_MON_A10_IDX_LDO10 0x05 1067 + 1068 + /* DA9063_REG_VARIANT_ID (addr=0x182) */ 1069 + #define DA9063_VARIANT_ID_VRC_SHIFT 0 1070 + #define DA9063_VARIANT_ID_VRC_MASK 0x0F 1071 + #define DA9063_VARIANT_ID_MRC_SHIFT 4 1072 + #define DA9063_VARIANT_ID_MRC_MASK 0xF0 1066 1073 1067 1074 #endif /* _DA9063_REG_H */