blob: 6a2205e130981e376b07e8a7870ff34e86a27f8d [file] [log] [blame]
Mayank Grover20fdd882016-10-25 16:53:30 +05301/* Copyright (c) 2012,2016 The Linux Foundation. All rights reserved.
Deepa Dinamani0bf2f442012-10-19 11:41:06 -07002 *
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 Dinamani62df2c72012-12-19 17:17:58 -080033#include <arch/ops.h>
Deepa Dinamani0bf2f442012-10-19 11:41:06 -070034#include <platform.h>
Deepa Dinamani9d470af2012-06-29 18:27:17 -070035#include <platform/interrupts.h>
36#include <platform/iomap.h>
37#include <platform/irqs.h>
Deepa Dinamanie5ccd6c2012-08-16 11:41:06 -070038#include <pow2.h>
Deepa Dinamani9d470af2012-06-29 18:27:17 -070039
40#define HLOS_EE_INDEX 0
41
Deepa Dinamani9d470af2012-06-29 18:27:17 -070042/* Resets pipe registers and state machines */
Deepa Dinamani87feab82012-10-04 14:28:05 -070043void bam_pipe_reset(struct bam_instance *bam,
44 uint8_t pipe_num)
Deepa Dinamani9d470af2012-06-29 18:27:17 -070045{
46 /* Start sw reset of the pipe to be allocated */
47 writel(1, BAM_P_RSTn(bam->pipe[pipe_num].pipe_num, bam->base));
48
49 /* No delay required */
50
51 /* Stop sw reset of the pipe to be allocated */
52 writel(0, BAM_P_RSTn(bam->pipe[pipe_num].pipe_num, bam->base));
53}
54
55static enum handler_return bam_interrupt_handler(void* arg)
56{
57 return 0;
58}
59
60/* A blocking function that waits till an interrupt is signalled.
61 * bam : BAM instance for the descriptors to be queued.
62 * pipe_num : pipe number for the descriptors to be queued.
63 * interrupt: interrupt to wait for.
64 */
65int bam_wait_for_interrupt(struct bam_instance *bam,
66 uint8_t pipe_num,
67 enum p_int_type interrupt)
68{
69 uint32_t val;
70
71 while (1)
72 {
73 /* Wait for a interrupt on the right pipe */
74 do{
75 /* Determine the pipe causing the interrupt */
Deepa Dinamanie9ded132012-11-27 15:03:38 -080076 val = readl(BAM_IRQ_SRCS(bam->base, bam->ee));
Deepa Dinamani9d470af2012-06-29 18:27:17 -070077 /* Flush out the right most global interrupt bit */
78 } while (!((val & 0x7FFF) & (1 << bam->pipe[pipe_num].pipe_num)));
79
Deepa Dinamani9d470af2012-06-29 18:27:17 -070080 /* Check the interrupt type */
81 /* Read interrupt status register */
82 val = readl(BAM_P_IRQ_STTSn(bam->pipe[pipe_num].pipe_num, bam->base));
83
84 /* Check for error */
85 if (val & P_ERR_EN_MASK)
86 goto bam_wait_int_error;
87
88 if (val & interrupt)
89 {
90 /* Correct interrupt was fired. */
91 /* Clear the other interrupts */
92 val = P_OUT_OF_DESC_EN_MASK | P_PRCSD_DESC_EN_MASK | P_TRNSFR_END_EN_MASK;
93 writel (val, BAM_P_IRQ_CLRn(bam->pipe[pipe_num].pipe_num, bam->base));
94 return BAM_RESULT_SUCCESS;
95 }
Deepa Dinamani9d470af2012-06-29 18:27:17 -070096 }
97
98bam_wait_int_error:
99
Sundarajan Srinivasan802a9ec2013-07-11 16:02:57 -0700100 dprintf(CRITICAL, "Unexpected interrupt : val %u\n", val);
Deepa Dinamani9d470af2012-06-29 18:27:17 -0700101 return BAM_RESULT_FAILURE;
102}
103
104/* Enable BAM and pipe level interrupts */
105void bam_enable_interrupts(struct bam_instance *bam, uint8_t pipe_num)
106{
107
108 uint32_t int_mask = P_ERR_EN_MASK | P_OUT_OF_DESC_EN_MASK |
Sundarajan Srinivasan802a9ec2013-07-11 16:02:57 -0700109 P_PRCSD_DESC_EN_MASK;
Deepa Dinamani9d470af2012-06-29 18:27:17 -0700110 uint32_t val;
111
Deepa Dinamani5f68e842013-05-14 16:46:08 -0700112 /* Leave BAM error interrupts disabled. */
Deepa Dinamani9d470af2012-06-29 18:27:17 -0700113 /* Enable the interrupts for the pipe by enabling the relevant bits
114 * in the BAM_PIPE_INTERRUPT_ENABLE register.
115 */
116 writel(int_mask,
117 BAM_P_IRQ_ENn(bam->pipe[pipe_num].pipe_num, bam->base));
118
119 /* Enable pipe interrups */
120 /* Do read-modify-write */
Deepa Dinamanie9ded132012-11-27 15:03:38 -0800121 val = readl(BAM_IRQ_SRCS_MSK(bam->base, bam->ee));
Deepa Dinamani9d470af2012-06-29 18:27:17 -0700122 writel((1 << bam->pipe[pipe_num].pipe_num) | val,
Deepa Dinamanie9ded132012-11-27 15:03:38 -0800123 BAM_IRQ_SRCS_MSK(bam->base, bam->ee));
Deepa Dinamani9d470af2012-06-29 18:27:17 -0700124
125 /* Unmask the QGIC interrupts only in the case of
126 * interrupt based transfer.
127 * Use polling othwerwise.
128 */
129 if (bam->pipe[pipe_num].int_mode)
130 {
131 /* Register interrupt handler */
132 register_int_handler(bam->pipe[pipe_num].spi_num, bam_interrupt_handler, 0);
133
134 /* Unmask the interrupt */
135 unmask_interrupt(bam->pipe[pipe_num].spi_num);
136 }
137}
138
139/* Reset and initialize the bam module */
140void bam_init(struct bam_instance *bam)
141{
Channagoud Kadabi6d3efd12015-08-19 18:11:44 -0700142 /* bam is initialized by TZ, so nothing needs to be done here */
Deepa Dinamani9d470af2012-06-29 18:27:17 -0700143}
144
145/* Funtion to setup a simple fifo structure.
146 * Note: Addr should be 8 byte aligned.
147 * bam : BAM instance for the descriptors to be queued.
148 * pipe_num : pipe number for the descriptors to be queued.
149 */
150int bam_pipe_fifo_init(struct bam_instance *bam,
151 uint8_t pipe_num)
152{
Deepa Dinamani9d470af2012-06-29 18:27:17 -0700153 if (bam->pipe[pipe_num].fifo.size > 0x7FFF)
154 {
155 dprintf(CRITICAL,
156 "Size exceeds max size for a descriptor(0x7FFF)\n");
157 return BAM_RESULT_FAILURE;
158 }
159
160 /* Check if fifo start is 8-byte alligned */
Deepa Dinamani0bf2f442012-10-19 11:41:06 -0700161 ASSERT(!((uint32_t)PA((addr_t)bam->pipe[pipe_num].fifo.head & 0x7)));
Deepa Dinamani9d470af2012-06-29 18:27:17 -0700162
Deepa Dinamanie5ccd6c2012-08-16 11:41:06 -0700163 /* Check if fifo size is a power of 2.
164 * The circular fifo logic in lk expects this.
165 */
166 ASSERT(ispow2(bam->pipe[pipe_num].fifo.size));
167
Deepa Dinamani9d470af2012-06-29 18:27:17 -0700168 bam->pipe[pipe_num].fifo.current = bam->pipe[pipe_num].fifo.head;
169
170 /* Set the descriptor buffer size. Must be a multiple of 8 */
171 writel(bam->pipe[pipe_num].fifo.size * BAM_DESC_SIZE,
172 BAM_P_FIFO_SIZESn(bam->pipe[pipe_num].pipe_num, bam->base));
173
174 /* Write descriptors FIFO base addr must be 8-byte aligned */
Deepa Dinamani0bf2f442012-10-19 11:41:06 -0700175 /* Needs a physical address conversion as we are setting up
176 * the base of the FIFO for the BAM state machine.
177 */
178 writel((uint32_t)PA((addr_t)bam->pipe[pipe_num].fifo.head),
Deepa Dinamani9d470af2012-06-29 18:27:17 -0700179 BAM_P_DESC_FIFO_ADDRn(bam->pipe[pipe_num].pipe_num, bam->base));
180
181 /* Initialize FIFO offset for the first read */
182 bam->pipe[pipe_num].fifo.offset = BAM_DESC_SIZE;
183
Deepa Dinamania0407ea2013-07-09 12:51:45 -0700184 writel(P_ENABLE | readl(BAM_P_CTRLn(bam->pipe[pipe_num].pipe_num, bam->base)),
185 BAM_P_CTRLn(bam->pipe[pipe_num].pipe_num, bam->base));
186
Deepa Dinamani9d470af2012-06-29 18:27:17 -0700187 /* Everything is set.
188 * Flag pipe init done.
189 */
190 bam->pipe[pipe_num].initialized = 1;
191
192 return BAM_RESULT_SUCCESS;
193}
194
195void bam_sys_pipe_init(struct bam_instance *bam,
196 uint8_t pipe_num)
197{
Deepa Dinamani9d470af2012-06-29 18:27:17 -0700198 /* Reset the pipe to be allocated */
199 bam_pipe_reset(bam, pipe_num);
200
201 /* Enable minimal interrupts */
202 bam_enable_interrupts(bam, pipe_num);
203
204 /* Pipe event threshold register is not relevant in sys modes */
205
206 /* Enable pipe in system mode and set the direction */
Deepa Dinamania0407ea2013-07-09 12:51:45 -0700207 writel(P_SYS_MODE_MASK | bam->pipe[pipe_num].lock_grp << P_LOCK_GRP_SHIFT |
208 (bam->pipe[pipe_num].trans_type << P_DIRECTION_SHIFT),
209 BAM_P_CTRLn(bam->pipe[pipe_num].pipe_num, bam->base));
Deepa Dinamani9d470af2012-06-29 18:27:17 -0700210
Deepa Dinamani9d470af2012-06-29 18:27:17 -0700211 /* Mark the pipe FIFO as uninitialized. */
212 bam->pipe[pipe_num].initialized = 0;
213}
214
215/* Function to notify written descriptors to BAM.
216 * bam : BAM instance for the descriptors to be queued.
217 * pipe_num : pipe number for the descriptors to be queued.
218 * num_desc : number of the descriptors.
219 * fifo : Circular FIFO used for the descriptors.
220 */
221void bam_sys_gen_event(struct bam_instance *bam,
222 uint8_t pipe_num,
223 unsigned int num_desc)
224{
225 uint32_t val = 0;
226
227 if (num_desc >= bam->pipe[pipe_num].fifo.size) {
228 dprintf(CRITICAL,
229 "Max allowed desc is one less than the fifo length\n");
230 return;
231 }
232
Sundarajan Srinivasan024bda52014-02-27 16:48:48 -0800233 /* bits 0:15 of BAM_P_EVNT_REGn denotes the offset. We read the offset,
234 * and update the offset to notify BAM HW that new descriptors have been written
235 */
236 val = readl(BAM_P_EVNT_REGn(bam->pipe[pipe_num].pipe_num, bam->base));
237
Deepa Dinamani9d470af2012-06-29 18:27:17 -0700238 /* Update the fifo peer offset */
Sundarajan Srinivasan024bda52014-02-27 16:48:48 -0800239 val += (num_desc) * BAM_DESC_SIZE;
Deepa Dinamanie5ccd6c2012-08-16 11:41:06 -0700240 val &= (bam->pipe[pipe_num].fifo.size * BAM_DESC_SIZE - 1);
Deepa Dinamani9d470af2012-06-29 18:27:17 -0700241
242 writel(val, BAM_P_EVNT_REGn(bam->pipe[pipe_num].pipe_num, bam->base));
243}
244
245/* Function to read the updates for FIFO offsets.
246 * bam : BAM that uses the FIFO.
247 * pipe : BAM pipe that uses the FIFO.
Sundarajan Srinivasan024bda52014-02-27 16:48:48 -0800248 * return : void.
249 * Note : As per IPCAT This register denotes the pointer Offset of the first un-Acknowledged Descriptor.
250 * This register is only used by the Software. After receiving an interrupt, software reads this register
251 * in order to know what descriptors has been processed. Although being Writable, Software
252 * should never write to this register.
Deepa Dinamani9d470af2012-06-29 18:27:17 -0700253 */
Deepa Dinamanie5ccd6c2012-08-16 11:41:06 -0700254void bam_read_offset_update(struct bam_instance *bam, unsigned int pipe_num)
Deepa Dinamani9d470af2012-06-29 18:27:17 -0700255{
256 uint32_t offset;
257
258 offset = readl(BAM_P_SW_OFSTSn(bam->pipe[pipe_num].pipe_num, bam->base));
259 offset &= 0xFFFF;
260
Deepa Dinamani9c59ac62012-12-03 10:51:59 -0800261 dprintf(SPEW, "Offset value is %d \n", offset);
Deepa Dinamani9d470af2012-06-29 18:27:17 -0700262}
263
264/* Function to get the next desc address.
265 * Keeps track of circular properties of the FIFO
266 * and returns the appropriate address.
267 */
268static struct bam_desc* fifo_getnext(struct bam_desc_fifo *fifo,
269 struct bam_desc* desc)
270{
271 uint16_t offset;
272
273 offset = desc - fifo->head;
Deepa Dinamani9d470af2012-06-29 18:27:17 -0700274
275 if (offset == (fifo->size - 1))
276 return fifo->head;
277 else
278 return desc + 1;
279}
280
281/* Function to add BAM descriptors for a given fifo.
282 * bam : BAM instance to be used.
Mayank Grover20fdd882016-10-25 16:53:30 +0530283 * data_ptr : Physical memory address for data transfer.
Deepa Dinamani9d470af2012-06-29 18:27:17 -0700284 * data_len : Length of the data_ptr.
Deepa Dinamanie5ccd6c2012-08-16 11:41:06 -0700285 * flags : Flags to be set on the last desc added.
Deepa Dinamani9d470af2012-06-29 18:27:17 -0700286 *
Deepa Dinamanie5ccd6c2012-08-16 11:41:06 -0700287 * Note: This function also notifies the BAM about the added descriptors.
Deepa Dinamani9d470af2012-06-29 18:27:17 -0700288 */
289int bam_add_desc(struct bam_instance *bam,
290 unsigned int pipe_num,
291 unsigned char *data_ptr,
Deepa Dinamanie5ccd6c2012-08-16 11:41:06 -0700292 unsigned int data_len,
293 unsigned flags)
Deepa Dinamani9d470af2012-06-29 18:27:17 -0700294{
Deepa Dinamani9d470af2012-06-29 18:27:17 -0700295 int bam_ret = BAM_RESULT_SUCCESS;
296 unsigned int len = data_len;
Deepa Dinamanie5ccd6c2012-08-16 11:41:06 -0700297 unsigned int desc_len;
Deepa Dinamani9d470af2012-06-29 18:27:17 -0700298 unsigned int n = 0;
Deepa Dinamanie5ccd6c2012-08-16 11:41:06 -0700299 unsigned int desc_flags;
Deepa Dinamani9d470af2012-06-29 18:27:17 -0700300
Deepa Dinamani9c59ac62012-12-03 10:51:59 -0800301 dprintf(SPEW, "Data length for BAM transfer is %u\n", data_len);
Deepa Dinamani9d470af2012-06-29 18:27:17 -0700302
303 if (data_ptr == NULL || len == 0)
304 {
305 dprintf(CRITICAL, "Wrong params for BAM transfer \n");
306 bam_ret = BAM_RESULT_FAILURE;
307 goto bam_add_desc_error;
308 }
309
Deepa Dinamani9d470af2012-06-29 18:27:17 -0700310 /* Check if we have enough space in FIFO */
Deepa Dinamanie9ded132012-11-27 15:03:38 -0800311 if (len > (unsigned)bam->pipe[pipe_num].fifo.size * bam->max_desc_len)
Deepa Dinamani9d470af2012-06-29 18:27:17 -0700312 {
313 dprintf(CRITICAL, "Data transfer exceeds desc fifo length.\n");
314 bam_ret = BAM_RESULT_FAILURE;
315 goto bam_add_desc_error;
316 }
317
318 while (len)
319 {
Deepa Dinamanie5ccd6c2012-08-16 11:41:06 -0700320
Deepa Dinamani9d470af2012-06-29 18:27:17 -0700321 /* There are only 16 bits to write data length.
322 * If more bits are needed, create more
323 * descriptors.
324 */
Deepa Dinamanie9ded132012-11-27 15:03:38 -0800325 if (len > bam->max_desc_len)
Deepa Dinamani9d470af2012-06-29 18:27:17 -0700326 {
Deepa Dinamanie9ded132012-11-27 15:03:38 -0800327 desc_len = bam->max_desc_len;
328 len -= bam->max_desc_len;
Deepa Dinamanie5ccd6c2012-08-16 11:41:06 -0700329 desc_flags = 0;
Deepa Dinamani9d470af2012-06-29 18:27:17 -0700330 }
331 else
332 {
Deepa Dinamanie5ccd6c2012-08-16 11:41:06 -0700333 desc_len = len;
Deepa Dinamani9d470af2012-06-29 18:27:17 -0700334 len = 0;
Deepa Dinamanie5ccd6c2012-08-16 11:41:06 -0700335 /* Set correct flags on the last desc. */
336 desc_flags = flags;
Deepa Dinamani9d470af2012-06-29 18:27:17 -0700337 }
338
Deepa Dinamanie5ccd6c2012-08-16 11:41:06 -0700339 /* Write descriptor */
340 bam_add_one_desc(bam, pipe_num, data_ptr, desc_len, desc_flags);
Deepa Dinamani9d470af2012-06-29 18:27:17 -0700341
Deepa Dinamanie9ded132012-11-27 15:03:38 -0800342 data_ptr += bam->max_desc_len;
Deepa Dinamani9d470af2012-06-29 18:27:17 -0700343 n++;
Deepa Dinamani9d470af2012-06-29 18:27:17 -0700344 }
345
Deepa Dinamani9d470af2012-06-29 18:27:17 -0700346
347 /* Create a read/write event to notify the periperal of the added desc. */
348 bam_sys_gen_event(bam, pipe_num, n);
349
350bam_add_desc_error:
351
352 return bam_ret;
353}
354
Deepa Dinamanie5ccd6c2012-08-16 11:41:06 -0700355/* Function to add a BAM descriptor for a given fifo.
356 * bam : BAM instance to be used.
357 * data_ptr : Memory address for data transfer.
358 * data_len : Length of the data_ptr.
359 * flags : Flags to be set on the desc added.
360 *
361 * Note: This function does not notify the BAM about the added descriptor.
362 */
363int bam_add_one_desc(struct bam_instance *bam,
364 unsigned int pipe_num,
365 unsigned char* data_ptr,
366 uint32_t len,
367 uint8_t flags)
368{
369
370 struct bam_desc *desc = bam->pipe[pipe_num].fifo.current;
371 int bam_ret = BAM_RESULT_SUCCESS;
372
373 if (data_ptr == NULL || len == 0)
374 {
375 dprintf(CRITICAL, "Wrong params for BAM transfer \n");
376 bam_ret = BAM_RESULT_FAILURE;
377 goto bam_add_one_desc_error;
378 }
379
380 /* Check if the FIFO is allocated for the pipe */
381 if (!bam->pipe[pipe_num].initialized)
382 {
383 dprintf(CRITICAL, "Please allocate the FIFO for the BAM pipe %d\n",
384 bam->pipe[pipe_num].pipe_num);
385 bam_ret = BAM_RESULT_FAILURE;
386 goto bam_add_one_desc_error;
387 }
388
389 if ((flags & BAM_DESC_LOCK_FLAG) && (flags & BAM_DESC_UNLOCK_FLAG))
390 {
391 dprintf(CRITICAL, "Can't lock and unlock in the same desc\n");
392 bam_ret = BAM_RESULT_FAILURE;
393 goto bam_add_one_desc_error;
394 }
395
396 /* Setting EOT flag on a CMD desc is not valid */
397 if ((flags & BAM_DESC_EOT_FLAG) && (flags & BAM_DESC_CMD_FLAG))
398 {
399 dprintf(CRITICAL, "EOT flag set on the CMD desc\n");
400 bam_ret = BAM_RESULT_FAILURE;
401 goto bam_add_one_desc_error;
402 }
403
404 /* Check for the length of the desc. */
Deepa Dinamanie9ded132012-11-27 15:03:38 -0800405 if (len > bam->max_desc_len)
Deepa Dinamanie5ccd6c2012-08-16 11:41:06 -0700406 {
407 dprintf(CRITICAL, "len of the desc exceeds max length"
Deepa Dinamanie9ded132012-11-27 15:03:38 -0800408 " %d > %d\n", len, bam->max_desc_len);
Deepa Dinamanie5ccd6c2012-08-16 11:41:06 -0700409 bam_ret = BAM_RESULT_FAILURE;
410 goto bam_add_one_desc_error;
411 }
412
Deepa Dinamani62df2c72012-12-19 17:17:58 -0800413 desc->flags = flags;
414 desc->addr = (uint32_t)data_ptr;
415 desc->size = (uint16_t)len;
Deepa Dinamanie5ccd6c2012-08-16 11:41:06 -0700416 desc->reserved = 0;
417
Deepa Dinamani62df2c72012-12-19 17:17:58 -0800418 arch_clean_invalidate_cache_range((addr_t) desc, BAM_DESC_SIZE);
419
Deepa Dinamanie5ccd6c2012-08-16 11:41:06 -0700420 /* Update the FIFO to point to the head */
421 bam->pipe[pipe_num].fifo.current = fifo_getnext(&bam->pipe[pipe_num].fifo, desc);
422
423bam_add_one_desc_error:
424 return bam_ret;
425}
426
Deepa Dinamani9d470af2012-06-29 18:27:17 -0700427struct cmd_element* bam_add_cmd_element(struct cmd_element *ptr,
428 uint32_t reg_addr,
429 uint32_t value,
430 enum bam_ce_cmd_t cmd_type)
431{
432 /* Write cmd type.
433 * Also, write the register address.
434 */
Deepa Dinamanie5ccd6c2012-08-16 11:41:06 -0700435 ptr->addr_n_cmd = (reg_addr & ~(0xFF000000)) | (cmd_type << 24);
Deepa Dinamani9d470af2012-06-29 18:27:17 -0700436
437 /* Do not mask any of the addr bits by default */
438 ptr->reg_mask = 0xFFFFFFFF;
439
440 /* Write the value to be written */
441 ptr->reg_data = value;
442
443 /* Return the address to add the next element to */
444 return ptr + 1;
445}