[LinuxBIOS] [PATCH] Re: Interest in a Free Software BIOS for Radeon cards?

Carl-Daniel Hailfinger c-d.hailfinger.devel.2006 at gmx.net
Tue Dec 18 15:56:26 CET 2007


Add support for reading the AMD/ATI RV630 graphics chipset flash ROM.
Needs a board enable command line option (flashrom -m AMDATI:RV630)
Works with RV630, but BAR addresses have to be fixed up.
A timing issue causes all reads to be right-shifted by one bit,
resulting in the loss of the LSB.
For better debugging, I have to know the exact model of the flash chip
and the frequency currently on the SCK connector of the flash chip.

Signed-off-by: Carl-Daniel Hailfinger <c-d.hailfinger.devel.2006 at gmx.net>

Index: flashrom-ati/flash.h
===================================================================
--- flashrom-ati/flash.h	(Revision 3012)
+++ flashrom-ati/flash.h	(Arbeitskopie)
@@ -262,6 +262,8 @@
 /* spi.c */
 int probe_spi(struct flashchip *flash);
 int it87xx_probe_spi_flash(const char *name);
+int ati_probe_spi_settings(const char *name);
+void read_ati_rom(char *buf, int size);
 int generic_spi_command(unsigned int writecnt, unsigned int readcnt, const unsigned char *writearr, unsigned char *readarr);
 void generic_spi_write_enable();
 void generic_spi_write_disable();
Index: flashrom-ati/spi.c
===================================================================
--- flashrom-ati/spi.c	(Revision 3012)
+++ flashrom-ati/spi.c	(Arbeitskopie)
@@ -22,9 +22,14 @@
  */
 
 #include <stdio.h>
+#include <errno.h>
+#include <fcntl.h>
 #include <pci/pci.h>
 #include <stdint.h>
+#include <stdlib.h>
 #include <string.h>
+#include <sys/mman.h>
+#include <unistd.h>
 #include "flash.h"
 
 #define ITE_SUPERIO_PORT1	0x2e
@@ -216,6 +221,158 @@
 	return 0;
 }
 
+int mem_fd = -1;
+unsigned int *ati_reg_mem_map = NULL;
+
+/* lspci output...
+ */
+
+#error You must fix up reg_addr and reg_len below, then remove the #error.
+unsigned int reg_addr = 0xff5f0000;
+unsigned int reg_len = 0x10000;
+
+unsigned int ati_register_read(unsigned int key)
+{
+  return ati_reg_mem_map[key >> 2];
+}
+
+/* FIXME: How are we going to make sure the write actually gets posted? */
+void ati_register_write(unsigned int key, unsigned int val)
+{
+  ati_reg_mem_map[key >> 2] = val;
+}
+
+int ati_open()
+{
+	if ((mem_fd = open("/dev/mem", O_RDWR)) < 0) {
+		fprintf(stderr, "flashrom: %s:%d: %s\n",
+			__FILE__, __LINE__, strerror(errno));
+		exit(EXIT_FAILURE);
+	}
+
+	// detect_reg_aperture();
+	if ((ati_reg_mem_map =
+		mmap(NULL, reg_len, PROT_READ | PROT_WRITE, MAP_SHARED, mem_fd,
+			reg_addr)) == MAP_FAILED) {
+		fprintf(stderr, "flashrom: %s:%d: %s\n",
+			__FILE__, __LINE__, strerror(errno));
+		exit(EXIT_FAILURE);
+	}
+	return 0;
+}
+
+int ati_close()
+{
+	if (munmap(ati_reg_mem_map, reg_len) < 0) {
+		fprintf(stderr, "flashrom: %s:%d: %s\n",
+			__FILE__, __LINE__, strerror(errno));
+		exit(EXIT_FAILURE);
+	}
+
+	if (close(mem_fd) < 0) {
+		fprintf(stderr, "flashrom: %s:%d: %s\n",
+			__FILE__, __LINE__, strerror(errno));
+		exit(EXIT_FAILURE);
+	}
+
+	return 0;
+}
+
+#define ATI_RV630
+
+#ifdef ATI_RV630
+/* all of the register indices are relative to GpuF0MMREG */
+#define ATI_BUS_CNTL	0x5420
+#define ATI_ROM_CNTL	0x1600
+#define ATI_ROM_STATUS	0x1608
+#define ATI_ROM_INDEX	0xA8
+#define ATI_ROM_DATA	0xAC
+#define ATI_ROM_START	0x1614
+#define ATI_ROM_UNK1	0x1604
+#define ATI_ROM_UNK2	0x160C
+#define ATI_ROM_UNK3	0x1610
+#else /* M56, does not work yet */
+/* register indices are relative to HIDEC */
+#define ATI_BIOS_ROM	0x5030
+#define ATI_BUS_CNTL	0x4C
+/* register indices are relative to VIPDEC */
+#define ATI_ROM_INDEX	0xA8
+#define ATI_ROM_DATA	0xAC
+#endif
+
+/* WARNING: This is only for RV630! */
+int ati_probe_spi_settings(const char *name)
+{
+	uint32_t tmp;
+	int ati_rom_size = 64 * 1024;
+	char *buf = malloc(ati_rom_size);
+
+	ati_open();
+	tmp = ati_register_read(ATI_BUS_CNTL);
+	printf("BIOS_ROM_WRT_EN: %sabled\n", (tmp & (1 << 0)) ? "en" : "dis");
+	printf("BIOS_ROM_DIS: %sabled\n", (tmp & (1 << 1)) ? "dis" : "en");
+	tmp = ati_register_read(ATI_ROM_CNTL);
+	printf("SCK_OVERWRITE: SCK sourced from %s\n", (tmp & (1 << 1)) ? "crystal clock" : "sclk");
+	printf("CLOCK_GATING_EN: dynamic clock gating %sabled\n", (tmp & (1 << 2)) ? "en" : "dis");
+	printf("CSB_ACTIVE_TO_SCK_SETUP_TIME: 0x%x\n", (tmp & 0xff00) >> 8);
+	printf("CSB_ACTIVE_TO_SCK_HOLD_TIME: 0x%x\n", (tmp & 0xff0000) >> 16);
+	printf("SCK_PRESCALE_REFCLK: 0x%x\n", (tmp & 0xf000000) >> 24);
+	printf("SCK_PRESCALE_CRYSTAL_CLK: 0x%x\n", (tmp & 0xf0000000) >> 28);
+	tmp = ati_register_read(ATI_ROM_STATUS);
+	printf("ROM_BUSY: SPI interface is %sbusy\n", (tmp & (1 << 0)) ? "" : "not ");
+	tmp = ati_register_read(ATI_ROM_INDEX);
+	printf("ROM_INDEX: address in ROM aperture relative to ROM_START is 0x%06x\n", tmp & 0xffffff);
+	tmp = ati_register_read(ATI_ROM_DATA);
+	printf("ROM_DATA: last four bytes read from ROM were 0x%08x\n", tmp);
+	tmp = ati_register_read(ATI_ROM_START);
+	printf("ROM_START: start address of ROM aperture is 0x%06x\n", tmp & 0xffffff);
+
+	read_ati_rom(buf, ati_rom_size);
+	ati_close();
+	
+	return 0;
+}
+
+void read_ati_rom(char *buf, int size)
+{
+	int i;
+	uint32_t tmp;
+
+	tmp = ati_register_read(ATI_ROM_START);
+	printf("ROM_START: start address of ROM aperture at time of dump is 0x%06x\n", tmp & 0xffffff);
+
+	for (i = 0; i < size; i += 4) {
+		usleep(1000);
+		while (ati_register_read(ATI_ROM_STATUS) & 0x1)
+			usleep(1000);
+		ati_register_write(ATI_ROM_INDEX, i);
+		usleep(1000);
+		while (ati_register_read(ATI_ROM_STATUS) & 0x1)
+			usleep(1000);
+		tmp = ati_register_read(ATI_ROM_DATA);
+		/* FIXME: The bitshift is most likely due to a timing problem.
+		 * To be clear: All ROM readouts are missing the LSB.
+		 * Two likely reasons:
+		 * - We read ATI_ROM_DATA too early. The unconditional
+		 *   usleep(1000) above should fix that.
+		 * - SCK has a too high frequency. Adjusting SCK_PRESCALE_*
+		 *   should fix that. If that doesn't work, we can try to use
+		 *   a different clock reference.
+		 */
+		tmp <<= 1;
+		printf("%02x", (tmp >> 0) & 0xff);
+		printf("%02x", (tmp >> 8) & 0xff);
+		printf("%02x", (tmp >> 16) & 0xff);
+		printf("%02x ", (tmp >> 24) & 0xff);
+		/* Line break after 72 chars */
+		if (((i / 4) % 8) == 7)
+			printf("\n");
+	}
+	printf("dump finished.\n");
+
+	return;		
+}
+
 int generic_spi_command(unsigned int writecnt, unsigned int readcnt, const unsigned char *writearr, unsigned char *readarr)
 {
 	if (it8716f_flashport)
Index: flashrom-ati/board_enable.c
===================================================================
--- flashrom-ati/board_enable.c	(Revision 3012)
+++ flashrom-ati/board_enable.c	(Arbeitskopie)
@@ -377,6 +377,9 @@
 };
 
 struct board_pciid_enable board_pciid_enables[] = {
+	/* FIXME: Check whether this is the correct PCI ID of the RV630 chipset. */
+	{0x1002, 0x9589, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	 "AMDATI", "RV630", "AMD/ATI RV630 graphics chipset", ati_probe_spi_settings},
 	{0x10de, 0x0360, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
 	 "gigabyte", "m57sli", "GIGABYTE GA-M57SLI-S4", it87xx_probe_spi_flash},
 	{0x10de, 0x03e0, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,






More information about the coreboot mailing list