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