xref: /rk3399_ARM-atf/plat/hisilicon/hikey960/hikey960_boardid.c (revision 09d40e0e08283a249e7dce0e106c07c5141f9b7e)
12f2abcf4SHaojian Zhuang /*
217cf8ab1SHaojian Zhuang  * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
32f2abcf4SHaojian Zhuang  *
42f2abcf4SHaojian Zhuang  * SPDX-License-Identifier: BSD-3-Clause
52f2abcf4SHaojian Zhuang  */
62f2abcf4SHaojian Zhuang 
72f2abcf4SHaojian Zhuang #include <assert.h>
82f2abcf4SHaojian Zhuang #include <errno.h>
92f2abcf4SHaojian Zhuang 
10*09d40e0eSAntonio Nino Diaz #include <common/debug.h>
11*09d40e0eSAntonio Nino Diaz #include <drivers/delay_timer.h>
12*09d40e0eSAntonio Nino Diaz #include <lib/mmio.h>
13*09d40e0eSAntonio Nino Diaz 
14*09d40e0eSAntonio Nino Diaz #include <hi3660.h>
152f2abcf4SHaojian Zhuang #include "hikey960_private.h"
162f2abcf4SHaojian Zhuang 
172f2abcf4SHaojian Zhuang #define ADC_ADCIN0				0
182f2abcf4SHaojian Zhuang #define ADC_ADCIN1				1
192f2abcf4SHaojian Zhuang #define ADC_ADCIN2				2
202f2abcf4SHaojian Zhuang 
212f2abcf4SHaojian Zhuang #define HKADC_DATA_GRADE0			0
222f2abcf4SHaojian Zhuang #define HKADC_DATA_GRADE1			100
232f2abcf4SHaojian Zhuang #define HKADC_DATA_GRADE2			300
242f2abcf4SHaojian Zhuang #define HKADC_DATA_GRADE3			500
252f2abcf4SHaojian Zhuang #define HKADC_DATA_GRADE4			700
262f2abcf4SHaojian Zhuang #define HKADC_DATA_GRADE5			900
272f2abcf4SHaojian Zhuang #define HKADC_DATA_GRADE6			1100
282f2abcf4SHaojian Zhuang #define HKADC_DATA_GRADE7			1300
292f2abcf4SHaojian Zhuang #define HKADC_DATA_GRADE8			1500
302f2abcf4SHaojian Zhuang #define HKADC_DATA_GRADE9			1700
312f2abcf4SHaojian Zhuang #define HKADC_DATA_GRADE10			1800
322f2abcf4SHaojian Zhuang 
332f2abcf4SHaojian Zhuang #define BOARDID_VALUE0				0
342f2abcf4SHaojian Zhuang #define BOARDID_VALUE1				1
352f2abcf4SHaojian Zhuang #define BOARDID_VALUE2				2
362f2abcf4SHaojian Zhuang #define BOARDID_VALUE3				3
372f2abcf4SHaojian Zhuang #define BOARDID_VALUE4				4
382f2abcf4SHaojian Zhuang #define BOARDID_VALUE5				5
392f2abcf4SHaojian Zhuang #define BOARDID_VALUE6				6
402f2abcf4SHaojian Zhuang #define BOARDID_VALUE7				7
412f2abcf4SHaojian Zhuang #define BOARDID_VALUE8				8
422f2abcf4SHaojian Zhuang #define BOARDID_VALUE9				9
432f2abcf4SHaojian Zhuang #define BOARDID_UNKNOWN				0xF
442f2abcf4SHaojian Zhuang 
452f2abcf4SHaojian Zhuang #define BOARDID3_BASE				5
462f2abcf4SHaojian Zhuang 
472f2abcf4SHaojian Zhuang 
482f2abcf4SHaojian Zhuang static void init_adc(void)
492f2abcf4SHaojian Zhuang {
502f2abcf4SHaojian Zhuang 	/* reset hkadc */
512f2abcf4SHaojian Zhuang 	mmio_write_32(CRG_PERRSTEN2_REG, PERRSTEN2_HKADCSSI);
522f2abcf4SHaojian Zhuang 	/* wait a few clock cycles */
532f2abcf4SHaojian Zhuang 	udelay(2);
542f2abcf4SHaojian Zhuang 	mmio_write_32(CRG_PERRSTDIS2_REG, PERRSTEN2_HKADCSSI);
552f2abcf4SHaojian Zhuang 	udelay(2);
562f2abcf4SHaojian Zhuang 	/* enable hkadc clock */
572f2abcf4SHaojian Zhuang 	mmio_write_32(CRG_PERDIS2_REG, PEREN2_HKADCSSI);
582f2abcf4SHaojian Zhuang 	udelay(2);
592f2abcf4SHaojian Zhuang 	mmio_write_32(CRG_PEREN2_REG, PEREN2_HKADCSSI);
602f2abcf4SHaojian Zhuang 	udelay(2);
612f2abcf4SHaojian Zhuang }
622f2abcf4SHaojian Zhuang 
632f2abcf4SHaojian Zhuang static int get_adc(unsigned int channel, unsigned int *value)
642f2abcf4SHaojian Zhuang {
652f2abcf4SHaojian Zhuang 	unsigned int	data, value1, value0;
662f2abcf4SHaojian Zhuang 
672f2abcf4SHaojian Zhuang 	if (channel > HKADC_CHANNEL_MAX) {
682f2abcf4SHaojian Zhuang 		WARN("invalid channel:%d\n", channel);
692f2abcf4SHaojian Zhuang 		return -EFAULT;
702f2abcf4SHaojian Zhuang 	}
712f2abcf4SHaojian Zhuang 	/* configure the read/write operation for external HKADC */
722f2abcf4SHaojian Zhuang 	mmio_write_32(HKADC_WR01_DATA_REG, HKADC_WR01_VALUE | channel);
732f2abcf4SHaojian Zhuang 	mmio_write_32(HKADC_WR23_DATA_REG, HKADC_WR23_VALUE);
742f2abcf4SHaojian Zhuang 	mmio_write_32(HKADC_WR45_DATA_REG, HKADC_WR45_VALUE);
752f2abcf4SHaojian Zhuang 	/* configure the number of accessing registers */
762f2abcf4SHaojian Zhuang 	mmio_write_32(HKADC_WR_NUM_REG, HKADC_WR_NUM_VALUE);
772f2abcf4SHaojian Zhuang 	/* configure delay of accessing registers */
782f2abcf4SHaojian Zhuang 	mmio_write_32(HKADC_DELAY01_REG, HKADC_CHANNEL0_DELAY01_VALUE);
792f2abcf4SHaojian Zhuang 	mmio_write_32(HKADC_DELAY23_REG, HKADC_DELAY23_VALUE);
802f2abcf4SHaojian Zhuang 
812f2abcf4SHaojian Zhuang 	/* start HKADC */
822f2abcf4SHaojian Zhuang 	mmio_write_32(HKADC_DSP_START_REG, 1);
832f2abcf4SHaojian Zhuang 	do {
842f2abcf4SHaojian Zhuang 		data = mmio_read_32(HKADC_DSP_START_REG);
852f2abcf4SHaojian Zhuang 	} while (data & 1);
862f2abcf4SHaojian Zhuang 
872f2abcf4SHaojian Zhuang 	/* convert AD result */
882f2abcf4SHaojian Zhuang 	value1 = mmio_read_32(HKADC_DSP_RD2_DATA_REG) & 0xffff;
892f2abcf4SHaojian Zhuang 	value0 = mmio_read_32(HKADC_DSP_RD3_DATA_REG) & 0xffff;
902f2abcf4SHaojian Zhuang 
912f2abcf4SHaojian Zhuang 	data = ((value1 << 4) & HKADC_VALUE_HIGH) |
922f2abcf4SHaojian Zhuang 	       ((value0 >> 4) & HKADC_VALUE_LOW);
932f2abcf4SHaojian Zhuang 	*value = data;
942f2abcf4SHaojian Zhuang 	return 0;
952f2abcf4SHaojian Zhuang }
962f2abcf4SHaojian Zhuang 
972f2abcf4SHaojian Zhuang static int get_value(unsigned int channel, unsigned int *value)
982f2abcf4SHaojian Zhuang {
992f2abcf4SHaojian Zhuang 	int ret;
1002f2abcf4SHaojian Zhuang 
1012f2abcf4SHaojian Zhuang 	ret = get_adc(channel, value);
1022f2abcf4SHaojian Zhuang 	if (ret)
1032f2abcf4SHaojian Zhuang 		return ret;
1042f2abcf4SHaojian Zhuang 
1052f2abcf4SHaojian Zhuang 	/* convert ADC value to micro-volt */
1062f2abcf4SHaojian Zhuang 	ret = ((*value & HKADC_VALID_VALUE) * HKADC_VREF_1V8) / HKADC_ACCURACY;
1072f2abcf4SHaojian Zhuang 	*value = ret;
1082f2abcf4SHaojian Zhuang 	return 0;
1092f2abcf4SHaojian Zhuang }
1102f2abcf4SHaojian Zhuang 
1112f2abcf4SHaojian Zhuang static int adcin_data_remap(unsigned int adcin_value)
1122f2abcf4SHaojian Zhuang {
1132f2abcf4SHaojian Zhuang 	int	ret;
1142f2abcf4SHaojian Zhuang 
1158aa928acSHaojian Zhuang 	if (adcin_value < HKADC_DATA_GRADE1)
1162f2abcf4SHaojian Zhuang 		ret = BOARDID_VALUE0;
1172f2abcf4SHaojian Zhuang 	else if (adcin_value < HKADC_DATA_GRADE2)
1182f2abcf4SHaojian Zhuang 		ret = BOARDID_VALUE1;
1192f2abcf4SHaojian Zhuang 	else if (adcin_value < HKADC_DATA_GRADE3)
1202f2abcf4SHaojian Zhuang 		ret = BOARDID_VALUE2;
1212f2abcf4SHaojian Zhuang 	else if (adcin_value < HKADC_DATA_GRADE4)
1222f2abcf4SHaojian Zhuang 		ret = BOARDID_VALUE3;
1232f2abcf4SHaojian Zhuang 	else if (adcin_value < HKADC_DATA_GRADE5)
1242f2abcf4SHaojian Zhuang 		ret = BOARDID_VALUE4;
1252f2abcf4SHaojian Zhuang 	else if (adcin_value < HKADC_DATA_GRADE6)
1262f2abcf4SHaojian Zhuang 		ret = BOARDID_VALUE5;
1272f2abcf4SHaojian Zhuang 	else if (adcin_value < HKADC_DATA_GRADE7)
1282f2abcf4SHaojian Zhuang 		ret = BOARDID_VALUE6;
1292f2abcf4SHaojian Zhuang 	else if (adcin_value < HKADC_DATA_GRADE8)
1302f2abcf4SHaojian Zhuang 		ret = BOARDID_VALUE7;
1312f2abcf4SHaojian Zhuang 	else if (adcin_value < HKADC_DATA_GRADE9)
1322f2abcf4SHaojian Zhuang 		ret = BOARDID_VALUE8;
1332f2abcf4SHaojian Zhuang 	else if (adcin_value < HKADC_DATA_GRADE10)
1342f2abcf4SHaojian Zhuang 		ret = BOARDID_VALUE9;
1352f2abcf4SHaojian Zhuang 	else
1362f2abcf4SHaojian Zhuang 		ret = BOARDID_UNKNOWN;
1372f2abcf4SHaojian Zhuang 	return ret;
1382f2abcf4SHaojian Zhuang }
1392f2abcf4SHaojian Zhuang 
1402f2abcf4SHaojian Zhuang int hikey960_read_boardid(unsigned int *id)
1412f2abcf4SHaojian Zhuang {
1422f2abcf4SHaojian Zhuang 	unsigned int	adcin0, adcin1, adcin2;
1432f2abcf4SHaojian Zhuang 	unsigned int	adcin0_remap, adcin1_remap, adcin2_remap;
1442f2abcf4SHaojian Zhuang 
1452f2abcf4SHaojian Zhuang 	assert(id != NULL);
1462f2abcf4SHaojian Zhuang 
1472f2abcf4SHaojian Zhuang 	init_adc();
1482f2abcf4SHaojian Zhuang 
1492f2abcf4SHaojian Zhuang 	/* read ADC channel0 data */
1502f2abcf4SHaojian Zhuang 	get_value(ADC_ADCIN0, &adcin0);
1512f2abcf4SHaojian Zhuang 	adcin0_remap = adcin_data_remap(adcin0);
1522f2abcf4SHaojian Zhuang 	if (adcin0_remap == BOARDID_UNKNOWN)
1532f2abcf4SHaojian Zhuang 		return -EINVAL;
1542f2abcf4SHaojian Zhuang 	/* read ADC channel1 data */
1552f2abcf4SHaojian Zhuang 	get_value(ADC_ADCIN1, &adcin1);
1562f2abcf4SHaojian Zhuang 	adcin1_remap = adcin_data_remap(adcin1);
1572f2abcf4SHaojian Zhuang 	if (adcin1_remap == BOARDID_UNKNOWN)
1582f2abcf4SHaojian Zhuang 		return -EINVAL;
1592f2abcf4SHaojian Zhuang 	/* read ADC channel2 data */
1602f2abcf4SHaojian Zhuang 	get_value(ADC_ADCIN2, &adcin2);
1612f2abcf4SHaojian Zhuang 	adcin2_remap = adcin_data_remap(adcin2);
1622f2abcf4SHaojian Zhuang 	if (adcin2_remap == BOARDID_UNKNOWN)
1632f2abcf4SHaojian Zhuang 		return -EINVAL;
1642f2abcf4SHaojian Zhuang 	*id = BOARDID3_BASE * 1000 + (adcin2_remap * 100) +
1652f2abcf4SHaojian Zhuang 		(adcin1_remap * 10) + adcin0_remap;
1662f2abcf4SHaojian Zhuang 	return 0;
1672f2abcf4SHaojian Zhuang }
168