1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/conf/landfall-examples/mips-jz4780-msc-block.cfg Sat Apr 27 23:46:28 2024 +0200 1.3 @@ -0,0 +1,87 @@ 1.4 +-- vim:set ft=lua: 1.5 + 1.6 +local L4 = require("L4"); 1.7 + 1.8 +local l = L4.default_loader; 1.9 + 1.10 +local io_buses = 1.11 + { 1.12 + common = l:new_channel(); 1.13 + }; 1.14 + 1.15 +l:start({ 1.16 + caps = { 1.17 + common = io_buses.common:svr(), 1.18 + icu = L4.Env.icu, 1.19 + sigma0 = L4.cast(L4.Proto.Factory, L4.Env.sigma0):create(L4.Proto.Sigma0), 1.20 + }, 1.21 + log = { "IO", "y" }, 1.22 + l4re_dbg = L4.Dbg.Warn, 1.23 + }, 1.24 + "rom/io rom/hw_devices.io rom/mips-jz4780-msc-block.io"); 1.25 + 1.26 +local block_server = l:new_channel(); 1.27 + 1.28 +l:startv({ 1.29 + caps = { 1.30 + fsserver = block_server:svr(), 1.31 + jdb = L4.Env.jdb, -- to set the server name 1.32 + icu = L4.Env.icu, 1.33 + vbus = io_buses.common, 1.34 + }, 1.35 + log = { "server", "r" }, 1.36 + }, 1.37 + -- arguments: machine, MSC channel/device, DMA channel, card index, memory pages 1.38 + "rom/msc_block_server", "jz4780", "0", "0", "0", "10"); 1.39 + 1.40 +local pipe_server = l:new_channel(); 1.41 + 1.42 +l:startv({ 1.43 + caps = { 1.44 + pipeserver = pipe_server:svr(), 1.45 + jdb = L4.Env.jdb, -- to set the server name 1.46 + }, 1.47 + log = { "pipes", "r" }, 1.48 + }, 1.49 + "rom/pipe_server", "10"); 1.50 + 1.51 +local ext2server = l:new_channel(); 1.52 + 1.53 +l:startv({ 1.54 + caps = { 1.55 + blockserver = block_server, 1.56 + pipeserver = pipe_server, 1.57 + fsserver = ext2server:svr(), 1.58 + jdb = L4.Env.jdb, -- to set the server name 1.59 + }, 1.60 + log = { "ext2svr", "y" }, 1.61 + }, 1.62 + "rom/ext2_server", "blockserver", "1", "20", "fsserver"); 1.63 + 1.64 +-- Obtain user filesystems with umask 0022 (18). 1.65 + 1.66 +local open_for_user = 6; 1.67 +local ext2server_paulb = L4.cast(L4.Proto.Factory, ext2server):create(open_for_user, 1000, 1000, 18); 1.68 + 1.69 +local process_server = l:new_channel(); 1.70 + 1.71 +l:startv({ 1.72 + caps = { 1.73 + fsserver = ext2server_paulb, 1.74 + prserver = process_server:svr(), 1.75 + jdb = L4.Env.jdb, -- to set the server name 1.76 + }, 1.77 + log = { "process", "y" }, 1.78 + }, 1.79 + "rom/process_server", "l4/exec_region_mapper"); 1.80 + 1.81 +l:startv({ 1.82 + log = L4.Env.log, 1.83 + caps = { 1.84 + fsserver = ext2server_paulb, 1.85 + pipeserver = pipe_server, 1.86 + prserver = process_server, 1.87 + }, 1.88 + }, 1.89 + -- program, options, operation involving a script file 1.90 + "rom/fsaccess", "-m", "0022", "script", "-");
2.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 2.2 +++ b/conf/landfall-examples/mips-jz4780-msc-block.io Sat Apr 27 23:46:28 2024 +0200 2.3 @@ -0,0 +1,14 @@ 2.4 +-- vi:ft=lua 2.5 +-- configuration file for io 2.6 + 2.7 +local hw = Io.system_bus() 2.8 + 2.9 +local bus = Io.Vi.System_bus 2.10 +{ 2.11 + CPM = wrap(hw:match("jz4780-cpm")); 2.12 + DMA = wrap(hw:match("jz4780-dma")); 2.13 + GPIO = wrap(hw:match("jz4780-gpio")); 2.14 + MSC = wrap(hw:match("jz4780-msc")); 2.15 +} 2.16 + 2.17 +Io.add_vbus("common", bus)
3.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 3.2 +++ b/conf/landfall-examples/mips-jz4780-msc-block.list Sat Apr 27 23:46:28 2024 +0200 3.3 @@ -0,0 +1,18 @@ 3.4 + 3.5 +modaddr 0x1100000 3.6 + 3.7 +entry mips-jz4780-msc-block 3.8 +bootstrap bootstrap -serial 3.9 +kernel fiasco -serial_esc 3.10 +roottask moe rom/mips-jz4780-msc-block.cfg 3.11 +module mips-jz4780-msc-block.cfg 3.12 +module mips-jz4780-msc-block.io 3.13 +module plat-ingenic-jz4780/hw_devices.io 3.14 +module l4re 3.15 +module io 3.16 +module ned 3.17 +module msc_block_server 3.18 +module ext2_server 3.19 +module pipe_server 3.20 +module process_server 3.21 +module fsaccess
4.1 --- a/conf/landfall-examples/mips-x1600-msc-block.cfg Wed Apr 24 00:47:34 2024 +0200 4.2 +++ b/conf/landfall-examples/mips-x1600-msc-block.cfg Sat Apr 27 23:46:28 2024 +0200 4.3 @@ -31,8 +31,8 @@ 4.4 }, 4.5 log = { "server", "r" }, 4.6 }, 4.7 - -- arguments: MSC channel/device, DMA channel, card index, memory pages 4.8 - "rom/msc_block_server", "0", "0", "0", "10"); 4.9 + -- arguments: machine, MSC channel/device, DMA channel, card index, memory pages 4.10 + "rom/msc_block_server", "x1600", "0", "0", "0", "10"); 4.11 4.12 local pipe_server = l:new_channel(); 4.13
5.1 --- a/pkg/devices/cpm/src/jz4730/cpm-jz4730.cc Wed Apr 24 00:47:34 2024 +0200 5.2 +++ b/pkg/devices/cpm/src/jz4730/cpm-jz4730.cc Sat Apr 27 23:46:28 2024 +0200 5.3 @@ -94,7 +94,7 @@ 5.4 5.5 /* Initialise the CPM abstraction. */ 5.6 5.7 - Cpm_jz4730_chip cpm_device(cpm_virt_base, 3686400); 5.8 + Cpm_jz4730_chip cpm_device(cpm_virt_base); 5.9 5.10 /* Initialise and register a server object. */ 5.11
6.1 --- a/pkg/devices/include/clocks.h Wed Apr 24 00:47:34 2024 +0200 6.2 +++ b/pkg/devices/include/clocks.h Sat Apr 27 23:46:28 2024 +0200 6.3 @@ -1,7 +1,7 @@ 6.4 /* 6.5 * Clock identifiers for clock and power management. 6.6 * 6.7 - * Copyright (C) 2021, 2023 Paul Boddie <paul@boddie.org.uk> 6.8 + * Copyright (C) 2021, 2023, 2024 Paul Boddie <paul@boddie.org.uk> 6.9 * 6.10 * This program is free software; you can redistribute it and/or 6.11 * modify it under the terms of the GNU General Public License as 6.12 @@ -41,7 +41,7 @@ 6.13 Clock_dma, 6.14 Clock_emac, 6.15 Clock_external, /* EXCLK */ 6.16 - Clock_external_div_512, 6.17 + Clock_external_div, /* EXCLK/128 (JZ4730) or EXCLK/512 (JZ4780) */ 6.18 Clock_hclock0, /* AHB0 */ 6.19 Clock_hclock2, /* AHB2 */ 6.20 Clock_hclock2_pclock, /* AHB2, APB parent clock (JZ4780, X1600) */ 6.21 @@ -64,6 +64,7 @@ 6.22 Clock_lcd_pixel1, 6.23 Clock_mac, 6.24 Clock_main, /* SCLK_A */ 6.25 + Clock_mclock, /* EMC and SDRAM parent clock (JZ4730) */ 6.26 Clock_mipi_csi, 6.27 Clock_msc, /* MSC parent clock (JZ4780) */ 6.28 Clock_msc0, 6.29 @@ -74,6 +75,7 @@ 6.30 Clock_otg1, 6.31 Clock_pclock, /* APB */ 6.32 Clock_pcm, 6.33 + Clock_pll, 6.34 Clock_pll_A, 6.35 Clock_pll_E, 6.36 Clock_pll_M,
7.1 --- a/pkg/devices/lcd/src/jz4780/lcd-jz4780-spi-device.cc Wed Apr 24 00:47:34 2024 +0200 7.2 +++ b/pkg/devices/lcd/src/jz4780/lcd-jz4780-spi-device.cc Sat Apr 27 23:46:28 2024 +0200 7.3 @@ -62,7 +62,7 @@ 7.4 static Gpio_jz4780_chip *gpio_chip; 7.5 static Spi_jz4780_chip *spi_chip; 7.6 7.7 -static Dma_jz4780_channel *dma_channel; 7.8 +static Dma_channel *dma_channel; 7.9 static Spi_hybrid *spi_channel; 7.10 static Spi_jz4780_channel *spi_jz4780_channel; 7.11
8.1 --- a/pkg/devices/lib/cpm/include/cpm-common.h Wed Apr 24 00:47:34 2024 +0200 8.2 +++ b/pkg/devices/lib/cpm/include/cpm-common.h Sat Apr 27 23:46:28 2024 +0200 8.3 @@ -64,6 +64,7 @@ 8.4 uint8_t bit; 8.5 bool defined; 8.6 uint32_t adjustment; 8.7 + const int *table = NULL; 8.8 uint32_t _asserted = 0, _deasserted = 0; 8.9 8.10 public: 8.11 @@ -72,6 +73,16 @@ 8.12 { 8.13 } 8.14 8.15 + // Field with table describing the encoded value. 8.16 + 8.17 + explicit Field(uint32_t reg, uint32_t mask, uint32_t bit, const int *table) 8.18 + : reg(reg), mask(mask), bit(bit), defined(true), table(table) 8.19 + { 8.20 + _asserted = mask; 8.21 + } 8.22 + 8.23 + // Field with possible inversion and encoded value adjustment. 8.24 + 8.25 explicit Field(uint32_t reg, uint32_t mask, uint32_t bit, 8.26 bool inverted = false, uint32_t adjustment = 0) 8.27 : reg(reg), mask(mask), bit(bit), defined(true), adjustment(adjustment)
9.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 9.2 +++ b/pkg/devices/lib/cpm/include/cpm-generic.h Sat Apr 27 23:46:28 2024 +0200 9.3 @@ -0,0 +1,88 @@ 9.4 +/* 9.5 + * Common clock and power management (CPM) abstractions. 9.6 + * 9.7 + * Copyright (C) 2017, 2018, 2020, 2021, 2023 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/devices/cpm-common.h> 9.28 +#include <l4/sys/types.h> 9.29 +#include <stdint.h> 9.30 + 9.31 + 9.32 + 9.33 +#ifdef __cplusplus 9.34 + 9.35 +/* A transitional abstraction supporting older CPM abstractions. */ 9.36 + 9.37 +class Cpm_chip_base 9.38 +{ 9.39 +public: 9.40 + virtual int have_clock(enum Clock_identifiers clock) = 0; 9.41 + virtual void start_clock(enum Clock_identifiers clock) = 0; 9.42 + virtual void stop_clock(enum Clock_identifiers clock) = 0; 9.43 +}; 9.44 + 9.45 +/* A simple abstraction for accessing the CPM registers. */ 9.46 + 9.47 +class Cpm_chip : public Cpm_chip_base 9.48 +{ 9.49 +protected: 9.50 + Clock_base **_clocks; 9.51 + Cpm_regs _cpm_regs; 9.52 + 9.53 +public: 9.54 + explicit Cpm_chip(l4_addr_t addr, Clock_base *clocks[]); 9.55 + 9.56 + const char *clock_type(enum Clock_identifiers clock); 9.57 + 9.58 + // Clock control. 9.59 + 9.60 + int have_clock(enum Clock_identifiers clock); 9.61 + void start_clock(enum Clock_identifiers clock); 9.62 + void stop_clock(enum Clock_identifiers clock); 9.63 + 9.64 + // Clock dividers. 9.65 + 9.66 + int get_parameters(enum Clock_identifiers clock, uint32_t parameters[]); 9.67 + int set_parameters(enum Clock_identifiers clock, int num_parameters, 9.68 + uint32_t parameters[]); 9.69 + 9.70 + // Clock sources. 9.71 + 9.72 + uint8_t get_source(enum Clock_identifiers clock); 9.73 + void set_source(enum Clock_identifiers clock, uint8_t source); 9.74 + enum Clock_identifiers get_source_clock(enum Clock_identifiers clock); 9.75 + void set_source_clock(enum Clock_identifiers clock, enum Clock_identifiers source); 9.76 + 9.77 + // Source frequencies. 9.78 + 9.79 + uint64_t get_source_frequency(enum Clock_identifiers clock); 9.80 + 9.81 + // Output clock frequencies. 9.82 + 9.83 + uint64_t get_frequency(enum Clock_identifiers clock); 9.84 + int set_frequency(enum Clock_identifiers clock, uint64_t frequency); 9.85 +}; 9.86 + 9.87 +/* Generic access to the CPM abstraction. */ 9.88 + 9.89 +Cpm_chip *new_cpm_chip(const char *name, l4_addr_t cpm_base); 9.90 + 9.91 +#endif /* __cplusplus */
10.1 --- a/pkg/devices/lib/cpm/include/cpm-jz4730.h Wed Apr 24 00:47:34 2024 +0200 10.2 +++ b/pkg/devices/lib/cpm/include/cpm-jz4730.h Sat Apr 27 23:46:28 2024 +0200 10.3 @@ -1,7 +1,8 @@ 10.4 /* 10.5 * CPM (clock and power management) support for the JZ4730. 10.6 * 10.7 - * Copyright (C) 2017, 2018, 2020, 2021, 2023 Paul Boddie <paul@boddie.org.uk> 10.8 + * Copyright (C) 2017, 2018, 2020, 2021, 2023, 10.9 + * 2024 Paul Boddie <paul@boddie.org.uk> 10.10 * 10.11 * This program is free software; you can redistribute it and/or 10.12 * modify it under the terms of the GNU General Public License as 10.13 @@ -27,77 +28,39 @@ 10.14 10.15 10.16 10.17 +/* JZ4730-specific clocks. */ 10.18 + 10.19 +enum Clock_jz4730_identifiers 10.20 +{ 10.21 + Clock_jz4730_identifier_base = Clock_specific_start, 10.22 + 10.23 + /* Actual clocks. */ 10.24 + 10.25 + Clock_lcd_pixel_in = Clock_specific_start, 10.26 + Clock_msc_16MHz, 10.27 + Clock_msc_24MHz, 10.28 + Clock_pll_div_2, 10.29 + Clock_pll_usb, 10.30 + Clock_usb_phy_48MHz, 10.31 + 10.32 + /* Not a clock: limit for array definition. */ 10.33 + 10.34 + Clock_jz4730_identifier_count, 10.35 +}; 10.36 + 10.37 + 10.38 + 10.39 #ifdef __cplusplus 10.40 10.41 -#include <l4/devices/cpm.h> 10.42 -#include <l4/devices/hw_register_block.h> 10.43 - 10.44 -/* A simple abstraction for accessing the CPM registers. 10.45 - * A proper device could inherit from Hw::Device and use an 10.46 - * Int_property for _exclk_freq. */ 10.47 - 10.48 -class Cpm_jz4730_chip : public Cpm_chip_base 10.49 -{ 10.50 -private: 10.51 - Hw::Register_block<32> _regs; 10.52 - uint32_t _exclk_freq; 10.53 - 10.54 - // Utility methods. 10.55 - 10.56 - uint8_t _get_divider(uint32_t reg, uint32_t mask, uint8_t shift); 10.57 - 10.58 - // PLL status. 10.59 - 10.60 - int have_pll(); 10.61 - int pll_enabled(); 10.62 - int pll_bypassed(); 10.63 - 10.64 - // Clock control. 10.65 - 10.66 - uint32_t get_clock_gate_value(enum Clock_identifiers clock); 10.67 - 10.68 -public: 10.69 - Cpm_jz4730_chip(l4_addr_t addr, uint32_t exclk_freq); 10.70 - 10.71 - // PLL configuration. 10.72 +#include <l4/devices/cpm-generic.h> 10.73 10.74 - uint16_t get_multiplier(); 10.75 - uint8_t get_input_division(); 10.76 - uint8_t get_output_division(); 10.77 - 10.78 - // Divider configuration. 10.79 - 10.80 - uint8_t get_cpu_divider(); 10.81 - uint8_t get_hclock_divider(); 10.82 - uint8_t get_pclock_divider(); 10.83 - uint8_t get_memory_divider(); 10.84 - uint8_t get_source_divider(); 10.85 - uint16_t get_lcd_pixel_divider(); 10.86 - 10.87 - void set_lcd_device_divider(uint8_t division); 10.88 - void set_lcd_pixel_divider(uint16_t division); 10.89 - 10.90 - // PLL frequency status. 10.91 +class Cpm_jz4730_chip : public Cpm_chip 10.92 +{ 10.93 +public: 10.94 + Cpm_jz4730_chip(l4_addr_t addr); 10.95 +}; 10.96 10.97 - uint32_t get_pll_frequency(); 10.98 - uint32_t get_source_frequency(); 10.99 - 10.100 - // Clock frequency status. 10.101 - 10.102 - uint32_t get_cpu_frequency(); 10.103 - uint32_t get_hclock_frequency(); 10.104 - uint32_t get_pclock_frequency(); 10.105 - uint32_t get_memory_frequency(); 10.106 - 10.107 - // Clock configuration. 10.108 - 10.109 - uint32_t get_frequency(enum Clock_identifiers clock); 10.110 - void set_frequency(enum Clock_identifiers clock, uint32_t frequency); 10.111 - 10.112 - int have_clock(enum Clock_identifiers clock); 10.113 - void start_clock(enum Clock_identifiers clock); 10.114 - void stop_clock(enum Clock_identifiers clock); 10.115 -}; 10.116 +Cpm_chip *jz4730_cpm_chip(l4_addr_t cpm_base); 10.117 10.118 #endif /* __cplusplus */ 10.119 10.120 @@ -109,21 +72,25 @@ 10.121 10.122 void *jz4730_cpm_init(l4_addr_t cpm_base); 10.123 10.124 -int jz4730_cpm_have_pll(void *cpm); 10.125 +const char *jz4730_cpm_clock_type(void *cpm, enum Clock_identifiers clock); 10.126 10.127 int jz4730_cpm_have_clock(void *cpm, enum Clock_identifiers clock); 10.128 void jz4730_cpm_start_clock(void *cpm, enum Clock_identifiers clock); 10.129 void jz4730_cpm_stop_clock(void *cpm, enum Clock_identifiers clock); 10.130 10.131 -uint16_t jz4730_cpm_get_lcd_pixel_divider(void *cpm); 10.132 - 10.133 -uint32_t jz4730_cpm_get_frequency(void *cpm, enum Clock_identifiers clock); 10.134 -void jz4730_cpm_set_frequency(void *cpm, enum Clock_identifiers clock, uint32_t frequency); 10.135 +int jz4730_cpm_get_parameters(void *cpm, enum Clock_identifiers clock, 10.136 + uint32_t parameters[]); 10.137 +int jz4730_cpm_set_parameters(void *cpm, enum Clock_identifiers clock, 10.138 + int num_parameters, uint32_t parameters[]); 10.139 10.140 -uint32_t jz4730_cpm_get_cpu_frequency(void *cpm); 10.141 -uint32_t jz4730_cpm_get_hclock_frequency(void *cpm); 10.142 -uint32_t jz4730_cpm_get_source_frequency(void *cpm); 10.143 -uint32_t jz4730_cpm_get_pclock_frequency(void *cpm); 10.144 -uint32_t jz4730_cpm_get_memory_frequency(void *cpm); 10.145 +uint8_t jz4730_cpm_get_source(void *cpm, enum Clock_identifiers clock); 10.146 +void jz4730_cpm_set_source(void *cpm, enum Clock_identifiers clock, uint8_t source); 10.147 +enum Clock_identifiers jz4730_cpm_get_source_clock(void *cpm, enum Clock_identifiers clock); 10.148 +void jz4730_cpm_set_source_clock(void *cpm, enum Clock_identifiers clock, enum Clock_identifiers source); 10.149 + 10.150 +uint64_t jz4730_cpm_get_source_frequency(void *cpm, enum Clock_identifiers clock); 10.151 + 10.152 +uint64_t jz4730_cpm_get_frequency(void *cpm, enum Clock_identifiers clock); 10.153 +int jz4730_cpm_set_frequency(void *cpm, enum Clock_identifiers clock, uint64_t frequency); 10.154 10.155 EXTERN_C_END
11.1 --- a/pkg/devices/lib/cpm/include/cpm-jz4740.h Wed Apr 24 00:47:34 2024 +0200 11.2 +++ b/pkg/devices/lib/cpm/include/cpm-jz4740.h Sat Apr 27 23:46:28 2024 +0200 11.3 @@ -1,7 +1,8 @@ 11.4 /* 11.5 * CPM (clock and power management) support for the JZ4740. 11.6 * 11.7 - * Copyright (C) 2017, 2018, 2020, 2021, 2023 Paul Boddie <paul@boddie.org.uk> 11.8 + * Copyright (C) 2017, 2018, 2020, 2021, 2023, 11.9 + * 2024 Paul Boddie <paul@boddie.org.uk> 11.10 * 11.11 * This program is free software; you can redistribute it and/or 11.12 * modify it under the terms of the GNU General Public License as 11.13 @@ -29,7 +30,7 @@ 11.14 11.15 #ifdef __cplusplus 11.16 11.17 -#include <l4/devices/cpm.h> 11.18 +#include <l4/devices/cpm-generic.h> 11.19 #include <l4/devices/hw_register_block.h> 11.20 11.21 /* A simple abstraction for accessing the CPM registers. 11.22 @@ -100,6 +101,8 @@ 11.23 11.24 }; 11.25 11.26 +// Cpm_chip *jz4740_cpm_chip(l4_addr_t cpm_base); 11.27 + 11.28 #endif /* __cplusplus */ 11.29 11.30
12.1 --- a/pkg/devices/lib/cpm/include/cpm-jz4780.h Wed Apr 24 00:47:34 2024 +0200 12.2 +++ b/pkg/devices/lib/cpm/include/cpm-jz4780.h Sat Apr 27 23:46:28 2024 +0200 12.3 @@ -1,7 +1,8 @@ 12.4 /* 12.5 * CPM (clock and power management) support for the JZ4780. 12.6 * 12.7 - * Copyright (C) 2017, 2018, 2020, 2021, 2023 Paul Boddie <paul@boddie.org.uk> 12.8 + * Copyright (C) 2017, 2018, 2020, 2021, 2023, 12.9 + * 2024 Paul Boddie <paul@boddie.org.uk> 12.10 * 12.11 * This program is free software; you can redistribute it and/or 12.12 * modify it under the terms of the GNU General Public License as 12.13 @@ -43,7 +44,7 @@ 12.14 12.15 #ifdef __cplusplus 12.16 12.17 -#include <l4/devices/cpm.h> 12.18 +#include <l4/devices/cpm-generic.h> 12.19 12.20 class Cpm_jz4780_chip : public Cpm_chip 12.21 { 12.22 @@ -51,6 +52,8 @@ 12.23 explicit Cpm_jz4780_chip(l4_addr_t addr); 12.24 }; 12.25 12.26 +Cpm_chip *jz4780_cpm_chip(l4_addr_t cpm_base); 12.27 + 12.28 #endif /* __cplusplus */ 12.29 12.30
13.1 --- a/pkg/devices/lib/cpm/include/cpm-x1600.h Wed Apr 24 00:47:34 2024 +0200 13.2 +++ b/pkg/devices/lib/cpm/include/cpm-x1600.h Sat Apr 27 23:46:28 2024 +0200 13.3 @@ -1,7 +1,8 @@ 13.4 /* 13.5 * CPM (clock and power management) support for the X1600. 13.6 * 13.7 - * Copyright (C) 2017, 2018, 2020, 2021, 2023 Paul Boddie <paul@boddie.org.uk> 13.8 + * Copyright (C) 2017, 2018, 2020, 2021, 2023, 13.9 + * 2024 Paul Boddie <paul@boddie.org.uk> 13.10 * 13.11 * This program is free software; you can redistribute it and/or 13.12 * modify it under the terms of the GNU General Public License as 13.13 @@ -40,7 +41,7 @@ 13.14 13.15 #ifdef __cplusplus 13.16 13.17 -#include <l4/devices/cpm.h> 13.18 +#include <l4/devices/cpm-generic.h> 13.19 13.20 class Cpm_x1600_chip : public Cpm_chip 13.21 { 13.22 @@ -48,6 +49,8 @@ 13.23 explicit Cpm_x1600_chip(l4_addr_t addr); 13.24 }; 13.25 13.26 +Cpm_chip *x1600_cpm_chip(l4_addr_t cpm_base); 13.27 + 13.28 #endif /* __cplusplus */ 13.29 13.30
14.1 --- a/pkg/devices/lib/cpm/src/Makefile Wed Apr 24 00:47:34 2024 +0200 14.2 +++ b/pkg/devices/lib/cpm/src/Makefile Sat Apr 27 23:46:28 2024 +0200 14.3 @@ -4,7 +4,7 @@ 14.4 TARGET = libcpm.o.a libcpm.o.so 14.5 PC_FILENAME := libdrivers-cpm 14.6 14.7 -SRC_CC := chip.cc common.cc jz4730.cc jz4740.cc jz4780.cc x1600.cc 14.8 +SRC_CC := chip.cc common.cc generic.cc jz4730.cc jz4740.cc jz4780.cc x1600.cc 14.9 14.10 PRIVATE_INCDIR += $(PKGDIR)/lib/cpm/include 14.11
15.1 --- a/pkg/devices/lib/cpm/src/chip.cc Wed Apr 24 00:47:34 2024 +0200 15.2 +++ b/pkg/devices/lib/cpm/src/chip.cc Sat Apr 27 23:46:28 2024 +0200 15.3 @@ -1,7 +1,7 @@ 15.4 /* 15.5 * Common clock and power management functionality. 15.6 * 15.7 - * Copyright (C) 2023 Paul Boddie <paul@boddie.org.uk> 15.8 + * Copyright (C) 2023, 2024 Paul Boddie <paul@boddie.org.uk> 15.9 * 15.10 * This program is free software; you can redistribute it and/or 15.11 * modify it under the terms of the GNU General Public License as 15.12 @@ -19,8 +19,8 @@ 15.13 * Boston, MA 02110-1301, USA 15.14 */ 15.15 15.16 -#include "cpm.h" 15.17 #include "cpm-common.h" 15.18 +#include "cpm-generic.h" 15.19 15.20 15.21
16.1 --- a/pkg/devices/lib/cpm/src/common.cc Wed Apr 24 00:47:34 2024 +0200 16.2 +++ b/pkg/devices/lib/cpm/src/common.cc Sat Apr 27 23:46:28 2024 +0200 16.3 @@ -63,7 +63,15 @@ 16.4 Field::get_field(Cpm_regs ®s) 16.5 { 16.6 if (defined) 16.7 - return regs.get_field(reg, mask, bit) + adjustment; 16.8 + { 16.9 + // With an encoding table, use the encoded value as index to obtain the 16.10 + // genuine value. 16.11 + 16.12 + if (table != NULL) 16.13 + return table[regs.get_field(reg, mask, bit)]; 16.14 + else 16.15 + return regs.get_field(reg, mask, bit) + adjustment; 16.16 + } 16.17 else 16.18 return 0; 16.19 } 16.20 @@ -72,7 +80,18 @@ 16.21 Field::set_field(Cpm_regs ®s, uint32_t value) 16.22 { 16.23 if (defined) 16.24 - regs.set_field(reg, mask, bit, value >= adjustment ? value - adjustment : 0); 16.25 + { 16.26 + // With an encoding table, find the index of the presented value. 16.27 + 16.28 + if (table != NULL) 16.29 + { 16.30 + for (uint32_t i = 0; i < mask; i++) 16.31 + if (table[i] == value) 16.32 + regs.set_field(reg, mask, bit, i); 16.33 + } 16.34 + else 16.35 + regs.set_field(reg, mask, bit, value >= adjustment ? value - adjustment : 0); 16.36 + } 16.37 } 16.38 16.39 // Undefined field.
17.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 17.2 +++ b/pkg/devices/lib/cpm/src/generic.cc Sat Apr 27 23:46:28 2024 +0200 17.3 @@ -0,0 +1,57 @@ 17.4 +/* 17.5 + * Generic access to clock and power management functionality. 17.6 + * 17.7 + * Copyright (C) 2024 Paul Boddie <paul@boddie.org.uk> 17.8 + * 17.9 + * This program is free software; you can redistribute it and/or 17.10 + * modify it under the terms of the GNU General Public License as 17.11 + * published by the Free Software Foundation; either version 2 of 17.12 + * the License, or (at your option) any later version. 17.13 + * 17.14 + * This program is distributed in the hope that it will be useful, 17.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 17.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17.17 + * GNU General Public License for more details. 17.18 + * 17.19 + * You should have received a copy of the GNU General Public License 17.20 + * along with this program; if not, write to the Free Software 17.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, 17.22 + * Boston, MA 02110-1301, USA 17.23 + */ 17.24 + 17.25 +#include <string.h> 17.26 +#include "cpm-generic.h" 17.27 + 17.28 +/* Function declarations reproduced here to avoid clock identifier conflicts in 17.29 + the chip-specific headers. */ 17.30 + 17.31 +// NOTE: To be supported... 17.32 +//extern Cpm_chip *jz4730_cpm_chip(l4_addr_t); 17.33 +//extern Cpm_chip *jz4740_cpm_chip(l4_addr_t); 17.34 +extern Cpm_chip *jz4780_cpm_chip(l4_addr_t); 17.35 +extern Cpm_chip *x1600_cpm_chip(l4_addr_t); 17.36 + 17.37 +struct cpm_function 17.38 +{ 17.39 + const char *name; 17.40 + Cpm_chip *(*function)(l4_addr_t); 17.41 +}; 17.42 + 17.43 +static struct cpm_function functions[] = { 17.44 + //{"jz4730", jz4730_cpm_chip}, 17.45 + //{"jz4740", jz4740_cpm_chip}, 17.46 + {"jz4780", jz4780_cpm_chip}, 17.47 + {"x1600", x1600_cpm_chip}, 17.48 + {NULL, NULL} 17.49 +}; 17.50 + 17.51 +Cpm_chip *new_cpm_chip(const char *name, l4_addr_t cpm_base) 17.52 +{ 17.53 + for (struct cpm_function *f = functions; f->name != NULL; f++) 17.54 + { 17.55 + if (!strcmp(name, f->name)) 17.56 + return f->function(cpm_base); 17.57 + } 17.58 + 17.59 + return NULL; 17.60 +}
18.1 --- a/pkg/devices/lib/cpm/src/jz4730.cc Wed Apr 24 00:47:34 2024 +0200 18.2 +++ b/pkg/devices/lib/cpm/src/jz4730.cc Sat Apr 27 23:46:28 2024 +0200 18.3 @@ -3,7 +3,8 @@ 18.4 * provided by the jz4730. The power management functionality could be exposed 18.5 * using a separate driver. 18.6 * 18.7 - * Copyright (C) 2017, 2018, 2020, 2021, 2023 Paul Boddie <paul@boddie.org.uk> 18.8 + * Copyright (C) 2017, 2018, 2020, 2021, 2023, 18.9 + * 2024 Paul Boddie <paul@boddie.org.uk> 18.10 * 18.11 * This program is free software; you can redistribute it and/or 18.12 * modify it under the terms of the GNU General Public License as 18.13 @@ -30,456 +31,369 @@ 18.14 { 18.15 Clock_control = 0x000, // CFCR (CPCCR in JZ4740) 18.16 Pll_control = 0x010, // PLCR1 (CPPCR in JZ4740) 18.17 + Exclk_oscillator = 0x01c, // OCR 18.18 Clock_gate = 0x020, // MSCR (CLKGR in JZ4740) 18.19 Sleep_control = 0x024, // SCR 18.20 Lcd_divider = 0x060, // CFCR2 18.21 }; 18.22 18.23 -enum Clock_bits : unsigned 18.24 -{ 18.25 - Clock_change_enable = 20, // UPE 18.26 - Clock_memory_divider = 16, // MFR 18.27 - Clock_lcd_divider = 12, // LFR 18.28 - Clock_pclock_divider = 8, // PFR (slow APB peripherals) 18.29 - Clock_hclock_divider = 4, // SFR (fast AHB peripherals) 18.30 - Clock_cpu_divider = 0, // IFR 18.31 -}; 18.32 + 18.33 + 18.34 +// Encoded value tables. 18.35 + 18.36 +static const uint32_t dv[] = {1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 1, 1, 1, 1, 1, 1}; 18.37 +static const uint32_t plldv[] = {1, 2, 2, 4}; 18.38 + 18.39 + 18.40 + 18.41 +// Register field definitions. 18.42 18.43 -enum Pll_bits : unsigned 18.44 -{ 18.45 - Pll_multiplier = 23, // PLL1FD 18.46 - Pll_input_division = 18, // PLL1RD 18.47 - Pll_output_division = 16, // PLL1OD 18.48 - Pll_stable = 10, // PLL1S 18.49 - Pll_bypassed = 9, // PLL1BP 18.50 - Pll_enabled = 8, // PLL1EN 18.51 -}; 18.52 +static Field Clock_source_ssi (Clock_control, 1, 31), // SCS 18.53 + Clock_source_lcd (Clock_control, 1, 30), // LCS 18.54 + Clock_source_i2s (Clock_control, 1, 29), // I2CS 18.55 + Clock_source_usb (Clock_control, 1, 28), // UCS 18.56 + Clock_source_msc (Clock_control, 1, 24), // MCS 18.57 + Clock_source_rtc (Exclk_oscillator, 1, 8), // O2SE 18.58 + 18.59 + Clock_change_enable (Clock_control, 1, 20), // UPE 18.60 + 18.61 + Clock_divider_cpu (Clock_control, 0x0f, 0, dv), // CFR 18.62 + Clock_divider_hclock (Clock_control, 0x0f, 4, dv), // HFR 18.63 + Clock_divider_pclock (Clock_control, 0x0f, 8, dv), // PFR 18.64 + Clock_divider_lcd (Clock_control, 0x0f, 12, false, 1), // LFR 18.65 + Clock_divider_mclock (Clock_control, 0x0f, 16, dv), // MFR 18.66 + Clock_divider_usb (Clock_control, 0x07, 25, false, 1), // UFR 18.67 + Clock_divider_lcd_pixel (Lcd_divider, 0x1ff, 0), // PXFR 18.68 18.69 -enum Clock_gate_bits : unsigned 18.70 -{ 18.71 - Clock_gate_uprt = 25, 18.72 - Clock_gate_udc = 24, 18.73 - Clock_gate_cim = 23, 18.74 - Clock_gate_kbc = 22, 18.75 - Clock_gate_emac = 21, 18.76 - Clock_gate_uart3 = 20, 18.77 - Clock_gate_aic_bitclk = 18, 18.78 - Clock_gate_scc = 14, 18.79 - Clock_gate_msc = 13, 18.80 - Clock_gate_ssi = 12, 18.81 - Clock_gate_pwm1 = 11, 18.82 - Clock_gate_pwm0 = 10, 18.83 - Clock_gate_aic_pclk = 9, 18.84 - Clock_gate_i2c = 8, 18.85 - Clock_gate_lcd = 7, 18.86 - Clock_gate_uhc = 6, 18.87 - Clock_gate_dmac = 5, 18.88 - Clock_gate_timer = 3, 18.89 - Clock_gate_uart2 = 2, 18.90 - Clock_gate_uart1 = 1, 18.91 - Clock_gate_uart0 = 0, 18.92 -}; 18.93 + Clock_gate_uprt (Clock_gate, 1, 25, true), 18.94 + Clock_gate_udc (Clock_gate, 1, 24, true), 18.95 + Clock_gate_cim (Clock_gate, 1, 23, true), 18.96 + Clock_gate_kbc (Clock_gate, 1, 22, true), 18.97 + Clock_gate_emac (Clock_gate, 1, 21, true), 18.98 + Clock_gate_uart3 (Clock_gate, 1, 20, true), 18.99 + Clock_gate_aic_bitclk (Clock_gate, 1, 18, true), 18.100 + Clock_gate_scc (Clock_gate, 1, 14, true), 18.101 + Clock_gate_msc (Clock_gate, 1, 13, true), 18.102 + Clock_gate_ssi (Clock_gate, 1, 12, true), 18.103 + Clock_gate_pwm1 (Clock_gate, 1, 11, true), 18.104 + Clock_gate_pwm0 (Clock_gate, 1, 10, true), 18.105 + Clock_gate_aic_pclk (Clock_gate, 1, 9, true), 18.106 + Clock_gate_i2c (Clock_gate, 1, 8, true), 18.107 + Clock_gate_lcd (Clock_gate, 1, 7, true), 18.108 + Clock_gate_uhc (Clock_gate, 1, 6, true), 18.109 + Clock_gate_dmac (Clock_gate, 1, 5, true), 18.110 + Clock_gate_timer (Clock_gate, 1, 3, true), 18.111 + Clock_gate_uart2 (Clock_gate, 1, 2, true), 18.112 + Clock_gate_uart1 (Clock_gate, 1, 1, true), 18.113 + Clock_gate_uart0 (Clock_gate, 1, 0, true), 18.114 + Clock_gate_sdram (Clock_control, 1, 22), 18.115 + 18.116 + Pll_enable (Pll_control, 1, 8), // PLLEN 18.117 + Pll_stable (Pll_control, 1, 10), // PLLS 18.118 + Pll_bypass (Pll_control, 1, 9), // PLLBP 18.119 + 18.120 + // Multiplier and input divider yield 2-based values. 18.121 18.122 -enum Lcd_divider_bits : unsigned 18.123 -{ 18.124 - Lcd_divider_value = 0, // PIXFR (in CFCR2) 18.125 -}; 18.126 + Pll_multiplier (Pll_control, 0x1ff, 23, false, 2), // PLLFD 18.127 + Pll_input_division (Pll_control, 0x1f, 18, false, 2), // PLLRD 18.128 + Pll_output_division (Pll_control, 0x03, 16, plldv); // PLLOD 18.129 + 18.130 + 18.131 + 18.132 +// Multiplexer instances. 18.133 + 18.134 +#define Clocks(...) ((enum Clock_identifiers []) {__VA_ARGS__}) 18.135 +#define Specific(CLOCK) ((enum Clock_identifiers) (CLOCK)) 18.136 + 18.137 +static Mux mux_external (Clock_external), 18.138 + 18.139 + // Clocks being propagated to others. 18.140 + 18.141 + mux_core (Clock_pll), 18.142 + mux_mclock (Clock_mclock), 18.143 + mux_hclock (Clock_hclock0), 18.144 + mux_pclock (Clock_pclock), 18.145 + 18.146 + // Clock selection. 18.147 + 18.148 + mux_i2s (2, Clocks(Clock_pll, Specific(Clock_pll_div_2))), 18.149 + mux_lcd_pixel (2, Clocks(Clock_lcd_pixel0, Specific(Clock_lcd_pixel_in))), 18.150 + mux_msc (2, Clocks(Specific(Clock_msc_16MHz), Specific(Clock_msc_24MHz))), 18.151 + mux_rtc (2, Clocks(Clock_external_div, Clock_rtc_external)), 18.152 + mux_ssi (2, Clocks(Clock_external, Clock_usb_phy)), 18.153 + mux_usb (2, Clocks(Specific(Clock_pll_usb), Specific(Clock_usb_phy_48MHz))); 18.154 18.155 18.156 18.157 -// If implemented as a Hw::Device, various properties would be 18.158 -// initialised in the constructor and obtained from the device tree 18.159 -// definitions. 18.160 +// Clock instances. 18.161 +// NOTE: Leaving the LCD pixel clock as a null clock. 18.162 18.163 -Cpm_jz4730_chip::Cpm_jz4730_chip(l4_addr_t addr, uint32_t exclk_freq) 18.164 -: _exclk_freq(exclk_freq) 18.165 -{ 18.166 - _regs = new Hw::Mmio_register_block<32>(addr); 18.167 - 18.168 - // add_cid("cpm"); 18.169 - // add_cid("cpm-jz4730"); 18.170 - // register_property("exclk_freq", &_exclk_freq); 18.171 -} 18.172 - 18.173 -// Clock/timer control. 18.174 +static Clock_null clock_none, 18.175 + clock_lcd_pixel_in; 18.176 18.177 -uint32_t 18.178 -Cpm_jz4730_chip::get_clock_gate_value(enum Clock_identifiers clock) 18.179 -{ 18.180 - switch (clock) 18.181 - { 18.182 - case Clock_uprt: return (1 << Clock_gate_uprt); 18.183 - case Clock_udc: return (1 << Clock_gate_udc); 18.184 - case Clock_cim: return (1 << Clock_gate_cim); 18.185 - case Clock_kbc: return (1 << Clock_gate_kbc); 18.186 - case Clock_emac: return (1 << Clock_gate_emac); 18.187 - case Clock_uart3: return (1 << Clock_gate_uart3); 18.188 - case Clock_aic_bitclk: return (1 << Clock_gate_aic_bitclk); 18.189 - case Clock_scc: return (1 << Clock_gate_scc); 18.190 - case Clock_msc0: return (1 << Clock_gate_msc); 18.191 - case Clock_ssi: return (1 << Clock_gate_ssi); 18.192 - case Clock_pwm1: return (1 << Clock_gate_pwm1); 18.193 - case Clock_pwm0: return (1 << Clock_gate_pwm0); 18.194 - case Clock_aic_pclk: return (1 << Clock_gate_aic_pclk); 18.195 - case Clock_i2c0: return (1 << Clock_gate_i2c); 18.196 - case Clock_lcd: return (1 << Clock_gate_lcd); 18.197 - case Clock_uhc: return (1 << Clock_gate_uhc); 18.198 - case Clock_dma: return (1 << Clock_gate_dmac); 18.199 - case Clock_timer: return (1 << Clock_gate_timer); 18.200 - case Clock_uart2: return (1 << Clock_gate_uart2); 18.201 - case Clock_uart1: return (1 << Clock_gate_uart1); 18.202 - case Clock_uart0: return (1 << Clock_gate_uart0); 18.203 - default: return 0; 18.204 - } 18.205 -} 18.206 +static Clock_passive clock_external(3686400), 18.207 + clock_mac(25000000), 18.208 + clock_msc_16MHz(16000000), 18.209 + clock_msc_24MHz(24000000), 18.210 + clock_rtc_external(32768), 18.211 + clock_usb_phy_48MHz(48000000); 18.212 18.213 -int 18.214 -Cpm_jz4730_chip::have_clock(enum Clock_identifiers clock) 18.215 -{ 18.216 - return !(_regs[Clock_gate] & get_clock_gate_value(clock)); 18.217 -} 18.218 +// Note the use of extra parentheses due to the annoying C++ "most vexing parse" 18.219 +// problem. See: https://en.wikipedia.org/wiki/Most_vexing_parse 18.220 18.221 -void 18.222 -Cpm_jz4730_chip::start_clock(enum Clock_identifiers clock) 18.223 -{ 18.224 - _regs[Clock_gate] = _regs[Clock_gate] & ~get_clock_gate_value(clock); 18.225 -} 18.226 - 18.227 -void 18.228 -Cpm_jz4730_chip::stop_clock(enum Clock_identifiers clock) 18.229 -{ 18.230 - _regs[Clock_gate] = _regs[Clock_gate] | get_clock_gate_value(clock); 18.231 -} 18.232 - 18.233 -// PLL control. 18.234 - 18.235 -// Return whether the PLL is stable. 18.236 - 18.237 -int 18.238 -Cpm_jz4730_chip::have_pll() 18.239 -{ 18.240 - return _regs[Pll_control] & (1 << Pll_stable); 18.241 -} 18.242 +static Clock 18.243 + clock_aic_bitclk((Source(mux_i2s)), Control(Clock_gate_aic_bitclk)), 18.244 + clock_aic_pclk((Source(mux_i2s)), Control(Clock_gate_aic_pclk)), 18.245 + clock_cim((Source(mux_hclock)), Control(Clock_gate_cim)), 18.246 + clock_dma((Source(mux_external)), Control(Clock_gate_dmac)), 18.247 + clock_emac((Source(mux_mclock)), Control(Clock_gate_emac)), 18.248 + clock_i2c0((Source(mux_external)), Control(Clock_gate_i2c)), 18.249 + clock_kbc((Source(mux_pclock)), Control(Clock_gate_kbc)), 18.250 + clock_msc0((Source(mux_msc)), Control(Clock_gate_msc)), 18.251 + clock_pwm0((Source(mux_external)), Control(Clock_gate_pwm0)), 18.252 + clock_pwm1((Source(mux_external)), Control(Clock_gate_pwm1)), 18.253 + clock_rtc((Source(mux_rtc))), 18.254 + clock_scc((Source(mux_external)), Control(Clock_gate_scc)), 18.255 + clock_sdram((Source(mux_mclock)), Control(Clock_gate_sdram)), 18.256 + clock_ssi0((Source(mux_ssi)), Control(Clock_gate_ssi)), 18.257 18.258 -int 18.259 -Cpm_jz4730_chip::pll_enabled() 18.260 -{ 18.261 - return _regs[Pll_control] & (1 << Pll_enabled); 18.262 -} 18.263 - 18.264 -int 18.265 -Cpm_jz4730_chip::pll_bypassed() 18.266 -{ 18.267 - return _regs[Pll_control] & (1 << Pll_bypassed); 18.268 -} 18.269 - 18.270 -// Feedback (9-bit) multiplier. 18.271 - 18.272 -uint16_t 18.273 -Cpm_jz4730_chip::get_multiplier() 18.274 -{ 18.275 - return ((_regs[Pll_control] & (0x1ff << Pll_multiplier)) >> Pll_multiplier) + 2; 18.276 -} 18.277 - 18.278 -// Input (5-bit) divider. 18.279 - 18.280 -uint8_t 18.281 -Cpm_jz4730_chip::get_input_division() 18.282 -{ 18.283 - return ((_regs[Pll_control] & (0x1f << Pll_input_division)) >> Pll_input_division) + 2; 18.284 -} 18.285 - 18.286 -// Output divider. 18.287 - 18.288 -static uint8_t od[4] = {1, 2, 2, 4}; 18.289 + // Timer propagates pclock but OST may select external 18.290 + // or rtc instead. 18.291 18.292 -uint8_t 18.293 -Cpm_jz4730_chip::get_output_division() 18.294 -{ 18.295 - return od[(_regs[Pll_control] & (0x03 << Pll_output_division)) >> Pll_output_division]; 18.296 -} 18.297 - 18.298 -// General clock divider. 18.299 - 18.300 -static uint8_t cd[] = {1, 2, 3, 4, 6, 8, 12, 16, 24, 32}; 18.301 - 18.302 -uint8_t 18.303 -Cpm_jz4730_chip::_get_divider(uint32_t reg, uint32_t mask, uint8_t shift) 18.304 -{ 18.305 - uint8_t d = (_regs[reg] & mask) >> shift; 18.306 - return (d < 10) ? cd[d] : 1; 18.307 -} 18.308 - 18.309 -// CPU clock (CCLK) divider. 18.310 - 18.311 -uint8_t 18.312 -Cpm_jz4730_chip::get_cpu_divider() 18.313 -{ 18.314 - return _get_divider(Clock_control, 0xf << Clock_cpu_divider, Clock_cpu_divider); 18.315 -} 18.316 - 18.317 -// Fast peripheral clock (HCLK) divider. 18.318 - 18.319 -uint8_t 18.320 -Cpm_jz4730_chip::get_hclock_divider() 18.321 -{ 18.322 - return _get_divider(Clock_control, 0xf << Clock_hclock_divider, Clock_hclock_divider); 18.323 -} 18.324 - 18.325 -// Slow peripheral clock (PCLK) divider. 18.326 - 18.327 -uint8_t 18.328 -Cpm_jz4730_chip::get_pclock_divider() 18.329 -{ 18.330 - return _get_divider(Clock_control, 0xf << Clock_pclock_divider, Clock_pclock_divider); 18.331 -} 18.332 - 18.333 -// Memory clock (MCLK) divider. 18.334 - 18.335 -uint8_t 18.336 -Cpm_jz4730_chip::get_memory_divider() 18.337 -{ 18.338 - return _get_divider(Clock_control, 0xf << Clock_memory_divider, Clock_memory_divider); 18.339 -} 18.340 - 18.341 -// Clock source divider for MSC, I2S, LCD and USB. 18.342 + clock_timer((Source(mux_pclock)), Control(Clock_gate_timer)), 18.343 + clock_uart0((Source(mux_external)), Control(Clock_gate_uart0)), 18.344 + clock_uart1((Source(mux_external)), Control(Clock_gate_uart1)), 18.345 + clock_uart2((Source(mux_external)), Control(Clock_gate_uart2)), 18.346 + clock_uart3((Source(mux_external)), Control(Clock_gate_uart3)), 18.347 + clock_udc((Source(mux_usb)), Control(Clock_gate_udc)), 18.348 + clock_uhc((Source(mux_usb)), Control(Clock_gate_uhc)), 18.349 + clock_uprt((Source(mux_external)), Control(Clock_gate_uprt)), 18.350 + clock_usb_phy((Source(mux_usb))); 18.351 18.352 -uint8_t 18.353 -Cpm_jz4730_chip::get_source_divider() 18.354 -{ 18.355 - return 1; 18.356 -} 18.357 - 18.358 -// LCD device clock divider. 18.359 - 18.360 -void 18.361 -Cpm_jz4730_chip::set_lcd_device_divider(uint8_t division) 18.362 -{ 18.363 - if (division == 0) 18.364 - division = 1; 18.365 - 18.366 - // NOTE: The vendor code (clock.c) bounds the divider at 16, but maybe this is 18.367 - // NOTE: confused with the width of the bitfield which actually contains an 18.368 - // NOTE: index for the clock divider value array (cd). 18.369 - 18.370 - else if (division > 16) 18.371 - division = 16; 18.372 - 18.373 - // Obtain the divider or closest higher divider. 18.374 - 18.375 - int i; 18.376 - 18.377 - for (i = 0; i < 10; i++) 18.378 - if (cd[i] >= division) break; 18.379 - 18.380 - _regs[Clock_control] = _regs[Clock_control] | (1 << Clock_change_enable); 18.381 +static Clock_divided 18.382 + clock_cpu(Source(mux_core), 18.383 + Control(Field::undefined, Clock_change_enable), 18.384 + Divider(Clock_divider_cpu)), 18.385 + clock_hclock(Source(mux_core), 18.386 + Control(Field::undefined, Clock_change_enable), 18.387 + Divider(Clock_divider_hclock)), 18.388 + clock_lcd(Source(mux_core), 18.389 + Control(Clock_gate_lcd, Clock_change_enable), 18.390 + Divider(Clock_divider_lcd)), 18.391 + clock_lcd_pixel(Source(mux_core), 18.392 + Control(Field::undefined, Clock_change_enable), 18.393 + Divider(Clock_divider_lcd_pixel)), 18.394 + clock_mclock(Source(mux_core), 18.395 + Control(Field::undefined, Clock_change_enable), 18.396 + Divider(Clock_divider_mclock)), 18.397 + clock_pclock(Source(mux_core), 18.398 + Control(Field::undefined, Clock_change_enable), 18.399 + Divider(Clock_divider_pclock)), 18.400 + clock_pll_usb(Source(mux_core), 18.401 + Control(Field::undefined, Clock_change_enable), 18.402 + Divider(Clock_divider_usb)); 18.403 18.404 - _regs[Clock_control] = (_regs[Clock_control] & ~(0xf << Clock_lcd_divider)) | 18.405 - (cd[i] << Clock_lcd_divider); 18.406 - 18.407 - _regs[Clock_control] = _regs[Clock_control] & ~(1 << Clock_change_enable); 18.408 -} 18.409 - 18.410 -// LCD pixel clock divider. 18.411 - 18.412 -uint16_t 18.413 -Cpm_jz4730_chip::get_lcd_pixel_divider() 18.414 -{ 18.415 - return (_regs[Lcd_divider] >> Lcd_divider_value) + 1; 18.416 -} 18.417 +static Clock_divided_fixed 18.418 + clock_external_div((Source(mux_external)), (Divider_fixed(128))), 18.419 + clock_pll_div_2((Source(mux_core)), (Divider_fixed(2))); 18.420 18.421 -void 18.422 -Cpm_jz4730_chip::set_lcd_pixel_divider(uint16_t division) 18.423 -{ 18.424 - if (division == 0) 18.425 - division = 1; 18.426 - else if (division > 512) 18.427 - division = 512; 18.428 +const double jz4730_pll_intermediate_min = 100000000, 18.429 + jz4730_pll_intermediate_max = 500000000; 18.430 18.431 - _regs[Clock_control] = _regs[Clock_control] | (1 << Clock_change_enable); 18.432 - 18.433 - _regs[Lcd_divider] = (_regs[Lcd_divider] & ~(0x1ff << Lcd_divider_value)) | 18.434 - ((division - 1) << Lcd_divider_value); 18.435 - 18.436 - _regs[Clock_control] = _regs[Clock_control] & ~(1 << Clock_change_enable); 18.437 -} 18.438 +static Pll clock_pll(Source(mux_external), 18.439 + Control_pll(Pll_enable, Pll_stable, Pll_bypass), 18.440 + Divider_pll(Pll_multiplier, Pll_input_division, 18.441 + Pll_output_division, 18.442 + jz4730_pll_intermediate_min, jz4730_pll_intermediate_max)); 18.443 18.444 18.445 18.446 -uint32_t 18.447 -Cpm_jz4730_chip::get_frequency(enum Clock_identifiers clock) 18.448 -{ 18.449 - if (clock == Clock_lcd_pixel0) 18.450 - return get_source_frequency() / get_lcd_pixel_divider(); 18.451 +// Clock register. 18.452 18.453 - // NOTE: Consider a better error result. 18.454 - return 0; 18.455 -} 18.456 - 18.457 -void 18.458 -Cpm_jz4730_chip::set_frequency(enum Clock_identifiers clock, uint32_t frequency) 18.459 -{ 18.460 - uint32_t out = get_source_frequency(); 18.461 +static Clock_base *clocks[Clock_jz4730_identifier_count] = { 18.462 + &clock_none, 18.463 18.464 - switch (clock) 18.465 - { 18.466 - // Limit the device frequency to 150MHz. 18.467 + &clock_none, // Clock_aic 18.468 + &clock_aic_bitclk, 18.469 + &clock_aic_pclk, 18.470 + &clock_none, // Clock_can0 18.471 + &clock_none, // Clock_can1 18.472 + &clock_none, // Clock_cdbus 18.473 + &clock_cim, 18.474 + &clock_cpu, 18.475 + &clock_sdram, // Clock_ddr 18.476 + &clock_dma, 18.477 + &clock_emac, 18.478 + &clock_external, 18.479 + &clock_external_div, 18.480 + &clock_hclock, // Clock_hclock0 18.481 + &clock_none, // Clock_hclock2 18.482 + &clock_none, // Clock_hclock2_pclock 18.483 + &clock_none, // Clock_hdmi 18.484 + &clock_i2c0, 18.485 + &clock_none, // Clock_i2c1 18.486 + &clock_none, // Clock_i2c2 18.487 + &clock_none, // Clock_i2c3 18.488 + &clock_none, // Clock_i2c4 18.489 + &clock_none, // Clock_i2s0 18.490 + &clock_none, // Clock_i2s0_rx 18.491 + &clock_none, // Clock_i2s0_tx 18.492 + &clock_none, // Clock_i2s1 18.493 + &clock_none, // Clock_i2s1_rx 18.494 + &clock_none, // Clock_i2s1_tx 18.495 + &clock_none, // Clock_kbc 18.496 + &clock_none, // Clock_l2cache 18.497 + &clock_lcd, 18.498 + &clock_lcd_pixel, // Clock_lcd_pixel0 18.499 + &clock_none, // Clock_lcd_pixel1 18.500 + &clock_mac, 18.501 + &clock_none, // Clock_main 18.502 + &clock_none, // Clock_mipi_csi 18.503 + &clock_none, // Clock_msc 18.504 + &clock_msc0, 18.505 + &clock_none, // Clock_msc1 18.506 + &clock_none, // Clock_msc2 18.507 + &clock_none, // Clock_nemc 18.508 + &clock_none, // Clock_otg0 18.509 + &clock_none, // Clock_otg1 18.510 + &clock_pclock, 18.511 + &clock_none, // Clock_pcm 18.512 + &clock_pll, 18.513 + &clock_none, // Clock_pll_A 18.514 + &clock_none, // Clock_pll_E 18.515 + &clock_none, // Clock_pll_M 18.516 + &clock_none, // Clock_pll_V 18.517 + &clock_pwm0, 18.518 + &clock_pwm1, 18.519 + &clock_rtc, 18.520 + &clock_rtc_external, 18.521 + &clock_none, // Clock_sadc 18.522 + &clock_scc, 18.523 + &clock_none, // Clock_sfc 18.524 + &clock_none, // Clock_ssi 18.525 + &clock_ssi0, 18.526 + &clock_none, // Clock_ssi1 18.527 + &clock_none, // Clock_ssi2 18.528 + &clock_none, // Clock_timer 18.529 + &clock_uart0, 18.530 + &clock_uart1, 18.531 + &clock_uart2, 18.532 + &clock_uart3, 18.533 + &clock_none, // Clock_uart4 18.534 + &clock_none, // Clock_udc 18.535 + &clock_uhc, 18.536 + &clock_uprt, 18.537 + &clock_usb_phy, 18.538 + &clock_none, // Clock_vpu 18.539 18.540 - case Clock_lcd: 18.541 - if (frequency > 150000000) 18.542 - frequency = 150000000; 18.543 - set_lcd_device_divider(out / frequency); 18.544 - break; 18.545 + /* JZ4730-specific clocks. */ 18.546 18.547 - case Clock_lcd_pixel0: 18.548 - set_lcd_pixel_divider(out / frequency); 18.549 - break; 18.550 - 18.551 - default: 18.552 - break; 18.553 - } 18.554 -} 18.555 + &clock_lcd_pixel_in, 18.556 + &clock_msc_16MHz, 18.557 + &clock_msc_24MHz, 18.558 + &clock_pll_div_2, 18.559 + &clock_pll_usb, 18.560 + &clock_usb_phy_48MHz, 18.561 +}; 18.562 18.563 18.564 - 18.565 -uint32_t 18.566 -Cpm_jz4730_chip::get_pll_frequency() 18.567 -{ 18.568 - // Test for PLL enable and not PLL bypass. 18.569 +// Peripheral abstraction. 18.570 18.571 - if (pll_enabled() && !pll_bypassed()) 18.572 - return (_exclk_freq * get_multiplier()) / 18.573 - (get_input_division() * get_output_division()); 18.574 - else 18.575 - return _exclk_freq; 18.576 +Cpm_jz4730_chip::Cpm_jz4730_chip(l4_addr_t addr) 18.577 +: Cpm_chip(addr, clocks) 18.578 +{ 18.579 } 18.580 18.581 -// Clock frequency for MSC, I2S, LCD and USB. 18.582 - 18.583 -uint32_t 18.584 -Cpm_jz4730_chip::get_source_frequency() 18.585 -{ 18.586 - return get_pll_frequency() / get_source_divider(); 18.587 -} 18.588 - 18.589 -// Clock frequency for the CPU. 18.590 - 18.591 -uint32_t Cpm_jz4730_chip::get_cpu_frequency() 18.592 -{ 18.593 - if (pll_enabled()) 18.594 - return get_pll_frequency() / get_cpu_divider(); 18.595 - else 18.596 - return _exclk_freq; 18.597 -} 18.598 - 18.599 -// Clock frequency for fast peripherals. 18.600 - 18.601 -uint32_t 18.602 -Cpm_jz4730_chip::get_hclock_frequency() 18.603 +Cpm_chip * 18.604 +jz4730_cpm_chip(l4_addr_t cpm_base) 18.605 { 18.606 - if (pll_enabled()) 18.607 - return get_pll_frequency() / get_hclock_divider(); 18.608 - else 18.609 - return _exclk_freq; 18.610 -} 18.611 - 18.612 -// Clock frequency for slow peripherals. 18.613 - 18.614 -uint32_t 18.615 -Cpm_jz4730_chip::get_pclock_frequency() 18.616 -{ 18.617 - if (pll_enabled()) 18.618 - return get_pll_frequency() / get_pclock_divider(); 18.619 - else 18.620 - return _exclk_freq; 18.621 -} 18.622 - 18.623 -// Clock frequency for the memory. 18.624 - 18.625 -uint32_t 18.626 -Cpm_jz4730_chip::get_memory_frequency() 18.627 -{ 18.628 - if (pll_enabled()) 18.629 - return get_pll_frequency() / get_memory_divider(); 18.630 - else 18.631 - return _exclk_freq; 18.632 + return new Cpm_jz4730_chip(cpm_base); 18.633 } 18.634 18.635 18.636 18.637 // C language interface functions. 18.638 18.639 -void 18.640 -*jz4730_cpm_init(l4_addr_t cpm_base) 18.641 +void * 18.642 +jz4730_cpm_init(l4_addr_t cpm_base) 18.643 { 18.644 - /* Initialise the clock and power management peripheral with the 18.645 - register memory region and a 3.6864 MHz EXCLK frequency. */ 18.646 + return (void *) jz4730_cpm_chip(cpm_base); 18.647 +} 18.648 18.649 - return (void *) new Cpm_jz4730_chip(cpm_base, 3686400); 18.650 +const char * 18.651 +jz4730_cpm_clock_type(void *cpm, enum Clock_identifiers clock) 18.652 +{ 18.653 + return static_cast<Cpm_chip *>(cpm)->clock_type(clock); 18.654 } 18.655 18.656 int 18.657 jz4730_cpm_have_clock(void *cpm, enum Clock_identifiers clock) 18.658 { 18.659 - return static_cast<Cpm_jz4730_chip *>(cpm)->have_clock(clock); 18.660 + return static_cast<Cpm_chip *>(cpm)->have_clock(clock); 18.661 } 18.662 18.663 void 18.664 jz4730_cpm_start_clock(void *cpm, enum Clock_identifiers clock) 18.665 { 18.666 - static_cast<Cpm_jz4730_chip *>(cpm)->start_clock(clock); 18.667 + static_cast<Cpm_chip *>(cpm)->start_clock(clock); 18.668 } 18.669 18.670 void 18.671 jz4730_cpm_stop_clock(void *cpm, enum Clock_identifiers clock) 18.672 { 18.673 - static_cast<Cpm_jz4730_chip *>(cpm)->stop_clock(clock); 18.674 -} 18.675 - 18.676 -uint32_t 18.677 -jz4730_cpm_get_cpu_frequency(void *cpm) 18.678 -{ 18.679 - return static_cast<Cpm_jz4730_chip *>(cpm)->get_cpu_frequency(); 18.680 + static_cast<Cpm_chip *>(cpm)->stop_clock(clock); 18.681 } 18.682 18.683 -uint32_t 18.684 -jz4730_cpm_get_hclock_frequency(void *cpm) 18.685 -{ 18.686 - return static_cast<Cpm_jz4730_chip *>(cpm)->get_hclock_frequency(); 18.687 -} 18.688 - 18.689 -uint32_t 18.690 -jz4730_cpm_get_source_frequency(void *cpm) 18.691 -{ 18.692 - return static_cast<Cpm_jz4730_chip *>(cpm)->get_source_frequency(); 18.693 +int 18.694 +jz4730_cpm_get_parameters(void *cpm, enum Clock_identifiers clock, uint32_t parameters[]) 18.695 +{ 18.696 + return static_cast<Cpm_chip *>(cpm)->get_parameters(clock, parameters); 18.697 } 18.698 18.699 -uint32_t 18.700 -jz4730_cpm_get_pclock_frequency(void *cpm) 18.701 -{ 18.702 - return static_cast<Cpm_jz4730_chip *>(cpm)->get_pclock_frequency(); 18.703 +int 18.704 +jz4730_cpm_set_parameters(void *cpm, enum Clock_identifiers clock, int num_parameters, uint32_t parameters[]) 18.705 +{ 18.706 + return static_cast<Cpm_chip *>(cpm)->set_parameters(clock, num_parameters, parameters); 18.707 } 18.708 18.709 -uint32_t 18.710 -jz4730_cpm_get_memory_frequency(void *cpm) 18.711 -{ 18.712 - return static_cast<Cpm_jz4730_chip *>(cpm)->get_memory_frequency(); 18.713 -} 18.714 - 18.715 -uint16_t 18.716 -jz4730_cpm_get_lcd_pixel_divider(void *cpm) 18.717 -{ 18.718 - return static_cast<Cpm_jz4730_chip *>(cpm)->get_lcd_pixel_divider(); 18.719 -} 18.720 - 18.721 -uint32_t 18.722 -jz4730_cpm_get_frequency(void *cpm, enum Clock_identifiers clock) 18.723 -{ 18.724 - return static_cast<Cpm_jz4730_chip *>(cpm)->get_frequency(clock); 18.725 +uint8_t 18.726 +jz4730_cpm_get_source(void *cpm, enum Clock_identifiers clock) 18.727 +{ 18.728 + return static_cast<Cpm_chip *>(cpm)->get_source(clock); 18.729 } 18.730 18.731 void 18.732 -jz4730_cpm_set_frequency(void *cpm, enum Clock_identifiers clock, uint32_t frequency) 18.733 +jz4730_cpm_set_source(void *cpm, enum Clock_identifiers clock, uint8_t source) 18.734 +{ 18.735 + static_cast<Cpm_chip *>(cpm)->set_source(clock, source); 18.736 +} 18.737 + 18.738 +enum Clock_identifiers 18.739 +jz4730_cpm_get_source_clock(void *cpm, enum Clock_identifiers clock) 18.740 +{ 18.741 + return static_cast<Cpm_chip *>(cpm)->get_source_clock(clock); 18.742 +} 18.743 + 18.744 +void 18.745 +jz4730_cpm_set_source_clock(void *cpm, enum Clock_identifiers clock, enum Clock_identifiers source) 18.746 +{ 18.747 + static_cast<Cpm_chip *>(cpm)->set_source_clock(clock, source); 18.748 +} 18.749 + 18.750 +uint64_t 18.751 +jz4730_cpm_get_source_frequency(void *cpm, enum Clock_identifiers clock) 18.752 +{ 18.753 + return static_cast<Cpm_chip *>(cpm)->get_source_frequency(clock); 18.754 +} 18.755 + 18.756 +uint64_t 18.757 +jz4730_cpm_get_frequency(void *cpm, enum Clock_identifiers clock) 18.758 +{ 18.759 + return static_cast<Cpm_chip *>(cpm)->get_frequency(clock); 18.760 +} 18.761 + 18.762 +int 18.763 +jz4730_cpm_set_frequency(void *cpm, enum Clock_identifiers clock, uint64_t frequency) 18.764 { 18.765 - static_cast<Cpm_jz4730_chip *>(cpm)->set_frequency(clock, frequency); 18.766 + return static_cast<Cpm_chip *>(cpm)->set_frequency(clock, frequency); 18.767 }
19.1 --- a/pkg/devices/lib/cpm/src/jz4740.cc Wed Apr 24 00:47:34 2024 +0200 19.2 +++ b/pkg/devices/lib/cpm/src/jz4740.cc Sat Apr 27 23:46:28 2024 +0200 19.3 @@ -3,7 +3,7 @@ 19.4 * provided by the jz4740 and related SoCs. The power management 19.5 * functionality could be exposed using a separate driver. 19.6 * 19.7 - * Copyright (C) 2017, 2018, 2021, 2023 Paul Boddie <paul@boddie.org.uk> 19.8 + * Copyright (C) 2017, 2018, 2021, 2023, 2024 Paul Boddie <paul@boddie.org.uk> 19.9 * 19.10 * This program is free software; you can redistribute it and/or 19.11 * modify it under the terms of the GNU General Public License as 19.12 @@ -347,15 +347,25 @@ 19.13 return get_pll_frequency() / get_memory_divider(); 19.14 } 19.15 19.16 +#if 0 19.17 +Cpm_chip * 19.18 +jz4740_cpm_chip(l4_addr_t cpm_base) 19.19 +{ 19.20 + /* Initialise the clock and power management peripheral with the 19.21 + register memory region and a 12MHz EXCLK frequency. */ 19.22 + 19.23 + return new Cpm_jz4740_chip(cpm_base, 12000000); 19.24 +} 19.25 +#endif 19.26 + 19.27 19.28 19.29 // C language interface functions. 19.30 19.31 -void 19.32 -*jz4740_cpm_init(l4_addr_t cpm_base) 19.33 +void * 19.34 +jz4740_cpm_init(l4_addr_t cpm_base) 19.35 { 19.36 - /* Initialise the clock and power management peripheral with the 19.37 - register memory region and a 12MHz EXCLK frequency. */ 19.38 + // NOTE: To call jz4740_cpm_chip instead. 19.39 19.40 return (void *) new Cpm_jz4740_chip(cpm_base, 12000000); 19.41 }
20.1 --- a/pkg/devices/lib/cpm/src/jz4780.cc Wed Apr 24 00:47:34 2024 +0200 20.2 +++ b/pkg/devices/lib/cpm/src/jz4780.cc Sat Apr 27 23:46:28 2024 +0200 20.3 @@ -451,7 +451,7 @@ 20.4 Divider(Clock_divider_vpu)); 20.5 20.6 static Clock_divided_fixed 20.7 - clock_external_div_512((Source(mux_external)), (Divider_fixed(512))); 20.8 + clock_external_div((Source(mux_external)), (Divider_fixed(512))); 20.9 20.10 const double jz4780_pll_intermediate_min = 300000000, 20.11 jz4780_pll_intermediate_max = 1500000000; 20.12 @@ -499,7 +499,7 @@ 20.13 &clock_dma, 20.14 &clock_none, // Clock_emac 20.15 &clock_external, 20.16 - &clock_external_div_512, 20.17 + &clock_external_div, 20.18 &clock_hclock0, 20.19 &clock_hclock2, 20.20 &clock_hclock2_pclock, 20.21 @@ -522,6 +522,7 @@ 20.22 &clock_lcd_pixel1, 20.23 &clock_mac, 20.24 &clock_main, 20.25 + &clock_none, // Clock_mclock 20.26 &clock_none, // Clock_mipi_csi 20.27 &clock_msc, 20.28 &clock_msc0, 20.29 @@ -532,13 +533,14 @@ 20.30 &clock_otg1, 20.31 &clock_pclock, 20.32 &clock_pcm, 20.33 + &clock_none, // Clock_pll 20.34 &clock_pll_A, 20.35 &clock_pll_E, 20.36 &clock_pll_M, 20.37 &clock_pll_V, 20.38 &clock_none, // Clock_pwm0 20.39 &clock_none, // Clock_pwm1 20.40 - &clock_external_div_512,// Clock_rtc 20.41 + &clock_external_div, // Clock_rtc 20.42 &clock_rtc_external, 20.43 &clock_sadc, 20.44 &clock_scc, 20.45 @@ -576,90 +578,96 @@ 20.46 { 20.47 } 20.48 20.49 +Cpm_chip * 20.50 +jz4780_cpm_chip(l4_addr_t cpm_base) 20.51 +{ 20.52 + return new Cpm_jz4780_chip(cpm_base); 20.53 +} 20.54 + 20.55 20.56 20.57 // C language interface functions. 20.58 20.59 -void 20.60 -*jz4780_cpm_init(l4_addr_t cpm_base) 20.61 +void * 20.62 +jz4780_cpm_init(l4_addr_t cpm_base) 20.63 { 20.64 - return (void *) new Cpm_jz4780_chip(cpm_base); 20.65 + return (void *) jz4780_cpm_chip(cpm_base); 20.66 } 20.67 20.68 const char * 20.69 jz4780_cpm_clock_type(void *cpm, enum Clock_identifiers clock) 20.70 { 20.71 - return static_cast<Cpm_jz4780_chip *>(cpm)->clock_type(clock); 20.72 + return static_cast<Cpm_chip *>(cpm)->clock_type(clock); 20.73 } 20.74 20.75 int 20.76 jz4780_cpm_have_clock(void *cpm, enum Clock_identifiers clock) 20.77 { 20.78 - return static_cast<Cpm_jz4780_chip *>(cpm)->have_clock(clock); 20.79 + return static_cast<Cpm_chip *>(cpm)->have_clock(clock); 20.80 } 20.81 20.82 void 20.83 jz4780_cpm_start_clock(void *cpm, enum Clock_identifiers clock) 20.84 { 20.85 - static_cast<Cpm_jz4780_chip *>(cpm)->start_clock(clock); 20.86 + static_cast<Cpm_chip *>(cpm)->start_clock(clock); 20.87 } 20.88 20.89 void 20.90 jz4780_cpm_stop_clock(void *cpm, enum Clock_identifiers clock) 20.91 { 20.92 - static_cast<Cpm_jz4780_chip *>(cpm)->stop_clock(clock); 20.93 + static_cast<Cpm_chip *>(cpm)->stop_clock(clock); 20.94 } 20.95 20.96 int 20.97 jz4780_cpm_get_parameters(void *cpm, enum Clock_identifiers clock, uint32_t parameters[]) 20.98 { 20.99 - return static_cast<Cpm_jz4780_chip *>(cpm)->get_parameters(clock, parameters); 20.100 + return static_cast<Cpm_chip *>(cpm)->get_parameters(clock, parameters); 20.101 } 20.102 20.103 int 20.104 jz4780_cpm_set_parameters(void *cpm, enum Clock_identifiers clock, int num_parameters, uint32_t parameters[]) 20.105 { 20.106 - return static_cast<Cpm_jz4780_chip *>(cpm)->set_parameters(clock, num_parameters, parameters); 20.107 + return static_cast<Cpm_chip *>(cpm)->set_parameters(clock, num_parameters, parameters); 20.108 } 20.109 20.110 uint8_t 20.111 jz4780_cpm_get_source(void *cpm, enum Clock_identifiers clock) 20.112 { 20.113 - return static_cast<Cpm_jz4780_chip *>(cpm)->get_source(clock); 20.114 + return static_cast<Cpm_chip *>(cpm)->get_source(clock); 20.115 } 20.116 20.117 void 20.118 jz4780_cpm_set_source(void *cpm, enum Clock_identifiers clock, uint8_t source) 20.119 { 20.120 - static_cast<Cpm_jz4780_chip *>(cpm)->set_source(clock, source); 20.121 + static_cast<Cpm_chip *>(cpm)->set_source(clock, source); 20.122 } 20.123 20.124 enum Clock_identifiers 20.125 jz4780_cpm_get_source_clock(void *cpm, enum Clock_identifiers clock) 20.126 { 20.127 - return static_cast<Cpm_jz4780_chip *>(cpm)->get_source_clock(clock); 20.128 + return static_cast<Cpm_chip *>(cpm)->get_source_clock(clock); 20.129 } 20.130 20.131 void 20.132 jz4780_cpm_set_source_clock(void *cpm, enum Clock_identifiers clock, enum Clock_identifiers source) 20.133 { 20.134 - static_cast<Cpm_jz4780_chip *>(cpm)->set_source_clock(clock, source); 20.135 + static_cast<Cpm_chip *>(cpm)->set_source_clock(clock, source); 20.136 } 20.137 20.138 uint64_t 20.139 jz4780_cpm_get_source_frequency(void *cpm, enum Clock_identifiers clock) 20.140 { 20.141 - return static_cast<Cpm_jz4780_chip *>(cpm)->get_source_frequency(clock); 20.142 + return static_cast<Cpm_chip *>(cpm)->get_source_frequency(clock); 20.143 } 20.144 20.145 uint64_t 20.146 jz4780_cpm_get_frequency(void *cpm, enum Clock_identifiers clock) 20.147 { 20.148 - return static_cast<Cpm_jz4780_chip *>(cpm)->get_frequency(clock); 20.149 + return static_cast<Cpm_chip *>(cpm)->get_frequency(clock); 20.150 } 20.151 20.152 int 20.153 jz4780_cpm_set_frequency(void *cpm, enum Clock_identifiers clock, uint64_t frequency) 20.154 { 20.155 - return static_cast<Cpm_jz4780_chip *>(cpm)->set_frequency(clock, frequency); 20.156 + return static_cast<Cpm_chip *>(cpm)->set_frequency(clock, frequency); 20.157 }
21.1 --- a/pkg/devices/lib/cpm/src/x1600.cc Wed Apr 24 00:47:34 2024 +0200 21.2 +++ b/pkg/devices/lib/cpm/src/x1600.cc Sat Apr 27 23:46:28 2024 +0200 21.3 @@ -273,7 +273,7 @@ 21.4 mux_dev (3, Clocks(Clock_main, Clock_pll_M, Clock_pll_E)), 21.5 mux_main (3, Clocks(Clock_none, Clock_external, Clock_pll_A)), 21.6 mux_i2s (2, Clocks(Clock_main, Clock_pll_E)), 21.7 - mux_rtc (2, Clocks(Clock_external_div_512, Clock_rtc_external)); 21.8 + mux_rtc (2, Clocks(Clock_external_div, Clock_rtc_external)); 21.9 21.10 21.11 21.12 @@ -410,7 +410,7 @@ 21.13 Divider(Clock_divider_ssi)); 21.14 21.15 static Clock_divided_fixed 21.16 - clock_external_div_512((Source(mux_external)), (Divider_fixed(512))); 21.17 + clock_external_div((Source(mux_external)), (Divider_fixed(512))); 21.18 21.19 static Clock_divided_i2s 21.20 clock_i2s0_rx(Source(mux_i2s0_rx), 21.21 @@ -465,7 +465,7 @@ 21.22 &clock_dma, 21.23 &clock_none, // Clock_emac 21.24 &clock_external, 21.25 - &clock_external_div_512, 21.26 + &clock_external_div, 21.27 &clock_hclock0, 21.28 &clock_hclock2, 21.29 &clock_hclock2_pclock, 21.30 @@ -488,6 +488,7 @@ 21.31 &clock_none, // Clock_lcd_pixel1 21.32 &clock_mac, 21.33 &clock_main, 21.34 + &clock_none, // Clock_mclock 21.35 &clock_mipi_csi, 21.36 &clock_none, // Clock_msc 21.37 &clock_msc0, 21.38 @@ -498,6 +499,7 @@ 21.39 &clock_none, // Clock_otg1 21.40 &clock_pclock, 21.41 &clock_none, // Clock_pcm 21.42 + &clock_none, // Clock_pll 21.43 &clock_pll_A, 21.44 &clock_pll_E, 21.45 &clock_pll_M, 21.46 @@ -539,6 +541,12 @@ 21.47 { 21.48 } 21.49 21.50 +Cpm_chip * 21.51 +x1600_cpm_chip(l4_addr_t cpm_base) 21.52 +{ 21.53 + return new Cpm_x1600_chip(cpm_base); 21.54 +} 21.55 + 21.56 21.57 21.58 // C language interface functions. 21.59 @@ -552,77 +560,77 @@ 21.60 const char * 21.61 x1600_cpm_clock_type(void *cpm, enum Clock_identifiers clock) 21.62 { 21.63 - return static_cast<Cpm_x1600_chip *>(cpm)->clock_type(clock); 21.64 + return static_cast<Cpm_chip *>(cpm)->clock_type(clock); 21.65 } 21.66 21.67 int 21.68 x1600_cpm_have_clock(void *cpm, enum Clock_identifiers clock) 21.69 { 21.70 - return static_cast<Cpm_x1600_chip *>(cpm)->have_clock(clock); 21.71 + return static_cast<Cpm_chip *>(cpm)->have_clock(clock); 21.72 } 21.73 21.74 void 21.75 x1600_cpm_start_clock(void *cpm, enum Clock_identifiers clock) 21.76 { 21.77 - static_cast<Cpm_x1600_chip *>(cpm)->start_clock(clock); 21.78 + static_cast<Cpm_chip *>(cpm)->start_clock(clock); 21.79 } 21.80 21.81 void 21.82 x1600_cpm_stop_clock(void *cpm, enum Clock_identifiers clock) 21.83 { 21.84 - static_cast<Cpm_x1600_chip *>(cpm)->stop_clock(clock); 21.85 + static_cast<Cpm_chip *>(cpm)->stop_clock(clock); 21.86 } 21.87 21.88 int 21.89 x1600_cpm_get_parameters(void *cpm, enum Clock_identifiers clock, uint32_t parameters[]) 21.90 { 21.91 - return static_cast<Cpm_x1600_chip *>(cpm)->get_parameters(clock, parameters); 21.92 + return static_cast<Cpm_chip *>(cpm)->get_parameters(clock, parameters); 21.93 } 21.94 21.95 int 21.96 x1600_cpm_set_parameters(void *cpm, enum Clock_identifiers clock, int num_parameters, uint32_t parameters[]) 21.97 { 21.98 - return static_cast<Cpm_x1600_chip *>(cpm)->set_parameters(clock, num_parameters, parameters); 21.99 + return static_cast<Cpm_chip *>(cpm)->set_parameters(clock, num_parameters, parameters); 21.100 } 21.101 21.102 uint8_t 21.103 x1600_cpm_get_source(void *cpm, enum Clock_identifiers clock) 21.104 { 21.105 - return static_cast<Cpm_x1600_chip *>(cpm)->get_source(clock); 21.106 + return static_cast<Cpm_chip *>(cpm)->get_source(clock); 21.107 } 21.108 21.109 void 21.110 x1600_cpm_set_source(void *cpm, enum Clock_identifiers clock, uint8_t source) 21.111 { 21.112 - static_cast<Cpm_x1600_chip *>(cpm)->set_source(clock, source); 21.113 + static_cast<Cpm_chip *>(cpm)->set_source(clock, source); 21.114 } 21.115 21.116 enum Clock_identifiers 21.117 x1600_cpm_get_source_clock(void *cpm, enum Clock_identifiers clock) 21.118 { 21.119 - return static_cast<Cpm_x1600_chip *>(cpm)->get_source_clock(clock); 21.120 + return static_cast<Cpm_chip *>(cpm)->get_source_clock(clock); 21.121 } 21.122 21.123 void 21.124 x1600_cpm_set_source_clock(void *cpm, enum Clock_identifiers clock, enum Clock_identifiers source) 21.125 { 21.126 - static_cast<Cpm_x1600_chip *>(cpm)->set_source_clock(clock, source); 21.127 + static_cast<Cpm_chip *>(cpm)->set_source_clock(clock, source); 21.128 } 21.129 21.130 uint64_t 21.131 x1600_cpm_get_source_frequency(void *cpm, enum Clock_identifiers clock) 21.132 { 21.133 - return static_cast<Cpm_x1600_chip *>(cpm)->get_source_frequency(clock); 21.134 + return static_cast<Cpm_chip *>(cpm)->get_source_frequency(clock); 21.135 } 21.136 21.137 uint64_t 21.138 x1600_cpm_get_frequency(void *cpm, enum Clock_identifiers clock) 21.139 { 21.140 - return static_cast<Cpm_x1600_chip *>(cpm)->get_frequency(clock); 21.141 + return static_cast<Cpm_chip *>(cpm)->get_frequency(clock); 21.142 } 21.143 21.144 int 21.145 x1600_cpm_set_frequency(void *cpm, enum Clock_identifiers clock, uint64_t frequency) 21.146 { 21.147 - return static_cast<Cpm_x1600_chip *>(cpm)->set_frequency(clock, frequency); 21.148 + return static_cast<Cpm_chip *>(cpm)->set_frequency(clock, frequency); 21.149 }
22.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 22.2 +++ b/pkg/devices/lib/dma/include/dma-generic.h Sat Apr 27 23:46:28 2024 +0200 22.3 @@ -0,0 +1,91 @@ 22.4 +/* 22.5 + * Generic DMA support. 22.6 + * 22.7 + * Copyright (C) 2024 Paul Boddie <paul@boddie.org.uk> 22.8 + * 22.9 + * This program is free software; you can redistribute it and/or 22.10 + * modify it under the terms of the GNU General Public License as 22.11 + * published by the Free Software Foundation; either version 2 of 22.12 + * the License, or (at your option) any later version. 22.13 + * 22.14 + * This program is distributed in the hope that it will be useful, 22.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 22.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 22.17 + * GNU General Public License for more details. 22.18 + * 22.19 + * You should have received a copy of the GNU General Public License 22.20 + * along with this program; if not, write to the Free Software 22.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, 22.22 + * Boston, MA 02110-1301, USA 22.23 + */ 22.24 + 22.25 +#pragma once 22.26 + 22.27 +#include <l4/sys/types.h> 22.28 +#include <stdint.h> 22.29 + 22.30 + 22.31 + 22.32 +#ifdef __cplusplus 22.33 + 22.34 +#include <l4/devices/cpm-generic.h> 22.35 +#include <l4/re/c/dma_space.h> 22.36 + 22.37 +// DMA channel. 22.38 + 22.39 +class Dma_channel 22.40 +{ 22.41 +public: 22.42 + virtual unsigned int transfer(uint32_t source, uint32_t destination, 22.43 + unsigned int count, 22.44 + bool source_increment, bool destination_increment, 22.45 + uint8_t source_width, uint8_t destination_width, 22.46 + uint8_t transfer_unit_size, 22.47 + int type, 22.48 + l4_addr_t desc_vaddr = 0, 22.49 + l4re_dma_space_dma_addr_t desc_paddr = 0) = 0; 22.50 + 22.51 + virtual unsigned int wait() = 0; 22.52 +}; 22.53 + 22.54 +// DMA device control. 22.55 + 22.56 +class Dma_chip 22.57 +{ 22.58 +public: 22.59 + virtual void disable() = 0; 22.60 + 22.61 + virtual void enable() = 0; 22.62 + 22.63 + virtual Dma_channel *get_channel(uint8_t channel, l4_cap_idx_t irq) = 0; 22.64 + 22.65 + // Transaction control. 22.66 + 22.67 + virtual void ack_irq(uint8_t channel) 22.68 + { 22.69 + (void) channel; 22.70 + } 22.71 + 22.72 + virtual bool error() 22.73 + { 22.74 + return false; 22.75 + } 22.76 + 22.77 + virtual bool halted() 22.78 + { 22.79 + return false; 22.80 + } 22.81 + 22.82 + virtual void commit_descriptor(uint8_t channel) 22.83 + { 22.84 + (void) channel; 22.85 + } 22.86 + 22.87 + virtual bool have_interrupt(uint8_t channel) = 0; 22.88 +}; 22.89 + 22.90 +// Generic access to the DMA abstraction. 22.91 + 22.92 +Dma_chip *new_dma_chip(const char *name, l4_addr_t start, l4_addr_t end, Cpm_chip *cpm); 22.93 + 22.94 +#endif /* __cplusplus */
23.1 --- a/pkg/devices/lib/dma/include/dma-jz4730.h Wed Apr 24 00:47:34 2024 +0200 23.2 +++ b/pkg/devices/lib/dma/include/dma-jz4730.h Sat Apr 27 23:46:28 2024 +0200 23.3 @@ -1,7 +1,7 @@ 23.4 /* 23.5 * DMA support for the JZ4730. 23.6 * 23.7 - * Copyright (C) 2021, 2023 Paul Boddie <paul@boddie.org.uk> 23.8 + * Copyright (C) 2021, 2023, 2024 Paul Boddie <paul@boddie.org.uk> 23.9 * 23.10 * This program is free software; you can redistribute it and/or 23.11 * modify it under the terms of the GNU General Public License as 23.12 @@ -77,7 +77,7 @@ 23.13 23.14 #ifdef __cplusplus 23.15 23.16 -#include <l4/devices/cpm-jz4730.h> 23.17 +#include <l4/devices/dma-generic.h> 23.18 #include <l4/devices/hw_mmio_register_block.h> 23.19 23.20 // Forward declaration. 23.21 @@ -88,11 +88,11 @@ 23.22 23.23 // DMA channel. 23.24 23.25 -class Dma_jz4730_channel 23.26 +class Dma_jz4730_channel : public Dma_channel 23.27 { 23.28 private: 23.29 Hw::Register_block<32> _regs; 23.30 - Dma_jz4730_chip *_chip; 23.31 + Dma_chip *_chip; 23.32 uint8_t _channel; 23.33 l4_cap_idx_t _irq = L4_INVALID_CAP; 23.34 23.35 @@ -104,14 +104,16 @@ 23.36 enum Dma_jz4730_ext_req_detect_mode _ext_req_detect_mode = Dma_ext_req_detect_mode_high_level; 23.37 23.38 public: 23.39 - Dma_jz4730_channel(Dma_jz4730_chip *chip, uint8_t channel, l4_addr_t start, l4_cap_idx_t irq); 23.40 + Dma_jz4730_channel(Dma_chip *chip, uint8_t channel, l4_addr_t start, l4_cap_idx_t irq); 23.41 23.42 unsigned int transfer(uint32_t source, uint32_t destination, 23.43 unsigned int count, 23.44 bool source_increment, bool destination_increment, 23.45 uint8_t source_width, uint8_t destination_width, 23.46 uint8_t transfer_unit_size, 23.47 - enum Dma_jz4730_request_type type=Dma_request_auto); 23.48 + int type=Dma_request_auto, 23.49 + l4_addr_t desc_vaddr = 0, 23.50 + l4re_dma_space_dma_addr_t desc_paddr = 0); 23.51 23.52 unsigned int wait(); 23.53 23.54 @@ -159,25 +161,27 @@ 23.55 23.56 // DMA device control. 23.57 23.58 -class Dma_jz4730_chip 23.59 +class Dma_jz4730_chip : public Dma_chip 23.60 { 23.61 private: 23.62 Hw::Register_block<32> _regs; 23.63 l4_addr_t _start, _end; 23.64 - Cpm_jz4730_chip *_cpm; 23.65 + Cpm_chip *_cpm; 23.66 23.67 public: 23.68 - Dma_jz4730_chip(l4_addr_t start, l4_addr_t end, Cpm_jz4730_chip *cpm); 23.69 + Dma_jz4730_chip(l4_addr_t start, l4_addr_t end, Cpm_chip *cpm); 23.70 23.71 void disable(); 23.72 23.73 void enable(); 23.74 23.75 - Dma_jz4730_channel *get_channel(uint8_t channel, l4_cap_idx_t irq); 23.76 + Dma_channel *get_channel(uint8_t channel, l4_cap_idx_t irq); 23.77 23.78 bool have_interrupt(uint8_t channel); 23.79 }; 23.80 23.81 +Dma_chip *jz4730_dma_chip(l4_addr_t start, l4_addr_t end, Cpm_chip *cpm); 23.82 + 23.83 #endif /* __cplusplus */ 23.84 23.85
24.1 --- a/pkg/devices/lib/dma/include/dma-jz4780.h Wed Apr 24 00:47:34 2024 +0200 24.2 +++ b/pkg/devices/lib/dma/include/dma-jz4780.h Sat Apr 27 23:46:28 2024 +0200 24.3 @@ -21,7 +21,6 @@ 24.4 24.5 #pragma once 24.6 24.7 -#include <l4/re/c/dma_space.h> 24.8 #include <l4/sys/types.h> 24.9 #include <stdint.h> 24.10 24.11 @@ -85,7 +84,7 @@ 24.12 24.13 #ifdef __cplusplus 24.14 24.15 -#include <l4/devices/cpm-jz4780.h> 24.16 +#include <l4/devices/dma-generic.h> 24.17 #include <l4/devices/hw_mmio_register_block.h> 24.18 24.19 // Forward declaration. 24.20 @@ -96,16 +95,16 @@ 24.21 24.22 // DMA channel. 24.23 24.24 -class Dma_jz4780_channel 24.25 +class Dma_jz4780_channel : public Dma_channel 24.26 { 24.27 private: 24.28 Hw::Register_block<32> _regs; 24.29 - Dma_jz4780_chip *_chip; 24.30 + Dma_chip *_chip; 24.31 uint8_t _channel; 24.32 l4_cap_idx_t _irq = L4_INVALID_CAP; 24.33 24.34 public: 24.35 - Dma_jz4780_channel(Dma_jz4780_chip *chip, uint8_t channel, l4_addr_t start, 24.36 + Dma_jz4780_channel(Dma_chip *chip, uint8_t channel, l4_addr_t start, 24.37 l4_cap_idx_t irq = L4_INVALID_CAP); 24.38 24.39 unsigned int transfer(uint32_t source, uint32_t destination, 24.40 @@ -113,7 +112,7 @@ 24.41 bool source_increment, bool destination_increment, 24.42 uint8_t source_width, uint8_t destination_width, 24.43 uint8_t transfer_unit_size, 24.44 - enum Dma_jz4780_request_type type=Dma_request_auto, 24.45 + int type=Dma_request_auto, 24.46 l4_addr_t desc_vaddr = 0, 24.47 l4re_dma_space_dma_addr_t desc_paddr = 0); 24.48 24.49 @@ -147,21 +146,21 @@ 24.50 24.51 // DMA device control. 24.52 24.53 -class Dma_jz4780_chip 24.54 +class Dma_jz4780_chip : public Dma_chip 24.55 { 24.56 private: 24.57 Hw::Register_block<32> _regs; 24.58 l4_addr_t _start, _end; 24.59 - Cpm_jz4780_chip *_cpm; 24.60 + Cpm_chip *_cpm; 24.61 24.62 public: 24.63 - Dma_jz4780_chip(l4_addr_t start, l4_addr_t end, Cpm_jz4780_chip *cpm); 24.64 + Dma_jz4780_chip(l4_addr_t start, l4_addr_t end, Cpm_chip *cpm); 24.65 24.66 void disable(); 24.67 24.68 void enable(); 24.69 24.70 - Dma_jz4780_channel *get_channel(uint8_t channel, 24.71 + Dma_channel *get_channel(uint8_t channel, 24.72 l4_cap_idx_t irq = L4_INVALID_CAP); 24.73 24.74 // Transaction control. 24.75 @@ -179,6 +178,8 @@ 24.76 void commit_descriptor(uint8_t channel); 24.77 }; 24.78 24.79 +Dma_chip *jz4780_dma_chip(l4_addr_t start, l4_addr_t end, Cpm_chip *cpm); 24.80 + 24.81 #endif /* __cplusplus */ 24.82 24.83
25.1 --- a/pkg/devices/lib/dma/include/dma-x1600.h Wed Apr 24 00:47:34 2024 +0200 25.2 +++ b/pkg/devices/lib/dma/include/dma-x1600.h Sat Apr 27 23:46:28 2024 +0200 25.3 @@ -69,11 +69,19 @@ 25.4 Dma_request_aic_in = 63, 25.5 }; 25.6 25.7 +/* Descriptor structure. */ 25.8 + 25.9 +struct x1600_dma_descriptor 25.10 +{ 25.11 + uint32_t command, source, destination, transfer_count, 25.12 + stride, request_source, reserved0, reserved1; 25.13 +}; 25.14 + 25.15 25.16 25.17 #ifdef __cplusplus 25.18 25.19 -#include <l4/devices/cpm-x1600.h> 25.20 +#include <l4/devices/dma-generic.h> 25.21 #include <l4/devices/hw_mmio_register_block.h> 25.22 25.23 // Forward declaration. 25.24 @@ -84,23 +92,25 @@ 25.25 25.26 // DMA channel. 25.27 25.28 -class Dma_x1600_channel 25.29 +class Dma_x1600_channel : public Dma_channel 25.30 { 25.31 private: 25.32 Hw::Register_block<32> _regs; 25.33 - Dma_x1600_chip *_chip; 25.34 + Dma_chip *_chip; 25.35 uint8_t _channel; 25.36 l4_cap_idx_t _irq = L4_INVALID_CAP; 25.37 25.38 public: 25.39 - Dma_x1600_channel(Dma_x1600_chip *chip, uint8_t channel, l4_addr_t start, l4_cap_idx_t irq); 25.40 + Dma_x1600_channel(Dma_chip *chip, uint8_t channel, l4_addr_t start, l4_cap_idx_t irq); 25.41 25.42 unsigned int transfer(uint32_t source, uint32_t destination, 25.43 unsigned int count, 25.44 bool source_increment, bool destination_increment, 25.45 uint8_t source_width, uint8_t destination_width, 25.46 uint8_t transfer_unit_size, 25.47 - enum Dma_x1600_request_type type=Dma_request_auto); 25.48 + int type=Dma_request_auto, 25.49 + l4_addr_t desc_vaddr = 0, 25.50 + l4re_dma_space_dma_addr_t desc_paddr = 0); 25.51 25.52 unsigned int wait(); 25.53 25.54 @@ -132,21 +142,21 @@ 25.55 25.56 // DMA device control. 25.57 25.58 -class Dma_x1600_chip 25.59 +class Dma_x1600_chip : public Dma_chip 25.60 { 25.61 private: 25.62 Hw::Register_block<32> _regs; 25.63 l4_addr_t _start, _end; 25.64 - Cpm_x1600_chip *_cpm; 25.65 + Cpm_chip *_cpm; 25.66 25.67 public: 25.68 - Dma_x1600_chip(l4_addr_t start, l4_addr_t end, Cpm_x1600_chip *cpm); 25.69 + Dma_x1600_chip(l4_addr_t start, l4_addr_t end, Cpm_chip *cpm); 25.70 25.71 void disable(); 25.72 25.73 void enable(); 25.74 25.75 - Dma_x1600_channel *get_channel(uint8_t channel, l4_cap_idx_t irq); 25.76 + Dma_channel *get_channel(uint8_t channel, l4_cap_idx_t irq); 25.77 25.78 // Transaction control. 25.79 25.80 @@ -157,8 +167,14 @@ 25.81 bool halted(); 25.82 25.83 bool have_interrupt(uint8_t channel); 25.84 + 25.85 + // Descriptor operations. 25.86 + 25.87 + void commit_descriptor(uint8_t channel); 25.88 }; 25.89 25.90 +Dma_chip *x1600_dma_chip(l4_addr_t start, l4_addr_t end, Cpm_chip *cpm); 25.91 + 25.92 #endif /* __cplusplus */ 25.93 25.94
26.1 --- a/pkg/devices/lib/dma/src/Makefile Wed Apr 24 00:47:34 2024 +0200 26.2 +++ b/pkg/devices/lib/dma/src/Makefile Sat Apr 27 23:46:28 2024 +0200 26.3 @@ -4,7 +4,7 @@ 26.4 TARGET = libdma.o.a libdma.o.so 26.5 PC_FILENAME := libdrivers-dma 26.6 26.7 -SRC_CC := jz4730.cc jz4780.cc x1600.cc 26.8 +SRC_CC := generic.cc jz4730.cc jz4780.cc x1600.cc 26.9 26.10 PRIVATE_INCDIR += $(PKGDIR)/lib/dma/include 26.11
27.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 27.2 +++ b/pkg/devices/lib/dma/src/generic.cc Sat Apr 27 23:46:28 2024 +0200 27.3 @@ -0,0 +1,56 @@ 27.4 +/* 27.5 + * Generic access to direct memory access functionality. 27.6 + * 27.7 + * Copyright (C) 2024 Paul Boddie <paul@boddie.org.uk> 27.8 + * 27.9 + * This program is free software; you can redistribute it and/or 27.10 + * modify it under the terms of the GNU General Public License as 27.11 + * published by the Free Software Foundation; either version 2 of 27.12 + * the License, or (at your option) any later version. 27.13 + * 27.14 + * This program is distributed in the hope that it will be useful, 27.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 27.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 27.17 + * GNU General Public License for more details. 27.18 + * 27.19 + * You should have received a copy of the GNU General Public License 27.20 + * along with this program; if not, write to the Free Software 27.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, 27.22 + * Boston, MA 02110-1301, USA 27.23 + */ 27.24 + 27.25 +#include <string.h> 27.26 +#include "dma-generic.h" 27.27 + 27.28 +/* Function declarations reproduced here to avoid clock identifier conflicts in 27.29 + the chip-specific headers. */ 27.30 + 27.31 +extern Dma_chip *jz4730_dma_chip(l4_addr_t, l4_addr_t, Cpm_chip *); 27.32 +//extern Dma_chip *jz4740_dma_chip(l4_addr_t, l4_addr_t, Cpm_chip *); 27.33 +extern Dma_chip *jz4780_dma_chip(l4_addr_t, l4_addr_t, Cpm_chip *); 27.34 +extern Dma_chip *x1600_dma_chip(l4_addr_t, l4_addr_t, Cpm_chip *); 27.35 + 27.36 +struct dma_function 27.37 +{ 27.38 + const char *name; 27.39 + Dma_chip *(*function)(l4_addr_t, l4_addr_t, Cpm_chip *); 27.40 +}; 27.41 + 27.42 +static struct dma_function functions[] = { 27.43 + {"jz4730", jz4730_dma_chip}, 27.44 + //{"jz4740", jz4740_dma_chip}, 27.45 + {"jz4780", jz4780_dma_chip}, 27.46 + {"x1600", x1600_dma_chip}, 27.47 + {NULL, NULL} 27.48 +}; 27.49 + 27.50 +Dma_chip *new_dma_chip(const char *name, l4_addr_t start, l4_addr_t end, Cpm_chip *cpm) 27.51 +{ 27.52 + for (struct dma_function *f = functions; f->name != NULL; f++) 27.53 + { 27.54 + if (!strcmp(name, f->name)) 27.55 + return f->function(start, end, cpm); 27.56 + } 27.57 + 27.58 + return NULL; 27.59 +}
28.1 --- a/pkg/devices/lib/dma/src/jz4730.cc Wed Apr 24 00:47:34 2024 +0200 28.2 +++ b/pkg/devices/lib/dma/src/jz4730.cc Sat Apr 27 23:46:28 2024 +0200 28.3 @@ -19,6 +19,7 @@ 28.4 * Boston, MA 02110-1301, USA 28.5 */ 28.6 28.7 +#include <l4/devices/cpm-jz4730.h> 28.8 #include <l4/devices/dma-jz4730.h> 28.9 #include <l4/devices/hw_mmio_register_block.h> 28.10 28.11 @@ -134,7 +135,7 @@ 28.12 28.13 // Initialise a channel. 28.14 28.15 -Dma_jz4730_channel::Dma_jz4730_channel(Dma_jz4730_chip *chip, uint8_t channel, 28.16 +Dma_jz4730_channel::Dma_jz4730_channel(Dma_chip *chip, uint8_t channel, 28.17 l4_addr_t start, l4_cap_idx_t irq) 28.18 : _chip(chip), _channel(channel), _irq(irq) 28.19 { 28.20 @@ -239,8 +240,14 @@ 28.21 bool source_increment, bool destination_increment, 28.22 uint8_t source_width, uint8_t destination_width, 28.23 uint8_t transfer_unit_size, 28.24 - enum Dma_jz4730_request_type type) 28.25 + int type, 28.26 + l4_addr_t desc_vaddr, 28.27 + l4re_dma_space_dma_addr_t desc_paddr) 28.28 { 28.29 + // Descriptor-based transfers are not supported. 28.30 + 28.31 + (void) desc_vaddr; (void) desc_paddr; 28.32 + 28.33 // Ensure an absence of address error and halt conditions globally and in this channel. 28.34 28.35 if (error() || halted()) 28.36 @@ -281,7 +288,7 @@ 28.37 * transfer mode (currently left as single) 28.38 */ 28.39 28.40 - _regs[Dma_control_status] = encode_external_transfer(type) | 28.41 + _regs[Dma_control_status] = encode_external_transfer((enum Dma_jz4730_request_type) type) | 28.42 (source_increment ? Dma_source_address_incr : Dma_source_address_no_incr) | 28.43 (destination_increment ? Dma_dest_address_incr : Dma_dest_address_no_incr) | 28.44 encode_source_port_width(source_width) | 28.45 @@ -393,7 +400,7 @@ 28.46 // Initialise the I2C controller. 28.47 28.48 Dma_jz4730_chip::Dma_jz4730_chip(l4_addr_t start, l4_addr_t end, 28.49 - Cpm_jz4730_chip *cpm) 28.50 + Cpm_chip *cpm) 28.51 : _start(start), _end(end), _cpm(cpm) 28.52 { 28.53 _regs = new Hw::Mmio_register_block<32>(start); 28.54 @@ -426,7 +433,7 @@ 28.55 28.56 // Obtain a channel object. 28.57 28.58 -Dma_jz4730_channel * 28.59 +Dma_channel * 28.60 Dma_jz4730_chip::get_channel(uint8_t channel, l4_cap_idx_t irq) 28.61 { 28.62 if (channel < 6) 28.63 @@ -443,28 +450,33 @@ 28.64 return _regs[Dma_irq_pending] & (1 << (Dma_irq_pending_ch0 - channel)) ? true : false; 28.65 } 28.66 28.67 +Dma_chip *jz4730_dma_chip(l4_addr_t start, l4_addr_t end, Cpm_chip *cpm) 28.68 +{ 28.69 + return new Dma_jz4730_chip(start, end, cpm); 28.70 +} 28.71 + 28.72 28.73 28.74 // C language interface functions. 28.75 28.76 void *jz4730_dma_init(l4_addr_t start, l4_addr_t end, void *cpm) 28.77 { 28.78 - return (void *) new Dma_jz4730_chip(start, end, static_cast<Cpm_jz4730_chip *>(cpm)); 28.79 + return (void *) jz4730_dma_chip(start, end, static_cast<Cpm_chip *>(cpm)); 28.80 } 28.81 28.82 void jz4730_dma_disable(void *dma_chip) 28.83 { 28.84 - static_cast<Dma_jz4730_chip *>(dma_chip)->disable(); 28.85 + static_cast<Dma_chip *>(dma_chip)->disable(); 28.86 } 28.87 28.88 void jz4730_dma_enable(void *dma_chip) 28.89 { 28.90 - static_cast<Dma_jz4730_chip *>(dma_chip)->enable(); 28.91 + static_cast<Dma_chip *>(dma_chip)->enable(); 28.92 } 28.93 28.94 void *jz4730_dma_get_channel(void *dma, uint8_t channel, l4_cap_idx_t irq) 28.95 { 28.96 - return static_cast<Dma_jz4730_chip *>(dma)->get_channel(channel, irq); 28.97 + return static_cast<Dma_chip *>(dma)->get_channel(channel, irq); 28.98 } 28.99 28.100 void jz4730_dma_set_output_polarity(void *dma_channel, enum Dma_jz4730_ext_level polarity)
29.1 --- a/pkg/devices/lib/dma/src/jz4780.cc Wed Apr 24 00:47:34 2024 +0200 29.2 +++ b/pkg/devices/lib/dma/src/jz4780.cc Sat Apr 27 23:46:28 2024 +0200 29.3 @@ -20,6 +20,7 @@ 29.4 * Boston, MA 02110-1301, USA 29.5 */ 29.6 29.7 +#include <l4/devices/cpm-jz4780.h> 29.8 #include <l4/devices/dma-jz4780.h> 29.9 #include <l4/devices/hw_mmio_register_block.h> 29.10 29.11 @@ -156,7 +157,7 @@ 29.12 29.13 // Initialise a channel. 29.14 29.15 -Dma_jz4780_channel::Dma_jz4780_channel(Dma_jz4780_chip *chip, uint8_t channel, 29.16 +Dma_jz4780_channel::Dma_jz4780_channel(Dma_chip *chip, uint8_t channel, 29.17 l4_addr_t start, l4_cap_idx_t irq) 29.18 : _chip(chip), _channel(channel), _irq(irq) 29.19 { 29.20 @@ -267,7 +268,7 @@ 29.21 bool source_increment, bool destination_increment, 29.22 uint8_t source_width, uint8_t destination_width, 29.23 uint8_t transfer_unit_size, 29.24 - enum Dma_jz4780_request_type type, 29.25 + int type, 29.26 l4_addr_t desc_vaddr, 29.27 l4re_dma_space_dma_addr_t desc_paddr) 29.28 { 29.29 @@ -321,7 +322,7 @@ 29.30 desc->destination = destination; 29.31 desc->transfer_count = (units & Dma_transfer_count_mask) | 29.32 (descriptor_offset << Dma_descriptor_offset_shift); 29.33 - desc->request_source = type; 29.34 + desc->request_source = (enum Dma_jz4780_request_type) type; 29.35 29.36 // NOTE: Stride not supported yet. 29.37 29.38 @@ -459,8 +460,7 @@ 29.39 29.40 // Initialise the I2C controller. 29.41 29.42 -Dma_jz4780_chip::Dma_jz4780_chip(l4_addr_t start, l4_addr_t end, 29.43 - Cpm_jz4780_chip *cpm) 29.44 +Dma_jz4780_chip::Dma_jz4780_chip(l4_addr_t start, l4_addr_t end, Cpm_chip *cpm) 29.45 : _start(start), _end(end), _cpm(cpm) 29.46 { 29.47 _regs = new Hw::Mmio_register_block<32>(start); 29.48 @@ -490,7 +490,7 @@ 29.49 29.50 // Obtain a channel object. 29.51 29.52 -Dma_jz4780_channel * 29.53 +Dma_channel * 29.54 Dma_jz4780_chip::get_channel(uint8_t channel, l4_cap_idx_t irq) 29.55 { 29.56 if (channel < 32) 29.57 @@ -537,28 +537,33 @@ 29.58 _regs[Dma_doorbell_set] = (1 << channel); 29.59 } 29.60 29.61 +Dma_chip *jz4780_dma_chip(l4_addr_t start, l4_addr_t end, Cpm_chip *cpm) 29.62 +{ 29.63 + return new Dma_jz4780_chip(start, end, cpm); 29.64 +} 29.65 + 29.66 29.67 29.68 // C language interface functions. 29.69 29.70 void *jz4780_dma_init(l4_addr_t start, l4_addr_t end, void *cpm) 29.71 { 29.72 - return (void *) new Dma_jz4780_chip(start, end, static_cast<Cpm_jz4780_chip *>(cpm)); 29.73 + return (void *) jz4780_dma_chip(start, end, static_cast<Cpm_chip *>(cpm)); 29.74 } 29.75 29.76 void jz4780_dma_disable(void *dma_chip) 29.77 { 29.78 - static_cast<Dma_jz4780_chip *>(dma_chip)->disable(); 29.79 + static_cast<Dma_chip *>(dma_chip)->disable(); 29.80 } 29.81 29.82 void jz4780_dma_enable(void *dma_chip) 29.83 { 29.84 - static_cast<Dma_jz4780_chip *>(dma_chip)->enable(); 29.85 + static_cast<Dma_chip *>(dma_chip)->enable(); 29.86 } 29.87 29.88 void *jz4780_dma_get_channel(void *dma, uint8_t channel, l4_cap_idx_t irq) 29.89 { 29.90 - return static_cast<Dma_jz4780_chip *>(dma)->get_channel(channel, irq); 29.91 + return static_cast<Dma_chip *>(dma)->get_channel(channel, irq); 29.92 } 29.93 29.94 unsigned int jz4780_dma_transfer(void *dma_channel,
30.1 --- a/pkg/devices/lib/dma/src/x1600.cc Wed Apr 24 00:47:34 2024 +0200 30.2 +++ b/pkg/devices/lib/dma/src/x1600.cc Sat Apr 27 23:46:28 2024 +0200 30.3 @@ -19,9 +19,11 @@ 30.4 * Boston, MA 02110-1301, USA 30.5 */ 30.6 30.7 +#include <l4/devices/cpm-x1600.h> 30.8 #include <l4/devices/dma-x1600.h> 30.9 #include <l4/devices/hw_mmio_register_block.h> 30.10 30.11 +#include <l4/sys/cache.h> 30.12 #include <l4/sys/ipc.h> 30.13 #include <l4/sys/irq.h> 30.14 #include <l4/sys/rcv_endpoint.h> 30.15 @@ -37,6 +39,8 @@ 30.16 { 30.17 Dma_control = 0x1000, // DMAC 30.18 Dma_irq_pending = 0x1004, // DIRQP 30.19 + Dma_doorbell = 0x1008, // DDB 30.20 + Dma_doorbell_set = 0x100c, // DDS 30.21 }; 30.22 30.23 enum Channel_regs 30.24 @@ -65,7 +69,10 @@ 30.25 30.26 enum Dma_transfer_count_bits : unsigned 30.27 { 30.28 + Dma_descriptor_offset_mask = 0xff000000, // DOA (in DES3) 30.29 + 30.30 Dma_transfer_count_mask = 0x00ffffff, 30.31 + Dma_descriptor_offset_shift = 24, 30.32 }; 30.33 30.34 enum Dma_request_source_bits : unsigned 30.35 @@ -133,8 +140,8 @@ 30.36 30.37 // Initialise a channel. 30.38 30.39 -Dma_x1600_channel::Dma_x1600_channel(Dma_x1600_chip *chip, uint8_t channel, 30.40 - l4_addr_t start, l4_cap_idx_t irq) 30.41 +Dma_x1600_channel::Dma_x1600_channel(Dma_chip *chip, uint8_t channel, 30.42 + l4_addr_t start, l4_cap_idx_t irq) 30.43 : _chip(chip), _channel(channel), _irq(irq) 30.44 { 30.45 _regs = new Hw::Mmio_register_block<32>(start); 30.46 @@ -245,7 +252,9 @@ 30.47 bool source_increment, bool destination_increment, 30.48 uint8_t source_width, uint8_t destination_width, 30.49 uint8_t transfer_unit_size, 30.50 - enum Dma_x1600_request_type type) 30.51 + int type, 30.52 + l4_addr_t desc_vaddr, 30.53 + l4re_dma_space_dma_addr_t desc_paddr) 30.54 { 30.55 // Ensure an absence of address error and halt conditions globally and in this channel. 30.56 30.57 @@ -261,41 +270,71 @@ 30.58 30.59 _regs[Dma_control_status] = _regs[Dma_control_status] & ~Dma_channel_enable; 30.60 30.61 - // Set addresses. 30.62 - 30.63 - _regs[Dma_source] = source; 30.64 - _regs[Dma_destination] = destination; 30.65 - 30.66 // Set transfer count to the number of units. 30.67 30.68 unsigned int units = count < Dma_transfer_count_mask ? count : Dma_transfer_count_mask; 30.69 30.70 - _regs[Dma_transfer_count] = units; 30.71 + // NOTE: Request detection interval length (for autonomous mode) not considered. 30.72 30.73 - // Set auto-request for memory-to-memory transfers. Otherwise, set the 30.74 - // indicated request type. 30.75 + uint32_t command = (source_increment ? Dma_source_address_increment 30.76 + : Dma_source_address_no_increment) | 30.77 + (destination_increment ? Dma_destination_address_increment 30.78 + : Dma_destination_address_no_increment) | 30.79 + encode_source_port_width(source_width) | 30.80 + encode_destination_port_width(destination_width) | 30.81 + encode_transfer_unit_size(transfer_unit_size) | 30.82 + Dma_transfer_irq_enable; 30.83 + 30.84 + // Populate the descriptor, largely corresponding to the population of 30.85 + // registers when descriptors are not being used. 30.86 30.87 - _regs[Dma_request_source] = type; 30.88 + if (desc_vaddr) 30.89 + { 30.90 + // For a descriptor, the descriptor address would be set and the doorbell 30.91 + // register field for the channel set. 30.92 30.93 - // For a descriptor, the actual fields would be populated instead of the 30.94 - // command register, descriptor transfer would be indicated in the control/ 30.95 - // status register along with the appropriate descriptor size indicator. 30.96 + // For a descriptor, the actual fields would be populated instead of the 30.97 + // command register, descriptor transfer would be indicated in the control/ 30.98 + // status register along with the appropriate descriptor size indicator. 30.99 + 30.100 + struct x1600_dma_descriptor *desc = (struct x1600_dma_descriptor *) desc_vaddr; 30.101 + 30.102 + // NOTE: Linking to the same descriptor. 30.103 + 30.104 + uint32_t descriptor_offset = 0; 30.105 30.106 - /* NOTE: To be considered... 30.107 - * request detection interval length (for autonomous mode) 30.108 - */ 30.109 + desc->command = command | Dma_descriptor_link_enable; 30.110 + desc->source = source; 30.111 + desc->destination = destination; 30.112 + desc->transfer_count = (units & Dma_transfer_count_mask) | 30.113 + (descriptor_offset << Dma_descriptor_offset_shift); 30.114 + desc->request_source = (enum Dma_x1600_request_type) type; 30.115 + 30.116 + // NOTE: Stride not supported yet. 30.117 + 30.118 + l4_cache_clean_data((unsigned long) desc_vaddr, 30.119 + (unsigned long) desc_vaddr + sizeof(*desc)); 30.120 + 30.121 + // Commit the descriptor. 30.122 30.123 - _regs[Dma_command] = (source_increment ? Dma_source_address_increment : Dma_source_address_no_increment) | 30.124 - (destination_increment ? Dma_destination_address_increment : Dma_destination_address_no_increment) | 30.125 - encode_source_port_width(source_width) | 30.126 - encode_destination_port_width(destination_width) | 30.127 - encode_transfer_unit_size(transfer_unit_size) | 30.128 - Dma_transfer_irq_enable; 30.129 + _regs[Dma_descriptor_address] = desc_paddr; 30.130 + _chip->commit_descriptor(_channel); 30.131 + } 30.132 + 30.133 + // Otherwise, populate the registers for a one-off transfer. 30.134 30.135 - // For a descriptor, the descriptor address would be set and the doorbell 30.136 - // register field for the channel set. 30.137 + else 30.138 + { 30.139 + // Set addresses and transfer count. 30.140 30.141 - // Enable the channel (and peripheral). 30.142 + _regs[Dma_source] = source; 30.143 + _regs[Dma_destination] = destination; 30.144 + _regs[Dma_transfer_count] = units; 30.145 + _regs[Dma_request_source] = (enum Dma_x1600_request_type) type; 30.146 + _regs[Dma_command] = command; 30.147 + } 30.148 + 30.149 + // Enable the channel with descriptor transfer configured if appropriate. 30.150 30.151 _regs[Dma_control_status] = Dma_no_descriptor_transfer | 30.152 Dma_channel_enable; 30.153 @@ -398,8 +437,7 @@ 30.154 30.155 // Initialise the I2C controller. 30.156 30.157 -Dma_x1600_chip::Dma_x1600_chip(l4_addr_t start, l4_addr_t end, 30.158 - Cpm_x1600_chip *cpm) 30.159 +Dma_x1600_chip::Dma_x1600_chip(l4_addr_t start, l4_addr_t end, Cpm_chip *cpm) 30.160 : _start(start), _end(end), _cpm(cpm) 30.161 { 30.162 _regs = new Hw::Mmio_register_block<32>(start); 30.163 @@ -429,7 +467,7 @@ 30.164 30.165 // Obtain a channel object. 30.166 30.167 -Dma_x1600_channel * 30.168 +Dma_channel * 30.169 Dma_x1600_chip::get_channel(uint8_t channel, l4_cap_idx_t irq) 30.170 { 30.171 if (channel < 32) 30.172 @@ -470,28 +508,39 @@ 30.173 return _regs[Dma_control] & Dma_control_trans_halted ? true : false; 30.174 } 30.175 30.176 +void 30.177 +Dma_x1600_chip::commit_descriptor(uint8_t channel) 30.178 +{ 30.179 + _regs[Dma_doorbell_set] = (1 << channel); 30.180 +} 30.181 + 30.182 +Dma_chip *x1600_dma_chip(l4_addr_t start, l4_addr_t end, Cpm_chip *cpm) 30.183 +{ 30.184 + return new Dma_x1600_chip(start, end, cpm); 30.185 +} 30.186 + 30.187 30.188 30.189 // C language interface functions. 30.190 30.191 void *x1600_dma_init(l4_addr_t start, l4_addr_t end, void *cpm) 30.192 { 30.193 - return (void *) new Dma_x1600_chip(start, end, static_cast<Cpm_x1600_chip *>(cpm)); 30.194 + return (void *) x1600_dma_chip(start, end, static_cast<Cpm_chip *>(cpm)); 30.195 } 30.196 30.197 void x1600_dma_disable(void *dma_chip) 30.198 { 30.199 - static_cast<Dma_x1600_chip *>(dma_chip)->disable(); 30.200 + static_cast<Dma_chip *>(dma_chip)->disable(); 30.201 } 30.202 30.203 void x1600_dma_enable(void *dma_chip) 30.204 { 30.205 - static_cast<Dma_x1600_chip *>(dma_chip)->enable(); 30.206 + static_cast<Dma_chip *>(dma_chip)->enable(); 30.207 } 30.208 30.209 void *x1600_dma_get_channel(void *dma, uint8_t channel, l4_cap_idx_t irq) 30.210 { 30.211 - return static_cast<Dma_x1600_chip *>(dma)->get_channel(channel, irq); 30.212 + return static_cast<Dma_chip *>(dma)->get_channel(channel, irq); 30.213 } 30.214 30.215 unsigned int x1600_dma_transfer(void *dma_channel,
31.1 --- a/pkg/devices/lib/i2c/include/i2c-common.h Wed Apr 24 00:47:34 2024 +0200 31.2 +++ b/pkg/devices/lib/i2c/include/i2c-common.h Sat Apr 27 23:46:28 2024 +0200 31.3 @@ -1,7 +1,7 @@ 31.4 /* 31.5 * I2C support for the JZ4780 and X1600. 31.6 * 31.7 - * Copyright (C) 2017, 2018, 2019, 2023 Paul Boddie <paul@boddie.org.uk> 31.8 + * Copyright (C) 2017, 2018, 2019, 2023, 2024 Paul Boddie <paul@boddie.org.uk> 31.9 * 31.10 * This program is free software; you can redistribute it and/or 31.11 * modify it under the terms of the GNU General Public License as 31.12 @@ -28,7 +28,7 @@ 31.13 31.14 #ifdef __cplusplus 31.15 31.16 -#include <l4/devices/cpm.h> 31.17 +#include <l4/devices/cpm-generic.h> 31.18 #include <l4/devices/hw_mmio_register_block.h> 31.19 31.20 // I2C channel.
32.1 --- a/pkg/devices/lib/msc/include/msc-defs.h Wed Apr 24 00:47:34 2024 +0200 32.2 +++ b/pkg/devices/lib/msc/include/msc-defs.h Sat Apr 27 23:46:28 2024 +0200 32.3 @@ -21,7 +21,7 @@ 32.4 32.5 #pragma once 32.6 32.7 -#include <l4/devices/msc-common.h> 32.8 +#include <l4/devices/msc-generic.h> 32.9 32.10 32.11
33.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 33.2 +++ b/pkg/devices/lib/msc/include/msc-generic.h Sat Apr 27 23:46:28 2024 +0200 33.3 @@ -0,0 +1,164 @@ 33.4 +/* 33.5 + * MSC (MMC/SD controller) peripheral support. 33.6 + * 33.7 + * Copyright (C) 2024 Paul Boddie <paul@boddie.org.uk> 33.8 + * 33.9 + * This program is free software; you can redistribute it and/or 33.10 + * modify it under the terms of the GNU General Public License as 33.11 + * published by the Free Software Foundation; either version 2 of 33.12 + * the License, or (at your option) any later version. 33.13 + * 33.14 + * This program is distributed in the hope that it will be useful, 33.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 33.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 33.17 + * GNU General Public License for more details. 33.18 + * 33.19 + * You should have received a copy of the GNU General Public License 33.20 + * along with this program; if not, write to the Free Software 33.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, 33.22 + * Boston, MA 02110-1301, USA 33.23 + */ 33.24 + 33.25 +#pragma once 33.26 + 33.27 +#include <l4/devices/clocks.h> 33.28 +#include <l4/devices/cpm-generic.h> 33.29 +#include <l4/devices/dma.h> 33.30 +#include <l4/devices/dma-generic.h> 33.31 +#include <l4/devices/msc.h> 33.32 +#include <l4/sys/types.h> 33.33 +#include <stdint.h> 33.34 + 33.35 + 33.36 + 33.37 +#ifdef __cplusplus 33.38 + 33.39 +#include <l4/devices/hw_mmio_register_block.h> 33.40 + 33.41 + 33.42 + 33.43 +// MMC/SD controller channel. 33.44 + 33.45 +class Msc_channel 33.46 +{ 33.47 +protected: 33.48 + l4_addr_t _msc_start; 33.49 + Hw::Register_block<32> _regs; 33.50 + l4_cap_idx_t _irq; 33.51 + Cpm_chip *_cpm; 33.52 + enum Clock_identifiers _clock; 33.53 + 33.54 + // Support eight cards. 33.55 + 33.56 + struct msc_card _cards[8]; 33.57 + uint8_t _num_cards; 33.58 + int _card; 33.59 + 33.60 + // Utility methods. 33.61 + 33.62 + uint32_t get_field(uint32_t reg, uint32_t mask, uint8_t shift); 33.63 + void set_field(uint32_t reg, uint32_t mask, uint8_t shift, uint32_t value); 33.64 + 33.65 + // Low-level operations. 33.66 + 33.67 + void ack_irq(uint32_t flags); 33.68 + void unmask_irq(uint32_t flags); 33.69 + 33.70 + virtual void reset(); 33.71 + 33.72 + bool set_clock_frequency(uint64_t frequency); 33.73 + void start_clock(); 33.74 + void stop_clock(); 33.75 + 33.76 + // Hardware properties. 33.77 + 33.78 + virtual bool have_dma_enable_in_command(); 33.79 + virtual bool have_dma_selection(); 33.80 + 33.81 + // Command properties. 33.82 + 33.83 + bool command_will_write(uint8_t index); 33.84 + bool command_with_data(uint8_t index); 33.85 + bool command_uses_busy(uint8_t index); 33.86 + uint8_t get_response_format(uint8_t index); 33.87 + 33.88 + bool app_command_will_write(uint8_t index); 33.89 + bool app_command_with_data(uint8_t index); 33.90 + bool app_command_uses_busy(uint8_t index); 33.91 + uint8_t get_app_response_format(uint8_t index); 33.92 + 33.93 + // Command initiation. 33.94 + 33.95 + bool send_app_command(uint8_t index, uint32_t arg); 33.96 + bool send_command(uint8_t index, uint32_t arg); 33.97 + bool send_command(uint8_t index, uint32_t arg, uint8_t response_format, 33.98 + bool data, bool write, bool busy); 33.99 + 33.100 + // Response handling. 33.101 + 33.102 + bool have_response(); 33.103 + void read_response(uint16_t *buffer, uint8_t units); 33.104 + bool wait_for_irq(uint32_t flags); 33.105 + bool wait_for_irq(uint32_t flags, unsigned int timeout); 33.106 + 33.107 + // Initialisation operations. 33.108 + 33.109 + bool check_sd(); 33.110 + void init_sdio(); 33.111 + void init_sdmem(); 33.112 + void init_mmc(); 33.113 + void identify_cards(); 33.114 + void query_cards(); 33.115 + 33.116 + // Transfer operations. 33.117 + 33.118 + uint32_t recv_data(struct dma_region *region, uint32_t count); 33.119 + uint32_t send_data(struct dma_region *region, uint32_t count); 33.120 + 33.121 + virtual uint32_t transfer(l4re_dma_space_dma_addr_t from_paddr, 33.122 + l4re_dma_space_dma_addr_t to_paddr, 33.123 + bool recv, uint32_t count) = 0; 33.124 + 33.125 +public: 33.126 + explicit Msc_channel(l4_addr_t msc_start, l4_addr_t start, l4_cap_idx_t irq, 33.127 + Cpm_chip *cpm, enum Clock_identifiers clock); 33.128 + 33.129 + virtual ~Msc_channel(); 33.130 + 33.131 + void enable(); 33.132 + 33.133 + msc_card *get_cards(); 33.134 + 33.135 + uint8_t num_cards(); 33.136 + 33.137 + uint32_t read(uint8_t card, struct dma_region *region, 33.138 + uint32_t address, uint32_t count); 33.139 + 33.140 + uint32_t read_blocks(uint8_t card, struct dma_region *region, 33.141 + uint32_t block_address, uint32_t block_count); 33.142 +}; 33.143 + 33.144 + 33.145 + 33.146 +// MMC/SD controller device control. 33.147 + 33.148 +class Msc_chip 33.149 +{ 33.150 +protected: 33.151 + l4_addr_t _msc_start, _start, _end; 33.152 + Cpm_chip *_cpm; 33.153 + 33.154 + virtual unsigned int num_channels() = 0; 33.155 + 33.156 +public: 33.157 + explicit Msc_chip(l4_addr_t msc_start, l4_addr_t start, l4_addr_t end, 33.158 + Cpm_chip *cpm); 33.159 + 33.160 + virtual Msc_channel *get_channel(uint8_t channel, l4_cap_idx_t irq, 33.161 + Dma_channel *dma) = 0; 33.162 +}; 33.163 + 33.164 +Msc_chip *new_msc_chip(const char *name, l4_addr_t msc_start, l4_addr_t start, 33.165 + l4_addr_t end, Cpm_chip *cpm); 33.166 + 33.167 +#endif /* __cplusplus */
34.1 --- a/pkg/devices/lib/msc/include/msc-jz4780.h Wed Apr 24 00:47:34 2024 +0200 34.2 +++ b/pkg/devices/lib/msc/include/msc-jz4780.h Sat Apr 27 23:46:28 2024 +0200 34.3 @@ -21,7 +21,7 @@ 34.4 34.5 #pragma once 34.6 34.7 -#include <l4/devices/msc-common.h> 34.8 +#include <l4/devices/msc-generic.h> 34.9 #include <l4/sys/types.h> 34.10 #include <stdint.h> 34.11 34.12 @@ -36,14 +36,14 @@ 34.13 class Msc_jz4780_channel : public Msc_channel 34.14 { 34.15 protected: 34.16 - Dma_jz4780_channel *_dma; 34.17 + Dma_channel *_dma; 34.18 enum Dma_jz4780_request_type _request_type_in, _request_type_out; 34.19 34.20 public: 34.21 explicit Msc_jz4780_channel(l4_addr_t msc_start, l4_addr_t addr, 34.22 l4_cap_idx_t irq, Cpm_chip *cpm, 34.23 enum Clock_identifiers clock, 34.24 - Dma_jz4780_channel *dma, 34.25 + Dma_channel *dma, 34.26 enum Dma_jz4780_request_type request_type_in, 34.27 enum Dma_jz4780_request_type request_type_out); 34.28 34.29 @@ -76,9 +76,12 @@ 34.30 Cpm_chip *cpm); 34.31 34.32 Msc_channel *get_channel(uint8_t channel, l4_cap_idx_t irq, 34.33 - Dma_jz4780_channel *dma); 34.34 + Dma_channel *dma); 34.35 }; 34.36 34.37 +Msc_chip *jz4780_msc_chip(l4_addr_t msc_start, l4_addr_t start, l4_addr_t end, 34.38 + Cpm_chip *cpm); 34.39 + 34.40 #endif /* __cplusplus */ 34.41 34.42 /* C language interface. */
35.1 --- a/pkg/devices/lib/msc/include/msc-x1600.h Wed Apr 24 00:47:34 2024 +0200 35.2 +++ b/pkg/devices/lib/msc/include/msc-x1600.h Sat Apr 27 23:46:28 2024 +0200 35.3 @@ -21,7 +21,7 @@ 35.4 35.5 #pragma once 35.6 35.7 -#include <l4/devices/msc-common.h> 35.8 +#include <l4/devices/msc-generic.h> 35.9 #include <l4/sys/types.h> 35.10 #include <stdint.h> 35.11 35.12 @@ -36,7 +36,7 @@ 35.13 class Msc_x1600_channel : public Msc_channel 35.14 { 35.15 protected: 35.16 - Dma_x1600_channel *_dma; 35.17 + Dma_channel *_dma; 35.18 enum Dma_x1600_request_type _request_type_in, _request_type_out; 35.19 35.20 // Special overridden method. 35.21 @@ -47,7 +47,7 @@ 35.22 explicit Msc_x1600_channel(l4_addr_t msc_start, l4_addr_t addr, 35.23 l4_cap_idx_t irq, Cpm_chip *cpm, 35.24 enum Clock_identifiers clock, 35.25 - Dma_x1600_channel *dma, 35.26 + Dma_channel *dma, 35.27 enum Dma_x1600_request_type request_type_in, 35.28 enum Dma_x1600_request_type request_type_out); 35.29 35.30 @@ -78,9 +78,12 @@ 35.31 Cpm_chip *cpm); 35.32 35.33 Msc_channel *get_channel(uint8_t channel, l4_cap_idx_t irq, 35.34 - Dma_x1600_channel *dma); 35.35 + Dma_channel *dma); 35.36 }; 35.37 35.38 +Msc_chip *x1600_msc_chip(l4_addr_t msc_start, l4_addr_t start, l4_addr_t end, 35.39 + Cpm_chip *cpm); 35.40 + 35.41 #endif /* __cplusplus */ 35.42 35.43 /* C language interface. */
36.1 --- a/pkg/devices/lib/msc/src/Makefile Wed Apr 24 00:47:34 2024 +0200 36.2 +++ b/pkg/devices/lib/msc/src/Makefile Sat Apr 27 23:46:28 2024 +0200 36.3 @@ -4,7 +4,7 @@ 36.4 TARGET = libmsc.o.a libmsc.o.so 36.5 PC_FILENAME := libdrivers-msc 36.6 36.7 -SRC_CC := common.cc jz4780.cc x1600.cc 36.8 +SRC_CC := common.cc generic.cc jz4780.cc x1600.cc 36.9 36.10 PRIVATE_INCDIR += $(PKGDIR)/lib/msc/include 36.11
37.1 --- a/pkg/devices/lib/msc/src/common.cc Wed Apr 24 00:47:34 2024 +0200 37.2 +++ b/pkg/devices/lib/msc/src/common.cc Sat Apr 27 23:46:28 2024 +0200 37.3 @@ -29,8 +29,8 @@ 37.4 #include <math.h> 37.5 #include <stdio.h> 37.6 37.7 -#include "msc-common.h" 37.8 #include "msc-defs.h" 37.9 +#include "msc-generic.h" 37.10 37.11 37.12
38.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 38.2 +++ b/pkg/devices/lib/msc/src/generic.cc Sat Apr 27 23:46:28 2024 +0200 38.3 @@ -0,0 +1,57 @@ 38.4 +/* 38.5 + * Generic access to memory card functionality. 38.6 + * 38.7 + * Copyright (C) 2024 Paul Boddie <paul@boddie.org.uk> 38.8 + * 38.9 + * This program is free software; you can redistribute it and/or 38.10 + * modify it under the terms of the GNU General Public License as 38.11 + * published by the Free Software Foundation; either version 2 of 38.12 + * the License, or (at your option) any later version. 38.13 + * 38.14 + * This program is distributed in the hope that it will be useful, 38.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 38.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 38.17 + * GNU General Public License for more details. 38.18 + * 38.19 + * You should have received a copy of the GNU General Public License 38.20 + * along with this program; if not, write to the Free Software 38.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, 38.22 + * Boston, MA 02110-1301, USA 38.23 + */ 38.24 + 38.25 +#include <string.h> 38.26 +#include "msc-generic.h" 38.27 + 38.28 +/* Function declarations reproduced here to avoid clock identifier conflicts in 38.29 + the chip-specific headers. */ 38.30 + 38.31 +//extern Msc_chip *jz4730_msc_chip(l4_addr_t, l4_addr_t, l4_addr_t, Cpm_chip *); 38.32 +//extern Msc_chip *jz4740_msc_chip(l4_addr_t, l4_addr_t, l4_addr_t, Cpm_chip *); 38.33 +extern Msc_chip *jz4780_msc_chip(l4_addr_t, l4_addr_t, l4_addr_t, Cpm_chip *); 38.34 +extern Msc_chip *x1600_msc_chip(l4_addr_t, l4_addr_t, l4_addr_t, Cpm_chip *); 38.35 + 38.36 +struct msc_function 38.37 +{ 38.38 + const char *name; 38.39 + Msc_chip *(*function)(l4_addr_t, l4_addr_t, l4_addr_t, Cpm_chip *); 38.40 +}; 38.41 + 38.42 +static struct msc_function functions[] = { 38.43 + //{"jz4730", jz4730_msc_chip}, 38.44 + //{"jz4740", jz4740_msc_chip}, 38.45 + {"jz4780", jz4780_msc_chip}, 38.46 + {"x1600", x1600_msc_chip}, 38.47 + {NULL, NULL} 38.48 +}; 38.49 + 38.50 +Msc_chip *new_msc_chip(const char *name, l4_addr_t msc_start, l4_addr_t start, 38.51 + l4_addr_t end, Cpm_chip *cpm) 38.52 +{ 38.53 + for (struct msc_function *f = functions; f->name != NULL; f++) 38.54 + { 38.55 + if (!strcmp(name, f->name)) 38.56 + return f->function(msc_start, start, end, cpm); 38.57 + } 38.58 + 38.59 + return NULL; 38.60 +}
39.1 --- a/pkg/devices/lib/msc/src/jz4780.cc Wed Apr 24 00:47:34 2024 +0200 39.2 +++ b/pkg/devices/lib/msc/src/jz4780.cc Sat Apr 27 23:46:28 2024 +0200 39.3 @@ -31,7 +31,7 @@ 39.4 Msc_jz4780_channel::Msc_jz4780_channel(l4_addr_t msc_start, l4_addr_t addr, 39.5 l4_cap_idx_t irq, 39.6 Cpm_chip *cpm, enum Clock_identifiers clock, 39.7 - Dma_jz4780_channel *dma, 39.8 + Dma_channel *dma, 39.9 enum Dma_jz4780_request_type request_type_in, 39.10 enum Dma_jz4780_request_type request_type_out) 39.11 : Msc_channel(msc_start, addr, irq, cpm, clock), 39.12 @@ -60,7 +60,7 @@ 39.13 recv ? false : true, // increment source if sending 39.14 recv ? true : false, // increment destination if receiving 39.15 4, 4, unit_size, 39.16 - recv ? _request_type_in : _request_type_out); 39.17 + (int) (recv ? _request_type_in : _request_type_out)); 39.18 39.19 return to_transfer * unit_size; 39.20 } 39.21 @@ -76,7 +76,7 @@ 39.22 } 39.23 39.24 Msc_channel *Msc_jz4780_chip::get_channel(uint8_t channel, l4_cap_idx_t irq, 39.25 - Dma_jz4780_channel *dma) 39.26 + Dma_channel *dma) 39.27 { 39.28 if (channel < num_channels()) 39.29 return new Msc_jz4780_channel(_msc_start + channel * Msc_channel_offset, 39.30 @@ -87,6 +87,12 @@ 39.31 throw -L4_EINVAL; 39.32 } 39.33 39.34 +Msc_chip *jz4780_msc_chip(l4_addr_t msc_start, l4_addr_t start, l4_addr_t end, 39.35 + Cpm_chip *cpm) 39.36 +{ 39.37 + return new Msc_jz4780_chip(msc_start, start, end, cpm); 39.38 +} 39.39 + 39.40 39.41 39.42 // C language interface functions. 39.43 @@ -94,15 +100,15 @@ 39.44 void *jz4780_msc_init(l4_addr_t msc_start, l4_addr_t start, l4_addr_t end, 39.45 void *cpm) 39.46 { 39.47 - return (void *) new Msc_jz4780_chip(msc_start, start, end, 39.48 - static_cast<Cpm_jz4780_chip *>(cpm)); 39.49 + return (void *) jz4780_msc_chip(msc_start, start, end, 39.50 + static_cast<Cpm_chip *>(cpm)); 39.51 } 39.52 39.53 void *jz4780_msc_get_channel(void *msc, uint8_t channel, l4_cap_idx_t irq, 39.54 void *dma) 39.55 { 39.56 - return static_cast<Msc_jz4780_chip *>(msc)->get_channel(channel, irq, 39.57 - static_cast<Dma_jz4780_channel *>(dma)); 39.58 + return static_cast<Msc_chip *>(msc)->get_channel(channel, irq, 39.59 + static_cast<Dma_channel *>(dma)); 39.60 } 39.61 39.62 struct msc_card *jz4780_msc_get_cards(void *msc_channel)
40.1 --- a/pkg/devices/lib/msc/src/x1600.cc Wed Apr 24 00:47:34 2024 +0200 40.2 +++ b/pkg/devices/lib/msc/src/x1600.cc Sat Apr 27 23:46:28 2024 +0200 40.3 @@ -31,7 +31,7 @@ 40.4 Msc_x1600_channel::Msc_x1600_channel(l4_addr_t msc_start, l4_addr_t addr, 40.5 l4_cap_idx_t irq, 40.6 Cpm_chip *cpm, enum Clock_identifiers clock, 40.7 - Dma_x1600_channel *dma, 40.8 + Dma_channel *dma, 40.9 enum Dma_x1600_request_type request_type_in, 40.10 enum Dma_x1600_request_type request_type_out) 40.11 : Msc_channel(msc_start, addr, irq, cpm, clock), 40.12 @@ -77,7 +77,7 @@ 40.13 recv ? false : true, // increment source if sending 40.14 recv ? true : false, // increment destination if receiving 40.15 4, 4, unit_size, 40.16 - recv ? _request_type_in : _request_type_out); 40.17 + (int) (recv ? _request_type_in : _request_type_out)); 40.18 40.19 return to_transfer * unit_size; 40.20 } 40.21 @@ -93,7 +93,7 @@ 40.22 } 40.23 40.24 Msc_channel *Msc_x1600_chip::get_channel(uint8_t channel, l4_cap_idx_t irq, 40.25 - Dma_x1600_channel *dma) 40.26 + Dma_channel *dma) 40.27 { 40.28 if (channel < num_channels()) 40.29 return new Msc_x1600_channel(_msc_start + channel * Msc_channel_offset, 40.30 @@ -104,6 +104,12 @@ 40.31 throw -L4_EINVAL; 40.32 } 40.33 40.34 +Msc_chip *x1600_msc_chip(l4_addr_t msc_start, l4_addr_t start, l4_addr_t end, 40.35 + Cpm_chip *cpm) 40.36 +{ 40.37 + return new Msc_x1600_chip(msc_start, start, end, cpm); 40.38 +} 40.39 + 40.40 40.41 40.42 // C language interface functions. 40.43 @@ -111,15 +117,15 @@ 40.44 void *x1600_msc_init(l4_addr_t msc_start, l4_addr_t start, l4_addr_t end, 40.45 void *cpm) 40.46 { 40.47 - return (void *) new Msc_x1600_chip(msc_start, start, end, 40.48 - static_cast<Cpm_x1600_chip *>(cpm)); 40.49 + return (void *) x1600_msc_chip(msc_start, start, end, 40.50 + static_cast<Cpm_chip *>(cpm)); 40.51 } 40.52 40.53 void *x1600_msc_get_channel(void *msc, uint8_t channel, l4_cap_idx_t irq, 40.54 void *dma) 40.55 { 40.56 - return static_cast<Msc_x1600_chip *>(msc)->get_channel(channel, irq, 40.57 - static_cast<Dma_x1600_channel *>(dma)); 40.58 + return static_cast<Msc_chip *>(msc)->get_channel(channel, irq, 40.59 + static_cast<Dma_channel *>(dma)); 40.60 } 40.61 40.62 struct msc_card *x1600_msc_get_cards(void *msc_channel)
41.1 --- a/pkg/devices/lib/spi/include/spi-jz4780.h Wed Apr 24 00:47:34 2024 +0200 41.2 +++ b/pkg/devices/lib/spi/include/spi-jz4780.h Sat Apr 27 23:46:28 2024 +0200 41.3 @@ -44,8 +44,8 @@ 41.4 41.5 l4_addr_t _spi_start; 41.6 enum Clock_identifiers _clock; 41.7 - Cpm_jz4780_chip *_cpm; 41.8 - Dma_jz4780_channel *_dma; 41.9 + Cpm_chip *_cpm; 41.10 + Dma_channel *_dma; 41.11 enum Dma_jz4780_request_type _request_type; 41.12 uint64_t _frequency; 41.13 41.14 @@ -58,8 +58,8 @@ 41.15 public: 41.16 explicit Spi_jz4780_channel(l4_addr_t spi_start, l4_addr_t start, 41.17 enum Clock_identifiers clock, 41.18 - Cpm_jz4780_chip *cpm, 41.19 - Dma_jz4780_channel *dma, 41.20 + Cpm_chip *cpm, 41.21 + Dma_channel *dma, 41.22 enum Dma_jz4780_request_type request_type, 41.23 uint64_t frequency); 41.24 41.25 @@ -87,12 +87,12 @@ 41.26 { 41.27 private: 41.28 l4_addr_t _spi_start, _start, _end; 41.29 - Cpm_jz4780_chip *_cpm; 41.30 + Cpm_chip *_cpm; 41.31 41.32 public: 41.33 - explicit Spi_jz4780_chip(l4_addr_t spi_start, l4_addr_t start, l4_addr_t end, Cpm_jz4780_chip *cpm); 41.34 + explicit Spi_jz4780_chip(l4_addr_t spi_start, l4_addr_t start, l4_addr_t end, Cpm_chip *cpm); 41.35 41.36 - Spi_jz4780_channel *get_channel(uint8_t channel, Dma_jz4780_channel *dma, uint64_t frequency); 41.37 + Spi_jz4780_channel *get_channel(uint8_t channel, Dma_channel *dma, uint64_t frequency); 41.38 }; 41.39 41.40 #endif /* __cplusplus */
42.1 --- a/pkg/devices/lib/spi/src/jz4780.cc Wed Apr 24 00:47:34 2024 +0200 42.2 +++ b/pkg/devices/lib/spi/src/jz4780.cc Sat Apr 27 23:46:28 2024 +0200 42.3 @@ -206,8 +206,8 @@ 42.4 42.5 Spi_jz4780_channel::Spi_jz4780_channel(l4_addr_t spi_start, l4_addr_t start, 42.6 enum Clock_identifiers clock, 42.7 - Cpm_jz4780_chip *cpm, 42.8 - Dma_jz4780_channel *dma, 42.9 + Cpm_chip *cpm, 42.10 + Dma_channel *dma, 42.11 enum Dma_jz4780_request_type request_type, 42.12 uint64_t frequency) 42.13 : _spi_start(spi_start), _clock(clock), _cpm(cpm), _dma(dma), 42.14 @@ -416,13 +416,13 @@ 42.15 /* Initialise the peripheral abstraction. */ 42.16 42.17 Spi_jz4780_chip::Spi_jz4780_chip(l4_addr_t spi_start, l4_addr_t start, 42.18 - l4_addr_t end, Cpm_jz4780_chip *cpm) 42.19 + l4_addr_t end, Cpm_chip *cpm) 42.20 : _spi_start(spi_start), _start(start), _end(end), _cpm(cpm) 42.21 { 42.22 } 42.23 42.24 Spi_jz4780_channel * 42.25 -Spi_jz4780_chip::get_channel(uint8_t channel, Dma_jz4780_channel *dma, 42.26 +Spi_jz4780_chip::get_channel(uint8_t channel, Dma_channel *dma, 42.27 uint64_t frequency) 42.28 { 42.29 // NOTE: Only sending is supported. 42.30 @@ -445,13 +445,13 @@ 42.31 42.32 void *jz4780_spi_init(l4_addr_t spi_start, l4_addr_t start, l4_addr_t end, void *cpm) 42.33 { 42.34 - return new Spi_jz4780_chip(spi_start, start, end, static_cast<Cpm_jz4780_chip *>(cpm)); 42.35 + return new Spi_jz4780_chip(spi_start, start, end, static_cast<Cpm_chip *>(cpm)); 42.36 } 42.37 42.38 void *jz4780_spi_get_channel(void *spi, uint8_t channel, void *dma, uint64_t frequency) 42.39 { 42.40 return static_cast<Spi_jz4780_chip *>(spi)->get_channel(channel, 42.41 - static_cast<Dma_jz4780_channel *>(dma), frequency); 42.42 + static_cast<Dma_channel *>(dma), frequency); 42.43 } 42.44 42.45 uint32_t jz4780_spi_send(void *channel, uint32_t bytes, const uint8_t data[])
43.1 --- a/pkg/landfall-examples/hw_info/jz4780.c Wed Apr 24 00:47:34 2024 +0200 43.2 +++ b/pkg/landfall-examples/hw_info/jz4780.c Sat Apr 27 23:46:28 2024 +0200 43.3 @@ -659,7 +659,7 @@ 43.4 43.5 struct clock_info clocks[] = { 43.6 {"ext", Clock_external, "EXCLK"}, 43.7 - {"ext_512", Clock_external_div_512, "EXCLK/512"}, 43.8 + {"ext_512", Clock_external_div, "EXCLK/512"}, 43.9 {"rtc_ext", Clock_rtc_external, "RTCLK"}, 43.10 {"plla", Clock_pll_A, "PLL A"}, 43.11 {"plle", Clock_pll_E, "PLL E"},
44.1 --- a/pkg/landfall-examples/hw_info/x1600.c Wed Apr 24 00:47:34 2024 +0200 44.2 +++ b/pkg/landfall-examples/hw_info/x1600.c Sat Apr 27 23:46:28 2024 +0200 44.3 @@ -645,7 +645,7 @@ 44.4 44.5 struct clock_info clocks[] = { 44.6 {"ext", Clock_external, "EXCLK"}, 44.7 - {"ext_512", Clock_external_div_512, "EXCLK/512"}, 44.8 + {"ext_512", Clock_external_div, "EXCLK/512"}, 44.9 {"rtc_ext", Clock_rtc_external, "RTCLK"}, 44.10 {"plla", Clock_pll_A, "PLL A"}, 44.11 {"plle", Clock_pll_E, "PLL E"},
45.1 --- a/pkg/landfall-examples/msc_block_server/msc_block_server.cc Wed Apr 24 00:47:34 2024 +0200 45.2 +++ b/pkg/landfall-examples/msc_block_server/msc_block_server.cc Sat Apr 27 23:46:28 2024 +0200 45.3 @@ -19,11 +19,10 @@ 45.4 * Boston, MA 02110-1301, USA 45.5 */ 45.6 45.7 -#include <l4/devices/cpm-x1600.h> 45.8 -#include <l4/devices/dma.h> 45.9 -#include <l4/devices/dma-x1600.h> 45.10 +#include <l4/devices/cpm-generic.h> 45.11 +#include <l4/devices/dma-generic.h> 45.12 #include <l4/devices/memory.h> 45.13 -#include <l4/devices/msc-x1600.h> 45.14 +#include <l4/devices/msc-generic.h> 45.15 45.16 #include <l4/re/c/util/cap_alloc.h> 45.17 #include <l4/sys/debugger.h> 45.18 @@ -37,6 +36,7 @@ 45.19 45.20 #include <stdio.h> 45.21 #include <stdlib.h> 45.22 +#include <string.h> 45.23 45.24 #include <mem/memory_incremental.h> 45.25 #include <fsserver/page_queue_shared.h> 45.26 @@ -102,16 +102,18 @@ 45.27 45.28 /* Peripheral resources. */ 45.29 45.30 -static Cpm_x1600_chip *cpm; 45.31 -static Dma_x1600_chip *dma; 45.32 -static Msc_x1600_chip *msc; 45.33 +static Cpm_chip *cpm; 45.34 +static Dma_chip *dma; 45.35 +static Msc_chip *msc; 45.36 45.37 /* Obtain an abstraction for the memory card. */ 45.38 45.39 -static MscRegionOperations *get_msc_region_operations(int msc_channel_num, 45.40 +static MscRegionOperations *get_msc_region_operations(const char *machine, 45.41 + int msc_channel_num, 45.42 int dma_channel_num, 45.43 int card) 45.44 { 45.45 + char resource[strlen(machine) + 8]; 45.46 l4_addr_t cpm_base = 0, cpm_base_end = 0; 45.47 l4_addr_t dma_base = 0, dma_base_end = 0; 45.48 l4_addr_t msc_base = 0, msc_base_end = 0; 45.49 @@ -123,17 +125,21 @@ 45.50 45.51 /* Obtain resource details describing I/O memory. */ 45.52 45.53 - if (get_memory("x1600-cpm", &cpm_base, &cpm_base_end) < 0) 45.54 + sprintf(resource, "%s-cpm", machine); 45.55 + 45.56 + if (get_memory(resource, &cpm_base, &cpm_base_end) < 0) 45.57 return NULL; 45.58 45.59 - cpm = new Cpm_x1600_chip(cpm_base); 45.60 + cpm = new_cpm_chip(machine, cpm_base); 45.61 45.62 - if (get_memory("x1600-dma", &dma_base, &dma_base_end) < 0) 45.63 + sprintf(resource, "%s-dma", machine); 45.64 + 45.65 + if (get_memory(resource, &dma_base, &dma_base_end) < 0) 45.66 return NULL; 45.67 45.68 - dma = new Dma_x1600_chip(dma_base, dma_base_end, cpm); 45.69 + dma = new_dma_chip(machine, dma_base, dma_base_end, cpm); 45.70 45.71 - if (get_irq("x1600-dma", &dma_irq_start, &dma_irq_end) < 0) 45.72 + if (get_irq(resource, &dma_irq_start, &dma_irq_end) < 0) 45.73 return NULL; 45.74 45.75 l4_cap_idx_t dma_irq = l4re_util_cap_alloc(); 45.76 @@ -143,13 +149,15 @@ 45.77 45.78 dma->enable(); 45.79 45.80 - if (get_memory_complete("x1600-msc", &msc_base, &msc_base_end, 45.81 + sprintf(resource, "%s-msc", machine); 45.82 + 45.83 + if (get_memory_complete(resource, &msc_base, &msc_base_end, 45.84 &msc_phys_base, &msc_phys_base_end) < 0) 45.85 return NULL; 45.86 45.87 - msc = new Msc_x1600_chip(msc_phys_base, msc_base, msc_base_end, cpm); 45.88 + msc = new_msc_chip(machine, msc_phys_base, msc_base, msc_base_end, cpm); 45.89 45.90 - if (get_irq("x1600-msc", &msc_irq_start, &msc_irq_end) < 0) 45.91 + if (get_irq(resource, &msc_irq_start, &msc_irq_end) < 0) 45.92 return NULL; 45.93 45.94 l4_cap_idx_t msc_irq = l4re_util_cap_alloc(); 45.95 @@ -157,7 +165,7 @@ 45.96 if (init_irq(msc_channel_num, msc_irq, msc_irq_start, msc_irq_end)) 45.97 return NULL; 45.98 45.99 - Dma_x1600_channel *dma_channel = dma->get_channel(dma_channel_num, dma_irq); 45.100 + Dma_channel *dma_channel = dma->get_channel(dma_channel_num, dma_irq); 45.101 Msc_channel *msc_channel = msc->get_channel(msc_channel_num, msc_irq, dma_channel); 45.102 45.103 msc_channel->enable(); 45.104 @@ -198,26 +206,30 @@ 45.105 return 1; 45.106 } 45.107 45.108 - if (argc < 4) 45.109 + if (argc < 5) 45.110 { 45.111 - printf("Need a MSC channel/peripheral number, a DMA channel number, " \ 45.112 - "and a card number.\n\n" \ 45.113 + printf("Need the following:\n\n" \ 45.114 + "A machine indicator such as jz4780 or x1600.\n" \ 45.115 + "An MSC channel/peripheral number.\n" \ 45.116 + "A DMA channel number.\n" \ 45.117 + "A card number.\n\n" \ 45.118 "A number of memory pages can be indicated for the use of the " \ 45.119 "server.\n\n" \ 45.120 "A named capability from the environment can be specified.\n"); 45.121 return 1; 45.122 } 45.123 45.124 - int msc_channel_num = atoi(argv[1]); 45.125 - int dma_channel_num = atoi(argv[2]); 45.126 - int card = atoi(argv[3]); 45.127 + char *machine = argv[1]; 45.128 + int msc_channel_num = atoi(argv[2]); 45.129 + int dma_channel_num = atoi(argv[3]); 45.130 + int card = atoi(argv[4]); 45.131 45.132 unsigned int memory_pages = MEMORY_PAGES; 45.133 45.134 - if (argc > 4) 45.135 - memory_pages = atoi(argv[4]); 45.136 + if (argc > 5) 45.137 + memory_pages = atoi(argv[5]); 45.138 45.139 - const char *server_name = (argc > 5) ? argv[5] : ENV_FILESYSTEM_SERVER_NAME; 45.140 + const char *server_name = (argc > 6) ? argv[6] : ENV_FILESYSTEM_SERVER_NAME; 45.141 45.142 /* Obtain a DMA space for associating allocated memory with physical 45.143 addresses. */ 45.144 @@ -232,7 +244,8 @@ 45.145 return 1; 45.146 } 45.147 45.148 - MscRegionOperations *ops = get_msc_region_operations(msc_channel_num, 45.149 + MscRegionOperations *ops = get_msc_region_operations(machine, 45.150 + msc_channel_num, 45.151 dma_channel_num, 45.152 card); 45.153
46.1 --- a/pkg/landfall-examples/msc_block_server/msc_region_operations.h Wed Apr 24 00:47:34 2024 +0200 46.2 +++ b/pkg/landfall-examples/msc_block_server/msc_region_operations.h Sat Apr 27 23:46:28 2024 +0200 46.3 @@ -25,7 +25,7 @@ 46.4 46.5 #include <l4/devices/boot.h> 46.6 #include <l4/devices/dma.h> 46.7 -#include <l4/devices/msc-common.h> 46.8 +#include <l4/devices/msc-generic.h> 46.9 #include <systypes/base.h> 46.10 46.11