Add sb800 spi support.
authorzbao <fishbaozi@gmail.com>
Fri, 23 Mar 2012 03:36:08 +0000 (11:36 +0800)
committerMarc Jones <marcj303@gmail.com>
Mon, 2 Apr 2012 18:35:03 +0000 (20:35 +0200)
It is for S3, storing the recovring data in the nonvolatile storage,
i.e., flash.

Change-Id: Ie9e4f42a80c93d92d2e442f0e833ce06d88294f9
Signed-off-by: Zheng Bao <zheng.bao@amd.com>
Signed-off-by: zbao <fishbaozi@gmail.com>
Reviewed-on: http://review.coreboot.org/620
Tested-by: build bot (Jenkins)
Reviewed-by: Marc Jones <marcj303@gmail.com>
src/southbridge/amd/cimx/sb800/Makefile.inc
src/southbridge/amd/cimx/sb800/SBPLATFORM.h
src/southbridge/amd/cimx/sb800/spi.c [new file with mode: 0644]
src/southbridge/amd/cimx/sb800/spi.h [new file with mode: 0644]

index 30d21337152515756a76fd66b9c8f7be636a992e..2b55feeb1cacf2eecbc5dca37038f770e945bae5 100644 (file)
@@ -27,6 +27,8 @@ romstage-y += smbus.c
 ramstage-y += cfg.c
 ramstage-y += late.c
 
 ramstage-y += cfg.c
 ramstage-y += late.c
 
+ramstage-$(CONFIG_HAVE_ACPI_RESUME) += spi.c
+
 driver-y   += smbus.c
 driver-y   += lpc.c
 
 driver-y   += smbus.c
 driver-y   += lpc.c
 
index db5343dff0b9ee89474758696eb5ed0a999c8680..25aba9528095649147768a6f601af7900d384b20 100644 (file)
@@ -158,4 +158,8 @@ typedef union _PCI_ADDR {
 
 #include "vendorcode/amd/cimx/sb800/AMDSBLIB.h"
 
 
 #include "vendorcode/amd/cimx/sb800/AMDSBLIB.h"
 
+#if CONFIG_HAVE_ACPI_RESUME == 1
+#include "spi.h"
+#endif
+
 #endif // _AMD_SBPLATFORM_H_
 #endif // _AMD_SBPLATFORM_H_
diff --git a/src/southbridge/amd/cimx/sb800/spi.c b/src/southbridge/amd/cimx/sb800/spi.c
new file mode 100644 (file)
index 0000000..b0ef753
--- /dev/null
@@ -0,0 +1,209 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2012 Advanced Micro Devices, 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; version 2 of the License.
+ *
+ * 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.
+ *
+ * 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
+ */
+#include <console/console.h>
+#include <arch/io.h>
+#include <device/device.h>
+#include "SBPLATFORM.h"
+
+
+void execute_command(volatile u8 * spi_address)
+{
+       *(spi_address + 2) |= 1;
+}
+
+void wait4command_complete(volatile u8 * spi_address)
+{
+       while (*(spi_address + 2) & 1)
+               printk(BIOS_DEBUG, "wait4CommandComplete\n");
+}
+
+void reset_internal_fifo_pointer(volatile u8 * spi_address)
+{
+       u8 val;
+
+       do {
+               *(spi_address + 2) |= 0x10;
+               val = *(spi_address + 0xd);
+       } while (val & 0x7);
+}
+
+u8 read_spi_status(volatile u8 * spi_address)
+{
+       u8 val;
+       *spi_address = 0x05;
+       *(spi_address + 1) = 0x11;
+       reset_internal_fifo_pointer(spi_address);
+       *(spi_address + 0xC) = 0x0;     /* dummy */
+       reset_internal_fifo_pointer(spi_address);
+       execute_command(spi_address);
+       wait4command_complete(spi_address);
+       reset_internal_fifo_pointer(spi_address);
+       val = *(spi_address + 0xC);
+       val = *(spi_address + 0xC);
+       return val;
+}
+
+void wait4flashpart_ready(volatile u8 * spi_address)
+{
+       while (read_spi_status(spi_address) & 1) ;
+}
+
+void write_spi_status(volatile u8 * spi_address, u8 status)
+{
+       *spi_address = 0x50;    /* EWSR */
+       *(spi_address + 1) = 0; /* RxByte=TxByte=0 */
+       execute_command(spi_address);
+       wait4command_complete(spi_address);
+
+       *spi_address = 0x01;    /* WRSR */
+       *(spi_address + 1) = 0x01;
+       reset_internal_fifo_pointer(spi_address);
+       *(spi_address + 0xC) = status;
+       reset_internal_fifo_pointer(spi_address);
+       execute_command(spi_address);
+       wait4command_complete(spi_address);
+       wait4flashpart_ready(spi_address);
+
+       read_spi_status(spi_address);
+}
+
+void read_spi_id(volatile u8 * spi_address)
+{
+       u8 mid = 0, did = 0;
+       *spi_address = 0x90;
+       *(spi_address + 1) = 0x23;      /* RxByte=2, TxByte=3 */
+       reset_internal_fifo_pointer(spi_address);
+       *(spi_address + 0xC) = 0;
+       *(spi_address + 0xC) = 0;
+       *(spi_address + 0xC) = 0;
+       reset_internal_fifo_pointer(spi_address);
+       execute_command(spi_address);
+       wait4command_complete(spi_address);
+       reset_internal_fifo_pointer(spi_address);
+       mid = *(spi_address + 0xC);
+       printk(BIOS_DEBUG, "mid=%x, did=%x\n", mid, did);
+       mid = *(spi_address + 0xC);
+       printk(BIOS_DEBUG, "mid=%x, did=%x\n", mid, did);
+       mid = *(spi_address + 0xC);
+       printk(BIOS_DEBUG, "mid=%x, did=%x\n", mid, did);
+
+       mid = *(spi_address + 0xC);
+       did = *(spi_address + 0xC);
+       printk(BIOS_DEBUG, "mid=%x, did=%x\n", mid, did);
+}
+
+void spi_write_enable(volatile u8 * spi_address)
+{
+       *spi_address = 0x06;    /* Write Enable */
+       *(spi_address + 1) = 0x0;       /* RxByte=0, TxByte=0 */
+       execute_command(spi_address);
+       wait4command_complete(spi_address);
+}
+
+void sector_erase_spi(volatile u8 * spi_address, u32 address)
+{
+       spi_write_enable(spi_address);
+       *spi_address = 0x20;
+       *(spi_address + 1) = 0x03;      /* RxByte=0, TxByte=3 */
+
+       reset_internal_fifo_pointer(spi_address);
+       *(spi_address + 0xC) = (address >> 16) & 0xFF;
+       *(spi_address + 0xC) = (address >> 8) & 0xFF;
+       *(spi_address + 0xC) = (address >> 0) & 0xFF;
+       reset_internal_fifo_pointer(spi_address);
+       execute_command(spi_address);
+       wait4command_complete(spi_address);
+       wait4flashpart_ready(spi_address);
+}
+
+void chip_erase_spi(volatile u8 * spi_address)
+{
+       spi_write_enable(spi_address);
+       *spi_address = 0xC7;
+       *(spi_address + 1) = 0x00;
+       execute_command(spi_address);
+       wait4command_complete(spi_address);
+       wait4flashpart_ready(spi_address);
+}
+
+void byte_program(volatile u8 * spi_address, u32 address, u32 data)
+{
+       spi_write_enable(spi_address);
+       *spi_address = 0x02;
+       *(spi_address + 1) = 0x0 << 4 | 4;
+       reset_internal_fifo_pointer(spi_address);
+       *(spi_address + 0xC) = (address >> 16) & 0xFF;
+       *(spi_address + 0xC) = (address >> 8) & 0xFF;
+       *(spi_address + 0xC) = (address >> 0) & 0xFF;
+       *(spi_address + 0xC) = data & 0xFF;
+       reset_internal_fifo_pointer(spi_address);
+       execute_command(spi_address);
+       wait4command_complete(spi_address);
+       wait4flashpart_ready(spi_address);
+}
+
+void dword_noneAAI_program(volatile u8 * spi_address, u32 address, u32 data)
+{
+       u8 i;
+       /*
+        * printk(BIOS_SPEW, "%s: addr=%x, data=%x\n", __func__, address, data);
+        */
+       for (i = 0; i < 4; i++) {
+               spi_write_enable(spi_address);
+               *spi_address = 0x02;
+               *(spi_address + 1) = 0x0 << 4 | 4;
+               reset_internal_fifo_pointer(spi_address);
+               *(spi_address + 0xC) = (address >> 16) & 0xFF;
+               *(spi_address + 0xC) = (address >> 8) & 0xFF;
+               *(spi_address + 0xC) = (address >> 0) & 0xFF;
+               *(spi_address + 0xC) = data & 0xFF;
+               data >>= 8;
+               address++;
+               reset_internal_fifo_pointer(spi_address);
+               execute_command(spi_address);
+               wait4command_complete(spi_address);
+               wait4flashpart_ready(spi_address);
+       }
+}
+
+void dword_program(volatile u8 * spi_address, u32 address, u32 data)
+{
+       spi_write_enable(spi_address);
+       *spi_address = 0x02;
+       *(spi_address + 1) = 0x0 << 4 | 7;
+       reset_internal_fifo_pointer(spi_address);
+       *(spi_address + 0xC) = (address >> 16) & 0xFF;
+       *(spi_address + 0xC) = (address >> 8) & 0xFF;
+       *(spi_address + 0xC) = (address >> 0) & 0xFF;
+       *(spi_address + 0xC) = data & 0xFF;
+       *(spi_address + 0xC) = (data >> 8) & 0xFF;
+       *(spi_address + 0xC) = (data >> 16) & 0xFF;
+       *(spi_address + 0xC) = (data >> 24) & 0xFF;
+       reset_internal_fifo_pointer(spi_address);
+       execute_command(spi_address);
+       wait4command_complete(spi_address);
+       wait4flashpart_ready(spi_address);
+}
+
+void direct_byte_program(volatile u8 * spi_address, volatile u32 * address, u32 data)
+{
+       spi_write_enable(spi_address);
+       *address = data;
+       wait4flashpart_ready(spi_address);
+}
diff --git a/src/southbridge/amd/cimx/sb800/spi.h b/src/southbridge/amd/cimx/sb800/spi.h
new file mode 100644 (file)
index 0000000..57921d9
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ *****************************************************************************
+ *
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2012 Advanced Micro Devices, 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; version 2 of the License.
+ *
+ * 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.
+ *
+ * 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
+ * ***************************************************************************
+ *
+ */
+
+#ifndef _SB800_CIMX_SPI_H_
+#define _SB800_CIMX_SPI_H_
+
+void execute_command(volatile u8 * spi_address);
+void wait4command_complete(volatile u8 * spi_address);
+void reset_internal_fifo_pointer(volatile u8 * spi_address);
+u8 read_spi_status(volatile u8 * spi_address);
+void wait4flashpart_ready(volatile u8 * spi_address);
+void write_spi_status(volatile u8 * spi_address, u8 status);
+void read_spi_id(volatile u8 * spi_address);
+void spi_write_enable(volatile u8 * spi_address);
+void sector_erase_spi(volatile u8 * spi_address, u32 address);
+void chip_erase_spi(volatile u8 * spi_address);
+void byte_program(volatile u8 * spi_address, u32 address, u32 data);
+void dword_noneAAI_program(volatile u8 * spi_address, u32 address, u32 data);
+void dword_program(volatile u8 * spi_address, u32 address, u32 data);
+void direct_byte_program(volatile u8 * spi_address, volatile u32 * address, u32 data);
+
+#endif