Signed-off-by: Leo Yan leo.yan@linaro.org --- plat/hikey/drivers/hisi_adc.c | 218 ++++++++++++++++++++++++++++++++++++++++ plat/hikey/include/hisi_hkadc.h | 152 ++++++++++++++++++++++++++++ 2 files changed, 370 insertions(+) create mode 100644 plat/hikey/drivers/hisi_adc.c create mode 100644 plat/hikey/include/hisi_hkadc.h
diff --git a/plat/hikey/drivers/hisi_adc.c b/plat/hikey/drivers/hisi_adc.c new file mode 100644 index 0000000..1d9527a --- /dev/null +++ b/plat/hikey/drivers/hisi_adc.c @@ -0,0 +1,218 @@ +/* + * Copyright (c) 2014-2015, Linaro Ltd and Contributors. All rights reserved. + * Copyright (c) 2014-2015, Hisilicon Ltd and Contributors. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of ARM nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include <arch_helpers.h> +#include <assert.h> +#include <bl_common.h> +#include <console.h> +#include <debug.h> +#include <hi6220.h> +#include <mmio.h> +#include <partitions.h> +#include <platform.h> +#include <platform_def.h> +#include <sp804_timer.h> +#include <string.h> + +void init_hkadc(void) +{ + /* reset hkadc */ + mmio_write_32(PERI_SC_PERIPH_RSTEN3, PERI_RST3_HKADC); + udelay(2); + mmio_write_32(PERI_SC_PERIPH_RSTDIS3, PERI_RST3_HKADC); + udelay(2); + + /* enable clock */ + mmio_write_32(PERI_SC_PERIPH_CLKDIS3, PERI_CLK3_HKADC); + udelay(2); + mmio_write_32(PERI_SC_PERIPH_CLKEN3, PERI_CLK3_HKADC); + udelay(2); + + return; +} + +int hkadc_bbp_convert(unsigned char enchan, int *pusvalue) +{ + unsigned int val = 0x00; + unsigned int count = 0x0; + unsigned short ret = 0; + unsigned short rd_data0 = 0; + unsigned short rd_data1 = 0; + + /* set channel, rate and eanble pmu hkadc */ + val = HKADC_WR01_VALUE | enchan; + + /* config operation */ + mmio_write_32(HKADC_WR01_DATA, val); + mmio_write_32(HKADC_WR23_DATA, HKADC_WR23_VALUE); + mmio_write_32(HKADC_WR45_DATA, HKADC_WR45_VALUE); + + /* set operation number*/ + mmio_write_32(HKADC_WR_NUM, HKADC_WR_NUM_VALUE); + + /* set delay for operations */ + mmio_write_32(HKADC_DELAY01, HKADC_DELAY01_VALUE); + mmio_write_32(HKADC_DELAY23, HKADC_DELAY23_VALUE); + + /* enable hkadc */ + mmio_write_32(HKADC_DSP_START, 0x1); + + /* check if the enable bit has been cleared */ + do { + if (count > HKADC_START_TIMEOUT) { + /* disable hkadc and return error */ + mmio_write_32(HKADC_DSP_START, 0x0); + ERROR("%s: HKADC start failed! (%d)\n", __func__); + return -1; + } + + val = mmio_read_32(HKADC_DSP_START); + count++; + } while(val & 0x1); + + /* read back adc result */ + rd_data0 = mmio_read_32(HKADC_DSP_RD2_DATA); + rd_data1 = mmio_read_32(HKADC_DSP_RD3_DATA); + + /* combine result */ + ret = (((rd_data1 << 4) & HKADC_VALUE_HIGH) | + ((rd_data0 >> 4) & HKADC_VALUE_LOW)); + + *pusvalue = (ret & HKADC_VALID_VALUE) * HKADC_VREF_1V8; + *pusvalue = *pusvalue >> 12; + + INFO("[BDID] bbp convert: data=%d, count=%d, value=%d\n", + ret, count, *pusvalue ); + return 0; +} + +/* + * Convert adcin raw data (12-bit) to remapping data (4-bit). + */ +int hkadc_adcin_data_remap(int adcin_value) +{ + unsigned int ret = BOARDID_UNKNOW; + + if (adcin_value < 0) + ret = BOARDID_UNKNOW; + else if (adcin_value <= BOUNDARY_VALUE0) + ret = BOARDID_VALUE0; + else if (adcin_value <= BOUNDARY_VALUE1) + ret = BOARDID_VALUE1; + else if (adcin_value <= BOUNDARY_VALUE2) + ret = BOARDID_VALUE2; + else if (adcin_value <= BOUNDARY_VALUE3) + ret = BOARDID_VALUE3; + else if (adcin_value <= BOUNDARY_VALUE4) + ret = BOARDID_VALUE4; + else if (adcin_value <= BOUNDARY_VALUE5) + ret = BOARDID_VALUE5; + else if (adcin_value <= BOUNDARY_VALUE6) + ret = BOARDID_VALUE6; + else if (adcin_value <= BOUNDARY_VALUE7) + ret = BOARDID_VALUE7; + else if (adcin_value <= BOUNDARY_VALUE8) + ret = BOARDID_VALUE8; + else if (adcin_value <= BOUNDARY_VALUE9) + ret = BOARDID_VALUE9; + else + ret = BOARDID_UNKNOW; + + return ret; +} + +int hkadc_read_board_id(unsigned int *data) +{ + int adcin0, adcin1, adcin2; + int ret; + + /* read adc channel data */ + ret = hkadc_bbp_convert(HKADC_CHAN_BOARDID0, &adcin0); + if (ret == -1) { + ERROR("[BDID] failed read board id chan=%d, adc=%d\n", + HKADC_CHAN_BOARDID0, adcin0); + return ret; + } + INFO("[BDID] adcin0_V:%d\n", adcin0); + + adcin0 = hkadc_adcin_data_remap(adcin0); + INFO("[BDID] adcin0_remap:0x%x\n", adcin0); + + ret = hkadc_bbp_convert(HKADC_CHAN_BOARDID1, &adcin1); + if (ret == -1) { + ERROR("[BDID] failed read board id chan=%d, adc=%d\n", + HKADC_CHAN_BOARDID1, adcin1); + return ret; + } + INFO("[BDID] adcin1_V:%d\n", adcin1); + + adcin1 = hkadc_adcin_data_remap(adcin1); + INFO("[BDID] adcin1_remap:0x%x\n", adcin1); + + ret = hkadc_bbp_convert(HKADC_CHAN_BOARDID2, &adcin2); + if (ret == -1) { + ERROR("[BDID] failed read board id chan=%d, adc=%d\n", + HKADC_CHAN_BOARDID2, adcin2); + return ret; + } + INFO("[BDID] adcin2_V:%d\n", adcin2); + + adcin2 = hkadc_adcin_data_remap(adcin2); + INFO("[BDID] adcin2_remap:0x%x\n", adcin2); + + /* Composed to adcin data to decimal boardid */ + *data = adcin2 * 100 + adcin1 * 10 + adcin0; + INFO("[BDID] boardid: %d %d %d %d\n", *data, adcin2, adcin1, adcin0); + + return 0; +} + +void init_boardid(void) +{ + unsigned int actual_boardid; + unsigned int reg; + + hkadc_read_board_id(&actual_boardid); + + /* Set chip id to sram */ + reg = read_midr_el1(); + mmio_write_32(MEMORY_AXI_CHIP_ADDR, reg); + INFO("[BDID] [%x] midr: 0x%x\n", MEMORY_AXI_CHIP_ADDR, reg); + + /* Set board type to sram */ + mmio_write_32(MEMORY_AXI_BOARD_TYPE_ADDR, 0x0); + INFO("[BDID] [%x] board type: 0\n", MEMORY_AXI_BOARD_TYPE_ADDR); + + /* Set board id to sram */ + mmio_write_32(MEMORY_AXI_BOARD_ID_ADDR, 0x2b); + INFO("[BDID] [%x] board id: 0x2b\n", MEMORY_AXI_BOARD_ID_ADDR); + return; +} diff --git a/plat/hikey/include/hisi_hkadc.h b/plat/hikey/include/hisi_hkadc.h new file mode 100644 index 0000000..e0189d3 --- /dev/null +++ b/plat/hikey/include/hisi_hkadc.h @@ -0,0 +1,152 @@ +/* + * Copyright (c) 2014-2015, Linaro Ltd and Contributors. All rights reserved. + * Copyright (c) 2014-2015, Hisilicon Ltd and Contributors. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of ARM nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __HISI_HKADC_H__ +#define __HISI_HKADC_H__ + +/* hkadc channel */ +#define HKADC_CHAN_UNUSE0 (0x00) +#define HKADC_CHAN_BOARDID1 (0x01) +#define HKADC_CHAN_BOARDID2 (0x02) +#define HKADC_CHAN_BOARDID0 (0x04) +#define HKADC_CHAN_VCOINMON (0x06) +#define HKADC_CHAN_RTMP (0x0A) +#define HKADC_CHAN_VBATMON (0x0B) + +/* hkadc registers */ +#define HKADC_BASE (0xF7013000) + +#define HKADC_DSP_START (HKADC_BASE + 0x0000) +#define HKADC_DSP_CFG (HKADC_BASE + 0x0004) +#define HKADC_WR_NUM (HKADC_BASE + 0x0008) +#define HKADC_DSP_WAIT_TIME (HKADC_BASE + 0x000C) +#define HKADC_TIMEOUT_ERR_CLR (HKADC_BASE + 0x0010) +#define HKADC_TIMEOUT_ERR (HKADC_BASE + 0x0018) +#define HKADC_DSP_START_CLR (HKADC_BASE + 0x001C) +#define HKADC_WR01_DATA (HKADC_BASE + 0x0020) +#define HKADC_WR23_DATA (HKADC_BASE + 0x0024) +#define HKADC_WR45_DATA (HKADC_BASE + 0x0028) +#define HKADC_WR67_DATA (HKADC_BASE + 0x002C) +#define HKADC_DELAY01 (HKADC_BASE + 0x0030) +#define HKADC_DELAY23 (HKADC_BASE + 0x0034) +#define HKADC_DELAY45 (HKADC_BASE + 0x0038) +#define HKADC_DELAY6 (HKADC_BASE + 0x003C) +#define HKADC_DSP_RD0_DATA (HKADC_BASE + 0x0040) +#define HKADC_DSP_RD1_DATA (HKADC_BASE + 0x0044) +#define HKADC_DSP_RD2_DATA (HKADC_BASE + 0x0048) +#define HKADC_DSP_RD3_DATA (HKADC_BASE + 0x004C) +#define HKADC_DSP_RD4_DATA (HKADC_BASE + 0x0050) +#define HKADC_DSP_RD5_DATA (HKADC_BASE + 0x0054) +#define HKADC_DSP_RD6_DATA (HKADC_BASE + 0x0058) +#define HKADC_DSP_RD7_DATA (HKADC_BASE + 0x005C) +#define HKADC_OP_INTERVAL (HKADC_BASE + 0x0060) +#define HKADC_OP_INTERVAL_BYPASS (HKADC_BASE + 0x0064) +#define HKADC_CHANNEL_EN (HKADC_BASE + 0x0068) +#define HKADC_DBG_INFO (HKADC_BASE + 0x00D0) +#define HKADC_FINSH_RAW_INT (HKADC_BASE + 0x0100) +#define HKADC_FINSH_MSK_INT (HKADC_BASE + 0x0104) +#define HKADC_FINSH_INT_CLR (HKADC_BASE + 0x0108) +#define HKADC_FINSH_INT_MSK (HKADC_BASE + 0x010C) + +#define PMU_HKADC_CFG_ADDR (0x00) +#define PMU_HKADC_START_ADDR (0x01) +#define PMU_HKADC_STATUS_ADDR (0x02) +#define PMU_HKADC_RDHIGH_ADDR (0x03) +#define PMU_HKADC_RDLOW_ADDR (0x04) + +#define HKADC_WR01_VALUE \ + ((0x0 << 31) | \ + (PMU_HKADC_START_ADDR << 24) | \ + (0x1 << 16) | \ + (0x0 << 15) | \ + (PMU_HKADC_CFG_ADDR << 8) | \ + (0x3 << 5)) + +#define HKADC_WR23_VALUE \ + ((0x1 << 31) | \ + (PMU_HKADC_RDHIGH_ADDR << 24) | \ + (0x1 << 15) | \ + (PMU_HKADC_RDLOW_ADDR << 8)) + +#define HKADC_WR45_VALUE \ + ((0x0 << 15) | \ + (PMU_HKADC_CFG_ADDR << 8) | \ + (0x80 << 0)) + +#define HKADC_WR_NUM_VALUE (5) +#define HKADC_DELAY01_VALUE ((0x0700 << 16) | (0x0200 << 0)) +#define HKADC_DELAY23_VALUE ((0x00c8 << 16) | (0x00c8 << 0)) +#define HKADC_START_TIMEOUT (2000) + +#define HKADC_VALUE_HIGH (0x0FF0) +#define HKADC_VALUE_LOW (0x000F) +#define HKADC_VALID_VALUE (0x0FFF) +#define HKADC_VREF_1V8 1800 + +#define HKADC_DATA_VOLT_GRADE0 (0) +#define HKADC_DATA_VOLT_GRADE1 (100) +#define HKADC_DATA_VOLT_GRADE2 (300) +#define HKADC_DATA_VOLT_GRADE3 (500) +#define HKADC_DATA_VOLT_GRADE4 (700) +#define HKADC_DATA_VOLT_GRADE5 (900) +#define HKADC_DATA_VOLT_GRADE6 (1100) +#define HKADC_DATA_VOLT_GRADE7 (1300) +#define HKADC_DATA_VOLT_GRADE8 (1500) +#define HKADC_DATA_VOLT_GRADE9 (1700) +#define HKADC_DATA_VOLT_GRADE10 (1800) + +#define BOUNDARY_VALUE0 HKADC_DATA_VOLT_GRADE1 +#define BOUNDARY_VALUE1 HKADC_DATA_VOLT_GRADE2 +#define BOUNDARY_VALUE2 HKADC_DATA_VOLT_GRADE3 +#define BOUNDARY_VALUE3 HKADC_DATA_VOLT_GRADE4 +#define BOUNDARY_VALUE4 HKADC_DATA_VOLT_GRADE5 +#define BOUNDARY_VALUE5 HKADC_DATA_VOLT_GRADE6 +#define BOUNDARY_VALUE6 HKADC_DATA_VOLT_GRADE7 +#define BOUNDARY_VALUE7 HKADC_DATA_VOLT_GRADE8 +#define BOUNDARY_VALUE8 HKADC_DATA_VOLT_GRADE9 +#define BOUNDARY_VALUE9 HKADC_DATA_VOLT_GRADE10 + +#define BOARDID_VALUE0 (0x0) +#define BOARDID_VALUE1 (0x1) +#define BOARDID_VALUE2 (0x2) +#define BOARDID_VALUE3 (0x3) +#define BOARDID_VALUE4 (0x4) +#define BOARDID_VALUE5 (0x5) +#define BOARDID_VALUE6 (0x6) +#define BOARDID_VALUE7 (0x7) +#define BOARDID_VALUE8 (0x8) +#define BOARDID_VALUE9 (0x9) +#define BOARDID_UNKNOW (0xF) + +extern void init_hkadc(void); +extern void init_boardid(void); + +#endif /* __HISI_HKADC_H__ */