# HG changeset patch # User Paul Boddie # Date 1698422569 -7200 # Node ID 678a57edbba5d78d79acd68afc1b26f7d725b424 # Parent 934192f4945707ab31efe7e90c0f0d1d95eac68e Broadened the revised CPM support to encompass the JZ4780. diff -r 934192f49457 -r 678a57edbba5 pkg/devices/cpm/src/jz4780/cpm-jz4780.cc --- a/pkg/devices/cpm/src/jz4780/cpm-jz4780.cc Tue Oct 24 18:52:06 2023 +0200 +++ b/pkg/devices/cpm/src/jz4780/cpm-jz4780.cc Fri Oct 27 18:02:49 2023 +0200 @@ -100,7 +100,7 @@ /* Initialise the CPM abstraction. */ - Cpm_jz4780_chip cpm_device(cpm_virt_base, 48000000, 32768); + Cpm_jz4780_chip cpm_device(cpm_virt_base); /* Initialise and register a server object. */ diff -r 934192f49457 -r 678a57edbba5 pkg/devices/display/src/ci20/display-ci20_hdmi.cc --- a/pkg/devices/display/src/ci20/display-ci20_hdmi.cc Tue Oct 24 18:52:06 2023 +0200 +++ b/pkg/devices/display/src/ci20/display-ci20_hdmi.cc Fri Oct 27 18:02:49 2023 +0200 @@ -122,7 +122,7 @@ // NOTE: Should test to see if it is connected. - if (!cpm_device->get_frequency(Clock_lcd_pixel, &frequency)) + if (!cpm_device->get_frequency(Clock_lcd_pixel0, &frequency)) { hdmi->enable(frequency); } diff -r 934192f49457 -r 678a57edbba5 pkg/devices/include/clocks.h --- a/pkg/devices/include/clocks.h Tue Oct 24 18:52:06 2023 +0200 +++ b/pkg/devices/include/clocks.h Fri Oct 27 18:02:49 2023 +0200 @@ -27,7 +27,7 @@ enum Clock_identifiers { - Clock_audio, + Clock_aic, Clock_aic_bitclk, Clock_aic_pclk, Clock_can0, @@ -38,13 +38,16 @@ Clock_ddr, Clock_dma, Clock_emac, - Clock_external, - Clock_hclock0, - Clock_hclock2, + Clock_external, /* EXCLK */ + Clock_hclock0, /* AHB0 */ + Clock_hclock2, /* AHB2 */ + Clock_hclock2_pclock, /* AHB2, APB parent clock (JZ4780, X1600) */ Clock_hdmi, - Clock_i2c, Clock_i2c0, Clock_i2c1, + Clock_i2c2, + Clock_i2c3, + Clock_i2c4, Clock_i2s0, Clock_i2s0_rx, Clock_i2s0_tx, @@ -52,31 +55,33 @@ Clock_i2s1_rx, Clock_i2s1_tx, Clock_kbc, - Clock_lcd, - Clock_lcd_pixel, + Clock_lcd, /* LCD peripheral clock */ + Clock_lcd_pixel0, + Clock_lcd_pixel1, Clock_mac, - Clock_main, + Clock_main, /* SCLK_A */ Clock_mipi_csi, - Clock_msc, + Clock_msc, /* MSC parent clock (JZ4780) */ Clock_msc0, Clock_msc1, + Clock_msc2, Clock_none, - Clock_otg, - Clock_pclock, + Clock_otg0, + Clock_otg1, + Clock_pclock, /* APB */ Clock_pll_A, Clock_pll_E, Clock_pll_M, - Clock_pwm, + Clock_pll_V, Clock_pwm0, Clock_pwm1, + Clock_rtc, /* RTCLK */ Clock_scc, Clock_sfc, - Clock_smb0, - Clock_smb1, - Clock_smb2, - Clock_smb3, - Clock_smb4, - Clock_ssi, + Clock_ssi, /* SSI parent clock (JZ4780) */ + Clock_ssi0, + Clock_ssi1, + Clock_ssi2, Clock_timer, Clock_uart0, Clock_uart1, diff -r 934192f49457 -r 678a57edbba5 pkg/devices/lcd/src/jz4740/lcd-jz4740-device.cc --- a/pkg/devices/lcd/src/jz4740/lcd-jz4740-device.cc Tue Oct 24 18:52:06 2023 +0200 +++ b/pkg/devices/lcd/src/jz4740/lcd-jz4740-device.cc Fri Oct 27 18:02:49 2023 +0200 @@ -67,7 +67,10 @@ // times that of the pixel clock. cpm_device->set_frequency(Clock_lcd, pclk * 3); - cpm_device->set_frequency(Clock_lcd_pixel, pclk); + + // NOTE: Should support multiple pixel clocks. + + cpm_device->set_frequency(Clock_lcd_pixel0, pclk); cpm_device->start_clock(Clock_lcd); l4_sleep(1); // 1ms == 1000us diff -r 934192f49457 -r 678a57edbba5 pkg/devices/lib/cpm/include/cpm-common.h --- a/pkg/devices/lib/cpm/include/cpm-common.h Tue Oct 24 18:52:06 2023 +0200 +++ b/pkg/devices/lib/cpm/include/cpm-common.h Fri Oct 27 18:02:49 2023 +0200 @@ -23,8 +23,8 @@ #ifdef __cplusplus +#include #include -#include #include #include @@ -38,16 +38,12 @@ class Cpm_regs { +protected: Hw::Register_block<32> _regs; - -protected: Clock_base **_clocks; public: - uint32_t exclk_freq; - - explicit Cpm_regs(l4_addr_t addr, Clock_base *clocks[], - uint32_t exclk_freq); + explicit Cpm_regs(l4_addr_t addr, Clock_base *clocks[]); // Utility methods. @@ -217,6 +213,10 @@ int have_clock(Cpm_regs ®s); void start_clock(Cpm_regs ®s); void stop_clock(Cpm_regs ®s); + + // Undefined control object. + + static Control undefined; }; @@ -314,6 +314,7 @@ class Divider_pll : public Divider_base { Field _multiplier, _input_divider, _output_divider0, _output_divider1; + double _intermediate_min, _intermediate_max; // General frequency modifiers. @@ -325,10 +326,26 @@ void set_output_divider(Cpm_regs ®s, uint32_t divider); public: + + // Double output divider constructor. + explicit Divider_pll(Field multiplier, Field input_divider, - Field output_divider0, Field output_divider1) + Field output_divider0, Field output_divider1, + double intermediate_min, double intermediate_max) : _multiplier(multiplier), _input_divider(input_divider), - _output_divider0(output_divider0), _output_divider1(output_divider1) + _output_divider0(output_divider0), _output_divider1(output_divider1), + _intermediate_min(intermediate_min), _intermediate_max(intermediate_max) + { + } + + // Single output divider constructor. + + explicit Divider_pll(Field multiplier, Field input_divider, + Field output_divider, + double intermediate_min, double intermediate_max) + : _multiplier(multiplier), _input_divider(input_divider), + _output_divider0(output_divider), _output_divider1(Field::undefined), + _intermediate_min(intermediate_min), _intermediate_max(intermediate_max) { } @@ -425,7 +442,15 @@ class Clock_passive : public Clock_base { +protected: + uint32_t _frequency; + public: + explicit Clock_passive(uint32_t frequency) + : _frequency(frequency) + { + } + const char *clock_type() { return "passive"; } // Clock control. @@ -584,6 +609,11 @@ { } + explicit Clock_divided(Source source, Divider divider) + : Clock_divided_base(source), _control(Control::undefined), _divider(divider) + { + } + const char *clock_type() { return "divided"; } }; diff -r 934192f49457 -r 678a57edbba5 pkg/devices/lib/cpm/include/cpm-jz4730.h --- a/pkg/devices/lib/cpm/include/cpm-jz4730.h Tue Oct 24 18:52:06 2023 +0200 +++ b/pkg/devices/lib/cpm/include/cpm-jz4730.h Fri Oct 27 18:02:49 2023 +0200 @@ -21,8 +21,7 @@ #pragma once -#include - +#include #include #include @@ -30,13 +29,14 @@ #ifdef __cplusplus +#include #include /* A simple abstraction for accessing the CPM registers. * A proper device could inherit from Hw::Device and use an * Int_property for _exclk_freq. */ -class Cpm_jz4730_chip : public Cpm_chip +class Cpm_jz4730_chip : public Cpm_chip_base { private: Hw::Register_block<32> _regs; diff -r 934192f49457 -r 678a57edbba5 pkg/devices/lib/cpm/include/cpm-jz4740.h --- a/pkg/devices/lib/cpm/include/cpm-jz4740.h Tue Oct 24 18:52:06 2023 +0200 +++ b/pkg/devices/lib/cpm/include/cpm-jz4740.h Fri Oct 27 18:02:49 2023 +0200 @@ -21,8 +21,7 @@ #pragma once -#include - +#include #include #include @@ -30,13 +29,14 @@ #ifdef __cplusplus +#include #include /* A simple abstraction for accessing the CPM registers. * A proper device could inherit from Hw::Device and use an * Int_property for _exclk_freq. */ -class Cpm_jz4740_chip : public Cpm_chip +class Cpm_jz4740_chip : public Cpm_chip_base { private: Hw::Register_block<32> _regs; diff -r 934192f49457 -r 678a57edbba5 pkg/devices/lib/cpm/include/cpm-jz4780.h --- a/pkg/devices/lib/cpm/include/cpm-jz4780.h Tue Oct 24 18:52:06 2023 +0200 +++ b/pkg/devices/lib/cpm/include/cpm-jz4780.h Fri Oct 27 18:02:49 2023 +0200 @@ -21,8 +21,7 @@ #pragma once -#include - +#include #include #include @@ -30,125 +29,12 @@ #ifdef __cplusplus -#include - -/* A simple abstraction for accessing the CPM registers. - * A proper device could inherit from Hw::Device and use an - * Int_property for _exclk_freq and _rtclk_freq. */ +#include class Cpm_jz4780_chip : public Cpm_chip { -private: - Hw::Register_block<32> _regs; - uint32_t _exclk_freq, _rtclk_freq; - - // Utility methods. - - uint32_t get_field(uint32_t reg, uint32_t mask, uint8_t shift); - void set_field(uint32_t reg, uint32_t mask, uint8_t shift, uint32_t value); - uint8_t _get_divider(uint32_t reg, uint32_t mask, uint8_t shift); - - // PLL status. - - int have_pll(uint32_t pll_reg); - int pll_enabled(uint32_t pll_reg); - int pll_bypassed(uint32_t pll_reg); - - // PLL control. - - void pll_disable(uint32_t pll_reg); - void pll_enable(uint32_t pll_reg); - - // General frequency modifiers. - - uint16_t get_multiplier(uint32_t pll_reg); - void set_multiplier(uint32_t pll_reg, uint16_t multiplier); - uint8_t get_input_division(uint32_t pll_reg); - void set_input_division(uint32_t pll_reg, uint8_t divider); - uint8_t get_output_division(uint32_t pll_reg); - void set_output_division(uint32_t pll_reg, uint8_t divider); - - // Clock dividers. - - void set_hdmi_divider(uint16_t division); - void set_lcd_pixel_divider(uint8_t controller, uint16_t division); - - // Input frequencies. - - uint32_t get_pll_frequency(uint32_t pll_reg); - - // Clock sources. - - void set_hclock2_source(uint8_t source); - void set_hdmi_source(uint8_t source); - void set_lcd_source(uint8_t controller, uint8_t source); - - // Clock control. - - uint32_t get_clock_gate_register(enum Clock_identifiers clock); - uint32_t get_clock_gate_value(enum Clock_identifiers clock); - public: - void set_pclock_source(uint8_t source); - Cpm_jz4780_chip(l4_addr_t addr, uint32_t exclk_freq, uint32_t rtclk_freq); - - // Clock divider values. - - uint8_t get_cpu_divider(); - uint8_t get_hclock0_divider(); - uint8_t get_hclock2_divider(); - uint8_t get_pclock_divider(); - uint8_t get_hdmi_divider(); - uint8_t get_lcd_pixel_divider(uint8_t controller = 0); - uint8_t get_memory_divider(); - - // Clock sources. - - uint8_t get_main_source(); - uint8_t get_cpu_source(); - uint8_t get_hclock0_source(); - uint8_t get_hclock2_source(); - uint8_t get_hdmi_source(); - uint8_t get_lcd_source(uint8_t controller); - uint8_t get_lcd_source() { return get_lcd_source(0); } - uint8_t get_memory_source(); - uint8_t get_pclock_source(); - - // PLL frequency status. - - uint32_t get_apll_frequency(); - uint32_t get_epll_frequency(); - uint32_t get_mpll_frequency(); - uint32_t get_vpll_frequency(); - - uint32_t get_main_frequency(); - uint32_t get_cpu_source_frequency(); - uint32_t get_hclock0_source_frequency(); - uint32_t get_hclock2_source_frequency(); - uint32_t get_hdmi_source_frequency(); - uint32_t get_lcd_source_frequency(uint8_t controller); - uint32_t get_lcd_source_frequency() { return get_lcd_source_frequency(0); } - uint32_t get_memory_source_frequency(); - uint32_t get_pclock_source_frequency(); - - // Clock frequency status. - - uint32_t get_cpu_frequency(); - uint32_t get_hclock0_frequency(); - uint32_t get_hclock2_frequency(); - uint32_t get_memory_frequency(); - uint32_t get_pclock_frequency(); - - void set_pll_parameters(uint32_t pll_reg, uint16_t multiplier, uint8_t in_divider, uint8_t out_divider); - - // Clock frequency configuration. - - uint32_t get_frequency(enum Clock_identifiers clock); - void set_frequency(enum Clock_identifiers clock, uint32_t frequency); - - int have_clock(enum Clock_identifiers clock); - void start_clock(enum Clock_identifiers clock); - void stop_clock(enum Clock_identifiers clock); + explicit Cpm_jz4780_chip(l4_addr_t addr); }; #endif /* __cplusplus */ @@ -161,51 +47,25 @@ void *jz4780_cpm_init(l4_addr_t cpm_base); +const char *jz4780_cpm_clock_type(void *cpm, enum Clock_identifiers clock); + int jz4780_cpm_have_clock(void *cpm, enum Clock_identifiers clock); void jz4780_cpm_start_clock(void *cpm, enum Clock_identifiers clock); void jz4780_cpm_stop_clock(void *cpm, enum Clock_identifiers clock); -uint8_t jz4780_cpm_get_cpu_divider(void *cpm); -uint8_t jz4780_cpm_get_hclock0_divider(void *cpm); -uint8_t jz4780_cpm_get_hclock2_divider(void *cpm); -uint8_t jz4780_cpm_get_hdmi_divider(void *cpm); -uint8_t jz4780_cpm_get_lcd_pixel_divider(void *cpm); -uint8_t jz4780_cpm_get_memory_divider(void *cpm); -uint8_t jz4780_cpm_get_pclock_divider(void *cpm); - -uint8_t jz4780_cpm_get_hclock0_source(void *cpm); -uint8_t jz4780_cpm_get_hclock2_source(void *cpm); -uint8_t jz4780_cpm_get_hdmi_source(void *cpm); -uint8_t jz4780_cpm_get_lcd_source(void *cpm); -uint8_t jz4780_cpm_get_memory_source(void *cpm); -uint8_t jz4780_cpm_get_pclock_source(void *cpm); +int jz4780_cpm_get_parameters(void *cpm, enum Clock_identifiers clock, + uint32_t parameters[]); +int jz4780_cpm_set_parameters(void *cpm, enum Clock_identifiers clock, + int num_parameters, uint32_t parameters[]); -uint32_t jz4780_cpm_get_hclock0_source_frequency(void *cpm); -uint32_t jz4780_cpm_get_hclock2_source_frequency(void *cpm); -uint32_t jz4780_cpm_get_hdmi_source_frequency(void *cpm); -uint32_t jz4780_cpm_get_lcd_source_frequency(void *cpm); -uint32_t jz4780_cpm_get_memory_source_frequency(void *cpm); -uint32_t jz4780_cpm_get_pclock_source_frequency(void *cpm); - -void jz4780_cpm_set_pclock_source(void *cpm, uint8_t source); +uint8_t jz4780_cpm_get_source(void *cpm, enum Clock_identifiers clock); +void jz4780_cpm_set_source(void *cpm, enum Clock_identifiers clock, uint8_t source); +enum Clock_identifiers jz4780_cpm_get_source_clock(void *cpm, enum Clock_identifiers clock); +void jz4780_cpm_set_source_clock(void *cpm, enum Clock_identifiers clock, enum Clock_identifiers source); -uint8_t jz4780_cpm_get_main_source(void *cpm); -uint32_t jz4780_cpm_get_main_frequency(void *cpm); - -uint32_t jz4780_cpm_get_cpu_frequency(void *cpm); -uint32_t jz4780_cpm_get_hclock0_frequency(void *cpm); -uint32_t jz4780_cpm_get_hclock2_frequency(void *cpm); -uint32_t jz4780_cpm_get_memory_frequency(void *cpm); -uint32_t jz4780_cpm_get_pclock_frequency(void *cpm); - -uint32_t jz4780_cpm_get_apll_frequency(void *cpm); -uint32_t jz4780_cpm_get_epll_frequency(void *cpm); -uint32_t jz4780_cpm_get_mpll_frequency(void *cpm); -uint32_t jz4780_cpm_get_vpll_frequency(void *cpm); +uint32_t jz4780_cpm_get_source_frequency(void *cpm, enum Clock_identifiers clock); uint32_t jz4780_cpm_get_frequency(void *cpm, enum Clock_identifiers clock); -void jz4780_cpm_set_frequency(void *cpm, enum Clock_identifiers clock, uint32_t frequency); - -void jz4780_cpm_set_mpll_parameters(void *cpm, uint16_t multiplier, uint8_t in_divider, uint8_t out_divider); +int jz4780_cpm_set_frequency(void *cpm, enum Clock_identifiers clock, uint32_t frequency); EXTERN_C_END diff -r 934192f49457 -r 678a57edbba5 pkg/devices/lib/cpm/include/cpm-x1600.h --- a/pkg/devices/lib/cpm/include/cpm-x1600.h Tue Oct 24 18:52:06 2023 +0200 +++ b/pkg/devices/lib/cpm/include/cpm-x1600.h Fri Oct 27 18:02:49 2023 +0200 @@ -21,7 +21,7 @@ #pragma once -#include +#include #include #include @@ -29,50 +29,12 @@ #ifdef __cplusplus -#include -#include - -/* A simple abstraction for accessing the CPM registers. - * A proper device could inherit from Hw::Device and use an - * Int_property for _exclk_freq. */ +#include class Cpm_x1600_chip : public Cpm_chip { -private: - Hw::Register_block<32> _regs; - uint32_t _exclk_freq; - Cpm_regs _cpm_regs; - public: - Cpm_x1600_chip(l4_addr_t addr, uint32_t exclk_freq); - - const char *clock_type(enum Clock_identifiers clock); - - int have_clock(enum Clock_identifiers clock); - void start_clock(enum Clock_identifiers clock); - void stop_clock(enum Clock_identifiers clock); - - // Clock dividers. - - int get_parameters(enum Clock_identifiers clock, uint32_t parameters[]); - int set_parameters(enum Clock_identifiers clock, int num_parameters, - uint32_t parameters[]); - - // Clock sources. - - uint8_t get_source(enum Clock_identifiers clock); - void set_source(enum Clock_identifiers clock, uint8_t source); - enum Clock_identifiers get_source_clock(enum Clock_identifiers clock); - void set_source_clock(enum Clock_identifiers clock, enum Clock_identifiers source); - - // Source frequencies. - - uint32_t get_source_frequency(enum Clock_identifiers clock); - - // Output clock frequencies. - - uint32_t get_frequency(enum Clock_identifiers clock); - int set_frequency(enum Clock_identifiers clock, uint32_t frequency); + explicit Cpm_x1600_chip(l4_addr_t addr); }; #endif /* __cplusplus */ diff -r 934192f49457 -r 678a57edbba5 pkg/devices/lib/cpm/include/cpm.h --- a/pkg/devices/lib/cpm/include/cpm.h Tue Oct 24 18:52:06 2023 +0200 +++ b/pkg/devices/lib/cpm/include/cpm.h Fri Oct 27 18:02:49 2023 +0200 @@ -1,5 +1,5 @@ /* - * Clock and power management (CPM) abstractions. + * Common clock and power management (CPM) abstractions. * * Copyright (C) 2017, 2018, 2020, 2021, 2023 Paul Boddie * @@ -21,7 +21,7 @@ #pragma once -#include +#include #include #include @@ -29,16 +29,56 @@ #ifdef __cplusplus -/* A simple abstraction for accessing the CPM registers. */ +/* A transitional abstraction supporting older CPM abstractions. */ -class Cpm_chip +class Cpm_chip_base { public: virtual int have_clock(enum Clock_identifiers clock) = 0; - virtual void start_clock(enum Clock_identifiers clock) = 0; - virtual void stop_clock(enum Clock_identifiers clock) = 0; }; +/* A simple abstraction for accessing the CPM registers. */ + +class Cpm_chip : public Cpm_chip_base +{ +protected: + Clock_base **_clocks; + Cpm_regs _cpm_regs; + +public: + explicit Cpm_chip(l4_addr_t addr, Clock_base *clocks[]); + + const char *clock_type(enum Clock_identifiers clock); + + // Clock control. + + int have_clock(enum Clock_identifiers clock); + void start_clock(enum Clock_identifiers clock); + void stop_clock(enum Clock_identifiers clock); + + // Clock dividers. + + int get_parameters(enum Clock_identifiers clock, uint32_t parameters[]); + int set_parameters(enum Clock_identifiers clock, int num_parameters, + uint32_t parameters[]); + + // Clock sources. + + uint8_t get_source(enum Clock_identifiers clock); + void set_source(enum Clock_identifiers clock, uint8_t source); + enum Clock_identifiers get_source_clock(enum Clock_identifiers clock); + void set_source_clock(enum Clock_identifiers clock, enum Clock_identifiers source); + + // Source frequencies. + + uint32_t get_source_frequency(enum Clock_identifiers clock); + + // Output clock frequencies. + + uint32_t get_frequency(enum Clock_identifiers clock); + int set_frequency(enum Clock_identifiers clock, uint32_t frequency); +}; + #endif /* __cplusplus */ diff -r 934192f49457 -r 678a57edbba5 pkg/devices/lib/cpm/src/Makefile --- a/pkg/devices/lib/cpm/src/Makefile Tue Oct 24 18:52:06 2023 +0200 +++ b/pkg/devices/lib/cpm/src/Makefile Fri Oct 27 18:02:49 2023 +0200 @@ -4,7 +4,7 @@ TARGET = libcpm.o.a libcpm.o.so PC_FILENAME := libdrivers-cpm -SRC_CC := common.cc jz4730.cc jz4740.cc jz4780.cc x1600.cc +SRC_CC := chip.cc common.cc jz4730.cc jz4740.cc jz4780.cc x1600.cc PRIVATE_INCDIR += $(PKGDIR)/lib/cpm/include diff -r 934192f49457 -r 678a57edbba5 pkg/devices/lib/cpm/src/chip.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pkg/devices/lib/cpm/src/chip.cc Fri Oct 27 18:02:49 2023 +0200 @@ -0,0 +1,144 @@ +/* + * Common clock and power management functionality. + * + * Copyright (C) 2023 Paul Boddie + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA + */ + +#include "cpm.h" +#include "cpm-common.h" + + + +Cpm_chip::Cpm_chip(l4_addr_t addr, Clock_base *clocks[]) +: _clocks(clocks), _cpm_regs(addr, clocks) +{ +} + +const char * +Cpm_chip::clock_type(enum Clock_identifiers clock) +{ + return _clocks[clock]->clock_type(); +} + +int +Cpm_chip::have_clock(enum Clock_identifiers clock) +{ + return _clocks[clock]->have_clock(_cpm_regs); +} + +void +Cpm_chip::start_clock(enum Clock_identifiers clock) +{ + _clocks[clock]->start_clock(_cpm_regs); +} + +void +Cpm_chip::stop_clock(enum Clock_identifiers clock) +{ + _clocks[clock]->stop_clock(_cpm_regs); +} + +int +Cpm_chip::get_parameters(enum Clock_identifiers clock, uint32_t parameters[]) +{ + Clock_divided_base *clk = dynamic_cast(_clocks[clock]); + + if (clk != NULL) + return clk->get_parameters(_cpm_regs, parameters); + else + return 0; +} + +int +Cpm_chip::set_parameters(enum Clock_identifiers clock, int num_parameters, uint32_t parameters[]) +{ + Clock_divided_base *clk = dynamic_cast(_clocks[clock]); + + if (clk != NULL) + return clk->set_parameters(_cpm_regs, num_parameters, parameters); + else + return 0; +} + +uint8_t +Cpm_chip::get_source(enum Clock_identifiers clock) +{ + Clock_active *clk = dynamic_cast(_clocks[clock]); + + if (clk != NULL) + return clk->get_source(_cpm_regs); + else + return 0; +} + +enum Clock_identifiers +Cpm_chip::get_source_clock(enum Clock_identifiers clock) +{ + Clock_active *clk = dynamic_cast(_clocks[clock]); + + if (clk != NULL) + return clk->get_source_clock(_cpm_regs); + else + return Clock_undefined; +} + +void +Cpm_chip::set_source_clock(enum Clock_identifiers clock, enum Clock_identifiers source) +{ + Clock_active *clk = dynamic_cast(_clocks[clock]); + + if (clk != NULL) + clk->set_source_clock(_cpm_regs, source); +} + +void +Cpm_chip::set_source(enum Clock_identifiers clock, uint8_t source) +{ + Clock_active *clk = dynamic_cast(_clocks[clock]); + + if (clk != NULL) + clk->set_source(_cpm_regs, source); +} + +uint32_t +Cpm_chip::get_source_frequency(enum Clock_identifiers clock) +{ + Clock_active *clk = dynamic_cast(_clocks[clock]); + + if (clk != NULL) + return clk->get_source_frequency(_cpm_regs); + else + return 0; +} + +uint32_t +Cpm_chip::get_frequency(enum Clock_identifiers clock) +{ + return _clocks[clock]->get_frequency(_cpm_regs); +} + +int +Cpm_chip::set_frequency(enum Clock_identifiers clock, uint32_t frequency) +{ + Clock_divided_base *clk = dynamic_cast(_clocks[clock]); + + if (clk != NULL) + return clk->set_frequency(_cpm_regs, frequency); + else + return 0; +} diff -r 934192f49457 -r 678a57edbba5 pkg/devices/lib/cpm/src/common.cc --- a/pkg/devices/lib/cpm/src/common.cc Tue Oct 24 18:52:06 2023 +0200 +++ b/pkg/devices/lib/cpm/src/common.cc Fri Oct 27 18:02:49 2023 +0200 @@ -29,9 +29,8 @@ // Register access. -Cpm_regs::Cpm_regs(l4_addr_t addr, Clock_base *clocks[], - uint32_t exclk_freq) -: _clocks(clocks), exclk_freq(exclk_freq) +Cpm_regs::Cpm_regs(l4_addr_t addr, Clock_base *clocks[]) +: _clocks(clocks) { _regs = new Hw::Mmio_register_block<32>(addr); } @@ -204,6 +203,10 @@ _change_enable.set_field(regs, 1); } +// Undefined control. + +Control Control::undefined; + // PLL-specific control. @@ -419,7 +422,8 @@ Divider_pll::get_output_divider(Cpm_regs ®s) { uint32_t d0 = zero_as_one(_output_divider0.get_field(regs)); - uint32_t d1 = zero_as_one(_output_divider1.get_field(regs)); + uint32_t d1 = _output_divider1.is_defined() ? + zero_as_one(_output_divider1.get_field(regs)) : 1; return d0 * d1; } @@ -427,14 +431,24 @@ void Divider_pll::set_output_divider(Cpm_regs ®s, uint32_t divider) { + uint32_t d0, d1; + // Assert 1 as a minimum. - // Divider 0 must be less than or equal to divider 1. - - uint32_t d0, d1; if (!divider) divider = 1; + // Attempt to set any single divider. + + if (!_output_divider1.is_defined()) + { + _output_divider0.set_field(regs, divider); + return; + } + + // For two-divider implementations such as the X1600, divider 0 must be less + // than or equal to divider 1. + if (divider < _output_divider1.get_limit()) { d0 = 1; @@ -460,41 +474,59 @@ int Divider_pll::set_frequency(Cpm_regs ®s, uint32_t source_frequency, uint32_t frequency) { - double intermediate_min = 600000000, intermediate_max = 2400000000; double intermediate_multiplier, intermediate_input_divider; uint32_t output_min, output_max, output0, output1; uint32_t multiplier, input_divider, output_divider; - // Distribute the divider across the input and output divider. For the X1600, - // the multiplier and input divider should collectively deliver a frequency in - // the range 600-2400 MHz. + // Define the range for the output dividers using the intermediate frequency + // range applying to each chip, this being the result of the multiplier and + // input divider. - output_min = (uint32_t) ceil(intermediate_min / frequency); - output_max = (uint32_t) floor(intermediate_max / frequency); + output_min = (uint32_t) ceil(_intermediate_min / frequency); + output_max = (uint32_t) floor(_intermediate_max / frequency); + + // Distribute the divider across the input and output dividers. output_divider = output_min; while (output_divider <= output_max) { + bool usable_divider; + // Test divider constraints. - output0 = (uint32_t) floor(sqrt(output_divider)); - output1 = (uint32_t) floor(output_divider / output0); + if (_output_divider1.is_defined()) + { + output0 = (uint32_t) floor(sqrt(output_divider)); + output1 = (uint32_t) floor(output_divider / output0); - if ((output0 * output1 == output_divider) && + usable_divider = ((output0 * output1 == output_divider) && (output0 <= _output_divider0.get_limit()) && - (output1 <= _output_divider1.get_limit())) + (output1 <= _output_divider1.get_limit())); + } + else + usable_divider = output_divider <= _output_divider0.get_limit(); + + // Apply any usable divider. + + if (usable_divider) { - // Calculate the other parameters. + // Calculate the other parameters. Start by working back from the desired + // output frequency to obtain an intermediate frequency using the proposed + // divider. uint32_t intermediate_frequency = frequency * output_divider; + // Calculate the required multiplier and divider. + get_divider_operands(intermediate_frequency, source_frequency, &intermediate_multiplier, &intermediate_input_divider); multiplier = (uint32_t) round(intermediate_multiplier); input_divider = (uint32_t) round(intermediate_input_divider); + // Attempt to reduce the multiplier and divider to usable values. + uint32_t multiplier_limit = _multiplier.get_limit(); uint32_t input_divider_limit = _input_divider.get_limit(); @@ -721,9 +753,8 @@ uint32_t Clock_passive::get_frequency(Cpm_regs ®s) { - // NOTE: Return the external clock frequency. - - return regs.exclk_freq; + (void) regs; + return _frequency; } diff -r 934192f49457 -r 678a57edbba5 pkg/devices/lib/cpm/src/jz4730.cc --- a/pkg/devices/lib/cpm/src/jz4730.cc Tue Oct 24 18:52:06 2023 +0200 +++ b/pkg/devices/lib/cpm/src/jz4730.cc Fri Oct 27 18:02:49 2023 +0200 @@ -116,12 +116,12 @@ case Clock_uart3: return (1 << Clock_gate_uart3); case Clock_aic_bitclk: return (1 << Clock_gate_aic_bitclk); case Clock_scc: return (1 << Clock_gate_scc); - case Clock_msc: return (1 << Clock_gate_msc); + case Clock_msc0: return (1 << Clock_gate_msc); case Clock_ssi: return (1 << Clock_gate_ssi); case Clock_pwm1: return (1 << Clock_gate_pwm1); case Clock_pwm0: return (1 << Clock_gate_pwm0); case Clock_aic_pclk: return (1 << Clock_gate_aic_pclk); - case Clock_i2c: return (1 << Clock_gate_i2c); + case Clock_i2c0: return (1 << Clock_gate_i2c); case Clock_lcd: return (1 << Clock_gate_lcd); case Clock_uhc: return (1 << Clock_gate_uhc); case Clock_dma: return (1 << Clock_gate_dmac); @@ -309,7 +309,7 @@ uint32_t Cpm_jz4730_chip::get_frequency(enum Clock_identifiers clock) { - if (clock == Clock_lcd_pixel) + if (clock == Clock_lcd_pixel0) return get_source_frequency() / get_lcd_pixel_divider(); // NOTE: Consider a better error result. @@ -331,7 +331,7 @@ set_lcd_device_divider(out / frequency); break; - case Clock_lcd_pixel: + case Clock_lcd_pixel0: set_lcd_pixel_divider(out / frequency); break; diff -r 934192f49457 -r 678a57edbba5 pkg/devices/lib/cpm/src/jz4740.cc --- a/pkg/devices/lib/cpm/src/jz4740.cc Tue Oct 24 18:52:06 2023 +0200 +++ b/pkg/devices/lib/cpm/src/jz4740.cc Fri Oct 27 18:02:49 2023 +0200 @@ -263,7 +263,7 @@ uint32_t Cpm_jz4740_chip::get_frequency(enum Clock_identifiers clock) { - if (clock == Clock_lcd_pixel) + if (clock == Clock_lcd_pixel0) return get_source_frequency() / get_lcd_pixel_divider(); // NOTE: Consider a better error result. @@ -285,7 +285,7 @@ set_lcd_device_divider(out / frequency); break; - case Clock_lcd_pixel: + case Clock_lcd_pixel0: set_lcd_pixel_divider(out / frequency); break; diff -r 934192f49457 -r 678a57edbba5 pkg/devices/lib/cpm/src/jz4780.cc --- a/pkg/devices/lib/cpm/src/jz4780.cc Tue Oct 24 18:52:06 2023 +0200 +++ b/pkg/devices/lib/cpm/src/jz4780.cc Fri Oct 27 18:02:49 2023 +0200 @@ -3,7 +3,7 @@ * provided by the jz4780 and related SoCs. The power management * functionality could be exposed using a separate driver. * - * Copyright (C) 2017, 2018, 2020, 2021 Paul Boddie + * Copyright (C) 2017, 2018, 2020, 2021, 2023 Paul Boddie * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as @@ -26,780 +26,514 @@ +// Register locations. + enum Regs : unsigned { Clock_control = 0x000, // CPCCR Low_power_control = 0x004, // LCR + Clock_gate0 = 0x020, // CLKGR0 + Clock_gate1 = 0x028, // CLKGR1 + Sleep_control = 0x024, // OPCR (oscillator and power control) + Clock_status = 0x0d4, // CPCSR + + Divider_bch = 0x0ac, // BCHCDR + Divider_cim = 0x07c, // CIMCDR + Divider_ddr = 0x02c, // DDRCDR + Divider_gpu = 0x088, // GPUCDR + Divider_hdmi = 0x08c, // HDMICDR + Divider_i2s0 = 0x060, // I2SCDR + Divider_i2s1 = 0x0a0, // I2S1CDR + Divider_lcd0 = 0x054, // LP0CDR + Divider_lcd1 = 0x064, // LP1CDR + Divider_msc0 = 0x068, // MSC0CDR + Divider_msc1 = 0x0a4, // MSC1CDR + Divider_msc2 = 0x0a8, // MSC2CDR + Divider_pcm = 0x084, // PCMCDR + Divider_ssi = 0x074, // SSICDR + Divider_uhc = 0x06c, // UHCCDR + Divider_vpu = 0x030, // VPUCDR + + Cpm_interrupt = 0x0b0, // CPM_INTR + Cpm_interrupt_en = 0x0b4, // CPM_INTRE + Cpm_scratch = 0x034, // CPSPR + Cpm_scratch_prot = 0x038, // CPSPPR + + Usb_param_control0 = 0x03c, // USBPCR + Usb_reset_detect = 0x040, // USBRDT + Usb_vbus_jitter = 0x044, // USBVBFIL + Usb_param_control1 = 0x048, // USBPCR1 + Pll_control = 0x00c, // CPPCR Pll_control_A = 0x010, // CPAPCR Pll_control_M = 0x014, // CPMPCR Pll_control_E = 0x018, // CPEPCR Pll_control_V = 0x01c, // CPVPCR - Clock_gate0 = 0x020, // CLKGR0 - Clock_gate1 = 0x028, // CLKGR1 - Sleep_control = 0x024, // OPCR (oscillator and power control) - Ddr_divider = 0x02c, // DDRCDR - I2s_divider0 = 0x060, // I2SCDR - I2s_divider1 = 0x0a0, // I2S1CDR - Lcd_divider0 = 0x054, // LP0CDR - Lcd_divider1 = 0x064, // LP1CDR - Msc_divider0 = 0x068, // MSC0CDR - Msc_divider1 = 0x0a4, // MSC1CDR - Msc_divider2 = 0x0a8, // MSC2CDR - Uhc_divider = 0x06c, // UHCCDR - Ssi_divider = 0x074, // SSICDR - - // ... - - Hdmi_divider = 0x08c, // HDMICDR - - // ... -}; - -enum Clock_bits : unsigned -{ - Clock_cpu_change_enable = 22, // CE_CPU - Clock_pclock_divider = 16, // PDIV (slow APB peripherals) - Clock_hclock2_divider = 12, // H2DIV (fast AHB peripherals) - Clock_hclock0_divider = 8, // H0DIV (fast AHB peripherals) - Clock_cpu_divider = 0, // CDIV -}; - -enum Pll_bits : unsigned -{ - Pll_multiplier = 19, // xPLLM - Pll_input_division = 13, // xPLLN - Pll_output_division = 9, // xPLLOD - Pll_stable = 4, // xPLL_ON - Pll_bypassed = 1, // xPLLBP - Pll_enabled = 0, // xPLLEN -}; - -enum Clock_source_bits : unsigned -{ - Clock_source_main = 30, // SEL_SRC (output to SCLK_A) - Clock_source_cpu = 28, // SEL_CPLL (output to CCLK) - Clock_source_hclock0 = 26, // SEL_H0PLL (output to AHB0) - Clock_source_hclock2 = 24, // SEL_H2PLL (output to AHB2) - Clock_source_ddr = 30, // DCS - Clock_source_i2s = 31, // I2CS - Clock_source_lcd = 30, // LPCS - Clock_source_hdmi = 30, // HPCS -}; - -enum Clock_sources : unsigned -{ - // Main clock sources. - - Source_pll_A = 1, // APLL - Source_external = 2, // EXCLK - Source_realtime = 3, // RTCLK - - // Stoppable clock sources. - - Source_mux_stopped = 0, - Source_mux_main = 1, // SCLK_A - Source_mux_pll_M = 2, // MPLL - Source_mux_pll_E = 3, // EPLL - Source_mux_realtime = 3, // RTCLK (TCK) - - // Unstoppable clock sources. - - Source_main = 0, // SCLK_A - Source_pll_M = 1, // MPLL - Source_pll_E = 2, // EPLL - Source_pll_V = 2, // VPLL - Source_otg_phy = 3, // OTG_PHY -}; - -enum Clock_gate_bits : unsigned -{ - Clock_gate_lcd1 = 28, // LCD (in CLKGR0) - Clock_gate_lcd0 = 27, // TVE (in CLKGR0) - Clock_gate_hdmi = 9, // HDMI (in CLKGR1) - Clock_gate_smb4 = 12, // SMB4 (in CLKGR1) - Clock_gate_smb3 = 0, // SMB3 (in CLKGR1) - Clock_gate_smb2 = 25, // SMB2 (in CLKGR0) - Clock_gate_smb1 = 6, // SMB1 (in CLKGR0) - Clock_gate_smb0 = 5, // SMB0 (in CLKGR0) -}; - -enum Divider_bits : unsigned -{ - Ddr_divider_value = 0, // DDRCDR - Hdmi_divider_value = 0, // HDMICDR - Lcd_divider_value = 0, // LPCDR -}; - -enum Lcd_clock_values : unsigned -{ - Lcd_change_enable = 0x10000000, // CE_LCD - Lcd_change_busy = 0x08000000, // LCD_BUSY - Lcd_clock_stop = 0x04000000, // LCD_STOP -}; - -enum Hdmi_divider_values : unsigned -{ - Hdmi_select_mask = 0xc0000000, // HPCS - Hdmi_change_enable = 0x20000000, // CE_HDMI - Hdmi_change_busy = 0x10000000, // HDMI_BUSY - Hdmi_clock_stop = 0x08000000, // HDMI_STOP }; -// If implemented as a Hw::Device, various properties would be -// initialised in the constructor and obtained from the device tree -// definitions. +// Register field definitions. -Cpm_jz4780_chip::Cpm_jz4780_chip(l4_addr_t addr, uint32_t exclk_freq, uint32_t rtclk_freq) -: _exclk_freq(exclk_freq), _rtclk_freq(rtclk_freq) -{ - _regs = new Hw::Mmio_register_block<32>(addr); - - // add_cid("cpm"); - // add_cid("cpm-jz4780"); - // register_property("exclk_freq", &_exclk_freq); -} - -// Clock/timer control. +static Field Clock_source_main (Clock_control, 3, 30), // SEL_SRC (output to SCLK_A) + Clock_source_cpu (Clock_control, 3, 28), // SEL_CPLL (output to CCLK) + Clock_source_hclock0 (Clock_control, 3, 26), // SEL_H0PLL (output to AHB0) + Clock_source_hclock2 (Clock_control, 3, 24), // SEL_H2PLL (output to AHB2) + Clock_source_bch (Divider_bch, 3, 30), // BPCS + Clock_source_cim (Divider_cim, 1, 31), // CIMPCS + Clock_source_ddr (Divider_ddr, 3, 30), // DCS + Clock_source_gpu (Divider_gpu, 3, 30), // GPCS + Clock_source_hdmi (Divider_hdmi, 3, 30), // HPCS + Clock_source_i2s0 (Divider_i2s0, 3, 30), // I2CS, I2PCS + Clock_source_i2s1 (Divider_i2s1, 3, 30), // I2CS, I2PCS + Clock_source_lcd0 (Divider_lcd0, 3, 30), // LPCS + Clock_source_lcd1 (Divider_lcd1, 3, 30), // LPCS + Clock_source_msc (Divider_msc0, 3, 30), // MPCS + Clock_source_pcm (Divider_pcm, 7, 29), // PCMS, PCMPCS + Clock_source_ssi (Divider_ssi, 1, 30), // SPCS + Clock_source_uhc (Divider_uhc, 3, 30), // UHCS + Clock_source_vpu (Divider_vpu, 3, 30), // VCS -uint32_t -Cpm_jz4780_chip::get_clock_gate_register(enum Clock_identifiers clock) -{ - switch (clock) - { - case Clock_hdmi: return Clock_gate1; - case Clock_smb4: return Clock_gate1; - case Clock_smb3: return Clock_gate1; - default: return Clock_gate0; - } -} + Clock_busy_cpu (Clock_status, 1, 0), + Clock_busy_hclock0 (Clock_status, 1, 1), + Clock_busy_hclock2 (Clock_status, 1, 2), + Clock_busy_bch (Divider_bch, 1, 28), + Clock_busy_cim (Divider_cim, 1, 29), + Clock_busy_ddr (Divider_ddr, 1, 28), + Clock_busy_gpu (Divider_gpu, 1, 28), + Clock_busy_hdmi (Divider_hdmi, 1, 28), + Clock_busy_i2s0 (Divider_i2s0, 1, 28), + Clock_busy_i2s1 (Divider_i2s1, 1, 28), + Clock_busy_lcd0 (Divider_lcd0, 1, 27), + Clock_busy_lcd1 (Divider_lcd1, 1, 27), + Clock_busy_msc0 (Divider_msc0, 1, 28), + Clock_busy_msc1 (Divider_msc1, 1, 28), + Clock_busy_msc2 (Divider_msc2, 1, 28), + Clock_busy_pcm (Divider_pcm, 1, 27), + Clock_busy_ssi (Divider_ssi, 1, 28), + Clock_busy_uhc (Divider_uhc, 1, 28), + Clock_busy_vpu (Divider_vpu, 1, 28), -uint32_t -Cpm_jz4780_chip::get_clock_gate_value(enum Clock_identifiers clock) -{ - switch (clock) - { - case Clock_lcd: return (1 << Clock_gate_lcd1) | (1 << Clock_gate_lcd0); - case Clock_hdmi: return (1 << Clock_gate_hdmi); - case Clock_smb4: return (1 << Clock_gate_smb4); - case Clock_smb3: return (1 << Clock_gate_smb3); - case Clock_smb2: return (1 << Clock_gate_smb2); - case Clock_smb1: return (1 << Clock_gate_smb1); - case Clock_smb0: return (1 << Clock_gate_smb0); - default: return 0; - } -} + Clock_change_enable_cpu (Clock_control, 1, 22), + Clock_change_enable_ahb0 (Clock_control, 1, 21), + Clock_change_enable_ahb2 (Clock_control, 1, 20), + Clock_change_enable_bch (Divider_bch, 1, 29), + Clock_change_enable_cim (Divider_cim, 1, 30), + Clock_change_enable_ddr (Divider_ddr, 1, 29), + Clock_change_enable_gpu (Divider_gpu, 1, 29), + Clock_change_enable_hdmi (Divider_hdmi, 1, 29), + Clock_change_enable_i2s0 (Divider_i2s0, 1, 29), + Clock_change_enable_i2s1 (Divider_i2s1, 1, 29), + Clock_change_enable_lcd0 (Divider_lcd0, 1, 28), + Clock_change_enable_lcd1 (Divider_lcd1, 1, 28), + Clock_change_enable_msc0 (Divider_msc0, 1, 29), + Clock_change_enable_msc1 (Divider_msc1, 1, 29), + Clock_change_enable_msc2 (Divider_msc2, 1, 29), + Clock_change_enable_pcm (Divider_pcm, 1, 28), + Clock_change_enable_ssi (Divider_ssi, 1, 29), + Clock_change_enable_uhc (Divider_uhc, 1, 29), + Clock_change_enable_vpu (Divider_vpu, 1, 29), -int -Cpm_jz4780_chip::have_clock(enum Clock_identifiers clock) -{ - return !(_regs[get_clock_gate_register(clock)] & get_clock_gate_value(clock)); -} - -void -Cpm_jz4780_chip::start_clock(enum Clock_identifiers clock) -{ - uint32_t gate = get_clock_gate_register(clock); - - _regs[gate] = _regs[gate] & ~get_clock_gate_value(clock); -} - -void -Cpm_jz4780_chip::stop_clock(enum Clock_identifiers clock) -{ - uint32_t gate = get_clock_gate_register(clock); - - _regs[gate] = _regs[gate] | get_clock_gate_value(clock); -} - - + Clock_divider_cpu (Clock_control, 0x0f, 0), // CDIV + Clock_divider_hclock0 (Clock_control, 0x0f, 8), // H0DIV (fast AHB peripherals) + Clock_divider_hclock2 (Clock_control, 0x0f, 12), // H2DIV (fast AHB peripherals) + Clock_divider_l2cache (Clock_control, 0x0f, 4), // L2CDIV + Clock_divider_pclock (Clock_control, 0x0f, 16), // PDIV (slow APB peripherals) + Clock_divider_bch (Divider_bch, 0x0f, 0), // BCHCDR + Clock_divider_cim (Divider_cim, 0xff, 0), // CIMCDR + Clock_divider_ddr (Divider_ddr, 0x0f, 0), // DDRCDR + Clock_divider_gpu (Divider_gpu, 0x0f, 0), // GPUCDR + Clock_divider_hdmi (Divider_hdmi, 0xff, 0), // HDMICDR + Clock_divider_i2s0 (Divider_i2s0, 0xff, 0), // I2SCDR + Clock_divider_i2s1 (Divider_i2s1, 0xff, 0), // I2SCDR + Clock_divider_lcd0 (Divider_lcd0, 0xff, 0), // LPCDR + Clock_divider_lcd1 (Divider_lcd1, 0xff, 0), // LPCDR + Clock_divider_msc0 (Divider_msc0, 0xff, 0), // MSC0CDR + Clock_divider_msc1 (Divider_msc1, 0xff, 0), // MSC1CDR + Clock_divider_msc2 (Divider_msc2, 0xff, 0), // MSC2CDR + Clock_divider_pcm (Divider_pcm, 0xff, 0), // PCMCDR + Clock_divider_ssi (Divider_ssi, 0xff, 0), // SSICDR + Clock_divider_uhc (Divider_uhc, 0xff, 0), // UHCCDR + Clock_divider_vpu (Divider_vpu, 0x0f, 0), // VPUCDR -// Utility methods. - -uint32_t -Cpm_jz4780_chip::get_field(uint32_t reg, uint32_t mask, uint8_t shift) -{ - return (_regs[reg] & (mask << shift)) >> shift; -} + Clock_gate_main (Clock_control, 1, 23, true), // GATE_SCLKA + Clock_gate_ddr (Clock_gate0, 3, 30, true), // DDR1, DDR0 + Clock_gate_ipu (Clock_gate0, 1, 29, true), // IPU + Clock_gate_lcd (Clock_gate0, 3, 27, true), // LCD, TVE + Clock_gate_cim (Clock_gate0, 1, 26, true), // CIM + Clock_gate_i2c2 (Clock_gate0, 1, 25, true), // SMB2 + Clock_gate_uhc (Clock_gate0, 1, 24, true), // UHC + Clock_gate_mac (Clock_gate0, 1, 23, true), // MAC + Clock_gate_gps (Clock_gate0, 1, 22, true), // GPS + Clock_gate_dma (Clock_gate0, 1, 21, true), // PDMA + Clock_gate_ssi2 (Clock_gate0, 1, 20, true), // SSI2 + Clock_gate_ssi1 (Clock_gate0, 1, 19, true), // SSI1 + Clock_gate_uart3 (Clock_gate0, 1, 18, true), // UART3 + Clock_gate_uart2 (Clock_gate0, 1, 17, true), // UART2 + Clock_gate_uart1 (Clock_gate0, 1, 16, true), // UART1 + Clock_gate_uart0 (Clock_gate0, 1, 15, true), // UART0 + Clock_gate_sadc (Clock_gate0, 1, 14, true), // SADC + Clock_gate_kbc (Clock_gate0, 1, 13, true), // KBC + Clock_gate_msc2 (Clock_gate0, 1, 12, true), // MSC2 + Clock_gate_msc1 (Clock_gate0, 1, 11, true), // MSC1 + Clock_gate_owi (Clock_gate0, 1, 10, true), // OWI + Clock_gate_tssi0 (Clock_gate0, 1, 9, true), // TSSI0 + Clock_gate_aic0 (Clock_gate0, 1, 8, true), // AIC0 + Clock_gate_scc (Clock_gate0, 1, 7, true), // SCC + Clock_gate_i2c1 (Clock_gate0, 1, 6, true), // SMB1 + Clock_gate_i2c0 (Clock_gate0, 1, 5, true), // SMB0 + Clock_gate_ssi0 (Clock_gate0, 1, 4, true), // SSI0 + Clock_gate_msc0 (Clock_gate0, 1, 3, true), // MSC0 + Clock_gate_otg0 (Clock_gate0, 1, 2, true), // OTG0 + Clock_gate_bch (Clock_gate0, 1, 1, true), // BCH + Clock_gate_nemc (Clock_gate0, 1, 0, true), // NEMC + Clock_gate_p1 (Clock_gate1, 1, 15, true), // P1 + Clock_gate_x2d (Clock_gate1, 1, 14, true), // X2D + Clock_gate_des (Clock_gate1, 1, 13, true), // DES + Clock_gate_i2c4 (Clock_gate1, 1, 12, true), // SMB4 + Clock_gate_ahb_mon (Clock_gate1, 1, 11, true), // AHB_MON + Clock_gate_uart4 (Clock_gate1, 1, 10, true), // UART4 + Clock_gate_hdmi (Clock_gate1, 1, 9, true), // HDMI + Clock_gate_otg1 (Clock_gate1, 1, 8, true), // OTG1 + Clock_gate_gpvlc (Clock_gate1, 1, 7, true), // GPVLC + Clock_gate_aic1 (Clock_gate1, 1, 6, true), // AIC1 + Clock_gate_compress (Clock_gate1, 1, 5, true), // COMPRESS + Clock_gate_gpu (Clock_gate1, 1, 4, true), // GPU + Clock_gate_pcm (Clock_gate1, 1, 3, true), // PCM + Clock_gate_vpu (Clock_gate1, 1, 2, true), // VPU + Clock_gate_tssi1 (Clock_gate1, 1, 1, true), // TSSI1 + Clock_gate_i2c3 (Clock_gate1, 1, 0, true), // I2C3 -void -Cpm_jz4780_chip::set_field(uint32_t reg, uint32_t mask, uint8_t shift, uint32_t value) -{ - _regs[reg] = (_regs[reg] & (~(mask << shift))) | ((mask & value) << shift); -} + Pll_enable_A (Pll_control_A, 1, 0), // APLLEN + Pll_enable_E (Pll_control_E, 1, 0), // EPLLEN + Pll_enable_M (Pll_control_M, 1, 0), // MPLLEN + Pll_enable_V (Pll_control_V, 1, 0), // VPLLEN -// General clock divider access. + Pll_stable_A (Pll_control_A, 1, 4), // APLL_ON + Pll_stable_E (Pll_control_E, 1, 4), // EPLL_ON + Pll_stable_M (Pll_control_M, 1, 4), // MPLL_ON + Pll_stable_V (Pll_control_V, 1, 4), // VPLL_ON + + Pll_bypass_A (Pll_control_A, 1, 1), // APLL_BP + Pll_bypass_E (Pll_control_E, 1, 1), // EPLL_BP + Pll_bypass_M (Pll_control_M, 1, 1), // MPLL_BP + Pll_bypass_V (Pll_control_V, 1, 1), // VPLL_BP -uint8_t -Cpm_jz4780_chip::_get_divider(uint32_t reg, uint32_t mask, uint8_t shift) -{ - uint8_t d = get_field(reg, mask, shift); + Pll_multiplier_A (Pll_control_A, 0x1fff, 19), // APLLM + Pll_multiplier_E (Pll_control_E, 0x1fff, 19), // EPLLM + Pll_multiplier_M (Pll_control_M, 0x1fff, 19), // MPLLM + Pll_multiplier_V (Pll_control_V, 0x1fff, 19), // VPLLM - // NOTE: Value 15 stops the clock, 14 presumably resumes the clock. + Pll_input_division_A (Pll_control_A, 0x3f, 13), // APLLN + Pll_input_division_E (Pll_control_E, 0x3f, 13), // EPLLN + Pll_input_division_M (Pll_control_M, 0x3f, 13), // MPLLN + Pll_input_division_V (Pll_control_V, 0x3f, 13), // VPLLN - return (d < 14) ? d + 1 : 1; -} + Pll_output_division_A (Pll_control_A, 0x0f, 9), // APLLOD + Pll_output_division_E (Pll_control_E, 0x0f, 9), // EPLLOD + Pll_output_division_M (Pll_control_M, 0x0f, 9), // MPLLOD + Pll_output_division_V (Pll_control_V, 0x0f, 9); // VPLLOD -// PLL control. - -// Return whether the PLL is stable. +// Multiplexer instances. -int -Cpm_jz4780_chip::have_pll(uint32_t pll_reg) -{ - return _regs[pll_reg] & (1 << Pll_stable); -} +#define Clocks(...) ((enum Clock_identifiers []) {__VA_ARGS__}) -int -Cpm_jz4780_chip::pll_enabled(uint32_t pll_reg) -{ - return _regs[pll_reg] & (1 << Pll_enabled); -} +static Mux mux_external (Clock_external), -int -Cpm_jz4780_chip::pll_bypassed(uint32_t pll_reg) -{ - return _regs[pll_reg] & (1 << Pll_bypassed); -} + // Clocks being propagated to others. -void -Cpm_jz4780_chip::pll_enable(uint32_t pll_reg) -{ - _regs[pll_reg] = _regs[pll_reg] | (1 << Pll_enabled); - while (!(_regs[pll_reg] & (1 << Pll_stable))); -} - -void -Cpm_jz4780_chip::pll_disable(uint32_t pll_reg) -{ - _regs[pll_reg] = _regs[pll_reg] & ~(1 << Pll_enabled); - while (_regs[pll_reg] & (1 << Pll_stable)); -} + mux_clock_ssi (Clock_ssi), + mux_clock_msc (Clock_msc), + mux_hclock2 (Clock_hclock2), + mux_hclock2_pclock (Clock_hclock2_pclock), + mux_pclock (Clock_pclock), -// Feedback (13-bit) multiplier. - -uint16_t -Cpm_jz4780_chip::get_multiplier(uint32_t pll_reg) -{ - return get_field(pll_reg, 0x1fff, Pll_multiplier) + 1; -} - -void -Cpm_jz4780_chip::set_multiplier(uint32_t pll_reg, uint16_t multiplier) -{ - set_field(pll_reg, 0x1fff, Pll_multiplier, multiplier - 1); -} - -// Input (6-bit) divider. + // Main bus and peripheral clock sources. -uint8_t -Cpm_jz4780_chip::get_input_division(uint32_t pll_reg) -{ - return get_field(pll_reg, 0x3f, Pll_input_division) + 1; -} - -void -Cpm_jz4780_chip::set_input_division(uint32_t pll_reg, uint8_t divider) -{ - set_field(pll_reg, 0x3f, Pll_input_division, divider - 1); -} + mux_ahb2 (4, Clocks(Clock_none, Clock_main, Clock_pll_M, Clock_rtc)), + mux_core (4, Clocks(Clock_none, Clock_main, Clock_pll_M, Clock_pll_E)), + mux_main (4, Clocks(Clock_none, Clock_pll_A, Clock_external, Clock_rtc)), -// Output divider. - -uint8_t -Cpm_jz4780_chip::get_output_division(uint32_t pll_reg) -{ - uint8_t d = get_field(pll_reg, 0x0f, Pll_output_division); - - // Zero yields a division of one. Otherwise enforce even results. - - return d == 0 ? 1 : (d + 1) & 0x0e; -} + // Memory and device clock sources. -void -Cpm_jz4780_chip::set_output_division(uint32_t pll_reg, uint8_t divider) -{ - uint8_t d = divider <= 1 ? 0 : (divider & 0x0e) - 1; - - set_field(pll_reg, 0x0f, Pll_output_division, d); -} - -uint32_t -Cpm_jz4780_chip::get_pll_frequency(uint32_t pll_reg) -{ - // Test for PLL enable and not PLL bypass. + mux_cim (2, Clocks(Clock_main, Clock_pll_M)), + mux_dev (3, Clocks(Clock_none, Clock_main, Clock_pll_M)), + mux_lcd (3, Clocks(Clock_main, Clock_pll_M, Clock_pll_V)), + mux_usb (3, Clocks(Clock_main, Clock_pll_M, Clock_pll_E /* , OTG PHY */)), - if (pll_enabled(pll_reg) && !pll_bypassed(pll_reg)) - return (_exclk_freq * get_multiplier(pll_reg)) / - (get_input_division(pll_reg) * get_output_division(pll_reg)); - else - return _exclk_freq; -} + // Clock selectors involving the external clock. -void -Cpm_jz4780_chip::set_pll_parameters(uint32_t pll_reg, uint16_t multiplier, uint8_t in_divider, uint8_t out_divider) -{ - set_multiplier(pll_reg, multiplier); - set_input_division(pll_reg, in_divider); - set_output_division(pll_reg, out_divider); - - if (pll_enabled(pll_reg) && !pll_bypassed(pll_reg)) - while (!have_pll(pll_reg)); -} + mux_i2s (4, Clocks(Clock_external, Clock_external, Clock_main, Clock_pll_E)), + mux_pcm (8, Clocks(Clock_external, Clock_external, Clock_external, Clock_external, + Clock_main, Clock_pll_M, Clock_pll_E, Clock_pll_V)), + mux_ssi (4, Clocks(Clock_external, Clock_external, Clock_main, Clock_pll_M)); -// CPU clock (CCLK) divider. - -uint8_t -Cpm_jz4780_chip::get_cpu_divider() -{ - return _get_divider(Clock_control, 0xf, Clock_cpu_divider); -} - -// Fast peripheral clock (H0CLK) divider. - -uint8_t -Cpm_jz4780_chip::get_hclock0_divider() -{ - return _get_divider(Clock_control, 0xf, Clock_hclock0_divider); -} - -// Fast peripheral clock (H2CLK) divider. - -uint8_t -Cpm_jz4780_chip::get_hclock2_divider() -{ - return _get_divider(Clock_control, 0xf, Clock_hclock2_divider); -} - -// Slow peripheral clock (PCLK) divider. - -uint8_t -Cpm_jz4780_chip::get_pclock_divider() -{ - return _get_divider(Clock_control, 0xf, Clock_pclock_divider); -} - -// HDMI clock divider. - -uint8_t -Cpm_jz4780_chip::get_hdmi_divider() -{ - return get_field(Hdmi_divider, 0xff, Hdmi_divider_value) + 1; -} - -// LCD clock (LPCLK) divider for LCD0 or LCD1 pixel clock. - -uint8_t -Cpm_jz4780_chip::get_lcd_pixel_divider(uint8_t controller) -{ - return get_field(controller ? Lcd_divider1 : Lcd_divider0, 0xff, Lcd_divider_value) + 1; -} - -// Memory clock (DDR_CLK) divider. +// Clock instances. -uint8_t -Cpm_jz4780_chip::get_memory_divider() -{ - return _get_divider(Ddr_divider, 0xf, Ddr_divider_value); -} - -// HDMI clock divider. - -void -Cpm_jz4780_chip::set_hdmi_divider(uint16_t division) -{ - if ((division < 1) || (division > 256)) - return; - - // Enable change. - - _regs[Hdmi_divider] = _regs[Hdmi_divider] | Hdmi_change_enable; - - // Set the divider. - - set_field(Hdmi_divider, 0xff, Hdmi_divider_value, division - 1); - - // Restart clock and disable change. +static Clock_null clock_none; - while (_regs[Hdmi_divider] & Hdmi_change_busy); - _regs[Hdmi_divider] = _regs[Hdmi_divider] & ~Hdmi_change_enable; -} - -// LCD pixel clock divider. -// NOTE: This only supports the first LCD peripheral. - -void -Cpm_jz4780_chip::set_lcd_pixel_divider(uint8_t controller, uint16_t division) -{ - uint32_t divider = controller ? Lcd_divider1 : Lcd_divider0; - - if ((division < 1) || (division > 256)) - return; - - // Enable change. - - _regs[divider] = _regs[divider] | Lcd_change_enable; - - // Set the divider. - - set_field(divider, 0xff, Lcd_divider_value, division - 1); - - // Restart clock and disable change. - - while (_regs[divider] & Lcd_change_busy); - _regs[divider] = _regs[divider] & ~Lcd_change_enable; -} +static Clock_passive clock_external(48000000), clock_rtc(32768); -// Clock sources. +// Note the use of extra parentheses due to the annoying C++ "most vexing parse" +// problem. See: https://en.wikipedia.org/wiki/Most_vexing_parse -uint8_t -Cpm_jz4780_chip::get_memory_source() -{ - return get_field(Ddr_divider, 0x3, Clock_source_ddr); -} +static Clock clock_ahb_mon((Source(mux_external)), (Control(Clock_gate_ahb_mon))), + + clock_compress((Source(mux_external)), (Control(Clock_gate_compress))), -uint32_t -Cpm_jz4780_chip::get_memory_source_frequency() -{ - switch (get_memory_source()) - { - case Source_mux_main: - return get_main_frequency(); - case Source_mux_pll_M: - return get_pll_frequency(Pll_control_M); - default: - return 0; - } -} + clock_des((Source(mux_external)), (Control(Clock_gate_des))), + + clock_dma((Source(mux_external)), (Control(Clock_gate_dma))), + + clock_gps((Source(mux_external)), (Control(Clock_gate_gps))), + + clock_gpvlc((Source(mux_external)), (Control(Clock_gate_gpvlc))), + + clock_i2c0((Source(mux_pclock)), (Control(Clock_gate_i2c0))), -uint8_t -Cpm_jz4780_chip::get_cpu_source() -{ - return get_field(Clock_control, 0x3, Clock_source_cpu); -} + clock_i2c1((Source(mux_pclock)), (Control(Clock_gate_i2c1))), + + clock_i2c2((Source(mux_pclock)), (Control(Clock_gate_i2c2))), + + clock_i2c3((Source(mux_pclock)), (Control(Clock_gate_i2c3))), + + clock_i2c4((Source(mux_pclock)), (Control(Clock_gate_i2c4))), -uint32_t -Cpm_jz4780_chip::get_cpu_source_frequency() -{ - switch (get_cpu_source()) - { - case Source_mux_main: - return get_main_frequency(); - case Source_mux_pll_M: - return get_pll_frequency(Pll_control_M); - case Source_mux_pll_E: - return get_pll_frequency(Pll_control_E); - default: - return 0; - } -} + clock_i2s0(Source(mux_i2s, Clock_source_i2s0), Control(Clock_gate_aic0)), + + clock_i2s1(Source(mux_i2s, Clock_source_i2s1), Control(Clock_gate_aic1)), + + clock_ipu((Source(mux_external)), (Control(Clock_gate_ipu))), + + clock_kbc((Source(mux_external)), (Control(Clock_gate_kbc))), + + clock_lcd((Source(mux_external)), (Control(Clock_gate_lcd))), -uint8_t -Cpm_jz4780_chip::get_hclock0_source() -{ - return get_field(Clock_control, 0x3, Clock_source_hclock0); -} + clock_main(Source(mux_main, Clock_source_main), Control(Clock_gate_main)), + + clock_mac((Source(mux_external)), (Control(Clock_gate_mac))), + + clock_msc((Source(mux_dev, Clock_source_msc))), + + clock_nemc((Source(mux_hclock2)), (Control(Clock_gate_nemc))), -uint32_t -Cpm_jz4780_chip::get_hclock0_source_frequency() -{ - switch (get_hclock0_source()) - { - case Source_mux_main: - return get_main_frequency(); - case Source_mux_pll_M: - return get_pll_frequency(Pll_control_M); - case Source_mux_pll_E: - return get_pll_frequency(Pll_control_E); - default: - return 0; - } -} + clock_otg0((Source(mux_external)), (Control(Clock_gate_otg0))), + + clock_otg1((Source(mux_external)), (Control(Clock_gate_otg1))), + + clock_owi((Source(mux_external)), (Control(Clock_gate_owi))), + + clock_sadc((Source(mux_external)), (Control(Clock_gate_sadc))), + + clock_scc((Source(mux_external)), (Control(Clock_gate_scc))), -uint8_t -Cpm_jz4780_chip::get_hclock2_source() -{ - return get_field(Clock_control, 0x3, Clock_source_hclock2); -} + clock_tssi0((Source(mux_external)), (Control(Clock_gate_tssi0))), + + clock_tssi1((Source(mux_external)), (Control(Clock_gate_tssi1))), + + clock_uart0((Source(mux_external)), (Control(Clock_gate_uart0))), + + clock_uart1((Source(mux_external)), (Control(Clock_gate_uart1))), + + clock_uart2((Source(mux_external)), (Control(Clock_gate_uart2))), -uint32_t -Cpm_jz4780_chip::get_hclock2_source_frequency() -{ - switch (get_hclock2_source()) - { - case Source_mux_main: - return get_main_frequency(); - case Source_mux_pll_M: - return get_pll_frequency(Pll_control_M); - case Source_mux_realtime: - return _rtclk_freq; // "TCK" in the manual, RTCLK in Linux driver code - default: - return 0; - } -} + clock_uart3((Source(mux_external)), (Control(Clock_gate_uart3))), + + clock_x2d((Source(mux_external)), (Control(Clock_gate_x2d))), -void -Cpm_jz4780_chip::set_hclock2_source(uint8_t source) -{ - set_field(Clock_control, 0x3, Clock_source_hclock2, source); -} + // Special parent clock for hclock2 and pclock. + + clock_hclock2_pclock(Source(mux_ahb2, Clock_source_hclock2)), + + // SSI channel clocks depending on a common parent divider. -uint8_t -Cpm_jz4780_chip::get_hdmi_source() -{ - return get_field(Hdmi_divider, 0x3, Clock_source_hdmi); -} + clock_ssi0((Source(mux_clock_ssi)), Control(Clock_gate_ssi0)), + + clock_ssi1((Source(mux_clock_ssi)), Control(Clock_gate_ssi1)), + + clock_ssi2((Source(mux_clock_ssi)), Control(Clock_gate_ssi2)); -uint32_t -Cpm_jz4780_chip::get_hdmi_source_frequency() -{ - switch (get_hdmi_source()) - { - case Source_main: - return get_main_frequency(); - case Source_pll_M: - return get_pll_frequency(Pll_control_M); - case Source_pll_V: - return get_pll_frequency(Pll_control_V); - default: - return 0; - } -} +static Clock_divided + clock_bch(Source(mux_core, Clock_source_bch), + Control(Clock_gate_bch, Clock_change_enable_bch, Clock_busy_bch), + Divider(Clock_divider_bch)), + + clock_cim(Source(mux_cim, Clock_source_cim), + Control(Clock_gate_cim, Clock_change_enable_cim, Clock_busy_cim), + Divider(Clock_divider_cim)), -void -Cpm_jz4780_chip::set_hdmi_source(uint8_t source) -{ - // Stop clock and enable change. + clock_cpu(Source(mux_core, Clock_source_cpu), + Control(Field::undefined, Clock_change_enable_cpu, Clock_busy_cpu), + Divider(Clock_divider_cpu)), - _regs[Hdmi_divider] = _regs[Hdmi_divider] | Hdmi_change_enable | Hdmi_clock_stop; - - // Set the source. - - set_field(Hdmi_divider, 0x03, Clock_source_hdmi, source); + clock_ddr(Source(mux_dev, Clock_source_ddr), + Control(Clock_gate_ddr, Clock_change_enable_ddr, Clock_busy_ddr), + Divider(Clock_divider_ddr)), - // Restart clock and disable change. - - while (_regs[Hdmi_divider] & Hdmi_change_busy); - _regs[Hdmi_divider] = _regs[Hdmi_divider] & ~(Hdmi_change_enable | Hdmi_clock_stop); -} + clock_gpu(Source(mux_core, Clock_source_gpu), + Control(Clock_gate_gpu, Clock_change_enable_gpu, Clock_busy_gpu), + Divider(Clock_divider_gpu)), -uint8_t -Cpm_jz4780_chip::get_lcd_source(uint8_t controller) -{ - return get_field(controller ? Lcd_divider1 : Lcd_divider0, 0x3, Clock_source_lcd); -} + clock_hclock0(Source(mux_core, Clock_source_hclock0), + Control(Field::undefined, Clock_change_enable_ahb0), + Divider(Clock_divider_hclock0)), + + clock_hclock2(Source(mux_hclock2_pclock), + Control(Field::undefined, Clock_change_enable_ahb2), + Divider(Clock_divider_hclock2)), -uint32_t -Cpm_jz4780_chip::get_lcd_source_frequency(uint8_t controller) -{ - switch (get_lcd_source(controller)) - { - case Source_main: - return get_main_frequency(); - case Source_pll_M: - return get_pll_frequency(Pll_control_M); - case Source_pll_V: - return get_pll_frequency(Pll_control_V); - default: - return 0; - } -} + clock_hdmi(Source(mux_lcd, Clock_source_hdmi), + Control(Clock_gate_hdmi, Clock_change_enable_hdmi, Clock_busy_hdmi), + Divider(Clock_divider_hdmi)), + + clock_lcd_pixel0(Source(mux_lcd, Clock_source_lcd0), + Control(Clock_gate_lcd, Clock_change_enable_lcd0, Clock_busy_lcd0), + Divider(Clock_divider_lcd0)), -void -Cpm_jz4780_chip::set_lcd_source(uint8_t controller, uint8_t source) -{ - uint32_t divider = controller ? Lcd_divider1 : Lcd_divider0; + clock_lcd_pixel1(Source(mux_lcd, Clock_source_lcd1), + Control(Clock_gate_lcd, Clock_change_enable_lcd1, Clock_busy_lcd1), + Divider(Clock_divider_lcd1)), - // Stop clock and enable change. + clock_msc0(Source(mux_clock_msc), + Control(Clock_gate_msc0, Clock_change_enable_msc0, Clock_busy_msc0), + Divider(Clock_divider_msc0)), - _regs[divider] = _regs[divider] | Lcd_change_enable | Lcd_clock_stop; + clock_msc1(Source(mux_clock_msc), + Control(Clock_gate_msc1, Clock_change_enable_msc1, Clock_busy_msc1), + Divider(Clock_divider_msc1)), - // Set the source. - - set_field(divider, 0x03, Clock_source_lcd, source); + clock_msc2(Source(mux_clock_msc), + Control(Clock_gate_msc2, Clock_change_enable_msc2, Clock_busy_msc2), + Divider(Clock_divider_msc2)), - // Restart clock and disable change. - - while (_regs[divider] & Lcd_change_busy); - _regs[divider] = _regs[divider] & ~(Lcd_change_enable | Lcd_clock_stop); -} + clock_pcm(Source(mux_pcm, Clock_source_pcm), + Control(Clock_gate_pcm, Clock_change_enable_pcm, Clock_busy_pcm), + Divider(Clock_divider_pcm)), -uint8_t -Cpm_jz4780_chip::get_pclock_source() -{ - return get_hclock2_source(); -} + clock_pclock(Source(mux_hclock2_pclock), + Control(Field::undefined, Clock_change_enable_ahb2), + Divider(Clock_divider_pclock)), -uint32_t -Cpm_jz4780_chip::get_pclock_source_frequency() -{ - return get_hclock2_source_frequency(); -} + clock_ssi(Source(mux_ssi, Clock_source_ssi), + Control(Field::undefined, Clock_change_enable_ssi, Clock_busy_ssi), + Divider(Clock_divider_ssi)), -void -Cpm_jz4780_chip::set_pclock_source(uint8_t source) -{ - set_hclock2_source(source); -} + clock_uhc(Source(mux_usb, Clock_source_uhc), + Control(Clock_gate_uhc, Clock_change_enable_uhc, Clock_busy_uhc), + Divider(Clock_divider_uhc)); -// Source frequency, used by various clock sources. - -uint8_t -Cpm_jz4780_chip::get_main_source() -{ - return get_field(Clock_control, 0x3, Clock_source_main); -} +const double jz4780_pll_intermediate_min = 300000000, + jz4780_pll_intermediate_max = 1500000000; -uint32_t -Cpm_jz4780_chip::get_main_frequency() -{ - switch (get_main_source()) - { - case Source_pll_A: - return get_pll_frequency(Pll_control_A); - case Source_external: - return _exclk_freq; - case Source_realtime: - return _rtclk_freq; - default: - return 0; - } -} - -// Clock frequency for the CPU. - -uint32_t -Cpm_jz4780_chip::get_cpu_frequency() -{ - return get_cpu_source_frequency() / get_cpu_divider(); -} - -// Clock frequency for fast peripherals. - -uint32_t -Cpm_jz4780_chip::get_hclock0_frequency() -{ - return get_hclock0_source_frequency() / get_hclock0_divider(); -} - -// Clock frequency for fast peripherals. +static Pll clock_pll_A(Source(mux_external), + Control_pll(Pll_enable_A, Pll_stable_A, Pll_bypass_A), + Divider_pll(Pll_multiplier_A, Pll_input_division_A, + Pll_output_division_A, + jz4780_pll_intermediate_min, jz4780_pll_intermediate_max)), -uint32_t -Cpm_jz4780_chip::get_hclock2_frequency() -{ - return get_hclock2_source_frequency() / get_hclock2_divider(); -} - -// Clock frequency for slow peripherals. - -uint32_t -Cpm_jz4780_chip::get_pclock_frequency() -{ - return get_pclock_source_frequency() / get_pclock_divider(); -} - -// Clock frequency for the memory. - -uint32_t -Cpm_jz4780_chip::get_memory_frequency() -{ - return get_memory_source_frequency() / get_memory_divider(); -} + clock_pll_E(Source(mux_external), + Control_pll(Pll_enable_E, Pll_stable_E, Pll_bypass_E), + Divider_pll(Pll_multiplier_E, Pll_input_division_E, + Pll_output_division_E, + jz4780_pll_intermediate_min, jz4780_pll_intermediate_max)), -uint32_t -Cpm_jz4780_chip::get_apll_frequency() -{ - return get_pll_frequency(Pll_control_A); -} - -uint32_t -Cpm_jz4780_chip::get_epll_frequency() -{ - return get_pll_frequency(Pll_control_E); -} + clock_pll_M(Source(mux_external), + Control_pll(Pll_enable_M, Pll_stable_M, Pll_bypass_M), + Divider_pll(Pll_multiplier_M, Pll_input_division_M, + Pll_output_division_M, + jz4780_pll_intermediate_min, jz4780_pll_intermediate_max)), -uint32_t -Cpm_jz4780_chip::get_mpll_frequency() -{ - return get_pll_frequency(Pll_control_M); -} - -uint32_t -Cpm_jz4780_chip::get_vpll_frequency() -{ - return get_pll_frequency(Pll_control_V); -} + clock_pll_V(Source(mux_external), + Control_pll(Pll_enable_V, Pll_stable_V, Pll_bypass_V), + Divider_pll(Pll_multiplier_V, Pll_input_division_V, + Pll_output_division_V, + jz4780_pll_intermediate_min, jz4780_pll_intermediate_max)); -uint32_t -Cpm_jz4780_chip::get_frequency(enum Clock_identifiers clock) -{ - switch (clock) - { - // NOTE: Returning only the frequency for controller 0. - - case Clock_lcd_pixel: - return get_lcd_source_frequency(0) / get_lcd_pixel_divider(0); - - case Clock_hdmi: - return get_hdmi_source_frequency() / get_hdmi_divider(); - - // NOTE: Consider a better error result. - - default: - return 0; - } -} - -void -Cpm_jz4780_chip::set_frequency(enum Clock_identifiers clock, uint32_t frequency) -{ - switch (clock) - { - // NOTE: HCLK/AHB0 must be 1.5 (for TFT) or 3 (for STN) times the pixel clock. - // NOTE: Here, the actual frequency value is ignored, but should at least be - // NOTE: tested. +// Clock register. - case Clock_lcd: - set_lcd_source(0, Source_pll_V); - set_lcd_source(1, Source_pll_V); - pll_enable(Pll_control_V); - break; - - // Unlike the JZ4740, HCLK/AHB0 is used as the device frequency, with the pixel - // frequency being based on the selected clock source (SCLK_A, MPLL or VPLL). - - case Clock_lcd_pixel: - - // Switch to the video PLL and attempt to set the divider. +static Clock_base *clocks[Clock_identifier_count] = { + &clock_none, // Clock_aic + &clock_none, // Clock_aic_bitclk + &clock_none, // Clock_aic_pclk + &clock_none, // Clock_can0 + &clock_none, // Clock_can1 + &clock_none, // Clock_cdbus + &clock_cim, + &clock_cpu, + &clock_ddr, + &clock_dma, + &clock_none, // Clock_emac + &clock_external, + &clock_hclock0, + &clock_hclock2, + &clock_hclock2_pclock, + &clock_hdmi, + &clock_i2c0, + &clock_i2c1, + &clock_i2c2, + &clock_i2c3, + &clock_i2c4, + &clock_i2s0, + &clock_none, // Clock_i2s0_rx + &clock_none, // Clock_i2s0_tx + &clock_i2s1, + &clock_none, // Clock_i2s1_rx + &clock_none, // Clock_i2s1_tx + &clock_none, // Clock_kbc + &clock_lcd, + &clock_lcd_pixel0, + &clock_lcd_pixel1, + &clock_mac, + &clock_main, + &clock_none, // Clock_mipi_csi + &clock_msc, + &clock_msc0, + &clock_msc1, + &clock_msc2, + &clock_none, // Clock_none + &clock_otg0, + &clock_otg1, + &clock_pclock, + &clock_pll_A, + &clock_pll_E, + &clock_pll_M, + &clock_pll_V, + &clock_none, // Clock_pwm0 + &clock_none, // Clock_pwm1 + &clock_rtc, + &clock_scc, + &clock_none, // Clock_sfc + &clock_ssi, + &clock_ssi0, + &clock_ssi1, + &clock_ssi2, + &clock_none, // Clock_timer + &clock_uart0, + &clock_uart1, + &clock_uart2, + &clock_uart3, + &clock_none, // Clock_udc + &clock_uhc, + &clock_none, // Clock_uprt +}; - set_lcd_pixel_divider(0, get_lcd_source_frequency() / frequency); - set_lcd_pixel_divider(1, get_lcd_source_frequency() / frequency); - break; + - case Clock_hdmi: - - // Switch to the video PLL and attempt to set the divider. +// Peripheral abstraction. - set_hdmi_source(Source_pll_V); - pll_enable(Pll_control_V); - set_hdmi_divider(get_hdmi_source_frequency() / frequency); - break; - - default: - break; - } +Cpm_jz4780_chip::Cpm_jz4780_chip(l4_addr_t addr) +: Cpm_chip(addr, clocks) +{ } @@ -809,10 +543,7 @@ void *jz4780_cpm_init(l4_addr_t cpm_base) { - /* Initialise the clock and power management peripheral with the - register memory region and a 48MHz EXCLK frequency. */ - - return (void *) new Cpm_jz4780_chip(cpm_base, 48000000, 32768); + return (void *) new Cpm_jz4780_chip(cpm_base); } int @@ -833,216 +564,56 @@ static_cast(cpm)->stop_clock(clock); } - - -uint8_t -jz4780_cpm_get_cpu_divider(void *cpm) -{ - return static_cast(cpm)->get_cpu_divider(); -} - -uint8_t -jz4780_cpm_get_hclock0_divider(void *cpm) -{ - return static_cast(cpm)->get_hclock0_divider(); +int +jz4780_cpm_get_parameters(void *cpm, enum Clock_identifiers clock, uint32_t parameters[]) +{ + return static_cast(cpm)->get_parameters(clock, parameters); } -uint8_t -jz4780_cpm_get_hclock2_divider(void *cpm) -{ - return static_cast(cpm)->get_hclock2_divider(); -} - -uint8_t -jz4780_cpm_get_hdmi_divider(void *cpm) -{ - return static_cast(cpm)->get_hdmi_divider(); -} - -uint8_t -jz4780_cpm_get_lcd_pixel_divider(void *cpm) -{ - return static_cast(cpm)->get_lcd_pixel_divider(); -} - -uint8_t -jz4780_cpm_get_memory_divider(void *cpm) -{ - return static_cast(cpm)->get_memory_divider(); +int +jz4780_cpm_set_parameters(void *cpm, enum Clock_identifiers clock, int num_parameters, uint32_t parameters[]) +{ + return static_cast(cpm)->set_parameters(clock, num_parameters, parameters); } uint8_t -jz4780_cpm_get_pclock_divider(void *cpm) -{ - return static_cast(cpm)->get_pclock_divider(); -} - - - -uint8_t -jz4780_cpm_get_hclock0_source(void *cpm) -{ - return static_cast(cpm)->get_hclock0_source(); -} - -uint8_t -jz4780_cpm_get_hclock2_source(void *cpm) -{ - return static_cast(cpm)->get_hclock2_source(); -} - -uint8_t -jz4780_cpm_get_hdmi_source(void *cpm) -{ - return static_cast(cpm)->get_hdmi_source(); -} - -uint8_t -jz4780_cpm_get_lcd_source(void *cpm) -{ - return static_cast(cpm)->get_lcd_source(); -} - -uint8_t -jz4780_cpm_get_memory_source(void *cpm) -{ - return static_cast(cpm)->get_memory_source(); -} - -uint8_t -jz4780_cpm_get_pclock_source(void *cpm) -{ - return static_cast(cpm)->get_pclock_source(); +jz4780_cpm_get_source(void *cpm, enum Clock_identifiers clock) +{ + return static_cast(cpm)->get_source(clock); } void -jz4780_cpm_set_pclock_source(void *cpm, uint8_t source) -{ - static_cast(cpm)->set_pclock_source(source); +jz4780_cpm_set_source(void *cpm, enum Clock_identifiers clock, uint8_t source) +{ + static_cast(cpm)->set_source(clock, source); } - - -uint32_t -jz4780_cpm_get_hclock0_source_frequency(void *cpm) -{ - return static_cast(cpm)->get_hclock0_source_frequency(); +enum Clock_identifiers +jz4780_cpm_get_source_clock(void *cpm, enum Clock_identifiers clock) +{ + return static_cast(cpm)->get_source_clock(clock); } -uint32_t -jz4780_cpm_get_hclock2_source_frequency(void *cpm) -{ - return static_cast(cpm)->get_hclock2_source_frequency(); +void +jz4780_cpm_set_source_clock(void *cpm, enum Clock_identifiers clock, enum Clock_identifiers source) +{ + static_cast(cpm)->set_source_clock(clock, source); } uint32_t -jz4780_cpm_get_hdmi_source_frequency(void *cpm) -{ - return static_cast(cpm)->get_hdmi_source_frequency(); -} - -uint32_t -jz4780_cpm_get_lcd_source_frequency(void *cpm) -{ - return static_cast(cpm)->get_lcd_source_frequency(); -} - -uint32_t -jz4780_cpm_get_memory_source_frequency(void *cpm) -{ - return static_cast(cpm)->get_memory_source_frequency(); -} - -uint32_t -jz4780_cpm_get_pclock_source_frequency(void *cpm) -{ - return static_cast(cpm)->get_pclock_source_frequency(); -} - - - -uint8_t -jz4780_cpm_get_main_source(void *cpm) -{ - return static_cast(cpm)->get_main_source(); -} - -uint32_t -jz4780_cpm_get_main_frequency(void *cpm) -{ - return static_cast(cpm)->get_main_frequency(); -} - -uint32_t -jz4780_cpm_get_cpu_frequency(void *cpm) -{ - return static_cast(cpm)->get_cpu_frequency(); -} - -uint32_t -jz4780_cpm_get_hclock0_frequency(void *cpm) -{ - return static_cast(cpm)->get_hclock0_frequency(); +jz4780_cpm_get_source_frequency(void *cpm, enum Clock_identifiers clock) +{ + return static_cast(cpm)->get_source_frequency(clock); } uint32_t -jz4780_cpm_get_hclock2_frequency(void *cpm) -{ - return static_cast(cpm)->get_hclock2_frequency(); -} - -uint32_t -jz4780_cpm_get_memory_frequency(void *cpm) -{ - return static_cast(cpm)->get_memory_frequency(); -} - -uint32_t -jz4780_cpm_get_pclock_frequency(void *cpm) -{ - return static_cast(cpm)->get_pclock_frequency(); -} - -uint32_t -jz4780_cpm_get_apll_frequency(void *cpm) -{ - return static_cast(cpm)->get_apll_frequency(); -} - -uint32_t -jz4780_cpm_get_epll_frequency(void *cpm) -{ - return static_cast(cpm)->get_epll_frequency(); -} - -uint32_t -jz4780_cpm_get_mpll_frequency(void *cpm) -{ - return static_cast(cpm)->get_mpll_frequency(); -} - -uint32_t -jz4780_cpm_get_vpll_frequency(void *cpm) -{ - return static_cast(cpm)->get_vpll_frequency(); -} - - - -uint32_t jz4780_cpm_get_frequency(void *cpm, enum Clock_identifiers clock) -{ +{ return static_cast(cpm)->get_frequency(clock); } -void +int jz4780_cpm_set_frequency(void *cpm, enum Clock_identifiers clock, uint32_t frequency) { - static_cast(cpm)->set_frequency(clock, frequency); + return static_cast(cpm)->set_frequency(clock, frequency); } - -void -jz4780_cpm_set_mpll_parameters(void *cpm, uint16_t multiplier, uint8_t in_divider, uint8_t out_divider) -{ - static_cast(cpm)->set_pll_parameters(Pll_control_M, multiplier, in_divider, out_divider); -} diff -r 934192f49457 -r 678a57edbba5 pkg/devices/lib/cpm/src/x1600.cc --- a/pkg/devices/lib/cpm/src/x1600.cc Tue Oct 24 18:52:06 2023 +0200 +++ b/pkg/devices/lib/cpm/src/x1600.cc Fri Oct 27 18:02:49 2023 +0200 @@ -23,8 +23,6 @@ #include #include "cpm-x1600.h" -#include -#include @@ -38,6 +36,11 @@ Clock_gate1 = 0x028, // CLKGR1 Sleep_control = 0x024, // OPCR (oscillator and power control) Clock_status = 0x0d4, // CPCSR + + Divider_can0 = 0x0a0, // CAN0CDR + Divider_can1 = 0x0a8, // CAN1CDR + Divider_cdbus = 0x0ac, // CDBUSCDR + Divider_cim = 0x078, // CIMCDR Divider_ddr = 0x02c, // DDRCDR Divider_mac = 0x054, // MACCDR Divider0_i2s0 = 0x060, // I2S0CDR @@ -45,26 +48,26 @@ Divider0_i2s1 = 0x07c, // I2S1CDR (from X2000 manual) Divider1_i2s1 = 0x080, // I2S1CDR1 (from X2000 manual) Divider_lcd = 0x064, // LPCDR + Divider_macphy0 = 0x0e4, // MPHY0C Divider_msc0 = 0x068, // MSC0CDR Divider_msc1 = 0x0a4, // MSC1CDR + Divider_pwm = 0x06c, // PWMCDR Divider_sfc = 0x074, // SFCCDR Divider_ssi = 0x05c, // SSICDR - Divider_cim = 0x078, // CIMCDR - Divider_pwm = 0x06c, // PWMCDR - Divider_can0 = 0x0a0, // CAN0CDR - Divider_can1 = 0x0a8, // CAN1CDR - Divider_cdbus = 0x0ac, // CDBUSCDR - Divider_macphy0 = 0x0e4, // MPHY0C + Cpm_interrupt = 0x0b0, // CPM_INTR Cpm_interrupt_en = 0x0b4, // CPM_INTRE Cpm_swi = 0x0bc, // CPM_SFTINT - Ddr_gate = 0x0d0, // DRCG + Cpm_scratch = 0x034, // CPSPR Cpm_scratch_prot = 0x038, // CPSPPR - Cpm_scratch = 0x034, // CPSPR + + Gate_ddr = 0x0d0, // DRCG + Usb_param_control0 = 0x03c, // USBPCR Usb_reset_detect = 0x040, // USBRDT Usb_vbus_jitter = 0x044, // USBVBFIL Usb_param_control1 = 0x048, // USBPCR1 + Pll_control = 0x00c, // CPPCR Pll_control_A = 0x010, // CPAPCR Pll_control_M = 0x014, // CPMPCR @@ -74,17 +77,6 @@ Pll_fraction_E = 0x08c, // CPEPACR }; -enum Clock_source_values : unsigned -{ - Source_mME_main = 0, - Source_mME_pll_M = 1, - Source_mME_pll_E = 2, - - // Special value - - Source_mask = 0x3, -}; - // Register field definitions. @@ -109,6 +101,8 @@ Clock_source_ssi (Divider_ssi, 3, 30), // SPCS Clock_busy_cpu (Clock_status, 1, 0), + Clock_busy_hclock0 (Clock_status, 1, 1), + Clock_busy_hclock2 (Clock_status, 1, 2), Clock_busy_ddr (Divider_ddr, 1, 28), Clock_busy_mac (Divider_mac, 1, 28), Clock_busy_lcd (Divider_lcd, 1, 28), @@ -140,26 +134,26 @@ Clock_change_enable_can1 (Divider_can1, 1, 29), Clock_change_enable_cdbus (Divider_cdbus, 1, 29), + Clock_divider_cpu (Clock_control, 0x0f, 0), // CDIV + Clock_divider_hclock0 (Clock_control, 0x0f, 8), // H0DIV (fast AHB peripherals) + Clock_divider_hclock2 (Clock_control, 0x0f, 12), // H2DIV (fast AHB peripherals) + Clock_divider_l2cache (Clock_control, 0x0f, 4), // L2CDIV + Clock_divider_pclock (Clock_control, 0x0f, 16), // PDIV (slow APB peripherals) Clock_divider_can0 (Divider_can0, 0xff, 0), // CAN0CDR Clock_divider_can1 (Divider_can1, 0xff, 0), // CAN1CDR Clock_divider_cdbus (Divider_cdbus, 0xff, 0), // CDBUSCDR Clock_divider_cim (Divider_cim, 0xff, 0), // CIMCDR - Clock_divider_cpu (Clock_control, 0x0f, 0), // CDIV Clock_divider_ddr (Divider_ddr, 0x0f, 0), // DDRCDR - Clock_divider_hclock0 (Clock_control, 0x0f, 8), // H0DIV (fast AHB peripherals) - Clock_divider_hclock2 (Clock_control, 0x0f, 12), // H2DIV (fast AHB peripherals) Clock_divider_i2s0_m (Divider0_i2s0, 0x1ff, 20), // I2SDIV_M Clock_divider_i2s0_n (Divider0_i2s0, 0xfffff, 0), // I2SDIV_N Clock_divider_i2s0_d (Divider1_i2s0, 0xfffff, 0), // I2SDIV_D Clock_divider_i2s1_m (Divider0_i2s1, 0x1ff, 20), // I2SDIV_M Clock_divider_i2s1_n (Divider0_i2s1, 0xfffff, 0), // I2SDIV_N Clock_divider_i2s1_d (Divider1_i2s1, 0xfffff, 0), // I2SDIV_D - Clock_divider_l2cache (Clock_control, 0x0f, 4), // L2CDIV Clock_divider_lcd (Divider_lcd, 0xff, 0), // LPCDR Clock_divider_mac (Divider_mac, 0xff, 0), // MACCDR Clock_divider_msc0 (Divider_msc0, 0xff, 0), // MSC0CDR Clock_divider_msc1 (Divider_msc1, 0xff, 0), // MSC1CDR - Clock_divider_pclock (Clock_control, 0x0f, 16), // PDIV (slow APB peripherals) Clock_divider_pwm (Divider_pwm, 0x0f, 0), // PWMCDR Clock_divider_sfc (Divider_sfc, 0xff, 0), // SFCCDR Clock_divider_ssi (Divider_ssi, 0xff, 0), // SSICDR @@ -186,7 +180,7 @@ Clock_gate_uart1 (Clock_gate0, 1, 15, true), // UART1 Clock_gate_uart0 (Clock_gate0, 1, 14, true), // UART0 Clock_gate_sadc (Clock_gate0, 1, 13, true), // SADC - Clock_gate_audio (Clock_gate0, 1, 11, true), // AUDIO + Clock_gate_aic (Clock_gate0, 1, 11, true), // AUDIO Clock_gate_ssi_slv (Clock_gate0, 1, 10, true), // SSI_SLV Clock_gate_i2c1 (Clock_gate0, 1, 8, true), // I2C1 Clock_gate_i2c0 (Clock_gate0, 1, 7, true), // I2C0 @@ -244,16 +238,23 @@ #define Clocks(...) ((enum Clock_identifiers []) {__VA_ARGS__}) static Mux mux_external (Clock_external), - mux_hclock0 (Clock_hclock0), - mux_hclock2 (Clock_hclock2), - mux_pclock (Clock_pclock), - mux_main (3, Clocks(Clock_none, Clock_external, Clock_pll_A)), + + // Clocks being propagated to others. + + mux_hclock0 (Clock_hclock0), + mux_hclock2 (Clock_hclock2), + mux_pclock (Clock_pclock), + mux_hclock2_pclock (Clock_hclock2_pclock), + mux_i2s0_rx (Clock_i2s0), + mux_i2s0_tx (Clock_i2s1), + + // Main peripheral and bus clock sources. + + mux_bus (4, Clocks(Clock_main, Clock_pll_M, Clock_pll_E, Clock_external)), mux_core (3, Clocks(Clock_none, Clock_main, Clock_pll_M)), - mux_bus (4, Clocks(Clock_main, Clock_pll_M, Clock_pll_E, Clock_external)), mux_dev (3, Clocks(Clock_main, Clock_pll_M, Clock_pll_E)), - mux_i2s (2, Clocks(Clock_main, Clock_pll_E)), - mux_i2s0_rx (Clock_i2s0), - mux_i2s0_tx (Clock_i2s1); + mux_main (3, Clocks(Clock_none, Clock_external, Clock_pll_A)), + mux_i2s (2, Clocks(Clock_main, Clock_pll_E)); @@ -261,17 +262,15 @@ static Clock_null clock_none; -static Clock_passive clock_external; +static Clock_passive clock_external(24000000); // Note the use of extra parentheses due to the annoying C++ "most vexing parse" // problem. See: https://en.wikipedia.org/wiki/Most_vexing_parse -static Clock clock_audio((Source(mux_hclock2)), (Control(Clock_gate_audio))), +static Clock clock_aic((Source(mux_hclock2)), (Control(Clock_gate_aic))), clock_dma((Source(mux_hclock2)), (Control(Clock_gate_dma))), - clock_i2c((Source(mux_pclock)), (Control(Clock_gate_i2c0))), - clock_i2c0((Source(mux_pclock)), (Control(Clock_gate_i2c0))), clock_i2c1((Source(mux_pclock)), (Control(Clock_gate_i2c1))), @@ -284,7 +283,7 @@ clock_mipi_csi((Source(mux_hclock0)), Control(Clock_gate_mipi_csi)), - clock_otg((Source(mux_hclock2)), (Control(Clock_gate_otg))), + clock_otg0((Source(mux_hclock2)), (Control(Clock_gate_otg))), clock_timer((Source(mux_pclock)), (Control(Clock_gate_timer))), @@ -294,7 +293,12 @@ clock_uart2((Source(mux_external)), (Control(Clock_gate_uart2))), - clock_uart3((Source(mux_external)), (Control(Clock_gate_uart3))); + clock_uart3((Source(mux_external)), (Control(Clock_gate_uart3))), + + // Special parent clock for hclock2 and pclock. + + clock_hclock2_pclock(Source(mux_core, Clock_source_hclock2), + Control(Clock_gate_apb0, Clock_change_enable_ahb2)); static Clock_divided clock_can0(Source(mux_bus, Clock_source_can0), @@ -325,9 +329,7 @@ Control(Clock_gate_ahb0, Clock_change_enable_ahb0), Divider(Clock_divider_hclock0)), - clock_hclock2(Source(mux_core, Clock_source_hclock2), - Control(Clock_gate_apb0, Clock_change_enable_ahb2), - Divider(Clock_divider_hclock2)), + clock_hclock2((Source(mux_hclock2_pclock)), (Divider(Clock_divider_hclock2))), clock_lcd_pixel(Source(mux_dev, Clock_source_lcd), Control(Clock_gate_lcd_pixel, Clock_change_enable_lcd, Clock_busy_lcd), @@ -337,10 +339,6 @@ Control(Clock_gate_gmac0, Clock_change_enable_mac, Clock_busy_mac), Divider(Clock_divider_mac)), - clock_msc(Source(mux_dev, Clock_source_msc0), - Control(Clock_gate_msc0, Clock_change_enable_msc0, Clock_busy_msc0), - Divider(Clock_divider_msc0)), - clock_msc0(Source(mux_dev, Clock_source_msc0), Control(Clock_gate_msc0, Clock_change_enable_msc0, Clock_busy_msc0), Divider(Clock_divider_msc0)), @@ -349,13 +347,7 @@ Control(Clock_gate_msc1, Clock_change_enable_msc1, Clock_busy_msc1), Divider(Clock_divider_msc1)), - clock_pclock(Source(mux_core, Clock_source_hclock2), - Control(Clock_gate_apb0, Clock_change_enable_ahb2), - Divider(Clock_divider_pclock)), - - clock_pwm(Source(mux_dev, Clock_source_pwm), - Control(Clock_gate_pwm, Clock_change_enable_pwm, Clock_busy_pwm), - Divider(Clock_divider_pwm)), + clock_pclock((Source(mux_hclock2_pclock)), (Divider(Clock_divider_pclock))), clock_pwm0(Source(mux_dev, Clock_source_pwm), Control(Clock_gate_pwm, Clock_change_enable_pwm, Clock_busy_pwm), @@ -365,9 +357,9 @@ Control(Clock_gate_sfc, Clock_change_enable_sfc, Clock_busy_sfc), Divider(Clock_divider_sfc)), - clock_ssi(Source(mux_dev, Clock_source_ssi), - Control(Clock_gate_ssi0, Clock_change_enable_ssi, Clock_busy_ssi), - Divider(Clock_divider_ssi)); + clock_ssi0(Source(mux_dev, Clock_source_ssi), + Control(Clock_gate_ssi0, Clock_change_enable_ssi, Clock_busy_ssi), + Divider(Clock_divider_ssi)); static Clock_divided_i2s clock_i2s0_rx(Source(mux_i2s0_rx), @@ -382,29 +374,35 @@ Clock_divider_i2s1_d, Clock_divider_i2s1_n_auto, Clock_divider_i2s1_d_auto)); +const double x1600_pll_intermediate_min = 600000000, + x1600_pll_intermediate_max = 2400000000; + static Pll clock_pll_A(Source(mux_external), Control_pll(Pll_enable_A, Pll_stable_A, Pll_bypass_A), Divider_pll(Pll_multiplier_A, Pll_input_division_A, - Pll_output_division0_A, Pll_output_division1_A)), + Pll_output_division0_A, Pll_output_division1_A, + x1600_pll_intermediate_min, x1600_pll_intermediate_max)), clock_pll_E(Source(mux_external), Control_pll(Pll_enable_E, Pll_stable_E, Pll_bypass_E), Divider_pll(Pll_multiplier_E, Pll_input_division_E, - Pll_output_division0_E, Pll_output_division1_E)), + Pll_output_division0_E, Pll_output_division1_E, + x1600_pll_intermediate_min, x1600_pll_intermediate_max)), clock_pll_M(Source(mux_external), Control_pll(Pll_enable_M, Pll_stable_M, Pll_bypass_M), Divider_pll(Pll_multiplier_M, Pll_input_division_M, - Pll_output_division0_M, Pll_output_division1_M)); + Pll_output_division0_M, Pll_output_division1_M, + x1600_pll_intermediate_min, x1600_pll_intermediate_max)); // Clock register. static Clock_base *clocks[Clock_identifier_count] = { - &clock_audio, - &clock_none, // Clock_aic_bitclk - &clock_none, // Clock_aic_pclk + &clock_aic, + &clock_none, // Clock_aic_bitclk + &clock_none, // Clock_aic_pclk &clock_can0, &clock_can1, &clock_cdbus, @@ -412,182 +410,68 @@ &clock_cpu, &clock_ddr, &clock_dma, - &clock_none, // Clock_emac + &clock_none, // Clock_emac &clock_external, &clock_hclock0, &clock_hclock2, - &clock_none, // Clock_hdmi - &clock_i2c, + &clock_hclock2_pclock, + &clock_none, // Clock_hdmi &clock_i2c0, &clock_i2c1, - &clock_i2s0, // supplies i2s0_rx + &clock_none, // Clock_i2c2 + &clock_none, // Clock_i2c3 + &clock_none, // Clock_i2c4 + &clock_i2s0, // supplies i2s0_rx &clock_i2s0_rx, &clock_i2s0_tx, - &clock_i2s1, // supplies i2s0_tx - &clock_none, // Clock_i2s1_rx - &clock_none, // Clock_i2s1_tx - &clock_none, // Clock_kbc - &clock_none, // Clock_lcd + &clock_i2s1, // supplies i2s0_tx + &clock_none, // Clock_i2s1_rx + &clock_none, // Clock_i2s1_tx + &clock_none, // Clock_kbc + &clock_none, // Clock_lcd &clock_lcd_pixel, + &clock_none, // Clock_lcd_pixel1 &clock_mac, &clock_main, &clock_mipi_csi, - &clock_msc, + &clock_none, // Clock_msc &clock_msc0, &clock_msc1, - &clock_none, - &clock_otg, + &clock_none, // Clock_msc2 + &clock_none, // Clock_none + &clock_otg0, + &clock_none, // Clock_otg1 &clock_pclock, &clock_pll_A, &clock_pll_E, &clock_pll_M, - &clock_pwm, + &clock_none, // Clock_pll_V &clock_pwm0, - &clock_none, // Clock_pwm1 - &clock_none, // Clock_scc + &clock_none, // Clock_pwm1 + &clock_none, // Clock_rtc + &clock_none, // Clock_scc &clock_sfc, - &clock_none, // Clock_smb0 - &clock_none, // Clock_smb1 - &clock_none, // Clock_smb2 - &clock_none, // Clock_smb3 - &clock_none, // Clock_smb4 - &clock_ssi, + &clock_none, // Clock_ssi + &clock_ssi0, + &clock_none, // Clock_ssi1 + &clock_none, // Clock_ssi2 &clock_timer, &clock_uart0, &clock_uart1, &clock_uart2, &clock_uart3, - &clock_none, // Clock_udc - &clock_none, // Clock_uhc - &clock_none, // Clock_uprt + &clock_none, // Clock_udc + &clock_none, // Clock_uhc + &clock_none, // Clock_uprt }; -// If implemented as a Hw::Device, various properties would be -// initialised in the constructor and obtained from the device tree -// definitions. - -Cpm_x1600_chip::Cpm_x1600_chip(l4_addr_t addr, uint32_t exclk_freq) -: _cpm_regs(addr, clocks, exclk_freq) -{ - // add_cid("cpm"); - // add_cid("cpm-x1600"); - // register_property("exclk_freq", &exclk_freq); -} - -const char * -Cpm_x1600_chip::clock_type(enum Clock_identifiers clock) -{ - return clocks[clock]->clock_type(); -} - -int -Cpm_x1600_chip::have_clock(enum Clock_identifiers clock) -{ - return clocks[clock]->have_clock(_cpm_regs); -} - -void -Cpm_x1600_chip::start_clock(enum Clock_identifiers clock) -{ - clocks[clock]->start_clock(_cpm_regs); -} +// Peripheral abstraction. -void -Cpm_x1600_chip::stop_clock(enum Clock_identifiers clock) -{ - clocks[clock]->stop_clock(_cpm_regs); -} - -int -Cpm_x1600_chip::get_parameters(enum Clock_identifiers clock, uint32_t parameters[]) -{ - Clock_divided_base *clk = dynamic_cast(clocks[clock]); - - if (clk != NULL) - return clk->get_parameters(_cpm_regs, parameters); - else - return 0; -} - -int -Cpm_x1600_chip::set_parameters(enum Clock_identifiers clock, int num_parameters, uint32_t parameters[]) -{ - Clock_divided_base *clk = dynamic_cast(clocks[clock]); - - if (clk != NULL) - return clk->set_parameters(_cpm_regs, num_parameters, parameters); - else - return 0; -} - -uint8_t -Cpm_x1600_chip::get_source(enum Clock_identifiers clock) +Cpm_x1600_chip::Cpm_x1600_chip(l4_addr_t addr) +: Cpm_chip(addr, clocks) { - Clock_active *clk = dynamic_cast(clocks[clock]); - - if (clk != NULL) - return clk->get_source(_cpm_regs); - else - return 0; -} - -enum Clock_identifiers -Cpm_x1600_chip::get_source_clock(enum Clock_identifiers clock) -{ - Clock_active *clk = dynamic_cast(clocks[clock]); - - if (clk != NULL) - return clk->get_source_clock(_cpm_regs); - else - return Clock_undefined; -} - -void -Cpm_x1600_chip::set_source_clock(enum Clock_identifiers clock, enum Clock_identifiers source) -{ - Clock_active *clk = dynamic_cast(clocks[clock]); - - if (clk != NULL) - clk->set_source_clock(_cpm_regs, source); -} - -void -Cpm_x1600_chip::set_source(enum Clock_identifiers clock, uint8_t source) -{ - Clock_active *clk = dynamic_cast(clocks[clock]); - - if (clk != NULL) - clk->set_source(_cpm_regs, source); -} - -uint32_t -Cpm_x1600_chip::get_source_frequency(enum Clock_identifiers clock) -{ - Clock_active *clk = dynamic_cast(clocks[clock]); - - if (clk != NULL) - return clk->get_source_frequency(_cpm_regs); - else - return 0; -} - -uint32_t -Cpm_x1600_chip::get_frequency(enum Clock_identifiers clock) -{ - return clocks[clock]->get_frequency(_cpm_regs); -} - -int -Cpm_x1600_chip::set_frequency(enum Clock_identifiers clock, uint32_t frequency) -{ - Clock_divided_base *clk = dynamic_cast(clocks[clock]); - - if (clk != NULL) - return clk->set_frequency(_cpm_regs, frequency); - else - return 0; } @@ -597,10 +481,7 @@ void *x1600_cpm_init(l4_addr_t cpm_base) { - /* Initialise the clock and power management peripheral with the - register memory region and a 24MHz EXCLK frequency. */ - - return (void *) new Cpm_x1600_chip(cpm_base, 24000000); + return (void *) new Cpm_x1600_chip(cpm_base); } const char * diff -r 934192f49457 -r 678a57edbba5 pkg/devices/lib/i2c/src/jz4730.cc --- a/pkg/devices/lib/i2c/src/jz4730.cc Tue Oct 24 18:52:06 2023 +0200 +++ b/pkg/devices/lib/i2c/src/jz4730.cc Fri Oct 27 18:02:49 2023 +0200 @@ -89,7 +89,7 @@ { // Make sure that the I2C clock is available. - _cpm->start_clock(Clock_i2c); + _cpm->start_clock(Clock_i2c0); // Set the bus clock frequency. @@ -119,7 +119,7 @@ // obtained from the CPM unit and is scaled to kHz in order to keep the // numbers easily representable, as is the bus frequency. - uint32_t pclk = _cpm->get_pclock_frequency() / 1000; + uint32_t pclk = _cpm->get_frequency(Clock_pclock) / 1000; uint32_t i2c_clk = _frequency / 1000; uint32_t division = pclk / (16 * i2c_clk); diff -r 934192f49457 -r 678a57edbba5 pkg/devices/lib/i2c/src/jz4780.cc --- a/pkg/devices/lib/i2c/src/jz4780.cc Tue Oct 24 18:52:06 2023 +0200 +++ b/pkg/devices/lib/i2c/src/jz4780.cc Fri Oct 27 18:02:49 2023 +0200 @@ -196,7 +196,7 @@ // kHz in order to keep the numbers easily representable, as is the bus // frequency. - uint32_t smb_clk = _cpm->get_pclock_frequency() / 1000; + uint32_t smb_clk = _cpm->get_frequency(Clock_pclock) / 1000; uint32_t i2c_clk = _frequency / 1000; unsigned int speed = (i2c_clk <= 100) ? 1 : 2; @@ -628,7 +628,7 @@ I2c_jz4780_chip::get_channel(uint8_t channel) { l4_addr_t block = _start + channel * Smb_block_offset; - enum Clock_identifiers bits[] = {Clock_smb0, Clock_smb1, Clock_smb2, Clock_smb3, Clock_smb4}; + enum Clock_identifiers bits[] = {Clock_i2c0, Clock_i2c1, Clock_i2c2, Clock_i2c3, Clock_i2c4}; if (channel < 5) { diff -r 934192f49457 -r 678a57edbba5 pkg/landfall-examples/ci20_cpm/ci20_cpm.c --- a/pkg/landfall-examples/ci20_cpm/ci20_cpm.c Tue Oct 24 18:52:06 2023 +0200 +++ b/pkg/landfall-examples/ci20_cpm/ci20_cpm.c Fri Oct 27 18:02:49 2023 +0200 @@ -129,69 +129,60 @@ /* Read information from the clock and power management unit. */ - printf("Main source: %d\n", jz4780_cpm_get_main_source(cpm)); - printf(" Main frequency: %d\n", jz4780_cpm_get_main_frequency(cpm)); - printf("APLL frequency: %d\n", jz4780_cpm_get_apll_frequency(cpm)); - printf("EPLL frequency: %d\n", jz4780_cpm_get_epll_frequency(cpm)); - printf("MPLL frequency: %d\n", jz4780_cpm_get_mpll_frequency(cpm)); - printf("VPLL frequency: %d\n", jz4780_cpm_get_vpll_frequency(cpm)); - printf("CPU divider: %d\n", jz4780_cpm_get_cpu_divider(cpm)); - printf(" CPU frequency: %d\n", jz4780_cpm_get_cpu_frequency(cpm)); - printf("Memory source: %d\n", jz4780_cpm_get_memory_source(cpm)); - printf(" Memory source frequency: %d\n", jz4780_cpm_get_memory_source_frequency(cpm)); - printf(" Memory divider: %d\n", jz4780_cpm_get_memory_divider(cpm)); - printf(" Memory frequency: %d\n", jz4780_cpm_get_memory_frequency(cpm)); - printf("APB source: %d\n", jz4780_cpm_get_pclock_source(cpm)); - printf(" APB source frequency: %d\n", jz4780_cpm_get_pclock_source_frequency(cpm)); - printf(" APB divider: %d\n", jz4780_cpm_get_pclock_divider(cpm)); - printf(" Slow peripheral (APB) frequency: %d\n", jz4780_cpm_get_pclock_frequency(cpm)); - printf("AHB0 source: %d\n", jz4780_cpm_get_hclock0_source(cpm)); - printf(" AHB0 source frequency: %d\n", jz4780_cpm_get_hclock0_source_frequency(cpm)); - printf(" AHB0 divider: %d\n", jz4780_cpm_get_hclock0_divider(cpm)); - printf(" Fast peripheral (AHB0) frequency: %d\n", jz4780_cpm_get_hclock0_frequency(cpm)); - printf("AHB2 source: %d\n", jz4780_cpm_get_hclock2_source(cpm)); - printf(" AHB2 source frequency: %d\n", jz4780_cpm_get_hclock2_source_frequency(cpm)); - printf(" AHB2 divider: %d\n", jz4780_cpm_get_hclock2_divider(cpm)); - printf(" Fast peripheral (AHB2) frequency: %d\n", jz4780_cpm_get_hclock2_frequency(cpm)); - printf("LCD source: %d\n", jz4780_cpm_get_lcd_source(cpm)); - printf(" LCD source frequency: %d\n", jz4780_cpm_get_lcd_source_frequency(cpm)); - printf(" LCD pixel clock divider: %d\n", jz4780_cpm_get_lcd_pixel_divider(cpm)); - printf(" LCD pixel clock frequency: %d\n", jz4780_cpm_get_frequency(cpm, Clock_lcd_pixel)); + printf("Main source: %d\n", jz4780_cpm_get_source(cpm, Clock_main)); + printf(" Main frequency: %d\n", jz4780_cpm_get_frequency(cpm, Clock_main)); + printf("APLL frequency: %d\n", jz4780_cpm_get_frequency(cpm, Clock_pll_A)); + printf("EPLL frequency: %d\n", jz4780_cpm_get_frequency(cpm, Clock_pll_E)); + printf("MPLL frequency: %d\n", jz4780_cpm_get_frequency(cpm, Clock_pll_M)); + printf("VPLL frequency: %d\n", jz4780_cpm_get_frequency(cpm, Clock_pll_V)); + printf("CPU frequency: %d\n", jz4780_cpm_get_frequency(cpm, Clock_cpu)); + printf("Memory source: %d\n", jz4780_cpm_get_source(cpm, Clock_ddr)); + printf(" Memory source frequency: %d\n", jz4780_cpm_get_source_frequency(cpm, Clock_ddr)); + printf(" Memory frequency: %d\n", jz4780_cpm_get_frequency(cpm, Clock_ddr)); + printf("APB source: %d\n", jz4780_cpm_get_source(cpm, Clock_pclock)); + printf(" APB source frequency: %d\n", jz4780_cpm_get_source_frequency(cpm, Clock_pclock)); + printf(" Slow peripheral (APB) frequency: %d\n", jz4780_cpm_get_frequency(cpm, Clock_pclock)); + printf("AHB0 source: %d\n", jz4780_cpm_get_source(cpm, Clock_hclock0)); + printf(" AHB0 source frequency: %d\n", jz4780_cpm_get_source_frequency(cpm, Clock_hclock0)); + printf(" Fast peripheral (AHB0) frequency: %d\n", jz4780_cpm_get_frequency(cpm, Clock_hclock0)); + printf("AHB2 source: %d\n", jz4780_cpm_get_source(cpm, Clock_hclock2)); + printf(" AHB2 source frequency: %d\n", jz4780_cpm_get_source_frequency(cpm, Clock_hclock2)); + printf(" Fast peripheral (AHB2) frequency: %d\n", jz4780_cpm_get_frequency(cpm, Clock_hclock2)); + printf("LCD source: %d\n", jz4780_cpm_get_source(cpm, Clock_lcd)); + printf(" LCD source frequency: %d\n", jz4780_cpm_get_source_frequency(cpm, Clock_lcd)); + printf(" LCD frequency: %d\n", jz4780_cpm_get_frequency(cpm, Clock_lcd)); + printf(" LCD pixel clock frequency: %d\n", jz4780_cpm_get_frequency(cpm, Clock_lcd_pixel0)); /* Attempt to set the pixel clock frequency. */ - jz4780_cpm_set_frequency(cpm, Clock_lcd_pixel, 108000000); + jz4780_cpm_set_frequency(cpm, Clock_lcd_pixel0, 108000000); - printf("LCD source: %d\n", jz4780_cpm_get_lcd_source(cpm)); - printf(" LCD source frequency: %d\n", jz4780_cpm_get_lcd_source_frequency(cpm)); - printf(" LCD pixel clock divider: %d\n", jz4780_cpm_get_lcd_pixel_divider(cpm)); - printf(" LCD pixel clock frequency: %d\n", jz4780_cpm_get_frequency(cpm, Clock_lcd_pixel)); + printf("LCD source: %d\n", jz4780_cpm_get_source(cpm, Clock_lcd)); + printf(" LCD source frequency: %d\n", jz4780_cpm_get_source_frequency(cpm, Clock_lcd)); + printf(" LCD frequency: %d\n", jz4780_cpm_get_frequency(cpm, Clock_lcd)); + printf(" LCD pixel clock frequency: %d\n", jz4780_cpm_get_frequency(cpm, Clock_lcd_pixel0)); /* Attempt to set the peripheral clock frequency. */ - jz4780_cpm_set_pclock_source(cpm, 1); + jz4780_cpm_set_source(cpm, Clock_pclock, 1); - printf("APB source: %d\n", jz4780_cpm_get_pclock_source(cpm)); - printf(" APB source frequency: %d\n", jz4780_cpm_get_pclock_source_frequency(cpm)); - printf(" APB divider: %d\n", jz4780_cpm_get_pclock_divider(cpm)); - printf(" Slow peripheral (APB) frequency: %d\n", jz4780_cpm_get_pclock_frequency(cpm)); - printf("AHB2 source: %d\n", jz4780_cpm_get_hclock2_source(cpm)); - printf(" AHB2 source frequency: %d\n", jz4780_cpm_get_hclock2_source_frequency(cpm)); - printf(" AHB2 divider: %d\n", jz4780_cpm_get_hclock2_divider(cpm)); - printf(" Fast peripheral (AHB2) frequency: %d\n", jz4780_cpm_get_hclock2_frequency(cpm)); + printf("APB source: %d\n", jz4780_cpm_get_source(cpm, Clock_pclock)); + printf(" APB source frequency: %d\n", jz4780_cpm_get_source_frequency(cpm, Clock_pclock)); + printf(" Slow peripheral (APB) frequency: %d\n", jz4780_cpm_get_frequency(cpm, Clock_pclock)); + printf("AHB2 source: %d\n", jz4780_cpm_get_source(cpm, Clock_hclock2)); + printf(" AHB2 source frequency: %d\n", jz4780_cpm_get_source_frequency(cpm, Clock_hclock2)); + printf(" Fast peripheral (AHB2) frequency: %d\n", jz4780_cpm_get_frequency(cpm, Clock_hclock2)); /* Attempt to set the MPLL output to EXCLK divided by 4. */ - jz4780_cpm_set_mpll_parameters(cpm, 1, 4, 1); + jz4780_cpm_set_parameters(cpm, Clock_pll_M, 3, (uint32_t []) {1, 4, 1}); - printf("APB source: %d\n", jz4780_cpm_get_pclock_source(cpm)); - printf(" APB source frequency: %d\n", jz4780_cpm_get_pclock_source_frequency(cpm)); - printf(" APB divider: %d\n", jz4780_cpm_get_pclock_divider(cpm)); - printf(" Slow peripheral (APB) frequency: %d\n", jz4780_cpm_get_pclock_frequency(cpm)); - printf("AHB2 source: %d\n", jz4780_cpm_get_hclock2_source(cpm)); - printf(" AHB2 source frequency: %d\n", jz4780_cpm_get_hclock2_source_frequency(cpm)); - printf(" AHB2 divider: %d\n", jz4780_cpm_get_hclock2_divider(cpm)); - printf(" Fast peripheral (AHB2) frequency: %d\n", jz4780_cpm_get_hclock2_frequency(cpm)); + printf("APB source: %d\n", jz4780_cpm_get_source(cpm, Clock_pclock)); + printf(" APB source frequency: %d\n", jz4780_cpm_get_source_frequency(cpm, Clock_pclock)); + printf(" Slow peripheral (APB) frequency: %d\n", jz4780_cpm_get_frequency(cpm, Clock_pclock)); + printf("AHB2 source: %d\n", jz4780_cpm_get_source(cpm, Clock_hclock2)); + printf(" AHB2 source frequency: %d\n", jz4780_cpm_get_source_frequency(cpm, Clock_hclock2)); + printf(" Fast peripheral (AHB2) frequency: %d\n", jz4780_cpm_get_frequency(cpm, Clock_hclock2)); return 0; } diff -r 934192f49457 -r 678a57edbba5 pkg/landfall-examples/ci20_hdmi_i2c/ci20_hdmi_i2c.c --- a/pkg/landfall-examples/ci20_hdmi_i2c/ci20_hdmi_i2c.c Tue Oct 24 18:52:06 2023 +0200 +++ b/pkg/landfall-examples/ci20_hdmi_i2c/ci20_hdmi_i2c.c Fri Oct 27 18:02:49 2023 +0200 @@ -272,14 +272,12 @@ cpm = jz4780_cpm_init(cpm_base); - printf("VPLL frequency: %d\n", jz4780_cpm_get_vpll_frequency(cpm)); - printf("HDMI divider: %d\n", jz4780_cpm_get_hdmi_divider(cpm)); + printf("VPLL frequency: %d\n", jz4780_cpm_get_frequency(cpm, Clock_pll_V)); printf("HDMI frequency: %d\n", jz4780_cpm_get_frequency(cpm, Clock_hdmi)); jz4780_cpm_stop_clock(cpm, Clock_hdmi); jz4780_cpm_set_frequency(cpm, Clock_hdmi, 27000000); - printf("HDMI divider: %d\n", jz4780_cpm_get_hdmi_divider(cpm)); printf("HDMI frequency: %d\n", jz4780_cpm_get_frequency(cpm, Clock_hdmi)); jz4780_cpm_start_clock(cpm, Clock_hdmi); @@ -340,25 +338,22 @@ /* Test initialisation with a frequency appropriate for the test panel. */ - printf("LCD source: %d\n", jz4780_cpm_get_lcd_source(cpm)); - printf("LCD divider: %d\n", jz4780_cpm_get_lcd_pixel_divider(cpm)); - printf("LCD frequency: %d\n", jz4780_cpm_get_frequency(cpm, Clock_lcd_pixel)); + printf("LCD source: %d\n", jz4780_cpm_get_source(cpm, Clock_lcd)); + printf("LCD frequency: %d\n", jz4780_cpm_get_frequency(cpm, Clock_lcd_pixel0)); printf("Desired frequency: %d\n", jz4740_lcd_get_pixel_clock(lcd)); jz4780_cpm_stop_clock(cpm, Clock_lcd); jz4780_cpm_set_frequency(cpm, Clock_lcd, jz4740_lcd_get_pixel_clock(lcd) * 3); - jz4780_cpm_set_frequency(cpm, Clock_lcd_pixel, jz4740_lcd_get_pixel_clock(lcd)); + jz4780_cpm_set_frequency(cpm, Clock_lcd_pixel0, jz4740_lcd_get_pixel_clock(lcd)); - printf("LCD source: %d\n", jz4780_cpm_get_lcd_source(cpm)); - printf("LCD divider: %d\n", jz4780_cpm_get_lcd_pixel_divider(cpm)); - printf("LCD frequency: %d\n", jz4780_cpm_get_frequency(cpm, Clock_lcd_pixel)); - printf("AHB0 frequency: %d\n", jz4780_cpm_get_hclock0_frequency(cpm)); + printf("LCD source: %d\n", jz4780_cpm_get_source(cpm, Clock_lcd)); + printf("LCD frequency: %d\n", jz4780_cpm_get_frequency(cpm, Clock_lcd_pixel0)); /* With the LCD pixel clock set up, bring up the HDMI. */ printf("Enable HDMI output...\n"); - jz4780_hdmi_enable(hdmi, jz4780_cpm_get_frequency(cpm, Clock_lcd_pixel)); + jz4780_hdmi_enable(hdmi, jz4780_cpm_get_frequency(cpm, Clock_lcd_pixel0)); /* Create the DMA space. */ diff -r 934192f49457 -r 678a57edbba5 pkg/landfall-examples/ci20_i2c/ci20_i2c.c --- a/pkg/landfall-examples/ci20_i2c/ci20_i2c.c Tue Oct 24 18:52:06 2023 +0200 +++ b/pkg/landfall-examples/ci20_i2c/ci20_i2c.c Fri Oct 27 18:02:49 2023 +0200 @@ -1,7 +1,7 @@ /* * (c) 2008-2009 Adam Lackorzynski * economic rights: Technische Universität Dresden (Germany) - * Copyright (C) 2017, 2018, 2019, 2020 Paul Boddie + * Copyright (C) 2017, 2018, 2019, 2020, 2023 Paul Boddie * * This file is part of TUD:OS and distributed under the terms of the * GNU General Public License 2. @@ -403,8 +403,8 @@ /* Attempt to set the PCLK source to SCLK_A. */ - jz4780_cpm_set_pclock_source(cpm, 1); - printf("Peripheral clock: %d\n", jz4780_cpm_get_pclock_frequency(cpm)); + jz4780_cpm_set_source_clock(cpm, Clock_pclock, Clock_main); + printf("Peripheral clock: %d\n", jz4780_cpm_get_frequency(cpm, Clock_pclock)); /* Obtain I2C reference. */ diff -r 934192f49457 -r 678a57edbba5 pkg/landfall-examples/qi_lb60_lcd/qi_lb60_lcd.c --- a/pkg/landfall-examples/qi_lb60_lcd/qi_lb60_lcd.c Tue Oct 24 18:52:06 2023 +0200 +++ b/pkg/landfall-examples/qi_lb60_lcd/qi_lb60_lcd.c Fri Oct 27 18:02:49 2023 +0200 @@ -188,7 +188,7 @@ jz4740_cpm_stop_clock(cpm, Clock_lcd); jz4740_cpm_set_frequency(cpm, Clock_lcd, jz4740_lcd_get_pixel_clock(lcd) * 3); - jz4740_cpm_set_frequency(cpm, Clock_lcd_pixel, jz4740_lcd_get_pixel_clock(lcd)); + jz4740_cpm_set_frequency(cpm, Clock_lcd_pixel0, jz4740_lcd_get_pixel_clock(lcd)); /* Create the DMA space. */ diff -r 934192f49457 -r 678a57edbba5 tools/install.sh --- a/tools/install.sh Tue Oct 24 18:52:06 2023 +0200 +++ b/tools/install.sh Fri Oct 27 18:02:49 2023 +0200 @@ -25,7 +25,7 @@ if [ "$1" = '--help' ]; then cat 1>&2 < [ --clean ] +Usage: $PROGNAME [ --clean | --preserve ] Copy the distributed packages into the "pkg" hierarchy found within the specified directory. Also copy the distributed configuration examples into the @@ -35,6 +35,9 @@ "conf" directory and a "pkg" directory inside it. Specifying --clean removes copied objects. + +Specifying --preserve preserves files and directories in locations used by this +distribution that are not (or are no longer) part of this distribution. EOF exit 1 fi @@ -58,13 +61,15 @@ fi L4DIR=$1 +CLEAN= +PRESERVE= # Determine the mode. if [ "$2" = '--clean' ] ; then CLEAN=$2 -else - CLEAN= +elif [ "$2" = '--preserve' ] ; then + PRESERVE=$2 fi # Check the configuration, if possible. @@ -140,6 +145,10 @@ # Remove obsolete files. + if [ "$PRESERVE" ] ; then + continue + fi + for OBJECT in "$SOURCEDIR/"* ; do OBJNAME=$(basename "$OBJECT") ORIGIN=$(readlink -f "$OBJECT")