[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 19:26:13 CET 2007
On 18.12.2007 18:49, Carl-Daniel Hailfinger wrote:
> On 18.12.2007 18:38, Carl-Daniel Hailfinger wrote:
>
>> On 18.12.2007 16:11, Carl-Daniel Hailfinger wrote:
>>
>>
>>> On 18.12.2007 15:56, Carl-Daniel Hailfinger wrote:
>>>
>>>
>>>
>>>> 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.
>>>>
>>>>
>>>>
>>>>
>>> Easiest way to debug would be to try this against a not POSTed card
>>> (secondary card) and then try it again when the card is POSTed. Compare
>>> the results (including status registers). Send them to the list.
>>>
>>>
>>>
>> Bit shift needed to happen in native byte order. Use interleaving read
>> to workaround the issue of lost LSB.
>>
>>
>
> Workaround didn't work: Register documentation was wrong.
Change PRESCALE from 1 to 3.
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,175 @@
return 0;
}
+int mem_fd = -1;
+unsigned int *ati_reg_mem_map = NULL;
+
+/*
+lspci output:
+02:00.0 VGA compatible controller: ATI Technologies Inc Unknown device 94c3 (prog-if 00 [VGA])
+ Subsystem: Hightech Information System Ltd. Unknown device 2232
+ Flags: bus master, fast devsel, latency 0, IRQ 11
+ Memory at c0000000 (64-bit, prefetchable) [size=256M]
+------> Memory at dfff0000 (64-bit, non-prefetchable) [size=64K] <------------
+ I/O ports at e800 [size=256]
+ Expansion ROM at dffc0000 [disabled] [size=128K]
+ */
+
+#error You must fix up reg_addr and reg_len below, then remove the #error.
+unsigned int reg_addr = 0xdfff0000;
+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, tmp2;
+
+ 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);
+
+ printf("Setting SCK_PRESCALE_* to 3\n");
+ tmp = ati_register_read(ATI_ROM_CNTL);
+ tmp &= 0x00ffffff;
+ /* SCK_PRESCALE_REFCLK = 3 */
+ tmp |= (0x3 << 24) & 0xf000000;
+ /* SCK_PRESCALE_CRYSTAL_CLK = 3 */
+ tmp |= (0x3 << 28) & 0xf0000000;
+ ati_register_write(ATI_ROM_CNTL, tmp);
+
+ 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);
+ /* 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.
+ */
+ tmp2 = ntohl(tmp);
+ tmp2 <<= 1;
+ tmp = htonl(tmp2);
+ printf("%02x", (tmp >> 0) & 0xff);
+ printf("%02x ", (tmp >> 8) & 0xff);
+ printf("%02x", (tmp >> 16) & 0xff);
+ printf("%02x ", (tmp >> 24) & 0xff);
+ /* Line break after 32 bytes. */
+ if ((i & 31) == 28)
+ 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,10 @@
};
struct board_pciid_enable board_pciid_enables[] = {
+ {0x1002, 0x9589, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ "ATI", "RV630", "ATI Technologies RV630 graphics", ati_probe_spi_settings},
+ {0x1002, 0x94c3, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ "ATI", "94c3", "ATI Technologies Inc 94c3", 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