AM335x McSPI Driver's Guide

= Introduction =


 * Serial interface


 * Synchronous


 * Master-slave configuration (driver supports only master mode)


 * Data Exchange - DMA/PIO

= SPI H/W Architecture =

McSPI is a general-purpose receive/transmit, master/slave controller that can interface with up to four slave external devices or one single external master.It allows a duplex, synchronous, serial communication between a CPU and SPI compliant external devices (Slaves and Masters).

The controller supports following features.


 * Programmable master clock generation (operating from fixed 48-MHz functional clock input)
 * Up to four SPI channels
 * Two DMA requests per channel, one interrupt line



= SPI Driver Architecture =



AM335x EVM does not contain a SPI based audio codec. The reference to 'SPI Codec' above are meant to serve as an example. Use MTD-Utils user space tools to access SPI flash device from Linux console.

= Driver Configuration =


 * SPI could be disabled/enabled from the following location during menuconfig.

start Linux Kernel Configuration tool. make CROSS_COMPILE=arm-arago-linux-gnueabi- ARCH=arm menuconfig

Building into Kernel
Device Drivers ---&gt; [*] SPI support ---&gt; &lt;*&gt;  McSPI driver for OMAP Device Drivers ---&gt; &lt;*&gt; Memory Technology Device (MTD) support ---&gt; Self-contained MTD device drivers ---&gt; &lt;*&gt; Support most SPI Flash chips (AT26DF, M25P, W25X, ...) [*]  Use FAST_READ OPCode allowing SPI CLK &lt;= 50MHz (NEW)
 * Enable W25Q64 SPI flash support. This step is mandatory if for using root file-system on SPI flash.

Building as Loadable Kernel Module
Device Drivers ---&gt; [*] SPI support ---&gt; &lt;M&gt;  McSPI driver for OMAP Device Drivers ---&gt;
 * Incase if you want to build the drivers as modules, use &lt;M&gt; instead of &lt;*&gt; during menuconfig while selecting the drivers (as shown below). For more information on loadable modules refer Loadable Module HOWTO

&lt;*&gt; Memory Technology Device (MTD) support ---&gt; Self-contained MTD device drivers ---&gt; &lt;M&gt; Support most SPI Flash chips (AT26DF, M25P, W25X, ...) [*]  Use FAST_READ OPCode allowing SPI CLK &lt;= 50MHz (NEW)


 * This step applies if the drivers are built as modules - Do "make modules" to build the McSPI driver and SPI Flash driver as module. The module should be present in "drivers/spi/omap2_mcspi.ko" and "drivers/mtd/devices/m25p80.ko". Load the driver using "insmod omap2_mcspi.ko" and "insmod m25p80.ko"

= Validating SPI Support =

cd /tmp dd if=/dev/mtd2 of=test.img bs=8k count=1 md5sum test.img flash_eraseall /dev/mtd4 cp test.img /dev/mtd4 dd if=/dev/mtd4 of=test1.img bs=8k count=1 md5sum test1.img
 * Use the MTD interface provided for SPI flash on the EVM to validate the SPI driver interface. The below step copies 8KiB from /dev/mtd2 partition (u-boot env) to /dev/mtd4 partition and reads the 8KiB image from /dev/mtd4 to a file and checks the md5sum. The md5sum of test.img and test1.img should be same.

= Porting for custom hardware =


 * 1) drivers/spi/omap2_mcspi.c implements core SPI master functionality.
 * 2) *This file is generic hence should not be modified.
 * 3) Board specific customizations are available in arch/arm/mach-omap2/board-am35xevm.c
 * 4) Modify device array am335x_spix_slave_info to change information on slaves connected to SPI. When adding new slave devices, ensure that num_chipselect member of the platform data for the corresponding SPI master.
 * 5) *Each member is of type spi_board_info defined in include/linux/spi.h. Each element of the device array represents one slave device.
 * 6) *#modalias used to match slave device to slave driver. Note that this is not the SPI master driver. Each slave needs to have its own driver. Example, SPI flash will have a MTD driver, SPI codec will have an ALSA driver etc.
 * 7) *#platform_data</tt> used by slave driver
 * 8) *#controller_data</tt> used by SPI master driver for slave specific information (of type omap2_mcspi_cs</tt>). This is used to take care of specific requirements of communicating with a given slave.
 * 9) *#bus_num</tt> 1 for SPI0 which is used by SPI flash in General purpose EVM &amp;  bus_num 2 for SPI1 which is used by SPI flash in AUtomation motor control EVM..
 * 10) *#chip_select</tt> chip select number for this SPI slave
 * 11) *#max_speed_hz</tt> SPI bus speed.
 * 12) Ensure all pins required for SPI operation are muxed correctly (especially if using GPIO for CS)

= Supporting SPI Flashes =

struct mtd_partition am335x_spi_partitions[] = { /* All the partition sizes are listed in terms of NAND block size */ {       .name       = "SPL", .offset    = 0,    /* Offset = 0x0 */ .size      = SZ_128K, .mask_flags = MTD_WRITEABLE,   /* force read-only */ },   {        .name       = "U-Boot", .offset    = MTDPART_OFS_APPEND,    /* Offset = 0x20000 */ .size      = 2 * SZ_128K, .mask_flags = MTD_WRITEABLE,   /* force read-only */ },   {        .name       = "U-Boot Env", .offset    = MTDPART_OFS_APPEND,   /* Offset = 0x60000 */ .size      = 2 * SZ_4K, },   {        .name       = "Kernel", .offset    = MTDPART_OFS_APPEND,   /* Offset = 0x62000 */ .size      = 28 * SZ_128K, },   {        .name       = "File System", .offset    = MTDPART_OFS_APPEND,   /* Offset = 0x3e2000 */ .size      = MTDPART_SIZ_FULL, } };
 * To modify partition layout on SPI flash following structure has to be modified in arch/arm/mach-omap2/board-am335xevm.c

struct spi_board_info __initdata am335x_spi0_slave_info[] = { {       .modalias   = "m25p80", .platform_data = &amp;am335x_spi_flash, .irq       = -1, .max_speed_hz  = 24000000, .bus_num   = 1, .chip_select   = 0, }, };
 * SPI Flash information is available in following structure in file arch/arm/mach-omap2/board-am335xevm.c. This structure should be modified to support a SPI flash. The example structure given here supports most of the SPI flashes, check drivers/mtd/devices/m25p80.c for support for the new SPI flash. The string constants .modalias and .type depend on device names provided in the slave driver (in our case m25p80.c). The .type string here selects W25Q64 SPI flash, which has to be modified in case of new SPI flash.

struct spi_board_info __initdata am335x_spi1_slave_info[] = { {       .modalias   = "m25p80", .platform_data = &amp;am335x_spi_flash, .irq       = -1, .max_speed_hz  = 12000000, .bus_num   = 2, .chip_select   = 0, }, };

const struct flash_platform_data am335x_spi_flash = {

.type      = "w25q64", .name      = "spi_flash", .parts     = am335xx_spi_partitions, .nr_parts  = ARRAY_SIZE(am335x_spi_partitions), };


 * Check drivers/mtd/devices/m25p80.c does not support the new SPI flash then it has to be added to the m25p_ids[] list.

= Proc Interface =

The  kernel interface is a status interface. A lot of useful information about the SPI system can be found in the  file.


 * Use /proc/mtd to get information on how many partitions are currently configured by the kernels flash driver.

target$ cat /proc/mtd

You should see output similar to:

target$ cat /proc/mtd dev:   size   erasesize  name mtd0: 00020000 00001000 "SPL" mtd1: 00040000 00001000 "U-Boot" mtd2: 00002000 00001000 "U-Boot Env" mtd3: 00380000 00001000 "Kernel" mtd4: 0041e000 00001000 "File System"

= Mounting SPI partition using JFFS2 =

Follow the steps mentioned in Enabling_JFFS2_support to recompile Linux to support JFFS2. After recompiling the kernel with JFFS2 support follw the steps below to mount the partition with JFFS2 file system. flash_eraseall /dev/mtd&lt;X&gt; Where x is the partition number to be erased.

Mount the partition using mount -t jffs2 /dev/mtdblock&lt;x&gt; &lt;mount_point&gt; Where x is the partition number to be erased. In the following example, partition 4 is mounted on /media/card mount point flash_eraseall /dev/mtd4

mount -t jffs2 /dev/mtdblock4 /media/card NOTE File system partition is available from offset 0x3E2000 with partition size of 0x41e000 (4.1 MB). So try to fit the image size below 4.1 MB.