xref: /freebsd/sys/arm/ti/am335x/am335x_pmic.c (revision e53470fee3cf7ba343701650d5e75b8142046acf)
1*e53470feSOleksandr Tymoshenko /*-
2*e53470feSOleksandr Tymoshenko  * Copyright (c) 2012 Damjan Marion <dmarion@Freebsd.org>
3*e53470feSOleksandr Tymoshenko  * All rights reserved.
4*e53470feSOleksandr Tymoshenko  *
5*e53470feSOleksandr Tymoshenko  * Redistribution and use in source and binary forms, with or without
6*e53470feSOleksandr Tymoshenko  * modification, are permitted provided that the following conditions
7*e53470feSOleksandr Tymoshenko  * are met:
8*e53470feSOleksandr Tymoshenko  * 1. Redistributions of source code must retain the above copyright
9*e53470feSOleksandr Tymoshenko  *    notice, this list of conditions and the following disclaimer.
10*e53470feSOleksandr Tymoshenko  * 2. Redistributions in binary form must reproduce the above copyright
11*e53470feSOleksandr Tymoshenko  *    notice, this list of conditions and the following disclaimer in the
12*e53470feSOleksandr Tymoshenko  *    documentation and/or other materials provided with the distribution.
13*e53470feSOleksandr Tymoshenko  *
14*e53470feSOleksandr Tymoshenko  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15*e53470feSOleksandr Tymoshenko  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16*e53470feSOleksandr Tymoshenko  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17*e53470feSOleksandr Tymoshenko  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18*e53470feSOleksandr Tymoshenko  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19*e53470feSOleksandr Tymoshenko  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20*e53470feSOleksandr Tymoshenko  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21*e53470feSOleksandr Tymoshenko  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22*e53470feSOleksandr Tymoshenko  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23*e53470feSOleksandr Tymoshenko  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24*e53470feSOleksandr Tymoshenko  * SUCH DAMAGE.
25*e53470feSOleksandr Tymoshenko  */
26*e53470feSOleksandr Tymoshenko 
27*e53470feSOleksandr Tymoshenko #include <sys/cdefs.h>
28*e53470feSOleksandr Tymoshenko __FBSDID("$FreeBSD$");
29*e53470feSOleksandr Tymoshenko /*
30*e53470feSOleksandr Tymoshenko * TPS65217 PMIC companion chip for AM335x SoC sitting on I2C bus
31*e53470feSOleksandr Tymoshenko */
32*e53470feSOleksandr Tymoshenko #include <sys/param.h>
33*e53470feSOleksandr Tymoshenko #include <sys/systm.h>
34*e53470feSOleksandr Tymoshenko #include <sys/kernel.h>
35*e53470feSOleksandr Tymoshenko #include <sys/module.h>
36*e53470feSOleksandr Tymoshenko #include <sys/clock.h>
37*e53470feSOleksandr Tymoshenko #include <sys/time.h>
38*e53470feSOleksandr Tymoshenko #include <sys/bus.h>
39*e53470feSOleksandr Tymoshenko #include <sys/resource.h>
40*e53470feSOleksandr Tymoshenko #include <sys/rman.h>
41*e53470feSOleksandr Tymoshenko 
42*e53470feSOleksandr Tymoshenko #include <dev/iicbus/iicbus.h>
43*e53470feSOleksandr Tymoshenko #include <dev/iicbus/iiconf.h>
44*e53470feSOleksandr Tymoshenko 
45*e53470feSOleksandr Tymoshenko #include <dev/ofw/openfirm.h>
46*e53470feSOleksandr Tymoshenko #include <dev/ofw/ofw_bus.h>
47*e53470feSOleksandr Tymoshenko #include <dev/ofw/ofw_bus_subr.h>
48*e53470feSOleksandr Tymoshenko 
49*e53470feSOleksandr Tymoshenko #include "iicbus_if.h"
50*e53470feSOleksandr Tymoshenko 
51*e53470feSOleksandr Tymoshenko #define TPS65217A		0x7
52*e53470feSOleksandr Tymoshenko #define TPS65217B		0xF
53*e53470feSOleksandr Tymoshenko 
54*e53470feSOleksandr Tymoshenko /* TPS65217 Reisters */
55*e53470feSOleksandr Tymoshenko #define TPS65217_CHIPID_REG	0x00
56*e53470feSOleksandr Tymoshenko #define TPS65217_STATUS_REG	0x0A
57*e53470feSOleksandr Tymoshenko 
58*e53470feSOleksandr Tymoshenko #define MAX_IIC_DATA_SIZE	2
59*e53470feSOleksandr Tymoshenko 
60*e53470feSOleksandr Tymoshenko 
61*e53470feSOleksandr Tymoshenko struct am335x_pmic_softc {
62*e53470feSOleksandr Tymoshenko 	device_t		sc_dev;
63*e53470feSOleksandr Tymoshenko 	uint32_t		sc_addr;
64*e53470feSOleksandr Tymoshenko 	struct intr_config_hook enum_hook;
65*e53470feSOleksandr Tymoshenko };
66*e53470feSOleksandr Tymoshenko 
67*e53470feSOleksandr Tymoshenko static int
68*e53470feSOleksandr Tymoshenko am335x_pmic_read(device_t dev, uint8_t addr, uint8_t *data, uint8_t size)
69*e53470feSOleksandr Tymoshenko {
70*e53470feSOleksandr Tymoshenko 	struct am335x_pmic_softc *sc = device_get_softc(dev);
71*e53470feSOleksandr Tymoshenko 	struct iic_msg msg[] = {
72*e53470feSOleksandr Tymoshenko 		{ sc->sc_addr, IIC_M_WR, 1, &addr },
73*e53470feSOleksandr Tymoshenko 		{ sc->sc_addr, IIC_M_RD, size, data },
74*e53470feSOleksandr Tymoshenko 	};
75*e53470feSOleksandr Tymoshenko 	return (iicbus_transfer(dev, msg, 2));
76*e53470feSOleksandr Tymoshenko }
77*e53470feSOleksandr Tymoshenko 
78*e53470feSOleksandr Tymoshenko #ifdef notyet
79*e53470feSOleksandr Tymoshenko static int
80*e53470feSOleksandr Tymoshenko am335x_pmic_write(device_t dev, uint8_t address, uint8_t *data, uint8_t size)
81*e53470feSOleksandr Tymoshenko {
82*e53470feSOleksandr Tymoshenko 	uint8_t buffer[MAX_IIC_DATA_SIZE + 1];
83*e53470feSOleksandr Tymoshenko 	struct am335x_pmic_softc *sc = device_get_softc(dev);
84*e53470feSOleksandr Tymoshenko 	struct iic_msg msg[] = {
85*e53470feSOleksandr Tymoshenko 		{ sc->sc_addr, IIC_M_WR, size + 1, buffer },
86*e53470feSOleksandr Tymoshenko 	};
87*e53470feSOleksandr Tymoshenko 
88*e53470feSOleksandr Tymoshenko 	if (size > MAX_IIC_DATA_SIZE)
89*e53470feSOleksandr Tymoshenko 		return (ENOMEM);
90*e53470feSOleksandr Tymoshenko 
91*e53470feSOleksandr Tymoshenko 	buffer[0] = address;
92*e53470feSOleksandr Tymoshenko 	memcpy(buffer + 1, data, size);
93*e53470feSOleksandr Tymoshenko 
94*e53470feSOleksandr Tymoshenko 	return (iicbus_transfer(dev, msg, 1));
95*e53470feSOleksandr Tymoshenko }
96*e53470feSOleksandr Tymoshenko #endif
97*e53470feSOleksandr Tymoshenko 
98*e53470feSOleksandr Tymoshenko static int
99*e53470feSOleksandr Tymoshenko am335x_pmic_probe(device_t dev)
100*e53470feSOleksandr Tymoshenko {
101*e53470feSOleksandr Tymoshenko 	struct am335x_pmic_softc *sc;
102*e53470feSOleksandr Tymoshenko 
103*e53470feSOleksandr Tymoshenko 	if (!ofw_bus_is_compatible(dev, "ti,am335x-pmic"))
104*e53470feSOleksandr Tymoshenko 		return (ENXIO);
105*e53470feSOleksandr Tymoshenko 
106*e53470feSOleksandr Tymoshenko 	sc = device_get_softc(dev);
107*e53470feSOleksandr Tymoshenko 	sc->sc_dev = dev;
108*e53470feSOleksandr Tymoshenko 	sc->sc_addr = iicbus_get_addr(dev);
109*e53470feSOleksandr Tymoshenko 
110*e53470feSOleksandr Tymoshenko 	device_set_desc(dev, "TI TPS65217 Power Management IC");
111*e53470feSOleksandr Tymoshenko 
112*e53470feSOleksandr Tymoshenko 	return (0);
113*e53470feSOleksandr Tymoshenko }
114*e53470feSOleksandr Tymoshenko 
115*e53470feSOleksandr Tymoshenko static void
116*e53470feSOleksandr Tymoshenko am335x_pmic_start(void *xdev)
117*e53470feSOleksandr Tymoshenko {
118*e53470feSOleksandr Tymoshenko 	struct am335x_pmic_softc *sc;
119*e53470feSOleksandr Tymoshenko 	device_t dev = (device_t)xdev;
120*e53470feSOleksandr Tymoshenko 	uint8_t reg;
121*e53470feSOleksandr Tymoshenko 	char name[20];
122*e53470feSOleksandr Tymoshenko 	char pwr[4][11] = {"Unknown", "USB", "AC", "USB and AC"};
123*e53470feSOleksandr Tymoshenko 
124*e53470feSOleksandr Tymoshenko 	sc = device_get_softc(dev);
125*e53470feSOleksandr Tymoshenko 
126*e53470feSOleksandr Tymoshenko 	am335x_pmic_read(dev, TPS65217_CHIPID_REG, &reg, 1);
127*e53470feSOleksandr Tymoshenko 	switch (reg>>4) {
128*e53470feSOleksandr Tymoshenko 		case TPS65217A:
129*e53470feSOleksandr Tymoshenko 			sprintf(name, "TPS65217A ver 1.%u", reg & 0xF);
130*e53470feSOleksandr Tymoshenko 			break;
131*e53470feSOleksandr Tymoshenko 		case TPS65217B:
132*e53470feSOleksandr Tymoshenko 			sprintf(name, "TPS65217B ver 1.%u", reg & 0xF);
133*e53470feSOleksandr Tymoshenko 			break;
134*e53470feSOleksandr Tymoshenko 		default:
135*e53470feSOleksandr Tymoshenko 			sprintf(name, "Unknown PMIC");
136*e53470feSOleksandr Tymoshenko 	}
137*e53470feSOleksandr Tymoshenko 
138*e53470feSOleksandr Tymoshenko 	am335x_pmic_read(dev, TPS65217_STATUS_REG, &reg, 1);
139*e53470feSOleksandr Tymoshenko 	device_printf(dev, "%s powered by %s\n", name, pwr[(reg>>2)&0x03]);
140*e53470feSOleksandr Tymoshenko 
141*e53470feSOleksandr Tymoshenko 	config_intrhook_disestablish(&sc->enum_hook);
142*e53470feSOleksandr Tymoshenko }
143*e53470feSOleksandr Tymoshenko 
144*e53470feSOleksandr Tymoshenko static int
145*e53470feSOleksandr Tymoshenko am335x_pmic_attach(device_t dev)
146*e53470feSOleksandr Tymoshenko {
147*e53470feSOleksandr Tymoshenko 	struct am335x_pmic_softc *sc;
148*e53470feSOleksandr Tymoshenko 
149*e53470feSOleksandr Tymoshenko 	sc = device_get_softc(dev);
150*e53470feSOleksandr Tymoshenko 
151*e53470feSOleksandr Tymoshenko 	sc->enum_hook.ich_func = am335x_pmic_start;
152*e53470feSOleksandr Tymoshenko 	sc->enum_hook.ich_arg = dev;
153*e53470feSOleksandr Tymoshenko 
154*e53470feSOleksandr Tymoshenko 	if (config_intrhook_establish(&sc->enum_hook) != 0)
155*e53470feSOleksandr Tymoshenko 		return (ENOMEM);
156*e53470feSOleksandr Tymoshenko 
157*e53470feSOleksandr Tymoshenko 	return (0);
158*e53470feSOleksandr Tymoshenko }
159*e53470feSOleksandr Tymoshenko 
160*e53470feSOleksandr Tymoshenko static device_method_t am335x_pmic_methods[] = {
161*e53470feSOleksandr Tymoshenko 	DEVMETHOD(device_probe,		am335x_pmic_probe),
162*e53470feSOleksandr Tymoshenko 	DEVMETHOD(device_attach,	am335x_pmic_attach),
163*e53470feSOleksandr Tymoshenko 	{0, 0},
164*e53470feSOleksandr Tymoshenko };
165*e53470feSOleksandr Tymoshenko 
166*e53470feSOleksandr Tymoshenko static driver_t am335x_pmic_driver = {
167*e53470feSOleksandr Tymoshenko 	"am335x_pmic",
168*e53470feSOleksandr Tymoshenko 	am335x_pmic_methods,
169*e53470feSOleksandr Tymoshenko 	sizeof(struct am335x_pmic_softc),
170*e53470feSOleksandr Tymoshenko };
171*e53470feSOleksandr Tymoshenko 
172*e53470feSOleksandr Tymoshenko static devclass_t am335x_pmic_devclass;
173*e53470feSOleksandr Tymoshenko 
174*e53470feSOleksandr Tymoshenko DRIVER_MODULE(am335x_pmic, iicbus, am335x_pmic_driver, am335x_pmic_devclass, 0, 0);
175*e53470feSOleksandr Tymoshenko MODULE_VERSION(am335x_pmic, 1);
176*e53470feSOleksandr Tymoshenko MODULE_DEPEND(am335x_pmic, iicbus, 1, 1, 1);
177