How do I properly configure chip select when adding AT25 EEPROM SPI device to Linux device tree?

Dear Toradex community,

I’m trying to add an AT25640B SPI EEPROM to my Linux configuration. The AT25 EEPROM is on a custom board attached to SPI1. PTD2/SPI1-CS3 is used as chip select signal. The EEPROM hold pin is permanently set to high by software. I added EEPROM_AT25 to my Linux kernel configuration and adapted my device tree file. In the root file system the file /sys/class/spi_master/spi1/spi1.3/eeprom occurs. But writing to or reading from it fails. On an oscilloscope I can see that the CS line is not set to low when accessing the EEPROM.

Reading or writing to the eeprom perfectly works when using the /dev/spidev1.0 device but I want to use the AT25 Linux driver.

This is my device tree file:

&iomuxc {
	vf610-colibri {
		pinctrl_additionalgpio: additionalgpios {
			fsl,pins = <
				VF610_PAD_PTB8__GPIO_30		0x22ed
				VF610_PAD_PTB9__GPIO_31		0x22ed
				VF610_PAD_PTB21__GPIO_43	0x22ed
				VF610_PAD_PTB22__GPIO_44	0x22ed
				VF610_PAD_PTD1__GPIO_80		0x22ed
				VF610_PAD_PTE2__GPIO_107	0x22ed
				VF610_PAD_PTE4__GPIO_109	0x22ed
				VF610_PAD_PTE7__GPIO_112	0x22ed
				VF610_PAD_PTE11__GPIO_116	0x22ed
				VF610_PAD_PTE12__GPIO_117	0x22ed
				VF610_PAD_PTE18__GPIO_123	0x22ed
			>;
		};

		pinctrl_dspi1: dspi1grp {
			fsl,pins = <
				VF610_PAD_PTD5__DSPI1_CS0		0x33e2
				VF610_PAD_PTD6__DSPI1_SIN		0x33e1
				VF610_PAD_PTD7__DSPI1_SOUT		0x33e2
				VF610_PAD_PTD8__DSPI1_SCK		0x33e2
			>;
		};

	};
};

&dspi1 {

	bus-num = <1>;
	pinctrl-names = "default";
	pinctrl-0 = <&pinctrl_dspi1>;
	status = "okay";

	mcp2515can: can@0 {
		status = "disabled";
	};

	eeprom: at25@0 {
		status = "okay";
		compatible = "atmel,at25";
		reg = <3>;
		spi-max-frequency = <5000000>;
		pagesize = <32>;
		size = <65536>;
		address-width = <16>;
	};
	
};

&can0 {
       status = "okay";
};

&can1 {
       status = "okay";
};
 
 &i2c0 {
       status = "disabled";
};

&uart0 {
	status = "okay";
};

&uart1 {
	status = "okay";
};

&uart2 {
	status = "okay";
};

I also tried modifiying pinctrl_dspi1 the following way which does no help at all.

		pinctrl_dspi1: dspi1grp {
			fsl,pins = <
				VF610_PAD_PTD5__DSPI1_CS0		0x33e2
				VF610_PAD_PTD4__DSPI1_CS1		0x33e2
				VF610_PAD_PTD3__DSPI1_CS2		0x33e2
				VF610_PAD_PTD2__DSPI1_CS3		0x33e2
				VF610_PAD_PTD6__DSPI1_SIN		0x33e1
				VF610_PAD_PTD7__DSPI1_SOUT		0x33e2
				VF610_PAD_PTD8__DSPI1_SCK		0x33e2
			>;
		}

Could you please help setting up the SPI communication with the EEPROM device?

Did you check dmesg logs? PTD2 is used by UART2 for RTS functionality. The below set of changes would be expected (Not tested).

diff --git a/arch/arm/boot/dts/vf-colibri-eval-v3.dtsi b/arch/arm/boot/dts/vf-colibri-eval-v3.dtsi
index f1d7496054d6..cc3cb2b5b4ba 100644
--- a/arch/arm/boot/dts/vf-colibri-eval-v3.dtsi
+++ b/arch/arm/boot/dts/vf-colibri-eval-v3.dtsi
@@ -103,6 +103,7 @@
                compatible = "toradex,evalspi";
                reg = <0>;
                spi-max-frequency = <50000000>;
+               status = "disabled";
        };
 
        mcp2515can: can@0 {
@@ -116,6 +117,17 @@
                interrupts = <11 GPIO_ACTIVE_LOW>;
                status = "disabled";
        };
+
+       at25@3 {
+               compatible = "atmel,at25", "st,m95256";
+               reg = <3>;
+               spi-max-frequency = <5000000>;
+
+               pagesize = <64>;
+               size = <32768>;
+               address-width = <16>;
+               status = "okay";
+       };
 };
 
 &esdhc1 {
@@ -179,7 +191,7 @@
 };
 
 &uart2 {
-       status = "okay";
+       status = "disabled";
 };
 
 &usbdev0 {
diff --git a/arch/arm/boot/dts/vf-colibri.dtsi b/arch/arm/boot/dts/vf-colibri.dtsi
index de1b1cb33f1a..47933d9b2546 100644
--- a/arch/arm/boot/dts/vf-colibri.dtsi
+++ b/arch/arm/boot/dts/vf-colibri.dtsi
@@ -270,6 +270,7 @@
                pinctrl_dspi1: dspi1grp {
                        fsl,pins = <
                                VF610_PAD_PTD5__DSPI1_CS0               0x33e2
+                               VF610_PAD_PTD2__DSPI1_CS3               0x33e2
                                VF610_PAD_PTD6__DSPI1_SIN               0x33e1
                                VF610_PAD_PTD7__DSPI1_SOUT              0x33e2
                                VF610_PAD_PTD8__DSPI1_SCK               0x33e2

Dear Sanchayan,

disabling uart2 and configuring pinctrl_dspi1 indeed solved the problem. Thank you so much! But there is no need for disabling spidev0.

Using the following device tree file, we’ve got working access to the AT25 EEPROM.

/*
 * Copyright 2014 Toradex AG
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 */

/dts-v1/;
#include "vf610-colibri.dtsi"
#include "vf-colibri-eval-v3.dtsi"

/ {
	model = "Toradex Colibri VF61 on Colibri Evaluation Board";
	compatible = "toradex,vf610-colibri_vf61-on-eval", "toradex,vf610-colibri_vf61", "fsl,vf610";
};

&iomuxc {
	vf610-colibri {
		pinctrl_additionalgpio: additionalgpios {
			fsl,pins = <
				VF610_PAD_PTB8__GPIO_30		0x22ed
				VF610_PAD_PTB9__GPIO_31		0x22ed
				VF610_PAD_PTB21__GPIO_43	0x22ed
				VF610_PAD_PTB22__GPIO_44	0x22ed
				VF610_PAD_PTD1__GPIO_80		0x22ed
				VF610_PAD_PTE2__GPIO_107	0x22ed
				VF610_PAD_PTE4__GPIO_109	0x22ed
				VF610_PAD_PTE7__GPIO_112	0x22ed
				VF610_PAD_PTE11__GPIO_116	0x22ed
				VF610_PAD_PTE12__GPIO_117	0x22ed
				VF610_PAD_PTE18__GPIO_123	0x22ed
			>;
		};

		pinctrl_dspi1: dspi1grp {
			fsl,pins = <
				VF610_PAD_PTD5__DSPI1_CS0		0x33e2
				VF610_PAD_PTD2__DSPI1_CS3       0x33e2
				VF610_PAD_PTD6__DSPI1_SIN		0x33e1
				VF610_PAD_PTD7__DSPI1_SOUT		0x33e2
				VF610_PAD_PTD8__DSPI1_SCK		0x33e2
			>;
		};

	};
};


&dspi1 {

	mcp2515can: can@0 {
		status = "disabled";
	};

	at25@0 {
		status = "okay";
		compatible = "atmel,at25";
		reg = <3>;
		spi-max-frequency = <5000000>;
		pagesize = <32>;
		size = <65536>;
		address-width = <16>;
	};

};


&can0 {
       status = "okay";
};

&can1 {
       status = "okay";
};
 
&i2c0 {
       status = "disabled";
};

&uart2 {
	status = "disabled";
};

Thanks for posting the final version again.

FWIW, by convention, the number after the @ is typically the reg value, e.g. at25 should be

at25@3 {