1234485Sadrian/*- 2234485Sadrian * Copyright (c) 2009, Oleksandr Tymoshenko <gonzo@FreeBSD.org> 3234485Sadrian * All rights reserved. 4234485Sadrian * 5234485Sadrian * Redistribution and use in source and binary forms, with or without 6234485Sadrian * modification, are permitted provided that the following conditions 7234485Sadrian * are met: 8234485Sadrian * 1. Redistributions of source code must retain the above copyright 9234485Sadrian * notice unmodified, this list of conditions, and the following 10234485Sadrian * disclaimer. 11234485Sadrian * 2. Redistributions in binary form must reproduce the above copyright 12234485Sadrian * notice, this list of conditions and the following disclaimer in the 13234485Sadrian * documentation and/or other materials provided with the distribution. 14234485Sadrian * 15234485Sadrian * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16234485Sadrian * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17234485Sadrian * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18234485Sadrian * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19234485Sadrian * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20234485Sadrian * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21234485Sadrian * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22234485Sadrian * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23234485Sadrian * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24234485Sadrian * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25234485Sadrian * SUCH DAMAGE. 26234485Sadrian */ 27234485Sadrian 28234485Sadrian#include <sys/cdefs.h> 29234485Sadrian__FBSDID("$FreeBSD: releng/10.3/sys/mips/atheros/ar71xx_fixup.c 234485 2012-04-20 08:26:05Z adrian $"); 30234485Sadrian 31234485Sadrian#include "opt_ar71xx.h" 32234485Sadrian 33234485Sadrian#include <sys/param.h> 34234485Sadrian#include <sys/systm.h> 35234485Sadrian 36234485Sadrian#include <sys/bus.h> 37234485Sadrian#include <sys/interrupt.h> 38234485Sadrian#include <sys/malloc.h> 39234485Sadrian#include <sys/kernel.h> 40234485Sadrian#include <sys/module.h> 41234485Sadrian#include <sys/rman.h> 42234485Sadrian#include <sys/lock.h> 43234485Sadrian#include <sys/mutex.h> 44234485Sadrian 45234485Sadrian#include <vm/vm.h> 46234485Sadrian#include <vm/pmap.h> 47234485Sadrian#include <vm/vm_extern.h> 48234485Sadrian 49234485Sadrian#include <machine/bus.h> 50234485Sadrian#include <machine/cpu.h> 51234485Sadrian#include <machine/intr_machdep.h> 52234485Sadrian#include <machine/pmap.h> 53234485Sadrian 54234485Sadrian#include <dev/pci/pcivar.h> 55234485Sadrian#include <dev/pci/pcireg.h> 56234485Sadrian 57234485Sadrian#include <dev/pci/pcib_private.h> 58234485Sadrian#include "pcib_if.h" 59234485Sadrian 60234485Sadrian#include <mips/atheros/ar71xxreg.h> 61234485Sadrian#include <mips/atheros/ar71xx_pci_bus_space.h> 62234485Sadrian 63234485Sadrian#include <mips/atheros/ar71xx_cpudef.h> 64234485Sadrian 65234485Sadrian#include <sys/linker.h> 66234485Sadrian#include <sys/firmware.h> 67234485Sadrian 68234485Sadrian#include <mips/atheros/ar71xx_fixup.h> 69234485Sadrian 70234485Sadrian/* 71234485Sadrian * Take a copy of the EEPROM contents and squirrel it away in a firmware. 72234485Sadrian * The SPI flash will eventually cease to be memory-mapped, so we need 73234485Sadrian * to take a copy of this before the SPI driver initialises. 74234485Sadrian */ 75234485Sadrianvoid 76234485Sadrianar71xx_pci_slot_create_eeprom_firmware(device_t dev, u_int bus, u_int slot, 77234485Sadrian u_int func, long int flash_addr, int size) 78234485Sadrian{ 79234485Sadrian char buf[64]; 80234485Sadrian uint16_t *cal_data = (uint16_t *) MIPS_PHYS_TO_KSEG1(flash_addr); 81234485Sadrian void *eeprom = NULL; 82234485Sadrian const struct firmware *fw = NULL; 83234485Sadrian 84234485Sadrian device_printf(dev, "EEPROM firmware: 0x%lx @ %d bytes\n", 85234485Sadrian flash_addr, size); 86234485Sadrian 87234485Sadrian eeprom = malloc(size, M_DEVBUF, M_WAITOK | M_ZERO); 88234485Sadrian if (! eeprom) { 89234485Sadrian device_printf(dev, 90234485Sadrian "%s: malloc failed for '%s', aborting EEPROM\n", 91234485Sadrian __func__, buf); 92234485Sadrian return; 93234485Sadrian } 94234485Sadrian 95234485Sadrian memcpy(eeprom, cal_data, size); 96234485Sadrian 97234485Sadrian /* 98234485Sadrian * Generate a flash EEPROM 'firmware' from the given memory 99234485Sadrian * region. Since the SPI controller will eventually 100234485Sadrian * go into port-IO mode instead of memory-mapped IO 101234485Sadrian * mode, a copy of the EEPROM contents is required. 102234485Sadrian */ 103234485Sadrian snprintf(buf, sizeof(buf), "%s.%d.bus.%d.%d.%d.eeprom_firmware", 104234485Sadrian device_get_name(dev), device_get_unit(dev), bus, slot, func); 105234485Sadrian fw = firmware_register(buf, eeprom, size, 1, NULL); 106234485Sadrian if (fw == NULL) { 107234485Sadrian device_printf(dev, "%s: firmware_register (%s) failed\n", 108234485Sadrian __func__, buf); 109234485Sadrian free(eeprom, M_DEVBUF); 110234485Sadrian return; 111234485Sadrian } 112234485Sadrian device_printf(dev, "device EEPROM '%s' registered\n", buf); 113234485Sadrian} 114234485Sadrian 115234485Sadrian#if 0 116234485Sadrianstatic void 117234485Sadrianar71xx_pci_slot_fixup(device_t dev, u_int bus, u_int slot, u_int func) 118234485Sadrian{ 119234485Sadrian long int flash_addr; 120234485Sadrian char buf[64]; 121234485Sadrian int size; 122234485Sadrian 123234485Sadrian /* 124234485Sadrian * Check whether the given slot has a hint to poke. 125234485Sadrian */ 126234485Sadrian if (bootverbose) 127234485Sadrian device_printf(dev, "%s: checking dev %s, %d/%d/%d\n", 128234485Sadrian __func__, device_get_nameunit(dev), bus, slot, func); 129234485Sadrian 130234485Sadrian snprintf(buf, sizeof(buf), "bus.%d.%d.%d.ath_fixup_addr", 131234485Sadrian bus, slot, func); 132234485Sadrian 133234485Sadrian if (resource_long_value(device_get_name(dev), device_get_unit(dev), 134234485Sadrian buf, &flash_addr) == 0) { 135234485Sadrian snprintf(buf, sizeof(buf), "bus.%d.%d.%d.ath_fixup_size", 136234485Sadrian bus, slot, func); 137234485Sadrian if (resource_int_value(device_get_name(dev), 138234485Sadrian device_get_unit(dev), buf, &size) != 0) { 139234485Sadrian device_printf(dev, 140234485Sadrian "%s: missing hint '%s', aborting EEPROM\n", 141234485Sadrian __func__, buf); 142234485Sadrian return; 143234485Sadrian } 144234485Sadrian 145234485Sadrian 146234485Sadrian device_printf(dev, "found EEPROM at 0x%lx on %d.%d.%d\n", 147234485Sadrian flash_addr, bus, slot, func); 148234485Sadrian ar71xx_pci_fixup(dev, bus, slot, func, flash_addr, size); 149234485Sadrian ar71xx_pci_slot_create_eeprom_firmware(dev, bus, slot, func, 150234485Sadrian flash_addr, size); 151234485Sadrian } 152234485Sadrian} 153234485Sadrian#endif /* 0 */ 154