1.1 --- a/conf/landfall-examples/mips-jz4780-info.io Thu Feb 01 01:09:29 2024 +0100 1.2 +++ b/conf/landfall-examples/mips-jz4780-info.io Thu Feb 01 01:16:04 2024 +0100 1.3 @@ -12,6 +12,7 @@ 1.4 I2C = wrap(hw:match("jz4780-i2c")); 1.5 RTC = wrap(hw:match("jz4780-rtc")); 1.6 SSI = wrap(hw:match("jz4780-ssi")); 1.7 + TCU = wrap(hw:match("jz4780-tcu")); 1.8 } 1.9 1.10 Io.add_vbus("common", bus)
2.1 --- a/conf/landfall-examples/mips-x1600-info.io Thu Feb 01 01:09:29 2024 +0100 2.2 +++ b/conf/landfall-examples/mips-x1600-info.io Thu Feb 01 01:16:04 2024 +0100 2.3 @@ -12,6 +12,7 @@ 2.4 I2C = wrap(hw:match("x1600-i2c")); 2.5 RTC = wrap(hw:match("x1600-rtc")); 2.6 SSI = wrap(hw:match("x1600-ssi")); 2.7 + TCU = wrap(hw:match("x1600-tcu")); 2.8 } 2.9 2.10 Io.add_vbus("common", bus)
3.1 --- a/pkg/devices/Control Thu Feb 01 01:09:29 2024 +0100 3.2 +++ b/pkg/devices/Control Thu Feb 01 01:16:04 2024 +0100 3.3 @@ -42,5 +42,6 @@ 3.4 provides: libdrivers-pwm 3.5 provides: libdrivers-rtc 3.6 provides: libdrivers-spi 3.7 +provides: libdrivers-tcu 3.8 requires: libc libc_be_l4re libdl l4re_c libio libipc 3.9 Maintainer: paul@boddie.org.uk
4.1 --- a/pkg/devices/lib/Makefile Thu Feb 01 01:09:29 2024 +0100 4.2 +++ b/pkg/devices/lib/Makefile Thu Feb 01 01:16:04 2024 +0100 4.3 @@ -1,7 +1,7 @@ 4.4 PKGDIR ?= .. 4.5 L4DIR ?= $(PKGDIR)/../.. 4.6 4.7 -TARGET := aic common cpm dma gpio hdmi i2c keypad lcd panel pwm rtc spi 4.8 +TARGET := aic common cpm dma gpio hdmi i2c keypad lcd panel pwm rtc spi tcu 4.9 4.10 include $(L4DIR)/mk/subdir.mk 4.11 4.12 @@ -17,3 +17,4 @@ 4.13 pwm: common 4.14 rtc: common 4.15 spi: cpm dma gpio 4.16 +tcu: common
5.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 5.2 +++ b/pkg/devices/lib/tcu/Makefile Thu Feb 01 01:16:04 2024 +0100 5.3 @@ -0,0 +1,8 @@ 5.4 +PKGDIR ?= ../.. 5.5 +L4DIR ?= $(PKGDIR)/../.. 5.6 + 5.7 +TARGET := include src 5.8 + 5.9 +include $(L4DIR)/mk/subdir.mk 5.10 + 5.11 +src: include
6.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 6.2 +++ b/pkg/devices/lib/tcu/include/Makefile Thu Feb 01 01:16:04 2024 +0100 6.3 @@ -0,0 +1,4 @@ 6.4 +PKGDIR = ../../.. 6.5 +L4DIR ?= $(PKGDIR)/../.. 6.6 + 6.7 +include $(L4DIR)/mk/include.mk
7.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 7.2 +++ b/pkg/devices/lib/tcu/include/tcu-common.h Thu Feb 01 01:16:04 2024 +0100 7.3 @@ -0,0 +1,81 @@ 7.4 +/* 7.5 + * TCU support for various chips. 7.6 + * 7.7 + * Copyright (C) 2024 Paul Boddie <paul@boddie.org.uk> 7.8 + * 7.9 + * This program is free software; you can redistribute it and/or 7.10 + * modify it under the terms of the GNU General Public License as 7.11 + * published by the Free Software Foundation; either version 2 of 7.12 + * the License, or (at your option) any later version. 7.13 + * 7.14 + * This program is distributed in the hope that it will be useful, 7.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 7.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 7.17 + * GNU General Public License for more details. 7.18 + * 7.19 + * You should have received a copy of the GNU General Public License 7.20 + * along with this program; if not, write to the Free Software 7.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, 7.22 + * Boston, MA 02110-1301, USA 7.23 + */ 7.24 + 7.25 +#pragma once 7.26 + 7.27 +#include <l4/sys/types.h> 7.28 +#include <stdint.h> 7.29 + 7.30 + 7.31 + 7.32 +#ifdef __cplusplus 7.33 + 7.34 +#include <l4/devices/hw_mmio_register_block.h> 7.35 + 7.36 +// TCU channel. 7.37 + 7.38 +class Tcu_channel 7.39 +{ 7.40 +protected: 7.41 + uint8_t _channel; 7.42 + Hw::Register_block<32> _regs; 7.43 + 7.44 + uint32_t get_field(uint32_t reg, uint32_t mask, uint8_t shift); 7.45 + void set_field(uint32_t reg, uint32_t mask, uint8_t shift, uint32_t value); 7.46 + 7.47 +public: 7.48 + explicit Tcu_channel(l4_addr_t start, uint8_t channel); 7.49 + 7.50 + virtual void disable(); 7.51 + virtual void enable(); 7.52 + virtual bool is_enabled(); 7.53 + virtual uint8_t get_clock(); 7.54 + virtual void set_clock(uint8_t clock); 7.55 + virtual uint32_t get_prescale(); 7.56 + virtual void set_prescale(uint32_t prescale); 7.57 + virtual uint32_t get_counter(); 7.58 + virtual void set_counter(uint32_t value); 7.59 + virtual uint8_t get_count_mode(); 7.60 + virtual void set_count_mode(uint8_t mode); 7.61 + virtual uint32_t get_full_data_value(); 7.62 + virtual void set_full_data_value(uint32_t value); 7.63 + virtual uint32_t get_half_data_value(); 7.64 + virtual void set_half_data_value(uint32_t value); 7.65 +}; 7.66 + 7.67 +// TCU device control. 7.68 + 7.69 +class Tcu_chip 7.70 +{ 7.71 +protected: 7.72 + l4_addr_t _start, _end; 7.73 + 7.74 + virtual unsigned int num_channels() = 0; 7.75 + 7.76 + virtual Tcu_channel *_get_channel(l4_addr_t addr, uint8_t channel) = 0; 7.77 + 7.78 +public: 7.79 + explicit Tcu_chip(l4_addr_t start, l4_addr_t end); 7.80 + 7.81 + Tcu_channel *get_channel(uint8_t channel); 7.82 +}; 7.83 + 7.84 +#endif /* __cplusplus */
8.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 8.2 +++ b/pkg/devices/lib/tcu/include/tcu-jz4780.h Thu Feb 01 01:16:04 2024 +0100 8.3 @@ -0,0 +1,95 @@ 8.4 +/* 8.5 + * TCU (timer/counter unit) support for the JZ4780. 8.6 + * 8.7 + * Copyright (C) 2024 Paul Boddie <paul@boddie.org.uk> 8.8 + * 8.9 + * This program is free software; you can redistribute it and/or 8.10 + * modify it under the terms of the GNU General Public License as 8.11 + * published by the Free Software Foundation; either version 2 of 8.12 + * the License, or (at your option) any later version. 8.13 + * 8.14 + * This program is distributed in the hope that it will be useful, 8.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 8.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 8.17 + * GNU General Public License for more details. 8.18 + * 8.19 + * You should have received a copy of the GNU General Public License 8.20 + * along with this program; if not, write to the Free Software 8.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, 8.22 + * Boston, MA 02110-1301, USA 8.23 + */ 8.24 + 8.25 +#pragma once 8.26 + 8.27 +#include <l4/sys/types.h> 8.28 +#include <stdint.h> 8.29 + 8.30 + 8.31 + 8.32 +#ifdef __cplusplus 8.33 + 8.34 +#include <l4/devices/tcu-common.h> 8.35 + 8.36 + 8.37 +class Tcu_jz4780_channel : public Tcu_channel 8.38 +{ 8.39 +public: 8.40 + explicit Tcu_jz4780_channel(l4_addr_t start, uint8_t channel); 8.41 +}; 8.42 + 8.43 + 8.44 +class Tcu_jz4780_chip : public Tcu_chip 8.45 +{ 8.46 +protected: 8.47 + unsigned int num_channels() 8.48 + { return 8; } 8.49 + 8.50 + Tcu_channel *_get_channel(l4_addr_t addr, uint8_t channel); 8.51 + 8.52 +public: 8.53 + explicit Tcu_jz4780_chip(l4_addr_t start, l4_addr_t end); 8.54 +}; 8.55 + 8.56 +#endif /* __cplusplus */ 8.57 + 8.58 + 8.59 + 8.60 +/* C language interface. */ 8.61 + 8.62 +EXTERN_C_BEGIN 8.63 + 8.64 +void *jz4780_tcu_init(l4_addr_t tcu_base, l4_addr_t tcu_base_end); 8.65 + 8.66 +void *jz4780_tcu_get_channel(void *tcu, uint8_t channel); 8.67 + 8.68 +void jz4780_tcu_disable(void *tcu_channel); 8.69 + 8.70 +void jz4780_tcu_enable(void *tcu_channel); 8.71 + 8.72 +int jz4780_tcu_is_enabled(void *tcu_channel); 8.73 + 8.74 +uint8_t jz4780_tcu_get_clock(void *tcu_channel); 8.75 + 8.76 +void jz4780_tcu_set_clock(void *tcu_channel, uint8_t clock); 8.77 + 8.78 +uint32_t jz4780_tcu_get_prescale(void *tcu_channel); 8.79 + 8.80 +void jz4780_tcu_set_prescale(void *tcu_channel, uint32_t prescale); 8.81 + 8.82 +uint32_t jz4780_tcu_get_counter(void *tcu_channel); 8.83 + 8.84 +void jz4780_tcu_set_counter(void *tcu_channel, uint32_t value); 8.85 + 8.86 +uint8_t jz4780_tcu_get_count_mode(void *tcu_channel); 8.87 + 8.88 +void jz4780_tcu_set_count_mode(void *tcu_channel, uint8_t mode); 8.89 + 8.90 +uint32_t jz4780_tcu_get_full_data_value(void *tcu_channel); 8.91 + 8.92 +void jz4780_tcu_set_full_data_value(void *tcu_channel, uint32_t value); 8.93 + 8.94 +uint32_t jz4780_tcu_get_half_data_value(void *tcu_channel); 8.95 + 8.96 +void jz4780_tcu_set_half_data_value(void *tcu_channel, uint32_t value); 8.97 + 8.98 +EXTERN_C_END
9.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 9.2 +++ b/pkg/devices/lib/tcu/include/tcu-x1600.h Thu Feb 01 01:16:04 2024 +0100 9.3 @@ -0,0 +1,99 @@ 9.4 +/* 9.5 + * TCU (timer/counter unit) support for the X1600. 9.6 + * 9.7 + * Copyright (C) 2024 Paul Boddie <paul@boddie.org.uk> 9.8 + * 9.9 + * This program is free software; you can redistribute it and/or 9.10 + * modify it under the terms of the GNU General Public License as 9.11 + * published by the Free Software Foundation; either version 2 of 9.12 + * the License, or (at your option) any later version. 9.13 + * 9.14 + * This program is distributed in the hope that it will be useful, 9.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 9.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 9.17 + * GNU General Public License for more details. 9.18 + * 9.19 + * You should have received a copy of the GNU General Public License 9.20 + * along with this program; if not, write to the Free Software 9.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, 9.22 + * Boston, MA 02110-1301, USA 9.23 + */ 9.24 + 9.25 +#pragma once 9.26 + 9.27 +#include <l4/sys/types.h> 9.28 +#include <stdint.h> 9.29 + 9.30 + 9.31 + 9.32 +#ifdef __cplusplus 9.33 + 9.34 +#include <l4/devices/tcu-common.h> 9.35 + 9.36 + 9.37 +class Tcu_x1600_channel : public Tcu_channel 9.38 +{ 9.39 +public: 9.40 + explicit Tcu_x1600_channel(l4_addr_t start, uint8_t channel); 9.41 + 9.42 + void enable(); 9.43 + uint8_t get_count_mode(); 9.44 + void set_count_mode(uint8_t mode); 9.45 +}; 9.46 + 9.47 + 9.48 +class Tcu_x1600_chip : public Tcu_chip 9.49 +{ 9.50 +protected: 9.51 + unsigned int num_channels() 9.52 + { return 8; } 9.53 + 9.54 + Tcu_channel *_get_channel(l4_addr_t addr, uint8_t channel); 9.55 + 9.56 +public: 9.57 + explicit Tcu_x1600_chip(l4_addr_t start, l4_addr_t end); 9.58 +}; 9.59 + 9.60 +#endif /* __cplusplus */ 9.61 + 9.62 + 9.63 + 9.64 +/* C language interface. */ 9.65 + 9.66 +EXTERN_C_BEGIN 9.67 + 9.68 +void *x1600_tcu_init(l4_addr_t tcu_base, l4_addr_t tcu_base_end); 9.69 + 9.70 +void *x1600_tcu_get_channel(void *tcu, uint8_t channel); 9.71 + 9.72 +void x1600_tcu_disable(void *tcu_channel); 9.73 + 9.74 +void x1600_tcu_enable(void *tcu_channel); 9.75 + 9.76 +int x1600_tcu_is_enabled(void *tcu_channel); 9.77 + 9.78 +uint8_t x1600_tcu_get_clock(void *tcu_channel); 9.79 + 9.80 +void x1600_tcu_set_clock(void *tcu_channel, uint8_t clock); 9.81 + 9.82 +uint32_t x1600_tcu_get_prescale(void *tcu_channel); 9.83 + 9.84 +void x1600_tcu_set_prescale(void *tcu_channel, uint32_t prescale); 9.85 + 9.86 +uint32_t x1600_tcu_get_counter(void *tcu_channel); 9.87 + 9.88 +void x1600_tcu_set_counter(void *tcu_channel, uint32_t value); 9.89 + 9.90 +uint8_t x1600_tcu_get_count_mode(void *tcu_channel); 9.91 + 9.92 +void x1600_tcu_set_count_mode(void *tcu_channel, uint8_t mode); 9.93 + 9.94 +uint32_t x1600_tcu_get_full_data_value(void *tcu_channel); 9.95 + 9.96 +void x1600_tcu_set_full_data_value(void *tcu_channel, uint32_t value); 9.97 + 9.98 +uint32_t x1600_tcu_get_half_data_value(void *tcu_channel); 9.99 + 9.100 +void x1600_tcu_set_half_data_value(void *tcu_channel, uint32_t value); 9.101 + 9.102 +EXTERN_C_END
10.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 10.2 +++ b/pkg/devices/lib/tcu/src/Makefile Thu Feb 01 01:16:04 2024 +0100 10.3 @@ -0,0 +1,13 @@ 10.4 +PKGDIR ?= ../../.. 10.5 +L4DIR ?= $(PKGDIR)/../.. 10.6 + 10.7 +TARGET = libtcu.o.a libtcu.o.so 10.8 +PC_FILENAME := libdrivers-tcu 10.9 + 10.10 +SRC_CC := common.cc jz4780.cc x1600.cc 10.11 + 10.12 +PRIVATE_INCDIR += $(PKGDIR)/lib/tcu/include 10.13 + 10.14 +REQUIRES_LIBS := l4re_c l4re_c-util libdrivers-common 10.15 + 10.16 +include $(L4DIR)/mk/lib.mk
11.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 11.2 +++ b/pkg/devices/lib/tcu/src/common.cc Thu Feb 01 01:16:04 2024 +0100 11.3 @@ -0,0 +1,247 @@ 11.4 +/* 11.5 + * Timer/counter unit support. 11.6 + * 11.7 + * Copyright (C) 2024 Paul Boddie <paul@boddie.org.uk> 11.8 + * 11.9 + * This program is free software; you can redistribute it and/or 11.10 + * modify it under the terms of the GNU General Public License as 11.11 + * published by the Free Software Foundation; either version 2 of 11.12 + * the License, or (at your option) any later version. 11.13 + * 11.14 + * This program is distributed in the hope that it will be useful, 11.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 11.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11.17 + * GNU General Public License for more details. 11.18 + * 11.19 + * You should have received a copy of the GNU General Public License 11.20 + * along with this program; if not, write to the Free Software 11.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, 11.22 + * Boston, MA 02110-1301, USA 11.23 + */ 11.24 + 11.25 +#include <l4/devices/hw_mmio_register_block.h> 11.26 +#include <l4/sys/err.h> 11.27 + 11.28 +#include <math.h> 11.29 + 11.30 +#include "tcu-common.h" 11.31 + 11.32 + 11.33 + 11.34 +// Register locations. 11.35 + 11.36 +enum Regs : unsigned 11.37 +{ 11.38 + Tcu_enable_status = 0x010, // TER 11.39 + Tcu_set_enable = 0x014, // TESR 11.40 + Tcu_clear_enable = 0x018, // TECR 11.41 + Tcu_stop_status = 0x01c, // TSR 11.42 + Tcu_set_stop = 0x02c, // TSSR 11.43 + Tcu_clear_stop = 0x03c, // TSCR 11.44 + Tcu_flag_status = 0x020, // TFR 11.45 + Tcu_set_flag = 0x024, // TFSR 11.46 + Tcu_clear_flag = 0x028, // TFCR 11.47 + Tcu_mask_status = 0x030, // TMR 11.48 + Tcu_set_mask = 0x034, // TMSR 11.49 + Tcu_clear_mask = 0x038, // TMCR 11.50 + 11.51 + // Channel-related locations. 11.52 + 11.53 + Tcu_full_data_value_base = 0x040, // TDFRn 11.54 + Tcu_half_data_value_base = 0x044, // TDHRn 11.55 + Tcu_counter_base = 0x048, // TCNTn 11.56 + Tcu_control_base = 0x04c, // TCRn 11.57 + 11.58 + // Block size/step/offset for the above register set. 11.59 + 11.60 + Tcu_data_block_offset = 0x010, 11.61 +}; 11.62 + 11.63 +// Field definitions. 11.64 + 11.65 +// Enable/stop register bits. 11.66 + 11.67 +enum Channel_bit_numbers : unsigned 11.68 +{ 11.69 + Channel_wdt = 16, // WDTS only 11.70 + 11.71 + // Enable/stop/flag/mask bit numbers. 11.72 + 11.73 + Channel_ost = 15, // OSTEN/OSTS/OSTFLAG 11.74 + Channel_tcu7 = 7, // TCEN7/STOP7/FFLAG7/SFLAG7 11.75 + Channel_tcu6 = 6, // TCEN6/STOP6/FFLAG6/SFLAG6 11.76 + Channel_tcu5 = 5, // TCEN5/STOP5/FFLAG5/SFLAG5 11.77 + Channel_tcu4 = 4, // TCEN4/STOP4/FFLAG4/SFLAG4 11.78 + Channel_tcu3 = 3, // TCEN3/STOP3/FFLAG3/SFLAG3 11.79 + Channel_tcu2 = 2, // TCEN2/STOP2/FFLAG2/SFLAG2 11.80 + Channel_tcu1 = 1, // TCEN1/STOP1/FFLAG1/SFLAG1 11.81 + Channel_tcu0 = 0, // TCEN0/STOP0/FFLAG0/SFLAG0 11.82 +}; 11.83 + 11.84 +// Counter data constraints. 11.85 + 11.86 +enum Data_masks : unsigned 11.87 +{ 11.88 + Data_mask = 0xffff, 11.89 +}; 11.90 + 11.91 +enum Control_bits : unsigned 11.92 +{ 11.93 + Count_prescale_field_mask = 0x7, // PRESCALE 11.94 + Count_prescale_max = 5, // CLK/1024 11.95 + Count_prescale_field_shift = 3, 11.96 + 11.97 + Count_clock_field_mask = 0x7, 11.98 + Count_clock_exclk = 4, // EXT_EN 11.99 + Count_clock_rtclk = 2, // RTC_EN 11.100 + Count_clock_pclk = 1, // PCK_EN 11.101 + Count_clock_field_shift = 0, 11.102 +}; 11.103 + 11.104 + 11.105 + 11.106 +// Channel abstraction. 11.107 + 11.108 +Tcu_channel::Tcu_channel(l4_addr_t addr, uint8_t channel) 11.109 +: _channel(channel) 11.110 +{ 11.111 + _regs = new Hw::Mmio_register_block<32>(addr); 11.112 +} 11.113 + 11.114 +// Utility methods. 11.115 +// NOTE: Also defined in the CPM abstraction, should be consolidated. 11.116 + 11.117 +uint32_t 11.118 +Tcu_channel::get_field(uint32_t reg, uint32_t mask, uint8_t shift) 11.119 +{ 11.120 + return (_regs[reg] & (mask << shift)) >> shift; 11.121 +} 11.122 + 11.123 +void 11.124 +Tcu_channel::set_field(uint32_t reg, uint32_t mask, uint8_t shift, uint32_t value) 11.125 +{ 11.126 + _regs[reg] = (_regs[reg] & (~(mask << shift))) | ((mask & value) << shift); 11.127 +} 11.128 + 11.129 +// Operation methods. 11.130 + 11.131 +uint8_t 11.132 +Tcu_channel::get_clock() 11.133 +{ 11.134 + return (uint8_t) get_field(Tcu_control_base + _channel * Tcu_data_block_offset, 11.135 + Count_clock_field_mask, Count_clock_field_shift); 11.136 +} 11.137 + 11.138 +void 11.139 +Tcu_channel::set_clock(uint8_t clock) 11.140 +{ 11.141 + 11.142 + set_field(Tcu_control_base + _channel * Tcu_data_block_offset, 11.143 + Count_clock_field_mask, Count_clock_field_shift, clock); 11.144 +} 11.145 + 11.146 +uint32_t 11.147 +Tcu_channel::get_prescale() 11.148 +{ 11.149 + return 1UL << (2 * get_field(Tcu_control_base + _channel * Tcu_data_block_offset, 11.150 + Count_prescale_field_mask, Count_prescale_field_shift)); 11.151 +} 11.152 + 11.153 +void 11.154 +Tcu_channel::set_prescale(uint32_t prescale) 11.155 +{ 11.156 + // Obtain the log4 value for prescale. 11.157 + 11.158 + uint32_t value = (uint32_t) log2(prescale) / 2; 11.159 + 11.160 + set_field(Tcu_control_base + _channel * Tcu_data_block_offset, 11.161 + Count_prescale_field_mask, Count_prescale_field_shift, 11.162 + value > Count_prescale_max ? Count_prescale_max : value); 11.163 +} 11.164 + 11.165 +void 11.166 +Tcu_channel::disable() 11.167 +{ 11.168 + _regs[Tcu_clear_enable] = 1UL << _channel; 11.169 +} 11.170 + 11.171 +void 11.172 +Tcu_channel::enable() 11.173 +{ 11.174 + _regs[Tcu_set_enable] = 1UL << _channel; 11.175 +} 11.176 + 11.177 +bool 11.178 +Tcu_channel::is_enabled() 11.179 +{ 11.180 + return _regs[Tcu_enable_status] & (1UL << _channel); 11.181 +} 11.182 + 11.183 +uint32_t 11.184 +Tcu_channel::get_counter() 11.185 +{ 11.186 + return _regs[Tcu_counter_base + _channel * Tcu_data_block_offset] & Data_mask; 11.187 +} 11.188 + 11.189 +void 11.190 +Tcu_channel::set_counter(uint32_t value) 11.191 +{ 11.192 + _regs[Tcu_counter_base + _channel * Tcu_data_block_offset] = value & Data_mask; 11.193 +} 11.194 + 11.195 +uint8_t 11.196 +Tcu_channel::get_count_mode() 11.197 +{ 11.198 + return 0; 11.199 +} 11.200 + 11.201 +void 11.202 +Tcu_channel::set_count_mode(uint8_t mode) 11.203 +{ 11.204 + if (mode != 0) 11.205 + throw -L4_EINVAL; 11.206 +} 11.207 + 11.208 +uint32_t 11.209 +Tcu_channel::get_full_data_value() 11.210 +{ 11.211 + return _regs[Tcu_full_data_value_base + _channel * Tcu_data_block_offset] & Data_mask; 11.212 +} 11.213 + 11.214 +void 11.215 +Tcu_channel::set_full_data_value(uint32_t value) 11.216 +{ 11.217 + _regs[Tcu_full_data_value_base + _channel * Tcu_data_block_offset] = value & Data_mask; 11.218 +} 11.219 + 11.220 +uint32_t 11.221 +Tcu_channel::get_half_data_value() 11.222 +{ 11.223 + return _regs[Tcu_half_data_value_base + _channel * Tcu_data_block_offset] & Data_mask; 11.224 +} 11.225 + 11.226 +void 11.227 +Tcu_channel::set_half_data_value(uint32_t value) 11.228 +{ 11.229 + _regs[Tcu_half_data_value_base + _channel * Tcu_data_block_offset] = value & Data_mask; 11.230 +} 11.231 + 11.232 + 11.233 + 11.234 +// Peripheral abstraction. 11.235 + 11.236 +Tcu_chip::Tcu_chip(l4_addr_t start, l4_addr_t end) 11.237 +: _start(start), _end(end) 11.238 +{ 11.239 +} 11.240 + 11.241 +// Obtain a channel object. 11.242 + 11.243 +Tcu_channel * 11.244 +Tcu_chip::get_channel(uint8_t channel) 11.245 +{ 11.246 + if (channel < num_channels()) 11.247 + return _get_channel(_start, channel); 11.248 + else 11.249 + throw -L4_EINVAL; 11.250 +}
12.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 12.2 +++ b/pkg/devices/lib/tcu/src/jz4780.cc Thu Feb 01 01:16:04 2024 +0100 12.3 @@ -0,0 +1,134 @@ 12.4 +/* 12.5 + * Timer/counter unit support for the JZ4780. 12.6 + * 12.7 + * Copyright (C) 2024 Paul Boddie <paul@boddie.org.uk> 12.8 + * 12.9 + * This program is free software; you can redistribute it and/or 12.10 + * modify it under the terms of the GNU General Public License as 12.11 + * published by the Free Software Foundation; either version 2 of 12.12 + * the License, or (at your option) any later version. 12.13 + * 12.14 + * This program is distributed in the hope that it will be useful, 12.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 12.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12.17 + * GNU General Public License for more details. 12.18 + * 12.19 + * You should have received a copy of the GNU General Public License 12.20 + * along with this program; if not, write to the Free Software 12.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, 12.22 + * Boston, MA 02110-1301, USA 12.23 + */ 12.24 + 12.25 +#include "tcu-jz4780.h" 12.26 + 12.27 + 12.28 + 12.29 +// Channel abstraction. 12.30 + 12.31 +Tcu_jz4780_channel::Tcu_jz4780_channel(l4_addr_t addr, uint8_t channel) 12.32 +: Tcu_channel(addr, channel) 12.33 +{ 12.34 +} 12.35 + 12.36 + 12.37 + 12.38 +// Peripheral abstraction. 12.39 + 12.40 +Tcu_jz4780_chip::Tcu_jz4780_chip(l4_addr_t start, l4_addr_t end) 12.41 +: Tcu_chip(start, end) 12.42 +{ 12.43 +} 12.44 + 12.45 +Tcu_channel *Tcu_jz4780_chip::_get_channel(l4_addr_t addr, uint8_t channel) 12.46 +{ 12.47 + return new Tcu_jz4780_channel(addr, channel); 12.48 +} 12.49 + 12.50 + 12.51 + 12.52 +// C language interface functions. 12.53 + 12.54 +void *jz4780_tcu_init(l4_addr_t tcu_base, l4_addr_t tcu_base_end) 12.55 +{ 12.56 + return (void *) new Tcu_jz4780_chip(tcu_base, tcu_base_end); 12.57 +} 12.58 + 12.59 +void *jz4780_tcu_get_channel(void *tcu, uint8_t channel) 12.60 +{ 12.61 + return static_cast<Tcu_jz4780_chip *>(tcu)->get_channel(channel); 12.62 +} 12.63 + 12.64 +void jz4780_tcu_disable(void *tcu_channel) 12.65 +{ 12.66 + static_cast<Tcu_jz4780_channel *>(tcu_channel)->disable(); 12.67 +} 12.68 + 12.69 +void jz4780_tcu_enable(void *tcu_channel) 12.70 +{ 12.71 + static_cast<Tcu_jz4780_channel *>(tcu_channel)->enable(); 12.72 +} 12.73 + 12.74 +int jz4780_tcu_is_enabled(void *tcu_channel) 12.75 +{ 12.76 + return static_cast<Tcu_jz4780_channel *>(tcu_channel)->is_enabled(); 12.77 +} 12.78 + 12.79 +uint8_t jz4780_tcu_get_clock(void *tcu_channel) 12.80 +{ 12.81 + return static_cast<Tcu_jz4780_channel *>(tcu_channel)->get_clock(); 12.82 +} 12.83 + 12.84 +void jz4780_tcu_set_clock(void *tcu_channel, uint8_t clock) 12.85 +{ 12.86 + static_cast<Tcu_jz4780_channel *>(tcu_channel)->set_clock(clock); 12.87 +} 12.88 + 12.89 +uint32_t jz4780_tcu_get_prescale(void *tcu_channel) 12.90 +{ 12.91 + return static_cast<Tcu_jz4780_channel *>(tcu_channel)->get_prescale(); 12.92 +} 12.93 + 12.94 +void jz4780_tcu_set_prescale(void *tcu_channel, uint32_t prescale) 12.95 +{ 12.96 + static_cast<Tcu_jz4780_channel *>(tcu_channel)->set_prescale(prescale); 12.97 +} 12.98 + 12.99 +uint32_t jz4780_tcu_get_counter(void *tcu_channel) 12.100 +{ 12.101 + return static_cast<Tcu_jz4780_channel *>(tcu_channel)->get_counter(); 12.102 +} 12.103 + 12.104 +void jz4780_tcu_set_counter(void *tcu_channel, uint32_t value) 12.105 +{ 12.106 + static_cast<Tcu_jz4780_channel *>(tcu_channel)->set_counter(value); 12.107 +} 12.108 + 12.109 +uint8_t jz4780_tcu_get_count_mode(void *tcu_channel) 12.110 +{ 12.111 + return static_cast<Tcu_jz4780_channel *>(tcu_channel)->get_count_mode(); 12.112 +} 12.113 + 12.114 +void jz4780_tcu_set_count_mode(void *tcu_channel, uint8_t mode) 12.115 +{ 12.116 + static_cast<Tcu_jz4780_channel *>(tcu_channel)->set_count_mode(mode); 12.117 +} 12.118 + 12.119 +uint32_t jz4780_tcu_get_full_data_value(void *tcu_channel) 12.120 +{ 12.121 + return static_cast<Tcu_jz4780_channel *>(tcu_channel)->get_full_data_value(); 12.122 +} 12.123 + 12.124 +void jz4780_tcu_set_full_data_value(void *tcu_channel, uint32_t value) 12.125 +{ 12.126 + static_cast<Tcu_jz4780_channel *>(tcu_channel)->set_full_data_value(value); 12.127 +} 12.128 + 12.129 +uint32_t jz4780_tcu_get_half_data_value(void *tcu_channel) 12.130 +{ 12.131 + return static_cast<Tcu_jz4780_channel *>(tcu_channel)->get_half_data_value(); 12.132 +} 12.133 + 12.134 +void jz4780_tcu_set_half_data_value(void *tcu_channel, uint32_t value) 12.135 +{ 12.136 + static_cast<Tcu_jz4780_channel *>(tcu_channel)->set_full_data_value(value); 12.137 +}
13.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 13.2 +++ b/pkg/devices/lib/tcu/src/x1600.cc Thu Feb 01 01:16:04 2024 +0100 13.3 @@ -0,0 +1,294 @@ 13.4 +/* 13.5 + * Timer/counter unit support. 13.6 + * 13.7 + * Copyright (C) 2024 Paul Boddie <paul@boddie.org.uk> 13.8 + * 13.9 + * This program is free software; you can redistribute it and/or 13.10 + * modify it under the terms of the GNU General Public License as 13.11 + * published by the Free Software Foundation; either version 2 of 13.12 + * the License, or (at your option) any later version. 13.13 + * 13.14 + * This program is distributed in the hope that it will be useful, 13.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 13.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13.17 + * GNU General Public License for more details. 13.18 + * 13.19 + * You should have received a copy of the GNU General Public License 13.20 + * along with this program; if not, write to the Free Software 13.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, 13.22 + * Boston, MA 02110-1301, USA 13.23 + */ 13.24 + 13.25 +#include "tcu-x1600.h" 13.26 + 13.27 + 13.28 + 13.29 +// Register locations. 13.30 + 13.31 +enum Regs : unsigned 13.32 +{ 13.33 + Tcu_control_base = 0x04c, // TCRn 13.34 + 13.35 + // Block size/step/offset for the above register set. 13.36 + 13.37 + Tcu_data_block_offset = 0x010, 13.38 +}; 13.39 + 13.40 +enum Regs_x1600 : unsigned 13.41 +{ 13.42 + // X1600 channel-related locations. 13.43 + 13.44 + Tcu_store_flag_status = 0x200, // TSFR 13.45 + Tcu_store_set_flag = 0x204, // TSFSR 13.46 + Tcu_store_clear_flag = 0x208, // TSFCR 13.47 + Tcu_store_mask_status = 0x210, // TSMR 13.48 + Tcu_store_set_mask = 0x214, // TSMSR 13.49 + Tcu_store_clear_mask = 0x218, // TSMCR 13.50 + 13.51 + Tcu_capture_control_base = 0x0c0, // TCRn 13.52 + Tcu_capture_counter_base = 0x0e0, // CAPVRn 13.53 + Tcu_filter_value_base = 0x1a0, // FIRVRn 13.54 + Tcu_stored_counter_base = 0x220, // TSVRn 13.55 + Tcu_stored_filter_counter_base = 0x240, // TSFVRn 13.56 + 13.57 + // Block size/step/offset for the above register set. 13.58 + 13.59 + Tcu_capture_block_offset = 0x004, 13.60 + 13.61 + // Limits. 13.62 + 13.63 + Tcu_capture_channel_max = 3, 13.64 +}; 13.65 + 13.66 +// Field definitions. 13.67 + 13.68 +// Flag/mask register bits. 13.69 + 13.70 +enum Flag_bit_numbers : unsigned 13.71 +{ 13.72 + Half_match_wdt = 24, // HFLAGW 13.73 + 13.74 + // Flag/mask group bit offsets. 13.75 + 13.76 + Half_match_shift = 16, 13.77 + Full_match_shift = 0, 13.78 +}; 13.79 + 13.80 +// Counter data constraints. 13.81 + 13.82 +enum Data_masks : unsigned 13.83 +{ 13.84 + Data_mask = 0xffff, 13.85 +}; 13.86 + 13.87 +enum Control_bits_x1600 : unsigned 13.88 +{ 13.89 + Store_negative_edge_enable = 0x04000000, // STORE_NEG_EN 13.90 + Store_positive_edge_enable = 0x02000000, // STORE_POS_EN 13.91 + Store_enable = 0x01000000, // STORE_EN 13.92 + 13.93 + Count_mode_field_mask = 0x3, // COUNT_MODE 13.94 + Count_mode_wrap_at_full_data = 0, 13.95 + Count_mode_wrap_at_field_limit = 1, 13.96 + Count_mode_stop_at_field_limit = 2, 13.97 + Count_mode_field_shift = 22, 13.98 + 13.99 + Count_source_field_mask = 0x3f, 13.100 + Count_gpio1_negative_edge_enable = 0x20, // GPIO1_NEG_EN 13.101 + Count_gpio1_positive_edge_enable = 0x10, // GPIO1_POS_EN 13.102 + Count_gpio0_negative_edge_enable = 0x08, // GPIO0_NEG_EN 13.103 + Count_gpio0_positive_edge_enable = 0x04, // GPIO0_POS_EN 13.104 + Count_clock_negative_edge_enable = 0x02, // CLK_NEG_EN 13.105 + Count_clock_positive_edge_enable = 0x01, // CLK_POS_EN 13.106 + Count_source_field_shift = 16, 13.107 + 13.108 + Count_shutdown = 0x00008000, // SHUTDOWN 13.109 + Count_gate_polarity_low = 0x00000000, // GATE_POLA = 0 13.110 + Count_gate_polarity_high = 0x00004000, // GATE_POLA = 1 13.111 + Count_direction_polarity_low = 0x00000000, // DIRECTION_POLA = 0 13.112 + Count_direction_polarity_high = 0x00002000, // DIRECTION_POLA = 1 13.113 + 13.114 + Count_gate_select_field_mask = 0x3, // GATE_SEL 13.115 + Count_gate_select_none = 0, 13.116 + Count_gate_select_clock = 1, 13.117 + Count_gate_select_gpio0 = 2, 13.118 + Count_gate_select_gpio1 = 3, 13.119 + Count_gate_select_field_shift = 11, 13.120 + 13.121 + Count_direction_select_field_mask = 0x7, // DIRECTION_SEL 13.122 + Count_direction_select_none = 0, 13.123 + Count_direction_select_clock = 1, 13.124 + Count_direction_select_gpio0 = 2, 13.125 + Count_direction_select_gpio1 = 3, 13.126 + Count_direction_select_gpio01 = 4, 13.127 + Count_direction_select_field_shift = 8, 13.128 + 13.129 + Count_gpio1_enable = 0x00000080, // GPIO1_EN 13.130 + Count_gpio0_enable = 0x00000040, // GPIO0_EN 13.131 +}; 13.132 + 13.133 +enum Capture_bits : unsigned 13.134 +{ 13.135 + Capture_select_mask = 0x00070000, // CAPTURE_SEL 13.136 + Capture_select_clock = 0x00000000, // CAPTURE_SEL = 0 13.137 + Capture_select_gpio0 = 0x00010000, // CAPTURE_SEL = 1 13.138 + Capture_select_gpio1 = 0x00020000, // CAPTURE_SEL = 2 13.139 + Capture_count_mask = 0x000000ff, // CAPTURE_NUM 13.140 +}; 13.141 + 13.142 +enum Capture_value_bits : unsigned 13.143 +{ 13.144 + Capture_time_all_mask = 0xffff0000, // CAPTURE_ALL 13.145 + Capture_time_high_mask = 0x0000ffff, // CAPTURE_HEIGHT (sic) 13.146 +}; 13.147 + 13.148 +enum Filter_value_bits : unsigned 13.149 +{ 13.150 + Filter_gpio1_value_mask = 0x03ff0000, // FIL_B 13.151 + Filter_gpio0_value_mask = 0x000003ff, // FIL_A 13.152 +}; 13.153 + 13.154 +enum Store_filter_bits : unsigned 13.155 +{ 13.156 + Store_filter_value_mask = 0x3ff, // STR_FIL 13.157 +}; 13.158 + 13.159 + 13.160 + 13.161 +// Channel abstraction. 13.162 + 13.163 +Tcu_x1600_channel::Tcu_x1600_channel(l4_addr_t addr, uint8_t channel) 13.164 +: Tcu_channel(addr, channel) 13.165 +{ 13.166 +} 13.167 + 13.168 +// Operation methods. 13.169 + 13.170 +void 13.171 +Tcu_x1600_channel::enable() 13.172 +{ 13.173 + // NOTE: Use a positive clock edge for the timer event by default. 13.174 + 13.175 + set_field(Tcu_control_base + _channel * Tcu_data_block_offset, 13.176 + Count_source_field_mask, Count_source_field_shift, 13.177 + Count_clock_positive_edge_enable); 13.178 + 13.179 + Tcu_channel::enable(); 13.180 +} 13.181 + 13.182 +uint8_t 13.183 +Tcu_x1600_channel::get_count_mode() 13.184 +{ 13.185 + return get_field(Tcu_control_base + _channel * Tcu_data_block_offset, 13.186 + Count_mode_field_mask, Count_mode_field_shift); 13.187 +} 13.188 + 13.189 +void 13.190 +Tcu_x1600_channel::set_count_mode(uint8_t mode) 13.191 +{ 13.192 + set_field(Tcu_control_base + _channel * Tcu_data_block_offset, 13.193 + Count_mode_field_mask, Count_mode_field_shift, mode); 13.194 +} 13.195 + 13.196 + 13.197 + 13.198 +// Peripheral abstraction. 13.199 + 13.200 +Tcu_x1600_chip::Tcu_x1600_chip(l4_addr_t start, l4_addr_t end) 13.201 +: Tcu_chip(start, end) 13.202 +{ 13.203 +} 13.204 + 13.205 +Tcu_channel *Tcu_x1600_chip::_get_channel(l4_addr_t addr, uint8_t channel) 13.206 +{ 13.207 + return new Tcu_x1600_channel(addr, channel); 13.208 +} 13.209 + 13.210 + 13.211 + 13.212 +// C language interface functions. 13.213 + 13.214 +void *x1600_tcu_init(l4_addr_t tcu_base, l4_addr_t tcu_base_end) 13.215 +{ 13.216 + return (void *) new Tcu_x1600_chip(tcu_base, tcu_base_end); 13.217 +} 13.218 + 13.219 +void *x1600_tcu_get_channel(void *tcu, uint8_t channel) 13.220 +{ 13.221 + return static_cast<Tcu_x1600_chip *>(tcu)->get_channel(channel); 13.222 +} 13.223 + 13.224 +void x1600_tcu_disable(void *tcu_channel) 13.225 +{ 13.226 + static_cast<Tcu_x1600_channel *>(tcu_channel)->disable(); 13.227 +} 13.228 + 13.229 +void x1600_tcu_enable(void *tcu_channel) 13.230 +{ 13.231 + static_cast<Tcu_x1600_channel *>(tcu_channel)->enable(); 13.232 +} 13.233 + 13.234 +int x1600_tcu_is_enabled(void *tcu_channel) 13.235 +{ 13.236 + return static_cast<Tcu_x1600_channel *>(tcu_channel)->is_enabled(); 13.237 +} 13.238 + 13.239 +uint8_t x1600_tcu_get_clock(void *tcu_channel) 13.240 +{ 13.241 + return static_cast<Tcu_x1600_channel *>(tcu_channel)->get_clock(); 13.242 +} 13.243 + 13.244 +void x1600_tcu_set_clock(void *tcu_channel, uint8_t clock) 13.245 +{ 13.246 + static_cast<Tcu_x1600_channel *>(tcu_channel)->set_clock(clock); 13.247 +} 13.248 + 13.249 +uint32_t x1600_tcu_get_prescale(void *tcu_channel) 13.250 +{ 13.251 + return static_cast<Tcu_x1600_channel *>(tcu_channel)->get_prescale(); 13.252 +} 13.253 + 13.254 +void x1600_tcu_set_prescale(void *tcu_channel, uint32_t prescale) 13.255 +{ 13.256 + static_cast<Tcu_x1600_channel *>(tcu_channel)->set_prescale(prescale); 13.257 +} 13.258 + 13.259 +uint32_t x1600_tcu_get_counter(void *tcu_channel) 13.260 +{ 13.261 + return static_cast<Tcu_x1600_channel *>(tcu_channel)->get_counter(); 13.262 +} 13.263 + 13.264 +void x1600_tcu_set_counter(void *tcu_channel, uint32_t value) 13.265 +{ 13.266 + static_cast<Tcu_x1600_channel *>(tcu_channel)->set_counter(value); 13.267 +} 13.268 + 13.269 +uint8_t x1600_tcu_get_count_mode(void *tcu_channel) 13.270 +{ 13.271 + return static_cast<Tcu_x1600_channel *>(tcu_channel)->get_count_mode(); 13.272 +} 13.273 + 13.274 +void x1600_tcu_set_count_mode(void *tcu_channel, uint8_t mode) 13.275 +{ 13.276 + static_cast<Tcu_x1600_channel *>(tcu_channel)->set_count_mode(mode); 13.277 +} 13.278 + 13.279 +uint32_t x1600_tcu_get_full_data_value(void *tcu_channel) 13.280 +{ 13.281 + return static_cast<Tcu_x1600_channel *>(tcu_channel)->get_full_data_value(); 13.282 +} 13.283 + 13.284 +void x1600_tcu_set_full_data_value(void *tcu_channel, uint32_t value) 13.285 +{ 13.286 + static_cast<Tcu_x1600_channel *>(tcu_channel)->set_full_data_value(value); 13.287 +} 13.288 + 13.289 +uint32_t x1600_tcu_get_half_data_value(void *tcu_channel) 13.290 +{ 13.291 + return static_cast<Tcu_x1600_channel *>(tcu_channel)->get_half_data_value(); 13.292 +} 13.293 + 13.294 +void x1600_tcu_set_half_data_value(void *tcu_channel, uint32_t value) 13.295 +{ 13.296 + static_cast<Tcu_x1600_channel *>(tcu_channel)->set_full_data_value(value); 13.297 +}