其中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) |