# HG changeset patch # User Paul Boddie # Date 1698683100 -3600 # Node ID 77a993bd713fe66b13cbe8cdaa231957c96852b9 # Parent a410f6cd5dc8c81db069f38156df364f523d9dc4 Added a hardware inspection utility for the JZ4780 and X1600. diff -r a410f6cd5dc8 -r 77a993bd713f conf/landfall-examples/mips-jz4780-info.cfg --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/conf/landfall-examples/mips-jz4780-info.cfg Mon Oct 30 17:25:00 2023 +0100 @@ -0,0 +1,30 @@ +# this is a configuration to start 'ex_jz4780_info' + +local L4 = require("L4"); + +local l = L4.default_loader; + +local io_buses = + { + common = l:new_channel(); + }; + +l:start({ + caps = { + common = io_buses.common:svr(), + icu = L4.Env.icu, + sigma0 = L4.cast(L4.Proto.Factory, L4.Env.sigma0):create(L4.Proto.Sigma0), + }, + log = { "IO", "y" }, + l4re_dbg = L4.Dbg.Warn, + }, + "rom/io rom/hw_devices.io rom/mips-jz4780-info.io"); + +l:start({ + log = L4.Env.log, + caps = { + icu = L4.Env.icu, + vbus = io_buses.common, + }, + }, + "rom/ex_jz4780_info"); diff -r a410f6cd5dc8 -r 77a993bd713f conf/landfall-examples/mips-jz4780-info.io --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/conf/landfall-examples/mips-jz4780-info.io Mon Oct 30 17:25:00 2023 +0100 @@ -0,0 +1,15 @@ +-- vi:ft=lua +-- configuration file for io + +local hw = Io.system_bus() + +local bus = Io.Vi.System_bus +{ + AIC = wrap(hw:match("jz4780-aic")); + CPM = wrap(hw:match("jz4780-cpm")); + DMA = wrap(hw:match("jz4780-dma")); + GPIO = wrap(hw:match("jz4780-gpio")); + I2C = wrap(hw:match("jz4780-i2c")); +} + +Io.add_vbus("common", bus) diff -r a410f6cd5dc8 -r 77a993bd713f conf/landfall-examples/mips-jz4780-info.list --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/conf/landfall-examples/mips-jz4780-info.list Mon Oct 30 17:25:00 2023 +0100 @@ -0,0 +1,15 @@ + +modaddr 0x1100000 + +entry mips-jz4780-info-example +bootstrap bootstrap -serial +kernel fiasco -serial_esc +roottask moe rom/mips-jz4780-info.cfg +module mips-jz4780-info.cfg +module mips-jz4780-info.io +module plat-ingenic-jz4780/hw_devices.io +module l4re +module io +module ned +module ex_jz4780_info +module piano-3.raw diff -r a410f6cd5dc8 -r 77a993bd713f conf/landfall-examples/mips-x1600-info.cfg --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/conf/landfall-examples/mips-x1600-info.cfg Mon Oct 30 17:25:00 2023 +0100 @@ -0,0 +1,30 @@ +# this is a configuration to start 'ex_x1600_info' + +local L4 = require("L4"); + +local l = L4.default_loader; + +local io_buses = + { + common = l:new_channel(); + }; + +l:start({ + caps = { + common = io_buses.common:svr(), + icu = L4.Env.icu, + sigma0 = L4.cast(L4.Proto.Factory, L4.Env.sigma0):create(L4.Proto.Sigma0), + }, + log = { "IO", "y" }, + l4re_dbg = L4.Dbg.Warn, + }, + "rom/io rom/hw_devices.io rom/mips-x1600-info.io"); + +l:start({ + log = L4.Env.log, + caps = { + icu = L4.Env.icu, + vbus = io_buses.common, + }, + }, + "rom/ex_x1600_info"); diff -r a410f6cd5dc8 -r 77a993bd713f conf/landfall-examples/mips-x1600-info.io --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/conf/landfall-examples/mips-x1600-info.io Mon Oct 30 17:25:00 2023 +0100 @@ -0,0 +1,15 @@ +-- vi:ft=lua +-- configuration file for io + +local hw = Io.system_bus() + +local bus = Io.Vi.System_bus +{ + AIC = wrap(hw:match("x1600-aic")); + CPM = wrap(hw:match("x1600-cpm")); + DMA = wrap(hw:match("x1600-dma")); + GPIO = wrap(hw:match("x1600-gpio")); + I2C = wrap(hw:match("x1600-i2c")); +} + +Io.add_vbus("common", bus) diff -r a410f6cd5dc8 -r 77a993bd713f conf/landfall-examples/mips-x1600-info.list --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/conf/landfall-examples/mips-x1600-info.list Mon Oct 30 17:25:00 2023 +0100 @@ -0,0 +1,15 @@ + +modaddr 0x1100000 + +entry mips-x1600-info-example +bootstrap bootstrap -serial +kernel fiasco -serial_esc +roottask moe rom/mips-x1600-info.cfg +module mips-x1600-info.cfg +module mips-x1600-info.io +module plat-ingenic-x1600/hw_devices.io +module l4re +module io +module ned +module ex_x1600_info +module piano-3.raw diff -r a410f6cd5dc8 -r 77a993bd713f conf/landfall-examples/piano-3.raw Binary file conf/landfall-examples/piano-3.raw has changed diff -r a410f6cd5dc8 -r 77a993bd713f docs/COPYING.txt --- a/docs/COPYING.txt Mon Oct 30 17:24:21 2023 +0100 +++ b/docs/COPYING.txt Mon Oct 30 17:25:00 2023 +0100 @@ -4,7 +4,7 @@ All original work in this distribution is covered by the following copyright and licensing information: -Copyright (C) 2015, 2016, 2017, 2018 Paul Boddie +Copyright (C) 2015-2023 Paul Boddie This software is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as @@ -82,3 +82,27 @@ to your version of the font, but you are not obligated to do so. If you do not wish to do so, delete this exception statement from your version. + +---- + +The piano-3.raw sound file was generated as follows: + +sox -v 0.25 /usr/share/sounds/sound-icons/piano-3.wav conf/landfall-examples/piano-3.raw + +The original file is provided by the sound-icons package on Debian systems. + + Copyright (C) 2003 Brailcom, o.p.s. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA diff -r a410f6cd5dc8 -r 77a993bd713f pkg/landfall-examples/hw_info/Makefile --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pkg/landfall-examples/hw_info/Makefile Mon Oct 30 17:25:00 2023 +0100 @@ -0,0 +1,12 @@ +PKGDIR ?= .. +L4DIR ?= $(PKGDIR)/../.. + +TARGET = ex_jz4780_info ex_x1600_info +SRC_C_ex_jz4780_info = hw_info.c jz4780.c +SRC_C_ex_x1600_info = hw_info.c x1600.c +REQUIRES_LIBS = \ + libio l4re_c-util libdrivers-aic libdrivers-cpm \ + libdrivers-dma libdrivers-gpio libdrivers-i2c \ + libdrivers-spi libdevice-util + +include $(L4DIR)/mk/prog.mk diff -r a410f6cd5dc8 -r 77a993bd713f pkg/landfall-examples/hw_info/common.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pkg/landfall-examples/hw_info/common.h Mon Oct 30 17:25:00 2023 +0100 @@ -0,0 +1,218 @@ +/* + * Access various peripherals on a board. + * + * Copyright (C) 2023 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 + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA + */ + +#pragma once + +#include +#include +#include +#include +#include + + + +/* AIC adapter functions. */ + +void *aic_init(l4_addr_t aic_start, l4_addr_t start, l4_addr_t end, void *cpm); + +void *aic_get_channel(void *aic, int num, void *channel); + +long aic_get_buffer(void *channel, uint32_t count, l4_addr_t *addr); + +unsigned int aic_transfer(void *channel, uint32_t count, uint32_t sample_rate, + uint8_t sample_size); + + + +/* CPM adapter functions. */ + +void *cpm_init(l4_addr_t cpm_base); + +const char *cpm_clock_type(void *cpm, enum Clock_identifiers clock); + +int cpm_have_clock(void *cpm, enum Clock_identifiers clock); + +void cpm_start_clock(void *cpm, enum Clock_identifiers clock); + +void cpm_stop_clock(void *cpm, enum Clock_identifiers clock); + +int cpm_get_parameters(void *cpm, enum Clock_identifiers clock, + uint32_t parameters[]); + +int cpm_set_parameters(void *cpm, enum Clock_identifiers clock, + int num_parameters, uint32_t parameters[]); + +uint8_t cpm_get_source(void *cpm, enum Clock_identifiers clock); + +void cpm_set_source(void *cpm, enum Clock_identifiers clock, uint8_t source); + +enum Clock_identifiers cpm_get_source_clock(void *cpm, enum Clock_identifiers clock); + +void cpm_set_source_clock(void *cpm, enum Clock_identifiers clock, + enum Clock_identifiers source); + +uint64_t cpm_get_source_frequency(void *cpm, enum Clock_identifiers clock); + +uint64_t cpm_get_frequency(void *cpm, enum Clock_identifiers clock); + +int cpm_set_frequency(void *cpm, enum Clock_identifiers clock, uint64_t frequency); + + + +/* DMA adapter functions. */ + +void *dma_init(l4_addr_t start, l4_addr_t end, void *cpm); + +void dma_disable(void *dma_chip); + +void dma_enable(void *dma_chip); + +void *dma_get_channel(void *dma, uint8_t channel, l4_cap_idx_t irq); + +unsigned int dma_transfer(void *dma_channel, + uint32_t source, uint32_t destination, + unsigned int count, + int source_increment, int destination_increment, + uint8_t source_width, uint8_t destination_width, + uint8_t transfer_unit_size, + int type); + +unsigned int dma_wait(void *dma_channel); + + + +/* GPIO adapter functions. */ + +void *gpio_init(l4_addr_t start, l4_addr_t end, unsigned pins, + l4_uint32_t pull_ups, l4_uint32_t pull_downs); + +void gpio_setup(void *gpio, unsigned pin, unsigned mode, int value); + +void gpio_config_pull(void *gpio, unsigned pin, unsigned mode); + +void gpio_config_pad(void *gpio, unsigned pin, unsigned func, unsigned value); + +void gpio_config_get(void *gpio, unsigned pin, unsigned reg, unsigned *value); + +void gpio_config_pad_get(void *gpio, unsigned pin, unsigned *func, unsigned *value); + +void gpio_multi_setup(void *gpio, Pin_slice const *mask, unsigned mode, unsigned outvalues); + +void gpio_multi_config_pad(void *gpio, Pin_slice const *mask, unsigned func, unsigned value); + +void gpio_multi_set(void *gpio, Pin_slice const *mask, unsigned data); + +unsigned gpio_multi_get(void *gpio, unsigned offset); + +int gpio_get(void *gpio, unsigned pin); + +void gpio_set(void *gpio, unsigned pin, int value); + +void *gpio_get_irq(void *gpio, unsigned pin); + +bool gpio_irq_set_mode(void *gpio_irq, unsigned mode); + + + +/* I2C adapter functions. */ + +void *i2c_init(l4_addr_t start, l4_addr_t end, void *cpm, uint32_t frequency); + +void *i2c_get_channel(void *i2c, uint8_t channel); + +uint32_t i2c_get_frequency(void *i2c_channel); + +void i2c_set_target(void *i2c_channel, uint8_t addr); + +void i2c_start_read(void *i2c_channel, uint8_t buf[], unsigned int total, + int stop); + +void i2c_read(void *i2c_channel); + +void i2c_start_write(void *i2c_channel, uint8_t buf[], unsigned int total, + int stop); + +void i2c_write(void *i2c_channel); + +int i2c_read_done(void *i2c_channel); + +int i2c_write_done(void *i2c_channel); + +unsigned int i2c_have_read(void *i2c_channel); + +unsigned int i2c_have_written(void *i2c_channel); + +int i2c_failed(void *i2c_channel); + +void i2c_stop(void *i2c_channel); + + + +/* SPI adapter functions. */ + +void *spi_get_channel(void *clock_chip, int clock_pin, + void *data_chip, int data_pin, + void *enable_chip, int enable_pin, + uint32_t frequency); + +void spi_send(void *channel, int bytes, const uint8_t data[]); + + + +/* Memory regions. */ + +enum memory_regions +{ + AIC, CPM, DMA, GPIO, I2C +}; + + + +/* CPM definitions. */ + +struct clock_info +{ + const char *id; + enum Clock_identifiers clock; + const char *name; +}; + + + +/* DMA definitions. */ + +struct dma_region +{ + unsigned int size; + unsigned int align; + l4_addr_t vaddr; + l4re_dma_space_dma_addr_t paddr; + l4_cap_idx_t mem; +}; + + + +/* GPIO definitions. */ + +struct gpio_port +{ + const uint32_t pull_ups, pull_downs; +}; diff -r a410f6cd5dc8 -r 77a993bd713f pkg/landfall-examples/hw_info/defs.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pkg/landfall-examples/hw_info/defs.h Mon Oct 30 17:25:00 2023 +0100 @@ -0,0 +1,88 @@ +/* + * Common declarations for chip-specific definitions. + * + * Copyright (C) 2023 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 + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA + */ + +#pragma once + +#include "common.h" + + + +/* Memory regions. */ + +extern const char *memory_regions[]; + + + +/* AIC definitions. */ + +extern void *aic_channels[]; + +extern const unsigned int num_aic_channels; + +extern l4_cap_idx_t aic_irqs[]; + + + +/* CPM definitions. */ + +extern struct clock_info clocks[]; + + + +/* DMA definitions. */ + +extern void *dma_channels[]; + +extern const unsigned int num_dma_channels; + +extern struct dma_region dma_regions[]; + +extern const unsigned int num_dma_regions; + +extern l4_cap_idx_t dma_irq; + + + +/* GPIO definitions. */ + +extern const unsigned int num_gpio_ports; + +extern struct gpio_port gpio_ports[]; + +extern const char gpio_port_labels[]; + + + +/* I2C definitions. */ + +extern void *i2c_channels[]; + +extern const unsigned int num_i2c_channels; + +extern l4_cap_idx_t i2c_irqs[]; + + + +/* SPI definitions. */ + +extern void *spi_channels[]; + +extern const unsigned int num_spi_channels; diff -r a410f6cd5dc8 -r 77a993bd713f pkg/landfall-examples/hw_info/hw_info.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pkg/landfall-examples/hw_info/hw_info.c Mon Oct 30 17:25:00 2023 +0100 @@ -0,0 +1,1365 @@ +/* + * Access various peripherals on the MIPS Creator CI20 board. + * + * Copyright (C) 2023 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 + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA + */ + +#include "common.h" +#include "defs.h" + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + + + +/* Common configuration. */ + +static l4_cap_idx_t icucap; + + + +/* Device and resource discovery. */ + +static long item_in_range(long start, long end, long index) +{ + if (start < end) + return start + index; + else if (start > end) + return start - index; + else + return start; +} + + + +/* Common functions. */ + +static int init_irq(int num, l4_cap_idx_t irq, l4_uint32_t start, l4_uint32_t end) +{ + /* Create interrupt object. */ + + long err = l4_error(l4_factory_create_irq(l4re_global_env->factory, irq)); + + if (err) + { + printf("Could not create IRQ object: %ld\n", err); + return 1; + } + + /* Bind interrupt objects to IRQ numbers. */ + + err = l4_error(l4_icu_bind(icucap, + item_in_range(start, end, num), + irq)); + + if (err) + { + printf("Could not bind IRQ to the ICU: %ld\n", err); + return 1; + } + + /* Attach ourselves to the interrupt handler. */ + + err = l4_error(l4_rcv_ep_bind_thread(irq, l4re_env()->main_thread, num)); + + if (err) + { + printf("Could not attach to IRQs: %ld\n", err); + return 1; + } + + return 0; +} + +static const char *delimiters = " \n"; + +static char *read_token(const char *message) +{ + char *token; + + if ((token = strtok(NULL, delimiters)) == NULL) + { + if (message != NULL) + printf("%s?\n", message); + } + + return token; +} + +static int read_increment(const char *message, int *increment) +{ + char *token = read_token(message); + + if (token == NULL) + return 0; + + *increment = !strncmp(token, "i", 1); + return 1; +} + +static int read_encoded_number(const char *message, const char *format, unsigned int *num) +{ + char *token = read_token(message); + + if (token == NULL) + return 0; + + sscanf(token, format, num); + return 1; +} + +static int read_number(const char *message, unsigned int *num) +{ + char *token = read_token(message); + + if (token == NULL) + return 0; + + if (!strncmp(token, "0x", 2) || !strncmp(token, "0X", 2)) + sscanf(token, "%x", num); + else + *num = atoi(token); + + return 1; +} + +static int get_resource_number(const char *type, unsigned int available) +{ + unsigned int num; + + if (!read_number(type, &num)) + return -1; + + if (num >= available) + { + printf("%s number out of range.\n", type); + return -1; + } + + return num; +} + +static int get_channel_number(unsigned int available) +{ + return get_resource_number("Channel", available); +} + +static int get_region_number(unsigned int available) +{ + return get_resource_number("Region", available); +} + +static void *get_channel(int num_channels, void *channels[], int *num) +{ + int n = get_channel_number(num_channels); + void *channel; + + if (n < 0) + return NULL; + + channel = channels[n]; + + if (channel == NULL) + printf("Channel needs creating.\n"); + + if (num != NULL) + *num = n; + + return channel; +} + +static void list_channels(int num_channels, void *channels[]) +{ + int num; + void *channel; + + for (num = 0; num < num_channels; num++) + { + printf("Channel %d: ", num); + + channel = channels[num]; + + if (channel == NULL) + printf("(inactive)\n"); + else + printf("active\n"); + } +} + + + +/* AIC/I2S configuration. */ + +static l4_uint32_t aic_irq_start = 0, aic_irq_end = 0; + +/* AIC/I2S operations. */ + +static void new_aic_channel(void *aic) +{ + l4_cap_idx_t irqcap; + int num = get_channel_number(num_aic_channels); + void *channel; + + if (num < 0) + return; + + channel = get_channel(num_dma_channels, dma_channels, NULL); + + if (channel == NULL) + return; + + irqcap = l4re_util_cap_alloc(); + + if (init_irq(num, irqcap, aic_irq_start, aic_irq_end)) + return; + + aic_channels[num] = aic_get_channel(aic, num, channel); + aic_irqs[num] = irqcap; +} + +static void set_aic_buffer(void) +{ + char *token; + FILE *fp; + void *channel = get_channel(num_aic_channels, aic_channels, NULL); + unsigned int size; + l4_addr_t vaddr; + + if (channel == NULL) + return; + + if (!read_number("Buffer size", &size)) + return; + + if (aic_get_buffer(channel, size, &vaddr)) + { + printf("Could not get buffer.\n"); + return; + } + + memset((void *) vaddr, 0, size); + + if ((token = read_token("Filename")) == NULL) + return; + + /* Populate the region from the file. */ + + fp = fopen(token, "r"); + + if (fp == NULL) + { + printf("File not readable.\n"); + return; + } + + fread((char *) vaddr, sizeof(char), size, fp); + fclose(fp); + + l4_cache_flush_data(vaddr, vaddr + size); +} + +static void aic_transfer_data(void) +{ + void *channel = get_channel(num_aic_channels, aic_channels, NULL); + unsigned int count, rate, resolution, transferred; + + if (channel == NULL) + return; + + if (!read_number("Sample size", &count)) + return; + + if (!read_number("Sample rate", &rate)) + return; + + if (!read_number("Sample resolution", &resolution)) + return; + + transferred = aic_transfer(channel, count, rate, resolution); + + printf("Transferred: %d\n", transferred); +} + + + +/* CPM operations. */ + +static const char *clock_id(enum Clock_identifiers clock) +{ + for (int i = 0; clocks[i].id != NULL; i++) + if (clock == clocks[i].clock) + return clocks[i].id; + + return NULL; +} + +static enum Clock_identifiers get_clock(char *id) +{ + if (id != NULL) + { + for (int i = 0; clocks[i].id != NULL; i++) + if (!strcmp(id, clocks[i].id)) + return clocks[i].clock; + } + + return Clock_undefined; +} + +static const char list_clocks_separator[] = "--------------------------------"; + +#define sep(x) (list_clocks_separator + sizeof(list_clocks_separator) - 1 - x) + +static void list_clocks(void *cpm) +{ + /* Read information from the clock and power management unit. */ + + printf("%-5s %-10s %-7s %-6s %-12s %-12s %-24s %-12s %-3s\n" + "%-5s %-10s %-7s %-6s %-12s %-12s %-24s %-12s %-3s\n", + "Id", "Clock", "Type", "Source", "Source Clock", "Source Freq.", + "Parameters", "Frequency", "On", + sep(5), sep(10), sep(7), sep(6), sep(12), sep(12), + sep(24), sep(12), sep(3)); + + for (int i = 0; clocks[i].id != NULL; i++) + { + uint32_t parameters[4]; + char parameter_str[25] = {0}; + const char *source_id = clock_id(cpm_get_source_clock(cpm, clocks[i].clock)); + int num_parameters = cpm_get_parameters(cpm, clocks[i].clock, parameters); + + for (int p = 0, pos = 0; p < num_parameters; p++) + { + int result = sprintf(parameter_str + pos, "%-7d ", parameters[p]); + if (result < 0) + break; + pos += result; + } + + printf("%-5s %-10s %-7s %-6d %-12s %-12lld %-24s %-12lld %-3s\n", + clocks[i].id, + clocks[i].name, + cpm_clock_type(cpm, clocks[i].clock), + cpm_get_source(cpm, clocks[i].clock), + source_id != NULL ? source_id : "...", + cpm_get_source_frequency(cpm, clocks[i].clock), + parameter_str, + cpm_get_frequency(cpm, clocks[i].clock), + cpm_have_clock(cpm, clocks[i].clock) ? "on" : "off"); + } +} + +static enum Clock_identifiers get_clock_by_name(void) +{ + char *token; + enum Clock_identifiers clock; + + if ((token = read_token("Clock")) == NULL) + return Clock_undefined; + + clock = get_clock(token); + + if (clock == Clock_undefined) + { + printf("Unrecognised clock: %s\n", token); + return Clock_undefined; + } + + return clock; +} + +static void set_frequency(void *cpm) +{ + enum Clock_identifiers clock; + unsigned int frequency; + + clock = get_clock_by_name(); + + if (clock == Clock_undefined) + return; + + if (!read_number("Frequency", &frequency)) + return; + + if (!cpm_set_frequency(cpm, clock, frequency)) + printf("Frequency not set.\n"); +} + +static void set_parameters(void *cpm) +{ + char *token; + enum Clock_identifiers clock; + uint32_t parameters[4]; + int num_parameters; + + clock = get_clock_by_name(); + + if (clock == Clock_undefined) + return; + + for (num_parameters = 0; num_parameters < 4; num_parameters++) + { + if ((token = read_token(NULL)) == NULL) + break; + + parameters[num_parameters] = atoi(token); + } + + if (!num_parameters) + { + printf("Parameters?\n"); + return; + } + + if (!cpm_set_parameters(cpm, clock, num_parameters, parameters)) + printf("Too few or invalid parameters.\n"); +} + +static void set_source(void *cpm) +{ + enum Clock_identifiers clock; + unsigned int source; + + clock = get_clock_by_name(); + + if (clock == Clock_undefined) + return; + + if (!read_number("Source", &source)) + return; + + cpm_set_source(cpm, clock, source); +} + +static void start_clock(void *cpm) +{ + enum Clock_identifiers clock; + + clock = get_clock_by_name(); + + if (clock == Clock_undefined) + return; + + cpm_start_clock(cpm, clock); +} + +static void stop_clock(void *cpm) +{ + enum Clock_identifiers clock; + + clock = get_clock_by_name(); + + if (clock == Clock_undefined) + return; + + cpm_stop_clock(cpm, clock); +} + + + +/* DMA configuration. */ + +static l4_uint32_t dma_irq_start = 0, dma_irq_end = 0; + +/* DMA operations. */ + +static int init_dma(void) +{ + unsigned int i; + + for (i = 0; i < num_dma_regions; i++) + dma_regions[i].mem = L4_INVALID_CAP; + + /* Here, only one IRQ is used. */ + + dma_irq = l4re_util_cap_alloc(); + return init_irq(0, dma_irq, dma_irq_start, dma_irq_end); +} + +static struct dma_region *_get_dma_region(void) +{ + int num = get_region_number(num_dma_regions); + + if (num < 0) + return NULL; + + return &dma_regions[num]; +} + +static void list_dma_regions(void) +{ + unsigned int num; + struct dma_region *region; + unsigned int i; + + for (num = 0; num < num_dma_regions; num++) + { + printf("Region %d: ", num); + + region = &dma_regions[num]; + + if (l4_is_invalid_cap(region->mem)) + printf("(inactive)\n"); + else + { + printf("size = %d; align = %d; virtual = 0x%lx; physical = 0x%llx\ndata =", + region->size, region->align, region->vaddr, region->paddr); + + for (i = 0; (i < region->size) && (i < 16); i++) + printf(" %02x", *((uint8_t *) region->vaddr + i)); + + printf("\n"); + } + } +} + +static void new_dma_channel(void *dma) +{ + int num = get_channel_number(num_dma_channels); + + if (num < 0) + return; + + if (dma_channels[num] != NULL) + { + printf("Channel already defined.\n"); + return; + } + + dma_channels[num] = dma_get_channel(dma, num, dma_irq); +} + +static void new_dma_region(void) +{ + struct dma_region *region = _get_dma_region(); + + if (region == NULL) + { + list_dma_regions(); + return; + } + + if (l4_is_valid_cap(region->mem)) + { + printf("Region already defined.\n"); + return; + } + + if (!read_number("Size", ®ion->size)) + return; + + if (!read_number("Alignment", ®ion->align)) + return; + + if (get_dma_region(region->size, region->align, ®ion->vaddr, ®ion->paddr, ®ion->mem)) + printf("Could not allocate region.\n"); +} + +static void set_dma_region(void) +{ + char *token; + struct dma_region *region = _get_dma_region(); + FILE *fp; + + if (region == NULL) + { + list_dma_regions(); + return; + } + + if (l4_is_invalid_cap(region->mem)) + { + printf("Region needs creating.\n"); + return; + } + + memset((void *) region->vaddr, 0, region->size); + + if ((token = read_token("Filename")) == NULL) + return; + + /* Populate the region from the file. */ + + fp = fopen(token, "r"); + + if (fp == NULL) + { + printf("File not readable.\n"); + return; + } + + fread((char *) region->vaddr, sizeof(char), region->size, fp); + fclose(fp); + + l4_cache_flush_data(region->vaddr, region->vaddr + region->size); +} + +static void dma_transfer_data(void) +{ + unsigned int count, to_transfer, transferred; + unsigned int source_address, destination_address, source_width, destination_width, + transfer_unit_size, request_type; + int source_increment, destination_increment; + void *channel = get_channel(num_dma_channels, dma_channels, NULL); + unsigned int i; + + if (channel == NULL) + return; + + if (!read_number("Source address", &source_address)) + return; + + if (!read_number("Destination address", &destination_address)) + return; + + if (!read_number("Transfer size", &count)) + return; + + if (!read_increment("Source increment", &source_increment)) + return; + + if (!read_increment("Destination increment", &destination_increment)) + return; + + if (!read_number("Source width", &source_width)) + return; + + if (!read_number("Destination width", &destination_width)) + return; + + if (!read_number("Transfer unit size", &transfer_unit_size)) + return; + + if (!read_number("Request type", &request_type)) + return; + + /* Invalidate DMA region contents in case of transfers between regions. */ + + for (i = 0; i < num_dma_regions; i++) + l4_cache_inv_data(dma_regions[i].vaddr, dma_regions[i].vaddr + dma_regions[i].size); + + to_transfer = dma_transfer(channel, source_address, destination_address, + count, + source_increment, destination_increment, + source_width, destination_width, + transfer_unit_size, + request_type); + + transferred = to_transfer ? count - dma_wait(channel) : 0; + + printf("Transferred: %d\n", transferred); +} + + + +/* GPIO operations. */ + +static char get_gpio_dir_label(unsigned int value, unsigned int level) +{ + return value == Fix_input ? (level ? 'I' : 'i') : (level ? 'O' : 'o'); +} + +static char get_gpio_irq_label(unsigned int value) +{ + switch (value) + { + case L4_IRQ_F_NEG_EDGE: return 'f'; + case L4_IRQ_F_POS_EDGE: return 'r'; + case L4_IRQ_F_LEVEL_LOW: return 'l'; + case L4_IRQ_F_LEVEL_HIGH: return 'h'; + default: return '?'; + } +} + +static void list_gpios(void *gpio[]) +{ + unsigned int port, pin; + unsigned int func, value, level; + + printf("gpio: I = input high; i = input low; O = output high; o = output low\n" + "irq: h = high level; l = low level; r = rising edge; f = falling edge\n" + "alt: function number\n\n"); + + /* Show pin numbering. */ + + printf("Port/Pin "); + + for (pin = 0; pin < 32; pin++) + { + if (!(pin % 10)) + printf(" %d", pin); + else + printf(" %d", pin % 10); + } + + printf("\n"); + + for (port = 0; port < num_gpio_ports; port++) + { + /* Show port and pin configuration. */ + + printf("%c ", gpio_port_labels[port]); + + for (pin = 0; pin < 32; pin++) + { + /* Pad below the first pin digit for multiples of ten other than zero. */ + + if (pin && !(pin % 10)) + printf(" "); + + gpio_config_pad_get(gpio[port], pin, &func, &value); + + switch (func) + { + case Function_alt: printf(" %d", value); break; + case Function_irq: printf(" %c", get_gpio_irq_label(value)); break; + case Function_gpio: + { + level = gpio_get(gpio[port], pin); + printf(" %c", get_gpio_dir_label(value, level)); + break; + } + default: printf(" ?"); break; + } + } + + printf("\n"); + } +} + +static int get_port_and_pin(unsigned int *port, unsigned int *pin) +{ + char *token; + + if ((token = read_token("Port")) == NULL) + return 0; + + if ((token[0] < 'A') || ((unsigned int) token[0] - (unsigned int) 'A' >= num_gpio_ports)) + { + printf("Bad port: %c\n", token[0]); + return 0; + } + + *port = (unsigned int) token[0] - (unsigned int) 'A'; + + if (!read_number("Pin", pin)) + return 0; + + return 1; +} + +static void set_gpio_alt_func(void *gpio[]) +{ + unsigned int port, pin, value; + + if (!get_port_and_pin(&port, &pin)) + return; + + if (!read_number("Function", &value)) + return; + + gpio_config_pad(gpio[port], pin, Function_alt, value); +} + +static void set_gpio_pad(void *gpio[]) +{ + char *token; + unsigned int port, pin, mode, value = 0; + + if (!get_port_and_pin(&port, &pin)) + return; + + if ((token = read_token("Mode")) == NULL) + return; + + if (!strcmp(token, "in")) + mode = Fix_input; + else if (!strcmp(token, "irq")) + mode = Fix_irq; + else if (!strcmp(token, "out")) + { + mode = Fix_output; + + if ((token = read_token(NULL)) != NULL) + value = atoi(token); + } + else + { + printf("Mode not recognised.\n"); + return; + } + + gpio_setup(gpio[port], pin, mode, value); +} + +static void set_gpio_pull(void *gpio[]) +{ + char *token; + unsigned int port, pin, mode; + + if (!get_port_and_pin(&port, &pin)) + return; + + if ((token = read_token("Mode")) == NULL) + return; + + if (!strcmp(token, "down")) + mode = Pull_down; + else if (!strcmp(token, "none")) + mode = Pull_none; + else if (!strcmp(token, "up")) + mode = Pull_up; + else + { + printf("Mode not recognised.\n"); + return; + } + + gpio_config_pull(gpio[port], pin, mode); +} + + + +/* I2C configuration. */ + +static l4_uint32_t i2c_irq_start = 0, i2c_irq_end = 0; + +/* I2C operations. */ + +static int _i2c_read(void *channel, uint8_t *buf, unsigned length, + int stop, l4_cap_idx_t irqcap, unsigned timeout) +{ + l4_msgtag_t tag; + + i2c_start_read(channel, buf, length, stop); + + while (!i2c_read_done(channel)) + { + tag = l4_irq_receive(irqcap, l4_timeout(L4_IPC_TIMEOUT_NEVER, l4_timeout_from_us(timeout))); + + // NOTE: Error not returned. + + if (l4_ipc_error(tag, l4_utcb())) + break; + + if (i2c_failed(channel)) + break; + + i2c_read(channel); + } + + if (stop) + i2c_stop(channel); + + return i2c_have_read(channel); +} + +static int _i2c_write(void *channel, uint8_t *buf, unsigned length, + int stop, l4_cap_idx_t irqcap, unsigned timeout) +{ + l4_msgtag_t tag; + + i2c_start_write(channel, buf, length, stop); + + while (!i2c_write_done(channel)) + { + tag = l4_irq_receive(irqcap, l4_timeout(L4_IPC_TIMEOUT_NEVER, l4_timeout_from_us(timeout))); + + // NOTE: Error not returned. + + if (l4_ipc_error(tag, l4_utcb())) + break; + + if (i2c_failed(channel)) + break; + + i2c_write(channel); + } + + if (stop) + i2c_stop(channel); + + return i2c_have_written(channel); +} + +static void list_i2c_channels(void) +{ + unsigned int num; + void *channel; + + printf("i2c: channel\n\n"); + + for (num = 0; num < num_i2c_channels; num++) + { + printf("Channel %d: ", num); + + channel = i2c_channels[num]; + + if (channel == NULL) + printf("(inactive)\n"); + else + printf("%d Hz\n", i2c_get_frequency(channel)); + } +} + +static void new_i2c_channel(void *i2c) +{ + l4_cap_idx_t irqcap; + int num = get_channel_number(num_i2c_channels); + + if (num < 0) + return; + + irqcap = l4re_util_cap_alloc(); + + if (init_irq(num, irqcap, i2c_irq_start, i2c_irq_end)) + return; + + i2c_channels[num] = i2c_get_channel(i2c, num); + i2c_irqs[num] = irqcap; +} + +static void i2c_get(void) +{ + void *channel; + int num; + uint8_t buffer[32]; + unsigned int address, reg, count; + int i, transferred; + + channel = get_channel(num_i2c_channels, i2c_channels, &num); + + if (channel == NULL) + return; + + if (!read_encoded_number("Address", "%2x", &address)) + return; + + if (address >= 0x80) + { + printf("Address must be less than 80.\n"); + return; + } + + if (!read_encoded_number("Register", "%2x", ®)) + return; + + if (!read_number(NULL, &count)) + count = 1; + + buffer[0] = (uint8_t) (reg & 0xff); + + i2c_set_target(channel, address); + + if (!_i2c_write(channel, buffer, 1, 0, i2c_irqs[num], 1000000)) + { + printf("Register request failed.\n"); + return; + } + + transferred = _i2c_read(channel, buffer, count, 1, i2c_irqs[num], 1000000); + + if (!transferred) + { + printf("Register read failed.\n"); + return; + } + + for (i = 0; i < transferred; i++) + printf("%02x ", buffer[i]); + printf("\n"); +} + +static void i2c_scan(void) +{ + void *channel; + unsigned int address; + uint8_t buffer[1]; + int num; + + channel = get_channel(num_i2c_channels, i2c_channels, &num); + + if (channel == NULL) + return; + + for (address = 0; address < 0x20; address++) + printf("%02x ", address); + printf("\n"); + + for (address = 0; address < 0x20; address++) + printf("-- "); + + for (address = 0; address < 0x80; address++) + { + if ((address % 32) == 0) + printf("\n"); + + i2c_set_target(channel, address); + + if (_i2c_read(channel, buffer, 1, 1, i2c_irqs[num], 1000)) + printf("%02x ", address); + else + printf("-- "); + } + + printf("\n"); + for (address = 0; address < 0x20; address++) + printf("-- "); + printf("\n\n"); +} + + + +/* SPI operations. */ + +static void new_spi_channel(void *gpio[]) +{ + unsigned int clock_port, clock_pin, data_port, data_pin, enable_port, enable_pin; + int num = get_channel_number(num_spi_channels); + uint32_t frequency; + + if (num < 0) + return; + + if (!get_port_and_pin(&clock_port, &clock_pin)) + return; + + if (!get_port_and_pin(&data_port, &data_pin)) + return; + + if (!get_port_and_pin(&enable_port, &enable_pin)) + return; + + if (!read_number("Frequency", &frequency)) + return; + + spi_channels[num] = spi_get_channel(gpio[clock_port], clock_pin, + gpio[data_port], data_pin, + gpio[enable_port], enable_pin, + frequency); +} + +static void spi_send_data(void) +{ + void *channel = get_channel(num_spi_channels, spi_channels, NULL); + int bytes; + unsigned int byte; + uint8_t buffer[256]; + + bytes = 0; + + while (read_encoded_number(NULL, "%2x", &byte)) + { + buffer[bytes] = (uint8_t) (byte & 0xff); + bytes++; + } + + spi_send(channel, bytes, buffer); +} + + + +/* Command processing. */ + +static void handle_aic(void *aic) +{ + char *token; + + if ((token = read_token(NULL)) != NULL) + { + if (!strcmp(token, "l") || !strcmp(token, "list")) + list_channels(num_aic_channels, aic_channels); + else if (!strcmp(token, "c") || !strcmp(token, "channel")) + new_aic_channel(aic); + else if (!strcmp(token, "s") || !strcmp(token, "set")) + set_aic_buffer(); + else if (!strcmp(token, "t") || !strcmp(token, "transfer")) + aic_transfer_data(); + else + printf("aic channel | list | set | transfer\n"); + } + else + list_channels(num_aic_channels, aic_channels); +} + +static void handle_cpm(void *cpm) +{ + char *token; + + if ((token = read_token(NULL)) != NULL) + { + if (!strcmp(token, "l") || !strcmp(token, "list")) + list_clocks(cpm); + else if (!strcmp(token, "f") || !strcmp(token, "frequency")) + set_frequency(cpm); + else if (!strcmp(token, "p") || !strcmp(token, "parameters")) + set_parameters(cpm); + else if (!strcmp(token, "s") || !strcmp(token, "source")) + set_source(cpm); + else if (!strcmp(token, "start")) + start_clock(cpm); + else if (!strcmp(token, "stop")) + stop_clock(cpm); + else + printf("cpm list | frequency | parameters | source | start | stop\n"); + } + else + list_clocks(cpm); +} + +static void handle_dma(void *dma) +{ + char *token; + + if ((token = read_token(NULL)) != NULL) + { + if (!strcmp(token, "l") || !strcmp(token, "list")) + list_channels(num_dma_channels, dma_channels); + else if (!strcmp(token, "c") || !strcmp(token, "channel")) + new_dma_channel(dma); + else if (!strcmp(token, "r") || !strcmp(token, "region")) + new_dma_region(); + else if (!strcmp(token, "s") || !strcmp(token, "set")) + set_dma_region(); + else if (!strcmp(token, "t") || !strcmp(token, "transfer")) + dma_transfer_data(); + else + printf("dma channel | list | region | set | transfer\n"); + } + else + list_channels(num_dma_channels, dma_channels); +} + +static void handle_gpio(void *gpio[]) +{ + char *token; + + if ((token = read_token(NULL)) != NULL) + { + if (!strcmp(token, "l") || !strcmp(token, "list")) + list_gpios(gpio); + else if (!strcmp(token, "a") || !strcmp(token, "alt")) + set_gpio_alt_func(gpio); + else if (!strcmp(token, "i") || !strcmp(token, "io")) + set_gpio_pad(gpio); + else if (!strcmp(token, "p") || !strcmp(token, "pull")) + set_gpio_pull(gpio); + else + printf("gpio list | alt | io | pull\n"); + } + else + list_gpios(gpio); +} + +static void handle_i2c(void *i2c) +{ + char *token; + + if ((token = read_token(NULL)) != NULL) + { + if (!strcmp(token, "l") || !strcmp(token, "list")) + list_i2c_channels(); + else if (!strcmp(token, "c") || !strcmp(token, "channel")) + new_i2c_channel(i2c); + else if (!strcmp(token, "g") || !strcmp(token, "get")) + i2c_get(); + else if (!strcmp(token, "s") || !strcmp(token, "scan")) + i2c_scan(); + else + printf("i2c channel | get | list | scan\n"); + } + else + list_i2c_channels(); +} + +static void handle_spi(void *gpio[]) +{ + char *token; + + if ((token = read_token(NULL)) != NULL) + { + if (!strcmp(token, "l") || !strcmp(token, "list")) + list_channels(num_spi_channels, spi_channels); + else if (!strcmp(token, "c") || !strcmp(token, "channel")) + new_spi_channel(gpio); + else if (!strcmp(token, "s") || !strcmp(token, "send")) + spi_send_data(); + else + printf("spi channel | list | send\n"); + } + else + list_channels(num_spi_channels, spi_channels); +} + + + +int main(void) +{ + l4_addr_t aic_base = 0, aic_base_end = 0; + l4_addr_t aic_phys_base = 0, aic_phys_base_end = 0; + l4_addr_t cpm_base = 0, cpm_base_end = 0; + l4_addr_t dma_base = 0, dma_base_end = 0; + l4_addr_t gpio_base = 0, gpio_base_end = 0; + l4_addr_t i2c_base = 0, i2c_base_end = 0; + void *aic, *cpm, *dma, *gpio[num_gpio_ports], *i2c; + int result = 0; + unsigned int port; + + icucap = l4re_env_get_cap("icu"); + + /* Obtain resource details describing I/O memory. */ + + printf("Access CPM...\n"); + + if ((result = get_memory(memory_regions[CPM], &cpm_base, &cpm_base_end)) < 0) + return 1; + + printf("CPM at 0x%lx...0x%lx.\n", cpm_base, cpm_base_end); + + cpm = cpm_init(cpm_base); + + printf("Access DMA...\n"); + + if ((result = get_memory(memory_regions[DMA], &dma_base, &dma_base_end)) < 0) + return 1; + + printf("DMA at 0x%lx...0x%lx.\n", dma_base, dma_base_end); + + dma = dma_init(dma_base, dma_base_end, cpm); + + if (get_irq(memory_regions[DMA], &dma_irq_start, &dma_irq_end) < 0) + return 1; + + printf("IRQ range at %d...%d.\n", dma_irq_start, dma_irq_end); + + if (init_dma()) + return 1; + + dma_enable(dma); + + printf("Access GPIO...\n"); + + if ((result = get_memory(memory_regions[GPIO], &gpio_base, &gpio_base_end)) < 0) + return 1; + + printf("GPIO at 0x%lx...0x%lx.\n", gpio_base, gpio_base_end); + + for (port = 0; port < num_gpio_ports; port++) + gpio[port] = gpio_init(gpio_base + port * 0x100, gpio_base + (port + 1) * 0x100, + 32, gpio_ports[port].pull_ups, gpio_ports[port].pull_downs); + + printf("Access I2C...\n"); + + if ((result = get_memory(memory_regions[I2C], &i2c_base, &i2c_base_end)) < 0) + return 1; + + printf("I2C at 0x%lx...0x%lx.\n", i2c_base, i2c_base_end); + + i2c = i2c_init(i2c_base, i2c_base_end, cpm, 100000); + + if (get_irq(memory_regions[I2C], &i2c_irq_start, &i2c_irq_end) < 0) + return 1; + + printf("IRQ range at %d...%d.\n", i2c_irq_start, i2c_irq_end); + + printf("Access AIC...\n"); + + if ((result = get_memory_complete(memory_regions[AIC], &aic_base, &aic_base_end, + &aic_phys_base, &aic_phys_base_end)) < 0) + return 1; + + printf("AIC at 0x%lx...0x%lx.\n", aic_base, aic_base_end); + + aic = aic_init(aic_phys_base, aic_base, aic_base_end, cpm); + + if (get_irq(memory_regions[AIC], &aic_irq_start, &aic_irq_end) < 0) + return 1; + + printf("IRQ range at %d...%d.\n", aic_irq_start, aic_irq_end); + + /* Start the interactive session. */ + + printf("aic, cpm, dma, gpio, i2c, spi\n"); + + while (1) + { + char cmdline[256], *token; + + printf("> "); + + token = fgets(cmdline, 64, stdin); + + if (token == NULL) + break; + + if ((token = strtok(cmdline, delimiters)) == NULL) + continue; + + /* AIC/I2S commands. */ + + if (!strcmp(token, "a") || !strcmp(token, "aic") || !strcmp(token, "i2s")) + handle_aic(aic); + + /* CPM commands. */ + + else if (!strcmp(token, "c") || !strcmp(token, "cpm")) + handle_cpm(cpm); + + /* DMA commands. */ + + else if (!strcmp(token, "d") || !strcmp(token, "dma")) + handle_dma(dma); + + /* GPIO commands. */ + + else if (!strcmp(token, "g") || !strcmp(token, "gpio")) + handle_gpio(gpio); + + /* I2C commands. */ + + else if (!strcmp(token, "i") || !strcmp(token, "i2c")) + handle_i2c(i2c); + + /* SPI commands. */ + + else if (!strcmp(token, "s") || !strcmp(token, "spi")) + handle_spi(gpio); + + else + printf("Command?\n"); + } + + printf("End of session.\n"); + return 0; +} diff -r a410f6cd5dc8 -r 77a993bd713f pkg/landfall-examples/hw_info/jz4780.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pkg/landfall-examples/hw_info/jz4780.c Mon Oct 30 17:25:00 2023 +0100 @@ -0,0 +1,458 @@ +/* + * Access various peripherals on a board using the JZ4780. + * + * Copyright (C) 2023 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 + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA + */ + +#include /* NOTE: To be replaced. */ +#include +#include +#include +#include +#include +#include "common.h" + + + +/* AIC adapter functions. */ + +void *aic_init(l4_addr_t aic_start, l4_addr_t start, l4_addr_t end, void *cpm) +{ + return x1600_aic_init(aic_start, start, end, cpm); +} + +void *aic_get_channel(void *aic, int num, void *channel) +{ + return x1600_aic_get_channel(aic, num, channel); +} + +long aic_get_buffer(void *channel, uint32_t count, l4_addr_t *addr) +{ + return x1600_aic_get_buffer(channel, count, addr); +} + +unsigned int aic_transfer(void *channel, uint32_t count, uint32_t sample_rate, uint8_t sample_size) +{ + return x1600_aic_transfer(channel, count, sample_rate, sample_size); +} + + + +/* CPM adapter functions. */ + +void *cpm_init(l4_addr_t cpm_base) +{ + return jz4780_cpm_init(cpm_base); +} + +const char *cpm_clock_type(void *cpm, enum Clock_identifiers clock) +{ + return jz4780_cpm_clock_type(cpm, clock); +} + +int cpm_have_clock(void *cpm, enum Clock_identifiers clock) +{ + return jz4780_cpm_have_clock(cpm, clock); +} + +void cpm_start_clock(void *cpm, enum Clock_identifiers clock) +{ + jz4780_cpm_start_clock(cpm, clock); +} + +void cpm_stop_clock(void *cpm, enum Clock_identifiers clock) +{ + jz4780_cpm_stop_clock(cpm, clock); +} + +int cpm_get_parameters(void *cpm, enum Clock_identifiers clock, + uint32_t parameters[]) +{ + return jz4780_cpm_get_parameters(cpm, clock, parameters); +} + +int cpm_set_parameters(void *cpm, enum Clock_identifiers clock, + int num_parameters, uint32_t parameters[]) +{ + return jz4780_cpm_set_parameters(cpm, clock, num_parameters, parameters); +} + +uint8_t cpm_get_source(void *cpm, enum Clock_identifiers clock) +{ + return jz4780_cpm_get_source(cpm, clock); +} + +void cpm_set_source(void *cpm, enum Clock_identifiers clock, uint8_t source) +{ + jz4780_cpm_set_source(cpm, clock, source); +} + +enum Clock_identifiers cpm_get_source_clock(void *cpm, enum Clock_identifiers clock) +{ + return jz4780_cpm_get_source_clock(cpm, clock); +} + +void cpm_set_source_clock(void *cpm, enum Clock_identifiers clock, enum Clock_identifiers source) +{ + jz4780_cpm_set_source_clock(cpm, clock, source); +} + +uint64_t cpm_get_source_frequency(void *cpm, enum Clock_identifiers clock) +{ + return jz4780_cpm_get_source_frequency(cpm, clock); +} + +uint64_t cpm_get_frequency(void *cpm, enum Clock_identifiers clock) +{ + return jz4780_cpm_get_frequency(cpm, clock); +} + +int cpm_set_frequency(void *cpm, enum Clock_identifiers clock, uint64_t frequency) +{ + return jz4780_cpm_set_frequency(cpm, clock, frequency); +} + + + +/* DMA adapter functions. */ + +void *dma_init(l4_addr_t start, l4_addr_t end, void *cpm) +{ + return jz4780_dma_init(start, end, cpm); +} + +void dma_disable(void *dma_chip) +{ + jz4780_dma_disable(dma_chip); +} + +void dma_enable(void *dma_chip) +{ + jz4780_dma_enable(dma_chip); +} + +void *dma_get_channel(void *dma, uint8_t channel, l4_cap_idx_t irq) +{ + return jz4780_dma_get_channel(dma, channel, irq); +} + +unsigned int dma_transfer(void *dma_channel, + uint32_t source, uint32_t destination, + unsigned int count, + int source_increment, int destination_increment, + uint8_t source_width, uint8_t destination_width, + uint8_t transfer_unit_size, + int type) +{ + return jz4780_dma_transfer(dma_channel, source, destination, count, + source_increment, destination_increment, + source_width, destination_width, + transfer_unit_size, type); +} + +unsigned int dma_wait(void *dma_channel) +{ + return jz4780_dma_wait(dma_channel); +} + + + +/* GPIO adapter functions. */ + +void *gpio_init(l4_addr_t start, l4_addr_t end, unsigned pins, + l4_uint32_t pull_ups, l4_uint32_t pull_downs) +{ + return jz4780_gpio_init(start, end, pins, pull_ups, pull_downs); +} + +void gpio_setup(void *gpio, unsigned pin, unsigned mode, int value) +{ + jz4780_gpio_setup(gpio, pin, mode, value); +} + +void gpio_config_pull(void *gpio, unsigned pin, unsigned mode) +{ + jz4780_gpio_config_pull(gpio, pin, mode); +} + +void gpio_config_pad(void *gpio, unsigned pin, unsigned func, unsigned value) +{ + jz4780_gpio_config_pad(gpio, pin, func, value); +} + +void gpio_config_get(void *gpio, unsigned pin, unsigned reg, unsigned *value) +{ + jz4780_gpio_config_get(gpio, pin, reg, value); +} + +void gpio_config_pad_get(void *gpio, unsigned pin, unsigned *func, unsigned *value) +{ + jz4780_gpio_config_pad_get(gpio, pin, func, value); +} + +void gpio_multi_setup(void *gpio, Pin_slice const *mask, unsigned mode, unsigned outvalues) +{ + jz4780_gpio_multi_setup(gpio, mask, mode, outvalues); +} + +void gpio_multi_config_pad(void *gpio, Pin_slice const *mask, unsigned func, unsigned value) +{ + jz4780_gpio_multi_config_pad(gpio, mask, func, value); +} + +void gpio_multi_set(void *gpio, Pin_slice const *mask, unsigned data) +{ + jz4780_gpio_multi_set(gpio, mask, data); +} + +unsigned gpio_multi_get(void *gpio, unsigned offset) +{ + return jz4780_gpio_multi_get(gpio, offset); +} + +int gpio_get(void *gpio, unsigned pin) +{ + return jz4780_gpio_get(gpio, pin); +} + +void gpio_set(void *gpio, unsigned pin, int value) +{ + jz4780_gpio_set(gpio, pin, value); +} + +void *gpio_get_irq(void *gpio, unsigned pin) +{ + return jz4780_gpio_get_irq(gpio, pin); +} + +bool gpio_irq_set_mode(void *gpio_irq, unsigned mode) +{ + return jz4780_gpio_irq_set_mode(gpio_irq, mode); +} + + + +/* I2C adapter functions. */ + +void *i2c_init(l4_addr_t start, l4_addr_t end, void *cpm, + uint32_t frequency) +{ + return jz4780_i2c_init(start, end, cpm, frequency); +} + +void *i2c_get_channel(void *i2c, uint8_t channel) +{ + return jz4780_i2c_get_channel(i2c, channel); +} + +uint32_t i2c_get_frequency(void *i2c_channel) +{ + return jz4780_i2c_get_frequency(i2c_channel); +} + +void i2c_set_target(void *i2c_channel, uint8_t addr) +{ + return jz4780_i2c_set_target(i2c_channel, addr); +} + +void i2c_start_read(void *i2c_channel, uint8_t buf[], unsigned int total, + int stop) +{ + jz4780_i2c_start_read(i2c_channel, buf, total, stop); +} + +void i2c_read(void *i2c_channel) +{ + jz4780_i2c_read(i2c_channel); +} + +void i2c_start_write(void *i2c_channel, uint8_t buf[], unsigned int total, + int stop) +{ + jz4780_i2c_start_write(i2c_channel, buf, total, stop); +} + +void i2c_write(void *i2c_channel) +{ + jz4780_i2c_write(i2c_channel); +} + +int i2c_read_done(void *i2c_channel) +{ + return jz4780_i2c_read_done(i2c_channel); +} + +int i2c_write_done(void *i2c_channel) +{ + return jz4780_i2c_write_done(i2c_channel); +} + +unsigned int i2c_have_read(void *i2c_channel) +{ + return jz4780_i2c_have_read(i2c_channel); +} + +unsigned int i2c_have_written(void *i2c_channel) +{ + return jz4780_i2c_have_written(i2c_channel); +} + +int i2c_failed(void *i2c_channel) +{ + return jz4780_i2c_failed(i2c_channel); +} + +void i2c_stop(void *i2c_channel) +{ + jz4780_i2c_stop(i2c_channel); +} + + + +/* SPI adapter functions. */ + +void *spi_get_channel(void *clock_chip, int clock_pin, + void *data_chip, int data_pin, + void *enable_chip, int enable_pin, + uint32_t frequency) +{ + return spi_gpio_get_channel(clock_chip, clock_pin, data_chip, data_pin, enable_chip, enable_pin, frequency); +} + +void spi_send(void *channel, int bytes, const uint8_t data[]) +{ + spi_gpio_send(channel, bytes, data); +} + + + +/* Memory regions. */ + +const char *memory_regions[] = { + [AIC] = "jz4780-aic", + [CPM] = "jz4780-cpm", + [DMA] = "jz4780-dma", + [GPIO] = "jz4780-gpio", + [I2C] = "jz4780-i2c", +}; + + + +/* AIC definitions. */ + +void *aic_channels[] = {NULL, NULL}; + +const unsigned int num_aic_channels = 2; + +l4_cap_idx_t aic_irqs[] = {L4_INVALID_CAP}; + + + +/* CPM definitions. */ + +struct clock_info clocks[] = { + {"ext", Clock_external, "External"}, + {"plla", Clock_pll_A, "PLL A"}, + {"plle", Clock_pll_E, "PLL E"}, + {"pllm", Clock_pll_M, "PLL M"}, + {"pllv", Clock_pll_V, "PLL V"}, + {"main", Clock_main, "Main"}, + {"cpu", Clock_cpu, "CPU"}, + {"h2p", Clock_hclock2_pclock, "AHB2/APB"}, + {"ahb0", Clock_hclock0, "AHB0"}, + {"ahb2", Clock_hclock2, "AHB2"}, + {"apb", Clock_pclock, "APB"}, + {"dma", Clock_dma, "DMA"}, + {"hdmi", Clock_lcd, "HDMI"}, + {"lcd", Clock_lcd, "LCD"}, + {"lcd0", Clock_lcd_pixel0, "LCD0 pixel"}, + {"lcd1", Clock_lcd_pixel1, "LCD1 pixel"}, + {"msc", Clock_msc, "MSC"}, + {"msc0", Clock_msc0, "MSC0"}, + {"msc1", Clock_msc1, "MSC1"}, + {"msc2", Clock_msc1, "MSC2"}, + {"otg0", Clock_otg0, "USB OTG0"}, + {"otg1", Clock_otg1, "USB OTG1"}, + {"i2c0", Clock_i2c0, "I2C0"}, + {"i2c1", Clock_i2c1, "I2C1"}, + {"i2c2", Clock_i2c2, "I2C2"}, + {"i2c3", Clock_i2c3, "I2C3"}, + {"i2c4", Clock_i2c4, "I2C4"}, + {"i2s0", Clock_i2s0, "I2S0"}, + {"i2s1", Clock_i2s1, "I2S1"}, + {"pcm", Clock_pcm, "PCM"}, + {"ssi", Clock_ssi, "SSI"}, + {"ssi0", Clock_ssi0, "SSI0"}, + {"ssi1", Clock_ssi1, "SSI1"}, + {"ssi2", Clock_ssi2, "SSI2"}, + {"uart0", Clock_uart0, "UART0"}, + {"uart1", Clock_uart1, "UART1"}, + {"uart2", Clock_uart2, "UART2"}, + {"uart3", Clock_uart3, "UART3"}, + {"uart4", Clock_uart4, "UART4"}, + {NULL, Clock_undefined, NULL}, +}; + + + +/* DMA definitions. */ + +void *dma_channels[32] = {NULL}; + +const unsigned int num_dma_channels = 32; + +struct dma_region dma_regions[2]; + +const unsigned int num_dma_regions = 2; + +l4_cap_idx_t dma_irq = L4_INVALID_CAP; + + + +/* GPIO definitions. */ + +struct gpio_port gpio_ports[] = { + {0x3fff00ff, 0x00000000}, + {0xfff0f3fc, 0x000f0c03}, + {0x0fffffff, 0x00000000}, + {0xffff4fff, 0x0000b000}, + {0xf0fff37c, 0x00000483}, + {0x7fa7f00f, 0x00580ff0}, +}; + +const unsigned int num_gpio_ports = 6; + +const char gpio_port_labels[] = "ABCDEF"; + + + +/* I2C definitions. */ + +void *i2c_channels[] = {NULL, NULL, NULL, NULL, NULL}; + +const unsigned int num_i2c_channels = 5; + +l4_cap_idx_t i2c_irqs[] = {L4_INVALID_CAP, L4_INVALID_CAP}; + + + +/* SPI definitions. */ + +void *spi_channels[] = {NULL, NULL}; + +const unsigned int num_spi_channels = 2; diff -r a410f6cd5dc8 -r 77a993bd713f pkg/landfall-examples/hw_info/x1600.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pkg/landfall-examples/hw_info/x1600.c Mon Oct 30 17:25:00 2023 +0100 @@ -0,0 +1,443 @@ +/* + * Access various peripherals on a board using the X1600. + * + * Copyright (C) 2023 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 + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA + */ + +#include +#include +#include +#include +#include +#include +#include "common.h" + + + +/* AIC adapter functions. */ + +void *aic_init(l4_addr_t aic_start, l4_addr_t start, l4_addr_t end, void *cpm) +{ + return x1600_aic_init(aic_start, start, end, cpm); +} + +void *aic_get_channel(void *aic, int num, void *channel) +{ + return x1600_aic_get_channel(aic, num, channel); +} + +long aic_get_buffer(void *channel, uint32_t count, l4_addr_t *addr) +{ + return x1600_aic_get_buffer(channel, count, addr); +} + +unsigned int aic_transfer(void *channel, uint32_t count, uint32_t sample_rate, uint8_t sample_size) +{ + return x1600_aic_transfer(channel, count, sample_rate, sample_size); +} + + + +/* CPM adapter functions. */ + +void *cpm_init(l4_addr_t cpm_base) +{ + return x1600_cpm_init(cpm_base); +} + +const char *cpm_clock_type(void *cpm, enum Clock_identifiers clock) +{ + return x1600_cpm_clock_type(cpm, clock); +} + +int cpm_have_clock(void *cpm, enum Clock_identifiers clock) +{ + return x1600_cpm_have_clock(cpm, clock); +} + +void cpm_start_clock(void *cpm, enum Clock_identifiers clock) +{ + x1600_cpm_start_clock(cpm, clock); +} + +void cpm_stop_clock(void *cpm, enum Clock_identifiers clock) +{ + x1600_cpm_stop_clock(cpm, clock); +} + +int cpm_get_parameters(void *cpm, enum Clock_identifiers clock, + uint32_t parameters[]) +{ + return x1600_cpm_get_parameters(cpm, clock, parameters); +} + +int cpm_set_parameters(void *cpm, enum Clock_identifiers clock, + int num_parameters, uint32_t parameters[]) +{ + return x1600_cpm_set_parameters(cpm, clock, num_parameters, parameters); +} + +uint8_t cpm_get_source(void *cpm, enum Clock_identifiers clock) +{ + return x1600_cpm_get_source(cpm, clock); +} + +void cpm_set_source(void *cpm, enum Clock_identifiers clock, uint8_t source) +{ + x1600_cpm_set_source(cpm, clock, source); +} + +enum Clock_identifiers cpm_get_source_clock(void *cpm, enum Clock_identifiers clock) +{ + return x1600_cpm_get_source_clock(cpm, clock); +} + +void cpm_set_source_clock(void *cpm, enum Clock_identifiers clock, enum Clock_identifiers source) +{ + x1600_cpm_set_source_clock(cpm, clock, source); +} + +uint64_t cpm_get_source_frequency(void *cpm, enum Clock_identifiers clock) +{ + return x1600_cpm_get_source_frequency(cpm, clock); +} + +uint64_t cpm_get_frequency(void *cpm, enum Clock_identifiers clock) +{ + return x1600_cpm_get_frequency(cpm, clock); +} + +int cpm_set_frequency(void *cpm, enum Clock_identifiers clock, uint64_t frequency) +{ + return x1600_cpm_set_frequency(cpm, clock, frequency); +} + + + +/* DMA adapter functions. */ + +void *dma_init(l4_addr_t start, l4_addr_t end, void *cpm) +{ + return x1600_dma_init(start, end, cpm); +} + +void dma_disable(void *dma_chip) +{ + x1600_dma_disable(dma_chip); +} + +void dma_enable(void *dma_chip) +{ + x1600_dma_enable(dma_chip); +} + +void *dma_get_channel(void *dma, uint8_t channel, l4_cap_idx_t irq) +{ + return x1600_dma_get_channel(dma, channel, irq); +} + +unsigned int dma_transfer(void *dma_channel, + uint32_t source, uint32_t destination, + unsigned int count, + int source_increment, int destination_increment, + uint8_t source_width, uint8_t destination_width, + uint8_t transfer_unit_size, + int type) +{ + return x1600_dma_transfer(dma_channel, source, destination, count, + source_increment, destination_increment, + source_width, destination_width, + transfer_unit_size, type); +} + +unsigned int dma_wait(void *dma_channel) +{ + return x1600_dma_wait(dma_channel); +} + + + +/* GPIO adapter functions. */ + +void *gpio_init(l4_addr_t start, l4_addr_t end, unsigned pins, + l4_uint32_t pull_ups, l4_uint32_t pull_downs) +{ + return x1600_gpio_init(start, end, pins, pull_ups, pull_downs); +} + +void gpio_setup(void *gpio, unsigned pin, unsigned mode, int value) +{ + x1600_gpio_setup(gpio, pin, mode, value); +} + +void gpio_config_pull(void *gpio, unsigned pin, unsigned mode) +{ + x1600_gpio_config_pull(gpio, pin, mode); +} + +void gpio_config_pad(void *gpio, unsigned pin, unsigned func, unsigned value) +{ + x1600_gpio_config_pad(gpio, pin, func, value); +} + +void gpio_config_get(void *gpio, unsigned pin, unsigned reg, unsigned *value) +{ + x1600_gpio_config_get(gpio, pin, reg, value); +} + +void gpio_config_pad_get(void *gpio, unsigned pin, unsigned *func, unsigned *value) +{ + x1600_gpio_config_pad_get(gpio, pin, func, value); +} + +void gpio_multi_setup(void *gpio, Pin_slice const *mask, unsigned mode, unsigned outvalues) +{ + x1600_gpio_multi_setup(gpio, mask, mode, outvalues); +} + +void gpio_multi_config_pad(void *gpio, Pin_slice const *mask, unsigned func, unsigned value) +{ + x1600_gpio_multi_config_pad(gpio, mask, func, value); +} + +void gpio_multi_set(void *gpio, Pin_slice const *mask, unsigned data) +{ + x1600_gpio_multi_set(gpio, mask, data); +} + +unsigned gpio_multi_get(void *gpio, unsigned offset) +{ + return x1600_gpio_multi_get(gpio, offset); +} + +int gpio_get(void *gpio, unsigned pin) +{ + return x1600_gpio_get(gpio, pin); +} + +void gpio_set(void *gpio, unsigned pin, int value) +{ + x1600_gpio_set(gpio, pin, value); +} + +void *gpio_get_irq(void *gpio, unsigned pin) +{ + return x1600_gpio_get_irq(gpio, pin); +} + +bool gpio_irq_set_mode(void *gpio_irq, unsigned mode) +{ + return x1600_gpio_irq_set_mode(gpio_irq, mode); +} + + + +/* I2C adapter functions. */ + +void *i2c_init(l4_addr_t start, l4_addr_t end, void *cpm, + uint32_t frequency) +{ + return x1600_i2c_init(start, end, cpm, frequency); +} + +void *i2c_get_channel(void *i2c, uint8_t channel) +{ + return x1600_i2c_get_channel(i2c, channel); +} + +uint32_t i2c_get_frequency(void *i2c_channel) +{ + return x1600_i2c_get_frequency(i2c_channel); +} + +void i2c_set_target(void *i2c_channel, uint8_t addr) +{ + return x1600_i2c_set_target(i2c_channel, addr); +} + +void i2c_start_read(void *i2c_channel, uint8_t buf[], unsigned int total, + int stop) +{ + x1600_i2c_start_read(i2c_channel, buf, total, stop); +} + +void i2c_read(void *i2c_channel) +{ + x1600_i2c_read(i2c_channel); +} + +void i2c_start_write(void *i2c_channel, uint8_t buf[], unsigned int total, + int stop) +{ + x1600_i2c_start_write(i2c_channel, buf, total, stop); +} + +void i2c_write(void *i2c_channel) +{ + x1600_i2c_write(i2c_channel); +} + +int i2c_read_done(void *i2c_channel) +{ + return x1600_i2c_read_done(i2c_channel); +} + +int i2c_write_done(void *i2c_channel) +{ + return x1600_i2c_write_done(i2c_channel); +} + +unsigned int i2c_have_read(void *i2c_channel) +{ + return x1600_i2c_have_read(i2c_channel); +} + +unsigned int i2c_have_written(void *i2c_channel) +{ + return x1600_i2c_have_written(i2c_channel); +} + +int i2c_failed(void *i2c_channel) +{ + return x1600_i2c_failed(i2c_channel); +} + +void i2c_stop(void *i2c_channel) +{ + x1600_i2c_stop(i2c_channel); +} + + + +/* SPI adapter functions. */ + +void *spi_get_channel(void *clock_chip, int clock_pin, + void *data_chip, int data_pin, + void *enable_chip, int enable_pin, + uint32_t frequency) +{ + return spi_gpio_get_channel(clock_chip, clock_pin, data_chip, data_pin, enable_chip, enable_pin, frequency); +} + +void spi_send(void *channel, int bytes, const uint8_t data[]) +{ + spi_gpio_send(channel, bytes, data); +} + + + +/* Memory regions. */ + +const char *memory_regions[] = { + [AIC] = "x1600-aic", + [CPM] = "x1600-cpm", + [DMA] = "x1600-dma", + [GPIO] = "x1600-gpio", + [I2C] = "x1600-i2c", +}; + + + +/* AIC definitions. */ + +void *aic_channels[] = {NULL}; + +const unsigned int num_aic_channels = 1; + +l4_cap_idx_t aic_irqs[] = {L4_INVALID_CAP}; + + + +/* CPM definitions. */ + +struct clock_info clocks[] = { + {"ext", Clock_external, "External"}, + {"plla", Clock_pll_A, "PLL A"}, + {"plle", Clock_pll_E, "PLL E"}, + {"pllm", Clock_pll_M, "PLL M"}, + {"main", Clock_main, "Main"}, + {"cpu", Clock_cpu, "CPU"}, + {"ahb0", Clock_hclock0, "AHB0"}, + {"ahb2", Clock_hclock2, "AHB2"}, + {"apb", Clock_pclock, "APB"}, + {"aic", Clock_aic, "AIC"}, + {"dma", Clock_dma, "DMA"}, + {"lcd", Clock_lcd_pixel0, "LCD pixel"}, + {"msc0", Clock_msc0, "MSC0"}, + {"msc1", Clock_msc1, "MSC1"}, + {"otg", Clock_otg0, "USB OTG"}, + {"i2c0", Clock_i2c0, "I2C0"}, + {"i2c1", Clock_i2c1, "I2C1"}, + {"i2s0", Clock_i2s0, "I2S0"}, + {"i2s1", Clock_i2s1, "I2S1"}, + {"i2s0r", Clock_i2s0_rx, "I2S0 RX"}, + {"i2s0t", Clock_i2s0_tx, "I2S0 TX"}, + {"ssi", Clock_ssi0, "SSI"}, + {"uart0", Clock_uart0, "UART0"}, + {"uart1", Clock_uart1, "UART1"}, + {"uart2", Clock_uart2, "UART2"}, + {"uart3", Clock_uart3, "UART3"}, + {NULL, Clock_undefined, NULL}, +}; + + + +/* DMA definitions. */ + +void *dma_channels[32] = {NULL}; + +const unsigned int num_dma_channels = 32; + +struct dma_region dma_regions[2]; + +const unsigned int num_dma_regions = 2; + +l4_cap_idx_t dma_irq = L4_INVALID_CAP; + + + +/* GPIO definitions. */ + +struct gpio_port gpio_ports[] = { + {0xffffffff, 0x00000000}, + {0xdffbf7bf, 0x00000000}, + {0x987e0000, 0x07000007}, + {0x0000003f, 0x00000000} +}; + +const unsigned int num_gpio_ports = 4; + +const char gpio_port_labels[] = "ABCD"; + + + +/* I2C definitions. */ + +void *i2c_channels[] = {NULL, NULL}; + +const unsigned int num_i2c_channels = 2; + +l4_cap_idx_t i2c_irqs[] = {L4_INVALID_CAP, L4_INVALID_CAP}; + + + +/* SPI definitions. */ + +void *spi_channels[] = {NULL}; + +const unsigned int num_spi_channels = 1;