From owner-svn-src-all@FreeBSD.ORG Sun Jan 15 19:29:33 2012 Return-Path: Delivered-To: svn-src-all@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 746801065673; Sun, 15 Jan 2012 19:29:33 +0000 (UTC) (envelope-from adrian@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 5EC378FC12; Sun, 15 Jan 2012 19:29:33 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.4/8.14.4) with ESMTP id q0FJTXSY096595; Sun, 15 Jan 2012 19:29:33 GMT (envelope-from adrian@svn.freebsd.org) Received: (from adrian@localhost) by svn.freebsd.org (8.14.4/8.14.4/Submit) id q0FJTXRa096593; Sun, 15 Jan 2012 19:29:33 GMT (envelope-from adrian@svn.freebsd.org) Message-Id: <201201151929.q0FJTXRa096593@svn.freebsd.org> From: Adrian Chadd Date: Sun, 15 Jan 2012 19:29:33 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r230148 - head/sys/mips/atheros X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 15 Jan 2012 19:29:33 -0000 Author: adrian Date: Sun Jan 15 19:29:33 2012 New Revision: 230148 URL: http://svn.freebsd.org/changeset/base/230148 Log: Some of the atheros based embedded devices use one or more PCI NICs on-board, glued to the AR71xx CPU. These may forgo separate WMAC EEPROMs (which store configuration and calibration data) and instead store it in the main board SPI flash. Normally the NIC reads the EEPROM attached to it to setup various PCI configuration registers. If this isn't done, the device will probe as something different (eg 0x168c:abcd, or 0x168c:ff??.) Other setup registers are also written to which may control important functions. This introduces a new compile option, AR71XX_ATH_EEPROM, which enables the use of this particular code. The ART offset in the SPI flash can be specified as a hint against the relevant slot/device number, for example: hint.pcib.0.bus.0.17.0.ath_fixup_addr=0x1fff1000 hint.pcib.0.bus.0.18.0.ath_fixup_addr=0x1fff5000 TODO: * Think of a better name; * Make the PCIe version of this fixup code also use this option; * Maybe also check slot 19; * This has to happen _before_ the SPI flash is set from memory-mapped to SPI-IO - so document that somewhere. Modified: head/sys/mips/atheros/ar71xx_pci.c Modified: head/sys/mips/atheros/ar71xx_pci.c ============================================================================== --- head/sys/mips/atheros/ar71xx_pci.c Sun Jan 15 19:22:34 2012 (r230147) +++ head/sys/mips/atheros/ar71xx_pci.c Sun Jan 15 19:29:33 2012 (r230148) @@ -248,6 +248,77 @@ ar71xx_pci_write_config(device_t dev, u_ } } +#ifdef AR71XX_ATH_EEPROM +/* + * Some embedded boards (eg AP94) have the MAC attached via PCI but they + * don't have the MAC-attached EEPROM. The register initialisation + * values and calibration data are stored in the on-board flash. + * This routine initialises the NIC via the EEPROM register contents + * before the probe/attach routines get a go at things. + */ +static void +ar71xx_pci_fixup(device_t dev, u_int bus, u_int slot, u_int func, + long flash_addr) +{ + uint16_t *cal_data = (uint16_t *) MIPS_PHYS_TO_KSEG1(flash_addr); + uint32_t reg, val, bar0; + + printf("%s: flash_addr=%lx, cal_data=%p\n", + __func__, flash_addr, cal_data); + + /* XXX check 0xa55a */ + /* Save bar(0) address - just to flush bar(0) (SoC WAR) ? */ + bar0 = ar71xx_pci_read_config(dev, bus, slot, func, PCIR_BAR(0), 4); + ar71xx_pci_write_config(dev, bus, slot, func, PCIR_BAR(0), + AR71XX_PCI_MEM_BASE, 4); + + val = ar71xx_pci_read_config(dev, bus, slot, func, PCIR_COMMAND, 2); + val |= (PCIM_CMD_BUSMASTEREN | PCIM_CMD_MEMEN); + ar71xx_pci_write_config(dev, bus, slot, func, PCIR_COMMAND, val, 2); + + cal_data += 3; + while (*cal_data != 0xffff) { + reg = *cal_data++; + val = *cal_data++; + val |= (*cal_data++) << 16; + printf(" reg: %x, val=%x\n", reg, val); + + /* Write eeprom fixup data to device memory */ + ATH_WRITE_REG(AR71XX_PCI_MEM_BASE + reg, val); + DELAY(100); + } + + val = ar71xx_pci_read_config(dev, bus, slot, func, PCIR_COMMAND, 2); + val &= ~(PCIM_CMD_BUSMASTEREN | PCIM_CMD_MEMEN); + ar71xx_pci_write_config(dev, bus, slot, func, PCIR_COMMAND, val, 2); + + /* Write the saved bar(0) address */ + ar71xx_pci_write_config(dev, bus, slot, func, PCIR_BAR(0), bar0, 4); +} + +static void +ar71xx_pci_slot_fixup(device_t dev, u_int bus, u_int slot, u_int func) +{ + long int flash_addr; + char buf[32]; + + /* + * Check whether the given slot has a hint to poke. + */ + printf("%s: checking dev %s, %d/%d/%d\n", + __func__, device_get_nameunit(dev), bus, slot, func); + snprintf(buf, sizeof(buf), "bus.%d.%d.%d.ath_fixup_addr", + bus, slot, func); + + if (resource_long_value(device_get_name(dev), device_get_unit(dev), + buf, &flash_addr) == 0) { + printf("%s: found fixupaddr at %lx: updating\n", + __func__, flash_addr); + ar71xx_pci_fixup(dev, bus, slot, func, flash_addr); + } +} +#endif /* AR71XX_ATH_EEPROM */ + static int ar71xx_pci_probe(device_t dev) { @@ -321,6 +392,16 @@ ar71xx_pci_attach(device_t dev) | PCIM_CMD_SERRESPEN | PCIM_CMD_BACKTOBACK | PCIM_CMD_PERRESPEN | PCIM_CMD_MWRICEN, 2); +#ifdef AR71XX_ATH_EEPROM + /* + * Hard-code a check for slot 17 and 18 - these are + * the two PCI slots which may have a PCI device that + * requires "fixing". + */ + ar71xx_pci_slot_fixup(dev, 0, 17, 0); + ar71xx_pci_slot_fixup(dev, 0, 18, 0); +#endif /* AR71XX_ATH_EEPROM */ + device_add_child(dev, "pci", busno); return (bus_generic_attach(dev)); }