]>
Commit | Line | Data |
---|---|---|
afbf8899 JR |
1 | /* |
2 | * Copyright (C) 2009 ST-Ericsson SA | |
3 | * | |
4 | * Adapted from the Linux version: | |
5 | * Author: Kumar Sanghvi <kumar.sanghvi@stericsson.com> | |
6 | * | |
1a459660 | 7 | * SPDX-License-Identifier: GPL-2.0+ |
afbf8899 JR |
8 | */ |
9 | ||
10 | /* | |
11 | * NOTE: This currently does not support the I2C workaround access method. | |
12 | */ | |
13 | ||
14 | #include <common.h> | |
15 | #include <config.h> | |
16 | #include <asm/io.h> | |
17 | #include <asm/arch/hardware.h> | |
18 | #include <asm/types.h> | |
19 | #include <asm/io.h> | |
20 | #include <asm/errno.h> | |
42cb8fb6 | 21 | #include <asm/arch/prcmu.h> |
afbf8899 JR |
22 | |
23 | /* CPU mailbox registers */ | |
101a769d MP |
24 | #define PRCMU_I2C_WRITE(slave) \ |
25 | (((slave) << 1) | I2CWRITE | (1 << 6)) | |
26 | #define PRCMU_I2C_READ(slave) \ | |
27 | (((slave) << 1) | I2CREAD | (1 << 6)) | |
afbf8899 | 28 | |
9652de7c MP |
29 | #define I2C_MBOX_BIT (1 << 5) |
30 | ||
afbf8899 JR |
31 | static int prcmu_is_ready(void) |
32 | { | |
33 | int ready = readb(PRCM_XP70_CUR_PWR_STATE) == AP_EXECUTE; | |
34 | if (!ready) | |
35 | printf("PRCMU firmware not ready\n"); | |
36 | return ready; | |
37 | } | |
38 | ||
101a769d | 39 | static int wait_for_i2c_mbx_rdy(void) |
afbf8899 | 40 | { |
101a769d | 41 | int timeout = 10000; |
afbf8899 | 42 | |
101a769d MP |
43 | if (readl(PRCM_ARM_IT1_VAL) & I2C_MBOX_BIT) { |
44 | printf("prcmu: warning i2c mailbox was not acked\n"); | |
45 | /* clear mailbox 5 ack irq */ | |
46 | writel(I2C_MBOX_BIT, PRCM_ARM_IT1_CLEAR); | |
47 | } | |
48 | ||
49 | /* check any already on-going transaction */ | |
50 | while ((readl(PRCM_MBOX_CPU_VAL) & I2C_MBOX_BIT) && timeout) | |
42cb8fb6 | 51 | timeout--; |
afbf8899 | 52 | |
101a769d MP |
53 | if (timeout == 0) |
54 | return -1; | |
55 | ||
56 | return 0; | |
57 | } | |
58 | ||
59 | static int wait_for_i2c_req_done(void) | |
60 | { | |
61 | int timeout = 10000; | |
afbf8899 JR |
62 | |
63 | /* Set an interrupt to XP70 */ | |
101a769d | 64 | writel(I2C_MBOX_BIT, PRCM_MBOX_CPU_SET); |
afbf8899 | 65 | |
101a769d MP |
66 | /* wait for mailbox 5 (i2c) ack */ |
67 | while (!(readl(PRCM_ARM_IT1_VAL) & I2C_MBOX_BIT) && timeout) | |
42cb8fb6 | 68 | timeout--; |
afbf8899 | 69 | |
101a769d | 70 | if (timeout == 0) |
afbf8899 | 71 | return -1; |
afbf8899 JR |
72 | |
73 | return 0; | |
74 | } | |
75 | ||
76 | /** | |
77 | * prcmu_i2c_read - PRCMU - 4500 communication using PRCMU I2C | |
78 | * @reg: - db8500 register bank to be accessed | |
79 | * @slave: - db8500 register to be accessed | |
80 | * Returns: ACK_MB5 value containing the status | |
81 | */ | |
82 | int prcmu_i2c_read(u8 reg, u16 slave) | |
83 | { | |
84 | uint8_t i2c_status; | |
85 | uint8_t i2c_val; | |
101a769d | 86 | int ret; |
afbf8899 JR |
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 | ||
101a769d MP |
94 | ret = wait_for_i2c_mbx_rdy(); |
95 | if (ret) { | |
96 | printf("prcmu_i2c_read: mailbox became not ready\n"); | |
97 | return ret; | |
98 | } | |
99 | ||
afbf8899 | 100 | /* prepare the data for mailbox 5 */ |
101a769d | 101 | writeb(PRCMU_I2C_READ(reg), PRCM_REQ_MB5_I2COPTYPE_REG); |
afbf8899 JR |
102 | writeb((1 << 3) | 0x0, PRCM_REQ_MB5_BIT_FIELDS); |
103 | writeb(slave, PRCM_REQ_MB5_I2CSLAVE); | |
104 | writeb(0, PRCM_REQ_MB5_I2CVAL); | |
105 | ||
101a769d MP |
106 | ret = wait_for_i2c_req_done(); |
107 | if (ret) { | |
108 | printf("prcmu_i2c_read: mailbox request timed out\n"); | |
109 | return ret; | |
110 | } | |
afbf8899 JR |
111 | |
112 | /* retrieve values */ | |
113 | debug("ack-mb5:transfer status = %x\n", | |
114 | readb(PRCM_ACK_MB5_STATUS)); | |
115 | debug("ack-mb5:reg bank = %x\n", readb(PRCM_ACK_MB5) >> 1); | |
116 | debug("ack-mb5:slave_add = %x\n", | |
117 | readb(PRCM_ACK_MB5_SLAVE)); | |
118 | debug("ack-mb5:reg_val = %d\n", readb(PRCM_ACK_MB5_VAL)); | |
119 | ||
120 | i2c_status = readb(PRCM_ACK_MB5_STATUS); | |
121 | i2c_val = readb(PRCM_ACK_MB5_VAL); | |
101a769d MP |
122 | /* clear mailbox 5 ack irq */ |
123 | writel(I2C_MBOX_BIT, PRCM_ARM_IT1_CLEAR); | |
afbf8899 JR |
124 | |
125 | if (i2c_status == I2C_RD_OK) | |
126 | return i2c_val; | |
afbf8899 | 127 | |
101a769d MP |
128 | printf("prcmu_i2c_read:read return status= %d\n", i2c_status); |
129 | return -1; | |
afbf8899 JR |
130 | } |
131 | ||
132 | /** | |
133 | * prcmu_i2c_write - PRCMU-db8500 communication using PRCMU I2C | |
134 | * @reg: - db8500 register bank to be accessed | |
135 | * @slave: - db800 register to be written to | |
136 | * @reg_data: - the data to write | |
137 | * Returns: ACK_MB5 value containing the status | |
138 | */ | |
139 | int prcmu_i2c_write(u8 reg, u16 slave, u8 reg_data) | |
140 | { | |
141 | uint8_t i2c_status; | |
101a769d | 142 | int ret; |
afbf8899 JR |
143 | |
144 | if (!prcmu_is_ready()) | |
145 | return -1; | |
146 | ||
147 | debug("\nprcmu_4500_i2c_write:bank=%x;reg=%x;\n", | |
148 | reg, slave); | |
149 | ||
101a769d MP |
150 | ret = wait_for_i2c_mbx_rdy(); |
151 | if (ret) { | |
152 | printf("prcmu_i2c_write: mailbox became not ready\n"); | |
153 | return ret; | |
154 | } | |
155 | ||
afbf8899 | 156 | /* prepare the data for mailbox 5 */ |
101a769d | 157 | writeb(PRCMU_I2C_WRITE(reg), PRCM_REQ_MB5_I2COPTYPE_REG); |
afbf8899 JR |
158 | writeb((1 << 3) | 0x0, PRCM_REQ_MB5_BIT_FIELDS); |
159 | writeb(slave, PRCM_REQ_MB5_I2CSLAVE); | |
160 | writeb(reg_data, PRCM_REQ_MB5_I2CVAL); | |
161 | ||
101a769d MP |
162 | ret = wait_for_i2c_req_done(); |
163 | if (ret) { | |
164 | printf("prcmu_i2c_write: mailbox request timed out\n"); | |
165 | return ret; | |
166 | } | |
afbf8899 JR |
167 | |
168 | /* retrieve values */ | |
169 | debug("ack-mb5:transfer status = %x\n", | |
170 | readb(PRCM_ACK_MB5_STATUS)); | |
171 | debug("ack-mb5:reg bank = %x\n", readb(PRCM_ACK_MB5) >> 1); | |
172 | debug("ack-mb5:slave_add = %x\n", | |
173 | readb(PRCM_ACK_MB5_SLAVE)); | |
174 | debug("ack-mb5:reg_val = %d\n", readb(PRCM_ACK_MB5_VAL)); | |
175 | ||
176 | i2c_status = readb(PRCM_ACK_MB5_STATUS); | |
177 | debug("\ni2c_status = %x\n", i2c_status); | |
101a769d MP |
178 | /* clear mailbox 5 ack irq */ |
179 | writel(I2C_MBOX_BIT, PRCM_ARM_IT1_CLEAR); | |
180 | ||
afbf8899 JR |
181 | if (i2c_status == I2C_WR_OK) |
182 | return 0; | |
101a769d MP |
183 | |
184 | printf("%s: i2c_status : 0x%x\n", __func__, i2c_status); | |
185 | return -1; | |
afbf8899 | 186 | } |
9652de7c MP |
187 | |
188 | void u8500_prcmu_enable(u32 *reg) | |
189 | { | |
190 | writel(readl(reg) | (1 << 8), reg); | |
191 | } | |
192 | ||
193 | void db8500_prcmu_init(void) | |
194 | { | |
195 | /* Enable timers */ | |
196 | writel(1 << 17, PRCM_TCR); | |
197 | ||
198 | u8500_prcmu_enable((u32 *)PRCM_PER1CLK_MGT_REG); | |
199 | u8500_prcmu_enable((u32 *)PRCM_PER2CLK_MGT_REG); | |
200 | u8500_prcmu_enable((u32 *)PRCM_PER3CLK_MGT_REG); | |
201 | /* PER4CLK does not exist */ | |
202 | u8500_prcmu_enable((u32 *)PRCM_PER5CLK_MGT_REG); | |
203 | u8500_prcmu_enable((u32 *)PRCM_PER6CLK_MGT_REG); | |
204 | /* Only exists in ED but is always ok to write to */ | |
205 | u8500_prcmu_enable((u32 *)PRCM_PER7CLK_MGT_REG); | |
206 | ||
207 | u8500_prcmu_enable((u32 *)PRCM_UARTCLK_MGT_REG); | |
208 | u8500_prcmu_enable((u32 *)PRCM_I2CCLK_MGT_REG); | |
209 | ||
210 | u8500_prcmu_enable((u32 *)PRCM_SDMMCCLK_MGT_REG); | |
211 | ||
212 | /* Clean up the mailbox interrupts after pre-u-boot code. */ | |
213 | writel(I2C_MBOX_BIT, PRCM_ARM_IT1_CLEAR); | |
214 | } |