// SPDX-License-Identifier: GPL-2.0+
/*
 * Copyright (C) 2018 Stefan Roese <sr@denx.de>
 *
 * This code is mostly based on the code extracted from this MediaTek
 * github repository:
 *
 * https://github.com/MediaTek-Labs/linkit-smart-uboot.git
 *
 * I was not able to find a specific license or other developers
 * copyrights here, so I can't add them here.
 *
 * Most functions in this file are copied from the MediaTek U-Boot
 * repository. Without any documentation, it was impossible to really
 * implement this differently. So its mostly a cleaned-up version of
 * the original code, with only support for the MT7628 / MT7688 SoC.
 */

#include <common.h>
#include <cpu_func.h>
#include <linux/io.h>
#include <asm/cacheops.h>
#include <asm/io.h>
#include "mt76xx.h"

#define NUM_OF_CACHELINE	128
#define MIN_START		6
#define MIN_FINE_START		0xf
#define MAX_START		7
#define MAX_FINE_START		0x0

#define CPU_FRAC_DIV		1

#if defined(CONFIG_ONBOARD_DDR2_SIZE_256MBIT)
#define DRAM_BUTTOM 0x02000000
#endif
#if defined(CONFIG_ONBOARD_DDR2_SIZE_512MBIT)
#define DRAM_BUTTOM 0x04000000
#endif
#if defined(CONFIG_ONBOARD_DDR2_SIZE_1024MBIT)
#define DRAM_BUTTOM 0x08000000
#endif
#if defined(CONFIG_ONBOARD_DDR2_SIZE_2048MBIT)
#define DRAM_BUTTOM 0x10000000
#endif

static inline void cal_memcpy(void *src, void *dst, u32 size)
{
	u8 *psrc = (u8 *)src;
	u8 *pdst = (u8 *)dst;
	int i;

	for (i = 0; i < size; i++, psrc++, pdst++)
		*pdst = *psrc;
}

static inline void cal_memset(void *src, u8 pat, u32 size)
{
	u8 *psrc = (u8 *)src;
	int i;

	for (i = 0; i < size; i++, psrc++)
		*psrc = pat;
}

#define pref_op(hint, addr)						\
	__asm__ __volatile__(						\
		".set	push\n"						\
		".set	noreorder\n"					\
		"pref	%0, %1\n"					\
		".set	pop\n"						\
		:							\
		: "i" (hint), "R" (*(u8 *)(addr)))

static inline void cal_patgen(u32 start_addr, u32 size, u32 bias)
{
	u32 *addr = (u32 *)start_addr;
	int i;

	for (i = 0; i < size; i++)
		addr[i] = start_addr + i + bias;
}

static inline int test_loop(int k, int dqs, u32 test_dqs, u32 *coarse_dqs,
			    u32 offs, u32 pat, u32 val)
{
	u32 nc_addr;
	u32 *c_addr;
	int i;

	for (nc_addr = 0xa0000000;
	     nc_addr < (0xa0000000 + DRAM_BUTTOM - NUM_OF_CACHELINE * 32);
	     nc_addr += (DRAM_BUTTOM >> 6) + offs) {
		writel(0x00007474, (void *)MT76XX_MEMCTRL_BASE + 0x64);
		wmb();		/* Make sure store if finished */

		c_addr = (u32 *)(nc_addr & 0xdfffffff);
		cal_memset(((u8 *)c_addr), 0x1F, NUM_OF_CACHELINE * 32);
		cal_patgen(nc_addr, NUM_OF_CACHELINE * 8, pat);

		if (dqs > 0)
			writel(0x00000074 |
			       (((k == 1) ? coarse_dqs[dqs] : test_dqs) << 12) |
			       (((k == 0) ? val : test_dqs) << 8),
			       (void *)MT76XX_MEMCTRL_BASE + 0x64);
		else
			writel(0x00007400 |
			       (((k == 1) ? coarse_dqs[dqs] : test_dqs) << 4) |
			       (((k == 0) ? val : test_dqs) << 0),
			       (void *)MT76XX_MEMCTRL_BASE + 0x64);
		wmb();		/* Make sure store if finished */

		invalidate_dcache_range((u32)c_addr,
					(u32)c_addr +
					NUM_OF_CACHELINE * 32);
		wmb();		/* Make sure store if finished */

		for (i = 0; i < NUM_OF_CACHELINE * 8; i++) {
			if (i % 8 == 0)
				pref_op(0, &c_addr[i]);
		}

		for (i = 0; i < NUM_OF_CACHELINE * 8; i++) {
			if (c_addr[i] != nc_addr + i + pat)
				return -1;
		}
	}

	return 0;
}

void ddr_calibrate(void)
{
	u32 min_coarse_dqs[2];
	u32 max_coarse_dqs[2];
	u32 min_fine_dqs[2];
	u32 max_fine_dqs[2];
	u32 coarse_dqs[2];
	u32 fine_dqs[2];
	int reg = 0, ddr_cfg2_reg;
	int flag;
	int i, k;
	int dqs = 0;
	u32 min_coarse_dqs_bnd, min_fine_dqs_bnd, coarse_dqs_dll, fine_dqs_dll;
	u32 val;
	u32 fdiv = 0, frac = 0;

	/* Setup clock to run at full speed */
	val = readl((void *)MT76XX_DYN_CFG0_REG);
	fdiv = (u32)((val >> 8) & 0x0F);
	if (CPU_FRAC_DIV < 1 || CPU_FRAC_DIV > 10)
		frac = val & 0x0f;
	else
		frac = CPU_FRAC_DIV;

	while (frac < fdiv) {
		val = readl((void *)MT76XX_DYN_CFG0_REG);
		fdiv = (val >> 8) & 0x0f;
		fdiv--;
		val &= ~(0x0f << 8);
		val |= (fdiv << 8);
		writel(val, (void *)MT76XX_DYN_CFG0_REG);
		udelay(500);
		val = readl((void *)MT76XX_DYN_CFG0_REG);
		fdiv = (val >> 8) & 0x0f;
	}

	clrbits_le32((void *)MT76XX_MEMCTRL_BASE + 0x10, BIT(4));
	ddr_cfg2_reg = readl((void *)MT76XX_MEMCTRL_BASE + 0x48);
	clrbits_le32((void *)MT76XX_MEMCTRL_BASE + 0x48,
		     (0x3 << 28) | (0x3 << 26));

	min_coarse_dqs[0] = MIN_START;
	min_coarse_dqs[1] = MIN_START;
	min_fine_dqs[0] = MIN_FINE_START;
	min_fine_dqs[1] = MIN_FINE_START;
	max_coarse_dqs[0] = MAX_START;
	max_coarse_dqs[1] = MAX_START;
	max_fine_dqs[0] = MAX_FINE_START;
	max_fine_dqs[1] = MAX_FINE_START;
	dqs = 0;

	/* Add by KP, DQS MIN boundary */
	reg = readl((void *)MT76XX_MEMCTRL_BASE + 0x20);
	coarse_dqs_dll = (reg & 0xf00) >> 8;
	fine_dqs_dll = (reg & 0xf0) >> 4;
	if (coarse_dqs_dll <= 8)
		min_coarse_dqs_bnd = 8 - coarse_dqs_dll;
	else
		min_coarse_dqs_bnd = 0;

	if (fine_dqs_dll <= 8)
		min_fine_dqs_bnd = 8 - fine_dqs_dll;
	else
		min_fine_dqs_bnd = 0;
	/* DQS MIN boundary */

DQS_CAL:

	for (k = 0; k < 2; k++) {
		u32 test_dqs;

		if (k == 0)
			test_dqs = MAX_START;
		else
			test_dqs = MAX_FINE_START;

		do {
			flag = test_loop(k, dqs, test_dqs, max_coarse_dqs,
					 0x400, 0x3, 0xf);
			if (flag == -1)
				break;

			test_dqs++;
		} while (test_dqs <= 0xf);

		if (k == 0) {
			max_coarse_dqs[dqs] = test_dqs;
		} else {
			test_dqs--;

			if (test_dqs == MAX_FINE_START - 1) {
				max_coarse_dqs[dqs]--;
				max_fine_dqs[dqs] = 0xf;
			} else {
				max_fine_dqs[dqs] = test_dqs;
			}
		}
	}

	for (k = 0; k < 2; k++) {
		u32 test_dqs;

		if (k == 0)
			test_dqs = MIN_START;
		else
			test_dqs = MIN_FINE_START;

		do {
			flag = test_loop(k, dqs, test_dqs, min_coarse_dqs,
					 0x480, 0x1, 0x0);
			if (k == 0) {
				if (flag == -1 ||
				    test_dqs == min_coarse_dqs_bnd)
					break;

				test_dqs--;

				if (test_dqs < min_coarse_dqs_bnd)
					break;
			} else {
				if (flag == -1) {
					test_dqs++;
					break;
				} else if (test_dqs == min_fine_dqs_bnd) {
					break;
				}

				test_dqs--;

				if (test_dqs < min_fine_dqs_bnd)
					break;
			}
		} while (test_dqs >= 0);

		if (k == 0) {
			min_coarse_dqs[dqs] = test_dqs;
		} else {
			if (test_dqs == MIN_FINE_START + 1) {
				min_coarse_dqs[dqs]++;
				min_fine_dqs[dqs] = 0x0;
			} else {
				min_fine_dqs[dqs] = test_dqs;
			}
		}
	}

	if (dqs == 0) {
		dqs = 1;
		goto DQS_CAL;
	}

	for (i = 0; i < 2; i++) {
		u32 temp;

		coarse_dqs[i] = (max_coarse_dqs[i] + min_coarse_dqs[i]) >> 1;
		temp =
		    (((max_coarse_dqs[i] + min_coarse_dqs[i]) % 2) * 4) +
		    ((max_fine_dqs[i] + min_fine_dqs[i]) >> 1);
		if (temp >= 0x10) {
			coarse_dqs[i]++;
			fine_dqs[i] = (temp - 0x10) + 0x8;
		} else {
			fine_dqs[i] = temp;
		}
	}
	reg = (coarse_dqs[1] << 12) | (fine_dqs[1] << 8) |
		(coarse_dqs[0] << 4) | fine_dqs[0];

	clrbits_le32((void *)MT76XX_MEMCTRL_BASE + 0x10, BIT(4));
	writel(reg, (void *)MT76XX_MEMCTRL_BASE + 0x64);
	writel(ddr_cfg2_reg, (void *)MT76XX_MEMCTRL_BASE + 0x48);
	setbits_le32((void *)MT76XX_MEMCTRL_BASE + 0x10, BIT(4));

	for (i = 0; i < 2; i++)
		debug("[%02X%02X%02X%02X]", min_coarse_dqs[i],
		      min_fine_dqs[i], max_coarse_dqs[i], max_fine_dqs[i]);
	debug("\nDDR Calibration DQS reg = %08X\n", reg);
}
