Chinaunix首页 | 论坛 | 博客
  • 博客访问: 52074
  • 博文数量: 14
  • 博客积分: 1545
  • 博客等级: 上尉
  • 技术积分: 170
  • 用 户 组: 普通用户
  • 注册时间: 2010-05-13 00:33
文章分类

全部博文(14)

文章存档

2011年(4)

2010年(10)

我的朋友

分类: LINUX

2011-08-27 11:47:08

/*
* mips-linux-2.6.15
*/

#include
#include

#include
#include
#include

#ifdef __BDI
#include "bdi.h"
#else
#ifdef __ECOS
#include
#include "ag7100_ecos.h"
#define printk             DEBUG_PRINTF
#define udelay             A_UDELAY
#else
#include
#include
#include "ar7100.h"
#endif
#endif

static ssize_t lm75a_read(struct file *filp, char __user *buf, size_t count,
    loff_t *f_pos);
static ssize_t lm75a_write(struct file *filp, const char __user *buf,
    size_t count, loff_t *f_pos);
static int16_t sensor_temp_get(void);

static struct file_operations lm75a_fops = {
    .owner = THIS_MODULE,
    .read = lm75a_read,
    .write = lm75a_write
};

static int lm75a_major = 0;
static struct cdev *cdev = NULL;

ssize_t lm75a_read(struct file *filp, char __user *buf, size_t count,
    loff_t *f_pos)
{
    //printk("<0>""test read......\n");
    int16_t temp = sensor_temp_get();
    char data[2];
    data[0] = temp >> 8;
    data[1] = temp;

    copy_to_user(buf, data, 2);
   
    return 0;
}

ssize_t lm75a_write(struct file *filp, const char __user *buf, size_t count,
    loff_t *f_pos)
{
    //printk("<0>""test write......\n");
    return 0;
}

#define I2C_SCL 11
#define I2C_SDA 6

static void gpio_set(int gpio, int val)
{
    if (val & 0x1)
    {
        ar7100_reg_wr(AR7100_GPIO_SET, (1 << gpio));
    }
    else
    {
        ar7100_reg_wr(AR7100_GPIO_CLEAR, (1 << gpio));
    }
    udelay(5);
}

static int gpio_get(int gpio)
{
    return ((1 << gpio) & (ar7100_reg_rd(AR7100_GPIO_IN)));
}

static void gpio_config_output(int gpio)
{
    ar7100_reg_rmw_set(AR7100_GPIO_OE, (1 << gpio));
    udelay(5);
}

static void gpio_config_input(int gpio)
{
    ar7100_reg_rmw_clear(AR7100_GPIO_OE, (1 << gpio));
    udelay(5);
}

static u_int16_t i2c_read(void)
{
    int i;
    u_int16_t data = 0;
    for (i = 7; i>= 0; i--)
    {
        gpio_set(I2C_SCL, 0);
        gpio_set(I2C_SCL, 1);
        data |= gpio_get(I2C_SDA) ? 1 : 0;
        data <<= 1;
    }

    return data >> 1;
}


static void i2c_write(u_int16_t reg)
{
    int i;
    for (i = 7; i >= 0; i--)
    {
        gpio_set(I2C_SCL, 0);
        gpio_set(I2C_SDA, (reg >> i) & 0x1);
        gpio_set(I2C_SCL, 1);
    }
}

static int16_t sensor_temp_get(void)
{
    int ack = 0;
    int16_t temp = 0;
    u_int16_t temp1 = 0;

    //start
    gpio_config_output(I2C_SCL);
    gpio_config_output(I2C_SDA);
    gpio_set(I2C_SCL, 1);
    gpio_set(I2C_SDA, 1);
    gpio_set(I2C_SDA, 0);

    //addr write
    i2c_write(0x90);
    gpio_config_input(I2C_SDA);
    gpio_set(I2C_SCL, 0);
    gpio_set(I2C_SDA, 1);
    gpio_set(I2C_SCL, 1);
    ack = gpio_get(I2C_SDA) ? 1 : 0;
    //printk("<0>""ack:%d\n", ack);

    //reg
    gpio_config_output(I2C_SDA);
    i2c_write(0x00);
    gpio_config_input(I2C_SDA);
    gpio_set(I2C_SCL, 0);   
    gpio_set(I2C_SDA, 1);
    gpio_set(I2C_SCL, 1);
    ack = gpio_get(I2C_SDA) ? 1 : 0;
    //printk("<0>""ack:%d\n", ack);
   
    //restart
    gpio_set(I2C_SCL, 0);
    gpio_config_output(I2C_SDA);
    gpio_set(I2C_SDA, 1);
    gpio_set(I2C_SCL, 1);
    gpio_set(I2C_SDA, 0);


    // addr read
    i2c_write(0x91);
    gpio_config_input(I2C_SDA);
    gpio_set(I2C_SCL, 0);
    gpio_set(I2C_SDA, 1);
    gpio_set(I2C_SCL, 1);
    ack = gpio_get(I2C_SDA) ? 1 : 0;
    //printk("<0>""ack:%d\n", ack);
    temp1 = i2c_read();
    //printk("<0>""temp1:%x\n", temp1);
    temp1 <<= 8;

    //send ack
    gpio_config_output(I2C_SDA);
    gpio_set(I2C_SCL, 0);
    gpio_set(I2C_SDA, 0);
    gpio_set(I2C_SCL, 1);

    //read second byte
    gpio_config_input(I2C_SDA);
    gpio_set(I2C_SDA, 1);
    temp1 += i2c_read();

    //send nack
    gpio_config_output(I2C_SDA);
    gpio_set(I2C_SCL, 0);
    gpio_set(I2C_SDA, 1);
    gpio_set(I2C_SCL, 1);

    //stop
    gpio_set(I2C_SCL, 0);
    gpio_set(I2C_SDA, 0);
    gpio_set(I2C_SCL, 1);
    gpio_set(I2C_SDA, 1);

    temp = temp1;
    //printk("<0>""temp1:%x\n", temp1);
    temp >>= 5; //MSB 11 bit is valid data
    if (temp & 0x400)
    {
        // -(2's complement of Temp data) * 0.125
        temp = -((((~temp) & 0x3FF) + 1) >> 3);
    }
    else
    {
        temp = temp >> 3; // (Temp data) * 0.125
    }

    return temp;
}

static void i2c_gpio_lm75a_init(void)
{
    ar7100_reg_rmw_set(AR7100_GPIO_FUNCTIONS,
        AR7100_GPIO_FUNCTION_SPI_CS_0_EN|AR7100_GPIO_FUNCTION_SPI_CS_1_EN);
     ar7100_reg_rmw_clear(AR7100_GPIO_INT_ENABLE,
         (1 << I2C_SCL) + (1 << I2C_SDA));
     ar7100_reg_rmw_set(AR7100_GPIO_OE, (1 << I2C_SCL) + (1 << I2C_SDA));
}

static int lm75a_init_module(void)
{
    int result = 0;
    dev_t dev = 0;
    result = alloc_chrdev_region(&dev, 0, 1, "lm75a");
    if (result < 0)
    {
        printk("<0>""alloc_chrdev_region fail...\n");
        return result;
    }
     
    cdev = cdev_alloc();
    cdev_init(cdev, &lm75a_fops);
    cdev->owner = THIS_MODULE;
    cdev->ops = &lm75a_fops;
   
    lm75a_major = MAJOR(dev);
    result = cdev_add(cdev, MKDEV(lm75a_major, 0), 1);
    if (result)
    {
        printk("<0>""cdev_add fail....\n");
    }

    //printk("<0>""OK......\n");
    i2c_gpio_lm75a_init();
    //int16_t temp = 0;
    //temp = sensor_temp_get();
    //printk("<0>""temp:%d\n", temp);

    return result;
}

static void lm75a_exit_module(void)
{
    if (cdev != NULL)
        cdev_del(cdev);
   
    dev_t devno = MKDEV(lm75a_major, 0);
    unregister_chrdev_region(devno, 1);
}

module_init(lm75a_init_module);
module_exit(lm75a_exit_module);
阅读(1228) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~