Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:23:52

0001 /* SPDX-License-Identifier: BSD-2-Clause */
0002 
0003 /*
0004  * Copyright (C) 2010, 2013 embedded brains GmbH & Co. KG
0005  *
0006  * Redistribution and use in source and binary forms, with or without
0007  * modification, are permitted provided that the following conditions
0008  * are met:
0009  * 1. Redistributions of source code must retain the above copyright
0010  *    notice, this list of conditions and the following disclaimer.
0011  * 2. Redistributions in binary form must reproduce the above copyright
0012  *    notice, this list of conditions and the following disclaimer in the
0013  *    documentation and/or other materials provided with the distribution.
0014  *
0015  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
0016  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
0017  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
0018  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
0019  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
0020  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
0021  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
0022  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
0023  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
0024  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
0025  * POSSIBILITY OF SUCH DAMAGE.
0026  */
0027 
0028 #ifndef GEN5200_BESTCOMM_H
0029 #define GEN5200_BESTCOMM_H
0030 
0031 #include "bestcomm_ops.h"
0032 
0033 #include <assert.h>
0034 
0035 #include <rtems.h>
0036 
0037 #include <bsp/mpc5200.h>
0038 #include <bsp/bestcomm/bestcomm_api.h>
0039 #include <bsp/bestcomm/bestcomm_glue.h>
0040 
0041 #ifdef __cplusplus
0042 extern "C" {
0043 #endif /* __cplusplus */
0044 
0045 /**
0046  * @defgroup BestComm BestComm Support
0047  *
0048  * @ingroup RTEMSBSPsPowerPCGen5200
0049  *
0050  * @brief BestComm support.
0051  *
0052  * @{
0053  */
0054 
0055 typedef struct {
0056   uint32_t *tdt_begin;
0057   uint32_t *tdt_last;
0058   volatile uint32_t (*var_table)[32];
0059   uint32_t fdt_and_pragmas;
0060   uint32_t reserved_0;
0061   uint32_t reserved_1;
0062   uint32_t *context_begin;
0063   uint32_t reserved_2;
0064 } bestcomm_task_entry;
0065 
0066 #define BESTCOMM_TASK_ENTRY_TABLE ((volatile bestcomm_task_entry *) 0xf0008000)
0067 
0068 #define BESTCOMM_IRQ_EVENT RTEMS_EVENT_13
0069 
0070 typedef struct {
0071   int task_index;
0072   rtems_id event_task_id;
0073 } bestcomm_irq;
0074 
0075 void bestcomm_irq_create(bestcomm_irq *self, int task_index);
0076 
0077 void bestcomm_irq_destroy(const bestcomm_irq *self);
0078 
0079 static inline void bestcomm_irq_enable(const bestcomm_irq *self)
0080 {
0081   bestcomm_glue_irq_enable(self->task_index);
0082 }
0083 
0084 static inline void bestcomm_irq_disable(const bestcomm_irq *self)
0085 {
0086   bestcomm_glue_irq_disable(self->task_index);
0087 }
0088 
0089 static inline void bestcomm_irq_clear(const bestcomm_irq *self)
0090 {
0091   SDMA_CLEAR_IEVENT(&mpc5200.sdma.IntPend, self->task_index);
0092 }
0093 
0094 static inline int bestcomm_irq_get_task_index(const bestcomm_irq *self)
0095 {
0096   return self->task_index;
0097 }
0098 
0099 static inline rtems_id bestcomm_irq_get_event_task_id(const bestcomm_irq *self)
0100 {
0101   return self->event_task_id;
0102 }
0103 
0104 static inline void bestcomm_irq_set_event_task_id(bestcomm_irq *self, rtems_id id)
0105 {
0106   self->event_task_id = id;
0107 }
0108 
0109 static inline void bestcomm_irq_wakeup_event_task(const bestcomm_irq *self)
0110 {
0111   rtems_status_code sc = rtems_event_send(self->event_task_id, BESTCOMM_IRQ_EVENT);
0112   assert(sc == RTEMS_SUCCESSFUL);
0113   (void) sc;
0114 }
0115 
0116 static inline void bestcomm_irq_wait(const bestcomm_irq *self)
0117 {
0118   rtems_event_set events;
0119   rtems_status_code sc = rtems_event_receive(
0120     BESTCOMM_IRQ_EVENT,
0121     RTEMS_EVENT_ALL | RTEMS_WAIT,
0122     RTEMS_NO_TIMEOUT,
0123     &events
0124   );
0125   assert(sc == RTEMS_SUCCESSFUL);
0126   assert(events == BESTCOMM_IRQ_EVENT);
0127   (void) sc;
0128 }
0129 
0130 static inline bool bestcomm_irq_peek(const bestcomm_irq *self)
0131 {
0132   rtems_event_set events;
0133   rtems_status_code sc = rtems_event_receive(0, 0, 0, &events);
0134   assert(sc == RTEMS_SUCCESSFUL);
0135   (void) sc;
0136 
0137   return (events & BESTCOMM_IRQ_EVENT) != 0;
0138 }
0139 
0140 typedef struct {
0141   volatile uint16_t *task_control_register;
0142 
0143   volatile uint32_t (*variable_table)[32];
0144 
0145   TaskId task_index;
0146 
0147   bestcomm_irq irq;
0148 
0149   uint32_t *tdt_begin;
0150 
0151   size_t tdt_opcode_count;
0152 } bestcomm_task;
0153 
0154 void bestcomm_task_create(bestcomm_task *self, TaskId task_index);
0155 
0156 void bestcomm_task_create_and_load(
0157   bestcomm_task *self,
0158   TaskId task_index,
0159   const uint32_t *tdt_source_begin,
0160   size_t tdt_size
0161 );
0162 
0163 void bestcomm_task_destroy(bestcomm_task *self);
0164 
0165 void bestcomm_task_load(bestcomm_task *self, const uint32_t *tdt_source_begin, size_t tdt_size);
0166 
0167 static inline void bestcomm_task_set_priority(bestcomm_task *self, int priority)
0168 {
0169   /* Allow higher priority initiator to block current initiator */
0170   mpc5200.sdma.ipr[self->task_index] = SDMA_IPR_PRIOR(priority);
0171 }
0172 
0173 static inline void bestcomm_task_irq_enable(const bestcomm_task *self)
0174 {
0175   bestcomm_irq_enable(&self->irq);
0176 }
0177 
0178 static inline void bestcomm_task_irq_disable(const bestcomm_task *self)
0179 {
0180   bestcomm_irq_disable(&self->irq);
0181 }
0182 
0183 static inline void bestcomm_task_irq_clear(const bestcomm_task *self)
0184 {
0185   bestcomm_irq_clear(&self->irq);
0186 }
0187 
0188 static inline rtems_id bestcomm_task_get_event_task_id(const bestcomm_task *self)
0189 {
0190   return bestcomm_irq_get_event_task_id(&self->irq);
0191 }
0192 
0193 static inline void bestcomm_task_set_event_task_id(bestcomm_task *self, rtems_id id)
0194 {
0195   bestcomm_irq_set_event_task_id(&self->irq, id);
0196 }
0197 
0198 static inline void bestcomm_task_associate_with_current_task(bestcomm_task *self)
0199 {
0200   bestcomm_task_set_event_task_id(self, rtems_task_self());
0201 }
0202 
0203 static inline void bestcomm_task_start(const bestcomm_task *self)
0204 {
0205   *self->task_control_register = SDMA_TCR_EN | SDMA_TCR_HIGH_EN;
0206 }
0207 
0208 static inline void bestcomm_task_start_with_autostart(const bestcomm_task *self)
0209 {
0210   *self->task_control_register = (uint16_t)
0211     (SDMA_TCR_EN | SDMA_TCR_HIGH_EN | SDMA_TCR_AUTO_START | SDMA_TCR_AS(self->task_index));
0212 }
0213 
0214 static inline void bestcomm_task_stop(const bestcomm_task *self)
0215 {
0216   *self->task_control_register = 0;
0217 }
0218 
0219 static inline void bestcomm_task_wakeup_event_task(const bestcomm_task *self)
0220 {
0221   bestcomm_irq_wakeup_event_task(&self->irq);
0222 }
0223 
0224 static inline void bestcomm_task_wait(const bestcomm_task *self)
0225 {
0226   bestcomm_irq_wait(&self->irq);
0227 }
0228 
0229 static inline bool bestcomm_task_peek(const bestcomm_task *self)
0230 {
0231   return bestcomm_irq_peek(&self->irq);
0232 }
0233 
0234 static inline bool bestcomm_task_is_running(const bestcomm_task *self)
0235 {
0236   return (*self->task_control_register & SDMA_TCR_EN) != 0;
0237 }
0238 
0239 static inline uint32_t bestcomm_get_task_variable(const bestcomm_task *self, size_t index)
0240 {
0241   assert(index < VAR_COUNT);
0242   return (*self->variable_table)[index];
0243 }
0244 
0245 static inline volatile uint32_t *bestcomm_task_get_address_of_variable(const bestcomm_task *self, size_t index)
0246 {
0247   assert(index < VAR_COUNT);
0248   return &(*self->variable_table)[index];
0249 }
0250 
0251 static inline void bestcomm_task_set_variable(const bestcomm_task *self, size_t index, uint32_t value)
0252 {
0253   assert(index < VAR_COUNT);
0254   (*self->variable_table)[index] = value;
0255 }
0256 
0257 static inline uint32_t bestcomm_task_get_increment_and_condition(const bestcomm_task *self, size_t index)
0258 {
0259   assert(index < INC_COUNT);
0260   return (*self->variable_table)[INC(index)];
0261 }
0262 
0263 static inline void bestcomm_task_set_increment_and_condition_32(
0264   const bestcomm_task *self,
0265   size_t index,
0266   uint32_t inc_and_cond
0267 )
0268 {
0269   assert(index < INC_COUNT);
0270   (*self->variable_table)[INC(index)] = inc_and_cond;
0271 }
0272 
0273 static inline void bestcomm_task_set_increment_and_condition(
0274   const bestcomm_task *self,
0275   size_t index,
0276   int16_t inc,
0277   int cond
0278 )
0279 {
0280   bestcomm_task_set_increment_and_condition_32(self, index, INC_INIT(cond, inc));
0281 }
0282 
0283 static inline void bestcomm_task_set_increment(const bestcomm_task *self, size_t index, int16_t inc)
0284 {
0285   bestcomm_task_set_increment_and_condition_32(self, index, INC_INIT(0, inc));
0286 }
0287 
0288 void bestcomm_task_clear_variables(const bestcomm_task *self);
0289 
0290 static inline uint32_t bestcomm_task_get_opcode(const bestcomm_task *self, size_t index)
0291 {
0292   assert(index < self->tdt_opcode_count);
0293   return self->tdt_begin[index];
0294 }
0295 
0296 static inline void bestcomm_task_set_opcode(bestcomm_task *self, size_t index, uint32_t opcode)
0297 {
0298   assert(index < self->tdt_opcode_count);
0299   self->tdt_begin[index] = opcode;
0300 }
0301 
0302 static inline void bestcomm_task_set_initiator(const bestcomm_task *self, int initiator)
0303 {
0304   rtems_interrupt_level level;
0305   rtems_interrupt_disable(level);
0306   *self->task_control_register = BSP_BFLD16SET(*self->task_control_register, initiator, 3, 7);
0307   rtems_interrupt_enable(level);
0308 }
0309 
0310 static inline volatile bestcomm_task_entry *bestcomm_task_get_task_entry(const bestcomm_task *self)
0311 {
0312   return &BESTCOMM_TASK_ENTRY_TABLE[self->task_index];
0313 }
0314 
0315 static inline void bestcomm_task_set_pragma(const bestcomm_task *self, int bit_pos, bool enable)
0316 {
0317   volatile bestcomm_task_entry *entry = bestcomm_task_get_task_entry(self);
0318   uint32_t mask = BSP_BIT32(bit_pos);
0319   uint32_t bit = enable ? mask : 0;
0320   entry->fdt_and_pragmas = (entry->fdt_and_pragmas & ~mask) | bit;
0321 }
0322 
0323 static inline void bestcomm_task_enable_precise_increment(const bestcomm_task *self, bool enable)
0324 {
0325   bestcomm_task_set_pragma(self, SDMA_PRAGMA_BIT_PRECISE_INC, enable);
0326 }
0327 
0328 static inline void bestcomm_task_enable_error_reset(const bestcomm_task *self, bool enable)
0329 {
0330   bestcomm_task_set_pragma(self, SDMA_PRAGMA_BIT_RST_ERROR_NO, !enable);
0331 }
0332 
0333 static inline void bestcomm_task_enable_pack_data(const bestcomm_task *self, bool enable)
0334 {
0335   bestcomm_task_set_pragma(self, SDMA_PRAGMA_BIT_PACK, enable);
0336 }
0337 
0338 static inline void bestcomm_task_enable_integer_mode(const bestcomm_task *self, bool enable)
0339 {
0340   bestcomm_task_set_pragma(self, SDMA_PRAGMA_BIT_INTEGER, enable);
0341 }
0342 
0343 static inline void bestcomm_task_enable_speculative_read(const bestcomm_task *self, bool enable)
0344 {
0345   bestcomm_task_set_pragma(self, SDMA_PRAGMA_BIT_SPECREAD, enable);
0346 }
0347 
0348 static inline void bestcomm_task_enable_combined_write(const bestcomm_task *self, bool enable)
0349 {
0350   bestcomm_task_set_pragma(self, SDMA_PRAGMA_BIT_CW, enable);
0351 }
0352 
0353 static inline void bestcomm_task_enable_read_buffer(const bestcomm_task *self, bool enable)
0354 {
0355   bestcomm_task_set_pragma(self, SDMA_PRAGMA_BIT_RL, enable);
0356 }
0357 
0358 static inline volatile uint16_t *bestcomm_task_get_task_control_register(const bestcomm_task *self)
0359 {
0360   return self->task_control_register;
0361 }
0362 
0363 static inline int bestcomm_task_get_task_index(const bestcomm_task *self)
0364 {
0365   return self->task_index;
0366 }
0367 
0368 static inline void bestcomm_task_free_tdt(bestcomm_task *self)
0369 {
0370   bestcomm_free(self->tdt_begin);
0371   self->tdt_begin = NULL;
0372 }
0373 
0374 static inline void bestcomm_task_clear_pragmas(const bestcomm_task *self)
0375 {
0376   volatile bestcomm_task_entry *entry = bestcomm_task_get_task_entry(self);
0377   entry->fdt_and_pragmas &= ~0xffU;
0378 }
0379 
0380 /** @} */
0381 
0382 #ifdef __cplusplus
0383 }
0384 #endif /* __cplusplus */
0385 
0386 #endif /* GEN5200_BESTCOMM_H */