summaryrefslogtreecommitdiff
path: root/src/soc/rockchip/rk3399/tsadc.c
blob: 9f699150fc8114fac4b6cd2bedf7ff69b87fd5e3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
/*
 * This file is part of the coreboot project.
 *
 * Copyright 2014 Rockchip Inc.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; version 2 of the License.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 */

#include <device/mmio.h>
#include <delay.h>
#include <soc/clock.h>
#include <soc/grf.h>
#include <soc/tsadc.h>
#include <stdint.h>

struct rk3399_tsadc_regs {
	u32	user_con;
	u32	auto_con;
	u32	int_en;
	u32	int_pd;
	u32	reserved0[(0x20 - 0x10) / 4];
	u32	data0;
	u32	data1;
	u32	data2;
	u32	data3;
	u32	comp0_int;
	u32	comp1_int;
	u32	comp2_int;
	u32	comp3_int;
	u32	comp0_shut;
	u32	comp1_shut;
	u32	comp2_shut;
	u32	comp3_shut;
	u32	reserved1[(0x60 - 0x50) / 4];
	u32	hight_int_debounce;
	u32	hight_tshut_debounce;
	u32	auto_period;
	u32	auto_period_ht;
};
check_member(rk3399_tsadc_regs, auto_period_ht, 0x6c);

/* user_con */
#define ADC_POWER_CTRL	(1 << 3)
#define START_MODE	(1 << 4)
#define START_SHIFT	5
#define START_MASK	1
#define INTER_PD_SHIFT	6
#define INTER_PD_MASK	0x3f

/* auto_con */
#define LAST_TSHUT	(1 << 24)
#define SRC3_EN		(1 << 7)
#define SRC2_EN		(1 << 6)
#define SRC1_EN		(1 << 5)
#define SRC0_EN		(1 << 4)
#define Q_SEL		(1 << 1)
#define AUTO_EN		(1 << 0)

/* int_en */
#define TSHUT_CRU_EN_SRC3	(1 << 11)
#define TSHUT_CRU_EN_SRC2	(1 << 10)
#define TSHUT_CRU_EN_SRC1	(1 << 9)
#define TSHUT_CRU_EN_SRC0	(1 << 8)
#define TSHUT_GPIO_EN_SRC3	(1 << 7)
#define TSHUT_GPIO_EN_SRC2	(1 << 6)
#define TSHUT_GPIO_EN_SRC1	(1 << 5)
#define TSHUT_GPIO_EN_SRC0	(1 << 4)

#define AUTO_PERIOD		187500 /* 250ms */
#define AUTO_DEBOUNCE		4
#define AUTO_PERIOD_HT		37500 /* 50ms */
#define AUTO_DEBOUNCE_HT	4
#define TSADC_CLOCK_HZ		(750 * KHz)

/* AD value, correspond to 120 degrees Celsius,
 * Please refer shut value table in:
 * https://patchwork.kernel.org/patch/8908411/
 * A quick ref:
 * {573, 60000}, {599, 75000}, {616, 85000}, {633, 95000},
 * {642, 100000}, {659, 110000}, {677, 120000}, {685, 125000}
 */
#define TSADC_SHUT_VALUE	677

#define GRF_TSADC_TSEN_PD0_ON	RK_SETBITS(0)
#define GRF_TSADC_TSEN_PD0_OFF	RK_CLRBITS(0)
#define GRF_SARADC_TSEN_ON	RK_SETBITS(0)

struct rk3399_tsadc_regs *rk3399_tsadc = (void *)TSADC_BASE;

void tsadc_init(uint32_t polarity)
{
	rkclk_configure_tsadc(TSADC_CLOCK_HZ);

	/* tsadc power sequence */
	clrbits32(&rk3399_tsadc->user_con, ADC_POWER_CTRL);
	write32(&rk3399_grf->tsadc_testbit_l, GRF_TSADC_TSEN_PD0_ON);
	udelay(50);
	write32(&rk3399_grf->tsadc_testbit_l, GRF_TSADC_TSEN_PD0_OFF);
	udelay(20);
	write32(&rk3399_grf->saradc_testbit, GRF_SARADC_TSEN_ON);
	udelay(100);

	/* set the tshut polarity */
	write32(&rk3399_tsadc->auto_con, polarity);

	/* setup the automatic mode:
	 * AUTO_PERIOD: interleave between every two accessing of TSADC
	 * AUTO_DEBOUNCE: only generate interrupt or TSHUT when temperature
	 *                is higher than COMP_INT for "debounce" times
	 * AUTO_PERIOD_HT: the interleave between every two accessing after the
	 *                 temperature is higher than COMP_SHUT or COMP_INT
	 * AUTO_DEBOUNCE_HT: only generate interrupt or TSHUT when temperature
	 *                   is higher than COMP_SHUT for "debounce" times.
	 */
	write32(&rk3399_tsadc->auto_period, AUTO_PERIOD);
	write32(&rk3399_tsadc->hight_int_debounce, AUTO_DEBOUNCE);
	write32(&rk3399_tsadc->auto_period_ht, AUTO_PERIOD_HT);
	write32(&rk3399_tsadc->hight_tshut_debounce, AUTO_DEBOUNCE_HT);
	/* Enable the src0, negative temperature coefficient */
	setbits32(&rk3399_tsadc->auto_con, Q_SEL | SRC0_EN);
	udelay(100);
	setbits32(&rk3399_tsadc->auto_con, AUTO_EN);

	write32(&rk3399_tsadc->comp0_shut, TSADC_SHUT_VALUE);
	write32(&rk3399_tsadc->int_en, TSHUT_CRU_EN_SRC0 | TSHUT_GPIO_EN_SRC0);

	/* Set the tsadc_int pinmux */
	write32(&rk3399_pmugrf->tsadc_int, IOMUX_TSADC_INT);
}