blob: fa917ceb7d7d2031206efb9a897bc9cae188e568 [file] [log] [blame]
Kinson Chikea646242011-09-01 13:53:16 -07001/*
2 * Copyright (c) 2009, Google Inc.
3 * All rights reserved.
4 *
Duy Truongf3ac7b32013-02-13 01:07:28 -08005 * Copyright (c) 2009-2011, The Linux Foundation. All rights reserved.
Kinson Chikea646242011-09-01 13:53:16 -07006 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * * Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * * Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in
14 * the documentation and/or other materials provided with the
15 * distribution.
16 * * Neither the name of Google, Inc. nor the names of its contributors
17 * may be used to endorse or promote products derived from this
18 * software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
26 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
27 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
28 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
29 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
30 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33#include <debug.h>
34#include <reg.h>
35#include <sys/types.h>
36#include <dev/ssbi.h>
Channagoud Kadabie1ecef52012-02-04 15:54:34 +053037#ifdef TARGET_USES_RSPIN_LOCK
38#include <platform/remote_spinlock.h>
39#endif
Kinson Chikea646242011-09-01 13:53:16 -070040
41int i2c_ssbi_poll_for_device_ready(void)
42{
43 unsigned long timeout = SSBI_TIMEOUT_US;
44
45 while (!(readl(MSM_SSBI_BASE + SSBI2_STATUS) & SSBI_STATUS_READY)) {
46 if (--timeout == 0) {
47 dprintf(INFO, "In Device ready function:Timeout, status %x\n", readl(MSM_SSBI_BASE + SSBI2_STATUS));
48 return 1;
49 }
50 }
51
52 return 0;
53}
54
55int i2c_ssbi_poll_for_read_completed(void)
56{
57 unsigned long timeout = SSBI_TIMEOUT_US;
58
59 while (!(readl(MSM_SSBI_BASE + SSBI2_STATUS) & SSBI_STATUS_RD_READY)) {
60 if (--timeout == 0) {
61 dprintf(INFO, "In read completed function:Timeout, status %x\n", readl(MSM_SSBI_BASE + SSBI2_STATUS));
62 return 1;
63 }
64 }
65
66 return 0;
67}
68
69int i2c_ssbi_read_bytes(unsigned char *buffer, unsigned short length,
70 unsigned short slave_addr)
71{
72 int ret = 0;
73 unsigned char *buf = buffer;
74 unsigned short len = length;
75 unsigned short addr = slave_addr;
Channagoud Kadabie1ecef52012-02-04 15:54:34 +053076 unsigned long read_cmd = 0;
77 unsigned long mode2 = 0;
78
79 /*
80 * Use remote spin locks since SSBI2 controller is shared with nonHLOS proc
81 */
Channagoud Kadabie18a52d2012-10-04 15:18:55 +053082#if TARGET_USES_RSPIN_LOCK
Channagoud Kadabie1ecef52012-02-04 15:54:34 +053083 remote_spin_lock(rlock);
84#endif
85 read_cmd = SSBI_CMD_READ(addr);
86 mode2 = readl(MSM_SSBI_BASE + SSBI2_MODE2);
Kinson Chikea646242011-09-01 13:53:16 -070087
88 //buf = alloc(len * sizeof(8));
89 if (mode2 & SSBI_MODE2_SSBI2_MODE)
90 writel(SSBI_MODE2_REG_ADDR_15_8(mode2, addr),
91 MSM_SSBI_BASE + SSBI2_MODE2);
92
93 while (len) {
94 ret = i2c_ssbi_poll_for_device_ready();
95 if (ret) {
96 dprintf (CRITICAL, "Error: device not ready\n");
Channagoud Kadabie1ecef52012-02-04 15:54:34 +053097 goto end;
Kinson Chikea646242011-09-01 13:53:16 -070098 }
99
100 writel(read_cmd, MSM_SSBI_BASE + SSBI2_CMD);
101
102 ret = i2c_ssbi_poll_for_read_completed();
103 if (ret) {
104 dprintf (CRITICAL, "Error: read not completed\n");
Channagoud Kadabie1ecef52012-02-04 15:54:34 +0530105 goto end;
Kinson Chikea646242011-09-01 13:53:16 -0700106 }
107
108 *buf++ = readl(MSM_SSBI_BASE + SSBI2_RD) & SSBI_RD_REG_DATA_MASK;
109 len--;
110 }
Channagoud Kadabie1ecef52012-02-04 15:54:34 +0530111end:
Channagoud Kadabie18a52d2012-10-04 15:18:55 +0530112#if TARGET_USES_RSPIN_LOCK
Channagoud Kadabie1ecef52012-02-04 15:54:34 +0530113 remote_spin_unlock(rlock);
114#endif
115 return ret;
Kinson Chikea646242011-09-01 13:53:16 -0700116}
117
118int i2c_ssbi_write_bytes(unsigned char *buffer, unsigned short length,
119 unsigned short slave_addr)
120{
121 int ret = 0;
122 unsigned long timeout = SSBI_TIMEOUT_US;
123 unsigned char *buf = buffer;
124 unsigned short len = length;
125 unsigned short addr = slave_addr;
Channagoud Kadabie1ecef52012-02-04 15:54:34 +0530126 unsigned long mode2 = 0;
127
128 /*
129 * Use remote spin locks since SSBI2 controller is shared with nonHLOS proc
130 */
Channagoud Kadabie18a52d2012-10-04 15:18:55 +0530131#if TARGET_USES_RSPIN_LOCK
Channagoud Kadabie1ecef52012-02-04 15:54:34 +0530132 remote_spin_lock(rlock);
133#endif
134 mode2 = readl(MSM_SSBI_BASE + SSBI2_MODE2);
Kinson Chikea646242011-09-01 13:53:16 -0700135
136 if (mode2 & SSBI_MODE2_SSBI2_MODE)
137 writel(SSBI_MODE2_REG_ADDR_15_8(mode2, addr),
138 MSM_SSBI_BASE + SSBI2_MODE2);
139
140 while (len) {
141 ret = i2c_ssbi_poll_for_device_ready();
142 if (ret) {
143 dprintf (CRITICAL, "Error: device not ready\n");
Channagoud Kadabie1ecef52012-02-04 15:54:34 +0530144 goto end;
Kinson Chikea646242011-09-01 13:53:16 -0700145 }
146
147 writel(SSBI_CMD_WRITE(addr, *buf++), MSM_SSBI_BASE + SSBI2_CMD);
148
149 while (readl(MSM_SSBI_BASE + SSBI2_STATUS) & SSBI_STATUS_MCHN_BUSY) {
150 if (--timeout == 0) {
Channagoud Kadabie1ecef52012-02-04 15:54:34 +0530151 dprintf(INFO, "In Device ready function:Timeout, status %x\n", readl(MSM_SSBI_BASE + SSBI2_STATUS));
152 ret = 1;
153 goto end;
Kinson Chikea646242011-09-01 13:53:16 -0700154 }
155 }
156 len--;
157 }
Channagoud Kadabie1ecef52012-02-04 15:54:34 +0530158end:
Channagoud Kadabie18a52d2012-10-04 15:18:55 +0530159#if TARGET_USES_RSPIN_LOCK
Channagoud Kadabie1ecef52012-02-04 15:54:34 +0530160 remote_spin_unlock(rlock);
161#endif
Channagoud Kadabie18a52d2012-10-04 15:18:55 +0530162 return ret;
Kinson Chikea646242011-09-01 13:53:16 -0700163}
164
165int pa1_ssbi2_read_bytes(unsigned char *buffer, unsigned short length,
166 unsigned short slave_addr)
167{
168 unsigned val = 0x0;
169 unsigned temp = 0x0000;
170 unsigned char *buf = buffer;
171 unsigned short len = length;
172 unsigned short addr = slave_addr;
173 unsigned long timeout = SSBI_TIMEOUT_US;
174
175 while(len)
176 {
177 val |= ((addr << PA1_SSBI2_REG_ADDR_SHIFT) |
178 (PA1_SSBI2_CMD_READ << PA1_SSBI2_CMD_RDWRN_SHIFT));
179 writel(val, PA1_SSBI2_CMD);
180 while(!((temp = readl(PA1_SSBI2_RD_STATUS)) & (1 << PA1_SSBI2_TRANS_DONE_SHIFT))) {
181 if (--timeout == 0) {
182 dprintf(INFO, "In Device ready function:Timeout\n");
183 return 1;
184 }
185 }
186 len--;
187 *buf++ = (temp & (PA1_SSBI2_REG_DATA_MASK << PA1_SSBI2_REG_DATA_SHIFT));
188 }
189 return 0;
190}
191
192int pa1_ssbi2_write_bytes(unsigned char *buffer, unsigned short length,
193 unsigned short slave_addr)
194{
195 unsigned val;
196 unsigned char *buf = buffer;
197 unsigned short len = length;
198 unsigned short addr = slave_addr;
199 unsigned temp = 0x00;
200 unsigned char written_data1 = 0x00;
201 unsigned long timeout = SSBI_TIMEOUT_US;
202 //unsigned char written_data2 = 0x00;
203
204 while(len)
205 {
206 temp = 0x00;
207 written_data1 = 0x00;
208 val = (addr << PA1_SSBI2_REG_ADDR_SHIFT) |
209 (PA1_SSBI2_CMD_WRITE << PA1_SSBI2_CMD_RDWRN_SHIFT) |
210 (*buf & 0xFF);
211 writel(val, PA1_SSBI2_CMD);
212 while(!((temp = readl(PA1_SSBI2_RD_STATUS)) & (1 << PA1_SSBI2_TRANS_DONE_SHIFT))) {
213 if (--timeout == 0) {
214 dprintf(INFO, "In Device write function:Timeout\n");
215 return 1;
216 }
217 }
218 len--;
219 buf++;
220 }
221 return 0;
222}
223
224int pa2_ssbi2_read_bytes(unsigned char *buffer, unsigned short length,
225 unsigned short slave_addr)
226{
227 unsigned val = 0x0;
228 unsigned temp = 0x0000;
229 unsigned char *buf = buffer;
230 unsigned short len = length;
231 unsigned short addr = slave_addr;
232 unsigned long timeout = SSBI_TIMEOUT_US;
233
234 while(len)
235 {
236 val |= ((addr << PA2_SSBI2_REG_ADDR_SHIFT) |
237 (PA2_SSBI2_CMD_READ << PA2_SSBI2_CMD_RDWRN_SHIFT));
238 writel(val, PA2_SSBI2_CMD);
239 while(!((temp = readl(PA2_SSBI2_RD_STATUS)) & (1 << PA2_SSBI2_TRANS_DONE_SHIFT))) {
240 if (--timeout == 0) {
241 dprintf(INFO, "In Device ready function:Timeout\n");
242 return 1;
243 }
244 }
245 len--;
246 *buf++ = (temp & (PA2_SSBI2_REG_DATA_MASK << PA2_SSBI2_REG_DATA_SHIFT));
247 }
248 return 0;
249}
250
251int pa2_ssbi2_write_bytes(unsigned char *buffer, unsigned short length,
252 unsigned short slave_addr)
253{
254 unsigned val;
255 unsigned char *buf = buffer;
256 unsigned short len = length;
257 unsigned short addr = slave_addr;
258 unsigned temp = 0x00;
259 unsigned char written_data1 = 0x00;
260 unsigned long timeout = SSBI_TIMEOUT_US;
261
262 while(len)
263 {
264 temp = 0x00;
265 written_data1 = 0x00;
266 val = (addr << PA2_SSBI2_REG_ADDR_SHIFT) |
267 (PA2_SSBI2_CMD_WRITE << PA2_SSBI2_CMD_RDWRN_SHIFT) |
268 (*buf & 0xFF);
269 writel(val, PA2_SSBI2_CMD);
270 while(!((temp = readl(PA2_SSBI2_RD_STATUS)) & (1 << PA2_SSBI2_TRANS_DONE_SHIFT))) {
271 if (--timeout == 0) {
272 dprintf(INFO, "In Device write function:Timeout\n");
273 return 1;
274 }
275 }
276 len--;
277 buf++;
278 }
279 return 0;
280}