soc/software/bios: add autoconfiguration functionality for LiteSPI core
This commit is contained in:
parent
d389005550
commit
61238beeae
|
@ -11,6 +11,7 @@
|
|||
// This file is Copyright (c) 2018 Sergiusz Bazanski <q3k@q3k.org>
|
||||
// This file is Copyright (c) 2016 Tim 'mithro' Ansell <mithro@mithis.com>
|
||||
// This file is Copyright (c) 2020 Franck Jullien <franck.jullien@gmail.com>
|
||||
// This file is Copyright (c) 2020 Antmicro <www.antmicro.com>
|
||||
|
||||
// License: BSD
|
||||
|
||||
|
@ -43,6 +44,7 @@
|
|||
|
||||
#include "sdram.h"
|
||||
#include "sdcard.h"
|
||||
#include "spi.h"
|
||||
#include "boot.h"
|
||||
#include "readline.h"
|
||||
#include "helpers.h"
|
||||
|
@ -133,6 +135,9 @@ int main(int i, char **c)
|
|||
printf("Memory initialization failed\n");
|
||||
printf("\n");
|
||||
#endif
|
||||
#ifdef CSR_SPI_BASE
|
||||
spi_autoconfig();
|
||||
#endif
|
||||
|
||||
if(sdr_ok) {
|
||||
printf("--============== \e[1mBoot\e[0m ==================--\n");
|
||||
|
|
|
@ -0,0 +1,83 @@
|
|||
// This file is Copyright (c) 2020 Antmicro <www.antmicro.com>
|
||||
// License: BSD
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <crc.h>
|
||||
|
||||
#include <generated/csr.h>
|
||||
#include <generated/mem.h>
|
||||
#include <hw/flags.h>
|
||||
#include <system.h>
|
||||
|
||||
#include "spi.h"
|
||||
|
||||
#define DEBUG 0
|
||||
#define USER_DEFINED_DUMMY_BITS 0
|
||||
|
||||
static spi_mode spi_get_mode(void)
|
||||
{
|
||||
return (spi_mode)spi_cfg_read();
|
||||
}
|
||||
|
||||
static void spi_set_mode(spi_mode mode)
|
||||
{
|
||||
spi_cfg_write((unsigned char)mode);
|
||||
}
|
||||
|
||||
int spi_frequency_test(void)
|
||||
{
|
||||
unsigned int lowest_div = spi_clk_divisor_read();
|
||||
unsigned int crc = crc32((unsigned char *)SPIXIP_BASE, SPI_FLASH_BLOCK_SIZE);
|
||||
unsigned int crc_test = crc;
|
||||
|
||||
#if DEBUG
|
||||
printf("Testing against CRC32: %08x\n\r", crc);
|
||||
#endif
|
||||
|
||||
if(spi_get_mode() != SPI_MODE_MMAP) {
|
||||
spi_set_mode(SPI_MODE_MMAP);
|
||||
}
|
||||
|
||||
/* Check if block is erased (filled with 0xFF) */
|
||||
if(crc == CRC32_ERASED_FLASH) {
|
||||
printf("Block of size %d, started on address 0x%x is erased. Cannot proceed with SPI frequency test.\n\r", SPI_FLASH_BLOCK_SIZE, SPIXIP_BASE);
|
||||
return -1;
|
||||
}
|
||||
|
||||
for(int i = lowest_div; (crc == crc_test) && (i >= 0); i--) {
|
||||
lowest_div = i;
|
||||
spi_clk_divisor_write((uint32_t)i);
|
||||
crc_test = crc32((unsigned char *)SPIXIP_BASE, SPI_FLASH_BLOCK_SIZE);
|
||||
#if DEBUG
|
||||
printf("[DIV: %d] %08x\n\r", i, crc_test);
|
||||
#endif
|
||||
}
|
||||
lowest_div++;
|
||||
printf("Maximum available frequency: %d Hz\n\r", (spi_sys_clk_freq_read()/(2*(1 + lowest_div))));
|
||||
|
||||
return lowest_div;
|
||||
}
|
||||
|
||||
void spi_dummy_bits_setup(unsigned int dummy_bits)
|
||||
{
|
||||
spi_dummy_bits_write((uint32_t)dummy_bits);
|
||||
#if DEBUG
|
||||
printf("Dummy bits set to: %d\n\r", spi_dummy_bits_read());
|
||||
#endif
|
||||
}
|
||||
|
||||
void spi_autoconfig(void)
|
||||
{
|
||||
int ret = spi_frequency_test();
|
||||
if(ret < 0) {
|
||||
return;
|
||||
} else {
|
||||
spi_clk_divisor_write((uint32_t)ret);
|
||||
}
|
||||
#if (USER_DEFINED_DUMMY_BITS > 0)
|
||||
spi_dummy_bits_setup(USER_DEFINED_DUMMY_BITS);
|
||||
#endif
|
||||
}
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
#ifndef __SPI_H
|
||||
#define __SPI_H
|
||||
|
||||
#include <generated/csr.h>
|
||||
|
||||
#define SPI_FLASH_BLOCK_SIZE 256
|
||||
#define CRC32_ERASED_FLASH 0xFEA8A821
|
||||
|
||||
typedef enum {
|
||||
SPI_MODE_MMAP = 0,
|
||||
SPI_MODE_MASTER = 1,
|
||||
} spi_mode;
|
||||
|
||||
int spi_frequency_test(void);
|
||||
void spi_dummy_bits_setup(unsigned int dummy_bits);
|
||||
void spi_autoconfig(void);
|
||||
|
||||
#endif /* __SPI_H */
|
Loading…
Reference in New Issue