summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorUwe Hermann <uwe@hermann-uwe.de>2009-05-16 21:39:19 +0000
committerUwe Hermann <uwe@hermann-uwe.de>2009-05-16 21:39:19 +0000
commit8403ccb49f98d1583736984c92d62735d9d466b5 (patch)
tree464c74c283c1800bb426667b9e2f1277bd743fc5
parent5820f42ef209cfa0d4070fa9be96c9c91123a93f (diff)
downloadast2050-flashrom-8403ccb49f98d1583736984c92d62735d9d466b5.zip
ast2050-flashrom-8403ccb49f98d1583736984c92d62735d9d466b5.tar.gz
Add proper workaround for 3COM 3C90xB cards, which need special fixups (the 3C90xC ones don't)
This is tested on hardware. Also, add initial support for the Atmel AT29C010A chip (which I inserted in a 3COM 3C90xB card for testing). It can be detected, read works, erase works, but write will need some additional code (will post in another patch later). Corresponding to flashrom svn r520. Signed-off-by: Uwe Hermann <uwe@hermann-uwe.de> Acked-by: Carl-Daniel Hailfinger <c-d.hailfinger.devel.2006@gmx.net>
-rw-r--r--flash.h3
-rw-r--r--flashchips.c14
-rw-r--r--nic3com.c26
-rw-r--r--pcidev.c10
4 files changed, 49 insertions, 4 deletions
diff --git a/flash.h b/flash.h
index b980cba..2a9b9bb 100644
--- a/flash.h
+++ b/flash.h
@@ -193,6 +193,7 @@ struct flashchip {
#define TEST_OK_ERASE (1<<2)
#define TEST_OK_WRITE (1<<3)
#define TEST_OK_PR (TEST_OK_PROBE|TEST_OK_READ)
+#define TEST_OK_PRE (TEST_OK_PROBE|TEST_OK_READ|TEST_OK_ERASE)
#define TEST_OK_PREW (TEST_OK_PROBE|TEST_OK_READ|TEST_OK_ERASE|TEST_OK_WRITE)
#define TEST_OK_MASK 0x0f
@@ -258,6 +259,7 @@ extern struct flashchip flashchips[];
#define AT_26DF321 0x4700 /* also 25DF321 */
#define AT_26F004 0x0400
#define AT_29C040A 0xA4
+#define AT_29C010A 0xD5
#define AT_29C020 0xDA
#define AT_45BR3214B /* No ID available */
#define AT_45CS1282 0x2920
@@ -559,6 +561,7 @@ struct pci_dev *pci_card_find(uint16_t vendor, uint16_t device,
extern uint32_t io_base_addr;
extern struct pci_access *pacc;
extern struct pci_filter filter;
+extern struct pci_dev *pcidev_dev;
struct pcidev_status {
uint16_t vendor_id;
uint16_t device_id;
diff --git a/flashchips.c b/flashchips.c
index eb241a9..36307c1 100644
--- a/flashchips.c
+++ b/flashchips.c
@@ -376,6 +376,20 @@ struct flashchip flashchips[] = {
{
.vendor = "Atmel",
+ .name = "AT29C010A",
+ .manufacture_id = ATMEL_ID,
+ .model_id = AT_29C010A,
+ .total_size = 128,
+ .page_size = 128,
+ .tested = TEST_OK_PRE,
+ .probe = probe_jedec,
+ .erase = erase_chip_jedec,
+ .write = write_jedec, /* FIXME */
+ .read = read_memmapped,
+ },
+
+ {
+ .vendor = "Atmel",
.name = "AT29C020",
.manufacture_id = ATMEL_ID,
.model_id = AT_29C020,
diff --git a/nic3com.c b/nic3com.c
index f5d0aa1..4e3e475 100644
--- a/nic3com.c
+++ b/nic3com.c
@@ -29,13 +29,17 @@
#define BIOS_ROM_ADDR 0x04
#define BIOS_ROM_DATA 0x08
#define INT_STATUS 0x0e
+#define INTERNAL_CONFIG 0x00
#define SELECT_REG_WINDOW 0x800
#define PCI_VENDOR_ID_3COM 0x10b7
+uint32_t internal_conf;
+uint16_t id;
+
struct pcidev_status nics_3com[] = {
/* 3C90xB */
- {0x10b7, 0x9055, PCI_NT, "3COM", "3C90xB: PCI 10/100 Mbps; shared 10BASE-T/100BASE-TX"},
+ {0x10b7, 0x9055, PCI_OK, "3COM", "3C90xB: PCI 10/100 Mbps; shared 10BASE-T/100BASE-TX"},
{0x10b7, 0x9001, PCI_NT, "3COM", "3C90xB: PCI 10/100 Mbps; shared 10BASE-T/100BASE-T4" },
{0x10b7, 0x9004, PCI_NT, "3COM", "3C90xB: PCI 10BASE-T (TPO)" },
{0x10b7, 0x9005, PCI_NT, "3COM", "3C90xB: PCI 10BASE-T/10BASE2/AUI (COMBO)" },
@@ -57,6 +61,18 @@ int nic3com_init(void)
get_io_perms();
io_base_addr = pcidev_init(PCI_VENDOR_ID_3COM, nics_3com);
+ id = pcidev_dev->device_id;
+
+ /* 3COM 3C90xB cards need a special fixup. */
+ if (id == 0x9055 || id == 0x9001 || id == 0x9004 || id == 0x9005
+ || id == 0x9006 || id == 0x900a || id == 0x905a) {
+ /* Select register window 3 and save the receiver status. */
+ OUTW(SELECT_REG_WINDOW + 3, io_base_addr + INT_STATUS);
+ internal_conf = INL(io_base_addr + INTERNAL_CONFIG);
+
+ /* Set receiver type to MII for full BIOS ROM access. */
+ OUTL((internal_conf & 0xf00fffff) | 0x00600000, io_base_addr);
+ }
/*
* The lowest 16 bytes of the I/O mapped register space of (most) 3COM
@@ -70,6 +86,14 @@ int nic3com_init(void)
int nic3com_shutdown(void)
{
+ /* 3COM 3C90xB cards need a special fixup. */
+ if (id == 0x9055 || id == 0x9001 || id == 0x9004 || id == 0x9005
+ || id == 0x9006 || id == 0x900a || id == 0x905a) {
+ /* Select register window 3 and restore the receiver status. */
+ OUTW(SELECT_REG_WINDOW + 3, io_base_addr + INT_STATUS);
+ OUTL(internal_conf, io_base_addr + INTERNAL_CONFIG);
+ }
+
free(pcidev_bdf);
pci_cleanup(pacc);
#if defined(__FreeBSD__) || defined(__DragonFly__)
diff --git a/pcidev.c b/pcidev.c
index f07fe80..41b5f25 100644
--- a/pcidev.c
+++ b/pcidev.c
@@ -32,6 +32,7 @@ uint32_t io_base_addr;
struct pci_access *pacc;
struct pci_filter filter;
char *pcidev_bdf = NULL;
+struct pci_dev *pcidev_dev = NULL;
uint32_t pcidev_validate(struct pci_dev *dev, struct pcidev_status *devs)
{
@@ -67,7 +68,7 @@ uint32_t pcidev_init(uint16_t vendor_id, struct pcidev_status *devs)
struct pci_dev *dev;
char *msg = NULL;
int found = 0;
- uint32_t addr = 0;
+ uint32_t addr = 0, curaddr = 0;
pacc = pci_alloc(); /* Get the pci_access structure */
pci_init(pacc); /* Initialize the PCI library */
@@ -85,8 +86,11 @@ uint32_t pcidev_init(uint16_t vendor_id, struct pcidev_status *devs)
for (dev = pacc->devices; dev; dev = dev->next) {
if (pci_filter_match(&filter, dev)) {
- if ((addr = pcidev_validate(dev, devs)) != 0)
+ if ((addr = pcidev_validate(dev, devs)) != 0) {
+ curaddr = addr;
+ pcidev_dev = dev;
found++;
+ }
}
}
@@ -102,7 +106,7 @@ uint32_t pcidev_init(uint16_t vendor_id, struct pcidev_status *devs)
exit(1);
}
- return addr;
+ return curaddr;
}
void print_supported_pcidevs(struct pcidev_status *devs)
OpenPOWER on IntegriCloud