GK SDK 源码库: XMIPCLinuxV100R005C00SPC030 (kernel/tools/open_source excluded)
This commit is contained in:
@@ -0,0 +1,38 @@
|
||||
config CHAIN_OF_TRUST
|
||||
depends on !FIT_SIGNATURE && NXP_ESBC
|
||||
imply CMD_BLOB
|
||||
imply CMD_HASH if ARM
|
||||
select FSL_CAAM
|
||||
select SPL_BOARD_INIT if (ARM && SPL)
|
||||
select SHA_HW_ACCEL
|
||||
select SHA_PROG_HW_ACCEL
|
||||
select ENV_IS_NOWHERE
|
||||
select CMD_EXT4 if ARM
|
||||
select CMD_EXT4_WRITE if ARM
|
||||
bool
|
||||
default y
|
||||
|
||||
config CMD_ESBC_VALIDATE
|
||||
bool "Enable the 'esbc_validate' and 'esbc_halt' commands"
|
||||
default y if CHAIN_OF_TRUST
|
||||
help
|
||||
This option enables two commands used for secure booting:
|
||||
|
||||
esbc_validate - validate signature using RSA verification
|
||||
esbc_halt - put the core in spin loop (Secure Boot Only)
|
||||
|
||||
config VOL_MONITOR_LTC3882_READ
|
||||
depends on VID
|
||||
bool "Enable the LTC3882 voltage monitor read"
|
||||
default n
|
||||
help
|
||||
This option enables LTC3882 voltage monitor read
|
||||
functionality. It is used by common VID driver.
|
||||
|
||||
config VOL_MONITOR_LTC3882_SET
|
||||
depends on VID
|
||||
bool "Enable the LTC3882 voltage monitor set"
|
||||
default n
|
||||
help
|
||||
This option enables LTC3882 voltage monitor set
|
||||
functionality. It is used by common VID driver.
|
||||
@@ -0,0 +1,83 @@
|
||||
# SPDX-License-Identifier: GPL-2.0+
|
||||
#
|
||||
# (C) Copyright 2006
|
||||
# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
|
||||
|
||||
MINIMAL=
|
||||
|
||||
ifdef CONFIG_SPL_BUILD
|
||||
ifdef CONFIG_SPL_INIT_MINIMAL
|
||||
MINIMAL=y
|
||||
endif
|
||||
endif
|
||||
|
||||
ifdef MINIMAL
|
||||
# necessary to create built-in.o
|
||||
obj- := __dummy__.o
|
||||
else
|
||||
obj-$(CONFIG_FSL_CADMUS) += cadmus.o
|
||||
obj-$(CONFIG_FSL_VIA) += cds_via.o
|
||||
obj-$(CONFIG_FMAN_ENET) += fman.o
|
||||
obj-$(CONFIG_FSL_PIXIS) += pixis.o
|
||||
ifndef CONFIG_SPL_BUILD
|
||||
obj-$(CONFIG_FSL_NGPIXIS) += ngpixis.o
|
||||
endif
|
||||
obj-$(CONFIG_VID) += vid.o
|
||||
obj-$(CONFIG_FSL_QIXIS) += qixis.o
|
||||
obj-$(CONFIG_PQ_MDS_PIB) += pq-mds-pib.o
|
||||
ifndef CONFIG_SPL_BUILD
|
||||
obj-$(CONFIG_ID_EEPROM) += sys_eeprom.o
|
||||
endif
|
||||
obj-$(CONFIG_FSL_SGMII_RISER) += sgmii_riser.o
|
||||
ifndef CONFIG_RAMBOOT_PBL
|
||||
obj-$(CONFIG_FSL_FIXED_MMC_LOCATION) += sdhc_boot.o
|
||||
endif
|
||||
|
||||
obj-$(CONFIG_FSL_DIU_CH7301) += diu_ch7301.o
|
||||
|
||||
ifdef CONFIG_ARM
|
||||
obj-$(CONFIG_DEEP_SLEEP) += arm_sleep.o
|
||||
else
|
||||
obj-$(CONFIG_DEEP_SLEEP) += mpc85xx_sleep.o
|
||||
endif
|
||||
|
||||
obj-$(CONFIG_FSL_DCU_SII9022A) += dcu_sii9022a.o
|
||||
|
||||
obj-$(CONFIG_TARGET_MPC8541CDS) += cds_pci_ft.o
|
||||
obj-$(CONFIG_TARGET_MPC8548CDS) += cds_pci_ft.o
|
||||
obj-$(CONFIG_TARGET_MPC8555CDS) += cds_pci_ft.o
|
||||
|
||||
obj-$(CONFIG_TARGET_MPC8536DS) += ics307_clk.o
|
||||
obj-$(CONFIG_TARGET_MPC8572DS) += ics307_clk.o
|
||||
obj-$(CONFIG_TARGET_P1022DS) += ics307_clk.o
|
||||
obj-$(CONFIG_P2020DS) += ics307_clk.o
|
||||
obj-$(CONFIG_TARGET_P3041DS) += ics307_clk.o
|
||||
obj-$(CONFIG_TARGET_P4080DS) += ics307_clk.o
|
||||
obj-$(CONFIG_TARGET_P5020DS) += ics307_clk.o
|
||||
obj-$(CONFIG_TARGET_P5040DS) += ics307_clk.o
|
||||
obj-$(CONFIG_VSC_CROSSBAR) += vsc3316_3308.o
|
||||
obj-$(CONFIG_IDT8T49N222A) += idt8t49n222a_serdes_clk.o
|
||||
obj-$(CONFIG_ZM7300) += zm7300.o
|
||||
obj-$(CONFIG_POWER_PFUZE100) += pfuze.o
|
||||
obj-$(CONFIG_DM_PMIC_PFUZE100) += pfuze.o
|
||||
obj-$(CONFIG_POWER_MC34VR500) += mc34vr500.o
|
||||
|
||||
obj-$(CONFIG_LS102XA_STREAM_ID) += ls102xa_stream_id.o
|
||||
|
||||
obj-$(CONFIG_EMC2305) += emc2305.o
|
||||
|
||||
# deal with common files for P-series corenet based devices
|
||||
obj-$(CONFIG_TARGET_P2041RDB) += p_corenet/
|
||||
obj-$(CONFIG_TARGET_P3041DS) += p_corenet/
|
||||
obj-$(CONFIG_TARGET_P4080DS) += p_corenet/
|
||||
obj-$(CONFIG_TARGET_P5020DS) += p_corenet/
|
||||
obj-$(CONFIG_TARGET_P5040DS) += p_corenet/
|
||||
|
||||
obj-$(CONFIG_LAYERSCAPE_NS_ACCESS) += ns_access.o
|
||||
|
||||
ifdef CONFIG_NXP_ESBC
|
||||
obj-$(CONFIG_CMD_ESBC_VALIDATE) += fsl_validate.o cmd_esbc_validate.o
|
||||
endif
|
||||
obj-$(CONFIG_CHAIN_OF_TRUST) += fsl_chain_of_trust.o
|
||||
|
||||
endif
|
||||
@@ -0,0 +1,129 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Copyright 2014 Freescale Semiconductor, Inc.
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <asm/io.h>
|
||||
#ifndef CONFIG_ARMV7_NONSEC
|
||||
#error " Deep sleep needs non-secure mode support. "
|
||||
#else
|
||||
#include <asm/secure.h>
|
||||
#endif
|
||||
#include <asm/armv7.h>
|
||||
|
||||
#if defined(CONFIG_ARCH_LS1021A)
|
||||
#include <asm/arch/immap_ls102xa.h>
|
||||
#endif
|
||||
|
||||
#include "sleep.h"
|
||||
#ifdef CONFIG_U_QE
|
||||
#include <fsl_qe.h>
|
||||
#endif
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
void __weak board_mem_sleep_setup(void)
|
||||
{
|
||||
}
|
||||
|
||||
void __weak board_sleep_prepare(void)
|
||||
{
|
||||
}
|
||||
|
||||
bool is_warm_boot(void)
|
||||
{
|
||||
struct ccsr_gur __iomem *gur = (void *)CONFIG_SYS_FSL_GUTS_ADDR;
|
||||
|
||||
if (in_be32(&gur->crstsr) & DCFG_CCSR_CRSTSR_WDRFR)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void fsl_dp_disable_console(void)
|
||||
{
|
||||
gd->flags |= GD_FLG_SILENT | GD_FLG_DISABLE_CONSOLE;
|
||||
}
|
||||
|
||||
/*
|
||||
* When wakeup from deep sleep, the first 128 bytes space
|
||||
* will be used to do DDR training which corrupts the data
|
||||
* in there. This function will restore them.
|
||||
*/
|
||||
static void dp_ddr_restore(void)
|
||||
{
|
||||
u64 *src, *dst;
|
||||
int i;
|
||||
struct ccsr_scfg __iomem *scfg = (void *)CONFIG_SYS_FSL_SCFG_ADDR;
|
||||
|
||||
/* get the address of ddr date from SPARECR3 */
|
||||
src = (u64 *)in_le32(&scfg->sparecr[2]);
|
||||
dst = (u64 *)CONFIG_SYS_SDRAM_BASE;
|
||||
|
||||
for (i = 0; i < DDR_BUFF_LEN / 8; i++)
|
||||
*dst++ = *src++;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_ARMV7_PSCI) && defined(CONFIG_ARCH_LS1021A)
|
||||
void ls1_psci_resume_fixup(void)
|
||||
{
|
||||
u32 tmp;
|
||||
struct ccsr_scfg __iomem *scfg = (void *)CONFIG_SYS_FSL_SCFG_ADDR;
|
||||
|
||||
#ifdef QIXIS_BASE
|
||||
void *qixis_base = (void *)QIXIS_BASE;
|
||||
|
||||
/* Pull on PCIe RST# */
|
||||
out_8(qixis_base + QIXIS_RST_FORCE_3, 0);
|
||||
|
||||
/* disable deep sleep signals in FPGA */
|
||||
tmp = in_8(qixis_base + QIXIS_PWR_CTL2);
|
||||
tmp &= ~QIXIS_PWR_CTL2_PCTL;
|
||||
out_8(qixis_base + QIXIS_PWR_CTL2, tmp);
|
||||
#endif
|
||||
|
||||
/* Disable wakeup interrupt during deep sleep */
|
||||
out_be32(&scfg->pmcintecr, 0);
|
||||
/* Clear PMC interrupt status */
|
||||
out_be32(&scfg->pmcintsr, 0xffffffff);
|
||||
|
||||
/* Disable Warm Device Reset */
|
||||
tmp = in_be32(&scfg->dpslpcr);
|
||||
tmp &= ~SCFG_DPSLPCR_WDRR_EN;
|
||||
out_be32(&scfg->dpslpcr, tmp);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void dp_resume_prepare(void)
|
||||
{
|
||||
dp_ddr_restore();
|
||||
board_sleep_prepare();
|
||||
armv7_init_nonsec();
|
||||
#ifdef CONFIG_U_QE
|
||||
u_qe_resume();
|
||||
#endif
|
||||
#if defined(CONFIG_ARMV7_PSCI) && defined(CONFIG_ARCH_LS1021A)
|
||||
ls1_psci_resume_fixup();
|
||||
#endif
|
||||
}
|
||||
|
||||
int fsl_dp_resume(void)
|
||||
{
|
||||
u32 start_addr;
|
||||
void (*kernel_resume)(void);
|
||||
struct ccsr_scfg __iomem *scfg = (void *)CONFIG_SYS_FSL_SCFG_ADDR;
|
||||
|
||||
if (!is_warm_boot())
|
||||
return 0;
|
||||
|
||||
dp_resume_prepare();
|
||||
|
||||
/* Get the entry address and jump to kernel */
|
||||
start_addr = in_le32(&scfg->sparecr[3]);
|
||||
debug("Entry address is 0x%08x\n", start_addr);
|
||||
kernel_resume = (void (*)(void))start_addr;
|
||||
secure_ram_addr(_do_nonsec_entry)(kernel_resume, 0, 0, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Copyright 2004, 2011 Freescale Semiconductor.
|
||||
*/
|
||||
|
||||
|
||||
#include <common.h>
|
||||
|
||||
|
||||
/*
|
||||
* CADMUS Board System Registers
|
||||
*/
|
||||
#ifndef CONFIG_SYS_CADMUS_BASE_REG
|
||||
#define CONFIG_SYS_CADMUS_BASE_REG (CADMUS_BASE_ADDR + 0x4000)
|
||||
#endif
|
||||
|
||||
typedef struct cadmus_reg {
|
||||
u_char cm_ver; /* Board version */
|
||||
u_char cm_csr; /* General control/status */
|
||||
u_char cm_rst; /* Reset control */
|
||||
u_char cm_hsclk; /* High speed clock */
|
||||
u_char cm_hsxclk; /* High speed clock extended */
|
||||
u_char cm_led; /* LED data */
|
||||
u_char cm_pci; /* PCI control/status */
|
||||
u_char cm_dma; /* DMA control */
|
||||
u_char cm_reserved[248]; /* Total 256 bytes */
|
||||
} cadmus_reg_t;
|
||||
|
||||
|
||||
unsigned int
|
||||
get_board_version(void)
|
||||
{
|
||||
volatile cadmus_reg_t *cadmus = (cadmus_reg_t *)CONFIG_SYS_CADMUS_BASE_REG;
|
||||
|
||||
return cadmus->cm_ver;
|
||||
}
|
||||
|
||||
|
||||
unsigned long
|
||||
get_clock_freq(void)
|
||||
{
|
||||
volatile cadmus_reg_t *cadmus = (cadmus_reg_t *)CONFIG_SYS_CADMUS_BASE_REG;
|
||||
|
||||
uint pci1_speed = (cadmus->cm_pci >> 2) & 0x3; /* PSPEED in [4:5] */
|
||||
|
||||
if (pci1_speed == 0) {
|
||||
return 33333333;
|
||||
} else if (pci1_speed == 1) {
|
||||
return 66666666;
|
||||
} else {
|
||||
/* Really, unknown. Be safe? */
|
||||
return 33333333;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
unsigned int
|
||||
get_pci_slot(void)
|
||||
{
|
||||
volatile cadmus_reg_t *cadmus = (cadmus_reg_t *)CONFIG_SYS_CADMUS_BASE_REG;
|
||||
|
||||
/*
|
||||
* PCI slot in USER bits CSR[6:7] by convention.
|
||||
*/
|
||||
return ((cadmus->cm_csr >> 6) & 0x3) + 1;
|
||||
}
|
||||
|
||||
|
||||
unsigned int
|
||||
get_pci_dual(void)
|
||||
{
|
||||
volatile cadmus_reg_t *cadmus = (cadmus_reg_t *)CONFIG_SYS_CADMUS_BASE_REG;
|
||||
|
||||
/*
|
||||
* PCI DUAL in CM_PCI[3]
|
||||
*/
|
||||
return cadmus->cm_pci & 0x10;
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||
/*
|
||||
* Copyright 2004 Freescale Semiconductor.
|
||||
*/
|
||||
|
||||
#ifndef __CADMUS_H_
|
||||
#define __CADMUS_H_
|
||||
|
||||
|
||||
/*
|
||||
* CADMUS Board System Register interface.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Returns board version register.
|
||||
*/
|
||||
extern unsigned int get_board_version(void);
|
||||
|
||||
/*
|
||||
* Returns either 33000000 or 66000000 as the SYS_CLK_FREQ.
|
||||
*/
|
||||
extern unsigned long get_clock_freq(void);
|
||||
|
||||
|
||||
/*
|
||||
* Returns 1 - 4, as found in the USER CSR[6:7] bits.
|
||||
*/
|
||||
extern unsigned int get_pci_slot(void);
|
||||
|
||||
|
||||
/*
|
||||
* Returns PCI DUAL as found in CM_PCI[3].
|
||||
*/
|
||||
extern unsigned int get_pci_dual(void);
|
||||
|
||||
|
||||
#endif /* __CADMUS_H_ */
|
||||
@@ -0,0 +1,77 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Copyright 2004 Freescale Semiconductor.
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <linux/libfdt.h>
|
||||
#include <fdt_support.h>
|
||||
#include "cadmus.h"
|
||||
|
||||
#if defined(CONFIG_OF_BOARD_SETUP)
|
||||
#if defined(CONFIG_PCI) && !defined(CONFIG_DM_PCI)
|
||||
static void cds_pci_fixup(void *blob)
|
||||
{
|
||||
int node;
|
||||
const char *path;
|
||||
int len, slot, i;
|
||||
u32 *map = NULL, *piccells = NULL;
|
||||
int off, cells;
|
||||
|
||||
node = fdt_path_offset(blob, "/aliases");
|
||||
if (node >= 0) {
|
||||
path = fdt_getprop(blob, node, "pci0", NULL);
|
||||
if (path) {
|
||||
node = fdt_path_offset(blob, path);
|
||||
if (node >= 0) {
|
||||
map = fdt_getprop_w(blob, node, "interrupt-map", &len);
|
||||
}
|
||||
/* Each item in "interrupt-map" property is translated with
|
||||
* following cells:
|
||||
* PCI #address-cells, PCI #interrupt-cells,
|
||||
* PIC address, PIC #address-cells, PIC #interrupt-cells.
|
||||
*/
|
||||
cells = fdt_getprop_u32_default(blob, path, "#address-cells", 1);
|
||||
cells += fdt_getprop_u32_default(blob, path, "#interrupt-cells", 1);
|
||||
off = fdt_node_offset_by_phandle(blob, fdt32_to_cpu(*(map+cells)));
|
||||
if (off <= 0)
|
||||
return;
|
||||
cells += 1;
|
||||
piccells = (u32 *)fdt_getprop(blob, off, "#address-cells", NULL);
|
||||
if (piccells == NULL)
|
||||
return;
|
||||
cells += *piccells;
|
||||
piccells = (u32 *)fdt_getprop(blob, off, "#interrupt-cells", NULL);
|
||||
if (piccells == NULL)
|
||||
return;
|
||||
cells += *piccells;
|
||||
}
|
||||
}
|
||||
|
||||
if (map) {
|
||||
len /= sizeof(u32);
|
||||
|
||||
slot = get_pci_slot();
|
||||
|
||||
for (i=0;i<len;i+=cells) {
|
||||
/* We rotate the interrupt pins so that the mapping
|
||||
* changes depending on the slot the carrier card is in.
|
||||
*/
|
||||
map[3] = ((map[3] + slot - 2) % 4) + 1;
|
||||
map+=cells;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
int ft_board_setup(void *blob, bd_t *bd)
|
||||
{
|
||||
ft_cpu_setup(blob, bd);
|
||||
#if defined(CONFIG_PCI) && !defined(CONFIG_DM_PCI)
|
||||
ft_pci_setup(blob, bd);
|
||||
cds_pci_fixup(blob);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,92 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Copyright 2006 Freescale Semiconductor.
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <pci.h>
|
||||
|
||||
/* Config the VIA chip */
|
||||
void mpc85xx_config_via(struct pci_controller *hose,
|
||||
pci_dev_t dev, struct pci_config_table *tab)
|
||||
{
|
||||
pci_dev_t bridge;
|
||||
unsigned int cmdstat;
|
||||
|
||||
/* Enable USB and IDE functions */
|
||||
pci_hose_write_config_byte(hose, dev, 0x48, 0x08);
|
||||
|
||||
pci_hose_read_config_dword(hose, dev, PCI_COMMAND, &cmdstat);
|
||||
cmdstat |= PCI_COMMAND_IO | PCI_COMMAND_MEMORY| PCI_COMMAND_MASTER;
|
||||
pci_hose_write_config_dword(hose, dev, PCI_COMMAND, cmdstat);
|
||||
pci_hose_write_config_byte(hose, dev, PCI_CACHE_LINE_SIZE, 0x08);
|
||||
pci_hose_write_config_byte(hose, dev, PCI_LATENCY_TIMER, 0x80);
|
||||
|
||||
/*
|
||||
* Force the backplane P2P bridge to have a window
|
||||
* open from 0x00000000-0x00001fff in PCI I/O space.
|
||||
* This allows legacy I/O (i8259, etc) on the VIA
|
||||
* southbridge to be accessed.
|
||||
*/
|
||||
bridge = PCI_BDF(0,BRIDGE_ID,0);
|
||||
pci_hose_write_config_byte(hose, bridge, PCI_IO_BASE, 0);
|
||||
pci_hose_write_config_word(hose, bridge, PCI_IO_BASE_UPPER16, 0);
|
||||
pci_hose_write_config_byte(hose, bridge, PCI_IO_LIMIT, 0x10);
|
||||
pci_hose_write_config_word(hose, bridge, PCI_IO_LIMIT_UPPER16, 0);
|
||||
}
|
||||
|
||||
/* Function 1, IDE */
|
||||
void mpc85xx_config_via_usbide(struct pci_controller *hose,
|
||||
pci_dev_t dev, struct pci_config_table *tab)
|
||||
{
|
||||
pciauto_config_device(hose, dev);
|
||||
/*
|
||||
* Since the P2P window was forced to cover the fixed
|
||||
* legacy I/O addresses, it is necessary to manually
|
||||
* place the base addresses for the IDE and USB functions
|
||||
* within this window.
|
||||
*/
|
||||
pci_hose_write_config_dword(hose, dev, PCI_BASE_ADDRESS_0, 0x1ff8);
|
||||
pci_hose_write_config_dword(hose, dev, PCI_BASE_ADDRESS_1, 0x1ff4);
|
||||
pci_hose_write_config_dword(hose, dev, PCI_BASE_ADDRESS_2, 0x1fe8);
|
||||
pci_hose_write_config_dword(hose, dev, PCI_BASE_ADDRESS_3, 0x1fe4);
|
||||
pci_hose_write_config_dword(hose, dev, PCI_BASE_ADDRESS_4, 0x1fd0);
|
||||
}
|
||||
|
||||
/* Function 2, USB ports 0-1 */
|
||||
void mpc85xx_config_via_usb(struct pci_controller *hose,
|
||||
pci_dev_t dev, struct pci_config_table *tab)
|
||||
{
|
||||
pciauto_config_device(hose, dev);
|
||||
|
||||
pci_hose_write_config_dword(hose, dev, PCI_BASE_ADDRESS_4, 0x1fa0);
|
||||
}
|
||||
|
||||
/* Function 3, USB ports 2-3 */
|
||||
void mpc85xx_config_via_usb2(struct pci_controller *hose,
|
||||
pci_dev_t dev, struct pci_config_table *tab)
|
||||
{
|
||||
pciauto_config_device(hose, dev);
|
||||
|
||||
pci_hose_write_config_dword(hose, dev, PCI_BASE_ADDRESS_4, 0x1f80);
|
||||
}
|
||||
|
||||
/* Function 5, Power Management */
|
||||
void mpc85xx_config_via_power(struct pci_controller *hose,
|
||||
pci_dev_t dev, struct pci_config_table *tab)
|
||||
{
|
||||
pciauto_config_device(hose, dev);
|
||||
|
||||
pci_hose_write_config_dword(hose, dev, PCI_BASE_ADDRESS_0, 0x1e00);
|
||||
pci_hose_write_config_dword(hose, dev, PCI_BASE_ADDRESS_1, 0x1dfc);
|
||||
pci_hose_write_config_dword(hose, dev, PCI_BASE_ADDRESS_2, 0x1df8);
|
||||
}
|
||||
|
||||
/* Function 6, AC97 Interface */
|
||||
void mpc85xx_config_via_ac97(struct pci_controller *hose,
|
||||
pci_dev_t dev, struct pci_config_table *tab)
|
||||
{
|
||||
pciauto_config_device(hose, dev);
|
||||
|
||||
pci_hose_write_config_dword(hose, dev, PCI_BASE_ADDRESS_0, 0x1c00);
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Copyright 2015 Freescale Semiconductor, Inc.
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <command.h>
|
||||
#include <env.h>
|
||||
#include <fsl_validate.h>
|
||||
|
||||
int do_esbc_halt(cmd_tbl_t *cmdtp, int flag, int argc,
|
||||
char * const argv[])
|
||||
{
|
||||
if (fsl_check_boot_mode_secure() == 0) {
|
||||
printf("Boot Mode is Non-Secure. Not entering spin loop.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
printf("Core is entering spin loop.\n");
|
||||
loop:
|
||||
goto loop;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifndef CONFIG_SPL_BUILD
|
||||
static int do_esbc_validate(cmd_tbl_t *cmdtp, int flag, int argc,
|
||||
char * const argv[])
|
||||
{
|
||||
char *hash_str = NULL;
|
||||
uintptr_t haddr;
|
||||
int ret;
|
||||
uintptr_t img_addr = 0;
|
||||
char buf[20];
|
||||
|
||||
if (argc < 2)
|
||||
return cmd_usage(cmdtp);
|
||||
else if (argc > 2)
|
||||
/* Second arg - Optional - Hash Str*/
|
||||
hash_str = argv[2];
|
||||
|
||||
/* First argument - header address -32/64bit */
|
||||
haddr = (uintptr_t)simple_strtoul(argv[1], NULL, 16);
|
||||
|
||||
/* With esbc_validate command, Image address must be
|
||||
* part of header. So, the function is called
|
||||
* by passing this argument as 0.
|
||||
*/
|
||||
ret = fsl_secboot_validate(haddr, hash_str, &img_addr);
|
||||
|
||||
/* Need to set "img_addr" even if validation failure.
|
||||
* Required when SB_EN in RCW set and non-fatal error
|
||||
* to continue U-Boot
|
||||
*/
|
||||
sprintf(buf, "%lx", img_addr);
|
||||
env_set("img_addr", buf);
|
||||
|
||||
if (ret)
|
||||
return 1;
|
||||
|
||||
printf("esbc_validate command successful\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/***************************************************/
|
||||
static char esbc_validate_help_text[] =
|
||||
"esbc_validate hdr_addr <hash_val> - Validates signature using\n"
|
||||
" RSA verification\n"
|
||||
" $hdr_addr Address of header of the image\n"
|
||||
" to be validated.\n"
|
||||
" $hash_val -Optional\n"
|
||||
" It provides Hash of public/srk key to be\n"
|
||||
" used to verify signature.\n";
|
||||
|
||||
U_BOOT_CMD(
|
||||
esbc_validate, 3, 0, do_esbc_validate,
|
||||
"Validates signature on a given image using RSA verification",
|
||||
esbc_validate_help_text
|
||||
);
|
||||
|
||||
U_BOOT_CMD(
|
||||
esbc_halt, 1, 0, do_esbc_halt,
|
||||
"Put the core in spin loop (Secure Boot Only)",
|
||||
""
|
||||
);
|
||||
#endif
|
||||
@@ -0,0 +1,152 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Copyright 2014 Freescale Semiconductor, Inc.
|
||||
*/
|
||||
|
||||
#include <asm/io.h>
|
||||
#include <common.h>
|
||||
#include <fsl_dcu_fb.h>
|
||||
#include <i2c.h>
|
||||
#include <linux/fb.h>
|
||||
|
||||
#define PIXEL_CLK_LSB_REG 0x00
|
||||
#define PIXEL_CLK_MSB_REG 0x01
|
||||
#define VERT_FREQ_LSB_REG 0x02
|
||||
#define VERT_FREQ_MSB_REG 0x03
|
||||
#define TOTAL_PIXELS_LSB_REG 0x04
|
||||
#define TOTAL_PIXELS_MSB_REG 0x05
|
||||
#define TOTAL_LINES_LSB_REG 0x06
|
||||
#define TOTAL_LINES_MSB_REG 0x07
|
||||
#define TPI_INBUS_FMT_REG 0x08
|
||||
#define TPI_INPUT_FMT_REG 0x09
|
||||
#define TPI_OUTPUT_FMT_REG 0x0A
|
||||
#define TPI_SYS_CTRL_REG 0x1A
|
||||
#define TPI_PWR_STAT_REG 0x1E
|
||||
#define TPI_AUDIO_HANDING_REG 0x25
|
||||
#define TPI_AUDIO_INTF_REG 0x26
|
||||
#define TPI_AUDIO_FREQ_REG 0x27
|
||||
#define TPI_SET_PAGE_REG 0xBC
|
||||
#define TPI_SET_OFFSET_REG 0xBD
|
||||
#define TPI_RW_ACCESS_REG 0xBE
|
||||
#define TPI_TRANS_MODE_REG 0xC7
|
||||
|
||||
#define TPI_INBUS_CLOCK_RATIO_1 (1 << 6)
|
||||
#define TPI_INBUS_FULL_PIXEL_WIDE (1 << 5)
|
||||
#define TPI_INBUS_RISING_EDGE (1 << 4)
|
||||
#define TPI_INPUT_CLR_DEPTH_8BIT (0 << 6)
|
||||
#define TPI_INPUT_VRANGE_EXPAN_AUTO (0 << 2)
|
||||
#define TPI_INPUT_CLR_RGB (0 << 0)
|
||||
#define TPI_OUTPUT_CLR_DEPTH_8BIT (0 << 6)
|
||||
#define TPI_OUTPUT_VRANGE_COMPRE_AUTO (0 << 2)
|
||||
#define TPI_OUTPUT_CLR_HDMI_RGB (0 << 0)
|
||||
#define TPI_SYS_TMDS_OUTPUT (0 << 4)
|
||||
#define TPI_SYS_AV_NORAML (0 << 3)
|
||||
#define TPI_SYS_AV_MUTE (1 << 3)
|
||||
#define TPI_SYS_DVI_MODE (0 << 0)
|
||||
#define TPI_SYS_HDMI_MODE (1 << 0)
|
||||
#define TPI_PWR_STAT_MASK (3 << 0)
|
||||
#define TPI_PWR_STAT_D0 (0 << 0)
|
||||
#define TPI_AUDIO_PASS_BASIC (0 << 0)
|
||||
#define TPI_AUDIO_INTF_I2S (2 << 6)
|
||||
#define TPI_AUDIO_INTF_NORMAL (0 << 4)
|
||||
#define TPI_AUDIO_TYPE_PCM (1 << 0)
|
||||
#define TPI_AUDIO_SAMP_SIZE_16BIT (1 << 6)
|
||||
#define TPI_AUDIO_SAMP_FREQ_44K (2 << 3)
|
||||
#define TPI_SET_PAGE_SII9022A 0x01
|
||||
#define TPI_SET_OFFSET_SII9022A 0x82
|
||||
#define TPI_RW_EN_SRC_TERMIN (1 << 0)
|
||||
#define TPI_TRANS_MODE_ENABLE (0 << 7)
|
||||
|
||||
/* Programming of Silicon SIi9022a HDMI Transmitter */
|
||||
int dcu_set_dvi_encoder(struct fb_videomode *videomode)
|
||||
{
|
||||
u8 temp;
|
||||
u16 temp1, temp2;
|
||||
u32 temp3;
|
||||
|
||||
i2c_set_bus_num(CONFIG_SYS_I2C_DVI_BUS_NUM);
|
||||
|
||||
/* Enable TPI transmitter mode */
|
||||
temp = TPI_TRANS_MODE_ENABLE;
|
||||
i2c_write(CONFIG_SYS_I2C_DVI_ADDR, TPI_TRANS_MODE_REG, 1, &temp, 1);
|
||||
|
||||
/* Enter into D0 state, full operation */
|
||||
i2c_read(CONFIG_SYS_I2C_DVI_ADDR, TPI_PWR_STAT_REG, 1, &temp, 1);
|
||||
temp &= ~TPI_PWR_STAT_MASK;
|
||||
temp |= TPI_PWR_STAT_D0;
|
||||
i2c_write(CONFIG_SYS_I2C_DVI_ADDR, TPI_PWR_STAT_REG, 1, &temp, 1);
|
||||
|
||||
/* Enable source termination */
|
||||
temp = TPI_SET_PAGE_SII9022A;
|
||||
i2c_write(CONFIG_SYS_I2C_DVI_ADDR, TPI_SET_PAGE_REG, 1, &temp, 1);
|
||||
temp = TPI_SET_OFFSET_SII9022A;
|
||||
i2c_write(CONFIG_SYS_I2C_DVI_ADDR, TPI_SET_OFFSET_REG, 1, &temp, 1);
|
||||
|
||||
i2c_read(CONFIG_SYS_I2C_DVI_ADDR, TPI_RW_ACCESS_REG, 1, &temp, 1);
|
||||
temp |= TPI_RW_EN_SRC_TERMIN;
|
||||
i2c_write(CONFIG_SYS_I2C_DVI_ADDR, TPI_RW_ACCESS_REG, 1, &temp, 1);
|
||||
|
||||
/* Set TPI system control */
|
||||
temp = TPI_SYS_TMDS_OUTPUT | TPI_SYS_AV_NORAML | TPI_SYS_DVI_MODE;
|
||||
i2c_write(CONFIG_SYS_I2C_DVI_ADDR, TPI_SYS_CTRL_REG, 1, &temp, 1);
|
||||
|
||||
/* Set pixel clock */
|
||||
temp1 = PICOS2KHZ(videomode->pixclock) / 10;
|
||||
temp = (u8)(temp1 & 0xFF);
|
||||
i2c_write(CONFIG_SYS_I2C_DVI_ADDR, PIXEL_CLK_LSB_REG, 1, &temp, 1);
|
||||
temp = (u8)(temp1 >> 8);
|
||||
i2c_write(CONFIG_SYS_I2C_DVI_ADDR, PIXEL_CLK_MSB_REG, 1, &temp, 1);
|
||||
|
||||
/* Set total pixels per line */
|
||||
temp1 = videomode->hsync_len + videomode->left_margin +
|
||||
videomode->xres + videomode->right_margin;
|
||||
temp = (u8)(temp1 & 0xFF);
|
||||
i2c_write(CONFIG_SYS_I2C_DVI_ADDR, TOTAL_PIXELS_LSB_REG, 1, &temp, 1);
|
||||
temp = (u8)(temp1 >> 8);
|
||||
i2c_write(CONFIG_SYS_I2C_DVI_ADDR, TOTAL_PIXELS_MSB_REG, 1, &temp, 1);
|
||||
|
||||
/* Set total lines */
|
||||
temp2 = videomode->vsync_len + videomode->upper_margin +
|
||||
videomode->yres + videomode->lower_margin;
|
||||
temp = (u8)(temp2 & 0xFF);
|
||||
i2c_write(CONFIG_SYS_I2C_DVI_ADDR, TOTAL_LINES_LSB_REG, 1, &temp, 1);
|
||||
temp = (u8)(temp2 >> 8);
|
||||
i2c_write(CONFIG_SYS_I2C_DVI_ADDR, TOTAL_LINES_MSB_REG, 1, &temp, 1);
|
||||
|
||||
/* Set vertical frequency in Hz */
|
||||
temp3 = temp1 * temp2;
|
||||
temp3 = (PICOS2KHZ(videomode->pixclock) * 1000) / temp3;
|
||||
temp1 = (u16)temp3 * 100;
|
||||
temp = (u8)(temp1 & 0xFF);
|
||||
i2c_write(CONFIG_SYS_I2C_DVI_ADDR, VERT_FREQ_LSB_REG, 1, &temp, 1);
|
||||
temp = (u8)(temp1 >> 8);
|
||||
i2c_write(CONFIG_SYS_I2C_DVI_ADDR, VERT_FREQ_MSB_REG, 1, &temp, 1);
|
||||
|
||||
/* Set TPI input bus and pixel repetition data */
|
||||
temp = TPI_INBUS_CLOCK_RATIO_1 | TPI_INBUS_FULL_PIXEL_WIDE |
|
||||
TPI_INBUS_RISING_EDGE;
|
||||
i2c_write(CONFIG_SYS_I2C_DVI_ADDR, TPI_INBUS_FMT_REG, 1, &temp, 1);
|
||||
|
||||
/* Set TPI AVI Input format data */
|
||||
temp = TPI_INPUT_CLR_DEPTH_8BIT | TPI_INPUT_VRANGE_EXPAN_AUTO |
|
||||
TPI_INPUT_CLR_RGB;
|
||||
i2c_write(CONFIG_SYS_I2C_DVI_ADDR, TPI_INPUT_FMT_REG, 1, &temp, 1);
|
||||
|
||||
/* Set TPI AVI Output format data */
|
||||
temp = TPI_OUTPUT_CLR_DEPTH_8BIT | TPI_OUTPUT_VRANGE_COMPRE_AUTO |
|
||||
TPI_OUTPUT_CLR_HDMI_RGB;
|
||||
i2c_write(CONFIG_SYS_I2C_DVI_ADDR, TPI_OUTPUT_FMT_REG, 1, &temp, 1);
|
||||
|
||||
/* Set TPI audio configuration write data */
|
||||
temp = TPI_AUDIO_PASS_BASIC;
|
||||
i2c_write(CONFIG_SYS_I2C_DVI_ADDR, TPI_AUDIO_HANDING_REG, 1, &temp, 1);
|
||||
|
||||
temp = TPI_AUDIO_INTF_I2S | TPI_AUDIO_INTF_NORMAL |
|
||||
TPI_AUDIO_TYPE_PCM;
|
||||
i2c_write(CONFIG_SYS_I2C_DVI_ADDR, TPI_AUDIO_INTF_REG, 1, &temp, 1);
|
||||
|
||||
temp = TPI_AUDIO_SAMP_SIZE_16BIT | TPI_AUDIO_SAMP_FREQ_44K;
|
||||
i2c_write(CONFIG_SYS_I2C_DVI_ADDR, TPI_AUDIO_FREQ_REG, 1, &temp, 1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||
/*
|
||||
* Copyright 2014 Freescale Semiconductor, Inc.
|
||||
*/
|
||||
|
||||
#ifndef __DCU_HDMI_SII9022A__
|
||||
#define __DCU_HDMI_SII9022A__
|
||||
|
||||
/* Programming of Silicon SII9022A connector HDMI Transmitter*/
|
||||
int dcu_set_dvi_encoder(struct fb_videomode *videomode);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,135 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Copyright 2014 Freescale Semiconductor, Inc.
|
||||
* Authors: Priyanka Jain <Priyanka.Jain@freescale.com>
|
||||
* Wang Dongsheng <dongsheng.wang@freescale.com>
|
||||
*
|
||||
* This file is copied and modified from the original t1040qds/diu.c.
|
||||
* Encoder can be used in T104x and LSx Platform.
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <stdio_dev.h>
|
||||
#include <i2c.h>
|
||||
|
||||
#define I2C_DVI_INPUT_DATA_FORMAT_REG 0x1F
|
||||
#define I2C_DVI_PLL_CHARGE_CNTL_REG 0x33
|
||||
#define I2C_DVI_PLL_DIVIDER_REG 0x34
|
||||
#define I2C_DVI_PLL_SUPPLY_CNTL_REG 0x35
|
||||
#define I2C_DVI_PLL_FILTER_REG 0x36
|
||||
#define I2C_DVI_TEST_PATTERN_REG 0x48
|
||||
#define I2C_DVI_POWER_MGMT_REG 0x49
|
||||
#define I2C_DVI_LOCK_STATE_REG 0x4D
|
||||
#define I2C_DVI_SYNC_POLARITY_REG 0x56
|
||||
|
||||
/*
|
||||
* Set VSYNC/HSYNC to active high. This is polarity of sync signals
|
||||
* from DIU->DVI. The DIU default is active igh, so DVI is set to
|
||||
* active high.
|
||||
*/
|
||||
#define I2C_DVI_INPUT_DATA_FORMAT_VAL 0x98
|
||||
|
||||
#define I2C_DVI_PLL_CHARGE_CNTL_HIGH_SPEED_VAL 0x06
|
||||
#define I2C_DVI_PLL_DIVIDER_HIGH_SPEED_VAL 0x26
|
||||
#define I2C_DVI_PLL_FILTER_HIGH_SPEED_VAL 0xA0
|
||||
#define I2C_DVI_PLL_CHARGE_CNTL_LOW_SPEED_VAL 0x08
|
||||
#define I2C_DVI_PLL_DIVIDER_LOW_SPEED_VAL 0x16
|
||||
#define I2C_DVI_PLL_FILTER_LOW_SPEED_VAL 0x60
|
||||
|
||||
/* Clear test pattern */
|
||||
#define I2C_DVI_TEST_PATTERN_VAL 0x18
|
||||
/* Exit Power-down mode */
|
||||
#define I2C_DVI_POWER_MGMT_VAL 0xC0
|
||||
|
||||
/* Monitor polarity is handled via DVI Sync Polarity Register */
|
||||
#define I2C_DVI_SYNC_POLARITY_VAL 0x00
|
||||
|
||||
/* Programming of HDMI Chrontel CH7301 connector */
|
||||
int diu_set_dvi_encoder(unsigned int pixclock)
|
||||
{
|
||||
int ret;
|
||||
u8 temp;
|
||||
|
||||
temp = I2C_DVI_TEST_PATTERN_VAL;
|
||||
ret = i2c_write(CONFIG_SYS_I2C_DVI_ADDR, I2C_DVI_TEST_PATTERN_REG, 1,
|
||||
&temp, 1);
|
||||
if (ret) {
|
||||
puts("I2C: failed to select proper dvi test pattern\n");
|
||||
return ret;
|
||||
}
|
||||
temp = I2C_DVI_INPUT_DATA_FORMAT_VAL;
|
||||
ret = i2c_write(CONFIG_SYS_I2C_DVI_ADDR, I2C_DVI_INPUT_DATA_FORMAT_REG,
|
||||
1, &temp, 1);
|
||||
if (ret) {
|
||||
puts("I2C: failed to select dvi input data format\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Set Sync polarity register */
|
||||
temp = I2C_DVI_SYNC_POLARITY_VAL;
|
||||
ret = i2c_write(CONFIG_SYS_I2C_DVI_ADDR, I2C_DVI_SYNC_POLARITY_REG, 1,
|
||||
&temp, 1);
|
||||
if (ret) {
|
||||
puts("I2C: failed to select dvi syc polarity\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Set PLL registers based on pixel clock rate*/
|
||||
if (pixclock > 65000000) {
|
||||
temp = I2C_DVI_PLL_CHARGE_CNTL_HIGH_SPEED_VAL;
|
||||
ret = i2c_write(CONFIG_SYS_I2C_DVI_ADDR,
|
||||
I2C_DVI_PLL_CHARGE_CNTL_REG, 1, &temp, 1);
|
||||
if (ret) {
|
||||
puts("I2C: failed to select dvi pll charge_cntl\n");
|
||||
return ret;
|
||||
}
|
||||
temp = I2C_DVI_PLL_DIVIDER_HIGH_SPEED_VAL;
|
||||
ret = i2c_write(CONFIG_SYS_I2C_DVI_ADDR,
|
||||
I2C_DVI_PLL_DIVIDER_REG, 1, &temp, 1);
|
||||
if (ret) {
|
||||
puts("I2C: failed to select dvi pll divider\n");
|
||||
return ret;
|
||||
}
|
||||
temp = I2C_DVI_PLL_FILTER_HIGH_SPEED_VAL;
|
||||
ret = i2c_write(CONFIG_SYS_I2C_DVI_ADDR,
|
||||
I2C_DVI_PLL_FILTER_REG, 1, &temp, 1);
|
||||
if (ret) {
|
||||
puts("I2C: failed to select dvi pll filter\n");
|
||||
return ret;
|
||||
}
|
||||
} else {
|
||||
temp = I2C_DVI_PLL_CHARGE_CNTL_LOW_SPEED_VAL;
|
||||
ret = i2c_write(CONFIG_SYS_I2C_DVI_ADDR,
|
||||
I2C_DVI_PLL_CHARGE_CNTL_REG, 1, &temp, 1);
|
||||
if (ret) {
|
||||
puts("I2C: failed to select dvi pll charge_cntl\n");
|
||||
return ret;
|
||||
}
|
||||
temp = I2C_DVI_PLL_DIVIDER_LOW_SPEED_VAL;
|
||||
ret = i2c_write(CONFIG_SYS_I2C_DVI_ADDR,
|
||||
I2C_DVI_PLL_DIVIDER_REG, 1, &temp, 1);
|
||||
if (ret) {
|
||||
puts("I2C: failed to select dvi pll divider\n");
|
||||
return ret;
|
||||
}
|
||||
temp = I2C_DVI_PLL_FILTER_LOW_SPEED_VAL;
|
||||
ret = i2c_write(CONFIG_SYS_I2C_DVI_ADDR,
|
||||
I2C_DVI_PLL_FILTER_REG, 1, &temp, 1);
|
||||
if (ret) {
|
||||
puts("I2C: failed to select dvi pll filter\n");
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
temp = I2C_DVI_POWER_MGMT_VAL;
|
||||
ret = i2c_write(CONFIG_SYS_I2C_DVI_ADDR, I2C_DVI_POWER_MGMT_REG, 1,
|
||||
&temp, 1);
|
||||
if (ret) {
|
||||
puts("I2C: failed to select dvi power mgmt\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
udelay(500);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||
/*
|
||||
* Copyright 2014 Freescale Semiconductor, Inc.
|
||||
*/
|
||||
|
||||
#ifndef __DIU_HDMI_CH7301__
|
||||
#define __DIU_HDMI_CH7301__
|
||||
|
||||
/* Programming of HDMI Chrontel CH7301 connector */
|
||||
int diu_set_dvi_encoder(unsigned int pixclock);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,33 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||
/*
|
||||
* Copyright 2004 Freescale Semiconductor.
|
||||
*/
|
||||
|
||||
#ifndef __EEPROM_H_
|
||||
#define __EEPROM_H_
|
||||
|
||||
|
||||
/*
|
||||
* EEPROM Board System Register interface.
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* CPU Board Revision
|
||||
*/
|
||||
#define MPC85XX_CPU_BOARD_REV(maj, min) ((((maj)&0xff) << 8) | ((min) & 0xff))
|
||||
#define MPC85XX_CPU_BOARD_MAJOR(rev) (((rev) >> 8) & 0xff)
|
||||
#define MPC85XX_CPU_BOARD_MINOR(rev) ((rev) & 0xff)
|
||||
|
||||
#define MPC85XX_CPU_BOARD_REV_UNKNOWN MPC85XX_CPU_BOARD_REV(0,0)
|
||||
#define MPC85XX_CPU_BOARD_REV_1_0 MPC85XX_CPU_BOARD_REV(1,0)
|
||||
#define MPC85XX_CPU_BOARD_REV_1_1 MPC85XX_CPU_BOARD_REV(1,1)
|
||||
|
||||
/*
|
||||
* Returns CPU board revision register as a 16-bit value with
|
||||
* the Major in the high byte, and Minor in the low byte.
|
||||
*/
|
||||
extern unsigned int get_cpu_board_revision(void);
|
||||
|
||||
|
||||
#endif /* __CADMUS_H_ */
|
||||
@@ -0,0 +1,62 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Copyright 2018 NXP.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <command.h>
|
||||
#include <i2c.h>
|
||||
#include <asm/io.h>
|
||||
|
||||
#include "emc2305.h"
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
void set_fan_speed(u8 data)
|
||||
{
|
||||
u8 index;
|
||||
u8 Fan[NUM_OF_FANS] = {I2C_EMC2305_FAN1,
|
||||
I2C_EMC2305_FAN2,
|
||||
I2C_EMC2305_FAN3,
|
||||
I2C_EMC2305_FAN4,
|
||||
I2C_EMC2305_FAN5};
|
||||
|
||||
for (index = 0; index < NUM_OF_FANS; index++) {
|
||||
#ifndef CONFIG_DM_I2C
|
||||
if (i2c_write(I2C_EMC2305_ADDR, Fan[index], 1, &data, 1) != 0) {
|
||||
printf("Error: failed to change fan speed @%x\n",
|
||||
Fan[index]);
|
||||
}
|
||||
#else
|
||||
struct udevice *dev;
|
||||
|
||||
if (i2c_get_chip_for_busnum(0, I2C_EMC2305_ADDR, 1, &dev))
|
||||
continue;
|
||||
|
||||
if (dm_i2c_write(dev, Fan[index], &data, 1) != 0) {
|
||||
printf("Error: failed to change fan speed @%x\n",
|
||||
Fan[index]);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void emc2305_init(void)
|
||||
{
|
||||
u8 data;
|
||||
|
||||
data = I2C_EMC2305_CMD;
|
||||
#ifndef CONFIG_DM_I2C
|
||||
if (i2c_write(I2C_EMC2305_ADDR, I2C_EMC2305_CONF, 1, &data, 1) != 0)
|
||||
printf("Error: failed to configure EMC2305\n");
|
||||
#else
|
||||
struct udevice *dev;
|
||||
|
||||
if (!i2c_get_chip_for_busnum(0, I2C_EMC2305_ADDR, 1, &dev))
|
||||
if (dm_i2c_write(dev, I2C_EMC2305_CONF, &data, 1))
|
||||
printf("Error: failed to configure EMC2305\n");
|
||||
#endif
|
||||
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||
/*
|
||||
* Copyright 2018 NXP
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#ifndef __EMC2305_H_
|
||||
#define __EMC2305_H_
|
||||
|
||||
#define I2C_EMC2305_CONF 0x20
|
||||
#define I2C_EMC2305_FAN1 0x30
|
||||
#define I2C_EMC2305_FAN2 0x40
|
||||
#define I2C_EMC2305_FAN3 0x50
|
||||
#define I2C_EMC2305_FAN4 0x60
|
||||
#define I2C_EMC2305_FAN5 0x70
|
||||
|
||||
#define NUM_OF_FANS 5
|
||||
|
||||
void emc2305_init(void);
|
||||
void set_fan_speed(u8 data);
|
||||
|
||||
#endif /* __EMC2305_H_ */
|
||||
@@ -0,0 +1,89 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Copyright 2011-2015 Freescale Semiconductor, Inc.
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <linux/libfdt.h>
|
||||
#include <linux/libfdt_env.h>
|
||||
#include <fdt_support.h>
|
||||
|
||||
#include <fm_eth.h>
|
||||
#ifdef CONFIG_FSL_LAYERSCAPE
|
||||
#include <asm/arch/fsl_serdes.h>
|
||||
#else
|
||||
#include <asm/fsl_serdes.h>
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Given the following ...
|
||||
*
|
||||
* 1) A pointer to an Fman Ethernet node (as identified by the 'compat'
|
||||
* compatible string and 'addr' physical address)
|
||||
*
|
||||
* 2) The name of an alias that points to the ethernet-phy node (usually inside
|
||||
* a virtual MDIO node)
|
||||
*
|
||||
* ... update that Ethernet node's phy-handle property to point to the
|
||||
* ethernet-phy node. This is how we link an Ethernet node to its PHY, so each
|
||||
* PHY in a virtual MDIO node must have an alias.
|
||||
*
|
||||
* Returns 0 on success, or a negative FDT error code on error.
|
||||
*/
|
||||
int fdt_set_phy_handle(void *fdt, char *compat, phys_addr_t addr,
|
||||
const char *alias)
|
||||
{
|
||||
int offset;
|
||||
unsigned int ph;
|
||||
const char *path;
|
||||
|
||||
/* Get a path to the node that 'alias' points to */
|
||||
path = fdt_get_alias(fdt, alias);
|
||||
if (!path)
|
||||
return -FDT_ERR_BADPATH;
|
||||
|
||||
/* Get the offset of that node */
|
||||
offset = fdt_path_offset(fdt, path);
|
||||
if (offset < 0)
|
||||
return offset;
|
||||
|
||||
ph = fdt_create_phandle(fdt, offset);
|
||||
if (!ph)
|
||||
return -FDT_ERR_BADPHANDLE;
|
||||
|
||||
ph = cpu_to_fdt32(ph);
|
||||
|
||||
offset = fdt_node_offset_by_compat_reg(fdt, compat, addr);
|
||||
if (offset < 0)
|
||||
return offset;
|
||||
|
||||
return fdt_setprop(fdt, offset, "phy-handle", &ph, sizeof(ph));
|
||||
}
|
||||
|
||||
/*
|
||||
* Return the SerDes device enum for a given Fman port
|
||||
*
|
||||
* This function just maps the fm_port namespace to the srds_prtcl namespace.
|
||||
*/
|
||||
enum srds_prtcl serdes_device_from_fm_port(enum fm_port port)
|
||||
{
|
||||
static const enum srds_prtcl srds_table[] = {
|
||||
[FM1_DTSEC1] = SGMII_FM1_DTSEC1,
|
||||
[FM1_DTSEC2] = SGMII_FM1_DTSEC2,
|
||||
[FM1_DTSEC3] = SGMII_FM1_DTSEC3,
|
||||
[FM1_DTSEC4] = SGMII_FM1_DTSEC4,
|
||||
[FM1_DTSEC5] = SGMII_FM1_DTSEC5,
|
||||
[FM1_10GEC1] = XAUI_FM1,
|
||||
[FM2_DTSEC1] = SGMII_FM2_DTSEC1,
|
||||
[FM2_DTSEC2] = SGMII_FM2_DTSEC2,
|
||||
[FM2_DTSEC3] = SGMII_FM2_DTSEC3,
|
||||
[FM2_DTSEC4] = SGMII_FM2_DTSEC4,
|
||||
[FM2_DTSEC5] = SGMII_FM2_DTSEC5,
|
||||
[FM2_10GEC1] = XAUI_FM2,
|
||||
};
|
||||
|
||||
if ((port < FM1_DTSEC1) || (port > FM2_10GEC1))
|
||||
return NONE;
|
||||
else
|
||||
return srds_table[port];
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||
/*
|
||||
* Copyright 2011 Freescale Semiconductor, Inc.
|
||||
*/
|
||||
|
||||
#ifndef __FMAN_BOARD_HELPER__
|
||||
#define __FMAN_BOARD_HELPER__
|
||||
|
||||
int fdt_set_phy_handle(void *fdt, char *compat, phys_addr_t addr,
|
||||
const char *alias);
|
||||
|
||||
enum srds_prtcl serdes_device_from_fm_port(enum fm_port port);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,165 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Copyright 2015 Freescale Semiconductor, Inc.
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <dm.h>
|
||||
#include <env.h>
|
||||
#include <fsl_validate.h>
|
||||
#include <fsl_secboot_err.h>
|
||||
#include <fsl_sfp.h>
|
||||
#include <dm/root.h>
|
||||
|
||||
#if defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_FRAMEWORK)
|
||||
#include <spl.h>
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_ADDR_MAP
|
||||
#include <asm/mmu.h>
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_FSL_CORENET
|
||||
#include <asm/fsl_pamu.h>
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_ARCH_LS1021A
|
||||
#include <asm/arch/immap_ls102xa.h>
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_MPC85xx)
|
||||
#define CONFIG_DCFG_ADDR CONFIG_SYS_MPC85xx_GUTS_ADDR
|
||||
#else
|
||||
#define CONFIG_DCFG_ADDR CONFIG_SYS_FSL_GUTS_ADDR
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SYS_FSL_CCSR_GUR_LE
|
||||
#define gur_in32(a) in_le32(a)
|
||||
#else
|
||||
#define gur_in32(a) in_be32(a)
|
||||
#endif
|
||||
|
||||
/* Check the Boot Mode. If Secure, return 1 else return 0 */
|
||||
int fsl_check_boot_mode_secure(void)
|
||||
{
|
||||
uint32_t val;
|
||||
struct ccsr_sfp_regs *sfp_regs = (void *)(CONFIG_SYS_SFP_ADDR);
|
||||
struct ccsr_gur __iomem *gur = (void *)(CONFIG_DCFG_ADDR);
|
||||
|
||||
val = sfp_in32(&sfp_regs->ospr) & ITS_MASK;
|
||||
if (val == ITS_MASK)
|
||||
return 1;
|
||||
|
||||
#if defined(CONFIG_FSL_CORENET) || !defined(CONFIG_MPC85xx)
|
||||
/* For PBL based platforms check the SB_EN bit in RCWSR */
|
||||
val = gur_in32(&gur->rcwsr[RCW_SB_EN_REG_INDEX - 1]) & RCW_SB_EN_MASK;
|
||||
if (val == RCW_SB_EN_MASK)
|
||||
return 1;
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_MPC85xx) && !defined(CONFIG_FSL_CORENET)
|
||||
/* For Non-PBL Platforms, check the Device Status register 2*/
|
||||
val = gur_in32(&gur->pordevsr2) & MPC85xx_PORDEVSR2_SBC_MASK;
|
||||
if (val != MPC85xx_PORDEVSR2_SBC_MASK)
|
||||
return 1;
|
||||
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifndef CONFIG_SPL_BUILD
|
||||
int fsl_setenv_chain_of_trust(void)
|
||||
{
|
||||
/* Check Boot Mode
|
||||
* If Boot Mode is Non-Secure, no changes are required
|
||||
*/
|
||||
if (fsl_check_boot_mode_secure() == 0)
|
||||
return 0;
|
||||
|
||||
/* If Boot mode is Secure, set the environment variables
|
||||
* bootdelay = 0 (To disable Boot Prompt)
|
||||
* bootcmd = CONFIG_CHAIN_BOOT_CMD (Validate and execute Boot script)
|
||||
*/
|
||||
env_set("bootdelay", "-2");
|
||||
|
||||
#ifdef CONFIG_ARM
|
||||
env_set("secureboot", "y");
|
||||
#else
|
||||
env_set("bootcmd", CONFIG_CHAIN_BOOT_CMD);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SPL_BUILD
|
||||
void spl_validate_uboot(uint32_t hdr_addr, uintptr_t img_addr)
|
||||
{
|
||||
int res;
|
||||
|
||||
/*
|
||||
* Check Boot Mode
|
||||
* If Boot Mode is Non-Secure, skip validation
|
||||
*/
|
||||
if (fsl_check_boot_mode_secure() == 0)
|
||||
return;
|
||||
|
||||
printf("SPL: Validating U-Boot image\n");
|
||||
|
||||
#ifdef CONFIG_ADDR_MAP
|
||||
init_addr_map();
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_FSL_CORENET
|
||||
if (pamu_init() < 0)
|
||||
fsl_secboot_handle_error(ERROR_ESBC_PAMU_INIT);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_FSL_CAAM
|
||||
if (sec_init() < 0)
|
||||
fsl_secboot_handle_error(ERROR_ESBC_SEC_INIT);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* dm_init_and_scan() is called as part of common SPL framework, so no
|
||||
* need to call it again but in case of powerpc platforms which currently
|
||||
* do not use common SPL framework, so need to call this function here.
|
||||
*/
|
||||
#if defined(CONFIG_SPL_DM) && (!defined(CONFIG_SPL_FRAMEWORK))
|
||||
dm_init_and_scan(true);
|
||||
#endif
|
||||
res = fsl_secboot_validate(hdr_addr, CONFIG_SPL_UBOOT_KEY_HASH,
|
||||
&img_addr);
|
||||
|
||||
if (res == 0)
|
||||
printf("SPL: Validation of U-boot successful\n");
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SPL_FRAMEWORK
|
||||
/* Override weak funtion defined in SPL framework to enable validation
|
||||
* of main u-boot image before jumping to u-boot image.
|
||||
*/
|
||||
void __noreturn jump_to_image_no_args(struct spl_image_info *spl_image)
|
||||
{
|
||||
typedef void __noreturn (*image_entry_noargs_t)(void);
|
||||
uint32_t hdr_addr;
|
||||
|
||||
image_entry_noargs_t image_entry =
|
||||
(image_entry_noargs_t)(unsigned long)spl_image->entry_point;
|
||||
|
||||
hdr_addr = (spl_image->entry_point + spl_image->size -
|
||||
CONFIG_U_BOOT_HDR_SIZE);
|
||||
spl_validate_uboot(hdr_addr, (uintptr_t)spl_image->entry_point);
|
||||
/*
|
||||
* In case of failure in validation, spl_validate_uboot would
|
||||
* not return back in case of Production environment with ITS=1.
|
||||
* Thus U-Boot will not start.
|
||||
* In Development environment (ITS=0 and SB_EN=1), the function
|
||||
* may return back in case of non-fatal failures.
|
||||
*/
|
||||
|
||||
debug("image entry point: 0x%lX\n", spl_image->entry_point);
|
||||
image_entry();
|
||||
}
|
||||
#endif /* ifdef CONFIG_SPL_FRAMEWORK */
|
||||
#endif /* ifdef CONFIG_SPL_BUILD */
|
||||
@@ -0,0 +1,962 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Copyright 2015 Freescale Semiconductor, Inc.
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <dm.h>
|
||||
#include <fsl_validate.h>
|
||||
#include <fsl_secboot_err.h>
|
||||
#include <fsl_sfp.h>
|
||||
#include <fsl_sec.h>
|
||||
#include <command.h>
|
||||
#include <malloc.h>
|
||||
#include <u-boot/rsa-mod-exp.h>
|
||||
#include <hash.h>
|
||||
#include <fsl_secboot_err.h>
|
||||
#ifdef CONFIG_ARCH_LS1021A
|
||||
#include <asm/arch/immap_ls102xa.h>
|
||||
#endif
|
||||
|
||||
#define SHA256_BITS 256
|
||||
#define SHA256_BYTES (256/8)
|
||||
#define SHA256_NIBBLES (256/4)
|
||||
#define NUM_HEX_CHARS (sizeof(ulong) * 2)
|
||||
|
||||
#define CHECK_KEY_LEN(key_len) (((key_len) == 2 * KEY_SIZE_BYTES / 4) || \
|
||||
((key_len) == 2 * KEY_SIZE_BYTES / 2) || \
|
||||
((key_len) == 2 * KEY_SIZE_BYTES))
|
||||
#if defined(CONFIG_FSL_ISBC_KEY_EXT)
|
||||
/* Global data structure */
|
||||
static struct fsl_secboot_glb glb;
|
||||
#endif
|
||||
|
||||
/* This array contains DER value for SHA-256 */
|
||||
static const u8 hash_identifier[] = { 0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60,
|
||||
0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00,
|
||||
0x04, 0x20
|
||||
};
|
||||
|
||||
static u8 hash_val[SHA256_BYTES];
|
||||
|
||||
#ifdef CONFIG_ESBC_HDR_LS
|
||||
/* New Barker Code for LS ESBC Header */
|
||||
static const u8 barker_code[ESBC_BARKER_LEN] = { 0x12, 0x19, 0x20, 0x01 };
|
||||
#else
|
||||
static const u8 barker_code[ESBC_BARKER_LEN] = { 0x68, 0x39, 0x27, 0x81 };
|
||||
#endif
|
||||
|
||||
void branch_to_self(void) __attribute__ ((noreturn));
|
||||
|
||||
/*
|
||||
* This function will put core in infinite loop.
|
||||
* This will be called when the ESBC can not proceed further due
|
||||
* to some unknown errors.
|
||||
*/
|
||||
void branch_to_self(void)
|
||||
{
|
||||
printf("Core is in infinite loop due to errors.\n");
|
||||
self:
|
||||
goto self;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_FSL_ISBC_KEY_EXT)
|
||||
static u32 check_ie(struct fsl_secboot_img_priv *img)
|
||||
{
|
||||
if (img->hdr.ie_flag & IE_FLAG_MASK)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* This function returns the CSF Header Address of uboot
|
||||
* For MPC85xx based platforms, the LAW mapping for NOR
|
||||
* flash changes in uboot code. Hence the offset needs
|
||||
* to be calculated and added to the new NOR flash base
|
||||
* address
|
||||
*/
|
||||
#if defined(CONFIG_MPC85xx)
|
||||
int get_csf_base_addr(u32 *csf_addr, u32 *flash_base_addr)
|
||||
{
|
||||
struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR);
|
||||
u32 csf_hdr_addr = in_be32(&gur->scratchrw[0]);
|
||||
u32 csf_flash_offset = csf_hdr_addr & ~(CONFIG_SYS_PBI_FLASH_BASE);
|
||||
u32 flash_addr, addr;
|
||||
int found = 0;
|
||||
int i = 0;
|
||||
|
||||
for (i = 0; i < CONFIG_SYS_MAX_FLASH_BANKS; i++) {
|
||||
flash_addr = flash_info[i].start[0];
|
||||
addr = flash_info[i].start[0] + csf_flash_offset;
|
||||
if (memcmp((u8 *)addr, barker_code, ESBC_BARKER_LEN) == 0) {
|
||||
debug("Barker found on addr %x\n", addr);
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found)
|
||||
return -1;
|
||||
|
||||
*csf_addr = addr;
|
||||
*flash_base_addr = flash_addr;
|
||||
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
/* For platforms like LS1020, correct flash address is present in
|
||||
* the header. So the function reqturns flash base address as 0
|
||||
*/
|
||||
int get_csf_base_addr(u32 *csf_addr, u32 *flash_base_addr)
|
||||
{
|
||||
struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR);
|
||||
u32 csf_hdr_addr = in_be32(&gur->scratchrw[0]);
|
||||
|
||||
if (memcmp((u8 *)(uintptr_t)csf_hdr_addr,
|
||||
barker_code, ESBC_BARKER_LEN))
|
||||
return -1;
|
||||
|
||||
*csf_addr = csf_hdr_addr;
|
||||
*flash_base_addr = 0;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_ESBC_HDR_LS)
|
||||
static int get_ie_info_addr(uintptr_t *ie_addr)
|
||||
{
|
||||
struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR);
|
||||
/* For LS-CH3, the address of IE Table is
|
||||
* stated in Scratch13 and scratch14 of DCFG.
|
||||
* Bootrom validates this table while validating uboot.
|
||||
* DCFG is LE*/
|
||||
*ie_addr = in_le32(&gur->scratchrw[SCRATCH_IE_HIGH_ADR - 1]);
|
||||
*ie_addr = *ie_addr << 32;
|
||||
*ie_addr |= in_le32(&gur->scratchrw[SCRATCH_IE_LOW_ADR - 1]);
|
||||
return 0;
|
||||
}
|
||||
#else /* CONFIG_ESBC_HDR_LS */
|
||||
static int get_ie_info_addr(uintptr_t *ie_addr)
|
||||
{
|
||||
struct fsl_secboot_img_hdr *hdr;
|
||||
struct fsl_secboot_sg_table *sg_tbl;
|
||||
u32 flash_base_addr, csf_addr;
|
||||
|
||||
if (get_csf_base_addr(&csf_addr, &flash_base_addr))
|
||||
return -1;
|
||||
|
||||
hdr = (struct fsl_secboot_img_hdr *)(uintptr_t)csf_addr;
|
||||
|
||||
/* For SoC's with Trust Architecture v1 with corenet bus
|
||||
* the sg table field in CSF header has absolute address
|
||||
* for sg table in memory. In other Trust Architecture,
|
||||
* this field specifies the offset of sg table from the
|
||||
* base address of CSF Header
|
||||
*/
|
||||
#if defined(CONFIG_FSL_TRUST_ARCH_v1) && defined(CONFIG_FSL_CORENET)
|
||||
sg_tbl = (struct fsl_secboot_sg_table *)
|
||||
(((u32)hdr->psgtable & ~(CONFIG_SYS_PBI_FLASH_BASE)) +
|
||||
flash_base_addr);
|
||||
#else
|
||||
sg_tbl = (struct fsl_secboot_sg_table *)(uintptr_t)(csf_addr +
|
||||
(u32)hdr->psgtable);
|
||||
#endif
|
||||
|
||||
/* IE Key Table is the first entry in the SG Table */
|
||||
#if defined(CONFIG_MPC85xx)
|
||||
*ie_addr = (uintptr_t)((sg_tbl->src_addr &
|
||||
~(CONFIG_SYS_PBI_FLASH_BASE)) +
|
||||
flash_base_addr);
|
||||
#else
|
||||
*ie_addr = (uintptr_t)sg_tbl->src_addr;
|
||||
#endif
|
||||
|
||||
debug("IE Table address is %lx\n", *ie_addr);
|
||||
return 0;
|
||||
}
|
||||
#endif /* CONFIG_ESBC_HDR_LS */
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_KEY_REVOCATION
|
||||
/* This function checks srk_table_flag in header and set/reset srk_flag.*/
|
||||
static u32 check_srk(struct fsl_secboot_img_priv *img)
|
||||
{
|
||||
#ifdef CONFIG_ESBC_HDR_LS
|
||||
/* In LS, No SRK Flag as SRK is always present if IE not present*/
|
||||
#if defined(CONFIG_FSL_ISBC_KEY_EXT)
|
||||
return !check_ie(img);
|
||||
#endif
|
||||
return 1;
|
||||
#else
|
||||
if (img->hdr.len_kr.srk_table_flag & SRK_FLAG)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* This function returns ospr's key_revoc values.*/
|
||||
static u32 get_key_revoc(void)
|
||||
{
|
||||
struct ccsr_sfp_regs *sfp_regs = (void *)(CONFIG_SYS_SFP_ADDR);
|
||||
return (sfp_in32(&sfp_regs->ospr) & OSPR_KEY_REVOC_MASK) >>
|
||||
OSPR_KEY_REVOC_SHIFT;
|
||||
}
|
||||
|
||||
/* This function checks if selected key is revoked or not.*/
|
||||
static u32 is_key_revoked(u32 keynum, u32 rev_flag)
|
||||
{
|
||||
if (keynum == UNREVOCABLE_KEY)
|
||||
return 0;
|
||||
|
||||
if ((u32)(1 << (ALIGN_REVOC_KEY - keynum)) & rev_flag)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* It read validates srk_table key lengths.*/
|
||||
static u32 read_validate_srk_tbl(struct fsl_secboot_img_priv *img)
|
||||
{
|
||||
int i = 0;
|
||||
u32 ret, key_num, key_revoc_flag, size;
|
||||
struct fsl_secboot_img_hdr *hdr = &img->hdr;
|
||||
void *esbc = (u8 *)(uintptr_t)img->ehdrloc;
|
||||
|
||||
if ((hdr->len_kr.num_srk == 0) ||
|
||||
(hdr->len_kr.num_srk > MAX_KEY_ENTRIES))
|
||||
return ERROR_ESBC_CLIENT_HEADER_INVALID_SRK_NUM_ENTRY;
|
||||
|
||||
key_num = hdr->len_kr.srk_sel;
|
||||
if (key_num == 0 || key_num > hdr->len_kr.num_srk)
|
||||
return ERROR_ESBC_CLIENT_HEADER_INVALID_KEY_NUM;
|
||||
|
||||
/* Get revoc key from sfp */
|
||||
key_revoc_flag = get_key_revoc();
|
||||
ret = is_key_revoked(key_num, key_revoc_flag);
|
||||
if (ret)
|
||||
return ERROR_ESBC_CLIENT_HEADER_KEY_REVOKED;
|
||||
|
||||
size = hdr->len_kr.num_srk * sizeof(struct srk_table);
|
||||
|
||||
memcpy(&img->srk_tbl, esbc + hdr->srk_tbl_off, size);
|
||||
|
||||
for (i = 0; i < hdr->len_kr.num_srk; i++) {
|
||||
if (!CHECK_KEY_LEN(img->srk_tbl[i].key_len))
|
||||
return ERROR_ESBC_CLIENT_HEADER_INV_SRK_ENTRY_KEYLEN;
|
||||
}
|
||||
|
||||
img->key_len = img->srk_tbl[key_num - 1].key_len;
|
||||
|
||||
memcpy(&img->img_key, &(img->srk_tbl[key_num - 1].pkey),
|
||||
img->key_len);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_ESBC_HDR_LS
|
||||
static u32 read_validate_single_key(struct fsl_secboot_img_priv *img)
|
||||
{
|
||||
struct fsl_secboot_img_hdr *hdr = &img->hdr;
|
||||
void *esbc = (u8 *)(uintptr_t)img->ehdrloc;
|
||||
|
||||
/* check key length */
|
||||
if (!CHECK_KEY_LEN(hdr->key_len))
|
||||
return ERROR_ESBC_CLIENT_HEADER_KEY_LEN;
|
||||
|
||||
memcpy(&img->img_key, esbc + hdr->pkey, hdr->key_len);
|
||||
|
||||
img->key_len = hdr->key_len;
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif /* CONFIG_ESBC_HDR_LS */
|
||||
|
||||
#if defined(CONFIG_FSL_ISBC_KEY_EXT)
|
||||
|
||||
static void install_ie_tbl(uintptr_t ie_tbl_addr,
|
||||
struct fsl_secboot_img_priv *img)
|
||||
{
|
||||
/* Copy IE tbl to Global Data */
|
||||
memcpy(&glb.ie_tbl, (u8 *)ie_tbl_addr, sizeof(struct ie_key_info));
|
||||
img->ie_addr = (uintptr_t)&glb.ie_tbl;
|
||||
glb.ie_addr = img->ie_addr;
|
||||
}
|
||||
|
||||
static u32 read_validate_ie_tbl(struct fsl_secboot_img_priv *img)
|
||||
{
|
||||
struct fsl_secboot_img_hdr *hdr = &img->hdr;
|
||||
u32 ie_key_len, ie_revoc_flag, ie_num;
|
||||
struct ie_key_info *ie_info;
|
||||
|
||||
if (!img->ie_addr) {
|
||||
if (get_ie_info_addr(&img->ie_addr))
|
||||
return ERROR_IE_TABLE_NOT_FOUND;
|
||||
else
|
||||
install_ie_tbl(img->ie_addr, img);
|
||||
}
|
||||
|
||||
ie_info = (struct ie_key_info *)(uintptr_t)img->ie_addr;
|
||||
if (ie_info->num_keys == 0 || ie_info->num_keys > 32)
|
||||
return ERROR_ESBC_CLIENT_HEADER_INVALID_IE_NUM_ENTRY;
|
||||
|
||||
ie_num = hdr->ie_key_sel;
|
||||
if (ie_num == 0 || ie_num > ie_info->num_keys)
|
||||
return ERROR_ESBC_CLIENT_HEADER_INVALID_IE_KEY_NUM;
|
||||
|
||||
ie_revoc_flag = ie_info->key_revok;
|
||||
if ((u32)(1 << (ie_num - 1)) & ie_revoc_flag)
|
||||
return ERROR_ESBC_CLIENT_HEADER_IE_KEY_REVOKED;
|
||||
|
||||
ie_key_len = ie_info->ie_key_tbl[ie_num - 1].key_len;
|
||||
|
||||
if (!CHECK_KEY_LEN(ie_key_len))
|
||||
return ERROR_ESBC_CLIENT_HEADER_INV_IE_ENTRY_KEYLEN;
|
||||
|
||||
memcpy(&img->img_key, &(ie_info->ie_key_tbl[ie_num - 1].pkey),
|
||||
ie_key_len);
|
||||
|
||||
img->key_len = ie_key_len;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/* This function return length of public key.*/
|
||||
static inline u32 get_key_len(struct fsl_secboot_img_priv *img)
|
||||
{
|
||||
return img->key_len;
|
||||
}
|
||||
|
||||
/*
|
||||
* Handles the ESBC uboot client header verification failure.
|
||||
* This function handles all the errors which might occur in the
|
||||
* parsing and checking of ESBC uboot client header. It will also
|
||||
* set the error bits in the SEC_MON.
|
||||
*/
|
||||
static void fsl_secboot_header_verification_failure(void)
|
||||
{
|
||||
struct ccsr_sfp_regs *sfp_regs = (void *)(CONFIG_SYS_SFP_ADDR);
|
||||
|
||||
/* 29th bit of OSPR is ITS */
|
||||
u32 its = sfp_in32(&sfp_regs->ospr) >> 2;
|
||||
|
||||
if (its == 1)
|
||||
set_sec_mon_state(HPSR_SSM_ST_SOFT_FAIL);
|
||||
else
|
||||
set_sec_mon_state(HPSR_SSM_ST_NON_SECURE);
|
||||
|
||||
printf("Generating reset request\n");
|
||||
do_reset(NULL, 0, 0, NULL);
|
||||
/* If reset doesn't coocur, halt execution */
|
||||
do_esbc_halt(NULL, 0, 0, NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Handles the ESBC uboot client image verification failure.
|
||||
* This function handles all the errors which might occur in the
|
||||
* public key hash comparison and signature verification of
|
||||
* ESBC uboot client image. It will also
|
||||
* set the error bits in the SEC_MON.
|
||||
*/
|
||||
static void fsl_secboot_image_verification_failure(void)
|
||||
{
|
||||
struct ccsr_sfp_regs *sfp_regs = (void *)(CONFIG_SYS_SFP_ADDR);
|
||||
|
||||
u32 its = (sfp_in32(&sfp_regs->ospr) & ITS_MASK) >> ITS_BIT;
|
||||
|
||||
if (its == 1) {
|
||||
set_sec_mon_state(HPSR_SSM_ST_SOFT_FAIL);
|
||||
|
||||
printf("Generating reset request\n");
|
||||
do_reset(NULL, 0, 0, NULL);
|
||||
/* If reset doesn't coocur, halt execution */
|
||||
do_esbc_halt(NULL, 0, 0, NULL);
|
||||
|
||||
} else {
|
||||
set_sec_mon_state(HPSR_SSM_ST_NON_SECURE);
|
||||
}
|
||||
}
|
||||
|
||||
static void fsl_secboot_bootscript_parse_failure(void)
|
||||
{
|
||||
fsl_secboot_header_verification_failure();
|
||||
}
|
||||
|
||||
/*
|
||||
* Handles the errors in esbc boot.
|
||||
* This function handles all the errors which might occur in the
|
||||
* esbc boot phase. It will call the appropriate api to log the
|
||||
* errors and set the error bits in the SEC_MON.
|
||||
*/
|
||||
void fsl_secboot_handle_error(int error)
|
||||
{
|
||||
#ifndef CONFIG_SPL_BUILD
|
||||
const struct fsl_secboot_errcode *e;
|
||||
|
||||
for (e = fsl_secboot_errcodes; e->errcode != ERROR_ESBC_CLIENT_MAX;
|
||||
e++) {
|
||||
if (e->errcode == error)
|
||||
printf("ERROR :: %x :: %s\n", error, e->name);
|
||||
}
|
||||
#else
|
||||
printf("ERROR :: %x\n", error);
|
||||
#endif
|
||||
|
||||
/* If Boot Mode is secure, transition the SNVS state and issue
|
||||
* reset based on type of failure and ITS setting.
|
||||
* If Boot mode is non-secure, return from this function.
|
||||
*/
|
||||
if (fsl_check_boot_mode_secure() == 0)
|
||||
return;
|
||||
|
||||
switch (error) {
|
||||
case ERROR_ESBC_CLIENT_HEADER_BARKER:
|
||||
case ERROR_ESBC_CLIENT_HEADER_IMG_SIZE:
|
||||
case ERROR_ESBC_CLIENT_HEADER_KEY_LEN:
|
||||
case ERROR_ESBC_CLIENT_HEADER_SIG_LEN:
|
||||
case ERROR_ESBC_CLIENT_HEADER_KEY_LEN_NOT_TWICE_SIG_LEN:
|
||||
case ERROR_ESBC_CLIENT_HEADER_KEY_MOD_1:
|
||||
case ERROR_ESBC_CLIENT_HEADER_KEY_MOD_2:
|
||||
case ERROR_ESBC_CLIENT_HEADER_SIG_KEY_MOD:
|
||||
case ERROR_ESBC_CLIENT_HEADER_SG_ESBC_EP:
|
||||
case ERROR_ESBC_CLIENT_HEADER_SG_ENTIRES_BAD:
|
||||
case ERROR_KEY_TABLE_NOT_FOUND:
|
||||
#ifdef CONFIG_KEY_REVOCATION
|
||||
case ERROR_ESBC_CLIENT_HEADER_KEY_REVOKED:
|
||||
case ERROR_ESBC_CLIENT_HEADER_INVALID_SRK_NUM_ENTRY:
|
||||
case ERROR_ESBC_CLIENT_HEADER_INVALID_KEY_NUM:
|
||||
case ERROR_ESBC_CLIENT_HEADER_INV_SRK_ENTRY_KEYLEN:
|
||||
#endif
|
||||
#if defined(CONFIG_FSL_ISBC_KEY_EXT)
|
||||
/*@fallthrough@*/
|
||||
case ERROR_ESBC_CLIENT_HEADER_IE_KEY_REVOKED:
|
||||
case ERROR_ESBC_CLIENT_HEADER_INVALID_IE_NUM_ENTRY:
|
||||
case ERROR_ESBC_CLIENT_HEADER_INVALID_IE_KEY_NUM:
|
||||
case ERROR_ESBC_CLIENT_HEADER_INV_IE_ENTRY_KEYLEN:
|
||||
case ERROR_IE_TABLE_NOT_FOUND:
|
||||
#endif
|
||||
fsl_secboot_header_verification_failure();
|
||||
break;
|
||||
case ERROR_ESBC_SEC_RESET:
|
||||
case ERROR_ESBC_SEC_DEQ:
|
||||
case ERROR_ESBC_SEC_ENQ:
|
||||
case ERROR_ESBC_SEC_DEQ_TO:
|
||||
case ERROR_ESBC_SEC_JOBQ_STATUS:
|
||||
case ERROR_ESBC_CLIENT_HASH_COMPARE_KEY:
|
||||
case ERROR_ESBC_CLIENT_HASH_COMPARE_EM:
|
||||
fsl_secboot_image_verification_failure();
|
||||
break;
|
||||
case ERROR_ESBC_MISSING_BOOTM:
|
||||
fsl_secboot_bootscript_parse_failure();
|
||||
break;
|
||||
case ERROR_ESBC_WRONG_CMD:
|
||||
default:
|
||||
branch_to_self();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void fsl_secblk_handle_error(int error)
|
||||
{
|
||||
switch (error) {
|
||||
case ERROR_ESBC_SEC_ENQ:
|
||||
fsl_secboot_handle_error(ERROR_ESBC_SEC_ENQ);
|
||||
break;
|
||||
case ERROR_ESBC_SEC_DEQ:
|
||||
fsl_secboot_handle_error(ERROR_ESBC_SEC_DEQ);
|
||||
break;
|
||||
case ERROR_ESBC_SEC_DEQ_TO:
|
||||
fsl_secboot_handle_error(ERROR_ESBC_SEC_DEQ_TO);
|
||||
break;
|
||||
default:
|
||||
printf("Job Queue Output status %x\n", error);
|
||||
fsl_secboot_handle_error(ERROR_ESBC_SEC_JOBQ_STATUS);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Calculate hash of key obtained via offset present in ESBC uboot
|
||||
* client hdr. This function calculates the hash of key which is obtained
|
||||
* through offset present in ESBC uboot client header.
|
||||
*/
|
||||
static int calc_img_key_hash(struct fsl_secboot_img_priv *img)
|
||||
{
|
||||
struct hash_algo *algo;
|
||||
void *ctx;
|
||||
int i, srk = 0;
|
||||
int ret = 0;
|
||||
const char *algo_name = "sha256";
|
||||
|
||||
/* Calculate hash of the esbc key */
|
||||
ret = hash_progressive_lookup_algo(algo_name, &algo);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = algo->hash_init(algo, &ctx);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Update hash for ESBC key */
|
||||
#ifdef CONFIG_KEY_REVOCATION
|
||||
if (check_srk(img)) {
|
||||
ret = algo->hash_update(algo, ctx,
|
||||
(u8 *)(uintptr_t)(img->ehdrloc + img->hdr.srk_tbl_off),
|
||||
img->hdr.len_kr.num_srk * sizeof(struct srk_table), 1);
|
||||
srk = 1;
|
||||
}
|
||||
#endif
|
||||
if (!srk)
|
||||
ret = algo->hash_update(algo, ctx,
|
||||
img->img_key, img->key_len, 1);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Copy hash at destination buffer */
|
||||
ret = algo->hash_finish(algo, ctx, hash_val, algo->digest_size);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
for (i = 0; i < SHA256_BYTES; i++)
|
||||
img->img_key_hash[i] = hash_val[i];
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Calculate hash of ESBC hdr and ESBC. This function calculates the
|
||||
* single hash of ESBC header and ESBC image. If SG flag is on, all
|
||||
* SG entries are also hashed alongwith the complete SG table.
|
||||
*/
|
||||
static int calc_esbchdr_esbc_hash(struct fsl_secboot_img_priv *img)
|
||||
{
|
||||
struct hash_algo *algo;
|
||||
void *ctx;
|
||||
int ret = 0;
|
||||
int key_hash = 0;
|
||||
const char *algo_name = "sha256";
|
||||
|
||||
/* Calculate the hash of the ESBC */
|
||||
ret = hash_progressive_lookup_algo(algo_name, &algo);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = algo->hash_init(algo, &ctx);
|
||||
/* Copy hash at destination buffer */
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Update hash for CSF Header */
|
||||
ret = algo->hash_update(algo, ctx,
|
||||
(u8 *)&img->hdr, sizeof(struct fsl_secboot_img_hdr), 0);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Update the hash with that of srk table if srk flag is 1
|
||||
* If IE Table is selected, key is not added in the hash
|
||||
* If neither srk table nor IE key table available, add key
|
||||
* from header in the hash calculation
|
||||
*/
|
||||
#ifdef CONFIG_KEY_REVOCATION
|
||||
if (check_srk(img)) {
|
||||
ret = algo->hash_update(algo, ctx,
|
||||
(u8 *)(uintptr_t)(img->ehdrloc + img->hdr.srk_tbl_off),
|
||||
img->hdr.len_kr.num_srk * sizeof(struct srk_table), 0);
|
||||
key_hash = 1;
|
||||
}
|
||||
#endif
|
||||
#if defined(CONFIG_FSL_ISBC_KEY_EXT)
|
||||
if (!key_hash && check_ie(img))
|
||||
key_hash = 1;
|
||||
#endif
|
||||
#ifndef CONFIG_ESBC_HDR_LS
|
||||
/* No single key support in LS ESBC header */
|
||||
if (!key_hash) {
|
||||
ret = algo->hash_update(algo, ctx,
|
||||
img->img_key, img->hdr.key_len, 0);
|
||||
key_hash = 1;
|
||||
}
|
||||
#endif
|
||||
if (ret)
|
||||
return ret;
|
||||
if (!key_hash)
|
||||
return ERROR_KEY_TABLE_NOT_FOUND;
|
||||
|
||||
/* Update hash for actual Image */
|
||||
ret = algo->hash_update(algo, ctx,
|
||||
(u8 *)(*(img->img_addr_ptr)), img->img_size, 1);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Copy hash at destination buffer */
|
||||
ret = algo->hash_finish(algo, ctx, hash_val, algo->digest_size);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Construct encoded hash EM' wrt PKCSv1.5. This function calculates the
|
||||
* pointers for padding, DER value and hash. And finally, constructs EM'
|
||||
* which includes hash of complete CSF header and ESBC image. If SG flag
|
||||
* is on, hash of SG table and entries is also included.
|
||||
*/
|
||||
static void construct_img_encoded_hash_second(struct fsl_secboot_img_priv *img)
|
||||
{
|
||||
/*
|
||||
* RSA PKCSv1.5 encoding format for encoded message is below
|
||||
* EM = 0x0 || 0x1 || PS || 0x0 || DER || Hash
|
||||
* PS is Padding String
|
||||
* DER is DER value for SHA-256
|
||||
* Hash is SHA-256 hash
|
||||
* *********************************************************
|
||||
* representative points to first byte of EM initially and is
|
||||
* filled with 0x0
|
||||
* representative is incremented by 1 and second byte is filled
|
||||
* with 0x1
|
||||
* padding points to third byte of EM
|
||||
* digest points to full length of EM - 32 bytes
|
||||
* hash_id (DER value) points to 19 bytes before pDigest
|
||||
* separator is one byte which separates padding and DER
|
||||
*/
|
||||
|
||||
size_t len;
|
||||
u8 *representative;
|
||||
u8 *padding, *digest;
|
||||
u8 *hash_id, *separator;
|
||||
int i;
|
||||
|
||||
len = (get_key_len(img) / 2) - 1;
|
||||
representative = img->img_encoded_hash_second;
|
||||
representative[0] = 0;
|
||||
representative[1] = 1; /* block type 1 */
|
||||
|
||||
padding = &representative[2];
|
||||
digest = &representative[1] + len - 32;
|
||||
hash_id = digest - sizeof(hash_identifier);
|
||||
separator = hash_id - 1;
|
||||
|
||||
/* fill padding area pointed by padding with 0xff */
|
||||
memset(padding, 0xff, separator - padding);
|
||||
|
||||
/* fill byte pointed by separator */
|
||||
*separator = 0;
|
||||
|
||||
/* fill SHA-256 DER value pointed by HashId */
|
||||
memcpy(hash_id, hash_identifier, sizeof(hash_identifier));
|
||||
|
||||
/* fill hash pointed by Digest */
|
||||
for (i = 0; i < SHA256_BYTES; i++)
|
||||
digest[i] = hash_val[i];
|
||||
}
|
||||
|
||||
/*
|
||||
* Reads and validates the ESBC client header.
|
||||
* This function reads key and signature from the ESBC client header.
|
||||
* If Scatter/Gather flag is on, lengths and offsets of images
|
||||
* present as SG entries are also read. This function also checks
|
||||
* whether the header is valid or not.
|
||||
*/
|
||||
static int read_validate_esbc_client_header(struct fsl_secboot_img_priv *img)
|
||||
{
|
||||
struct fsl_secboot_img_hdr *hdr = &img->hdr;
|
||||
void *esbc = (u8 *)(uintptr_t)img->ehdrloc;
|
||||
u8 *k, *s;
|
||||
u32 ret = 0;
|
||||
|
||||
int key_found = 0;
|
||||
|
||||
/* check barker code */
|
||||
if (memcmp(hdr->barker, barker_code, ESBC_BARKER_LEN))
|
||||
return ERROR_ESBC_CLIENT_HEADER_BARKER;
|
||||
|
||||
/* If Image Address is not passed as argument to function,
|
||||
* then Address and Size must be read from the Header.
|
||||
*/
|
||||
if (*(img->img_addr_ptr) == 0) {
|
||||
#ifdef CONFIG_ESBC_ADDR_64BIT
|
||||
*(img->img_addr_ptr) = hdr->pimg64;
|
||||
#else
|
||||
*(img->img_addr_ptr) = hdr->pimg;
|
||||
#endif
|
||||
}
|
||||
|
||||
if (!hdr->img_size)
|
||||
return ERROR_ESBC_CLIENT_HEADER_IMG_SIZE;
|
||||
|
||||
img->img_size = hdr->img_size;
|
||||
|
||||
/* Key checking*/
|
||||
#ifdef CONFIG_KEY_REVOCATION
|
||||
if (check_srk(img)) {
|
||||
ret = read_validate_srk_tbl(img);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
key_found = 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_FSL_ISBC_KEY_EXT)
|
||||
if (!key_found && check_ie(img)) {
|
||||
ret = read_validate_ie_tbl(img);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
key_found = 1;
|
||||
}
|
||||
#endif
|
||||
#ifndef CONFIG_ESBC_HDR_LS
|
||||
/* Single Key Feature not available in LS ESBC Header */
|
||||
if (key_found == 0) {
|
||||
ret = read_validate_single_key(img);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
key_found = 1;
|
||||
}
|
||||
#endif
|
||||
if (!key_found)
|
||||
return ERROR_KEY_TABLE_NOT_FOUND;
|
||||
|
||||
/* check signaure */
|
||||
if (get_key_len(img) == 2 * hdr->sign_len) {
|
||||
/* check signature length */
|
||||
if (!((hdr->sign_len == KEY_SIZE_BYTES / 4) ||
|
||||
(hdr->sign_len == KEY_SIZE_BYTES / 2) ||
|
||||
(hdr->sign_len == KEY_SIZE_BYTES)))
|
||||
return ERROR_ESBC_CLIENT_HEADER_SIG_LEN;
|
||||
} else {
|
||||
return ERROR_ESBC_CLIENT_HEADER_KEY_LEN_NOT_TWICE_SIG_LEN;
|
||||
}
|
||||
|
||||
memcpy(&img->img_sign, esbc + hdr->psign, hdr->sign_len);
|
||||
/* No SG support in LS-CH3 */
|
||||
#ifndef CONFIG_ESBC_HDR_LS
|
||||
/* No SG support */
|
||||
if (hdr->sg_flag)
|
||||
return ERROR_ESBC_CLIENT_HEADER_SG;
|
||||
#endif
|
||||
|
||||
/* modulus most significant bit should be set */
|
||||
k = (u8 *)&img->img_key;
|
||||
|
||||
if ((k[0] & 0x80) == 0)
|
||||
return ERROR_ESBC_CLIENT_HEADER_KEY_MOD_1;
|
||||
|
||||
/* modulus value should be odd */
|
||||
if ((k[get_key_len(img) / 2 - 1] & 0x1) == 0)
|
||||
return ERROR_ESBC_CLIENT_HEADER_KEY_MOD_2;
|
||||
|
||||
/* Check signature value < modulus value */
|
||||
s = (u8 *)&img->img_sign;
|
||||
|
||||
if (!(memcmp(s, k, hdr->sign_len) < 0))
|
||||
return ERROR_ESBC_CLIENT_HEADER_SIG_KEY_MOD;
|
||||
|
||||
return ESBC_VALID_HDR;
|
||||
}
|
||||
|
||||
static inline int str2longbe(const char *p, ulong *num)
|
||||
{
|
||||
char *endptr;
|
||||
ulong tmp;
|
||||
|
||||
if (!p) {
|
||||
return 0;
|
||||
} else {
|
||||
tmp = simple_strtoul(p, &endptr, 16);
|
||||
if (sizeof(ulong) == 4)
|
||||
*num = cpu_to_be32(tmp);
|
||||
else
|
||||
*num = cpu_to_be64(tmp);
|
||||
}
|
||||
|
||||
return *p != '\0' && *endptr == '\0';
|
||||
}
|
||||
/* Function to calculate the ESBC Image Hash
|
||||
* and hash from Digital signature.
|
||||
* The Two hash's are compared to yield the
|
||||
* result of signature validation.
|
||||
*/
|
||||
static int calculate_cmp_img_sig(struct fsl_secboot_img_priv *img)
|
||||
{
|
||||
int ret;
|
||||
uint32_t key_len;
|
||||
struct key_prop prop;
|
||||
#if !defined(USE_HOSTCC)
|
||||
struct udevice *mod_exp_dev;
|
||||
#endif
|
||||
ret = calc_esbchdr_esbc_hash(img);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Construct encoded hash EM' wrt PKCSv1.5 */
|
||||
construct_img_encoded_hash_second(img);
|
||||
|
||||
/* Fill prop structure for public key */
|
||||
memset(&prop, 0, sizeof(struct key_prop));
|
||||
key_len = get_key_len(img) / 2;
|
||||
prop.modulus = img->img_key;
|
||||
prop.public_exponent = img->img_key + key_len;
|
||||
prop.num_bits = key_len * 8;
|
||||
prop.exp_len = key_len;
|
||||
|
||||
ret = uclass_get_device(UCLASS_MOD_EXP, 0, &mod_exp_dev);
|
||||
if (ret) {
|
||||
printf("RSA: Can't find Modular Exp implementation\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = rsa_mod_exp(mod_exp_dev, img->img_sign, img->hdr.sign_len,
|
||||
&prop, img->img_encoded_hash);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/*
|
||||
* compare the encoded messages EM' and EM wrt RSA PKCSv1.5
|
||||
* memcmp returns zero on success
|
||||
* memcmp returns non-zero on failure
|
||||
*/
|
||||
ret = memcmp(&img->img_encoded_hash_second, &img->img_encoded_hash,
|
||||
img->hdr.sign_len);
|
||||
|
||||
if (ret)
|
||||
return ERROR_ESBC_CLIENT_HASH_COMPARE_EM;
|
||||
|
||||
return 0;
|
||||
}
|
||||
/* Function to initialize img priv and global data structure
|
||||
*/
|
||||
static int secboot_init(struct fsl_secboot_img_priv **img_ptr)
|
||||
{
|
||||
*img_ptr = malloc(sizeof(struct fsl_secboot_img_priv));
|
||||
|
||||
struct fsl_secboot_img_priv *img = *img_ptr;
|
||||
|
||||
if (!img)
|
||||
return -ENOMEM;
|
||||
memset(img, 0, sizeof(struct fsl_secboot_img_priv));
|
||||
|
||||
#if defined(CONFIG_FSL_ISBC_KEY_EXT)
|
||||
if (glb.ie_addr)
|
||||
img->ie_addr = glb.ie_addr;
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* haddr - Address of the header of image to be validated.
|
||||
* arg_hash_str - Option hash string. If provided, this
|
||||
* overrides the key hash in the SFP fuses.
|
||||
* img_addr_ptr - Optional pointer to address of image to be validated.
|
||||
* If non zero addr, this overrides the addr of image in header,
|
||||
* otherwise updated to image addr in header.
|
||||
* Acts as both input and output of function.
|
||||
* This pointer shouldn't be NULL.
|
||||
*/
|
||||
int fsl_secboot_validate(uintptr_t haddr, char *arg_hash_str,
|
||||
uintptr_t *img_addr_ptr)
|
||||
{
|
||||
struct ccsr_sfp_regs *sfp_regs = (void *)(CONFIG_SYS_SFP_ADDR);
|
||||
ulong hash[SHA256_BYTES/sizeof(ulong)];
|
||||
char hash_str[NUM_HEX_CHARS + 1];
|
||||
struct fsl_secboot_img_priv *img;
|
||||
struct fsl_secboot_img_hdr *hdr;
|
||||
void *esbc;
|
||||
int ret, i, hash_cmd = 0;
|
||||
u32 srk_hash[8];
|
||||
|
||||
if (arg_hash_str != NULL) {
|
||||
const char *cp = arg_hash_str;
|
||||
int i = 0;
|
||||
|
||||
if (*cp == '0' && *(cp + 1) == 'x')
|
||||
cp += 2;
|
||||
|
||||
/* The input string expected is in hex, where
|
||||
* each 4 bits would be represented by a hex
|
||||
* sha256 hash is 256 bits long, which would mean
|
||||
* num of characters = 256 / 4
|
||||
*/
|
||||
if (strlen(cp) != SHA256_NIBBLES) {
|
||||
printf("%s is not a 256 bits hex string as expected\n",
|
||||
arg_hash_str);
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (i = 0; i < sizeof(hash)/sizeof(ulong); i++) {
|
||||
strncpy(hash_str, cp + (i * NUM_HEX_CHARS),
|
||||
NUM_HEX_CHARS);
|
||||
hash_str[NUM_HEX_CHARS] = '\0';
|
||||
if (!str2longbe(hash_str, &hash[i])) {
|
||||
printf("%s is not a 256 bits hex string ",
|
||||
arg_hash_str);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
hash_cmd = 1;
|
||||
}
|
||||
|
||||
ret = secboot_init(&img);
|
||||
if (ret)
|
||||
goto exit;
|
||||
|
||||
/* Update the information in Private Struct */
|
||||
hdr = &img->hdr;
|
||||
img->ehdrloc = haddr;
|
||||
img->img_addr_ptr = img_addr_ptr;
|
||||
esbc = (u8 *)img->ehdrloc;
|
||||
|
||||
memcpy(hdr, esbc, sizeof(struct fsl_secboot_img_hdr));
|
||||
|
||||
/* read and validate esbc header */
|
||||
ret = read_validate_esbc_client_header(img);
|
||||
|
||||
if (ret != ESBC_VALID_HDR) {
|
||||
fsl_secboot_handle_error(ret);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/* SRKH present in SFP */
|
||||
for (i = 0; i < NUM_SRKH_REGS; i++)
|
||||
srk_hash[i] = srk_in32(&sfp_regs->srk_hash[i]);
|
||||
|
||||
/*
|
||||
* Calculate hash of key obtained via offset present in
|
||||
* ESBC uboot client hdr
|
||||
*/
|
||||
ret = calc_img_key_hash(img);
|
||||
if (ret) {
|
||||
fsl_secblk_handle_error(ret);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/* Compare hash obtained above with SRK hash present in SFP */
|
||||
if (hash_cmd)
|
||||
ret = memcmp(&hash, &img->img_key_hash, SHA256_BYTES);
|
||||
else
|
||||
ret = memcmp(srk_hash, img->img_key_hash, SHA256_BYTES);
|
||||
|
||||
#if defined(CONFIG_FSL_ISBC_KEY_EXT)
|
||||
if (!hash_cmd && check_ie(img))
|
||||
ret = 0;
|
||||
#endif
|
||||
|
||||
if (ret != 0) {
|
||||
fsl_secboot_handle_error(ERROR_ESBC_CLIENT_HASH_COMPARE_KEY);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
ret = calculate_cmp_img_sig(img);
|
||||
if (ret) {
|
||||
fsl_secboot_handle_error(ret);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
exit:
|
||||
/* Free Img as it was malloc'ed*/
|
||||
free(img);
|
||||
return ret;
|
||||
}
|
||||
@@ -0,0 +1,145 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Copyright 2010-2011 Freescale Semiconductor, Inc.
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <asm/io.h>
|
||||
|
||||
#include "ics307_clk.h"
|
||||
|
||||
#if defined(CONFIG_FSL_NGPIXIS)
|
||||
#include "ngpixis.h"
|
||||
#define fpga_reg pixis
|
||||
#elif defined(CONFIG_FSL_QIXIS)
|
||||
#include "qixis.h"
|
||||
#define fpga_reg ((struct qixis *)QIXIS_BASE)
|
||||
#else
|
||||
#include "pixis.h"
|
||||
#define fpga_reg pixis
|
||||
#endif
|
||||
|
||||
/* define for SYS CLK or CLK1Frequency */
|
||||
#define TTL 1
|
||||
#define CLK2 0
|
||||
#define CRYSTAL 0
|
||||
#define MAX_VDW (511 + 8)
|
||||
#define MAX_RDW (127 + 2)
|
||||
#define MIN_VDW (4 + 8)
|
||||
#define MIN_RDW (1 + 2)
|
||||
#define NUM_OD_SETTING 8
|
||||
/*
|
||||
* These defines cover the industrial temperature range part,
|
||||
* for commercial, change below to 400000 and 55000, respectively
|
||||
*/
|
||||
#define MAX_VCO 360000
|
||||
#define MIN_VCO 60000
|
||||
|
||||
/* decode S[0-2] to Output Divider (OD) */
|
||||
static u8 ics307_s_to_od[] = {
|
||||
10, 2, 8, 4, 5, 7, 3, 6
|
||||
};
|
||||
|
||||
/*
|
||||
* Find one solution to generate required frequency for SYSCLK
|
||||
* out_freq: KHz, required frequency to the SYSCLK
|
||||
* the result will be retuned with component RDW, VDW, OD, TTL,
|
||||
* CLK2 and crystal
|
||||
*/
|
||||
unsigned long ics307_sysclk_calculator(unsigned long out_freq)
|
||||
{
|
||||
const unsigned long input_freq = CONFIG_ICS307_REFCLK_HZ;
|
||||
unsigned long vdw, rdw, odp, s_vdw = 0, s_rdw = 0, s_odp = 0, od;
|
||||
unsigned long tmp_out, diff, result = 0;
|
||||
int found = 0;
|
||||
|
||||
for (odp = 0; odp < NUM_OD_SETTING; odp++) {
|
||||
od = ics307_s_to_od[odp];
|
||||
if (od * out_freq < MIN_VCO || od * out_freq > MAX_VCO)
|
||||
continue;
|
||||
for (rdw = MIN_RDW; rdw <= MAX_RDW; rdw++) {
|
||||
/* Calculate the VDW */
|
||||
vdw = out_freq * 1000 * od * rdw / (input_freq * 2);
|
||||
if (vdw > MAX_VDW)
|
||||
vdw = MAX_VDW;
|
||||
if (vdw < MIN_VDW)
|
||||
continue;
|
||||
/* Calculate the temp out frequency */
|
||||
tmp_out = input_freq * 2 * vdw / (rdw * od * 1000);
|
||||
diff = max(out_freq, tmp_out) - min(out_freq, tmp_out);
|
||||
/*
|
||||
* calculate the percent, the precision is 1/1000
|
||||
* If greater than 1/1000, continue
|
||||
* otherwise, we think the solution is we required
|
||||
*/
|
||||
if (diff * 1000 / out_freq > 1)
|
||||
continue;
|
||||
else {
|
||||
s_vdw = vdw;
|
||||
s_rdw = rdw;
|
||||
s_odp = odp;
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (found)
|
||||
result = (s_rdw - 2) | (s_vdw - 8) << 7 | s_odp << 16 |
|
||||
CLK2 << 19 | TTL << 21 | CRYSTAL << 22;
|
||||
|
||||
debug("ICS307-02: RDW: %ld, VDW: %ld, OD: %d\n", s_rdw - 2, s_vdw - 8,
|
||||
ics307_s_to_od[s_odp]);
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* Calculate frequency being generated by ICS307-02 clock chip based upon
|
||||
* the control bytes being programmed into it.
|
||||
*/
|
||||
static unsigned long ics307_clk_freq(u8 cw0, u8 cw1, u8 cw2)
|
||||
{
|
||||
const unsigned long input_freq = CONFIG_ICS307_REFCLK_HZ;
|
||||
unsigned long vdw = ((cw1 << 1) & 0x1FE) + ((cw2 >> 7) & 1);
|
||||
unsigned long rdw = cw2 & 0x7F;
|
||||
unsigned long od = ics307_s_to_od[cw0 & 0x7];
|
||||
unsigned long freq;
|
||||
|
||||
/*
|
||||
* CLK1 Freq = Input Frequency * 2 * (VDW + 8) / ((RDW + 2) * OD)
|
||||
*
|
||||
* cw0: C1 C0 TTL F1 F0 S2 S1 S0
|
||||
* cw1: V8 V7 V6 V5 V4 V3 V2 V1
|
||||
* cw2: V0 R6 R5 R4 R3 R2 R1 R0
|
||||
*
|
||||
* R6:R0 = Reference Divider Word (RDW)
|
||||
* V8:V0 = VCO Divider Word (VDW)
|
||||
* S2:S0 = Output Divider Select (OD)
|
||||
* F1:F0 = Function of CLK2 Output
|
||||
* TTL = duty cycle
|
||||
* C1:C0 = internal load capacitance for cyrstal
|
||||
*
|
||||
*/
|
||||
|
||||
freq = input_freq * 2 * (vdw + 8) / ((rdw + 2) * od);
|
||||
|
||||
debug("ICS307: CW[0-2]: %02X %02X %02X => %lu Hz\n", cw0, cw1, cw2,
|
||||
freq);
|
||||
return freq;
|
||||
}
|
||||
|
||||
unsigned long get_board_sys_clk(void)
|
||||
{
|
||||
return ics307_clk_freq(
|
||||
in_8(&fpga_reg->sclk[0]),
|
||||
in_8(&fpga_reg->sclk[1]),
|
||||
in_8(&fpga_reg->sclk[2]));
|
||||
}
|
||||
|
||||
unsigned long get_board_ddr_clk(void)
|
||||
{
|
||||
return ics307_clk_freq(
|
||||
in_8(&fpga_reg->dclk[0]),
|
||||
in_8(&fpga_reg->dclk[1]),
|
||||
in_8(&fpga_reg->dclk[2]));
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||
/*
|
||||
* Copyright 2010-2011 Freescale Semiconductor, Inc.
|
||||
*/
|
||||
#ifndef __ICS_CLK_H_
|
||||
#define __ICS_CLK_H_ 1
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
extern unsigned long get_board_sys_clk(void);
|
||||
extern unsigned long get_board_ddr_clk(void);
|
||||
extern unsigned long ics307_sysclk_calculator(unsigned long out_freq);
|
||||
#endif
|
||||
|
||||
#endif /* __ICS_CLK_H_ */
|
||||
@@ -0,0 +1,206 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Copyright 2013 Freescale Semiconductor, Inc.
|
||||
* Author: Shaveta Leekha <shaveta@freescale.com>
|
||||
*/
|
||||
|
||||
#include "idt8t49n222a_serdes_clk.h"
|
||||
|
||||
#define DEVICE_ID_REG 0x00
|
||||
|
||||
static int check_pll_status(u8 idt_addr)
|
||||
{
|
||||
u8 val = 0;
|
||||
int ret;
|
||||
|
||||
ret = i2c_read(idt_addr, 0x17, 1, &val, 1);
|
||||
if (ret < 0) {
|
||||
printf("IDT:0x%x could not read status register from device.\n",
|
||||
idt_addr);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (val & 0x04) {
|
||||
debug("idt8t49n222a PLL is LOCKED: %x\n", val);
|
||||
} else {
|
||||
printf("idt8t49n222a PLL is not LOCKED: %x\n", val);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int set_serdes_refclk(u8 idt_addr, u8 serdes_num,
|
||||
enum serdes_refclk refclk1,
|
||||
enum serdes_refclk refclk2, u8 feedback)
|
||||
{
|
||||
u8 dev_id = 0;
|
||||
int i, ret;
|
||||
|
||||
debug("IDT:Configuring idt8t49n222a device at I2C address: 0x%2x\n",
|
||||
idt_addr);
|
||||
|
||||
ret = i2c_read(idt_addr, DEVICE_ID_REG, 1, &dev_id, 1);
|
||||
if (ret < 0) {
|
||||
debug("IDT:0x%x could not read DEV_ID from device.\n",
|
||||
idt_addr);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if ((dev_id != 0x00) && (dev_id != 0x24) && (dev_id != 0x2a)) {
|
||||
debug("IDT: device at address 0x%x is not idt8t49n222a.\n",
|
||||
idt_addr);
|
||||
}
|
||||
|
||||
if (serdes_num != 1 && serdes_num != 2) {
|
||||
debug("serdes_num should be 1 for SerDes1 and"
|
||||
" 2 for SerDes2.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((refclk1 == SERDES_REFCLK_122_88 && refclk2 != SERDES_REFCLK_122_88)
|
||||
|| (refclk1 != SERDES_REFCLK_122_88
|
||||
&& refclk2 == SERDES_REFCLK_122_88)) {
|
||||
debug("Only one refclk at 122.88MHz is not supported."
|
||||
" Please set both refclk1 & refclk2 to 122.88MHz"
|
||||
" or both not to 122.88MHz.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (refclk1 != SERDES_REFCLK_100 && refclk1 != SERDES_REFCLK_122_88
|
||||
&& refclk1 != SERDES_REFCLK_125
|
||||
&& refclk1 != SERDES_REFCLK_156_25) {
|
||||
debug("refclk1 should be 100MHZ, 122.88MHz, 125MHz"
|
||||
" or 156.25MHz.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (refclk2 != SERDES_REFCLK_100 && refclk2 != SERDES_REFCLK_122_88
|
||||
&& refclk2 != SERDES_REFCLK_125
|
||||
&& refclk2 != SERDES_REFCLK_156_25) {
|
||||
debug("refclk2 should be 100MHZ, 122.88MHz, 125MHz"
|
||||
" or 156.25MHz.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (feedback != 0 && feedback != 1) {
|
||||
debug("valid values for feedback are 0(default) or 1.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Configuring IDT for output refclks as
|
||||
* Refclk1 = 122.88MHz Refclk2 = 122.88MHz
|
||||
*/
|
||||
if (refclk1 == SERDES_REFCLK_122_88 &&
|
||||
refclk2 == SERDES_REFCLK_122_88) {
|
||||
printf("Setting refclk1:122.88 and refclk2:122.88\n");
|
||||
for (i = 0; i < NUM_IDT_REGS; i++)
|
||||
i2c_reg_write(idt_addr, idt_conf_122_88[i][0],
|
||||
idt_conf_122_88[i][1]);
|
||||
|
||||
if (feedback) {
|
||||
for (i = 0; i < NUM_IDT_REGS_FEEDBACK; i++)
|
||||
i2c_reg_write(idt_addr,
|
||||
idt_conf_122_88_feedback[i][0],
|
||||
idt_conf_122_88_feedback[i][1]);
|
||||
}
|
||||
}
|
||||
|
||||
if (refclk1 != SERDES_REFCLK_122_88 &&
|
||||
refclk2 != SERDES_REFCLK_122_88) {
|
||||
for (i = 0; i < NUM_IDT_REGS; i++)
|
||||
i2c_reg_write(idt_addr, idt_conf_not_122_88[i][0],
|
||||
idt_conf_not_122_88[i][1]);
|
||||
}
|
||||
|
||||
/* Configuring IDT for output refclks as
|
||||
* Refclk1 = 100MHz Refclk2 = 125MHz
|
||||
*/
|
||||
if (refclk1 == SERDES_REFCLK_100 && refclk2 == SERDES_REFCLK_125) {
|
||||
printf("Setting refclk1:100 and refclk2:125\n");
|
||||
i2c_reg_write(idt_addr, 0x11, 0x10);
|
||||
}
|
||||
|
||||
/* Configuring IDT for output refclks as
|
||||
* Refclk1 = 125MHz Refclk2 = 125MHz
|
||||
*/
|
||||
if (refclk1 == SERDES_REFCLK_125 && refclk2 == SERDES_REFCLK_125) {
|
||||
printf("Setting refclk1:125 and refclk2:125\n");
|
||||
i2c_reg_write(idt_addr, 0x10, 0x10);
|
||||
i2c_reg_write(idt_addr, 0x11, 0x10);
|
||||
}
|
||||
|
||||
/* Configuring IDT for output refclks as
|
||||
* Refclk1 = 125MHz Refclk2 = 100MHz
|
||||
*/
|
||||
if (refclk1 == SERDES_REFCLK_125 && refclk2 == SERDES_REFCLK_100) {
|
||||
printf("Setting refclk1:125 and refclk2:100\n");
|
||||
i2c_reg_write(idt_addr, 0x10, 0x10);
|
||||
}
|
||||
|
||||
/* Configuring IDT for output refclks as
|
||||
* Refclk1 = 156.25MHz Refclk2 = 156.25MHz
|
||||
*/
|
||||
if (refclk1 == SERDES_REFCLK_156_25 &&
|
||||
refclk2 == SERDES_REFCLK_156_25) {
|
||||
printf("Setting refclk1:156.25 and refclk2:156.25\n");
|
||||
for (i = 0; i < NUM_IDT_REGS_156_25; i++)
|
||||
i2c_reg_write(idt_addr, idt_conf_156_25[i][0],
|
||||
idt_conf_156_25[i][1]);
|
||||
}
|
||||
|
||||
/* Configuring IDT for output refclks as
|
||||
* Refclk1 = 100MHz Refclk2 = 156.25MHz
|
||||
*/
|
||||
if (refclk1 == SERDES_REFCLK_100 &&
|
||||
refclk2 == SERDES_REFCLK_156_25) {
|
||||
printf("Setting refclk1:100 and refclk2:156.25\n");
|
||||
for (i = 0; i < NUM_IDT_REGS_156_25; i++)
|
||||
i2c_reg_write(idt_addr, idt_conf_100_156_25[i][0],
|
||||
idt_conf_100_156_25[i][1]);
|
||||
}
|
||||
|
||||
/* Configuring IDT for output refclks as
|
||||
* Refclk1 = 125MHz Refclk2 = 156.25MHz
|
||||
*/
|
||||
if (refclk1 == SERDES_REFCLK_125 &&
|
||||
refclk2 == SERDES_REFCLK_156_25) {
|
||||
printf("Setting refclk1:125 and refclk2:156.25\n");
|
||||
for (i = 0; i < NUM_IDT_REGS_156_25; i++)
|
||||
i2c_reg_write(idt_addr, idt_conf_125_156_25[i][0],
|
||||
idt_conf_125_156_25[i][1]);
|
||||
}
|
||||
|
||||
/* Configuring IDT for output refclks as
|
||||
* Refclk1 = 156.25MHz Refclk2 = 100MHz
|
||||
*/
|
||||
if (refclk1 == SERDES_REFCLK_156_25 &&
|
||||
refclk2 == SERDES_REFCLK_100) {
|
||||
printf("Setting refclk1:156.25 and refclk2:100\n");
|
||||
for (i = 0; i < NUM_IDT_REGS_156_25; i++)
|
||||
i2c_reg_write(idt_addr, idt_conf_156_25_100[i][0],
|
||||
idt_conf_156_25_100[i][1]);
|
||||
}
|
||||
|
||||
/* Configuring IDT for output refclks as
|
||||
* Refclk1 = 156.25MHz Refclk2 = 125MHz
|
||||
*/
|
||||
if (refclk1 == SERDES_REFCLK_156_25 &&
|
||||
refclk2 == SERDES_REFCLK_125) {
|
||||
printf("Setting refclk1:156.25 and refclk2:125\n");
|
||||
for (i = 0; i < NUM_IDT_REGS_156_25; i++)
|
||||
i2c_reg_write(idt_addr, idt_conf_156_25_125[i][0],
|
||||
idt_conf_156_25_125[i][1]);
|
||||
}
|
||||
|
||||
/* waiting for maximum of 1 second if PLL doesn'r get locked
|
||||
* initially. then check the status again.
|
||||
*/
|
||||
if (check_pll_status(idt_addr)) {
|
||||
mdelay(1000);
|
||||
if (check_pll_status(idt_addr))
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,106 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||
/*
|
||||
* Copyright 2013 Freescale Semiconductor, Inc.
|
||||
* Author: Shaveta Leekha <shaveta@freescale.com>
|
||||
*/
|
||||
|
||||
#ifndef __IDT8T49N222A_SERDES_CLK_H_
|
||||
#define __IDT8T49N222A_SERDES_CLK_H_ 1
|
||||
|
||||
#include <common.h>
|
||||
#include <i2c.h>
|
||||
#include "qixis.h"
|
||||
#include "../b4860qds/b4860qds_qixis.h"
|
||||
#include <errno.h>
|
||||
|
||||
#define NUM_IDT_REGS 23
|
||||
#define NUM_IDT_REGS_FEEDBACK 12
|
||||
#define NUM_IDT_REGS_156_25 11
|
||||
|
||||
/* CLK */
|
||||
enum serdes_refclk {
|
||||
SERDES_REFCLK_100, /* refclk 100Mhz */
|
||||
SERDES_REFCLK_122_88, /* refclk 122.88Mhz */
|
||||
SERDES_REFCLK_125, /* refclk 125Mhz */
|
||||
SERDES_REFCLK_156_25, /* refclk 156.25Mhz */
|
||||
SERDES_REFCLK_NONE = -1,
|
||||
};
|
||||
|
||||
/* configuration values for IDT registers for Output Refclks:
|
||||
* Refclk1 = 122.88MHz Refclk2 = 122.88MHz
|
||||
*/
|
||||
static const u8 idt_conf_122_88[23][2] = { {0x00, 0x3C}, {0x01, 0x00},
|
||||
{0x02, 0x9F}, {0x03, 0x00}, {0x04, 0x0B}, {0x05, 0x00},
|
||||
{0x06, 0x00}, {0x07, 0x00}, {0x08, 0x7D}, {0x09, 0x00},
|
||||
{0x0A, 0x08}, {0x0B, 0x00}, {0x0C, 0xDC}, {0x0D, 0x00},
|
||||
{0x0E, 0x00}, {0x0F, 0x00}, {0x10, 0x12}, {0x11, 0x12},
|
||||
{0x12, 0xB9}, {0x13, 0xBC}, {0x14, 0x40}, {0x15, 0x08},
|
||||
{0x16, 0xA0} };
|
||||
|
||||
|
||||
/* configuration values for IDT registers for Output Refclks:
|
||||
* Refclk1 not equal to 122.88MHz Refclk2 not equal to 122.88MHz
|
||||
*/
|
||||
static const u8 idt_conf_not_122_88[23][2] = { {0x00, 0x00}, {0x01, 0x00},
|
||||
{0x02, 0x00}, {0x03, 0x00}, {0x04, 0x0A}, {0x05, 0x00},
|
||||
{0x06, 0x00}, {0x07, 0x00}, {0x08, 0x7D}, {0x09, 0x00},
|
||||
{0x0A, 0x08}, {0x0B, 0x00}, {0x0C, 0xDC}, {0x0D, 0x00},
|
||||
{0x0E, 0x00}, {0x0F, 0x00}, {0x10, 0x14}, {0x11, 0x14},
|
||||
{0x12, 0x35}, {0x13, 0xBC}, {0x14, 0x40}, {0x15, 0x08},
|
||||
{0x16, 0xA0} };
|
||||
|
||||
/* Reconfiguration values for some of IDT registers for
|
||||
* Output Refclks:
|
||||
* Refclk1 = 122.88MHz Refclk2 = 122.88MHz
|
||||
* and with feedback as 1
|
||||
*/
|
||||
static const u8 idt_conf_122_88_feedback[12][2] = { {0x00, 0x50}, {0x02, 0xD7},
|
||||
{0x04, 0x89}, {0x06, 0xC3}, {0x08, 0xC0}, {0x0A, 0x07},
|
||||
{0x0C, 0x80}, {0x10, 0x10}, {0x11, 0x10}, {0x12, 0x1B},
|
||||
{0x14, 0x00}, {0x15, 0xE8} };
|
||||
|
||||
/* configuration values for IDT registers for Output Refclks:
|
||||
* Refclk1 : 156.25MHz Refclk2 : 156.25MHz
|
||||
*/
|
||||
static const u8 idt_conf_156_25[11][2] = { {0x04, 0x19}, {0x06, 0x03},
|
||||
{0x08, 0xC0}, {0x0A, 0x07}, {0x0C, 0xA1}, {0x0E, 0x20},
|
||||
{0x10, 0x10}, {0x11, 0x10}, {0x12, 0xB5}, {0x13, 0x3C},
|
||||
{0x15, 0xE8} };
|
||||
|
||||
/* configuration values for IDT registers for Output Refclks:
|
||||
* Refclk1 : 100MHz Refclk2 : 156.25MHz
|
||||
*/
|
||||
static const u8 idt_conf_100_156_25[11][2] = { {0x04, 0x19}, {0x06, 0x03},
|
||||
{0x08, 0xC0}, {0x0A, 0x07}, {0x0C, 0xA1}, {0x0E, 0x20},
|
||||
{0x10, 0x19}, {0x11, 0x10}, {0x12, 0xB5}, {0x13, 0x3C},
|
||||
{0x15, 0xE8} };
|
||||
|
||||
/* configuration values for IDT registers for Output Refclks:
|
||||
* Refclk1 : 125MHz Refclk2 : 156.25MHz
|
||||
*/
|
||||
static const u8 idt_conf_125_156_25[11][2] = { {0x04, 0x19}, {0x06, 0x03},
|
||||
{0x08, 0xC0}, {0x0A, 0x07}, {0x0C, 0xA1}, {0x0E, 0x20},
|
||||
{0x10, 0x14}, {0x11, 0x10}, {0x12, 0xB5}, {0x13, 0x3C},
|
||||
{0x15, 0xE8} };
|
||||
|
||||
/* configuration values for IDT registers for Output Refclks:
|
||||
* Refclk1 : 156.25MHz Refclk2 : 100MHz
|
||||
*/
|
||||
static const u8 idt_conf_156_25_100[11][2] = { {0x04, 0x19}, {0x06, 0x03},
|
||||
{0x08, 0xC0}, {0x0A, 0x07}, {0x0C, 0xA1}, {0x0E, 0x20},
|
||||
{0x10, 0x10}, {0x11, 0x19}, {0x12, 0xB5}, {0x13, 0x3C},
|
||||
{0x15, 0xE8} };
|
||||
|
||||
/* configuration values for IDT registers for Output Refclks:
|
||||
* Refclk1 : 156.25MHz Refclk2 : 125MHz
|
||||
*/
|
||||
static const u8 idt_conf_156_25_125[11][2] = { {0x04, 0x19}, {0x06, 0x03},
|
||||
{0x08, 0xC0}, {0x0A, 0x07}, {0x0C, 0xA1}, {0x0E, 0x20},
|
||||
{0x10, 0x10}, {0x11, 0x14}, {0x12, 0xB5}, {0x13, 0x3C},
|
||||
{0x15, 0xE8} };
|
||||
|
||||
int set_serdes_refclk(u8 idt_addr, u8 serdes_num,
|
||||
enum serdes_refclk refclk1,
|
||||
enum serdes_refclk refclk2, u8 feedback);
|
||||
|
||||
#endif /*__IDT8T49N222A_SERDES_CLK_H_ */
|
||||
@@ -0,0 +1,35 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Copyright 2014 Freescale Semiconductor
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/arch/ls102xa_stream_id.h>
|
||||
|
||||
void ls102xa_config_smmu_stream_id(struct smmu_stream_id *id, uint32_t num)
|
||||
{
|
||||
void *scfg = (void *)CONFIG_SYS_FSL_SCFG_ADDR;
|
||||
int i;
|
||||
u32 icid;
|
||||
|
||||
for (i = 0; i < num; i++) {
|
||||
icid = (id[i].stream_id & 0xff) << 24;
|
||||
out_be32((u32 *)(scfg + id[i].offset), icid);
|
||||
}
|
||||
}
|
||||
|
||||
void ls1021x_config_caam_stream_id(struct liodn_id_table *tbl, int size)
|
||||
{
|
||||
int i;
|
||||
u32 liodn;
|
||||
|
||||
for (i = 0; i < size; i++) {
|
||||
if (tbl[i].num_ids == 2)
|
||||
liodn = (tbl[i].id[0] << 16) | tbl[i].id[1];
|
||||
else
|
||||
liodn = tbl[i].id[0];
|
||||
|
||||
out_le32((u32 *)(tbl[i].reg_offset), liodn);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Copyright 2016 Freescale Semiconductor, Inc.
|
||||
* Hou Zhiqiang <Zhiqiang.Hou@freescale.com>
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <errno.h>
|
||||
#include <i2c.h>
|
||||
#include <power/pmic.h>
|
||||
#include <power/mc34vr500_pmic.h>
|
||||
|
||||
static uint8_t swxvolt_addr[4] = { MC34VR500_SW1VOLT,
|
||||
MC34VR500_SW2VOLT,
|
||||
MC34VR500_SW3VOLT,
|
||||
MC34VR500_SW4VOLT };
|
||||
|
||||
static uint8_t swx_set_point_base[4] = { 13, 9, 9, 9 };
|
||||
|
||||
int mc34vr500_get_sw_volt(uint8_t sw)
|
||||
{
|
||||
struct pmic *p;
|
||||
u32 swxvolt;
|
||||
uint8_t spb;
|
||||
int sw_volt;
|
||||
int ret;
|
||||
|
||||
debug("%s: Get SW%u volt from swxvolt_addr = 0x%x\n",
|
||||
__func__, sw + 1, swxvolt_addr[sw]);
|
||||
if (sw > SW4) {
|
||||
printf("%s: Unsupported SW(sw%d)\n", __func__, sw + 1);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
p = pmic_get("MC34VR500");
|
||||
if (!p) {
|
||||
printf("%s: Did NOT find PMIC MC34VR500\n", __func__);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
ret = pmic_probe(p);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = pmic_reg_read(p, swxvolt_addr[sw], &swxvolt);
|
||||
if (ret) {
|
||||
printf("%s: Failed to get SW%u volt\n", __func__, sw + 1);
|
||||
return ret;
|
||||
}
|
||||
|
||||
debug("%s: SW%d step point swxvolt = %u\n", __func__, sw + 1, swxvolt);
|
||||
spb = swx_set_point_base[sw];
|
||||
/* The base of SW volt is 625mV and increase by step 25mV */
|
||||
sw_volt = 625 + (swxvolt - spb) * 25;
|
||||
|
||||
debug("%s: SW%u volt = %dmV\n", __func__, sw + 1, sw_volt);
|
||||
return sw_volt;
|
||||
}
|
||||
|
||||
int mc34vr500_set_sw_volt(uint8_t sw, int sw_volt)
|
||||
{
|
||||
struct pmic *p;
|
||||
u32 swxvolt;
|
||||
uint8_t spb;
|
||||
int ret;
|
||||
|
||||
debug("%s: Set SW%u volt to %dmV\n", __func__, sw + 1, sw_volt);
|
||||
/* The least SW volt is 625mV, and only 4 SW outputs */
|
||||
if (sw > SW4 || sw_volt < 625)
|
||||
return -EINVAL;
|
||||
|
||||
p = pmic_get("MC34VR500");
|
||||
if (!p) {
|
||||
printf("%s: Did NOT find PMIC MC34VR500\n", __func__);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
ret = pmic_probe(p);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
spb = swx_set_point_base[sw];
|
||||
/* The base of SW volt is 625mV and increase by step 25mV */
|
||||
swxvolt = (sw_volt - 625) / 25 + spb;
|
||||
debug("%s: SW%d step point swxvolt = %u\n", __func__, sw + 1, swxvolt);
|
||||
if (swxvolt > 63)
|
||||
return -EINVAL;
|
||||
|
||||
ret = pmic_reg_write(p, swxvolt_addr[sw], swxvolt);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Copyright 2014 Freescale Semiconductor, Inc.
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <asm/immap_85xx.h>
|
||||
#include "sleep.h"
|
||||
#ifdef CONFIG_U_QE
|
||||
#include <fsl_qe.h>
|
||||
#endif
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
void __weak board_mem_sleep_setup(void)
|
||||
{
|
||||
}
|
||||
|
||||
void __weak board_sleep_prepare(void)
|
||||
{
|
||||
}
|
||||
|
||||
bool is_warm_boot(void)
|
||||
{
|
||||
struct ccsr_gur __iomem *gur = (void *)CONFIG_SYS_MPC85xx_GUTS_ADDR;
|
||||
|
||||
if (in_be32(&gur->scrtsr[0]) & DCFG_CCSR_CRSTSR_WDRFR)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void fsl_dp_disable_console(void)
|
||||
{
|
||||
gd->flags |= GD_FLG_SILENT | GD_FLG_DISABLE_CONSOLE;
|
||||
}
|
||||
|
||||
/*
|
||||
* When wakeup from deep sleep, the first 128 bytes space
|
||||
* will be used to do DDR training which corrupts the data
|
||||
* in there. This function will restore them.
|
||||
*/
|
||||
static void dp_ddr_restore(void)
|
||||
{
|
||||
u64 *src, *dst;
|
||||
int i;
|
||||
struct ccsr_scfg __iomem *scfg = (void *)CONFIG_SYS_MPC85xx_SCFG;
|
||||
|
||||
/* get the address of ddr date from SPARECR3 */
|
||||
src = (u64 *)(in_be32(&scfg->sparecr[2]) + DDR_BUFF_LEN - 8);
|
||||
dst = (u64 *)(CONFIG_SYS_SDRAM_BASE + DDR_BUFF_LEN - 8);
|
||||
|
||||
for (i = 0; i < DDR_BUFF_LEN / 8; i++)
|
||||
*dst-- = *src--;
|
||||
|
||||
flush_dcache();
|
||||
}
|
||||
|
||||
static void dp_resume_prepare(void)
|
||||
{
|
||||
dp_ddr_restore();
|
||||
|
||||
board_sleep_prepare();
|
||||
|
||||
l2cache_init();
|
||||
#if defined(CONFIG_RAMBOOT_PBL)
|
||||
disable_cpc_sram();
|
||||
#endif
|
||||
enable_cpc();
|
||||
|
||||
#ifdef CONFIG_U_QE
|
||||
u_qe_resume();
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
int fsl_dp_resume(void)
|
||||
{
|
||||
u32 start_addr;
|
||||
void (*kernel_resume)(void);
|
||||
struct ccsr_scfg __iomem *scfg = (void *)CONFIG_SYS_MPC85xx_SCFG;
|
||||
|
||||
if (!is_warm_boot())
|
||||
return 0;
|
||||
|
||||
dp_resume_prepare();
|
||||
|
||||
/* Get the entry address and jump to kernel */
|
||||
start_addr = in_be32(&scfg->sparecr[1]);
|
||||
debug("Entry address is 0x%08x\n", start_addr);
|
||||
kernel_resume = (void (*)(void))start_addr;
|
||||
kernel_resume();
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,249 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/**
|
||||
* Copyright 2010-2011 Freescale Semiconductor
|
||||
* Author: Timur Tabi <timur@freescale.com>
|
||||
*
|
||||
* This file provides support for the ngPIXIS, a board-specific FPGA used on
|
||||
* some Freescale reference boards.
|
||||
*
|
||||
* A "switch" is black rectangular block on the motherboard. It contains
|
||||
* eight "bits". The ngPIXIS has a set of memory-mapped registers (SWx) that
|
||||
* shadow the actual physical switches. There is also another set of
|
||||
* registers (ENx) that tell the ngPIXIS which bits of SWx should actually be
|
||||
* used to override the values of the bits in the physical switches.
|
||||
*
|
||||
* The following macros need to be defined:
|
||||
*
|
||||
* PIXIS_BASE - The virtual address of the base of the PIXIS register map
|
||||
*
|
||||
* PIXIS_LBMAP_SWITCH - The switch number (i.e. the "x" in "SWx"). This value
|
||||
* is used in the PIXIS_SW() macro to determine which offset in
|
||||
* the PIXIS register map corresponds to the physical switch that controls
|
||||
* the boot bank.
|
||||
*
|
||||
* PIXIS_LBMAP_MASK - A bit mask the defines which bits in SWx to use.
|
||||
*
|
||||
* PIXIS_LBMAP_SHIFT - The shift value that corresponds to PIXIS_LBMAP_MASK.
|
||||
*
|
||||
* PIXIS_LBMAP_ALTBANK - The value to program into SWx to tell the ngPIXIS to
|
||||
* boot from the alternate bank.
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <command.h>
|
||||
#include <asm/io.h>
|
||||
|
||||
#include "ngpixis.h"
|
||||
|
||||
static u8 __pixis_read(unsigned int reg)
|
||||
{
|
||||
void *p = (void *)PIXIS_BASE;
|
||||
|
||||
return in_8(p + reg);
|
||||
}
|
||||
u8 pixis_read(unsigned int reg) __attribute__((weak, alias("__pixis_read")));
|
||||
|
||||
static void __pixis_write(unsigned int reg, u8 value)
|
||||
{
|
||||
void *p = (void *)PIXIS_BASE;
|
||||
|
||||
out_8(p + reg, value);
|
||||
}
|
||||
void pixis_write(unsigned int reg, u8 value)
|
||||
__attribute__((weak, alias("__pixis_write")));
|
||||
|
||||
/*
|
||||
* Reset the board. This ignores the ENx registers.
|
||||
*/
|
||||
void __pixis_reset(void)
|
||||
{
|
||||
PIXIS_WRITE(rst, 0);
|
||||
|
||||
while (1);
|
||||
}
|
||||
void pixis_reset(void) __attribute__((weak, alias("__pixis_reset")));
|
||||
|
||||
/*
|
||||
* Reset the board. Like pixis_reset(), but it honors the ENx registers.
|
||||
*/
|
||||
void __pixis_bank_reset(void)
|
||||
{
|
||||
PIXIS_WRITE(vctl, 0);
|
||||
PIXIS_WRITE(vctl, 1);
|
||||
|
||||
while (1);
|
||||
}
|
||||
void pixis_bank_reset(void) __attribute__((weak, alias("__pixis_bank_reset")));
|
||||
|
||||
/**
|
||||
* Set the boot bank to the power-on default bank
|
||||
*/
|
||||
void __clear_altbank(void)
|
||||
{
|
||||
u8 reg;
|
||||
|
||||
/* Tell the ngPIXIS to use this the bits in the physical switch for the
|
||||
* boot bank value, instead of the SWx register. We need to be careful
|
||||
* only to set the bits in SWx that correspond to the boot bank.
|
||||
*/
|
||||
reg = PIXIS_READ(s[PIXIS_LBMAP_SWITCH - 1].en);
|
||||
reg &= ~PIXIS_LBMAP_MASK;
|
||||
PIXIS_WRITE(s[PIXIS_LBMAP_SWITCH - 1].en, reg);
|
||||
}
|
||||
void clear_altbank(void) __attribute__((weak, alias("__clear_altbank")));
|
||||
|
||||
/**
|
||||
* Set the boot bank to the alternate bank
|
||||
*/
|
||||
void __set_altbank(void)
|
||||
{
|
||||
u8 reg;
|
||||
|
||||
/* Program the alternate bank number into the SWx register.
|
||||
*/
|
||||
reg = PIXIS_READ(s[PIXIS_LBMAP_SWITCH - 1].sw);
|
||||
reg = (reg & ~PIXIS_LBMAP_MASK) | PIXIS_LBMAP_ALTBANK;
|
||||
PIXIS_WRITE(s[PIXIS_LBMAP_SWITCH - 1].sw, reg);
|
||||
|
||||
/* Tell the ngPIXIS to use this the bits in the SWx register for the
|
||||
* boot bank value, instead of the physical switch. We need to be
|
||||
* careful only to set the bits in SWx that correspond to the boot bank.
|
||||
*/
|
||||
reg = PIXIS_READ(s[PIXIS_LBMAP_SWITCH - 1].en);
|
||||
reg |= PIXIS_LBMAP_MASK;
|
||||
PIXIS_WRITE(s[PIXIS_LBMAP_SWITCH - 1].en, reg);
|
||||
}
|
||||
void set_altbank(void) __attribute__((weak, alias("__set_altbank")));
|
||||
|
||||
#ifdef DEBUG
|
||||
static void pixis_dump_regs(void)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
printf("id=%02x\n", PIXIS_READ(id));
|
||||
printf("arch=%02x\n", PIXIS_READ(arch));
|
||||
printf("scver=%02x\n", PIXIS_READ(scver));
|
||||
printf("csr=%02x\n", PIXIS_READ(csr));
|
||||
printf("rst=%02x\n", PIXIS_READ(rst));
|
||||
printf("aux=%02x\n", PIXIS_READ(aux));
|
||||
printf("spd=%02x\n", PIXIS_READ(spd));
|
||||
printf("brdcfg0=%02x\n", PIXIS_READ(brdcfg0));
|
||||
printf("brdcfg1=%02x\n", PIXIS_READ(brdcfg1));
|
||||
printf("addr=%02x\n", PIXIS_READ(addr));
|
||||
printf("data=%02x\n", PIXIS_READ(data));
|
||||
printf("led=%02x\n", PIXIS_READ(led));
|
||||
printf("vctl=%02x\n", PIXIS_READ(vctl));
|
||||
printf("vstat=%02x\n", PIXIS_READ(vstat));
|
||||
printf("vcfgen0=%02x\n", PIXIS_READ(vcfgen0));
|
||||
printf("ocmcsr=%02x\n", PIXIS_READ(ocmcsr));
|
||||
printf("ocmmsg=%02x\n", PIXIS_READ(ocmmsg));
|
||||
printf("gmdbg=%02x\n", PIXIS_READ(gmdbg));
|
||||
printf("sclk=%02x%02x%02x\n",
|
||||
PIXIS_READ(sclk[0]), PIXIS_READ(sclk[1]), PIXIS_READ(sclk[2]));
|
||||
printf("dclk=%02x%02x%02x\n",
|
||||
PIXIS_READ(dclk[0]), PIXIS_READ(dclk[1]), PIXIS_READ(dclk[2]));
|
||||
printf("watch=%02x\n", PIXIS_READ(watch));
|
||||
|
||||
for (i = 0; i < 8; i++) {
|
||||
printf("SW%u=%02x/%02x ", i + 1,
|
||||
PIXIS_READ(s[i].sw), PIXIS_READ(s[i].en));
|
||||
}
|
||||
putc('\n');
|
||||
}
|
||||
#endif
|
||||
|
||||
void pixis_sysclk_set(unsigned long sysclk)
|
||||
{
|
||||
unsigned long freq_word;
|
||||
u8 sclk0, sclk1, sclk2;
|
||||
|
||||
freq_word = ics307_sysclk_calculator(sysclk);
|
||||
sclk2 = freq_word & 0xff;
|
||||
sclk1 = (freq_word >> 8) & 0xff;
|
||||
sclk0 = (freq_word >> 16) & 0xff;
|
||||
|
||||
/* set SYSCLK enable bit */
|
||||
PIXIS_WRITE(vcfgen0, 0x01);
|
||||
|
||||
/* SYSCLK to required frequency */
|
||||
PIXIS_WRITE(sclk[0], sclk0);
|
||||
PIXIS_WRITE(sclk[1], sclk1);
|
||||
PIXIS_WRITE(sclk[2], sclk2);
|
||||
}
|
||||
|
||||
int pixis_reset_cmd(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
|
||||
{
|
||||
unsigned int i;
|
||||
unsigned long sysclk;
|
||||
char *p_altbank = NULL;
|
||||
#ifdef DEBUG
|
||||
char *p_dump = NULL;
|
||||
#endif
|
||||
char *unknown_param = NULL;
|
||||
|
||||
/* No args is a simple reset request.
|
||||
*/
|
||||
if (argc <= 1)
|
||||
pixis_reset();
|
||||
|
||||
for (i = 1; i < argc; i++) {
|
||||
if (strcmp(argv[i], "altbank") == 0) {
|
||||
p_altbank = argv[i];
|
||||
continue;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
if (strcmp(argv[i], "dump") == 0) {
|
||||
p_dump = argv[i];
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
if (strcmp(argv[i], "sysclk") == 0) {
|
||||
sysclk = simple_strtoul(argv[i + 1], NULL, 0);
|
||||
i += 1;
|
||||
pixis_sysclk_set(sysclk);
|
||||
continue;
|
||||
}
|
||||
|
||||
unknown_param = argv[i];
|
||||
}
|
||||
|
||||
if (unknown_param) {
|
||||
printf("Invalid option: %s\n", unknown_param);
|
||||
return 1;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
if (p_dump) {
|
||||
pixis_dump_regs();
|
||||
|
||||
/* 'dump' ignores other commands */
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (p_altbank)
|
||||
set_altbank();
|
||||
else
|
||||
clear_altbank();
|
||||
|
||||
pixis_bank_reset();
|
||||
|
||||
/* Shouldn't be reached. */
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SYS_LONGHELP
|
||||
static char pixis_help_text[] =
|
||||
"- hard reset to default bank\n"
|
||||
"pixis_reset altbank - reset to alternate bank\n"
|
||||
#ifdef DEBUG
|
||||
"pixis_reset dump - display the PIXIS registers\n"
|
||||
#endif
|
||||
"pixis_reset sysclk <SYSCLK_freq> - reset with SYSCLK frequency(KHz)\n";
|
||||
#endif
|
||||
|
||||
U_BOOT_CMD(
|
||||
pixis_reset, CONFIG_SYS_MAXARGS, 1, pixis_reset_cmd,
|
||||
"Reset the board using the FPGA sequencer", pixis_help_text
|
||||
);
|
||||
@@ -0,0 +1,60 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||
/**
|
||||
* Copyright 2010-2011 Freescale Semiconductor
|
||||
* Author: Timur Tabi <timur@freescale.com>
|
||||
*
|
||||
* This file provides support for the ngPIXIS, a board-specific FPGA used on
|
||||
* some Freescale reference boards.
|
||||
*/
|
||||
|
||||
/* ngPIXIS register set. Hopefully, this won't change too much over time.
|
||||
* Feel free to add board-specific #ifdefs where necessary.
|
||||
*/
|
||||
typedef struct ngpixis {
|
||||
u8 id;
|
||||
u8 arch;
|
||||
u8 scver;
|
||||
u8 csr;
|
||||
u8 rst;
|
||||
u8 serclk;
|
||||
u8 aux;
|
||||
u8 spd;
|
||||
u8 brdcfg0;
|
||||
u8 brdcfg1; /* On some boards, this register is called 'dma' */
|
||||
u8 addr;
|
||||
u8 brdcfg2;
|
||||
u8 gpiodir;
|
||||
u8 data;
|
||||
u8 led;
|
||||
u8 tag;
|
||||
u8 vctl;
|
||||
u8 vstat;
|
||||
u8 vcfgen0;
|
||||
u8 res4;
|
||||
u8 ocmcsr;
|
||||
u8 ocmmsg;
|
||||
u8 gmdbg;
|
||||
u8 res5[2];
|
||||
u8 sclk[3];
|
||||
u8 dclk[3];
|
||||
u8 watch;
|
||||
struct {
|
||||
u8 sw;
|
||||
u8 en;
|
||||
} s[9]; /* s[0]..s[7] is SW1..SW8, and s[8] is SW11 */
|
||||
} __attribute__ ((packed)) ngpixis_t;
|
||||
|
||||
/* Pointer to the PIXIS register set */
|
||||
#define pixis ((ngpixis_t *)PIXIS_BASE)
|
||||
|
||||
/* The PIXIS SW register that corresponds to board switch X, where x >= 1 */
|
||||
#define PIXIS_SW(x) (pixis->s[(x) - 1].sw)
|
||||
|
||||
/* The PIXIS EN register that corresponds to board switch X, where x >= 1 */
|
||||
#define PIXIS_EN(x) (pixis->s[(x) - 1].en)
|
||||
|
||||
u8 pixis_read(unsigned int reg);
|
||||
void pixis_write(unsigned int reg, u8 value);
|
||||
|
||||
#define PIXIS_READ(reg) pixis_read(offsetof(ngpixis_t, reg))
|
||||
#define PIXIS_WRITE(reg, value) pixis_write(offsetof(ngpixis_t, reg), value)
|
||||
@@ -0,0 +1,239 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Copyright 2014 Freescale Semiconductor
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <asm/io.h>
|
||||
#include <fsl_csu.h>
|
||||
#include <asm/arch/ns_access.h>
|
||||
#include <asm/arch/fsl_serdes.h>
|
||||
|
||||
#ifdef CONFIG_ARCH_LS1021A
|
||||
static struct csu_ns_dev ns_dev[] = {
|
||||
{ CSU_CSLX_PCIE2_IO, CSU_ALL_RW },
|
||||
{ CSU_CSLX_PCIE1_IO, CSU_ALL_RW },
|
||||
{ CSU_CSLX_MG2TPR_IP, CSU_ALL_RW },
|
||||
{ CSU_CSLX_IFC_MEM, CSU_ALL_RW },
|
||||
{ CSU_CSLX_OCRAM, CSU_ALL_RW },
|
||||
{ CSU_CSLX_GIC, CSU_ALL_RW },
|
||||
{ CSU_CSLX_PCIE1, CSU_ALL_RW },
|
||||
{ CSU_CSLX_OCRAM2, CSU_ALL_RW },
|
||||
{ CSU_CSLX_QSPI_MEM, CSU_ALL_RW },
|
||||
{ CSU_CSLX_PCIE2, CSU_ALL_RW },
|
||||
{ CSU_CSLX_SATA, CSU_ALL_RW },
|
||||
{ CSU_CSLX_USB3, CSU_ALL_RW },
|
||||
{ CSU_CSLX_SERDES, CSU_ALL_RW },
|
||||
{ CSU_CSLX_QDMA, CSU_ALL_RW },
|
||||
{ CSU_CSLX_LPUART2, CSU_ALL_RW },
|
||||
{ CSU_CSLX_LPUART1, CSU_ALL_RW },
|
||||
{ CSU_CSLX_LPUART4, CSU_ALL_RW },
|
||||
{ CSU_CSLX_LPUART3, CSU_ALL_RW },
|
||||
{ CSU_CSLX_LPUART6, CSU_ALL_RW },
|
||||
{ CSU_CSLX_LPUART5, CSU_ALL_RW },
|
||||
{ CSU_CSLX_DSPI2, CSU_ALL_RW },
|
||||
{ CSU_CSLX_DSPI1, CSU_ALL_RW },
|
||||
{ CSU_CSLX_QSPI, CSU_ALL_RW },
|
||||
{ CSU_CSLX_ESDHC, CSU_ALL_RW },
|
||||
{ CSU_CSLX_2D_ACE, CSU_ALL_RW },
|
||||
{ CSU_CSLX_IFC, CSU_ALL_RW },
|
||||
{ CSU_CSLX_I2C1, CSU_ALL_RW },
|
||||
{ CSU_CSLX_USB2, CSU_ALL_RW },
|
||||
{ CSU_CSLX_I2C3, CSU_ALL_RW },
|
||||
{ CSU_CSLX_I2C2, CSU_ALL_RW },
|
||||
{ CSU_CSLX_DUART2, CSU_ALL_RW },
|
||||
{ CSU_CSLX_DUART1, CSU_ALL_RW },
|
||||
{ CSU_CSLX_WDT2, CSU_ALL_RW },
|
||||
{ CSU_CSLX_WDT1, CSU_ALL_RW },
|
||||
{ CSU_CSLX_EDMA, CSU_ALL_RW },
|
||||
{ CSU_CSLX_SYS_CNT, CSU_ALL_RW },
|
||||
{ CSU_CSLX_DMA_MUX2, CSU_ALL_RW },
|
||||
{ CSU_CSLX_DMA_MUX1, CSU_ALL_RW },
|
||||
{ CSU_CSLX_DDR, CSU_ALL_RW },
|
||||
{ CSU_CSLX_QUICC, CSU_ALL_RW },
|
||||
{ CSU_CSLX_DCFG_CCU_RCPM, CSU_ALL_RW },
|
||||
{ CSU_CSLX_SECURE_BOOTROM, CSU_ALL_RW },
|
||||
{ CSU_CSLX_SFP, CSU_ALL_RW },
|
||||
{ CSU_CSLX_TMU, CSU_ALL_RW },
|
||||
{ CSU_CSLX_SECURE_MONITOR, CSU_ALL_RW },
|
||||
{ CSU_CSLX_RESERVED0, CSU_ALL_RW },
|
||||
{ CSU_CSLX_ETSEC1, CSU_ALL_RW },
|
||||
{ CSU_CSLX_SEC5_5, CSU_ALL_RW },
|
||||
{ CSU_CSLX_ETSEC3, CSU_ALL_RW },
|
||||
{ CSU_CSLX_ETSEC2, CSU_ALL_RW },
|
||||
{ CSU_CSLX_GPIO2, CSU_ALL_RW },
|
||||
{ CSU_CSLX_GPIO1, CSU_ALL_RW },
|
||||
{ CSU_CSLX_GPIO4, CSU_ALL_RW },
|
||||
{ CSU_CSLX_GPIO3, CSU_ALL_RW },
|
||||
{ CSU_CSLX_PLATFORM_CONT, CSU_ALL_RW },
|
||||
{ CSU_CSLX_CSU, CSU_ALL_RW },
|
||||
{ CSU_CSLX_ASRC, CSU_ALL_RW },
|
||||
{ CSU_CSLX_SPDIF, CSU_ALL_RW },
|
||||
{ CSU_CSLX_FLEXCAN2, CSU_ALL_RW },
|
||||
{ CSU_CSLX_FLEXCAN1, CSU_ALL_RW },
|
||||
{ CSU_CSLX_FLEXCAN4, CSU_ALL_RW },
|
||||
{ CSU_CSLX_FLEXCAN3, CSU_ALL_RW },
|
||||
{ CSU_CSLX_SAI2, CSU_ALL_RW },
|
||||
{ CSU_CSLX_SAI1, CSU_ALL_RW },
|
||||
{ CSU_CSLX_SAI4, CSU_ALL_RW },
|
||||
{ CSU_CSLX_SAI3, CSU_ALL_RW },
|
||||
{ CSU_CSLX_FTM2, CSU_ALL_RW },
|
||||
{ CSU_CSLX_FTM1, CSU_ALL_RW },
|
||||
{ CSU_CSLX_FTM4, CSU_ALL_RW },
|
||||
{ CSU_CSLX_FTM3, CSU_ALL_RW },
|
||||
{ CSU_CSLX_FTM6, CSU_ALL_RW },
|
||||
{ CSU_CSLX_FTM5, CSU_ALL_RW },
|
||||
{ CSU_CSLX_FTM8, CSU_ALL_RW },
|
||||
{ CSU_CSLX_FTM7, CSU_ALL_RW },
|
||||
{ CSU_CSLX_COP_DCSR, CSU_ALL_RW },
|
||||
{ CSU_CSLX_EPU, CSU_ALL_RW },
|
||||
{ CSU_CSLX_GDI, CSU_ALL_RW },
|
||||
{ CSU_CSLX_DDI, CSU_ALL_RW },
|
||||
{ CSU_CSLX_RESERVED1, CSU_ALL_RW },
|
||||
{ CSU_CSLX_USB3_PHY, CSU_ALL_RW },
|
||||
{ CSU_CSLX_RESERVED2, CSU_ALL_RW },
|
||||
};
|
||||
|
||||
#else
|
||||
static struct csu_ns_dev ns_dev[] = {
|
||||
{CSU_CSLX_PCIE2_IO, CSU_ALL_RW},
|
||||
{CSU_CSLX_PCIE1_IO, CSU_ALL_RW},
|
||||
{CSU_CSLX_MG2TPR_IP, CSU_ALL_RW},
|
||||
{CSU_CSLX_IFC_MEM, CSU_ALL_RW},
|
||||
{CSU_CSLX_OCRAM, CSU_ALL_RW},
|
||||
{CSU_CSLX_GIC, CSU_ALL_RW},
|
||||
{CSU_CSLX_PCIE1, CSU_ALL_RW},
|
||||
{CSU_CSLX_OCRAM2, CSU_ALL_RW},
|
||||
{CSU_CSLX_QSPI_MEM, CSU_ALL_RW},
|
||||
{CSU_CSLX_PCIE2, CSU_ALL_RW},
|
||||
{CSU_CSLX_SATA, CSU_ALL_RW},
|
||||
{CSU_CSLX_USB1, CSU_ALL_RW},
|
||||
{CSU_CSLX_QM_BM_SWPORTAL, CSU_ALL_RW},
|
||||
{CSU_CSLX_PCIE3, CSU_ALL_RW},
|
||||
{CSU_CSLX_PCIE3_IO, CSU_ALL_RW},
|
||||
{CSU_CSLX_USB3, CSU_ALL_RW},
|
||||
{CSU_CSLX_USB2, CSU_ALL_RW},
|
||||
{CSU_CSLX_PFE, CSU_ALL_RW},
|
||||
{CSU_CSLX_SERDES, CSU_ALL_RW},
|
||||
{CSU_CSLX_QDMA, CSU_ALL_RW},
|
||||
{CSU_CSLX_LPUART2, CSU_ALL_RW},
|
||||
{CSU_CSLX_LPUART1, CSU_ALL_RW},
|
||||
{CSU_CSLX_LPUART4, CSU_ALL_RW},
|
||||
{CSU_CSLX_LPUART3, CSU_ALL_RW},
|
||||
{CSU_CSLX_LPUART6, CSU_ALL_RW},
|
||||
{CSU_CSLX_LPUART5, CSU_ALL_RW},
|
||||
{CSU_CSLX_DSPI1, CSU_ALL_RW},
|
||||
{CSU_CSLX_QSPI, CSU_ALL_RW},
|
||||
{CSU_CSLX_ESDHC, CSU_ALL_RW},
|
||||
{CSU_CSLX_IFC, CSU_ALL_RW},
|
||||
{CSU_CSLX_I2C1, CSU_ALL_RW},
|
||||
{CSU_CSLX_I2C3, CSU_ALL_RW},
|
||||
{CSU_CSLX_I2C2, CSU_ALL_RW},
|
||||
{CSU_CSLX_DUART2, CSU_ALL_RW},
|
||||
{CSU_CSLX_DUART1, CSU_ALL_RW},
|
||||
{CSU_CSLX_WDT2, CSU_ALL_RW},
|
||||
{CSU_CSLX_WDT1, CSU_ALL_RW},
|
||||
{CSU_CSLX_EDMA, CSU_ALL_RW},
|
||||
{CSU_CSLX_SYS_CNT, CSU_ALL_RW},
|
||||
{CSU_CSLX_DMA_MUX2, CSU_ALL_RW},
|
||||
{CSU_CSLX_DMA_MUX1, CSU_ALL_RW},
|
||||
{CSU_CSLX_DDR, CSU_ALL_RW},
|
||||
{CSU_CSLX_QUICC, CSU_ALL_RW},
|
||||
{CSU_CSLX_DCFG_CCU_RCPM, CSU_ALL_RW},
|
||||
{CSU_CSLX_SECURE_BOOTROM, CSU_ALL_RW},
|
||||
{CSU_CSLX_SFP, CSU_ALL_RW},
|
||||
{CSU_CSLX_TMU, CSU_ALL_RW},
|
||||
{CSU_CSLX_SECURE_MONITOR, CSU_ALL_RW},
|
||||
{CSU_CSLX_SCFG, CSU_ALL_RW},
|
||||
{CSU_CSLX_FM, CSU_ALL_RW},
|
||||
{CSU_CSLX_SEC5_5, CSU_ALL_RW},
|
||||
{CSU_CSLX_BM, CSU_ALL_RW},
|
||||
{CSU_CSLX_QM, CSU_ALL_RW},
|
||||
{CSU_CSLX_GPIO2, CSU_ALL_RW},
|
||||
{CSU_CSLX_GPIO1, CSU_ALL_RW},
|
||||
{CSU_CSLX_GPIO4, CSU_ALL_RW},
|
||||
{CSU_CSLX_GPIO3, CSU_ALL_RW},
|
||||
{CSU_CSLX_PLATFORM_CONT, CSU_ALL_RW},
|
||||
{CSU_CSLX_CSU, CSU_ALL_RW},
|
||||
{CSU_CSLX_IIC4, CSU_ALL_RW},
|
||||
{CSU_CSLX_WDT4, CSU_ALL_RW},
|
||||
{CSU_CSLX_WDT3, CSU_ALL_RW},
|
||||
{CSU_CSLX_ESDHC2, CSU_ALL_RW},
|
||||
{CSU_CSLX_WDT5, CSU_ALL_RW},
|
||||
{CSU_CSLX_SAI2, CSU_ALL_RW},
|
||||
{CSU_CSLX_SAI1, CSU_ALL_RW},
|
||||
{CSU_CSLX_SAI4, CSU_ALL_RW},
|
||||
{CSU_CSLX_SAI3, CSU_ALL_RW},
|
||||
{CSU_CSLX_FTM2, CSU_ALL_RW},
|
||||
{CSU_CSLX_FTM1, CSU_ALL_RW},
|
||||
{CSU_CSLX_FTM4, CSU_ALL_RW},
|
||||
{CSU_CSLX_FTM3, CSU_ALL_RW},
|
||||
{CSU_CSLX_FTM6, CSU_ALL_RW},
|
||||
{CSU_CSLX_FTM5, CSU_ALL_RW},
|
||||
{CSU_CSLX_FTM8, CSU_ALL_RW},
|
||||
{CSU_CSLX_FTM7, CSU_ALL_RW},
|
||||
{CSU_CSLX_DSCR, CSU_ALL_RW},
|
||||
};
|
||||
#endif
|
||||
|
||||
void set_devices_ns_access(unsigned long index, u16 val)
|
||||
{
|
||||
u32 *base = (u32 *)CONFIG_SYS_FSL_CSU_ADDR;
|
||||
u32 *reg;
|
||||
uint32_t tmp;
|
||||
|
||||
reg = base + index / 2;
|
||||
tmp = in_be32(reg);
|
||||
if (index % 2 == 0) {
|
||||
tmp &= 0x0000ffff;
|
||||
tmp |= val << 16;
|
||||
} else {
|
||||
tmp &= 0xffff0000;
|
||||
tmp |= val;
|
||||
}
|
||||
|
||||
out_be32(reg, tmp);
|
||||
}
|
||||
|
||||
static void enable_devices_ns_access(struct csu_ns_dev *ns_dev, uint32_t num)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < num; i++)
|
||||
set_devices_ns_access(ns_dev[i].ind, ns_dev[i].val);
|
||||
}
|
||||
|
||||
void enable_layerscape_ns_access(void)
|
||||
{
|
||||
#ifdef CONFIG_ARM64
|
||||
if (current_el() == 3)
|
||||
#endif
|
||||
enable_devices_ns_access(ns_dev, ARRAY_SIZE(ns_dev));
|
||||
}
|
||||
|
||||
void set_pcie_ns_access(int pcie, u16 val)
|
||||
{
|
||||
switch (pcie) {
|
||||
#ifdef CONFIG_PCIE1
|
||||
case PCIE1:
|
||||
set_devices_ns_access(CSU_CSLX_PCIE1, val);
|
||||
set_devices_ns_access(CSU_CSLX_PCIE1_IO, val);
|
||||
return;
|
||||
#endif
|
||||
#ifdef CONFIG_PCIE2
|
||||
case PCIE2:
|
||||
set_devices_ns_access(CSU_CSLX_PCIE2, val);
|
||||
set_devices_ns_access(CSU_CSLX_PCIE2_IO, val);
|
||||
return;
|
||||
#endif
|
||||
#ifdef CONFIG_PCIE3
|
||||
case PCIE3:
|
||||
set_devices_ns_access(CSU_CSLX_PCIE3, val);
|
||||
set_devices_ns_access(CSU_CSLX_PCIE3_IO, val);
|
||||
return;
|
||||
#endif
|
||||
default:
|
||||
debug("The PCIE%d doesn't exist!\n", pcie);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
# SPDX-License-Identifier: GPL-2.0+
|
||||
#
|
||||
# (C) Copyright 2002-2006
|
||||
# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
|
||||
|
||||
obj-y += law.o
|
||||
obj-$(CONFIG_PCI) += pci.o
|
||||
obj-y += tlb.o
|
||||
@@ -0,0 +1,36 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Copyright 2008-2011 Freescale Semiconductor, Inc.
|
||||
*
|
||||
* (C) Copyright 2000
|
||||
* Wolfgang Denk, DENX Software Engineering, wd@denx.de.
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <asm/fsl_law.h>
|
||||
#include <asm/mmu.h>
|
||||
|
||||
struct law_entry law_table[] = {
|
||||
SET_LAW(CONFIG_SYS_FLASH_BASE_PHYS, LAW_SIZE_256M, LAW_TRGT_IF_LBC),
|
||||
#ifdef CONFIG_SYS_BMAN_MEM_PHYS
|
||||
SET_LAW(CONFIG_SYS_BMAN_MEM_PHYS, LAW_SIZE_2M, LAW_TRGT_IF_BMAN),
|
||||
#endif
|
||||
#ifdef CONFIG_SYS_QMAN_MEM_PHYS
|
||||
SET_LAW(CONFIG_SYS_QMAN_MEM_PHYS, LAW_SIZE_2M, LAW_TRGT_IF_QMAN),
|
||||
#endif
|
||||
#ifdef PIXIS_BASE_PHYS
|
||||
SET_LAW(PIXIS_BASE_PHYS, LAW_SIZE_4K, LAW_TRGT_IF_LBC),
|
||||
#endif
|
||||
#ifdef CPLD_BASE_PHYS
|
||||
SET_LAW(CPLD_BASE_PHYS, LAW_SIZE_4K, LAW_TRGT_IF_LBC),
|
||||
#endif
|
||||
#ifdef CONFIG_SYS_DCSRBAR_PHYS
|
||||
/* Limit DCSR to 32M to access NPC Trace Buffer */
|
||||
SET_LAW(CONFIG_SYS_DCSRBAR_PHYS, LAW_SIZE_32M, LAW_TRGT_IF_DCSR),
|
||||
#endif
|
||||
#ifdef CONFIG_SYS_NAND_BASE_PHYS
|
||||
SET_LAW(CONFIG_SYS_NAND_BASE_PHYS, LAW_SIZE_1M, LAW_TRGT_IF_LBC),
|
||||
#endif
|
||||
};
|
||||
|
||||
int num_law_entries = ARRAY_SIZE(law_table);
|
||||
@@ -0,0 +1,25 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Copyright 2007-2011 Freescale Semiconductor, Inc.
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <command.h>
|
||||
#include <init.h>
|
||||
#include <pci.h>
|
||||
#include <asm/fsl_pci.h>
|
||||
#include <linux/libfdt.h>
|
||||
#include <fdt_support.h>
|
||||
#include <asm/fsl_serdes.h>
|
||||
|
||||
#if !defined(CONFIG_DM_PCI)
|
||||
void pci_init_board(void)
|
||||
{
|
||||
fsl_pcie_init_board(0);
|
||||
}
|
||||
|
||||
void pci_of_setup(void *blob, bd_t *bd)
|
||||
{
|
||||
FT_FSL_PCI_SETUP;
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,160 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Copyright 2008-2011 Freescale Semiconductor, Inc.
|
||||
*
|
||||
* (C) Copyright 2000
|
||||
* Wolfgang Denk, DENX Software Engineering, wd@denx.de.
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <asm/mmu.h>
|
||||
|
||||
struct fsl_e_tlb_entry tlb_table[] = {
|
||||
/* TLB 0 - for temp stack in cache */
|
||||
SET_TLB_ENTRY(0, CONFIG_SYS_INIT_RAM_ADDR,
|
||||
CONFIG_SYS_INIT_RAM_ADDR_PHYS,
|
||||
MAS3_SW|MAS3_SR, 0,
|
||||
0, 0, BOOKE_PAGESZ_4K, 0),
|
||||
SET_TLB_ENTRY(0, CONFIG_SYS_INIT_RAM_ADDR + 4 * 1024,
|
||||
CONFIG_SYS_INIT_RAM_ADDR_PHYS + 4 * 1024,
|
||||
MAS3_SW|MAS3_SR, 0,
|
||||
0, 0, BOOKE_PAGESZ_4K, 0),
|
||||
SET_TLB_ENTRY(0, CONFIG_SYS_INIT_RAM_ADDR + 8 * 1024,
|
||||
CONFIG_SYS_INIT_RAM_ADDR_PHYS + 8 * 1024,
|
||||
MAS3_SW|MAS3_SR, 0,
|
||||
0, 0, BOOKE_PAGESZ_4K, 0),
|
||||
SET_TLB_ENTRY(0, CONFIG_SYS_INIT_RAM_ADDR + 12 * 1024,
|
||||
CONFIG_SYS_INIT_RAM_ADDR_PHYS + 12 * 1024,
|
||||
MAS3_SW|MAS3_SR, 0,
|
||||
0, 0, BOOKE_PAGESZ_4K, 0),
|
||||
#ifdef CPLD_BASE
|
||||
SET_TLB_ENTRY(0, CPLD_BASE, CPLD_BASE_PHYS,
|
||||
MAS3_SW|MAS3_SR, MAS2_I|MAS2_G,
|
||||
0, 0, BOOKE_PAGESZ_4K, 0),
|
||||
#endif
|
||||
|
||||
#ifdef PIXIS_BASE
|
||||
SET_TLB_ENTRY(0, PIXIS_BASE, PIXIS_BASE_PHYS,
|
||||
MAS3_SW|MAS3_SR, MAS2_I|MAS2_G,
|
||||
0, 0, BOOKE_PAGESZ_4K, 0),
|
||||
#endif
|
||||
|
||||
/* TLB 1 */
|
||||
/* *I*** - Covers boot page */
|
||||
#if defined(CONFIG_SYS_RAMBOOT) && defined(CONFIG_SYS_INIT_L3_ADDR)
|
||||
|
||||
#if !defined(CONFIG_NXP_ESBC)
|
||||
/*
|
||||
* *I*G - L3SRAM. When L3 is used as 1M SRAM, the address of the
|
||||
* SRAM is at 0xfff00000, it covered the 0xfffff000.
|
||||
*/
|
||||
SET_TLB_ENTRY(1, CONFIG_SYS_INIT_L3_ADDR, CONFIG_SYS_INIT_L3_ADDR,
|
||||
MAS3_SX|MAS3_SW|MAS3_SR, MAS2_I|MAS2_G,
|
||||
0, 0, BOOKE_PAGESZ_1M, 1),
|
||||
#else
|
||||
/*
|
||||
* *I*G - L3SRAM. When L3 is used as 1M SRAM, in case of Secure Boot
|
||||
* the physical address of the SRAM is at CONFIG_SYS_INIT_L3_ADDR,
|
||||
* and virtual address is CONFIG_SYS_MONITOR_BASE
|
||||
*/
|
||||
|
||||
SET_TLB_ENTRY(1, CONFIG_SYS_MONITOR_BASE & 0xfff00000,
|
||||
CONFIG_SYS_INIT_L3_ADDR & 0xfff00000,
|
||||
MAS3_SX|MAS3_SW|MAS3_SR, MAS2_I|MAS2_G,
|
||||
0, 0, BOOKE_PAGESZ_1M, 1),
|
||||
#endif
|
||||
|
||||
#elif defined(CONFIG_SRIO_PCIE_BOOT_SLAVE)
|
||||
/*
|
||||
* SRIO_PCIE_BOOT-SLAVE. When slave boot, the address of the
|
||||
* space is at 0xfff00000, it covered the 0xfffff000.
|
||||
*/
|
||||
SET_TLB_ENTRY(1, CONFIG_SYS_SRIO_PCIE_BOOT_SLAVE_ADDR,
|
||||
CONFIG_SYS_SRIO_PCIE_BOOT_SLAVE_ADDR_PHYS,
|
||||
MAS3_SX|MAS3_SW|MAS3_SR, MAS2_W|MAS2_G,
|
||||
0, 0, BOOKE_PAGESZ_1M, 1),
|
||||
#else
|
||||
SET_TLB_ENTRY(1, 0xfffff000, 0xfffff000,
|
||||
MAS3_SX|MAS3_SW|MAS3_SR, MAS2_I|MAS2_G,
|
||||
0, 0, BOOKE_PAGESZ_4K, 1),
|
||||
#endif
|
||||
|
||||
/* *I*G* - CCSRBAR */
|
||||
SET_TLB_ENTRY(1, CONFIG_SYS_CCSRBAR, CONFIG_SYS_CCSRBAR_PHYS,
|
||||
MAS3_SW|MAS3_SR, MAS2_I|MAS2_G,
|
||||
0, 1, BOOKE_PAGESZ_16M, 1),
|
||||
|
||||
/* *I*G* - Flash, localbus */
|
||||
/* This will be changed to *I*G* after relocation to RAM. */
|
||||
SET_TLB_ENTRY(1, CONFIG_SYS_FLASH_BASE, CONFIG_SYS_FLASH_BASE_PHYS,
|
||||
MAS3_SX|MAS3_SR, MAS2_W|MAS2_G,
|
||||
0, 2, BOOKE_PAGESZ_256M, 1),
|
||||
|
||||
/* *I*G* - PCI */
|
||||
SET_TLB_ENTRY(1, CONFIG_SYS_PCIE1_MEM_VIRT, CONFIG_SYS_PCIE1_MEM_PHYS,
|
||||
MAS3_SW|MAS3_SR, MAS2_I|MAS2_G,
|
||||
0, 3, BOOKE_PAGESZ_1G, 1),
|
||||
|
||||
/* *I*G* - PCI */
|
||||
SET_TLB_ENTRY(1, CONFIG_SYS_PCIE1_MEM_VIRT + 0x40000000,
|
||||
CONFIG_SYS_PCIE1_MEM_PHYS + 0x40000000,
|
||||
MAS3_SW|MAS3_SR, MAS2_I|MAS2_G,
|
||||
0, 4, BOOKE_PAGESZ_256M, 1),
|
||||
|
||||
SET_TLB_ENTRY(1, CONFIG_SYS_PCIE1_MEM_VIRT + 0x50000000,
|
||||
CONFIG_SYS_PCIE1_MEM_PHYS + 0x50000000,
|
||||
MAS3_SW|MAS3_SR, MAS2_I|MAS2_G,
|
||||
0, 5, BOOKE_PAGESZ_256M, 1),
|
||||
|
||||
/* *I*G* - PCI I/O */
|
||||
SET_TLB_ENTRY(1, CONFIG_SYS_PCIE1_IO_VIRT, CONFIG_SYS_PCIE1_IO_PHYS,
|
||||
MAS3_SW|MAS3_SR, MAS2_I|MAS2_G,
|
||||
0, 6, BOOKE_PAGESZ_256K, 1),
|
||||
|
||||
/* Bman/Qman */
|
||||
#ifdef CONFIG_SYS_BMAN_MEM_PHYS
|
||||
SET_TLB_ENTRY(1, CONFIG_SYS_BMAN_MEM_BASE, CONFIG_SYS_BMAN_MEM_PHYS,
|
||||
MAS3_SW|MAS3_SR, 0,
|
||||
0, 9, BOOKE_PAGESZ_1M, 1),
|
||||
SET_TLB_ENTRY(1, CONFIG_SYS_BMAN_MEM_BASE + 0x00100000,
|
||||
CONFIG_SYS_BMAN_MEM_PHYS + 0x00100000,
|
||||
MAS3_SW|MAS3_SR, MAS2_I|MAS2_G,
|
||||
0, 10, BOOKE_PAGESZ_1M, 1),
|
||||
#endif
|
||||
#ifdef CONFIG_SYS_QMAN_MEM_PHYS
|
||||
SET_TLB_ENTRY(1, CONFIG_SYS_QMAN_MEM_BASE, CONFIG_SYS_QMAN_MEM_PHYS,
|
||||
MAS3_SW|MAS3_SR, 0,
|
||||
0, 11, BOOKE_PAGESZ_1M, 1),
|
||||
SET_TLB_ENTRY(1, CONFIG_SYS_QMAN_MEM_BASE + 0x00100000,
|
||||
CONFIG_SYS_QMAN_MEM_PHYS + 0x00100000,
|
||||
MAS3_SW|MAS3_SR, MAS2_I|MAS2_G,
|
||||
0, 12, BOOKE_PAGESZ_1M, 1),
|
||||
#endif
|
||||
#ifdef CONFIG_SYS_DCSRBAR_PHYS
|
||||
SET_TLB_ENTRY(1, CONFIG_SYS_DCSRBAR, CONFIG_SYS_DCSRBAR_PHYS,
|
||||
MAS3_SW|MAS3_SR, MAS2_I|MAS2_G,
|
||||
0, 13, BOOKE_PAGESZ_4M, 1),
|
||||
#endif
|
||||
#ifdef CONFIG_SYS_NAND_BASE
|
||||
/*
|
||||
* *I*G - NAND
|
||||
* entry 14 and 15 has been used hard coded, they will be disabled
|
||||
* in cpu_init_f, so we use entry 16 for nand.
|
||||
*/
|
||||
SET_TLB_ENTRY(1, CONFIG_SYS_NAND_BASE, CONFIG_SYS_NAND_BASE_PHYS,
|
||||
MAS3_SX|MAS3_SW|MAS3_SR, MAS2_I|MAS2_G,
|
||||
0, 16, BOOKE_PAGESZ_1M, 1),
|
||||
#endif
|
||||
#ifdef CONFIG_SRIO_PCIE_BOOT_SLAVE
|
||||
/*
|
||||
* SRIO_PCIE_BOOT-SLAVE. 1M space from 0xffe00000 for
|
||||
* fetching ucode and ENV from master
|
||||
*/
|
||||
SET_TLB_ENTRY(1, CONFIG_SYS_SRIO_PCIE_BOOT_UCODE_ENV_ADDR,
|
||||
CONFIG_SYS_SRIO_PCIE_BOOT_UCODE_ENV_ADDR_PHYS,
|
||||
MAS3_SX|MAS3_SW|MAS3_SR, MAS2_G,
|
||||
0, 17, BOOKE_PAGESZ_1M, 1),
|
||||
#endif
|
||||
};
|
||||
|
||||
int num_tlb_entries = ARRAY_SIZE(tlb_table);
|
||||
@@ -0,0 +1,173 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Copyright 2014 Freescale Semiconductor, Inc.
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <errno.h>
|
||||
#include <power/pmic.h>
|
||||
#include <power/pfuze100_pmic.h>
|
||||
|
||||
#ifndef CONFIG_DM_PMIC_PFUZE100
|
||||
int pfuze_mode_init(struct pmic *p, u32 mode)
|
||||
{
|
||||
unsigned char offset, i, switch_num;
|
||||
u32 id;
|
||||
int ret;
|
||||
|
||||
pmic_reg_read(p, PFUZE100_DEVICEID, &id);
|
||||
id = id & 0xf;
|
||||
|
||||
if (id == 0) {
|
||||
switch_num = 6;
|
||||
offset = PFUZE100_SW1CMODE;
|
||||
} else if (id == 1) {
|
||||
switch_num = 4;
|
||||
offset = PFUZE100_SW2MODE;
|
||||
} else {
|
||||
printf("Not supported, id=%d\n", id);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = pmic_reg_write(p, PFUZE100_SW1ABMODE, mode);
|
||||
if (ret < 0) {
|
||||
printf("Set SW1AB mode error!\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
for (i = 0; i < switch_num - 1; i++) {
|
||||
ret = pmic_reg_write(p, offset + i * SWITCH_SIZE, mode);
|
||||
if (ret < 0) {
|
||||
printf("Set switch 0x%x mode error!\n",
|
||||
offset + i * SWITCH_SIZE);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
struct pmic *pfuze_common_init(unsigned char i2cbus)
|
||||
{
|
||||
struct pmic *p;
|
||||
int ret;
|
||||
unsigned int reg;
|
||||
|
||||
ret = power_pfuze100_init(i2cbus);
|
||||
if (ret)
|
||||
return NULL;
|
||||
|
||||
p = pmic_get("PFUZE100");
|
||||
ret = pmic_probe(p);
|
||||
if (ret)
|
||||
return NULL;
|
||||
|
||||
pmic_reg_read(p, PFUZE100_DEVICEID, ®);
|
||||
printf("PMIC: PFUZE100 ID=0x%02x\n", reg);
|
||||
|
||||
/* Set SW1AB stanby volage to 0.975V */
|
||||
pmic_reg_read(p, PFUZE100_SW1ABSTBY, ®);
|
||||
reg &= ~SW1x_STBY_MASK;
|
||||
reg |= SW1x_0_975V;
|
||||
pmic_reg_write(p, PFUZE100_SW1ABSTBY, reg);
|
||||
|
||||
/* Set SW1AB/VDDARM step ramp up time from 16us to 4us/25mV */
|
||||
pmic_reg_read(p, PFUZE100_SW1ABCONF, ®);
|
||||
reg &= ~SW1xCONF_DVSSPEED_MASK;
|
||||
reg |= SW1xCONF_DVSSPEED_4US;
|
||||
pmic_reg_write(p, PFUZE100_SW1ABCONF, reg);
|
||||
|
||||
/* Set SW1C standby voltage to 0.975V */
|
||||
pmic_reg_read(p, PFUZE100_SW1CSTBY, ®);
|
||||
reg &= ~SW1x_STBY_MASK;
|
||||
reg |= SW1x_0_975V;
|
||||
pmic_reg_write(p, PFUZE100_SW1CSTBY, reg);
|
||||
|
||||
/* Set SW1C/VDDSOC step ramp up time from 16us to 4us/25mV */
|
||||
pmic_reg_read(p, PFUZE100_SW1CCONF, ®);
|
||||
reg &= ~SW1xCONF_DVSSPEED_MASK;
|
||||
reg |= SW1xCONF_DVSSPEED_4US;
|
||||
pmic_reg_write(p, PFUZE100_SW1CCONF, reg);
|
||||
|
||||
return p;
|
||||
}
|
||||
#else
|
||||
int pfuze_mode_init(struct udevice *dev, u32 mode)
|
||||
{
|
||||
unsigned char offset, i, switch_num;
|
||||
u32 id;
|
||||
int ret;
|
||||
|
||||
id = pmic_reg_read(dev, PFUZE100_DEVICEID);
|
||||
id = id & 0xf;
|
||||
|
||||
if (id == 0) {
|
||||
switch_num = 6;
|
||||
offset = PFUZE100_SW1CMODE;
|
||||
} else if (id == 1) {
|
||||
switch_num = 4;
|
||||
offset = PFUZE100_SW2MODE;
|
||||
} else {
|
||||
printf("Not supported, id=%d\n", id);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = pmic_reg_write(dev, PFUZE100_SW1ABMODE, mode);
|
||||
if (ret < 0) {
|
||||
printf("Set SW1AB mode error!\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
for (i = 0; i < switch_num - 1; i++) {
|
||||
ret = pmic_reg_write(dev, offset + i * SWITCH_SIZE, mode);
|
||||
if (ret < 0) {
|
||||
printf("Set switch 0x%x mode error!\n",
|
||||
offset + i * SWITCH_SIZE);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
struct udevice *pfuze_common_init(void)
|
||||
{
|
||||
struct udevice *dev;
|
||||
int ret;
|
||||
unsigned int reg, dev_id, rev_id;
|
||||
|
||||
ret = pmic_get("pfuze100@8", &dev);
|
||||
if (ret == -ENODEV)
|
||||
return NULL;
|
||||
|
||||
dev_id = pmic_reg_read(dev, PFUZE100_DEVICEID);
|
||||
rev_id = pmic_reg_read(dev, PFUZE100_REVID);
|
||||
printf("PMIC: PFUZE100! DEV_ID=0x%x REV_ID=0x%x\n", dev_id, rev_id);
|
||||
|
||||
/* Set SW1AB stanby volage to 0.975V */
|
||||
reg = pmic_reg_read(dev, PFUZE100_SW1ABSTBY);
|
||||
reg &= ~SW1x_STBY_MASK;
|
||||
reg |= SW1x_0_975V;
|
||||
pmic_reg_write(dev, PFUZE100_SW1ABSTBY, reg);
|
||||
|
||||
/* Set SW1AB/VDDARM step ramp up time from 16us to 4us/25mV */
|
||||
reg = pmic_reg_read(dev, PFUZE100_SW1ABCONF);
|
||||
reg &= ~SW1xCONF_DVSSPEED_MASK;
|
||||
reg |= SW1xCONF_DVSSPEED_4US;
|
||||
pmic_reg_write(dev, PFUZE100_SW1ABCONF, reg);
|
||||
|
||||
/* Set SW1C standby voltage to 0.975V */
|
||||
reg = pmic_reg_read(dev, PFUZE100_SW1CSTBY);
|
||||
reg &= ~SW1x_STBY_MASK;
|
||||
reg |= SW1x_0_975V;
|
||||
pmic_reg_write(dev, PFUZE100_SW1CSTBY, reg);
|
||||
|
||||
/* Set SW1C/VDDSOC step ramp up time from 16us to 4us/25mV */
|
||||
reg = pmic_reg_read(dev, PFUZE100_SW1CCONF);
|
||||
reg &= ~SW1xCONF_DVSSPEED_MASK;
|
||||
reg |= SW1xCONF_DVSSPEED_4US;
|
||||
pmic_reg_write(dev, PFUZE100_SW1CCONF, reg);
|
||||
|
||||
return dev;
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,17 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||
/*
|
||||
* Copyright 2014 Freescale Semiconductor, Inc.
|
||||
*/
|
||||
|
||||
#ifndef __PFUZE_BOARD_HELPER__
|
||||
#define __PFUZE_BOARD_HELPER__
|
||||
|
||||
#ifdef CONFIG_DM_PMIC_PFUZE100
|
||||
struct udevice *pfuze_common_init(void);
|
||||
int pfuze_mode_init(struct udevice *dev, u32 mode);
|
||||
#else
|
||||
struct pmic *pfuze_common_init(unsigned char i2cbus);
|
||||
int pfuze_mode_init(struct pmic *p, u32 mode);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,541 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Copyright 2006,2010 Freescale Semiconductor
|
||||
* Jeff Brown
|
||||
* Srikanth Srinivasan (srikanth.srinivasan@freescale.com)
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <command.h>
|
||||
#include <asm/io.h>
|
||||
|
||||
#define pixis_base (u8 *)PIXIS_BASE
|
||||
|
||||
/*
|
||||
* Simple board reset.
|
||||
*/
|
||||
void pixis_reset(void)
|
||||
{
|
||||
out_8(pixis_base + PIXIS_RST, 0);
|
||||
|
||||
while (1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Per table 27, page 58 of MPC8641HPCN spec.
|
||||
*/
|
||||
static int set_px_sysclk(unsigned long sysclk)
|
||||
{
|
||||
u8 sysclk_s, sysclk_r, sysclk_v, vclkh, vclkl, sysclk_aux;
|
||||
|
||||
switch (sysclk) {
|
||||
case 33:
|
||||
sysclk_s = 0x04;
|
||||
sysclk_r = 0x04;
|
||||
sysclk_v = 0x07;
|
||||
sysclk_aux = 0x00;
|
||||
break;
|
||||
case 40:
|
||||
sysclk_s = 0x01;
|
||||
sysclk_r = 0x1F;
|
||||
sysclk_v = 0x20;
|
||||
sysclk_aux = 0x01;
|
||||
break;
|
||||
case 50:
|
||||
sysclk_s = 0x01;
|
||||
sysclk_r = 0x1F;
|
||||
sysclk_v = 0x2A;
|
||||
sysclk_aux = 0x02;
|
||||
break;
|
||||
case 66:
|
||||
sysclk_s = 0x01;
|
||||
sysclk_r = 0x04;
|
||||
sysclk_v = 0x04;
|
||||
sysclk_aux = 0x03;
|
||||
break;
|
||||
case 83:
|
||||
sysclk_s = 0x01;
|
||||
sysclk_r = 0x1F;
|
||||
sysclk_v = 0x4B;
|
||||
sysclk_aux = 0x04;
|
||||
break;
|
||||
case 100:
|
||||
sysclk_s = 0x01;
|
||||
sysclk_r = 0x1F;
|
||||
sysclk_v = 0x5C;
|
||||
sysclk_aux = 0x05;
|
||||
break;
|
||||
case 134:
|
||||
sysclk_s = 0x06;
|
||||
sysclk_r = 0x1F;
|
||||
sysclk_v = 0x3B;
|
||||
sysclk_aux = 0x06;
|
||||
break;
|
||||
case 166:
|
||||
sysclk_s = 0x06;
|
||||
sysclk_r = 0x1F;
|
||||
sysclk_v = 0x4B;
|
||||
sysclk_aux = 0x07;
|
||||
break;
|
||||
default:
|
||||
printf("Unsupported SYSCLK frequency.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
vclkh = (sysclk_s << 5) | sysclk_r;
|
||||
vclkl = sysclk_v;
|
||||
|
||||
out_8(pixis_base + PIXIS_VCLKH, vclkh);
|
||||
out_8(pixis_base + PIXIS_VCLKL, vclkl);
|
||||
|
||||
out_8(pixis_base + PIXIS_AUX, sysclk_aux);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Set the CFG_SYSPLL bits
|
||||
*
|
||||
* This only has effect if PX_VCFGEN0[SYSPLL]=1, which is true if
|
||||
* read_from_px_regs() is called.
|
||||
*/
|
||||
static int set_px_mpxpll(unsigned long mpxpll)
|
||||
{
|
||||
switch (mpxpll) {
|
||||
case 2:
|
||||
case 4:
|
||||
case 6:
|
||||
case 8:
|
||||
case 10:
|
||||
case 12:
|
||||
case 14:
|
||||
case 16:
|
||||
clrsetbits_8(pixis_base + PIXIS_VSPEED1, 0x1F, mpxpll);
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf("Unsupported MPXPLL ratio.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int set_px_corepll(unsigned long corepll)
|
||||
{
|
||||
u8 val;
|
||||
|
||||
switch (corepll) {
|
||||
case 20:
|
||||
val = 0x08;
|
||||
break;
|
||||
case 25:
|
||||
val = 0x0C;
|
||||
break;
|
||||
case 30:
|
||||
val = 0x10;
|
||||
break;
|
||||
case 35:
|
||||
val = 0x1C;
|
||||
break;
|
||||
case 40:
|
||||
val = 0x14;
|
||||
break;
|
||||
case 45:
|
||||
val = 0x0E;
|
||||
break;
|
||||
default:
|
||||
printf("Unsupported COREPLL ratio.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
clrsetbits_8(pixis_base + PIXIS_VSPEED0, 0x1F, val);
|
||||
return 1;
|
||||
}
|
||||
|
||||
#ifndef CONFIG_SYS_PIXIS_VCFGEN0_ENABLE
|
||||
#define CONFIG_SYS_PIXIS_VCFGEN0_ENABLE 0x1C
|
||||
#endif
|
||||
|
||||
/* Tell the PIXIS where to find the COREPLL, MPXPLL, SYSCLK values
|
||||
*
|
||||
* The PIXIS can be programmed to look at either the on-board dip switches
|
||||
* or various other PIXIS registers to determine the values for COREPLL,
|
||||
* MPXPLL, and SYSCLK.
|
||||
*
|
||||
* CONFIG_SYS_PIXIS_VCFGEN0_ENABLE is the value to write to the PIXIS_VCFGEN0
|
||||
* register that tells the pixis to use the various PIXIS register.
|
||||
*/
|
||||
static void read_from_px_regs(int set)
|
||||
{
|
||||
u8 tmp = in_8(pixis_base + PIXIS_VCFGEN0);
|
||||
|
||||
if (set)
|
||||
tmp = tmp | CONFIG_SYS_PIXIS_VCFGEN0_ENABLE;
|
||||
else
|
||||
tmp = tmp & ~CONFIG_SYS_PIXIS_VCFGEN0_ENABLE;
|
||||
|
||||
out_8(pixis_base + PIXIS_VCFGEN0, tmp);
|
||||
}
|
||||
|
||||
/* CONFIG_SYS_PIXIS_VBOOT_ENABLE is the value to write to the PX_VCFGEN1
|
||||
* register that tells the pixis to use the PX_VBOOT[LBMAP] register.
|
||||
*/
|
||||
#ifndef CONFIG_SYS_PIXIS_VBOOT_ENABLE
|
||||
#define CONFIG_SYS_PIXIS_VBOOT_ENABLE 0x04
|
||||
#endif
|
||||
|
||||
/* Configure the source of the boot location
|
||||
*
|
||||
* The PIXIS can be programmed to look at either the on-board dip switches
|
||||
* or the PX_VBOOT[LBMAP] register to determine where we should boot.
|
||||
*
|
||||
* If we want to boot from the alternate boot bank, we need to tell the PIXIS
|
||||
* to ignore the on-board dip switches and use the PX_VBOOT[LBMAP] instead.
|
||||
*/
|
||||
static void read_from_px_regs_altbank(int set)
|
||||
{
|
||||
u8 tmp = in_8(pixis_base + PIXIS_VCFGEN1);
|
||||
|
||||
if (set)
|
||||
tmp = tmp | CONFIG_SYS_PIXIS_VBOOT_ENABLE;
|
||||
else
|
||||
tmp = tmp & ~CONFIG_SYS_PIXIS_VBOOT_ENABLE;
|
||||
|
||||
out_8(pixis_base + PIXIS_VCFGEN1, tmp);
|
||||
}
|
||||
|
||||
/* CONFIG_SYS_PIXIS_VBOOT_MASK contains the bits to set in VBOOT register that
|
||||
* tells the PIXIS what the alternate flash bank is.
|
||||
*
|
||||
* Note that it's not really a mask. It contains the actual LBMAP bits that
|
||||
* must be set to select the alternate bank. This code assumes that the
|
||||
* primary bank has these bits set to 0, and the alternate bank has these
|
||||
* bits set to 1.
|
||||
*/
|
||||
#ifndef CONFIG_SYS_PIXIS_VBOOT_MASK
|
||||
#define CONFIG_SYS_PIXIS_VBOOT_MASK (0x40)
|
||||
#endif
|
||||
|
||||
/* Tell the PIXIS to boot from the default flash bank
|
||||
*
|
||||
* Program the default flash bank into the VBOOT register. This register is
|
||||
* used only if PX_VCFGEN1[FLASH]=1.
|
||||
*/
|
||||
static void clear_altbank(void)
|
||||
{
|
||||
clrbits_8(pixis_base + PIXIS_VBOOT, CONFIG_SYS_PIXIS_VBOOT_MASK);
|
||||
}
|
||||
|
||||
/* Tell the PIXIS to boot from the alternate flash bank
|
||||
*
|
||||
* Program the alternate flash bank into the VBOOT register. This register is
|
||||
* used only if PX_VCFGEN1[FLASH]=1.
|
||||
*/
|
||||
static void set_altbank(void)
|
||||
{
|
||||
setbits_8(pixis_base + PIXIS_VBOOT, CONFIG_SYS_PIXIS_VBOOT_MASK);
|
||||
}
|
||||
|
||||
/* Reset the board with watchdog disabled.
|
||||
*
|
||||
* This respects the altbank setting.
|
||||
*/
|
||||
static void set_px_go(void)
|
||||
{
|
||||
/* Disable the VELA sequencer and watchdog */
|
||||
clrbits_8(pixis_base + PIXIS_VCTL, 9);
|
||||
|
||||
/* Reboot by starting the VELA sequencer */
|
||||
setbits_8(pixis_base + PIXIS_VCTL, 0x1);
|
||||
|
||||
while (1);
|
||||
}
|
||||
|
||||
/* Reset the board with watchdog enabled.
|
||||
*
|
||||
* This respects the altbank setting.
|
||||
*/
|
||||
static void set_px_go_with_watchdog(void)
|
||||
{
|
||||
/* Disable the VELA sequencer */
|
||||
clrbits_8(pixis_base + PIXIS_VCTL, 1);
|
||||
|
||||
/* Enable the watchdog and reboot by starting the VELA sequencer */
|
||||
setbits_8(pixis_base + PIXIS_VCTL, 0x9);
|
||||
|
||||
while (1);
|
||||
}
|
||||
|
||||
/* Disable the watchdog
|
||||
*
|
||||
*/
|
||||
static int pixis_disable_watchdog_cmd(cmd_tbl_t *cmdtp, int flag, int argc,
|
||||
char * const argv[])
|
||||
{
|
||||
/* Disable the VELA sequencer and the watchdog */
|
||||
clrbits_8(pixis_base + PIXIS_VCTL, 9);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
U_BOOT_CMD(
|
||||
diswd, 1, 0, pixis_disable_watchdog_cmd,
|
||||
"Disable watchdog timer",
|
||||
""
|
||||
);
|
||||
|
||||
#ifdef CONFIG_PIXIS_SGMII_CMD
|
||||
|
||||
/* Enable or disable SGMII mode for a TSEC
|
||||
*/
|
||||
static int pixis_set_sgmii(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
|
||||
{
|
||||
int which_tsec = -1;
|
||||
unsigned char mask;
|
||||
unsigned char switch_mask;
|
||||
|
||||
if ((argc > 2) && (strcmp(argv[1], "all") != 0))
|
||||
which_tsec = simple_strtoul(argv[1], NULL, 0);
|
||||
|
||||
switch (which_tsec) {
|
||||
#ifdef CONFIG_TSEC1
|
||||
case 1:
|
||||
mask = PIXIS_VSPEED2_TSEC1SER;
|
||||
switch_mask = PIXIS_VCFGEN1_TSEC1SER;
|
||||
break;
|
||||
#endif
|
||||
#ifdef CONFIG_TSEC2
|
||||
case 2:
|
||||
mask = PIXIS_VSPEED2_TSEC2SER;
|
||||
switch_mask = PIXIS_VCFGEN1_TSEC2SER;
|
||||
break;
|
||||
#endif
|
||||
#ifdef CONFIG_TSEC3
|
||||
case 3:
|
||||
mask = PIXIS_VSPEED2_TSEC3SER;
|
||||
switch_mask = PIXIS_VCFGEN1_TSEC3SER;
|
||||
break;
|
||||
#endif
|
||||
#ifdef CONFIG_TSEC4
|
||||
case 4:
|
||||
mask = PIXIS_VSPEED2_TSEC4SER;
|
||||
switch_mask = PIXIS_VCFGEN1_TSEC4SER;
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
mask = PIXIS_VSPEED2_MASK;
|
||||
switch_mask = PIXIS_VCFGEN1_MASK;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Toggle whether the switches or FPGA control the settings */
|
||||
if (!strcmp(argv[argc - 1], "switch"))
|
||||
clrbits_8(pixis_base + PIXIS_VCFGEN1, switch_mask);
|
||||
else
|
||||
setbits_8(pixis_base + PIXIS_VCFGEN1, switch_mask);
|
||||
|
||||
/* If it's not the switches, enable or disable SGMII, as specified */
|
||||
if (!strcmp(argv[argc - 1], "on"))
|
||||
clrbits_8(pixis_base + PIXIS_VSPEED2, mask);
|
||||
else if (!strcmp(argv[argc - 1], "off"))
|
||||
setbits_8(pixis_base + PIXIS_VSPEED2, mask);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
U_BOOT_CMD(
|
||||
pixis_set_sgmii, CONFIG_SYS_MAXARGS, 1, pixis_set_sgmii,
|
||||
"pixis_set_sgmii"
|
||||
" - Enable or disable SGMII mode for a given TSEC \n",
|
||||
"\npixis_set_sgmii [TSEC num] <on|off|switch>\n"
|
||||
" TSEC num: 1,2,3,4 or 'all'. 'all' is default.\n"
|
||||
" on - enables SGMII\n"
|
||||
" off - disables SGMII\n"
|
||||
" switch - use switch settings"
|
||||
);
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
* This function takes the non-integral cpu:mpx pll ratio
|
||||
* and converts it to an integer that can be used to assign
|
||||
* FPGA register values.
|
||||
* input: strptr i.e. argv[2]
|
||||
*/
|
||||
static unsigned long strfractoint(char *strptr)
|
||||
{
|
||||
int i, j;
|
||||
int mulconst;
|
||||
int no_dec = 0;
|
||||
unsigned long intval = 0, decval = 0;
|
||||
char intarr[3], decarr[3];
|
||||
|
||||
/* Assign the integer part to intarr[]
|
||||
* If there is no decimal point i.e.
|
||||
* if the ratio is an integral value
|
||||
* simply create the intarr.
|
||||
*/
|
||||
i = 0;
|
||||
while (strptr[i] != '.') {
|
||||
if (strptr[i] == 0) {
|
||||
no_dec = 1;
|
||||
break;
|
||||
}
|
||||
intarr[i] = strptr[i];
|
||||
i++;
|
||||
}
|
||||
|
||||
intarr[i] = '\0';
|
||||
|
||||
if (no_dec) {
|
||||
/* Currently needed only for single digit corepll ratios */
|
||||
mulconst = 10;
|
||||
decval = 0;
|
||||
} else {
|
||||
j = 0;
|
||||
i++; /* Skipping the decimal point */
|
||||
while ((strptr[i] >= '0') && (strptr[i] <= '9')) {
|
||||
decarr[j] = strptr[i];
|
||||
i++;
|
||||
j++;
|
||||
}
|
||||
|
||||
decarr[j] = '\0';
|
||||
|
||||
mulconst = 1;
|
||||
for (i = 0; i < j; i++)
|
||||
mulconst *= 10;
|
||||
decval = simple_strtoul(decarr, NULL, 10);
|
||||
}
|
||||
|
||||
intval = simple_strtoul(intarr, NULL, 10);
|
||||
intval = intval * mulconst;
|
||||
|
||||
return intval + decval;
|
||||
}
|
||||
|
||||
static int pixis_reset_cmd(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
|
||||
{
|
||||
unsigned int i;
|
||||
char *p_cf = NULL;
|
||||
char *p_cf_sysclk = NULL;
|
||||
char *p_cf_corepll = NULL;
|
||||
char *p_cf_mpxpll = NULL;
|
||||
char *p_altbank = NULL;
|
||||
char *p_wd = NULL;
|
||||
int unknown_param = 0;
|
||||
|
||||
/*
|
||||
* No args is a simple reset request.
|
||||
*/
|
||||
if (argc <= 1) {
|
||||
pixis_reset();
|
||||
/* not reached */
|
||||
}
|
||||
|
||||
for (i = 1; i < argc; i++) {
|
||||
if (strcmp(argv[i], "cf") == 0) {
|
||||
p_cf = argv[i];
|
||||
if (i + 3 >= argc) {
|
||||
break;
|
||||
}
|
||||
p_cf_sysclk = argv[i+1];
|
||||
p_cf_corepll = argv[i+2];
|
||||
p_cf_mpxpll = argv[i+3];
|
||||
i += 3;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (strcmp(argv[i], "altbank") == 0) {
|
||||
p_altbank = argv[i];
|
||||
continue;
|
||||
}
|
||||
|
||||
if (strcmp(argv[i], "wd") == 0) {
|
||||
p_wd = argv[i];
|
||||
continue;
|
||||
}
|
||||
|
||||
unknown_param = 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check that cf has all required parms
|
||||
*/
|
||||
if ((p_cf && !(p_cf_sysclk && p_cf_corepll && p_cf_mpxpll))
|
||||
|| unknown_param) {
|
||||
#ifdef CONFIG_SYS_LONGHELP
|
||||
puts(cmdtp->help);
|
||||
putc('\n');
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* PIXIS seems to be sensitive to the ordering of
|
||||
* the registers that are touched.
|
||||
*/
|
||||
read_from_px_regs(0);
|
||||
|
||||
if (p_altbank)
|
||||
read_from_px_regs_altbank(0);
|
||||
|
||||
clear_altbank();
|
||||
|
||||
/*
|
||||
* Clock configuration specified.
|
||||
*/
|
||||
if (p_cf) {
|
||||
unsigned long sysclk;
|
||||
unsigned long corepll;
|
||||
unsigned long mpxpll;
|
||||
|
||||
sysclk = simple_strtoul(p_cf_sysclk, NULL, 10);
|
||||
corepll = strfractoint(p_cf_corepll);
|
||||
mpxpll = simple_strtoul(p_cf_mpxpll, NULL, 10);
|
||||
|
||||
if (!(set_px_sysclk(sysclk)
|
||||
&& set_px_corepll(corepll)
|
||||
&& set_px_mpxpll(mpxpll))) {
|
||||
#ifdef CONFIG_SYS_LONGHELP
|
||||
puts(cmdtp->help);
|
||||
putc('\n');
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
read_from_px_regs(1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Altbank specified
|
||||
*
|
||||
* NOTE CHANGE IN BEHAVIOR: previous code would default
|
||||
* to enabling watchdog if altbank is specified.
|
||||
* Now the watchdog must be enabled explicitly using 'wd'.
|
||||
*/
|
||||
if (p_altbank) {
|
||||
set_altbank();
|
||||
read_from_px_regs_altbank(1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Reset with watchdog specified.
|
||||
*/
|
||||
if (p_wd)
|
||||
set_px_go_with_watchdog();
|
||||
else
|
||||
set_px_go();
|
||||
|
||||
/*
|
||||
* Shouldn't be reached.
|
||||
*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
U_BOOT_CMD(
|
||||
pixis_reset, CONFIG_SYS_MAXARGS, 1, pixis_reset_cmd,
|
||||
"Reset the board using the FPGA sequencer",
|
||||
" pixis_reset\n"
|
||||
" pixis_reset [altbank]\n"
|
||||
" pixis_reset altbank wd\n"
|
||||
" pixis_reset altbank cf <SYSCLK freq> <COREPLL ratio> <MPXPLL ratio>\n"
|
||||
" pixis_reset cf <SYSCLK freq> <COREPLL ratio> <MPXPLL ratio>"
|
||||
);
|
||||
@@ -0,0 +1,165 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||
/*
|
||||
* Copyright 2010 Freescale Semiconductor, Inc.
|
||||
*/
|
||||
#ifndef __PIXIS_H_
|
||||
#define __PIXIS_H_ 1
|
||||
|
||||
/* PIXIS register set. */
|
||||
#if defined(CONFIG_TARGET_MPC8536DS)
|
||||
typedef struct pixis {
|
||||
u8 id;
|
||||
u8 ver;
|
||||
u8 pver;
|
||||
u8 csr;
|
||||
u8 rst;
|
||||
u8 rst2;
|
||||
u8 aux1;
|
||||
u8 spd;
|
||||
u8 aux2;
|
||||
u8 csr2;
|
||||
u8 watch;
|
||||
u8 led;
|
||||
u8 pwr;
|
||||
u8 res[3];
|
||||
u8 vctl;
|
||||
u8 vstat;
|
||||
u8 vcfgen0;
|
||||
u8 vcfgen1;
|
||||
u8 vcore0;
|
||||
u8 res1;
|
||||
u8 vboot;
|
||||
u8 vspeed[3];
|
||||
u8 sclk[3];
|
||||
u8 dclk[3];
|
||||
u8 i2cdacr;
|
||||
u8 vcoreacc[4];
|
||||
u8 vcorecnt[3];
|
||||
u8 vcoremax[2];
|
||||
u8 vplatacc[4];
|
||||
u8 vplatcnt[3];
|
||||
u8 vplatmax[2];
|
||||
u8 vtempacc[4];
|
||||
u8 vtempcnt[3];
|
||||
u8 vtempmax[2];
|
||||
u8 res2[4];
|
||||
} __attribute__ ((packed)) pixis_t;
|
||||
|
||||
#elif defined(CONFIG_TARGET_MPC8544DS)
|
||||
typedef struct pixis {
|
||||
u8 id;
|
||||
u8 ver;
|
||||
u8 pver;
|
||||
u8 csr;
|
||||
u8 rst;
|
||||
u8 pwr;
|
||||
u8 aux1;
|
||||
u8 spd;
|
||||
u8 res[8];
|
||||
u8 vctl;
|
||||
u8 vstat;
|
||||
u8 vcfgen0;
|
||||
u8 vcfgen1;
|
||||
u8 vcore0;
|
||||
u8 res1;
|
||||
u8 vboot;
|
||||
u8 vspeed[2];
|
||||
u8 vclkh;
|
||||
u8 vclkl;
|
||||
u8 watch;
|
||||
u8 led;
|
||||
u8 vspeed2;
|
||||
u8 res2[34];
|
||||
} __attribute__ ((packed)) pixis_t;
|
||||
|
||||
#elif defined(CONFIG_TARGET_MPC8572DS)
|
||||
typedef struct pixis {
|
||||
u8 id;
|
||||
u8 ver;
|
||||
u8 pver;
|
||||
u8 csr;
|
||||
u8 rst;
|
||||
u8 pwr1;
|
||||
u8 aux1;
|
||||
u8 spd;
|
||||
u8 aux2;
|
||||
u8 res[7];
|
||||
u8 vctl;
|
||||
u8 vstat;
|
||||
u8 vcfgen0;
|
||||
u8 vcfgen1;
|
||||
u8 vcore0;
|
||||
u8 res1;
|
||||
u8 vboot;
|
||||
u8 vspeed[3];
|
||||
u8 res2[2];
|
||||
u8 sclk[3];
|
||||
u8 dclk[3];
|
||||
u8 res3[2];
|
||||
u8 watch;
|
||||
u8 led;
|
||||
u8 res4[25];
|
||||
} __attribute__ ((packed)) pixis_t;
|
||||
|
||||
#elif defined(CONFIG_TARGET_MPC8610HPCD)
|
||||
typedef struct pixis {
|
||||
u8 id;
|
||||
u8 ver; /* also called arch */
|
||||
u8 pver;
|
||||
u8 csr;
|
||||
u8 rst;
|
||||
u8 pwr;
|
||||
u8 aux;
|
||||
u8 spd;
|
||||
u8 brdcfg0;
|
||||
u8 brdcfg1;
|
||||
u8 res[4];
|
||||
u8 led;
|
||||
u8 serno;
|
||||
u8 vctl;
|
||||
u8 vstat;
|
||||
u8 vcfgen0;
|
||||
u8 vcfgen1;
|
||||
u8 vcore0;
|
||||
u8 res1;
|
||||
u8 vboot;
|
||||
u8 vspeed[2];
|
||||
u8 res2;
|
||||
u8 sclk[3];
|
||||
u8 res3;
|
||||
u8 watch;
|
||||
u8 res4[33];
|
||||
} __attribute__ ((packed)) pixis_t;
|
||||
|
||||
#elif defined(CONFIG_TARGET_MPC8641HPCN)
|
||||
typedef struct pixis {
|
||||
u8 id;
|
||||
u8 ver;
|
||||
u8 pver;
|
||||
u8 csr;
|
||||
u8 rst;
|
||||
u8 pwr;
|
||||
u8 aux;
|
||||
u8 spd;
|
||||
u8 res[8];
|
||||
u8 vctl;
|
||||
u8 vstat;
|
||||
u8 vcfgen0;
|
||||
u8 vcfgen1;
|
||||
u8 vcore0;
|
||||
u8 res1;
|
||||
u8 vboot;
|
||||
u8 vspeed[2];
|
||||
u8 vclkh;
|
||||
u8 vclkl;
|
||||
u8 watch;
|
||||
u8 res3[36];
|
||||
} __attribute__ ((packed)) pixis_t;
|
||||
#else
|
||||
#error Need to define pixis_t for this board
|
||||
#endif
|
||||
|
||||
/* Pointer to the PIXIS register set */
|
||||
#define pixis ((pixis_t *)PIXIS_BASE)
|
||||
|
||||
#endif /* __PIXIS_H_ */
|
||||
@@ -0,0 +1,102 @@
|
||||
/*
|
||||
* Copyright (C) 2007 Freescale Semiconductor, Inc.
|
||||
*
|
||||
* Tony Li <tony.li@freescale.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation;
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <i2c.h>
|
||||
#include <asm/io.h>
|
||||
|
||||
#include "pq-mds-pib.h"
|
||||
|
||||
int pib_init(void)
|
||||
{
|
||||
u8 val8;
|
||||
u8 orig_i2c_bus;
|
||||
|
||||
/* Switch temporarily to I2C bus #2 */
|
||||
orig_i2c_bus = i2c_get_bus_num();
|
||||
i2c_set_bus_num(1);
|
||||
|
||||
val8 = 0;
|
||||
#if defined(CONFIG_PCI) && !defined(CONFIG_PCISLAVE)
|
||||
/* Assign PIB PMC slot to desired PCI bus */
|
||||
i2c_write(0x23, 0x6, 1, &val8, 1);
|
||||
i2c_write(0x23, 0x7, 1, &val8, 1);
|
||||
val8 = 0xff;
|
||||
i2c_write(0x23, 0x2, 1, &val8, 1);
|
||||
i2c_write(0x23, 0x3, 1, &val8, 1);
|
||||
|
||||
val8 = 0;
|
||||
i2c_write(0x26, 0x6, 1, &val8, 1);
|
||||
val8 = 0x34;
|
||||
i2c_write(0x26, 0x7, 1, &val8, 1);
|
||||
#if defined(CONFIG_TARGET_MPC832XEMDS)
|
||||
val8 = 0xf9; /* PMC2, PMC3 slot to PCI bus */
|
||||
#else
|
||||
val8 = 0xf3; /* PMC1, PMC2, PMC3 slot to PCI bus */
|
||||
#endif
|
||||
i2c_write(0x26, 0x2, 1, &val8, 1);
|
||||
val8 = 0xff;
|
||||
i2c_write(0x26, 0x3, 1, &val8, 1);
|
||||
|
||||
val8 = 0;
|
||||
i2c_write(0x27, 0x6, 1, &val8, 1);
|
||||
i2c_write(0x27, 0x7, 1, &val8, 1);
|
||||
val8 = 0xff;
|
||||
i2c_write(0x27, 0x2, 1, &val8, 1);
|
||||
val8 = 0xef;
|
||||
i2c_write(0x27, 0x3, 1, &val8, 1);
|
||||
|
||||
eieio();
|
||||
|
||||
#if defined(CONFIG_TARGET_MPC832XEMDS)
|
||||
printf("PCI 32bit bus on PMC2 &PMC3\n");
|
||||
#else
|
||||
printf("PCI 32bit bus on PMC1 & PMC2 &PMC3\n");
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_PQ_MDS_PIB_ATM)
|
||||
#if defined(CONFIG_TARGET_MPC8569MDS)
|
||||
val8 = 0;
|
||||
i2c_write(0x20, 0x6, 1, &val8, 1);
|
||||
i2c_write(0x20, 0x7, 1, &val8, 1);
|
||||
|
||||
val8 = 0xdf;
|
||||
i2c_write(0x20, 0x2, 1, &val8, 1);
|
||||
val8 = 0xf7;
|
||||
i2c_write(0x20, 0x3, 1, &val8, 1);
|
||||
|
||||
eieio();
|
||||
|
||||
printf("QOC3 ATM card on PMC0\n");
|
||||
#elif defined(CONFIG_TARGET_MPC832XEMDS)
|
||||
val8 = 0;
|
||||
i2c_write(0x26, 0x7, 1, &val8, 1);
|
||||
val8 = 0xf7;
|
||||
i2c_write(0x26, 0x3, 1, &val8, 1);
|
||||
|
||||
val8 = 0;
|
||||
i2c_write(0x21, 0x6, 1, &val8, 1);
|
||||
i2c_write(0x21, 0x7, 1, &val8, 1);
|
||||
|
||||
val8 = 0xdf;
|
||||
i2c_write(0x21, 0x2, 1, &val8, 1);
|
||||
val8 = 0xef;
|
||||
i2c_write(0x21, 0x3, 1, &val8, 1);
|
||||
|
||||
eieio();
|
||||
|
||||
printf("QOC3 ATM card on PMC1\n");
|
||||
#endif
|
||||
#endif
|
||||
/* Reset to original I2C bus */
|
||||
i2c_set_bus_num(orig_i2c_bus);
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
/*
|
||||
* Copyright (C) 2007 Freescale Semiconductor, Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation;
|
||||
*/
|
||||
|
||||
extern int pib_init(void);
|
||||
@@ -0,0 +1,370 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Copyright 2011 Freescale Semiconductor
|
||||
* Author: Shengzhou Liu <Shengzhou.Liu@freescale.com>
|
||||
*
|
||||
* This file provides support for the QIXIS of some Freescale reference boards.
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <command.h>
|
||||
#include <asm/io.h>
|
||||
#include <linux/compiler.h>
|
||||
#include <linux/time.h>
|
||||
#include <i2c.h>
|
||||
#include "qixis.h"
|
||||
|
||||
#ifndef QIXIS_LBMAP_BRDCFG_REG
|
||||
/*
|
||||
* For consistency with existing platforms
|
||||
*/
|
||||
#define QIXIS_LBMAP_BRDCFG_REG 0x00
|
||||
#endif
|
||||
|
||||
#ifndef QIXIS_RCFG_CTL_RECONFIG_IDLE
|
||||
#define QIXIS_RCFG_CTL_RECONFIG_IDLE 0x20
|
||||
#endif
|
||||
#ifndef QIXIS_RCFG_CTL_RECONFIG_START
|
||||
#define QIXIS_RCFG_CTL_RECONFIG_START 0x21
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SYS_I2C_FPGA_ADDR
|
||||
u8 qixis_read_i2c(unsigned int reg)
|
||||
{
|
||||
#ifndef CONFIG_DM_I2C
|
||||
return i2c_reg_read(CONFIG_SYS_I2C_FPGA_ADDR, reg);
|
||||
#else
|
||||
struct udevice *dev;
|
||||
|
||||
if (i2c_get_chip_for_busnum(0, CONFIG_SYS_I2C_FPGA_ADDR, 1, &dev))
|
||||
return 0xff;
|
||||
|
||||
return dm_i2c_reg_read(dev, reg);
|
||||
#endif
|
||||
}
|
||||
|
||||
void qixis_write_i2c(unsigned int reg, u8 value)
|
||||
{
|
||||
u8 val = value;
|
||||
#ifndef CONFIG_DM_I2C
|
||||
i2c_reg_write(CONFIG_SYS_I2C_FPGA_ADDR, reg, val);
|
||||
#else
|
||||
struct udevice *dev;
|
||||
|
||||
if (!i2c_get_chip_for_busnum(0, CONFIG_SYS_I2C_FPGA_ADDR, 1, &dev))
|
||||
dm_i2c_reg_write(dev, reg, val);
|
||||
#endif
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef QIXIS_BASE
|
||||
u8 qixis_read(unsigned int reg)
|
||||
{
|
||||
void *p = (void *)QIXIS_BASE;
|
||||
|
||||
return in_8(p + reg);
|
||||
}
|
||||
|
||||
void qixis_write(unsigned int reg, u8 value)
|
||||
{
|
||||
void *p = (void *)QIXIS_BASE;
|
||||
|
||||
out_8(p + reg, value);
|
||||
}
|
||||
#endif
|
||||
|
||||
u16 qixis_read_minor(void)
|
||||
{
|
||||
u16 minor;
|
||||
|
||||
/* this data is in little endian */
|
||||
QIXIS_WRITE(tagdata, 5);
|
||||
minor = QIXIS_READ(tagdata);
|
||||
QIXIS_WRITE(tagdata, 6);
|
||||
minor += QIXIS_READ(tagdata) << 8;
|
||||
|
||||
return minor;
|
||||
}
|
||||
|
||||
char *qixis_read_time(char *result)
|
||||
{
|
||||
time_t time = 0;
|
||||
int i;
|
||||
|
||||
/* timestamp is in 32-bit big endian */
|
||||
for (i = 8; i <= 11; i++) {
|
||||
QIXIS_WRITE(tagdata, i);
|
||||
time = (time << 8) + QIXIS_READ(tagdata);
|
||||
}
|
||||
|
||||
return ctime_r(&time, result);
|
||||
}
|
||||
|
||||
char *qixis_read_tag(char *buf)
|
||||
{
|
||||
int i;
|
||||
char tag, *ptr = buf;
|
||||
|
||||
for (i = 16; i <= 63; i++) {
|
||||
QIXIS_WRITE(tagdata, i);
|
||||
tag = QIXIS_READ(tagdata);
|
||||
*(ptr++) = tag;
|
||||
if (!tag)
|
||||
break;
|
||||
}
|
||||
if (i > 63)
|
||||
*ptr = '\0';
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
/*
|
||||
* return the string of binary of u8 in the format of
|
||||
* 1010 10_0. The masked bit is filled as underscore.
|
||||
*/
|
||||
const char *byte_to_binary_mask(u8 val, u8 mask, char *buf)
|
||||
{
|
||||
char *ptr;
|
||||
int i;
|
||||
|
||||
ptr = buf;
|
||||
for (i = 0x80; i > 0x08 ; i >>= 1, ptr++)
|
||||
*ptr = (val & i) ? '1' : ((mask & i) ? '_' : '0');
|
||||
*(ptr++) = ' ';
|
||||
for (i = 0x08; i > 0 ; i >>= 1, ptr++)
|
||||
*ptr = (val & i) ? '1' : ((mask & i) ? '_' : '0');
|
||||
|
||||
*ptr = '\0';
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
#ifdef QIXIS_RST_FORCE_MEM
|
||||
void board_assert_mem_reset(void)
|
||||
{
|
||||
u8 rst;
|
||||
|
||||
rst = QIXIS_READ(rst_frc[0]);
|
||||
if (!(rst & QIXIS_RST_FORCE_MEM))
|
||||
QIXIS_WRITE(rst_frc[0], rst | QIXIS_RST_FORCE_MEM);
|
||||
}
|
||||
|
||||
void board_deassert_mem_reset(void)
|
||||
{
|
||||
u8 rst;
|
||||
|
||||
rst = QIXIS_READ(rst_frc[0]);
|
||||
if (rst & QIXIS_RST_FORCE_MEM)
|
||||
QIXIS_WRITE(rst_frc[0], rst & ~QIXIS_RST_FORCE_MEM);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_SPL_BUILD
|
||||
static void qixis_reset(void)
|
||||
{
|
||||
QIXIS_WRITE(rst_ctl, QIXIS_RST_CTL_RESET);
|
||||
}
|
||||
|
||||
#ifdef QIXIS_LBMAP_ALTBANK
|
||||
static void qixis_bank_reset(void)
|
||||
{
|
||||
QIXIS_WRITE(rcfg_ctl, QIXIS_RCFG_CTL_RECONFIG_IDLE);
|
||||
QIXIS_WRITE(rcfg_ctl, QIXIS_RCFG_CTL_RECONFIG_START);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void __maybe_unused set_lbmap(int lbmap)
|
||||
{
|
||||
u8 reg;
|
||||
|
||||
reg = QIXIS_READ(brdcfg[QIXIS_LBMAP_BRDCFG_REG]);
|
||||
reg = (reg & ~QIXIS_LBMAP_MASK) | lbmap;
|
||||
QIXIS_WRITE(brdcfg[QIXIS_LBMAP_BRDCFG_REG], reg);
|
||||
}
|
||||
|
||||
static void __maybe_unused set_rcw_src(int rcw_src)
|
||||
{
|
||||
#ifdef CONFIG_NXP_LSCH3_2
|
||||
QIXIS_WRITE(dutcfg[0], (rcw_src & 0xff));
|
||||
#else
|
||||
u8 reg;
|
||||
|
||||
reg = QIXIS_READ(dutcfg[1]);
|
||||
reg = (reg & ~1) | (rcw_src & 1);
|
||||
QIXIS_WRITE(dutcfg[1], reg);
|
||||
QIXIS_WRITE(dutcfg[0], (rcw_src >> 1) & 0xff);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void qixis_dump_regs(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
printf("id = %02x\n", QIXIS_READ(id));
|
||||
printf("arch = %02x\n", QIXIS_READ(arch));
|
||||
printf("scver = %02x\n", QIXIS_READ(scver));
|
||||
printf("model = %02x\n", QIXIS_READ(model));
|
||||
printf("rst_ctl = %02x\n", QIXIS_READ(rst_ctl));
|
||||
printf("aux = %02x\n", QIXIS_READ(aux));
|
||||
for (i = 0; i < 16; i++)
|
||||
printf("brdcfg%02d = %02x\n", i, QIXIS_READ(brdcfg[i]));
|
||||
for (i = 0; i < 16; i++)
|
||||
printf("dutcfg%02d = %02x\n", i, QIXIS_READ(dutcfg[i]));
|
||||
printf("sclk = %02x%02x%02x\n", QIXIS_READ(sclk[0]),
|
||||
QIXIS_READ(sclk[1]), QIXIS_READ(sclk[2]));
|
||||
printf("dclk = %02x%02x%02x\n", QIXIS_READ(dclk[0]),
|
||||
QIXIS_READ(dclk[1]), QIXIS_READ(dclk[2]));
|
||||
printf("aux = %02x\n", QIXIS_READ(aux));
|
||||
printf("watch = %02x\n", QIXIS_READ(watch));
|
||||
printf("ctl_sys = %02x\n", QIXIS_READ(ctl_sys));
|
||||
printf("rcw_ctl = %02x\n", QIXIS_READ(rcw_ctl));
|
||||
printf("present = %02x\n", QIXIS_READ(present));
|
||||
printf("present2 = %02x\n", QIXIS_READ(present2));
|
||||
printf("clk_spd = %02x\n", QIXIS_READ(clk_spd));
|
||||
printf("stat_dut = %02x\n", QIXIS_READ(stat_dut));
|
||||
printf("stat_sys = %02x\n", QIXIS_READ(stat_sys));
|
||||
printf("stat_alrm = %02x\n", QIXIS_READ(stat_alrm));
|
||||
}
|
||||
|
||||
void __weak qixis_dump_switch(void)
|
||||
{
|
||||
puts("Reverse engineering switch is not implemented for this board\n");
|
||||
}
|
||||
|
||||
static int qixis_reset_cmd(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
|
||||
{
|
||||
int i;
|
||||
|
||||
if (argc <= 1) {
|
||||
set_lbmap(QIXIS_LBMAP_DFLTBANK);
|
||||
qixis_reset();
|
||||
} else if (strcmp(argv[1], "altbank") == 0) {
|
||||
#ifdef QIXIS_LBMAP_ALTBANK
|
||||
set_lbmap(QIXIS_LBMAP_ALTBANK);
|
||||
qixis_bank_reset();
|
||||
#else
|
||||
printf("No Altbank!\n");
|
||||
#endif
|
||||
} else if (strcmp(argv[1], "nand") == 0) {
|
||||
#ifdef QIXIS_LBMAP_NAND
|
||||
QIXIS_WRITE(rst_ctl, 0x30);
|
||||
QIXIS_WRITE(rcfg_ctl, 0);
|
||||
set_lbmap(QIXIS_LBMAP_NAND);
|
||||
set_rcw_src(QIXIS_RCW_SRC_NAND);
|
||||
QIXIS_WRITE(rcfg_ctl, QIXIS_RCFG_CTL_RECONFIG_IDLE);
|
||||
QIXIS_WRITE(rcfg_ctl, QIXIS_RCFG_CTL_RECONFIG_START);
|
||||
#else
|
||||
printf("Not implemented\n");
|
||||
#endif
|
||||
} else if (strcmp(argv[1], "sd") == 0) {
|
||||
#ifdef QIXIS_LBMAP_SD
|
||||
QIXIS_WRITE(rst_ctl, 0x30);
|
||||
QIXIS_WRITE(rcfg_ctl, 0);
|
||||
#ifdef NON_EXTENDED_DUTCFG
|
||||
QIXIS_WRITE(dutcfg[0], QIXIS_RCW_SRC_SD);
|
||||
#else
|
||||
set_lbmap(QIXIS_LBMAP_SD);
|
||||
set_rcw_src(QIXIS_RCW_SRC_SD);
|
||||
#endif
|
||||
QIXIS_WRITE(rcfg_ctl, QIXIS_RCFG_CTL_RECONFIG_IDLE);
|
||||
QIXIS_WRITE(rcfg_ctl, QIXIS_RCFG_CTL_RECONFIG_START);
|
||||
#else
|
||||
printf("Not implemented\n");
|
||||
#endif
|
||||
} else if (strcmp(argv[1], "ifc") == 0) {
|
||||
#ifdef QIXIS_LBMAP_IFC
|
||||
QIXIS_WRITE(rst_ctl, 0x30);
|
||||
QIXIS_WRITE(rcfg_ctl, 0);
|
||||
set_lbmap(QIXIS_LBMAP_IFC);
|
||||
set_rcw_src(QIXIS_RCW_SRC_IFC);
|
||||
QIXIS_WRITE(rcfg_ctl, QIXIS_RCFG_CTL_RECONFIG_IDLE);
|
||||
QIXIS_WRITE(rcfg_ctl, QIXIS_RCFG_CTL_RECONFIG_START);
|
||||
#else
|
||||
printf("Not implemented\n");
|
||||
#endif
|
||||
} else if (strcmp(argv[1], "emmc") == 0) {
|
||||
#ifdef QIXIS_LBMAP_EMMC
|
||||
QIXIS_WRITE(rst_ctl, 0x30);
|
||||
QIXIS_WRITE(rcfg_ctl, 0);
|
||||
set_lbmap(QIXIS_LBMAP_EMMC);
|
||||
set_rcw_src(QIXIS_RCW_SRC_EMMC);
|
||||
QIXIS_WRITE(rcfg_ctl, QIXIS_RCFG_CTL_RECONFIG_IDLE);
|
||||
QIXIS_WRITE(rcfg_ctl, QIXIS_RCFG_CTL_RECONFIG_START);
|
||||
#else
|
||||
printf("Not implemented\n");
|
||||
#endif
|
||||
} else if (strcmp(argv[1], "sd_qspi") == 0) {
|
||||
#ifdef QIXIS_LBMAP_SD_QSPI
|
||||
QIXIS_WRITE(rst_ctl, 0x30);
|
||||
QIXIS_WRITE(rcfg_ctl, 0);
|
||||
set_lbmap(QIXIS_LBMAP_SD_QSPI);
|
||||
set_rcw_src(QIXIS_RCW_SRC_SD);
|
||||
qixis_write_i2c(offsetof(struct qixis, rcfg_ctl),
|
||||
QIXIS_RCFG_CTL_RECONFIG_IDLE);
|
||||
qixis_write_i2c(offsetof(struct qixis, rcfg_ctl),
|
||||
QIXIS_RCFG_CTL_RECONFIG_START);
|
||||
#else
|
||||
printf("Not implemented\n");
|
||||
#endif
|
||||
} else if (strcmp(argv[1], "qspi") == 0) {
|
||||
#ifdef QIXIS_LBMAP_QSPI
|
||||
QIXIS_WRITE(rst_ctl, 0x30);
|
||||
QIXIS_WRITE(rcfg_ctl, 0);
|
||||
set_lbmap(QIXIS_LBMAP_QSPI);
|
||||
set_rcw_src(QIXIS_RCW_SRC_QSPI);
|
||||
qixis_write_i2c(offsetof(struct qixis, rcfg_ctl),
|
||||
QIXIS_RCFG_CTL_RECONFIG_IDLE);
|
||||
qixis_write_i2c(offsetof(struct qixis, rcfg_ctl),
|
||||
QIXIS_RCFG_CTL_RECONFIG_START);
|
||||
#else
|
||||
printf("Not implemented\n");
|
||||
#endif
|
||||
} else if (strcmp(argv[1], "watchdog") == 0) {
|
||||
static char *period[9] = {"2s", "4s", "8s", "16s", "32s",
|
||||
"1min", "2min", "4min", "8min"};
|
||||
u8 rcfg = QIXIS_READ(rcfg_ctl);
|
||||
|
||||
if (argv[2] == NULL) {
|
||||
printf("qixis watchdog <watchdog_period>\n");
|
||||
return 0;
|
||||
}
|
||||
for (i = 0; i < ARRAY_SIZE(period); i++) {
|
||||
if (strcmp(argv[2], period[i]) == 0) {
|
||||
/* disable watchdog */
|
||||
QIXIS_WRITE(rcfg_ctl,
|
||||
rcfg & ~QIXIS_RCFG_CTL_WATCHDOG_ENBLE);
|
||||
QIXIS_WRITE(watch, ((i<<2) - 1));
|
||||
QIXIS_WRITE(rcfg_ctl, rcfg);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
} else if (strcmp(argv[1], "dump") == 0) {
|
||||
qixis_dump_regs();
|
||||
return 0;
|
||||
} else if (strcmp(argv[1], "switch") == 0) {
|
||||
qixis_dump_switch();
|
||||
return 0;
|
||||
} else {
|
||||
printf("Invalid option: %s\n", argv[1]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
U_BOOT_CMD(
|
||||
qixis_reset, CONFIG_SYS_MAXARGS, 1, qixis_reset_cmd,
|
||||
"Reset the board using the FPGA sequencer",
|
||||
"- hard reset to default bank\n"
|
||||
"qixis_reset altbank - reset to alternate bank\n"
|
||||
"qixis_reset nand - reset to nand\n"
|
||||
"qixis_reset sd - reset to sd\n"
|
||||
"qixis_reset sd_qspi - reset to sd with qspi support\n"
|
||||
"qixis_reset qspi - reset to qspi\n"
|
||||
"qixis watchdog <watchdog_period> - set the watchdog period\n"
|
||||
" period: 1s 2s 4s 8s 16s 32s 1min 2min 4min 8min\n"
|
||||
"qixis_reset dump - display the QIXIS registers\n"
|
||||
"qixis_reset switch - display switch\n"
|
||||
);
|
||||
#endif
|
||||
@@ -0,0 +1,136 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||
/*
|
||||
* Copyright 2011 Freescale Semiconductor
|
||||
* Author: Shengzhou Liu <Shengzhou.Liu@freescale.com>
|
||||
*
|
||||
* This file provides support for the QIXIS of some Freescale reference boards.
|
||||
*/
|
||||
|
||||
#ifndef __QIXIS_H_
|
||||
#define __QIXIS_H_
|
||||
|
||||
struct qixis {
|
||||
u8 id; /* ID value uniquely identifying each QDS board type */
|
||||
u8 arch; /* Board version information */
|
||||
u8 scver; /* QIXIS Version Register */
|
||||
u8 model; /* Information of software programming model version */
|
||||
u8 tagdata;
|
||||
u8 ctl_sys;
|
||||
u8 aux; /* Auxiliary Register,0x06 */
|
||||
u8 clk_spd;
|
||||
u8 stat_dut;
|
||||
u8 stat_sys;
|
||||
u8 stat_alrm;
|
||||
u8 present;
|
||||
u8 present2; /* Presence Status Register 2,0x0c */
|
||||
u8 rcw_ctl;
|
||||
u8 ctl_led;
|
||||
u8 i2cblk;
|
||||
u8 rcfg_ctl; /* Reconfig Control Register,0x10 */
|
||||
u8 rcfg_st;
|
||||
u8 dcm_ad;
|
||||
u8 dcm_da;
|
||||
u8 dcmd;
|
||||
u8 dmsg;
|
||||
u8 gdc;
|
||||
u8 gdd; /* DCM Debug Data Register,0x17 */
|
||||
u8 dmack;
|
||||
u8 res1[6];
|
||||
u8 watch; /* Watchdog Register,0x1F */
|
||||
u8 pwr_ctl[2]; /* Power Control Register,0x20 */
|
||||
u8 res2[2];
|
||||
u8 pwr_stat[4]; /* Power Status Register,0x24 */
|
||||
u8 res3[8];
|
||||
u8 clk_spd2[2]; /* SYSCLK clock Speed Register,0x30 */
|
||||
u8 res4[2];
|
||||
u8 sclk[3]; /* Clock Configuration Registers,0x34 */
|
||||
u8 res5;
|
||||
u8 dclk[3];
|
||||
u8 res6;
|
||||
u8 clk_dspd[3];
|
||||
u8 res7;
|
||||
u8 rst_ctl; /* Reset Control Register,0x40 */
|
||||
u8 rst_stat; /* Reset Status Register */
|
||||
u8 rst_rsn; /* Reset Reason Register */
|
||||
u8 rst_frc[2]; /* Reset Force Registers,0x43 */
|
||||
u8 res8[11];
|
||||
u8 brdcfg[16]; /* Board Configuration Register,0x50 */
|
||||
u8 dutcfg[16];
|
||||
u8 rcw_ad[2]; /* RCW SRAM Address Registers,0x70 */
|
||||
u8 rcw_data;
|
||||
u8 res9[5];
|
||||
u8 post_ctl;
|
||||
u8 post_stat;
|
||||
u8 post_dat[2];
|
||||
u8 pi_d[4];
|
||||
u8 gpio_io[4];
|
||||
u8 gpio_dir[4];
|
||||
u8 res10[20];
|
||||
u8 rjtag_ctl;
|
||||
u8 rjtag_dat;
|
||||
u8 res11[2];
|
||||
u8 trig_src[4];
|
||||
u8 trig_dst[4];
|
||||
u8 trig_stat;
|
||||
u8 res12[3];
|
||||
u8 trig_ctr[4];
|
||||
u8 res13[16];
|
||||
u8 clk_freq[6]; /* Clock Measurement Registers */
|
||||
u8 res_c6[8];
|
||||
u8 clk_base[2]; /* Clock Frequency Base Reg */
|
||||
u8 res_d0[8];
|
||||
u8 cms[2]; /* Core Management Space Address Register, 0xD8 */
|
||||
u8 res_c0[6];
|
||||
u8 aux2[4]; /* Auxiliary Registers,0xE0 */
|
||||
u8 res14[10];
|
||||
u8 aux_ad;
|
||||
u8 aux_da;
|
||||
u8 res15[16];
|
||||
};
|
||||
|
||||
u8 qixis_read(unsigned int reg);
|
||||
void qixis_write(unsigned int reg, u8 value);
|
||||
u16 qixis_read_minor(void);
|
||||
char *qixis_read_time(char *result);
|
||||
char *qixis_read_tag(char *buf);
|
||||
const char *byte_to_binary_mask(u8 val, u8 mask, char *buf);
|
||||
#ifdef CONFIG_SYS_I2C_FPGA_ADDR
|
||||
u8 qixis_read_i2c(unsigned int reg);
|
||||
void qixis_write_i2c(unsigned int reg, u8 value);
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_QIXIS_I2C_ACCESS) && defined(CONFIG_SYS_I2C_FPGA_ADDR)
|
||||
#define QIXIS_READ(reg) qixis_read_i2c(offsetof(struct qixis, reg))
|
||||
#define QIXIS_WRITE(reg, value) \
|
||||
qixis_write_i2c(offsetof(struct qixis, reg), value)
|
||||
#else
|
||||
#define QIXIS_READ(reg) qixis_read(offsetof(struct qixis, reg))
|
||||
#define QIXIS_WRITE(reg, value) qixis_write(offsetof(struct qixis, reg), value)
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SYS_I2C_FPGA_ADDR
|
||||
#define QIXIS_READ_I2C(reg) qixis_read_i2c(offsetof(struct qixis, reg))
|
||||
#define QIXIS_WRITE_I2C(reg, value) \
|
||||
qixis_write_i2c(offsetof(struct qixis, reg), value)
|
||||
#endif
|
||||
|
||||
/* Use for SDHC adapter card type identification and operation */
|
||||
#ifdef CONFIG_FSL_ESDHC_ADAPTER_IDENT
|
||||
#define QIXIS_SDID_MASK 0x07
|
||||
#define QIXIS_ESDHC_ADAPTER_TYPE_EMMC45 0x1 /* eMMC Card Rev4.5 */
|
||||
#define QIXIS_ESDHC_ADAPTER_TYPE_SDMMC_LEGACY 0x2 /* SD/MMC Legacy Card */
|
||||
#define QIXIS_ESDHC_ADAPTER_TYPE_EMMC44 0x3 /* eMMC Card Rev4.4 */
|
||||
#define QIXIS_ESDHC_ADAPTER_TYPE_RSV 0x4 /* Reserved */
|
||||
#define QIXIS_ESDHC_ADAPTER_TYPE_MMC 0x5 /* MMC Card */
|
||||
#define QIXIS_ESDHC_ADAPTER_TYPE_SD 0x6 /* SD Card Rev2.0 3.0 */
|
||||
#define QIXIS_ESDHC_NO_ADAPTER 0x7 /* No Card is Present*/
|
||||
|
||||
#define QIXIS_SDCLKIN 0x08
|
||||
#define QIXIS_SDCLKOUT 0x02
|
||||
#define QIXIS_DAT5_6_7 0X02
|
||||
#define QIXIS_DAT4 0X01
|
||||
|
||||
#define QIXIS_EVDD_BY_SDHC_VS 0x0c
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,79 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Copyright 2011 Freescale Semiconductor, Inc.
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <mmc.h>
|
||||
#include <malloc.h>
|
||||
|
||||
/*
|
||||
* The environment variables are written to just after the u-boot image
|
||||
* on SDCard, so we must read the MBR to get the start address and code
|
||||
* length of the u-boot image, then calculate the address of the env.
|
||||
*/
|
||||
#define ESDHC_BOOT_IMAGE_SIZE 0x48
|
||||
#define ESDHC_BOOT_IMAGE_ADDR 0x50
|
||||
|
||||
#define ESDHC_DEFAULT_ENVADDR 0x400
|
||||
|
||||
int mmc_get_env_addr(struct mmc *mmc, int copy, u32 *env_addr)
|
||||
{
|
||||
u8 *tmp_buf;
|
||||
u32 blklen, code_offset, code_len, n;
|
||||
|
||||
blklen = mmc->read_bl_len;
|
||||
tmp_buf = malloc(blklen);
|
||||
if (!tmp_buf)
|
||||
return 1;
|
||||
|
||||
/* read out the first block, get the config data information */
|
||||
#ifdef CONFIG_BLK
|
||||
n = blk_dread(mmc_get_blk_desc(mmc), 0, 1, tmp_buf);
|
||||
#else
|
||||
n = mmc->block_dev.block_read(&mmc->block_dev, 0, 1, tmp_buf);
|
||||
#endif
|
||||
if (!n) {
|
||||
free(tmp_buf);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Get the Source Address, from offset 0x50 */
|
||||
code_offset = *(u32 *)(tmp_buf + ESDHC_BOOT_IMAGE_ADDR);
|
||||
|
||||
/* Get the code size from offset 0x48 */
|
||||
code_len = *(u32 *)(tmp_buf + ESDHC_BOOT_IMAGE_SIZE);
|
||||
|
||||
#ifdef CONFIG_ESDHC_HC_BLK_ADDR
|
||||
/*
|
||||
* On soc BSC9131, BSC9132:
|
||||
* In High Capacity SD Cards (> 2 GBytes), the 32-bit source address and
|
||||
* code length of these soc specify the memory address in block address
|
||||
* format. Block length is fixed to 512 bytes as per the SD High
|
||||
* Capacity specification.
|
||||
*/
|
||||
u64 tmp;
|
||||
|
||||
if (mmc->high_capacity) {
|
||||
tmp = (u64)code_offset * blklen;
|
||||
tmp += code_len * blklen;
|
||||
} else
|
||||
tmp = code_offset + code_len;
|
||||
|
||||
if ((tmp + CONFIG_ENV_SIZE > mmc->capacity) ||
|
||||
(tmp > 0xFFFFFFFFU))
|
||||
*env_addr = ESDHC_DEFAULT_ENVADDR;
|
||||
else
|
||||
*env_addr = tmp;
|
||||
|
||||
free(tmp_buf);
|
||||
|
||||
return 0;
|
||||
#endif
|
||||
|
||||
*env_addr = code_offset + code_len;
|
||||
|
||||
free(tmp_buf);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,129 @@
|
||||
/*
|
||||
* Freescale SGMII Riser Card
|
||||
*
|
||||
* This driver supports the SGMII Riser card found on the
|
||||
* "DS" style of development board from Freescale.
|
||||
*
|
||||
* This software may be used and distributed according to the
|
||||
* terms of the GNU Public License, Version 2, incorporated
|
||||
* herein by reference.
|
||||
*
|
||||
* Copyright 2008 Freescale Semiconductor, Inc.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
#include <common.h>
|
||||
#include <net.h>
|
||||
#include <linux/libfdt.h>
|
||||
#include <tsec.h>
|
||||
#include <fdt_support.h>
|
||||
|
||||
void fsl_sgmii_riser_init(struct tsec_info_struct *tsec_info, int num)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < num; i++)
|
||||
if (tsec_info[i].flags & TSEC_SGMII)
|
||||
tsec_info[i].phyaddr += SGMII_RISER_PHY_OFFSET;
|
||||
}
|
||||
|
||||
void fsl_sgmii_riser_fdt_fixup(void *fdt)
|
||||
{
|
||||
struct eth_device *dev;
|
||||
int node;
|
||||
int mdio_node;
|
||||
int i = -1;
|
||||
int etsec_num = 0;
|
||||
|
||||
node = fdt_path_offset(fdt, "/aliases");
|
||||
if (node < 0)
|
||||
return;
|
||||
|
||||
while ((dev = eth_get_dev_by_index(++i)) != NULL) {
|
||||
struct tsec_private *priv;
|
||||
int phy_node;
|
||||
int enet_node;
|
||||
uint32_t ph;
|
||||
char sgmii_phy[16];
|
||||
char enet[16];
|
||||
const u32 *phyh;
|
||||
const char *model;
|
||||
const char *path;
|
||||
|
||||
if (!strstr(dev->name, "eTSEC"))
|
||||
continue;
|
||||
|
||||
priv = dev->priv;
|
||||
if (!(priv->flags & TSEC_SGMII)) {
|
||||
etsec_num++;
|
||||
continue;
|
||||
}
|
||||
|
||||
mdio_node = fdt_node_offset_by_compatible(fdt, -1,
|
||||
"fsl,gianfar-mdio");
|
||||
if (mdio_node < 0)
|
||||
return;
|
||||
|
||||
sprintf(sgmii_phy, "sgmii-phy@%d", etsec_num);
|
||||
phy_node = fdt_subnode_offset(fdt, mdio_node, sgmii_phy);
|
||||
if (phy_node > 0) {
|
||||
fdt_increase_size(fdt, 32);
|
||||
ph = fdt_create_phandle(fdt, phy_node);
|
||||
if (!ph)
|
||||
continue;
|
||||
}
|
||||
|
||||
sprintf(enet, "ethernet%d", etsec_num++);
|
||||
path = fdt_getprop(fdt, node, enet, NULL);
|
||||
if (!path) {
|
||||
debug("No alias for %s\n", enet);
|
||||
continue;
|
||||
}
|
||||
|
||||
enet_node = fdt_path_offset(fdt, path);
|
||||
if (enet_node < 0)
|
||||
continue;
|
||||
|
||||
model = fdt_getprop(fdt, enet_node, "model", NULL);
|
||||
|
||||
/*
|
||||
* We only want to do this to eTSECs. On some platforms
|
||||
* there are more than one type of gianfar-style ethernet
|
||||
* controller, and as we are creating an implicit connection
|
||||
* between ethernet nodes and eTSEC devices, it is best to
|
||||
* make the connection use as much explicit information
|
||||
* as exists.
|
||||
*/
|
||||
if (!strstr(model, "TSEC"))
|
||||
continue;
|
||||
|
||||
if (phy_node < 0) {
|
||||
/*
|
||||
* This part is only for old device tree without
|
||||
* sgmii_phy nodes. It's kept just for compatible
|
||||
* reason. Soon to be deprecated if all device tree
|
||||
* get updated.
|
||||
*/
|
||||
phyh = fdt_getprop(fdt, enet_node, "phy-handle", NULL);
|
||||
if (!phyh)
|
||||
continue;
|
||||
|
||||
phy_node = fdt_node_offset_by_phandle(fdt,
|
||||
fdt32_to_cpu(*phyh));
|
||||
|
||||
priv = dev->priv;
|
||||
|
||||
if (priv->flags & TSEC_SGMII)
|
||||
fdt_setprop_cell(fdt, phy_node, "reg",
|
||||
priv->phyaddr);
|
||||
} else {
|
||||
fdt_setprop(fdt, enet_node, "phy-handle", &ph,
|
||||
sizeof(ph));
|
||||
fdt_setprop_string(fdt, enet_node,
|
||||
"phy-connection-type",
|
||||
phy_string_for_interface(
|
||||
PHY_INTERFACE_MODE_SGMII));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
/*
|
||||
* Freescale SGMII Riser Card
|
||||
*
|
||||
* This driver supports the SGMII Riser card found on the
|
||||
* "DS" style of development board from Freescale.
|
||||
*
|
||||
* This software may be used and distributed according to the
|
||||
* terms of the GNU Public License, Version 2, incorporated
|
||||
* herein by reference.
|
||||
*
|
||||
* Copyright 2008 Freescale Semiconductor, Inc.
|
||||
*
|
||||
*/
|
||||
|
||||
void fsl_sgmii_riser_init(struct tsec_info_struct *tsec_info, int num);
|
||||
void fsl_sgmii_riser_fdt_fixup(void *fdt);
|
||||
@@ -0,0 +1,20 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||
/*
|
||||
* Copyright 2014 Freescale Semiconductor, Inc.
|
||||
*/
|
||||
|
||||
#ifndef __SLEEP_H
|
||||
#define __SLEEP_H
|
||||
|
||||
#define DCFG_CCSR_CRSTSR_WDRFR (1 << 3)
|
||||
#define DDR_BUFF_LEN 128
|
||||
|
||||
/* determine if it is a wakeup from deep sleep */
|
||||
bool is_warm_boot(void);
|
||||
|
||||
/* disable console output */
|
||||
void fsl_dp_disable_console(void);
|
||||
|
||||
/* clean up everything and jump to kernel */
|
||||
int fsl_dp_resume(void);
|
||||
#endif
|
||||
@@ -0,0 +1,12 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||
/*
|
||||
* Copyright 2016 Google, Inc
|
||||
*/
|
||||
|
||||
#ifndef __FREESCALE_BOARD_SPL_H
|
||||
#define __FREESCALE_BOARD_SPL_H
|
||||
|
||||
void fsl_spi_spl_load_image(uint32_t offs, unsigned int size, void *vdst);
|
||||
void fsl_spi_boot(void) __noreturn;
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,620 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Copyright 2006, 2008-2009, 2011 Freescale Semiconductor
|
||||
* York Sun (yorksun@freescale.com)
|
||||
* Haiying Wang (haiying.wang@freescale.com)
|
||||
* Timur Tabi (timur@freescale.com)
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <command.h>
|
||||
#include <env.h>
|
||||
#include <i2c.h>
|
||||
#include <linux/ctype.h>
|
||||
#include <u-boot/crc.h>
|
||||
|
||||
#ifdef CONFIG_SYS_I2C_EEPROM_CCID
|
||||
#include "../common/eeprom.h"
|
||||
#define MAX_NUM_PORTS 8
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SYS_I2C_EEPROM_NXID
|
||||
/* some boards with non-256-bytes EEPROM have special define */
|
||||
/* for MAX_NUM_PORTS in board-specific file */
|
||||
#ifndef MAX_NUM_PORTS
|
||||
#define MAX_NUM_PORTS 16
|
||||
#endif
|
||||
#define NXID_VERSION 1
|
||||
#endif
|
||||
|
||||
/**
|
||||
* static eeprom: EEPROM layout for CCID or NXID formats
|
||||
*
|
||||
* See application note AN3638 for details.
|
||||
*/
|
||||
static struct __attribute__ ((__packed__)) eeprom {
|
||||
#ifdef CONFIG_SYS_I2C_EEPROM_CCID
|
||||
u8 id[4]; /* 0x00 - 0x03 EEPROM Tag 'CCID' */
|
||||
u8 major; /* 0x04 Board revision, major */
|
||||
u8 minor; /* 0x05 Board revision, minor */
|
||||
u8 sn[10]; /* 0x06 - 0x0F Serial Number*/
|
||||
u8 errata[2]; /* 0x10 - 0x11 Errata Level */
|
||||
u8 date[6]; /* 0x12 - 0x17 Build Date */
|
||||
u8 res_0[40]; /* 0x18 - 0x3f Reserved */
|
||||
u8 mac_count; /* 0x40 Number of MAC addresses */
|
||||
u8 mac_flag; /* 0x41 MAC table flags */
|
||||
u8 mac[MAX_NUM_PORTS][6]; /* 0x42 - 0x71 MAC addresses */
|
||||
u32 crc; /* 0x72 CRC32 checksum */
|
||||
#endif
|
||||
#ifdef CONFIG_SYS_I2C_EEPROM_NXID
|
||||
u8 id[4]; /* 0x00 - 0x03 EEPROM Tag 'NXID' */
|
||||
u8 sn[12]; /* 0x04 - 0x0F Serial Number */
|
||||
u8 errata[5]; /* 0x10 - 0x14 Errata Level */
|
||||
u8 date[6]; /* 0x15 - 0x1a Build Date */
|
||||
u8 res_0; /* 0x1b Reserved */
|
||||
u32 version; /* 0x1c - 0x1f NXID Version */
|
||||
u8 tempcal[8]; /* 0x20 - 0x27 Temperature Calibration Factors */
|
||||
u8 tempcalsys[2]; /* 0x28 - 0x29 System Temperature Calibration Factors */
|
||||
u8 tempcalflags; /* 0x2a Temperature Calibration Flags */
|
||||
u8 res_1[21]; /* 0x2b - 0x3f Reserved */
|
||||
u8 mac_count; /* 0x40 Number of MAC addresses */
|
||||
u8 mac_flag; /* 0x41 MAC table flags */
|
||||
u8 mac[MAX_NUM_PORTS][6]; /* 0x42 - 0xa1 MAC addresses */
|
||||
u8 res_2[90]; /* 0xa2 - 0xfb Reserved */
|
||||
u32 crc; /* 0xfc - 0xff CRC32 checksum */
|
||||
#endif
|
||||
} e;
|
||||
|
||||
/* Set to 1 if we've read EEPROM into memory */
|
||||
static int has_been_read = 0;
|
||||
|
||||
#ifdef CONFIG_SYS_I2C_EEPROM_NXID
|
||||
/* Is this a valid NXID EEPROM? */
|
||||
#define is_valid ((e.id[0] == 'N') || (e.id[1] == 'X') || \
|
||||
(e.id[2] == 'I') || (e.id[3] == 'D'))
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SYS_I2C_EEPROM_CCID
|
||||
/* Is this a valid CCID EEPROM? */
|
||||
#define is_valid ((e.id[0] == 'C') || (e.id[1] == 'C') || \
|
||||
(e.id[2] == 'I') || (e.id[3] == 'D'))
|
||||
#endif
|
||||
|
||||
/**
|
||||
* show_eeprom - display the contents of the EEPROM
|
||||
*/
|
||||
static void show_eeprom(void)
|
||||
{
|
||||
int i;
|
||||
unsigned int crc;
|
||||
|
||||
/* EEPROM tag ID, either CCID or NXID */
|
||||
#ifdef CONFIG_SYS_I2C_EEPROM_NXID
|
||||
printf("ID: %c%c%c%c v%u\n", e.id[0], e.id[1], e.id[2], e.id[3],
|
||||
be32_to_cpu(e.version));
|
||||
#else
|
||||
printf("ID: %c%c%c%c\n", e.id[0], e.id[1], e.id[2], e.id[3]);
|
||||
#endif
|
||||
|
||||
/* Serial number */
|
||||
printf("SN: %s\n", e.sn);
|
||||
|
||||
/* Errata level. */
|
||||
#ifdef CONFIG_SYS_I2C_EEPROM_NXID
|
||||
printf("Errata: %s\n", e.errata);
|
||||
#else
|
||||
printf("Errata: %c%c\n",
|
||||
e.errata[0] ? e.errata[0] : '.',
|
||||
e.errata[1] ? e.errata[1] : '.');
|
||||
#endif
|
||||
|
||||
/* Build date, BCD date values, as YYMMDDhhmmss */
|
||||
printf("Build date: 20%02x/%02x/%02x %02x:%02x:%02x %s\n",
|
||||
e.date[0], e.date[1], e.date[2],
|
||||
e.date[3] & 0x7F, e.date[4], e.date[5],
|
||||
e.date[3] & 0x80 ? "PM" : "");
|
||||
|
||||
/* Show MAC addresses */
|
||||
for (i = 0; i < min(e.mac_count, (u8)MAX_NUM_PORTS); i++) {
|
||||
|
||||
u8 *p = e.mac[i];
|
||||
|
||||
printf("Eth%u: %02x:%02x:%02x:%02x:%02x:%02x\n", i,
|
||||
p[0], p[1], p[2], p[3], p[4], p[5]);
|
||||
}
|
||||
|
||||
crc = crc32(0, (void *)&e, sizeof(e) - 4);
|
||||
|
||||
if (crc == be32_to_cpu(e.crc))
|
||||
printf("CRC: %08x\n", be32_to_cpu(e.crc));
|
||||
else
|
||||
printf("CRC: %08x (should be %08x)\n",
|
||||
be32_to_cpu(e.crc), crc);
|
||||
|
||||
#ifdef DEBUG
|
||||
printf("EEPROM dump: (0x%x bytes)\n", sizeof(e));
|
||||
for (i = 0; i < sizeof(e); i++) {
|
||||
if ((i % 16) == 0)
|
||||
printf("%02X: ", i);
|
||||
printf("%02X ", ((u8 *)&e)[i]);
|
||||
if (((i % 16) == 15) || (i == sizeof(e) - 1))
|
||||
printf("\n");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* read_eeprom - read the EEPROM into memory
|
||||
*/
|
||||
static int read_eeprom(void)
|
||||
{
|
||||
int ret;
|
||||
#ifdef CONFIG_SYS_EEPROM_BUS_NUM
|
||||
#ifndef CONFIG_DM_I2C
|
||||
unsigned int bus;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
if (has_been_read)
|
||||
return 0;
|
||||
|
||||
#ifdef CONFIG_SYS_EEPROM_BUS_NUM
|
||||
#ifndef CONFIG_DM_I2C
|
||||
bus = i2c_get_bus_num();
|
||||
i2c_set_bus_num(CONFIG_SYS_EEPROM_BUS_NUM);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_DM_I2C
|
||||
ret = i2c_read(CONFIG_SYS_I2C_EEPROM_ADDR, 0,
|
||||
CONFIG_SYS_I2C_EEPROM_ADDR_LEN,
|
||||
(void *)&e, sizeof(e));
|
||||
#else
|
||||
struct udevice *dev;
|
||||
#ifdef CONFIG_SYS_EEPROM_BUS_NUM
|
||||
ret = i2c_get_chip_for_busnum(CONFIG_SYS_EEPROM_BUS_NUM,
|
||||
CONFIG_SYS_I2C_EEPROM_ADDR, 1, &dev);
|
||||
#else
|
||||
ret = i2c_get_chip_for_busnum(0, CONFIG_SYS_I2C_EEPROM_ADDR, 1, &dev);
|
||||
#endif
|
||||
if (!ret)
|
||||
ret = dm_i2c_read(dev, 0, (void *)&e, sizeof(e));
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SYS_EEPROM_BUS_NUM
|
||||
#ifndef CONFIG_DM_I2C
|
||||
i2c_set_bus_num(bus);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG
|
||||
show_eeprom();
|
||||
#endif
|
||||
|
||||
has_been_read = (ret == 0) ? 1 : 0;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* update_crc - update the CRC
|
||||
*
|
||||
* This function should be called after each update to the EEPROM structure,
|
||||
* to make sure the CRC is always correct.
|
||||
*/
|
||||
static void update_crc(void)
|
||||
{
|
||||
u32 crc;
|
||||
|
||||
crc = crc32(0, (void *)&e, sizeof(e) - 4);
|
||||
e.crc = cpu_to_be32(crc);
|
||||
}
|
||||
|
||||
/**
|
||||
* prog_eeprom - write the EEPROM from memory
|
||||
*/
|
||||
static int prog_eeprom(void)
|
||||
{
|
||||
int ret = 0;
|
||||
int i;
|
||||
void *p;
|
||||
#ifdef CONFIG_SYS_EEPROM_BUS_NUM
|
||||
#ifndef CONFIG_DM_I2C
|
||||
unsigned int bus;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Set the reserved values to 0xFF */
|
||||
#ifdef CONFIG_SYS_I2C_EEPROM_NXID
|
||||
e.res_0 = 0xFF;
|
||||
memset(e.res_1, 0xFF, sizeof(e.res_1));
|
||||
#else
|
||||
memset(e.res_0, 0xFF, sizeof(e.res_0));
|
||||
#endif
|
||||
update_crc();
|
||||
|
||||
#ifndef CONFIG_DM_I2C
|
||||
#ifdef CONFIG_SYS_EEPROM_BUS_NUM
|
||||
bus = i2c_get_bus_num();
|
||||
i2c_set_bus_num(CONFIG_SYS_EEPROM_BUS_NUM);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
* The AT24C02 datasheet says that data can only be written in page
|
||||
* mode, which means 8 bytes at a time, and it takes up to 5ms to
|
||||
* complete a given write.
|
||||
*/
|
||||
for (i = 0, p = &e; i < sizeof(e); i += 8, p += 8) {
|
||||
#ifndef CONFIG_DM_I2C
|
||||
ret = i2c_write(CONFIG_SYS_I2C_EEPROM_ADDR, i,
|
||||
CONFIG_SYS_I2C_EEPROM_ADDR_LEN,
|
||||
p, min((int)(sizeof(e) - i), 8));
|
||||
#else
|
||||
struct udevice *dev;
|
||||
#ifdef CONFIG_SYS_EEPROM_BUS_NUM
|
||||
ret = i2c_get_chip_for_busnum(CONFIG_SYS_EEPROM_BUS_NUM,
|
||||
CONFIG_SYS_I2C_EEPROM_ADDR,
|
||||
CONFIG_SYS_I2C_EEPROM_ADDR_LEN,
|
||||
&dev);
|
||||
#else
|
||||
ret = i2c_get_chip_for_busnum(0, CONFIG_SYS_I2C_EEPROM_ADDR,
|
||||
CONFIG_SYS_I2C_EEPROM_ADDR_LEN,
|
||||
&dev);
|
||||
#endif
|
||||
if (!ret)
|
||||
ret = dm_i2c_write(dev, i, p, min((int)(sizeof(e) - i),
|
||||
8));
|
||||
#endif
|
||||
if (ret)
|
||||
break;
|
||||
udelay(5000); /* 5ms write cycle timing */
|
||||
}
|
||||
|
||||
if (!ret) {
|
||||
/* Verify the write by reading back the EEPROM and comparing */
|
||||
struct eeprom e2;
|
||||
|
||||
#ifndef CONFIG_DM_I2C
|
||||
ret = i2c_read(CONFIG_SYS_I2C_EEPROM_ADDR, 0,
|
||||
CONFIG_SYS_I2C_EEPROM_ADDR_LEN,
|
||||
(void *)&e2, sizeof(e2));
|
||||
#else
|
||||
struct udevice *dev;
|
||||
#ifdef CONFIG_SYS_EEPROM_BUS_NUM
|
||||
ret = i2c_get_chip_for_busnum(CONFIG_SYS_EEPROM_BUS_NUM,
|
||||
CONFIG_SYS_I2C_EEPROM_ADDR,
|
||||
CONFIG_SYS_I2C_EEPROM_ADDR_LEN,
|
||||
&dev);
|
||||
#else
|
||||
ret = i2c_get_chip_for_busnum(0, CONFIG_SYS_I2C_EEPROM_ADDR,
|
||||
CONFIG_SYS_I2C_EEPROM_ADDR_LEN,
|
||||
&dev);
|
||||
#endif
|
||||
if (!ret)
|
||||
ret = dm_i2c_read(dev, 0, (void *)&e2, sizeof(e2));
|
||||
#endif
|
||||
if (!ret && memcmp(&e, &e2, sizeof(e)))
|
||||
ret = -1;
|
||||
}
|
||||
|
||||
#ifndef CONFIG_DM_I2C
|
||||
#ifdef CONFIG_SYS_EEPROM_BUS_NUM
|
||||
i2c_set_bus_num(bus);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
if (ret) {
|
||||
printf("Programming failed.\n");
|
||||
has_been_read = 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
printf("Programming passed.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* h2i - converts hex character into a number
|
||||
*
|
||||
* This function takes a hexadecimal character (e.g. '7' or 'C') and returns
|
||||
* the integer equivalent.
|
||||
*/
|
||||
static inline u8 h2i(char p)
|
||||
{
|
||||
if ((p >= '0') && (p <= '9'))
|
||||
return p - '0';
|
||||
|
||||
if ((p >= 'A') && (p <= 'F'))
|
||||
return (p - 'A') + 10;
|
||||
|
||||
if ((p >= 'a') && (p <= 'f'))
|
||||
return (p - 'a') + 10;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* set_date - stores the build date into the EEPROM
|
||||
*
|
||||
* This function takes a pointer to a string in the format "YYMMDDhhmmss"
|
||||
* (2-digit year, 2-digit month, etc), converts it to a 6-byte BCD string,
|
||||
* and stores it in the build date field of the EEPROM local copy.
|
||||
*/
|
||||
static void set_date(const char *string)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
if (strlen(string) != 12) {
|
||||
printf("Usage: mac date YYMMDDhhmmss\n");
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < 6; i++)
|
||||
e.date[i] = h2i(string[2 * i]) << 4 | h2i(string[2 * i + 1]);
|
||||
|
||||
update_crc();
|
||||
}
|
||||
|
||||
/**
|
||||
* set_mac_address - stores a MAC address into the EEPROM
|
||||
*
|
||||
* This function takes a pointer to MAC address string
|
||||
* (i.e."XX:XX:XX:XX:XX:XX", where "XX" is a two-digit hex number) and
|
||||
* stores it in one of the MAC address fields of the EEPROM local copy.
|
||||
*/
|
||||
static void set_mac_address(unsigned int index, const char *string)
|
||||
{
|
||||
char *p = (char *) string;
|
||||
unsigned int i;
|
||||
|
||||
if ((index >= MAX_NUM_PORTS) || !string) {
|
||||
printf("Usage: mac <n> XX:XX:XX:XX:XX:XX\n");
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; *p && (i < 6); i++) {
|
||||
e.mac[index][i] = simple_strtoul(p, &p, 16);
|
||||
if (*p == ':')
|
||||
p++;
|
||||
}
|
||||
|
||||
update_crc();
|
||||
}
|
||||
|
||||
int do_mac(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
|
||||
{
|
||||
char cmd;
|
||||
|
||||
if (argc == 1) {
|
||||
show_eeprom();
|
||||
return 0;
|
||||
}
|
||||
|
||||
cmd = argv[1][0];
|
||||
|
||||
if (cmd == 'r') {
|
||||
read_eeprom();
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (cmd == 'i') {
|
||||
#ifdef CONFIG_SYS_I2C_EEPROM_NXID
|
||||
memcpy(e.id, "NXID", sizeof(e.id));
|
||||
e.version = cpu_to_be32(NXID_VERSION);
|
||||
#else
|
||||
memcpy(e.id, "CCID", sizeof(e.id));
|
||||
#endif
|
||||
update_crc();
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!is_valid) {
|
||||
printf("Please read the EEPROM ('r') and/or set the ID ('i') first.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (argc == 2) {
|
||||
switch (cmd) {
|
||||
case 's': /* save */
|
||||
prog_eeprom();
|
||||
break;
|
||||
default:
|
||||
return cmd_usage(cmdtp);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* We know we have at least one parameter */
|
||||
|
||||
switch (cmd) {
|
||||
case 'n': /* serial number */
|
||||
memset(e.sn, 0, sizeof(e.sn));
|
||||
strncpy((char *)e.sn, argv[2], sizeof(e.sn) - 1);
|
||||
update_crc();
|
||||
break;
|
||||
case 'e': /* errata */
|
||||
#ifdef CONFIG_SYS_I2C_EEPROM_NXID
|
||||
memset(e.errata, 0, 5);
|
||||
strncpy((char *)e.errata, argv[2], 4);
|
||||
#else
|
||||
e.errata[0] = argv[2][0];
|
||||
e.errata[1] = argv[2][1];
|
||||
#endif
|
||||
update_crc();
|
||||
break;
|
||||
case 'd': /* date BCD format YYMMDDhhmmss */
|
||||
set_date(argv[2]);
|
||||
break;
|
||||
case 'p': /* MAC table size */
|
||||
e.mac_count = simple_strtoul(argv[2], NULL, 16);
|
||||
update_crc();
|
||||
break;
|
||||
case '0' ... '9': /* "mac 0" through "mac 22" */
|
||||
set_mac_address(simple_strtoul(argv[1], NULL, 10), argv[2]);
|
||||
break;
|
||||
case 'h': /* help */
|
||||
default:
|
||||
return cmd_usage(cmdtp);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* mac_read_from_eeprom - read the MAC addresses from EEPROM
|
||||
*
|
||||
* This function reads the MAC addresses from EEPROM and sets the
|
||||
* appropriate environment variables for each one read.
|
||||
*
|
||||
* The environment variables are only set if they haven't been set already.
|
||||
* This ensures that any user-saved variables are never overwritten.
|
||||
*
|
||||
* This function must be called after relocation.
|
||||
*
|
||||
* For NXID v1 EEPROMs, we support loading and up-converting the older NXID v0
|
||||
* format. In a v0 EEPROM, there are only eight MAC addresses and the CRC is
|
||||
* located at a different offset.
|
||||
*/
|
||||
int mac_read_from_eeprom(void)
|
||||
{
|
||||
unsigned int i;
|
||||
u32 crc, crc_offset = offsetof(struct eeprom, crc);
|
||||
u32 *crcp; /* Pointer to the CRC in the data read from the EEPROM */
|
||||
|
||||
puts("EEPROM: ");
|
||||
|
||||
if (read_eeprom()) {
|
||||
printf("Read failed.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!is_valid) {
|
||||
printf("Invalid ID (%02x %02x %02x %02x)\n",
|
||||
e.id[0], e.id[1], e.id[2], e.id[3]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SYS_I2C_EEPROM_NXID
|
||||
/*
|
||||
* If we've read an NXID v0 EEPROM, then we need to set the CRC offset
|
||||
* to where it is in v0.
|
||||
*/
|
||||
if (e.version == 0)
|
||||
crc_offset = 0x72;
|
||||
#endif
|
||||
|
||||
crc = crc32(0, (void *)&e, crc_offset);
|
||||
crcp = (void *)&e + crc_offset;
|
||||
if (crc != be32_to_cpu(*crcp)) {
|
||||
printf("CRC mismatch (%08x != %08x)\n", crc, be32_to_cpu(e.crc));
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SYS_I2C_EEPROM_NXID
|
||||
/*
|
||||
* MAC address #9 in v1 occupies the same position as the CRC in v0.
|
||||
* Erase it so that it's not mistaken for a MAC address. We'll
|
||||
* update the CRC later.
|
||||
*/
|
||||
if (e.version == 0)
|
||||
memset(e.mac[8], 0xff, 6);
|
||||
#endif
|
||||
|
||||
for (i = 0; i < min(e.mac_count, (u8)MAX_NUM_PORTS); i++) {
|
||||
if (memcmp(&e.mac[i], "\0\0\0\0\0\0", 6) &&
|
||||
memcmp(&e.mac[i], "\xFF\xFF\xFF\xFF\xFF\xFF", 6)) {
|
||||
char ethaddr[18];
|
||||
char enetvar[9];
|
||||
|
||||
sprintf(ethaddr, "%02X:%02X:%02X:%02X:%02X:%02X",
|
||||
e.mac[i][0],
|
||||
e.mac[i][1],
|
||||
e.mac[i][2],
|
||||
e.mac[i][3],
|
||||
e.mac[i][4],
|
||||
e.mac[i][5]);
|
||||
sprintf(enetvar, i ? "eth%daddr" : "ethaddr", i);
|
||||
/* Only initialize environment variables that are blank
|
||||
* (i.e. have not yet been set)
|
||||
*/
|
||||
if (!env_get(enetvar))
|
||||
env_set(enetvar, ethaddr);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SYS_I2C_EEPROM_NXID
|
||||
printf("%c%c%c%c v%u\n", e.id[0], e.id[1], e.id[2], e.id[3],
|
||||
be32_to_cpu(e.version));
|
||||
#else
|
||||
printf("%c%c%c%c\n", e.id[0], e.id[1], e.id[2], e.id[3]);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SYS_I2C_EEPROM_NXID
|
||||
/*
|
||||
* Now we need to upconvert the data into v1 format. We do this last so
|
||||
* that at boot time, U-Boot will still say "NXID v0".
|
||||
*/
|
||||
if (e.version == 0) {
|
||||
e.version = cpu_to_be32(NXID_VERSION);
|
||||
update_crc();
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SYS_I2C_EEPROM_CCID
|
||||
|
||||
/**
|
||||
* get_cpu_board_revision - get the CPU board revision on 85xx boards
|
||||
*
|
||||
* Read the EEPROM to determine the board revision.
|
||||
*
|
||||
* This function is called before relocation, so we need to read a private
|
||||
* copy of the EEPROM into a local variable on the stack.
|
||||
*
|
||||
* Also, we assume that CONFIG_SYS_EEPROM_BUS_NUM == CONFIG_SYS_SPD_BUS_NUM. The global
|
||||
* variable i2c_bus_num must be compile-time initialized to CONFIG_SYS_SPD_BUS_NUM,
|
||||
* so that the SPD code will work. This means that all pre-relocation I2C
|
||||
* operations can only occur on the CONFIG_SYS_SPD_BUS_NUM bus. So if
|
||||
* CONFIG_SYS_EEPROM_BUS_NUM != CONFIG_SYS_SPD_BUS_NUM, then we can't read the EEPROM when
|
||||
* this function is called. Oh well.
|
||||
*/
|
||||
unsigned int get_cpu_board_revision(void)
|
||||
{
|
||||
struct board_eeprom {
|
||||
u32 id; /* 0x00 - 0x03 EEPROM Tag 'CCID' */
|
||||
u8 major; /* 0x04 Board revision, major */
|
||||
u8 minor; /* 0x05 Board revision, minor */
|
||||
} be;
|
||||
|
||||
#ifndef CONFIG_DM_I2C
|
||||
i2c_read(CONFIG_SYS_I2C_EEPROM_ADDR, 0, CONFIG_SYS_I2C_EEPROM_ADDR_LEN,
|
||||
(void *)&be, sizeof(be));
|
||||
#else
|
||||
struct udevice *dev;
|
||||
#ifdef CONFIG_SYS_EEPROM_BUS_NUM
|
||||
ret = i2c_get_chip_for_busnum(CONFIG_SYS_EEPROM_BUS_NUM,
|
||||
CONFIG_SYS_I2C_EEPROM_ADDR,
|
||||
CONFIG_SYS_I2C_EEPROM_ADDR_LEN,
|
||||
&dev);
|
||||
#else
|
||||
ret = i2c_get_chip_for_busnum(0, CONFIG_SYS_I2C_EEPROM_ADDR,
|
||||
CONFIG_SYS_I2C_EEPROM_ADDR_LEN,
|
||||
&dev)
|
||||
#endif
|
||||
if (!ret)
|
||||
dm_i2c_read(dev, 0, (void *)&be, sizeof(be));
|
||||
#endif
|
||||
|
||||
if (be.id != (('C' << 24) | ('C' << 16) | ('I' << 8) | 'D'))
|
||||
return MPC85XX_CPU_BOARD_REV(0, 0);
|
||||
|
||||
if ((be.major == 0xff) && (be.minor == 0xff))
|
||||
return MPC85XX_CPU_BOARD_REV(0, 0);
|
||||
|
||||
return MPC85XX_CPU_BOARD_REV(be.major, be.minor);
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,18 @@
|
||||
#ifndef _MPC85xx_VIA_H
|
||||
void mpc85xx_config_via(struct pci_controller* hose, pci_dev_t dev, struct pci_config_table *tab);
|
||||
|
||||
/* Function 1, IDE */
|
||||
void mpc85xx_config_via_usbide(struct pci_controller* hose, pci_dev_t dev, struct pci_config_table *tab);
|
||||
|
||||
/* Function 2, USB ports 0-1 */
|
||||
void mpc85xx_config_via_usb(struct pci_controller* hose, pci_dev_t dev, struct pci_config_table *tab);
|
||||
|
||||
/* Function 3, USB ports 2-3 */
|
||||
void mpc85xx_config_via_usb2(struct pci_controller* hose, pci_dev_t dev, struct pci_config_table *tab);
|
||||
|
||||
/* Function 5, Power Management */
|
||||
void mpc85xx_config_via_power(struct pci_controller* hose, pci_dev_t dev, struct pci_config_table *tab);
|
||||
|
||||
/* Function 6, AC97 Interface */
|
||||
void mpc85xx_config_via_ac97(struct pci_controller* hose, pci_dev_t dev, struct pci_config_table *tab);
|
||||
#endif /* _MPC85xx_VIA_H */
|
||||
@@ -0,0 +1,965 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Copyright 2014 Freescale Semiconductor, Inc.
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <command.h>
|
||||
#include <env.h>
|
||||
#include <i2c.h>
|
||||
#include <irq_func.h>
|
||||
#include <asm/io.h>
|
||||
#ifdef CONFIG_FSL_LSCH2
|
||||
#include <asm/arch/immap_lsch2.h>
|
||||
#elif defined(CONFIG_FSL_LSCH3)
|
||||
#include <asm/arch/immap_lsch3.h>
|
||||
#else
|
||||
#include <asm/immap_85xx.h>
|
||||
#endif
|
||||
#include "vid.h"
|
||||
|
||||
int __weak i2c_multiplexer_select_vid_channel(u8 channel)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Compensate for a board specific voltage drop between regulator and SoC
|
||||
* return a value in mV
|
||||
*/
|
||||
int __weak board_vdd_drop_compensation(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Board specific settings for specific voltage value
|
||||
*/
|
||||
int __weak board_adjust_vdd(int vdd)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_VOL_MONITOR_IR36021_SET) || \
|
||||
defined(CONFIG_VOL_MONITOR_IR36021_READ)
|
||||
/*
|
||||
* Get the i2c address configuration for the IR regulator chip
|
||||
*
|
||||
* There are some variance in the RDB HW regarding the I2C address configuration
|
||||
* for the IR regulator chip, which is likely a problem of external resistor
|
||||
* accuracy. So we just check each address in a hopefully non-intrusive mode
|
||||
* and use the first one that seems to work
|
||||
*
|
||||
* The IR chip can show up under the following addresses:
|
||||
* 0x08 (Verified on T1040RDB-PA,T4240RDB-PB,X-T4240RDB-16GPA)
|
||||
* 0x09 (Verified on T1040RDB-PA)
|
||||
* 0x38 (Verified on T2080QDS, T2081QDS, T4240RDB)
|
||||
*/
|
||||
static int find_ir_chip_on_i2c(void)
|
||||
{
|
||||
int i2caddress;
|
||||
int ret;
|
||||
u8 byte;
|
||||
int i;
|
||||
const int ir_i2c_addr[] = {0x38, 0x08, 0x09};
|
||||
#ifdef CONFIG_DM_I2C
|
||||
struct udevice *dev;
|
||||
#endif
|
||||
|
||||
/* Check all the address */
|
||||
for (i = 0; i < (sizeof(ir_i2c_addr)/sizeof(ir_i2c_addr[0])); i++) {
|
||||
i2caddress = ir_i2c_addr[i];
|
||||
#ifndef CONFIG_DM_I2C
|
||||
ret = i2c_read(i2caddress,
|
||||
IR36021_MFR_ID_OFFSET, 1, (void *)&byte,
|
||||
sizeof(byte));
|
||||
#else
|
||||
ret = i2c_get_chip_for_busnum(0, i2caddress, 1, &dev);
|
||||
if (!ret)
|
||||
ret = dm_i2c_read(dev, IR36021_MFR_ID_OFFSET,
|
||||
(void *)&byte, sizeof(byte));
|
||||
#endif
|
||||
if ((ret >= 0) && (byte == IR36021_MFR_ID))
|
||||
return i2caddress;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Maximum loop count waiting for new voltage to take effect */
|
||||
#define MAX_LOOP_WAIT_NEW_VOL 100
|
||||
/* Maximum loop count waiting for the voltage to be stable */
|
||||
#define MAX_LOOP_WAIT_VOL_STABLE 100
|
||||
/*
|
||||
* read_voltage from sensor on I2C bus
|
||||
* We use average of 4 readings, waiting for WAIT_FOR_ADC before
|
||||
* another reading
|
||||
*/
|
||||
#define NUM_READINGS 4 /* prefer to be power of 2 for efficiency */
|
||||
|
||||
/* If an INA220 chip is available, we can use it to read back the voltage
|
||||
* as it may have a higher accuracy than the IR chip for the same purpose
|
||||
*/
|
||||
#ifdef CONFIG_VOL_MONITOR_INA220
|
||||
#define WAIT_FOR_ADC 532 /* wait for 532 microseconds for ADC */
|
||||
#define ADC_MIN_ACCURACY 4
|
||||
#else
|
||||
#define WAIT_FOR_ADC 138 /* wait for 138 microseconds for ADC */
|
||||
#define ADC_MIN_ACCURACY 4
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_VOL_MONITOR_INA220
|
||||
static int read_voltage_from_INA220(int i2caddress)
|
||||
{
|
||||
int i, ret, voltage_read = 0;
|
||||
u16 vol_mon;
|
||||
u8 buf[2];
|
||||
#ifdef CONFIG_DM_I2C
|
||||
struct udevice *dev;
|
||||
#endif
|
||||
|
||||
for (i = 0; i < NUM_READINGS; i++) {
|
||||
#ifndef CONFIG_DM_I2C
|
||||
ret = i2c_read(I2C_VOL_MONITOR_ADDR,
|
||||
I2C_VOL_MONITOR_BUS_V_OFFSET, 1,
|
||||
(void *)&buf, 2);
|
||||
#else
|
||||
ret = i2c_get_chip_for_busnum(0, I2C_VOL_MONITOR_ADDR, 1, &dev);
|
||||
if (!ret)
|
||||
ret = dm_i2c_read(dev, I2C_VOL_MONITOR_BUS_V_OFFSET,
|
||||
(void *)&buf, 2);
|
||||
#endif
|
||||
if (ret) {
|
||||
printf("VID: failed to read core voltage\n");
|
||||
return ret;
|
||||
}
|
||||
vol_mon = (buf[0] << 8) | buf[1];
|
||||
if (vol_mon & I2C_VOL_MONITOR_BUS_V_OVF) {
|
||||
printf("VID: Core voltage sensor error\n");
|
||||
return -1;
|
||||
}
|
||||
debug("VID: bus voltage reads 0x%04x\n", vol_mon);
|
||||
/* LSB = 4mv */
|
||||
voltage_read += (vol_mon >> I2C_VOL_MONITOR_BUS_V_SHIFT) * 4;
|
||||
udelay(WAIT_FOR_ADC);
|
||||
}
|
||||
/* calculate the average */
|
||||
voltage_read /= NUM_READINGS;
|
||||
|
||||
return voltage_read;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* read voltage from IR */
|
||||
#ifdef CONFIG_VOL_MONITOR_IR36021_READ
|
||||
static int read_voltage_from_IR(int i2caddress)
|
||||
{
|
||||
int i, ret, voltage_read = 0;
|
||||
u16 vol_mon;
|
||||
u8 buf;
|
||||
#ifdef CONFIG_DM_I2C
|
||||
struct udevice *dev;
|
||||
#endif
|
||||
|
||||
for (i = 0; i < NUM_READINGS; i++) {
|
||||
#ifndef CONFIG_DM_I2C
|
||||
ret = i2c_read(i2caddress,
|
||||
IR36021_LOOP1_VOUT_OFFSET,
|
||||
1, (void *)&buf, 1);
|
||||
#else
|
||||
ret = i2c_get_chip_for_busnum(0, i2caddress, 1, &dev);
|
||||
if (!ret)
|
||||
ret = dm_i2c_read(dev, IR36021_LOOP1_VOUT_OFFSET,
|
||||
(void *)&buf, 1);
|
||||
#endif
|
||||
if (ret) {
|
||||
printf("VID: failed to read vcpu\n");
|
||||
return ret;
|
||||
}
|
||||
vol_mon = buf;
|
||||
if (!vol_mon) {
|
||||
printf("VID: Core voltage sensor error\n");
|
||||
return -1;
|
||||
}
|
||||
debug("VID: bus voltage reads 0x%02x\n", vol_mon);
|
||||
/* Resolution is 1/128V. We scale up here to get 1/128mV
|
||||
* and divide at the end
|
||||
*/
|
||||
voltage_read += vol_mon * 1000;
|
||||
udelay(WAIT_FOR_ADC);
|
||||
}
|
||||
/* Scale down to the real mV as IR resolution is 1/128V, rounding up */
|
||||
voltage_read = DIV_ROUND_UP(voltage_read, 128);
|
||||
|
||||
/* calculate the average */
|
||||
voltage_read /= NUM_READINGS;
|
||||
|
||||
/* Compensate for a board specific voltage drop between regulator and
|
||||
* SoC before converting into an IR VID value
|
||||
*/
|
||||
voltage_read -= board_vdd_drop_compensation();
|
||||
|
||||
return voltage_read;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_VOL_MONITOR_LTC3882_READ
|
||||
/* read the current value of the LTC Regulator Voltage */
|
||||
static int read_voltage_from_LTC(int i2caddress)
|
||||
{
|
||||
int ret, vcode = 0;
|
||||
u8 chan = PWM_CHANNEL0;
|
||||
|
||||
#ifndef CONFIG_DM_I2C
|
||||
/* select the PAGE 0 using PMBus commands PAGE for VDD*/
|
||||
ret = i2c_write(I2C_VOL_MONITOR_ADDR,
|
||||
PMBUS_CMD_PAGE, 1, &chan, 1);
|
||||
#else
|
||||
struct udevice *dev;
|
||||
|
||||
ret = i2c_get_chip_for_busnum(0, I2C_VOL_MONITOR_ADDR, 1, &dev);
|
||||
if (!ret)
|
||||
ret = dm_i2c_write(dev, PMBUS_CMD_PAGE, &chan, 1);
|
||||
#endif
|
||||
if (ret) {
|
||||
printf("VID: failed to select VDD Page 0\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifndef CONFIG_DM_I2C
|
||||
/*read the output voltage using PMBus command READ_VOUT*/
|
||||
ret = i2c_read(I2C_VOL_MONITOR_ADDR,
|
||||
PMBUS_CMD_READ_VOUT, 1, (void *)&vcode, 2);
|
||||
#else
|
||||
ret = dm_i2c_read(dev, PMBUS_CMD_READ_VOUT, (void *)&vcode, 2);
|
||||
if (ret) {
|
||||
printf("VID: failed to read the volatge\n");
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
if (ret) {
|
||||
printf("VID: failed to read the volatge\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Scale down to the real mV as LTC resolution is 1/4096V,rounding up */
|
||||
vcode = DIV_ROUND_UP(vcode * 1000, 4096);
|
||||
|
||||
return vcode;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int read_voltage(int i2caddress)
|
||||
{
|
||||
int voltage_read;
|
||||
#ifdef CONFIG_VOL_MONITOR_INA220
|
||||
voltage_read = read_voltage_from_INA220(i2caddress);
|
||||
#elif defined CONFIG_VOL_MONITOR_IR36021_READ
|
||||
voltage_read = read_voltage_from_IR(i2caddress);
|
||||
#elif defined CONFIG_VOL_MONITOR_LTC3882_READ
|
||||
voltage_read = read_voltage_from_LTC(i2caddress);
|
||||
#else
|
||||
return -1;
|
||||
#endif
|
||||
return voltage_read;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_VOL_MONITOR_IR36021_SET
|
||||
/*
|
||||
* We need to calculate how long before the voltage stops to drop
|
||||
* or increase. It returns with the loop count. Each loop takes
|
||||
* several readings (WAIT_FOR_ADC)
|
||||
*/
|
||||
static int wait_for_new_voltage(int vdd, int i2caddress)
|
||||
{
|
||||
int timeout, vdd_current;
|
||||
|
||||
vdd_current = read_voltage(i2caddress);
|
||||
/* wait until voltage starts to reach the target. Voltage slew
|
||||
* rates by typical regulators will always lead to stable readings
|
||||
* within each fairly long ADC interval in comparison to the
|
||||
* intended voltage delta change until the target voltage is
|
||||
* reached. The fairly small voltage delta change to any target
|
||||
* VID voltage also means that this function will always complete
|
||||
* within few iterations. If the timeout was ever reached, it would
|
||||
* point to a serious failure in the regulator system.
|
||||
*/
|
||||
for (timeout = 0;
|
||||
abs(vdd - vdd_current) > (IR_VDD_STEP_UP + IR_VDD_STEP_DOWN) &&
|
||||
timeout < MAX_LOOP_WAIT_NEW_VOL; timeout++) {
|
||||
vdd_current = read_voltage(i2caddress);
|
||||
}
|
||||
if (timeout >= MAX_LOOP_WAIT_NEW_VOL) {
|
||||
printf("VID: Voltage adjustment timeout\n");
|
||||
return -1;
|
||||
}
|
||||
return timeout;
|
||||
}
|
||||
|
||||
/*
|
||||
* this function keeps reading the voltage until it is stable or until the
|
||||
* timeout expires
|
||||
*/
|
||||
static int wait_for_voltage_stable(int i2caddress)
|
||||
{
|
||||
int timeout, vdd_current, vdd;
|
||||
|
||||
vdd = read_voltage(i2caddress);
|
||||
udelay(NUM_READINGS * WAIT_FOR_ADC);
|
||||
|
||||
/* wait until voltage is stable */
|
||||
vdd_current = read_voltage(i2caddress);
|
||||
/* The maximum timeout is
|
||||
* MAX_LOOP_WAIT_VOL_STABLE * NUM_READINGS * WAIT_FOR_ADC
|
||||
*/
|
||||
for (timeout = MAX_LOOP_WAIT_VOL_STABLE;
|
||||
abs(vdd - vdd_current) > ADC_MIN_ACCURACY &&
|
||||
timeout > 0; timeout--) {
|
||||
vdd = vdd_current;
|
||||
udelay(NUM_READINGS * WAIT_FOR_ADC);
|
||||
vdd_current = read_voltage(i2caddress);
|
||||
}
|
||||
if (timeout == 0)
|
||||
return -1;
|
||||
return vdd_current;
|
||||
}
|
||||
|
||||
/* Set the voltage to the IR chip */
|
||||
static int set_voltage_to_IR(int i2caddress, int vdd)
|
||||
{
|
||||
int wait, vdd_last;
|
||||
int ret;
|
||||
u8 vid;
|
||||
|
||||
/* Compensate for a board specific voltage drop between regulator and
|
||||
* SoC before converting into an IR VID value
|
||||
*/
|
||||
vdd += board_vdd_drop_compensation();
|
||||
#ifdef CONFIG_FSL_LSCH2
|
||||
vid = DIV_ROUND_UP(vdd - 265, 5);
|
||||
#else
|
||||
vid = DIV_ROUND_UP(vdd - 245, 5);
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_DM_I2C
|
||||
ret = i2c_write(i2caddress, IR36021_LOOP1_MANUAL_ID_OFFSET,
|
||||
1, (void *)&vid, sizeof(vid));
|
||||
#else
|
||||
struct udevice *dev;
|
||||
|
||||
ret = i2c_get_chip_for_busnum(0, i2caddress, 1, &dev);
|
||||
if (!ret)
|
||||
ret = dm_i2c_write(dev, IR36021_LOOP1_MANUAL_ID_OFFSET,
|
||||
(void *)&vid, sizeof(vid));
|
||||
|
||||
#endif
|
||||
if (ret) {
|
||||
printf("VID: failed to write VID\n");
|
||||
return -1;
|
||||
}
|
||||
wait = wait_for_new_voltage(vdd, i2caddress);
|
||||
if (wait < 0)
|
||||
return -1;
|
||||
debug("VID: Waited %d us\n", wait * NUM_READINGS * WAIT_FOR_ADC);
|
||||
|
||||
vdd_last = wait_for_voltage_stable(i2caddress);
|
||||
if (vdd_last < 0)
|
||||
return -1;
|
||||
debug("VID: Current voltage is %d mV\n", vdd_last);
|
||||
return vdd_last;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_VOL_MONITOR_LTC3882_SET
|
||||
/* this function sets the VDD and returns the value set */
|
||||
static int set_voltage_to_LTC(int i2caddress, int vdd)
|
||||
{
|
||||
int ret, vdd_last, vdd_target = vdd;
|
||||
int count = 100, temp = 0;
|
||||
|
||||
/* Scale up to the LTC resolution is 1/4096V */
|
||||
vdd = (vdd * 4096) / 1000;
|
||||
|
||||
/* 5-byte buffer which needs to be sent following the
|
||||
* PMBus command PAGE_PLUS_WRITE.
|
||||
*/
|
||||
u8 buff[5] = {0x04, PWM_CHANNEL0, PMBUS_CMD_VOUT_COMMAND,
|
||||
vdd & 0xFF, (vdd & 0xFF00) >> 8};
|
||||
|
||||
/* Write the desired voltage code to the regulator */
|
||||
#ifndef CONFIG_DM_I2C
|
||||
ret = i2c_write(I2C_VOL_MONITOR_ADDR,
|
||||
PMBUS_CMD_PAGE_PLUS_WRITE, 1, (void *)&buff, 5);
|
||||
#else
|
||||
struct udevice *dev;
|
||||
|
||||
ret = i2c_get_chip_for_busnum(0, I2C_VOL_MONITOR_ADDR, 1, &dev);
|
||||
if (!ret)
|
||||
ret = dm_i2c_write(dev, PMBUS_CMD_PAGE_PLUS_WRITE,
|
||||
(void *)&buff, 5);
|
||||
#endif
|
||||
if (ret) {
|
||||
printf("VID: I2C failed to write to the volatge regulator\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Wait for the volatge to get to the desired value */
|
||||
do {
|
||||
vdd_last = read_voltage_from_LTC(i2caddress);
|
||||
if (vdd_last < 0) {
|
||||
printf("VID: Couldn't read sensor abort VID adjust\n");
|
||||
return -1;
|
||||
}
|
||||
count--;
|
||||
temp = vdd_last - vdd_target;
|
||||
} while ((abs(temp) > 2) && (count > 0));
|
||||
|
||||
return vdd_last;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int set_voltage(int i2caddress, int vdd)
|
||||
{
|
||||
int vdd_last = -1;
|
||||
|
||||
#ifdef CONFIG_VOL_MONITOR_IR36021_SET
|
||||
vdd_last = set_voltage_to_IR(i2caddress, vdd);
|
||||
#elif defined CONFIG_VOL_MONITOR_LTC3882_SET
|
||||
vdd_last = set_voltage_to_LTC(i2caddress, vdd);
|
||||
#else
|
||||
#error Specific voltage monitor must be defined
|
||||
#endif
|
||||
return vdd_last;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_FSL_LSCH3
|
||||
int adjust_vdd(ulong vdd_override)
|
||||
{
|
||||
int re_enable = disable_interrupts();
|
||||
struct ccsr_gur *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR);
|
||||
u32 fusesr;
|
||||
#if defined(CONFIG_VOL_MONITOR_IR36021_SET) || \
|
||||
defined(CONFIG_VOL_MONITOR_IR36021_READ)
|
||||
u8 vid, buf;
|
||||
#else
|
||||
u8 vid;
|
||||
#endif
|
||||
int vdd_target, vdd_current, vdd_last;
|
||||
int ret, i2caddress;
|
||||
unsigned long vdd_string_override;
|
||||
char *vdd_string;
|
||||
#ifdef CONFIG_ARCH_LX2160A
|
||||
static const u16 vdd[32] = {
|
||||
8250,
|
||||
7875,
|
||||
7750,
|
||||
0, /* reserved */
|
||||
0, /* reserved */
|
||||
0, /* reserved */
|
||||
0, /* reserved */
|
||||
0, /* reserved */
|
||||
0, /* reserved */
|
||||
0, /* reserved */
|
||||
0, /* reserved */
|
||||
0, /* reserved */
|
||||
0, /* reserved */
|
||||
0, /* reserved */
|
||||
0, /* reserved */
|
||||
0, /* reserved */
|
||||
8000,
|
||||
8125,
|
||||
8250,
|
||||
0, /* reserved */
|
||||
8500,
|
||||
0, /* reserved */
|
||||
0, /* reserved */
|
||||
0, /* reserved */
|
||||
0, /* reserved */
|
||||
0, /* reserved */
|
||||
0, /* reserved */
|
||||
0, /* reserved */
|
||||
0, /* reserved */
|
||||
0, /* reserved */
|
||||
0, /* reserved */
|
||||
0, /* reserved */
|
||||
};
|
||||
#else
|
||||
#ifdef CONFIG_ARCH_LS1088A
|
||||
static const uint16_t vdd[32] = {
|
||||
10250,
|
||||
9875,
|
||||
9750,
|
||||
0, /* reserved */
|
||||
0, /* reserved */
|
||||
0, /* reserved */
|
||||
0, /* reserved */
|
||||
0, /* reserved */
|
||||
9000,
|
||||
0, /* reserved */
|
||||
0, /* reserved */
|
||||
0, /* reserved */
|
||||
0, /* reserved */
|
||||
0, /* reserved */
|
||||
0, /* reserved */
|
||||
0, /* reserved */
|
||||
10000, /* 1.0000V */
|
||||
10125,
|
||||
10250,
|
||||
0, /* reserved */
|
||||
0, /* reserved */
|
||||
0, /* reserved */
|
||||
0, /* reserved */
|
||||
0, /* reserved */
|
||||
0, /* reserved */
|
||||
0, /* reserved */
|
||||
0, /* reserved */
|
||||
0, /* reserved */
|
||||
0, /* reserved */
|
||||
0, /* reserved */
|
||||
0, /* reserved */
|
||||
0, /* reserved */
|
||||
};
|
||||
|
||||
#else
|
||||
static const uint16_t vdd[32] = {
|
||||
10500,
|
||||
0, /* reserved */
|
||||
9750,
|
||||
0, /* reserved */
|
||||
9500,
|
||||
0, /* reserved */
|
||||
0, /* reserved */
|
||||
0, /* reserved */
|
||||
0, /* reserved */
|
||||
0, /* reserved */
|
||||
0, /* reserved */
|
||||
9000, /* reserved */
|
||||
0, /* reserved */
|
||||
0, /* reserved */
|
||||
0, /* reserved */
|
||||
0, /* reserved */
|
||||
10000, /* 1.0000V */
|
||||
0, /* reserved */
|
||||
10250,
|
||||
0, /* reserved */
|
||||
10500,
|
||||
0, /* reserved */
|
||||
0, /* reserved */
|
||||
0, /* reserved */
|
||||
0, /* reserved */
|
||||
0, /* reserved */
|
||||
0, /* reserved */
|
||||
0, /* reserved */
|
||||
0, /* reserved */
|
||||
0, /* reserved */
|
||||
0, /* reserved */
|
||||
0, /* reserved */
|
||||
};
|
||||
#endif
|
||||
#endif
|
||||
struct vdd_drive {
|
||||
u8 vid;
|
||||
unsigned voltage;
|
||||
};
|
||||
|
||||
ret = i2c_multiplexer_select_vid_channel(I2C_MUX_CH_VOL_MONITOR);
|
||||
if (ret) {
|
||||
debug("VID: I2C failed to switch channel\n");
|
||||
ret = -1;
|
||||
goto exit;
|
||||
}
|
||||
#if defined(CONFIG_VOL_MONITOR_IR36021_SET) || \
|
||||
defined(CONFIG_VOL_MONITOR_IR36021_READ)
|
||||
ret = find_ir_chip_on_i2c();
|
||||
if (ret < 0) {
|
||||
printf("VID: Could not find voltage regulator on I2C.\n");
|
||||
ret = -1;
|
||||
goto exit;
|
||||
} else {
|
||||
i2caddress = ret;
|
||||
debug("VID: IR Chip found on I2C address 0x%02x\n", i2caddress);
|
||||
}
|
||||
|
||||
/* check IR chip work on Intel mode*/
|
||||
#ifndef CONFIG_DM_I2C
|
||||
ret = i2c_read(i2caddress,
|
||||
IR36021_INTEL_MODE_OOFSET,
|
||||
1, (void *)&buf, 1);
|
||||
#else
|
||||
struct udevice *dev;
|
||||
|
||||
ret = i2c_get_chip_for_busnum(0, i2caddress, 1, &dev);
|
||||
if (!ret)
|
||||
ret = dm_i2c_read(dev, IR36021_INTEL_MODE_OOFSET,
|
||||
(void *)&buf, 1);
|
||||
#endif
|
||||
if (ret) {
|
||||
printf("VID: failed to read IR chip mode.\n");
|
||||
ret = -1;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if ((buf & IR36021_MODE_MASK) != IR36021_INTEL_MODE) {
|
||||
printf("VID: IR Chip is not used in Intel mode.\n");
|
||||
ret = -1;
|
||||
goto exit;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* get the voltage ID from fuse status register */
|
||||
fusesr = in_le32(&gur->dcfg_fusesr);
|
||||
vid = (fusesr >> FSL_CHASSIS3_DCFG_FUSESR_ALTVID_SHIFT) &
|
||||
FSL_CHASSIS3_DCFG_FUSESR_ALTVID_MASK;
|
||||
if ((vid == 0) || (vid == FSL_CHASSIS3_DCFG_FUSESR_ALTVID_MASK)) {
|
||||
vid = (fusesr >> FSL_CHASSIS3_DCFG_FUSESR_VID_SHIFT) &
|
||||
FSL_CHASSIS3_DCFG_FUSESR_VID_MASK;
|
||||
}
|
||||
vdd_target = vdd[vid];
|
||||
|
||||
/* check override variable for overriding VDD */
|
||||
vdd_string = env_get(CONFIG_VID_FLS_ENV);
|
||||
if (vdd_override == 0 && vdd_string &&
|
||||
!strict_strtoul(vdd_string, 10, &vdd_string_override))
|
||||
vdd_override = vdd_string_override;
|
||||
|
||||
if (vdd_override >= VDD_MV_MIN && vdd_override <= VDD_MV_MAX) {
|
||||
vdd_target = vdd_override * 10; /* convert to 1/10 mV */
|
||||
debug("VDD override is %lu\n", vdd_override);
|
||||
} else if (vdd_override != 0) {
|
||||
printf("Invalid value.\n");
|
||||
}
|
||||
|
||||
/* divide and round up by 10 to get a value in mV */
|
||||
vdd_target = DIV_ROUND_UP(vdd_target, 10);
|
||||
if (vdd_target == 0) {
|
||||
debug("VID: VID not used\n");
|
||||
ret = 0;
|
||||
goto exit;
|
||||
} else if (vdd_target < VDD_MV_MIN || vdd_target > VDD_MV_MAX) {
|
||||
/* Check vdd_target is in valid range */
|
||||
printf("VID: Target VID %d mV is not in range.\n",
|
||||
vdd_target);
|
||||
ret = -1;
|
||||
goto exit;
|
||||
} else {
|
||||
debug("VID: vid = %d mV\n", vdd_target);
|
||||
}
|
||||
|
||||
/*
|
||||
* Read voltage monitor to check real voltage.
|
||||
*/
|
||||
vdd_last = read_voltage(i2caddress);
|
||||
if (vdd_last < 0) {
|
||||
printf("VID: Couldn't read sensor abort VID adjustment\n");
|
||||
ret = -1;
|
||||
goto exit;
|
||||
}
|
||||
vdd_current = vdd_last;
|
||||
debug("VID: Core voltage is currently at %d mV\n", vdd_last);
|
||||
|
||||
#ifdef CONFIG_VOL_MONITOR_LTC3882_SET
|
||||
/* Set the target voltage */
|
||||
vdd_last = vdd_current = set_voltage(i2caddress, vdd_target);
|
||||
#else
|
||||
/*
|
||||
* Adjust voltage to at or one step above target.
|
||||
* As measurements are less precise than setting the values
|
||||
* we may run through dummy steps that cancel each other
|
||||
* when stepping up and then down.
|
||||
*/
|
||||
while (vdd_last > 0 &&
|
||||
vdd_last < vdd_target) {
|
||||
vdd_current += IR_VDD_STEP_UP;
|
||||
vdd_last = set_voltage(i2caddress, vdd_current);
|
||||
}
|
||||
while (vdd_last > 0 &&
|
||||
vdd_last > vdd_target + (IR_VDD_STEP_DOWN - 1)) {
|
||||
vdd_current -= IR_VDD_STEP_DOWN;
|
||||
vdd_last = set_voltage(i2caddress, vdd_current);
|
||||
}
|
||||
|
||||
#endif
|
||||
if (board_adjust_vdd(vdd_target) < 0) {
|
||||
ret = -1;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (vdd_last > 0)
|
||||
printf("VID: Core voltage after adjustment is at %d mV\n",
|
||||
vdd_last);
|
||||
else
|
||||
ret = -1;
|
||||
exit:
|
||||
if (re_enable)
|
||||
enable_interrupts();
|
||||
i2c_multiplexer_select_vid_channel(I2C_MUX_CH_DEFAULT);
|
||||
return ret;
|
||||
}
|
||||
#else /* !CONFIG_FSL_LSCH3 */
|
||||
int adjust_vdd(ulong vdd_override)
|
||||
{
|
||||
int re_enable = disable_interrupts();
|
||||
#if defined(CONFIG_FSL_LSCH2)
|
||||
struct ccsr_gur *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR);
|
||||
#else
|
||||
ccsr_gur_t __iomem *gur =
|
||||
(void __iomem *)(CONFIG_SYS_MPC85xx_GUTS_ADDR);
|
||||
#endif
|
||||
u32 fusesr;
|
||||
u8 vid, buf;
|
||||
int vdd_target, vdd_current, vdd_last;
|
||||
int ret, i2caddress;
|
||||
unsigned long vdd_string_override;
|
||||
char *vdd_string;
|
||||
static const uint16_t vdd[32] = {
|
||||
0, /* unused */
|
||||
9875, /* 0.9875V */
|
||||
9750,
|
||||
9625,
|
||||
9500,
|
||||
9375,
|
||||
9250,
|
||||
9125,
|
||||
9000,
|
||||
8875,
|
||||
8750,
|
||||
8625,
|
||||
8500,
|
||||
8375,
|
||||
8250,
|
||||
8125,
|
||||
10000, /* 1.0000V */
|
||||
10125,
|
||||
10250,
|
||||
10375,
|
||||
10500,
|
||||
10625,
|
||||
10750,
|
||||
10875,
|
||||
11000,
|
||||
0, /* reserved */
|
||||
};
|
||||
struct vdd_drive {
|
||||
u8 vid;
|
||||
unsigned voltage;
|
||||
};
|
||||
|
||||
ret = i2c_multiplexer_select_vid_channel(I2C_MUX_CH_VOL_MONITOR);
|
||||
if (ret) {
|
||||
debug("VID: I2C failed to switch channel\n");
|
||||
ret = -1;
|
||||
goto exit;
|
||||
}
|
||||
#if defined(CONFIG_VOL_MONITOR_IR36021_SET) || \
|
||||
defined(CONFIG_VOL_MONITOR_IR36021_READ)
|
||||
ret = find_ir_chip_on_i2c();
|
||||
if (ret < 0) {
|
||||
printf("VID: Could not find voltage regulator on I2C.\n");
|
||||
ret = -1;
|
||||
goto exit;
|
||||
} else {
|
||||
i2caddress = ret;
|
||||
debug("VID: IR Chip found on I2C address 0x%02x\n", i2caddress);
|
||||
}
|
||||
|
||||
/* check IR chip work on Intel mode*/
|
||||
#ifndef CONFIG_DM_I2C
|
||||
ret = i2c_read(i2caddress,
|
||||
IR36021_INTEL_MODE_OOFSET,
|
||||
1, (void *)&buf, 1);
|
||||
#else
|
||||
struct udevice *dev;
|
||||
|
||||
ret = i2c_get_chip_for_busnum(0, i2caddress, 1, &dev);
|
||||
if (!ret)
|
||||
ret = dm_i2c_read(dev, IR36021_INTEL_MODE_OOFSET,
|
||||
(void *)&buf, 1);
|
||||
#endif
|
||||
if (ret) {
|
||||
printf("VID: failed to read IR chip mode.\n");
|
||||
ret = -1;
|
||||
goto exit;
|
||||
}
|
||||
if ((buf & IR36021_MODE_MASK) != IR36021_INTEL_MODE) {
|
||||
printf("VID: IR Chip is not used in Intel mode.\n");
|
||||
ret = -1;
|
||||
goto exit;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* get the voltage ID from fuse status register */
|
||||
fusesr = in_be32(&gur->dcfg_fusesr);
|
||||
/*
|
||||
* VID is used according to the table below
|
||||
* ---------------------------------------
|
||||
* | DA_V |
|
||||
* |-------------------------------------|
|
||||
* | 5b00000 | 5b00001-5b11110 | 5b11111 |
|
||||
* ---------------+---------+-----------------+---------|
|
||||
* | D | 5b00000 | NO VID | VID = DA_V | NO VID |
|
||||
* | A |----------+---------+-----------------+---------|
|
||||
* | _ | 5b00001 |VID = | VID = |VID = |
|
||||
* | V | ~ | DA_V_ALT| DA_V_ALT | DA_A_VLT|
|
||||
* | _ | 5b11110 | | | |
|
||||
* | A |----------+---------+-----------------+---------|
|
||||
* | L | 5b11111 | No VID | VID = DA_V | NO VID |
|
||||
* | T | | | | |
|
||||
* ------------------------------------------------------
|
||||
*/
|
||||
#ifdef CONFIG_FSL_LSCH2
|
||||
vid = (fusesr >> FSL_CHASSIS2_DCFG_FUSESR_ALTVID_SHIFT) &
|
||||
FSL_CHASSIS2_DCFG_FUSESR_ALTVID_MASK;
|
||||
if ((vid == 0) || (vid == FSL_CHASSIS2_DCFG_FUSESR_ALTVID_MASK)) {
|
||||
vid = (fusesr >> FSL_CHASSIS2_DCFG_FUSESR_VID_SHIFT) &
|
||||
FSL_CHASSIS2_DCFG_FUSESR_VID_MASK;
|
||||
}
|
||||
#else
|
||||
vid = (fusesr >> FSL_CORENET_DCFG_FUSESR_ALTVID_SHIFT) &
|
||||
FSL_CORENET_DCFG_FUSESR_ALTVID_MASK;
|
||||
if ((vid == 0) || (vid == FSL_CORENET_DCFG_FUSESR_ALTVID_MASK)) {
|
||||
vid = (fusesr >> FSL_CORENET_DCFG_FUSESR_VID_SHIFT) &
|
||||
FSL_CORENET_DCFG_FUSESR_VID_MASK;
|
||||
}
|
||||
#endif
|
||||
vdd_target = vdd[vid];
|
||||
|
||||
/* check override variable for overriding VDD */
|
||||
vdd_string = env_get(CONFIG_VID_FLS_ENV);
|
||||
if (vdd_override == 0 && vdd_string &&
|
||||
!strict_strtoul(vdd_string, 10, &vdd_string_override))
|
||||
vdd_override = vdd_string_override;
|
||||
if (vdd_override >= VDD_MV_MIN && vdd_override <= VDD_MV_MAX) {
|
||||
vdd_target = vdd_override * 10; /* convert to 1/10 mV */
|
||||
debug("VDD override is %lu\n", vdd_override);
|
||||
} else if (vdd_override != 0) {
|
||||
printf("Invalid value.\n");
|
||||
}
|
||||
if (vdd_target == 0) {
|
||||
debug("VID: VID not used\n");
|
||||
ret = 0;
|
||||
goto exit;
|
||||
} else {
|
||||
/* divide and round up by 10 to get a value in mV */
|
||||
vdd_target = DIV_ROUND_UP(vdd_target, 10);
|
||||
debug("VID: vid = %d mV\n", vdd_target);
|
||||
}
|
||||
|
||||
/*
|
||||
* Read voltage monitor to check real voltage.
|
||||
*/
|
||||
vdd_last = read_voltage(i2caddress);
|
||||
if (vdd_last < 0) {
|
||||
printf("VID: Couldn't read sensor abort VID adjustment\n");
|
||||
ret = -1;
|
||||
goto exit;
|
||||
}
|
||||
vdd_current = vdd_last;
|
||||
debug("VID: Core voltage is currently at %d mV\n", vdd_last);
|
||||
/*
|
||||
* Adjust voltage to at or one step above target.
|
||||
* As measurements are less precise than setting the values
|
||||
* we may run through dummy steps that cancel each other
|
||||
* when stepping up and then down.
|
||||
*/
|
||||
while (vdd_last > 0 &&
|
||||
vdd_last < vdd_target) {
|
||||
vdd_current += IR_VDD_STEP_UP;
|
||||
vdd_last = set_voltage(i2caddress, vdd_current);
|
||||
}
|
||||
while (vdd_last > 0 &&
|
||||
vdd_last > vdd_target + (IR_VDD_STEP_DOWN - 1)) {
|
||||
vdd_current -= IR_VDD_STEP_DOWN;
|
||||
vdd_last = set_voltage(i2caddress, vdd_current);
|
||||
}
|
||||
|
||||
if (vdd_last > 0)
|
||||
printf("VID: Core voltage after adjustment is at %d mV\n",
|
||||
vdd_last);
|
||||
else
|
||||
ret = -1;
|
||||
exit:
|
||||
if (re_enable)
|
||||
enable_interrupts();
|
||||
|
||||
i2c_multiplexer_select_vid_channel(I2C_MUX_CH_DEFAULT);
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int print_vdd(void)
|
||||
{
|
||||
int vdd_last, ret, i2caddress;
|
||||
|
||||
ret = i2c_multiplexer_select_vid_channel(I2C_MUX_CH_VOL_MONITOR);
|
||||
if (ret) {
|
||||
debug("VID : I2c failed to switch channel\n");
|
||||
return -1;
|
||||
}
|
||||
#if defined(CONFIG_VOL_MONITOR_IR36021_SET) || \
|
||||
defined(CONFIG_VOL_MONITOR_IR36021_READ)
|
||||
ret = find_ir_chip_on_i2c();
|
||||
if (ret < 0) {
|
||||
printf("VID: Could not find voltage regulator on I2C.\n");
|
||||
goto exit;
|
||||
} else {
|
||||
i2caddress = ret;
|
||||
debug("VID: IR Chip found on I2C address 0x%02x\n", i2caddress);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Read voltage monitor to check real voltage.
|
||||
*/
|
||||
vdd_last = read_voltage(i2caddress);
|
||||
if (vdd_last < 0) {
|
||||
printf("VID: Couldn't read sensor abort VID adjustment\n");
|
||||
goto exit;
|
||||
}
|
||||
printf("VID: Core voltage is at %d mV\n", vdd_last);
|
||||
exit:
|
||||
i2c_multiplexer_select_vid_channel(I2C_MUX_CH_DEFAULT);
|
||||
|
||||
return ret < 0 ? -1 : 0;
|
||||
|
||||
}
|
||||
|
||||
static int do_vdd_override(cmd_tbl_t *cmdtp,
|
||||
int flag, int argc,
|
||||
char * const argv[])
|
||||
{
|
||||
ulong override;
|
||||
|
||||
if (argc < 2)
|
||||
return CMD_RET_USAGE;
|
||||
|
||||
if (!strict_strtoul(argv[1], 10, &override))
|
||||
adjust_vdd(override); /* the value is checked by callee */
|
||||
else
|
||||
return CMD_RET_USAGE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int do_vdd_read(cmd_tbl_t *cmdtp,
|
||||
int flag, int argc,
|
||||
char * const argv[])
|
||||
{
|
||||
if (argc < 1)
|
||||
return CMD_RET_USAGE;
|
||||
print_vdd();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
U_BOOT_CMD(
|
||||
vdd_override, 2, 0, do_vdd_override,
|
||||
"override VDD",
|
||||
" - override with the voltage specified in mV, eg. 1050"
|
||||
);
|
||||
|
||||
U_BOOT_CMD(
|
||||
vdd_read, 1, 0, do_vdd_read,
|
||||
"read VDD",
|
||||
" - Read the voltage specified in mV"
|
||||
)
|
||||
@@ -0,0 +1,23 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||
/*
|
||||
* Copyright 2014 Freescale Semiconductor, Inc.
|
||||
*/
|
||||
|
||||
#ifndef __VID_H_
|
||||
#define __VID_H_
|
||||
|
||||
#define IR36021_LOOP1_MANUAL_ID_OFFSET 0x6A
|
||||
#define IR36021_LOOP1_VOUT_OFFSET 0x9A
|
||||
#define IR36021_MFR_ID_OFFSET 0x92
|
||||
#define IR36021_MFR_ID 0x43
|
||||
#define IR36021_INTEL_MODE_OOFSET 0x14
|
||||
#define IR36021_MODE_MASK 0x20
|
||||
#define IR36021_INTEL_MODE 0x00
|
||||
#define IR36021_AMD_MODE 0x20
|
||||
|
||||
/* step the IR regulator in 5mV increments */
|
||||
#define IR_VDD_STEP_DOWN 5
|
||||
#define IR_VDD_STEP_UP 5
|
||||
int adjust_vdd(ulong vdd_override);
|
||||
|
||||
#endif /* __VID_H_ */
|
||||
@@ -0,0 +1,275 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Copyright 2012 Freescale Semiconductor, Inc.
|
||||
*/
|
||||
|
||||
#include "vsc3316_3308.h"
|
||||
|
||||
#define REVISION_ID_REG 0x7E
|
||||
#define INTERFACE_MODE_REG 0x79
|
||||
#define CURRENT_PAGE_REGISTER 0x7F
|
||||
#define CONNECTION_CONFIG_PAGE 0x00
|
||||
#define INPUT_STATE_REG 0x13
|
||||
#define GLOBAL_INPUT_ISE1 0x51
|
||||
#define GLOBAL_INPUT_ISE2 0x52
|
||||
#define GLOBAL_INPUT_GAIN 0x53
|
||||
#define GLOBAL_INPUT_LOS 0x55
|
||||
#define GLOBAL_OUTPUT_PE1 0x56
|
||||
#define GLOBAL_OUTPUT_PE2 0x57
|
||||
#define GLOBAL_OUTPUT_LEVEL 0x58
|
||||
#define GLOBAL_OUTPUT_TERMINATION 0x5A
|
||||
#define GLOBAL_CORE_CNTRL 0x5D
|
||||
#define OUTPUT_MODE_PAGE 0x23
|
||||
#define CORE_CONTROL_PAGE 0x25
|
||||
#define CORE_CONFIG_REG 0x75
|
||||
|
||||
int vsc_if_enable(unsigned int vsc_addr)
|
||||
{
|
||||
u8 data;
|
||||
|
||||
debug("VSC:Configuring VSC at I2C address 0x%2x"
|
||||
" for 2-wire interface\n", vsc_addr);
|
||||
|
||||
/* enable 2-wire Serial InterFace (I2C) */
|
||||
data = 0x02;
|
||||
return i2c_write(vsc_addr, INTERFACE_MODE_REG, 1, &data, 1);
|
||||
}
|
||||
|
||||
int vsc3316_config(unsigned int vsc_addr, int8_t con_arr[][2],
|
||||
unsigned int num_con)
|
||||
{
|
||||
unsigned int i;
|
||||
u8 rev_id = 0;
|
||||
int ret;
|
||||
|
||||
debug("VSC:Initializing VSC3316 at I2C address 0x%2x"
|
||||
" for Tx\n", vsc_addr);
|
||||
|
||||
ret = i2c_read(vsc_addr, REVISION_ID_REG, 1, &rev_id, 1);
|
||||
if (ret < 0) {
|
||||
printf("VSC:0x%x could not read REV_ID from device.\n",
|
||||
vsc_addr);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (rev_id != 0xab) {
|
||||
printf("VSC: device at address 0x%x is not VSC3316/3308.\n",
|
||||
vsc_addr);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
ret = vsc_if_enable(vsc_addr);
|
||||
if (ret) {
|
||||
printf("VSC:0x%x could not configured for 2-wire I/F.\n",
|
||||
vsc_addr);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* config connections - page 0x00 */
|
||||
i2c_reg_write(vsc_addr, CURRENT_PAGE_REGISTER, CONNECTION_CONFIG_PAGE);
|
||||
|
||||
/* Making crosspoint connections, by connecting required
|
||||
* input to output */
|
||||
for (i = 0; i < num_con ; i++)
|
||||
i2c_reg_write(vsc_addr, con_arr[i][1], con_arr[i][0]);
|
||||
|
||||
/* input state - page 0x13 */
|
||||
i2c_reg_write(vsc_addr, CURRENT_PAGE_REGISTER, INPUT_STATE_REG);
|
||||
/* Configuring the required input of the switch */
|
||||
for (i = 0; i < num_con ; i++)
|
||||
i2c_reg_write(vsc_addr, con_arr[i][0], 0x80);
|
||||
|
||||
/* Setting Global Input LOS threshold value */
|
||||
i2c_reg_write(vsc_addr, GLOBAL_INPUT_LOS, 0x60);
|
||||
|
||||
/* config output mode - page 0x23 */
|
||||
i2c_reg_write(vsc_addr, CURRENT_PAGE_REGISTER, OUTPUT_MODE_PAGE);
|
||||
/* Turn ON the Output driver correspond to required output*/
|
||||
for (i = 0; i < num_con ; i++)
|
||||
i2c_reg_write(vsc_addr, con_arr[i][1], 0);
|
||||
|
||||
/* configure global core control register, Turn on Global core power */
|
||||
i2c_reg_write(vsc_addr, GLOBAL_CORE_CNTRL, 0);
|
||||
|
||||
vsc_wp_config(vsc_addr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SYS_FSL_B4860QDS_XFI_ERR
|
||||
int vsc3308_config_adjust(unsigned int vsc_addr, const int8_t con_arr[][2],
|
||||
unsigned int num_con)
|
||||
{
|
||||
unsigned int i;
|
||||
u8 rev_id = 0;
|
||||
int ret;
|
||||
|
||||
debug("VSC:Initializing VSC3308 at I2C address 0x%x for Tx\n",
|
||||
vsc_addr);
|
||||
|
||||
ret = i2c_read(vsc_addr, REVISION_ID_REG, 1, &rev_id, 1);
|
||||
if (ret < 0) {
|
||||
printf("VSC:0x%x could not read REV_ID from device.\n",
|
||||
vsc_addr);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (rev_id != 0xab) {
|
||||
printf("VSC: device at address 0x%x is not VSC3316/3308.\n",
|
||||
vsc_addr);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
ret = vsc_if_enable(vsc_addr);
|
||||
if (ret) {
|
||||
printf("VSC:0x%x could not configured for 2-wire I/F.\n",
|
||||
vsc_addr);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* config connections - page 0x00 */
|
||||
i2c_reg_write(vsc_addr, CURRENT_PAGE_REGISTER, CONNECTION_CONFIG_PAGE);
|
||||
|
||||
/* Configure Global Input ISE */
|
||||
i2c_reg_write(vsc_addr, GLOBAL_INPUT_ISE1, 0);
|
||||
i2c_reg_write(vsc_addr, GLOBAL_INPUT_ISE2, 0);
|
||||
|
||||
/* Configure Tx/Rx Global Output PE1 */
|
||||
i2c_reg_write(vsc_addr, GLOBAL_OUTPUT_PE1, 0);
|
||||
|
||||
/* Configure Tx/Rx Global Output PE2 */
|
||||
i2c_reg_write(vsc_addr, GLOBAL_OUTPUT_PE2, 0);
|
||||
|
||||
/* Configure Tx/Rx Global Input GAIN */
|
||||
i2c_reg_write(vsc_addr, GLOBAL_INPUT_GAIN, 0x3F);
|
||||
|
||||
/* Setting Global Input LOS threshold value */
|
||||
i2c_reg_write(vsc_addr, GLOBAL_INPUT_LOS, 0xE0);
|
||||
|
||||
/* Setting Global output termination */
|
||||
i2c_reg_write(vsc_addr, GLOBAL_OUTPUT_TERMINATION, 0);
|
||||
|
||||
/* Configure Tx/Rx Global Output level */
|
||||
if (vsc_addr == VSC3308_TX_ADDRESS)
|
||||
i2c_reg_write(vsc_addr, GLOBAL_OUTPUT_LEVEL, 4);
|
||||
else
|
||||
i2c_reg_write(vsc_addr, GLOBAL_OUTPUT_LEVEL, 2);
|
||||
|
||||
/* Making crosspoint connections, by connecting required
|
||||
* input to output */
|
||||
for (i = 0; i < num_con ; i++)
|
||||
i2c_reg_write(vsc_addr, con_arr[i][1], con_arr[i][0]);
|
||||
|
||||
/* input state - page 0x13 */
|
||||
i2c_reg_write(vsc_addr, CURRENT_PAGE_REGISTER, INPUT_STATE_REG);
|
||||
/* Turning off all the required input of the switch */
|
||||
for (i = 0; i < num_con; i++)
|
||||
i2c_reg_write(vsc_addr, con_arr[i][0], 1);
|
||||
|
||||
/* only turn on specific Tx/Rx requested by the XFI erratum */
|
||||
if (vsc_addr == VSC3308_TX_ADDRESS) {
|
||||
i2c_reg_write(vsc_addr, 2, 0);
|
||||
i2c_reg_write(vsc_addr, 3, 0);
|
||||
} else {
|
||||
i2c_reg_write(vsc_addr, 0, 0);
|
||||
i2c_reg_write(vsc_addr, 1, 0);
|
||||
}
|
||||
|
||||
/* config output mode - page 0x23 */
|
||||
i2c_reg_write(vsc_addr, CURRENT_PAGE_REGISTER, OUTPUT_MODE_PAGE);
|
||||
/* Turn off the Output driver correspond to required output*/
|
||||
for (i = 0; i < num_con ; i++)
|
||||
i2c_reg_write(vsc_addr, con_arr[i][1], 1);
|
||||
|
||||
/* only turn on specific Tx/Rx requested by the XFI erratum */
|
||||
if (vsc_addr == VSC3308_TX_ADDRESS) {
|
||||
i2c_reg_write(vsc_addr, 0, 0);
|
||||
i2c_reg_write(vsc_addr, 1, 0);
|
||||
} else {
|
||||
i2c_reg_write(vsc_addr, 3, 0);
|
||||
i2c_reg_write(vsc_addr, 4, 0);
|
||||
}
|
||||
|
||||
/* configure global core control register, Turn on Global core power */
|
||||
i2c_reg_write(vsc_addr, GLOBAL_CORE_CNTRL, 0);
|
||||
|
||||
vsc_wp_config(vsc_addr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
int vsc3308_config(unsigned int vsc_addr, const int8_t con_arr[][2],
|
||||
unsigned int num_con)
|
||||
{
|
||||
unsigned int i;
|
||||
u8 rev_id = 0;
|
||||
int ret;
|
||||
|
||||
debug("VSC:Initializing VSC3308 at I2C address 0x%x"
|
||||
" for Tx\n", vsc_addr);
|
||||
|
||||
ret = i2c_read(vsc_addr, REVISION_ID_REG, 1, &rev_id, 1);
|
||||
if (ret < 0) {
|
||||
printf("VSC:0x%x could not read REV_ID from device.\n",
|
||||
vsc_addr);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (rev_id != 0xab) {
|
||||
printf("VSC: device at address 0x%x is not VSC3316/3308.\n",
|
||||
vsc_addr);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
ret = vsc_if_enable(vsc_addr);
|
||||
if (ret) {
|
||||
printf("VSC:0x%x could not configured for 2-wire I/F.\n",
|
||||
vsc_addr);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* config connections - page 0x00 */
|
||||
i2c_reg_write(vsc_addr, CURRENT_PAGE_REGISTER, CONNECTION_CONFIG_PAGE);
|
||||
|
||||
/* Making crosspoint connections, by connecting required
|
||||
* input to output */
|
||||
for (i = 0; i < num_con ; i++)
|
||||
i2c_reg_write(vsc_addr, con_arr[i][1], con_arr[i][0]);
|
||||
|
||||
/*Configure Global Input ISE and gain */
|
||||
i2c_reg_write(vsc_addr, GLOBAL_INPUT_ISE1, 0x12);
|
||||
i2c_reg_write(vsc_addr, GLOBAL_INPUT_ISE2, 0x12);
|
||||
|
||||
/* input state - page 0x13 */
|
||||
i2c_reg_write(vsc_addr, CURRENT_PAGE_REGISTER, INPUT_STATE_REG);
|
||||
/* Turning ON the required input of the switch */
|
||||
for (i = 0; i < num_con ; i++)
|
||||
i2c_reg_write(vsc_addr, con_arr[i][0], 0);
|
||||
|
||||
/* Setting Global Input LOS threshold value */
|
||||
i2c_reg_write(vsc_addr, GLOBAL_INPUT_LOS, 0x60);
|
||||
|
||||
/* config output mode - page 0x23 */
|
||||
i2c_reg_write(vsc_addr, CURRENT_PAGE_REGISTER, OUTPUT_MODE_PAGE);
|
||||
/* Turn ON the Output driver correspond to required output*/
|
||||
for (i = 0; i < num_con ; i++)
|
||||
i2c_reg_write(vsc_addr, con_arr[i][1], 0);
|
||||
|
||||
/* configure global core control register, Turn on Global core power */
|
||||
i2c_reg_write(vsc_addr, GLOBAL_CORE_CNTRL, 0);
|
||||
|
||||
vsc_wp_config(vsc_addr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void vsc_wp_config(unsigned int vsc_addr)
|
||||
{
|
||||
debug("VSC:Configuring VSC at address:0x%x for WP\n", vsc_addr);
|
||||
|
||||
/* For new crosspoint configuration to occur, WP bit of
|
||||
* CORE_CONFIG_REG should be set 1 and then reset to 0 */
|
||||
i2c_reg_write(vsc_addr, CORE_CONFIG_REG, 0x01);
|
||||
i2c_reg_write(vsc_addr, CORE_CONFIG_REG, 0x0);
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||
/*
|
||||
* Copyright 2012 Freescale Semiconductor, Inc.
|
||||
*/
|
||||
|
||||
#ifndef __VSC_CROSSBAR_H_
|
||||
#define __VSC_CROSSBAR_H 1_
|
||||
|
||||
#include <common.h>
|
||||
#include <i2c.h>
|
||||
#include <errno.h>
|
||||
|
||||
int vsc_if_enable(unsigned int vsc_addr);
|
||||
int vsc3316_config(unsigned int vsc_addr, int8_t con_arr[][2],
|
||||
unsigned int num_con);
|
||||
#ifdef CONFIG_SYS_FSL_B4860QDS_XFI_ERR
|
||||
int vsc3308_config_adjust(unsigned int vsc_addr, const int8_t con_arr[][2],
|
||||
unsigned int num_con);
|
||||
#endif
|
||||
int vsc3308_config(unsigned int vsc_addr, const int8_t con_arr[][2],
|
||||
unsigned int num_con);
|
||||
void vsc_wp_config(unsigned int vsc_addr);
|
||||
|
||||
#endif /* __VSC_CROSSBAR_H_ */
|
||||
@@ -0,0 +1,232 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Copyright 2013 Freescale Semiconductor, Inc.
|
||||
*/
|
||||
|
||||
/* Power-One ZM7300 DPM */
|
||||
#include "zm7300.h"
|
||||
|
||||
#define DPM_WP 0x96
|
||||
#define WRP_OPCODE 0x01
|
||||
#define WRM_OPCODE 0x02
|
||||
#define RRP_OPCODE 0x11
|
||||
|
||||
#define DPM_SUCCESS 0x01
|
||||
#define DPM_EXEC_FAIL 0x00
|
||||
|
||||
static const uint16_t hex_to_1_10mv[] = {
|
||||
5000,
|
||||
5125,
|
||||
5250,
|
||||
5375,
|
||||
5500,
|
||||
5625,
|
||||
5750,
|
||||
5875,
|
||||
6000,
|
||||
6125,
|
||||
6250,
|
||||
6375,
|
||||
6500,
|
||||
6625,
|
||||
6750,
|
||||
6875,
|
||||
7000,
|
||||
7125,
|
||||
7250,
|
||||
7375,
|
||||
7500,
|
||||
7625,
|
||||
7750,
|
||||
7875,
|
||||
8000,
|
||||
8125,
|
||||
8250,
|
||||
8375,
|
||||
8500,
|
||||
8625,
|
||||
8750,
|
||||
8875,
|
||||
9000,
|
||||
9125,
|
||||
9250,
|
||||
9375,
|
||||
9500, /* 0.95mV */
|
||||
9625,
|
||||
9750,
|
||||
9875,
|
||||
10000, /* 1.0V */
|
||||
10125,
|
||||
10250,
|
||||
10375,
|
||||
10500,
|
||||
10625,
|
||||
10750,
|
||||
10875,
|
||||
11000,
|
||||
11125,
|
||||
11250,
|
||||
11375,
|
||||
11500,
|
||||
11625,
|
||||
11750,
|
||||
11875,
|
||||
12000,
|
||||
12125,
|
||||
12250,
|
||||
12375,
|
||||
0, /* reserved */
|
||||
};
|
||||
|
||||
|
||||
/* Read Data d from Register r of POL p */
|
||||
u8 dpm_rrp(uchar r)
|
||||
{
|
||||
u8 ret[5];
|
||||
|
||||
ret[0] = RRP_OPCODE;
|
||||
/* POL is 0 */
|
||||
ret[1] = 0;
|
||||
ret[2] = r;
|
||||
i2c_read(I2C_DPM_ADDR, 0, -3, ret, 2);
|
||||
if (ret[1] == DPM_SUCCESS) { /* the DPM returned success as status */
|
||||
debug("RRP_OPCODE returned success data is %x\n", ret[0]);
|
||||
return ret[0];
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Write Data d into DPM register r (RAM) */
|
||||
int dpm_wrm(u8 r, u8 d)
|
||||
{
|
||||
u8 ret[5];
|
||||
|
||||
ret[0] = WRM_OPCODE;
|
||||
ret[1] = r;
|
||||
ret[2] = d;
|
||||
i2c_read(I2C_DPM_ADDR, 0, -3, ret, 1);
|
||||
if (ret[0] == DPM_SUCCESS) { /* the DPM returned success as status */
|
||||
debug("WRM_OPCODE returned success data is %x\n", ret[0]);
|
||||
return ret[0];
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Write Data d into Register r of POL(s) a */
|
||||
int dpm_wrp(u8 r, u8 d)
|
||||
{
|
||||
u8 ret[7];
|
||||
|
||||
ret[0] = WRP_OPCODE;
|
||||
/* only POL0 is present */
|
||||
ret[1] = 0x01;
|
||||
ret[2] = 0x00;
|
||||
ret[3] = 0x00;
|
||||
ret[4] = 0x00;
|
||||
ret[5] = r;
|
||||
ret[6] = d;
|
||||
i2c_read(I2C_DPM_ADDR, 0, -7, ret, 1);
|
||||
if (ret[0] == DPM_SUCCESS) { /* the DPM returned success as status */
|
||||
debug("WRP_OPCODE returned success data is %x\n", ret[0]);
|
||||
return 0;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Uses the DPM command RRP */
|
||||
u8 zm_read(uchar reg)
|
||||
{
|
||||
return dpm_rrp(reg);
|
||||
}
|
||||
|
||||
/* ZM_write --
|
||||
Steps:
|
||||
a. Write data to the register
|
||||
b. Read data from register and compare to written value
|
||||
c. Return return_code & voltage_read
|
||||
*/
|
||||
u8 zm_write(u8 reg, u8 data)
|
||||
{
|
||||
u8 d;
|
||||
|
||||
/* write data to register */
|
||||
dpm_wrp(reg, data);
|
||||
|
||||
/* read register and compare to written value */
|
||||
d = dpm_rrp(reg);
|
||||
if (d != data) {
|
||||
printf("zm_write : Comparison register data failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return d;
|
||||
}
|
||||
|
||||
/* zm_write_out_voltage
|
||||
* voltage in 1/10 mV
|
||||
*/
|
||||
int zm_write_voltage(int voltage)
|
||||
{
|
||||
u8 reg = 0x7, vid;
|
||||
uint16_t voltage_read;
|
||||
u8 ret;
|
||||
|
||||
vid = (voltage - 5000) / ZM_STEP;
|
||||
|
||||
ret = zm_write(reg, vid);
|
||||
if (ret != -1) {
|
||||
voltage_read = hex_to_1_10mv[ret];
|
||||
debug("voltage set to %dmV\n", voltage_read/10);
|
||||
return voltage_read;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* zm_read_out_voltage
|
||||
* voltage in 1/10 mV
|
||||
*/
|
||||
int zm_read_voltage(void)
|
||||
{
|
||||
u8 reg = 0x7;
|
||||
u8 ret;
|
||||
int voltage;
|
||||
|
||||
ret = zm_read(reg);
|
||||
if (ret != -1) {
|
||||
voltage = hex_to_1_10mv[ret];
|
||||
debug("Voltage read is %dmV\n", voltage/10);
|
||||
return voltage;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
int zm_disable_wp()
|
||||
{
|
||||
u8 new_wp_value;
|
||||
|
||||
/* Disable using Write-Protect register 0x96 */
|
||||
new_wp_value = 0x8;
|
||||
if ((dpm_wrm(DPM_WP, new_wp_value)) < 0) {
|
||||
printf("Disable Write-Protect register failed\n");
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int zm_enable_wp()
|
||||
{
|
||||
u8 orig_wp_value;
|
||||
orig_wp_value = 0x0;
|
||||
|
||||
/* Enable using Write-Protect register 0x96 */
|
||||
if ((dpm_wrm(DPM_WP, orig_wp_value)) < 0) {
|
||||
printf("Enable Write-Protect register failed\n");
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||
/*
|
||||
* Copyright 2013 Freescale Semiconductor, Inc.
|
||||
*/
|
||||
|
||||
#ifndef __ZM7300_H_
|
||||
#define __ZM7300_H 1_
|
||||
|
||||
#include <common.h>
|
||||
#include <i2c.h>
|
||||
#include <errno.h>
|
||||
#include <asm/io.h>
|
||||
|
||||
#define ZM_STEP 125
|
||||
int zm7300_set_voltage(int voltage_1_10mv);
|
||||
int zm_write_voltage(int voltage);
|
||||
int zm_read_voltage(void);
|
||||
int zm_disable_wp(void);
|
||||
int zm_enable_wp(void);
|
||||
|
||||
#endif /* __ZM7300_H_ */
|
||||
Reference in New Issue
Block a user