blob: 90faa9d3055fa3e9157b2ee965fc400c59502540 [file] [log] [blame]
Haojian Zhuang602362d2017-06-01 12:15:14 +08001/*
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
47static 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
62static 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
96static 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
110static int adcin_data_remap(unsigned int adcin_value)
111{
112 int ret;
113
Haojian Zhuangb7ee0922017-06-12 22:20:38 +0800114 if (adcin_value < HKADC_DATA_GRADE1)
Haojian Zhuang602362d2017-06-01 12:15:14 +0800115 ret = BOARDID_VALUE0;
116 else if (adcin_value < HKADC_DATA_GRADE2)
117 ret = BOARDID_VALUE1;
118 else if (adcin_value < HKADC_DATA_GRADE3)
119 ret = BOARDID_VALUE2;
120 else if (adcin_value < HKADC_DATA_GRADE4)
121 ret = BOARDID_VALUE3;
122 else if (adcin_value < HKADC_DATA_GRADE5)
123 ret = BOARDID_VALUE4;
124 else if (adcin_value < HKADC_DATA_GRADE6)
125 ret = BOARDID_VALUE5;
126 else if (adcin_value < HKADC_DATA_GRADE7)
127 ret = BOARDID_VALUE6;
128 else if (adcin_value < HKADC_DATA_GRADE8)
129 ret = BOARDID_VALUE7;
130 else if (adcin_value < HKADC_DATA_GRADE9)
131 ret = BOARDID_VALUE8;
132 else if (adcin_value < HKADC_DATA_GRADE10)
133 ret = BOARDID_VALUE9;
134 else
135 ret = BOARDID_UNKNOWN;
136 return ret;
137}
138
139int hikey960_read_boardid(unsigned int *id)
140{
141 unsigned int adcin0, adcin1, adcin2;
142 unsigned int adcin0_remap, adcin1_remap, adcin2_remap;
143
144 assert(id != NULL);
145
146 init_adc();
147
148 /* read ADC channel0 data */
149 get_value(ADC_ADCIN0, &adcin0);
150 adcin0_remap = adcin_data_remap(adcin0);
151 INFO("[BDID]adcin0:%d adcin0_remap:%d\n", adcin0, adcin0_remap);
152 if (adcin0_remap == BOARDID_UNKNOWN)
153 return -EINVAL;
154 /* read ADC channel1 data */
155 get_value(ADC_ADCIN1, &adcin1);
156 adcin1_remap = adcin_data_remap(adcin1);
157 INFO("[BDID]adcin1:%d adcin1_remap:%d\n", adcin1, adcin1_remap);
158 if (adcin1_remap == BOARDID_UNKNOWN)
159 return -EINVAL;
160 /* read ADC channel2 data */
161 get_value(ADC_ADCIN2, &adcin2);
162 adcin2_remap = adcin_data_remap(adcin2);
163 INFO("[BDID]adcin2:%d adcin2_remap:%d\n", adcin2, adcin2_remap);
164 if (adcin2_remap == BOARDID_UNKNOWN)
165 return -EINVAL;
166 *id = BOARDID3_BASE * 1000 + (adcin2_remap * 100) +
167 (adcin1_remap * 10) + adcin0_remap;
168 INFO("[BDID]boardid: %d\n", *id);
169 return 0;
170}