# HG changeset patch # User Paul Boddie # Date 1706823776 -3600 # Node ID d7e274394389194ed1fc1b9d57cae78a9de6d704 # Parent 8bda1afbc1f5fd4a5d01fba3ce9510b1f277f88f Added TCU support to the hw_info program. diff -r 8bda1afbc1f5 -r d7e274394389 pkg/landfall-examples/hw_info/Makefile --- a/pkg/landfall-examples/hw_info/Makefile Thu Feb 01 22:41:30 2024 +0100 +++ b/pkg/landfall-examples/hw_info/Makefile Thu Feb 01 22:42:56 2024 +0100 @@ -7,6 +7,7 @@ REQUIRES_LIBS = \ libio l4re_c-util libdrivers-aic libdrivers-cpm \ libdrivers-dma libdrivers-gpio libdrivers-i2c \ - libdrivers-rtc libdrivers-spi libdevice-util + libdrivers-rtc libdrivers-spi libdrivers-tcu \ + libdevice-util include $(L4DIR)/mk/prog.mk diff -r 8bda1afbc1f5 -r d7e274394389 pkg/landfall-examples/hw_info/common.h --- a/pkg/landfall-examples/hw_info/common.h Thu Feb 01 22:41:30 2024 +0100 +++ b/pkg/landfall-examples/hw_info/common.h Thu Feb 01 22:42:56 2024 +0100 @@ -1,7 +1,8 @@ /* - * Access various peripherals on a board. + * Common definitions and adapter function signatures for access to + * board-specific functionality. * - * Copyright (C) 2023 Paul Boddie + * Copyright (C) 2023, 2024 Paul Boddie * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as @@ -222,11 +223,61 @@ +/* TCU adapter functions. */ + +void *tcu_init(l4_addr_t start, l4_addr_t end); + +void *tcu_get_channel(void *tcu, uint8_t channel, l4_cap_idx_t irq); + +void tcu_disable(void *tcu_channel); + +void tcu_enable(void *tcu_channel); + +int tcu_is_enabled(void *tcu_channel); + +uint8_t tcu_get_clock(void *tcu_channel); + +void tcu_set_clock(void *tcu_channel, uint8_t clock); + +uint32_t tcu_get_prescale(void *tcu_channel); + +void tcu_set_prescale(void *tcu_channel, uint32_t prescale); + +uint32_t tcu_get_counter(void *tcu_channel); + +void tcu_set_counter(void *tcu_channel, uint32_t value); + +uint8_t tcu_get_count_mode(void *tcu_channel); + +void tcu_set_count_mode(void *tcu_channel, uint8_t mode); + +uint32_t tcu_get_full_data_value(void *tcu_channel); + +void tcu_set_full_data_value(void *tcu_channel, uint32_t value); + +uint32_t tcu_get_half_data_value(void *tcu_channel); + +void tcu_set_half_data_value(void *tcu_channel, uint32_t value); + +int tcu_get_full_data_mask(void *tcu_channel); + +void tcu_set_full_data_mask(void *tcu_channel, int masked); + +int tcu_get_half_data_mask(void *tcu_channel); + +void tcu_set_half_data_mask(void *tcu_channel, int masked); + +int tcu_have_interrupt(void *tcu_channel); + +int tcu_wait_for_irq(void *tcu_channel, uint32_t timeout); + + + /* Memory regions. */ enum memory_regions { - AIC, CPM, DMA, GPIO, I2C, RTC, SSI + AIC, CPM, DMA, GPIO, I2C, RTC, SSI, TCU }; diff -r 8bda1afbc1f5 -r d7e274394389 pkg/landfall-examples/hw_info/defs.h --- a/pkg/landfall-examples/hw_info/defs.h Thu Feb 01 22:41:30 2024 +0100 +++ b/pkg/landfall-examples/hw_info/defs.h Thu Feb 01 22:42:56 2024 +0100 @@ -1,7 +1,7 @@ /* * Common declarations for chip-specific definitions. * - * Copyright (C) 2023 Paul Boddie + * Copyright (C) 2023, 2024 Paul Boddie * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as @@ -86,3 +86,13 @@ extern void *spi_channels[]; extern const unsigned int num_spi_channels; + + + +/* TCU definitions. */ + +extern void *tcu_channels[]; + +extern const unsigned int num_tcu_channels; + +extern l4_cap_idx_t tcu_irq; diff -r 8bda1afbc1f5 -r d7e274394389 pkg/landfall-examples/hw_info/hw_info.c --- a/pkg/landfall-examples/hw_info/hw_info.c Thu Feb 01 22:41:30 2024 +0100 +++ b/pkg/landfall-examples/hw_info/hw_info.c Thu Feb 01 22:42:56 2024 +0100 @@ -1,7 +1,7 @@ /* * Access various peripherals on the MIPS Creator CI20 board. * - * Copyright (C) 2023 Paul Boddie + * Copyright (C) 2023, 2024 Paul Boddie * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as @@ -248,9 +248,10 @@ static int get_memory_region(unsigned int size, l4_addr_t *addr) { - *addr = (l4_addr_t) calloc(size, sizeof(char)); - - return !(*addr); + void *a = calloc(size, sizeof(char)); + + *addr = (l4_addr_t) a; + return a == NULL ? 1 : 0; } @@ -897,8 +898,6 @@ unsigned int num; void *channel; - printf("i2c: channel\n\n"); - for (num = 0; num < num_i2c_channels; num++) { printf("Channel %d: ", num); @@ -1325,6 +1324,233 @@ +/* TCU configuration. */ + +static l4_uint32_t tcu_irq_start = 0, tcu_irq_end = 0; + +/* TCU operations. */ + +static int init_tcu(void) +{ + /* Here, only one IRQ is used. */ + + tcu_irq = l4re_util_cap_alloc(); + return init_irq(0, tcu_irq, tcu_irq_start, tcu_irq_end); +} + +static void disable_tcu_counter(void) +{ + int num = get_channel_number(num_tcu_channels); + void *channel; + + if (num < 0) + return; + + channel = tcu_channels[num]; + + if (channel == NULL) + return; + + tcu_disable(channel); +} + +static void enable_tcu_counter(void) +{ + int num = get_channel_number(num_tcu_channels); + void *channel; + + if (num < 0) + return; + + channel = tcu_channels[num]; + + if (channel == NULL) + return; + + tcu_enable(channel); +} + +static void new_tcu_channel(void *tcu) +{ + int num = get_channel_number(num_tcu_channels); + + if (num < 0) + return; + + tcu_channels[num] = tcu_get_channel(tcu, num, tcu_irq); +} + +static void list_tcu_channels(void) +{ + unsigned int num; + void *channel; + + printf(" Clock.. Counter......... Mask..............\n"); + printf("Channel Status C Pre Cnt Half Full Half Full Int\n"); + + for (num = 0; num < num_tcu_channels; num++) + { + printf("%d ", num); + + channel = tcu_channels[num]; + + if (channel == NULL) + printf("inactive\n"); + else + printf("%s %d %4d %04x %04x %04x %s %s %s\n", + tcu_is_enabled(channel) ? "enabled " : "disabled", + tcu_get_clock(channel), + tcu_get_prescale(channel), + tcu_get_counter(channel), + tcu_get_half_data_value(channel), + tcu_get_full_data_value(channel), + tcu_get_half_data_mask(channel) ? "masked " : "unmasked", + tcu_get_full_data_mask(channel) ? "masked " : "unmasked", + tcu_have_interrupt(channel) ? "!" : "_"); + } +} + +static void set_tcu_counter(void) +{ + int num = get_channel_number(num_tcu_channels); + void *channel; + uint32_t counter; + + if (num < 0) + return; + + channel = tcu_channels[num]; + + if (channel == NULL) + return; + + if (!read_number("Value", &counter)) + return; + + tcu_set_counter(channel, counter); +} + +static void set_tcu_clock(void) +{ + int num = get_channel_number(num_tcu_channels); + void *channel; + uint32_t clock; + + if (num < 0) + return; + + channel = tcu_channels[num]; + + if (channel == NULL) + return; + + if (!read_number("Clock", &clock)) + return; + + tcu_set_clock(channel, clock); +} + +static void set_tcu_full(void) +{ + int num = get_channel_number(num_tcu_channels); + void *channel; + uint32_t value; + + if (num < 0) + return; + + channel = tcu_channels[num]; + + if (channel == NULL) + return; + + if (!read_number("Full value", &value)) + return; + + tcu_set_full_data_value(channel, value); +} + +static void set_tcu_half(void) +{ + int num = get_channel_number(num_tcu_channels); + void *channel; + uint32_t value; + + if (num < 0) + return; + + channel = tcu_channels[num]; + + if (channel == NULL) + return; + + if (!read_number("Half value", &value)) + return; + + tcu_set_half_data_value(channel, value); +} + +static void set_tcu_mask(int full_mask, int masked) +{ + int num = get_channel_number(num_tcu_channels); + void *channel; + + if (num < 0) + return; + + channel = tcu_channels[num]; + + if (channel == NULL) + return; + + if (full_mask) + tcu_set_full_data_mask(channel, masked); + else + tcu_set_half_data_mask(channel, masked); +} + +static void set_tcu_prescale(void) +{ + int num = get_channel_number(num_tcu_channels); + void *channel; + uint32_t prescale; + + if (num < 0) + return; + + channel = tcu_channels[num]; + + if (channel == NULL) + return; + + if (!read_number("Prescale", &prescale)) + return; + + tcu_set_prescale(channel, prescale); +} + +static void tcu_wait(void) +{ + int num = get_channel_number(num_tcu_channels); + void *channel; + uint32_t timeout; + + if (num < 0) + return; + + channel = tcu_channels[num]; + + if (channel == NULL) + return; + + if (!read_number("Timeout", &timeout)) + return; + + printf("IRQ received: %s\n", tcu_wait_for_irq(channel, timeout) ? "yes" : "no"); +} + + + /* Command processing. */ static void handle_aic(void *aic) @@ -1511,6 +1737,49 @@ list_channels(num_spi_channels, spi_channels); } +static void handle_tcu(void *tcu) +{ + char *token; + + if ((token = read_token(NULL)) != NULL) + { + if (!strcmp(token, "l") || !strcmp(token, "list")) + list_tcu_channels(); + else if (!strcmp(token, "c") || !strcmp(token, "channel")) + new_tcu_channel(tcu); + else if (!strcmp(token, "C") || !strcmp(token, "clock")) + set_tcu_clock(); + else if (!strcmp(token, "d") || !strcmp(token, "disable")) + disable_tcu_counter(); + else if (!strcmp(token, "e") || !strcmp(token, "enable")) + enable_tcu_counter(); + else if (!strcmp(token, "f") || !strcmp(token, "full")) + set_tcu_full(); + else if (!strcmp(token, "fm") || !strcmp(token, "full-mask")) + set_tcu_mask(1, 1); + else if (!strcmp(token, "fu") || !strcmp(token, "full-unmask")) + set_tcu_mask(1, 0); + else if (!strcmp(token, "h") || !strcmp(token, "half")) + set_tcu_half(); + else if (!strcmp(token, "hm") || !strcmp(token, "half-mask")) + set_tcu_mask(0, 1); + else if (!strcmp(token, "hu") || !strcmp(token, "half-unmask")) + set_tcu_mask(0, 0); + else if (!strcmp(token, "p") || !strcmp(token, "prescale")) + set_tcu_prescale(); + else if (!strcmp(token, "s") || !strcmp(token, "set")) + set_tcu_counter(); + else if (!strcmp(token, "w") || !strcmp(token, "wait")) + tcu_wait(); + else + printf("tcu channel | clock | disable | enable | full | full-mask | " \ + "full-unmask | half | half-mask | half-unmask | list | mask | " \ + "prescale | set | unmask | wait\n"); + } + else + list_tcu_channels(); +} + int main(void) @@ -1524,7 +1793,8 @@ l4_addr_t rtc_base = 0, rtc_base_end = 0; l4_addr_t ssi_base = 0, ssi_base_end = 0; l4_addr_t ssi_phys_base = 0, ssi_phys_base_end = 0; - void *aic, *cpm, *dma, *gpio[num_gpio_ports], *i2c, *rtc, *spi; + l4_addr_t tcu_base = 0, tcu_base_end = 0; + void *aic, *cpm, *dma, *gpio[num_gpio_ports], *i2c, *rtc, *spi, *tcu; int result = 0; unsigned int port; @@ -1614,9 +1884,26 @@ spi = spi_init(ssi_phys_base, ssi_base, ssi_base_end, cpm); + printf("Access TCU...\n"); + + if ((result = get_memory(io_memory_regions[TCU], &tcu_base, &tcu_base_end)) < 0) + return 1; + + printf("TCU at 0x%lx...0x%lx.\n", tcu_base, tcu_base_end); + + tcu = tcu_init(tcu_base, tcu_base_end); + + if (get_irq(io_memory_regions[TCU], &tcu_irq_start, &tcu_irq_end) < 0) + return 1; + + printf("IRQ range at %d...%d.\n", tcu_irq_start, tcu_irq_end); + + if (init_tcu()) + return 1; + /* Start the interactive session. */ - printf("aic, cpm, dma, gpio, i2c, rtc, spi\n"); + printf("aic, cpm, dma, gpio, i2c, rtc, spi, tcu\n"); while (1) { @@ -1672,6 +1959,11 @@ else if (!strcmp(token, "s") || !strcmp(token, "spi")) handle_spi(spi, gpio); + /* TCU commands. */ + + else if (!strcmp(token, "t") || !strcmp(token, "tcu")) + handle_tcu(tcu); + /* Comments and blank lines. */ else if (strncmp(token, "#", 1) && strlen(token)) diff -r 8bda1afbc1f5 -r d7e274394389 pkg/landfall-examples/hw_info/jz4780.c --- a/pkg/landfall-examples/hw_info/jz4780.c Thu Feb 01 22:41:30 2024 +0100 +++ b/pkg/landfall-examples/hw_info/jz4780.c Thu Feb 01 22:42:56 2024 +0100 @@ -39,6 +39,7 @@ #include #include #include +#include #include "common.h" @@ -462,6 +463,125 @@ +/* TCU adapter functions. */ + +void *tcu_init(l4_addr_t start, l4_addr_t end) +{ + return jz4780_tcu_init(start, end); +} + +void *tcu_get_channel(void *tcu, uint8_t channel, l4_cap_idx_t irq) +{ + return jz4780_tcu_get_channel(tcu, channel, irq); +} + +void tcu_disable(void *tcu_channel) +{ + jz4780_tcu_disable(tcu_channel); +} + +void tcu_enable(void *tcu_channel) +{ + jz4780_tcu_enable(tcu_channel); +} + +int tcu_is_enabled(void *tcu_channel) +{ + return jz4780_tcu_is_enabled(tcu_channel); +} + +uint8_t tcu_get_clock(void *tcu_channel) +{ + return jz4780_tcu_get_clock(tcu_channel); +} + +void tcu_set_clock(void *tcu_channel, uint8_t clock) +{ + jz4780_tcu_set_clock(tcu_channel, clock); +} + +uint32_t tcu_get_prescale(void *tcu_channel) +{ + return jz4780_tcu_get_prescale(tcu_channel); +} + +void tcu_set_prescale(void *tcu_channel, uint32_t prescale) +{ + jz4780_tcu_set_prescale(tcu_channel, prescale); +} + +uint32_t tcu_get_counter(void *tcu_channel) +{ + return jz4780_tcu_get_counter(tcu_channel); +} + +void tcu_set_counter(void *tcu_channel, uint32_t value) +{ + jz4780_tcu_set_counter(tcu_channel, value); +} + +uint8_t tcu_get_count_mode(void *tcu_channel) +{ + return jz4780_tcu_get_count_mode(tcu_channel); +} + +void tcu_set_count_mode(void *tcu_channel, uint8_t mode) +{ + jz4780_tcu_set_count_mode(tcu_channel, mode); +} + +uint32_t tcu_get_full_data_value(void *tcu_channel) +{ + return jz4780_tcu_get_full_data_value(tcu_channel); +} + +void tcu_set_full_data_value(void *tcu_channel, uint32_t value) +{ + jz4780_tcu_set_full_data_value(tcu_channel, value); +} + +uint32_t tcu_get_half_data_value(void *tcu_channel) +{ + return jz4780_tcu_get_half_data_value(tcu_channel); +} + +void tcu_set_half_data_value(void *tcu_channel, uint32_t value) +{ + jz4780_tcu_set_half_data_value(tcu_channel, value); +} + +int tcu_get_full_data_mask(void *tcu_channel) +{ + return jz4780_tcu_get_full_data_mask(tcu_channel); +} + +void tcu_set_full_data_mask(void *tcu_channel, int masked) +{ + jz4780_tcu_set_full_data_mask(tcu_channel, masked); +} + +int tcu_get_half_data_mask(void *tcu_channel) +{ + return jz4780_tcu_get_half_data_mask(tcu_channel); +} + +void tcu_set_half_data_mask(void *tcu_channel, int masked) +{ + jz4780_tcu_set_half_data_mask(tcu_channel, masked); +} + +int tcu_have_interrupt(void *tcu_channel) +{ + return jz4780_tcu_have_interrupt(tcu_channel); +} + +int tcu_wait_for_irq(void *tcu_channel, uint32_t timeout) +{ + return jz4780_tcu_wait_for_irq(tcu_channel, timeout); +} + + + /* Memory regions. */ const char *io_memory_regions[] = { @@ -472,6 +592,7 @@ [I2C] = "jz4780-i2c", [RTC] = "jz4780-rtc", [SSI] = "jz4780-ssi", + [TCU] = "jz4780-tcu", }; @@ -583,3 +704,13 @@ void *spi_channels[] = {NULL, NULL}; const unsigned int num_spi_channels = 2; + + + +/* TCU definitions. */ + +void *tcu_channels[] = {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL}; + +const unsigned int num_tcu_channels = 8; + +l4_cap_idx_t tcu_irq = L4_INVALID_CAP; diff -r 8bda1afbc1f5 -r d7e274394389 pkg/landfall-examples/hw_info/x1600.c --- a/pkg/landfall-examples/hw_info/x1600.c Thu Feb 01 22:41:30 2024 +0100 +++ b/pkg/landfall-examples/hw_info/x1600.c Thu Feb 01 22:42:56 2024 +0100 @@ -1,7 +1,7 @@ /* * Access various peripherals on a board using the X1600. * - * Copyright (C) 2023 Paul Boddie + * Copyright (C) 2023, 2024 Paul Boddie * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as @@ -28,6 +28,7 @@ #include #include #include +#include #include "common.h" @@ -448,6 +449,125 @@ +/* TCU adapter functions. */ + +void *tcu_init(l4_addr_t start, l4_addr_t end) +{ + return x1600_tcu_init(start, end); +} + +void *tcu_get_channel(void *tcu, uint8_t channel, l4_cap_idx_t irq) +{ + return x1600_tcu_get_channel(tcu, channel, irq); +} + +void tcu_disable(void *tcu_channel) +{ + x1600_tcu_disable(tcu_channel); +} + +void tcu_enable(void *tcu_channel) +{ + x1600_tcu_enable(tcu_channel); +} + +int tcu_is_enabled(void *tcu_channel) +{ + return x1600_tcu_is_enabled(tcu_channel); +} + +uint8_t tcu_get_clock(void *tcu_channel) +{ + return x1600_tcu_get_clock(tcu_channel); +} + +void tcu_set_clock(void *tcu_channel, uint8_t clock) +{ + x1600_tcu_set_clock(tcu_channel, clock); +} + +uint32_t tcu_get_prescale(void *tcu_channel) +{ + return x1600_tcu_get_prescale(tcu_channel); +} + +void tcu_set_prescale(void *tcu_channel, uint32_t prescale) +{ + x1600_tcu_set_prescale(tcu_channel, prescale); +} + +uint32_t tcu_get_counter(void *tcu_channel) +{ + return x1600_tcu_get_counter(tcu_channel); +} + +void tcu_set_counter(void *tcu_channel, uint32_t value) +{ + x1600_tcu_set_counter(tcu_channel, value); +} + +uint8_t tcu_get_count_mode(void *tcu_channel) +{ + return x1600_tcu_get_count_mode(tcu_channel); +} + +void tcu_set_count_mode(void *tcu_channel, uint8_t mode) +{ + x1600_tcu_set_count_mode(tcu_channel, mode); +} + +uint32_t tcu_get_full_data_value(void *tcu_channel) +{ + return x1600_tcu_get_full_data_value(tcu_channel); +} + +void tcu_set_full_data_value(void *tcu_channel, uint32_t value) +{ + x1600_tcu_set_full_data_value(tcu_channel, value); +} + +uint32_t tcu_get_half_data_value(void *tcu_channel) +{ + return x1600_tcu_get_half_data_value(tcu_channel); +} + +void tcu_set_half_data_value(void *tcu_channel, uint32_t value) +{ + x1600_tcu_set_half_data_value(tcu_channel, value); +} + +int tcu_get_full_data_mask(void *tcu_channel) +{ + return x1600_tcu_get_full_data_mask(tcu_channel); +} + +void tcu_set_full_data_mask(void *tcu_channel, int masked) +{ + x1600_tcu_set_full_data_mask(tcu_channel, masked); +} + +int tcu_get_half_data_mask(void *tcu_channel) +{ + return x1600_tcu_get_half_data_mask(tcu_channel); +} + +void tcu_set_half_data_mask(void *tcu_channel, int masked) +{ + x1600_tcu_set_half_data_mask(tcu_channel, masked); +} + +int tcu_have_interrupt(void *tcu_channel) +{ + return x1600_tcu_have_interrupt(tcu_channel); +} + +int tcu_wait_for_irq(void *tcu_channel, uint32_t timeout) +{ + return x1600_tcu_wait_for_irq(tcu_channel, timeout); +} + + + /* Memory regions. */ const char *io_memory_regions[] = { @@ -458,6 +578,7 @@ [I2C] = "x1600-i2c", [RTC] = "x1600-rtc", [SSI] = "x1600-ssi", + [TCU] = "x1600-tcu", }; @@ -555,3 +676,13 @@ void *spi_channels[] = {NULL}; const unsigned int num_spi_channels = 1; + + + +/* TCU definitions. */ + +void *tcu_channels[] = {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL}; + +const unsigned int num_tcu_channels = 8; + +l4_cap_idx_t tcu_irq = L4_INVALID_CAP;