Enabling SPI in mini2440

Neo
Hi,

I am trying to enable the SPI interface in mini2440 board. I followed the
link http://members.cox.net/ebrombaugh1/embedded/mini2440/index.html and
made changes to my board file accordingly. Now I am trying to connect a
GPIO expander via SPI. It is not working. When I insert the module, nothing
happens. (I can't even see the print messages that I inserted in the probe
function). So, I checked the SPICLK0 pin. It doesn't seem to be active. It
always stays low. 
1) Should I enable the SPI clock to make it work? If so, which will be the
best place to do it? 

2) I did a few changes in the file (arch/arm/plat-s3c24xx/s3c2410-clock.c).
I moved the clock structure of SPI from init_clocks_disable and to
init_clocks. What else should I do to enable the clock?

GPIO expander : MAX7301 from Maxim semiconductor 
Kernel module :  max7301.c (in location drivers/gpio/)

open-nandra
Do similar and it work fine: Check this:
http://open-nandra.com/2010/09/friendly-arm-2440-and-sca3000-accelerometer/

marek

Neo
Thanks for the link. I followed it and somehow initialized the max7301
driver. But the device doesn't seem to be working. When I checked the
SPICLK0 it always stays low. What should I do to enable the SPICLOCK. In
which file I should add it?

open-nandra
Could you please post you changes in kernel to check?

Neo
These are the changes,
In file mach-mini2440.c

//
static void mini2440_spi0_cs(struct s3c2410_spi_info *spi, int cs, int pol)
{
    s3c2410_gpio_setpin(S3C2410_GPG(2), pol);
}

static struct s3c2410_spi_info mini2440_spi0_platdata = {
    .num_cs = 1,
    .bus_num = 0,
    .set_cs = mini2440_spi0_cs,
};

static struct max7301_platform_data max7301_info = {
  .base = -1,
};

/* bus_num must match id in pxa2xx_set_spi_info() call */
static struct spi_board_info mini2440_spi_board_info[] __initdata = {
  {
    .modalias  = "max7301",
    .platform_data  = &max7301_info,
    .max_speed_hz  = 13000000,
    .bus_num  = 0,
    .chip_select  = 0,
    .mode    = SPI_MODE_0,
  },
};

In platform_device structure I added this line to enable the SPI device,
  &s3c_device_spi0,

And in the static void __init mini2440_machine_init(void)
  
  /* setup SPI0 pins */
  s3c2410_gpio_cfgpin(S3C2410_GPE(11), S3C2410_GPE11_SPIMISO0);
  s3c2410_gpio_cfgpin(S3C2410_GPE(12), S3C2410_GPE12_SPIMOSI0);
  s3c2410_gpio_cfgpin(S3C2410_GPE(13), S3C2410_GPE13_SPICLK0);
  s3c2410_gpio_cfgpin(S3C2410_GPG(2), S3C2410_GPIO_OUTPUT);
        s3c_device_spi0.dev.platform_data = &mini2440_spi0_platdata;
  spi_register_board_info(mini2440_spi_board_info,
    ARRAY_SIZE(mini2440_spi_board_info));
  printk(KERN_ERR "Setup SPI0\n");


Please let me know If I have missed something.

-
Neo

open-nandra
Attachment: 0001-Add-max7301-spi-driver (2.72 KB)
Your code doesn't work? Seems good.
Try patch in attachment. Don't have HW to test. It's just compile tested.
If it wouldn't work will look next week ;).

marek

Neo
Thanks for the patch. Will test with this. Hoping to solve it this week at
least. Also I would like to try with the bit banging driver. If you have
any idea on how to use that in mini2440, Please let me know.

-
Neo

linuxNewbie
Hello, 
I would like to use a GPIO expander max 7301.
I have made the modifications that are described above, compiled and
downloaded the new kernel on my target, but i don't know what to do after
that. 

I would like to write a simple application to toggle  a led connected on a
pin of my max7301.

Thanks for your kindness, i'm completely newbie...

Domodom
Hello, 

To add more GPIOs on the mini2440, i would like to use 2 max7301.
I started with only one max7301, it works well.

Now, i would like to add a second max7301, but i'm a bit confused : if i
have well understood, the mini2440_spi_board_info table contains the
definition of each SPI slave connected on the bus. Then i only have to add
a new element in this table.

But where can i define the pin number used for the chip select of the
second component ? For the first one, it is in the mini2440_spi0_platdata
structure, thanks to a pointer on the mini2440_spi0_cs() function that
drives the output, but i don't see where to define the chip select of the
second SPI slave...

I would be happy if someone takes the time to answer me.

domodom

open-nandra
NO you need to do similar for second slave mac7301 chip as here:
http://friendlyarm.net/forum/attachment/11539

You need add specific struct same as for mini2440_spi0_pdata. Then extend
mini2440_spi_devs for your next device and register platform data.

Lemme know if it works.

marek

Domodom
Hello Marek, 
Thank you very much for your answer. 
Just to be sure to well understand you, are you suggesting to do that ?
(it's a test i made with spidev, but i think it's the same as with mx7301
): 

// First SPI slave
static struct s3c2410_spi_info mini2440_spi0_platdata = {
    .num_cs = 1,
    .bus_num = 0,
    .pin_cs = S3C2410_GPG(2),
    .gpio_setup = &s3c24xx_spi_gpiocfg_bus0_gpe11_12_13,
};
static struct spi_board_info mini2440_spi_board_info[] __initdata = {
  {
    .modalias  = "spidev",
    .max_speed_hz  = 13000000,
    .bus_num  = 0,
    .chip_select  = 0,
    .mode    = SPI_MODE_0,
  },
};
// Second SPI slave
static struct s3c2410_spi_info mini2440_spi0_platdata2 = {
    .num_cs = 1,
    .bus_num = 0,
    .pin_cs = S3C2410_GPG(0),
    .gpio_setup = &s3c24xx_spi_gpiocfg_bus0_gpe11_12_13,
};
static struct spi_board_info mini2440_spi_board_info2[] __initdata = {
  {
    .modalias  = "spidev",
    .max_speed_hz  = 13000000,
    .bus_num  = 1,
    .chip_select  = 0,
    .mode    = SPI_MODE_0,
  },
};

In platform_device structure, there are 2 lines : 
  &s3c_device_spi0,
  &s3c_device_spi1,

And in the static void __init mini2440_machine_init(void)

  /* setup SPI0 pins */
  s3c2410_gpio_cfgpin(S3C2410_GPE(11), S3C2410_GPE11_SPIMISO0);
  s3c2410_gpio_cfgpin(S3C2410_GPE(12), S3C2410_GPE12_SPIMOSI0);
  s3c2410_gpio_cfgpin(S3C2410_GPE(13), S3C2410_GPE13_SPICLK0);
  // first SPI driver instance
  s3c2410_gpio_cfgpin(S3C2410_GPG(2), S3C2410_GPIO_OUTPUT);
  s3c_device_spi0.dev.platform_data = &mini2440_spi0_platdata;
  spi_register_board_info(mini2440_spi_board_info,
ARRAY_SIZE(mini2440_spi_board_info));
  // Second SPI driver instance
  s3c2410_gpio_cfgpin(S3C2410_GPG(0), S3C2410_GPIO_OUTPUT);
  s3c_device_spi0.dev.platform_data = &mini2440_spi0_platdata2;
  spi_register_board_info(mini2440_spi_board_info2,
ARRAY_SIZE(mini2440_spi_board_info2));


The idea is to declare 2 SPI drivers with a SPI slave for each one.
The ls /dev command returns :
spidev0.0
spidev0.1

What i wanted to do was to have spidev0.0 and spidev0.1. It's possible with
the following code : 
static struct s3c2410_spi_info mini2440_spi0_platdata = {
    .num_cs = 2,
    .bus_num = 0,
    .pin_cs = S3C2410_GPG(2),
    .gpio_setup = &s3c24xx_spi_gpiocfg_bus0_gpe11_12_13,
};
static struct spi_board_info mini2440_spi_board_info[] __initdata = {
  {
    .modalias  = "spidev",
    .max_speed_hz  = 13000000,
    .bus_num  = 0,
    .chip_select  = 0,
    .mode    = SPI_MODE_0,
  },
  {
    .modalias  = "spidev",
    .max_speed_hz  = 13000000,
    .bus_num  = 0,
    .chip_select  = 1,
    .mode    = SPI_MODE_0,
  },
};
The rest stay the same as in the post of Neo.
With this configuration, the command ls /dev returns : 
spidev0.0
spidev0.1

It should be possible, BUT in this configuration, i have the same
Chip_select for the both SPI slaves !! I don't understand why it is not
possible to have this configuration...

Whatever, i will use your solution. 
If i not abuse, a last question : with 2 drivers declared for the same
physical bus, what mecanism prevents 2 threads to access the bus at the
same time ?

Thanks you very much for your help
domodom

domodom
I have found a solution !
In the mini2440_spi0_platdata structure, there are 2 ways to declare the
chip_select : 
- the new one, with pin_cs, that is the pin number of the chip_select
signal.
- the old one, with the set_cs parameter, that is a pointer on a function
called each time the chip_select state must be changed.

With the new way, there is no possibility to declare several chip_select
signals.
But with the old one, it is possible to write a function that drives the
good chip_select.

The, the source code is : 

static void mini2440_spi0_cs(struct s3c2410_spi_info *spi, int cs, int pol)
{
    switch(cs):
        case 0: 
            s3c2410_gpio_setpin(S3C2410_GPF(0), pol);
        break;
        case 1: 
            s3c2410_gpio_setpin(S3C2410_GPF(3), pol);
        break;
}

static struct s3c2410_spi_info mini2440_spi0_platdata = {
    .num_cs = 2,  // = the number of SPI devices declared in
mini2440_spi_board_info
    .bus_num = 0,
    .set_cs = mini2440_spi0_cs,
    .gpio_setup = &s3c24xx_spi_gpiocfg_bus0_gpe11_12_13,
};
static struct spi_board_info mini2440_spi_board_info[] __initdata = {
  {
    .modalias  = "spidev",
    .max_speed_hz  = 13000000,
    .bus_num  = 0,
    .chip_select  = 0,      // = the number passed to the mini2440_spi0_cs
function
    .mode    = SPI_MODE_0,
  },
  {
    .modalias  = "spidev",
    .max_speed_hz  = 13000000,
    .bus_num  = 0,
    .chip_select  = 1,
    .mode    = SPI_MODE_0,
  },
};

Best regards
domodom

Meher
Is it possible to connect a PIC as a slave to mini2440 over SPI.

davef
My guess is that it would be possible.  One issue is how much time it will
take.  Have you any kernel driver experience?

I took a different route, after trying to do something similar, and that
was to control a ATmega32U4 via USB.  

See Teensy and Adafruit for dev boards and software.

Also the Odroid platforms have a add-on board using a PIC

Meher
No davef, I don't have a kernel driver experience. 
I need to connect a PIC micro to mini2440 over SPI. can you pls guide me?
Is there any step by step approach what exactly has to be done to enable
SPI from mini24440 and how? In my case, mini will work as the master. 
Thanks in advance

davef
Meher,

Read through this thread

http://www.friendlyarm.net/forum/topic/4801

I think it summarises my SPI experience.  This should get the mini2440
enabled as a SPI master.

I know there are a few steps to set up the AVR ATmega series as a SPI slave
so you would have to work out how to do that on the PIC devices.

Good luck.

Meher
Hi
 To start with, I am trying to have a kernel experience with the "Hello
Module" as described in mini2440 manual. But I am stuck at "make
menuconfig" in the linux-2.6.32.2 directory, as I'm not able to change the
driver option from "[]" to "<M>". It only takes "[]" and "[*]". 
can anybody help?

Meher
davef
in your note for enabling SPI 
 
"In the BSP go to:

platform-mini2440/build-target/

and make a copy of linux-3.1 and call it linux-3.1.orig."

where is this located?

 I could find linux-2.6.32.2.

davef
There should be a folder called Linux 3.1

Appears to me that you are not looking in the installed Pengutronix
mini2440 BSP.  If you are, what version of the BSP have you installed?

In the latest mini2440 BSP there should be much more recent Linux versions
in that folder.

Meher
where to see for the BSP version?

Meher
My board has come with preloaded linux.

davef
Well the pre-loaded linux will not have SPI enabled.

You can either start with your existing kernel version and get setup for
cross-compilation on a host computer and try with 2.6.32.2

or

if you haven't done any cross-compilation yet go to the Pengutronix webpage
and look for instructions on getting setup using their BSP.

And then you will find 3.1 and much later versions as well.

Meher
Thanks davef

can you please guide me what exactly I have to do  for the Pengutronix BSP.

for your information, I have extracted the linux tar file supplied with CD.
and there is a /Bootstrap-v1.11/linux-2.6.32.2/drivers/spi/spi_s3c24xx.c
file. Is this the SPI driver?

davef
I think you found it, now all you have to do is hack it.

There are some other SPI examples around.  Try searching for <buserror SPI>
and <eric bromaugh spi mini2440> 


Pengutronix ... download the QuickStart.pdf guide and download the latest
toolchain, PTXdist and mini2440BSP versions and have a go.

davef
I should have said, download the toolchain and PTXdist recommended in the
latest QuickStart guide and the latest mini2440BSP

davef
Sorry, I got that wrong.  That may the SPI driver file, but the two files
that need modifying are in my document:

Enabling SPI in the Pengutronix kernel version 3.1

Did you get a copy of that?

Meher
Yes I got that doc, As I got confused of linux 3.1 and pengutronix BSP, I
asked you about that. 

So can I do the same changes to this file as well and do the same procedure
to compile the existing kernel?

davef
You could try.

First I would do a diff on the files in question both in 3.1 and 2.6.32.2
and if the are the same maybe you will get lucky.

Meher
Hello Davef

whatever "/Bootstrap-v1.11/linux-2.6.32.2/drivers/spi/spi_s3c24xx.c" file I
had in linux folder, I have modified according to the instruction in your
"Enabling SPI in the Pengutronix kernel version 3.1" document and saved it.
But while doing "make", under the linux directory, I get the following
error. 
What is this error? can you please suggest solution?

CHK     include/linux/version.h
make[1]: `include/asm-arm/mach-types.h' is up to date.
  CHK     include/linux/utsrelease.h
  SYMLINK include/asm -> include/asm-arm
  CALL    scripts/checksyscalls.sh
  CHK     include/linux/compile.h
  CC [M]  drivers/message/fusion/mptscsih.o
  CC [M]  drivers/message/fusion/mptspi.o
  CC [M]  drivers/message/fusion/mptfc.o
  CC [M]  drivers/message/fusion/mptsas.o
  CC [M]  drivers/message/fusion/mptctl.o
  CC [M]  drivers/message/fusion/mptlan.o
  CC [M]  drivers/message/i2o/bus-osm.o
  CC [M]  drivers/message/i2o/config-osm.o
  CC [M]  drivers/message/i2o/iop.o
  CC [M]  drivers/message/i2o/driver.o
  CC [M]  drivers/message/i2o/device.o
  CC [M]  drivers/message/i2o/debug.o
  CC [M]  drivers/message/i2o/pci.o
  CC [M]  drivers/message/i2o/exec-osm.o
  CC [M]  drivers/message/i2o/memory.o
  LD [M]  drivers/message/i2o/i2o_core.o
  LD [M]  drivers/message/i2o/i2o_config.o
  LD [M]  drivers/message/i2o/i2o_bus.o
  CC [M]  drivers/message/i2o/i2o_block.o
  CC [M]  drivers/message/i2o/i2o_scsi.o
  CC [M]  drivers/message/i2o/i2o_proc.o
  CC      drivers/mfd/ezx-pcap.o
drivers/mfd/ezx-pcap.c: In function 'pcap_isr_work':
drivers/mfd/ezx-pcap.c:213: error: implicit declaration of function
'irq_to_gpio'
make[2]: *** [drivers/mfd/ezx-pcap.o] Error 1
make[1]: *** [drivers/mfd] Error 2
make: *** [drivers] Error 2

By the way, I have downloaded the Pengutronix ptxdist and OSELAS toolchain
and installed it my PC. But before proceeding further, I just wanted to
check if it works with the existing kernel. 
Please reply.

davef
Just guessing here ... what is ezx-pcap?  Have you enabled something else
in the provided kernel?

I tried searching ezx-cap and it doesn't help much.  I first thought it
might have something to do with Wireshark or WinPcap or the Linux version
of packet capture.

> implicit declaration of function

is telling you that some .h file is not available to the compiler.  Look
for a ezx-pcap.h file.  Is it there?

davef
http://mirrors.neusoft.edu.cn/rpi-kernel/drivers/mfd/ezx-pcap.c

 Driver for Motorola PCAP2 as present in EZX phones

Huh???

Meher
Thanks for your reply, 

I am trying to make zImage, it gives the following error.
 LD      arch/arm/mach-s3c2400/built-in.o
  LD      arch/arm/mach-s3c2412/built-in.o
  CC      arch/arm/mach-s3c2440/s3c2440.o
  CC      arch/arm/mach-s3c2440/dsc.o
  CC      arch/arm/mach-s3c2440/irq.o
  CC      arch/arm/mach-s3c2440/clock.o
  CC      arch/arm/mach-s3c2440/mach-mini2440.o
arch/arm/mach-s3c2440/mach-mini2440.c:79: error: 's3c2410_GPG2' undeclared
here (not in a function)
arch/arm/mach-s3c2440/mach-mini2440.c:82: error:
's3c24XX_spi_gpiocfg_bus0_gpe11_12_13' undeclared here (not in a function)
arch/arm/mach-s3c2440/mach-mini2440.c:87: error: field name not in record
or union initializer
arch/arm/mach-s3c2440/mach-mini2440.c:87: error: (near initialization for
'mini2440_spi_devs')
arch/arm/mach-s3c2440/mach-mini2440.c:87: warning: missing braces around
initializer
arch/arm/mach-s3c2440/mach-mini2440.c:87: warning: (near initialization for
'mini2440_spi_devs[0]')
arch/arm/mach-s3c2440/mach-mini2440.c:88: error: field name not in record
or union initializer
arch/arm/mach-s3c2440/mach-mini2440.c:88: error: (near initialization for
'mini2440_spi_devs')
arch/arm/mach-s3c2440/mach-mini2440.c:89: error: field name not in record
or union initializer
arch/arm/mach-s3c2440/mach-mini2440.c:89: error: (near initialization for
'mini2440_spi_devs')
arch/arm/mach-s3c2440/mach-mini2440.c:89: warning: large integer implicitly
truncated to unsigned type
arch/arm/mach-s3c2440/mach-mini2440.c:90: error: field name not in record
or union initializer
arch/arm/mach-s3c2440/mach-mini2440.c:90: error: (near initialization for
'mini2440_spi_devs')
arch/arm/mach-s3c2440/mach-mini2440.c: In function 'mini2440_machine_init':
arch/arm/mach-s3c2440/mach-mini2440.c:516: error: implicit declaration of
function 'Array_SIZE'
make[1]: *** [arch/arm/mach-s3c2440/mach-mini2440.o] Error 1
make: *** [arch/arm/mach-s3c2440] Error 2

what is the error?

davef
How did you fix the previous error?

Just guessing again ... either there is some major difference between the
kernel versions of mach-mini2440.c or you have not modified it correctly.

Or some .h file needs modifying.

Checking my document I see a last step:
*****
From platform-mini2440/build-target/ run:

diff -urB linux-3.1.orig linux-3.1 > enable-spidev.diff

Manually added header information, changed the number of files changed and
the number of insertions.  (There must be an option in diff for this!)
*****

Suggests to me that you may only succeed when you use the Pengutronix BSP
... with this document.

Meher
As described in the attached video for linux-2.6.32.2(Please see that) I
have done accordingly. But at the last step while making zImage, the error
comes. 

https://www.youtube.com/watch?v=OzrxEIAHdxo

davef
Watched the video.

First thing to understand that he is enabling GPIO and (I think) SPI for
the userspace.  My document is for enabling SPI in kernel space.

So, focusing on the video and your error ... always sort out the first
error.

>  's3c2410_GPG2' undeclared here (not in a function)

This tells you that either the mach-mini2440.c is not including the
mach-mini2440.h, the mach-mini2440.h file is not present (usually in the
same directory) as the mach-mini2440.c (can you find that?) OR there is an
error in the mach-mini2440.h file, ie there is no mention of s3c2410_GPG2.

What do you find?

Meher
Attachment: mach-mini2440.c (12.77 KB)
The attached file is the one which I have modified according to your doc
and presently using. there is no s3c2410_GPG2.and mach-mini2440.h.

Meher
Attachment: mach-mini2440.c (13.17 KB)
hello davef
I have included the 'ezx-pcap.h' file in the same directory where the 
ezx-pcap.c file belongs i.e.
'/home/mou/Downloads/linux-2.6.32.2/drivers/mfd' but still get the error
while making zImage. 

  CC      drivers/mfd/mfd-core.o
  CC      drivers/mfd/ezx-pcap.o
drivers/mfd/ezx-pcap.c:21:28: error: linux/gpio-pxa.h: No such file or
directory
drivers/mfd/ezx-pcap.c: In function 'pcap_isr_work':
drivers/mfd/ezx-pcap.c:214: error: implicit declaration of function
'irq_to_gpio'
make[2]: *** [drivers/mfd/ezx-pcap.o] Error 1
make[1]: *** [drivers/mfd] Error 2
make: *** [drivers] Error 2


and the follwing error while 'make' under the linux 2.6.32.2  directory.

drivers/input/touchscreen/eeti_ts.c: In function 'eeti_ts_irq_active':
drivers/input/touchscreen/eeti_ts.c:64: error: implicit declaration of
function 'irq_to_gpio'
make[3]: *** [drivers/input/touchscreen/eeti_ts.o] Error 1
make[2]: *** [drivers/input/touchscreen] Error 2
make[1]: *** [drivers/input] Error 2
make: *** [drivers] Error 2

Please suggest.............I'm just stuck here
 Also attached is the new 'mach-mini2440.c' file I have downloaded . kindly
have a look. Is it the correct file to get through with SPI?

davef
Meher,

Something has gone wrong with our communications. I am sure I replied to
your posting of 2015-05-22.  Let's try again.

The problem with
's3c2410_GPG2' undeclared here (not in a function)

I think a typo might have creep into my document, ie s3c2410_GPG2 became
S3C2410_GPG2.  

s3c2410_GPG2 has to be declared somewhere in an included file.  You are
right, there is no mach-mini2440.h.

For your most problem there are still missing files.