u-boot-2016/board/qca/arm/devsoc/devsoc.c
Vandhiadevan Karunamoorthy 270d1e7245 board: arm: devsoc: Add eMMC support
This changes add 4-Bit eMMC flash support

Change-Id: Iad789ba44aaa0e11da5f8c16dd0a07d2e80de682
Signed-off-by: Vandhiadevan Karunamoorthy <quic_vkarunam@quicinc.com>
2022-05-10 17:18:31 +05:30

297 lines
6 KiB
C

/*
* Copyright (c) 2016-2019, The Linux Foundation. All rights reserved.
*
* Copyright (c) 2022 Qualcomm Innovation Center, 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 version 2 and
* only version 2 as published by the Free Software Foundation.
*
* 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.
*/
#include <common.h>
#include <asm/global_data.h>
#include <asm/io.h>
#include <asm/errno.h>
#include <environment.h>
#include <fdtdec.h>
#include <asm/arch-qca-common/gpio.h>
#include <asm/arch-qca-common/uart.h>
#include <asm/arch-qca-common/scm.h>
#include <asm/arch-qca-common/iomap.h>
#include <devsoc.h>
#ifdef CONFIG_QPIC_NAND
#include <asm/arch-qca-common/qpic_nand.h>
#include <nand.h>
#endif
#ifdef CONFIG_QCA_MMC
#include <mmc.h>
#include <sdhci.h>
#endif
DECLARE_GLOBAL_DATA_PTR;
extern int ipq_spi_init(u16);
const char *rsvd_node = "/reserved-memory";
const char *del_node[] = {"uboot",
"sbl",
NULL};
const add_node_t add_fdt_node[] = {{}};
unsigned int qpic_frequency = 0, qpic_phase = 0;
#ifdef CONFIG_QPIC_SERIAL
extern unsigned int qpic_training_offset;
#endif
#ifdef CONFIG_QCA_MMC
struct sdhci_host mmc_host;
#endif
void qca_serial_init(struct ipq_serial_platdata *plat)
{
int ret;
if (plat->gpio_node >= 0) {
qca_gpio_init(plat->gpio_node);
}
plat->port_id = UART_PORT_ID(plat->reg_base);
ret = uart_clock_config(plat);
if (ret)
printf("UART clock config failed %d\n", ret);
return;
}
void reset_board(void)
{
run_command("reset", 0);
}
/*
* Set the uuid in bootargs variable for mounting rootfilesystem
*/
#ifdef CONFIG_QCA_MMC
int set_uuid_bootargs(char *boot_args, char *part_name, int buflen,
bool gpt_flag)
{
int ret, len;
block_dev_desc_t *blk_dev;
disk_partition_t disk_info;
blk_dev = mmc_get_dev(mmc_host.dev_num);
if (!blk_dev) {
printf("Invalid block device name\n");
return -EINVAL;
}
if (buflen <= 0 || buflen > MAX_BOOT_ARGS_SIZE)
return -EINVAL;
#ifdef CONFIG_PARTITION_UUIDS
ret = get_partition_info_efi_by_name(blk_dev,
part_name, &disk_info);
if (ret) {
printf("bootipq: unsupported partition name %s\n",part_name);
return -EINVAL;
}
if ((len = strlcpy(boot_args, "root=PARTUUID=", buflen)) >= buflen)
return -EINVAL;
#else
if ((len = strlcpy(boot_args, "rootfsname=", buflen)) >= buflen)
return -EINVAL;
#endif
boot_args += len;
buflen -= len;
#ifdef CONFIG_PARTITION_UUIDS
if ((len = strlcpy(boot_args, disk_info.uuid, buflen)) >= buflen)
return -EINVAL;
#else
if ((len = strlcpy(boot_args, part_name, buflen)) >= buflen)
return -EINVAL;
#endif
boot_args += len;
buflen -= len;
if (gpt_flag && strlcpy(boot_args, " gpt", buflen) >= buflen)
return -EINVAL;
return 0;
}
#else
int set_uuid_bootargs(char *boot_args, char *part_name, int buflen,
bool gpt_flag)
{
return 0;
}
#endif
#ifdef CONFIG_QCA_MMC
void mmc_iopad_config(struct sdhci_host *host)
{
u32 val;
val = sdhci_readb(host, SDHCI_VENDOR_IOPAD);
/*set bit 15 & 16*/
val |= 0x18000;
writel(val, host->ioaddr + SDHCI_VENDOR_IOPAD);
}
void sdhci_bus_pwr_off(struct sdhci_host *host)
{
u32 val;
val = sdhci_readb(host, SDHCI_HOST_CONTROL);
sdhci_writeb(host,(val & (~SDHCI_POWER_ON)), SDHCI_POWER_CONTROL);
}
__weak void board_mmc_deinit(void)
{
/*since we do not have misc register in devsoc
* so simply return from this function
*/
return;
}
int board_mmc_init(bd_t *bis)
{
int node, gpio_node;
int ret = 0;
qca_smem_flash_info_t *sfi = &qca_smem_flash_info;
node = fdt_path_offset(gd->fdt_blob, "mmc");
if (node < 0) {
printf("sdhci: Node Not found, skipping initialization\n");
return -1;
}
gpio_node = fdt_subnode_offset(gd->fdt_blob, node, "mmc_gpio");
if (node >= 0)
qca_gpio_init(gpio_node);
mmc_host.ioaddr = (void *)MSM_SDC1_SDHCI_BASE;
mmc_host.voltages = MMC_VDD_165_195;
mmc_host.version = SDHCI_SPEC_300;
mmc_host.cfg.part_type = PART_TYPE_EFI;
mmc_host.quirks = SDHCI_QUIRK_BROKEN_VOLTAGE;
emmc_clock_reset();
udelay(10);
emmc_clock_init();
if (add_sdhci(&mmc_host, 200000000, 400000)) {
printf("add_sdhci fail!\n");
return -1;
}
if (!ret && sfi->flash_type == SMEM_BOOT_MMC_FLASH) {
ret = board_mmc_env_init(mmc_host);
}
return ret;
}
#else
int board_mmc_init(bd_t *bis)
{
return 0;
}
#endif
__weak int ipq_get_tz_version(char *version_name, int buf_size)
{
return 1;
}
int apps_iscrashed(void)
{
return 0;
}
void reset_crashdump(void)
{
return;
}
void psci_sys_reset(void)
{
return;
}
void qti_scm_pshold(void)
{
return;
}
void reset_cpu(unsigned long a)
{
reset_crashdump();
if (is_scm_armv8()) {
psci_sys_reset();
} else {
qti_scm_pshold();
}
while(1);
}
void board_nand_init(void)
{
#ifdef CONFIG_QPIC_SERIAL
/* check for nand node in dts
* if nand node in dts is disabled then
* simply return from here without
* initializing
*/
int node;
node = fdt_path_offset(gd->fdt_blob, "/nand-controller");
if (!fdtdec_get_is_enabled(gd->fdt_blob, node)) {
printf("QPIC: disabled, skipping initialization\n");
} else {
qpic_nand_init(NULL);
}
#endif
#ifdef CONFIG_QCA_SPI
int gpio_node;
gpio_node = fdt_path_offset(gd->fdt_blob, "/spi/spi_gpio");
if (gpio_node >= 0) {
qca_gpio_init(gpio_node);
#ifdef CONFIG_MTD_DEVICE
ipq_spi_init(CONFIG_IPQ_SPI_NOR_INFO_IDX);
#endif
}
#endif
}
void enable_caches(void)
{
qca_smem_flash_info_t *sfi = &qca_smem_flash_info;
smem_get_boot_flash(&sfi->flash_type,
&sfi->flash_index,
&sfi->flash_chip_select,
&sfi->flash_block_size,
&sfi->flash_density);
icache_enable();
/*Skips dcache_enable during JTAG recovery */
if (sfi->flash_type)
dcache_enable();
}
void disable_caches(void)
{
icache_disable();
dcache_disable();
}
unsigned long timer_read_counter(void)
{
return 0;
}
void set_flash_secondary_type(qca_smem_flash_info_t *smem)
{
return;
};