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