1

(I am really unsure of which tags to apply, so apologies in advance if I chose the wrong ones.)

I hope that this is not a too stupid question, but I'm really lost here.

A client lent me an Atmel SAMA5D2 Xplained board with Linux4SAM to play around with. I'm trying to interface the SPI interface on it, but I have no clue where to start.

To be clear, I've used similar boards (not this particular one) bare-metal. I've also used Linux for many years and wrote a few simple devices drivers some years ago. And still I'm lost.

dmesg | grep spi gives me the following output:

[    1.840000] atmel_spi f8000000.spi: version: 0x311
[    1.840000] atmel_spi f8000000.spi: Using dma0chan0 (tx) and dma0chan1 (rx) for DMA transfers
[    1.850000] atmel_spi f8000000.spi: Using FIFO (16 data)
[    1.860000] atmel_spi f8000000.spi: Atmel SPI Controller at 0xf8000000 (irq 32)
[    1.860000] m25p80 spi32766.0: at25df321a (4096 Kbytes)

From this I infer that a driver is loaded and that it is configured to use DMA. Yet, looking in /dev/ there is nothing that looks like a SPI device (I was expecting to find something like /dev/spidev or /dev/spi32766.0 or similar.)

Does this mean that there is no actual device driver loaded? Do I have to write one in order to use the SPI?

If I look at the Makefile in the Linux4SAM source tree, I see around line 1171 that the kernel does not support loading of modules. Does this imply I have to recompile the kernel to include my new driver? This seems to be a silly approach; why providing a Linux distribution if I can't access the hardware with it?

What am I missing here? (I feel rather stupid...)

EDIT To be clear: I want to access the external SPI interface that will be connected to some external device. I think the m25p80 is some internal Flash memory; I'm not interested to read/write there.

Ludo
  • 813
  • 1
  • 9
  • 21
  • 2
    https://www.kernel.org/doc/Documentation/spi/spidev and you have to enable spidev in kernel configuration and in resource provider like Device Tree. – 0andriy Jan 24 '17 at 23:19
  • *"If I look at the Makefile ... the kernel does not support loading of modules. "* -- You won't find configuration specifics in the Makefile. *"I think the m25p80 is some internal Flash memory"* -- Wrong, that is external flash connected through SPI. Study kernel **Documentation/spi/spi-summary**. SPI (slave) devices typically have device-node names derived from their functionality, rather than the interface it uses. Spidev is the exception since it's a userspace kludge. – sawdust Jan 25 '17 at 00:21
  • @0andriy: spidev is enabled in the kernel configuration. I can load the module (modprobe), but no new device appears. I hadn't thought of having to specify something additional in the Device Tree... I'm new to Linux on such platforms. – Ludo Jan 25 '17 at 08:04
  • @sawdust: I phrased it wrong. The kernel does support loading of modules, but the Makefile tells me I can't compile new modules using the source tree (`make -C modules`). I did read the documentation you're referring to, but it's difficult to connect the dots if I don't know what information I'm looking for. – Ludo Jan 25 '17 at 08:07
  • check the spidevice listed here *cat /proc/devices*, if yes and not able to see device node(/dev/spidev*), i suspect your driver doen't created the device node, you need to create manually by using mknod. – ntshetty Jan 31 '17 at 08:29

2 Answers2

2

spidev is a standard Linux device driver which just exports a low level API to userspace via /dev interface

if you want to access specific SPI client(slave) you should write your driver according to Linux SPI driver model:

static const struct of_device_id myspi_dt_ids[] = {
{ .compatible = "xxxx,yyyyy" },
{},

static struct spi_driver xxx_spi_driver = {
.driver = {
    .name =     "myspi",
    .owner =    THIS_MODULE,
    .of_match_table = of_match_ptr(myspi_dt_ids),
},
.probe =    myspi_probe,
.remove =   myspi_remove,

e.g. define spi_driver struct, of_device_id struct, callbacks(hooks), and register it. You should bind it to your DT node with compatible property string.

            myspi@0 {
            compatible = "xxxx,yyyyy";
            spi-max-frequency = <5000000>;
            reg = <0>;
        };

second,

compatible = "linux,spidev";

Linux discourages using this compatible property because nodes should describe real HW devices not userspace abstractions

Dražen G.
  • 358
  • 3
  • 10
  • The initial question was to get a test program to work, which I was hoping to get done with spidev, but I never got it to work. To develop the functionality that I needed beyond the quick test, I did exactly as you describe here. – Ludo Nov 16 '18 at 08:13
1

@0andriy put me on the right track. I had to add a SPI resource to the Device Tree and flash the compile Device Tree Blob to the board. (Since I didn't know about Device Trees at all, this information is really hard to find...).

I now have a /dev/spidev32765.0. I added this to the device tree:

        spi1: spi@fc000000 {
            pinctrl-names = "default";
            pinctrl-0 = <&pinctrl_spi1_default>;
            status = "okay";

            spidev@0 {
                compatible = "linux,spidev";
                spi-max-frequency = <83000000>;
                reg = <0>;
            };
        };

        pinctrl@fc038000 {
            pinctrl_spi1_default: spi1_default {
                pinmux = <PIN_PD25__SPI1_SPCK>,
                     <PIN_PD26__SPI1_MOSI>,
                     <PIN_PD27__SPI1_MISO>,
                     <PIN_PD28__SPI1_NPCS0>;
                bias-disable;
            };
        };

Although I read that adding the spidev@0 is not really the right thing to do (I indeed see in dmesg output "spidev spi32765.0: buggy DT: spidev listed directly in DT").

Now, if I run spidev_test it still doesn't work (it times out), but I guess that's for another question.

Ludo
  • 813
  • 1
  • 9
  • 21