omap-tps65010.c
来自「嵌入式系统中的,TPS65010 驱动程序, IIC 接口」· C语言 代码 · 共 505 行
C
505 行
#include <linux/module.h>
#include <linux/config.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/miscdevice.h>
#include <linux/ioctl.h>
#include <linux/proc_fs.h>
#include <linux/i2c.h>
#include <asm/io.h>
#include <asm/arch/pm.h>
#include "omap-tps65010.h"
#if 1
#define DBGPRINT(fmt, args...) printk(fmt, ##args)
#else
#define DBGPRINT(fmt, args...)
#endif
extern void tps_deep_sleep(void);
#define TPS_I2C_SLAVE_ADDR 0x48
#define TPS_VDCDC1_REG 0x0c
#define TPS_LP_BIT 0x08
#define TPS_SET_LP_BIT(v) ( v |= TPS_LP_BIT )
#define TPS_CLR_LP_BIT(v) ( v &= ~(TPS_LP_BIT) )
#define TPS_LED_REG 0x10
#define TPS_KB_LED_BIT 0x01
#define TPS_MAIN_LED_BIT 0x04
#define TPS_SUB_LED_BIT 0x02
#define TPS_ALL_LED_BIT ( TPS_KB_LED_BIT | TPS_MAIN_LED_BIT| TPS_SUB_LED_BIT )
#define TPS_SET_KB_LED_BIT(v) ( v |= TPS_KB_LED_BIT )
#define TPS_CLR_KB_LED_BIT(v) ( v &= ~(TPS_KB_LED_BIT) )
#define TPS_GET_KB_LED_BIT(v) ( (v & TPS_KB_LED_BIT) == TPS_KB_LED_BIT )
#define TPS_SET_MAIN_LED_BIT(v) ( v |= TPS_MAIN_LED_BIT )
#define TPS_CLR_MAIN_LED_BIT(v) ( v &= ~(TPS_MAIN_LED_BIT) )
#define TPS_GET_MAIN_LED_BIT(v) ( (v & TPS_MAIN_LED_BIT) == TPS_MAIN_LED_BIT )
#define TPS_SET_SUB_LED_BIT(v) ( v |= TPS_SUB_LED_BIT )
#define TPS_CLR_SUB_LED_BIT(v) ( v &= ~(TPS_SUB_LED_BIT) )
#define TPS_GET_SUB_LED_BIT(v) ( (v & TPS_SUB_LED_BIT) == TPS_SUB_LED_BIT )
#define TPS_SET_ALL_LED_BIT(v) ( v |= TPS_ALL_LED_BIT )
#define TPS_CLR_ALL_LED_BIT(v) ( v &= ~(TPS_ALL_LED_BIT) )
#define TPS_VIB_REG 0x0d
#define TPS_VIB_BIT 0x02
#define TPS_SET_VIB_BIT(v) ( v |= TPS_VIB_BIT )
#define TPS_CLR_VIB_BIT(v) ( v &= ~(TPS_VIB_BIT) )
#define TPS_GET_VIB_BIT(v) ( (v & TPS_VIB_BIT) == TPS_VIB_BIT )
#define TPS_QS6400_REG 0x10
#define TPS_QS6400_BIT 0x08
#define TPS_SET_QS6400_BIT(v) ( v |= TPS_QS6400_BIT )
#define TPS_CLR_QS6400_BIT(v) ( v &= ~(TPS_QS6400_BIT) )
static int tps_probe(struct i2c_adapter *adap);
static int tps_detach(struct i2c_client *client);
static struct i2c_driver tps_driver =
{
.name = "OMAP1510+TPS",
.id = I2C_DRIVERID_EXP0,
.flags = I2C_DF_NOTIFY,
.attach_adapter = tps_probe,
.detach_client = tps_detach,
};
static struct i2c_client tps_client =
{
.name = "OMAP1510+TPS",
.id = -1,
.adapter = NULL,
.driver = &tps_driver
};
static unsigned short normal_addr[] = { TPS_I2C_SLAVE_ADDR, I2C_CLIENT_END };
static unsigned short ignore[] = { I2C_CLIENT_END };
static struct i2c_client_address_data addr_data =
{
.normal_i2c = normal_addr,
.normal_i2c_range = ignore,
.probe = ignore,
.probe_range = ignore,
.ignore = ignore,
.ignore_range = ignore,
.force = ignore,
};
static int tps_attach(struct i2c_adapter *adap, int addr,
unsigned short flags, int kind)
{
u8 status;
DBGPRINT("%s\n", __FUNCTION__);
printk(KERN_INFO "TPS found @ 0x%x by %s\n", addr, adap->name);
tps_client.adapter = adap;
tps_client.addr = addr;
i2c_attach_client(&tps_client);
status = i2c_smbus_read_byte_data(&tps_client, TPS_LED_REG);
status |= 0xf0;
i2c_smbus_write_byte_data(&tps_client, TPS_LED_REG, status);
tps_set_lowpower(1);
return 0;
}
static int tps_probe(struct i2c_adapter *adap)
{
DBGPRINT("%s\n", __FUNCTION__);
return i2c_probe(adap, &addr_data, tps_attach);
}
static int tps_detach(struct i2c_client *client)
{
DBGPRINT("%s\n", __FUNCTION__);
i2c_detach_client(client);
return 0;
}
int tps_set_lowpower(int mode)
{
u8 vdcdc1;
DBGPRINT("%s: %d\n", __FUNCTION__, mode);
vdcdc1 = i2c_smbus_read_byte_data(&tps_client, TPS_VDCDC1_REG);
if ( mode )
TPS_SET_LP_BIT(vdcdc1);
else
TPS_CLR_LP_BIT(vdcdc1);
i2c_smbus_write_byte_data(&tps_client, TPS_VDCDC1_REG, vdcdc1);
return 0;
}
int tps_sleep(int mode)
{
DBGPRINT("%s: %d\n", __FUNCTION__, mode);
omap_pm_suspend();
return 0;
}
int tps_led_on(int led)
{
u8 status;
DBGPRINT("%s: %d\n", __FUNCTION__, led);
status = i2c_smbus_read_byte_data(&tps_client, TPS_LED_REG);
switch ( led )
{
case TPS_ALL_LED:
TPS_SET_ALL_LED_BIT(status);
break;
case TPS_KB_LED:
TPS_SET_KB_LED_BIT(status);
break;
case TPS_MAIN_LED:
TPS_SET_MAIN_LED_BIT(status);
break;
case TPS_SUB_LED:
TPS_SET_SUB_LED_BIT(status);
break;
default:
printk("%s: bad led number: %d\n", __FUNCTION__, led);
return -EINVAL;
}
i2c_smbus_write_byte_data(&tps_client, TPS_LED_REG, status);
return 0;
}
int tps_led_off(int led)
{
u8 status;
DBGPRINT("%s: %d\n", __FUNCTION__, led);
status = i2c_smbus_read_byte_data(&tps_client, TPS_LED_REG);
switch ( led )
{
case TPS_ALL_LED:
TPS_CLR_ALL_LED_BIT(status);
break;
case TPS_KB_LED:
TPS_CLR_KB_LED_BIT(status);
break;
case TPS_MAIN_LED:
TPS_CLR_MAIN_LED_BIT(status);
break;
case TPS_SUB_LED:
TPS_CLR_SUB_LED_BIT(status);
break;
default:
printk("%s: bad led number: %d\n", __FUNCTION__, led);
return -EINVAL;
}
i2c_smbus_write_byte_data(&tps_client, TPS_LED_REG, status);
return 0;
}
int tps_led_state(int led)
{
int ret = 0;
u8 status;
DBGPRINT("%s: %d\n", __FUNCTION__, led);
status = i2c_smbus_read_byte_data(&tps_client, TPS_LED_REG);
switch ( led )
{
case TPS_KB_LED:
ret = TPS_GET_KB_LED_BIT(status);
break;
case TPS_MAIN_LED:
ret = TPS_GET_MAIN_LED_BIT(status);
break;
case TPS_SUB_LED:
ret = TPS_GET_SUB_LED_BIT(status);
break;
default:
printk("%s: bad led number: %d\n", __FUNCTION__, led);
return -EINVAL;
}
return ret;
}
int tps_vib_cmd(int cmd)
{
u8 status;
DBGPRINT("%s: %d\n", __FUNCTION__, cmd);
status = i2c_smbus_read_byte_data(&tps_client, TPS_VIB_REG);
if ( cmd == TPS_VIB_RUN )
{
TPS_SET_VIB_BIT(status);
}
else
{
TPS_CLR_VIB_BIT(status);
}
i2c_smbus_write_byte_data(&tps_client, TPS_VIB_REG, status);
return 0;
}
int tps_vib_state(void)
{
u8 status;
DBGPRINT("%s\n", __FUNCTION__);
status = i2c_smbus_read_byte_data(&tps_client, TPS_VIB_REG);
return TPS_GET_VIB_BIT(status);
}
int tps_qs6400_wake(void)
{
u8 status;
DBGPRINT("%s\n", __FUNCTION__);
status = i2c_smbus_read_byte_data(&tps_client, TPS_QS6400_REG);
TPS_SET_QS6400_BIT(status);
i2c_smbus_write_byte_data(&tps_client, TPS_QS6400_REG, status);
udelay(10);
TPS_CLR_QS6400_BIT(status);
i2c_smbus_write_byte_data(&tps_client, TPS_QS6400_REG, status);
return 0;
}
static int tps_stats(char *buf, char **start, off_t offset,
int count, int *eof, void *data)
{
int len;
char * p = buf;
DBGPRINT("%s\n", __FUNCTION__);
p += sprintf(p, "TPS info: \n");
p += sprintf(p, " keypad led state: %d\n", tps_led_state(TPS_KB_LED));
p += sprintf(p, " main led state : %d\n", tps_led_state(TPS_MAIN_LED));
p += sprintf(p, " sub led state : %d\n", tps_led_state(TPS_SUB_LED));
p += sprintf(p, " VIB state : %d\n", tps_vib_state());
p += sprintf(p, " VDCDC1 REG : 0x%x\n", i2c_smbus_read_byte_data(&tps_client, TPS_VDCDC1_REG));
len = p - buf;
return len;
}
static int tps_ioctl(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg)
{
int ret = 0;
DBGPRINT("%s: cmd: 0x%x, arg: %ld\n", __FUNCTION__, cmd, arg);
switch(cmd)
{
case TPS_IOC_SLEEP:
ret = tps_sleep(arg);
break;
case TPS_IOC_LED_ON:
ret = tps_led_on(arg);
break;
case TPS_IOC_LED_OFF:
ret = tps_led_off(arg);
break;
case TPS_IOC_LED_STATE:
ret = tps_led_state(arg);
break;
case TPS_IOC_VIB_CMD:
ret = tps_vib_cmd(arg);
break;
case TPS_IOC_VIB_STATE:
ret = tps_vib_state();
break;
case TPS_IOC_QS6400_WAKE:
ret = tps_qs6400_wake();
break;
default:
printk("%s: bad ioctl cmd\n", __FUNCTION__);
ret = -EINVAL;
break;
}
return ret;
}
static int tps_open(struct inode *inode, struct file * filp)
{
int minor;
DBGPRINT("%s\n", __FUNCTION__);
minor = MINOR(inode->i_rdev);
if ( minor != TPS_MINOR )
{
return -ENODEV;
}
#ifdef MODULE
MOD_INC_USE_COUNT;
#endif
return 0;
}
static int tps_release(struct inode *inode, struct file *filp)
{
DBGPRINT("%s\n", __FUNCTION__);
#ifdef MODULE
MOD_DEC_USE_COUNT;
#endif
return 0;
}
static struct file_operations tps_fops =
{
owner: THIS_MODULE,
open: tps_open,
release: tps_release,
ioctl: tps_ioctl,
};
static struct miscdevice tps_miscdev =
{
TPS_MINOR,
"tps",
&tps_fops
};
static int __init tps_init(void)
{
int ret;
DBGPRINT("%s\n", __FUNCTION__);
ret = i2c_add_driver(&tps_driver);
if ( ret )
{
printk(KERN_INFO "failed to find TPS\n");
return ret;
}
misc_register(&tps_miscdev);
create_proc_read_entry(TPS_PROC_NAME, 0, NULL, tps_stats, NULL);
return 0;
}
static void __exit tps_exit(void)
{
DBGPRINT("%s\n", __FUNCTION__);
remove_proc_entry(TPS_PROC_NAME, NULL);
misc_deregister(&tps_miscdev);
i2c_del_driver(&tps_driver);
}
module_init(tps_init);
module_exit(tps_exit);
EXPORT_SYMBOL(tps_set_lowpower);
EXPORT_SYMBOL(tps_sleep);
EXPORT_SYMBOL(tps_led_on);
EXPORT_SYMBOL(tps_led_off);
EXPORT_SYMBOL(tps_led_state);
EXPORT_SYMBOL(tps_vib_cmd);
EXPORT_SYMBOL(tps_vib_state);
EXPORT_SYMBOL(tps_qs6400_wake);
MODULE_LICENSE("GPL");
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?