0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #include <linux/i2c.h>
0012 #include <linux/interrupt.h>
0013 #include <linux/mfd/core.h>
0014 #include <linux/mfd/rohm-generic.h>
0015 #include <linux/module.h>
0016
0017 #include <linux/mfd/bd9571mwv.h>
0018
0019 static const struct mfd_cell bd9571mwv_cells[] = {
0020 { .name = "bd9571mwv-regulator", },
0021 { .name = "bd9571mwv-gpio", },
0022 };
0023
0024 static const struct regmap_range bd9571mwv_readable_yes_ranges[] = {
0025 regmap_reg_range(BD9571MWV_VENDOR_CODE, BD9571MWV_PRODUCT_REVISION),
0026 regmap_reg_range(BD9571MWV_BKUP_MODE_CNT, BD9571MWV_BKUP_MODE_CNT),
0027 regmap_reg_range(BD9571MWV_AVS_SET_MONI, BD9571MWV_AVS_DVFS_VID(3)),
0028 regmap_reg_range(BD9571MWV_VD18_VID, BD9571MWV_VD33_VID),
0029 regmap_reg_range(BD9571MWV_DVFS_VINIT, BD9571MWV_DVFS_VINIT),
0030 regmap_reg_range(BD9571MWV_DVFS_SETVMAX, BD9571MWV_DVFS_MONIVDAC),
0031 regmap_reg_range(BD9571MWV_GPIO_IN, BD9571MWV_GPIO_IN),
0032 regmap_reg_range(BD9571MWV_GPIO_INT, BD9571MWV_GPIO_INTMASK),
0033 regmap_reg_range(BD9571MWV_INT_INTREQ, BD9571MWV_INT_INTMASK),
0034 };
0035
0036 static const struct regmap_access_table bd9571mwv_readable_table = {
0037 .yes_ranges = bd9571mwv_readable_yes_ranges,
0038 .n_yes_ranges = ARRAY_SIZE(bd9571mwv_readable_yes_ranges),
0039 };
0040
0041 static const struct regmap_range bd9571mwv_writable_yes_ranges[] = {
0042 regmap_reg_range(BD9571MWV_BKUP_MODE_CNT, BD9571MWV_BKUP_MODE_CNT),
0043 regmap_reg_range(BD9571MWV_AVS_VD09_VID(0), BD9571MWV_AVS_VD09_VID(3)),
0044 regmap_reg_range(BD9571MWV_DVFS_SETVID, BD9571MWV_DVFS_SETVID),
0045 regmap_reg_range(BD9571MWV_GPIO_DIR, BD9571MWV_GPIO_OUT),
0046 regmap_reg_range(BD9571MWV_GPIO_INT_SET, BD9571MWV_GPIO_INTMASK),
0047 regmap_reg_range(BD9571MWV_INT_INTREQ, BD9571MWV_INT_INTMASK),
0048 };
0049
0050 static const struct regmap_access_table bd9571mwv_writable_table = {
0051 .yes_ranges = bd9571mwv_writable_yes_ranges,
0052 .n_yes_ranges = ARRAY_SIZE(bd9571mwv_writable_yes_ranges),
0053 };
0054
0055 static const struct regmap_range bd9571mwv_volatile_yes_ranges[] = {
0056 regmap_reg_range(BD9571MWV_DVFS_MONIVDAC, BD9571MWV_DVFS_MONIVDAC),
0057 regmap_reg_range(BD9571MWV_GPIO_IN, BD9571MWV_GPIO_IN),
0058 regmap_reg_range(BD9571MWV_GPIO_INT, BD9571MWV_GPIO_INT),
0059 regmap_reg_range(BD9571MWV_INT_INTREQ, BD9571MWV_INT_INTREQ),
0060 };
0061
0062 static const struct regmap_access_table bd9571mwv_volatile_table = {
0063 .yes_ranges = bd9571mwv_volatile_yes_ranges,
0064 .n_yes_ranges = ARRAY_SIZE(bd9571mwv_volatile_yes_ranges),
0065 };
0066
0067 static const struct regmap_config bd9571mwv_regmap_config = {
0068 .reg_bits = 8,
0069 .val_bits = 8,
0070 .cache_type = REGCACHE_RBTREE,
0071 .rd_table = &bd9571mwv_readable_table,
0072 .wr_table = &bd9571mwv_writable_table,
0073 .volatile_table = &bd9571mwv_volatile_table,
0074 .max_register = 0xff,
0075 };
0076
0077 static const struct regmap_irq bd9571mwv_irqs[] = {
0078 REGMAP_IRQ_REG(BD9571MWV_IRQ_MD1, 0,
0079 BD9571MWV_INT_INTREQ_MD1_INT),
0080 REGMAP_IRQ_REG(BD9571MWV_IRQ_MD2_E1, 0,
0081 BD9571MWV_INT_INTREQ_MD2_E1_INT),
0082 REGMAP_IRQ_REG(BD9571MWV_IRQ_MD2_E2, 0,
0083 BD9571MWV_INT_INTREQ_MD2_E2_INT),
0084 REGMAP_IRQ_REG(BD9571MWV_IRQ_PROT_ERR, 0,
0085 BD9571MWV_INT_INTREQ_PROT_ERR_INT),
0086 REGMAP_IRQ_REG(BD9571MWV_IRQ_GP, 0,
0087 BD9571MWV_INT_INTREQ_GP_INT),
0088 REGMAP_IRQ_REG(BD9571MWV_IRQ_128H_OF, 0,
0089 BD9571MWV_INT_INTREQ_128H_OF_INT),
0090 REGMAP_IRQ_REG(BD9571MWV_IRQ_WDT_OF, 0,
0091 BD9571MWV_INT_INTREQ_WDT_OF_INT),
0092 REGMAP_IRQ_REG(BD9571MWV_IRQ_BKUP_TRG, 0,
0093 BD9571MWV_INT_INTREQ_BKUP_TRG_INT),
0094 };
0095
0096 static struct regmap_irq_chip bd9571mwv_irq_chip = {
0097 .name = "bd9571mwv",
0098 .status_base = BD9571MWV_INT_INTREQ,
0099 .mask_base = BD9571MWV_INT_INTMASK,
0100 .ack_base = BD9571MWV_INT_INTREQ,
0101 .init_ack_masked = true,
0102 .num_regs = 1,
0103 .irqs = bd9571mwv_irqs,
0104 .num_irqs = ARRAY_SIZE(bd9571mwv_irqs),
0105 };
0106
0107 static const struct mfd_cell bd9574mwf_cells[] = {
0108 { .name = "bd9574mwf-regulator", },
0109 { .name = "bd9574mwf-gpio", },
0110 };
0111
0112 static const struct regmap_range bd9574mwf_readable_yes_ranges[] = {
0113 regmap_reg_range(BD9571MWV_VENDOR_CODE, BD9571MWV_PRODUCT_REVISION),
0114 regmap_reg_range(BD9571MWV_BKUP_MODE_CNT, BD9571MWV_BKUP_MODE_CNT),
0115 regmap_reg_range(BD9571MWV_DVFS_VINIT, BD9571MWV_DVFS_SETVMAX),
0116 regmap_reg_range(BD9571MWV_DVFS_SETVID, BD9571MWV_DVFS_MONIVDAC),
0117 regmap_reg_range(BD9571MWV_GPIO_IN, BD9571MWV_GPIO_IN),
0118 regmap_reg_range(BD9571MWV_GPIO_INT, BD9571MWV_GPIO_INTMASK),
0119 regmap_reg_range(BD9571MWV_INT_INTREQ, BD9571MWV_INT_INTMASK),
0120 };
0121
0122 static const struct regmap_access_table bd9574mwf_readable_table = {
0123 .yes_ranges = bd9574mwf_readable_yes_ranges,
0124 .n_yes_ranges = ARRAY_SIZE(bd9574mwf_readable_yes_ranges),
0125 };
0126
0127 static const struct regmap_range bd9574mwf_writable_yes_ranges[] = {
0128 regmap_reg_range(BD9571MWV_BKUP_MODE_CNT, BD9571MWV_BKUP_MODE_CNT),
0129 regmap_reg_range(BD9571MWV_DVFS_SETVID, BD9571MWV_DVFS_SETVID),
0130 regmap_reg_range(BD9571MWV_GPIO_DIR, BD9571MWV_GPIO_OUT),
0131 regmap_reg_range(BD9571MWV_GPIO_INT_SET, BD9571MWV_GPIO_INTMASK),
0132 regmap_reg_range(BD9571MWV_INT_INTREQ, BD9571MWV_INT_INTMASK),
0133 };
0134
0135 static const struct regmap_access_table bd9574mwf_writable_table = {
0136 .yes_ranges = bd9574mwf_writable_yes_ranges,
0137 .n_yes_ranges = ARRAY_SIZE(bd9574mwf_writable_yes_ranges),
0138 };
0139
0140 static const struct regmap_range bd9574mwf_volatile_yes_ranges[] = {
0141 regmap_reg_range(BD9571MWV_DVFS_MONIVDAC, BD9571MWV_DVFS_MONIVDAC),
0142 regmap_reg_range(BD9571MWV_GPIO_IN, BD9571MWV_GPIO_IN),
0143 regmap_reg_range(BD9571MWV_GPIO_INT, BD9571MWV_GPIO_INT),
0144 regmap_reg_range(BD9571MWV_INT_INTREQ, BD9571MWV_INT_INTREQ),
0145 };
0146
0147 static const struct regmap_access_table bd9574mwf_volatile_table = {
0148 .yes_ranges = bd9574mwf_volatile_yes_ranges,
0149 .n_yes_ranges = ARRAY_SIZE(bd9574mwf_volatile_yes_ranges),
0150 };
0151
0152 static const struct regmap_config bd9574mwf_regmap_config = {
0153 .reg_bits = 8,
0154 .val_bits = 8,
0155 .cache_type = REGCACHE_RBTREE,
0156 .rd_table = &bd9574mwf_readable_table,
0157 .wr_table = &bd9574mwf_writable_table,
0158 .volatile_table = &bd9574mwf_volatile_table,
0159 .max_register = 0xff,
0160 };
0161
0162 static struct regmap_irq_chip bd9574mwf_irq_chip = {
0163 .name = "bd9574mwf",
0164 .status_base = BD9571MWV_INT_INTREQ,
0165 .mask_base = BD9571MWV_INT_INTMASK,
0166 .ack_base = BD9571MWV_INT_INTREQ,
0167 .init_ack_masked = true,
0168 .num_regs = 1,
0169 .irqs = bd9571mwv_irqs,
0170 .num_irqs = ARRAY_SIZE(bd9571mwv_irqs),
0171 };
0172
0173 static int bd957x_identify(struct device *dev, struct regmap *regmap)
0174 {
0175 unsigned int value;
0176 int ret;
0177
0178 ret = regmap_read(regmap, BD9571MWV_VENDOR_CODE, &value);
0179 if (ret) {
0180 dev_err(dev, "Failed to read vendor code register (ret=%i)\n",
0181 ret);
0182 return ret;
0183 }
0184
0185 if (value != BD9571MWV_VENDOR_CODE_VAL) {
0186 dev_err(dev, "Invalid vendor code ID %02x (expected %02x)\n",
0187 value, BD9571MWV_VENDOR_CODE_VAL);
0188 return -EINVAL;
0189 }
0190
0191 ret = regmap_read(regmap, BD9571MWV_PRODUCT_CODE, &value);
0192 if (ret) {
0193 dev_err(dev, "Failed to read product code register (ret=%i)\n",
0194 ret);
0195 return ret;
0196 }
0197 ret = regmap_read(regmap, BD9571MWV_PRODUCT_REVISION, &value);
0198 if (ret) {
0199 dev_err(dev, "Failed to read revision register (ret=%i)\n",
0200 ret);
0201 return ret;
0202 }
0203
0204 return 0;
0205 }
0206
0207 static int bd9571mwv_probe(struct i2c_client *client,
0208 const struct i2c_device_id *ids)
0209 {
0210 const struct regmap_config *regmap_config;
0211 const struct regmap_irq_chip *irq_chip;
0212 const struct mfd_cell *cells;
0213 struct device *dev = &client->dev;
0214 struct regmap *regmap;
0215 struct regmap_irq_chip_data *irq_data;
0216 int ret, num_cells, irq = client->irq;
0217
0218
0219 ret = i2c_smbus_read_byte_data(client, BD9571MWV_PRODUCT_CODE);
0220 if (ret < 0) {
0221 dev_err(dev, "Failed to read product code\n");
0222 return ret;
0223 }
0224
0225 switch (ret) {
0226 case BD9571MWV_PRODUCT_CODE_BD9571MWV:
0227 regmap_config = &bd9571mwv_regmap_config;
0228 irq_chip = &bd9571mwv_irq_chip;
0229 cells = bd9571mwv_cells;
0230 num_cells = ARRAY_SIZE(bd9571mwv_cells);
0231 break;
0232 case BD9571MWV_PRODUCT_CODE_BD9574MWF:
0233 regmap_config = &bd9574mwf_regmap_config;
0234 irq_chip = &bd9574mwf_irq_chip;
0235 cells = bd9574mwf_cells;
0236 num_cells = ARRAY_SIZE(bd9574mwf_cells);
0237 break;
0238 default:
0239 dev_err(dev, "Unsupported device 0x%x\n", ret);
0240 return -ENODEV;
0241 }
0242
0243 regmap = devm_regmap_init_i2c(client, regmap_config);
0244 if (IS_ERR(regmap)) {
0245 dev_err(dev, "Failed to initialize register map\n");
0246 return PTR_ERR(regmap);
0247 }
0248
0249 ret = bd957x_identify(dev, regmap);
0250 if (ret)
0251 return ret;
0252
0253 ret = devm_regmap_add_irq_chip(dev, regmap, irq, IRQF_ONESHOT, 0,
0254 irq_chip, &irq_data);
0255 if (ret) {
0256 dev_err(dev, "Failed to register IRQ chip\n");
0257 return ret;
0258 }
0259
0260 return devm_mfd_add_devices(dev, PLATFORM_DEVID_AUTO, cells, num_cells,
0261 NULL, 0, regmap_irq_get_domain(irq_data));
0262 }
0263
0264 static const struct of_device_id bd9571mwv_of_match_table[] = {
0265 { .compatible = "rohm,bd9571mwv", },
0266 { .compatible = "rohm,bd9574mwf", },
0267 { }
0268 };
0269 MODULE_DEVICE_TABLE(of, bd9571mwv_of_match_table);
0270
0271 static const struct i2c_device_id bd9571mwv_id_table[] = {
0272 { "bd9571mwv", 0 },
0273 { }
0274 };
0275 MODULE_DEVICE_TABLE(i2c, bd9571mwv_id_table);
0276
0277 static struct i2c_driver bd9571mwv_driver = {
0278 .driver = {
0279 .name = "bd9571mwv",
0280 .of_match_table = bd9571mwv_of_match_table,
0281 },
0282 .probe = bd9571mwv_probe,
0283 .id_table = bd9571mwv_id_table,
0284 };
0285 module_i2c_driver(bd9571mwv_driver);
0286
0287 MODULE_AUTHOR("Marek Vasut <marek.vasut+renesas@gmail.com>");
0288 MODULE_DESCRIPTION("BD9571MWV PMIC Driver");
0289 MODULE_LICENSE("GPL v2");