您的位置:首页 > 运维架构 > Linux

Davinci DM6446 Linux 内核分析——io.c

2013-06-11 17:10 411 查看
/*

* linux/arch/arm/mach-davinci/io.c

*

* DaVinci I/O mapping code

*

* Copyright (C) 2005-2006 Texas Instruments

*

* 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 <linux/module.h>

#include <linux/kernel.h>

#include <linux/init.h>

#include <asm/tlb.h>

#include <asm/io.h>

#include <asm/mach/map.h>

#include <asm/arch/memory.h>

#include <asm/arch/cpu.h>

#include <asm/arch/mux.h>

/*

该文件实现了DM644x平台的IO寄存器物理地址到虚拟地址的映射和IRAM的物理地址到虚拟地址的映射,

以及模块时钟的注册和复用引脚的初始化。

*/

extern int davinci_clk_init(void);

extern void davinci_check_revision(void);

unsigned int davinci_cpu_index = DM644X_CPU_IDX; // 0

/*

* The machine specific code may provide the extra mapping besides the

* default mapping provided here.

*/

static struct map_desc davinci_io_desc[] __initdata = {

{

.virtual = IO_VIRT, // 0xe1000000

.physical = IO_PHYS, // 0x01c00000

.length = IO_SIZE, // 4M

.type = MT_DEVICE,

},

};

// 针对DM644x平台的映射

static struct map_desc dm644x_io_desc[] __initdata = {

{

.virtual = DAVINCI_IRAM_VIRT, // IO_VIRT+IO_SIZE+4M

.physical = DAVINCI_IRAM_BASE, // 0x00008000

.length = DAVINCI_IRAM_SIZE, // 16K

.type = MT_DEVICE,

},

};

// 针对DM646x平台的映射

static struct map_desc dm646x_io_desc[] __initdata = {

{

.virtual = DM646X_IO_VIRT,

.physical = DM646X_IO_PHYS,

.length = DM646X_IO_SIZE,

.type = MT_DEVICE,

},

{

.virtual = DAVINCI_IRAM_VIRT,

.physical = DM646X_IRAM_BASE,

.length = DAVINCI_IRAM_SIZE,

.type = MT_DEVICE,

},

{

.virtual = EMIF_CNTRL_VIRT,

.physical = DAVINCI_DM646X_ASYNC_EMIF_CNTRL_BASE,

.length = SZ_16K,

.type = MT_DEVICE,

},

};

/*

IO内存初始化。

davinci_map_common_io()例程被davinci_map_io()例程调用,而其又被注册到board_evm.c中的

机器描述符中(struct machine_desc),故具体调用过程是:

start_kernel()-->setup_arch()-->paging_init()-->mdesc->map_io()

(其就是davinci_map_io())-->davinci_map_common_io()。

*/

void __init davinci_map_common_io(void)

{

// 创建IO寄存器物理地址到虚拟地址的映射,不cache

iotable_init(davinci_io_desc, ARRAY_SIZE(davinci_io_desc));

/* We want to check CPU revision early for cpu_is_davinci_xxxx() macros.

* IO space mapping must be initialized before we can do that.

*/

// 从寄存器中读取达芬奇平台版本号并打印

davinci_check_revision();

// 根据不同的平台映射IRAM的物理地址到虚拟地址,不cache

if (cpu_is_davinci_dm644x()) {

iotable_init(dm644x_io_desc, ARRAY_SIZE(dm644x_io_desc));

} else if (cpu_is_davinci_dm6467()) {

davinci_cpu_index = DM6467_CPU_IDX;

iotable_init(dm646x_io_desc, ARRAY_SIZE(dm646x_io_desc));

} else if (cpu_is_davinci_dm355()) {

davinci_cpu_index = DM355_CPU_IDX;

}

/* Normally devicemaps_init() would flush caches and tlb after

* mdesc->map_io(), but we must also do it here because of the CPU

* revision check below.

*/

flush_tlb_all();

flush_cache_all();

// 初始化各服用功能引脚(与GPIO引脚复用)

davinci_mux_init();

// 注册模块时钟,以便使用模块时申请

davinci_clk_init();

}

io.h

/*

* linux/include/asm-arm/arch-davinci/io.h

*

* Copyright (C) 2006 Texas Instruments.

*

* This program is free software; you can redistribute it and/or modify it

* under the terms of the GNU General Public License as published by the

* Free Software Foundation; either version 2 of the License, or (at your

* option) any later version.

*

* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED

* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF

* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN

* NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,

* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT

* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF

* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON

* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT

* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF

* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

*

* You should have received a copy of the GNU General Public License along

* with this program; if not, write to the Free Software Foundation, Inc.,

* 675 Mass Ave, Cambridge, MA 02139, USA.

*

*/

#ifndef __ASM_ARCH_IO_H

#define __ASM_ARCH_IO_H

#include <asm/arch/hardware.h>

#include <asm/types.h>

#define IO_SPACE_LIMIT 0xffffffff

/*

* ----------------------------------------------------------------------------

* I/O mapping

* ----------------------------------------------------------------------------

*/

#define IO_PHYS 0x01c00000

#define IO_VIRT 0xe1000000

#define IO_SIZE SZ_4M

/* DM646X need to map 0x02000000-0x02400000 to 0x0e1400000-0x0e1800000*/

/* This is put in the generic section so IRAM is mapped the same between

DaVinci and DM646X - Note that this will leave a hole for DaVinci */

#define DM646X_IO_PHYS 0x02000000

#define DM646X_IO_VIRT (IO_VIRT + IO_SIZE)

#define DM646X_IO_SIZE SZ_4M

#define DAVINCI_IRAM_VIRT (DM646X_IO_VIRT + DM646X_IO_SIZE)

/* after 4M of IO space */

#define DAVINCI_IRAM_SIZE SZ_16K

/*

* DM644X specific mappings

*/

/* DaVinci IRAM mapping */

#define DAVINCI_IRAM_BASE 0x00008000 /* ARM Internal RAM (Data) */

/* handle VLYNQ remap */

#define VLYNQ_REMOTE_PHYS 0x0C000000

#define VLYNQ_REMOTE_VIRT DAVINCI_IRAM_VIRT + DAVINCI_IRAM_SIZE

#define VLYNQ_REMOTE_SIZE SZ_64M

#define VLYNQ_PHYS_TO_VIRT(addr) ((addr) - (VLYNQ_REMOTE_PHYS) + \

(VLYNQ_REMOTE_VIRT))

#define VLYNQ_VIRT_TO_PHYS(addr) ((addr) + (VLYNQ_REMOTE_PHYS) - \

(VLYNQ_REMOTE_VIRT))

/*

* DM646X specific mappings

*/

/* IRAM mappings */

#define DM646X_IRAM_BASE 0x00010000 /* ARM Internal RAM (Data) */

/* handle DM646X EMIF remap */

#define EMIF_CNTRL_VIRT (DAVINCI_IRAM_VIRT + DAVINCI_IRAM_SIZE)

#define EMIF_P2V(addr) ((emifregsovly) \

((addr) - (DAVINCI_DM646X_ASYNC_EMIF_CNTRL_BASE) + (EMIF_CNTRL_VIRT)))

/*

* cconversion functions

*/

/* IO寄存器虚拟地址和物理地址转换api。因为是线性映射的,所以转换器来很容易 */

#define io_p2v(pa) (((pa) - (IO_PHYS)) + IO_VIRT)

#define io_v2p(va) (((va) - (IO_VIRT)) + IO_PHYS)

#define IO_ADDRESS(x) io_p2v(x)

/*

* We don't actually have real ISA nor PCI buses, but there is so many

* drivers out there that might just work if we fake them...

*/

#define PCIO_BASE 0

#define __io(a) ((void __iomem *)(PCIO_BASE + (a)))

#define __mem_pci(a) (a)

#define __mem_isa(a) (a)

#ifndef __ASSEMBLER__

/*

* Functions to access the DaVinci IO region

*

* NOTE: - Use davinci_read/write[bwl] for physical register addresses

* - Use __raw_read/write[bwl]() for virtual register addresses

* - Use IO_ADDRESS(phys_addr) to convert registers to virtual addresses

* - DO NOT use hardcoded virtual addresses to allow changing the

* IO address space again if needed

所有的指针强制类型转换中都加了volatile修饰符,防止IO地址被cache

*/

#define davinci_readb(a) (*(volatile unsigned char *)IO_ADDRESS(a))

#define davinci_readw(a) (*(volatile unsigned short *)IO_ADDRESS(a))

#define davinci_readl(a) (*(volatile unsigned int *)IO_ADDRESS(a))

#define davinci_writeb(v,a) (*(volatile unsigned char *)IO_ADDRESS(a) = (v))

#define davinci_writew(v,a) (*(volatile unsigned short *)IO_ADDRESS(a) = (v))

#define davinci_writel(v,a) (*(volatile unsigned int *)IO_ADDRESS(a) = (v))

/* 16 bit uses LDRH/STRH, base +/- offset_8 */

typedef struct { volatile u16 offset[256]; } __regbase16;

#define __REGV16(vaddr) ((__regbase16 *)((vaddr)&~0xff)) \

->offset[((vaddr)&0xff)>>1]

#define __REG16(paddr) __REGV16(io_p2v(paddr))

/* 8/32 bit uses LDR/STR, base +/- offset_12 */

typedef struct { volatile u8 offset[4096]; } __regbase8;

#define __REGV8(vaddr) ((__regbase8 *)((vaddr)&~4095)) \

->offset[((vaddr)&4095)>>0]

#define __REG8(paddr) __REGV8(io_p2v(paddr))

typedef struct { volatile u32 offset[4096]; } __regbase32;

#define __REGV32(vaddr) ((__regbase32 *)((vaddr)&~4095)) \

->offset[((vaddr)&4095)>>2]

/* FIXME: Just for compilation sake changed from __REG32 to __REG */

#define __REG(paddr) __REGV32(io_p2v(paddr))

extern void davinci_map_common_io(void);

extern void davinci_init_common_hw(void);

#else

#define __REG(x) (*((volatile unsigned long *)io_p2v(x)))

#endif

#endif /* __ASM_ARCH_IO_H */
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: