linux3.18 内核移植记录(Exynos4412)

来源:互联网 发布:长安大学网络教育 编辑:程序博客网 时间:2024/05/17 05:55

初始化

引入Device Tree之后,MACHINE_START变更为DT_MACHINE_START,其中含有一个.dt_compat成员,用于表明相关的machine与.dts中root结点的compatible属性兼容关系。如果Bootloader传递给内核的Device Tree中root结点的compatible属性出现在某machine的.dt_compat表中,相关的machine就与对应的Device Tree匹配,从而引发这一machine的一系列初始化函数被执行。

arch/arm/mach-exynos/exynos.c:

DT_MACHINE_START(EXYNOS_DT, "SAMSUNG EXYNOS (Flattened Device Tree)")    /* Maintainer: Thomas Abraham <thomas.abraham@linaro.org> */    /* Maintainer: Kukjin Kim <kgene.kim@samsung.com> */    .l2c_aux_val    = 0x3c400001,    .l2c_aux_mask   = 0xc20fffff,    .smp        = smp_ops(exynos_smp_ops),    .map_io     = exynos_init_io,    .init_early = exynos_firmware_init,    .init_irq   = exynos_init_irq,    .init_machine   = exynos_dt_machine_init,    .init_late  = exynos_init_late,    .dt_compat  = exynos_dt_compat,    .restart    = exynos_restart,    .reserve    = exynos_reserve,    .dt_fixup   = exynos_dt_fixup,MACHINE_END

若启动时出现“Starting kernel …“后挂掉,可以打开Kernel low-level debugging functions, 并在启动参数中添加earlyprintk。

emmc驱动

内核已经自带了exynos平台的mmc驱动,位于drivers/mmc/host/dw_mmc-exynos.c中,只需在dts文件中打开相应的配置即可。

mmc@12550000 {        num-slots = <1>;        broken-cd;        non-removable;        card-detect-delay = <200>;        //vmmc-supply = <&vemmc_reg>;        clock-frequency = <100000000>;        max-frequency = <100000000>;        samsung,dw-mshc-ciu-div = <3>;        samsung,dw-mshc-sdr-timing = <2 3>;         samsung,dw-mshc-ddr-timing = <1 2>;         pinctrl-0 = <&sd4_clk &sd4_cmd &sd4_bus8>;        pinctrl-names = "default";        status = "okay";        bus-width = <8>;        cap-mmc-highspeed;        sd-uhs-ddr50;        mmc-ddr-1_8v;        //slot@0{        //  reg=<0>;        //  bus-width=<8>;        //};    };

移植过程中出现了有时能启动,有时启动不了的情况,

[    2.946761] sdhci: Secure Digital Host Controller Interface driver[    2.952011] sdhci: Copyright(c) Pierre Ossman[    2.956787] s3c-sdhci 12530000.sdhci: clock source 2: mmc_busclk.2 (100000000 Hz)[    2.964198] s3c-sdhci 12530000.sdhci: No vmmc regulator found[    2.969557] s3c-sdhci 12530000.sdhci: No vqmmc regulator found[    3.002313] mmc0: SDHCI controller on samsung-hsmmc [12530000.sdhci] using ADMA[    3.008362] Synopsys Designware Multimedia Card Interface Driver[    3.015085] dwmmc_exynos 12550000.mmc: Using internal DMA controller.[    3.020629] dwmmc_exynos 12550000.mmc: Version ID is 240a[    3.026287] dwmmc_exynos 12550000.mmc: DW MMC controller at irq 109, 32 bit host data width, 128 deep fifo[    3.035673] dwmmc_exynos 12550000.mmc: No vmmc regulator found[    3.041431] dwmmc_exynos 12550000.mmc: No vqmmc regulator found[    3.077404] dwmmc_exynos 12550000.mmc: 1 slots initialized[    3.082601] usbcore: registered new interface driver usbhid[    3.086971] usbhid: USB HID core driver[    3.091464] TCP: cubic registered[    3.094146] NET: Registered protocol family 17[    3.098621] NET: Registered protocol family 15[    3.103116] Registering SWP/SWPB emulation handler[    3.109697] isp-power-domain: Power-off latency exceeded, new value 304833 ns[    3.115427] gps-alive-power-domain: Power-off latency exceeded, new value 5793625 ns

然后就一直卡在这里,没有任何反应,而且每次卡的位置也不是完全一样。后来打开CONFIG_MMC_DEBUG后,可以输出错误信息,发现是rootfs没有挂载上;查看init/do_mounts.c后发现可以加rootdelay参数延迟挂载。在uboot的启动参数中加入rootdelay=5后,内核启动的时候在等5秒钟之后再挂载rootfs,这样改了之后虽然启动慢了点,但每次都能顺利启动了。

LCD驱动

3.18内核中自带的framebuffer驱动位于drivers/video/fbdev/s3c-fb.c,但是它不支持device tree,后来在网上找相应的补丁加入了对device tree的支持,然后在dts文件中添加相应的node:

    fimd@11c00000 {        pinctrl-0 = <&lcd_clk &lcd_data24 >;        pinctrl-names = "default";        status = "okay";        samsung,fimd-display = <&lcd_fimd0>;        samsung,fimd-vidout-rgb;        samsung,fimd-frame-rate = <60>;        lcd-gpios = <&gpx2 7 0>,            <&gpk3 2 0 >,            <&gpk3 3 0 >;        gpios=<&gpf0 0 2 >,            <&gpf0 1 2 >,            <&gpf0 2 2 >,            <&gpf0 3 2 >,            <&gpf0 4 2 >,            <&gpf0 5 2 >,            <&gpf0 6 2 >,            <&gpf0 7 2 >,            <&gpf1 0 2 >,            <&gpf1 1 2 >,            <&gpf1 2 2 >,            <&gpf1 3 2 >,            <&gpf1 4 2 >,            <&gpf1 5 2 >,            <&gpf1 6 2 >,            <&gpf1 7 2 >,            <&gpf2 0 2 >,            <&gpf2 1 2 >,            <&gpf2 2 2 >,            <&gpf2 3 2 >,            <&gpf2 4 2 >,            <&gpf2 5 2 >,            <&gpf2 6 2 >,            <&gpf2 7 2 >,            <&gpf3 0 2 >,            <&gpf3 1 2 >,            <&gpf3 2 2 >,            <&gpf3 3 2 >;        window0 {            samsung,fimd-win-id = <0>;            samsung,fimd-win-bpp = <32 24>;            samsung,fimd-win-res = <1024 600>;            samsung,fimd-win-vres = <1024 600>;        };        window1 {            samsung,fimd-win-id = <1>;            samsung,fimd-win-bpp = <32 24>;            samsung,fimd-win-res = <1024 600>;            samsung,fimd-win-vres = <1024 600>;        };    };    lcd_fimd0: lcd_fimd0{        lcd-htiming = <120 120 80 1024>;        lcd-vtiming = <22 10 3 600>;    };

对于其中的gpio资源,在驱动中可以通过调用以下两个函数获取:

of_get_gpio(dev->of_node, idx);of_get_named_gpio(dev->of_node,"lcd-gpios",idx);

这样启动后出现了”failed to get bus clock”的错误,通过修改exynos4.dtsi中的clock-names解决了,对于clk这一块还没完全搞清楚,

--- a/arch/arm/boot/dts/exynos4.dtsi+++ b/arch/arm/boot/dts/exynos4.dtsi@@ -640,7 +640,7 @@     interrupt-names = "fifo", "vsync", "lcd_sys";     interrupts = <11 0>, <11 1>, <11 2>;     clocks = <&clock CLK_SCLK_FIMD0>, <&clock CLK_FIMD0>;-    clock-names = "sclk_fimd", "fimd";+    clock-names = "sclk_fimd", "lcd";     samsung,power-domain = <&pd_lcd0>;     samsung,sysreg = <&sys_reg>;     status = "disabled";

改完后重新编译发现屏幕终于亮起来了,但是会闪烁,像是扫描过慢的感觉,然后又加了如下代码修改clock频率:

@@ -1413,6 +1644,22 @@ static int s3c_fb_probe(struct platform_device *pdev)               ret = PTR_ERR(sfb->lcd_clk);               goto err_bus_clk;       }+      printk("lcd_clk: %d\n",clk_get_rate(sfb->lcd_clk));+      ret=clk_set_rate(sfb->lcd_clk, 50000000);+      if (ret < 0) {+           dev_err(dev, "failed to clk_set_rate of sclk for fimd\n");+      }

i2c驱动

电容触摸屏用到了i2c,把触摸屏驱动改成device tree支持后,再在dts文件中加入i2c的node,

i2c@13860000 {    status = "okay";    samsung,i2c-max-bus-freq = <400000>;    samsung,i2c-sda-delay = <100>;    gsl680@40{        compatible = "gsl680-i2c";        reg=<0x40>;        gsl680-gpios = <&gpx1 5 1>,                <&gpx1 6 0xf>;    };};

其中gsl680驱动的地址为0x40,用到了两个gpio口,其中一个用于中断,在驱动中通过of_get_named_gpio和gpio_to_irq得到对应的irq号,

static int gsl_ts_probe(struct i2c_client *client,            const struct i2c_device_id *id) {    struct gsl_ts *ts;     int rc;    struct device_node* np=client->dev.of_node;    gpio_ts_wake= of_get_named_gpio(np,"gsl680-gpios", 0);    irq_gpio= of_get_named_gpio(np,"gsl680-gpios", 1);                                     irq_port= gpio_to_irq(irq_gpio);

”samsung,i2c-max-bus-freq“指定i2c频率为400K,刚开始没有加“samsung,i2c-sda-delay”,导致了i2c数据读写出错,搞了很久之后才解决这个问题。

0 0
原创粉丝点击