cancel
Showing results for 
Search instead for 
Did you mean: 
Highlighted
Observer
Observer
22,355 Views
Registered: ‎02-19-2014

linux SPI for zynq

Hi,

 

I’ would like to use Peripheral  spi:0 of Zynq Xilinx with Linux OS on the ZC706 . And I selec /device driver/SPI support/Xilinx SPI controller common module in the menu, so SPIDEV is built in the uImage. And zynq-zc706.dts is added the following sentence for SPI.

        spi_0: spi@e0006000 {
            compatible = "xlnx,ps7-spi-1.00.a";
            reg = <0xE0006000 0x1000>;
            interrupts = <0 26 4>;
            interrupt-parent = <&ps7_scugic_0>;
            speed-hz = <166666672>;
            bus-num = <0>;
            num-chip-select = <3>;
            #address-cells = <1>;
            #size-cells = <0>;
                  spidev@0 {
                      compatible = "spidev";
                      reg = <0>;  /* CS */
                      spi-max-frequency = <25000000>;
                      /*spi-cpha; Possible property */
                      /*spi-cpol; Possible property */
                      /*spi-cs-high; Possible property */
                      /*spi-3wire; Possible property */
                      /*no interrupts */
            };
        }

 

unfortunately, SPI driver can not loaded correctly, I do not find spi device in the /dev folder and the log is as following:

xspips e0006000.spi: aper_clk clock not found.
xspips: probe of e0006000.spi failed with error -2


I got linux and uboot from

https://github.com/Xilinx/linux-xlnx/releases/tag/xilinx-v2013.4

 

I used the following version

linux kernel version: v2013.4

uboot version: v2013.4

 

0 Kudos
21 Replies
Highlighted
Xilinx Employee
Xilinx Employee
22,341 Views
Registered: ‎03-13-2012

Re: linux SPI for zynq

You're missing 'clocks' and 'clock-names' properties in your DT (cmp: https://github.com/Xilinx/linux-xlnx/blob/master-next/arch/arm/boot/dts/zynq-zc770-xm010.dts#L316 ).

0 Kudos
Highlighted
Visitor
Visitor
22,325 Views
Registered: ‎10-02-2013

Re: linux SPI for zynq

I'm having similar trouble.  I can successfully control SPI with bare metal code.  I'm trying to transition to Linux and really struggling with the SPI.  Does anyone actually have it working in Linux with a ZC706?  I have SP0 enabled as EMIO.  I have the latest kernel compiled with SPIDEV.  My devicetree has the clocks as mentioned by sorenb.  It is:

		ps7_spi_0: ps7-spi@e0006000 {
			clock-names = "ref_clk", "aper_clk";
			clocks = <&clkc 25>, <&clkc 34>;
			compatible = "xlnx,ps7-spi-1.00.a";
			interrupt-parent = <&ps7_scugic_0>;
			interrupts = <0 26 4>;
			num-chip-select = <4>;
			reg = <0xe0006000 0x1000>;
			#address-cells=<1>;
			#size-cells=<0>;
			spidev@0{
				compatible="spidev";
				reg =<0>; //chipselect 0
				spi-max-frequency= <50000000>;
			};
			spidev@1{
				compatible="spidev";
				reg =<1>; //chipselect 1
				spi-max-frequency= <50000000>;
			};
			spidev@2{
				compatible="spidev";
				reg =<2>; //chipselect 2
				spi-max-frequency= <50000000>;
			};
		} ;

 My tree was generated by the device tree generator tool, and I added everything from #address-cells=<1> down.

 

I have my SS1 and SS2 wired to the FMC connector going to a SPI controled ADC card.  Again, I can control the ADC over SPI perfectly with the bare_metal BSP code.

 

In Linux I get /dev/spidev1.0, /dev/spidev1.1, and /dev/spidev1.2.  When I run spidev_test on either spidev1.1 or spidev 1.2, I can see the correct chip select getting set on a scope.  However, Linux completely locks up on the transmit attempt and the scope shows a SCLK (clock) that both doesn't look correct and never stops.

 

I've run out of ideas on how to further debug this so any comments/suggestions would be welcomed!

Highlighted
Xilinx Employee
Xilinx Employee
22,323 Views
Registered: ‎03-13-2012

Re: linux SPI for zynq

I'm certainly not a SPI expert, so just some generic advice:

It sounds like you may run in some deadlock. Do you have deadlock debugging/detection enabled (cmp: https://github.com/Xilinx/linux-xlnx/commit/e8a0f03e48a0b28fb2d8137745bc7dd9da61d724 ). That might give some additional hints where a deadlock may be originating from.

0 Kudos
Highlighted
Visitor
Visitor
22,302 Views
Registered: ‎10-02-2013

Re: linux SPI for zynq

Ok.  That's digging in to the kernel a bit more than I'm ready for at the moment.  My SPI needs are limited (simple polled writing).  So for now, I wrote a simple HLS block to do my SPI and that works so I'm moving on.  I'd rather use the built-in SPI, but I'll have to try your debug suggestions later.  Thanks.

0 Kudos
Highlighted
Observer
Observer
22,282 Views
Registered: ‎02-19-2014

Re: linux SPI for zynq

I did not verify whether SPI be controlled with bare metal code based on standalone.I changed dts that is same to your dts. and i investigate this issue that seems halted in the wait_for_completion from xspips_start_transfer. I am not sure FPGA bitstream has been loaded successfully, which is provided by xilinx FAE engineer, and just SPI control MSIO pin is connected to the FPGA pin. any suggestion is welcome.thanks.

 

ps, register value from SPI controller register is shown as the following.
0xf0068000 0000fc21 00000004 00000000 00000000
0xf0068010 00000000 00000001 00000000 00000000
0xf0068020 00000000 000000ff 00000001 00000001
reg:0xf00680fc 00090106

0 Kudos
Highlighted
Observer
Observer
22,276 Views
Registered: ‎02-19-2014

Re: linux SPI for zynq

I found FPGA done led is light.but still wait_for_completion not be finished.

0 Kudos
Highlighted
Observer
Observer
22,262 Views
Registered: ‎02-19-2014

Re: linux SPI for zynq

to investigate this issue, MOSI is connected to MISO in FPGA. But this issue is the same as before. any suggestion? thanks.

spi_lp.PNG
0 Kudos
Highlighted
Scholar
Scholar
22,252 Views
Registered: ‎05-28-2013

Re: linux SPI for zynq

A patch to prevent getting stuck in wait_for_completion is here https://github.com/Xilinx/linux-xlnx/commit/07e258388ac3433afdfa27460c340f3e737cb3d4

However that will not make the actual transfer work... I suggest checking that you have clocks correctly configured and enabled... if the SPI controller doesn't receive a clock, it will most certainly not work!


Also I noticed a potential bug in the SPI driver, relating to setting the final clock divider:

while ((baud_rate_val < 8) && (frequency /(2 << baud_rate_val)) > req_hz)
baud_rate_val++;

Upon exit from the loop, baud_rate_val could be 8. However the max value permitted is 7 according to the Zynq TRM. When written to the control register at E000600, the baud_rate_val=8 actually spills over into an adjacent field that is reserved ("write 00").
0 Kudos
Highlighted
Scholar
Scholar
22,172 Views
Registered: ‎05-28-2013

Re: linux SPI for zynq

Update: if you are using SS0 for your chip select, then check this known issue: http://www.xilinx.com/support/answers/47511.htm

After fixing that in our PL, using a scope we are seeing the correct signals on EMIO for SPI device.
Highlighted
Observer
Observer
13,459 Views
Registered: ‎02-19-2014

Re: linux SPI for zynq

As you said for your patch, It does not make the actual transfer work, only not pending in the wait_for_completion.
clock is from reference clock when SPI controller is master mode, I suppose the clock has been configured correctly. How to check the clock configured correctly?
baud_rate_val is not greater than 8 in our project.
0 Kudos
Highlighted
Observer
Observer
13,459 Views
Registered: ‎02-19-2014

Re: linux SPI for zynq

Thanks. I am using SS0 in our project and I will try to do following this scenario, or will try to use SS1/SS2.
0 Kudos
Highlighted
Observer
Observer
13,461 Views
Registered: ‎02-19-2014

Re: linux SPI for zynq

Hi, asigint, could you share your bitstream for me and i Try it. thanks
0 Kudos
Highlighted
Scholar
Scholar
13,439 Views
Registered: ‎05-28-2013

Re: linux SPI for zynq

You can verify clocks and divisors by checking the following registers. See the Zynq TRM for details on these.

 

SPI_CLK_CTRL at physical address 0xF8000158

bits 13:8 are the clock divider

bits 5:4 are the clock source

bit 0 must be set to enable reference clock for SPI0 controller

 

APER_CLK_CTRL at physical address 0xF800012C

bit 14 must be set, to enable clock to SPI0 controller

 

SPI0 control register at address 0xE0006000

bits 5:3 are the baud rate divisor

 

The final clock rate on the SCLK signal is your master clock (we use IOPLL at 1000MHz), divided by the first divisor (we use value of 5, giving us SPI_ref clock of 200MHz), divided by the baud rate divisor (we use value 3, which divides by 16, giving us 12.5MHz SCLK rate).

0 Kudos
Highlighted
Observer
Observer
13,432 Views
Registered: ‎02-19-2014

Re: linux SPI for zynq

return value from these register is as following:
SLCR_SPI_CLK_CTRL: 00003f03
SLCR_APER_CLK_CTRL: 01ac444d

register value from SPI controller register is shown as the following.
0xf0068000 0000fc21 00000004 00000000 00000000
0xf0068010 00000000 00000001 00000000 00000000
0xf0068020 00000000 000000ff 00000001 00000001
reg:0xf00680fc 00090106

I did not find any wrong configuration from this value.
0 Kudos
Highlighted
Observer
Observer
13,428 Views
Registered: ‎02-19-2014

Re: linux SPI for zynq

good news. it works. I re-built fsbl and pack into BOOT.bin. I do not know why these fsbl impact SPI interface.
0 Kudos
Highlighted
Xilinx Employee
Xilinx Employee
13,422 Views
Registered: ‎03-13-2012

Re: linux SPI for zynq

Well, the FSBL does all the low level setup, including the clock frequencies and pin muxing. If you change your HW design you must update your FSBL.

0 Kudos
Highlighted
Visitor
Visitor
13,113 Views
Registered: ‎03-20-2014

Re: linux SPI for zynq

Hello, it seems you had let your spi works well. I can successfully control SPI with bare-metal code and I'm trying to transition to Linux. I'm using XC7Z010 on Microzed. I had modified the device tree and when Linux start, I can see a virtual address mapped to the new spi device.
ps7_spi_0: ps7-spi@e0006000 {
compatible = "xlnx,ps7-spi-1.00.a";
#address-cells=<1>;
#size-cells=<0>;
bus-num = <0>;
num-chip-select = <4>;
interrupts = <0 26 4>;
interrupt-parent = <&ps7_scugic_0>;
reg = < 0xe0006000 0x1000 >;
speed-hz = <50000000>;
xlnx,has-ss0 = <0x1>;
xlnx,has-ss1 = <0x1>;
xlnx,has-ss2 = <0x1>;
device@0 {
compatible = "spidev";
reg = <0>; //Chip select 0
spi-max-frequency = <50000000>;
};
device@1 {
compatible = "spidev";
reg = <1>; //Chip select 1
spi-max-frequency = <50000000>;
};
device@2 {
compatible = "spidev";
reg = <2>; //Chip select 2
spi-max-frequency = <50000000>;
};
};
Except I can't find /dev/spidev1.0, /dev/spidev1.1, and /dev/spidev1.2 inside Linux. It seems I had to compile the kernel with SPIDEV?? Or I had to modify something inside the kernel? Does anyone can tell me how to do it?
Any comments/suggestions would be welcomed!
0 Kudos
Highlighted
Scholar
Scholar
13,109 Views
Registered: ‎05-28-2013

Re: linux SPI for zynq

Yes, you need to rebuild your kernel with the driver enabled, or build it as a module and load it with "modprobe". It is in the linux kernel configuration under Device Drivers -> SPI Support -> User mode SPI device driver support.
0 Kudos
Highlighted
Visitor
Visitor
11,947 Views
Registered: ‎07-20-2014

Re: linux SPI for zynq

hi sorenb, i met a similar problem about spi in zynq.

 

i used a customized board with ZC030, i wanna enable spi1 via MIO, but i cannot found /dev/spixx when liunx bring up,

 

the figure below is my kernel configration,

 

323c6eaff34750e78a529dd259a67a35_看图王.png

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

0 Kudos
Highlighted
Visitor
Visitor
7,715 Views
Registered: ‎07-20-2014

Re: linux SPI for zynq

and the .dts generated by petalinux has
/*is-decoded-cs = <0>;*/
/*num-cs = <1>;*/
options ,
i don't kown the reason
0 Kudos
Highlighted
Adventurer
Adventurer
7,382 Views
Registered: ‎08-05-2012

Re: linux SPI for zynq

Hello, thanks for the tip on AR# 47511.  I am amazed that you can piece together the exact nature of the problem from the vague technical description on the AR, and hope I can get some clarification (also considering filing a webcase, but it is the weekend, and I am not sure if I will get any further clarification).

 

Firstly, this is what I understand after reading http://www.xilinx.com/support/answers/47511.html:

  • In master mode, SS[x] should be driven as an output pin (of course!)
  • There is apparently a bug where if nSS0 is pulled low, the controller resets.  The workaround is to either NOT use SS0 and tie SS0 to Vcc.  I am actually unsure whether the correct workaround is NOT to use SS0 at all, or just don't use it in a multi-master setting; because the rest of the explanation makes little sense to me, like this one: "The unused input signal from the MIO/EMIO multiplexer must remain deasserted."  Taken literally, it has nothing to do with SS0 being pulled down and the SPI controller resetting.  Yes, in a multi-master situation, SS0 may perhaps be pulled down by another controller.  So exactly what is the nature of the problem?  That SS0 should NEVER be pulled down low by any other controller?  Or that SS0 should never by pulled down PERIOD--in which case SS0 just should not be used?
0 Kudos