[coreboot] SB600 SPI Driver for Flashrom, addition of Generic SPI MMIO functions

Sean Nelson snelson at nmt.edu
Thu Oct 16 21:29:28 CEST 2008


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 at 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 at 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
-------------- next part --------------
An embedded and charset-unspecified text was scrubbed...
Name: sb600_spi_driver_rev4.diff
URL: <http://www.coreboot.org/pipermail/coreboot/attachments/20081016/a0cbef6b/attachment.ksh>


More information about the coreboot mailing list