AD5669 IIC DAC driver

*/

/*!
 * @file ad5669.c
 *
 * @brief AD5669 voltage-output DAC driver
 *
 */

#include <linux/module.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/ctype.h>
#include <linux/types.h>
#include <linux/delay.h>
#include <linux/device.h>
#include <linux/fs.h>
#include <linux/i2c.h>

#define AD5669_IOCTL_WRITE_DA  _IOW(0, 1, unsigned long)

#define AD5669_CMD_WRITE_INPUT_N   0x0
#define AD5669_CMD_UPDATE_DAC_N    0x1
#define AD5669_CMD_WRITE_INPUT_N_UPDATE_ALL 0x2
#define AD5669_CMD_WRITE_INPUT_N_UPDATE_N 0x3
#define AD5669_CMD_POWERDOWN_DAC   0x4
#define AD5669_CMD_CLEAR     0x5
#define AD5669_CMD_LDAC_MASK    0x6
#define AD5669_CMD_RESET     0x7
#define AD5669_CMD_CONFIG     0x8

static struct {
 struct i2c_client *i2c_client;
 struct class *ad5669_class;
 int major;
} ad5669_data;

static int ad5669_probe(struct i2c_client *adapter, const struct i2c_device_id *id);
static int ad5669_remove(struct i2c_client *client);

static const struct i2c_device_id ad5669_id[] = {
 {"ad5669", 0},
 {},
};

MODULE_DEVICE_TABLE(i2c, ad5669_id);

static struct i2c_driver ad5669_i2c_driver = {
 .driver = {
     .owner = THIS_MODULE,
     .name = "ad5669",
     },
 .probe = ad5669_probe,
 .remove = __devexit_p(ad5669_remove),
 .id_table = ad5669_id,
};

static int ad5669_write_reg(u8 command, u16 val)
{
 char data[3];

 data[0] = command;
 data[1] = val >> 8;
 data[2] = val & 0xff;

 if (i2c_master_send(ad5669_data.i2c_client, data, 3) < 0) {
  dev_err(&ad5669_data.i2c_client->dev,
   "%s: write reg error: command = 0x%02X, val = 0x%04X\n", __func__,
   command, val);
  return -EIO;
 }

 return 0;
}

static ssize_t ad5669_read(struct file *file, char __user *buf, size_t len,
                                  loff_t *ppos)
{
 return 0;
}

static ssize_t ad5669_write(struct file *file, const char __user *data,
                                   size_t len, loff_t *ppos)
{
 return 0;
}

static int ad5669_open(struct inode *inode, struct file *file)
{
 return 0;
}

static int ad5669_release(struct inode *inode, struct file *file)
{
 return 0;
}

static int ad5669_ioctl(struct inode *inode, struct file *file,
       unsigned int cmd, unsigned long arg)
{
 int ret = 0, channel;
 u16 value;

 pr_debug("ioctl cmd %d is issued...\n", cmd);

 switch (cmd) {
 case AD5669_IOCTL_WRITE_DA:
  channel = arg >> 16;
  value = arg & 0xffff;

  if ((channel > 7) && (channel != 15)) {
   ret = -EINVAL;
   break;
  }

  ret = ad5669_write_reg((AD5669_CMD_WRITE_INPUT_N_UPDATE_N << 4) | channel, value);
  break;
 default:
  ret = -EINVAL;
  break;
 }

 return ret;
}

static const struct file_operations ad5669_fops = {
 .owner  = THIS_MODULE,
 .read  = ad5669_read,
 .write  = ad5669_write,
 .open  = ad5669_open,
 .release = ad5669_release,
 .ioctl  = ad5669_ioctl,
};

static int ad5669_probe(struct i2c_client *client, const struct i2c_device_id *id)
{
 int ret = 0;
 struct device *dev;

 dev_dbg(&ad5669_data.i2c_client->dev,
  "%s:ad5669 probe i2c address is 0x%02X \n",
  __func__, ad5669_data.i2c_client->addr);

 ad5669_data.i2c_client = client;
 ad5669_data.major = 0;

 ret = register_chrdev(ad5669_data.major, "ad5669", &ad5669_fops);
 if (ret < 0)
  return ret;

 if (ad5669_data.major == 0) {
  ad5669_data.major = ret;
  printk(KERN_INFO "AD5669: major number %d\n", ad5669_data.major);
 }

 /* create class and device for udev information */
 ad5669_data.ad5669_class = class_create(THIS_MODULE, "ad5669");
 if (IS_ERR(ad5669_data.ad5669_class)) {
  dev_err(&client->dev, "AD5669: failed to create ad5669 class\n");
  goto char_dev_remove;
 }

 dev = device_create(ad5669_data.ad5669_class, NULL,
       MKDEV(ad5669_data.major, 0), NULL, "ad5669");
 if (IS_ERR(dev)) {
  dev_err(&client->dev,
   "AD5669: failed to create class device\n");
  goto class_remove;
 }

 return 0;

class_remove:
 class_destroy(ad5669_data.ad5669_class);
char_dev_remove:
 unregister_chrdev(ad5669_data.major, "ad5669");

 return -ENODEV;
}

static int ad5669_remove(struct i2c_client *client)
{
 device_destroy(ad5669_data.ad5669_class, MKDEV(ad5669_data.major, 0));
 class_destroy(ad5669_data.ad5669_class);
 unregister_chrdev(ad5669_data.major, "ad5669");

 return 0;
}

static __init int ad5669_init(void)
{
 u8 err = 0;

 dev_dbg(&ad5669_data.i2c_client->dev, "In ad5669_init\n");

 /* Tells the i2c driver what functions to call for this driver. */
 err = i2c_add_driver(&ad5669_i2c_driver);
 if (err != 0)
  pr_err("%s:driver registration failed, error=%d \n",
   __func__, err);

 return err;
}

static void __exit ad5669_exit(void)
{
 dev_dbg(&ad5669_data.i2c_client->dev, "In ad5669_exit\n");
 i2c_del_driver(&ad5669_i2c_driver);
}

module_init(ad5669_init);
module_exit(ad5669_exit);

MODULE_AUTHOR("Electronics, Inc");
MODULE_DESCRIPTION("AD5669 voltage-output DAC driver");
MODULE_LICENSE("GPL");

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值