Index: Makefile =================================================================== --- Makefile (revision 1357) +++ Makefile (working copy) @@ -164,6 +164,9 @@ # IMPORTANT: This code is not yet working! CONFIG_ATAHPT ?= no +# VIA VT6421A LPC memory support +CONFIG_ATAVIA ?= yes + # Always enable FT2232 SPI dongles for now. CONFIG_FT2232_SPI ?= yes @@ -270,6 +273,12 @@ NEED_PCI := yes endif +ifeq ($(CONFIG_ATAVIA), yes) +FEATURE_CFLAGS += -D'CONFIG_ATAVIA=1' +PROGRAMMER_OBJS += atavia.o +NEED_PCI := yes +endif + ifeq ($(CONFIG_FT2232_SPI), yes) FTDILIBS := $(shell pkg-config --libs libftdi 2>/dev/null || printf "%s" "-lftdi -lusb") # This is a totally ugly hack. Index: atavia.c =================================================================== --- atavia.c (revision 0) +++ atavia.c (revision 0) @@ -0,0 +1,142 @@ +/* + * This file is part of the flashrom project. + * + * Copyright (C) 2010 Uwe Hermann + * Copyright (C) 2011 Jonathan Kollasch + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include "flash.h" +#include "programmer.h" +#include + +#define PCI_VENDOR_ID_VIA 0x1106 + +#define BROM_ADDR 0x60 +#define BROM_DATA 0x64 + +#define BROM_ACCESS 0x68 +#define BROM_TRIGGER 0x80 +#define BROM_WRITE 0x40 +#define BROM_SIZE_MASK 0x30 +#define BROM_SIZE_64K 0x00 +#define BROM_SIZE_32K 0x10 +#define BROM_SIZE_16K 0x20 +#define BROM_SIZE_0K 0x30 +#define BROM_BYTE_ENABLE_MASK 0x0f + +/* + * Select the byte we want to access. This is done by clearing the bit + * corresponding to the byte we want to access, leaving the others set. + * (Yes, really.) + */ +#define ENABLE(address) ((~(1 << ((address) & 3))) & BROM_BYTE_ENABLE_MASK) + +#define BROM_STATUS 0x69 +#define BROM_ERROR_STATUS 0x80 + +static bool atavia_ready(void); + +const struct pcidev_status ata_via[] = { + {PCI_VENDOR_ID_VIA, 0x3249, NT, "VIA", "VT6421A"}, + + {}, +}; + +static int atavia_shutdown(void *data) +{ + pci_cleanup(pacc); + release_io_perms(); + + return 0; +} + + +static bool atavia_ready(void) +{ + int try; + uint8_t access; + bool status; + + for (status = false, try = 0; try < 300; try++) { + access = pci_read_byte(pcidev_dev, BROM_ACCESS); + if ((access & BROM_TRIGGER) == 0) { + status = true; + break; + } else { + programmer_delay(1); + continue; + } + } + + msg_pdbg("%s() %s after %d tries\n", __FUNCTION__, + status ? "suceeded" : "failed", try); + + return status; +} + +int atavia_init(void) +{ + buses_supported = CHIP_BUSTYPE_LPC; + + pcidev_init(4, ata_via); + + /* must be done before rpci calls */ + if (register_shutdown(atavia_shutdown, NULL)) + return 1; + + rpci_write_long(pcidev_dev, PCI_ROM_ADDRESS, 0xFFFFFFFF); + programmer_delay(90); + pci_write_long(pcidev_dev, PCI_ROM_ADDRESS, 0); + programmer_delay(10); + + return ((atavia_ready() == true) ? 0 : 1); +} + +void *atavia_map(const char *descr, unsigned long phys_addr, size_t len) +{ + return (void *)phys_addr; +} + +void atavia_chip_writeb(uint8_t val, chipaddr addr) +{ + pci_write_long(pcidev_dev, BROM_ADDR, (addr & ~3)); + pci_write_long(pcidev_dev, BROM_DATA, val << (8 * (addr & 3))); + pci_write_byte(pcidev_dev, BROM_ACCESS, BROM_TRIGGER | BROM_WRITE | ENABLE(addr)); + + if (atavia_ready() == false) { + msg_perr("not ready after write\n"); + } +} + +uint8_t atavia_chip_readb(const chipaddr addr) +{ + uint8_t val; + + pci_write_long(pcidev_dev, BROM_ADDR, (addr & ~3)); + pci_write_byte(pcidev_dev, BROM_ACCESS, BROM_TRIGGER | ENABLE(addr)); + + if (atavia_ready() == false) { + msg_perr("not ready after read\n"); + } + + val = (pci_read_long(pcidev_dev, BROM_DATA) >> ((addr & 3)*8)) & 0xff; + + return val; +} Index: flashrom.c =================================================================== --- flashrom.c (revision 1357) +++ flashrom.c (working copy) @@ -52,7 +52,7 @@ * if more than one of them is selected. If only one is selected, it is clear * that the user wants that one to become the default. */ -#if CONFIG_NIC3COM+CONFIG_NICREALTEK+CONFIG_NICNATSEMI+CONFIG_GFXNVIDIA+CONFIG_DRKAISER+CONFIG_SATASII+CONFIG_ATAHPT+CONFIG_FT2232_SPI+CONFIG_SERPROG+CONFIG_BUSPIRATE_SPI+CONFIG_DEDIPROG+CONFIG_RAYER_SPI+CONFIG_NICINTEL+CONFIG_NICINTEL_SPI+CONFIG_OGP_SPI+CONFIG_SATAMV > 1 +#if CONFIG_NIC3COM+CONFIG_NICREALTEK+CONFIG_NICNATSEMI+CONFIG_GFXNVIDIA+CONFIG_DRKAISER+CONFIG_SATASII+CONFIG_ATAHPT+CONFIG_ATAVIA+CONFIG_FT2232_SPI+CONFIG_SERPROG+CONFIG_BUSPIRATE_SPI+CONFIG_DEDIPROG+CONFIG_RAYER_SPI+CONFIG_NICINTEL+CONFIG_NICINTEL_SPI+CONFIG_OGP_SPI+CONFIG_SATAMV > 1 #error Please enable either CONFIG_DUMMY or CONFIG_INTERNAL or disable support for all programmers except one. #endif enum programmer programmer = @@ -77,6 +77,9 @@ #if CONFIG_ATAHPT == 1 PROGRAMMER_ATAHPT #endif +#if CONFIG_ATAVIA == 1 + PROGRAMMER_ATAVIA +#endif #if CONFIG_FT2232_SPI == 1 PROGRAMMER_FT2232_SPI #endif @@ -289,6 +292,24 @@ }, #endif +#if CONFIG_ATAVIA == 1 + { + .name = "atavia", + .init = atavia_init, + .map_flash_region = atavia_map, + .unmap_flash_region = fallback_unmap, + .chip_readb = atavia_chip_readb, + .chip_readw = fallback_chip_readw, + .chip_readl = fallback_chip_readl, + .chip_readn = fallback_chip_readn, + .chip_writeb = atavia_chip_writeb, + .chip_writew = fallback_chip_writew, + .chip_writel = fallback_chip_writel, + .chip_writen = fallback_chip_writen, + .delay = internal_delay, + }, +#endif + #if CONFIG_FT2232_SPI == 1 { .name = "ft2232_spi", Index: programmer.h =================================================================== --- programmer.h (revision 1357) +++ programmer.h (working copy) @@ -52,6 +52,9 @@ #if CONFIG_ATAHPT == 1 PROGRAMMER_ATAHPT, #endif +#if CONFIG_ATAVIA == 1 + PROGRAMMER_ATAVIA, +#endif #if CONFIG_FT2232_SPI == 1 PROGRAMMER_FT2232_SPI, #endif @@ -460,6 +463,15 @@ extern const struct pcidev_status ata_hpt[]; #endif +/* atavia.c */ +#if CONFIG_ATAVIA == 1 +int atavia_init(void); +void *atavia_map(const char *descr, unsigned long phys_addr, size_t len); +void atavia_chip_writeb(uint8_t val, chipaddr addr); +uint8_t atavia_chip_readb(const chipaddr addr); +extern const struct pcidev_status ata_via[]; +#endif + /* ft2232_spi.c */ #if CONFIG_FT2232_SPI == 1 struct usbdev_status { Index: print.c =================================================================== --- print.c (revision 1357) +++ print.c (working copy) @@ -313,6 +313,11 @@ programmer_table[PROGRAMMER_ATAHPT].name); print_supported_pcidevs(ata_hpt); #endif +#if CONFIG_ATAVIA == 1 + printf("\nSupported devices for the %s programmer:\n", + programmer_table[PROGRAMMER_ATAVIA].name); + print_supported_pcidevs(ata_via); +#endif #if CONFIG_FT2232_SPI == 1 msg_ginfo("\nSupported devices for the %s programmer:\n", programmer_table[PROGRAMMER_FT2232_SPI].name);