On 11.12.2007 22:43, Oliver McFadden wrote:
On 12/11/07, Oliver McFadden z3ro.geek@gmail.com wrote:
On 12/10/07, Carl-Daniel Hailfinger c-d.hailfinger.devel.2006@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@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,