Now in the deep zone.
From /proc/interrupts, I know esw, gdma, sdhci etc have interrupts.
Check gdma source code, we can add similar irq code to spi.
static irqreturn_t mt7621_spi_irq(int irq, void *devid) { struct mt7621_spi *rs = (struct mt7621_spi *)devid; printk(KERN_INFO "mt7621_spi_irq %d trigger\n", irq); return IRQ_HANDLED; } ... irq = platform_get_irq(pdev, 0); if (irq < 0) { dev_err(&pdev->dev, "failed to get irq\n"); return -EINVAL; } ret = devm_request_irq(&pdev->dev, irq, mt7621_spi_irq, 0, dev_name(&pdev->dev), rs); if (ret) { dev_err(&pdev->dev, "failed to request irq\n"); return ret; }
and in vocore2 dts(device tree, mt7628an.dtsi), we also need to add spi interrupt.
spi0: spi@b00 { compatible = "ralink,mt7621-spi"; reg = <0xb00 0x100>; resets = <&rstctrl 18>; reset-names = "spi"; #address-cells = <1>; #size-cells = <0>; pinctrl-names = "default"; pinctrl-0 = <&spi_pins>; interrupt-parent = <&intc>; interrupts = <11>; status = "disabled"; };
OK, that all, we can compile and check if this works.
After VoCore2 upgrade ready and flash init ready, we can call mem command(I write this command for easy debug, source code can be downloaded at vocore.io/v2.html) to enable spi interrupt.
mem 0x10000b28 0xe0128a84
Then, write something through spi, like ‘touch /root/x’, this will create a new file under /root/, so OS will try to use spi write to the flash.
Ouch… I just get endless messages “mt7621_spi_irq 19 trigger” from console, after a while, the system dead.
I guess there must be something wrong in the interrupt code. As I remember, once interrupt is triggered, we must write to some register to clean the interrupt, or it will keep in trigger status, that will cause a deadloop, system will hang up too.
Checking esw(ethernet switch) source code, I find esw 0x00 register is Interrupt Status Register, once you write same thing into the register, it will clean up the interrupt.
So SPI must has something similar.
Finally I find it is 0x10000b34 register, its name is SPI Status. The final bit of it:
Once the register is read by system, the interrupt will be clear, easy 😉
Update IRQ code to the following code
static irqreturn_t mt7621_spi_irq(int irq, void *devid) { struct mt7621_spi *rs = (struct mt7621_spi *)devid; u32 reg; reg = mt7621_spi_read(rs, MT7621_SPI_STATUS); printk(KERN_INFO "mt7621_spi_irq %d trigger, status 0x%08x\n", irq, reg); return IRQ_HANDLED; }
Now once we touch new file into flash, we just get around ten lines of the kernel interrupt log, that means, it works! Check system, spi interrupt is not zero anymore.
root@OpenWrt:~# cat /proc/interrupts CPU0 5: 895 MIPS 5 10100000.ethernet 6: 50378 MIPS 6 ra0 7: 266055 MIPS 7 timer 15: 0 INTC 7 10002800.gdma 19: 138 INTC 11 10000b00.spi 22: 79014 INTC 14 10130000.sdhci 25: 2 INTC 17 esw 26: 1 INTC 18 ehci_hcd:usb1, ohci_hcd:usb2 30: 440 INTC 22 ttyS2 ERR: 0
Next I will try to combine the interrupt into the source code, this is pretty risk, because once Linux boot up, it is using this driver read from flash.
Next next, if I have any luck go that far, maybe try GDMA with SPI, then we have some fast speed spi devices.