
/*
 * arch/arm/cpu/armv8/txl/sdio.c
 *
 * Copyright (C) 2015 Amlogic, Inc. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 * more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
*/

#include <config.h>
#include <asm/arch/io.h>
#include <asm/arch/cpu_sdio.h>
#include <asm/arch/secure_apb.h>
#include <asm/arch/cpu_id.h>
#include <common.h>

void  cpu_sd_emmc_pwr_prepare(unsigned port)
{
//    switch(port)
//    {
//        case SDIO_PORT_A:
//            clrbits_le32(P_PREG_PAD_GPIO4_EN_N,0x30f);
//            clrbits_le32(P_PREG_PAD_GPIO4_O   ,0x30f);
//            clrbits_le32(P_PERIPHS_PIN_MUX_8,0x3f);
//            break;
//        case SDIO_PORT_B:
//            clrbits_le32(P_PREG_PAD_GPIO5_EN_N,0x3f<<23);
//            clrbits_le32(P_PREG_PAD_GPIO5_O   ,0x3f<<23);
//            clrbits_le32(P_PERIPHS_PIN_MUX_2,0x3f<<10);
//            break;
//        case SDIO_PORT_C:
//            //clrbits_le32(P_PREG_PAD_GPIO3_EN_N,0xc0f);
//            //clrbits_le32(P_PREG_PAD_GPIO3_O   ,0xc0f);
//            //clrbits_le32(P_PERIPHS_PIN_MUX_6,(0x3f<<24));break;
//            break;
//    }

    /**
        do nothing here
    */
}
unsigned sd_debug_board_1bit_flag = 0;
int cpu_sd_emmc_init(unsigned port)
{
	cpu_id_t cpuid = get_cpu_id();

	switch (port)
	{
	case SDIO_PORT_A:
		clrsetbits_le32(P_PERIPHS_PIN_MUX_3,
						0xFFFFFF, 0x111111);
		break;
	case SDIO_PORT_B:
		if (cpuid.chip_rev == 0xA)
			clrsetbits_le32(P_PAD_DS_REG1A, 0xFFFF, 0x5555);
		else if (cpuid.chip_rev == 0xB) {
			clrsetbits_le32(P_PAD_DS_REG1A, 0xFFFF, 0x5555);
			//setbits_le32(P_PAD_DS_REG1A, 0xFFFF);
			/* pullup & pullupen */
			setbits_le32(P_PAD_PULL_UP_EN_REG1, 0x7F);
			setbits_le32(P_PAD_PULL_UP_REG1, 0x7F);
			clrbits_le32(P_PREG_PAD_GPIO5_O, 1<<17);
		}

		if (sd_debug_board_1bit_flag == 1)
			clrsetbits_le32(P_PERIPHS_PIN_MUX_9,
						((0xFF << 16) | 0xF), ((0x11 << 16) | 0x1));
		else
			clrsetbits_le32(P_PERIPHS_PIN_MUX_9,
						0xFFFFFF, 0x111111);
		break;
	case SDIO_PORT_C:
		/* set driver strength */
		if (cpuid.chip_rev == 0xA)
			writel(0x55555555, P_PAD_DS_REG0A);
		else if (cpuid.chip_rev == 0xB)
			writel(0xFFFFFFFF, P_PAD_DS_REG0A);
		/* pull up data by default */
		setbits_le32(P_PAD_PULL_UP_EN_REG0, 0x35ff);
		setbits_le32(P_PAD_PULL_UP_REG0, 0x35ff);
		/* set pinmux */
		writel(0x11111111, P_PERIPHS_PIN_MUX_0);
		clrsetbits_le32(P_PERIPHS_PIN_MUX_1,
						((0xFF << 16) | (0xF << 8) | 0xF),
						((0x1 << 20) | (0x1 << 8) | 0x1));
		/* hardware reset with pull boot12 */
		clrbits_le32(P_PREG_PAD_GPIO0_EN_N, 1<<12);
		clrbits_le32(P_PREG_PAD_GPIO0_O, 1<<12);
		udelay(10);
		setbits_le32(P_PREG_PAD_GPIO0_O, 1<<12);
		break;
	default:
		return -1;
	}
	return 0;
}

/* return:
	0: insert
	1: not insert
 */
__weak int  sd_emmc_detect(unsigned port)
{
	int ret = 0;
	unsigned pinmux_9;

    switch (port) {

	case SDIO_PORT_A:
		break;
	case SDIO_PORT_B:
		pinmux_9 = readl(P_PERIPHS_PIN_MUX_9);
		clrbits_le32(P_PERIPHS_PIN_MUX_9, 0xF << 24);
		setbits_le32(P_PREG_PAD_GPIO1_EN_N, 1 << 6);
		setbits_le32(P_PAD_PULL_UP_EN_REG1, 1 << 6);
		setbits_le32(P_PAD_PULL_UP_REG1, 1 << 6);

		ret = readl(P_PREG_PAD_GPIO1_I) & (1 << 6);
		printf("%s\n", ret ? "card out" : "card in");
		if (!ret) {
			clrbits_le32(P_PERIPHS_PIN_MUX_9, 0xF << 12);
			setbits_le32(P_PREG_PAD_GPIO1_EN_N, 1 << 3);
			setbits_le32(P_PAD_PULL_UP_EN_REG1, 1 << 3);
			setbits_le32(P_PAD_PULL_UP_REG1, 1 << 3);
			/* debug board in when D3 is low */
			if (!(readl(P_PREG_PAD_GPIO1_I) & (1 << 3))) {
				/* switch uart to GPIOC(Card) */
				clrbits_le32(P_AO_RTI_PINMUX_REG0, 0xFF);
				clrsetbits_le32(P_PERIPHS_PIN_MUX_9, 0xFF << 8, 0x22 << 8);
				clrsetbits_le32(P_PERIPHS_PIN_MUX_9,
						((0xFF << 16) | 0xF), ((0x11 << 16) | 0x1));
				printf("sdio debug board detected\n");
				sd_debug_board_1bit_flag = 1;
			} else {
				//4bit card
				writel(pinmux_9, P_PERIPHS_PIN_MUX_9);
				sd_debug_board_1bit_flag = 0;
			}

		}
		break;
	default:
		break;
	}
	return ret;
}


