mirror of
https://github.com/brain-hackers/u-boot-brain
synced 2024-06-09 23:36:03 +09:00
Merge branch '2019-07-17-ti-imports'
- Bring in the first three series that we need in order to enhance the TI AM65x series support and then later introduce J721E support.
This commit is contained in:
commit
9a06eb800c
|
@ -69,4 +69,78 @@
|
|||
clock-frequency = <48000000>;
|
||||
current-speed = <115200>;
|
||||
};
|
||||
|
||||
main_pmx0: pinmux@11c000 {
|
||||
compatible = "pinctrl-single";
|
||||
reg = <0x0 0x11c000 0x0 0x2e4>;
|
||||
#pinctrl-cells = <1>;
|
||||
pinctrl-single,register-width = <32>;
|
||||
pinctrl-single,function-mask = <0xffffffff>;
|
||||
};
|
||||
|
||||
main_pmx1: pinmux@11c2e8 {
|
||||
compatible = "pinctrl-single";
|
||||
reg = <0x0 0x11c2e8 0x0 0x24>;
|
||||
#pinctrl-cells = <1>;
|
||||
pinctrl-single,register-width = <32>;
|
||||
pinctrl-single,function-mask = <0xffffffff>;
|
||||
};
|
||||
|
||||
sdhci0: sdhci@4f80000 {
|
||||
compatible = "ti,am654-sdhci-5.1";
|
||||
reg = <0x0 0x4f80000 0x0 0x260>, <0x0 0x4f90000 0x0 0x134>;
|
||||
power-domains = <&k3_pds 47>;
|
||||
clocks = <&k3_clks 47 0>, <&k3_clks 47 1>;
|
||||
clock-names = "clk_ahb", "clk_xin";
|
||||
interrupts = <GIC_SPI 136 IRQ_TYPE_LEVEL_HIGH>;
|
||||
mmc-ddr-1_8v;
|
||||
mmc-hs200-1_8v;
|
||||
ti,otap-del-sel = <0x2>;
|
||||
ti,trm-icp = <0x8>;
|
||||
dma-coherent;
|
||||
};
|
||||
|
||||
main_i2c0: i2c@2000000 {
|
||||
compatible = "ti,am654-i2c", "ti,omap4-i2c";
|
||||
reg = <0x0 0x2000000 0x0 0x100>;
|
||||
interrupts = <GIC_SPI 200 IRQ_TYPE_LEVEL_HIGH>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
clock-names = "fck";
|
||||
clocks = <&k3_clks 110 1>;
|
||||
power-domains = <&k3_pds 110>;
|
||||
};
|
||||
|
||||
main_i2c1: i2c@2010000 {
|
||||
compatible = "ti,am654-i2c", "ti,omap4-i2c";
|
||||
reg = <0x0 0x2010000 0x0 0x100>;
|
||||
interrupts = <GIC_SPI 201 IRQ_TYPE_LEVEL_HIGH>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
clock-names = "fck";
|
||||
clocks = <&k3_clks 111 1>;
|
||||
power-domains = <&k3_pds 111>;
|
||||
};
|
||||
|
||||
main_i2c2: i2c@2020000 {
|
||||
compatible = "ti,am654-i2c", "ti,omap4-i2c";
|
||||
reg = <0x0 0x2020000 0x0 0x100>;
|
||||
interrupts = <GIC_SPI 202 IRQ_TYPE_LEVEL_HIGH>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
clock-names = "fck";
|
||||
clocks = <&k3_clks 112 1>;
|
||||
power-domains = <&k3_pds 112>;
|
||||
};
|
||||
|
||||
main_i2c3: i2c@2030000 {
|
||||
compatible = "ti,am654-i2c", "ti,omap4-i2c";
|
||||
reg = <0x0 0x2030000 0x0 0x100>;
|
||||
interrupts = <GIC_SPI 203 IRQ_TYPE_LEVEL_HIGH>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
clock-names = "fck";
|
||||
clocks = <&k3_clks 113 1>;
|
||||
power-domains = <&k3_pds 113>;
|
||||
};
|
||||
};
|
||||
|
|
|
@ -15,4 +15,15 @@
|
|||
clock-frequency = <96000000>;
|
||||
current-speed = <115200>;
|
||||
};
|
||||
|
||||
mcu_i2c0: i2c@40b00000 {
|
||||
compatible = "ti,am654-i2c", "ti,omap4-i2c";
|
||||
reg = <0x0 0x40b00000 0x0 0x100>;
|
||||
interrupts = <GIC_SPI 564 IRQ_TYPE_LEVEL_HIGH>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
clock-names = "fck";
|
||||
clocks = <&k3_clks 114 1>;
|
||||
power-domains = <&k3_pds 114>;
|
||||
};
|
||||
};
|
||||
|
|
|
@ -34,6 +34,14 @@
|
|||
};
|
||||
};
|
||||
|
||||
wkup_pmx0: pinmux@4301c000 {
|
||||
compatible = "pinctrl-single";
|
||||
reg = <0x4301c000 0x118>;
|
||||
#pinctrl-cells = <1>;
|
||||
pinctrl-single,register-width = <32>;
|
||||
pinctrl-single,function-mask = <0xffffffff>;
|
||||
};
|
||||
|
||||
wkup_uart0: serial@42300000 {
|
||||
compatible = "ti,am654-uart";
|
||||
reg = <0x42300000 0x100>;
|
||||
|
@ -43,4 +51,15 @@
|
|||
clock-frequency = <48000000>;
|
||||
current-speed = <115200>;
|
||||
};
|
||||
|
||||
wkup_i2c0: i2c@42120000 {
|
||||
compatible = "ti,am654-i2c", "ti,omap4-i2c";
|
||||
reg = <0x42120000 0x100>;
|
||||
interrupts = <GIC_SPI 696 IRQ_TYPE_LEVEL_HIGH>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
clock-names = "fck";
|
||||
clocks = <&k3_clks 115 1>;
|
||||
power-domains = <&k3_pds 115>;
|
||||
};
|
||||
};
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
#include <dt-bindings/gpio/gpio.h>
|
||||
#include <dt-bindings/interrupt-controller/irq.h>
|
||||
#include <dt-bindings/interrupt-controller/arm-gic.h>
|
||||
#include <dt-bindings/pinctrl/k3.h>
|
||||
|
||||
/ {
|
||||
model = "Texas Instruments K3 AM654 SoC";
|
||||
|
@ -22,6 +23,12 @@
|
|||
serial2 = &main_uart0;
|
||||
serial3 = &main_uart1;
|
||||
serial4 = &main_uart2;
|
||||
i2c0 = &wkup_i2c0;
|
||||
i2c1 = &mcu_i2c0;
|
||||
i2c2 = &main_i2c0;
|
||||
i2c3 = &main_i2c1;
|
||||
i2c4 = &main_i2c2;
|
||||
i2c5 = &main_i2c3;
|
||||
};
|
||||
|
||||
chosen { };
|
||||
|
|
|
@ -21,51 +21,21 @@
|
|||
&cbass_main{
|
||||
u-boot,dm-spl;
|
||||
|
||||
main_pmx0: pinmux@11c000 {
|
||||
compatible = "pinctrl-single";
|
||||
reg = <0x0 0x11c000 0x0 0x2e4>;
|
||||
#pinctrl-cells = <1>;
|
||||
pinctrl-single,register-width = <32>;
|
||||
pinctrl-single,function-mask = <0xffffffff>;
|
||||
};
|
||||
|
||||
main_pmx1: pinmux@11c2e8 {
|
||||
compatible = "pinctrl-single";
|
||||
reg = <0x0 0x11c2e8 0x0 0x24>;
|
||||
#pinctrl-cells = <1>;
|
||||
pinctrl-single,register-width = <32>;
|
||||
pinctrl-single,function-mask = <0xffffffff>;
|
||||
};
|
||||
|
||||
sdhci0: sdhci@04F80000 {
|
||||
compatible = "arasan,sdhci-5.1";
|
||||
reg = <0x0 0x4F80000 0x0 0x1000>,
|
||||
<0x0 0x4F90000 0x0 0x400>;
|
||||
clocks = <&k3_clks 47 1>;
|
||||
power-domains = <&k3_pds 47>;
|
||||
max-frequency = <25000000>;
|
||||
};
|
||||
|
||||
sdhci1: sdhci@04FA0000 {
|
||||
compatible = "arasan,sdhci-5.1";
|
||||
compatible = "ti,am654-sdhci-5.1";
|
||||
reg = <0x0 0x4FA0000 0x0 0x1000>,
|
||||
<0x0 0x4FB0000 0x0 0x400>;
|
||||
clocks = <&k3_clks 48 1>;
|
||||
power-domains = <&k3_pds 48>;
|
||||
max-frequency = <25000000>;
|
||||
ti,otap-del-sel = <0x2>;
|
||||
ti,trm-icp = <0x8>;
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
&cbass_mcu {
|
||||
u-boot,dm-spl;
|
||||
wkup_pmx0: pinmux@4301c000 {
|
||||
compatible = "pinctrl-single";
|
||||
reg = <0x0 0x4301c000 0x0 0x118>;
|
||||
#pinctrl-cells = <1>;
|
||||
pinctrl-single,register-width = <32>;
|
||||
pinctrl-single,function-mask = <0xffffffff>;
|
||||
};
|
||||
|
||||
navss_mcu: navss-mcu {
|
||||
compatible = "simple-bus";
|
||||
|
@ -252,6 +222,14 @@
|
|||
u-boot,dm-spl;
|
||||
};
|
||||
|
||||
&wkup_pmx0 {
|
||||
u-boot,dm-spl;
|
||||
|
||||
wkup_i2c0_pins_default {
|
||||
u-boot,dm-spl;
|
||||
};
|
||||
};
|
||||
|
||||
&main_pmx0 {
|
||||
u-boot,dm-spl;
|
||||
main_uart0_pins_default: main_uart0_pins_default {
|
||||
|
@ -276,7 +254,8 @@
|
|||
AM65X_IOPAD(0x0190, PIN_INPUT_PULLUP, 0) /* (A24) MMC0_DAT5 */
|
||||
AM65X_IOPAD(0x018c, PIN_INPUT_PULLUP, 0) /* (B26) MMC0_DAT6 */
|
||||
AM65X_IOPAD(0x0188, PIN_INPUT_PULLUP, 0) /* (D25) MMC0_DAT7 */
|
||||
AM65X_IOPAD(0x01b0, PIN_INPUT, 0) /* (C25) MMC0_DS */
|
||||
AM65X_IOPAD(0x01b4, PIN_INPUT_PULLUP, 0) /* (A23) MMC0_SDCD */
|
||||
AM65X_IOPAD(0x01b0, PIN_INPUT, 0) /* (C25) MMC0_DS */
|
||||
>;
|
||||
u-boot,dm-spl;
|
||||
};
|
||||
|
@ -336,11 +315,6 @@
|
|||
|
||||
&sdhci0 {
|
||||
u-boot,dm-spl;
|
||||
status = "okay";
|
||||
non-removable;
|
||||
bus-width = <8>;
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&main_mmc0_pins_default>;
|
||||
};
|
||||
|
||||
&sdhci1 {
|
||||
|
@ -349,6 +323,7 @@
|
|||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&main_mmc1_pins_default>;
|
||||
sdhci-caps-mask = <0x7 0x0>;
|
||||
ti,driver-strength-ohm = <50>;
|
||||
};
|
||||
|
||||
&mcu_cpsw {
|
||||
|
@ -382,3 +357,7 @@
|
|||
reg-names = "gmii-sel";
|
||||
};
|
||||
};
|
||||
|
||||
&wkup_i2c0 {
|
||||
u-boot,dm-spl;
|
||||
};
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
/dts-v1/;
|
||||
|
||||
#include "k3-am654.dtsi"
|
||||
#include <dt-bindings/pinctrl/k3.h>
|
||||
|
||||
/ {
|
||||
compatible = "ti,am654-evm", "ti,am654";
|
||||
|
@ -34,3 +35,52 @@
|
|||
};
|
||||
};
|
||||
};
|
||||
|
||||
&main_pmx0 {
|
||||
main_mmc0_pins_default: main_mmc0_pins_default {
|
||||
pinctrl-single,pins = <
|
||||
AM65X_IOPAD(0x01a8, PIN_INPUT_PULLDOWN, 0) /* (B25) MMC0_CLK */
|
||||
AM65X_IOPAD(0x01aC, PIN_INPUT_PULLUP, 0) /* (B27) MMC0_CMD */
|
||||
AM65X_IOPAD(0x01a4, PIN_INPUT_PULLUP, 0) /* (A26) MMC0_DAT0 */
|
||||
AM65X_IOPAD(0x01a0, PIN_INPUT_PULLUP, 0) /* (E25) MMC0_DAT1 */
|
||||
AM65X_IOPAD(0x019c, PIN_INPUT_PULLUP, 0) /* (C26) MMC0_DAT2 */
|
||||
AM65X_IOPAD(0x0198, PIN_INPUT_PULLUP, 0) /* (A25) MMC0_DAT3 */
|
||||
AM65X_IOPAD(0x0194, PIN_INPUT_PULLUP, 0) /* (E24) MMC0_DAT4 */
|
||||
AM65X_IOPAD(0x0190, PIN_INPUT_PULLUP, 0) /* (A24) MMC0_DAT5 */
|
||||
AM65X_IOPAD(0x018c, PIN_INPUT_PULLUP, 0) /* (B26) MMC0_DAT6 */
|
||||
AM65X_IOPAD(0x0188, PIN_INPUT_PULLUP, 0) /* (D25) MMC0_DAT7 */
|
||||
AM65X_IOPAD(0x01b4, PIN_INPUT_PULLUP, 0) /* (A23) MMC0_SDCD */
|
||||
AM65X_IOPAD(0x01b0, PIN_INPUT, 0) /* (C25) MMC0_DS */
|
||||
>;
|
||||
};
|
||||
};
|
||||
|
||||
&wkup_pmx0 {
|
||||
wkup_i2c0_pins_default: wkup-i2c0-pins-default {
|
||||
pinctrl-single,pins = <
|
||||
AM65X_WKUP_IOPAD(0x00e0, PIN_INPUT, 0) /* (AC7) WKUP_I2C0_SCL */
|
||||
AM65X_WKUP_IOPAD(0x00e4, PIN_INPUT, 0) /* (AD6) WKUP_I2C0_SDA */
|
||||
>;
|
||||
};
|
||||
};
|
||||
|
||||
&sdhci0 {
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&main_mmc0_pins_default>;
|
||||
bus-width = <8>;
|
||||
non-removable;
|
||||
ti,driver-strength-ohm = <50>;
|
||||
};
|
||||
|
||||
&wkup_i2c0 {
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&wkup_i2c0_pins_default>;
|
||||
clock-frequency = <400000>;
|
||||
|
||||
tca9554: gpio@38 {
|
||||
compatible = "nxp,pca9554";
|
||||
reg = <0x38>;
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
};
|
||||
};
|
||||
|
|
|
@ -96,6 +96,12 @@
|
|||
u-boot,dm-spl;
|
||||
};
|
||||
|
||||
clk_200mhz: dummy_clock {
|
||||
compatible = "fixed-clock";
|
||||
#clock-cells = <0>;
|
||||
clock-frequency = <200000000>;
|
||||
u-boot,dm-spl;
|
||||
};
|
||||
};
|
||||
|
||||
&dmsc {
|
||||
|
@ -130,6 +136,32 @@
|
|||
>;
|
||||
u-boot,dm-spl;
|
||||
};
|
||||
|
||||
wkup_i2c0_pins_default: wkup-i2c0-pins-default {
|
||||
pinctrl-single,pins = <
|
||||
AM65X_WKUP_IOPAD(0x00e0, PIN_INPUT, 0) /* (AC7) WKUP_I2C0_SCL */
|
||||
AM65X_WKUP_IOPAD(0x00e4, PIN_INPUT, 0) /* (AD6) WKUP_I2C0_SDA */
|
||||
>;
|
||||
};
|
||||
};
|
||||
|
||||
&main_pmx0 {
|
||||
u-boot,dm-spl;
|
||||
main_mmc0_pins_default: main_mmc0_pins_default {
|
||||
pinctrl-single,pins = <
|
||||
AM65X_IOPAD(0x01a8, PIN_INPUT_PULLDOWN, 0) /* (B25) MMC0_CLK */
|
||||
AM65X_IOPAD(0x01aC, PIN_INPUT_PULLUP, 0) /* (B27) MMC0_CMD */
|
||||
AM65X_IOPAD(0x01a4, PIN_INPUT_PULLUP, 0) /* (A26) MMC0_DAT0 */
|
||||
AM65X_IOPAD(0x01a0, PIN_INPUT_PULLUP, 0) /* (E25) MMC0_DAT1 */
|
||||
AM65X_IOPAD(0x019c, PIN_INPUT_PULLUP, 0) /* (C26) MMC0_DAT2 */
|
||||
AM65X_IOPAD(0x0198, PIN_INPUT_PULLUP, 0) /* (A25) MMC0_DAT3 */
|
||||
AM65X_IOPAD(0x0194, PIN_INPUT_PULLUP, 0) /* (E24) MMC0_DAT4 */
|
||||
AM65X_IOPAD(0x0190, PIN_INPUT_PULLUP, 0) /* (A24) MMC0_DAT5 */
|
||||
AM65X_IOPAD(0x018c, PIN_INPUT_PULLUP, 0) /* (B26) MMC0_DAT6 */
|
||||
AM65X_IOPAD(0x0188, PIN_INPUT_PULLUP, 0) /* (D25) MMC0_DAT7 */
|
||||
AM65X_IOPAD(0x01b0, PIN_INPUT, 0) /* (C25) MMC0_DS */
|
||||
>;
|
||||
};
|
||||
};
|
||||
|
||||
&memorycontroller {
|
||||
|
@ -137,3 +169,23 @@
|
|||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&wkup_vtt_pins_default>;
|
||||
};
|
||||
|
||||
&sdhci0 {
|
||||
clock-names = "clk_xin";
|
||||
clocks = <&clk_200mhz>;
|
||||
/delete-property/ power-domains;
|
||||
ti,driver-strength-ohm = <50>;
|
||||
};
|
||||
|
||||
&sdhci1 {
|
||||
clock-names = "clk_xin";
|
||||
clocks = <&clk_200mhz>;
|
||||
/delete-property/ power-domains;
|
||||
ti,driver-strength-ohm = <50>;
|
||||
};
|
||||
|
||||
&wkup_i2c0 {
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&wkup_i2c0_pins_default>;
|
||||
clock-frequency = <400000>;
|
||||
};
|
||||
|
|
|
@ -3,8 +3,6 @@
|
|||
#ifndef _OMAP_I2C_H
|
||||
#define _OMAP_I2C_H
|
||||
|
||||
#include <asm/arch/cpu.h>
|
||||
|
||||
#ifdef CONFIG_DM_I2C
|
||||
|
||||
/* Information about a GPIO bank */
|
||||
|
|
|
@ -57,6 +57,33 @@
|
|||
* For more information see 'Board Initialisation Flow in README.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Macro for clearing BSS during SPL execution. Usually called during the
|
||||
* relocation process for most boards before entering board_init_r(), but
|
||||
* can also be done early before entering board_init_f() on plaforms that
|
||||
* can afford it due to sufficient memory being available early.
|
||||
*/
|
||||
|
||||
.macro SPL_CLEAR_BSS
|
||||
ldr r0, =__bss_start /* this is auto-relocated! */
|
||||
|
||||
#ifdef CONFIG_USE_ARCH_MEMSET
|
||||
ldr r3, =__bss_end /* this is auto-relocated! */
|
||||
mov r1, #0x00000000 /* prepare zero to clear BSS */
|
||||
|
||||
subs r2, r3, r0 /* r2 = memset len */
|
||||
bl memset
|
||||
#else
|
||||
ldr r1, =__bss_end /* this is auto-relocated! */
|
||||
mov r2, #0x00000000 /* prepare zero to clear BSS */
|
||||
|
||||
clbss_l:cmp r0, r1 /* while not at end of BSS */
|
||||
strlo r2, [r0] /* clear 32-bit BSS word */
|
||||
addlo r0, r0, #4 /* move to next */
|
||||
blo clbss_l
|
||||
#endif
|
||||
.endm
|
||||
|
||||
/*
|
||||
* entry point of crt0 sequence
|
||||
*/
|
||||
|
@ -82,6 +109,10 @@ ENTRY(_main)
|
|||
mov r9, r0
|
||||
bl board_init_f_init_reserve
|
||||
|
||||
#if defined(CONFIG_SPL_EARLY_BSS)
|
||||
SPL_CLEAR_BSS
|
||||
#endif
|
||||
|
||||
mov r0, #0
|
||||
bl board_init_f
|
||||
|
||||
|
@ -119,6 +150,11 @@ here:
|
|||
bl c_runtime_cpu_setup /* we still call old routine here */
|
||||
#endif
|
||||
#if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_FRAMEWORK)
|
||||
|
||||
#if !defined(CONFIG_SPL_EARLY_BSS)
|
||||
SPL_CLEAR_BSS
|
||||
#endif
|
||||
|
||||
# ifdef CONFIG_SPL_BUILD
|
||||
/* Use a DRAM stack for the rest of SPL, if requested */
|
||||
bl spl_relocate_stack_gd
|
||||
|
@ -126,23 +162,6 @@ here:
|
|||
movne sp, r0
|
||||
movne r9, r0
|
||||
# endif
|
||||
ldr r0, =__bss_start /* this is auto-relocated! */
|
||||
|
||||
#ifdef CONFIG_USE_ARCH_MEMSET
|
||||
ldr r3, =__bss_end /* this is auto-relocated! */
|
||||
mov r1, #0x00000000 /* prepare zero to clear BSS */
|
||||
|
||||
subs r2, r3, r0 /* r2 = memset len */
|
||||
bl memset
|
||||
#else
|
||||
ldr r1, =__bss_end /* this is auto-relocated! */
|
||||
mov r2, #0x00000000 /* prepare zero to clear BSS */
|
||||
|
||||
clbss_l:cmp r0, r1 /* while not at end of BSS */
|
||||
strlo r2, [r0] /* clear 32-bit BSS word */
|
||||
addlo r0, r0, #4 /* move to next */
|
||||
blo clbss_l
|
||||
#endif
|
||||
|
||||
#if ! defined(CONFIG_SPL_BUILD)
|
||||
bl coloured_LED_init
|
||||
|
|
|
@ -58,6 +58,45 @@ config SYS_K3_BOOT_CORE_ID
|
|||
int
|
||||
default 16
|
||||
|
||||
config K3_LOAD_SYSFW
|
||||
bool
|
||||
depends on SPL
|
||||
|
||||
config K3_SYSFW_IMAGE_NAME
|
||||
string "File name of SYSFW firmware and configuration blob"
|
||||
depends on K3_LOAD_SYSFW
|
||||
default "sysfw.itb"
|
||||
help
|
||||
Filename of the combined System Firmware and configuration image tree
|
||||
blob to be loaded when booting from a filesystem.
|
||||
|
||||
config K3_SYSFW_IMAGE_MMCSD_RAW_MODE_SECT
|
||||
hex "MMC sector to load SYSFW firmware and configuration blob from"
|
||||
depends on K3_LOAD_SYSFW && SYS_MMCSD_RAW_MODE_U_BOOT_USE_SECTOR
|
||||
default 0x3600
|
||||
help
|
||||
Address on the MMC to load the combined System Firmware and
|
||||
configuration image tree blob from, when the MMC is being used
|
||||
in raw mode. Units: MMC sectors (1 sector = 512 bytes).
|
||||
|
||||
config K3_SYSFW_IMAGE_MMCSD_RAW_MODE_PART
|
||||
hex "MMC partition to load SYSFW firmware and configuration blob from"
|
||||
depends on K3_LOAD_SYSFW && SYS_MMCSD_RAW_MODE_U_BOOT_USE_PARTITION
|
||||
default 2
|
||||
help
|
||||
Partition on the MMC to the combined System Firmware and configuration
|
||||
image tree blob from, when the MMC is being used in raw mode.
|
||||
|
||||
config K3_SYSFW_IMAGE_SIZE_MAX
|
||||
int "Amount of memory dynamically allocated for loading SYSFW blob"
|
||||
depends on K3_LOAD_SYSFW
|
||||
default 269000
|
||||
help
|
||||
Amount of memory (in bytes) reserved through dynamic allocation at
|
||||
runtime for loading the combined System Firmware and configuration image
|
||||
tree blob. Keep it as tight as possible, as this directly affects the
|
||||
overall SPL memory footprint.
|
||||
|
||||
config SYS_K3_SPL_ATF
|
||||
bool "Start Cortex-A from SPL"
|
||||
depends on SPL && CPU_V7R
|
||||
|
|
|
@ -7,4 +7,7 @@ obj-$(CONFIG_SOC_K3_AM6) += am6_init.o
|
|||
obj-$(CONFIG_ARM64) += arm64-mmu.o
|
||||
obj-$(CONFIG_CPU_V7R) += r5_mpu.o lowlevel_init.o
|
||||
obj-$(CONFIG_TI_SECURE_DEVICE) += security.o
|
||||
ifeq ($(CONFIG_SPL_BUILD),y)
|
||||
obj-$(CONFIG_K3_LOAD_SYSFW) += sysfw-loader.o
|
||||
endif
|
||||
obj-y += common.o
|
||||
|
|
|
@ -10,8 +10,12 @@
|
|||
#include <asm/io.h>
|
||||
#include <spl.h>
|
||||
#include <asm/arch/hardware.h>
|
||||
#include <asm/arch/sysfw-loader.h>
|
||||
#include <asm/arch/sys_proto.h>
|
||||
#include "common.h"
|
||||
#include <dm.h>
|
||||
#include <dm/uclass-internal.h>
|
||||
#include <dm/pinctrl.h>
|
||||
|
||||
#ifdef CONFIG_SPL_BUILD
|
||||
static void mmr_unlock(u32 base, u32 partition)
|
||||
|
@ -63,7 +67,7 @@ static void store_boot_index_from_rom(void)
|
|||
|
||||
void board_init_f(ulong dummy)
|
||||
{
|
||||
#if defined(CONFIG_K3_AM654_DDRSS)
|
||||
#if defined(CONFIG_K3_LOAD_SYSFW) || defined(CONFIG_K3_AM654_DDRSS)
|
||||
struct udevice *dev;
|
||||
int ret;
|
||||
#endif
|
||||
|
@ -83,8 +87,33 @@ void board_init_f(ulong dummy)
|
|||
/* Init DM early in-order to invoke system controller */
|
||||
spl_early_init();
|
||||
|
||||
#ifdef CONFIG_K3_LOAD_SYSFW
|
||||
/*
|
||||
* Process pinctrl for the serial0 a.k.a. WKUP_UART0 module and continue
|
||||
* regardless of the result of pinctrl. Do this without probing the
|
||||
* device, but instead by searching the device that would request the
|
||||
* given sequence number if probed. The UART will be used by the system
|
||||
* firmware (SYSFW) image for various purposes and SYSFW depends on us
|
||||
* to initialize its pin settings.
|
||||
*/
|
||||
ret = uclass_find_device_by_seq(UCLASS_SERIAL, 0, true, &dev);
|
||||
if (!ret)
|
||||
pinctrl_select_state(dev, "default");
|
||||
|
||||
/*
|
||||
* Load, start up, and configure system controller firmware. Provide
|
||||
* the U-Boot console init function to the SYSFW post-PM configuration
|
||||
* callback hook, effectively switching on (or over) the console
|
||||
* output.
|
||||
*/
|
||||
k3_sysfw_loader(preloader_console_init);
|
||||
#else
|
||||
/* Prepare console output */
|
||||
preloader_console_init();
|
||||
#endif
|
||||
|
||||
/* Perform EEPROM-based board detection */
|
||||
do_board_detect();
|
||||
|
||||
#ifdef CONFIG_K3_AM654_DDRSS
|
||||
ret = uclass_get_device(UCLASS_RAM, 0, &dev);
|
||||
|
|
|
@ -44,4 +44,7 @@
|
|||
#define CTRLMMR_LOCK_KICK1 0x0100c
|
||||
#define CTRLMMR_LOCK_KICK1_UNLOCK_VAL 0xd172bc5a
|
||||
|
||||
/* MCU SCRATCHPAD usage */
|
||||
#define TI_SRAM_SCRATCH_BOARD_EEPROM_START CONFIG_SYS_K3_MCU_SCRATCHPAD_BASE
|
||||
|
||||
#endif /* __ASM_ARCH_AM6_HARDWARE_H */
|
||||
|
|
|
@ -12,4 +12,6 @@ u32 wait_on_value(u32 read_bit_mask, u32 match_value, void *read_addr,
|
|||
u32 bound);
|
||||
struct ti_sci_handle *get_ti_sci_handle(void);
|
||||
int fdt_fixup_msmc_ram(void *blob, char *parent_path, char *node_name);
|
||||
int do_board_detect(void);
|
||||
|
||||
#endif
|
||||
|
|
12
arch/arm/mach-k3/include/mach/sysfw-loader.h
Normal file
12
arch/arm/mach-k3/include/mach/sysfw-loader.h
Normal file
|
@ -0,0 +1,12 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||
/*
|
||||
* Copyright (C) 2019 Texas Instruments Incorporated - http://www.ti.com/
|
||||
* Andreas Dannenberg <dannenberg@ti.com>
|
||||
*/
|
||||
|
||||
#ifndef _SYSFW_LOADER_H_
|
||||
#define _SYSFW_LOADER_H_
|
||||
|
||||
void k3_sysfw_loader(void (*config_pm_done_callback)(void));
|
||||
|
||||
#endif
|
260
arch/arm/mach-k3/sysfw-loader.c
Normal file
260
arch/arm/mach-k3/sysfw-loader.c
Normal file
|
@ -0,0 +1,260 @@
|
|||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* K3: System Firmware Loader
|
||||
*
|
||||
* Copyright (C) 2019 Texas Instruments Incorporated - http://www.ti.com/
|
||||
* Andreas Dannenberg <dannenberg@ti.com>
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <spl.h>
|
||||
#include <malloc.h>
|
||||
#include <remoteproc.h>
|
||||
#include <linux/soc/ti/ti_sci_protocol.h>
|
||||
#include <asm/arch/sys_proto.h>
|
||||
|
||||
/* Name of the FIT image nodes for SYSFW and its config data */
|
||||
#define SYSFW_FIRMWARE "sysfw.bin"
|
||||
#define SYSFW_CFG_BOARD "board-cfg.bin"
|
||||
#define SYSFW_CFG_PM "pm-cfg.bin"
|
||||
#define SYSFW_CFG_RM "rm-cfg.bin"
|
||||
#define SYSFW_CFG_SEC "sec-cfg.bin"
|
||||
|
||||
static bool sysfw_loaded;
|
||||
static void *sysfw_load_address;
|
||||
|
||||
/*
|
||||
* Populate SPL hook to override the default load address used by the SPL
|
||||
* loader function with a custom address for SYSFW loading.
|
||||
*/
|
||||
struct image_header *spl_get_load_buffer(ssize_t offset, size_t size)
|
||||
{
|
||||
if (sysfw_loaded)
|
||||
return (struct image_header *)(CONFIG_SYS_TEXT_BASE + offset);
|
||||
else if (sysfw_load_address)
|
||||
return sysfw_load_address;
|
||||
else
|
||||
panic("SYSFW load address not defined!");
|
||||
}
|
||||
|
||||
/*
|
||||
* Populate SPL hook to skip the default SPL loader FIT post-processing steps
|
||||
* during SYSFW loading and return to the calling function so we can perform
|
||||
* our own custom processing.
|
||||
*/
|
||||
bool spl_load_simple_fit_skip_processing(void)
|
||||
{
|
||||
return !sysfw_loaded;
|
||||
}
|
||||
|
||||
static int fit_get_data_by_name(const void *fit, int images, const char *name,
|
||||
const void **addr, size_t *size)
|
||||
{
|
||||
int node_offset;
|
||||
|
||||
node_offset = fdt_subnode_offset(fit, images, name);
|
||||
if (node_offset < 0)
|
||||
return -ENOENT;
|
||||
|
||||
return fit_image_get_data(fit, node_offset, addr, size);
|
||||
}
|
||||
|
||||
static void k3_sysfw_load_using_fit(void *fit)
|
||||
{
|
||||
int images;
|
||||
const void *sysfw_addr;
|
||||
size_t sysfw_size;
|
||||
int ret;
|
||||
|
||||
/* Find the node holding the images information */
|
||||
images = fdt_path_offset(fit, FIT_IMAGES_PATH);
|
||||
if (images < 0)
|
||||
panic("Cannot find /images node (%d)\n", images);
|
||||
|
||||
/* Extract System Firmware (SYSFW) image from FIT */
|
||||
ret = fit_get_data_by_name(fit, images, SYSFW_FIRMWARE,
|
||||
&sysfw_addr, &sysfw_size);
|
||||
if (ret < 0)
|
||||
panic("Error accessing %s node in FIT (%d)\n", SYSFW_FIRMWARE,
|
||||
ret);
|
||||
|
||||
/*
|
||||
* Start up system controller firmware
|
||||
*
|
||||
* It is assumed that remoteproc device 0 is the corresponding
|
||||
* system-controller that runs SYSFW. Make sure DT reflects the same.
|
||||
*/
|
||||
ret = rproc_dev_init(0);
|
||||
if (ret)
|
||||
panic("rproc failed to be initialized (%d)\n", ret);
|
||||
|
||||
ret = rproc_load(0, (ulong)sysfw_addr, (ulong)sysfw_size);
|
||||
if (ret)
|
||||
panic("Firmware failed to start on rproc (%d)\n", ret);
|
||||
|
||||
ret = rproc_start(0);
|
||||
if (ret)
|
||||
panic("Firmware init failed on rproc (%d)\n", ret);
|
||||
}
|
||||
|
||||
static void k3_sysfw_configure_using_fit(void *fit,
|
||||
struct ti_sci_handle *ti_sci)
|
||||
{
|
||||
struct ti_sci_board_ops *board_ops = &ti_sci->ops.board_ops;
|
||||
int images;
|
||||
const void *cfg_fragment_addr;
|
||||
size_t cfg_fragment_size;
|
||||
int ret;
|
||||
|
||||
/* Find the node holding the images information */
|
||||
images = fdt_path_offset(fit, FIT_IMAGES_PATH);
|
||||
if (images < 0)
|
||||
panic("Cannot find /images node (%d)\n", images);
|
||||
|
||||
/* Extract board configuration from FIT */
|
||||
ret = fit_get_data_by_name(fit, images, SYSFW_CFG_BOARD,
|
||||
&cfg_fragment_addr, &cfg_fragment_size);
|
||||
if (ret < 0)
|
||||
panic("Error accessing %s node in FIT (%d)\n", SYSFW_CFG_BOARD,
|
||||
ret);
|
||||
|
||||
/* Apply board configuration to SYSFW */
|
||||
ret = board_ops->board_config(ti_sci,
|
||||
(u64)(u32)cfg_fragment_addr,
|
||||
(u32)cfg_fragment_size);
|
||||
if (ret)
|
||||
panic("Failed to set board configuration (%d)\n", ret);
|
||||
|
||||
/* Extract power/clock (PM) specific configuration from FIT */
|
||||
ret = fit_get_data_by_name(fit, images, SYSFW_CFG_PM,
|
||||
&cfg_fragment_addr, &cfg_fragment_size);
|
||||
if (ret < 0)
|
||||
panic("Error accessing %s node in FIT (%d)\n", SYSFW_CFG_PM,
|
||||
ret);
|
||||
|
||||
/* Apply power/clock (PM) specific configuration to SYSFW */
|
||||
ret = board_ops->board_config_pm(ti_sci,
|
||||
(u64)(u32)cfg_fragment_addr,
|
||||
(u32)cfg_fragment_size);
|
||||
if (ret)
|
||||
panic("Failed to set board PM configuration (%d)\n", ret);
|
||||
|
||||
/* Extract resource management (RM) specific configuration from FIT */
|
||||
ret = fit_get_data_by_name(fit, images, SYSFW_CFG_RM,
|
||||
&cfg_fragment_addr, &cfg_fragment_size);
|
||||
if (ret < 0)
|
||||
panic("Error accessing %s node in FIT (%d)\n", SYSFW_CFG_RM,
|
||||
ret);
|
||||
|
||||
/* Apply resource management (RM) configuration to SYSFW */
|
||||
ret = board_ops->board_config_rm(ti_sci,
|
||||
(u64)(u32)cfg_fragment_addr,
|
||||
(u32)cfg_fragment_size);
|
||||
if (ret)
|
||||
panic("Failed to set board RM configuration (%d)\n", ret);
|
||||
|
||||
/* Extract security specific configuration from FIT */
|
||||
ret = fit_get_data_by_name(fit, images, SYSFW_CFG_SEC,
|
||||
&cfg_fragment_addr, &cfg_fragment_size);
|
||||
if (ret < 0)
|
||||
panic("Error accessing %s node in FIT (%d)\n", SYSFW_CFG_SEC,
|
||||
ret);
|
||||
|
||||
/* Apply security configuration to SYSFW */
|
||||
ret = board_ops->board_config_security(ti_sci,
|
||||
(u64)(u32)cfg_fragment_addr,
|
||||
(u32)cfg_fragment_size);
|
||||
if (ret)
|
||||
panic("Failed to set board security configuration (%d)\n",
|
||||
ret);
|
||||
}
|
||||
|
||||
void k3_sysfw_loader(void (*config_pm_done_callback)(void))
|
||||
{
|
||||
struct spl_image_info spl_image = { 0 };
|
||||
struct spl_boot_device bootdev = { 0 };
|
||||
struct ti_sci_handle *ti_sci;
|
||||
int ret;
|
||||
|
||||
/* Reserve a block of aligned memory for loading the SYSFW image */
|
||||
sysfw_load_address = memalign(ARCH_DMA_MINALIGN,
|
||||
CONFIG_K3_SYSFW_IMAGE_SIZE_MAX);
|
||||
if (!sysfw_load_address)
|
||||
panic("Error allocating %u bytes of memory for SYSFW image\n",
|
||||
CONFIG_K3_SYSFW_IMAGE_SIZE_MAX);
|
||||
|
||||
debug("%s: allocated %u bytes at 0x%p\n", __func__,
|
||||
CONFIG_K3_SYSFW_IMAGE_SIZE_MAX, sysfw_load_address);
|
||||
|
||||
/* Set load address for legacy modes that bypass spl_get_load_buffer */
|
||||
spl_image.load_addr = (uintptr_t)sysfw_load_address;
|
||||
|
||||
bootdev.boot_device = spl_boot_device();
|
||||
|
||||
/* Load combined System Controller firmware and config data image */
|
||||
switch (bootdev.boot_device) {
|
||||
#if CONFIG_IS_ENABLED(MMC_SUPPORT)
|
||||
case BOOT_DEVICE_MMC1:
|
||||
case BOOT_DEVICE_MMC2:
|
||||
case BOOT_DEVICE_MMC2_2:
|
||||
ret = spl_mmc_load(&spl_image, &bootdev,
|
||||
#ifdef CONFIG_K3_SYSFW_IMAGE_NAME
|
||||
CONFIG_K3_SYSFW_IMAGE_NAME,
|
||||
#else
|
||||
NULL,
|
||||
#endif
|
||||
#ifdef CONFIG_K3_SYSFW_IMAGE_MMCSD_RAW_MODE_PART
|
||||
CONFIG_K3_SYSFW_IMAGE_MMCSD_RAW_MODE_PART,
|
||||
#else
|
||||
0,
|
||||
#endif
|
||||
#ifdef CONFIG_K3_SYSFW_IMAGE_MMCSD_RAW_MODE_SECT
|
||||
CONFIG_K3_SYSFW_IMAGE_MMCSD_RAW_MODE_SECT);
|
||||
#else
|
||||
0);
|
||||
#endif
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
panic("Loading SYSFW image from device %u not supported!\n",
|
||||
bootdev.boot_device);
|
||||
}
|
||||
|
||||
if (ret)
|
||||
panic("Error %d occurred during loading SYSFW image!\n", ret);
|
||||
|
||||
/*
|
||||
* Now that SYSFW got loaded set helper flag to restore regular SPL
|
||||
* loader behavior so we can later boot into the next stage as expected.
|
||||
*/
|
||||
sysfw_loaded = true;
|
||||
|
||||
/* Ensure the SYSFW image is in FIT format */
|
||||
if (image_get_magic((const image_header_t *)sysfw_load_address) !=
|
||||
FDT_MAGIC)
|
||||
panic("SYSFW image not in FIT format!\n");
|
||||
|
||||
/* Extract and start SYSFW */
|
||||
k3_sysfw_load_using_fit(sysfw_load_address);
|
||||
|
||||
/* Get handle for accessing SYSFW services */
|
||||
ti_sci = get_ti_sci_handle();
|
||||
|
||||
/* Parse and apply the different SYSFW configuration fragments */
|
||||
k3_sysfw_configure_using_fit(sysfw_load_address, ti_sci);
|
||||
|
||||
/*
|
||||
* Now that all clocks and PM aspects are setup, invoke a user-
|
||||
* provided callback function. Usually this callback would be used
|
||||
* to setup or re-configure the U-Boot console UART.
|
||||
*/
|
||||
if (config_pm_done_callback)
|
||||
config_pm_done_callback();
|
||||
|
||||
/* Output System Firmware version info */
|
||||
printf("SYSFW ABI: %d.%d (firmware rev 0x%04x '%.*s')\n",
|
||||
ti_sci->version.abi_major, ti_sci->version.abi_minor,
|
||||
ti_sci->version.firmware_revision,
|
||||
sizeof(ti_sci->version.firmware_description),
|
||||
ti_sci->version.firmware_description);
|
||||
}
|
|
@ -12,14 +12,18 @@ config TARGET_AM654_A53_EVM
|
|||
select ARM64
|
||||
select SOC_K3_AM6
|
||||
select SYS_DISABLE_DCACHE_OPS
|
||||
select BOARD_LATE_INIT
|
||||
imply TI_I2C_BOARD_DETECT
|
||||
|
||||
config TARGET_AM654_R5_EVM
|
||||
bool "TI K3 based AM654 EVM running on R5"
|
||||
select CPU_V7R
|
||||
select SYS_THUMB_BUILD
|
||||
select SOC_K3_AM6
|
||||
select K3_LOAD_SYSFW
|
||||
select K3_AM654_DDRSS
|
||||
imply SYS_K3_SPL_ATF
|
||||
imply TI_I2C_BOARD_DETECT
|
||||
|
||||
endchoice
|
||||
|
||||
|
@ -34,6 +38,8 @@ config SYS_VENDOR
|
|||
config SYS_CONFIG_NAME
|
||||
default "am65x_evm"
|
||||
|
||||
source "board/ti/common/Kconfig"
|
||||
|
||||
endif
|
||||
|
||||
if TARGET_AM654_R5_EVM
|
||||
|
@ -50,4 +56,6 @@ config SYS_CONFIG_NAME
|
|||
config SPL_LDSCRIPT
|
||||
default "arch/arm/mach-omap2/u-boot-spl.lds"
|
||||
|
||||
source "board/ti/common/Kconfig"
|
||||
|
||||
endif
|
||||
|
|
|
@ -209,3 +209,55 @@ Image formats:
|
|||
| | Secure config | |
|
||||
| +-------------------+ |
|
||||
+-----------------------+
|
||||
|
||||
eMMC:
|
||||
-----
|
||||
ROM supports booting from eMMC from boot0 partition offset 0x0
|
||||
|
||||
Flashing images to eMMC:
|
||||
|
||||
The following commands can be used to download tiboot3.bin, tispl.bin,
|
||||
u-boot.img, and sysfw.itb from an SD card and write them to the eMMC boot0
|
||||
partition at respective addresses.
|
||||
|
||||
=> mmc dev 0 1
|
||||
=> fatload mmc 1 ${loadaddr} tiboot3.bin
|
||||
=> mmc write ${loadaddr} 0x0 0x400
|
||||
=> fatload mmc 1 ${loadaddr} tispl.bin
|
||||
=> mmc write ${loadaddr} 0x400 0x1000
|
||||
=> fatload mmc 1 ${loadaddr} u-boot.img
|
||||
=> mmc write ${loadaddr} 0x1400 0x2000
|
||||
=> fatload mmc 1 ${loadaddr} sysfw.itb
|
||||
=> mmc write ${loadaddr} 0x3600 0x800
|
||||
|
||||
To give the ROM access to the boot partition, the following commands must be
|
||||
used for the first time:
|
||||
=> mmc partconf 0 1 1 1
|
||||
=> mmc bootbus 0 1 0 0
|
||||
|
||||
To create a software partition for the rootfs, the following command can be
|
||||
used:
|
||||
=> gpt write mmc 0 ${partitions}
|
||||
|
||||
eMMC layout:
|
||||
|
||||
boot0 partition (8 MB) user partition
|
||||
0x0+----------------------------------+ 0x0+-------------------------+
|
||||
| tiboot3.bin (512 KB) | | |
|
||||
0x400+----------------------------------+ | |
|
||||
| tispl.bin (2 MB) | | |
|
||||
0x1400+----------------------------------+ | rootfs |
|
||||
| u-boot.img (4 MB) | | |
|
||||
0x3400+----------------------------------+ | |
|
||||
| environment (128 KB) | | |
|
||||
0x3500+----------------------------------+ | |
|
||||
| backup environment (128 KB) | | |
|
||||
0x3600+----------------------------------+ | |
|
||||
| sysfw (1 MB) | | |
|
||||
0x3E00+----------------------------------+ +-------------------------+
|
||||
|
||||
Kernel image and DT are expected to be present in the /boot folder of rootfs.
|
||||
To boot kernel from eMMC, use the following commands:
|
||||
=> setenv mmcdev 0
|
||||
=> setenv bootpart 0
|
||||
=> boot
|
||||
|
|
|
@ -8,10 +8,31 @@
|
|||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <dm.h>
|
||||
#include <asm/arch/sys_proto.h>
|
||||
#include <asm/arch/hardware.h>
|
||||
#include <asm/gpio.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/omap_common.h>
|
||||
#include <spl.h>
|
||||
#include <asm/arch/sys_proto.h>
|
||||
|
||||
#include "../common/board_detect.h"
|
||||
|
||||
#define board_is_am65x_base_board() board_ti_is("AM6-COMPROCEVM")
|
||||
|
||||
/* Daughter card presence detection signals */
|
||||
enum {
|
||||
AM65X_EVM_APP_BRD_DET,
|
||||
AM65X_EVM_LCD_BRD_DET,
|
||||
AM65X_EVM_SERDES_BRD_DET,
|
||||
AM65X_EVM_HDMI_GPMC_BRD_DET,
|
||||
AM65X_EVM_BRD_DET_COUNT,
|
||||
};
|
||||
|
||||
/* Max number of MAC addresses that are parsed/processed per daughter card */
|
||||
#define DAUGHTER_CARD_NO_OF_MAC_ADDR 8
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
int board_init(void)
|
||||
|
@ -80,3 +101,223 @@ int ft_board_setup(void *blob, bd_t *bd)
|
|||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
int do_board_detect(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = ti_i2c_eeprom_am6_get_base(CONFIG_EEPROM_BUS_ADDRESS,
|
||||
CONFIG_EEPROM_CHIP_ADDRESS);
|
||||
if (ret)
|
||||
pr_err("Reading on-board EEPROM at 0x%02x failed %d\n",
|
||||
CONFIG_EEPROM_CHIP_ADDRESS, ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void setup_board_eeprom_env(void)
|
||||
{
|
||||
char *name = "am65x";
|
||||
|
||||
if (do_board_detect())
|
||||
goto invalid_eeprom;
|
||||
|
||||
if (board_is_am65x_base_board())
|
||||
name = "am65x";
|
||||
else
|
||||
printf("Unidentified board claims %s in eeprom header\n",
|
||||
board_ti_get_name());
|
||||
|
||||
invalid_eeprom:
|
||||
set_board_info_env_am6(name);
|
||||
}
|
||||
|
||||
static int init_daughtercard_det_gpio(char *gpio_name, struct gpio_desc *desc)
|
||||
{
|
||||
int ret;
|
||||
|
||||
memset(desc, 0, sizeof(*desc));
|
||||
|
||||
ret = dm_gpio_lookup_name(gpio_name, desc);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/* Request GPIO, simply re-using the name as label */
|
||||
ret = dm_gpio_request(desc, gpio_name);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return dm_gpio_set_dir_flags(desc, GPIOD_IS_IN);
|
||||
}
|
||||
|
||||
static int probe_daughtercards(void)
|
||||
{
|
||||
struct ti_am6_eeprom ep;
|
||||
struct gpio_desc board_det_gpios[AM65X_EVM_BRD_DET_COUNT];
|
||||
char mac_addr[DAUGHTER_CARD_NO_OF_MAC_ADDR][TI_EEPROM_HDR_ETH_ALEN];
|
||||
u8 mac_addr_cnt;
|
||||
char name_overlays[1024] = { 0 };
|
||||
int i, j;
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* Daughter card presence detection signal name to GPIO (via I2C I/O
|
||||
* expander @ address 0x38) name and EEPROM I2C address mapping.
|
||||
*/
|
||||
const struct {
|
||||
char *gpio_name;
|
||||
u8 i2c_addr;
|
||||
} slot_map[AM65X_EVM_BRD_DET_COUNT] = {
|
||||
{ "gpio@38_0", 0x52, }, /* AM65X_EVM_APP_BRD_DET */
|
||||
{ "gpio@38_1", 0x55, }, /* AM65X_EVM_LCD_BRD_DET */
|
||||
{ "gpio@38_2", 0x54, }, /* AM65X_EVM_SERDES_BRD_DET */
|
||||
{ "gpio@38_3", 0x53, }, /* AM65X_EVM_HDMI_GPMC_BRD_DET */
|
||||
};
|
||||
|
||||
/* Declaration of daughtercards to probe */
|
||||
const struct {
|
||||
u8 slot_index; /* Slot the card is installed */
|
||||
char *card_name; /* EEPROM-programmed card name */
|
||||
char *dtbo_name; /* Device tree overlay to apply */
|
||||
u8 eth_offset; /* ethXaddr MAC address index offset */
|
||||
} cards[] = {
|
||||
{
|
||||
AM65X_EVM_APP_BRD_DET,
|
||||
"AM6-GPAPPEVM",
|
||||
"k3-am654-gp.dtbo",
|
||||
0,
|
||||
},
|
||||
{
|
||||
AM65X_EVM_APP_BRD_DET,
|
||||
"AM6-IDKAPPEVM",
|
||||
"k3-am654-idk.dtbo",
|
||||
3,
|
||||
},
|
||||
{
|
||||
AM65X_EVM_SERDES_BRD_DET,
|
||||
"SER-PCIE2LEVM",
|
||||
"k3-am654-pcie-usb2.dtbo",
|
||||
0,
|
||||
},
|
||||
{
|
||||
AM65X_EVM_SERDES_BRD_DET,
|
||||
"SER-PCIEUSBEVM",
|
||||
"k3-am654-pcie-usb3.dtbo",
|
||||
0,
|
||||
},
|
||||
{
|
||||
AM65X_EVM_LCD_BRD_DET,
|
||||
"OLDI-LCD1EVM",
|
||||
"k3-am654-evm-oldi-lcd1evm.dtbo",
|
||||
0,
|
||||
},
|
||||
};
|
||||
|
||||
/*
|
||||
* Initialize GPIO used for daughtercard slot presence detection and
|
||||
* keep the resulting handles in local array for easier access.
|
||||
*/
|
||||
for (i = 0; i < AM65X_EVM_BRD_DET_COUNT; i++) {
|
||||
ret = init_daughtercard_det_gpio(slot_map[i].gpio_name,
|
||||
&board_det_gpios[i]);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(cards); i++) {
|
||||
/* Obtain card-specific slot index and associated I2C address */
|
||||
u8 slot_index = cards[i].slot_index;
|
||||
u8 i2c_addr = slot_map[slot_index].i2c_addr;
|
||||
|
||||
/*
|
||||
* The presence detection signal is active-low, hence skip
|
||||
* over this card slot if anything other than 0 is returned.
|
||||
*/
|
||||
ret = dm_gpio_get_value(&board_det_gpios[slot_index]);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
else if (ret)
|
||||
continue;
|
||||
|
||||
/* Get and parse the daughter card EEPROM record */
|
||||
ret = ti_i2c_eeprom_am6_get(CONFIG_EEPROM_BUS_ADDRESS, i2c_addr,
|
||||
&ep,
|
||||
(char **)mac_addr,
|
||||
DAUGHTER_CARD_NO_OF_MAC_ADDR,
|
||||
&mac_addr_cnt);
|
||||
if (ret) {
|
||||
pr_err("Reading daughtercard EEPROM at 0x%02x failed %d\n",
|
||||
i2c_addr, ret);
|
||||
/*
|
||||
* Even this is pretty serious let's just skip over
|
||||
* this particular daughtercard, rather than ending
|
||||
* the probing process altogether.
|
||||
*/
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Only process the parsed data if we found a match */
|
||||
if (strncmp(ep.name, cards[i].card_name, sizeof(ep.name)))
|
||||
continue;
|
||||
|
||||
printf("detected %s\n", cards[i].card_name);
|
||||
|
||||
/*
|
||||
* Populate any MAC addresses from daughtercard into the U-Boot
|
||||
* environment, starting with a card-specific offset so we can
|
||||
* have multiple cards contribute to the MAC pool in a well-
|
||||
* defined manner.
|
||||
*/
|
||||
for (j = 0; j < mac_addr_cnt; j++) {
|
||||
if (!is_valid_ethaddr((u8 *)mac_addr[j]))
|
||||
continue;
|
||||
|
||||
eth_env_set_enetaddr_by_index("eth",
|
||||
cards[i].eth_offset + j,
|
||||
(uchar *)mac_addr[j]);
|
||||
}
|
||||
|
||||
/* Skip if no overlays are to be added */
|
||||
if (!strlen(cards[i].dtbo_name))
|
||||
continue;
|
||||
|
||||
/*
|
||||
* Make sure we are not running out of buffer space by checking
|
||||
* if we can fit the new overlay, a trailing space to be used
|
||||
* as a separator, plus the terminating zero.
|
||||
*/
|
||||
if (strlen(name_overlays) + strlen(cards[i].dtbo_name) + 2 >
|
||||
sizeof(name_overlays))
|
||||
return -ENOMEM;
|
||||
|
||||
/* Append to our list of overlays */
|
||||
strcat(name_overlays, cards[i].dtbo_name);
|
||||
strcat(name_overlays, " ");
|
||||
}
|
||||
|
||||
/* Apply device tree overlay(s) to the U-Boot environment, if any */
|
||||
if (strlen(name_overlays))
|
||||
return env_set("name_overlays", name_overlays);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int board_late_init(void)
|
||||
{
|
||||
struct ti_am6_eeprom *ep = TI_AM6_EEPROM_DATA;
|
||||
|
||||
setup_board_eeprom_env();
|
||||
|
||||
/*
|
||||
* The first MAC address for ethernet a.k.a. ethernet0 comes from
|
||||
* efuse populated via the am654 gigabit eth switch subsystem driver.
|
||||
* All the other ones are populated via EEPROM, hence continue with
|
||||
* an index of 1.
|
||||
*/
|
||||
board_ti_am6_set_ethaddr(1, ep->mac_addr_cnt);
|
||||
|
||||
/* Check for and probe any plugged-in daughtercards */
|
||||
probe_daughtercards();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <asm/arch/hardware.h>
|
||||
#include <asm/omap_common.h>
|
||||
#include <dm/uclass.h>
|
||||
#include <i2c.h>
|
||||
|
@ -284,6 +285,191 @@ int __maybe_unused ti_i2c_eeprom_dra7_get(int bus_addr, int dev_addr)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int ti_i2c_eeprom_am6_parse_record(struct ti_am6_eeprom_record *record,
|
||||
struct ti_am6_eeprom *ep,
|
||||
char **mac_addr,
|
||||
u8 mac_addr_max_cnt,
|
||||
u8 *mac_addr_cnt)
|
||||
{
|
||||
switch (record->header.id) {
|
||||
case TI_AM6_EEPROM_RECORD_BOARD_INFO:
|
||||
if (record->header.len != sizeof(record->data.board_info))
|
||||
return -EINVAL;
|
||||
|
||||
if (!ep)
|
||||
break;
|
||||
|
||||
/* Populate (and clean, if needed) the board name */
|
||||
strlcpy(ep->name, record->data.board_info.name,
|
||||
sizeof(ep->name));
|
||||
ti_eeprom_string_cleanup(ep->name);
|
||||
|
||||
/* Populate selected other fields from the board info record */
|
||||
strlcpy(ep->version, record->data.board_info.version,
|
||||
sizeof(ep->version));
|
||||
strlcpy(ep->software_revision,
|
||||
record->data.board_info.software_revision,
|
||||
sizeof(ep->software_revision));
|
||||
strlcpy(ep->serial, record->data.board_info.serial,
|
||||
sizeof(ep->serial));
|
||||
break;
|
||||
case TI_AM6_EEPROM_RECORD_MAC_INFO:
|
||||
if (record->header.len != sizeof(record->data.mac_info))
|
||||
return -EINVAL;
|
||||
|
||||
if (!mac_addr || !mac_addr_max_cnt)
|
||||
break;
|
||||
|
||||
*mac_addr_cnt = ((record->data.mac_info.mac_control &
|
||||
TI_AM6_EEPROM_MAC_ADDR_COUNT_MASK) >>
|
||||
TI_AM6_EEPROM_MAC_ADDR_COUNT_SHIFT) + 1;
|
||||
|
||||
/*
|
||||
* The EEPROM can (but may not) hold a very large amount
|
||||
* of MAC addresses, by far exceeding what we want/can store
|
||||
* in the common memory array, so only grab what we can fit.
|
||||
* Note that a value of 0 means 1 MAC address, and so on.
|
||||
*/
|
||||
*mac_addr_cnt = min(*mac_addr_cnt, mac_addr_max_cnt);
|
||||
|
||||
memcpy(mac_addr, record->data.mac_info.mac_addr,
|
||||
*mac_addr_cnt * TI_EEPROM_HDR_ETH_ALEN);
|
||||
break;
|
||||
case 0x00:
|
||||
/* Illegal value... Fall through... */
|
||||
case 0xFF:
|
||||
/* Illegal value... Something went horribly wrong... */
|
||||
return -EINVAL;
|
||||
default:
|
||||
pr_warn("%s: Ignoring record id %u\n", __func__,
|
||||
record->header.id);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int __maybe_unused ti_i2c_eeprom_am6_get(int bus_addr, int dev_addr,
|
||||
struct ti_am6_eeprom *ep,
|
||||
char **mac_addr,
|
||||
u8 mac_addr_max_cnt,
|
||||
u8 *mac_addr_cnt)
|
||||
{
|
||||
struct udevice *dev;
|
||||
struct udevice *bus;
|
||||
unsigned int eeprom_addr;
|
||||
struct ti_am6_eeprom_record_board_id board_id;
|
||||
struct ti_am6_eeprom_record record;
|
||||
int rc;
|
||||
|
||||
/* Initialize with a known bad marker for i2c fails.. */
|
||||
memset(ep, 0, sizeof(*ep));
|
||||
ep->header = TI_DEAD_EEPROM_MAGIC;
|
||||
|
||||
/* Read the board ID record which is always the first EEPROM record */
|
||||
rc = ti_i2c_eeprom_get(bus_addr, dev_addr, TI_EEPROM_HEADER_MAGIC,
|
||||
sizeof(board_id), (uint8_t *)&board_id);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
if (board_id.header.id != TI_AM6_EEPROM_RECORD_BOARD_ID) {
|
||||
pr_err("%s: Invalid board ID record!\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Establish DM handle to board config EEPROM */
|
||||
rc = uclass_get_device_by_seq(UCLASS_I2C, bus_addr, &bus);
|
||||
if (rc)
|
||||
return rc;
|
||||
rc = i2c_get_chip(bus, dev_addr, 1, &dev);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
ep->header = TI_EEPROM_HEADER_MAGIC;
|
||||
|
||||
/* Ready to parse TLV structure. Initialize variables... */
|
||||
*mac_addr_cnt = 0;
|
||||
|
||||
/*
|
||||
* After the all-encompassing board ID record all other records follow
|
||||
* a TLV-type scheme. Point to the first such record and then start
|
||||
* parsing those one by one.
|
||||
*/
|
||||
eeprom_addr = sizeof(board_id);
|
||||
|
||||
while (true) {
|
||||
rc = dm_i2c_read(dev, eeprom_addr, (uint8_t *)&record.header,
|
||||
sizeof(record.header));
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
/*
|
||||
* Check for end of list marker. If we reached it don't go
|
||||
* any further and stop parsing right here.
|
||||
*/
|
||||
if (record.header.id == TI_AM6_EEPROM_RECORD_END_LIST)
|
||||
break;
|
||||
|
||||
eeprom_addr += sizeof(record.header);
|
||||
|
||||
debug("%s: dev_addr=0x%02x header.id=%u header.len=%u\n",
|
||||
__func__, dev_addr, record.header.id,
|
||||
record.header.len);
|
||||
|
||||
/* Read record into memory if it fits */
|
||||
if (record.header.len <= sizeof(record.data)) {
|
||||
rc = dm_i2c_read(dev, eeprom_addr,
|
||||
(uint8_t *)&record.data,
|
||||
record.header.len);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
/* Process record */
|
||||
rc = ti_i2c_eeprom_am6_parse_record(&record, ep,
|
||||
mac_addr,
|
||||
mac_addr_max_cnt,
|
||||
mac_addr_cnt);
|
||||
if (rc) {
|
||||
pr_err("%s: EEPROM parsing error!\n", __func__);
|
||||
return rc;
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* We may get here in case of larger records which
|
||||
* are not yet understood.
|
||||
*/
|
||||
pr_err("%s: Ignoring record id %u\n", __func__,
|
||||
record.header.id);
|
||||
}
|
||||
|
||||
eeprom_addr += record.header.len;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int __maybe_unused ti_i2c_eeprom_am6_get_base(int bus_addr, int dev_addr)
|
||||
{
|
||||
struct ti_am6_eeprom *ep = TI_AM6_EEPROM_DATA;
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* Always execute EEPROM read by not allowing to bypass it during the
|
||||
* first invocation of SPL which happens on the R5 core.
|
||||
*/
|
||||
#if !(defined(CONFIG_SPL_BUILD) && defined(CONFIG_CPU_V7R))
|
||||
if (ep->header == TI_EEPROM_HEADER_MAGIC) {
|
||||
debug("%s: EEPROM has already been read\n", __func__);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
ret = ti_i2c_eeprom_am6_get(bus_addr, dev_addr, ep,
|
||||
(char **)ep->mac_addr,
|
||||
AM6_EEPROM_HDR_NO_OF_MAC_ADDR,
|
||||
&ep->mac_addr_cnt);
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool __maybe_unused board_ti_is(char *name_tag)
|
||||
{
|
||||
struct ti_common_eeprom *ep = TI_EEPROM_DATA;
|
||||
|
@ -348,6 +534,25 @@ fail:
|
|||
memset(mac_addr, 0, TI_EEPROM_HDR_ETH_ALEN);
|
||||
}
|
||||
|
||||
void __maybe_unused
|
||||
board_ti_am6_get_eth_mac_addr(int index,
|
||||
u8 mac_addr[TI_EEPROM_HDR_ETH_ALEN])
|
||||
{
|
||||
struct ti_am6_eeprom *ep = TI_AM6_EEPROM_DATA;
|
||||
|
||||
if (ep->header == TI_DEAD_EEPROM_MAGIC)
|
||||
goto fail;
|
||||
|
||||
if (index < 0 || index >= ep->mac_addr_cnt)
|
||||
goto fail;
|
||||
|
||||
memcpy(mac_addr, ep->mac_addr[index], TI_EEPROM_HDR_ETH_ALEN);
|
||||
return;
|
||||
|
||||
fail:
|
||||
memset(mac_addr, 0, TI_EEPROM_HDR_ETH_ALEN);
|
||||
}
|
||||
|
||||
u64 __maybe_unused board_ti_get_emif1_size(void)
|
||||
{
|
||||
struct ti_common_eeprom *ep = TI_EEPROM_DATA;
|
||||
|
@ -391,6 +596,34 @@ void __maybe_unused set_board_info_env(char *name)
|
|||
env_set("board_serial", unknown);
|
||||
}
|
||||
|
||||
void __maybe_unused set_board_info_env_am6(char *name)
|
||||
{
|
||||
char *unknown = "unknown";
|
||||
struct ti_am6_eeprom *ep = TI_AM6_EEPROM_DATA;
|
||||
|
||||
if (name)
|
||||
env_set("board_name", name);
|
||||
else if (ep->name)
|
||||
env_set("board_name", ep->name);
|
||||
else
|
||||
env_set("board_name", unknown);
|
||||
|
||||
if (ep->version)
|
||||
env_set("board_rev", ep->version);
|
||||
else
|
||||
env_set("board_rev", unknown);
|
||||
|
||||
if (ep->software_revision)
|
||||
env_set("board_software_revision", ep->software_revision);
|
||||
else
|
||||
env_set("board_software_revision", unknown);
|
||||
|
||||
if (ep->serial)
|
||||
env_set("board_serial", ep->serial);
|
||||
else
|
||||
env_set("board_serial", unknown);
|
||||
}
|
||||
|
||||
static u64 mac_to_u64(u8 mac[6])
|
||||
{
|
||||
int i;
|
||||
|
@ -453,6 +686,19 @@ void board_ti_set_ethaddr(int index)
|
|||
}
|
||||
}
|
||||
|
||||
void board_ti_am6_set_ethaddr(int index, int count)
|
||||
{
|
||||
u8 mac_addr[6];
|
||||
int i;
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
board_ti_am6_get_eth_mac_addr(i, mac_addr);
|
||||
if (is_valid_ethaddr(mac_addr))
|
||||
eth_env_set_enetaddr_by_index("eth", i + index,
|
||||
mac_addr);
|
||||
}
|
||||
}
|
||||
|
||||
bool __maybe_unused board_ti_was_eeprom_read(void)
|
||||
{
|
||||
struct ti_common_eeprom *ep = TI_EEPROM_DATA;
|
||||
|
|
|
@ -43,6 +43,133 @@ struct ti_am_eeprom {
|
|||
char mac_addr[TI_EEPROM_HDR_NO_OF_MAC_ADDR][TI_EEPROM_HDR_ETH_ALEN];
|
||||
} __attribute__ ((__packed__));
|
||||
|
||||
/* AM6x TI EVM EEPROM Definitions */
|
||||
#define TI_AM6_EEPROM_RECORD_BOARD_ID 0x01
|
||||
#define TI_AM6_EEPROM_RECORD_BOARD_INFO 0x10
|
||||
#define TI_AM6_EEPROM_RECORD_DDR_INFO 0x11
|
||||
#define TI_AM6_EEPROM_RECORD_DDR_SPD 0x12
|
||||
#define TI_AM6_EEPROM_RECORD_MAC_INFO 0x13
|
||||
#define TI_AM6_EEPROM_RECORD_END_LIST 0xFE
|
||||
|
||||
/*
|
||||
* Common header for AM6x TI EVM EEPROM records. Used to encapsulate the config
|
||||
* EEPROM in its entirety as well as for individual records contained within.
|
||||
*/
|
||||
struct ti_am6_eeprom_record_header {
|
||||
u8 id;
|
||||
u16 len;
|
||||
} __attribute__ ((__packed__));
|
||||
|
||||
/* AM6x TI EVM EEPROM board ID structure */
|
||||
struct ti_am6_eeprom_record_board_id {
|
||||
u32 magic_number;
|
||||
struct ti_am6_eeprom_record_header header;
|
||||
} __attribute__ ((__packed__));
|
||||
|
||||
/* AM6x TI EVM EEPROM board info structure */
|
||||
#define AM6_EEPROM_HDR_NAME_LEN 16
|
||||
#define AM6_EEPROM_HDR_VERSION_LEN 2
|
||||
#define AM6_EEPROM_HDR_PROC_NR_LEN 4
|
||||
#define AM6_EEPROM_HDR_VARIANT_LEN 2
|
||||
#define AM6_EEPROM_HDR_PCB_REV_LEN 2
|
||||
#define AM6_EEPROM_HDR_SCH_BOM_REV_LEN 2
|
||||
#define AM6_EEPROM_HDR_SW_REV_LEN 2
|
||||
#define AM6_EEPROM_HDR_VID_LEN 2
|
||||
#define AM6_EEPROM_HDR_BLD_WK_LEN 2
|
||||
#define AM6_EEPROM_HDR_BLD_YR_LEN 2
|
||||
#define AM6_EEPROM_HDR_4P_NR_LEN 6
|
||||
#define AM6_EEPROM_HDR_SERIAL_LEN 4
|
||||
|
||||
struct ti_am6_eeprom_record_board_info {
|
||||
char name[AM6_EEPROM_HDR_NAME_LEN];
|
||||
char version[AM6_EEPROM_HDR_VERSION_LEN];
|
||||
char proc_number[AM6_EEPROM_HDR_PROC_NR_LEN];
|
||||
char variant[AM6_EEPROM_HDR_VARIANT_LEN];
|
||||
char pcb_revision[AM6_EEPROM_HDR_PCB_REV_LEN];
|
||||
char schematic_bom_revision[AM6_EEPROM_HDR_SCH_BOM_REV_LEN];
|
||||
char software_revision[AM6_EEPROM_HDR_SW_REV_LEN];
|
||||
char vendor_id[AM6_EEPROM_HDR_VID_LEN];
|
||||
char build_week[AM6_EEPROM_HDR_BLD_WK_LEN];
|
||||
char build_year[AM6_EEPROM_HDR_BLD_YR_LEN];
|
||||
char board_4p_number[AM6_EEPROM_HDR_4P_NR_LEN];
|
||||
char serial[AM6_EEPROM_HDR_SERIAL_LEN];
|
||||
} __attribute__ ((__packed__));
|
||||
|
||||
/* Memory location to keep a copy of the AM6 board info record */
|
||||
#define TI_AM6_EEPROM_BD_INFO_DATA ((struct ti_am6_eeprom_record_board_info *) \
|
||||
TI_SRAM_SCRATCH_BOARD_EEPROM_START)
|
||||
|
||||
/* AM6x TI EVM EEPROM DDR info structure */
|
||||
#define TI_AM6_EEPROM_DDR_CTRL_INSTANCE_MASK GENMASK(1, 0)
|
||||
#define TI_AM6_EEPROM_DDR_CTRL_INSTANCE_SHIFT 0
|
||||
#define TI_AM6_EEPROM_DDR_CTRL_SPD_DATA_LOC_MASK GENMASK(3, 2)
|
||||
#define TI_AM6_EEPROM_DDR_CTRL_SPD_DATA_LOC_NA (0 << 2)
|
||||
#define TI_AM6_EEPROM_DDR_CTRL_SPD_DATA_LOC_BOARDID (2 << 2)
|
||||
#define TI_AM6_EEPROM_DDR_CTRL_SPD_DATA_LOC_I2C51 (3 << 2)
|
||||
#define TI_AM6_EEPROM_DDR_CTRL_MEM_TYPE_MASK GENMASK(5, 4)
|
||||
#define TI_AM6_EEPROM_DDR_CTRL_MEM_TYPE_DDR3 (0 << 4)
|
||||
#define TI_AM6_EEPROM_DDR_CTRL_MEM_TYPE_DDR4 (1 << 4)
|
||||
#define TI_AM6_EEPROM_DDR_CTRL_MEM_TYPE_LPDDR4 (2 << 4)
|
||||
#define TI_AM6_EEPROM_DDR_CTRL_IF_DATA_WIDTH_MASK GENMASK(7, 6)
|
||||
#define TI_AM6_EEPROM_DDR_CTRL_IF_DATA_WIDTH_16 (0 << 6)
|
||||
#define TI_AM6_EEPROM_DDR_CTRL_IF_DATA_WIDTH_32 (1 << 6)
|
||||
#define TI_AM6_EEPROM_DDR_CTRL_IF_DATA_WIDTH_64 (2 << 6)
|
||||
#define TI_AM6_EEPROM_DDR_CTRL_DEV_DATA_WIDTH_MASK GENMASK(9, 8)
|
||||
#define TI_AM6_EEPROM_DDR_CTRL_DEV_DATA_WIDTH_8 (0 << 8)
|
||||
#define TI_AM6_EEPROM_DDR_CTRL_DEV_DATA_WIDTH_16 (1 << 8)
|
||||
#define TI_AM6_EEPROM_DDR_CTRL_DEV_DATA_WIDTH_32 (2 << 8)
|
||||
#define TI_AM6_EEPROM_DDR_CTRL_RANKS_2 BIT(10)
|
||||
#define TI_AM6_EEPROM_DDR_CTRL_DENS_MASK GENMASK(13, 11)
|
||||
#define TI_AM6_EEPROM_DDR_CTRL_DENS_1GB (0 << 11)
|
||||
#define TI_AM6_EEPROM_DDR_CTRL_DENS_2GB (1 << 11)
|
||||
#define TI_AM6_EEPROM_DDR_CTRL_DENS_4GB (2 << 11)
|
||||
#define TI_AM6_EEPROM_DDR_CTRL_DENS_8GB (3 << 11)
|
||||
#define TI_AM6_EEPROM_DDR_CTRL_DENS_12GB (4 << 11)
|
||||
#define TI_AM6_EEPROM_DDR_CTRL_DENS_16GB (5 << 11)
|
||||
#define TI_AM6_EEPROM_DDR_CTRL_DENS_24GB (6 << 11)
|
||||
#define TI_AM6_EEPROM_DDR_CTRL_DENS_32GB (7 << 11)
|
||||
#define TI_AM6_EEPROM_DDR_CTRL_ECC BIT(14)
|
||||
|
||||
struct ti_am6_eeprom_record_ddr_info {
|
||||
u16 ddr_control;
|
||||
} __attribute__ ((__packed__));
|
||||
|
||||
/* AM6x TI EVM EEPROM DDR SPD structure */
|
||||
#define TI_AM6_EEPROM_DDR_SPD_INSTANCE_MASK GENMASK(1, 0)
|
||||
#define TI_AM6_EEPROM_DDR_SPD_INSTANCE_SHIFT 0
|
||||
#define TI_AM6_EEPROM_DDR_SPD_MEM_TYPE_MASK GENMASK(4, 3)
|
||||
#define TI_AM6_EEPROM_DDR_SPD_MEM_TYPE_DDR3 (0 << 3)
|
||||
#define TI_AM6_EEPROM_DDR_SPD_MEM_TYPE_DDR4 (1 << 3)
|
||||
#define TI_AM6_EEPROM_DDR_SPD_MEM_TYPE_LPDDR4 (2 << 3)
|
||||
#define TI_AM6_EEPROM_DDR_SPD_DATA_LEN 512
|
||||
|
||||
struct ti_am6_eeprom_record_ddr_spd {
|
||||
u16 spd_control;
|
||||
u8 data[TI_AM6_EEPROM_DDR_SPD_DATA_LEN];
|
||||
} __attribute__ ((__packed__));
|
||||
|
||||
/* AM6x TI EVM EEPROM MAC info structure */
|
||||
#define TI_AM6_EEPROM_MAC_INFO_INSTANCE_MASK GENMASK(2, 0)
|
||||
#define TI_AM6_EEPROM_MAC_INFO_INSTANCE_SHIFT 0
|
||||
#define TI_AM6_EEPROM_MAC_ADDR_COUNT_MASK GENMASK(7, 3)
|
||||
#define TI_AM6_EEPROM_MAC_ADDR_COUNT_SHIFT 3
|
||||
#define TI_AM6_EEPROM_MAC_ADDR_MAX_COUNT 32
|
||||
|
||||
struct ti_am6_eeprom_record_mac_info {
|
||||
u16 mac_control;
|
||||
u8 mac_addr[TI_AM6_EEPROM_MAC_ADDR_MAX_COUNT][TI_EEPROM_HDR_ETH_ALEN];
|
||||
} __attribute__ ((__packed__));
|
||||
|
||||
struct ti_am6_eeprom_record {
|
||||
struct ti_am6_eeprom_record_header header;
|
||||
union {
|
||||
struct ti_am6_eeprom_record_board_info board_info;
|
||||
struct ti_am6_eeprom_record_ddr_info ddr_info;
|
||||
struct ti_am6_eeprom_record_ddr_spd ddr_spd;
|
||||
struct ti_am6_eeprom_record_mac_info mac_info;
|
||||
} data;
|
||||
} __attribute__ ((__packed__));
|
||||
|
||||
/* DRA7 EEPROM MAGIC Header identifier */
|
||||
#define DRA7_EEPROM_HEADER_MAGIC 0xAA5533EE
|
||||
#define DRA7_EEPROM_HDR_NAME_LEN 16
|
||||
|
@ -99,6 +226,37 @@ struct ti_common_eeprom {
|
|||
#define TI_EEPROM_DATA ((struct ti_common_eeprom *)\
|
||||
TI_SRAM_SCRATCH_BOARD_EEPROM_START)
|
||||
|
||||
/*
|
||||
* Maximum number of Ethernet MAC addresses extracted from the AM6x on-board
|
||||
* EEPROM during the initial probe and carried forward in SRAM.
|
||||
*/
|
||||
#define AM6_EEPROM_HDR_NO_OF_MAC_ADDR 8
|
||||
|
||||
/**
|
||||
* struct ti_am6_eeprom - Null terminated, usable EEPROM contents, as extracted
|
||||
* from the AM6 on-board EEPROM. Note that we only carry a subset of data
|
||||
* at this time to be considerate about memory consumption.
|
||||
* @header: Magic number for data validity indication
|
||||
* @name: NULL terminated name
|
||||
* @version: NULL terminated version
|
||||
* @software_revision: NULL terminated software revision
|
||||
* @serial: Board serial number
|
||||
* @mac_addr_cnt: Number of MAC addresses stored in this object
|
||||
* @mac_addr: MAC addresses
|
||||
*/
|
||||
struct ti_am6_eeprom {
|
||||
u32 header;
|
||||
char name[AM6_EEPROM_HDR_NAME_LEN + 1];
|
||||
char version[AM6_EEPROM_HDR_VERSION_LEN + 1];
|
||||
char software_revision[AM6_EEPROM_HDR_SW_REV_LEN + 1];
|
||||
char serial[AM6_EEPROM_HDR_SERIAL_LEN + 1];
|
||||
u8 mac_addr_cnt;
|
||||
char mac_addr[AM6_EEPROM_HDR_NO_OF_MAC_ADDR][TI_EEPROM_HDR_ETH_ALEN];
|
||||
};
|
||||
|
||||
#define TI_AM6_EEPROM_DATA ((struct ti_am6_eeprom *) \
|
||||
TI_SRAM_SCRATCH_BOARD_EEPROM_START)
|
||||
|
||||
/**
|
||||
* ti_i2c_eeprom_am_get() - Consolidated eeprom data collection for AM* TI EVMs
|
||||
* @bus_addr: I2C bus address
|
||||
|
@ -116,6 +274,33 @@ int ti_i2c_eeprom_am_get(int bus_addr, int dev_addr);
|
|||
*/
|
||||
int ti_i2c_eeprom_dra7_get(int bus_addr, int dev_addr);
|
||||
|
||||
/**
|
||||
* ti_i2c_eeprom_am6_get() - Consolidated eeprom data for AM6x TI EVMs and
|
||||
* associated daughter cards, parsed into user-
|
||||
* provided data structures
|
||||
* @bus_addr: I2C bus address
|
||||
* @dev_addr: I2C slave address
|
||||
* @ep: Pointer to structure receiving AM6-specific header data
|
||||
* @mac_addr: Pointer to memory receiving parsed MAC addresses. May be
|
||||
* NULL to skip MAC parsing.
|
||||
* @mac_addr_max_cnt: Maximum number of MAC addresses that can be stored into
|
||||
* mac_addr. May be NULL to skip MAC parsing.
|
||||
* @mac_addr_cnt: Pointer to a location returning how many MAC addressed got
|
||||
* actually parsed.
|
||||
*/
|
||||
int __maybe_unused ti_i2c_eeprom_am6_get(int bus_addr, int dev_addr,
|
||||
struct ti_am6_eeprom *ep,
|
||||
char **mac_addr,
|
||||
u8 mac_addr_max_cnt,
|
||||
u8 *mac_addr_cnt);
|
||||
|
||||
/**
|
||||
* ti_i2c_eeprom_am6_get_base() - Consolidated eeprom data for AM6x TI EVMs
|
||||
* @bus_addr: I2C bus address
|
||||
* @dev_addr: I2C slave address
|
||||
*/
|
||||
int __maybe_unused ti_i2c_eeprom_am6_get_base(int bus_addr, int dev_addr);
|
||||
|
||||
/**
|
||||
* board_ti_is() - Board detection logic for TI EVMs
|
||||
* @name_tag: Tag used in eeprom for the board
|
||||
|
@ -192,6 +377,15 @@ u64 board_ti_get_emif2_size(void);
|
|||
*/
|
||||
void set_board_info_env(char *name);
|
||||
|
||||
/**
|
||||
* set_board_info_env_am6() - Setup commonly used board information environment
|
||||
* vars for AM6-type boards
|
||||
* @name: Name of the board
|
||||
*
|
||||
* If name is NULL, default_name is used.
|
||||
*/
|
||||
void set_board_info_env_am6(char *name);
|
||||
|
||||
/**
|
||||
* board_ti_set_ethaddr- Sets the ethaddr environment from EEPROM
|
||||
* @index: The first eth<index>addr environment variable to set
|
||||
|
@ -204,6 +398,18 @@ void set_board_info_env(char *name);
|
|||
*/
|
||||
void board_ti_set_ethaddr(int index);
|
||||
|
||||
/**
|
||||
* board_ti_am6_set_ethaddr- Sets the ethaddr environment from EEPROM
|
||||
* @index: The first eth<index>addr environment variable to set
|
||||
* @count: The number of MAC addresses to process
|
||||
*
|
||||
* EEPROM should be already read before calling this function. The EEPROM
|
||||
* contains n dedicated MAC addresses. This function sets the ethaddr
|
||||
* environment variable for all the available MAC addresses starting
|
||||
* from eth<index>addr.
|
||||
*/
|
||||
void board_ti_am6_set_ethaddr(int index, int count);
|
||||
|
||||
/**
|
||||
* board_ti_was_eeprom_read() - Check to see if the eeprom contents have been read
|
||||
*
|
||||
|
|
|
@ -248,6 +248,16 @@ config TPL_BANNER_PRINT
|
|||
info. Disabling this option could be useful to reduce SPL boot time
|
||||
(e.g. approx. 6 ms faster, when output on i.MX6 with 115200 baud).
|
||||
|
||||
config SPL_EARLY_BSS
|
||||
depends on ARM && !ARM64
|
||||
bool "Allows initializing BSS early before entering board_init_f"
|
||||
help
|
||||
On some platform we have sufficient memory available early on to
|
||||
allow setting up and using a basic BSS prior to entering
|
||||
board_init_f. Activating this option will also de-activate the
|
||||
clearing of BSS during the SPL relocation process, thus allowing
|
||||
to carry state from board_init_f to board_init_r by way of BSS.
|
||||
|
||||
config SPL_DISPLAY_PRINT
|
||||
bool "Display a board-specific message in SPL"
|
||||
help
|
||||
|
|
|
@ -340,6 +340,16 @@ static int spl_fit_image_get_os(const void *fit, int noffset, uint8_t *os)
|
|||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* Weak default function to allow customizing SPL fit loading for load-only
|
||||
* use cases by allowing to skip the parsing/processing of the FIT contents
|
||||
* (so that this can be done separately in a more customized fashion)
|
||||
*/
|
||||
__weak bool spl_load_simple_fit_skip_processing(void)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
int spl_load_simple_fit(struct spl_image_info *spl_image,
|
||||
struct spl_load_info *info, ulong sector, void *fit)
|
||||
{
|
||||
|
@ -389,6 +399,10 @@ int spl_load_simple_fit(struct spl_image_info *spl_image,
|
|||
if (count == 0)
|
||||
return -EIO;
|
||||
|
||||
/* skip further processing if requested to enable load-only use cases */
|
||||
if (spl_load_simple_fit_skip_processing())
|
||||
return 0;
|
||||
|
||||
/* find the node holding the images information */
|
||||
images = fdt_path_offset(fit, FIT_IMAGES_PATH);
|
||||
if (images < 0) {
|
||||
|
|
|
@ -151,7 +151,8 @@ static int spl_mmc_find_device(struct mmc **mmcp, u32 boot_device)
|
|||
|
||||
#ifdef CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_USE_PARTITION
|
||||
static int mmc_load_image_raw_partition(struct spl_image_info *spl_image,
|
||||
struct mmc *mmc, int partition)
|
||||
struct mmc *mmc, int partition,
|
||||
unsigned long sector)
|
||||
{
|
||||
disk_partition_t info;
|
||||
int err;
|
||||
|
@ -180,8 +181,7 @@ static int mmc_load_image_raw_partition(struct spl_image_info *spl_image,
|
|||
}
|
||||
|
||||
#ifdef CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_USE_SECTOR
|
||||
return mmc_load_image_raw_sector(spl_image, mmc,
|
||||
info.start + CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR);
|
||||
return mmc_load_image_raw_sector(spl_image, mmc, info.start + sector);
|
||||
#else
|
||||
return mmc_load_image_raw_sector(spl_image, mmc, info.start);
|
||||
#endif
|
||||
|
@ -234,7 +234,8 @@ static int mmc_load_image_raw_os(struct spl_image_info *spl_image,
|
|||
#endif
|
||||
|
||||
#ifdef CONFIG_SYS_MMCSD_FS_BOOT_PARTITION
|
||||
static int spl_mmc_do_fs_boot(struct spl_image_info *spl_image, struct mmc *mmc)
|
||||
static int spl_mmc_do_fs_boot(struct spl_image_info *spl_image, struct mmc *mmc,
|
||||
const char *filename)
|
||||
{
|
||||
int err = -ENOSYS;
|
||||
|
||||
|
@ -248,7 +249,7 @@ static int spl_mmc_do_fs_boot(struct spl_image_info *spl_image, struct mmc *mmc)
|
|||
#ifdef CONFIG_SPL_FS_LOAD_PAYLOAD_NAME
|
||||
err = spl_load_image_fat(spl_image, mmc_get_blk_desc(mmc),
|
||||
CONFIG_SYS_MMCSD_FS_BOOT_PARTITION,
|
||||
CONFIG_SPL_FS_LOAD_PAYLOAD_NAME);
|
||||
filename);
|
||||
if (!err)
|
||||
return err;
|
||||
#endif
|
||||
|
@ -263,7 +264,7 @@ static int spl_mmc_do_fs_boot(struct spl_image_info *spl_image, struct mmc *mmc)
|
|||
#ifdef CONFIG_SPL_FS_LOAD_PAYLOAD_NAME
|
||||
err = spl_load_image_ext(spl_image, mmc_get_blk_desc(mmc),
|
||||
CONFIG_SYS_MMCSD_FS_BOOT_PARTITION,
|
||||
CONFIG_SPL_FS_LOAD_PAYLOAD_NAME);
|
||||
filename);
|
||||
if (!err)
|
||||
return err;
|
||||
#endif
|
||||
|
@ -276,7 +277,8 @@ static int spl_mmc_do_fs_boot(struct spl_image_info *spl_image, struct mmc *mmc)
|
|||
return err;
|
||||
}
|
||||
#else
|
||||
static int spl_mmc_do_fs_boot(struct spl_image_info *spl_image, struct mmc *mmc)
|
||||
static int spl_mmc_do_fs_boot(struct spl_image_info *spl_image, struct mmc *mmc,
|
||||
const char *filename)
|
||||
{
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
@ -301,24 +303,31 @@ int spl_boot_partition(const u32 boot_device)
|
|||
}
|
||||
#endif
|
||||
|
||||
int spl_mmc_load_image(struct spl_image_info *spl_image,
|
||||
struct spl_boot_device *bootdev)
|
||||
int spl_mmc_load(struct spl_image_info *spl_image,
|
||||
struct spl_boot_device *bootdev,
|
||||
const char *filename,
|
||||
int raw_part,
|
||||
unsigned long raw_sect)
|
||||
{
|
||||
struct mmc *mmc = NULL;
|
||||
static struct mmc *mmc;
|
||||
u32 boot_mode;
|
||||
int err = 0;
|
||||
__maybe_unused int part;
|
||||
|
||||
err = spl_mmc_find_device(&mmc, bootdev->boot_device);
|
||||
if (err)
|
||||
return err;
|
||||
/* Perform peripheral init only once */
|
||||
if (!mmc) {
|
||||
err = spl_mmc_find_device(&mmc, bootdev->boot_device);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
err = mmc_init(mmc);
|
||||
if (err) {
|
||||
err = mmc_init(mmc);
|
||||
if (err) {
|
||||
mmc = NULL;
|
||||
#ifdef CONFIG_SPL_LIBCOMMON_SUPPORT
|
||||
printf("spl: mmc init failed with error: %d\n", err);
|
||||
printf("spl: mmc init failed with error: %d\n", err);
|
||||
#endif
|
||||
return err;
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
boot_mode = spl_boot_mode(bootdev->boot_device);
|
||||
|
@ -356,17 +365,13 @@ int spl_mmc_load_image(struct spl_image_info *spl_image,
|
|||
return err;
|
||||
}
|
||||
#ifdef CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_USE_PARTITION
|
||||
err = spl_boot_partition(bootdev->boot_device);
|
||||
if (!err)
|
||||
return err;
|
||||
|
||||
err = mmc_load_image_raw_partition(spl_image, mmc, err);
|
||||
err = mmc_load_image_raw_partition(spl_image, mmc, raw_part,
|
||||
raw_sect);
|
||||
if (!err)
|
||||
return err;
|
||||
#endif
|
||||
#ifdef CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_USE_SECTOR
|
||||
err = mmc_load_image_raw_sector(spl_image, mmc,
|
||||
CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR);
|
||||
err = mmc_load_image_raw_sector(spl_image, mmc, raw_sect);
|
||||
if (!err)
|
||||
return err;
|
||||
#endif
|
||||
|
@ -374,7 +379,7 @@ int spl_mmc_load_image(struct spl_image_info *spl_image,
|
|||
case MMCSD_MODE_FS:
|
||||
debug("spl: mmc boot mode: fs\n");
|
||||
|
||||
err = spl_mmc_do_fs_boot(spl_image, mmc);
|
||||
err = spl_mmc_do_fs_boot(spl_image, mmc, filename);
|
||||
if (!err)
|
||||
return err;
|
||||
|
||||
|
@ -388,6 +393,27 @@ int spl_mmc_load_image(struct spl_image_info *spl_image,
|
|||
return err;
|
||||
}
|
||||
|
||||
int spl_mmc_load_image(struct spl_image_info *spl_image,
|
||||
struct spl_boot_device *bootdev)
|
||||
{
|
||||
return spl_mmc_load(spl_image, bootdev,
|
||||
#ifdef CONFIG_SPL_FS_LOAD_PAYLOAD_NAME
|
||||
CONFIG_SPL_FS_LOAD_PAYLOAD_NAME,
|
||||
#else
|
||||
NULL,
|
||||
#endif
|
||||
#ifdef CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_PARTITION
|
||||
spl_boot_partition(bootdev->boot_device),
|
||||
#else
|
||||
0,
|
||||
#endif
|
||||
#ifdef CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR
|
||||
CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR);
|
||||
#else
|
||||
0);
|
||||
#endif
|
||||
}
|
||||
|
||||
SPL_LOAD_IMAGE_METHOD("MMC1", 0, BOOT_DEVICE_MMC1, spl_mmc_load_image);
|
||||
SPL_LOAD_IMAGE_METHOD("MMC2", 0, BOOT_DEVICE_MMC2, spl_mmc_load_image);
|
||||
SPL_LOAD_IMAGE_METHOD("MMC2_2", 0, BOOT_DEVICE_MMC2_2, spl_mmc_load_image);
|
||||
|
|
|
@ -1,4 +1,8 @@
|
|||
CONFIG_ARM=y
|
||||
# CONFIG_SPL_USE_ARCH_MEMCPY is not set
|
||||
# CONFIG_TPL_USE_ARCH_MEMCPY is not set
|
||||
# CONFIG_SPL_USE_ARCH_MEMSET is not set
|
||||
# CONFIG_TPL_USE_ARCH_MEMSET is not set
|
||||
CONFIG_ARCH_OMAP2PLUS=y
|
||||
CONFIG_TI_COMMON_CMD_OPTIONS=y
|
||||
CONFIG_AM33XX=y
|
||||
|
|
|
@ -2,7 +2,7 @@ CONFIG_ARM=y
|
|||
CONFIG_ARCH_K3=y
|
||||
CONFIG_SPL_LIBCOMMON_SUPPORT=y
|
||||
CONFIG_SPL_LIBGENERIC_SUPPORT=y
|
||||
CONFIG_SYS_MALLOC_F_LEN=0x2000
|
||||
CONFIG_SYS_MALLOC_F_LEN=0x8000
|
||||
CONFIG_SOC_K3_AM6=y
|
||||
CONFIG_TARGET_AM654_A53_EVM=y
|
||||
CONFIG_SPL_MMC_SUPPORT=y
|
||||
|
@ -16,12 +16,14 @@ CONFIG_DISTRO_DEFAULTS=y
|
|||
# CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
|
||||
CONFIG_SPL_LOAD_FIT=y
|
||||
CONFIG_OF_BOARD_SETUP=y
|
||||
CONFIG_BOOTCOMMAND="run findfdt; run envboot; run init_${boot}; run get_kern_${boot}; run get_fdt_${boot}; run run_kern"
|
||||
CONFIG_BOOTCOMMAND="run findfdt; run envboot; run init_${boot}; run get_kern_${boot}; run get_fdt_${boot}; run get_overlay_${boot}; run run_kern"
|
||||
# CONFIG_DISPLAY_CPUINFO is not set
|
||||
CONFIG_SPL_TEXT_BASE=0x80080000
|
||||
CONFIG_SPL_SYS_MALLOC_SIMPLE=y
|
||||
CONFIG_SPL_STACK_R=y
|
||||
CONFIG_SPL_SEPARATE_BSS=y
|
||||
CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_USE_SECTOR=y
|
||||
CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR=0x1400
|
||||
CONFIG_SPL_I2C_SUPPORT=y
|
||||
CONFIG_SPL_DM_MAILBOX=y
|
||||
CONFIG_SPL_DM_RESET=y
|
||||
|
@ -30,35 +32,41 @@ CONFIG_SPL_REMOTEPROC=y
|
|||
CONFIG_SPL_YMODEM_SUPPORT=y
|
||||
CONFIG_CMD_ASKENV=y
|
||||
# CONFIG_CMD_FLASH is not set
|
||||
CONFIG_CMD_GPT=y
|
||||
CONFIG_CMD_I2C=y
|
||||
CONFIG_CMD_MMC=y
|
||||
CONFIG_CMD_REMOTEPROC=y
|
||||
# CONFIG_CMD_SETEXPR is not set
|
||||
CONFIG_CMD_TIME=y
|
||||
# CONFIG_ISO_PARTITION is not set
|
||||
# CONFIG_EFI_PARTITION is not set
|
||||
CONFIG_OF_CONTROL=y
|
||||
CONFIG_SPL_OF_CONTROL=y
|
||||
CONFIG_DEFAULT_DEVICE_TREE="k3-am654-base-board"
|
||||
CONFIG_SPL_MULTI_DTB_FIT=y
|
||||
CONFIG_SPL_MULTI_DTB_FIT_NO_COMPRESSION=y
|
||||
CONFIG_ENV_IS_IN_FAT=y
|
||||
CONFIG_ENV_FAT_INTERFACE="mmc"
|
||||
CONFIG_ENV_FAT_DEVICE_AND_PART="1:1"
|
||||
CONFIG_ENV_IS_IN_MMC=y
|
||||
CONFIG_NET_RANDOM_ETHADDR=y
|
||||
CONFIG_DM=y
|
||||
CONFIG_SPL_DM=y
|
||||
CONFIG_SPL_DM_SEQ_ALIAS=y
|
||||
CONFIG_REGMAP=y
|
||||
CONFIG_SPL_REGMAP=y
|
||||
CONFIG_CLK=y
|
||||
CONFIG_SPL_CLK=y
|
||||
CONFIG_CLK_TI_SCI=y
|
||||
CONFIG_DMA_CHANNELS=y
|
||||
CONFIG_TI_K3_NAVSS_UDMA=y
|
||||
CONFIG_TI_SCI_PROTOCOL=y
|
||||
CONFIG_DM_GPIO=y
|
||||
CONFIG_DM_PCA953X=y
|
||||
CONFIG_DM_I2C=y
|
||||
CONFIG_I2C_SET_DEFAULT_BUS_NUM=y
|
||||
CONFIG_SYS_I2C_OMAP24XX=y
|
||||
CONFIG_DM_MAILBOX=y
|
||||
CONFIG_K3_SEC_PROXY=y
|
||||
CONFIG_DM_MMC=y
|
||||
CONFIG_MMC_SDHCI=y
|
||||
CONFIG_MMC_SDHCI_K3_ARASAN=y
|
||||
CONFIG_MMC_SDHCI_AM654=y
|
||||
CONFIG_PHY_TI=y
|
||||
CONFIG_PHY_FIXED=y
|
||||
CONFIG_DM_ETH=y
|
||||
|
@ -80,3 +88,5 @@ CONFIG_SOC_TI=y
|
|||
CONFIG_SYSRESET=y
|
||||
CONFIG_SPL_SYSRESET=y
|
||||
CONFIG_SYSRESET_TI_SCI=y
|
||||
CONFIG_FAT_WRITE=y
|
||||
CONFIG_OF_LIBFDT_OVERLAY=y
|
||||
|
|
|
@ -3,7 +3,7 @@ CONFIG_ARCH_K3=y
|
|||
CONFIG_SPL_GPIO_SUPPORT=y
|
||||
CONFIG_SPL_LIBCOMMON_SUPPORT=y
|
||||
CONFIG_SPL_LIBGENERIC_SUPPORT=y
|
||||
CONFIG_SYS_MALLOC_F_LEN=0x2000
|
||||
CONFIG_SYS_MALLOC_F_LEN=0x55000
|
||||
CONFIG_SOC_K3_AM6=y
|
||||
CONFIG_TARGET_AM654_R5_EVM=y
|
||||
CONFIG_SPL_MMC_SUPPORT=y
|
||||
|
@ -18,9 +18,11 @@ CONFIG_SPL_LOAD_FIT=y
|
|||
CONFIG_USE_BOOTCOMMAND=y
|
||||
# CONFIG_DISPLAY_CPUINFO is not set
|
||||
CONFIG_SPL_TEXT_BASE=0x41c00000
|
||||
CONFIG_SPL_SYS_MALLOC_SIMPLE=y
|
||||
CONFIG_SPL_STACK_R=y
|
||||
CONFIG_SPL_SEPARATE_BSS=y
|
||||
CONFIG_SPL_EARLY_BSS=y
|
||||
CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_USE_SECTOR=y
|
||||
CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR=0x400
|
||||
CONFIG_SPL_I2C_SUPPORT=y
|
||||
CONFIG_SPL_DM_MAILBOX=y
|
||||
CONFIG_SPL_DM_RESET=y
|
||||
|
@ -35,6 +37,7 @@ CONFIG_CMD_BOOTZ=y
|
|||
CONFIG_CMD_ASKENV=y
|
||||
# CONFIG_CMD_FLASH is not set
|
||||
CONFIG_CMD_GPT=y
|
||||
CONFIG_CMD_I2C=y
|
||||
CONFIG_CMD_MMC=y
|
||||
CONFIG_CMD_REMOTEPROC=y
|
||||
# CONFIG_CMD_SETEXPR is not set
|
||||
|
@ -51,6 +54,8 @@ CONFIG_ENV_FAT_DEVICE_AND_PART="1:1"
|
|||
CONFIG_DM=y
|
||||
CONFIG_SPL_DM=y
|
||||
CONFIG_SPL_DM_SEQ_ALIAS=y
|
||||
CONFIG_REGMAP=y
|
||||
CONFIG_SPL_REGMAP=y
|
||||
CONFIG_SPL_OF_TRANSLATE=y
|
||||
CONFIG_CLK=y
|
||||
CONFIG_SPL_CLK=y
|
||||
|
@ -58,12 +63,15 @@ CONFIG_CLK_TI_SCI=y
|
|||
CONFIG_TI_SCI_PROTOCOL=y
|
||||
CONFIG_DM_GPIO=y
|
||||
CONFIG_DA8XX_GPIO=y
|
||||
CONFIG_DM_I2C=y
|
||||
CONFIG_I2C_SET_DEFAULT_BUS_NUM=y
|
||||
CONFIG_SYS_I2C_OMAP24XX=y
|
||||
CONFIG_DM_MAILBOX=y
|
||||
CONFIG_K3_SEC_PROXY=y
|
||||
CONFIG_MISC=y
|
||||
CONFIG_DM_MMC=y
|
||||
CONFIG_MMC_SDHCI=y
|
||||
CONFIG_MMC_SDHCI_K3_ARASAN=y
|
||||
CONFIG_MMC_SDHCI_AM654=y
|
||||
CONFIG_PINCTRL=y
|
||||
# CONFIG_PINCTRL_GENERIC is not set
|
||||
CONFIG_SPL_PINCTRL=y
|
||||
|
@ -88,3 +96,4 @@ CONFIG_SYSRESET_TI_SCI=y
|
|||
CONFIG_TIMER=y
|
||||
CONFIG_SPL_TIMER=y
|
||||
CONFIG_OMAP_TIMER=y
|
||||
CONFIG_FS_FAT_MAX_CLUSTSIZE=16384
|
||||
|
|
|
@ -3,7 +3,7 @@ CONFIG_ARCH_K3=y
|
|||
CONFIG_TI_SECURE_DEVICE=y
|
||||
CONFIG_SPL_LIBCOMMON_SUPPORT=y
|
||||
CONFIG_SPL_LIBGENERIC_SUPPORT=y
|
||||
CONFIG_SYS_MALLOC_F_LEN=0x2000
|
||||
CONFIG_SYS_MALLOC_F_LEN=0x8000
|
||||
CONFIG_SOC_K3_AM6=y
|
||||
CONFIG_TARGET_AM654_A53_EVM=y
|
||||
CONFIG_SPL_MMC_SUPPORT=y
|
||||
|
@ -19,12 +19,14 @@ CONFIG_FIT_IMAGE_POST_PROCESS=y
|
|||
CONFIG_SPL_LOAD_FIT=y
|
||||
CONFIG_SPL_FIT_IMAGE_POST_PROCESS=y
|
||||
CONFIG_OF_BOARD_SETUP=y
|
||||
CONFIG_BOOTCOMMAND="run findfdt; run envboot; run init_${boot}; run get_kern_${boot}; run get_fdt_${boot}; run run_kern"
|
||||
CONFIG_BOOTCOMMAND="run findfdt; run envboot; run init_${boot}; run get_kern_${boot}; run get_fdt_${boot}; run get_overlay_${boot}; run run_kern"
|
||||
# CONFIG_DISPLAY_CPUINFO is not set
|
||||
CONFIG_SPL_TEXT_BASE=0x80080000
|
||||
CONFIG_SPL_SYS_MALLOC_SIMPLE=y
|
||||
CONFIG_SPL_STACK_R=y
|
||||
CONFIG_SPL_SEPARATE_BSS=y
|
||||
CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_USE_SECTOR=y
|
||||
CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR=0x1400
|
||||
CONFIG_SPL_I2C_SUPPORT=y
|
||||
CONFIG_SPL_DM_MAILBOX=y
|
||||
CONFIG_SPL_DM_RESET=y
|
||||
|
@ -33,6 +35,7 @@ CONFIG_SPL_REMOTEPROC=y
|
|||
CONFIG_SPL_YMODEM_SUPPORT=y
|
||||
CONFIG_CMD_ASKENV=y
|
||||
# CONFIG_CMD_FLASH is not set
|
||||
CONFIG_CMD_I2C=y
|
||||
CONFIG_CMD_MMC=y
|
||||
CONFIG_CMD_REMOTEPROC=y
|
||||
# CONFIG_CMD_SETEXPR is not set
|
||||
|
@ -56,6 +59,11 @@ CONFIG_CLK_TI_SCI=y
|
|||
CONFIG_DMA_CHANNELS=y
|
||||
CONFIG_TI_K3_NAVSS_UDMA=y
|
||||
CONFIG_TI_SCI_PROTOCOL=y
|
||||
CONFIG_DM_GPIO=y
|
||||
CONFIG_DM_PCA953X=y
|
||||
CONFIG_DM_I2C=y
|
||||
CONFIG_I2C_SET_DEFAULT_BUS_NUM=y
|
||||
CONFIG_SYS_I2C_OMAP24XX=y
|
||||
CONFIG_DM_MAILBOX=y
|
||||
CONFIG_K3_SEC_PROXY=y
|
||||
CONFIG_DM_MMC=y
|
||||
|
@ -77,3 +85,4 @@ CONFIG_SOC_TI=y
|
|||
CONFIG_SYSRESET=y
|
||||
CONFIG_SPL_SYSRESET=y
|
||||
CONFIG_SYSRESET_TI_SCI=y
|
||||
CONFIG_OF_LIBFDT_OVERLAY=y
|
||||
|
|
|
@ -4,7 +4,7 @@ CONFIG_TI_SECURE_DEVICE=y
|
|||
CONFIG_SPL_GPIO_SUPPORT=y
|
||||
CONFIG_SPL_LIBCOMMON_SUPPORT=y
|
||||
CONFIG_SPL_LIBGENERIC_SUPPORT=y
|
||||
CONFIG_SYS_MALLOC_F_LEN=0x2000
|
||||
CONFIG_SYS_MALLOC_F_LEN=0x55000
|
||||
CONFIG_SOC_K3_AM6=y
|
||||
CONFIG_TARGET_AM654_R5_EVM=y
|
||||
CONFIG_SPL_MMC_SUPPORT=y
|
||||
|
@ -20,9 +20,11 @@ CONFIG_SPL_FIT_IMAGE_POST_PROCESS=y
|
|||
CONFIG_USE_BOOTCOMMAND=y
|
||||
# CONFIG_DISPLAY_CPUINFO is not set
|
||||
CONFIG_SPL_TEXT_BASE=0x41c00000
|
||||
CONFIG_SPL_SYS_MALLOC_SIMPLE=y
|
||||
CONFIG_SPL_STACK_R=y
|
||||
CONFIG_SPL_SEPARATE_BSS=y
|
||||
CONFIG_SPL_EARLY_BSS=y
|
||||
CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_USE_SECTOR=y
|
||||
CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR=0x400
|
||||
CONFIG_SPL_I2C_SUPPORT=y
|
||||
CONFIG_SPL_DM_MAILBOX=y
|
||||
CONFIG_SPL_DM_RESET=y
|
||||
|
@ -37,6 +39,7 @@ CONFIG_CMD_BOOTZ=y
|
|||
CONFIG_CMD_ASKENV=y
|
||||
# CONFIG_CMD_FLASH is not set
|
||||
CONFIG_CMD_GPT=y
|
||||
CONFIG_CMD_I2C=y
|
||||
CONFIG_CMD_MMC=y
|
||||
CONFIG_CMD_REMOTEPROC=y
|
||||
# CONFIG_CMD_SETEXPR is not set
|
||||
|
@ -60,6 +63,9 @@ CONFIG_CLK_TI_SCI=y
|
|||
CONFIG_TI_SCI_PROTOCOL=y
|
||||
CONFIG_DM_GPIO=y
|
||||
CONFIG_DA8XX_GPIO=y
|
||||
CONFIG_DM_I2C=y
|
||||
CONFIG_I2C_SET_DEFAULT_BUS_NUM=y
|
||||
CONFIG_SYS_I2C_OMAP24XX=y
|
||||
CONFIG_DM_MAILBOX=y
|
||||
CONFIG_K3_SEC_PROXY=y
|
||||
CONFIG_MISC=y
|
||||
|
@ -90,3 +96,4 @@ CONFIG_SYSRESET_TI_SCI=y
|
|||
CONFIG_TIMER=y
|
||||
CONFIG_SPL_TIMER=y
|
||||
CONFIG_OMAP_TIMER=y
|
||||
CONFIG_FS_FAT_MAX_CLUSTSIZE=16384
|
||||
|
|
|
@ -108,6 +108,48 @@ static int init_range(ofnode node, struct regmap_range *range, int addr_len,
|
|||
return 0;
|
||||
}
|
||||
|
||||
int regmap_init_mem_index(ofnode node, struct regmap **mapp, int index)
|
||||
{
|
||||
struct regmap *map;
|
||||
int addr_len, size_len;
|
||||
int ret;
|
||||
|
||||
addr_len = ofnode_read_simple_addr_cells(ofnode_get_parent(node));
|
||||
if (addr_len < 0) {
|
||||
debug("%s: Error while reading the addr length (ret = %d)\n",
|
||||
ofnode_get_name(node), addr_len);
|
||||
return addr_len;
|
||||
}
|
||||
|
||||
size_len = ofnode_read_simple_size_cells(ofnode_get_parent(node));
|
||||
if (size_len < 0) {
|
||||
debug("%s: Error while reading the size length: (ret = %d)\n",
|
||||
ofnode_get_name(node), size_len);
|
||||
return size_len;
|
||||
}
|
||||
|
||||
map = regmap_alloc(1);
|
||||
if (!map)
|
||||
return -ENOMEM;
|
||||
|
||||
ret = init_range(node, map->ranges, addr_len, size_len, index);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (ofnode_read_bool(node, "little-endian"))
|
||||
map->endianness = REGMAP_LITTLE_ENDIAN;
|
||||
else if (ofnode_read_bool(node, "big-endian"))
|
||||
map->endianness = REGMAP_BIG_ENDIAN;
|
||||
else if (ofnode_read_bool(node, "native-endian"))
|
||||
map->endianness = REGMAP_NATIVE_ENDIAN;
|
||||
else /* Default: native endianness */
|
||||
map->endianness = REGMAP_NATIVE_ENDIAN;
|
||||
|
||||
*mapp = map;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int regmap_init_mem(ofnode node, struct regmap **mapp)
|
||||
{
|
||||
struct regmap_range *range;
|
||||
|
|
|
@ -330,7 +330,7 @@ endif
|
|||
|
||||
config SYS_I2C_OMAP24XX
|
||||
bool "TI OMAP2+ I2C driver"
|
||||
depends on ARCH_OMAP2PLUS
|
||||
depends on ARCH_OMAP2PLUS || ARCH_K3
|
||||
help
|
||||
Add support for the OMAP2+ I2C driver.
|
||||
|
||||
|
|
|
@ -468,14 +468,15 @@ config MMC_SDHCI_CADENCE
|
|||
|
||||
If unsure, say N.
|
||||
|
||||
config MMC_SDHCI_K3_ARASAN
|
||||
bool "Arasan SDHCI controller for TI's K3 based SoCs"
|
||||
config MMC_SDHCI_AM654
|
||||
bool "SDHCI Controller on TI's Am654 devices"
|
||||
depends on ARCH_K3
|
||||
depends on MMC_SDHCI
|
||||
depends on DM_MMC && OF_CONTROL && BLK
|
||||
depends on REGMAP
|
||||
help
|
||||
Support for Arasan SDHCI host controller on Texas Instruments'
|
||||
K3 family based SoC platforms
|
||||
Support for Secure Digital Host Controller Interface (SDHCI)
|
||||
controllers present on TI's AM654 SOCs.
|
||||
|
||||
config MMC_SDHCI_KONA
|
||||
bool "SDHCI support on Broadcom KONA platform"
|
||||
|
|
|
@ -50,7 +50,7 @@ obj-$(CONFIG_MMC_SDHCI_ATMEL) += atmel_sdhci.o
|
|||
obj-$(CONFIG_MMC_SDHCI_BCM2835) += bcm2835_sdhci.o
|
||||
obj-$(CONFIG_MMC_SDHCI_BCMSTB) += bcmstb_sdhci.o
|
||||
obj-$(CONFIG_MMC_SDHCI_CADENCE) += sdhci-cadence.o
|
||||
obj-$(CONFIG_MMC_SDHCI_K3_ARASAN) += k3_arsan_sdhci.o
|
||||
obj-$(CONFIG_MMC_SDHCI_AM654) += am654_sdhci.o
|
||||
obj-$(CONFIG_MMC_SDHCI_KONA) += kona_sdhci.o
|
||||
obj-$(CONFIG_MMC_SDHCI_MSM) += msm_sdhci.o
|
||||
obj-$(CONFIG_MMC_SDHCI_MV) += mv_sdhci.o
|
||||
|
|
333
drivers/mmc/am654_sdhci.c
Normal file
333
drivers/mmc/am654_sdhci.c
Normal file
|
@ -0,0 +1,333 @@
|
|||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com/
|
||||
*
|
||||
* Texas Instruments' K3 SD Host Controller Interface
|
||||
*/
|
||||
|
||||
#include <clk.h>
|
||||
#include <common.h>
|
||||
#include <dm.h>
|
||||
#include <malloc.h>
|
||||
#include <power-domain.h>
|
||||
#include <regmap.h>
|
||||
#include <sdhci.h>
|
||||
|
||||
/* CTL_CFG Registers */
|
||||
#define CTL_CFG_2 0x14
|
||||
|
||||
#define SLOTTYPE_MASK GENMASK(31, 30)
|
||||
#define SLOTTYPE_EMBEDDED BIT(30)
|
||||
|
||||
/* PHY Registers */
|
||||
#define PHY_CTRL1 0x100
|
||||
#define PHY_CTRL2 0x104
|
||||
#define PHY_CTRL3 0x108
|
||||
#define PHY_CTRL4 0x10C
|
||||
#define PHY_CTRL5 0x110
|
||||
#define PHY_CTRL6 0x114
|
||||
#define PHY_STAT1 0x130
|
||||
#define PHY_STAT2 0x134
|
||||
|
||||
#define IOMUX_ENABLE_SHIFT 31
|
||||
#define IOMUX_ENABLE_MASK BIT(IOMUX_ENABLE_SHIFT)
|
||||
#define OTAPDLYENA_SHIFT 20
|
||||
#define OTAPDLYENA_MASK BIT(OTAPDLYENA_SHIFT)
|
||||
#define OTAPDLYSEL_SHIFT 12
|
||||
#define OTAPDLYSEL_MASK GENMASK(15, 12)
|
||||
#define STRBSEL_SHIFT 24
|
||||
#define STRBSEL_MASK GENMASK(27, 24)
|
||||
#define SEL50_SHIFT 8
|
||||
#define SEL50_MASK BIT(SEL50_SHIFT)
|
||||
#define SEL100_SHIFT 9
|
||||
#define SEL100_MASK BIT(SEL100_SHIFT)
|
||||
#define DLL_TRIM_ICP_SHIFT 4
|
||||
#define DLL_TRIM_ICP_MASK GENMASK(7, 4)
|
||||
#define DR_TY_SHIFT 20
|
||||
#define DR_TY_MASK GENMASK(22, 20)
|
||||
#define ENDLL_SHIFT 1
|
||||
#define ENDLL_MASK BIT(ENDLL_SHIFT)
|
||||
#define DLLRDY_SHIFT 0
|
||||
#define DLLRDY_MASK BIT(DLLRDY_SHIFT)
|
||||
#define PDB_SHIFT 0
|
||||
#define PDB_MASK BIT(PDB_SHIFT)
|
||||
#define CALDONE_SHIFT 1
|
||||
#define CALDONE_MASK BIT(CALDONE_SHIFT)
|
||||
#define RETRIM_SHIFT 17
|
||||
#define RETRIM_MASK BIT(RETRIM_SHIFT)
|
||||
|
||||
#define DRIVER_STRENGTH_50_OHM 0x0
|
||||
#define DRIVER_STRENGTH_33_OHM 0x1
|
||||
#define DRIVER_STRENGTH_66_OHM 0x2
|
||||
#define DRIVER_STRENGTH_100_OHM 0x3
|
||||
#define DRIVER_STRENGTH_40_OHM 0x4
|
||||
|
||||
#define AM654_SDHCI_MIN_FREQ 400000
|
||||
|
||||
struct am654_sdhci_plat {
|
||||
struct mmc_config cfg;
|
||||
struct mmc mmc;
|
||||
struct regmap *base;
|
||||
bool non_removable;
|
||||
u32 otap_del_sel;
|
||||
u32 trm_icp;
|
||||
u32 drv_strength;
|
||||
bool dll_on;
|
||||
};
|
||||
|
||||
static void am654_sdhci_set_control_reg(struct sdhci_host *host)
|
||||
{
|
||||
struct mmc *mmc = (struct mmc *)host->mmc;
|
||||
u32 reg;
|
||||
|
||||
if (IS_SD(host->mmc) &&
|
||||
mmc->signal_voltage == MMC_SIGNAL_VOLTAGE_180) {
|
||||
reg = sdhci_readw(host, SDHCI_HOST_CONTROL2);
|
||||
reg |= SDHCI_CTRL_VDD_180;
|
||||
sdhci_writew(host, reg, SDHCI_HOST_CONTROL2);
|
||||
}
|
||||
|
||||
sdhci_set_uhs_timing(host);
|
||||
}
|
||||
|
||||
static int am654_sdhci_set_ios_post(struct sdhci_host *host)
|
||||
{
|
||||
struct udevice *dev = host->mmc->dev;
|
||||
struct am654_sdhci_plat *plat = dev_get_platdata(dev);
|
||||
unsigned int speed = host->mmc->clock;
|
||||
int sel50, sel100;
|
||||
u32 mask, val;
|
||||
int ret;
|
||||
|
||||
/* Reset SD Clock Enable */
|
||||
val = sdhci_readw(host, SDHCI_CLOCK_CONTROL);
|
||||
val &= ~SDHCI_CLOCK_CARD_EN;
|
||||
sdhci_writew(host, val, SDHCI_CLOCK_CONTROL);
|
||||
|
||||
/* power off phy */
|
||||
if (plat->dll_on) {
|
||||
regmap_update_bits(plat->base, PHY_CTRL1, ENDLL_MASK, 0);
|
||||
|
||||
plat->dll_on = false;
|
||||
}
|
||||
|
||||
/* restart clock */
|
||||
sdhci_set_clock(host->mmc, speed);
|
||||
|
||||
/* switch phy back on */
|
||||
if (speed > AM654_SDHCI_MIN_FREQ) {
|
||||
mask = OTAPDLYENA_MASK | OTAPDLYSEL_MASK;
|
||||
val = (1 << OTAPDLYENA_SHIFT) |
|
||||
(plat->otap_del_sel << OTAPDLYSEL_SHIFT);
|
||||
regmap_update_bits(plat->base, PHY_CTRL4, mask, val);
|
||||
switch (speed) {
|
||||
case 200000000:
|
||||
sel50 = 0;
|
||||
sel100 = 0;
|
||||
break;
|
||||
case 100000000:
|
||||
sel50 = 0;
|
||||
sel100 = 1;
|
||||
break;
|
||||
default:
|
||||
sel50 = 1;
|
||||
sel100 = 0;
|
||||
}
|
||||
|
||||
/* Configure PHY DLL frequency */
|
||||
mask = SEL50_MASK | SEL100_MASK;
|
||||
val = (sel50 << SEL50_SHIFT) | (sel100 << SEL100_SHIFT);
|
||||
regmap_update_bits(plat->base, PHY_CTRL5, mask, val);
|
||||
|
||||
/* Enable DLL */
|
||||
regmap_update_bits(plat->base, PHY_CTRL1, ENDLL_MASK,
|
||||
0x1 << ENDLL_SHIFT);
|
||||
/*
|
||||
* Poll for DLL ready. Use a one second timeout.
|
||||
* Works in all experiments done so far
|
||||
*/
|
||||
ret = regmap_read_poll_timeout(plat->base, PHY_STAT1, val,
|
||||
val & DLLRDY_MASK, 1000, 1000000);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
plat->dll_on = true;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
const struct sdhci_ops am654_sdhci_ops = {
|
||||
.set_ios_post = &am654_sdhci_set_ios_post,
|
||||
.set_control_reg = &am654_sdhci_set_control_reg,
|
||||
};
|
||||
|
||||
int am654_sdhci_init(struct am654_sdhci_plat *plat)
|
||||
{
|
||||
u32 ctl_cfg_2 = 0;
|
||||
u32 mask, val;
|
||||
int ret;
|
||||
|
||||
/* Reset OTAP to default value */
|
||||
mask = OTAPDLYENA_MASK | OTAPDLYSEL_MASK;
|
||||
regmap_update_bits(plat->base, PHY_CTRL4, mask, 0x0);
|
||||
|
||||
regmap_read(plat->base, PHY_STAT1, &val);
|
||||
if (~val & CALDONE_MASK) {
|
||||
/* Calibrate IO lines */
|
||||
regmap_update_bits(plat->base, PHY_CTRL1, PDB_MASK, PDB_MASK);
|
||||
ret = regmap_read_poll_timeout(plat->base, PHY_STAT1, val,
|
||||
val & CALDONE_MASK, 1, 20);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Configure DLL TRIM */
|
||||
mask = DLL_TRIM_ICP_MASK;
|
||||
val = plat->trm_icp << DLL_TRIM_ICP_SHIFT;
|
||||
|
||||
/* Configure DLL driver strength */
|
||||
mask |= DR_TY_MASK;
|
||||
val |= plat->drv_strength << DR_TY_SHIFT;
|
||||
regmap_update_bits(plat->base, PHY_CTRL1, mask, val);
|
||||
|
||||
/* Enable pins by setting IO mux to 0 */
|
||||
regmap_update_bits(plat->base, PHY_CTRL1, IOMUX_ENABLE_MASK, 0);
|
||||
|
||||
/* Set slot type based on SD or eMMC */
|
||||
if (plat->non_removable)
|
||||
ctl_cfg_2 = SLOTTYPE_EMBEDDED;
|
||||
|
||||
regmap_update_bits(plat->base, CTL_CFG_2, SLOTTYPE_MASK, ctl_cfg_2);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int am654_sdhci_probe(struct udevice *dev)
|
||||
{
|
||||
struct am654_sdhci_plat *plat = dev_get_platdata(dev);
|
||||
struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev);
|
||||
struct sdhci_host *host = dev_get_priv(dev);
|
||||
struct mmc_config *cfg = &plat->cfg;
|
||||
struct power_domain sdhci_pwrdmn;
|
||||
struct clk clk;
|
||||
unsigned long clock;
|
||||
int ret;
|
||||
|
||||
ret = power_domain_get_by_index(dev, &sdhci_pwrdmn, 0);
|
||||
if (!ret) {
|
||||
ret = power_domain_on(&sdhci_pwrdmn);
|
||||
if (ret) {
|
||||
dev_err(dev, "Power domain on failed (%d)\n", ret);
|
||||
return ret;
|
||||
}
|
||||
} else if (ret != -ENOENT && ret != -ENODEV && ret != -ENOSYS) {
|
||||
dev_err(dev, "failed to get power domain (%d)\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = clk_get_by_index(dev, 0, &clk);
|
||||
if (ret) {
|
||||
dev_err(dev, "failed to get clock\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
clock = clk_get_rate(&clk);
|
||||
if (IS_ERR_VALUE(clock)) {
|
||||
dev_err(dev, "failed to get rate\n");
|
||||
return clock;
|
||||
}
|
||||
|
||||
host->max_clk = clock;
|
||||
host->mmc = &plat->mmc;
|
||||
host->mmc->dev = dev;
|
||||
ret = sdhci_setup_cfg(cfg, host, cfg->f_max,
|
||||
AM654_SDHCI_MIN_FREQ);
|
||||
if (ret)
|
||||
return ret;
|
||||
host->ops = &am654_sdhci_ops;
|
||||
host->mmc->priv = host;
|
||||
upriv->mmc = host->mmc;
|
||||
|
||||
regmap_init_mem_index(dev_ofnode(dev), &plat->base, 1);
|
||||
|
||||
am654_sdhci_init(plat);
|
||||
|
||||
return sdhci_probe(dev);
|
||||
}
|
||||
|
||||
static int am654_sdhci_ofdata_to_platdata(struct udevice *dev)
|
||||
{
|
||||
struct am654_sdhci_plat *plat = dev_get_platdata(dev);
|
||||
struct sdhci_host *host = dev_get_priv(dev);
|
||||
struct mmc_config *cfg = &plat->cfg;
|
||||
u32 drv_strength;
|
||||
int ret;
|
||||
|
||||
host->name = dev->name;
|
||||
host->ioaddr = (void *)dev_read_addr(dev);
|
||||
plat->non_removable = dev_read_bool(dev, "non-removable");
|
||||
|
||||
ret = dev_read_u32(dev, "ti,trm-icp", &plat->trm_icp);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = dev_read_u32(dev, "ti,otap-del-sel", &plat->otap_del_sel);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = dev_read_u32(dev, "ti,driver-strength-ohm", &drv_strength);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
switch (drv_strength) {
|
||||
case 50:
|
||||
plat->drv_strength = DRIVER_STRENGTH_50_OHM;
|
||||
break;
|
||||
case 33:
|
||||
plat->drv_strength = DRIVER_STRENGTH_33_OHM;
|
||||
break;
|
||||
case 66:
|
||||
plat->drv_strength = DRIVER_STRENGTH_66_OHM;
|
||||
break;
|
||||
case 100:
|
||||
plat->drv_strength = DRIVER_STRENGTH_100_OHM;
|
||||
break;
|
||||
case 40:
|
||||
plat->drv_strength = DRIVER_STRENGTH_40_OHM;
|
||||
break;
|
||||
default:
|
||||
dev_err(dev, "Invalid driver strength\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = mmc_of_parse(dev, cfg);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int am654_sdhci_bind(struct udevice *dev)
|
||||
{
|
||||
struct am654_sdhci_plat *plat = dev_get_platdata(dev);
|
||||
|
||||
return sdhci_bind(dev, &plat->mmc, &plat->cfg);
|
||||
}
|
||||
|
||||
static const struct udevice_id am654_sdhci_ids[] = {
|
||||
{ .compatible = "ti,am654-sdhci-5.1" },
|
||||
{ }
|
||||
};
|
||||
|
||||
U_BOOT_DRIVER(am654_sdhci_drv) = {
|
||||
.name = "am654_sdhci",
|
||||
.id = UCLASS_MMC,
|
||||
.of_match = am654_sdhci_ids,
|
||||
.ofdata_to_platdata = am654_sdhci_ofdata_to_platdata,
|
||||
.ops = &sdhci_ops,
|
||||
.bind = am654_sdhci_bind,
|
||||
.probe = am654_sdhci_probe,
|
||||
.priv_auto_alloc_size = sizeof(struct sdhci_host),
|
||||
.platdata_auto_alloc_size = sizeof(struct am654_sdhci_plat),
|
||||
};
|
|
@ -1,109 +0,0 @@
|
|||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com/
|
||||
*
|
||||
* Texas Instruments' K3 SD Host Controller Interface
|
||||
*/
|
||||
|
||||
#include <clk.h>
|
||||
#include <common.h>
|
||||
#include <dm.h>
|
||||
#include <malloc.h>
|
||||
#include <power-domain.h>
|
||||
#include <sdhci.h>
|
||||
|
||||
#define K3_ARASAN_SDHCI_MIN_FREQ 0
|
||||
|
||||
struct k3_arasan_sdhci_plat {
|
||||
struct mmc_config cfg;
|
||||
struct mmc mmc;
|
||||
unsigned int f_max;
|
||||
};
|
||||
|
||||
static int k3_arasan_sdhci_probe(struct udevice *dev)
|
||||
{
|
||||
struct k3_arasan_sdhci_plat *plat = dev_get_platdata(dev);
|
||||
struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev);
|
||||
struct sdhci_host *host = dev_get_priv(dev);
|
||||
struct power_domain sdhci_pwrdmn;
|
||||
struct clk clk;
|
||||
unsigned long clock;
|
||||
int ret;
|
||||
|
||||
ret = power_domain_get_by_index(dev, &sdhci_pwrdmn, 0);
|
||||
if (ret) {
|
||||
dev_err(dev, "failed to get power domain\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = power_domain_on(&sdhci_pwrdmn);
|
||||
if (ret) {
|
||||
dev_err(dev, "Power domain on failed\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = clk_get_by_index(dev, 0, &clk);
|
||||
if (ret) {
|
||||
dev_err(dev, "failed to get clock\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
clock = clk_get_rate(&clk);
|
||||
if (IS_ERR_VALUE(clock)) {
|
||||
dev_err(dev, "failed to get rate\n");
|
||||
return clock;
|
||||
}
|
||||
|
||||
host->quirks = SDHCI_QUIRK_WAIT_SEND_CMD |
|
||||
SDHCI_QUIRK_BROKEN_R1B;
|
||||
|
||||
host->max_clk = clock;
|
||||
|
||||
ret = sdhci_setup_cfg(&plat->cfg, host, plat->f_max,
|
||||
K3_ARASAN_SDHCI_MIN_FREQ);
|
||||
host->mmc = &plat->mmc;
|
||||
if (ret)
|
||||
return ret;
|
||||
host->mmc->priv = host;
|
||||
host->mmc->dev = dev;
|
||||
upriv->mmc = host->mmc;
|
||||
|
||||
return sdhci_probe(dev);
|
||||
}
|
||||
|
||||
static int k3_arasan_sdhci_ofdata_to_platdata(struct udevice *dev)
|
||||
{
|
||||
struct k3_arasan_sdhci_plat *plat = dev_get_platdata(dev);
|
||||
struct sdhci_host *host = dev_get_priv(dev);
|
||||
|
||||
host->name = dev->name;
|
||||
host->ioaddr = (void *)dev_read_addr(dev);
|
||||
host->bus_width = dev_read_u32_default(dev, "bus-width", 4);
|
||||
plat->f_max = dev_read_u32_default(dev, "max-frequency", 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int k3_arasan_sdhci_bind(struct udevice *dev)
|
||||
{
|
||||
struct k3_arasan_sdhci_plat *plat = dev_get_platdata(dev);
|
||||
|
||||
return sdhci_bind(dev, &plat->mmc, &plat->cfg);
|
||||
}
|
||||
|
||||
static const struct udevice_id k3_arasan_sdhci_ids[] = {
|
||||
{ .compatible = "arasan,sdhci-5.1" },
|
||||
{ }
|
||||
};
|
||||
|
||||
U_BOOT_DRIVER(k3_arasan_sdhci_drv) = {
|
||||
.name = "k3_arasan_sdhci",
|
||||
.id = UCLASS_MMC,
|
||||
.of_match = k3_arasan_sdhci_ids,
|
||||
.ofdata_to_platdata = k3_arasan_sdhci_ofdata_to_platdata,
|
||||
.ops = &sdhci_ops,
|
||||
.bind = k3_arasan_sdhci_bind,
|
||||
.probe = k3_arasan_sdhci_probe,
|
||||
.priv_auto_alloc_size = sizeof(struct sdhci_host),
|
||||
.platdata_auto_alloc_size = sizeof(struct k3_arasan_sdhci_plat),
|
||||
};
|
|
@ -8,6 +8,7 @@
|
|||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <dm.h>
|
||||
#include <errno.h>
|
||||
#include <malloc.h>
|
||||
#include <mmc.h>
|
||||
|
@ -409,7 +410,7 @@ static int sdhci_execute_tuning(struct udevice *dev, uint opcode)
|
|||
return 0;
|
||||
}
|
||||
#endif
|
||||
static int sdhci_set_clock(struct mmc *mmc, unsigned int clock)
|
||||
int sdhci_set_clock(struct mmc *mmc, unsigned int clock)
|
||||
{
|
||||
struct sdhci_host *host = mmc->priv;
|
||||
unsigned int div, clk = 0, timeout;
|
||||
|
@ -533,6 +534,34 @@ static void sdhci_set_power(struct sdhci_host *host, unsigned short power)
|
|||
sdhci_writeb(host, pwr, SDHCI_POWER_CONTROL);
|
||||
}
|
||||
|
||||
void sdhci_set_uhs_timing(struct sdhci_host *host)
|
||||
{
|
||||
struct mmc *mmc = (struct mmc *)host->mmc;
|
||||
u32 reg;
|
||||
|
||||
reg = sdhci_readw(host, SDHCI_HOST_CONTROL2);
|
||||
reg &= ~SDHCI_CTRL_UHS_MASK;
|
||||
|
||||
switch (mmc->selected_mode) {
|
||||
case UHS_SDR50:
|
||||
case MMC_HS_52:
|
||||
reg |= SDHCI_CTRL_UHS_SDR50;
|
||||
break;
|
||||
case UHS_DDR50:
|
||||
case MMC_DDR_52:
|
||||
reg |= SDHCI_CTRL_UHS_DDR50;
|
||||
break;
|
||||
case UHS_SDR104:
|
||||
case MMC_HS_200:
|
||||
reg |= SDHCI_CTRL_UHS_SDR104;
|
||||
break;
|
||||
default:
|
||||
reg |= SDHCI_CTRL_UHS_SDR12;
|
||||
}
|
||||
|
||||
sdhci_writew(host, reg, SDHCI_HOST_CONTROL2);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_DM_MMC
|
||||
static int sdhci_set_ios(struct udevice *dev)
|
||||
{
|
||||
|
@ -583,7 +612,7 @@ static int sdhci_set_ios(struct mmc *mmc)
|
|||
|
||||
/* If available, call the driver specific "post" set_ios() function */
|
||||
if (host->ops && host->ops->set_ios_post)
|
||||
host->ops->set_ios_post(host);
|
||||
return host->ops->set_ios_post(host);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -681,8 +710,18 @@ int sdhci_setup_cfg(struct mmc_config *cfg, struct sdhci_host *host,
|
|||
u32 f_max, u32 f_min)
|
||||
{
|
||||
u32 caps, caps_1 = 0;
|
||||
#if CONFIG_IS_ENABLED(DM_MMC)
|
||||
u32 mask[2] = {0};
|
||||
int ret;
|
||||
ret = dev_read_u32_array(host->mmc->dev, "sdhci-caps-mask",
|
||||
mask, 2);
|
||||
if (ret && ret != -1)
|
||||
return ret;
|
||||
|
||||
caps = ~mask[1] & sdhci_readl(host, SDHCI_CAPABILITIES);
|
||||
#else
|
||||
caps = sdhci_readl(host, SDHCI_CAPABILITIES);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_MMC_SDHCI_SDMA
|
||||
if (!(caps & SDHCI_CAN_DO_SDMA)) {
|
||||
|
@ -722,7 +761,11 @@ int sdhci_setup_cfg(struct mmc_config *cfg, struct sdhci_host *host,
|
|||
|
||||
/* Check whether the clock multiplier is supported or not */
|
||||
if (SDHCI_GET_VERSION(host) >= SDHCI_SPEC_300) {
|
||||
#if CONFIG_IS_ENABLED(DM_MMC)
|
||||
caps_1 = ~mask[0] & sdhci_readl(host, SDHCI_CAPABILITIES_1);
|
||||
#else
|
||||
caps_1 = sdhci_readl(host, SDHCI_CAPABILITIES_1);
|
||||
#endif
|
||||
host->clk_mul = (caps_1 & SDHCI_CLOCK_MUL_MASK) >>
|
||||
SDHCI_CLOCK_MUL_SHIFT;
|
||||
}
|
||||
|
@ -779,9 +822,6 @@ int sdhci_setup_cfg(struct mmc_config *cfg, struct sdhci_host *host,
|
|||
cfg->host_caps &= ~MMC_MODE_HS_52MHz;
|
||||
}
|
||||
|
||||
if (SDHCI_GET_VERSION(host) >= SDHCI_SPEC_300)
|
||||
caps_1 = sdhci_readl(host, SDHCI_CAPABILITIES_1);
|
||||
|
||||
if (!(cfg->voltages & MMC_VDD_165_195) ||
|
||||
(host->quirks & SDHCI_QUIRK_NO_1_8_V))
|
||||
caps_1 &= ~(SDHCI_SUPPORT_SDR104 | SDHCI_SUPPORT_SDR50 |
|
||||
|
|
|
@ -326,7 +326,7 @@ static void xenon_mask_cmd_conflict_err(struct sdhci_host *host)
|
|||
}
|
||||
|
||||
/* Platform specific function for post set_ios configuration */
|
||||
static void xenon_sdhci_set_ios_post(struct sdhci_host *host)
|
||||
static int xenon_sdhci_set_ios_post(struct sdhci_host *host)
|
||||
{
|
||||
struct xenon_sdhci_priv *priv = host->mmc->priv;
|
||||
uint speed = host->mmc->tran_speed;
|
||||
|
@ -364,6 +364,8 @@ static void xenon_sdhci_set_ios_post(struct sdhci_host *host)
|
|||
|
||||
/* Re-init the PHY */
|
||||
xenon_mmc_phy_set(host);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Install a driver specific handler for post set_ios configuration */
|
||||
|
|
|
@ -48,11 +48,6 @@ static const u8 mode2timing[] = {
|
|||
[MMC_HS_200] = MMC_HS200_BUS_SPEED,
|
||||
};
|
||||
|
||||
#define SDHCI_HOST_CTRL2 0x3E
|
||||
#define SDHCI_CTRL2_MODE_MASK 0x7
|
||||
#define SDHCI_18V_SIGNAL 0x8
|
||||
#define SDHCI_CTRL_EXEC_TUNING 0x0040
|
||||
#define SDHCI_CTRL_TUNED_CLK 0x80
|
||||
#define SDHCI_TUNING_LOOP_COUNT 40
|
||||
|
||||
static void arasan_zynqmp_dll_reset(struct sdhci_host *host, u8 deviceid)
|
||||
|
@ -99,9 +94,9 @@ static int arasan_sdhci_execute_tuning(struct mmc *mmc, u8 opcode)
|
|||
host = priv->host;
|
||||
deviceid = priv->deviceid;
|
||||
|
||||
ctrl = sdhci_readw(host, SDHCI_HOST_CTRL2);
|
||||
ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2);
|
||||
ctrl |= SDHCI_CTRL_EXEC_TUNING;
|
||||
sdhci_writew(host, ctrl, SDHCI_HOST_CTRL2);
|
||||
sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2);
|
||||
|
||||
mdelay(1);
|
||||
|
||||
|
@ -133,7 +128,7 @@ static int arasan_sdhci_execute_tuning(struct mmc *mmc, u8 opcode)
|
|||
sdhci_writew(host, SDHCI_TRNS_READ, SDHCI_TRANSFER_MODE);
|
||||
|
||||
mmc_send_cmd(mmc, &cmd, NULL);
|
||||
ctrl = sdhci_readw(host, SDHCI_HOST_CTRL2);
|
||||
ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2);
|
||||
|
||||
if (cmd.cmdidx == MMC_CMD_SEND_TUNING_BLOCK)
|
||||
udelay(1);
|
||||
|
@ -142,7 +137,7 @@ static int arasan_sdhci_execute_tuning(struct mmc *mmc, u8 opcode)
|
|||
|
||||
if (tuning_loop_counter < 0) {
|
||||
ctrl &= ~SDHCI_CTRL_TUNED_CLK;
|
||||
sdhci_writel(host, ctrl, SDHCI_HOST_CTRL2);
|
||||
sdhci_writel(host, ctrl, SDHCI_HOST_CONTROL2);
|
||||
}
|
||||
|
||||
if (!(ctrl & SDHCI_CTRL_TUNED_CLK)) {
|
||||
|
@ -184,36 +179,14 @@ static void arasan_sdhci_set_control_reg(struct sdhci_host *host)
|
|||
return;
|
||||
|
||||
if (mmc->signal_voltage == MMC_SIGNAL_VOLTAGE_180) {
|
||||
reg = sdhci_readw(host, SDHCI_HOST_CTRL2);
|
||||
reg |= SDHCI_18V_SIGNAL;
|
||||
sdhci_writew(host, reg, SDHCI_HOST_CTRL2);
|
||||
reg = sdhci_readw(host, SDHCI_HOST_CONTROL2);
|
||||
reg |= SDHCI_CTRL_VDD_180;
|
||||
sdhci_writew(host, reg, SDHCI_HOST_CONTROL2);
|
||||
}
|
||||
|
||||
if (mmc->selected_mode > SD_HS &&
|
||||
mmc->selected_mode <= UHS_DDR50) {
|
||||
reg = sdhci_readw(host, SDHCI_HOST_CTRL2);
|
||||
reg &= ~SDHCI_CTRL2_MODE_MASK;
|
||||
switch (mmc->selected_mode) {
|
||||
case UHS_SDR12:
|
||||
reg |= UHS_SDR12_BUS_SPEED;
|
||||
break;
|
||||
case UHS_SDR25:
|
||||
reg |= UHS_SDR25_BUS_SPEED;
|
||||
break;
|
||||
case UHS_SDR50:
|
||||
reg |= UHS_SDR50_BUS_SPEED;
|
||||
break;
|
||||
case UHS_SDR104:
|
||||
reg |= UHS_SDR104_BUS_SPEED;
|
||||
break;
|
||||
case UHS_DDR50:
|
||||
reg |= UHS_DDR50_BUS_SPEED;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
sdhci_writew(host, reg, SDHCI_HOST_CTRL2);
|
||||
}
|
||||
mmc->selected_mode <= UHS_DDR50)
|
||||
sdhci_set_uhs_timing(host);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
@ -19,6 +19,32 @@
|
|||
#define CONFIG_SYS_SDRAM_BASE1 0x880000000
|
||||
|
||||
/* SPL Loader Configuration */
|
||||
#ifdef CONFIG_TARGET_AM654_A53_EVM
|
||||
#define CONFIG_SYS_INIT_SP_ADDR (CONFIG_SPL_TEXT_BASE + \
|
||||
CONFIG_SYS_K3_NON_SECURE_MSRAM_SIZE)
|
||||
#else
|
||||
/*
|
||||
* Maximum size in memory allocated to the SPL BSS. Keep it as tight as
|
||||
* possible (to allow the build to go through), as this directly affects
|
||||
* our memory footprint. The less we use for BSS the more we have available
|
||||
* for everything else.
|
||||
*/
|
||||
#define CONFIG_SPL_BSS_MAX_SIZE 0x5000
|
||||
/*
|
||||
* Link BSS to be within SPL in a dedicated region located near the top of
|
||||
* the MCU SRAM, this way making it available also before relocation. Note
|
||||
* that we are not using the actual top of the MCU SRAM as there is a memory
|
||||
* location filled in by the boot ROM that we want to read out without any
|
||||
* interference from the C context.
|
||||
*/
|
||||
#define CONFIG_SPL_BSS_START_ADDR (CONFIG_SYS_K3_BOOT_PARAM_TABLE_INDEX -\
|
||||
CONFIG_SPL_BSS_MAX_SIZE)
|
||||
/* Set the stack right below the SPL BSS section */
|
||||
#define CONFIG_SYS_INIT_SP_ADDR CONFIG_SPL_BSS_START_ADDR
|
||||
/* Configure R5 SPL post-relocation malloc pool in DDR */
|
||||
#define CONFIG_SYS_SPL_MALLOC_START 0x84000000
|
||||
#define CONFIG_SYS_SPL_MALLOC_SIZE SZ_16M
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SYS_K3_SPL_ATF
|
||||
#define CONFIG_SPL_FS_LOAD_PAYLOAD_NAME "tispl.bin"
|
||||
|
@ -29,26 +55,26 @@
|
|||
#endif
|
||||
|
||||
#define CONFIG_SPL_MAX_SIZE CONFIG_SYS_K3_MAX_DOWNLODABLE_IMAGE_SIZE
|
||||
#define CONFIG_SYS_INIT_SP_ADDR (CONFIG_SPL_TEXT_BASE + \
|
||||
CONFIG_SYS_K3_NON_SECURE_MSRAM_SIZE - 4)
|
||||
|
||||
#define CONFIG_SYS_BOOTM_LEN SZ_64M
|
||||
|
||||
#define PARTS_DEFAULT \
|
||||
/* Linux partitions */ \
|
||||
"name=rootfs,start=0,size=-,uuid=${uuid_gpt_rootfs}\0"
|
||||
|
||||
/* U-Boot general configuration */
|
||||
#define EXTRA_ENV_AM65X_BOARD_SETTINGS \
|
||||
"findfdt=" \
|
||||
"if test $board_name = am65x; then " \
|
||||
"setenv name_fdt k3-am654-base-board.dtb; " \
|
||||
"else if test $name_fdt = undefined; then " \
|
||||
"echo WARNING: Could not determine device tree to use;"\
|
||||
"fi; fi; " \
|
||||
"setenv fdtfile ${name_fdt}\0" \
|
||||
"setenv name_fdt k3-am654-base-board.dtb;" \
|
||||
"setenv fdtfile ${name_fdt};" \
|
||||
"setenv overlay_files ${name_overlays}\0" \
|
||||
"loadaddr=0x80080000\0" \
|
||||
"fdtaddr=0x82000000\0" \
|
||||
"overlayaddr=0x83000000\0" \
|
||||
"name_kern=Image\0" \
|
||||
"console=ttyS2,115200n8\0" \
|
||||
"args_all=setenv optargs earlycon=ns16550a,mmio32,0x02800000\0" \
|
||||
"run_kern=booti ${loadaddr} ${rd_spec} ${fdtaddr}\0"
|
||||
"run_kern=booti ${loadaddr} ${rd_spec} ${fdtaddr}\0" \
|
||||
|
||||
/* U-Boot MMC-specific configuration */
|
||||
#define EXTRA_ENV_AM65X_BOARD_SETTINGS_MMC \
|
||||
|
@ -59,8 +85,17 @@
|
|||
"rd_spec=-\0" \
|
||||
"init_mmc=run args_all args_mmc\0" \
|
||||
"get_fdt_mmc=load mmc ${bootpart} ${fdtaddr} ${bootdir}/${name_fdt}\0" \
|
||||
"get_overlay_mmc=" \
|
||||
"fdt address ${fdtaddr};" \
|
||||
"fdt resize 0x100000;" \
|
||||
"for overlay in $overlay_files;" \
|
||||
"do;" \
|
||||
"load mmc ${bootpart} ${overlayaddr} ${bootdir}/${overlay};" \
|
||||
"fdt apply ${overlayaddr};" \
|
||||
"done;\0" \
|
||||
"get_kern_mmc=load mmc ${bootpart} ${loadaddr} " \
|
||||
"${bootdir}/${name_kern}\0"
|
||||
"${bootdir}/${name_kern}\0" \
|
||||
"partitions=" PARTS_DEFAULT
|
||||
|
||||
/* Incorporate settings into the U-Boot environment */
|
||||
#define CONFIG_EXTRA_ENV_SETTINGS \
|
||||
|
@ -68,6 +103,18 @@
|
|||
EXTRA_ENV_AM65X_BOARD_SETTINGS \
|
||||
EXTRA_ENV_AM65X_BOARD_SETTINGS_MMC
|
||||
|
||||
/* MMC ENV related defines */
|
||||
#ifdef CONFIG_ENV_IS_IN_MMC
|
||||
#define CONFIG_SYS_MMC_ENV_DEV 0
|
||||
#define CONFIG_SYS_MMC_ENV_PART 1
|
||||
#define CONFIG_ENV_SIZE (128 << 10)
|
||||
#define CONFIG_ENV_OFFSET 0x680000
|
||||
#define CONFIG_ENV_OFFSET_REDUND (CONFIG_ENV_OFFSET + CONFIG_ENV_SIZE)
|
||||
#define CONFIG_SYS_REDUNDAND_ENVIRONMENT
|
||||
#endif
|
||||
|
||||
#define CONFIG_SUPPORT_EMMC_BOOT
|
||||
|
||||
/* Now for the remaining common defines */
|
||||
#include <configs/ti_armv7_common.h>
|
||||
|
||||
|
|
|
@ -330,6 +330,8 @@ int regmap_init_mem(ofnode node, struct regmap **mapp);
|
|||
int regmap_init_mem_platdata(struct udevice *dev, fdt_val_t *reg, int count,
|
||||
struct regmap **mapp);
|
||||
|
||||
int regmap_init_mem_index(ofnode node, struct regmap **mapp, int index);
|
||||
|
||||
/**
|
||||
* regmap_get_range() - Obtain the base memory address of a regmap range
|
||||
*
|
||||
|
|
|
@ -144,7 +144,23 @@
|
|||
|
||||
#define SDHCI_ACMD12_ERR 0x3C
|
||||
|
||||
/* 3E-3F reserved */
|
||||
#define SDHCI_HOST_CONTROL2 0x3E
|
||||
#define SDHCI_CTRL_UHS_MASK 0x0007
|
||||
#define SDHCI_CTRL_UHS_SDR12 0x0000
|
||||
#define SDHCI_CTRL_UHS_SDR25 0x0001
|
||||
#define SDHCI_CTRL_UHS_SDR50 0x0002
|
||||
#define SDHCI_CTRL_UHS_SDR104 0x0003
|
||||
#define SDHCI_CTRL_UHS_DDR50 0x0004
|
||||
#define SDHCI_CTRL_HS400 0x0005 /* Non-standard */
|
||||
#define SDHCI_CTRL_VDD_180 0x0008
|
||||
#define SDHCI_CTRL_DRV_TYPE_MASK 0x0030
|
||||
#define SDHCI_CTRL_DRV_TYPE_B 0x0000
|
||||
#define SDHCI_CTRL_DRV_TYPE_A 0x0010
|
||||
#define SDHCI_CTRL_DRV_TYPE_C 0x0020
|
||||
#define SDHCI_CTRL_DRV_TYPE_D 0x0030
|
||||
#define SDHCI_CTRL_EXEC_TUNING 0x0040
|
||||
#define SDHCI_CTRL_TUNED_CLK 0x0080
|
||||
#define SDHCI_CTRL_PRESET_VAL_ENABLE 0x8000
|
||||
|
||||
#define SDHCI_CAPABILITIES 0x40
|
||||
#define SDHCI_TIMEOUT_CLK_MASK 0x0000003F
|
||||
|
@ -247,7 +263,7 @@ struct sdhci_ops {
|
|||
#endif
|
||||
int (*get_cd)(struct sdhci_host *host);
|
||||
void (*set_control_reg)(struct sdhci_host *host);
|
||||
void (*set_ios_post)(struct sdhci_host *host);
|
||||
int (*set_ios_post)(struct sdhci_host *host);
|
||||
void (*set_clock)(struct sdhci_host *host, u32 div);
|
||||
int (*platform_execute_tuning)(struct mmc *host, u8 opcode);
|
||||
void (*set_delay)(struct sdhci_host *host);
|
||||
|
@ -467,9 +483,11 @@ int sdhci_bind(struct udevice *dev, struct mmc *mmc, struct mmc_config *cfg);
|
|||
int add_sdhci(struct sdhci_host *host, u32 f_max, u32 f_min);
|
||||
#endif /* !CONFIG_BLK */
|
||||
|
||||
void sdhci_set_uhs_timing(struct sdhci_host *host);
|
||||
#ifdef CONFIG_DM_MMC
|
||||
/* Export the operations to drivers */
|
||||
int sdhci_probe(struct udevice *dev);
|
||||
int sdhci_set_clock(struct mmc *mmc, unsigned int clock);
|
||||
extern const struct dm_mmc_ops sdhci_ops;
|
||||
#else
|
||||
#endif
|
||||
|
|
|
@ -108,6 +108,15 @@ struct spl_load_info {
|
|||
*/
|
||||
binman_sym_extern(ulong, u_boot_any, image_pos);
|
||||
|
||||
/**
|
||||
* spl_load_simple_fit_skip_processing() - Hook to allow skipping the FIT
|
||||
* image processing during spl_load_simple_fit().
|
||||
*
|
||||
* Return true to skip FIT processing, false to preserve the full code flow
|
||||
* of spl_load_simple_fit().
|
||||
*/
|
||||
bool spl_load_simple_fit_skip_processing(void);
|
||||
|
||||
/**
|
||||
* spl_load_simple_fit() - Loads a fit image from a device.
|
||||
* @spl_image: Image description to set up
|
||||
|
@ -330,6 +339,23 @@ int spl_dfu_cmd(int usbctrl, char *dfu_alt_info, char *interface, char *devstr);
|
|||
int spl_mmc_load_image(struct spl_image_info *spl_image,
|
||||
struct spl_boot_device *bootdev);
|
||||
|
||||
/**
|
||||
* spl_mmc_load() - Load an image file from MMC/SD media
|
||||
*
|
||||
* @param spl_image Image data filled in by loading process
|
||||
* @param bootdev Describes which device to load from
|
||||
* @param filename Name of file to load (in FS mode)
|
||||
* @param raw_part Partition to load from (in RAW mode)
|
||||
* @param raw_sect Sector to load from (in RAW mode)
|
||||
*
|
||||
* @return 0 on success, otherwise error code
|
||||
*/
|
||||
int spl_mmc_load(struct spl_image_info *spl_image,
|
||||
struct spl_boot_device *bootdev,
|
||||
const char *filename,
|
||||
int raw_part,
|
||||
unsigned long raw_sect);
|
||||
|
||||
/**
|
||||
* spl_invoke_atf - boot using an ARM trusted firmware image
|
||||
*/
|
||||
|
|
Loading…
Reference in New Issue
Block a user