1/*-
2 * SPDX-License-Identifier: BSD-2-Clause
3 *
4 * Copyright (c) 2019 Michal Meloun <mmel@FreeBSD.org>
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 *    notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 *    notice, this list of conditions and the following disclaimer in the
13 *    documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 */
27
28#include <sys/cdefs.h>
29/*
30 * Thermometer and thermal zones driver for RockChip SoCs.
31 * Calibration data are taken from Linux, because this part of SoC
32 * is undocumented in TRM.
33 */
34
35#include <sys/param.h>
36#include <sys/systm.h>
37#include <sys/bus.h>
38#include <sys/gpio.h>
39#include <sys/kernel.h>
40#include <sys/module.h>
41#include <sys/malloc.h>
42#include <sys/rman.h>
43#include <sys/sysctl.h>
44
45#include <machine/bus.h>
46
47#include <dev/clk/clk.h>
48#include <dev/hwreset/hwreset.h>
49#include <dev/syscon/syscon.h>
50#include <dev/ofw/ofw_bus.h>
51#include <dev/ofw/ofw_bus_subr.h>
52
53#include "syscon_if.h"
54#include "rk_tsadc_if.h"
55
56/* Version of HW */
57#define	TSADC_V2				1
58#define	TSADC_V3				2
59#define	TSADC_V7				3
60
61/* Global registers */
62#define	TSADC_USER_CON				0x000
63#define	TSADC_AUTO_CON				0x004
64#define	 TSADC_AUTO_CON_POL_HI				(1 << 8)
65#define	 TSADC_AUTO_SRC_EN(x)				(1 << (4 + (x)))
66#define	 TSADC_AUTO_Q_SEL				(1 << 1) /* V3 only */
67#define	 TSADC_AUTO_CON_AUTO				(1 << 0)
68
69#define	TSADC_INT_EN				0x008
70#define	 TSADC_INT_EN_2CRU_EN_SRC(x)			(1 << (8 + (x)))
71#define	 TSADC_INT_EN_2GPIO_EN_SRC(x)			(1 << (4 + (x)))
72#define	TSADC_INT_PD				0x00c
73#define	TSADC_DATA(x)				(0x20 + (x) * 0x04)
74#define	TSADC_COMP_INT(x)			(0x30 + (x) * 0x04)
75#define	 TSADC_COMP_INT_SRC_EN(x)			(1 << (0 + (x)))
76#define	TSADC_COMP_SHUT(x)			(0x40 + (x) * 0x04)
77#define	TSADC_HIGHT_INT_DEBOUNCE		0x060
78#define	TSADC_HIGHT_TSHUT_DEBOUNCE		0x064
79#define	TSADC_AUTO_PERIOD			0x068
80#define	TSADC_AUTO_PERIOD_HT			0x06c
81#define	TSADC_COMP0_LOW_INT			0x080	/* V3 only */
82#define	TSADC_COMP1_LOW_INT			0x084	/* V3 only */
83
84/* V3 GFR registers */
85#define	GRF_SARADC_TESTBIT			0x0e644
86#define	 GRF_SARADC_TESTBIT_ON				(0x10001 << 2)
87#define GRF_TSADC_TESTBIT_L			0x0e648
88#define	 GRF_TSADC_VCM_EN_L				(0x10001 << 7)
89#define	GRF_TSADC_TESTBIT_H			0x0e64c
90#define	 GRF_TSADC_VCM_EN_H				(0x10001 << 7)
91#define	 GRF_TSADC_TESTBIT_H_ON				(0x10001 << 2)
92
93/* V7 GRF register */
94#define	GRF_TSADC_CON				0x0600
95#define	 GRF_TSADC_ANA_REG0			(0x10001 << 0)
96#define	 GRF_TSADC_ANA_REG1			(0x10001 << 1)
97#define	 GRF_TSADC_ANA_REG2			(0x10001 << 2)
98#define	 GRF_TSADC_TSEN				(0x10001 << 8)
99
100#define	WR4(_sc, _r, _v)	bus_write_4((_sc)->mem_res, (_r), (_v))
101#define	RD4(_sc, _r)		bus_read_4((_sc)->mem_res, (_r))
102
103static struct sysctl_ctx_list tsadc_sysctl_ctx;
104
105struct tsensor {
106	char 			*name;
107	int			id;
108	int			channel;
109};
110
111struct rk_calib_entry {
112	uint32_t	raw;
113	int		temp;
114};
115
116struct tsadc_calib_info {
117	struct rk_calib_entry	*table;
118	int			nentries;
119};
120
121struct tsadc_conf {
122	int			version;
123	int			q_sel_ntc;
124	int			shutdown_temp;
125	int			shutdown_mode;
126	int			shutdown_pol;
127	struct tsensor		*tsensors;
128	int			ntsensors;
129	struct tsadc_calib_info	calib_info;
130};
131
132struct tsadc_softc {
133	device_t		dev;
134	struct resource		*mem_res;
135	struct resource		*irq_res;
136	void			*irq_ih;
137
138	clk_t			tsadc_clk;
139	clk_t			apb_pclk_clk;
140	hwreset_array_t		hwreset;
141	struct syscon		*grf;
142
143	struct tsadc_conf	*conf;
144
145	int			shutdown_temp;
146	int			shutdown_mode;
147	int			shutdown_pol;
148
149	int			alarm_temp;
150};
151
152static struct rk_calib_entry rk3288_calib_data[] = {
153	{3800, -40000},
154	{3792, -35000},
155	{3783, -30000},
156	{3774, -25000},
157	{3765, -20000},
158	{3756, -15000},
159	{3747, -10000},
160	{3737, -5000},
161	{3728, 0},
162	{3718, 5000},
163	{3708, 10000},
164	{3698, 15000},
165	{3688, 20000},
166	{3678, 25000},
167	{3667, 30000},
168	{3656, 35000},
169	{3645, 40000},
170	{3634, 45000},
171	{3623, 50000},
172	{3611, 55000},
173	{3600, 60000},
174	{3588, 65000},
175	{3575, 70000},
176	{3563, 75000},
177	{3550, 80000},
178	{3537, 85000},
179	{3524, 90000},
180	{3510, 95000},
181	{3496, 100000},
182	{3482, 105000},
183	{3467, 110000},
184	{3452, 115000},
185	{3437, 120000},
186	{3421, 125000},
187};
188
189struct tsensor rk3288_tsensors[] = {
190	{ .channel = 0, .id = 2, .name = "reserved"},
191	{ .channel = 1, .id = 0, .name = "CPU"},
192	{ .channel = 2, .id = 1, .name = "GPU"},
193};
194
195struct tsadc_conf rk3288_tsadc_conf = {
196	.version =		TSADC_V2,
197	.q_sel_ntc =		0,
198	.shutdown_temp =	95000,
199	.shutdown_mode =	1, /* GPIO */
200	.shutdown_pol =		0, /* Low  */
201	.tsensors = 		rk3288_tsensors,
202	.ntsensors = 		nitems(rk3288_tsensors),
203	.calib_info = 	{
204			.table = rk3288_calib_data,
205			.nentries = nitems(rk3288_calib_data),
206	}
207};
208
209static struct rk_calib_entry rk3328_calib_data[] = {
210	{296, -40000},
211	{304, -35000},
212	{313, -30000},
213	{331, -20000},
214	{340, -15000},
215	{349, -10000},
216	{359, -5000},
217	{368, 0},
218	{378, 5000},
219	{388, 10000},
220	{398, 15000},
221	{408, 20000},
222	{418, 25000},
223	{429, 30000},
224	{440, 35000},
225	{451, 40000},
226	{462, 45000},
227	{473, 50000},
228	{485, 55000},
229	{496, 60000},
230	{508, 65000},
231	{521, 70000},
232	{533, 75000},
233	{546, 80000},
234	{559, 85000},
235	{572, 90000},
236	{586, 95000},
237	{600, 100000},
238	{614, 105000},
239	{629, 110000},
240	{644, 115000},
241	{659, 120000},
242	{675, 125000},
243};
244
245static struct tsensor rk3328_tsensors[] = {
246	{ .channel = 0, .id = 0, .name = "CPU"},
247};
248
249static struct tsadc_conf rk3328_tsadc_conf = {
250	.version =		TSADC_V2,
251	.q_sel_ntc =		1,
252	.shutdown_temp =	95000,
253	.shutdown_mode =	0, /* CRU */
254	.shutdown_pol =		0, /* Low  */
255	.tsensors = 		rk3328_tsensors,
256	.ntsensors = 		nitems(rk3328_tsensors),
257	.calib_info = 	{
258			.table = rk3328_calib_data,
259			.nentries = nitems(rk3328_calib_data),
260	}
261};
262
263static struct rk_calib_entry rk3399_calib_data[] = {
264	{402, -40000},
265	{410, -35000},
266	{419, -30000},
267	{427, -25000},
268	{436, -20000},
269	{444, -15000},
270	{453, -10000},
271	{461, -5000},
272	{470, 0},
273	{478, 5000},
274	{487, 10000},
275	{496, 15000},
276	{504, 20000},
277	{513, 25000},
278	{521, 30000},
279	{530, 35000},
280	{538, 40000},
281	{547, 45000},
282	{555, 50000},
283	{564, 55000},
284	{573, 60000},
285	{581, 65000},
286	{590, 70000},
287	{599, 75000},
288	{607, 80000},
289	{616, 85000},
290	{624, 90000},
291	{633, 95000},
292	{642, 100000},
293	{650, 105000},
294	{659, 110000},
295	{668, 115000},
296	{677, 120000},
297	{685, 125000},
298};
299
300static struct tsensor rk3399_tsensors[] = {
301	{ .channel = 0, .id = 0, .name = "CPU"},
302	{ .channel = 1, .id = 1, .name = "GPU"},
303};
304
305static struct tsadc_conf rk3399_tsadc_conf = {
306	.version =		TSADC_V3,
307	.q_sel_ntc =		1,
308	.shutdown_temp =	95000,
309	.shutdown_mode =	1, /* GPIO */
310	.shutdown_pol =		0, /* Low  */
311	.tsensors = 		rk3399_tsensors,
312	.ntsensors = 		nitems(rk3399_tsensors),
313	.calib_info = 	{
314			.table = rk3399_calib_data,
315			.nentries = nitems(rk3399_calib_data),
316	}
317};
318
319static struct rk_calib_entry rk3568_calib_data[] = {
320	{0, -40000},
321	{1584, -40000},
322	{1620, -35000},
323	{1652, -30000},
324	{1688, -25000},
325	{1720, -20000},
326	{1756, -15000},
327	{1788, -10000},
328	{1824, -5000},
329	{1856, 0},
330	{1892, 5000},
331	{1924, 10000},
332	{1956, 15000},
333	{1992, 20000},
334	{2024, 25000},
335	{2060, 30000},
336	{2092, 35000},
337	{2128, 40000},
338	{2160, 45000},
339	{2196, 50000},
340	{2228, 55000},
341	{2264, 60000},
342	{2300, 65000},
343	{2332, 70000},
344	{2368, 75000},
345	{2400, 80000},
346	{2436, 85000},
347	{2468, 90000},
348	{2500, 95000},
349	{2536, 100000},
350	{2572, 105000},
351	{2604, 110000},
352	{2636, 115000},
353	{2672, 120000},
354	{2704, 125000},
355};
356
357static struct tsensor rk3568_tsensors[] = {
358	{ .channel = 0, .id = 0, .name = "CPU"},
359	{ .channel = 1, .id = 1, .name = "GPU"},
360};
361
362static struct tsadc_conf rk3568_tsadc_conf = {
363	.version =		TSADC_V7,
364	.q_sel_ntc =		1,
365	.shutdown_temp =        95000,
366	.shutdown_mode =	1, /* GPIO */
367	.shutdown_pol =		0, /* Low  */
368	.tsensors =		rk3568_tsensors,
369	.ntsensors =		nitems(rk3568_tsensors),
370	.calib_info =	{
371			.table = rk3568_calib_data,
372			.nentries = nitems(rk3568_calib_data),
373	}
374};
375
376static struct ofw_compat_data compat_data[] = {
377	{"rockchip,rk3288-tsadc",	(uintptr_t)&rk3288_tsadc_conf},
378	{"rockchip,rk3328-tsadc",	(uintptr_t)&rk3328_tsadc_conf},
379	{"rockchip,rk3399-tsadc",	(uintptr_t)&rk3399_tsadc_conf},
380	{"rockchip,rk3568-tsadc",	(uintptr_t)&rk3568_tsadc_conf},
381	{NULL,		0}
382};
383
384static uint32_t
385tsadc_temp_to_raw(struct tsadc_softc *sc, int temp)
386{
387	struct rk_calib_entry *tbl;
388	int denom, ntbl, raw, i;
389
390	tbl = sc->conf->calib_info.table;
391	ntbl = sc->conf->calib_info.nentries;
392
393	if (temp <= tbl[0].temp)
394		return (tbl[0].raw);
395
396	if (temp >= tbl[ntbl - 1].temp)
397		return (tbl[ntbl - 1].raw);
398
399	for (i = 1; i < (ntbl - 1); i++) {
400		/* Exact match */
401		if (temp == tbl[i].temp)
402			return (tbl[i].raw);
403		if (temp < tbl[i].temp)
404			break;
405	}
406
407	/*
408	* Translated value is between i and i - 1 table entries.
409	* Do linear interpolation for it.
410	*/
411	raw = (int)tbl[i - 1].raw - (int)tbl[i].raw;
412	raw *= temp - tbl[i - 1].temp;
413	denom = tbl[i - 1].temp - tbl[i].temp;
414	raw = tbl[i - 1].raw + raw / denom;
415	return (raw);
416}
417
418static int
419tsadc_raw_to_temp(struct tsadc_softc *sc, uint32_t raw)
420{
421	struct rk_calib_entry *tbl;
422	int denom, ntbl, temp, i;
423	bool descending;
424
425	tbl = sc->conf->calib_info.table;
426	ntbl = sc->conf->calib_info.nentries;
427	descending = tbl[0].raw > tbl[1].raw;
428
429	if (descending) {
430		/* Raw column is in descending order. */
431		if (raw >= tbl[0].raw)
432			return (tbl[0].temp);
433		if (raw <= tbl[ntbl - 1].raw)
434			return (tbl[ntbl - 1].temp);
435
436		for (i = ntbl - 2; i > 0; i--) {
437			/* Exact match */
438			if (raw == tbl[i].raw)
439				return (tbl[i].temp);
440			if (raw < tbl[i].raw)
441				break;
442		}
443	} else {
444		/* Raw column is in ascending order. */
445		if (raw <= tbl[0].raw)
446			return (tbl[0].temp);
447		if (raw >= tbl[ntbl - 1].raw)
448			return (tbl[ntbl - 1].temp);
449		for (i = 1; i < (ntbl - 1); i++) {
450			/* Exact match */
451			if (raw == tbl[i].raw)
452				return (tbl[i].temp);
453			if (raw < tbl[i].raw)
454				break;
455		}
456	}
457
458	/*
459	* Translated value is between i and i - 1 table entries.
460	* Do linear interpolation for it.
461	*/
462	temp  = (int)tbl[i - 1].temp - (int)tbl[i].temp;
463	temp *= raw - tbl[i - 1].raw;
464	denom = tbl[i - 1].raw - tbl[i].raw;
465	temp = tbl[i - 1].temp + temp / denom;
466	return (temp);
467}
468
469static void
470tsadc_init_tsensor(struct tsadc_softc *sc, struct tsensor *sensor)
471{
472	uint32_t val;
473
474	/* Shutdown mode */
475	val = RD4(sc, TSADC_INT_EN);
476	if (sc->shutdown_mode != 0) {
477		/* Signal shutdown of GPIO pin */
478		val &= ~TSADC_INT_EN_2CRU_EN_SRC(sensor->channel);
479		val |= TSADC_INT_EN_2GPIO_EN_SRC(sensor->channel);
480	} else {
481		val |= TSADC_INT_EN_2CRU_EN_SRC(sensor->channel);
482		val &= ~TSADC_INT_EN_2GPIO_EN_SRC(sensor->channel);
483	}
484	WR4(sc, TSADC_INT_EN, val);
485
486	/* Shutdown temperature */
487	val =  tsadc_raw_to_temp(sc, sc->shutdown_temp);
488	WR4(sc, TSADC_COMP_SHUT(sensor->channel), val);
489	val = RD4(sc, TSADC_AUTO_CON);
490	val |= TSADC_AUTO_SRC_EN(sensor->channel);
491	WR4(sc, TSADC_AUTO_CON, val);
492
493	/* Alarm temperature */
494	val =  tsadc_temp_to_raw(sc, sc->alarm_temp);
495	WR4(sc, TSADC_COMP_INT(sensor->channel), val);
496	val = RD4(sc, TSADC_INT_EN);
497	val |= TSADC_COMP_INT_SRC_EN(sensor->channel);
498	WR4(sc, TSADC_INT_EN, val);
499}
500
501static void
502tsadc_init(struct tsadc_softc *sc)
503{
504	uint32_t val;
505
506	/* Common part */
507	val = 0;	/* XXX Is this right? */
508	if (sc->shutdown_pol != 0)
509		val |= TSADC_AUTO_CON_POL_HI;
510	else
511		val &= ~TSADC_AUTO_CON_POL_HI;
512	if (sc->conf->q_sel_ntc)
513		val |= TSADC_AUTO_Q_SEL;
514	WR4(sc, TSADC_AUTO_CON, val);
515
516	switch (sc->conf->version) {
517	case TSADC_V2:
518		/* V2 init */
519		WR4(sc, TSADC_AUTO_PERIOD, 250); 	/* 250 ms */
520		WR4(sc, TSADC_AUTO_PERIOD_HT, 50);	/*  50 ms */
521		WR4(sc, TSADC_HIGHT_INT_DEBOUNCE, 4);
522		WR4(sc, TSADC_HIGHT_TSHUT_DEBOUNCE, 4);
523		break;
524	case TSADC_V3:
525		/* V3 init */
526		if (sc->grf == NULL) {
527			/* Errata: adjust interleave to working value */
528			WR4(sc, TSADC_USER_CON, 13 << 6); 	/* 13 clks */
529		} else {
530			SYSCON_WRITE_4(sc->grf, GRF_TSADC_TESTBIT_L,
531			    GRF_TSADC_VCM_EN_L);
532			SYSCON_WRITE_4(sc->grf, GRF_TSADC_TESTBIT_H,
533			    GRF_TSADC_VCM_EN_H);
534			DELAY(30);  /* 15 usec min */
535
536			SYSCON_WRITE_4(sc->grf, GRF_SARADC_TESTBIT,
537			    GRF_SARADC_TESTBIT_ON);
538			SYSCON_WRITE_4(sc->grf, GRF_TSADC_TESTBIT_H,
539			    GRF_TSADC_TESTBIT_H_ON);
540			DELAY(180);  /* 90 usec min */
541		}
542		WR4(sc, TSADC_AUTO_PERIOD, 1875); 	/* 2.5 ms */
543		WR4(sc, TSADC_AUTO_PERIOD_HT, 1875);	/* 2.5 ms */
544		WR4(sc, TSADC_HIGHT_INT_DEBOUNCE, 4);
545		WR4(sc, TSADC_HIGHT_TSHUT_DEBOUNCE, 4);
546		break;
547	case TSADC_V7:
548		/* V7 init */
549		WR4(sc, TSADC_USER_CON, 0xfc0);		/* 97us, at least 90us */
550		WR4(sc, TSADC_AUTO_PERIOD, 1622);	/* 2.5ms */
551		WR4(sc, TSADC_HIGHT_INT_DEBOUNCE, 4);
552		WR4(sc, TSADC_AUTO_PERIOD_HT, 1622);	/* 2.5ms */
553		WR4(sc, TSADC_HIGHT_TSHUT_DEBOUNCE, 4);
554		if (sc->grf) {
555			SYSCON_WRITE_4(sc->grf, GRF_TSADC_CON, GRF_TSADC_TSEN);
556			DELAY(15);			/* 10 usec min */
557			SYSCON_WRITE_4(sc->grf, GRF_TSADC_CON,
558			    GRF_TSADC_ANA_REG0);
559			SYSCON_WRITE_4(sc->grf, GRF_TSADC_CON,
560			    GRF_TSADC_ANA_REG1);
561			SYSCON_WRITE_4(sc->grf, GRF_TSADC_CON,
562			    GRF_TSADC_ANA_REG2);
563			DELAY(100);			/* 90 usec min */
564		}
565		break;
566	}
567}
568
569static int
570tsadc_read_temp(struct tsadc_softc *sc, struct tsensor *sensor, int *temp)
571{
572	uint32_t val;
573
574	val = RD4(sc, TSADC_DATA(sensor->channel));
575	*temp = tsadc_raw_to_temp(sc, val);
576
577#ifdef DEBUG
578	device_printf(sc->dev, "%s: Sensor(id: %d, ch: %d), val: %d temp: %d\n",
579	    __func__, sensor->id, sensor->channel, val, *temp);
580	device_printf(sc->dev, "%s: user_con=0x%08x auto_con=0x%08x "
581	    "comp_int=0x%08x comp_shut=0x%08x\n",
582	    __func__, RD4(sc, TSADC_USER_CON), RD4(sc, TSADC_AUTO_CON),
583	    RD4(sc, TSADC_COMP_INT(sensor->channel)),
584	    RD4(sc, TSADC_COMP_SHUT(sensor->channel)));
585#endif
586	return (0);
587}
588
589static int
590tsadc_get_temp(device_t dev, device_t cdev, uintptr_t id, int *val)
591{
592	struct tsadc_softc *sc;
593	int i, rv;
594
595	sc = device_get_softc(dev);
596
597	if (id >= sc->conf->ntsensors)
598		return (ERANGE);
599
600	for (i = 0; i < sc->conf->ntsensors; i++) {
601		if (sc->conf->tsensors->id == id) {
602			rv =tsadc_read_temp(sc, sc->conf->tsensors + id, val);
603			return (rv);
604		}
605	}
606	return (ERANGE);
607}
608
609static int
610tsadc_sysctl_temperature(SYSCTL_HANDLER_ARGS)
611{
612	struct tsadc_softc *sc;
613	int val;
614	int rv;
615	int id;
616
617	/* Write request */
618	if (req->newptr != NULL)
619		return (EINVAL);
620
621	sc = arg1;
622	id = arg2;
623
624	if (id >= sc->conf->ntsensors)
625		return (ERANGE);
626	rv =  tsadc_read_temp(sc, sc->conf->tsensors + id, &val);
627	if (rv != 0)
628		return (rv);
629
630	val = val / 100;
631	val +=  2731;
632	rv = sysctl_handle_int(oidp, &val, 0, req);
633	return (rv);
634}
635
636static int
637tsadc_init_sysctl(struct tsadc_softc *sc)
638{
639	int i;
640	struct sysctl_oid *oid, *tmp;
641
642	sysctl_ctx_init(&tsadc_sysctl_ctx);
643	/* create node for hw.temp */
644	oid = SYSCTL_ADD_NODE(&tsadc_sysctl_ctx,
645	    SYSCTL_STATIC_CHILDREN(_hw), OID_AUTO, "temperature",
646	    CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, "");
647	if (oid == NULL)
648		return (ENXIO);
649
650	/* Add sensors */
651	for (i = sc->conf->ntsensors  - 1; i >= 0; i--) {
652		tmp = SYSCTL_ADD_PROC(&tsadc_sysctl_ctx,
653		    SYSCTL_CHILDREN(oid), OID_AUTO, sc->conf->tsensors[i].name,
654		    CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_NEEDGIANT, sc, i,
655		    tsadc_sysctl_temperature, "IK", "SoC Temperature");
656		if (tmp == NULL)
657			return (ENXIO);
658	}
659
660	return (0);
661}
662
663static int
664tsadc_intr(void *arg)
665{
666	struct tsadc_softc *sc;
667	uint32_t val;
668
669	sc = (struct tsadc_softc *)arg;
670
671	val = RD4(sc, TSADC_INT_PD);
672	WR4(sc, TSADC_INT_PD, val);
673
674	/* XXX Handle shutdown and alarm interrupts. */
675	if (val & 0x00F0) {
676		device_printf(sc->dev, "Alarm: device temperature "
677		    "is above of shutdown level.\n");
678	} else if (val & 0x000F) {
679		device_printf(sc->dev, "Alarm: device temperature "
680		    "is above of alarm level.\n");
681	}
682	return (FILTER_HANDLED);
683}
684
685static int
686tsadc_probe(device_t dev)
687{
688
689	if (!ofw_bus_status_okay(dev))
690		return (ENXIO);
691
692	if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0)
693		return (ENXIO);
694
695	device_set_desc(dev, "RockChip temperature sensors");
696	return (BUS_PROBE_DEFAULT);
697}
698
699static int
700tsadc_attach(device_t dev)
701{
702	struct tsadc_softc *sc;
703	phandle_t node;
704	uint32_t val;
705	int i, rid, rv;
706
707	sc = device_get_softc(dev);
708	sc->dev = dev;
709	node = ofw_bus_get_node(sc->dev);
710	sc->conf = (struct tsadc_conf *)
711	    ofw_bus_search_compatible(dev, compat_data)->ocd_data;
712	sc->alarm_temp = 90000;
713
714	rid = 0;
715	sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
716	    RF_ACTIVE);
717	if (sc->mem_res == NULL) {
718		device_printf(dev, "Cannot allocate memory resources\n");
719		goto fail;
720	}
721
722	rid = 0;
723	sc->irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, RF_ACTIVE);
724	if (sc->irq_res == NULL) {
725		device_printf(dev, "Cannot allocate IRQ resources\n");
726		goto fail;
727	}
728
729	if ((bus_setup_intr(dev, sc->irq_res, INTR_TYPE_MISC | INTR_MPSAFE,
730	    tsadc_intr, NULL, sc, &sc->irq_ih))) {
731		device_printf(dev,
732		    "WARNING: unable to register interrupt handler\n");
733		goto fail;
734	}
735
736	/* FDT resources */
737	rv = hwreset_array_get_ofw(dev, 0, &sc->hwreset);
738	if (rv != 0) {
739		device_printf(dev, "Cannot get resets\n");
740		goto fail;
741	}
742	rv = clk_get_by_ofw_name(dev, 0, "tsadc", &sc->tsadc_clk);
743	if (rv != 0) {
744		device_printf(dev, "Cannot get 'tsadc' clock: %d\n", rv);
745		goto fail;
746	}
747	rv = clk_get_by_ofw_name(dev, 0, "apb_pclk", &sc->apb_pclk_clk);
748	if (rv != 0) {
749		device_printf(dev, "Cannot get 'apb_pclk' clock: %d\n", rv);
750		goto fail;
751	}
752
753	/* grf is optional */
754	rv = syscon_get_by_ofw_property(dev, node, "rockchip,grf", &sc->grf);
755	if (rv != 0 && rv != ENOENT) {
756		device_printf(dev, "Cannot get 'grf' syscon: %d\n", rv);
757		goto fail;
758	}
759
760	rv = OF_getencprop(node, "rockchip,hw-tshut-temp",
761	    &sc->shutdown_temp, sizeof(sc->shutdown_temp));
762	if (rv <= 0)
763		sc->shutdown_temp = sc->conf->shutdown_temp;
764
765	rv = OF_getencprop(node, "rockchip,hw-tshut-mode",
766	    &sc->shutdown_mode, sizeof(sc->shutdown_mode));
767	if (rv <= 0)
768		sc->shutdown_mode = sc->conf->shutdown_mode;
769
770	rv = OF_getencprop(node, "rockchip,hw-tshut-polarity",
771	    &sc->shutdown_pol, sizeof(sc->shutdown_pol));
772	if (rv <= 0)
773		sc->shutdown_pol = sc->conf->shutdown_pol;
774
775	/* Wakeup controller */
776	rv = hwreset_array_assert(sc->hwreset);
777	if (rv != 0) {
778		device_printf(dev, "Cannot assert reset\n");
779		goto fail;
780	}
781
782	/* Set the assigned clocks parent and freq */
783	rv = clk_set_assigned(sc->dev, node);
784	if (rv != 0 && rv != ENOENT) {
785		device_printf(dev, "clk_set_assigned failed\n");
786		goto fail;
787	}
788
789	rv = clk_enable(sc->tsadc_clk);
790	if (rv != 0) {
791		device_printf(dev, "Cannot enable 'tsadc_clk' clock: %d\n", rv);
792		goto fail;
793	}
794	rv = clk_enable(sc->apb_pclk_clk);
795	if (rv != 0) {
796		device_printf(dev, "Cannot enable 'apb_pclk' clock: %d\n", rv);
797		goto fail;
798	}
799	rv = hwreset_array_deassert(sc->hwreset);
800	if (rv != 0) {
801		device_printf(dev, "Cannot deassert reset\n");
802		goto fail;
803	}
804
805	tsadc_init(sc);
806	for (i = 0; i < sc->conf->ntsensors; i++)
807		tsadc_init_tsensor(sc, sc->conf->tsensors + i);
808
809	/* Enable auto mode */
810	val = RD4(sc, TSADC_AUTO_CON);
811	val |= TSADC_AUTO_CON_AUTO;
812	WR4(sc, TSADC_AUTO_CON, val);
813
814	rv = tsadc_init_sysctl(sc);
815	if (rv != 0) {
816		device_printf(sc->dev, "Cannot initialize sysctls\n");
817		goto fail_sysctl;
818	}
819
820	OF_device_register_xref(OF_xref_from_node(node), dev);
821	return (bus_generic_attach(dev));
822
823fail_sysctl:
824	sysctl_ctx_free(&tsadc_sysctl_ctx);
825fail:
826	if (sc->irq_ih != NULL)
827		bus_teardown_intr(dev, sc->irq_res, sc->irq_ih);
828	if (sc->tsadc_clk != NULL)
829		clk_release(sc->tsadc_clk);
830	if (sc->apb_pclk_clk != NULL)
831		clk_release(sc->apb_pclk_clk);
832	if (sc->hwreset != NULL)
833		hwreset_array_release(sc->hwreset);
834	if (sc->irq_res != NULL)
835		bus_release_resource(dev, SYS_RES_IRQ, 0, sc->irq_res);
836	if (sc->mem_res != NULL)
837		bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->mem_res);
838
839	return (ENXIO);
840}
841
842static int
843tsadc_detach(device_t dev)
844{
845	struct tsadc_softc *sc;
846	sc = device_get_softc(dev);
847
848	if (sc->irq_ih != NULL)
849		bus_teardown_intr(dev, sc->irq_res, sc->irq_ih);
850	sysctl_ctx_free(&tsadc_sysctl_ctx);
851	if (sc->tsadc_clk != NULL)
852		clk_release(sc->tsadc_clk);
853	if (sc->apb_pclk_clk != NULL)
854		clk_release(sc->apb_pclk_clk);
855	if (sc->hwreset != NULL)
856		hwreset_array_release(sc->hwreset);
857	if (sc->irq_res != NULL)
858		bus_release_resource(dev, SYS_RES_IRQ, 0, sc->irq_res);
859	if (sc->mem_res != NULL)
860		bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->mem_res);
861
862	return (ENXIO);
863}
864
865static device_method_t rk_tsadc_methods[] = {
866	/* Device interface */
867	DEVMETHOD(device_probe,			tsadc_probe),
868	DEVMETHOD(device_attach,		tsadc_attach),
869	DEVMETHOD(device_detach,		tsadc_detach),
870
871	/* TSADC interface */
872	DEVMETHOD(rk_tsadc_get_temperature,	tsadc_get_temp),
873
874	DEVMETHOD_END
875};
876
877static DEFINE_CLASS_0(rk_tsadc, rk_tsadc_driver, rk_tsadc_methods,
878    sizeof(struct tsadc_softc));
879EARLY_DRIVER_MODULE(rk_tsadc, simplebus, rk_tsadc_driver, NULL, NULL,
880    BUS_PASS_TIMER + BUS_PASS_ORDER_LAST);
881