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 19 static const struct mfd_cell bd9571mwv_cells[] = { 20 { .name = "bd9571mwv-regulator", }, 21 { .name = "bd9571mwv-gpio", }, 22 }; 23 24 static 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 36 static 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 41 static 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 50 static 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 55 static 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 62 static 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 67 static 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 77 static 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 96 static 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 107 static const struct mfd_cell bd9574mwf_cells[] = { 108 { .name = "bd9574mwf-regulator", }, 109 { .name = "bd9574mwf-gpio", }, 110 }; 111 112 static 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 122 static 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 127 static 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 135 static 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 140 static 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 147 static 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 152 static 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 162 static 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 173 static 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 207 static 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 264 static const struct of_device_id bd9571mwv_of_match_table[] = { 265 { .compatible = "rohm,bd9571mwv", }, 266 { .compatible = "rohm,bd9574mwf", }, 267 { /* sentinel */ } 268 }; 269 MODULE_DEVICE_TABLE(of, bd9571mwv_of_match_table); 270 271 static const struct i2c_device_id bd9571mwv_id_table[] = { 272 { "bd9571mwv", 0 }, 273 { /* sentinel */ } 274 }; 275 MODULE_DEVICE_TABLE(i2c, bd9571mwv_id_table); 276 277 static 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 }; 285 module_i2c_driver(bd9571mwv_driver); 286 287 MODULE_AUTHOR("Marek Vasut <marek.vasut+renesas@gmail.com>"); 288 MODULE_DESCRIPTION("BD9571MWV PMIC Driver"); 289 MODULE_LICENSE("GPL v2"); 290