blob: dfe61f98278a7e9965e02633a1f99fc65d59764f [file] [log] [blame]
/*
* Copyright (c) 2016-2018, 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/global_data.h>
#include <asm/io.h>
#include <asm/errno.h>
#include <environment.h>
#include <asm/arch-qca-common/qpic_nand.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 <ipq6018.h>
#include <mmc.h>
#include <sdhci.h>
#include <usb.h>
#include <i2c.h>
#include <dm.h>
#include <command.h>
#define DLOAD_MAGIC_COOKIE 0x10
#define DLOAD_DISABLED 0x40
#define TCSR_SOC_HW_VERSION_REG 0x194D000
DECLARE_GLOBAL_DATA_PTR;
struct sdhci_host mmc_host;
extern int ipq6018_edma_init(void *cfg);
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[] = {{}};
static int aq_phy_initialised;
struct dumpinfo_t dumpinfo_n[] = {
/* TZ stores the DDR physical address at which it stores the
* APSS regs, UTCM copy dump. We will have the TZ IMEM
* IMEM Addr at which the DDR physical address is stored as
* the start
* --------------------
* | DDR phy (start) | ----> ------------------------
* -------------------- | APSS regsave (8k) |
* ------------------------
* | |
* | UTCM copy |
* | (192k) |
* | |
* ------------------------
*/
/* Compressed EBICS dump follows descending order
* to use in-memory compression for which destination
* for compression will be address of EBICS2.BIN
*
* EBICS2 - (ddr size / 2) [to] end of ddr
* EBICS1 - uboot end addr [to] (ddr size / 2)
* EBICS0 - ddr start [to] uboot start addr
*/
{ "EBICS0.BIN", 0x40000000, 0x10000000, 0 },
{ "EBICS2.BIN", 0x60000000, 0x20000000, 0, 0, 0, 0, 1 },
{ "EBICS1.BIN", CONFIG_UBOOT_END_ADDR, 0x10000000, 0, 0, 0, 0, 1 },
{ "EBICS0.BIN", 0x40000000, CONFIG_QCA_UBOOT_OFFSET, 0, 0, 0, 0, 1 },
{ "CODERAM.BIN", 0x00200000, 0x00028000, 0 },
{ "DATARAM.BIN", 0x00290000, 0x00014000, 0 },
{ "MSGRAM.BIN", 0x00060000, 0x00006000, 1 },
{ "IMEM.BIN", 0x08600000, 0x00001000, 0 },
{ "NSSUTCM.BIN", 0x08600658, 0x00030000, 0, 1, 0x2000 },
{ "UNAME.BIN", 0, 0, 0, 0, 0, MINIMAL_DUMP },
{ "CPU_INFO.BIN", 0, 0, 0, 0, 0, MINIMAL_DUMP },
{ "DMESG.BIN", 0, 0, 0, 0, 0, MINIMAL_DUMP },
{ "PT.BIN", 0, 0, 0, 0, 0, MINIMAL_DUMP },
{ "WLAN_MOD.BIN", 0, 0, 0, 0, 0, MINIMAL_DUMP },
};
int dump_entries_n = ARRAY_SIZE(dumpinfo_n);
/* Compressed dumps:
* EBICS_S2 - (ddr start + 256M) [to] end of ddr
* EBICS_S1 - uboot end addr [to] (ddr start + 256M)
* EBICS_S0 - ddr start [to] uboot start addr
*/
struct dumpinfo_t dumpinfo_s[] = {
{ "EBICS_S0.BIN", 0x40000000, 0xA600000, 0 },
{ "EBICS_S1.BIN", CONFIG_TZ_END_ADDR, 0x10000000, 0 },
{ "EBICS_S2.BIN", 0x50000000, 0x10000000, 0, 0, 0, 0, 1 },
{ "EBICS_S1.BIN", CONFIG_UBOOT_END_ADDR, 0x5B00000, 0, 0, 0, 0, 1 },
{ "EBICS_S0.BIN", 0x40000000, CONFIG_QCA_UBOOT_OFFSET, 0, 0, 0, 0, 1 },
{ "DATARAM.BIN", 0x00290000, 0x00014000, 0 },
{ "MSGRAM.BIN", 0x00060000, 0x00006000, 1 },
{ "IMEM.BIN", 0x08600000, 0x00001000, 0 },
{ "NSSUTCM.BIN", 0x08600658, 0x00030000, 0, 1, 0x2000 },
{ "UNAME.BIN", 0, 0, 0, 0, 0, MINIMAL_DUMP },
{ "CPU_INFO.BIN", 0, 0, 0, 0, 0, MINIMAL_DUMP },
{ "DMESG.BIN", 0, 0, 0, 0, 0, MINIMAL_DUMP },
{ "PT.BIN", 0, 0, 0, 0, 0, MINIMAL_DUMP },
{ "WLAN_MOD.BIN", 0, 0, 0, 0, 0, MINIMAL_DUMP },
};
int dump_entries_s = ARRAY_SIZE(dumpinfo_s);
u32 *tz_wonce = (u32 *)CONFIG_IPQ6018_TZ_WONCE_4_ADDR;
#define BLSP1_UART0_BASE 0x078AF000
#define UART_PORT_ID(reg) ((reg - BLSP1_UART0_BASE) / 0x1000)
void qca_serial_init(struct ipq_serial_platdata *plat)
{
int ret;
if (plat->gpio_node < 0) {
printf("serial_init: unable to find gpio node \n");
return;
}
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;
}
int do_pmic_reset()
{
struct udevice *bus, *dev;
int bus_no = 1;
int ret;
uchar byte = CONFIG_IPQ6018_PMIC_RESET_VAL;
ret = uclass_get_device_by_seq(UCLASS_I2C, bus_no, &bus);
if (ret) {
debug("%s: No bus %d\n", __func__, bus_no);
return -1;
}
ret = dm_i2c_probe(bus, CONFIG_IPQ6018_PMIC_CHIP_ADDR, 0, &dev);
if (ret) {
printf("Probe failed\n");
return -1;
}
ret = i2c_get_chip(bus, CONFIG_IPQ6018_PMIC_CHIP_ADDR, 1, &dev);
if (ret) {
printf("Error 'i2c_get_chip': %d\n",ret);
return CMD_RET_FAILURE;
}
ret = dm_i2c_write(dev, CONFIG_IPQ6018_PMIC_OFFSET, &byte, 1);
if (ret) {
printf("Error writing the chip: %d\n", ret);
return CMD_RET_FAILURE;
}
return 0;
}
void reset_crashdump(void)
{
unsigned int ret = 0;
qca_scm_sdi();
ret = qca_scm_dload(CLEAR_MAGIC);
if (ret)
printf ("Error in reseting the Magic cookie\n");
return;
}
#ifdef CONFIG_QCA_MMC
void emmc_clock_config(void)
{
int cfg;
/* Configure sdcc1_apps_clk_src */
cfg = (GCC_SDCC1_APPS_CFG_RCGR_SRC_SEL
| GCC_SDCC1_APPS_CFG_RCGR_SRC_DIV);
writel(cfg, GCC_SDCC1_APPS_CFG_RCGR);
writel(SDCC1_M_VAL, GCC_SDCC1_APPS_M);
writel(SDCC1_N_VAL, GCC_SDCC1_APPS_N);
writel(SDCC1_D_VAL, GCC_SDCC1_APPS_D);
writel(CMD_UPDATE, GCC_SDCC1_APPS_CMD_RCGR);
mdelay(100);
writel(ROOT_EN, GCC_SDCC1_APPS_CMD_RCGR);
/* Configure CBCRs */
writel(readl(GCC_SDCC1_APPS_CBCR) | CLK_ENABLE, GCC_SDCC1_APPS_CBCR);
udelay(10);
writel(readl(GCC_SDCC1_AHB_CBCR) | CLK_ENABLE, GCC_SDCC1_AHB_CBCR);
}
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);
}
void emmc_clock_disable(void)
{
/* Clear divider */
writel(0x0, GCC_SDCC1_MISC);
}
void board_mmc_deinit(void)
{
emmc_clock_disable();
}
void emmc_clock_reset(void)
{
writel(0x1, GCC_SDCC1_BCR);
udelay(10);
writel(0x0, GCC_SDCC1_BCR);
}
int board_mmc_init(bd_t *bis)
{
int 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;
}
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();
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
#ifdef CONFIG_QCA_SPI
static void spi_clock_init(void)
{
int cfg;
/* Configure qup1_spi_apps_clk_src */
cfg = (GCC_BLSP1_QUP1_SPI_APPS_CFG_RCGR_SRC_SEL |
GCC_BLSP1_QUP1_SPI_APPS_CFG_RCGR_SRC_DIV);
writel(cfg, GCC_BLSP1_QUP1_SPI_APPS_CFG_RCGR);
writel(CMD_UPDATE, GCC_BLSP1_QUP1_SPI_APPS_CMD_RCGR);
mdelay(100);
writel(ROOT_EN, GCC_BLSP1_QUP1_SPI_APPS_CMD_RCGR);
/* Configure CBCR */
writel(CLK_ENABLE, GCC_BLSP1_QUP1_SPI_APPS_CBCR);
}
#endif
void board_nand_init(void)
{
#ifdef CONFIG_QCA_SPI
int gpio_node;
#endif
qpic_nand_init(NULL);
#ifdef CONFIG_QCA_SPI
spi_clock_init();
gpio_node = fdt_path_offset(gd->fdt_blob, "/spi/spi_gpio");
if (gpio_node >= 0) {
qca_gpio_init(gpio_node);
ipq_spi_init(CONFIG_IPQ_SPI_NOR_INFO_IDX);
}
#ifdef CONFIG_SPI_NAND
if (fdtdec_get_uint(gd->fdt_blob, 0, "spi_nand_available", 0))
spi_nand_init();
#endif
#endif
}
#ifdef CONFIG_PCI_IPQ
static void pcie_v2_clock_init(void)
{
int cfg;
/* Configure pcie0_aux_clk_src */
cfg = (GCC_PCIE0_AUX_CFG_RCGR_SRC_SEL | GCC_PCIE0_AUX_CFG_RCGR_SRC_DIV);
writel(cfg, GCC_PCIE0_AUX_CFG_RCGR);
writel(CMD_UPDATE, GCC_PCIE0_AUX_CMD_RCGR);
mdelay(100);
writel(ROOT_EN, GCC_PCIE0_AUX_CMD_RCGR);
/* Configure pcie0_axi_clk_src */
cfg = (GCC_PCIE0_AXI_CFG_RCGR_SRC_SEL | GCC_PCIE0_AXI_CFG_RCGR_SRC_DIV);
writel(cfg, GCC_PCIE0_AXI_CFG_RCGR);
writel(CMD_UPDATE, GCC_PCIE0_AXI_CMD_RCGR);
mdelay(100);
writel(ROOT_EN, GCC_PCIE0_AXI_CMD_RCGR);
/* Configure CBCRs */
writel(CLK_ENABLE, GCC_SYS_NOC_PCIE0_AXI_CBCR);
writel(CLK_ENABLE, GCC_PCIE0_AHB_CBCR);
writel(CLK_ENABLE, GCC_PCIE0_AXI_M_CBCR);
writel(CLK_ENABLE, GCC_PCIE0_AXI_S_CBCR);
writel(CLK_ENABLE, GCC_PCIE0_AUX_CBCR);
writel(PIPE_CLK_ENABLE, GCC_PCIE0_PIPE_CBCR);
writel(CLK_ENABLE, GCC_PCIE0_AXI_S_BRIDGE_CBCR);
/* Configure pcie0_rchng_clk_src */
cfg = (GCC_PCIE0_RCHNG_CFG_RCGR_SRC_SEL
| GCC_PCIE0_RCHNG_CFG_RCGR_SRC_DIV);
writel(cfg, GCC_PCIE0_RCHNG_CFG_RCGR);
writel(CMD_UPDATE, GCC_PCIE0_RCHNG_CMD_RCGR);
mdelay(100);
writel(ROOT_EN, GCC_PCIE0_RCHNG_CMD_RCGR);
}
static void pcie_v2_clock_deinit(void)
{
writel(0x0, GCC_PCIE0_AUX_CMD_RCGR);
writel(0x0, GCC_PCIE0_AXI_CFG_RCGR);
writel(0x0, GCC_PCIE0_AXI_CMD_RCGR);
mdelay(100);
writel(0x0, GCC_SYS_NOC_PCIE0_AXI_CBCR);
writel(0x0, GCC_PCIE0_AHB_CBCR);
writel(0x0, GCC_PCIE0_AXI_M_CBCR);
writel(0x0, GCC_PCIE0_AXI_S_CBCR);
writel(0x0, GCC_PCIE0_AUX_CBCR);
writel(0x0, GCC_PCIE0_PIPE_CBCR);
writel(0x0, GCC_PCIE0_AXI_S_BRIDGE_CBCR);
writel(0x0, GCC_PCIE0_RCHNG_CFG_RCGR);
writel(0x0, GCC_PCIE0_RCHNG_CMD_RCGR);
}
void board_pci_init(int id)
{
int node, gpio_node;
char name[16];
snprintf(name, sizeof(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_v2_clock_init();
return;
}
void board_pci_deinit()
{
int node, gpio_node, i, err;
char name[16];
struct fdt_resource parf;
struct fdt_resource pci_phy;
for (i = 0; i < PCI_MAX_DEVICES; i++) {
snprintf(name, sizeof(name), "pci%d", i);
node = fdt_path_offset(gd->fdt_blob, name);
if (node < 0) {
printf("Could not find PCI in device tree\n");
return;
}
err = fdt_get_named_resource(gd->fdt_blob, node, "reg", "reg-names", "parf",
&parf);
writel(0x0, parf.start + 0x358);
writel(0x1, parf.start + 0x40);
err = fdt_get_named_resource(gd->fdt_blob, node, "reg", "reg-names", "pci_phy",
&pci_phy);
if (err < 0)
return;
writel(0x1, pci_phy.start + 800);
writel(0x0, pci_phy.start + 804);
gpio_node = fdt_subnode_offset(gd->fdt_blob, node, "pci_gpio");
if (gpio_node >= 0)
qca_gpio_deinit(gpio_node);
}
pcie_v2_clock_deinit();
return ;
}
#endif
void set_flash_secondary_type(qca_smem_flash_info_t *smem)
{
return;
};
#ifdef CONFIG_USB_XHCI_IPQ
void board_usb_deinit(int id)
{
int nodeoff;
char node_name[8];
snprintf(node_name, sizeof(node_name), "usb%d", id);
nodeoff = fdt_path_offset(gd->fdt_blob, node_name);
if (fdtdec_get_int(gd->fdt_blob, nodeoff, "qcom,emulation", 0))
return;
if (id == 0) {
/* Enable USB PHY Power down */
setbits_le32(USB30_PHY_1_QUSB2PHY_BASE + 0xB4, 0x1);
/* Disable clocks */
writel(0x8000, GCC_USB0_PHY_CFG_AHB_CBCR);
writel(0xcff0, GCC_USB0_MASTER_CBCR);
writel(0, GCC_SYS_NOC_USB0_AXI_CBCR);
writel(0, GCC_SNOC_BUS_TIMEOUT2_AHB_CBCR);
writel(0, GCC_USB0_SLEEP_CBCR);
writel(0, GCC_USB0_MOCK_UTMI_CBCR);
writel(0, GCC_USB0_AUX_CBCR);
/* GCC_QUSB2_0_PHY_BCR */
set_mdelay_clearbits_le32(GCC_QUSB2_0_PHY_BCR, 0x1, 10);
/* GCC_USB0_PHY_BCR */
set_mdelay_clearbits_le32(GCC_USB0_PHY_BCR, 0x1, 10);
/* GCC Reset USB BCR */
set_mdelay_clearbits_le32(GCC_USB0_BCR, 0x1, 10);
} else if (id == 1) {
/* Enable USB PHY Power down */
setbits_le32(USB30_PHY_2_QUSB2PHY_BASE + 0xB4, 0x1);
/* Disable clocks */
writel(0x8000, GCC_USB1_PHY_CFG_AHB_CBCR);
writel(0xcff0, GCC_USB1_MASTER_CBCR);
writel(0, GCC_USB1_SLEEP_CBCR);
writel(0, GCC_USB1_MOCK_UTMI_CBCR);
/* GCC_QUSB2_0_PHY_BCR */
set_mdelay_clearbits_le32(GCC_QUSB2_1_PHY_BCR, 0x1, 10);
/* GCC Reset USB0 BCR */
set_mdelay_clearbits_le32(GCC_USB1_BCR, 0x1, 10);
}
}
static void usb_clock_init(int id)
{
int cfg;
if (id == 0) {
cfg = readl(GCC_USB0_GDSCR) | SW_OVERRIDE_ENABLE;
cfg &= ~(SW_COLLAPSE_ENABLE);
writel(cfg, GCC_USB0_GDSCR);
/* Configure usb0_master_clk_src */
cfg = (GCC_USB0_MASTER_CFG_RCGR_SRC_SEL |
GCC_USB0_MASTER_CFG_RCGR_SRC_DIV);
writel(cfg, GCC_USB0_MASTER_CFG_RCGR);
writel(CMD_UPDATE, GCC_USB0_MASTER_CMD_RCGR);
mdelay(100);
writel(ROOT_EN, GCC_USB0_MASTER_CMD_RCGR);
/* Configure usb0_mock_utmi_clk_src */
cfg = (GCC_USB_MOCK_UTMI_SRC_SEL |
GCC_USB_MOCK_UTMI_SRC_DIV);
writel(cfg, GCC_USB0_MOCK_UTMI_CFG_RCGR);
writel(UTMI_M, GCC_USB0_MOCK_UTMI_M);
writel(UTMI_N, GCC_USB0_MOCK_UTMI_N);
writel(UTMI_D, GCC_USB0_MOCK_UTMI_D);
writel(CMD_UPDATE, GCC_USB0_MOCK_UTMI_CMD_RCGR);
mdelay(100);
writel(ROOT_EN, GCC_USB0_MOCK_UTMI_CMD_RCGR);
/* Configure usb0_aux_clk_src */
cfg = (GCC_USB0_AUX_CFG_SRC_SEL |
GCC_USB0_AUX_CFG_SRC_DIV);
writel(cfg, GCC_USB0_AUX_CFG_RCGR);
writel(AUX_M, GCC_USB0_AUX_M);
writel(AUX_N, GCC_USB0_AUX_N);
writel(AUX_D, GCC_USB0_AUX_D);
writel(CMD_UPDATE, GCC_USB0_AUX_CMD_RCGR);
mdelay(100);
writel(ROOT_EN, GCC_USB0_AUX_CMD_RCGR);
/* Configure CBCRs */
writel(CLK_DISABLE, GCC_SYS_NOC_USB0_AXI_CBCR);
writel(CLK_DISABLE, GCC_SNOC_BUS_TIMEOUT2_AHB_CBCR);
writel(CLK_ENABLE, GCC_SYS_NOC_USB0_AXI_CBCR);
writel((readl(GCC_USB0_MASTER_CBCR) | CLK_ENABLE),
GCC_USB0_MASTER_CBCR);
writel(CLK_ENABLE, GCC_SNOC_BUS_TIMEOUT2_AHB_CBCR);
writel(CLK_ENABLE, GCC_USB0_SLEEP_CBCR);
writel(CLK_ENABLE, GCC_USB0_MOCK_UTMI_CBCR);
writel((CLK_ENABLE | NOC_HANDSHAKE_FSM_EN),
GCC_USB0_PHY_CFG_AHB_CBCR);
writel(CLK_ENABLE, GCC_USB0_AUX_CBCR);
writel(CLK_ENABLE, GCC_USB0_PIPE_CBCR);
} else if (id == 1) {
cfg = readl(GCC_USB1_GDSCR) | SW_OVERRIDE_ENABLE;
cfg &= ~(SW_COLLAPSE_ENABLE);
writel(cfg, GCC_USB1_GDSCR);
/* Configure usb1_mock_utmi_clk_src */
cfg = (GCC_USB_MOCK_UTMI_SRC_SEL |
GCC_USB_MOCK_UTMI_SRC_DIV);
writel(cfg, GCC_USB1_MOCK_UTMI_CFG_RCGR);
writel(UTMI_M, GCC_USB1_MOCK_UTMI_M);
writel(UTMI_N, GCC_USB1_MOCK_UTMI_N);
writel(UTMI_D, GCC_USB1_MOCK_UTMI_D);
writel(CMD_UPDATE, GCC_USB1_MOCK_UTMI_CMD_RCGR);
mdelay(100);
writel(ROOT_EN, GCC_USB1_MOCK_UTMI_CMD_RCGR);
/* Configure CBCRs */
writel(readl(GCC_USB1_MASTER_CBCR) | CLK_ENABLE,
GCC_USB1_MASTER_CBCR);
writel(CLK_ENABLE, GCC_USB1_SLEEP_CBCR);
writel(CLK_ENABLE, GCC_USB1_MOCK_UTMI_CBCR);
writel((CLK_ENABLE | NOC_HANDSHAKE_FSM_EN),
GCC_USB1_PHY_CFG_AHB_CBCR);
}
}
static void usb_init_hsphy(void __iomem *phybase)
{
/* Enable QUSB2PHY Power down */
setbits_le32(phybase+0xB4, 0x1);
/* PHY Config Sequence */
/* QUSB2PHY_PLL:PLL Feedback Divider Value */
out_8(phybase+0x00, 0x14);
/* QUSB2PHY_PORT_TUNE1: USB Product Application Tuning Register A */
out_8(phybase+0x80, 0xF8);
/* QUSB2PHY_PORT_TUNE2: USB Product Application Tuning Register B */
out_8(phybase+0x84, 0xB3);
/* QUSB2PHY_PORT_TUNE3: USB Product Application Tuning Register C */
out_8(phybase+0x88, 0x83);
/* QUSB2PHY_PORT_TUNE4: USB Product Application Tuning Register D */
out_8(phybase+0x8C, 0xC0);
/* QUSB2PHY_PORT_TEST2 */
out_8(phybase+0x9C, 0x14);
/* QUSB2PHY_PLL_TUNE: PLL Test Configuration */
out_8(phybase+0x08, 0x30);
/* QUSB2PHY_PLL_USER_CTL1: PLL Control Configuration */
out_8(phybase+0x0C, 0x79);
/* QUSB2PHY_PLL_USER_CTL2: PLL Control Configuration */
out_8(phybase+0x10, 0x21);
/* QUSB2PHY_PORT_TUNE5 */
out_8(phybase+0x90, 0x00);
/* QUSB2PHY_PLL_PWR_CTL: PLL Manual SW Programming
* and Biasing Power Options */
out_8(phybase+0x18, 0x00);
/* QUSB2PHY_PLL_AUTOPGM_CTL1: Auto vs. Manual PLL/Power-mode
* programming State Machine Control Options */
out_8(phybase+0x1C, 0x9F);
/* QUSB2PHY_PLL_TEST: PLL Test Configuration-Disable diff ended clock */
out_8(phybase+0x04, 0x80);
/* Disable QUSB2PHY Power down */
clrbits_le32(phybase+0xB4, 0x1);
}
static void usb_init_ssphy(void __iomem *phybase)
{
out_8(phybase + USB3_PHY_POWER_DOWN_CONTROL,0x1);
out_8(phybase + QSERDES_COM_SYSCLK_EN_SEL,0x1a);
out_8(phybase + QSERDES_COM_BIAS_EN_CLKBUFLR_EN,0x08);
out_8(phybase + QSERDES_COM_CLK_SELECT,0x30);
out_8(phybase + QSERDES_COM_BG_TRIM,0x0f);
out_8(phybase + QSERDES_RX_UCDR_FASTLOCK_FO_GAIN,0x0b);
out_8(phybase + QSERDES_COM_SVS_MODE_CLK_SEL,0x01);
out_8(phybase + QSERDES_COM_HSCLK_SEL,0x00);
out_8(phybase + QSERDES_COM_CMN_CONFIG,0x06);
out_8(phybase + QSERDES_COM_PLL_IVCO,0x0f);
out_8(phybase + QSERDES_COM_SYS_CLK_CTRL,0x06);
out_8(phybase + QSERDES_COM_DEC_START_MODE0,0x68);
out_8(phybase + QSERDES_COM_DIV_FRAC_START1_MODE0,0xAB);
out_8(phybase + QSERDES_COM_DIV_FRAC_START2_MODE0,0xAA);
out_8(phybase + QSERDES_COM_DIV_FRAC_START3_MODE0,0x02);
out_8(phybase + QSERDES_COM_CP_CTRL_MODE0,0x09);
out_8(phybase + QSERDES_COM_PLL_RCTRL_MODE0,0x16);
out_8(phybase + QSERDES_COM_PLL_CCTRL_MODE0,0x28);
out_8(phybase + QSERDES_COM_INTEGLOOP_GAIN0_MODE0,0xA0);
out_8(phybase + QSERDES_COM_LOCK_CMP1_MODE0,0xAA);
out_8(phybase + QSERDES_COM_LOCK_CMP2_MODE0,0x29);
out_8(phybase + QSERDES_COM_LOCK_CMP3_MODE0,0x00);
out_8(phybase + QSERDES_COM_CORE_CLK_EN,0x00);
out_8(phybase + QSERDES_COM_LOCK_CMP_CFG,0x00);
out_8(phybase + QSERDES_COM_VCO_TUNE_MAP,0x00);
out_8(phybase + QSERDES_COM_BG_TIMER,0x0a);
out_8(phybase + QSERDES_COM_SSC_EN_CENTER,0x01);
out_8(phybase + QSERDES_COM_SSC_PER1,0x7D);
out_8(phybase + QSERDES_COM_SSC_PER2,0x01);
out_8(phybase + QSERDES_COM_SSC_ADJ_PER1,0x00);
out_8(phybase + QSERDES_COM_SSC_ADJ_PER2,0x00);
out_8(phybase + QSERDES_COM_SSC_STEP_SIZE1,0x0A);
out_8(phybase + QSERDES_COM_SSC_STEP_SIZE2,0x05);
out_8(phybase + QSERDES_RX_UCDR_SO_GAIN,0x06);
out_8(phybase + QSERDES_RX_RX_EQU_ADAPTOR_CNTRL2,0x02);
out_8(phybase + QSERDES_RX_RX_EQU_ADAPTOR_CNTRL3,0x6c);
out_8(phybase + QSERDES_RX_RX_EQU_ADAPTOR_CNTRL3,0x4c);
out_8(phybase + QSERDES_RX_RX_EQU_ADAPTOR_CNTRL4,0xb8);
out_8(phybase + QSERDES_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL,0x77);
out_8(phybase + QSERDES_RX_RX_OFFSET_ADAPTOR_CNTRL2,0x80);
out_8(phybase + QSERDES_RX_SIGDET_CNTRL,0x03);
out_8(phybase + QSERDES_RX_SIGDET_DEGLITCH_CNTRL,0x16);
out_8(phybase + QSERDES_RX_SIGDET_ENABLES,0x0c);
out_8(phybase + QSERDES_TX_HIGHZ_TRANSCEIVEREN_BIAS_D,0x45);
out_8(phybase + QSERDES_TX_RCV_DETECT_LVL_2,0x12);
out_8(phybase + QSERDES_TX_LANE_MODE,0x06);
out_8(phybase + PCS_TXDEEMPH_M6DB_V0,0x15);
out_8(phybase + PCS_TXDEEMPH_M3P5DB_V0,0x0e);
out_8(phybase + PCS_FLL_CNTRL2,0x83);
out_8(phybase + PCS_FLL_CNTRL1,0x02);
out_8(phybase + PCS_FLL_CNT_VAL_L,0x09);
out_8(phybase + PCS_FLL_CNT_VAL_H_TOL,0xa2);
out_8(phybase + PCS_FLL_MAN_CODE,0x85);
out_8(phybase + PCS_LOCK_DETECT_CONFIG1,0xd1);
out_8(phybase + PCS_LOCK_DETECT_CONFIG2,0x1f);
out_8(phybase + PCS_LOCK_DETECT_CONFIG3,0x47);
out_8(phybase + PCS_POWER_STATE_CONFIG2,0x1b);
out_8(phybase + PCS_RXEQTRAINING_WAIT_TIME,0x75);
out_8(phybase + PCS_RXEQTRAINING_RUN_TIME,0x13);
out_8(phybase + PCS_LFPS_TX_ECSTART_EQTLOCK,0x86);
out_8(phybase + PCS_PWRUP_RESET_DLY_TIME_AUXCLK,0x04);
out_8(phybase + PCS_TSYNC_RSYNC_TIME,0x44);
out_8(phybase + PCS_RCVR_DTCT_DLY_P1U2_L,0xe7);
out_8(phybase + PCS_RCVR_DTCT_DLY_P1U2_H,0x03);
out_8(phybase + PCS_RCVR_DTCT_DLY_U3_L,0x40);
out_8(phybase + PCS_RCVR_DTCT_DLY_U3_H,0x00);
out_8(phybase + PCS_RX_SIGDET_LVL,0x88);
out_8(phybase + USB3_PCS_TXDEEMPH_M6DB_V0,0x17);
out_8(phybase + USB3_PCS_TXDEEMPH_M3P5DB_V0,0x0f);
out_8(phybase + QSERDES_RX_SIGDET_ENABLES,0x0);
out_8(phybase + USB3_PHY_START_CONTROL,0x03);
out_8(phybase + USB3_PHY_SW_RESET,0x00);
}
static void usb_init_phy(int index)
{
void __iomem *boot_clk_ctl, *usb_bcr, *qusb2_phy_bcr;
if (index == 0) {
boot_clk_ctl = (u32 *)GCC_USB_0_BOOT_CLOCK_CTL;
usb_bcr = (u32 *)GCC_USB0_BCR;
qusb2_phy_bcr = (u32 *)GCC_QUSB2_0_PHY_BCR;
} else if (index == 1) {
boot_clk_ctl = (u32 *)GCC_USB_1_BOOT_CLOCK_CTL;
usb_bcr = (u32 *)GCC_USB1_BCR;
qusb2_phy_bcr = (u32 *)GCC_QUSB2_1_PHY_BCR;
} else {
return;
}
/* Enable SS Ref Clock */
setbits_le32(GCC_USB_SS_REF_CLK_EN, 0x1);
/* Disable USB Boot Clock */
clrbits_le32(boot_clk_ctl, 0x0);
/* GCC Reset USB BCR */
set_mdelay_clearbits_le32(usb_bcr, 0x1, 10);
/* GCC_QUSB2_PHY_BCR */
setbits_le32(qusb2_phy_bcr, 0x1);
if (index == 0) {
/* GCC_USB0_PHY_BCR */
setbits_le32(GCC_USB0_PHY_BCR, 0x1);
setbits_le32(GCC_USB3PHY_0_PHY_BCR, 0x1);
mdelay(10);
clrbits_le32(GCC_USB3PHY_0_PHY_BCR, 0x1);
clrbits_le32(GCC_USB0_PHY_BCR, 0x1);
/* Config user control register */
writel(0x0a40c010, USB30_1_GUCTL);
writel(0x0a87f0a0, USB30_1_FLADJ);
} else if (index == 1) {
/* Config user control register */
writel(0x0a40c010, GUCTL);
writel(0x0a87f0a0, FLADJ);
} else {
return;
}
/* GCC_QUSB2_0_PHY_BCR */
clrbits_le32(qusb2_phy_bcr, 0x1);
mdelay(10);
if (index == 0) {
usb_init_hsphy((u32 *)USB30_PHY_1_QUSB2PHY_BASE);
usb_init_ssphy((u32 *)USB30_PHY_1_USB3PHY_AHB2PHY_BASE);
} else {
usb_init_hsphy((u32 *)USB30_PHY_2_QUSB2PHY_BASE);
}
}
int ipq_board_usb_init(void)
{
int i, nodeoff;
char node_name[8];
for (i=0; i<CONFIG_USB_MAX_CONTROLLER_COUNT; i++) {
snprintf(node_name, sizeof(node_name), "usb%d", i);
nodeoff = fdt_path_offset(gd->fdt_blob, node_name);
if (!fdtdec_get_int(gd->fdt_blob, nodeoff, "qcom,emulation", 0)) {
usb_clock_init(i);
usb_init_phy(i);
}
}
return 0;
}
#endif
static void __fixup_usb_device_mode(void *blob)
{
parse_fdt_fixup("/soc/usb3@8A00000/dwc3@8A00000%dr_mode%?peripheral", blob);
parse_fdt_fixup("/soc/usb3@8A00000/dwc3@8A00000%maximum-speed%?high-speed", blob);
}
static void fdt_fixup_diag_gadget(void *blob)
{
__fixup_usb_device_mode(blob);
parse_fdt_fixup("/soc/qcom,gadget_diag@0%status%?ok", blob);
}
void ipq_fdt_fixup_usb_device_mode(void *blob)
{
const char *usb_cfg;
usb_cfg = getenv("usb_mode");
if (!usb_cfg)
return;
if (!strncmp(usb_cfg, "peripheral", sizeof("peripheral")))
__fixup_usb_device_mode(blob);
else if (!strncmp(usb_cfg, "diag_gadget", sizeof("diag_gadget")))
fdt_fixup_diag_gadget(blob);
else
printf("%s: invalid param for usb_mode\n", __func__);
}
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();
}
__weak int ipq_get_tz_version(char *version_name, int buf_size)
{
return 1;
}
int apps_iscrashed_crashdump_disabled(void)
{
u32 *dmagic = (u32 *)CONFIG_IPQ6018_DMAGIC_ADDR;
if (*dmagic == DLOAD_DISABLED)
return 1;
return 0;
}
int apps_iscrashed(void)
{
u32 *dmagic = (u32 *)CONFIG_IPQ6018_DMAGIC_ADDR;
if (*dmagic == DLOAD_MAGIC_COOKIE)
return 1;
return 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
int get_aquantia_gpio(void)
{
int aquantia_gpio = -1, node;
node = fdt_path_offset(gd->fdt_blob, "/ess-switch");
if (node >= 0)
aquantia_gpio = fdtdec_get_uint(gd->fdt_blob, node, "aquantia_gpio", -1);
else
return node;
return aquantia_gpio;
}
int get_napa_gpio(int napa_gpio[2])
{
int napa_gpio_cnt = -1, node;
int res = -1;
node = fdt_path_offset(gd->fdt_blob, "/ess-switch");
if (node >= 0) {
napa_gpio_cnt = fdtdec_get_uint(gd->fdt_blob, node, "napa_gpio_cnt", -1);
if (napa_gpio_cnt >= 1) {
res = fdtdec_get_int_array(gd->fdt_blob, node, "napa_gpio",
(u32 *)napa_gpio, napa_gpio_cnt);
if (res >= 0)
return napa_gpio_cnt;
}
}
return res;
}
int get_malibu_gpio(int malibu_gpio[2])
{
int malibu_gpio_cnt = -1, node;
int res = -1;
node = fdt_path_offset(gd->fdt_blob, "/ess-switch");
if (node >= 0) {
malibu_gpio_cnt = fdtdec_get_uint(gd->fdt_blob, node, "malibu_gpio_cnt", -1);
if (malibu_gpio_cnt >= 1) {
res = fdtdec_get_int_array(gd->fdt_blob, node, "malibu_gpio",
(u32 *)malibu_gpio, malibu_gpio_cnt);
if (res >= 0)
return malibu_gpio_cnt;
}
}
return res;
}
void aquantia_phy_reset_init(void)
{
int aquantia_gpio = -1, node;
unsigned int *aquantia_gpio_base;
if (!aq_phy_initialised) {
node = fdt_path_offset(gd->fdt_blob, "/ess-switch");
if (node >= 0)
aquantia_gpio = fdtdec_get_uint(gd->fdt_blob, node, "aquantia_gpio", -1);
if (aquantia_gpio >=0) {
aquantia_gpio_base = (unsigned int *)GPIO_CONFIG_ADDR(aquantia_gpio);
writel(0x203, aquantia_gpio_base);
gpio_direction_output(aquantia_gpio, 0x0);
}
aq_phy_initialised = 1;
}
}
void napa_phy_reset_init(void)
{
int napa_gpio[2] = {0}, napa_gpio_cnt, i;
unsigned int *napa_gpio_base;
napa_gpio_cnt = get_napa_gpio(napa_gpio);
if (napa_gpio_cnt >= 1) {
for (i = 0; i < napa_gpio_cnt; i++) {
if (napa_gpio[i] >=0) {
napa_gpio_base = (unsigned int *)GPIO_CONFIG_ADDR(napa_gpio[i]);
writel(0x203, napa_gpio_base);
gpio_direction_output(napa_gpio[i], 0x0);
}
}
}
}
void malibu_phy_reset_init(void)
{
int malibu_gpio[2] = {0}, malibu_gpio_cnt, i;
unsigned int *malibu_gpio_base;
malibu_gpio_cnt = get_malibu_gpio(malibu_gpio);
if (malibu_gpio_cnt >= 1) {
for (i = 0; i < malibu_gpio_cnt; i++) {
if (malibu_gpio[i] >=0) {
malibu_gpio_base = (unsigned int *)GPIO_CONFIG_ADDR(malibu_gpio[i]);
writel(0x203, malibu_gpio_base);
gpio_direction_output(malibu_gpio[i], 0x0);
}
}
}
}
void sfp_reset_init(void)
{
int sfp_gpio = -1, node;
unsigned int *sfp_gpio_base;
node = fdt_path_offset(gd->fdt_blob, "/ess-switch");
if (node >= 0)
sfp_gpio = fdtdec_get_uint(gd->fdt_blob, node, "sfp_gpio", -1);
if (sfp_gpio >=0) {
sfp_gpio_base = (unsigned int *)GPIO_CONFIG_ADDR(sfp_gpio);
writel(0x2C1, sfp_gpio_base);
}
}
void aquantia_phy_reset_init_done(void)
{
int aquantia_gpio;
aquantia_gpio = get_aquantia_gpio();
if (aquantia_gpio >= 0) {
gpio_set_value(aquantia_gpio, 0x1);
}
}
void napa_phy_reset_init_done(void)
{
int napa_gpio[2] = {0}, napa_gpio_cnt, i;
napa_gpio_cnt = get_napa_gpio(napa_gpio);
if (napa_gpio_cnt >= 1) {
for (i = 0; i < napa_gpio_cnt; i++)
gpio_set_value(napa_gpio[i], 0x1);
}
}
void malibu_phy_reset_init_done(void)
{
int malibu_gpio[2] = {0}, malibu_gpio_cnt, i;
malibu_gpio_cnt = get_malibu_gpio(malibu_gpio);
if (malibu_gpio_cnt >= 1) {
for (i = 0; i < malibu_gpio_cnt; i++)
gpio_set_value(malibu_gpio[i], 0x1);
}
}
int get_mdc_mdio_gpio(int mdc_mdio_gpio[2])
{
int mdc_mdio_gpio_cnt = 2, node;
int res = -1;
node = fdt_path_offset(gd->fdt_blob, "/ess-switch");
if (node >= 0) {
res = fdtdec_get_int_array(gd->fdt_blob, node, "mdc_mdio_gpio",
(u32 *)mdc_mdio_gpio, mdc_mdio_gpio_cnt);
if (res >= 0)
return mdc_mdio_gpio_cnt;
}
return res;
}
void set_function_select_as_mdc_mdio(void)
{
int mdc_mdio_gpio[2] = {0}, mdc_mdio_gpio_cnt, i;
unsigned int *mdc_mdio_gpio_base;
mdc_mdio_gpio_cnt = get_mdc_mdio_gpio(mdc_mdio_gpio);
if (mdc_mdio_gpio_cnt >= 1) {
for (i = 0; i < mdc_mdio_gpio_cnt; i++) {
if (mdc_mdio_gpio[i] >=0) {
mdc_mdio_gpio_base = (unsigned int *)GPIO_CONFIG_ADDR(mdc_mdio_gpio[i]);
writel(0xC7, mdc_mdio_gpio_base);
}
}
}
}
static void ppe_clk_init(void)
{
uint32_t reg_val, i;
int gcc_ppeclock_base = 0x01868000;
int gcc_pll_base = 0x0009B780;
reg_val = readl(gcc_pll_base + 4);
reg_val=(reg_val&0xfffffff0)|0x7;
writel(reg_val, gcc_pll_base + 0x4);
reg_val = readl(gcc_pll_base);
reg_val=reg_val | 0x40;
writel(reg_val, gcc_pll_base);
mdelay(1);
reg_val=reg_val & (~0x40);
writel(reg_val, gcc_pll_base);
writel(0xbf, gcc_pll_base);
reg_val = readl(gcc_pll_base);
mdelay(1);
writel(0xff, gcc_pll_base);
reg_val = readl(gcc_pll_base);
mdelay(1);
/*set clock src and div*/
reg_val = 1 | (1 << 8);
writel(reg_val, gcc_ppeclock_base + 0x84);
/*issue command*/
reg_val = readl(gcc_ppeclock_base + 0x80);
reg_val |= 1;
writel(reg_val, gcc_ppeclock_base + 0x80);
mdelay(100);
reg_val = readl(gcc_ppeclock_base + 0x80);
reg_val |= 2;
writel(reg_val, gcc_ppeclock_base + 0x80);
/*set CBCR*/
for (i= 0; i < 4; i++) {
reg_val = readl(gcc_ppeclock_base + 0x190 + i*4);
reg_val |= 1;
writel(reg_val, gcc_ppeclock_base + 0x190 + i*4);
}
/*enable nss noc ppe*/
reg_val = readl(gcc_ppeclock_base + 0x300);
reg_val |= 1;
writel(reg_val, gcc_ppeclock_base + 0x300);
/*enable nss noc ppe config*/
reg_val = readl(gcc_ppeclock_base + 0x304);
reg_val |= 1;
writel(reg_val, gcc_ppeclock_base + 0x304);
/*enable crypto ppe*/
reg_val = readl(gcc_ppeclock_base + 0x310);
reg_val |= 1;
writel(reg_val, gcc_ppeclock_base + 0x310);
/*enable mac, ipe btq*/
for (i= 0; i < 8; i++) {
reg_val = readl(gcc_ppeclock_base + 0x320 + i*4);
reg_val |= 1;
writel(reg_val, gcc_ppeclock_base + 0x320 + i*4);
}
}
void eth_clock_enable(void)
{
ppe_clk_init();
/* RCGR and CBCR regs will be
* config by SBL. It will later be moved to u-boot.
*/
/*
* Take NSS PPE out of reset
*/
writel(PPE_ASSERT, GCC_NSS_PPE_RESET);
mdelay(500);
writel(PPE_DEASSERT, GCC_NSS_PPE_RESET);
mdelay(100);
/* set function select as mdio */
set_function_select_as_mdc_mdio();
/* bring phy out of reset */
malibu_phy_reset_init();
aquantia_phy_reset_init();
napa_phy_reset_init();
sfp_reset_init();
mdelay(500);
malibu_phy_reset_init_done();
aquantia_phy_reset_init_done();
napa_phy_reset_init_done();
mdelay(500);
}
int board_eth_init(bd_t *bis)
{
int ret=0;
eth_clock_enable();
ret = ipq6018_edma_init(NULL);
if (ret != 0)
printf("%s: ipq6018_edma_init failed : %d\n", __func__, ret);
return ret;
}
unsigned long timer_read_counter(void)
{
return 0;
}
void psci_sys_reset(void)
{
__invoke_psci_fn_smc(0x84000009, 0, 0, 0);
}
void qti_scm_pshold(void)
{
int ret;
ret = scm_call(SCM_SVC_BOOT, SCM_CMD_TZ_PSHOLD, NULL, 0, NULL, 0);
if (ret != 0)
writel(0, GCNT_PSHOLD);
}
static void atf_reset(void)
{
if(*tz_wonce == 0 ) { /*COLD REBOOT*/
if(do_pmic_reset())
printf("PMIC Reset failed, please do power cycle\n");
}
else { /*WARM REBOOT*/
psci_sys_reset();
}
while(1);
}
void reset_cpu(unsigned long a)
{
reset_crashdump();
if(getenv("atf"))
atf_reset();
else
psci_sys_reset();
while(1);
}
void reset_board(void)
{
reset_crashdump();
puts ("resetting ...\n");
mdelay(100);
if(*tz_wonce == 0) { /*COLD REBOOT*/
if(do_pmic_reset())
printf("PMIC Reset failed, please do power cycle\n");
}
else { /*WARM REBOOT*/
psci_sys_reset();
}
while(1);
}
void ipq_fdt_fixup_socinfo(void *blob)
{
uint32_t cpu_type;
uint32_t soc_version, soc_version_major, soc_version_minor;
int nodeoff, ret;
nodeoff = fdt_path_offset(blob, "/");
if (nodeoff < 0) {
printf("ipq: fdt fixup cannot find root node\n");
return;
}
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("%s: cannot get socinfo\n", __func__);
}
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__);
}
return;
}
void fdt_fixup_auto_restart(void *blob)
{
const char *paniconwcssfatal;
paniconwcssfatal = getenv("paniconwcssfatal");
if (!paniconwcssfatal)
return;
if (strncmp(paniconwcssfatal, "1", sizeof("1"))) {
printf("fixup_auto_restart: invalid variable 'paniconwcssfatal'");
} else {
parse_fdt_fixup("/soc/q6v5_wcss@CD00000%delete%?qca,auto-restart", blob);
}
return;
}
int is_secondary_core_off(unsigned int cpuid)
{
int err;
err = __invoke_psci_fn_smc(ARM_PSCI_TZ_FN_AFFINITY_INFO, cpuid, 0, 0);
return err;
}
void bring_secondary_core_down(unsigned int state)
{
__invoke_psci_fn_smc(ARM_PSCI_TZ_FN_CPU_OFF, state, 0, 0);
}
int bring_sec_core_up(unsigned int cpuid, unsigned int entry, unsigned int arg)
{
int err;
err = __invoke_psci_fn_smc(ARM_PSCI_TZ_FN_CPU_ON, cpuid, entry, arg);
if (err) {
printf("Enabling CPU%d via psci failed!\n", cpuid);
return -1;
}
printf("Enabled CPU%d via psci successfully!\n", cpuid);
return 0;
}
unsigned int get_dts_machid(unsigned int machid)
{
switch (machid)
{
case MACH_TYPE_IPQ6018_AP_CP01_C2:
case MACH_TYPE_IPQ6018_AP_CP01_C3:
return MACH_TYPE_IPQ6018_AP_CP01_C1;
case MACH_TYPE_IPQ6018_AP_CP01_C4:
return MACH_TYPE_IPQ6018_AP_CP01_C1;
default:
return machid;
}
}
void ipq_uboot_fdt_fixup(void)
{
int ret, len;
char *config = NULL;
switch (gd->bd->bi_arch_number)
{
case MACH_TYPE_IPQ6018_AP_CP01_C2:
config = "config@cp01-c2";
break;
case MACH_TYPE_IPQ6018_AP_CP01_C3:
config = "config@cp01-c3";
break;
case MACH_TYPE_IPQ6018_AP_CP01_C4:
config = "config@cp01-c4";
break;
}
if (config != NULL)
{
len = fdt_totalsize(gd->fdt_blob) + strlen(config) + 1;
/*
* Open in place with a new length.
*/
ret = fdt_open_into(gd->fdt_blob, (void *)gd->fdt_blob, len);
if (ret)
printf("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)
printf("uboot-fdt-fixup: unable to set config_name(%d)\n", ret);
}
return;
}
void fdt_fixup_set_qca_cold_reboot_enable(void *blob)
{
parse_fdt_fixup("/soc/qca,scm_restart_reason%qca,coldreboot-enabled%1", blob);
}
void fdt_fixup_wcss_rproc_for_atf(void *blob)
{
parse_fdt_fixup("/soc/qcom_q6v5_wcss@CD00000%qcom,nosecure%1", blob);
parse_fdt_fixup("/soc/qcom_q6v5_wcss@CD00000%qca,wcss-aon-reset-seq%1", blob);
}
int get_soc_hw_version(void)
{
return readl(TCSR_SOC_HW_VERSION_REG);
}