summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoradrian <adrian@FreeBSD.org>2012-04-20 08:26:05 +0000
committeradrian <adrian@FreeBSD.org>2012-04-20 08:26:05 +0000
commit6152dc39f23cf9b5f8db831ea0d2de2e59e9feea (patch)
treeba57b3f3aab8e5919d290c7481fe4840bc6a74f4
parentd9895ac1fe988335e2619f56d942d954d835bb07 (diff)
downloadFreeBSD-src-6152dc39f23cf9b5f8db831ea0d2de2e59e9feea.zip
FreeBSD-src-6152dc39f23cf9b5f8db831ea0d2de2e59e9feea.tar.gz
Introduce the matching PCI ath(4) fixup code from ar71xx_pci into
ar724x_pci.c. * Move out the code which populates the firmware into ar71xx_fixup.c * Shuffle around the ar724x fixup code to match what the ar71xx fixup code does. I've validated this on an AR7240 with AR9285 on-board NIC. It doesn't yet load, as the AR9285 EEPROM code needs to be made "flash aware." TODO: * Validate that I haven't broken AR71xx * Test AR9285/AR9287 onboard NICs, complete with EEPROM code changes * Port over the needed BAR hacks for AR7240, AR7241 and AR7242 from Linux OpenWRT. The current WAR has only been tested on the AR7240 and I'm not sure the way the BAR register is treated is "right". The "fixup" method here is right when setting the BAR for local access - ie, the BAR address is either 0xffff (AR7240) or 0x1000ffff (AR7241/AR7242), but the ath9k-fixup.c code (Linux OpenWRT) does this when setting the initial "fixup" BAR. It then restores the original BAR. I'll have to read the ar724x PCI bus glue to see what other special cases await.
-rw-r--r--sys/mips/atheros/ar71xx_fixup.c153
-rw-r--r--sys/mips/atheros/ar71xx_fixup.h36
-rw-r--r--sys/mips/atheros/ar71xx_pci.c80
-rw-r--r--sys/mips/atheros/ar724x_pci.c88
-rw-r--r--sys/mips/atheros/files.ar71xx1
5 files changed, 275 insertions, 83 deletions
diff --git a/sys/mips/atheros/ar71xx_fixup.c b/sys/mips/atheros/ar71xx_fixup.c
new file mode 100644
index 0000000..8ab8855
--- /dev/null
+++ b/sys/mips/atheros/ar71xx_fixup.c
@@ -0,0 +1,153 @@
+/*-
+ * Copyright (c) 2009, Oleksandr Tymoshenko <gonzo@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice unmodified, this list of conditions, and the following
+ * disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "opt_ar71xx.h"
+
+#include <sys/param.h>
+#include <sys/systm.h>
+
+#include <sys/bus.h>
+#include <sys/interrupt.h>
+#include <sys/malloc.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/rman.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+
+#include <vm/vm.h>
+#include <vm/pmap.h>
+#include <vm/vm_extern.h>
+
+#include <machine/bus.h>
+#include <machine/cpu.h>
+#include <machine/intr_machdep.h>
+#include <machine/pmap.h>
+
+#include <dev/pci/pcivar.h>
+#include <dev/pci/pcireg.h>
+
+#include <dev/pci/pcib_private.h>
+#include "pcib_if.h"
+
+#include <mips/atheros/ar71xxreg.h>
+#include <mips/atheros/ar71xx_pci_bus_space.h>
+
+#include <mips/atheros/ar71xx_cpudef.h>
+
+#include <sys/linker.h>
+#include <sys/firmware.h>
+
+#include <mips/atheros/ar71xx_fixup.h>
+
+/*
+ * 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.
+ */
+void
+ar71xx_pci_slot_create_eeprom_firmware(device_t dev, u_int bus, u_int slot,
+ u_int func, long int flash_addr, int size)
+{
+ char buf[64];
+ uint16_t *cal_data = (uint16_t *) MIPS_PHYS_TO_KSEG1(flash_addr);
+ void *eeprom = NULL;
+ const struct firmware *fw = NULL;
+
+ device_printf(dev, "EEPROM firmware: 0x%lx @ %d bytes\n",
+ flash_addr, size);
+
+ eeprom = malloc(size, 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, size);
+
+ /*
+ * 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, size, 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);
+}
+
+#if 0
+static void
+ar71xx_pci_slot_fixup(device_t dev, u_int bus, u_int slot, u_int func)
+{
+ long int flash_addr;
+ char buf[64];
+ int size;
+
+ /*
+ * Check whether the given slot has a hint to poke.
+ */
+ 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) {
+ 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, &size) != 0) {
+ device_printf(dev,
+ "%s: missing hint '%s', aborting EEPROM\n",
+ __func__, buf);
+ return;
+ }
+
+
+ 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, size);
+ ar71xx_pci_slot_create_eeprom_firmware(dev, bus, slot, func,
+ flash_addr, size);
+ }
+}
+#endif /* 0 */
diff --git a/sys/mips/atheros/ar71xx_fixup.h b/sys/mips/atheros/ar71xx_fixup.h
new file mode 100644
index 0000000..f81840f
--- /dev/null
+++ b/sys/mips/atheros/ar71xx_fixup.h
@@ -0,0 +1,36 @@
+/*-
+ * Copyright (c) 2012, Adrian Chadd <adrian@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice unmodified, this list of conditions, and the following
+ * disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef __ATHEROS_AR71XX_FIXUP_H__
+#define __ATHEROS_AR71XX_FIXUP_H__
+
+extern void ar71xx_pci_slot_create_eeprom_firmware(device_t dev,
+ u_int bus, u_int slot, u_int func, long int flash_addr, int size);
+
+#endif /* __ATHEROS_AR71XX_FIXUP_H__ */
diff --git a/sys/mips/atheros/ar71xx_pci.c b/sys/mips/atheros/ar71xx_pci.c
index 25cc810..126537c 100644
--- a/sys/mips/atheros/ar71xx_pci.c
+++ b/sys/mips/atheros/ar71xx_pci.c
@@ -63,8 +63,7 @@ __FBSDID("$FreeBSD$");
#include <mips/atheros/ar71xx_cpudef.h>
#ifdef AR71XX_ATH_EEPROM
-#include <sys/linker.h>
-#include <sys/firmware.h>
+#include <mips/atheros/ar71xx_fixup.h>
#endif /* AR71XX_ATH_EEPROM */
#undef AR71XX_PCI_DEBUG
@@ -288,7 +287,7 @@ ar71xx_pci_write_config(device_t dev, u_int bus, u_int slot, u_int func,
*/
static void
ar71xx_pci_fixup(device_t dev, u_int bus, u_int slot, u_int func,
- long flash_addr)
+ long flash_addr, int len)
{
uint16_t *cal_data = (uint16_t *) MIPS_PHYS_TO_KSEG1(flash_addr);
uint32_t reg, val, bar0;
@@ -328,67 +327,12 @@ ar71xx_pci_fixup(device_t dev, u_int bus, u_int slot, u_int func,
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)
{
long int flash_addr;
- char buf[32];
+ char buf[64];
+ int size;
/*
* Check whether the given slot has a hint to poke.
@@ -396,16 +340,28 @@ ar71xx_pci_slot_fixup(device_t dev, u_int bus, u_int slot, u_int func)
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) {
+ 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, &size) != 0) {
+ device_printf(dev,
+ "%s: missing hint '%s', aborting EEPROM\n",
+ __func__, buf);
+ return;
+ }
+
+
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_fixup(dev, bus, slot, func, flash_addr, size);
ar71xx_pci_slot_create_eeprom_firmware(dev, bus, slot, func,
- flash_addr);
+ flash_addr, size);
}
}
#endif /* AR71XX_ATH_EEPROM */
diff --git a/sys/mips/atheros/ar724x_pci.c b/sys/mips/atheros/ar724x_pci.c
index f3519c6..07c2c67 100644
--- a/sys/mips/atheros/ar724x_pci.c
+++ b/sys/mips/atheros/ar724x_pci.c
@@ -29,6 +29,8 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
+#include "opt_ar71xx.h"
+
#include <sys/param.h>
#include <sys/systm.h>
@@ -61,6 +63,10 @@ __FBSDID("$FreeBSD$");
#include <mips/atheros/ar71xx_cpudef.h>
+#ifdef AR71XX_ATH_EEPROM
+#include <mips/atheros/ar71xx_fixup.h>
+#endif /* AR71XX_ATH_EEPROM */
+
#undef AR724X_PCI_DEBUG
#ifdef AR724X_PCI_DEBUG
#define dprintf printf
@@ -243,27 +249,21 @@ ar724x_pci_setup(device_t dev)
return (0);
}
+#ifdef AR71XX_ATH_EEPROM
#define AR5416_EEPROM_MAGIC 0xa55a
/*
* XXX - This should not be here ! And this looks like Atheros (if_ath) only.
*/
static void
-ar724x_load_eeprom_data(device_t dev)
+ar724x_pci_fixup(device_t dev, long flash_addr, int len)
{
- uint32_t bar0, hint, reg, val;
- uint16_t *data = NULL;
-
- /* Search for a hint of eeprom data offset */
- if (resource_int_value(device_get_name(dev),
- device_get_unit(dev), "eepromdata", &hint) != 0)
- return;
-
- device_printf(dev, "Loading the eeprom fixup data from %#x\n", hint);
- data = (uint16_t *)MIPS_PHYS_TO_KSEG1(hint);
+ uint32_t bar0, reg, val;
+ uint16_t *cal_data = (uint16_t *) MIPS_PHYS_TO_KSEG1(flash_addr);
- if (*data != AR5416_EEPROM_MAGIC) {
- device_printf(dev, "Invalid calibration data from %#x\n", hint);
+ if (cal_data[0] != AR5416_EEPROM_MAGIC) {
+ device_printf(dev, "%s: Invalid calibration data from 0x%x\n",
+ __func__, (uintptr_t) flash_addr);
return;
}
@@ -275,11 +275,14 @@ ar724x_load_eeprom_data(device_t dev)
ar724x_pci_write_config(dev, 0, 0, 0, PCIR_COMMAND, val, 2);
/* set pointer to first reg address */
- data += 3;
- while (*data != 0xffff) {
- reg = *data++;
- val = *data++;
- val |= (*data++) << 16;
+ cal_data += 3;
+ while (*cal_data != 0xffff) {
+ reg = *cal_data++;
+ val = *cal_data++;
+ val |= (*cal_data++) << 16;
+
+ if (bootverbose)
+ printf(" 0x%08x=0x%04x\n", reg, val);
/* Write eeprom fixup data to device memory */
ATH_WRITE_REG(AR71XX_PCI_MEM_BASE + reg, val);
@@ -293,9 +296,51 @@ ar724x_load_eeprom_data(device_t dev)
/* Write the saved bar(0) address */
ar724x_pci_write_config(dev, 0, 0, 0, PCIR_BAR(0), bar0, 4);
}
-
#undef AR5416_EEPROM_MAGIC
+/*
+ * XXX This is (mostly) duplicated with ar71xx_pci.c.
+ * It should at some point be fixed.
+ */
+static void
+ar724x_pci_slot_fixup(device_t dev)
+{
+ long int flash_addr;
+ char buf[64];
+ int size;
+
+ /*
+ * Check whether the given slot has a hint to poke.
+ */
+ if (bootverbose)
+ device_printf(dev, "%s: checking dev %s, %d/%d/%d\n",
+ __func__, device_get_nameunit(dev), 0, 0, 0);
+
+ snprintf(buf, sizeof(buf), "bus.%d.%d.%d.ath_fixup_addr",
+ 0, 0, 0);
+
+ if (resource_long_value(device_get_name(dev), device_get_unit(dev),
+ buf, &flash_addr) == 0) {
+ snprintf(buf, sizeof(buf), "bus.%d.%d.%d.ath_fixup_size",
+ 0, 0, 0);
+ if (resource_int_value(device_get_name(dev),
+ device_get_unit(dev), buf, &size) != 0) {
+ device_printf(dev,
+ "%s: missing hint '%s', aborting EEPROM\n",
+ __func__, buf);
+ return;
+ }
+
+
+ device_printf(dev, "found EEPROM at 0x%lx on %d.%d.%d\n",
+ flash_addr, 0, 0, 0);
+ ar724x_pci_fixup(dev, flash_addr, size);
+ ar71xx_pci_slot_create_eeprom_firmware(dev, 0, 0, 0,
+ flash_addr, size);
+ }
+}
+#endif /* AR71XX_ATH_EEPROM */
+
static int
ar724x_pci_probe(device_t dev)
{
@@ -357,8 +402,9 @@ ar724x_pci_attach(device_t dev)
if (ar724x_pci_setup(dev))
return (ENXIO);
- /* XXX - Load eeprom fixup data */
- ar724x_load_eeprom_data(dev);
+#ifdef AR71XX_ATH_EEPROM
+ ar724x_pci_slot_fixup(dev);
+#endif /* AR71XX_ATH_EEPROM */
/* Fixup internal PCI bridge */
ar724x_pci_write_config(dev, 0, 0, 0, PCIR_COMMAND,
diff --git a/sys/mips/atheros/files.ar71xx b/sys/mips/atheros/files.ar71xx
index 86de7f1..cd090db 100644
--- a/sys/mips/atheros/files.ar71xx
+++ b/sys/mips/atheros/files.ar71xx
@@ -21,5 +21,6 @@ mips/atheros/ar71xx_setup.c standard
mips/atheros/ar71xx_chip.c standard
mips/atheros/ar724x_chip.c standard
mips/atheros/ar91xx_chip.c standard
+mips/atheros/ar71xx_fixup.c optional ar71xx_ath_eeprom
dev/hwpmc/hwpmc_mips24k.c optional hwpmc
OpenPOWER on IntegriCloud