海思uboot阶段模拟i2c

理论所有linux都可以使用。在文件i2c_hibvt.c改为。下面的代码主要修改GPIO_15_BASE SCL_SHIFT_NUM,修改makefile kconfig保证代码被编译


#include 

 
#include "i2c_hibvt.h"
#define demo_delay time_delay_us(2)
#ifdef HI_FPGA
 
#define GPIO_15_BASE 0x12240000
#define SCL_SHIFT_NUM 2
#define SDA_SHIFT_NUM 3
#define SCL (0x1 << SCL_SHIFT_NUM)                                                                                   /* GPIO7 0_7 */
#define SDA (0x1 << SDA_SHIFT_NUM)                                                                                   /* GPIO7 0_6 */
#define GPIO_I2C_SCL_REG IO_ADDRESS(GPIO_15_BASE + (0x1 << (SCL_SHIFT_NUM + 2)))                                     /* 0x200 */
#define GPIO_I2C_SDA_REG IO_ADDRESS(GPIO_15_BASE + (0x1 << (SDA_SHIFT_NUM + 2)))                                     /* 0x100 */
#define GPIO_I2C_SCLSDA_REG IO_ADDRESS(GPIO_15_BASE + ((0x1 << (SCL_SHIFT_NUM + 2)) + (0x1 << (SDA_SHIFT_NUM + 2)))) /* 0x300 need check */
 
#else
/*记得修改Makefile里面的路径*/
/*下面需要修改为对应芯片的*/
#define GPIO_15_BASE 0x120b1000 
#define SCL_SHIFT_NUM 4
#define SDA_SHIFT_NUM 5
/*上面需要修改为对应芯片的*/
 
 
#define SCL (0x1 << SCL_SHIFT_NUM)                                                                                   /* GPIO1 0_7 */
#define SDA (0x1 << SDA_SHIFT_NUM)                                                                                   /* GPIO1 0_6 */
void  * GPIO_I2C_SCL_REG; 
void  * GPIO_I2C_SDA_REG;
void  * GPIO_I2C_SCLSDA_REG; /* 0x300 need check */
 
#endif
 
void  *GPIO_0_DIR; 
#define HW_REG(reg) *((volatile unsigned int *)(reg))
#define DELAY(us) time_delay_us(us)
 
/* 
 * I2C by GPIO simulated  clear 0 routine.
 *
 * @param whichline: GPIO control line
 *
 */
static void i2c_clr(unsigned char whichline)
{
    unsigned char regvalue;
 
    if (whichline == SCL)
    {
        regvalue = HW_REG(GPIO_0_DIR);
        regvalue |= SCL;
        HW_REG(GPIO_0_DIR) = regvalue;
 
        HW_REG(GPIO_I2C_SCL_REG) = 0;
        return;
    }
    else if (whichline == SDA)
    {
        regvalue = HW_REG(GPIO_0_DIR);
        regvalue |= SDA;
        HW_REG(GPIO_0_DIR) = regvalue;
 
        HW_REG(GPIO_I2C_SDA_REG) = 0;
        return;
    }
    else if (whichline == (SDA | SCL))
    {
        regvalue = HW_REG(GPIO_0_DIR);
        regvalue |= (SDA | SCL);
        HW_REG(GPIO_0_DIR) = regvalue;
 
        HW_REG(GPIO_I2C_SCLSDA_REG) = 0;
        return;
    }
    else
    {
        printk("Error input.\n");
        return;
    }
}
 
 
/*
 *  delays for a specified number of micro seconds rountine.
 *
 *  @param usec: number of micro seconds to pause for
 *
 */
void time_delay_us(unsigned int usec)
{
    //	volatile int i,j;
 
#ifdef HI_FPGA
    for (i = 0; i < usec * 5; i++)
    {
        for (j = 0; j < 47; j++)
        {
            ;
        }
    }
#else
    udelay(usec * 60);
 
#endif
}
/* 
 * I2C by GPIO simulated  set 1 routine.
 *
 * @param whichline: GPIO control line
 *
 */
static void i2c_set(unsigned char whichline)
{
    unsigned char regvalue;
 
    if (whichline == SCL)
    {
        regvalue = HW_REG(GPIO_0_DIR);
        regvalue |= SCL;
        HW_REG(GPIO_0_DIR) = regvalue;
 
        HW_REG(GPIO_I2C_SCL_REG) = SCL;
        return;
    }
    else if (whichline == SDA)
    {
        regvalue = HW_REG(GPIO_0_DIR);
        regvalue |= SDA;
        HW_REG(GPIO_0_DIR) = regvalue;
 
        HW_REG(GPIO_I2C_SDA_REG) = SDA;
        return;
    }
    else if (whichline == (SDA | SCL))
    {
        regvalue = HW_REG(GPIO_0_DIR);
        regvalue |= (SDA | SCL);
        HW_REG(GPIO_0_DIR) = regvalue;
 
        HW_REG(GPIO_I2C_SCLSDA_REG) = (SDA | SCL);
        return;
    }
    else
    {
        printk("Error input.\n");
        return;
    }
}
 
/* 
 * I2C by GPIO simulated  read data routine.
 *
 * @return value: a bit for read 
 *
 */
 
static unsigned char i2c_data_read(void)
{
    unsigned char regvalue;
 
    regvalue = HW_REG(GPIO_0_DIR);
    regvalue &= (~SDA);
    HW_REG(GPIO_0_DIR) = regvalue;
    DELAY(1);
 
    regvalue = HW_REG(GPIO_I2C_SDA_REG);
    if ((regvalue & SDA) != 0)
        return 1;
    else
        return 0;
}
 
static void demo_i2c_start(void)
{
    // //out_scl();
    // //out_sda();
 
    high_scl;
 
    high_sda;
    demo_delay;
    low_sda;
    demo_delay;
 
    low_scl;
}
 
static void demo_i2c_stop(void)
{
    //out_scl();
    //out_sda();
 
    high_scl;
 
    low_sda;
    demo_delay;
    high_sda;
    demo_delay;
 
    low_scl;
}
 
/*
 * sends a character over I2C rountine.
 *
 * @param  c: character to send
 *
 */
static void demo_i2c_send_byte(unsigned char data)
{
    int i = 0;
    //out_scl();
    //out_sda();
 
    low_scl;
    for(i=0;i<8;i++) {
        if(data & (0x80>>i))
            high_sda;
        else
            low_sda;
        demo_delay;
        high_scl;
        demo_delay;
        low_scl;
    }
}
 
/*  receives a character from I2C rountine.
 *
 *  @return value: character received
 *
 */
static unsigned char demo_i2c_recv_byte(void)
{
    int i = 0;
    unsigned char data = 0;
    //out_scl();
    //in_sda();
 
    low_scl;
    for(i=0;i<8;i++) {
        demo_delay;
        high_scl;
        demo_delay;
        data <<= 1;//循环8次,最终只左移了7次
        data |= i2c_data_read();
        low_scl;
    }
    return data;
}
 
 
/*  receives an acknowledge from I2C rountine.
 *
 *  @return value: 0--Ack received; 1--Nack received
 *          
 */
static unsigned char demo_i2c_recv_ack(void)
{
    int nack;
    unsigned char regvalue;
    regvalue = HW_REG(GPIO_0_DIR);
    regvalue &= (~SDA);
    HW_REG(GPIO_0_DIR) = regvalue;
 
    //DELAY(1);
    i2c_clr(SCL);
    DELAY(1);
    i2c_set(SCL);
    DELAY(1);
 
    nack = i2c_data_read();
 
    DELAY(1);
    i2c_clr(SCL);
    DELAY(1);
 
    if (nack == 0)
    {
        return 0;
    }
    else
    {
        return 1;
    }
}
 
 
static void demo_i2c_send_ack(unsigned char ack)
{
    //out_scl();
    //out_sda();
    low_scl;
    if(ack)
        high_sda;
    else
        low_sda;
    demo_delay;
    high_scl;
    demo_delay;
    low_scl;
}
 
 
EXPORT_SYMBOL(gpio_i2c_read);
unsigned char gpio_i2c_read(unsigned char devaddress, unsigned char address)
{
    int i = 0,len=1;
    char buff;
 
    demo_i2c_start();
    demo_i2c_send_byte((unsigned char)(devaddress));
    if(demo_i2c_recv_ack()) {
        printk("data:0x%02x\n",(unsigned char)(devaddress));
        printf( "%d,get a nack.\n", __LINE__);
        return -1;
    }
    demo_i2c_send_byte(address & 0xff);
    if(demo_i2c_recv_ack()) {
        printk("address:0x%02x\n",address & 0xff);
        printf( "%d,get a nack.\n", __LINE__);
        return -1;
    }
 
    demo_i2c_start();
    demo_i2c_send_byte((unsigned char)(devaddress) | 1);
    if(demo_i2c_recv_ack()) {
        printk("devaddress:0x%02x\n",(unsigned char)(devaddress) | 1);
        printf( "%d,get a nack.\n", __LINE__);
        return -1;
    }
 
    for(i=0; i<(len-1); i++) {
        buff = demo_i2c_recv_byte();
        demo_i2c_send_ack(0);
    }
    buff = demo_i2c_recv_byte();
    demo_i2c_send_ack(1);
 
    demo_i2c_stop();
    return buff;
}
 
EXPORT_SYMBOL(gpio_i2c_write);
void gpio_i2c_write(unsigned char devaddress, unsigned int address, unsigned char data)
{
   int i = 0,len=1;
 
    demo_i2c_start();
    demo_i2c_send_byte((unsigned char)(devaddress));
    if(demo_i2c_recv_ack()) {
        printf( "%d,get a nack.\n", __LINE__);
        return -1;
    }
    demo_i2c_send_byte(address & 0xff);
    if(demo_i2c_recv_ack()) {
        printf( "%d,get a nack.\n", __LINE__);
        return -1;
    }
    for(i=0; i

你可能感兴趣的:(linux,fpga开发,单片机,嵌入式硬件)