Author: ian
Date: Tue Feb 11 21:13:37 2014
New Revision: 261779
URL: http://svnweb.freebsd.org/changeset/base/261779

Log:
  Check in the "real" board_tsc4370 file in place of the stubbed out one.
  
  Real means the one TSC / Symmetricom / Microsemi actually uses on their 4370
  and other rm9200 boards.  This code demonstrates a variety of useful things
  board init code can do, including adjusting the master clock frequency.

Modified:
  head/sys/arm/at91/board_tsc4370.c

Modified: head/sys/arm/at91/board_tsc4370.c
==============================================================================
--- head/sys/arm/at91/board_tsc4370.c   Tue Feb 11 20:14:54 2014        
(r261778)
+++ head/sys/arm/at91/board_tsc4370.c   Tue Feb 11 21:13:37 2014        
(r261779)
@@ -1,6 +1,7 @@
 /*-
  * Copyright (c) 2005-2008 Olivier Houchard.  All rights reserved.
  * Copyright (c) 2005-2012 Warner Losh.  All rights reserved.
+ * Copyright (c) 2007-2014 Ian Lepore.  All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -24,45 +25,573 @@
  * SUCH DAMAGE.
  */
 
+/*
+ * Board init code for the TSC4370, and all other current TSC mainboards.
+ */
+
 #include <sys/cdefs.h>
 __FBSDID("$FreeBSD$");
 #include <sys/param.h>
 #include <sys/systm.h>
 
-#include <machine/board.h>
+#include <arm/at91/at91_pioreg.h>
+#include <arm/at91/at91_piovar.h>
+#include <arm/at91/at91_pmcreg.h>
+#include <arm/at91/at91_pmcvar.h>
+#include <arm/at91/at91_twireg.h>
+#include <arm/at91/at91_usartreg.h>
 #include <arm/at91/at91board.h>
 #include <arm/at91/at91var.h>
-#include <arm/at91/at91rm92reg.h>
 #include <arm/at91/at91rm9200var.h>
-#include <arm/at91/at91_piovar.h>
-#include <arm/at91/at91_pioreg.h>
+#include <arm/at91/at91rm92reg.h>
+#include <arm/at91/if_atereg.h>
+#include <machine/board.h>
+#include <machine/cpu.h>
+#include <machine/machdep.h>
+#include <net/ethernet.h>
+#include <sys/reboot.h>
+
+/*
+ * RD4HW()/WR4HW() read and write at91rm9200 hardware register space directly.
+ * They serve the same purpose as the RD4()/WR4() idiom you see in many 
drivers,
+ * except that those translate to bus_space calls, but in this code we need to
+ * access the registers directly before the at91 bus_space stuff is set up.
+ */
+
+static inline uint32_t 
+RD4HW(uint32_t devbase, uint32_t regoff)
+{
+       return *(volatile uint32_t *)(AT91_BASE + devbase + regoff);
+}
+
+static inline void
+WR4HW(uint32_t devbase, uint32_t regoff, uint32_t val)
+{
+       *(volatile uint32_t *)(AT91_BASE + devbase + regoff) = val;
+}
+
+#ifndef BAUD2DIVISOR
+#define BAUD2DIVISOR(b) \
+       ((((at91_master_clock * 10) / ((b) * 16)) + 5) / 10)
+#endif
+
+/*
+ * If doing an in-house build, use tsc_bootinfo.h which is shared with our
+ * custom boot2.  Otherwise define some crucial bits of it here, enough to 
allow
+ * this code to compile.
+ */
+#ifdef TSC_BUILD
+#include <machine/tsc_bootinfo.h>
+#else
+struct tsc_bootinfo {
+       uint32_t        bi_size;
+       uint32_t        bi_version;
+       uint32_t        bi_flags; /* RB_xxxxx flags from sys/reboot.h */
+       char    bi_rootdevname[64];
+};
+#define TSC_BOOTINFO_MAGIC     0x06C30000 
+#endif
+
+static struct arm_boot_params  boot_params;
+static struct tsc_bootinfo     inkernel_bootinfo;
+
+/*
+ * Override the default boot param parser (supplied via weak linkage) with one
+ * that knows how to handle our custom tsc_bootinfo passed in from boot2.
+ */
+vm_offset_t
+parse_boot_param(struct arm_boot_params *abp)
+{
+
+       boot_params = *abp;
+
+       /*
+        * If the right magic is in r0 and a non-NULL pointer is in r1, then
+        * it's our bootinfo, copy it.  The pointer in r1 is a physical address
+        * passed from boot2.  This routine is called immediately upon entry to
+        * initarm() and is in very nearly the same environment as boot2.  In
+        * particular, va=pa and we can safely copy the args before we lose easy
+        * access to the memory they're stashed in right now.
+        *
+        * Note that all versions of boot2 that we've ever shipped have put
+        * zeroes into r2 and r3.  Maybe that'll be useful some day.
+        */
+       if (abp->abp_r0 == TSC_BOOTINFO_MAGIC && abp->abp_r1 != 0) {
+               inkernel_bootinfo = *(struct tsc_bootinfo *)(abp->abp_r1);
+       }
+
+       return fake_preload_metadata(abp);
+}
+
+/*
+ * Change the master clock config and wait for it to stabilize.
+ */
+static void
+change_mckr(uint32_t mckr)
+{
+       int i;
+
+       WR4HW(AT91RM92_PMC_BASE, PMC_MCKR, mckr);
+
+       for (i = 0; i < 1000; ++i)
+               if ((RD4HW(AT91RM92_PMC_BASE, PMC_SR) & PMC_IER_MCKRDY))
+                       return;
+}
+
+/*
+ * Allow the master clock frequency to be changed from whatever the bootloader
+ * set up, because sometimes it's harder to change/update a bootloader than it
+ * is to change/update the kernel once a product is in the field.
+ */
+static void
+master_clock_init(void)
+{
+       uint32_t mckr = RD4HW(AT91RM92_PMC_BASE, PMC_MCKR);
+       int hintvalue = 0;
+       int newmckr = 0;
+
+        /*
+        * If there's a hint that specifies the contents of MCKR, use it
+        * without question (it had better be right).
+        *
+        * If there's a "mckfreq" hint it might be in hertz or mhz (convert the
+        * latter to hz).  Calculate the new MCK divider.  If the CPU frequency
+        * is not a sane multiple of the hinted MCK frequency this is likely to
+        * behave badly.  The moral is: don't hint at impossibilities.
+        */
+
+       if (resource_int_value("at91", 0, "mckr", &hintvalue) == 0) {
+               newmckr = hintvalue;
+       } else {
+               hintvalue = 90; /* Default to 90mhz if not specified. */
+               resource_int_value("at91", 0, "mckfreq", &hintvalue);
+               if (hintvalue != 0) {
+                       if (hintvalue < 1000)
+                               hintvalue *= 1000000;
+                       if (hintvalue != at91_master_clock) {
+                               uint32_t divider;
+                               struct at91_pmc_clock * cpuclk;
+                               cpuclk = at91_pmc_clock_ref("cpu");
+                               divider = (cpuclk->hz / hintvalue) - 1;
+                               newmckr = (mckr & 0xFFFFFCFF) | ((divider & 
0x03) << 8);
+                               at91_pmc_clock_deref(cpuclk);
+                       }
+               }
+       }
+
+       /* If the new mckr value is different than what's in the register now,
+        * make the change and wait for the clocks to settle (MCKRDY status).
+        *
+        * MCKRDY will never be asserted unless either the selected clock or the
+        * prescaler value changes (but not both at once) [this is detailed in
+        * the rm9200 errata]. This code assumes the prescaler value is always
+        * zero and that by time we get to here we're running on something other
+        * than the slow clock, so to change the mckr divider we first change
+        * back to the slow clock (keeping prescaler and divider unchanged),
+        * then go back to the original selected clock with the new divider.
+        *
+        * After changing MCK, go re-init everything clock-related, and reset
+        * the baud rate generator for the console (doing this here is kind of a
+        * rude hack, but hey, you do what you have to to run MCK faster).
+        */
+
+       if (newmckr != 0 && newmckr != mckr) {
+               if (mckr & 0x03)
+                       change_mckr(mckr & ~0x03);
+               change_mckr(newmckr);
+               at91_pmc_init_clock();
+               WR4HW(AT91RM92_DBGU_BASE, USART_BRGR, BAUD2DIVISOR(115200));
+       }
+}
+
+/*
+ * TSC-specific code to read the ID eeprom on the mainboard and extract the
+ * unit's EUI-64 which gets translated into a MAC-48 for ethernet.
+ */
+static void
+eeprom_init(void)
+{
+       const uint32_t twiHz    = 400000;
+       const uint32_t twiCkDiv = 1 << 16;
+       const uint32_t twiChDiv = ((at91_master_clock / twiHz) - 2) << 8;
+       const uint32_t twiClDiv = ((at91_master_clock / twiHz) - 2);
+
+       /*
+        * Set the TWCK and TWD lines for Periph A, no pullup, open-drain.
+        */
+       at91_pio_use_periph_a(AT91RM92_PIOA_BASE,
+           AT91C_PIO_PA25 | AT91C_PIO_PA26, 0);
+       at91_pio_gpio_high_z(AT91RM92_PIOA_BASE, AT91C_PIO_PA25, 1);
+
+       /*
+        * Enable TWI power (irq numbers are also device IDs for power)
+        */
+       WR4HW(AT91RM92_PMC_BASE, PMC_PCER, 1u << AT91RM92_IRQ_TWI);
+
+       /*
+        * Disable TWI interrupts, reset device, enable Master mode,
+        * disable Slave mode, set the clock.
+        */
+       WR4HW(AT91RM92_TWI_BASE, TWI_IDR, 0xffffffff);
+       WR4HW(AT91RM92_TWI_BASE, TWI_CR, TWI_CR_SWRST);
+       WR4HW(AT91RM92_TWI_BASE, TWI_CR, TWI_CR_MSEN | TWI_CR_SVDIS);
+       WR4HW(AT91RM92_TWI_BASE, TWI_CWGR, twiCkDiv | twiChDiv | twiClDiv);
+}
+
+static int
+eeprom_read(uint32_t EE_DEV_ADDR, uint32_t ee_off, void * buf, uint32_t size)
+{
+       uint8_t *bufptr = (uint8_t *)buf;
+       uint32_t status;
+       uint32_t count;
+
+       /* Clean out any old status and received byte. */
+       status = RD4HW(AT91RM92_TWI_BASE, TWI_SR);
+       status = RD4HW(AT91RM92_TWI_BASE, TWI_RHR);
+
+       /* Set the TWI Master Mode Register */
+       WR4HW(AT91RM92_TWI_BASE, TWI_MMR,
+           TWI_MMR_DADR(EE_DEV_ADDR) | TWI_MMR_IADRSZ(2) | TWI_MMR_MREAD);
+
+       /* Set TWI Internal Address Register */
+       WR4HW(AT91RM92_TWI_BASE, TWI_IADR, ee_off);
+
+       /* Start transfer */
+       WR4HW(AT91RM92_TWI_BASE, TWI_CR, TWI_CR_START);
+
+       status = RD4HW(AT91RM92_TWI_BASE, TWI_SR);
+
+       while (size-- > 1){
+               /* Wait until Receive Holding Register is full */
+               count = 1000000;
+               while (!(RD4HW(AT91RM92_TWI_BASE, TWI_SR) & TWI_SR_RXRDY) && 
+                   --count != 0)
+                       continue;
+               if (count <= 0)
+                       return -1;
+               /* Read and store byte */
+               *bufptr++ = (uint8_t)RD4HW(AT91RM92_TWI_BASE, TWI_RHR);
+       }
+       WR4HW(AT91RM92_TWI_BASE, TWI_CR, TWI_CR_STOP);
+
+       status = RD4HW(AT91RM92_TWI_BASE, TWI_SR);
+
+       /* Wait until transfer is finished */
+       while (!(RD4HW(AT91RM92_TWI_BASE, TWI_SR) & TWI_SR_TXCOMP))
+               continue;
+
+       /* Read last byte */
+       *bufptr = (uint8_t)RD4HW(AT91RM92_TWI_BASE, TWI_RHR);
+
+       return 0;
+}
+
+static int
+set_mac_from_idprom(void)
+{
+#define SIGNATURE_SIZE          4
+#define EETYPE_SIZE             2
+#define BSLENGTH_SIZE           2
+#define RAW_SIZE                52
+#define EUI64_SIZE              8
+#define BS_SIGNATURE            0x21706d69
+#define BSO_SIGNATURE           0x216f7362
+#define DEVOFFSET_BSO_SIGNATURE 0x20
+#define OFFSET_BS_SIGNATURE     0
+#define SIZE_BS_SIGNATURE       SIGNATURE_SIZE
+#define OFFSET_EETYPE           (OFFSET_BS_SIGNATURE + SIZE_BS_SIGNATURE)
+#define SIZE_EETYPE             EETYPE_SIZE
+#define OFFSET_BOOTSECTSIZE     (OFFSET_EETYPE + SIZE_EETYPE)
+#define SIZE_BOOTSECTSIZE       BSLENGTH_SIZE
+#define OFFSET_RAW              (OFFSET_BOOTSECTSIZE + SIZE_BOOTSECTSIZE)
+#define OFFSET_EUI64            (OFFSET_RAW + RAW_SIZE)
+#define EE_DEV_ADDR             0xA0    /* eeprom is AT24C256 at address 0xA0 
*/
+
+       int status;
+       uint32_t dev_offset = 0;
+       uint32_t sig;
+       uint8_t eui64[EUI64_SIZE];
+       uint8_t eaddr[ETHER_ADDR_LEN];
+
+       eeprom_init();
+
+       /* Check for the boot section signature at offset 0. */
+       status = eeprom_read(EE_DEV_ADDR, OFFSET_BS_SIGNATURE, &sig, 
sizeof(sig));
+       if (status == -1)
+               return -1;
+
+       if (sig != BS_SIGNATURE) {
+               /* Check for the boot section offset signature. */
+               status = eeprom_read(EE_DEV_ADDR, 
+                   DEVOFFSET_BSO_SIGNATURE, &sig, sizeof(sig));
+               if ((status == -1) || (sig != BSO_SIGNATURE))
+                               return -1;
+
+               /* Read the device offset of the boot section structure. */
+               status = eeprom_read(EE_DEV_ADDR, 
+                   DEVOFFSET_BSO_SIGNATURE + sizeof(sig), 
+                   &dev_offset, sizeof(dev_offset));
+               if (status == -1)
+                               return -1;;
+
+               /* Check for the boot section signature. */
+               status = eeprom_read(EE_DEV_ADDR, 
+                   dev_offset + OFFSET_BS_SIGNATURE, &sig, sizeof(sig));
+               if ((status == -1) || (sig != BS_SIGNATURE))
+                               return -1;;
+       }
+       dev_offset += OFFSET_EUI64;
+
+       /* Read the EUI64 from the device.  */
+       if (eeprom_read(EE_DEV_ADDR, dev_offset, eui64, sizeof(eui64)) == -1)
+               return -1;;
+
+       /* Transcribe the EUI-64 to a MAC-48.
+        *
+        * Given an EUI-64 of aa:bb:cc:dd:ee:ff:gg:hh
+        *
+        *   if (ff is zero and ee is non-zero)
+        *      mac is aa:bb:cc:ee:gg:hh
+        *   else
+        *      mac is aa:bb:cc:ff:gg:hh
+        *
+        * This logic fixes a glitch in our mfg process in which the ff byte was
+        * always zero and the ee byte contained a non-zero value.  This
+        * resulted in duplicate MAC addresses because we discarded the ee byte.
+        * Now they've fixed the process so that the ff byte is non-zero and
+        * unique addresses are formed from the ff:gg:hh bytes.  If the ff byte
+        * is zero, then we have a unit manufactured during the glitch era, and
+        * we fix the problem by grabbing the ee byte rather than the ff byte.
+        */
+       eaddr[0] = eui64[0];
+       eaddr[1] = eui64[1];
+       eaddr[2] = eui64[2];
+       eaddr[3] = eui64[5];
+       eaddr[4] = eui64[6];
+       eaddr[5] = eui64[7];
+
+       if (eui64[5] == 0 && eui64[4] != 0) {
+               eaddr[3] = eui64[4];
+       }
+
+       /*
+        * Set the address in the hardware regs where the ate driver
+        * looks for it.
+        */
+       WR4HW(AT91RM92_EMAC_BASE, ETH_SA1L, 
+           (eaddr[3] << 24) | (eaddr[2] << 16) | (eaddr[1] << 8) | eaddr[0]);
+       WR4HW(AT91RM92_EMAC_BASE, ETH_SA1H, 
+           (eaddr[5] << 8) | (eaddr[4]));
+
+       printf(
+           "ID: EUI-64 %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n"
+           "    MAC-48 %02x:%02x:%02x:%02x:%02x:%02x\n"
+           "    read from i2c device 0x%02X offset 0x%x\n",
+           eui64[0], eui64[1], eui64[2], eui64[3], 
+           eui64[4], eui64[5], eui64[6], eui64[7], 
+           eaddr[0], eaddr[1], eaddr[2], 
+           eaddr[3], eaddr[4], eaddr[5], 
+           EE_DEV_ADDR, dev_offset);
+
+       return (0);
+}
+
+/*
+ * Assign SPI chip select pins based on which chip selects are found in hints.
+ */
+static void
+assign_spi_pins(void)
+{
+       struct {
+               uint32_t     num;
+               const char * name;
+       } chipsel_pins[] = {
+               { AT91C_PIO_PA3, "PA3", },
+               { AT91C_PIO_PA4, "PA4", },
+               { AT91C_PIO_PA5, "PA5", },
+               { AT91C_PIO_PA6, "PA6", },
+       };
+       int anchor = 0;
+       uint32_t chipsel_inuse = 0;
+
+       /*
+        * Search through all device hints looking for any that have
+        * ".at=spibus0".  For each one found, ensure that there is also a
+        * chip select hint ".cs=<num>" and that <num> is 0-3, and assign the
+        * corresponding pin to the SPI peripheral.  Whine if we find a SPI
+        * device with a missing or invalid chipsel hint.
+        */
+       for (;;) {
+               const char * rName = "";
+               int unit = 0;
+               int cs = 0;
+               int ret;
+
+               ret = resource_find_match(&anchor, &rName, &unit, "at", 
"spibus0");
+               if (ret != 0)
+                       break;
+
+               ret = resource_int_value(rName, unit, "cs", &cs);
+               if (ret != 0) {
+                       printf( "Error: hint for SPI device %s%d "
+                               "without a chip select hint; "
+                               "device will not function.\n",
+                               rName, unit);
+                       continue;
+               }
+               if (cs < 0 || cs > 3) {
+                       printf( "Error: hint for SPI device %s%d "
+                               "contains an invalid chip select "
+                               "value: %d\n",
+                               rName, unit, cs);
+                       continue;
+               }
+               if (chipsel_inuse & (1 << cs)) {
+                       printf( "Error: hint for SPI device %s%d "
+                               "specifies chip select %d, which "
+                               "is already used by another device\n",
+                               rName, unit, cs);
+                       continue;
+               }
+               chipsel_inuse |= 1 << cs;
+               at91_pio_use_periph_a(AT91RM92_PIOA_BASE, 
+                       chipsel_pins[cs].num, 1);
+               printf( "Configured pin %s as SPI chip "
+                       "select %d for %s%d\n",
+                       chipsel_pins[cs].name, cs, rName, unit);
+       }
+
+       /*
+        * If there were hints for any SPI devices, assign the basic SPI IO pins
+        * and enable SPI power (irq numbers are also device IDs for power).
+        */
+       if (chipsel_inuse != 0) {
+               at91_pio_use_periph_a(AT91RM92_PIOA_BASE, 
+                       AT91C_PIO_PA1 | AT91C_PIO_PA0 | AT91C_PIO_PA2, 0);
+               WR4HW(AT91RM92_PMC_BASE, PMC_PCER, 1u << AT91RM92_IRQ_SPI);
+       }
+}
 
 BOARD_INIT long
 board_init(void)
 {
+       int is_bga, rev_mii;
+
+       /*
+        * Deal with bootinfo (if any) passed in from the boot2 bootloader and
+        * copied to the static inkernel_bootinfo earlier in the init.  Do this
+        * early so that bootverbose is set from this point on.
+        */
+       if (inkernel_bootinfo.bi_size > 0 && 
+           (inkernel_bootinfo.bi_flags & RB_BOOTINFO)) {
+               struct tsc_bootinfo *bip = &inkernel_bootinfo;
+               printf("TSC_BOOTINFO: size %u howtoflags=0x%08x 
rootdev='%s'\n", 
+                   bip->bi_size, bip->bi_flags, bip->bi_rootdevname);
+               boothowto = bip->bi_flags;
+               bootverbose = (boothowto & RB_VERBOSE);
+               if (bip->bi_rootdevname[0] != 0)
+                       rootdevnames[0] = bip->bi_rootdevname;
+       }
 
-       at91rm9200_set_subtype(AT91_ST_RM9200_PQFP);
+       /*
+        * The only way to know if we're in a BGA package (and thus have PIOD)
+        * is to be told via a hint; there's nothing detectable in the silicon.
+        * This is esentially an rm92-specific extension to getting the chip ID
+        * (which was done by at91_machdep just before calling this routine).
+        * If it is the BGA package, enable the clock for PIOD.
+        */
+       is_bga = 0;
+       resource_int_value("at91", 0, "is_bga_package", &is_bga);
+       
+       if (is_bga)
+               WR4HW(AT91RM92_PMC_BASE, PMC_PCER, 1u << AT91RM92_IRQ_PIOD);
+       
+#if __FreeBSD_version >= 1000000
+       at91rm9200_set_subtype(is_bga ? AT91_ST_RM9200_BGA : 
+           AT91_ST_RM9200_PQFP);
+#endif
 
+       /*
+        * Go reprogram the MCK frequency based on hints.
+        */
+       master_clock_init();
+
+       /*
+        * Configure UARTs.
+        */
        at91rm9200_config_uart(AT91_ID_DBGU, 0, 0);   /* DBGU just Tx and Rx */
        at91rm9200_config_uart(AT91RM9200_ID_USART0, 1, 0);   /* Tx and Rx */
        at91rm9200_config_uart(AT91RM9200_ID_USART1, 2, 0);   /* Tx and Rx */
        at91rm9200_config_uart(AT91RM9200_ID_USART2, 3, 0);   /* Tx and Rx */
        at91rm9200_config_uart(AT91RM9200_ID_USART3, 4, 0);   /* Tx and Rx */
 
-       at91rm9200_config_mci(0);                       /* tsc4370 board has 
only 1 wire */
-                                                       /* Newer boards may 
have 4 wires */
+       /*
+        * Configure MCI (sdcard)
+        */
+       at91rm9200_config_mci(0);
+
+       /*
+        * Assign the pins needed by the emac device, and power it up. Also,
+        * configure it for RMII operation unless the 'revmii_mode' hint is set,
+        * in which case configure the full set of MII pins.  The revmii_mode
+        * hint is for so-called reverse-MII, used for connections to a Broadcom
+        * 5325E switch on some boards.  Note that order is important here:
+        * configure pins, then power on the device, then access the device's
+        * config registers.
+        */
+       rev_mii = 0;
+       resource_int_value("ate", 0, "phy_revmii_mode", &rev_mii);
+
+       at91_pio_use_periph_a(AT91RM92_PIOA_BASE, 
+               AT91C_PIO_PA7 | AT91C_PIO_PA8 | AT91C_PIO_PA9 |
+               AT91C_PIO_PA10 | AT91C_PIO_PA11 | AT91C_PIO_PA12 |
+               AT91C_PIO_PA13 | AT91C_PIO_PA14 | AT91C_PIO_PA15 |
+               AT91C_PIO_PA16, 0);
+       if (rev_mii) {
+               at91_pio_use_periph_b(AT91RM92_PIOB_BASE,
+                   AT91C_PIO_PB12 | AT91C_PIO_PB13  | AT91C_PIO_PB14 |
+                   AT91C_PIO_PB15 | AT91C_PIO_PB16  | AT91C_PIO_PB17 |
+                   AT91C_PIO_PB18 | AT91C_PIO_PB19, 0);
+       }
+       WR4HW(AT91RM92_PMC_BASE, PMC_PCER, 1u << AT91RM92_IRQ_EMAC);
+       if (!rev_mii) {
+               WR4HW(AT91RM92_EMAC_BASE, ETH_CFG, 
+                   RD4HW(AT91RM92_EMAC_BASE, ETH_CFG) | ETH_CFG_RMII);
+       }
 
-       /* Configure TWI */
-       /* Configure SPI + dataflash */
-       /* Configure SSC */
-       /* Configure USB Host */
-       /* Configure FPGA attached to chip selects */
-
-       /* Pin assignment */
-       /* Assert PA24 low -- talk to rubidium */
-       at91_pio_use_gpio(AT91RM92_PIOA_BASE, AT91C_PIO_PA24);
-       at91_pio_gpio_output(AT91RM92_PIOA_BASE, AT91C_PIO_PA24, 0);
-       at91_pio_gpio_clear(AT91RM92_PIOA_BASE, AT91C_PIO_PA24);
+       /*
+        * Get our ethernet MAC address from the ID eeprom.
+        * Configures TWI as a side effect.
+        */
+       set_mac_from_idprom();
+
+       /*
+        * Configure SPI
+        */
+       assign_spi_pins();
+
+       /*
+        * Configure SSC
+        */
+       at91_pio_use_periph_a(
+           AT91RM92_PIOB_BASE,
+           AT91C_PIO_PB6 | AT91C_PIO_PB7 | AT91C_PIO_PB8 |   /* transmit */
+           AT91C_PIO_PB9 | AT91C_PIO_PB10 | AT91C_PIO_PB11,  /* receive */
+           0);                                               /* no pullup */
+
+       /*
+        *  We're using TC1's A1 input for PPS measurements that drive the
+        *  kernel PLL and our NTP refclock.  On some old boards we route a 5mhz
+        *  signal to TC1's A2 input (pin PA21), but we have never used that
+        *  clock (it rolls over too fast for hz=100), and now newer boards are
+        *  using pin PA21 as a CTS0 for USART1, so we no longer assign it to
+        *  the timer block like we used to here.
+        */
+       at91_pio_use_periph_b(AT91RM92_PIOA_BASE, AT91C_PIO_PA19, 0);
+
+       /*
+        * Configure pins used to bitbang-upload the firmware to the main FPGA.
+        */
        at91_pio_use_gpio(AT91RM92_PIOB_BASE,
            AT91C_PIO_PB16 | AT91C_PIO_PB17 | AT91C_PIO_PB18 | AT91C_PIO_PB19);
 
@@ -70,3 +599,4 @@ board_init(void)
 }
 
 ARM_BOARD(NONE, "TSC4370 Controller Board");
+
_______________________________________________
[email protected] mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "[email protected]"

Reply via email to