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

Carl-Daniel Hailfinger c-d.hailfinger.devel.2006 at gmx.net
Wed Dec 12 15:49:28 CET 2007


On 11.12.2007 22:43, Oliver McFadden wrote:
> On 12/11/07, Oliver McFadden <z3ro.geek at gmail.com> wrote:
>   
>> On 12/10/07, Carl-Daniel Hailfinger <c-d.hailfinger.devel.2006 at gmx.net>
>> wrote:
>>     
>>> Thanks for the pointers. I will look into implementing SPI support for
>>> these cards in a week or so. Ping me if you don't see any code/questions
>>> until then.
>>>       
>> Here is the code for a simple mmap based interface to the card. You'll need
>> to
>> check lspci -v for the appropriate reg_addr and reg_len variables; the
>> detection
>> code is quite big to include...
>>
>> You're looking for a block of non-prefetchable memory exactly 64K in size;
>> this
>> is from my card:
>>
>> Memory at ff5f0000 (32-bit, non-prefetchable) [size=64K]
>>     
>
> I forgot to comment out the bogus register_write in that code, so anyone who
> wants to use it, first comment out the register_write.
>   

First stab at the code, needs a board enable command line option, does a
lot of things the wrong way and only works with RV630.

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

Index: flashrom-ati/flash.h
===================================================================
--- flashrom-ati/flash.h	(Revision 3003)
+++ flashrom-ati/flash.h	(Arbeitskopie)
@@ -249,6 +249,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 3003)
+++ 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,151 @@
 	return 0;
 }
 
+int mem_fd = -1;
+unsigned int *ati_reg_mem_map = NULL;
+
+/*
+ * 05:00.0 VGA compatible controller: ATI Technologies Inc Radeon R350 [Radeon 9800 Pro] (prog-if 00 [VGA])
+ *         Subsystem: ATI Technologies Inc Unknown device 0002
+ *         Flags: bus master, stepping, 66MHz, medium devsel, latency 64, IRQ 16
+ *         Memory at e8000000 (32-bit, prefetchable) [size=128M]
+ *         I/O ports at c800 [size=256]
+ *         Memory at ff5f0000 (32-bit, non-prefetchable) [size=64K]
+ *         Expansion ROM at ff5c0000 [disabled] [size=128K]
+ *         Capabilities: [58] AGP version 3.0
+ *         Capabilities: [50] Power Management version 2
+ */
+
+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) {
+		while (ati_register_read(ATI_ROM_STATUS) & 0x1)
+			usleep(1000);
+		ati_register_write(ATI_ROM_INDEX, i);
+		while (ati_register_read(ATI_ROM_STATUS) & 0x1)
+			usleep(1000);
+		tmp = ati_register_read(ATI_ROM_DATA);
+		printf("%08x ", tmp);
+		/* 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 3003)
+++ 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