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 { 209 const struct regmap_config *regmap_config; 210 const struct regmap_irq_chip *irq_chip; 211 const struct mfd_cell *cells; 212 struct device *dev = &client->dev; 213 struct regmap *regmap; 214 struct regmap_irq_chip_data *irq_data; 215 int ret, num_cells, irq = client->irq; 216 217 /* Read the PMIC product code */ 218 ret = i2c_smbus_read_byte_data(client, BD9571MWV_PRODUCT_CODE); 219 if (ret < 0) { 220 dev_err(dev, "Failed to read product code\n"); 221 return ret; 222 } 223 224 switch (ret) { 225 case BD9571MWV_PRODUCT_CODE_BD9571MWV: 226 regmap_config = &bd9571mwv_regmap_config; 227 irq_chip = &bd9571mwv_irq_chip; 228 cells = bd9571mwv_cells; 229 num_cells = ARRAY_SIZE(bd9571mwv_cells); 230 break; 231 case BD9571MWV_PRODUCT_CODE_BD9574MWF: 232 regmap_config = &bd9574mwf_regmap_config; 233 irq_chip = &bd9574mwf_irq_chip; 234 cells = bd9574mwf_cells; 235 num_cells = ARRAY_SIZE(bd9574mwf_cells); 236 break; 237 default: 238 dev_err(dev, "Unsupported device 0x%x\n", ret); 239 return -ENODEV; 240 } 241 242 regmap = devm_regmap_init_i2c(client, regmap_config); 243 if (IS_ERR(regmap)) { 244 dev_err(dev, "Failed to initialize register map\n"); 245 return PTR_ERR(regmap); 246 } 247 248 ret = bd957x_identify(dev, regmap); 249 if (ret) 250 return ret; 251 252 ret = devm_regmap_add_irq_chip(dev, regmap, irq, IRQF_ONESHOT, 0, 253 irq_chip, &irq_data); 254 if (ret) { 255 dev_err(dev, "Failed to register IRQ chip\n"); 256 return ret; 257 } 258 259 return devm_mfd_add_devices(dev, PLATFORM_DEVID_AUTO, cells, num_cells, 260 NULL, 0, regmap_irq_get_domain(irq_data)); 261 } 262 263 static const struct of_device_id bd9571mwv_of_match_table[] = { 264 { .compatible = "rohm,bd9571mwv", }, 265 { .compatible = "rohm,bd9574mwf", }, 266 { /* sentinel */ } 267 }; 268 MODULE_DEVICE_TABLE(of, bd9571mwv_of_match_table); 269 270 static const struct i2c_device_id bd9571mwv_id_table[] = { 271 { "bd9571mwv", 0 }, 272 { /* sentinel */ } 273 }; 274 MODULE_DEVICE_TABLE(i2c, bd9571mwv_id_table); 275 276 static struct i2c_driver bd9571mwv_driver = { 277 .driver = { 278 .name = "bd9571mwv", 279 .of_match_table = bd9571mwv_of_match_table, 280 }, 281 .probe = bd9571mwv_probe, 282 .id_table = bd9571mwv_id_table, 283 }; 284 module_i2c_driver(bd9571mwv_driver); 285 286 MODULE_AUTHOR("Marek Vasut <marek.vasut+renesas@gmail.com>"); 287 MODULE_DESCRIPTION("BD9571MWV PMIC Driver"); 288 MODULE_LICENSE("GPL v2"); 289