Daily Archives: 2019-10-11

VoCore2: develop SPI driver 2

Continue with last blog…

PS: because I am a totally noob of kernel develop, the process is pretty slow 🙂

I only have a little experience on DMA, I2S and sound codec…for SPI part, still a blank paper. This blog must be hard to understand and very few people will read, but the process is pretty fun for me.

For a common vocore2, once it boot up, the SPI control register 0x10000b28 is like this:

root@OpenWrt:/# mem 0x10000b28 bit
31:1 30:1 29:1 28:0 27:0 26:0 25:0 24:0 23:0 22:0 21:0 20:1 19:0 18:0 17:1 16:0 
15:1 14:0 13:0 12:0 11:1 10:0 09:0 08:0 07:1 06:0 05:0 04:0 03:0 02:1 01:0 00:0

Its ninth bit is int_en, I guess that should be enabled.

Then read datasheet(pretty painful for me) page 11/347, we can find:

So SPI interrupt is 11(0x0b)

Let’s check interrupt register, 0x10000270.
For my VoCore2, the result like this:

root@OpenWrt:~# mem 0x10000270 bit
31:1 30:0 29:0 28:0 27:0 26:0 25:0 24:0 23:0 22:1 21:0 20:0 19:0 18:1 17:1 16:0 
15:0 14:1 13:0 12:0 11:0 10:0 09:0 08:0 07:1 06:1 05:0 04:0 03:0 02:0 01:0 00:0 

22 is UART-Lite2, which we used it for debug console.
18 is USB20, so from its name it should be USB2.0.
17 is ESW, from its name it should be ethernet switcher.
14 is SDXC, absolutely for SD card.
07 is GDMA, general DMA, for sound and i2s we use it to boost up speed.
06 is GPIO, so for fast GPIO it should be useful, like trigger button by low to high voltage edge.
11 is SPI, currently the driver is not used, that is what I will going to do.
31 is not there…as I know it is for soft interrupt, once I read code about it, but can not remember where it is.

I have no idea where to start.
Let’s check GDMA driver first, in dts/MT7628AN.dtsi(openwrt source code)

                gdma: gdma@2800 {
                        compatible = "ralink,rt3883-gdma";
                        reg = <0x2800 0x800>;

                        resets = <&rstctrl 14>;
                        reset-names = "dma";

                        interrupt-parent = <&intc>;
                        interrupts = <7>;

                        #dma-cells = <1>;
                        #dma-channels = <16>;
                        #dma-requests = <16>;

                        status = "disabled";
                };

We can find it has intc at <7>, and in its source code, it connects interrupt with this source code. driver/dma/ralink-gdma.c (linux source code)

	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	base = devm_ioremap_resource(&pdev->dev, res);
	if (IS_ERR(base))
		return PTR_ERR(base);
	dma_dev->base = base;
	tasklet_init(&dma_dev->task, gdma_dma_tasklet, (unsigned long)dma_dev);

so once the interrupt is triggered, the kernel should call gdma_dma_tasklet.

Next blog I will update the spi driver source code in linux to check if this interrupt works 😉