Chinaunix首页 | 论坛 | 博客
  • 博客访问: 533068
  • 博文数量: 174
  • 博客积分: 4177
  • 博客等级: 上校
  • 技术积分: 1827
  • 用 户 组: 普通用户
  • 注册时间: 2007-10-15 14:12
文章分类

全部博文(174)

文章存档

2018年(1)

2017年(1)

2013年(3)

2012年(9)

2010年(12)

2009年(5)

2008年(106)

2007年(37)

我的朋友

分类: LINUX

2008-06-24 01:02:15

    
     其中io_p2v的定义如下所示:

    *** include/asm-arm/arch-pxa/hardware.h:
    #define io_p2v(x) (0xf2000000 + ((x) & 0x01ffffff) + (((x) & 0x1c000000) >> 1))

    下面我们来看xhyper255_map_io()函数:其定义如下所示:

static void __init xhyper255_map_io(void)
{
    pxa_map_io();
    iotable_init(xhyper255_io_desc, ARRAY_SIZE(xhyper255_io_desc));

    /* SSP data pins */
    pxa_gpio_mode(GPIO23_SCLK_MD);
    pxa_gpio_mode(GPIO25_STXD_MD);
    pxa_gpio_mode(GPIO26_SRXD_MD);

    /* This enables the BTUART */
    pxa_gpio_mode(GPIO42_BTRXD_MD);
    pxa_gpio_mode(GPIO43_BTTXD_MD);
    pxa_gpio_mode(GPIO44_BTCTS_MD);
    pxa_gpio_mode(GPIO45_BTRTS_MD);

    GPSR(GPIO48_nPOE) =
        GPIO_bit(GPIO48_nPOE) |
        GPIO_bit(GPIO49_nPWE) |
        GPIO_bit(GPIO50_nPIOR) |
        GPIO_bit(GPIO51_nPIOW) |
        GPIO_bit(GPIO52_nPCE_1) |
        GPIO_bit(GPIO53_nPCE_2);

    pxa_gpio_mode(GPIO48_nPOE_MD);
    pxa_gpio_mode(GPIO49_nPWE_MD);
    pxa_gpio_mode(GPIO50_nPIOR_MD);
    pxa_gpio_mode(GPIO51_nPIOW_MD);
    pxa_gpio_mode(GPIO52_nPCE_1_MD);
    pxa_gpio_mode(GPIO53_nPCE_2_MD);
    pxa_gpio_mode(GPIO54_pSKTSEL_MD);
    pxa_gpio_mode(GPIO55_nPREG_MD);
    pxa_gpio_mode(GPIO56_nPWAIT_MD);
    pxa_gpio_mode(GPIO57_nIOIS16_MD);

    /* This is for the SMC chip select */
    pxa_gpio_mode(GPIO79_nCS_3_MD);

    /* setup sleep mode values */
    PWER  = 0x00000002;
    PFER  = 0x00000000;
    PRER  = 0x00000002;
    PGSR0 = 0x00008000;
    PGSR1 = 0x003F0202;
    PGSR2 = 0x0001C000;
    PCFR |= PCFR_OPDE;
}

    其中的pxa_map_io()定义如下:

*** arch/arm/mach-pxa/generic.c:
void __init pxa_map_io(void )
{
    iotable_init(standard_io_desc, ARRAY_SIZE(standard_io_desc));
      get_clk_frequency_khz(1);
}

    其中iotable_init()的定义如下:

*** arch/arm/mm/mmu.c:
/*                                                                                                                                            
 * Create the architecture specific mappings                                                                                                  
 */
void __init iotable_init(struct map_desc *io_desc, int nr)
{
        int i;

        for (i = 0; i < nr; i++)
                create_mapping(io_desc + i);
}
     由此可知,该函数的功能实际上是利用io_desc指针指向的nr个map_desc结构完成内存的映射,具体的映射细节我们暂且不追究。需要注意的是上述的映射是在有MMU的情况下调用的,如果没有MMU的话,则调用下面的函数:

*** include/asm-arm/mach/map.h:
#define iotable_init(map,num) do { } while (0)

    这是通过在上述map.h中的一个ifdef语句实现的,如下所示:

#ifdef CONFIG_MMU
extern void iotable_init(struct map_desc *, int);
#else
#define iotable_init(map,num)   do { } while (0)
#endif
   
    我们再来看它的参数,第一个参数是一个map_desc结构,它用来描述物理内存与虚拟内存之间的映射关系,定义如下:

*** include/asm-arm/mach/map.h:
struct map_desc {                                                    
        unsigned long virtual;                                        
        unsigned long pfn;                                            
        unsigned long length;                                        
        unsigned int type;                                            
}; 
其中type的可取的值如下,它们均定义于同一文件中

*** include/asm-arm/io.h:
#define MT_DEVICE               0
#define MT_DEVICE_NONSHARED     1
#define MT_DEVICE_CACHED        2
#define MT_DEVICE_IXP2000       3
*** include/asm-arm/mach/map.h:
#define MT_CACHECLEAN           4
#define MT_MINICLEAN            5
#define MT_LOW_VECTORS          6
#define MT_HIGH_VECTORS         7
#define MT_MEMORY               8
#define MT_ROM                  9

#define MT_NONSHARED_DEVICE     MT_DEVICE_NONSHARED
#define MT_IXP2000_DEVICE       MT_DEVICE_IXP2000

    下面我们再来看对应的实参,pxa_map_io()里面调用的iotable_init(standard_io_desc, ARRAY_SIZE(standard_io_desc))我们无需理会,因为这个映射是通用的,我们只需要看针对具体板子的映射,即xhyper255_map_io()里面调用的iotable_init(xhyper255_io_desc, ARRAY_SIZE(xhyper255_io_desc))函数,xhyper255_io_desc定义在xhyper255.c中,如下所示:

static struct map_desc xhyper255_io_desc[] __initdata = {
        {       /* CPLD */
        .virtual        =  LUBBOCK_FPGA_VIRT,
          .pfn            = __phys_to_pfn(LUBBOCK_FPGA_PHYS),
            .length         = 0x00100000,
            .type           = MT_DEVICE
    }
};

    剩下的就是对一些串口等的设置,在此就先不说了,到些xhyper255_map_io()函数完成。
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
                *** 中断初始化 ***

    下面来看中断初始化函数,与板子对应的就是xhyper255_init_irq(),定义如下:

***arch/arm/mach-pxa/xhyper255.c:
static void __init xhyper255_init_irq(void)
{
        int irq;

        pxa25x_init_irq();

    /* setup extra xhyper255 irqs */
        for (irq = LUBBOCK_IRQ(0); irq <= LUBBOCK_LAST_IRQ; irq++) {
                set_irq_chip(irq, &xhyper255_irq_chip);
            set_irq_handler(irq, handle_level_irq);
                set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
    }

    set_irq_chained_handler(IRQ_GPIO(0), xhyper255_irq_handler);
      set_irq_type(IRQ_GPIO(0), IRQT_FALLING);
}
    首先,是对pxa25x系列处理器中断的一个初始化,定义如下:

***arch/arm/mach-pxa/pxa25x.c:
void __init pxa25x_init_irq(void)
{
    pxa_init_irq_low();
    pxa_init_irq_gpio(85);
    pxa_init_irq_set_wake(pxa25x_set_wake);
}
     其中的三个函数均位于arch/arm/mach-pxa/irq.c,它们的功能这时暂时不做介绍,先继续往下看,这主要是针对具体的板子的一些中断的初始化,因而我们在移植的时候,这是我们需要重点关注的地方。它们完成的功能主要还是将特定的中断号与中断处理函数绑定。

***arch/arm/mach-pxa/irqs.h:
#define PXA_GPIO_IRQ_BASE    (64)
#define PXA_GPIO_IRQ_NUM    (128)
#define IRQ_BOARD_START        (PXA_GPIO_IRQ_BASE + PXA_GPIO_IRQ_NUM)
#define LUBBOCK_IRQ(x)        (IRQ_BOARD_START + (x))
...
#define LUBBOCK_LAST_IRQ    LUBBOCK_IRQ(6)

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
            *** timer初始化 ***

    map_desc的下一个成员是pxa_timer,它是一个sys_timer结构,定义如下:

*** include/asm-arm/mach/time.h:
/*                                                                                                                                            
 * This is our kernel timer structure.                                                                                                        
 *                                                                                                                                            
 * - init                                                                                                                                     
 *   Initialise the kernels jiffy timer source, claim interrupt                                                                               
 *   using setup_irq.  This is called early on during initialisation                                                                          
 *   while interrupts are still disabled on the local CPU.                                                                                    
 * - suspend                                                                                                                                  
 *   Suspend the kernel jiffy timer source, if necessary.  This                                                                               
 *   is called with interrupts disabled, after all normal devices                                                                             
 *   have been suspended.  If no action is required, set this to                                                                              
 *   NULL.                                                                                                                                    
 * - resume                                                                                                                                   
 *   Resume the kernel jiffy timer source, if necessary.  This                                                                                
 *   is called with interrupts disabled before any normal devices                                                                             
 *   are resumed.  If no action is required, set this to NULL.                                                                                
 * - offset                                                                                                                                   
 *   Return the timer offset in microseconds since the last timer                                                                             
 *   interrupt.  Note: this must take account of any unprocessed
 *   timer interrupt which may be pending.                                                                                                    
 */
struct sys_timer {
      struct sys_device       dev;
        void                    (*init)(void);
      void                    (*suspend)(void);
        void                    (*resume)(void);
#ifndef CONFIG_GENERIC_TIME
        unsigned long           (*offset)(void);
#endif

#ifdef CONFIG_NO_IDLE_HZ
        struct dyn_tick_timer   *dyn_tick;
#endif
};
struct dyn_tick_timer {
        spinlock_t      lock;
        unsigned int    state;                      /* Current state */
        int             (*enable)(void);            /* Enables dynamic tick */
        int             (*disable)(void);           /* Disables dynamic tick */
        void            (*reprogram)(unsigned long);     /* Reprograms the timer */
        int             (*handler)(int, void *);
};

*** arch/arm/mach-pxa/time.c:
struct sys_timer pxa_timer = {
        .init           = pxa_timer_init,
        .suspend        = pxa_timer_suspend,
        .resume         = pxa_timer_resume,
};
其中的三个函数也位于上述文件中。
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
            *** 板子初始化 ***

    map_desc的下一个成员是init_machine,用来对其赋值的是xhyper255_init(),这个主要用来对板子进行初始化,定义如下:

*** arch/arm/mach-pxa/xhyper255.c
static void __init xhyper255_init(void)
{
    int flashboot = (LUB_CONF_SWITCHES & 1);

    pxa_set_udc_info(&udc_info);
    set_pxa_fb_info(&sharp_lm8v31);
    pxa_set_mci_info(&xhyper255_mci_platform_data);
    pxa_set_ficp_info(&xhyper255_ficp_platform_data);

    xhyper255_flash_data[0].width = xhyper255_flash_data[1].width =
        (BOOT_DEF & 1) ? 2 : 4;
    /* Compensate for the nROMBT switch which swaps the flash banks */
    printk(KERN_NOTICE "Lubbock configured to boot from %s (bank %d)\n",
           flashboot?"Flash":"ROM", flashboot);

    xhyper255_flash_data[flashboot^1].name = "application-flash";
    xhyper255_flash_data[flashboot].name = "boot-rom";
    (void) platform_add_devices(devices, ARRAY_SIZE(devices));

    spi_register_board_info(spi_board_info, ARRAY_SIZE(spi_board_info));
}

首先是设置UDC(USB Device Controller)的信息,主要就是检测UDC是否连接上了

*** include/asm-arm/mach/udc_pxa2xx.h:
struct pxa2xx_udc_mach_info {
        int  (*udc_is_connected)(void);         /* do we see host? */
    void (*udc_command)(int cmd);
#define PXA2XX_UDC_CMD_CONNECT          0       /* let host see us */
#define PXA2XX_UDC_CMD_DISCONNECT       1       /* so host won't see us */

        /* Boards following the design guidelines in the developer's manual,                                                                  
         * with on-chip GPIOs not Lubbock's weird hardware, can have a sane                                                                   
         * VBUS IRQ and omit the methods above.  Store the GPIO number                                                                        
         * here; for GPIO 0, also mask in one of the pxa_gpio_mode() bits.                                                                    
         * Note that sometimes the signals go through inverters...                                                                            
         */
    bool    gpio_vbus_inverted;
        u16     gpio_vbus;                      /* high == vbus present */
    u16     gpio_pullup;                    /* high == pullup activated */
};

对应的变量及其赋的值分别为:

*** arch/arm/mach-pxa/xhyper255.c:
static struct pxa2xx_udc_mach_info udc_info __initdata = {
    .udc_is_connected    = xhyper255_udc_is_connected,
    // no D+ pullup; xhyper255 can't connect/disconnect in software
};
static int xhyper255_udc_is_connected(void)
{
    return (LUB_MISC_RD & (1 << 9)) == 0;
}
其中的LUB_MISC_RD定义如下:
*** include/asm-arm/arch-pxa/xhyper255.h:
#ifndef __ASSEMBLY__
#  define __LUB_REG(x)          (*((volatile unsigned long *)LUB_P2V(x)))
#else
#  define __LUB_REG(x)          LUB_P2V(x)
#endif

#define LUB_MISC_RD __LUB_REG(LUBBOCK_FPGA_PHYS + 0x090)


其次是设置FrameBuffer,

*** arch/arm/mach-pxa/xhyper255.c:
static struct pxafb_mode_info sharp_lm8v31_mode = {
    .pixclock    = 270000,
    .xres        = 640,
    .yres        = 480,
    .bpp        = 16,
    .hsync_len    = 1,
    .left_margin    = 3,
    .right_margin    = 3,
    .vsync_len    = 1,
    .upper_margin    = 0,
    .lower_margin    = 0,
    .sync        = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
    .cmap_greyscale    = 0,
};

static struct pxafb_mach_info sharp_lm8v31 = {
    .modes        = &sharp_lm8v31_mode,
    .num_modes    = 1,
    .cmap_inverse    = 0,
    .cmap_static    = 0,
    .lccr0        = LCCR0_SDS,
    .lccr3        = LCCR3_PCP | LCCR3_Acb(255),
};

*** include/asm-arm/arch-pxa/pxafb.h:
struct pxafb_mode_info {
        u_long          pixclock;

        u_short         xres;
        u_short         yres;

        u_char          bpp;
      u_char          hsync_len;
        u_char          left_margin;
        u_char          right_margin;

        u_char          vsync_len;
        u_char          upper_margin;
        u_char          lower_margin;
        u_char          sync;

        u_int           cmap_greyscale:1,
                        unused:31;
};

struct pxafb_mach_info {
        struct pxafb_mode_info *modes;
        unsigned int num_modes;

        u_int           fixed_modes:1,
                        cmap_inverse:1,
                        cmap_static:1,
                        unused:29;

        /* The following should be defined in LCCR0                                                                                           
         *      LCCR0_Act or LCCR0_Pas          Active or Passive                                                                             
         *      LCCR0_Sngl or LCCR0_Dual        Single/Dual panel                                                                             
         *      LCCR0_Mono or LCCR0_Color       Mono/Color                                                                                    
         *      LCCR0_4PixMono or LCCR0_8PixMono (in mono single mode)                                                                        
         *      LCCR0_DMADel(Tcpu) (optional)   DMA request delay                                                                             
         *                                                                                                                                    
         * The following should not be defined in LCCR0:                                                                                      
         *      LCCR0_OUM, LCCR0_BM, LCCR0_QDM, LCCR0_DIS, LCCR0_EFM                                                                          
         *      LCCR0_IUM, LCCR0_SFM, LCCR0_LDM, LCCR0_ENB                                                                                    
         */
        u_int           lccr0;
        /* The following should be defined in LCCR3                                                                                           
         *      LCCR3_OutEnH or LCCR3_OutEnL    Output enable polarity
         *      LCCR3_PixRsEdg or LCCR3_PixFlEdg Pixel clock edge type                                                                        
         *      LCCR3_Acb(X)                    AB Bias pin frequency                                                                         
         *      LCCR3_DPC (optional)            Double Pixel Clock mode (untested)                                                            
         *                                                                                                                                    
         * The following should not be defined in LCCR3                                                                                       
         *      LCCR3_HSP, LCCR3_VSP, LCCR0_Pcd(x), LCCR3_Bpp                                                                                 
         */
        u_int           lccr3;
        /* The following should be defined in LCCR4                                                                                           
         *      LCCR4_PAL_FOR_0 or LCCR4_PAL_FOR_1 or LCCR4_PAL_FOR_2                                                                         
         *                                                                                                                                    
         * All other bits in LCCR4 should be left alone.                                                                                      
         */
        u_int           lccr4;
        void (*pxafb_backlight_power)(int);
        void (*pxafb_lcd_power)(int, struct fb_var_screeninfo *);

};
 
阅读(1065) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~