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,34 @@
if TARGET_LS2080AQDS
config SYS_BOARD
default "ls2080aqds"
config SYS_VENDOR
default "freescale"
config SYS_SOC
default "fsl-layerscape"
config SYS_CONFIG_NAME
default "ls2080aqds"
if FSL_LS_PPA
config SYS_LS_PPA_FW_ADDR
hex "PPA Firmware Addr"
default 0x20400000 if SYS_LS_PPA_FW_IN_XIP && QSPI_BOOT
default 0x580400000 if SYS_LS_PPA_FW_IN_XIP
default 0x400000 if SYS_LS_PPA_FW_IN_MMC || SYS_LS_PPA_FW_IN_NAND
if CHAIN_OF_TRUST
config SYS_LS_PPA_ESBC_ADDR
hex "PPA Firmware HDR Addr"
default 0x20680000 if SYS_LS_PPA_FW_IN_XIP && QSPI_BOOT
default 0x580680000 if SYS_LS_PPA_FW_IN_XIP
default 0x680000 if SYS_LS_PPA_FW_IN_MMC || SYS_LS_PPA_FW_IN_NAND
endif
endif
source "board/freescale/common/Kconfig"
endif
@@ -0,0 +1,17 @@
LS2080A BOARD
M: Prabhakar Kushwaha <prabhakar.kushwaha@nxp.com>, Priyanka Jain <priyanka.jain@nxp.com>
M: Rajesh Bhagat <rajesh.bhagat@nxp.com>
S: Maintained
F: board/freescale/ls2080aqds/
F: board/freescale/ls2080a/ls2080aqds.c
F: include/configs/ls2080aqds.h
F: configs/ls2080aqds_defconfig
F: configs/ls2080aqds_nand_defconfig
F: configs/ls2080aqds_qspi_defconfig
F: configs/ls2080aqds_sdcard_defconfig
F: configs/ls2088aqds_tfa_defconfig
LS2080A_SECURE_BOOT BOARD
#M: Saksham Jain <saksham.jain@nxp.freescale.com>
S: Orphan (since 2018-05)
F: configs/ls2080aqds_SECURE_BOOT_defconfig
@@ -0,0 +1,7 @@
# SPDX-License-Identifier: GPL-2.0+
#
# Copyright 2015 Freescale Semiconductor
obj-y += ls2080aqds.o
obj-y += ddr.o
obj-y += eth.o
@@ -0,0 +1,216 @@
Overview
--------
The LS2080A Development System (QDS) is a high-performance computing,
evaluation, and development platform that supports the QorIQ LS2080A
and LS2088A Layerscape Architecture processor. The LS2080AQDS provides
validation and SW development platform for the Freescale LS2080A, LS2088A
processor series, with a complete debugging environment.
LS2080A, LS2088A SoC Overview
--------------------
Please refer arch/arm/cpu/armv8/fsl-layerscape/doc/README.soc for LS2080A,
LS2088A SoC overview.
LS2080AQDS board Overview
-----------------------
- SERDES Connections, 16 lanes supporting:
- PCI Express - 3.0
- SGMII, SGMII 2.5
- QSGMII
- SATA 3.0
- XAUI
- XFI
- DDR Controller
- Two ports of 72-bits (8-bits ECC) DDR4. Each port supports four
chip-selects and two DIMM connectors. Support is up to 2133MT/s.
- One port of 40-bits (8-bits ECC) DDR4 which supports four chip-selects
and two DIMM connectors. Support is up to 1600MT/s.
-IFC/Local Bus
- IFC rev. 2.0 implementation supporting Little Endian connection scheme.
- One in-socket 128 MB NOR flash 16-bit data bus
- One 512 MB NAND flash with ECC support
- IFC Test Port
- PromJet Port
- FPGA connection
- USB 3.0
- Two high speed USB 3.0 ports
- First USB 3.0 port configured as Host with Type-A connector
- Second USB 3.0 port configured as OTG with micro-AB connector
- SDHC: PCIe x1 Right Angle connector for supporting following cards
- 1/4-/8-bit SD/MMC Legacy CARD supporting 3.3V devices only
- 1-/4-/8-bit SD/MMC Card supporting 1.8V devices only
- 4-bit eMMC Card Rev 4.4 (1.8V only)
- 8-bit eMMC Card Rev 4.5 (1.8V only)
- SD Card Rev 2.0 and Rev 3.0
- DSPI: 3 high-speed flash Memory for storage
- 16 MB high-speed flash Memory for boot code and storage (up to 108MHz)
- 8 MB high-speed flash Memory (up to 104 MHz)
- 512 MB low-speed flash Memory (up to 40 MHz)
- QSPI: via NAND/QSPI Card
- 4 I2C controllers
- Two SATA onboard connectors
- UART
- Two 4-pin (HW control) or four 2-pin (SW control) serial ports at up to 115.2 Kbit/s
- Two DB9 D-Type connectors supporting one Serial port each
- ARM JTAG support
Memory map from core's view
----------------------------
0x00_0000_0000 .. 0x00_000F_FFFF Boot Rom
0x00_0100_0000 .. 0x00_0FFF_FFFF CCSR
0x00_1800_0000 .. 0x00_181F_FFFF OCRAM
0x00_3000_0000 .. 0x00_3FFF_FFFF IFC region #1
0x00_8000_0000 .. 0x00_FFFF_FFFF DDR region #1
0x05_1000_0000 .. 0x05_FFFF_FFFF IFC region #2
0x80_8000_0000 .. 0xFF_FFFF_FFFF DDR region #2
Other addresses are either reserved, or not used directly by U-Boot.
This list should be updated when more addresses are used.
IFC region map from core's view
-------------------------------
During boot i.e. IFC Region #1:-
0x30000000 - 0x37ffffff : 128MB : NOR flash
0x38000000 - 0x3BFFFFFF : 64MB : Promjet
0x3C000000 - 0x40000000 : 64MB : FPGA etc
After relocate to DDR i.e. IFC Region #2:-
0x5_1000_0000..0x5_1fff_ffff Memory Hole
0x5_2000_0000..0x5_3fff_ffff IFC CSx (FPGA, NAND and others 512MB)
0x5_4000_0000..0x5_7fff_ffff ASIC or others 1GB
0x5_8000_0000..0x5_bfff_ffff IFC CS0 1GB (NOR/Promjet)
0x5_C000_0000..0x5_ffff_ffff IFC CS1 1GB (NOR/Promjet)
Booting Options
---------------
a) Promjet Boot
b) NOR boot
c) NAND boot
d) SD boot
e) QSPI boot
Memory map for NOR boot
-------------------------
Image Flash Offset
RCW+PBI 0x00000000
Boot firmware (U-Boot) 0x00100000
Boot firmware Environment 0x00300000
PPA firmware 0x00400000
Secure Headers 0x00600000
DPAA2 MC 0x00A00000
DPAA2 DPL 0x00D00000
DPAA2 DPC 0x00E00000
Kernel.itb 0x01000000
Memory map for SD boot
-------------------------
Image Flash Offset SD Card
Start Block No.
RCW+PBI 0x00000000 0x00008
Boot firmware (U-Boot) 0x00100000 0x00800
Boot firmware Environment 0x00300000 0x01800
PPA firmware 0x00400000 0x02000
DPAA2 MC 0x00A00000 0x05000
DPAA2 DPL 0x00D00000 0x06800
DPAA2 DPC 0x00E00000 0x07000
Kernel.itb 0x01000000 0x08000
Environment Variables
---------------------
- mcboottimeout: MC boot timeout in milliseconds. If this variable is not defined
the value CONFIG_SYS_LS_MC_BOOT_TIMEOUT_MS will be assumed.
- mcmemsize: MC DRAM block size. If this variable is not defined
the value CONFIG_SYS_LS_MC_DRAM_BLOCK_MIN_SIZE will be assumed.
Booting Linux flavors which do not support 48-bit VA (< Linux 3.18)
-------------------------------------------------------------------
One needs to use appropriate bootargs to boot Linux flavors which do
not support 48-bit VA (for e.g. < Linux 3.18) by appending mem=2048M, as shown
below:
=> setenv bootargs 'console=ttyS1,115200 root=/dev/ram
earlycon=uart8250,mmio,0x21c0600,115200 default_hugepagesz=2m hugepagesz=2m
hugepages=16 mem=2048M'
X-QSGMII-16PORT riser card
----------------------------
The X-QSGMII-16PORT is a 4xQSGMII/8xSGMII riser card with eighth SerDes
interfaces implemented in PCIe form factor board.
It supports following:
- Card can operate with up to 4 QSGMII lane simultaneously
- Card can operate with up to 8 SGMII lane simultaneously
Supported card configuration
- CSEL : ON ON ON ON
- MSEL1 : ON ON ON ON OFF OFF OFF OFF
- MSEL2 : OFF OFF OFF OFF ON ON ON ON
To enable this card: modify hwconfig to add "xqsgmii" variable.
Supported PHY addresses during SGMII:
#define XQSGMII_CARD_PHY1_PORT0_ADDR 0x0
#define XQSGMII_CARD_PHY1_PORT2_ADDR 0x2
#define XQSGMII_CARD_PHY2_PORT0_ADDR 0x4
#define XQSGMII_CARD_PHY2_PORT2_ADDR 0x6
#define XQSGMII_CARD_PHY3_PORT0_ADDR 0x8
#define XQSGMII_CARD_PHY3_PORT2_ADDR 0xa
#define XQSGMII_CARD_PHY4_PORT0_ADDR 0xc
#define XQSGMII_CARD_PHY4_PORT2_ADDR 0xe
Mapping DPMACx to PHY during SGMII
DPMAC1 -> PHY1-P0
DPMAC2 -> PHY2-P0
DPMAC3 -> PHY3-P0
DPMAC4 -> PHY4-P0
DPMAC5 -> PHY3-P2
DPMAC6 -> PHY1-P2
DPMAC7 -> PHY4-P1
DPMAC8 -> PHY2-P2
DPMAC9 -> PHY1-P0
DPMAC10 -> PHY2-P0
DPMAC11 -> PHY3-P0
DPMAC12 -> PHY4-P0
DPMAC13 -> PHY3-P2
DPMAC14 -> PHY1-P2
DPMAC15 -> PHY4-P1
DPMAC16 -> PHY2-P2
Supported PHY address during QSGMII
#define XQSGMII_CARD_PHY1_PORT0_ADDR 0x0
#define XQSGMII_CARD_PHY1_PORT1_ADDR 0x1
#define XQSGMII_CARD_PHY1_PORT2_ADDR 0x2
#define XQSGMII_CARD_PHY1_PORT3_ADDR 0x3
#define XQSGMII_CARD_PHY2_PORT0_ADDR 0x4
#define XQSGMII_CARD_PHY2_PORT1_ADDR 0x5
#define XQSGMII_CARD_PHY2_PORT2_ADDR 0x6
#define XQSGMII_CARD_PHY2_PORT3_ADDR 0x7
#define XQSGMII_CARD_PHY3_PORT0_ADDR 0x8
#define XQSGMII_CARD_PHY3_PORT1_ADDR 0x9
#define XQSGMII_CARD_PHY3_PORT2_ADDR 0xa
#define XQSGMII_CARD_PHY3_PORT3_ADDR 0xb
#define XQSGMII_CARD_PHY4_PORT0_ADDR 0xc
#define XQSGMII_CARD_PHY4_PORT1_ADDR 0xd
#define XQSGMII_CARD_PHY4_PORT2_ADDR 0xe
#define XQSGMII_CARD_PHY4_PORT3_ADDR 0xf
Mapping DPMACx to PHY during QSGMII
DPMAC1 -> PHY1-P3
DPMAC2 -> PHY1-P2
DPMAC3 -> PHY1-P1
DPMAC4 -> PHY1-P0
DPMAC5 -> PHY2-P3
DPMAC6 -> PHY2-P2
DPMAC7 -> PHY2-P1
DPMAC8 -> PHY2-P0
DPMAC9 -> PHY3-P0
DPMAC10 -> PHY3-P1
DPMAC11 -> PHY3-P2
DPMAC12 -> PHY3-P3
DPMAC13 -> PHY4-P0
DPMAC14 -> PHY4-P1
DPMAC15 -> PHY4-P2
DPMAC16 -> PHY4-P3
@@ -0,0 +1,181 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright 2015 Freescale Semiconductor, Inc.
*/
#include <common.h>
#include <fsl_ddr_sdram.h>
#include <fsl_ddr_dimm_params.h>
#include <asm/arch/soc.h>
#include <asm/arch/clock.h>
#include "ddr.h"
DECLARE_GLOBAL_DATA_PTR;
void fsl_ddr_board_options(memctl_options_t *popts,
dimm_params_t *pdimm,
unsigned int ctrl_num)
{
#ifdef CONFIG_SYS_FSL_HAS_DP_DDR
u8 dq_mapping_0, dq_mapping_2, dq_mapping_3;
#endif
const struct board_specific_parameters *pbsp, *pbsp_highest = NULL;
ulong ddr_freq;
int slot;
if (ctrl_num > 2) {
printf("Not supported controller number %d\n", ctrl_num);
return;
}
for (slot = 0; slot < CONFIG_DIMM_SLOTS_PER_CTLR; slot++) {
if (pdimm[slot].n_ranks)
break;
}
if (slot >= CONFIG_DIMM_SLOTS_PER_CTLR)
return;
/*
* we use identical timing for all slots. If needed, change the code
* to pbsp = rdimms[ctrl_num] or pbsp = udimms[ctrl_num];
*/
if (popts->registered_dimm_en)
pbsp = rdimms[ctrl_num];
else
pbsp = udimms[ctrl_num];
/* Get clk_adjust, wrlvl_start, wrlvl_ctl, according to the board ddr
* freqency and n_banks specified in board_specific_parameters table.
*/
ddr_freq = get_ddr_freq(ctrl_num) / 1000000;
while (pbsp->datarate_mhz_high) {
if (pbsp->n_ranks == pdimm[slot].n_ranks &&
(pdimm[slot].rank_density >> 30) >= pbsp->rank_gb) {
if (ddr_freq <= pbsp->datarate_mhz_high) {
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;
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->clk_adjust = pbsp_highest->clk_adjust;
popts->wrlvl_start = pbsp_highest->wrlvl_start;
popts->wrlvl_ctl_2 = pbsp->wrlvl_ctl_2;
popts->wrlvl_ctl_3 = pbsp->wrlvl_ctl_3;
} else {
panic("DIMM is not supported by this board");
}
found:
debug("Found timing match: n_ranks %d, data rate %d, rank_gb %d\n"
"\tclk_adjust %d, wrlvl_start %d, wrlvl_ctrl_2 0x%x, wrlvl_ctrl_3 0x%x\n",
pbsp->n_ranks, pbsp->datarate_mhz_high, pbsp->rank_gb,
pbsp->clk_adjust, pbsp->wrlvl_start, pbsp->wrlvl_ctl_2,
pbsp->wrlvl_ctl_3);
#ifdef CONFIG_SYS_FSL_HAS_DP_DDR
if (ctrl_num == CONFIG_DP_DDR_CTRL) {
/* force DDR bus width to 32 bits */
popts->data_bus_width = 1;
popts->otf_burst_chop_en = 0;
popts->burst_length = DDR_BL8;
popts->bstopre = 0; /* enable auto precharge */
/*
* Layout optimization results byte mapping
* Byte 0 -> Byte ECC
* Byte 1 -> Byte 3
* Byte 2 -> Byte 2
* Byte 3 -> Byte 1
* Byte ECC -> Byte 0
*/
dq_mapping_0 = pdimm[slot].dq_mapping[0];
dq_mapping_2 = pdimm[slot].dq_mapping[2];
dq_mapping_3 = pdimm[slot].dq_mapping[3];
pdimm[slot].dq_mapping[0] = pdimm[slot].dq_mapping[8];
pdimm[slot].dq_mapping[1] = pdimm[slot].dq_mapping[9];
pdimm[slot].dq_mapping[2] = pdimm[slot].dq_mapping[6];
pdimm[slot].dq_mapping[3] = pdimm[slot].dq_mapping[7];
pdimm[slot].dq_mapping[6] = dq_mapping_2;
pdimm[slot].dq_mapping[7] = dq_mapping_3;
pdimm[slot].dq_mapping[8] = dq_mapping_0;
pdimm[slot].dq_mapping[9] = 0;
pdimm[slot].dq_mapping[10] = 0;
pdimm[slot].dq_mapping[11] = 0;
pdimm[slot].dq_mapping[12] = 0;
pdimm[slot].dq_mapping[13] = 0;
pdimm[slot].dq_mapping[14] = 0;
pdimm[slot].dq_mapping[15] = 0;
pdimm[slot].dq_mapping[16] = 0;
pdimm[slot].dq_mapping[17] = 0;
}
#endif
/* To work at higher than 1333MT/s */
popts->half_strength_driver_enable = 0;
/*
* Write leveling override
*/
popts->wrlvl_override = 1;
popts->wrlvl_sample = 0x0; /* 32 clocks */
/*
* Rtt and Rtt_WR override
*/
popts->rtt_override = 0;
/* Enable ZQ calibration */
popts->zq_en = 1;
if (ddr_freq < 2350) {
if (pdimm[0].n_ranks == 2 && pdimm[1].n_ranks == 2) {
/* four chip-selects */
popts->ddr_cdr1 = DDR_CDR1_DHC_EN |
DDR_CDR1_ODT(DDR_CDR_ODT_80ohm);
popts->ddr_cdr2 = DDR_CDR2_ODT(DDR_CDR_ODT_80ohm);
popts->twot_en = 1; /* enable 2T timing */
} else {
popts->ddr_cdr1 = DDR_CDR1_DHC_EN |
DDR_CDR1_ODT(DDR_CDR_ODT_60ohm);
popts->ddr_cdr2 = DDR_CDR2_ODT(DDR_CDR_ODT_60ohm) |
DDR_CDR2_VREF_RANGE_2;
}
} else {
popts->ddr_cdr1 = DDR_CDR1_DHC_EN |
DDR_CDR1_ODT(DDR_CDR_ODT_100ohm);
popts->ddr_cdr2 = DDR_CDR2_ODT(DDR_CDR_ODT_100ohm) |
DDR_CDR2_VREF_RANGE_2;
}
}
#ifdef CONFIG_TFABOOT
int fsl_initdram(void)
{
gd->ram_size = tfa_get_dram_size();
if (!gd->ram_size)
gd->ram_size = fsl_ddr_sdram_size();
return 0;
}
#else
int fsl_initdram(void)
{
#if defined(CONFIG_SPL) && !defined(CONFIG_SPL_BUILD)
gd->ram_size = fsl_ddr_sdram_size();
#else
puts("Initializing DDR....using SPD\n");
gd->ram_size = fsl_ddr_sdram();
#endif
return 0;
}
#endif /* CONFIG_TFABOOT */
@@ -0,0 +1,91 @@
/* SPDX-License-Identifier: GPL-2.0+ */
/*
* Copyright 2015 Freescale Semiconductor, Inc.
*/
#ifndef __DDR_H__
#define __DDR_H__
struct board_specific_parameters {
u32 n_ranks;
u32 datarate_mhz_high;
u32 rank_gb;
u32 clk_adjust;
u32 wrlvl_start;
u32 wrlvl_ctl_2;
u32 wrlvl_ctl_3;
};
/*
* These tables contain 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| rank| clk| wrlvl | wrlvl | wrlvl
* ranks| mhz| GB |adjst| start | ctl2 | ctl3
*/
{2, 1350, 0, 8, 6, 0x0708090B, 0x0C0D0E09,},
{2, 1666, 0, 8, 7, 0x08090A0C, 0x0D0F100B,},
{2, 1900, 0, 8, 7, 0x09090B0D, 0x0E10120B,},
{2, 2300, 0, 8, 8, 0x090A0C0F, 0x1012130C,},
{}
};
/* DP-DDR DIMM */
static const struct board_specific_parameters udimm2[] = {
/*
* memory controller 2
* num| hi| rank| clk| wrlvl | wrlvl | wrlvl
* ranks| mhz| GB |adjst| start | ctl2 | ctl3
*/
{2, 1350, 0, 8, 0xd, 0x0C0A0A00, 0x00000009,},
{2, 1666, 0, 8, 0xd, 0x0C0A0A00, 0x00000009,},
{2, 1900, 0, 8, 0xe, 0x0D0C0B00, 0x0000000A,},
{2, 2200, 0, 8, 0xe, 0x0D0C0B00, 0x0000000A,},
{}
};
static const struct board_specific_parameters rdimm0[] = {
/*
* memory controller 0
* num| hi| rank| clk| wrlvl | wrlvl | wrlvl
* ranks| mhz| GB |adjst| start | ctl2 | ctl3
*/
{2, 1350, 0, 8, 6, 0x0708090B, 0x0C0D0E09,},
{2, 1666, 0, 8, 7, 0x08090A0C, 0x0D0F100B,},
{2, 1900, 0, 8, 7, 0x09090B0D, 0x0E10120B,},
{2, 2200, 0, 8, 8, 0x090A0C0F, 0x1012130C,},
{}
};
/* DP-DDR DIMM */
static const struct board_specific_parameters rdimm2[] = {
/*
* memory controller 2
* num| hi| rank| clk| wrlvl | wrlvl | wrlvl
* ranks| mhz| GB |adjst| start | ctl2 | ctl3
*/
{2, 1350, 0, 8, 6, 0x0708090B, 0x0C0D0E09,},
{2, 1666, 0, 8, 7, 0x0B0A090C, 0x0D0F100B,},
{2, 1900, 0, 8, 7, 0x09090B0D, 0x0E10120B,},
{2, 2200, 0, 8, 8, 0x090A0C0F, 0x1012130C,},
{}
};
static const struct board_specific_parameters *udimms[] = {
udimm0,
udimm0,
udimm2,
};
static const struct board_specific_parameters *rdimms[] = {
rdimm0,
rdimm0,
rdimm2,
};
#endif
@@ -0,0 +1,981 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright 2015 Freescale Semiconductor, Inc.
*/
#include <common.h>
#include <env.h>
#include <netdev.h>
#include <asm/io.h>
#include <asm/arch/fsl_serdes.h>
#include <hwconfig.h>
#include <fsl_mdio.h>
#include <malloc.h>
#include <fm_eth.h>
#include <i2c.h>
#include <miiphy.h>
#include <fsl-mc/fsl_mc.h>
#include <fsl-mc/ldpaa_wriop.h>
#include "../common/qixis.h"
#include "ls2080aqds_qixis.h"
#define MC_BOOT_ENV_VAR "mcinitcmd"
#if defined(CONFIG_FSL_MC_ENET) && !defined(CONFIG_SPL_BUILD)
/* - In LS2080A there are only 16 SERDES lanes, spread across 2 SERDES banks.
* Bank 1 -> Lanes A, B, C, D, E, F, G, H
* Bank 2 -> Lanes A,B, C, D, E, F, G, H
*/
/* Mapping of 16 SERDES lanes to LS2080A QDS board slots. A value of '0' here
* means that the mapping must be determined dynamically, or that the lane
* maps to something other than a board slot.
*/
static u8 lane_to_slot_fsm1[] = {
0, 0, 0, 0, 0, 0, 0, 0
};
static u8 lane_to_slot_fsm2[] = {
0, 0, 0, 0, 0, 0, 0, 0
};
/* On the Vitesse VSC8234XHG SGMII riser card there are 4 SGMII PHYs
* housed.
*/
static int xqsgii_riser_phy_addr[] = {
XQSGMII_CARD_PHY1_PORT0_ADDR,
XQSGMII_CARD_PHY2_PORT0_ADDR,
XQSGMII_CARD_PHY3_PORT0_ADDR,
XQSGMII_CARD_PHY4_PORT0_ADDR,
XQSGMII_CARD_PHY3_PORT2_ADDR,
XQSGMII_CARD_PHY1_PORT2_ADDR,
XQSGMII_CARD_PHY4_PORT2_ADDR,
XQSGMII_CARD_PHY2_PORT2_ADDR,
};
static int sgmii_riser_phy_addr[] = {
SGMII_CARD_PORT1_PHY_ADDR,
SGMII_CARD_PORT2_PHY_ADDR,
SGMII_CARD_PORT3_PHY_ADDR,
SGMII_CARD_PORT4_PHY_ADDR,
};
/* Slot2 does not have EMI connections */
#define EMI_NONE 0xFF
#define EMI1_SLOT1 0
#define EMI1_SLOT2 1
#define EMI1_SLOT3 2
#define EMI1_SLOT4 3
#define EMI1_SLOT5 4
#define EMI1_SLOT6 5
#define EMI2 6
#define SFP_TX 0
static const char * const mdio_names[] = {
"LS2080A_QDS_MDIO0",
"LS2080A_QDS_MDIO1",
"LS2080A_QDS_MDIO2",
"LS2080A_QDS_MDIO3",
"LS2080A_QDS_MDIO4",
"LS2080A_QDS_MDIO5",
DEFAULT_WRIOP_MDIO2_NAME,
};
struct ls2080a_qds_mdio {
u8 muxval;
struct mii_dev *realbus;
};
struct reg_pair {
uint addr;
u8 *val;
};
static void sgmii_configure_repeater(int serdes_port)
{
struct mii_dev *bus;
uint8_t a = 0xf;
int i, j, k, ret;
int dpmac_id = 0, dpmac, mii_bus = 0;
unsigned short value;
char dev[2][20] = {"LS2080A_QDS_MDIO0", "LS2080A_QDS_MDIO3"};
uint8_t i2c_addr[] = {0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5f, 0x60};
uint8_t ch_a_eq[] = {0x1, 0x2, 0x3, 0x7};
uint8_t ch_a_ctl2[] = {0x81, 0x82, 0x83, 0x84};
uint8_t ch_b_eq[] = {0x1, 0x2, 0x3, 0x7};
uint8_t ch_b_ctl2[] = {0x81, 0x82, 0x83, 0x84};
u8 reg_val[6] = {0x18, 0x38, 0x4, 0x14, 0xb5, 0x20};
struct reg_pair reg_pair[10] = {
{6, &reg_val[0]}, {4, &reg_val[1]},
{8, &reg_val[2]}, {0xf, NULL},
{0x11, NULL}, {0x16, NULL},
{0x18, NULL}, {0x23, &reg_val[3]},
{0x2d, &reg_val[4]}, {4, &reg_val[5]},
};
int *riser_phy_addr = &xqsgii_riser_phy_addr[0];
#ifdef CONFIG_DM_I2C
struct udevice *udev;
#endif
/* Set I2c to Slot 1 */
#ifndef CONFIG_DM_I2C
ret = i2c_write(0x77, 0, 0, &a, 1);
#else
ret = i2c_get_chip_for_busnum(0, 0x77, 1, &udev);
if (!ret)
ret = dm_i2c_write(udev, 0, &a, 1);
#endif
if (ret)
goto error;
for (dpmac = 0; dpmac < 8; dpmac++) {
/* Check the PHY status */
switch (serdes_port) {
case 1:
mii_bus = 0;
dpmac_id = dpmac + 1;
break;
case 2:
mii_bus = 1;
dpmac_id = dpmac + 9;
a = 0xb;
#ifndef CONFIG_DM_I2C
ret = i2c_write(0x76, 0, 0, &a, 1);
#else
ret = i2c_get_chip_for_busnum(0, 0x76, 1, &udev);
if (!ret)
ret = dm_i2c_write(udev, 0, &a, 1);
#endif
if (ret)
goto error;
break;
}
ret = miiphy_set_current_dev(dev[mii_bus]);
if (ret > 0)
goto error;
bus = mdio_get_current_dev();
debug("Reading from bus %s\n", bus->name);
ret = miiphy_write(dev[mii_bus], riser_phy_addr[dpmac], 0x1f,
3);
if (ret > 0)
goto error;
mdelay(10);
ret = miiphy_read(dev[mii_bus], riser_phy_addr[dpmac], 0x11,
&value);
if (ret > 0)
goto error;
mdelay(10);
if ((value & 0xfff) == 0x401) {
printf("DPMAC %d:PHY is ..... Configured\n", dpmac_id);
miiphy_write(dev[mii_bus], riser_phy_addr[dpmac],
0x1f, 0);
continue;
}
for (i = 0; i < 4; i++) {
for (j = 0; j < 4; j++) {
reg_pair[3].val = &ch_a_eq[i];
reg_pair[4].val = &ch_a_ctl2[j];
reg_pair[5].val = &ch_b_eq[i];
reg_pair[6].val = &ch_b_ctl2[j];
for (k = 0; k < 10; k++) {
#ifndef CONFIG_DM_I2C
ret = i2c_write(i2c_addr[dpmac],
reg_pair[k].addr,
1, reg_pair[k].val, 1);
#else
ret = i2c_get_chip_for_busnum(0,
i2c_addr[dpmac],
1, &udev);
if (!ret)
ret = dm_i2c_write(udev,
reg_pair[k].addr,
reg_pair[k].val, 1);
#endif
if (ret)
goto error;
}
mdelay(100);
ret = miiphy_read(dev[mii_bus],
riser_phy_addr[dpmac],
0x11, &value);
if (ret > 0)
goto error;
mdelay(100);
ret = miiphy_read(dev[mii_bus],
riser_phy_addr[dpmac],
0x11, &value);
if (ret > 0)
goto error;
if ((value & 0xfff) == 0x401) {
printf("DPMAC %d :PHY is configured ",
dpmac_id);
printf("after setting repeater 0x%x\n",
value);
i = 5;
j = 5;
} else {
printf("DPMAC %d :PHY is failed to ",
dpmac_id);
printf("configure the repeater 0x%x\n",
value);
}
}
}
miiphy_write(dev[mii_bus], riser_phy_addr[dpmac], 0x1f, 0);
}
error:
if (ret)
printf("DPMAC %d ..... FAILED to configure PHY\n", dpmac_id);
return;
}
static void qsgmii_configure_repeater(int dpmac)
{
uint8_t a = 0xf;
int i, j, k;
int i2c_phy_addr = 0;
int phy_addr = 0;
int i2c_addr[] = {0x58, 0x59, 0x5a, 0x5b};
uint8_t ch_a_eq[] = {0x1, 0x2, 0x3, 0x7};
uint8_t ch_a_ctl2[] = {0x81, 0x82, 0x83, 0x84};
uint8_t ch_b_eq[] = {0x1, 0x2, 0x3, 0x7};
uint8_t ch_b_ctl2[] = {0x81, 0x82, 0x83, 0x84};
u8 reg_val[6] = {0x18, 0x38, 0x4, 0x14, 0xb5, 0x20};
struct reg_pair reg_pair[10] = {
{6, &reg_val[0]}, {4, &reg_val[1]},
{8, &reg_val[2]}, {0xf, NULL},
{0x11, NULL}, {0x16, NULL},
{0x18, NULL}, {0x23, &reg_val[3]},
{0x2d, &reg_val[4]}, {4, &reg_val[5]},
};
const char *dev = "LS2080A_QDS_MDIO0";
int ret = 0;
unsigned short value;
#ifdef CONFIG_DM_I2C
struct udevice *udev;
#endif
/* Set I2c to Slot 1 */
#ifndef CONFIG_DM_I2C
ret = i2c_write(0x77, 0, 0, &a, 1);
#else
ret = i2c_get_chip_for_busnum(0, 0x77, 1, &udev);
if (!ret)
ret = dm_i2c_write(udev, 0, &a, 1);
#endif
if (ret)
goto error;
switch (dpmac) {
case 1:
case 2:
case 3:
case 4:
i2c_phy_addr = i2c_addr[0];
phy_addr = 0;
break;
case 5:
case 6:
case 7:
case 8:
i2c_phy_addr = i2c_addr[1];
phy_addr = 4;
break;
case 9:
case 10:
case 11:
case 12:
i2c_phy_addr = i2c_addr[2];
phy_addr = 8;
break;
case 13:
case 14:
case 15:
case 16:
i2c_phy_addr = i2c_addr[3];
phy_addr = 0xc;
break;
}
/* Check the PHY status */
ret = miiphy_set_current_dev(dev);
ret = miiphy_write(dev, phy_addr, 0x1f, 3);
mdelay(10);
ret = miiphy_read(dev, phy_addr, 0x11, &value);
mdelay(10);
ret = miiphy_read(dev, phy_addr, 0x11, &value);
mdelay(10);
if ((value & 0xf) == 0xf) {
printf("DPMAC %d :PHY is ..... Configured\n", dpmac);
return;
}
for (i = 0; i < 4; i++) {
for (j = 0; j < 4; j++) {
reg_pair[3].val = &ch_a_eq[i];
reg_pair[4].val = &ch_a_ctl2[j];
reg_pair[5].val = &ch_b_eq[i];
reg_pair[6].val = &ch_b_ctl2[j];
for (k = 0; k < 10; k++) {
#ifndef CONFIG_DM_I2C
ret = i2c_write(i2c_phy_addr,
reg_pair[k].addr,
1, reg_pair[k].val, 1);
#else
ret = i2c_get_chip_for_busnum(0,
i2c_phy_addr,
1, &udev);
if (!ret)
ret = dm_i2c_write(udev,
reg_pair[k].addr,
reg_pair[k].val, 1);
#endif
if (ret)
goto error;
}
mdelay(100);
ret = miiphy_read(dev, phy_addr, 0x11, &value);
if (ret > 0)
goto error;
mdelay(1);
ret = miiphy_read(dev, phy_addr, 0x11, &value);
if (ret > 0)
goto error;
mdelay(10);
if ((value & 0xf) == 0xf) {
printf("DPMAC %d :PHY is ..... Configured\n",
dpmac);
return;
}
}
}
error:
printf("DPMAC %d :PHY ..... FAILED to configure PHY\n", dpmac);
return;
}
static const char *ls2080a_qds_mdio_name_for_muxval(u8 muxval)
{
return mdio_names[muxval];
}
struct mii_dev *mii_dev_for_muxval(u8 muxval)
{
struct mii_dev *bus;
const char *name = ls2080a_qds_mdio_name_for_muxval(muxval);
if (!name) {
printf("No bus for muxval %x\n", muxval);
return NULL;
}
bus = miiphy_get_dev_by_name(name);
if (!bus) {
printf("No bus by name %s\n", name);
return NULL;
}
return bus;
}
static void ls2080a_qds_enable_SFP_TX(u8 muxval)
{
u8 brdcfg9;
brdcfg9 = QIXIS_READ(brdcfg[9]);
brdcfg9 &= ~BRDCFG9_SFPTX_MASK;
brdcfg9 |= (muxval << BRDCFG9_SFPTX_SHIFT);
QIXIS_WRITE(brdcfg[9], brdcfg9);
}
static void ls2080a_qds_mux_mdio(u8 muxval)
{
u8 brdcfg4;
if (muxval <= 5) {
brdcfg4 = QIXIS_READ(brdcfg[4]);
brdcfg4 &= ~BRDCFG4_EMISEL_MASK;
brdcfg4 |= (muxval << BRDCFG4_EMISEL_SHIFT);
QIXIS_WRITE(brdcfg[4], brdcfg4);
}
}
static int ls2080a_qds_mdio_read(struct mii_dev *bus, int addr,
int devad, int regnum)
{
struct ls2080a_qds_mdio *priv = bus->priv;
ls2080a_qds_mux_mdio(priv->muxval);
return priv->realbus->read(priv->realbus, addr, devad, regnum);
}
static int ls2080a_qds_mdio_write(struct mii_dev *bus, int addr, int devad,
int regnum, u16 value)
{
struct ls2080a_qds_mdio *priv = bus->priv;
ls2080a_qds_mux_mdio(priv->muxval);
return priv->realbus->write(priv->realbus, addr, devad, regnum, value);
}
static int ls2080a_qds_mdio_reset(struct mii_dev *bus)
{
struct ls2080a_qds_mdio *priv = bus->priv;
return priv->realbus->reset(priv->realbus);
}
static int ls2080a_qds_mdio_init(char *realbusname, u8 muxval)
{
struct ls2080a_qds_mdio *pmdio;
struct mii_dev *bus = mdio_alloc();
if (!bus) {
printf("Failed to allocate ls2080a_qds MDIO bus\n");
return -1;
}
pmdio = malloc(sizeof(*pmdio));
if (!pmdio) {
printf("Failed to allocate ls2080a_qds private data\n");
free(bus);
return -1;
}
bus->read = ls2080a_qds_mdio_read;
bus->write = ls2080a_qds_mdio_write;
bus->reset = ls2080a_qds_mdio_reset;
strcpy(bus->name, ls2080a_qds_mdio_name_for_muxval(muxval));
pmdio->realbus = miiphy_get_dev_by_name(realbusname);
if (!pmdio->realbus) {
printf("No bus with name %s\n", realbusname);
free(bus);
free(pmdio);
return -1;
}
pmdio->muxval = muxval;
bus->priv = pmdio;
return mdio_register(bus);
}
/*
* Initialize the dpmac_info array.
*
*/
static void initialize_dpmac_to_slot(void)
{
struct ccsr_gur __iomem *gur = (void *)CONFIG_SYS_FSL_GUTS_ADDR;
int serdes1_prtcl = (in_le32(&gur->rcwsr[28]) &
FSL_CHASSIS3_RCWSR28_SRDS1_PRTCL_MASK)
>> FSL_CHASSIS3_RCWSR28_SRDS1_PRTCL_SHIFT;
int serdes2_prtcl = (in_le32(&gur->rcwsr[28]) &
FSL_CHASSIS3_RCWSR28_SRDS2_PRTCL_MASK)
>> FSL_CHASSIS3_RCWSR28_SRDS2_PRTCL_SHIFT;
char *env_hwconfig;
env_hwconfig = env_get("hwconfig");
switch (serdes1_prtcl) {
case 0x07:
case 0x09:
case 0x33:
printf("qds: WRIOP: Supported SerDes1 Protocol 0x%02x\n",
serdes1_prtcl);
lane_to_slot_fsm1[0] = EMI1_SLOT1;
lane_to_slot_fsm1[1] = EMI1_SLOT1;
lane_to_slot_fsm1[2] = EMI1_SLOT1;
lane_to_slot_fsm1[3] = EMI1_SLOT1;
if (hwconfig_f("xqsgmii", env_hwconfig)) {
lane_to_slot_fsm1[4] = EMI1_SLOT1;
lane_to_slot_fsm1[5] = EMI1_SLOT1;
lane_to_slot_fsm1[6] = EMI1_SLOT1;
lane_to_slot_fsm1[7] = EMI1_SLOT1;
} else {
lane_to_slot_fsm1[4] = EMI1_SLOT2;
lane_to_slot_fsm1[5] = EMI1_SLOT2;
lane_to_slot_fsm1[6] = EMI1_SLOT2;
lane_to_slot_fsm1[7] = EMI1_SLOT2;
}
break;
case 0x39:
printf("qds: WRIOP: Supported SerDes1 Protocol 0x%02x\n",
serdes1_prtcl);
if (hwconfig_f("xqsgmii", env_hwconfig)) {
lane_to_slot_fsm1[0] = EMI1_SLOT3;
lane_to_slot_fsm1[1] = EMI1_SLOT3;
lane_to_slot_fsm1[2] = EMI1_SLOT3;
lane_to_slot_fsm1[3] = EMI_NONE;
} else {
lane_to_slot_fsm1[0] = EMI_NONE;
lane_to_slot_fsm1[1] = EMI_NONE;
lane_to_slot_fsm1[2] = EMI_NONE;
lane_to_slot_fsm1[3] = EMI_NONE;
}
lane_to_slot_fsm1[4] = EMI1_SLOT3;
lane_to_slot_fsm1[5] = EMI1_SLOT3;
lane_to_slot_fsm1[6] = EMI1_SLOT3;
lane_to_slot_fsm1[7] = EMI_NONE;
break;
case 0x4D:
printf("qds: WRIOP: Supported SerDes1 Protocol 0x%02x\n",
serdes1_prtcl);
if (hwconfig_f("xqsgmii", env_hwconfig)) {
lane_to_slot_fsm1[0] = EMI1_SLOT3;
lane_to_slot_fsm1[1] = EMI1_SLOT3;
lane_to_slot_fsm1[2] = EMI_NONE;
lane_to_slot_fsm1[3] = EMI_NONE;
} else {
lane_to_slot_fsm1[0] = EMI_NONE;
lane_to_slot_fsm1[1] = EMI_NONE;
lane_to_slot_fsm1[2] = EMI_NONE;
lane_to_slot_fsm1[3] = EMI_NONE;
}
lane_to_slot_fsm1[4] = EMI1_SLOT3;
lane_to_slot_fsm1[5] = EMI1_SLOT3;
lane_to_slot_fsm1[6] = EMI_NONE;
lane_to_slot_fsm1[7] = EMI_NONE;
break;
case 0x2A:
case 0x4B:
case 0x4C:
printf("qds: WRIOP: Supported SerDes1 Protocol 0x%02x\n",
serdes1_prtcl);
break;
default:
printf("%s qds: WRIOP: Unsupported SerDes1 Protocol 0x%02x\n",
__func__, serdes1_prtcl);
break;
}
switch (serdes2_prtcl) {
case 0x07:
case 0x08:
case 0x09:
case 0x49:
printf("qds: WRIOP: Supported SerDes2 Protocol 0x%02x\n",
serdes2_prtcl);
lane_to_slot_fsm2[0] = EMI1_SLOT4;
lane_to_slot_fsm2[1] = EMI1_SLOT4;
lane_to_slot_fsm2[2] = EMI1_SLOT4;
lane_to_slot_fsm2[3] = EMI1_SLOT4;
if (hwconfig_f("xqsgmii", env_hwconfig)) {
lane_to_slot_fsm2[4] = EMI1_SLOT4;
lane_to_slot_fsm2[5] = EMI1_SLOT4;
lane_to_slot_fsm2[6] = EMI1_SLOT4;
lane_to_slot_fsm2[7] = EMI1_SLOT4;
} else {
/* No MDIO physical connection */
lane_to_slot_fsm2[4] = EMI1_SLOT6;
lane_to_slot_fsm2[5] = EMI1_SLOT6;
lane_to_slot_fsm2[6] = EMI1_SLOT6;
lane_to_slot_fsm2[7] = EMI1_SLOT6;
}
break;
case 0x47:
printf("qds: WRIOP: Supported SerDes2 Protocol 0x%02x\n",
serdes2_prtcl);
lane_to_slot_fsm2[0] = EMI_NONE;
lane_to_slot_fsm2[1] = EMI1_SLOT5;
lane_to_slot_fsm2[2] = EMI1_SLOT5;
lane_to_slot_fsm2[3] = EMI1_SLOT5;
if (hwconfig_f("xqsgmii", env_hwconfig)) {
lane_to_slot_fsm2[4] = EMI_NONE;
lane_to_slot_fsm2[5] = EMI1_SLOT5;
lane_to_slot_fsm2[6] = EMI1_SLOT5;
lane_to_slot_fsm2[7] = EMI1_SLOT5;
}
break;
case 0x57:
printf("qds: WRIOP: Supported SerDes2 Protocol 0x%02x\n",
serdes2_prtcl);
if (hwconfig_f("xqsgmii", env_hwconfig)) {
lane_to_slot_fsm2[0] = EMI_NONE;
lane_to_slot_fsm2[1] = EMI_NONE;
lane_to_slot_fsm2[2] = EMI_NONE;
lane_to_slot_fsm2[3] = EMI_NONE;
}
lane_to_slot_fsm2[4] = EMI_NONE;
lane_to_slot_fsm2[5] = EMI_NONE;
lane_to_slot_fsm2[6] = EMI1_SLOT5;
lane_to_slot_fsm2[7] = EMI1_SLOT5;
break;
default:
printf(" %s qds: WRIOP: Unsupported SerDes2 Protocol 0x%02x\n",
__func__ , serdes2_prtcl);
break;
}
}
void ls2080a_handle_phy_interface_sgmii(int dpmac_id)
{
int lane, slot;
struct mii_dev *bus;
struct ccsr_gur __iomem *gur = (void *)CONFIG_SYS_FSL_GUTS_ADDR;
int serdes1_prtcl = (in_le32(&gur->rcwsr[28]) &
FSL_CHASSIS3_RCWSR28_SRDS1_PRTCL_MASK)
>> FSL_CHASSIS3_RCWSR28_SRDS1_PRTCL_SHIFT;
int serdes2_prtcl = (in_le32(&gur->rcwsr[28]) &
FSL_CHASSIS3_RCWSR28_SRDS2_PRTCL_MASK)
>> FSL_CHASSIS3_RCWSR28_SRDS2_PRTCL_SHIFT;
int *riser_phy_addr;
char *env_hwconfig = env_get("hwconfig");
if (hwconfig_f("xqsgmii", env_hwconfig))
riser_phy_addr = &xqsgii_riser_phy_addr[0];
else
riser_phy_addr = &sgmii_riser_phy_addr[0];
if (dpmac_id > WRIOP1_DPMAC9)
goto serdes2;
switch (serdes1_prtcl) {
case 0x07:
case 0x39:
case 0x4D:
lane = serdes_get_first_lane(FSL_SRDS_1, SGMII1 + dpmac_id - 1);
slot = lane_to_slot_fsm1[lane];
switch (++slot) {
case 1:
/* Slot housing a SGMII riser card? */
wriop_set_phy_address(dpmac_id, 0,
riser_phy_addr[dpmac_id - 1]);
dpmac_info[dpmac_id].board_mux = EMI1_SLOT1;
bus = mii_dev_for_muxval(EMI1_SLOT1);
wriop_set_mdio(dpmac_id, bus);
break;
case 2:
/* Slot housing a SGMII riser card? */
wriop_set_phy_address(dpmac_id, 0,
riser_phy_addr[dpmac_id - 1]);
dpmac_info[dpmac_id].board_mux = EMI1_SLOT2;
bus = mii_dev_for_muxval(EMI1_SLOT2);
wriop_set_mdio(dpmac_id, bus);
break;
case 3:
if (slot == EMI_NONE)
return;
if (serdes1_prtcl == 0x39) {
wriop_set_phy_address(dpmac_id, 0,
riser_phy_addr[dpmac_id - 2]);
if (dpmac_id >= 6 && hwconfig_f("xqsgmii",
env_hwconfig))
wriop_set_phy_address(dpmac_id, 0,
riser_phy_addr[dpmac_id - 3]);
} else {
wriop_set_phy_address(dpmac_id, 0,
riser_phy_addr[dpmac_id - 2]);
if (dpmac_id >= 7 && hwconfig_f("xqsgmii",
env_hwconfig))
wriop_set_phy_address(dpmac_id, 0,
riser_phy_addr[dpmac_id - 3]);
}
dpmac_info[dpmac_id].board_mux = EMI1_SLOT3;
bus = mii_dev_for_muxval(EMI1_SLOT3);
wriop_set_mdio(dpmac_id, bus);
break;
case 4:
break;
case 5:
break;
case 6:
break;
}
break;
default:
printf("%s qds: WRIOP: Unsupported SerDes1 Protocol 0x%02x\n",
__func__ , serdes1_prtcl);
break;
}
serdes2:
switch (serdes2_prtcl) {
case 0x07:
case 0x08:
case 0x49:
case 0x47:
case 0x57:
lane = serdes_get_first_lane(FSL_SRDS_2, SGMII9 +
(dpmac_id - 9));
slot = lane_to_slot_fsm2[lane];
switch (++slot) {
case 1:
break;
case 3:
break;
case 4:
/* Slot housing a SGMII riser card? */
wriop_set_phy_address(dpmac_id, 0,
riser_phy_addr[dpmac_id - 9]);
dpmac_info[dpmac_id].board_mux = EMI1_SLOT4;
bus = mii_dev_for_muxval(EMI1_SLOT4);
wriop_set_mdio(dpmac_id, bus);
break;
case 5:
if (slot == EMI_NONE)
return;
if (serdes2_prtcl == 0x47) {
wriop_set_phy_address(dpmac_id, 0,
riser_phy_addr[dpmac_id - 10]);
if (dpmac_id >= 14 && hwconfig_f("xqsgmii",
env_hwconfig))
wriop_set_phy_address(dpmac_id, 0,
riser_phy_addr[dpmac_id - 11]);
} else {
wriop_set_phy_address(dpmac_id, 0,
riser_phy_addr[dpmac_id - 11]);
}
dpmac_info[dpmac_id].board_mux = EMI1_SLOT5;
bus = mii_dev_for_muxval(EMI1_SLOT5);
wriop_set_mdio(dpmac_id, bus);
break;
case 6:
/* Slot housing a SGMII riser card? */
wriop_set_phy_address(dpmac_id, 0,
riser_phy_addr[dpmac_id - 13]);
dpmac_info[dpmac_id].board_mux = EMI1_SLOT6;
bus = mii_dev_for_muxval(EMI1_SLOT6);
wriop_set_mdio(dpmac_id, bus);
break;
}
break;
default:
printf("%s qds: WRIOP: Unsupported SerDes2 Protocol 0x%02x\n",
__func__, serdes2_prtcl);
break;
}
}
void ls2080a_handle_phy_interface_qsgmii(int dpmac_id)
{
int lane = 0, slot;
struct mii_dev *bus;
struct ccsr_gur __iomem *gur = (void *)CONFIG_SYS_FSL_GUTS_ADDR;
int serdes1_prtcl = (in_le32(&gur->rcwsr[28]) &
FSL_CHASSIS3_RCWSR28_SRDS1_PRTCL_MASK)
>> FSL_CHASSIS3_RCWSR28_SRDS1_PRTCL_SHIFT;
switch (serdes1_prtcl) {
case 0x33:
switch (dpmac_id) {
case 1:
case 2:
case 3:
case 4:
lane = serdes_get_first_lane(FSL_SRDS_1, QSGMII_A);
break;
case 5:
case 6:
case 7:
case 8:
lane = serdes_get_first_lane(FSL_SRDS_1, QSGMII_B);
break;
case 9:
case 10:
case 11:
case 12:
lane = serdes_get_first_lane(FSL_SRDS_1, QSGMII_C);
break;
case 13:
case 14:
case 15:
case 16:
lane = serdes_get_first_lane(FSL_SRDS_1, QSGMII_D);
break;
}
slot = lane_to_slot_fsm1[lane];
switch (++slot) {
case 1:
/* Slot housing a QSGMII riser card? */
wriop_set_phy_address(dpmac_id, 0, dpmac_id - 1);
dpmac_info[dpmac_id].board_mux = EMI1_SLOT1;
bus = mii_dev_for_muxval(EMI1_SLOT1);
wriop_set_mdio(dpmac_id, bus);
break;
case 3:
break;
case 4:
break;
case 5:
break;
case 6:
break;
}
break;
default:
printf("qds: WRIOP: Unsupported SerDes Protocol 0x%02x\n",
serdes1_prtcl);
break;
}
qsgmii_configure_repeater(dpmac_id);
}
void ls2080a_handle_phy_interface_xsgmii(int i)
{
struct ccsr_gur __iomem *gur = (void *)CONFIG_SYS_FSL_GUTS_ADDR;
int serdes1_prtcl = (in_le32(&gur->rcwsr[28]) &
FSL_CHASSIS3_RCWSR28_SRDS1_PRTCL_MASK)
>> FSL_CHASSIS3_RCWSR28_SRDS1_PRTCL_SHIFT;
switch (serdes1_prtcl) {
case 0x2A:
case 0x4B:
case 0x4C:
/*
* XFI does not need a PHY to work, but to avoid U-Boot use
* default PHY address which is zero to a MAC when it found
* a MAC has no PHY address, we give a PHY address to XFI
* MAC, and should not use a real XAUI PHY address, since
* MDIO can access it successfully, and then MDIO thinks
* the XAUI card is used for the XFI MAC, which will cause
* error.
*/
wriop_set_phy_address(i, 0, i + 4);
ls2080a_qds_enable_SFP_TX(SFP_TX);
break;
default:
printf("qds: WRIOP: Unsupported SerDes Protocol 0x%02x\n",
serdes1_prtcl);
break;
}
}
#endif
int board_eth_init(bd_t *bis)
{
int error;
#if defined(CONFIG_FSL_MC_ENET) && !defined(CONFIG_SPL_BUILD)
struct ccsr_gur __iomem *gur = (void *)CONFIG_SYS_FSL_GUTS_ADDR;
int serdes1_prtcl = (in_le32(&gur->rcwsr[28]) &
FSL_CHASSIS3_RCWSR28_SRDS1_PRTCL_MASK)
>> FSL_CHASSIS3_RCWSR28_SRDS1_PRTCL_SHIFT;
int serdes2_prtcl = (in_le32(&gur->rcwsr[28]) &
FSL_CHASSIS3_RCWSR28_SRDS2_PRTCL_MASK)
>> FSL_CHASSIS3_RCWSR28_SRDS2_PRTCL_SHIFT;
struct memac_mdio_info *memac_mdio0_info;
struct memac_mdio_info *memac_mdio1_info;
unsigned int i;
char *env_hwconfig;
env_hwconfig = env_get("hwconfig");
initialize_dpmac_to_slot();
memac_mdio0_info = (struct memac_mdio_info *)malloc(
sizeof(struct memac_mdio_info));
memac_mdio0_info->regs =
(struct memac_mdio_controller *)
CONFIG_SYS_FSL_WRIOP1_MDIO1;
memac_mdio0_info->name = DEFAULT_WRIOP_MDIO1_NAME;
/* Register the real MDIO1 bus */
fm_memac_mdio_init(bis, memac_mdio0_info);
memac_mdio1_info = (struct memac_mdio_info *)malloc(
sizeof(struct memac_mdio_info));
memac_mdio1_info->regs =
(struct memac_mdio_controller *)
CONFIG_SYS_FSL_WRIOP1_MDIO2;
memac_mdio1_info->name = DEFAULT_WRIOP_MDIO2_NAME;
/* Register the real MDIO2 bus */
fm_memac_mdio_init(bis, memac_mdio1_info);
/* Register the muxing front-ends to the MDIO buses */
ls2080a_qds_mdio_init(DEFAULT_WRIOP_MDIO1_NAME, EMI1_SLOT1);
ls2080a_qds_mdio_init(DEFAULT_WRIOP_MDIO1_NAME, EMI1_SLOT2);
ls2080a_qds_mdio_init(DEFAULT_WRIOP_MDIO1_NAME, EMI1_SLOT3);
ls2080a_qds_mdio_init(DEFAULT_WRIOP_MDIO1_NAME, EMI1_SLOT4);
ls2080a_qds_mdio_init(DEFAULT_WRIOP_MDIO1_NAME, EMI1_SLOT5);
ls2080a_qds_mdio_init(DEFAULT_WRIOP_MDIO1_NAME, EMI1_SLOT6);
ls2080a_qds_mdio_init(DEFAULT_WRIOP_MDIO2_NAME, EMI2);
for (i = WRIOP1_DPMAC1; i < NUM_WRIOP_PORTS; i++) {
switch (wriop_get_enet_if(i)) {
case PHY_INTERFACE_MODE_QSGMII:
ls2080a_handle_phy_interface_qsgmii(i);
break;
case PHY_INTERFACE_MODE_SGMII:
ls2080a_handle_phy_interface_sgmii(i);
break;
case PHY_INTERFACE_MODE_XGMII:
ls2080a_handle_phy_interface_xsgmii(i);
break;
default:
break;
if (i == 16)
i = NUM_WRIOP_PORTS;
}
}
error = cpu_eth_init(bis);
if (hwconfig_f("xqsgmii", env_hwconfig)) {
if (serdes1_prtcl == 0x7)
sgmii_configure_repeater(1);
if (serdes2_prtcl == 0x7 || serdes2_prtcl == 0x8 ||
serdes2_prtcl == 0x49)
sgmii_configure_repeater(2);
}
#endif
error = pci_eth_init(bis);
return error;
}
#if defined(CONFIG_RESET_PHY_R)
void reset_phy(void)
{
mc_env_boot();
}
#endif /* CONFIG_RESET_PHY_R */
@@ -0,0 +1,380 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright 2015 Freescale Semiconductor
*/
#include <common.h>
#include <env.h>
#include <malloc.h>
#include <errno.h>
#include <netdev.h>
#include <fsl_ifc.h>
#include <fsl_ddr.h>
#include <asm/io.h>
#include <fdt_support.h>
#include <linux/libfdt.h>
#include <fsl-mc/fsl_mc.h>
#include <env_internal.h>
#include <i2c.h>
#include <rtc.h>
#include <asm/arch/soc.h>
#include <hwconfig.h>
#include <fsl_sec.h>
#include <asm/arch/ppa.h>
#include <asm/arch-fsl-layerscape/fsl_icid.h>
#include "../common/qixis.h"
#include "ls2080aqds_qixis.h"
#include "../common/vid.h"
#define PIN_MUX_SEL_SDHC 0x00
#define PIN_MUX_SEL_DSPI 0x0a
#define SCFG_QSPICLKCTRL_DIV_20 (5 << 27)
#define SET_SDHC_MUX_SEL(reg, value) ((reg & 0xf0) | value)
DECLARE_GLOBAL_DATA_PTR;
enum {
MUX_TYPE_SDHC,
MUX_TYPE_DSPI,
};
unsigned long long get_qixis_addr(void)
{
unsigned long long addr;
if (gd->flags & GD_FLG_RELOC)
addr = QIXIS_BASE_PHYS;
else
addr = QIXIS_BASE_PHYS_EARLY;
/*
* IFC address under 256MB is mapped to 0x30000000, any address above
* is mapped to 0x5_10000000 up to 4GB.
*/
addr = addr > 0x10000000 ? addr + 0x500000000ULL : addr + 0x30000000;
return addr;
}
int checkboard(void)
{
char buf[64];
u8 sw;
static const char *const freq[] = {"100", "125", "156.25",
"100 separate SSCG"};
int clock;
cpu_name(buf);
printf("Board: %s-QDS, ", buf);
sw = QIXIS_READ(arch);
printf("Board Arch: V%d, ", sw >> 4);
printf("Board version: %c, boot from ", (sw & 0xf) + 'A' - 1);
memset((u8 *)buf, 0x00, ARRAY_SIZE(buf));
sw = QIXIS_READ(brdcfg[0]);
sw = (sw & QIXIS_LBMAP_MASK) >> QIXIS_LBMAP_SHIFT;
if (sw < 0x8)
printf("vBank: %d\n", sw);
else if (sw == 0x8)
puts("PromJet\n");
else if (sw == 0x9)
puts("NAND\n");
else if (sw == 0xf)
puts("QSPI\n");
else if (sw == 0x15)
printf("IFCCard\n");
else
printf("invalid setting of SW%u\n", QIXIS_LBMAP_SWITCH);
printf("FPGA: v%d (%s), build %d",
(int)QIXIS_READ(scver), qixis_read_tag(buf),
(int)qixis_read_minor());
/* the timestamp string contains "\n" at the end */
printf(" on %s", qixis_read_time(buf));
/*
* Display the actual SERDES reference clocks as configured by the
* dip switches on the board. Note that the SWx registers could
* technically be set to force the reference clocks to match the
* values that the SERDES expects (or vice versa). For now, however,
* we just display both values and hope the user notices when they
* don't match.
*/
puts("SERDES1 Reference : ");
sw = QIXIS_READ(brdcfg[2]);
clock = (sw >> 6) & 3;
printf("Clock1 = %sMHz ", freq[clock]);
clock = (sw >> 4) & 3;
printf("Clock2 = %sMHz", freq[clock]);
puts("\nSERDES2 Reference : ");
clock = (sw >> 2) & 3;
printf("Clock1 = %sMHz ", freq[clock]);
clock = (sw >> 0) & 3;
printf("Clock2 = %sMHz\n", freq[clock]);
return 0;
}
unsigned long get_board_sys_clk(void)
{
u8 sysclk_conf = QIXIS_READ(brdcfg[1]);
switch (sysclk_conf & 0x0F) {
case QIXIS_SYSCLK_83:
return 83333333;
case QIXIS_SYSCLK_100:
return 100000000;
case QIXIS_SYSCLK_125:
return 125000000;
case QIXIS_SYSCLK_133:
return 133333333;
case QIXIS_SYSCLK_150:
return 150000000;
case QIXIS_SYSCLK_160:
return 160000000;
case QIXIS_SYSCLK_166:
return 166666666;
}
return 66666666;
}
unsigned long get_board_ddr_clk(void)
{
u8 ddrclk_conf = QIXIS_READ(brdcfg[1]);
switch ((ddrclk_conf & 0x30) >> 4) {
case QIXIS_DDRCLK_100:
return 100000000;
case QIXIS_DDRCLK_125:
return 125000000;
case QIXIS_DDRCLK_133:
return 133333333;
}
return 66666666;
}
int select_i2c_ch_pca9547(u8 ch)
{
int ret;
#ifdef CONFIG_DM_I2C
struct udevice *dev;
ret = i2c_get_chip_for_busnum(0, I2C_MUX_PCA_ADDR_PRI, 1, &dev);
if (!ret)
ret = dm_i2c_write(dev, 0, &ch, 1);
#else
ret = i2c_write(I2C_MUX_PCA_ADDR_PRI, 0, 1, &ch, 1);
#endif
if (ret) {
puts("PCA: failed to select proper channel\n");
return ret;
}
return 0;
}
int config_board_mux(int ctrl_type)
{
u8 reg5;
reg5 = QIXIS_READ(brdcfg[5]);
switch (ctrl_type) {
case MUX_TYPE_SDHC:
reg5 = SET_SDHC_MUX_SEL(reg5, PIN_MUX_SEL_SDHC);
break;
case MUX_TYPE_DSPI:
reg5 = SET_SDHC_MUX_SEL(reg5, PIN_MUX_SEL_DSPI);
break;
default:
printf("Wrong mux interface type\n");
return -1;
}
QIXIS_WRITE(brdcfg[5], reg5);
return 0;
}
int board_init(void)
{
char *env_hwconfig;
u32 __iomem *dcfg_ccsr = (u32 __iomem *)DCFG_BASE;
u32 val;
init_final_memctl_regs();
val = in_le32(dcfg_ccsr + DCFG_RCWSR13 / 4);
env_hwconfig = env_get("hwconfig");
if (hwconfig_f("dspi", env_hwconfig) &&
DCFG_RCWSR13_DSPI == (val & (u32)(0xf << 8)))
config_board_mux(MUX_TYPE_DSPI);
else
config_board_mux(MUX_TYPE_SDHC);
#if defined(CONFIG_MTD_RAW_NAND) && defined(CONFIG_FSL_QSPI)
val = in_le32(dcfg_ccsr + DCFG_RCWSR15 / 4);
if (DCFG_RCWSR15_IFCGRPABASE_QSPI == (val & (u32)0x3))
QIXIS_WRITE(brdcfg[9],
(QIXIS_READ(brdcfg[9]) & 0xf8) |
FSL_QIXIS_BRDCFG9_QSPI);
#endif
#ifdef CONFIG_ENV_IS_NOWHERE
gd->env_addr = (ulong)&default_environment[0];
#endif
select_i2c_ch_pca9547(I2C_MUX_CH_DEFAULT);
#ifdef CONFIG_RTC_ENABLE_32KHZ_OUTPUT
#ifdef CONFIG_DM_I2C
rtc_enable_32khz_output(0, CONFIG_SYS_I2C_RTC_ADDR);
#else
rtc_enable_32khz_output();
#endif
#endif
#ifdef CONFIG_FSL_CAAM
sec_init();
#endif
#ifdef CONFIG_FSL_LS_PPA
ppa_init();
#endif
return 0;
}
int board_early_init_f(void)
{
#ifdef CONFIG_SYS_I2C_EARLY_INIT
i2c_early_init_f();
#endif
fsl_lsch3_early_init_f();
#ifdef CONFIG_FSL_QSPI
/* input clk: 1/2 platform clk, output: input/20 */
out_le32(SCFG_BASE + SCFG_QSPICLKCTLR, SCFG_QSPICLKCTRL_DIV_20);
#endif
return 0;
}
int misc_init_r(void)
{
if (adjust_vdd(0))
printf("Warning: Adjusting core voltage failed.\n");
return 0;
}
void detail_board_ddr_info(void)
{
puts("\nDDR ");
print_size(gd->bd->bi_dram[0].size + gd->bd->bi_dram[1].size, "");
print_ddr_info(0);
#ifdef CONFIG_SYS_FSL_HAS_DP_DDR
if (soc_has_dp_ddr() && gd->bd->bi_dram[2].size) {
puts("\nDP-DDR ");
print_size(gd->bd->bi_dram[2].size, "");
print_ddr_info(CONFIG_DP_DDR_CTRL);
}
#endif
}
#if defined(CONFIG_ARCH_MISC_INIT)
int arch_misc_init(void)
{
return 0;
}
#endif
#if defined(CONFIG_FSL_MC_ENET) && !defined(CONFIG_SPL_BUILD)
void fdt_fixup_board_enet(void *fdt)
{
int offset;
offset = fdt_path_offset(fdt, "/soc/fsl-mc");
if (offset < 0)
offset = fdt_path_offset(fdt, "/fsl-mc");
if (offset < 0) {
printf("%s: ERROR: fsl-mc node not found in device tree (error %d)\n",
__func__, offset);
return;
}
if (get_mc_boot_status() == 0 &&
(is_lazy_dpl_addr_valid() || get_dpl_apply_status() == 0))
fdt_status_okay(fdt, offset);
else
fdt_status_fail(fdt, offset);
}
void board_quiesce_devices(void)
{
fsl_mc_ldpaa_exit(gd->bd);
}
#endif
#ifdef CONFIG_OF_BOARD_SETUP
int ft_board_setup(void *blob, bd_t *bd)
{
u64 base[CONFIG_NR_DRAM_BANKS];
u64 size[CONFIG_NR_DRAM_BANKS];
ft_cpu_setup(blob, bd);
/* fixup DT for the two GPP DDR banks */
base[0] = gd->bd->bi_dram[0].start;
size[0] = gd->bd->bi_dram[0].size;
base[1] = gd->bd->bi_dram[1].start;
size[1] = gd->bd->bi_dram[1].size;
#ifdef CONFIG_RESV_RAM
/* reduce size if reserved memory is within this bank */
if (gd->arch.resv_ram >= base[0] &&
gd->arch.resv_ram < base[0] + size[0])
size[0] = gd->arch.resv_ram - base[0];
else if (gd->arch.resv_ram >= base[1] &&
gd->arch.resv_ram < base[1] + size[1])
size[1] = gd->arch.resv_ram - base[1];
#endif
fdt_fixup_memory_banks(blob, base, size, 2);
fdt_fsl_mc_fixup_iommu_map_entry(blob);
fsl_fdt_fixup_dr_usb(blob, bd);
#if defined(CONFIG_FSL_MC_ENET) && !defined(CONFIG_SPL_BUILD)
fdt_fixup_board_enet(blob);
#endif
fdt_fixup_icid(blob);
return 0;
}
#endif
void qixis_dump_switch(void)
{
int i, nr_of_cfgsw;
QIXIS_WRITE(cms[0], 0x00);
nr_of_cfgsw = QIXIS_READ(cms[1]);
puts("DIP switch settings dump:\n");
for (i = 1; i <= nr_of_cfgsw; i++) {
QIXIS_WRITE(cms[0], i);
printf("SW%d = (0x%02x)\n", i, QIXIS_READ(cms[1]));
}
}
@@ -0,0 +1,29 @@
/* SPDX-License-Identifier: GPL-2.0+ */
/*
* Copyright 2015 Freescale Semiconductor, Inc.
*/
#ifndef __LS2_QDS_QIXIS_H__
#define __LS2_QDS_QIXIS_H__
/* SYSCLK */
#define QIXIS_SYSCLK_66 0x0
#define QIXIS_SYSCLK_83 0x1
#define QIXIS_SYSCLK_100 0x2
#define QIXIS_SYSCLK_125 0x3
#define QIXIS_SYSCLK_133 0x4
#define QIXIS_SYSCLK_150 0x5
#define QIXIS_SYSCLK_160 0x6
#define QIXIS_SYSCLK_166 0x7
/* DDRCLK */
#define QIXIS_DDRCLK_66 0x0
#define QIXIS_DDRCLK_100 0x1
#define QIXIS_DDRCLK_125 0x2
#define QIXIS_DDRCLK_133 0x3
#define BRDCFG4_EMISEL_MASK 0xE0
#define BRDCFG4_EMISEL_SHIFT 5
#define BRDCFG9_SFPTX_MASK 0x10
#define BRDCFG9_SFPTX_SHIFT 4
#endif /*__LS2_QDS_QIXIS_H__*/