From owner-svn-src-all@FreeBSD.ORG Fri Apr 13 08:45:51 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 1D200106564A; Fri, 13 Apr 2012 08:45:51 +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 F21378FC18; Fri, 13 Apr 2012 08:45:50 +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 q3D8joDN068844; Fri, 13 Apr 2012 08:45:50 GMT (envelope-from adrian@svn.freebsd.org) Received: (from adrian@localhost) by svn.freebsd.org (8.14.4/8.14.4/Submit) id q3D8joSO068842; Fri, 13 Apr 2012 08:45:50 GMT (envelope-from adrian@svn.freebsd.org) Message-Id: <201204130845.q3D8joSO068842@svn.freebsd.org> From: Adrian Chadd Date: Fri, 13 Apr 2012 08:45:50 +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: r234217 - 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: Fri, 13 Apr 2012 08:45:51 -0000 Author: adrian Date: Fri Apr 13 08:45:50 2012 New Revision: 234217 URL: http://svn.freebsd.org/changeset/base/234217 Log: (ab)Use the firmware API to store away EEPROM calibration data for future use by the ath(4) driver. These embedded devices put the calibration/PCI bootstrap data on the on board SPI flash rather than on an EEPROM connected to the NIC. For some boards, there's two NICs and two sets of EEPROM data in the main SPI flash. The particulars: * Introduce ath_fixup_size, which is the size of the EEPROM area in bytes. * Create a firmware image with a name based on the PCI device identifier (bus/slot/device/function). * Hide some verbose debugging behind 'bootverbose'. ath(4) can then use this to load in the EEPROM data. This requires AR71XX_ATH_EEPROM to be defined. Modified: head/sys/mips/atheros/ar71xx_pci.c Modified: head/sys/mips/atheros/ar71xx_pci.c ============================================================================== --- head/sys/mips/atheros/ar71xx_pci.c Fri Apr 13 08:11:14 2012 (r234216) +++ head/sys/mips/atheros/ar71xx_pci.c Fri Apr 13 08:45:50 2012 (r234217) @@ -60,6 +60,11 @@ __FBSDID("$FreeBSD$"); #include +#ifdef AR71XX_ATH_EEPROM +#include +#include +#endif /* AR71XX_ATH_EEPROM */ + #undef AR71XX_PCI_DEBUG #ifdef AR71XX_PCI_DEBUG #define dprintf printf @@ -266,8 +271,9 @@ ar71xx_pci_fixup(device_t dev, u_int bus 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); + if (bootverbose) + device_printf(dev, "%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) ? */ @@ -284,7 +290,8 @@ ar71xx_pci_fixup(device_t dev, u_int bus reg = *cal_data++; val = *cal_data++; val |= (*cal_data++) << 16; - printf(" reg: %x, val=%x\n", reg, val); + if (bootverbose) + printf(" reg: %x, val=%x\n", reg, val); /* Write eeprom fixup data to device memory */ ATH_WRITE_REG(AR71XX_PCI_MEM_BASE + reg, val); @@ -299,6 +306,62 @@ ar71xx_pci_fixup(device_t dev, u_int bus ar71xx_pci_write_config(dev, bus, slot, func, PCIR_BAR(0), bar0, 4); } +/* + * Take a copy of the EEPROM contents and squirrel it away in a firmware. + * The SPI flash will eventually cease to be memory-mapped, so we need + * to take a copy of this before the SPI driver initialises. + */ +static void +ar71xx_pci_slot_create_eeprom_firmware(device_t dev, u_int bus, u_int slot, + u_int func, long int flash_addr) +{ + char buf[64]; + uint16_t *cal_data = (uint16_t *) MIPS_PHYS_TO_KSEG1(flash_addr); + void *eeprom = NULL; + const struct firmware *fw = NULL; + int len; + + snprintf(buf, sizeof(buf), "bus.%d.%d.%d.ath_fixup_size", + bus, slot, func); + + if (resource_int_value(device_get_name(dev), device_get_unit(dev), + buf, &len) != 0) { + device_printf(dev, "%s: missing hint '%s', aborting EEPROM\n", + __func__, buf); + return; + } + + device_printf(dev, "EEPROM firmware: 0x%lx @ %d bytes\n", + flash_addr, len); + + eeprom = malloc(len, M_DEVBUF, M_WAITOK | M_ZERO); + if (! eeprom) { + device_printf(dev, + "%s: malloc failed for '%s', aborting EEPROM\n", + __func__, buf); + return; + } + + memcpy(eeprom, cal_data, len); + + /* + * Generate a flash EEPROM 'firmware' from the given memory + * region. Since the SPI controller will eventually + * go into port-IO mode instead of memory-mapped IO + * mode, a copy of the EEPROM contents is required. + */ + snprintf(buf, sizeof(buf), "%s.%d.bus.%d.%d.%d.eeprom_firmware", + device_get_name(dev), device_get_unit(dev), bus, slot, func); + fw = firmware_register(buf, eeprom, len, 1, NULL); + if (fw == NULL) { + device_printf(dev, "%s: firmware_register (%s) failed\n", + __func__, buf); + free(eeprom, M_DEVBUF); + return; + } + device_printf(dev, "device EEPROM '%s' registered\n", buf); +} + static void ar71xx_pci_slot_fixup(device_t dev, u_int bus, u_int slot, u_int func) { @@ -308,16 +371,19 @@ ar71xx_pci_slot_fixup(device_t dev, u_in /* * Check whether the given slot has a hint to poke. */ - printf("%s: checking dev %s, %d/%d/%d\n", + if (bootverbose) + device_printf(dev, "%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); + device_printf(dev, "found EEPROM at 0x%lx on %d.%d.%d\n", + flash_addr, bus, slot, func); ar71xx_pci_fixup(dev, bus, slot, func, flash_addr); + ar71xx_pci_slot_create_eeprom_firmware(dev, bus, slot, func, + flash_addr); } } #endif /* AR71XX_ATH_EEPROM */