1.1 --- a/pkg/devices/Makefile Sat Jan 16 23:10:48 2021 +0100 1.2 +++ b/pkg/devices/Makefile Sat Jan 16 23:47:39 2021 +0100 1.3 @@ -17,6 +17,6 @@ 1.4 input: keypad lib 1.5 keypad: lib util 1.6 lcd: display lib util 1.7 -lib: util 1.8 +lib: include util 1.9 pwm: lib util 1.10 spi: lib util
2.1 --- a/pkg/devices/cpm/src/jz4730/cpm-jz4730.cc Sat Jan 16 23:10:48 2021 +0100 2.2 +++ b/pkg/devices/cpm/src/jz4730/cpm-jz4730.cc Sat Jan 16 23:47:39 2021 +0100 2.3 @@ -1,7 +1,7 @@ 2.4 /* 2.5 * JZ4730 CPM server. 2.6 * 2.7 - * Copyright (C) 2018, 2020 Paul Boddie <paul@boddie.org.uk> 2.8 + * Copyright (C) 2018, 2020, 2021 Paul Boddie <paul@boddie.org.uk> 2.9 * 2.10 * This program is free software; you can redistribute it and/or 2.11 * modify it under the terms of the GNU General Public License as 2.12 @@ -63,15 +63,21 @@ 2.13 return L4_EOK; 2.14 } 2.15 2.16 - long start_lcd() 2.17 + long have_clock(enum Clock_identifiers clock, int *enabled) 2.18 { 2.19 - _chip->start_lcd(); 2.20 + *enabled = _chip->have_clock(clock); 2.21 return L4_EOK; 2.22 } 2.23 2.24 - long stop_lcd() 2.25 + long start_clock(enum Clock_identifiers clock) 2.26 { 2.27 - _chip->stop_lcd(); 2.28 + _chip->start_clock(clock); 2.29 + return L4_EOK; 2.30 + } 2.31 + 2.32 + long stop_clock(enum Clock_identifiers clock) 2.33 + { 2.34 + _chip->stop_clock(clock); 2.35 return L4_EOK; 2.36 } 2.37
3.1 --- a/pkg/devices/cpm/src/jz4740/cpm-jz4740.cc Sat Jan 16 23:10:48 2021 +0100 3.2 +++ b/pkg/devices/cpm/src/jz4740/cpm-jz4740.cc Sat Jan 16 23:47:39 2021 +0100 3.3 @@ -1,7 +1,7 @@ 3.4 /* 3.5 * JZ4740 CPM server. 3.6 * 3.7 - * Copyright (C) 2018, 2020 Paul Boddie <paul@boddie.org.uk> 3.8 + * Copyright (C) 2018, 2020, 2021 Paul Boddie <paul@boddie.org.uk> 3.9 * 3.10 * This program is free software; you can redistribute it and/or 3.11 * modify it under the terms of the GNU General Public License as 3.12 @@ -63,15 +63,21 @@ 3.13 return L4_EOK; 3.14 } 3.15 3.16 - long start_lcd() 3.17 + long have_clock(enum Clock_identifiers clock, int *enabled) 3.18 { 3.19 - _chip->start_lcd(); 3.20 + *enabled = _chip->have_clock(clock); 3.21 return L4_EOK; 3.22 } 3.23 3.24 - long stop_lcd() 3.25 + long start_clock(enum Clock_identifiers clock) 3.26 { 3.27 - _chip->stop_lcd(); 3.28 + _chip->start_clock(clock); 3.29 + return L4_EOK; 3.30 + } 3.31 + 3.32 + long stop_clock(enum Clock_identifiers clock) 3.33 + { 3.34 + _chip->stop_clock(clock); 3.35 return L4_EOK; 3.36 } 3.37
4.1 --- a/pkg/devices/cpm/src/jz4780/cpm-jz4780.cc Sat Jan 16 23:10:48 2021 +0100 4.2 +++ b/pkg/devices/cpm/src/jz4780/cpm-jz4780.cc Sat Jan 16 23:47:39 2021 +0100 4.3 @@ -1,7 +1,7 @@ 4.4 /* 4.5 * JZ4780 CPM server. 4.6 * 4.7 - * Copyright (C) 2018, 2020 Paul Boddie <paul@boddie.org.uk> 4.8 + * Copyright (C) 2018, 2020, 2021 Paul Boddie <paul@boddie.org.uk> 4.9 * 4.10 * This program is free software; you can redistribute it and/or 4.11 * modify it under the terms of the GNU General Public License as 4.12 @@ -75,27 +75,21 @@ 4.13 return L4_EOK; 4.14 } 4.15 4.16 - long start_hdmi() 4.17 + long have_clock(enum Clock_identifiers clock, int *enabled) 4.18 { 4.19 - _chip->start_hdmi(); 4.20 + *enabled = _chip->have_clock(clock); 4.21 return L4_EOK; 4.22 } 4.23 4.24 - long stop_hdmi() 4.25 + long start_clock(enum Clock_identifiers clock) 4.26 { 4.27 - _chip->stop_hdmi(); 4.28 + _chip->start_clock(clock); 4.29 return L4_EOK; 4.30 } 4.31 4.32 - long start_lcd() 4.33 + long stop_clock(enum Clock_identifiers clock) 4.34 { 4.35 - _chip->start_lcd(); 4.36 - return L4_EOK; 4.37 - } 4.38 - 4.39 - long stop_lcd() 4.40 - { 4.41 - _chip->stop_lcd(); 4.42 + _chip->stop_clock(clock); 4.43 return L4_EOK; 4.44 } 4.45
5.1 --- a/pkg/devices/display/src/ci20/display-ci20_hdmi.cc Sat Jan 16 23:10:48 2021 +0100 5.2 +++ b/pkg/devices/display/src/ci20/display-ci20_hdmi.cc Sat Jan 16 23:47:39 2021 +0100 5.3 @@ -64,9 +64,9 @@ 5.4 5.5 /* Start the HDMI peripheral. */ 5.6 5.7 - cpm_device->stop_hdmi(); 5.8 + cpm_device->stop_clock(Clock_hdmi); 5.9 cpm_device->set_hdmi_frequency(27000000); 5.10 - cpm_device->start_hdmi(); 5.11 + cpm_device->start_clock(Clock_hdmi); 5.12 5.13 /* Load the panel data from the configured library. */ 5.14
6.1 --- a/pkg/devices/idl/cpm.idl Sat Jan 16 23:10:48 2021 +0100 6.2 +++ b/pkg/devices/idl/cpm.idl Sat Jan 16 23:47:39 2021 +0100 6.3 @@ -1,3 +1,4 @@ 6.4 +#include <l4/devices/clocks.h> 6.5 #include <l4/devices/protocols.h> 6.6 #include <stdint.h> 6.7 6.8 @@ -13,13 +14,11 @@ 6.9 6.10 void set_lcd_frequencies(in uint32_t pclk, in uint8_t multiplier); 6.11 6.12 - void start_hdmi(); 6.13 - 6.14 - void stop_hdmi(); 6.15 + void have_clock(in enum Clock_identifiers clock, out int enabled); 6.16 6.17 - void start_lcd(); 6.18 + void start_clock(in enum Clock_identifiers clock); 6.19 6.20 - void stop_lcd(); 6.21 + void stop_clock(in enum Clock_identifiers clock); 6.22 6.23 void update_output_frequency(); 6.24 };
7.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 7.2 +++ b/pkg/devices/include/clocks.h Sat Jan 16 23:47:39 2021 +0100 7.3 @@ -0,0 +1,55 @@ 7.4 +/* 7.5 + * Clock identifiers for clock and power management. 7.6 + * 7.7 + * Copyright (C) 2021 Paul Boddie <paul@boddie.org.uk> 7.8 + * 7.9 + * This program is free software; you can redistribute it and/or 7.10 + * modify it under the terms of the GNU General Public License as 7.11 + * published by the Free Software Foundation; either version 2 of 7.12 + * the License, or (at your option) any later version. 7.13 + * 7.14 + * This program is distributed in the hope that it will be useful, 7.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 7.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 7.17 + * GNU General Public License for more details. 7.18 + * 7.19 + * You should have received a copy of the GNU General Public License 7.20 + * along with this program; if not, write to the Free Software 7.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, 7.22 + * Boston, MA 02110-1301, USA 7.23 + */ 7.24 + 7.25 +#pragma once 7.26 + 7.27 +enum Clock_identifiers 7.28 +{ 7.29 + Clock_aic_bitclk, 7.30 + Clock_aic_pclk, 7.31 + Clock_cim, 7.32 + Clock_dma, 7.33 + Clock_emac, 7.34 + Clock_hdmi, 7.35 + Clock_i2c, 7.36 + Clock_kbc, 7.37 + Clock_lcd, 7.38 + Clock_msc, 7.39 + Clock_pmw0, 7.40 + Clock_pwm1, 7.41 + Clock_scc, 7.42 + Clock_smb0, 7.43 + Clock_smb1, 7.44 + Clock_smb2, 7.45 + Clock_smb3, 7.46 + Clock_smb4, 7.47 + Clock_ssi, 7.48 + Clock_timer, 7.49 + Clock_uart0, 7.50 + Clock_uart1, 7.51 + Clock_uart2, 7.52 + Clock_uart3, 7.53 + Clock_udc, 7.54 + Clock_uhc, 7.55 + Clock_uprt, 7.56 +}; 7.57 + 7.58 +// vim: tabstop=2 expandtab shiftwidth=2
8.1 --- a/pkg/devices/lcd/src/jz4740/lcd-jz4740-device.cc Sat Jan 16 23:10:48 2021 +0100 8.2 +++ b/pkg/devices/lcd/src/jz4740/lcd-jz4740-device.cc Sat Jan 16 23:47:39 2021 +0100 8.3 @@ -1,7 +1,7 @@ 8.4 /* 8.5 * Common LCD device support for the JZ4740 and related SoCs. 8.6 * 8.7 - * Copyright (C) 2018, 2020 Paul Boddie <paul@boddie.org.uk> 8.8 + * Copyright (C) 2018, 2020, 2021 Paul Boddie <paul@boddie.org.uk> 8.9 * 8.10 * This program is free software; you can redistribute it and/or 8.11 * modify it under the terms of the GNU General Public License as 8.12 @@ -57,7 +57,7 @@ 8.13 { 8.14 uint32_t pclk = lcd_chip->get_pixel_clock(); 8.15 8.16 - cpm_device->stop_lcd(); 8.17 + cpm_device->stop_clock(Clock_lcd); 8.18 8.19 // Original comment: LCDClock > 2.5*Pixclock 8.20 // However, the documentation indicates that a TFT panel needs a device clock 8.21 @@ -66,7 +66,7 @@ 8.22 8.23 cpm_device->set_lcd_frequencies(pclk, 3); 8.24 cpm_device->update_output_frequency(); 8.25 - cpm_device->start_lcd(); 8.26 + cpm_device->start_clock(Clock_lcd); 8.27 8.28 l4_sleep(1); // 1ms == 1000us 8.29 }
9.1 --- a/pkg/devices/lib/Makefile Sat Jan 16 23:10:48 2021 +0100 9.2 +++ b/pkg/devices/lib/Makefile Sat Jan 16 23:47:39 2021 +0100 9.3 @@ -1,11 +1,12 @@ 9.4 PKGDIR ?= .. 9.5 L4DIR ?= $(PKGDIR)/../.. 9.6 9.7 -TARGET := common cpm gpio hdmi i2c keypad lcd panel pwm 9.8 +TARGET := common cpm dma gpio hdmi i2c keypad lcd panel pwm 9.9 9.10 include $(L4DIR)/mk/subdir.mk 9.11 9.12 cpm: common 9.13 +dma: common 9.14 gpio: common 9.15 hdmi: panel 9.16 i2c: common
10.1 --- a/pkg/devices/lib/cpm/include/cpm-jz4730.h Sat Jan 16 23:10:48 2021 +0100 10.2 +++ b/pkg/devices/lib/cpm/include/cpm-jz4730.h Sat Jan 16 23:47:39 2021 +0100 10.3 @@ -1,7 +1,7 @@ 10.4 /* 10.5 * CPM (clock and power management) support for the JZ4730. 10.6 * 10.7 - * Copyright (C) 2017, 2018, 2020 Paul Boddie <paul@boddie.org.uk> 10.8 + * Copyright (C) 2017, 2018, 2020, 2021 Paul Boddie <paul@boddie.org.uk> 10.9 * 10.10 * This program is free software; you can redistribute it and/or 10.11 * modify it under the terms of the GNU General Public License as 10.12 @@ -45,12 +45,13 @@ 10.13 int pll_enabled(); 10.14 int pll_bypassed(); 10.15 10.16 + // Clock control. 10.17 + 10.18 + uint32_t get_clock_gate_value(enum Clock_identifiers clock); 10.19 + 10.20 public: 10.21 Cpm_jz4730_chip(l4_addr_t addr, uint32_t exclk_freq); 10.22 10.23 - int have_clock(); 10.24 - void start_clock(); 10.25 - 10.26 int have_pll(); 10.27 10.28 uint16_t get_multiplier(); 10.29 @@ -71,11 +72,9 @@ 10.30 void set_lcd_pixel_divider(uint16_t division); 10.31 void set_lcd_frequencies(uint32_t pclk, uint8_t ratio); 10.32 10.33 - void start_i2c(); 10.34 - void stop_i2c(); 10.35 - 10.36 - void start_lcd(); 10.37 - void stop_lcd(); 10.38 + int have_clock(enum Clock_identifiers clock); 10.39 + void start_clock(enum Clock_identifiers clock); 10.40 + void stop_clock(enum Clock_identifiers clock); 10.41 10.42 uint32_t get_pll_frequency(); 10.43 uint32_t get_output_frequency(); 10.44 @@ -99,14 +98,9 @@ 10.45 10.46 int jz4730_cpm_have_pll(void *cpm); 10.47 10.48 -int jz4730_cpm_have_clock(void *cpm); 10.49 -void jz4730_cpm_start_clock(void *cpm); 10.50 - 10.51 -void jz4730_cpm_start_i2c(void *cpm); 10.52 -void jz4730_cpm_stop_i2c(void *cpm); 10.53 - 10.54 -void jz4730_cpm_start_lcd(void *cpm); 10.55 -void jz4730_cpm_stop_lcd(void *cpm); 10.56 +int jz4730_cpm_have_clock(void *cpm, enum Clock_identifiers clock); 10.57 +void jz4730_cpm_start_clock(void *cpm, enum Clock_identifiers clock); 10.58 +void jz4730_cpm_stop_clock(void *cpm, enum Clock_identifiers clock); 10.59 10.60 uint16_t jz4730_cpm_get_lcd_pixel_divider(void *cpm); 10.61 uint32_t jz4730_cpm_get_lcd_pixel_frequency(void *cpm);
11.1 --- a/pkg/devices/lib/cpm/include/cpm-jz4740.h Sat Jan 16 23:10:48 2021 +0100 11.2 +++ b/pkg/devices/lib/cpm/include/cpm-jz4740.h Sat Jan 16 23:47:39 2021 +0100 11.3 @@ -1,5 +1,7 @@ 11.4 /* 11.5 - * Copyright (C) 2017, 2018 Paul Boddie <paul@boddie.org.uk> 11.6 + * CPM (clock and power management) support for the JZ4740. 11.7 + * 11.8 + * Copyright (C) 2017, 2018, 2020, 2021 Paul Boddie <paul@boddie.org.uk> 11.9 * 11.10 * This program is free software; you can redistribute it and/or 11.11 * modify it under the terms of the GNU General Public License as 11.12 @@ -43,11 +45,16 @@ 11.13 int pll_enabled(); 11.14 int pll_bypassed(); 11.15 11.16 + // Clock control. 11.17 + 11.18 + uint32_t get_clock_gate_value(enum Clock_identifiers clock); 11.19 + 11.20 public: 11.21 Cpm_jz4740_chip(l4_addr_t addr, uint32_t exclk_freq); 11.22 11.23 - int have_clock(); 11.24 - void start_clock(); 11.25 + int have_clock(enum Clock_identifiers clock); 11.26 + void start_clock(enum Clock_identifiers clock); 11.27 + void stop_clock(enum Clock_identifiers clock); 11.28 11.29 int have_pll(); 11.30 11.31 @@ -69,9 +76,6 @@ 11.32 void set_lcd_pixel_divider(uint16_t division); 11.33 void set_lcd_frequencies(uint32_t pclk, uint8_t ratio); 11.34 11.35 - void start_lcd(); 11.36 - void stop_lcd(); 11.37 - 11.38 uint32_t get_pll_frequency(); 11.39 uint32_t get_output_frequency(); 11.40 void update_output_frequency(); 11.41 @@ -94,11 +98,9 @@ 11.42 11.43 int jz4740_cpm_have_pll(void *cpm); 11.44 11.45 -int jz4740_cpm_have_clock(void *cpm); 11.46 -void jz4740_cpm_start_clock(void *cpm); 11.47 - 11.48 -void jz4740_cpm_start_lcd(void *cpm); 11.49 -void jz4740_cpm_stop_lcd(void *cpm); 11.50 +int jz4740_cpm_have_clock(void *cpm, enum Clock_identifiers clock); 11.51 +void jz4740_cpm_start_clock(void *cpm, enum Clock_identifiers clock); 11.52 +void jz4740_cpm_stop_clock(void *cpm, enum Clock_identifiers clock); 11.53 11.54 uint16_t jz4740_cpm_get_lcd_pixel_divider(void *cpm); 11.55 uint32_t jz4740_cpm_get_lcd_pixel_frequency(void *cpm);
12.1 --- a/pkg/devices/lib/cpm/include/cpm-jz4780.h Sat Jan 16 23:10:48 2021 +0100 12.2 +++ b/pkg/devices/lib/cpm/include/cpm-jz4780.h Sat Jan 16 23:47:39 2021 +0100 12.3 @@ -1,5 +1,7 @@ 12.4 /* 12.5 - * Copyright (C) 2017, 2018, 2020 Paul Boddie <paul@boddie.org.uk> 12.6 + * CPM (clock and power management) support for the JZ4780. 12.7 + * 12.8 + * Copyright (C) 2017, 2018, 2020, 2021 Paul Boddie <paul@boddie.org.uk> 12.9 * 12.10 * This program is free software; you can redistribute it and/or 12.11 * modify it under the terms of the GNU General Public License as 12.12 @@ -68,10 +70,6 @@ 12.13 void set_hdmi_divider(uint16_t division); 12.14 void set_lcd_pixel_divider(uint8_t controller, uint16_t division); 12.15 12.16 - // Clock control. 12.17 - 12.18 - void _update_i2c(uint8_t channel, int enable); 12.19 - 12.20 // Input frequencies. 12.21 12.22 uint32_t get_pll_frequency(uint32_t pll_reg); 12.23 @@ -82,12 +80,18 @@ 12.24 void set_hdmi_source(uint8_t source); 12.25 void set_lcd_source(uint8_t controller, uint8_t source); 12.26 12.27 + // Clock control. 12.28 + 12.29 + uint32_t get_clock_gate_register(enum Clock_identifiers clock); 12.30 + uint32_t get_clock_gate_value(enum Clock_identifiers clock); 12.31 + 12.32 public: 12.33 void set_pclock_source(uint8_t source); 12.34 Cpm_jz4780_chip(l4_addr_t addr, uint32_t exclk_freq, uint32_t rtclk_freq); 12.35 12.36 - int have_clock(); 12.37 - void start_clock(); 12.38 + int have_clock(enum Clock_identifiers clock); 12.39 + void start_clock(enum Clock_identifiers clock); 12.40 + void stop_clock(enum Clock_identifiers clock); 12.41 12.42 // Clock divider values. 12.43 12.44 @@ -99,17 +103,6 @@ 12.45 uint8_t get_lcd_pixel_divider(uint8_t controller = 0); 12.46 uint8_t get_memory_divider(); 12.47 12.48 - // Clock control. 12.49 - 12.50 - void start_hdmi(); 12.51 - void stop_hdmi(); 12.52 - 12.53 - void start_lcd(); 12.54 - void stop_lcd(); 12.55 - 12.56 - void start_i2c(uint8_t channel); 12.57 - void stop_i2c(uint8_t channel); 12.58 - 12.59 // Input frequencies. 12.60 12.61 uint8_t get_main_source(); 12.62 @@ -169,14 +162,9 @@ 12.63 12.64 void *jz4780_cpm_init(l4_addr_t cpm_base); 12.65 12.66 -int jz4780_cpm_have_clock(void *cpm); 12.67 -void jz4780_cpm_start_clock(void *cpm); 12.68 - 12.69 -void jz4780_cpm_start_hdmi(void *cpm); 12.70 -void jz4780_cpm_stop_hdmi(void *cpm); 12.71 - 12.72 -void jz4780_cpm_start_lcd(void *cpm); 12.73 -void jz4780_cpm_stop_lcd(void *cpm); 12.74 +int jz4780_cpm_have_clock(void *cpm, enum Clock_identifiers clock); 12.75 +void jz4780_cpm_start_clock(void *cpm, enum Clock_identifiers clock); 12.76 +void jz4780_cpm_stop_clock(void *cpm, enum Clock_identifiers clock); 12.77 12.78 uint8_t jz4780_cpm_get_cpu_divider(void *cpm); 12.79 uint8_t jz4780_cpm_get_hclock0_divider(void *cpm);
13.1 --- a/pkg/devices/lib/cpm/include/cpm.h Sat Jan 16 23:10:48 2021 +0100 13.2 +++ b/pkg/devices/lib/cpm/include/cpm.h Sat Jan 16 23:47:39 2021 +0100 13.3 @@ -1,7 +1,7 @@ 13.4 /* 13.5 * Clock and power management (CPM) abstractions. 13.6 * 13.7 - * Copyright (C) 2017, 2018, 2020 Paul Boddie <paul@boddie.org.uk> 13.8 + * Copyright (C) 2017, 2018, 2020, 2021 Paul Boddie <paul@boddie.org.uk> 13.9 * 13.10 * This program is free software; you can redistribute it and/or 13.11 * modify it under the terms of the GNU General Public License as 13.12 @@ -21,6 +21,7 @@ 13.13 13.14 #pragma once 13.15 13.16 +#include <l4/devices/clocks.h> 13.17 #include <l4/sys/types.h> 13.18 #include <stdint.h> 13.19 13.20 @@ -37,13 +38,13 @@ 13.21 13.22 virtual void set_hdmi_frequency(uint32_t) { } 13.23 13.24 - virtual void start_hdmi() { } 13.25 - virtual void stop_hdmi() { } 13.26 - 13.27 virtual void set_lcd_frequencies(uint32_t pclk, uint8_t ratio) = 0; 13.28 13.29 - virtual void start_lcd() = 0; 13.30 - virtual void stop_lcd() = 0; 13.31 + virtual int have_clock(enum Clock_identifiers clock) = 0; 13.32 + 13.33 + virtual void start_clock(enum Clock_identifiers clock) = 0; 13.34 + 13.35 + virtual void stop_clock(enum Clock_identifiers clock) = 0; 13.36 13.37 virtual void update_output_frequency() = 0; 13.38 };
14.1 --- a/pkg/devices/lib/cpm/src/jz4730.cc Sat Jan 16 23:10:48 2021 +0100 14.2 +++ b/pkg/devices/lib/cpm/src/jz4730.cc Sat Jan 16 23:47:39 2021 +0100 14.3 @@ -103,16 +103,52 @@ 14.4 14.5 // Clock/timer control. 14.6 14.7 +uint32_t 14.8 +Cpm_jz4730_chip::get_clock_gate_value(enum Clock_identifiers clock) 14.9 +{ 14.10 + switch (clock) 14.11 + { 14.12 + case Clock_uprt: return (1 << Clock_gate_uprt); 14.13 + case Clock_udc: return (1 << Clock_gate_udc); 14.14 + case Clock_cim: return (1 << Clock_gate_cim); 14.15 + case Clock_kbc: return (1 << Clock_gate_kbc); 14.16 + case Clock_emac: return (1 << Clock_gate_emac); 14.17 + case Clock_uart3: return (1 << Clock_gate_uart3); 14.18 + case Clock_aic_bitclk: return (1 << Clock_gate_aic_bitclk); 14.19 + case Clock_scc: return (1 << Clock_gate_scc); 14.20 + case Clock_msc: return (1 << Clock_gate_msc); 14.21 + case Clock_ssi: return (1 << Clock_gate_ssi); 14.22 + case Clock_pwm1: return (1 << Clock_gate_pwm1); 14.23 + case Clock_pmw0: return (1 << Clock_gate_pmw0); 14.24 + case Clock_aic_pclk: return (1 << Clock_gate_aic_pclk); 14.25 + case Clock_i2c: return (1 << Clock_gate_i2c); 14.26 + case Clock_lcd: return (1 << Clock_gate_lcd); 14.27 + case Clock_uhc: return (1 << Clock_gate_uhc); 14.28 + case Clock_dma: return (1 << Clock_gate_dmac); 14.29 + case Clock_timer: return (1 << Clock_gate_timer); 14.30 + case Clock_uart2: return (1 << Clock_gate_uart2); 14.31 + case Clock_uart1: return (1 << Clock_gate_uart1); 14.32 + case Clock_uart0: return (1 << Clock_gate_uart0); 14.33 + default: return 0; 14.34 + } 14.35 +} 14.36 + 14.37 int 14.38 -Cpm_jz4730_chip::have_clock() 14.39 +Cpm_jz4730_chip::have_clock(enum Clock_identifiers clock) 14.40 { 14.41 - return !(_regs[Clock_gate] & (1 << Clock_gate_timer)); 14.42 + return !(_regs[Clock_gate] & get_clock_gate_value(clock)); 14.43 } 14.44 14.45 void 14.46 -Cpm_jz4730_chip::start_clock() 14.47 +Cpm_jz4730_chip::start_clock(enum Clock_identifiers clock) 14.48 { 14.49 - _regs[Clock_gate] = _regs[Clock_gate] & ~(1 << Clock_gate_timer); 14.50 + _regs[Clock_gate] = _regs[Clock_gate] & ~get_clock_gate_value(clock); 14.51 +} 14.52 + 14.53 +void 14.54 +Cpm_jz4730_chip::stop_clock(enum Clock_identifiers clock) 14.55 +{ 14.56 + _regs[Clock_gate] = _regs[Clock_gate] | get_clock_gate_value(clock); 14.57 } 14.58 14.59 // PLL control. 14.60 @@ -288,38 +324,6 @@ 14.61 14.62 14.63 14.64 -// I2C clock control. 14.65 - 14.66 -void 14.67 -Cpm_jz4730_chip::start_i2c() 14.68 -{ 14.69 - _regs[Clock_gate] = _regs[Clock_gate] & ~(1 << Clock_gate_i2c); 14.70 -} 14.71 - 14.72 -void 14.73 -Cpm_jz4730_chip::stop_i2c() 14.74 -{ 14.75 - _regs[Clock_gate] = _regs[Clock_gate] | (1 << Clock_gate_i2c); 14.76 -} 14.77 - 14.78 - 14.79 - 14.80 -// LCD clock control. 14.81 - 14.82 -void 14.83 -Cpm_jz4730_chip::start_lcd() 14.84 -{ 14.85 - _regs[Clock_gate] = _regs[Clock_gate] & ~(1 << Clock_gate_lcd); 14.86 -} 14.87 - 14.88 -void 14.89 -Cpm_jz4730_chip::stop_lcd() 14.90 -{ 14.91 - _regs[Clock_gate] = _regs[Clock_gate] | (1 << Clock_gate_lcd); 14.92 -} 14.93 - 14.94 - 14.95 - 14.96 uint32_t 14.97 Cpm_jz4730_chip::get_pll_frequency() 14.98 { 14.99 @@ -403,39 +407,21 @@ 14.100 } 14.101 14.102 int 14.103 -jz4730_cpm_have_clock(void *cpm) 14.104 +jz4730_cpm_have_clock(void *cpm, enum Clock_identifiers clock) 14.105 { 14.106 - return static_cast<Cpm_jz4730_chip *>(cpm)->have_clock(); 14.107 -} 14.108 - 14.109 -void 14.110 -jz4730_cpm_start_clock(void *cpm) 14.111 -{ 14.112 - static_cast<Cpm_jz4730_chip *>(cpm)->start_clock(); 14.113 + return static_cast<Cpm_jz4730_chip *>(cpm)->have_clock(clock); 14.114 } 14.115 14.116 void 14.117 -jz4730_cpm_start_i2c(void *cpm) 14.118 +jz4730_cpm_start_clock(void *cpm, enum Clock_identifiers clock) 14.119 { 14.120 - static_cast<Cpm_jz4730_chip *>(cpm)->start_i2c(); 14.121 + static_cast<Cpm_jz4730_chip *>(cpm)->start_clock(clock); 14.122 } 14.123 14.124 void 14.125 -jz4730_cpm_stop_i2c(void *cpm) 14.126 -{ 14.127 - static_cast<Cpm_jz4730_chip *>(cpm)->stop_i2c(); 14.128 -} 14.129 - 14.130 -void 14.131 -jz4730_cpm_start_lcd(void *cpm) 14.132 +jz4730_cpm_stop_clock(void *cpm, enum Clock_identifiers clock) 14.133 { 14.134 - static_cast<Cpm_jz4730_chip *>(cpm)->start_lcd(); 14.135 -} 14.136 - 14.137 -void 14.138 -jz4730_cpm_stop_lcd(void *cpm) 14.139 -{ 14.140 - static_cast<Cpm_jz4730_chip *>(cpm)->stop_lcd(); 14.141 + static_cast<Cpm_jz4730_chip *>(cpm)->stop_clock(clock); 14.142 } 14.143 14.144 uint32_t
15.1 --- a/pkg/devices/lib/cpm/src/jz4740.cc Sat Jan 16 23:10:48 2021 +0100 15.2 +++ b/pkg/devices/lib/cpm/src/jz4740.cc Sat Jan 16 23:47:39 2021 +0100 15.3 @@ -3,7 +3,7 @@ 15.4 * provided by the jz4740 and related SoCs. The power management 15.5 * functionality could be exposed using a separate driver. 15.6 * 15.7 - * Copyright (C) 2017, 2018 Paul Boddie <paul@boddie.org.uk> 15.8 + * Copyright (C) 2017, 2018, 2021 Paul Boddie <paul@boddie.org.uk> 15.9 * 15.10 * This program is free software; you can redistribute it and/or 15.11 * modify it under the terms of the GNU General Public License as 15.12 @@ -90,16 +90,33 @@ 15.13 15.14 // Clock/timer control. 15.15 15.16 +uint32_t 15.17 +Cpm_jz4740_chip::get_clock_gate_value(enum Clock_identifiers clock) 15.18 +{ 15.19 + switch (clock) 15.20 + { 15.21 + case Clock_lcd: return (1 << Clock_gate_lcd); 15.22 + case Clock_timer: return (1 << Clock_gate_timer); 15.23 + default: return 0; 15.24 + } 15.25 +} 15.26 + 15.27 int 15.28 -Cpm_jz4740_chip::have_clock() 15.29 +Cpm_jz4740_chip::have_clock(enum Clock_identifiers clock) 15.30 { 15.31 - return !(_regs[Clock_gate] & (1 << Clock_gate_timer)); 15.32 + return !(_regs[Clock_gate] & get_clock_gate_value(clock)); 15.33 } 15.34 15.35 void 15.36 -Cpm_jz4740_chip::start_clock() 15.37 +Cpm_jz4740_chip::start_clock(enum Clock_identifiers clock) 15.38 { 15.39 - _regs[Clock_gate] = _regs[Clock_gate] & ~(1 << Clock_gate_timer); 15.40 + _regs[Clock_gate] = _regs[Clock_gate] & ~get_clock_gate_value(clock); 15.41 +} 15.42 + 15.43 +void 15.44 +Cpm_jz4740_chip::stop_clock(enum Clock_identifiers clock) 15.45 +{ 15.46 + _regs[Clock_gate] = _regs[Clock_gate] | get_clock_gate_value(clock); 15.47 } 15.48 15.49 // PLL control. 15.50 @@ -261,22 +278,6 @@ 15.51 15.52 15.53 15.54 -// LCD clock control. 15.55 - 15.56 -void 15.57 -Cpm_jz4740_chip::start_lcd() 15.58 -{ 15.59 - _regs[Clock_gate] = _regs[Clock_gate] & ~(1 << Clock_gate_lcd); 15.60 -} 15.61 - 15.62 -void 15.63 -Cpm_jz4740_chip::stop_lcd() 15.64 -{ 15.65 - _regs[Clock_gate] = _regs[Clock_gate] | (1 << Clock_gate_lcd); 15.66 -} 15.67 - 15.68 - 15.69 - 15.70 uint32_t 15.71 Cpm_jz4740_chip::get_pll_frequency() 15.72 { 15.73 @@ -348,27 +349,21 @@ 15.74 } 15.75 15.76 int 15.77 -jz4740_cpm_have_clock(void *cpm) 15.78 +jz4740_cpm_have_clock(void *cpm, enum Clock_identifiers clock) 15.79 { 15.80 - return static_cast<Cpm_jz4740_chip *>(cpm)->have_clock(); 15.81 + return static_cast<Cpm_jz4740_chip *>(cpm)->have_clock(clock); 15.82 } 15.83 15.84 void 15.85 -jz4740_cpm_start_clock(void *cpm) 15.86 +jz4740_cpm_start_clock(void *cpm, enum Clock_identifiers clock) 15.87 { 15.88 - static_cast<Cpm_jz4740_chip *>(cpm)->start_clock(); 15.89 + static_cast<Cpm_jz4740_chip *>(cpm)->start_clock(clock); 15.90 } 15.91 15.92 void 15.93 -jz4740_cpm_start_lcd(void *cpm) 15.94 +jz4740_cpm_stop_clock(void *cpm, enum Clock_identifiers clock) 15.95 { 15.96 - static_cast<Cpm_jz4740_chip *>(cpm)->start_lcd(); 15.97 -} 15.98 - 15.99 -void 15.100 -jz4740_cpm_stop_lcd(void *cpm) 15.101 -{ 15.102 - static_cast<Cpm_jz4740_chip *>(cpm)->stop_lcd(); 15.103 + static_cast<Cpm_jz4740_chip *>(cpm)->stop_clock(clock); 15.104 } 15.105 15.106 uint32_t
16.1 --- a/pkg/devices/lib/cpm/src/jz4780.cc Sat Jan 16 23:10:48 2021 +0100 16.2 +++ b/pkg/devices/lib/cpm/src/jz4780.cc Sat Jan 16 23:47:39 2021 +0100 16.3 @@ -120,17 +120,8 @@ 16.4 Clock_gate_smb4 = 12, // SMB4 (in CLKGR1) 16.5 Clock_gate_smb3 = 0, // SMB3 (in CLKGR1) 16.6 Clock_gate_smb2 = 25, // SMB2 (in CLKGR0) 16.7 - Clock_gate_smb1 = 6, // SMB2 (in CLKGR0) 16.8 - Clock_gate_smb0 = 5, // SMB2 (in CLKGR0) 16.9 -}; 16.10 - 16.11 -enum Clock_gate_regs : unsigned 16.12 -{ 16.13 - Clock_gate_reg_smb4 = Clock_gate1, 16.14 - Clock_gate_reg_smb3 = Clock_gate1, 16.15 - Clock_gate_reg_smb2 = Clock_gate0, 16.16 - Clock_gate_reg_smb1 = Clock_gate0, 16.17 - Clock_gate_reg_smb0 = Clock_gate0, 16.18 + Clock_gate_smb1 = 6, // SMB1 (in CLKGR0) 16.19 + Clock_gate_smb0 = 5, // SMB0 (in CLKGR0) 16.20 }; 16.21 16.22 enum Divider_bits : unsigned 16.23 @@ -172,19 +163,55 @@ 16.24 } 16.25 16.26 // Clock/timer control. 16.27 -// NOTE: For the time being, assume that the system is configured. 16.28 + 16.29 +uint32_t 16.30 +Cpm_jz4780_chip::get_clock_gate_register(enum Clock_identifiers clock) 16.31 +{ 16.32 + switch (clock) 16.33 + { 16.34 + case Clock_hdmi: return Clock_gate1; 16.35 + case Clock_smb4: return Clock_gate1; 16.36 + case Clock_smb3: return Clock_gate1; 16.37 + default: return Clock_gate0; 16.38 + } 16.39 +} 16.40 + 16.41 +uint32_t 16.42 +Cpm_jz4780_chip::get_clock_gate_value(enum Clock_identifiers clock) 16.43 +{ 16.44 + switch (clock) 16.45 + { 16.46 + case Clock_lcd: return (1 << Clock_gate_lcd1) | (1 << Clock_gate_lcd0); 16.47 + case Clock_hdmi: return (1 << Clock_gate_hdmi); 16.48 + case Clock_smb4: return (1 << Clock_gate_smb4); 16.49 + case Clock_smb3: return (1 << Clock_gate_smb3); 16.50 + case Clock_smb2: return (1 << Clock_gate_smb2); 16.51 + case Clock_smb1: return (1 << Clock_gate_smb1); 16.52 + case Clock_smb0: return (1 << Clock_gate_smb0); 16.53 + default: return 0; 16.54 + } 16.55 +} 16.56 16.57 int 16.58 -Cpm_jz4780_chip::have_clock() 16.59 +Cpm_jz4780_chip::have_clock(enum Clock_identifiers clock) 16.60 { 16.61 - // return !(_regs[Clock_gate] & (1 << Clock_gate_timer)); 16.62 - return 1; 16.63 + return !(_regs[get_clock_gate_register(clock)] & get_clock_gate_value(clock)); 16.64 } 16.65 16.66 void 16.67 -Cpm_jz4780_chip::start_clock() 16.68 +Cpm_jz4780_chip::start_clock(enum Clock_identifiers clock) 16.69 { 16.70 - // _regs[Clock_gate] = _regs[Clock_gate] & ~(1 << Clock_gate_timer); 16.71 + uint32_t gate = get_clock_gate_register(clock); 16.72 + 16.73 + _regs[gate] = _regs[gate] & ~get_clock_gate_value(clock); 16.74 +} 16.75 + 16.76 +void 16.77 +Cpm_jz4780_chip::stop_clock(enum Clock_identifiers clock) 16.78 +{ 16.79 + uint32_t gate = get_clock_gate_register(clock); 16.80 + 16.81 + _regs[gate] = _regs[gate] | get_clock_gate_value(clock); 16.82 } 16.83 16.84 16.85 @@ -431,75 +458,6 @@ 16.86 16.87 16.88 16.89 -// Clock gating control. 16.90 - 16.91 -void 16.92 -Cpm_jz4780_chip::start_hdmi() 16.93 -{ 16.94 - _regs[Clock_gate1] = _regs[Clock_gate1] & ~(1 << Clock_gate_hdmi); 16.95 -} 16.96 - 16.97 -void 16.98 -Cpm_jz4780_chip::stop_hdmi() 16.99 -{ 16.100 - _regs[Clock_gate1] = _regs[Clock_gate1] | (1 << Clock_gate_hdmi); 16.101 -} 16.102 - 16.103 -void 16.104 -Cpm_jz4780_chip::start_lcd() 16.105 -{ 16.106 - // JZ4780 apparently needs LCD0/TVE to be ungated for the LCD peripheral to 16.107 - // work. The Linux 3.0.8 vendor kernel reveals that the TVE clock is actually 16.108 - // LCD0 and that the LCD clock is actually LCD1. 16.109 - 16.110 - // According to the 3.0.8 kernel, LCD1 is the parent of LCD0. However, LCD0 16.111 - // does seem to operate without LCD1 enabled. 16.112 - 16.113 - _regs[Clock_gate0] = _regs[Clock_gate0] & ~(1 << Clock_gate_lcd1); 16.114 - _regs[Clock_gate0] = _regs[Clock_gate0] & ~(1 << Clock_gate_lcd0); 16.115 -} 16.116 - 16.117 -void 16.118 -Cpm_jz4780_chip::stop_lcd() 16.119 -{ 16.120 - _regs[Clock_gate0] = _regs[Clock_gate0] | (1 << Clock_gate_lcd1); 16.121 - _regs[Clock_gate0] = _regs[Clock_gate0] | (1 << Clock_gate_lcd0); 16.122 -} 16.123 - 16.124 -void 16.125 -Cpm_jz4780_chip::_update_i2c(uint8_t channel, int enable) 16.126 -{ 16.127 - uint8_t bit; 16.128 - uint32_t reg; 16.129 - switch (channel) 16.130 - { 16.131 - case 0: bit = Clock_gate_smb0; reg = Clock_gate_reg_smb0; break; 16.132 - case 1: bit = Clock_gate_smb1; reg = Clock_gate_reg_smb1; break; 16.133 - case 2: bit = Clock_gate_smb2; reg = Clock_gate_reg_smb2; break; 16.134 - case 3: bit = Clock_gate_smb3; reg = Clock_gate_reg_smb3; break; 16.135 - case 4: bit = Clock_gate_smb4; reg = Clock_gate_reg_smb4; break; 16.136 - default: return; 16.137 - } 16.138 - if (enable) 16.139 - _regs[reg] = _regs[reg] & ~(1 << bit); 16.140 - else 16.141 - _regs[reg] = _regs[reg] | (1 << bit); 16.142 -} 16.143 - 16.144 -void 16.145 -Cpm_jz4780_chip::start_i2c(uint8_t channel) 16.146 -{ 16.147 - _update_i2c(channel, 1); 16.148 -} 16.149 - 16.150 -void 16.151 -Cpm_jz4780_chip::stop_i2c(uint8_t channel) 16.152 -{ 16.153 - _update_i2c(channel, 0); 16.154 -} 16.155 - 16.156 - 16.157 - 16.158 // Clock sources. 16.159 16.160 uint8_t 16.161 @@ -858,41 +816,21 @@ 16.162 } 16.163 16.164 int 16.165 -jz4780_cpm_have_clock(void *cpm) 16.166 +jz4780_cpm_have_clock(void *cpm, enum Clock_identifiers clock) 16.167 { 16.168 - return static_cast<Cpm_jz4780_chip *>(cpm)->have_clock(); 16.169 + return static_cast<Cpm_jz4780_chip *>(cpm)->have_clock(clock); 16.170 } 16.171 16.172 void 16.173 -jz4780_cpm_start_clock(void *cpm) 16.174 +jz4780_cpm_start_clock(void *cpm, enum Clock_identifiers clock) 16.175 { 16.176 - static_cast<Cpm_jz4780_chip *>(cpm)->start_clock(); 16.177 -} 16.178 - 16.179 - 16.180 - 16.181 -void 16.182 -jz4780_cpm_start_hdmi(void *cpm) 16.183 -{ 16.184 - static_cast<Cpm_jz4780_chip *>(cpm)->start_hdmi(); 16.185 + static_cast<Cpm_jz4780_chip *>(cpm)->start_clock(clock); 16.186 } 16.187 16.188 void 16.189 -jz4780_cpm_stop_hdmi(void *cpm) 16.190 -{ 16.191 - static_cast<Cpm_jz4780_chip *>(cpm)->stop_hdmi(); 16.192 -} 16.193 - 16.194 -void 16.195 -jz4780_cpm_start_lcd(void *cpm) 16.196 +jz4780_cpm_stop_clock(void *cpm, enum Clock_identifiers clock) 16.197 { 16.198 - static_cast<Cpm_jz4780_chip *>(cpm)->start_lcd(); 16.199 -} 16.200 - 16.201 -void 16.202 -jz4780_cpm_stop_lcd(void *cpm) 16.203 -{ 16.204 - static_cast<Cpm_jz4780_chip *>(cpm)->stop_lcd(); 16.205 + static_cast<Cpm_jz4780_chip *>(cpm)->stop_clock(clock); 16.206 } 16.207 16.208
17.1 --- a/pkg/devices/lib/dma/src/jz4730.cc Sat Jan 16 23:10:48 2021 +0100 17.2 +++ b/pkg/devices/lib/dma/src/jz4730.cc Sat Jan 16 23:47:39 2021 +0100 17.3 @@ -406,7 +406,7 @@ 17.4 { 17.5 // Make sure that the DMA clock is available. 17.6 17.7 - _cpm->start_dma(); 17.8 + _cpm->start_clock(Clock_dma); 17.9 17.10 // Enable the channel. 17.11 // NOTE: No configuration is done for channel priority mode.
18.1 --- a/pkg/devices/lib/i2c/src/jz4730.cc Sat Jan 16 23:10:48 2021 +0100 18.2 +++ b/pkg/devices/lib/i2c/src/jz4730.cc Sat Jan 16 23:47:39 2021 +0100 18.3 @@ -89,7 +89,7 @@ 18.4 { 18.5 // Make sure that the I2C clock is available. 18.6 18.7 - _cpm->start_i2c(); 18.8 + _cpm->start_clock(Clock_i2c); 18.9 18.10 // Set the bus clock frequency. 18.11
19.1 --- a/pkg/devices/lib/i2c/src/jz4780.cc Sat Jan 16 23:10:48 2021 +0100 19.2 +++ b/pkg/devices/lib/i2c/src/jz4780.cc Sat Jan 16 23:47:39 2021 +0100 19.3 @@ -1,7 +1,7 @@ 19.4 /* 19.5 * I2C support for the JZ4780. 19.6 * 19.7 - * Copyright (C) 2017, 2018 Paul Boddie <paul@boddie.org.uk> 19.8 + * Copyright (C) 2017, 2018, 2021 Paul Boddie <paul@boddie.org.uk> 19.9 * 19.10 * This program is free software; you can redistribute it and/or 19.11 * modify it under the terms of the GNU General Public License as 19.12 @@ -628,10 +628,11 @@ 19.13 I2c_jz4780_chip::get_channel(uint8_t channel) 19.14 { 19.15 l4_addr_t block = _start + channel * Smb_block_offset; 19.16 + enum Clock_identifiers bits[] = {Clock_smb0, Clock_smb1, Clock_smb2, Clock_smb3, Clock_smb4}; 19.17 19.18 - if (block < _end) 19.19 + if (channel < 5) 19.20 { 19.21 - _cpm->start_i2c(channel); 19.22 + _cpm->start_clock(bits[channel]); 19.23 return new I2c_jz4780_channel(block, _cpm, _frequency); 19.24 } 19.25 else