/*
 * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
 *
 * SPDX-License-Identifier: BSD-3-Clause
 */

#include <assert.h>
#include <debug.h>
#include <delay_timer.h>
#include <errno.h>
#include <hi3660.h>
#include <mmio.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_GRADE0)
		ret = BOARDID_UNKNOWN;
	else 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);
	INFO("[BDID]adcin0:%d adcin0_remap:%d\n", adcin0, adcin0_remap);
	if (adcin0_remap == BOARDID_UNKNOWN)
		return -EINVAL;
	/* read ADC channel1 data */
	get_value(ADC_ADCIN1, &adcin1);
	adcin1_remap = adcin_data_remap(adcin1);
	INFO("[BDID]adcin1:%d adcin1_remap:%d\n", adcin1, adcin1_remap);
	if (adcin1_remap == BOARDID_UNKNOWN)
		return -EINVAL;
	/* read ADC channel2 data */
	get_value(ADC_ADCIN2, &adcin2);
	adcin2_remap = adcin_data_remap(adcin2);
	INFO("[BDID]adcin2:%d adcin2_remap:%d\n", adcin2, adcin2_remap);
	if (adcin2_remap == BOARDID_UNKNOWN)
		return -EINVAL;
	*id = BOARDID3_BASE * 1000 + (adcin2_remap * 100) +
		(adcin1_remap * 10) + adcin0_remap;
	INFO("[BDID]boardid: %d\n", *id);
	return 0;
}
