cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

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");