Jordan Crouse wrote:
On 16/10/08 11:17 -0600, Sean Nelson wrote:
Ok, I've made the changes to the best of my abilities. If there's something else still wrong, I'll leave that to someone more qualified. Like the ROM Sharing Synchronization.
You are still missing the header and signed-off-by line.
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);
The address still needs to be mapped in /dev/mem. I don't see that code.
- if (sb600_flashport)
flashbus = BUS_TYPE_SB600_SPI;
- return (!sb600_flashport);
+}
I'm not sure I like this - I think this code should be chipset_enable.c with everything else. And I also think that we should re-use the "spibar" variable that ICH uses (perhaps better remamed) and then use some generic spi_read{8,16,32} and spi_write{8,16,32} functions. We may even be able to make the mapping code generic for all platforms.
The sb600_flashport[blah] = blah used below is accurate, but IMHO is just asking for trouble.
+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);
Just remove this all together - don't worry about the MAC stuff, that would be platform specific anyway.
- /* 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);
See how this is a little bit scary? Read/modify/write is your friend.
- 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;
+}
This patch adds ATI/AMD SB600 SPI interface, it also adds generic spi mmio functions for use else where with SPI (as suggested by Jordan Crouse). Detection code for the sb600 spi interface is in chipset_enable.c
Thanks to Jordan Crouse, Carl-Daniel Hailfinger, Corey Osgood, and Peter Stuge for all their help.
Signed-off-by: Sean Nelson snelson@nmt.edu
---
If there is anything left to be done, I'll leave that for someone else. I'm not understanding the Rom Sharing Syncing, and Jordan said to ignore and leave MAC for board_enable.c
This patch adds ATI/AMD SB600 SPI interface, it also adds generic spi mmio functions for use else where (as suggested by Jordan Crouse). Detection code for the sb600 spi interface is in chipset_enable.c
Thanks to Jordan Crouse, Carl-Daniel Hailfinger, Corey Osgood, and Peter Stuge for all their help.
Signed-off-by: Sean Nelson snelson@nmt.edu ---
Index: flash.h =================================================================== --- flash.h (revision 3659) +++ flash.h (working copy) @@ -380,11 +380,13 @@ BUS_TYPE_ICH7_SPI, BUS_TYPE_ICH9_SPI, BUS_TYPE_IT87XX_SPI, + BUS_TYPE_SB600_SPI, BUS_TYPE_VIA_SPI } flashbus_t;
extern flashbus_t flashbus; extern void *spibar; +extern void *spi_mmio_baseaddr;
/* Physical memory mapping device */ #if defined (__sun) && (defined(__i386) || defined(__amd64)) @@ -413,6 +415,12 @@ extern char *lb_part, *lb_vendor;
/* spi.c */ +uint8_t spi_read8(uint8_t reg); +uint16_t spi_read16(uint8_t reg); +uint32_t spi_read32(uint8_t reg); +void spi_write8(uint8_t reg, uint8_t val); +void spi_write16(uint8_t reg, uint16_t val); +void spi_write32(uint8_t reg, uint32_t val); int probe_spi_rdid(struct flashchip *flash); int probe_spi_rdid4(struct flashchip *flash); int probe_spi_res(struct flashchip *flash); @@ -454,6 +462,11 @@ int it8716f_spi_chip_read(struct flashchip *flash, uint8_t *buf); int it8716f_spi_chip_write(struct flashchip *flash, uint8_t *buf);
+/* sb600spi.c */ +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) @@ -29,7 +29,42 @@ #include "flash.h" #include "spi.h"
+static uint8_t spi_read8(uint8_t reg) +{ + volatile uint8_t regval; + regval = *(volatile uint8_t *) ((uint8_t *) spi_mmio_baseaddr + reg); + return regval; +}
+static uint16_t spi_read16(uint8_t reg) +{ + volatile uint16_t regval; + regval = *(volatile uint16_t *) ((uint8_t *) spi_mmio_baseaddr + reg); + return regval; +} + +static uint32_t spi_read32(uint8_t reg) +{ + volatile uint32_t regval; + regval = *(volatile uint32_t *) ((uint8_t *) spi_mmio_baseaddr + reg); + return regval; +} + +static void spi_write8(uint8_t reg, uint8_t val) +{ + (*(uint8_t *)((uint8_t *) spi_mmio_baseaddr + reg) = val); +} + +static void spi_write16(uint8_t reg, uint16_t val) +{ + (*(uint16_t *)((uint8_t *) spi_mmio_baseaddr + reg) = val); +} + +static void spi_write32(uint8_t reg, uint32_t val); +{ + (*(uint32_t *)((uint8_t *) spi_mmio_baseaddr + reg) = val); +} + void spi_prettyprint_status_register(struct flashchip *flash);
int spi_command(unsigned int writecnt, unsigned int readcnt, const unsigned char *writearr, unsigned char *readarr) @@ -37,6 +72,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 +176,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: @@ -378,6 +416,8 @@ {
switch (flashbus) { + case BUS_TYPE_SB600_SPI: + return sb600_spi_chip_read(flash, buf); case BUS_TYPE_IT87XX_SPI: return it8716f_spi_chip_read(flash, buf); case BUS_TYPE_ICH7_SPI: @@ -394,6 +434,8 @@ int spi_chip_write(struct flashchip *flash, uint8_t *buf) { switch (flashbus) { + case BUS_TYPE_SB600_SPI: + return sb600_spi_chip_write(flash, buf); case BUS_TYPE_IT87XX_SPI: return it8716f_spi_chip_write(flash, buf); case BUS_TYPE_ICH7_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: chipset_enable.c =================================================================== --- chipset_enable.c (revision 3659) +++ chipset_enable.c (working copy) @@ -44,6 +44,7 @@
flashbus_t flashbus = BUS_TYPE_LPC; void *spibar = NULL; +void *spi_mmio_baseaddr = NULL;
static int enable_flash_ali_m1533(struct pci_dev *dev, const char *name) @@ -221,6 +222,29 @@ return 0; }
+static int enable_flash_sb600_spi(struct pci_dev *dev, const char *name) +{ + uint32_t flashspi_base; + + /* SPI Base Address (A0h) */ + flashspi_base = pci_read_word(dev, 0xa0); + printf_debug("MMIO base at = 0x%x\n", flashspi_base); + + sb600_spibase = mmap(NULL, 0x20, PROT_WRITE | PROT_READ, MAP_SHARED, + fd_mem, flashspi_base); + + if (sb600_spibase == MAP_FAILED) + { + perror("Can't mmpa memory using " MEM_DEV); + exit(1); + } + + flashbus = BUS_TYPE_SB600_SPI; + + return 0; +} + + static int enable_flash_ich_dc_spi(struct pci_dev *dev, const char *name, int ich_generation) { int ret, i; Index: sb600spi.c =================================================================== --- sb600spi.c (revision 0) +++ sb600spi.c (revision 0) @@ -0,0 +1,151 @@ +/* + * 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" + +/* use fast 33MHz SPI (<>0) or slow 16MHz (0) */ +int fast_spi = 1; + +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, sendbits; + int i; + + /* Make sure we have the SPI's MMIO BaseAddr set for use */ + if (spi_mmio_baseaddr != 0) + { + printf("spi_mmio_baseaddr needs to be set to use sb600 SPI\n"); + return 1; + } + + /* 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; + } + + /* check what the fifo ptr is (bits 2-0) */ + FifoPtr = spi_read8(0x0d) & 0x7; + /* clear fifo ptr (bit 4) */ + if(FifoPtr != 0) + { + FifoPtrClr = spi_read8(0x03); + spi_write8(0x03, FifoPtrClr|(1<<4)); + } + spi_write(0x00, writearr[0]); + for(i=1; i < writecnt; i++) + { + /* write fifo byte */ + spi_write8(0x0c, writearr[i]); + /* increment fifo ptr; to get next byte (bit 5) */ + FifoPtrInc = spi_read8(0x03); + spi_write8(0x03, FifoPtrInc|(1<<5)); + } + + /* + * set the SPI clock speed (0x0D) + * NormSpeed: bit 5 & 4 + * FastSpeed: bit 7 & 6 + * + * 33MHz - 0x1 + * 22MHz - 0x2 + * 16.5MHz - 0x3 + */ + speed = spi_read8(0x0d); + spi_write8(0x0d, speed | ((fast_spi ? 1 : 3)<<6) | ((fast_spi ? 1 : 3)<<4) ); + + /* + * set the TxByte and RxBytes (0x01) + * TxByteCount: bit 3-0 + * RxByteCount: bit 7-4 + */ + sendbits = spi_read8(0x01); + spi_write8(0x01, sendbits | ((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 + */ + cmd_exec = spi_read8(0x02); + spi_write8(0x02 ,cmd_exec|(1<<0)); + + /* check what the fifo ptr is (bits 2-0) */ + FifoPtr = spi_read8(0x0d) & 0x7; + /* clear fifo ptr (bit 4) */ + if(FifoPtr != 0) + { + FifoPtrClr = spi_read8(0x03); + spi_write8(0x03, FifoPtrClr|(1<<4)); + } + if (readcnt > 0) { + for (i = 0; i < readcnt; i++) { + /* read fifo byte */ + readarr[i] = spi_read8(0x0c); + /* increment fifo ptr; to get next byte (bit 5) */ + FifoPtrInc = spi_read8(0x03); + spi_write8(0x03, FifoPtrInc|(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; +} +