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