blob: 3ed2be95578e8360f05cc57c574f4db9d2bc96df [file] [log] [blame]
Deepa Dinamani0bf2f442012-10-19 11:41:06 -07001/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
2 *
Deepa Dinamani9d470af2012-06-29 18:27:17 -07003 * Redistribution and use in source and binary forms, with or without
4 * modification, are permitted provided that the following conditions are
5 * met:
Deepa Dinamani0bf2f442012-10-19 11:41:06 -07006 * * Redistributions of source code must retain the above copyright
7 * notice, this list of conditions and the following disclaimer.
8 * * Redistributions in binary form must reproduce the above
9 * copyright notice, this list of conditions and the following
10 * disclaimer in the documentation and/or other materials provided
11 * with the distribution.
12 * * Neither the name of The Linux Foundation nor the names of its
13 * contributors may be used to endorse or promote products derived
14 * from this software without specific prior written permission.
Deepa Dinamani9d470af2012-06-29 18:27:17 -070015 *
16 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
23 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
24 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
25 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
26 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29#include <bam.h>
30#include <reg.h>
31#include <debug.h>
32#include <stdlib.h>
Deepa Dinamani0bf2f442012-10-19 11:41:06 -070033#include <platform.h>
Deepa Dinamani9d470af2012-06-29 18:27:17 -070034#include <platform/interrupts.h>
35#include <platform/iomap.h>
36#include <platform/irqs.h>
Deepa Dinamanie5ccd6c2012-08-16 11:41:06 -070037#include <pow2.h>
Deepa Dinamani9d470af2012-06-29 18:27:17 -070038
39#define HLOS_EE_INDEX 0
40
41/* Reset BAM registers and pipes */
42static void bam_reset(struct bam_instance *bam)
43{
44 /* Initiate SW reset */
45 writel(BAM_SW_RST_BIT_MASK, BAM_CTRL_REG(bam->base));
46
47 /* No delay required */
48
49 /* Disable SW reset */
50 writel(~BAM_SW_RST_BIT_MASK, BAM_CTRL_REG(bam->base));
51}
52
53/* Resets pipe registers and state machines */
Deepa Dinamani87feab82012-10-04 14:28:05 -070054void bam_pipe_reset(struct bam_instance *bam,
55 uint8_t pipe_num)
Deepa Dinamani9d470af2012-06-29 18:27:17 -070056{
57 /* Start sw reset of the pipe to be allocated */
58 writel(1, BAM_P_RSTn(bam->pipe[pipe_num].pipe_num, bam->base));
59
60 /* No delay required */
61
62 /* Stop sw reset of the pipe to be allocated */
63 writel(0, BAM_P_RSTn(bam->pipe[pipe_num].pipe_num, bam->base));
64}
65
66static enum handler_return bam_interrupt_handler(void* arg)
67{
68 return 0;
69}
70
71/* A blocking function that waits till an interrupt is signalled.
72 * bam : BAM instance for the descriptors to be queued.
73 * pipe_num : pipe number for the descriptors to be queued.
74 * interrupt: interrupt to wait for.
75 */
76int bam_wait_for_interrupt(struct bam_instance *bam,
77 uint8_t pipe_num,
78 enum p_int_type interrupt)
79{
80 uint32_t val;
81
82 while (1)
83 {
84 /* Wait for a interrupt on the right pipe */
85 do{
86 /* Determine the pipe causing the interrupt */
87 val = readl(BAM_IRQ_SRCS(bam->base));
88 /* Flush out the right most global interrupt bit */
89 } while (!((val & 0x7FFF) & (1 << bam->pipe[pipe_num].pipe_num)));
90
91 /* Check the reason for this BAM interrupt */
92 if (readl(BAM_IRQ_STTS(bam->base)))
93 goto bam_wait_int_error;
94
95 /* Check the interrupt type */
96 /* Read interrupt status register */
97 val = readl(BAM_P_IRQ_STTSn(bam->pipe[pipe_num].pipe_num, bam->base));
98
99 /* Check for error */
100 if (val & P_ERR_EN_MASK)
101 goto bam_wait_int_error;
102
103 if (val & interrupt)
104 {
105 /* Correct interrupt was fired. */
106 /* Clear the other interrupts */
107 val = P_OUT_OF_DESC_EN_MASK | P_PRCSD_DESC_EN_MASK | P_TRNSFR_END_EN_MASK;
108 writel (val, BAM_P_IRQ_CLRn(bam->pipe[pipe_num].pipe_num, bam->base));
109 return BAM_RESULT_SUCCESS;
110 }
111 else if (val & P_TRNSFR_END_EN_MASK)
112 {
113 dprintf(CRITICAL,
114 "Trasfer end signalled before the last descc was processed\n");
115 goto bam_wait_int_error;
116 }
117 }
118
119bam_wait_int_error:
120
121 dprintf(CRITICAL, "Unexpected interrupt\n");
122 return BAM_RESULT_FAILURE;
123}
124
125/* Enable BAM and pipe level interrupts */
126void bam_enable_interrupts(struct bam_instance *bam, uint8_t pipe_num)
127{
128
129 uint32_t int_mask = P_ERR_EN_MASK | P_OUT_OF_DESC_EN_MASK |
130 P_PRCSD_DESC_EN_MASK | P_TRNSFR_END_EN_MASK;
131 uint32_t val;
132
133 /* Enable BAM error interrupts */
134 writel(BAM_ERROR_EN_MASK, BAM_IRQ_EN_REG(bam->base));
135
136 /* Enable the interrupts for the pipe by enabling the relevant bits
137 * in the BAM_PIPE_INTERRUPT_ENABLE register.
138 */
139 writel(int_mask,
140 BAM_P_IRQ_ENn(bam->pipe[pipe_num].pipe_num, bam->base));
141
142 /* Enable pipe interrups */
143 /* Do read-modify-write */
144 val = readl(BAM_IRQ_SRCS_MSK(bam->base));
145 writel((1 << bam->pipe[pipe_num].pipe_num) | val,
146 BAM_IRQ_SRCS_MSK(bam->base));
147
148 /* Unmask the QGIC interrupts only in the case of
149 * interrupt based transfer.
150 * Use polling othwerwise.
151 */
152 if (bam->pipe[pipe_num].int_mode)
153 {
154 /* Register interrupt handler */
155 register_int_handler(bam->pipe[pipe_num].spi_num, bam_interrupt_handler, 0);
156
157 /* Unmask the interrupt */
158 unmask_interrupt(bam->pipe[pipe_num].spi_num);
159 }
160}
161
162/* Reset and initialize the bam module */
163void bam_init(struct bam_instance *bam)
164{
165 uint32_t val = 0;
166
Deepa Dinamani87feab82012-10-04 14:28:05 -0700167// bam_reset(bam);
Deepa Dinamani9d470af2012-06-29 18:27:17 -0700168
169 /* Check for only one pipe's direction.
170 * The other is assumed to be the opposite system
171 * transaction.
172 */
173 if (bam->pipe[0].trans_type == SYS2BAM ||
174 bam->pipe[0].trans_type == BAM2SYS)
175 {
176 /* Program the threshold count */
177 writel(bam->threshold, BAM_DESC_CNT_TRSHLD_REG(bam->base));
178 }
179
180 /* Program config register for H/W bug fixes */
181 val = 0xffffffff & ~(1 << 11);
182 writel(val, BAM_CNFG_BITS(bam->base));
183
Deepa Dinamani9d470af2012-06-29 18:27:17 -0700184 /* Enable the BAM */
185 writel(BAM_ENABLE_BIT_MASK, BAM_CTRL_REG(bam->base));
186}
187
188/* Funtion to setup a simple fifo structure.
189 * Note: Addr should be 8 byte aligned.
190 * bam : BAM instance for the descriptors to be queued.
191 * pipe_num : pipe number for the descriptors to be queued.
192 */
193int bam_pipe_fifo_init(struct bam_instance *bam,
194 uint8_t pipe_num)
195{
Deepa Dinamani9d470af2012-06-29 18:27:17 -0700196 if (bam->pipe[pipe_num].fifo.size > 0x7FFF)
197 {
198 dprintf(CRITICAL,
199 "Size exceeds max size for a descriptor(0x7FFF)\n");
200 return BAM_RESULT_FAILURE;
201 }
202
203 /* Check if fifo start is 8-byte alligned */
Deepa Dinamani0bf2f442012-10-19 11:41:06 -0700204 ASSERT(!((uint32_t)PA((addr_t)bam->pipe[pipe_num].fifo.head & 0x7)));
Deepa Dinamani9d470af2012-06-29 18:27:17 -0700205
Deepa Dinamanie5ccd6c2012-08-16 11:41:06 -0700206 /* Check if fifo size is a power of 2.
207 * The circular fifo logic in lk expects this.
208 */
209 ASSERT(ispow2(bam->pipe[pipe_num].fifo.size));
210
Deepa Dinamani9d470af2012-06-29 18:27:17 -0700211 bam->pipe[pipe_num].fifo.current = bam->pipe[pipe_num].fifo.head;
212
213 /* Set the descriptor buffer size. Must be a multiple of 8 */
214 writel(bam->pipe[pipe_num].fifo.size * BAM_DESC_SIZE,
215 BAM_P_FIFO_SIZESn(bam->pipe[pipe_num].pipe_num, bam->base));
216
217 /* Write descriptors FIFO base addr must be 8-byte aligned */
Deepa Dinamani0bf2f442012-10-19 11:41:06 -0700218 /* Needs a physical address conversion as we are setting up
219 * the base of the FIFO for the BAM state machine.
220 */
221 writel((uint32_t)PA((addr_t)bam->pipe[pipe_num].fifo.head),
Deepa Dinamani9d470af2012-06-29 18:27:17 -0700222 BAM_P_DESC_FIFO_ADDRn(bam->pipe[pipe_num].pipe_num, bam->base));
223
224 /* Initialize FIFO offset for the first read */
225 bam->pipe[pipe_num].fifo.offset = BAM_DESC_SIZE;
226
227 /* Everything is set.
228 * Flag pipe init done.
229 */
230 bam->pipe[pipe_num].initialized = 1;
231
232 return BAM_RESULT_SUCCESS;
233}
234
235void bam_sys_pipe_init(struct bam_instance *bam,
236 uint8_t pipe_num)
237{
Deepa Dinamani9d470af2012-06-29 18:27:17 -0700238 /* Reset the pipe to be allocated */
239 bam_pipe_reset(bam, pipe_num);
240
241 /* Enable minimal interrupts */
242 bam_enable_interrupts(bam, pipe_num);
243
244 /* Pipe event threshold register is not relevant in sys modes */
245
246 /* Enable pipe in system mode and set the direction */
247 writel(P_SYS_MODE_MASK | P_ENABLE |
248 (bam->pipe[pipe_num].trans_type << P_DIRECTION_SHIFT),
249 BAM_P_CTRLn(bam->pipe[pipe_num].pipe_num, bam->base));
250
Deepa Dinamani9d470af2012-06-29 18:27:17 -0700251 /* Mark the pipe FIFO as uninitialized. */
252 bam->pipe[pipe_num].initialized = 0;
253}
254
255/* Function to notify written descriptors to BAM.
256 * bam : BAM instance for the descriptors to be queued.
257 * pipe_num : pipe number for the descriptors to be queued.
258 * num_desc : number of the descriptors.
259 * fifo : Circular FIFO used for the descriptors.
260 */
261void bam_sys_gen_event(struct bam_instance *bam,
262 uint8_t pipe_num,
263 unsigned int num_desc)
264{
265 uint32_t val = 0;
266
267 if (num_desc >= bam->pipe[pipe_num].fifo.size) {
268 dprintf(CRITICAL,
269 "Max allowed desc is one less than the fifo length\n");
270 return;
271 }
272
273 /* Update the fifo peer offset */
274 val = (num_desc - 1) * BAM_DESC_SIZE;
275 val += bam->pipe[pipe_num].fifo.offset;
Deepa Dinamanie5ccd6c2012-08-16 11:41:06 -0700276 val &= (bam->pipe[pipe_num].fifo.size * BAM_DESC_SIZE - 1);
Deepa Dinamani9d470af2012-06-29 18:27:17 -0700277
278 writel(val, BAM_P_EVNT_REGn(bam->pipe[pipe_num].pipe_num, bam->base));
279}
280
281/* Function to read the updates for FIFO offsets.
282 * bam : BAM that uses the FIFO.
283 * pipe : BAM pipe that uses the FIFO.
284 * return : FIFO offset where the next descriptor should be written.
285 * Note : S/W maintains the circular properties of the FIFO and updates
286 * the offsets accordingly.
287 */
Deepa Dinamanie5ccd6c2012-08-16 11:41:06 -0700288void bam_read_offset_update(struct bam_instance *bam, unsigned int pipe_num)
Deepa Dinamani9d470af2012-06-29 18:27:17 -0700289{
290 uint32_t offset;
291
292 offset = readl(BAM_P_SW_OFSTSn(bam->pipe[pipe_num].pipe_num, bam->base));
293 offset &= 0xFFFF;
294
295 dprintf(INFO, "Offset value is %d \n", offset);
296
Deepa Dinamanie5ccd6c2012-08-16 11:41:06 -0700297 /* Save the next offset to be written to. */
Deepa Dinamani9d470af2012-06-29 18:27:17 -0700298 bam->pipe[pipe_num].fifo.current = (struct bam_desc*)
299 ((uint32_t)bam->pipe[pipe_num].fifo.head + offset);
300
301 bam->pipe[pipe_num].fifo.offset = offset + BAM_DESC_SIZE ;
Deepa Dinamani9d470af2012-06-29 18:27:17 -0700302}
303
304/* Function to get the next desc address.
305 * Keeps track of circular properties of the FIFO
306 * and returns the appropriate address.
307 */
308static struct bam_desc* fifo_getnext(struct bam_desc_fifo *fifo,
309 struct bam_desc* desc)
310{
311 uint16_t offset;
312
313 offset = desc - fifo->head;
Deepa Dinamani9d470af2012-06-29 18:27:17 -0700314
315 if (offset == (fifo->size - 1))
316 return fifo->head;
317 else
318 return desc + 1;
319}
320
321/* Function to add BAM descriptors for a given fifo.
322 * bam : BAM instance to be used.
323 * data_ptr : Memory address for data transfer.
324 * data_len : Length of the data_ptr.
Deepa Dinamanie5ccd6c2012-08-16 11:41:06 -0700325 * flags : Flags to be set on the last desc added.
Deepa Dinamani9d470af2012-06-29 18:27:17 -0700326 *
Deepa Dinamanie5ccd6c2012-08-16 11:41:06 -0700327 * Note: This function also notifies the BAM about the added descriptors.
Deepa Dinamani9d470af2012-06-29 18:27:17 -0700328 */
329int bam_add_desc(struct bam_instance *bam,
330 unsigned int pipe_num,
331 unsigned char *data_ptr,
Deepa Dinamanie5ccd6c2012-08-16 11:41:06 -0700332 unsigned int data_len,
333 unsigned flags)
Deepa Dinamani9d470af2012-06-29 18:27:17 -0700334{
Deepa Dinamani9d470af2012-06-29 18:27:17 -0700335 int bam_ret = BAM_RESULT_SUCCESS;
336 unsigned int len = data_len;
Deepa Dinamanie5ccd6c2012-08-16 11:41:06 -0700337 unsigned int desc_len;
Deepa Dinamani9d470af2012-06-29 18:27:17 -0700338 unsigned int n = 0;
Deepa Dinamanie5ccd6c2012-08-16 11:41:06 -0700339 unsigned int desc_flags;
Deepa Dinamani9d470af2012-06-29 18:27:17 -0700340
341 dprintf(INFO, "Data length for BAM transfer is %u\n", data_len);
342
343 if (data_ptr == NULL || len == 0)
344 {
345 dprintf(CRITICAL, "Wrong params for BAM transfer \n");
346 bam_ret = BAM_RESULT_FAILURE;
347 goto bam_add_desc_error;
348 }
349
Deepa Dinamani9d470af2012-06-29 18:27:17 -0700350 /* Check if we have enough space in FIFO */
351 if (len > (unsigned)bam->pipe[pipe_num].fifo.size * BAM_MAX_DESC_DATA_LEN)
352 {
353 dprintf(CRITICAL, "Data transfer exceeds desc fifo length.\n");
354 bam_ret = BAM_RESULT_FAILURE;
355 goto bam_add_desc_error;
356 }
357
358 while (len)
359 {
Deepa Dinamanie5ccd6c2012-08-16 11:41:06 -0700360
Deepa Dinamani9d470af2012-06-29 18:27:17 -0700361 /* There are only 16 bits to write data length.
362 * If more bits are needed, create more
363 * descriptors.
364 */
365 if (len > BAM_MAX_DESC_DATA_LEN)
366 {
Deepa Dinamanie5ccd6c2012-08-16 11:41:06 -0700367 desc_len = BAM_MAX_DESC_DATA_LEN;
Deepa Dinamani9d470af2012-06-29 18:27:17 -0700368 len -= BAM_MAX_DESC_DATA_LEN;
Deepa Dinamanie5ccd6c2012-08-16 11:41:06 -0700369 desc_flags = 0;
Deepa Dinamani9d470af2012-06-29 18:27:17 -0700370 }
371 else
372 {
Deepa Dinamanie5ccd6c2012-08-16 11:41:06 -0700373 desc_len = len;
Deepa Dinamani9d470af2012-06-29 18:27:17 -0700374 len = 0;
Deepa Dinamanie5ccd6c2012-08-16 11:41:06 -0700375 /* Set correct flags on the last desc. */
376 desc_flags = flags;
Deepa Dinamani9d470af2012-06-29 18:27:17 -0700377 }
378
Deepa Dinamanie5ccd6c2012-08-16 11:41:06 -0700379 /* Write descriptor */
380 bam_add_one_desc(bam, pipe_num, data_ptr, desc_len, desc_flags);
Deepa Dinamani9d470af2012-06-29 18:27:17 -0700381
Deepa Dinamani9d470af2012-06-29 18:27:17 -0700382 data_ptr += BAM_MAX_DESC_DATA_LEN;
383 n++;
Deepa Dinamani9d470af2012-06-29 18:27:17 -0700384 }
385
Deepa Dinamani9d470af2012-06-29 18:27:17 -0700386
387 /* Create a read/write event to notify the periperal of the added desc. */
388 bam_sys_gen_event(bam, pipe_num, n);
389
390bam_add_desc_error:
391
392 return bam_ret;
393}
394
Deepa Dinamanie5ccd6c2012-08-16 11:41:06 -0700395/* Function to add a BAM descriptor for a given fifo.
396 * bam : BAM instance to be used.
397 * data_ptr : Memory address for data transfer.
398 * data_len : Length of the data_ptr.
399 * flags : Flags to be set on the desc added.
400 *
401 * Note: This function does not notify the BAM about the added descriptor.
402 */
403int bam_add_one_desc(struct bam_instance *bam,
404 unsigned int pipe_num,
405 unsigned char* data_ptr,
406 uint32_t len,
407 uint8_t flags)
408{
409
410 struct bam_desc *desc = bam->pipe[pipe_num].fifo.current;
411 int bam_ret = BAM_RESULT_SUCCESS;
412
413 if (data_ptr == NULL || len == 0)
414 {
415 dprintf(CRITICAL, "Wrong params for BAM transfer \n");
416 bam_ret = BAM_RESULT_FAILURE;
417 goto bam_add_one_desc_error;
418 }
419
420 /* Check if the FIFO is allocated for the pipe */
421 if (!bam->pipe[pipe_num].initialized)
422 {
423 dprintf(CRITICAL, "Please allocate the FIFO for the BAM pipe %d\n",
424 bam->pipe[pipe_num].pipe_num);
425 bam_ret = BAM_RESULT_FAILURE;
426 goto bam_add_one_desc_error;
427 }
428
429 if ((flags & BAM_DESC_LOCK_FLAG) && (flags & BAM_DESC_UNLOCK_FLAG))
430 {
431 dprintf(CRITICAL, "Can't lock and unlock in the same desc\n");
432 bam_ret = BAM_RESULT_FAILURE;
433 goto bam_add_one_desc_error;
434 }
435
436 /* Setting EOT flag on a CMD desc is not valid */
437 if ((flags & BAM_DESC_EOT_FLAG) && (flags & BAM_DESC_CMD_FLAG))
438 {
439 dprintf(CRITICAL, "EOT flag set on the CMD desc\n");
440 bam_ret = BAM_RESULT_FAILURE;
441 goto bam_add_one_desc_error;
442 }
443
444 /* Check for the length of the desc. */
445 if (len > BAM_MAX_DESC_DATA_LEN)
446 {
447 dprintf(CRITICAL, "len of the desc exceeds max length"
448 " %d > %d\n", len, BAM_MAX_DESC_DATA_LEN);
449 bam_ret = BAM_RESULT_FAILURE;
450 goto bam_add_one_desc_error;
451 }
452
453 desc->flags = flags;
454 desc->addr = (uint32_t)data_ptr;
455 desc->size = (uint16_t)len;
456 desc->reserved = 0;
457
458 /* Update the FIFO to point to the head */
459 bam->pipe[pipe_num].fifo.current = fifo_getnext(&bam->pipe[pipe_num].fifo, desc);
460
461bam_add_one_desc_error:
462 return bam_ret;
463}
464
Deepa Dinamani9d470af2012-06-29 18:27:17 -0700465struct cmd_element* bam_add_cmd_element(struct cmd_element *ptr,
466 uint32_t reg_addr,
467 uint32_t value,
468 enum bam_ce_cmd_t cmd_type)
469{
470 /* Write cmd type.
471 * Also, write the register address.
472 */
Deepa Dinamanie5ccd6c2012-08-16 11:41:06 -0700473 ptr->addr_n_cmd = (reg_addr & ~(0xFF000000)) | (cmd_type << 24);
Deepa Dinamani9d470af2012-06-29 18:27:17 -0700474
475 /* Do not mask any of the addr bits by default */
476 ptr->reg_mask = 0xFFFFFFFF;
477
478 /* Write the value to be written */
479 ptr->reg_data = value;
480
481 /* Return the address to add the next element to */
482 return ptr + 1;
483}