1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/pkg/devices/lib/tcu/src/x1600.cc Thu Feb 01 01:16:04 2024 +0100
1.3 @@ -0,0 +1,294 @@
1.4 +/*
1.5 + * Timer/counter unit support.
1.6 + *
1.7 + * Copyright (C) 2024 Paul Boddie <paul@boddie.org.uk>
1.8 + *
1.9 + * This program is free software; you can redistribute it and/or
1.10 + * modify it under the terms of the GNU General Public License as
1.11 + * published by the Free Software Foundation; either version 2 of
1.12 + * the License, or (at your option) any later version.
1.13 + *
1.14 + * This program is distributed in the hope that it will be useful,
1.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
1.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1.17 + * GNU General Public License for more details.
1.18 + *
1.19 + * You should have received a copy of the GNU General Public License
1.20 + * along with this program; if not, write to the Free Software
1.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor,
1.22 + * Boston, MA 02110-1301, USA
1.23 + */
1.24 +
1.25 +#include "tcu-x1600.h"
1.26 +
1.27 +
1.28 +
1.29 +// Register locations.
1.30 +
1.31 +enum Regs : unsigned
1.32 +{
1.33 + Tcu_control_base = 0x04c, // TCRn
1.34 +
1.35 + // Block size/step/offset for the above register set.
1.36 +
1.37 + Tcu_data_block_offset = 0x010,
1.38 +};
1.39 +
1.40 +enum Regs_x1600 : unsigned
1.41 +{
1.42 + // X1600 channel-related locations.
1.43 +
1.44 + Tcu_store_flag_status = 0x200, // TSFR
1.45 + Tcu_store_set_flag = 0x204, // TSFSR
1.46 + Tcu_store_clear_flag = 0x208, // TSFCR
1.47 + Tcu_store_mask_status = 0x210, // TSMR
1.48 + Tcu_store_set_mask = 0x214, // TSMSR
1.49 + Tcu_store_clear_mask = 0x218, // TSMCR
1.50 +
1.51 + Tcu_capture_control_base = 0x0c0, // TCRn
1.52 + Tcu_capture_counter_base = 0x0e0, // CAPVRn
1.53 + Tcu_filter_value_base = 0x1a0, // FIRVRn
1.54 + Tcu_stored_counter_base = 0x220, // TSVRn
1.55 + Tcu_stored_filter_counter_base = 0x240, // TSFVRn
1.56 +
1.57 + // Block size/step/offset for the above register set.
1.58 +
1.59 + Tcu_capture_block_offset = 0x004,
1.60 +
1.61 + // Limits.
1.62 +
1.63 + Tcu_capture_channel_max = 3,
1.64 +};
1.65 +
1.66 +// Field definitions.
1.67 +
1.68 +// Flag/mask register bits.
1.69 +
1.70 +enum Flag_bit_numbers : unsigned
1.71 +{
1.72 + Half_match_wdt = 24, // HFLAGW
1.73 +
1.74 + // Flag/mask group bit offsets.
1.75 +
1.76 + Half_match_shift = 16,
1.77 + Full_match_shift = 0,
1.78 +};
1.79 +
1.80 +// Counter data constraints.
1.81 +
1.82 +enum Data_masks : unsigned
1.83 +{
1.84 + Data_mask = 0xffff,
1.85 +};
1.86 +
1.87 +enum Control_bits_x1600 : unsigned
1.88 +{
1.89 + Store_negative_edge_enable = 0x04000000, // STORE_NEG_EN
1.90 + Store_positive_edge_enable = 0x02000000, // STORE_POS_EN
1.91 + Store_enable = 0x01000000, // STORE_EN
1.92 +
1.93 + Count_mode_field_mask = 0x3, // COUNT_MODE
1.94 + Count_mode_wrap_at_full_data = 0,
1.95 + Count_mode_wrap_at_field_limit = 1,
1.96 + Count_mode_stop_at_field_limit = 2,
1.97 + Count_mode_field_shift = 22,
1.98 +
1.99 + Count_source_field_mask = 0x3f,
1.100 + Count_gpio1_negative_edge_enable = 0x20, // GPIO1_NEG_EN
1.101 + Count_gpio1_positive_edge_enable = 0x10, // GPIO1_POS_EN
1.102 + Count_gpio0_negative_edge_enable = 0x08, // GPIO0_NEG_EN
1.103 + Count_gpio0_positive_edge_enable = 0x04, // GPIO0_POS_EN
1.104 + Count_clock_negative_edge_enable = 0x02, // CLK_NEG_EN
1.105 + Count_clock_positive_edge_enable = 0x01, // CLK_POS_EN
1.106 + Count_source_field_shift = 16,
1.107 +
1.108 + Count_shutdown = 0x00008000, // SHUTDOWN
1.109 + Count_gate_polarity_low = 0x00000000, // GATE_POLA = 0
1.110 + Count_gate_polarity_high = 0x00004000, // GATE_POLA = 1
1.111 + Count_direction_polarity_low = 0x00000000, // DIRECTION_POLA = 0
1.112 + Count_direction_polarity_high = 0x00002000, // DIRECTION_POLA = 1
1.113 +
1.114 + Count_gate_select_field_mask = 0x3, // GATE_SEL
1.115 + Count_gate_select_none = 0,
1.116 + Count_gate_select_clock = 1,
1.117 + Count_gate_select_gpio0 = 2,
1.118 + Count_gate_select_gpio1 = 3,
1.119 + Count_gate_select_field_shift = 11,
1.120 +
1.121 + Count_direction_select_field_mask = 0x7, // DIRECTION_SEL
1.122 + Count_direction_select_none = 0,
1.123 + Count_direction_select_clock = 1,
1.124 + Count_direction_select_gpio0 = 2,
1.125 + Count_direction_select_gpio1 = 3,
1.126 + Count_direction_select_gpio01 = 4,
1.127 + Count_direction_select_field_shift = 8,
1.128 +
1.129 + Count_gpio1_enable = 0x00000080, // GPIO1_EN
1.130 + Count_gpio0_enable = 0x00000040, // GPIO0_EN
1.131 +};
1.132 +
1.133 +enum Capture_bits : unsigned
1.134 +{
1.135 + Capture_select_mask = 0x00070000, // CAPTURE_SEL
1.136 + Capture_select_clock = 0x00000000, // CAPTURE_SEL = 0
1.137 + Capture_select_gpio0 = 0x00010000, // CAPTURE_SEL = 1
1.138 + Capture_select_gpio1 = 0x00020000, // CAPTURE_SEL = 2
1.139 + Capture_count_mask = 0x000000ff, // CAPTURE_NUM
1.140 +};
1.141 +
1.142 +enum Capture_value_bits : unsigned
1.143 +{
1.144 + Capture_time_all_mask = 0xffff0000, // CAPTURE_ALL
1.145 + Capture_time_high_mask = 0x0000ffff, // CAPTURE_HEIGHT (sic)
1.146 +};
1.147 +
1.148 +enum Filter_value_bits : unsigned
1.149 +{
1.150 + Filter_gpio1_value_mask = 0x03ff0000, // FIL_B
1.151 + Filter_gpio0_value_mask = 0x000003ff, // FIL_A
1.152 +};
1.153 +
1.154 +enum Store_filter_bits : unsigned
1.155 +{
1.156 + Store_filter_value_mask = 0x3ff, // STR_FIL
1.157 +};
1.158 +
1.159 +
1.160 +
1.161 +// Channel abstraction.
1.162 +
1.163 +Tcu_x1600_channel::Tcu_x1600_channel(l4_addr_t addr, uint8_t channel)
1.164 +: Tcu_channel(addr, channel)
1.165 +{
1.166 +}
1.167 +
1.168 +// Operation methods.
1.169 +
1.170 +void
1.171 +Tcu_x1600_channel::enable()
1.172 +{
1.173 + // NOTE: Use a positive clock edge for the timer event by default.
1.174 +
1.175 + set_field(Tcu_control_base + _channel * Tcu_data_block_offset,
1.176 + Count_source_field_mask, Count_source_field_shift,
1.177 + Count_clock_positive_edge_enable);
1.178 +
1.179 + Tcu_channel::enable();
1.180 +}
1.181 +
1.182 +uint8_t
1.183 +Tcu_x1600_channel::get_count_mode()
1.184 +{
1.185 + return get_field(Tcu_control_base + _channel * Tcu_data_block_offset,
1.186 + Count_mode_field_mask, Count_mode_field_shift);
1.187 +}
1.188 +
1.189 +void
1.190 +Tcu_x1600_channel::set_count_mode(uint8_t mode)
1.191 +{
1.192 + set_field(Tcu_control_base + _channel * Tcu_data_block_offset,
1.193 + Count_mode_field_mask, Count_mode_field_shift, mode);
1.194 +}
1.195 +
1.196 +
1.197 +
1.198 +// Peripheral abstraction.
1.199 +
1.200 +Tcu_x1600_chip::Tcu_x1600_chip(l4_addr_t start, l4_addr_t end)
1.201 +: Tcu_chip(start, end)
1.202 +{
1.203 +}
1.204 +
1.205 +Tcu_channel *Tcu_x1600_chip::_get_channel(l4_addr_t addr, uint8_t channel)
1.206 +{
1.207 + return new Tcu_x1600_channel(addr, channel);
1.208 +}
1.209 +
1.210 +
1.211 +
1.212 +// C language interface functions.
1.213 +
1.214 +void *x1600_tcu_init(l4_addr_t tcu_base, l4_addr_t tcu_base_end)
1.215 +{
1.216 + return (void *) new Tcu_x1600_chip(tcu_base, tcu_base_end);
1.217 +}
1.218 +
1.219 +void *x1600_tcu_get_channel(void *tcu, uint8_t channel)
1.220 +{
1.221 + return static_cast<Tcu_x1600_chip *>(tcu)->get_channel(channel);
1.222 +}
1.223 +
1.224 +void x1600_tcu_disable(void *tcu_channel)
1.225 +{
1.226 + static_cast<Tcu_x1600_channel *>(tcu_channel)->disable();
1.227 +}
1.228 +
1.229 +void x1600_tcu_enable(void *tcu_channel)
1.230 +{
1.231 + static_cast<Tcu_x1600_channel *>(tcu_channel)->enable();
1.232 +}
1.233 +
1.234 +int x1600_tcu_is_enabled(void *tcu_channel)
1.235 +{
1.236 + return static_cast<Tcu_x1600_channel *>(tcu_channel)->is_enabled();
1.237 +}
1.238 +
1.239 +uint8_t x1600_tcu_get_clock(void *tcu_channel)
1.240 +{
1.241 + return static_cast<Tcu_x1600_channel *>(tcu_channel)->get_clock();
1.242 +}
1.243 +
1.244 +void x1600_tcu_set_clock(void *tcu_channel, uint8_t clock)
1.245 +{
1.246 + static_cast<Tcu_x1600_channel *>(tcu_channel)->set_clock(clock);
1.247 +}
1.248 +
1.249 +uint32_t x1600_tcu_get_prescale(void *tcu_channel)
1.250 +{
1.251 + return static_cast<Tcu_x1600_channel *>(tcu_channel)->get_prescale();
1.252 +}
1.253 +
1.254 +void x1600_tcu_set_prescale(void *tcu_channel, uint32_t prescale)
1.255 +{
1.256 + static_cast<Tcu_x1600_channel *>(tcu_channel)->set_prescale(prescale);
1.257 +}
1.258 +
1.259 +uint32_t x1600_tcu_get_counter(void *tcu_channel)
1.260 +{
1.261 + return static_cast<Tcu_x1600_channel *>(tcu_channel)->get_counter();
1.262 +}
1.263 +
1.264 +void x1600_tcu_set_counter(void *tcu_channel, uint32_t value)
1.265 +{
1.266 + static_cast<Tcu_x1600_channel *>(tcu_channel)->set_counter(value);
1.267 +}
1.268 +
1.269 +uint8_t x1600_tcu_get_count_mode(void *tcu_channel)
1.270 +{
1.271 + return static_cast<Tcu_x1600_channel *>(tcu_channel)->get_count_mode();
1.272 +}
1.273 +
1.274 +void x1600_tcu_set_count_mode(void *tcu_channel, uint8_t mode)
1.275 +{
1.276 + static_cast<Tcu_x1600_channel *>(tcu_channel)->set_count_mode(mode);
1.277 +}
1.278 +
1.279 +uint32_t x1600_tcu_get_full_data_value(void *tcu_channel)
1.280 +{
1.281 + return static_cast<Tcu_x1600_channel *>(tcu_channel)->get_full_data_value();
1.282 +}
1.283 +
1.284 +void x1600_tcu_set_full_data_value(void *tcu_channel, uint32_t value)
1.285 +{
1.286 + static_cast<Tcu_x1600_channel *>(tcu_channel)->set_full_data_value(value);
1.287 +}
1.288 +
1.289 +uint32_t x1600_tcu_get_half_data_value(void *tcu_channel)
1.290 +{
1.291 + return static_cast<Tcu_x1600_channel *>(tcu_channel)->get_half_data_value();
1.292 +}
1.293 +
1.294 +void x1600_tcu_set_half_data_value(void *tcu_channel, uint32_t value)
1.295 +{
1.296 + static_cast<Tcu_x1600_channel *>(tcu_channel)->set_full_data_value(value);
1.297 +}