OpenWrt Forum Archive

Topic: How to add a generic SPI, Serial Peripheral Interface

The content of this topic has been archived on 4 Apr 2018. There are no obvious gaps in this topic, but there may still be some posts missing at the end.

I started with the MMC driver documented at 2.2. Adding an MMC/SD Card, hacked out the MMC/SD parts and replaced the block driver code with character driver code.  The new driver creates a /dev/spi/0

I want to put the code into the Wiki, but before I do that, I want to get all the copyright notices and attributions correct.  In particular, most of the code in the SPI driver, came from the MMC driver by "Madsuk/Rohde".  What is the appropriate way to write the MODULE_AUTHOR line?  I don't want to claim that I wrote their code, nor do I want them to suffer from bugs in my code.

My version of the code is at http://hamjudo.com/spi_driver in the files spi.c and Makefile.  There is also a program spitest.c that does a trivial test of the spi driver.  I added symlinks ending in .txt for the 3 files, since I didn't want to delay everything while I looked up how to get  the files to transfer as type text for your browsers.

Right now there is no logic for multiple SPI ports, it needs more comments, general cleanup, and probably bug fixes.  After I get the copyright notices and attributions correct, then I'll add support for /dev/spi/1.  With /dev/spi/0 and /dev/spi/1, it'll be obvious to other coders how to add more SPI devices in the source, as long as there are GPIO lines available.

The code as written doesn't support full duplex communication over the SPI port.  It writes all ones when it reads.  If I can get an example full duplex device, I can add an ioctl or other interface to switch to a real full duplex mode. I'm old, I only know ioctl, but I can learn the new better way to do this sort of thing.

If it isn't already obvious, the goal is to talk to spi devices other than MMC cards.  I just haven't started on that part of the hardware.

As I was researching this, I came across links to an LCD driver at http://www.duff.dk/wrt54gs, which is another driver that contains an SPI driver.  My goal is to make something a bit more generic for connecting PIC's, AVR's and random chips from DigiKey. So I want to keep as much as the chip specific stuff in user space.

Oh - that sounds great. Our hope with releasing all the stuff was that other people could have fun with it.
You are free to do whatever you like with the code and preferable you should put yourself in module author since you will be maintaining it.

But really nice idea to make a general SPI driver (perhaps it could also be made into an i2c driver?)

Thanks.  I've changed the module author.

Is there anything wrong with the i2c driver listed in item 2.14 of http://wiki.openwrt.org/OpenWrtDocs/Customizing.

Or by making it into an i2c driver did you mean something fancier, like a scheme for allocating GPIO lines, so that you can't have the i2c driver "share" GPIO4 with the spi driver, since that's how the code is written now, and it certainly could not really work.

The process of recompiling to change GPIO pin assignments in the modules is less than ideal.  I'm open to suggestions on how to do that more cleanly.

Didn't know that the i2c driver actually existed so just forget my comment smile

I think recompilation for changing pins is ok by me. Of course you could add some module parameters enabling people to change them, but don't think there is much need for that anyway.

got the module and test program to compile. when i transfer to my router and isnmod spi.o seems to work (shows up in dmesg) but then when i try to run the test program, it says /dev/spi/0 does not exist. im using dd wrt right now, forgot my power brick for the router, so i cant put openwrt on it right now.

also, i dont have any jffs space, so im just scp-ing the files over to /tmp and running them. should be OK, right?

edit: i have no idea which kernel i compiled for so i guess that might be my problem....

(Last edited by dext3r on 28 Jan 2008, 19:35)

alright, got Kamikaze 7.09 on the router. recompiled the driver and test program

here are the outputs:

makefile:

#changed the buildroot 
#dext3r - 1/25/08

TARGET  := spi
BUILDROOT := /home/dext3r/trunk
WARN    := -W -Wall -Wstrict-prototypes -Wmissing-prototypes -fno-strict-aliasing -mips32
INCLUDE := -isystem ${BUILDROOT}/build_mipsel/linux/include 
CFLAGS  := -O2 -DMODULE -D__KERNEL__ ${WARN} ${INCLUDE} -fno-pic -mno-abicalls -mlong-calls
 CC      := ${BUILDROOT}/staging_dir/toolchain-mipsel_gcc3.4.6/bin/mipsel-linux-gcc

all: ${TARGET}.o spitest
${TARGET}.o: ${TARGET}.c

spitest: spitest.c
     ${BUILDROOT}/staging_dir/toolchain-mipsel_gcc3.4.6/bin/mipsel-linux-gcc -o spitest spitest.c

running make on my desktop

dext3r@dext3r-ubuntu7:~/Desktop$ make. 
/home/dext3r/trunk/staging_dir/toolchain-mipsel_gcc3.4.6/bin/mipsel-linux-gcc -O2 -DMODULE -D__KERNEL__ -W -Wall -Wstrict-prototypes -Wmissing-prototypes -fno-strict-aliasing -mips32 -isystem /home/dext3r/trunk/build_mipsel/linux/include  -fno-pic -mno-abicalls -mlong-calls   -c -o spi.o spi.c
/home/dext3r/trunk/staging_dir/toolchain-mipsel_gcc3.4.6/lib/gcc/mipsel-linux-uclibc/3.4.6/../../../../mipsel-linux-uclibc/sys-include/linux/devfs_fs_kernel.h:143: warning: unused parameter 'de'
/home/dext3r/trunk/staging_dir/toolchain-mipsel_gcc3.4.6/lib/gcc/mipsel-linux-uclibc/3.4.6/../../../../mipsel-linux-uclibc/sys-include/linux/devfs_fs_kernel.h:153: warning: unused parameter 'dir'
/home/dext3r/trunk/staging_dir/toolchain-mipsel_gcc3.4.6/lib/gcc/mipsel-linux-uclibc/3.4.6/../../../../mipsel-linux-uclibc/sys-include/linux/devfs_fs_kernel.h:154: warning: unused parameter 'name'
/home/dext3r/trunk/staging_dir/toolchain-mipsel_gcc3.4.6/lib/gcc/mipsel-linux-uclibc/3.4.6/../../../../mipsel-linux-uclibc/sys-include/linux/devfs_fs_kernel.h:154: warning: unused parameter 'info'
/home/dext3r/trunk/staging_dir/toolchain-mipsel_gcc3.4.6/lib/gcc/mipsel-linux-uclibc/3.4.6/../../../../mipsel-linux-uclibc/sys-include/linux/devfs_fs_kernel.h:133: warning: unused parameter 'dir'
/home/dext3r/trunk/staging_dir/toolchain-mipsel_gcc3.4.6/lib/gcc/mipsel-linux-uclibc/3.4.6/../../../../mipsel-linux-uclibc/sys-include/linux/devfs_fs_kernel.h:134: warning: unused parameter 'name'
/home/dext3r/trunk/staging_dir/toolchain-mipsel_gcc3.4.6/lib/gcc/mipsel-linux-uclibc/3.4.6/../../../../mipsel-linux-uclibc/sys-include/linux/devfs_fs_kernel.h:135: warning: unused parameter 'flags'
/home/dext3r/trunk/staging_dir/toolchain-mipsel_gcc3.4.6/lib/gcc/mipsel-linux-uclibc/3.4.6/../../../../mipsel-linux-uclibc/sys-include/linux/devfs_fs_kernel.h:136: warning: unused parameter 'major'
/home/dext3r/trunk/staging_dir/toolchain-mipsel_gcc3.4.6/lib/gcc/mipsel-linux-uclibc/3.4.6/../../../../mipsel-linux-uclibc/sys-include/linux/devfs_fs_kernel.h:137: warning: unused parameter 'minor'
/home/dext3r/trunk/staging_dir/toolchain-mipsel_gcc3.4.6/lib/gcc/mipsel-linux-uclibc/3.4.6/../../../../mipsel-linux-uclibc/sys-include/linux/devfs_fs_kernel.h:138: warning: unused parameter 'mode'
/home/dext3r/trunk/staging_dir/toolchain-mipsel_gcc3.4.6/lib/gcc/mipsel-linux-uclibc/3.4.6/../../../../mipsel-linux-uclibc/sys-include/linux/devfs_fs_kernel.h:139: warning: unused parameter 'ops'
/home/dext3r/trunk/staging_dir/toolchain-mipsel_gcc3.4.6/lib/gcc/mipsel-linux-uclibc/3.4.6/../../../../mipsel-linux-uclibc/sys-include/linux/devfs_fs_kernel.h:139: warning: unused parameter 'info'

lsmod on the router

root@OpenWrt:~# lsmod
Module                  Size  Used by    Tainted: P  
spi                     1548   0 (unused)
wlcompat               14944   0 (unused)
ip_conntrack_tftp       1712   0 (unused)
ip_nat_irc              2336   0 (unused)
ip_conntrack_irc        3128   1
ip_nat_ftp              2960   0 (unused)
ip_conntrack_ftp        4272   1
ppp_async               7884   0 (unused)
ppp_generic            22300   0 [ppp_async]
slhc                    6064   0 [ppp_generic]
wl                    630776   0 (unused)
switch-robo             4540   0 (unused)
switch-core             4864   0 [switch-robo]
diag                   25520   0 (unused)

dmesg

root@OpenWrt:~# dmesg
CPU revision is: 00029008
Primary instruction cache 16kB, physically tagged, 2-way, linesize 16 bytes.
Primary data cache 8kB, 2-way, linesize 16 bytes.
Linux version 2.4.34 (nbd@ds10) (gcc version 3.4.6 (OpenWrt-2.0)) #3 Sun Sep 30 20:33:21 CEST 2007
Setting the PFC to its default value
Determined physical RAM map:
 memory: 01000000 @ 00000000 (usable)
On node 0 totalpages: 4096
zone(0): 4096 pages.
zone(1): 0 pages.
zone(2): 0 pages.
Kernel command line: root=/dev/mtdblock2 rootfstype=squashfs,jffs2 init=/etc/preinit noinitrd console=ttyS0,115200
CPU: BCM5352 rev 0 at 200 MHz
Using 100.000 MHz high precision timer.
Calibrating delay loop... 199.47 BogoMIPS
Memory: 14224k/16384k available (1462k kernel code, 2160k reserved, 100k data, 80k init, 0k highmem)
Dentry cache hash table entries: 2048 (order: 2, 16384 bytes)
Inode cache hash table entries: 1024 (order: 1, 8192 bytes)
Mount cache hash table entries: 512 (order: 0, 4096 bytes)
Buffer cache hash table entries: 1024 (order: 0, 4096 bytes)
Page-cache hash table entries: 4096 (order: 2, 16384 bytes)
Checking for 'wait' instruction...  unavailable.
POSIX conformance testing by UNIFIX
PCI: no core
PCI: Fixing up bus 0
Linux NET4.0 for Linux 2.4
Based upon Swansea University Computer Society NET3.039
Initializing RT netlink socket
Starting kswapd
Registering mini_fo version $Id$
devfs: v1.12c (20020818) Richard Gooch (rgooch@atnf.csiro.au)
devfs: boot_options: 0x1
JFFS2 version 2.1. (C) 2001 Red Hat, Inc., designed by Axis Communications AB.
squashfs: version 3.0 (2006/03/15) Phillip Lougher
pty: 256 Unix98 ptys configured
Serial driver version 5.05c (2001-07-08) with MANY_PORTS SHARE_IRQ SERIAL_PCI enabled
ttyS00 at 0xb8000300 (irq = 3) is a 16550A
ttyS01 at 0xb8000400 (irq = 3) is a 16550A
b44.c:v0.93 (Mar, 2004)
PCI: Setting latency timer of device 00:01.0 to 64
eth0: Broadcom 47xx 10/100BaseT Ethernet 00:16:01:d2:5e:76
Physically mapped flash: Found an alias at 0x400000 for the chip at 0x0
Physically mapped flash: Found an alias at 0x800000 for the chip at 0x0
Physically mapped flash: Found an alias at 0xc00000 for the chip at 0x0
Physically mapped flash: Found an alias at 0x1000000 for the chip at 0x0
Physically mapped flash: Found an alias at 0x1400000 for the chip at 0x0
Physically mapped flash: Found an alias at 0x1800000 for the chip at 0x0
Physically mapped flash: Found an alias at 0x1c00000 for the chip at 0x0
 Amd/Fujitsu Extended Query Table v1.3 at 0x0040
number of CFI chips: 1
cfi_cmdset_0002: Disabling fast programming due to code brokenness.
Flash device: 0x400000 at 0x1c000000
bootloader size: 262144
Physically mapped flash: Filesystem type: squashfs, size=0x121cc8
Creating 5 MTD partitions on "Physically mapped flash":
0x00000000-0x00040000 : "cfe"
0x00040000-0x003f0000 : "linux"
0x000be400-0x001f0000 : "rootfs"
mtd: partition "rootfs" doesn't start on an erase block boundary -- force read-only
0x003f0000-0x00400000 : "nvram"
0x001f0000-0x003f0000 : "rootfs_data"
sflash: found no supported devices
Initializing Cryptographic API
NET4: Linux TCP/IP 1.0 for NET4.0
IP Protocols: ICMP, UDP, TCP, IGMP
IP: routing cache hash table of 512 buckets, 4Kbytes
TCP: Hash tables configured (established 1024 bind 2048)
ip_conntrack version 2.1 (5953 buckets, 5953 max) - 360 bytes per conntrack
ip_tables: (C) 2000-2002 Netfilter core team
NET4: Unix domain sockets 1.0/SMP for Linux NET4.0.
NET4: Ethernet Bridge 008 for NET4.0
802.1Q VLAN Support v1.8 Ben Greear <greearb@candelatech.com>
All bugs added by David S. Miller <davem@redhat.com>
VFS: Mounted root (squashfs filesystem) readonly.
Mounted devfs on /dev
Freeing unused kernel memory: 80k freed
Algorithmics/MIPS FPU Emulator v1.5
diag: Detected 'Buffalo WHR-HP-G54'
b44: eth0: Link is up at 100 Mbps, full duplex.
b44: eth0: Flow control is off for TX and off for RX.
Probing device eth0: found!
mini_fo: using base directory: /
mini_fo: using storage directory: /jffs
jffs2.bbc: SIZE compression mode activated.
b44: eth0: Link is up at 100 Mbps, full duplex.
b44: eth0: Flow control is off for TX and off for RX.
BFL_ENETADM not set in boardflags. Use force=1 to ignore.
device eth0.0 entered promiscuous mode
eth0.0: dev_set_promiscuity(master, 1)
device eth0 entered promiscuous mode
br-lan: port 1(eth0.0) entering learning state
br-lan: port 1(eth0.0) entering forwarding state
br-lan: topology change detected, propagating
eth0.1: add 01:00:5e:00:00:01 mcast address to master interface
PCI: Setting latency timer of device 00:05.0 to 64
wl0: Broadcom BCM4318 802.11 Wireless Controller 4.80.53.0
CSLIP: code copyright 1989 Regents of the University of California
PPP generic driver version 2.4.2
spi Hardware init
spi port init

Also, running the spitest program turns on my GPIO 7, which is correct in the code. so its just not creating /dev/spi/0 properly. do i need to compile it differently?

any ideas?
thanks!

(Last edited by dext3r on 29 Jan 2008, 19:42)

The discussion might have continued from here.