60 changes: 46 additions & 14 deletions configs/pcengines_apu2.config
Expand Up @@ -7,13 +7,13 @@
# General setup
#
# CONFIG_EXPERT is not set
CONFIG_LOCALVERSION="4.0.12"
CONFIG_LOCALVERSION=""
CONFIG_CBFS_PREFIX="fallback"
CONFIG_COMPILER_GCC=y
# CONFIG_COMPILER_LLVM_CLANG is not set
# CONFIG_ANY_TOOLCHAIN is not set
# CONFIG_CCACHE is not set
# CONFIG_COMPRESS_RAMSTAGE is not set
CONFIG_COMPRESS_RAMSTAGE=y
CONFIG_INCLUDE_CONFIG_FILE=y
# CONFIG_EARLY_CBMEM_INIT is not set
# CONFIG_COLLECT_TIMESTAMPS is not set
Expand All @@ -31,10 +31,11 @@ CONFIG_BOOTBLOCK_SOURCE="bootblock_simple.c"
CONFIG_VENDOR_PCENGINES=y
CONFIG_BOARD_PCENGINES_APU2=y
# CONFIG_BOARD_PCENGINES_APU3 is not set
# CONFIG_BOARD_PCENGINES_APU4 is not set
# CONFIG_BOARD_PCENGINES_APU5 is not set
CONFIG_BOARD_SPECIFIC_OPTIONS=y
CONFIG_MAINBOARD_DIR="pcengines/apu2"
CONFIG_MAINBOARD_PART_NUMBER="PC Engines apu2"
CONFIG_MAINBOARD_PART_NUMBER="apu2"
# CONFIG_SVI2_SLOW_SPEED is not set
CONFIG_SVI_WAIT_COMP_DIS=y
CONFIG_HW_MEM_HOLE_SIZEK=0x200000
Expand All @@ -53,7 +54,6 @@ CONFIG_AGESA_HEAP_MEMTEST=y
# CONFIG_DUMP_GPIO_CONFIGURATION is not set
# CONFIG_DUMP_CLOCK_CONFIGURATION is not set
# CONFIG_DUMP_LINK_CONFIGURATION is not set
CONFIG_INCLUDE_SGABIOS=y
# CONFIG_FORCE_CONSOLE is not set
CONFIG_MAINBOARD_VENDOR="PC Engines"
CONFIG_BOARD_ROMSIZE_KB_8192=y
Expand Down Expand Up @@ -179,6 +179,7 @@ CONFIG_X86_AMD_FIXED_MTRRS=y
# CONFIG_PARALLEL_MP is not set
# CONFIG_BACKUP_DEFAULT_SMM_REGION is not set
# CONFIG_MIRROR_PAYLOAD_TO_RAM_BEFORE_LOADING is not set
CONFIG_BOOT_MEDIA_SPI_BUS=0
CONFIG_CACHE_AS_RAM=y
CONFIG_SMP=y
CONFIG_AP_SIPI_VECTOR=0xfffff000
Expand Down Expand Up @@ -213,8 +214,7 @@ CONFIG_HUDSON_PSP=y
CONFIG_HUDSON_XHCI_FWM_FILE="3rdparty/southbridge/amd/avalon/xhci.bin"
CONFIG_HUDSON_FWM=y
CONFIG_HUDSON_FWM_POSITION=0xFF820000
CONFIG_HUDSON_PSP_CUSTOM=y
CONFIG_HUDSON_PSP_POSITION=0xFFFA0000
# CONFIG_HUDSON_PSP_CUSTOM is not set
CONFIG_AMD_PUBKEY_FILE="3rdparty/southbridge/amd/avalon/PSP/AmdPubKey.bin"
CONFIG_HUDSON_SATA_MODE=0

Expand Down Expand Up @@ -260,13 +260,13 @@ CONFIG_PCI_BUS_SEGN_BITS=0
CONFIG_SUBSYSTEM_VENDOR_ID=0x0000
CONFIG_SUBSYSTEM_DEVICE_ID=0x0000
# CONFIG_VGA_BIOS is not set
# CONFIG_PXE_ROM is not set
# CONFIG_SOFTWARE_I2C is not set

#
# Generic Drivers
#
# CONFIG_DRIVERS_AS3722_RTC is not set
# CONFIG_ELOG is not set
# CONFIG_DRIVERS_I2C_RTD2132 is not set
# CONFIG_INTEL_DP is not set
# CONFIG_INTEL_DDI is not set
Expand All @@ -280,7 +280,25 @@ CONFIG_SUBSYSTEM_DEVICE_ID=0x0000
# CONFIG_LPC_TPM is not set
CONFIG_DRIVERS_MC146818=y
# CONFIG_DRIVERS_SIL_3114 is not set
# CONFIG_SPI_FLASH is not set
CONFIG_SPI_FLASH=y
CONFIG_BOOT_DEVICE_SPI_FLASH_BUS=0
CONFIG_BOOT_DEVICE_SPI_FLASH_RW_NOMMAP=y
# CONFIG_BOOT_DEVICE_SPI_FLASH_RW_NOMMAP_EARLY is not set
CONFIG_SPI_FLASH_INCLUDE_ALL_DRIVERS=y
# CONFIG_SPI_FLASH_NO_FAST_READ is not set
CONFIG_SPI_FLASH_ADESTO=y
CONFIG_SPI_FLASH_AMIC=y
CONFIG_SPI_FLASH_ATMEL=y
CONFIG_SPI_FLASH_EON=y
CONFIG_SPI_FLASH_GIGADEVICE=y
CONFIG_SPI_FLASH_MACRONIX=y
CONFIG_SPI_FLASH_SPANSION=y
CONFIG_SPI_FLASH_SST=y
CONFIG_SPI_FLASH_STMICRO=y
CONFIG_SPI_FLASH_WINBOND=y
# CONFIG_SPI_FLASH_FAST_READ_DUAL_OUTPUT_3B is not set
# CONFIG_SPI_FLASH_HAS_VOLATILE_GROUP is not set
# CONFIG_HAVE_SPI_CONSOLE_SUPPORT is not set
# CONFIG_DRIVER_TI_TPS65090 is not set
CONFIG_DRIVERS_UART=y
CONFIG_DRIVERS_UART_8250IO=y
Expand Down Expand Up @@ -321,10 +339,7 @@ CONFIG_TTYS0_LCS=3
# CONFIG_SPKMODEM is not set
# CONFIG_ONBOARD_VGA_IS_PRIMARY is not set
# CONFIG_CONSOLE_NE2K is not set
CONFIG_CONSOLE_CBMEM=y
CONFIG_CONSOLE_CBMEM_BUFFER_SIZE=0x20000
CONFIG_CONSOLE_PRERAM_BUFFER_BASE=0xabadbeef
CONFIG_CONSOLE_PRERAM_BUFFER_SIZE=0x0
# CONFIG_CONSOLE_CBMEM is not set
# CONFIG_DEFAULT_CONSOLE_LOGLEVEL_8 is not set
# CONFIG_DEFAULT_CONSOLE_LOGLEVEL_7 is not set
# CONFIG_DEFAULT_CONSOLE_LOGLEVEL_6 is not set
Expand All @@ -344,6 +359,10 @@ CONFIG_POST_DEVICE_NONE=y
# CONFIG_POST_DEVICE_PCI_PCIE is not set
CONFIG_POST_IO=y
CONFIG_POST_IO_PORT=0x80
# CONFIG_BOOT_DEVICE_NOT_SPI_FLASH is not set
CONFIG_BOOT_DEVICE_SPI_FLASH=y
CONFIG_BOOT_DEVICE_MEMORY_MAPPED=y
# CONFIG_BOOT_DEVICE_SUPPORTS_WRITES is not set
# CONFIG_HAVE_ACPI_RESUME is not set
# CONFIG_HAVE_ACPI_SLIC is not set
CONFIG_HAVE_HARD_RESET=y
Expand Down Expand Up @@ -391,14 +410,26 @@ CONFIG_PAYLOAD_SEABIOS=y
CONFIG_SEABIOS_ELTAN=y
CONFIG_SEABIOS_STABLE=y
# CONFIG_SEABIOS_MASTER is not set
CONFIG_ELTAN_SEABIOS_TAG="rel-1.10.2.1"
CONFIG_ELTAN_SEABIOS_TAG="rel-1.11.0.4"
CONFIG_SEABIOS_SERIAL_CONSOLE=y
# CONFIG_SKIP_PXE_LOAD is not set
# CONFIG_SEABIOS_THREAD_OPTIONROMS is not set
CONFIG_SEABIOS_MALLOC_UPPERMEMORY=y
CONFIG_PAYLOAD_FILE="payloads/external/SeaBIOS/seabios/out/bios.bin.elf"
CONFIG_COMPRESSED_PAYLOAD_LZMA=y
CONFIG_SORTBOOTORDER=y
CONFIG_PXE=y

#
# PXE Options
#
# CONFIG_PXE_ROM is not set
CONFIG_BUILD_IPXE=y
# CONFIG_IPXE_STABLE is not set
CONFIG_IPXE_MASTER=y
# CONFIG_PXE_SERIAL_CONSOLE is not set
CONFIG_PXE_ROM_ID="8086,157b"
CONFIG_PXE_CUSTOM_GENERAL_H="../../../../apu2-documentation/ipxe/general.h"
CONFIG_PXE_CUSTOM_BOOTMENU_FILE="../../../../apu2-documentation/ipxe/menu.ipxe"

#
# Debugging
Expand All @@ -411,6 +442,7 @@ CONFIG_SORTBOOTORDER=y
# CONFIG_HAVE_DEBUG_SMBUS is not set
# CONFIG_DEBUG_MALLOC is not set
# CONFIG_DEBUG_ACPI is not set
# CONFIG_DEBUG_SPI_FLASH is not set
# CONFIG_TRACE is not set
# CONFIG_ENABLE_APIC_EXT_ID is not set
CONFIG_WARNINGS_ARE_ERRORS=y
Expand Down
60 changes: 46 additions & 14 deletions configs/pcengines_apu3.config
Expand Up @@ -7,13 +7,13 @@
# General setup
#
# CONFIG_EXPERT is not set
CONFIG_LOCALVERSION="4.0.12"
CONFIG_LOCALVERSION=""
CONFIG_CBFS_PREFIX="fallback"
CONFIG_COMPILER_GCC=y
# CONFIG_COMPILER_LLVM_CLANG is not set
# CONFIG_ANY_TOOLCHAIN is not set
# CONFIG_CCACHE is not set
# CONFIG_COMPRESS_RAMSTAGE is not set
CONFIG_COMPRESS_RAMSTAGE=y
CONFIG_INCLUDE_CONFIG_FILE=y
# CONFIG_EARLY_CBMEM_INIT is not set
# CONFIG_COLLECT_TIMESTAMPS is not set
Expand All @@ -31,10 +31,11 @@ CONFIG_BOOTBLOCK_SOURCE="bootblock_simple.c"
CONFIG_VENDOR_PCENGINES=y
# CONFIG_BOARD_PCENGINES_APU2 is not set
CONFIG_BOARD_PCENGINES_APU3=y
# CONFIG_BOARD_PCENGINES_APU4 is not set
# CONFIG_BOARD_PCENGINES_APU5 is not set
CONFIG_BOARD_SPECIFIC_OPTIONS=y
CONFIG_MAINBOARD_DIR="pcengines/apu3"
CONFIG_MAINBOARD_PART_NUMBER="PC Engines apu3"
CONFIG_MAINBOARD_PART_NUMBER="apu3"
# CONFIG_SVI2_SLOW_SPEED is not set
CONFIG_SVI_WAIT_COMP_DIS=y
CONFIG_HW_MEM_HOLE_SIZEK=0x200000
Expand All @@ -53,7 +54,6 @@ CONFIG_AGESA_HEAP_MEMTEST=y
# CONFIG_DUMP_GPIO_CONFIGURATION is not set
# CONFIG_DUMP_CLOCK_CONFIGURATION is not set
# CONFIG_DUMP_LINK_CONFIGURATION is not set
CONFIG_INCLUDE_SGABIOS=y
# CONFIG_FORCE_CONSOLE is not set
CONFIG_MAINBOARD_VENDOR="PC Engines"
CONFIG_BOARD_ROMSIZE_KB_8192=y
Expand Down Expand Up @@ -179,6 +179,7 @@ CONFIG_X86_AMD_FIXED_MTRRS=y
# CONFIG_PARALLEL_MP is not set
# CONFIG_BACKUP_DEFAULT_SMM_REGION is not set
# CONFIG_MIRROR_PAYLOAD_TO_RAM_BEFORE_LOADING is not set
CONFIG_BOOT_MEDIA_SPI_BUS=0
CONFIG_CACHE_AS_RAM=y
CONFIG_SMP=y
CONFIG_AP_SIPI_VECTOR=0xfffff000
Expand Down Expand Up @@ -213,8 +214,7 @@ CONFIG_HUDSON_PSP=y
CONFIG_HUDSON_XHCI_FWM_FILE="3rdparty/southbridge/amd/avalon/xhci.bin"
CONFIG_HUDSON_FWM=y
CONFIG_HUDSON_FWM_POSITION=0xFF820000
CONFIG_HUDSON_PSP_CUSTOM=y
CONFIG_HUDSON_PSP_POSITION=0xFFFA0000
# CONFIG_HUDSON_PSP_CUSTOM is not set
CONFIG_AMD_PUBKEY_FILE="3rdparty/southbridge/amd/avalon/PSP/AmdPubKey.bin"
CONFIG_HUDSON_SATA_MODE=0

Expand Down Expand Up @@ -260,13 +260,13 @@ CONFIG_PCI_BUS_SEGN_BITS=0
CONFIG_SUBSYSTEM_VENDOR_ID=0x0000
CONFIG_SUBSYSTEM_DEVICE_ID=0x0000
# CONFIG_VGA_BIOS is not set
# CONFIG_PXE_ROM is not set
# CONFIG_SOFTWARE_I2C is not set

#
# Generic Drivers
#
# CONFIG_DRIVERS_AS3722_RTC is not set
# CONFIG_ELOG is not set
# CONFIG_DRIVERS_I2C_RTD2132 is not set
# CONFIG_INTEL_DP is not set
# CONFIG_INTEL_DDI is not set
Expand All @@ -280,7 +280,25 @@ CONFIG_SUBSYSTEM_DEVICE_ID=0x0000
# CONFIG_LPC_TPM is not set
CONFIG_DRIVERS_MC146818=y
# CONFIG_DRIVERS_SIL_3114 is not set
# CONFIG_SPI_FLASH is not set
CONFIG_SPI_FLASH=y
CONFIG_BOOT_DEVICE_SPI_FLASH_BUS=0
CONFIG_BOOT_DEVICE_SPI_FLASH_RW_NOMMAP=y
# CONFIG_BOOT_DEVICE_SPI_FLASH_RW_NOMMAP_EARLY is not set
CONFIG_SPI_FLASH_INCLUDE_ALL_DRIVERS=y
# CONFIG_SPI_FLASH_NO_FAST_READ is not set
CONFIG_SPI_FLASH_ADESTO=y
CONFIG_SPI_FLASH_AMIC=y
CONFIG_SPI_FLASH_ATMEL=y
CONFIG_SPI_FLASH_EON=y
CONFIG_SPI_FLASH_GIGADEVICE=y
CONFIG_SPI_FLASH_MACRONIX=y
CONFIG_SPI_FLASH_SPANSION=y
CONFIG_SPI_FLASH_SST=y
CONFIG_SPI_FLASH_STMICRO=y
CONFIG_SPI_FLASH_WINBOND=y
# CONFIG_SPI_FLASH_FAST_READ_DUAL_OUTPUT_3B is not set
# CONFIG_SPI_FLASH_HAS_VOLATILE_GROUP is not set
# CONFIG_HAVE_SPI_CONSOLE_SUPPORT is not set
# CONFIG_DRIVER_TI_TPS65090 is not set
CONFIG_DRIVERS_UART=y
CONFIG_DRIVERS_UART_8250IO=y
Expand Down Expand Up @@ -321,10 +339,7 @@ CONFIG_TTYS0_LCS=3
# CONFIG_SPKMODEM is not set
# CONFIG_ONBOARD_VGA_IS_PRIMARY is not set
# CONFIG_CONSOLE_NE2K is not set
CONFIG_CONSOLE_CBMEM=y
CONFIG_CONSOLE_CBMEM_BUFFER_SIZE=0x20000
CONFIG_CONSOLE_PRERAM_BUFFER_BASE=0xabadbeef
CONFIG_CONSOLE_PRERAM_BUFFER_SIZE=0x0
# CONFIG_CONSOLE_CBMEM is not set
# CONFIG_DEFAULT_CONSOLE_LOGLEVEL_8 is not set
# CONFIG_DEFAULT_CONSOLE_LOGLEVEL_7 is not set
# CONFIG_DEFAULT_CONSOLE_LOGLEVEL_6 is not set
Expand All @@ -344,6 +359,10 @@ CONFIG_POST_DEVICE_NONE=y
# CONFIG_POST_DEVICE_PCI_PCIE is not set
CONFIG_POST_IO=y
CONFIG_POST_IO_PORT=0x80
# CONFIG_BOOT_DEVICE_NOT_SPI_FLASH is not set
CONFIG_BOOT_DEVICE_SPI_FLASH=y
CONFIG_BOOT_DEVICE_MEMORY_MAPPED=y
# CONFIG_BOOT_DEVICE_SUPPORTS_WRITES is not set
# CONFIG_HAVE_ACPI_RESUME is not set
# CONFIG_HAVE_ACPI_SLIC is not set
CONFIG_HAVE_HARD_RESET=y
Expand Down Expand Up @@ -391,14 +410,26 @@ CONFIG_PAYLOAD_SEABIOS=y
CONFIG_SEABIOS_ELTAN=y
CONFIG_SEABIOS_STABLE=y
# CONFIG_SEABIOS_MASTER is not set
CONFIG_ELTAN_SEABIOS_TAG="rel-1.10.2.1"
CONFIG_ELTAN_SEABIOS_TAG="rel-1.11.0.4"
CONFIG_SEABIOS_SERIAL_CONSOLE=y
# CONFIG_SKIP_PXE_LOAD is not set
# CONFIG_SEABIOS_THREAD_OPTIONROMS is not set
CONFIG_SEABIOS_MALLOC_UPPERMEMORY=y
CONFIG_PAYLOAD_FILE="payloads/external/SeaBIOS/seabios/out/bios.bin.elf"
CONFIG_COMPRESSED_PAYLOAD_LZMA=y
CONFIG_SORTBOOTORDER=y
CONFIG_PXE=y

#
# PXE Options
#
# CONFIG_PXE_ROM is not set
CONFIG_BUILD_IPXE=y
# CONFIG_IPXE_STABLE is not set
CONFIG_IPXE_MASTER=y
# CONFIG_PXE_SERIAL_CONSOLE is not set
CONFIG_PXE_ROM_ID="8086,1539"
CONFIG_PXE_CUSTOM_GENERAL_H="../../../../apu2-documentation/ipxe/general.h"
CONFIG_PXE_CUSTOM_BOOTMENU_FILE="../../../../apu2-documentation/ipxe/menu.ipxe"

#
# Debugging
Expand All @@ -411,6 +442,7 @@ CONFIG_SORTBOOTORDER=y
# CONFIG_HAVE_DEBUG_SMBUS is not set
# CONFIG_DEBUG_MALLOC is not set
# CONFIG_DEBUG_ACPI is not set
# CONFIG_DEBUG_SPI_FLASH is not set
# CONFIG_TRACE is not set
# CONFIG_ENABLE_APIC_EXT_ID is not set
CONFIG_WARNINGS_ARE_ERRORS=y
Expand Down
455 changes: 455 additions & 0 deletions configs/pcengines_apu4.config

Large diffs are not rendered by default.

60 changes: 46 additions & 14 deletions configs/pcengines_apu5.config
Expand Up @@ -7,13 +7,13 @@
# General setup
#
# CONFIG_EXPERT is not set
CONFIG_LOCALVERSION="4.0.12"
CONFIG_LOCALVERSION=""
CONFIG_CBFS_PREFIX="fallback"
CONFIG_COMPILER_GCC=y
# CONFIG_COMPILER_LLVM_CLANG is not set
# CONFIG_ANY_TOOLCHAIN is not set
# CONFIG_CCACHE is not set
# CONFIG_COMPRESS_RAMSTAGE is not set
CONFIG_COMPRESS_RAMSTAGE=y
CONFIG_INCLUDE_CONFIG_FILE=y
# CONFIG_EARLY_CBMEM_INIT is not set
# CONFIG_COLLECT_TIMESTAMPS is not set
Expand All @@ -31,10 +31,11 @@ CONFIG_BOOTBLOCK_SOURCE="bootblock_simple.c"
CONFIG_VENDOR_PCENGINES=y
# CONFIG_BOARD_PCENGINES_APU2 is not set
# CONFIG_BOARD_PCENGINES_APU3 is not set
# CONFIG_BOARD_PCENGINES_APU4 is not set
CONFIG_BOARD_PCENGINES_APU5=y
CONFIG_BOARD_SPECIFIC_OPTIONS=y
CONFIG_MAINBOARD_DIR="pcengines/apu5"
CONFIG_MAINBOARD_PART_NUMBER="PC Engines apu5"
CONFIG_MAINBOARD_PART_NUMBER="apu5"
# CONFIG_SVI2_SLOW_SPEED is not set
CONFIG_SVI_WAIT_COMP_DIS=y
CONFIG_HW_MEM_HOLE_SIZEK=0x200000
Expand All @@ -53,7 +54,6 @@ CONFIG_AGESA_HEAP_MEMTEST=y
# CONFIG_DUMP_GPIO_CONFIGURATION is not set
# CONFIG_DUMP_CLOCK_CONFIGURATION is not set
# CONFIG_DUMP_LINK_CONFIGURATION is not set
CONFIG_INCLUDE_SGABIOS=y
# CONFIG_FORCE_CONSOLE is not set
CONFIG_MAINBOARD_VENDOR="PC Engines"
CONFIG_BOARD_ROMSIZE_KB_8192=y
Expand Down Expand Up @@ -179,6 +179,7 @@ CONFIG_X86_AMD_FIXED_MTRRS=y
# CONFIG_PARALLEL_MP is not set
# CONFIG_BACKUP_DEFAULT_SMM_REGION is not set
# CONFIG_MIRROR_PAYLOAD_TO_RAM_BEFORE_LOADING is not set
CONFIG_BOOT_MEDIA_SPI_BUS=0
CONFIG_CACHE_AS_RAM=y
CONFIG_SMP=y
CONFIG_AP_SIPI_VECTOR=0xfffff000
Expand Down Expand Up @@ -213,8 +214,7 @@ CONFIG_HUDSON_PSP=y
CONFIG_HUDSON_XHCI_FWM_FILE="3rdparty/southbridge/amd/avalon/xhci.bin"
CONFIG_HUDSON_FWM=y
CONFIG_HUDSON_FWM_POSITION=0xFF820000
CONFIG_HUDSON_PSP_CUSTOM=y
CONFIG_HUDSON_PSP_POSITION=0xFFFA0000
# CONFIG_HUDSON_PSP_CUSTOM is not set
CONFIG_AMD_PUBKEY_FILE="3rdparty/southbridge/amd/avalon/PSP/AmdPubKey.bin"
CONFIG_HUDSON_SATA_MODE=0

Expand Down Expand Up @@ -260,13 +260,13 @@ CONFIG_PCI_BUS_SEGN_BITS=0
CONFIG_SUBSYSTEM_VENDOR_ID=0x0000
CONFIG_SUBSYSTEM_DEVICE_ID=0x0000
# CONFIG_VGA_BIOS is not set
# CONFIG_PXE_ROM is not set
# CONFIG_SOFTWARE_I2C is not set

#
# Generic Drivers
#
# CONFIG_DRIVERS_AS3722_RTC is not set
# CONFIG_ELOG is not set
# CONFIG_DRIVERS_I2C_RTD2132 is not set
# CONFIG_INTEL_DP is not set
# CONFIG_INTEL_DDI is not set
Expand All @@ -280,7 +280,25 @@ CONFIG_SUBSYSTEM_DEVICE_ID=0x0000
# CONFIG_LPC_TPM is not set
CONFIG_DRIVERS_MC146818=y
# CONFIG_DRIVERS_SIL_3114 is not set
# CONFIG_SPI_FLASH is not set
CONFIG_SPI_FLASH=y
CONFIG_BOOT_DEVICE_SPI_FLASH_BUS=0
CONFIG_BOOT_DEVICE_SPI_FLASH_RW_NOMMAP=y
# CONFIG_BOOT_DEVICE_SPI_FLASH_RW_NOMMAP_EARLY is not set
CONFIG_SPI_FLASH_INCLUDE_ALL_DRIVERS=y
# CONFIG_SPI_FLASH_NO_FAST_READ is not set
CONFIG_SPI_FLASH_ADESTO=y
CONFIG_SPI_FLASH_AMIC=y
CONFIG_SPI_FLASH_ATMEL=y
CONFIG_SPI_FLASH_EON=y
CONFIG_SPI_FLASH_GIGADEVICE=y
CONFIG_SPI_FLASH_MACRONIX=y
CONFIG_SPI_FLASH_SPANSION=y
CONFIG_SPI_FLASH_SST=y
CONFIG_SPI_FLASH_STMICRO=y
CONFIG_SPI_FLASH_WINBOND=y
# CONFIG_SPI_FLASH_FAST_READ_DUAL_OUTPUT_3B is not set
# CONFIG_SPI_FLASH_HAS_VOLATILE_GROUP is not set
# CONFIG_HAVE_SPI_CONSOLE_SUPPORT is not set
# CONFIG_DRIVER_TI_TPS65090 is not set
CONFIG_DRIVERS_UART=y
CONFIG_DRIVERS_UART_8250IO=y
Expand Down Expand Up @@ -321,10 +339,7 @@ CONFIG_TTYS0_LCS=3
# CONFIG_SPKMODEM is not set
# CONFIG_ONBOARD_VGA_IS_PRIMARY is not set
# CONFIG_CONSOLE_NE2K is not set
CONFIG_CONSOLE_CBMEM=y
CONFIG_CONSOLE_CBMEM_BUFFER_SIZE=0x20000
CONFIG_CONSOLE_PRERAM_BUFFER_BASE=0xabadbeef
CONFIG_CONSOLE_PRERAM_BUFFER_SIZE=0x0
# CONFIG_CONSOLE_CBMEM is not set
# CONFIG_DEFAULT_CONSOLE_LOGLEVEL_8 is not set
# CONFIG_DEFAULT_CONSOLE_LOGLEVEL_7 is not set
# CONFIG_DEFAULT_CONSOLE_LOGLEVEL_6 is not set
Expand All @@ -344,6 +359,10 @@ CONFIG_POST_DEVICE_NONE=y
# CONFIG_POST_DEVICE_PCI_PCIE is not set
CONFIG_POST_IO=y
CONFIG_POST_IO_PORT=0x80
# CONFIG_BOOT_DEVICE_NOT_SPI_FLASH is not set
CONFIG_BOOT_DEVICE_SPI_FLASH=y
CONFIG_BOOT_DEVICE_MEMORY_MAPPED=y
# CONFIG_BOOT_DEVICE_SUPPORTS_WRITES is not set
# CONFIG_HAVE_ACPI_RESUME is not set
# CONFIG_HAVE_ACPI_SLIC is not set
CONFIG_HAVE_HARD_RESET=y
Expand Down Expand Up @@ -391,14 +410,26 @@ CONFIG_PAYLOAD_SEABIOS=y
CONFIG_SEABIOS_ELTAN=y
CONFIG_SEABIOS_STABLE=y
# CONFIG_SEABIOS_MASTER is not set
CONFIG_ELTAN_SEABIOS_TAG="rel-1.10.2.1"
CONFIG_ELTAN_SEABIOS_TAG="rel-1.11.0.4"
CONFIG_SEABIOS_SERIAL_CONSOLE=y
# CONFIG_SKIP_PXE_LOAD is not set
# CONFIG_SEABIOS_THREAD_OPTIONROMS is not set
CONFIG_SEABIOS_MALLOC_UPPERMEMORY=y
CONFIG_PAYLOAD_FILE="payloads/external/SeaBIOS/seabios/out/bios.bin.elf"
CONFIG_COMPRESSED_PAYLOAD_LZMA=y
CONFIG_SORTBOOTORDER=y
CONFIG_PXE=y

#
# PXE Options
#
# CONFIG_PXE_ROM is not set
CONFIG_BUILD_IPXE=y
# CONFIG_IPXE_STABLE is not set
CONFIG_IPXE_MASTER=y
# CONFIG_PXE_SERIAL_CONSOLE is not set
CONFIG_PXE_ROM_ID="8086,1539"
CONFIG_PXE_CUSTOM_GENERAL_H="../../../../apu2-documentation/ipxe/general.h"
CONFIG_PXE_CUSTOM_BOOTMENU_FILE="../../../../apu2-documentation/ipxe/menu.ipxe"

#
# Debugging
Expand All @@ -411,6 +442,7 @@ CONFIG_SORTBOOTORDER=y
# CONFIG_HAVE_DEBUG_SMBUS is not set
# CONFIG_DEBUG_MALLOC is not set
# CONFIG_DEBUG_ACPI is not set
# CONFIG_DEBUG_SPI_FLASH is not set
# CONFIG_TRACE is not set
# CONFIG_ENABLE_APIC_EXT_ID is not set
CONFIG_WARNINGS_ARE_ERRORS=y
Expand Down
4 changes: 2 additions & 2 deletions payloads/external/SeaBIOS/Kconfig
Expand Up @@ -23,7 +23,7 @@ choice
depends on PAYLOAD_SEABIOS

config SEABIOS_STABLE
bool "Stable version (1.11.0.3 for std)"
bool "Stable version (1.11.0.4 for std)"
help
Stable SeaBIOS version

Expand All @@ -39,7 +39,7 @@ config ELTAN_SEABIOS_TAG
depends on SEABIOS_ELTAN
depends on SEABIOS_STABLE
string "SeaBIOS TAG"
default "rel-1.11.0.3"
default "rel-1.11.0.4"
help
Specify the SeaBIOS tag to check out

Expand Down
26 changes: 24 additions & 2 deletions src/Kconfig
Expand Up @@ -342,6 +342,29 @@ config BOOTMODE_STRAPS

source src/console/Kconfig

config BOOT_DEVICE_NOT_SPI_FLASH
bool
default n

config BOOT_DEVICE_SPI_FLASH
bool
default y if !BOOT_DEVICE_NOT_SPI_FLASH
default n

config BOOT_DEVICE_MEMORY_MAPPED
bool
default y if ARCH_X86 && BOOT_DEVICE_SPI_FLASH
default n
help
Inform system if SPI is memory-mapped or not.

config BOOT_DEVICE_SUPPORTS_WRITES
bool
default n
help
Indicate that the platform has writable boot device
support.

config HAVE_ACPI_RESUME
bool
default n
Expand Down Expand Up @@ -752,7 +775,7 @@ config LINUX_INITRD

config SORTBOOTORDER
bool "sortbootorder"
depends on BOARD_PCENGINES_APU2 || BOARD_PCENGINES_APU3 || BOARD_PCENGINES_APU5
depends on BOARD_PCENGINES_APU2 || BOARD_PCENGINES_APU3 || BOARD_PCENGINES_APU4 || BOARD_PCENGINES_APU5
default y
help
APU series setup utility
Expand Down Expand Up @@ -1170,4 +1193,3 @@ config VBOOT_VERIFY_FIRMWARE

config CHROMEOS
bool

14 changes: 6 additions & 8 deletions src/cpu/amd/pi/spi.c
Expand Up @@ -25,7 +25,7 @@

void spi_SaveS3info(u32 pos, u32 size, u8 *buf, u32 len)
{
struct spi_flash *flash;
const struct spi_flash *flash;

spi_init();
flash = spi_flash_probe(0, 0);
Expand All @@ -35,15 +35,13 @@ void spi_SaveS3info(u32 pos, u32 size, u8 *buf, u32 len)
return;
}

flash->spi->rw = SPI_WRITE_FLAG;
spi_claim_bus(flash->spi);
spi_claim_bus(&(flash->spi));

flash->erase(flash, pos, size);
flash->write(flash, pos, sizeof(len), &len);
flash->write(flash, pos + sizeof(len), len, buf);
flash->internal_erase(flash, pos, size);
flash->internal_write(flash, pos, sizeof(len), &len);
flash->internal_write(flash, pos + sizeof(len), len, buf);

flash->spi->rw = SPI_WRITE_FLAG;
spi_release_bus(flash->spi);
spi_release_bus(&(flash->spi));

return;
}
69 changes: 44 additions & 25 deletions src/drivers/spi/Kconfig
Expand Up @@ -12,36 +12,45 @@
## 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 St, Fifth Floor, Boston, MA 02110-1301 USA
##

config SPI_FLASH
bool
default y if BOOT_DEVICE_SPI_FLASH && BOOT_DEVICE_SUPPORTS_WRITES
default n
help
Select this option if your chipset driver needs to store certain
data in the SPI flash.

if SPI_FLASH

config SPI_ATOMIC_SEQUENCING
# Keep at 0 because lots of boards assume this default.
config BOOT_DEVICE_SPI_FLASH_BUS
int
default 0
help
Which SPI bus the boot device is connected to.

config BOOT_DEVICE_SPI_FLASH_RW_NOMMAP
bool
default y if ARCH_X86
default n if !ARCH_X86
default y if !COMMON_CBFS_SPI_WRAPPER
default n
depends on BOOT_DEVICE_SPI_FLASH
help
Select this option if the SPI controller uses "atomic sequencing."
Atomic sequencing is when the sequence of commands is pre-programmed
in the SPI controller. Hardware manages the transaction instead of
software. This is common on x86 platforms.
Provide common implementation of the RW boot device that
doesn't provide mmap() operations.

config SPI_FLASH_MEMORY_MAPPED
config BOOT_DEVICE_SPI_FLASH_RW_NOMMAP_EARLY
bool
default y if ARCH_X86
default n if !ARCH_X86
default n
depends on BOOT_DEVICE_SPI_FLASH_RW_NOMMAP
help
Inform system if SPI is memory-mapped or not.
Include the common implementation in all stages, including the
early ones.

config SPI_FLASH_INCLUDE_ALL_DRIVERS
bool
default n if COMMON_CBFS_SPI_WRAPPER
default y

config SPI_FLASH_SMM
bool "SPI flash driver support in SMM"
Expand All @@ -59,70 +68,70 @@ config SPI_FLASH_NO_FAST_READ

config SPI_FLASH_ADESTO
bool
default y if !COMMON_CBFS_SPI_WRAPPER
default y if SPI_FLASH_INCLUDE_ALL_DRIVERS
help
Select this option if your chipset driver needs to store certain
data in the SPI flash and your SPI flash is made by Adesto Technologies.

config SPI_FLASH_AMIC
bool
default y if !COMMON_CBFS_SPI_WRAPPER
default y if SPI_FLASH_INCLUDE_ALL_DRIVERS
help
Select this option if your chipset driver needs to store certain
data in the SPI flash and your SPI flash is made by AMIC.

config SPI_FLASH_ATMEL
bool
default y if !COMMON_CBFS_SPI_WRAPPER
default y if SPI_FLASH_INCLUDE_ALL_DRIVERS
help
Select this option if your chipset driver needs to store certain
data in the SPI flash and your SPI flash is made by Atmel.

config SPI_FLASH_EON
bool
default y if !COMMON_CBFS_SPI_WRAPPER
default y if SPI_FLASH_INCLUDE_ALL_DRIVERS
help
Select this option if your chipset driver needs to store certain
data in the SPI flash and your SPI flash is made by EON.

config SPI_FLASH_GIGADEVICE
bool
default y if !COMMON_CBFS_SPI_WRAPPER
default y if SPI_FLASH_INCLUDE_ALL_DRIVERS
help
Select this option if your chipset driver needs to store certain
data in the SPI flash and your SPI flash is made by Gigadevice.

config SPI_FLASH_MACRONIX
bool
default y if !COMMON_CBFS_SPI_WRAPPER
default y if SPI_FLASH_INCLUDE_ALL_DRIVERS
help
Select this option if your chipset driver needs to store certain
data in the SPI flash and your SPI flash is made by Macronix.

config SPI_FLASH_SPANSION
bool
default y if !COMMON_CBFS_SPI_WRAPPER
default y if SPI_FLASH_INCLUDE_ALL_DRIVERS
help
Select this option if your chipset driver needs to store certain
data in the SPI flash and your SPI flash is made by Spansion.

config SPI_FLASH_SST
bool
default y if !COMMON_CBFS_SPI_WRAPPER
default y if SPI_FLASH_INCLUDE_ALL_DRIVERS
help
Select this option if your chipset driver needs to store certain
data in the SPI flash and your SPI flash is made by SST.

config SPI_FLASH_STMICRO
bool
default y if !COMMON_CBFS_SPI_WRAPPER
default y if SPI_FLASH_INCLUDE_ALL_DRIVERS
help
Select this option if your chipset driver needs to store certain
data in the SPI flash and your SPI flash is made by ST MICRO.

config SPI_FLASH_WINBOND
bool
default y if !COMMON_CBFS_SPI_WRAPPER
default y if SPI_FLASH_INCLUDE_ALL_DRIVERS
help
Select this option if your chipset driver needs to store certain
data in the SPI flash and your SPI flash is made by Winbond.
Expand All @@ -136,4 +145,14 @@ config SPI_FLASH_FAST_READ_DUAL_OUTPUT_3B
output command (opcode 0x3b) where the opcode and address are sent
to the chip on MOSI and data is received on both MOSI and MISO.

config SPI_FLASH_HAS_VOLATILE_GROUP
bool
default n
help
Allows chipset to group write/erase operations under a single volatile
group.

endif # SPI_FLASH

config HAVE_SPI_CONSOLE_SUPPORT
def_bool n
30 changes: 27 additions & 3 deletions src/drivers/spi/Makefile.inc
@@ -1,7 +1,12 @@
# SPI flash driver interface

ifeq ($(CONFIG_COMMON_CBFS_SPI_WRAPPER),y)
bootblock-y += spi_flash.c

bootblock-y += spi-generic.c
bootblock-$(CONFIG_SPI_FLASH) += spi_flash.c
bootblock-$(CONFIG_SPI_FLASH_ADESTO) += adesto.c
bootblock-$(CONFIG_SPI_FLASH_AMIC) += amic.c
bootblock-$(CONFIG_SPI_FLASH_ATMEL) += atmel.c
bootblock-$(CONFIG_SPI_FLASH_EON) += eon.c
bootblock-$(CONFIG_SPI_FLASH_GIGADEVICE) += gigadevice.c
bootblock-$(CONFIG_SPI_FLASH_MACRONIX) += macronix.c
Expand All @@ -11,7 +16,11 @@ bootblock-$(CONFIG_SPI_FLASH_STMICRO) += stmicro.c
bootblock-$(CONFIG_SPI_FLASH_WINBOND) += winbond.c
bootblock-$(CONFIG_SPI_FRAM_RAMTRON) += ramtron.c

romstage-y += spi-generic.c
romstage-$(CONFIG_SPI_FLASH) += spi_flash.c
romstage-$(CONFIG_SPI_FLASH_ADESTO) += adesto.c
romstage-$(CONFIG_SPI_FLASH_AMIC) += amic.c
romstage-$(CONFIG_SPI_FLASH_ATMEL) += atmel.c
romstage-$(CONFIG_SPI_FLASH_EON) += eon.c
romstage-$(CONFIG_SPI_FLASH_GIGADEVICE) += gigadevice.c
romstage-$(CONFIG_SPI_FLASH_MACRONIX) += macronix.c
Expand All @@ -20,11 +29,25 @@ romstage-$(CONFIG_SPI_FLASH_SST) += sst.c
romstage-$(CONFIG_SPI_FLASH_STMICRO) += stmicro.c
romstage-$(CONFIG_SPI_FLASH_WINBOND) += winbond.c
romstage-$(CONFIG_SPI_FRAM_RAMTRON) += ramtron.c

endif

ramstage-$(CONFIG_SPI_FLASH) += spi_flash.c
verstage-y += spi-generic.c
verstage-$(CONFIG_SPI_FLASH) += spi_flash.c
verstage-$(CONFIG_SPI_FLASH_ADESTO) += adesto.c
verstage-$(CONFIG_SPI_FLASH_AMIC) += amic.c
verstage-$(CONFIG_SPI_FLASH_ATMEL) += atmel.c
verstage-$(CONFIG_SPI_FLASH_EON) += eon.c
verstage-$(CONFIG_SPI_FLASH_GIGADEVICE) += gigadevice.c
verstage-$(CONFIG_SPI_FLASH_MACRONIX) += macronix.c
verstage-$(CONFIG_SPI_FLASH_SPANSION) += spansion.c
verstage-$(CONFIG_SPI_FLASH_SST) += sst.c
verstage-$(CONFIG_SPI_FLASH_STMICRO) += stmicro.c
verstage-$(CONFIG_SPI_FLASH_WINBOND) += winbond.c
verstage-$(CONFIG_SPI_FRAM_RAMTRON) += ramtron.c

# drivers
ramstage-y += spi-generic.c
ramstage-$(CONFIG_SPI_FLASH) += spi_flash.c
ramstage-$(CONFIG_SPI_FLASH_ADESTO) += adesto.c
ramstage-$(CONFIG_SPI_FLASH_AMIC) += amic.c
ramstage-$(CONFIG_SPI_FLASH_ATMEL) += atmel.c
Expand All @@ -38,6 +61,7 @@ ramstage-$(CONFIG_SPI_FLASH_WINBOND) += winbond.c
ramstage-$(CONFIG_SPI_FRAM_RAMTRON) += ramtron.c

ifeq ($(CONFIG_SPI_FLASH_SMM),y)
smm-y += spi-generic.c
# SPI flash driver interface
smm-$(CONFIG_SPI_FLASH) += spi_flash.c

Expand Down
40 changes: 15 additions & 25 deletions src/drivers/spi/adesto.c
Expand Up @@ -10,8 +10,11 @@
* Licensed under the GPL-2 or later.
*/

#include <console/console.h>
#include <stdlib.h>
#include <string.h>
#include <spi_flash.h>
#include <spi-generic.h>

#include "spi_flash_internal.h"

Expand Down Expand Up @@ -46,7 +49,7 @@ struct adesto_spi_flash {
};

static inline struct adesto_spi_flash *
to_adesto_spi_flash(struct spi_flash *flash)
to_adesto_spi_flash(const struct spi_flash *flash)
{
return container_of(flash, struct adesto_spi_flash, flash);
}
Expand Down Expand Up @@ -78,8 +81,8 @@ static const struct adesto_spi_flash_params adesto_spi_flash_table[] = {
},
};

static int adesto_write(struct spi_flash *flash,
u32 offset, size_t len, const void *buf)
static int adesto_write(const struct spi_flash *flash, u32 offset, size_t len,
const void *buf)
{
struct adesto_spi_flash *stm = to_adesto_spi_flash(flash);
unsigned long byte_addr;
Expand All @@ -90,16 +93,9 @@ static int adesto_write(struct spi_flash *flash,
u8 cmd[4];

page_size = 1 << stm->params->l2_page_size;
byte_addr = offset % page_size;

flash->spi->rw = SPI_WRITE_FLAG;
ret = spi_claim_bus(flash->spi);
if (ret) {
printk(BIOS_WARNING, "SF: Unable to claim SPI bus\n");
return ret;
}

for (actual = 0; actual < len; actual += chunk_len) {
byte_addr = offset % page_size;
chunk_len = min(len - actual, page_size - byte_addr);
chunk_len = spi_crop_chunk(sizeof(cmd), chunk_len);

Expand All @@ -113,13 +109,13 @@ static int adesto_write(struct spi_flash *flash,
cmd[0], cmd[1], cmd[2], cmd[3], chunk_len);
#endif

ret = spi_flash_cmd(flash->spi, CMD_AT25DF_WREN, NULL, 0);
ret = spi_flash_cmd(&flash->spi, CMD_AT25DF_WREN, NULL, 0);
if (ret < 0) {
printk(BIOS_WARNING, "SF: Enabling Write failed\n");
goto out;
}

ret = spi_flash_cmd_write(flash->spi, cmd, sizeof(cmd),
ret = spi_flash_cmd_write(&flash->spi, cmd, sizeof(cmd),
buf + actual, chunk_len);
if (ret < 0) {
printk(BIOS_WARNING, "SF: adesto Page Program failed\n");
Expand All @@ -131,7 +127,6 @@ static int adesto_write(struct spi_flash *flash,
goto out;

offset += chunk_len;
byte_addr = 0;
}

#if CONFIG_DEBUG_SPI_FLASH
Expand All @@ -141,15 +136,9 @@ static int adesto_write(struct spi_flash *flash,
ret = 0;

out:
spi_release_bus(flash->spi);
return ret;
}

static int adesto_erase(struct spi_flash *flash, u32 offset, size_t len)
{
return spi_flash_cmd_erase(flash, CMD_AT25DF_SE, offset, len);
}

struct spi_flash *spi_flash_probe_adesto(struct spi_slave *spi, u8 *idcode)
{
const struct adesto_spi_flash_params *params;
Expand All @@ -176,24 +165,25 @@ struct spi_flash *spi_flash_probe_adesto(struct spi_slave *spi, u8 *idcode)
}

stm->params = params;
stm->flash.spi = spi;
memcpy(&stm->flash.spi, spi, sizeof(*spi));
stm->flash.name = params->name;

/* Assuming power-of-two page size initially. */
page_size = 1 << params->l2_page_size;

stm->flash.write = adesto_write;
stm->flash.erase = adesto_erase;
stm->flash.internal_write = adesto_write;
stm->flash.internal_erase = spi_flash_cmd_erase;
#if CONFIG_SPI_FLASH_NO_FAST_READ
stm->flash.read = spi_flash_cmd_read_slow;
stm->flash.internal_read = spi_flash_cmd_read_slow;
#else
stm->flash.read = spi_flash_cmd_read_fast;
stm->flash.internal_read = spi_flash_cmd_read_fast;
#endif
stm->flash.sector_size = (1 << stm->params->l2_page_size) *
stm->params->pages_per_sector;
stm->flash.size = page_size * params->pages_per_sector
* params->sectors_per_block
* params->nr_blocks;
stm->flash.erase_cmd = CMD_AT25DF_SE;

return &stm->flash;
}
37 changes: 14 additions & 23 deletions src/drivers/spi/amic.c
Expand Up @@ -8,8 +8,11 @@
* Licensed under the GPL-2 or later.
*/

#include <console/console.h>
#include <stdlib.h>
#include <spi_flash.h>
#include <spi-generic.h>
#include <string.h>

#include "spi_flash_internal.h"

Expand Down Expand Up @@ -44,7 +47,7 @@ struct amic_spi_flash {
};

static inline struct amic_spi_flash *
to_amic_spi_flash(struct spi_flash *flash)
to_amic_spi_flash(const struct spi_flash *flash)
{
return container_of(flash, struct amic_spi_flash, flash);
}
Expand All @@ -60,8 +63,8 @@ static const struct amic_spi_flash_params amic_spi_flash_table[] = {
},
};

static int amic_write(struct spi_flash *flash,
u32 offset, size_t len, const void *buf)
static int amic_write(const struct spi_flash *flash, u32 offset, size_t len,
const void *buf)
{
struct amic_spi_flash *amic = to_amic_spi_flash(flash);
unsigned long byte_addr;
Expand All @@ -74,13 +77,6 @@ static int amic_write(struct spi_flash *flash,
page_size = 1 << amic->params->l2_page_size;
byte_addr = offset % page_size;

flash->spi->rw = SPI_WRITE_FLAG;
ret = spi_claim_bus(flash->spi);
if (ret) {
printk(BIOS_WARNING, "SF: Unable to claim SPI bus\n");
return ret;
}

for (actual = 0; actual < len; actual += chunk_len) {
chunk_len = min(len - actual, page_size - byte_addr);
chunk_len = spi_crop_chunk(sizeof(cmd), chunk_len);
Expand All @@ -95,13 +91,13 @@ static int amic_write(struct spi_flash *flash,
cmd[0], cmd[1], cmd[2], cmd[3], chunk_len);
#endif

ret = spi_flash_cmd(flash->spi, CMD_A25_WREN, NULL, 0);
ret = spi_flash_cmd(&flash->spi, CMD_A25_WREN, NULL, 0);
if (ret < 0) {
printk(BIOS_WARNING, "SF: Enabling Write failed\n");
goto out;
}

ret = spi_flash_cmd_write(flash->spi, cmd, sizeof(cmd),
ret = spi_flash_cmd_write(&flash->spi, cmd, sizeof(cmd),
buf + actual, chunk_len);
if (ret < 0) {
printk(BIOS_WARNING, "SF: AMIC Page Program failed\n");
Expand All @@ -123,15 +119,9 @@ static int amic_write(struct spi_flash *flash,
ret = 0;

out:
spi_release_bus(flash->spi);
return ret;
}

static int amic_erase(struct spi_flash *flash, u32 offset, size_t len)
{
return spi_flash_cmd_erase(flash, CMD_A25_SE, offset, len);
}

struct spi_flash *spi_flash_probe_amic(struct spi_slave *spi, u8 *idcode)
{
const struct amic_spi_flash_params *params;
Expand All @@ -158,24 +148,25 @@ struct spi_flash *spi_flash_probe_amic(struct spi_slave *spi, u8 *idcode)
}

amic->params = params;
amic->flash.spi = spi;
memcpy(&amic->flash.spi, spi, sizeof(*spi));
amic->flash.name = params->name;

/* Assuming power-of-two page size initially. */
page_size = 1 << params->l2_page_size;

amic->flash.write = amic_write;
amic->flash.erase = amic_erase;
amic->flash.internal_write = amic_write;
amic->flash.internal_erase = spi_flash_cmd_erase;
#if CONFIG_SPI_FLASH_NO_FAST_READ
amic->flash.read = spi_flash_cmd_read_slow;
amic->flash.internal_read = spi_flash_cmd_read_slow;
#else
amic->flash.read = spi_flash_cmd_read_fast;
amic->flash.internal_read = spi_flash_cmd_read_fast;
#endif
amic->flash.sector_size = (1 << amic->params->l2_page_size) *
amic->params->pages_per_sector;
amic->flash.size = page_size * params->pages_per_sector
* params->sectors_per_block
* params->nr_blocks;
amic->flash.erase_cmd = CMD_A25_SE;

return &amic->flash;
}
41 changes: 16 additions & 25 deletions src/drivers/spi/atmel.c
Expand Up @@ -6,8 +6,12 @@
* Licensed under the GPL-2 or later.
*/

#include <console/console.h>
#include <stdlib.h>
#include <spi_flash.h>
#include <spi-generic.h>
#include <string.h>

#include "spi_flash_internal.h"

/* M25Pxx-specific commands */
Expand Down Expand Up @@ -41,7 +45,7 @@ struct atmel_spi_flash {
};

static inline struct atmel_spi_flash *
to_atmel_spi_flash(struct spi_flash *flash)
to_atmel_spi_flash(const struct spi_flash *flash)
{
return container_of(flash, struct atmel_spi_flash, flash);
}
Expand Down Expand Up @@ -105,8 +109,8 @@ static const struct atmel_spi_flash_params atmel_spi_flash_table[] = {
},
};

static int atmel_write(struct spi_flash *flash,
u32 offset, size_t len, const void *buf)
static int atmel_write(const struct spi_flash *flash, u32 offset, size_t len,
const void *buf)
{
struct atmel_spi_flash *stm = to_atmel_spi_flash(flash);
unsigned long byte_addr;
Expand All @@ -117,16 +121,9 @@ static int atmel_write(struct spi_flash *flash,
u8 cmd[4];

page_size = 1 << stm->params->l2_page_size;
byte_addr = offset % page_size;

flash->spi->rw = SPI_WRITE_FLAG;
ret = spi_claim_bus(flash->spi);
if (ret) {
printk(BIOS_WARNING, "SF: Unable to claim SPI bus\n");
return ret;
}

for (actual = 0; actual < len; actual += chunk_len) {
byte_addr = offset % page_size;
chunk_len = min(len - actual, page_size - byte_addr);
chunk_len = spi_crop_chunk(sizeof(cmd), chunk_len);

Expand All @@ -140,13 +137,13 @@ static int atmel_write(struct spi_flash *flash,
cmd[0], cmd[1], cmd[2], cmd[3], chunk_len);
#endif

ret = spi_flash_cmd(flash->spi, CMD_AT25_WREN, NULL, 0);
ret = spi_flash_cmd(&flash->spi, CMD_AT25_WREN, NULL, 0);
if (ret < 0) {
printk(BIOS_WARNING, "SF: Enabling Write failed\n");
goto out;
}

ret = spi_flash_cmd_write(flash->spi, cmd, sizeof(cmd),
ret = spi_flash_cmd_write(&flash->spi, cmd, sizeof(cmd),
buf + actual, chunk_len);
if (ret < 0) {
printk(BIOS_WARNING, "SF: Atmel Page Program failed\n");
Expand All @@ -158,7 +155,6 @@ static int atmel_write(struct spi_flash *flash,
goto out;

offset += chunk_len;
byte_addr = 0;
}

#if CONFIG_DEBUG_SPI_FLASH
Expand All @@ -168,15 +164,9 @@ static int atmel_write(struct spi_flash *flash,
ret = 0;

out:
spi_release_bus(flash->spi);
return ret;
}

static int atmel_erase(struct spi_flash *flash, u32 offset, size_t len)
{
return spi_flash_cmd_erase(flash, CMD_AT25_SE, offset, len);
}

struct spi_flash *spi_flash_probe_atmel(struct spi_slave *spi, u8 *idcode)
{
const struct atmel_spi_flash_params *params;
Expand All @@ -203,24 +193,25 @@ struct spi_flash *spi_flash_probe_atmel(struct spi_slave *spi, u8 *idcode)
}

stm->params = params;
stm->flash.spi = spi;
memcpy(&stm->flash.spi, spi, sizeof(*spi));
stm->flash.name = params->name;

/* Assuming power-of-two page size initially. */
page_size = 1 << params->l2_page_size;

stm->flash.write = atmel_write;
stm->flash.erase = atmel_erase;
stm->flash.internal_write = atmel_write;
stm->flash.internal_erase = spi_flash_cmd_erase;
#if CONFIG_SPI_FLASH_NO_FAST_READ
stm->flash.read = spi_flash_cmd_read_slow;
stm->flash.internal_read = spi_flash_cmd_read_slow;
#else
stm->flash.read = spi_flash_cmd_read_fast;
stm->flash.internal_read = spi_flash_cmd_read_fast;
#endif
stm->flash.sector_size = (1 << stm->params->l2_page_size) *
stm->params->pages_per_sector;
stm->flash.size = page_size * params->pages_per_sector
* params->sectors_per_block
* params->nr_blocks;
stm->flash.erase_cmd = CMD_AT25_SE;

return &stm->flash;
}
33 changes: 16 additions & 17 deletions src/drivers/spi/eon.c
Expand Up @@ -6,8 +6,11 @@
* Licensed under the GPL-2 or later.
*/

#include <console/console.h>
#include <stdlib.h>
#include <spi_flash.h>
#include <spi-generic.h>
#include <string.h>

#include "spi_flash_internal.h"

Expand Down Expand Up @@ -43,7 +46,8 @@ struct eon_spi_flash {
const struct eon_spi_flash_params *params;
};

static inline struct eon_spi_flash *to_eon_spi_flash(struct spi_flash *flash)
static inline
struct eon_spi_flash *to_eon_spi_flash(const struct spi_flash *flash)
{
return container_of(flash, struct eon_spi_flash, flash);
}
Expand Down Expand Up @@ -75,7 +79,7 @@ static const struct eon_spi_flash_params eon_spi_flash_table[] = {
},
};

static int eon_write(struct spi_flash *flash,
static int eon_write(const struct spi_flash *flash,
u32 offset, size_t len, const void *buf)
{
struct eon_spi_flash *eon = to_eon_spi_flash(flash);
Expand All @@ -87,15 +91,13 @@ static int eon_write(struct spi_flash *flash,
u8 cmd[4];

page_size = 1 << eon->params->page_size;
byte_addr = offset % page_size;

flash->spi->rw = SPI_WRITE_FLAG;

for (actual = 0; actual < len; actual += chunk_len) {
byte_addr = offset % page_size;
chunk_len = min(len - actual, page_size - byte_addr);
chunk_len = spi_crop_chunk(sizeof(cmd), chunk_len);

ret = spi_flash_cmd(flash->spi, CMD_EN25_WREN, NULL, 0);
ret = spi_flash_cmd(&flash->spi, CMD_EN25_WREN, NULL, 0);
if (ret < 0) {
printk(BIOS_WARNING, "SF: Enabling Write failed\n");
goto out;
Expand All @@ -112,7 +114,7 @@ static int eon_write(struct spi_flash *flash,
buf + actual, cmd[0], cmd[1], cmd[2], cmd[3], chunk_len);
#endif

ret = spi_flash_cmd_write(flash->spi, cmd, sizeof(cmd),
ret = spi_flash_cmd_write(&flash->spi, cmd, sizeof(cmd),
buf + actual, chunk_len);
if (ret < 0) {
printk(BIOS_WARNING, "SF: EON Page Program failed\n");
Expand All @@ -126,7 +128,6 @@ static int eon_write(struct spi_flash *flash,
}

offset += chunk_len;
byte_addr = 0;
}

#if CONFIG_DEBUG_SPI_FLASH
Expand All @@ -138,11 +139,6 @@ static int eon_write(struct spi_flash *flash,
return ret;
}

static int eon_erase(struct spi_flash *flash, u32 offset, size_t len)
{
return spi_flash_cmd_erase(flash, CMD_EN25_SE, offset, len);
}

struct spi_flash *spi_flash_probe_eon(struct spi_slave *spi, u8 *idcode)
{
const struct eon_spi_flash_params *params;
Expand All @@ -168,15 +164,18 @@ struct spi_flash *spi_flash_probe_eon(struct spi_slave *spi, u8 *idcode)
}

eon->params = params;
eon->flash.spi = spi;
memcpy(&eon->flash.spi, spi, sizeof(*spi));
eon->flash.name = params->name;

eon->flash.write = eon_write;
eon->flash.erase = eon_erase;
eon->flash.read = spi_flash_cmd_read_fast;
eon->flash.internal_write = eon_write;
eon->flash.internal_erase = spi_flash_cmd_erase;
eon->flash.internal_status = spi_flash_cmd_status;
eon->flash.internal_read = spi_flash_cmd_read_fast;
eon->flash.sector_size = params->page_size * params->pages_per_sector;
eon->flash.size = params->page_size * params->pages_per_sector
* params->nr_sectors;
eon->flash.erase_cmd = CMD_EN25_SE;
eon->flash.status_cmd = CMD_EN25_RDSR;

return &eon->flash;
}
75 changes: 33 additions & 42 deletions src/drivers/spi/gigadevice.c
Expand Up @@ -6,9 +6,6 @@
* Copyright 2008, Network Appliance Inc.
* Jason McMullan <mcmullan@netapp.com>
*
* See file CREDITS for list of people who contributed to this
* project.
*
* This program 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
Expand All @@ -18,16 +15,13 @@
* 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-1301 USA
*/


#include <console/console.h>
#include <stdlib.h>
#include <spi_flash.h>
#include <spi-generic.h>
#include <string.h>

#include "spi_flash_internal.h"

Expand Down Expand Up @@ -62,7 +56,7 @@ struct gigadevice_spi_flash {
};

static inline struct gigadevice_spi_flash *
to_gigadevice_spi_flash(struct spi_flash *flash)
to_gigadevice_spi_flash(const struct spi_flash *flash)
{
return container_of(flash, struct gigadevice_spi_flash, flash);
}
Expand Down Expand Up @@ -106,7 +100,15 @@ static const struct gigadevice_spi_flash_params gigadevice_spi_flash_table[] = {
.pages_per_sector = 16,
.sectors_per_block = 16,
.nr_blocks = 128,
.name = "GD25Q64(B)",
.name = "GD25Q64B/GD25B64C",
},
{
.id = 0x6017,
.l2_page_size = 8,
.pages_per_sector = 16,
.sectors_per_block = 16,
.nr_blocks = 128,
.name = "GD25LQ64C/GD25LB64C",
},
{
.id = 0x4018,
Expand All @@ -118,8 +120,8 @@ static const struct gigadevice_spi_flash_params gigadevice_spi_flash_table[] = {
},
};

static int gigadevice_write(struct spi_flash *flash, u32 offset,
size_t len, const void *buf)
static int gigadevice_write(const struct spi_flash *flash, u32 offset,
size_t len, const void *buf)
{
struct gigadevice_spi_flash *stm = to_gigadevice_spi_flash(flash);
unsigned long byte_addr;
Expand All @@ -130,15 +132,13 @@ static int gigadevice_write(struct spi_flash *flash, u32 offset,
u8 cmd[4];

page_size = 1 << stm->params->l2_page_size;
byte_addr = offset % page_size;

flash->spi->rw = SPI_WRITE_FLAG;

for (actual = 0; actual < len; actual += chunk_len) {
byte_addr = offset % page_size;
chunk_len = min(len - actual, page_size - byte_addr);
chunk_len = spi_crop_chunk(sizeof(cmd), chunk_len);

ret = spi_flash_cmd(flash->spi, CMD_GD25_WREN, NULL, 0);
ret = spi_flash_cmd(&flash->spi, CMD_GD25_WREN, NULL, 0);
if (ret < 0) {
printk(BIOS_WARNING,
"SF gigadevice.c: Enabling Write failed\n");
Expand All @@ -156,7 +156,7 @@ static int gigadevice_write(struct spi_flash *flash, u32 offset,
cmd[0], cmd[1], cmd[2], cmd[3], chunk_len);
#endif

ret = spi_flash_cmd_write(flash->spi, cmd, sizeof(cmd),
ret = spi_flash_cmd_write(&flash->spi, cmd, sizeof(cmd),
buf + actual, chunk_len);
if (ret < 0) {
printk(BIOS_WARNING,
Expand All @@ -169,7 +169,6 @@ static int gigadevice_write(struct spi_flash *flash, u32 offset,
goto out;

offset += chunk_len;
byte_addr = 0;
}

#if CONFIG_DEBUG_SPI_FLASH
Expand All @@ -184,16 +183,12 @@ static int gigadevice_write(struct spi_flash *flash, u32 offset,
return ret;
}

static int gigadevice_erase(struct spi_flash *flash, u32 offset, size_t len)
{
return spi_flash_cmd_erase(flash, CMD_GD25_SE, offset, len);
}
static struct gigadevice_spi_flash stm;

struct spi_flash *spi_flash_probe_gigadevice(struct spi_slave *spi, u8 *idcode)
{
const struct gigadevice_spi_flash_params *params;
unsigned page_size;
struct gigadevice_spi_flash *stm;
unsigned int i;

for (i = 0; i < ARRAY_SIZE(gigadevice_spi_flash_table); i++) {
Expand All @@ -209,32 +204,28 @@ struct spi_flash *spi_flash_probe_gigadevice(struct spi_slave *spi, u8 *idcode)
return NULL;
}

stm = malloc(sizeof(struct gigadevice_spi_flash));
if (!stm) {
printk(BIOS_WARNING,
"SF gigadevice.c: Failed to allocate memory\n");
return NULL;
}

stm->params = params;
stm->flash.spi = spi;
stm->flash.name = params->name;
stm.params = params;
memcpy(&stm.flash.spi, spi, sizeof(*spi));
stm.flash.name = params->name;

/* Assuming power-of-two page size initially. */
page_size = 1 << params->l2_page_size;

stm->flash.write = gigadevice_write;
stm->flash.erase = gigadevice_erase;
stm.flash.internal_write = gigadevice_write;
stm.flash.internal_erase = spi_flash_cmd_erase;
stm.flash.internal_status = spi_flash_cmd_status;
#if CONFIG_SPI_FLASH_NO_FAST_READ
stm->flash.read = spi_flash_cmd_read_slow;
stm.flash.internal_read = spi_flash_cmd_read_slow;
#else
stm->flash.read = spi_flash_cmd_read_fast;
stm.flash.internal_read = spi_flash_cmd_read_fast;
#endif
stm->flash.sector_size = (1 << stm->params->l2_page_size) *
stm->params->pages_per_sector;
stm->flash.size = page_size * params->pages_per_sector
stm.flash.sector_size = (1 << stm.params->l2_page_size) *
stm.params->pages_per_sector;
stm.flash.size = page_size * params->pages_per_sector
* params->sectors_per_block
* params->nr_blocks;
stm.flash.erase_cmd = CMD_GD25_SE;
stm.flash.status_cmd = CMD_GD25_RDSR;

return &stm->flash;
return &stm.flash;
}
63 changes: 24 additions & 39 deletions src/drivers/spi/macronix.c
Expand Up @@ -10,9 +10,6 @@
* Copyright (C) 2004-2007 Freescale Semiconductor, Inc.
* TsiChung Liew (Tsi-Chung.Liew@freescale.com)
*
* See file CREDITS for list of people who contributed to this
* project.
*
* This program 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
Expand All @@ -22,15 +19,13 @@
* 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-1301 USA
*/

#include <console/console.h>
#include <stdlib.h>
#include <spi_flash.h>
#include <spi-generic.h>
#include <string.h>

#include "spi_flash_internal.h"

Expand Down Expand Up @@ -64,8 +59,8 @@ struct macronix_spi_flash {
const struct macronix_spi_flash_params *params;
};

static inline struct macronix_spi_flash *to_macronix_spi_flash(struct spi_flash
*flash)
static inline
struct macronix_spi_flash *to_macronix_spi_flash(const struct spi_flash *flash)
{
return container_of(flash, struct macronix_spi_flash, flash);
}
Expand Down Expand Up @@ -153,8 +148,8 @@ static const struct macronix_spi_flash_params macronix_spi_flash_table[] = {
},
};

static int macronix_write(struct spi_flash *flash,
u32 offset, size_t len, const void *buf)
static int macronix_write(const struct spi_flash *flash, u32 offset, size_t len,
const void *buf)
{
struct macronix_spi_flash *mcx = to_macronix_spi_flash(flash);
unsigned long byte_addr;
Expand All @@ -165,11 +160,9 @@ static int macronix_write(struct spi_flash *flash,
u8 cmd[4];

page_size = mcx->params->page_size;
byte_addr = offset % page_size;

flash->spi->rw = SPI_WRITE_FLAG;

for (actual = 0; actual < len; actual += chunk_len) {
byte_addr = offset % page_size;
chunk_len = min(len - actual, page_size - byte_addr);
chunk_len = spi_crop_chunk(sizeof(cmd), chunk_len);

Expand All @@ -183,13 +176,13 @@ static int macronix_write(struct spi_flash *flash,
buf + actual, cmd[0], cmd[1], cmd[2], cmd[3], chunk_len);
#endif

ret = spi_flash_cmd(flash->spi, CMD_MX25XX_WREN, NULL, 0);
ret = spi_flash_cmd(&flash->spi, CMD_MX25XX_WREN, NULL, 0);
if (ret < 0) {
printk(BIOS_WARNING, "SF: Enabling Write failed\n");
break;
}

ret = spi_flash_cmd_write(flash->spi, cmd, sizeof(cmd),
ret = spi_flash_cmd_write(&flash->spi, cmd, sizeof(cmd),
buf + actual, chunk_len);
if (ret < 0) {
printk(BIOS_WARNING, "SF: Macronix Page Program failed\n");
Expand All @@ -201,7 +194,6 @@ static int macronix_write(struct spi_flash *flash,
break;

offset += chunk_len;
byte_addr = 0;
}

#if CONFIG_DEBUG_SPI_FLASH
Expand All @@ -212,15 +204,11 @@ static int macronix_write(struct spi_flash *flash,
return ret;
}

static int macronix_erase(struct spi_flash *flash, u32 offset, size_t len)
{
return spi_flash_cmd_erase(flash, CMD_MX25XX_SE, offset, len);
}
static struct macronix_spi_flash mcx;

struct spi_flash *spi_flash_probe_macronix(struct spi_slave *spi, u8 *idcode)
{
const struct macronix_spi_flash_params *params;
struct macronix_spi_flash *mcx;
unsigned int i;
u16 id = idcode[2] | idcode[1] << 8;

Expand All @@ -235,26 +223,23 @@ struct spi_flash *spi_flash_probe_macronix(struct spi_slave *spi, u8 *idcode)
return NULL;
}

mcx = malloc(sizeof(*mcx));
if (!mcx) {
printk(BIOS_WARNING, "SF: Failed to allocate memory\n");
return NULL;
}

mcx->params = params;
mcx->flash.spi = spi;
mcx->flash.name = params->name;
mcx.params = params;
memcpy(&mcx.flash.spi, spi, sizeof(*spi));
mcx.flash.name = params->name;

mcx->flash.write = macronix_write;
mcx->flash.erase = macronix_erase;
mcx.flash.internal_write = macronix_write;
mcx.flash.internal_erase = spi_flash_cmd_erase;
mcx.flash.internal_status = spi_flash_cmd_status;
#if CONFIG_SPI_FLASH_NO_FAST_READ
mcx->flash.read = spi_flash_cmd_read_slow;
mcx.flash.internal_read = spi_flash_cmd_read_slow;
#else
mcx->flash.read = spi_flash_cmd_read_fast;
mcx.flash.internal_read = spi_flash_cmd_read_fast;
#endif
mcx->flash.sector_size = params->page_size * params->pages_per_sector;
mcx->flash.size = mcx->flash.sector_size * params->sectors_per_block *
mcx.flash.sector_size = params->page_size * params->pages_per_sector;
mcx.flash.size = mcx.flash.sector_size * params->sectors_per_block *
params->nr_blocks;
mcx.flash.erase_cmd = CMD_MX25XX_SE;
mcx.flash.status_cmd = CMD_MX25XX_RDSR;

return &mcx->flash;
return &mcx.flash;
}
125 changes: 83 additions & 42 deletions src/drivers/spi/spansion.c
Expand Up @@ -6,9 +6,6 @@
* TsiChung Liew (Tsi-Chung.Liew@freescale.com),
* and Jason McMullan (mcmullan@netapp.com)
*
* See file CREDITS for list of people who contributed to this
* project.
*
* This program 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
Expand All @@ -18,15 +15,13 @@
* 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., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*/

#include <console/console.h>
#include <stdlib.h>
#include <spi_flash.h>
#include <spi-generic.h>
#include <string.h>

#include "spi_flash_internal.h"

Expand All @@ -44,20 +39,25 @@
#define CMD_S25FLXX_DP 0xb9 /* Deep Power-down */
#define CMD_S25FLXX_RES 0xab /* Release from DP, and Read Signature */

#define SPSN_MANUFACTURER_ID_S25FL116K 0x01
#define SPSN_ID_S25FL008A 0x0213
#define SPSN_ID_S25FL016A 0x0214
#define SPSN_ID_S25FL032A 0x0215
#define SPSN_ID_S25FL064A 0x0216
#define SPSN_ID_S25FL128S 0x0219
#define SPSN_ID_S25FL128P 0x2018
#define SPSN_ID_S25FL116K 0x4015
#define SPSN_EXT_ID_S25FL128P_256KB 0x0300
#define SPSN_EXT_ID_S25FL128P_64KB 0x0301
#define SPSN_EXT_ID_S25FL032P 0x4d00
#define SPSN_EXT_ID_S25FLXXS_64KB 0x4d01

struct spansion_spi_flash_params {
u8 idcode0;
u16 idcode1;
u16 idcode2;
int (*identify) (const struct spansion_spi_flash_params *params,
u8 *idcode);
u16 page_size;
u16 pages_per_sector;
u16 nr_sectors;
Expand All @@ -69,92 +69,142 @@ struct spansion_spi_flash {
const struct spansion_spi_flash_params *params;
};

static inline struct spansion_spi_flash *to_spansion_spi_flash(struct spi_flash
*flash)
static inline
struct spansion_spi_flash *to_spansion_spi_flash(const struct spi_flash *flash)
{
return container_of(flash, struct spansion_spi_flash, flash);
}

/*
* returns non-zero if the given idcode matches the ID of the chip. this is for
* chips which use 2nd, 3rd, 4th, and 5th byte.
*/
static int identify_2345(const struct spansion_spi_flash_params *params,
u8 *idcode)
{
u16 jedec = idcode[1] << 8 | idcode[2];
u16 ext_jedec = idcode[3] << 8 | idcode[4];
return (params->idcode1 == jedec) && (params->idcode2 == ext_jedec);
}

/*
* returns non-zero if the given idcode matches the ID of the chip. this is for
* chips which use 1st, 2nd, and 3rd byte.
*/
static int identify_123(const struct spansion_spi_flash_params *params,
u8 *idcode)
{
u16 jedec = idcode[1] << 8 | idcode[2];
return (params->idcode0 == idcode[0]) && (params->idcode1 == jedec);
}

static const struct spansion_spi_flash_params spansion_spi_flash_table[] = {
{
.idcode0 = 0,
.idcode1 = SPSN_ID_S25FL008A,
.idcode2 = 0,
.identify = identify_2345,
.page_size = 256,
.pages_per_sector = 256,
.nr_sectors = 16,
.name = "S25FL008A",
},
{
.idcode0 = 0,
.idcode1 = SPSN_ID_S25FL016A,
.idcode2 = 0,
.identify = identify_2345,
.page_size = 256,
.pages_per_sector = 256,
.nr_sectors = 32,
.name = "S25FL016A",
},
{
.idcode0 = 0,
.idcode1 = SPSN_ID_S25FL032A,
.idcode2 = 0,
.identify = identify_2345,
.page_size = 256,
.pages_per_sector = 256,
.nr_sectors = 64,
.name = "S25FL032A",
},
{
.idcode0 = 0,
.idcode1 = SPSN_ID_S25FL064A,
.idcode2 = 0,
.identify = identify_2345,
.page_size = 256,
.pages_per_sector = 256,
.nr_sectors = 128,
.name = "S25FL064A",
},
{
.idcode0 = 0,
.idcode1 = SPSN_ID_S25FL128P,
.idcode2 = SPSN_EXT_ID_S25FL128P_64KB,
.identify = identify_2345,
.page_size = 256,
.pages_per_sector = 256,
.nr_sectors = 256,
.name = "S25FL128P_64K",
},
{
.idcode0 = 0,
.idcode1 = SPSN_ID_S25FL128P,
.idcode2 = SPSN_EXT_ID_S25FL128P_256KB,
.identify = identify_2345,
.page_size = 256,
.pages_per_sector = 1024,
.nr_sectors = 64,
.name = "S25FL128P_256K",
},
{
.idcode0 = 0,
.idcode1 = SPSN_ID_S25FL128S,
.idcode2 = SPSN_EXT_ID_S25FLXXS_64KB,
.identify = identify_2345,
.page_size = 256,
.pages_per_sector = 256,
.nr_sectors = 512,
.name = "S25FL128S_256K",
},
{
.idcode0 = 0,
.idcode1 = SPSN_ID_S25FL032A,
.idcode2 = SPSN_EXT_ID_S25FL032P,
.identify = identify_2345,
.page_size = 256,
.pages_per_sector = 256,
.nr_sectors = 64,
.name = "S25FL032P",
},
{
.idcode0 = 0,
.idcode1 = SPSN_ID_S25FL128P,
.idcode2 = SPSN_EXT_ID_S25FLXXS_64KB,
.identify = identify_2345,
.page_size = 256,
.pages_per_sector = 256,
.nr_sectors = 256,
.name = "25FS128S",
},
{
.idcode0 = SPSN_MANUFACTURER_ID_S25FL116K,
.idcode1 = SPSN_ID_S25FL116K,
.idcode2 = 0,
.identify = identify_123,
.page_size = 256,
.pages_per_sector = 256,
.nr_sectors = 32,
.name = "S25FL116K_16M",
},
};

static int spansion_write(struct spi_flash *flash,
u32 offset, size_t len, const void *buf)
static int spansion_write(const struct spi_flash *flash, u32 offset, size_t len,
const void *buf)
{
struct spansion_spi_flash *spsn = to_spansion_spi_flash(flash);
unsigned long page_addr;
unsigned long byte_addr;
unsigned long page_size;
size_t chunk_len;
Expand All @@ -163,32 +213,30 @@ static int spansion_write(struct spi_flash *flash,
u8 cmd[4];

page_size = spsn->params->page_size;
page_addr = offset / page_size;
byte_addr = offset % page_size;

flash->spi->rw = SPI_WRITE_FLAG;

for (actual = 0; actual < len; actual += chunk_len) {
byte_addr = offset % page_size;
chunk_len = min(len - actual, page_size - byte_addr);
chunk_len = spi_crop_chunk(sizeof(cmd), chunk_len);

cmd[0] = CMD_S25FLXX_PP;
cmd[1] = page_addr >> 8;
cmd[2] = page_addr;
cmd[3] = byte_addr;
cmd[1] = (offset >> 16) & 0xff;
cmd[2] = (offset >> 8) & 0xff;
cmd[3] = offset & 0xff;

#if CONFIG_DEBUG_SPI_FLASH
printk(BIOS_SPEW, "PP: 0x%p => cmd = { 0x%02x 0x%02x%02x%02x }"
" chunk_len = %zu\n",
buf + actual, cmd[0], cmd[1], cmd[2], cmd[3], chunk_len);
#endif

ret = spi_flash_cmd(flash->spi, CMD_S25FLXX_WREN, NULL, 0);
ret = spi_flash_cmd(&flash->spi, CMD_S25FLXX_WREN, NULL, 0);
if (ret < 0) {
printk(BIOS_WARNING, "SF: Enabling Write failed\n");
break;
}

ret = spi_flash_cmd_write(flash->spi, cmd, 4,
ret = spi_flash_cmd_write(&flash->spi, cmd, 4,
buf + actual, chunk_len);
if (ret < 0) {
printk(BIOS_WARNING, "SF: SPANSION Page Program failed\n");
Expand All @@ -199,8 +247,7 @@ static int spansion_write(struct spi_flash *flash,
if (ret)
break;

page_addr++;
byte_addr = 0;
offset += chunk_len;
}

#if CONFIG_DEBUG_SPI_FLASH
Expand All @@ -211,47 +258,41 @@ static int spansion_write(struct spi_flash *flash,
return ret;
}

static int spansion_erase(struct spi_flash *flash, u32 offset, size_t len)
{
return spi_flash_cmd_erase(flash, CMD_S25FLXX_SE, offset, len);
}

static struct spansion_spi_flash spsn_flash;

struct spi_flash *spi_flash_probe_spansion(struct spi_slave *spi, u8 *idcode)
{
const struct spansion_spi_flash_params *params;
struct spansion_spi_flash *spsn;
unsigned int i;
unsigned short jedec, ext_jedec;

jedec = idcode[1] << 8 | idcode[2];
ext_jedec = idcode[3] << 8 | idcode[4];

for (i = 0; i < ARRAY_SIZE(spansion_spi_flash_table); i++) {
params = &spansion_spi_flash_table[i];
if (params->idcode1 == jedec) {
if (params->idcode2 == ext_jedec)
break;
}
if (params->identify(params, idcode))
break;
}

if (i == ARRAY_SIZE(spansion_spi_flash_table)) {
printk(BIOS_WARNING, "SF: Unsupported SPANSION ID %04x %04x\n", jedec, ext_jedec);
printk(BIOS_WARNING,
"SF: Unsupported SPANSION ID %02x %02x %02x %02x %02x\n",
idcode[0], idcode[1], idcode[2], idcode[3], idcode[4]);
return NULL;
}

spsn = &spsn_flash;

spsn->params = params;
spsn->flash.spi = spi;
memcpy(&spsn->flash.spi, spi, sizeof(*spi));
spsn->flash.name = params->name;

spsn->flash.write = spansion_write;
spsn->flash.erase = spansion_erase;
spsn->flash.read = spi_flash_cmd_read_slow;
spsn->flash.internal_write = spansion_write;
spsn->flash.internal_erase = spi_flash_cmd_erase;
spsn->flash.internal_read = spi_flash_cmd_read_slow;
spsn->flash.internal_status = spi_flash_cmd_status;
spsn->flash.sector_size = params->page_size * params->pages_per_sector;
spsn->flash.size = spsn->flash.sector_size * params->nr_sectors;
spsn->flash.erase_cmd = CMD_S25FLXX_SE;
spsn->flash.status_cmd = CMD_S25FLXX_RDSR;

return &spsn->flash;
}
177 changes: 177 additions & 0 deletions src/drivers/spi/spi-generic.c
@@ -0,0 +1,177 @@
/*
* This file is part of the coreboot project.
*
* Copyright 2016 Google Inc.
*
* This program 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.
*
* This program 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.
*/

#include <assert.h>
#include <spi-generic.h>
#include <string.h>

int spi_claim_bus(const struct spi_slave *slave)
{
const struct spi_ctrlr *ctrlr = slave->ctrlr;
if (ctrlr && ctrlr->claim_bus)
return ctrlr->claim_bus(slave);
return 0;
}

void spi_release_bus(const struct spi_slave *slave)
{
const struct spi_ctrlr *ctrlr = slave->ctrlr;
if (ctrlr && ctrlr->release_bus)
ctrlr->release_bus(slave);
}

static int spi_xfer_single_op(const struct spi_slave *slave,
struct spi_op *op)
{
const struct spi_ctrlr *ctrlr = slave->ctrlr;
int ret;

if (!ctrlr || !ctrlr->xfer)
return -1;

ret = ctrlr->xfer(slave, op->dout, op->bytesout, op->din, op->bytesin);
if (ret)
op->status = SPI_OP_FAILURE;
else
op->status = SPI_OP_SUCCESS;

return ret;
}

static int spi_xfer_vector_default(const struct spi_slave *slave,
struct spi_op vectors[], size_t count)
{
size_t i;
int ret;

for (i = 0; i < count; i++) {
ret = spi_xfer_single_op(slave, &vectors[i]);
if (ret)
return ret;
}

return 0;
}

int spi_xfer_vector(const struct spi_slave *slave,
struct spi_op vectors[], size_t count)
{
const struct spi_ctrlr *ctrlr = slave->ctrlr;

if (ctrlr && ctrlr->xfer_vector)
return ctrlr->xfer_vector(slave, vectors, count);

return spi_xfer_vector_default(slave, vectors, count);
}

int spi_xfer(const struct spi_slave *slave, const void *dout, size_t bytesout,
void *din, size_t bytesin)
{
const struct spi_ctrlr *ctrlr = slave->ctrlr;

if (ctrlr && ctrlr->xfer)
return ctrlr->xfer(slave, dout, bytesout, din, bytesin);

return -1;
}

void __attribute__((weak)) spi_init(void)
{
/* Default weak implementation - do nothing. */
}

const struct spi_ctrlr_buses spi_ctrlr_bus_map[0] __attribute__((weak));
const size_t spi_ctrlr_bus_map_count __attribute__((weak));

int __attribute__((weak)) spi_setup_slave(unsigned int bus, unsigned int cs,
struct spi_slave *slave)
{
size_t i;

memset(slave, 0, sizeof(*slave));

for (i = 0; i < spi_ctrlr_bus_map_count; i++) {
if ((spi_ctrlr_bus_map[i].bus_start <= bus) &&
(spi_ctrlr_bus_map[i].bus_end >= bus)) {
slave->ctrlr = spi_ctrlr_bus_map[i].ctrlr;
break;
}
}

if (slave->ctrlr == NULL)
return -1;

slave->bus = bus;
slave->cs = cs;

if (slave->ctrlr->setup)
return slave->ctrlr->setup(slave);

return 0;
}

static int spi_xfer_combine_two_vectors(const struct spi_slave *slave,
struct spi_op *v1, struct spi_op *v2)
{
struct spi_op op = {
.dout = v1->dout, .bytesout = v1->bytesout,
.din = v2->din, .bytesin = v2->bytesin,
};
int ret;

/*
* Combine two vectors only if:
* v1 has non-NULL dout and NULL din and
* v2 has non-NULL din and NULL dout and
*
* In all other cases, do not combine the two vectors.
*/
if ((!v1->dout || v1->din) || (v2->dout || !v2->din))
return -1;

ret = spi_xfer_single_op(slave, &op);
v1->status = v2->status = op.status;

return ret;
}

/*
* Helper function to allow chipsets to combine two vectors if possible. This
* function can only handle upto 2 vectors.
*
* Two vectors are combined if first vector has a non-NULL dout and NULL din and
* second vector has a non-NULL din and NULL dout. Otherwise, each vector is
* operated upon one at a time.
*
* Returns 0 on success and non-zero on failure.
*/
int spi_xfer_two_vectors(const struct spi_slave *slave,
struct spi_op vectors[], size_t count)
{
int ret;

assert (count <= 2);

if (count == 2) {
ret = spi_xfer_combine_two_vectors(slave, &vectors[0],
&vectors[1]);

if (!ret || (vectors[0].status != SPI_OP_NOT_EXECUTED))
return ret;
}

return spi_xfer_vector_default(slave, vectors, count);
}
324 changes: 202 additions & 122 deletions src/drivers/spi/spi_flash.c

Large diffs are not rendered by default.

38 changes: 15 additions & 23 deletions src/drivers/spi/spi_flash_internal.h
Expand Up @@ -26,52 +26,44 @@
#define CMD_READ_STATUS 0x05
#define CMD_WRITE_ENABLE 0x06

#define CMD_BLOCK_ERASE 0xD8

/* Common status */
#define STATUS_WIP 0x01

/* Send a single-byte command to the device and read the response */
int spi_flash_cmd(struct spi_slave *spi, u8 cmd, void *response, size_t len);

/*
* Send a multi-byte command to the device and read the response. Used
* for flash array reads, etc.
*/
int spi_flash_cmd_read(struct spi_slave *spi, const u8 *cmd,
size_t cmd_len, void *data, size_t data_len);
int spi_flash_cmd(const struct spi_slave *spi, u8 cmd, void *response, size_t len);
int spi_flash_cmd_read(const struct spi_slave *spi, const u8 *cmd,
size_t cmd_len, void *data, size_t data_len);

int spi_flash_cmd_read_fast(struct spi_flash *flash, u32 offset,
int spi_flash_cmd_read_fast(const struct spi_flash *flash, u32 offset,
size_t len, void *data);

int spi_flash_cmd_read_slow(struct spi_flash *flash, u32 offset,
int spi_flash_cmd_read_slow(const struct spi_flash *flash, u32 offset,
size_t len, void *data);

/*
* Send a multi-byte command to the device followed by (optional)
* data. Used for programming the flash array, etc.
*/
int spi_flash_cmd_write(struct spi_slave *spi, const u8 *cmd, size_t cmd_len,
const void *data, size_t data_len);

/*
* Same as spi_flash_cmd_read() except it also claims/releases the SPI
* bus. Used as common part of the ->read() operation.
*/
int spi_flash_read_common(struct spi_flash *flash, const u8 *cmd,
size_t cmd_len, void *data, size_t data_len);
int spi_flash_cmd_write(const struct spi_slave *spi, const u8 *cmd,
size_t cmd_len, const void *data, size_t data_len);

/* Send a command to the device and wait for some bit to clear itself. */
int spi_flash_cmd_poll_bit(struct spi_flash *flash, unsigned long timeout,
int spi_flash_cmd_poll_bit(const struct spi_flash *flash, unsigned long timeout,
u8 cmd, u8 poll_bit);

/*
* Send the read status command to the device and wait for the wip
* (write-in-progress) bit to clear itself.
*/
int spi_flash_cmd_wait_ready(struct spi_flash *flash, unsigned long timeout);
int spi_flash_cmd_wait_ready(const struct spi_flash *flash, unsigned long timeout);

/* Erase sectors. */
int spi_flash_cmd_erase(struct spi_flash *flash, u8 erase_cmd,
u32 offset, size_t len);
int spi_flash_cmd_erase(const struct spi_flash *flash, u32 offset, size_t len);

/* Read status register. */
int spi_flash_cmd_status(const struct spi_flash *flash, u8 *reg);

/* Manufacturer-specific probe functions */
struct spi_flash *spi_flash_probe_spansion(struct spi_slave *spi, u8 *idcode);
Expand Down
141 changes: 115 additions & 26 deletions src/drivers/spi/sst.c
Expand Up @@ -12,8 +12,11 @@
* Licensed under the GPL-2 or later.
*/

#include <console/console.h>
#include <stdlib.h>
#include <spi_flash.h>
#include <spi-generic.h>
#include <string.h>

#include "spi_flash_internal.h"

Expand All @@ -40,83 +43,99 @@ struct sst_spi_flash_params {
u8 idcode1;
u16 nr_sectors;
const char *name;
int (*write)(const struct spi_flash *flash, u32 offset,
size_t len, const void *buf);
};

struct sst_spi_flash {
struct spi_flash flash;
const struct sst_spi_flash_params *params;
};

static int sst_write_ai(const struct spi_flash *flash, u32 offset, size_t len,
const void *buf);
static int sst_write_256(const struct spi_flash *flash, u32 offset, size_t len,
const void *buf);

#define SST_SECTOR_SIZE (4 * 1024)
static const struct sst_spi_flash_params sst_spi_flash_table[] = {
{
.idcode1 = 0x8d,
.nr_sectors = 128,
.name = "SST25VF040B",
.write = sst_write_ai,
},{
.idcode1 = 0x8e,
.nr_sectors = 256,
.name = "SST25VF080B",
.write = sst_write_ai,
},{
.idcode1 = 0x41,
.nr_sectors = 512,
.name = "SST25VF016B",
.write = sst_write_ai,
},{
.idcode1 = 0x4a,
.nr_sectors = 1024,
.name = "SST25VF032B",
.write = sst_write_ai,
},{
.idcode1 = 0x4b,
.nr_sectors = 2048,
.name = "SST25VF064C",
.write = sst_write_256,
},{
.idcode1 = 0x01,
.nr_sectors = 16,
.name = "SST25WF512",
.write = sst_write_ai,
},{
.idcode1 = 0x02,
.nr_sectors = 32,
.name = "SST25WF010",
.write = sst_write_ai,
},{
.idcode1 = 0x03,
.nr_sectors = 64,
.name = "SST25WF020",
.write = sst_write_ai,
},{
.idcode1 = 0x04,
.nr_sectors = 128,
.name = "SST25WF040",
.write = sst_write_ai,
},
};

static int
sst_enable_writing(struct spi_flash *flash)
sst_enable_writing(const struct spi_flash *flash)
{
int ret = spi_flash_cmd(flash->spi, CMD_SST_WREN, NULL, 0);
int ret = spi_flash_cmd(&flash->spi, CMD_SST_WREN, NULL, 0);
if (ret)
printk(BIOS_WARNING, "SF: Enabling Write failed\n");
return ret;
}

static int
sst_enable_writing_status(struct spi_flash *flash)
sst_enable_writing_status(const struct spi_flash *flash)
{
int ret = spi_flash_cmd(flash->spi, CMD_SST_EWSR, NULL, 0);
int ret = spi_flash_cmd(&flash->spi, CMD_SST_EWSR, NULL, 0);
if (ret)
printk(BIOS_WARNING, "SF: Enabling Write Status failed\n");
return ret;
}

static int
sst_disable_writing(struct spi_flash *flash)
sst_disable_writing(const struct spi_flash *flash)
{
int ret = spi_flash_cmd(flash->spi, CMD_SST_WRDI, NULL, 0);
int ret = spi_flash_cmd(&flash->spi, CMD_SST_WRDI, NULL, 0);
if (ret)
printk(BIOS_WARNING, "SF: Disabling Write failed\n");
return ret;
}

static int
sst_byte_write(struct spi_flash *flash, u32 offset, const void *buf)
sst_byte_write(const struct spi_flash *flash, u32 offset, const void *buf)
{
int ret;
u8 cmd[4] = {
Expand All @@ -128,28 +147,99 @@ sst_byte_write(struct spi_flash *flash, u32 offset, const void *buf)

#if CONFIG_DEBUG_SPI_FLASH
printk(BIOS_SPEW, "BP[%02x]: 0x%p => cmd = { 0x%02x 0x%06x }\n",
spi_w8r8(flash->spi, CMD_SST_RDSR), buf, cmd[0], offset);
spi_w8r8(&flash->spi, CMD_SST_RDSR), buf, cmd[0], offset);
#endif

ret = sst_enable_writing(flash);
if (ret)
return ret;

ret = spi_flash_cmd_write(flash->spi, cmd, sizeof(cmd), buf, 1);
ret = spi_flash_cmd_write(&flash->spi, cmd, sizeof(cmd), buf, 1);
if (ret)
return ret;

return spi_flash_cmd_wait_ready(flash, SPI_FLASH_PROG_TIMEOUT);
}

static int
sst_write(struct spi_flash *flash, u32 offset, size_t len, const void *buf)
static int sst_write_256(const struct spi_flash *flash, u32 offset, size_t len,
const void *buf)
{
size_t actual, cmd_len;
size_t actual, chunk_len, cmd_len;
unsigned long byte_addr;
unsigned long page_size;
int ret = 0;
u8 cmd[4];

flash->spi->rw = SPI_WRITE_FLAG;
page_size = 256;

/* If the data is not word aligned, write out leading single byte */
actual = offset % 2;
if (actual) {
ret = sst_byte_write(flash, offset, buf);
if (ret)
goto done;
}
offset += actual;

ret = sst_enable_writing(flash);
if (ret)
goto done;

cmd_len = 4;
cmd[0] = CMD_SST_AAI_WP;
cmd[1] = offset >> 16;
cmd[2] = offset >> 8;
cmd[3] = offset;

for (actual = 0; actual < len; actual += chunk_len) {
byte_addr = offset % page_size;
chunk_len = min(len - actual, page_size - byte_addr);
chunk_len = spi_crop_chunk(sizeof(cmd), chunk_len);

cmd[0] = CMD_SST_BP;
cmd[1] = (offset >> 16) & 0xff;
cmd[2] = (offset >> 8) & 0xff;
cmd[3] = offset & 0xff;
#if CONFIG_DEBUG_SPI_FLASH
printk(BIOS_SPEW, "PP: 0x%p => cmd = { 0x%02x 0x%02x%02x%02x }"
" chunk_len = %zu\n",
buf + actual, cmd[0], cmd[1], cmd[2], cmd[3], chunk_len);
#endif

ret = spi_flash_cmd(&flash->spi, CMD_SST_WREN, NULL, 0);
if (ret < 0) {
printk(BIOS_WARNING, "SF: Enabling Write failed\n");
break;
}

ret = spi_flash_cmd_write(&flash->spi, cmd, sizeof(cmd),
buf + actual, chunk_len);
if (ret < 0) {
printk(BIOS_WARNING, "SF: SST Page Program failed\n");
break;
}

ret = spi_flash_cmd_wait_ready(flash, SPI_FLASH_PROG_TIMEOUT);
if (ret)
break;

offset += chunk_len;
}

done:
#if CONFIG_DEBUG_SPI_FLASH
printk(BIOS_SPEW, "SF: SST: program %s %zu bytes @ 0x%lx\n",
ret ? "failure" : "success", len, (unsigned long)offset - actual);
#endif
return ret;
}

static int sst_write_ai(const struct spi_flash *flash, u32 offset, size_t len,
const void *buf)
{
size_t actual, cmd_len;
int ret = 0;
u8 cmd[4];

/* If the data is not word aligned, write out leading single byte */
actual = offset % 2;
Expand All @@ -173,11 +263,11 @@ sst_write(struct spi_flash *flash, u32 offset, size_t len, const void *buf)
for (; actual < len - 1; actual += 2) {
#if CONFIG_DEBUG_SPI_FLASH
printk(BIOS_SPEW, "WP[%02x]: 0x%p => cmd = { 0x%02x 0x%06x }\n",
spi_w8r8(flash->spi, CMD_SST_RDSR), buf + actual, cmd[0],
spi_w8r8(&flash->spi, CMD_SST_RDSR), buf + actual, cmd[0],
offset);
#endif

ret = spi_flash_cmd_write(flash->spi, cmd, cmd_len,
ret = spi_flash_cmd_write(&flash->spi, cmd, cmd_len,
buf + actual, 2);
if (ret) {
printk(BIOS_WARNING, "SF: SST word program failed\n");
Expand Down Expand Up @@ -207,13 +297,9 @@ sst_write(struct spi_flash *flash, u32 offset, size_t len, const void *buf)
return ret;
}

static int sst_erase(struct spi_flash *flash, u32 offset, size_t len)
{
return spi_flash_cmd_erase(flash, CMD_SST_SE, offset, len);
}

static int
sst_unlock(struct spi_flash *flash)
sst_unlock(const struct spi_flash *flash)
{
int ret;
u8 cmd, status;
Expand All @@ -224,11 +310,11 @@ sst_unlock(struct spi_flash *flash)

cmd = CMD_SST_WRSR;
status = 0;
ret = spi_flash_cmd_write(flash->spi, &cmd, 1, &status, 1);
ret = spi_flash_cmd_write(&flash->spi, &cmd, 1, &status, 1);
if (ret)
printk(BIOS_WARNING, "SF: Unable to set status byte\n");

printk(BIOS_INFO, "SF: SST: status = %x\n", spi_w8r8(flash->spi, CMD_SST_RDSR));
printk(BIOS_INFO, "SF: SST: status = %x\n", spi_w8r8(&flash->spi, CMD_SST_RDSR));

return ret;
}
Expand Down Expand Up @@ -258,14 +344,17 @@ spi_flash_probe_sst(struct spi_slave *spi, u8 *idcode)
}

stm->params = params;
stm->flash.spi = spi;
memcpy(&stm->flash.spi, spi, sizeof(*spi));
stm->flash.name = params->name;

stm->flash.write = sst_write;
stm->flash.erase = sst_erase;
stm->flash.read = spi_flash_cmd_read_fast;
stm->flash.internal_write = params->write;
stm->flash.internal_erase = spi_flash_cmd_erase;
stm->flash.internal_status = spi_flash_cmd_status;
stm->flash.internal_read = spi_flash_cmd_read_fast;
stm->flash.sector_size = SST_SECTOR_SIZE;
stm->flash.size = stm->flash.sector_size * params->nr_sectors;
stm->flash.erase_cmd = CMD_SST_SE;
stm->flash.status_cmd = CMD_SST_RDSR;

/* Flash powers up read-only, so clear BP# bits */
sst_unlock(&stm->flash);
Expand Down
162 changes: 80 additions & 82 deletions src/drivers/spi/stmicro.c
Expand Up @@ -8,9 +8,6 @@
* Copyright (C) 2004-2007 Freescale Semiconductor, Inc.
* TsiChung Liew (Tsi-Chung.Liew@freescale.com)
*
* See file CREDITS for list of people who contributed to this
* project.
*
* This program 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
Expand All @@ -20,15 +17,13 @@
* 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., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*/

#include <console/console.h>
#include <stdlib.h>
#include <spi_flash.h>
#include <spi-generic.h>
#include <string.h>

#include "spi_flash_internal.h"

Expand All @@ -46,25 +41,25 @@
#define CMD_M25PXX_DP 0xb9 /* Deep Power-down */
#define CMD_M25PXX_RES 0xab /* Release from DP, and Read Signature */

#define STM_ID_M25P10 0x11
#define STM_ID_M25P16 0x15
#define STM_ID_M25P20 0x12
#define STM_ID_M25P32 0x16
#define STM_ID_M25P40 0x13
#define STM_ID_M25P64 0x17
#define STM_ID_M25P80 0x14
#define STM_ID_M25P128 0x18
#define STM_ID_USE_ALT_ID 0xFF

/* Some SPI flash share the same .idcode1 (idcode[2]). To handle this without
* (possibly) breaking existing implementations, add the new device at the top
* of the flash table array and set its .idcode1 = STM_ID_USE_ALT_ID. The .id
* is then (idcode[1] << 8 | idcode[2]).
/*
* Device ID = (memory_type << 8) + memory_capacity
*/
#define STM_ID_M25P10 0x2011
#define STM_ID_M25P16 0x2015
#define STM_ID_M25P20 0x2012
#define STM_ID_M25P32 0x2016
#define STM_ID_M25P40 0x2013
#define STM_ID_M25P64 0x2017
#define STM_ID_M25P80 0x2014
#define STM_ID_M25P128 0x2018
#define STM_ID_N25Q256 0xba19
#define STM_ID_N25Q064 0xbb17
#define STM_ID_N25Q128 0xbb18
#define STM_ID_N25Q128A 0xba18

struct stmicro_spi_flash_params {
u8 idcode1;
u16 device_id;
u8 op_erase;
u16 id;
u16 page_size;
u16 pages_per_sector;
u16 nr_sectors;
Expand All @@ -77,89 +72,112 @@ struct stmicro_spi_flash {
const struct stmicro_spi_flash_params *params;
};

static inline struct stmicro_spi_flash *to_stmicro_spi_flash(struct spi_flash
*flash)
static inline
struct stmicro_spi_flash *to_stmicro_spi_flash(const struct spi_flash *flash)
{
return container_of(flash, struct stmicro_spi_flash, flash);
}

static const struct stmicro_spi_flash_params stmicro_spi_flash_table[] = {
{
.idcode1 = STM_ID_USE_ALT_ID,
.id = 0xbb18,
.op_erase = CMD_M25PXX_SSE,
.page_size = 256,
.pages_per_sector = 16,
.nr_sectors = 4096,
.name = "N25Q128",
},
{
.idcode1 = STM_ID_M25P10,
.device_id = STM_ID_M25P10,
.op_erase = CMD_M25PXX_SE,
.page_size = 256,
.pages_per_sector = 128,
.nr_sectors = 4,
.name = "M25P10",
},
{
.idcode1 = STM_ID_M25P16,
.device_id = STM_ID_M25P16,
.op_erase = CMD_M25PXX_SE,
.page_size = 256,
.pages_per_sector = 256,
.nr_sectors = 32,
.name = "M25P16",
},
{
.idcode1 = STM_ID_M25P20,
.device_id = STM_ID_M25P20,
.op_erase = CMD_M25PXX_SE,
.page_size = 256,
.pages_per_sector = 256,
.nr_sectors = 4,
.name = "M25P20",
},
{
.idcode1 = STM_ID_M25P32,
.device_id = STM_ID_M25P32,
.op_erase = CMD_M25PXX_SE,
.page_size = 256,
.pages_per_sector = 256,
.nr_sectors = 64,
.name = "M25P32",
},
{
.idcode1 = STM_ID_M25P40,
.device_id = STM_ID_M25P40,
.op_erase = CMD_M25PXX_SE,
.page_size = 256,
.pages_per_sector = 256,
.nr_sectors = 8,
.name = "M25P40",
},
{
.idcode1 = STM_ID_M25P64,
.device_id = STM_ID_M25P64,
.op_erase = CMD_M25PXX_SE,
.page_size = 256,
.pages_per_sector = 256,
.nr_sectors = 128,
.name = "M25P64",
},
{
.idcode1 = STM_ID_M25P80,
.device_id = STM_ID_M25P80,
.op_erase = CMD_M25PXX_SE,
.page_size = 256,
.pages_per_sector = 256,
.nr_sectors = 16,
.name = "M25P80",
},
{
.idcode1 = STM_ID_M25P128,
.device_id = STM_ID_M25P128,
.op_erase = CMD_M25PXX_SE,
.page_size = 256,
.pages_per_sector = 1024,
.nr_sectors = 64,
.name = "M25P128",
},
{
.device_id = STM_ID_N25Q064,
.op_erase = CMD_M25PXX_SSE,
.page_size = 256,
.pages_per_sector = 16,
.nr_sectors = 2048,
.name = "N25Q064",
},
{
.device_id = STM_ID_N25Q128,
.op_erase = CMD_M25PXX_SSE,
.page_size = 256,
.pages_per_sector = 16,
.nr_sectors = 4096,
.name = "N25Q128",
},
{
.device_id = STM_ID_N25Q128A,
.op_erase = CMD_M25PXX_SSE,
.page_size = 256,
.pages_per_sector = 16,
.nr_sectors = 4096,
.name = "N25Q128A",
},
{
.device_id = STM_ID_N25Q256,
.op_erase = CMD_M25PXX_SSE,
.page_size = 256,
.pages_per_sector = 16,
.nr_sectors = 8192,
.name = "N25Q256",
},
};

static int stmicro_write(struct spi_flash *flash,
static int stmicro_write(const struct spi_flash *flash,
u32 offset, size_t len, const void *buf)
{
struct stmicro_spi_flash *stm = to_stmicro_spi_flash(flash);
Expand All @@ -171,11 +189,9 @@ static int stmicro_write(struct spi_flash *flash,
u8 cmd[4];

page_size = stm->params->page_size;
byte_addr = offset % page_size;

flash->spi->rw = SPI_WRITE_FLAG;

for (actual = 0; actual < len; actual += chunk_len) {
byte_addr = offset % page_size;
chunk_len = min(len - actual, page_size - byte_addr);
chunk_len = spi_crop_chunk(sizeof(cmd), chunk_len);

Expand All @@ -189,13 +205,13 @@ static int stmicro_write(struct spi_flash *flash,
buf + actual, cmd[0], cmd[1], cmd[2], cmd[3], chunk_len);
#endif

ret = spi_flash_cmd(flash->spi, CMD_M25PXX_WREN, NULL, 0);
ret = spi_flash_cmd(&flash->spi, CMD_M25PXX_WREN, NULL, 0);
if (ret < 0) {
printk(BIOS_WARNING, "SF: Enabling Write failed\n");
goto out;
}

ret = spi_flash_cmd_write(flash->spi, cmd, sizeof(cmd),
ret = spi_flash_cmd_write(&flash->spi, cmd, sizeof(cmd),
buf + actual, chunk_len);
if (ret < 0) {
printk(BIOS_WARNING, "SF: STMicro Page Program failed\n");
Expand All @@ -207,7 +223,6 @@ static int stmicro_write(struct spi_flash *flash,
goto out;

offset += chunk_len;
byte_addr = 0;
}

#if CONFIG_DEBUG_SPI_FLASH
Expand All @@ -217,26 +232,18 @@ static int stmicro_write(struct spi_flash *flash,
ret = 0;

out:
spi_release_bus(flash->spi);
return ret;
}

static int stmicro_erase(struct spi_flash *flash, u32 offset, size_t len)
{
struct stmicro_spi_flash *stm = to_stmicro_spi_flash(flash);

return spi_flash_cmd_erase(flash, stm->params->op_erase, offset, len);
}
static struct stmicro_spi_flash stm;

struct spi_flash *spi_flash_probe_stmicro(struct spi_slave *spi, u8 * idcode)
{
const struct stmicro_spi_flash_params *params;
struct stmicro_spi_flash *stm;
unsigned int i;

if (idcode[0] == 0xff) {
i = spi_flash_cmd(spi, CMD_M25PXX_RES,
idcode, 4);
i = spi_flash_cmd(spi, CMD_M25PXX_RES, idcode, 4);
if (i)
return NULL;
if ((idcode[3] & 0xf0) == 0x10) {
Expand All @@ -249,36 +256,27 @@ struct spi_flash *spi_flash_probe_stmicro(struct spi_slave *spi, u8 * idcode)

for (i = 0; i < ARRAY_SIZE(stmicro_spi_flash_table); i++) {
params = &stmicro_spi_flash_table[i];
if (params->idcode1 == STM_ID_USE_ALT_ID) {
if (params->id == ((idcode[1] << 8) | idcode[2])) {
break;
}
}
else if (params->idcode1 == idcode[2]) {
if (params->device_id == (idcode[1] << 8 | idcode[2])) {
break;
}
}

if (i == ARRAY_SIZE(stmicro_spi_flash_table)) {
printk(BIOS_WARNING, "SF: Unsupported STMicro ID %02x\n", idcode[1]);
return NULL;
}

stm = malloc(sizeof(struct stmicro_spi_flash));
if (!stm) {
printk(BIOS_WARNING, "SF: Failed to allocate memory\n");
printk(BIOS_WARNING, "SF: Unsupported STMicro ID %02x%02x\n",
idcode[1], idcode[2]);
return NULL;
}

stm->params = params;
stm->flash.spi = spi;
stm->flash.name = params->name;
stm.params = params;
memcpy(&stm.flash.spi, spi, sizeof(*spi));
stm.flash.name = params->name;

stm->flash.write = stmicro_write;
stm->flash.erase = stmicro_erase;
stm->flash.read = spi_flash_cmd_read_fast;
stm->flash.sector_size = params->page_size * params->pages_per_sector;
stm->flash.size = stm->flash.sector_size * params->nr_sectors;
stm.flash.internal_write = stmicro_write;
stm.flash.internal_erase = spi_flash_cmd_erase;
stm.flash.internal_read = spi_flash_cmd_read_fast;
stm.flash.sector_size = params->page_size * params->pages_per_sector;
stm.flash.size = stm.flash.sector_size * params->nr_sectors;
stm.flash.erase_cmd = params->op_erase;

return &stm->flash;
return &stm.flash;
}
98 changes: 69 additions & 29 deletions src/drivers/spi/winbond.c
Expand Up @@ -4,8 +4,11 @@
* Licensed under the GPL-2 or later.
*/

#include <console/console.h>
#include <stdlib.h>
#include <spi_flash.h>
#include <spi-generic.h>
#include <string.h>

#include "spi_flash_internal.h"

Expand All @@ -22,6 +25,12 @@
#define CMD_W25_CE 0xc7 /* Chip Erase */
#define CMD_W25_DP 0xb9 /* Deep Power-down */
#define CMD_W25_RES 0xab /* Release from DP, and Read Signature */
#define CMD_W25_RD_SEC 0x48 /* Read security registers */

#define ADDR_W25_SEC1 0x10 /* Address offset for sec register 1 */
#define ADDR_W25_SEC2 0x20 /* Address offset for sec register 2 */
#define ADDR_W25_SEC3 0x30 /* Address offset for sec register 3 */
#define ADDR_W25_SEC_SHIFT 8 /* Address shift for sec registers */

struct winbond_spi_flash_params {
uint16_t id;
Expand All @@ -40,7 +49,7 @@ struct winbond_spi_flash {
};

static inline struct winbond_spi_flash *
to_winbond_spi_flash(struct spi_flash *flash)
to_winbond_spi_flash(const struct spi_flash *flash)
{
return container_of(flash, struct winbond_spi_flash, flash);
}
Expand Down Expand Up @@ -126,10 +135,18 @@ static const struct winbond_spi_flash_params winbond_spi_flash_table[] = {
.nr_blocks = 256,
.name = "W25Q128FW",
},
{
.id = 0x4019,
.l2_page_size = 8,
.pages_per_sector = 16,
.sectors_per_block = 16,
.nr_blocks = 512,
.name = "W25Q256",
},
};

static int winbond_write(struct spi_flash *flash,
u32 offset, size_t len, const void *buf)
static int winbond_write(const struct spi_flash *flash, u32 offset, size_t len,
const void *buf)
{
struct winbond_spi_flash *stm = to_winbond_spi_flash(flash);
unsigned long byte_addr;
Expand All @@ -140,11 +157,9 @@ static int winbond_write(struct spi_flash *flash,
u8 cmd[4];

page_size = 1 << stm->params->l2_page_size;
byte_addr = offset % page_size;

flash->spi->rw = SPI_WRITE_FLAG;

for (actual = 0; actual < len; actual += chunk_len) {
byte_addr = offset % page_size;
chunk_len = min(len - actual, page_size - byte_addr);
chunk_len = spi_crop_chunk(sizeof(cmd), chunk_len);

Expand All @@ -158,13 +173,13 @@ static int winbond_write(struct spi_flash *flash,
cmd[0], cmd[1], cmd[2], cmd[3], chunk_len);
#endif

ret = spi_flash_cmd(flash->spi, CMD_W25_WREN, NULL, 0);
ret = spi_flash_cmd(&flash->spi, CMD_W25_WREN, NULL, 0);
if (ret < 0) {
printk(BIOS_WARNING, "SF: Enabling Write failed\n");
goto out;
}

ret = spi_flash_cmd_write(flash->spi, cmd, sizeof(cmd),
ret = spi_flash_cmd_write(&flash->spi, cmd, sizeof(cmd),
buf + actual, chunk_len);
if (ret < 0) {
printk(BIOS_WARNING, "SF: Winbond Page Program failed\n");
Expand All @@ -176,7 +191,6 @@ static int winbond_write(struct spi_flash *flash,
goto out;

offset += chunk_len;
byte_addr = 0;
}

#if CONFIG_DEBUG_SPI_FLASH
Expand All @@ -189,16 +203,44 @@ static int winbond_write(struct spi_flash *flash,
return ret;
}

static int winbond_erase(struct spi_flash *flash, u32 offset, size_t len)
static int winbond_sec_read(const struct spi_flash *flash, u32 offset,
size_t len, void *buf)
{
return spi_flash_cmd_erase(flash, CMD_W25_SE, offset, len);
int ret;
u8 cmd[5];
u8 reg = (offset >> ADDR_W25_SEC_SHIFT) & 0xFF;
u8 addr = offset & 0xFF;

if ((reg != ADDR_W25_SEC1) &&
(reg != ADDR_W25_SEC2) &&
(reg != ADDR_W25_SEC3)) {
printk(BIOS_WARNING, "SF: Wrong security register\n");
return 1;
}

cmd[0] = CMD_W25_RD_SEC;
cmd[1] = 0x0;
cmd[2] = reg;
cmd[3] = addr;
cmd[4] = 0x0; /* dummy byte */

ret = spi_flash_cmd_read(&flash->spi, cmd, sizeof(cmd), buf, len);
if (ret) {
printk(BIOS_WARNING, "SF: Can't read sec register %d\n",
reg >> 4);
}

return ret;
}



static struct winbond_spi_flash stm;

struct spi_flash *spi_flash_probe_winbond(struct spi_slave *spi, u8 *idcode)
{
const struct winbond_spi_flash_params *params;
unsigned page_size;
struct winbond_spi_flash *stm;
unsigned int i;

for (i = 0; i < ARRAY_SIZE(winbond_spi_flash_table); i++) {
Expand All @@ -213,31 +255,29 @@ struct spi_flash *spi_flash_probe_winbond(struct spi_slave *spi, u8 *idcode)
return NULL;
}

stm = malloc(sizeof(struct winbond_spi_flash));
if (!stm) {
printk(BIOS_WARNING, "SF: Failed to allocate memory\n");
return NULL;
}

stm->params = params;
stm->flash.spi = spi;
stm->flash.name = params->name;
stm.params = params;
memcpy(&stm.flash.spi, spi, sizeof(*spi));
stm.flash.name = params->name;

/* Assuming power-of-two page size initially. */
page_size = 1 << params->l2_page_size;

stm->flash.write = winbond_write;
stm->flash.erase = winbond_erase;
stm.flash.internal_write = winbond_write;
stm.flash.internal_erase = spi_flash_cmd_erase;
stm.flash.internal_status = spi_flash_cmd_status;
stm.flash.internal_read_sec = winbond_sec_read;
#if CONFIG_SPI_FLASH_NO_FAST_READ
stm->flash.read = spi_flash_cmd_read_slow;
stm.flash.internal_read = spi_flash_cmd_read_slow;
#else
stm->flash.read = spi_flash_cmd_read_fast;
stm.flash.internal_read = spi_flash_cmd_read_fast;
#endif
stm->flash.sector_size = (1 << stm->params->l2_page_size) *
stm->params->pages_per_sector;
stm->flash.size = page_size * params->pages_per_sector
stm.flash.sector_size = (1 << stm.params->l2_page_size) *
stm.params->pages_per_sector;
stm.flash.size = page_size * params->pages_per_sector
* params->sectors_per_block
* params->nr_blocks;
stm.flash.erase_cmd = CMD_W25_SE;
stm.flash.status_cmd = CMD_W25_RDSR;

return &stm->flash;
return &stm.flash;
}