1/*-
2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3 *
4 * Copyright (c) 2016 Jared McNeill <jmcneill@invisible.ca>
5 * Copyright (c) 2018 Emmanuel Vadot <manu@FreeBSD.org>
6 * Copyright (c) 2019 Michal Meloun <mmel@FreeBSD.org>
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 *    notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 *    notice, this list of conditions and the following disclaimer in the
15 *    documentation and/or other materials provided with the distribution.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30#include <sys/cdefs.h>
31__FBSDID("$FreeBSD$");
32
33#include <sys/param.h>
34#include <sys/bus.h>
35#include <sys/kernel.h>
36#include <sys/module.h>
37#include <sys/mutex.h>
38#include <sys/rman.h>
39#include <machine/bus.h>
40
41#include <dev/iicbus/iiconf.h>
42#include <dev/iicbus/iicbus.h>
43
44#include <dev/ofw/ofw_bus.h>
45#include <dev/ofw/ofw_bus_subr.h>
46
47#include <dev/extres/regulator/regulator.h>
48
49#include "regdev_if.h"
50
51/* Registers */
52#define	FAN53555_VSEL0		0x00
53#define	FAN53555_VSEL1		0x01
54#define	 FAN53555_VSEL_ENA		(1 << 7)
55#define	 FAN53555_VSEL_MODE		(1 << 6)
56#define	 FAN53555_VSEL_MASK		0x3f
57#define	FAN53555_CTRL		0x02
58#define	FAN53555_ID1		0x03
59#define	 FAN53555_ID1_DIE_ID(x)		(((x) >> 4) & 0x0F)
60#define	FAN53555_ID2		0x04
61#define	 FAN53555_ID2_DIE_REV(x)	(((x) >> 4) & 0x0F)
62#define	FAN53555_MON		0x05
63
64
65#if 0
66#define	dprintf(sc, format, arg...)					\
67	device_printf(sc->base_dev, "%s: " format, __func__, arg)
68#else
69#define	dprintf(sc, format, arg...)
70#endif
71
72enum fan53555_pmic_type {
73	FAN53555 = 1,
74	SYR827,
75	SYR828,
76};
77
78static struct ofw_compat_data compat_data[] = {
79	{"fcs,fan53555", 	FAN53555},
80	{"silergy,syr827",	SYR827},
81	{"silergy,syr828",	SYR828},
82	{NULL,		0}
83};
84
85struct fan53555_reg_sc {
86	struct regnode		*regnode;
87	char			*name;
88	device_t		base_dev;
89	uint8_t			live_reg;
90	uint8_t			sleep_reg;
91	struct regulator_range	*range;
92	struct regnode_std_param *param;
93};
94
95struct fan53555_softc {
96	device_t		dev;
97	uint8_t			live_reg;
98	uint8_t			sleep_reg;
99};
100
101static struct regulator_range syr_8_range =
102   REG_RANGE_INIT(  0, 0x3F,  712500, 12500);
103
104static struct regulator_range fan_0_0_range =
105   REG_RANGE_INIT(  0, 0x3F,  600000, 10000);
106static struct regulator_range fan_0_13_range =
107   REG_RANGE_INIT(  0, 0x3F,  800000, 10000);
108static struct regulator_range fan_1_range =
109   REG_RANGE_INIT(  0, 0x3F,  600000, 10000);
110static struct regulator_range fan_4_range =
111   REG_RANGE_INIT(  0, 0x3F,  603000, 12826);
112
113
114static int
115fan53555_read(device_t dev, uint8_t reg, uint8_t *val)
116{
117	uint8_t addr;
118	int rv;
119	struct iic_msg msgs[2] = {
120		{0, IIC_M_WR | IIC_M_NOSTOP, 1, &addr},
121		{0, IIC_M_RD, 1, val},
122	};
123
124	msgs[0].slave = iicbus_get_addr(dev);
125	msgs[1].slave = iicbus_get_addr(dev);
126	addr = reg;
127
128	rv = iicbus_transfer_excl(dev, msgs, 2, IIC_INTRWAIT);
129	if (rv != 0) {
130		device_printf(dev, "Error when reading reg 0x%02X, rv: %d\n",
131		    reg,  rv);
132		return (EIO);
133	}
134
135	return (0);
136}
137
138static int
139fan53555_write(device_t dev, uint8_t reg, uint8_t val)
140{
141	uint8_t data[2];
142	int rv;
143
144	struct iic_msg msgs[1] = {
145		{0, IIC_M_WR, 2, data},
146	};
147
148	msgs[0].slave = iicbus_get_addr(dev);
149	data[0] = reg;
150	data[1] = val;
151
152	rv = iicbus_transfer_excl(dev, msgs, 1, IIC_INTRWAIT);
153	if (rv != 0) {
154		device_printf(dev,
155		    "Error when writing reg 0x%02X, rv: %d\n", reg, rv);
156		return (EIO);
157	}
158	return (0);
159}
160
161static int
162fan53555_read_sel(struct fan53555_reg_sc *sc, uint8_t *sel)
163{
164	int rv;
165
166	rv = fan53555_read(sc->base_dev, sc->live_reg, sel);
167	if (rv != 0)
168		return (rv);
169	*sel &= FAN53555_VSEL_MASK;
170	return (0);
171}
172
173static int
174fan53555_write_sel(struct fan53555_reg_sc *sc, uint8_t sel)
175{
176	int rv;
177	uint8_t reg;
178
179	rv = fan53555_read(sc->base_dev, sc->live_reg, &reg);
180	if (rv != 0)
181		return (rv);
182	reg &= ~FAN53555_VSEL_MASK;
183	reg |= sel;
184
185	rv = fan53555_write(sc->base_dev, sc->live_reg, reg);
186	if (rv != 0)
187		return (rv);
188	return (rv);
189}
190
191static int
192fan53555_regnode_init(struct regnode *regnode)
193{
194	return (0);
195}
196
197static int
198fan53555_regnode_enable(struct regnode *regnode, bool enable, int *udelay)
199{
200	struct fan53555_reg_sc *sc;
201	uint8_t val;
202
203	sc = regnode_get_softc(regnode);
204
205	dprintf(sc, "%sabling regulator %s\n", enable ? "En" : "Dis",
206	    sc->name);
207	fan53555_read(sc->base_dev, sc->live_reg, &val);
208	if (enable)
209		val |=FAN53555_VSEL_ENA;
210	else
211		val &= ~FAN53555_VSEL_ENA;
212	fan53555_write(sc->base_dev, sc->live_reg, val);
213
214	*udelay = sc->param->enable_delay;
215	return (0);
216}
217
218
219static int
220fan53555_regnode_set_voltage(struct regnode *regnode, int min_uvolt,
221    int max_uvolt, int *udelay)
222{
223	struct fan53555_reg_sc *sc;
224	uint8_t sel;
225	int uvolt, rv;
226
227	sc = regnode_get_softc(regnode);
228
229	dprintf(sc, "Setting %s to %d<->%d uvolts\n", sc->name, min_uvolt,
230	    max_uvolt);
231	rv = regulator_range_volt_to_sel8(sc->range, 1, min_uvolt, max_uvolt,
232	    &sel);
233	if (rv != 0)
234		return (rv);
235	*udelay = sc->param->ramp_delay;
236	rv = fan53555_write_sel(sc, sel);
237	dprintf(sc, "Regulator %s writing sel: 0x%02X\n", sc->name, sel);
238
239	fan53555_read_sel(sc, &sel);
240	regulator_range_sel8_to_volt(sc->range, 1, sel, &uvolt);
241	dprintf(sc, "Regulator %s set to %d uvolt (sel: 0x%02X)\n", sc->name,
242	    uvolt, sel);
243
244	return (rv);
245}
246
247static int
248fan53555_regnode_get_voltage(struct regnode *regnode, int *uvolt)
249{
250	struct fan53555_reg_sc *sc;
251	uint8_t sel;
252	int rv;
253
254	sc = regnode_get_softc(regnode);
255
256	rv = fan53555_read_sel(sc, &sel);
257	if (rv != 0)
258		return (rv);
259	rv = regulator_range_sel8_to_volt(sc->range, 1, sel, uvolt);
260	dprintf(sc, "Regulator %s is at %d uvolt ((sel: 0x%02X)\n", sc->name,
261	    *uvolt, sel);
262
263	return (rv);
264}
265
266static regnode_method_t fan53555_regnode_methods[] = {
267	/* Regulator interface */
268	REGNODEMETHOD(regnode_init,		fan53555_regnode_init),
269	REGNODEMETHOD(regnode_enable,		fan53555_regnode_enable),
270	REGNODEMETHOD(regnode_set_voltage,	fan53555_regnode_set_voltage),
271	REGNODEMETHOD(regnode_get_voltage,	fan53555_regnode_get_voltage),
272	REGNODEMETHOD_END
273};
274DEFINE_CLASS_1(fan53555_regnode, fan53555_regnode_class,
275    fan53555_regnode_methods, sizeof(struct fan53555_reg_sc), regnode_class);
276
277static struct regulator_range *
278fan53555_get_range(struct fan53555_softc *sc, int type, uint8_t id,
279    uint8_t rev)
280{
281	if (type == SYR827 || type == SYR828) {
282		switch (id) {
283		case 8:
284			return (&syr_8_range);
285		default:
286			return (NULL);
287		}
288	}
289
290	if (type == FAN53555) {
291		switch (id) {
292		case 0:
293			if (rev == 0)
294				return (&fan_0_0_range);
295			else if (rev == 13)
296				return (&fan_0_13_range);
297			else
298				return (NULL);
299		case 1:
300		case 3:
301		case 5:
302		case 8:
303			return (&fan_1_range);
304		case 4:
305			return (&fan_4_range);
306		default:
307			return (NULL);
308		}
309	}
310
311	return (NULL);
312}
313
314static struct fan53555_reg_sc *
315fan53555_reg_attach(struct fan53555_softc *sc, phandle_t node, int  type)
316{
317	struct fan53555_reg_sc *reg_sc;
318	struct regnode_init_def initdef;
319	struct regnode *regnode;
320	static struct regulator_range *range;
321	uint8_t id1, id2;
322
323	memset(&initdef, 0, sizeof(initdef));
324	if (regulator_parse_ofw_stdparam(sc->dev, node, &initdef) != 0) {
325		device_printf(sc->dev, "cannot parse regulator FDT data\n");
326		return (NULL);
327	}
328
329	if (fan53555_read(sc->dev, FAN53555_ID1, &id1) != 0) {
330		device_printf(sc->dev, "cannot read ID1\n");
331		return (NULL);
332	}
333
334	if (fan53555_read(sc->dev, FAN53555_ID2, &id2) != 0) {
335		device_printf(sc->dev, "cannot read ID2\n");
336		return (NULL);
337	}
338	dprintf(sc, "Device ID1: 0x%02X, ID2: 0x%02X\n", id1, id2);
339
340	range = fan53555_get_range(sc, type, FAN53555_ID1_DIE_ID(id1),
341	     FAN53555_ID2_DIE_REV(id2));
342	if (range == NULL) {
343		device_printf(sc->dev,
344		    "cannot determine chip type (ID1: 0x%02X, ID2: 0x%02X)\n",
345		    id1, id2);
346		return (NULL);
347	}
348
349	initdef.id = 1;
350	initdef.ofw_node = node;
351
352	regnode = regnode_create(sc->dev, &fan53555_regnode_class, &initdef);
353	if (regnode == NULL) {
354		device_printf(sc->dev, "cannot create regulator\n");
355		return (NULL);
356	}
357
358	reg_sc = regnode_get_softc(regnode);
359	reg_sc->name = "fan53555";
360	reg_sc->regnode = regnode;
361	reg_sc->base_dev = sc->dev;
362	reg_sc->param = regnode_get_stdparam(regnode);
363	reg_sc->range = range;
364	reg_sc->live_reg = sc->live_reg;
365	reg_sc->sleep_reg = sc->sleep_reg;
366
367	dprintf(sc->dev, "live_reg: %d, sleep_reg: %d\n", reg_sc->live_reg,
368	    reg_sc->sleep_reg);
369
370	regnode_register(regnode);
371
372	if (bootverbose) {
373		int volt, rv;
374		regnode_topo_slock();
375		rv = regnode_get_voltage(regnode, &volt);
376		if (rv == ENODEV) {
377			device_printf(sc->dev,
378			   " Regulator %s: parent doesn't exist yet.\n",
379			   regnode_get_name(regnode));
380		} else if (rv != 0) {
381			device_printf(sc->dev,
382			   " Regulator %s: voltage: INVALID!!!\n",
383			   regnode_get_name(regnode));
384		} else {
385			device_printf(sc->dev,
386			    " Regulator %s: voltage: %d uV\n",
387			    regnode_get_name(regnode), volt);
388		}
389		regnode_topo_unlock();
390	}
391
392	return (reg_sc);
393}
394
395static int
396fan53555_probe(device_t dev)
397{
398	int type;
399
400	if (!ofw_bus_status_okay(dev))
401		return (ENXIO);
402
403	type = ofw_bus_search_compatible(dev, compat_data)->ocd_data;
404	switch (type) {
405	case FAN53555:
406		device_set_desc(dev, "FAN53555 PMIC");
407		break;
408	case SYR827:
409		device_set_desc(dev, "SYR827 PMIC");
410		break;
411	case SYR828:
412		device_set_desc(dev, "SYR828 PMIC");
413		break;
414	default:
415		return (ENXIO);
416	}
417
418	return (BUS_PROBE_DEFAULT);
419}
420
421static int
422fan53555_attach(device_t dev)
423{
424	struct fan53555_softc *sc;
425	phandle_t node;
426	int type, susp_sel, rv;
427
428	sc = device_get_softc(dev);
429	sc->dev = dev;
430	node = ofw_bus_get_node(dev);
431	type = ofw_bus_search_compatible(dev, compat_data)->ocd_data;
432
433	rv = OF_getencprop(node, "fcs,suspend-voltage-selector", &susp_sel,
434		sizeof(susp_sel));
435	if (rv <= 0)
436		susp_sel = 1;
437	if (susp_sel == 1) {
438		sc->live_reg = FAN53555_VSEL0;
439		sc->sleep_reg = FAN53555_VSEL1;
440	} else {
441		sc->live_reg = FAN53555_VSEL1;
442		sc->sleep_reg = FAN53555_VSEL0;
443	}
444	if (fan53555_reg_attach(sc, node, type) == NULL)
445		device_printf(dev, "cannot attach regulator.\n");
446
447	return (0);
448}
449
450static int
451fan53555_detach(device_t dev)
452{
453
454	/* We cannot detach regulators */
455	return (EBUSY);
456}
457
458static device_method_t fan53555_methods[] = {
459	DEVMETHOD(device_probe,		fan53555_probe),
460	DEVMETHOD(device_attach,	fan53555_attach),
461	DEVMETHOD(device_detach,	fan53555_detach),
462
463	/* Regdev interface */
464	DEVMETHOD(regdev_map,		regdev_default_ofw_map),
465
466	DEVMETHOD_END
467};
468
469static devclass_t fan53555_devclass;
470static DEFINE_CLASS_0(fan53555_pmic, fan53555_driver, fan53555_methods,
471    sizeof(struct fan53555_softc));
472
473EARLY_DRIVER_MODULE(fan53555, iicbus, fan53555_driver, fan53555_devclass, 0, 0,
474    BUS_PASS_RESOURCE);
475MODULE_VERSION(fan53555, 1);
476MODULE_DEPEND(fan53555, iicbus, IICBUS_MINVER, IICBUS_PREFVER, IICBUS_MAXVER);
477IICBUS_FDT_PNP_INFO(compat_data);
478