aboutsummaryrefslogtreecommitdiff
path: root/plat/hisilicon/hikey960/hikey960_boardid.c
blob: 1e1126fb1a903bf1c2225c6a4a3963416c88cfda (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
/*
 * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
 *
 * SPDX-License-Identifier: BSD-3-Clause
 */

#include <assert.h>
#include <errno.h>

#include <common/debug.h>
#include <drivers/delay_timer.h>
#include <lib/mmio.h>

#include <hi3660.h>
#include "hikey960_private.h"

#define ADC_ADCIN0				0
#define ADC_ADCIN1				1
#define ADC_ADCIN2				2

#define HKADC_DATA_GRADE0			0
#define HKADC_DATA_GRADE1			100
#define HKADC_DATA_GRADE2			300
#define HKADC_DATA_GRADE3			500
#define HKADC_DATA_GRADE4			700
#define HKADC_DATA_GRADE5			900
#define HKADC_DATA_GRADE6			1100
#define HKADC_DATA_GRADE7			1300
#define HKADC_DATA_GRADE8			1500
#define HKADC_DATA_GRADE9			1700
#define HKADC_DATA_GRADE10			1800

#define BOARDID_VALUE0				0
#define BOARDID_VALUE1				1
#define BOARDID_VALUE2				2
#define BOARDID_VALUE3				3
#define BOARDID_VALUE4				4
#define BOARDID_VALUE5				5
#define BOARDID_VALUE6				6
#define BOARDID_VALUE7				7
#define BOARDID_VALUE8				8
#define BOARDID_VALUE9				9
#define BOARDID_UNKNOWN				0xF

#define BOARDID3_BASE				5


static void init_adc(void)
{
	/* reset hkadc */
	mmio_write_32(CRG_PERRSTEN2_REG, PERRSTEN2_HKADCSSI);
	/* wait a few clock cycles */
	udelay(2);
	mmio_write_32(CRG_PERRSTDIS2_REG, PERRSTEN2_HKADCSSI);
	udelay(2);
	/* enable hkadc clock */
	mmio_write_32(CRG_PERDIS2_REG, PEREN2_HKADCSSI);
	udelay(2);
	mmio_write_32(CRG_PEREN2_REG, PEREN2_HKADCSSI);
	udelay(2);
}

static int get_adc(unsigned int channel, unsigned int *value)
{
	unsigned int	data, value1, value0;

	if (channel > HKADC_CHANNEL_MAX) {
		WARN("invalid channel:%d\n", channel);
		return -EFAULT;
	}
	/* configure the read/write operation for external HKADC */
	mmio_write_32(HKADC_WR01_DATA_REG, HKADC_WR01_VALUE | channel);
	mmio_write_32(HKADC_WR23_DATA_REG, HKADC_WR23_VALUE);
	mmio_write_32(HKADC_WR45_DATA_REG, HKADC_WR45_VALUE);
	/* configure the number of accessing registers */
	mmio_write_32(HKADC_WR_NUM_REG, HKADC_WR_NUM_VALUE);
	/* configure delay of accessing registers */
	mmio_write_32(HKADC_DELAY01_REG, HKADC_CHANNEL0_DELAY01_VALUE);
	mmio_write_32(HKADC_DELAY23_REG, HKADC_DELAY23_VALUE);

	/* start HKADC */
	mmio_write_32(HKADC_DSP_START_REG, 1);
	do {
		data = mmio_read_32(HKADC_DSP_START_REG);
	} while (data & 1);

	/* convert AD result */
	value1 = mmio_read_32(HKADC_DSP_RD2_DATA_REG) & 0xffff;
	value0 = mmio_read_32(HKADC_DSP_RD3_DATA_REG) & 0xffff;

	data = ((value1 << 4) & HKADC_VALUE_HIGH) |
	       ((value0 >> 4) & HKADC_VALUE_LOW);
	*value = data;
	return 0;
}

static int get_value(unsigned int channel, unsigned int *value)
{
	int ret;

	ret = get_adc(channel, value);
	if (ret)
		return ret;

	/* convert ADC value to micro-volt */
	ret = ((*value & HKADC_VALID_VALUE) * HKADC_VREF_1V8) / HKADC_ACCURACY;
	*value = ret;
	return 0;
}

static int adcin_data_remap(unsigned int adcin_value)
{
	int	ret;

	if (adcin_value < HKADC_DATA_GRADE1)
		ret = BOARDID_VALUE0;
	else if (adcin_value < HKADC_DATA_GRADE2)
		ret = BOARDID_VALUE1;
	else if (adcin_value < HKADC_DATA_GRADE3)
		ret = BOARDID_VALUE2;
	else if (adcin_value < HKADC_DATA_GRADE4)
		ret = BOARDID_VALUE3;
	else if (adcin_value < HKADC_DATA_GRADE5)
		ret = BOARDID_VALUE4;
	else if (adcin_value < HKADC_DATA_GRADE6)
		ret = BOARDID_VALUE5;
	else if (adcin_value < HKADC_DATA_GRADE7)
		ret = BOARDID_VALUE6;
	else if (adcin_value < HKADC_DATA_GRADE8)
		ret = BOARDID_VALUE7;
	else if (adcin_value < HKADC_DATA_GRADE9)
		ret = BOARDID_VALUE8;
	else if (adcin_value < HKADC_DATA_GRADE10)
		ret = BOARDID_VALUE9;
	else
		ret = BOARDID_UNKNOWN;
	return ret;
}

int hikey960_read_boardid(unsigned int *id)
{
	unsigned int	adcin0, adcin1, adcin2;
	unsigned int	adcin0_remap, adcin1_remap, adcin2_remap;

	assert(id != NULL);

	init_adc();

	/* read ADC channel0 data */
	get_value(ADC_ADCIN0, &adcin0);
	adcin0_remap = adcin_data_remap(adcin0);
	if (adcin0_remap == BOARDID_UNKNOWN)
		return -EINVAL;
	/* read ADC channel1 data */
	get_value(ADC_ADCIN1, &adcin1);
	adcin1_remap = adcin_data_remap(adcin1);
	if (adcin1_remap == BOARDID_UNKNOWN)
		return -EINVAL;
	/* read ADC channel2 data */
	get_value(ADC_ADCIN2, &adcin2);
	adcin2_remap = adcin_data_remap(adcin2);
	if (adcin2_remap == BOARDID_UNKNOWN)
		return -EINVAL;
	*id = BOARDID3_BASE * 1000 + (adcin2_remap * 100) +
		(adcin1_remap * 10) + adcin0_remap;
	return 0;
}