]> git.sur5r.net Git - u-boot/blobdiff - arch/arm/cpu/armv7/u8500/prcmu.c
Merge branch 'master' of git://git.denx.de/u-boot-mmc
[u-boot] / arch / arm / cpu / armv7 / u8500 / prcmu.c
index b256d27b84e7d3300687f4d9f8ce65cde6cd296d..26ffdc2e02043d8b0825b56a97c40129aec25502 100644 (file)
@@ -4,22 +4,7 @@
  * Adapted from the Linux version:
  * Author: Kumar Sanghvi <kumar.sanghvi@stericsson.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., 675 Mass Ave, Cambridge, MA 02139, USA.
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2
- * as published by the Free Software Foundation.
+ * SPDX-License-Identifier:    GPL-2.0+
  */
 
 /*
 #include <asm/arch/prcmu.h>
 
 /* CPU mailbox registers */
-#define PRCM_MBOX_CPU_VAL (U8500_PRCMU_BASE + 0x0fc)
-#define PRCM_MBOX_CPU_SET (U8500_PRCMU_BASE + 0x100)
-#define PRCM_MBOX_CPU_CLR (U8500_PRCMU_BASE + 0x104)
+#define PRCMU_I2C_WRITE(slave)  \
+       (((slave) << 1) | I2CWRITE | (1 << 6))
+#define PRCMU_I2C_READ(slave) \
+       (((slave) << 1) | I2CREAD | (1 << 6))
+
+#define I2C_MBOX_BIT    (1 << 5)
 
 static int prcmu_is_ready(void)
 {
@@ -48,26 +36,39 @@ static int prcmu_is_ready(void)
        return ready;
 }
 
-static int _wait_for_req_complete(int num)
+static int wait_for_i2c_mbx_rdy(void)
 {
-       int timeout = 1000;
+       int timeout = 10000;
+
+       if (readl(PRCM_ARM_IT1_VAL) & I2C_MBOX_BIT) {
+               printf("prcmu: warning i2c mailbox was not acked\n");
+               /* clear mailbox 5 ack irq */
+               writel(I2C_MBOX_BIT, PRCM_ARM_IT1_CLEAR);
+       }
 
-       /* checking any already on-going transaction */
-       while ((readl(PRCM_MBOX_CPU_VAL) & (1 << num)) && timeout)
+       /* check any already on-going transaction */
+       while ((readl(PRCM_MBOX_CPU_VAL) & I2C_MBOX_BIT) && timeout)
                timeout--;
 
-       timeout = 1000;
+       if (timeout == 0)
+               return -1;
+
+       return 0;
+}
+
+static int wait_for_i2c_req_done(void)
+{
+       int timeout = 10000;
 
        /* Set an interrupt to XP70 */
-       writel(1 << num, PRCM_MBOX_CPU_SET);
+       writel(I2C_MBOX_BIT, PRCM_MBOX_CPU_SET);
 
-       while ((readl(PRCM_MBOX_CPU_VAL) & (1 << num)) && timeout)
+       /* wait for mailbox 5 (i2c) ack */
+       while (!(readl(PRCM_ARM_IT1_VAL) & I2C_MBOX_BIT) && timeout)
                timeout--;
 
-       if (!timeout) {
-               printf("PRCMU operation timed out\n");
+       if (timeout == 0)
                return -1;
-       }
 
        return 0;
 }
@@ -82,6 +83,7 @@ int prcmu_i2c_read(u8 reg, u16 slave)
 {
        uint8_t i2c_status;
        uint8_t i2c_val;
+       int ret;
 
        if (!prcmu_is_ready())
                return -1;
@@ -89,13 +91,23 @@ int prcmu_i2c_read(u8 reg, u16 slave)
        debug("\nprcmu_4500_i2c_read:bank=%x;reg=%x;\n",
                        reg, slave);
 
+       ret = wait_for_i2c_mbx_rdy();
+       if (ret) {
+               printf("prcmu_i2c_read: mailbox became not ready\n");
+               return ret;
+       }
+
        /* prepare the data for mailbox 5 */
-       writeb((reg << 1) | I2CREAD, PRCM_REQ_MB5_I2COPTYPE_REG);
+       writeb(PRCMU_I2C_READ(reg), PRCM_REQ_MB5_I2COPTYPE_REG);
        writeb((1 << 3) | 0x0, PRCM_REQ_MB5_BIT_FIELDS);
        writeb(slave, PRCM_REQ_MB5_I2CSLAVE);
        writeb(0, PRCM_REQ_MB5_I2CVAL);
 
-       _wait_for_req_complete(REQ_MB5);
+       ret = wait_for_i2c_req_done();
+       if (ret) {
+               printf("prcmu_i2c_read: mailbox request timed out\n");
+               return ret;
+       }
 
        /* retrieve values */
        debug("ack-mb5:transfer status = %x\n",
@@ -107,16 +119,14 @@ int prcmu_i2c_read(u8 reg, u16 slave)
 
        i2c_status = readb(PRCM_ACK_MB5_STATUS);
        i2c_val = readb(PRCM_ACK_MB5_VAL);
+       /* clear mailbox 5 ack irq */
+       writel(I2C_MBOX_BIT, PRCM_ARM_IT1_CLEAR);
 
        if (i2c_status == I2C_RD_OK)
                return i2c_val;
-       else {
-
-               printf("prcmu_i2c_read:read return status= %d\n",
-                               i2c_status);
-               return -1;
-       }
 
+       printf("prcmu_i2c_read:read return status= %d\n", i2c_status);
+       return -1;
 }
 
 /**
@@ -129,6 +139,7 @@ int prcmu_i2c_read(u8 reg, u16 slave)
 int prcmu_i2c_write(u8 reg, u16 slave, u8 reg_data)
 {
        uint8_t i2c_status;
+       int ret;
 
        if (!prcmu_is_ready())
                return -1;
@@ -136,14 +147,23 @@ int prcmu_i2c_write(u8 reg, u16 slave, u8 reg_data)
        debug("\nprcmu_4500_i2c_write:bank=%x;reg=%x;\n",
                        reg, slave);
 
+       ret = wait_for_i2c_mbx_rdy();
+       if (ret) {
+               printf("prcmu_i2c_write: mailbox became not ready\n");
+               return ret;
+       }
+
        /* prepare the data for mailbox 5 */
-       writeb((reg << 1) | I2CWRITE, PRCM_REQ_MB5_I2COPTYPE_REG);
+       writeb(PRCMU_I2C_WRITE(reg), PRCM_REQ_MB5_I2COPTYPE_REG);
        writeb((1 << 3) | 0x0, PRCM_REQ_MB5_BIT_FIELDS);
        writeb(slave, PRCM_REQ_MB5_I2CSLAVE);
        writeb(reg_data, PRCM_REQ_MB5_I2CVAL);
 
-       debug("\ncpu_is_u8500v11\n");
-       _wait_for_req_complete(REQ_MB5);
+       ret = wait_for_i2c_req_done();
+       if (ret) {
+               printf("prcmu_i2c_write: mailbox request timed out\n");
+               return ret;
+       }
 
        /* retrieve values */
        debug("ack-mb5:transfer status = %x\n",
@@ -155,10 +175,40 @@ int prcmu_i2c_write(u8 reg, u16 slave, u8 reg_data)
 
        i2c_status = readb(PRCM_ACK_MB5_STATUS);
        debug("\ni2c_status = %x\n", i2c_status);
+       /* clear mailbox 5 ack irq */
+       writel(I2C_MBOX_BIT, PRCM_ARM_IT1_CLEAR);
+
        if (i2c_status == I2C_WR_OK)
                return 0;
-       else {
-               printf("ape-i2c: i2c_status : 0x%x\n", i2c_status);
-               return -1;
-       }
+
+       printf("%s: i2c_status : 0x%x\n", __func__, i2c_status);
+       return -1;
+}
+
+void u8500_prcmu_enable(u32 *reg)
+{
+       writel(readl(reg) | (1 << 8), reg);
+}
+
+void db8500_prcmu_init(void)
+{
+       /* Enable timers */
+       writel(1 << 17, PRCM_TCR);
+
+       u8500_prcmu_enable((u32 *)PRCM_PER1CLK_MGT_REG);
+       u8500_prcmu_enable((u32 *)PRCM_PER2CLK_MGT_REG);
+       u8500_prcmu_enable((u32 *)PRCM_PER3CLK_MGT_REG);
+       /* PER4CLK does not exist */
+       u8500_prcmu_enable((u32 *)PRCM_PER5CLK_MGT_REG);
+       u8500_prcmu_enable((u32 *)PRCM_PER6CLK_MGT_REG);
+       /* Only exists in ED but is always ok to write to */
+       u8500_prcmu_enable((u32 *)PRCM_PER7CLK_MGT_REG);
+
+       u8500_prcmu_enable((u32 *)PRCM_UARTCLK_MGT_REG);
+       u8500_prcmu_enable((u32 *)PRCM_I2CCLK_MGT_REG);
+
+       u8500_prcmu_enable((u32 *)PRCM_SDMMCCLK_MGT_REG);
+
+       /* Clean up the mailbox interrupts after pre-u-boot code. */
+       writel(I2C_MBOX_BIT, PRCM_ARM_IT1_CLEAR);
 }