Exemplo n.º 1
0
int i2c_init(uint32_t base, uint32_t baud)
{
    int instance;
    
    // Accept either an instance or base address for the base param.
    if (base >= 1 && base <= HW_I2C_INSTANCE_COUNT)
    {
        instance = base;
    }
    else
    {
        instance = REGS_I2C_INSTANCE(base);
    }
    
    // enable the source clocks to the I2C port 
    clock_gating_config(REGS_I2C_BASE(instance), CLOCK_ON);

    // Set iomux configuration 
    i2c_iomux_config(instance);

    // reset I2C 
    HW_I2C_I2CR_WR(instance, 0);

    // Set clock.
    set_i2c_clock(instance, baud);

    // set an I2C slave address 
   // HW_I2C_IADR_WR(instance, IMX6_DEFAULT_SLAVE_ID);

    // clear the status register 
    HW_I2C_I2SR_WR(instance, 0);

    // enable the I2C controller 
    HW_I2C_I2CR_WR(instance, BM_I2C_I2CR_IEN);

    return 0;
}
Exemplo n.º 2
0
int i2c_xfer(const imx_i2c_request_t *rq, int dir)
{
    uint32_t reg;
    uint32_t ret = 0;
    uint16_t i2cr;
    uint8_t i;
    uint8_t data;
    uint32_t instance = i2c_get_request_instance(rq);
    uint8_t address = (rq->device ? rq->device->address : rq->dev_addr) << 1;

    if (rq->buffer_sz == 0 || rq->buffer == NULL) {
        debug_printf("Invalid register address size=%x, buffer size=%x, buffer=%x\n",
               rq->reg_addr_sz, rq->buffer_sz, (unsigned int)rq->buffer);
        return ERR_INVALID_REQUEST;
    }

    // clear the status register 
    HW_I2C_I2SR_WR(instance, 0);

    // enable the I2C controller 
    HW_I2C_I2CR_WR(instance, BM_I2C_I2CR_IEN);

    // Check if bus is free, if not return error 
    if (is_bus_free(instance) != 0) {
        return -1;
    }
    
    // If the request has device info attached and it has a non-zero bit rate, then
    // change the clock to the specified rate.
    if (rq->device && rq->device->freq)
    {
        set_i2c_clock(instance, rq->device->freq);
    }

    // Step 1: Select master mode, assert START signal and also indicate TX mode 
    HW_I2C_I2CR_WR(instance, BM_I2C_I2CR_IEN | BM_I2C_I2CR_MSTA | BM_I2C_I2CR_MTX);

    // make sure bus is busy after the START signal 
    if (wait_till_busy(instance) != 0) {
        debug_printf("1\n");
        return -1;
    }
    
    // Step 2: send slave address + read/write at the LSB 
    data = address | I2C_WRITE;

    if ((ret = tx_byte(&data, instance)) != 0) {
        debug_printf("START TX ERR %d\n", ret);

        if (ret == ERR_NO_ACK) {
            return ERR_NO_ACK_ON_START;
        } else {
            return ret;
        }
    }
    
    // Step 3: send I2C device register address 
    if (rq->reg_addr_sz > 4) {
        debug_printf("Warning register address size %d should less than 4\n", rq->reg_addr_sz);
        return ERR_INVALID_REQUEST;
    }

    reg = rq->reg_addr;

    for (i = 0; i < rq->reg_addr_sz; i++, reg >>= 8) {
        data = reg & 0xFF;
        
#if TRACE_I2C
        debug_printf("sending I2C=%d device register: data=0x%x, byte %d\n", instance, data, i);
#endif // TRACE_I2C

        if (tx_byte(&data, instance) != 0) {
            return -1;
        }
    }

    // Step 4: read/write data 
    if (dir == I2C_READ) {
        // do repeat-start 
        HW_I2C_I2CR(instance).B.RSTA = 1;

        // make sure bus is busy after the REPEATED START signal 
        if (wait_till_busy(instance) != 0) {
            return ERR_TX;
        }
        
        // send slave address again, but indicate read operation 
        data = address | I2C_READ;

        if (tx_byte(&data, instance) != 0) {
            return -1;
        }

        // change to receive mode 
        i2cr = HW_I2C_I2CR_RD(instance) & ~BM_I2C_I2CR_MTX;
        
        // if only one byte to read, make sure don't send ack 
        if (rq->buffer_sz == 1) {
            i2cr |= BM_I2C_I2CR_TXAK;
        }
        HW_I2C_I2CR_WR(instance, i2cr);

        // dummy read 
        data = HW_I2C_I2DR_RD(instance);

        // now reading ... 
        if (rx_bytes(rq->buffer, instance, rq->buffer_sz) != 0) {
            return -1;
        }
    } else {
        // I2C_WRITE 
        for (i = 0; i < rq->buffer_sz; i++) {
            // send device register value 
            data = rq->buffer[i];

            if ((ret = tx_byte(&data, instance)) != 0) {
                break;
            }
        }
    }

    // generate STOP by clearing MSTA bit 
    imx_send_stop(instance);

    // Check if bus is free, if not return error 
    if (is_bus_free(instance) != 0) {
        debug_printf("WARNING: bus is not free\n");
    }
    
    // disable the controller 
    HW_I2C_I2CR_WR(instance, 0);

    return ret;
}
Exemplo n.º 3
0
/*
**********************************************************************************************************************
*                                               i2c_init
*
* Description:
*
* Arguments  :
*
* Returns    :    none
*
* Notes      :    none
*
**********************************************************************************************************************
*/
void i2c_init(int speed, int slaveaddr)
{
	int i, clk_n, clk_m;
	int i2c_nodeoffset;
	
	/*set gpio and clock*/
#ifndef CONFIG_CPUS_I2C
	i2c_nodeoffset = fdt_path_offset(working_fdt,"/soc/twi_para");
	if(i2c_nodeoffset < 0)
	{
		printf("axp: get node[%s] error\n",PMU_SCRIPT_NAME);
		return ;
	}

	//if(script_parser_fetch(PMU_SCRIPT_NAME, "pmu_pwron_vol", &vol_value, 1))
	if(fdt_getprop_u32(working_fdt,i2c_nodeoffset,"twi_port", (uint32_t*)&bus_num)<0)
	{
		printf("can not get i2c bus num \n");
	}
        if(bus_num > SUNXI_I2C_CONTROLLER)
        {
                printf("can not support i2c bus num %d \n",bus_num);
                return ;
        }
	set_i2c_clock();
	if(0 != fdt_set_all_pin_by_offset(i2c_nodeoffset,"pinctrl-0"))
	{
	 	printf("set pin for i2c bus num %d error\n",bus_num);
		return ;
	}
        i2c = (struct sunxi_twi_reg *)(SUNXI_TWI0_BASE + (bus_num * TWI_CONTROL_OFFSET));
#else
	set_cpus_i2c_clock();
        fdt_set_all_pin("/soc/s_twi0","pinctrl-0");
#endif
	/* reset i2c control  */
    i = 0xffff;
    i2c->srst = 1;
    while((i2c->srst) && (i))
    {
    	i --;
    }
    if((i2c->lcr & 0x30) != 0x30 )
    {
    	/* toggle I2CSCL until bus idle */
    	i2c->lcr = 0x05;
    	__usdelay(500);
    	i = 10;
		while ((i > 0) && ((i2c->lcr & 0x02) != 2))
		{
			i2c->lcr |= 0x08;
			__usdelay(1000);
			i2c->lcr &= ~0x08;
			__usdelay(1000);
			i--;
		}
		i2c->lcr = 0x0;
		__usdelay(500);
    }

	if(speed < 100)
	{
		speed = 100;
	}
	else if(speed > 400)
	{
		speed = 400;
	}
	clk_n = 1;
	clk_m = (24000/10)/((2^clk_n) * speed) - 1;

    i2c->clk = (clk_m<<3) | clk_n;
    i2c->ctl = 0x40;
    i2c->eft = 0;
    return ;
}