1. 程式人生 > >Davinci DM6446Linux 核心分析board-evm.c

Davinci DM6446Linux 核心分析board-evm.c

                                             

http://www.61ic.com/Article/DaVinci/DM644X/201201/40304.html

/**************************************************************************
  * Included Files
  **************************************************************************/
 
#include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/fs.h>
 #include <linux/major.h>
 #include <linux/root_dev.h>
 #include <linux/dma-mapping.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/partitions.h>
 #include <linux/serial.h>
 #include <linux/usb_musb.h>
 #include <linux/mtd/nand.h>
 #include <linux/serial_8250.h>
 #include <linux/davinci_mmc.h>
 #include <linux/nand_davinci.h>
 
#include <asm/setup.h>
 #include <asm/io.h>
 #include <asm/mach-types.h>
 
#include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 #include <asm/mach/flash.h>
 #include <asm/arch/irqs.h>
 #include <asm/arch/hardware.h>
 #include <asm/arch/edma.h>
 #include <linux/kgdb.h>
 #include <asm/arch/cpu.h>
 #include <asm/arch/mux.h>
 #include "clock.h"
 
/*
 核心在啟動的時候會執行start_kernel() , 然後它會呼叫體系結構相關的setup_arch(&command_line), arm體系結構在arch/arm/kernel/setup.c中, 接著初始化平臺相關的裝置, 但在此之前, 它必須找到這塊目標板的描述結構, 所以它會先通過setup_machine,其呼叫lookup_machine_type(nr)來查詢這個結構, 引數是由u-boot傳進來的, 儲存在r2中. 假設它傳入的是DAVINCI_EVM的nr, lookup_machine_type(nr)  就會找到本檔案中到最後定義的結構體machine_desc.
 start_kernel之前的linux核心啟動的詳細過程,可參考該文章

http://blog.csdn.net/gates84/archive/2007/01/15/1483979.aspx
 */
 

/**************************************************************************
  * Definitions
  **************************************************************************/
 #define DAVINCI_UART_CLK        27000000    // 串列埠時鐘,與輸入的晶振頻率相同
 
/*
 * dm644x平臺採用8250相容串列埠,該資料結構定義了串列埠的硬體資源,將填充在其platform_device結構體中,
 * 即下面的serial_device中。在該platform_devic被註冊後,如果其相關的驅動被註冊,則會自動找到它,
 * 並可呼叫其中的資源。plat_serial8250_port定義在include/linux/serial_8250.h檔案中
 */
 static struct plat_serial8250_port serial_platform_data[] = {
     {
         .membase    = (char *)IO_ADDRESS(DAVINCI_UART0_BASE),    // 串列埠0暫存器開始處的虛擬地址是IO_ADDRESS(0x01C20000)
         .mapbase    = (unsigned long)DAVINCI_UART0_BASE,        // 串列埠0暫存器開始處的實地址是0x01C20000
         .irq        = IRQ_UARTINT0,                                // 串列埠0的中斷號是40
         .flags        = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
         .iotype        = UPIO_MEM32,
         .regshift    = 2,
         .uartclk    = DAVINCI_UART_CLK,                            // 串列埠時鐘頻率是27MHz
     },
     {
         .flags    = 0,
     },
 };
 
/* 見上述解釋。platform_device定義在include/linux/device.h檔案中
 * 一般platform_device在系統啟動的時候就註冊了,而其相應到驅動platform_driver或device_driver可在模組中載入。
 *

http://hi.baidu.com/zengzhaonong/blog/item/440bb91e57e5251a413417d9.html 有關於platform_device結構體的詳細解釋
 */
 static struct platform_device serial_device    = {
     .name            = "serial8250",        // 這個名字很重要,與對應驅動中的機構體device_driver中的.name相同,其被驅動模組用來查詢裝置
     .id            = 0,                    // 例項名字尾為0
     .dev            = {
         .platform_data    = serial_platform_data,        // 裝置的私有資料或資源
     },
 };
 
/* 該資料結構定義了USB的私有資料,主要是usb的型別和功能,musb_hdrc_platform_data定義在include/linux/device.h檔案中 */
 static struct musb_hdrc_platform_data usb_data[] = {
     {
 #if defined(CONFIG_USB_MUSB_OTG)
         /* OTG requires a Mini-AB connector */
         .mode        = MUSB_OTG,                    // OTG型別的usb模組,既可以作usb裝置也可以作主機usb使用
 #elif defined(CONFIG_USB_MUSB_PERIPHERAL)
         .mode        = MUSB_PERIPHERAL,
 #elif defined(CONFIG_USB_MUSB_HOST)                // usb裝置
         .mode        = MUSB_HOST,                // 主機usb,類似於電腦的usb功能
 #endif
         .set_vbus    = NULL,
         /* irlml6401 switches 5V */
         .power        = 255, /* sustains 3.0+ Amps (!) */
         .potpgt        = 4, /* ~8 msec */
         .multipoint    = 1,                        // 1個收發埠
     },        /* Need Multipoint support */
 };
 
/* 該資料結構定義了USB的硬體資源, resource定義在include/linux/ioport.h檔案中 */
 static struct resource usb_resources[] = {
     {
         /* physical address */
         .start        = DAVINCI_USB_OTG_BASE,            // USB_OTG暫存器起始處的實地址是0x01C20000
         .end        = DAVINCI_USB_OTG_BASE + 0x5ff,    // USB_OTG暫存器末尾處的實地址是0x01C20000
         .flags        = IORESOURCE_MEM,                // 標識為IO地址資源
     },
     {
         .start        = IRQ_USBINT,                    // USB_OTG中斷號是12
         .flags        = IORESOURCE_IRQ,                // 標識為中斷資源
     },
 };
 
static u64 usb_dmamask = DMA_32BIT_MASK;
 
/* usb的platform_device結構體,用於註冊usb裝置*/
 static struct platform_device usb_dev = {
     .name        = "musb_hdrc",                    // 與對應驅動中的名字相同,用於繫結驅動   
     .id        = -1,                                // -1表示只有一個例項,無數字字尾
     .dev        = {
         .platform_data = usb_data,                // USB的私有資料
         .dma_mask = &usb_dmamask,                // 32位的dma
         .coherent_dma_mask = DMA_32BIT_MASK,
     },
     .resource    = usb_resources,                // USB的硬體資源
     .num_resources    = ARRAY_SIZE(usb_resources),
 };
 
/* 返回cpu的型別:DaVinci EVM*/
 /**************************************************************************
  * Public Functions
  **************************************************************************/
 int cpu_type(void)
 {
     return MACH_TYPE_DAVINCI_EVM;
 }
 
/* 串列埠初始化,主要的工作是開啟串列埠時鐘,定義在arch/arm/mach-davinci/serial.c檔案中*/
 extern void davinci_serial_init(struct platform_device *pdev);
 
/*如果在menuconfig中配置了使用nand啟動系統,則下面的的程式碼將會被編譯。
 * mtd_partition定義在include/linux/mtd/partitions.h檔案中
 */
 #if defined (CONFIG_MTD_NAND_DAVINCI) || defined(CONFIG_MTD_NAND_DAVINCI_MODULE)
 static struct mtd_partition nand_partitions[] = {
     /* bootloader (U-Boot, etc) in first sector */
     {
         .name        = "bootloader",            // bootloader,一般使用u-boot
         .offset        = 0,                    // 從mtd分割槽開始地址的偏移量是0
         .size        = SZ_256K,                // 分割槽大小是256K
         .mask_flags    = 0,    /* force read-only */    // 只讀
     },
     /* bootloader params in the next sector */
     {   
         .name        = "params",                // 存放bootloader的引數
         .offset        = MTDPART_OFS_APPEND,    // 從上一分割槽(bootloader分割槽)開始
         .size        = SZ_128K,               
         .mask_flags    = MTD_WRITEABLE,    /* force read-only */    // 可寫
     },
     /* kernel */
     {
         .name        = "kernel",                // 存放核心
         .offset        = MTDPART_OFS_APPEND,
         .size        = SZ_4M,
         .mask_flags    = 0,
     },
     /* file system */
     {
         .name        = "filesystem",            // 存放檔案系統
         .offset        = MTDPART_OFS_APPEND,
         .size        = MTDPART_SIZ_FULL,        // 整個分割槽的剩餘儲存空間
         .mask_flags    = 0,
     }
 };
 
/* nand platform device 私有資料,用於描述nand flash banks
 * nand_davinci_platform_data定義在include/linux/nand_davinci.h檔案中
 */
 static struct nand_davinci_platform_data nand_data = {
     .options        = 0,               
     .eccmode        = NAND_ECC_HW3_512,        // 校驗模式
     .cle_mask        = 0x10,
     .ale_mask        = 0x08,
     .bbt_td            = NULL,
     .bbt_md            = NULL,
     .parts            = nand_partitions,        // 分割槽資訊
     .nr_parts        = ARRAY_SIZE(nand_partitions),
 };
 
/* 定義了nand裝置使用的硬體資源 */
 static struct resource nand_resources[]        = {
     [0] = {        /* First memory resource is AEMIF control registers */
         .start        = DM644X_ASYNC_EMIF_CNTRL_BASE,
         .end        = DM644X_ASYNC_EMIF_CNTRL_BASE + SZ_4K - 1,
         .flags        = IORESOURCE_MEM,
     },
     [1] = {        /* Second memory resource is NAND I/O window */
         .start        = DAVINCI_ASYNC_EMIF_DATA_CE0_BASE,
         .end        = DAVINCI_ASYNC_EMIF_DATA_CE0_BASE + SZ_16K - 1,
         .flags        = IORESOURCE_MEM,
     },
 };
 


/* nand platform_device ,用於註冊nand device到platform匯流排 */
 static struct platform_device nand_device = {
     .name            = "nand_davinci",
     .id            = 0,
     .dev            = {
         .platform_data    = &nand_data,
     },
 
    .num_resources        = ARRAY_SIZE(nand_resources),
     .resource        = nand_resources,
 };
 #endif
 
/*如果在menuconfig中配置了使用nor啟動系統,則下面的的程式碼將會被編譯。
 * mtd_partition定義在include/linux/mtd/partitions.h檔案中
 */
 #if defined (CONFIG_MTD_DAVINCI_NOR) || defined(CONFIG_MTD_DAVINCI_NOR_MODULE)
 static struct mtd_partition davinci_evm_nor_partitions[] = {
     /* bootloader (U-Boot, etc) in first sector */
      {
          .name             = "bootloader",
          .offset             = 0,
          .size             = SZ_128K,
          .mask_flags         = 0
      },
      /* bootloader params in the next sector */
      {
          .name             = "params",
          .offset             = MTDPART_OFS_APPEND,
          .size             = SZ_128K,
          .mask_flags         = MTD_WRITEABLE, /* force read-only */
      },
      /* kernel */
      {
          .name             = "kernel",
          .offset             = MTDPART_OFS_APPEND,
          .size             = SZ_4M,
          .mask_flags         = 0
      },
      /*cramfs file system */
      {
          .name             = "cramfs",
          .offset             = MTDPART_OFS_APPEND,
          .size             = SZ_2M,
          .mask_flags         = 0
      },
      /* jffs2 file system */
      {
          .name             = "jffs2",        // jffs2檔案分割槽
          .offset             = MTDPART_OFS_APPEND,
          .size             = MTDPART_SIZ_FULL,
          .mask_flags         = 0
      }
 };
 
/* nor platform device 私有資料,用於描述nor flash banks
 * flash_platform_data定義在include/asm-arm/mach/flash.h檔案中
 */
 static struct flash_platform_data davinci_evm_flash_data = {
     .map_name        = "cfi_probe",
     .width            = 2,
     .parts            = davinci_evm_nor_partitions,
     .nr_parts        = ARRAY_SIZE(davinci_evm_nor_partitions),
 };
 
/* 定義了nor裝置使用的硬體資源 */
 /* NOTE: CFI probe will correctly detect flash part as 32M, but EMIF
  ;* limits addresses to 16M, so using addresses past 16M will wrap */
 static struct resource davinci_evm_flash_resource = {
     .start            = DAVINCI_ASYNC_EMIF_DATA_CE0_BASE,
     .end            = DAVINCI_ASYNC_EMIF_DATA_CE0_BASE + SZ_16M - 1,
     .flags            = IORESOURCE_MEM,
 };
 
/* nor platform_device ,用於註冊nor device到platform匯流排 */
 static struct platform_device davinci_evm_flash_device = {
     .name            = "nor_davinci",
     .id            = 0,
     .dev            = {
         .platform_data    = &davinci_evm_flash_data,
     },
 
    .num_resources        = 1,
     .resource        = &davinci_evm_flash_resource,
 };
 #endif
 
/* 定義了mmc裝置使用的硬體資源 */
 #if defined(CONFIG_MMC_DAVINCI) || defined(CONFIG_MMC_DAVINCI_MODULE)
 static struct resource mmc0_resources[] = {
     [0] = {            /* registers */            // 暫存器
         .start        = DAVINCI_MMC_SD_BASE,
         .end        = DAVINCI_MMC_SD_BASE + SZ_1K - 1,
         .flags        = IORESOURCE_MEM,
     },
     [1] = {            /* interrupt */            // 中斷號
         .start        = IRQ_MMCINT,
         .end        = IRQ_MMCINT,
         .flags        = IORESOURCE_IRQ,
     },
     [2] = {            /* dma rx */            // dma 接收暫存器
         .start        = DAVINCI_DMA_MMCRXEVT,
         .end        = DAVINCI_DMA_MMCRXEVT,
         .flags        = IORESOURCE_DMA,
     },
     [3] = {            /* dma tx */            // dma 傳送暫存器
         .start        = DAVINCI_DMA_MMCTXEVT,
         .end        = DAVINCI_DMA_MMCTXEVT,
         .flags        = IORESOURCE_DMA,
     },
 };
 
/* mmc platform device 私有資料,用於描述mmc flash banks
 * davinci_mmc_platform_data定義在include/linux/davinci_mmc.h檔案中
 */
 static struct davinci_mmc_platform_data mmc0_platform_data = {
     .mmc_clk        = "MMCSDCLK0",        //     用於獲mmc取時鐘
     .rw_threshold        = 32,
     .use_4bit_mode        = 1,
 };
 
/* mmc platform_device ,用於註冊mmc0_device到platform匯流排 */
 static struct platform_device mmc0_device = {
     .name            = "mmc",
     .id            = 0,
     .dev            = {
         .platform_data    = &mmc0_platform_data,
     },
 
    .num_resources        = ARRAY_SIZE(mmc0_resources),
     .resource        = mmc0_resources,
 };
 
/* 開啟mmc模組的電源*/
 static void setup_mmc(void)
 {
     board_setup_psc(DAVINCI_GPSC_ARMDOMAIN, DAVINCI_LPSC_MMC_SD0, 1);
 }
 #else
 #define setup_mmc()
 #endif
 
/* platform_device指標陣列 */
 static struct platform_device *davinci_evm_devices[] __initdata = {
     &serial_device,
     &usb_dev,
 #if defined (CONFIG_MTD_NAND_DAVINCI) || defined(CONFIG_MTD_NAND_DAVINCI_MODULE)
     &nand_device,
 #endif
 
#if defined (CONFIG_MTD_DAVINCI_NOR) || defined(CONFIG_MTD_DAVINCI_NOR_MODULE)
     &davinci_evm_flash_device,
 #endif
 
#if defined(CONFIG_MMC_DAVINCI) || defined(CONFIG_MMC_DAVINCI_MODULE)
     &mmc0_device,
 #endif
 };
 
/* 用於設定fiq,irq 的優先順序*/
 /* FIQ are pri 0-1; otherwise 2-7, with 7 lowest priority */
 static const u8 dm644x_default_priorities[DAVINCI_N_AINTC_IRQ] = {
     [IRQ_VDINT0]        = 2,
     [IRQ_VDINT1]        = 6,
     [IRQ_VDINT2]        = 6,
     [IRQ_HISTINT]        = 6,
     [IRQ_H3AINT]        = 6,
     [IRQ_PRVUINT]        = 6,
     [IRQ_RSZINT]        = 6,
     [IRQ_VFOCINT]        = 7,
     [IRQ_VENCINT]        = 6,
     [IRQ_ASQINT]        = 6,
     [IRQ_IMXINT]        = 6,
     [IRQ_VLCDINT]        = 6,
     [IRQ_USBINT]        = 4,
     [IRQ_EMACINT]        = 4,
     [IRQ_IEEE1394INT]    = 7,
     [IRQ_IEEE1394WK]    = 7,
     [IRQ_CCINT0]        = 5,    /* dma */
     [IRQ_CCERRINT]        = 5,    /* dma */
     [IRQ_TCERRINT0]        = 5,    /* dma */
     [IRQ_TCERRINT]        = 5,    /* dma */
     [IRQ_PSCINT]        = 7,
     [21]            = 7,
     [IRQ_IDE]        = 4,
     [IRQ_HPIINT]        = 7,
     [IRQ_MBXINT]        = 7,
     [IRQ_MBRINT]        = 7,
     [IRQ_MMCINT]        = 7,
     [IRQ_SDIOINT]        = 7,
     [IRQ_HPIINT]        = 7,
     [IRQ_DDRINT]        = 7,
     [IRQ_AEMIFINT]        = 7,
     [IRQ_VLQINT]        = 4,
     [IRQ_TINT0_TINT12]    = 2,    /* clockevent */
     [IRQ_TINT0_TINT34]    = 2,    /* clocksource */
     [IRQ_TINT1_TINT12]    = 7,    /* DSP timer */
     [IRQ_TINT1_TINT34]    = 7,    /* system tick */
     [IRQ_PWMINT0]        = 7,
     [IRQ_PWMINT1]        = 7,
     [IRQ_PWMINT2]        = 7,
     [IRQ_I2C]        = 3,
     [IRQ_UARTINT0]        = 3,
     [IRQ_UARTINT1]        = 3,
     [IRQ_UARTINT2]        = 3,
     [IRQ_SPINT0]        = 3,
     [IRQ_SPINT1]        = 3,
     [45]            = 7,
     [IRQ_DSP2ARM0]        = 4,
     [IRQ_DSP2ARM1]        = 4,
     [IRQ_GPIO0]        = 7,
     [IRQ_GPIO1]        = 7,
     [IRQ_GPIO2]        = 7,
     [IRQ_GPIO3]        = 7,
     [IRQ_GPIO4]        = 7,
     [IRQ_GPIO5]        = 7,
     [IRQ_GPIO6]        = 7,
     [IRQ_GPIO7]        = 7,
     [IRQ_GPIOBNK0]        = 7,
     [IRQ_GPIOBNK1]        = 7,
     [IRQ_GPIOBNK2]        = 7,
     [IRQ_GPIOBNK3]        = 7,
     [IRQ_GPIOBNK4]        = 7,
     [IRQ_COMMTX]        = 7,
     [IRQ_COMMRX]        = 7,
     [IRQ_EMUINT]        = 7,
 };
 
/* davinci平臺初始化,主要是開啟各模組到電源。dm644x平臺到電源管理是分模組到,不使用到時候關掉,可降低功耗。
 * 所以需要使用哪個模組,必須在程式中開啟,開啟後才能設定相應的暫存器。
 */
 static void board_init(void)
 {
     board_setup_psc(DAVINCI_GPSC_ARMDOMAIN, DAVINCI_LPSC_VLYNQ, 1);       
 
    board_setup_psc(DAVINCI_GPSC_ARMDOMAIN, DAVINCI_LPSC_VPSSMSTR, 1);   
     board_setup_psc(DAVINCI_GPSC_ARMDOMAIN, DAVINCI_LPSC_VPSSSLV, 1);
     board_setup_psc(DAVINCI_GPSC_ARMDOMAIN, DAVINCI_LPSC_TPCC, 1);
     board_setup_psc(DAVINCI_GPSC_ARMDOMAIN, DAVINCI_LPSC_TPTC0, 1);
     board_setup_psc(DAVINCI_GPSC_ARMDOMAIN, DAVINCI_LPSC_TPTC1, 1);
     board_setup_psc(DAVINCI_GPSC_ARMDOMAIN, DAVINCI_LPSC_GPIO, 1);
 
    /* Turn on WatchDog timer LPSC. Needed for RESET to work */
     board_setup_psc(DAVINCI_GPSC_ARMDOMAIN, DAVINCI_LPSC_TIMER2, 1);
 
    davinci_serial_init(&serial_device);    // 初始化串列埠
 }
 
/* dm644x平臺許多功能模組到引腳是gpio複用到,功能引腳和gpio腳是互斥的 ,
 * 該函式用來設定這些引腳.
 */
 static void dm644x_setup_pinmux(unsigned int id)
 {
     switch (id) {
     case DAVINCI_LPSC_ATA:
         davinci_cfg_reg(DM644X_HDIREN);
         davinci_cfg_reg(DM644X_ATAEN);
         break;
     case DAVINCI_LPSC_MMC_SD0:
         /* VDD power manipulations are done in U-Boot for CPMAC
         * so applies to MMC as well
         */
         /*Set up the pull register for MMC */
         DAVINCI_VDD3P3V_PWDN = 0x0;
         davinci_cfg_reg(DM644X_MSTK);
         break;
     case DAVINCI_LPSC_I2C:
         davinci_cfg_reg(DM644X_I2C);
         break;
     case DAVINCI_LPSC_McBSP0:
         davinci_cfg_reg(DM644X_MCBSP0);
         break;
     case DAVINCI_LPSC_PWM0:
         davinci_cfg_reg(DM644X_PWM0);
         break;
     case DAVINCI_LPSC_PWM1:
         davinci_cfg_reg(DM644X_PWM1);
         break;
     case DAVINCI_LPSC_PWM2:
         davinci_cfg_reg(DM644X_PWM2);
         break;
     case DAVINCI_LPSC_VLYNQ:
         davinci_cfg_reg(DM644X_VLINQEN);
         davinci_cfg_reg(DM644X_VLINQWD);
         break;
     default:
         break;
 
    }
 }
 
/* 用於設定各中斷的優先順序,
 * 該指標定義在arch/arm/mach-davinci/irq.c中
  */
 extern const u8 *davinci_def_priorities;
 
/* 初始化IO口,開啟各模組電源 */
 static void __init davinci_map_io(void)
 {
     davinci_pinmux_setup = dm644x_setup_pinmux;
     davinci_def_priorities = dm644x_default_priorities;
     davinci_map_common_io();
 
#ifdef CONFIG_KGDB_8250
     early_serial_setup((struct uart_port *)
              &serial_platform_data[kgdb8250_ttyS]);
     kgdb8250_add_platform_port(kgdb8250_ttyS,
                  &serial_platform_data[kgdb8250_ttyS]);
 #endif
     /* Initialize the DaVinci EVM board settigs */
     board_init ();
 }
 
/* 初始化平臺irq,該函式在arch/arm/mach-davinci/irq.c中定義 */
 int __init davinci_gpio_irq_setup(void);
 

void davinci_msp430_deep_sleep(void)
 {
     unsigned int icstr = DAVINCI_I2C_BASE + 0x08;
     unsigned int icsar = DAVINCI_I2C_BASE + 0x1C;
     unsigned int iccnt = DAVINCI_I2C_BASE + 0x14;
     unsigned int icdxr = DAVINCI_I2C_BASE + 0x20;
     unsigned int icmdr = DAVINCI_I2C_BASE + 0x24;
     u32 cnt = 0, buflen = 2;
     char rtcdata[2] = { 2, 8 };
     char *buffer = rtcdata;
 
    /* check for bus busy */
     while (readl(icstr) & 0x1000) ;
 
    /* configure the count register */
     writel(2, iccnt);
 
    /* set the salve address */
     writel(0x23, icsar);
 
    /* Take I2C out of reset, configure it as master,
      * set the start bit, stop bit and enable the
      * transmitter */
     writel(0x2e20, icmdr);
 
    while (cnt < buflen) {
         if ((readl(icstr) & 0x0010) != 0) {
             writel(*buffer, icdxr);
             ++buffer;
             ++cnt;
         }
     }
 }
 
/* 該驅動的初始化函式 */
 static __init void evm_init(void)
 {
 #if defined (CONFIG_MTD_DAVINCI_NOR) || defined(CONFIG_MTD_DAVINCI_NOR_MODULE)
 #if defined(CONFIG_BLK_DEV_DAVINCI) || defined(CONFIG_BLK_DEV_DAVINCI_MODULE)
 #warning IDE and NOR flash are are pin-muxed. Disable IDE or NOR.
     printk(KERN_WARNING "WARNING: both IDE and NOR flash are enabled, "
          "but are pin-muxed.\n\t Disable IDE or NOR support.\n");
 #endif
 #if defined (CONFIG_MTD_NAND_DAVINCI) || defined(CONFIG_MTD_NAND_DAVINCI_MODULE)
 #warning NAND and NOR flash are are pin-muxed. Disable NAND or NOR.
     printk(KERN_WARNING "WARNING: both NAND and NOR flash are enabled, "
          "but are pin-muxed.\n\t Disable NAND or NOR support.\n");
 #endif
 #endif
 
#if defined(CONFIG_BLK_DEV_DAVINCI) || defined(CONFIG_BLK_DEV_DAVINCI_MODULE)
 #if defined (CONFIG_MTD_NAND_DAVINCI) || defined(CONFIG_MTD_NAND_DAVINCI_MODULE)
 #warning IDE and NAND flash are are pin-muxed. Disable IDE or NAND.
     printk(KERN_WARNING "WARNING: both IDE and NAND flash are enabled, "
          "but are pin-muxed.\n\t Disable IDE or NAND support.\n");
 #endif
 #endif
     pm_power_off = davinci_msp430_deep_sleep;
     setup_mmc();
     davinci_gpio_irq_setup();
     platform_add_devices(davinci_evm_devices,        // 註冊所有已定義的platform_device
         ARRAY_SIZE(davinci_evm_devices));
 }
 
/* 初始化ARM中斷控制暫存器函式
 * 在arch/arm/mach-davinci/irq.c檔案中定義
 */
 extern void davinci_irq_init(void);
 
/* 系統定時器結構體,用於初始化平臺的定時器 */
 extern struct sys_timer davinci_timer;
 
/* 定義平臺屬性,MACHINE_START是個巨集定義,用於填充平臺描述符結構體machine_desc
 * 它們都在include/asm-arm/mach-davinci/arch.h中定義
 *
  */
 MACHINE_START(DAVINCI_EVM, "DaVinci EVM")
     MAINTAINER("Texas Instruments, PSP Team")
     BOOT_MEM(DAVINCI_DDR_BASE, IO_PHYS, IO_VIRT)    // 定義了DDR2的起始實體地址,IO暫存器的起始實體地址以及IO暫存器的到虛擬地址
     BOOT_PARAMS(0x80000100)            // bootloader存放啟動引數到起始實體地址,系統啟動會從中讀取各種引數
     MAPIO(davinci_map_io)            // IO模組初始化,定義在本檔案中
     INITIRQ(davinci_irq_init)       
     .timer = &davinci_timer,
     INIT_MACHINE(evm_init)
     MACHINE_END
 EXPORT_SYMBOL(cpu_type)

                                             閱讀更多                  
                                          

http://www.61ic.com/Article/DaVinci/DM644X/201201/40304.html

/**************************************************************************
  * Included Files
  **************************************************************************/
 
#include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/fs.h>
 #include <linux/major.h>
 #include <linux/root_dev.h>
 #include <linux/dma-mapping.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/partitions.h>
 #include <linux/serial.h>
 #include <linux/usb_musb.h>
 #include <linux/mtd/nand.h>
 #include <linux/serial_8250.h>
 #include <linux/davinci_mmc.h>
 #include <linux/nand_davinci.h>
 
#include <asm/setup.h>
 #include <asm/io.h>
 #include <asm/mach-types.h>
 
#include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 #include <asm/mach/flash.h>
 #include <asm/arch/irqs.h>
 #include <asm/arch/hardware.h>
 #include <asm/arch/edma.h>
 #include <linux/kgdb.h>
 #include <asm/arch/cpu.h>
 #include <asm/arch/mux.h>
 #include "clock.h"
 
/*
 核心在啟動的時候會執行start_kernel() , 然後它會呼叫體系結構相關的setup_arch(&command_line), arm體系結構在arch/arm/kernel/setup.c中, 接著初始化平臺相關的裝置, 但在此之前, 它必須找到這塊目標板的描述結構, 所以它會先通過setup_machine,其呼叫lookup_machine_type(nr)來查詢這個結構, 引數是由u-boot傳進來的, 儲存在r2中. 假設它傳入的是DAVINCI_EVM的nr, lookup_machine_type(nr)  就會找到本檔案中到最後定義的結構體machine_desc.
 start_kernel之前的linux核心啟動的詳細過程,可參考該文章http://blog.csdn.net/gates84/archive/2007/01/15/1483979.aspx
 */
 

/**************************************************************************
  * Definitions
  **************************************************************************/
 #define DAVINCI_UART_CLK        27000000    // 串列埠時鐘,與輸入的晶振頻率相同
 
/*
 * dm644x平臺採用8250相容串列埠,該資料結構定義了串列埠的硬體資源,將填充在其platform_device結構體中,
 * 即下面的serial_device中。在該platform_devic被註冊後,如果其相關的驅動被註冊,則會自動找到它,
 * 並可呼叫其中的資源。plat_serial8250_port定義在include/linux/serial_8250.h檔案中
 */
 static struct plat_serial8250_port serial_platform_data[] = {
     {
         .membase    = (char *)IO_ADDRESS(DAVINCI_UART0_BASE),    // 串列埠0暫存器開始處的虛擬地址是IO_ADDRESS(0x01C20000)
         .mapbase    = (unsigned long)DAVINCI_UART0_BASE,        // 串列埠0暫存器開始處的實地址是0x01C20000
         .irq        = IRQ_UARTINT0,                                // 串列埠0的中斷號是40
         .flags        = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
         .iotype        = UPIO_MEM32,
         .regshift    = 2,
         .uartclk    = DAVINCI_UART_CLK,                            // 串列埠時鐘頻率是27MHz
     },
     {
         .flags    = 0,
     },
 };
 
/* 見上述解釋。platform_device定義在include/linux/device.h檔案中
 * 一般platform_device在系統啟動的時候就註冊了,而其相應到驅動platform_driver或device_driver可在模組中載入。
 * http://hi.baidu.com/zengzhaonong/blog/item/440bb91e57e5251a413417d9.html 有關於platform_device結構體的詳細解釋
 */
 static struct platform_device serial_device    = {
     .name            = "serial8250",        // 這個名字很重要,與對應驅動中的機構體device_driver中的.name相同,其被驅動模組用來查詢裝置
     .id            = 0,                    // 例項名字尾為0
     .dev            = {
         .platform_data    = serial_platform_data,        // 裝置的私有資料或資源
     },
 };
 
/* 該資料結構定義了USB的私有資料,主要是usb的型別和功能,musb_hdrc_platform_data定義在include/linux/device.h檔案中 */
 static struct musb_hdrc_platform_data usb_data[] = {
     {
 #if defined(CONFIG_USB_MUSB_OTG)
         /* OTG requires a Mini-AB connector */
         .mode        = MUSB_OTG,                    // OTG型別的usb模組,既可以作usb裝置也可以作主機usb使用
 #elif defined(CONFIG_USB_MUSB_PERIPHERAL)
         .mode        = MUSB_PERIPHERAL,
 #elif defined(CONFIG_USB_MUSB_HOST)                // usb裝置
         .mode        = MUSB_HOST,                // 主機usb,類似於電腦的usb功能
 #endif
         .set_vbus    = NULL,
         /* irlml6401 switches 5V */
         .power        = 255, /* sustains 3.0+ Amps (!) */
         .potpgt        = 4, /* ~8 msec */
         .multipoint    = 1,                        // 1個收發埠
     },        /* Need Multipoint support */
 };
 
/* 該資料結構定義了USB的硬體資源, resource定義在include/linux/ioport.h檔案中 */
 static struct resource usb_resources[] = {
     {
         /* physical address */
         .start        = DAVINCI_USB_OTG_BASE,            // USB_OTG暫存器起始處的實地址是0x01C20000
         .end        = DAVINCI_USB_OTG_BASE + 0x5ff,    // USB_OTG暫存器末尾處的實地址是0x01C20000
         .flags        = IORESOURCE_MEM,                // 標識為IO地址資源
     },
     {
         .start        = IRQ_USBINT,                    // USB_OTG中斷號是12
         .flags        = IORESOURCE_IRQ,                // 標識為中斷資源
     },
 };
 
static u64 usb_dmamask = DMA_32BIT_MASK;
 
/* usb的platform_device結構體,用於註冊usb裝置*/
 static struct platform_device usb_dev = {
     .name        = "musb_hdrc",                    // 與對應驅動中的名字相同,用於繫結驅動   
     .id        = -1,                                // -1表示只有一個例項,無數字字尾
     .dev        = {
         .platform_data = usb_data,                // USB的私有資料
         .dma_mask = &usb_dmamask,                // 32位的dma
         .coherent_dma_mask = DMA_32BIT_MASK,
     },
     .resource    = usb_resources,                // USB的硬體資源
     .num_resources    = ARRAY_SIZE(usb_resources),
 };
 
/* 返回cpu的型別:DaVinci EVM*/
 /**************************************************************************
  * Public Functions
  **************************************************************************/
 int cpu_type(void)
 {
     return MACH_TYPE_DAVINCI_EVM;
 }
 
/* 串列埠初始化,主要的工作是開啟串列埠時鐘,定義在arch/arm/mach-davinci/serial.c檔案中*/
 extern void davinci_serial_init(struct platform_device *pdev);
 
/*如果在menuconfig中配置了使用nand啟動系統,則下面的的程式碼將會被編譯。
 * mtd_partition定義在include/linux/mtd/partitions.h檔案中
 */
 #if defined (CONFIG_MTD_NAND_DAVINCI) || defined(CONFIG_MTD_NAND_DAVINCI_MODULE)
 static struct mtd_partition nand_partitions[] = {
     /* bootloader (U-Boot, etc) in first sector */
     {
         .name        = "bootloader",            // bootloader,一般使用u-boot
         .offset        = 0,                    // 從mtd分割槽開始地址的偏移量是0
         .size        = SZ_256K,                // 分割槽大小是256K
         .mask_flags    = 0,    /* force read-only */    // 只讀
     },
     /* bootloader params in the next sector */
     {   
         .name        = "params",                // 存放bootloader的引數
         .offset        = MTDPART_OFS_APPEND,    // 從上一分割槽(bootloader分割槽)開始
         .size        = SZ_128K,               
         .mask_flags    = MTD_WRITEABLE,    /* force read-only */    // 可寫
     },
     /* kernel */
     {
         .name        = "kernel",                // 存放核心
         .offset        = MTDPART_OFS_APPEND,
         .size        = SZ_4M,
         .mask_flags    = 0,
     },
     /* file system */
     {
         .name        = "filesystem",            // 存放檔案系統
         .offset        = MTDPART_OFS_APPEND,
         .size        = MTDPART_SIZ_FULL,        // 整個分割槽的剩餘儲存空間
         .mask_flags    = 0,
     }
 };
 
/* nand platform device 私有資料,用於描述nand flash banks
 * nand_davinci_platform_data定義在include/linux/nand_davinci.h檔案中
 */
 static struct nand_davinci_platform_data nand_data = {
     .options        = 0,               
     .eccmode        = NAND_ECC_HW3_512,        // 校驗模式
     .cle_mask        = 0x10,
     .ale_mask        = 0x08,
     .bbt_td            = NULL,
     .bbt_md