194 lines
2.6 KiB
ArmAsm
194 lines
2.6 KiB
ArmAsm
/*
|
|
* boot.S
|
|
*
|
|
* SPI boot code
|
|
*
|
|
* Copyright (C) 2020-2023 Sylvain Munaut <tnt@246tNt.com>
|
|
* SPDX-License-Identifier: MIT
|
|
*/
|
|
|
|
#ifndef APP_FLASH_ADDR
|
|
#define APP_FLASH_ADDR 0x000a0000
|
|
#endif
|
|
|
|
#ifndef APP_SRAM_ADDR
|
|
#define APP_SRAM_ADDR 0x00020000
|
|
#endif
|
|
|
|
#ifndef APP_SIZE
|
|
#define APP_SIZE 0x00010000
|
|
#endif
|
|
|
|
.section .text.start
|
|
.global _start
|
|
_start:
|
|
|
|
// SPI init
|
|
jal spi_init
|
|
jal spi_wakeup
|
|
|
|
// Read from flash to SRAM
|
|
li a0, APP_SRAM_ADDR
|
|
li a1, APP_SIZE
|
|
li a2, APP_FLASH_ADDR
|
|
jal spi_flash_read
|
|
|
|
// Setup reboot code
|
|
li t0, 0x0002006f
|
|
sw t0, 0(zero)
|
|
|
|
// Jump to main code
|
|
j APP_SRAM_ADDR
|
|
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// SB_SPI driver code
|
|
// ---------------------------------------------------------------------------
|
|
|
|
// Register definitions
|
|
|
|
.equ SPI_BASE, 0x81000000
|
|
|
|
.equ SPICR0, 4 * 0x08
|
|
.equ SPICR1, 4 * 0x09
|
|
.equ SPICR2, 4 * 0x0a
|
|
.equ SPIBR, 4 * 0x0b
|
|
.equ SPISR, 4 * 0x0c
|
|
.equ SPITXDR, 4 * 0x0d
|
|
.equ SPIRXDR, 4 * 0x0e
|
|
.equ SPICSR, 4 * 0x0f
|
|
|
|
|
|
// Initializes te SPI hardware
|
|
//
|
|
// Clobbers a0, a1
|
|
|
|
spi_init:
|
|
li a0, SPI_BASE
|
|
|
|
li a1, 0xff
|
|
sw a1, SPICR0(a0)
|
|
|
|
li a1, 0x80
|
|
sw a1, SPICR1(a0)
|
|
|
|
li a1, 0xc0
|
|
sw a1, SPICR2(a0)
|
|
|
|
li a1, 0x03
|
|
sw a1, SPIBR(a0)
|
|
|
|
li a1, 0x0f
|
|
sw a1, SPICSR(a0)
|
|
|
|
ret
|
|
|
|
|
|
//
|
|
// Wake up flash
|
|
//
|
|
spi_wakeup:
|
|
|
|
mv s2, ra
|
|
|
|
// Setup CS
|
|
li t0, SPI_BASE
|
|
li t1, 0x0e
|
|
sw t1, SPICSR(t0)
|
|
|
|
// Send command
|
|
li a0, 0xAB
|
|
jal _spi_do_one
|
|
|
|
// Release CS
|
|
li t0, SPI_BASE
|
|
li t1, 0x0f
|
|
sw t1, SPICSR(t0)
|
|
|
|
// Wait a bit
|
|
li s1, 0x10000
|
|
1:
|
|
addi s1, s1, -1
|
|
bne s1, zero, 1b
|
|
|
|
// Done
|
|
jr s2
|
|
|
|
|
|
// Reads a block of memory from SPI flash
|
|
//
|
|
// Params:
|
|
// a0 - destination pointer
|
|
// a1 - length (bytes)
|
|
// a2 - flash offset
|
|
// Clobbers t0, t1, s0, s1, s2
|
|
|
|
spi_flash_read:
|
|
// Save params
|
|
mv s0, a0
|
|
mv s1, a1
|
|
mv s2, ra
|
|
|
|
// Setup CS
|
|
li t0, SPI_BASE
|
|
li t1, 0x0e
|
|
sw t1, SPICSR(t0)
|
|
|
|
// Send command
|
|
li a0, 0x03
|
|
jal _spi_do_one
|
|
|
|
srli a0, a2, 16
|
|
and a0, a0, 0xff
|
|
jal _spi_do_one
|
|
|
|
srli a0, a2, 8
|
|
and a0, a0, 0xff
|
|
jal _spi_do_one
|
|
|
|
and a0, a2, 0xff
|
|
jal _spi_do_one
|
|
|
|
// Read loop
|
|
_spi_loop:
|
|
li a0, 0x00
|
|
jal _spi_do_one
|
|
sb a0, 0(s0)
|
|
addi s0, s0, 1
|
|
addi s1, s1, -1
|
|
bne s1, zero, _spi_loop
|
|
|
|
// Release CS
|
|
li t0, SPI_BASE
|
|
li t1, 0x0f
|
|
sw t1, SPICSR(t0)
|
|
|
|
// Done
|
|
jr s2
|
|
|
|
|
|
// Performs a single 8 bit SPI xfer
|
|
//
|
|
// Params: a0 - Data to TX
|
|
// Returns: a0 - RX data
|
|
// Clobbers t0, t1
|
|
|
|
_spi_do_one:
|
|
li t0, SPI_BASE
|
|
li t1, 0x08
|
|
|
|
// Write TX data
|
|
sw a0, SPITXDR(t0)
|
|
|
|
// Wait for RXRDY
|
|
1:
|
|
lw a0, SPISR(t0)
|
|
and a0, a0, t1
|
|
bne a0, t1, 1b
|
|
|
|
// Read RX data
|
|
lw a0, SPIRXDR(t0)
|
|
|
|
// Done
|
|
ret
|