[flashrom] A quick hack to support AMD Family 16h SOC
Wei Hu
wei at aristanetworks.com
Fri Jul 26 07:18:52 CEST 2013
Carl-Daniel,
Have you checked the public BKDG
http://support.amd.com/us/Processor_TechDocs/48751_BKDG_Fam_16h_Mod_00h-0Fh.pdf?
It actually does talk about the SPI registers in Section 3.26.9.2.
I'm not very familiar with AMD's code names, but I think Kabini's FCH
is called Yangtze? Hudson seems to be previous generations.
I'll give you modified patch a test tomorrow.
On Thu, Jul 25, 2013 at 7:21 PM, Carl-Daniel Hailfinger
<c-d.hailfinger.devel.2006 at gmx.net> wrote:
> Hello Wei Hu,
>
> thanks for your patch!
>
> Am 27.06.2013 02:34 schrieb Wei Hu:
>> In the past I posted a question at
>> http://www.flashrom.org/pipermail/flashrom/2013-April/010924.html
>> about failure to run flashrom on the new AMD SOC. It turns out the SPI
>> flash interface has introduced incompatible changes from SB600. I have
>> created a quick hack and made it available at
>> http://blogs.coreboot.org/blog/2013/06/26/gsoc-2013-flashrom-week-1-while1/.
>> Based on the discussion there I'm posting the patch here as well. Hope
>> it will be helpful.
>>
>> A quick hack to support AMD Family 16h SOC (Kabini).
>> This patch is just a proof of concept and incompatible with previous generations of AMD chipset.
>> Tested reading and writing on ASRock IMB-A180.
>>
>> Signed-off-by: Wei Hu <wei at aristanetworks.com>
>
> I have tried to change the patch in a way which keeps compatibility with
> older AMD chipsets.
> Please test with and without USE_THE_EXTENDED_SPIDataFifoPtr_REGISTER
> #defined. If any errors crop up, please send them to the mailing list in
> reply to this mail.
>
> The biggest problem was the missing register reference guide (RRG) for
> AMD FCH. I had to guess the way to identify affected chipsets, and I now
> test for PCI device ID 0x438d (Hudson FCH, probably too broad match). I
> really hope this is the right ID. It would be great if you could confirm
> that the FIFO pointer management change affects all FCH with this PCI
> device ID.
>
> Is there a way to get access to the RRG for Kabini or the integrated
> FCH? Right now my changes are guesses
>
> Signed-off-by: Wei Hu <wei at aristanetworks.com>
> Signed-off-by: Carl-Daniel Hailfinger <c-d.hailfinger.devel.2006 at gmx.net>
>
> Index: flashrom-kabini/sb600spi.c
> ===================================================================
> --- flashrom-kabini/sb600spi.c (Revision 1704)
> +++ flashrom-kabini/sb600spi.c (Arbeitskopie)
> @@ -45,6 +45,8 @@
>
> static uint8_t *sb600_spibar = NULL;
>
> +static int hudson_method = 0;
> +
> static void reset_internal_fifo_pointer(void)
> {
> mmio_writeb(mmio_readb(sb600_spibar + 2) | 0x10, sb600_spibar + 2);
> @@ -58,14 +60,17 @@
> {
> uint8_t tmp;
>
> +#ifdef USE_THE_EXTENDED_SPIDataFifoPtr_REGISTER
> + mmio_writeb(7, sb600_spibar + 0x1e);
> + tmp = mmio_readb(sb600_spibar + 0x1f);
> +#else /* either way works */
> tmp = mmio_readb(sb600_spibar + 0xd) & 0x07;
> want &= 0x7;
> +#endif
> if (want != tmp) {
> msg_perr("FIFO pointer corruption! Pointer is %d, wanted %d\n", tmp, want);
> - msg_perr("Something else is accessing the flash chip and "
> - "causes random corruption.\nPlease stop all "
> - "applications and drivers and IPMI which access the "
> - "flash chip.\n");
> + msg_perr("Something else is accessing the flash chip and causes random corruption.\n"
> + "Please stop all applications and drivers and IPMI which access the flash chip.\n");
> return 1;
> } else {
> msg_pspew("SB600 FIFO pointer is %d, wanted %d\n", tmp, want);
> @@ -99,7 +104,7 @@
> /* First byte is cmd which can not being sent through FIFO. */
> unsigned char cmd = *writearr++;
> unsigned int readoffby1;
> - unsigned char readwrite;
> + unsigned char readwrite = 0;
>
> writecnt--;
>
> @@ -118,15 +123,21 @@
> return SPI_INVALID_LENGTH;
> }
>
> - /* This is a workaround for a bug in SB600 and SB700. If we only send
> - * an opcode and no additional data/address, the SPI controller will
> - * read one byte too few from the chip. Basically, the last byte of
> - * the chip response is discarded and will not end up in the FIFO.
> - * It is unclear if the CS# line is set high too early as well.
> - */
> - readoffby1 = (writecnt) ? 0 : 1;
> - readwrite = (readcnt + readoffby1) << 4 | (writecnt);
> - mmio_writeb(readwrite, sb600_spibar + 1);
> + if (hudson_method) {
> + /* Use the extended TxByteCount and RxByteCount register. */
> + mmio_writeb(writecnt, sb600_spibar + 0x48);
> + mmio_writeb(readcnt, sb600_spibar + 0x4b);
> + } else {
> + /* This is a workaround for a bug in SB600 and SB700. If we only send
> + * an opcode and no additional data/address, the SPI controller will
> + * read one byte too few from the chip. Basically, the last byte of
> + * the chip response is discarded and will not end up in the FIFO.
> + * It is unclear if the CS# line is set high too early as well.
> + */
> + readoffby1 = (writecnt) ? 0 : 1;
> + readwrite = (readcnt + readoffby1) << 4 | (writecnt);
> + mmio_writeb(readwrite, sb600_spibar + 1);
> + }
> mmio_writeb(cmd, sb600_spibar + 0);
>
> /* Before we use the FIFO, reset it first. */
> @@ -171,27 +182,58 @@
> msg_pspew("[%02x]", cmd);
> }
> msg_pspew("\n");
> - if (compare_internal_fifo_pointer(writecnt))
> - return SPI_PROGRAMMER_ERROR;
>
> + /* Reading from the FIFO apparently doesn't advance the FIFO pointer on Hudson, but it does so on all
> + * chipsets before Hudson.
> + */
> + if (hudson_method) {
> + if (compare_internal_fifo_pointer(0))
> + return SPI_PROGRAMMER_ERROR;
> + } else {
> + if (compare_internal_fifo_pointer(writecnt))
> + return SPI_PROGRAMMER_ERROR;
> + }
> +
> msg_pspew("Reading: ");
> for (count = 0; count < readcnt; count++, readarr++) {
> *readarr = mmio_readb(sb600_spibar + 0xC);
> msg_pspew("[%02x]", *readarr);
> }
> msg_pspew("\n");
> - if (reset_compare_internal_fifo_pointer(readcnt + writecnt))
> - return SPI_PROGRAMMER_ERROR;
>
> - if (mmio_readb(sb600_spibar + 1) != readwrite) {
> - msg_perr("Unexpected change in SB600 read/write count!\n");
> - msg_perr("Something else is accessing the flash chip and "
> - "causes random corruption.\nPlease stop all "
> - "applications and drivers and IPMI which access the "
> - "flash chip.\n");
> - return SPI_PROGRAMMER_ERROR;
> + /* Reading from the FIFO apparently doesn't advance the FIFO pointer on Hudson, but it does so on all
> + * chipsets before Hudson.
> + */
> + if (hudson_method) {
> + if (compare_internal_fifo_pointer(0))
> + return SPI_PROGRAMMER_ERROR;
> + } else {
> + if (reset_compare_internal_fifo_pointer(readcnt + writecnt))
> + return SPI_PROGRAMMER_ERROR;
> }
>
> + if (hudson_method) {
> + uint8_t tmp_wc = mmio_readb(sb600_spibar + 0x48);
> + uint8_t tmp_rc = mmio_readb(sb600_spibar + 0x4b);
> + if ((tmp_rc != readcnt) || (tmp_wc != writecnt)) {
> + msg_perr("Unexpected change in Hudson read/write count: %i/%i instead of %i/%i!\n",
> + tmp_rc, tmp_wc, readcnt, writecnt);
> + msg_perr("Something else is accessing the flash chip and causes random corruption.\n"
> + "Please stop all applications and drivers and IPMI which access the flash "
> + "chip.\n");
> + return SPI_PROGRAMMER_ERROR;
> + }
> + } else {
> + uint8_t tmp_rw = mmio_readb(sb600_spibar + 1);
> + if (tmp_rw != readwrite) {
> + msg_perr("Unexpected change in SB600 read/write count: %i instead of %i!\n", tmp_rw,
> + readwrite);
> + msg_perr("Something else is accessing the flash chip and causes random corruption.\n"
> + "Please stop all applications and drivers and IPMI which access the flash "
> + "chip.\n");
> + return SPI_PROGRAMMER_ERROR;
> + }
> + }
> return 0;
> }
>
> @@ -310,6 +352,14 @@
> tmp = (mmio_readb(sb600_spibar + 0xd) >> 4) & 0x3;
> msg_pdbg("NormSpeed is %s MHz\n", speed_names[tmp]);
>
> + /* AMD Hudson apparently requires use of a different SPI registers for read/write counts. */
> + if (dev->device_id == 0x438d) {
> + msg_pdbg("Using AMD Hudson SPI access method.\n");
> + hudson_method = 1;
> + } else {
> + hudson_method = 0;
> + }
> +
> /* Look for the SMBus device. */
> smbus_dev = pci_dev_find(0x1002, 0x4385);
>
>
> --
> http://www.hailfinger.org/
>
More information about the flashrom
mailing list