iTop4412驱动开发之六:ioremap物理地址映射到虚拟内存用法

    技术2024-08-04  63

    说明:在linux系统内,一切程序都运行在虚拟内存中,无法直接操作物理内存地址,可用ioremap函数完成物理地址到虚拟内存的映射,然后通过虚拟地址实现操作硬件物理地址。

    void __iomem * ioremap (unsigned long phys_addr, unsigned long size); 参数1 phys_addr:物理地址。 参数2 size :从映射的物理地址开始,总共多少个字节。

    #include <linux/init.h> #include <linux/module.h> #include <linux/cdev.h> #include <linux/types.h> #include <linux/fs.h> #include <linux/errno.h> #include <linux/mm.h> #include <asm/io.h> #include <asm/system.h> #include <asm/uaccess.h> #include <linux/slab.h> #include <linux/delay.h> #include <linux/interrupt.h> #include <linux/ioremap.h> #include <linux/gpio.h> #include <plat/gpio-cfg.h> #include <mach/gpio.h> #include <mach/gpio-exynos4.h> #include <linux/platform_device.h> #include <mach/regs-gpio.h> #include <asm/io.h> #include <linux/regulator/consumer.h> #define DRIVER_NAME "ioremap_test" volatile unsigned long virt_addr, phys_addr; volatile unsigned long *GPL2CON, *GPL2DAT, *GPL2PUD; struct resource *ioresource = NULL; void gpl2_device_init(void) { phys_addr = 0x11000100; ioresource = request_mem_region(phys_addr, 0x10, "GPL2"); virt_addr = (unsigned long)ioremap(phys_addr, 0x10); GPL2CON = (unsigned long *)(virt_addr + 0x00); GPL2DAT = (unsigned long *)(virt_addr + 0x04); GPL2PUD = (unsigned long *)(virt_addr + 0x08); } void gpl2_config(void) { *GPL2CON |= 0x00000001; *GPL2PUD |= 0x0003; } unsigned long gpl2_data(void) { return ioread32(GPL2DAT); } void gpl2_on(void) { printk("GPL2 ON.\n"); unsigned long data = ioread32(GPL2DAT); iowrite32(data | 0x01, GPL2DAT); } void gpl2_off(void) { printk("GPL2 OFF.\n"); unsigned long data = ioread32(GPL2DAT); iowrite32(data & 0xfe, GPL2DAT); } static int led_gpios[] = { //EXYNOS4_GPL2(0), EXYNOS4_GPK1(1), }; #define LED_NUM 1 static ioremapreturn_t eint9_interrupt(int ioremap, void *dev_id) { printk("%s-%d\n", __FUNCTION__, __LINE__); if (gpl2_data() & 0x1) { gpl2_off(); } else { gpl2_on(); } return ioremap_HANDLED; } static ioremapreturn_t eint10_interrupt(int ioremap, void *dev_id) { printk("%s-%d\n", __FUNCTION__, __LINE__); if (gpio_get_value(led_gpios[1])) { gpio_set_value(led_gpios[1], 0); } else { gpio_set_value(led_gpios[1], 1); } return ioremap_HANDLED; } static int ioremap_probe(struct platform_device *pdev) { int ret, i; char *banner = "ioremap_test init.\n"; printk(banner); //初始化LED控制GPIO gpl2_device_init(); gpl2_config(); ret = gpio_request(EXYNOS4_GPX1(1), "EINT9"); s3c_gpio_cfgpin(EXYNOS4_GPX1(1), S3C_GPIO_SFN(0XF)); s3c_gpio_setpull(EXYNOS4_GPX1(1), S3C_GPIO_PULL_UP); gpio_free(EXYNOS4_GPX1(1)); ret = gpio_request(EXYNOS4_GPX1(2), "EINT10"); s3c_gpio_cfgpin(EXYNOS4_GPX1(2), S3C_GPIO_SFN(0XF)); s3c_gpio_setpull(EXYNOS4_GPX1(2), S3C_GPIO_PULL_UP); gpio_free(EXYNOS4_GPX1(2)); ret = request_ioremap(ioremap_EINT(9), eint9_interrupt, ioremap_TYPE_EDGE_FALLING, "eint9", pdev); ret = request_ioremap(ioremap_EINT(10), eint10_interrupt, ioremap_TYPE_EDGE_FALLING, "eint9", pdev); return 0; } static int ioremap_remove(struct platform_device *pdev) { iounmap(virt_addr); release_mem_region(ioresource, 0x10); release_region(phys_addr, 0x10); } static struct platform_driver ioremap_driver = { .probe = ioremap_probe, .remove = ioremap_remove, .driver = { .name = DRIVER_NAME, .owner = THIS_MODULE, } }; struct platform_device ioremap_dev = { .name = "ioremap_test", .id = -1, }; static int __init ioremap_test_init(void) { platform_device_register(&ioremap_dev); platform_driver_register(&ioremap_driver); } static void __exit ioremap_test_exit(void) { platform_driver_unregister(&ioremap_driver); platform_device_unregister(&ioremap_dev); } module_init(ioremap_test_init); module_exit(ioremap_test_exit); MODULE_LICENSE("Dual BSD/GPL");
    Processed: 0.010, SQL: 9