Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * ROHM BD9571MWV-M and BD9574MVF-M core driver
0004  *
0005  * Copyright (C) 2017 Marek Vasut <marek.vasut+renesas@gmail.com>
0006  * Copyright (C) 2020 Renesas Electronics Corporation
0007  *
0008  * Based on the TPS65086 driver
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     /* Read the PMIC product code */
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     { /* sentinel */ }
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     { /* sentinel */ }
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");