bd9571mwv.c (9400B)
1// SPDX-License-Identifier: GPL-2.0-only 2/* 3 * ROHM BD9571MWV-M and BD9574MVF-M core driver 4 * 5 * Copyright (C) 2017 Marek Vasut <marek.vasut+renesas@gmail.com> 6 * Copyright (C) 2020 Renesas Electronics Corporation 7 * 8 * Based on the TPS65086 driver 9 */ 10 11#include <linux/i2c.h> 12#include <linux/interrupt.h> 13#include <linux/mfd/core.h> 14#include <linux/mfd/rohm-generic.h> 15#include <linux/module.h> 16 17#include <linux/mfd/bd9571mwv.h> 18 19static const struct mfd_cell bd9571mwv_cells[] = { 20 { .name = "bd9571mwv-regulator", }, 21 { .name = "bd9571mwv-gpio", }, 22}; 23 24static const struct regmap_range bd9571mwv_readable_yes_ranges[] = { 25 regmap_reg_range(BD9571MWV_VENDOR_CODE, BD9571MWV_PRODUCT_REVISION), 26 regmap_reg_range(BD9571MWV_BKUP_MODE_CNT, BD9571MWV_BKUP_MODE_CNT), 27 regmap_reg_range(BD9571MWV_AVS_SET_MONI, BD9571MWV_AVS_DVFS_VID(3)), 28 regmap_reg_range(BD9571MWV_VD18_VID, BD9571MWV_VD33_VID), 29 regmap_reg_range(BD9571MWV_DVFS_VINIT, BD9571MWV_DVFS_VINIT), 30 regmap_reg_range(BD9571MWV_DVFS_SETVMAX, BD9571MWV_DVFS_MONIVDAC), 31 regmap_reg_range(BD9571MWV_GPIO_IN, BD9571MWV_GPIO_IN), 32 regmap_reg_range(BD9571MWV_GPIO_INT, BD9571MWV_GPIO_INTMASK), 33 regmap_reg_range(BD9571MWV_INT_INTREQ, BD9571MWV_INT_INTMASK), 34}; 35 36static const struct regmap_access_table bd9571mwv_readable_table = { 37 .yes_ranges = bd9571mwv_readable_yes_ranges, 38 .n_yes_ranges = ARRAY_SIZE(bd9571mwv_readable_yes_ranges), 39}; 40 41static const struct regmap_range bd9571mwv_writable_yes_ranges[] = { 42 regmap_reg_range(BD9571MWV_BKUP_MODE_CNT, BD9571MWV_BKUP_MODE_CNT), 43 regmap_reg_range(BD9571MWV_AVS_VD09_VID(0), BD9571MWV_AVS_VD09_VID(3)), 44 regmap_reg_range(BD9571MWV_DVFS_SETVID, BD9571MWV_DVFS_SETVID), 45 regmap_reg_range(BD9571MWV_GPIO_DIR, BD9571MWV_GPIO_OUT), 46 regmap_reg_range(BD9571MWV_GPIO_INT_SET, BD9571MWV_GPIO_INTMASK), 47 regmap_reg_range(BD9571MWV_INT_INTREQ, BD9571MWV_INT_INTMASK), 48}; 49 50static const struct regmap_access_table bd9571mwv_writable_table = { 51 .yes_ranges = bd9571mwv_writable_yes_ranges, 52 .n_yes_ranges = ARRAY_SIZE(bd9571mwv_writable_yes_ranges), 53}; 54 55static const struct regmap_range bd9571mwv_volatile_yes_ranges[] = { 56 regmap_reg_range(BD9571MWV_DVFS_MONIVDAC, BD9571MWV_DVFS_MONIVDAC), 57 regmap_reg_range(BD9571MWV_GPIO_IN, BD9571MWV_GPIO_IN), 58 regmap_reg_range(BD9571MWV_GPIO_INT, BD9571MWV_GPIO_INT), 59 regmap_reg_range(BD9571MWV_INT_INTREQ, BD9571MWV_INT_INTREQ), 60}; 61 62static const struct regmap_access_table bd9571mwv_volatile_table = { 63 .yes_ranges = bd9571mwv_volatile_yes_ranges, 64 .n_yes_ranges = ARRAY_SIZE(bd9571mwv_volatile_yes_ranges), 65}; 66 67static const struct regmap_config bd9571mwv_regmap_config = { 68 .reg_bits = 8, 69 .val_bits = 8, 70 .cache_type = REGCACHE_RBTREE, 71 .rd_table = &bd9571mwv_readable_table, 72 .wr_table = &bd9571mwv_writable_table, 73 .volatile_table = &bd9571mwv_volatile_table, 74 .max_register = 0xff, 75}; 76 77static const struct regmap_irq bd9571mwv_irqs[] = { 78 REGMAP_IRQ_REG(BD9571MWV_IRQ_MD1, 0, 79 BD9571MWV_INT_INTREQ_MD1_INT), 80 REGMAP_IRQ_REG(BD9571MWV_IRQ_MD2_E1, 0, 81 BD9571MWV_INT_INTREQ_MD2_E1_INT), 82 REGMAP_IRQ_REG(BD9571MWV_IRQ_MD2_E2, 0, 83 BD9571MWV_INT_INTREQ_MD2_E2_INT), 84 REGMAP_IRQ_REG(BD9571MWV_IRQ_PROT_ERR, 0, 85 BD9571MWV_INT_INTREQ_PROT_ERR_INT), 86 REGMAP_IRQ_REG(BD9571MWV_IRQ_GP, 0, 87 BD9571MWV_INT_INTREQ_GP_INT), 88 REGMAP_IRQ_REG(BD9571MWV_IRQ_128H_OF, 0, 89 BD9571MWV_INT_INTREQ_128H_OF_INT), 90 REGMAP_IRQ_REG(BD9571MWV_IRQ_WDT_OF, 0, 91 BD9571MWV_INT_INTREQ_WDT_OF_INT), 92 REGMAP_IRQ_REG(BD9571MWV_IRQ_BKUP_TRG, 0, 93 BD9571MWV_INT_INTREQ_BKUP_TRG_INT), 94}; 95 96static struct regmap_irq_chip bd9571mwv_irq_chip = { 97 .name = "bd9571mwv", 98 .status_base = BD9571MWV_INT_INTREQ, 99 .mask_base = BD9571MWV_INT_INTMASK, 100 .ack_base = BD9571MWV_INT_INTREQ, 101 .init_ack_masked = true, 102 .num_regs = 1, 103 .irqs = bd9571mwv_irqs, 104 .num_irqs = ARRAY_SIZE(bd9571mwv_irqs), 105}; 106 107static const struct mfd_cell bd9574mwf_cells[] = { 108 { .name = "bd9574mwf-regulator", }, 109 { .name = "bd9574mwf-gpio", }, 110}; 111 112static const struct regmap_range bd9574mwf_readable_yes_ranges[] = { 113 regmap_reg_range(BD9571MWV_VENDOR_CODE, BD9571MWV_PRODUCT_REVISION), 114 regmap_reg_range(BD9571MWV_BKUP_MODE_CNT, BD9571MWV_BKUP_MODE_CNT), 115 regmap_reg_range(BD9571MWV_DVFS_VINIT, BD9571MWV_DVFS_SETVMAX), 116 regmap_reg_range(BD9571MWV_DVFS_SETVID, BD9571MWV_DVFS_MONIVDAC), 117 regmap_reg_range(BD9571MWV_GPIO_IN, BD9571MWV_GPIO_IN), 118 regmap_reg_range(BD9571MWV_GPIO_INT, BD9571MWV_GPIO_INTMASK), 119 regmap_reg_range(BD9571MWV_INT_INTREQ, BD9571MWV_INT_INTMASK), 120}; 121 122static const struct regmap_access_table bd9574mwf_readable_table = { 123 .yes_ranges = bd9574mwf_readable_yes_ranges, 124 .n_yes_ranges = ARRAY_SIZE(bd9574mwf_readable_yes_ranges), 125}; 126 127static const struct regmap_range bd9574mwf_writable_yes_ranges[] = { 128 regmap_reg_range(BD9571MWV_BKUP_MODE_CNT, BD9571MWV_BKUP_MODE_CNT), 129 regmap_reg_range(BD9571MWV_DVFS_SETVID, BD9571MWV_DVFS_SETVID), 130 regmap_reg_range(BD9571MWV_GPIO_DIR, BD9571MWV_GPIO_OUT), 131 regmap_reg_range(BD9571MWV_GPIO_INT_SET, BD9571MWV_GPIO_INTMASK), 132 regmap_reg_range(BD9571MWV_INT_INTREQ, BD9571MWV_INT_INTMASK), 133}; 134 135static const struct regmap_access_table bd9574mwf_writable_table = { 136 .yes_ranges = bd9574mwf_writable_yes_ranges, 137 .n_yes_ranges = ARRAY_SIZE(bd9574mwf_writable_yes_ranges), 138}; 139 140static const struct regmap_range bd9574mwf_volatile_yes_ranges[] = { 141 regmap_reg_range(BD9571MWV_DVFS_MONIVDAC, BD9571MWV_DVFS_MONIVDAC), 142 regmap_reg_range(BD9571MWV_GPIO_IN, BD9571MWV_GPIO_IN), 143 regmap_reg_range(BD9571MWV_GPIO_INT, BD9571MWV_GPIO_INT), 144 regmap_reg_range(BD9571MWV_INT_INTREQ, BD9571MWV_INT_INTREQ), 145}; 146 147static const struct regmap_access_table bd9574mwf_volatile_table = { 148 .yes_ranges = bd9574mwf_volatile_yes_ranges, 149 .n_yes_ranges = ARRAY_SIZE(bd9574mwf_volatile_yes_ranges), 150}; 151 152static const struct regmap_config bd9574mwf_regmap_config = { 153 .reg_bits = 8, 154 .val_bits = 8, 155 .cache_type = REGCACHE_RBTREE, 156 .rd_table = &bd9574mwf_readable_table, 157 .wr_table = &bd9574mwf_writable_table, 158 .volatile_table = &bd9574mwf_volatile_table, 159 .max_register = 0xff, 160}; 161 162static struct regmap_irq_chip bd9574mwf_irq_chip = { 163 .name = "bd9574mwf", 164 .status_base = BD9571MWV_INT_INTREQ, 165 .mask_base = BD9571MWV_INT_INTMASK, 166 .ack_base = BD9571MWV_INT_INTREQ, 167 .init_ack_masked = true, 168 .num_regs = 1, 169 .irqs = bd9571mwv_irqs, 170 .num_irqs = ARRAY_SIZE(bd9571mwv_irqs), 171}; 172 173static int bd957x_identify(struct device *dev, struct regmap *regmap) 174{ 175 unsigned int value; 176 int ret; 177 178 ret = regmap_read(regmap, BD9571MWV_VENDOR_CODE, &value); 179 if (ret) { 180 dev_err(dev, "Failed to read vendor code register (ret=%i)\n", 181 ret); 182 return ret; 183 } 184 185 if (value != BD9571MWV_VENDOR_CODE_VAL) { 186 dev_err(dev, "Invalid vendor code ID %02x (expected %02x)\n", 187 value, BD9571MWV_VENDOR_CODE_VAL); 188 return -EINVAL; 189 } 190 191 ret = regmap_read(regmap, BD9571MWV_PRODUCT_CODE, &value); 192 if (ret) { 193 dev_err(dev, "Failed to read product code register (ret=%i)\n", 194 ret); 195 return ret; 196 } 197 ret = regmap_read(regmap, BD9571MWV_PRODUCT_REVISION, &value); 198 if (ret) { 199 dev_err(dev, "Failed to read revision register (ret=%i)\n", 200 ret); 201 return ret; 202 } 203 204 return 0; 205} 206 207static int bd9571mwv_probe(struct i2c_client *client, 208 const struct i2c_device_id *ids) 209{ 210 const struct regmap_config *regmap_config; 211 const struct regmap_irq_chip *irq_chip; 212 const struct mfd_cell *cells; 213 struct device *dev = &client->dev; 214 struct regmap *regmap; 215 struct regmap_irq_chip_data *irq_data; 216 int ret, num_cells, irq = client->irq; 217 218 /* Read the PMIC product code */ 219 ret = i2c_smbus_read_byte_data(client, BD9571MWV_PRODUCT_CODE); 220 if (ret < 0) { 221 dev_err(dev, "Failed to read product code\n"); 222 return ret; 223 } 224 225 switch (ret) { 226 case BD9571MWV_PRODUCT_CODE_BD9571MWV: 227 regmap_config = &bd9571mwv_regmap_config; 228 irq_chip = &bd9571mwv_irq_chip; 229 cells = bd9571mwv_cells; 230 num_cells = ARRAY_SIZE(bd9571mwv_cells); 231 break; 232 case BD9571MWV_PRODUCT_CODE_BD9574MWF: 233 regmap_config = &bd9574mwf_regmap_config; 234 irq_chip = &bd9574mwf_irq_chip; 235 cells = bd9574mwf_cells; 236 num_cells = ARRAY_SIZE(bd9574mwf_cells); 237 break; 238 default: 239 dev_err(dev, "Unsupported device 0x%x\n", ret); 240 return -ENODEV; 241 } 242 243 regmap = devm_regmap_init_i2c(client, regmap_config); 244 if (IS_ERR(regmap)) { 245 dev_err(dev, "Failed to initialize register map\n"); 246 return PTR_ERR(regmap); 247 } 248 249 ret = bd957x_identify(dev, regmap); 250 if (ret) 251 return ret; 252 253 ret = devm_regmap_add_irq_chip(dev, regmap, irq, IRQF_ONESHOT, 0, 254 irq_chip, &irq_data); 255 if (ret) { 256 dev_err(dev, "Failed to register IRQ chip\n"); 257 return ret; 258 } 259 260 return devm_mfd_add_devices(dev, PLATFORM_DEVID_AUTO, cells, num_cells, 261 NULL, 0, regmap_irq_get_domain(irq_data)); 262} 263 264static const struct of_device_id bd9571mwv_of_match_table[] = { 265 { .compatible = "rohm,bd9571mwv", }, 266 { .compatible = "rohm,bd9574mwf", }, 267 { /* sentinel */ } 268}; 269MODULE_DEVICE_TABLE(of, bd9571mwv_of_match_table); 270 271static const struct i2c_device_id bd9571mwv_id_table[] = { 272 { "bd9571mwv", 0 }, 273 { /* sentinel */ } 274}; 275MODULE_DEVICE_TABLE(i2c, bd9571mwv_id_table); 276 277static struct i2c_driver bd9571mwv_driver = { 278 .driver = { 279 .name = "bd9571mwv", 280 .of_match_table = bd9571mwv_of_match_table, 281 }, 282 .probe = bd9571mwv_probe, 283 .id_table = bd9571mwv_id_table, 284}; 285module_i2c_driver(bd9571mwv_driver); 286 287MODULE_AUTHOR("Marek Vasut <marek.vasut+renesas@gmail.com>"); 288MODULE_DESCRIPTION("BD9571MWV PMIC Driver"); 289MODULE_LICENSE("GPL v2");