xref: /rk3399_ARM-atf/plat/hisilicon/hikey960/hikey960_boardid.c (revision 2f2abcf4ba37bdd1332111c240961aae509c5d9c)
1*2f2abcf4SHaojian Zhuang /*
2*2f2abcf4SHaojian Zhuang  * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
3*2f2abcf4SHaojian Zhuang  *
4*2f2abcf4SHaojian Zhuang  * SPDX-License-Identifier: BSD-3-Clause
5*2f2abcf4SHaojian Zhuang  */
6*2f2abcf4SHaojian Zhuang 
7*2f2abcf4SHaojian Zhuang #include <assert.h>
8*2f2abcf4SHaojian Zhuang #include <debug.h>
9*2f2abcf4SHaojian Zhuang #include <delay_timer.h>
10*2f2abcf4SHaojian Zhuang #include <errno.h>
11*2f2abcf4SHaojian Zhuang #include <hi3660.h>
12*2f2abcf4SHaojian Zhuang #include <mmio.h>
13*2f2abcf4SHaojian Zhuang 
14*2f2abcf4SHaojian Zhuang #include "hikey960_private.h"
15*2f2abcf4SHaojian Zhuang 
16*2f2abcf4SHaojian Zhuang #define ADC_ADCIN0				0
17*2f2abcf4SHaojian Zhuang #define ADC_ADCIN1				1
18*2f2abcf4SHaojian Zhuang #define ADC_ADCIN2				2
19*2f2abcf4SHaojian Zhuang 
20*2f2abcf4SHaojian Zhuang #define HKADC_DATA_GRADE0			0
21*2f2abcf4SHaojian Zhuang #define HKADC_DATA_GRADE1			100
22*2f2abcf4SHaojian Zhuang #define HKADC_DATA_GRADE2			300
23*2f2abcf4SHaojian Zhuang #define HKADC_DATA_GRADE3			500
24*2f2abcf4SHaojian Zhuang #define HKADC_DATA_GRADE4			700
25*2f2abcf4SHaojian Zhuang #define HKADC_DATA_GRADE5			900
26*2f2abcf4SHaojian Zhuang #define HKADC_DATA_GRADE6			1100
27*2f2abcf4SHaojian Zhuang #define HKADC_DATA_GRADE7			1300
28*2f2abcf4SHaojian Zhuang #define HKADC_DATA_GRADE8			1500
29*2f2abcf4SHaojian Zhuang #define HKADC_DATA_GRADE9			1700
30*2f2abcf4SHaojian Zhuang #define HKADC_DATA_GRADE10			1800
31*2f2abcf4SHaojian Zhuang 
32*2f2abcf4SHaojian Zhuang #define BOARDID_VALUE0				0
33*2f2abcf4SHaojian Zhuang #define BOARDID_VALUE1				1
34*2f2abcf4SHaojian Zhuang #define BOARDID_VALUE2				2
35*2f2abcf4SHaojian Zhuang #define BOARDID_VALUE3				3
36*2f2abcf4SHaojian Zhuang #define BOARDID_VALUE4				4
37*2f2abcf4SHaojian Zhuang #define BOARDID_VALUE5				5
38*2f2abcf4SHaojian Zhuang #define BOARDID_VALUE6				6
39*2f2abcf4SHaojian Zhuang #define BOARDID_VALUE7				7
40*2f2abcf4SHaojian Zhuang #define BOARDID_VALUE8				8
41*2f2abcf4SHaojian Zhuang #define BOARDID_VALUE9				9
42*2f2abcf4SHaojian Zhuang #define BOARDID_UNKNOWN				0xF
43*2f2abcf4SHaojian Zhuang 
44*2f2abcf4SHaojian Zhuang #define BOARDID3_BASE				5
45*2f2abcf4SHaojian Zhuang 
46*2f2abcf4SHaojian Zhuang 
47*2f2abcf4SHaojian Zhuang static void init_adc(void)
48*2f2abcf4SHaojian Zhuang {
49*2f2abcf4SHaojian Zhuang 	/* reset hkadc */
50*2f2abcf4SHaojian Zhuang 	mmio_write_32(CRG_PERRSTEN2_REG, PERRSTEN2_HKADCSSI);
51*2f2abcf4SHaojian Zhuang 	/* wait a few clock cycles */
52*2f2abcf4SHaojian Zhuang 	udelay(2);
53*2f2abcf4SHaojian Zhuang 	mmio_write_32(CRG_PERRSTDIS2_REG, PERRSTEN2_HKADCSSI);
54*2f2abcf4SHaojian Zhuang 	udelay(2);
55*2f2abcf4SHaojian Zhuang 	/* enable hkadc clock */
56*2f2abcf4SHaojian Zhuang 	mmio_write_32(CRG_PERDIS2_REG, PEREN2_HKADCSSI);
57*2f2abcf4SHaojian Zhuang 	udelay(2);
58*2f2abcf4SHaojian Zhuang 	mmio_write_32(CRG_PEREN2_REG, PEREN2_HKADCSSI);
59*2f2abcf4SHaojian Zhuang 	udelay(2);
60*2f2abcf4SHaojian Zhuang }
61*2f2abcf4SHaojian Zhuang 
62*2f2abcf4SHaojian Zhuang static int get_adc(unsigned int channel, unsigned int *value)
63*2f2abcf4SHaojian Zhuang {
64*2f2abcf4SHaojian Zhuang 	unsigned int	data, value1, value0;
65*2f2abcf4SHaojian Zhuang 
66*2f2abcf4SHaojian Zhuang 	if (channel > HKADC_CHANNEL_MAX) {
67*2f2abcf4SHaojian Zhuang 		WARN("invalid channel:%d\n", channel);
68*2f2abcf4SHaojian Zhuang 		return -EFAULT;
69*2f2abcf4SHaojian Zhuang 	}
70*2f2abcf4SHaojian Zhuang 	/* configure the read/write operation for external HKADC */
71*2f2abcf4SHaojian Zhuang 	mmio_write_32(HKADC_WR01_DATA_REG, HKADC_WR01_VALUE | channel);
72*2f2abcf4SHaojian Zhuang 	mmio_write_32(HKADC_WR23_DATA_REG, HKADC_WR23_VALUE);
73*2f2abcf4SHaojian Zhuang 	mmio_write_32(HKADC_WR45_DATA_REG, HKADC_WR45_VALUE);
74*2f2abcf4SHaojian Zhuang 	/* configure the number of accessing registers */
75*2f2abcf4SHaojian Zhuang 	mmio_write_32(HKADC_WR_NUM_REG, HKADC_WR_NUM_VALUE);
76*2f2abcf4SHaojian Zhuang 	/* configure delay of accessing registers */
77*2f2abcf4SHaojian Zhuang 	mmio_write_32(HKADC_DELAY01_REG, HKADC_CHANNEL0_DELAY01_VALUE);
78*2f2abcf4SHaojian Zhuang 	mmio_write_32(HKADC_DELAY23_REG, HKADC_DELAY23_VALUE);
79*2f2abcf4SHaojian Zhuang 
80*2f2abcf4SHaojian Zhuang 	/* start HKADC */
81*2f2abcf4SHaojian Zhuang 	mmio_write_32(HKADC_DSP_START_REG, 1);
82*2f2abcf4SHaojian Zhuang 	do {
83*2f2abcf4SHaojian Zhuang 		data = mmio_read_32(HKADC_DSP_START_REG);
84*2f2abcf4SHaojian Zhuang 	} while (data & 1);
85*2f2abcf4SHaojian Zhuang 
86*2f2abcf4SHaojian Zhuang 	/* convert AD result */
87*2f2abcf4SHaojian Zhuang 	value1 = mmio_read_32(HKADC_DSP_RD2_DATA_REG) & 0xffff;
88*2f2abcf4SHaojian Zhuang 	value0 = mmio_read_32(HKADC_DSP_RD3_DATA_REG) & 0xffff;
89*2f2abcf4SHaojian Zhuang 
90*2f2abcf4SHaojian Zhuang 	data = ((value1 << 4) & HKADC_VALUE_HIGH) |
91*2f2abcf4SHaojian Zhuang 	       ((value0 >> 4) & HKADC_VALUE_LOW);
92*2f2abcf4SHaojian Zhuang 	*value = data;
93*2f2abcf4SHaojian Zhuang 	return 0;
94*2f2abcf4SHaojian Zhuang }
95*2f2abcf4SHaojian Zhuang 
96*2f2abcf4SHaojian Zhuang static int get_value(unsigned int channel, unsigned int *value)
97*2f2abcf4SHaojian Zhuang {
98*2f2abcf4SHaojian Zhuang 	int ret;
99*2f2abcf4SHaojian Zhuang 
100*2f2abcf4SHaojian Zhuang 	ret = get_adc(channel, value);
101*2f2abcf4SHaojian Zhuang 	if (ret)
102*2f2abcf4SHaojian Zhuang 		return ret;
103*2f2abcf4SHaojian Zhuang 
104*2f2abcf4SHaojian Zhuang 	/* convert ADC value to micro-volt */
105*2f2abcf4SHaojian Zhuang 	ret = ((*value & HKADC_VALID_VALUE) * HKADC_VREF_1V8) / HKADC_ACCURACY;
106*2f2abcf4SHaojian Zhuang 	*value = ret;
107*2f2abcf4SHaojian Zhuang 	return 0;
108*2f2abcf4SHaojian Zhuang }
109*2f2abcf4SHaojian Zhuang 
110*2f2abcf4SHaojian Zhuang static int adcin_data_remap(unsigned int adcin_value)
111*2f2abcf4SHaojian Zhuang {
112*2f2abcf4SHaojian Zhuang 	int	ret;
113*2f2abcf4SHaojian Zhuang 
114*2f2abcf4SHaojian Zhuang 	if (adcin_value < HKADC_DATA_GRADE0)
115*2f2abcf4SHaojian Zhuang 		ret = BOARDID_UNKNOWN;
116*2f2abcf4SHaojian Zhuang 	else if (adcin_value < HKADC_DATA_GRADE1)
117*2f2abcf4SHaojian Zhuang 		ret = BOARDID_VALUE0;
118*2f2abcf4SHaojian Zhuang 	else if (adcin_value < HKADC_DATA_GRADE2)
119*2f2abcf4SHaojian Zhuang 		ret = BOARDID_VALUE1;
120*2f2abcf4SHaojian Zhuang 	else if (adcin_value < HKADC_DATA_GRADE3)
121*2f2abcf4SHaojian Zhuang 		ret = BOARDID_VALUE2;
122*2f2abcf4SHaojian Zhuang 	else if (adcin_value < HKADC_DATA_GRADE4)
123*2f2abcf4SHaojian Zhuang 		ret = BOARDID_VALUE3;
124*2f2abcf4SHaojian Zhuang 	else if (adcin_value < HKADC_DATA_GRADE5)
125*2f2abcf4SHaojian Zhuang 		ret = BOARDID_VALUE4;
126*2f2abcf4SHaojian Zhuang 	else if (adcin_value < HKADC_DATA_GRADE6)
127*2f2abcf4SHaojian Zhuang 		ret = BOARDID_VALUE5;
128*2f2abcf4SHaojian Zhuang 	else if (adcin_value < HKADC_DATA_GRADE7)
129*2f2abcf4SHaojian Zhuang 		ret = BOARDID_VALUE6;
130*2f2abcf4SHaojian Zhuang 	else if (adcin_value < HKADC_DATA_GRADE8)
131*2f2abcf4SHaojian Zhuang 		ret = BOARDID_VALUE7;
132*2f2abcf4SHaojian Zhuang 	else if (adcin_value < HKADC_DATA_GRADE9)
133*2f2abcf4SHaojian Zhuang 		ret = BOARDID_VALUE8;
134*2f2abcf4SHaojian Zhuang 	else if (adcin_value < HKADC_DATA_GRADE10)
135*2f2abcf4SHaojian Zhuang 		ret = BOARDID_VALUE9;
136*2f2abcf4SHaojian Zhuang 	else
137*2f2abcf4SHaojian Zhuang 		ret = BOARDID_UNKNOWN;
138*2f2abcf4SHaojian Zhuang 	return ret;
139*2f2abcf4SHaojian Zhuang }
140*2f2abcf4SHaojian Zhuang 
141*2f2abcf4SHaojian Zhuang int hikey960_read_boardid(unsigned int *id)
142*2f2abcf4SHaojian Zhuang {
143*2f2abcf4SHaojian Zhuang 	unsigned int	adcin0, adcin1, adcin2;
144*2f2abcf4SHaojian Zhuang 	unsigned int	adcin0_remap, adcin1_remap, adcin2_remap;
145*2f2abcf4SHaojian Zhuang 
146*2f2abcf4SHaojian Zhuang 	assert(id != NULL);
147*2f2abcf4SHaojian Zhuang 
148*2f2abcf4SHaojian Zhuang 	init_adc();
149*2f2abcf4SHaojian Zhuang 
150*2f2abcf4SHaojian Zhuang 	/* read ADC channel0 data */
151*2f2abcf4SHaojian Zhuang 	get_value(ADC_ADCIN0, &adcin0);
152*2f2abcf4SHaojian Zhuang 	adcin0_remap = adcin_data_remap(adcin0);
153*2f2abcf4SHaojian Zhuang 	INFO("[BDID]adcin0:%d adcin0_remap:%d\n", adcin0, adcin0_remap);
154*2f2abcf4SHaojian Zhuang 	if (adcin0_remap == BOARDID_UNKNOWN)
155*2f2abcf4SHaojian Zhuang 		return -EINVAL;
156*2f2abcf4SHaojian Zhuang 	/* read ADC channel1 data */
157*2f2abcf4SHaojian Zhuang 	get_value(ADC_ADCIN1, &adcin1);
158*2f2abcf4SHaojian Zhuang 	adcin1_remap = adcin_data_remap(adcin1);
159*2f2abcf4SHaojian Zhuang 	INFO("[BDID]adcin1:%d adcin1_remap:%d\n", adcin1, adcin1_remap);
160*2f2abcf4SHaojian Zhuang 	if (adcin1_remap == BOARDID_UNKNOWN)
161*2f2abcf4SHaojian Zhuang 		return -EINVAL;
162*2f2abcf4SHaojian Zhuang 	/* read ADC channel2 data */
163*2f2abcf4SHaojian Zhuang 	get_value(ADC_ADCIN2, &adcin2);
164*2f2abcf4SHaojian Zhuang 	adcin2_remap = adcin_data_remap(adcin2);
165*2f2abcf4SHaojian Zhuang 	INFO("[BDID]adcin2:%d adcin2_remap:%d\n", adcin2, adcin2_remap);
166*2f2abcf4SHaojian Zhuang 	if (adcin2_remap == BOARDID_UNKNOWN)
167*2f2abcf4SHaojian Zhuang 		return -EINVAL;
168*2f2abcf4SHaojian Zhuang 	*id = BOARDID3_BASE * 1000 + (adcin2_remap * 100) +
169*2f2abcf4SHaojian Zhuang 		(adcin1_remap * 10) + adcin0_remap;
170*2f2abcf4SHaojian Zhuang 	INFO("[BDID]boardid: %d\n", *id);
171*2f2abcf4SHaojian Zhuang 	return 0;
172*2f2abcf4SHaojian Zhuang }
173