summaryrefslogtreecommitdiff
path: root/src/southbridge
diff options
context:
space:
mode:
authorzbao <fishbaozi@gmail.com>2012-03-23 11:36:08 +0800
committerMarc Jones <marcj303@gmail.com>2012-04-02 20:35:03 +0200
commit01bd79ff697b4a6976e2b03ff15f4853fa561c0d (patch)
treef277f59e299dcdadb141616a230ee2d47d6666d4 /src/southbridge
parent971804ed68347f4fe7ca985a3c924b28041a4079 (diff)
downloadcoreboot-01bd79ff697b4a6976e2b03ff15f4853fa561c0d.tar.xz
Add sb800 spi support.
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>
Diffstat (limited to 'src/southbridge')
-rw-r--r--src/southbridge/amd/cimx/sb800/Makefile.inc2
-rw-r--r--src/southbridge/amd/cimx/sb800/SBPLATFORM.h4
-rw-r--r--src/southbridge/amd/cimx/sb800/spi.c209
-rw-r--r--src/southbridge/amd/cimx/sb800/spi.h42
4 files changed, 257 insertions, 0 deletions
diff --git a/src/southbridge/amd/cimx/sb800/Makefile.inc b/src/southbridge/amd/cimx/sb800/Makefile.inc
index 30d2133715..2b55feeb1c 100644
--- a/src/southbridge/amd/cimx/sb800/Makefile.inc
+++ b/src/southbridge/amd/cimx/sb800/Makefile.inc
@@ -27,6 +27,8 @@ romstage-y += smbus.c
ramstage-y += cfg.c
ramstage-y += late.c
+ramstage-$(CONFIG_HAVE_ACPI_RESUME) += spi.c
+
driver-y += smbus.c
driver-y += lpc.c
diff --git a/src/southbridge/amd/cimx/sb800/SBPLATFORM.h b/src/southbridge/amd/cimx/sb800/SBPLATFORM.h
index db5343dff0..25aba95280 100644
--- a/src/southbridge/amd/cimx/sb800/SBPLATFORM.h
+++ b/src/southbridge/amd/cimx/sb800/SBPLATFORM.h
@@ -158,4 +158,8 @@ typedef union _PCI_ADDR {
#include "vendorcode/amd/cimx/sb800/AMDSBLIB.h"
+#if CONFIG_HAVE_ACPI_RESUME == 1
+#include "spi.h"
+#endif
+
#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
index 0000000000..b0ef753e10
--- /dev/null
+++ b/src/southbridge/amd/cimx/sb800/spi.c
@@ -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
index 0000000000..57921d9dfc
--- /dev/null
+++ b/src/southbridge/amd/cimx/sb800/spi.h
@@ -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