xref: /openbmc/linux/drivers/mfd/bd9571mwv.c (revision 1e40a92c651f4bb383df757b69821f74820b6e6a)
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * ROHM BD9571MWV-M MFD driver
4  *
5  * Copyright (C) 2017 Marek Vasut <marek.vasut+renesas@gmail.com>
6  *
7  * Based on the TPS65086 driver
8  */
9 
10 #include <linux/i2c.h>
11 #include <linux/interrupt.h>
12 #include <linux/mfd/core.h>
13 #include <linux/module.h>
14 
15 #include <linux/mfd/bd9571mwv.h>
16 
17 static const struct mfd_cell bd9571mwv_cells[] = {
18 	{ .name = "bd9571mwv-regulator", },
19 	{ .name = "bd9571mwv-gpio", },
20 };
21 
22 static const struct regmap_range bd9571mwv_readable_yes_ranges[] = {
23 	regmap_reg_range(BD9571MWV_VENDOR_CODE, BD9571MWV_PRODUCT_REVISION),
24 	regmap_reg_range(BD9571MWV_BKUP_MODE_CNT, BD9571MWV_BKUP_MODE_CNT),
25 	regmap_reg_range(BD9571MWV_AVS_SET_MONI, BD9571MWV_AVS_DVFS_VID(3)),
26 	regmap_reg_range(BD9571MWV_VD18_VID, BD9571MWV_VD33_VID),
27 	regmap_reg_range(BD9571MWV_DVFS_VINIT, BD9571MWV_DVFS_VINIT),
28 	regmap_reg_range(BD9571MWV_DVFS_SETVMAX, BD9571MWV_DVFS_MONIVDAC),
29 	regmap_reg_range(BD9571MWV_GPIO_IN, BD9571MWV_GPIO_IN),
30 	regmap_reg_range(BD9571MWV_GPIO_INT, BD9571MWV_GPIO_INTMASK),
31 	regmap_reg_range(BD9571MWV_INT_INTREQ, BD9571MWV_INT_INTMASK),
32 };
33 
34 static const struct regmap_access_table bd9571mwv_readable_table = {
35 	.yes_ranges	= bd9571mwv_readable_yes_ranges,
36 	.n_yes_ranges	= ARRAY_SIZE(bd9571mwv_readable_yes_ranges),
37 };
38 
39 static const struct regmap_range bd9571mwv_writable_yes_ranges[] = {
40 	regmap_reg_range(BD9571MWV_BKUP_MODE_CNT, BD9571MWV_BKUP_MODE_CNT),
41 	regmap_reg_range(BD9571MWV_AVS_VD09_VID(0), BD9571MWV_AVS_VD09_VID(3)),
42 	regmap_reg_range(BD9571MWV_DVFS_SETVID, BD9571MWV_DVFS_SETVID),
43 	regmap_reg_range(BD9571MWV_GPIO_DIR, BD9571MWV_GPIO_OUT),
44 	regmap_reg_range(BD9571MWV_GPIO_INT_SET, BD9571MWV_GPIO_INTMASK),
45 	regmap_reg_range(BD9571MWV_INT_INTREQ, BD9571MWV_INT_INTMASK),
46 };
47 
48 static const struct regmap_access_table bd9571mwv_writable_table = {
49 	.yes_ranges	= bd9571mwv_writable_yes_ranges,
50 	.n_yes_ranges	= ARRAY_SIZE(bd9571mwv_writable_yes_ranges),
51 };
52 
53 static const struct regmap_range bd9571mwv_volatile_yes_ranges[] = {
54 	regmap_reg_range(BD9571MWV_DVFS_MONIVDAC, BD9571MWV_DVFS_MONIVDAC),
55 	regmap_reg_range(BD9571MWV_GPIO_IN, BD9571MWV_GPIO_IN),
56 	regmap_reg_range(BD9571MWV_GPIO_INT, BD9571MWV_GPIO_INT),
57 	regmap_reg_range(BD9571MWV_INT_INTREQ, BD9571MWV_INT_INTREQ),
58 };
59 
60 static const struct regmap_access_table bd9571mwv_volatile_table = {
61 	.yes_ranges	= bd9571mwv_volatile_yes_ranges,
62 	.n_yes_ranges	= ARRAY_SIZE(bd9571mwv_volatile_yes_ranges),
63 };
64 
65 static const struct regmap_config bd9571mwv_regmap_config = {
66 	.reg_bits	= 8,
67 	.val_bits	= 8,
68 	.cache_type	= REGCACHE_RBTREE,
69 	.rd_table	= &bd9571mwv_readable_table,
70 	.wr_table	= &bd9571mwv_writable_table,
71 	.volatile_table	= &bd9571mwv_volatile_table,
72 	.max_register	= 0xff,
73 };
74 
75 static const struct regmap_irq bd9571mwv_irqs[] = {
76 	REGMAP_IRQ_REG(BD9571MWV_IRQ_MD1, 0,
77 		       BD9571MWV_INT_INTREQ_MD1_INT),
78 	REGMAP_IRQ_REG(BD9571MWV_IRQ_MD2_E1, 0,
79 		       BD9571MWV_INT_INTREQ_MD2_E1_INT),
80 	REGMAP_IRQ_REG(BD9571MWV_IRQ_MD2_E2, 0,
81 		       BD9571MWV_INT_INTREQ_MD2_E2_INT),
82 	REGMAP_IRQ_REG(BD9571MWV_IRQ_PROT_ERR, 0,
83 		       BD9571MWV_INT_INTREQ_PROT_ERR_INT),
84 	REGMAP_IRQ_REG(BD9571MWV_IRQ_GP, 0,
85 		       BD9571MWV_INT_INTREQ_GP_INT),
86 	REGMAP_IRQ_REG(BD9571MWV_IRQ_128H_OF, 0,
87 		       BD9571MWV_INT_INTREQ_128H_OF_INT),
88 	REGMAP_IRQ_REG(BD9571MWV_IRQ_WDT_OF, 0,
89 		       BD9571MWV_INT_INTREQ_WDT_OF_INT),
90 	REGMAP_IRQ_REG(BD9571MWV_IRQ_BKUP_TRG, 0,
91 		       BD9571MWV_INT_INTREQ_BKUP_TRG_INT),
92 };
93 
94 static struct regmap_irq_chip bd9571mwv_irq_chip = {
95 	.name		= "bd9571mwv",
96 	.status_base	= BD9571MWV_INT_INTREQ,
97 	.mask_base	= BD9571MWV_INT_INTMASK,
98 	.ack_base	= BD9571MWV_INT_INTREQ,
99 	.init_ack_masked = true,
100 	.num_regs	= 1,
101 	.irqs		= bd9571mwv_irqs,
102 	.num_irqs	= ARRAY_SIZE(bd9571mwv_irqs),
103 };
104 
105 static int bd9571mwv_identify(struct bd9571mwv *bd)
106 {
107 	struct device *dev = bd->dev;
108 	unsigned int value;
109 	int ret;
110 
111 	ret = regmap_read(bd->regmap, BD9571MWV_VENDOR_CODE, &value);
112 	if (ret) {
113 		dev_err(dev, "Failed to read vendor code register (ret=%i)\n",
114 			ret);
115 		return ret;
116 	}
117 
118 	if (value != BD9571MWV_VENDOR_CODE_VAL) {
119 		dev_err(dev, "Invalid vendor code ID %02x (expected %02x)\n",
120 			value, BD9571MWV_VENDOR_CODE_VAL);
121 		return -EINVAL;
122 	}
123 
124 	ret = regmap_read(bd->regmap, BD9571MWV_PRODUCT_CODE, &value);
125 	if (ret) {
126 		dev_err(dev, "Failed to read product code register (ret=%i)\n",
127 			ret);
128 		return ret;
129 	}
130 
131 	if (value != BD9571MWV_PRODUCT_CODE_VAL) {
132 		dev_err(dev, "Invalid product code ID %02x (expected %02x)\n",
133 			value, BD9571MWV_PRODUCT_CODE_VAL);
134 		return -EINVAL;
135 	}
136 
137 	ret = regmap_read(bd->regmap, BD9571MWV_PRODUCT_REVISION, &value);
138 	if (ret) {
139 		dev_err(dev, "Failed to read revision register (ret=%i)\n",
140 			ret);
141 		return ret;
142 	}
143 
144 	dev_info(dev, "Device: BD9571MWV rev. %d\n", value & 0xff);
145 
146 	return 0;
147 }
148 
149 static int bd9571mwv_probe(struct i2c_client *client,
150 			  const struct i2c_device_id *ids)
151 {
152 	struct bd9571mwv *bd;
153 	int ret;
154 
155 	bd = devm_kzalloc(&client->dev, sizeof(*bd), GFP_KERNEL);
156 	if (!bd)
157 		return -ENOMEM;
158 
159 	i2c_set_clientdata(client, bd);
160 	bd->dev = &client->dev;
161 	bd->irq = client->irq;
162 
163 	bd->regmap = devm_regmap_init_i2c(client, &bd9571mwv_regmap_config);
164 	if (IS_ERR(bd->regmap)) {
165 		dev_err(bd->dev, "Failed to initialize register map\n");
166 		return PTR_ERR(bd->regmap);
167 	}
168 
169 	ret = bd9571mwv_identify(bd);
170 	if (ret)
171 		return ret;
172 
173 	ret = devm_regmap_add_irq_chip(bd->dev, bd->regmap, bd->irq,
174 				       IRQF_ONESHOT, 0, &bd9571mwv_irq_chip,
175 				       &bd->irq_data);
176 	if (ret) {
177 		dev_err(bd->dev, "Failed to register IRQ chip\n");
178 		return ret;
179 	}
180 
181 	return devm_mfd_add_devices(bd->dev, PLATFORM_DEVID_AUTO,
182 				    bd9571mwv_cells, ARRAY_SIZE(bd9571mwv_cells),
183 				    NULL, 0, regmap_irq_get_domain(bd->irq_data));
184 }
185 
186 static const struct of_device_id bd9571mwv_of_match_table[] = {
187 	{ .compatible = "rohm,bd9571mwv", },
188 	{ /* sentinel */ }
189 };
190 MODULE_DEVICE_TABLE(of, bd9571mwv_of_match_table);
191 
192 static const struct i2c_device_id bd9571mwv_id_table[] = {
193 	{ "bd9571mwv", 0 },
194 	{ /* sentinel */ }
195 };
196 MODULE_DEVICE_TABLE(i2c, bd9571mwv_id_table);
197 
198 static struct i2c_driver bd9571mwv_driver = {
199 	.driver		= {
200 		.name	= "bd9571mwv",
201 		.of_match_table = bd9571mwv_of_match_table,
202 	},
203 	.probe		= bd9571mwv_probe,
204 	.id_table       = bd9571mwv_id_table,
205 };
206 module_i2c_driver(bd9571mwv_driver);
207 
208 MODULE_AUTHOR("Marek Vasut <marek.vasut+renesas@gmail.com>");
209 MODULE_DESCRIPTION("BD9571MWV PMIC Driver");
210 MODULE_LICENSE("GPL v2");
211