Table of Contents

Driver Porting and Configuration

Porting I/O Control Driver

The I/O control driver is built as a module, can be used for controlling common peripherals, such as LED, push button, buzzer.

Copy io_control_dev to your ubuntu system, compile it with your own system setting (refer to Appendix 1 "Compiling Driver Module"), and copy the generated io_control.ko file to the board, use the following command to load the driver module:

$insmod  io_control.ko

Now you can start to try the I/O control API demo (refer to Appendix 2 "Running API Demo").

The buzzer can be shut up via configuring the related I/O port. Config the script.fex as follows:

[lcd0_para]
lcd_gpio_0 = port:PH15<0><0><default><default>

Then convert it into script.bin format by using fex2bin, and replace the earlier script.bin on the board. (for more info, refer to the document Prepare for Kernel and Drivers Porting Reboot the system to apply new configuration.

Porting Dallas’s 1-wire Driver

Config the Kernel

Config the kernel to include Dallas’s 1-wire(DS18B20) driver. Under the root directory, enter the following commnad:

#make menuconfig

(All the make menuconfig that follows in this document, is executed under root directory)

Config as follows:

Device Drivers  --->
<*> Dallas's 1-wire support  --->
    1-wire Bus Masters  --->
        <*> GPIO 1-wire busmaster
    1-wire Slaves  --->
        <*> Thermal family implementation

Save and exit, re-compile the kernel:

#make uImage

Replace the earlier uImage on the board with the new generated uImage under arch/arm/boot/ directory via NFS. (for more info, refer to the document Prepare for Kernel and Drivers Porting

Config the script.fex

Config the script.fex as follows, add the [w1_para] setting:

[w1_para]
w1_used = 1
w1_pin = port:PB10<1><default><default><default>

Then convert it into script.bin format by using fex2bin, and replace the earlier script.bin on the board. (for more info, refer to the document Prepare for Kernel and Drivers Porting

Reboot the system, insert the DS18B20 device.

Copy ds18b20_dev to your ubuntu system, compile it with your own system setting (refer to Appendix 1 "Compiling Driver Module"), and copy the generated w1-sun4i.ko file to the board, use the following command to load the driver:

$insmod  w1-sun4i.ko

Enter the /sys/bus/w1/devices/w1_bus_master1 directory, there's a folder with the name preceding with "28-", which represents the DS18B20 device. The 28 means the current temperature sensor is DS18B20, the characters/numbers string follows stands for the device unique ID. Enter the folder, you should find it's device file named w1_slave, to get current temperature, enter this command on the terminal:

$cat w1_slave

As shown in the picture below:

documentations-6_1.jpg

Porting I2C Bus Driver

Config the Kernel

Config the kernel to include I2C bus driver:

#make menuconfig 
Device Drivers  --->
{*} I2C support  --->
  	  I2C Hardware Bus support  --->
     	  <*> Allwinner Technology SUNXI I2C interface

Save and exit. Comment out lines 914 to 918 of the i2c-sunxi.c file, which is located in drivers/i2c/busses directory, as follows:

914 /*  else if (ret != num){
915         printk("incomplete xfer (0x%x)\n", ret);
916         ret = -ECOMM;
917         //dev_dbg(i2c->adap.dev, "incomplete xfer (%d)\n", ret); 918     }*/

Save, and re-compile the kernel:

#make uImage

Replace the earlier uImage on the board with the new generated uImage under arch/arm/boot/ directory via NFS. (for more info, refer to the document <4. Prepare for Kernel and Drivers Porting>)

Config the script.fex

Our AT24/FM24 module can be used to test the I2C driver, which is connected to the I2C1 controller. Therefore, config the [twi1_para] setting in the script.fex as follows:

[twi1_para]
twi1_used = 1
twi1_scl = port:PB18<2><default><default><default>
twi1_sda = port:PB19<2><default><default><default>

Then convert it into script.bin format by using fex2bin, and replace the earlier script.bin on the board. (for more info, refer to the document Prepare for Kernel and Drivers Porting

Reboot the system.

For more info about testing the AT24/FM24 module, like reading/writing data, please refer to the document DVK521 User Manual and Appendix 2 "Running API Demo".

Porting SPI Devices Driver

Config the Kernel

The A20 SPI is not natively supported by linux-sunxi-sunxi-3.4.61 kernel. You should copy the spi-sun7i.c file spi-sun7i.c to the drivers/spi directory in the kernel, and modify the related Makefile and Kconfig under the same directory.

Add the following line in Makefile:

obj-$(CONFIG_SPI_SUN7I)         += spi-sun7i.o

Add the following line in Kconfig:

config SPI_SUN7I
   tristate "SUN7I SPI Controller"
   depends on ARCH_SUN7I
   help
       Allwinner Soc SPI controller,present on SUN7I chips.
       
config SUN7I_SPI_NDMA
    bool "SUN7I SPI Normal DMA mode select"
    depends on SPI_SUN7I
    help
       This selects SPI DMA mode with DMA transfer
       Y select NDMA mode and N select DDMA mode
#make menuconfig
Device Drivers  --->
[*] SPI support  --->
    <*>   SUN7I SPI Controller
[*]     SUN7I SPI Normal DMA mode select
<*>   DesignWare SPI controller core support 
<*>   User mode SPI device driver support

Save and exit, re-compile the kernel:

#make uImage

Replace the earlier uImage on the board with the new generated uImage under arch/arm/boot/ directory via NFS. (for more info, refer to the document Prepare for Kernel and Drivers Porting

Config the script.fex

Our SPI module AT45DBXX DataFlash Board is connected to the SPI0 controller, therefore, config the [spi0_para], [spi_devices], and [spi_board0] settings in the script.fex as follows:

[spi0_para]
spi_used = 1
spi_cs_bitmap = 1
spi_cs0 = port:PI10<2><default><default><default>
spi_cs1 = port:PI14<2><default><default><default>
spi_sclk = port:PI11<2><default><default><default>
spi_mosi = port:PI12<2><default><default><default>
spi_miso = port:PI13<2><default><default><default>
[spi_devices]
spi_dev_num = 1
[spi_board0]
modalias = "spidev"
max_speed_hz = 12000000
bus_num = 0
chip_select = 0
mode = 3
full_duplex = 0
manual_cs = 0

Then convert it into script.bin format by using fex2bin, and replace the earlier script.bin on the board. (for more info, refer to the document Prepare for Kernel and Drivers Porting

Now the kernel and script.fex configuration for SPI device have completed, the last step is to load the io_control.ko driver module (refer to the previous section " Porting I/O Control Driver").

Reboot the system.

Now you can use the AT45DBXX DataFlash Board to test the SPI driver (refer to Appendix 2 "Running API Demo").

Porting LCD Driver

Config the Kernel

The LCD driver support has been included in linux-sunxi-sunxi-3.4.61, the driver file can be found on drivers/video/sunxi/lcd.

Check the kernel configuration, confirm that the driver is included:

#make menuconfig
Device Drivers  --->
Graphics support  --->
{*} Support for frame buffer devices  --->
<*>   DISP Driver Support(sunxi)
-*-     Reserve memory block for sunxi/fb
[*]     Enable FB/UMP Integration
<*>    LCD Driver Support(sunxi)
<*>       HDMI Driver Support(sunxi)

Save and exit, re-compile the kernel:

#make uImage

Replace the earlier uImage on the board with the new generated uImage under arch/arm/boot/ directory via NFS. (for more info, refer to the document Prepare for Kernel and Drivers Porting

Config the script.fex

The A20 supports two channel video output, however, only LCD0 is available on Cubieboard, therefore, we connect the 7inch capacitive LCD to the LCD0 controller.

Config the script.fex, [dis_init] setting for display device initialization, and [lcd0_para] setting for LCD parameters (depending on the specifications of concrete LCD), as follows:

[disp_init]
disp_init_enable = 1
disp_mode = 0
screen0_output_type = 1
screen0_output_mode = 4
screen1_output_type = 0
screen1_output_mode = 4
fb0_width = 1024
fb0_height = 768
fb0_framebuffer_num = 2
fb0_format = 10
fb0_pixel_sequence = 0
fb0_scaler_mode_enable = 0
fb1_width = 1024
fb1_height = 768
fb1_framebuffer_num = 2
fb1_format = 10
fb1_pixel_sequence = 0
fb1_scaler_mode_enable = 0
lcd0_backlight = 197
lcd1_backlight = 197
lcd0_bright = 50
lcd0_contrast = 50
lcd0_saturation = 57
lcd0_hue = 50
lcd1_bright = 50 
lcd1_contrast = 50
lcd1_saturation = 57
lcd1_hue = 50
[lcd0_para]
lcd_used = 1
lcd_x = 800 
lcd_y = 480
lcd_dclk_freq = 33
lcd_pwm_not_used = 0
lcd_pwm_ch = 0
lcd_pwm_freq = 10000
lcd_pwm_pol = 0
lcd_max_bright = 240
lcd_min_bright = 64
lcd_if = 0
lcd_hbp = 215
lcd_ht = 1055
lcd_vbp = 34
lcd_vt = 1050
lcd_vspw = 3
lcd_hspw = 20
lcd_hv_if = 0
lcd_hv_smode = 0
lcd_hv_s888_if = 0
lcd_hv_syuv_if = 0
lcd_lvds_ch = 0
lcd_lvds_mode = 0
lcd_lvds_bitwidth = 0
lcd_lvds_io_cross = 0
lcd_cpu_if = 0
lcd_frm = 1
lcd_io_cfg0 = 0
lcd_gamma_correction_en = 0
lcd_gamma_tbl_0 = 0x0
lcd_gamma_tbl_1 = 0x10101
lcd_gamma_tbl_255 = 0xffffff
lcd_bl_en_used = 1
lcd_bl_en = port:PH07<1><0><default><1>
lcd_power_used = 1
lcd_power = port:PH08<1><0><default><1>
lcd_pwm_used = 1
lcd_pwm = port:PB02<2><0><default><default>
lcd_gpio_0 = port:PH15<0><0><default><default>
lcd_gpio_1 =
lcd_gpio_2 =
lcd_gpio_3 =
lcdd0 = port:PD00<2><0><default><default>
lcdd1 = port:PD01<2><0><default><default>
lcdd2 = port:PD02<2><0><default><default>
lcdd3 = port:PD03<2><0><default><default>
lcdd4 = port:PD04<2><0><default><default>
lcdd5 = port:PD05<2><0><default><default>
lcdd6 = port:PD06<2><0><default><default>
lcdd7 = port:PD07<2><0><default><default>
lcdd8 = port:PD08<2><0><default><default>
lcdd9 = port:PD09<2><0><default><default>
lcdd10 = port:PD10<2><0><default><default>
lcdd11 = port:PD11<2><0><default><default>
lcdd12 = port:PD12<2><0><default><default>
lcdd13 = port:PD13<2><0><default><default>
lcdd14 = port:PD14<2><0><default><default>
lcdd15 = port:PD15<2><0><default><default>
lcdd16 = port:PD16<2><0><default><default>
lcdd17 = port:PD17<2><0><default><default>
lcdd18 = port:PD18<2><0><default><default>
lcdd19 = port:PD19<2><0><default><default>
lcdd20 = port:PD20<2><0><default><default>
lcdd21 = port:PD21<2><0><default><default>
lcdd22 = port:PD22<2><0><default><default>
lcdd23 = port:PD23<2><0><default><default>
lcdclk = port:PD24<2><0><default><default>
lcdde = port:PD25<2><0><default><default>
lcdhsync = port:PD26<2><0><default><default>
lcdvsync = port:PD27<2><0><default><default>

Then convert it into script.bin format by using fex2bin, and replace the earlier script.bin on the board. (for more info, refer to the document <4. Prepare for Kernel and Drivers Porting>)

Reboot the system, the LCD should be ready to work.

Porting CTP Driver

Config the Kernel

Our capacitive touch screen integrates FT5206 as the touch controller, and the related driver file is ft5x_ts.c. Unfortunately the original ft5x_ts.c in linux-sunxi-sunxi-3.4.61 kernel doesn’t support A20, therefore, copy the new ft5x_ts.c ft5x_ts.c to the drivers/input/touchscreen directory in kernel and replace the original one. Besides, the touch screen interrupt pin ctp_int_port requires GPIO interrupts, make sure the GPIO driver is included when configuring.

Config the Kernel to include touchscreen driver:

#make menuconfig
Device Drivers  --->
Input device support  --->
[*]   Touchscreens  --->
<*>   ft5x touchscreen driver

Device Drivers  --->
[*] GPIO Support  --->
<*>   GPIO Support for sunxi platform

Re-compile the kernel:

#make uImage

Replace the earlier uImage on the board with the new generated uImage under arch/arm/boot/ directory via NFS. (for more info, refer to the document Prepare for Kernel and Drivers Porting

Config the script.fex

Since the touch screen is connected to I2C1 controller, make sure the I2C driver has been ported (refer to the previous section "Porting I2C Bus Driver"). Config the [ctp_para],[ctp_list_para],and[gpio_para] setting in script.fex.

ctp_name:driver name
ctp_twi_id:I2C controller which is actually used
ctp_twi_addr:I2C device address (7bit)
ctp_screen_max_x:touch panel resolution
ctp_screen_max_y:touch panel resolution
ctp_revert_x_flag:set 1 to revert x axis
ctp_revert_y_flag:set 1 to revert y axis
ctp_exchange_x_y_flag:set 1 to exchange x axis and y axis
ctp_int_port:touch interrupt pin
ctp_wakeup:touch wakeup pin
ctp_io_port:interrupt pin configuration

According to the specifications and hardware connection of our 7inch capacitive LCD, config as follows:

[ctp_para]
ctp_used = 1
ctp_name = "ft5x_ts"
ctp_twi_id = 1
ctp_twi_addr = 0x38
ctp_screen_max_x = 800
ctp_screen_max_y = 480
ctp_revert_x_flag = 0
ctp_revert_y_flag = 1
ctp_exchange_x_y_flag = 0
ctp_firm = 1
ctp_wakeup = port:PB13<1><default><default><1>

[ctp_list_para]
ctp_det_used = 1
ft5x_ts = 1
gt82x = 0
gslX680 = 0
gt9xx_ts = 0
gt811 = 0

[gpio_para]
gpio_pin_3 = port:PH07<6><default><default><default> 

Then convert it into script.bin format by using fex2bin, and replace the earlier script.bin on the board. (for more info, refer to the document Prepare for Kernel and Drivers Porting

Connect the 7inch capacitive LCD, reboot the system, try to touch the icons on the screen.

Porting VGA Driver

VAG driver has been includes in the kernel, just config the script.fex directly:

[disp_init]
disp_init_enable = 1
disp_mode = 0
screen0_output_type = 4
screen0_output_mode = 4
screen1_output_type = 0
screen1_output_mode = 4
fb0_width = 1024
fb0_height = 768
fb0_framebuffer_num = 2
fb0_format = 10
fb0_pixel_sequence = 0
fb0_scaler_mode_enable = 0
fb1_width = 1024
fb1_height = 768
fb1_framebuffer_num = 2
fb1_format = 10
fb1_pixel_sequence = 0
fb1_scaler_mode_enable = 0
lcd0_backlight = 197
lcd1_backlight = 197
lcd0_bright = 50
lcd0_contrast = 50
lcd0_saturation = 57
lcd0_hue = 50
lcd1_bright = 50
lcd1_contrast = 50
lcd1_saturation = 57
lcd1_hue = 50

Then convert it into script.bin format by using fex2bin, and replace the earlier script.bin on the board. (for more info, refer to the document <4. Prepare for Kernel and Drivers Porting>) Reboot the system, now the VGA can be used for displaying.

Porting HDMI Driver

HDMI driver has been includes in the kernel, just config the script.fex directly:

[disp_init]
disp_init_enable = 1
disp_mode = 0
screen0_output_type = 3
screen0_output_mode = 5
screen1_output_type = 0
screen1_output_mode = 4
fb0_width = 1024
fb0_height = 768
fb0_framebuffer_num = 2
fb0_format = 10
fb0_pixel_sequence = 0
fb0_scaler_mode_enable = 0
fb1_width = 1024
fb1_height = 768
fb1_framebuffer_num = 2
fb1_format = 10
fb1_pixel_sequence = 0
fb1_scaler_mode_enable = 0
lcd0_backlight = 197
lcd1_backlight = 197
lcd0_bright = 50
lcd0_contrast = 50
lcd0_saturation = 57
lcd0_hue = 50
lcd1_bright = 50
lcd1_contrast = 50
lcd1_saturation = 57
lcd1_hue = 50

Reboot the system, now the HDMI can be used for displaying.

Porting CSI Driver

Config the Kernel

#make menuconfig
Device Drivers  --->
   <*> Multimedia support  --->
      <*>   Video For Linux
      [*]   CSI Driver Config for sun4i  --->
          <M>   OmniVision OV7670 sensor support

Built the camera driver as module, save and exit.

Comment out the print messages in the s32 img_sw_para_to_reg(u8 type, u8 mode, u8 value) function in disp_layer.c file, which is under drivers/video/sunxi/disp directory.

Lines 95 to 99:

95 /*      else {
96            DE_WRN("not supported yuv channel format:%d in "
97                    "img_sw_para_to_reg\n", value);
98             return 0;
99         }*/

Lines 125 to 129:

125 /*      else {
126         DE_WRN("not supported yuv channel pixel sequence:%d "
127                    "in img_sw_para_to_reg\n", value);
128             return 0;
129         }*/

Lines 168 to 172:

168 /*      else {
169          DE_WRN("not supported image0 pixel sequence:%d in "
170                    "img_sw_para_to_reg\n", value);
171             return 0;
172         }*/

Line 175:

175 //  DE_WRN("not supported type:%d in img_sw_para_to_reg\n", type);

Save, re-compile the kernel:

#make uImage

Compile the kernel modules:

#make modules

Install the kernel modules:

#make modules_install

The installation copies the compiled kernel module from the kernel source code to the ubuntu /lib/modules directory.

The related driver module files include: videobuf-core.ko, videobuf-dma-contig.ko, sun4i_csi1.ko, ov7670.ko, which are located respectively in:

videobuf-core.ko, videobuf-dma-contig.ko:
/lib/modules/3.4.61+/kernel/drivers/media/video
ov7670.ko:
/lib/modules/3.4.61+/kernel/drivers/media/video/sun4i_csi/device
sun4i_csi1.ko:
/lib/modules/3.4.61+/kernel/drivers/media/video/sun4i_csi/csi1

Replace the earlier uImage on the board with the new generated uImage under arch/arm/boot/ directory via NFS. (for more info, refer to the document Prepare for Kernel and Drivers Porting

Copy the above 4 driver files to the board, and install them in order:

$insmod  videobuf-core.ko
$insmod  videobuf-dma-contig.ko
$insmod  ov7670.ko
$insmod  sun4i_csi1.ko

Note: please pay attention to the installing order, camera driver should be installed before sun4i_csi1.ko.

Config the script.fex

Since our OV7670 camera is connected to the CSI1 controller, config the [csi1_para] and [camera_list_para] setting in script.fex. The suffix _b in the parameter name indicates that this is a secondary camera parameter while two cameras were connected to the same CSI.

The parameters are interpreted as follows:

csi_used = xx:enable/disable csi0 or csi1
csi_mode = xx:CSI receiver buffer mode:
0:a stand-alone buffer for each CSI receiver 
1:a shared buffer for both CSI receiver
csi_dev_qty = xx:CSI device quantity, 1 or 2
csi_stby_mode = xx:standby power statue
0:power on when standby
1:power off when standby 
csi_mname = “xxx”: CSI module name, matches with the driver, valid option includes: ov7670/gc0308/gt2005/hi704/sp0338/mt9m112/gc0307/mt9m113/mt9d112/hi253/ov5640 
csi_twi_id = xx:I2C
csi_twi_addr = xx:I2C address
csi_if = xx:interface timing:
0:8bit data line, with Hsync,Vsync 
1:16bit data line, with Hsync,Vsync 
2:24bit data line, with Hsync,Vsync 
3:8bit data line, BT656 embedded sync, single-channel
4:8bit data line, BT656 embedded sync, dual-channels
5:8bit data line, BT656 embedded sync, four-channels
csi_vflip = xx:video vertical flip
0:normal
1:flip
csi_hflip = xx:video horizontal flip
0:normal
1:flip
csi_iovdd = "", csi_avdd = "", and csi_dvdd = "": power supply of the camera module's IO, Analog, and Core.
"axp20_pll": powering from AXP20 LDO3
"axp20_hdmi": powering from AXP20 LDO4
"": powering from other source
csi_flash_pol = xx:flash polarity for cameras that feature flash IO control
0: flash lights when IO low level
1: flash lights when IO high level
csi_pck = xx:GPIO configuration for clock signal from module to CSI
csi_ck = xx:GPIO configuration for clock signal from CSI to module
csi_hsync = xx:GPIO configuration for horizontal sync signal from module to CSI
csi_vsync = xx:GPIO configuration for vertical sync signal from module to CSI
csi_d0 = xx to csi_d15 = xx:GPIO configuration for 8bit/16bit data from module to CSI
csi_reset = xx:GPIO configuration for module reset 
csi_power_en = xx:GPIO configuration for module power, high active by default
csi_stby = xx:GPIO configuration for module standby
csi_af_en = xx:GPIO configuration for module AF power

The details configuration:

[csi1_para]
csi_used = 1
csi_dev_qty = 1
csi_stby_mode = 0
csi_mname = "ov7670"
csi_if = 0
csi_iovdd = "axp20_pll"
csi_avdd = ""
csi_dvdd = ""
csi_vol_iovdd = 2800
csi_vol_dvdd =
csi_vol_avdd =
csi_vflip = 1
csi_hflip = 0
csi_flash_pol = 1
csi_facing = 1
csi_twi_id = 1
csi_twi_addr = 0x42
csi_pck = port:PG00<3><default><default><default>
csi_ck = port:PG01<3><default><default><default>
csi_hsync = port:PG02<3><default><default><default>
csi_vsync = port:PG03<3><default><default><default>
csi_d0 = port:PG04<3><default><default><default>
csi_d1 = port:PG05<3><default><default><default>
csi_d2 = port:PG06<3><default><default><default>
csi_d3 = port:PG07<3><default><default><default>
csi_d4 = port:PG08<3><default><default><default>
csi_d5 = port:PG09<3><default><default><default>
csi_d6 = port:PG10<3><default><default><default>
csi_d7 = port:PG11<3><default><default><default>
csi_reset = port:PH13<1><default><default><0>
csi_power_en = port:PH16<1><default><default><0>
csi_stby = port:PH19<1><default><default><0>
[camera_list_para]
camera_list_para_used = 1
ov7670 = 1
gc0308 = 0
gt2005 = 0
hi704 = 0
sp0838 = 0
mt9m112 = 0
mt9m113 = 0
ov2655 = 0
hi253 = 0
gc0307 = 0
mt9d112 = 0
ov5640 = 0
gc2015 = 0
ov2643 = 0
gc0329 = 0
gc0309 = 0
tvp5150 = 0
s5k4ec = 0
ov5650_mv9335 = 0
siv121d = 0
gc2035 = 0

Then convert it into script.bin format by using fex2bin, and replace the earlier script.bin on the board. (for more info, refer to the document Prepare for Kernel and Drivers Porting

Connect the OV7670 camera module and the LCD to the board, reboot the system.

Now you can start to try the camera API demo (refer to Appendix 2 "Running API Demo").

Appendix 1: Compiling Driver Module

The provided xx.ko files under Driver is compiled to run on our system image only.

If the drivers are going to being loaded on your own system, they need to be re-compiled according to you system kernel path.

Use the io_control_dev.ko for demonstration.

1.1 Copy the io_control_dev to ubuntu, assume the target directory is /home/waveshare/cubieboard2/waveshare_demo/driver . Modify the files permission:

#cd /home/waveshare/cubieboard2/waveshare_demo/driver/io_control_dev

a20_6_1.jpg

#chmod 777 ./*

1.2 Modify the Makefile

#vi Makefile

a20_6_2.jpg

Assign the KERNELDIR according to your actual kernel path.

1.3 Clear the old files

#make clean

a20_6_3.jpg

1.4 Compile

#make

An error might occur while compiling:

io_control.c:1:23: fatal error: linux/init.h: No such file or directory
compilation terminated.
make: *** [modules] Error 1

As shown in the picture below:

a20_6_4.jpg

It is caused by the different kernel version, can be just omitted. a20_6_5.jpg

Copy the new generated io_control.ko file to your own system and load it.

Appendix 2 "Running API Demo"

When the driver has been loaded, you can start to try the API demo.

Copy the API source code to your ubuntu, and modify the files permission:

#chmod 777 ./*

Execute the following command to compile:

#make

Then copy the executable file to the board, say, "test_led", use the following command to run it:

#./ test_led