mirror of
https://github.com/AsahiLinux/u-boot
synced 2024-11-10 15:14:43 +00:00
Merge git://git.denx.de/u-boot-dm
- MPC83xx device tree additions (CPU and RAM) - Fix sandbox build error - Sync bitrev with Linux - Various ofnode/DT improvements
This commit is contained in:
commit
4e710ebb44
70 changed files with 4695 additions and 91 deletions
23
Documentation/devicetree/bindings/clk/fsl,mpc83xx-clk.txt
Normal file
23
Documentation/devicetree/bindings/clk/fsl,mpc83xx-clk.txt
Normal file
|
@ -0,0 +1,23 @@
|
|||
MPC83xx system clock devices
|
||||
|
||||
MPC83xx SoCs supply a variety of clocks to drive various components of a
|
||||
system.
|
||||
|
||||
Required properties:
|
||||
- compatible: must be one of "fsl,mpc8308-clk",
|
||||
"fsl,mpc8309-clk",
|
||||
"fsl,mpc8313-clk",
|
||||
"fsl,mpc8315-clk",
|
||||
"fsl,mpc832x-clk",
|
||||
"fsl,mpc8349-clk",
|
||||
"fsl,mpc8360-clk",
|
||||
"fsl,mpc8379-clk"
|
||||
depending on which SoC is employed
|
||||
- #clock-cells: Must be 1
|
||||
|
||||
Example:
|
||||
|
||||
socclocks: clocks {
|
||||
compatible = "fsl,mpc832x-clk";
|
||||
#clock-cells = <1>;
|
||||
};
|
34
Documentation/devicetree/bindings/cpu/fsl,mpc83xx.txt
Normal file
34
Documentation/devicetree/bindings/cpu/fsl,mpc83xx.txt
Normal file
|
@ -0,0 +1,34 @@
|
|||
MPC83xx CPU devices
|
||||
|
||||
MPC83xx SoCs contain a e300 core as their main processor.
|
||||
|
||||
Required properties:
|
||||
- compatible: must be one of "fsl,mpc83xx",
|
||||
"fsl,mpc8308",
|
||||
"fsl,mpc8309",
|
||||
"fsl,mpc8313",
|
||||
"fsl,mpc8315",
|
||||
"fsl,mpc832x",
|
||||
"fsl,mpc8349",
|
||||
"fsl,mpc8360",
|
||||
"fsl,mpc8379"
|
||||
- clocks: has to have two entries, which must be the core clock at index 0 and
|
||||
the CSB (Coherent System Bus) clock at index 1. Both are given by a suitable
|
||||
"fsl,mpc83xx-clk" device
|
||||
|
||||
Example:
|
||||
|
||||
socclocks: clocks {
|
||||
compatible = "fsl,mpc8315-clk";
|
||||
#clock-cells = <1>;
|
||||
};
|
||||
|
||||
cpus {
|
||||
compatible = "cpu_bus";
|
||||
|
||||
PowerPC,8315@0 {
|
||||
compatible = "fsl,mpc8315";
|
||||
clocks = <&socclocks MPC83XX_CLK_CORE
|
||||
&socclocks MPC83XX_CLK_CSB>;
|
||||
};
|
||||
};
|
|
@ -0,0 +1,24 @@
|
|||
MPC83xx SerDes controller devices
|
||||
|
||||
MPC83xx SoCs contain a built-in SerDes controller that determines which
|
||||
protocols (SATA, PCI Express, SGMII, ...) are used on the system's serdes lines
|
||||
and how the lines are configured.
|
||||
|
||||
Required properties:
|
||||
- compatible: must be "fsl,mpc83xx-serdes"
|
||||
- reg: must point to the serdes controller's register map
|
||||
- proto: selects for which protocol the serdes lines are configured. One of
|
||||
"sata", "pex", "pex-x2", "sgmii"
|
||||
- serdes-clk: determines the frequency the serdes lines are configured for. One
|
||||
of 100, 125, 150.
|
||||
- vdd: determines whether 1.0V core VDD is used or not
|
||||
|
||||
Example:
|
||||
|
||||
SERDES: serdes@e3000 {
|
||||
reg = <0xe3000 0x200>;
|
||||
compatible = "fsl,mpc83xx-serdes";
|
||||
proto = "pex";
|
||||
serdes-clk = <100>;
|
||||
vdd;
|
||||
};
|
|
@ -0,0 +1,314 @@
|
|||
MPC83xx RAM controller
|
||||
|
||||
This driver supplies support for the embedded RAM controller on MCP83xx-series
|
||||
SoCs.
|
||||
|
||||
For static configuration mode, each controller node should have child nodes
|
||||
describing the actual RAM modules installed.
|
||||
|
||||
Controller node
|
||||
===============
|
||||
|
||||
Required properties:
|
||||
- compatible: Must be "fsl,mpc83xx-mem-controller"
|
||||
- reg: The address of the RAM controller's register space
|
||||
- #address-cells: Must be 2
|
||||
- #size-cells: Must be 1
|
||||
- driver_software_override: DDR driver software override is enabled (1) or
|
||||
disabled (0)
|
||||
- p_impedance_override: DDR driver software p-impedance override; possible
|
||||
values:
|
||||
* DSO_P_IMPEDANCE_HIGHEST_Z
|
||||
* DSO_P_IMPEDANCE_MUCH_HIGHER_Z
|
||||
* DSO_P_IMPEDANCE_HIGHER_Z
|
||||
* DSO_P_IMPEDANCE_NOMINAL
|
||||
* DSO_P_IMPEDANCE_LOWER_Z
|
||||
- n_impedance_override: DDR driver software n-impedance override; possible
|
||||
values:
|
||||
* DSO_N_IMPEDANCE_HIGHEST_Z
|
||||
* DSO_N_IMPEDANCE_MUCH_HIGHER_Z
|
||||
* DSO_N_IMPEDANCE_HIGHER_Z
|
||||
* DSO_N_IMPEDANCE_NOMINAL
|
||||
* DSO_N_IMPEDANCE_LOWER_Z
|
||||
- odt_termination_value: ODT termination value for I/Os; possible values:
|
||||
* ODT_TERMINATION_75_OHM
|
||||
* ODT_TERMINATION_150_OHM
|
||||
- ddr_type: Selects voltage level for DDR pads; possible
|
||||
values:
|
||||
* DDR_TYPE_DDR2_1_8_VOLT
|
||||
* DDR_TYPE_DDR1_2_5_VOLT
|
||||
- mvref_sel: Determine where MVREF_SEL signal is generated;
|
||||
possible values:
|
||||
* MVREF_SEL_EXTERNAL
|
||||
* MVREF_SEL_INTERNAL_GVDD
|
||||
- m_odr: Disable memory transaction reordering; possible
|
||||
values:
|
||||
* M_ODR_ENABLE
|
||||
* M_ODR_DISABLE
|
||||
- clock_adjust: Clock adjust; possible values:
|
||||
* CLOCK_ADJUST_025
|
||||
* CLOCK_ADJUST_05
|
||||
* CLOCK_ADJUST_075
|
||||
* CLOCK_ADJUST_1
|
||||
- ext_refresh_rec: Extended refresh recovery time; possible values:
|
||||
0, 16, 32, 48, 64, 80, 96, 112
|
||||
- read_to_write: Read-to-write turnaround; possible values:
|
||||
0, 1, 2, 3
|
||||
- write_to_read: Write-to-read turnaround; possible values:
|
||||
0, 1, 2, 3
|
||||
- read_to_read: Read-to-read turnaround; possible values:
|
||||
0, 1, 2, 3
|
||||
- write_to_write: Write-to-write turnaround; possible values:
|
||||
0, 1, 2, 3
|
||||
- active_powerdown_exit: Active powerdown exit timing; possible values:
|
||||
1, 2, 3, 4, 5, 6, 7
|
||||
- precharge_powerdown_exit: Precharge powerdown exit timing; possible values:
|
||||
1, 2, 3, 4, 5, 6, 7
|
||||
- odt_powerdown_exit: ODT powerdown exit timing; possible values:
|
||||
0, 1, 2, 3, 4, 5, 6, 7, 8,
|
||||
9, 10, 11, 12, 13, 14, 15
|
||||
- mode_reg_set_cycle: Mode register set cycle time; possible values:
|
||||
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15
|
||||
- precharge_to_activate: Precharge-to-acitvate interval; possible values:
|
||||
1, 2, 3, 4, 5, 6, 7
|
||||
- activate_to_precharge: Activate to precharge interval; possible values:
|
||||
4, 5, 6, 7, 8, 9, 10, 11, 12,
|
||||
13, 14, 15, 16, 17, 18, 19
|
||||
- activate_to_readwrite: Activate to read/write interval for SDRAM;
|
||||
possible values:
|
||||
1, 2, 3, 4, 5, 6, 7
|
||||
- mcas_latency: MCAS latency from READ command; possible values:
|
||||
* CASLAT_20
|
||||
* CASLAT_25
|
||||
* CASLAT_30
|
||||
* CASLAT_35
|
||||
* CASLAT_40
|
||||
* CASLAT_45
|
||||
* CASLAT_50
|
||||
* CASLAT_55
|
||||
* CASLAT_60
|
||||
* CASLAT_65
|
||||
* CASLAT_70
|
||||
* CASLAT_75
|
||||
* CASLAT_80
|
||||
- refresh_recovery: Refresh recovery time; possible values:
|
||||
8, 9, 10, 11, 12, 13, 14, 15,
|
||||
16, 17, 18, 19, 20, 21, 22, 23
|
||||
- last_data_to_precharge: Last data to precharge minimum interval; possible
|
||||
values:
|
||||
1, 2, 3, 4, 5, 6, 7
|
||||
- activate_to_activate: Activate-to-activate interval; possible values:
|
||||
1, 2, 3, 4, 5, 6, 7
|
||||
- last_write_data_to_read: Last write data pair to read command issue
|
||||
interval; possible values:
|
||||
1, 2, 3, 4, 5, 6, 7
|
||||
- additive_latency: Additive latency; possible values:
|
||||
0, 1, 2, 3, 4, 5
|
||||
- mcas_to_preamble_override: MCAS-to-preamble-override; possible values:
|
||||
* READ_LAT
|
||||
* READ_LAT_PLUS_1_4
|
||||
* READ_LAT_PLUS_1_2
|
||||
* READ_LAT_PLUS_3_4
|
||||
* READ_LAT_PLUS_1
|
||||
* READ_LAT_PLUS_5_4
|
||||
* READ_LAT_PLUS_3_2
|
||||
* READ_LAT_PLUS_7_4
|
||||
* READ_LAT_PLUS_2
|
||||
* READ_LAT_PLUS_9_4
|
||||
* READ_LAT_PLUS_5_2
|
||||
* READ_LAT_PLUS_11_4
|
||||
* READ_LAT_PLUS_3
|
||||
* READ_LAT_PLUS_13_4
|
||||
* READ_LAT_PLUS_7_2
|
||||
* READ_LAT_PLUS_15_4
|
||||
* READ_LAT_PLUS_4
|
||||
* READ_LAT_PLUS_17_4
|
||||
* READ_LAT_PLUS_9_2
|
||||
* READ_LAT_PLUS_19_4
|
||||
- write_latency: Write latency; possible values:
|
||||
1, 2, 3, 4, 5, 6, 7
|
||||
- read_to_precharge: Read to precharge; possible values:
|
||||
1, 2, 3, 4
|
||||
- write_cmd_to_write_data: Write command to write data strobe timing
|
||||
adjustment; possible values:
|
||||
* CLOCK_DELAY_0
|
||||
* CLOCK_DELAY_1_4
|
||||
* CLOCK_DELAY_1_2
|
||||
* CLOCK_DELAY_3_4
|
||||
* CLOCK_DELAY_1
|
||||
* CLOCK_DELAY_5_4
|
||||
* CLOCK_DELAY_3_2
|
||||
- minimum_cke_pulse_width: Minimum CKE pulse width; possible values:
|
||||
1, 2, 3, 4
|
||||
- four_activates_window: Window for four activates; possible values:
|
||||
1, 2, 3, 4 8, 9, 10, 11, 12,
|
||||
13, 14, 15, 16, 17, 18, 19
|
||||
- self_refresh: Self refresh (during sleep); possible values:
|
||||
* SREN_DISABLE
|
||||
* SREN_ENABLE
|
||||
- ecc: Support for ECC; possible values:
|
||||
* ECC_DISABLE
|
||||
* ECC_ENABLE
|
||||
- registered_dram: Support for registered DRAM; possible values:
|
||||
* RD_DISABLE
|
||||
* RD_ENABLE
|
||||
- sdram_type: Type of SDRAM device to be used; possible values:
|
||||
* TYPE_DDR1
|
||||
* TYPE_DDR2
|
||||
- dynamic_power_management: Dynamic power management mode; possible values:
|
||||
* DYN_PWR_DISABLE
|
||||
* DYN_PWR_ENABLE
|
||||
- databus_width: DRAM data bus width; possible values
|
||||
* DATA_BUS_WIDTH_16
|
||||
* DATA_BUS_WIDTH_32
|
||||
- nc_auto_precharge: Non-concurrent auto-precharge; possible values:
|
||||
* NCAP_DISABLE
|
||||
* NCAP_ENABLE
|
||||
- timing_2t: 2T timing; possible values:
|
||||
* TIMING_1T
|
||||
* TIMING_2T
|
||||
- bank_interleaving_ctrl: Bank (chip select) interleaving control; possible
|
||||
values:
|
||||
* INTERLEAVE_NONE
|
||||
* INTERLEAVE_1_AND_2
|
||||
- precharge_bit_8: Precharge bin 8; possible values
|
||||
* PRECHARGE_MA_10
|
||||
* PRECHARGE_MA_8
|
||||
- half_strength: Global half-strength override; possible values:
|
||||
* STRENGTH_FULL
|
||||
* STRENGTH_HALF
|
||||
- bypass_initialization: Bypass initialization; possible values:
|
||||
* INITIALIZATION_DONT_BYPASS
|
||||
* INITIALIZATION_BYPASS
|
||||
- force_self_refresh: Force self refresh; possible values:
|
||||
* MODE_NORMAL
|
||||
* MODE_REFRESH
|
||||
- dll_reset: DLL reset; possible values:
|
||||
* DLL_RESET_ENABLE
|
||||
* DLL_RESET_DISABLE
|
||||
- dqs_config: DQS configuration; possible values:
|
||||
* DQS_TRUE
|
||||
- odt_config: ODT configuration; possible values:
|
||||
* ODT_ASSERT_NEVER
|
||||
* ODT_ASSERT_WRITES
|
||||
* ODT_ASSERT_READS
|
||||
* ODT_ASSERT_ALWAYS
|
||||
- posted_refreshes: Number of posted refreshes
|
||||
1, 2, 3, 4, 5, 6, 7, 8
|
||||
- sdmode: Initial value loaded into the DDR SDRAM mode
|
||||
register
|
||||
- esdmode: Initial value loaded into the DDR SDRAM extended
|
||||
mode register
|
||||
- esdmode2: Initial value loaded into the DDR SDRAM extended
|
||||
mode 2 register
|
||||
- esdmode3: Initial value loaded into the DDR SDRAM extended
|
||||
mode 3 register
|
||||
- refresh_interval: Refresh interval; possible values:
|
||||
0 - 65535
|
||||
- precharge_interval: Precharge interval; possible values:
|
||||
0 - 16383
|
||||
|
||||
RAM module node:
|
||||
================
|
||||
|
||||
Required properties:
|
||||
- reg: A triple <cs addr size>, which consists of:
|
||||
* cs - the chipselect used to drive this RAM module
|
||||
* addr - the address where this RAM module's memory is map
|
||||
to in the global memory space
|
||||
* size - the size of the RAM module's memory in bytes
|
||||
- auto_precharge: Chip select auto-precharge; possible values:
|
||||
* AUTO_PRECHARGE_ENABLE
|
||||
* AUTO_PRECHARGE_DISABLE
|
||||
- odt_rd_cfg: ODT for reads configuration; possible values:
|
||||
* ODT_RD_NEVER
|
||||
* ODT_RD_ONLY_CURRENT
|
||||
* ODT_RD_ONLY_OTHER_CS
|
||||
* ODT_RD_ONLY_OTHER_DIMM
|
||||
* ODT_RD_ALL
|
||||
- odt_wr_cfg: ODT for writes configuration; possible values:
|
||||
* ODT_WR_NEVER
|
||||
* ODT_WR_ONLY_CURRENT
|
||||
* ODT_WR_ONLY_OTHER_CS
|
||||
* ODT_WR_ONLY_OTHER_DIMM
|
||||
* ODT_WR_ALL
|
||||
- bank_bits: Number of bank bits for SDRAM on chip select; possible
|
||||
values:
|
||||
2, 3
|
||||
- row_bits: Number of row bits for SDRAM on chip select; possible values:
|
||||
12, 13, 14
|
||||
- col_bits: Number of column bits for SDRAM on chip select; possible
|
||||
values:
|
||||
8, 9, 10, 11
|
||||
|
||||
Example:
|
||||
|
||||
memory@2000 {
|
||||
#address-cells = <2>;
|
||||
#size-cells = <1>;
|
||||
compatible = "fsl,mpc83xx-mem-controller";
|
||||
reg = <0x2000 0x1000>;
|
||||
device_type = "memory";
|
||||
u-boot,dm-pre-reloc;
|
||||
|
||||
driver_software_override = <DSO_ENABLE>;
|
||||
p_impedance_override = <DSO_P_IMPEDANCE_NOMINAL>;
|
||||
n_impedance_override = <DSO_N_IMPEDANCE_NOMINAL>;
|
||||
odt_termination_value = <ODT_TERMINATION_150_OHM>;
|
||||
ddr_type = <DDR_TYPE_DDR2_1_8_VOLT>;
|
||||
|
||||
clock_adjust = <CLOCK_ADJUST_05>;
|
||||
|
||||
read_to_write = <0>;
|
||||
write_to_read = <0>;
|
||||
read_to_read = <0>;
|
||||
write_to_write = <0>;
|
||||
active_powerdown_exit = <2>;
|
||||
precharge_powerdown_exit = <6>;
|
||||
odt_powerdown_exit = <8>;
|
||||
mode_reg_set_cycle = <2>;
|
||||
|
||||
precharge_to_activate = <2>;
|
||||
activate_to_precharge = <6>;
|
||||
activate_to_readwrite = <2>;
|
||||
mcas_latency = <CASLAT_40>;
|
||||
refresh_recovery = <17>;
|
||||
last_data_to_precharge = <2>;
|
||||
activate_to_activate = <2>;
|
||||
last_write_data_to_read = <2>;
|
||||
|
||||
additive_latency = <0>;
|
||||
mcas_to_preamble_override = <READ_LAT_PLUS_1_2>;
|
||||
write_latency = <3>;
|
||||
read_to_precharge = <2>;
|
||||
write_cmd_to_write_data = <CLOCK_DELAY_1_2>;
|
||||
minimum_cke_pulse_width = <3>;
|
||||
four_activates_window = <5>;
|
||||
|
||||
self_refresh = <SREN_ENABLE>;
|
||||
sdram_type = <TYPE_DDR2>;
|
||||
databus_width = <DATA_BUS_WIDTH_32>;
|
||||
|
||||
force_self_refresh = <MODE_NORMAL>;
|
||||
dll_reset = <DLL_RESET_ENABLE>;
|
||||
dqs_config = <DQS_TRUE>;
|
||||
odt_config = <ODT_ASSERT_READS>;
|
||||
posted_refreshes = <1>;
|
||||
|
||||
refresh_interval = <2084>;
|
||||
precharge_interval = <256>;
|
||||
|
||||
sdmode = <0x0242>;
|
||||
esdmode = <0x0440>;
|
||||
|
||||
ram@0 {
|
||||
reg = <0x0 0x0 0x8000000>;
|
||||
compatible = "nanya,nt5tu64m16hg";
|
||||
|
||||
odt_rd_cfg = <ODT_RD_NEVER>;
|
||||
odt_wr_cfg = <ODT_WR_ONLY_CURRENT>;
|
||||
bank_bits = <3>;
|
||||
row_bits = <13>;
|
||||
col_bits = <10>;
|
||||
};
|
||||
};
|
|
@ -0,0 +1,21 @@
|
|||
MPC83xx timer devices
|
||||
|
||||
MPC83xx SoCs offer a decrementer interrupt that can be used to implement delay
|
||||
functionality, and periodically triggered actions.
|
||||
|
||||
Required properties:
|
||||
- compatible: must be "fsl,mpc83xx-timer"
|
||||
- clocks: must be a reference to the system's CSB (coherent system bus) clock,
|
||||
provided by one of the "fsl,mpc83xx-clk" devices
|
||||
|
||||
Example:
|
||||
|
||||
socclocks: clocks {
|
||||
compatible = "fsl,mpc832x-clk";
|
||||
#clock-cells = <1>;
|
||||
};
|
||||
|
||||
timer {
|
||||
compatible = "fsl,mpc83xx-timer";
|
||||
clocks = <&socclocks MPC83XX_CLK_CSB>;
|
||||
};
|
11
MAINTAINERS
11
MAINTAINERS
|
@ -519,6 +519,17 @@ POWERPC MPC83XX
|
|||
M: Mario Six <mario.six@gdsys.cc>
|
||||
S: Maintained
|
||||
T: git git://git.denx.de/u-boot-mpc83xx.git
|
||||
F: drivers/ram/mpc83xx_sdram.c
|
||||
F: include/dt-bindings/memory/mpc83xx-sdram.h
|
||||
F: drivers/sysreset/sysreset_mpc83xx.c
|
||||
F: drivers/sysreset/sysreset_mpc83xx.h
|
||||
F: drivers/clk/mpc83xx_clk.c
|
||||
F: drivers/clk/mpc83xx_clk.h
|
||||
F: include/dt-bindings/clk/mpc83xx-clk.h
|
||||
F: drivers/timer/mpc83xx_timer.c
|
||||
F: drivers/cpu/mpc83xx_cpu.c
|
||||
F: drivers/cpu/mpc83xx_cpu.h
|
||||
F: drivers/misc/mpc83xx_serdes.c
|
||||
F: arch/powerpc/cpu/mpc83xx/
|
||||
F: arch/powerpc/include/asm/arch-mpc83xx/
|
||||
|
||||
|
|
|
@ -78,6 +78,7 @@ config SANDBOX
|
|||
select LZO
|
||||
select SPI
|
||||
select SUPPORT_OF_CONTROL
|
||||
imply BITREVERSE
|
||||
imply CMD_DM
|
||||
imply CMD_GETTIME
|
||||
imply CMD_HASH
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
#ifndef CONFIG_CPU_MPC83XX
|
||||
int checkcpu(void)
|
||||
{
|
||||
volatile immap_t *immr;
|
||||
|
@ -114,7 +115,9 @@ int checkcpu(void)
|
|||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_SYSRESET
|
||||
int
|
||||
do_reset (cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
|
||||
{
|
||||
|
@ -169,17 +172,17 @@ do_reset (cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
|
|||
|
||||
return 1;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Get timebase clock frequency (like cpu_clk in Hz)
|
||||
*/
|
||||
|
||||
#ifndef CONFIG_TIMER
|
||||
unsigned long get_tbclk(void)
|
||||
{
|
||||
return (gd->bus_clk + 3L) / 4L;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_WATCHDOG)
|
||||
void watchdog_reset (void)
|
||||
|
|
|
@ -464,6 +464,7 @@ static int print_83xx_arb_event(int force)
|
|||
}
|
||||
#endif /* CONFIG_DISPLAY_AER_xxxx */
|
||||
|
||||
#ifndef CONFIG_CPU_MPC83XX
|
||||
/*
|
||||
* Figure out the cause of the reset
|
||||
*/
|
||||
|
@ -505,3 +506,4 @@ int prt_83xx_rsr(void)
|
|||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -8,6 +8,8 @@
|
|||
* Author: Li Yang <leoli@freescale.com>
|
||||
*/
|
||||
|
||||
#ifndef CONFIG_MPC83XX_SERDES
|
||||
|
||||
#include <config.h>
|
||||
#include <common.h>
|
||||
#include <asm/io.h>
|
||||
|
@ -148,3 +150,5 @@ void fsl_setup_serdes(u32 offset, char proto, u32 rfcks, char vdd)
|
|||
tmp |= FSL_SRDSRSTCTL_RST;
|
||||
out_be32(regs + FSL_SRDSRSTCTL_OFFS, tmp);
|
||||
}
|
||||
|
||||
#endif /* !CONFIG_MPC83XX_SERDES */
|
||||
|
|
|
@ -10,6 +10,8 @@
|
|||
* Xianghua Xiao (X.Xiao@motorola.com)
|
||||
*/
|
||||
|
||||
#ifndef CONFIG_MPC83XX_SDRAM
|
||||
|
||||
#include <common.h>
|
||||
#include <asm/processor.h>
|
||||
#include <asm/io.h>
|
||||
|
@ -924,3 +926,5 @@ void ddr_enable_ecc(unsigned int dram_size)
|
|||
__asm__ __volatile__ ("isync");
|
||||
}
|
||||
#endif /* CONFIG_DDR_ECC */
|
||||
|
||||
#endif /* !CONFIG_MPC83XX_SDRAM */
|
||||
|
|
|
@ -6,6 +6,8 @@
|
|||
* Copyright (C) 2004-2007 Freescale Semiconductor, Inc.
|
||||
*/
|
||||
|
||||
#ifndef CONFIG_CLK_MPC83XX
|
||||
|
||||
#include <common.h>
|
||||
#include <mpc83xx.h>
|
||||
#include <command.h>
|
||||
|
@ -590,3 +592,5 @@ U_BOOT_CMD(clocks, 1, 0, do_clocks,
|
|||
"print clock configuration",
|
||||
" clocks"
|
||||
);
|
||||
|
||||
#endif
|
||||
|
|
74
arch/powerpc/include/asm/arch-mpc83xx/soc.h
Normal file
74
arch/powerpc/include/asm/arch-mpc83xx/soc.h
Normal file
|
@ -0,0 +1,74 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||
/*
|
||||
* (C) Copyright 2018
|
||||
* Mario Six, Guntermann & Drunck GmbH, mario.six@gdsys.cc
|
||||
*/
|
||||
|
||||
#ifndef _MPC83XX_SOC_H_
|
||||
#define _MPC83XX_SOC_H_
|
||||
|
||||
enum soc_type {
|
||||
SOC_MPC8308,
|
||||
SOC_MPC8309,
|
||||
SOC_MPC8313,
|
||||
SOC_MPC8315,
|
||||
SOC_MPC832X,
|
||||
SOC_MPC8349,
|
||||
SOC_MPC8360,
|
||||
SOC_MPC8379,
|
||||
};
|
||||
|
||||
bool mpc83xx_has_sdhc(int type)
|
||||
{
|
||||
return (type == SOC_MPC8308) ||
|
||||
(type == SOC_MPC8309) ||
|
||||
(type == SOC_MPC8379);
|
||||
}
|
||||
|
||||
bool mpc83xx_has_tsec(int type)
|
||||
{
|
||||
return (type == SOC_MPC8308) ||
|
||||
(type == SOC_MPC8313) ||
|
||||
(type == SOC_MPC8315) ||
|
||||
(type == SOC_MPC8349) ||
|
||||
(type == SOC_MPC8379);
|
||||
}
|
||||
|
||||
bool mpc83xx_has_pcie1(int type)
|
||||
{
|
||||
return (type == SOC_MPC8308) ||
|
||||
(type == SOC_MPC8315) ||
|
||||
(type == SOC_MPC8379);
|
||||
}
|
||||
|
||||
bool mpc83xx_has_pcie2(int type)
|
||||
{
|
||||
return (type == SOC_MPC8315) ||
|
||||
(type == SOC_MPC8379);
|
||||
}
|
||||
|
||||
bool mpc83xx_has_sata(int type)
|
||||
{
|
||||
return (type == SOC_MPC8315) ||
|
||||
(type == SOC_MPC8379);
|
||||
}
|
||||
|
||||
bool mpc83xx_has_pci(int type)
|
||||
{
|
||||
return type != SOC_MPC8308;
|
||||
}
|
||||
|
||||
bool mpc83xx_has_second_i2c(int type)
|
||||
{
|
||||
return (type != SOC_MPC8315) &&
|
||||
(type != SOC_MPC832X);
|
||||
}
|
||||
|
||||
bool mpc83xx_has_quicc_engine(int type)
|
||||
{
|
||||
return (type == SOC_MPC8309) ||
|
||||
(type == SOC_MPC832X) ||
|
||||
(type == SOC_MPC8360);
|
||||
}
|
||||
|
||||
#endif /* _MPC83XX_SOC_H_ */
|
|
@ -75,7 +75,7 @@
|
|||
/* All PPC boards must swap IDE bytes */
|
||||
#define CONFIG_IDE_SWAP_IO
|
||||
|
||||
#if defined(CONFIG_DM_SERIAL)
|
||||
#if defined(CONFIG_DM_SERIAL) && !defined(CONFIG_CLK_MPC83XX)
|
||||
/*
|
||||
* TODO: Convert this to a clock driver exists that can give us the UART
|
||||
* clock here.
|
||||
|
|
|
@ -6,6 +6,8 @@
|
|||
#ifndef __FSL_MPC83XX_SERDES_H
|
||||
#define __FSL_MPC83XX_SERDES_H
|
||||
|
||||
#ifndef CONFIG_MPC83XX_SERDES
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#define FSL_SERDES_CLK_100 (0 << 28)
|
||||
|
@ -19,4 +21,6 @@
|
|||
|
||||
extern void fsl_setup_serdes(u32 offset, char proto, u32 rfcks, char vdd);
|
||||
|
||||
#endif /* !CONFIG_MPC83XX_SERDES */
|
||||
|
||||
#endif /* __FSL_MPC83XX_SERDES_H */
|
||||
|
|
|
@ -30,6 +30,9 @@ struct arch_global_data {
|
|||
#endif
|
||||
/* TODO: sjg@chromium.org: Should these be unslgned long? */
|
||||
#if defined(CONFIG_MPC83xx)
|
||||
#ifdef CONFIG_CLK_MPC83XX
|
||||
u32 core_clk;
|
||||
#else
|
||||
/* There are other clocks in the MPC83XX */
|
||||
u32 csb_clk;
|
||||
# if defined(CONFIG_MPC8308) || defined(CONFIG_MPC831x) || \
|
||||
|
@ -62,6 +65,7 @@ struct arch_global_data {
|
|||
u32 mem_sec_clk;
|
||||
# endif /* CONFIG_MPC8360 */
|
||||
#endif
|
||||
#endif
|
||||
#if defined(CONFIG_MPC85xx) || defined(CONFIG_MPC86xx)
|
||||
u32 lbc_clk;
|
||||
void *cpu;
|
||||
|
|
|
@ -282,6 +282,24 @@ static inline void out_be32(volatile unsigned __iomem *addr, u32 val)
|
|||
#define setbits_8(addr, set) setbits(8, addr, set)
|
||||
#define clrsetbits_8(addr, clear, set) clrsetbits(8, addr, clear, set)
|
||||
|
||||
#define readb_be(addr) \
|
||||
__raw_readb((__force unsigned *)(addr))
|
||||
#define readw_be(addr) \
|
||||
be16_to_cpu(__raw_readw((__force unsigned *)(addr)))
|
||||
#define readl_be(addr) \
|
||||
be32_to_cpu(__raw_readl((__force unsigned *)(addr)))
|
||||
#define readq_be(addr) \
|
||||
be64_to_cpu(__raw_readq((__force unsigned *)(addr)))
|
||||
|
||||
#define writeb_be(val, addr) \
|
||||
__raw_writeb((val), (__force unsigned *)(addr))
|
||||
#define writew_be(val, addr) \
|
||||
__raw_writew(cpu_to_be16((val)), (__force unsigned *)(addr))
|
||||
#define writel_be(val, addr) \
|
||||
__raw_writel(cpu_to_be32((val)), (__force unsigned *)(addr))
|
||||
#define writeq_be(val, addr) \
|
||||
__raw_writeq(cpu_to_be64((val)), (__force unsigned *)(addr))
|
||||
|
||||
static inline void *phys_to_virt(phys_addr_t paddr)
|
||||
{
|
||||
#ifdef CONFIG_ADDR_MAP
|
||||
|
|
|
@ -1325,7 +1325,9 @@ void ll_puts(const char *);
|
|||
/* In misc.c */
|
||||
void _nmask_and_or_msr(unsigned long nmask, unsigned long or_val);
|
||||
|
||||
#ifndef CONFIG_CPU_MPC83XX
|
||||
int prt_83xx_rsr(void);
|
||||
#endif
|
||||
|
||||
#endif /* ndef ASSEMBLY*/
|
||||
|
||||
|
|
|
@ -17,13 +17,17 @@ endif
|
|||
|
||||
ifdef MINIMAL
|
||||
obj-y += cache.o time.o
|
||||
ifndef CONFIG_TIMER
|
||||
obj-y += ticks.o
|
||||
endif
|
||||
else
|
||||
|
||||
obj-y += ppcstring.o
|
||||
|
||||
obj-y += ppccache.o
|
||||
ifndef CONFIG_TIMER
|
||||
obj-y += ticks.o
|
||||
endif
|
||||
obj-y += reloc.o
|
||||
|
||||
obj-$(CONFIG_BAT_RW) += bat_rw.o
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#include <status_led.h>
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_MPC83XX_TIMER
|
||||
#ifdef CONFIG_SHOW_ACTIVITY
|
||||
void board_show_activity (ulong) __attribute__((weak, alias("__board_show_activity")));
|
||||
|
||||
|
@ -44,7 +45,7 @@ static __inline__ void set_dec (unsigned long val)
|
|||
if (val)
|
||||
asm volatile ("mtdec %0"::"r" (val));
|
||||
}
|
||||
|
||||
#endif /* !CONFIG_MPC83XX_TIMER */
|
||||
|
||||
void enable_interrupts (void)
|
||||
{
|
||||
|
@ -60,6 +61,7 @@ int disable_interrupts (void)
|
|||
return ((msr & MSR_EE) != 0);
|
||||
}
|
||||
|
||||
#ifndef CONFIG_MPC83XX_TIMER
|
||||
int interrupt_init (void)
|
||||
{
|
||||
/* call cpu specific function from $(CPU)/interrupts.c */
|
||||
|
@ -102,3 +104,4 @@ ulong get_timer (ulong base)
|
|||
{
|
||||
return (timestamp - base);
|
||||
}
|
||||
#endif /* !CONFIG_MPC83XX_TIMER */
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
PLATFORM_CPPFLAGS += -D__SANDBOX__ -U_FORTIFY_SOURCE
|
||||
PLATFORM_CPPFLAGS += -DCONFIG_ARCH_MAP_SYSMEM
|
||||
PLATFORM_CPPFLAGS += -fPIC
|
||||
PLATFORM_LIBS += -lrt
|
||||
|
||||
# Define this to avoid linking with SDL, which requires SDL libraries
|
||||
|
|
|
@ -297,6 +297,18 @@
|
|||
mbox-names = "other", "test";
|
||||
};
|
||||
|
||||
cpu-test1 {
|
||||
compatible = "sandbox,cpu_sandbox";
|
||||
};
|
||||
|
||||
cpu-test2 {
|
||||
compatible = "sandbox,cpu_sandbox";
|
||||
};
|
||||
|
||||
cpu-test3 {
|
||||
compatible = "sandbox,cpu_sandbox";
|
||||
};
|
||||
|
||||
misc-test {
|
||||
compatible = "sandbox,misc_sandbox";
|
||||
};
|
||||
|
|
|
@ -11,8 +11,9 @@
|
|||
|
||||
#include <common.h>
|
||||
#include <console.h>
|
||||
#include <environment.h>
|
||||
#include <cpu.h>
|
||||
#include <dm.h>
|
||||
#include <environment.h>
|
||||
#include <fdtdec.h>
|
||||
#include <fs.h>
|
||||
#include <i2c.h>
|
||||
|
@ -24,6 +25,7 @@
|
|||
#include <relocate.h>
|
||||
#include <spi.h>
|
||||
#include <status_led.h>
|
||||
#include <sysreset.h>
|
||||
#include <timer.h>
|
||||
#include <trace.h>
|
||||
#include <video.h>
|
||||
|
@ -140,6 +142,57 @@ static int display_text_info(void)
|
|||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SYSRESET
|
||||
static int print_resetinfo(void)
|
||||
{
|
||||
struct udevice *dev;
|
||||
char status[256];
|
||||
int ret;
|
||||
|
||||
ret = uclass_first_device_err(UCLASS_SYSRESET, &dev);
|
||||
if (ret) {
|
||||
debug("%s: No sysreset device found (error: %d)\n",
|
||||
__func__, ret);
|
||||
/* Not all boards have sysreset drivers available during early
|
||||
* boot, so don't fail if one can't be found.
|
||||
*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!sysreset_get_status(dev, status, sizeof(status)))
|
||||
printf("%s", status);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_DISPLAY_CPUINFO) && CONFIG_IS_ENABLED(CPU)
|
||||
static int print_cpuinfo(void)
|
||||
{
|
||||
struct udevice *dev;
|
||||
char desc[512];
|
||||
int ret;
|
||||
|
||||
ret = uclass_first_device_err(UCLASS_CPU, &dev);
|
||||
if (ret) {
|
||||
debug("%s: Could not get CPU device (err = %d)\n",
|
||||
__func__, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = cpu_get_desc(dev, desc, sizeof(desc));
|
||||
if (ret) {
|
||||
debug("%s: Could not get CPU description (err = %d)\n",
|
||||
dev->name, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
printf("%s", desc);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int announce_dram_init(void)
|
||||
{
|
||||
puts("DRAM: ");
|
||||
|
@ -790,6 +843,9 @@ static const init_fnc_t init_sequence_f[] = {
|
|||
#if defined(CONFIG_PPC) || defined(CONFIG_SH) || defined(CONFIG_X86)
|
||||
checkcpu,
|
||||
#endif
|
||||
#if defined(CONFIG_SYSRESET)
|
||||
print_resetinfo,
|
||||
#endif
|
||||
#if defined(CONFIG_DISPLAY_CPUINFO)
|
||||
print_cpuinfo, /* display cpu info (and speed) */
|
||||
#endif
|
||||
|
|
|
@ -107,4 +107,10 @@ config ICS8N3QV01
|
|||
Crystal Oscillator). The output frequency can be programmed via an
|
||||
I2C interface.
|
||||
|
||||
config CLK_MPC83XX
|
||||
bool "Enable MPC83xx clock driver"
|
||||
depends on CLK
|
||||
help
|
||||
Support for the clock driver of the MPC83xx series of SoCs.
|
||||
|
||||
endmenu
|
||||
|
|
|
@ -18,6 +18,7 @@ obj-$(CONFIG_CLK_BCM6345) += clk_bcm6345.o
|
|||
obj-$(CONFIG_CLK_BOSTON) += clk_boston.o
|
||||
obj-$(CONFIG_CLK_EXYNOS) += exynos/
|
||||
obj-$(CONFIG_CLK_HSDK) += clk-hsdk-cgu.o
|
||||
obj-$(CONFIG_CLK_MPC83XX) += mpc83xx_clk.o
|
||||
obj-$(CONFIG_CLK_OWL) += owl/
|
||||
obj-$(CONFIG_CLK_RENESAS) += renesas/
|
||||
obj-$(CONFIG_CLK_STM32F) += clk_stm32f.o
|
||||
|
|
410
drivers/clk/mpc83xx_clk.c
Normal file
410
drivers/clk/mpc83xx_clk.c
Normal file
|
@ -0,0 +1,410 @@
|
|||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* (C) Copyright 2017
|
||||
* Mario Six, Guntermann & Drunck GmbH, mario.six@gdsys.cc
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <clk-uclass.h>
|
||||
#include <dm.h>
|
||||
#include <dm/lists.h>
|
||||
#include <dt-bindings/clk/mpc83xx-clk.h>
|
||||
#include <asm/arch/soc.h>
|
||||
|
||||
#include "mpc83xx_clk.h"
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
/**
|
||||
* struct mpc83xx_clk_priv - Private data structure for the MPC83xx clock
|
||||
* driver
|
||||
* @speed: Array containing the speed values of all system clocks (initialized
|
||||
* once, then only read back)
|
||||
*/
|
||||
struct mpc83xx_clk_priv {
|
||||
u32 speed[MPC83XX_CLK_COUNT];
|
||||
};
|
||||
|
||||
/**
|
||||
* is_clk_valid() - Check if clock ID is valid for given clock device
|
||||
* @clk: The clock device for which to check a clock ID
|
||||
* @id: The clock ID to check
|
||||
*
|
||||
* Return: true if clock ID is valid for clock device, false if not
|
||||
*/
|
||||
static inline bool is_clk_valid(struct udevice *clk, int id)
|
||||
{
|
||||
ulong type = dev_get_driver_data(clk);
|
||||
|
||||
switch (id) {
|
||||
case MPC83XX_CLK_MEM:
|
||||
return true;
|
||||
case MPC83XX_CLK_MEM_SEC:
|
||||
return type == SOC_MPC8360;
|
||||
case MPC83XX_CLK_ENC:
|
||||
return (type == SOC_MPC8308) || (type == SOC_MPC8309);
|
||||
case MPC83XX_CLK_I2C1:
|
||||
return true;
|
||||
case MPC83XX_CLK_TDM:
|
||||
return type == SOC_MPC8315;
|
||||
case MPC83XX_CLK_SDHC:
|
||||
return mpc83xx_has_sdhc(type);
|
||||
case MPC83XX_CLK_TSEC1:
|
||||
case MPC83XX_CLK_TSEC2:
|
||||
return mpc83xx_has_tsec(type);
|
||||
case MPC83XX_CLK_USBDR:
|
||||
return type == SOC_MPC8360;
|
||||
case MPC83XX_CLK_USBMPH:
|
||||
return type == SOC_MPC8349;
|
||||
case MPC83XX_CLK_PCIEXP1:
|
||||
return mpc83xx_has_pcie1(type);
|
||||
case MPC83XX_CLK_PCIEXP2:
|
||||
return mpc83xx_has_pcie2(type);
|
||||
case MPC83XX_CLK_SATA:
|
||||
return mpc83xx_has_sata(type);
|
||||
case MPC83XX_CLK_DMAC:
|
||||
return (type == SOC_MPC8308) || (type == SOC_MPC8309);
|
||||
case MPC83XX_CLK_PCI:
|
||||
return mpc83xx_has_pci(type);
|
||||
case MPC83XX_CLK_CSB:
|
||||
return true;
|
||||
case MPC83XX_CLK_I2C2:
|
||||
return mpc83xx_has_second_i2c(type);
|
||||
case MPC83XX_CLK_QE:
|
||||
case MPC83XX_CLK_BRG:
|
||||
return mpc83xx_has_quicc_engine(type) && (type != SOC_MPC8309);
|
||||
case MPC83XX_CLK_LCLK:
|
||||
case MPC83XX_CLK_LBIU:
|
||||
case MPC83XX_CLK_CORE:
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* init_single_clk() - Initialize a clock with a given ID
|
||||
* @dev: The clock device for which to initialize the clock
|
||||
* @clk: The clock ID
|
||||
*
|
||||
* The clock speed is read from the hardware's registers, and stored in the
|
||||
* private data structure of the driver. From there it is only retrieved, and
|
||||
* not set.
|
||||
*
|
||||
* Return: 0 if OK, -ve on error
|
||||
*/
|
||||
static int init_single_clk(struct udevice *dev, int clk)
|
||||
{
|
||||
struct mpc83xx_clk_priv *priv = dev_get_priv(dev);
|
||||
immap_t *im = (immap_t *)CONFIG_SYS_IMMR;
|
||||
ulong type = dev_get_driver_data(dev);
|
||||
struct clk_mode mode;
|
||||
ulong mask;
|
||||
u32 csb_clk = get_csb_clk(im);
|
||||
int ret;
|
||||
|
||||
ret = retrieve_mode(clk, type, &mode);
|
||||
if (ret) {
|
||||
debug("%s: Could not retrieve mode for clk %d (ret = %d)\n",
|
||||
dev->name, clk, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (mode.type == TYPE_INVALID) {
|
||||
debug("%s: clock %d invalid\n", dev->name, clk);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (mode.type == TYPE_SCCR_STANDARD) {
|
||||
mask = GENMASK(31 - mode.low, 31 - mode.high);
|
||||
|
||||
switch (sccr_field(im, mask)) {
|
||||
case 0:
|
||||
priv->speed[clk] = 0;
|
||||
break;
|
||||
case 1:
|
||||
priv->speed[clk] = csb_clk;
|
||||
break;
|
||||
case 2:
|
||||
priv->speed[clk] = csb_clk / 2;
|
||||
break;
|
||||
case 3:
|
||||
priv->speed[clk] = csb_clk / 3;
|
||||
break;
|
||||
default:
|
||||
priv->speed[clk] = 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (mode.type == TYPE_SPMR_DIRECT_MULTIPLY) {
|
||||
mask = GENMASK(31 - mode.low, 31 - mode.high);
|
||||
|
||||
priv->speed[clk] = csb_clk * (1 + sccr_field(im, mask));
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (clk == MPC83XX_CLK_CSB || clk == MPC83XX_CLK_I2C2) {
|
||||
priv->speed[clk] = csb_clk; /* i2c-2 clk is equal to csb clk */
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (clk == MPC83XX_CLK_QE || clk == MPC83XX_CLK_BRG) {
|
||||
u32 pci_sync_in = get_pci_sync_in(im);
|
||||
u32 qepmf = spmr_field(im, SPMR_CEPMF);
|
||||
u32 qepdf = spmr_field(im, SPMR_CEPDF);
|
||||
u32 qe_clk = (pci_sync_in * qepmf) / (1 + qepdf);
|
||||
|
||||
if (clk == MPC83XX_CLK_QE)
|
||||
priv->speed[clk] = qe_clk;
|
||||
else
|
||||
priv->speed[clk] = qe_clk / 2;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (clk == MPC83XX_CLK_LCLK || clk == MPC83XX_CLK_LBIU) {
|
||||
u32 lbiu_clk = csb_clk *
|
||||
(1 + spmr_field(im, SPMR_LBIUCM));
|
||||
u32 clkdiv = lcrr_field(im, LCRR_CLKDIV);
|
||||
|
||||
if (clk == MPC83XX_CLK_LBIU)
|
||||
priv->speed[clk] = lbiu_clk;
|
||||
|
||||
switch (clkdiv) {
|
||||
case 2:
|
||||
case 4:
|
||||
case 8:
|
||||
priv->speed[clk] = lbiu_clk / clkdiv;
|
||||
break;
|
||||
default:
|
||||
/* unknown lcrr */
|
||||
priv->speed[clk] = 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (clk == MPC83XX_CLK_CORE) {
|
||||
u8 corepll = spmr_field(im, SPMR_COREPLL);
|
||||
u32 corecnf_tab_index = ((corepll & 0x1F) << 2) |
|
||||
((corepll & 0x60) >> 5);
|
||||
|
||||
if (corecnf_tab_index > (ARRAY_SIZE(corecnf_tab))) {
|
||||
debug("%s: Core configuration index %02x too high; possible wrong value",
|
||||
dev->name, corecnf_tab_index);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
switch (corecnf_tab[corecnf_tab_index].core_csb_ratio) {
|
||||
case RAT_BYP:
|
||||
case RAT_1_TO_1:
|
||||
priv->speed[clk] = csb_clk;
|
||||
break;
|
||||
case RAT_1_5_TO_1:
|
||||
priv->speed[clk] = (3 * csb_clk) / 2;
|
||||
break;
|
||||
case RAT_2_TO_1:
|
||||
priv->speed[clk] = 2 * csb_clk;
|
||||
break;
|
||||
case RAT_2_5_TO_1:
|
||||
priv->speed[clk] = (5 * csb_clk) / 2;
|
||||
break;
|
||||
case RAT_3_TO_1:
|
||||
priv->speed[clk] = 3 * csb_clk;
|
||||
break;
|
||||
default:
|
||||
/* unknown core to csb ratio */
|
||||
priv->speed[clk] = 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Unknown clk value -> error */
|
||||
debug("%s: clock %d invalid\n", dev->name, clk);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/**
|
||||
* init_all_clks() - Initialize all clocks of a clock device
|
||||
* @dev: The clock device whose clocks should be initialized
|
||||
*
|
||||
* Return: 0 if OK, -ve on error
|
||||
*/
|
||||
static inline int init_all_clks(struct udevice *dev)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < MPC83XX_CLK_COUNT; i++) {
|
||||
int ret;
|
||||
|
||||
if (!is_clk_valid(dev, i))
|
||||
continue;
|
||||
|
||||
ret = init_single_clk(dev, i);
|
||||
if (ret) {
|
||||
debug("%s: Failed to initialize %s clock\n",
|
||||
dev->name, names[i]);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mpc83xx_clk_request(struct clk *clock)
|
||||
{
|
||||
/* Reject requests of clocks that are not available */
|
||||
if (is_clk_valid(clock->dev, clock->id))
|
||||
return 0;
|
||||
else
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
static ulong mpc83xx_clk_get_rate(struct clk *clk)
|
||||
{
|
||||
struct mpc83xx_clk_priv *priv = dev_get_priv(clk->dev);
|
||||
|
||||
if (clk->id >= MPC83XX_CLK_COUNT) {
|
||||
debug("%s: clock index %lu invalid\n", __func__, clk->id);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return priv->speed[clk->id];
|
||||
}
|
||||
|
||||
int get_clocks(void)
|
||||
{
|
||||
/* Empty implementation to keep the prototype in common.h happy */
|
||||
return 0;
|
||||
}
|
||||
|
||||
int get_serial_clock(void)
|
||||
{
|
||||
struct mpc83xx_clk_priv *priv;
|
||||
struct udevice *clk;
|
||||
int ret;
|
||||
|
||||
ret = uclass_first_device_err(UCLASS_CLK, &clk);
|
||||
if (ret) {
|
||||
debug("%s: Could not get clock device\n", __func__);
|
||||
return ret;
|
||||
}
|
||||
|
||||
priv = dev_get_priv(clk);
|
||||
|
||||
return priv->speed[MPC83XX_CLK_CSB];
|
||||
}
|
||||
|
||||
const struct clk_ops mpc83xx_clk_ops = {
|
||||
.request = mpc83xx_clk_request,
|
||||
.get_rate = mpc83xx_clk_get_rate,
|
||||
};
|
||||
|
||||
static const struct udevice_id mpc83xx_clk_match[] = {
|
||||
{ .compatible = "fsl,mpc8308-clk", .data = SOC_MPC8308 },
|
||||
{ .compatible = "fsl,mpc8309-clk", .data = SOC_MPC8309 },
|
||||
{ .compatible = "fsl,mpc8313-clk", .data = SOC_MPC8313 },
|
||||
{ .compatible = "fsl,mpc8315-clk", .data = SOC_MPC8315 },
|
||||
{ .compatible = "fsl,mpc832x-clk", .data = SOC_MPC832X },
|
||||
{ .compatible = "fsl,mpc8349-clk", .data = SOC_MPC8349 },
|
||||
{ .compatible = "fsl,mpc8360-clk", .data = SOC_MPC8360 },
|
||||
{ .compatible = "fsl,mpc8379-clk", .data = SOC_MPC8379 },
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
|
||||
static int mpc83xx_clk_probe(struct udevice *dev)
|
||||
{
|
||||
struct mpc83xx_clk_priv *priv = dev_get_priv(dev);
|
||||
ulong type;
|
||||
int ret;
|
||||
|
||||
ret = init_all_clks(dev);
|
||||
if (ret) {
|
||||
debug("%s: Could not initialize all clocks (ret = %d)\n",
|
||||
dev->name, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
type = dev_get_driver_data(dev);
|
||||
|
||||
if (mpc83xx_has_sdhc(type))
|
||||
gd->arch.sdhc_clk = priv->speed[MPC83XX_CLK_SDHC];
|
||||
|
||||
gd->arch.core_clk = priv->speed[MPC83XX_CLK_CORE];
|
||||
gd->arch.i2c1_clk = priv->speed[MPC83XX_CLK_I2C1];
|
||||
if (mpc83xx_has_second_i2c(type))
|
||||
gd->arch.i2c2_clk = priv->speed[MPC83XX_CLK_I2C2];
|
||||
|
||||
gd->mem_clk = priv->speed[MPC83XX_CLK_MEM];
|
||||
|
||||
if (mpc83xx_has_pci(type))
|
||||
gd->pci_clk = priv->speed[MPC83XX_CLK_PCI];
|
||||
|
||||
gd->cpu_clk = priv->speed[MPC83XX_CLK_CORE];
|
||||
gd->bus_clk = priv->speed[MPC83XX_CLK_CSB];
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mpc83xx_clk_bind(struct udevice *dev)
|
||||
{
|
||||
int ret;
|
||||
struct udevice *sys_child;
|
||||
|
||||
/*
|
||||
* Since there is no corresponding device tree entry, and since the
|
||||
* clock driver has to be present in either case, bind the sysreset
|
||||
* driver here.
|
||||
*/
|
||||
ret = device_bind_driver(dev, "mpc83xx_sysreset", "sysreset",
|
||||
&sys_child);
|
||||
if (ret)
|
||||
debug("%s: No sysreset driver: ret=%d\n",
|
||||
dev->name, ret);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
U_BOOT_DRIVER(mpc83xx_clk) = {
|
||||
.name = "mpc83xx_clk",
|
||||
.id = UCLASS_CLK,
|
||||
.of_match = mpc83xx_clk_match,
|
||||
.ops = &mpc83xx_clk_ops,
|
||||
.probe = mpc83xx_clk_probe,
|
||||
.priv_auto_alloc_size = sizeof(struct mpc83xx_clk_priv),
|
||||
.bind = mpc83xx_clk_bind,
|
||||
};
|
||||
|
||||
static int do_clocks(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
|
||||
{
|
||||
int i;
|
||||
char buf[32];
|
||||
struct udevice *clk;
|
||||
int ret;
|
||||
struct mpc83xx_clk_priv *priv;
|
||||
|
||||
ret = uclass_first_device_err(UCLASS_CLK, &clk);
|
||||
if (ret) {
|
||||
debug("%s: Could not get clock device\n", __func__);
|
||||
return ret;
|
||||
}
|
||||
|
||||
for (i = 0; i < MPC83XX_CLK_COUNT; i++) {
|
||||
if (!is_clk_valid(clk, i))
|
||||
continue;
|
||||
|
||||
priv = dev_get_priv(clk);
|
||||
|
||||
printf("%s = %s MHz\n", names[i], strmhz(buf, priv->speed[i]));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
U_BOOT_CMD(clocks, 1, 1, do_clocks,
|
||||
"display values of SoC's clocks",
|
||||
""
|
||||
);
|
379
drivers/clk/mpc83xx_clk.h
Normal file
379
drivers/clk/mpc83xx_clk.h
Normal file
|
@ -0,0 +1,379 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||
/*
|
||||
* (C) Copyright 2018
|
||||
* Mario Six, Guntermann & Drunck GmbH, mario.six@gdsys.cc
|
||||
*/
|
||||
|
||||
/**
|
||||
* enum ratio - Description of a core clock ratio
|
||||
* @RAT_UNK: Unknown ratio
|
||||
* @RAT_BYP: Bypass
|
||||
* @RAT_1_TO_8: Ratio 1:8
|
||||
* @RAT_1_TO_4: Ratio 1:4
|
||||
* @RAT_1_TO_2: Ratio 1:2
|
||||
* @RAT_1_TO_1: Ratio 1:1
|
||||
* @RAT_1_5_TO_1: Ratio 1.5:1
|
||||
* @RAT_2_TO_1: Ratio 2:1
|
||||
* @RAT_2_5_TO_1: Ratio 2.5:1
|
||||
* @RAT_3_TO_1: Ratio 3:1
|
||||
*/
|
||||
enum ratio {
|
||||
RAT_UNK,
|
||||
RAT_BYP,
|
||||
RAT_1_TO_8,
|
||||
RAT_1_TO_4,
|
||||
RAT_1_TO_2,
|
||||
RAT_1_TO_1,
|
||||
RAT_1_5_TO_1,
|
||||
RAT_2_TO_1,
|
||||
RAT_2_5_TO_1,
|
||||
RAT_3_TO_1
|
||||
};
|
||||
|
||||
/**
|
||||
* struct corecnf - Description for a core clock configuration
|
||||
* @core_csb_ratio: Core clock frequency to CSB clock frequency ratio
|
||||
* @vco_divider: VCO divider (Core VCO frequency = Core frequency * VCO divider)
|
||||
*/
|
||||
struct corecnf {
|
||||
int core_csb_ratio;
|
||||
int vco_divider;
|
||||
};
|
||||
|
||||
/*
|
||||
* Table with all valid Core CSB frequency ratio / VCO divider combinations as
|
||||
* indexed by the COREPLL field of the SPMR
|
||||
*/
|
||||
static const struct corecnf corecnf_tab[] = {
|
||||
{RAT_BYP, RAT_BYP}, /* 0x00 */
|
||||
{RAT_BYP, RAT_BYP}, /* 0x01 */
|
||||
{RAT_BYP, RAT_BYP}, /* 0x02 */
|
||||
{RAT_BYP, RAT_BYP}, /* 0x03 */
|
||||
{RAT_BYP, RAT_BYP}, /* 0x04 */
|
||||
{RAT_BYP, RAT_BYP}, /* 0x05 */
|
||||
{RAT_BYP, RAT_BYP}, /* 0x06 */
|
||||
{RAT_BYP, RAT_BYP}, /* 0x07 */
|
||||
{RAT_1_TO_1, RAT_1_TO_2}, /* 0x08 */
|
||||
{RAT_1_TO_1, RAT_1_TO_4}, /* 0x09 */
|
||||
{RAT_1_TO_1, RAT_1_TO_8}, /* 0x0A */
|
||||
{RAT_1_TO_1, RAT_1_TO_8}, /* 0x0B */
|
||||
{RAT_1_5_TO_1, RAT_1_TO_2}, /* 0x0C */
|
||||
{RAT_1_5_TO_1, RAT_1_TO_4}, /* 0x0D */
|
||||
{RAT_1_5_TO_1, RAT_1_TO_8}, /* 0x0E */
|
||||
{RAT_1_5_TO_1, RAT_1_TO_8}, /* 0x0F */
|
||||
{RAT_2_TO_1, RAT_1_TO_2}, /* 0x10 */
|
||||
{RAT_2_TO_1, RAT_1_TO_4}, /* 0x11 */
|
||||
{RAT_2_TO_1, RAT_1_TO_8}, /* 0x12 */
|
||||
{RAT_2_TO_1, RAT_1_TO_8}, /* 0x13 */
|
||||
{RAT_2_5_TO_1, RAT_1_TO_2}, /* 0x14 */
|
||||
{RAT_2_5_TO_1, RAT_1_TO_4}, /* 0x15 */
|
||||
{RAT_2_5_TO_1, RAT_1_TO_8}, /* 0x16 */
|
||||
{RAT_2_5_TO_1, RAT_1_TO_8}, /* 0x17 */
|
||||
{RAT_3_TO_1, RAT_1_TO_2}, /* 0x18 */
|
||||
{RAT_3_TO_1, RAT_1_TO_4}, /* 0x19 */
|
||||
{RAT_3_TO_1, RAT_1_TO_8}, /* 0x1A */
|
||||
{RAT_3_TO_1, RAT_1_TO_8}, /* 0x1B */
|
||||
};
|
||||
|
||||
/**
|
||||
* enum reg_type - Register to read a field from
|
||||
* @REG_SCCR: Use the SCCR register
|
||||
* @REG_SPMR: Use the SPMR register
|
||||
*/
|
||||
enum reg_type {
|
||||
REG_SCCR,
|
||||
REG_SPMR,
|
||||
};
|
||||
|
||||
/**
|
||||
* enum mode_type - Description of how to read a specific frequency value
|
||||
* @TYPE_INVALID: Unknown type, will provoke error
|
||||
* @TYPE_SCCR_STANDARD: Read a field from the SCCR register, and use it
|
||||
* as a divider for the CSB clock to compute the
|
||||
* frequency
|
||||
* @TYPE_SCCR_ONOFF: The field describes a bit flag that can turn the
|
||||
* clock on or off
|
||||
* @TYPE_SPMR_DIRECT_MULTIPLY: Read a field from the SPMR register, and use it
|
||||
* as a multiplier for the CSB clock to compute the
|
||||
* frequency
|
||||
* @TYPE_SPECIAL: The frequency is calculated in a non-standard way
|
||||
*/
|
||||
enum mode_type {
|
||||
TYPE_INVALID = 0,
|
||||
TYPE_SCCR_STANDARD,
|
||||
TYPE_SCCR_ONOFF,
|
||||
TYPE_SPMR_DIRECT_MULTIPLY,
|
||||
TYPE_SPECIAL,
|
||||
};
|
||||
|
||||
/* Map of each clock index to its human-readable name */
|
||||
static const char * const names[] = {
|
||||
[MPC83XX_CLK_CORE] = "Core",
|
||||
[MPC83XX_CLK_CSB] = "Coherent System Bus",
|
||||
[MPC83XX_CLK_QE] = "QE",
|
||||
[MPC83XX_CLK_BRG] = "BRG",
|
||||
[MPC83XX_CLK_LBIU] = "Local Bus Controller",
|
||||
[MPC83XX_CLK_LCLK] = "Local Bus",
|
||||
[MPC83XX_CLK_MEM] = "DDR",
|
||||
[MPC83XX_CLK_MEM_SEC] = "DDR Secondary",
|
||||
[MPC83XX_CLK_ENC] = "SEC",
|
||||
[MPC83XX_CLK_I2C1] = "I2C1",
|
||||
[MPC83XX_CLK_I2C2] = "I2C2",
|
||||
[MPC83XX_CLK_TDM] = "TDM",
|
||||
[MPC83XX_CLK_SDHC] = "SDHC",
|
||||
[MPC83XX_CLK_TSEC1] = "TSEC1",
|
||||
[MPC83XX_CLK_TSEC2] = "TSEC2",
|
||||
[MPC83XX_CLK_USBDR] = "USB DR",
|
||||
[MPC83XX_CLK_USBMPH] = "USB MPH",
|
||||
[MPC83XX_CLK_PCIEXP1] = "PCIEXP1",
|
||||
[MPC83XX_CLK_PCIEXP2] = "PCIEXP2",
|
||||
[MPC83XX_CLK_SATA] = "SATA",
|
||||
[MPC83XX_CLK_DMAC] = "DMAC",
|
||||
[MPC83XX_CLK_PCI] = "PCI",
|
||||
};
|
||||
|
||||
/**
|
||||
* struct clk_mode - Structure for clock mode descriiptions
|
||||
* @low: The low bit of the data field to read for this mode (may not apply to
|
||||
* some modes)
|
||||
* @high: The high bit of the data field to read for this mode (may not apply to
|
||||
* some modes)
|
||||
* @type: The type of the mode description (one of enum mode_type)
|
||||
*/
|
||||
struct clk_mode {
|
||||
u8 low;
|
||||
u8 high;
|
||||
int type;
|
||||
};
|
||||
|
||||
/**
|
||||
* set_mode() - Build a clock mode description from data
|
||||
* @mode: The clock mode description to be filled out
|
||||
* @low: The low bit of the data field to read for this mode (may not apply to
|
||||
* some modes)
|
||||
* @high: The high bit of the data field to read for this mode (may not apply to
|
||||
* some modes)
|
||||
* @type: The type of the mode description (one of enum mode_type)
|
||||
*
|
||||
* Clock mode descriptions are a succinct description of how to read a specific
|
||||
* clock's rate from the hardware; usually by reading a specific field of a
|
||||
* register, such a s the SCCR register, but some types use different methods
|
||||
* for obtaining the clock rate.
|
||||
*/
|
||||
static void set_mode(struct clk_mode *mode, u8 low, u8 high, int type)
|
||||
{
|
||||
mode->low = low;
|
||||
mode->high = high;
|
||||
mode->type = type;
|
||||
}
|
||||
|
||||
/**
|
||||
* retrieve_mode() - Get the clock mode description for a specific clock
|
||||
* @clk: The identifier of the clock for which the clock description should
|
||||
* be retrieved
|
||||
* @soc_type: The type of MPC83xx SoC for which the clock description should be
|
||||
* retrieved
|
||||
* @mode: Pointer to a clk_mode structure to be filled with data for the
|
||||
* clock
|
||||
*
|
||||
* Since some clock rate are stored in different places on different MPC83xx
|
||||
* SoCs, the SoC type has to be supplied along with the clock's identifier.
|
||||
*
|
||||
* Return: 0 if OK, -ve on error
|
||||
*/
|
||||
static int retrieve_mode(int clk, int soc_type, struct clk_mode *mode)
|
||||
{
|
||||
switch (clk) {
|
||||
case MPC83XX_CLK_CORE:
|
||||
case MPC83XX_CLK_CSB:
|
||||
case MPC83XX_CLK_QE:
|
||||
case MPC83XX_CLK_BRG:
|
||||
case MPC83XX_CLK_LCLK:
|
||||
case MPC83XX_CLK_I2C2:
|
||||
set_mode(mode, 0, 0, TYPE_SPECIAL);
|
||||
break;
|
||||
case MPC83XX_CLK_MEM:
|
||||
set_mode(mode, 1, 1, TYPE_SPMR_DIRECT_MULTIPLY);
|
||||
break;
|
||||
case MPC83XX_CLK_LBIU:
|
||||
case MPC83XX_CLK_MEM_SEC:
|
||||
set_mode(mode, 0, 0, TYPE_SPMR_DIRECT_MULTIPLY);
|
||||
break;
|
||||
case MPC83XX_CLK_TSEC1:
|
||||
set_mode(mode, 0, 1, TYPE_SCCR_STANDARD);
|
||||
break;
|
||||
case MPC83XX_CLK_TSEC2:
|
||||
if (soc_type == SOC_MPC8313) /* I2C and TSEC2 are the same register */
|
||||
set_mode(mode, 2, 3, TYPE_SCCR_STANDARD);
|
||||
else /* FIXME(mario.six@gdsys.cc): This has separate enable/disable bit! */
|
||||
set_mode(mode, 0, 1, TYPE_SCCR_STANDARD);
|
||||
break;
|
||||
case MPC83XX_CLK_SDHC:
|
||||
set_mode(mode, 4, 5, TYPE_SCCR_STANDARD);
|
||||
break;
|
||||
case MPC83XX_CLK_ENC:
|
||||
set_mode(mode, 6, 7, TYPE_SCCR_STANDARD);
|
||||
break;
|
||||
case MPC83XX_CLK_I2C1:
|
||||
if (soc_type == SOC_MPC8349)
|
||||
set_mode(mode, 2, 3, TYPE_SCCR_STANDARD);
|
||||
else /* I2C and ENC are the same register */
|
||||
set_mode(mode, 6, 7, TYPE_SCCR_STANDARD);
|
||||
break;
|
||||
case MPC83XX_CLK_PCIEXP1:
|
||||
set_mode(mode, 10, 11, TYPE_SCCR_STANDARD);
|
||||
break;
|
||||
case MPC83XX_CLK_PCIEXP2:
|
||||
set_mode(mode, 12, 13, TYPE_SCCR_STANDARD);
|
||||
break;
|
||||
case MPC83XX_CLK_USBDR:
|
||||
if (soc_type == SOC_MPC8313 || soc_type == SOC_MPC8349)
|
||||
set_mode(mode, 10, 11, TYPE_SCCR_STANDARD);
|
||||
else
|
||||
set_mode(mode, 8, 9, TYPE_SCCR_STANDARD);
|
||||
break;
|
||||
case MPC83XX_CLK_USBMPH:
|
||||
set_mode(mode, 8, 9, TYPE_SCCR_STANDARD);
|
||||
break;
|
||||
case MPC83XX_CLK_PCI:
|
||||
set_mode(mode, 15, 15, TYPE_SCCR_ONOFF);
|
||||
break;
|
||||
case MPC83XX_CLK_DMAC:
|
||||
set_mode(mode, 26, 27, TYPE_SCCR_STANDARD);
|
||||
break;
|
||||
case MPC83XX_CLK_SATA:
|
||||
/* FIXME(mario.six@gdsys.cc): All SATA controllers must have the same clock ratio */
|
||||
if (soc_type == SOC_MPC8379) {
|
||||
set_mode(mode, 24, 25, TYPE_SCCR_STANDARD);
|
||||
set_mode(mode, 26, 27, TYPE_SCCR_STANDARD);
|
||||
set_mode(mode, 28, 29, TYPE_SCCR_STANDARD);
|
||||
set_mode(mode, 30, 31, TYPE_SCCR_STANDARD);
|
||||
} else {
|
||||
set_mode(mode, 18, 19, TYPE_SCCR_STANDARD);
|
||||
set_mode(mode, 20, 21, TYPE_SCCR_STANDARD);
|
||||
}
|
||||
break;
|
||||
case MPC83XX_CLK_TDM:
|
||||
set_mode(mode, 26, 27, TYPE_SCCR_STANDARD);
|
||||
break;
|
||||
default:
|
||||
debug("%s: Unknown clock type %d on soc type %d\n",
|
||||
__func__, clk, soc_type);
|
||||
set_mode(mode, 0, 0, TYPE_INVALID);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* get_spmr() - Read the SPMR (System PLL Mode Register)
|
||||
* @im: Pointer to the MPC83xx main register map in question
|
||||
*
|
||||
* Return: The SPMR value as a 32-bit number.
|
||||
*/
|
||||
static inline u32 get_spmr(immap_t *im)
|
||||
{
|
||||
u32 res = in_be32(&im->clk.spmr);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* get_sccr() - Read the SCCR (System Clock Control Register)
|
||||
* @im: Pointer to the MPC83xx main register map in question
|
||||
*
|
||||
* Return: The SCCR value as a 32-bit number.
|
||||
*/
|
||||
static inline u32 get_sccr(immap_t *im)
|
||||
{
|
||||
u32 res = in_be32(&im->clk.sccr);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* get_lcrr() - Read the LCRR (Clock Ratio Register)
|
||||
* @im: Pointer to the MPC83xx main register map in question
|
||||
*
|
||||
* Return: The LCRR value as a 32-bit number.
|
||||
*/
|
||||
static inline u32 get_lcrr(immap_t *im)
|
||||
{
|
||||
u32 res = in_be32(&im->im_lbc.lcrr);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* get_pci_sync_in() - Read the PCI synchronization clock speed
|
||||
* @im: Pointer to the MPC83xx main register map in question
|
||||
*
|
||||
* Return: The PCI synchronization clock speed value as a 32-bit number.
|
||||
*/
|
||||
static inline u32 get_pci_sync_in(immap_t *im)
|
||||
{
|
||||
u8 clkin_div;
|
||||
|
||||
clkin_div = (get_spmr(im) & SPMR_CKID) >> SPMR_CKID_SHIFT;
|
||||
return CONFIG_SYS_CLK_FREQ / (1 + clkin_div);
|
||||
}
|
||||
|
||||
/**
|
||||
* get_csb_clk() - Read the CSB (Coheren System Bus) clock speed
|
||||
* @im: Pointer to the MPC83xx main register map in question
|
||||
*
|
||||
* Return: The CSB clock speed value as a 32-bit number.
|
||||
*/
|
||||
static inline u32 get_csb_clk(immap_t *im)
|
||||
{
|
||||
u8 spmf;
|
||||
|
||||
spmf = (get_spmr(im) & SPMR_SPMF) >> SPMR_SPMF_SHIFT;
|
||||
return CONFIG_SYS_CLK_FREQ * spmf;
|
||||
}
|
||||
|
||||
/**
|
||||
* spmr_field() - Read a specific SPMR field
|
||||
* @im: Pointer to the MPC83xx main register map in question
|
||||
* @mask: A bitmask that describes the bitfield to be read
|
||||
*
|
||||
* Return: The value of the bit field as a 32-bit number.
|
||||
*/
|
||||
static inline uint spmr_field(immap_t *im, u32 mask)
|
||||
{
|
||||
/* Extract shift from bitmask */
|
||||
uint shift = mask ? ffs(mask) - 1 : 0;
|
||||
|
||||
return (get_spmr(im) & mask) >> shift;
|
||||
}
|
||||
|
||||
/**
|
||||
* sccr_field() - Read a specific SCCR field
|
||||
* @im: Pointer to the MPC83xx main register map in question
|
||||
* @mask: A bitmask that describes the bitfield to be read
|
||||
*
|
||||
* Return: The value of the bit field as a 32-bit number.
|
||||
*/
|
||||
static inline uint sccr_field(immap_t *im, u32 mask)
|
||||
{
|
||||
/* Extract shift from bitmask */
|
||||
uint shift = mask ? ffs(mask) - 1 : 0;
|
||||
|
||||
return (get_sccr(im) & mask) >> shift;
|
||||
}
|
||||
|
||||
/**
|
||||
* lcrr_field() - Read a specific LCRR field
|
||||
* @im: Pointer to the MPC83xx main register map in question
|
||||
* @mask: A bitmask that describes the bitfield to be read
|
||||
*
|
||||
* Return: The value of the bit field as a 32-bit number.
|
||||
*/
|
||||
static inline uint lcrr_field(immap_t *im, u32 mask)
|
||||
{
|
||||
/* Extract shift from bitmask */
|
||||
uint shift = mask ? ffs(mask) - 1 : 0;
|
||||
|
||||
return (get_lcrr(im) & mask) >> shift;
|
||||
}
|
|
@ -138,7 +138,7 @@ void *devfdt_get_addr_ptr(struct udevice *dev)
|
|||
|
||||
void *devfdt_remap_addr_index(struct udevice *dev, int index)
|
||||
{
|
||||
fdt_addr_t addr = devfdt_get_addr(dev);
|
||||
fdt_addr_t addr = devfdt_get_addr_index(dev, index);
|
||||
|
||||
if (addr == FDT_ADDR_T_NONE)
|
||||
return NULL;
|
||||
|
|
|
@ -376,6 +376,33 @@ struct device_node *of_find_compatible_node(struct device_node *from,
|
|||
return np;
|
||||
}
|
||||
|
||||
static int of_device_has_prop_value(const struct device_node *device,
|
||||
const char *propname, const void *propval,
|
||||
int proplen)
|
||||
{
|
||||
struct property *prop = of_find_property(device, propname, NULL);
|
||||
|
||||
if (!prop || !prop->value || prop->length != proplen)
|
||||
return 0;
|
||||
return !memcmp(prop->value, propval, proplen);
|
||||
}
|
||||
|
||||
struct device_node *of_find_node_by_prop_value(struct device_node *from,
|
||||
const char *propname,
|
||||
const void *propval, int proplen)
|
||||
{
|
||||
struct device_node *np;
|
||||
|
||||
for_each_of_allnodes_from(from, np) {
|
||||
if (of_device_has_prop_value(np, propname, propval, proplen) &&
|
||||
of_node_get(np))
|
||||
break;
|
||||
}
|
||||
of_node_put(from);
|
||||
|
||||
return np;
|
||||
}
|
||||
|
||||
struct device_node *of_find_node_by_phandle(phandle handle)
|
||||
{
|
||||
struct device_node *np;
|
||||
|
|
|
@ -777,3 +777,17 @@ ofnode ofnode_by_compatible(ofnode from, const char *compat)
|
|||
gd->fdt_blob, ofnode_to_offset(from), compat));
|
||||
}
|
||||
}
|
||||
|
||||
ofnode ofnode_by_prop_value(ofnode from, const char *propname,
|
||||
const void *propval, int proplen)
|
||||
{
|
||||
if (of_live_active()) {
|
||||
return np_to_ofnode(of_find_node_by_prop_value(
|
||||
(struct device_node *)ofnode_to_np(from), propname,
|
||||
propval, proplen));
|
||||
} else {
|
||||
return offset_to_ofnode(fdt_node_offset_by_prop_value(
|
||||
gd->fdt_blob, ofnode_to_offset(from),
|
||||
propname, propval, proplen));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -330,10 +330,25 @@ static int dm_scan_fdt_node(struct udevice *parent, const void *blob,
|
|||
}
|
||||
#endif
|
||||
|
||||
static int dm_scan_fdt_ofnode_path(const char *path, bool pre_reloc_only)
|
||||
{
|
||||
ofnode node;
|
||||
|
||||
node = ofnode_path(path);
|
||||
if (!ofnode_valid(node))
|
||||
return 0;
|
||||
|
||||
#if CONFIG_IS_ENABLED(OF_LIVE)
|
||||
if (of_live_active())
|
||||
return dm_scan_fdt_live(gd->dm_root, node.np, pre_reloc_only);
|
||||
#endif
|
||||
return dm_scan_fdt_node(gd->dm_root, gd->fdt_blob, node.of_offset,
|
||||
pre_reloc_only);
|
||||
}
|
||||
|
||||
int dm_extended_scan_fdt(const void *blob, bool pre_reloc_only)
|
||||
{
|
||||
int ret;
|
||||
ofnode node;
|
||||
|
||||
ret = dm_scan_fdt(gd->fdt_blob, pre_reloc_only);
|
||||
if (ret) {
|
||||
|
@ -341,21 +356,15 @@ int dm_extended_scan_fdt(const void *blob, bool pre_reloc_only)
|
|||
return ret;
|
||||
}
|
||||
|
||||
/* bind fixed-clock */
|
||||
node = ofnode_path("/clocks");
|
||||
/* if no DT "clocks" node, no need to go further */
|
||||
if (!ofnode_valid(node))
|
||||
ret = dm_scan_fdt_ofnode_path("/clocks", pre_reloc_only);
|
||||
if (ret) {
|
||||
debug("scan for /clocks failed: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
#if CONFIG_IS_ENABLED(OF_LIVE)
|
||||
if (of_live_active())
|
||||
ret = dm_scan_fdt_live(gd->dm_root, node.np, pre_reloc_only);
|
||||
else
|
||||
#endif
|
||||
ret = dm_scan_fdt_node(gd->dm_root, gd->fdt_blob, node.of_offset,
|
||||
pre_reloc_only);
|
||||
ret = dm_scan_fdt_ofnode_path("/firmware", pre_reloc_only);
|
||||
if (ret)
|
||||
debug("dm_scan_fdt_node() failed: %d\n", ret);
|
||||
debug("scan for /firmware failed: %d\n", ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -6,3 +6,10 @@ config CPU
|
|||
multiple CPUs, then normally have to be set up in U-Boot so that
|
||||
they can work correctly in the OS. This provides a framework for
|
||||
finding out information about available CPUs and making changes.
|
||||
|
||||
config CPU_MPC83XX
|
||||
bool "Enable MPC83xx CPU driver"
|
||||
depends on CPU
|
||||
select CLK_MPC83XX
|
||||
help
|
||||
Support CPU cores for SoCs of the MPC83xx series.
|
||||
|
|
|
@ -7,3 +7,5 @@
|
|||
obj-$(CONFIG_CPU) += cpu-uclass.o
|
||||
|
||||
obj-$(CONFIG_ARCH_BMIPS) += bmips_cpu.o
|
||||
obj-$(CONFIG_CPU_MPC83XX) += mpc83xx_cpu.o
|
||||
obj-$(CONFIG_SANDBOX) += cpu_sandbox.o
|
||||
|
|
|
@ -11,6 +11,29 @@
|
|||
#include <dm/lists.h>
|
||||
#include <dm/root.h>
|
||||
|
||||
int cpu_probe_all(void)
|
||||
{
|
||||
struct udevice *cpu;
|
||||
int ret;
|
||||
|
||||
ret = uclass_first_device(UCLASS_CPU, &cpu);
|
||||
if (ret) {
|
||||
debug("%s: No CPU found (err = %d)\n", __func__, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
while (cpu) {
|
||||
ret = uclass_next_device(&cpu);
|
||||
if (ret) {
|
||||
debug("%s: Error while probing CPU (err = %d)\n",
|
||||
__func__, ret);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int cpu_get_desc(struct udevice *dev, char *buf, int size)
|
||||
{
|
||||
struct cpu_ops *ops = cpu_get_ops(dev);
|
||||
|
|
61
drivers/cpu/cpu_sandbox.c
Normal file
61
drivers/cpu/cpu_sandbox.c
Normal file
|
@ -0,0 +1,61 @@
|
|||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* (C) Copyright 2018
|
||||
* Mario Six, Guntermann & Drunck GmbH, mario.six@gdsys.cc
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <dm.h>
|
||||
#include <cpu.h>
|
||||
|
||||
int cpu_sandbox_get_desc(struct udevice *dev, char *buf, int size)
|
||||
{
|
||||
snprintf(buf, size, "LEG Inc. SuperMegaUltraTurbo CPU No. 1");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int cpu_sandbox_get_info(struct udevice *dev, struct cpu_info *info)
|
||||
{
|
||||
info->cpu_freq = 42 * 42 * 42 * 42 * 42;
|
||||
info->features = 0x42424242;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int cpu_sandbox_get_count(struct udevice *dev)
|
||||
{
|
||||
return 42;
|
||||
}
|
||||
|
||||
int cpu_sandbox_get_vendor(struct udevice *dev, char *buf, int size)
|
||||
{
|
||||
snprintf(buf, size, "Languid Example Garbage Inc.");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct cpu_ops cpu_sandbox_ops = {
|
||||
.get_desc = cpu_sandbox_get_desc,
|
||||
.get_info = cpu_sandbox_get_info,
|
||||
.get_count = cpu_sandbox_get_count,
|
||||
.get_vendor = cpu_sandbox_get_vendor,
|
||||
};
|
||||
|
||||
int cpu_sandbox_probe(struct udevice *dev)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct udevice_id cpu_sandbox_ids[] = {
|
||||
{ .compatible = "sandbox,cpu_sandbox" },
|
||||
{ }
|
||||
};
|
||||
|
||||
U_BOOT_DRIVER(cpu_sandbox) = {
|
||||
.name = "cpu_sandbox",
|
||||
.id = UCLASS_CPU,
|
||||
.ops = &cpu_sandbox_ops,
|
||||
.of_match = cpu_sandbox_ids,
|
||||
.probe = cpu_sandbox_probe,
|
||||
};
|
349
drivers/cpu/mpc83xx_cpu.c
Normal file
349
drivers/cpu/mpc83xx_cpu.c
Normal file
|
@ -0,0 +1,349 @@
|
|||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* (C) Copyright 2018
|
||||
* Mario Six, Guntermann & Drunck GmbH, mario.six@gdsys.cc
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <bitfield.h>
|
||||
#include <clk.h>
|
||||
#include <cpu.h>
|
||||
#include <dm.h>
|
||||
|
||||
#include "mpc83xx_cpu.h"
|
||||
|
||||
/**
|
||||
* struct mpc83xx_cpu_priv - Private data for MPC83xx CPUs
|
||||
* @e300_type: The e300 core type of the MPC83xx CPU
|
||||
* @family: The MPC83xx family the CPU belongs to
|
||||
* @type: The MPC83xx type of the CPU
|
||||
* @is_e_processor: Flag indicating whether the CPU is a E processor or not
|
||||
* @is_a_variant: Flag indicating whtther the CPU is a A variant or not
|
||||
* @revid: The revision ID of the CPU
|
||||
* @revid.major: The major part of the CPU's revision ID
|
||||
* @revid.minor: The minor part of the CPU's revision ID
|
||||
*/
|
||||
struct mpc83xx_cpu_priv {
|
||||
enum e300_type e300_type;
|
||||
enum mpc83xx_cpu_family family;
|
||||
enum mpc83xx_cpu_type type;
|
||||
bool is_e_processor;
|
||||
bool is_a_variant;
|
||||
struct {
|
||||
uint major;
|
||||
uint minor;
|
||||
} revid;
|
||||
};
|
||||
|
||||
int checkcpu(void)
|
||||
{
|
||||
/* Activate all CPUs from board_f.c */
|
||||
return cpu_probe_all();
|
||||
}
|
||||
|
||||
/**
|
||||
* get_spridr() - Read SPRIDR (System Part and Revision ID Register) of CPU
|
||||
*
|
||||
* Return: The SPRIDR value
|
||||
*/
|
||||
static inline u32 get_spridr(void)
|
||||
{
|
||||
immap_t *immr = (immap_t *)CONFIG_SYS_IMMR;
|
||||
|
||||
return in_be32(&immr->sysconf.spridr);
|
||||
}
|
||||
|
||||
/**
|
||||
* determine_type() - Determine CPU family of MPC83xx device
|
||||
* @dev: CPU device from which to read CPU family from
|
||||
*/
|
||||
static inline void determine_family(struct udevice *dev)
|
||||
{
|
||||
struct mpc83xx_cpu_priv *priv = dev_get_priv(dev);
|
||||
/* Upper 12 bits of PARTID field (bits 0-23 in SPRIDR) */
|
||||
const u32 PARTID_FAMILY_MASK = 0xFFF00000;
|
||||
|
||||
switch (bitfield_extract_by_mask(get_spridr(), PARTID_FAMILY_MASK)) {
|
||||
case 0x810:
|
||||
case 0x811:
|
||||
priv->family = FAMILY_830X;
|
||||
break;
|
||||
case 0x80B:
|
||||
priv->family = FAMILY_831X;
|
||||
break;
|
||||
case 0x806:
|
||||
priv->family = FAMILY_832X;
|
||||
break;
|
||||
case 0x803:
|
||||
priv->family = FAMILY_834X;
|
||||
break;
|
||||
case 0x804:
|
||||
priv->family = FAMILY_836X;
|
||||
break;
|
||||
case 0x80C:
|
||||
priv->family = FAMILY_837X;
|
||||
break;
|
||||
default:
|
||||
priv->family = FAMILY_UNKNOWN;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* determine_type() - Determine CPU type of MPC83xx device
|
||||
* @dev: CPU device from which to read CPU type from
|
||||
*/
|
||||
static inline void determine_type(struct udevice *dev)
|
||||
{
|
||||
struct mpc83xx_cpu_priv *priv = dev_get_priv(dev);
|
||||
/* Upper 16 bits of PVR (Processor Version Register) */
|
||||
const u32 PCR_UPPER_MASK = 0xFFFF0000;
|
||||
u32 val;
|
||||
|
||||
val = bitfield_extract_by_mask(get_spridr(), PCR_UPPER_MASK);
|
||||
|
||||
/* Mask out E-variant bit */
|
||||
switch (val & 0xFFFE) {
|
||||
case 0x8100:
|
||||
priv->type = TYPE_8308;
|
||||
break;
|
||||
case 0x8110:
|
||||
priv->type = TYPE_8309;
|
||||
break;
|
||||
case 0x80B2:
|
||||
priv->type = TYPE_8311;
|
||||
break;
|
||||
case 0x80B0:
|
||||
priv->type = TYPE_8313;
|
||||
break;
|
||||
case 0x80B6:
|
||||
priv->type = TYPE_8314;
|
||||
break;
|
||||
case 0x80B4:
|
||||
priv->type = TYPE_8315;
|
||||
break;
|
||||
case 0x8066:
|
||||
priv->type = TYPE_8321;
|
||||
break;
|
||||
case 0x8062:
|
||||
priv->type = TYPE_8323;
|
||||
break;
|
||||
case 0x8036:
|
||||
priv->type = TYPE_8343;
|
||||
break;
|
||||
case 0x8032:
|
||||
priv->type = TYPE_8347_TBGA;
|
||||
break;
|
||||
case 0x8034:
|
||||
priv->type = TYPE_8347_PBGA;
|
||||
break;
|
||||
case 0x8030:
|
||||
priv->type = TYPE_8349;
|
||||
break;
|
||||
case 0x804A:
|
||||
priv->type = TYPE_8358_TBGA;
|
||||
break;
|
||||
case 0x804E:
|
||||
priv->type = TYPE_8358_PBGA;
|
||||
break;
|
||||
case 0x8048:
|
||||
priv->type = TYPE_8360;
|
||||
break;
|
||||
case 0x80C6:
|
||||
priv->type = TYPE_8377;
|
||||
break;
|
||||
case 0x80C4:
|
||||
priv->type = TYPE_8378;
|
||||
break;
|
||||
case 0x80C2:
|
||||
priv->type = TYPE_8379;
|
||||
break;
|
||||
default:
|
||||
priv->type = TYPE_UNKNOWN;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* determine_e300_type() - Determine e300 core type of MPC83xx device
|
||||
* @dev: CPU device from which to read e300 core type from
|
||||
*/
|
||||
static inline void determine_e300_type(struct udevice *dev)
|
||||
{
|
||||
struct mpc83xx_cpu_priv *priv = dev_get_priv(dev);
|
||||
/* Upper 16 bits of PVR (Processor Version Register) */
|
||||
const u32 PCR_UPPER_MASK = 0xFFFF0000;
|
||||
u32 pvr = get_pvr();
|
||||
|
||||
switch ((pvr & PCR_UPPER_MASK) >> 16) {
|
||||
case 0x8083:
|
||||
priv->e300_type = E300C1;
|
||||
break;
|
||||
case 0x8084:
|
||||
priv->e300_type = E300C2;
|
||||
break;
|
||||
case 0x8085:
|
||||
priv->e300_type = E300C3;
|
||||
break;
|
||||
case 0x8086:
|
||||
priv->e300_type = E300C4;
|
||||
break;
|
||||
default:
|
||||
priv->e300_type = E300_UNKNOWN;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* determine_revid() - Determine revision ID of CPU device
|
||||
* @dev: CPU device from which to read revision ID
|
||||
*/
|
||||
static inline void determine_revid(struct udevice *dev)
|
||||
{
|
||||
struct mpc83xx_cpu_priv *priv = dev_get_priv(dev);
|
||||
u32 REVID_MAJOR_MASK;
|
||||
u32 REVID_MINOR_MASK;
|
||||
u32 spridr = get_spridr();
|
||||
|
||||
if (priv->family == FAMILY_834X) {
|
||||
REVID_MAJOR_MASK = 0x0000FF00;
|
||||
REVID_MINOR_MASK = 0x000000FF;
|
||||
} else {
|
||||
REVID_MAJOR_MASK = 0x000000F0;
|
||||
REVID_MINOR_MASK = 0x0000000F;
|
||||
}
|
||||
|
||||
priv->revid.major = bitfield_extract_by_mask(spridr, REVID_MAJOR_MASK);
|
||||
priv->revid.minor = bitfield_extract_by_mask(spridr, REVID_MINOR_MASK);
|
||||
}
|
||||
|
||||
/**
|
||||
* determine_cpu_data() - Determine CPU information from hardware
|
||||
* @dev: CPU device from which to read information
|
||||
*/
|
||||
static void determine_cpu_data(struct udevice *dev)
|
||||
{
|
||||
struct mpc83xx_cpu_priv *priv = dev_get_priv(dev);
|
||||
const u32 E_FLAG_MASK = 0x00010000;
|
||||
u32 spridr = get_spridr();
|
||||
|
||||
determine_family(dev);
|
||||
determine_type(dev);
|
||||
determine_e300_type(dev);
|
||||
determine_revid(dev);
|
||||
|
||||
if ((priv->family == FAMILY_834X ||
|
||||
priv->family == FAMILY_836X) && priv->revid.major >= 2)
|
||||
priv->is_a_variant = true;
|
||||
|
||||
priv->is_e_processor = !bitfield_extract_by_mask(spridr, E_FLAG_MASK);
|
||||
}
|
||||
|
||||
static int mpc83xx_cpu_get_desc(struct udevice *dev, char *buf, int size)
|
||||
{
|
||||
struct mpc83xx_cpu_priv *priv = dev_get_priv(dev);
|
||||
struct clk core_clk;
|
||||
struct clk csb_clk;
|
||||
char core_freq[32];
|
||||
char csb_freq[32];
|
||||
int ret;
|
||||
|
||||
ret = clk_get_by_index(dev, 0, &core_clk);
|
||||
if (ret) {
|
||||
debug("%s: Failed to get core clock (err = %d)\n",
|
||||
dev->name, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = clk_get_by_index(dev, 1, &csb_clk);
|
||||
if (ret) {
|
||||
debug("%s: Failed to get CSB clock (err = %d)\n",
|
||||
dev->name, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
determine_cpu_data(dev);
|
||||
|
||||
snprintf(buf, size,
|
||||
"CPU: %s, MPC%s%s%s, Rev: %d.%d at %s MHz, CSB: %s MHz\n",
|
||||
e300_names[priv->e300_type],
|
||||
cpu_type_names[priv->type],
|
||||
priv->is_e_processor ? "E" : "",
|
||||
priv->is_a_variant ? "A" : "",
|
||||
priv->revid.major,
|
||||
priv->revid.minor,
|
||||
strmhz(core_freq, clk_get_rate(&core_clk)),
|
||||
strmhz(csb_freq, clk_get_rate(&csb_clk)));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mpc83xx_cpu_get_info(struct udevice *dev, struct cpu_info *info)
|
||||
{
|
||||
struct clk clock;
|
||||
int ret;
|
||||
ulong freq;
|
||||
|
||||
ret = clk_get_by_index(dev, 0, &clock);
|
||||
if (ret) {
|
||||
debug("%s: Failed to get core clock (err = %d)\n",
|
||||
dev->name, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
freq = clk_get_rate(&clock);
|
||||
if (!freq) {
|
||||
debug("%s: Core clock speed is zero\n", dev->name);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
info->cpu_freq = freq;
|
||||
info->features = BIT(CPU_FEAT_L1_CACHE) | BIT(CPU_FEAT_MMU);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mpc83xx_cpu_get_count(struct udevice *dev)
|
||||
{
|
||||
/* We have one e300cX core */
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int mpc83xx_cpu_get_vendor(struct udevice *dev, char *buf, int size)
|
||||
{
|
||||
snprintf(buf, size, "NXP");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct cpu_ops mpc83xx_cpu_ops = {
|
||||
.get_desc = mpc83xx_cpu_get_desc,
|
||||
.get_info = mpc83xx_cpu_get_info,
|
||||
.get_count = mpc83xx_cpu_get_count,
|
||||
.get_vendor = mpc83xx_cpu_get_vendor,
|
||||
};
|
||||
|
||||
static int mpc83xx_cpu_probe(struct udevice *dev)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct udevice_id mpc83xx_cpu_ids[] = {
|
||||
{ .compatible = "fsl,mpc83xx", },
|
||||
{ .compatible = "fsl,mpc8308", },
|
||||
{ .compatible = "fsl,mpc8309", },
|
||||
{ .compatible = "fsl,mpc8313", },
|
||||
{ .compatible = "fsl,mpc8315", },
|
||||
{ .compatible = "fsl,mpc832x", },
|
||||
{ .compatible = "fsl,mpc8349", },
|
||||
{ .compatible = "fsl,mpc8360", },
|
||||
{ .compatible = "fsl,mpc8379", },
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
|
||||
U_BOOT_DRIVER(mpc83xx_cpu) = {
|
||||
.name = "mpc83xx_cpu",
|
||||
.id = UCLASS_CPU,
|
||||
.of_match = mpc83xx_cpu_ids,
|
||||
.probe = mpc83xx_cpu_probe,
|
||||
.priv_auto_alloc_size = sizeof(struct mpc83xx_cpu_priv),
|
||||
.ops = &mpc83xx_cpu_ops,
|
||||
.flags = DM_FLAG_PRE_RELOC,
|
||||
};
|
126
drivers/cpu/mpc83xx_cpu.h
Normal file
126
drivers/cpu/mpc83xx_cpu.h
Normal file
|
@ -0,0 +1,126 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||
/*
|
||||
* (C) Copyright 2018
|
||||
* Mario Six, Guntermann & Drunck GmbH, mario.six@gdsys.cc
|
||||
*/
|
||||
|
||||
#ifndef _MPC83XX_CPU_H_
|
||||
#define _MPC83XX_CPU_H_
|
||||
|
||||
/**
|
||||
* enum e300_type - Identifiers for e300 cores
|
||||
* @E300C1: Identifier for e300c1 cores
|
||||
* @E300C2: Identifier for e300c2 cores
|
||||
* @E300C3: Identifier for e300c3 cores
|
||||
* @E300C4: Identifier for e300c4 cores
|
||||
* @E300_UNKNOWN: Identifier for unknown e300 cores
|
||||
*/
|
||||
enum e300_type {
|
||||
E300C1,
|
||||
E300C2,
|
||||
E300C3,
|
||||
E300C4,
|
||||
E300_UNKNOWN,
|
||||
};
|
||||
|
||||
/* Array mapping the e300 core types to their human-readable names */
|
||||
static const char * const e300_names[] = {
|
||||
[E300C1] = "e300c1",
|
||||
[E300C2] = "e300c2",
|
||||
[E300C3] = "e300c3",
|
||||
[E300C4] = "e300c4",
|
||||
[E300_UNKNOWN] = "Unknown e300",
|
||||
};
|
||||
|
||||
/**
|
||||
* enum mpc83xx_cpu_family - Identifiers for MPC83xx CPU families
|
||||
* @FAMILY_830X: Identifier for the MPC830x CPU family
|
||||
* @FAMILY_831X: Identifier for the MPC831x CPU family
|
||||
* @FAMILY_832X: Identifier for the MPC832x CPU family
|
||||
* @FAMILY_834X: Identifier for the MPC834x CPU family
|
||||
* @FAMILY_836X: Identifier for the MPC836x CPU family
|
||||
* @FAMILY_837X: Identifier for the MPC837x CPU family
|
||||
* @FAMILY_UNKNOWN: Identifier for an unknown MPC83xx CPU family
|
||||
*/
|
||||
enum mpc83xx_cpu_family {
|
||||
FAMILY_830X,
|
||||
FAMILY_831X,
|
||||
FAMILY_832X,
|
||||
FAMILY_834X,
|
||||
FAMILY_836X,
|
||||
FAMILY_837X,
|
||||
FAMILY_UNKNOWN,
|
||||
};
|
||||
|
||||
/**
|
||||
* enum mpc83xx_cpu_type - Identifiers for MPC83xx CPU types
|
||||
* @TYPE_8308: Identifier for the MPC8308 CPU type
|
||||
* @TYPE_8309: Identifier for the MPC8309 CPU type
|
||||
* @TYPE_8311: Identifier for the MPC8311 CPU type
|
||||
* @TYPE_8313: Identifier for the MPC8313 CPU type
|
||||
* @TYPE_8314: Identifier for the MPC8314 CPU type
|
||||
* @TYPE_8315: Identifier for the MPC8315 CPU type
|
||||
* @TYPE_8321: Identifier for the MPC8321 CPU type
|
||||
* @TYPE_8323: Identifier for the MPC8323 CPU type
|
||||
* @TYPE_8343: Identifier for the MPC8343 CPU type
|
||||
* @TYPE_8347_TBGA: Identifier for the MPC8347 CPU type (Tape Ball Grid Array
|
||||
* version)
|
||||
* @TYPE_8347_PBGA: Identifier for the MPC8347 CPU type (Plastic Ball Grid Array
|
||||
* version)
|
||||
* @TYPE_8349: Identifier for the MPC8349 CPU type
|
||||
* @TYPE_8358_TBGA: Identifier for the MPC8358 CPU type (Tape Ball Grid Array
|
||||
* version)
|
||||
* @TYPE_8358_PBGA: Identifier for the MPC8358 CPU type (Plastic Ball Grid Array
|
||||
* version)
|
||||
* @TYPE_8360: Identifier for the MPC8360 CPU type
|
||||
* @TYPE_8377: Identifier for the MPC8377 CPU type
|
||||
* @TYPE_8378: Identifier for the MPC8378 CPU type
|
||||
* @TYPE_8379: Identifier for the MPC8379 CPU type
|
||||
* @TYPE_UNKNOWN: Identifier for an unknown MPC83xx CPU type
|
||||
*/
|
||||
enum mpc83xx_cpu_type {
|
||||
TYPE_8308,
|
||||
TYPE_8309,
|
||||
TYPE_8311,
|
||||
TYPE_8313,
|
||||
TYPE_8314,
|
||||
TYPE_8315,
|
||||
TYPE_8321,
|
||||
TYPE_8323,
|
||||
TYPE_8343,
|
||||
TYPE_8347_TBGA,
|
||||
TYPE_8347_PBGA,
|
||||
TYPE_8349,
|
||||
TYPE_8358_TBGA,
|
||||
TYPE_8358_PBGA,
|
||||
TYPE_8360,
|
||||
TYPE_8377,
|
||||
TYPE_8378,
|
||||
TYPE_8379,
|
||||
TYPE_UNKNOWN,
|
||||
};
|
||||
|
||||
/* Array mapping the MCP83xx CPUs to their human-readable names */
|
||||
static const char * const cpu_type_names[] = {
|
||||
[TYPE_8308] = "8308",
|
||||
[TYPE_8309] = "8309",
|
||||
[TYPE_8311] = "8311",
|
||||
[TYPE_8313] = "8313",
|
||||
[TYPE_8314] = "8314",
|
||||
[TYPE_8315] = "8315",
|
||||
[TYPE_8321] = "8321",
|
||||
[TYPE_8323] = "8323",
|
||||
[TYPE_8343] = "8343",
|
||||
[TYPE_8347_TBGA] = "8347_TBGA",
|
||||
[TYPE_8347_PBGA] = "8347_PBGA",
|
||||
[TYPE_8349] = "8349",
|
||||
[TYPE_8358_TBGA] = "8358_TBGA",
|
||||
[TYPE_8358_PBGA] = "8358_PBGA",
|
||||
[TYPE_8360] = "8360",
|
||||
[TYPE_8377] = "8377",
|
||||
[TYPE_8378] = "8378",
|
||||
[TYPE_8379] = "8379",
|
||||
[TYPE_UNKNOWN] = "Unknown CPU",
|
||||
};
|
||||
|
||||
#endif /* !_MPC83XX_CPU_H_ */
|
|
@ -288,4 +288,11 @@ config GDSYS_IOEP
|
|||
depends on MISC
|
||||
help
|
||||
Support gdsys FPGA's IO endpoint driver.
|
||||
|
||||
config MPC83XX_SERDES
|
||||
bool "Enable MPC83xx serdes driver"
|
||||
depends on MISC
|
||||
help
|
||||
Support for serdes found on MPC83xx SoCs.
|
||||
|
||||
endmenu
|
||||
|
|
|
@ -55,3 +55,4 @@ obj-$(CONFIG_STM32MP_FUSE) += stm32mp_fuse.o
|
|||
obj-$(CONFIG_SYS_DPAA_QBMAN) += fsl_portals.o
|
||||
obj-$(CONFIG_GDSYS_IOEP) += gdsys_ioep.o
|
||||
obj-$(CONFIG_GDSYS_RXAUI_CTRL) += gdsys_rxaui_ctrl.o
|
||||
obj-$(CONFIG_MPC83XX_SERDES) += mpc83xx_serdes.o
|
||||
|
|
185
drivers/misc/mpc83xx_serdes.c
Normal file
185
drivers/misc/mpc83xx_serdes.c
Normal file
|
@ -0,0 +1,185 @@
|
|||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* (C) Copyright 2018
|
||||
* Mario Six, Guntermann & Drunck GmbH, mario.six@gdsys.cc
|
||||
*
|
||||
* base on the MPC83xx serdes initialization, which is
|
||||
*
|
||||
* Copyright 2007,2011 Freescale Semiconductor, Inc.
|
||||
* Copyright (C) 2008 MontaVista Software, Inc.
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <dm.h>
|
||||
#include <mapmem.h>
|
||||
#include <misc.h>
|
||||
|
||||
#include "mpc83xx_serdes.h"
|
||||
|
||||
/**
|
||||
* struct mpc83xx_serdes_priv - Private structure for MPC83xx serdes
|
||||
* @regs: The device's register map
|
||||
* @rfcks: Variable to keep the serdes reference clock selection set during
|
||||
* initialization in (is or'd to every value written to SRDSCR4)
|
||||
*/
|
||||
struct mpc83xx_serdes_priv {
|
||||
struct mpc83xx_serdes_regs *regs;
|
||||
u32 rfcks;
|
||||
};
|
||||
|
||||
/**
|
||||
* setup_sata() - Configure the SerDes device to SATA mode
|
||||
* @dev: The device to configure
|
||||
*/
|
||||
static void setup_sata(struct udevice *dev)
|
||||
{
|
||||
struct mpc83xx_serdes_priv *priv = dev_get_priv(dev);
|
||||
|
||||
/* Set and clear reset bits */
|
||||
setbits_be32(&priv->regs->srdsrstctl, SRDSRSTCTL_SATA_RESET);
|
||||
udelay(1000);
|
||||
clrbits_be32(&priv->regs->srdsrstctl, SRDSRSTCTL_SATA_RESET);
|
||||
|
||||
/* Configure SRDSCR0 */
|
||||
clrsetbits_be32(&priv->regs->srdscr0,
|
||||
SRDSCR0_TXEQA_MASK | SRDSCR0_TXEQE_MASK,
|
||||
SRDSCR0_TXEQA_SATA | SRDSCR0_TXEQE_SATA);
|
||||
|
||||
/* Configure SRDSCR1 */
|
||||
clrbits_be32(&priv->regs->srdscr1, SRDSCR1_PLLBW);
|
||||
|
||||
/* Configure SRDSCR2 */
|
||||
clrsetbits_be32(&priv->regs->srdscr2,
|
||||
SRDSCR2_SEIC_MASK,
|
||||
SRDSCR2_SEIC_SATA);
|
||||
|
||||
/* Configure SRDSCR3 */
|
||||
out_be32(&priv->regs->srdscr3,
|
||||
SRDSCR3_KFR_SATA | SRDSCR3_KPH_SATA |
|
||||
SRDSCR3_SDFM_SATA_PEX | SRDSCR3_SDTXL_SATA);
|
||||
|
||||
/* Configure SRDSCR4 */
|
||||
out_be32(&priv->regs->srdscr4, priv->rfcks | SRDSCR4_PROT_SATA);
|
||||
}
|
||||
|
||||
/**
|
||||
* setup_pex() - Configure the SerDes device to PCI Express mode
|
||||
* @dev: The device to configure
|
||||
* @type: The PCI Express type to configure for (x1 or x2)
|
||||
*/
|
||||
static void setup_pex(struct udevice *dev, enum pex_type type)
|
||||
{
|
||||
struct mpc83xx_serdes_priv *priv = dev_get_priv(dev);
|
||||
|
||||
/* Configure SRDSCR1 */
|
||||
setbits_be32(&priv->regs->srdscr1, SRDSCR1_PLLBW);
|
||||
|
||||
/* Configure SRDSCR2 */
|
||||
clrsetbits_be32(&priv->regs->srdscr2,
|
||||
SRDSCR2_SEIC_MASK,
|
||||
SRDSCR2_SEIC_PEX);
|
||||
|
||||
/* Configure SRDSCR3 */
|
||||
out_be32(&priv->regs->srdscr3, SRDSCR3_SDFM_SATA_PEX);
|
||||
|
||||
/* Configure SRDSCR4 */
|
||||
if (type == PEX_X2)
|
||||
out_be32(&priv->regs->srdscr4,
|
||||
priv->rfcks | SRDSCR4_PROT_PEX | SRDSCR4_PLANE_X2);
|
||||
else
|
||||
out_be32(&priv->regs->srdscr4,
|
||||
priv->rfcks | SRDSCR4_PROT_PEX);
|
||||
}
|
||||
|
||||
/**
|
||||
* setup_sgmii() - Configure the SerDes device to SGMII mode
|
||||
* @dev: The device to configure
|
||||
*/
|
||||
static void setup_sgmii(struct udevice *dev)
|
||||
{
|
||||
struct mpc83xx_serdes_priv *priv = dev_get_priv(dev);
|
||||
|
||||
/* Configure SRDSCR1 */
|
||||
clrbits_be32(&priv->regs->srdscr1, SRDSCR1_PLLBW);
|
||||
|
||||
/* Configure SRDSCR2 */
|
||||
clrsetbits_be32(&priv->regs->srdscr2,
|
||||
SRDSCR2_SEIC_MASK,
|
||||
SRDSCR2_SEIC_SGMII);
|
||||
|
||||
/* Configure SRDSCR3 */
|
||||
out_be32(&priv->regs->srdscr3, 0);
|
||||
|
||||
/* Configure SRDSCR4 */
|
||||
out_be32(&priv->regs->srdscr4, priv->rfcks | SRDSCR4_PROT_SGMII);
|
||||
}
|
||||
|
||||
static int mpc83xx_serdes_probe(struct udevice *dev)
|
||||
{
|
||||
struct mpc83xx_serdes_priv *priv = dev_get_priv(dev);
|
||||
bool vdd;
|
||||
const char *proto;
|
||||
|
||||
priv->regs = map_sysmem(dev_read_addr(dev),
|
||||
sizeof(struct mpc83xx_serdes_regs));
|
||||
|
||||
switch (dev_read_u32_default(dev, "serdes-clk", -1)) {
|
||||
case 100:
|
||||
priv->rfcks = SRDSCR4_RFCKS_100;
|
||||
break;
|
||||
case 125:
|
||||
priv->rfcks = SRDSCR4_RFCKS_125;
|
||||
break;
|
||||
case 150:
|
||||
priv->rfcks = SRDSCR4_RFCKS_150;
|
||||
break;
|
||||
default:
|
||||
debug("%s: Could not read serdes clock value\n", dev->name);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
vdd = dev_read_bool(dev, "vdd");
|
||||
|
||||
/* 1.0V corevdd */
|
||||
if (vdd) {
|
||||
/* DPPE/DPPA = 0 */
|
||||
clrbits_be32(&priv->regs->srdscr0, SRDSCR0_DPP_1V2);
|
||||
|
||||
/* VDD = 0 */
|
||||
clrbits_be32(&priv->regs->srdscr0, SRDSCR2_VDD_1V2);
|
||||
}
|
||||
|
||||
proto = dev_read_string(dev, "proto");
|
||||
|
||||
/* protocol specific configuration */
|
||||
if (!strcmp(proto, "sata")) {
|
||||
setup_sata(dev);
|
||||
} else if (!strcmp(proto, "pex")) {
|
||||
setup_pex(dev, PEX_X1);
|
||||
} else if (!strcmp(proto, "pex-x2")) {
|
||||
setup_pex(dev, PEX_X2);
|
||||
} else if (!strcmp(proto, "sgmii")) {
|
||||
setup_sgmii(dev);
|
||||
} else {
|
||||
debug("%s: Invalid protocol value %s\n", dev->name, proto);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Do a software reset */
|
||||
setbits_be32(&priv->regs->srdsrstctl, SRDSRSTCTL_RST);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct udevice_id mpc83xx_serdes_ids[] = {
|
||||
{ .compatible = "fsl,mpc83xx-serdes" },
|
||||
{ }
|
||||
};
|
||||
|
||||
U_BOOT_DRIVER(mpc83xx_serdes) = {
|
||||
.name = "mpc83xx_serdes",
|
||||
.id = UCLASS_MISC,
|
||||
.of_match = mpc83xx_serdes_ids,
|
||||
.probe = mpc83xx_serdes_probe,
|
||||
.priv_auto_alloc_size = sizeof(struct mpc83xx_serdes_priv),
|
||||
};
|
232
drivers/misc/mpc83xx_serdes.h
Normal file
232
drivers/misc/mpc83xx_serdes.h
Normal file
|
@ -0,0 +1,232 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||
/*
|
||||
* (C) Copyright 2018
|
||||
* Mario Six, Guntermann & Drunck GmbH, mario.six@gdsys.cc
|
||||
*/
|
||||
|
||||
/**
|
||||
* enum srdscr0_mask - Bit masks for SRDSCR0 (SerDes Control Register 0)
|
||||
* @SRDSCR0_DPPA: Bitmask for the DPPA (diff pk-pk swing for lane A)
|
||||
* field of the SRCSCR0
|
||||
* @SRDSCR0_DPPE: Bitmask for the DPPE (diff pk-pk swing for lane E)
|
||||
* field of the SRCSCR0
|
||||
* @SRDSCR0_DPP_1V2: Combined bitmask to set diff pk-pk swing for both lanes
|
||||
* @SRDSCR0_TXEQA_MASK: Bitmask for the TXEQA (transmit equalization for
|
||||
* lane A) field of the SRCSCR0
|
||||
* @SRDSCR0_TXEQA_SATA: Bitmask to set the TXEQA to the value used for SATA
|
||||
* @SRDSCR0_TXEQE_MASK: Bitmask for the TXEQE (transmit equalization for
|
||||
* lane E) field of the SRCSCR0
|
||||
* @SRDSCR0_TXEQE_SATA: Bitmask to set the TXEQE to the value used for SATA
|
||||
*/
|
||||
enum srdscr0_mask {
|
||||
SRDSCR0_DPPA = BIT(31 - 16),
|
||||
SRDSCR0_DPPE = BIT(31 - 20),
|
||||
SRDSCR0_DPP_1V2 = SRDSCR0_DPPE | SRDSCR0_DPPA,
|
||||
|
||||
SRDSCR0_TXEQA_MASK = 0x00007000,
|
||||
SRDSCR0_TXEQA_SATA = 0x00001000,
|
||||
SRDSCR0_TXEQE_MASK = 0x00000700,
|
||||
SRDSCR0_TXEQE_SATA = 0x00000100,
|
||||
};
|
||||
|
||||
/**
|
||||
* enum srdscr1_mask - Bit masks for SRDSCR1 (SerDes Control Register 1)
|
||||
* @SRDSCR1_PLLBW: Bitmask for the PLLBW (PLL bandwidth) field of SRDSCR1
|
||||
*/
|
||||
enum srdscr1_mask {
|
||||
SRDSCR1_PLLBW = BIT(31 - 25),
|
||||
};
|
||||
|
||||
/**
|
||||
* enum srdscr2_mask - Bit masks for SRDSCR2 (SerDes Control Register 2)
|
||||
* @SRDSCR2_VDD_1V2: Bit mask to to set the VDD field of the SCRSCR2
|
||||
* @SRDSCR2_SEICA_MASK: Bitmask for the SEICA (Receiver electrical idle
|
||||
* detection control for lane A) field of the SRCSCR2
|
||||
* @SRDSCR2_SEICE_MASK: Bitmask for the SEICE (Receiver electrical idle
|
||||
* detection control for lane E) field of the SRCSCR2
|
||||
* @SRDSCR2_SEIC_MASK: Combined bitmask to set the receiver electrical idle
|
||||
* detection control for both lanes
|
||||
* @SRDSCR2_SEICA_SATA: Bitmask to set the SEICA field to the value used for
|
||||
* SATA
|
||||
* @SRDSCR2_SEICE_SATA: Bitmask to set the SEICE field to the value used for
|
||||
* SATA
|
||||
* @SRDSCR2_SEIC_SATA: Combined bitmask to set the value of both SEIC fields
|
||||
* to the value used for SATA
|
||||
* @SRDSCR2_SEICA_PEX: Bitmask to set the SEICA field to the value used for
|
||||
* PCI Express
|
||||
* @SRDSCR2_SEICE_PEX: Bitmask to set the SEICE field to the value used for
|
||||
* PCI Express
|
||||
* @SRDSCR2_SEIC_PEX: Combined bitmask to set the value of both SEIC fields
|
||||
* to the value used for PCI Express
|
||||
* @SRDSCR2_SEICA_SGMII: Bitmask to set the SEICA field to the value used for
|
||||
* SGMII
|
||||
* @SRDSCR2_SEICE_SGMII: Bitmask to set the SEICE field to the value used for
|
||||
* SGMII
|
||||
* @SRDSCR2_SEIC_SGMII: Combined bitmask to set the value of both SEIC fields
|
||||
* to the value used for SGMII
|
||||
*/
|
||||
enum srdscr2_mask {
|
||||
SRDSCR2_VDD_1V2 = 0x00800000,
|
||||
|
||||
SRDSCR2_SEICA_MASK = 0x00001c00,
|
||||
SRDSCR2_SEICE_MASK = 0x0000001c,
|
||||
SRDSCR2_SEIC_MASK = SRDSCR2_SEICA_MASK | SRDSCR2_SEICE_MASK,
|
||||
|
||||
SRDSCR2_SEICA_SATA = 0x00001400,
|
||||
SRDSCR2_SEICE_SATA = 0x00000014,
|
||||
SRDSCR2_SEIC_SATA = SRDSCR2_SEICA_SATA | SRDSCR2_SEICE_SATA,
|
||||
|
||||
SRDSCR2_SEICA_PEX = 0x00001000,
|
||||
SRDSCR2_SEICE_PEX = 0x00000010,
|
||||
SRDSCR2_SEIC_PEX = SRDSCR2_SEICA_PEX | SRDSCR2_SEICE_PEX,
|
||||
|
||||
SRDSCR2_SEICA_SGMII = 0x00000100,
|
||||
SRDSCR2_SEICE_SGMII = 0x00000001,
|
||||
SRDSCR2_SEIC_SGMII = SRDSCR2_SEICA_SGMII | SRDSCR2_SEICE_SGMII,
|
||||
};
|
||||
|
||||
/**
|
||||
* enum srdscr3_mask - Bit masks for SRDSCR3 (SerDes Control Register 3)
|
||||
* @SRDSCR3_KFRA_SATA: Bitmask to set the KFRA field of SRDSCR3 to the
|
||||
* value used by SATA
|
||||
* @SRDSCR3_KFRE_SATA: Bitmask to set the KFRE field of SRDSCR3 to the
|
||||
* value used by SATA
|
||||
* @SRDSCR3_KFR_SATA: Combined bitmask to set both KFR fields to the
|
||||
* value used by SATA
|
||||
* @SRDSCR3_KPHA_SATA: Bitmask to set the KPHA field of SRDSCR3 to the
|
||||
* value used by SATA
|
||||
* @SRDSCR3_KPHE_SATA: Bitmask to set the KPHE field of SRDSCR3 to the
|
||||
* value used by SATA
|
||||
* @SRDSCR3_KPH_SATA: Combined bitmask to set both KPH fields to the
|
||||
* value used by SATA
|
||||
* @SRDSCR3_SDFMA_SATA_PEX: Bitmask to set the SDFMA field of SRDSCR3 to the
|
||||
* value used by SATA and PCI Express
|
||||
* @SRDSCR3_SDFME_SATA_PEX: Bitmask to set the SDFME field of SRDSCR3 to the
|
||||
* value used by SATA and PCI Express
|
||||
* @SRDSCR3_SDFM_SATA_PEX: Combined bitmask to set both SDFM fields to the
|
||||
* value used by SATA and PCI Express
|
||||
* @SRDSCR3_SDTXLA_SATA: Bitmask to set the SDTXLA field of SRDSCR3 to the
|
||||
* value used by SATA
|
||||
* @SRDSCR3_SDTXLE_SATA: Bitmask to set the SDTXLE field of SRDSCR3 to the
|
||||
* value used by SATA
|
||||
* @SRDSCR3_SDTXL_SATA: Combined bitmask to set both SDTXL fields to the
|
||||
* value used by SATA
|
||||
*
|
||||
* KFRA = 'Kfr' gain selection in the CDR for lane A
|
||||
* KFRE = 'Kfr' gain selection in the CDR for lane E
|
||||
* SDFMA = Bandwidth of digital filter for lane A
|
||||
* SDFME = Bandwidth of digital filter for lane E
|
||||
* SDTXLA = Lane A transmitter amplitude levels
|
||||
* SDTXLE = Lane E transmitter amplitude levels
|
||||
*/
|
||||
enum srdscr3_mask {
|
||||
SRDSCR3_KFRA_SATA = 0x10000000,
|
||||
SRDSCR3_KFRE_SATA = 0x00100000,
|
||||
SRDSCR3_KFR_SATA = SRDSCR3_KFRA_SATA | SRDSCR3_KFRE_SATA,
|
||||
|
||||
SRDSCR3_KPHA_SATA = 0x04000000,
|
||||
SRDSCR3_KPHE_SATA = 0x00040000,
|
||||
SRDSCR3_KPH_SATA = SRDSCR3_KPHA_SATA | SRDSCR3_KPHE_SATA,
|
||||
|
||||
SRDSCR3_SDFMA_SATA_PEX = 0x01000000,
|
||||
SRDSCR3_SDFME_SATA_PEX = 0x00010000,
|
||||
SRDSCR3_SDFM_SATA_PEX = SRDSCR3_SDFMA_SATA_PEX | SRDSCR3_SDFME_SATA_PEX,
|
||||
|
||||
SRDSCR3_SDTXLA_SATA = 0x00000500,
|
||||
SRDSCR3_SDTXLE_SATA = 0x00000005,
|
||||
SRDSCR3_SDTXL_SATA = SRDSCR3_SDTXLA_SATA | SRDSCR3_SDTXLE_SATA,
|
||||
};
|
||||
|
||||
/**
|
||||
* enum srdscr4_mask - Bit masks for SRDSCR4 (SerDes Control Register 4)
|
||||
* @SRDSCR4_PROTA_SATA: Bitmask to set the PROTA field of SRDSCR4 to the
|
||||
* value used by SATA
|
||||
* @SRDSCR4_PROTE_SATA: Bitmask to set the PROTE field of SRDSCR4 to the
|
||||
* value used by SATA
|
||||
* @SRDSCR4_PROT_SATA: Combined bitmask to set both PROT fields to the
|
||||
* value used by SATA
|
||||
* @SRDSCR4_PROTA_PEX: Bitmask to set the PROTA field of SRDSCR4 to the
|
||||
* value used by PCI Express
|
||||
* @SRDSCR4_PROTE_PEX: Bitmask to set the PROTE field of SRDSCR4 to the
|
||||
* value used by PCI Express
|
||||
* @SRDSCR4_PROT_PEX: Combined bitmask to set both PROT fields to the
|
||||
* value used by PCI Express
|
||||
* @SRDSCR4_PROTA_SGMII: Bitmask to set the PROTA field of SRDSCR4 to the
|
||||
* value used by SGMII
|
||||
* @SRDSCR4_PROTE_SGMII: Bitmask to set the PROTE field of SRDSCR4 to the
|
||||
* value used by SGMII
|
||||
* @SRDSCR4_PROT_SGMII: Combined bitmask to set both PROT fields to the
|
||||
* value used by SGMII
|
||||
* @SRDSCR4_PLANE_X2: Bitmask to set the PLANE field of SRDSCR4
|
||||
* @SRDSCR4_RFCKS_100: Bitmask to set the RFCKS field of SRDSCR4 to the
|
||||
* value 100Mhz
|
||||
* @SRDSCR4_RFCKS_125: Bitmask to set the RFCKS field of SRDSCR4 to the
|
||||
* value 125Mhz
|
||||
* @SRDSCR4_RFCKS_150: Bitmask to set the RFCKS field of SRDSCR4 to the
|
||||
* value 150Mhz
|
||||
*
|
||||
* PROTA = Lane A protocol select
|
||||
* PROTE = Lane E protocol select
|
||||
* PLAME = Number of PCI Express lanes
|
||||
*/
|
||||
enum srdscr4_mask {
|
||||
SRDSCR4_PROTA_SATA = 0x00000800,
|
||||
SRDSCR4_PROTE_SATA = 0x00000008,
|
||||
SRDSCR4_PROT_SATA = SRDSCR4_PROTA_SATA | SRDSCR4_PROTE_SATA,
|
||||
|
||||
SRDSCR4_PROTA_PEX = 0x00000100,
|
||||
SRDSCR4_PROTE_PEX = 0x00000001,
|
||||
SRDSCR4_PROT_PEX = SRDSCR4_PROTA_PEX | SRDSCR4_PROTE_PEX,
|
||||
|
||||
SRDSCR4_PROTA_SGMII = 0x00000500,
|
||||
SRDSCR4_PROTE_SGMII = 0x00000005,
|
||||
SRDSCR4_PROT_SGMII = SRDSCR4_PROTA_SGMII | SRDSCR4_PROTE_SGMII,
|
||||
|
||||
SRDSCR4_PLANE_X2 = 0x01000000,
|
||||
|
||||
SRDSCR4_RFCKS_100 = (0 << 28),
|
||||
SRDSCR4_RFCKS_125 = (1 << 28),
|
||||
SRDSCR4_RFCKS_150 = (3 << 28),
|
||||
};
|
||||
|
||||
/**
|
||||
* enum srdsrstctl_mask - Bit masks for SRDSRSTCTL (SerDes Reset Control Register)
|
||||
* @SRDSRSTCTL_RST: Bitmask for the RST (Software reset) field of the
|
||||
* SRDSRSTCTL
|
||||
* @SRDSRSTCTL_SATA_RESET: Bitmask for the SATA_RESET (SATA reset) field of the
|
||||
* SRDSRSTCTL
|
||||
*/
|
||||
enum srdsrstctl_mask {
|
||||
SRDSRSTCTL_RST = 0x80000000,
|
||||
SRDSRSTCTL_SATA_RESET = 0xf,
|
||||
};
|
||||
|
||||
/**
|
||||
* struct mpc83xx_serdes_regs - Register map of the SerDes controller
|
||||
* @srdscr0: SerDes Control Register 0
|
||||
* @srdscr1: SerDes Control Register 1
|
||||
* @srdscr2: SerDes Control Register 2
|
||||
* @srdscr3: SerDes Control Register 3
|
||||
* @srdscr4: SerDes Control Register 4
|
||||
* @fill0: Reserved space in the register map
|
||||
* @srdsrstctl: SerDes Reset Control Register
|
||||
*/
|
||||
struct mpc83xx_serdes_regs {
|
||||
u32 srdscr0;
|
||||
u32 srdscr1;
|
||||
u32 srdscr2;
|
||||
u32 srdscr3;
|
||||
u32 srdscr4;
|
||||
u8 fill0[12];
|
||||
u32 srdsrstctl;
|
||||
};
|
||||
|
||||
/**
|
||||
* enum pex_type - Types of PCI Express
|
||||
* @PEX_X1: PCI Express in x1 mode
|
||||
* @PEX_X2: PCI Express in x2 mode
|
||||
*/
|
||||
enum pex_type {
|
||||
PEX_X1,
|
||||
PEX_X2,
|
||||
};
|
|
@ -34,4 +34,13 @@ config STM32_SDRAM
|
|||
support external memories like sdram, psram & nand.
|
||||
This driver is for the sdram memory interface with the FMC.
|
||||
|
||||
config MPC83XX_SDRAM
|
||||
bool "Enable MPC83XX SDRAM support"
|
||||
depends on RAM
|
||||
help
|
||||
Enable support for the internal DDR Memory Controller of the MPC83xx
|
||||
family of SoCs. Both static configurations, as well as configuring
|
||||
the RAM through the use of SPD (Serial Presence Detect) is supported
|
||||
via device tree settings.
|
||||
|
||||
source "drivers/ram/stm32mp1/Kconfig"
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
# SPDX-License-Identifier: GPL-2.0+
|
||||
#
|
||||
obj-$(CONFIG_RAM) += ram-uclass.o
|
||||
obj-$(CONFIG_MPC83XX_SDRAM) += mpc83xx_sdram.o
|
||||
obj-$(CONFIG_SANDBOX) += sandbox_ram.o
|
||||
obj-$(CONFIG_STM32MP1_DDR) += stm32mp1/
|
||||
obj-$(CONFIG_STM32_SDRAM) += stm32_sdram.o
|
||||
|
|
1096
drivers/ram/mpc83xx_sdram.c
Normal file
1096
drivers/ram/mpc83xx_sdram.c
Normal file
File diff suppressed because it is too large
Load diff
|
@ -64,4 +64,9 @@ config SYSRESET_X86
|
|||
help
|
||||
Reboot support for generic x86 processor reset.
|
||||
|
||||
config SYSRESET_MCP83XX
|
||||
bool "Enable support MPC83xx SoC family reboot driver"
|
||||
help
|
||||
Reboot support for NXP MPC83xx SoCs.
|
||||
|
||||
endmenu
|
||||
|
|
|
@ -3,15 +3,16 @@
|
|||
# (C) Copyright 2016 Cadence Design Systems Inc.
|
||||
|
||||
obj-$(CONFIG_SYSRESET) += sysreset-uclass.o
|
||||
obj-$(CONFIG_ARCH_ASPEED) += sysreset_ast.o
|
||||
obj-$(CONFIG_ARCH_ROCKCHIP) += sysreset_rockchip.o
|
||||
obj-$(CONFIG_ARCH_STI) += sysreset_sti.o
|
||||
obj-$(CONFIG_SANDBOX) += sysreset_sandbox.o
|
||||
obj-$(CONFIG_SYSRESET_GPIO) += sysreset_gpio.o
|
||||
obj-$(CONFIG_SYSRESET_MCP83XX) += sysreset_mpc83xx.o
|
||||
obj-$(CONFIG_SYSRESET_MICROBLAZE) += sysreset_microblaze.o
|
||||
obj-$(CONFIG_SYSRESET_PSCI) += sysreset_psci.o
|
||||
obj-$(CONFIG_SYSRESET_TI_SCI) += sysreset-ti-sci.o
|
||||
obj-$(CONFIG_SYSRESET_SYSCON) += sysreset_syscon.o
|
||||
obj-$(CONFIG_SYSRESET_WATCHDOG) += sysreset_watchdog.o
|
||||
obj-$(CONFIG_SYSRESET_X86) += sysreset_x86.o
|
||||
obj-$(CONFIG_ARCH_ROCKCHIP) += sysreset_rockchip.o
|
||||
obj-$(CONFIG_SANDBOX) += sysreset_sandbox.o
|
||||
obj-$(CONFIG_ARCH_STI) += sysreset_sti.o
|
||||
obj-$(CONFIG_TARGET_XTFPGA) += sysreset_xtfpga.o
|
||||
obj-$(CONFIG_ARCH_ASPEED) += sysreset_ast.o
|
||||
|
|
|
@ -24,6 +24,16 @@ int sysreset_request(struct udevice *dev, enum sysreset_t type)
|
|||
return ops->request(dev, type);
|
||||
}
|
||||
|
||||
int sysreset_get_status(struct udevice *dev, char *buf, int size)
|
||||
{
|
||||
struct sysreset_ops *ops = sysreset_get_ops(dev);
|
||||
|
||||
if (!ops->get_status)
|
||||
return -ENOSYS;
|
||||
|
||||
return ops->get_status(dev, buf, size);
|
||||
}
|
||||
|
||||
int sysreset_walk(enum sysreset_t type)
|
||||
{
|
||||
struct udevice *dev;
|
||||
|
|
212
drivers/sysreset/sysreset_mpc83xx.c
Normal file
212
drivers/sysreset/sysreset_mpc83xx.c
Normal file
|
@ -0,0 +1,212 @@
|
|||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* (C) Copyright 2018
|
||||
* Mario Six, Guntermann & Drunck GmbH, mario.six@gdsys.cc
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <dm.h>
|
||||
#include <sysreset.h>
|
||||
#include <wait_bit.h>
|
||||
|
||||
#include "sysreset_mpc83xx.h"
|
||||
|
||||
/* Magic 4-byte word to enable reset ('RSTE' in ASCII) */
|
||||
static const u32 RPR_MAGIC = 0x52535445;
|
||||
/* Wait at most 2000ms for reset control enable bit */
|
||||
static const uint RESET_WAIT_TIMEOUT = 2000;
|
||||
|
||||
/**
|
||||
* __do_reset() - Execute the system reset
|
||||
*
|
||||
* Return: The functions resets the system, and never returns.
|
||||
*/
|
||||
static int __do_reset(void)
|
||||
{
|
||||
ulong msr;
|
||||
int res;
|
||||
|
||||
immap_t *immap = (immap_t *)CONFIG_SYS_IMMR;
|
||||
|
||||
puts("Resetting the board.\n");
|
||||
|
||||
/* Interrupts and MMU off */
|
||||
msr = mfmsr();
|
||||
msr &= ~(MSR_EE | MSR_IR | MSR_DR);
|
||||
mtmsr(msr);
|
||||
|
||||
/* Enable Reset Control Reg */
|
||||
out_be32(&immap->reset.rpr, RPR_MAGIC);
|
||||
sync();
|
||||
isync();
|
||||
|
||||
/* Confirm Reset Control Reg is enabled */
|
||||
res = wait_for_bit_be32(&immap->reset.rcer, RCER_CRE, true,
|
||||
RESET_WAIT_TIMEOUT, false);
|
||||
if (res) {
|
||||
debug("%s: Timed out waiting for reset control to be set\n",
|
||||
__func__);
|
||||
return res;
|
||||
}
|
||||
|
||||
udelay(200);
|
||||
|
||||
/* Perform reset, only one bit */
|
||||
out_be32(&immap->reset.rcr, RCR_SWHR);
|
||||
|
||||
/* Never executes */
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mpc83xx_sysreset_request(struct udevice *dev, enum sysreset_t type)
|
||||
{
|
||||
switch (type) {
|
||||
case SYSRESET_WARM:
|
||||
case SYSRESET_COLD:
|
||||
return __do_reset();
|
||||
default:
|
||||
return -EPROTONOSUPPORT;
|
||||
}
|
||||
|
||||
return -EINPROGRESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* print_83xx_arb_event() - Print arbiter events to buffer
|
||||
* @force: Print arbiter events, even if none are indicated by the system
|
||||
* @buf: The buffer to receive the printed arbiter event information
|
||||
* @size: The size of the buffer to receive the printed arbiter event
|
||||
* information in bytes
|
||||
*
|
||||
* Return: Number of bytes printed to buffer, -ve on error
|
||||
*/
|
||||
static int print_83xx_arb_event(bool force, char *buf, int size)
|
||||
{
|
||||
int etype = (gd->arch.arbiter_event_attributes & AEATR_EVENT)
|
||||
>> AEATR_EVENT_SHIFT;
|
||||
int mstr_id = (gd->arch.arbiter_event_attributes & AEATR_MSTR_ID)
|
||||
>> AEATR_MSTR_ID_SHIFT;
|
||||
int tbst = (gd->arch.arbiter_event_attributes & AEATR_TBST)
|
||||
>> AEATR_TBST_SHIFT;
|
||||
int tsize = (gd->arch.arbiter_event_attributes & AEATR_TSIZE)
|
||||
>> AEATR_TSIZE_SHIFT;
|
||||
int ttype = (gd->arch.arbiter_event_attributes & AEATR_TTYPE)
|
||||
>> AEATR_TTYPE_SHIFT;
|
||||
int tsize_val = (tbst << 3) | tsize;
|
||||
int tsize_bytes = tbst ? (tsize ? tsize : 8) : 16 + 8 * tsize;
|
||||
int res = 0;
|
||||
|
||||
/*
|
||||
* If we don't force output, and there is no event (event address ==
|
||||
* 0), then don't print anything
|
||||
*/
|
||||
if (!force && !gd->arch.arbiter_event_address)
|
||||
return 0;
|
||||
|
||||
if (CONFIG_IS_ENABLED(CONFIG_DISPLAY_AER_FULL)) {
|
||||
res = snprintf(buf, size,
|
||||
"Arbiter Event Status:\n"
|
||||
" %s: 0x%08lX\n"
|
||||
" %s: 0x%1x = %s\n"
|
||||
" %s: 0x%02x = %s\n"
|
||||
" %s: 0x%1x = %d bytes\n"
|
||||
" %s: 0x%02x = %s\n",
|
||||
"Event Address", gd->arch.arbiter_event_address,
|
||||
"Event Type", etype, event[etype],
|
||||
"Master ID", mstr_id, master[mstr_id],
|
||||
"Transfer Size", tsize_val, tsize_bytes,
|
||||
"Transfer Type", ttype, transfer[ttype]);
|
||||
} else if (CONFIG_IS_ENABLED(CONFIG_DISPLAY_AER_BRIEF)) {
|
||||
res = snprintf(buf, size,
|
||||
"Arbiter Event Status: AEATR=0x%08lX, AEADR=0x%08lX\n",
|
||||
gd->arch.arbiter_event_attributes,
|
||||
gd->arch.arbiter_event_address);
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static int mpc83xx_sysreset_get_status(struct udevice *dev, char *buf, int size)
|
||||
{
|
||||
/* Ad-hoc data structure to map RSR bit values to their descriptions */
|
||||
static const struct {
|
||||
/* Bit mask for the bit in question */
|
||||
ulong mask;
|
||||
/* Description of the bitmask in question */
|
||||
char *desc;
|
||||
} bits[] = {
|
||||
{
|
||||
RSR_SWSR, "Software Soft"}, {
|
||||
RSR_SWHR, "Software Hard"}, {
|
||||
RSR_JSRS, "JTAG Soft"}, {
|
||||
RSR_CSHR, "Check Stop"}, {
|
||||
RSR_SWRS, "Software Watchdog"}, {
|
||||
RSR_BMRS, "Bus Monitor"}, {
|
||||
RSR_SRS, "External/Internal Soft"}, {
|
||||
RSR_HRS, "External/Internal Hard"}
|
||||
};
|
||||
int res;
|
||||
ulong rsr = gd->arch.reset_status;
|
||||
int i;
|
||||
char *sep;
|
||||
|
||||
res = snprintf(buf, size, "Reset Status:");
|
||||
if (res < 0) {
|
||||
debug("%s: Could not write reset status message (err = %d)\n",
|
||||
dev->name, res);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
buf += res;
|
||||
size -= res;
|
||||
|
||||
sep = " ";
|
||||
for (i = 0; i < ARRAY_SIZE(bits); i++)
|
||||
/* Print description of set bits */
|
||||
if (rsr & bits[i].mask) {
|
||||
res = snprintf(buf, size, "%s%s%s", sep, bits[i].desc,
|
||||
(i == ARRAY_SIZE(bits) - 1) ? "\n" : "");
|
||||
if (res < 0) {
|
||||
debug("%s: Could not write reset status message (err = %d)\n",
|
||||
dev->name, res);
|
||||
return -EIO;
|
||||
}
|
||||
buf += res;
|
||||
size -= res;
|
||||
sep = ", ";
|
||||
}
|
||||
|
||||
/*
|
||||
* TODO(mario.six@gdsys.cc): Move this into a dedicated
|
||||
* arbiter driver
|
||||
*/
|
||||
if (CONFIG_IS_ENABLED(CONFIG_DISPLAY_AER_FULL) ||
|
||||
CONFIG_IS_ENABLED(CONFIG_DISPLAY_AER_BRIEF)) {
|
||||
/*
|
||||
* If there was a bus monitor reset event, we force the arbiter
|
||||
* event to be printed
|
||||
*/
|
||||
res = print_83xx_arb_event(rsr & RSR_BMRS, buf, size);
|
||||
if (res < 0) {
|
||||
debug("%s: Could not write arbiter event message (err = %d)\n",
|
||||
dev->name, res);
|
||||
return -EIO;
|
||||
}
|
||||
buf += res;
|
||||
size -= res;
|
||||
}
|
||||
snprintf(buf, size, "\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct sysreset_ops mpc83xx_sysreset = {
|
||||
.request = mpc83xx_sysreset_request,
|
||||
.get_status = mpc83xx_sysreset_get_status,
|
||||
};
|
||||
|
||||
U_BOOT_DRIVER(sysreset_mpc83xx) = {
|
||||
.name = "mpc83xx_sysreset",
|
||||
.id = UCLASS_SYSRESET,
|
||||
.ops = &mpc83xx_sysreset,
|
||||
};
|
103
drivers/sysreset/sysreset_mpc83xx.h
Normal file
103
drivers/sysreset/sysreset_mpc83xx.h
Normal file
|
@ -0,0 +1,103 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||
/*
|
||||
* (C) Copyright 2018
|
||||
* Mario Six, Guntermann & Drunck GmbH, mario.six@gdsys.cc
|
||||
*/
|
||||
|
||||
#ifndef _SYSRESET_MPC83XX_H_
|
||||
#define _SYSRESET_MPC83XX_H_
|
||||
|
||||
/*
|
||||
* String array for all possible event types; indexed by the EVENT field of the
|
||||
* AEATR register.
|
||||
*/
|
||||
static const char * const event[] = {
|
||||
"Address Time Out",
|
||||
"Data Time Out",
|
||||
"Address Only Transfer Type",
|
||||
"External Control Word Transfer Type",
|
||||
"Reserved Transfer Type",
|
||||
"Transfer Error",
|
||||
"reserved",
|
||||
"reserved"
|
||||
};
|
||||
|
||||
/*
|
||||
* String array for all possible master IDs, which reflects the source of the
|
||||
* transaction that caused the error; indexed by the MSTR_ID field of the AEATR
|
||||
* register.
|
||||
*/
|
||||
static const char * const master[] = {
|
||||
"e300 Core Data Transaction",
|
||||
"reserved",
|
||||
"e300 Core Instruction Fetch",
|
||||
"reserved",
|
||||
"TSEC1",
|
||||
"TSEC2",
|
||||
"USB MPH",
|
||||
"USB DR",
|
||||
"Encryption Core",
|
||||
"I2C Boot Sequencer",
|
||||
"JTAG",
|
||||
"reserved",
|
||||
"eSDHC",
|
||||
"PCI1",
|
||||
"PCI2",
|
||||
"DMA",
|
||||
"QUICC Engine 00",
|
||||
"QUICC Engine 01",
|
||||
"QUICC Engine 10",
|
||||
"QUICC Engine 11",
|
||||
"reserved",
|
||||
"reserved",
|
||||
"reserved",
|
||||
"reserved",
|
||||
"SATA1",
|
||||
"SATA2",
|
||||
"SATA3",
|
||||
"SATA4",
|
||||
"reserved",
|
||||
"PCI Express 1",
|
||||
"PCI Express 2",
|
||||
"TDM-DMAC"
|
||||
};
|
||||
|
||||
/*
|
||||
* String array for all possible transfer types; indexed by the TTYPE field of
|
||||
* the AEATR register.
|
||||
*/
|
||||
static const char * const transfer[] = {
|
||||
"Address-only, Clean Block",
|
||||
"Address-only, lwarx reservation set",
|
||||
"Single-beat or Burst write",
|
||||
"reserved",
|
||||
"Address-only, Flush Block",
|
||||
"reserved",
|
||||
"Burst write",
|
||||
"reserved",
|
||||
"Address-only, sync",
|
||||
"Address-only, tlbsync",
|
||||
"Single-beat or Burst read",
|
||||
"Single-beat or Burst read",
|
||||
"Address-only, Kill Block",
|
||||
"Address-only, icbi",
|
||||
"Burst read",
|
||||
"reserved",
|
||||
"Address-only, eieio",
|
||||
"reserved",
|
||||
"Single-beat write",
|
||||
"reserved",
|
||||
"ecowx - Illegal single-beat write",
|
||||
"reserved",
|
||||
"reserved",
|
||||
"reserved",
|
||||
"Address-only, TLB Invalidate",
|
||||
"reserved",
|
||||
"Single-beat or Burst read",
|
||||
"reserved",
|
||||
"eciwx - Illegal single-beat read",
|
||||
"reserved",
|
||||
"Burst read",
|
||||
"reserved"
|
||||
};
|
||||
#endif /* _SYSRESET_MPC83XX_H_ */
|
|
@ -29,6 +29,13 @@ static int sandbox_warm_sysreset_request(struct udevice *dev,
|
|||
return -EINPROGRESS;
|
||||
}
|
||||
|
||||
int sandbox_warm_sysreset_get_status(struct udevice *dev, char *buf, int size)
|
||||
{
|
||||
strlcpy(buf, "Reset Status: WARM", size);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sandbox_sysreset_request(struct udevice *dev, enum sysreset_t type)
|
||||
{
|
||||
struct sandbox_state *state = state_get_current();
|
||||
|
@ -60,8 +67,16 @@ static int sandbox_sysreset_request(struct udevice *dev, enum sysreset_t type)
|
|||
return -EINPROGRESS;
|
||||
}
|
||||
|
||||
int sandbox_sysreset_get_status(struct udevice *dev, char *buf, int size)
|
||||
{
|
||||
strlcpy(buf, "Reset Status: COLD", size);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct sysreset_ops sandbox_sysreset_ops = {
|
||||
.request = sandbox_sysreset_request,
|
||||
.get_status = sandbox_sysreset_get_status,
|
||||
};
|
||||
|
||||
static const struct udevice_id sandbox_sysreset_ids[] = {
|
||||
|
@ -78,6 +93,7 @@ U_BOOT_DRIVER(sysreset_sandbox) = {
|
|||
|
||||
static struct sysreset_ops sandbox_warm_sysreset_ops = {
|
||||
.request = sandbox_warm_sysreset_request,
|
||||
.get_status = sandbox_warm_sysreset_get_status,
|
||||
};
|
||||
|
||||
static const struct udevice_id sandbox_warm_sysreset_ids[] = {
|
||||
|
|
|
@ -140,4 +140,11 @@ config STM32_TIMER
|
|||
Select this to enable support for the timer found on
|
||||
STM32 devices.
|
||||
|
||||
config MPC83XX_TIMER
|
||||
bool "MPC83xx timer support"
|
||||
depends on TIMER
|
||||
help
|
||||
Select this to enable support for the timer found on
|
||||
devices based on the MPC83xx family of SoCs.
|
||||
|
||||
endmenu
|
||||
|
|
|
@ -3,17 +3,18 @@
|
|||
# Copyright (C) 2015 Thomas Chou <thomas@wytron.com.tw>
|
||||
|
||||
obj-y += timer-uclass.o
|
||||
obj-$(CONFIG_AG101P_TIMER) += ag101p_timer.o
|
||||
obj-$(CONFIG_ALTERA_TIMER) += altera_timer.o
|
||||
obj-$(CONFIG_ARC_TIMER) += arc_timer.o
|
||||
obj-$(CONFIG_AST_TIMER) += ast_timer.o
|
||||
obj-$(CONFIG_ATCPIT100_TIMER) += atcpit100_timer.o
|
||||
obj-$(CONFIG_ATMEL_PIT_TIMER) += atmel_pit_timer.o
|
||||
obj-$(CONFIG_CADENCE_TTC_TIMER) += cadence-ttc.o
|
||||
obj-$(CONFIG_DESIGNWARE_APB_TIMER) += dw-apb-timer.o
|
||||
obj-$(CONFIG_SANDBOX_TIMER) += sandbox_timer.o
|
||||
obj-$(CONFIG_X86_TSC_TIMER) += tsc_timer.o
|
||||
obj-$(CONFIG_MPC83XX_TIMER) += mpc83xx_timer.o
|
||||
obj-$(CONFIG_OMAP_TIMER) += omap-timer.o
|
||||
obj-$(CONFIG_AST_TIMER) += ast_timer.o
|
||||
obj-$(CONFIG_STI_TIMER) += sti-timer.o
|
||||
obj-$(CONFIG_ARC_TIMER) += arc_timer.o
|
||||
obj-$(CONFIG_AG101P_TIMER) += ag101p_timer.o
|
||||
obj-$(CONFIG_ATCPIT100_TIMER) += atcpit100_timer.o
|
||||
obj-$(CONFIG_ROCKCHIP_TIMER) += rockchip_timer.o
|
||||
obj-$(CONFIG_ATMEL_PIT_TIMER) += atmel_pit_timer.o
|
||||
obj-$(CONFIG_SANDBOX_TIMER) += sandbox_timer.o
|
||||
obj-$(CONFIG_STI_TIMER) += sti-timer.o
|
||||
obj-$(CONFIG_STM32_TIMER) += stm32_timer.o
|
||||
obj-$(CONFIG_X86_TSC_TIMER) += tsc_timer.o
|
||||
|
|
249
drivers/timer/mpc83xx_timer.c
Normal file
249
drivers/timer/mpc83xx_timer.c
Normal file
|
@ -0,0 +1,249 @@
|
|||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* (C) Copyright 2018
|
||||
* Mario Six, Guntermann & Drunck GmbH, mario.six@gdsys.cc
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <board.h>
|
||||
#include <clk.h>
|
||||
#include <dm.h>
|
||||
#include <timer.h>
|
||||
#include <watchdog.h>
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
/**
|
||||
* struct mpc83xx_timer_priv - Private data structure for MPC83xx timer driver
|
||||
* @decrementer_count: Value to which the decrementer register should be re-set
|
||||
* to when a timer interrupt occurs, thus determines the
|
||||
* interrupt frequency (value for 1e6/HZ microseconds)
|
||||
* @timestamp: Counter for the number of timer interrupts that have
|
||||
* occurred (i.e. can be used to trigger events
|
||||
* periodically in the timer interrupt)
|
||||
*/
|
||||
struct mpc83xx_timer_priv {
|
||||
uint decrementer_count;
|
||||
ulong timestamp;
|
||||
};
|
||||
|
||||
/*
|
||||
* Bitmask for enabling the time base in the SPCR (System Priority
|
||||
* Configuration Register)
|
||||
*/
|
||||
static const u32 SPCR_TBEN_MASK = BIT(31 - 9);
|
||||
|
||||
/**
|
||||
* get_dec() - Get the value of the decrementer register
|
||||
*
|
||||
* Return: The value of the decrementer register
|
||||
*/
|
||||
static inline unsigned long get_dec(void)
|
||||
{
|
||||
unsigned long val;
|
||||
|
||||
asm volatile ("mfdec %0" : "=r" (val) : );
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
/**
|
||||
* set_dec() - Set the value of the decrementer register
|
||||
* @val: The value of the decrementer register to be set
|
||||
*/
|
||||
static inline void set_dec(unsigned long val)
|
||||
{
|
||||
if (val)
|
||||
asm volatile ("mtdec %0"::"r" (val));
|
||||
}
|
||||
|
||||
/**
|
||||
* mftbu() - Get value of TBU (upper time base) register
|
||||
*
|
||||
* Return: Value of the TBU register
|
||||
*/
|
||||
static inline u32 mftbu(void)
|
||||
{
|
||||
u32 rval;
|
||||
|
||||
asm volatile("mftbu %0" : "=r" (rval));
|
||||
return rval;
|
||||
}
|
||||
|
||||
/**
|
||||
* mftb() - Get value of TBL (lower time base) register
|
||||
*
|
||||
* Return: Value of the TBL register
|
||||
*/
|
||||
static inline u32 mftb(void)
|
||||
{
|
||||
u32 rval;
|
||||
|
||||
asm volatile("mftb %0" : "=r" (rval));
|
||||
return rval;
|
||||
}
|
||||
|
||||
/*
|
||||
* TODO(mario.six@gdsys.cc): This should really be done by timer_init, and the
|
||||
* interrupt init should go into a interrupt driver.
|
||||
*/
|
||||
int interrupt_init(void)
|
||||
{
|
||||
immap_t *immr = (immap_t *)CONFIG_SYS_IMMR;
|
||||
struct udevice *csb;
|
||||
struct udevice *board;
|
||||
struct udevice *timer;
|
||||
struct mpc83xx_timer_priv *timer_priv;
|
||||
struct clk clock;
|
||||
int ret;
|
||||
|
||||
ret = uclass_first_device_err(UCLASS_TIMER, &timer);
|
||||
if (ret) {
|
||||
debug("%s: Could not find timer device (error: %d)",
|
||||
__func__, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
timer_priv = dev_get_priv(timer);
|
||||
|
||||
if (board_get(&board)) {
|
||||
debug("%s: board device could not be fetched.\n", __func__);
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
ret = uclass_get_device_by_phandle(UCLASS_SIMPLE_BUS, board,
|
||||
"csb", &csb);
|
||||
if (ret) {
|
||||
debug("%s: Could not retrieve CSB device (error: %d)",
|
||||
__func__, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = clk_get_by_index(csb, 0, &clock);
|
||||
if (ret) {
|
||||
debug("%s: Could not retrieve clock (error: %d)",
|
||||
__func__, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
timer_priv->decrementer_count = (clk_get_rate(&clock) / 4)
|
||||
/ CONFIG_SYS_HZ;
|
||||
/* Enable e300 time base */
|
||||
setbits_be32(&immr->sysconf.spcr, SPCR_TBEN_MASK);
|
||||
|
||||
set_dec(timer_priv->decrementer_count);
|
||||
|
||||
/* Switch on interrupts */
|
||||
set_msr(get_msr() | MSR_EE);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* timer_interrupt() - Handler for the timer interrupt
|
||||
* @regs: Array of register values
|
||||
*/
|
||||
void timer_interrupt(struct pt_regs *regs)
|
||||
{
|
||||
struct udevice *timer = gd->timer;
|
||||
struct mpc83xx_timer_priv *priv;
|
||||
|
||||
/*
|
||||
* During initialization, gd->timer might not be set yet, but the timer
|
||||
* interrupt may already be enabled. In this case, wait for the
|
||||
* initialization to complete
|
||||
*/
|
||||
if (!timer)
|
||||
return;
|
||||
|
||||
priv = dev_get_priv(timer);
|
||||
|
||||
/* Restore Decrementer Count */
|
||||
set_dec(priv->decrementer_count);
|
||||
|
||||
priv->timestamp++;
|
||||
|
||||
#if defined(CONFIG_WATCHDOG) || defined(CONFIG_HW_WATCHDOG)
|
||||
if ((timestamp % (CONFIG_SYS_WATCHDOG_FREQ)) == 0)
|
||||
WATCHDOG_RESET();
|
||||
#endif /* CONFIG_WATCHDOG || CONFIG_HW_WATCHDOG */
|
||||
|
||||
#ifdef CONFIG_LED_STATUS
|
||||
status_led_tick(priv->timestamp);
|
||||
#endif /* CONFIG_LED_STATUS */
|
||||
|
||||
#ifdef CONFIG_SHOW_ACTIVITY
|
||||
board_show_activity(priv->timestamp);
|
||||
#endif /* CONFIG_SHOW_ACTIVITY */
|
||||
}
|
||||
|
||||
void wait_ticks(ulong ticks)
|
||||
{
|
||||
ulong end = get_ticks() + ticks;
|
||||
|
||||
while (end > get_ticks())
|
||||
WATCHDOG_RESET();
|
||||
}
|
||||
|
||||
static int mpc83xx_timer_get_count(struct udevice *dev, u64 *count)
|
||||
{
|
||||
u32 tbu, tbl;
|
||||
|
||||
/*
|
||||
* To make sure that no tbl overflow occurred between reading tbl and
|
||||
* tbu, read tbu again, and compare it with the previously read tbu
|
||||
* value: If they're different, a tbl overflow has occurred.
|
||||
*/
|
||||
do {
|
||||
tbu = mftbu();
|
||||
tbl = mftb();
|
||||
} while (tbu != mftbu());
|
||||
|
||||
*count = (tbu * 0x10000ULL) + tbl;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mpc83xx_timer_probe(struct udevice *dev)
|
||||
{
|
||||
struct timer_dev_priv *uc_priv = dev->uclass_priv;
|
||||
struct clk clock;
|
||||
int ret;
|
||||
|
||||
ret = interrupt_init();
|
||||
if (ret) {
|
||||
debug("%s: interrupt_init failed (err = %d)\n",
|
||||
dev->name, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = clk_get_by_index(dev, 0, &clock);
|
||||
if (ret) {
|
||||
debug("%s: Could not retrieve clock (err = %d)\n",
|
||||
dev->name, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
uc_priv->clock_rate = (clk_get_rate(&clock) + 3L) / 4L;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct timer_ops mpc83xx_timer_ops = {
|
||||
.get_count = mpc83xx_timer_get_count,
|
||||
};
|
||||
|
||||
static const struct udevice_id mpc83xx_timer_ids[] = {
|
||||
{ .compatible = "fsl,mpc83xx-timer" },
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
|
||||
U_BOOT_DRIVER(mpc83xx_timer) = {
|
||||
.name = "mpc83xx_timer",
|
||||
.id = UCLASS_TIMER,
|
||||
.of_match = mpc83xx_timer_ids,
|
||||
.probe = mpc83xx_timer_probe,
|
||||
.ops = &mpc83xx_timer_ops,
|
||||
.flags = DM_FLAG_PRE_RELOC,
|
||||
.priv_auto_alloc_size = sizeof(struct mpc83xx_timer_priv),
|
||||
};
|
|
@ -9,19 +9,21 @@
|
|||
|
||||
/**
|
||||
* struct cpu_platdata - platform data for a CPU
|
||||
* @cpu_id: Platform-specific way of identifying the CPU.
|
||||
* @ucode_version: Microcode version, if CPU_FEAT_UCODE is set
|
||||
* @device_id: Driver-defined device identifier
|
||||
* @family: DMTF CPU Family identifier
|
||||
* @id: DMTF CPU Processor identifier
|
||||
*
|
||||
* This can be accessed with dev_get_parent_platdata() for any UCLASS_CPU
|
||||
* device.
|
||||
*
|
||||
* @cpu_id: Platform-specific way of identifying the CPU.
|
||||
* @ucode_version: Microcode version, if CPU_FEAT_UCODE is set
|
||||
*/
|
||||
struct cpu_platdata {
|
||||
int cpu_id;
|
||||
int ucode_version;
|
||||
ulong device_id;
|
||||
u16 family; /* DMTF CPU Family */
|
||||
u32 id[2]; /* DMTF CPU Processor IDs */
|
||||
u16 family;
|
||||
u32 id[2];
|
||||
};
|
||||
|
||||
/* CPU features - mostly just a placeholder for now */
|
||||
|
@ -88,39 +90,46 @@ struct cpu_ops {
|
|||
|
||||
/**
|
||||
* cpu_get_desc() - Get a description string for a CPU
|
||||
*
|
||||
* @dev: Device to check (UCLASS_CPU)
|
||||
* @buf: Buffer to place string
|
||||
* @size: Size of string space
|
||||
* @return 0 if OK, -ENOSPC if buffer is too small, other -ve on error
|
||||
*
|
||||
* Return: 0 if OK, -ENOSPC if buffer is too small, other -ve on error
|
||||
*/
|
||||
int cpu_get_desc(struct udevice *dev, char *buf, int size);
|
||||
|
||||
/**
|
||||
* cpu_get_info() - Get information about a CPU
|
||||
*
|
||||
* @dev: Device to check (UCLASS_CPU)
|
||||
* @info: Returns CPU info
|
||||
* @return 0 if OK, -ve on error
|
||||
*
|
||||
* Return: 0 if OK, -ve on error
|
||||
*/
|
||||
int cpu_get_info(struct udevice *dev, struct cpu_info *info);
|
||||
|
||||
/**
|
||||
* cpu_get_count() - Get number of CPUs
|
||||
*
|
||||
* @dev: Device to check (UCLASS_CPU)
|
||||
* @return CPU count if OK, -ve on error
|
||||
*
|
||||
* Return: CPU count if OK, -ve on error
|
||||
*/
|
||||
int cpu_get_count(struct udevice *dev);
|
||||
|
||||
/**
|
||||
* cpu_get_vendor() - Get vendor name of a CPU
|
||||
*
|
||||
* @dev: Device to check (UCLASS_CPU)
|
||||
* @buf: Buffer to place string
|
||||
* @size: Size of string space
|
||||
* @return 0 if OK, -ENOSPC if buffer is too small, other -ve on error
|
||||
*
|
||||
* Return: 0 if OK, -ENOSPC if buffer is too small, other -ve on error
|
||||
*/
|
||||
int cpu_get_vendor(struct udevice *dev, char *buf, int size);
|
||||
|
||||
/**
|
||||
* cpu_probe_all() - Probe all available CPUs
|
||||
*
|
||||
* Return: 0 if OK, -ve on error
|
||||
*/
|
||||
int cpu_probe_all(void);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -193,6 +193,22 @@ static inline struct device_node *of_find_node_by_path(const char *path)
|
|||
struct device_node *of_find_compatible_node(struct device_node *from,
|
||||
const char *type, const char *compatible);
|
||||
|
||||
/**
|
||||
* of_find_node_by_prop_value() - find a node with a given property value
|
||||
*
|
||||
* Find a node based on a property value.
|
||||
* @from: Node to start searching from or NULL. the node you pass will not be
|
||||
* searched, only the next one will; typically, you pass what the previous
|
||||
* call returned.
|
||||
* @propname: property name to check
|
||||
* @propval: property value to search for
|
||||
* @proplen: length of the value in propval
|
||||
* @return node pointer or NULL if not found
|
||||
*/
|
||||
struct device_node *of_find_node_by_prop_value(struct device_node *from,
|
||||
const char *propname,
|
||||
const void *propval,
|
||||
int proplen);
|
||||
/**
|
||||
* of_find_node_by_phandle() - Find a node given a phandle
|
||||
*
|
||||
|
|
|
@ -702,6 +702,20 @@ int ofnode_read_resource_byname(ofnode node, const char *name,
|
|||
*/
|
||||
ofnode ofnode_by_compatible(ofnode from, const char *compat);
|
||||
|
||||
/**
|
||||
* ofnode_by_prop_value() - Find the next node with given property value
|
||||
*
|
||||
* Find the next node after @from that has a @propname with a value
|
||||
* @propval and a length @proplen.
|
||||
*
|
||||
* @from: ofnode to start from (use ofnode_null() to start at the
|
||||
* beginning) @propname: property name to check @propval: property value to
|
||||
* search for @proplen: length of the value in propval @return ofnode
|
||||
* found, or ofnode_null() if none
|
||||
*/
|
||||
ofnode ofnode_by_prop_value(ofnode from, const char *propname,
|
||||
const void *propval, int proplen);
|
||||
|
||||
/**
|
||||
* ofnode_for_each_subnode() - iterate over all subnodes of a parent
|
||||
*
|
||||
|
|
|
@ -58,6 +58,7 @@ struct udevice;
|
|||
* @post_probe: Called after a new device is probed
|
||||
* @pre_remove: Called before a device is removed
|
||||
* @child_post_bind: Called after a child is bound to a device in this uclass
|
||||
* @child_pre_probe: Called before a child is probed in this uclass
|
||||
* @init: Called to set up the uclass
|
||||
* @destroy: Called to destroy the uclass
|
||||
* @priv_auto_alloc_size: If non-zero this is the size of the private data
|
||||
|
|
33
include/dt-bindings/clk/mpc83xx-clk.h
Normal file
33
include/dt-bindings/clk/mpc83xx-clk.h
Normal file
|
@ -0,0 +1,33 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||
/*
|
||||
* (C) Copyright 2018
|
||||
* Mario Six, Guntermann & Drunck GmbH, mario.six@gdsys.cc
|
||||
*/
|
||||
|
||||
#ifndef DT_BINDINGS_MPC83XX_CLK_H
|
||||
#define DT_BINDINGS_MPC83XX_CLK_H
|
||||
#define MPC83XX_CLK_CORE 0
|
||||
#define MPC83XX_CLK_CSB 1
|
||||
#define MPC83XX_CLK_QE 2
|
||||
#define MPC83XX_CLK_BRG 3
|
||||
#define MPC83XX_CLK_LBIU 4
|
||||
#define MPC83XX_CLK_LCLK 5
|
||||
#define MPC83XX_CLK_MEM 6
|
||||
#define MPC83XX_CLK_MEM_SEC 7
|
||||
#define MPC83XX_CLK_ENC 8
|
||||
#define MPC83XX_CLK_I2C1 9
|
||||
#define MPC83XX_CLK_I2C2 10
|
||||
#define MPC83XX_CLK_TDM 11
|
||||
#define MPC83XX_CLK_SDHC 12
|
||||
#define MPC83XX_CLK_TSEC1 13
|
||||
#define MPC83XX_CLK_TSEC2 14
|
||||
#define MPC83XX_CLK_USBDR 15
|
||||
#define MPC83XX_CLK_USBMPH 16
|
||||
#define MPC83XX_CLK_PCIEXP1 17
|
||||
#define MPC83XX_CLK_PCIEXP2 18
|
||||
#define MPC83XX_CLK_SATA 19
|
||||
#define MPC83XX_CLK_DMAC 20
|
||||
#define MPC83XX_CLK_PCI 21
|
||||
/* Count */
|
||||
#define MPC83XX_CLK_COUNT 22
|
||||
#endif /* DT_BINDINGS_MPC83XX_CLK_H */
|
161
include/dt-bindings/memory/mpc83xx-sdram.h
Normal file
161
include/dt-bindings/memory/mpc83xx-sdram.h
Normal file
|
@ -0,0 +1,161 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||
/*
|
||||
* (C) Copyright 2018
|
||||
* Mario Six, Guntermann & Drunck GmbH, mario.six@gdsys.cc
|
||||
*/
|
||||
|
||||
#ifndef DT_BINDINGS_MPC83XX_SDRAM_H
|
||||
#define DT_BINDINGS_MPC83XX_SDRAM_H
|
||||
|
||||
/* DDR Control Driver register */
|
||||
|
||||
#define DSO_DISABLE 0
|
||||
#define DSO_ENABLE 1
|
||||
|
||||
#define DSO_P_IMPEDANCE_HIGHEST_Z 0x0
|
||||
#define DSO_P_IMPEDANCE_MUCH_HIGHER_Z 0x8
|
||||
#define DSO_P_IMPEDANCE_HIGHER_Z 0xC
|
||||
#define DSO_P_IMPEDANCE_NOMINAL 0xE
|
||||
#define DSO_P_IMPEDANCE_LOWER_Z 0xF
|
||||
|
||||
#define DSO_N_IMPEDANCE_HIGHEST_Z 0x0
|
||||
#define DSO_N_IMPEDANCE_MUCH_HIGHER_Z 0x8
|
||||
#define DSO_N_IMPEDANCE_HIGHER_Z 0xC
|
||||
#define DSO_N_IMPEDANCE_NOMINAL 0xE
|
||||
#define DSO_N_IMPEDANCE_LOWER_Z 0xF
|
||||
|
||||
#define ODT_TERMINATION_75_OHM 0
|
||||
#define ODT_TERMINATION_150_OHM 1
|
||||
|
||||
#define DDR_TYPE_DDR2_1_8_VOLT 0
|
||||
#define DDR_TYPE_DDR1_2_5_VOLT 1
|
||||
|
||||
#define MVREF_SEL_EXTERNAL 0
|
||||
#define MVREF_SEL_INTERNAL_GVDD 1
|
||||
|
||||
#define M_ODR_ENABLE 0
|
||||
#define M_ODR_DISABLE 1
|
||||
|
||||
/* CS config register */
|
||||
|
||||
#define AUTO_PRECHARGE_ENABLE 0x00800000
|
||||
#define AUTO_PRECHARGE_DISABLE 0x00000000
|
||||
|
||||
#define ODT_RD_NEVER 0x00000000
|
||||
#define ODT_RD_ONLY_CURRENT 0x00100000
|
||||
#define ODT_RD_ONLY_OTHER_CS 0x00200000
|
||||
#define ODT_RD_ONLY_OTHER_DIMM 0x00300000
|
||||
#define ODT_RD_ALL 0x00400000
|
||||
|
||||
#define ODT_WR_NEVER 0x00000000
|
||||
#define ODT_WR_ONLY_CURRENT 0x00010000
|
||||
#define ODT_WR_ONLY_OTHER_CS 0x00020000
|
||||
#define ODT_WR_ONLY_OTHER_DIMM 0x00030000
|
||||
#define ODT_WR_ALL 0x00040000
|
||||
|
||||
/* DDR SDRAM Clock Control register */
|
||||
|
||||
#define CLOCK_ADJUST_025 0x01000000
|
||||
#define CLOCK_ADJUST_05 0x02000000
|
||||
#define CLOCK_ADJUST_075 0x03000000
|
||||
#define CLOCK_ADJUST_1 0x04000000
|
||||
|
||||
#define CASLAT_20 0x3 /* CAS latency = 2.0 */
|
||||
#define CASLAT_25 0x4 /* CAS latency = 2.5 */
|
||||
#define CASLAT_30 0x5 /* CAS latency = 3.0 */
|
||||
#define CASLAT_35 0x6 /* CAS latency = 3.5 */
|
||||
#define CASLAT_40 0x7 /* CAS latency = 4.0 */
|
||||
#define CASLAT_45 0x8 /* CAS latency = 4.5 */
|
||||
#define CASLAT_50 0x9 /* CAS latency = 5.0 */
|
||||
#define CASLAT_55 0xa /* CAS latency = 5.5 */
|
||||
#define CASLAT_60 0xb /* CAS latency = 6.0 */
|
||||
#define CASLAT_65 0xc /* CAS latency = 6.5 */
|
||||
#define CASLAT_70 0xd /* CAS latency = 7.0 */
|
||||
#define CASLAT_75 0xe /* CAS latency = 7.5 */
|
||||
#define CASLAT_80 0xf /* CAS latency = 8.0 */
|
||||
|
||||
/* DDR SDRAM Timing Configuration 2 register */
|
||||
|
||||
#define READ_LAT_PLUS_1 0x0
|
||||
#define READ_LAT 0x2
|
||||
#define READ_LAT_PLUS_1_4 0x3
|
||||
#define READ_LAT_PLUS_1_2 0x4
|
||||
#define READ_LAT_PLUS_3_4 0x5
|
||||
#define READ_LAT_PLUS_5_4 0x7
|
||||
#define READ_LAT_PLUS_3_2 0x8
|
||||
#define READ_LAT_PLUS_7_4 0x9
|
||||
#define READ_LAT_PLUS_2 0xA
|
||||
#define READ_LAT_PLUS_9_4 0xB
|
||||
#define READ_LAT_PLUS_5_2 0xC
|
||||
#define READ_LAT_PLUS_11_4 0xD
|
||||
#define READ_LAT_PLUS_3 0xE
|
||||
#define READ_LAT_PLUS_13_4 0xF
|
||||
#define READ_LAT_PLUS_7_2 0x10
|
||||
#define READ_LAT_PLUS_15_4 0x11
|
||||
#define READ_LAT_PLUS_4 0x12
|
||||
#define READ_LAT_PLUS_17_4 0x13
|
||||
#define READ_LAT_PLUS_9_2 0x14
|
||||
#define READ_LAT_PLUS_19_4 0x15
|
||||
|
||||
#define CLOCK_DELAY_0 0x0
|
||||
#define CLOCK_DELAY_1_4 0x1
|
||||
#define CLOCK_DELAY_1_2 0x2
|
||||
#define CLOCK_DELAY_3_4 0x3
|
||||
#define CLOCK_DELAY_1 0x4
|
||||
#define CLOCK_DELAY_5_4 0x5
|
||||
#define CLOCK_DELAY_3_2 0x6
|
||||
|
||||
/* DDR SDRAM Control Configuration */
|
||||
|
||||
#define SREN_DISABLE 0x0
|
||||
#define SREN_ENABLE 0x1
|
||||
|
||||
#define ECC_DISABLE 0x0
|
||||
#define ECC_ENABLE 0x1
|
||||
|
||||
#define RD_DISABLE 0x0
|
||||
#define RD_ENABLE 0x1
|
||||
|
||||
#define TYPE_DDR1 0x2
|
||||
#define TYPE_DDR2 0x3
|
||||
|
||||
#define DYN_PWR_DISABLE 0x0
|
||||
#define DYN_PWR_ENABLE 0x1
|
||||
|
||||
#define DATA_BUS_WIDTH_16 0x1
|
||||
#define DATA_BUS_WIDTH_32 0x2
|
||||
|
||||
#define NCAP_DISABLE 0x0
|
||||
#define NCAP_ENABLE 0x1
|
||||
|
||||
#define TIMING_1T 0x0
|
||||
#define TIMING_2T 0x1
|
||||
|
||||
#define INTERLEAVE_NONE 0x0
|
||||
#define INTERLEAVE_1_AND_2 0x1
|
||||
|
||||
#define PRECHARGE_MA_10 0x0
|
||||
#define PRECHARGE_MA_8 0x1
|
||||
|
||||
#define STRENGTH_FULL 0x0
|
||||
#define STRENGTH_HALF 0x1
|
||||
|
||||
#define INITIALIZATION_DONT_BYPASS 0x0
|
||||
#define INITIALIZATION_BYPASS 0x1
|
||||
|
||||
/* DDR SDRAM Control Configuration 2 register */
|
||||
|
||||
#define MODE_NORMAL 0x0
|
||||
#define MODE_REFRESH 0x1
|
||||
|
||||
#define DLL_RESET_ENABLE 0x0
|
||||
#define DLL_RESET_DISABLE 0x1
|
||||
|
||||
#define DQS_TRUE 0x0
|
||||
|
||||
#define ODT_ASSERT_NEVER 0x0
|
||||
#define ODT_ASSERT_WRITES 0x1
|
||||
#define ODT_ASSERT_READS 0x2
|
||||
#define ODT_ASSERT_ALWAYS 0x3
|
||||
|
||||
#endif
|
|
@ -27,7 +27,7 @@ void board_init_f(ulong dummy);
|
|||
* board_f.c for where it is called. If this is not provided, a default
|
||||
* version (which does nothing) will be used.
|
||||
*
|
||||
* @return: 0 on success, otherwise error
|
||||
* Return: 0 on success, otherwise error
|
||||
*/
|
||||
int arch_cpu_init(void);
|
||||
|
||||
|
@ -38,7 +38,7 @@ int arch_cpu_init(void);
|
|||
* relocation. This is similar to arch_cpu_init() but is able to reference
|
||||
* devices
|
||||
*
|
||||
* @return 0 if OK, -ve on error
|
||||
* Return: 0 if OK, -ve on error
|
||||
*/
|
||||
int arch_cpu_init_dm(void);
|
||||
|
||||
|
@ -50,7 +50,7 @@ int arch_cpu_init_dm(void);
|
|||
* board_f.c for where it is called. If this is not provided, a default
|
||||
* version (which does nothing) will be used.
|
||||
*
|
||||
* @return: 0 on success, otherwise error
|
||||
* Return: 0 on success, otherwise error
|
||||
*/
|
||||
int mach_cpu_init(void);
|
||||
|
||||
|
@ -60,6 +60,8 @@ int mach_cpu_init(void);
|
|||
* Where U-Boot relies on binary blobs to handle part of the system init, this
|
||||
* function can be used to set up the blobs. This is used on some Intel
|
||||
* platforms.
|
||||
*
|
||||
* Return: 0
|
||||
*/
|
||||
int arch_fsp_init(void);
|
||||
|
||||
|
@ -78,12 +80,12 @@ int dram_init(void);
|
|||
* CONFIG_SYS_SDRAM_BASE and the size will be determined by a call to
|
||||
* get_effective_memsize().
|
||||
*
|
||||
* @return 0 if OK, -ve on error
|
||||
* Return: 0 if OK, -ve on error
|
||||
*/
|
||||
int dram_init_banksize(void);
|
||||
|
||||
/**
|
||||
* Reserve all necessary stacks
|
||||
* arch_reserve_stacks() - Reserve all necessary stacks
|
||||
*
|
||||
* This is used in generic board init sequence in common/board_f.c. Each
|
||||
* architecture could provide this function to tailor the required stacks.
|
||||
|
@ -96,21 +98,29 @@ int dram_init_banksize(void);
|
|||
* positions of the stack. The stack pointer(s) will be set to this later.
|
||||
* gd->irq_sp is only required, if the architecture needs it.
|
||||
*
|
||||
* @return 0 if no error
|
||||
* Return: 0 if no error
|
||||
*/
|
||||
int arch_reserve_stacks(void);
|
||||
|
||||
/**
|
||||
* init_cache_f_r() - Turn on the cache in preparation for relocation
|
||||
*
|
||||
* @return 0 if OK, -ve on error
|
||||
* Return: 0 if OK, -ve on error
|
||||
*/
|
||||
int init_cache_f_r(void);
|
||||
|
||||
#if !CONFIG_IS_ENABLED(CPU)
|
||||
/**
|
||||
* print_cpuinfo() - Display information about the CPU
|
||||
*
|
||||
* Return: 0 if OK, -ve on error
|
||||
*/
|
||||
int print_cpuinfo(void);
|
||||
#endif
|
||||
int timer_init(void);
|
||||
int reserve_mmu(void);
|
||||
int misc_init_f(void);
|
||||
|
||||
#if defined(CONFIG_DTB_RESELECT)
|
||||
int embedded_dtb_select(void);
|
||||
#endif
|
||||
|
@ -120,28 +130,28 @@ extern ulong monitor_flash_len;
|
|||
|
||||
/**
|
||||
* ulong board_init_f_alloc_reserve - allocate reserved area
|
||||
* @top: top of the reserve area, growing down.
|
||||
*
|
||||
* This function is called by each architecture very early in the start-up
|
||||
* code to allow the C runtime to reserve space on the stack for writable
|
||||
* 'globals' such as GD and the malloc arena.
|
||||
*
|
||||
* @top: top of the reserve area, growing down.
|
||||
* @return: bottom of reserved area
|
||||
* Return: bottom of reserved area
|
||||
*/
|
||||
ulong board_init_f_alloc_reserve(ulong top);
|
||||
|
||||
/**
|
||||
* board_init_f_init_reserve - initialize the reserved area(s)
|
||||
* @base: top from which reservation was done
|
||||
*
|
||||
* This function is called once the C runtime has allocated the reserved
|
||||
* area on the stack. It must initialize the GD at the base of that area.
|
||||
*
|
||||
* @base: top from which reservation was done
|
||||
*/
|
||||
void board_init_f_init_reserve(ulong base);
|
||||
|
||||
/**
|
||||
* arch_setup_gd() - Set up the global_data pointer
|
||||
* @gd_ptr: Pointer to global data
|
||||
*
|
||||
* This pointer is special in some architectures and cannot easily be assigned
|
||||
* to. For example on x86 it is implemented by adding a specific record to its
|
||||
|
@ -149,8 +159,6 @@ void board_init_f_init_reserve(ulong base);
|
|||
* For most architectures this can simply be:
|
||||
*
|
||||
* gd = gd_ptr;
|
||||
*
|
||||
* @gd_ptr: Pointer to global data
|
||||
*/
|
||||
void arch_setup_gd(gd_t *gd_ptr);
|
||||
|
||||
|
|
|
@ -1,21 +1,105 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||
/*
|
||||
* Based on bitrev from the Linux kernel, by Akinobu Mita
|
||||
*/
|
||||
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
#ifndef _LINUX_BITREV_H
|
||||
#define _LINUX_BITREV_H
|
||||
|
||||
#include <linux/types.h>
|
||||
|
||||
extern u8 const byte_rev_table[256];
|
||||
#ifdef CONFIG_HAVE_ARCH_BITREVERSE
|
||||
#include <asm/bitrev.h>
|
||||
|
||||
static inline u8 bitrev8(u8 byte)
|
||||
#define __bitrev32 __arch_bitrev32
|
||||
#define __bitrev16 __arch_bitrev16
|
||||
#define __bitrev8 __arch_bitrev8
|
||||
|
||||
#else
|
||||
extern u8 const byte_rev_table[256];
|
||||
static inline u8 __bitrev8(u8 byte)
|
||||
{
|
||||
return byte_rev_table[byte];
|
||||
}
|
||||
|
||||
u16 bitrev16(u16 in);
|
||||
u32 bitrev32(u32 in);
|
||||
static inline u16 __bitrev16(u16 x)
|
||||
{
|
||||
return (__bitrev8(x & 0xff) << 8) | __bitrev8(x >> 8);
|
||||
}
|
||||
|
||||
static inline u32 __bitrev32(u32 x)
|
||||
{
|
||||
return (__bitrev16(x & 0xffff) << 16) | __bitrev16(x >> 16);
|
||||
}
|
||||
|
||||
#endif /* CONFIG_HAVE_ARCH_BITREVERSE */
|
||||
|
||||
#define __bitrev8x4(x) (__bitrev32(swab32(x)))
|
||||
|
||||
#define __constant_bitrev32(x) \
|
||||
({ \
|
||||
u32 __x = x; \
|
||||
__x = (__x >> 16) | (__x << 16);\
|
||||
__x = ((__x & (u32)0xFF00FF00UL) >> 8) | ((__x & (u32)0x00FF00FFUL) << 8); \
|
||||
__x = ((__x & (u32)0xF0F0F0F0UL) >> 4) | ((__x & (u32)0x0F0F0F0FUL) << 4); \
|
||||
__x = ((__x & (u32)0xCCCCCCCCUL) >> 2) | ((__x & (u32)0x33333333UL) << 2); \
|
||||
__x = ((__x & (u32)0xAAAAAAAAUL) >> 1) | ((__x & (u32)0x55555555UL) << 1); \
|
||||
__x; \
|
||||
})
|
||||
|
||||
#define __constant_bitrev16(x) \
|
||||
({ \
|
||||
u16 __x = x; \
|
||||
__x = (__x >> 8) | (__x << 8); \
|
||||
__x = ((__x & (u16)0xF0F0U) >> 4) | ((__x & (u16)0x0F0FU) << 4); \
|
||||
__x = ((__x & (u16)0xCCCCU) >> 2) | ((__x & (u16)0x3333U) << 2); \
|
||||
__x = ((__x & (u16)0xAAAAU) >> 1) | ((__x & (u16)0x5555U) << 1); \
|
||||
__x; \
|
||||
})
|
||||
|
||||
#define __constant_bitrev8x4(x) \
|
||||
({ \
|
||||
u32 __x = x; \
|
||||
__x = ((__x & (u32)0xF0F0F0F0UL) >> 4) | ((__x & (u32)0x0F0F0F0FUL) << 4); \
|
||||
__x = ((__x & (u32)0xCCCCCCCCUL) >> 2) | ((__x & (u32)0x33333333UL) << 2); \
|
||||
__x = ((__x & (u32)0xAAAAAAAAUL) >> 1) | ((__x & (u32)0x55555555UL) << 1); \
|
||||
__x; \
|
||||
})
|
||||
|
||||
#define __constant_bitrev8(x) \
|
||||
({ \
|
||||
u8 __x = x; \
|
||||
__x = (__x >> 4) | (__x << 4); \
|
||||
__x = ((__x & (u8)0xCCU) >> 2) | ((__x & (u8)0x33U) << 2); \
|
||||
__x = ((__x & (u8)0xAAU) >> 1) | ((__x & (u8)0x55U) << 1); \
|
||||
__x; \
|
||||
})
|
||||
|
||||
#define bitrev32(x) \
|
||||
({ \
|
||||
u32 __x = x; \
|
||||
__builtin_constant_p(__x) ? \
|
||||
__constant_bitrev32(__x) : \
|
||||
__bitrev32(__x); \
|
||||
})
|
||||
|
||||
#define bitrev16(x) \
|
||||
({ \
|
||||
u16 __x = x; \
|
||||
__builtin_constant_p(__x) ? \
|
||||
__constant_bitrev16(__x) : \
|
||||
__bitrev16(__x); \
|
||||
})
|
||||
|
||||
#define bitrev8x4(x) \
|
||||
({ \
|
||||
u32 __x = x; \
|
||||
__builtin_constant_p(__x) ? \
|
||||
__constant_bitrev8x4(__x) : \
|
||||
__bitrev8x4(__x); \
|
||||
})
|
||||
|
||||
#define bitrev8(x) \
|
||||
({ \
|
||||
u8 __x = x; \
|
||||
__builtin_constant_p(__x) ? \
|
||||
__constant_bitrev8(__x) : \
|
||||
__bitrev8(__x) ; \
|
||||
})
|
||||
#endif /* _LINUX_BITREV_H */
|
||||
|
|
|
@ -1110,6 +1110,8 @@
|
|||
#define CSBNDS_EA 0x000000FF
|
||||
#define CSBNDS_EA_SHIFT 24
|
||||
|
||||
#ifndef CONFIG_MPC83XX_SDRAM
|
||||
|
||||
/*
|
||||
* CSn_CONFIG - Chip Select Configuration Register
|
||||
*/
|
||||
|
@ -1407,6 +1409,8 @@
|
|||
#define ECC_ERROR_MAN_SBEC (0xff000000 >> 24)
|
||||
#define ECC_ERROR_MAN_SBEC_SHIFT 0
|
||||
|
||||
#endif /* !CONFIG_MPC83XX_SDRAM */
|
||||
|
||||
/*
|
||||
* CONFIG_ADDRESS - PCI Config Address Register
|
||||
*/
|
||||
|
@ -1510,6 +1514,7 @@
|
|||
*/
|
||||
#define PMCCR1_POWER_OFF 0x00000020
|
||||
|
||||
#ifndef CONFIG_RAM
|
||||
/*
|
||||
* DDRCDR - DDR Control Driver Register
|
||||
*/
|
||||
|
@ -1531,6 +1536,7 @@
|
|||
#define DDRCDR_DDR_CFG 0x00040000
|
||||
#define DDRCDR_M_ODR 0x00000002
|
||||
#define DDRCDR_Q_DRN 0x00000001
|
||||
#endif /* !CONFIG_RAM */
|
||||
|
||||
/*
|
||||
* PCIE Bridge Register
|
||||
|
|
|
@ -28,6 +28,14 @@ struct sysreset_ops {
|
|||
* (in which case this method will not actually return)
|
||||
*/
|
||||
int (*request)(struct udevice *dev, enum sysreset_t type);
|
||||
/**
|
||||
* get_status() - get printable reset status information
|
||||
*
|
||||
* @buf: Buffer to receive the textual reset information
|
||||
* @size: Size of the passed buffer
|
||||
* @return 0 if OK, -ve on error
|
||||
*/
|
||||
int (*get_status)(struct udevice *dev, char *buf, int size);
|
||||
};
|
||||
|
||||
#define sysreset_get_ops(dev) ((struct sysreset_ops *)(dev)->driver->ops)
|
||||
|
@ -40,6 +48,15 @@ struct sysreset_ops {
|
|||
*/
|
||||
int sysreset_request(struct udevice *dev, enum sysreset_t type);
|
||||
|
||||
/**
|
||||
* get_status() - get printable reset status information
|
||||
*
|
||||
* @buf: Buffer to receive the textual reset information
|
||||
* @size: Size of the passed buffer
|
||||
* @return 0 if OK, -ve on error
|
||||
*/
|
||||
int sysreset_get_status(struct udevice *dev, char *buf, int size);
|
||||
|
||||
/**
|
||||
* sysreset_walk() - cause a system reset
|
||||
*
|
||||
|
|
28
lib/bitrev.c
28
lib/bitrev.c
|
@ -1,13 +1,14 @@
|
|||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
*
|
||||
* Based on bitrev from the Linux kernel, by Akinobu Mita
|
||||
*/
|
||||
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
#ifndef CONFIG_HAVE_ARCH_BITREVERSE
|
||||
#include <linux/types.h>
|
||||
#include <linux/compat.h>
|
||||
#include <linux/bitrev.h>
|
||||
|
||||
MODULE_AUTHOR("Akinobu Mita <akinobu.mita@gmail.com>");
|
||||
MODULE_DESCRIPTION("Bit ordering reversal functions");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
const u8 byte_rev_table[256] = {
|
||||
0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
|
||||
0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
|
||||
|
@ -42,17 +43,6 @@ const u8 byte_rev_table[256] = {
|
|||
0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef,
|
||||
0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff,
|
||||
};
|
||||
EXPORT_SYMBOL_GPL(byte_rev_table);
|
||||
|
||||
u16 bitrev16(u16 x)
|
||||
{
|
||||
return (bitrev8(x & 0xff) << 8) | bitrev8(x >> 8);
|
||||
}
|
||||
|
||||
/**
|
||||
* bitrev32 - reverse the order of bits in a u32 value
|
||||
* @x: value to be bit-reversed
|
||||
*/
|
||||
u32 bitrev32(u32 x)
|
||||
{
|
||||
return (bitrev16(x & 0xffff) << 16) | bitrev16(x >> 16);
|
||||
}
|
||||
#endif /* CONFIG_HAVE_ARCH_BITREVERSE */
|
||||
|
|
|
@ -47,4 +47,5 @@ obj-$(CONFIG_WDT) += wdt.o
|
|||
obj-$(CONFIG_AXI) += axi.o
|
||||
obj-$(CONFIG_MISC) += misc.o
|
||||
obj-$(CONFIG_DM_SERIAL) += serial.o
|
||||
obj-$(CONFIG_CPU) += cpu.o
|
||||
endif
|
||||
|
|
|
@ -82,7 +82,7 @@ static int do_dm(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
|
|||
U_BOOT_CMD(
|
||||
dm, 3, 1, do_dm,
|
||||
"Driver model low level access",
|
||||
"tree Dump driver model tree ('*' = activated)\n"
|
||||
"tree Dump driver model tree ('*' = activated)\n"
|
||||
"dm uclass Dump list of instances for each uclass\n"
|
||||
"dm devres Dump list of device resources for each device"
|
||||
);
|
||||
|
|
45
test/dm/cpu.c
Normal file
45
test/dm/cpu.c
Normal file
|
@ -0,0 +1,45 @@
|
|||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* (C) Copyright 2018
|
||||
* Mario Six, Guntermann & Drunck GmbH, mario.six@gdsys.cc
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <dm.h>
|
||||
#include <dm/test.h>
|
||||
#include <dm/uclass-internal.h>
|
||||
#include <cpu.h>
|
||||
#include <test/ut.h>
|
||||
|
||||
static int dm_test_cpu(struct unit_test_state *uts)
|
||||
{
|
||||
struct udevice *dev;
|
||||
char text[128];
|
||||
struct cpu_info info;
|
||||
|
||||
ut_assertok(cpu_probe_all());
|
||||
|
||||
/* Check that cpu_probe_all really activated all CPUs */
|
||||
for (uclass_find_first_device(UCLASS_CPU, &dev);
|
||||
dev;
|
||||
uclass_find_next_device(&dev))
|
||||
ut_assert(dev->flags & DM_FLAG_ACTIVATED);
|
||||
|
||||
ut_assertok(uclass_get_device_by_name(UCLASS_CPU, "cpu-test1", &dev));
|
||||
|
||||
ut_assertok(cpu_get_desc(dev, text, sizeof(text)));
|
||||
ut_assertok(strcmp(text, "LEG Inc. SuperMegaUltraTurbo CPU No. 1"));
|
||||
|
||||
ut_assertok(cpu_get_info(dev, &info));
|
||||
ut_asserteq(info.cpu_freq, 42 * 42 * 42 * 42 * 42);
|
||||
ut_asserteq(info.features, 0x42424242);
|
||||
|
||||
ut_asserteq(cpu_get_count(dev), 42);
|
||||
|
||||
ut_assertok(cpu_get_vendor(dev, text, sizeof(text)));
|
||||
ut_assertok(strcmp(text, "Languid Example Garbage Inc."));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
DM_TEST(dm_test_cpu, DM_TESTF_SCAN_FDT);
|
|
@ -15,3 +15,30 @@ static int dm_test_ofnode_compatible(struct unit_test_state *uts)
|
|||
return 0;
|
||||
}
|
||||
DM_TEST(dm_test_ofnode_compatible, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
|
||||
|
||||
static int dm_test_ofnode_by_prop_value(struct unit_test_state *uts)
|
||||
{
|
||||
const char propname[] = "compatible";
|
||||
const char propval[] = "denx,u-boot-fdt-test";
|
||||
const char *str;
|
||||
ofnode node = ofnode_null();
|
||||
|
||||
/* Find first matching node, there should be at least one */
|
||||
node = ofnode_by_prop_value(node, propname, propval, sizeof(propval));
|
||||
ut_assert(ofnode_valid(node));
|
||||
str = ofnode_read_string(node, propname);
|
||||
ut_assert(str && !strcmp(str, propval));
|
||||
|
||||
/* Find the rest of the matching nodes */
|
||||
while (true) {
|
||||
node = ofnode_by_prop_value(node, propname, propval,
|
||||
sizeof(propval));
|
||||
if (!ofnode_valid(node))
|
||||
break;
|
||||
str = ofnode_read_string(node, propname);
|
||||
ut_assert(str && !strcmp(str, propval));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
DM_TEST(dm_test_ofnode_by_prop_value, DM_TESTF_SCAN_FDT);
|
||||
|
|
|
@ -45,6 +45,26 @@ static int dm_test_sysreset_base(struct unit_test_state *uts)
|
|||
}
|
||||
DM_TEST(dm_test_sysreset_base, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
|
||||
|
||||
static int dm_test_sysreset_get_status(struct unit_test_state *uts)
|
||||
{
|
||||
struct udevice *dev;
|
||||
char msg[64];
|
||||
|
||||
/* Device 1 is the warm sysreset device */
|
||||
ut_assertok(uclass_get_device(UCLASS_SYSRESET, 1, &dev));
|
||||
ut_assertok(sysreset_get_status(dev, msg, sizeof(msg)));
|
||||
ut_asserteq_str("Reset Status: WARM", msg);
|
||||
|
||||
/* Device 2 is the cold sysreset device */
|
||||
ut_assertok(uclass_get_device(UCLASS_SYSRESET, 2, &dev));
|
||||
ut_assertok(sysreset_get_status(dev, msg, sizeof(msg)));
|
||||
ut_asserteq_str("Reset Status: COLD", msg);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
DM_TEST(dm_test_sysreset_get_status, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
|
||||
|
||||
/* Test that we can walk through the sysreset devices */
|
||||
static int dm_test_sysreset_walk(struct unit_test_state *uts)
|
||||
{
|
||||
|
|
|
@ -130,9 +130,9 @@ called from the U-Boot build system for this reason.
|
|||
|
||||
Binman considers the output files created by mkimage to be binary blobs
|
||||
which it can place in an image. Binman does not replace the mkimage tool or
|
||||
this purpose. It would be possible in some situtions to create a new entry
|
||||
this purpose. It would be possible in some situations to create a new entry
|
||||
type for the images in mkimage, but this would not add functionality. It
|
||||
seems better to use the mkiamge tool to generate binaries and avoid blurring
|
||||
seems better to use the mkimage tool to generate binaries and avoid blurring
|
||||
the boundaries between building input files (mkimage) and packaging then
|
||||
into a final image (binman).
|
||||
|
||||
|
@ -169,7 +169,7 @@ Example use of binman for x86
|
|||
In most cases x86 images have a lot of binary blobs, 'black-box' code
|
||||
provided by Intel which must be run for the platform to work. Typically
|
||||
these blobs are not relocatable and must be placed at fixed areas in the
|
||||
firmare image.
|
||||
firmware image.
|
||||
|
||||
Currently this is handled by ifdtool, which places microcode, FSP, MRC, VGA
|
||||
BIOS, reference code and Intel ME binaries into a u-boot.rom file.
|
||||
|
@ -406,7 +406,7 @@ either by using a unit number suffix (u-boot@0, u-boot@1) or by using a
|
|||
different name for each and specifying the type with the 'type' attribute.
|
||||
|
||||
|
||||
Sections and hiearchical images
|
||||
Sections and hierachical images
|
||||
-------------------------------
|
||||
|
||||
Sometimes it is convenient to split an image into several pieces, each of which
|
||||
|
|
Loading…
Reference in a new issue