GK SDK 源码库: XMIPCLinuxV100R005C00SPC030 (kernel/tools/open_source excluded)

This commit is contained in:
lai
2026-09-06 03:52:57 +08:00
commit b1928b41c0
21813 changed files with 4413081 additions and 0 deletions
@@ -0,0 +1,14 @@
if TARGET_B4860QDS || TARGET_B4420QDS
config SYS_BOARD
default "b4860qds"
config SYS_VENDOR
default "freescale"
config SYS_CONFIG_NAME
default "B4860QDS"
source "board/freescale/common/Kconfig"
endif
@@ -0,0 +1,17 @@
B4860QDS BOARD
M: Ashish Kumar <ashish.kumar@nxp.com>
S: Maintained
F: board/freescale/b4860qds/
F: include/configs/B4860QDS.h
F: configs/B4420QDS_defconfig
F: configs/B4420QDS_NAND_defconfig
F: configs/B4420QDS_SPIFLASH_defconfig
F: configs/B4860QDS_defconfig
F: configs/B4860QDS_NAND_defconfig
F: configs/B4860QDS_SPIFLASH_defconfig
F: configs/B4860QDS_SRIO_PCIE_BOOT_defconfig
B4860QDS_SECURE_BOOT BOARD
M: Ruchika Gupta <ruchika.gupta@nxp.com>
S: Maintained
F: configs/B4860QDS_SECURE_BOOT_defconfig
@@ -0,0 +1,16 @@
# SPDX-License-Identifier: GPL-2.0+
#
# Copyright 2012 Freescale Semiconductor, Inc.
ifdef CONFIG_SPL_BUILD
obj-y += spl.o
else
obj-y += b4860qds.o
obj-$(CONFIG_TARGET_B4860QDS) += eth_b4860qds.o
obj-$(CONFIG_TARGET_B4420QDS) += eth_b4860qds.o
obj-$(CONFIG_PCI) += pci.o
endif
obj-y += ddr.o
obj-y += law.o
obj-y += tlb.o
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,12 @@
/* SPDX-License-Identifier: GPL-2.0+ */
/*
* Copyright 2011-2012 Freescale Semiconductor, Inc.
*/
#ifndef __CORENET_DS_H__
#define __CORENET_DS_H__
void fdt_fixup_board_enet(void *blob);
void pci_of_setup(void *blob, bd_t *bd);
#endif
@@ -0,0 +1,72 @@
/* SPDX-License-Identifier: GPL-2.0+ */
/*
* Copyright 2012 Freescale Semiconductor, Inc.
*/
#ifndef __CROSSBAR_CONNECTIONS_H__
#define __CROSSBAR_CONNECTIONS_H__
#define NUM_CON_VSC3316 8
#define NUM_CON_VSC3308 4
static const int8_t vsc16_tx_amc[8][2] = { {15, 3}, {0, 2}, {7, 4}, {9, 10},
{5, 11}, {4, 5}, {2, 6}, {12, 9} };
static int8_t vsc16_tx_sfp[8][2] = { {15, 7}, {0, 1}, {7, 8}, {9, 0},
{-1, -1}, {-1, -1}, {-1, -1}, {-1, -1} };
static int8_t vsc16_tx_4sfp_sgmii_12_56[8][2] = { {15, 7}, {0, 1},
{7, 8}, {9, 0}, {2, 14}, {12, 15},
{-1, -1}, {-1, -1} };
static const int8_t vsc16_tx_4sfp_sgmii_34[8][2] = { {15, 7}, {0, 1},
{7, 8}, {9, 0}, {5, 14}, {4, 15},
{-1, -1}, {-1, -1} };
static int8_t vsc16_tx_sfp_sgmii_aurora[8][2] = { {15, 7}, {0, 1},
{7, 8}, {9, 0}, {5, 14},
{4, 15}, {2, 12}, {12, 13} };
#ifdef CONFIG_ARCH_B4420
static int8_t vsc16_tx_sgmii_lane_cd[8][2] = { {5, 14}, {4, 15},
{-1, -1}, {-1, -1}, {-1, -1}, {-1, -1}, {-1, -1}, {-1, -1} };
#endif
static const int8_t vsc16_tx_aurora[8][2] = { {2, 13}, {12, 12}, {-1, -1},
{-1, -1}, {-1, -1}, {-1, -1}, {-1, -1}, {-1, -1} };
static const int8_t vsc16_rx_amc[8][2] = { {3, 15}, {2, 1}, {4, 8}, {10, 9},
{11, 11}, {5, 10}, {6, 3}, {9, 12} };
static int8_t vsc16_rx_sfp[8][2] = { {8, 15}, {0, 1}, {7, 8}, {1, 9},
{-1, -1}, {-1, -1}, {-1, -1}, {-1, -1} };
static int8_t vsc16_rx_4sfp_sgmii_12_56[8][2] = { {8, 15}, {0, 1},
{7, 8}, {1, 9}, {14, 3}, {15, 12},
{-1, -1}, {-1, -1} };
static const int8_t vsc16_rx_4sfp_sgmii_34[8][2] = { {8, 15}, {0, 1},
{7, 8}, {1, 9}, {14, 11}, {15, 10},
{-1, -1}, {-1, -1} };
static int8_t vsc16_rx_sfp_sgmii_aurora[8][2] = { {8, 15}, {0, 1},
{7, 8}, {1, 9}, {14, 11},
{15, 10}, {13, 3}, {12, 12} };
#ifdef CONFIG_ARCH_B4420
static int8_t vsc16_rx_sgmii_lane_cd[8][2] = { {14, 11}, {15, 10},
{-1, -1}, {-1, -1}, {-1, -1}, {-1, -1}, {-1, -1}, {-1, -1} };
#endif
static const int8_t vsc16_rx_aurora[8][2] = { {13, 3}, {12, 12}, {-1, -1},
{-1, -1}, {-1, -1}, {-1, -1}, {-1, -1}, {-1, -1} };
static const int8_t vsc08_tx_amc[4][2] = { {2, 2}, {3, 3}, {7, 4}, {1, 5} };
static const int8_t vsc08_tx_sfp[4][2] = { {2, 1}, {3, 0}, {7, 6}, {1, 7} };
static const int8_t vsc08_rx_amc[4][2] = { {2, 3}, {3, 4}, {4, 7}, {5, 1} };
static const int8_t vsc08_rx_sfp[4][2] = { {1, 3}, {0, 4}, {6, 7}, {7, 1} };
#endif
@@ -0,0 +1,28 @@
/* SPDX-License-Identifier: GPL-2.0+ */
/*
* Copyright 2012 Freescale Semiconductor, Inc.
*/
#ifndef __B4860QDS_QIXIS_H__
#define __B4860QDS_QIXIS_H__
/* Definitions of QIXIS Registers for B4860QDS */
/* BRDCFG4[4:7]] select EC1 and EC2 as a pair */
#define BRDCFG4_EMISEL_MASK 0xE0
#define BRDCFG4_EMISEL_SHIFT 5
/* CLK */
#define QIXIS_CLK_66 0x0
#define QIXIS_CLK_100 0x1
#define QIXIS_CLK_125 0x2
#define QIXIS_CLK_133 0x3
#define QIXIS_SRDS1CLK_122 0x5a
#define QIXIS_SRDS1CLK_125 0x5e
/* SGMII */
#define PHY_BASE_ADDR 0x18
#define PORT_NUM 0x04
#define REGNUM 0x00
#endif
@@ -0,0 +1,30 @@
#PBI commands
#Initialize CPC1
09010000 00200400
09138000 00000000
091380c0 00000100
#Configure CPC1 as 512KB SRAM
09010100 00000000
09010104 fff80009
09010f00 08000000
09010000 80000000
#Configure LAW for CPC1
09000d00 00000000
09000d04 fff80000
09000d08 81000012
#Configure alternate space
09000010 00000000
09000014 ff000000
09000018 81000000
#Configure SPI controller
09110000 80000403
09110020 2d170008
09110024 00100008
09110028 00100008
0911002c 00100008
#slowing down the MDC clock to make it <= 2.5 MHZ
094fc030 00008148
094fd030 00008148
#Flush PBL data
09138000 00000000
091380c0 00000000
@@ -0,0 +1,7 @@
#PBL preamble and RCW header
aa55aa55 010e0100
# serdes protocol 0x2A_0x98
140e0018 0f001218 00000000 00000000
54980000 9000a000 e8104000 a9000000
01000000 00000000 00000000 0001b1f8
00000000 14000020 00000000 00000011
@@ -0,0 +1,265 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright 2011-2012 Freescale Semiconductor, Inc.
*/
#include <common.h>
#include <i2c.h>
#include <hwconfig.h>
#include <fsl_ddr.h>
#include <asm/mmu.h>
#include <fsl_ddr_sdram.h>
#include <fsl_ddr_dimm_params.h>
#include <asm/fsl_law.h>
DECLARE_GLOBAL_DATA_PTR;
dimm_params_t ddr_raw_timing = {
.n_ranks = 2,
.rank_density = 2147483648u,
.capacity = 4294967296u,
.primary_sdram_width = 64,
.ec_sdram_width = 8,
.registered_dimm = 0,
.mirrored_dimm = 1,
.n_row_addr = 15,
.n_col_addr = 10,
.n_banks_per_sdram_device = 8,
.edc_config = 2, /* ECC */
.burst_lengths_bitmask = 0x0c,
.tckmin_x_ps = 1071,
.caslat_x = 0x2fe << 4, /* 5,6,7,8,9,10,11,13 */
.taa_ps = 13910,
.twr_ps = 15000,
.trcd_ps = 13910,
.trrd_ps = 6000,
.trp_ps = 13910,
.tras_ps = 34000,
.trc_ps = 48910,
.trfc_ps = 260000,
.twtr_ps = 7500,
.trtp_ps = 7500,
.refresh_rate_ps = 7800000,
.tfaw_ps = 35000,
};
int fsl_ddr_get_dimm_params(dimm_params_t *pdimm,
unsigned int controller_number,
unsigned int dimm_number)
{
const char dimm_model[] = "RAW timing DDR";
if ((controller_number == 0) && (dimm_number == 0)) {
memcpy(pdimm, &ddr_raw_timing, sizeof(dimm_params_t));
memset(pdimm->mpart, 0, sizeof(pdimm->mpart));
memcpy(pdimm->mpart, dimm_model, sizeof(dimm_model) - 1);
}
return 0;
}
struct board_specific_parameters {
u32 n_ranks;
u32 datarate_mhz_high;
u32 clk_adjust;
u32 wrlvl_start;
u32 wrlvl_ctl_2;
u32 wrlvl_ctl_3;
u32 cpo;
u32 write_data_delay;
u32 force_2t;
};
/*
* This table contains all valid speeds we want to override with board
* specific parameters. datarate_mhz_high values need to be in ascending order
* for each n_ranks group.
*/
static const struct board_specific_parameters udimm0[] = {
/*
* memory controller 0
* num| hi| clk| wrlvl | wrlvl | wrlvl | cpo |wrdata|2T
* ranks| mhz|adjst| start | ctl2 | ctl3 | |delay |
*/
{2, 1350, 4, 7, 0x09080807, 0x07060607, 0xff, 2, 0},
{2, 1666, 4, 7, 0x09080806, 0x06050607, 0xff, 2, 0},
{2, 1900, 3, 7, 0x08070706, 0x06040507, 0xff, 2, 0},
{1, 1350, 4, 7, 0x09080807, 0x07060607, 0xff, 2, 0},
{1, 1700, 4, 7, 0x09080806, 0x06050607, 0xff, 2, 0},
{1, 1900, 3, 7, 0x08070706, 0x06040507, 0xff, 2, 0},
{}
};
static const struct board_specific_parameters *udimms[] = {
udimm0,
};
void fsl_ddr_board_options(memctl_options_t *popts,
dimm_params_t *pdimm,
unsigned int ctrl_num)
{
const struct board_specific_parameters *pbsp, *pbsp_highest = NULL;
ulong ddr_freq;
if (ctrl_num > 2) {
printf("Not supported controller number %d\n", ctrl_num);
return;
}
if (!pdimm->n_ranks)
return;
pbsp = udimms[0];
/* Get clk_adjust, cpo, write_data_delay,2T, according to the board ddr
* freqency and n_banks specified in board_specific_parameters table.
*/
ddr_freq = get_ddr_freq(0) / 1000000;
while (pbsp->datarate_mhz_high) {
if (pbsp->n_ranks == pdimm->n_ranks) {
if (ddr_freq <= pbsp->datarate_mhz_high) {
popts->cpo_override = pbsp->cpo;
popts->write_data_delay =
pbsp->write_data_delay;
popts->clk_adjust = pbsp->clk_adjust;
popts->wrlvl_start = pbsp->wrlvl_start;
popts->wrlvl_ctl_2 = pbsp->wrlvl_ctl_2;
popts->wrlvl_ctl_3 = pbsp->wrlvl_ctl_3;
popts->twot_en = pbsp->force_2t;
goto found;
}
pbsp_highest = pbsp;
}
pbsp++;
}
if (pbsp_highest) {
printf("Error: board specific timing not found "
"for data rate %lu MT/s\n"
"Trying to use the highest speed (%u) parameters\n",
ddr_freq, pbsp_highest->datarate_mhz_high);
popts->cpo_override = pbsp_highest->cpo;
popts->write_data_delay = pbsp_highest->write_data_delay;
popts->clk_adjust = pbsp_highest->clk_adjust;
popts->wrlvl_start = pbsp_highest->wrlvl_start;
popts->twot_en = pbsp_highest->force_2t;
} else {
panic("DIMM is not supported by this board");
}
found:
/*
* Factors to consider for half-strength driver enable:
* - number of DIMMs installed
*/
popts->half_strength_driver_enable = 0;
/*
* Write leveling override
*/
popts->wrlvl_override = 1;
popts->wrlvl_sample = 0xf;
/*
* Rtt and Rtt_WR override
*/
popts->rtt_override = 0;
/* Enable ZQ calibration */
popts->zq_en = 1;
/* DHC_EN =1, ODT = 75 Ohm */
popts->ddr_cdr1 = DDR_CDR1_DHC_EN | DDR_CDR1_ODT(DDR_CDR_ODT_75ohm);
popts->ddr_cdr2 = DDR_CDR2_ODT(DDR_CDR_ODT_75ohm);
/* optimize cpo for erratum A-009942 */
popts->cpo_sample = 0x3e;
}
int dram_init(void)
{
phys_size_t dram_size;
#if defined(CONFIG_SPL_BUILD) || !defined(CONFIG_RAMBOOT_PBL)
puts("Initializing....using SPD\n");
dram_size = fsl_ddr_sdram();
#else
dram_size = fsl_ddr_sdram_size();
#endif
dram_size = setup_ddr_tlbs(dram_size / 0x100000);
dram_size *= 0x100000;
gd->ram_size = dram_size;
return 0;
}
unsigned long long step_assign_addresses(fsl_ddr_info_t *pinfo,
unsigned int dbw_cap_adj[])
{
int i, j;
unsigned long long total_mem, current_mem_base, total_ctlr_mem;
unsigned long long rank_density, ctlr_density = 0;
current_mem_base = 0ull;
total_mem = 0;
/*
* This board has soldered DDR chips. DDRC1 has two rank.
* DDRC2 has only one rank.
* Assigning DDRC2 to lower address and DDRC1 to higher address.
*/
if (pinfo->memctl_opts[0].memctl_interleaving) {
rank_density = pinfo->dimm_params[0][0].rank_density >>
dbw_cap_adj[0];
ctlr_density = rank_density;
debug("rank density is 0x%llx, ctlr density is 0x%llx\n",
rank_density, ctlr_density);
for (i = CONFIG_SYS_NUM_DDR_CTLRS - 1; i >= 0; i--) {
switch (pinfo->memctl_opts[i].memctl_interleaving_mode) {
case FSL_DDR_CACHE_LINE_INTERLEAVING:
case FSL_DDR_PAGE_INTERLEAVING:
case FSL_DDR_BANK_INTERLEAVING:
case FSL_DDR_SUPERBANK_INTERLEAVING:
total_ctlr_mem = 2 * ctlr_density;
break;
default:
panic("Unknown interleaving mode");
}
pinfo->common_timing_params[i].base_address =
current_mem_base;
pinfo->common_timing_params[i].total_mem =
total_ctlr_mem;
total_mem = current_mem_base + total_ctlr_mem;
debug("ctrl %d base 0x%llx\n", i, current_mem_base);
debug("ctrl %d total 0x%llx\n", i, total_ctlr_mem);
}
} else {
/*
* Simple linear assignment if memory
* controllers are not interleaved.
*/
for (i = CONFIG_SYS_NUM_DDR_CTLRS - 1; i >= 0; i--) {
total_ctlr_mem = 0;
pinfo->common_timing_params[i].base_address =
current_mem_base;
for (j = 0; j < CONFIG_DIMM_SLOTS_PER_CTLR; j++) {
/* Compute DIMM base addresses. */
unsigned long long cap =
pinfo->dimm_params[i][j].capacity;
pinfo->dimm_params[i][j].base_address =
current_mem_base;
debug("ctrl %d dimm %d base 0x%llx\n",
i, j, current_mem_base);
current_mem_base += cap;
total_ctlr_mem += cap;
}
debug("ctrl %d total 0x%llx\n", i, total_ctlr_mem);
pinfo->common_timing_params[i].total_mem =
total_ctlr_mem;
total_mem += total_ctlr_mem;
}
}
debug("Total mem by %s is 0x%llx\n", __func__, total_mem);
return total_mem;
}
@@ -0,0 +1,452 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright 2012 Freescale Semiconductor, Inc.
* Author: Sandeep Kumar Singh <sandeep@freescale.com>
*/
/* This file is based on board/freescale/corenet_ds/eth_superhydra.c */
/*
* This file handles the board muxing between the Fman Ethernet MACs and
* the RGMII/SGMII/XGMII PHYs on a Freescale B4860 "Centaur". The SGMII
* PHYs are the two on-board 1Gb ports. There are no RGMII PHY on board.
* The 10Gb XGMII PHY is provided via the XAUI riser card. There is only
* one Fman device on B4860. The SERDES configuration is used to determine
* where the SGMII and XAUI cards exist, and also which Fman MACs are routed
* to which PHYs. So for a given Fman MAC, there is one and only PHY it
* connects to. MACs cannot be routed to PHYs dynamically. This configuration
* is done at boot time by reading SERDES protocol from RCW.
*/
#include <common.h>
#include <netdev.h>
#include <asm/fsl_serdes.h>
#include <fm_eth.h>
#include <fsl_mdio.h>
#include <malloc.h>
#include <fdt_support.h>
#include <fsl_dtsec.h>
#include "../common/ngpixis.h"
#include "../common/fman.h"
#include "../common/qixis.h"
#include "b4860qds_qixis.h"
#define EMI_NONE 0xFFFFFFFF
#ifdef CONFIG_FMAN_ENET
/*
* Mapping of all 16 SERDES lanes to board slots. A value n(>0) will mean that
* lane at index is mapped to slot number n. A value of '0' will mean
* that the mapping must be determined dynamically, or that the lane maps to
* something other than a board slot
*/
static u8 lane_to_slot[] = {
0, 0, 0, 0,
0, 0, 0, 0,
1, 1, 1, 1,
0, 0, 0, 0
};
/*
* This function initializes the lane_to_slot[] array. It reads RCW to check
* if Serdes2{E,F,G,H} is configured as slot 2 or as SFP and initializes
* lane_to_slot[] accordingly
*/
static void initialize_lane_to_slot(void)
{
unsigned int serdes2_prtcl;
ccsr_gur_t *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR);
serdes2_prtcl = in_be32(&gur->rcwsr[4]) &
FSL_CORENET2_RCWSR4_SRDS2_PRTCL;
serdes2_prtcl >>= FSL_CORENET2_RCWSR4_SRDS2_PRTCL_SHIFT;
debug("Initializing lane to slot: Serdes2 protocol: %x\n",
serdes2_prtcl);
switch (serdes2_prtcl) {
case 0x17:
case 0x18:
/*
* Configuration:
* SERDES: 2
* Lanes: A,B,C,D: SGMII
* Lanes: E,F: Aur
* Lanes: G,H: SRIO
*/
case 0x91:
/*
* Configuration:
* SERDES: 2
* Lanes: A,B: SGMII
* Lanes: C,D: SRIO2
* Lanes: E,F,G,H: XAUI2
*/
case 0x93:
/*
* Configuration:
* SERDES: 2
* Lanes: A,B,C,D: SGMII
* Lanes: E,F,G,H: XAUI2
*/
case 0x98:
/*
* Configuration:
* SERDES: 2
* Lanes: A,B,C,D: XAUI2
* Lanes: E,F,G,H: XAUI2
*/
case 0x9a:
/*
* Configuration:
* SERDES: 2
* Lanes: A,B: PCI
* Lanes: C,D: SGMII
* Lanes: E,F,G,H: XAUI2
*/
case 0x9e:
/*
* Configuration:
* SERDES: 2
* Lanes: A,B,C,D: PCI
* Lanes: E,F,G,H: XAUI2
*/
case 0xb1:
case 0xb2:
case 0x8c:
case 0x8d:
/*
* Configuration:
* SERDES: 2
* Lanes: A,B,C,D: PCI
* Lanes: E,F: SGMII 3&4
* Lanes: G,H: XFI
*/
case 0xc2:
/*
* Configuration:
* SERDES: 2
* Lanes: A,B: SGMII
* Lanes: C,D: SRIO2
* Lanes: E,F,G,H: XAUI2
*/
lane_to_slot[12] = 2;
lane_to_slot[13] = lane_to_slot[12];
lane_to_slot[14] = lane_to_slot[12];
lane_to_slot[15] = lane_to_slot[12];
break;
default:
printf("Fman: Unsupported SerDes2 Protocol 0x%02x\n",
serdes2_prtcl);
break;
}
return;
}
#endif /* #ifdef CONFIG_FMAN_ENET */
int board_eth_init(bd_t *bis)
{
#ifdef CONFIG_FMAN_ENET
struct memac_mdio_info memac_mdio_info;
struct memac_mdio_info tg_memac_mdio_info;
unsigned int i;
unsigned int serdes1_prtcl, serdes2_prtcl;
int qsgmii;
struct mii_dev *bus;
ccsr_gur_t *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR);
serdes1_prtcl = in_be32(&gur->rcwsr[4]) &
FSL_CORENET2_RCWSR4_SRDS1_PRTCL;
if (!serdes1_prtcl) {
printf("SERDES1 is not enabled\n");
return 0;
}
serdes1_prtcl >>= FSL_CORENET2_RCWSR4_SRDS1_PRTCL_SHIFT;
debug("Using SERDES1 Protocol: 0x%x:\n", serdes1_prtcl);
serdes2_prtcl = in_be32(&gur->rcwsr[4]) &
FSL_CORENET2_RCWSR4_SRDS2_PRTCL;
if (!serdes2_prtcl) {
printf("SERDES2 is not enabled\n");
return 0;
}
serdes2_prtcl >>= FSL_CORENET2_RCWSR4_SRDS2_PRTCL_SHIFT;
debug("Using SERDES2 Protocol: 0x%x:\n", serdes2_prtcl);
printf("Initializing Fman\n");
initialize_lane_to_slot();
memac_mdio_info.regs =
(struct memac_mdio_controller *)CONFIG_SYS_FM1_DTSEC_MDIO_ADDR;
memac_mdio_info.name = DEFAULT_FM_MDIO_NAME;
/* Register the real 1G MDIO bus */
fm_memac_mdio_init(bis, &memac_mdio_info);
tg_memac_mdio_info.regs =
(struct memac_mdio_controller *)CONFIG_SYS_FM1_TGEC_MDIO_ADDR;
tg_memac_mdio_info.name = DEFAULT_FM_TGEC_MDIO_NAME;
/* Register the real 10G MDIO bus */
fm_memac_mdio_init(bis, &tg_memac_mdio_info);
/*
* Program the two on board DTSEC PHY addresses assuming that they are
* all SGMII. RGMII is not supported on this board. Setting SGMII 5 and
* 6 to on board SGMII phys
*/
fm_info_set_phy_address(FM1_DTSEC5, CONFIG_SYS_FM1_ONBOARD_PHY1_ADDR);
fm_info_set_phy_address(FM1_DTSEC6, CONFIG_SYS_FM1_ONBOARD_PHY2_ADDR);
switch (serdes1_prtcl) {
case 0x29:
case 0x2a:
/* Serdes 1: A-B SGMII, Configuring DTSEC 5 and 6 */
debug("Set phy addresses for FM1_DTSEC5:%x, FM1_DTSEC6:%x\n",
CONFIG_SYS_FM1_ONBOARD_PHY1_ADDR,
CONFIG_SYS_FM1_ONBOARD_PHY2_ADDR);
fm_info_set_phy_address(FM1_DTSEC5,
CONFIG_SYS_FM1_ONBOARD_PHY1_ADDR);
fm_info_set_phy_address(FM1_DTSEC6,
CONFIG_SYS_FM1_ONBOARD_PHY2_ADDR);
break;
#ifdef CONFIG_ARCH_B4420
case 0x17:
case 0x18:
/* Serdes 1: A-D SGMII, Configuring on board dual SGMII Phy */
debug("Set phy addresses for FM1_DTSEC3:%x, FM1_DTSEC4:%x\n",
CONFIG_SYS_FM1_ONBOARD_PHY1_ADDR,
CONFIG_SYS_FM1_ONBOARD_PHY2_ADDR);
/* Fixing Serdes clock by programming FPGA register */
QIXIS_WRITE(brdcfg[4], QIXIS_SRDS1CLK_125);
fm_info_set_phy_address(FM1_DTSEC3,
CONFIG_SYS_FM1_ONBOARD_PHY1_ADDR);
fm_info_set_phy_address(FM1_DTSEC4,
CONFIG_SYS_FM1_ONBOARD_PHY2_ADDR);
break;
#endif
default:
printf("Fman: Unsupported SerDes1 Protocol 0x%02x\n",
serdes1_prtcl);
break;
}
switch (serdes2_prtcl) {
case 0x17:
case 0x18:
debug("Set phy address on SGMII Riser for FM1_DTSEC1:%x\n",
CONFIG_SYS_FM1_DTSEC1_RISER_PHY_ADDR);
fm_info_set_phy_address(FM1_DTSEC1,
CONFIG_SYS_FM1_DTSEC1_RISER_PHY_ADDR);
fm_info_set_phy_address(FM1_DTSEC2,
CONFIG_SYS_FM1_DTSEC2_RISER_PHY_ADDR);
fm_info_set_phy_address(FM1_DTSEC3,
CONFIG_SYS_FM1_DTSEC3_RISER_PHY_ADDR);
fm_info_set_phy_address(FM1_DTSEC4,
CONFIG_SYS_FM1_DTSEC4_RISER_PHY_ADDR);
break;
case 0x48:
case 0x49:
debug("Set phy address on SGMII Riser for FM1_DTSEC1:%x\n",
CONFIG_SYS_FM1_DTSEC1_RISER_PHY_ADDR);
fm_info_set_phy_address(FM1_DTSEC1,
CONFIG_SYS_FM1_DTSEC1_RISER_PHY_ADDR);
fm_info_set_phy_address(FM1_DTSEC2,
CONFIG_SYS_FM1_DTSEC2_RISER_PHY_ADDR);
fm_info_set_phy_address(FM1_DTSEC3,
CONFIG_SYS_FM1_DTSEC3_RISER_PHY_ADDR);
break;
case 0xb1:
case 0xb2:
case 0x8c:
case 0x8d:
debug("Set phy addresses on SGMII Riser for FM1_DTSEC1:%x\n",
CONFIG_SYS_FM1_DTSEC1_RISER_PHY_ADDR);
fm_info_set_phy_address(FM1_DTSEC3,
CONFIG_SYS_FM1_DTSEC1_RISER_PHY_ADDR);
fm_info_set_phy_address(FM1_DTSEC4,
CONFIG_SYS_FM1_DTSEC2_RISER_PHY_ADDR);
/*
* XFI does not need a PHY to work, but to make U-Boot
* happy, assign a fake PHY address for a XFI port.
*/
fm_info_set_phy_address(FM1_10GEC1, 0);
fm_info_set_phy_address(FM1_10GEC2, 1);
break;
case 0x98:
/* XAUI in Slot1 and Slot2 */
debug("Set phy address of AMC2PEX-2S for FM1_10GEC1:%x\n",
CONFIG_SYS_FM1_10GEC1_PHY_ADDR);
fm_info_set_phy_address(FM1_10GEC1,
CONFIG_SYS_FM1_10GEC1_PHY_ADDR);
debug("Set phy address of AMC2PEX-2S for FM1_10GEC2:%x\n",
CONFIG_SYS_FM1_10GEC2_PHY_ADDR);
fm_info_set_phy_address(FM1_10GEC2,
CONFIG_SYS_FM1_10GEC2_PHY_ADDR);
break;
case 0x9E:
/* XAUI in Slot2 */
debug("Sett phy address of AMC2PEX-2S for FM1_10GEC2:%x\n",
CONFIG_SYS_FM1_10GEC2_PHY_ADDR);
fm_info_set_phy_address(FM1_10GEC2,
CONFIG_SYS_FM1_10GEC2_PHY_ADDR);
break;
default:
printf("Fman: Unsupported SerDes2 Protocol 0x%02x\n",
serdes2_prtcl);
break;
}
/*set PHY address for QSGMII Riser Card on slot2*/
bus = miiphy_get_dev_by_name(DEFAULT_FM_MDIO_NAME);
qsgmii = is_qsgmii_riser_card(bus, PHY_BASE_ADDR, PORT_NUM, REGNUM);
if (qsgmii) {
switch (serdes2_prtcl) {
case 0xb2:
case 0x8d:
fm_info_set_phy_address(FM1_DTSEC3, PHY_BASE_ADDR);
fm_info_set_phy_address(FM1_DTSEC4, PHY_BASE_ADDR + 1);
break;
default:
break;
}
}
for (i = FM1_DTSEC1; i < FM1_DTSEC1 + CONFIG_SYS_NUM_FM1_DTSEC; i++) {
int idx = i - FM1_DTSEC1;
switch (fm_info_get_enet_if(i)) {
case PHY_INTERFACE_MODE_SGMII:
fm_info_set_mdio(i,
miiphy_get_dev_by_name(DEFAULT_FM_MDIO_NAME));
break;
case PHY_INTERFACE_MODE_NONE:
fm_info_set_phy_address(i, 0);
break;
default:
printf("Fman1: DTSEC%u set to unknown interface %i\n",
idx + 1, fm_info_get_enet_if(i));
fm_info_set_phy_address(i, 0);
break;
}
}
for (i = FM1_10GEC1; i < FM1_10GEC1 + CONFIG_SYS_NUM_FM1_10GEC; i++) {
int idx = i - FM1_10GEC1;
switch (fm_info_get_enet_if(i)) {
case PHY_INTERFACE_MODE_XGMII:
fm_info_set_mdio(i,
miiphy_get_dev_by_name
(DEFAULT_FM_TGEC_MDIO_NAME));
break;
case PHY_INTERFACE_MODE_NONE:
fm_info_set_phy_address(i, 0);
break;
default:
printf("Fman1: TGEC%u set to unknown interface %i\n",
idx + 1, fm_info_get_enet_if(i));
fm_info_set_phy_address(i, 0);
break;
}
}
cpu_eth_init(bis);
#endif
return pci_eth_init(bis);
}
void board_ft_fman_fixup_port(void *fdt, char *compat, phys_addr_t addr,
enum fm_port port, int offset)
{
int phy;
char alias[32];
struct fixed_link f_link;
ccsr_gur_t *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR);
u32 prtcl2 = in_be32(&gur->rcwsr[4]) & FSL_CORENET2_RCWSR4_SRDS2_PRTCL;
prtcl2 >>= FSL_CORENET2_RCWSR4_SRDS2_PRTCL_SHIFT;
if (fm_info_get_enet_if(port) == PHY_INTERFACE_MODE_SGMII) {
phy = fm_info_get_phy_address(port);
sprintf(alias, "phy_sgmii_%x", phy);
fdt_set_phy_handle(fdt, compat, addr, alias);
fdt_status_okay_by_alias(fdt, alias);
} else if (fm_info_get_enet_if(port) == PHY_INTERFACE_MODE_XGMII) {
/* check if it's XFI interface for 10g */
switch (prtcl2) {
case 0x80:
case 0x81:
case 0x82:
case 0x83:
case 0x84:
case 0x85:
case 0x86:
case 0x87:
case 0x88:
case 0x89:
case 0x8a:
case 0x8b:
case 0x8c:
case 0x8d:
case 0x8e:
case 0xb1:
case 0xb2:
f_link.phy_id = port;
f_link.duplex = 1;
f_link.link_speed = 10000;
f_link.pause = 0;
f_link.asym_pause = 0;
fdt_delprop(fdt, offset, "phy-handle");
fdt_setprop(fdt, offset, "fixed-link", &f_link,
sizeof(f_link));
break;
case 0x98: /* XAUI interface */
strcpy(alias, "phy_xaui_slot1");
fdt_status_okay_by_alias(fdt, alias);
strcpy(alias, "phy_xaui_slot2");
fdt_status_okay_by_alias(fdt, alias);
break;
case 0x9e: /* XAUI interface */
case 0x9a:
case 0x93:
case 0x91:
strcpy(alias, "phy_xaui_slot1");
fdt_status_okay_by_alias(fdt, alias);
break;
case 0x97: /* XAUI interface */
case 0xc3:
strcpy(alias, "phy_xaui_slot2");
fdt_status_okay_by_alias(fdt, alias);
break;
default:
break;
}
}
}
/*
* Set status to disabled for unused ethernet node
*/
void fdt_fixup_board_enet(void *fdt)
{
int i;
char alias[32];
for (i = FM1_DTSEC1; i <= FM1_10GEC2; i++) {
switch (fm_info_get_enet_if(i)) {
case PHY_INTERFACE_MODE_NONE:
sprintf(alias, "ethernet%u", i);
fdt_status_disabled_by_alias(fdt, alias);
break;
default:
break;
}
}
}
@@ -0,0 +1,28 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright 2011-2012 Freescale Semiconductor, Inc.
*/
#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_IFC),
#ifdef CONFIG_SYS_BMAN_MEM_PHYS
SET_LAW(CONFIG_SYS_BMAN_MEM_PHYS, LAW_SIZE_32M, LAW_TRGT_IF_BMAN),
#endif
#ifdef CONFIG_SYS_QMAN_MEM_PHYS
SET_LAW(CONFIG_SYS_QMAN_MEM_PHYS, LAW_SIZE_32M, LAW_TRGT_IF_QMAN),
#endif
SET_LAW(QIXIS_BASE_PHYS, LAW_SIZE_4K, LAW_TRGT_IF_IFC),
#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_64K, LAW_TRGT_IF_IFC),
#endif
};
int num_law_entries = ARRAY_SIZE(law_table);
@@ -0,0 +1,23 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright 2011-2012 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>
void pci_init_board(void)
{
fsl_pcie_init_board(0);
}
void pci_of_setup(void *blob, bd_t *bd)
{
FT_FSL_PCI_SETUP;
}
@@ -0,0 +1,117 @@
// SPDX-License-Identifier: GPL-2.0+
/* Copyright 2013 Freescale Semiconductor, Inc.
*/
#include <common.h>
#include <console.h>
#include <env.h>
#include <env_internal.h>
#include <asm/spl.h>
#include <malloc.h>
#include <ns16550.h>
#include <nand.h>
#include <i2c.h>
#include "../common/qixis.h"
#include "b4860qds_qixis.h"
DECLARE_GLOBAL_DATA_PTR;
phys_size_t get_effective_memsize(void)
{
return CONFIG_SYS_L3_SIZE;
}
unsigned long get_board_sys_clk(void)
{
u8 sysclk_conf = QIXIS_READ(brdcfg[1]);
switch ((sysclk_conf & 0x0C) >> 2) {
case QIXIS_CLK_100:
return 100000000;
case QIXIS_CLK_125:
return 125000000;
case QIXIS_CLK_133:
return 133333333;
}
return 66666666;
}
unsigned long get_board_ddr_clk(void)
{
u8 ddrclk_conf = QIXIS_READ(brdcfg[1]);
switch (ddrclk_conf & 0x03) {
case QIXIS_CLK_100:
return 100000000;
case QIXIS_CLK_125:
return 125000000;
case QIXIS_CLK_133:
return 133333333;
}
return 66666666;
}
void board_init_f(ulong bootflag)
{
u32 plat_ratio, sys_clk, uart_clk;
ccsr_gur_t *gur = (void *)CONFIG_SYS_MPC85xx_GUTS_ADDR;
/* Memcpy existing GD at CONFIG_SPL_GD_ADDR */
memcpy((void *)CONFIG_SPL_GD_ADDR, (void *)gd, sizeof(gd_t));
/* Update GD pointer */
gd = (gd_t *)(CONFIG_SPL_GD_ADDR);
/* compiler optimization barrier needed for GCC >= 3.4 */
__asm__ __volatile__("" : : : "memory");
console_init_f();
/* initialize selected port with appropriate baud rate */
sys_clk = get_board_sys_clk();
plat_ratio = (in_be32(&gur->rcwsr[0]) >> 25) & 0x1f;
uart_clk = sys_clk * plat_ratio / 2;
NS16550_init((NS16550_t)CONFIG_SYS_NS16550_COM1,
uart_clk / 16 / CONFIG_BAUDRATE);
relocate_code(CONFIG_SPL_RELOC_STACK, (gd_t *)CONFIG_SPL_GD_ADDR, 0x0);
}
void board_init_r(gd_t *gd, ulong dest_addr)
{
bd_t *bd;
bd = (bd_t *)(gd + sizeof(gd_t));
memset(bd, 0, sizeof(bd_t));
gd->bd = bd;
bd->bi_memstart = CONFIG_SYS_INIT_L3_ADDR;
bd->bi_memsize = CONFIG_SYS_L3_SIZE;
arch_cpu_init();
get_clocks();
mem_malloc_init(CONFIG_SPL_RELOC_MALLOC_ADDR,
CONFIG_SPL_RELOC_MALLOC_SIZE);
gd->flags |= GD_FLG_FULL_MALLOC_INIT;
#ifndef CONFIG_SPL_NAND_BOOT
env_init();
env_relocate();
#else
/* relocate environment function pointers etc. */
nand_spl_load_image(CONFIG_ENV_OFFSET, CONFIG_ENV_SIZE,
(uchar *)SPL_ENV_ADDR);
gd->env_addr = (ulong)(SPL_ENV_ADDR);
gd->env_valid = ENV_VALID;
#endif
i2c_init_all();
puts("\n\n");
dram_init();
#ifdef CONFIG_SPL_NAND_BOOT
nand_boot();
#endif
}
@@ -0,0 +1,154 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright 2011-2012 Freescale Semiconductor, Inc.
*/
#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_SX|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_SX|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_SX|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_SX|MAS3_SW|MAS3_SR, 0,
0, 0, BOOKE_PAGESZ_4K, 0),
/* TLB 1 */
/* *I*** - Covers boot page */
#if defined(CONFIG_SYS_RAMBOOT) && defined(CONFIG_SYS_INIT_L3_ADDR)
/*
* *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),
#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_SX|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),
#ifndef CONFIG_SPL_BUILD
/* *I*G* - PCI */
SET_TLB_ENTRY(1, CONFIG_SYS_PCIE1_MEM_VIRT, CONFIG_SYS_PCIE1_MEM_PHYS,
MAS3_SX|MAS3_SW|MAS3_SR, MAS2_I|MAS2_G,
0, 3, BOOKE_PAGESZ_256M, 1),
SET_TLB_ENTRY(1, CONFIG_SYS_PCIE1_MEM_VIRT + 0x10000000,
CONFIG_SYS_PCIE1_MEM_PHYS + 0x10000000,
MAS3_SX|MAS3_SW|MAS3_SR, MAS2_I|MAS2_G,
0, 4, BOOKE_PAGESZ_256M, 1),
/* *I*G* - PCI I/O */
SET_TLB_ENTRY(1, CONFIG_SYS_PCIE1_IO_VIRT, CONFIG_SYS_PCIE1_IO_PHYS,
MAS3_SX|MAS3_SW|MAS3_SR, MAS2_I|MAS2_G,
0, 5, BOOKE_PAGESZ_64K, 1),
/* Bman/Qman */
#ifdef CONFIG_SYS_BMAN_MEM_PHYS
SET_TLB_ENTRY(1, CONFIG_SYS_BMAN_MEM_BASE, CONFIG_SYS_BMAN_MEM_PHYS,
MAS3_SX|MAS3_SW|MAS3_SR, 0,
0, 6, BOOKE_PAGESZ_16M, 1),
SET_TLB_ENTRY(1, CONFIG_SYS_BMAN_MEM_BASE + 0x01000000,
CONFIG_SYS_BMAN_MEM_PHYS + 0x01000000,
MAS3_SX|MAS3_SW|MAS3_SR, MAS2_I|MAS2_G,
0, 7, BOOKE_PAGESZ_16M, 1),
#endif
#ifdef CONFIG_SYS_QMAN_MEM_PHYS
SET_TLB_ENTRY(1, CONFIG_SYS_QMAN_MEM_BASE, CONFIG_SYS_QMAN_MEM_PHYS,
MAS3_SX|MAS3_SW|MAS3_SR, 0,
0, 8, BOOKE_PAGESZ_16M, 1),
SET_TLB_ENTRY(1, CONFIG_SYS_QMAN_MEM_BASE + 0x01000000,
CONFIG_SYS_QMAN_MEM_PHYS + 0x01000000,
MAS3_SX|MAS3_SW|MAS3_SR, MAS2_I|MAS2_G,
0, 9, BOOKE_PAGESZ_16M, 1),
#endif
#endif
#ifdef CONFIG_SYS_DCSRBAR_PHYS
SET_TLB_ENTRY(1, CONFIG_SYS_DCSRBAR, CONFIG_SYS_DCSRBAR_PHYS,
MAS3_SX|MAS3_SW|MAS3_SR, MAS2_I|MAS2_G,
0, 10, BOOKE_PAGESZ_32M, 1),
#endif
#ifdef CONFIG_SYS_NAND_BASE
/*
* *I*G - 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, 11, BOOKE_PAGESZ_64K, 1),
#endif
SET_TLB_ENTRY(1, QIXIS_BASE, QIXIS_BASE_PHYS,
MAS3_SX|MAS3_SW|MAS3_SR, MAS2_I|MAS2_G,
0, 12, BOOKE_PAGESZ_4K, 1),
/*
* *I*G - SRIO
* entry 14 and 15 has been used hard coded, they will be disabled
* in cpu_init_f, so we use entry 16 for SRIO2.
*/
#ifndef CONFIG_SPL_BUILD
#ifdef CONFIG_SYS_SRIO1_MEM_PHYS
/* *I*G* - SRIO1 */
SET_TLB_ENTRY(1, CONFIG_SYS_SRIO1_MEM_VIRT, CONFIG_SYS_SRIO1_MEM_PHYS,
MAS3_SW|MAS3_SR, MAS2_I|MAS2_G,
0, 13, BOOKE_PAGESZ_256M, 1),
#endif
#ifdef CONFIG_SYS_SRIO2_MEM_PHYS
/* *I*G* - SRIO2 */
SET_TLB_ENTRY(1, CONFIG_SYS_SRIO2_MEM_VIRT, CONFIG_SYS_SRIO2_MEM_PHYS,
MAS3_SW|MAS3_SR, MAS2_I|MAS2_G,
0, 16, BOOKE_PAGESZ_256M, 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
#endif
#if defined(CONFIG_RAMBOOT_PBL) && !defined(CONFIG_SPL_BUILD)
SET_TLB_ENTRY(1, CONFIG_SYS_DDR_SDRAM_BASE, CONFIG_SYS_DDR_SDRAM_BASE,
MAS3_SX|MAS3_SW|MAS3_SR, MAS2_M,
0, 17, BOOKE_PAGESZ_2G, 1)
#endif
};
int num_tlb_entries = ARRAY_SIZE(tlb_table);
@@ -0,0 +1,12 @@
if TARGET_BSC9131RDB
config SYS_BOARD
default "bsc9131rdb"
config SYS_VENDOR
default "freescale"
config SYS_CONFIG_NAME
default "BSC9131RDB"
endif
@@ -0,0 +1,9 @@
BSC9131RDB BOARD
M: Poonam Aggrwal <poonam.aggrwal@nxp.com>
S: Maintained
F: board/freescale/bsc9131rdb/
F: include/configs/BSC9131RDB.h
F: configs/BSC9131RDB_NAND_defconfig
F: configs/BSC9131RDB_NAND_SYSCLK100_defconfig
F: configs/BSC9131RDB_SPIFLASH_defconfig
F: configs/BSC9131RDB_SPIFLASH_SYSCLK100_defconfig
@@ -0,0 +1,21 @@
# SPDX-License-Identifier: GPL-2.0+
#
# Copyright 2011-2012 Freescale Semiconductor, Inc.
MINIMAL=
ifdef CONFIG_SPL_BUILD
ifdef CONFIG_SPL_INIT_MINIMAL
MINIMAL=y
endif
endif
ifdef MINIMAL
obj-y += spl_minimal.o
else
obj-y += bsc9131rdb.o
obj-y += ddr.o
endif
obj-y += law.o
obj-y += tlb.o
@@ -0,0 +1,151 @@
Overview
--------
- BSC9131 is integrated device that targets Femto base station market.
It combines Power Architecture e500v2 and DSP StarCore SC3850 core
technologies with MAPLE-B2F baseband acceleration processing elements.
- It's MAPLE disabled personality is called 9231.
The BSC9131 SoC includes the following function and features:
. Power Architecture subsystem including a e500 processor with 256-Kbyte shared
L2 cache
. StarCore SC3850 DSP subsystem with a 512-Kbyte private L2 cache
. The Multi Accelerator Platform Engine for Femto BaseStation Baseband
Processing (MAPLE-B2F)
. A multi-standard baseband algorithm accelerator for Channel Decoding/Encoding,
Fourier Transforms, UMTS chip rate processing, LTE UP/DL Channel processing,
and CRC algorithms
. Consists of accelerators for Convolution, Filtering, Turbo Encoding,
Turbo Decoding, Viterbi decoding, Chiprate processing, and Matrix Inversion
operations
. DDR3/3L memory interface with 32-bit data width without ECC and 16-bit with
ECC, up to 400-MHz clock/800 MHz data rate
. Dedicated security engine featuring trusted boot
. DMA controller
. OCNDMA with four bidirectional channels
. Interfaces
. Two triple-speed Gigabit Ethernet controllers featuring network acceleration
including IEEE 1588. v2 hardware support and virtualization (eTSEC)
. eTSEC 1 supports RGMII/RMII
. eTSEC 2 supports RGMII
. High-speed USB 2.0 host and device controller with ULPI interface
. Enhanced secure digital (SD/MMC) host controller (eSDHC)
. Antenna interface controller (AIC), supporting three industry standard
JESD207/three custom ADI RF interfaces (two dual port and one single port)
and three MAXIM's MaxPHY serial interfaces
. ADI lanes support both full duplex FDD support and half duplex TDD support
. Universal Subscriber Identity Module (USIM) interface that facilitates
communication to SIM cards or Eurochip pre-paid phone cards
. TDM with one TDM port
. Two DUART, four eSPI, and two I2C controllers
. Integrated Flash memory controller (IFC)
. TDM with 256 channels
. GPIO
. Sixteen 32-bit timers
The e500 core subsystem within the Power Architecture consists of the following:
. 32-Kbyte L1 instruction cache
. 32-Kbyte L1 data cache
. 256-Kbyte L2 cache/L2 memory/L2 stash
. programmable interrupt controller (PIC)
. Debug support
. Timers
The SC3850 core subsystem consists of the following:
. 32 Kbyte 8-way level 1 instruction cache (L1 ICache)
. 32 Kbyte 8-way level 1 data cache (L1 DCache)
. 512 Kbyte 8-way level 2 unified instruction/data cache (M2 memory)
. Memory management unit (MMU)
. Enhanced programmable interrupt controller (EPIC)
. Debug and profiling unit (DPU)
. Two 32-bit timers
BSC9131RDB board Overview
-------------------------
1Gbyte DDR3 (on board DDR)
128Mbyte 2K page size NAND Flash
256 Kbit M24256 I2C EEPROM
128 Mbit SPI Flash memory
USB-ULPI
eTSEC1: Connected to RGMII PHY
eTSEC2: Connected to RGMII PHY
DUART interface: supports one UARTs up to 115200 bps for console display
USIM connector
Frequency Combinations Supported
--------------------------------
Core MHz/CCB MHz/DDR(MT/s)
1. 1000/500/800
2. 800/400/667
Boot Methods Supported
-----------------------
1. NAND Flash
2. SPI Flash
Default Boot Method
--------------------
NAND boot
Building U-Boot
--------------
To build the U-Boot for BSC9131RDB:
1. NAND Flash with sysclk 66MHz(J16 on RDB closed, default)
make BSC9131RDB_NAND
2. NAND Flash with sysclk 100MHz(J16 on RDB open)
make BSC9131RDB_NAND_SYSCLK100
3. SPI Flash with sysclk 66MHz(J16 on RDB closed, default)
make BSC9131RDB_SPIFLASH
4. SPI Flash with sysclk 100MHz(J16 on RDB open)
make BSC9131RDB_SPIFLASH_SYSCLK100
Memory map
-----------
0x0000_0000 0x7FFF_FFFF DDR 1G cacheable
0xA0000000 0xBFFFFFFF Shared DSP core L2/M2 space 512M
0xC100_0000 0xC13F_FFFF MAPLE-2F 4M
0xC1F0_0000 0xC1F3_FFFF PA SRAM Region 0 256K
0xC1F8_0000 0xC1F9_FFFF PA SRAM Region 1 128K
0xFED0_0000 0xFED0_3FFF SEC Secured RAM 16K
0xFEE0_0000 0xFEE0_0FFF DSP Boot ROM 4K
0xFF60_0000 0xFF6F_FFFF DSP CCSR 1M
0xFF70_0000 0xFF7F_FFFF PA CCSR 1M
0xFF80_0000 0xFFFF_FFFF Boot Page & NAND Buffer 8M
DDR Memory map
---------------
0x0000_0000 0x36FF_FFFF Memory passed onto Linux
0x3700_0000 0x37FF_FFFF PowerPC-DSP shared control area
0x3800_0000 0x4FFF_FFFF DSP Private area
Out of 880M, passed onto Linux, 1hugetlb page of 256M is reserved for
data communcation between PowerPC and DSP core.
Rest is PowerPC private area.
Flashing Images
---------------
To place a new U-Boot image in the NAND flash and then boot
with that new image temporarily, use this:
tftp 1000000 u-boot-nand.bin
nand erase 0 100000
nand write 1000000 0 100000
reset
Using the Device Tree Source File
---------------------------------
To create the DTB (Device Tree Binary) image file,
use a command similar to this:
dtc -b 0 -f -I dts -O dtb bsc9131rdb.dts > bsc9131rdb.dtb
Likely, that .dts file will come from here;
linux-2.6/arch/powerpc/boot/dts/bsc9131rdb.dts
Booting Linux
-------------
Place a linux uImage in the TFTP disk area.
tftp 1000000 uImage
tftp 2000000 rootfs.ext2.gz.uboot
tftp c00000 bsc9131rdb.dtb
bootm 1000000 2000000 c00000
@@ -0,0 +1,80 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright 2011-2012 Freescale Semiconductor, Inc.
*/
#include <common.h>
#include <asm/processor.h>
#include <asm/mmu.h>
#include <asm/cache.h>
#include <asm/immap_85xx.h>
#include <asm/io.h>
#include <env.h>
#include <miiphy.h>
#include <linux/libfdt.h>
#include <fdt_support.h>
#include <fsl_mdio.h>
#include <tsec.h>
#include <jffs2/load_kernel.h>
#include <mtd_node.h>
#include <flash.h>
#include <netdev.h>
DECLARE_GLOBAL_DATA_PTR;
int board_early_init_f(void)
{
ccsr_gur_t *gur = (void *)CONFIG_SYS_MPC85xx_GUTS_ADDR;
clrbits_be32(&gur->pmuxcr2, MPC85xx_PMUXCR2_UART_CTS_B0_GPIO42);
setbits_be32(&gur->pmuxcr2, MPC85xx_PMUXCR2_UART_CTS_B0_DSP_TMS);
clrbits_be32(&gur->pmuxcr2, MPC85xx_PMUXCR2_UART_RTS_B0_GPIO43);
setbits_be32(&gur->pmuxcr2, MPC85xx_PMUXCR2_UART_RTS_B0_DSP_TCK |
MPC85xx_PMUXCR2_UART_CTS_B1_SIM_PD);
setbits_be32(&gur->halt_req_mask, HALTED_TO_HALT_REQ_MASK_0);
clrsetbits_be32(&gur->pmuxcr, MPC85xx_PMUXCR_IFC_AD_GPIO_MASK |
MPC85xx_PMUXCR_IFC_AD17_GPO_MASK,
MPC85xx_PMUXCR_IFC_AD_GPIO |
MPC85xx_PMUXCR_IFC_AD17_GPO | MPC85xx_PMUXCR_SDHC_USIM);
return 0;
}
int checkboard(void)
{
struct cpu_type *cpu;
cpu = gd->arch.cpu;
printf("Board: %sRDB\n", cpu->name);
return 0;
}
#if defined(CONFIG_OF_BOARD_SETUP)
#ifdef CONFIG_FDT_FIXUP_PARTITIONS
static const struct node_info nodes[] = {
{ "fsl,ifc-nand", MTD_DEV_TYPE_NAND, },
};
#endif
int ft_board_setup(void *blob, bd_t *bd)
{
phys_addr_t base;
phys_size_t size;
ft_cpu_setup(blob, bd);
base = env_get_bootm_low();
size = env_get_bootm_size();
fdt_fixup_memory(blob, (u64)base, (u64)size);
#ifdef CONFIG_FDT_FIXUP_PARTITIONS
fdt_fixup_mtdparts(blob, nodes, ARRAY_SIZE(nodes));
#endif
fsl_fdt_fixup_dr_usb(blob, bd);
return 0;
}
#endif
@@ -0,0 +1,169 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright 2011-2012 Freescale Semiconductor, Inc.
*/
#include <common.h>
#include <vsprintf.h>
#include <asm/mmu.h>
#include <asm/immap_85xx.h>
#include <asm/processor.h>
#include <fsl_ddr_sdram.h>
#include <fsl_ddr_dimm_params.h>
#include <asm/io.h>
#include <asm/fsl_law.h>
#ifndef CONFIG_SYS_DDR_RAW_TIMING
#define CONFIG_SYS_DRAM_SIZE 1024
fsl_ddr_cfg_regs_t ddr_cfg_regs_800 = {
.cs[0].bnds = CONFIG_SYS_DDR_CS0_BNDS,
.cs[0].config = CONFIG_SYS_DDR_CS0_CONFIG,
.cs[0].config_2 = CONFIG_SYS_DDR_CS0_CONFIG_2,
.timing_cfg_3 = CONFIG_SYS_DDR_TIMING_3_800,
.timing_cfg_0 = CONFIG_SYS_DDR_TIMING_0_800,
.timing_cfg_1 = CONFIG_SYS_DDR_TIMING_1_800,
.timing_cfg_2 = CONFIG_SYS_DDR_TIMING_2_800,
.ddr_sdram_cfg = CONFIG_SYS_DDR_CONTROL,
.ddr_sdram_cfg_2 = CONFIG_SYS_DDR_CONTROL_2,
.ddr_sdram_mode = CONFIG_SYS_DDR_MODE_1_800,
.ddr_sdram_mode_2 = CONFIG_SYS_DDR_MODE_2_800,
.ddr_sdram_md_cntl = CONFIG_SYS_DDR_MODE_CONTROL,
.ddr_sdram_interval = CONFIG_SYS_DDR_INTERVAL_800,
.ddr_data_init = CONFIG_MEM_INIT_VALUE,
.ddr_sdram_clk_cntl = CONFIG_SYS_DDR_CLK_CTRL_800,
.ddr_init_addr = CONFIG_SYS_DDR_INIT_ADDR,
.ddr_init_ext_addr = CONFIG_SYS_DDR_INIT_EXT_ADDR,
.timing_cfg_4 = CONFIG_SYS_DDR_TIMING_4,
.timing_cfg_5 = CONFIG_SYS_DDR_TIMING_5,
.ddr_zq_cntl = CONFIG_SYS_DDR_ZQ_CONTROL,
.ddr_wrlvl_cntl = CONFIG_SYS_DDR_WRLVL_CONTROL_800,
.ddr_sr_cntr = CONFIG_SYS_DDR_SR_CNTR,
.ddr_sdram_rcw_1 = CONFIG_SYS_DDR_RCW_1,
.ddr_sdram_rcw_2 = CONFIG_SYS_DDR_RCW_2
};
fixed_ddr_parm_t fixed_ddr_parm_0[] = {
{750, 850, &ddr_cfg_regs_800},
{0, 0, NULL}
};
unsigned long get_sdram_size(void)
{
return get_ram_size(CONFIG_SYS_DDR_SDRAM_BASE, CONFIG_SYS_DRAM_SIZE);
}
/*
* Fixed sdram init -- doesn't use serial presence detect.
*/
phys_size_t fixed_sdram(void)
{
int i;
char buf[32];
fsl_ddr_cfg_regs_t ddr_cfg_regs;
phys_size_t ddr_size;
ulong ddr_freq, ddr_freq_mhz;
ddr_freq = get_ddr_freq(0);
ddr_freq_mhz = ddr_freq / 1000000;
printf("Configuring DDR for %s MT/s data rate\n",
strmhz(buf, ddr_freq));
for (i = 0; fixed_ddr_parm_0[i].max_freq > 0; i++) {
if ((ddr_freq_mhz > fixed_ddr_parm_0[i].min_freq) &&
(ddr_freq_mhz <= fixed_ddr_parm_0[i].max_freq)) {
memcpy(&ddr_cfg_regs, fixed_ddr_parm_0[i].ddr_settings,
sizeof(ddr_cfg_regs));
break;
}
}
if (fixed_ddr_parm_0[i].max_freq == 0) {
panic("Unsupported DDR data rate %s MT/s data rate\n",
strmhz(buf, ddr_freq));
}
ddr_size = (phys_size_t) CONFIG_SYS_SDRAM_SIZE * 1024 * 1024;
fsl_ddr_set_memctl_regs(&ddr_cfg_regs, 0, 0);
if (set_ddr_laws(CONFIG_SYS_DDR_SDRAM_BASE, ddr_size,
LAW_TRGT_IF_DDR_1) < 0) {
printf("ERROR setting Local Access Windows for DDR\n");
return 0;
}
return ddr_size;
}
#else /* CONFIG_SYS_DDR_RAW_TIMING */
/* Micron MT41J256M8HX-15E */
dimm_params_t ddr_raw_timing = {
.n_ranks = 1,
.rank_density = 1073741824u,
.capacity = 1073741824u,
.primary_sdram_width = 32,
.ec_sdram_width = 0,
.registered_dimm = 0,
.mirrored_dimm = 0,
.n_row_addr = 15,
.n_col_addr = 10,
.n_banks_per_sdram_device = 8,
.edc_config = 0,
.burst_lengths_bitmask = 0x0c,
.tckmin_x_ps = 1870,
.caslat_x = 0x1e << 4, /* 5,6,7,8 */
.taa_ps = 13125,
.twr_ps = 15000,
.trcd_ps = 13125,
.trrd_ps = 7500,
.trp_ps = 13125,
.tras_ps = 37500,
.trc_ps = 50625,
.trfc_ps = 160000,
.twtr_ps = 7500,
.trtp_ps = 7500,
.refresh_rate_ps = 7800000,
.tfaw_ps = 37500,
};
int fsl_ddr_get_dimm_params(dimm_params_t *pdimm,
unsigned int controller_number,
unsigned int dimm_number)
{
const char dimm_model[] = "Fixed DDR on board";
if ((controller_number == 0) && (dimm_number == 0)) {
memcpy(pdimm, &ddr_raw_timing, sizeof(dimm_params_t));
memset(pdimm->mpart, 0, sizeof(pdimm->mpart));
memcpy(pdimm->mpart, dimm_model, sizeof(dimm_model) - 1);
}
return 0;
}
void fsl_ddr_board_options(memctl_options_t *popts,
dimm_params_t *pdimm,
unsigned int ctrl_num)
{
int i;
popts->clk_adjust = 6;
popts->cpo_override = 0x1f;
popts->write_data_delay = 2;
popts->half_strength_driver_enable = 1;
/* Write leveling override */
popts->wrlvl_en = 1;
popts->wrlvl_override = 1;
popts->wrlvl_sample = 0xf;
popts->wrlvl_start = 0x8;
popts->trwt_override = 1;
popts->trwt = 0;
for (i = 0; i < CONFIG_CHIP_SELECTS_PER_CTRL; i++) {
popts->cs_local_opts[i].odt_rd_cfg = FSL_DDR_ODT_NEVER;
popts->cs_local_opts[i].odt_wr_cfg = FSL_DDR_ODT_CS;
}
}
#endif /* CONFIG_SYS_DDR_RAW_TIMING */
@@ -0,0 +1,18 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright 2011-2012 Freescale Semiconductor, Inc.
*/
#include <common.h>
#include <asm/fsl_law.h>
#include <asm/mmu.h>
struct law_entry law_table[] = {
SET_LAW(CONFIG_SYS_NAND_BASE_PHYS, LAW_SIZE_1M, LAW_TRGT_IF_IFC),
SET_LAW(CONFIG_SYS_FSL_DSP_CCSRBAR_PHYS, LAW_SIZE_1M,
LAW_TRGT_IF_DSP_CCSR),
SET_LAW(CONFIG_SYS_FSL_DSP_M2_RAM_ADDR, LAW_SIZE_16M,
LAW_TRGT_IF_OCN_DSP),
};
int num_law_entries = ARRAY_SIZE(law_table);
@@ -0,0 +1,103 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright 2013 Freescale Semiconductor, Inc.
*/
#include <common.h>
#include <ns16550.h>
#include <asm/io.h>
#include <nand.h>
#include <linux/compiler.h>
#include <asm/fsl_law.h>
#include <fsl_ddr_sdram.h>
#include <asm/global_data.h>
DECLARE_GLOBAL_DATA_PTR;
/*
* Fixed sdram init -- doesn't use serial presence detect.
*/
static void sdram_init(void)
{
struct ccsr_ddr __iomem *ddr =
(struct ccsr_ddr __iomem *)CONFIG_SYS_FSL_DDR_ADDR;
__raw_writel(CONFIG_SYS_DDR_CS0_BNDS, &ddr->cs0_bnds);
__raw_writel(CONFIG_SYS_DDR_CS0_CONFIG, &ddr->cs0_config);
#if CONFIG_CHIP_SELECTS_PER_CTRL > 1
__raw_writel(CONFIG_SYS_DDR_CS1_BNDS, &ddr->cs1_bnds);
__raw_writel(CONFIG_SYS_DDR_CS1_CONFIG, &ddr->cs1_config);
#endif
__raw_writel(CONFIG_SYS_DDR_TIMING_3_800, &ddr->timing_cfg_3);
__raw_writel(CONFIG_SYS_DDR_TIMING_0_800, &ddr->timing_cfg_0);
__raw_writel(CONFIG_SYS_DDR_TIMING_1_800, &ddr->timing_cfg_1);
__raw_writel(CONFIG_SYS_DDR_TIMING_2_800, &ddr->timing_cfg_2);
__raw_writel(CONFIG_SYS_DDR_CONTROL_2, &ddr->sdram_cfg_2);
__raw_writel(CONFIG_SYS_DDR_MODE_1_800, &ddr->sdram_mode);
__raw_writel(CONFIG_SYS_DDR_MODE_2_800, &ddr->sdram_mode_2);
__raw_writel(CONFIG_SYS_DDR_INTERVAL_800, &ddr->sdram_interval);
__raw_writel(CONFIG_SYS_DDR_DATA_INIT, &ddr->sdram_data_init);
__raw_writel(CONFIG_SYS_DDR_CLK_CTRL_800, &ddr->sdram_clk_cntl);
__raw_writel(CONFIG_SYS_DDR_WRLVL_CONTROL_800, &ddr->ddr_wrlvl_cntl);
__raw_writel(CONFIG_SYS_DDR_TIMING_4, &ddr->timing_cfg_4);
__raw_writel(CONFIG_SYS_DDR_TIMING_5, &ddr->timing_cfg_5);
__raw_writel(CONFIG_SYS_DDR_ZQ_CONTROL, &ddr->ddr_zq_cntl);
/* Set, but do not enable the memory */
__raw_writel(CONFIG_SYS_DDR_CONTROL & ~SDRAM_CFG_MEM_EN, &ddr->sdram_cfg);
asm volatile("sync;isync");
udelay(500);
/* Let the controller go */
out_be32(&ddr->sdram_cfg, in_be32(&ddr->sdram_cfg) | SDRAM_CFG_MEM_EN);
set_next_law(CONFIG_SYS_NAND_DDR_LAW, LAW_SIZE_1G, LAW_TRGT_IF_DDR_1);
}
void board_init_f(ulong bootflag)
{
u32 plat_ratio;
ccsr_gur_t *gur = (void *)CONFIG_SYS_MPC85xx_GUTS_ADDR;
/* initialize selected port with appropriate baud rate */
plat_ratio = in_be32(&gur->porpllsr) & MPC85xx_PORPLLSR_PLAT_RATIO;
plat_ratio >>= 1;
gd->bus_clk = CONFIG_SYS_CLK_FREQ * plat_ratio;
NS16550_init((NS16550_t)CONFIG_SYS_NS16550_COM1,
gd->bus_clk / 16 / CONFIG_BAUDRATE);
puts("\nNAND boot... ");
/* Initialize the DDR3 */
sdram_init();
/* copy code to RAM and jump to it - this should not return */
/* NOTE - code has to be copied out of NAND buffer before
* other blocks can be read.
*/
relocate_code(CONFIG_SPL_RELOC_STACK, 0, CONFIG_SPL_RELOC_TEXT_BASE);
}
void board_init_r(gd_t *gd, ulong dest_addr)
{
nand_boot();
}
void putc(char c)
{
if (c == '\n')
NS16550_putc((NS16550_t)CONFIG_SYS_NS16550_COM1, '\r');
NS16550_putc((NS16550_t)CONFIG_SYS_NS16550_COM1, c);
}
void puts(const char *str)
{
while (*str)
putc(*str++);
}
@@ -0,0 +1,61 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright 2011-2012 Freescale Semiconductor, Inc.
*/
#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,
MAS3_SX|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 + 4 * 1024,
MAS3_SX|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 + 8 * 1024,
MAS3_SX|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 + 12 * 1024,
MAS3_SX|MAS3_SW|MAS3_SR, 0,
0, 0, BOOKE_PAGESZ_4K, 0),
/* TLB 1 */
/* *I*** - Covers boot page */
SET_TLB_ENTRY(1, 0xfffff000, 0xfffff000,
MAS3_SX|MAS3_SW|MAS3_SR, MAS2_I|MAS2_G,
0, 0, BOOKE_PAGESZ_4K, 1),
#ifdef CONFIG_SPL_NAND_BOOT
SET_TLB_ENTRY(1, 0xffffe000, 0xffffe000,
MAS3_SX|MAS3_SW|MAS3_SR, MAS2_I|MAS2_G,
0, 10, BOOKE_PAGESZ_4K, 1),
#endif
/* *I*G* - CCSRBAR (PA) */
SET_TLB_ENTRY(1, CONFIG_SYS_CCSRBAR, CONFIG_SYS_CCSRBAR_PHYS,
MAS3_SX|MAS3_SW|MAS3_SR, MAS2_I|MAS2_G,
0, 1, BOOKE_PAGESZ_1M, 1),
/* CCSRBAR (DSP) */
SET_TLB_ENTRY(1, CONFIG_SYS_FSL_DSP_CCSRBAR,
CONFIG_SYS_FSL_DSP_CCSRBAR_PHYS,
MAS3_SW|MAS3_SR, MAS2_I|MAS2_G,
0, 2, BOOKE_PAGESZ_1M, 1),
#if defined(CONFIG_SYS_RAMBOOT) || defined(CONFIG_SPL)
SET_TLB_ENTRY(1, CONFIG_SYS_DDR_SDRAM_BASE, CONFIG_SYS_DDR_SDRAM_BASE,
MAS3_SX|MAS3_SW|MAS3_SR, MAS2_M,
0, 8, BOOKE_PAGESZ_1G, 1),
#endif
SET_TLB_ENTRY(1, CONFIG_SYS_NAND_BASE, CONFIG_SYS_NAND_BASE_PHYS,
MAS3_SX|MAS3_SW|MAS3_SR, MAS2_I|MAS2_G,
0, 3, BOOKE_PAGESZ_1M, 1)
};
int num_tlb_entries = ARRAY_SIZE(tlb_table);
@@ -0,0 +1,14 @@
if TARGET_BSC9132QDS
config SYS_BOARD
default "bsc9132qds"
config SYS_VENDOR
default "freescale"
config SYS_CONFIG_NAME
default "BSC9132QDS"
source "board/freescale/common/Kconfig"
endif
@@ -0,0 +1,25 @@
BSC9132QDS BOARD
M: Naveen Burmi <naveen.burmi@nxp.com>
S: Maintained
F: board/freescale/bsc9132qds/
F: include/configs/BSC9132QDS.h
F: configs/BSC9132QDS_NAND_DDRCLK100_defconfig
F: configs/BSC9132QDS_NAND_DDRCLK133_defconfig
F: configs/BSC9132QDS_NOR_DDRCLK100_defconfig
F: configs/BSC9132QDS_NOR_DDRCLK133_defconfig
F: configs/BSC9132QDS_SDCARD_DDRCLK100_defconfig
F: configs/BSC9132QDS_SDCARD_DDRCLK133_defconfig
F: configs/BSC9132QDS_SPIFLASH_DDRCLK100_defconfig
F: configs/BSC9132QDS_SPIFLASH_DDRCLK133_defconfig
BSC9132QDS_NAND_DDRCLK100_SECURE BOARD
M: Ruchika Gupta <ruchika.gupta@nxp.com>
S: Maintained
F: configs/BSC9132QDS_NAND_DDRCLK100_SECURE_defconfig
F: configs/BSC9132QDS_NAND_DDRCLK133_SECURE_defconfig
F: configs/BSC9132QDS_NOR_DDRCLK100_SECURE_defconfig
F: configs/BSC9132QDS_NOR_DDRCLK133_SECURE_defconfig
F: configs/BSC9132QDS_SDCARD_DDRCLK100_SECURE_defconfig
F: configs/BSC9132QDS_SDCARD_DDRCLK133_SECURE_defconfig
F: configs/BSC9132QDS_SPIFLASH_DDRCLK100_SECURE_defconfig
F: configs/BSC9132QDS_SPIFLASH_DDRCLK133_SECURE_defconfig
@@ -0,0 +1,21 @@
# SPDX-License-Identifier: GPL-2.0+
#
# Copyright 2013 Freescale Semiconductor, Inc.
MINIMAL=
ifdef CONFIG_SPL_BUILD
ifdef CONFIG_SPL_INIT_MINIMAL
MINIMAL=y
endif
endif
ifdef MINIMAL
obj-y += spl_minimal.o
else
obj-y += bsc9132qds.o
obj-y += ddr.o
endif
obj-y += law.o
obj-y += tlb.o
@@ -0,0 +1,150 @@
Overview
--------
The BSC9132 is a highly integrated device that targets the evolving
Microcell, Picocell, and Enterprise-Femto base station market subsegments.
The BSC9132 device combines Power Architecture e500 and DSP StarCore SC3850
core technologies with MAPLE-B2P baseband acceleration processing elements
to address the need for a high performance, low cost, integrated solution
that handles all required processing layers without the need for an
external device except for an RF transceiver or, in a Micro base station
configuration, a host device that handles the L3/L4 and handover between
sectors.
The BSC9132 SoC includes the following function and features:
- Power Architecture subsystem including two e500 processors with
512-Kbyte shared L2 cache
- Two StarCore SC3850 DSP subsystems, each with a 512-Kbyte private L2
cache
- 32 Kbyte of shared M3 memory
- The Multi Accelerator Platform Engine for Pico BaseStation Baseband
Processing (MAPLE-B2P)
- Two DDR3/3L memory interfaces with 32-bit data width (40 bits including
ECC), up to 1333 MHz data rate
- Dedicated security engine featuring trusted boot
- Two DMA controllers
- OCNDMA with four bidirectional channels
- SysDMA with sixteen bidirectional channels
- Interfaces
- Four-lane SerDes PHY
- PCI Express controller complies with the PEX Specification-Rev 2.0
- Two Common Public Radio Interface (CPRI) controller lanes
- High-speed USB 2.0 host and device controller with ULPI interface
- Enhanced secure digital (SD/MMC) host controller (eSDHC)
- Antenna interface controller (AIC), supporting four industry
standard JESD207/four custom ADI RF interfaces
- ADI lanes support both full duplex FDD support & half duplex TDD
- Universal Subscriber Identity Module (USIM) interface that
facilitates communication to SIM cards or Eurochip pre-paid phone
cards
- Two DUART, two eSPI, and two I2C controllers
- Integrated Flash memory controller (IFC)
- GPIO
- Sixteen 32-bit timers
The SC3850 core subsystem consists of the following:
- 32 KB, 8-way, level 1 instruction cache (L1 ICache)
- 32 KB, 8-way, level 1 data cache (L1 DCache)
- 512 KB, 8-way, level 2 unified instruction/data cache (L2 cache/M2 memory)
- Memory management unit (MMU)
- Global interrupt controller ( GIC)
- Debug and profiling unit (DPU)
- Two 32-bit quad timers
BSC9132QDS board Overview
-------------------------
2Gbyte DDR3 (on board DDR), Dual Ranki
32Mbyte 16bit NOR flash
128Mbyte 2K page size NAND Flash
256 Kbit M24256 I2C EEPROM
128 Mbit SPI Flash memory
SD slot
USB-ULPI
eTSEC1: Connected to SGMII PHY
eTSEC2: Connected to SGMII PHY
PCIe
CPRI
SerDes
I2C RTC
DUART interface: supports one UARTs up to 115200 bps for console display
Frequency Combinations Supported
--------------------------------
Core MHz/CCB MHz/DDR(MT/s)
1. CPU0/CPU1/CCB/DDR: 1000MHz/1000MHz/500MHz/800MHz
(SYSCLK = 100MHz, DDRCLK = 100MHz)
2. CPU0/CPU1/CCB/DDR: 1200MHz/1200MHz/600MHz/1330MHz
(SYSCLK = 100MHz, DDRCLK = 133MHz)
Boot Methods Supported
-----------------------
1. NOR Flash
2. NAND Flash
3. SD Card
4. SPI flash
Default Boot Method
--------------------
NOR boot
Building U-Boot
--------------
To build the U-Boot for BSC9132QDS:
1. NOR Flash
make BSC9132QDS_NOR_DDRCLK100 : For 100MHZ DDR CLK
make BSC9132QDS_NOR_DDRCLK133 : For 133MHZ DDR CLK
2. NAND Flash : It is currently not supported
3. SPI Flash
make BSC9132QDS_SPIFLASH_DDRCLK100 : For 100MHZ DDR CLK
make BSC9132QDS_SPIFLASH_DDRCLK133 : For 133MHZ DDR CLK
4. SD Card
make BSC9132QDS_SDCARD_DDRCLK100 : For 100MHZ DDR CLK
make BSC9132QDS_SDCARD_DDRCLK133 : For 133MHZ DDR CLK
Memory map
-----------
0x0000_0000 0x7FFF_FFFF DDR 2G cacheable
0x8000_0000 0x8FFF_FFFF NOR Flash 256M
0x9000_0000 0x9FFF_FFFF PCIe Memory 256M
0xA000_0000 0xA7FF_FFFF DSP core1 L2 space 128M
0xB000_0000 0xB0FF_FFFF DSP core0 M2 space 16M
0xB100_0000 0xB1FF_FFFF DSP core1 M2 space 16M
0xC000_0000 0xC000_7FFF M3 Memory 32K
0xC001_0000 0xC001_FFFF PCI Express I/O 64K
0xC100_0000 0xC13F_FFFF MAPLE-2F 4M
0xC1F0_0000 0xC1F7_FFFF PA SRAM Region 0 512K
0xC1F8_0000 0xC1FB_FFFF PA SRAM Region 1 512K
0xFED0_0000 0xFED0_3FFF SEC Secured RAM 16K
0xFEE0_0000 0xFEE0_0FFF DSP Boot ROM 4K
0xFF60_0000 0xFF6F_FFFF DSP CCSR 1M
0xFF70_0000 0xFF7F_FFFF PA CCSR 1M
0xFF80_0000 0xFFFF_FFFF Boot Page & NAND Buffer 8M
Flashing Images
---------------
To place a new U-Boot image in the NAND flash and then boot
with that new image temporarily, use this:
tftp 1000000 u-boot-nand.bin
nand erase 0 100000
nand write 1000000 0 100000
reset
Using the Device Tree Source File
---------------------------------
To create the DTB (Device Tree Binary) image file,
use a command similar to this:
dtc -b 0 -f -I dts -O dtb bsc9132qds.dts > bsc9132qds.dtb
Likely, that .dts file will come from here;
linux-2.6/arch/powerpc/boot/dts/bsc9132qds.dts
Booting Linux
-------------
Place a linux uImage in the TFTP disk area.
tftp 1000000 uImage
tftp 2000000 rootfs.ext2.gz.uboot
tftp c00000 bsc9132qds.dtb
bootm 1000000 2000000 c00000
@@ -0,0 +1,430 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright 2013 Freescale Semiconductor, Inc.
*/
#include <common.h>
#include <init.h>
#include <asm/processor.h>
#include <asm/mmu.h>
#include <asm/cache.h>
#include <asm/immap_85xx.h>
#include <asm/io.h>
#include <env.h>
#include <miiphy.h>
#include <linux/libfdt.h>
#include <fdt_support.h>
#include <fsl_mdio.h>
#include <tsec.h>
#include <mmc.h>
#include <netdev.h>
#include <fsl_ifc.h>
#include <hwconfig.h>
#include <i2c.h>
#include <fsl_ddr_sdram.h>
#include <jffs2/load_kernel.h>
#include <mtd_node.h>
#include <flash.h>
#ifdef CONFIG_PCI
#include <pci.h>
#include <asm/fsl_pci.h>
#endif
#include "../common/qixis.h"
DECLARE_GLOBAL_DATA_PTR;
int board_early_init_f(void)
{
struct fsl_ifc ifc = {(void *)CONFIG_SYS_IFC_ADDR, (void *)NULL};
setbits_be32(&ifc.gregs->ifc_gcr, 1 << IFC_GCR_TBCTL_TRN_TIME_SHIFT);
return 0;
}
void board_config_serdes_mux(void)
{
ccsr_gur_t *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR);
u32 pordevsr = in_be32(&gur->pordevsr);
u32 srds_cfg = (pordevsr & MPC85xx_PORDEVSR_IO_SEL) >>
MPC85xx_PORDEVSR_IO_SEL_SHIFT;
switch (srds_cfg) {
/* PEX(1) PEX(2) CPRI 2 CPRI 1 */
case 1:
case 2:
case 3:
case 4:
case 5:
case 22:
case 23:
case 24:
case 25:
case 26:
QIXIS_WRITE_I2C(brdcfg[4], 0x03);
break;
/* PEX(1) PEX(2) SGMII1 CPRI 1 */
case 6:
case 7:
case 8:
case 9:
case 10:
case 27:
case 28:
case 29:
case 30:
case 31:
QIXIS_WRITE_I2C(brdcfg[4], 0x01);
break;
/* PEX(1) PEX(2) SGMII1 SGMII2 */
case 11:
case 32:
QIXIS_WRITE_I2C(brdcfg[4], 0x00);
break;
/* PEX(1) SGMII2 CPRI 2 CPRI 1 */
case 12:
case 13:
case 14:
case 15:
case 16:
case 33:
case 34:
case 35:
case 36:
case 37:
QIXIS_WRITE_I2C(brdcfg[4], 0x07);
break;
/* PEX(1) SGMII2 SGMII1 CPRI 1 */
case 17:
case 18:
case 19:
case 20:
case 21:
case 38:
case 39:
case 40:
case 41:
case 42:
QIXIS_WRITE_I2C(brdcfg[4], 0x05);
break;
/* SGMII1 SGMII2 CPRI 2 CPRI 1 */
case 43:
case 44:
case 45:
case 46:
case 47:
QIXIS_WRITE_I2C(brdcfg[4], 0x0F);
break;
default:
break;
}
}
/* Configure DSP DDR controller */
void dsp_ddr_configure(void)
{
/*
*There are separate DDR-controllers for DSP and PowerPC side DDR.
*copy the ddr controller settings from PowerPC side DDR controller
*to the DSP DDR controller as connected DDR memories are similar.
*/
struct ccsr_ddr __iomem *pa_ddr =
(struct ccsr_ddr __iomem *)CONFIG_SYS_FSL_DDR_ADDR;
struct ccsr_ddr temp_ddr;
struct ccsr_ddr __iomem *dsp_ddr =
(struct ccsr_ddr __iomem *)CONFIG_SYS_FSL_DSP_CCSR_DDR_ADDR;
memcpy(&temp_ddr, pa_ddr, sizeof(struct ccsr_ddr));
temp_ddr.cs0_bnds = CONFIG_SYS_DDR1_CS0_BNDS;
temp_ddr.sdram_cfg &= ~SDRAM_CFG_MEM_EN;
memcpy(dsp_ddr, &temp_ddr, sizeof(struct ccsr_ddr));
dsp_ddr->sdram_cfg |= SDRAM_CFG_MEM_EN;
}
int board_early_init_r(void)
{
#ifdef CONFIG_MTD_NOR_FLASH
const unsigned int flashbase = CONFIG_SYS_FLASH_BASE;
int flash_esel = find_tlb_idx((void *)flashbase, 1);
/*
* Remap Boot flash region to caching-inhibited
* so that flash can be erased properly.
*/
/* Flush d-cache and invalidate i-cache of any FLASH data */
flush_dcache();
invalidate_icache();
if (flash_esel == -1) {
/* very unlikely unless something is messed up */
puts("Error: Could not find TLB for FLASH BASE\n");
flash_esel = 2; /* give our best effort to continue */
} else {
/* invalidate existing TLB entry for flash */
disable_tlb(flash_esel);
}
set_tlb(1, flashbase, CONFIG_SYS_FLASH_BASE_PHYS,
MAS3_SX|MAS3_SW|MAS3_SR, MAS2_I|MAS2_G,
0, flash_esel, BOOKE_PAGESZ_64M, 1);
set_tlb(1, flashbase + 0x4000000,
CONFIG_SYS_FLASH_BASE_PHYS + 0x4000000,
MAS3_SX|MAS3_SW|MAS3_SR, MAS2_I|MAS2_G,
0, flash_esel+1, BOOKE_PAGESZ_64M, 1);
#endif
board_config_serdes_mux();
dsp_ddr_configure();
return 0;
}
#ifdef CONFIG_PCI
void pci_init_board(void)
{
fsl_pcie_init_board(0);
}
#endif /* ifdef CONFIG_PCI */
int checkboard(void)
{
struct cpu_type *cpu;
u8 sw;
cpu = gd->arch.cpu;
printf("Board: %sQDS\n", cpu->name);
printf("Sys ID: 0x%02x, Sys Ver: 0x%02x, FPGA Ver: 0x%02x,\n",
QIXIS_READ(id), QIXIS_READ(arch), QIXIS_READ(scver));
sw = QIXIS_READ(brdcfg[0]);
sw = (sw & QIXIS_LBMAP_MASK) >> QIXIS_LBMAP_SHIFT;
printf("IFC chip select:");
switch (sw) {
case 0:
printf("NOR\n");
break;
case 2:
printf("Promjet\n");
break;
case 4:
printf("NAND\n");
break;
default:
printf("Invalid setting of SW%u\n", QIXIS_LBMAP_SWITCH);
break;
}
return 0;
}
int board_eth_init(bd_t *bis)
{
#ifdef CONFIG_TSEC_ENET
struct fsl_pq_mdio_info mdio_info;
struct tsec_info_struct tsec_info[4];
int num = 0;
#ifdef CONFIG_TSEC1
SET_STD_TSEC_INFO(tsec_info[num], 1);
num++;
#endif
#ifdef CONFIG_TSEC2
SET_STD_TSEC_INFO(tsec_info[num], 2);
num++;
#endif
mdio_info.regs = (struct tsec_mii_mng *)CONFIG_SYS_MDIO_BASE_ADDR;
mdio_info.name = DEFAULT_MII_NAME;
fsl_pq_mdio_init(bis, &mdio_info);
tsec_eth_init(bis, tsec_info, num);
#endif
#ifdef CONFIG_PCI
pci_eth_init(bis);
#endif
return 0;
}
#define USBMUX_SEL_MASK 0xc0
#define USBMUX_SEL_UART2 0xc0
#define USBMUX_SEL_USB 0x40
#define SPIMUX_SEL_UART3 0x80
#define GPS_MUX_SEL_GPS 0x40
#define TSEC_1588_CLKIN_MASK 0x03
#define CON_XCVR_REF_CLK 0x00
int misc_init_r(void)
{
u8 val;
ccsr_gur_t *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR);
u32 porbmsr = in_be32(&gur->porbmsr);
u32 romloc = (porbmsr >> MPC85xx_PORBMSR_ROMLOC_SHIFT) & 0xf;
/*Configure 1588 clock-in source from RF Card*/
val = QIXIS_READ_I2C(brdcfg[5]);
QIXIS_WRITE_I2C(brdcfg[5],
(val & ~(TSEC_1588_CLKIN_MASK)) | CON_XCVR_REF_CLK);
if (hwconfig("uart2") && hwconfig("usb1")) {
printf("UART2 and USB cannot work together on the board\n");
printf("Remove one from hwconfig and reset\n");
} else {
if (hwconfig("uart2")) {
val = QIXIS_READ_I2C(brdcfg[5]);
QIXIS_WRITE_I2C(brdcfg[5],
(val & ~(USBMUX_SEL_MASK)) | USBMUX_SEL_UART2);
clrbits_be32(&gur->pmuxcr3,
MPC85xx_PMUXCR3_USB_SEL_MASK);
setbits_be32(&gur->pmuxcr3, MPC85xx_PMUXCR3_UART2_SEL);
} else {
/* By default USB should be selected.
* Programming FPGA to select USB. */
val = QIXIS_READ_I2C(brdcfg[5]);
QIXIS_WRITE_I2C(brdcfg[5],
(val & ~(USBMUX_SEL_MASK)) | USBMUX_SEL_USB);
}
}
if (hwconfig("sim")) {
if (romloc == PORBMSR_ROMLOC_NAND_2K ||
romloc == PORBMSR_ROMLOC_NOR ||
romloc == PORBMSR_ROMLOC_SPI) {
val = QIXIS_READ_I2C(brdcfg[3]);
QIXIS_WRITE_I2C(brdcfg[3], val|0x10);
clrbits_be32(&gur->pmuxcr,
MPC85xx_PMUXCR0_SIM_SEL_MASK);
setbits_be32(&gur->pmuxcr, MPC85xx_PMUXCR0_SIM_SEL);
}
}
if (hwconfig("uart3")) {
if (romloc == PORBMSR_ROMLOC_NAND_2K ||
romloc == PORBMSR_ROMLOC_NOR ||
romloc == PORBMSR_ROMLOC_SDHC) {
/* UART3 and SPI1 (Flashes) are muxed together */
val = QIXIS_READ_I2C(brdcfg[3]);
QIXIS_WRITE_I2C(brdcfg[3], (val | SPIMUX_SEL_UART3));
clrbits_be32(&gur->pmuxcr3,
MPC85xx_PMUXCR3_UART3_SEL_MASK);
setbits_be32(&gur->pmuxcr3, MPC85xx_PMUXCR3_UART3_SEL);
/* MUX to select UART3 connection to J24 header
* or to GPS */
val = QIXIS_READ_I2C(brdcfg[6]);
if (hwconfig("gps"))
QIXIS_WRITE_I2C(brdcfg[6],
(val | GPS_MUX_SEL_GPS));
else
QIXIS_WRITE_I2C(brdcfg[6],
(val & ~(GPS_MUX_SEL_GPS)));
}
}
return 0;
}
void fdt_del_node_compat(void *blob, const char *compatible)
{
int err;
int off = fdt_node_offset_by_compatible(blob, -1, compatible);
if (off < 0) {
printf("WARNING: could not find compatible node %s: %s.\n",
compatible, fdt_strerror(off));
return;
}
err = fdt_del_node(blob, off);
if (err < 0) {
printf("WARNING: could not remove %s: %s.\n",
compatible, fdt_strerror(err));
}
}
#if defined(CONFIG_OF_BOARD_SETUP)
#ifdef CONFIG_FDT_FIXUP_PARTITIONS
static const struct node_info nodes[] = {
{ "cfi-flash", MTD_DEV_TYPE_NOR, },
{ "fsl,ifc-nand", MTD_DEV_TYPE_NAND, },
};
#endif
int ft_board_setup(void *blob, bd_t *bd)
{
phys_addr_t base;
phys_size_t size;
ft_cpu_setup(blob, bd);
base = env_get_bootm_low();
size = env_get_bootm_size();
#if defined(CONFIG_PCI)
FT_FSL_PCI_SETUP;
#endif
fdt_fixup_memory(blob, (u64)base, (u64)size);
#ifdef CONFIG_FDT_FIXUP_PARTITIONS
fdt_fixup_mtdparts(blob, nodes, ARRAY_SIZE(nodes));
#endif
ccsr_gur_t *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR);
u32 porbmsr = in_be32(&gur->porbmsr);
u32 romloc = (porbmsr >> MPC85xx_PORBMSR_ROMLOC_SHIFT) & 0xf;
if (!(hwconfig("uart2") && hwconfig("usb1"))) {
/* If uart2 is there in hwconfig remove usb node from
* device tree */
if (hwconfig("uart2")) {
/* remove dts usb node */
fdt_del_node_compat(blob, "fsl-usb2-dr");
} else {
fsl_fdt_fixup_dr_usb(blob, bd);
fdt_del_node_and_alias(blob, "serial2");
}
}
if (hwconfig("uart3")) {
if (romloc == PORBMSR_ROMLOC_NAND_2K ||
romloc == PORBMSR_ROMLOC_NOR ||
romloc == PORBMSR_ROMLOC_SDHC)
/* Delete SPI node from the device tree */
fdt_del_node_and_alias(blob, "spi1");
} else
fdt_del_node_and_alias(blob, "serial3");
if (hwconfig("sim")) {
if (romloc == PORBMSR_ROMLOC_NAND_2K ||
romloc == PORBMSR_ROMLOC_NOR ||
romloc == PORBMSR_ROMLOC_SPI) {
/* remove dts sdhc node */
fdt_del_node_compat(blob, "fsl,esdhc");
} else if (romloc == PORBMSR_ROMLOC_SDHC) {
/* remove dts sim node */
fdt_del_node_compat(blob, "fsl,sim-v1.0");
printf("SIM & SDHC can't work together on the board");
printf("\nRemove sim from hwconfig and reset\n");
}
}
return 0;
}
#endif
@@ -0,0 +1,191 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright 2013 Freescale Semiconductor, Inc.
*/
#include <common.h>
#include <vsprintf.h>
#include <asm/mmu.h>
#include <asm/immap_85xx.h>
#include <asm/processor.h>
#include <fsl_ddr_sdram.h>
#include <fsl_ddr_dimm_params.h>
#include <asm/io.h>
#include <asm/fsl_law.h>
#ifndef CONFIG_SYS_DDR_RAW_TIMING
fsl_ddr_cfg_regs_t ddr_cfg_regs_800 = {
.cs[0].bnds = CONFIG_SYS_DDR_CS0_BNDS,
.cs[0].config = CONFIG_SYS_DDR_CS0_CONFIG,
.cs[0].config_2 = CONFIG_SYS_DDR_CS0_CONFIG_2,
.timing_cfg_3 = CONFIG_SYS_DDR_TIMING_3_800,
.timing_cfg_0 = CONFIG_SYS_DDR_TIMING_0_800,
.timing_cfg_1 = CONFIG_SYS_DDR_TIMING_1_800,
.timing_cfg_2 = CONFIG_SYS_DDR_TIMING_2_800,
.ddr_sdram_cfg = CONFIG_SYS_DDR_CONTROL,
.ddr_sdram_cfg_2 = CONFIG_SYS_DDR_CONTROL_2,
.ddr_sdram_mode = CONFIG_SYS_DDR_MODE_1_800,
.ddr_sdram_mode_2 = CONFIG_SYS_DDR_MODE_2_800,
.ddr_sdram_md_cntl = CONFIG_SYS_DDR_MODE_CONTROL,
.ddr_sdram_interval = CONFIG_SYS_DDR_INTERVAL_800,
.ddr_data_init = CONFIG_MEM_INIT_VALUE,
.ddr_sdram_clk_cntl = CONFIG_SYS_DDR_CLK_CTRL_800,
.ddr_init_addr = CONFIG_SYS_DDR_INIT_ADDR,
.ddr_init_ext_addr = CONFIG_SYS_DDR_INIT_EXT_ADDR,
.timing_cfg_4 = CONFIG_SYS_DDR_TIMING_4,
.timing_cfg_5 = CONFIG_SYS_DDR_TIMING_5,
.ddr_zq_cntl = CONFIG_SYS_DDR_ZQ_CONTROL,
.ddr_wrlvl_cntl = CONFIG_SYS_DDR_WRLVL_CONTROL_800,
.ddr_sr_cntr = CONFIG_SYS_DDR_SR_CNTR,
.ddr_sdram_rcw_1 = CONFIG_SYS_DDR_RCW_1,
.ddr_sdram_rcw_2 = CONFIG_SYS_DDR_RCW_2
};
fsl_ddr_cfg_regs_t ddr_cfg_regs_1333 = {
.cs[0].bnds = CONFIG_SYS_DDR_CS0_BNDS,
.cs[0].config = CONFIG_SYS_DDR_CS0_CONFIG,
.cs[0].config_2 = CONFIG_SYS_DDR_CS0_CONFIG_2,
.timing_cfg_3 = CONFIG_SYS_DDR_TIMING_3_1333,
.timing_cfg_0 = CONFIG_SYS_DDR_TIMING_0_1333,
.timing_cfg_1 = CONFIG_SYS_DDR_TIMING_1_1333,
.timing_cfg_2 = CONFIG_SYS_DDR_TIMING_2_1333,
.ddr_sdram_cfg = CONFIG_SYS_DDR_CONTROL,
.ddr_sdram_cfg_2 = CONFIG_SYS_DDR_CONTROL_2,
.ddr_sdram_mode = CONFIG_SYS_DDR_MODE_1_1333,
.ddr_sdram_mode_2 = CONFIG_SYS_DDR_MODE_2_1333,
.ddr_sdram_md_cntl = CONFIG_SYS_DDR_MODE_CONTROL,
.ddr_sdram_interval = CONFIG_SYS_DDR_INTERVAL_1333,
.ddr_data_init = CONFIG_MEM_INIT_VALUE,
.ddr_sdram_clk_cntl = CONFIG_SYS_DDR_CLK_CTRL_1333,
.ddr_init_addr = CONFIG_SYS_DDR_INIT_ADDR,
.ddr_init_ext_addr = CONFIG_SYS_DDR_INIT_EXT_ADDR,
.timing_cfg_4 = CONFIG_SYS_DDR_TIMING_4,
.timing_cfg_5 = CONFIG_SYS_DDR_TIMING_5,
.ddr_zq_cntl = CONFIG_SYS_DDR_ZQ_CONTROL,
.ddr_wrlvl_cntl = CONFIG_SYS_DDR_WRLVL_CONTROL_1333,
.ddr_sr_cntr = CONFIG_SYS_DDR_SR_CNTR,
.ddr_sdram_rcw_1 = CONFIG_SYS_DDR_RCW_1,
.ddr_sdram_rcw_2 = CONFIG_SYS_DDR_RCW_2
};
fixed_ddr_parm_t fixed_ddr_parm_0[] = {
{750, 850, &ddr_cfg_regs_800},
{1060, 1333, &ddr_cfg_regs_1333},
{0, 0, NULL}
};
/*
* Fixed sdram init -- doesn't use serial presence detect.
*/
phys_size_t fixed_sdram(void)
{
int i;
char buf[32];
fsl_ddr_cfg_regs_t ddr_cfg_regs;
phys_size_t ddr_size;
ulong ddr_freq, ddr_freq_mhz;
ddr_freq = get_ddr_freq(0);
ddr_freq_mhz = ddr_freq / 1000000;
printf("Configuring DDR for %s MT/s data rate\n",
strmhz(buf, ddr_freq));
for (i = 0; fixed_ddr_parm_0[i].max_freq > 0; i++) {
if ((ddr_freq_mhz > fixed_ddr_parm_0[i].min_freq) &&
(ddr_freq_mhz <= fixed_ddr_parm_0[i].max_freq)) {
memcpy(&ddr_cfg_regs, fixed_ddr_parm_0[i].ddr_settings,
sizeof(ddr_cfg_regs));
break;
}
}
if (fixed_ddr_parm_0[i].max_freq == 0)
panic("Unsupported DDR data rate %s MT/s data rate\n",
strmhz(buf, ddr_freq));
ddr_size = (phys_size_t) CONFIG_SYS_SDRAM_SIZE * 1024 * 1024;
fsl_ddr_set_memctl_regs(&ddr_cfg_regs, 0, 0);
if (set_ddr_laws(CONFIG_SYS_DDR_SDRAM_BASE, ddr_size,
LAW_TRGT_IF_DDR_1) < 0) {
printf("ERROR setting Local Access Windows for DDR\n");
return 0;
}
return ddr_size;
}
#else /* CONFIG_SYS_DDR_RAW_TIMING */
/* Micron MT41J512M8_187E */
dimm_params_t ddr_raw_timing = {
.n_ranks = 1,
.rank_density = 1073741824u,
.capacity = 1073741824u,
.primary_sdram_width = 32,
.ec_sdram_width = 0,
.registered_dimm = 0,
.mirrored_dimm = 0,
.n_row_addr = 15,
.n_col_addr = 10,
.n_banks_per_sdram_device = 8,
.edc_config = 0,
.burst_lengths_bitmask = 0x0c,
.tckmin_x_ps = 1870,
.caslat_x = 0x1e << 4, /* 5,6,7,8 */
.taa_ps = 13125,
.twr_ps = 15000,
.trcd_ps = 13125,
.trrd_ps = 7500,
.trp_ps = 13125,
.tras_ps = 37500,
.trc_ps = 50625,
.trfc_ps = 160000,
.twtr_ps = 7500,
.trtp_ps = 7500,
.refresh_rate_ps = 7800000,
.tfaw_ps = 37500,
};
int fsl_ddr_get_dimm_params(dimm_params_t *pdimm,
unsigned int controller_number,
unsigned int dimm_number)
{
const char dimm_model[] = "Fixed DDR on board";
if ((controller_number == 0) && (dimm_number == 0)) {
memcpy(pdimm, &ddr_raw_timing, sizeof(dimm_params_t));
memset(pdimm->mpart, 0, sizeof(pdimm->mpart));
memcpy(pdimm->mpart, dimm_model, sizeof(dimm_model) - 1);
}
return 0;
}
void fsl_ddr_board_options(memctl_options_t *popts,
dimm_params_t *pdimm,
unsigned int ctrl_num)
{
int i;
popts->clk_adjust = 6;
popts->cpo_override = 0x1f;
popts->write_data_delay = 2;
popts->half_strength_driver_enable = 1;
/* Write leveling override */
popts->wrlvl_en = 1;
popts->wrlvl_override = 1;
popts->wrlvl_sample = 0xf;
popts->wrlvl_start = 0x8;
popts->trwt_override = 1;
popts->trwt = 0;
for (i = 0; i < CONFIG_CHIP_SELECTS_PER_CTRL; i++) {
popts->cs_local_opts[i].odt_rd_cfg = FSL_DDR_ODT_NEVER;
popts->cs_local_opts[i].odt_wr_cfg = FSL_DDR_ODT_CS;
}
}
#endif /* CONFIG_SYS_DDR_RAW_TIMING */
@@ -0,0 +1,28 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright 2013 Freescale Semiconductor, Inc.
*/
#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_128M, LAW_TRGT_IF_IFC),
#ifdef CONFIG_SYS_NAND_BASE_PHYS
SET_LAW(CONFIG_SYS_NAND_BASE_PHYS, LAW_SIZE_1M, LAW_TRGT_IF_IFC),
#endif
#ifdef CONFIG_SYS_FPGA_BASE_PHYS
SET_LAW(CONFIG_SYS_FPGA_BASE_PHYS, LAW_SIZE_128K, LAW_TRGT_IF_IFC),
#endif
SET_LAW(CONFIG_SYS_FSL_DSP_CCSRBAR_PHYS, LAW_SIZE_1M,
LAW_TRGT_IF_DSP_CCSR),
SET_LAW(CONFIG_SYS_FSL_DSP_M2_RAM_ADDR, LAW_SIZE_32M,
LAW_TRGT_IF_OCN_DSP),
SET_LAW(CONFIG_SYS_FSL_DSP_M3_RAM_ADDR, LAW_SIZE_32K,
LAW_TRGT_IF_CLASS_DSP),
SET_LAW(CONFIG_SYS_FSL_DSP_DDR_ADDR, LAW_SIZE_1G,
LAW_TRGT_IF_CLASS_DSP)
};
int num_law_entries = ARRAY_SIZE(law_table);
@@ -0,0 +1,115 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright 2013 Freescale Semiconductor, Inc.
*/
#include <common.h>
#include <ns16550.h>
#include <asm/io.h>
#include <nand.h>
#include <linux/compiler.h>
#include <asm/fsl_law.h>
#include <fsl_ddr_sdram.h>
#include <asm/global_data.h>
DECLARE_GLOBAL_DATA_PTR;
static void sdram_init(void)
{
struct ccsr_ddr __iomem *ddr =
(struct ccsr_ddr __iomem *)CONFIG_SYS_FSL_DDR_ADDR;
#if CONFIG_DDR_CLK_FREQ == 100000000
__raw_writel(CONFIG_SYS_DDR_CS0_BNDS, &ddr->cs0_bnds);
__raw_writel(CONFIG_SYS_DDR_CS0_CONFIG, &ddr->cs0_config);
__raw_writel(CONFIG_SYS_DDR_CONTROL_800 | SDRAM_CFG_32_BE, &ddr->sdram_cfg);
__raw_writel(CONFIG_SYS_DDR_CONTROL_2_800, &ddr->sdram_cfg_2);
__raw_writel(CONFIG_SYS_DDR_DATA_INIT, &ddr->sdram_data_init);
__raw_writel(CONFIG_SYS_DDR_TIMING_3_800, &ddr->timing_cfg_3);
__raw_writel(CONFIG_SYS_DDR_TIMING_0_800, &ddr->timing_cfg_0);
__raw_writel(CONFIG_SYS_DDR_TIMING_1_800, &ddr->timing_cfg_1);
__raw_writel(CONFIG_SYS_DDR_TIMING_2_800, &ddr->timing_cfg_2);
__raw_writel(CONFIG_SYS_DDR_MODE_1_800, &ddr->sdram_mode);
__raw_writel(CONFIG_SYS_DDR_MODE_2_800, &ddr->sdram_mode_2);
__raw_writel(CONFIG_SYS_DDR_INTERVAL_800, &ddr->sdram_interval);
__raw_writel(CONFIG_SYS_DDR_CLK_CTRL_800, &ddr->sdram_clk_cntl);
__raw_writel(CONFIG_SYS_DDR_WRLVL_CONTROL_800, &ddr->ddr_wrlvl_cntl);
__raw_writel(CONFIG_SYS_DDR_TIMING_4_800, &ddr->timing_cfg_4);
__raw_writel(CONFIG_SYS_DDR_TIMING_5_800, &ddr->timing_cfg_5);
__raw_writel(CONFIG_SYS_DDR_ZQ_CONTROL, &ddr->ddr_zq_cntl);
#elif CONFIG_DDR_CLK_FREQ == 133000000
__raw_writel(CONFIG_SYS_DDR_CS0_BNDS, &ddr->cs0_bnds);
__raw_writel(CONFIG_SYS_DDR_CS0_CONFIG, &ddr->cs0_config);
__raw_writel(CONFIG_SYS_DDR_CONTROL_1333 | SDRAM_CFG_32_BE, &ddr->sdram_cfg);
__raw_writel(CONFIG_SYS_DDR_CONTROL_2_1333, &ddr->sdram_cfg_2);
__raw_writel(CONFIG_SYS_DDR_DATA_INIT, &ddr->sdram_data_init);
__raw_writel(CONFIG_SYS_DDR_TIMING_3_1333, &ddr->timing_cfg_3);
__raw_writel(CONFIG_SYS_DDR_TIMING_0_1333, &ddr->timing_cfg_0);
__raw_writel(CONFIG_SYS_DDR_TIMING_1_1333, &ddr->timing_cfg_1);
__raw_writel(CONFIG_SYS_DDR_TIMING_2_1333, &ddr->timing_cfg_2);
__raw_writel(CONFIG_SYS_DDR_MODE_1_1333, &ddr->sdram_mode);
__raw_writel(CONFIG_SYS_DDR_MODE_2_1333, &ddr->sdram_mode_2);
__raw_writel(CONFIG_SYS_DDR_INTERVAL_1333, &ddr->sdram_interval);
__raw_writel(CONFIG_SYS_DDR_CLK_CTRL_1333, &ddr->sdram_clk_cntl);
__raw_writel(CONFIG_SYS_DDR_WRLVL_CONTROL_1333, &ddr->ddr_wrlvl_cntl);
__raw_writel(CONFIG_SYS_DDR_TIMING_4_1333, &ddr->timing_cfg_4);
__raw_writel(CONFIG_SYS_DDR_TIMING_5_1333, &ddr->timing_cfg_5);
__raw_writel(CONFIG_SYS_DDR_ZQ_CONTROL, &ddr->ddr_zq_cntl);
#else
puts("Not a valid DDR Freq Found! Please Reset\n");
#endif
asm volatile("sync;isync");
udelay(500);
/* Let the controller go */
out_be32(&ddr->sdram_cfg, in_be32(&ddr->sdram_cfg) | SDRAM_CFG_MEM_EN);
set_next_law(CONFIG_SYS_NAND_DDR_LAW, LAW_SIZE_1G, LAW_TRGT_IF_DDR_1);
}
void board_init_f(ulong bootflag)
{
u32 plat_ratio;
ccsr_gur_t *gur = (void *)CONFIG_SYS_MPC85xx_GUTS_ADDR;
/* initialize selected port with appropriate baud rate */
plat_ratio = in_be32(&gur->porpllsr) & MPC85xx_PORPLLSR_PLAT_RATIO;
plat_ratio >>= 1;
gd->bus_clk = CONFIG_SYS_CLK_FREQ * plat_ratio;
NS16550_init((NS16550_t)CONFIG_SYS_NS16550_COM1,
gd->bus_clk / 16 / CONFIG_BAUDRATE);
puts("\nNAND boot... ");
/* Initialize the DDR3 */
sdram_init();
/* copy code to RAM and jump to it - this should not return */
/* NOTE - code has to be copied out of NAND buffer before
* other blocks can be read.
*/
relocate_code(CONFIG_SPL_RELOC_STACK, 0, CONFIG_SPL_RELOC_TEXT_BASE);
}
void board_init_r(gd_t *gd, ulong dest_addr)
{
nand_boot();
}
void putc(char c)
{
if (c == '\n')
NS16550_putc((NS16550_t)CONFIG_SYS_NS16550_COM1, '\r');
NS16550_putc((NS16550_t)CONFIG_SYS_NS16550_COM1, c);
}
void puts(const char *str)
{
while (*str)
putc(*str++);
}
@@ -0,0 +1,91 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright 2013 Freescale Semiconductor, Inc.
*/
#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,
MAS3_SX|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 + 4 * 1024,
MAS3_SX|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 + 8 * 1024,
MAS3_SX|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 + 12 * 1024,
MAS3_SX|MAS3_SW|MAS3_SR, 0,
0, 0, BOOKE_PAGESZ_4K, 0),
/* TLB 1 */
/* *I*** - Covers boot page */
SET_TLB_ENTRY(1, 0xfffff000, 0xfffff000,
MAS3_SX|MAS3_SW|MAS3_SR, MAS2_I|MAS2_G,
0, 0, BOOKE_PAGESZ_4K, 1),
#ifdef CONFIG_SPL_NAND_BOOT
SET_TLB_ENTRY(1, 0xffffe000, 0xffffe000,
MAS3_SX|MAS3_SW|MAS3_SR, MAS2_I|MAS2_G,
0, 10, BOOKE_PAGESZ_4K, 1),
#endif
/* *I*G* - CCSRBAR (PA) */
SET_TLB_ENTRY(1, CONFIG_SYS_CCSRBAR, CONFIG_SYS_CCSRBAR_PHYS,
MAS3_SX|MAS3_SW|MAS3_SR, MAS2_I|MAS2_G,
0, 1, BOOKE_PAGESZ_1M, 1),
/* CCSRBAR (DSP) */
SET_TLB_ENTRY(1, CONFIG_SYS_FSL_DSP_CCSRBAR,
CONFIG_SYS_FSL_DSP_CCSRBAR_PHYS, MAS3_SW|MAS3_SR,
MAS2_I|MAS2_G, 0, 2, BOOKE_PAGESZ_1M, 1),
#ifndef CONFIG_SPL_BUILD
SET_TLB_ENTRY(1, CONFIG_SYS_FLASH_BASE, CONFIG_SYS_FLASH_BASE_PHYS,
MAS3_SX|MAS3_SR, MAS2_W|MAS2_G,
0, 3, BOOKE_PAGESZ_64M, 1),
SET_TLB_ENTRY(1, CONFIG_SYS_FLASH_BASE + 0x4000000,
CONFIG_SYS_FLASH_BASE_PHYS + 0x4000000,
MAS3_SX|MAS3_SR, MAS2_W|MAS2_G,
0, 4, BOOKE_PAGESZ_64M, 1),
#ifdef CONFIG_PCI
/* *I*G* - PCI */
SET_TLB_ENTRY(1, CONFIG_SYS_PCIE1_MEM_VIRT, CONFIG_SYS_PCIE1_MEM_PHYS,
MAS3_SX|MAS3_SW|MAS3_SR, MAS2_I|MAS2_G,
0, 6, BOOKE_PAGESZ_256M, 1),
/* *I*G* - PCI I/O */
SET_TLB_ENTRY(1, CONFIG_SYS_PCIE1_IO_VIRT, CONFIG_SYS_PCIE1_IO_PHYS,
MAS3_SX|MAS3_SW|MAS3_SR, MAS2_I|MAS2_G,
0, 7, BOOKE_PAGESZ_64K, 1),
#endif
#endif
#if defined(CONFIG_SYS_RAMBOOT) || defined(CONFIG_SPL)
SET_TLB_ENTRY(1, CONFIG_SYS_DDR_SDRAM_BASE, CONFIG_SYS_DDR_SDRAM_BASE,
MAS3_SX|MAS3_SW|MAS3_SR, MAS2_M,
0, 8, BOOKE_PAGESZ_1G, 1),
#endif
#ifdef CONFIG_SYS_FPGA_BASE
/* *I*G - Board FPGA */
SET_TLB_ENTRY(1, CONFIG_SYS_FPGA_BASE, CONFIG_SYS_FPGA_BASE_PHYS,
MAS3_SX|MAS3_SW|MAS3_SR, MAS2_I|MAS2_G,
0, 9, BOOKE_PAGESZ_256K, 1),
#endif
#ifdef CONFIG_SYS_NAND_BASE_PHYS
SET_TLB_ENTRY(1, CONFIG_SYS_NAND_BASE, CONFIG_SYS_NAND_BASE_PHYS,
MAS3_SX|MAS3_SW|MAS3_SR, MAS2_I|MAS2_G,
0, 5, BOOKE_PAGESZ_1M, 1),
#endif
};
int num_tlb_entries = ARRAY_SIZE(tlb_table);
@@ -0,0 +1,14 @@
if TARGET_C29XPCIE
config SYS_BOARD
default "c29xpcie"
config SYS_VENDOR
default "freescale"
config SYS_CONFIG_NAME
default "C29XPCIE"
source "board/freescale/common/Kconfig"
endif
@@ -0,0 +1,10 @@
C29XPCIE BOARD
M: Po Liu <po.liu@nxp.com>
S: Maintained
F: board/freescale/c29xpcie/
F: include/configs/C29XPCIE.h
F: configs/C29XPCIE_defconfig
F: configs/C29XPCIE_NAND_defconfig
F: configs/C29XPCIE_SPIFLASH_defconfig
F: configs/C29XPCIE_NOR_SECBOOT_defconfig
F: configs/C29XPCIE_SPIFLASH_SECBOOT_defconfig
@@ -0,0 +1,25 @@
# SPDX-License-Identifier: GPL-2.0+
#
# Copyright 2013 Freescale Semiconductor, Inc.
#
MINIMAL=
ifdef CONFIG_SPL_BUILD
ifdef CONFIG_SPL_INIT_MINIMAL
MINIMAL=y
endif
endif
ifdef MINIMAL
obj-y += spl_minimal.o
else
ifdef CONFIG_SPL_BUILD
obj-y += spl.o
endif
obj-y += c29xpcie.o
obj-y += cpld.o
obj-y += ddr.o
endif
obj-y += law.o
obj-y += tlb.o
@@ -0,0 +1,100 @@
Overview
=========
C29XPCIE board is a series of Freescale PCIe add-in cards to perform
as public key crypto accelerator or secure key management module.
It includes C293PCIE board, C293PCIE board and C291PCIE board.
The Freescale C29x family is a high performance crypto co-processor.
It combines a single e500v2 core with necessary SEC engines.
(maximum core frequency 1000/1200 MHz).
The C29xPCIE board features are as follows:
Memory subsystem:
- 512Mbyte unbuffered DDR3 SDRAM discrete devices (32-bit bus)
- 64 Mbyte NOR flash single-chip memory
- 4 Gbyte NAND flash memory
- 1 Mbit AT24C1024 I2C EEPROM
- 16 Mbyte SPI memory
Interfaces:
- 10/100/1000 BaseT Ethernet ports:
- eTSEC1, RGMII: one 10/100/1000 port
- eTSEC2, RGMII: one 10/100/1000 port
- DUART interface:
- DUART interface: supports two UARTs up to 115200 bps for
console display
Board connectors:
- Mini-ITX power supply connector
- JTAG/COP for debugging
Physical Memory Map on C29xPCIE
===============================
Address Start Address End Memory type
0x0_0000_0000 - 0x0_1fff_ffff 512MB DDR
0xc_0000_0000 - 0xc_8fff_ffff 256MB PCIE memory
0xf_ec00_0000 - 0xf_efff_ffff 64MB NOR flash
0xf_ffb0_0000 - 0xf_ffb7_ffff 512KB SRAM
0xf_ffc0_0000 - 0xf_ffc0_ffff 64KB PCIE IO
0xf_ffdf_0000 - 0xf_ffdf_0fff 4KB CPLD
0xf_ffe0_0000 - 0xf_ffef_ffff 1MB CCSR
Serial Port Configuration on C29xPCIE
=====================================
Configure the serial port of the attached computer with the following values:
-Data rate: 115200 bps
-Number of data bits: 8
-Parity: None
-Number of Stop bits: 1
-Flow Control: Hardware/None
Settings of DIP-switch
======================
SW5[1:4]= 1111 and SW5[6]=0 for boot from 16bit NOR flash
SW5[1:4]= 0110 and SW5[6]=0 for boot from SPI flash
Note: 1 stands for 'off', 0 stands for 'on'
Build and program U-Boot to NOR flash
==================================
1. Build u-boot.bin image example:
export ARCH=powerpc
export CROSS_COMPILE=/your_path/powerpc-linux-gnu-
make C293PCIE
2. Program u-boot.bin into NOR flash
=> tftp $loadaddr $uboot
=> protect off eff40000 +$filesize
=> erase eff40000 +$filesize
=> cp.b $loadaddr eff40000 $filesize
3. Check SW5[1:4]= 1111 and SW5[6]=0, then power on.
Alternate NOR bank
==================
There are four banks in C29XPCIE board, example to change bank booting:
1. Program u-boot.bin into alternate NOR bank
=> tftp $loadaddr $uboot
=> protect off e9f40000 +$filesize
=> erase e9f40000 +$filesize
=> cp.b $loadaddr e9f40000 $filesize
2. Switch to alternate NOR bank
=> cpld_cmd reset altbank [bank]
- [bank] bank value select 1-4
- bank 1 on the flash 0x0000000~0x0ffffff
- bank 2 on the flash 0x1000000~0x1ffffff
- bank 3 on the flash 0x2000000~0x2ffffff
- bank 4 on the flash 0x3000000~0x3ffffff
or set SW5[7]= ON/OFF and SW5[7]= ON/OFF, then power on again.
Build and program U-Boot to SPI flash
==================================
1. Build u-boot-spi.bin image
make C29xPCIE_SPIFLASH_config; make
Need the boot_format tool to generate u-boot-spi.bin from the u-boot.bin.
2. Program u-boot-spi.bin into SPI flash
=> tftp $loadaddr $uboot-spi
=> sf erase 0 100000
=> sf write $loadaddr 0 $filesize
3. Check SW5[1:4]= 0110 and SW5[6]=0, then power on.
@@ -0,0 +1,157 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright 2013 Freescale Semiconductor, Inc.
*/
#include <common.h>
#include <init.h>
#include <asm/processor.h>
#include <asm/mmu.h>
#include <asm/cache.h>
#include <asm/immap_85xx.h>
#include <asm/io.h>
#include <env.h>
#include <miiphy.h>
#include <linux/libfdt.h>
#include <fdt_support.h>
#include <fsl_mdio.h>
#include <tsec.h>
#include <mmc.h>
#include <netdev.h>
#include <pci.h>
#include <fsl_ifc.h>
#include <asm/fsl_pci.h>
#include "cpld.h"
DECLARE_GLOBAL_DATA_PTR;
int checkboard(void)
{
struct cpu_type *cpu = gd->arch.cpu;
struct cpld_data *cpld_data = (void *)(CONFIG_SYS_CPLD_BASE);
printf("Board: %sPCIe, ", cpu->name);
printf("CPLD Ver: 0x%02x\n", in_8(&cpld_data->cpldver));
return 0;
}
int board_early_init_f(void)
{
struct fsl_ifc ifc = {(void *)CONFIG_SYS_IFC_ADDR, (void *)NULL};
/* Clock configuration to access CPLD using IFC(GPCM) */
setbits_be32(&ifc.gregs->ifc_gcr, 1 << IFC_GCR_TBCTL_TRN_TIME_SHIFT);
return 0;
}
int board_early_init_r(void)
{
const unsigned long flashbase = CONFIG_SYS_FLASH_BASE;
int flash_esel = find_tlb_idx((void *)flashbase, 1);
/*
* Remap Boot flash region to caching-inhibited
* so that flash can be erased properly.
*/
/* Flush d-cache and invalidate i-cache of any FLASH data */
flush_dcache();
invalidate_icache();
if (flash_esel == -1) {
/* very unlikely unless something is messed up */
puts("Error: Could not find TLB for FLASH BASE\n");
flash_esel = 1; /* give our best effort to continue */
} else {
/* invalidate existing TLB entry for flash */
disable_tlb(flash_esel);
}
set_tlb(1, flashbase, CONFIG_SYS_FLASH_BASE_PHYS,
MAS3_SW|MAS3_SR, MAS2_I|MAS2_G,
0, flash_esel, BOOKE_PAGESZ_64M, 1);
return 0;
}
#ifdef CONFIG_PCI
void pci_init_board(void)
{
fsl_pcie_init_board(0);
}
#endif /* ifdef CONFIG_PCI */
int board_eth_init(bd_t *bis)
{
#ifdef CONFIG_TSEC_ENET
struct fsl_pq_mdio_info mdio_info;
struct tsec_info_struct tsec_info[2];
int num = 0;
#ifdef CONFIG_TSEC1
SET_STD_TSEC_INFO(tsec_info[num], 1);
num++;
#endif
#ifdef CONFIG_TSEC2
SET_STD_TSEC_INFO(tsec_info[num], 2);
num++;
#endif
if (!num) {
printf("No TSECs initialized\n");
return 0;
}
/* Register 1G MDIO bus */
mdio_info.regs = (struct tsec_mii_mng *)CONFIG_SYS_MDIO_BASE_ADDR;
mdio_info.name = DEFAULT_MII_NAME;
fsl_pq_mdio_init(bis, &mdio_info);
tsec_eth_init(bis, tsec_info, num);
#endif
return pci_eth_init(bis);
}
#if defined(CONFIG_OF_BOARD_SETUP)
void fdt_del_sec(void *blob, int offset)
{
int nodeoff = 0;
while ((nodeoff = fdt_node_offset_by_compat_reg(blob, "fsl,sec-v6.0",
CONFIG_SYS_CCSRBAR_PHYS + CONFIG_SYS_FSL_SEC_OFFSET
+ offset * CONFIG_SYS_FSL_SEC_IDX_OFFSET)) >= 0) {
fdt_del_node(blob, nodeoff);
offset++;
}
}
int ft_board_setup(void *blob, bd_t *bd)
{
phys_addr_t base;
phys_size_t size;
struct cpu_type *cpu;
cpu = gd->arch.cpu;
ft_cpu_setup(blob, bd);
base = env_get_bootm_low();
size = env_get_bootm_size();
#if defined(CONFIG_PCI)
FT_FSL_PCI_SETUP;
#endif
fdt_fixup_memory(blob, (u64)base, (u64)size);
if (cpu->soc_ver == SVR_C291)
fdt_del_sec(blob, 1);
else if (cpu->soc_ver == SVR_C292)
fdt_del_sec(blob, 2);
return 0;
}
#endif
@@ -0,0 +1,132 @@
// SPDX-License-Identifier: GPL-2.0+
/**
* Copyright 2013 Freescale Semiconductor
* Author: Mingkai Hu <Mingkai.hu@freescale.com>
* Po Liu <Po.Liu@freescale.com>
*
* This file provides support for the board-specific CPLD used on some Freescale
* reference boards.
*
* The following macros need to be defined:
*
* CONFIG_SYS_CPLD_BASE - The virtual address of the base of the
* CPLD register map
*
*/
#include <common.h>
#include <command.h>
#include <asm/io.h>
#include "cpld.h"
/**
* Set the boot bank to the alternate bank
*/
void cpld_set_altbank(u8 banksel)
{
struct cpld_data *cpld_data = (void *)(CONFIG_SYS_CPLD_BASE);
u8 reg11;
reg11 = in_8(&cpld_data->flhcsr);
switch (banksel) {
case 1:
out_8(&cpld_data->flhcsr, (reg11 & CPLD_BANKSEL_MASK)
| CPLD_BANKSEL_EN | CPLD_SELECT_BANK1);
break;
case 2:
out_8(&cpld_data->flhcsr, (reg11 & CPLD_BANKSEL_MASK)
| CPLD_BANKSEL_EN | CPLD_SELECT_BANK2);
break;
case 3:
out_8(&cpld_data->flhcsr, (reg11 & CPLD_BANKSEL_MASK)
| CPLD_BANKSEL_EN | CPLD_SELECT_BANK3);
break;
case 4:
out_8(&cpld_data->flhcsr, (reg11 & CPLD_BANKSEL_MASK)
| CPLD_BANKSEL_EN | CPLD_SELECT_BANK4);
break;
default:
printf("Invalid value! [1-4]\n");
return;
}
udelay(100);
do_reset(NULL, 0, 0, NULL);
}
/**
* Set the boot bank to the default bank
*/
void cpld_set_defbank(void)
{
cpld_set_altbank(4);
}
#ifdef DEBUG
static void cpld_dump_regs(void)
{
struct cpld_data *cpld_data = (void *)(CONFIG_SYS_CPLD_BASE);
printf("chipid1 = 0x%02x\n", in_8(&cpld_data->chipid1));
printf("chipid2 = 0x%02x\n", in_8(&cpld_data->chipid2));
printf("hwver = 0x%02x\n", in_8(&cpld_data->hwver));
printf("cpldver = 0x%02x\n", in_8(&cpld_data->cpldver));
printf("rstcon = 0x%02x\n", in_8(&cpld_data->rstcon));
printf("flhcsr = 0x%02x\n", in_8(&cpld_data->flhcsr));
printf("wdcsr = 0x%02x\n", in_8(&cpld_data->wdcsr));
printf("wdkick = 0x%02x\n", in_8(&cpld_data->wdkick));
printf("fancsr = 0x%02x\n", in_8(&cpld_data->fancsr));
printf("ledcsr = 0x%02x\n", in_8(&cpld_data->ledcsr));
printf("misc = 0x%02x\n", in_8(&cpld_data->misccsr));
printf("bootor = 0x%02x\n", in_8(&cpld_data->bootor));
printf("bootcfg1 = 0x%02x\n", in_8(&cpld_data->bootcfg1));
printf("bootcfg2 = 0x%02x\n", in_8(&cpld_data->bootcfg2));
printf("bootcfg3 = 0x%02x\n", in_8(&cpld_data->bootcfg3));
printf("bootcfg4 = 0x%02x\n", in_8(&cpld_data->bootcfg4));
putc('\n');
}
#endif
#ifndef CONFIG_SPL_BUILD
int cpld_cmd(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
{
int rc = 0;
unsigned char value;
if (argc <= 1)
return cmd_usage(cmdtp);
if (strcmp(argv[1], "reset") == 0) {
if (!strcmp(argv[2], "altbank") && argv[3]) {
value = (u8)simple_strtoul(argv[3], NULL, 16);
cpld_set_altbank(value);
} else if (!argv[2])
cpld_set_defbank();
else
cmd_usage(cmdtp);
#ifdef DEBUG
} else if (strcmp(argv[1], "dump") == 0) {
cpld_dump_regs();
#endif
} else
rc = cmd_usage(cmdtp);
return rc;
}
U_BOOT_CMD(
cpld_cmd, CONFIG_SYS_MAXARGS, 1, cpld_cmd,
"Reset the board using the CPLD sequencer",
"reset - hard reset to default bank 4\n"
"cpld_cmd reset altbank [bank]- reset to alternate bank\n"
" - [bank] bank value select 1-4\n"
" - bank 1 on the flash 0x0000000~0x0ffffff\n"
" - bank 2 on the flash 0x1000000~0x1ffffff\n"
" - bank 3 on the flash 0x2000000~0x2ffffff\n"
" - bank 4 on the flash 0x3000000~0x3ffffff\n"
#ifdef DEBUG
"cpld_cmd dump - display the CPLD registers\n"
#endif
);
#endif
@@ -0,0 +1,39 @@
/* SPDX-License-Identifier: GPL-2.0+ */
/**
* Copyright 2013 Freescale Semiconductor
* Author: Mingkai Hu <Mingkai.Hu@freescale.com>
* Po Liu <Po.Liu@freescale.com>
*
* This file provides support for the ngPIXIS, a board-specific FPGA used on
* some Freescale reference boards.
*/
/*
* CPLD register set. Feel free to add board-specific #ifdefs where necessary.
*/
struct cpld_data {
u8 chipid1; /* 0x0 - CPLD Chip ID1 Register */
u8 chipid2; /* 0x1 - CPLD Chip ID2 Register */
u8 hwver; /* 0x2 - Hardware Version Register */
u8 cpldver; /* 0x3 - Software Version Register */
u8 res[12];
u8 rstcon; /* 0x10 - Reset control register */
u8 flhcsr; /* 0x11 - Flash control and status Register */
u8 wdcsr; /* 0x12 - Watchdog control and status Register */
u8 wdkick; /* 0x13 - Watchdog kick Register */
u8 fancsr; /* 0x14 - Fan control and status Register */
u8 ledcsr; /* 0x15 - LED control and status Register */
u8 misccsr; /* 0x16 - Misc control and status Register */
u8 bootor; /* 0x17 - Boot configure override Register */
u8 bootcfg1; /* 0x18 - Boot configure 1 Register */
u8 bootcfg2; /* 0x19 - Boot configure 2 Register */
u8 bootcfg3; /* 0x1a - Boot configure 3 Register */
u8 bootcfg4; /* 0x1b - Boot configure 4 Register */
};
#define CPLD_BANKSEL_EN 0x02
#define CPLD_BANKSEL_MASK 0x3f
#define CPLD_SELECT_BANK1 0xc0
#define CPLD_SELECT_BANK2 0x80
#define CPLD_SELECT_BANK3 0x40
#define CPLD_SELECT_BANK4 0x00
@@ -0,0 +1,106 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright 2013 Freescale Semiconductor, Inc.
*/
#include <common.h>
#include <i2c.h>
#include <asm/fsl_law.h>
#include <fsl_ddr_sdram.h>
#include <fsl_ddr_dimm_params.h>
#include "cpld.h"
#define C29XPCIE_HARDWARE_REVA 0x40
/*
* Micron MT41J128M16HA-15E
* */
dimm_params_t ddr_raw_timing = {
.n_ranks = 1,
.rank_density = 536870912u,
.capacity = 536870912u,
.primary_sdram_width = 32,
.ec_sdram_width = 8,
.registered_dimm = 0,
.mirrored_dimm = 0,
.n_row_addr = 14,
.n_col_addr = 10,
.n_banks_per_sdram_device = 8,
.edc_config = 2,
.burst_lengths_bitmask = 0x0c,
.tckmin_x_ps = 1650,
.caslat_x = 0x7e << 4, /* 5,6,7,8,9,10 */
.taa_ps = 14050,
.twr_ps = 15000,
.trcd_ps = 13500,
.trrd_ps = 75000,
.trp_ps = 13500,
.tras_ps = 40000,
.trc_ps = 49500,
.trfc_ps = 160000,
.twtr_ps = 75000,
.trtp_ps = 75000,
.refresh_rate_ps = 7800000,
.tfaw_ps = 30000,
};
int fsl_ddr_get_dimm_params(dimm_params_t *pdimm,
unsigned int controller_number,
unsigned int dimm_number)
{
const char dimm_model[] = "Fixed DDR on board";
if ((controller_number == 0) && (dimm_number == 0)) {
memcpy(pdimm, &ddr_raw_timing, sizeof(dimm_params_t));
memset(pdimm->mpart, 0, sizeof(pdimm->mpart));
memcpy(pdimm->mpart, dimm_model, sizeof(dimm_model) - 1);
}
return 0;
}
void fsl_ddr_board_options(memctl_options_t *popts,
dimm_params_t *pdimm,
unsigned int ctrl_num)
{
struct cpld_data *cpld_data = (void *)(CONFIG_SYS_CPLD_BASE);
int i;
popts->clk_adjust = 4;
popts->cpo_override = 0x1f;
popts->write_data_delay = 4;
popts->half_strength_driver_enable = 1;
popts->bstopre = 0x3cf;
popts->quad_rank_present = 1;
popts->rtt_override = 1;
popts->rtt_override_value = 1;
popts->dynamic_power = 1;
/* Write leveling override */
popts->wrlvl_en = 1;
popts->wrlvl_override = 1;
popts->wrlvl_sample = 0xf;
popts->wrlvl_start = 0x4;
popts->trwt_override = 1;
popts->trwt = 0;
if (in_8(&cpld_data->hwver) == C29XPCIE_HARDWARE_REVA)
popts->ecc_mode = 0;
for (i = 0; i < CONFIG_CHIP_SELECTS_PER_CTRL; i++) {
popts->cs_local_opts[i].odt_rd_cfg = FSL_DDR_ODT_NEVER;
popts->cs_local_opts[i].odt_wr_cfg = FSL_DDR_ODT_CS;
}
}
void get_spd(generic_spd_eeprom_t *spd, u8 i2c_address)
{
int ret = i2c_read(i2c_address, 0, 2, (uint8_t *)spd,
sizeof(generic_spd_eeprom_t));
if (ret) {
printf("DDR: failed to read SPD from address %u\n",
i2c_address);
memset(spd, 0, sizeof(generic_spd_eeprom_t));
}
}
@@ -0,0 +1,18 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright 2013 Freescale Semiconductor, Inc.
*/
#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_64M, LAW_TRGT_IF_IFC),
SET_LAW(CONFIG_SYS_CPLD_BASE_PHYS, LAW_SIZE_64K, LAW_TRGT_IF_IFC),
SET_LAW(CONFIG_SYS_NAND_BASE_PHYS, LAW_SIZE_64K, LAW_TRGT_IF_IFC),
SET_LAW(CONFIG_SYS_PLATFORM_SRAM_BASE_PHYS, LAW_SIZE_512K,
LAW_TRGT_IF_PLATFORM_SRAM),
};
int num_law_entries = ARRAY_SIZE(law_table);
@@ -0,0 +1,79 @@
// SPDX-License-Identifier: GPL-2.0+
/* Copyright 2013 Freescale Semiconductor, Inc.
*/
#include <common.h>
#include <console.h>
#include <env_internal.h>
#include <ns16550.h>
#include <malloc.h>
#include <mmc.h>
#include <nand.h>
#include <i2c.h>
DECLARE_GLOBAL_DATA_PTR;
phys_size_t get_effective_memsize(void)
{
return CONFIG_SYS_L2_SIZE;
}
void board_init_f(ulong bootflag)
{
u32 plat_ratio;
ccsr_gur_t *gur = (void *)CONFIG_SYS_MPC85xx_GUTS_ADDR;
console_init_f();
/* initialize selected port with appropriate baud rate */
plat_ratio = in_be32(&gur->porpllsr) & MPC85xx_PORPLLSR_PLAT_RATIO;
plat_ratio >>= 1;
gd->bus_clk = CONFIG_SYS_CLK_FREQ * plat_ratio;
NS16550_init((NS16550_t)CONFIG_SYS_NS16550_COM1,
gd->bus_clk / 16 / CONFIG_BAUDRATE);
/* copy code to RAM and jump to it - this should not return */
/* NOTE - code has to be copied out of NAND buffer before
* other blocks can be read.
*/
relocate_code(CONFIG_SPL_RELOC_STACK, 0, CONFIG_SPL_RELOC_TEXT_BASE);
}
void board_init_r(gd_t *gd, ulong dest_addr)
{
/* Pointer is writable since we allocated a register for it */
gd = (gd_t *)CONFIG_SPL_GD_ADDR;
bd_t *bd;
memset(gd, 0, sizeof(gd_t));
bd = (bd_t *)(CONFIG_SPL_GD_ADDR + sizeof(gd_t));
memset(bd, 0, sizeof(bd_t));
gd->bd = bd;
bd->bi_memstart = CONFIG_SYS_INIT_L2_ADDR;
bd->bi_memsize = CONFIG_SYS_L2_SIZE;
arch_cpu_init();
get_clocks();
mem_malloc_init(CONFIG_SPL_RELOC_MALLOC_ADDR,
CONFIG_SPL_RELOC_MALLOC_SIZE);
gd->flags |= GD_FLG_FULL_MALLOC_INIT;
/* relocate environment function pointers etc. */
nand_spl_load_image(CONFIG_ENV_OFFSET, CONFIG_ENV_SIZE,
(uchar *)SPL_ENV_ADDR);
gd->env_addr = (ulong)(SPL_ENV_ADDR);
gd->env_valid = ENV_VALID;
i2c_init_all();
dram_init();
#ifdef CONFIG_SPL_NAND_BOOT
puts("TPL\n");
#else
puts("SPL\n");
#endif
nand_boot();
}
@@ -0,0 +1,62 @@
// SPDX-License-Identifier: GPL-2.0+
/* Copyright 2013 Freescale Semiconductor, Inc.
*/
#include <common.h>
#include <mpc85xx.h>
#include <asm/io.h>
#include <ns16550.h>
#include <nand.h>
#include <asm/mmu.h>
#include <asm/immap_85xx.h>
#include <asm/fsl_law.h>
#include <asm/global_data.h>
DECLARE_GLOBAL_DATA_PTR;
void board_init_f(ulong bootflag)
{
u32 plat_ratio;
ccsr_gur_t *gur = (void *)CONFIG_SYS_MPC85xx_GUTS_ADDR;
#if defined(CONFIG_SYS_NAND_BR_PRELIM) && defined(CONFIG_SYS_NAND_OR_PRELIM)
set_lbc_br(0, CONFIG_SYS_NAND_BR_PRELIM);
set_lbc_or(0, CONFIG_SYS_NAND_OR_PRELIM);
#endif
/* initialize selected port with appropriate baud rate */
plat_ratio = in_be32(&gur->porpllsr) & MPC85xx_PORPLLSR_PLAT_RATIO;
plat_ratio >>= 1;
gd->bus_clk = CONFIG_SYS_CLK_FREQ * plat_ratio;
NS16550_init((NS16550_t)CONFIG_SYS_NS16550_COM1,
gd->bus_clk / 16 / CONFIG_BAUDRATE);
puts("\nNAND boot...\n");
/* copy code to RAM and jump to it - this should not return */
/* NOTE - code has to be copied out of NAND buffer before
* other blocks can be read.
*/
relocate_code(CONFIG_SPL_RELOC_STACK, 0, CONFIG_SPL_RELOC_TEXT_BASE);
}
void board_init_r(gd_t *gd, ulong dest_addr)
{
puts("SPL\n");
nand_boot();
}
void putc(char c)
{
if (c == '\n')
NS16550_putc((NS16550_t)CONFIG_SYS_NS16550_COM1, '\r');
NS16550_putc((NS16550_t)CONFIG_SYS_NS16550_COM1, c);
}
void puts(const char *str)
{
while (*str)
putc(*str++);
}
@@ -0,0 +1,84 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright 2013 Freescale Semiconductor, Inc.
*/
#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,
MAS3_SX|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 + 4 * 1024,
MAS3_SX|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 + 8 * 1024,
MAS3_SX|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 + 12 * 1024,
MAS3_SX|MAS3_SW|MAS3_SR, 0,
0, 0, BOOKE_PAGESZ_4K, 0),
/* TLB 1 */
SET_TLB_ENTRY(1, CONFIG_SYS_CCSRBAR, CONFIG_SYS_CCSRBAR_PHYS,
MAS3_SW|MAS3_SR, MAS2_I|MAS2_G,
0, 0, BOOKE_PAGESZ_1M, 1),
#ifndef CONFIG_SPL_BUILD
SET_TLB_ENTRY(1, CONFIG_SYS_FLASH_BASE, CONFIG_SYS_FLASH_BASE_PHYS,
MAS3_SX|MAS3_SR, MAS2_W|MAS2_G,
0, 1, BOOKE_PAGESZ_64M, 1),
#ifdef CONFIG_PCI
SET_TLB_ENTRY(1, CONFIG_SYS_PCIE1_MEM_VIRT, CONFIG_SYS_PCIE1_MEM_PHYS,
MAS3_SW|MAS3_SR, MAS2_I|MAS2_G,
0, 2, BOOKE_PAGESZ_256M, 1),
SET_TLB_ENTRY(1, CONFIG_SYS_PCIE1_IO_VIRT, CONFIG_SYS_PCIE1_IO_PHYS,
MAS3_SW|MAS3_SR, MAS2_I|MAS2_G,
0, 3, BOOKE_PAGESZ_256K, 1),
#endif
#endif
SET_TLB_ENTRY(1, CONFIG_SYS_CPLD_BASE, CONFIG_SYS_CPLD_BASE_PHYS,
MAS3_SW|MAS3_SR, MAS2_I|MAS2_G,
0, 4, BOOKE_PAGESZ_64K, 1),
SET_TLB_ENTRY(1, CONFIG_SYS_NAND_BASE, CONFIG_SYS_NAND_BASE_PHYS,
MAS3_SX|MAS3_SW|MAS3_SR, MAS2_I|MAS2_G,
0, 5, BOOKE_PAGESZ_64K, 1),
SET_TLB_ENTRY(1, CONFIG_SYS_PLATFORM_SRAM_BASE,
CONFIG_SYS_PLATFORM_SRAM_BASE_PHYS,
MAS3_SX|MAS3_SW|MAS3_SR, 0,
0, 6, BOOKE_PAGESZ_256K, 1),
SET_TLB_ENTRY(1, CONFIG_SYS_PLATFORM_SRAM_BASE + 0x40000,
CONFIG_SYS_PLATFORM_SRAM_BASE_PHYS + 0x40000,
MAS3_SX|MAS3_SW|MAS3_SR, 0,
0, 7, BOOKE_PAGESZ_256K, 1),
#if defined(CONFIG_SYS_RAMBOOT) || \
(defined(CONFIG_SPL) && !defined(CONFIG_SPL_BUILD))
SET_TLB_ENTRY(1, CONFIG_SYS_DDR_SDRAM_BASE,
CONFIG_SYS_DDR_SDRAM_BASE,
MAS3_SX|MAS3_SW|MAS3_SR, MAS2_M,
0, 8, BOOKE_PAGESZ_256M, 1),
SET_TLB_ENTRY(1, CONFIG_SYS_DDR_SDRAM_BASE + 0x10000000,
CONFIG_SYS_DDR_SDRAM_BASE + 0x10000000,
MAS3_SX|MAS3_SW|MAS3_SR, MAS2_M,
0, 9, BOOKE_PAGESZ_256M, 1),
#endif
#ifdef CONFIG_SYS_INIT_L2_ADDR
SET_TLB_ENTRY(1, CONFIG_SYS_INIT_L2_ADDR, CONFIG_SYS_INIT_L2_ADDR_PHYS,
MAS3_SX|MAS3_SW|MAS3_SR, MAS2_G,
0, 12, BOOKE_PAGESZ_256K, 1)
#endif
};
int num_tlb_entries = ARRAY_SIZE(tlb_table);
@@ -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, &reg);
printf("PMIC: PFUZE100 ID=0x%02x\n", reg);
/* Set SW1AB stanby volage to 0.975V */
pmic_reg_read(p, PFUZE100_SW1ABSTBY, &reg);
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);
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);
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);
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_ */
@@ -0,0 +1,59 @@
if TARGET_P3041DS
config SYS_BOARD
default "corenet_ds"
config SYS_VENDOR
default "freescale"
config SYS_CONFIG_NAME
default "P3041DS"
source "board/freescale/common/Kconfig"
endif
if TARGET_P4080DS
config SYS_BOARD
default "corenet_ds"
config SYS_VENDOR
default "freescale"
config SYS_CONFIG_NAME
default "P4080DS"
source "board/freescale/common/Kconfig"
endif
if TARGET_P5020DS
config SYS_BOARD
default "corenet_ds"
config SYS_VENDOR
default "freescale"
config SYS_CONFIG_NAME
default "P5020DS"
source "board/freescale/common/Kconfig"
endif
if TARGET_P5040DS
config SYS_BOARD
default "corenet_ds"
config SYS_VENDOR
default "freescale"
config SYS_CONFIG_NAME
default "P5040DS"
source "board/freescale/common/Kconfig"
endif

Some files were not shown because too many files have changed in this diff Show More