blob: 61bd3ee3e16f8c14c11070e23e8264626d274aa7 [file] [log] [blame]
/*
* Copyright (c) 2015-2017 The Linux Foundation. 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/io.h>
#include <asm/errno.h>
#include <environment.h>
#include <configs/ipq40xx.h>
#include <nand.h>
#include <part.h>
#include <asm/arch-qca-common/smem.h>
#include <asm/arch-ipq40xx/clk.h>
#include <asm/arch-qca-common/scm.h>
#include <asm/arch-qca-common/qpic_nand.h>
#include <asm/arch-qca-common/gpio.h>
#include <asm/arch-qca-common/iomap.h>
#include <jffs2/load_kernel.h>
#include <fdtdec.h>
#include <asm/arch-qca-common/uart.h>
#include "fdt_info.h"
#include <asm/arch-ipq40xx/ess/ipq40xx_edma.h>
#include <phy.h>
#include "ipq40xx_edma_eth.h"
#include <asm/arch-qca-common/qca_common.h>
#include "ipq_phy.h"
#include <sdhci.h>
#define DLOAD_MAGIC_COOKIE 0x10
#define TCSR_USB_HSPHY_DEVICE_MODE 0x00C700E7
#define TCSR_SOC_HW_VERSION_REG 0x194D000
DECLARE_GLOBAL_DATA_PTR;
#define CPU0_APCS_SAW2_VCTL 0x0b089014
#define CPU0_APCS_CPU_PWR_CTL 0x0b088004
#define CPU_APCS_SAW2_VCTL(cpuid) (CPU0_APCS_SAW2_VCTL + (cpuid * 0x10000))
#define CPU_APCS_CPU_PWR_CTL(cpuid) (CPU0_APCS_CPU_PWR_CTL + (cpuid * 0x10000))
#ifndef CONFIG_SDHCI_SUPPORT
qca_mmc mmc_host;
#else
struct sdhci_host mmc_host;
#endif
#define ADSS_AUDIO_RXM_CBCR_REG 0x0770012C
#define ADSS_AUDIO_RXB_CBCR_REG 0x0770010C
#define ADSS_AUDIO_TXB_CBCR_REG 0x0770014C
#define ADSS_AUDIO_SPDIF_CBCR_REG 0x07700154
#define ADSS_AUDIO_SPDIF_DIV2_CBCR_REG 0x0770015C
#define ADSS_AUDIO_TXM_CBCR_REG 0x0770016C
#define ADSS_AUDIO_PCM_CBCR_REG 0x077001AC
#define ADSS_AUDIO_SPDIF_IN_FAST_CBCR_REG 0x077001EC
const char *rsvd_node = "/reserved-memory";
const char *del_node[] = {"rsvd1",
"rsvd2",
"wifi_dump",
NULL};
const add_node_t add_fdt_node[] = {
{
.nodename = "rsvd1",
.val[0] = htonl(RESERVE_ADDRESS_START),
.val[1] = htonl(RESERVE_ADDRESS_SIZE)
},
{
}
};
struct dumpinfo_t dumpinfo_n[] = {
{ "EBICS0.BIN", 0x80000000, 0x10000000, 0 },
{ "EBICS2.BIN", 0xA0000000, 0x10000000, 0, 0, 0, 0, 1 },
{ "EBICS1.BIN", CONFIG_UBOOT_END_ADDR, 0x10000000, 0, 0, 0, 0, 1 },
{ "EBICS0.BIN", 0x80000000, CONFIG_QCA_UBOOT_OFFSET, 0, 0, 0, 0, 1 },
};
int dump_entries_n = ARRAY_SIZE(dumpinfo_n);
struct dumpinfo_t dumpinfo_s[] = {
{ "EBICS_S0.BIN", CONFIG_QCA_KERNEL_CRASHDUMP_ADDRESS,
CONFIG_CPU_CONTEXT_DUMP_SIZE, 0 },
};
int dump_entries_s = ARRAY_SIZE(dumpinfo_s);
extern loff_t board_env_offset;
extern loff_t board_env_range;
extern loff_t board_env_size;
extern int ipq_spi_init(u16);
extern int mmc_env_init(void);
extern void mmc_env_relocate_spec(void);
extern int ipq40xx_edma_init(ipq40xx_edma_board_cfg_t *edma_cfg);
extern int ipq_qca8075_phy_init(struct phy_ops **ops);
extern int ipq40xx_qca8033_phy_init(struct ipq40xx_eth_dev *cfg);
extern void ipq40xx_register_switch(
int (*sw_init)(struct phy_ops **ops));
void qca_serial_init(struct ipq_serial_platdata *plat)
{
int node, uart2_node;
node = fdt_path_offset(gd->fdt_blob, "/serial/serial_gpio");
if (node < 0) {
printf("Could not find serial_gpio node\n");
return;
}
if (plat->port_id == 2) {
uart2_node = fdt_path_offset(gd->fdt_blob, "uart2");
if (uart2_node < 0) {
printf("Could not find uart2 node\n");
return;
}
node = fdt_subnode_offset(gd->fdt_blob,
uart2_node, "serial_gpio");
uart2_clock_config(plat->m_value, plat->n_value, plat->d_value);
writel(1, GCC_BLSP1_UART2_APPS_CBCR);
}
qca_gpio_init(node);
}
void reset_crashdump(void)
{
unsigned int magic_cookie = CLEAR_MAGIC;
unsigned int clear_info[] =
{ 1 /* Disable wdog debug */, 0 /* SDI enable*/, };
scm_call(SCM_SVC_BOOT, SCM_CMD_TZ_CONFIG_HW_FOR_RAM_DUMP_ID,
(const void *)&clear_info, sizeof(clear_info), NULL, 0);
scm_call(SCM_SVC_BOOT, SCM_CMD_TZ_FORCE_DLOAD_ID, &magic_cookie,
sizeof(magic_cookie), NULL, 0);
}
void reset_cpu(ulong addr)
{
/* Clear Debug sw entry register */
reset_crashdump();
/* clear ps-hold bit to reset the soc */
writel(0, GCNT_PSHOLD);
while (1);
}
void reset_board(void)
{
run_command("reset", 0);
}
void board_nand_init(void)
{
int gpio_node;
qpic_nand_init(NULL);
gpio_node = fdt_path_offset(gd->fdt_blob, "/spi/spi_gpio");
if (gpio_node >= 0) {
qca_gpio_init(gpio_node);
}
#ifdef CONFIG_SPI_NAND
if (fdtdec_get_uint(gd->fdt_blob, 0, "spi_nand_available", 0))
spi_nand_init();
#endif
if (fdtdec_get_uint(gd->fdt_blob, 0, "spi_nor_available", 0))
ipq_spi_init(CONFIG_IPQ_SPI_NOR_INFO_IDX);
}
static void ipq40xx_edma_common_init(void)
{
writel(1, GCC_ESS_BCR);
mdelay(10);
writel(0, GCC_ESS_BCR);
mdelay(100);
writel(1, GCC_MDIO_AHB_CBCR);
writel(MDIO_CTRL_0_DIV(0xff) |
MDIO_CTRL_0_MDC_MODE |
MDIO_CTRL_0_GPHY(0xa), MDIO_CTRL_0_REG);
}
int board_eth_init(bd_t *bis)
{
u32 status;
int gpio_node, node, len;
ipq40xx_edma_board_cfg_t* edma_cfg =
(ipq40xx_edma_board_cfg_t*)malloc(sizeof(ipq40xx_edma_board_cfg_t));
gpio_node = fdt_path_offset(gd->fdt_blob, "/ess-switch/sw_gpio");
if (gpio_node >= 0)
qca_gpio_init(gpio_node);
ipq40xx_edma_common_init();
switch (gd->bd->bi_arch_number) {
case MACH_TYPE_IPQ40XX_AP_DK01_1_S1:
case MACH_TYPE_IPQ40XX_AP_DK01_1_C2:
case MACH_TYPE_IPQ40XX_AP_DK05_1_C1:
/* 8075 out of reset */
mdelay(1);
gpio_set_value(62, 1);
ipq40xx_register_switch(ipq_qca8075_phy_init);
break;
case MACH_TYPE_IPQ40XX_AP_DK01_1_C1:
/* 8075 out of reset */
mdelay(1);
gpio_set_value(59, 1);
ipq40xx_register_switch(ipq_qca8075_phy_init);
break;
case MACH_TYPE_IPQ40XX_AP_DK04_1_C1:
case MACH_TYPE_IPQ40XX_AP_DK04_1_C3:
case MACH_TYPE_IPQ40XX_AP_DK04_1_C4:
case MACH_TYPE_IPQ40XX_AP_DK04_1_C6:
/* 8075 out of reset */
mdelay(1);
gpio_set_value(47, 1);
ipq40xx_register_switch(ipq_qca8075_phy_init);
break;
case MACH_TYPE_IPQ40XX_AP_DK04_1_C2:
/* 8075 out of reset */
mdelay(1);
gpio_set_value(67, 1);
ipq40xx_register_switch(ipq_qca8075_phy_init);
break;
case MACH_TYPE_IPQ40XX_AP_DK06_1_C1:
/* 8075 out of reset */
mdelay(1);
gpio_set_value(19, 1);
ipq40xx_register_switch(ipq_qca8075_phy_init);
break;
case MACH_TYPE_IPQ40XX_AP_DK07_1_C1:
case MACH_TYPE_IPQ40XX_AP_DK07_1_C2:
case MACH_TYPE_IPQ40XX_AP_DK07_1_C3:
case MACH_TYPE_IPQ40XX_AP_DK07_1_C4:
/* 8075 out of reset */
mdelay(1);
gpio_set_value(41, 1);
ipq40xx_register_switch(ipq_qca8075_phy_init);
break;
default:
break;
}
node = fdt_path_offset(gd->fdt_blob, "/edma_cfg");
if (node < 0) {
printf("Error: edma_cfg not specified in dts");
return -1;
}
edma_cfg->unit = fdtdec_get_uint(gd->fdt_blob, node, "unit", 0);
edma_cfg->phy = fdtdec_get_uint(gd->fdt_blob, node, "phy", 0);
strcpy((char *)edma_cfg->phy_name, fdt_getprop(gd->fdt_blob, node, "phy_name", &len));
status = ipq40xx_edma_init(edma_cfg);
return status;
}
#ifdef CONFIG_QCA_MMC
void emmc_clock_reset(void)
{
writel(0x1, GCC_SDCC1_BCR);
udelay(100);
writel(0x0, GCC_SDCC1_BCR);
}
void emmc_sdhci_init(void)
{
writel(readl(MSM_SDC1_MCI_HC_MODE) & (~0x1), MSM_SDC1_MCI_HC_MODE);
writel(readl(MSM_SDC1_BASE) | (1 << 7), MSM_SDC1_BASE); //SW_RST
udelay(10);
writel(readl(MSM_SDC1_MCI_HC_MODE) | (0x1), MSM_SDC1_MCI_HC_MODE);
}
int board_mmc_init(bd_t *bis)
{
int ret = 0;
int node, gpio_node;
fdt_addr_t base;
qca_smem_flash_info_t *sfi = &qca_smem_flash_info;
node = fdt_path_offset(gd->fdt_blob, "/sdhci");
if (!fdtdec_get_is_enabled(gd->fdt_blob, node)) {
printf("sdhci: disabled, skipping initialization\n");
return -1;
}
gpio_node = fdt_subnode_offset(gd->fdt_blob, node, "mmc_gpio");
qca_gpio_init(gpio_node);
base = fdtdec_get_addr(gd->fdt_blob, node, "reg");
if (base == FDT_ADDR_T_NONE) {
printf("No valid MMC base address found in device tree\n");
return -1;
}
#ifndef CONFIG_SDHCI_SUPPORT
mmc_host.base = base;
mmc_host.clk_mode = MMC_IDENTIFY_MODE;
emmc_clock_config(mmc_host.clk_mode);
ret = qca_mmc_init(bis, &mmc_host);
#else
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_disable();
emmc_clock_reset();
udelay(10);
emmc_clock_config(MMC_DATA_TRANSFER_SDHCI_MODE);
emmc_sdhci_init();
if (add_sdhci(&mmc_host, 200000000, 400000)) {
printf("add_sdhci fail!\n");
return -1;
}
#endif
if (!ret && sfi->flash_type == SMEM_BOOT_MMC_FLASH) {
ret = board_mmc_env_init(mmc_host);
}
return ret;
}
void board_mmc_deinit(void)
{
emmc_clock_reset();
udelay(10);
emmc_clock_disable();
}
#endif
static void pcie_clock_init(void)
{
/* Enable PCIE CLKS */
pcie_clock_enable(GCC_PCIE_SLEEP_CBCR);
pcie_clock_enable(GCC_PCIE_AXI_M_CBCR);
pcie_clock_enable(GCC_PCIE_AXI_S_CBCR);
pcie_clock_enable(GCC_PCIE_AHB_CBCR);
}
void board_pci_init(int id)
{
int node, gpio_node;
char name[16];
sprintf(name, "pci%d", id);
node = fdt_path_offset(gd->fdt_blob, name);
if (node < 0) {
printf("Could not find PCI in device tree\n");
return;
}
gpio_node = fdt_subnode_offset(gd->fdt_blob, node, "pci_gpio");
if (gpio_node >= 0)
qca_gpio_init(gpio_node);
pcie_clock_init();
}
void board_pci_deinit(void)
{
/* Disable PCIE CLKS */
pcie_clock_disable(GCC_PCIE_SLEEP_CBCR);
pcie_clock_disable(GCC_PCIE_AXI_M_CBCR);
pcie_clock_disable(GCC_PCIE_AXI_S_CBCR);
pcie_clock_disable(GCC_PCIE_AHB_CBCR);
}
/*
* The audio block is out of reset by default due to which the
* audio clock blocks are also turned on. When audio TLMM is
* enabled in kernel, the clocks will also be available at the
* pins which causes pop noise during kernel bootup.
* To avoid this, the clocks are turned off in u-boot.
*/
void disable_audio_clks(void)
{
writel(0, ADSS_AUDIO_RXM_CBCR_REG);
writel(0, ADSS_AUDIO_RXB_CBCR_REG);
writel(0, ADSS_AUDIO_TXB_CBCR_REG);
writel(0, ADSS_AUDIO_SPDIF_CBCR_REG);
writel(0, ADSS_AUDIO_SPDIF_DIV2_CBCR_REG);
writel(0, ADSS_AUDIO_TXM_CBCR_REG);
writel(0, ADSS_AUDIO_PCM_CBCR_REG);
writel(0, ADSS_AUDIO_SPDIF_IN_FAST_CBCR_REG);
}
void ipq_fdt_fixup_socinfo(void *blob)
{
int nodeoff, ret;
uint32_t cpu_type;
uint32_t soc_version, soc_version_major, soc_version_minor;
const char *model = "Qualcomm Technologies, Inc. IPQ4019/AP-DK04.1-C6";
nodeoff = fdt_path_offset(blob, "/");
if (nodeoff < 0) {
printf("ipq: fdt fixup cannot find root node\n");
return;
}
if (gd->bd->bi_arch_number == MACH_TYPE_IPQ40XX_AP_DK04_1_C6)
ret = fdt_setprop(blob, nodeoff, "model",
model, (strlen(model) + 1));
/* Add "cpu_type" to root node of the devicetree*/
ret = ipq_smem_get_socinfo_cpu_type(&cpu_type);
if (!ret) {
ret = fdt_setprop(blob, nodeoff, "cpu_type",
&cpu_type, sizeof(cpu_type));
if (ret)
printf("%s: cannot set cpu type %d\n", __func__, ret);
} else {
printf("ipq: fdt fixup cannot get socinfo\n");
}
ret = ipq_smem_get_socinfo_version((uint32_t *)&soc_version);
if (!ret) {
soc_version_major = SOCINFO_VERSION_MAJOR(soc_version);
soc_version_minor = SOCINFO_VERSION_MINOR(soc_version);
ret = fdt_setprop(blob, nodeoff, "soc_version_major",
&soc_version_major,
sizeof(soc_version_major));
if (ret)
printf("%s: cannot set soc_version_major %d\n",
__func__, soc_version_major);
ret = fdt_setprop(blob, nodeoff, "soc_version_minor",
&soc_version_minor,
sizeof(soc_version_minor));
if (ret)
printf("%s: cannot set soc_version_minor %d\n",
__func__, soc_version_minor);
} else {
printf("%s: cannot get soc version\n", __func__);
}
}
void fdt_fixup_sd_ldo_gpios_toggle(void *blob)
{
int noff;
int ret;
if (mmc_host.mmc != NULL) {
if (mmc_host.mmc->has_init == 0)
return;
else {
if(IS_SD(mmc_host.mmc))
return;
}
}
else
return;
noff = fdt_path_offset(blob, "/soc/sdhci");
if (noff < 0) {
printf("ipq: fdt fixup unable to find node /soc/sdhci\n");
return;
}
/**
* In eMMC card, power-on write protection also gets cleared
* during sd-ldo toggle in kernel.
*/
ret = fdt_delprop(blob, noff, "sd-ldo-gpios");
if (ret < 0) {
printf("sdhci: cann't delete sd-ldo-gpios\n");
return;
}
}
void ipq_fdt_fixup_usb_device_mode(void *blob)
{
int nodeoff, ret, i;
int phy_mode = htonl(TCSR_USB_HSPHY_DEVICE_MODE);
const char *mode = "peripheral";
const char *node[] = {"/soc/ssphy", "/soc/hsphy", "/soc/usb3"};
char *usb_cfg;
usb_cfg = getenv("usb_mode");
if (!usb_cfg)
return;
if (strcmp(usb_cfg, "device"))
return;
nodeoff = fdt_path_offset(blob, "/soc/tcsr");
if (nodeoff < 0) {
printf("ipq: fdt fixup unable to find node /soc/tcsr\n");
return;
}
ret = fdt_setprop(blob, nodeoff, "ipq,usb-hsphy-mode-select",
&phy_mode, sizeof(phy_mode));
if (ret != 0) {
printf("ipq: unable to set prop: %d\n", ret);
return;
}
phy_mode = 0;
for (i = 0; i < (sizeof(node) / sizeof(node[0])); i++) {
nodeoff = fdt_path_offset(blob, node[i]);
if (nodeoff < 0) {
printf("ipq: fdt fixup unable to find node %s\n",
node[i]);
continue;
}
ret = fdt_setprop(blob, nodeoff, "qca,host",
&phy_mode, sizeof(phy_mode));
if (ret != 0) {
printf("ipq: unable to set prop: %d\n", ret);
continue;
}
}
nodeoff = fdt_path_offset(blob, "/soc/usb3/dwc3");
if (nodeoff < 0) {
printf("ipq: fdt fixup unable to find node /soc/usb3/dwc3\n");
return;
}
ret = fdt_setprop(blob, nodeoff, "dr_mode",
mode, (strlen(mode) + 1));
if (ret != 0) {
printf("ipq: unable to set prop: %d\n", ret);
return;
}
return;
}
void fdt_fixup_auto_restart(void *blob)
{
return;
}
void set_flash_secondary_type(qca_smem_flash_info_t * smem)
{
return;
}
int apps_iscrashed(void)
{
u32 *dmagic = (u32 *)0x193D100;
if (*dmagic == DLOAD_MAGIC_COOKIE)
return 1;
return 0;
}
unsigned int get_smem_spi_addr_len(void)
{
return SPI_DEFAULT_ADDR_LEN;
}
void enable_caches(void)
{
icache_enable();
dcache_enable();
}
void disable_caches(void)
{
icache_disable();
dcache_disable();
}
unsigned int get_dts_machid(unsigned int machid)
{
switch (machid)
{
case MACH_TYPE_IPQ40XX_AP_DK04_1_C6:
return MACH_TYPE_IPQ40XX_AP_DK04_1_C1;
case MACH_TYPE_IPQ40XX_AP_DK05_1_C1:
return MACH_TYPE_IPQ40XX_AP_DK01_1_C2;
default:
return machid;
}
}
/**
* Set the uuid in bootargs variable for mounting rootfilesystem
*/
int set_uuid_bootargs(char *boot_args, char *part_name, int buflen, bool gpt_flag)
{
return 0;
}
extern void dk_secondary_cpu_init(void);
extern void dk_secondary_cpu_reinit(void);
/*
* Set the cold/warm boot address for one of the CPU cores.
*/
int scm_set_boot_addr(bool enable_sec_core)
{
int ret;
struct {
unsigned int flags;
unsigned long addr;
} cmd;
if (!enable_sec_core)
return -1;
cmd.addr = (unsigned long)dk_secondary_cpu_init;
cmd.flags = 0xff;
ret = scm_call(SCM_SVC_BOOT, SCM_BOOT_ADDR,
&cmd, sizeof(cmd), NULL, 0);
if (ret) {
printf("--- %s: scm_call failed ret = %d\n", __func__, ret);
}
return ret;
}
int is_secondary_core_off(unsigned int cpuid)
{
return 1;
}
static int secondary_core_already_reset[NR_CPUS];
static int scm_boot_addr_already_set;
extern int get_cpu_id(void);
static volatile int core_var;
void bring_secondary_core_down(unsigned int state)
{
int current_cpu_id;
current_cpu_id = (1 << get_cpu_id());
core_var &= (~current_cpu_id);
while (!(core_var & current_cpu_id)) {
cp_delay();
}
dk_secondary_cpu_reinit();
}
static int kpssv1_release_secondary(unsigned int cpuid)
{
dcache_enable();
writel(0xa4, CPU_APCS_SAW2_VCTL(cpuid));
barrier();
udelay(512);
writel(0x109, CPU_APCS_CPU_PWR_CTL(cpuid));
writel(0x101, CPU_APCS_CPU_PWR_CTL(cpuid));
barrier();
udelay(1);
writel(0x121, CPU_APCS_CPU_PWR_CTL(cpuid));
barrier();
udelay(2);
writel(0x120, CPU_APCS_CPU_PWR_CTL(cpuid));
barrier();
udelay(2);
writel(0x100, CPU_APCS_CPU_PWR_CTL(cpuid));
barrier();
udelay(100);
writel(0x180, CPU_APCS_CPU_PWR_CTL(cpuid));
barrier();
dcache_disable();
return 0;
}
int bring_sec_core_up(unsigned int cpuid, unsigned int entry, unsigned int arg)
{
int err = 0;
if (!secondary_core_already_reset[cpuid]) {
if (!scm_boot_addr_already_set) {
err = scm_set_boot_addr(true);
core_var = 0;
if (!err) {
scm_boot_addr_already_set = 1;
kpssv1_release_secondary(cpuid);
secondary_core_already_reset[cpuid] = 1;
} else
return err;
} else {
kpssv1_release_secondary(cpuid);
secondary_core_already_reset[cpuid] = 1;
}
} else {
core_var |= (1 << cpuid);
}
return 0;
}
int smem_read_cpu_count()
{
uint32_t core_no;
if (!smem_read_alloc_entry(SMEM_NUM_CPUINFO, &core_no,
sizeof(uint32_t))) {
if (core_no != 4)
return core_no;
}
return -1;
}
void fdt_fixup_cpus_node(void *blob)
{
int numcpus;
int nodeoff;
numcpus = smem_read_cpu_count();
if (numcpus == 2)
{
nodeoff = fdt_path_offset(blob, "/cpus/cpu@2");
if (nodeoff >= 0)
fdt_del_node((void *)blob, nodeoff);
else
printf("fixup_cpus_node: can't disable cpu2\n");
nodeoff = fdt_path_offset(blob, "/cpus/cpu@3");
if (nodeoff >= 0)
fdt_del_node((void *)blob, nodeoff);
else
printf("fixup_cpus_node: can't disable cpu3\n");
}
else if (numcpus == 1)
{
nodeoff = fdt_path_offset(blob, "/cpus/cpu@1");
if (nodeoff >= 0)
fdt_del_node((void *)blob, nodeoff);
else
printf("fixup_cpus_node: can't disable cpu1\n");
nodeoff = fdt_path_offset(blob, "/cpus/cpu@2");
if (nodeoff >= 0)
fdt_del_node((void *)blob, nodeoff);
else
printf("fixup_cpus_node: can't disable cpu2\n");
nodeoff = fdt_path_offset(blob, "/cpus/cpu@3");
if (nodeoff >= 0)
fdt_del_node((void *)blob, nodeoff);
else
printf("fixup_cpus_node: can't disable cpu3\n");
}
return;
}
void ipq_uboot_fdt_fixup(void)
{
int ret, len;
const char *config = "config@ap.dk05.1-c1";
len = fdt_totalsize(gd->fdt_blob) + strlen(config) + 1;
if (gd->bd->bi_arch_number == MACH_TYPE_IPQ40XX_AP_DK05_1_C1)
{
/*
* Open in place with a new length.
*/
ret = fdt_open_into(gd->fdt_blob, (void *)gd->fdt_blob, len);
if (ret)
debug("uboot-fdt-fixup: Cannot expand FDT: %s\n", fdt_strerror(ret));
ret = fdt_setprop((void *)gd->fdt_blob, 0, "config_name",
config, (strlen(config)+1));
if (ret)
debug("uboot-fdt-fixup: unable to set config_name(%d)\n", ret);
}
return;
}
int get_soc_hw_version(void)
{
return readl(TCSR_SOC_HW_VERSION_REG);
}