summaryrefslogtreecommitdiffstats
path: root/bsps/powerpc/gen5200/include/bsp/bestcomm.h
blob: 2c379d4bbe025412a2ccec9c28ccc682ef5dc782 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
/*
 * Copyright (c) 2010-2013 embedded brains GmbH.  All rights reserved.
 *
 *  embedded brains GmbH
 *  Dornierstr. 4
 *  82178 Puchheim
 *  Germany
 *  <rtems@embedded-brains.de>
 *
 * The license and distribution terms for this file may be
 * found in the file LICENSE in this distribution or at
 * http://www.rtems.org/license/LICENSE.
 */

#ifndef GEN5200_BESTCOMM_H
#define GEN5200_BESTCOMM_H

#include "bestcomm_ops.h"

#include <assert.h>

#include <rtems.h>

#include <bsp/mpc5200.h>
#include <bsp/bestcomm/bestcomm_api.h>
#include <bsp/bestcomm/bestcomm_glue.h>

#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */

/**
 * @defgroup BestComm BestComm Support
 *
 * @ingroup RTEMSBSPsPowerPCGen5200
 *
 * @brief BestComm support.
 *
 * @{
 */

typedef struct {
  uint32_t *tdt_begin;
  uint32_t *tdt_last;
  volatile uint32_t (*var_table)[32];
  uint32_t fdt_and_pragmas;
  uint32_t reserved_0;
  uint32_t reserved_1;
  uint32_t *context_begin;
  uint32_t reserved_2;
} bestcomm_task_entry;

#define BESTCOMM_TASK_ENTRY_TABLE ((volatile bestcomm_task_entry *) 0xf0008000)

#define BESTCOMM_IRQ_EVENT RTEMS_EVENT_13

typedef struct {
  int task_index;
  rtems_id event_task_id;
} bestcomm_irq;

void bestcomm_irq_create(bestcomm_irq *self, int task_index);

void bestcomm_irq_destroy(const bestcomm_irq *self);

static inline void bestcomm_irq_enable(const bestcomm_irq *self)
{
  bestcomm_glue_irq_enable(self->task_index);
}

static inline void bestcomm_irq_disable(const bestcomm_irq *self)
{
  bestcomm_glue_irq_disable(self->task_index);
}

static inline void bestcomm_irq_clear(const bestcomm_irq *self)
{
  SDMA_CLEAR_IEVENT(&mpc5200.sdma.IntPend, self->task_index);
}

static inline int bestcomm_irq_get_task_index(const bestcomm_irq *self)
{
  return self->task_index;
}

static inline rtems_id bestcomm_irq_get_event_task_id(const bestcomm_irq *self)
{
  return self->event_task_id;
}

static inline void bestcomm_irq_set_event_task_id(bestcomm_irq *self, rtems_id id)
{
  self->event_task_id = id;
}

static inline void bestcomm_irq_wakeup_event_task(const bestcomm_irq *self)
{
  rtems_status_code sc = rtems_event_send(self->event_task_id, BESTCOMM_IRQ_EVENT);
  assert(sc == RTEMS_SUCCESSFUL);
  (void) sc;
}

static inline void bestcomm_irq_wait(const bestcomm_irq *self)
{
  rtems_event_set events;
  rtems_status_code sc = rtems_event_receive(
    BESTCOMM_IRQ_EVENT,
    RTEMS_EVENT_ALL | RTEMS_WAIT,
    RTEMS_NO_TIMEOUT,
    &events
  );
  assert(sc == RTEMS_SUCCESSFUL);
  assert(events == BESTCOMM_IRQ_EVENT);
  (void) sc;
}

static inline bool bestcomm_irq_peek(const bestcomm_irq *self)
{
  rtems_event_set events;
  rtems_status_code sc = rtems_event_receive(0, 0, 0, &events);
  assert(sc == RTEMS_SUCCESSFUL);
  (void) sc;

  return (events & BESTCOMM_IRQ_EVENT) != 0;
}

typedef struct {
  volatile uint16_t *task_control_register;

  volatile uint32_t (*variable_table)[32];

  TaskId task_index;

  bestcomm_irq irq;

  uint32_t *tdt_begin;

  size_t tdt_opcode_count;
} bestcomm_task;

void bestcomm_task_create(bestcomm_task *self, TaskId task_index);

void bestcomm_task_create_and_load(
  bestcomm_task *self,
  TaskId task_index,
  const uint32_t *tdt_source_begin,
  size_t tdt_size
);

void bestcomm_task_destroy(bestcomm_task *self);

void bestcomm_task_load(bestcomm_task *self, const uint32_t *tdt_source_begin, size_t tdt_size);

static inline void bestcomm_task_set_priority(bestcomm_task *self, int priority)
{
  /* Allow higher priority initiator to block current initiator */
  mpc5200.sdma.ipr[self->task_index] = SDMA_IPR_PRIOR(priority);
}

static inline void bestcomm_task_irq_enable(const bestcomm_task *self)
{
  bestcomm_irq_enable(&self->irq);
}

static inline void bestcomm_task_irq_disable(const bestcomm_task *self)
{
  bestcomm_irq_disable(&self->irq);
}

static inline void bestcomm_task_irq_clear(const bestcomm_task *self)
{
  bestcomm_irq_clear(&self->irq);
}

static inline rtems_id bestcomm_task_get_event_task_id(const bestcomm_task *self)
{
  return bestcomm_irq_get_event_task_id(&self->irq);
}

static inline void bestcomm_task_set_event_task_id(bestcomm_task *self, rtems_id id)
{
  bestcomm_irq_set_event_task_id(&self->irq, id);
}

static inline void bestcomm_task_associate_with_current_task(bestcomm_task *self)
{
  bestcomm_task_set_event_task_id(self, rtems_task_self());
}

static inline void bestcomm_task_start(const bestcomm_task *self)
{
  *self->task_control_register = SDMA_TCR_EN | SDMA_TCR_HIGH_EN;
}

static inline void bestcomm_task_start_with_autostart(const bestcomm_task *self)
{
  *self->task_control_register = (uint16_t)
    (SDMA_TCR_EN | SDMA_TCR_HIGH_EN | SDMA_TCR_AUTO_START | SDMA_TCR_AS(self->task_index));
}

static inline void bestcomm_task_stop(const bestcomm_task *self)
{
  *self->task_control_register = 0;
}

static inline void bestcomm_task_wakeup_event_task(const bestcomm_task *self)
{
  bestcomm_irq_wakeup_event_task(&self->irq);
}

static inline void bestcomm_task_wait(const bestcomm_task *self)
{
  bestcomm_irq_wait(&self->irq);
}

static inline bool bestcomm_task_peek(const bestcomm_task *self)
{
  return bestcomm_irq_peek(&self->irq);
}

static inline bool bestcomm_task_is_running(const bestcomm_task *self)
{
  return (*self->task_control_register & SDMA_TCR_EN) != 0;
}

static inline uint32_t bestcomm_get_task_variable(const bestcomm_task *self, size_t index)
{
  assert(index < VAR_COUNT);
  return (*self->variable_table)[index];
}

static inline volatile uint32_t *bestcomm_task_get_address_of_variable(const bestcomm_task *self, size_t index)
{
  assert(index < VAR_COUNT);
  return &(*self->variable_table)[index];
}

static inline void bestcomm_task_set_variable(const bestcomm_task *self, size_t index, uint32_t value)
{
  assert(index < VAR_COUNT);
  (*self->variable_table)[index] = value;
}

static inline uint32_t bestcomm_task_get_increment_and_condition(const bestcomm_task *self, size_t index)
{
  assert(index < INC_COUNT);
  return (*self->variable_table)[INC(index)];
}

static inline void bestcomm_task_set_increment_and_condition_32(
  const bestcomm_task *self,
  size_t index,
  uint32_t inc_and_cond
)
{
  assert(index < INC_COUNT);
  (*self->variable_table)[INC(index)] = inc_and_cond;
}

static inline void bestcomm_task_set_increment_and_condition(
  const bestcomm_task *self,
  size_t index,
  int16_t inc,
  int cond
)
{
  bestcomm_task_set_increment_and_condition_32(self, index, INC_INIT(cond, inc));
}

static inline void bestcomm_task_set_increment(const bestcomm_task *self, size_t index, int16_t inc)
{
  bestcomm_task_set_increment_and_condition_32(self, index, INC_INIT(0, inc));
}

void bestcomm_task_clear_variables(const bestcomm_task *self);

static inline uint32_t bestcomm_task_get_opcode(const bestcomm_task *self, size_t index)
{
  assert(index < self->tdt_opcode_count);
  return self->tdt_begin[index];
}

static inline void bestcomm_task_set_opcode(bestcomm_task *self, size_t index, uint32_t opcode)
{
  assert(index < self->tdt_opcode_count);
  self->tdt_begin[index] = opcode;
}

static inline void bestcomm_task_set_initiator(const bestcomm_task *self, int initiator)
{
  rtems_interrupt_level level;
  rtems_interrupt_disable(level);
  *self->task_control_register = BSP_BFLD16SET(*self->task_control_register, initiator, 3, 7);
  rtems_interrupt_enable(level);
}

static inline volatile bestcomm_task_entry *bestcomm_task_get_task_entry(const bestcomm_task *self)
{
  return &BESTCOMM_TASK_ENTRY_TABLE[self->task_index];
}

static inline void bestcomm_task_set_pragma(const bestcomm_task *self, int bit_pos, bool enable)
{
  volatile bestcomm_task_entry *entry = bestcomm_task_get_task_entry(self);
  uint32_t mask = BSP_BIT32(bit_pos);
  uint32_t bit = enable ? mask : 0;
  entry->fdt_and_pragmas = (entry->fdt_and_pragmas & ~mask) | bit;
}

static inline void bestcomm_task_enable_precise_increment(const bestcomm_task *self, bool enable)
{
  bestcomm_task_set_pragma(self, SDMA_PRAGMA_BIT_PRECISE_INC, enable);
}

static inline void bestcomm_task_enable_error_reset(const bestcomm_task *self, bool enable)
{
  bestcomm_task_set_pragma(self, SDMA_PRAGMA_BIT_RST_ERROR_NO, !enable);
}

static inline void bestcomm_task_enable_pack_data(const bestcomm_task *self, bool enable)
{
  bestcomm_task_set_pragma(self, SDMA_PRAGMA_BIT_PACK, enable);
}

static inline void bestcomm_task_enable_integer_mode(const bestcomm_task *self, bool enable)
{
  bestcomm_task_set_pragma(self, SDMA_PRAGMA_BIT_INTEGER, enable);
}

static inline void bestcomm_task_enable_speculative_read(const bestcomm_task *self, bool enable)
{
  bestcomm_task_set_pragma(self, SDMA_PRAGMA_BIT_SPECREAD, enable);
}

static inline void bestcomm_task_enable_combined_write(const bestcomm_task *self, bool enable)
{
  bestcomm_task_set_pragma(self, SDMA_PRAGMA_BIT_CW, enable);
}

static inline void bestcomm_task_enable_read_buffer(const bestcomm_task *self, bool enable)
{
  bestcomm_task_set_pragma(self, SDMA_PRAGMA_BIT_RL, enable);
}

static inline volatile uint16_t *bestcomm_task_get_task_control_register(const bestcomm_task *self)
{
  return self->task_control_register;
}

static inline int bestcomm_task_get_task_index(const bestcomm_task *self)
{
  return self->task_index;
}

static inline void bestcomm_task_free_tdt(bestcomm_task *self)
{
  bestcomm_free(self->tdt_begin);
  self->tdt_begin = NULL;
}

static inline void bestcomm_task_clear_pragmas(const bestcomm_task *self)
{
  volatile bestcomm_task_entry *entry = bestcomm_task_get_task_entry(self);
  entry->fdt_and_pragmas &= ~0xffU;
}

/** @} */

#ifdef __cplusplus
}
#endif /* __cplusplus */

#endif /* GEN5200_BESTCOMM_H */