]> git.kernelconcepts.de Git - karo-tx-uboot.git/blobdiff - drivers/i2c/mv_i2c.c
sf: Tidy up public and private header files
[karo-tx-uboot.git] / drivers / i2c / mv_i2c.c
index 562b9502248a961cacbfed315b8fa489ea30780f..dac346334d8100f46b90e18eb82a6b74eff8b100 100644 (file)
@@ -8,23 +8,10 @@
  * (C) Copyright 2003 Pengutronix e.K.
  * Robert Schwebel <r.schwebel@pengutronix.de>
  *
- * See file CREDITS for list of people who contributed to this
- * project.
+ * (C) Copyright 2011 Marvell Inc.
+ * Lei Wen <leiwen@marvell.com>
  *
- * 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
+ * SPDX-License-Identifier:    GPL-2.0+
  *
  * Back ported to the 8xx platform (from the 8260 platform) by
  * Murray.Jensen@cmst.csiro.au, 27-Jan-01.
 #include <asm/io.h>
 
 #ifdef CONFIG_HARD_I2C
-
-/*
- *     - CONFIG_SYS_I2C_SPEED
- *     - I2C_PXA_SLAVE_ADDR
- */
-
-#include <asm/arch/hardware.h>
-#include <asm/arch/pxa-regs.h>
 #include <i2c.h>
-
-#if (CONFIG_SYS_I2C_SPEED == 400000)
-#define I2C_ICR_INIT   (ICR_FM | ICR_BEIE | ICR_IRFIE | ICR_ITEIE | ICR_GCD \
-                       | ICR_SCLE)
-#else
-#define I2C_ICR_INIT   (ICR_BEIE | ICR_IRFIE | ICR_ITEIE | ICR_GCD | ICR_SCLE)
-#endif
-
-#define I2C_ISR_INIT           0x7FF
+#include "mv_i2c.h"
 
 #ifdef DEBUG_I2C
 #define PRINTD(x) printf x
 #define PRINTD(x)
 #endif
 
-/* Shall the current transfer have a start/stop condition? */
-#define I2C_COND_NORMAL                0
-#define I2C_COND_START         1
-#define I2C_COND_STOP          2
-
-/* Shall the current transfer be ack/nacked or being waited for it? */
-#define I2C_ACKNAK_WAITACK     1
-#define I2C_ACKNAK_SENDACK     2
-#define I2C_ACKNAK_SENDNAK     4
-
-/* Specify who shall transfer the data (master or slave) */
-#define I2C_READ               0
-#define I2C_WRITE              1
-
 /* All transfers are described by this data structure */
 struct i2c_msg {
        u8 condition;
@@ -81,27 +38,86 @@ struct i2c_msg {
        u8 data;
 };
 
+struct mv_i2c {
+       u32 ibmr;
+       u32 pad0;
+       u32 idbr;
+       u32 pad1;
+       u32 icr;
+       u32 pad2;
+       u32 isr;
+       u32 pad3;
+       u32 isar;
+};
+
+static struct mv_i2c *base;
+static void i2c_board_init(struct mv_i2c *base)
+{
+#ifdef CONFIG_SYS_I2C_INIT_BOARD
+       u32 icr;
+       /*
+        * call board specific i2c bus reset routine before accessing the
+        * environment, which might be in a chip on that bus. For details
+        * about this problem see doc/I2C_Edge_Conditions.
+        *
+        * disable I2C controller first, otherwhise it thinks we want to
+        * talk to the slave port...
+        */
+       icr = readl(&base->icr);
+       writel(readl(&base->icr) & ~(ICR_SCLE | ICR_IUE), &base->icr);
+
+       i2c_init_board();
+
+       writel(icr, &base->icr);
+#endif
+}
+
+#ifdef CONFIG_I2C_MULTI_BUS
+static u32 i2c_regs[CONFIG_MV_I2C_NUM] = CONFIG_MV_I2C_REG;
+static unsigned int bus_initialized[CONFIG_MV_I2C_NUM];
+static unsigned int current_bus;
+
+int i2c_set_bus_num(unsigned int bus)
+{
+       if ((bus < 0) || (bus >= CONFIG_MV_I2C_NUM)) {
+               printf("Bad bus: %d\n", bus);
+               return -1;
+       }
+
+       base = (struct mv_i2c *)i2c_regs[bus];
+       current_bus = bus;
+
+       if (!bus_initialized[current_bus]) {
+               i2c_board_init(base);
+               bus_initialized[current_bus] = 1;
+       }
+
+       return 0;
+}
+
+unsigned int i2c_get_bus_num(void)
+{
+       return current_bus;
+}
+#endif
+
 /*
- * i2c_pxa_reset: - reset the host controller
+ * i2c_reset: - reset the host controller
  *
  */
 static void i2c_reset(void)
 {
-       writel(readl(ICR) & ~ICR_IUE, ICR);     /* disable unit */
-       writel(readl(ICR) | ICR_UR, ICR);       /* reset the unit */
+       writel(readl(&base->icr) & ~ICR_IUE, &base->icr); /* disable unit */
+       writel(readl(&base->icr) | ICR_UR, &base->icr);   /* reset the unit */
        udelay(100);
-       writel(readl(ICR) & ~ICR_IUE, ICR);     /* disable unit */
-#ifdef CONFIG_CPU_MONAHANS
-       /* | CKENB_1_PWM1 | CKENB_0_PWM0); */
-       writel(readl(CKENB) | (CKENB_4_I2C), CKENB);
-#else /* CONFIG_CPU_MONAHANS */
-       /* set the global I2C clock on */
-       writel(readl(CKEN) | CKEN14_I2C, CKEN);
-#endif
-       writel(I2C_PXA_SLAVE_ADDR, ISAR);       /* set our slave address */
-       writel(I2C_ICR_INIT, ICR);              /* set control reg values */
-       writel(I2C_ISR_INIT, ISR);              /* set clear interrupt bits */
-       writel(readl(ICR) | ICR_IUE, ICR);      /* enable unit */
+       writel(readl(&base->icr) & ~ICR_IUE, &base->icr); /* disable unit */
+
+       i2c_clk_enable();
+
+       writel(CONFIG_SYS_I2C_SLAVE, &base->isar); /* set our slave address */
+       writel(I2C_ICR_INIT, &base->icr); /* set control reg values */
+       writel(I2C_ISR_INIT, &base->isr); /* set clear interrupt bits */
+       writel(readl(&base->icr) | ICR_IUE, &base->icr); /* enable unit */
        udelay(100);
 }
 
@@ -114,13 +130,15 @@ static void i2c_reset(void)
 static int i2c_isr_set_cleared(unsigned long set_mask,
                               unsigned long cleared_mask)
 {
-       int timeout = 1000;
+       int timeout = 1000, isr;
 
-       while (((ISR & set_mask) != set_mask) || ((ISR & cleared_mask) != 0)) {
+       do {
+               isr = readl(&base->isr);
                udelay(10);
                if (timeout-- < 0)
                        return 0;
-       }
+       } while (((isr & set_mask) != set_mask)
+               || ((isr & cleared_mask) != 0));
 
        return 1;
 }
@@ -153,26 +171,26 @@ int i2c_transfer(struct i2c_msg *msg)
                        goto transfer_error_bus_busy;
 
                /* start transmission */
-               writel(readl(ICR) & ~ICR_START, ICR);
-               writel(readl(ICR) & ~ICR_STOP, ICR);
-               writel(msg->data, IDBR);
+               writel(readl(&base->icr) & ~ICR_START, &base->icr);
+               writel(readl(&base->icr) & ~ICR_STOP, &base->icr);
+               writel(msg->data, &base->idbr);
                if (msg->condition == I2C_COND_START)
-                       writel(readl(ICR) | ICR_START, ICR);
+                       writel(readl(&base->icr) | ICR_START, &base->icr);
                if (msg->condition == I2C_COND_STOP)
-                       writel(readl(ICR) | ICR_STOP, ICR);
+                       writel(readl(&base->icr) | ICR_STOP, &base->icr);
                if (msg->acknack == I2C_ACKNAK_SENDNAK)
-                       writel(readl(ICR) | ICR_ACKNAK, ICR);
+                       writel(readl(&base->icr) | ICR_ACKNAK, &base->icr);
                if (msg->acknack == I2C_ACKNAK_SENDACK)
-                       writel(readl(ICR) & ~ICR_ACKNAK, ICR);
-               writel(readl(ICR) & ~ICR_ALDIE, ICR);
-               writel(readl(ICR) | ICR_TB, ICR);
+                       writel(readl(&base->icr) & ~ICR_ACKNAK, &base->icr);
+               writel(readl(&base->icr) & ~ICR_ALDIE, &base->icr);
+               writel(readl(&base->icr) | ICR_TB, &base->icr);
 
                /* transmit register empty? */
                if (!i2c_isr_set_cleared(ISR_ITE, 0))
                        goto transfer_error_transmit_timeout;
 
                /* clear 'transmit empty' state */
-               writel(readl(ISR) | ISR_ITE, ISR);
+               writel(readl(&base->isr) | ISR_ITE, &base->isr);
 
                /* wait for ACK from slave */
                if (msg->acknack == I2C_ACKNAK_WAITACK)
@@ -187,28 +205,27 @@ int i2c_transfer(struct i2c_msg *msg)
                        goto transfer_error_bus_busy;
 
                /* start receive */
-               writel(readl(ICR) & ~ICR_START, ICR);
-               writel(readl(ICR) & ~ICR_STOP, ICR);
+               writel(readl(&base->icr) & ~ICR_START, &base->icr);
+               writel(readl(&base->icr) & ~ICR_STOP, &base->icr);
                if (msg->condition == I2C_COND_START)
-                       writel(readl(ICR) | ICR_START, ICR);
+                       writel(readl(&base->icr) | ICR_START, &base->icr);
                if (msg->condition == I2C_COND_STOP)
-                       writel(readl(ICR) | ICR_STOP, ICR);
+                       writel(readl(&base->icr) | ICR_STOP, &base->icr);
                if (msg->acknack == I2C_ACKNAK_SENDNAK)
-                       writel(readl(ICR) | ICR_ACKNAK, ICR);
+                       writel(readl(&base->icr) | ICR_ACKNAK, &base->icr);
                if (msg->acknack == I2C_ACKNAK_SENDACK)
-                       writel(readl(ICR) & ~ICR_ACKNAK, ICR);
-               writel(readl(ICR) & ~ICR_ALDIE, ICR);
-               writel(readl(ICR) | ICR_TB, ICR);
+                       writel(readl(&base->icr) & ~ICR_ACKNAK, &base->icr);
+               writel(readl(&base->icr) & ~ICR_ALDIE, &base->icr);
+               writel(readl(&base->icr) | ICR_TB, &base->icr);
 
                /* receive register full? */
                if (!i2c_isr_set_cleared(ISR_IRF, 0))
                        goto transfer_error_receive_timeout;
 
-               msg->data = readl(IDBR);
+               msg->data = readl(&base->idbr);
 
                /* clear 'receive empty' state */
-               writel(readl(ISR) | ISR_IRF, ISR);
-
+               writel(readl(&base->isr) | ISR_IRF, &base->isr);
                break;
        default:
                goto transfer_error_illegal_param;
@@ -241,7 +258,7 @@ transfer_error_bus_busy:
                ret = -6; goto i2c_transfer_finish;
 
 i2c_transfer_finish:
-               PRINTD(("i2c_transfer: ISR: 0x%04x\n", ISR));
+               PRINTD(("i2c_transfer: ISR: 0x%04x\n", readl(&base->isr)));
                i2c_reset();
                return ret;
 }
@@ -251,12 +268,14 @@ i2c_transfer_finish:
 /* ------------------------------------------------------------------------ */
 void i2c_init(int speed, int slaveaddr)
 {
-#ifdef CONFIG_SYS_I2C_INIT_BOARD
-       /* call board specific i2c bus reset routine before accessing the   */
-       /* environment, which might be in a chip on that bus. For details   */
-       /* about this problem see doc/I2C_Edge_Conditions.                  */
-       i2c_init_board();
+#ifdef CONFIG_I2C_MULTI_BUS
+       current_bus = 0;
+       base = (struct mv_i2c *)i2c_regs[current_bus];
+#else
+       base = (struct mv_i2c *)CONFIG_MV_I2C_REG;
 #endif
+
+       i2c_board_init(base);
 }
 
 /*