注:本文参考了韦东山设备树视频和pengdonglin的博客讓TQ2440也用上設備樹(1),只用于学习记录。
????在前面的博客Linux设备树学习笔记(三、修改uboot、linux-4.15内核在JZ2440使用设备树)记录过设备树在JZ2440的简单使用,但是后来学到gpio、pinctrl子系统发现在使用
注:本次的移植是在前前面的博客Linux设备树学习笔记(三、修改uboot、linux-4.15内核在JZ2440使用设备树)的基础上进行的,即已修改uboot支持设备树、修改好uboot、kernel分区。
1. 添加设备树文件
(1) 进入内核linux-4.15的目录arch/arm/boot/dts查看发现并没有支持2440的设备树文件,最接近的也就只有2416的设备树。于是,我们可以仿照s3c2416的添加JZ2440的设备树文件,把s3c2416.dtsi、s3c2416-pinctrl.dtsi、s3c2416-smdk2416.dts分别复制为s3c2440.dtsi、s3c2440-pinctrl.dtsi、s3c2440-jz2440.dts,下面是设备树的结构:
1 2 3 4 5 | s3c2440-jz2440.dts ----> s3c2440.dtsi ----> s3c24xx.dtsi ----> skeleton.dtsi ----> s3c2440-pinctrl.dtsi |
上面的文件介绍:
① skeleton.dtsi 存放的是一个设备树必备的一些基本属性;
② s3c24xx.dtsi 中存放的是整个s3c24xx系列SoC公共的一些属性,如中段控制器、串口、看门狗、RTC、I2C控制器等等;
③ s3c2440-pinctrl.dtsi 存放的是s3c2440这款SoC中GPIO控制器、外部中断控制器、引脚复用等信息的配置;
④ s3c2440.dtsi 存放的是s3c2440这个SoC跟其他s3c24xx系列不同的一些硬件信息,如clock控制器、串口等等;
⑤ s3c2440-jz2440.dts 存放的是jz2440的硬件信息。
(2) 修改设备树文件
① s3c2440.dtsi修改为如下:(只支持serial0、rtc、watchdog、DM9000网卡,nand flash(添加),其余的已删掉,后续学到对应的驱动再添加)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 | /* * Samsung's S3C2416 SoC device tree source * * Copyright (c) 2013 Heiko Stuebner <[email protected]> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. */ #include <dt-bindings/clock/s3c2410.h> #include "s3c24xx.dtsi" #include "s3c2440-pinctrl.dtsi" / { model = "Samsung S3C2440 SoC"; compatible = "samsung,s3c2440"; cpus { #address-cells = <1>; #size-cells = <0>; cpu { compatible = "arm,arm920t"; }; }; interrupt-controller@4a000000 { compatible = "samsung,s3c2410-irq"; }; clocks: clock-controller@0x4c000000 { compatible = "samsung,s3c2440-clock"; reg = <0x4c000000 0x20>; #clock-cells = <1>; }; pinctrl@56000000 { compatible = "samsung,s3c2440-pinctrl"; }; timer@51000000 { clocks = <&clocks PCLK_PWM>; clock-names = "timers"; }; uart_0: serial@50000000 { compatible = "samsung,s3c2440-uart"; clock-names = "uart"; clocks = <&clocks PCLK_UART0>; }; watchdog: watchdog@53000000 { interrupts = <1 9 27 3>; clocks = <&clocks PCLK>; clock-names = "watchdog"; }; rtc: rtc@57000000 { compatible = "samsung,s3c2410-rtc"; clocks = <&clocks PCLK_RTC>; clock-names = "rtc"; }; /* */ nand0: nand@4e000000 { compatible = "samsung,s3c2440-nand"; reg = <0x4e000000 0x40>; interrupts = <0 0 24 3>; clocks = <&clocks HCLK_NAND>; clock-names = "nand"; pinctrl-names = "default"; pinctrl-0 = <&nand_pinctrl>; status = "disabled"; }; }; |
② s3c2440-pinctrl.dtsi 修改为如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 | /* * Samsung S3C2416 pinctrl settings * * Copyright (c) 2013 Heiko Stuebner <[email protected]> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. */ #include <dt-bindings/pinctrl/samsung.h> &pinctrl_0 { /* * Pin banks */ /*s3c2440只有GPA~GPJ*/ gpa: gpa { gpio-controller; #gpio-cells = <2>; }; gpb: gpb { gpio-controller; #gpio-cells = <2>; }; gpc: gpc { gpio-controller; #gpio-cells = <2>; }; gpd: gpd { gpio-controller; #gpio-cells = <2>; }; gpe: gpe { gpio-controller; #gpio-cells = <2>; }; gpf: gpf { gpio-controller; #gpio-cells = <2>; interrupt-controller; #interrupt-cells = <2>; }; gpg: gpg { gpio-controller; #gpio-cells = <2>; interrupt-controller; #interrupt-cells = <2>; }; gph: gph { gpio-controller; #gpio-cells = <2>; }; gpj: gpj { gpio-controller; #gpio-cells = <2>; }; /* * Pin groups */ uart0_data: uart0-data { samsung,pins = "gph-2", "gph-3"; samsung,pin-function = <EXYNOS_PIN_FUNC_2>; }; /*添加NAND flash所用的管脚*/ nand_pinctrl: nand_pinctrl { samsung,pins = "gpa-17", "gpa-18", "gpa-19", "gpa-20", "gpa-22"; samsung,pin-function = <1>; }; }; |
③ s3c2440-jz2440.dts 修改为如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 | /* * SAMSUNG SMDK2416 board device tree source * * Copyright (c) 2013 Heiko Stuebner <[email protected]> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. */ /dts-v1/; #include "s3c2440.dtsi" #include <dt-bindings/gpio/gpio.h> #include <dt-bindings/interrupt-controller/irq.h> / { model = "JZ2440"; compatible = "samsung,jz2440"; memory { reg = <0x30000000 0x4000000>; }; /*设置内核启动参数*/ chosen { bootargs = "console=ttySAC0,115200n8 rw root=/dev/mtdblock4 rootfstype=yaffs2"; /*bootargs = "console=ttySAC0,115200n8 rw root=/dev/mtdblock4 rootfstype=yaffs2 ignore_loglevel earlyprintk";*/ }; clocks { compatible = "simple-bus"; #address-cells = <1>; #size-cells = <1>; xti: xti { compatible = "fixed-clock"; clock-frequency = <12000000>; clock-output-names = "xti"; #clock-cells = <0>; }; }; /*添加DM9000 网卡,以便于后面的驱动开发调试*/ srom-cs4@20000000 { compatible = "simple-bus"; #address-cells = <1>; #size-cells = <1>; reg = <0x20000000 0x8000000>; ranges; ethernet@20000000 { compatible = "davicom,dm9000"; reg = <0x20000000 0x2 0x20000004 0x2>; interrupt-parent = <&gpf>; interrupts = <7 IRQ_TYPE_EDGE_RISING>; local-mac-address = [00 00 de ad be ef]; davicom,no-eeprom; }; }; }; &rtc { status = "okay"; }; &uart_0 { status = "okay"; pinctrl-names = "default"; pinctrl-0 = <&uart0_data>; }; &watchdog { status = "okay"; }; &nand0 { status = "okay"; nand,tacls = <0xa>; nand,twrph0 = <0x19>; nand,twrph1 = <0xa>; #address-cells = <1>; #size-cells = <1>; /*Nand flash 分区*/ partitions { /* MTD partition table */ #address-cells = <1>; #size-cells = <1>; nr-chips = <1>; set-name = "jz2440-0"; partition@0 { label = "bootloader"; reg = <0x0000000 0x00080000>; read-only; }; partition@80000 { label = "device_tree"; reg = <0x00080000 0x00020000>; read-only; }; partition@a0000 { label = "params"; reg = <0x000a0000 0x00040000>; read-only; }; partition@e0000 { label = "kernel"; reg = <0x000e0000 0x00400000>; read-only; }; partition@4e0000 { label = "rootfs"; reg = <0x004e0000 0x0>; /*read-only;*/ /*若rootfs为read-only,内核加载文件系统后,文件系统只能读不能写*/ }; }; }; |
(3) 修改arch/arm/boot/dts目录下的Makefile,以便在
2. 修改Makefile和Kconfig,添加JZ2440板子的信息
2.1 修改arch/arm/mach-s3c24xx/Kconfig
添加的信息如下:
注:在博客讓TQ2440也用上設備樹(1)的第一个 “select” 是 选择CLKSRC_OF,这里用select TIMER_OF替代。其实select CLKSRC_OF 与 select TIMER_OF所配置的内容是一样的,这只是内核Linux-4.9 与 Linux-4.15 的微小差异(不过也正因为这个差异,搞了好久,最终是参考韦老师的做法,在内核添加
对比两个内核的drivers/clocksource/samsung_pwm_timer.c第421行后的代码,发现它们是一样的。
言归正传,在make menuconfig的时候,选上这个配置,CONFIG_TIMER_OF、CONFIG_USE_OF、CONFIG_PINCTRL、CONFIG_S3C24XX配置都会被选上。配置如下:
System Type —>
????SAMSUNG S3C24XX SoCs Support —>
2.2 修改arch/arm/mach-s3c24xx/Makefile
在Makefile添加
2.3 添加arch/arm/mach-s3c24xx/mach-jz2440-dt.c文件
mach-jz2440-dt.c文件内容如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | #include <linux/clocksource.h> #include <linux/irqchip.h> #include <linux/serial_s3c.h> #include <asm/mach/arch.h> #include <mach/map.h> #include <plat/cpu.h> #include <plat/pm.h> #include "common.h" #include <linux/of_platform.h> static void __init jz2440_dt_map_io(void) { s3c24xx_init_io(NULL, 0); } static void __init jz2440_dt_machine_init(void) { s3c_pm_init(); } static const char *const jz2440_dt_compat[] __initconst = { "samsung,jz2440", NULL, }; DT_MACHINE_START(JZ2440_DT, "Samsung S3C2440 (Flattened Device Tree)") .dt_compat = jz2440_dt_compat, .map_io = jz2440_dt_map_io, .init_irq = irqchip_init, .init_machine = jz2440_dt_machine_init, MACHINE_END |
注:如果内核配置make menuconfig中选择支持设备树
1 2 3 | make menuconfig ---> Boot options ---> Flattened Device Tree support |
以前没有设备树的时候是内核启动通过u-boot传入的machine id来找到对应的单板,而使用设备树后内核启动则通过上面的jz2440_dt_compat数组的信息和设备树的compatible 属性比较匹配来对应的单板。
3. 配置打开内核调试
在启动kernel的時候最烦人的是,uboot打印出”Starting kernel …”后,整个系统就沒有任何动静了,此时,就需要打开内核早期的调试log,方法如下:
为了能够尽量看到更多内核启动早期的log,一定要在内核配置文件中把内核早期的log配置打开:
1 2 3 4 5 6 7 | Kernel hacking ---> [*] Kernel low-level debugging functions (read help!) Kernel low-level debugging port (Use Samsung S3C UART 0 for low-level debug) ---> [*] Early printk |
除了上面的配置,还必须在bootargs中添加一个earlyprintk字符串,否则这些log还是是打印不出来,此外,建议再在bootargs中添加一个ignore_loglevel参数,防止有些模块的log由于loglevel的问题无法输出log。
因此:chosen节点可以写成:
1 2 3 | chosen { bootargs = "console=ttySAC0,115200n8 rw root=/dev/mtdblock4 rootfstype=yaffs2 ignore_loglevel earlyprintk"; }; |
4. 配置编译内核
make s3c2410_defconfig之后,配置内核支持设备树,选择JZ2440单板支持设备树(前面已讲),重新编译内核(
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 | U-Boot 2016.03 (May 24 2020 - 00:33:54 +0800) CPUID: 32440001 FCLK: 400 MHz HCLK: 100 MHz PCLK: 50 MHz DRAM: 64 MiB WARNING: Caches not enabled Flash: 2 MiB NAND: 256 MiB *** Warning - bad CRC, using default environment In: serial Out: serial Err: serial Net: dm9000 Hit any key to stop autoboot: 0 NAND read: device 0 offset 0xe0000, size 0x400000 4194304 bytes read: OK NAND read: device 0 offset 0x80000, size 0x20000 131072 bytes read: OK ## Booting kernel from Legacy Image at 30000000 ... Image Name: Linux-4.15.0 Image Type: ARM Linux Kernel Image (uncompressed) Data Size: 3479496 Bytes = 3.3 MiB Load Address: 30008000 Entry Point: 30008000 Verifying Checksum ... OK ## Flattened Device Tree blob at 32000000 Booting using the fdt blob at 0x32000000 Loading Kernel Image ... OK Loading Device Tree to 33afa000, end 33afe1da ... OK Starting kernel ... Booting Linux on physical CPU 0x0 Linux version 4.15.0 (book@book-virtual-machine) (gcc version 4.9.4 (Linaro GCC 4.9-2017.01)) #3 Thu May 21 22:24:54 CST 2020 CPU: ARM920T [41129200] revision 0 (ARMv4T), cr=c000717f CPU: VIVT data cache, VIVT instruction cache OF: fdt: Machine model: JZ2440 Memory policy: Data cache writeback arch/arm/mach-s3c24xx/mach-jz2440-dt.c jz2440_dt_map_io 14 CPU S3C2440A (id 0x32440001) DT missing boot CPU MPIDR[23:0], fall back to default cpu_logical_map random: fast init done Built 1 zonelists, mobility grouping on. Total pages: 16256 Kernel command line: console=ttySAC0,115200n8 rw root=/dev/mtdblock4 rootfstype=yaffs2 Dentry cache hash table entries: 8192 (order: 3, 32768 bytes) Inode-cache hash table entries: 4096 (order: 2, 16384 bytes) Memory: 57936K/65536K available (5013K kernel code, 213K rwdata, 1180K rodata, 188K init, 202K bss, 7600K reserved, 0K cma-reserved) Virtual kernel memory layout: vector : 0xffff0000 - 0xffff1000 ( 4 kB) fixmap : 0xffc00000 - 0xfff00000 (3072 kB) vmalloc : 0xc4800000 - 0xff800000 ( 944 MB) lowmem : 0xc0000000 - 0xc4000000 ( 64 MB) modules : 0xbf000000 - 0xc0000000 ( 16 MB) .text : 0x(ptrval) - 0x(ptrval) (5015 kB) .init : 0x(ptrval) - 0x(ptrval) ( 188 kB) .data : 0x(ptrval) - 0x(ptrval) ( 214 kB) .bss : 0x(ptrval) - 0x(ptrval) ( 203 kB) NR_IRQS: 103 irq: clearing pending status 00000002 _get_rate: could not find clock xti sched_clock: 16 bits at 1000kHz, resolution 1000ns, wraps every 32767500ns clocksource: samsung_clocksource_timer: mask: 0xffff max_cycles: 0xffff, max_idle_ns: 29163075 ns Console: colour dummy device 80x30 Calibrating delay loop... 199.06 BogoMIPS (lpj=995328) pid_max: default: 32768 minimum: 301 Mount-cache hash table entries: 1024 (order: 0, 4096 bytes) Mountpoint-cache hash table entries: 1024 (order: 0, 4096 bytes) CPU: Testing write buffer coherency: ok Setting up static identity map for 0x300081e0 - 0x30008238 clocksource: jiffies: mask: 0xffffffff max_cycles: 0xffffffff, max_idle_ns: 19112604462750000 ns futex hash table entries: 256 (order: -1, 3072 bytes) pinctrl core: initialized pinctrl subsystem NET: Registered protocol family 16 DMA: preallocated 256 KiB pool for atomic coherent allocations S3C Power Management, Copyright 2004 Simtec Electronics S3C2440: Initialising architecture SCSI subsystem initialized usbcore: registered new interface driver usbfs usbcore: registered new interface driver hub usbcore: registered new device driver usb Advanced Linux Sound Architecture Driver Initialized. clocksource: Switched to clocksource samsung_clocksource_timer NET: Registered protocol family 2 TCP established hash table entries: 1024 (order: 0, 4096 bytes) TCP bind hash table entries: 1024 (order: 0, 4096 bytes) TCP: Hash tables configured (established 1024 bind 1024) UDP hash table entries: 256 (order: 0, 4096 bytes) UDP-Lite hash table entries: 256 (order: 0, 4096 bytes) NET: Registered protocol family 1 RPC: Registered named UNIX socket transport module. RPC: Registered udp transport module. RPC: Registered tcp transport module. RPC: Registered tcp NFSv4.1 backchannel transport module. NetWinder Floating Point Emulator V0.97 (extended precision) Initialise system trusted keyrings workingset: timestamp_bits=30 max_order=14 bucket_order=0 jffs2: version 2.2. (NAND) (SUMMARY) ? 2001-2006 Red Hat, Inc. romfs: ROMFS MTD (C) 2007 Red Hat, Inc. Key type asymmetric registered Asymmetric key parser 'x509' registered io scheduler noop registered io scheduler deadline registered io scheduler cfq registered (default) io scheduler mq-deadline registered io scheduler kyber registered Serial: 8250/16550 driver, 4 ports, IRQ sharing enabled 50000000.serial: ttySAC0 at MMIO 0x50000000 (irq = 32, base_baud = 0) is a S3C2440 console [ttySAC0] enabled lp: driver loaded but no devices found ppdev: user-space parallel port driver brd: module loaded loop: module loaded s3c24xx-nand 4e000000.nand: Tacls=1, 10ns Twrph0=5 50ns, Twrph1=2 20ns nand: device found, Manufacturer ID: 0xec, Chip ID: 0xda nand: Samsung NAND 256MiB 3,3V 8-bit nand: 256 MiB, SLC, erase size: 128 KiB, page size: 2048, OOB size: 64 s3c24xx-nand 4e000000.nand: ECC disabled nand: NAND_ECC_NONE selected by board driver. This is not recommended! Scanning device for bad blocks Bad eraseblock 1027 at 0x000008060000 5 ofpart partitions found on MTD device partitions Creating 5 MTD partitions on "partitions": 0x000000000000-0x000000080000 : "bootloader" 0x000000080000-0x0000000a0000 : "device_tree" 0x0000000a0000-0x0000000e0000 : "params" 0x0000000e0000-0x0000004e0000 : "kernel" 0x0000004e0000-0x000010000000 : "rootfs" s3c24xx-nand 4e000000.nand: Tacls=1, 10ns Twrph0=5 50ns, Twrph1=2 20ns eth0: dm9000b at ab428955,46df3c1c IRQ 7 MAC: 00:0c:29:4d:e4:f4 (platform data) ohci_hcd: USB 1.1 'Open' Host Controller (OHCI) Driver ohci-s3c2410: OHCI S3C2410 driver usbcore: registered new interface driver usbserial_generic usbserial: USB Serial support registered for generic usbcore: registered new interface driver ftdi_sio usbserial: USB Serial support registered for FTDI USB Serial Device usbcore: registered new interface driver pl2303 usbserial: USB Serial support registered for pl2303 s3c-rtc 57000000.rtc: rtc disabled, re-enabling rtc rtc0: invalid alarm value: 1900-2-1 0:0:0 s3c-rtc 57000000.rtc: rtc core: registered s3c as rtc0 s3c2410-wdt 53000000.watchdog: watchdog inactive, reset disabled, irq disabled NET: Registered protocol family 10 Segment Routing with IPv6 sit: IPv6, IPv4 and MPLS over IPv4 tunneling driver NET: Registered protocol family 17 Loading compiled-in X.509 certificates s3c-rtc 57000000.rtc: setting system clock to 2000-10-17 09:22:55 UTC (971774575) ALSA device list: No soundcards found. yaffs: dev is 32505860 name is "mtdblock4" rw yaffs: passed flags "" VFS: Mounted root (yaffs2 filesystem) on device 31:4. Freeing unused kernel memory: 188K This architecture does not have kernel memory protection. dm9000 20000000.ethernet eth0: link down IPv6: ADDRCONF(NETDEV_UP): eth0: link is not ready dm9000 20000000.ethernet eth0: link down Please press Enter to activate this console. / # |
最后,关于设备树的修改,大家可以阅读pengdonglin的博客讓TQ2440也用上設備樹(1),这博写得非常好。