SPI with Pengutronix BSP??

Hello Juergen,

I am using mini2440 board with Pengutronics BSP with following version.

I install kernel and filesystem successfully, but I am not getting SPI
device register under /dev directory.

Is there any way to enable SPI in BSP? or latest BSP support SPI
automatically without any patch?

How can I use SPI device from C program?

Look forward to hear from you soon.

Juergen Beisert
Support for SPI is a generic part of the kernel. But what's missing is the
registration of the SPI master driver and the attached devices in the
Mini2440's platform file.
Grep for "s3c2410-spi" in the "arch/arm" and "drivers/spi" to get an idea
what has to be added to the "arch/arm/mach-s3c24xx/mach-mini2440.c" to get
SPI work and some of the docs in "Documentation/spi"

> Is there any way to enable SPI in BSP?

You could enable the SPI master driver in the kernel, but until someone
registers the corresponding devices at run-time nothing will happen.

So, you need to add more patches to the existing kernel's patch stack to
modify "arch/arm/mach-s3c24xx/mach-mini2440.c" in a way you need it.

> or latest BSP support SPI automatically without any patch?

No, sorry.

> How can I use SPI device from C program?

Sure. Most SPI device drivers provide their features/functions via entries
in the sysfs or some via device nodes in dev/

Happy hacking


Thanks for the prompt reply. I will do modification and let you know.

/* SPI devices */
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,

//Suresh Added

/* 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;
  // Second SPI driver instance
  s3c2410_gpio_cfgpin(S3C2410_GPG(0), S3C2410_GPIO_OUTPUT);
  s3c_device_spi0.dev.platform_data = &mini2440_spi0_platdata2;

I have added following code in mach-mini2440.c and compile the kernel,
however after kernel boot, nothing appear on /dev device. I suppose to get
/dec/spidev*, but nothing happen.

I am using Pengutronicx kernel. Am I missing something here...?


I have made a patch for the Pengutronix BSP for SPI.  I will dig the
information out tomorrow.

Good night.

Dave Festing
Attached is a Word doc renamed to .zip, just rename it back to .doc

Dave Festing
Attachment: enable_spi.diff (2.45 KB)
Here is the patch

Dave Festing
Attachment: series (1.55 KB)
And at the end of series files add . . .

# enable spidev

I use a commonly available program called spidev_test to verify that things
are working.

Good luck.


Thanks for sharing patch. I will get back to you once I will check it.

Thank you for your time and consideration.


Hi Dave 
I have downloaded latest Pengutonix kernel for mini2440 can you please give
me steps for patching to latest kernel manually.

Dave Festing
Rename to .doc

The part you want is after:

and in Kconfig 

down to:

. . . and save it.

That should be the same as everything that has a + in the patch file.

Hello Dave Festing,

I'm using OSELAS.BSP-Pengutronix-Mini2440-2012.06.0
I'm just trying to modify linux-3.4 in order to activate the SPI and I can
see that


does not contain mach-mini2440.c and Kconfig with the lines under which I
have to add the modification for the SPI.

But I can find them in

And I think I should modify this files? Yes or No?

Also there are some differences between .DOC and .diff files.

.DOC                                 .diff
.pin_cs = S3C2410_GPG2,              .pin_cs = S3C2410_GPG(2),
.max_speed_hz = 48 * 1000 * 1000,    .max_speed_hz = 1000000,
                                     .mode = SPI_MODE_0,

Which one should I use?

Thank in advance for your cooperation. ;)

Also can I use SPI.h from David Brownell


Or should I create one specially for mini2440?

What about this drivers?



Just got to work and saw these emails from you.  All my Linux gear is at

Sounds like things have changed between 3.1 and 3.4  I think this is where
the experts say, "welcome to the world of up-grading to newer kernel

I would have to have a close look myself and then probably ask some
questions, ie why the changes?

The links you supplied look like they are for some quite old kernel

I would save the original file and then just try modifying it a step at a

I don't understand your comment:
> does not contain mach-mini2440.c and Kconfig

You can't find Kconfig?

Is the ".DOC" file my document file?  What is this .diff file?  The changes
don't look important to me, but then again I am no expert!

Juergen Beisert
"/arch/arm/mach_s3c2440 -> /arch/arm/mach_s3c24xx"

Yes. Currently many things happen in the ARM part of the kernel. Everyone
is working on the goal to also be able to boot *one* binary kernel on
different platforms (like it works at x86). So, the files are moved and
deleted to reduce the file count. Later on, the platform files will be
removed entirely and replaces by generic files, where the so called "device
tree" describes the system.

What is your problem with the SPI driver for the S3C2440 SoC? The SPI
master driver you need is already present in the kernel, since years (refer
"drivers/spi/spi-s3c24xx.c" in the kernel). You just have to enable it and
register it at run-time in the platform file like Dave already mentioned.
And then you have to register your devices which are connected to this SPI
bus, to be able to access them. And now I can't help, because I don't know
what you intend to do and to attach to your SPI bus.

Read the files in "Documentation/spi" for further help how to do so.

davef I think I'm using your .doc file. You are also Dave Festing, right?

and .diff file I think is your patch file. 

And if you open and compare both files you will see that there are some
differences as I mentioned in my previous post and here they are:

Enable.. .DOC                             enable_spi.diff
.pin_cs = S3C2410_GPG2,                  .pin_cs = S3C2410_GPG(2),
.max_speed_hz = 48 * 1000 * 1000,        .max_speed_hz = 1000000,
                                         .mode = SPI_MODE_0,

As Juergen already explained everything is moved to s3c24xx folder and the
KConfig differ in both folders. But I took the s3c24xx folder and I'm
working with it.

Juergen Belsert,

Thank you for your clarification. :)

I read the Documentation/spi and right now I'm learning how to do all of
this. :)

Concerning the instruction of Dave Festing

The only think that I didn't understand is should I write my own spi.h file
or should I use a generic one and from where I can download one?
Google don't have answer for this question. :)

Also when I try to compile it, ptxdist throw me an error for missing
mach/spi.h and linux/spi/spi.h files, which I think is normal because there
are no spi.h file in both locations

Should I change this two lines to something else or to place a copy of
spi.h file in this locations?

I never touched any spi.h file.

I'll check why the .doc and .diff files are different.  I would go with the
.diff file, perhaps I didn't update something in the .doc file.

I can find linux/spi/spi.h in 3.7 but no mach/spi.h ??

Is there any difference between mach/spi.h and linux/spi/spi.h files or it
is the same file?

Juergen Beisert
> Is there any difference between mach/spi.h and linux/spi/spi.h
> files or it is the same file?

Maybe you should simply read and compare these files to answer yourself?
Sorry, if you want to program inside the kernel you should read more doc
and try by yourself prior asking such questions.
And you should think about software layering (generic part -> architecture
specific part -> board specific part).

Well that is why I'm asking. I'm missing the mach/spi.h and I wanted to
know if I can simply copy/paste it from linux/spi/spi.h or I should create
a new mach/spi.h file specifically for my device?


As always you are helpful but as always you are as Microsoft Help file. :)

So correct and yet so incomprehensible. :)

And the sad part is the lack of knowledge of the users of Pengutronix and
FriendlyArm. :)

Juergen Beisert
There is a difference: For the Microsoft help you have to pay for. My help
for you here is for free, and so I expect a little bit more effort at the
user's side. Sometimes I can provide out-of-the-box-help. But sometimes I
only can provide hints how to do things because I have no real clue what
the problem at your side is. And so it is up to you to dig deeper into the
area you want to work on. Everything you need to make usage of the SPI bus
is prepared in the board support package. You just have to add and
configure the slave devices in the software you want to talk to via SPI.
Sorry, no idea why you are fighting against a missing header file and why.

I was not trying to offend you in any way. Don't get me wrong. It is good
that you are around. :)
Just sometime we, the users, don't know exactly what we do. :)

If I offended you. Please accept my apologizes. 

About the missing header file.
I can't compile without it. That is why I'm asking is it the same file as
linux/spi/spi.h or I will have to create the file. Or I should just remove
the include line in "mach-mini2440.c"!

Juergen Beisert
Hi BaHko, you didn't offend me. Don't worry. But sometimes I run out of
ideas where the problem is.
To do what you want to do needs a little bit more programming experience in
C I think. You just have to modify one file: the mach-mini2440.c. All other
sources are present. Do the modification, take a look what strctures and
defines the modification needs and then include the corresponding header
files where you find these declarations. Okay, its not that simple. But
always keep in mind: you try to modify an operating system. And a little
bit knowledge about the kernel internals are really helpful, when you do
And the linux/spi/spi.h cannot be the same like the mach/spi.h. That is why
I was talking about software layering. linux/spi/spi.h is the generic part.
But the architecture which runs the SPI master may need additional
definitions to make its SPI work. These definitions will never be part of
the generic header file. So, try without the mach/spi.h inclusion, see what
error messages you will get, use http://lxr.linux.no/#linux+v3.8.5/ to get
an idea where the missing defines are located and include these header
files instead.

Happy hacking

> Or I should just remove the include line in "mach-mini2440.c"!

Doesn't sound like a bad idea.

Another way of determining what has happen is for you to apply my patch to
3.1 from Pengutronix.  Then when you have proved that it is working you
will know that something has changed between kernel versions.

It appears that mach/spi.h has disappeared.  Does Google have anything to
say about that?  

What differences do you see between 3.1 and 3.7 in the mach-mini2440.c file

Meld is a handy tool for this sort work.

Based on this two links I was able to trace what had happen to mach/spi.h



mach/spi.h was removed and he was placed in include/linux/spi.s3c24xx.h

The data that was in mach/spi.h is:

    struct s3c2410_spi_info {
  int       pin_cs;  /* simple gpio cs */
  unsigned int     num_cs;  /* total chipselects */
  int       bus_num;       /* bus number to use. */

  unsigned int     use_fiq:1;  /* use fiq */

  void (*gpio_setup)(struct s3c2410_spi_info *spi, int enable);
  void (*set_cs)(struct s3c2410_spi_info *spi, int cs, int pol);

So in mach-s3c24xx.c I added linux/spi/s3c24xx.h instead of mach/spi.h

Now everything is almost perfect. I just have only one more error:
's3c24xx_spi_gpiocfg_bus0_gpe11_12_13' undeclared here (not in a function)

Juergen Beisert
This function was removed with patch
0f78b2443a654afad7c5efdf0157c80747078682 because in the mainline kernel was
no user of it, You have to add its content into the platform file now:

  s3c_gpio_cfgpin(S3C2410_GPE(13), S3C2410_GPE13_SPICLK0);
  s3c_gpio_cfgpin(S3C2410_GPE(12), S3C2410_GPE12_SPIMOSI0);
  s3c_gpio_cfgpin(S3C2410_GPE(11), S3C2410_GPE11_SPIMISO0);
  s3c2410_gpio_pullup(S3C2410_GPE(11), 0);
  s3c2410_gpio_pullup(S3C2410_GPE(13), 0);

(these calls just configure the pins to act as SPI lines instead of GPIOs)


Good detective work.  Nice to know if I ever wanted to use SPI on this
platform in 3.7 I now know how to do it!

Of course, thanks to Juergen for the added 5 lines of code.

Thanks, and hopefully it will help others. :)

I know that the pins are not registered. That's why I posted the error.
By "platform file" you mean "mach-s3c24xx.c" file right?
If I follow the logic it should be there. But for some reasons I'm pretty
sure I'm wrong. :) So please give me/us some more hints. 
Which file and where should I/We add the lines for the pins.

Thanks in advance. :)

Actually this 5 lines of code were in
and they were in function s3c24xx_spi_gpiocfg_bus0_gpe11_12_13

So I just create the same function before:
static struct s3c2410_spi_info mini2440_spi0_pdata = {

in file arm/arch/mach-s3c24xx/mach-mini2440.c

It compiles fine but with some DMA errors. Should I care or just leave it
this way?

What are the errors?  Are they warnings or errors?

Try running a SPI test program, search for spidev_test.

The warnings:

make[1]: Entering directory
  CHK     include/linux/version.h
  CHK     include/generated/utsrelease.h
make[2]: `include/generated/mach-types.h' is up to date.
  CALL    scripts/checksyscalls.sh
  CHK     include/generated/compile.h
  CC      arch/arm/mach-s3c24xx/mach-mini2440.o
arch/arm/mach-s3c24xx/mach-mini2440.c:315:2: warning: initialization from
incompatible pointer type [enabled by default]
arch/arm/mach-s3c24xx/mach-mini2440.c:315:2: warning: (near initialization
for 'mini2440_spi0_pdata.gpio_setup') [enabled by default]
  LD      arch/arm/mach-s3c24xx/built-in.o
WARNING: arch/arm/mach-s3c24xx/built-in.o(.data+0x448): Section mismatch in
reference from the variable s3c2440_dma_interface to the function
The variable s3c2440_dma_interface references
the function __init s3c2440_dma_add()
If the reference is valid then annotate the
variable with __init* or __refdata (see linux/init.h) or name the variable:
*_template, *_timer, *_sht, *_ops, *_probe, *_probe_one, *_console

  CHK     kernel/config_data.h
  CC      drivers/spi/spi-s3c24xx.o
  LD      drivers/spi/spi-s3c24xx-hw.o
  LD      drivers/spi/built-in.o
  LD      drivers/built-in.o
  LD      vmlinux.o
  MODPOST vmlinux.o
WARNING: vmlinux.o(.text+0xa294): Section mismatch in reference from the
function s3c2440_clk_add() to the function .init.text:clkdev_add_table()
The function s3c2440_clk_add() references
the function __init clkdev_add_table().
This is often because s3c2440_clk_add lacks a __init 
annotation or the annotation of clkdev_add_table is wrong.

WARNING: vmlinux.o(.text+0xaab0): Section mismatch in reference from the
function s3c2440_cpufreq_add() to the function
The function s3c2440_cpufreq_add() references
the function __init s3c_cpufreq_register().
This is often because s3c2440_cpufreq_add lacks a __init 
annotation or the annotation of s3c_cpufreq_register is wrong.

WARNING: vmlinux.o(.data+0x1848): Section mismatch in reference from the
variable s3c2440_dma_interface to the function .init.text:s3c2440_dma_add()
The variable s3c2440_dma_interface references
the function __init s3c2440_dma_add()
If the reference is valid then annotate the
variable with __init* or __refdata (see linux/init.h) or name the variable:
*_template, *_timer, *_sht, *_ops, *_probe, *_probe_one, *_console


LINE 315 from mach-mini24xx.c:

  .gpio_setup = &s3c24xx_spi_gpiocfg_bus0_gpe11_12_13,


FUNCTION gpio_setup = &s3c24xx_spi_gpiocfg_bus0_gpe11_12_13:

    void s3c24xx_spi_gpiocfg_bus0_gpe11_12_13(struct s3c2410_spi_info
  s3c_gpio_cfgpin(S3C2410_GPE(13), S3C2410_GPE13_SPICLK0);
  s3c_gpio_cfgpin(S3C2410_GPE(12), S3C2410_GPE12_SPIMOSI0);
  s3c_gpio_cfgpin(S3C2410_GPE(11), S3C2410_GPE11_SPIMISO0);
  s3c2410_gpio_pullup(S3C2410_GPE(11), 0);
  s3c2410_gpio_pullup(S3C2410_GPE(13), 0);


Right now I'm not sure I can run any SPI because I'm using the Micro2440
SDK and there is no SPI support on it. Hopefully in couple of weeks when
the Mini2440 arrive I will test it. :) But still I can prepare everything
for the Mini. :)

Juergen Beisert
> I'm using the Micro2440 SDK and there is no SPI support on it

If you can electrically connect GPE11, GPE12 and GPE13 and an additional
GPIO acting as chip select you *have* an SPI bus. Its the same on the
Mini2440. There is no real SPI bus on the card, just the GPIOs are
connected to some pin headers.  Its up to you to form a full SPI with it by
connecting an SPI slave device.

I think if you tried to cross-compile the standard kernel, before your
modifications, you will get some Warning messages.  Most kernels I have
compiled with these sort of Warnings seem to work.

But, then again this is not my paid employment!

That is something I was thinking about. But I don't know if I will have the
time this and next week. I was looking over the schematics of micro2440 and
I can see that MISO, MOSI, SCKL are K9,P9,L9 also known as
PGE11,PGE12,PGE13 but I don't know which pins they should be on the

First I want to trace them down properly. And To be sure that everything
will work and if my mini is not delivered I will proceed with the micro.


eMail (not visible)
Subject (no text only in upper case; no HELP, URGENT...)
HTML tags are not supported and links are generated automatically if they start with http or ftp.
Please submit long source code or log files as attachment (only registered users).
Please enter the number without blanks: 3 6 6 1