本来想做的是Android APP方向的工作,结果稀里糊涂的就干起了驱动。长话短说,作为人生中的第一个驱动,当灯终于亮起来的时候,还是蛮感动的,菜鸟真的很感动的说。
AW9523B分为2种工作模式,分别为GPIO模式和LED模式,由于刚开始的时候并不熟悉驱动编写,也根本没有仔细看数据手册的习惯(计算机专业的通病吗?),所以开始的道路真是曲折的不行。后来在带头大哥的英明指导下,终于发现了这茬,通过配置12H和13H寄存器 可以将P0_1-7和P1_1-7的工作模式切换,默认都是GPIO模式,若想将某个IO口配为LED模式,则将改为写0;
开始的时候由于不知道有LED模式这种东西的存在,傻乎乎的就开搞了,虽然结果不咋地,但是好歹是亮起来了。
首先,从probe函数开始:
static int led_probe(struct i2c_client *client, const struct i2c_device_id *id)
{
struct led_data *led;
int err;
led = kzalloc(sizeof(struct led_data), GFP_KERNEL);
if (!led) {
printk("[led]:alloc data failed.n");
err = -ENOMEM;
goto exit_alloc_data_failed;
}
printk(" ++++value=%x ++++n ",client->addr);
INIT_WORK(&led->work, led_work_func);
INIT_DELAYED_WORK(&led->delaywork, led_delaywork_func);
schedule_work(&led->work);
led->client = client;
i2c_set_clientdata(client, led);
this_client = client;
err = led_init_client(client);
if (err < 0) {
printk(KERN_ERR
"led_probe: led_init_client failedn");
goto exit_request_gpio_irq_failed;
}
iomux_set(GPIO1_A6);
mdelay(100);
gpio_request(RK30_PIN1_PA6, "i2c_led-start");
mdelay(50);
gpio_direction_output(RK30_PIN1_PA6, 1);
printk("============in func:%s, LINE:%d ==============n", __func__, __LINE__);
light_red_on();
// led_start(client, LED_RATE_32);
led_device.parent = &client->dev;
err = misc_register(&led_device);
if (err < 0) {
printk(KERN_ERR
"led_probe: led_device register failedn");
return 0;
}
err = i2c0_led_sysfs_init();
if (err < 0) {
printk(KERN_ERR
"led_probe: i2c0_led sysfs init failedn");
goto exit_i2c0_led_sysfs_init_failed;
}
printk(KERN_INFO "led probe okn");
return 0;
exit_i2c0_led_sysfs_init_failed:
misc_deregister(&led_device);
exit_request_gpio_irq_failed:
kfree(led);
exit_alloc_data_failed:
;
return err;
}
其实回过头再看,探测函数是非常的简单啊,无非就是申请内存,定义工作队列以及定义sys文件系统。
然后就是很重要的I2C读写函数了:
static int led_rx_data(struct i2c_client *client, char *rxData, int length)
{
int ret = 0;
char reg = rxData[0];
ret = i2c_master_reg8_recv(client, reg, rxData, length, LED_SPEED);
printk("led_rx_data++++++++++++++++++++++n");
return (ret > 0)? 0 : ret;
}
static int led_tx8_data(struct i2c_client *client, char *txData, int length)
{
int ret = 0;
char reg = txData[0];
printk("led_tx8_data++++++++++++++++++++++n");
ret = i2c_master_reg8_send(client, reg, &txData[1], length-1, LED_SPEED);
printk("led_tx8_data++++++++++++++++++++++n");
return (ret > 0)? 0 : ret;
}
创建sys节点:
static int i2c0_led_sysfs_init(void)
{
int ret ;
android_i2c0_led_kobj = kobject_create_and_add("android_i2c0_led", NULL);
if (android_i2c0_led_kobj == NULL) {
printk(KERN_ERR
"i2c0_led_sysfs_init:"
"subsystem_register failedn");
ret = -ENOMEM;
goto err;
}
ret = sysfs_create_file(android_i2c0_led_kobj, &dev_attr_i2c0_led.attr);
if (ret) {
printk(KERN_ERR
"i2c0_led_sysfs_init:"
"sysfs_create_group failedn");
goto err4;
}
printk("i2c_led_sysfs_init ++++++++++++++++n");
return 0 ;
err4:
kobject_del(android_i2c0_led_kobj);
err:
return ret ;
}
由于硬件工程师将18个灯分别挂到四条I2C总线上,所以本菜鸟很聪明的写了四个I2C设备驱动,简单粗暴。开始的时候怎么都亮不了,硬件工程师检测I2C也是有供电的,后来自己瞎琢磨半天,才发现原来 是由于复位脚没有拉高,所以I2C设备根本都没有工作起来,不管咋说,瞎整瞎整总算是也把灯给点亮了,算是涨姿势了,哈哈。
明天尝试下LED模式下的LED驱动编写,加油。
本来想做的是Android APP方向的工作,结果稀里糊涂的就干起了驱动。长话短说,作为人生中的第一个驱动,当灯终于亮起来的时候,还是蛮感动的,菜鸟真的很感动的说。
AW9523B分为2种工作模式,分别为GPIO模式和LED模式,由于刚开始的时候并不熟悉驱动编写,也根本没有仔细看数据手册的习惯(计算机专业的通病吗?),所以开始的道路真是曲折的不行。后来在带头大哥的英明指导下,终于发现了这茬,通过配置12H和13H寄存器 可以将P0_1-7和P1_1-7的工作模式切换,默认都是GPIO模式,若想将某个IO口配为LED模式,则将改为写0;
开始的时候由于不知道有LED模式这种东西的存在,傻乎乎的就开搞了,虽然结果不咋地,但是好歹是亮起来了。
首先,从probe函数开始:
static int led_probe(struct i2c_client *client, const struct i2c_device_id *id)
{
struct led_data *led;
int err;
led = kzalloc(sizeof(struct led_data), GFP_KERNEL);
if (!led) {
printk("[led]:alloc data failed.n");
err = -ENOMEM;
goto exit_alloc_data_failed;
}
printk(" ++++value=%x ++++n ",client->addr);
INIT_WORK(&led->work, led_work_func);
INIT_DELAYED_WORK(&led->delaywork, led_delaywork_func);
schedule_work(&led->work);
led->client = client;
i2c_set_clientdata(client, led);
this_client = client;
err = led_init_client(client);
if (err < 0) {
printk(KERN_ERR
"led_probe: led_init_client failedn");
goto exit_request_gpio_irq_failed;
}
iomux_set(GPIO1_A6);
mdelay(100);
gpio_request(RK30_PIN1_PA6, "i2c_led-start");
mdelay(50);
gpio_direction_output(RK30_PIN1_PA6, 1);
printk("============in func:%s, LINE:%d ==============n", __func__, __LINE__);
light_red_on();
// led_start(client, LED_RATE_32);
led_device.parent = &client->dev;
err = misc_register(&led_device);
if (err < 0) {
printk(KERN_ERR
"led_probe: led_device register failedn");
return 0;
}
err = i2c0_led_sysfs_init();
if (err < 0) {
printk(KERN_ERR
"led_probe: i2c0_led sysfs init failedn");
goto exit_i2c0_led_sysfs_init_failed;
}
printk(KERN_INFO "led probe okn");
return 0;
exit_i2c0_led_sysfs_init_failed:
misc_deregister(&led_device);
exit_request_gpio_irq_failed:
kfree(led);
exit_alloc_data_failed:
;
return err;
}
其实回过头再看,探测函数是非常的简单啊,无非就是申请内存,定义工作队列以及定义sys文件系统。
然后就是很重要的I2C读写函数了:
static int led_rx_data(struct i2c_client *client, char *rxData, int length)
{
int ret = 0;
char reg = rxData[0];
ret = i2c_master_reg8_recv(client, reg, rxData, length, LED_SPEED);
printk("led_rx_data++++++++++++++++++++++n");
return (ret > 0)? 0 : ret;
}
static int led_tx8_data(struct i2c_client *client, char *txData, int length)
{
int ret = 0;
char reg = txData[0];
printk("led_tx8_data++++++++++++++++++++++n");
ret = i2c_master_reg8_send(client, reg, &txData[1], length-1, LED_SPEED);
printk("led_tx8_data++++++++++++++++++++++n");
return (ret > 0)? 0 : ret;
}
创建sys节点:
static int i2c0_led_sysfs_init(void)
{
int ret ;
android_i2c0_led_kobj = kobject_create_and_add("android_i2c0_led", NULL);
if (android_i2c0_led_kobj == NULL) {
printk(KERN_ERR
"i2c0_led_sysfs_init:"
"subsystem_register failedn");
ret = -ENOMEM;
goto err;
}
ret = sysfs_create_file(android_i2c0_led_kobj, &dev_attr_i2c0_led.attr);
if (ret) {
printk(KERN_ERR
"i2c0_led_sysfs_init:"
"sysfs_create_group failedn");
goto err4;
}
printk("i2c_led_sysfs_init ++++++++++++++++n");
return 0 ;
err4:
kobject_del(android_i2c0_led_kobj);
err:
return ret ;
}
由于硬件工程师将18个灯分别挂到四条I2C总线上,所以本菜鸟很聪明的写了四个I2C设备驱动,简单粗暴。开始的时候怎么都亮不了,硬件工程师检测I2C也是有供电的,后来自己瞎琢磨半天,才发现原来 是由于复位脚没有拉高,所以I2C设备根本都没有工作起来,不管咋说,瞎整瞎整总算是也把灯给点亮了,算是涨姿势了,哈哈。
明天尝试下LED模式下的LED驱动编写,加油。
举报