xref: /openbmc/linux/drivers/mfd/bd9571mwv.c (revision 2d99a7ec)
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_new	= 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