1 /* 2 * Copyright (C) 2017, 2018, 2020 Paul Boddie <paul@boddie.org.uk> 3 * 4 * This program is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU General Public License as 6 * published by the Free Software Foundation; either version 2 of 7 * the License, or (at your option) any later version. 8 * 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with this program; if not, write to the Free Software 16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, 17 * Boston, MA 02110-1301, USA 18 */ 19 20 #pragma once 21 22 #include "cpm.h" 23 24 #include <l4/sys/types.h> 25 #include <stdint.h> 26 27 28 29 #ifdef __cplusplus 30 31 #include <l4/devices/hw_register_block.h> 32 33 /* A simple abstraction for accessing the CPM registers. 34 * A proper device could inherit from Hw::Device and use an 35 * Int_property for _exclk_freq and _rtclk_freq. */ 36 37 class Cpm_jz4780_chip : public Cpm_chip 38 { 39 private: 40 Hw::Register_block<32> _regs; 41 uint32_t _exclk_freq, _rtclk_freq; 42 43 // Utility methods. 44 45 uint32_t get_field(uint32_t reg, uint32_t mask, uint8_t shift); 46 void set_field(uint32_t reg, uint32_t mask, uint8_t shift, uint32_t value); 47 uint8_t _get_divider(uint32_t reg, uint32_t mask, uint8_t shift); 48 49 // PLL control. 50 51 int have_pll(uint32_t pll_reg); 52 int pll_enabled(uint32_t pll_reg); 53 int pll_bypassed(uint32_t pll_reg); 54 void pll_disable(uint32_t pll_reg); 55 void pll_enable(uint32_t pll_reg); 56 57 // General frequency modifiers. 58 59 uint16_t get_multiplier(uint32_t pll_reg); 60 void set_multiplier(uint32_t pll_reg, uint16_t multiplier); 61 uint8_t get_input_division(uint32_t pll_reg); 62 void set_input_division(uint32_t pll_reg, uint8_t divider); 63 uint8_t get_output_division(uint32_t pll_reg); 64 void set_output_division(uint32_t pll_reg, uint8_t divider); 65 66 // Clock dividers. 67 68 void set_hdmi_divider(uint16_t division); 69 void set_lcd_pixel_divider(uint8_t controller, uint16_t division); 70 71 // Clock control. 72 73 void _update_i2c(uint8_t channel, int enable); 74 75 // Input frequencies. 76 77 uint32_t get_pll_frequency(uint32_t pll_reg); 78 79 // Clock sources. 80 81 void set_hclock2_source(uint8_t source); 82 void set_hdmi_source(uint8_t source); 83 void set_lcd_source(uint8_t controller, uint8_t source); 84 85 public: 86 void set_pclock_source(uint8_t source); 87 Cpm_jz4780_chip(l4_addr_t addr, uint32_t exclk_freq, uint32_t rtclk_freq); 88 89 int have_clock(); 90 void start_clock(); 91 92 // Clock divider values. 93 94 uint8_t get_cpu_divider(); 95 uint8_t get_hclock0_divider(); 96 uint8_t get_hclock2_divider(); 97 uint8_t get_pclock_divider(); 98 uint8_t get_hdmi_divider(); 99 uint8_t get_lcd_pixel_divider(uint8_t controller = 0); 100 uint8_t get_memory_divider(); 101 102 // Clock control. 103 104 void start_hdmi(); 105 void stop_hdmi(); 106 107 void start_lcd(); 108 void stop_lcd(); 109 110 void start_i2c(uint8_t channel); 111 void stop_i2c(uint8_t channel); 112 113 // Input frequencies. 114 115 uint8_t get_main_source(); 116 uint32_t get_main_frequency(); 117 118 // Clock sources, providing the input frequency. 119 120 uint8_t get_cpu_source(); 121 uint8_t get_hclock0_source(); 122 uint8_t get_hclock2_source(); 123 uint8_t get_hdmi_source(); 124 uint8_t get_lcd_source(uint8_t controller); 125 uint8_t get_lcd_source() { return get_lcd_source(0); } 126 uint8_t get_memory_source(); 127 uint8_t get_pclock_source(); 128 129 uint32_t get_cpu_source_frequency(); 130 uint32_t get_hclock0_source_frequency(); 131 uint32_t get_hclock2_source_frequency(); 132 uint32_t get_hdmi_source_frequency(); 133 uint32_t get_lcd_source_frequency(uint8_t controller); 134 uint32_t get_lcd_source_frequency() { return get_lcd_source_frequency(0); } 135 uint32_t get_memory_source_frequency(); 136 uint32_t get_pclock_source_frequency(); 137 138 // Final, calculated frequencies. 139 140 uint32_t get_cpu_frequency(); 141 uint32_t get_hclock0_frequency(); 142 uint32_t get_hclock2_frequency(); 143 uint32_t get_hdmi_frequency(); 144 uint32_t get_lcd_pixel_frequency(uint8_t controller); 145 uint32_t get_lcd_pixel_frequency() { return get_lcd_pixel_frequency(0); } 146 uint32_t get_memory_frequency(); 147 uint32_t get_pclock_frequency(); 148 149 uint32_t get_apll_frequency(); 150 uint32_t get_epll_frequency(); 151 uint32_t get_mpll_frequency(); 152 uint32_t get_vpll_frequency(); 153 154 void set_hdmi_frequency(uint32_t pclk); 155 void set_lcd_pixel_frequency(uint32_t pclk); 156 void set_lcd_frequencies(uint32_t pclk, uint8_t multiplier); 157 void set_pll_parameters(uint32_t pll_reg, uint16_t multiplier, uint8_t in_divider, uint8_t out_divider); 158 159 void update_output_frequency(); 160 }; 161 162 #endif /* __cplusplus */ 163 164 165 166 /* C language interface. */ 167 168 EXTERN_C_BEGIN 169 170 void *jz4780_cpm_init(l4_addr_t cpm_base); 171 172 int jz4780_cpm_have_clock(void *cpm); 173 void jz4780_cpm_start_clock(void *cpm); 174 175 void jz4780_cpm_start_hdmi(void *cpm); 176 void jz4780_cpm_stop_hdmi(void *cpm); 177 178 void jz4780_cpm_start_lcd(void *cpm); 179 void jz4780_cpm_stop_lcd(void *cpm); 180 181 uint8_t jz4780_cpm_get_cpu_divider(void *cpm); 182 uint8_t jz4780_cpm_get_hclock0_divider(void *cpm); 183 uint8_t jz4780_cpm_get_hclock2_divider(void *cpm); 184 uint8_t jz4780_cpm_get_hdmi_divider(void *cpm); 185 uint8_t jz4780_cpm_get_lcd_pixel_divider(void *cpm); 186 uint8_t jz4780_cpm_get_memory_divider(void *cpm); 187 uint8_t jz4780_cpm_get_pclock_divider(void *cpm); 188 189 uint8_t jz4780_cpm_get_hclock0_source(void *cpm); 190 uint8_t jz4780_cpm_get_hclock2_source(void *cpm); 191 uint8_t jz4780_cpm_get_hdmi_source(void *cpm); 192 uint8_t jz4780_cpm_get_lcd_source(void *cpm); 193 uint8_t jz4780_cpm_get_memory_source(void *cpm); 194 uint8_t jz4780_cpm_get_pclock_source(void *cpm); 195 196 uint32_t jz4780_cpm_get_hclock0_source_frequency(void *cpm); 197 uint32_t jz4780_cpm_get_hclock2_source_frequency(void *cpm); 198 uint32_t jz4780_cpm_get_hdmi_source_frequency(void *cpm); 199 uint32_t jz4780_cpm_get_lcd_source_frequency(void *cpm); 200 uint32_t jz4780_cpm_get_memory_source_frequency(void *cpm); 201 uint32_t jz4780_cpm_get_pclock_source_frequency(void *cpm); 202 203 void jz4780_cpm_set_pclock_source(void *cpm, uint8_t source); 204 205 uint8_t jz4780_cpm_get_main_source(void *cpm); 206 uint32_t jz4780_cpm_get_main_frequency(void *cpm); 207 208 uint32_t jz4780_cpm_get_cpu_frequency(void *cpm); 209 uint32_t jz4780_cpm_get_hclock0_frequency(void *cpm); 210 uint32_t jz4780_cpm_get_hclock2_frequency(void *cpm); 211 uint32_t jz4780_cpm_get_hdmi_frequency(void *cpm); 212 uint32_t jz4780_cpm_get_lcd_pixel_frequency(void *cpm); 213 uint32_t jz4780_cpm_get_memory_frequency(void *cpm); 214 uint32_t jz4780_cpm_get_pclock_frequency(void *cpm); 215 216 uint32_t jz4780_cpm_get_apll_frequency(void *cpm); 217 uint32_t jz4780_cpm_get_epll_frequency(void *cpm); 218 uint32_t jz4780_cpm_get_mpll_frequency(void *cpm); 219 uint32_t jz4780_cpm_get_vpll_frequency(void *cpm); 220 221 void jz4780_cpm_set_hdmi_frequency(void *cpm, uint32_t pclk); 222 void jz4780_cpm_set_lcd_pixel_frequency(void *cpm, uint32_t pclk); 223 void jz4780_cpm_set_lcd_frequencies(void *cpm, uint32_t pclk, uint8_t ratio); 224 void jz4780_cpm_set_mpll_parameters(void *cpm, uint16_t multiplier, uint8_t in_divider, uint8_t out_divider); 225 226 EXTERN_C_END