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