]> git.sur5r.net Git - u-boot/blob - arch/arm/cpu/armv7/u8500/prcmu.c
snowball: Adding architecture dependent initialisation
[u-boot] / arch / arm / cpu / armv7 / u8500 / prcmu.c
1 /*
2  * Copyright (C) 2009 ST-Ericsson SA
3  *
4  * Adapted from the Linux version:
5  * Author: Kumar Sanghvi <kumar.sanghvi@stericsson.com>
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20  * This program is free software; you can redistribute it and/or modify
21  * it under the terms of the GNU General Public License version 2
22  * as published by the Free Software Foundation.
23  */
24
25 /*
26  * NOTE: This currently does not support the I2C workaround access method.
27  */
28
29 #include <common.h>
30 #include <config.h>
31 #include <asm/io.h>
32 #include <asm/arch/hardware.h>
33 #include <asm/types.h>
34 #include <asm/io.h>
35 #include <asm/errno.h>
36 #include <asm/arch/prcmu.h>
37
38 /* CPU mailbox registers */
39 #define PRCM_MBOX_CPU_VAL (U8500_PRCMU_BASE + 0x0fc)
40 #define PRCM_MBOX_CPU_SET (U8500_PRCMU_BASE + 0x100)
41 #define PRCM_MBOX_CPU_CLR (U8500_PRCMU_BASE + 0x104)
42
43 #define I2C_MBOX_BIT    (1 << 5)
44
45 static int prcmu_is_ready(void)
46 {
47         int ready = readb(PRCM_XP70_CUR_PWR_STATE) == AP_EXECUTE;
48         if (!ready)
49                 printf("PRCMU firmware not ready\n");
50         return ready;
51 }
52
53 static int _wait_for_req_complete(int num)
54 {
55         int timeout = 1000;
56
57         /* checking any already on-going transaction */
58         while ((readl(PRCM_MBOX_CPU_VAL) & (1 << num)) && timeout)
59                 timeout--;
60
61         timeout = 1000;
62
63         /* Set an interrupt to XP70 */
64         writel(1 << num, PRCM_MBOX_CPU_SET);
65
66         while ((readl(PRCM_MBOX_CPU_VAL) & (1 << num)) && timeout)
67                 timeout--;
68
69         if (!timeout) {
70                 printf("PRCMU operation timed out\n");
71                 return -1;
72         }
73
74         return 0;
75 }
76
77 /**
78  * prcmu_i2c_read - PRCMU - 4500 communication using PRCMU I2C
79  * @reg: - db8500 register bank to be accessed
80  * @slave:  - db8500 register to be accessed
81  * Returns: ACK_MB5  value containing the status
82  */
83 int prcmu_i2c_read(u8 reg, u16 slave)
84 {
85         uint8_t i2c_status;
86         uint8_t i2c_val;
87
88         if (!prcmu_is_ready())
89                 return -1;
90
91         debug("\nprcmu_4500_i2c_read:bank=%x;reg=%x;\n",
92                         reg, slave);
93
94         /* prepare the data for mailbox 5 */
95         writeb((reg << 1) | I2CREAD, PRCM_REQ_MB5_I2COPTYPE_REG);
96         writeb((1 << 3) | 0x0, PRCM_REQ_MB5_BIT_FIELDS);
97         writeb(slave, PRCM_REQ_MB5_I2CSLAVE);
98         writeb(0, PRCM_REQ_MB5_I2CVAL);
99
100         _wait_for_req_complete(REQ_MB5);
101
102         /* retrieve values */
103         debug("ack-mb5:transfer status = %x\n",
104                         readb(PRCM_ACK_MB5_STATUS));
105         debug("ack-mb5:reg bank = %x\n", readb(PRCM_ACK_MB5) >> 1);
106         debug("ack-mb5:slave_add = %x\n",
107                         readb(PRCM_ACK_MB5_SLAVE));
108         debug("ack-mb5:reg_val = %d\n", readb(PRCM_ACK_MB5_VAL));
109
110         i2c_status = readb(PRCM_ACK_MB5_STATUS);
111         i2c_val = readb(PRCM_ACK_MB5_VAL);
112
113         if (i2c_status == I2C_RD_OK)
114                 return i2c_val;
115         else {
116
117                 printf("prcmu_i2c_read:read return status= %d\n",
118                                 i2c_status);
119                 return -1;
120         }
121
122 }
123
124 /**
125  * prcmu_i2c_write - PRCMU-db8500 communication using PRCMU I2C
126  * @reg: - db8500 register bank to be accessed
127  * @slave:  - db800 register to be written to
128  * @reg_data: - the data to write
129  * Returns: ACK_MB5 value containing the status
130  */
131 int prcmu_i2c_write(u8 reg, u16 slave, u8 reg_data)
132 {
133         uint8_t i2c_status;
134
135         if (!prcmu_is_ready())
136                 return -1;
137
138         debug("\nprcmu_4500_i2c_write:bank=%x;reg=%x;\n",
139                         reg, slave);
140
141         /* prepare the data for mailbox 5 */
142         writeb((reg << 1) | I2CWRITE, PRCM_REQ_MB5_I2COPTYPE_REG);
143         writeb((1 << 3) | 0x0, PRCM_REQ_MB5_BIT_FIELDS);
144         writeb(slave, PRCM_REQ_MB5_I2CSLAVE);
145         writeb(reg_data, PRCM_REQ_MB5_I2CVAL);
146
147         debug("\ncpu_is_u8500v11\n");
148         _wait_for_req_complete(REQ_MB5);
149
150         /* retrieve values */
151         debug("ack-mb5:transfer status = %x\n",
152                         readb(PRCM_ACK_MB5_STATUS));
153         debug("ack-mb5:reg bank = %x\n", readb(PRCM_ACK_MB5) >> 1);
154         debug("ack-mb5:slave_add = %x\n",
155                         readb(PRCM_ACK_MB5_SLAVE));
156         debug("ack-mb5:reg_val = %d\n", readb(PRCM_ACK_MB5_VAL));
157
158         i2c_status = readb(PRCM_ACK_MB5_STATUS);
159         debug("\ni2c_status = %x\n", i2c_status);
160         if (i2c_status == I2C_WR_OK)
161                 return 0;
162         else {
163                 printf("ape-i2c: i2c_status : 0x%x\n", i2c_status);
164                 return -1;
165         }
166 }
167
168 void u8500_prcmu_enable(u32 *reg)
169 {
170         writel(readl(reg) | (1 << 8), reg);
171 }
172
173 void db8500_prcmu_init(void)
174 {
175         /* Enable timers */
176         writel(1 << 17, PRCM_TCR);
177
178         u8500_prcmu_enable((u32 *)PRCM_PER1CLK_MGT_REG);
179         u8500_prcmu_enable((u32 *)PRCM_PER2CLK_MGT_REG);
180         u8500_prcmu_enable((u32 *)PRCM_PER3CLK_MGT_REG);
181         /* PER4CLK does not exist */
182         u8500_prcmu_enable((u32 *)PRCM_PER5CLK_MGT_REG);
183         u8500_prcmu_enable((u32 *)PRCM_PER6CLK_MGT_REG);
184         /* Only exists in ED but is always ok to write to */
185         u8500_prcmu_enable((u32 *)PRCM_PER7CLK_MGT_REG);
186
187         u8500_prcmu_enable((u32 *)PRCM_UARTCLK_MGT_REG);
188         u8500_prcmu_enable((u32 *)PRCM_I2CCLK_MGT_REG);
189
190         u8500_prcmu_enable((u32 *)PRCM_SDMMCCLK_MGT_REG);
191
192         /* Clean up the mailbox interrupts after pre-u-boot code. */
193         writel(I2C_MBOX_BIT, PRCM_ARM_IT1_CLEAR);
194 }