cavium: Add CN81xx SoC and eval board support
This adds Cavium CN81xx SoC and SFF EVB files. Code is based off of Cavium's Octeon-TX SDK: https://github.com/Cavium-Open-Source-Distributions/OCTEON-TX-SDK BDK coreboot differences: bootblock: - Get rid of BDK header - Add Kconfig for link address - Move CAR setup code into assembly - Move unaligned memory access enable into assembly - Implement custom bootblock entry function - Add CLIB and CSIB blobs romstage: - Use minimal DRAM init only devicetree: - Convert FTD to static C file containing key value pairs Tested on CN81xx: - Boots to payload - Tested with GNU/Linux 4.16.3 - All hardware is usable (after applying additional commits) Implemented in future commits: - Vboot integration - MMU suuport - L2 Cache handling - ATF from external repo - Devicetree patching - Extended DRAM testing - UART init Not working: - Booting a payload - Booting upstream ATF TODO: - Configuration straps Change-Id: I47b4412d29203b45aee49bfa026c1d86ef7ce688 Signed-off-by: David Hendricks <dhendricks@fb.com> Signed-off-by: Patrick Rudolph <patrick.rudolph@9elements.com> Reviewed-on: https://review.coreboot.org/23037 Tested-by: build bot (Jenkins) <no-reply@coreboot.org> Reviewed-by: David Hendricks <david.hendricks@gmail.com>
This commit is contained in:
parent
03d3142733
commit
8cbd569f74
55 changed files with 5750 additions and 9 deletions
30
src/mainboard/cavium/Kconfig
Normal file
30
src/mainboard/cavium/Kconfig
Normal file
|
@ -0,0 +1,30 @@
|
|||
##
|
||||
## This file is part of the coreboot project.
|
||||
##
|
||||
## Copyright (C) 2018 Facebook Inc
|
||||
##
|
||||
## This program is free software; you can redistribute it and/or modify
|
||||
## it under the terms of the GNU General Public License as published by
|
||||
## the Free Software Foundation; version 2 of the License.
|
||||
##
|
||||
## This program is distributed in the hope that it will be useful,
|
||||
## but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
## GNU General Public License for more details.
|
||||
##
|
||||
if VENDOR_CAVIUM
|
||||
|
||||
choice
|
||||
prompt "Mainboard model"
|
||||
|
||||
source "src/mainboard/cavium/*/Kconfig.name"
|
||||
|
||||
endchoice
|
||||
|
||||
source "src/mainboard/cavium/*/Kconfig"
|
||||
|
||||
config MAINBOARD_VENDOR
|
||||
string "Mainboard Vendor"
|
||||
default "Cavium"
|
||||
|
||||
endif # VENDOR_CAVIUM
|
2
src/mainboard/cavium/Kconfig.name
Normal file
2
src/mainboard/cavium/Kconfig.name
Normal file
|
@ -0,0 +1,2 @@
|
|||
config VENDOR_CAVIUM
|
||||
bool "Cavium"
|
68
src/mainboard/cavium/cn8100_sff_evb/Kconfig
Normal file
68
src/mainboard/cavium/cn8100_sff_evb/Kconfig
Normal file
|
@ -0,0 +1,68 @@
|
|||
##
|
||||
## This file is part of the coreboot project.
|
||||
##
|
||||
## Copyright 2018 Facebook, Inc.
|
||||
##
|
||||
## This program is free software; you can redistribute it and/or modify
|
||||
## it under the terms of the GNU General Public License as published by
|
||||
## the Free Software Foundation; version 2 of the License.
|
||||
##
|
||||
## This program is distributed in the hope that it will be useful,
|
||||
## but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
## GNU General Public License for more details.
|
||||
##
|
||||
|
||||
if BOARD_CAVIUM_CN8100_SFF_EVB
|
||||
|
||||
config BOARD_SPECIFIC_OPTIONS
|
||||
def_bool y
|
||||
select BOARD_ROMSIZE_KB_16384
|
||||
select COMMON_CBFS_SPI_WRAPPER
|
||||
select RTC
|
||||
select SOC_CAVIUM_CN81XX
|
||||
select SPI_FLASH
|
||||
select SPI_FLASH_STMICRO
|
||||
|
||||
config MAINBOARD_DIR
|
||||
string
|
||||
default "cavium/cn8100_sff_evb"
|
||||
|
||||
config MAINBOARD_VENDOR
|
||||
string
|
||||
default "Cavium"
|
||||
|
||||
config DRAM_SIZE_MB
|
||||
int
|
||||
default 8192
|
||||
|
||||
config BOOT_DEVICE_SPI_FLASH_BUS
|
||||
int
|
||||
default 0
|
||||
|
||||
config CONSOLE_SERIAL_UART_ADDRESS
|
||||
hex
|
||||
depends on DRIVERS_UART
|
||||
default 0x87E028000000
|
||||
|
||||
config UART_FOR_CONSOLE
|
||||
int
|
||||
depends on DRIVERS_UART
|
||||
default 0
|
||||
|
||||
config FMDFILE
|
||||
string
|
||||
default "src/mainboard/$(CONFIG_MAINBOARD_DIR)/board.fmd"
|
||||
|
||||
##########################################################
|
||||
#### Update below when adding a new derivative board. ####
|
||||
##########################################################
|
||||
config DEVICETREE
|
||||
string
|
||||
default "devicetree.cb"
|
||||
|
||||
config MAINBOARD_PART_NUMBER
|
||||
string
|
||||
default "CN8100_SFF_EVB"
|
||||
|
||||
endif
|
2
src/mainboard/cavium/cn8100_sff_evb/Kconfig.name
Normal file
2
src/mainboard/cavium/cn8100_sff_evb/Kconfig.name
Normal file
|
@ -0,0 +1,2 @@
|
|||
config BOARD_CAVIUM_CN8100_SFF_EVB
|
||||
bool "CN8100 SFF EVB"
|
27
src/mainboard/cavium/cn8100_sff_evb/Makefile.inc
Normal file
27
src/mainboard/cavium/cn8100_sff_evb/Makefile.inc
Normal file
|
@ -0,0 +1,27 @@
|
|||
##
|
||||
## This file is part of the coreboot project.
|
||||
##
|
||||
## Copyright 2017-present Facebook, Inc.
|
||||
##
|
||||
## This program is free software; you can redistribute it and/or modify
|
||||
## it under the terms of the GNU General Public License as published by
|
||||
## the Free Software Foundation; version 2 of the License.
|
||||
##
|
||||
## This program is distributed in the hope that it will be useful,
|
||||
## but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
## GNU General Public License for more details.
|
||||
##
|
||||
|
||||
bootblock-y += bootblock.c
|
||||
bootblock-y += memlayout.ld
|
||||
|
||||
romstage-y += memlayout.ld
|
||||
romstage-y += romstage.c
|
||||
romstage-y += bdk_devicetree.c
|
||||
|
||||
ramstage-y += mainboard.c
|
||||
ramstage-y += memlayout.ld
|
||||
ramstage-y += bdk_devicetree.c
|
||||
|
||||
verstage-y += memlayout.ld
|
125
src/mainboard/cavium/cn8100_sff_evb/bdk_devicetree.c
Normal file
125
src/mainboard/cavium/cn8100_sff_evb/bdk_devicetree.c
Normal file
|
@ -0,0 +1,125 @@
|
|||
/*
|
||||
* This file is part of the coreboot project.
|
||||
*
|
||||
* Copyright 2017-present Facebook, Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; version 2 of the License.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
*/
|
||||
|
||||
// This file is automatically generated.
|
||||
// DO NOT EDIT BY HAND.
|
||||
|
||||
#include <bdk-devicetree.h>
|
||||
|
||||
const struct bdk_devicetree_key_value devtree[] = {
|
||||
{"DDR-CONFIG-DQX-CTL", "0x4"},
|
||||
{"DDR-CONFIG-WODT-MASK.RANKS2.DIMMS2", "0xc0c0303"},
|
||||
{"DDR-CONFIG-WODT-MASK.RANKS4.DIMMS1", "0x1030203"},
|
||||
{"DDR-CONFIG-MODE1-RTT-WR.RANKS1.DIMMS1.RANK0", "0x4"},
|
||||
{"DDR-CONFIG-MODE1-RTT-WR.RANKS1.DIMMS2.RANK0", "0x4"},
|
||||
{"DDR-CONFIG-MODE1-RTT-WR.RANKS1.DIMMS2.RANK2", "0x4"},
|
||||
{"DDR-CONFIG-MODE1-RTT-WR.RANKS2.DIMMS1.RANK0", "0x2"},
|
||||
{"DDR-CONFIG-MODE1-RTT-WR.RANKS2.DIMMS1.RANK1", "0x2"},
|
||||
{"DDR-CONFIG-MODE1-RTT-WR.RANKS2.DIMMS2", "0x2"},
|
||||
{"DDR-CONFIG-MODE1-RTT-WR.RANKS4", "0x1"},
|
||||
{"DDR-CONFIG-MODE1-DIC.RANKS4.DIMMS1", "0x1"},
|
||||
{"DDR-CONFIG-MODE1-RTT-NOM.RANKS2.DIMMS2", "0x2"},
|
||||
{"DDR-CONFIG-MODE1-RTT-NOM.RANKS4.DIMMS1.RANK0", "0x4"},
|
||||
{"DDR-CONFIG-MODE1-RTT-NOM.RANKS4.DIMMS1.RANK2", "0x4"},
|
||||
{"DDR-CONFIG-MODE2-RTT-PARK.RANKS1.DIMMS1.RANK0", "0x1"},
|
||||
{"DDR-CONFIG-MODE2-RTT-PARK.RANKS1.DIMMS2.RANK0", "0x5"},
|
||||
{"DDR-CONFIG-MODE2-RTT-PARK.RANKS1.DIMMS2.RANK2", "0x5"},
|
||||
{"DDR-CONFIG-MODE2-RTT-PARK.RANKS2.DIMMS1.RANK0", "0x2"},
|
||||
{"DDR-CONFIG-MODE2-RTT-PARK.RANKS2.DIMMS1.RANK1", "0x2"},
|
||||
{"DDR-CONFIG-MODE2-RTT-PARK.RANKS2.DIMMS2", "0x1"},
|
||||
{"DDR-CONFIG-MODE2-RTT-PARK.RANKS4.DIMMS1.RANK0", "0x6"},
|
||||
{"DDR-CONFIG-MODE2-RTT-PARK.RANKS4.DIMMS1.RANK1", "0x6"},
|
||||
{"DDR-CONFIG-MODE2-VREF-VALUE.RANKS1.DIMMS1.RANK0", "0x22"},
|
||||
{"DDR-CONFIG-MODE2-VREF-VALUE.RANKS1.DIMMS2.RANK0", "0x1f"},
|
||||
{"DDR-CONFIG-MODE2-VREF-VALUE.RANKS1.DIMMS2.RANK2", "0x1f"},
|
||||
{"DDR-CONFIG-MODE2-VREF-VALUE.RANKS2.DIMMS1.RANK0", "0x19"},
|
||||
{"DDR-CONFIG-MODE2-VREF-VALUE.RANKS2.DIMMS1.RANK1", "0x19"},
|
||||
{"DDR-CONFIG-MODE2-VREF-VALUE.RANKS2.DIMMS2", "0x19"},
|
||||
{"DDR-CONFIG-MODE2-VREF-VALUE.RANKS4.DIMMS1.RANK0", "0x1f"},
|
||||
{"DDR-CONFIG-MODE2-VREF-VALUE.RANKS4.DIMMS1.RANK1", "0x1f"},
|
||||
{"DDR-CONFIG-RODT-CTL.RANKS1.DIMMS1", "0x7"},
|
||||
{"DDR-CONFIG-RODT-CTL.RANKS1.DIMMS2", "0x3"},
|
||||
{"DDR-CONFIG-RODT-CTL.RANKS2.DIMMS1", "0x3"},
|
||||
{"DDR-CONFIG-RODT-CTL.RANKS2.DIMMS2", "0x7"},
|
||||
{"DDR-CONFIG-RODT-CTL.RANKS4.DIMMS1", "0x7"},
|
||||
{"DDR-CONFIG-RODT-MASK.RANKS2.DIMMS2", "0x4080102"},
|
||||
{"DDR-CONFIG-RODT-MASK.RANKS4.DIMMS1", "0x1010202"},
|
||||
{"DDR-CONFIG-CUSTOM-MIN-RTT-NOM-IDX", "0x1"},
|
||||
{"DDR-CONFIG-CUSTOM-MAX-RTT-NOM-IDX", "0x7"},
|
||||
{"DDR-CONFIG-CUSTOM-MIN-RODT-CTL", "0x1"},
|
||||
{"DDR-CONFIG-CUSTOM-MAX-RODT-CTL", "0x7"},
|
||||
{"DDR-CONFIG-CUSTOM-CK-CTL", "0x4"},
|
||||
{"DDR-CONFIG-CUSTOM-CMD-CTL", "0x4"},
|
||||
{"DDR-CONFIG-CUSTOM-CTL-CTL", "0x4"},
|
||||
{"DDR-CONFIG-CUSTOM-OFFSET-EN", "0x1"},
|
||||
{"DDR-CONFIG-CUSTOM-OFFSET", "0x2"},
|
||||
{"DDR-CONFIG-CUSTOM-DDR2T", "0x1"},
|
||||
{"DDR-CONFIG-CUSTOM-MAXIMUM-ADJACENT-RLEVEL-DELAY-INCREMENT", "0x2"},
|
||||
{"DDR-CONFIG-CUSTOM-FPRCH2", "0x2"},
|
||||
{"PHY-ADDRESS.N0.BGX0.P0", "0xff000010"},
|
||||
{"PHY-ADDRESS.N0.BGX0.P1", "0xff000011"},
|
||||
{"PHY-ADDRESS.N0.BGX0.P2", "0xff000012"},
|
||||
{"PHY-ADDRESS.N0.BGX0.P3", "0xff000013"},
|
||||
{"PHY-ADDRESS.N0.BGX1.P0", "0xff002014"},
|
||||
{"PHY-ADDRESS.N0.BGX1.P1", "0xff002014"},
|
||||
{"PHY-ADDRESS.N0.BGX2.P0", "0xff000000"},
|
||||
{"BGX-ENABLE.N0.BGX0.P0", "1"},
|
||||
{"BGX-ENABLE.N0.BGX0.P1", "1"},
|
||||
{"BGX-ENABLE.N0.BGX0.P2", "1"},
|
||||
{"BGX-ENABLE.N0.BGX0.P3", "1"},
|
||||
{"BGX-ENABLE.N0.BGX1.P0", "1"},
|
||||
{"BGX-ENABLE.N0.BGX1.P1", "1"},
|
||||
{"BGX-ENABLE.N0.BGX2.P0", "1"},
|
||||
{"BDK-NUM-PACKET-BUFFERS", "0x1000"},
|
||||
{"BDK-PACKET-BUFFER-SIZE", "0x400"},
|
||||
{"BDK-SHOW-LINK-STATUS", "1"},
|
||||
{"BDK-COREMASK", "0"},
|
||||
{"MULTI-NODE", "0"},
|
||||
{"QLM-AUTO-CONFIG", "0"},
|
||||
{"QLM-DIP-AUTO-CONFIG", "1"},
|
||||
{"DDR-SPEED.N0", "1333"},
|
||||
{"DDR-CONFIG-SPD-ADDR.DIMM0.LMC0", "0x1050"},
|
||||
{"USB-PWR-GPIO.N0.PORT0", "12"},
|
||||
{"USB-PWR-GPIO-POLARITY.N0.PORT0", "0"},
|
||||
{"USB-REFCLK-SRC.N0.PORT0", "0"},
|
||||
{"GPIO-PIN-SELECT-GPIO15", "0x24f"},
|
||||
{"GPIO-PIN-SELECT-GPIO16", "0x24e"},
|
||||
{"GPIO-PIN-SELECT-GPIO17", "0x24b"},
|
||||
{"GPIO-PIN-SELECT-GPIO18", "0x247"},
|
||||
{"GPIO-PIN-SELECT-GPIO19", "0x24d"},
|
||||
{"GPIO-PIN-SELECT-GPIO20", "0x24c"},
|
||||
{"GPIO-PIN-SELECT-GPIO37", "0x24a"},
|
||||
{"GPIO-PIN-SELECT-GPIO38", "0x246"},
|
||||
{"GPIO-PIN-SELECT-GPIO7", "0xe1"},
|
||||
{"GPIO-PIN-SELECT-GPIO24", "0xeb"},
|
||||
{"GPIO-PIN-SELECT-GPIO27", "0xed"},
|
||||
{"GPIO-PIN-SELECT-GPIO28", "0xe3"},
|
||||
{"GPIO-PIN-SELECT-GPIO29", "0xe0"},
|
||||
{"GPIO-PIN-SELECT-GPIO30", "0xe2"},
|
||||
{"GPIO-PIN-SELECT-GPIO40", "0x112"},
|
||||
{"GPIO-PIN-SELECT-GPIO41", "0x113"},
|
||||
{"GPIO-PIN-SELECT-GPIO42", "0x114"},
|
||||
{"GPIO-PIN-SELECT-GPIO43", "0x115"},
|
||||
{"GPIO-PIN-SELECT-GPIO44", "0x116"},
|
||||
{"GPIO-PIN-SELECT-GPIO45", "0x117"},
|
||||
{"GPIO-PIN-SELECT-GPIO46", "0x118"},
|
||||
{"GPIO-PIN-SELECT-GPIO47", "0x119"},
|
||||
{"GPIO-POLARITY-GPIO7", "1"},
|
||||
{"GPIO-POLARITY-GPIO27", "1"},
|
||||
{"GPIO-POLARITY-GPIO28", "1"},
|
||||
{"GPIO-POLARITY-GPIO30", "1"},
|
||||
{0, 0},
|
||||
};
|
24
src/mainboard/cavium/cn8100_sff_evb/board.fmd
Normal file
24
src/mainboard/cavium/cn8100_sff_evb/board.fmd
Normal file
|
@ -0,0 +1,24 @@
|
|||
FLASH@0x0 8M {
|
||||
WP_RO@0x0 0x400000 {
|
||||
RO_SECTION@0x0 0x200000 {
|
||||
# bootblock includes trusted/non-trusted CLIB, CSIB,
|
||||
# and BL1FWs packaged in
|
||||
# src/soc/cavium/common/Makefile.inc.
|
||||
BOOTBLOCK@0x10000 0x70000
|
||||
FMAP@0x90000 0x1000
|
||||
COREBOOT(CBFS)@0x100000 0x100000
|
||||
}
|
||||
}
|
||||
RW_SECTION_A@0x400000 0xe8000 {
|
||||
VBLOCK_A@0x0 0x2000
|
||||
FW_MAIN_A(CBFS)@0x2000 0xe5f00
|
||||
RW_FWID_A@0xe7f00 0x100
|
||||
}
|
||||
RW_UNUSED@0x4e8000 0x8000
|
||||
RW_ELOG@0x5d8000 0x1000
|
||||
RW_SHARED@0x5e0000 0x10000 {
|
||||
SHARED_DATA@0x0 0x10000
|
||||
}
|
||||
RW_NVRAM@0x5f0000 0x10000
|
||||
CONSOLE@0x700000 0x100000
|
||||
}
|
6
src/mainboard/cavium/cn8100_sff_evb/board_info.txt
Normal file
6
src/mainboard/cavium/cn8100_sff_evb/board_info.txt
Normal file
|
@ -0,0 +1,6 @@
|
|||
Vendor name: Cavium
|
||||
Board name: CN81XX SFF EVB
|
||||
Category: eval
|
||||
ROM protocol: SPI
|
||||
ROM socketed: n
|
||||
Flashrom support: n
|
46
src/mainboard/cavium/cn8100_sff_evb/bootblock.c
Normal file
46
src/mainboard/cavium/cn8100_sff_evb/bootblock.c
Normal file
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
* This file is part of the coreboot project.
|
||||
*
|
||||
* Copyright 2018 Facebook, Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; version 2 of the License.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#include <bootblock_common.h>
|
||||
#include <soc/soc.h>
|
||||
#include <soc/spi.h>
|
||||
#include <soc/uart.h>
|
||||
|
||||
void bootblock_mainboard_early_init(void)
|
||||
{
|
||||
if (IS_ENABLED(CONFIG_BOOTBLOCK_CONSOLE)) {
|
||||
if (!uart_is_enabled(0))
|
||||
uart_setup(0, CONFIG_TTYS0_BAUD);
|
||||
if (!uart_is_enabled(1))
|
||||
uart_setup(0, CONFIG_TTYS0_BAUD);
|
||||
}
|
||||
}
|
||||
|
||||
static void configure_spi_flash(void)
|
||||
{
|
||||
/* FIXME: Only tested on EM100 Pro */
|
||||
spi_init_custom(0, // bus
|
||||
25000000, // speed Hz
|
||||
0, // idle low disabled
|
||||
0, // zero idle cycles between transfers
|
||||
0, // MSB first
|
||||
0, // Chip select 0
|
||||
1); // assert is high
|
||||
}
|
||||
|
||||
void bootblock_mainboard_init(void)
|
||||
{
|
||||
configure_spi_flash();
|
||||
}
|
496
src/mainboard/cavium/cn8100_sff_evb/cn81xx-linux.dtsi
Normal file
496
src/mainboard/cavium/cn8100_sff_evb/cn81xx-linux.dtsi
Normal file
|
@ -0,0 +1,496 @@
|
|||
/*
|
||||
* Cavium Thunder DTS file - Thunder SoC description
|
||||
*
|
||||
* Copyright (C) 2016, Cavium Inc.
|
||||
*
|
||||
* This file is dual-licensed: you can use it either under the terms
|
||||
* of the GPL or the X11 license, at your option. Note that this dual
|
||||
* licensing only applies to this file, and not this project as a
|
||||
* whole.
|
||||
*
|
||||
* a) This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; version 2 of the License.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* Or, alternatively,
|
||||
*
|
||||
* b) Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation
|
||||
* files (the "Software"), to deal in the Software without
|
||||
* restriction, including without limitation the rights to use,
|
||||
* copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following
|
||||
* conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
/ {
|
||||
model = "Cavium ThunderX CN81XX board";
|
||||
compatible = "cavium,thunder-81xx";
|
||||
interrupt-parent = <&gic0>;
|
||||
#address-cells = <2>;
|
||||
#size-cells = <2>;
|
||||
|
||||
psci {
|
||||
compatible = "arm,psci-0.2";
|
||||
method = "smc";
|
||||
};
|
||||
|
||||
cpus {
|
||||
#address-cells = <2>;
|
||||
#size-cells = <0>;
|
||||
|
||||
cpu-map {
|
||||
cluster0 {
|
||||
core0 {
|
||||
cpu = <&CPU0>;
|
||||
};
|
||||
core1 {
|
||||
cpu = <&CPU1>;
|
||||
};
|
||||
core2 {
|
||||
cpu = <&CPU2>;
|
||||
};
|
||||
core3 {
|
||||
cpu = <&CPU3>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
CPU0: cpu@0 {
|
||||
device_type = "cpu";
|
||||
compatible = "cavium,thunder", "arm,armv8";
|
||||
reg = <0x0 0x000>;
|
||||
enable-method = "psci";
|
||||
/* socket 0 */
|
||||
numa-node-id = <0>;
|
||||
next-level-cache = <&thunderx_L2_0>;
|
||||
};
|
||||
CPU1: cpu@1 {
|
||||
device_type = "cpu";
|
||||
compatible = "cavium,thunder", "arm,armv8";
|
||||
reg = <0x0 0x001>;
|
||||
enable-method = "psci";
|
||||
numa-node-id = <0>;
|
||||
next-level-cache = <&thunderx_L2_0>;
|
||||
};
|
||||
CPU2: cpu@2 {
|
||||
device_type = "cpu";
|
||||
compatible = "cavium,thunder", "arm,armv8";
|
||||
reg = <0x0 0x002>;
|
||||
enable-method = "psci";
|
||||
numa-node-id = <0>;
|
||||
next-level-cache = <&thunderx_L2_0>;
|
||||
};
|
||||
CPU3: cpu@3 {
|
||||
device_type = "cpu";
|
||||
compatible = "cavium,thunder", "arm,armv8";
|
||||
reg = <0x0 0x003>;
|
||||
enable-method = "psci";
|
||||
numa-node-id = <0>;
|
||||
next-level-cache = <&thunderx_L2_0>;
|
||||
};
|
||||
};
|
||||
|
||||
thunderx_L2_0: l2-cache0 {
|
||||
compatible = "cache";
|
||||
numa-node-id = <0>;
|
||||
};
|
||||
|
||||
timer {
|
||||
compatible = "arm,armv8-timer";
|
||||
interrupts = <1 13 4>,
|
||||
<1 14 4>,
|
||||
<1 11 4>,
|
||||
<1 10 4>;
|
||||
};
|
||||
|
||||
pmu {
|
||||
compatible = "cavium,thunder-pmu", "arm,armv8-pmuv3";
|
||||
interrupts = <1 7 4>;
|
||||
};
|
||||
|
||||
mmc_supply_3v3: mmc_supply_3v3 {
|
||||
compatible = "regulator-fixed";
|
||||
regulator-name = "mmc_supply_3v3";
|
||||
regulator-min-microvolt = <3300000>;
|
||||
regulator-max-microvolt = <3300000>;
|
||||
|
||||
gpio = <&gpio_6_0 8 0>;
|
||||
enable-active-high;
|
||||
};
|
||||
|
||||
gic0: interrupt-controller@801000000000 {
|
||||
compatible = "arm,gic-v3";
|
||||
#interrupt-cells = <3>;
|
||||
#address-cells = <2>;
|
||||
#size-cells = <2>;
|
||||
#redistributor-regions = <1>;
|
||||
ranges;
|
||||
interrupt-controller;
|
||||
reg = <0x8010 0x00000000 0x0 0x010000>, /* GICD */
|
||||
<0x8010 0x80000000 0x0 0x600000>; /* GICR */
|
||||
interrupts = <1 9 4>;
|
||||
|
||||
its: gic-its@801000020000 {
|
||||
compatible = "arm,gic-v3-its";
|
||||
reg = <0x8010 0x20000 0x0 0x200000>;
|
||||
msi-controller;
|
||||
numa-node-id = <0>;
|
||||
};
|
||||
};
|
||||
|
||||
soc@0 {
|
||||
compatible = "simple-bus";
|
||||
#address-cells = <2>;
|
||||
#size-cells = <2>;
|
||||
ranges;
|
||||
numa-node-id = <0>;
|
||||
|
||||
refclkuaa: refclkuaa {
|
||||
compatible = "fixed-clock";
|
||||
#clock-cells = <0>;
|
||||
clock-frequency = <116640000>;
|
||||
clock-output-names = "refclkuaa";
|
||||
};
|
||||
|
||||
sclk: sclk {
|
||||
compatible = "fixed-clock";
|
||||
#clock-cells = <0>;
|
||||
clock-frequency = <800000000>;
|
||||
clock-output-names = "sclk";
|
||||
};
|
||||
|
||||
uaa0: serial@87e028000000 {
|
||||
compatible = "arm,pl011", "arm,primecell";
|
||||
reg = <0x87e0 0x28000000 0x0 0x1000>;
|
||||
interrupts = <0 5 4>;
|
||||
clocks = <&refclkuaa>;
|
||||
clock-names = "apb_pclk";
|
||||
skip-init;
|
||||
};
|
||||
|
||||
uaa1: serial@87e029000000 {
|
||||
compatible = "arm,pl011", "arm,primecell";
|
||||
reg = <0x87e0 0x29000000 0x0 0x1000>;
|
||||
interrupts = <0 6 4>;
|
||||
clocks = <&refclkuaa>;
|
||||
clock-names = "apb_pclk";
|
||||
skip-init;
|
||||
};
|
||||
|
||||
uaa2: serial@87e02a000000 {
|
||||
compatible = "arm,pl011", "arm,primecell";
|
||||
reg = <0x87e0 0x2a000000 0x0 0x1000>;
|
||||
interrupts = <0 7 4>;
|
||||
clocks = <&refclkuaa>;
|
||||
clock-names = "apb_pclk";
|
||||
skip-init;
|
||||
};
|
||||
|
||||
uaa3: serial@87e02b000000 {
|
||||
compatible = "arm,pl011", "arm,primecell";
|
||||
reg = <0x87e0 0x2b000000 0x0 0x1000>;
|
||||
interrupts = <0 8 4>;
|
||||
clocks = <&refclkuaa>;
|
||||
clock-names = "apb_pclk";
|
||||
skip-init;
|
||||
};
|
||||
|
||||
watch-dog@8440000a0000 {
|
||||
compatible = "arm,sbsa-gwdt";
|
||||
reg = <0x8440 0xa0000 0x0 0x1000>, <0x8440 0xb0000 0x0 0x1000>;
|
||||
interrupts = <0 9 4>;
|
||||
};
|
||||
|
||||
pbus0: nor@0 {
|
||||
compatible = "cfi-flash";
|
||||
reg = <0x8000 0x0 0x0 0x800000>;
|
||||
device-width = <1>;
|
||||
bank-width = <1>;
|
||||
clocks = <&sclk>;
|
||||
};
|
||||
|
||||
smmu0@830000000000 {
|
||||
compatible = "cavium,smmu-v2";
|
||||
reg = <0x8300 0x0 0x0 0x2000000>;
|
||||
#global-interrupts = <1>;
|
||||
interrupts = <0 68 4>, <0 69 4>, <0 69 4>, <0 69 4>, <0 69 4>, <0 69 4>,
|
||||
<0 69 4>, <0 69 4>, <0 69 4>, <0 69 4>, <0 69 4>, <0 69 4>,
|
||||
<0 69 4>, <0 69 4>, <0 69 4>, <0 69 4>, <0 69 4>, <0 69 4>,
|
||||
<0 69 4>, <0 69 4>, <0 69 4>, <0 69 4>, <0 69 4>, <0 69 4>,
|
||||
<0 69 4>, <0 69 4>, <0 69 4>, <0 69 4>, <0 69 4>, <0 69 4>,
|
||||
<0 69 4>, <0 69 4>, <0 69 4>, <0 69 4>, <0 69 4>, <0 69 4>,
|
||||
<0 69 4>, <0 69 4>, <0 69 4>, <0 69 4>, <0 69 4>, <0 69 4>,
|
||||
<0 69 4>, <0 69 4>, <0 69 4>, <0 69 4>, <0 69 4>, <0 69 4>,
|
||||
<0 69 4>, <0 69 4>, <0 69 4>, <0 69 4>, <0 69 4>, <0 69 4>,
|
||||
<0 69 4>, <0 69 4>, <0 69 4>, <0 69 4>, <0 69 4>, <0 69 4>,
|
||||
<0 69 4>, <0 69 4>, <0 69 4>, <0 69 4>, <0 69 4>;
|
||||
|
||||
mmu-masters = <&ecam0 0x100>,
|
||||
<&pem0 0x200>,
|
||||
<&pem1 0x300>,
|
||||
<&pem2 0x400>;
|
||||
|
||||
};
|
||||
|
||||
ecam0: pci@848000000000 {
|
||||
compatible = "pci-host-ecam-generic";
|
||||
device_type = "pci";
|
||||
msi-parent = <&its>;
|
||||
msi-map = <0 &its 0 0x10000>;
|
||||
bus-range = <0 31>;
|
||||
#size-cells = <2>;
|
||||
#address-cells = <3>;
|
||||
#stream-id-cells = <1>;
|
||||
u-boot,dm-pre-reloc;
|
||||
dma-coherent;
|
||||
reg = <0x8480 0x00000000 0 0x02000000>; /* Configuration space */
|
||||
ranges = <0x03000000 0x8010 0x00000000 0x8010 0x00000000 0x080 0x00000000>, /* mem ranges */
|
||||
<0x03000000 0x8100 0x00000000 0x8100 0x00000000 0x80 0x00000000>, /* SATA */
|
||||
<0x03000000 0x8680 0x00000000 0x8680 0x00000000 0x160 0x28000000>, /* UARTs */
|
||||
<0x03000000 0x87e0 0x2c000000 0x87e0 0x2c000000 0x000 0x94000000>, /* PEMs */
|
||||
<0x03000000 0x8400 0x00000000 0x8400 0x00000000 0x010 0x00000000>, /* RNM */
|
||||
<0x03000000 0x8430 0x00000000 0x8430 0x00000000 0x02 0x00000000>, /* NIC0*/
|
||||
<0x03000000 0x87e0 0xc6000000 0x87e0 0xc6000000 0x01f 0x3a000000>;
|
||||
|
||||
mrml_bridge: mrml-bridge0@1,0 {
|
||||
compatible = "pci-bridge", "cavium,thunder-8890-mrml-bridge";
|
||||
#size-cells = <2>;
|
||||
#address-cells = <3>;
|
||||
ranges = <0x03000000 0x87e0 0x00000000 0x03000000 0x87e0 0x00000000 0x10 0x00000000>;
|
||||
reg = <0x0800 0 0 0 0>; /* DEVFN = 0x08 (1:0) */
|
||||
device_type = "pci";
|
||||
u-boot,dm-pre-reloc;
|
||||
|
||||
mdio-nexus@1,3 {
|
||||
compatible = "cavium,thunder-8890-mdio-nexus";
|
||||
#address-cells = <2>;
|
||||
#size-cells = <2>;
|
||||
reg = <0x0b00 0 0 0 0>; /* DEVFN = 0x0b (1:3) */
|
||||
assigned-addresses = <0x03000000 0x87e0 0x05000000 0x0 0x800000>;
|
||||
ranges = <0x87e0 0x05000000 0x03000000 0x87e0 0x05000000 0x0 0x800000>;
|
||||
mdio0@87e005003800 {
|
||||
compatible = "cavium,thunder-8890-mdio";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
reg = <0x87e0 0x05003800 0x0 0x30>;
|
||||
};
|
||||
mdio1@87e005003880 {
|
||||
compatible = "cavium,thunder-8890-mdio";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
reg = <0x87e0 0x05003880 0x0 0x30>;
|
||||
};
|
||||
};
|
||||
|
||||
mmc_1_4: mmc@1,4 {
|
||||
compatible = "cavium,thunder-8890-mmc";
|
||||
reg = <0x0c00 0 0 0 0>; /* DEVFN = 0x0c (1:4) */
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
clocks = <&sclk>;
|
||||
};
|
||||
|
||||
i2c_9_0: i2c@9,0 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
compatible = "cavium,thunder-8890-twsi";
|
||||
reg = <0x4800 0 0 0 0>; /* DEVFN = 0x48 (9:0) */
|
||||
clock-frequency = <100000>;
|
||||
clocks = <&sclk>;
|
||||
u-boot,dm-pre-reloc;
|
||||
};
|
||||
|
||||
i2c_9_1: i2c@9,1 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
compatible = "cavium,thunder-8890-twsi";
|
||||
reg = <0x4900 0 0 0 0>; /* DEVFN = 0x49 (9:1) */
|
||||
clock-frequency = <100000>;
|
||||
clocks = <&sclk>;
|
||||
u-boot,dm-pre-reloc;
|
||||
};
|
||||
|
||||
rgx0 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
compatible = "cavium,thunder-8890-bgx";
|
||||
reg = <0x9000 0 0 0 0>; /* DEVFN = 0x90 (16:1) */
|
||||
};
|
||||
bgx0 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
compatible = "cavium,thunder-8890-bgx";
|
||||
reg = <0x8000 0 0 0 0>; /* DEVFN = 0x80 (16:0) */
|
||||
};
|
||||
bgx1 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
compatible = "cavium,thunder-8890-bgx";
|
||||
reg = <0x8100 0 0 0 0>; /* DEVFN = 0x81 (16:1) */
|
||||
};
|
||||
};
|
||||
|
||||
spi_7_0: spi@7,0 {
|
||||
compatible = "cavium,thunder-8190-spi";
|
||||
reg = <0x3800 0x0 0x0 0x0 0x0>; /* DEVFN = 0x38 (7:0) */
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
clocks = <&sclk>;
|
||||
};
|
||||
|
||||
gpio_6_0: gpio0@6,0 {
|
||||
#gpio-cells = <2>;
|
||||
compatible = "cavium,thunder-8890-gpio";
|
||||
gpio-controller;
|
||||
reg = <0x3000 0 0 0 0>; /* DEVFN = 0x30 (6:0) */
|
||||
u-boot,dm-pre-reloc;
|
||||
};
|
||||
|
||||
nfc: nand@b,0 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
compatible = "cavium,cn8130-nand";
|
||||
reg = <0x5800 0 0 0 0>; /* DEVFN = 0x58 (b:0) */
|
||||
clocks = <&sclk>;
|
||||
};
|
||||
};
|
||||
|
||||
pem0: pci@87e0c0000000 {
|
||||
|
||||
/* "cavium,pci-host-thunder-pem" implies that
|
||||
the first bus in bus-range has config access
|
||||
via the "PEM space", subsequent buses have
|
||||
config assess via the "Configuration space".
|
||||
The "mem64 PEM" range is used to map the PEM
|
||||
BAR0, which is used by the AER and PME MSI-X
|
||||
sources. UEFI and Linux must assign the same
|
||||
bus number to each device, otherwise Linux
|
||||
enumeration gets confused. Because UEFI
|
||||
skips the PEM bus and its PCIe-RC bridge it
|
||||
uses a numbering that starts 1 bus higher.
|
||||
*/
|
||||
|
||||
compatible = "cavium,pci-host-thunder-pem";
|
||||
device_type = "pci";
|
||||
msi-parent = <&its>;
|
||||
msi-map = <0 &its 0 0x10000>;
|
||||
bus-range = <0x1f 0x57>;
|
||||
#size-cells = <2>;
|
||||
#address-cells = <3>;
|
||||
#stream-id-cells = <1>;
|
||||
dma-coherent;
|
||||
reg = <0x8800 0x1f000000 0x0 0x39000000>, /* Configuration space */
|
||||
<0x87e0 0xc0000000 0x0 0x01000000>; /* PEM space */
|
||||
ranges = <0x01000000 0x00 0x00000000 0x8830 0x00000000 0x00 0x00010000>, /* I/O */
|
||||
<0x03000000 0x00 0x10000000 0x8810 0x10000000 0x0f 0xf0000000>, /* mem64 */
|
||||
<0x43000000 0x10 0x00000000 0x8820 0x00000000 0x10 0x00000000>, /* mem64-pref */
|
||||
<0x03000000 0x87e0 0xc0000000 0x87e0 0xc0000000 0x00 0x01000000>; /* mem64 PEM */
|
||||
|
||||
#interrupt-cells = <1>;
|
||||
interrupt-map-mask = <0 0 0 7>;
|
||||
interrupt-map = <0 0 0 1 &gic0 0 0 0 16 4>, /* INTA */
|
||||
<0 0 0 2 &gic0 0 0 0 17 4>, /* INTB */
|
||||
<0 0 0 3 &gic0 0 0 0 18 4>, /* INTC */
|
||||
<0 0 0 4 &gic0 0 0 0 19 4>; /* INTD */
|
||||
};
|
||||
|
||||
pem1: pci@87e0c1000000 {
|
||||
compatible = "cavium,pci-host-thunder-pem";
|
||||
device_type = "pci";
|
||||
msi-parent = <&its>;
|
||||
msi-map = <0 &its 0 0x10000>;
|
||||
bus-range = <0x57 0x8f>;
|
||||
#size-cells = <2>;
|
||||
#address-cells = <3>;
|
||||
#stream-id-cells = <1>;
|
||||
dma-coherent;
|
||||
reg = <0x8840 0x57000000 0x0 0x39000000>, /* Configuration space */
|
||||
<0x87e0 0xc1000000 0x0 0x01000000>; /* PEM space */
|
||||
ranges = <0x01000000 0x00 0x00010000 0x8870 0x00010000 0x00 0x00010000>, /* I/O */
|
||||
<0x03000000 0x00 0x10000000 0x8850 0x10000000 0x0f 0xf0000000>, /* mem64 */
|
||||
<0x43000000 0x10 0x00000000 0x8860 0x00000000 0x10 0x00000000>, /* mem64-pref */
|
||||
<0x03000000 0x87e0 0xc1000000 0x87e0 0xc1000000 0x00 0x01000000>; /* mem64 PEM */
|
||||
|
||||
#interrupt-cells = <1>;
|
||||
interrupt-map-mask = <0 0 0 7>;
|
||||
interrupt-map = <0 0 0 1 &gic0 0 0 0 20 4>, /* INTA */
|
||||
<0 0 0 2 &gic0 0 0 0 21 4>, /* INTB */
|
||||
<0 0 0 3 &gic0 0 0 0 22 4>, /* INTC */
|
||||
<0 0 0 4 &gic0 0 0 0 23 4>; /* INTD */
|
||||
};
|
||||
|
||||
pem2: pci@87e0c2000000 {
|
||||
compatible = "cavium,pci-host-thunder-pem";
|
||||
device_type = "pci";
|
||||
msi-parent = <&its>;
|
||||
msi-map = <0 &its 0 0x10000>;
|
||||
bus-range = <0x8f 0xc7>;
|
||||
#size-cells = <2>;
|
||||
#address-cells = <3>;
|
||||
#stream-id-cells = <1>;
|
||||
dma-coherent;
|
||||
reg = <0x8880 0x8f000000 0x0 0x39000000>, /* Configuration space */
|
||||
<0x87e0 0xc2000000 0x0 0x01000000>; /* PEM space */
|
||||
ranges = <0x01000000 0x00 0x00020000 0x88b0 0x00020000 0x00 0x00010000>, /* I/O */
|
||||
<0x03000000 0x00 0x10000000 0x8890 0x10000000 0x0f 0xf0000000>, /* mem64 */
|
||||
<0x43000000 0x10 0x00000000 0x88a0 0x00000000 0x10 0x00000000>, /* mem64-pref */
|
||||
<0x03000000 0x87e0 0xc2000000 0x87e0 0xc2000000 0x00 0x01000000>; /* mem64 PEM */
|
||||
|
||||
#interrupt-cells = <1>;
|
||||
interrupt-map-mask = <0 0 0 7>;
|
||||
interrupt-map = <0 0 0 1 &gic0 0 0 0 24 4>, /* INTA */
|
||||
<0 0 0 2 &gic0 0 0 0 25 4>, /* INTB */
|
||||
<0 0 0 3 &gic0 0 0 0 26 4>, /* INTC */
|
||||
<0 0 0 4 &gic0 0 0 0 27 4>; /* INTD */
|
||||
};
|
||||
|
||||
tdm: tdm@d,0 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
compatible = "cavium,thunder-8190-tdm";
|
||||
reg = <0x6800 0 0 0>; /* DEVFN = 0x68 (d:0) */
|
||||
clocks = <&sclk>;
|
||||
};
|
||||
};
|
||||
|
||||
aliases {
|
||||
serial0 = &uaa0;
|
||||
serial1 = &uaa1;
|
||||
serial2 = &uaa2;
|
||||
serial3 = &uaa3;
|
||||
i2c0 = &i2c_9_0;
|
||||
i2c1 = &i2c_9_1;
|
||||
spi0 = &spi_7_0;
|
||||
};
|
||||
|
||||
chosen {
|
||||
stdout-path = "serial0:115200n8";
|
||||
};
|
||||
|
||||
|
||||
memory@0 {
|
||||
device_type = "memory";
|
||||
reg = <0x0 0x01400000 0x0 0x7EC00000>;
|
||||
/* socket 0 */
|
||||
numa-node-id = <0>;
|
||||
};
|
||||
};
|
802
src/mainboard/cavium/cn8100_sff_evb/ddr4-common.dtsi
Normal file
802
src/mainboard/cavium/cn8100_sff_evb/ddr4-common.dtsi
Normal file
|
@ -0,0 +1,802 @@
|
|||
/***********************license start***********************************
|
||||
* Copyright (c) 2003-2016 Cavium Inc. (support@cavium.com). All rights
|
||||
* reserved.
|
||||
*
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* * Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer in the documentation and/or other materials provided
|
||||
* with the distribution.
|
||||
*
|
||||
* * Neither the name of Cavium Inc. nor the names of
|
||||
* its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written
|
||||
* permission.
|
||||
*
|
||||
* This Software, including technical data, may be subject to U.S. export
|
||||
* control laws, including the U.S. Export Administration Act and its
|
||||
* associated regulations, and may be subject to export or import
|
||||
* regulations in other countries.
|
||||
*
|
||||
* TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
|
||||
* AND WITH ALL FAULTS AND CAVIUM INC. MAKES NO PROMISES, REPRESENTATIONS OR
|
||||
* WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT
|
||||
* TO THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY
|
||||
* REPRESENTATION OR DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT
|
||||
* DEFECTS, AND CAVIUM SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES
|
||||
* OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR
|
||||
* PURPOSE, LACK OF VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT,
|
||||
* QUIET POSSESSION OR CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK
|
||||
* ARISING OUT OF USE OR PERFORMANCE OF THE SOFTWARE LIES WITH YOU.
|
||||
***********************license end**************************************/
|
||||
/ {
|
||||
cavium,bdk {
|
||||
/* Speed grade to use for DRAM in MT/s. Hardware may adjust this value
|
||||
slightly to improve DRAM stability, so scope measurements may not
|
||||
exactly match the frequency with MT/s. The Cavium supported speed
|
||||
grades are:
|
||||
0 (auto-set from SPD contents)
|
||||
666 MT/s (DDR3 only)
|
||||
800 MT/s (DDR3 only)
|
||||
1066 MT/s (DDR3 only)
|
||||
1333 MT/s (DDR3 only)
|
||||
1600 MT/s
|
||||
1866 MT/s
|
||||
2133 MT/s (DDR4 only)
|
||||
Parameters:
|
||||
N#: Parameter can be different for each node. This specifies
|
||||
which node the value is for. Node must be 0-3. Optional. */
|
||||
//DDR-SPEED.N%d = "0";
|
||||
|
||||
/* Set to use a an alternate reference clock for DRAM than the usual
|
||||
50Mhz reference. The value of here specifies the frequency of the
|
||||
alternate clock in Mhz. Currently the only supported reference
|
||||
clock frequencies are 50Mhz and 100Mhz.
|
||||
Parameters:
|
||||
N#: Parameter can be different for each node. This specifies
|
||||
which node the value is for. Node must be 0-3. Optional. */
|
||||
//DDR-ALT-REFCLK.N%d = "0";
|
||||
|
||||
/* TWSI address of the DIMM SPD. The encoding of this address is
|
||||
: [15:12]: TWSI bus the DIMM is connected to.
|
||||
[11:7]: Reserved, set to zero.
|
||||
[6:0]: TWSI address for the DIMM.
|
||||
A value of zero means the DIMMs are not accessible. Hard coded
|
||||
values will be read from DDR-CONFIG-SPD-DATA.Parameters:
|
||||
LMC#: Parameter can be different for memory controller. This
|
||||
specifies which LMC the value is for. LMC must be
|
||||
0-3. Optional.
|
||||
N#: Parameter can be different for each node. This specifies
|
||||
which node the value is for. Node must be 0-3. Optional. */
|
||||
//DDR-CONFIG-SPD-ADDR.DIMM%d.LMC%d.N%d = "0";
|
||||
// Note: The SPD addresses are not specified here so boards don't
|
||||
// inherit a default. The default causes trouble with UEFI when it
|
||||
// builds SMBIOS tables.
|
||||
|
||||
/* DIMM SPD data to be used if memory doesn't support the standard
|
||||
TWSI access to DIMM SPDs. The format of this is a binary blob
|
||||
stored in the device tree. An example would be:
|
||||
Parameters:
|
||||
LMC#: Parameter can be different for memory controller. This
|
||||
specifies which LMC the value is for. LMC must be
|
||||
0-3. Optional.
|
||||
N#: Parameter can be different for each node. This specifies
|
||||
which node the value is for. Node must be 0-3. Optional. */
|
||||
//DDR-CONFIG-SPD-DATA.DIMM%d.LMC%d.N%d = [];
|
||||
|
||||
/* Drive strength control for DDR_DQ* / DDR_DQS_*_P/N drivers.
|
||||
0x1 = 24 ohm.
|
||||
0x2 = 26.67 ohm.
|
||||
0x3 = 30 ohm.
|
||||
0x4 = 34.3 ohm.
|
||||
0x5 = 40 ohm.
|
||||
0x6 = 48 ohm.
|
||||
0x7 = 60 ohm.
|
||||
_ else = Reserved.
|
||||
Parameters:
|
||||
RANKS#: Specifies that this parameter only applies to DIMMs
|
||||
with the supplied number of ranks. Support ranks is 1, 2,
|
||||
or 4. Optional.
|
||||
DIMMS#: Specifies that this parameter only applies when the
|
||||
DIMMs per memory controller matches. Support number of
|
||||
DIMMs is 1 or 2. Optional.
|
||||
LMC#: Parameter can be different for memory controller. This
|
||||
specifies which LMC the value is for. LMC must be
|
||||
0-3. Optional.
|
||||
N#: Parameter can be different for each node. This specifies
|
||||
which node the value is for. Node must be 0-3. Optional. */
|
||||
//DDR-CONFIG-DQX-CTL.RANKS%d.DIMMS%d.LMC%d.N%d = "0";
|
||||
DDR-CONFIG-DQX-CTL = "0x4";
|
||||
|
||||
/* LMC Write OnDieTermination Mask Register
|
||||
System designers may desire to terminate DQ/DQS lines for
|
||||
higher-frequency DDR operations, especially on a multirank system.
|
||||
DDR3 DQ/DQS I/Os have built-in termination resistors that can be
|
||||
turned on or off by the controller, after meeting TAOND and TAOF
|
||||
timing requirements. Each rank has its own ODT pin that fans out
|
||||
to all of the memory parts in that DIMM. System designers may
|
||||
prefer different combinations of ODT ONs for write operations into
|
||||
different ranks. CNXXXX supports full programmability by way of
|
||||
the mask register below. Each rank position has its own 8-bit
|
||||
programmable field. When the controller does a write to that rank,
|
||||
it sets the 4 ODT pins to the mask pins below. For example, when
|
||||
doing a write into Rank0, a system designer may desire to terminate
|
||||
the lines with the resistor on DIMM0/Rank1. The mask WODT_D0_R0
|
||||
would then be {00000010}.
|
||||
CNXXXX drives the appropriate mask values on the ODT pins by
|
||||
default. If this feature is not required, write 0x0 in this
|
||||
register. When a given RANK is selected, the WODT mask for that
|
||||
RANK is used.
|
||||
Parameters:
|
||||
RANKS#: Specifies that this parameter only applies to DIMMs
|
||||
with the supplied number of ranks. Support ranks is 1, 2,
|
||||
or 4. Optional.
|
||||
DIMMS#: Specifies that this parameter only applies when the
|
||||
DIMMs per memory controller matches. Support number of
|
||||
DIMMs is 1 or 2. Optional.
|
||||
LMC#: Parameter can be different for memory controller. This
|
||||
specifies which LMC the value is for. LMC must be
|
||||
0-3. Optional.
|
||||
N#: Parameter can be different for each node. This specifies
|
||||
which node the value is for. Node must be 0-3. Optional. */
|
||||
//DDR-CONFIG-WODT-MASK.RANKS%d.DIMMS%d.LMC%d.N%d = "0";
|
||||
DDR-CONFIG-WODT-MASK.RANKS2.DIMMS2 = "0xc0c0303";
|
||||
DDR-CONFIG-WODT-MASK.RANKS4.DIMMS1 = "0x1030203";
|
||||
|
||||
/* Partial array self-refresh per rank. LMC writes this value to
|
||||
MR2[PASR] in the rank (i.e. DIMM0_CS0) DDR3 parts when selected
|
||||
during power-up/init, write-leveling, and, if
|
||||
LMC()_CONFIG[SREF_WITH_DLL] is set, self-refresh entry and exit
|
||||
instruction sequences. See LMC()_SEQ_CTL[SEQ_SEL,INIT_START] and
|
||||
LMC()_CONFIG[RANKMASK] and LMC()_RESET_CTL[DDR3PWARM,DDR3PSOFT].
|
||||
Parameters:
|
||||
RANKS#: Specifies that this parameter only applies to DIMMs
|
||||
with the supplied number of ranks. Support ranks is 1, 2,
|
||||
or 4. Optional.
|
||||
DIMMS#: Specifies that this parameter only applies when the
|
||||
DIMMs per memory controller matches. Support number of
|
||||
DIMMs is 1 or 2. Optional.
|
||||
RANK#: Parameter can be different for each rank of a DIMM. This
|
||||
specifies which rank the value is for. Rank must be
|
||||
0-3. Optional.
|
||||
LMC#: Parameter can be different for memory controller. This
|
||||
specifies which LMC the value is for. LMC must be
|
||||
0-3. Optional.
|
||||
N#: Parameter can be different for each node. This specifies
|
||||
which node the value is for. Node must be 0-3. Optional. */
|
||||
//DDR-CONFIG-MODE1-PASR.RANKS%d.DIMMS%d.RANK%d.LMC%d.N%d = "0";
|
||||
|
||||
/* Auto self-refresh per rank. LMC writes this value to MR2[ASR] in
|
||||
the rank (i.e. DIMM0_CS0) DDR3 parts when selected during
|
||||
power-up/init, write-leveling, and, if LMC()_CONFIG[SREF_WITH_DLL]
|
||||
is set, self-refresh entry and exit instruction sequences. See
|
||||
LMC()_SEQ_CTL[SEQ_SEL,INIT_START] and LMC()_CONFIG[RANKMASK] and
|
||||
LMC()_RESET_CTL [DDR3PWARM,DDR3PSOFT].
|
||||
Parameters:
|
||||
RANKS#: Specifies that this parameter only applies to DIMMs
|
||||
with the supplied number of ranks. Support ranks is 1, 2,
|
||||
or 4. Optional.
|
||||
DIMMS#: Specifies that this parameter only applies when the
|
||||
DIMMs per memory controller matches. Support number of
|
||||
DIMMs is 1 or 2. Optional.
|
||||
RANK#: Parameter can be different for each rank of a DIMM. This
|
||||
specifies which rank the value is for. Rank must be
|
||||
0-3. Optional.
|
||||
LMC#: Parameter can be different for memory controller. This
|
||||
specifies which LMC the value is for. LMC must be
|
||||
0-3. Optional.
|
||||
N#: Parameter can be different for each node. This specifies
|
||||
which node the value is for. Node must be 0-3. Optional. */
|
||||
//DDR-CONFIG-MODE1-ASR.RANKS%d.DIMMS%d.RANK%d.LMC%d.N%d = "0";
|
||||
|
||||
/* Self-refresh temperature range per rank. LMC writes this value to
|
||||
MR2[SRT] in the rank (i.e. DIMM0_CS0) DDR3 parts when selected
|
||||
during power-up/init, write-leveling, and, if
|
||||
LMC()_CONFIG[SREF_WITH_DLL] is set, self-refresh entry and exit
|
||||
instruction sequences. See LMC()_SEQ_CTL[SEQ_SEL,INIT_START] and
|
||||
LMC()_CONFIG[RANKMASK] and LMC()_RESET_CTL[DDR3PWARM,DDR3PSOFT].
|
||||
Parameters:
|
||||
RANKS#: Specifies that this parameter only applies to DIMMs
|
||||
with the supplied number of ranks. Support ranks is 1, 2,
|
||||
or 4. Optional.
|
||||
DIMMS#: Specifies that this parameter only applies when the
|
||||
DIMMs per memory controller matches. Support number of
|
||||
DIMMs is 1 or 2. Optional.
|
||||
RANK#: Parameter can be different for each rank of a DIMM. This
|
||||
specifies which rank the value is for. Rank must be
|
||||
0-3. Optional.
|
||||
LMC#: Parameter can be different for memory controller. This
|
||||
specifies which LMC the value is for. LMC must be
|
||||
0-3. Optional.
|
||||
N#: Parameter can be different for each node. This specifies
|
||||
which node the value is for. Node must be 0-3. Optional. */
|
||||
//DDR-CONFIG-MODE1-SRT.RANKS%d.DIMMS%d.RANK%d.LMC%d.N%d = "0";
|
||||
|
||||
/* RTT_WR per rank. LMC writes this value to MR2[RTT_WR] in the rank
|
||||
(i.e. DIMM0_CS0) DDR3 parts when selected during power-up/init,
|
||||
write-leveling, and, if LMC()_CONFIG[SREF_WITH_DLL] is set,
|
||||
self-refresh entry and exit instruction sequences. See
|
||||
LMC()_SEQ_CTL[SEQ_SEL,INIT_START] and LMC()_CONFIG[RANKMASK] and
|
||||
LMC()_RESET_CTL[DDR3PWARM, DDR3PSOFT].
|
||||
Parameters:
|
||||
RANKS#: Specifies that this parameter only applies to DIMMs
|
||||
with the supplied number of ranks. Support ranks is 1, 2,
|
||||
or 4. Optional.
|
||||
DIMMS#: Specifies that this parameter only applies when the
|
||||
DIMMs per memory controller matches. Support number of
|
||||
DIMMs is 1 or 2. Optional.
|
||||
RANK#: Parameter can be different for each rank of a DIMM. This
|
||||
specifies which rank the value is for. Rank must be
|
||||
0-3. Optional.
|
||||
LMC#: Parameter can be different for memory controller. This
|
||||
specifies which LMC the value is for. LMC must be
|
||||
0-3. Optional.
|
||||
N#: Parameter can be different for each node. This specifies
|
||||
which node the value is for. Node must be 0-3. Optional. */
|
||||
//DDR-CONFIG-MODE1-RTT-WR.RANKS%d.DIMMS%d.RANK%d.LMC%d.N%d = "0";
|
||||
|
||||
//DDR-CONFIG-MODE1-RTT-WR.RANKS1 = "0x4";
|
||||
DDR-CONFIG-MODE1-RTT-WR.RANKS1.DIMMS1.RANK0 = "0x4";
|
||||
DDR-CONFIG-MODE1-RTT-WR.RANKS1.DIMMS2.RANK0 = "0x4";
|
||||
DDR-CONFIG-MODE1-RTT-WR.RANKS1.DIMMS2.RANK2 = "0x4";
|
||||
|
||||
//DDR-CONFIG-MODE1-RTT-WR.RANKS2 = "0x2";
|
||||
DDR-CONFIG-MODE1-RTT-WR.RANKS2.DIMMS1.RANK0 = "0x2";
|
||||
DDR-CONFIG-MODE1-RTT-WR.RANKS2.DIMMS1.RANK1 = "0x2";
|
||||
DDR-CONFIG-MODE1-RTT-WR.RANKS2.DIMMS2 = "0x2";
|
||||
|
||||
DDR-CONFIG-MODE1-RTT-WR.RANKS4 = "0x1";
|
||||
|
||||
/* Output driver impedance control per rank. LMC writes this value
|
||||
to MR1[D.I.C.] in the rank (i.e. DIMM0_CS0) DDR3 parts when
|
||||
selected during power-up/init, write-leveling, and, if
|
||||
LMC()_CONFIG[SREF_WITH_DLL] is set, self-refresh entry and exit
|
||||
instruction sequences. See LMC()_SEQ_CTL[SEQ_SEL,INIT_START] and
|
||||
LMC()_CONFIG[RANKMASK] and LMC()_RESET_CTL[DDR3PWARM,DDR3PSOFT].
|
||||
Parameters:
|
||||
RANKS#: Specifies that this parameter only applies to DIMMs
|
||||
with the supplied number of ranks. Support ranks is 1, 2,
|
||||
or 4. Optional.
|
||||
DIMMS#: Specifies that this parameter only applies when the
|
||||
DIMMs per memory controller matches. Support number of
|
||||
DIMMs is 1 or 2. Optional.
|
||||
RANK#: Parameter can be different for each rank of a DIMM. This
|
||||
specifies which rank the value is for. Rank must be
|
||||
0-3. Optional.
|
||||
LMC#: Parameter can be different for memory controller. This
|
||||
specifies which LMC the value is for. LMC must be
|
||||
0-3. Optional.
|
||||
N#: Parameter can be different for each node. This specifies
|
||||
which node the value is for. Node must be 0-3. Optional. */
|
||||
//DDR-CONFIG-MODE1-DIC.RANKS%d.DIMMS%d.RANK%d.LMC%d.N%d = "0";
|
||||
DDR-CONFIG-MODE1-DIC.RANKS4.DIMMS1 = "0x1";
|
||||
|
||||
/* RTT_NOM per rank. LMC writes this value to MR1[RTT_NOM] in the
|
||||
rank (i.e. DIMM0_CS0) DDR3 parts when selected during
|
||||
power-up/init, write-leveling, and, if LMC()_CONFIG[SREF_WITH_DLL]
|
||||
is set, self-refresh entry and exit instruction sequences. See
|
||||
LMC()_SEQ_CTL[SEQ_SEL,INIT_START] and LMC()_CONFIG[RANKMASK] and
|
||||
LMC()_RESET_CTL[DDR3PWARM, DDR3PSOFT]. Per JEDEC DDR3
|
||||
specifications, if RTT_NOM is used during write operations, only
|
||||
values MR1[RTT_NOM] = 1 (RZQ/4), 2 (RZQ/2), or 3 (RZQ/6) are
|
||||
allowed. Otherwise, values MR1[RTT_NOM] = 4 (RZQ/12) and 5 (RZQ/8)
|
||||
are also allowed.
|
||||
Parameters:
|
||||
RANKS#: Specifies that this parameter only applies to DIMMs
|
||||
with the supplied number of ranks. Support ranks is 1, 2,
|
||||
or 4. Optional.
|
||||
DIMMS#: Specifies that this parameter only applies when the
|
||||
DIMMs per memory controller matches. Support number of
|
||||
DIMMs is 1 or 2. Optional.
|
||||
RANK#: Parameter can be different for each rank of a DIMM. This
|
||||
specifies which rank the value is for. Rank must be
|
||||
0-3. Optional.
|
||||
LMC#: Parameter can be different for memory controller. This
|
||||
specifies which LMC the value is for. LMC must be
|
||||
0-3. Optional.
|
||||
N#: Parameter can be different for each node. This specifies
|
||||
which node the value is for. Node must be 0-3. Optional. */
|
||||
//DDR-CONFIG-MODE1-RTT-NOM.RANKS%d.DIMMS%d.RANK%d.LMC%d.N%d = "0";
|
||||
DDR-CONFIG-MODE1-RTT-NOM.RANKS2.DIMMS2 = "0x2";
|
||||
DDR-CONFIG-MODE1-RTT-NOM.RANKS4.DIMMS1.RANK0 = "0x4";
|
||||
DDR-CONFIG-MODE1-RTT-NOM.RANKS4.DIMMS1.RANK2 = "0x4";
|
||||
|
||||
/* Host Interface DQ/DQS Output Driver Impedance control for DIMM0's
|
||||
Data Buffer. This is the default value used during Host Interface
|
||||
Write Leveling in LRDIMM environment, i.e.,
|
||||
LMC()_CONFIG[LRDIMM_ENA] = 1, LMC()_SEQ_CTL[SEQ_SEL] = 0x6.
|
||||
0x0 = RZQ/6 (40 ohm).
|
||||
0x1 = RZQ/7 (34 ohm).
|
||||
0x2 = RZQ/5 (48 ohm).
|
||||
0x3-0x7 = Reserved.
|
||||
Parameters:
|
||||
RANKS#: Specifies that this parameter only applies to DIMMs
|
||||
with the supplied number of ranks. Support ranks is 1, 2,
|
||||
or 4. Optional.
|
||||
DIMMS#: Specifies that this parameter only applies when the
|
||||
DIMMs per memory controller matches. Support number of
|
||||
DIMMs is 1 or 2. Optional.
|
||||
LMC#: Parameter can be different for memory controller. This
|
||||
specifies which LMC the value is for. LMC must be
|
||||
0-3. Optional.
|
||||
N#: Parameter can be different for each node. This specifies
|
||||
which node the value is for. Node must be 0-3. Optional. */
|
||||
//DDR-CONFIG-MODE1-DB-OUTPUT-IMPEDANCE.RANKS%d.DIMMS%d.LMC%d.N%d = "0";
|
||||
|
||||
/* RTT park value per rank.
|
||||
Parameters:
|
||||
RANKS#: Specifies that this parameter only applies to DIMMs
|
||||
with the supplied number of ranks. Support ranks is 1, 2,
|
||||
or 4. Optional.
|
||||
DIMMS#: Specifies that this parameter only applies when the
|
||||
DIMMs per memory controller matches. Support number of
|
||||
DIMMs is 1 or 2. Optional.
|
||||
RANK#: Parameter can be different for each rank of a DIMM. This
|
||||
specifies which rank the value is for. Rank must be
|
||||
0-3. Optional.
|
||||
LMC#: Parameter can be different for memory controller. This
|
||||
specifies which LMC the value is for. LMC must be
|
||||
0-3. Optional.
|
||||
N#: Parameter can be different for each node. This specifies
|
||||
which node the value is for. Node must be 0-3. Optional. */
|
||||
//DDR-CONFIG-MODE2-RTT-PARK.RANKS%d.DIMMS%d.RANK%d.LMC%d.N%d = "0";
|
||||
|
||||
//DDR-CONFIG-MODE2-RTT-PARK.RANKS1.DIMMS1 = "0x1";
|
||||
DDR-CONFIG-MODE2-RTT-PARK.RANKS1.DIMMS1.RANK0 = "0x1";
|
||||
|
||||
//DDR-CONFIG-MODE2-RTT-PARK.RANKS1.DIMMS2 = "0x5";
|
||||
DDR-CONFIG-MODE2-RTT-PARK.RANKS1.DIMMS2.RANK0 = "0x5";
|
||||
DDR-CONFIG-MODE2-RTT-PARK.RANKS1.DIMMS2.RANK2 = "0x5";
|
||||
|
||||
//DDR-CONFIG-MODE2-RTT-PARK.RANKS2.DIMMS1 = "0x2";
|
||||
DDR-CONFIG-MODE2-RTT-PARK.RANKS2.DIMMS1.RANK0 = "0x2";
|
||||
DDR-CONFIG-MODE2-RTT-PARK.RANKS2.DIMMS1.RANK1 = "0x2";
|
||||
|
||||
DDR-CONFIG-MODE2-RTT-PARK.RANKS2.DIMMS2 = "0x1";
|
||||
DDR-CONFIG-MODE2-RTT-PARK.RANKS4.DIMMS1.RANK0 = "0x6";
|
||||
DDR-CONFIG-MODE2-RTT-PARK.RANKS4.DIMMS1.RANK1 = "0x6";
|
||||
|
||||
/* VREF value per rank.
|
||||
Parameters:
|
||||
RANKS#: Specifies that this parameter only applies to DIMMs
|
||||
with the supplied number of ranks. Support ranks is 1, 2,
|
||||
or 4. Optional.
|
||||
DIMMS#: Specifies that this parameter only applies when the
|
||||
DIMMs per memory controller matches. Support number of
|
||||
DIMMs is 1 or 2. Optional.
|
||||
RANK#: Parameter can be different for each rank of a DIMM. This
|
||||
specifies which rank the value is for. Rank must be
|
||||
0-3. Optional.
|
||||
LMC#: Parameter can be different for memory controller. This
|
||||
specifies which LMC the value is for. LMC must be
|
||||
0-3. Optional.
|
||||
N#: Parameter can be different for each node. This specifies
|
||||
which node the value is for. Node must be 0-3. Optional. */
|
||||
//DDR-CONFIG-MODE2-VREF-VALUE.RANKS%d.DIMMS%d.RANK%d.LMC%d.N%d = "0";
|
||||
|
||||
//DDR-CONFIG-MODE2-VREF-VALUE.RANKS1.DIMMS1 = "0x22";
|
||||
DDR-CONFIG-MODE2-VREF-VALUE.RANKS1.DIMMS1.RANK0 = "0x22";
|
||||
|
||||
//DDR-CONFIG-MODE2-VREF-VALUE.RANKS1.DIMMS2 = "0x1f";
|
||||
DDR-CONFIG-MODE2-VREF-VALUE.RANKS1.DIMMS2.RANK0 = "0x1f";
|
||||
DDR-CONFIG-MODE2-VREF-VALUE.RANKS1.DIMMS2.RANK2 = "0x1f";
|
||||
|
||||
//DDR-CONFIG-MODE2-VREF-VALUE.RANKS2.DIMMS1 = "0x19";
|
||||
DDR-CONFIG-MODE2-VREF-VALUE.RANKS2.DIMMS1.RANK0 = "0x19";
|
||||
DDR-CONFIG-MODE2-VREF-VALUE.RANKS2.DIMMS1.RANK1 = "0x19";
|
||||
|
||||
DDR-CONFIG-MODE2-VREF-VALUE.RANKS2.DIMMS2 = "0x19";
|
||||
DDR-CONFIG-MODE2-VREF-VALUE.RANKS4.DIMMS1.RANK0 = "0x1f";
|
||||
DDR-CONFIG-MODE2-VREF-VALUE.RANKS4.DIMMS1.RANK1 = "0x1f";
|
||||
|
||||
/* VREF range per rank.
|
||||
Parameters:
|
||||
RANKS#: Specifies that this parameter only applies to DIMMs
|
||||
with the supplied number of ranks. Support ranks is 1, 2,
|
||||
or 4. Optional.
|
||||
DIMMS#: Specifies that this parameter only applies when the
|
||||
DIMMs per memory controller matches. Support number of
|
||||
DIMMs is 1 or 2. Optional.
|
||||
RANK#: Parameter can be different for each rank of a DIMM. This
|
||||
specifies which rank the value is for. Rank must be
|
||||
0-3. Optional.
|
||||
LMC#: Parameter can be different for memory controller. This
|
||||
specifies which LMC the value is for. LMC must be
|
||||
0-3. Optional.
|
||||
N#: Parameter can be different for each node. This specifies
|
||||
which node the value is for. Node must be 0-3. Optional. */
|
||||
//DDR-CONFIG-MODE2-VREF-RANGE.RANKS%d.DIMMS%d.RANK%d.LMC%d.N%d = "0";
|
||||
|
||||
/* Vref training mode enable, used for all ranks.
|
||||
Parameters:
|
||||
RANKS#: Specifies that this parameter only applies to DIMMs
|
||||
with the supplied number of ranks. Support ranks is 1, 2,
|
||||
or 4. Optional.
|
||||
DIMMS#: Specifies that this parameter only applies when the
|
||||
DIMMs per memory controller matches. Support number of
|
||||
DIMMs is 1 or 2. Optional.
|
||||
LMC#: Parameter can be different for memory controller. This
|
||||
specifies which LMC the value is for. LMC must be
|
||||
0-3. Optional.
|
||||
N#: Parameter can be different for each node. This specifies
|
||||
which node the value is for. Node must be 0-3. Optional. */
|
||||
//DDR-CONFIG-MODE2-VREFDQ-TRAIN-EN.RANKS%d.DIMMS%d.LMC%d.N%d = "0";
|
||||
|
||||
/* RODT NCTL impedance control bits. This field controls ODT values
|
||||
during a memory read.
|
||||
0x0 = No ODT.
|
||||
0x1 = 20 ohm.
|
||||
0x2 = 30 ohm.
|
||||
0x3 = 40 ohm.
|
||||
0x4 = 60 ohm.
|
||||
0x5 = 120 ohm.
|
||||
_ else = Reserved.
|
||||
In DDR4 mode:
|
||||
0x0 = No ODT.
|
||||
0x1 = 40 ohm.
|
||||
0x2 = 60 ohm.
|
||||
0x3 = 80 ohm.
|
||||
0x4 = 120 ohm.
|
||||
0x5 = 240 ohm.
|
||||
0x6 = 34 ohm.
|
||||
0x7 = 48 ohm.
|
||||
_ else = Reserved.
|
||||
Parameters:
|
||||
RANKS#: Specifies that this parameter only applies to DIMMs
|
||||
with the supplied number of ranks. Support ranks is 1, 2,
|
||||
or 4. Optional.
|
||||
DIMMS#: Specifies that this parameter only applies when the
|
||||
DIMMs per memory controller matches. Support number of
|
||||
DIMMs is 1 or 2. Optional.
|
||||
LMC#: Parameter can be different for memory controller. This
|
||||
specifies which LMC the value is for. LMC must be
|
||||
0-3. Optional.
|
||||
N#: Parameter can be different for each node. This specifies
|
||||
which node the value is for. Node must be 0-3. Optional. */
|
||||
//DDR-CONFIG-RODT-CTL.RANKS%d.DIMMS%d.LMC%d.N%d = "0";
|
||||
DDR-CONFIG-RODT-CTL.RANKS1.DIMMS1 = "0x7";
|
||||
DDR-CONFIG-RODT-CTL.RANKS1.DIMMS2 = "0x3";
|
||||
DDR-CONFIG-RODT-CTL.RANKS2.DIMMS1 = "0x3";
|
||||
DDR-CONFIG-RODT-CTL.RANKS2.DIMMS2 = "0x7";
|
||||
DDR-CONFIG-RODT-CTL.RANKS4.DIMMS1 = "0x7";
|
||||
|
||||
/* LMC Read OnDieTermination Mask Register
|
||||
System designers may desire to terminate DQ/DQS lines for higher
|
||||
frequency DDR operations, especially on a multirank system. DDR3
|
||||
DQ/DQS I/Os have built-in termination resistors that can be turned
|
||||
on or off by the controller, after meeting TAOND and TAOF timing
|
||||
requirements.
|
||||
Each rank has its own ODT pin that fans out to all the memory
|
||||
parts in that DIMM. System designers may prefer different
|
||||
combinations of ODT ONs for read operations into different ranks.
|
||||
CNXXXX supports full programmability by way of the mask register
|
||||
below. Each rank position has its own 4-bit programmable field.
|
||||
When the controller does a read to that rank, it sets the 4 ODT
|
||||
pins to the MASK pins below. For example, when doing a read from
|
||||
Rank0, a system designer may desire to terminate the lines with
|
||||
the resistor on DIMM0/Rank1. The mask RODT_D0_R0 would then be {0010}.
|
||||
CNXXXX drives the appropriate mask values on the ODT pins by
|
||||
default. If this feature is not required, write 0x0 in this
|
||||
register. Note that, as per the JEDEC DDR3 specifications, the ODT
|
||||
pin for the rank that is being read should always be 0x0. When a
|
||||
given RANK is selected, the RODT mask for that rank is used.
|
||||
Parameters:
|
||||
RANKS#: Specifies that this parameter only applies to DIMMs
|
||||
with the supplied number of ranks. Support ranks is 1, 2,
|
||||
or 4. Optional.
|
||||
DIMMS#: Specifies that this parameter only applies when the
|
||||
DIMMs per memory controller matches. Support number of
|
||||
DIMMs is 1 or 2. Optional.
|
||||
LMC#: Parameter can be different for memory controller. This
|
||||
specifies which LMC the value is for. LMC must be
|
||||
0-3. Optional.
|
||||
N#: Parameter can be different for each node. This specifies
|
||||
which node the value is for. Node must be 0-3. Optional. */
|
||||
//DDR-CONFIG-RODT-MASK.RANKS%d.DIMMS%d.LMC%d.N%d = "0";
|
||||
DDR-CONFIG-RODT-MASK.RANKS2.DIMMS2 = "0x4080102";
|
||||
DDR-CONFIG-RODT-MASK.RANKS4.DIMMS1 = "0x1010202";
|
||||
|
||||
/* 1=120ohms, 2=60ohms, 3=40ohms, 4=30ohms, 5=20ohms
|
||||
Parameters:
|
||||
LMC#: Parameter can be different for memory controller. This
|
||||
specifies which LMC the value is for. LMC must be
|
||||
0-3. Optional.
|
||||
N#: Parameter can be different for each node. This specifies
|
||||
which node the value is for. Node must be 0-3. Optional. */
|
||||
//DDR-CONFIG-CUSTOM-MIN-RTT-NOM-IDX.LMC%d.N%d = "1";
|
||||
DDR-CONFIG-CUSTOM-MIN-RTT-NOM-IDX = "0x1";
|
||||
|
||||
/* 1=120ohms, 2=60ohms, 3=40ohms, 4=30ohms, 5=20ohms
|
||||
Parameters:
|
||||
LMC#: Parameter can be different for memory controller. This
|
||||
specifies which LMC the value is for. LMC must be
|
||||
0-3. Optional.
|
||||
N#: Parameter can be different for each node. This specifies
|
||||
which node the value is for. Node must be 0-3. Optional. */
|
||||
//DDR-CONFIG-CUSTOM-MAX-RTT-NOM-IDX.LMC%d.N%d = "5";
|
||||
DDR-CONFIG-CUSTOM-MAX-RTT-NOM-IDX = "0x7";
|
||||
|
||||
/* 1=20ohms, 2=30ohms, 3=40ohms, 4=60ohms, 5=120ohms
|
||||
Parameters:
|
||||
LMC#: Parameter can be different for memory controller. This
|
||||
specifies which LMC the value is for. LMC must be
|
||||
0-3. Optional.
|
||||
N#: Parameter can be different for each node. This specifies
|
||||
which node the value is for. Node must be 0-3. Optional. */
|
||||
//DDR-CONFIG-CUSTOM-MIN-RODT-CTL.LMC%d.N%d = "1";
|
||||
DDR-CONFIG-CUSTOM-MIN-RODT-CTL = "0x1";
|
||||
|
||||
/* 1=20ohms, 2=30ohms, 3=40ohms, 4=60ohms, 5=120ohms
|
||||
Parameters:
|
||||
LMC#: Parameter can be different for memory controller. This
|
||||
specifies which LMC the value is for. LMC must be
|
||||
0-3. Optional.
|
||||
N#: Parameter can be different for each node. This specifies
|
||||
which node the value is for. Node must be 0-3. Optional. */
|
||||
//DDR-CONFIG-CUSTOM-MAX-RODT-CTL.LMC%d.N%d = "5";
|
||||
DDR-CONFIG-CUSTOM-MAX-RODT-CTL = "0x7";
|
||||
|
||||
/* Drive strength control for DDR_CK_X_P, DDR_DIMMX_CSX_L,
|
||||
DDR_DIMMX_ODT_X drivers.
|
||||
Parameters:
|
||||
LMC#: Parameter can be different for memory controller. This
|
||||
specifies which LMC the value is for. LMC must be
|
||||
0-3. Optional.
|
||||
N#: Parameter can be different for each node. This specifies
|
||||
which node the value is for. Node must be 0-3. Optional. */
|
||||
//DDR-CONFIG-CUSTOM-CK-CTL.LMC%d.N%d = "0";
|
||||
DDR-CONFIG-CUSTOM-CK-CTL = "0x4";
|
||||
|
||||
/* Drive strength control for CMD/A/RESET_L/CKEX drivers.
|
||||
Parameters:
|
||||
LMC#: Parameter can be different for memory controller. This
|
||||
specifies which LMC the value is for. LMC must be
|
||||
0-3. Optional.
|
||||
N#: Parameter can be different for each node. This specifies
|
||||
which node the value is for. Node must be 0-3. Optional. */
|
||||
//DDR-CONFIG-CUSTOM-CMD-CTL.LMC%d.N%d = "0";
|
||||
DDR-CONFIG-CUSTOM-CMD-CTL = "0x4";
|
||||
|
||||
/* Drive strength control for ODT, etc. drivers.
|
||||
In DDR3 mode:
|
||||
0x1 = 24 ohm.
|
||||
0x2 = 26.67 ohm.
|
||||
0x3 = 30 ohm.
|
||||
0x4 = 34.3 ohm.
|
||||
0x5 = 40 ohm.
|
||||
0x6 = 48 ohm.
|
||||
0x7 = 60 ohm.
|
||||
else = Reserved.
|
||||
In DDR4 mode:
|
||||
0x0 = Reserved.
|
||||
0x1 = Reserved.
|
||||
0x2 = 26 ohm.
|
||||
0x3 = 30 ohm.
|
||||
0x4 = 34 ohm.
|
||||
0x5 = 40 ohm.
|
||||
0x6 = 48 ohm.
|
||||
else = Reserved.
|
||||
Parameters:
|
||||
LMC#: Parameter can be different for memory controller. This
|
||||
specifies which LMC the value is for. LMC must be
|
||||
0-3. Optional.
|
||||
N#: Parameter can be different for each node. This specifies
|
||||
which node the value is for. Node must be 0-3. Optional. */
|
||||
//DDR-CONFIG-CUSTOM-CTL-CTL.LMC%d.N%d = "0";
|
||||
DDR-CONFIG-CUSTOM-CTL-CTL = "0x4";
|
||||
|
||||
/* Minimum allowed CAS Latency
|
||||
Parameters:
|
||||
LMC#: Parameter can be different for memory controller. This
|
||||
specifies which LMC the value is for. LMC must be
|
||||
0-3. Optional.
|
||||
N#: Parameter can be different for each node. This specifies
|
||||
which node the value is for. Node must be 0-3. Optional. */
|
||||
//DDR-CONFIG-CUSTOM-MIN-CAS-LATENCY.LMC%d.N%d = "0";
|
||||
|
||||
/* When set, LMC attempts to select the read-leveling setting that is
|
||||
LMC()_RLEVEL_CTL[OFFSET] settings earlier than the last passing
|
||||
read-leveling setting in the largest contiguous sequence of
|
||||
passing settings. When clear, or if the setting selected by
|
||||
LMC()_RLEVEL_CTL[OFFSET] did not pass, LMC selects the middle
|
||||
setting in the largest contiguous sequence of passing settings,
|
||||
rounding earlier when necessary.
|
||||
Parameters:
|
||||
LMC#: Parameter can be different for memory controller. This
|
||||
specifies which LMC the value is for. LMC must be
|
||||
0-3. Optional.
|
||||
N#: Parameter can be different for each node. This specifies
|
||||
which node the value is for. Node must be 0-3. Optional. */
|
||||
//DDR-CONFIG-CUSTOM-OFFSET-EN.LMC%d.N%d = "1";
|
||||
DDR-CONFIG-CUSTOM-OFFSET-EN = "0x1";
|
||||
|
||||
/* The offset used when LMC()_RLEVEL_CTL[OFFSET] is set.
|
||||
Parameters:
|
||||
%s: This setting can by specified by DRAM type (UDIMM or RDIMM)
|
||||
Different settings can be used for each, or the type can be
|
||||
omitted to use the same setting for both.
|
||||
LMC#: Parameter can be different for memory controller. This
|
||||
specifies which LMC the value is for. LMC must be
|
||||
0-3. Optional.
|
||||
N#: Parameter can be different for each node. This specifies
|
||||
which node the value is for. Node must be 0-3. Optional. */
|
||||
//DDR-CONFIG-CUSTOM-OFFSET.%s.LMC%d.N%d = "0";
|
||||
DDR-CONFIG-CUSTOM-OFFSET = "0x2";
|
||||
|
||||
/* Enables software interpretation of per-byte read delays using the
|
||||
measurements collected by the chip rather than completely relying
|
||||
on the automatically to determine the delays. 1=software
|
||||
computation is recommended since a more complete analysis is
|
||||
implemented in software.
|
||||
Parameters:
|
||||
LMC#: Parameter can be different for memory controller. This
|
||||
specifies which LMC the value is for. LMC must be
|
||||
0-3. Optional.
|
||||
N#: Parameter can be different for each node. This specifies
|
||||
which node the value is for. Node must be 0-3. Optional. */
|
||||
//DDR-CONFIG-CUSTOM-RLEVEL-COMPUTE.LMC%d.N%d = "0";
|
||||
|
||||
/* Set to 2 unless instructed differently by Cavium.
|
||||
Parameters:
|
||||
LMC#: Parameter can be different for memory controller. This
|
||||
specifies which LMC the value is for. LMC must be
|
||||
0-3. Optional.
|
||||
N#: Parameter can be different for each node. This specifies
|
||||
which node the value is for. Node must be 0-3. Optional. */
|
||||
//DDR-CONFIG-CUSTOM-RLEVEL-COMP-OFFSET.%s.LMC%d.N%d = "2";
|
||||
|
||||
/* Turn on the DDR 2T mode. 2-cycle window for CMD and address. This
|
||||
mode helps relieve setup time pressure on the address and command
|
||||
bus. Please refer to Micron's tech note tn_47_01 titled DDR2-533
|
||||
Memory Design Guide for Two DIMM Unbuffered Systems for physical
|
||||
details.
|
||||
Parameters:
|
||||
%s: This setting can by specified by DRAM type (UDIMM or RDIMM)
|
||||
Different settings can be used for each, or the type can be
|
||||
omitted to use the same setting for both.
|
||||
LMC#: Parameter can be different for memory controller. This
|
||||
specifies which LMC the value is for. LMC must be
|
||||
0-3. Optional.
|
||||
N#: Parameter can be different for each node. This specifies
|
||||
which node the value is for. Node must be 0-3. Optional. */
|
||||
//DDR-CONFIG-CUSTOM-DDR2T.%s.LMC%d.N%d = "0";
|
||||
DDR-CONFIG-CUSTOM-DDR2T = "0x1";
|
||||
|
||||
/* As result of the flyby topology prescribed in the JEDEC
|
||||
specifications the byte delays should maintain a consistent
|
||||
increasing or decreasing trend across the bytes on standard DIMMs.
|
||||
This setting can be used disable that check for unusual
|
||||
circumstances where the check is not useful.
|
||||
Parameters:
|
||||
LMC#: Parameter can be different for memory controller. This
|
||||
specifies which LMC the value is for. LMC must be
|
||||
0-3. Optional.
|
||||
N#: Parameter can be different for each node. This specifies
|
||||
which node the value is for. Node must be 0-3. Optional. */
|
||||
//DDR-CONFIG-CUSTOM-DISABLE-SEQUENTIAL-DELAY-CHECK.LMC%d.N%d = "0";
|
||||
|
||||
/* An additional sequential delay check for the delays that result
|
||||
from the flyby topology. This value specifies the maximum
|
||||
difference between the delays of adjacent bytes. A value of 0
|
||||
disables this check.
|
||||
Parameters:
|
||||
LMC#: Parameter can be different for memory controller. This
|
||||
specifies which LMC the value is for. LMC must be
|
||||
0-3. Optional.
|
||||
N#: Parameter can be different for each node. This specifies
|
||||
which node the value is for. Node must be 0-3. Optional. */
|
||||
//DDR-CONFIG-CUSTOM-MAXIMUM-ADJACENT-RLEVEL-DELAY-INCREMENT.LMC%d.N%d = "0";
|
||||
DDR-CONFIG-CUSTOM-MAXIMUM-ADJACENT-RLEVEL-DELAY-INCREMENT = "0x2";
|
||||
|
||||
/* The parity input signal PAR_IN on each DIMM must be strapped high
|
||||
or low on the board. This bit is programmed into
|
||||
LMC0_DIMM_CTL[PARITY] and it must be set to match the board
|
||||
strapping. This signal is typically strapped low.
|
||||
Parameters:
|
||||
LMC#: Parameter can be different for memory controller. This
|
||||
specifies which LMC the value is for. LMC must be
|
||||
0-3. Optional.
|
||||
N#: Parameter can be different for each node. This specifies
|
||||
which node the value is for. Node must be 0-3. Optional. */
|
||||
//DDR-CONFIG-CUSTOM-PARITY.LMC%d.N%d = "0";
|
||||
|
||||
/* Front Porch Enable: When set, the turn-off time for the default
|
||||
DDR_DQ/DQS drivers is FPRCH2 CKs earlier.
|
||||
0 = 0 CKs
|
||||
1 = 1 CKs
|
||||
2 = 2 CKs
|
||||
Parameters:
|
||||
LMC#: Parameter can be different for memory controller. This
|
||||
specifies which LMC the value is for. LMC must be
|
||||
0-3. Optional.
|
||||
N#: Parameter can be different for each node. This specifies
|
||||
which node the value is for. Node must be 0-3. Optional. */
|
||||
//DDR-CONFIG-CUSTOM-FPRCH2.LMC%d.N%d = "0";
|
||||
DDR-CONFIG-CUSTOM-FPRCH2 = "0x2";
|
||||
|
||||
/* Enable 32-bit datapath mode. Set to 1 if only 32 DQ pins are
|
||||
used.
|
||||
Parameters:
|
||||
LMC#: Parameter can be different for memory controller. This
|
||||
specifies which LMC the value is for. LMC must be
|
||||
0-3. Optional.
|
||||
N#: Parameter can be different for each node. This specifies
|
||||
which node the value is for. Node must be 0-3. Optional. */
|
||||
//DDR-CONFIG-CUSTOM-MODE32B.LMC%d.N%d = "0";
|
||||
|
||||
/* Use Measured VREF
|
||||
Parameters:
|
||||
LMC#: Parameter can be different for memory controller. This
|
||||
specifies which LMC the value is for. LMC must be
|
||||
0-3. Optional.
|
||||
N#: Parameter can be different for each node. This specifies
|
||||
which node the value is for. Node must be 0-3. Optional. */
|
||||
//DDR-CONFIG-CUSTOM-MEASURED-VREF.LMC%d.N%d = "0";
|
||||
|
||||
/* Supply a custom DLL write offset
|
||||
Parameters:
|
||||
BYTE#: Byte lane to apply the parameter to (0-8).
|
||||
LMC#: Parameter can be different for memory controller. This
|
||||
specifies which LMC the value is for. LMC must be
|
||||
0-3. Optional.
|
||||
N#: Parameter can be different for each node. This specifies
|
||||
which node the value is for. Node must be 0-3. Optional. */
|
||||
//DDR-CONFIG-CUSTOM-DLL-WRITE-OFFSET.BYTE%d.LMC%d.N%d = "0";
|
||||
|
||||
/* Supply a custom DLL read offset
|
||||
Parameters:
|
||||
BYTE#: Byte lane to apply the parameter to (0-8).
|
||||
LMC#: Parameter can be different for memory controller. This
|
||||
specifies which LMC the value is for. LMC must be
|
||||
0-3. Optional.
|
||||
N#: Parameter can be different for each node. This specifies
|
||||
which node the value is for. Node must be 0-3. Optional. */
|
||||
//DDR-CONFIG-CUSTOM-DLL-READ-OFFSET.BYTE%d.LMC%d.N%d = "0";
|
||||
|
||||
/* Choose the debug logging level used during DRAM initialization.
|
||||
Zero disables debug logging. The possible debug levels are:
|
||||
0: Off, no logging
|
||||
1: Logging of DRAM initialization at a normal detail level
|
||||
2: Logging of DRAM initialization at FAE detail level
|
||||
3: Logging of DRAM initialization at TME detail level
|
||||
4: Logging of DRAM initialization at DEV detail level
|
||||
5: Logging of DRAM initialization at DEV2 detail level
|
||||
6: Logging of DRAM initialization at DEV3 detail level
|
||||
7: Logging of DRAM initialization at DEV4 detail level
|
||||
Add in the following for special trace features.
|
||||
16: Trace specialized DRAM controller sequences.
|
||||
32: Trace every DRAM controller register write. */
|
||||
//DDR-VERBOSE = "0";
|
||||
|
||||
/* Run a short DRAM test after DRAM is initialized as quick check
|
||||
for functionality. This is normally not needed required. Boards
|
||||
with poor DRAM power supplies may use this to detect failures
|
||||
during boot. This should be used in combination with the watchdog
|
||||
timer. */
|
||||
//DDR-TEST-BOOT = "0";
|
||||
|
||||
/* The DRAM initialization code has the ability to toggle a GPIO to
|
||||
signal when it is running. Boards may need to mux TWSI access
|
||||
between a BMC and the SOC so the BMC can monitor DIMM temperatures
|
||||
and health. This GPIO will be driven high when the SOC may read
|
||||
from the SPDs on the DIMMs. When driven low, another device (BMC)
|
||||
may takeover the TWSI connections to the DIMMS. The default value
|
||||
(-1) disables this feature. */
|
||||
//DDR-CONFIG-GPIO = "-1";
|
||||
|
||||
/* Scramble DRAM to prevent snooping. This options programs the DRAM
|
||||
controller to scramble addresses and data with random values.
|
||||
Supported values:
|
||||
0: No scrambling
|
||||
1: Always scramble
|
||||
2: Scramble only when using trusted boot (Default) */
|
||||
//DDR-CONFIG-SCRAMBLE = "2";
|
||||
}; /* cavium,bdk */
|
||||
}; /* / */
|
18
src/mainboard/cavium/cn8100_sff_evb/devicetree.cb
Normal file
18
src/mainboard/cavium/cn8100_sff_evb/devicetree.cb
Normal file
|
@ -0,0 +1,18 @@
|
|||
##
|
||||
## This file is part of the coreboot project.
|
||||
##
|
||||
## Copyright 2017-present Facebook, Inc.
|
||||
##
|
||||
## This program is free software; you can redistribute it and/or modify
|
||||
## it under the terms of the GNU General Public License as published by
|
||||
## the Free Software Foundation; version 2 of the License.
|
||||
##
|
||||
## This program is distributed in the hope that it will be useful,
|
||||
## but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
## GNU General Public License for more details.
|
||||
##
|
||||
|
||||
chip soc/cavium/cn81xx
|
||||
device cpu_cluster 0 on end
|
||||
end
|
216
src/mainboard/cavium/cn8100_sff_evb/mainboard.c
Normal file
216
src/mainboard/cavium/cn8100_sff_evb/mainboard.c
Normal file
|
@ -0,0 +1,216 @@
|
|||
/*
|
||||
* This file is part of the coreboot project.
|
||||
*
|
||||
* Copyright 2017-2018 Facebook, Inc.
|
||||
* Copyright 2003-2017 Cavium Inc. (support@cavium.com)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; version 2 of the License.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* Derived from Cavium's BSD-3 Clause OCTEONTX-SDK-6.2.0.
|
||||
*/
|
||||
|
||||
#include <device/device.h>
|
||||
#include <libbdk-hal/bdk-config.h>
|
||||
#include <libbdk-hal/bdk-twsi.h>
|
||||
#include <soc/twsi.h>
|
||||
#include <soc/gpio.h>
|
||||
#include <delay.h>
|
||||
|
||||
extern const struct bdk_devicetree_key_value devtree[];
|
||||
|
||||
static void mainboard_init(struct device *dev)
|
||||
{
|
||||
/* FIXME: stub */
|
||||
}
|
||||
|
||||
static void mainboard_enable(struct device *dev)
|
||||
{
|
||||
dev->ops->init = &mainboard_init;
|
||||
|
||||
bdk_config_set_fdt(devtree);
|
||||
|
||||
/*
|
||||
* Adapted from Cavium's devicetree TWSI-WRITE:
|
||||
* Init board-specific I2C hardware:
|
||||
*/
|
||||
twsi_init(0, I2C_SPEED_STANDARD);
|
||||
|
||||
/* Initialize IO expander U6 to power-up defaults */
|
||||
/* float all pins 0.0-0.7 */
|
||||
bdk_twsix_write_ia(0,0,0x21,6,1,1,0xff);
|
||||
/* float all pins 1.0-1.7 */
|
||||
bdk_twsix_write_ia(0,0,0x21,7,1,1,0xff);
|
||||
/* 0.x: all outputs low, but disabled */
|
||||
bdk_twsix_write_ia(0,0,0x21,2,1,1,0x00);
|
||||
/* 1.x: all outputs low, but disabled */
|
||||
bdk_twsix_write_ia(0,0,0x21,3,1,1,0x00);
|
||||
/* 0.x: no polarity inversion */
|
||||
bdk_twsix_write_ia(0,0,0x21,4,1,1,0x00);
|
||||
/* 1.x: no polarity inversion */
|
||||
bdk_twsix_write_ia(0,0,0x21,5,1,1,0x00);
|
||||
/* Initialize IO expander U89 to power-up defaults */
|
||||
/* float all pins 0.0-0.7 */
|
||||
bdk_twsix_write_ia(0,0,0x22,6,1,1,0xff);
|
||||
/* float all pins 1.0-1.7 */
|
||||
bdk_twsix_write_ia(0,0,0x22,7,1,1,0xff);
|
||||
/* 0.x: all outputs low, but disabled */
|
||||
bdk_twsix_write_ia(0,0,0x22,2,1,1,0x00);
|
||||
/* 1.x: all outputs low, but disabled */
|
||||
bdk_twsix_write_ia(0,0,0x22,3,1,1,0x00);
|
||||
/* 0.x: no polarity inversion */
|
||||
bdk_twsix_write_ia(0,0,0x22,4,1,1,0x00);
|
||||
/* 1.x: no polarity inversion */
|
||||
bdk_twsix_write_ia(0,0,0x22,5,1,1,0x00);
|
||||
/* set outputs SLIC_RESET_L=0 and SPI_SEL=0 */
|
||||
bdk_twsix_write_ia(0,0,0x21,6,1,1,0xee); /* 0.0 & 0.4 are outputs */
|
||||
|
||||
/* Select channel-0 in PCA9546A to enable SFI */
|
||||
bdk_twsix_write_ia(0, 0, 0x70, 0, 1, 1, 0x7);
|
||||
mdelay(10);
|
||||
/* Configure I2C-GPIO expander I/O directions */
|
||||
bdk_twsix_write_ia(0, 0, 0x22, 6, 1, 1, 0x07);
|
||||
mdelay(10);
|
||||
/* Configure I2C-GPIO expander I/O directions */
|
||||
bdk_twsix_write_ia(0, 0, 0x22, 7, 1, 1, 0x38);
|
||||
mdelay(10);
|
||||
/* Turn on SFP+ Transmitters */
|
||||
bdk_twsix_write_ia(0, 0, 0x22, 2, 1, 1, 0x0);
|
||||
mdelay(10);
|
||||
/* Set VSC7224 to I2C mode */
|
||||
bdk_twsix_write_ia(0, 0, 0x22, 3, 1, 1, 0x0);
|
||||
mdelay(10);
|
||||
/* Assert VSC7224 reset*/
|
||||
bdk_twsix_write_ia(0, 0, 0x22, 2, 1, 1, 0x80);
|
||||
mdelay(50);
|
||||
/* Deassert VSC7224 reset*/
|
||||
bdk_twsix_write_ia(0, 0, 0x22, 2, 1, 1, 0x0);
|
||||
mdelay(50);
|
||||
/* Page select FSYNC0 (0x30) */
|
||||
bdk_twsix_write_ia(0, 0, 0x14, 0x7f, 2, 1, 0x0030);
|
||||
mdelay(10);
|
||||
/* Set FSYNC0 for 10.3125Gbps See Table 3 */
|
||||
bdk_twsix_write_ia(0, 0, 0x14, 0x80, 2, 1, 0x2841);
|
||||
mdelay(10);
|
||||
bdk_twsix_write_ia(0, 0, 0x14, 0x81, 2, 1, 0x0008);
|
||||
mdelay(10);
|
||||
bdk_twsix_write_ia(0, 0, 0x14, 0x82, 2, 1, 0x7a00);
|
||||
mdelay(10);
|
||||
bdk_twsix_write_ia(0, 0, 0x14, 0x83, 2, 1, 0x000f);
|
||||
mdelay(10);
|
||||
bdk_twsix_write_ia(0, 0, 0x14, 0x84, 2, 1, 0x9c18);
|
||||
mdelay(10);
|
||||
bdk_twsix_write_ia(0, 0, 0x14, 0x85, 2, 1, 0x0);
|
||||
mdelay(10);
|
||||
|
||||
/* All channels Rx settings set equally */
|
||||
bdk_twsix_write_ia(0, 0, 0x14, 0x7f, 2, 1, 0x0050);
|
||||
mdelay(10);
|
||||
/* Shrink EQ_BUFF */
|
||||
bdk_twsix_write_ia(0, 0, 0x14, 0x82, 2, 1, 0x0014);
|
||||
mdelay(10);
|
||||
/* Select min DFE Delay (DFE_DELAY) */
|
||||
bdk_twsix_write_ia(0, 0, 0x14, 0x90, 2, 1, 0x5585);
|
||||
mdelay(10);
|
||||
/* Set DFE 1-3 limit (DXMAX) = 32dec, AP Max limit = 127 decimal */
|
||||
bdk_twsix_write_ia(0, 0, 0x14, 0x92, 2, 1, 0x207f);
|
||||
mdelay(10);
|
||||
/* Set AP Min limit = 32 decimal */
|
||||
bdk_twsix_write_ia(0, 0, 0x14, 0x93, 2, 1, 0x2000);
|
||||
mdelay(10);
|
||||
/* Set DFE Averaging to the slowest (DFE_AVG) */
|
||||
bdk_twsix_write_ia(0, 0, 0x14, 0x94, 2, 1, 0x0031);
|
||||
mdelay(10);
|
||||
/* Set Inductor Bypass OD_IND_BYP = 0 & fastest Rise/Fall */
|
||||
bdk_twsix_write_ia(0, 0, 0x14, 0x9c, 2, 1, 0x0000);
|
||||
mdelay(10);
|
||||
/* Setting DFE Boost = none. Must set for rev C
|
||||
* (if DFE in adapt mode) */
|
||||
bdk_twsix_write_ia(0, 0, 0x14, 0xaa, 2, 1, 0x0888);
|
||||
mdelay(10);
|
||||
/* Setting EQ Min/Max = 8/72 */
|
||||
bdk_twsix_write_ia(0, 0, 0x14, 0xa8, 2, 1, 0x2408);
|
||||
mdelay(10);
|
||||
/* Setting EQVGA = 96, when in EQVGA manual mode */
|
||||
bdk_twsix_write_ia(0, 0, 0x14, 0xa9, 2, 1, 0x0060);
|
||||
mdelay(10);
|
||||
/* Setting SW_BFOCM, bits 15:14 to 01 */
|
||||
bdk_twsix_write_ia(0, 0, 0x14, 0x87, 2, 1, 0x4021);
|
||||
mdelay(10);
|
||||
/* Turn off adaptive input equalization and VGA adaptive algorithm
|
||||
* control */
|
||||
bdk_twsix_write_ia(0, 0, 0x14, 0x89, 2, 1, 0x7313);
|
||||
mdelay(10);
|
||||
/* Turn on adaptive input equalization and VGA adaptive algorithm
|
||||
* control */
|
||||
bdk_twsix_write_ia(0, 0, 0x14, 0x89, 2, 1, 0x7f13);
|
||||
mdelay(10);
|
||||
|
||||
/* TAP settings for each channel 0-3 */
|
||||
/* Ch-0 Tx */
|
||||
bdk_twsix_write_ia(0, 0, 0x14, 0x7f, 2, 1, 0x0000);
|
||||
mdelay(10);
|
||||
bdk_twsix_write_ia(0, 0, 0x14, 0x99, 2, 1, 0x001f);
|
||||
mdelay(10);
|
||||
bdk_twsix_write_ia(0, 0, 0x14, 0x9a, 2, 1, 0x000f);
|
||||
mdelay(10);
|
||||
bdk_twsix_write_ia(0, 0, 0x14, 0x9b, 2, 1, 0x0004);
|
||||
mdelay(10);
|
||||
|
||||
/* Ch-1 Rx */
|
||||
bdk_twsix_write_ia(0, 0, 0x14, 0x7f, 2, 1, 0x0001);
|
||||
mdelay(10);
|
||||
bdk_twsix_write_ia(0, 0, 0x14, 0x97, 2, 1, 0x1400);
|
||||
mdelay(10);
|
||||
/* Transmitter Output polarity Inverted (Unfortunately,
|
||||
* Rx polarity lines are wrongly inverted on board */
|
||||
bdk_twsix_write_ia(0, 0, 0x14, 0x97, 2, 1, 0x4000);
|
||||
mdelay(10);
|
||||
bdk_twsix_write_ia(0, 0, 0x14, 0x99, 2, 1, 0x000f);
|
||||
mdelay(10);
|
||||
|
||||
/* Ch-2 Tx */
|
||||
bdk_twsix_write_ia(0, 0, 0x14, 0x7f, 2, 1, 0x0002);
|
||||
mdelay(10);
|
||||
bdk_twsix_write_ia(0, 0, 0x14, 0x99, 2, 1, 0x001f);
|
||||
mdelay(10);
|
||||
bdk_twsix_write_ia(0, 0, 0x14, 0x9a, 2, 1, 0x000f);
|
||||
mdelay(10);
|
||||
bdk_twsix_write_ia(0, 0, 0x14, 0x9b, 2, 1, 0x0004);
|
||||
mdelay(10);
|
||||
|
||||
/* Ch-3 Rx */
|
||||
bdk_twsix_write_ia(0, 0, 0x14, 0x7f, 2, 1, 0x0003);
|
||||
mdelay(10);
|
||||
bdk_twsix_write_ia(0, 0, 0x14, 0x97, 2, 1, 0x1400);
|
||||
mdelay(10);
|
||||
/* Transmitter Output polarity Inverted (Unfortunately,
|
||||
* Rx polarity lines are wrongly inverted on board */
|
||||
bdk_twsix_write_ia(0, 0, 0x14, 0x97, 2, 1, 0x4000);
|
||||
mdelay(10);
|
||||
bdk_twsix_write_ia(0, 0, 0x14, 0x99, 2, 1, 0x000f);
|
||||
mdelay(10);
|
||||
|
||||
/**
|
||||
* The following hardware magically starts working after toggling
|
||||
* GPIO_10_PHY_RESET_L:
|
||||
* * SATA PHY
|
||||
* * GBE PHY
|
||||
* * XFI PHY
|
||||
* * MMC
|
||||
*/
|
||||
gpio_output(10, 0);
|
||||
udelay(100);
|
||||
gpio_output(10, 1);
|
||||
}
|
||||
|
||||
struct chip_operations mainboard_ops = {
|
||||
.name = CONFIG_MAINBOARD_PART_NUMBER,
|
||||
.enable_dev = mainboard_enable,
|
||||
};
|
1
src/mainboard/cavium/cn8100_sff_evb/memlayout.ld
Normal file
1
src/mainboard/cavium/cn8100_sff_evb/memlayout.ld
Normal file
|
@ -0,0 +1 @@
|
|||
#include <soc/memlayout.ld>
|
45
src/mainboard/cavium/cn8100_sff_evb/romstage.c
Normal file
45
src/mainboard/cavium/cn8100_sff_evb/romstage.c
Normal file
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
* This file is part of the coreboot project.
|
||||
*
|
||||
* Copyright 2017-present Facebook, Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; version 2 of the License.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <arch/exception.h>
|
||||
#include <cbmem.h>
|
||||
#include <romstage_handoff.h>
|
||||
#include <soc/sdram.h>
|
||||
#include <soc/timer.h>
|
||||
#include <stdlib.h>
|
||||
#include <console/console.h>
|
||||
#include <program_loading.h>
|
||||
#include <libbdk-hal/bdk-config.h>
|
||||
#include <string.h>
|
||||
|
||||
extern const struct bdk_devicetree_key_value devtree[];
|
||||
|
||||
void main(void)
|
||||
{
|
||||
watchdog_poke(0);
|
||||
|
||||
console_init();
|
||||
exception_init();
|
||||
|
||||
bdk_config_set_fdt(devtree);
|
||||
|
||||
sdram_init();
|
||||
|
||||
watchdog_poke(0);
|
||||
|
||||
cbmem_initialize_empty();
|
||||
run_ramstage();
|
||||
}
|
282
src/mainboard/cavium/cn8100_sff_evb/sff8104-linux.dts
Normal file
282
src/mainboard/cavium/cn8100_sff_evb/sff8104-linux.dts
Normal file
|
@ -0,0 +1,282 @@
|
|||
/*
|
||||
* Cavium Thunder DTS file - Thunder board description
|
||||
*
|
||||
* Copyright (C) 2016, Cavium Inc.
|
||||
*
|
||||
* This file is dual-licensed: you can use it either under the terms
|
||||
* of the GPL or the X11 license, at your option. Note that this dual
|
||||
* licensing only applies to this file, and not this project as a
|
||||
* whole.
|
||||
*
|
||||
* a) This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; version 2 of the License.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* Or, alternatively,
|
||||
*
|
||||
* b) Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation
|
||||
* files (the "Software"), to deal in the Software without
|
||||
* restriction, including without limitation the rights to use,
|
||||
* copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following
|
||||
* conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
/dts-v1/;
|
||||
|
||||
/include/ "cn81xx-linux.dtsi"
|
||||
|
||||
&mrml_bridge {
|
||||
mdio-nexus@1,3 {
|
||||
mdio0@87e005003800 {
|
||||
rgmii00: rgmii00 {
|
||||
reg = <0> ;
|
||||
compatible = "marvell,88e1510", "ethernet-phy-ieee802.3-c22";
|
||||
};
|
||||
|
||||
qsgmii00: qsgmii00 {
|
||||
qlm-mode = "0x000,qsgmii";
|
||||
reg = <0x10> ;
|
||||
compatible = "vitesse,vsc8574", "ethernet-phy-ieee802.3-c22";
|
||||
};
|
||||
qsgmii01: qsgmii01 {
|
||||
qlm-mode = "0x001,qsgmii";
|
||||
reg = <0x11> ;
|
||||
compatible = "vitesse,vsc8574", "ethernet-phy-ieee802.3-c22";
|
||||
};
|
||||
qsgmii02: qsgmii02 {
|
||||
qlm-mode = "0x002,qsgmii";
|
||||
reg = <0x12> ;
|
||||
compatible = "vitesse,vsc8574", "ethernet-phy-ieee802.3-c22";
|
||||
};
|
||||
qsgmii03: qsgmii03 {
|
||||
qlm-mode = "0x003,qsgmii";
|
||||
reg = <0x13> ;
|
||||
compatible = "vitesse,vsc8574", "ethernet-phy-ieee802.3-c22";
|
||||
};
|
||||
};
|
||||
mdio1@87e005003880 {
|
||||
xfi00: xfi00 {
|
||||
qlm-mode = "0x000,xfi";
|
||||
reg = <0x0>;
|
||||
compatible = "aquantia,aqr105", "ethernet-phy-ieee802.3-c45";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
rgx0 {
|
||||
rgmii00 {
|
||||
reg = <0>;
|
||||
local-mac-address = [00 00 00 00 00 00];
|
||||
phy-handle = <&rgmii00>;
|
||||
};
|
||||
};
|
||||
|
||||
bgx0 {
|
||||
/* typename+qlm+typenumber eg :
|
||||
qsgmii+bgx0+sgmmi0
|
||||
*/
|
||||
qsgmii00 {
|
||||
reg = <0>;
|
||||
qlm-mode = "0x000,qsgmii";
|
||||
local-mac-address = [00 00 00 00 00 00];
|
||||
phy-handle = <&qsgmii00>;
|
||||
};
|
||||
qsgmii01 {
|
||||
reg = <1>;
|
||||
qlm-mode = "0x001,qsgmii";
|
||||
local-mac-address = [00 00 00 00 00 00];
|
||||
phy-handle = <&qsgmii01>;
|
||||
};
|
||||
qsgmii02 {
|
||||
reg = <2>;
|
||||
qlm-mode = "0x002,qsgmii";
|
||||
local-mac-address = [00 00 00 00 00 00];
|
||||
phy-handle = <&qsgmii02>;
|
||||
};
|
||||
qsgmii03 {
|
||||
reg = <3>;
|
||||
qlm-mode = "0x003,qsgmii";
|
||||
local-mac-address = [00 00 00 00 00 00];
|
||||
phy-handle = <&qsgmii03>;
|
||||
};
|
||||
|
||||
xfi00 {
|
||||
reg = <0>;
|
||||
qlm-mode = "0x000,xfi";
|
||||
local-mac-address = [00 00 00 00 00 00];
|
||||
phy-handle = <&xfi00>;
|
||||
};
|
||||
};
|
||||
|
||||
bgx1 {
|
||||
xfi10 {
|
||||
reg = <0>;
|
||||
qlm-mode = "0x010,xfi";
|
||||
local-mac-address = [00 00 00 00 00 00];
|
||||
};
|
||||
|
||||
xfi11 {
|
||||
reg = <1>;
|
||||
qlm-mode = "0x011,xfi";
|
||||
local-mac-address = [00 00 00 00 00 00];
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
};
|
||||
|
||||
&mmc_1_4 {
|
||||
/* NOTE: the BDK is responsible for swapping the two slots.
|
||||
* Unfortunately there does not appear to be any way to read the
|
||||
* position of SW2-7 in software.
|
||||
*/
|
||||
mmc-slot@0 {
|
||||
compatible = "mmc-slot";
|
||||
reg = <0>;
|
||||
vmmc-supply = <&mmc_supply_3v3>;
|
||||
max-frequency = <26000000>;
|
||||
/* 1.8v is not supported */
|
||||
no-1-8-v;
|
||||
/* Bus width is only 4 bits maximum */
|
||||
bus-width = <4>;
|
||||
/* No write-protect switch is present */
|
||||
disable-wp;
|
||||
/* There is no card detection available; polling must be used. */
|
||||
broken-cd;
|
||||
/* High-speed mode is supported */
|
||||
cap-sd-highspeed;
|
||||
/* speed up device probing */
|
||||
no-sdio;
|
||||
no-mmc;
|
||||
};
|
||||
mmc-slot@1 {
|
||||
compatible = "mmc-slot";
|
||||
reg = <1>;
|
||||
vmmc-supply = <&mmc_supply_3v3>;
|
||||
max-frequency = <26000000>;
|
||||
mmc-ddr-3_3v;
|
||||
/* 1.8v is not supported */
|
||||
no-1-8-v;
|
||||
/* Bus width is only 8 bits maximum */
|
||||
bus-width = <8>;
|
||||
/* No write-protect switch is present */
|
||||
disable-wp;
|
||||
/* There is no card detection available; polling must be used. */
|
||||
broken-cd;
|
||||
/* High-speed mode is supported */
|
||||
cap-mmc-highspeed;
|
||||
/* eMMC device is soldered onto the board */
|
||||
non-removable;
|
||||
/* speed up device probing */
|
||||
no-sdio;
|
||||
no-sd;
|
||||
};
|
||||
};
|
||||
|
||||
&i2c_9_0 {
|
||||
/* another pca9535 at 0x20 is only visible via jtag */
|
||||
gpio1: gpio-i2c@21 {
|
||||
compatible = "nxp,pca9535";
|
||||
gpio-controller;
|
||||
reg = <0x21>;
|
||||
gpio_base = <48>;
|
||||
pins = <48 16>;
|
||||
ngpios = <16>; // standard
|
||||
n_gpios = <16>; // deprecated, driver required
|
||||
#gpio-cells = <2>;
|
||||
};
|
||||
|
||||
gpio2: gpio-i2c@22 {
|
||||
compatible = "nxp,pca9535";
|
||||
gpio-controller;
|
||||
reg = <0x22>;
|
||||
gpio_base = <64>;
|
||||
pins = <64 16>;
|
||||
ngpios = <16>; // standard
|
||||
n_gpios = <16>; // deprecated, driver required
|
||||
#gpio-cells = <2>;
|
||||
};
|
||||
|
||||
mux@70 {
|
||||
compatible = "nxp,pca9546";
|
||||
reg = <0x70>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
i2c@0 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
reg = <0>;
|
||||
};
|
||||
|
||||
i2c@1 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
reg = <1>;
|
||||
};
|
||||
|
||||
i2c@2 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
reg = <2>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
&i2c_9_1 {
|
||||
rom@54 {
|
||||
compatible = "atmel,24c256";
|
||||
reg = <0x54>;
|
||||
pagesize = <64>;
|
||||
};
|
||||
|
||||
rtc@68 {
|
||||
compatible = "isil,isl12057";
|
||||
reg = <0x68>;
|
||||
};
|
||||
};
|
||||
|
||||
&spi_7_0 {
|
||||
flash@0 {
|
||||
compatible = "micron,n25q128a13", "spi-flash", "jedec,spi-nor";
|
||||
reg = <0x0>;
|
||||
spi-max-frequency = <16000000>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
};
|
||||
flash@1 {
|
||||
compatible = "spinand,mt29f", "mt29f";
|
||||
reg = <0x1>;
|
||||
spi-max-frequency = <50000000>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
nand-ecc-mode = "none";
|
||||
};
|
||||
};
|
||||
|
||||
&nfc {
|
||||
nand@1 {
|
||||
reg = <0x1>;
|
||||
nand-ecc-mode = "none";
|
||||
};
|
||||
};
|
2
src/soc/cavium/Kconfig
Normal file
2
src/soc/cavium/Kconfig
Normal file
|
@ -0,0 +1,2 @@
|
|||
# Load all chipsets
|
||||
source "src/soc/cavium/*/Kconfig"
|
27
src/soc/cavium/cn81xx/Kconfig
Normal file
27
src/soc/cavium/cn81xx/Kconfig
Normal file
|
@ -0,0 +1,27 @@
|
|||
config SOC_CAVIUM_CN81XX
|
||||
bool
|
||||
default n
|
||||
select ARCH_BOOTBLOCK_ARMV8_64
|
||||
select ARCH_RAMSTAGE_ARMV8_64
|
||||
select ARCH_ROMSTAGE_ARMV8_64
|
||||
select ARCH_VERSTAGE_ARMV8_64
|
||||
select BOOTBLOCK_CONSOLE
|
||||
select DRIVERS_UART_PL011
|
||||
select GENERIC_UDELAY
|
||||
select HAVE_MONOTONIC_TIMER
|
||||
select UART_OVERRIDE_REFCLK
|
||||
select SOC_CAVIUM_COMMON
|
||||
|
||||
if SOC_CAVIUM_CN81XX
|
||||
|
||||
config ARCH_ARMV8_EXTENSION
|
||||
int
|
||||
default 1
|
||||
|
||||
config HEAP_SIZE
|
||||
default 0x10000
|
||||
|
||||
config STACK_SIZE
|
||||
default 0x2000
|
||||
|
||||
endif
|
70
src/soc/cavium/cn81xx/Makefile.inc
Normal file
70
src/soc/cavium/cn81xx/Makefile.inc
Normal file
|
@ -0,0 +1,70 @@
|
|||
##
|
||||
## This file is part of the coreboot project.
|
||||
##
|
||||
## Copyright 2017-present Facebook, Inc.
|
||||
##
|
||||
## This program is free software; you can redistribute it and/or modify
|
||||
## it under the terms of the GNU General Public License as published by
|
||||
## the Free Software Foundation; version 2 of the License.
|
||||
##
|
||||
## This program is distributed in the hope that it will be useful,
|
||||
## but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
## GNU General Public License for more details.
|
||||
##
|
||||
|
||||
ifeq ($(CONFIG_SOC_CAVIUM_CN81XX),y)
|
||||
|
||||
# bootblock
|
||||
bootblock-$(CONFIG_BOOTBLOCK_CUSTOM) += bootblock_custom.S
|
||||
bootblock-y += bootblock.c
|
||||
bootblock-y += twsi.c
|
||||
bootblock-y += clock.c
|
||||
bootblock-y += gpio.c
|
||||
bootblock-y += timer.c
|
||||
bootblock-y += spi.c
|
||||
bootblock-y += uart.c
|
||||
bootblock-y += cpu.c
|
||||
ifeq ($(CONFIG_BOOTBLOCK_CONSOLE),y)
|
||||
bootblock-$(CONFIG_DRIVERS_UART) += uart.c
|
||||
endif
|
||||
|
||||
################################################################################
|
||||
# romstage
|
||||
|
||||
romstage-y += twsi.c
|
||||
romstage-y += clock.c
|
||||
romstage-y += gpio.c
|
||||
romstage-y += timer.c
|
||||
romstage-y += spi.c
|
||||
romstage-y += uart.c
|
||||
romstage-$(CONFIG_DRIVERS_UART) += uart.c
|
||||
romstage-< += cpu.c
|
||||
|
||||
romstage-y += sdram.c
|
||||
romstage-y += ../common/cbmem.c
|
||||
# BDK coreboot interface
|
||||
romstage-y += ../common/bdk-coreboot.c
|
||||
|
||||
|
||||
################################################################################
|
||||
# ramstage
|
||||
|
||||
ramstage-y += twsi.c
|
||||
ramstage-y += clock.c
|
||||
ramstage-y += gpio.c
|
||||
ramstage-y += timer.c
|
||||
ramstage-y += spi.c
|
||||
ramstage-y += uart.c
|
||||
ramstage-$(CONFIG_DRIVERS_UART) += uart.c
|
||||
ramstage-y += sdram.c
|
||||
ramstage-y += soc.c
|
||||
ramstage-y += cpu.c
|
||||
|
||||
# BDK coreboot interface
|
||||
ramstage-y += ../common/bdk-coreboot.c
|
||||
|
||||
|
||||
CPPFLAGS_common += -Isrc/soc/cavium/cn81xx/include
|
||||
|
||||
endif
|
50
src/soc/cavium/cn81xx/bootblock.c
Normal file
50
src/soc/cavium/cn81xx/bootblock.c
Normal file
|
@ -0,0 +1,50 @@
|
|||
/*
|
||||
* This file is part of the coreboot project.
|
||||
*
|
||||
* Copyright 2018 Facebook, Inc.
|
||||
* Copyright 2003-2017 Cavium Inc. <support@cavium.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; version 2 of the License.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* Derived from Cavium's BSD-3 Clause OCTEONTX-SDK-6.2.0.
|
||||
*/
|
||||
|
||||
#include <arch/io.h>
|
||||
#include <commonlib/helpers.h>
|
||||
#include <soc/bootblock.h>
|
||||
#include <soc/sysreg.h>
|
||||
#include <soc/timer.h>
|
||||
#include <libbdk-arch/bdk-asm.h>
|
||||
|
||||
static void init_sysreg(void)
|
||||
{
|
||||
/* The defaults for write buffer timeouts are poor */
|
||||
u64 cvmmemctl0;
|
||||
BDK_MRS(s3_0_c11_c0_4, cvmmemctl0);
|
||||
cvmmemctl0 |= AP_CVMMEMCTL0_EL1_WBFTONSHENA |
|
||||
AP_CVMMEMCTL0_EL1_WBFTOMRGCLRENA;
|
||||
BDK_MSR(s3_0_c11_c0_4, cvmmemctl0);
|
||||
}
|
||||
|
||||
void bootblock_soc_early_init(void)
|
||||
{
|
||||
}
|
||||
|
||||
void bootblock_soc_init(void)
|
||||
{
|
||||
/* initialize system registers */
|
||||
init_sysreg();
|
||||
|
||||
/* Set watchdog to 5 seconds timeout */
|
||||
watchdog_set(0, 5000);
|
||||
watchdog_poke(0);
|
||||
|
||||
/* TODO: additional clock init? */
|
||||
}
|
257
src/soc/cavium/cn81xx/bootblock_custom.S
Normal file
257
src/soc/cavium/cn81xx/bootblock_custom.S
Normal file
|
@ -0,0 +1,257 @@
|
|||
/*
|
||||
* Early initialization code for aarch64 (a.k.a. armv8)
|
||||
*
|
||||
* Copyright 2016 Cavium, Inc. <support@cavium.com>
|
||||
* Copyright 2018-present Facebook, Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; version 2 of
|
||||
* the License.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#include <arch/asm.h>
|
||||
#include <soc/addressmap.h>
|
||||
|
||||
ENTRY(_start)
|
||||
.org 0
|
||||
/**
|
||||
* According to the reference manual the first instruction is fetched from
|
||||
* offset 0x100, but at offset 0 a branch instruction is always placed.
|
||||
* Support two entry points for now.
|
||||
* To save memory put the cavium specific init code between those to entry
|
||||
* points.
|
||||
*/
|
||||
ic ialluis
|
||||
fmov d30, x0 /* Save X0 in FPR for use later */
|
||||
fmov d31, x1 /* Save X1 in FPR for use later */
|
||||
adr x1, _start /* x1 = _start location based on PC */
|
||||
fmov d29, x1 /* Save PC in FPR for use later */
|
||||
|
||||
#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
|
||||
/* Change the core to big endian mode for EL3 */
|
||||
mrs x0, SCTLR_EL3
|
||||
mov x1, 1<<25 /* Set SCTLR_EL3[ee]=1 */
|
||||
orr x0, x0, x1
|
||||
msr SCTLR_EL3, x0
|
||||
#define ENDIAN_CONVERT64(reg) rev reg, reg
|
||||
#define ENDIAN_CONVERT32(reg) rev reg, reg
|
||||
#define ENDIAN_CONVERT16(reg) rev16 reg, reg
|
||||
#elif __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
|
||||
/* Nothing needed, default is little endian */
|
||||
#define ENDIAN_CONVERT64(reg)
|
||||
#define ENDIAN_CONVERT32(reg)
|
||||
#define ENDIAN_CONVERT16(reg)
|
||||
#else
|
||||
#error Unknown endianness
|
||||
#endif
|
||||
|
||||
mov x0, (LMC0_PF_BAR0 >> 32)
|
||||
lsl x0, x0, 32
|
||||
mov x1, (LMC0_PF_BAR0 & 0xffffffff)
|
||||
orr x0, x0, x1
|
||||
|
||||
/* Test if DRAM PLL is running */
|
||||
ldr x1, [x0, LMC0_DDR_PLL_CTL0]
|
||||
|
||||
tst x1, 0x80
|
||||
|
||||
b.ne cache_setup_done
|
||||
|
||||
bl _setup_car
|
||||
|
||||
cache_setup_done:
|
||||
|
||||
/* Check that we're running on the node we're linked for */
|
||||
mrs x0, MPIDR_EL1
|
||||
ubfx x0, x0, 16, 8 /* Bits 23:16 are the physical node ID */
|
||||
mov x1, 0x0
|
||||
cmp x0, x1
|
||||
|
||||
b.ne _wfi
|
||||
|
||||
node_check_done:
|
||||
/* Get code position */
|
||||
mov x1, 0x020000
|
||||
mov x0, BOOTROM_OFFSET
|
||||
add x1, x0, x1
|
||||
|
||||
adr x0, _start
|
||||
|
||||
/**
|
||||
* Check if IROM has loaded the code to CONFIG_BOOTROM_OFFSET.
|
||||
* In case the offset is wrong, try to relocate.
|
||||
* Ideally the following code is never executed.
|
||||
* FIXME: Add region overlap check.
|
||||
*/
|
||||
cmp x0, x1
|
||||
b.eq after_relocate
|
||||
|
||||
relocate:
|
||||
/* Get bootblock length */
|
||||
ldr x2, =_program
|
||||
ldr x3, =_eprogram
|
||||
sub x2, x2, x3
|
||||
b copy_code
|
||||
|
||||
.align 7
|
||||
copy_code:
|
||||
ldp q0, q1, [x1], 32 /* Load 32 bytes */
|
||||
subs w2, w2, 32 /* Subtract 32 from length, setting flags */
|
||||
stp q0, q1, [x0], 32 /* Store 32 bytes */
|
||||
b.gt copy_code /* Repeat if length is still positive */
|
||||
dmb sy
|
||||
|
||||
/* Load the actual location we're suppose to be at */
|
||||
adr x0, after_relocate /* Relative address */
|
||||
adr x1, _start /* Relative address */
|
||||
sub x0, x0, x1 /* This only works if _start is suppose to be zero */
|
||||
mov x1, BOOTROM_OFFSET
|
||||
add x0, x0, x1
|
||||
br x0 /* Branch to relocated code */
|
||||
|
||||
ic ialluis /* Clear the icache now that all code is correct */
|
||||
|
||||
after_relocate:
|
||||
/* Allow unaligned memory access as long as MMU is disabled */
|
||||
mrs x22, s3_0_c11_c0_4
|
||||
orr x22, x22, # (1 << 37) /* Set DCVA47 */
|
||||
msr s3_0_c11_c0_4, x22
|
||||
|
||||
bl start
|
||||
|
||||
/* Real entry point */
|
||||
.org 0x100
|
||||
b _start
|
||||
ENDPROC(_start)
|
||||
|
||||
|
||||
ENTRY(_setup_car)
|
||||
mrs x0, MIDR_EL1
|
||||
ubfx x0, x0, 4, 12 /* Bits 15:4 are the part number */
|
||||
cmp x0, 0xb0
|
||||
b.ge _wfi
|
||||
|
||||
thunder1_cache_setup:
|
||||
/**
|
||||
* Setup L2 cache to allow secure access to all of the address space
|
||||
* thunder1 compability list:
|
||||
* - CN81XX
|
||||
* - CN83XX
|
||||
* - CN88XX
|
||||
*/
|
||||
#define REGIONX_START 0x1000
|
||||
#define REGIONX_END 0x1008
|
||||
#define REGIONX_ATTR 0x1010
|
||||
mov x0, L2C_PF_BAR0 >> 32
|
||||
lsl x0, x0, 32
|
||||
mov x1, (L2C_PF_BAR0 & 0xffffffff)
|
||||
orr x0, x0, x1
|
||||
str xzr, [x0, REGIONX_START] /* Start of zero */
|
||||
mov x1, 0x3fffff00000 /* End of max address */
|
||||
ENDIAN_CONVERT64(x1)
|
||||
str x1, [x0, REGIONX_END]
|
||||
mov x1, 2 /* Secure only access */
|
||||
ENDIAN_CONVERT64(x1)
|
||||
str x1, [x0, REGIONX_ATTR]
|
||||
/* Update way partition to allow core 0 to write to L2 */
|
||||
#define L2C_WPAR_PP0_OFFSET 0x40000
|
||||
mov x1, L2C_WPAR_PP0_OFFSET
|
||||
str xzr, [x0, x1]
|
||||
ldr xzr, [x0, x1] /* Read back to make sure done */
|
||||
#undef REGIONX_START
|
||||
#undef REGIONX_END
|
||||
#undef REGIONX_ATTR
|
||||
#undef L2C_WPAR_PP0_OFFSET
|
||||
|
||||
/**
|
||||
* At this point the whole CAR is readable and writeable, but if
|
||||
* we touch to many cache-lines our code might get flushed out.
|
||||
* We have to lock all cache-lines that are to be used as RAM, which are
|
||||
* the ones marked as SRAM in memlayout.
|
||||
*/
|
||||
mrs x0, CTR_EL0 /* Get cache-line size */
|
||||
/* [19:16] - Indicates (Log2(number of words in cache line) */
|
||||
ubfx x0, x0, 16, 4
|
||||
mov x1, 4 /* Bytes in a word (32-bit) */
|
||||
lsl x0, x1, x0 /* Number of Bytes in x0 */
|
||||
|
||||
sub x1, x0, 1
|
||||
mvn x1, x1 /* Place mask in x1 */
|
||||
|
||||
ldr x3, =_sram
|
||||
and x3, x3, x1 /* Align addresses with cache-lines */
|
||||
ldr x4, =_esram
|
||||
add x4, x4, x0
|
||||
sub x4, x4, 1
|
||||
and x4, x4, x1 /* Align addresses with cache-lines */
|
||||
sub x2, x4, x3 /* Store sram length in x2 */
|
||||
|
||||
lock_cache_lines:
|
||||
sys #0, c11, c1, #4, x3
|
||||
add x3, x3, x0 /* Increment address by cache-line bytes */
|
||||
subs w2, w2, w0 /* Subtract cache-line bytes from length */
|
||||
b.gt lock_cache_lines /* Repeat if length is still positive */
|
||||
|
||||
/**
|
||||
* The locked region isn't considered dirty by L2. Do read/write of
|
||||
* each cache line to force each to be dirty. This is needed across the
|
||||
* whole line to make sure the L2 dirty bits are all up to date.
|
||||
* NOTE: If we'd relocate we could memset the whole memory !
|
||||
*/
|
||||
ldr x3, =_sram
|
||||
and x3, x3, x1 /* Align addresses with cache-lines */
|
||||
ldr x4, =_esram
|
||||
add x4, x4, x0
|
||||
sub x4, x4, 1
|
||||
and x4, x4, x1 /* Align addresses with cache-lines */
|
||||
sub x2, x4, x3 /* Store sram length in x2 */
|
||||
mov x4, x3
|
||||
b dirty_cache_line
|
||||
|
||||
.align 7
|
||||
dirty_cache_line:
|
||||
ldp q0, q1, [x3], 32 /* Load 32 bytes */
|
||||
subs w2, w2, 32 /* Subtract 32 from length, setting flags */
|
||||
stp q0, q1, [x4], 32 /* Store 32 bytes */
|
||||
b.gt dirty_cache_line /* Repeat if length is still positive */
|
||||
dmb sy
|
||||
|
||||
clear_interrupts:
|
||||
/**
|
||||
* As the memory controller isn't running, but we access the DRAM's
|
||||
* address space, some interrupt flags had been set.
|
||||
* Tidy up our mess now on (valid for CN81XX only).
|
||||
*/
|
||||
mov x0, (L2C_TAD0_INT_W1C >> 32)
|
||||
lsl x0, x0, 32
|
||||
mov x1, (L2C_TAD0_INT_W1C & 0xffffffff)
|
||||
orr x0, x0, x1
|
||||
|
||||
ldr x1, [x0]
|
||||
orr x1, x1, 0x1c00 /* Clear WRDISLMC, RDDISLMC, RDNXM */
|
||||
str x1, [x0]
|
||||
|
||||
ret
|
||||
ENDPROC(_setup_car)
|
||||
|
||||
ENTRY(_wfi)
|
||||
wfi
|
||||
ENDPROC(_wfi)
|
||||
|
||||
ENTRY(start)
|
||||
bl arm64_init_cpu
|
||||
|
||||
fmov x0, d30 /* The original X0, info from previous image */
|
||||
fmov x1, d31 /* The original X1, info from previous image */
|
||||
fmov x2, d29 /* The original PC we were loaded at */
|
||||
|
||||
/* Call C entry */
|
||||
bl bootblock_main
|
||||
|
||||
ENDPROC(start)
|
22
src/soc/cavium/cn81xx/chip.h
Normal file
22
src/soc/cavium/cn81xx/chip.h
Normal file
|
@ -0,0 +1,22 @@
|
|||
/*
|
||||
* This file is part of the coreboot project.
|
||||
*
|
||||
* Copyright 2018-present Facebook, Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; version 2 of the License.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#ifndef __SOC_CAVIUM_CN81XX_CHIP_H
|
||||
#define __SOC_CAVIUM_CN81XX_CHIP_H
|
||||
|
||||
struct soc_cavium_cn81xx_config {
|
||||
};
|
||||
|
||||
#endif /* __SOC_CAVIUM_CN81XX_CHIP_H */
|
79
src/soc/cavium/cn81xx/clock.c
Normal file
79
src/soc/cavium/cn81xx/clock.c
Normal file
|
@ -0,0 +1,79 @@
|
|||
/*
|
||||
* This file is part of the coreboot project.
|
||||
*
|
||||
* Copyright 2018 Facebook, Inc.
|
||||
* Copyright 2003-2017 Cavium Inc. <support@cavium.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; version 2 of the License.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
#include <soc/clock.h>
|
||||
#include <arch/io.h>
|
||||
#include <soc/addressmap.h>
|
||||
|
||||
#define PLL_REF_CLK 50000000 /* 50 MHz */
|
||||
|
||||
union cavm_rst_boot {
|
||||
u64 u;
|
||||
struct {
|
||||
u64 rboot_pin:1;
|
||||
u64 rboot:1;
|
||||
u64 lboot:10;
|
||||
u64 lboot_ext23:6;
|
||||
u64 lboot_ext45:6;
|
||||
u64 reserved_24_29:6;
|
||||
u64 lboot_oci:3;
|
||||
u64 pnr_mul:6;
|
||||
u64 reserved_39_39:1;
|
||||
u64 c_mul:7;
|
||||
u64 reserved_47_54:8;
|
||||
u64 dis_scan:1;
|
||||
u64 dis_huk:1;
|
||||
u64 vrm_err:1;
|
||||
u64 jt_tstmode:1;
|
||||
u64 ckill_ppdis:1;
|
||||
u64 trusted_mode:1;
|
||||
u64 ejtagdis:1;
|
||||
u64 jtcsrdis:1;
|
||||
u64 chipkill:1;
|
||||
} s;
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the reference clock speed in Hz
|
||||
*/
|
||||
u64 thunderx_get_ref_clock(void)
|
||||
{
|
||||
return PLL_REF_CLK;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the I/O clock speed in Hz
|
||||
*/
|
||||
u64 thunderx_get_io_clock(void)
|
||||
{
|
||||
union cavm_rst_boot rst_boot;
|
||||
|
||||
rst_boot.u = read64((void *)RST_PF_BAR0);
|
||||
|
||||
return rst_boot.s.pnr_mul * PLL_REF_CLK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the core clock speed in Hz
|
||||
*/
|
||||
u64 thunderx_get_core_clock(void)
|
||||
{
|
||||
union cavm_rst_boot rst_boot;
|
||||
|
||||
rst_boot.u = read64((void *)RST_PF_BAR0);
|
||||
|
||||
return rst_boot.s.c_mul * PLL_REF_CLK;
|
||||
}
|
26
src/soc/cavium/cn81xx/cpu.c
Normal file
26
src/soc/cavium/cn81xx/cpu.c
Normal file
|
@ -0,0 +1,26 @@
|
|||
/*
|
||||
* This file is part of the coreboot project.
|
||||
*
|
||||
* Copyright 2018-present Facebook, Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; version 2 of the License.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#include <types.h>
|
||||
#include <arch/io.h>
|
||||
#include <soc/cpu.h>
|
||||
#include <bdk-coreboot.h>
|
||||
|
||||
/* Return the number of cores available in the chip */
|
||||
size_t cpu_get_num_cores(void)
|
||||
{
|
||||
uint64_t available = read64((void *)0x87e006001738ll);
|
||||
return bdk_dpop(available);
|
||||
}
|
193
src/soc/cavium/cn81xx/gpio.c
Normal file
193
src/soc/cavium/cn81xx/gpio.c
Normal file
|
@ -0,0 +1,193 @@
|
|||
/*
|
||||
* This file is part of the coreboot project.
|
||||
*
|
||||
* Copyright 2018 Facebook, Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; version 2 of the License.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#include <console/console.h>
|
||||
#include <soc/gpio.h>
|
||||
#include <arch/io.h>
|
||||
#include <endian.h>
|
||||
#include <soc/addressmap.h>
|
||||
|
||||
union gpio_const {
|
||||
u64 u;
|
||||
struct {
|
||||
u64 gpios:8; /** Number of GPIOs implemented */
|
||||
u64 pp:8; /** Number of PP vectors */
|
||||
u64:48; /* Reserved */
|
||||
} s;
|
||||
};
|
||||
union bit_cfg {
|
||||
u64 u;
|
||||
struct {
|
||||
u64 tx_oe : 1; /* Output Enable */
|
||||
u64 xor : 1; /* Invert */
|
||||
u64 int_en : 1; /* Interrupt Enable */
|
||||
u64 int_type : 1; /* Type of Interrupt */
|
||||
u64 filt_cnt : 4; /* Glitch filter counter */
|
||||
u64 filt_sel : 4; /* Glitch filter select */
|
||||
u64 tx_od : 1; /* Set Output to Open Drain */
|
||||
u64 : 3;
|
||||
u64 pin_sel : 10; /* Select type of pin */
|
||||
u64 : 38;
|
||||
} s;
|
||||
};
|
||||
|
||||
struct cavium_gpio {
|
||||
u64 rx_dat;
|
||||
u64 tx_set;
|
||||
u64 tx_clr;
|
||||
u64 multicast;
|
||||
u64 ocla_exten_trg;
|
||||
u64 strap;
|
||||
u64 reserved[12];
|
||||
union gpio_const gpio_const; /* Offset 90 */
|
||||
u64 reserved2[109];
|
||||
union bit_cfg bit_cfg[48]; /* Offset 400 */
|
||||
};
|
||||
|
||||
/* Base address of GPIO BAR */
|
||||
static const void *gpio_get_baseaddr(void)
|
||||
{
|
||||
return (const void *)GPIO_PF_BAR0;
|
||||
}
|
||||
|
||||
/* Number of GPIO pins. Usually 48. */
|
||||
gpio_t gpio_pin_count(void)
|
||||
{
|
||||
struct cavium_gpio *regs = (struct cavium_gpio *)gpio_get_baseaddr();
|
||||
union gpio_const gpio_const;
|
||||
|
||||
gpio_const.u = read64(®s->gpio_const.u);
|
||||
|
||||
if (gpio_const.s.gpios > 64)
|
||||
return 64; // FIXME: Add support for more than 64 GPIOs
|
||||
return gpio_const.s.gpios;
|
||||
}
|
||||
|
||||
/* Set GPIO to software control and direction INPUT */
|
||||
void gpio_input(gpio_t gpio)
|
||||
{
|
||||
struct cavium_gpio *regs = (struct cavium_gpio *)gpio_get_baseaddr();
|
||||
union bit_cfg bit_cfg;
|
||||
|
||||
if (gpio >= gpio_pin_count())
|
||||
return;
|
||||
|
||||
printk(BIOS_SPEW, "GPIO(%u): direction input\n", gpio);
|
||||
|
||||
bit_cfg.u = read64(®s->bit_cfg[gpio]);
|
||||
bit_cfg.s.pin_sel = 0;
|
||||
bit_cfg.s.tx_oe = 0;
|
||||
write64(®s->bit_cfg[gpio], bit_cfg.u);
|
||||
}
|
||||
|
||||
/* Set GPIO of direction OUTPUT to level */
|
||||
void gpio_set(gpio_t gpio, int value)
|
||||
{
|
||||
struct cavium_gpio *regs = (struct cavium_gpio *)gpio_get_baseaddr();
|
||||
|
||||
if (gpio >= gpio_pin_count())
|
||||
return;
|
||||
|
||||
printk(BIOS_SPEW, "GPIO(%u): level: %u\n", gpio, !!value);
|
||||
|
||||
if (value)
|
||||
write64(®s->tx_set, 1 << gpio);
|
||||
else
|
||||
write64(®s->tx_clr, 1 << gpio);
|
||||
}
|
||||
|
||||
/* Set GPIO direction to OUTPUT with level */
|
||||
void gpio_output(gpio_t gpio, int value)
|
||||
{
|
||||
struct cavium_gpio *regs = (struct cavium_gpio *)gpio_get_baseaddr();
|
||||
union bit_cfg bit_cfg;
|
||||
|
||||
if (gpio >= gpio_pin_count())
|
||||
return;
|
||||
|
||||
gpio_set(gpio, value);
|
||||
|
||||
printk(BIOS_SPEW, "GPIO(%u): direction output with level: %u\n", gpio,
|
||||
!!value);
|
||||
|
||||
bit_cfg.u = read64(®s->bit_cfg[gpio]);
|
||||
bit_cfg.s.pin_sel = 0;
|
||||
bit_cfg.s.tx_oe = 1;
|
||||
write64(®s->bit_cfg[gpio], bit_cfg.u);
|
||||
}
|
||||
|
||||
/* Set GPIO invert flag, that affects INPUT and OUTPUT */
|
||||
void gpio_invert(gpio_t gpio, int value)
|
||||
{
|
||||
struct cavium_gpio *regs = (struct cavium_gpio *)gpio_get_baseaddr();
|
||||
union bit_cfg bit_cfg;
|
||||
|
||||
if (gpio >= gpio_pin_count())
|
||||
return;
|
||||
|
||||
bit_cfg.u = read64(®s->bit_cfg[gpio]);
|
||||
bit_cfg.s.xor = !!value;
|
||||
write64(®s->bit_cfg[gpio], bit_cfg.u);
|
||||
|
||||
printk(BIOS_SPEW, "GPIO(%u): invert: %s\n", gpio, value ? "ON" : "OFF");
|
||||
}
|
||||
|
||||
/* Read GPIO level with direction set to INPUT */
|
||||
int gpio_get(gpio_t gpio)
|
||||
{
|
||||
struct cavium_gpio *regs = (struct cavium_gpio *)gpio_get_baseaddr();
|
||||
|
||||
if (gpio >= gpio_pin_count())
|
||||
return 0;
|
||||
|
||||
const u64 reg = read64(®s->rx_dat);
|
||||
printk(BIOS_SPEW, "GPIO(%u): input: %u\n", gpio, !!(reg & (1 << gpio)));
|
||||
|
||||
return !!(reg & (1 << gpio));
|
||||
}
|
||||
|
||||
/* Read GPIO STRAP level sampled at cold boot */
|
||||
int gpio_strap_value(gpio_t gpio)
|
||||
{
|
||||
struct cavium_gpio *regs = (struct cavium_gpio *)gpio_get_baseaddr();
|
||||
|
||||
if (gpio >= gpio_pin_count())
|
||||
return 0;
|
||||
|
||||
const u64 reg = read64(®s->strap);
|
||||
printk(BIOS_SPEW, "GPIO(%u): strap: %u\n", gpio, !!(reg & (1 << gpio)));
|
||||
|
||||
return !!(reg & (1 << gpio));
|
||||
}
|
||||
|
||||
/* FIXME: Parse devicetree ? */
|
||||
void gpio_init(void)
|
||||
{
|
||||
const size_t pin_count = gpio_pin_count();
|
||||
|
||||
printk(BIOS_DEBUG, "GPIO: base address: %p, pin count: %zd\n",
|
||||
gpio_get_baseaddr(), pin_count);
|
||||
|
||||
if (!pin_count)
|
||||
return;
|
||||
}
|
||||
|
||||
void gpio_input_pulldown(gpio_t gpio)
|
||||
{
|
||||
}
|
||||
|
||||
void gpio_input_pullup(gpio_t gpio)
|
||||
{
|
||||
}
|
123
src/soc/cavium/cn81xx/include/soc/addressmap.h
Normal file
123
src/soc/cavium/cn81xx/include/soc/addressmap.h
Normal file
|
@ -0,0 +1,123 @@
|
|||
/*
|
||||
* This file is part of the coreboot project.
|
||||
*
|
||||
* Copyright 2017-present Facebook, Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; version 2 of the License.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#ifndef __SOC_CAVIUM_CN81XX_ADDRESSMAP_H__
|
||||
#define __SOC_CAVIUM_CN81XX_ADDRESSMAP_H__
|
||||
|
||||
#define MAX_DRAM_ADDRESS 0x2000000000ULL /* 128GB */
|
||||
|
||||
/* Physical addressed with bit 47 set indicate I/O memory space. */
|
||||
|
||||
/* ARM code entry vector */
|
||||
#define BOOTROM_OFFSET 0x100000
|
||||
|
||||
/* L2C */
|
||||
#define L2C_PF_BAR0 0x87E080800000ULL
|
||||
#define L2C_TAD0_PF_BAR0 (0x87E050000000ULL + 0x10000)
|
||||
#define L2C_TAD0_INT_W1C (0x87E050000000ULL + 0x40000)
|
||||
#define L2C_CBC0_PF_BAR0 0x87E058000000ULL
|
||||
#define L2C_MCI0_PF_BAR0 0x87E05C000000ULL
|
||||
|
||||
/* LMC */
|
||||
#define LMC0_PF_BAR0 0x87E088000000ULL
|
||||
#define LMC0_DDR_PLL_CTL0 0x258
|
||||
|
||||
/* OCLA */
|
||||
|
||||
/* IOB */
|
||||
#define IOBN0_PF_BAR0 0x87E0F0000000ULL
|
||||
#define MRML_PF_BAR0 0x87E0FC000000ULL
|
||||
|
||||
/* SMMU */
|
||||
#define SMMU_PF_BAR0 0x830000000000ULL
|
||||
|
||||
/* GTI */
|
||||
#define GTI_PF_BAR0 0x844000000000ULL
|
||||
|
||||
/* PCC */
|
||||
#define ECAM_PF_BAR2 0x848000000000ULL
|
||||
|
||||
/* CPT */
|
||||
/* SLI */
|
||||
|
||||
/* RST */
|
||||
#define RST_PF_BAR0 (0x87E006000000ULL + 0x1600)
|
||||
#define FUSF_PF_BAR0 0x87E004000000ULL
|
||||
#define MIO_FUS_PF_BAR0 0x87E003000000ULL
|
||||
#define MIO_BOOT_PF_BAR0 0x87E000000000ULL
|
||||
|
||||
/* PTP */
|
||||
#define MIO_PTP_PF_BAR0 0x807000000000ULL
|
||||
|
||||
/* GIC */
|
||||
/* NIC */
|
||||
/* LBK */
|
||||
|
||||
#define GTI_PF_BAR0 0x844000000000ULL
|
||||
|
||||
/* DAP */
|
||||
/* BCH */
|
||||
/* KEY */
|
||||
/* RNG */
|
||||
|
||||
#define GSER0_PF_BAR0 (0x87E090000000ULL + (0 << 24))
|
||||
#define GSER1_PF_BAR0 (0x87E090000000ULL + (1 << 24))
|
||||
#define GSER2_PF_BAR0 (0x87E090000000ULL + (2 << 24))
|
||||
#define GSER3_PF_BAR0 (0x87E090000000ULL + (3 << 24))
|
||||
#define GSERx_PF_BAR0(x) \
|
||||
((((x) == 0) || ((x) == 1) || ((x) == 2) || ((x) == 3)) ? \
|
||||
(0x87E090000000ULL + ((x) << 24)) : 0)
|
||||
|
||||
/* PEM */
|
||||
/* SATA */
|
||||
/* USB */
|
||||
|
||||
/* UAA */
|
||||
#define UAA0_PF_BAR0 (0x87E028000000ULL + (0 << 24))
|
||||
#define UAA1_PF_BAR0 (0x87E028000000ULL + (1 << 24))
|
||||
#define UAA2_PF_BAR0 (0x87E028000000ULL + (2 << 24))
|
||||
#define UAA3_PF_BAR0 (0x87E028000000ULL + (3 << 24))
|
||||
#define UAAx_PF_BAR0(x) \
|
||||
((((x) == 0) || ((x) == 1) || ((x) == 2) || ((x) == 3)) ? \
|
||||
(0x87E028000000ULL + ((x) << 24)) : 0)
|
||||
|
||||
|
||||
/* TWSI */
|
||||
#define MIO_TWS0_PF_BAR0 (0x87E0D0000000ULL + (0 << 24))
|
||||
#define MIO_TWS1_PF_BAR0 (0x87E0D0000000ULL + (1 << 24))
|
||||
#define MIO_TWSx_PF_BAR0(x) \
|
||||
((((x) == 0) || ((x) == 1)) ? (0x87E0D0000000ULL + ((x) << 24)) : 0)
|
||||
|
||||
/* GPIO */
|
||||
#define GPIO_PF_BAR0 0x803000000000ULL
|
||||
|
||||
/* SGPIO */
|
||||
#define SGP_PF_BAR0 0x803000000000ULL
|
||||
|
||||
/* SMI */
|
||||
|
||||
/* SPI */
|
||||
#define MPI_PF_BAR0 (0x804000000000ULL + 0x1000)
|
||||
|
||||
/* PCM */
|
||||
/* PBUS */
|
||||
/* NDF */
|
||||
/* EMM */
|
||||
|
||||
/* VRM */
|
||||
/* VRM BARs are spaced apart by 0x1000000 */
|
||||
#define VRM0_PF_BAR0 0x87E021000000ULL
|
||||
|
||||
#endif /* __SOC_CAVIUM_CN81XX_ADDRESSMAP_H__ */
|
26
src/soc/cavium/cn81xx/include/soc/clock.h
Normal file
26
src/soc/cavium/cn81xx/include/soc/clock.h
Normal file
|
@ -0,0 +1,26 @@
|
|||
/*
|
||||
* This file is part of the coreboot project.
|
||||
*
|
||||
* Copyright 2017-present Facebook, Inc.
|
||||
* Copyright 2003-2017 Cavium Inc. <support@cavium.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; version 2 of the License.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#ifndef SRC_SOC_CAVIUM_CN81XX_INCLUDE_CLOCK_H_
|
||||
#define SRC_SOC_CAVIUM_CN81XX_INCLUDE_CLOCK_H_
|
||||
|
||||
#include <types.h>
|
||||
|
||||
u64 thunderx_get_ref_clock(void);
|
||||
u64 thunderx_get_io_clock(void);
|
||||
u64 thunderx_get_core_clock(void);
|
||||
|
||||
#endif /* SRC_SOC_CAVIUM_CN81XX_INCLUDE_CLOCK_H_ */
|
22
src/soc/cavium/cn81xx/include/soc/cpu.h
Normal file
22
src/soc/cavium/cn81xx/include/soc/cpu.h
Normal file
|
@ -0,0 +1,22 @@
|
|||
/*
|
||||
* This file is part of the coreboot project.
|
||||
*
|
||||
* Copyright 2017-present Facebook, Inc.
|
||||
* Copyright 2003-2017 Cavium Inc. <support@cavium.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; version 2 of the License.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#ifndef __SOC_CAVIUM_CN81XX_CPU_H__
|
||||
#define __SOC_CAVIUM_CN81XX_CPU_H__
|
||||
|
||||
size_t cpu_get_num_cores(void);
|
||||
|
||||
#endif /* __SOC_CAVIUM_CN81XX_CPU_H__ */
|
34
src/soc/cavium/cn81xx/include/soc/gpio.h
Normal file
34
src/soc/cavium/cn81xx/include/soc/gpio.h
Normal file
|
@ -0,0 +1,34 @@
|
|||
/*
|
||||
* This file is part of the coreboot project.
|
||||
*
|
||||
* Copyright 2016 Rockchip Inc.
|
||||
* Copyright 2018-present Facebook, Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; version 2 of the License.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#ifndef __COREBOOT_SRC_SOC_CAVIUM_COMMON_INCLUDE_SOC_GPIO_H
|
||||
#define __COREBOOT_SRC_SOC_CAVIUM_COMMON_INCLUDE_SOC_GPIO_H
|
||||
|
||||
#include <types.h>
|
||||
|
||||
typedef u32 gpio_t;
|
||||
#include <gpio.h>
|
||||
|
||||
/* The following functions must be implemented by SoC/board code. */
|
||||
|
||||
|
||||
gpio_t gpio_pin_count(void);
|
||||
void gpio_invert(gpio_t gpio, int value);
|
||||
int gpio_strap_value(gpio_t gpio);
|
||||
|
||||
void gpio_init(void);
|
||||
|
||||
#endif
|
41
src/soc/cavium/cn81xx/include/soc/memlayout.ld
Normal file
41
src/soc/cavium/cn81xx/include/soc/memlayout.ld
Normal file
|
@ -0,0 +1,41 @@
|
|||
/*
|
||||
* This file is part of the coreboot project.
|
||||
*
|
||||
* Copyright 2016 Rockchip Inc.
|
||||
* Copyright 2017-present Facebook, Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; version 2 of the License.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#include <memlayout.h>
|
||||
#include <soc/addressmap.h>
|
||||
#include <arch/header.ld>
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
DRAM_START(0x00000000)
|
||||
/* FIXME: Place BL31 in first 1MiB */
|
||||
|
||||
/* bootblock-custom.S does setup CAR from SRAM_START to SRAM_END */
|
||||
SRAM_START(BOOTROM_OFFSET)
|
||||
STACK(BOOTROM_OFFSET, 16K)
|
||||
TIMESTAMP(BOOTROM_OFFSET + 0x4000, 4K)
|
||||
PRERAM_CBFS_CACHE(BOOTROM_OFFSET + 0x6000, 8K)
|
||||
PRERAM_CBMEM_CONSOLE(BOOTROM_OFFSET + 0x8000, 8K)
|
||||
|
||||
BOOTBLOCK(BOOTROM_OFFSET + 0x20000, 64K)
|
||||
ROMSTAGE(BOOTROM_OFFSET + 0x40000, 256K)
|
||||
SRAM_END(BOOTROM_OFFSET + 0x80000)
|
||||
TTB(BOOTROM_OFFSET + 0x80000, 128K)
|
||||
RAMSTAGE(BOOTROM_OFFSET + 0xa0000, 512K)
|
||||
|
||||
/* Leave some space for the payload */
|
||||
POSTRAM_CBFS_CACHE(0x2000000, 16M)
|
||||
}
|
25
src/soc/cavium/cn81xx/include/soc/sdram.h
Normal file
25
src/soc/cavium/cn81xx/include/soc/sdram.h
Normal file
|
@ -0,0 +1,25 @@
|
|||
/*
|
||||
* This file is part of the coreboot project.
|
||||
*
|
||||
* Copyright 2017-present Facebook, Inc.
|
||||
* Copyright 2003-2017 Cavium Inc. <support@cavium.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; version 2 of the License.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#ifndef __SOC_CAVIUM_CN81XX_SDRAM_H__
|
||||
#define __SOC_CAVIUM_CN81XX_SDRAM_H__
|
||||
|
||||
#include <types.h>
|
||||
|
||||
size_t sdram_size_mb(void);
|
||||
void sdram_init(void);
|
||||
|
||||
#endif /* !__SOC_CAVIUM_CN81XX_SDRAM_H__ */
|
43
src/soc/cavium/cn81xx/include/soc/soc.h
Normal file
43
src/soc/cavium/cn81xx/include/soc/soc.h
Normal file
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
* This file is part of the coreboot project.
|
||||
*
|
||||
* Copyright 2017-present Facebook, Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; version 2 of the License.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#ifndef __SOC_CAVIUM_CN81XX_INCLUDE_SOC_SOC_H
|
||||
#define __SOC_CAVIUM_CN81XX_INCLUDE_SOC_SOC_H
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <types.h>
|
||||
|
||||
/* MIO BOOT Registers */
|
||||
struct cn81xx_mio_boot {
|
||||
u8 rsvd0[0xb0];
|
||||
u64 thr;
|
||||
u8 rsvd1[0x8];
|
||||
u64 pin_defs;
|
||||
u8 rsvd2[0x8];
|
||||
u64 ap_jump;
|
||||
u64 rom_limit;
|
||||
u8 rsvd3[0x18];
|
||||
u64 bist_stat;
|
||||
};
|
||||
check_member(cn81xx_mio_boot, bist_stat, 0xf8);
|
||||
|
||||
/*
|
||||
* 0 = Board supplies 100MHz to DLM_REF_CLK
|
||||
* 1 = bOard supplies 50MHz to PLL_REFCLK
|
||||
* */
|
||||
#define MIO_BOOT_PIN_DEFS_UART0_RTS (1 << 16)
|
||||
#define MIO_BOOT_PIN_DEFS_UART1_RTS (1 << 17)
|
||||
|
||||
#endif /* ! __SOC_CAVIUM_CN81XX_INCLUDE_SOC_SOC_H */
|
40
src/soc/cavium/cn81xx/include/soc/spi.h
Normal file
40
src/soc/cavium/cn81xx/include/soc/spi.h
Normal file
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
* This file is part of the coreboot project.
|
||||
*
|
||||
* Copyright 2017-present Facebook, Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; version 2 of the License.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#ifndef __COREBOOT_SRC_SOC_CN81XX_INCLUDE_SOC_SPI_H
|
||||
#define __COREBOOT_SRC_SOC_CN81XX_INCLUDE_SOC_SPI_H
|
||||
|
||||
/* This driver serves as a CBFS media source. */
|
||||
#include <spi-generic.h>
|
||||
#include <stddef.h>
|
||||
|
||||
void spi_enable(const size_t bus);
|
||||
void spi_disable(const size_t bus);
|
||||
void spi_set_cs(const size_t bus,
|
||||
const size_t chip_select,
|
||||
const size_t assert_is_low);
|
||||
void spi_set_clock(const size_t bus,
|
||||
const size_t speed_hz,
|
||||
const size_t idle_low,
|
||||
const size_t idle_cycles);
|
||||
void spi_set_lsbmsb(const size_t bus, const size_t lsb_first);
|
||||
void spi_init_custom(const size_t bus,
|
||||
const size_t speed_hz,
|
||||
const size_t idle_low,
|
||||
const size_t idle_cycles,
|
||||
const size_t lsb_first,
|
||||
const size_t chip_select,
|
||||
const size_t assert_is_low);
|
||||
#endif /* ! __COREBOOT_SRC_SOC_CN81XX_INCLUDE_SOC_SPI_H */
|
30
src/soc/cavium/cn81xx/include/soc/timer.h
Normal file
30
src/soc/cavium/cn81xx/include/soc/timer.h
Normal file
|
@ -0,0 +1,30 @@
|
|||
/*
|
||||
* This file is part of the coreboot project.
|
||||
*
|
||||
* Copyright 2017-present Facebook, Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; version 2 of the License.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#ifndef __SOC_CAVIUM_CN81XX_TIMER_H__
|
||||
#define __SOC_CAVIUM_CN81XX_TIMER_H__
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <types.h>
|
||||
#include <timer.h>
|
||||
#include <delay.h>
|
||||
|
||||
/* Watchdog functions */
|
||||
void watchdog_set(const size_t index, unsigned int timeout_ms);
|
||||
void watchdog_poke(const size_t index);
|
||||
void watchdog_disable(const size_t index);
|
||||
int watchdog_is_running(const size_t index);
|
||||
|
||||
#endif /* __SOC_CAVIUM_CN81XX_TIMER_H__ */
|
23
src/soc/cavium/cn81xx/include/soc/twsi.h
Normal file
23
src/soc/cavium/cn81xx/include/soc/twsi.h
Normal file
|
@ -0,0 +1,23 @@
|
|||
/*
|
||||
* This file is part of the coreboot project.
|
||||
*
|
||||
* Copyright 2017-present Facebook, Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; version 2 of the License.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
#include <types.h>
|
||||
#include <device/i2c.h>
|
||||
|
||||
#ifndef __SOC_CAVIUM_CN81XX_INCLUDE_SOC_TWSI_H
|
||||
#define __SOC_CAVIUM_CN81XX_INCLUDE_SOC_TWSI_H
|
||||
|
||||
int twsi_init(unsigned int bus, enum i2c_speed hz);
|
||||
|
||||
#endif
|
25
src/soc/cavium/cn81xx/include/soc/uart.h
Normal file
25
src/soc/cavium/cn81xx/include/soc/uart.h
Normal file
|
@ -0,0 +1,25 @@
|
|||
/*
|
||||
* This file is part of the coreboot project.
|
||||
*
|
||||
* Copyright 2017-present Facebook, Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; version 2 of the License.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#ifndef __SOC_CAVIUM_COMMON_INCLUDE_SOC_UART_H
|
||||
#define __SOC_CAVIUM_COMMON_INCLUDE_SOC_UART_H
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <types.h>
|
||||
|
||||
int uart_is_enabled(const size_t bus);
|
||||
int uart_setup(const size_t bus, int baudrate);
|
||||
|
||||
#endif /* __SOC_CAVIUM_COMMON_INCLUDE_SOC_UART_H */
|
94
src/soc/cavium/cn81xx/sdram.c
Normal file
94
src/soc/cavium/cn81xx/sdram.c
Normal file
|
@ -0,0 +1,94 @@
|
|||
/*
|
||||
* This file is part of the coreboot project.
|
||||
*
|
||||
* Copyright 2018 Facebook, Inc.
|
||||
* Copyright 2003-2017 Cavium Inc. <support@cavium.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; version 2 of the License.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* Derived from Cavium's BSD-3 Clause OCTEONTX-SDK-6.2.0.
|
||||
*/
|
||||
|
||||
#include <console/console.h>
|
||||
#include <soc/sdram.h>
|
||||
|
||||
#include <libbdk-arch/bdk-warn.h>
|
||||
#include <libbdk-arch/bdk-csrs-rst.h>
|
||||
#include <libbdk-boot/bdk-watchdog.h>
|
||||
#include <libbdk-dram/bdk-dram-config.h>
|
||||
#include <libbdk-dram/bdk-dram-test.h>
|
||||
#include <libbdk-hal/bdk-config.h>
|
||||
#include <libbdk-hal/bdk-utils.h>
|
||||
#include <libbdk-hal/bdk-l2c.h>
|
||||
#include <libdram/libdram-config.h>
|
||||
|
||||
size_t sdram_size_mb(void)
|
||||
{
|
||||
return bdk_dram_get_size_mbytes(0);
|
||||
}
|
||||
|
||||
/* based on bdk_boot_dram() */
|
||||
void sdram_init(void)
|
||||
{
|
||||
printk(BIOS_DEBUG, "Initializing DRAM\n");
|
||||
|
||||
/**
|
||||
* FIXME: second arg is actually a desired frequency if set (the
|
||||
* function usually obtains frequency via the config). That might
|
||||
* be useful if FDT or u-boot env is too cumbersome.
|
||||
*/
|
||||
int mbytes = bdk_dram_config(0, 0);
|
||||
if (mbytes < 0) {
|
||||
bdk_error("N0: Failed DRAM init\n");
|
||||
die("DRAM INIT FAILED !\n");
|
||||
}
|
||||
|
||||
/* Poke the watchdog */
|
||||
bdk_watchdog_poke();
|
||||
|
||||
/* Report DRAM status */
|
||||
printf("N0: DRAM:%s\n", bdk_dram_get_info_string(0));
|
||||
|
||||
/* See if we should test this node's DRAM during boot */
|
||||
int test_dram = bdk_config_get_int(BDK_CONFIG_DRAM_BOOT_TEST, 0);
|
||||
if (test_dram) {
|
||||
/* Run the address test to make sure DRAM works */
|
||||
if (bdk_dram_test(13, 0, 0x10000000000ull, BDK_DRAM_TEST_NO_STATS | (1<<0))) {
|
||||
/**
|
||||
* FIXME(dhendrix): This should be handled by mainboard code since we
|
||||
* don't necessarily have a BMC to report to. Also, we need to figure out
|
||||
* if we need to keep going as to avoid getting into a boot loop.
|
||||
*/
|
||||
// bdk_boot_status(BDK_BOOT_STATUS_REQUEST_POWER_CYCLE);
|
||||
printk(BIOS_ERR, "%s: Failed DRAM test.\n", __func__);
|
||||
}
|
||||
bdk_watchdog_poke();
|
||||
/* Put other node core back in reset */
|
||||
if (0 != bdk_numa_master())
|
||||
BDK_CSR_WRITE(0, BDK_RST_PP_RESET, -1);
|
||||
/* Clear DRAM */
|
||||
uint64_t skip = 0;
|
||||
if (0 == bdk_numa_master())
|
||||
skip = bdk_dram_get_top_of_bdk();
|
||||
void *base = bdk_phys_to_ptr(bdk_numa_get_address(0, skip));
|
||||
bdk_zero_memory(base, ((uint64_t)mbytes << 20) - skip);
|
||||
bdk_watchdog_poke();
|
||||
}
|
||||
|
||||
/* Unlock L2 now that DRAM works */
|
||||
if (0 == bdk_numa_master()) {
|
||||
uint64_t l2_size = bdk_l2c_get_cache_size_bytes(0);
|
||||
BDK_TRACE(INIT, "Unlocking L2\n");
|
||||
bdk_l2c_unlock_mem_region(0, 0, l2_size);
|
||||
bdk_watchdog_poke();
|
||||
}
|
||||
|
||||
printk(BIOS_INFO, "SDRAM initialization finished.\n");
|
||||
}
|
65
src/soc/cavium/cn81xx/soc.c
Normal file
65
src/soc/cavium/cn81xx/soc.c
Normal file
|
@ -0,0 +1,65 @@
|
|||
/*
|
||||
* This file is part of the coreboot project.
|
||||
*
|
||||
* Copyright 2018 Facebook, Inc.
|
||||
* Copyright 2003-2017 Cavium Inc. <support@cavium.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; version 2 of the License.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* Derived from Cavium's BSD-3 Clause OCTEONTX-SDK-6.2.0.
|
||||
*/
|
||||
|
||||
#include <bootmode.h>
|
||||
#include <console/console.h>
|
||||
#include <cpu/cpu.h>
|
||||
#include <device/device.h>
|
||||
#include <soc/addressmap.h>
|
||||
#include <soc/clock.h>
|
||||
#include <soc/sdram.h>
|
||||
#include <soc/timer.h>
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <symbols.h>
|
||||
#include <libbdk-boot/bdk-boot.h>
|
||||
|
||||
static void soc_read_resources(device_t dev)
|
||||
{
|
||||
ram_resource(dev, 0, (uintptr_t)_dram / KiB, sdram_size_mb() * KiB);
|
||||
}
|
||||
|
||||
static void soc_init(device_t dev)
|
||||
{
|
||||
/* Init ECAM, MDIO, PEM, PHY, QLM ... */
|
||||
bdk_boot();
|
||||
|
||||
/* TODO: additional trustzone init */
|
||||
}
|
||||
|
||||
static void soc_final(device_t dev)
|
||||
{
|
||||
watchdog_disable(0);
|
||||
}
|
||||
|
||||
static struct device_operations soc_ops = {
|
||||
.read_resources = soc_read_resources,
|
||||
.init = soc_init,
|
||||
.final = soc_final,
|
||||
};
|
||||
|
||||
static void enable_soc_dev(device_t dev)
|
||||
{
|
||||
dev->ops = &soc_ops;
|
||||
}
|
||||
|
||||
struct chip_operations soc_cavium_cn81xx_ops = {
|
||||
CHIP_NAME("SOC Cavium CN81XX")
|
||||
.enable_dev = enable_soc_dev,
|
||||
};
|
401
src/soc/cavium/cn81xx/spi.c
Normal file
401
src/soc/cavium/cn81xx/spi.c
Normal file
|
@ -0,0 +1,401 @@
|
|||
/*
|
||||
* This file is part of the coreboot project.
|
||||
*
|
||||
* Copyright 2018 Facebook, Inc.
|
||||
* Copyright 2003-2017 Cavium Inc. <support@cavium.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; version 2 of the License.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* Derived from Cavium's BSD-3 Clause OCTEONTX-SDK-6.2.0.
|
||||
*/
|
||||
|
||||
#include <arch/io.h>
|
||||
#include <assert.h>
|
||||
#include <console/console.h>
|
||||
#include <delay.h>
|
||||
#include <endian.h>
|
||||
#include <soc/addressmap.h>
|
||||
#include <soc/spi.h>
|
||||
#include <soc/clock.h>
|
||||
#include <spi-generic.h>
|
||||
#include <spi_flash.h>
|
||||
#include <stdlib.h>
|
||||
#include <timer.h>
|
||||
|
||||
union cavium_spi_cfg {
|
||||
u64 u;
|
||||
struct {
|
||||
u64 enable : 1;
|
||||
u64 idlelow : 1;
|
||||
u64 clk_cont : 1;
|
||||
u64 wireor : 1;
|
||||
u64 lsbfirst : 1;
|
||||
u64 : 2;
|
||||
u64 cshi : 1;
|
||||
u64 idleclks : 2;
|
||||
u64 tristate : 1;
|
||||
u64 cslate : 1;
|
||||
u64 csena : 4; /* Must be one */
|
||||
u64 clkdiv : 13;
|
||||
u64 : 35;
|
||||
} s;
|
||||
};
|
||||
|
||||
union cavium_spi_sts {
|
||||
u64 u;
|
||||
struct {
|
||||
u64 busy : 1;
|
||||
u64 mpi_intr : 1;
|
||||
u64 : 6;
|
||||
u64 rxnum : 5;
|
||||
u64 : 51;
|
||||
} s;
|
||||
};
|
||||
|
||||
union cavium_spi_tx {
|
||||
u64 u;
|
||||
struct {
|
||||
u64 totnum : 5;
|
||||
u64 : 3;
|
||||
u64 txnum : 5;
|
||||
u64 : 3;
|
||||
u64 leavecs : 1;
|
||||
u64 : 3;
|
||||
u64 csid : 2;
|
||||
u64 : 42;
|
||||
} s;
|
||||
};
|
||||
|
||||
struct cavium_spi {
|
||||
union cavium_spi_cfg cfg;
|
||||
union cavium_spi_sts sts;
|
||||
union cavium_spi_tx tx;
|
||||
u64 rsvd1;
|
||||
u64 sts_w1s;
|
||||
u64 rsvd2;
|
||||
u64 int_ena_w1c;
|
||||
u64 int_ena_w1s;
|
||||
u64 wide_dat;
|
||||
u8 rsvd4[0x38];
|
||||
u64 dat[8];
|
||||
};
|
||||
|
||||
check_member(cavium_spi, cfg, 0);
|
||||
check_member(cavium_spi, sts, 0x8);
|
||||
check_member(cavium_spi, tx, 0x10);
|
||||
check_member(cavium_spi, dat[7], 0xb8);
|
||||
|
||||
struct cavium_spi_slave {
|
||||
struct cavium_spi *regs;
|
||||
int cs;
|
||||
};
|
||||
|
||||
#define SPI_TIMEOUT_US 5000
|
||||
|
||||
static struct cavium_spi_slave cavium_spi_slaves[] = {
|
||||
{
|
||||
.regs = (struct cavium_spi *)MPI_PF_BAR0,
|
||||
.cs = 0,
|
||||
},
|
||||
};
|
||||
|
||||
static struct cavium_spi_slave *to_cavium_spi(const struct spi_slave *slave)
|
||||
{
|
||||
assert(slave->bus < ARRAY_SIZE(cavium_spi_slaves));
|
||||
return &cavium_spi_slaves[slave->bus];
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable the SPI controller. Pins are driven.
|
||||
*
|
||||
* @param bus The SPI bus to operate on
|
||||
*/
|
||||
void spi_enable(const size_t bus)
|
||||
{
|
||||
union cavium_spi_cfg cfg;
|
||||
|
||||
assert(bus < ARRAY_SIZE(cavium_spi_slaves));
|
||||
if (bus >= ARRAY_SIZE(cavium_spi_slaves))
|
||||
return;
|
||||
|
||||
struct cavium_spi *regs = cavium_spi_slaves[bus].regs;
|
||||
|
||||
cfg.u = read64(®s->cfg);
|
||||
cfg.s.csena = 0xf;
|
||||
cfg.s.enable = 1;
|
||||
write64(®s->cfg, cfg.u);
|
||||
}
|
||||
|
||||
/**
|
||||
* Disable the SPI controller. Pins are tristated.
|
||||
*
|
||||
* @param bus The SPI bus to operate on
|
||||
*/
|
||||
void spi_disable(const size_t bus)
|
||||
{
|
||||
union cavium_spi_cfg cfg;
|
||||
|
||||
assert(bus < ARRAY_SIZE(cavium_spi_slaves));
|
||||
if (bus >= ARRAY_SIZE(cavium_spi_slaves))
|
||||
return;
|
||||
|
||||
struct cavium_spi *regs = cavium_spi_slaves[bus].regs;
|
||||
|
||||
cfg.u = read64(®s->cfg);
|
||||
cfg.s.csena = 0xf;
|
||||
cfg.s.enable = 0;
|
||||
write64(®s->cfg, cfg.u);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set SPI Chip select line and level if asserted.
|
||||
*
|
||||
* @param bus The SPI bus to operate on
|
||||
* @param chip_select The chip select pin to use (0 - 3)
|
||||
* @param assert_is_low CS pin state is low when asserted
|
||||
*/
|
||||
void spi_set_cs(const size_t bus,
|
||||
const size_t chip_select,
|
||||
const size_t assert_is_low)
|
||||
{
|
||||
union cavium_spi_cfg cfg;
|
||||
|
||||
assert(bus < ARRAY_SIZE(cavium_spi_slaves));
|
||||
if (bus >= ARRAY_SIZE(cavium_spi_slaves))
|
||||
return;
|
||||
|
||||
cavium_spi_slaves[bus].cs = chip_select & 0x3;
|
||||
struct cavium_spi *regs = cavium_spi_slaves[bus].regs;
|
||||
|
||||
cfg.u = read64(®s->cfg);
|
||||
cfg.s.csena = 0xf;
|
||||
cfg.s.cshi = !assert_is_low;
|
||||
write64(®s->cfg, cfg.u);
|
||||
|
||||
//FIXME: CS2/3: Change pin mux here
|
||||
}
|
||||
|
||||
/**
|
||||
* Set SPI clock frequency.
|
||||
*
|
||||
* @param bus The SPI bus to operate on
|
||||
* @param speed_hz The SPI frequency in Hz
|
||||
* @param idle_low The SPI clock idles low
|
||||
* @param idle_cycles Number of CLK cycles between two commands (0 - 3)
|
||||
|
||||
*/
|
||||
void spi_set_clock(const size_t bus,
|
||||
const size_t speed_hz,
|
||||
const size_t idle_low,
|
||||
const size_t idle_cycles)
|
||||
{
|
||||
union cavium_spi_cfg cfg;
|
||||
|
||||
assert(bus < ARRAY_SIZE(cavium_spi_slaves));
|
||||
if (bus >= ARRAY_SIZE(cavium_spi_slaves))
|
||||
return;
|
||||
|
||||
struct cavium_spi *regs = cavium_spi_slaves[bus].regs;
|
||||
const uint64_t sclk = thunderx_get_io_clock();
|
||||
|
||||
cfg.u = read64(®s->cfg);
|
||||
cfg.s.csena = 0xf;
|
||||
cfg.s.clk_cont = 0;
|
||||
cfg.s.idlelow = !!idle_low;
|
||||
cfg.s.idleclks = idle_cycles & 0x3;
|
||||
cfg.s.clkdiv = MIN(sclk / (2ULL * speed_hz), 0x1fff);
|
||||
write64(®s->cfg, cfg.u);
|
||||
|
||||
printk(BIOS_DEBUG, "SPI: set clock to %lld kHz\n",
|
||||
(sclk / (2ULL * cfg.s.clkdiv)) >> 10);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set SPI LSB/MSB first.
|
||||
*
|
||||
* @param bus The SPI bus to operate on
|
||||
* @param lsb_first The SPI operates LSB first
|
||||
*
|
||||
*/
|
||||
void spi_set_lsbmsb(const size_t bus, const size_t lsb_first)
|
||||
{
|
||||
union cavium_spi_cfg cfg;
|
||||
|
||||
assert(bus < ARRAY_SIZE(cavium_spi_slaves));
|
||||
if (bus >= ARRAY_SIZE(cavium_spi_slaves))
|
||||
return;
|
||||
|
||||
struct cavium_spi *regs = cavium_spi_slaves[bus].regs;
|
||||
|
||||
cfg.u = read64(®s->cfg);
|
||||
cfg.s.csena = 0xf;
|
||||
cfg.s.lsbfirst = !!lsb_first;
|
||||
write64(®s->cfg, cfg.u);
|
||||
}
|
||||
|
||||
/**
|
||||
* Init SPI with custom parameters and enable SPI controller.
|
||||
*
|
||||
* @param bus The SPI bus to operate on
|
||||
* @param speed_hz The SPI frequency in Hz
|
||||
* @param idle_low The SPI clock idles low
|
||||
* @param idle_cycles Number of CLK cycles between two commands (0 - 3)
|
||||
* @param lsb_first The SPI operates LSB first
|
||||
* @param chip_select The chip select pin to use (0 - 3)
|
||||
* @param assert_is_low CS pin state is low when asserted
|
||||
*/
|
||||
void spi_init_custom(const size_t bus,
|
||||
const size_t speed_hz,
|
||||
const size_t idle_low,
|
||||
const size_t idle_cycles,
|
||||
const size_t lsb_first,
|
||||
const size_t chip_select,
|
||||
const size_t assert_is_low)
|
||||
{
|
||||
spi_disable(bus);
|
||||
spi_set_clock(bus, speed_hz, idle_low, idle_cycles);
|
||||
spi_set_lsbmsb(bus, lsb_first);
|
||||
spi_set_cs(bus, chip_select, assert_is_low);
|
||||
spi_enable(bus);
|
||||
}
|
||||
|
||||
/**
|
||||
* Init all SPI controllers with default values and enable all SPI controller.
|
||||
*
|
||||
*/
|
||||
void spi_init(void)
|
||||
{
|
||||
for (size_t i = 0; i < ARRAY_SIZE(cavium_spi_slaves); i++) {
|
||||
spi_disable(i);
|
||||
spi_set_clock(i, 12500000, 0, 0);
|
||||
spi_set_lsbmsb(i, 0);
|
||||
spi_set_cs(i, 0, 1);
|
||||
spi_enable(i);
|
||||
}
|
||||
}
|
||||
|
||||
static int cavium_spi_wait(struct cavium_spi *regs)
|
||||
{
|
||||
struct stopwatch sw;
|
||||
union cavium_spi_sts sts;
|
||||
|
||||
stopwatch_init_usecs_expire(&sw, SPI_TIMEOUT_US);
|
||||
do {
|
||||
sts.u = read64(®s->sts);
|
||||
if (!sts.s.busy)
|
||||
return 0;
|
||||
} while (!stopwatch_expired(&sw));
|
||||
printk(BIOS_DEBUG, "SPI: Timed out after %uus\n", SPI_TIMEOUT_US);
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int do_xfer(const struct spi_slave *slave, struct spi_op *vector,
|
||||
int leavecs)
|
||||
{
|
||||
struct cavium_spi *regs = to_cavium_spi(slave)->regs;
|
||||
uint8_t *out_buf = (uint8_t *)vector->dout;
|
||||
size_t bytesout = vector->bytesout;
|
||||
uint8_t *in_buf = (uint8_t *)vector->din;
|
||||
size_t bytesin = vector->bytesin;
|
||||
union cavium_spi_sts sts;
|
||||
union cavium_spi_tx tx;
|
||||
|
||||
/**
|
||||
* The CN81xx SPI controller is half-duplex and has 8 data registers.
|
||||
* If >8 bytes remain in the transfer then we must set LEAVECS = 1 so
|
||||
* that the /CS remains asserted. Once <=8 bytes remain we must set
|
||||
* LEAVECS = 0 so that /CS is de-asserted, thus completing the transfer.
|
||||
*/
|
||||
while (bytesout) {
|
||||
size_t out_now = MIN(bytesout, 8);
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < out_now; i++)
|
||||
write64(®s->dat[i], out_buf[i] & 0xff);
|
||||
|
||||
tx.u = 0;
|
||||
tx.s.csid = to_cavium_spi(slave)->cs;
|
||||
if (leavecs || ((bytesout > 8) || bytesin))
|
||||
tx.s.leavecs = 1;
|
||||
/* number of bytes to transmit goes in both TXNUM and TOTNUM */
|
||||
tx.s.totnum = out_now;
|
||||
tx.s.txnum = out_now;
|
||||
write64(®s->tx, tx.u);
|
||||
|
||||
/* check status */
|
||||
if (cavium_spi_wait(regs) < 0)
|
||||
return -1;
|
||||
|
||||
bytesout -= out_now;
|
||||
out_buf += out_now;
|
||||
}
|
||||
|
||||
while (bytesin) {
|
||||
size_t in_now = MIN(bytesin, 8);
|
||||
unsigned int i;
|
||||
|
||||
tx.u = 0;
|
||||
tx.s.csid = to_cavium_spi(slave)->cs;
|
||||
if (leavecs || (bytesin > 8))
|
||||
tx.s.leavecs = 1;
|
||||
tx.s.totnum = in_now;
|
||||
write64(®s->tx, tx.u);
|
||||
|
||||
/* check status */
|
||||
if (cavium_spi_wait(regs) < 0)
|
||||
return -1;
|
||||
|
||||
sts.u = read64(®s->sts);
|
||||
if (sts.s.rxnum != in_now) {
|
||||
printk(BIOS_ERR,
|
||||
"SPI: Incorrect number of bytes received: %u.\n",
|
||||
sts.s.rxnum);
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (i = 0; i < in_now; i++) {
|
||||
*in_buf = (uint8_t)((read64(®s->dat[i]) & 0xff));
|
||||
in_buf++;
|
||||
}
|
||||
bytesin -= in_now;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int spi_ctrlr_xfer_vector(const struct spi_slave *slave,
|
||||
struct spi_op vectors[], size_t count)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
if (do_xfer(slave, &vectors[i], count - 1 == i ? 0 : 1)) {
|
||||
printk(BIOS_ERR,
|
||||
"SPI: Failed to transfer %zu vectors.\n", count);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
static const struct spi_ctrlr spi_ctrlr = {
|
||||
|
||||
.xfer_vector = spi_ctrlr_xfer_vector,
|
||||
.max_xfer_size = SPI_CTRLR_DEFAULT_MAX_XFER_SIZE,
|
||||
};
|
||||
|
||||
const struct spi_ctrlr_buses spi_ctrlr_bus_map[] = {
|
||||
{
|
||||
.ctrlr = &spi_ctrlr,
|
||||
.bus_start = 0,
|
||||
.bus_end = ARRAY_SIZE(cavium_spi_slaves) - 1,
|
||||
},
|
||||
};
|
||||
const size_t spi_ctrlr_bus_map_count = ARRAY_SIZE(spi_ctrlr_bus_map);
|
226
src/soc/cavium/cn81xx/timer.c
Normal file
226
src/soc/cavium/cn81xx/timer.c
Normal file
|
@ -0,0 +1,226 @@
|
|||
/*
|
||||
* This file is part of the coreboot project.
|
||||
*
|
||||
* Copyright 2018 Facebook, Inc.
|
||||
* Copyright 2003-2017 Cavium Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; version 2 of the License.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* Derived from Cavium's BSD-3 Clause OCTEONTX-SDK-6.2.0.
|
||||
*/
|
||||
|
||||
#include <arch/io.h>
|
||||
#include <console/console.h>
|
||||
#include <inttypes.h>
|
||||
#include <soc/clock.h>
|
||||
#include <soc/timer.h>
|
||||
#include <stdint.h>
|
||||
#include <timer.h>
|
||||
#include <soc/addressmap.h>
|
||||
#include <assert.h>
|
||||
|
||||
/* Global System Timers Unit (GTI) registers */
|
||||
struct cn81xx_timer {
|
||||
u32 cc_cntcr;
|
||||
u32 cc_cntsr;
|
||||
u64 cc_cntcv;
|
||||
u8 rsvd[0x10];
|
||||
u32 cc_cntfid0;
|
||||
u32 cc_cntfid1;
|
||||
u8 rsvd2[0x98];
|
||||
u32 cc_cntrate;
|
||||
u32 cc_cntracc;
|
||||
u64 cc_cntadd;
|
||||
u64 cc_cntmb;
|
||||
u64 cc_cntmbts;
|
||||
u64 cc_cntmb_int;
|
||||
u64 cc_cntmb_int_set;
|
||||
u64 cc_cntmb_int_ena_clr;
|
||||
u64 cc_cntmb_int_ena_set;
|
||||
u64 cc_imp_ctl;
|
||||
u8 skip[0x1fef8];
|
||||
u32 ctl_cntfrq;
|
||||
u32 ctl_cntnsar;
|
||||
u32 ctl_cnttidr;
|
||||
u8 rsvd3[0x34];
|
||||
u32 ctl_cntacr0;
|
||||
u8 skip2[0x1ffb8];
|
||||
u64 cwd_wdog[48]; /* Offset 0x40000 */
|
||||
u8 skip3[0xfe80];
|
||||
u64 cwd_poke[48]; /* Offset 0x50000 */
|
||||
};
|
||||
|
||||
check_member(cn81xx_timer, cc_imp_ctl, 0x100);
|
||||
check_member(cn81xx_timer, ctl_cntacr0, 0x20040);
|
||||
check_member(cn81xx_timer, cwd_wdog[0], 0x40000);
|
||||
check_member(cn81xx_timer, cwd_poke[0], 0x50000);
|
||||
|
||||
|
||||
#define GTI_CC_CNTCR_EN (1 << 0)
|
||||
#define GTI_CC_CNTCR_HDBG (1 << 1)
|
||||
#define GTI_CC_CNTCR_FCREQ (1 << 8)
|
||||
|
||||
#define GTI_CC_CNTSR_DBGH (1 << 1)
|
||||
#define GTI_CC_CNTSR_FCACK (1 << 8)
|
||||
|
||||
#define GTI_CWD_WDOG_MODE_SHIFT 0
|
||||
#define GTI_CWD_WDOG_MODE_MASK 0x3
|
||||
#define GTI_CWD_WDOG_STATE_SHIFT 2
|
||||
#define GTI_CWD_WDOG_STATE_MASK 0x3
|
||||
#define GTI_CWD_WDOG_LEN_SHIFT 4
|
||||
#define GTI_CWD_WDOG_LEN_MASK 0xffff
|
||||
#define GTI_CWD_WDOG_CNT_SHIFT 20
|
||||
#define GTI_CWD_WDOG_CNT_MASK 0xffffff
|
||||
#define GTI_CWD_WDOC_DSTOP (1 << 44)
|
||||
#define GTI_CWD_WDOC_GSTOP (1 << 45)
|
||||
|
||||
static uint64_t timer_raw_value(void)
|
||||
{
|
||||
struct cn81xx_timer *timer = (void *)GTI_PF_BAR0;
|
||||
|
||||
return read64(&timer->cc_cntcv);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get GTI counter value.
|
||||
* @param mt Structure to fill
|
||||
*/
|
||||
void timer_monotonic_get(struct mono_time *mt)
|
||||
{
|
||||
mono_time_set_usecs(mt, timer_raw_value());
|
||||
}
|
||||
|
||||
/**
|
||||
* Init Global System Timers Unit (GTI).
|
||||
* Configure timer to run at 1MHz tick-rate.
|
||||
*/
|
||||
void init_timer(void)
|
||||
{
|
||||
struct cn81xx_timer *gti = (struct cn81xx_timer *)GTI_PF_BAR0;
|
||||
|
||||
/* Check if the counter was already setup */
|
||||
if (gti->cc_cntcr & GTI_CC_CNTCR_EN)
|
||||
return;
|
||||
|
||||
u64 sclk = thunderx_get_io_clock();
|
||||
|
||||
/* Use coprocessor clock source */
|
||||
write32(>i->cc_imp_ctl, 0);
|
||||
|
||||
/* Setup counter to operate at 1MHz */
|
||||
const size_t tickrate = 1000000;
|
||||
write32(>i->cc_cntfid0, tickrate);
|
||||
write32(>i->ctl_cntfrq, tickrate);
|
||||
write32(>i->cc_cntrate, ((1ULL << 32) * tickrate) / sclk);
|
||||
|
||||
/* Enable the counter */
|
||||
setbits_le32(>i->cc_cntcr, GTI_CC_CNTCR_EN);
|
||||
|
||||
//u32 u = (CNTPS_CTL_EL1_IMASK | CNTPS_CTL_EL1_EN);
|
||||
//BDK_MSR(CNTPS_CTL_EL1, u);
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup the watchdog to expire in timeout_ms milliseconds. When the watchdog
|
||||
* expires, the chip three things happen:
|
||||
* 1) Expire 1: interrupt that is ignored by the BDK
|
||||
* 2) Expire 2: DEL3T interrupt, which is disabled and ignored
|
||||
* 3) Expire 3: Soft reset of the chip
|
||||
*
|
||||
* Since we want a soft reset, we actually program the watchdog to expire at
|
||||
* the timeout / 3.
|
||||
*
|
||||
* @param index Index of watchdog to configure
|
||||
* @param timeout_ms Timeout in milliseconds.
|
||||
*/
|
||||
void watchdog_set(const size_t index, unsigned int timeout_ms)
|
||||
{
|
||||
uint64_t sclk = thunderx_get_io_clock();
|
||||
uint64_t timeout_sclk = sclk * timeout_ms / 1000;
|
||||
struct cn81xx_timer *timer = (struct cn81xx_timer *)GTI_PF_BAR0;
|
||||
|
||||
assert(index < ARRAY_SIZE(timer->cwd_wdog));
|
||||
if (index >= ARRAY_SIZE(timer->cwd_wdog))
|
||||
return;
|
||||
|
||||
/*
|
||||
* Per comment above, we want the watchdog to expire at 3x the rate
|
||||
* specified
|
||||
*/
|
||||
timeout_sclk /= 3;
|
||||
/* Watchdog counts in 1024 cycle steps */
|
||||
uint64_t timeout_wdog = timeout_sclk >> 10;
|
||||
/* We can only specify the upper 16 bits of a 24 bit value. Round up */
|
||||
timeout_wdog = (timeout_wdog + 0xff) >> 8;
|
||||
/* If the timeout overflows the hardware limit, set max */
|
||||
if (timeout_wdog >= 0x10000)
|
||||
timeout_wdog = 0xffff;
|
||||
|
||||
printk(BIOS_DEBUG, "Watchdog: Set to expire %llu SCLK cycles\n",
|
||||
timeout_wdog << 18);
|
||||
clrsetbits_le64(&timer->cwd_wdog[index],
|
||||
(GTI_CWD_WDOG_LEN_MASK << GTI_CWD_WDOG_LEN_SHIFT) |
|
||||
(GTI_CWD_WDOG_MODE_MASK << GTI_CWD_WDOG_MODE_SHIFT),
|
||||
(timeout_wdog << GTI_CWD_WDOG_LEN_SHIFT) |
|
||||
(3 << GTI_CWD_WDOG_MODE_SHIFT));
|
||||
}
|
||||
|
||||
/**
|
||||
* Signal the watchdog that we are still running.
|
||||
*
|
||||
* @param index Index of watchdog to configure.
|
||||
*/
|
||||
void watchdog_poke(const size_t index)
|
||||
{
|
||||
struct cn81xx_timer *timer = (struct cn81xx_timer *)GTI_PF_BAR0;
|
||||
|
||||
assert(index < ARRAY_SIZE(timer->cwd_poke));
|
||||
if (index >= ARRAY_SIZE(timer->cwd_poke))
|
||||
return;
|
||||
|
||||
write64(&timer->cwd_poke[0], 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Disable the hardware watchdog
|
||||
*
|
||||
* @param index Index of watchdog to configure.
|
||||
*/
|
||||
void watchdog_disable(const size_t index)
|
||||
{
|
||||
struct cn81xx_timer *timer = (struct cn81xx_timer *)GTI_PF_BAR0;
|
||||
|
||||
assert(index < ARRAY_SIZE(timer->cwd_wdog));
|
||||
if (index >= ARRAY_SIZE(timer->cwd_wdog))
|
||||
return;
|
||||
|
||||
write64(&timer->cwd_wdog[index], 0);
|
||||
printk(BIOS_DEBUG, "Watchdog: Disabled\n");
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the watchdog is configured and running
|
||||
*
|
||||
* @param index Index of watchdog to configure.
|
||||
*
|
||||
* @return Non-zero if watchdog is running.
|
||||
*/
|
||||
int watchdog_is_running(const size_t index)
|
||||
{
|
||||
struct cn81xx_timer *timer = (struct cn81xx_timer *)GTI_PF_BAR0;
|
||||
|
||||
assert(index < ARRAY_SIZE(timer->cwd_wdog));
|
||||
if (index >= ARRAY_SIZE(timer->cwd_wdog))
|
||||
return 0;
|
||||
|
||||
uint64_t val = read64(&timer->cwd_wdog[index]);
|
||||
|
||||
return !!(val & (GTI_CWD_WDOG_MODE_MASK << GTI_CWD_WDOG_MODE_SHIFT));
|
||||
}
|
696
src/soc/cavium/cn81xx/twsi.c
Normal file
696
src/soc/cavium/cn81xx/twsi.c
Normal file
|
@ -0,0 +1,696 @@
|
|||
/*
|
||||
* This file is part of the coreboot project.
|
||||
*
|
||||
* Copyright 2018 Facebook, Inc.
|
||||
* Copyright 2003-2017 Cavium Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; version 2 of the License.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* Derived from Cavium's BSD-3 Clause OCTEONTX-SDK-6.2.0.
|
||||
*/
|
||||
#include <console/console.h>
|
||||
#include <soc/twsi.h>
|
||||
#include <soc/clock.h>
|
||||
#include <device/i2c.h>
|
||||
#include <device/i2c_simple.h>
|
||||
#include <assert.h>
|
||||
#include <delay.h>
|
||||
#include <arch/io.h>
|
||||
#include <soc/addressmap.h>
|
||||
|
||||
#define TWSI_THP 24
|
||||
|
||||
#define TWSI_SW_TWSI 0x1000
|
||||
#define TWSI_TWSI_SW 0x1008
|
||||
#define TWSI_INT 0x1010
|
||||
#define TWSI_SW_TWSI_EXT 0x1018
|
||||
|
||||
union twsx_sw_twsi {
|
||||
u64 u;
|
||||
struct {
|
||||
u64 data:32;
|
||||
u64 eop_ia:3;
|
||||
u64 ia:5;
|
||||
u64 addr:10;
|
||||
u64 scr:2;
|
||||
u64 size:3;
|
||||
u64 sovr:1;
|
||||
u64 r:1;
|
||||
u64 op:4;
|
||||
u64 eia:1;
|
||||
u64 slonly:1;
|
||||
u64 v:1;
|
||||
} s;
|
||||
};
|
||||
|
||||
union twsx_sw_twsi_ext {
|
||||
u64 u;
|
||||
struct {
|
||||
u64 data:32;
|
||||
u64 ia:8;
|
||||
u64 :24;
|
||||
} s;
|
||||
};
|
||||
|
||||
union twsx_int {
|
||||
u64 u;
|
||||
struct {
|
||||
u64 st_int:1; /** TWSX_SW_TWSI register update int */
|
||||
u64 ts_int:1; /** TWSX_TWSI_SW register update int */
|
||||
u64 core_int:1; /** TWSI core interrupt, ignored for HLC */
|
||||
u64 :5; /** Reserved */
|
||||
u64 sda_ovr:1; /** SDA testing override */
|
||||
u64 scl_ovr:1; /** SCL testing override */
|
||||
u64 sda:1; /** SDA signal */
|
||||
u64 scl:1; /** SCL signal */
|
||||
u64 :52; /** Reserved */
|
||||
} s;
|
||||
};
|
||||
|
||||
enum {
|
||||
TWSI_OP_WRITE = 0,
|
||||
TWSI_OP_READ = 1,
|
||||
};
|
||||
|
||||
enum {
|
||||
TWSI_EOP_SLAVE_ADDR = 0,
|
||||
TWSI_EOP_CLK_CTL = 3,
|
||||
TWSI_SW_EOP_IA = 6,
|
||||
};
|
||||
|
||||
enum {
|
||||
TWSI_SLAVEADD = 0,
|
||||
TWSI_DATA = 1,
|
||||
TWSI_CTL = 2,
|
||||
TWSI_CLKCTL = 3,
|
||||
TWSI_STAT = 3,
|
||||
TWSI_SLAVEADD_EXT = 4,
|
||||
TWSI_RST = 7,
|
||||
};
|
||||
|
||||
enum {
|
||||
TWSI_CTL_AAK = (1 << 2),
|
||||
TWSI_CTL_IFLG = (1 << 3),
|
||||
TWSI_CTL_STP = (1 << 4),
|
||||
TWSI_CTL_STA = (1 << 5),
|
||||
TWSI_CTL_ENAB = (1 << 6),
|
||||
TWSI_CTL_CE = (1 << 7),
|
||||
};
|
||||
|
||||
enum {
|
||||
/** Bus error */
|
||||
TWSI_STAT_BUS_ERROR = 0x00,
|
||||
/** Start condition transmitted */
|
||||
TWSI_STAT_START = 0x08,
|
||||
/** Repeat start condition transmitted */
|
||||
TWSI_STAT_RSTART = 0x10,
|
||||
/** Address + write bit transmitted, ACK received */
|
||||
TWSI_STAT_TXADDR_ACK = 0x18,
|
||||
/** Address + write bit transmitted, /ACK received */
|
||||
TWSI_STAT_TXADDR_NAK = 0x20,
|
||||
/** Data byte transmitted in master mode, ACK received */
|
||||
TWSI_STAT_TXDATA_ACK = 0x28,
|
||||
/** Data byte transmitted in master mode, ACK received */
|
||||
TWSI_STAT_TXDATA_NAK = 0x30,
|
||||
/** Arbitration lost in address or data byte */
|
||||
TWSI_STAT_TX_ARB_LOST = 0x38,
|
||||
/** Address + read bit transmitted, ACK received */
|
||||
TWSI_STAT_RXADDR_ACK = 0x40,
|
||||
/** Address + read bit transmitted, /ACK received */
|
||||
TWSI_STAT_RXADDR_NAK = 0x48,
|
||||
/** Data byte received in master mode, ACK transmitted */
|
||||
TWSI_STAT_RXDATA_ACK_SENT = 0x50,
|
||||
/** Data byte received, NACK transmitted */
|
||||
TWSI_STAT_RXDATA_NAK_SENT = 0x58,
|
||||
/** Slave address received, sent ACK */
|
||||
TWSI_STAT_SLAVE_RXADDR_ACK = 0x60,
|
||||
/**
|
||||
* Arbitration lost in address as master, slave address + write bit
|
||||
* received, ACK transmitted
|
||||
*/
|
||||
TWSI_STAT_TX_ACK_ARB_LOST = 0x68,
|
||||
/** General call address received, ACK transmitted */
|
||||
TWSI_STAT_RX_GEN_ADDR_ACK = 0x70,
|
||||
/**
|
||||
* Arbitration lost in address as master, general call address
|
||||
* received, ACK transmitted
|
||||
*/
|
||||
TWSI_STAT_RX_GEN_ADDR_ARB_LOST = 0x78,
|
||||
/** Data byte received after slave address received, ACK transmitted */
|
||||
TWSI_STAT_SLAVE_RXDATA_ACK = 0x80,
|
||||
/** Data byte received after slave address received, /ACK transmitted */
|
||||
TWSI_STAT_SLAVE_RXDATA_NAK = 0x88,
|
||||
/**
|
||||
* Data byte received after general call address received, ACK
|
||||
* transmitted
|
||||
*/
|
||||
TWSI_STAT_GEN_RXADDR_ACK = 0x90,
|
||||
/**
|
||||
* Data byte received after general call address received, /ACK
|
||||
* transmitted
|
||||
*/
|
||||
TWSI_STAT_GEN_RXADDR_NAK = 0x98,
|
||||
/** STOP or repeated START condition received in slave mode */
|
||||
TWSI_STAT_STOP_MULTI_START = 0xA0,
|
||||
/** Slave address + read bit received, ACK transmitted */
|
||||
TWSI_STAT_SLAVE_RXADDR2_ACK = 0xA8,
|
||||
/**
|
||||
* Arbitration lost in address as master, slave address + read bit
|
||||
* received, ACK transmitted
|
||||
*/
|
||||
TWSI_STAT_RXDATA_ACK_ARB_LOST = 0xB0,
|
||||
/** Data byte transmitted in slave mode, ACK received */
|
||||
TWSI_STAT_SLAVE_TXDATA_ACK = 0xB8,
|
||||
/** Data byte transmitted in slave mode, /ACK received */
|
||||
TWSI_STAT_SLAVE_TXDATA_NAK = 0xC0,
|
||||
/** Last byte transmitted in slave mode, ACK received */
|
||||
TWSI_STAT_SLAVE_TXDATA_END_ACK = 0xC8,
|
||||
/** Second address byte + write bit transmitted, ACK received */
|
||||
TWSI_STAT_TXADDR2DATA_ACK = 0xD0,
|
||||
/** Second address byte + write bit transmitted, /ACK received */
|
||||
TWSI_STAT_TXADDR2DATA_NAK = 0xD8,
|
||||
/** No relevant status information */
|
||||
TWSI_STAT_IDLE = 0xF8
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns true if we lost arbitration
|
||||
*
|
||||
* @param code status code
|
||||
* @param final_read true if this is the final read operation
|
||||
*
|
||||
* @return true if arbitration has been lost, false if it hasn't been lost.
|
||||
*/
|
||||
static int twsi_i2c_lost_arb(u8 code, int final_read)
|
||||
{
|
||||
switch (code) {
|
||||
/* Arbitration lost */
|
||||
case TWSI_STAT_TX_ARB_LOST:
|
||||
case TWSI_STAT_TX_ACK_ARB_LOST:
|
||||
case TWSI_STAT_RX_GEN_ADDR_ARB_LOST:
|
||||
case TWSI_STAT_RXDATA_ACK_ARB_LOST:
|
||||
return -1;
|
||||
|
||||
/* Being addressed as slave, should back off and listen */
|
||||
case TWSI_STAT_SLAVE_RXADDR_ACK:
|
||||
case TWSI_STAT_RX_GEN_ADDR_ACK:
|
||||
case TWSI_STAT_GEN_RXADDR_ACK:
|
||||
case TWSI_STAT_GEN_RXADDR_NAK:
|
||||
return -1;
|
||||
|
||||
/* Core busy as slave */
|
||||
case TWSI_STAT_SLAVE_RXDATA_ACK:
|
||||
case TWSI_STAT_SLAVE_RXDATA_NAK:
|
||||
case TWSI_STAT_STOP_MULTI_START:
|
||||
case TWSI_STAT_SLAVE_RXADDR2_ACK:
|
||||
case TWSI_STAT_SLAVE_TXDATA_ACK:
|
||||
case TWSI_STAT_SLAVE_TXDATA_NAK:
|
||||
case TWSI_STAT_SLAVE_TXDATA_END_ACK:
|
||||
return -1;
|
||||
|
||||
/* Ack allowed on pre-terminal bytes only */
|
||||
case TWSI_STAT_RXDATA_ACK_SENT:
|
||||
if (!final_read)
|
||||
return 0;
|
||||
return -1;
|
||||
|
||||
/* NAK allowed on terminal byte only */
|
||||
case TWSI_STAT_RXDATA_NAK_SENT:
|
||||
if (!final_read)
|
||||
return 0;
|
||||
return -1;
|
||||
|
||||
case TWSI_STAT_TXDATA_NAK:
|
||||
case TWSI_STAT_TXADDR_NAK:
|
||||
case TWSI_STAT_RXADDR_NAK:
|
||||
case TWSI_STAT_TXADDR2DATA_NAK:
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define RST_BOOT_PNR_MUL(Val) ((Val >> 33) & 0x1F)
|
||||
|
||||
/**
|
||||
* Writes to the MIO_TWS(0..5)_SW_TWSI register
|
||||
*
|
||||
* @param baseaddr Base address of i2c registers
|
||||
* @param sw_twsi value to write
|
||||
*
|
||||
* @return 0 for success, otherwise error
|
||||
*/
|
||||
static u64 twsi_write_sw(void *baseaddr, union twsx_sw_twsi sw_twsi)
|
||||
{
|
||||
unsigned long timeout = 500000;
|
||||
|
||||
sw_twsi.s.r = 0;
|
||||
sw_twsi.s.v = 1;
|
||||
|
||||
printk(BIOS_SPEW, "%s(%p, 0x%llx)\n", __func__, baseaddr, sw_twsi.u);
|
||||
write64(baseaddr + TWSI_SW_TWSI, sw_twsi.u);
|
||||
do {
|
||||
sw_twsi.u = read64(baseaddr + TWSI_SW_TWSI);
|
||||
timeout--;
|
||||
} while (sw_twsi.s.v != 0 && timeout > 0);
|
||||
|
||||
if (sw_twsi.s.v)
|
||||
printk(BIOS_ERR, "%s: timed out\n", __func__);
|
||||
return sw_twsi.u;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads the MIO_TWS(0..5)_SW_TWSI register
|
||||
*
|
||||
* @param baseaddr Base address of i2c registers
|
||||
* @param sw_twsi value for eia and op, etc. to read
|
||||
*
|
||||
* @return value of the register
|
||||
*/
|
||||
static u64 twsi_read_sw(void *baseaddr, union twsx_sw_twsi sw_twsi)
|
||||
{
|
||||
unsigned long timeout = 500000;
|
||||
sw_twsi.s.r = 1;
|
||||
sw_twsi.s.v = 1;
|
||||
|
||||
printk(BIOS_SPEW, "%s(%p, 0x%llx)\n", __func__, baseaddr, sw_twsi.u);
|
||||
write64(baseaddr + TWSI_SW_TWSI, sw_twsi.u);
|
||||
|
||||
do {
|
||||
sw_twsi.u = read64(baseaddr + TWSI_SW_TWSI);
|
||||
timeout--;
|
||||
} while (sw_twsi.s.v != 0 && timeout > 0);
|
||||
|
||||
if (sw_twsi.s.v)
|
||||
printk(BIOS_ERR, "%s: Error writing 0x%llx\n", __func__,
|
||||
sw_twsi.u);
|
||||
|
||||
printk(BIOS_SPEW, "%s: Returning 0x%llx\n", __func__, sw_twsi.u);
|
||||
return sw_twsi.u;
|
||||
}
|
||||
|
||||
/**
|
||||
* Write control register
|
||||
*
|
||||
* @param baseaddr Base address for i2c registers
|
||||
* @param data data to write
|
||||
*/
|
||||
static void twsi_write_ctl(void *baseaddr, const u8 data)
|
||||
{
|
||||
union twsx_sw_twsi twsi_sw;
|
||||
|
||||
printk(BIOS_SPEW, "%s(%p, 0x%x)\n", __func__, baseaddr, data);
|
||||
twsi_sw.u = 0;
|
||||
|
||||
twsi_sw.s.op = TWSI_SW_EOP_IA;
|
||||
twsi_sw.s.eop_ia = TWSI_CTL;
|
||||
twsi_sw.s.data = data;
|
||||
|
||||
twsi_write_sw(baseaddr, twsi_sw);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads the TWSI Control Register
|
||||
*
|
||||
* @param[in] baseaddr Base address for i2c
|
||||
*
|
||||
* @return 8-bit TWSI control register
|
||||
*/
|
||||
static u32 twsi_read_ctl(void *baseaddr)
|
||||
{
|
||||
union twsx_sw_twsi sw_twsi;
|
||||
|
||||
sw_twsi.u = 0;
|
||||
sw_twsi.s.op = TWSI_SW_EOP_IA;
|
||||
sw_twsi.s.eop_ia = TWSI_CTL;
|
||||
|
||||
sw_twsi.u = twsi_read_sw(baseaddr, sw_twsi);
|
||||
printk(BIOS_SPEW, "%s(%p): 0x%x\n", __func__, baseaddr, sw_twsi.s.data);
|
||||
return sw_twsi.s.data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read i2c status register
|
||||
*
|
||||
* @param baseaddr Base address of i2c registers
|
||||
*
|
||||
* @return value of status register
|
||||
*/
|
||||
static u8 twsi_read_status(void *baseaddr)
|
||||
{
|
||||
union twsx_sw_twsi twsi_sw;
|
||||
|
||||
twsi_sw.u = 0;
|
||||
twsi_sw.s.op = TWSI_SW_EOP_IA;
|
||||
twsi_sw.s.eop_ia = TWSI_STAT;
|
||||
|
||||
return twsi_read_sw(baseaddr, twsi_sw);
|
||||
}
|
||||
|
||||
/**
|
||||
* Waits for an i2c operation to complete
|
||||
*
|
||||
* @param baseaddr Base address of registers
|
||||
*
|
||||
* @return 0 for success, 1 if timeout
|
||||
*/
|
||||
static int twsi_wait(void *baseaddr)
|
||||
{
|
||||
unsigned long timeout = 500000;
|
||||
u8 twsi_ctl;
|
||||
|
||||
printk(BIOS_SPEW, "%s(%p)\n", __func__, baseaddr);
|
||||
do {
|
||||
twsi_ctl = twsi_read_ctl(baseaddr);
|
||||
twsi_ctl &= TWSI_CTL_IFLG;
|
||||
timeout--;
|
||||
} while (!twsi_ctl && timeout > 0);
|
||||
|
||||
printk(BIOS_SPEW, " return: %u\n", !twsi_ctl);
|
||||
return !twsi_ctl;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends an i2c stop condition
|
||||
*
|
||||
* @param baseaddr register base address
|
||||
*
|
||||
* @return 0 for success, -1 if error
|
||||
*/
|
||||
static int twsi_stop(void *baseaddr)
|
||||
{
|
||||
u8 stat;
|
||||
twsi_write_ctl(baseaddr, TWSI_CTL_STP | TWSI_CTL_ENAB);
|
||||
|
||||
stat = twsi_read_status(baseaddr);
|
||||
if (stat != TWSI_STAT_IDLE) {
|
||||
printk(BIOS_ERR, "%s: Bad status on bus@%p\n", __func__,
|
||||
baseaddr);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Manually clear the I2C bus and send a stop
|
||||
*/
|
||||
static void twsi_unblock(void *baseaddr)
|
||||
{
|
||||
int i;
|
||||
union twsx_int int_reg;
|
||||
|
||||
int_reg.u = 0;
|
||||
for (i = 0; i < 9; i++) {
|
||||
int_reg.s.scl_ovr = 0;
|
||||
write64(baseaddr + TWSI_INT, int_reg.u);
|
||||
udelay(5);
|
||||
int_reg.s.scl_ovr = 1;
|
||||
write64(baseaddr + TWSI_INT, int_reg.u);
|
||||
udelay(5);
|
||||
}
|
||||
int_reg.s.sda_ovr = 1;
|
||||
write64(baseaddr + TWSI_INT, int_reg.u);
|
||||
udelay(5);
|
||||
int_reg.s.scl_ovr = 0;
|
||||
write64(baseaddr + TWSI_INT, int_reg.u);
|
||||
udelay(5);
|
||||
int_reg.u = 0;
|
||||
write64(baseaddr + TWSI_INT, int_reg.u);
|
||||
udelay(5);
|
||||
}
|
||||
|
||||
/**
|
||||
* Unsticks the i2c bus
|
||||
*
|
||||
* @param baseaddr base address of registers
|
||||
*/
|
||||
static int twsi_start_unstick(void *baseaddr)
|
||||
{
|
||||
twsi_stop(baseaddr);
|
||||
|
||||
twsi_unblock(baseaddr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends an i2c start condition
|
||||
*
|
||||
* @param baseaddr base address of registers
|
||||
*
|
||||
* @return 0 for success, otherwise error
|
||||
*/
|
||||
static int twsi_start(void *baseaddr)
|
||||
{
|
||||
int result;
|
||||
u8 stat;
|
||||
|
||||
printk(BIOS_SPEW, "%s(%p)\n", __func__, baseaddr);
|
||||
twsi_write_ctl(baseaddr, TWSI_CTL_STA | TWSI_CTL_ENAB);
|
||||
result = twsi_wait(baseaddr);
|
||||
if (result) {
|
||||
stat = twsi_read_status(baseaddr);
|
||||
printk(BIOS_SPEW, "%s: result: 0x%x, status: 0x%x\n", __func__,
|
||||
result, stat);
|
||||
switch (stat) {
|
||||
case TWSI_STAT_START:
|
||||
case TWSI_STAT_RSTART:
|
||||
return 0;
|
||||
case TWSI_STAT_RXADDR_ACK:
|
||||
default:
|
||||
return twsi_start_unstick(baseaddr);
|
||||
}
|
||||
}
|
||||
printk(BIOS_SPEW, "%s: success\n", __func__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes data to the i2c bus
|
||||
*
|
||||
* @param baseraddr register base address
|
||||
* @param slave_addr address of slave to write to
|
||||
* @param buffer Pointer to buffer to write
|
||||
* @param length Number of bytes in buffer to write
|
||||
*
|
||||
* @return 0 for success, otherwise error
|
||||
*/
|
||||
static int twsi_write_data(void *baseaddr, const u8 slave_addr,
|
||||
const u8 *buffer, const unsigned int length)
|
||||
{
|
||||
union twsx_sw_twsi twsi_sw;
|
||||
unsigned int curr = 0;
|
||||
int result;
|
||||
|
||||
printk(BIOS_SPEW, "%s(%p, 0x%x, %p, 0x%x)\n", __func__, baseaddr,
|
||||
slave_addr, buffer, length);
|
||||
result = twsi_start(baseaddr);
|
||||
if (result) {
|
||||
printk(BIOS_ERR, "%s: Could not start BUS transaction\n",
|
||||
__func__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
result = twsi_wait(baseaddr);
|
||||
if (result) {
|
||||
printk(BIOS_ERR, "%s: wait failed\n", __func__);
|
||||
return result;
|
||||
}
|
||||
|
||||
twsi_sw.u = 0;
|
||||
twsi_sw.s.op = TWSI_SW_EOP_IA;
|
||||
twsi_sw.s.eop_ia = TWSI_DATA;
|
||||
twsi_sw.s.data = (u32) (slave_addr << 1) | TWSI_OP_WRITE;
|
||||
|
||||
twsi_write_sw(baseaddr, twsi_sw);
|
||||
twsi_write_ctl(baseaddr, TWSI_CTL_ENAB);
|
||||
|
||||
printk(BIOS_SPEW, "%s: Waiting\n", __func__);
|
||||
result = twsi_wait(baseaddr);
|
||||
if (result) {
|
||||
printk(BIOS_ERR, "%s: Timed out writing slave address 0x%x\n",
|
||||
__func__, slave_addr);
|
||||
return result;
|
||||
}
|
||||
result = twsi_read_status(baseaddr);
|
||||
if ((result = twsi_read_status(baseaddr)) != TWSI_STAT_TXADDR_ACK) {
|
||||
twsi_stop(baseaddr);
|
||||
return twsi_i2c_lost_arb(result, 0);
|
||||
}
|
||||
|
||||
while (curr < length) {
|
||||
twsi_sw.u = 0;
|
||||
twsi_sw.s.op = TWSI_SW_EOP_IA;
|
||||
twsi_sw.s.eop_ia = TWSI_DATA;
|
||||
twsi_sw.s.data = buffer[curr++];
|
||||
|
||||
twsi_write_sw(baseaddr, twsi_sw);
|
||||
twsi_write_ctl(baseaddr, TWSI_CTL_ENAB);
|
||||
|
||||
result = twsi_wait(baseaddr);
|
||||
if (result) {
|
||||
printk(BIOS_ERR, "%s: Timed out writing data to 0x%x\n",
|
||||
__func__, slave_addr);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
printk(BIOS_SPEW, "%s: Stopping\n", __func__);
|
||||
return twsi_stop(baseaddr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs a read transaction on the i2c bus
|
||||
*
|
||||
* @param baseaddr Base address of twsi registers
|
||||
* @param slave_addr i2c bus address to read from
|
||||
* @param buffer buffer to read into
|
||||
* @param length number of bytes to read
|
||||
*
|
||||
* @return 0 for success, otherwise error
|
||||
*/
|
||||
static int twsi_read_data(void *baseaddr, const u8 slave_addr,
|
||||
u8 *buffer, const unsigned int length)
|
||||
{
|
||||
union twsx_sw_twsi twsi_sw;
|
||||
unsigned int curr = 0;
|
||||
int result;
|
||||
|
||||
printk(BIOS_SPEW, "%s(%p, 0x%x, %p, %u)\n", __func__, baseaddr,
|
||||
slave_addr, buffer, length);
|
||||
result = twsi_start(baseaddr);
|
||||
if (result) {
|
||||
printk(BIOS_ERR, "%s: start failed\n", __func__);
|
||||
return result;
|
||||
}
|
||||
|
||||
result = twsi_wait(baseaddr);
|
||||
if (result) {
|
||||
printk(BIOS_ERR, "%s: wait failed\n", __func__);
|
||||
return result;
|
||||
}
|
||||
|
||||
twsi_sw.u = 0;
|
||||
|
||||
twsi_sw.s.op = TWSI_SW_EOP_IA;
|
||||
twsi_sw.s.eop_ia = TWSI_DATA;
|
||||
|
||||
twsi_sw.s.data = (u32) (slave_addr << 1) | TWSI_OP_READ;
|
||||
|
||||
twsi_write_sw(baseaddr, twsi_sw);
|
||||
twsi_write_ctl(baseaddr, TWSI_CTL_ENAB);
|
||||
|
||||
result = twsi_wait(baseaddr);
|
||||
if (result) {
|
||||
printk(BIOS_ERR, "%s: waiting for sending addr failed\n", __func__);
|
||||
return result;
|
||||
}
|
||||
|
||||
result = twsi_read_status(baseaddr);
|
||||
if (result != TWSI_STAT_RXADDR_ACK) {
|
||||
twsi_stop(baseaddr);
|
||||
return twsi_i2c_lost_arb(result, 0);
|
||||
}
|
||||
|
||||
while (curr < length) {
|
||||
twsi_write_ctl(baseaddr, TWSI_CTL_ENAB |
|
||||
((curr < length - 1) ? TWSI_CTL_AAK : 0));
|
||||
|
||||
result = twsi_wait(baseaddr);
|
||||
if (result) {
|
||||
printk(BIOS_ERR, "%s: waiting for data failed\n",
|
||||
__func__);
|
||||
return result;
|
||||
}
|
||||
|
||||
twsi_sw.u = twsi_read_sw(baseaddr, twsi_sw);
|
||||
buffer[curr++] = twsi_sw.s.data;
|
||||
}
|
||||
|
||||
twsi_stop(baseaddr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int twsi_set_speed(void *baseaddr, const unsigned int speed)
|
||||
{
|
||||
u64 io_clock_hz;
|
||||
int n_div;
|
||||
int m_div;
|
||||
union twsx_sw_twsi sw_twsi;
|
||||
|
||||
io_clock_hz = thunderx_get_io_clock();
|
||||
|
||||
/* Set the TWSI clock to a conservative TWSI_BUS_FREQ. Compute the
|
||||
* clocks M divider based on the SCLK.
|
||||
* TWSI freq = (core freq) / (20 x (M+1) x (thp+1) x 2^N)
|
||||
* M = ((core freq) / (20 x (TWSI freq) x (thp+1) x 2^N)) - 1
|
||||
*/
|
||||
for (n_div = 0; n_div < 8; n_div++) {
|
||||
m_div = io_clock_hz / (20 * speed * (TWSI_THP + 1));
|
||||
m_div /= 1 << n_div;
|
||||
m_div -= 1;
|
||||
if (m_div < 16)
|
||||
break;
|
||||
}
|
||||
if (m_div >= 16)
|
||||
return -1;
|
||||
|
||||
sw_twsi.u = 0;
|
||||
sw_twsi.s.v = 1;
|
||||
sw_twsi.s.op = 0x6; /* See EOP field */
|
||||
sw_twsi.s.r = 0; /* Select CLKCTL when R = 0 */
|
||||
sw_twsi.s.eop_ia = 3; /* R=0 selects CLKCTL, R=1 selects STAT */
|
||||
sw_twsi.s.data = ((m_div & 0xf) << 3) | ((n_div & 0x7) << 0);
|
||||
|
||||
twsi_write_sw(baseaddr, sw_twsi);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int twsi_init(unsigned int bus, enum i2c_speed hz)
|
||||
{
|
||||
void *baseaddr = (void *)MIO_TWSx_PF_BAR0(bus);
|
||||
if (!baseaddr)
|
||||
return -1;
|
||||
|
||||
if (twsi_set_speed(baseaddr, hz) < 0)
|
||||
return -1;
|
||||
|
||||
/* Enable TWSI, HLC disable, STOP, NAK */
|
||||
twsi_write_ctl(baseaddr, TWSI_CTL_ENAB);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int platform_i2c_transfer(unsigned bus, struct i2c_msg *segments,
|
||||
int seg_count)
|
||||
{
|
||||
int result;
|
||||
void *baseaddr = (void *)MIO_TWSx_PF_BAR0(bus);
|
||||
if (!baseaddr)
|
||||
return -1;
|
||||
|
||||
printk(BIOS_SPEW, "%s: %d messages\n", __func__, seg_count);
|
||||
for (; seg_count > 0; seg_count--, segments++) {
|
||||
if (segments->flags & I2C_M_RD) {
|
||||
result = twsi_read_data(baseaddr, segments->slave,
|
||||
segments->buf, segments->len);
|
||||
} else {
|
||||
result = twsi_write_data(baseaddr, segments->slave,
|
||||
segments->buf, segments->len);
|
||||
}
|
||||
if (result) {
|
||||
printk(BIOS_ERR, "%s: error transmitting data\n",
|
||||
__func__);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
265
src/soc/cavium/cn81xx/uart.c
Normal file
265
src/soc/cavium/cn81xx/uart.c
Normal file
|
@ -0,0 +1,265 @@
|
|||
/*
|
||||
* This file is part of the coreboot project.
|
||||
*
|
||||
* Copyright 2018 Facebook, Inc.
|
||||
* Copyright 2003-2017 Cavium Inc. <support@cavium.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; version 2 of the License.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* Derived from Cavium's BSD-3 Clause OCTEONTX-SDK-6.2.0.
|
||||
*/
|
||||
|
||||
#include <arch/io.h>
|
||||
#include <console/uart.h>
|
||||
#include <delay.h>
|
||||
#include <endian.h>
|
||||
#include <stdint.h>
|
||||
#include <soc/clock.h>
|
||||
#include <soc/uart.h>
|
||||
#include <assert.h>
|
||||
#include <soc/addressmap.h>
|
||||
#include <drivers/uart/pl011.h>
|
||||
|
||||
union cn81xx_uart_ctl {
|
||||
u64 u;
|
||||
struct {
|
||||
u64 uctl_rst : 1;
|
||||
u64 uaa_rst : 1;
|
||||
u64 : 2;
|
||||
u64 csclk_en : 1;
|
||||
u64 : 19;
|
||||
u64 h_clkdiv_sel : 3;
|
||||
u64 : 1;
|
||||
u64 h_clkdiv_rst : 1;
|
||||
u64 h_clk_byp_sel : 1;
|
||||
u64 h_clk_en : 1;
|
||||
u64 : 33;
|
||||
} s;
|
||||
};
|
||||
|
||||
struct cn81xx_uart {
|
||||
struct pl011_uart pl011;
|
||||
union cn81xx_uart_ctl uctl_ctl;
|
||||
u8 rsvd4[0x8];
|
||||
u64 uctl_spare0;
|
||||
u8 rsvd5[0xe0];
|
||||
u64 uctl_spare1;
|
||||
};
|
||||
|
||||
#define UART_IBRD_BAUD_DIVINT_SHIFT 0
|
||||
#define UART_IBRD_BAUD_DIVINT_MASK 0xffff
|
||||
|
||||
#define UART_FBRD_BAUD_DIVFRAC_SHIFT 0
|
||||
#define UART_FBRD_BAUD_DIVFRAC_MASK 0x3f
|
||||
|
||||
|
||||
check_member(cn81xx_uart, uctl_ctl, 0x1000);
|
||||
check_member(cn81xx_uart, uctl_spare1, 0x10f8);
|
||||
|
||||
#define UART_SCLK_DIV 3
|
||||
|
||||
/**
|
||||
* Returns the current UART HCLK divider
|
||||
*
|
||||
* @param reg The H_CLKDIV_SEL value
|
||||
* @return The HCLK divider
|
||||
*/
|
||||
static size_t uart_sclk_divisor(const size_t reg)
|
||||
{
|
||||
static const u8 div[] = {1, 2, 4, 6, 8, 16, 24, 32};
|
||||
|
||||
assert(reg < ARRAY_SIZE(div));
|
||||
|
||||
return div[reg];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the current UART HCLK
|
||||
*
|
||||
* @param uart The UART to operate on
|
||||
* @return The HCLK in Hz
|
||||
*/
|
||||
static size_t uart_hclk(struct cn81xx_uart *uart)
|
||||
{
|
||||
union cn81xx_uart_ctl ctl;
|
||||
const uint64_t sclk = thunderx_get_io_clock();
|
||||
|
||||
ctl.u = read64(&uart->uctl_ctl);
|
||||
return sclk / uart_sclk_divisor(ctl.s.h_clkdiv_sel);
|
||||
}
|
||||
|
||||
unsigned int uart_platform_refclk(void)
|
||||
{
|
||||
struct cn81xx_uart *uart =
|
||||
(struct cn81xx_uart *)CONFIG_CONSOLE_SERIAL_UART_ADDRESS;
|
||||
|
||||
if (!uart)
|
||||
return 0;
|
||||
|
||||
return uart_hclk(uart);
|
||||
}
|
||||
|
||||
uintptr_t uart_platform_base(int idx)
|
||||
{
|
||||
return CONFIG_CONSOLE_SERIAL_UART_ADDRESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Waits given count if HCLK cycles
|
||||
*
|
||||
* @param uart The UART to operate on
|
||||
* @param hclks The number of HCLK cycles to wait
|
||||
*/
|
||||
static void uart_wait_hclk(struct cn81xx_uart *uart, const size_t hclks)
|
||||
{
|
||||
const size_t hclk = uart_hclk(uart);
|
||||
const size_t delay = (hclks * 1000000ULL) / hclk;
|
||||
udelay(MAX(delay, 1));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the UART state.
|
||||
*
|
||||
* @param bus The UART to operate on
|
||||
* @return Boolean: True if UART is enabled
|
||||
*/
|
||||
int uart_is_enabled(const size_t bus)
|
||||
{
|
||||
struct cn81xx_uart *uart = (struct cn81xx_uart *)UAAx_PF_BAR0(bus);
|
||||
union cn81xx_uart_ctl ctl;
|
||||
|
||||
assert(uart);
|
||||
if (!uart)
|
||||
return 0;
|
||||
|
||||
ctl.u = read64(&uart->uctl_ctl);
|
||||
return !!ctl.s.csclk_en;
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup UART with desired BAUD rate in 8N1, no parity mode.
|
||||
*
|
||||
* @param bus The UART to operate on
|
||||
* @param baudrate baudrate to set up
|
||||
*
|
||||
* @return Boolean: True on error
|
||||
*/
|
||||
int uart_setup(const size_t bus, int baudrate)
|
||||
{
|
||||
union cn81xx_uart_ctl ctl;
|
||||
struct cn81xx_uart *uart = (struct cn81xx_uart *)UAAx_PF_BAR0(bus);
|
||||
|
||||
assert(uart);
|
||||
if (!uart)
|
||||
return 1;
|
||||
|
||||
/* 1.2.1 Initialization Sequence (Power-On/Hard/Cold Reset) */
|
||||
/* 1. Wait for IOI reset (srst_n) to deassert. */
|
||||
|
||||
/**
|
||||
* 2. Assert all resets:
|
||||
* a. UAA reset: UCTL_CTL[UAA_RST] = 1
|
||||
* b. UCTL reset: UCTL_CTL[UCTL_RST] = 1
|
||||
*/
|
||||
ctl.u = read64(&uart->uctl_ctl);
|
||||
ctl.s.uctl_rst = 1;
|
||||
ctl.s.uaa_rst = 1;
|
||||
write64(&uart->uctl_ctl, ctl.u);
|
||||
|
||||
/**
|
||||
* 3. Configure the HCLK:
|
||||
* a. Reset the clock dividers: UCTL_CTL[H_CLKDIV_RST] = 1.
|
||||
* b. Select the HCLK frequency
|
||||
* i. UCTL_CTL[H_CLKDIV] = desired value,
|
||||
* ii. UCTL_CTL[H_CLKDIV_EN] = 1 to enable the HCLK.
|
||||
* iii. Readback UCTL_CTL to ensure the values take effect.
|
||||
* c. Deassert the HCLK clock divider reset: UCTL_CTL[H_CLKDIV_RST] = 0.
|
||||
*/
|
||||
ctl.u = read64(&uart->uctl_ctl);
|
||||
ctl.s.h_clkdiv_sel = UART_SCLK_DIV;
|
||||
write64(&uart->uctl_ctl, ctl.u);
|
||||
|
||||
ctl.u = read64(&uart->uctl_ctl);
|
||||
ctl.s.h_clk_byp_sel = 0;
|
||||
write64(&uart->uctl_ctl, ctl.u);
|
||||
|
||||
ctl.u = read64(&uart->uctl_ctl);
|
||||
ctl.s.h_clk_en = 1;
|
||||
write64(&uart->uctl_ctl, ctl.u);
|
||||
|
||||
ctl.u = read64(&uart->uctl_ctl);
|
||||
ctl.s.h_clkdiv_rst = 0;
|
||||
write64(&uart->uctl_ctl, ctl.u);
|
||||
|
||||
/**
|
||||
* 4. Wait 20 HCLK cycles from step 3 for HCLK to start and async fifo
|
||||
* to properly reset.
|
||||
*/
|
||||
uart_wait_hclk(uart, 20 + 1);
|
||||
|
||||
/**
|
||||
* 5. Deassert UCTL and UAHC resets:
|
||||
* a. UCTL_CTL[UCTL_RST] = 0
|
||||
* b. Wait 10 HCLK cycles.
|
||||
* c. UCTL_CTL[UAHC_RST] = 0
|
||||
* d. You will have to wait 10 HCLK cycles before accessing any
|
||||
* HCLK-only registers.
|
||||
*/
|
||||
ctl.u = read64(&uart->uctl_ctl);
|
||||
ctl.s.uctl_rst = 0;
|
||||
write64(&uart->uctl_ctl, ctl.u);
|
||||
|
||||
uart_wait_hclk(uart, 10 + 1);
|
||||
|
||||
ctl.u = read64(&uart->uctl_ctl);
|
||||
ctl.s.uaa_rst = 0;
|
||||
write64(&uart->uctl_ctl, ctl.u);
|
||||
|
||||
uart_wait_hclk(uart, 10 + 1);
|
||||
|
||||
/**
|
||||
* 6. Enable conditional SCLK of UCTL by writing
|
||||
* UCTL_CTL[CSCLK_EN] = 1.
|
||||
*/
|
||||
ctl.u = read64(&uart->uctl_ctl);
|
||||
ctl.s.csclk_en = 1;
|
||||
write64(&uart->uctl_ctl, ctl.u);
|
||||
|
||||
/**
|
||||
* 7. Initialize the integer and fractional baud rate divider registers
|
||||
* UARTIBRD and UARTFBRD as follows:
|
||||
* a. Baud Rate Divisor = UARTCLK/(16xBaud Rate) = BRDI + BRDF
|
||||
* b. The fractional register BRDF, m is calculated as
|
||||
* integer(BRDF x 64 + 0.5)
|
||||
* Example calculation:
|
||||
* If the required baud rate is 230400 and hclk = 4MHz then:
|
||||
* Baud Rate Divisor = (4x10^6)/(16x230400) = 1.085
|
||||
* This means BRDI = 1 and BRDF = 0.085.
|
||||
* Therefore, fractional part, BRDF = integer((0.085x64)+0.5) = 5
|
||||
* Generated baud rate divider = 1+5/64 = 1.078
|
||||
*/
|
||||
u64 divisor = thunderx_get_io_clock() /
|
||||
(baudrate * 16 * uart_sclk_divisor(UART_SCLK_DIV) / 64);
|
||||
write32(&uart->pl011.ibrd, divisor >> 6);
|
||||
write32(&uart->pl011.fbrd, divisor & UART_FBRD_BAUD_DIVFRAC_MASK);
|
||||
|
||||
/**
|
||||
* 8. Program the line control register UAA(0..1)_LCR_H and the control
|
||||
* register UAA(0..1)_CR
|
||||
*/
|
||||
/* 8-bits, FIFO enable */
|
||||
write32(&uart->pl011.lcr_h, PL011_UARTLCR_H_WLEN_8 |
|
||||
PL011_UARTLCR_H_FEN);
|
||||
/* RX/TX enable, UART enable */
|
||||
write32(&uart->pl011.cr, PL011_UARTCR_RXE | PL011_UARTCR_TXE |
|
||||
PL011_UARTCR_UARTEN);
|
||||
|
||||
return 0;
|
||||
}
|
12
src/soc/cavium/common/Kconfig
Normal file
12
src/soc/cavium/common/Kconfig
Normal file
|
@ -0,0 +1,12 @@
|
|||
config SOC_CAVIUM_COMMON
|
||||
bool
|
||||
default n
|
||||
select BOOTBLOCK_CUSTOM
|
||||
select CAVIUM_BDK
|
||||
select FLATTENED_DEVICE_TREE
|
||||
# FIXME: No Cavium support in ATF
|
||||
# select ARM64_USE_ARM_TRUSTED_FIRMWARE
|
||||
|
||||
if SOC_CAVIUM_COMMON
|
||||
|
||||
endif
|
58
src/soc/cavium/common/Makefile.inc
Normal file
58
src/soc/cavium/common/Makefile.inc
Normal file
|
@ -0,0 +1,58 @@
|
|||
##
|
||||
## This file is part of the coreboot project.
|
||||
##
|
||||
## Copyright 2017-present Facebook, Inc.
|
||||
##
|
||||
## This program is free software; you can redistribute it and/or modify
|
||||
## it under the terms of the GNU General Public License as published by
|
||||
## the Free Software Foundation; version 2 of the License.
|
||||
##
|
||||
## This program is distributed in the hope that it will be useful,
|
||||
## but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
## GNU General Public License for more details.
|
||||
##
|
||||
|
||||
ifeq ($(CONFIG_SOC_CAVIUM_COMMON),y)
|
||||
|
||||
CFLAGS_arm64 += -Wstack-usage=8192
|
||||
|
||||
bootblock-$(CONFIG_BOOTBLOCK_CUSTOM) += bootblock.c
|
||||
|
||||
################################################################################
|
||||
# romstage
|
||||
|
||||
romstage-y += cbmem.c
|
||||
romstage-y += bdk-coreboot.c
|
||||
|
||||
################################################################################
|
||||
# ramstage
|
||||
|
||||
ramstage-y += cbmem.c
|
||||
ramstage-$(CONFIG_ARM64_USE_ARM_TRUSTED_FIRMWARE) += bl31_plat_params.c
|
||||
|
||||
CPPFLAGS_common += -Isrc/soc/cavium/common/include
|
||||
|
||||
ROM_HEADER_BIN := $(objgenerated)/rom_header.bin
|
||||
ROM_HEADER_SOURCES += rom_clib_s_nbl1fw
|
||||
ROM_HEADER_SOURCES += rom_csib_s_nbl1fw
|
||||
|
||||
ROM_HEADER_DEPS := $(foreach f, $(ROM_HEADER_SOURCES), src/soc/cavium/common/$(f).bin.hex)
|
||||
|
||||
# Include ROM header
|
||||
$(ROM_HEADER_BIN): $(ROM_HEADER_DEPS)
|
||||
for f in $+; \
|
||||
do for c in $$(cat $$f | grep -v ^#); \
|
||||
do printf $$(printf '\%o' 0x$$c); \
|
||||
done; \
|
||||
done > $@
|
||||
|
||||
$(objcbfs)/bootblock.bin: $(objcbfs)/bootblock.raw.bin $(ROM_HEADER_BIN)
|
||||
@printf " GEN $(subst $(obj)/,,$(@))\n"
|
||||
dd if=/dev/zero ibs=1 count=$$(($(shell stat --printf="%s" $(objcbfs)/bootblock.raw.bin) + 0x10000)) of=$@ status=none
|
||||
# Insert CLIB at 0x0 and CSIB at 0x100
|
||||
dd if=$(ROM_HEADER_BIN) of=$@ bs=1 seek=0 conv=notrunc status=none
|
||||
# Insert bootblock at 0x10000
|
||||
dd if=$(objcbfs)/bootblock.raw.bin of=$@ bs=1 seek=$$((0x10000)) conv=notrunc status=none
|
||||
|
||||
endif
|
130
src/soc/cavium/common/bdk-coreboot.c
Normal file
130
src/soc/cavium/common/bdk-coreboot.c
Normal file
|
@ -0,0 +1,130 @@
|
|||
/*
|
||||
* This file is part of the coreboot project.
|
||||
*
|
||||
* Copyright 2017-present Facebook, Inc.
|
||||
* Copyright 2003-2017 Cavium Inc. <support@cavium.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; version 2 of the License.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* This file consists of data imported from bdk-config.c
|
||||
*/
|
||||
// coreboot
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <device/i2c.h>
|
||||
#include <device/i2c_simple.h>
|
||||
#include <endian.h>
|
||||
#include <arch/io.h>
|
||||
#include <delay.h>
|
||||
#include <reset.h>
|
||||
#include <soc/timer.h>
|
||||
|
||||
// BDK
|
||||
#include <libbdk-arch/bdk-numa.h>
|
||||
#include <libbdk-hal/bdk-config.h>
|
||||
#include <libbdk-hal/bdk-twsi.h>
|
||||
#include <libbdk-boot/bdk-watchdog.h>
|
||||
|
||||
/**
|
||||
* Do a twsi read from a 7 bit device address using an (optional)
|
||||
* internal address. Up to 4 bytes can be read at a time.
|
||||
*
|
||||
* @param twsi_id which TWSI bus to use
|
||||
* @param dev_addr Device address (7 bit)
|
||||
* @param internal_addr
|
||||
* Internal address. Can be 0, 1 or 2 bytes in width
|
||||
* @param num_bytes Number of data bytes to read (1-4)
|
||||
* @param ia_width_bytes
|
||||
* Internal address size in bytes (0, 1, or 2)
|
||||
*
|
||||
* @return Read data, or -1 on failure
|
||||
*/
|
||||
int64_t bdk_twsix_read_ia(bdk_node_t node, int twsi_id, uint8_t dev_addr,
|
||||
uint16_t internal_addr, int num_bytes,
|
||||
int ia_width_bytes)
|
||||
{
|
||||
struct i2c_msg seg[2];
|
||||
u32 buf;
|
||||
|
||||
assert (num_bytes < 5);
|
||||
assert (ia_width_bytes < 3);
|
||||
|
||||
seg[0].flags = 0;
|
||||
seg[0].slave = dev_addr;
|
||||
seg[0].buf = (u8 *)&internal_addr;
|
||||
seg[0].len = ia_width_bytes;
|
||||
seg[1].flags = I2C_M_RD;
|
||||
seg[1].slave = dev_addr;
|
||||
seg[1].buf = (u8 *)&buf;
|
||||
seg[1].len = num_bytes;
|
||||
|
||||
if (i2c_transfer(twsi_id, seg, ARRAY_SIZE(seg)) < 0)
|
||||
return -1;
|
||||
|
||||
return cpu_to_be32(buf);
|
||||
}
|
||||
|
||||
/**
|
||||
* Write 1-8 bytes to a TWSI device using an internal address.
|
||||
*
|
||||
* @param twsi_id which TWSI interface to use
|
||||
* @param dev_addr TWSI device address (7 bit only)
|
||||
* @param internal_addr
|
||||
* TWSI internal address (0, 8, or 16 bits)
|
||||
* @param num_bytes Number of bytes to write (1-8)
|
||||
* @param ia_width_bytes
|
||||
* internal address width, in bytes (0, 1, 2)
|
||||
* @param data Data to write. Data is written MSB first on the twsi bus, and
|
||||
* only the lower num_bytes bytes of the argument are valid. (If
|
||||
* a 2 byte write is done, only the low 2 bytes of the argument is
|
||||
* used.
|
||||
*
|
||||
* @return Zero on success, -1 on error
|
||||
*/
|
||||
int bdk_twsix_write_ia(bdk_node_t node, int twsi_id, uint8_t dev_addr,
|
||||
uint16_t internal_addr, int num_bytes,
|
||||
int ia_width_bytes, uint64_t data)
|
||||
{
|
||||
struct i2c_msg seg;
|
||||
u8 buf[10];
|
||||
|
||||
assert (num_bytes <= 8);
|
||||
assert (ia_width_bytes < 3);
|
||||
|
||||
memcpy(buf, &internal_addr, ia_width_bytes);
|
||||
memcpy(&buf[ia_width_bytes], &data, num_bytes);
|
||||
|
||||
seg.flags = 0;
|
||||
seg.slave = dev_addr;
|
||||
seg.buf = buf;
|
||||
seg.len = num_bytes + ia_width_bytes;
|
||||
|
||||
return platform_i2c_transfer(twsi_id, &seg, 1);
|
||||
}
|
||||
|
||||
void bdk_watchdog_set(unsigned int timeout_ms)
|
||||
{
|
||||
watchdog_set(0, timeout_ms);
|
||||
}
|
||||
|
||||
void bdk_watchdog_poke(void)
|
||||
{
|
||||
watchdog_poke(0);
|
||||
}
|
||||
|
||||
void bdk_watchdog_disable(void)
|
||||
{
|
||||
watchdog_disable(0);
|
||||
}
|
||||
|
||||
int bdk_watchdog_is_running(void)
|
||||
{
|
||||
return watchdog_is_running(0);
|
||||
}
|
32
src/soc/cavium/common/bl31_plat_params.c
Normal file
32
src/soc/cavium/common/bl31_plat_params.c
Normal file
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
* This file is part of the coreboot project.
|
||||
*
|
||||
* Copyright 2016 Rockchip Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; version 2 of the License.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <arm_tf.h>
|
||||
#include <assert.h>
|
||||
#include <soc/bl31_plat_params.h>
|
||||
|
||||
static struct bl31_plat_param *plat_params;
|
||||
|
||||
void register_bl31_param(struct bl31_plat_param *param)
|
||||
{
|
||||
param->next = plat_params;
|
||||
plat_params = param;
|
||||
}
|
||||
|
||||
void *soc_get_bl31_plat_params(bl31_params_t *bl31_params)
|
||||
{
|
||||
return plat_params;
|
||||
}
|
68
src/soc/cavium/common/bootblock.c
Normal file
68
src/soc/cavium/common/bootblock.c
Normal file
|
@ -0,0 +1,68 @@
|
|||
/*
|
||||
* This file is part of the coreboot project.
|
||||
*
|
||||
* Copyright 2018-present Facebook, Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; version 2 of
|
||||
* the License.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#include <arch/exception.h>
|
||||
#include <console/console.h>
|
||||
#include <delay.h>
|
||||
#include <program_loading.h>
|
||||
#include <symbols.h>
|
||||
#include <timestamp.h>
|
||||
#include <soc/bootblock.h>
|
||||
|
||||
DECLARE_OPTIONAL_REGION(timestamp);
|
||||
|
||||
__attribute__((weak)) void bootblock_mainboard_early_init(void) { /* no-op */ }
|
||||
__attribute__((weak)) void bootblock_soc_early_init(void) { /* do nothing */ }
|
||||
__attribute__((weak)) void bootblock_soc_init(void) { /* do nothing */ }
|
||||
__attribute__((weak)) void bootblock_mainboard_init(void) { /* do nothing */ }
|
||||
|
||||
|
||||
/* C code entry point for the boot block */
|
||||
void bootblock_main(const uint64_t reg_x0,
|
||||
const uint64_t reg_x1,
|
||||
const uint64_t reg_pc)
|
||||
{
|
||||
uint64_t base_timestamp = 0;
|
||||
|
||||
init_timer();
|
||||
|
||||
if (IS_ENABLED(CONFIG_COLLECT_TIMESTAMPS))
|
||||
base_timestamp = timestamp_get();
|
||||
|
||||
/* Initialize timestamps if we have TIMESTAMP region in memlayout.ld. */
|
||||
if (IS_ENABLED(CONFIG_COLLECT_TIMESTAMPS) && _timestamp_size > 0)
|
||||
timestamp_init(base_timestamp);
|
||||
|
||||
bootblock_soc_early_init();
|
||||
bootblock_mainboard_early_init();
|
||||
|
||||
if (IS_ENABLED(CONFIG_BOOTBLOCK_CONSOLE)) {
|
||||
console_init();
|
||||
exception_init();
|
||||
|
||||
if (reg_x0)
|
||||
printk(BIOS_ERR,
|
||||
"BOOTBLOCK: RST Boot Failure Code %lld\n",
|
||||
reg_x0);
|
||||
|
||||
printk(BIOS_DEBUG, "BOOTBLOCK: FDT 0x%llX\n", reg_x1);
|
||||
}
|
||||
|
||||
bootblock_soc_init();
|
||||
bootblock_mainboard_init();
|
||||
|
||||
run_romstage();
|
||||
}
|
26
src/soc/cavium/common/cbmem.c
Normal file
26
src/soc/cavium/common/cbmem.c
Normal file
|
@ -0,0 +1,26 @@
|
|||
/*
|
||||
* This file is part of the coreboot project.
|
||||
*
|
||||
* Copyright 2014 Rockchip Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; version 2 of the License.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#include <cbmem.h>
|
||||
#include <soc/addressmap.h>
|
||||
#include <soc/sdram.h>
|
||||
#include <stdlib.h>
|
||||
#include <symbols.h>
|
||||
|
||||
void *cbmem_top(void)
|
||||
{
|
||||
return (void *)min((uintptr_t)_dram + sdram_size_mb() * MiB,
|
||||
MAX_DRAM_ADDRESS);
|
||||
}
|
25
src/soc/cavium/common/include/soc/bl31_plat_params.h
Normal file
25
src/soc/cavium/common/include/soc/bl31_plat_params.h
Normal file
|
@ -0,0 +1,25 @@
|
|||
/*
|
||||
* This file is part of the coreboot project.
|
||||
*
|
||||
* Copyright 2016 Rockchip Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; version 2 of the License.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __BL31_PLAT_PARAMS_H__
|
||||
#define __BL31_PLAT_PARAMS_H__
|
||||
|
||||
// FIXME: use correct path one ATF is upstream
|
||||
#include <arm-trusted-firmware/plat/rockchip/common/include/plat_params.h>
|
||||
|
||||
void register_bl31_param(struct bl31_plat_param *param);
|
||||
|
||||
#endif/* __BL31_PLAT_PARAMS_H__ */
|
29
src/soc/cavium/common/include/soc/bootblock.h
Normal file
29
src/soc/cavium/common/include/soc/bootblock.h
Normal file
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
* This file is part of the coreboot project.
|
||||
*
|
||||
* Copyright 2018-present Facebook, Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; version 2 of
|
||||
* the License.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
#ifndef SRC_SOC_CAVIUM_COMMON_INCLUDE_SOC_BOOTBLOCK_H_
|
||||
#define SRC_SOC_CAVIUM_COMMON_INCLUDE_SOC_BOOTBLOCK_H_
|
||||
|
||||
void bootblock_mainboard_early_init(void);
|
||||
void bootblock_soc_early_init(void);
|
||||
void bootblock_soc_init(void);
|
||||
void bootblock_mainboard_init(void);
|
||||
|
||||
void bootblock_main(const uint64_t reg_x0,
|
||||
const uint64_t reg_x1,
|
||||
const uint64_t reg_pc);
|
||||
|
||||
|
||||
#endif /* SRC_SOC_CAVIUM_COMMON_INCLUDE_SOC_BOOTBLOCK_H_ */
|
65
src/soc/cavium/common/include/soc/sysreg.h
Normal file
65
src/soc/cavium/common/include/soc/sysreg.h
Normal file
|
@ -0,0 +1,65 @@
|
|||
/*
|
||||
* This file is part of the coreboot project.
|
||||
*
|
||||
* Copyright 2018-present Facebook, Inc.
|
||||
* Copyright (c) 2003-2017 Cavium Inc. (support@cavium.com). All rights
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; version 2 of
|
||||
* the License.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
#ifndef __SOC_CAVIUM_COMMON_INCLUDE_SOC_SYSREG_H
|
||||
#define __SOC_CAVIUM_COMMON_INCLUDE_SOC_SYSREG_H
|
||||
|
||||
/* TODO: add CVMCTL_EL1 */
|
||||
|
||||
#define AP_CVMMEMCTL0_EL1_NODE_SHIFT 61
|
||||
#define AP_CVMMEMCTL0_EL1_NODE_MASK 0x3
|
||||
#define AP_CVMMEMCTL0_EL1_STEXFAILCNT_SHIFT 58
|
||||
#define AP_CVMMEMCTL0_EL1_STEXFAILCNT_MASK 0x7
|
||||
#define AP_CVMMEMCTL0_EL1_WFELDEX1DIS (1 << 57)
|
||||
#define AP_CVMMEMCTL0_EL1_STLSTALLFORCE (1 << 56)
|
||||
#define AP_CVMMEMCTL0_EL1_DMBSTALLFORCE (1 << 55)
|
||||
#define AP_CVMMEMCTL0_EL1_TLBINOPDIS (1 << 54)
|
||||
#define AP_CVMMEMCTL0_EL1_TLBIICFLUSH (1 << 53)
|
||||
#define AP_CVMMEMCTL0_EL1_GSYNCTO_SHIFT 48
|
||||
#define AP_CVMMEMCTL0_EL1_GSYNCTO_MASK 0x1f
|
||||
#define AP_CVMMEMCTL0_EL1_UTLBFILLBYPDIS (1 << 47)
|
||||
#define AP_CVMMEMCTL0_EL1_TLBIALL (1 << 46)
|
||||
#define AP_CVMMEMCTL0_EL1_WBFDSBFLUSHALL (1 << 45)
|
||||
#define AP_CVMMEMCTL0_EL1_WBFDMBFLUSHNEXT (1 << 44)
|
||||
#define AP_CVMMEMCTL0_EL1_STEXL2CFORCE (1 << 43)
|
||||
#define AP_CVMMEMCTL0_EL1_WCUMISSFORCE (1 << 41)
|
||||
#define AP_CVMMEMCTL0_EL1_REPLAYPREFDIS (1 << 40)
|
||||
#define AP_CVMMEMCTL0_EL1_ZVAL2CDIS (1 << 39)
|
||||
#define AP_CVMMEMCTL0_EL1_LDIL2CDIS (1 << 38)
|
||||
#define AP_CVMMEMCTL0_EL1_DVCA47 (1 << 37)
|
||||
#define AP_CVMMEMCTL0_EL1_STPREFDIS (1 << 36)
|
||||
#define AP_CVMMEMCTL0_EL1_LDPREFDIS (1 << 35)
|
||||
#define AP_CVMMEMCTL0_EL1_WFILDEXDIS (1 << 34)
|
||||
#define AP_CVMMEMCTL0_EL1_WFITO_SHIFT 31
|
||||
#define AP_CVMMEMCTL0_EL1_WFITO_MASK 0x7
|
||||
#define AP_CVMMEMCTL0_EL1_RBFSHORTTO_SHIFT 26
|
||||
#define AP_CVMMEMCTL0_EL1_RBFSHORTTO_MASK 0x1f
|
||||
#define AP_CVMMEMCTL0_EL1_RBFTO_SHIFT 21
|
||||
#define AP_CVMMEMCTL0_EL1_RBFTO_MASK 0x1f
|
||||
#define AP_CVMMEMCTL0_EL1_WBFALLBARRIER (1 << 20)
|
||||
#define AP_CVMMEMCTL0_EL1_WBFNOMERGE (1 << 19)
|
||||
#define AP_CVMMEMCTL0_EL1_WBFTONSHENA (1 << 18)
|
||||
#define AP_CVMMEMCTL0_EL1_WBFTOMRGCLRENA (1 << 17)
|
||||
#define AP_CVMMEMCTL0_EL1_WBFTO_SHIFT 12
|
||||
#define AP_CVMMEMCTL0_EL1_WBFTO_MASK 0x1f
|
||||
#define AP_CVMMEMCTL0_EL1_WBFTHRESH_SHIFT 7
|
||||
#define AP_CVMMEMCTL0_EL1_WBFTHRESH_MASK 0x1f
|
||||
#define AP_CVMMEMCTL0_EL1_UTLBENTRIESM1_SHIFT 2
|
||||
#define AP_CVMMEMCTL0_EL1_UTLBENTRIESM1_MASK 0x1f
|
||||
#define AP_CVMMEMCTL0_EL1_CCLKFORCE (1 << 1)
|
||||
#define AP_CVMMEMCTL0_EL1_MCLKFORCE (1 << 0)
|
||||
|
||||
#endif /* __SOC_CAVIUM_COMMON_INCLUDE_SOC_SYSREG_H */
|
16
src/soc/cavium/common/rom_clib_s_nbl1fw.bin.hex
Normal file
16
src/soc/cavium/common/rom_clib_s_nbl1fw.bin.hex
Normal file
|
@ -0,0 +1,16 @@
|
|||
43 56 4d 5f 43 4c 49 42 00 00 00 00 00 00 00 00
|
||||
00 00 02 00 00 00 00 00 00 00 03 00 00 00 00 00
|
||||
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
||||
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
||||
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
||||
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
||||
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
||||
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
||||
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
||||
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
||||
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
||||
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
||||
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
||||
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
||||
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
||||
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
16
src/soc/cavium/common/rom_csib_s_nbl1fw.bin.hex
Normal file
16
src/soc/cavium/common/rom_csib_s_nbl1fw.bin.hex
Normal file
|
@ -0,0 +1,16 @@
|
|||
43 56 4d 5f 43 53 49 42 00 00 00 00 00 00 00 00
|
||||
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
||||
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
||||
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
||||
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
||||
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
||||
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
||||
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
||||
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
||||
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
||||
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
||||
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
||||
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
||||
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
||||
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
||||
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
173
src/vendorcode/cavium/include/bdk/bdk-coreboot.h
Normal file
173
src/vendorcode/cavium/include/bdk/bdk-coreboot.h
Normal file
|
@ -0,0 +1,173 @@
|
|||
/*
|
||||
* This file is part of the coreboot project.
|
||||
* Copyright (c) 2003-2017 Cavium Inc. (support@cavium.com). All rights
|
||||
* reserved.
|
||||
* Copyright 2018-present Facebook, Inc.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*
|
||||
* access.h: Wrappers for memory access
|
||||
*/
|
||||
|
||||
#ifndef __BDK_BDK_COREBOOT_H
|
||||
#define __BDK_BDK_COREBOOT_H
|
||||
|
||||
#include <arch/io.h>
|
||||
#include <delay.h>
|
||||
|
||||
/**
|
||||
* Convert a memory pointer (void*) into a hardware compatible
|
||||
* memory address (uint64_t). Cavium hardware widgets don't
|
||||
* understand logical addresses.
|
||||
*
|
||||
* @param ptr C style memory pointer
|
||||
* @return Hardware physical address
|
||||
*/
|
||||
static inline uint64_t bdk_ptr_to_phys(void *ptr)
|
||||
{
|
||||
/* PA = VA for coreboot's purposes */
|
||||
return (uint64_t)ptr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a hardware physical address (uint64_t) into a
|
||||
* memory pointer (void *).
|
||||
*
|
||||
* @param physical_address
|
||||
* Hardware physical address to memory
|
||||
* @return Pointer to memory
|
||||
*/
|
||||
static inline void *bdk_phys_to_ptr(uint64_t physical_address)
|
||||
{
|
||||
/* PA = VA for coreboot's purposes */
|
||||
return (void *)physical_address;
|
||||
}
|
||||
|
||||
static inline void bdk_write64_int64(uint64_t address, int64_t value)
|
||||
{
|
||||
dmb();
|
||||
*(volatile int64_t *)address = value;
|
||||
dmb();
|
||||
}
|
||||
|
||||
static inline void bdk_write64_uint64(uint64_t address, uint64_t value)
|
||||
{
|
||||
write64(bdk_phys_to_ptr(address), value);
|
||||
}
|
||||
|
||||
static inline void bdk_write64_int32(uint64_t address, int32_t value)
|
||||
{
|
||||
dmb();
|
||||
*(volatile int32_t *)address = value;
|
||||
dmb();
|
||||
}
|
||||
|
||||
static inline void bdk_write64_uint32(uint64_t address, uint32_t value)
|
||||
{
|
||||
write32(bdk_phys_to_ptr(address), value);
|
||||
}
|
||||
|
||||
static inline void bdk_write64_int16(uint64_t address, int16_t value)
|
||||
{
|
||||
dmb();
|
||||
*(volatile int16_t *)address = value;
|
||||
dmb();
|
||||
}
|
||||
|
||||
static inline void bdk_write64_uint16(uint64_t address, uint16_t value)
|
||||
{
|
||||
write16(bdk_phys_to_ptr(address), value);
|
||||
}
|
||||
|
||||
static inline void bdk_write64_int8(uint64_t address, int8_t value)
|
||||
{
|
||||
dmb();
|
||||
*(volatile int8_t *)address = value;
|
||||
dmb();
|
||||
}
|
||||
|
||||
static inline void bdk_write64_uint8(uint64_t address, uint8_t value)
|
||||
{
|
||||
write8(bdk_phys_to_ptr(address), value);
|
||||
}
|
||||
|
||||
static inline int64_t bdk_read64_int64(uint64_t address)
|
||||
{
|
||||
return *(volatile int64_t *)bdk_phys_to_ptr(address);
|
||||
}
|
||||
|
||||
static inline uint64_t bdk_read64_uint64(uint64_t address)
|
||||
{
|
||||
return read64(bdk_phys_to_ptr(address));
|
||||
}
|
||||
|
||||
static inline int32_t bdk_read64_int32(uint64_t address)
|
||||
{
|
||||
return *(volatile int32_t *)bdk_phys_to_ptr(address);
|
||||
}
|
||||
|
||||
static inline uint32_t bdk_read64_uint32(uint64_t address)
|
||||
{
|
||||
return read32(bdk_phys_to_ptr(address));
|
||||
}
|
||||
|
||||
static inline int16_t bdk_read64_int16(uint64_t address)
|
||||
{
|
||||
return *(volatile int16_t *)bdk_phys_to_ptr(address);
|
||||
}
|
||||
|
||||
static inline uint16_t bdk_read64_uint16(uint64_t address)
|
||||
{
|
||||
return read16(bdk_phys_to_ptr(address));
|
||||
}
|
||||
|
||||
static inline int8_t bdk_read64_int8(uint64_t address)
|
||||
{
|
||||
return *(volatile int8_t *)bdk_phys_to_ptr(address);
|
||||
}
|
||||
|
||||
static inline uint8_t bdk_read64_uint8(uint64_t address)
|
||||
{
|
||||
return read8(bdk_phys_to_ptr(address));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of bits set in the provided value.
|
||||
* Simple wrapper for POP instruction.
|
||||
*
|
||||
* @param val 32 bit value to count set bits in
|
||||
*
|
||||
* @return Number of bits set
|
||||
*/
|
||||
inline uint32_t bdk_pop(uint32_t v)
|
||||
{
|
||||
/* Use parallel SWAR algorithm */
|
||||
v = v - ((v >> 1) & 0x55555555);
|
||||
v = (v & 0x33333333) + ((v >> 2) & 0x33333333);
|
||||
return (((v + (v >> 4)) & 0xF0F0F0F) * 0x1010101) >> 24;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of bits set in the provided value.
|
||||
* Simple wrapper for DPOP instruction.
|
||||
*
|
||||
* @param val 64 bit value to count set bits in
|
||||
*
|
||||
* @return Number of bits set
|
||||
*/
|
||||
inline int bdk_dpop(uint64_t val)
|
||||
{
|
||||
return bdk_pop(val & 0xffffffff) + bdk_pop(val >> 32);
|
||||
}
|
||||
|
||||
/**
|
||||
* Wait for the specified number of micro seconds
|
||||
*
|
||||
* @param usec micro seconds to wait
|
||||
*/
|
||||
static inline void bdk_wait_usec(uint64_t usec)
|
||||
{
|
||||
udelay((unsigned int)usec);
|
||||
}
|
||||
|
||||
#endif /* !__BDK_BDK_COREBOOT_H */
|
|
@ -10,13 +10,12 @@
|
|||
* bdk-minimal.h: Subset of bdk.h used by coreboot
|
||||
*/
|
||||
|
||||
#ifndef __SOC_CAVIUM_COMMON_BDK_MINIMAL_H__
|
||||
#define __SOC_CAVIUM_COMMON_BDK_MINIMAL_H__
|
||||
#ifndef BDK_MINIMAL_H__
|
||||
#define BDK_MINIMAL_H__
|
||||
|
||||
#include <console/console.h> /* for printk */
|
||||
#include <endian.h>
|
||||
#include <stddef.h> /* for NULL */
|
||||
#include <libbdk-hal/bdk-access.h>
|
||||
|
||||
#define bdk_le16_to_cpu(x) le16_to_cpu(x)
|
||||
#define bdk_le32_to_cpu(x) le32_to_cpu(x)
|
||||
|
@ -28,11 +27,6 @@
|
|||
#define bdk_cpu_to_le32(x) cpu_to_le32(x)
|
||||
#define bdk_cpu_to_le64(x) cpu_to_le64(x)
|
||||
|
||||
#define __BYTE_ORDER __BYTE_ORDER__
|
||||
/* Watch out for __BIG_ENDIAN. coreboot usually checks if it's defined at all
|
||||
* but the Cavium BDK checks its value. */
|
||||
#define __BIG_ENDIAN 4321
|
||||
|
||||
#define printf(format, ...) printk(BIOS_DEBUG, format, ##__VA_ARGS__)
|
||||
#define puts(str) printk(BIOS_INFO, str)
|
||||
#define fflush(x) /* output gets flushed automatically */
|
||||
|
@ -42,8 +36,10 @@
|
|||
#include <libbdk-arch/bdk-asm.h>
|
||||
#include <libbdk-arch/bdk-model.h>
|
||||
#include <libbdk-arch/bdk-numa.h>
|
||||
#include <libbdk-hal/bdk-access.h>
|
||||
|
||||
#include <libbdk-arch/bdk-require.h>
|
||||
|
||||
#include <libbdk-arch/bdk-csr.h>
|
||||
|
||||
#include <libbdk-os/bdk-thread.h>
|
||||
|
@ -57,4 +53,4 @@
|
|||
|
||||
static inline char *getenv(const char *name) { return NULL; }
|
||||
|
||||
#endif /* !__SOC_CAVIUM_COMMON_BDK_MINIMAL_H__ */
|
||||
#endif /* BDK_MINIMAL_H__ */
|
||||
|
|
Loading…
Reference in a new issue