sb600 spi driver file for flashrom
Index: sb600spi.c =================================================================== --- sb600spi.c (revision 0) +++ sb600spi.c (revision 0) @@ -0,0 +1,126 @@ +/* + * 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 + */ + +#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; + +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); + + /* SPI Base Address (A0h) */ + flashport = pci_read_word(dev, 0xa0); + + return flashport; +} + +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); +} + +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; + } + + OUTB(writearr[0], sb600_flashport + 0x00); + for(i=1; i < (writecnt-1); i++) + { + OUTB(writearr[i], sb600_flashport + 0x0c); + } + + /* + * set the SPI clock speed (0x0D) + * NormSpeed: bit 5 & 4 + * FastSpeed: bit 7 & 6 + * + * 33MHz - 01b + * 16.5MHz - 11b + */ + speed = (fast_spi ? 1 : 3)<<6; + speed = (fast_spi ? 1 : 3)<<4; + OUTB(speed, sb600_flashport); + + /* + * set the TxByte and RxBytes (0x01) + * TxByteCount: bit 3-0 + * RxByteCount: bit 7-4 + */ + OUTB(((writecnt-1)<<4)|(readcnt), sb600_flashport) + + /* + * 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 + */ + OUTB((1<<3)|(1<<0), sb600_flashport); + + if (readcnt > 0) { + for (i = 0; i < readcnt; i++) { + readarr[i] = INB(sb600_flashport + 0x0c); + } + } + + 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; +} +
Thanks for your contribution! I know nothing about sb600, so I'll leave code review to those who know, but for the patch itself, we need a sign-off before we can commit any patches, see this: http://www.coreboot.org/Development_Guidelines#Sign-off_Procedure Please repost with your sign off, I assume this applies to your other patch too.
Thanks! Corey
2008/10/15 Sean Nelson snelson@nmt.edu
sb600 spi driver file for flashrom
Index: sb600spi.c
--- sb600spi.c (revision 0) +++ sb600spi.c (revision 0) @@ -0,0 +1,126 @@ +/*
- 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
- */
+#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;
+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);
/* SPI Base Address (A0h) */
flashport = pci_read_word(dev, 0xa0);
return flashport;
+}
+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);
+}
+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;
}
OUTB(writearr[0], sb600_flashport + 0x00);
for(i=1; i < (writecnt-1); i++)
{
OUTB(writearr[i], sb600_flashport + 0x0c);
}
/*
* set the SPI clock speed (0x0D)
* NormSpeed: bit 5 & 4
* FastSpeed: bit 7 & 6
*
* 33MHz - 01b
* 16.5MHz - 11b
*/
speed = (fast_spi ? 1 : 3)<<6;
speed = (fast_spi ? 1 : 3)<<4;
OUTB(speed, sb600_flashport);
/*
* set the TxByte and RxBytes (0x01)
* TxByteCount: bit 3-0
* RxByteCount: bit 7-4
*/
OUTB(((writecnt-1)<<4)|(readcnt), sb600_flashport)
/*
* 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
*/
OUTB((1<<3)|(1<<0), sb600_flashport);
if (readcnt > 0) {
for (i = 0; i < readcnt; i++) {
readarr[i] = INB(sb600_flashport + 0x0c);
}
}
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;
+}
-- coreboot mailing list: coreboot@coreboot.org http://www.coreboot.org/mailman/listinfo/coreboot
Corey Osgood wrote:
Thanks for your contribution! I know nothing about sb600, so I'll leave code review to those who know, but for the patch itself, we need a sign-off before we can commit any patches, see this: http://www.coreboot.org/Development_Guidelines#Sign-off_Procedure Please repost with your sign off, I assume this applies to your other patch too.
Thanks! Corey
2008/10/15 Sean Nelson <snelson@nmt.edu mailto:snelson@nmt.edu>
sb600 spi driver file for flashrom Index: sb600spi.c =================================================================== --- sb600spi.c (revision 0) +++ sb600spi.c (revision 0) @@ -0,0 +1,126 @@ +/* + * This file is part of the flashrom project. + * + * Copyright (C) 2008 Sean Nelson <snelson@nmt.edu <mailto: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 + */ + +#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; + +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); + + /* SPI Base Address (A0h) */ + flashport = pci_read_word(dev, 0xa0); + + return flashport; +} + +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); +} + +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; + } + + OUTB(writearr[0], sb600_flashport + 0x00); + for(i=1; i < (writecnt-1); i++) + { + OUTB(writearr[i], sb600_flashport + 0x0c); + } + + /* + * set the SPI clock speed (0x0D) + * NormSpeed: bit 5 & 4 + * FastSpeed: bit 7 & 6 + * + * 33MHz - 01b + * 16.5MHz - 11b + */ + speed = (fast_spi ? 1 : 3)<<6; + speed = (fast_spi ? 1 : 3)<<4; + OUTB(speed, sb600_flashport); + + /* + * set the TxByte and RxBytes (0x01) + * TxByteCount: bit 3-0 + * RxByteCount: bit 7-4 + */ + OUTB(((writecnt-1)<<4)|(readcnt), sb600_flashport) + + /* + * 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 + */ + OUTB((1<<3)|(1<<0), sb600_flashport); + + if (readcnt > 0) { + for (i = 0; i < readcnt; i++) { + readarr[i] = INB(sb600_flashport + 0x0c); + } + } + + 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; +} + -- coreboot mailing list: coreboot@coreboot.org <mailto:coreboot@coreboot.org> http://www.coreboot.org/mailman/listinfo/coreboot
Thanks to Peter Stuge for help. The SPI interface is for the ATI/AMD SB600 Southbridge. This was easier than the Fintek SPI interface.
Signed-off-by: Sean Nelson snelson@nmt.edu --- This code was developed using the datasheets and has not been tested.
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
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
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.
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; +} +
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;
+}
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; +} +
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; +} +