summaryrefslogtreecommitdiff
path: root/cpu/mpc83xx/i2c.c
diff options
context:
space:
mode:
Diffstat (limited to 'cpu/mpc83xx/i2c.c')
-rw-r--r--cpu/mpc83xx/i2c.c423
1 files changed, 0 insertions, 423 deletions
diff --git a/cpu/mpc83xx/i2c.c b/cpu/mpc83xx/i2c.c
deleted file mode 100644
index ce78491..0000000
--- a/cpu/mpc83xx/i2c.c
+++ /dev/null
@@ -1,423 +0,0 @@
-/*
- * (C) Copyright 2006 Freescale Semiconductor, Inc.
- *
- * (C) Copyright 2003,Motorola Inc.
- * Xianghua Xiao <x.xiao@motorola.com>
- * Adapted for Motorola 85xx chip.
- *
- * (C) Copyright 2003
- * Gleb Natapov <gnatapov@mrv.com>
- * Some bits are taken from linux driver writen by adrian@humboldt.co.uk
- *
- * Hardware I2C driver for MPC107 PCI bridge.
- *
- * See file CREDITS for list of people who contributed to this
- * project.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of
- * the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
- * MA 02111-1307 USA
- *
- * Change log:
- *
- * 20050101: Eran Liberty (liberty@freescale.com)
- * Initial file creating (porting from 85XX & 8260)
- * 20060601: Dave Liu (daveliu@freescale.com)
- * Unified variable names for mpc83xx
- */
-
-#include <common.h>
-#include <command.h>
-#include <asm/io.h>
-
-#ifdef CONFIG_HARD_I2C
-#include <i2c.h>
-#include <asm/i2c.h>
-
-DECLARE_GLOBAL_DATA_PTR;
-
-/* Initialize the bus pointer to whatever one the SPD EEPROM is on.
- * Default is bus 1. This is necessary because the DDR initialization
- * runs from ROM, and we can't switch buses because we can't modify
- * the i2c_dev variable. Everything gets straightened out once i2c_init
- * is called from RAM. */
-
-#ifndef CFG_SPD_BUS_NUM
-#define CFG_SPD_BUS_NUM 1
-#endif
-
-static unsigned int i2c_bus_num = CFG_SPD_BUS_NUM;
-
-#if CFG_SPD_BUS_NUM == 1
-static volatile i2c_t *i2c_dev = I2C_1;
-#else
-static volatile i2c_t *i2c_dev = I2C_2;
-#endif
-
-static int i2c_bus_speed[2] = {0, 0};
-
-/*
- * Map the frequency divider to the FDR. This data is taken from table 17-5
- * of the MPC8349EA reference manual, with duplicates removed.
- */
-static struct {
- unsigned int divider;
- u8 fdr;
-} i2c_speed_map[] =
-{
- {0, 0x20},
- {256, 0x20},
- {288, 0x21},
- {320, 0x22},
- {352, 0x23},
- {384, 0x24},
- {416, 0x01},
- {448, 0x25},
- {480, 0x02},
- {512, 0x26},
- {576, 0x27},
- {640, 0x28},
- {704, 0x05},
- {768, 0x29},
- {832, 0x06},
- {896, 0x2A},
- {1024, 0x2B},
- {1152, 0x08},
- {1280, 0x2C},
- {1536, 0x2D},
- {1792, 0x2E},
- {1920, 0x0B},
- {2048, 0x2F},
- {2304, 0x0C},
- {2560, 0x30},
- {3072, 0x31},
- {3584, 0x32},
- {3840, 0x0F},
- {4096, 0x33},
- {4608, 0x10},
- {5120, 0x34},
- {6144, 0x35},
- {7168, 0x36},
- {7680, 0x13},
- {8192, 0x37},
- {9216, 0x14},
- {10240, 0x38},
- {12288, 0x39},
- {14336, 0x3A},
- {15360, 0x17},
- {16384, 0x3B},
- {18432, 0x18},
- {20480, 0x3C},
- {24576, 0x3D},
- {28672, 0x3E},
- {30720, 0x1B},
- {32768, 0x3F},
- {36864, 0x1C},
- {40960, 0x1D},
- {49152, 0x1E},
- {61440, 0x1F},
- {-1, 0x1F}
-};
-
-#define NUM_I2C_SPEEDS (sizeof(i2c_speed_map) / sizeof(i2c_speed_map[0]))
-
-static int set_speed(unsigned int speed)
-{
- unsigned long i2c_clk;
- unsigned int divider, i;
- u8 fdr = 0x3F;
-
- i2c_clk = (i2c_bus_num == 2) ? gd->i2c2_clk : gd->i2c1_clk;
-
- divider = i2c_clk / speed;
-
- /* Scan i2c_speed_map[] for the closest matching divider.*/
-
- for (i = 0; i < NUM_I2C_SPEEDS-1; i++) {
- /* Locate our divider in between two entries in i2c_speed_map[] */
- if ((divider >= i2c_speed_map[i].divider) &&
- (divider <= i2c_speed_map[i+1].divider)) {
- /* Which one is closer? */
- if ((divider - i2c_speed_map[i].divider) < (i2c_speed_map[i+1].divider - divider)) {
- fdr = i2c_speed_map[i].fdr;
- } else {
- fdr = i2c_speed_map[i+1].fdr;
- }
- break;
- }
- }
-
- writeb(fdr, &i2c_dev->fdr);
- i2c_bus_speed[i2c_bus_num - 1] = speed;
-
- return 0;
-}
-
-
-static void _i2c_init(int speed, int slaveadd)
-{
- /* stop I2C controller */
- writeb(0x00 , &i2c_dev->cr);
-
- /* set clock */
- set_speed(speed);
-
- /* set default filter */
- writeb(IC2_FDR,&i2c_dev->dfsrr);
-
- /* write slave address */
- writeb(slaveadd, &i2c_dev->adr);
-
- /* clear status register */
- writeb(I2C_CR_MTX, &i2c_dev->sr);
-
- /* start I2C controller */
- writeb(I2C_CR_MEN, &i2c_dev->cr);
-}
-
-void i2c_init(int speed, int slaveadd)
-{
- /* Set both interfaces to the same speed and slave address */
- /* Note: This function gets called twice - before and after
- * relocation to RAM. The first time it's called, we are unable
- * to change buses, so whichever one 'i2c_dev' was initialized to
- * gets set twice. When run from RAM both buses get set properly */
-
- i2c_set_bus_num(1);
- _i2c_init(speed, slaveadd);
-#ifdef CFG_I2C2_OFFSET
- i2c_set_bus_num(2);
- _i2c_init(speed, slaveadd);
- i2c_set_bus_num(1);
-#endif /* CFG_I2C2_OFFSET */
-}
-
-static __inline__ int
-i2c_wait4bus (void)
-{
- ulong timeval = get_timer (0);
- while (readb(&i2c_dev->sr) & I2C_SR_MBB) {
- if (get_timer (timeval) > I2C_TIMEOUT) {
- return -1;
- }
- }
- return 0;
-}
-
-static __inline__ int
-i2c_wait (int write)
-{
- u32 csr;
- ulong timeval = get_timer(0);
- do {
- csr = readb(&i2c_dev->sr);
-
- if (!(csr & I2C_SR_MIF))
- continue;
-
- writeb(0x0, &i2c_dev->sr);
-
- if (csr & I2C_SR_MAL) {
- debug("i2c_wait: MAL\n");
- return -1;
- }
-
- if (!(csr & I2C_SR_MCF)) {
- debug("i2c_wait: unfinished\n");
- return -1;
- }
-
- if (write == I2C_WRITE && (csr & I2C_SR_RXAK)) {
- debug("i2c_wait: No RXACK\n");
- return -1;
- }
-
- return 0;
- } while (get_timer (timeval) < I2C_TIMEOUT);
-
- debug("i2c_wait: timed out\n");
- return -1;
-}
-
-static __inline__ int
-i2c_write_addr (u8 dev, u8 dir, int rsta)
-{
- writeb(I2C_CR_MEN | I2C_CR_MSTA | I2C_CR_MTX |
- (rsta?I2C_CR_RSTA:0),
- &i2c_dev->cr);
-
- writeb((dev << 1) | dir, &i2c_dev->dr);
-
- if (i2c_wait (I2C_WRITE) < 0)
- return 0;
- return 1;
-}
-
-static __inline__ int
-__i2c_write (u8 *data, int length)
-{
- int i;
-
- writeb(I2C_CR_MEN | I2C_CR_MSTA | I2C_CR_MTX,
- &i2c_dev->cr);
-
- for (i=0; i < length; i++) {
- writeb(data[i], &i2c_dev->dr);
-
- if (i2c_wait (I2C_WRITE) < 0)
- break;
- }
- return i;
-}
-
-static __inline__ int
-__i2c_read (u8 *data, int length)
-{
- int i;
-
- writeb(I2C_CR_MEN | I2C_CR_MSTA |
- ((length == 1) ? I2C_CR_TXAK : 0),
- &i2c_dev->cr);
-
- /* dummy read */
- readb(&i2c_dev->dr);
-
- for (i=0; i < length; i++) {
- if (i2c_wait (I2C_READ) < 0)
- break;
-
- /* Generate ack on last next to last byte */
- if (i == length - 2)
- writeb(I2C_CR_MEN | I2C_CR_MSTA |
- I2C_CR_TXAK,
- &i2c_dev->cr);
-
- /* Generate stop on last byte */
- if (i == length - 1)
- writeb(I2C_CR_MEN | I2C_CR_TXAK, &i2c_dev->cr);
-
- data[i] = readb(&i2c_dev->dr);
- }
- return i;
-}
-
-int
-i2c_read (u8 dev, uint addr, int alen, u8 *data, int length)
-{
- int i = 0;
- u8 *a = (u8*)&addr;
-
- if (i2c_wait4bus () < 0)
- goto exit;
-
- if (i2c_write_addr (dev, I2C_WRITE, 0) == 0)
- goto exit;
-
- if (__i2c_write (&a[4 - alen], alen) != alen)
- goto exit;
-
- if (i2c_write_addr (dev, I2C_READ, 1) == 0)
- goto exit;
-
- i = __i2c_read (data, length);
-
- exit:
- writeb(I2C_CR_MEN, &i2c_dev->cr);
- return !(i == length);
-}
-
-int
-i2c_write (u8 dev, uint addr, int alen, u8 *data, int length)
-{
- int i = 0;
- u8 *a = (u8*)&addr;
-
- if (i2c_wait4bus () < 0)
- goto exit;
-
- if (i2c_write_addr (dev, I2C_WRITE, 0) == 0)
- goto exit;
-
- if (__i2c_write (&a[4 - alen], alen) != alen)
- goto exit;
-
- i = __i2c_write (data, length);
-
- exit:
- writeb(I2C_CR_MEN, &i2c_dev->cr);
- return !(i == length);
-}
-
-int i2c_probe (uchar chip)
-{
- int tmp;
-
- /*
- * Try to read the first location of the chip. The underlying
- * driver doesn't appear to support sending just the chip address
- * and looking for an <ACK> back.
- */
- udelay(10000);
- return i2c_read (chip, 0, 1, (uchar *)&tmp, 1);
-}
-
-uchar i2c_reg_read (uchar i2c_addr, uchar reg)
-{
- uchar buf[1];
-
- i2c_read (i2c_addr, reg, 1, buf, 1);
-
- return (buf[0]);
-}
-
-void i2c_reg_write (uchar i2c_addr, uchar reg, uchar val)
-{
- i2c_write (i2c_addr, reg, 1, &val, 1);
-}
-
-int i2c_set_bus_num(unsigned int bus)
-{
- if(bus == 1)
- {
- i2c_dev = I2C_1;
- }
-#ifdef CFG_I2C2_OFFSET
- else if(bus == 2)
- {
- i2c_dev = I2C_2;
- }
-#endif
- else
- {
- return -1;
- }
- i2c_bus_num = bus;
- return 0;
-}
-
-int i2c_set_bus_speed(unsigned int speed)
-{
- return set_speed(speed);
-}
-
-unsigned int i2c_get_bus_num(void)
-{
- return i2c_bus_num;
-}
-
-unsigned int i2c_get_bus_speed(void)
-{
- return i2c_bus_speed[i2c_bus_num - 1];
-}
-#endif /* CONFIG_HARD_I2C */