                          Fox G20 SPI NOTES
                          =-=-=-=-=-=-=-=-=

Introduction
============
The Serial Peripheral Interface Bus (SPI) bus is a synchronous serial data
link standard. As usual, Wikipedia has a good explanatory article:
  http://en.wikipedia.org/wiki/Serial_Peripheral_Interface_Bus

SPI is relatively simple from an electrical point of view (compared with
something like USB) and can typically run at higher speeds (e.g. over 25
MHz) than classical (asynchronous) serial and I2C. SD cards support
multiple protocols including SPI (see the "Transfer modes" section of
http://en.wikipedia.org/wiki/Secure_Digital).

SPI can be done with "bit banging" in the user space using GPIO lines but
the clock speed would be in the 10 kHz range. Linux has a SPI bit banging
kernel driver (called SPI_GPIO) which would be a bit better. This
note will concentrate on the kernel driver for SPI hardware support in the
AT91SAM9G20 chip (called SPI_ATMEL).

Higher SPI clock speeds require shorter and better wiring plus a "clean"
3.3 volt supply. As usual there is a trade-off between speed and
reliability. In my experiments a SPI 15 MHz clock roughly wired to a SD card
read data at about 1.3 MB/sec (approximately the SPI clock speed divided by
11) but with the occasional error. At a SPI clock of 10 MHz the read speed
dropped to 970 kB/sec without any READ errors. 


Fox G20 hardware SPI basics and pins
====================================
The AT91SAM9G20 has two independent SPI controllers which can be configured
as either SPI masters or slaves.

        |  SPI0           SPI1
--------|------------------------------
MISO    |  PA0            PB0
MOSI    |  PA1            PB1
SPCK    |  PA2            PB2
CS0     |  PA3            PB3
CS1     |  PC11           PC5,PC18
CS2     |  PC16           PC4,PC19
CS3     |  PC17           PC3,PC20

PA0, PA1 and PA3 are used by the MMC interface (G20 MCI unit) to access the
microSD card. Since the microSD card on the FoxG20 main board is needed to
run the G20, then SPI0 is not available. Also PC16 and above are used to
access the RAM on the Netus board so are not available for other uses. PC4
and PC5 have a 1.8 volt rail (so should not exceed 2.1 volts) while PC3
is on the AVDD (analog) supply which is probably set to 3.3 volts. The
PA* and PB* lines have a 3.3 volt rail.

The Daisy-1 "mother" board names its D7 connector "SPI". It has pins for PB0
(pin 3), PB1 (2), PB2 (4) and PB3 (5). Pin 7 is PC4_33 (i.e. PC4 level
translated to 3.3 volts) and pin 6 is PC5_33 (i.e. PC5 level translated to
3.3 volts). Pin 8 is PC3 whose power rail is AVDD which is probably 3.3
volts.

On the FoxG20 the AT91SAM9G20 "master" clock (MCLK) is 132 MHz and SPCK
(i.e. clock driven by the SPI master) divides MCLK by a number in the range
1 to 255. The 'net suggests that the SPI clock to a SD card can be in the
range 0 MHz (DC) to 25 MHz. The SPI speed in this case is set in the
arch/arm/mach-at91/board-foxg20.c file (after my spi patch is applied);
look for ".max_speed_hz".


SD card with SPI interface example
==================================
A table follows which shows the mapping from GPIO lines (with their
SPI name equivalents) to the Daisy-1 board D7 connector. The
corresponding SD (SPI transfer mode) names are also shown:

GPIO    SPI     D7      SD      Notes
line    name    pin     name
---------------------------------------------------
PB0     MISO    3       DO
PB1     MOSI    2       DI
PB2     MSCK    4       SCK
PB3     NPCS0   5       CS      **
-       -       -       CD      Card Detect ***
-       -       1       Vcc     3.3 volts
-       -       10      Gnd     ground (0 volts)
-       -       9       -       5 volts (not used)
---------------------------------------------------

**  PB3 corresponds to .chip_select=0 in board-foxg20.c .
    [Could use PC5_33 with .chip_select=1 (but my spi patch
     would need a small edit).]

*** kernel doesn't seem to support CD. Could use gpio line and user
    space code to do sensible things when a card is inserted or
    removed


My test setup was based on the lk 3.1.0 kernel with patches found at
http://sg.danny.cz/foxg20/ applied. The patch for hardware SPI on
PB0, PB1, PB2, PB3 (and PC5) is fg20_spi304.patch . That patch does
the following:
   a) configures PB0, PB1, PB2 and PB3 (chip select) for a SD card
      and calls the mmc_spi module (which should result in the
      /dev/mmcblk1 (plus its partition devices) appearing).
   b) configures PB0, PB1, PB2 and PC5 (chip select) to be a SPI
      pass-through device with a name like /dev/spidev1.1
      [See Documentation/spi/spidev in the linux kernel source.]

Note that PB0, PB1, PB2 (and PB3 or PC5) cannot be used as "normal"
GPIO lines if the hardware SPI facility is required. Since this might
interfere with existing usage (it does in some of my systems) then
a kernel configuration parameters called CONFIG_SAM9G20_SPI1 is added
by the above patch. After applying that patch to select it use
'make menuconfig' and then under 'System type' and then 'Atmel AT91
System-on-Chip' check 'SPI on PB0 to PB2'.

The lsmod output on my test machine is as follows:
Module                  Size  Used by
ipv6                  223167  10 
mmc_spi                 8161  0 
crc7                     743  1 mmc_spi
spidev                  4278  0

Since the SPI hardware is detected (look at the output of dmesg) then
the kernel autoloads the mmc_spi and spidev modules. Obviously they
need to be build in the kernel. The 310.config_spi file on my site
is a copy of my '.config' file at the top level of my kernel source
tree. The 310_PATCHES file lists the patches I have applied to the
kernel source.

With a Sparkfun microSD breakout card wired to a Daisy-12 prototyping
board as indicated above, and a Daisy cable connecting the Daisy-12
to D7 ("SPI") on a Daisy-1 "mother" card, I see the following in
the dmesg output:
  ...
  atmel_spi atmel_spi.1: Atmel SPI Controller at 0xfffcc000 (irq 13)
  ...
  mmc_spi spi1.0: ASSUMING 3.2-3.4 V slot power
  mmc_spi spi1.0: SD/MMC host mmc1, no WP, no poweroff
  ...
  mmc1: host does not support reading read-only switch. assuming write-enable.
  mmc1: new SDHC card on SPI
  mmcblk1: mmc1:0000 SU04G 3.69 GiB 
   mmcblk1: p1 p2 p3

The speed is reasonable (IMO):
  # dd if=/dev/mmcblk1p2 bs=16k of=/dev/null count=1k
  1024+0 records in
  1024+0 records out
  16777216 bytes (17 MB) copied, 17.3201 s, 969 kB/s

and file systems can be mounted:
  # mount /dev/mmcblk1p1 /mnt/extra/

  # df -hT
  Filesystem    Type    Size  Used Avail Use% Mounted on
  /dev/mmcblk0p2
                ext4    886M  626M  252M  72% /
  tmpfs        tmpfs     30M     0   30M   0% /lib/init/rw
  varrun       tmpfs     30M   24K   30M   1% /var/run
  udev         tmpfs     10M  144K  9.9M   2% /dev
  tmpfs        tmpfs     30M     0   30M   0% /dev/shm
  /dev/mmcblk1p1
                vfat     64M  7.7M   57M  12% /mnt/extra


Note that the kernel does not detect an SD card being inserted or removed.
If you are aware the SD card is about to be removed then any file system
on it should be unmounted and doing a 'rmmod mmc_spi' command will clean
things up (failing that, use some 'sync' commands). Then after a SD card is
inserted doing a 'modprobe mmc_spi' command should make the corresponding
device nodes (e.g. /dev/mmcblk1p1) available (perhaps check the end of the
dmesg output).


SD card pinout
==============
For those that don't have a SD card breakout board the pinout on the actual
SD card follows. Holding a SD card with the pins up and facing you, the
angle should be on the upper left. Then the pins are numbered: 9, 1, 2, 3,
4, 5, 6, 7, 8 from left (the angle) to right:

 pin  name         used by SPI
 ---|-----------|---------------
  9 | DAT2      |     -
  1 | CS/DAT3   |     CS
  2 | DI/CMD    |     DI
  3 | Vss       |     ground
  4 | Vdd       |     3.3 volts
  5 | SCLK      |     SCK (clock)
  6 | Vss2      |     ground
  7 | DO/DAT0   |     DO
  8 | DAT1      |     - 


FoxG20 red LED improvement
==========================
The red LED on the FoxG20 is set to a "heartbeat" pattern after a Debian
kernel is loaded successfully. Aparting from being annoying (after a while)
it isn't very useful in showing that the G20 is actually running, for
example the heartbeat continues to run after the G20 is halted or if the
kernel crashes (an oops).

Someone [name] pointed out a better use for that red LED (driven by
the PC7 gpio line), and that is to show "disk" usage (reads or writes).
That can be done with this one-liner:
  # echo mmc0 > /sys/class/leds/user_led/trigger

That would be for the microSD card on the FoxG20 card. To associate
the red LED with this SPI-based SD card discussed in this note use:
  # echo mmc1 > /sys/class/leds/user_led/trigger

or to turn off the red LED:
  # echo none > /sys/class/leds/user_led/trigger
  


Douglas Gilbert [dgilbert@interlog.com]
20111026
