2 * This file is part of the coreboot project.
4 * Copyright (C) 2012 Advanced Micro Devices, Inc.
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 2 of the License.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 #include <console/console.h>
21 #include <device/device.h>
22 #include "SBPLATFORM.h"
25 void execute_command(volatile u8 * spi_address)
27 *(spi_address + 2) |= 1;
30 void wait4command_complete(volatile u8 * spi_address)
32 while (*(spi_address + 2) & 1)
33 printk(BIOS_DEBUG, "wait4CommandComplete\n");
36 void reset_internal_fifo_pointer(volatile u8 * spi_address)
41 *(spi_address + 2) |= 0x10;
42 val = *(spi_address + 0xd);
46 u8 read_spi_status(volatile u8 * spi_address)
50 *(spi_address + 1) = 0x11;
51 reset_internal_fifo_pointer(spi_address);
52 *(spi_address + 0xC) = 0x0; /* dummy */
53 reset_internal_fifo_pointer(spi_address);
54 execute_command(spi_address);
55 wait4command_complete(spi_address);
56 reset_internal_fifo_pointer(spi_address);
57 val = *(spi_address + 0xC);
58 val = *(spi_address + 0xC);
62 void wait4flashpart_ready(volatile u8 * spi_address)
64 while (read_spi_status(spi_address) & 1) ;
67 void write_spi_status(volatile u8 * spi_address, u8 status)
69 *spi_address = 0x50; /* EWSR */
70 *(spi_address + 1) = 0; /* RxByte=TxByte=0 */
71 execute_command(spi_address);
72 wait4command_complete(spi_address);
74 *spi_address = 0x01; /* WRSR */
75 *(spi_address + 1) = 0x01;
76 reset_internal_fifo_pointer(spi_address);
77 *(spi_address + 0xC) = status;
78 reset_internal_fifo_pointer(spi_address);
79 execute_command(spi_address);
80 wait4command_complete(spi_address);
81 wait4flashpart_ready(spi_address);
83 read_spi_status(spi_address);
86 void read_spi_id(volatile u8 * spi_address)
90 *(spi_address + 1) = 0x23; /* RxByte=2, TxByte=3 */
91 reset_internal_fifo_pointer(spi_address);
92 *(spi_address + 0xC) = 0;
93 *(spi_address + 0xC) = 0;
94 *(spi_address + 0xC) = 0;
95 reset_internal_fifo_pointer(spi_address);
96 execute_command(spi_address);
97 wait4command_complete(spi_address);
98 reset_internal_fifo_pointer(spi_address);
99 mid = *(spi_address + 0xC);
100 printk(BIOS_DEBUG, "mid=%x, did=%x\n", mid, did);
101 mid = *(spi_address + 0xC);
102 printk(BIOS_DEBUG, "mid=%x, did=%x\n", mid, did);
103 mid = *(spi_address + 0xC);
104 printk(BIOS_DEBUG, "mid=%x, did=%x\n", mid, did);
106 mid = *(spi_address + 0xC);
107 did = *(spi_address + 0xC);
108 printk(BIOS_DEBUG, "mid=%x, did=%x\n", mid, did);
111 void spi_write_enable(volatile u8 * spi_address)
113 *spi_address = 0x06; /* Write Enable */
114 *(spi_address + 1) = 0x0; /* RxByte=0, TxByte=0 */
115 execute_command(spi_address);
116 wait4command_complete(spi_address);
119 void sector_erase_spi(volatile u8 * spi_address, u32 address)
121 spi_write_enable(spi_address);
123 *(spi_address + 1) = 0x03; /* RxByte=0, TxByte=3 */
125 reset_internal_fifo_pointer(spi_address);
126 *(spi_address + 0xC) = (address >> 16) & 0xFF;
127 *(spi_address + 0xC) = (address >> 8) & 0xFF;
128 *(spi_address + 0xC) = (address >> 0) & 0xFF;
129 reset_internal_fifo_pointer(spi_address);
130 execute_command(spi_address);
131 wait4command_complete(spi_address);
132 wait4flashpart_ready(spi_address);
135 void chip_erase_spi(volatile u8 * spi_address)
137 spi_write_enable(spi_address);
139 *(spi_address + 1) = 0x00;
140 execute_command(spi_address);
141 wait4command_complete(spi_address);
142 wait4flashpart_ready(spi_address);
145 void byte_program(volatile u8 * spi_address, u32 address, u32 data)
147 spi_write_enable(spi_address);
149 *(spi_address + 1) = 0x0 << 4 | 4;
150 reset_internal_fifo_pointer(spi_address);
151 *(spi_address + 0xC) = (address >> 16) & 0xFF;
152 *(spi_address + 0xC) = (address >> 8) & 0xFF;
153 *(spi_address + 0xC) = (address >> 0) & 0xFF;
154 *(spi_address + 0xC) = data & 0xFF;
155 reset_internal_fifo_pointer(spi_address);
156 execute_command(spi_address);
157 wait4command_complete(spi_address);
158 wait4flashpart_ready(spi_address);
161 void dword_noneAAI_program(volatile u8 * spi_address, u32 address, u32 data)
165 * printk(BIOS_SPEW, "%s: addr=%x, data=%x\n", __func__, address, data);
167 for (i = 0; i < 4; i++) {
168 spi_write_enable(spi_address);
170 *(spi_address + 1) = 0x0 << 4 | 4;
171 reset_internal_fifo_pointer(spi_address);
172 *(spi_address + 0xC) = (address >> 16) & 0xFF;
173 *(spi_address + 0xC) = (address >> 8) & 0xFF;
174 *(spi_address + 0xC) = (address >> 0) & 0xFF;
175 *(spi_address + 0xC) = data & 0xFF;
178 reset_internal_fifo_pointer(spi_address);
179 execute_command(spi_address);
180 wait4command_complete(spi_address);
181 wait4flashpart_ready(spi_address);
185 void dword_program(volatile u8 * spi_address, u32 address, u32 data)
187 spi_write_enable(spi_address);
189 *(spi_address + 1) = 0x0 << 4 | 7;
190 reset_internal_fifo_pointer(spi_address);
191 *(spi_address + 0xC) = (address >> 16) & 0xFF;
192 *(spi_address + 0xC) = (address >> 8) & 0xFF;
193 *(spi_address + 0xC) = (address >> 0) & 0xFF;
194 *(spi_address + 0xC) = data & 0xFF;
195 *(spi_address + 0xC) = (data >> 8) & 0xFF;
196 *(spi_address + 0xC) = (data >> 16) & 0xFF;
197 *(spi_address + 0xC) = (data >> 24) & 0xFF;
198 reset_internal_fifo_pointer(spi_address);
199 execute_command(spi_address);
200 wait4command_complete(spi_address);
201 wait4flashpart_ready(spi_address);
204 void direct_byte_program(volatile u8 * spi_address, volatile u32 * address, u32 data)
206 spi_write_enable(spi_address);
208 wait4flashpart_ready(spi_address);