[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