日期:2014-05-16  浏览次数:20555 次

linux下点灯问题
硬件平台:OMAP-L138
软件平台:linux-2.6.32+VMware

问题描述:
板子上有个CPLD,CPLD的逻辑关系开发商不给,只给了文档描述,如下:


我自己写了个字符驱动用来控制灯的状态:
代码如下:
C/C++ code

static int __init hello_init(void)
{
        unsigned long led_addr;

        led_addr = (unsigned long)ioremap(0x64000040,0x08);

        printk("\nled_addr is 0x%x.\n",led_addr);

        writel(0x00,led_addr);

        iounmap(led_addr);

        printk("\nhelloword:: Hello module is installed!!!!!!\n");

        return 0;
}




动态加载的信息如下:
root@seed:/opt# insmod first_driver_hello.ko

led_addr is 0xc4888040.

helloword:: Hello module is installed!!!!!!
root@seed:/opt# 

但是灯没有点亮,已证实硬件没有问题,请高手指点~~~

------解决方案--------------------
不要这么直接嘛
先试试读写是否正常
先读 再写 再读,看看你的写入是否有效果
------解决方案--------------------
随便在内核里找了段代码
if (!request_mem_region(up->port.mapbase, size, "serial")) {
ret = -EBUSY;
break;
}

if (up->port.flags & UPF_IOREMAP) {
up->port.membase = ioremap_nocache(up->port.mapbase,
size);
if (!up->port.membase) {
release_mem_region(up->port.mapbase, size);
ret = -ENOMEM;
}
}

这里你应该先request_mem_region
此外建议使用ioread8 iowrite8 这样的api
------解决方案--------------------
C/C++ code

这个驱动,请根据你的需要进行修改。
#include <linux/config.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fcntl.h>
#include <linux/fs.h>
#include <linux/types.h>
#include <linux/input.h>

#include <asm/io.h>



void *R_GPBCON;
void *R_GPBDAT;

static u32 resave_gpbcon;
static u32 resave_gpbdat;

static struct input_dev my_led_dev;


static void iomap_gpb(void)
{
    R_GPBCON = ioremap(0x56000010,0x4);
    R_GPBDAT = ioremap(0x56000014,0x4);
}

static void unmap_gpb(void)
{
    iounmap(R_GPBCON);
    iounmap(R_GPBDAT);
}



static void init_led_reg(void)
{
    u32 temp;

    resave_gpbcon = __raw_readl(R_GPBCON);
    resave_gpbdat = __raw_readl(R_GPBDAT);
    
    temp = resave_gpbcon & (~(0xff << 10));
    temp |= ((0x1 << 10) | (0x1 << 12)| \
                     (0x1 << 14) | (0x1 << 16));
    __raw_writel(temp,R_GPBCON);


    temp = resave_gpbdat | ( 0xf << 5);
    __raw_writel(temp,R_GPBDAT);    
}


static void resave_led_reg(void)
{
    __raw_writel(resave_gpbcon,R_GPBCON);
    __raw_writel(resave_gpbdat,R_GPBDAT);
}


static int my_led_event(struct input_dev *dev, \
       unsigned int type, unsigned int code, int value)
       
{
    u32 temp;
        
    if (type != EV_LED)
        return -1;

    switch (code) {
        case LED_NUML: 
            break;
        default: 
            return -1;
    }
    
    temp = __raw_readl(R_GPBDAT);
    temp &= (~(0xf << 5));

    __raw_writel(temp | value,R_GPBDAT);
    
    return 0;
}

static int __init my_led_init(void)
{
    init_input_dev(&my_led_dev);
    
    my_led_dev.evbit[0] = BIT(EV_LED);
    my_led_dev.ledbit[0] = BIT(LED_NUML);
    my_led_dev.event = my_led_event;

    my_led_dev.name = "my_led_name";
    my_led_dev.phys = "my_led_phys";
    my_led_dev.id.bustype = BUS_HOST;
    my_led_dev.id.vendor = 0x001f;
    my_led_dev.id.product = 0x0001;
    my_led_dev.id.version = 0x0100;
    
    iomap_gpb();
    init_led_reg();

    input_register_device(&my_led_dev);
    return 0;
}

static void __exit my_led_exit(void)
{
        resave_led_reg();
        unmap_gpb();
        
    input_unregister_device(&my