mirror of
https://github.com/AsahiLinux/u-boot
synced 2024-11-25 14:10:43 +00:00
arm: mvebu: Add Armada 38x SERDES / PHY init code from Marvell bin_hdr
This code is ported from the Marvell bin_hdr code into mainline SPL U-Boot. It needs to be executed very early so that the devices connected to the serdes PHY are configured correctly. Signed-off-by: Stefan Roese <sr@denx.de>
This commit is contained in:
parent
29b103c733
commit
edb4702533
13 changed files with 5204 additions and 0 deletions
|
@ -20,6 +20,7 @@ obj-y += timer.o
|
|||
obj-$(CONFIG_SPL_BUILD) += spl.o
|
||||
obj-$(CONFIG_SPL_BUILD) += lowlevel_spl.o
|
||||
|
||||
obj-$(CONFIG_SYS_MVEBU_DDR_A38X) += serdes/a38x/
|
||||
obj-$(CONFIG_SYS_MVEBU_DDR_AXP) += serdes/axp/
|
||||
|
||||
endif
|
||||
|
|
10
arch/arm/mach-mvebu/serdes/a38x/Makefile
Normal file
10
arch/arm/mach-mvebu/serdes/a38x/Makefile
Normal file
|
@ -0,0 +1,10 @@
|
|||
#
|
||||
# SPDX-License-Identifier: GPL-2.0+
|
||||
#
|
||||
|
||||
obj-$(CONFIG_SPL_BUILD) = ctrl_pex.o
|
||||
obj-$(CONFIG_SPL_BUILD) += high_speed_env_spec.o
|
||||
obj-$(CONFIG_SPL_BUILD) += high_speed_env_spec-38x.o
|
||||
obj-$(CONFIG_SPL_BUILD) += high_speed_topology_spec-38x.o
|
||||
obj-$(CONFIG_SPL_BUILD) += seq_exec.o
|
||||
obj-$(CONFIG_SPL_BUILD) += sys_env_lib.o
|
347
arch/arm/mach-mvebu/serdes/a38x/ctrl_pex.c
Normal file
347
arch/arm/mach-mvebu/serdes/a38x/ctrl_pex.c
Normal file
|
@ -0,0 +1,347 @@
|
|||
/*
|
||||
* Copyright (C) Marvell International Ltd. and its affiliates
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <spl.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/arch/cpu.h>
|
||||
#include <asm/arch/soc.h>
|
||||
|
||||
#include "ctrl_pex.h"
|
||||
#include "sys_env_lib.h"
|
||||
|
||||
int hws_pex_config(struct serdes_map *serdes_map)
|
||||
{
|
||||
u32 pex_idx, tmp, next_busno, first_busno, temp_pex_reg,
|
||||
temp_reg, addr, dev_id, ctrl_mode;
|
||||
enum serdes_type serdes_type;
|
||||
u32 idx, max_lane_num;
|
||||
|
||||
DEBUG_INIT_FULL_S("\n### hws_pex_config ###\n");
|
||||
|
||||
max_lane_num = hws_serdes_get_max_lane();
|
||||
for (idx = 0; idx < max_lane_num; idx++) {
|
||||
serdes_type = serdes_map[idx].serdes_type;
|
||||
/* configuration for PEX only */
|
||||
if ((serdes_type != PEX0) && (serdes_type != PEX1) &&
|
||||
(serdes_type != PEX2) && (serdes_type != PEX3))
|
||||
continue;
|
||||
|
||||
if ((serdes_type != PEX0) &&
|
||||
((serdes_map[idx].serdes_mode == PEX_ROOT_COMPLEX_X4) ||
|
||||
(serdes_map[idx].serdes_mode == PEX_END_POINT_X4))) {
|
||||
/* for PEX by4 - relevant for the first port only */
|
||||
continue;
|
||||
}
|
||||
|
||||
pex_idx = serdes_type - PEX0;
|
||||
tmp = reg_read(PEX_CAPABILITIES_REG(pex_idx));
|
||||
tmp &= ~(0xf << 20);
|
||||
tmp |= (0x4 << 20);
|
||||
reg_write(PEX_CAPABILITIES_REG(pex_idx), tmp);
|
||||
}
|
||||
|
||||
tmp = reg_read(SOC_CTRL_REG);
|
||||
tmp &= ~0x03;
|
||||
|
||||
for (idx = 0; idx < max_lane_num; idx++) {
|
||||
serdes_type = serdes_map[idx].serdes_type;
|
||||
if ((serdes_type != PEX0) &&
|
||||
((serdes_map[idx].serdes_mode == PEX_ROOT_COMPLEX_X4) ||
|
||||
(serdes_map[idx].serdes_mode == PEX_END_POINT_X4))) {
|
||||
/* for PEX by4 - relevant for the first port only */
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (serdes_type) {
|
||||
case PEX0:
|
||||
tmp |= 0x1 << PCIE0_ENABLE_OFFS;
|
||||
break;
|
||||
case PEX1:
|
||||
tmp |= 0x1 << PCIE1_ENABLE_OFFS;
|
||||
break;
|
||||
case PEX2:
|
||||
tmp |= 0x1 << PCIE2_ENABLE_OFFS;
|
||||
break;
|
||||
case PEX3:
|
||||
tmp |= 0x1 << PCIE3_ENABLE_OFFS;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
reg_write(SOC_CTRL_REG, tmp);
|
||||
|
||||
/* Support gen1/gen2 */
|
||||
DEBUG_INIT_FULL_S("Support gen1/gen2\n");
|
||||
next_busno = 0;
|
||||
mdelay(150);
|
||||
|
||||
for (idx = 0; idx < max_lane_num; idx++) {
|
||||
serdes_type = serdes_map[idx].serdes_type;
|
||||
DEBUG_INIT_FULL_S(" serdes_type=0x");
|
||||
DEBUG_INIT_FULL_D(serdes_type, 8);
|
||||
DEBUG_INIT_FULL_S("\n");
|
||||
DEBUG_INIT_FULL_S(" idx=0x");
|
||||
DEBUG_INIT_FULL_D(idx, 8);
|
||||
DEBUG_INIT_FULL_S("\n");
|
||||
|
||||
/* Configuration for PEX only */
|
||||
if ((serdes_type != PEX0) && (serdes_type != PEX1) &&
|
||||
(serdes_type != PEX2) && (serdes_type != PEX3))
|
||||
continue;
|
||||
|
||||
if ((serdes_type != PEX0) &&
|
||||
((serdes_map[idx].serdes_mode == PEX_ROOT_COMPLEX_X4) ||
|
||||
(serdes_map[idx].serdes_mode == PEX_END_POINT_X4))) {
|
||||
/* for PEX by4 - relevant for the first port only */
|
||||
continue;
|
||||
}
|
||||
|
||||
pex_idx = serdes_type - PEX0;
|
||||
tmp = reg_read(PEX_DBG_STATUS_REG(pex_idx));
|
||||
|
||||
first_busno = next_busno;
|
||||
if ((tmp & 0x7f) != 0x7e) {
|
||||
DEBUG_INIT_S("PCIe, Idx ");
|
||||
DEBUG_INIT_D(pex_idx, 1);
|
||||
DEBUG_INIT_S(": detected no link\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
next_busno++;
|
||||
temp_pex_reg = reg_read((PEX_CFG_DIRECT_ACCESS
|
||||
(pex_idx, PEX_LINK_CAPABILITY_REG)));
|
||||
temp_pex_reg &= 0xf;
|
||||
if (temp_pex_reg != 0x2)
|
||||
continue;
|
||||
|
||||
temp_reg = (reg_read(PEX_CFG_DIRECT_ACCESS(
|
||||
pex_idx,
|
||||
PEX_LINK_CTRL_STAT_REG)) &
|
||||
0xf0000) >> 16;
|
||||
|
||||
/* Check if the link established is GEN1 */
|
||||
DEBUG_INIT_FULL_S
|
||||
("Checking if the link established is gen1\n");
|
||||
if (temp_reg != 0x1)
|
||||
continue;
|
||||
|
||||
pex_local_bus_num_set(pex_idx, first_busno);
|
||||
pex_local_dev_num_set(pex_idx, 1);
|
||||
DEBUG_INIT_FULL_S("PCIe, Idx ");
|
||||
DEBUG_INIT_FULL_D(pex_idx, 1);
|
||||
|
||||
DEBUG_INIT_S(":** Link is Gen1, check the EP capability\n");
|
||||
/* link is Gen1, check the EP capability */
|
||||
addr = pex_config_read(pex_idx, first_busno, 0, 0, 0x34) & 0xff;
|
||||
DEBUG_INIT_FULL_C("pex_config_read: return addr=0x%x", addr, 4);
|
||||
if (addr == 0xff) {
|
||||
DEBUG_INIT_FULL_C
|
||||
("pex_config_read: return 0xff -->PCIe (%d): Detected No Link.",
|
||||
pex_idx, 1);
|
||||
continue;
|
||||
}
|
||||
|
||||
while ((pex_config_read(pex_idx, first_busno, 0, 0, addr)
|
||||
& 0xff) != 0x10) {
|
||||
addr = (pex_config_read(pex_idx, first_busno, 0,
|
||||
0, addr) & 0xff00) >> 8;
|
||||
}
|
||||
|
||||
/* Check for Gen2 and above */
|
||||
if ((pex_config_read(pex_idx, first_busno, 0, 0,
|
||||
addr + 0xc) & 0xf) < 0x2) {
|
||||
DEBUG_INIT_S("PCIe, Idx ");
|
||||
DEBUG_INIT_D(pex_idx, 1);
|
||||
DEBUG_INIT_S(": remains Gen1\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
tmp = reg_read(PEX_LINK_CTRL_STATUS2_REG(pex_idx));
|
||||
DEBUG_RD_REG(PEX_LINK_CTRL_STATUS2_REG(pex_idx), tmp);
|
||||
tmp &= ~(BIT(0) | BIT(1));
|
||||
tmp |= BIT(1);
|
||||
tmp |= BIT(6); /* Select Deemphasize (-3.5d_b) */
|
||||
reg_write(PEX_LINK_CTRL_STATUS2_REG(pex_idx), tmp);
|
||||
DEBUG_WR_REG(PEX_LINK_CTRL_STATUS2_REG(pex_idx), tmp);
|
||||
|
||||
tmp = reg_read(PEX_CTRL_REG(pex_idx));
|
||||
DEBUG_RD_REG(PEX_CTRL_REG(pex_idx), tmp);
|
||||
tmp |= BIT(10);
|
||||
reg_write(PEX_CTRL_REG(pex_idx), tmp);
|
||||
DEBUG_WR_REG(PEX_CTRL_REG(pex_idx), tmp);
|
||||
|
||||
/*
|
||||
* We need to wait 10ms before reading the PEX_DBG_STATUS_REG
|
||||
* in order not to read the status of the former state
|
||||
*/
|
||||
mdelay(10);
|
||||
|
||||
DEBUG_INIT_S("PCIe, Idx ");
|
||||
DEBUG_INIT_D(pex_idx, 1);
|
||||
DEBUG_INIT_S
|
||||
(": Link upgraded to Gen2 based on client cpabilities\n");
|
||||
}
|
||||
|
||||
/* Update pex DEVICE ID */
|
||||
ctrl_mode = sys_env_model_get();
|
||||
|
||||
for (idx = 0; idx < max_lane_num; idx++) {
|
||||
serdes_type = serdes_map[idx].serdes_type;
|
||||
/* configuration for PEX only */
|
||||
if ((serdes_type != PEX0) && (serdes_type != PEX1) &&
|
||||
(serdes_type != PEX2) && (serdes_type != PEX3))
|
||||
continue;
|
||||
|
||||
if ((serdes_type != PEX0) &&
|
||||
((serdes_map[idx].serdes_mode == PEX_ROOT_COMPLEX_X4) ||
|
||||
(serdes_map[idx].serdes_mode == PEX_END_POINT_X4))) {
|
||||
/* for PEX by4 - relevant for the first port only */
|
||||
continue;
|
||||
}
|
||||
|
||||
pex_idx = serdes_type - PEX0;
|
||||
dev_id = reg_read(PEX_CFG_DIRECT_ACCESS
|
||||
(pex_idx, PEX_DEVICE_AND_VENDOR_ID));
|
||||
dev_id &= 0xffff;
|
||||
dev_id |= ((ctrl_mode << 16) & 0xffff0000);
|
||||
reg_write(PEX_CFG_DIRECT_ACCESS
|
||||
(pex_idx, PEX_DEVICE_AND_VENDOR_ID), dev_id);
|
||||
}
|
||||
DEBUG_INIT_FULL_C("Update PEX Device ID ", ctrl_mode, 4);
|
||||
|
||||
return MV_OK;
|
||||
}
|
||||
|
||||
int pex_local_bus_num_set(u32 pex_if, u32 bus_num)
|
||||
{
|
||||
u32 pex_status;
|
||||
|
||||
DEBUG_INIT_FULL_S("\n### pex_local_bus_num_set ###\n");
|
||||
|
||||
if (bus_num >= MAX_PEX_BUSSES) {
|
||||
DEBUG_INIT_C("pex_local_bus_num_set: Illegal bus number %d\n",
|
||||
bus_num, 4);
|
||||
return MV_BAD_PARAM;
|
||||
}
|
||||
|
||||
pex_status = reg_read(PEX_STATUS_REG(pex_if));
|
||||
pex_status &= ~PXSR_PEX_BUS_NUM_MASK;
|
||||
pex_status |=
|
||||
(bus_num << PXSR_PEX_BUS_NUM_OFFS) & PXSR_PEX_BUS_NUM_MASK;
|
||||
reg_write(PEX_STATUS_REG(pex_if), pex_status);
|
||||
|
||||
return MV_OK;
|
||||
}
|
||||
|
||||
int pex_local_dev_num_set(u32 pex_if, u32 dev_num)
|
||||
{
|
||||
u32 pex_status;
|
||||
|
||||
DEBUG_INIT_FULL_S("\n### pex_local_dev_num_set ###\n");
|
||||
|
||||
pex_status = reg_read(PEX_STATUS_REG(pex_if));
|
||||
pex_status &= ~PXSR_PEX_DEV_NUM_MASK;
|
||||
pex_status |=
|
||||
(dev_num << PXSR_PEX_DEV_NUM_OFFS) & PXSR_PEX_DEV_NUM_MASK;
|
||||
reg_write(PEX_STATUS_REG(pex_if), pex_status);
|
||||
|
||||
return MV_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* pex_config_read - Read from configuration space
|
||||
*
|
||||
* DESCRIPTION:
|
||||
* This function performs a 32 bit read from PEX configuration space.
|
||||
* It supports both type 0 and type 1 of Configuration Transactions
|
||||
* (local and over bridge). In order to read from local bus segment, use
|
||||
* bus number retrieved from pex_local_bus_num_get(). Other bus numbers
|
||||
* will result configuration transaction of type 1 (over bridge).
|
||||
*
|
||||
* INPUT:
|
||||
* pex_if - PEX interface number.
|
||||
* bus - PEX segment bus number.
|
||||
* dev - PEX device number.
|
||||
* func - Function number.
|
||||
* reg_offs - Register offset.
|
||||
*
|
||||
* OUTPUT:
|
||||
* None.
|
||||
*
|
||||
* RETURN:
|
||||
* 32bit register data, 0xffffffff on error
|
||||
*/
|
||||
u32 pex_config_read(u32 pex_if, u32 bus, u32 dev, u32 func, u32 reg_off)
|
||||
{
|
||||
u32 pex_data = 0;
|
||||
u32 local_dev, local_bus;
|
||||
u32 pex_status;
|
||||
|
||||
pex_status = reg_read(PEX_STATUS_REG(pex_if));
|
||||
local_dev =
|
||||
((pex_status & PXSR_PEX_DEV_NUM_MASK) >> PXSR_PEX_DEV_NUM_OFFS);
|
||||
local_bus =
|
||||
((pex_status & PXSR_PEX_BUS_NUM_MASK) >> PXSR_PEX_BUS_NUM_OFFS);
|
||||
|
||||
/*
|
||||
* In PCI Express we have only one device number
|
||||
* and this number is the first number we encounter
|
||||
* else that the local_dev
|
||||
* spec pex define return on config read/write on any device
|
||||
*/
|
||||
if (bus == local_bus) {
|
||||
if (local_dev == 0) {
|
||||
/*
|
||||
* if local dev is 0 then the first number we encounter
|
||||
* after 0 is 1
|
||||
*/
|
||||
if ((dev != 1) && (dev != local_dev))
|
||||
return MV_ERROR;
|
||||
} else {
|
||||
/*
|
||||
* if local dev is not 0 then the first number we
|
||||
* encounter is 0
|
||||
*/
|
||||
if ((dev != 0) && (dev != local_dev))
|
||||
return MV_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
/* Creating PEX address to be passed */
|
||||
pex_data = (bus << PXCAR_BUS_NUM_OFFS);
|
||||
pex_data |= (dev << PXCAR_DEVICE_NUM_OFFS);
|
||||
pex_data |= (func << PXCAR_FUNC_NUM_OFFS);
|
||||
/* Legacy register space */
|
||||
pex_data |= (reg_off & PXCAR_REG_NUM_MASK);
|
||||
/* Extended register space */
|
||||
pex_data |= (((reg_off & PXCAR_REAL_EXT_REG_NUM_MASK) >>
|
||||
PXCAR_REAL_EXT_REG_NUM_OFFS) << PXCAR_EXT_REG_NUM_OFFS);
|
||||
pex_data |= PXCAR_CONFIG_EN;
|
||||
|
||||
/* Write the address to the PEX configuration address register */
|
||||
reg_write(PEX_CFG_ADDR_REG(pex_if), pex_data);
|
||||
|
||||
/*
|
||||
* In order to let the PEX controller absorbed the address
|
||||
* of the read transaction we perform a validity check that
|
||||
* the address was written
|
||||
*/
|
||||
if (pex_data != reg_read(PEX_CFG_ADDR_REG(pex_if)))
|
||||
return MV_ERROR;
|
||||
|
||||
/* Cleaning Master Abort */
|
||||
reg_bit_set(PEX_CFG_DIRECT_ACCESS(pex_if, PEX_STATUS_AND_COMMAND),
|
||||
PXSAC_MABORT);
|
||||
/* Read the Data returned in the PEX Data register */
|
||||
pex_data = reg_read(PEX_CFG_DATA_REG(pex_if));
|
||||
|
||||
DEBUG_INIT_FULL_C(" --> ", pex_data, 4);
|
||||
|
||||
return pex_data;
|
||||
}
|
82
arch/arm/mach-mvebu/serdes/a38x/ctrl_pex.h
Normal file
82
arch/arm/mach-mvebu/serdes/a38x/ctrl_pex.h
Normal file
|
@ -0,0 +1,82 @@
|
|||
/*
|
||||
* Copyright (C) Marvell International Ltd. and its affiliates
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0
|
||||
*/
|
||||
|
||||
#ifndef _CTRL_PEX_H
|
||||
#define _CTRL_PEX_H
|
||||
|
||||
#include "high_speed_env_spec.h"
|
||||
|
||||
/* Sample at Reset */
|
||||
#define MPP_SAMPLE_AT_RESET(id) (0xe4200 + (id * 4))
|
||||
|
||||
/* PCI Express Control and Status Registers */
|
||||
#define MAX_PEX_BUSSES 256
|
||||
|
||||
#define MISC_REGS_OFFSET 0x18200
|
||||
#define MV_MISC_REGS_BASE MISC_REGS_OFFSET
|
||||
#define SOC_CTRL_REG (MV_MISC_REGS_BASE + 0x4)
|
||||
|
||||
#define PEX_CAPABILITIES_REG(if) ((PEX_IF_REGS_BASE(if)) + 0x60)
|
||||
#define PEX_LINK_CTRL_STATUS2_REG(if) ((PEX_IF_REGS_BASE(if)) + 0x90)
|
||||
#define PEX_CTRL_REG(if) ((PEX_IF_REGS_BASE(if)) + 0x1a00)
|
||||
#define PEX_STATUS_REG(if) ((PEX_IF_REGS_BASE(if)) + 0x1a04)
|
||||
#define PEX_DBG_STATUS_REG(if) ((PEX_IF_REGS_BASE(if)) + 0x1a64)
|
||||
#define PEX_LINK_CAPABILITY_REG 0x6c
|
||||
#define PEX_LINK_CTRL_STAT_REG 0x70
|
||||
#define PXSR_PEX_DEV_NUM_OFFS 16 /* Device Number Indication */
|
||||
#define PXSR_PEX_DEV_NUM_MASK (0x1f << PXSR_PEX_DEV_NUM_OFFS)
|
||||
#define PXSR_PEX_BUS_NUM_OFFS 8 /* Bus Number Indication */
|
||||
#define PXSR_PEX_BUS_NUM_MASK (0xff << PXSR_PEX_BUS_NUM_OFFS)
|
||||
|
||||
/* PEX_CAPABILITIES_REG fields */
|
||||
#define PCIE0_ENABLE_OFFS 0
|
||||
#define PCIE0_ENABLE_MASK (0x1 << PCIE0_ENABLE_OFFS)
|
||||
#define PCIE1_ENABLE_OFFS 1
|
||||
#define PCIE1_ENABLE_MASK (0x1 << PCIE1_ENABLE_OFFS)
|
||||
#define PCIE2_ENABLE_OFFS 2
|
||||
#define PCIE2_ENABLE_MASK (0x1 << PCIE2_ENABLE_OFFS)
|
||||
#define PCIE3_ENABLE_OFFS 3
|
||||
#define PCIE4_ENABLE_MASK (0x1 << PCIE3_ENABLE_OFFS)
|
||||
|
||||
/* Controller revision info */
|
||||
#define PEX_DEVICE_AND_VENDOR_ID 0x000
|
||||
|
||||
/* PCI Express Configuration Address Register */
|
||||
#define PXCAR_REG_NUM_OFFS 2
|
||||
#define PXCAR_REG_NUM_MAX 0x3f
|
||||
#define PXCAR_REG_NUM_MASK (PXCAR_REG_NUM_MAX << \
|
||||
PXCAR_REG_NUM_OFFS)
|
||||
#define PXCAR_FUNC_NUM_OFFS 8
|
||||
#define PXCAR_FUNC_NUM_MAX 0x7
|
||||
#define PXCAR_FUNC_NUM_MASK (PXCAR_FUNC_NUM_MAX << \
|
||||
PXCAR_FUNC_NUM_OFFS)
|
||||
#define PXCAR_DEVICE_NUM_OFFS 11
|
||||
#define PXCAR_DEVICE_NUM_MAX 0x1f
|
||||
#define PXCAR_DEVICE_NUM_MASK (PXCAR_DEVICE_NUM_MAX << \
|
||||
PXCAR_DEVICE_NUM_OFFS)
|
||||
#define PXCAR_BUS_NUM_OFFS 16
|
||||
#define PXCAR_BUS_NUM_MAX 0xff
|
||||
#define PXCAR_BUS_NUM_MASK (PXCAR_BUS_NUM_MAX << \
|
||||
PXCAR_BUS_NUM_OFFS)
|
||||
#define PXCAR_EXT_REG_NUM_OFFS 24
|
||||
#define PXCAR_EXT_REG_NUM_MAX 0xf
|
||||
|
||||
#define PEX_CFG_ADDR_REG(if) ((PEX_IF_REGS_BASE(if)) + 0x18f8)
|
||||
#define PEX_CFG_DATA_REG(if) ((PEX_IF_REGS_BASE(if)) + 0x18fc)
|
||||
|
||||
#define PXCAR_REAL_EXT_REG_NUM_OFFS 8
|
||||
#define PXCAR_REAL_EXT_REG_NUM_MASK (0xf << PXCAR_REAL_EXT_REG_NUM_OFFS)
|
||||
|
||||
#define PXCAR_CONFIG_EN BIT(31)
|
||||
#define PEX_STATUS_AND_COMMAND 0x004
|
||||
#define PXSAC_MABORT BIT(29) /* Recieved Master Abort */
|
||||
|
||||
int hws_pex_config(struct serdes_map *serdes_map);
|
||||
int pex_local_bus_num_set(u32 pex_if, u32 bus_num);
|
||||
int pex_local_dev_num_set(u32 pex_if, u32 dev_num);
|
||||
u32 pex_config_read(u32 pex_if, u32 bus, u32 dev, u32 func, u32 reg_off);
|
||||
|
||||
#endif
|
158
arch/arm/mach-mvebu/serdes/a38x/high_speed_env_spec-38x.c
Normal file
158
arch/arm/mach-mvebu/serdes/a38x/high_speed_env_spec-38x.c
Normal file
|
@ -0,0 +1,158 @@
|
|||
/*
|
||||
* Copyright (C) Marvell International Ltd. and its affiliates
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <i2c.h>
|
||||
#include <spl.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/arch/cpu.h>
|
||||
#include <asm/arch/soc.h>
|
||||
|
||||
#include "high_speed_env_spec.h"
|
||||
#include "sys_env_lib.h"
|
||||
|
||||
#define SERDES_VERION "2.0"
|
||||
|
||||
u8 selectors_serdes_rev1_map[LAST_SERDES_TYPE][MAX_SERDES_LANES] = {
|
||||
/* 0 1 2 3 4 5 */
|
||||
{0x1, 0x1, NA, NA, NA, NA}, /* PEX0 */
|
||||
{NA, 0x2, 0x1, NA, 0x1, NA}, /* PEX1 */
|
||||
{NA, NA, 0x2, NA, NA, 0x1}, /* PEX2 */
|
||||
{NA, NA, NA, 0x1, NA, NA}, /* PEX3 */
|
||||
{0x2, 0x3, NA, NA, NA, NA}, /* SATA0 */
|
||||
{NA, NA, 0x3, NA, 0x2, NA}, /* SATA1 */
|
||||
{NA, NA, NA, NA, 0x6, 0x2}, /* SATA2 */
|
||||
{NA, NA, NA, 0x3, NA, NA}, /* SATA3 */
|
||||
{0x3, 0x4, NA, NA, NA, NA}, /* SGMII0 */
|
||||
{NA, 0x5, 0x4, NA, 0x3, NA}, /* SGMII1 */
|
||||
{NA, NA, NA, 0x4, NA, 0x3}, /* SGMII2 */
|
||||
{NA, 0x7, NA, NA, NA, NA}, /* QSGMII */
|
||||
{NA, 0x6, NA, NA, 0x4, NA}, /* USB3_HOST0 */
|
||||
{NA, NA, NA, 0x5, NA, 0x4}, /* USB3_HOST1 */
|
||||
{NA, NA, NA, 0x6, 0x5, 0x5}, /* USB3_DEVICE */
|
||||
{0x0, 0x0, 0x0, 0x0, 0x0, 0x0} /* DEFAULT_SERDES */
|
||||
};
|
||||
|
||||
int hws_serdes_seq_init(void)
|
||||
{
|
||||
DEBUG_INIT_FULL_S("\n### serdes_seq_init ###\n");
|
||||
|
||||
if (hws_serdes_seq_db_init() != MV_OK) {
|
||||
printf("hws_serdes_seq_init: Error: Serdes initialization fail\n");
|
||||
return MV_FAIL;
|
||||
}
|
||||
|
||||
return MV_OK;
|
||||
}
|
||||
|
||||
int serdes_power_up_ctrl_ext(u32 serdes_num, int serdes_power_up,
|
||||
enum serdes_type serdes_type,
|
||||
enum serdes_speed baud_rate,
|
||||
enum serdes_mode serdes_mode,
|
||||
enum ref_clock ref_clock)
|
||||
{
|
||||
return MV_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
u32 hws_serdes_silicon_ref_clock_get(void)
|
||||
{
|
||||
DEBUG_INIT_FULL_S("\n### hws_serdes_silicon_ref_clock_get ###\n");
|
||||
|
||||
return REF_CLOCK_25MHZ;
|
||||
}
|
||||
|
||||
u32 hws_serdes_get_max_lane(void)
|
||||
{
|
||||
switch (sys_env_device_id_get()) {
|
||||
case MV_6811: /* A381/A3282: 6811/6821: single/dual cpu */
|
||||
return 4;
|
||||
case MV_6810:
|
||||
return 5;
|
||||
case MV_6820:
|
||||
case MV_6828:
|
||||
return 6;
|
||||
default: /* not the right module */
|
||||
printf("%s: Device ID Error, using 4 SerDes lanes\n",
|
||||
__func__);
|
||||
return 4;
|
||||
}
|
||||
return 6;
|
||||
}
|
||||
|
||||
int hws_is_serdes_active(u8 lane_num)
|
||||
{
|
||||
int ret = 1;
|
||||
|
||||
/* Maximum lane count for A388 (6828) is 6 */
|
||||
if (lane_num > 6)
|
||||
ret = 0;
|
||||
|
||||
/* 4th Lane (#4 on Device 6810 is not Active */
|
||||
if (sys_env_device_id_get() == MV_6810 && lane_num == 4) {
|
||||
printf("%s: Error: Lane#4 on Device 6810 is not Active.\n",
|
||||
__func__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* 6th Lane (#5) on Device 6810 is Active, even though 6810
|
||||
* has only 5 lanes
|
||||
*/
|
||||
if (sys_env_device_id_get() == MV_6810 && lane_num == 5)
|
||||
return 1;
|
||||
|
||||
if (lane_num >= hws_serdes_get_max_lane())
|
||||
ret = 0;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int hws_get_ext_base_addr(u32 serdes_num, u32 base_addr, u32 unit_base_offset,
|
||||
u32 *unit_base_reg, u32 *unit_offset)
|
||||
{
|
||||
*unit_base_reg = base_addr;
|
||||
*unit_offset = unit_base_offset;
|
||||
|
||||
return MV_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* hws_serdes_get_phy_selector_val
|
||||
*
|
||||
* DESCRIPTION: Get the mapping of Serdes Selector values according to the
|
||||
* Serdes revision number
|
||||
* INPUT: serdes_num - Serdes number
|
||||
* serdes_type - Serdes type
|
||||
* OUTPUT: None
|
||||
* RETURN:
|
||||
* Mapping of Serdes Selector values
|
||||
*/
|
||||
u32 hws_serdes_get_phy_selector_val(int serdes_num,
|
||||
enum serdes_type serdes_type)
|
||||
{
|
||||
if (serdes_type >= LAST_SERDES_TYPE)
|
||||
return 0xff;
|
||||
|
||||
if (hws_ctrl_serdes_rev_get() == MV_SERDES_REV_1_2) {
|
||||
return selectors_serdes_rev1_map
|
||||
[serdes_type][serdes_num];
|
||||
} else
|
||||
return selectors_serdes_rev2_map
|
||||
[serdes_type][serdes_num];
|
||||
}
|
||||
|
||||
u32 hws_get_physical_serdes_num(u32 serdes_num)
|
||||
{
|
||||
if ((serdes_num == 4) && (sys_env_device_id_get() == MV_6810)) {
|
||||
/*
|
||||
* For 6810, there are 5 Serdes and Serdes Num 4 doesn't
|
||||
* exist. Instead Serdes Num 5 is connected.
|
||||
*/
|
||||
return 5;
|
||||
} else {
|
||||
return serdes_num;
|
||||
}
|
||||
}
|
2228
arch/arm/mach-mvebu/serdes/a38x/high_speed_env_spec.c
Normal file
2228
arch/arm/mach-mvebu/serdes/a38x/high_speed_env_spec.c
Normal file
File diff suppressed because it is too large
Load diff
251
arch/arm/mach-mvebu/serdes/a38x/high_speed_env_spec.h
Normal file
251
arch/arm/mach-mvebu/serdes/a38x/high_speed_env_spec.h
Normal file
|
@ -0,0 +1,251 @@
|
|||
/*
|
||||
* Copyright (C) Marvell International Ltd. and its affiliates
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0
|
||||
*/
|
||||
|
||||
#ifndef _HIGH_SPEED_ENV_SPEC_H
|
||||
#define _HIGH_SPEED_ENV_SPEC_H
|
||||
|
||||
#include "seq_exec.h"
|
||||
|
||||
/*
|
||||
* For setting or clearing a certain bit (bit is a number between 0 and 31)
|
||||
* in the data
|
||||
*/
|
||||
#define SET_BIT(data, bit) ((data) | (0x1 << (bit)))
|
||||
#define CLEAR_BIT(data, bit) ((data) & (~(0x1 << (bit))))
|
||||
|
||||
#define MAX_SERDES_LANES 7 /* as in a39x */
|
||||
|
||||
/* Serdes revision */
|
||||
/* Serdes revision 1.2 (for A38x-Z1) */
|
||||
#define MV_SERDES_REV_1_2 0x0
|
||||
/* Serdes revision 2.1 (for A39x-Z1, A38x-A0) */
|
||||
#define MV_SERDES_REV_2_1 0x1
|
||||
#define MV_SERDES_REV_NA 0xff
|
||||
|
||||
#define SERDES_REGS_LANE_BASE_OFFSET(lane) (0x800 * (lane))
|
||||
|
||||
#define PEX_X4_ENABLE_OFFS \
|
||||
(hws_ctrl_serdes_rev_get() == MV_SERDES_REV_1_2 ? 18 : 31)
|
||||
|
||||
/* Serdes lane types */
|
||||
enum serdes_type {
|
||||
PEX0,
|
||||
PEX1,
|
||||
PEX2,
|
||||
PEX3,
|
||||
SATA0,
|
||||
SATA1,
|
||||
SATA2,
|
||||
SATA3,
|
||||
SGMII0,
|
||||
SGMII1,
|
||||
SGMII2,
|
||||
QSGMII,
|
||||
USB3_HOST0,
|
||||
USB3_HOST1,
|
||||
USB3_DEVICE,
|
||||
SGMII3,
|
||||
XAUI,
|
||||
RXAUI,
|
||||
DEFAULT_SERDES,
|
||||
LAST_SERDES_TYPE
|
||||
};
|
||||
|
||||
/* Serdes baud rates */
|
||||
enum serdes_speed {
|
||||
SERDES_SPEED_1_25_GBPS,
|
||||
SERDES_SPEED_1_5_GBPS,
|
||||
SERDES_SPEED_2_5_GBPS,
|
||||
SERDES_SPEED_3_GBPS,
|
||||
SERDES_SPEED_3_125_GBPS,
|
||||
SERDES_SPEED_5_GBPS,
|
||||
SERDES_SPEED_6_GBPS,
|
||||
SERDES_SPEED_6_25_GBPS,
|
||||
LAST_SERDES_SPEED
|
||||
};
|
||||
|
||||
/* Serdes modes */
|
||||
enum serdes_mode {
|
||||
PEX_ROOT_COMPLEX_X1,
|
||||
PEX_ROOT_COMPLEX_X4,
|
||||
PEX_END_POINT_X1,
|
||||
PEX_END_POINT_X4,
|
||||
|
||||
SERDES_DEFAULT_MODE, /* not pex */
|
||||
|
||||
SERDES_LAST_MODE
|
||||
};
|
||||
|
||||
struct serdes_map {
|
||||
enum serdes_type serdes_type;
|
||||
enum serdes_speed serdes_speed;
|
||||
enum serdes_mode serdes_mode;
|
||||
int swap_rx;
|
||||
int swap_tx;
|
||||
};
|
||||
|
||||
/* Serdes ref clock options */
|
||||
enum ref_clock {
|
||||
REF_CLOCK_25MHZ,
|
||||
REF_CLOCK_100MHZ,
|
||||
REF_CLOCK_40MHZ,
|
||||
REF_CLOCK_UNSUPPORTED
|
||||
};
|
||||
|
||||
/* Serdes sequences */
|
||||
enum serdes_seq {
|
||||
SATA_PORT_0_ONLY_POWER_UP_SEQ,
|
||||
SATA_PORT_1_ONLY_POWER_UP_SEQ,
|
||||
SATA_POWER_UP_SEQ,
|
||||
SATA_1_5_SPEED_CONFIG_SEQ,
|
||||
SATA_3_SPEED_CONFIG_SEQ,
|
||||
SATA_6_SPEED_CONFIG_SEQ,
|
||||
SATA_ELECTRICAL_CONFIG_SEQ,
|
||||
SATA_TX_CONFIG_SEQ1,
|
||||
SATA_PORT_0_ONLY_TX_CONFIG_SEQ,
|
||||
SATA_PORT_1_ONLY_TX_CONFIG_SEQ,
|
||||
SATA_TX_CONFIG_SEQ2,
|
||||
|
||||
SGMII_POWER_UP_SEQ,
|
||||
SGMII_1_25_SPEED_CONFIG_SEQ,
|
||||
SGMII_3_125_SPEED_CONFIG_SEQ,
|
||||
SGMII_ELECTRICAL_CONFIG_SEQ,
|
||||
SGMII_TX_CONFIG_SEQ1,
|
||||
SGMII_TX_CONFIG_SEQ2,
|
||||
|
||||
PEX_POWER_UP_SEQ,
|
||||
PEX_2_5_SPEED_CONFIG_SEQ,
|
||||
PEX_5_SPEED_CONFIG_SEQ,
|
||||
PEX_ELECTRICAL_CONFIG_SEQ,
|
||||
PEX_TX_CONFIG_SEQ1,
|
||||
PEX_TX_CONFIG_SEQ2,
|
||||
PEX_TX_CONFIG_SEQ3,
|
||||
PEX_BY_4_CONFIG_SEQ,
|
||||
PEX_CONFIG_REF_CLOCK_25MHZ_SEQ,
|
||||
PEX_CONFIG_REF_CLOCK_100MHZ_SEQ,
|
||||
PEX_CONFIG_REF_CLOCK_40MHZ_SEQ,
|
||||
|
||||
USB3_POWER_UP_SEQ,
|
||||
USB3_HOST_SPEED_CONFIG_SEQ,
|
||||
USB3_DEVICE_SPEED_CONFIG_SEQ,
|
||||
USB3_ELECTRICAL_CONFIG_SEQ,
|
||||
USB3_TX_CONFIG_SEQ1,
|
||||
USB3_TX_CONFIG_SEQ2,
|
||||
USB3_TX_CONFIG_SEQ3,
|
||||
USB3_DEVICE_CONFIG_SEQ,
|
||||
|
||||
USB2_POWER_UP_SEQ,
|
||||
|
||||
SERDES_POWER_DOWN_SEQ,
|
||||
|
||||
SGMII3_POWER_UP_SEQ,
|
||||
SGMII3_1_25_SPEED_CONFIG_SEQ,
|
||||
SGMII3_TX_CONFIG_SEQ1,
|
||||
SGMII3_TX_CONFIG_SEQ2,
|
||||
|
||||
QSGMII_POWER_UP_SEQ,
|
||||
QSGMII_5_SPEED_CONFIG_SEQ,
|
||||
QSGMII_ELECTRICAL_CONFIG_SEQ,
|
||||
QSGMII_TX_CONFIG_SEQ1,
|
||||
QSGMII_TX_CONFIG_SEQ2,
|
||||
|
||||
XAUI_POWER_UP_SEQ,
|
||||
XAUI_3_125_SPEED_CONFIG_SEQ,
|
||||
XAUI_ELECTRICAL_CONFIG_SEQ,
|
||||
XAUI_TX_CONFIG_SEQ1,
|
||||
XAUI_TX_CONFIG_SEQ2,
|
||||
|
||||
RXAUI_POWER_UP_SEQ,
|
||||
RXAUI_6_25_SPEED_CONFIG_SEQ,
|
||||
RXAUI_ELECTRICAL_CONFIG_SEQ,
|
||||
RXAUI_TX_CONFIG_SEQ1,
|
||||
RXAUI_TX_CONFIG_SEQ2,
|
||||
|
||||
SERDES_LAST_SEQ
|
||||
};
|
||||
|
||||
/* The different sequence types for PEX and USB3 */
|
||||
enum {
|
||||
PEX,
|
||||
USB3,
|
||||
LAST_PEX_USB_SEQ_TYPE
|
||||
};
|
||||
|
||||
enum {
|
||||
PEXSERDES_SPEED_2_5_GBPS,
|
||||
PEXSERDES_SPEED_5_GBPS,
|
||||
USB3SERDES_SPEED_5_GBPS_HOST,
|
||||
USB3SERDES_SPEED_5_GBPS_DEVICE,
|
||||
LAST_PEX_USB_SPEED_SEQ_TYPE
|
||||
};
|
||||
|
||||
/* The different sequence types for SATA and SGMII */
|
||||
enum {
|
||||
SATA,
|
||||
SGMII,
|
||||
SGMII_3_125,
|
||||
LAST_SATA_SGMII_SEQ_TYPE
|
||||
};
|
||||
|
||||
enum {
|
||||
QSGMII_SEQ_IDX,
|
||||
LAST_QSGMII_SEQ_TYPE
|
||||
};
|
||||
|
||||
enum {
|
||||
XAUI_SEQ_IDX,
|
||||
RXAUI_SEQ_IDX,
|
||||
LAST_XAUI_RXAUI_SEQ_TYPE
|
||||
};
|
||||
|
||||
enum {
|
||||
SATASERDES_SPEED_1_5_GBPS,
|
||||
SATASERDES_SPEED_3_GBPS,
|
||||
SATASERDES_SPEED_6_GBPS,
|
||||
SGMIISERDES_SPEED_1_25_GBPS,
|
||||
SGMIISERDES_SPEED_3_125_GBPS,
|
||||
LAST_SATA_SGMII_SPEED_SEQ_TYPE
|
||||
};
|
||||
|
||||
extern u8 selectors_serdes_rev1_map[LAST_SERDES_TYPE][MAX_SERDES_LANES];
|
||||
extern u8 selectors_serdes_rev2_map[LAST_SERDES_TYPE][MAX_SERDES_LANES];
|
||||
|
||||
u8 hws_ctrl_serdes_rev_get(void);
|
||||
int mv_update_serdes_select_phy_mode_seq(void);
|
||||
int hws_board_topology_load(struct serdes_map *serdes_map_array);
|
||||
enum serdes_seq serdes_type_and_speed_to_speed_seq(enum serdes_type serdes_type,
|
||||
enum serdes_speed baud_rate);
|
||||
int hws_serdes_seq_init(void);
|
||||
int hws_serdes_seq_db_init(void);
|
||||
int hws_power_up_serdes_lanes(struct serdes_map *serdes_config_map);
|
||||
int hws_ctrl_high_speed_serdes_phy_config(void);
|
||||
int serdes_power_up_ctrl(u32 serdes_num, int serdes_power_up,
|
||||
enum serdes_type serdes_type,
|
||||
enum serdes_speed baud_rate,
|
||||
enum serdes_mode serdes_mode,
|
||||
enum ref_clock ref_clock);
|
||||
int serdes_power_up_ctrl_ext(u32 serdes_num, int serdes_power_up,
|
||||
enum serdes_type serdes_type,
|
||||
enum serdes_speed baud_rate,
|
||||
enum serdes_mode serdes_mode,
|
||||
enum ref_clock ref_clock);
|
||||
u32 hws_serdes_silicon_ref_clock_get(void);
|
||||
int hws_serdes_pex_ref_clock_get(enum serdes_type serdes_type,
|
||||
enum ref_clock *ref_clock);
|
||||
int hws_ref_clock_set(u32 serdes_num, enum serdes_type serdes_type,
|
||||
enum ref_clock ref_clock);
|
||||
int hws_update_serdes_phy_selectors(struct serdes_map *serdes_config_map);
|
||||
u32 hws_serdes_get_phy_selector_val(int serdes_num,
|
||||
enum serdes_type serdes_type);
|
||||
u32 hws_serdes_get_ref_clock_val(enum serdes_type serdes_type);
|
||||
u32 hws_serdes_get_max_lane(void);
|
||||
int hws_get_ext_base_addr(u32 serdes_num, u32 base_addr, u32 unit_base_offset,
|
||||
u32 *unit_base_reg, u32 *unit_offset);
|
||||
int hws_pex_tx_config_seq(struct serdes_map *serdes_map);
|
||||
u32 hws_get_physical_serdes_num(u32 serdes_num);
|
||||
int hws_is_serdes_active(u8 lane_num);
|
||||
|
||||
#endif /* _HIGH_SPEED_ENV_SPEC_H */
|
1009
arch/arm/mach-mvebu/serdes/a38x/high_speed_topology_spec-38x.c
Normal file
1009
arch/arm/mach-mvebu/serdes/a38x/high_speed_topology_spec-38x.c
Normal file
File diff suppressed because it is too large
Load diff
124
arch/arm/mach-mvebu/serdes/a38x/high_speed_topology_spec.h
Normal file
124
arch/arm/mach-mvebu/serdes/a38x/high_speed_topology_spec.h
Normal file
|
@ -0,0 +1,124 @@
|
|||
/*
|
||||
* Copyright (C) Marvell International Ltd. and its affiliates
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0
|
||||
*/
|
||||
|
||||
#ifndef _HIGHSPEED_TOPOLOGY_SPEC_H
|
||||
#define _HIGHSPEED_TOPOLOGY_SPEC_H
|
||||
|
||||
#include "high_speed_env_spec.h"
|
||||
|
||||
/* Topology map options for the DB_A38X_BP board */
|
||||
enum topology_config_db {
|
||||
DB_CONFIG_SLM1363_C,
|
||||
DB_CONFIG_SLM1363_D,
|
||||
DB_CONFIG_SLM1363_E,
|
||||
DB_CONFIG_SLM1363_F,
|
||||
DB_CONFIG_SLM1364_D,
|
||||
DB_CONFIG_SLM1364_E,
|
||||
DB_CONFIG_SLM1364_F,
|
||||
DB_CONFIG_DEFAULT,
|
||||
DB_NO_TOPOLOGY
|
||||
};
|
||||
|
||||
/*
|
||||
* this enum must be aligned with topology_config_db_381 array,
|
||||
* every update to this enum requires update to topology_config_db_381
|
||||
* array
|
||||
*/
|
||||
enum topology_config_db381 {
|
||||
DB_CONFIG_SLM1427, /* enum for db_config_slm1427 */
|
||||
DB_CONFIG_SLM1426, /* enum for db_config_slm1426 */
|
||||
DB_381_CONFIG_DEFAULT,
|
||||
DB_381_NO_TOPOLOGY
|
||||
};
|
||||
|
||||
/* A generic function pointer for loading the board topology map */
|
||||
typedef int (*load_topology_func_ptr)(struct serdes_map *serdes_map_array);
|
||||
|
||||
extern load_topology_func_ptr load_topology_func_arr[];
|
||||
|
||||
/*
|
||||
* topology_config_db_mode_get -
|
||||
*
|
||||
* DESCRIPTION: Gets the relevant topology mode (index).
|
||||
* for load_topology_db use only.
|
||||
* INPUT: None.
|
||||
* OUTPUT: None.
|
||||
* RETURNS: the topology mode
|
||||
*/
|
||||
u8 topology_config_db_mode_get(void);
|
||||
|
||||
/*
|
||||
* load_topology_xxx -
|
||||
*
|
||||
* DESCRIPTION: Loads the board topology for the XXX board
|
||||
* INPUT: serdes_map_array - The struct that will contain
|
||||
* the board topology map
|
||||
* OUTPUT: The board topology map.
|
||||
* RETURNS: MV_OK for success
|
||||
* MV_FAIL for failure (a wrong topology mode was read
|
||||
* from the board)
|
||||
*/
|
||||
|
||||
/* load_topology_db - Loads the board topology for DB Board */
|
||||
int load_topology_db(struct serdes_map *serdes_map_array);
|
||||
|
||||
/* load_topology_rd - Loads the board topology for RD Board */
|
||||
int load_topology_rd(struct serdes_map *serdes_map_array);
|
||||
|
||||
/* load_topology_rd_nas - Loads the board topology for RD NAS Board */
|
||||
int load_topology_rd_nas(struct serdes_map *serdes_map_array);
|
||||
|
||||
/* load_topology_rd_ap - Loads the board topology for RD Ap Board */
|
||||
int load_topology_rd_ap(struct serdes_map *serdes_map_array);
|
||||
|
||||
/* load_topology_db_ap - Loads the board topology for DB-AP Board */
|
||||
int load_topology_db_ap(struct serdes_map *serdes_map_array);
|
||||
|
||||
/* load_topology_db_gp - Loads the board topology for DB GP Board */
|
||||
int load_topology_db_gp(struct serdes_map *serdes_map_array);
|
||||
|
||||
/* load_topology_db_381 - Loads the board topology for 381 DB-BP Board */
|
||||
int load_topology_db_381(struct serdes_map *serdes_map_array);
|
||||
|
||||
/* load_topology_db_amc - Loads the board topology for DB-AMC Board */
|
||||
int load_topology_db_amc(struct serdes_map *serdes_map_array);
|
||||
|
||||
/*
|
||||
* hws_update_device_toplogy
|
||||
* DESCRIPTION: Update the default board topology for specific device Id
|
||||
* INPUT:
|
||||
* topology_config_ptr - pointer to the Serdes mapping
|
||||
* topology_mode - topology mode (index)
|
||||
* OUTPUT: None
|
||||
* RRETURNS:
|
||||
* MV_OK - if updating the board topology success
|
||||
* MV_BAD_PARAM - if the input parameter is wrong
|
||||
*/
|
||||
int hws_update_device_toplogy(struct serdes_map *topology_config_ptr,
|
||||
enum topology_config_db topology_mode);
|
||||
|
||||
/*
|
||||
* load_topology_rd_sgmii_usb -
|
||||
*
|
||||
* DESCRIPTION: For RD board check if lane 4 is USB3 or SGMII
|
||||
* INPUT: None
|
||||
* OUTPUT: is_sgmii - return 1 if lane 4 is SGMII
|
||||
* return 0 if lane 4 is USB.
|
||||
* RETURNS: MV_OK for success
|
||||
*/
|
||||
int load_topology_rd_sgmii_usb(int *is_sgmii);
|
||||
|
||||
/*
|
||||
* load_topology_usb_mode_get -
|
||||
*
|
||||
* DESCRIPTION: For DB board check if USB3.0 mode
|
||||
* INPUT: None
|
||||
* OUTPUT: twsi_data - return data read from S@R via I2C
|
||||
* RETURNS: MV_OK for success
|
||||
*/
|
||||
int load_topology_usb_mode_get(u8 *twsi_data);
|
||||
|
||||
#endif /* _HIGHSPEED_TOPOLOGY_SPEC_H */
|
170
arch/arm/mach-mvebu/serdes/a38x/seq_exec.c
Normal file
170
arch/arm/mach-mvebu/serdes/a38x/seq_exec.c
Normal file
|
@ -0,0 +1,170 @@
|
|||
/*
|
||||
* Copyright (C) Marvell International Ltd. and its affiliates
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <i2c.h>
|
||||
#include <spl.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/arch/cpu.h>
|
||||
#include <asm/arch/soc.h>
|
||||
|
||||
#include "seq_exec.h"
|
||||
#include "high_speed_env_spec.h"
|
||||
|
||||
#include "../../../drivers/ddr/marvell/a38x/ddr3_init.h"
|
||||
|
||||
#if defined(MV_DEBUG_INIT_FULL) || defined(MV_DEBUG)
|
||||
#define DB(x) x
|
||||
#else
|
||||
#define DB(x)
|
||||
#endif
|
||||
|
||||
/* Array for mapping the operation (write, poll or delay) functions */
|
||||
op_execute_func_ptr op_execute_func_arr[] = {
|
||||
write_op_execute,
|
||||
delay_op_execute,
|
||||
poll_op_execute
|
||||
};
|
||||
|
||||
int write_op_execute(u32 serdes_num, struct op_params *params, u32 data_arr_idx)
|
||||
{
|
||||
u32 unit_base_reg, unit_offset, data, mask, reg_data, reg_addr;
|
||||
|
||||
/* Getting write op params from the input parameter */
|
||||
data = params->data[data_arr_idx];
|
||||
mask = params->mask;
|
||||
|
||||
/* an empty operation */
|
||||
if (data == NO_DATA)
|
||||
return MV_OK;
|
||||
|
||||
/* get updated base address since it can be different between Serdes */
|
||||
CHECK_STATUS(hws_get_ext_base_addr(serdes_num, params->unit_base_reg,
|
||||
params->unit_offset,
|
||||
&unit_base_reg, &unit_offset));
|
||||
|
||||
/* Address calculation */
|
||||
reg_addr = unit_base_reg + unit_offset * serdes_num;
|
||||
|
||||
#ifdef SEQ_DEBUG
|
||||
printf("Write: 0x%x: 0x%x (mask 0x%x) - ", reg_addr, data, mask);
|
||||
#endif
|
||||
/* Reading old value */
|
||||
reg_data = reg_read(reg_addr);
|
||||
reg_data &= (~mask);
|
||||
|
||||
/* Writing new data */
|
||||
data &= mask;
|
||||
reg_data |= data;
|
||||
reg_write(reg_addr, reg_data);
|
||||
|
||||
#ifdef SEQ_DEBUG
|
||||
printf(" - 0x%x\n", reg_data);
|
||||
#endif
|
||||
|
||||
return MV_OK;
|
||||
}
|
||||
|
||||
int delay_op_execute(u32 serdes_num, struct op_params *params, u32 data_arr_idx)
|
||||
{
|
||||
u32 delay;
|
||||
|
||||
/* Getting delay op params from the input parameter */
|
||||
delay = params->wait_time;
|
||||
#ifdef SEQ_DEBUG
|
||||
printf("Delay: %d\n", delay);
|
||||
#endif
|
||||
mdelay(delay);
|
||||
|
||||
return MV_OK;
|
||||
}
|
||||
|
||||
int poll_op_execute(u32 serdes_num, struct op_params *params, u32 data_arr_idx)
|
||||
{
|
||||
u32 unit_base_reg, unit_offset, data, mask, num_of_loops, wait_time;
|
||||
u32 poll_counter = 0;
|
||||
u32 reg_addr, reg_data;
|
||||
|
||||
/* Getting poll op params from the input parameter */
|
||||
data = params->data[data_arr_idx];
|
||||
mask = params->mask;
|
||||
num_of_loops = params->num_of_loops;
|
||||
wait_time = params->wait_time;
|
||||
|
||||
/* an empty operation */
|
||||
if (data == NO_DATA)
|
||||
return MV_OK;
|
||||
|
||||
/* get updated base address since it can be different between Serdes */
|
||||
CHECK_STATUS(hws_get_ext_base_addr(serdes_num, params->unit_base_reg,
|
||||
params->unit_offset,
|
||||
&unit_base_reg, &unit_offset));
|
||||
|
||||
/* Address calculation */
|
||||
reg_addr = unit_base_reg + unit_offset * serdes_num;
|
||||
|
||||
/* Polling */
|
||||
#ifdef SEQ_DEBUG
|
||||
printf("Poll: 0x%x: 0x%x (mask 0x%x)\n", reg_addr, data, mask);
|
||||
#endif
|
||||
|
||||
do {
|
||||
reg_data = reg_read(reg_addr) & mask;
|
||||
poll_counter++;
|
||||
udelay(wait_time);
|
||||
} while ((reg_data != data) && (poll_counter < num_of_loops));
|
||||
|
||||
if ((poll_counter >= num_of_loops) && (reg_data != data)) {
|
||||
DEBUG_INIT_S("poll_op_execute: TIMEOUT\n");
|
||||
return MV_TIMEOUT;
|
||||
}
|
||||
|
||||
return MV_OK;
|
||||
}
|
||||
|
||||
enum mv_op get_cfg_seq_op(struct op_params *params)
|
||||
{
|
||||
if (params->wait_time == 0)
|
||||
return WRITE_OP;
|
||||
else if (params->num_of_loops == 0)
|
||||
return DELAY_OP;
|
||||
|
||||
return POLL_OP;
|
||||
}
|
||||
|
||||
int mv_seq_exec(u32 serdes_num, u32 seq_id)
|
||||
{
|
||||
u32 seq_idx;
|
||||
struct op_params *seq_arr;
|
||||
u32 seq_size;
|
||||
u32 data_arr_idx;
|
||||
enum mv_op curr_op;
|
||||
|
||||
DB(printf("\n### mv_seq_exec ###\n"));
|
||||
DB(printf("seq id: %d\n", seq_id));
|
||||
|
||||
if (hws_is_serdes_active(serdes_num) != 1) {
|
||||
printf("mv_seq_exec_ext:Error: SerDes lane %d is not valid\n",
|
||||
serdes_num);
|
||||
return MV_BAD_PARAM;
|
||||
}
|
||||
|
||||
seq_arr = serdes_seq_db[seq_id].op_params_ptr;
|
||||
seq_size = serdes_seq_db[seq_id].cfg_seq_size;
|
||||
data_arr_idx = serdes_seq_db[seq_id].data_arr_idx;
|
||||
|
||||
DB(printf("seq_size: %d\n", seq_size));
|
||||
DB(printf("data_arr_idx: %d\n", data_arr_idx));
|
||||
|
||||
/* Executing the sequence operations */
|
||||
for (seq_idx = 0; seq_idx < seq_size; seq_idx++) {
|
||||
curr_op = get_cfg_seq_op(&seq_arr[seq_idx]);
|
||||
op_execute_func_arr[curr_op](serdes_num, &seq_arr[seq_idx],
|
||||
data_arr_idx);
|
||||
}
|
||||
|
||||
return MV_OK;
|
||||
}
|
65
arch/arm/mach-mvebu/serdes/a38x/seq_exec.h
Normal file
65
arch/arm/mach-mvebu/serdes/a38x/seq_exec.h
Normal file
|
@ -0,0 +1,65 @@
|
|||
/*
|
||||
* Copyright (C) Marvell International Ltd. and its affiliates
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0
|
||||
*/
|
||||
|
||||
#ifndef _SEQ_EXEC_H
|
||||
#define _SEQ_EXEC_H
|
||||
|
||||
#define NA 0xff
|
||||
#define DEFAULT_PARAM 0
|
||||
#define MV_BOARD_TCLK_ERROR 0xffffffff
|
||||
|
||||
#define NO_DATA 0xffffffff
|
||||
#define MAX_DATA_ARRAY 5
|
||||
#define FIRST_CELL 0
|
||||
|
||||
/* Operation types */
|
||||
enum mv_op {
|
||||
WRITE_OP,
|
||||
DELAY_OP,
|
||||
POLL_OP,
|
||||
};
|
||||
|
||||
/* Operation parameters */
|
||||
struct op_params {
|
||||
u32 unit_base_reg;
|
||||
u32 unit_offset;
|
||||
u32 mask;
|
||||
u32 data[MAX_DATA_ARRAY]; /* data array */
|
||||
u8 wait_time; /* msec */
|
||||
u16 num_of_loops; /* for polling only */
|
||||
};
|
||||
|
||||
/*
|
||||
* Sequence parameters. Each sequence contains:
|
||||
* 1. Sequence id.
|
||||
* 2. Sequence size (total amount of operations during the sequence)
|
||||
* 3. a series of operations. operations can be write, poll or delay
|
||||
* 4. index in the data array (the entry where the relevant data sits)
|
||||
*/
|
||||
struct cfg_seq {
|
||||
struct op_params *op_params_ptr;
|
||||
u8 cfg_seq_size;
|
||||
u8 data_arr_idx;
|
||||
};
|
||||
|
||||
extern struct cfg_seq serdes_seq_db[];
|
||||
|
||||
/*
|
||||
* A generic function type for executing an operation (write, poll or delay)
|
||||
*/
|
||||
typedef int (*op_execute_func_ptr)(u32 serdes_num, struct op_params *params,
|
||||
u32 data_arr_idx);
|
||||
|
||||
/* Specific functions for executing each operation */
|
||||
int write_op_execute(u32 serdes_num, struct op_params *params,
|
||||
u32 data_arr_idx);
|
||||
int delay_op_execute(u32 serdes_num, struct op_params *params,
|
||||
u32 data_arr_idx);
|
||||
int poll_op_execute(u32 serdes_num, struct op_params *params, u32 data_arr_idx);
|
||||
enum mv_op get_cfg_seq_op(struct op_params *params);
|
||||
int mv_seq_exec(u32 serdes_num, u32 seq_id);
|
||||
|
||||
#endif /*_SEQ_EXEC_H*/
|
388
arch/arm/mach-mvebu/serdes/a38x/sys_env_lib.c
Normal file
388
arch/arm/mach-mvebu/serdes/a38x/sys_env_lib.c
Normal file
|
@ -0,0 +1,388 @@
|
|||
/*
|
||||
* Copyright (C) Marvell International Ltd. and its affiliates
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <i2c.h>
|
||||
#include <spl.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/arch/cpu.h>
|
||||
#include <asm/arch/soc.h>
|
||||
|
||||
#include "seq_exec.h"
|
||||
#include "sys_env_lib.h"
|
||||
|
||||
#include "../../../drivers/ddr/marvell/a38x/ddr3_a38x.h"
|
||||
|
||||
#ifdef CONFIG_ARMADA_38X
|
||||
enum unit_id sys_env_soc_unit_nums[MAX_UNITS_ID][MAX_DEV_ID_NUM] = {
|
||||
/* 6820 6810 6811 6828 */
|
||||
/* PEX_UNIT_ID */ { 4, 3, 3, 4},
|
||||
/* ETH_GIG_UNIT_ID */ { 3, 2, 3, 3},
|
||||
/* USB3H_UNIT_ID */ { 2, 2, 2, 2},
|
||||
/* USB3D_UNIT_ID */ { 1, 1, 1, 1},
|
||||
/* SATA_UNIT_ID */ { 2, 2, 2, 4},
|
||||
/* QSGMII_UNIT_ID */ { 1, 0, 0, 1},
|
||||
/* XAUI_UNIT_ID */ { 0, 0, 0, 0},
|
||||
/* RXAUI_UNIT_ID */ { 0, 0, 0, 0}
|
||||
};
|
||||
#else /* if (CONFIG_ARMADA_39X) */
|
||||
enum unit_id sys_env_soc_unit_nums[MAX_UNITS_ID][MAX_DEV_ID_NUM] = {
|
||||
/* 6920 6928 */
|
||||
/* PEX_UNIT_ID */ { 4, 4},
|
||||
/* ETH_GIG_UNIT_ID */ { 3, 4},
|
||||
/* USB3H_UNIT_ID */ { 1, 2},
|
||||
/* USB3D_UNIT_ID */ { 0, 1},
|
||||
/* SATA_UNIT_ID */ { 0, 4},
|
||||
/* QSGMII_UNIT_ID */ { 0, 1},
|
||||
/* XAUI_UNIT_ID */ { 1, 1},
|
||||
/* RXAUI_UNIT_ID */ { 1, 1}
|
||||
};
|
||||
#endif
|
||||
|
||||
u32 g_dev_id = -1;
|
||||
|
||||
u32 mv_board_id_get(void)
|
||||
{
|
||||
#if defined(CONFIG_DB_88F6820_GP)
|
||||
return DB_GP_68XX_ID;
|
||||
#else
|
||||
/*
|
||||
* Return 0 here for custom board as this should not be used
|
||||
* for custom boards.
|
||||
*/
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
u32 mv_board_tclk_get(void)
|
||||
{
|
||||
u32 value;
|
||||
|
||||
value = (reg_read(DEVICE_SAMPLE_AT_RESET1_REG) >> 15) & 0x1;
|
||||
|
||||
switch (value) {
|
||||
case (0x0):
|
||||
return 250000000;
|
||||
case (0x1):
|
||||
return 200000000;
|
||||
default:
|
||||
return 0xffffffff;
|
||||
}
|
||||
}
|
||||
|
||||
u32 mv_board_id_index_get(u32 board_id)
|
||||
{
|
||||
/*
|
||||
* Marvell Boards use 0x10 as base for Board ID:
|
||||
* mask MSB to receive index for board ID
|
||||
*/
|
||||
return board_id & (MARVELL_BOARD_ID_MASK - 1);
|
||||
}
|
||||
|
||||
/*
|
||||
* sys_env_suspend_wakeup_check
|
||||
* DESCRIPTION: Reads GPIO input for suspend-wakeup indication.
|
||||
* INPUT: None.
|
||||
* OUTPUT:
|
||||
* RETURNS: u32 indicating suspend wakeup status:
|
||||
* 0 - Not supported,
|
||||
* 1 - supported: read magic word detect wakeup,
|
||||
* 2 - detected wakeup from GPIO.
|
||||
*/
|
||||
enum suspend_wakeup_status sys_env_suspend_wakeup_check(void)
|
||||
{
|
||||
u32 reg, board_id_index, gpio;
|
||||
struct board_wakeup_gpio board_gpio[] = MV_BOARD_WAKEUP_GPIO_INFO;
|
||||
|
||||
board_id_index = mv_board_id_index_get(mv_board_id_get());
|
||||
if (!(sizeof(board_gpio) / sizeof(struct board_wakeup_gpio) >
|
||||
board_id_index)) {
|
||||
printf("\n_failed loading Suspend-Wakeup information (invalid board ID)\n");
|
||||
return SUSPEND_WAKEUP_DISABLED;
|
||||
}
|
||||
|
||||
/*
|
||||
* - Detect if Suspend-Wakeup is supported on current board
|
||||
* - Fetch the GPIO number for wakeup status input indication
|
||||
*/
|
||||
if (board_gpio[board_id_index].gpio_num == -1) {
|
||||
/* Suspend to RAM is not supported */
|
||||
return SUSPEND_WAKEUP_DISABLED;
|
||||
} else if (board_gpio[board_id_index].gpio_num == -2) {
|
||||
/*
|
||||
* Suspend to RAM is supported but GPIO indication is
|
||||
* not implemented - Skip
|
||||
*/
|
||||
return SUSPEND_WAKEUP_ENABLED;
|
||||
} else {
|
||||
gpio = board_gpio[board_id_index].gpio_num;
|
||||
}
|
||||
|
||||
/* Initialize MPP for GPIO (set MPP = 0x0) */
|
||||
reg = reg_read(MPP_CONTROL_REG(MPP_REG_NUM(gpio)));
|
||||
/* reset MPP21 to 0x0, keep rest of MPP settings*/
|
||||
reg &= ~MPP_MASK(gpio);
|
||||
reg_write(MPP_CONTROL_REG(MPP_REG_NUM(gpio)), reg);
|
||||
|
||||
/* Initialize GPIO as input */
|
||||
reg = reg_read(GPP_DATA_OUT_EN_REG(GPP_REG_NUM(gpio)));
|
||||
reg |= GPP_MASK(gpio);
|
||||
reg_write(GPP_DATA_OUT_EN_REG(GPP_REG_NUM(gpio)), reg);
|
||||
|
||||
/*
|
||||
* Check GPP for input status from PIC: 0 - regular init,
|
||||
* 1 - suspend wakeup
|
||||
*/
|
||||
reg = reg_read(GPP_DATA_IN_REG(GPP_REG_NUM(gpio)));
|
||||
|
||||
/* if GPIO is ON: wakeup from S2RAM indication detected */
|
||||
return (reg & GPP_MASK(gpio)) ? SUSPEND_WAKEUP_ENABLED_GPIO_DETECTED :
|
||||
SUSPEND_WAKEUP_DISABLED;
|
||||
}
|
||||
|
||||
/*
|
||||
* mv_ctrl_dev_id_index_get
|
||||
*
|
||||
* DESCRIPTION: return SOC device index
|
||||
* INPUT: None
|
||||
* OUTPUT: None
|
||||
* RETURN:
|
||||
* return SOC device index
|
||||
*/
|
||||
u32 sys_env_id_index_get(u32 ctrl_model)
|
||||
{
|
||||
switch (ctrl_model) {
|
||||
case MV_6820_DEV_ID:
|
||||
return MV_6820_INDEX;
|
||||
case MV_6810_DEV_ID:
|
||||
return MV_6810_INDEX;
|
||||
case MV_6811_DEV_ID:
|
||||
return MV_6811_INDEX;
|
||||
case MV_6828_DEV_ID:
|
||||
return MV_6828_INDEX;
|
||||
case MV_6920_DEV_ID:
|
||||
return MV_6920_INDEX;
|
||||
case MV_6928_DEV_ID:
|
||||
return MV_6928_INDEX;
|
||||
default:
|
||||
return MV_6820_INDEX;
|
||||
}
|
||||
}
|
||||
|
||||
u32 sys_env_unit_max_num_get(enum unit_id unit)
|
||||
{
|
||||
u32 dev_id_index;
|
||||
|
||||
if (unit >= MAX_UNITS_ID) {
|
||||
printf("%s: Error: Wrong unit type (%u)\n", __func__, unit);
|
||||
return 0;
|
||||
}
|
||||
|
||||
dev_id_index = sys_env_id_index_get(sys_env_model_get());
|
||||
return sys_env_soc_unit_nums[unit][dev_id_index];
|
||||
}
|
||||
|
||||
/*
|
||||
* sys_env_model_get
|
||||
* DESCRIPTION: Returns 16bit describing the device model (ID) as defined
|
||||
* in Vendor ID configuration register
|
||||
*/
|
||||
u16 sys_env_model_get(void)
|
||||
{
|
||||
u32 default_ctrl_id, ctrl_id = reg_read(DEV_ID_REG);
|
||||
ctrl_id = (ctrl_id & (DEV_ID_REG_DEVICE_ID_MASK)) >>
|
||||
DEV_ID_REG_DEVICE_ID_OFFS;
|
||||
|
||||
switch (ctrl_id) {
|
||||
case MV_6820_DEV_ID:
|
||||
case MV_6810_DEV_ID:
|
||||
case MV_6811_DEV_ID:
|
||||
case MV_6828_DEV_ID:
|
||||
case MV_6920_DEV_ID:
|
||||
case MV_6928_DEV_ID:
|
||||
return ctrl_id;
|
||||
default:
|
||||
/* Device ID Default for A38x: 6820 , for A39x: 6920 */
|
||||
#ifdef CONFIG_ARMADA_38X
|
||||
default_ctrl_id = MV_6820_DEV_ID;
|
||||
#else
|
||||
default_ctrl_id = MV_6920_DEV_ID;
|
||||
#endif
|
||||
printf("%s: Error retrieving device ID (%x), using default ID = %x\n",
|
||||
__func__, ctrl_id, default_ctrl_id);
|
||||
return default_ctrl_id;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* sys_env_device_id_get
|
||||
* DESCRIPTION: Returns enum (0..7) index of the device model (ID)
|
||||
*/
|
||||
u32 sys_env_device_id_get(void)
|
||||
{
|
||||
char *device_id_str[7] = {
|
||||
"6810", "6820", "6811", "6828", "NONE", "6920", "6928"
|
||||
};
|
||||
|
||||
if (g_dev_id != -1)
|
||||
return g_dev_id;
|
||||
|
||||
g_dev_id = reg_read(DEVICE_SAMPLE_AT_RESET1_REG);
|
||||
g_dev_id = g_dev_id >> SAR_DEV_ID_OFFS & SAR_DEV_ID_MASK;
|
||||
printf("Detected Device ID %s\n", device_id_str[g_dev_id]);
|
||||
|
||||
return g_dev_id;
|
||||
}
|
||||
|
||||
#ifdef MV_DDR_TOPOLOGY_UPDATE_FROM_TWSI
|
||||
/*
|
||||
* sys_env_get_topology_update_info
|
||||
* DESCRIPTION: Read TWSI fields to update DDR topology structure
|
||||
* INPUT: None
|
||||
* OUTPUT: None, 0 means no topology update
|
||||
* RETURN:
|
||||
* Bit mask of changes topology features
|
||||
*/
|
||||
#ifdef CONFIG_ARMADA_39X
|
||||
u32 sys_env_get_topology_update_info(
|
||||
struct topology_update_info *tui)
|
||||
{
|
||||
/* Set 16/32 bit configuration*/
|
||||
tui->update_width = 1;
|
||||
tui->width = TOPOLOGY_UPDATE_WIDTH_32BIT;
|
||||
|
||||
#ifdef CONFIG_DDR3
|
||||
if (1 == sys_env_config_get(MV_CONFIG_DDR_BUSWIDTH)) {
|
||||
/* 16bit */
|
||||
tui->width = TOPOLOGY_UPDATE_WIDTH_16BIT;
|
||||
} else {
|
||||
/* 32bit */
|
||||
tui->width = TOPOLOGY_UPDATE_WIDTH_32BIT;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Set ECC/no ECC bit configuration */
|
||||
tui->update_ecc = 1;
|
||||
if (0 == sys_env_config_get(MV_CONFIG_DDR_ECC_EN)) {
|
||||
/* NO ECC */
|
||||
tui->ecc = TOPOLOGY_UPDATE_ECC_OFF;
|
||||
} else {
|
||||
/* ECC */
|
||||
tui->ecc = TOPOLOGY_UPDATE_ECC_ON;
|
||||
}
|
||||
|
||||
tui->update_ecc_pup3_mode = 1;
|
||||
tui->ecc_pup_mode_offset = TOPOLOGY_UPDATE_ECC_OFFSET_PUP4;
|
||||
|
||||
return MV_OK;
|
||||
}
|
||||
#else /*CONFIG_ARMADA_38X*/
|
||||
u32 sys_env_get_topology_update_info(
|
||||
struct topology_update_info *tui)
|
||||
{
|
||||
u8 config_val;
|
||||
u8 ecc_mode[A38X_MV_MAX_MARVELL_BOARD_ID -
|
||||
A38X_MARVELL_BOARD_ID_BASE][5] = TOPOLOGY_UPDATE;
|
||||
u8 board_id = mv_board_id_get();
|
||||
int ret;
|
||||
|
||||
board_id = mv_board_id_index_get(board_id);
|
||||
ret = i2c_read(EEPROM_I2C_ADDR, 0, 2, &config_val, 1);
|
||||
if (ret) {
|
||||
DEBUG_INIT_S("sys_env_get_topology_update_info: TWSI Read failed\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Set 16/32 bit configuration */
|
||||
if ((0 == (config_val & DDR_SATR_CONFIG_MASK_WIDTH)) ||
|
||||
(ecc_mode[board_id][TOPOLOGY_UPDATE_32BIT] == 0)) {
|
||||
/* 16bit by SatR of 32bit mode not supported for the board */
|
||||
if ((ecc_mode[board_id][TOPOLOGY_UPDATE_16BIT] != 0)) {
|
||||
tui->update_width = 1;
|
||||
tui->width = TOPOLOGY_UPDATE_WIDTH_16BIT;
|
||||
}
|
||||
} else {
|
||||
/* 32bit */
|
||||
if ((ecc_mode[board_id][TOPOLOGY_UPDATE_32BIT] != 0)) {
|
||||
tui->update_width = 1;
|
||||
tui->width = TOPOLOGY_UPDATE_WIDTH_32BIT;
|
||||
}
|
||||
}
|
||||
|
||||
/* Set ECC/no ECC bit configuration */
|
||||
if (0 == (config_val & DDR_SATR_CONFIG_MASK_ECC)) {
|
||||
/* NO ECC */
|
||||
tui->update_ecc = 1;
|
||||
tui->ecc = TOPOLOGY_UPDATE_ECC_OFF;
|
||||
} else {
|
||||
/* ECC */
|
||||
if ((ecc_mode[board_id][TOPOLOGY_UPDATE_32BIT_ECC] != 0) ||
|
||||
(ecc_mode[board_id][TOPOLOGY_UPDATE_16BIT_ECC] != 0) ||
|
||||
(ecc_mode[board_id][TOPOLOGY_UPDATE_16BIT_ECC_PUP3] != 0)) {
|
||||
tui->update_ecc = 1;
|
||||
tui->ecc = TOPOLOGY_UPDATE_ECC_ON;
|
||||
}
|
||||
}
|
||||
|
||||
/* Set ECC pup bit configuration */
|
||||
if (0 == (config_val & DDR_SATR_CONFIG_MASK_ECC_PUP)) {
|
||||
/* PUP3 */
|
||||
/*
|
||||
* Check if PUP3 configuration allowed, if not -
|
||||
* force Pup4 with warning message
|
||||
*/
|
||||
if ((ecc_mode[board_id][TOPOLOGY_UPDATE_16BIT_ECC_PUP3] != 0)) {
|
||||
if (tui->width == TOPOLOGY_UPDATE_WIDTH_16BIT) {
|
||||
tui->update_ecc_pup3_mode = 1;
|
||||
tui->ecc_pup_mode_offset =
|
||||
TOPOLOGY_UPDATE_ECC_OFFSET_PUP3;
|
||||
} else {
|
||||
if ((ecc_mode[board_id][TOPOLOGY_UPDATE_32BIT_ECC] != 0)) {
|
||||
printf("DDR Topology Update: ECC PUP3 not valid for 32bit mode, force ECC in PUP4\n");
|
||||
tui->update_ecc_pup3_mode = 1;
|
||||
tui->ecc_pup_mode_offset =
|
||||
TOPOLOGY_UPDATE_ECC_OFFSET_PUP4;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (ecc_mode[board_id][TOPOLOGY_UPDATE_16BIT_ECC] !=
|
||||
0) {
|
||||
printf("DDR Topology Update: ECC on PUP3 not supported, force ECC on PUP4\n");
|
||||
tui->update_ecc_pup3_mode = 1;
|
||||
tui->ecc_pup_mode_offset =
|
||||
TOPOLOGY_UPDATE_ECC_OFFSET_PUP4;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* PUP4 */
|
||||
if ((ecc_mode[board_id][TOPOLOGY_UPDATE_32BIT_ECC] != 0) ||
|
||||
(ecc_mode[board_id][TOPOLOGY_UPDATE_16BIT_ECC] != 0)) {
|
||||
tui->update_ecc_pup3_mode = 1;
|
||||
tui->ecc_pup_mode_offset =
|
||||
TOPOLOGY_UPDATE_ECC_OFFSET_PUP4;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Check for forbidden ECC mode,
|
||||
* if by default width and pup selection set 32bit ECC mode and this
|
||||
* mode not supported for the board - config 16bit with ECC on PUP3
|
||||
*/
|
||||
if ((tui->ecc == TOPOLOGY_UPDATE_ECC_ON) &&
|
||||
(tui->width == TOPOLOGY_UPDATE_WIDTH_32BIT)) {
|
||||
if (ecc_mode[board_id][TOPOLOGY_UPDATE_32BIT_ECC] == 0) {
|
||||
printf("DDR Topology Update: 32bit mode with ECC not allowed on this board, forced 16bit with ECC on PUP3\n");
|
||||
tui->width = TOPOLOGY_UPDATE_WIDTH_16BIT;
|
||||
tui->update_ecc_pup3_mode = 1;
|
||||
tui->ecc_pup_mode_offset =
|
||||
TOPOLOGY_UPDATE_ECC_OFFSET_PUP3;
|
||||
}
|
||||
}
|
||||
|
||||
return MV_OK;
|
||||
}
|
||||
#endif /* CONFIG_ARMADA_38X */
|
||||
#endif /* MV_DDR_TOPOLOGY_UPDATE_FROM_TWSI */
|
371
arch/arm/mach-mvebu/serdes/a38x/sys_env_lib.h
Normal file
371
arch/arm/mach-mvebu/serdes/a38x/sys_env_lib.h
Normal file
|
@ -0,0 +1,371 @@
|
|||
/*
|
||||
* Copyright (C) Marvell International Ltd. and its affiliates
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0
|
||||
*/
|
||||
|
||||
#ifndef _SYS_ENV_LIB_H
|
||||
#define _SYS_ENV_LIB_H
|
||||
|
||||
#include "../../../drivers/ddr/marvell/a38x/ddr3_init.h"
|
||||
#include "../../../drivers/ddr/marvell/a38x/ddr3_hws_hw_training.h"
|
||||
|
||||
/* Serdes definitions */
|
||||
#define COMMON_PHY_BASE_ADDR 0x18300
|
||||
|
||||
#define DEVICE_CONFIGURATION_REG0 0x18284
|
||||
#define DEVICE_CONFIGURATION_REG1 0x18288
|
||||
#define COMMON_PHY_CONFIGURATION1_REG 0x18300
|
||||
#define COMMON_PHY_CONFIGURATION2_REG 0x18304
|
||||
#define COMMON_PHY_CONFIGURATION4_REG 0x1830c
|
||||
#define COMMON_PHY_STATUS1_REG 0x18318
|
||||
#define COMMON_PHYS_SELECTORS_REG 0x183fc
|
||||
#define SOC_CONTROL_REG1 0x18204
|
||||
#define GENERAL_PURPOSE_RESERVED0_REG 0x182e0
|
||||
#define GBE_CONFIGURATION_REG 0x18460
|
||||
#define DEVICE_SAMPLE_AT_RESET1_REG 0x18600
|
||||
#define DEVICE_SAMPLE_AT_RESET2_REG 0x18604
|
||||
#define DEV_ID_REG 0x18238
|
||||
|
||||
#define CORE_PLL_PARAMETERS_REG 0xe42e0
|
||||
#define CORE_PLL_CONFIG_REG 0xe42e4
|
||||
|
||||
#define QSGMII_CONTROL_REG1 0x18494
|
||||
|
||||
#define DEV_ID_REG_DEVICE_ID_OFFS 16
|
||||
#define DEV_ID_REG_DEVICE_ID_MASK 0xffff0000
|
||||
|
||||
#define SAR_DEV_ID_OFFS 27
|
||||
#define SAR_DEV_ID_MASK 0x7
|
||||
|
||||
#define POWER_AND_PLL_CTRL_REG 0xa0004
|
||||
#define CALIBRATION_CTRL_REG 0xa0008
|
||||
#define DFE_REG0 0xa001c
|
||||
#define DFE_REG3 0xa0028
|
||||
#define RESET_DFE_REG 0xa0148
|
||||
#define LOOPBACK_REG 0xa008c
|
||||
#define SYNC_PATTERN_REG 0xa0090
|
||||
#define INTERFACE_REG 0xa0094
|
||||
#define ISOLATE_REG 0xa0098
|
||||
#define MISC_REG 0xa013c
|
||||
#define GLUE_REG 0xa0140
|
||||
#define GENERATION_DIVIDER_FORCE_REG 0xa0144
|
||||
#define PCIE_REG0 0xa0120
|
||||
#define LANE_ALIGN_REG0 0xa0124
|
||||
#define SQUELCH_FFE_SETTING_REG 0xa0018
|
||||
#define G1_SETTINGS_0_REG 0xa0034
|
||||
#define G1_SETTINGS_1_REG 0xa0038
|
||||
#define G1_SETTINGS_3_REG 0xa0440
|
||||
#define G1_SETTINGS_4_REG 0xa0444
|
||||
#define G2_SETTINGS_0_REG 0xa003c
|
||||
#define G2_SETTINGS_1_REG 0xa0040
|
||||
#define G2_SETTINGS_2_REG 0xa00f8
|
||||
#define G2_SETTINGS_3_REG 0xa0448
|
||||
#define G2_SETTINGS_4_REG 0xa044c
|
||||
#define G3_SETTINGS_0_REG 0xa0044
|
||||
#define G3_SETTINGS_1_REG 0xa0048
|
||||
#define G3_SETTINGS_3_REG 0xa0450
|
||||
#define G3_SETTINGS_4_REG 0xa0454
|
||||
#define VTHIMPCAL_CTRL_REG 0xa0104
|
||||
#define REF_REG0 0xa0134
|
||||
#define CAL_REG6 0xa0168
|
||||
#define RX_REG2 0xa0184
|
||||
#define RX_REG3 0xa0188
|
||||
#define PCIE_REG1 0xa0288
|
||||
#define PCIE_REG3 0xa0290
|
||||
#define LANE_CFG1_REG 0xa0604
|
||||
#define LANE_CFG4_REG 0xa0620
|
||||
#define LANE_CFG5_REG 0xa0624
|
||||
#define GLOBAL_CLK_CTRL 0xa0704
|
||||
#define GLOBAL_MISC_CTRL 0xa0718
|
||||
#define GLOBAL_CLK_SRC_HI 0xa0710
|
||||
|
||||
#define GLOBAL_CLK_CTRL 0xa0704
|
||||
#define GLOBAL_MISC_CTRL 0xa0718
|
||||
#define GLOBAL_PM_CTRL 0xa0740
|
||||
|
||||
/* SATA registers */
|
||||
#define SATA_CTRL_REG_IND_ADDR 0xa80a0
|
||||
#define SATA_CTRL_REG_IND_DATA 0xa80a4
|
||||
|
||||
#define SATA_VENDOR_PORT_0_REG_ADDR 0xa8178
|
||||
#define SATA_VENDOR_PORT_1_REG_ADDR 0xa81f8
|
||||
#define SATA_VENDOR_PORT_0_REG_DATA 0xa817c
|
||||
#define SATA_VENDOR_PORT_1_REG_DATA 0xa81fc
|
||||
|
||||
/* Reference clock values and mask */
|
||||
#define POWER_AND_PLL_CTRL_REG_100MHZ_VAL 0x0
|
||||
#define POWER_AND_PLL_CTRL_REG_25MHZ_VAL_1 0x1
|
||||
#define POWER_AND_PLL_CTRL_REG_25MHZ_VAL_2 0x2
|
||||
#define POWER_AND_PLL_CTRL_REG_40MHZ_VAL 0x3
|
||||
#define GLOBAL_PM_CTRL_REG_25MHZ_VAL 0x7
|
||||
#define GLOBAL_PM_CTRL_REG_40MHZ_VAL 0xc
|
||||
#define LANE_CFG4_REG_25MHZ_VAL 0x200
|
||||
#define LANE_CFG4_REG_40MHZ_VAL 0x300
|
||||
|
||||
#define POWER_AND_PLL_CTRL_REG_MASK (~(0x1f))
|
||||
#define GLOBAL_PM_CTRL_REG_MASK (~(0xff))
|
||||
#define LANE_CFG4_REG_MASK (~(0x1f00))
|
||||
|
||||
#define REF_CLK_SELECTOR_VAL_PEX0(reg_val) (reg_val >> 2) & 0x1
|
||||
#define REF_CLK_SELECTOR_VAL_PEX1(reg_val) (reg_val >> 3) & 0x1
|
||||
#define REF_CLK_SELECTOR_VAL_PEX2(reg_val) (reg_val >> 30) & 0x1
|
||||
#define REF_CLK_SELECTOR_VAL_PEX3(reg_val) (reg_val >> 31) & 0x1
|
||||
#define REF_CLK_SELECTOR_VAL(reg_val) (reg_val & 0x1)
|
||||
|
||||
#define MAX_SELECTOR_VAL 10
|
||||
|
||||
/* TWSI addresses */
|
||||
/* starting from A38x A0, i2c address of EEPROM is 0x57 */
|
||||
#ifdef CONFIG_ARMADA_39X
|
||||
#define EEPROM_I2C_ADDR 0x50
|
||||
#else
|
||||
#define EEPROM_I2C_ADDR (sys_env_device_rev_get() == \
|
||||
MV_88F68XX_Z1_ID ? 0x50 : 0x57)
|
||||
#endif
|
||||
#define RD_GET_MODE_ADDR 0x4c
|
||||
#define DB_GET_MODE_SLM1363_ADDR 0x25
|
||||
#define DB_GET_MODE_SLM1364_ADDR 0x24
|
||||
#define DB381_GET_MODE_SLM1426_1427_ADDR 0x56
|
||||
|
||||
/* DB-BP Board 'SatR' mapping */
|
||||
#define SATR_DB_LANE1_MAX_OPTIONS 7
|
||||
#define SATR_DB_LANE1_CFG_MASK 0x7
|
||||
#define SATR_DB_LANE1_CFG_OFFSET 0
|
||||
#define SATR_DB_LANE2_MAX_OPTIONS 4
|
||||
#define SATR_DB_LANE2_CFG_MASK 0x38
|
||||
#define SATR_DB_LANE2_CFG_OFFSET 3
|
||||
|
||||
/* GP Board 'SatR' mapping */
|
||||
#define SATR_GP_LANE1_CFG_MASK 0x4
|
||||
#define SATR_GP_LANE1_CFG_OFFSET 2
|
||||
#define SATR_GP_LANE2_CFG_MASK 0x8
|
||||
#define SATR_GP_LANE2_CFG_OFFSET 3
|
||||
|
||||
/* For setting MPP2 and MPP3 to be TWSI mode and MPP 0,1 to UART mode */
|
||||
#define MPP_CTRL_REG 0x18000
|
||||
#define MPP_SET_MASK (~(0xffff))
|
||||
#define MPP_SET_DATA (0x1111)
|
||||
#define MPP_UART1_SET_MASK (~(0xff000))
|
||||
#define MPP_UART1_SET_DATA (0x66000)
|
||||
|
||||
#define AVS_DEBUG_CNTR_REG 0xe4124
|
||||
#define AVS_DEBUG_CNTR_DEFAULT_VALUE 0x08008073
|
||||
|
||||
#define AVS_ENABLED_CONTROL 0xe4130
|
||||
#define AVS_LOW_VDD_LIMIT_OFFS 4
|
||||
#define AVS_LOW_VDD_LIMIT_MASK (0xff << AVS_LOW_VDD_LIMIT_OFFS)
|
||||
#define AVS_LOW_VDD_LIMIT_VAL (0x27 << AVS_LOW_VDD_LIMIT_OFFS)
|
||||
|
||||
#define AVS_HIGH_VDD_LIMIT_OFFS 12
|
||||
#define AVS_HIGH_VDD_LIMIT_MASK (0xff << AVS_HIGH_VDD_LIMIT_OFFS)
|
||||
#define AVS_HIGH_VDD_LIMIT_VAL (0x27 << AVS_HIGH_VDD_LIMIT_OFFS)
|
||||
|
||||
/* Board ID numbers */
|
||||
#define MARVELL_BOARD_ID_MASK 0x10
|
||||
/* Customer boards for A38x */
|
||||
#define A38X_CUSTOMER_BOARD_ID_BASE 0x0
|
||||
#define A38X_CUSTOMER_BOARD_ID0 (A38X_CUSTOMER_BOARD_ID_BASE + 0)
|
||||
#define A38X_CUSTOMER_BOARD_ID1 (A38X_CUSTOMER_BOARD_ID_BASE + 1)
|
||||
#define A38X_MV_MAX_CUSTOMER_BOARD_ID (A38X_CUSTOMER_BOARD_ID_BASE + 2)
|
||||
#define A38X_MV_CUSTOMER_BOARD_NUM (A38X_MV_MAX_CUSTOMER_BOARD_ID - \
|
||||
A38X_CUSTOMER_BOARD_ID_BASE)
|
||||
|
||||
/* Marvell boards for A38x */
|
||||
#define A38X_MARVELL_BOARD_ID_BASE 0x10
|
||||
#define RD_NAS_68XX_ID (A38X_MARVELL_BOARD_ID_BASE + 0)
|
||||
#define DB_68XX_ID (A38X_MARVELL_BOARD_ID_BASE + 1)
|
||||
#define RD_AP_68XX_ID (A38X_MARVELL_BOARD_ID_BASE + 2)
|
||||
#define DB_AP_68XX_ID (A38X_MARVELL_BOARD_ID_BASE + 3)
|
||||
#define DB_GP_68XX_ID (A38X_MARVELL_BOARD_ID_BASE + 4)
|
||||
#define DB_BP_6821_ID (A38X_MARVELL_BOARD_ID_BASE + 5)
|
||||
#define DB_AMC_6820_ID (A38X_MARVELL_BOARD_ID_BASE + 6)
|
||||
#define A38X_MV_MAX_MARVELL_BOARD_ID (A38X_MARVELL_BOARD_ID_BASE + 7)
|
||||
#define A38X_MV_MARVELL_BOARD_NUM (A38X_MV_MAX_MARVELL_BOARD_ID - \
|
||||
A38X_MARVELL_BOARD_ID_BASE)
|
||||
|
||||
/* Customer boards for A39x */
|
||||
#define A39X_CUSTOMER_BOARD_ID_BASE 0x20
|
||||
#define A39X_CUSTOMER_BOARD_ID0 (A39X_CUSTOMER_BOARD_ID_BASE + 0)
|
||||
#define A39X_CUSTOMER_BOARD_ID1 (A39X_CUSTOMER_BOARD_ID_BASE + 1)
|
||||
#define A39X_MV_MAX_CUSTOMER_BOARD_ID (A39X_CUSTOMER_BOARD_ID_BASE + 2)
|
||||
#define A39X_MV_CUSTOMER_BOARD_NUM (A39X_MV_MAX_CUSTOMER_BOARD_ID - \
|
||||
A39X_CUSTOMER_BOARD_ID_BASE)
|
||||
|
||||
/* Marvell boards for A39x */
|
||||
#define A39X_MARVELL_BOARD_ID_BASE 0x30
|
||||
#define A39X_DB_69XX_ID (A39X_MARVELL_BOARD_ID_BASE + 0)
|
||||
#define A39X_RD_69XX_ID (A39X_MARVELL_BOARD_ID_BASE + 1)
|
||||
#define A39X_MV_MAX_MARVELL_BOARD_ID (A39X_MARVELL_BOARD_ID_BASE + 2)
|
||||
#define A39X_MV_MARVELL_BOARD_NUM (A39X_MV_MAX_MARVELL_BOARD_ID - \
|
||||
A39X_MARVELL_BOARD_ID_BASE)
|
||||
|
||||
#ifdef CONFIG_ARMADA_38X
|
||||
#define CUTOMER_BOARD_ID_BASE A38X_CUSTOMER_BOARD_ID_BASE
|
||||
#define CUSTOMER_BOARD_ID0 A38X_CUSTOMER_BOARD_ID0
|
||||
#define CUSTOMER_BOARD_ID1 A38X_CUSTOMER_BOARD_ID1
|
||||
#define MV_MAX_CUSTOMER_BOARD_ID A38X_MV_MAX_CUSTOMER_BOARD_ID
|
||||
#define MV_CUSTOMER_BOARD_NUM A38X_MV_CUSTOMER_BOARD_NUM
|
||||
#define MARVELL_BOARD_ID_BASE A38X_MARVELL_BOARD_ID_BASE
|
||||
#define MV_MAX_MARVELL_BOARD_ID A38X_MV_MAX_MARVELL_BOARD_ID
|
||||
#define MV_MARVELL_BOARD_NUM A38X_MV_MARVELL_BOARD_NUM
|
||||
#define MV_DEFAULT_BOARD_ID DB_68XX_ID
|
||||
#define MV_DEFAULT_DEVICE_ID MV_6811
|
||||
#elif defined(CONFIG_ARMADA_39X)
|
||||
#define CUTOMER_BOARD_ID_BASE A39X_CUSTOMER_BOARD_ID_BASE
|
||||
#define CUSTOMER_BOARD_ID0 A39X_CUSTOMER_BOARD_ID0
|
||||
#define CUSTOMER_BOARD_ID1 A39X_CUSTOMER_BOARD_ID1
|
||||
#define MV_MAX_CUSTOMER_BOARD_ID A39X_MV_MAX_CUSTOMER_BOARD_ID
|
||||
#define MV_CUSTOMER_BOARD_NUM A39X_MV_CUSTOMER_BOARD_NUM
|
||||
#define MARVELL_BOARD_ID_BASE A39X_MARVELL_BOARD_ID_BASE
|
||||
#define MV_MAX_MARVELL_BOARD_ID A39X_MV_MAX_MARVELL_BOARD_ID
|
||||
#define MV_MARVELL_BOARD_NUM A39X_MV_MARVELL_BOARD_NUM
|
||||
#define MV_DEFAULT_BOARD_ID A39X_DB_69XX_ID
|
||||
#define MV_DEFAULT_DEVICE_ID MV_6920
|
||||
#endif
|
||||
|
||||
#define MV_INVALID_BOARD_ID 0xffffffff
|
||||
|
||||
/* device revesion */
|
||||
#define DEV_VERSION_ID_REG 0x1823c
|
||||
#define REVISON_ID_OFFS 8
|
||||
#define REVISON_ID_MASK 0xf00
|
||||
|
||||
/* A38x revisions */
|
||||
#define MV_88F68XX_Z1_ID 0x0
|
||||
#define MV_88F68XX_A0_ID 0x4
|
||||
/* A39x revisions */
|
||||
#define MV_88F69XX_Z1_ID 0x2
|
||||
|
||||
#define MPP_CONTROL_REG(id) (0x18000 + (id * 4))
|
||||
#define GPP_DATA_OUT_REG(grp) (MV_GPP_REGS_BASE(grp) + 0x00)
|
||||
#define GPP_DATA_OUT_EN_REG(grp) (MV_GPP_REGS_BASE(grp) + 0x04)
|
||||
#define GPP_DATA_IN_REG(grp) (MV_GPP_REGS_BASE(grp) + 0x10)
|
||||
#define MV_GPP_REGS_BASE(unit) (0x18100 + ((unit) * 0x40))
|
||||
|
||||
#define MPP_REG_NUM(GPIO_NUM) (GPIO_NUM / 8)
|
||||
#define MPP_MASK(GPIO_NUM) (0xf << 4 * (GPIO_NUM - \
|
||||
(MPP_REG_NUM(GPIO_NUM) * 8)));
|
||||
#define GPP_REG_NUM(GPIO_NUM) (GPIO_NUM / 32)
|
||||
#define GPP_MASK(GPIO_NUM) (1 << GPIO_NUM % 32)
|
||||
|
||||
/* device ID */
|
||||
/* Armada 38x Family */
|
||||
#define MV_6810_DEV_ID 0x6810
|
||||
#define MV_6811_DEV_ID 0x6811
|
||||
#define MV_6820_DEV_ID 0x6820
|
||||
#define MV_6828_DEV_ID 0x6828
|
||||
/* Armada 39x Family */
|
||||
#define MV_6920_DEV_ID 0x6920
|
||||
#define MV_6928_DEV_ID 0x6928
|
||||
|
||||
enum {
|
||||
MV_6810,
|
||||
MV_6820,
|
||||
MV_6811,
|
||||
MV_6828,
|
||||
MV_NONE,
|
||||
MV_6920,
|
||||
MV_6928,
|
||||
MV_MAX_DEV_ID,
|
||||
};
|
||||
|
||||
#define MV_6820_INDEX 0
|
||||
#define MV_6810_INDEX 1
|
||||
#define MV_6811_INDEX 2
|
||||
#define MV_6828_INDEX 3
|
||||
|
||||
#define MV_6920_INDEX 0
|
||||
#define MV_6928_INDEX 1
|
||||
|
||||
#ifdef CONFIG_ARMADA_38X
|
||||
#define MAX_DEV_ID_NUM 4
|
||||
#else
|
||||
#define MAX_DEV_ID_NUM 2
|
||||
#endif
|
||||
|
||||
#define MV_6820_INDEX 0
|
||||
#define MV_6810_INDEX 1
|
||||
#define MV_6811_INDEX 2
|
||||
#define MV_6828_INDEX 3
|
||||
#define MV_6920_INDEX 0
|
||||
#define MV_6928_INDEX 1
|
||||
|
||||
enum unit_id {
|
||||
PEX_UNIT_ID,
|
||||
ETH_GIG_UNIT_ID,
|
||||
USB3H_UNIT_ID,
|
||||
USB3D_UNIT_ID,
|
||||
SATA_UNIT_ID,
|
||||
QSGMII_UNIT_ID,
|
||||
XAUI_UNIT_ID,
|
||||
RXAUI_UNIT_ID,
|
||||
MAX_UNITS_ID
|
||||
};
|
||||
|
||||
struct board_wakeup_gpio {
|
||||
u32 board_id;
|
||||
int gpio_num;
|
||||
};
|
||||
|
||||
enum suspend_wakeup_status {
|
||||
SUSPEND_WAKEUP_DISABLED,
|
||||
SUSPEND_WAKEUP_ENABLED,
|
||||
SUSPEND_WAKEUP_ENABLED_GPIO_DETECTED,
|
||||
};
|
||||
|
||||
/*
|
||||
* GPIO status indication for Suspend Wakeup:
|
||||
* If suspend to RAM is supported and GPIO inidcation is implemented,
|
||||
* set the gpio number
|
||||
* If suspend to RAM is supported but GPIO indication is not implemented
|
||||
* set '-2'
|
||||
* If suspend to RAM is not supported set '-1'
|
||||
*/
|
||||
#ifdef CONFIG_CUSTOMER_BOARD_SUPPORT
|
||||
#ifdef CONFIG_ARMADA_38X
|
||||
#define MV_BOARD_WAKEUP_GPIO_INFO { \
|
||||
{A38X_CUSTOMER_BOARD_ID0, -1 }, \
|
||||
{A38X_CUSTOMER_BOARD_ID0, -1 }, \
|
||||
};
|
||||
#else
|
||||
#define MV_BOARD_WAKEUP_GPIO_INFO { \
|
||||
{A39X_CUSTOMER_BOARD_ID0, -1 }, \
|
||||
{A39X_CUSTOMER_BOARD_ID0, -1 }, \
|
||||
};
|
||||
#endif /* CONFIG_ARMADA_38X */
|
||||
|
||||
#else
|
||||
|
||||
#ifdef CONFIG_ARMADA_38X
|
||||
#define MV_BOARD_WAKEUP_GPIO_INFO { \
|
||||
{RD_NAS_68XX_ID, -2 }, \
|
||||
{DB_68XX_ID, -1 }, \
|
||||
{RD_AP_68XX_ID, -2 }, \
|
||||
{DB_AP_68XX_ID, -2 }, \
|
||||
{DB_GP_68XX_ID, -2 }, \
|
||||
{DB_BP_6821_ID, -2 }, \
|
||||
{DB_AMC_6820_ID, -2 }, \
|
||||
};
|
||||
#else
|
||||
#define MV_BOARD_WAKEUP_GPIO_INFO { \
|
||||
{A39X_RD_69XX_ID, -1 }, \
|
||||
{A39X_DB_69XX_ID, -1 }, \
|
||||
};
|
||||
#endif /* CONFIG_ARMADA_38X */
|
||||
#endif /* CONFIG_CUSTOMER_BOARD_SUPPORT */
|
||||
|
||||
u32 mv_board_tclk_get(void);
|
||||
u32 mv_board_id_get(void);
|
||||
u32 mv_board_id_index_get(u32 board_id);
|
||||
u32 sys_env_unit_max_num_get(enum unit_id unit);
|
||||
enum suspend_wakeup_status sys_env_suspend_wakeup_check(void);
|
||||
u8 sys_env_device_rev_get(void);
|
||||
u32 sys_env_device_id_get(void);
|
||||
u16 sys_env_model_get(void);
|
||||
struct dlb_config *sys_env_dlb_config_ptr_get(void);
|
||||
u32 sys_env_get_topology_update_info(
|
||||
struct topology_update_info *topology_update_info);
|
||||
u32 sys_env_get_cs_ena_from_reg(void);
|
||||
|
||||
#endif /* _SYS_ENV_LIB_H */
|
Loading…
Reference in a new issue