L4Re Operating System Framework
Interface and Usage Documentation
Loading...
Searching...
No Matches
hw_register_block
1// vi:set ft=cpp: -*- Mode: C++ -*-
2/*
3 * Copyright (C) 2014-2021, 2023-2024 Kernkonzept GmbH.
4 * Author(s): Alexander Warg <alexander.warg@kernkonzept.com>
5 *
6 * License: see LICENSE.spdx (in this directory or the directories above)
7 */
8#pragma once
9
10#include <l4/sys/types.h>
11#include <l4/cxx/type_traits>
12
13namespace L4drivers {
14
15
62
63
71template< unsigned MAX_BITS = 32 >
73
74template<>
75struct Register_block_base<8>
76{
77 virtual l4_uint8_t do_read_8(l4_addr_t reg) const = 0;
78 virtual void do_write_8(l4_uint8_t value, l4_addr_t reg) = 0;
79 virtual ~Register_block_base() = 0;
80};
81
83
84template<>
85struct Register_block_base<16> : Register_block_base<8>
86{
87 virtual l4_uint16_t do_read_16(l4_addr_t reg) const = 0;
88 virtual void do_write_16(l4_uint16_t value, l4_addr_t reg) = 0;
89};
90
91template<>
93{
94 virtual l4_uint32_t do_read_32(l4_addr_t reg) const = 0;
95 virtual void do_write_32(l4_uint32_t value, l4_addr_t reg) = 0;
96};
97
98template<>
100{
101 virtual l4_uint64_t do_read_64(l4_addr_t reg) const = 0;
102 virtual void do_write_64(l4_uint64_t value, l4_addr_t reg) = 0;
103};
104#undef REGBLK_READ_TEMPLATE
105#undef REGBLK_WRITE_TEMPLATE
106
107template<typename CHILD>
108struct Register_block_modify_mixin
109{
110 template< typename T >
111 T modify(T clear_bits, T set_bits, l4_addr_t reg) const
112 {
113 CHILD const *c = static_cast<CHILD const *>(this);
114 T r = (c->template read<T>(reg) & ~clear_bits) | set_bits;
115 c->template write<T>(r, reg);
116 return r;
117 }
118
119 template< typename T >
120 T set(T set_bits, l4_addr_t reg) const
121 { return this->template modify<T>(T(0), set_bits, reg); }
122
123 template< typename T >
124 T clear(T clear_bits, l4_addr_t reg) const
125 { return this->template modify<T>(clear_bits, T(0), reg); }
126};
127
128
129#define REGBLK_READ_TEMPLATE(sz) \
130 template< typename T > \
131 typename cxx::enable_if<sizeof(T) == (sz / 8), T>::type read(l4_addr_t reg) const \
132 { \
133 union X { T t; l4_uint##sz##_t v; } m; \
134 m.v = _b->do_read_##sz (reg); \
135 return m.t; \
136 }
137
138#define REGBLK_WRITE_TEMPLATE(sz) \
139 template< typename T > \
140 void write(T value, l4_addr_t reg, typename cxx::enable_if<sizeof(T) == (sz / 8), T>::type = T()) const \
141 { \
142 union X { T t; l4_uint##sz##_t v; } m; \
143 m.t = value; \
144 _b->do_write_##sz(m.v, reg); \
145 }
146
155template< typename BLOCK >
156class Register_block_tmpl
157: public Register_block_modify_mixin<Register_block_tmpl<BLOCK> >
158{
159private:
160 BLOCK *_b;
161
162public:
163 Register_block_tmpl(BLOCK *blk) : _b(blk) {}
164 Register_block_tmpl() = default;
165
166 operator BLOCK * () const { return _b; }
167
168 REGBLK_READ_TEMPLATE(8)
169 REGBLK_WRITE_TEMPLATE(8)
170 REGBLK_READ_TEMPLATE(16)
171 REGBLK_WRITE_TEMPLATE(16)
172 REGBLK_READ_TEMPLATE(32)
173 REGBLK_WRITE_TEMPLATE(32)
174 REGBLK_READ_TEMPLATE(64)
175 REGBLK_WRITE_TEMPLATE(64)
176};
177
178
179#undef REGBLK_READ_TEMPLATE
180#undef REGBLK_WRITE_TEMPLATE
181
182namespace __Type_helper {
183 template<unsigned> struct Unsigned;
184 template<> struct Unsigned<8> { typedef l4_uint8_t type; };
185 template<> struct Unsigned<16> { typedef l4_uint16_t type; };
186 template<> struct Unsigned<32> { typedef l4_uint32_t type; };
187 template<> struct Unsigned<64> { typedef l4_uint64_t type; };
188};
189
190
200template< unsigned BITS, typename BLOCK >
201class Ro_register_tmpl
202{
203protected:
204 BLOCK _b;
205 unsigned _o;
206
207public:
208 typedef typename __Type_helper::Unsigned<BITS>::type value_type;
209
210 Ro_register_tmpl(BLOCK const &blk, unsigned offset) : _b(blk), _o(offset) {}
211 Ro_register_tmpl() = default;
212
217 operator value_type () const
218 { return _b.template read<value_type>(_o); }
219
224 value_type read() const
225 { return _b.template read<value_type>(_o); }
226};
227
228
236template< unsigned BITS, typename BLOCK >
237class Register_tmpl : public Ro_register_tmpl<BITS, BLOCK>
238{
239public:
240 typedef typename Ro_register_tmpl<BITS, BLOCK>::value_type value_type;
241
242 Register_tmpl(BLOCK const &blk, unsigned offset)
243 : Ro_register_tmpl<BITS, BLOCK>(blk, offset)
244 {}
245
246 Register_tmpl() = default;
247
252 Register_tmpl &operator = (value_type val)
253 { this->_b.template write<value_type>(val, this->_o); return *this; }
254
259 void write(value_type val)
260 { this->_b.template write<value_type>(val, this->_o); }
261
274 value_type set(value_type set_bits)
275 { return this->_b.template set<value_type>(set_bits, this->_o); }
276
290 value_type clear(value_type clear_bits)
291 { return this->_b.template clear<value_type>(clear_bits, this->_o); }
292
308 value_type modify(value_type clear_bits, value_type set_bits)
309 { return this->_b.template modify<value_type>(clear_bits, set_bits, this->_o); }
310};
311
312
324template<
325 unsigned MAX_BITS,
326 typename BLOCK = Register_block_tmpl<
327 Register_block_base<MAX_BITS>
328 >
329>
330class Register_block
331{
332private:
333 template< unsigned B, typename BLK > friend class Register_block;
334 template< unsigned B, typename BLK > friend class Ro_register_block;
335 typedef BLOCK Block;
336 Block _b;
337
338public:
339 Register_block() = default;
340 Register_block(Block const &blk) : _b(blk) {}
341 Register_block &operator = (Block const &blk)
342 { _b = blk; return *this; }
343
344 template< unsigned BITS >
345 Register_block(Register_block<BITS> blk) : _b(blk._b) {}
346
347 typedef Register_tmpl<MAX_BITS, Block> Register;
348 typedef Ro_register_tmpl<MAX_BITS, Block> Ro_register;
349
356 template< unsigned BITS >
357 Ro_register_tmpl<BITS, Block> r(unsigned offset) const
358 { return Ro_register_tmpl<BITS, Block>(this->_b, offset); }
359
365 Ro_register operator [] (unsigned offset) const
366 { return this->r<MAX_BITS>(offset); }
367
368
375 template< unsigned BITS >
377 { return Register_tmpl<BITS, Block>(this->_b, offset); }
378
385 Register operator [] (unsigned offset)
386 { return this->r<MAX_BITS>(offset); }
387};
388
398template<
399 unsigned MAX_BITS,
400 typename BLOCK = Register_block_tmpl<
401 Register_block_base<MAX_BITS> const
402 >
403>
404class Ro_register_block
405{
406private:
407 template< unsigned B, typename BLK > friend class Ro_register_block;
408 typedef BLOCK Block;
409 Block _b;
410
411public:
412 Ro_register_block() = default;
413 Ro_register_block(BLOCK const &blk) : _b(blk) {}
414
415 template< unsigned BITS >
416 Ro_register_block(Register_block<BITS> const &blk) : _b(blk._b) {}
417
418 typedef Ro_register_tmpl<MAX_BITS, Block> Ro_register;
419 typedef Ro_register Register;
420
426 Ro_register operator [] (unsigned offset) const
427 { return Ro_register(this->_b, offset); }
428
435 template< unsigned BITS >
436 Ro_register_tmpl<BITS, Block> r(unsigned offset) const
437 { return Ro_register_tmpl<BITS, Block>(this->_b, offset); }
438};
439
440
454template< typename BASE, unsigned MAX_BITS = 32 >
456
457#define REGBLK_IMPL_RW_TEMPLATE(sz, ...) \
458 l4_uint##sz##_t do_read_##sz(l4_addr_t reg) const override \
459 { return static_cast<BASE const *>(this)->template read<l4_uint##sz##_t>(reg); } \
460 \
461 void do_write_##sz(l4_uint##sz##_t value, l4_addr_t reg) override \
462 { static_cast<BASE*>(this)->template write<l4_uint##sz##_t>(value, reg); }
463
464
465template< typename BASE >
466struct Register_block_impl<BASE, 8> : public Register_block_base<8>
467{
468 REGBLK_IMPL_RW_TEMPLATE(8);
469};
470
471template< typename BASE >
472struct Register_block_impl<BASE, 16> : public Register_block_base<16>
473{
474 REGBLK_IMPL_RW_TEMPLATE(8);
475 REGBLK_IMPL_RW_TEMPLATE(16);
476};
477
478template< typename BASE >
479struct Register_block_impl<BASE, 32> : public Register_block_base<32>
480{
481 REGBLK_IMPL_RW_TEMPLATE(8);
482 REGBLK_IMPL_RW_TEMPLATE(16);
483 REGBLK_IMPL_RW_TEMPLATE(32);
484};
485
486template< typename BASE >
487struct Register_block_impl<BASE, 64> : public Register_block_base<64>
488{
489 REGBLK_IMPL_RW_TEMPLATE(8);
490 REGBLK_IMPL_RW_TEMPLATE(16);
491 REGBLK_IMPL_RW_TEMPLATE(32);
492 REGBLK_IMPL_RW_TEMPLATE(64);
493};
494
495#undef REGBLK_IMPL_RW_TEMPLATE
496
497}
Handles a reference to a register block of the given maximum access width.
Ro_register operator[](unsigned offset) const
Read only access to register at offset offset.
Register_tmpl< BITS, Block > r(unsigned offset)
Read/write access to register at offset offset.
Ro_register_tmpl< BITS, Block > r(unsigned offset) const
Read only access to register at offset offset.
Single hardware register inside a Register_block_base interface.
value_type clear(value_type clear_bits)
clears bits in clear_bits in the hardware register.
value_type modify(value_type clear_bits, value_type set_bits)
clears bits in clear_bits and sets bits in set_bits in the hardware register.
value_type set(value_type set_bits)
set bits in set_bits in the hardware register.
void write(value_type val)
write val into the hardware register.
Register_tmpl & operator=(value_type val)
write val into the hardware register.
Ro_register operator[](unsigned offset) const
Read only access to register at offset offset.
Ro_register_tmpl< BITS, Block > r(unsigned offset) const
Read only access to register at offset offset.
Single read only register inside a Register_block_base interface.
value_type read() const
read the value from the hardware register.
unsigned long l4_addr_t
Address type.
Definition l4int.h:34
unsigned char l4_uint8_t
Unsigned 8bit value.
Definition l4int.h:25
unsigned int l4_uint32_t
Unsigned 32bit value.
Definition l4int.h:29
unsigned short int l4_uint16_t
Unsigned 16bit value.
Definition l4int.h:27
unsigned long long l4_uint64_t
Unsigned 64bit value.
Definition l4int.h:31
Common L4 ABI Data Types.
Abstract register block interface.
Implementation helper for register blocks.