VoCore2: UART2 for openwrt

Now uboot part works, we need to make openwrt serial also output to UART2.

PS: weird issue, I find /dev/mem gone…is Linux 4.4.6 removed it?

My code based on trunk@49094. It is a develop openwrt version also contains many bugs. 🙂 If my code works please help me commit to openwrt.

If we do not modify anything, just flash uboot firmware to VoCore2, the serial log will end here.

U-Boot 1.1.3 (Mar 28 2016 - 22:54:05)

Board: Ralink APSoC DRAM:  64 MB
relocate_code Pointer at: 83fb8000
******************************
Software System Reset Occurred
******************************
flash manufacture id: c8, device id 40 18
find flash: GD25Q128C
*** Warning - bad CRC, using default environment

============================================ 
Ralink UBoot Version: 4.3.0.0
-------------------------------------------- 
ASIC 7628_MP (Port5<->None)
DRAM component: 512 Mbits DDR, width 16
DRAM bus: 16 bit
Total memory: 64 MBytes
Flash component: SPI Flash
Date:Mar 28 2016  Time:22:54:05
============================================ 
icache: sets:512, ways:4, linesz:32 ,total:65536
dcache: sets:256, ways:4, linesz:32 ,total:32768 

 ##### The CPU freq = 575 MHZ #### 
 estimate memory size =64 Mbytes
RESET MT7628 PHY!!!!!!
Please choose the operation: 
   1: Load system code to SDRAM via TFTP. 
   2: Load system code then write to Flash via TFTP. 
   3: Boot system code via Flash (default).
   4: Entr boot command line interface.
   7: Load Boot Loader code then write to Flash via Serial. 
   9: Load Boot Loader code then write to Flash via TFTP. 
 0 
   
3: System Boot system code via Flash.
## Booting image at bc050000 ...
   Image Name:   MIPS OpenWrt Linux-4.4.6
   Image Type:   MIPS Linux Kernel Image (lzma compressed)
   Data Size:    1270118 Bytes =  1.2 MB
   Load Address: 80000000
   Entry Point:  80000000
   Verifying Checksum ... OK
   Uncompressing Kernel Image ... OK
No initrd
## Transferring control to Linux (at address 80000000) ...
## Giving linux memsize in MB, 64

Starting kernel ...

[    0.000000] Linux version 4.4.6 (vocore@ubuntu) (gcc version 5.3.0 (OpenWrt GCC 5.3.0 r49094) ) #7 Fri Apr 1 18:35:11 UTC 2016
[    0.000000] Board has DDR2
[    0.000000] Analog PMU set to hw control
[    0.000000] Digital PMU set to hw control
[    0.000000] SoC Type: MediaTek MT7628AN ver:1 eco:2
[    0.000000] bootconsole [early0] enabled
[    0.000000] CPU0 revision is: 00019655 (MIPS 24KEc)
[    0.000000] MIPS: machine is VoCore2 64MB
[    0.000000] Determined physical RAM map:
[    0.000000]  memory: 04000000 @ 00000000 (usable)
[    0.000000] Initrd not found or empty - disabling initrd
[    0.000000] Zone ranges:
[    0.000000]   Normal   [mem 0x0000000000000000-0x0000000003ffffff]
[    0.000000] Movable zone start for each node
[    0.000000] Early memory node ranges
[    0.000000]   node   0: [mem 0x0000000000000000-0x0000000003ffffff]
[    0.000000] Initmem setup node 0 [mem 0x0000000000000000-0x0000000003ffffff]
[    0.000000] Primary instruction cache 64kB, VIPT, 4-way, linesize 32 bytes.
[    0.000000] Primary data cache 32kB, 4-way, PIPT, no aliases, linesize 32 bytes
[    0.000000] Built 1 zonelists in Zone order, mobility grouping on.  Total pages: 16256
[    0.000000] Kernel command line: console=ttyS0,57600 rootfstype=squashfs,jffs2
[    0.000000] PID hash table entries: 256 (order: -2, 1024 bytes)
[    0.000000] Dentry cache hash table entries: 8192 (order: 3, 32768 bytes)
[    0.000000] Inode-cache hash table entries: 4096 (order: 2, 16384 bytes)
[    0.000000] Writing ErrCtl register=00073670
[    0.000000] Readback ErrCtl register=00073670
[    0.000000] Memory: 60844K/65536K available (2859K kernel code, 132K rwdata, 692K rodata, 148K init, 195K bss, 4692K reserved, 0K cma-reserved)
[    0.000000] SLUB: HWalign=32, Order=0-3, MinObjects=0, CPUs=1, Nodes=1
[    0.000000] NR_IRQS:256
[    0.000000] intc: using register map from devicetree
[    0.000000] add clock for 10000d00.uart1, rate = 40000000
[    0.000000] add clock for 10000e00.uart2, rate = 40000000
[    0.000000] add clock for cpu, rate = 580000000
[    0.000000] add clock for 10000100.timer, rate = 40000000
[    0.000000] add clock for 10000120.watchdog, rate = 40000000
[    0.000000] add clock for 10000b00.spi, rate = 193333333
[    0.000000] add clock for 10000b40.spi, rate = 193333333
[    0.000000] add clock for 10000c00.uartlite, rate = 40000000
[    0.000000] add clock for 10180000.wmac, rate = 40000000
[    0.000000] CPU Clock: 580MHz
[    0.000000] clocksource_probe: no matching clocksources found
[    0.000000] clocksource: MIPS: mask: 0xffffffff max_cycles: 0xffffffff, max_idle_ns: 6590553264 ns
[    0.000011] sched_clock: 32 bits at 290MHz, resolution 3ns, wraps every 7405115902ns
[    0.015349] Calibrating delay loop... 385.84 BogoMIPS (lpj=1929216)
[    0.080520] pid_max: default: 32768 minimum: 301
[    0.089782] Mount-cache hash table entries: 1024 (order: 0, 4096 bytes)
[    0.102736] Mountpoint-cache hash table entries: 1024 (order: 0, 4096 bytes)
[    0.122279] clocksource: jiffies: mask: 0xffffffff max_cycles: 0xffffffff, max_idle_ns: 19112604462750000 ns
[    0.141778] pinctrl core: initialized pinctrl subsystem
[    0.152723] NET: Registered protocol family 16
[    0.179323] mt7621_gpio 10000600.gpio: registering 32 gpios
[    0.190412] mt7621_gpio 10000600.gpio: registering 32 gpios
[    0.201416] mt7621_gpio 10000600.gpio: registering 32 gpios
[    0.213941] clocksource: Switched to clocksource MIPS
[    0.225338] NET: Registered protocol family 2
[    0.234765] TCP established hash table entries: 1024 (order: 0, 4096 bytes)
[    0.248470] TCP bind hash table entries: 1024 (order: 0, 4096 bytes)
[    0.260983] TCP: Hash tables configured (established 1024 bind 1024)
[    0.273632] UDP hash table entries: 256 (order: 0, 4096 bytes)
[    0.285086] UDP-Lite hash table entries: 256 (order: 0, 4096 bytes)
[    0.297732] NET: Registered protocol family 1
[    0.307657] futex hash table entries: 256 (order: -1, 3072 bytes)
[    0.338516] squashfs: version 4.0 (2009/01/31) Phillip Lougher
[    0.349983] jffs2: version 2.2 (NAND) (SUMMARY) (LZMA) (RTIME) (CMODE_PRIORITY) (c) 2001-2006 Red Hat, Inc.
[    0.372014] io scheduler noop registered
[    0.379693] io scheduler deadline registered (default)
[    0.390672] Serial: 8250/16550 driver, 2 ports, IRQ sharing disabled
[    0.404112] rt2880-pinmux pinctrl: invalid group "spis" for function "pwm"
[    0.417827] console [ttyS0] disabled
[    0.424820] 10000e00.uart2: ttyS0 at MMIO 0x10000e00 (irq = 30, base_baud = 2500000) is a 16550A
[    0.442151] console [ttyS0] enabled
[    0.442151] console [ttyS0] enabled
[    0.455889] bootconsole [early0] disabled
[    0.455889] bootconsole [early0] disabled
[    0.473336] spi-mt7621 10000b00.spi: sys_freq: 193333333
[    0.487529] m25p80 spi32766.0: using chunked io (size=32)
[    0.498290] m25p80 spi32766.0: gd25q128 (16384 Kbytes)
[    0.508501] 4 ofpart partitions found on MTD device spi32766.0
[    0.520053] Creating 4 MTD partitions on "spi32766.0":
[    0.530233] 0x000000000000-0x000000030000 : "u-boot"
[    0.541846] 0x000000030000-0x000000040000 : "u-boot-env"
[    0.554307] 0x000000040000-0x000000050000 : "factory"
[    0.566168] 0x000000050000-0x000000800000 : "firmware"
[    0.603038] 2 uimage-fw partitions found on MTD device firmware
[    0.614797] 0x000000050000-0x0000001861a6 : "kernel"
[    0.626261] 0x0000001861a6-0x000000800000 : "rootfs"
[    0.637985] mtd: device 5 (rootfs) set to be root filesystem
[    0.649351] 1 squashfs-split partitions found on MTD device rootfs
[    0.661606] 0x000000370000-0x000000800000 : "rootfs_data"
[    0.683669] rt3050-esw 10110000.esw: link changed 0x00
[    0.695347] mtk_soc_eth 10100000.ethernet: generated random MAC address fe:67:bf:04:9d:38
[    0.712449] mtk_soc_eth 10100000.ethernet eth0: mediatek frame engine at 0xb0100000, irq 5
[    0.729378] mt7621_wdt 10000120.watchdog: Initialized
[    0.740958] NET: Registered protocol family 10
[    0.753409] NET: Registered protocol family 17
[    0.762371] bridge: automatic filtering via arp/ip/ip6tables has been deprecated. Update your scripts to load br_netfilter if you need this.
[    0.787379] 8021q: 802.1Q VLAN Support v1.8

Now my fix( as dirty as always 😀 )
1. modify MIWIFI-NANO.dts(I did not create new VoCore2.dts to make test easier)

+++ b/target/linux/ramips/dts/MIWIFI-NANO.dts
@@ -3,11 +3,11 @@
 /include/ "mt7628an.dtsi"
 
 / {
-       compatible = "xiaomi,MiWifi Nano", "mediatek,mt7628an-soc";
-       model = "MiWiFi Nano";
+       compatible = "vocore2,vocore", "mediatek,mt7628an-soc";
+       model = "VoCore2 64MB";
 
        chosen {
-               bootargs = "console=ttyS0,115200";
+               bootargs = "console=ttyS0,57600";
        };
 
        memory@0 {
@@ -18,7 +18,7 @@
        pinctrl {
                state_default: pinctrl0 {
                        gpio {
-                               ralink,group = "refclk", "wled", "gpio";
+                               ralink,group = "refclk", "gpio";
                                ralink,function = "gpio";
                        };
                };
@@ -87,5 +87,13 @@
                                };
                        };
                };
+
+               uart2@e00 {
+                        status = "okay";
+               };
+
+               pwm@5000 {
+                        status = "okay";
+               };
        };
 };
diff --git a/target/linux/ramips/dts/mt7628an.dtsi b/target/linux/ramips/dts/mt7628an.dtsi
index e120e56..819ac82 100644
--- a/target/linux/ramips/dts/mt7628an.dtsi
+++ b/target/linux/ramips/dts/mt7628an.dtsi
@@ -170,6 +170,8 @@
 
                        pinctrl-names = "default";
                        pinctrl-0 = <&uart0_pins>;
+
+                       status = "disabled";
                };
 
                uart1@d00 {
@@ -301,8 +303,8 @@
 
                uart2_pins: uart2 {
                        uart2 {
-                               ralink,group = "uart2";
-                               ralink,function = "uart2";
+                               ralink,group = "spis";
+                               ralink,function = "pwm";
                        };
                };

2. modify /linux-4.4.6/arch/mips/ralink/mt7620.c:407

		ralink_clk_add("10000d00.uartlite", periph_rate);
		ralink_clk_add("10000e00.uartlite", periph_rate);

change to

		ralink_clk_add("10000d00.uart1", periph_rate);
		ralink_clk_add("10000e00.uart2", periph_rate);

This just works, but I do not think it is the best way. We should use ttyS2 in dts, but not ttyS0. I still need time to understand how pinctrl works. 🙂

VoCore2: UART2 for uBoot

New VoCore2 small size blocked UART0 and UART1, so I have to use UART2 for debug.
From datasheet, we have two plans for UART2:
3A69A6BF-FDE9-4D9D-A96B-0355921A6856B1AE6949-8298-44A9-9312-C8654C9FE7E7
36FF3277-8CCF-47D0-8499-CC64C804CE15

The only valid plan for VoCore2 is SPIS_MODE.
Default uboot is using UART0 as default console port, we must change it.

MTK uboot source code already have it, we just need to modify two lines.
1. serial.h, change RT2880_UART1 in macro MT7628_ASIC_BOARD to RT2880_UART3.
This is to tell uboot, we will use UART3 control register(it is UART2 on chip).
2. serial.c, add one line in function serial_setbrg, ra_or(RALINK_SYSCTL_BASE + 0x0060, (1<<2|1<<3)); This is to change uart2 pins from gpio to real uart in system control. After this, just simply "make menuconfig", remember to choose "ETH One Port", then "make", everything will work. PS: uboot autoconf has a bug in config.in, have to change ETH_ONE_PORT_ONLY to CONFIG_ETH_ONE_PORT_ONLY.

VoCore2: Update

First, we made four versions of beta version, it is in PCB factory now. In beta version we want to pick the best performance one.

The busy days has passed finally. 🙂

Then,
Screen Shot 2016-03-29 at 10.08.56

And also the new site mockup, its backend are totally machine.. http://103.230.121.40

Last, new VoCore2+Dock ready, photo will come soon. It contains audio, tf card slot, ethernet, usb, usb2ttl on board, but just same size as current VoCore+Dock.
We also plan to make another ‘super’ version, add a 320×240 screen to it, able to run dosbox. 🙂

PS: sorry for the junk post in the forum…I must click ‘approve’ instead of ‘disapprove’ by mistake T-T

VoCore2: Wireless

c

VoCore2 wireless is finally working, but I think there still have some driver issue, looks like only one antenna works, another is still not.
Same place compare to another router HiWiFi, this one has two big antennas 🙂

a

RSSI is not as good as the one with big antenna, but TX rate is not bad. Next step is to use special device to check and adjust antenna circuit, modify factory setting part to increase antenna power output.

Beta will come soon, please email to support@vocore.io for preorder if you want to join the test. 😀

VoCore: I2S Sound Card WM8960G 4(End)

Now the tutorial continues, as I promised 🙂

1. use this firmware, download here: Test Firmware
(This firmware is just used to make sure your VoCore do not have other drivers stop you install the new one. It installed enough tools for this tutorial, so you do not have to find it online)

2. flash this firmware to your VoCore.

3. get two files here:package uncompress and upload them to VoCore /tmp/ folder.
“vocore_gdma.ko” is the driver.
“out” is the test data file, just a part of a wav file, 44100Hz, 16bits, stereo.

4. copy and run the following magic command.

i2cset -y 0 0x1a 0x1e 0x00
i2cset -y 0 0x1a 0x0e 0x02
i2cset -y 0 0x1a 0x08 0x05
i2cset -y 0 0x1a 0x68 0x07
i2cset -y 0 0x1a 0x6a 0x86
i2cset -y 0 0x1a 0x6c 0xc2
i2cset -y 0 0x1a 0x6e 0x26
i2cset -y 0 0x1a 0x32 0xc0
i2cset -y 0 0x1a 0x35 0xe1
i2cset -y 0 0x1a 0x5e 0x0c
i2cset -y 0 0x1a 0x45 0x00
i2cset -y 0 0x1a 0x4b 0x00
i2cset -y 0 0x1a 0x0a 0x00
i2cset -y 0 0x1a 0x05 0xff
i2cset -y 0 0x1a 0x07 0xff

4.1. insert driver to kernel.

insmod /tmp/vocore-gdma.ko

4.2. send data to audio buffer.

cat /tmp/out > /sys/devices/10000000.palmbus/10002800.gdma/data

5. now, everything is ready, final command to play “out”.

echo 1 > /sys/devices/10000000.palmbus/10002800.gdma/play

6. After 5, you can heard some “music” output from your headphone, just a 5.9 seconds dead loop. Call this command to stop it.

echo 0 > /sys/devices/10000000.palmbus/10002800.gdma/play

PS: the music slice is from alan, æ‚Čしみはé›Șă«çœ ă‚‹, a lovely music 🙂
PSS: the music is weird somewhere…I think I must make some mistake when setting up the wm8960…(i2cset command)

But anyway, there is some music output at last. 😀
Here is the driver source code:vocore-gdma.c

Here is app from Wutong, did not use DMA interrupts, so you can run it under user mode.
i2swrite.zip

VoCore Camera H264 FHD

[embedyt] http://www.youtube.com/watch?v=uWDr5UYh4o4[/embedyt]
PS: Sorry about first batch, the plastic dock is not matched very well, current batch fixed such problem. Please contact support@vocore.io to replace your plastic dock.
PSS: better to use 720p/15fps format or less for long time monitor usage(>= 30 minutes).

VoCore FHD H264 Camera Support

Firmware download here: Download

Source code for Linux here: uvc_3.10

Compile:
1. modify makefile

TARGET=sonix_uvcvideo
KDIR:=$YOUR_OPENWRT_PATH/build_dir/target-mipsel_24kec+dsp_uClibc-0.9.33.2/linux-ramips_rt305x/linux-3.10.49/
PWD:=$(shell pwd)

CCFLAGS += -I $(KDIR)/include/

$(TARGET)-objs  := uvc_driver.o uvc_queue.o uvc_v4l2.o uvc_video.o uvc_ctrl.o \
                  uvc_status.o uvc_isight.o uvc_debugfs.o nalu.o

obj-m:=$(TARGET).o

default:
        make $(CCFLAGS) -C $(KDIR) M=$(PWD) ARCH=mips CROSS_COMPILE=mipsel-openwrt-linux- modules
clean:
        rm -rf *.o *.ko *.mod.* modules.* Module.* .tmp_versions .*.*.cmd

2. make it to create sonix_uvcvideo.ko
3. run on VoCore

opkg install kmod-input-core kmod-video-uvc
insmod sonix_uvcvideo.ko

result:
/dev/video0 is mjpeg stream, /dev/video1 is h264 stream.
also you will find UAC, the 8K onboard microphone in /dev/ folder.

ls /dev/video*
v4l2-ctl --list-formats -d /dev/video0
v4l2-ctl --list-formats -d /dev/video1

opkg install v4l-utils

root@OpenWrt:~# v4l2-ctl --list-formats -d /dev/video0
ioctl: VIDIOC_ENUM_FMT
    Index       : 0
    Type        : Video Capture
    Pixel Format: 'MJPG' (compressed)
    Name        : MJPEG

    Index       : 1
    Type        : Video Capture
    Pixel Format: 'YUYV'
    Name        : YUV 4:2:2 (YUYV)
    
root@OpenWrt:~# v4l2-ctl --list-formats -d /dev/video1
ioctl: VIDIOC_ENUM_FMT
    Index       : 0
    Type        : Video Capture
    Pixel Format: 'H264' (compressed)
    Name        : H.264
    

VoCore Dock2: Package Update

Recently I get some complain about the broken VoCore + Dock during the shipping especially the package to US.
The post office said currently there are too many packages already exceeds their limit, so it is normal some packages are broken…:'(
All new packages will ship with a plastic case, to avoid recently “violence delivery”.
And if your dock is broken during the shipping, please email to support@vocore.io with picture, we will ship a new replacement.

9D01E798FDB1892E082F8D000C5A0F12

VoCore: Dock2 Firmware

This is the first version of the firmware
This firmware is only for dock2(with WM8960 chip at bottom)
Download at
http://vonger.cn/upload/firmware/vocore.dock2.bin

Compile by yourself:

1. clone openwrt 14.07 to your linux pc or vm.
git clone git://git.openwrt.org/14.07/openwrt.git

2. update VOCORE.dts, the following one is mine.

/dts-v1/;

/include/ "rt5350.dtsi"

/ {
	compatible = "VoCore", "ralink,rt5350-soc";
	model = "VoCore";

	palmbus@10000000 {
		gpio1: gpio@660 {
			status = "okay";
		};

		spi@b00 {
			status = "okay";

			m25p80@0 {
				#address-cells = <1>;
				#size-cells = <1>;
				compatible = "s25fl064k";
				reg = <0>;
				linux,modalias = "m25p80", "s25fl064k";
				spi-max-frequency = <10000000>;

				partition@0 {
					label = "uboot";
					reg = <0x0 0x30000>;
					read-only;
				};

				partition@30000 {
					label = "uboot-env";
					reg = <0x30000 0x10000>;
					read-only;
				};

				factory: partition@40000 {
					label = "factory";
					reg = <0x40000 0x10000>;
					read-only;
				};

				partition@50000 {
					label = "firmware";
					reg = <0x50000 0xfb0000>;
				};
			};

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

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

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

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

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

		i2s: i2s@a00 {
			compatible = "ralink,mt7620a-i2s";
			reg = <0xa00 0x100>;

			resets = <&rstctrl 17>;
			reset-names = "i2s";

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

			dmas = <&gdma 2 &gdma 3>;
			dma-names = "tx", "rx";
		};
	};

	pinctrl {
		state_default: pinctrl0 {
			gpio {
				ralink,group = "jtag", "led";
				ralink,function = "gpio";
			};

			gpio_i2s {
				ralink,group = "uartf";
				ralink,function = "gpio i2s";
			};
		};
	};

	ethernet@10100000 {
		mtd-mac-address = <&factory 0x4>;
	};

	esw@10110000 {
		ralink,portmap = <0x17>;
	};

	wmac@10180000 {
		ralink,mtd-eeprom = <&factory 0>;
	};

	ehci@101c0000 {
		status = "okay";
	};

	ohci@101c1000 {
		status = "okay";
	};

	i2c-gpio {
		compatible = "i2c-gpio";
		gpios = <&gpio0 11 0 &gpio0 14 0>;
		i2c-gpio,delay-us = <2>; /* around 400KHz */

		#address-cells = <1>;
		#size-cells = <0>;

		wm8960: wm8960@1a {
			compatible = "wm8960";
			reg = <0x1a>;
		};
	};

	audio {
		compatible = "ralink,wm8960-audio";
		model = "wm8960-audio";
		
		cpu-dai = <&i2s>;
		codec-dai = <&wm8960>;
	};

	gpio-export {
		compatible = "gpio-export";
		#size-cells = <0>;

		gpio0 {
			gpio-export,name = "gpio0";
			gpio-export,direction_may_change = <1>;
			gpios = <&gpio0 0 0>;
		};

		gpio12 {
			/* UARTF_DCD_N */
			gpio-export,name = "gpio12";
			gpio-export,direction_may_change = <1>;
			gpios = <&gpio0 12 0>;
		};
		gpio13 {
			/* UARTF_DSR_N */
			gpio-export,name = "gpio13";
			gpio-export,direction_may_change = <1>;
			gpios = <&gpio0 13 0>;
		};

		/* JTAG */
		gpio17 {
			/* JTAG_TDO */
			gpio-export,name = "gpio17";
			gpio-export,direction_may_change = <1>;
			gpios = <&gpio0 17 0>;
		};
		gpio18 {
			/* JTAG_TDI */
			gpio-export,name = "gpio18";
			gpio-export,direction_may_change = <1>;
			gpios = <&gpio0 18 0>;
		};
		gpio19 {
			/* JTAG_TMS */
			gpio-export,name = "gpio19";
			gpio-export,direction_may_change = <1>;
			gpios = <&gpio0 19 0>;
		};
		gpio20 {
			/* JTAG_TCLK */
			gpio-export,name = "gpio20";
			gpio-export,direction_may_change = <1>;
			gpios = <&gpio0 20 0>;
		};
		gpio21 {
			/* JTAG_TRST_N */
			gpio-export,name = "gpio21";
			gpio-export,direction_may_change = <1>;
			gpios = <&gpio0 21 0>;
		};

		/* ETH LEDs */
		gpio23 {
			/* ETH1_LED */
			gpio-export,name = "gpio23";
			gpio-export,direction_may_change = <1>;
			gpios = <&gpio1 1 0>;
		};
		gpio24 {
			/* ETH2_LED */
			gpio-export,name = "gpio24";
			gpio-export,direction_may_change = <1>;
			gpios = <&gpio1 2 0>;
		};
		gpio25 {
			/* ETH3_LED */
			gpio-export,name = "gpio25";
			gpio-export,direction_may_change = <1>;
			gpios = <&gpio1 3 0>;
		};
	};

	gpio-leds {
		compatible = "gpio-leds";
		status {
			label = "vocore:green:status";
			gpios = <&gpio1 0 0>;
		};
		eth {
			label = "vocore:orange:eth";
			gpios = <&gpio1 4 0>;
		};
	};
};

3. Setup dma driver, add dma.mk to [openwrt]/package/kernel/linux/modules/

DMA_MENU:=DMA support


define KernelPackage/ralink-gdma
  TITLE:=Ralink GDMA driver
  SUBMENU:=$(DMA_MENU)
  KCONFIG:= \
        CONFIG_DMADEVICES=y \
	CONFIG_DMA_ENGINE=y \
        CONFIG_DMA_VIRTUAL_CHANNELS \
        CONFIG_DMA_RALINK 
  FILES:= \
        $(LINUX_DIR)/drivers/dma/virt-dma.ko \
        $(LINUX_DIR)/drivers/dma/ralink-gdma.ko
  AUTOLOAD:=$(call AutoLoad,11,ralink-gdma)
endef

define KernelPackage/ralink-gdma/description
 Kernel module for Ralink GDMA device support
endef

$(eval $(call KernelPackage,ralink-gdma))

4. Setup ALSA DMA
Whatever I do to the makefile/config, still two files can not be compiled, no idea what is wrong.
They are $LINUX/sound/soc/soc-dmaengine-pcm.c soc-generic-dmaengine-pcm.c
I have to force them to be compiled.

4.1. modify $LINUX/sound/Kconfig, comment that ifneq and endif.

#ifneq ($(CONFIG_SND_SOC_DMAENGINE_PCM),)
snd-soc-core-objs += soc-dmaengine-pcm.o
#endif

#ifneq ($(CONFIG_SND_SOC_GENERIC_DMAENGINE_PCM),)
snd-soc-core-objs += soc-generic-dmaengine-pcm.o
#endif

4.2. modify $OPENWRT/target/linux/ramips/rt305x/config-3.10 to force it compiled.
add two line at end of it.

CONFIG_SND_SOC_DMAENGINE_PCM=y
CONFIG_SND_SOC_GENERIC_DMAENGINE_PCM=y

5. Setup ALSA WM8960/I2S driver.
modify $OPENWRT/target/linux/ramips/modules.mk
@TARGET_ramips_mt7620a to @TARGET_ramips, so it will show not only MT7620a kernel but also in RT5350.

define KernelPackage/sound-mt7620
  TITLE:=MT7620 PCM/I2S Alsa Driver
  DEPENDS:=@TARGET_ramips +kmod-sound-soc-core +kmod-regmap
  KCONFIG:= \
        CONFIG_SND_MT7620_SOC_I2S \
        CONFIG_SND_MT7620_SOC_WM8960
  FILES:= \
        $(LINUX_DIR)/sound/soc/ralink/snd-soc-mt7620-i2s.ko \
        $(LINUX_DIR)/sound/soc/ralink/snd-soc-mt7620-wm8960.ko \
        $(LINUX_DIR)/sound/soc/codecs/snd-soc-wm8960.ko
  AUTOLOAD:=$(call AutoLoad,90,snd-soc-wm8960 snd-soc-mt7620-i2s snd-soc-mt7620-wm8960)
  $(call AddDepends/sound)
endef

define KernelPackage/sound-mt7620/description
 Alsa modules for ralink i2s controller.
endef

$(eval $(call KernelPackage,sound-mt7620))

6. Now, everything is ready. make menuconfig
Select in Kernel modules:
add I2C support/kmod-i2c-gpio-custom;
del I2C support/kmod-i2c-ralink;
add DMA support/kmod-ralink-gdma
add Sound support/kmod-sound-mt7620

7. That’s all, make V=s, build the bin file.

Later I will do more test on this firmware, dma, i2c and i2s works well in this firmware.

Drivers works:

root@OpenWrt:/dev# ls
audio               i2c-0               mtd0ro              mtd3ro              mtdblock1           network_throughput  shm                 urandom
bus                 kmsg                mtd1                mtd4                mtdblock2           null                snd                 watchdog
console             log                 mtd1ro              mtd4ro              mtdblock3           ppp                 spidev32766.1       watchdog0
cpu_dma_latency     mem                 mtd2                mtd5                mtdblock4           ptmx                tty                 zero
dsp                 mixer               mtd2ro              mtd5ro              mtdblock5           pts                 ttyS0
full                mtd0                mtd3                mtdblock0           network_latency     random              ttyS1
root@OpenWrt:/dev# cd snd
root@OpenWrt:/dev/snd# ls
controlC0  pcmC0D0c   pcmC0D0p   timer

root@OpenWrt:/dev/snd# lsmod
arc4                    1312  2 
cfg80211              197639  2 rt2x00lib
compat                  2285  3 rt2800soc
crc_ccitt               1019  2 rt2800lib
crc_itu_t               1019  0 
crypto_blkcipher       10375  1 arc4
eeprom_93cx6            1807  0 
ehci_hcd               29964  1 ehci_platform
ehci_platform           2272  0 
gpio_button_hotplug     5984  0 
i2c_algo_bit            4538  1 i2c_gpio
i2c_core               15054  6 snd_soc_wm8960
i2c_dev                 4064  0 
i2c_gpio                2400  0 
input_core             24281  1 snd
ip6_tables              8993  3 ip6table_raw
ip6t_REJECT             2336  2 
ip6table_filter          608  1 
ip6table_mangle         1024  1 
ip6table_raw             576  1 
ip_tables               9165  4 iptable_nat
ipt_MASQUERADE          1136  1 
ipt_REJECT              1776  2 
iptable_filter           672  1 
iptable_mangle           928  1 
iptable_nat             1680  1 
iptable_raw              640  1 
ipv6                  238854 26 ip6t_REJECT
leds_gpio               2944  0 
lzo_compress            2082  1 regmap_core
lzo_decompress          1351  1 regmap_core
mac80211              344225  3 rt2800lib
nf_conntrack           44715 13 iptable_nat
nf_conntrack_ftp        5136  1 nf_nat_ftp
nf_conntrack_ipv4       4676  8 
nf_conntrack_ipv6       4976  3 
nf_conntrack_irc        2784  1 nf_nat_irc
nf_defrag_ipv4           758  1 nf_conntrack_ipv4
nf_defrag_ipv6          8695  1 nf_conntrack_ipv6
nf_nat                  9759  7 iptable_nat
nf_nat_ftp              1216  0 
nf_nat_ipv4             2526  1 iptable_nat
nf_nat_irc              1008  0 
nls_base                5006  1 usbcore
of_i2c                  1344  1 i2c_gpio
ohci_hcd               13360  0 
ppp_async               6176  0 
ppp_generic            19650  3 pppoe
pppoe                   7744  0 
pppox                   1338  1 pppoe
ralink_gdma             4032  2 
regmap_core            25039  4 snd_soc_wm8960
regmap_i2c               966  2 snd_soc_wm8960
regmap_spi              1078  1 snd_soc_core
rt2800lib              91441  2 rt2800soc
rt2800mmio              6338  1 rt2800soc
rt2800soc               2464  0 
rt2x00lib              34047  5 rt2800soc
rt2x00mmio              1952  2 rt2800soc
rt2x00soc               1218  1 rt2800soc
slhc                    4347  1 ppp_generic
snd                    39083 10 snd_soc_wm8960
snd_compress            6175  1 snd_soc_core
snd_hwdep               4302  0 
snd_mixer_oss          12393  1 snd_pcm_oss
snd_page_alloc          3249  1 snd_pcm
snd_pcm                56509  2 snd_soc_core
snd_pcm_oss            33553  0 
snd_rawmidi            14995  0 
snd_seq_device          4301  1 snd_rawmidi
snd_soc_core           91031  3 snd_soc_mt7620_wm8960
snd_soc_mt7620_i2s      2896  2 
snd_soc_mt7620_wm8960    2048  0 
snd_soc_wm8960         16944  1 
snd_timer              14382  1 snd_pcm
soundcore               3788  1 snd
usb_common              1160  1 usbcore
usbcore               106727  3 ohci_hcd
virt_dma                1333  1 ralink_gdma
x_tables               10997 26 ipt_MASQUERADE
xt_CT                   2272  0 
xt_LOG                  9552  0 
xt_REDIRECT             1056  0 
xt_TCPMSS               2704  2 
xt_comment               480 53 
xt_conntrack            2144 10 
xt_id                    480  0 
xt_limit                 992 20 
xt_mac                   608  0 
xt_mark                  672  0 
xt_multiport            1200  0 
xt_nat                  1072  0 
xt_state                 688  0 
xt_tcpudp               1712  8 
xt_time                 1664  0 

root@OpenWrt:/sys/class/dma# ls
dma0chan0   dma0chan1   dma0chan10  dma0chan11  dma0chan12  dma0chan13  dma0chan14  dma0chan15  dma0chan2   dma0chan3   dma0chan4   dma0chan5   dma0chan6   dma0chan7   dma0chan8   dma0chan9

root@OpenWrt:/proc# cat interrupts
           CPU0       
  5:        203      MIPS  10100000.ethernet
  6:     229856      MIPS  rt2800_wmac
  7:     353640      MIPS  timer
  9:          0      INTC  10000100.timer
 15:        121      INTC  10002800.gdma
 20:         30      INTC  serial
 25:          1      INTC  esw
 26:          1      INTC  ehci_hcd:usb1, ohci_hcd:usb2
ERR:          0

ralink-gdma.c might have a bug, once I remove the log output, it will not trigger 10002800.gdma interrupts, very weird.

VoCore: Audio Driver

Special thanks to Guangqian Luo. When I am debugging my linux audio driver, he notified me there already exists source code in linux kernel/ALSA and it really works. He is using the right way doing the work but I am not 😀 I am reinventing the wheel…ALSA exists code is much better than mine.

To make WM8960 work, we need five necessary parts:
1. I2C interface, used to transfer command to WM8960.
2. I2S interface, used to transfer data to WM8960.
3. WM8960 driver, used to call I2S, I2C driver.
4. ALSA middle layer driver, used to connect user and kernel.
5. DMA interface, used to smooth data transfer between software and hardware.

1. I2C part, that is easy, we use i2c-gpio, based on gpio 11,14.
add these lines to VOCORE.dts, root part.

        i2c-gpio {
                compatible = "i2c-gpio";
                gpios = <&gpio0 11 0 &gpio0 14 0>;
                i2c-gpio,delay-us = <2>; /* around 400KHz */

                #address-cells = <1>;
                #size-cells = <0>;

                wm8960: wm8960@1a {
                        compatible = "wm8960";
                        reg = <0x1a>;
                };
        };

2. I2S interface, source code already there, in [kernel]/sound/soc/ralink/mt7620-i2s.c
This is for MT7620, but I checked datasheet, the register of MT7620 and RT5350 are 99% same, only one bit is not same but nothing matter.

3. WM8960 driver.
[kernel]/sound/soc/codecs/wm8960.c

4. ALSA driver.
[kernel]/sound/soc/ralink/mt7620-wm8960.c

5. DMA driver.
[kernel]/drivers/dma/ralink-gdma.c

Haha, the codes are clean and stable(OpenWRT 14.07, Linux 3.10.49), looks like my code is useless now, maybe later it can be used to help starter learn kernel driver.

I will base on the exists source make a new firmware soon.