|  | #include <common.h> | 
|  | #include <mpc8xx.h> | 
|  | #include <malloc.h> | 
|  | #include <galileo/gt64260R.h> | 
|  | #include <galileo/core.h> | 
|  |  | 
|  | #define MAX_I2C_RETRYS	    10 | 
|  | #define I2C_DELAY	    1000  /* Should be at least the # of MHz of Tclk */ | 
|  | #undef	DEBUG_I2C | 
|  |  | 
|  | #ifdef DEBUG_I2C | 
|  | #define DP(x) x | 
|  | #else | 
|  | #define DP(x) | 
|  | #endif | 
|  |  | 
|  | /* Assuming that there is only one master on the bus (us) */ | 
|  |  | 
|  | static void | 
|  | i2c_init(int speed, int slaveaddr) | 
|  | { | 
|  | unsigned int n, m, freq, margin, power; | 
|  | unsigned int actualFreq, actualN=0, actualM=0; | 
|  | unsigned int control, status; | 
|  | unsigned int minMargin = 0xffffffff; | 
|  | unsigned int tclk = 125000000; | 
|  |  | 
|  | DP(puts("i2c_init\n")); | 
|  |  | 
|  | for(n = 0 ; n < 8 ; n++) | 
|  | { | 
|  | for(m = 0 ; m < 16 ; m++) | 
|  | { | 
|  | power = 2<<n; /* power = 2^(n+1) */ | 
|  | freq = tclk/(10*(m+1)*power); | 
|  | if (speed > freq) | 
|  | margin = speed - freq; | 
|  | else | 
|  | margin = freq - speed; | 
|  | if(margin < minMargin) | 
|  | { | 
|  | minMargin   = margin; | 
|  | actualFreq  = freq; | 
|  | actualN	    = n; | 
|  | actualM	    = m; | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | DP(puts("setup i2c bus\n")); | 
|  |  | 
|  | /* Setup bus */ | 
|  |  | 
|  | GT_REG_WRITE(I2C_SOFT_RESET, 0); | 
|  |  | 
|  | DP(puts("udelay...\n")); | 
|  |  | 
|  | udelay(I2C_DELAY); | 
|  |  | 
|  | DP(puts("set baudrate\n")); | 
|  |  | 
|  | GT_REG_WRITE(I2C_STATUS_BAUDE_RATE, (actualM << 3) | actualN); | 
|  | GT_REG_WRITE(I2C_CONTROL, (0x1 << 2) | (0x1 << 6)); | 
|  |  | 
|  | udelay(I2C_DELAY * 10); | 
|  |  | 
|  | DP(puts("read control, baudrate\n")); | 
|  |  | 
|  | GT_REG_READ(I2C_STATUS_BAUDE_RATE, &status); | 
|  | GT_REG_READ(I2C_CONTROL, &control); | 
|  | } | 
|  |  | 
|  | static uchar | 
|  | i2c_start(void) | 
|  | { | 
|  | unsigned int control, status; | 
|  | int count = 0; | 
|  |  | 
|  | DP(puts("i2c_start\n")); | 
|  |  | 
|  | /* Set the start bit */ | 
|  |  | 
|  | GT_REG_READ(I2C_CONTROL, &control); | 
|  | control |= (0x1 << 5); | 
|  | GT_REG_WRITE(I2C_CONTROL, control); | 
|  |  | 
|  | GT_REG_READ(I2C_STATUS_BAUDE_RATE, &status); | 
|  |  | 
|  | count = 0; | 
|  | while ((status & 0xff) != 0x08) { | 
|  | udelay(I2C_DELAY); | 
|  | if (count > 20) { | 
|  | GT_REG_WRITE(I2C_CONTROL, (0x1 << 4)); /*stop*/ | 
|  | return (status); | 
|  | } | 
|  | GT_REG_READ(I2C_STATUS_BAUDE_RATE, &status); | 
|  | count++; | 
|  | } | 
|  |  | 
|  | return (0); | 
|  | } | 
|  |  | 
|  | static uchar | 
|  | i2c_select_device(uchar dev_addr, uchar read, int ten_bit) | 
|  | { | 
|  | unsigned int status, data, bits = 7; | 
|  | int count = 0; | 
|  |  | 
|  | DP(puts("i2c_select_device\n")); | 
|  |  | 
|  | /* Output slave address */ | 
|  |  | 
|  | if (ten_bit) { | 
|  | bits = 10; | 
|  | } | 
|  |  | 
|  | data = (dev_addr << 1); | 
|  | /* set the read bit */ | 
|  | data |= read; | 
|  | GT_REG_WRITE(I2C_DATA, data); | 
|  | /* assert the address */ | 
|  | RESET_REG_BITS(I2C_CONTROL, BIT3); | 
|  |  | 
|  | udelay(I2C_DELAY); | 
|  |  | 
|  | GT_REG_READ(I2C_STATUS_BAUDE_RATE, &status); | 
|  | count = 0; | 
|  | while (((status & 0xff) != 0x40) && ((status & 0xff) != 0x18)) { | 
|  | udelay(I2C_DELAY); | 
|  | if (count > 20) { | 
|  | GT_REG_WRITE(I2C_CONTROL, (0x1 << 4)); /*stop*/ | 
|  | return(status); | 
|  | } | 
|  | GT_REG_READ(I2C_STATUS_BAUDE_RATE, &status); | 
|  | count++; | 
|  | } | 
|  |  | 
|  | if (bits == 10) { | 
|  | printf("10 bit I2C addressing not yet implemented\n"); | 
|  | return (0xff); | 
|  | } | 
|  |  | 
|  | return (0); | 
|  | } | 
|  |  | 
|  | static uchar | 
|  | i2c_get_data(uchar* return_data, int len) { | 
|  |  | 
|  | unsigned int data, status = 0; | 
|  | int count = 0; | 
|  |  | 
|  | DP(puts("i2c_get_data\n")); | 
|  |  | 
|  | while (len) { | 
|  |  | 
|  | /* Get and return the data */ | 
|  |  | 
|  | RESET_REG_BITS(I2C_CONTROL, (0x1 << 3)); | 
|  |  | 
|  | udelay(I2C_DELAY * 5); | 
|  |  | 
|  | GT_REG_READ(I2C_STATUS_BAUDE_RATE, &status); | 
|  | count++; | 
|  | while ((status & 0xff) != 0x50) { | 
|  | udelay(I2C_DELAY); | 
|  | if(count > 2) { | 
|  | GT_REG_WRITE(I2C_CONTROL, (0x1 << 4)); /*stop*/ | 
|  | return 0; | 
|  | } | 
|  | GT_REG_READ(I2C_STATUS_BAUDE_RATE, &status); | 
|  | count++; | 
|  | } | 
|  | GT_REG_READ(I2C_DATA, &data); | 
|  | len--; | 
|  | *return_data = (uchar)data; | 
|  | return_data++; | 
|  | } | 
|  | RESET_REG_BITS(I2C_CONTROL, BIT2|BIT3); | 
|  | while ((status & 0xff) != 0x58) { | 
|  | udelay(I2C_DELAY); | 
|  | if(count > 200) { | 
|  | GT_REG_WRITE(I2C_CONTROL, (0x1 << 4)); /*stop*/ | 
|  | return (status); | 
|  | } | 
|  | GT_REG_READ(I2C_STATUS_BAUDE_RATE, &status); | 
|  | count++; | 
|  | } | 
|  | GT_REG_WRITE(I2C_CONTROL, (0x1 << 4)); /* stop */ | 
|  |  | 
|  | return (0); | 
|  | } | 
|  |  | 
|  | static uchar | 
|  | i2c_write_data(unsigned int data, int len) | 
|  | { | 
|  | unsigned int status; | 
|  | int count = 0; | 
|  |  | 
|  | DP(puts("i2c_write_data\n")); | 
|  |  | 
|  | if (len > 4) | 
|  | return -1; | 
|  |  | 
|  | while (len) { | 
|  | /* Set and assert the data */ | 
|  |  | 
|  | GT_REG_WRITE(I2C_DATA, (unsigned int)data); | 
|  | RESET_REG_BITS(I2C_CONTROL, (0x1 << 3)); | 
|  |  | 
|  | udelay(I2C_DELAY); | 
|  |  | 
|  | GT_REG_READ(I2C_STATUS_BAUDE_RATE, &status); | 
|  | count++; | 
|  | while ((status & 0xff) != 0x28) { | 
|  | udelay(I2C_DELAY); | 
|  | if(count > 20) { | 
|  | GT_REG_WRITE(I2C_CONTROL, (0x1 << 4)); /*stop*/ | 
|  | return (status); | 
|  | } | 
|  | GT_REG_READ(I2C_STATUS_BAUDE_RATE, &status); | 
|  | count++; | 
|  | } | 
|  | len--; | 
|  | } | 
|  | GT_REG_WRITE(I2C_CONTROL, (0x1 << 3) | (0x1 << 4)); | 
|  | GT_REG_WRITE(I2C_CONTROL, (0x1 << 4)); | 
|  |  | 
|  | udelay(I2C_DELAY * 10); | 
|  |  | 
|  | return (0); | 
|  | } | 
|  |  | 
|  | static uchar | 
|  | i2c_set_dev_offset(uchar dev_addr, unsigned int offset, int ten_bit) | 
|  | { | 
|  | uchar status; | 
|  |  | 
|  | DP(puts("i2c_set_dev_offset\n")); | 
|  |  | 
|  | status = i2c_select_device(dev_addr, 0, ten_bit); | 
|  | if (status) { | 
|  | #ifdef DEBUG_I2C | 
|  | printf("Failed to select device setting offset: 0x%02x\n", | 
|  | status); | 
|  | #endif | 
|  | return status; | 
|  | } | 
|  |  | 
|  | status = i2c_write_data(offset, 1); | 
|  | if (status) { | 
|  | #ifdef DEBUG_I2C | 
|  | printf("Failed to write data: 0x%02x\n", status); | 
|  | #endif | 
|  | return status; | 
|  | } | 
|  |  | 
|  | return (0); | 
|  | } | 
|  |  | 
|  | uchar | 
|  | i2c_read(uchar dev_addr, unsigned int offset, int len, uchar* data, | 
|  | int ten_bit) | 
|  | { | 
|  | uchar status = 0; | 
|  | unsigned int i2cFreq = 400000; | 
|  |  | 
|  | DP(puts("i2c_read\n")); | 
|  |  | 
|  | i2c_init(i2cFreq,0); | 
|  |  | 
|  | status = i2c_start(); | 
|  |  | 
|  | if (status) { | 
|  | #ifdef DEBUG_I2C | 
|  | printf("Transaction start failed: 0x%02x\n", status); | 
|  | #endif | 
|  | return status; | 
|  | } | 
|  |  | 
|  | status = i2c_set_dev_offset(dev_addr, 0, 0); | 
|  | if (status) { | 
|  | #ifdef DEBUG_I2C | 
|  | printf("Failed to set offset: 0x%02x\n", status); | 
|  | #endif | 
|  | return status; | 
|  | } | 
|  |  | 
|  | i2c_init(i2cFreq,0); | 
|  |  | 
|  | status = i2c_start(); | 
|  | if (status) { | 
|  | #ifdef DEBUG_I2C | 
|  | printf("Transaction restart failed: 0x%02x\n", status); | 
|  | #endif | 
|  | return status; | 
|  | } | 
|  |  | 
|  | status = i2c_select_device(dev_addr, 1, ten_bit); | 
|  | if (status) { | 
|  | #ifdef DEBUG_I2C | 
|  | printf("Address not acknowledged: 0x%02x\n", status); | 
|  | #endif | 
|  | return status; | 
|  | } | 
|  |  | 
|  | status = i2c_get_data(data, len); | 
|  | if (status) { | 
|  | #ifdef DEBUG_I2C | 
|  | printf("Data not recieved: 0x%02x\n", status); | 
|  | #endif | 
|  | return status; | 
|  | } | 
|  |  | 
|  | return 0; | 
|  | } |