1.1 --- a/pkg/devices/lib/tcu/include/tcu-common.h Thu Feb 01 22:40:19 2024 +0100 1.2 +++ b/pkg/devices/lib/tcu/include/tcu-common.h Thu Feb 01 22:41:30 2024 +0100 1.3 @@ -36,13 +36,14 @@ 1.4 { 1.5 protected: 1.6 uint8_t _channel; 1.7 + l4_cap_idx_t _irq; 1.8 Hw::Register_block<32> _regs; 1.9 1.10 uint32_t get_field(uint32_t reg, uint32_t mask, uint8_t shift); 1.11 void set_field(uint32_t reg, uint32_t mask, uint8_t shift, uint32_t value); 1.12 1.13 public: 1.14 - explicit Tcu_channel(l4_addr_t start, uint8_t channel); 1.15 + explicit Tcu_channel(l4_addr_t start, uint8_t channel, l4_cap_idx_t irq); 1.16 1.17 virtual void disable(); 1.18 virtual void enable(); 1.19 @@ -59,6 +60,18 @@ 1.20 virtual void set_full_data_value(uint32_t value); 1.21 virtual uint32_t get_half_data_value(); 1.22 virtual void set_half_data_value(uint32_t value); 1.23 + 1.24 + // Interrupt-related operations. 1.25 + 1.26 + virtual bool get_full_data_mask(); 1.27 + virtual void set_full_data_mask(bool masked); 1.28 + virtual bool get_half_data_mask(); 1.29 + virtual void set_half_data_mask(bool masked); 1.30 + 1.31 + virtual void ack_irq(); 1.32 + virtual bool have_interrupt(); 1.33 + virtual bool wait_for_irq(); 1.34 + virtual bool wait_for_irq(unsigned int timeout); 1.35 }; 1.36 1.37 // TCU device control. 1.38 @@ -70,12 +83,13 @@ 1.39 1.40 virtual unsigned int num_channels() = 0; 1.41 1.42 - virtual Tcu_channel *_get_channel(l4_addr_t addr, uint8_t channel) = 0; 1.43 + virtual Tcu_channel *_get_channel(l4_addr_t addr, uint8_t channel, 1.44 + l4_cap_idx_t irq) = 0; 1.45 1.46 public: 1.47 explicit Tcu_chip(l4_addr_t start, l4_addr_t end); 1.48 1.49 - Tcu_channel *get_channel(uint8_t channel); 1.50 + Tcu_channel *get_channel(uint8_t channel, l4_cap_idx_t irq); 1.51 }; 1.52 1.53 #endif /* __cplusplus */
2.1 --- a/pkg/devices/lib/tcu/include/tcu-jz4780.h Thu Feb 01 22:40:19 2024 +0100 2.2 +++ b/pkg/devices/lib/tcu/include/tcu-jz4780.h Thu Feb 01 22:41:30 2024 +0100 2.3 @@ -34,7 +34,7 @@ 2.4 class Tcu_jz4780_channel : public Tcu_channel 2.5 { 2.6 public: 2.7 - explicit Tcu_jz4780_channel(l4_addr_t start, uint8_t channel); 2.8 + explicit Tcu_jz4780_channel(l4_addr_t start, uint8_t channel, l4_cap_idx_t irq); 2.9 }; 2.10 2.11 2.12 @@ -44,7 +44,7 @@ 2.13 unsigned int num_channels() 2.14 { return 8; } 2.15 2.16 - Tcu_channel *_get_channel(l4_addr_t addr, uint8_t channel); 2.17 + Tcu_channel *_get_channel(l4_addr_t addr, uint8_t channel, l4_cap_idx_t irq); 2.18 2.19 public: 2.20 explicit Tcu_jz4780_chip(l4_addr_t start, l4_addr_t end); 2.21 @@ -60,7 +60,7 @@ 2.22 2.23 void *jz4780_tcu_init(l4_addr_t tcu_base, l4_addr_t tcu_base_end); 2.24 2.25 -void *jz4780_tcu_get_channel(void *tcu, uint8_t channel); 2.26 +void *jz4780_tcu_get_channel(void *tcu, uint8_t channel, l4_cap_idx_t irq); 2.27 2.28 void jz4780_tcu_disable(void *tcu_channel); 2.29 2.30 @@ -92,4 +92,16 @@ 2.31 2.32 void jz4780_tcu_set_half_data_value(void *tcu_channel, uint32_t value); 2.33 2.34 +int jz4780_tcu_get_full_data_mask(void *tcu_channel); 2.35 + 2.36 +void jz4780_tcu_set_full_data_mask(void *tcu_channel, int masked); 2.37 + 2.38 +int jz4780_tcu_get_half_data_mask(void *tcu_channel); 2.39 + 2.40 +void jz4780_tcu_set_half_data_mask(void *tcu_channel, int masked); 2.41 + 2.42 +int jz4780_tcu_have_interrupt(void *tcu_channel); 2.43 + 2.44 +int jz4780_tcu_wait_for_irq(void *tcu_channel, unsigned int timeout); 2.45 + 2.46 EXTERN_C_END
3.1 --- a/pkg/devices/lib/tcu/include/tcu-x1600.h Thu Feb 01 22:40:19 2024 +0100 3.2 +++ b/pkg/devices/lib/tcu/include/tcu-x1600.h Thu Feb 01 22:41:30 2024 +0100 3.3 @@ -34,7 +34,7 @@ 3.4 class Tcu_x1600_channel : public Tcu_channel 3.5 { 3.6 public: 3.7 - explicit Tcu_x1600_channel(l4_addr_t start, uint8_t channel); 3.8 + explicit Tcu_x1600_channel(l4_addr_t start, uint8_t channel, l4_cap_idx_t irq); 3.9 3.10 void enable(); 3.11 uint8_t get_count_mode(); 3.12 @@ -48,7 +48,7 @@ 3.13 unsigned int num_channels() 3.14 { return 8; } 3.15 3.16 - Tcu_channel *_get_channel(l4_addr_t addr, uint8_t channel); 3.17 + Tcu_channel *_get_channel(l4_addr_t addr, uint8_t channel, l4_cap_idx_t irq); 3.18 3.19 public: 3.20 explicit Tcu_x1600_chip(l4_addr_t start, l4_addr_t end); 3.21 @@ -64,7 +64,7 @@ 3.22 3.23 void *x1600_tcu_init(l4_addr_t tcu_base, l4_addr_t tcu_base_end); 3.24 3.25 -void *x1600_tcu_get_channel(void *tcu, uint8_t channel); 3.26 +void *x1600_tcu_get_channel(void *tcu, uint8_t channel, l4_cap_idx_t irq); 3.27 3.28 void x1600_tcu_disable(void *tcu_channel); 3.29 3.30 @@ -96,4 +96,16 @@ 3.31 3.32 void x1600_tcu_set_half_data_value(void *tcu_channel, uint32_t value); 3.33 3.34 +int x1600_tcu_get_full_data_mask(void *tcu_channel); 3.35 + 3.36 +void x1600_tcu_set_full_data_mask(void *tcu_channel, int masked); 3.37 + 3.38 +int x1600_tcu_get_half_data_mask(void *tcu_channel); 3.39 + 3.40 +void x1600_tcu_set_half_data_mask(void *tcu_channel, int masked); 3.41 + 3.42 +int x1600_tcu_have_interrupt(void *tcu_channel); 3.43 + 3.44 +int x1600_tcu_wait_for_irq(void *tcu_channel, unsigned int timeout); 3.45 + 3.46 EXTERN_C_END
4.1 --- a/pkg/devices/lib/tcu/src/common.cc Thu Feb 01 22:40:19 2024 +0100 4.2 +++ b/pkg/devices/lib/tcu/src/common.cc Thu Feb 01 22:41:30 2024 +0100 4.3 @@ -21,8 +21,10 @@ 4.4 4.5 #include <l4/devices/hw_mmio_register_block.h> 4.6 #include <l4/sys/err.h> 4.7 +#include <l4/sys/irq.h> 4.8 +#include <l4/util/util.h> 4.9 4.10 -#include <math.h> 4.11 +#include <math.h> // log2 4.12 4.13 #include "tcu-common.h" 4.14 4.15 @@ -78,6 +80,18 @@ 4.16 Channel_tcu0 = 0, // TCEN0/STOP0/FFLAG0/SFLAG0 4.17 }; 4.18 4.19 +// Flag/mask register bits. 4.20 + 4.21 +enum Flag_bit_numbers : unsigned 4.22 +{ 4.23 + Half_match_wdt = 24, // HFLAGW 4.24 + 4.25 + // Flag/mask group bit offsets. 4.26 + 4.27 + Half_match_shift = 16, 4.28 + Full_match_shift = 0, 4.29 +}; 4.30 + 4.31 // Counter data constraints. 4.32 4.33 enum Data_masks : unsigned 4.34 @@ -102,8 +116,8 @@ 4.35 4.36 // Channel abstraction. 4.37 4.38 -Tcu_channel::Tcu_channel(l4_addr_t addr, uint8_t channel) 4.39 -: _channel(channel) 4.40 +Tcu_channel::Tcu_channel(l4_addr_t addr, uint8_t channel, l4_cap_idx_t irq) 4.41 +: _channel(channel), _irq(irq) 4.42 { 4.43 _regs = new Hw::Mmio_register_block<32>(addr); 4.44 } 4.45 @@ -226,6 +240,73 @@ 4.46 _regs[Tcu_half_data_value_base + _channel * Tcu_data_block_offset] = value & Data_mask; 4.47 } 4.48 4.49 +bool 4.50 +Tcu_channel::get_full_data_mask() 4.51 +{ 4.52 + return _regs[Tcu_mask_status] & (1UL << (_channel + Full_match_shift)); 4.53 +} 4.54 + 4.55 +void 4.56 +Tcu_channel::set_full_data_mask(bool masked) 4.57 +{ 4.58 + _regs[masked ? Tcu_set_mask : Tcu_clear_mask] = (1UL << (_channel + Full_match_shift)); 4.59 +} 4.60 + 4.61 +bool 4.62 +Tcu_channel::get_half_data_mask() 4.63 +{ 4.64 + return _regs[Tcu_mask_status] & (1UL << (_channel + Half_match_shift)); 4.65 +} 4.66 + 4.67 +void 4.68 +Tcu_channel::set_half_data_mask(bool masked) 4.69 +{ 4.70 + _regs[masked ? Tcu_set_mask : Tcu_clear_mask] = (1UL << (_channel + Half_match_shift)); 4.71 +} 4.72 + 4.73 +// Wait indefinitely for an interrupt request, returning true if one was delivered. 4.74 + 4.75 +bool 4.76 +Tcu_channel::wait_for_irq() 4.77 +{ 4.78 + bool irq = !l4_error(l4_irq_receive(_irq, L4_IPC_NEVER)) && have_interrupt(); 4.79 + 4.80 + if (irq) 4.81 + ack_irq(); 4.82 + 4.83 + return irq; 4.84 +} 4.85 + 4.86 +// Wait up to the given timeout (in microseconds) for an interrupt request, 4.87 +// returning true if one was delivered. 4.88 + 4.89 +bool 4.90 +Tcu_channel::wait_for_irq(unsigned int timeout) 4.91 +{ 4.92 + bool irq = !l4_error(l4_irq_receive(_irq, l4_timeout(L4_IPC_TIMEOUT_NEVER, l4util_micros2l4to(timeout)))) && have_interrupt(); 4.93 + 4.94 + if (irq) 4.95 + ack_irq(); 4.96 + 4.97 + return irq; 4.98 +} 4.99 + 4.100 +// Acknowledge an interrupt condition. 4.101 + 4.102 +void 4.103 +Tcu_channel::ack_irq() 4.104 +{ 4.105 + _regs[Tcu_clear_flag] = 1UL << _channel; 4.106 +} 4.107 + 4.108 +// Return whether an interrupt is pending on the given channel. 4.109 + 4.110 +bool 4.111 +Tcu_channel::have_interrupt() 4.112 +{ 4.113 + return _regs[Tcu_flag_status] & (1UL << _channel) ? true : false; 4.114 +} 4.115 + 4.116 4.117 4.118 // Peripheral abstraction. 4.119 @@ -238,10 +319,10 @@ 4.120 // Obtain a channel object. 4.121 4.122 Tcu_channel * 4.123 -Tcu_chip::get_channel(uint8_t channel) 4.124 +Tcu_chip::get_channel(uint8_t channel, l4_cap_idx_t irq) 4.125 { 4.126 if (channel < num_channels()) 4.127 - return _get_channel(_start, channel); 4.128 + return _get_channel(_start, channel, irq); 4.129 else 4.130 throw -L4_EINVAL; 4.131 }
5.1 --- a/pkg/devices/lib/tcu/src/jz4780.cc Thu Feb 01 22:40:19 2024 +0100 5.2 +++ b/pkg/devices/lib/tcu/src/jz4780.cc Thu Feb 01 22:41:30 2024 +0100 5.3 @@ -25,8 +25,9 @@ 5.4 5.5 // Channel abstraction. 5.6 5.7 -Tcu_jz4780_channel::Tcu_jz4780_channel(l4_addr_t addr, uint8_t channel) 5.8 -: Tcu_channel(addr, channel) 5.9 +Tcu_jz4780_channel::Tcu_jz4780_channel(l4_addr_t addr, uint8_t channel, 5.10 + l4_cap_idx_t irq) 5.11 +: Tcu_channel(addr, channel, irq) 5.12 { 5.13 } 5.14 5.15 @@ -39,9 +40,10 @@ 5.16 { 5.17 } 5.18 5.19 -Tcu_channel *Tcu_jz4780_chip::_get_channel(l4_addr_t addr, uint8_t channel) 5.20 +Tcu_channel *Tcu_jz4780_chip::_get_channel(l4_addr_t addr, uint8_t channel, 5.21 + l4_cap_idx_t irq) 5.22 { 5.23 - return new Tcu_jz4780_channel(addr, channel); 5.24 + return new Tcu_jz4780_channel(addr, channel, irq); 5.25 } 5.26 5.27 5.28 @@ -53,9 +55,9 @@ 5.29 return (void *) new Tcu_jz4780_chip(tcu_base, tcu_base_end); 5.30 } 5.31 5.32 -void *jz4780_tcu_get_channel(void *tcu, uint8_t channel) 5.33 +void *jz4780_tcu_get_channel(void *tcu, uint8_t channel, l4_cap_idx_t irq) 5.34 { 5.35 - return static_cast<Tcu_jz4780_chip *>(tcu)->get_channel(channel); 5.36 + return static_cast<Tcu_jz4780_chip *>(tcu)->get_channel(channel, irq); 5.37 } 5.38 5.39 void jz4780_tcu_disable(void *tcu_channel) 5.40 @@ -132,3 +134,33 @@ 5.41 { 5.42 static_cast<Tcu_jz4780_channel *>(tcu_channel)->set_full_data_value(value); 5.43 } 5.44 + 5.45 +int jz4780_tcu_get_full_data_mask(void *tcu_channel) 5.46 +{ 5.47 + return static_cast<Tcu_jz4780_channel *>(tcu_channel)->get_full_data_mask(); 5.48 +} 5.49 + 5.50 +void jz4780_tcu_set_full_data_mask(void *tcu_channel, int masked) 5.51 +{ 5.52 + static_cast<Tcu_jz4780_channel *>(tcu_channel)->set_full_data_mask(masked); 5.53 +} 5.54 + 5.55 +int jz4780_tcu_get_half_data_mask(void *tcu_channel) 5.56 +{ 5.57 + return static_cast<Tcu_jz4780_channel *>(tcu_channel)->get_half_data_mask(); 5.58 +} 5.59 + 5.60 +void jz4780_tcu_set_half_data_mask(void *tcu_channel, int masked) 5.61 +{ 5.62 + static_cast<Tcu_jz4780_channel *>(tcu_channel)->set_half_data_mask(masked); 5.63 +} 5.64 + 5.65 +int jz4780_tcu_have_interrupt(void *tcu_channel) 5.66 +{ 5.67 + return static_cast<Tcu_jz4780_channel *>(tcu_channel)->have_interrupt(); 5.68 +} 5.69 + 5.70 +int jz4780_tcu_wait_for_irq(void *tcu_channel, unsigned int timeout) 5.71 +{ 5.72 + return static_cast<Tcu_jz4780_channel *>(tcu_channel)->wait_for_irq(timeout); 5.73 +}
6.1 --- a/pkg/devices/lib/tcu/src/x1600.cc Thu Feb 01 22:40:19 2024 +0100 6.2 +++ b/pkg/devices/lib/tcu/src/x1600.cc Thu Feb 01 22:41:30 2024 +0100 6.3 @@ -62,18 +62,6 @@ 6.4 6.5 // Field definitions. 6.6 6.7 -// Flag/mask register bits. 6.8 - 6.9 -enum Flag_bit_numbers : unsigned 6.10 -{ 6.11 - Half_match_wdt = 24, // HFLAGW 6.12 - 6.13 - // Flag/mask group bit offsets. 6.14 - 6.15 - Half_match_shift = 16, 6.16 - Full_match_shift = 0, 6.17 -}; 6.18 - 6.19 // Counter data constraints. 6.20 6.21 enum Data_masks : unsigned 6.22 @@ -157,8 +145,9 @@ 6.23 6.24 // Channel abstraction. 6.25 6.26 -Tcu_x1600_channel::Tcu_x1600_channel(l4_addr_t addr, uint8_t channel) 6.27 -: Tcu_channel(addr, channel) 6.28 +Tcu_x1600_channel::Tcu_x1600_channel(l4_addr_t addr, uint8_t channel, 6.29 + l4_cap_idx_t irq) 6.30 +: Tcu_channel(addr, channel, irq) 6.31 { 6.32 } 6.33 6.34 @@ -199,9 +188,10 @@ 6.35 { 6.36 } 6.37 6.38 -Tcu_channel *Tcu_x1600_chip::_get_channel(l4_addr_t addr, uint8_t channel) 6.39 +Tcu_channel *Tcu_x1600_chip::_get_channel(l4_addr_t addr, uint8_t channel, 6.40 + l4_cap_idx_t irq) 6.41 { 6.42 - return new Tcu_x1600_channel(addr, channel); 6.43 + return new Tcu_x1600_channel(addr, channel, irq); 6.44 } 6.45 6.46 6.47 @@ -213,9 +203,9 @@ 6.48 return (void *) new Tcu_x1600_chip(tcu_base, tcu_base_end); 6.49 } 6.50 6.51 -void *x1600_tcu_get_channel(void *tcu, uint8_t channel) 6.52 +void *x1600_tcu_get_channel(void *tcu, uint8_t channel, l4_cap_idx_t irq) 6.53 { 6.54 - return static_cast<Tcu_x1600_chip *>(tcu)->get_channel(channel); 6.55 + return static_cast<Tcu_x1600_chip *>(tcu)->get_channel(channel, irq); 6.56 } 6.57 6.58 void x1600_tcu_disable(void *tcu_channel) 6.59 @@ -292,3 +282,33 @@ 6.60 { 6.61 static_cast<Tcu_x1600_channel *>(tcu_channel)->set_full_data_value(value); 6.62 } 6.63 + 6.64 +int x1600_tcu_get_full_data_mask(void *tcu_channel) 6.65 +{ 6.66 + return static_cast<Tcu_x1600_channel *>(tcu_channel)->get_full_data_mask(); 6.67 +} 6.68 + 6.69 +void x1600_tcu_set_full_data_mask(void *tcu_channel, int masked) 6.70 +{ 6.71 + static_cast<Tcu_x1600_channel *>(tcu_channel)->set_full_data_mask(masked); 6.72 +} 6.73 + 6.74 +int x1600_tcu_get_half_data_mask(void *tcu_channel) 6.75 +{ 6.76 + return static_cast<Tcu_x1600_channel *>(tcu_channel)->get_half_data_mask(); 6.77 +} 6.78 + 6.79 +void x1600_tcu_set_half_data_mask(void *tcu_channel, int masked) 6.80 +{ 6.81 + static_cast<Tcu_x1600_channel *>(tcu_channel)->set_half_data_mask(masked); 6.82 +} 6.83 + 6.84 +int x1600_tcu_have_interrupt(void *tcu_channel) 6.85 +{ 6.86 + return static_cast<Tcu_x1600_channel *>(tcu_channel)->have_interrupt(); 6.87 +} 6.88 + 6.89 +int x1600_tcu_wait_for_irq(void *tcu_channel, unsigned int timeout) 6.90 +{ 6.91 + return static_cast<Tcu_x1600_channel *>(tcu_channel)->wait_for_irq(timeout); 6.92 +}