From 516feae978f75afe4eb6ab408d736d766f3980d5 Mon Sep 17 00:00:00 2001 From: David Garske Date: Wed, 24 Apr 2024 17:16:45 -0700 Subject: [PATCH] Support for external SPI flash. --- docs/Targets.md | 23 ++++- hal/rx65n.c | 204 +++++++++++++++++++++++++++++++++++++++- hal/spi/spi_drv_rx65n.c | 48 ++++++++++ hal/spi/spi_drv_rx65n.h | 25 +++++ include/spi_drv.h | 11 +++ 5 files changed, 309 insertions(+), 2 deletions(-) create mode 100644 hal/spi/spi_drv_rx65n.c create mode 100644 hal/spi/spi_drv_rx65n.h diff --git a/docs/Targets.md b/docs/Targets.md index fc44923e2d..4ae5045c71 100644 --- a/docs/Targets.md +++ b/docs/Targets.md @@ -1866,7 +1866,28 @@ Example Boot Output (with DEBUG_UART=1): ``` wolfBoot HAL Init Boot partition: 0xFFE00000 -Image size 27108 +Image size 25932 + +| ------------------------------------------------------------------- | +| Renesas RX User Application in BOOT partition started by wolfBoot | +| ------------------------------------------------------------------- | + +wolfBoot HAL Init + +=== Boot Partition[ffe00000] === +Magic: WOLF +Version: 01 +Status: ff (New) +Tail Mgc: ˇˇˇˇ + +=== Update Partition[ffef0000] === +Magic: ˇˇˇˇ +Version: 00 +Status: ff (New) +Tail Mgc: ˇˇˇˇ + +Current Firmware Version: 1 +Hit any key to call wolfBoot_success the firmware. ``` Default Onboard Flash Memory Layout (2MB) (32KB sector): diff --git a/hal/rx65n.c b/hal/rx65n.c index 00b08494f7..5985c7c99a 100644 --- a/hal/rx65n.c +++ b/hal/rx65n.c @@ -32,6 +32,7 @@ #include "hal/renesas-rx.h" #define SYS_CLK (240000000) /* 240MHz */ +#define PCLKA (120000000) /* 120MHz */ #define PCLKB (60000000) /* 60MHz */ /* System Registers */ @@ -134,6 +135,7 @@ #define SCI_SMR_CKS(clk) (clk & 0x3) /* 0=PCLK, 1=PCLK/4, 2=PCLK/16, 3=PCLK/64 */ #define SCI_SMR_STOP (1 << 3) /* 0=1 stop bit */ #define SCI_SMR_CHR (1 << 6) /* 0=8-bit */ +#define SCI_SMR_CM (1 << 7) /* Mode: 0=Async/Simple I2C, 1=Sync/simple SPI */ #define SCI_BRR(n) (*(volatile uint8_t *)(SCI_BASE(n) + 0x01)) /* Bit Rate Reg < 255 */ #define SCI_SCR(n) (*(volatile uint8_t *)(SCI_BASE(n) + 0x02)) #define SCI_SCR_RE (1 << 4) @@ -146,6 +148,9 @@ #define SCI_RDR(n) (*(volatile uint8_t *)(SCI_BASE(n) + 0x05)) /* Receive Data Register */ #define SCI_SCMR(n) (*(volatile uint8_t *)(SCI_BASE(n) + 0x06)) #define SCI_SCMR_CHR1 (1 << 4) /* 1=8-bit */ +#define SCI_SCMR_SDIR (1 << 3) /* Transmitted/Received Data Transfer Direction */ +#define SCI_SCMR_SINV (1 << 2) /* Transmitted/Received Data Invert */ + #define SCI_SEMR(n) (*(volatile uint8_t *)(SCI_BASE(n) + 0x08)) #define SCI_SEMR_ASC0 (1 << 0) /* Asynchronous Mode Clock Source Select 0=external clock input */ #define SCI_SEMR_BRME (1 << 2) /* Bit Rate Modulation Enable */ @@ -154,6 +159,13 @@ #define SCI_SEMR_BGDM (1 << 6) /* Baud Rate Generator Double-Speed Mode Select */ #define SCI_SEMR_RXDESEL (1 << 7) /* Asynchronous Start Bit Edge Detection Select */ +/* SPI */ +#define SCI_SPMR (*(volatile uint8_t *)(SCI_BASE(n) + 0x0D)) +#define SCI_SPMR_SSE (1 << 0) /* 0=SSn# pin func disabled, 1=enabled */ +#define SCI_SPMR_MSS (1 << 2) /* Master slave select: 0=master, 1=slave */ +#define SCI_SPMR_CKPOL (1 << 6) /* Clock Polarity: 0=not inverted, 1=inverted */ +#define SCI_SPMR_CKPH (1 << 7) /* Clock Phase: 0=not delayed, 1=delayed */ + /* MPC (Multi-Function Pin Controller) */ #define MPC_PWPR (*(volatile uint8_t *)(0x8C11F)) #define MPC_PWPR_B0WI (1 << 7) @@ -171,7 +183,57 @@ #define PORT_PCR(n) (*(volatile uint8_t*)(PORT_BASE + 0xC0 + (n))) /* Pull-Up Resistor Control Register: 0=Disable pull-up, 1=Enable input pull-up */ #define PORT_DSCR(n) (*(volatile uint8_t*)(PORT_BASE + 0xE0 + (n))) /* Drive Capacity Control Register: 0=Normal, 1=High-drive output */ -/* SPI Flash (N25Q032) on SCI1 SCK=P27, MOSI=P26, MISO=P30, SS=P31 */ +/* RSPI */ +#define RSPI_BASE(n) (0xD0100 + ((n) * 0x40)) /* n=0-2 (RSPI0,RSPI1,RSPI2) */ +#define RSPI_SPCR(n) (*(volatile uint8_t *)(RSPI_BASE(n) + 0x00)) /* Control */ +#define RSPI_SPCR_SPMS (1 << 0) /* RSPI Mode Select 0=SPI operation (4-wire method) */ +#define RSPI_SPCR_TXMD (1 << 1) +#define RSPI_SPCR_MSTR (1 << 3) /* 0=Slave, 1=Master */ +#define RSPI_SPCR_SPE (1 << 6) /* 1=Enable RSPI */ +#define RSPI_SPPCR(n) (*(volatile uint8_t *)(RSPI_BASE(n) + 0x02)) /* Pin Control */ +#define RSPI_SPPCR_MOIFV (1 << 4) /* MOSI Idle Fixed Value */ +#define RSPI_SPPCR_MOIDE (1 << 5) /* MOSI Idle Value Fixing Enable */ +#define RSPI_SPSR(n) (*(volatile uint8_t *)(RSPI_BASE(n) + 0x03)) /* Status */ +#define RSPI_SPSR_OVRF (1 << 0) /* Overrun Error Flag */ +#define RSPI_SPSR_IDLNF (1 << 1) /* Idle Flag */ +#define RSPI_SPSR_MODF (1 << 2) /* Mode Fault Error Flag */ +#define RSPI_SPSR_PERF (1 << 3) /* Parity Error Flag */ +#define RSPI_SPSR_UDRF (1 << 4) /* Underrun Error Flag */ +#define RSPI_SPSR_SPTEF (1 << 5) /* Transmit Buffer Empty Flag */ +#define RSPI_SPSR_SPRF (1 << 7) /* Receive Buffer Full Flag */ +#define RSPI_SPSR8(n) (*(volatile uint8_t *)(RSPI_BASE(n) + 0x04)) /* Data */ +#define RSPI_SPSR16(n) (*(volatile uint16_t *)(RSPI_BASE(n) + 0x04)) /* Data */ +#define RSPI_SPSR32(n) (*(volatile uint32_t *)(RSPI_BASE(n) + 0x04)) /* Data */ +#define RSPI_SPSCR(n) (*(volatile uint32_t *)(RSPI_BASE(n) + 0x08)) /* Sequence Control */ +#define RSPI_SPSCR_SPSLN(s) ((s) & 0x7) /* Sequence Length Specification: 0=seq len 1 */ +#define RSPI_SPBR(n) (*(volatile uint8_t *)(RSPI_BASE(n) + 0x0A)) /* Bit Rate = PCLKA / (2 x (n + 1) X 2^n): 1=30 Mbps, 2=20Mpbs, 3=15Mbps, 4=12Mbps, 5=10Mbps */ +#define RSPI_SPDCR(n) (*(volatile uint8_t *)(RSPI_BASE(n) + 0x0B)) /* Data Control */ +#define RSPI_SPDCR_SPFC(f) ((f) & 0x3) /* Number of Frames Specification: 0=1 frame, 1=2 frames */ +#define RSPI_SPDCR_SPRDTD (1 << 4) /* Receive/Transmit Data Select */ +#define RSPI_SPDCR_SPLW (1 << 5) /* Longword Access/ Word Access Specification */ +#define RSPI_SPDCR_SPBYT (1 << 6) /* Byte Access Specification */ +#define RSPI_SPCKD(n) (*(volatile uint8_t *)(RSPI_BASE(n) + 0x0C)) /* Clock Delay */ +#define RSPI_SPCKD_SCKDL(d) ((d) & 0x7) /* RSPCK Delay Setting: 0=1 RSPCK, 1=2 RSPCK */ +#define RSPI_SSLND(n) (*(volatile uint8_t *)(RSPI_BASE(n) + 0x0D)) /* Slave Select Negation Delay */ +#define RSPI_SSLND_SLNDL(d) ((d) & 0x7) /* RSPCK Delay Setting: 0=1 RSPCK, 1=2 RSPCK */ +#define RSPI_SPND(n) (*(volatile uint8_t *)(RSPI_BASE(n) + 0x0D)) /* Next-Access Delay */ +#define RSPI_SPND_SPNDL(d) ((d) & 0x7) /* Next-Access Delay Setting: 0=1RSPCK+2PCLK, 1=2RSPCK+2PCLK */ +#define RSPI_SPCR2(n) (*(volatile uint8_t *)(RSPI_BASE(n) + 0x0F)) /* Control 2 */ +#define RSPI_SPCR2_SPPE (1 << 0) /* Parity Enable */ +#define RSPI_SPCR2_SPOE (1 << 1) /* Parity Mode */ +#define RSPI_SPCMD(n, m) (*(volatile uint16_t *)(RSPI_BASE(n) + 0x10 + (((m) & 0x7)*2))) /* Command Register m */ +#define RSPI_SPCMD_CPHA (1 << 0) /* Phase: 0=Data sampling on odd edge, data variation on even edge */ +#define RSPI_SPCMD_CPOL (1 << 1) /* Polarity: 0=RSPCK is low when idle, 1=High when idle */ +#define RSPI_SPCMD_BRDV(d) (((d) & 0x3) << 2) /* Bit Rate Division : 0=none,1=div2,2=div4,3=div8 */ +#define RSPI_SPCMD_SSLA(s) (((s) & 0x7) << 4) /* Signal Assert 0=SSL0, 1=SSL1 */ +#define RSPI_SPCMD_SSLKP (1 << 7) /* Signal Level Keeping: 0=Deassert on transfer complete, 1=Keep asserted */ +#define RSPI_SPCMD_SPB(l) (((l) & 0xF) << 8) /* Data Length: 7=8bits, 15=16=bits, 1=24bits, 3=32bits */ +#define RSPI_SPCMD_LSBF (1 << 12) /* LSB First: 0=MSB First, 1=LSB First */ +#define RSPI_SPCMD_SPNDEN (1 << 13) /* Next-Access Delay Enable */ +#define RSPI_SPCMD_SLNDEN (1 << 14) /* SSL Negation Delay Setting Enable */ +#define RSPI_SPCMD_SCKDEN (1 << 15) /* RSPCK Delay Setting Enable */ +#define RSPI_SPDCR2(n) (*(volatile uint8_t *)(RSPI_BASE(n) + 0x20)) /* Data Control 2 */ +#define RSPI_SPDCR2_BYSW (1 << 0) /* Byte Swap: 0=Byte swapping of SPDR data disabled, 1=Byte swapping of SPDR data enabled */ static void hal_delay_us(uint32_t us) @@ -182,6 +244,115 @@ static void hal_delay_us(uint32_t us) } } +#ifdef SPI_FLASH +/* SPI Flash (N25Q032) on SCI1 SCK=P27, MOSI=P26, MISO=P30, SS=P31 */ +#ifndef SPI_FLASH_SCI +#define SPI_FLASH_SCI 1 /* SCI1 */ +#endif +#ifndef SPI_FLASH_CLK_HZ +#define SPI_FLASH_CLK_HZ 15000000 +#endif +//#define SPI_USE_HW_CS +void spi_init(int polarity, int phase) +{ + /* Release SCII module stop (clear bit) */ + /* bit 31=SCI0, 30=SCI1, 29=SCI2, 28=SCI3, 27=SCI4, 26=SCI5, 25=SCI6, 24=SCI7 */ + PROTECT_OFF(); + SYS_MSTPCRB &= ~(1 << 30); + PROTECT_ON(); + + /* Disable RX/TX */ + SCI_SCR(SPI_FLASH_SCI) = 0; + + /* Configure P26-27 and P30-31 for SPI */ + PORT_PMR(0x2) |= ((1 << 6) | (1 << 7)); + PORT_PMR(0x3) |= (1 << 0); +#ifdef SPI_USE_HW_CS + PORT_PMR(0x3) |= (1 << 1); +#endif + + /* Disable MPC Write Protect for PFS */ + MPC_PWPR &= ~MPC_PWPR_B0WI; + MPC_PWPR |= MPC_PWPR_PFSWE; + + /* SCI1 Function Select = 0xA */ + MPC_PFS(0x76) = 0xA; /* P26 = MOSI */ + MPC_PFS(0x77) = 0xA; /* P27 = SCK */ + MPC_PFS(0x78) = 0xA; /* P30 = MISO */ +#ifdef SPI_USE_HW_CS + MPC_PFS(0x79) = 0xA; /* P31 = SS */ +#endif + + /* Enable MPC Write Protect for PFS */ + MPC_PWPR &= ~(MPC_PWPR_PFSWE | MPC_PWPR_B0WI); + MPC_PWPR |= MPC_PWPR_PFSWE; + + /* baud rate table: */ + /* divisor, abcs, bgdm, cks + * 4, 0, 0, 0 (using this one: 60MHZ/4=15MHz) + * 16, 0, 0, 1 + * 64, 0, 0, 2 + * 256, 0, 0, 3 + */ + + /* 8-bit, cks=0 (/4), bgdm=0, abcs=0 */ + SCI_BRR(SPI_FLASH_SCI) = 0; /* not used */ + SCI_SEMR(SPI_FLASH_SCI) &= ~SCI_SEMR_ABCS; + SCI_SEMR(SPI_FLASH_SCI) &= ~SCI_SEMR_BGDM; + SCI_SMR(SPI_FLASH_SCI) = SCI_SMR_CKS(0) | SCI_SMR_CM; + SCI_SCMR(SPI_FLASH_SCI) |= SCI_SCMR_CHR1; + if (polarity) + SCI_SPMR(SPI_FLASH_SCI) |= SCI_SPMR_CKPOL; + if (phase) + SCI_SPMR(SPI_FLASH_SCI) |= SCI_SPMR_CKPH; + + /* Enable SS control */ +#ifdef SPI_USE_HW_CS + SCI_SPMR(SPI_FLASH_SCI) = (SCI_SPMR_SSE) +#else + PORT_PDR(0x3) |= (1 << 1); /* enable SS as output */ + PORT_PODR(0x3) |= (1 << 1); /* drive high */ +#endif + + /* Enable TX/RX */ + SCI_SCR(SPI_FLASH_SCI) = (SCI_SCR_RE | SCI_SCR_TE); +} + +void spi_release(void) +{ + /* Disable RX/TX */ + SCI_SCR(SPI_FLASH_SCI) = 0; +} + +void spi_cs_on(uint32_t base, int pin) +{ + (void)base; + (void)pin; +#ifndef SPI_USE_HW_CS + PORT_PODR(0x3) &= ~(1 << 1); /* drive low */ +#endif +} +void spi_cs_off(uint32_t base, int pin) +{ + (void)base; + (void)pin; +#ifndef SPI_USE_HW_CS + PORT_PODR(0x3) |= (1 << 1); /* drive high */ +#endif +} + +void spi_write(const char byte) +{ + while ((SCI_SSR(SPI_FLASH_SCI) & SCI_SSR_TEND) == 0); + SCI_TDR(SPI_FLASH_SCI) = byte; +} +uint8_t spi_read(void) +{ + while ((SCI_SSR(SPI_FLASH_SCI) & SCI_SSR_RDRF) == 0); + return SCI_RDR(SPI_FLASH_SCI); +} +#endif + #ifdef DEBUG_UART /* Use SCI5 on PC3 at 115200 baud */ @@ -404,6 +575,7 @@ void hal_clk_init(void) void hal_init(void) { hal_clk_init(); + #ifdef DEBUG_UART uart_init(); uart_write("wolfBoot HAL Init\n", 18); @@ -435,3 +607,33 @@ void hal_prepare_boot(void) { return; } + +#if defined(EXT_FLASH) && !defined(SPI_FLASH) && !defined(QSPI_FLASH) +void ext_flash_lock(void) +{ + /* no op */ +} + +void ext_flash_unlock(void) +{ + /* no op */ +} + +int ext_flash_write(uintptr_t address, const uint8_t *data, int len) +{ + //memcpy(flash_base + address, data, len); + return 0; +} + +int ext_flash_read(uintptr_t address, uint8_t *data, int len) +{ + //memcpy(data, flash_base + address, len); + return len; +} + +int ext_flash_erase(uintptr_t address, int len) +{ + //memset(flash_base + address, FLASH_BYTE_ERASED, len); + return 0; +} +#endif /* EXT_FLASH */ diff --git a/hal/spi/spi_drv_rx65n.c b/hal/spi/spi_drv_rx65n.c new file mode 100644 index 0000000000..966d7629b4 --- /dev/null +++ b/hal/spi/spi_drv_rx65n.c @@ -0,0 +1,48 @@ +/* spi_drv_rx65n.c + * + * Driver for the SPI back-end of the SPI_FLASH module. + * + * Example implementation for Renesas RX65N. + * + * Copyright (C) 2024 wolfSSL Inc. + * + * This file is part of wolfBoot. + * + * wolfBoot is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfBoot is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ +#include +#include "spi_drv.h" +#include "spi_drv_rx65n.h" + +#if defined(SPI_FLASH) || defined(WOLFBOOT_TPM) + + +#ifdef WOLFBOOT_TPM +int spi_xfer(int cs, const uint8_t* tx, uint8_t* rx, uint32_t sz, int flags) +{ + uint32_t i; + spi_cs_on(SPI_CS_TPM_PIO_BASE, cs); + for (i = 0; i < sz; i++) { + spi_write((const char)tx[i]); + rx[i] = spi_read(); + } + if (!(flags & SPI_XFER_FLAG_CONTINUE)) { + spi_cs_off(SPI_CS_TPM_PIO_BASE, cs); + } + return 0; +} +#endif /* WOLFBOOT_TPM */ + +#endif /* SPI_FLASH || WOLFBOOT_TPM */ diff --git a/hal/spi/spi_drv_rx65n.h b/hal/spi/spi_drv_rx65n.h new file mode 100644 index 0000000000..5482ef7fda --- /dev/null +++ b/hal/spi/spi_drv_rx65n.h @@ -0,0 +1,25 @@ +/* spi_drv_rx65n.h + * + * wolfBoot is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfBoot is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + +#ifndef SPI_DRV_RX65N_H_INCLUDED +#define SPI_DRV_RX65N_H_INCLUDED +#include + +#define SPI_CS_FLASH 0 +#define SPI_CS_PIO_BASE 0UL + +#endif /* !SPI_DRV_RX65N_H_INCLUDED */ diff --git a/include/spi_drv.h b/include/spi_drv.h index 0d0c0f6b92..6fff00257a 100644 --- a/include/spi_drv.h +++ b/include/spi_drv.h @@ -58,6 +58,10 @@ #include "hal/spi/spi_drv_nxp.h" #endif +#if defined(PLATFORM_rx65n) +#include "hal/spi/spi_drv_rx65n.h" +#endif + void spi_init(int polarity, int phase); void spi_release(void); @@ -93,6 +97,13 @@ int qspi_transfer(uint8_t fmode, const uint8_t cmd, ); #endif /* QSPI_FLASH || OCTOSPI_FLASH */ +#ifndef SPI_CS_FLASH +#define SPI_CS_FLASH 0 +#endif +#ifndef SPI_CS_PIO_BASE +#define SPI_CS_PIO_BASE 0UL +#endif + #endif /* SPI_FLASH || WOLFBOOT_TPM || QSPI_FLASH || OCTOSPI_FLASH */ #endif /* !SPI_DRV_H_INCLUDED */