xref: /freebsd-11-stable/sys/arm/at91/board_tsc4370.c (revision 4ab2e064d7950be84256d671a7ae93f87cc6aa36)
1 /*-
2  * Copyright (c) 2005-2008 Olivier Houchard.  All rights reserved.
3  * Copyright (c) 2005-2012 Warner Losh.  All rights reserved.
4  * Copyright (c) 2007-2014 Ian Lepore.  All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25  * SUCH DAMAGE.
26  */
27 
28 /*
29  * Board init code for the TSC4370, and all other current TSC mainboards.
30  */
31 
32 #include <sys/cdefs.h>
33 __FBSDID("$FreeBSD$");
34 #include <sys/param.h>
35 #include <sys/systm.h>
36 
37 #include <arm/at91/at91_pioreg.h>
38 #include <arm/at91/at91_piovar.h>
39 #include <arm/at91/at91_pmcreg.h>
40 #include <arm/at91/at91_pmcvar.h>
41 #include <arm/at91/at91_twireg.h>
42 #include <arm/at91/at91_usartreg.h>
43 #include <arm/at91/at91board.h>
44 #include <arm/at91/at91var.h>
45 #include <arm/at91/at91rm9200var.h>
46 #include <arm/at91/at91rm92reg.h>
47 #include <arm/at91/if_atereg.h>
48 #include <machine/board.h>
49 #include <machine/cpu.h>
50 #include <machine/machdep.h>
51 #include <net/ethernet.h>
52 #include <sys/reboot.h>
53 
54 /*
55  * RD4HW()/WR4HW() read and write at91rm9200 hardware register space directly.
56  * They serve the same purpose as the RD4()/WR4() idiom you see in many drivers,
57  * except that those translate to bus_space calls, but in this code we need to
58  * access the registers directly before the at91 bus_space stuff is set up.
59  */
60 
61 static inline uint32_t
RD4HW(uint32_t devbase,uint32_t regoff)62 RD4HW(uint32_t devbase, uint32_t regoff)
63 {
64 	return *(volatile uint32_t *)(AT91_BASE + devbase + regoff);
65 }
66 
67 static inline void
WR4HW(uint32_t devbase,uint32_t regoff,uint32_t val)68 WR4HW(uint32_t devbase, uint32_t regoff, uint32_t val)
69 {
70 	*(volatile uint32_t *)(AT91_BASE + devbase + regoff) = val;
71 }
72 
73 /*
74  * This is the same calculation the at91 uart driver does, we use it to update
75  * the console uart baud rate after changing the MCK rate.
76  */
77 #ifndef BAUD2DIVISOR
78 #define BAUD2DIVISOR(b) \
79 	((((at91_master_clock * 10) / ((b) * 16)) + 5) / 10)
80 #endif
81 
82 /*
83  * If doing an in-house build, use tsc_bootinfo.h which is shared with our
84  * custom boot2.  Otherwise define some crucial bits of it here, enough to allow
85  * this code to compile.
86  */
87 #ifdef TSC_BUILD
88 #include <machine/tsc_bootinfo.h>
89 #else
90 struct tsc_bootinfo {
91 	uint32_t	bi_size;
92 	uint32_t	bi_version;
93 	uint32_t	bi_flags; /* RB_xxxxx flags from sys/reboot.h */
94 	char	bi_rootdevname[64];
95 };
96 #define TSC_BOOTINFO_MAGIC	0x06C30000
97 #endif
98 
99 static struct arm_boot_params	boot_params;
100 static struct tsc_bootinfo	inkernel_bootinfo;
101 
102 /*
103  * Change the master clock config and wait for it to stabilize.
104  */
105 static void
change_mckr(uint32_t mckr)106 change_mckr(uint32_t mckr)
107 {
108 	int i;
109 
110 	WR4HW(AT91RM92_PMC_BASE, PMC_MCKR, mckr);
111 
112 	for (i = 0; i < 1000; ++i)
113 		if ((RD4HW(AT91RM92_PMC_BASE, PMC_SR) & PMC_IER_MCKRDY))
114 			return;
115 }
116 
117 /*
118  * Allow the master clock frequency to be changed from whatever the bootloader
119  * set up, because sometimes it's harder to change/update a bootloader than it
120  * is to change/update the kernel once a product is in the field.
121  */
122 static void
master_clock_init(void)123 master_clock_init(void)
124 {
125 	uint32_t mckr = RD4HW(AT91RM92_PMC_BASE, PMC_MCKR);
126 	int hintvalue = 0;
127 	int newmckr = 0;
128 
129 	 /*
130 	 * If there's a hint that specifies the contents of MCKR, use it
131 	 * without question (it had better be right).
132 	 *
133 	 * If there's a "mckfreq" hint it might be in hertz or mhz (convert the
134 	 * latter to hz).  Calculate the new MCK divider.  If the CPU frequency
135 	 * is not a sane multiple of the hinted MCK frequency this is likely to
136 	 * behave badly.  The moral is: don't hint at impossibilities.
137 	 */
138 
139 	if (resource_int_value("at91", 0, "mckr", &hintvalue) == 0) {
140 		newmckr = hintvalue;
141 	} else {
142 		hintvalue = 90; /* Default to 90mhz if not specified. */
143 		resource_int_value("at91", 0, "mckfreq", &hintvalue);
144 		if (hintvalue != 0) {
145 			if (hintvalue < 1000)
146 				hintvalue *= 1000000;
147 			if (hintvalue != at91_master_clock) {
148 				uint32_t divider;
149 				struct at91_pmc_clock * cpuclk;
150 				cpuclk = at91_pmc_clock_ref("cpu");
151 				divider = (cpuclk->hz / hintvalue) - 1;
152 				newmckr = (mckr & 0xFFFFFCFF) | ((divider & 0x03) << 8);
153 				at91_pmc_clock_deref(cpuclk);
154 			}
155 		}
156 	}
157 
158 	/* If the new mckr value is different than what's in the register now,
159 	 * make the change and wait for the clocks to settle (MCKRDY status).
160 	 *
161 	 * MCKRDY will never be asserted unless either the selected clock or the
162 	 * prescaler value changes (but not both at once) [this is detailed in
163 	 * the rm9200 errata]. This code assumes the prescaler value is always
164 	 * zero and that by time we get to here we're running on something other
165 	 * than the slow clock, so to change the mckr divider we first change
166 	 * back to the slow clock (keeping prescaler and divider unchanged),
167 	 * then go back to the original selected clock with the new divider.
168 	 *
169 	 * After changing MCK, go re-init everything clock-related, and reset
170 	 * the baud rate generator for the console (doing this here is kind of a
171 	 * rude hack, but hey, you do what you have to to run MCK faster).
172 	 */
173 
174 	if (newmckr != 0 && newmckr != mckr) {
175 		if (mckr & 0x03)
176 			change_mckr(mckr & ~0x03);
177 		change_mckr(newmckr);
178 		at91_pmc_init_clock();
179 		WR4HW(AT91RM92_DBGU_BASE, USART_BRGR, BAUD2DIVISOR(115200));
180 	}
181 }
182 
183 /*
184  * TSC-specific code to read the ID eeprom on the mainboard and extract the
185  * unit's EUI-64 which gets translated into a MAC-48 for ethernet.
186  */
187 static void
eeprom_init(void)188 eeprom_init(void)
189 {
190 	const uint32_t twiHz    = 400000;
191 	const uint32_t twiCkDiv = 1 << 16;
192 	const uint32_t twiChDiv = ((at91_master_clock / twiHz) - 2) << 8;
193 	const uint32_t twiClDiv = ((at91_master_clock / twiHz) - 2);
194 
195 	/*
196 	 * Set the TWCK and TWD lines for Periph A, no pullup, open-drain.
197 	 */
198 	at91_pio_use_periph_a(AT91RM92_PIOA_BASE,
199 	    AT91C_PIO_PA25 | AT91C_PIO_PA26, 0);
200 	at91_pio_gpio_high_z(AT91RM92_PIOA_BASE, AT91C_PIO_PA25, 1);
201 
202 	/*
203 	 * Enable TWI power (irq numbers are also device IDs for power)
204 	 */
205 	WR4HW(AT91RM92_PMC_BASE, PMC_PCER, 1u << AT91RM92_IRQ_TWI);
206 
207 	/*
208 	 * Disable TWI interrupts, reset device, enable Master mode,
209 	 * disable Slave mode, set the clock.
210 	 */
211 	WR4HW(AT91RM92_TWI_BASE, TWI_IDR, 0xffffffff);
212 	WR4HW(AT91RM92_TWI_BASE, TWI_CR, TWI_CR_SWRST);
213 	WR4HW(AT91RM92_TWI_BASE, TWI_CR, TWI_CR_MSEN | TWI_CR_SVDIS);
214 	WR4HW(AT91RM92_TWI_BASE, TWI_CWGR, twiCkDiv | twiChDiv | twiClDiv);
215 }
216 
217 static int
eeprom_read(uint32_t EE_DEV_ADDR,uint32_t ee_off,void * buf,uint32_t size)218 eeprom_read(uint32_t EE_DEV_ADDR, uint32_t ee_off, void * buf, uint32_t size)
219 {
220 	uint8_t *bufptr = (uint8_t *)buf;
221 	uint32_t status;
222 	uint32_t count;
223 
224 	/* Clean out any old status and received byte. */
225 	status = RD4HW(AT91RM92_TWI_BASE, TWI_SR);
226 	status = RD4HW(AT91RM92_TWI_BASE, TWI_RHR);
227 
228 	/* Set the TWI Master Mode Register */
229 	WR4HW(AT91RM92_TWI_BASE, TWI_MMR,
230 	    TWI_MMR_DADR(EE_DEV_ADDR) | TWI_MMR_IADRSZ(2) | TWI_MMR_MREAD);
231 
232 	/* Set TWI Internal Address Register */
233 	WR4HW(AT91RM92_TWI_BASE, TWI_IADR, ee_off);
234 
235 	/* Start transfer */
236 	WR4HW(AT91RM92_TWI_BASE, TWI_CR, TWI_CR_START);
237 
238 	status = RD4HW(AT91RM92_TWI_BASE, TWI_SR);
239 
240 	while (size-- > 1){
241 		/* Wait until Receive Holding Register is full */
242 		count = 1000000;
243 		while (!(RD4HW(AT91RM92_TWI_BASE, TWI_SR) & TWI_SR_RXRDY) &&
244 		    --count != 0)
245 			continue;
246 		if (count <= 0)
247 			return -1;
248 		/* Read and store byte */
249 		*bufptr++ = (uint8_t)RD4HW(AT91RM92_TWI_BASE, TWI_RHR);
250 	}
251 	WR4HW(AT91RM92_TWI_BASE, TWI_CR, TWI_CR_STOP);
252 
253 	status = RD4HW(AT91RM92_TWI_BASE, TWI_SR);
254 
255 	/* Wait until transfer is finished */
256 	while (!(RD4HW(AT91RM92_TWI_BASE, TWI_SR) & TWI_SR_TXCOMP))
257 		continue;
258 
259 	/* Read last byte */
260 	*bufptr = (uint8_t)RD4HW(AT91RM92_TWI_BASE, TWI_RHR);
261 
262 	return 0;
263 }
264 
265 static int
set_mac_from_idprom(void)266 set_mac_from_idprom(void)
267 {
268 #define SIGNATURE_SIZE          4
269 #define EETYPE_SIZE             2
270 #define BSLENGTH_SIZE           2
271 #define RAW_SIZE                52
272 #define EUI64_SIZE              8
273 #define BS_SIGNATURE            0x21706d69
274 #define BSO_SIGNATURE           0x216f7362
275 #define DEVOFFSET_BSO_SIGNATURE 0x20
276 #define OFFSET_BS_SIGNATURE     0
277 #define SIZE_BS_SIGNATURE       SIGNATURE_SIZE
278 #define OFFSET_EETYPE           (OFFSET_BS_SIGNATURE + SIZE_BS_SIGNATURE)
279 #define SIZE_EETYPE             EETYPE_SIZE
280 #define OFFSET_BOOTSECTSIZE     (OFFSET_EETYPE + SIZE_EETYPE)
281 #define SIZE_BOOTSECTSIZE       BSLENGTH_SIZE
282 #define OFFSET_RAW              (OFFSET_BOOTSECTSIZE + SIZE_BOOTSECTSIZE)
283 #define OFFSET_EUI64            (OFFSET_RAW + RAW_SIZE)
284 #define EE_DEV_ADDR             0xA0    /* eeprom is AT24C256 at address 0xA0 */
285 
286 	int status;
287 	uint32_t dev_offset = 0;
288 	uint32_t sig;
289 	uint8_t eui64[EUI64_SIZE];
290 	uint8_t eaddr[ETHER_ADDR_LEN];
291 
292 	eeprom_init();
293 
294 	/* Check for the boot section signature at offset 0. */
295 	status = eeprom_read(EE_DEV_ADDR, OFFSET_BS_SIGNATURE, &sig, sizeof(sig));
296 	if (status == -1)
297 		return -1;
298 
299 	if (sig != BS_SIGNATURE) {
300 		/* Check for the boot section offset signature. */
301 		status = eeprom_read(EE_DEV_ADDR,
302 		    DEVOFFSET_BSO_SIGNATURE, &sig, sizeof(sig));
303 		if ((status == -1) || (sig != BSO_SIGNATURE))
304 				return -1;
305 
306 		/* Read the device offset of the boot section structure. */
307 		status = eeprom_read(EE_DEV_ADDR,
308 		    DEVOFFSET_BSO_SIGNATURE + sizeof(sig),
309 		    &dev_offset, sizeof(dev_offset));
310 		if (status == -1)
311 				return -1;
312 
313 		/* Check for the boot section signature. */
314 		status = eeprom_read(EE_DEV_ADDR,
315 		    dev_offset + OFFSET_BS_SIGNATURE, &sig, sizeof(sig));
316 		if ((status == -1) || (sig != BS_SIGNATURE))
317 				return -1;
318 	}
319 	dev_offset += OFFSET_EUI64;
320 
321 	/* Read the EUI64 from the device.  */
322 	if (eeprom_read(EE_DEV_ADDR, dev_offset, eui64, sizeof(eui64)) == -1)
323 		return -1;
324 
325 	/* Transcribe the EUI-64 to a MAC-48.
326 	 *
327 	 * Given an EUI-64 of aa:bb:cc:dd:ee:ff:gg:hh
328 	 *
329 	 *   if (ff is zero and ee is non-zero)
330 	 *      mac is aa:bb:cc:ee:gg:hh
331 	 *   else
332 	 *      mac is aa:bb:cc:ff:gg:hh
333 	 *
334 	 * This logic fixes a glitch in our mfg process in which the ff byte was
335 	 * always zero and the ee byte contained a non-zero value.  This
336 	 * resulted in duplicate MAC addresses because we discarded the ee byte.
337 	 * Now they've fixed the process so that the ff byte is non-zero and
338 	 * unique addresses are formed from the ff:gg:hh bytes.  If the ff byte
339 	 * is zero, then we have a unit manufactured during the glitch era, and
340 	 * we fix the problem by grabbing the ee byte rather than the ff byte.
341 	 */
342 	eaddr[0] = eui64[0];
343 	eaddr[1] = eui64[1];
344 	eaddr[2] = eui64[2];
345 	eaddr[3] = eui64[5];
346 	eaddr[4] = eui64[6];
347 	eaddr[5] = eui64[7];
348 
349 	if (eui64[5] == 0 && eui64[4] != 0) {
350 		eaddr[3] = eui64[4];
351 	}
352 
353 	/*
354 	 * Set the address in the hardware regs where the ate driver
355 	 * looks for it.
356 	 */
357 	WR4HW(AT91RM92_EMAC_BASE, ETH_SA1L,
358 	    (eaddr[3] << 24) | (eaddr[2] << 16) | (eaddr[1] << 8) | eaddr[0]);
359 	WR4HW(AT91RM92_EMAC_BASE, ETH_SA1H,
360 	    (eaddr[5] << 8) | (eaddr[4]));
361 
362 	printf(
363 	    "ID: EUI-64 %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n"
364 	    "    MAC-48 %02x:%02x:%02x:%02x:%02x:%02x\n"
365 	    "    read from i2c device 0x%02X offset 0x%x\n",
366 	    eui64[0], eui64[1], eui64[2], eui64[3],
367 	    eui64[4], eui64[5], eui64[6], eui64[7],
368 	    eaddr[0], eaddr[1], eaddr[2],
369 	    eaddr[3], eaddr[4], eaddr[5],
370 	    EE_DEV_ADDR, dev_offset);
371 
372 	return (0);
373 }
374 
375 /*
376  * Assign SPI chip select pins based on which chip selects are found in hints.
377  */
378 static void
assign_spi_pins(void)379 assign_spi_pins(void)
380 {
381 	struct {
382 		uint32_t     num;
383 		const char * name;
384 	} chipsel_pins[] = {
385 		{ AT91C_PIO_PA3, "PA3", },
386 		{ AT91C_PIO_PA4, "PA4", },
387 		{ AT91C_PIO_PA5, "PA5", },
388 		{ AT91C_PIO_PA6, "PA6", },
389 	};
390 	int anchor = 0;
391 	uint32_t chipsel_inuse = 0;
392 
393 	/*
394 	 * Search through all device hints looking for any that have
395 	 * ".at=spibus0".  For each one found, ensure that there is also a
396 	 * chip select hint ".cs=<num>" and that <num> is 0-3, and assign the
397 	 * corresponding pin to the SPI peripheral.  Whine if we find a SPI
398 	 * device with a missing or invalid chipsel hint.
399 	 */
400 	for (;;) {
401 		const char * rName = "";
402 		int unit = 0;
403 		int cs = 0;
404 		int ret;
405 
406 		ret = resource_find_match(&anchor, &rName, &unit, "at", "spibus0");
407 		if (ret != 0)
408 			break;
409 
410 		ret = resource_int_value(rName, unit, "cs", &cs);
411 		if (ret != 0) {
412 			printf( "Error: hint for SPI device %s%d "
413 				"without a chip select hint; "
414 				"device will not function.\n",
415 				rName, unit);
416 			continue;
417 		}
418 		if (cs < 0 || cs > 3) {
419 			printf( "Error: hint for SPI device %s%d "
420 				"contains an invalid chip select "
421 				"value: %d\n",
422 				rName, unit, cs);
423 			continue;
424 		}
425 		if (chipsel_inuse & (1 << cs)) {
426 			printf( "Error: hint for SPI device %s%d "
427 				"specifies chip select %d, which "
428 				"is already used by another device\n",
429 				rName, unit, cs);
430 			continue;
431 		}
432 		chipsel_inuse |= 1 << cs;
433 		at91_pio_use_periph_a(AT91RM92_PIOA_BASE,
434 			chipsel_pins[cs].num, 1);
435 		printf( "Configured pin %s as SPI chip "
436 			"select %d for %s%d\n",
437 			chipsel_pins[cs].name, cs, rName, unit);
438 	}
439 
440 	/*
441 	 * If there were hints for any SPI devices, assign the basic SPI IO pins
442 	 * and enable SPI power (irq numbers are also device IDs for power).
443 	 */
444 	if (chipsel_inuse != 0) {
445 		at91_pio_use_periph_a(AT91RM92_PIOA_BASE,
446 			AT91C_PIO_PA1 | AT91C_PIO_PA0 | AT91C_PIO_PA2, 0);
447 		WR4HW(AT91RM92_PMC_BASE, PMC_PCER, 1u << AT91RM92_IRQ_SPI);
448 	}
449 }
450 
451 BOARD_INIT long
board_init(void)452 board_init(void)
453 {
454 	int is_bga, rev_mii;
455 
456 	/*
457 	 * Deal with bootinfo (if any) passed in from the boot2 bootloader and
458 	 * copied to the static inkernel_bootinfo earlier in the init.  Do this
459 	 * early so that bootverbose is set from this point on.
460 	 */
461 	if (inkernel_bootinfo.bi_size > 0 &&
462 	    (inkernel_bootinfo.bi_flags & RB_BOOTINFO)) {
463 		struct tsc_bootinfo *bip = &inkernel_bootinfo;
464 		printf("TSC_BOOTINFO: size %u howtoflags=0x%08x rootdev='%s'\n",
465 		    bip->bi_size, bip->bi_flags, bip->bi_rootdevname);
466 		boothowto = bip->bi_flags;
467 		bootverbose = (boothowto & RB_VERBOSE);
468 		if (bip->bi_rootdevname[0] != 0)
469 			rootdevnames[0] = bip->bi_rootdevname;
470 	}
471 
472 	/*
473 	 * The only way to know if we're in a BGA package (and thus have PIOD)
474 	 * is to be told via a hint; there's nothing detectable in the silicon.
475 	 * This is esentially an rm92-specific extension to getting the chip ID
476 	 * (which was done by at91_machdep just before calling this routine).
477 	 * If it is the BGA package, enable the clock for PIOD.
478 	 */
479 	is_bga = 0;
480 	resource_int_value("at91", 0, "is_bga_package", &is_bga);
481 
482 	if (is_bga)
483 		WR4HW(AT91RM92_PMC_BASE, PMC_PCER, 1u << AT91RM92_IRQ_PIOD);
484 
485 #if __FreeBSD_version >= 1000000
486 	at91rm9200_set_subtype(is_bga ? AT91_ST_RM9200_BGA :
487 	    AT91_ST_RM9200_PQFP);
488 #endif
489 
490 	/*
491 	 * Go reprogram the MCK frequency based on hints.
492 	 */
493 	master_clock_init();
494 
495 	/* From this point on you can use printf. */
496 
497 	/*
498 	 * Configure UARTs.
499 	 */
500 	at91rm9200_config_uart(AT91_ID_DBGU, 0, 0);   /* DBGU just Tx and Rx */
501 	at91rm9200_config_uart(AT91RM9200_ID_USART0, 1, 0);   /* Tx and Rx */
502 	at91rm9200_config_uart(AT91RM9200_ID_USART1, 2, 0);   /* Tx and Rx */
503 	at91rm9200_config_uart(AT91RM9200_ID_USART2, 3, 0);   /* Tx and Rx */
504 	at91rm9200_config_uart(AT91RM9200_ID_USART3, 4, 0);   /* Tx and Rx */
505 
506 	/*
507 	 * Configure MCI (sdcard)
508 	 */
509 	at91rm9200_config_mci(0);
510 
511 	/*
512 	 * Assign the pins needed by the emac device, and power it up. Also,
513 	 * configure it for RMII operation unless the 'revmii_mode' hint is set,
514 	 * in which case configure the full set of MII pins.  The revmii_mode
515 	 * hint is for so-called reverse-MII, used for connections to a Broadcom
516 	 * 5325E switch on some boards.  Note that order is important here:
517 	 * configure pins, then power on the device, then access the device's
518 	 * config registers.
519 	 */
520 	rev_mii = 0;
521 	resource_int_value("ate", 0, "phy_revmii_mode", &rev_mii);
522 
523 	at91_pio_use_periph_a(AT91RM92_PIOA_BASE,
524 		AT91C_PIO_PA7 | AT91C_PIO_PA8 | AT91C_PIO_PA9 |
525 		AT91C_PIO_PA10 | AT91C_PIO_PA11 | AT91C_PIO_PA12 |
526 		AT91C_PIO_PA13 | AT91C_PIO_PA14 | AT91C_PIO_PA15 |
527 		AT91C_PIO_PA16, 0);
528 	if (rev_mii) {
529 		at91_pio_use_periph_b(AT91RM92_PIOB_BASE,
530 		    AT91C_PIO_PB12 | AT91C_PIO_PB13  | AT91C_PIO_PB14 |
531 		    AT91C_PIO_PB15 | AT91C_PIO_PB16  | AT91C_PIO_PB17 |
532 		    AT91C_PIO_PB18 | AT91C_PIO_PB19, 0);
533 	}
534 	WR4HW(AT91RM92_PMC_BASE, PMC_PCER, 1u << AT91RM92_IRQ_EMAC);
535 	if (!rev_mii) {
536 		WR4HW(AT91RM92_EMAC_BASE, ETH_CFG,
537 		    RD4HW(AT91RM92_EMAC_BASE, ETH_CFG) | ETH_CFG_RMII);
538 	}
539 
540 	/*
541 	 * Get our ethernet MAC address from the ID eeprom.
542 	 * Configures TWI as a side effect.
543 	 */
544 	set_mac_from_idprom();
545 
546 	/*
547 	 * Configure SPI
548 	 */
549 	assign_spi_pins();
550 
551 	/*
552 	 * Configure SSC
553 	 */
554 	at91_pio_use_periph_a(
555 	    AT91RM92_PIOB_BASE,
556 	    AT91C_PIO_PB6 | AT91C_PIO_PB7 | AT91C_PIO_PB8 |   /* transmit */
557 	    AT91C_PIO_PB9 | AT91C_PIO_PB10 | AT91C_PIO_PB11,  /* receive */
558 	    0);                                               /* no pullup */
559 
560 	/*
561 	 *  We're using TC1's A1 input for PPS measurements that drive the
562 	 *  kernel PLL and our NTP refclock.  On some old boards we route a 5mhz
563 	 *  signal to TC1's A2 input (pin PA21), but we have never used that
564 	 *  clock (it rolls over too fast for hz=100), and now newer boards are
565 	 *  using pin PA21 as a CTS0 for USART1, so we no longer assign it to
566 	 *  the timer block like we used to here.
567 	 */
568 	at91_pio_use_periph_b(AT91RM92_PIOA_BASE, AT91C_PIO_PA19, 0);
569 
570 	/*
571 	 * Configure pins used to bitbang-upload the firmware to the main FPGA.
572 	 */
573 	at91_pio_use_gpio(AT91RM92_PIOB_BASE,
574 	    AT91C_PIO_PB16 | AT91C_PIO_PB17 | AT91C_PIO_PB18 | AT91C_PIO_PB19);
575 
576 	return (at91_ramsize());
577 }
578 
579 /*
580  * Override the default boot param parser (supplied via weak linkage) with one
581  * that knows how to handle our custom tsc_bootinfo passed in from boot2.
582  */
583 vm_offset_t
parse_boot_param(struct arm_boot_params * abp)584 parse_boot_param(struct arm_boot_params *abp)
585 {
586 
587 	boot_params = *abp;
588 
589 	/*
590 	 * If the right magic is in r0 and a non-NULL pointer is in r1, then
591 	 * it's our bootinfo, copy it.  The pointer in r1 is a physical address
592 	 * passed from boot2.  This routine is called immediately upon entry to
593 	 * initarm() and is in very nearly the same environment as boot2.  In
594 	 * particular, va=pa and we can safely copy the args before we lose easy
595 	 * access to the memory they're stashed in right now.
596 	 *
597 	 * Note that all versions of boot2 that we've ever shipped have put
598 	 * zeroes into r2 and r3.  Maybe that'll be useful some day.
599 	 */
600 	if (abp->abp_r0 == TSC_BOOTINFO_MAGIC && abp->abp_r1 != 0) {
601 		inkernel_bootinfo = *(struct tsc_bootinfo *)(abp->abp_r1);
602 	}
603 
604 	return fake_preload_metadata(abp, NULL, 0);
605 }
606 
607 ARM_BOARD(NONE, "TSC4370 Controller Board");
608 
609