Peter Stuge wrote:
Sean Nelson wrote:
sb600 spi driver file for flashrom
This one needs some more work.
The SB600 SPI controller registers aren't IO mapped like on the superios, but memory mapped according to the 0xa0 BAR in the LPC bridge. See page 260 of 46155_sb600_rrg_pub_3.03.pdf.
This driver must also be careful to properly synchronize when ROM sharing is being used.
Some more comments:
+static uint16_t find_sb600_spi_flash_port(uint16_t device_id) +{
- struct pci_dev *dev;
- uint16_t flashport = 0;
- /* sb600's LPC ISA Bridge */
- dev = pci_dev_find(0x1002, device_id);
Must check return value here:
if (!dev) return 1;
+int sb600_probe_spi_flash(const char *name) +{
- sb600_flashport = find_ite_spi_flash_port(0x438d);
- if (sb600_flashport)
flashbus = BUS_TYPE_SB600_SPI;
- return (!it8716f_flashport);
+}
I'd prefer merging these two functions into one because find_ite_spi_flash_port() will never be called from anywhere else.
Also there seems to be a copypaste error here, it8716f_flashport can't be right. :)
+int sb600_spi_command(unsigned int writecnt, unsigned int readcnt, const unsigned char *writearr, unsigned char *readarr) +{
- uint8_t busy, speed;
- int i;
- if (readcnt > 8) {
printf("%s called with unsupported readcnt %i.\n",
__FUNCTION__, readcnt);
return 1;
- }
Make sure to check writecnt as well. And please use __func__ instead of __FUNCTION__ everywhere.
//Peter
-- coreboot mailing list: coreboot@coreboot.org http://www.coreboot.org/mailman/listinfo/coreboot
Thanks to Jordan Crouse, for telling me to change flashrom to use sb600 SPI drive.
Index: flash.h =================================================================== --- flash.h (revision 3659) +++ flash.h (working copy) @@ -380,6 +380,7 @@ BUS_TYPE_ICH7_SPI, BUS_TYPE_ICH9_SPI, BUS_TYPE_IT87XX_SPI, + BUS_TYPE_SB600_SPI, BUS_TYPE_VIA_SPI } flashbus_t;
@@ -454,6 +455,13 @@ int it8716f_spi_chip_read(struct flashchip *flash, uint8_t *buf); int it8716f_spi_chip_write(struct flashchip *flash, uint8_t *buf);
+/* sb600spi.c */ +extern uint16_t sb600_flashport; +int sb600_probe_spi_flash(const char *name); +int sb600_spi_command(unsigned int writecnt, unsigned int readcnt, const unsigned char *writearr, unsigned char *readarr); +int sb600_spi_chip_read(struct flashchip *flash, uint8_t *buf); +int sb600_spi_chip_write(struct flashchip *flash, uint8_t *buf); + /* jedec.c */ uint8_t oddparity(uint8_t val); void toggle_ready_jedec(volatile uint8_t *dst); Index: spi.c =================================================================== --- spi.c (revision 3659) +++ spi.c (working copy) @@ -37,6 +37,8 @@ switch (flashbus) { case BUS_TYPE_IT87XX_SPI: return it8716f_spi_command(writecnt, readcnt, writearr, readarr); + case BUS_TYPE_SB600_SPI: + return sb600_spi_command(writecnt, readcnt, writearr, readarr); case BUS_TYPE_ICH7_SPI: case BUS_TYPE_ICH9_SPI: case BUS_TYPE_VIA_SPI: @@ -139,6 +141,7 @@
/* only some SPI chipsets support 4 bytes commands */ switch (flashbus) { + case BUS_TYPE_SB600_SPI: case BUS_TYPE_ICH7_SPI: case BUS_TYPE_ICH9_SPI: case BUS_TYPE_VIA_SPI: @@ -380,6 +383,8 @@ switch (flashbus) { case BUS_TYPE_IT87XX_SPI: return it8716f_spi_chip_read(flash, buf); + case BUS_TYPE_SB600_SPI: + return sb600_spi_chip_read(flash, buf); case BUS_TYPE_ICH7_SPI: case BUS_TYPE_ICH9_SPI: case BUS_TYPE_VIA_SPI: @@ -396,6 +401,8 @@ switch (flashbus) { case BUS_TYPE_IT87XX_SPI: return it8716f_spi_chip_write(flash, buf); + case BUS_TYPE_SB600_SPI: + return sb600_spi_chip_write(flash, buf); case BUS_TYPE_ICH7_SPI: case BUS_TYPE_ICH9_SPI: case BUS_TYPE_VIA_SPI: Index: Makefile =================================================================== --- Makefile (revision 3659) +++ Makefile (working copy) @@ -29,7 +29,7 @@ w49f002u.o 82802ab.o pm49fl00x.o sst49lf040.o en29f002a.o \ sst49lfxxxc.o sst_fwhub.o layout.o cbtable.o flashchips.o \ flashrom.o w39v080fa.o sharplhf00l04.o w29ee011.o spi.o it87spi.o \ - ichspi.o w39v040c.o + ichspi.o w39v040c.o sb600spi.o
all: pciutils dep $(PROGRAM)
Index: sb600spi.c =================================================================== --- sb600spi.c (revision 0) +++ sb600spi.c (revision 0) @@ -0,0 +1,165 @@ +/* + * This file is part of the flashrom project. + * + * Copyright (C) 2008 Sean Nelson snelson@nmt.edu + * + * 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 + */ + +/* + * SPI interface for SB600 + * Note for the SB600 in Sharing Mode (BIOS and MAC): + * This driver must also be careful to properly synchronize when + * NOTE: This SPI is memory mapped not IO mapped, so no INB/OUTB + */ + +#include <stdio.h> +#include <pci/pci.h> +#include <stdint.h> +#include <string.h> +#include "flash.h" +#include "spi.h" + +uint16_t sb600_flashport = 0; + +/* use fast 33MHz SPI (<>0) or slow 16MHz (0) */ +int fast_spi = 1; + +int sb600_probe_spi_flash(const char *name) +{ + + struct pci_dev *dev; + uint16_t flashport = 0; + + /* sb600's LPC ISA Bridge */ + dev = pci_dev_find(0x1002, device_id); + + if (!dev) + return 1; + + /* SPI Base Address (A0h) */ + sb600_flashport = pci_read_word(dev, 0xa0); + + if (sb600_flashport) + flashbus = BUS_TYPE_SB600_SPI; + + return (!sb600_flashport); +} + +int sb600_spi_command(unsigned int writecnt, unsigned int readcnt, + const unsigned char *writearr, unsigned char *readarr) +{ + uint8_t busy, speed, cmd_exec, FifoPtr, FifoPtrClr, FifoPtrInc; + int i; + + /* the sb600 fifo can only handle 8 bytes for reading + * and 8 bytes for writing + */ + if (readcnt > 8) { + printf("%s called with unsupported readcnt %i.\n", + __func__, readcnt); + return 1; + } + + /* the write count for the sb600 is the number of bytes being sent + * through the FIFO which doesn't include the cmd byte that we count + * as part of the write count + */ + if ((writecnt-1) > 8) { + printf("%s called with unsupported writecnt %i.\n", + __func__, (writecnt-1)); + return 1; + } + + /* + * The SB600 SPI can share between BIOS and MAC, so we must lock to BIOS + * and unlock to allow Access for the MAC + * or Should we ?? + */ + //sb600_flashport[] |= (1<<3); + + /* check what the fifo ptr is (bits 2-0) */ + FifoPtr = sb600_flashport[0x0d] & 0x7; + /* clear fifo ptr (bit 4) */ + if(FifoPtr != 0) + sb600_flashport[0x03] |= (1<<4); + + sb600_flashport[0x00] = writearr[0]; + for(i=1; i < writecnt; i++) + { + /* read fifo byte */ + sb600_flashport[0x0c] = writearr[i]; + /* increment fifo ptr; to get next byte (bit 5) */ + sb600_flashport[0x03] |= (1<<5); + } + + /* + * set the SPI clock speed (0x0D) + * NormSpeed: bit 5 & 4 + * FastSpeed: bit 7 & 6 + * + * 33MHz - 0x1 + * 22MHz - 0x2 + * 16.5MHz - 0x3 + */ + sb600_flashport[0x0d] = (fast_spi ? 1 : 3)<<6; + sb600_flashport[0x0d] = (fast_spi ? 1 : 3)<<4; + + /* + * set the TxByte and RxBytes (0x01) + * TxByteCount: bit 3-0 + * RxByteCount: bit 7-4 + */ + sb600_flashport[0x01] = ((writecnt-1)<<4)|(readcnt); + + /* + * start the command execution (0x02) + * ExecuteOpCode: bit 0; start off the SPI command + * Reserved: bit 1&2 + * SpiArbEnable: bit 3; 0 to speed up SPI ROM Access, if only BIOS + */ + sb600_flashport[0x02] |= (1<<0); + + /* check what the fifo ptr is (bits 2-0) */ + FifoPtr = sb600_flashport[0x0d] & 0x7; + /* clear fifo ptr (bit 4) */ + if(FifoPtr != 0) + sb600_flashport[0x03] |= (1<<4); + + if (readcnt > 0) { + for (i = 0; i < readcnt; i++) { + /* read fifo byte */ + readarr[i] = sb600_flashport[0x0c]; + /* increment fifo ptr; to get next byte (bit 5) */ + sb600_flashport[0x03] |= (1<<5); + } + } + + return 0; +} + +int sb600_spi_chip_read(struct flashchip *flash, uint8_t *buf) +{ + int total_size = 1024 * flash->total_size; + memcpy(buf, (const char *)flash->virtual_memory, total_size); + return 0; +} + +int sb600_spi_chip_write(struct flashchip *flash, uint8_t *buf) +{ + int total_size = 1024 * flash->total_size; + memcpy((const char*)flash->virtual_memory, buf, total_size); + return 0; +} +