mirror of https://github.com/wolfSSL/wolfBoot.git
Add LS1028A eSDHC SD card disk boot support
parent
8eafe1ef76
commit
a8c8c19fe8
|
|
@ -274,6 +274,14 @@ jobs:
|
||||||
config-file: ./config/examples/nxp-ls1028a-tpm.config
|
config-file: ./config/examples/nxp-ls1028a-tpm.config
|
||||||
make-args: CROSS_COMPILE=aarch64-linux-gnu-
|
make-args: CROSS_COMPILE=aarch64-linux-gnu-
|
||||||
|
|
||||||
|
# SD card disk boot via the Freescale eSDHC driver (hal/nxp_esdhc.o)
|
||||||
|
nxp_ls1028a_sdcard_test:
|
||||||
|
uses: ./.github/workflows/test-build.yml
|
||||||
|
with:
|
||||||
|
arch: aarch64
|
||||||
|
config-file: ./config/examples/nxp-ls1028a-sdcard.config
|
||||||
|
make-args: CROSS_COMPILE=aarch64-linux-gnu-
|
||||||
|
|
||||||
nxp_mcxa_test:
|
nxp_mcxa_test:
|
||||||
uses: ./.github/workflows/test-build-mcux-sdk-manifests.yml
|
uses: ./.github/workflows/test-build-mcux-sdk-manifests.yml
|
||||||
with:
|
with:
|
||||||
|
|
|
||||||
20
arch.mk
20
arch.mk
|
|
@ -181,6 +181,18 @@ ifeq ($(ARCH),AARCH64)
|
||||||
CFLAGS+=-fno-builtin-printf
|
CFLAGS+=-fno-builtin-printf
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
# SD card disk boot uses the Freescale eSDHC driver, not the Cadence
|
||||||
|
# SDHCI one (the shared AARCH64 block below wires update_disk.o).
|
||||||
|
# hal/nxp_esdhc.c is SD card only, so DISK_EMMC has no driver here:
|
||||||
|
# reject it rather than silently link the wrong controller driver.
|
||||||
|
ifeq ($(DISK_EMMC),1)
|
||||||
|
$(error DISK_EMMC is not supported on nxp_ls1028a (hal/nxp_esdhc.c is SD card only))
|
||||||
|
endif
|
||||||
|
ifeq ($(DISK_SDCARD),1)
|
||||||
|
override DISK_DRIVER=esdhc
|
||||||
|
OBJS+=hal/nxp_esdhc.o
|
||||||
|
endif
|
||||||
|
|
||||||
SPI_TARGET=nxp
|
SPI_TARGET=nxp
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
|
@ -1598,10 +1610,16 @@ ifneq ($(filter nxp_t1024 nxp_t1040,$(TARGET)),)
|
||||||
# Disk boot from SD card (eSDHC controller, driver hal/nxp_esdhc.c).
|
# Disk boot from SD card (eSDHC controller, driver hal/nxp_esdhc.c).
|
||||||
# src/gpt.o is already linked for all PPC targets above. The driver is
|
# src/gpt.o is already linked for all PPC targets above. The driver is
|
||||||
# kept out of the size-constrained stage1 loader.
|
# kept out of the size-constrained stage1 loader.
|
||||||
ifneq ($(filter 1,$(DISK_SDCARD) $(DISK_EMMC)),)
|
# hal/nxp_esdhc.c drives SD cards only: it has no eMMC (CMD1/EXT_CSD)
|
||||||
|
# initialization, so DISK_EMMC has no driver on this arch.
|
||||||
|
ifeq ($(DISK_EMMC),1)
|
||||||
|
$(error DISK_EMMC is not supported on PPC (hal/nxp_esdhc.c is SD card only))
|
||||||
|
endif
|
||||||
|
ifeq ($(DISK_SDCARD),1)
|
||||||
CFLAGS+=-D"WOLFBOOT_UPDATE_DISK" -D"MAX_DISKS=1"
|
CFLAGS+=-D"WOLFBOOT_UPDATE_DISK" -D"MAX_DISKS=1"
|
||||||
UPDATE_OBJS:=src/update_disk.o
|
UPDATE_OBJS:=src/update_disk.o
|
||||||
OBJS+=src/disk.o
|
OBJS+=src/disk.o
|
||||||
|
override DISK_DRIVER=esdhc
|
||||||
ifneq ($(STAGE1),1)
|
ifneq ($(STAGE1),1)
|
||||||
OBJS+=hal/nxp_esdhc.o
|
OBJS+=hal/nxp_esdhc.o
|
||||||
endif
|
endif
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,88 @@
|
||||||
|
# NXP LS1028A with SD card disk boot
|
||||||
|
#
|
||||||
|
# Same as nxp-ls1028a.config, but the signed application image is loaded
|
||||||
|
# from the SD card slot (eSDHC1 at 0x02140000) instead of XSPI NOR. The
|
||||||
|
# card is GPT (or MBR) partitioned; the signed image sits at offset 0 of
|
||||||
|
# the first two partitions (BOOT_PART_A / BOOT_PART_B, 0-based indexes
|
||||||
|
# into the partition table - same card layout as the T1040 eSDHC target).
|
||||||
|
# wolfBoot picks the slot with the higher version, verifies it and boots
|
||||||
|
# it from DDR (src/update_disk.c).
|
||||||
|
|
||||||
|
ARCH=AARCH64
|
||||||
|
TARGET=nxp_ls1028a
|
||||||
|
SIGN?=ECC256
|
||||||
|
HASH?=SHA256
|
||||||
|
DEBUG?=0
|
||||||
|
DEBUG_UART?=1
|
||||||
|
VTOR?=0
|
||||||
|
CORTEX_M0?=0
|
||||||
|
NO_ASM?=0
|
||||||
|
EXT_FLASH?=1
|
||||||
|
SPI_FLASH?=0
|
||||||
|
## Force app to be copied into ram
|
||||||
|
NO_XIP?=1
|
||||||
|
UART_FLASH?=0
|
||||||
|
ALLOW_DOWNGRADE?=0
|
||||||
|
NVM_FLASH_WRITEONCE?=0
|
||||||
|
WOLFBOOT_VERSION?=0
|
||||||
|
V?=0
|
||||||
|
NO_MPU?=0
|
||||||
|
SPMATH?=1
|
||||||
|
RAM_CODE?=0
|
||||||
|
DUALBANK_SWAP?=0
|
||||||
|
PKA?=0
|
||||||
|
ELF?=1
|
||||||
|
|
||||||
|
# SD card disk boot (Freescale eSDHC driver, hal/nxp_esdhc.c)
|
||||||
|
DISK_SDCARD=1
|
||||||
|
# Upper bound for the unauthenticated image size read from disk
|
||||||
|
WOLFBOOT_RAMBOOT_MAX_SIZE?=0x1000000
|
||||||
|
# Boot slots: partition table indexes (0-based) and read chunk size
|
||||||
|
CFLAGS_EXTRA+=-DBOOT_PART_A=0 -DBOOT_PART_B=1
|
||||||
|
CFLAGS_EXTRA+=-DDISK_BLOCK_SIZE=0x8000
|
||||||
|
# do_boot keeps the MMU and caches on (ENETC coherency) and cleans from the
|
||||||
|
# entry point before the jump. Pin the clean length to the RAMBOOT window so
|
||||||
|
# it covers the area images are loaded into regardless of what
|
||||||
|
# WOLFBOOT_PARTITION_SIZE is set to. Note this cleans one span from the
|
||||||
|
# entry point: an ELF or FIT payload that relocates a segment outside this
|
||||||
|
# window would need its own cache maintenance.
|
||||||
|
CFLAGS_EXTRA+=-DWOLFBOOT_MMU_FLUSH_APP_SIZE=0x1000000
|
||||||
|
# eSDHC bring-up trace on the DUART console
|
||||||
|
#CFLAGS_EXTRA+=-DDEBUG_ESDHC
|
||||||
|
|
||||||
|
# NOR Base Address
|
||||||
|
ARCH_FLASH_OFFSET?=0x20000000
|
||||||
|
|
||||||
|
# Flash Sector Size (128 KB)
|
||||||
|
WOLFBOOT_SECTOR_SIZE=0x20000
|
||||||
|
|
||||||
|
# wolfBoot start address
|
||||||
|
WOLFBOOT_ORIGIN=0x20020000
|
||||||
|
|
||||||
|
# wolfBoot partition size
|
||||||
|
BOOTLOADER_PARTITION_SIZE=0x20000
|
||||||
|
|
||||||
|
# Application Partition size. Matches the 16MB SD card slots; the sign
|
||||||
|
# tool bounds the image against this even though disk boot does not use
|
||||||
|
# the NOR partitions.
|
||||||
|
WOLFBOOT_PARTITION_SIZE?=0x1000000
|
||||||
|
|
||||||
|
# Location in Flash for Application Partition (unused for disk boot,
|
||||||
|
# kept for target.h consistency)
|
||||||
|
WOLFBOOT_PARTITION_BOOT_ADDRESS?=0x20100000
|
||||||
|
|
||||||
|
# Load the image to DDR, not the default OCRAM: OCRAM also holds
|
||||||
|
# wolfBoot's own .data/.bss/.stack and cannot hold a disk-sized image.
|
||||||
|
WOLFBOOT_LOAD_ADDRESS?=0x80100000
|
||||||
|
|
||||||
|
# Location in Flash for Update Partition
|
||||||
|
WOLFBOOT_PARTITION_UPDATE_ADDRESS?=0x21100000
|
||||||
|
|
||||||
|
# Location of temporary sector used during updates
|
||||||
|
WOLFBOOT_PARTITION_SWAP_ADDRESS?=0x22100000
|
||||||
|
|
||||||
|
# DTS (Device Tree). The load address must sit above
|
||||||
|
# WOLFBOOT_LOAD_ADDRESS + WOLFBOOT_RAMBOOT_MAX_SIZE.
|
||||||
|
WOLFBOOT_LOAD_DTS_ADDRESS?=0x82000000
|
||||||
|
WOLFBOOT_DTS_BOOT_ADDRESS?=0x20F00000
|
||||||
|
WOLFBOOT_DTS_UPDATE_ADDRESS?=0x20F00000
|
||||||
|
|
@ -3698,6 +3698,11 @@ The LS1028A is a AARCH64 armv8-a Cortex-A72 processor. Support has been tested w
|
||||||
Example configurations for this target are provided in:
|
Example configurations for this target are provided in:
|
||||||
* NXP LS1028A: [/config/examples/nxp-ls1028a.config](/config/examples/nxp-ls1028a.config).
|
* NXP LS1028A: [/config/examples/nxp-ls1028a.config](/config/examples/nxp-ls1028a.config).
|
||||||
* NXP LS1028A with TPM: [/config/examples/nxp-ls1028a-tpm.config](/config/examples/nxp-ls1028a-tpm.config).
|
* NXP LS1028A with TPM: [/config/examples/nxp-ls1028a-tpm.config](/config/examples/nxp-ls1028a-tpm.config).
|
||||||
|
* NXP LS1028A with SD card boot: [/config/examples/nxp-ls1028a-sdcard.config](/config/examples/nxp-ls1028a-sdcard.config).
|
||||||
|
|
||||||
|
### LS1028A SD Card Boot (eSDHC)
|
||||||
|
|
||||||
|
The LS1028A can load the signed application image from the SD card slot (eSDHC1) using the same Freescale eSDHC driver as the T1040 (`hal/nxp_esdhc.c`, built as its own object). The card layout is identical to the T1040 SD target: GPT (or MBR) partitioned, with the signed image at offset 0 of the first two partitions (`BOOT_PART_A`/`BOOT_PART_B`, 0-based). wolfBoot reads both headers, picks the higher version, loads it to DDR (`WOLFBOOT_LOAD_ADDRESS=0x80100000`), verifies the signature and boots it. The driver reprograms the eSDHC source clock (HWA2) at init, because the NOR-boot RCW leaves it on a source too fast for card identification. Define `DEBUG_ESDHC` (see the config) for controller bring-up trace on the DUART console. Validated on the LS1028ARDB booting a signed image from SD.
|
||||||
|
|
||||||
### Building wolfBoot for NXP LS1028A
|
### Building wolfBoot for NXP LS1028A
|
||||||
|
|
||||||
|
|
|
||||||
131
hal/nxp_esdhc.c
131
hal/nxp_esdhc.c
|
|
@ -19,7 +19,8 @@
|
||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* Freescale/NXP eSDHC block driver for QorIQ (T1040, T1024, T2080).
|
/* Freescale/NXP eSDHC block driver for QorIQ PPC (T1040, T1024, T2080)
|
||||||
|
* and Layerscape (LS1028A).
|
||||||
*
|
*
|
||||||
* Provides the four entry points src/disk.c expects (disk_init, disk_read,
|
* Provides the four entry points src/disk.c expects (disk_init, disk_read,
|
||||||
* disk_write, disk_close) so the disk boot path, and therefore DISK_FS, can
|
* disk_write, disk_close) so the disk boot path, and therefore DISK_FS, can
|
||||||
|
|
@ -30,9 +31,9 @@
|
||||||
* one XFERTYP register, combines block size and count into BLKATTR, and has
|
* one XFERTYP register, combines block size and count into BLKATTR, and has
|
||||||
* a watermark register with no standard-SDHCI equivalent.
|
* a watermark register with no standard-SDHCI equivalent.
|
||||||
*
|
*
|
||||||
* Compiled as its own object (arch.mk adds hal/nxp_esdhc.o when
|
* Compiled as its own object (the target's arch.mk block adds
|
||||||
* DISK_SDCARD or DISK_EMMC is set); the clock helpers it needs are
|
* hal/nxp_esdhc.o and sets DISK_DRIVER=esdhc when DISK_SDCARD is set);
|
||||||
* exported by nxp_ppc.h.
|
* per-target base address, clocks and byte order are selected below.
|
||||||
*
|
*
|
||||||
* Transfers use PIO through DATPORT rather than DMA. On e5500 with the MMU
|
* Transfers use PIO through DATPORT rather than DMA. On e5500 with the MMU
|
||||||
* enabled a DMA descriptor would need cache maintenance on the destination,
|
* enabled a DMA descriptor would need cache maintenance on the destination,
|
||||||
|
|
@ -47,7 +48,38 @@
|
||||||
|
|
||||||
#include "disk.h"
|
#include "disk.h"
|
||||||
#include "printf.h"
|
#include "printf.h"
|
||||||
|
|
||||||
|
/* Per-target selection. The eSDHC block is the same IP on big-endian QorIQ
|
||||||
|
* PPC and little-endian Layerscape; the register file follows the
|
||||||
|
* integration, so a native 32-bit access reads it correctly on both. Only
|
||||||
|
* the base address, source clock and DATPORT byte order move per target. */
|
||||||
|
#if defined(TARGET_nxp_ls1028a)
|
||||||
|
|
||||||
|
#include "nxp_ls1028a.h"
|
||||||
|
/* eSDHC1 is the SD card slot; eSDHC2 is eMMC, not supported by this driver. */
|
||||||
|
#define ESDHC_CTRL_BASE ESDHC_BASE(0)
|
||||||
|
#define ESDHC_EMODE_SEL ESDHC_PROCTL_EMODE_LE
|
||||||
|
#ifndef ESDHC_REF_CLK
|
||||||
|
#define ESDHC_REF_CLK 400000000UL
|
||||||
|
#endif
|
||||||
|
/* The block is clocked by hardware-accelerator mux HWA2 (the device tree
|
||||||
|
* binds mmc@2140000 to QORIQ_CLK_HWACCEL index 1). The NOR-boot RCW leaves
|
||||||
|
* it on CGA_PLL2 (1.2 GHz), which overruns the card during identification;
|
||||||
|
* CLKSEL=7 selects CGA_PLL1/3. Set at runtime so SD works whichever RCW
|
||||||
|
* booted us. hwaccel[idx] = clockgen + 0x20*idx + 0x10, eSDHC is idx 1. */
|
||||||
|
#define LS1028A_HWA2CSR (CGUCGA_BASE + 0x30)
|
||||||
|
#define HWA_CLKSEL_MASK 0x78000000U
|
||||||
|
#define HWA_CLKSEL_SHIFT 27
|
||||||
|
#define HWA_CLKSEL_ESDHC 7U
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
/* QorIQ PPC T-series: big-endian core and registers. */
|
||||||
#include "nxp_ppc.h"
|
#include "nxp_ppc.h"
|
||||||
|
#define ESDHC_CTRL_BASE (CCSRBAR + 0x114000)
|
||||||
|
#define ESDHC_EMODE_SEL ESDHC_PROCTL_EMODE_BE
|
||||||
|
|
||||||
|
#endif /* target selection */
|
||||||
|
|
||||||
#ifdef DEBUG_ESDHC
|
#ifdef DEBUG_ESDHC
|
||||||
#define ESDHC_DBG(_f_, ...) wolfBoot_printf(_f_, ##__VA_ARGS__)
|
#define ESDHC_DBG(_f_, ...) wolfBoot_printf(_f_, ##__VA_ARGS__)
|
||||||
|
|
@ -55,18 +87,7 @@
|
||||||
#define ESDHC_DBG(_f_, ...) do{}while(0)
|
#define ESDHC_DBG(_f_, ...) do{}while(0)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* ---------------------------------------------------------------------
|
#define ESDHC_REG(off) ((volatile uint32_t*)(ESDHC_CTRL_BASE + (off)))
|
||||||
* Register map. CCSRBAR comes from nxp_ppc.h for the selected target.
|
|
||||||
*
|
|
||||||
* The block presents its registers big-endian and the e5500 is big-endian,
|
|
||||||
* so a native 32-bit access reads them correctly with no swapping. The one
|
|
||||||
* exception is DATPORT, whose byte order is selected by PROCTL[EMODE] and is
|
|
||||||
* configured below.
|
|
||||||
* --------------------------------------------------------------------- */
|
|
||||||
#ifndef ESDHC_BASE
|
|
||||||
#define ESDHC_BASE (CCSRBAR + 0x114000)
|
|
||||||
#endif
|
|
||||||
#define ESDHC_REG(off) ((volatile uint32_t*)(ESDHC_BASE + (off)))
|
|
||||||
|
|
||||||
#define ESDHC_DSADDR 0x00
|
#define ESDHC_DSADDR 0x00
|
||||||
#define ESDHC_BLKATTR 0x04
|
#define ESDHC_BLKATTR 0x04
|
||||||
|
|
@ -117,11 +138,11 @@
|
||||||
#define ESDHC_PROCTL_DTW_1BIT (0U << 1)
|
#define ESDHC_PROCTL_DTW_1BIT (0U << 1)
|
||||||
#define ESDHC_PROCTL_DTW_4BIT (1U << 1)
|
#define ESDHC_PROCTL_DTW_4BIT (1U << 1)
|
||||||
#define ESDHC_PROCTL_DTW_MASK (3U << 1)
|
#define ESDHC_PROCTL_DTW_MASK (3U << 1)
|
||||||
/* EMODE selects the byte order of DATPORT. Big-endian mode delivers bytes
|
/* EMODE sets DATPORT byte order; ESDHC_EMODE_SEL picks the mode giving
|
||||||
* in media order when the word is stored natively by this big-endian core.
|
* media order for a native word store. Silicon-verified: BE on the T1040
|
||||||
* Verified on T1040D4RDB silicon: little-endian mode read every aligned
|
* (LE there returned every aligned 4-byte group reversed). */
|
||||||
* 4-byte group byte-reversed (MBR signature came back AA55). */
|
|
||||||
#define ESDHC_PROCTL_EMODE_BE (0U << 4)
|
#define ESDHC_PROCTL_EMODE_BE (0U << 4)
|
||||||
|
#define ESDHC_PROCTL_EMODE_LE (2U << 4)
|
||||||
#define ESDHC_PROCTL_EMODE_MASK (3U << 4)
|
#define ESDHC_PROCTL_EMODE_MASK (3U << 4)
|
||||||
|
|
||||||
/* SYSCTL */
|
/* SYSCTL */
|
||||||
|
|
@ -186,6 +207,27 @@ static int g_esdhc_ready;
|
||||||
* 37500000 Hz (600 MHz / 16).
|
* 37500000 Hz (600 MHz / 16).
|
||||||
* --------------------------------------------------------------------- */
|
* --------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
#if defined(TARGET_nxp_ls1028a)
|
||||||
|
|
||||||
|
/* ARM generic timer; hal_init() enables the system counter first. */
|
||||||
|
static uint64_t esdhc_timebase(void)
|
||||||
|
{
|
||||||
|
uint64_t cnt;
|
||||||
|
|
||||||
|
__asm__ __volatile__("isb; mrs %0, cntpct_el0" : "=r"(cnt));
|
||||||
|
return cnt;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint32_t esdhc_read_tb_hz(void)
|
||||||
|
{
|
||||||
|
uint64_t frq;
|
||||||
|
|
||||||
|
__asm__ __volatile__("mrs %0, cntfrq_el0" : "=r"(frq));
|
||||||
|
return (uint32_t)frq;
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
static uint64_t esdhc_timebase(void)
|
static uint64_t esdhc_timebase(void)
|
||||||
{
|
{
|
||||||
uint32_t hi, lo, hi2;
|
uint32_t hi, lo, hi2;
|
||||||
|
|
@ -201,6 +243,13 @@ static uint64_t esdhc_timebase(void)
|
||||||
return ((uint64_t)hi << 32) | (uint64_t)lo;
|
return ((uint64_t)hi << 32) | (uint64_t)lo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static uint32_t esdhc_read_tb_hz(void)
|
||||||
|
{
|
||||||
|
return TIMEBASE_HZ;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* target timebase */
|
||||||
|
|
||||||
/* Timebase frequency, cached by disk_init(). TIMEBASE_HZ reads clock
|
/* Timebase frequency, cached by disk_init(). TIMEBASE_HZ reads clock
|
||||||
* registers and divides on every use; the value cannot change at runtime,
|
* registers and divides on every use; the value cannot change at runtime,
|
||||||
* and disk_init() rejects a zero reading before any other driver path can
|
* and disk_init() rejects a zero reading before any other driver path can
|
||||||
|
|
@ -311,7 +360,11 @@ static int esdhc_send_cmd(uint32_t idx, uint32_t arg, uint32_t xfertyp,
|
||||||
/* Set the SD clock. The divider is SDCLKFS (base 2 prescaler) times DVS. */
|
/* Set the SD clock. The divider is SDCLKFS (base 2 prescaler) times DVS. */
|
||||||
static void esdhc_set_clock(uint32_t target_hz)
|
static void esdhc_set_clock(uint32_t target_hz)
|
||||||
{
|
{
|
||||||
|
#if defined(TARGET_nxp_ls1028a)
|
||||||
|
uint32_t base = ESDHC_REF_CLK;
|
||||||
|
#else
|
||||||
uint32_t base = hal_get_bus_clk();
|
uint32_t base = hal_get_bus_clk();
|
||||||
|
#endif
|
||||||
uint32_t pre = 2, div = 1, sysctl;
|
uint32_t pre = 2, div = 1, sysctl;
|
||||||
|
|
||||||
if (target_hz == 0U) {
|
if (target_hz == 0U) {
|
||||||
|
|
@ -341,8 +394,9 @@ static void esdhc_set_clock(uint32_t target_hz)
|
||||||
ESDHC_SYSCTL_SDCLKEN;
|
ESDHC_SYSCTL_SDCLKEN;
|
||||||
esdhc_udelay(100);
|
esdhc_udelay(100);
|
||||||
|
|
||||||
ESDHC_DBG("esdhc: clock %u Hz (pre %u, div %u)\r\n",
|
ESDHC_DBG("esdhc: clock %u Hz (pre %u, div %u) SYSCTL %x PROCTL %x\r\n",
|
||||||
(base / pre) / div, pre, div);
|
(base / pre) / div, pre, div,
|
||||||
|
*ESDHC_REG(ESDHC_SYSCTL), *ESDHC_REG(ESDHC_PROCTL));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -376,7 +430,7 @@ static int esdhc_host_init(void)
|
||||||
/* 1-bit bus for identification, and set the data-port byte order. */
|
/* 1-bit bus for identification, and set the data-port byte order. */
|
||||||
proctl = *ESDHC_REG(ESDHC_PROCTL);
|
proctl = *ESDHC_REG(ESDHC_PROCTL);
|
||||||
proctl &= ~(ESDHC_PROCTL_DTW_MASK | ESDHC_PROCTL_EMODE_MASK);
|
proctl &= ~(ESDHC_PROCTL_DTW_MASK | ESDHC_PROCTL_EMODE_MASK);
|
||||||
proctl |= ESDHC_PROCTL_DTW_1BIT | ESDHC_PROCTL_EMODE_BE;
|
proctl |= ESDHC_PROCTL_DTW_1BIT | ESDHC_EMODE_SEL;
|
||||||
*ESDHC_REG(ESDHC_PROCTL) = proctl;
|
*ESDHC_REG(ESDHC_PROCTL) = proctl;
|
||||||
|
|
||||||
esdhc_set_clock(400000U);
|
esdhc_set_clock(400000U);
|
||||||
|
|
@ -403,6 +457,7 @@ static int esdhc_send_acmd(uint32_t idx, uint32_t arg, uint32_t xfertyp,
|
||||||
ESDHC_XFERTYP_RSPTYP_48 | ESDHC_XFERTYP_CICEN | ESDHC_XFERTYP_CCCEN,
|
ESDHC_XFERTYP_RSPTYP_48 | ESDHC_XFERTYP_CICEN | ESDHC_XFERTYP_CCCEN,
|
||||||
NULL);
|
NULL);
|
||||||
if (ret != 0) {
|
if (ret != 0) {
|
||||||
|
ESDHC_DBG("esdhc: CMD55 (for ACMD%u) failed\r\n", idx);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
return esdhc_send_cmd(idx, arg, xfertyp, resp);
|
return esdhc_send_cmd(idx, arg, xfertyp, resp);
|
||||||
|
|
@ -442,8 +497,10 @@ static int esdhc_card_init(void)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
v2 = 1;
|
v2 = 1;
|
||||||
|
ESDHC_DBG("esdhc: CMD8 ok resp %x\r\n", resp[0]);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
ESDHC_DBG("esdhc: CMD8 no response (v1 or signalling)\r\n");
|
||||||
/* CMD8 leaves the command line in error state on a v1 card. */
|
/* CMD8 leaves the command line in error state on a v1 card. */
|
||||||
*ESDHC_REG(ESDHC_SYSCTL) = *ESDHC_REG(ESDHC_SYSCTL) |
|
*ESDHC_REG(ESDHC_SYSCTL) = *ESDHC_REG(ESDHC_SYSCTL) |
|
||||||
ESDHC_SYSCTL_RSTC;
|
ESDHC_SYSCTL_RSTC;
|
||||||
|
|
@ -529,10 +586,12 @@ static int esdhc_card_init(void)
|
||||||
|
|
||||||
/* Drain one block from the data port.
|
/* Drain one block from the data port.
|
||||||
*
|
*
|
||||||
* PROCTL[EMODE] is set to big-endian above, so a native 32-bit read of
|
* ESDHC_EMODE_SEL (set per target above) makes a native 32-bit read of
|
||||||
* DATPORT returns the four media bytes already in order and they can be
|
* DATPORT return the four media bytes already in order, so they are
|
||||||
* stored as-is. Silicon-verified: little-endian mode returned every
|
* stored as-is. The correct mode differs by integration and both are
|
||||||
* aligned 4-byte group byte-reversed. */
|
* silicon-verified: big-endian on the big-endian T1040, where
|
||||||
|
* little-endian returned every aligned 4-byte group reversed, and
|
||||||
|
* little-endian on the little-endian LS1028A. */
|
||||||
static int esdhc_read_block(uint8_t *buf)
|
static int esdhc_read_block(uint8_t *buf)
|
||||||
{
|
{
|
||||||
uint32_t i, word;
|
uint32_t i, word;
|
||||||
|
|
@ -662,6 +721,19 @@ static int esdhc_read_blocks(uint64_t lba, uint32_t count, uint8_t *buf)
|
||||||
* disk.c interface
|
* disk.c interface
|
||||||
* --------------------------------------------------------------------- */
|
* --------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
#if defined(TARGET_nxp_ls1028a)
|
||||||
|
/* Route a usable source clock to the eSDHC block (see HWA2CSR above). */
|
||||||
|
static void esdhc_clock_src_init(void)
|
||||||
|
{
|
||||||
|
volatile uint32_t *hwa2 = (volatile uint32_t*)LS1028A_HWA2CSR;
|
||||||
|
uint32_t val = (*hwa2 & ~HWA_CLKSEL_MASK) |
|
||||||
|
(HWA_CLKSEL_ESDHC << HWA_CLKSEL_SHIFT);
|
||||||
|
|
||||||
|
*hwa2 = val;
|
||||||
|
ESDHC_DBG("esdhc: HWA2CSR %x\r\n", *hwa2);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
int disk_init(int drv)
|
int disk_init(int drv)
|
||||||
{
|
{
|
||||||
if (drv != 0) {
|
if (drv != 0) {
|
||||||
|
|
@ -673,7 +745,10 @@ int disk_init(int drv)
|
||||||
/* Cache the timebase frequency for every delay and timeout below. A
|
/* Cache the timebase frequency for every delay and timeout below. A
|
||||||
* zero reading means no timeout in this driver could ever expire, so
|
* zero reading means no timeout in this driver could ever expire, so
|
||||||
* fail here and let the caller panic instead of spinning forever. */
|
* fail here and let the caller panic instead of spinning forever. */
|
||||||
g_esdhc_tb_hz = TIMEBASE_HZ;
|
#if defined(TARGET_nxp_ls1028a)
|
||||||
|
esdhc_clock_src_init();
|
||||||
|
#endif
|
||||||
|
g_esdhc_tb_hz = esdhc_read_tb_hz();
|
||||||
if (g_esdhc_tb_hz == 0U) {
|
if (g_esdhc_tb_hz == 0U) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
12
options.mk
12
options.mk
|
|
@ -801,12 +801,14 @@ ifeq ($(DISK_EMMC),1)
|
||||||
CFLAGS+=-D"DISK_EMMC=1"
|
CFLAGS+=-D"DISK_EMMC=1"
|
||||||
endif
|
endif
|
||||||
|
|
||||||
# Add SDHCI driver if SD card or eMMC is enabled (only add once).
|
# Add the SD/eMMC block driver if SD card or eMMC is enabled (only once).
|
||||||
# PPC targets provide their own eSDHC driver (hal/nxp_esdhc.o, added in
|
# DISK_DRIVER selects which one: the Cadence SDHCI driver (src/sdhci.c,
|
||||||
# arch.mk), so the Cadence SDHCI driver must not be linked there (its
|
# the default) or the Freescale eSDHC driver (hal/nxp_esdhc.o, added by
|
||||||
# disk_* entry points would collide).
|
# the target's arch.mk block, which also sets DISK_DRIVER=esdhc). Exactly
|
||||||
|
# one may link: both define the disk_* entry points.
|
||||||
|
DISK_DRIVER?=cadence
|
||||||
ifneq ($(filter 1,$(DISK_SDCARD) $(DISK_EMMC)),)
|
ifneq ($(filter 1,$(DISK_SDCARD) $(DISK_EMMC)),)
|
||||||
ifneq ($(ARCH),PPC)
|
ifeq ($(DISK_DRIVER),cadence)
|
||||||
OBJS+= src/sdhci.o
|
OBJS+= src/sdhci.o
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue