1// SPDX-License-Identifier: GPL-2.0+ 2/* 3 * Copyright (C) 2016 Nexell Co., Ltd. 4 * 5 * Author: junghyun, kim <jhkim@nexell.co.kr> 6 */ 7 8#include <linux/types.h> 9#include <linux/io.h> 10 11#include "s5pxx18_soc_disptop_clk.h" 12#include "s5pxx18_soc_disptop.h" 13 14static struct { 15 struct nx_disptop_clkgen_register_set *__g_pregister; 16} __g_module_variables[NUMBER_OF_DISPTOP_CLKGEN_MODULE] = { 17 { NULL,}, 18}; 19 20int nx_disp_top_clkgen_initialize(void) 21{ 22 static int binit; 23 u32 i; 24 25 if (binit == 0) { 26 for (i = 0; i < NUMBER_OF_DISPTOP_CLKGEN_MODULE; i++) 27 __g_module_variables[i].__g_pregister = NULL; 28 binit = 1; 29 } 30 return 1; 31} 32 33u32 nx_disp_top_clkgen_get_number_of_module(void) 34{ 35 return NUMBER_OF_DISPTOP_CLKGEN_MODULE; 36} 37 38u32 nx_disp_top_clkgen_get_physical_address(u32 module_index) 39{ 40 static const u32 physical_addr[] = 41 PHY_BASEADDR_DISPTOP_CLKGEN_LIST; 42 43 return (u32)physical_addr[module_index]; 44} 45 46u32 nx_disp_top_clkgen_get_size_of_register_set(void) 47{ 48 return sizeof(struct nx_disptop_clkgen_register_set); 49} 50 51void nx_disp_top_clkgen_set_base_address(u32 module_index, void *base_address) 52{ 53 __g_module_variables[module_index].__g_pregister = 54 (struct nx_disptop_clkgen_register_set *)base_address; 55} 56 57void *nx_disp_top_clkgen_get_base_address(u32 module_index) 58{ 59 return (void *)__g_module_variables[module_index].__g_pregister; 60} 61 62void nx_disp_top_clkgen_set_clock_bclk_mode(u32 module_index, 63 enum nx_bclkmode mode) 64{ 65 register struct nx_disptop_clkgen_register_set *pregister; 66 register u32 regvalue; 67 u32 clkmode = 0; 68 69 pregister = __g_module_variables[module_index].__g_pregister; 70 switch (mode) { 71 case nx_bclkmode_disable: 72 clkmode = 0; 73 case nx_bclkmode_dynamic: 74 clkmode = 2; 75 break; 76 case nx_bclkmode_always: 77 clkmode = 3; 78 break; 79 default: 80 break; 81 } 82 83 regvalue = pregister->clkenb; 84 regvalue &= ~3ul; 85 regvalue |= (clkmode & 0x03); 86 87 writel(regvalue, &pregister->clkenb); 88} 89 90enum nx_bclkmode nx_disp_top_clkgen_get_clock_bclk_mode(u32 module_index) 91{ 92 register struct nx_disptop_clkgen_register_set *pregister; 93 u32 mode = 0; 94 95 pregister = __g_module_variables[module_index].__g_pregister; 96 mode = (pregister->clkenb & 3ul); 97 98 switch (mode) { 99 case 0: 100 return nx_bclkmode_disable; 101 case 2: 102 return nx_bclkmode_dynamic; 103 case 3: 104 return nx_bclkmode_always; 105 default: 106 break; 107 } 108 return nx_bclkmode_disable; 109} 110 111void nx_disp_top_clkgen_set_clock_pclk_mode(u32 module_index, 112 enum nx_pclkmode mode) 113{ 114 register struct nx_disptop_clkgen_register_set *pregister; 115 register u32 regvalue; 116 const u32 pclkmode_pos = 3; 117 u32 clkmode = 0; 118 119 pregister = __g_module_variables[module_index].__g_pregister; 120 switch (mode) { 121 case nx_pclkmode_dynamic: 122 clkmode = 0; 123 break; 124 case nx_pclkmode_always: 125 clkmode = 1; 126 break; 127 default: 128 break; 129 } 130 131 regvalue = pregister->clkenb; 132 regvalue &= ~(1ul << pclkmode_pos); 133 regvalue |= (clkmode & 0x01) << pclkmode_pos; 134 135 writel(regvalue, &pregister->clkenb); 136} 137 138enum nx_pclkmode nx_disp_top_clkgen_get_clock_pclk_mode(u32 module_index) 139{ 140 register struct nx_disptop_clkgen_register_set *pregister; 141 const u32 pclkmode_pos = 3; 142 143 pregister = __g_module_variables[module_index].__g_pregister; 144 145 if (pregister->clkenb & (1ul << pclkmode_pos)) 146 return nx_pclkmode_always; 147 148 return nx_pclkmode_dynamic; 149} 150 151void nx_disp_top_clkgen_set_clock_source(u32 module_index, u32 index, 152 u32 clk_src) 153{ 154 register struct nx_disptop_clkgen_register_set *pregister; 155 register u32 read_value; 156 157 const u32 clksrcsel_pos = 2; 158 const u32 clksrcsel_mask = 0x07 << clksrcsel_pos; 159 160 pregister = __g_module_variables[module_index].__g_pregister; 161 162 read_value = pregister->CLKGEN[index << 1]; 163 read_value &= ~clksrcsel_mask; 164 read_value |= clk_src << clksrcsel_pos; 165 166 writel(read_value, &pregister->CLKGEN[index << 1]); 167} 168 169u32 nx_disp_top_clkgen_get_clock_source(u32 module_index, u32 index) 170{ 171 register struct nx_disptop_clkgen_register_set *pregister; 172 const u32 clksrcsel_pos = 2; 173 const u32 clksrcsel_mask = 0x07 << clksrcsel_pos; 174 175 pregister = __g_module_variables[module_index].__g_pregister; 176 177 return (pregister->CLKGEN[index << 1] & 178 clksrcsel_mask) >> clksrcsel_pos; 179} 180 181void nx_disp_top_clkgen_set_clock_divisor(u32 module_index, u32 index, 182 u32 divisor) 183{ 184 register struct nx_disptop_clkgen_register_set *pregister; 185 const u32 clkdiv_pos = 5; 186 const u32 clkdiv_mask = 0xff << clkdiv_pos; 187 register u32 read_value; 188 189 pregister = __g_module_variables[module_index].__g_pregister; 190 191 read_value = pregister->CLKGEN[index << 1]; 192 read_value &= ~clkdiv_mask; 193 read_value |= (divisor - 1) << clkdiv_pos; 194 writel(read_value, &pregister->CLKGEN[index << 1]); 195} 196 197u32 nx_disp_top_clkgen_get_clock_divisor(u32 module_index, u32 index) 198{ 199 register struct nx_disptop_clkgen_register_set *pregister; 200 const u32 clkdiv_pos = 5; 201 const u32 clkdiv_mask = 0xff << clkdiv_pos; 202 203 pregister = __g_module_variables[module_index].__g_pregister; 204 205 return ((pregister->CLKGEN[index << 1] & 206 clkdiv_mask) >> clkdiv_pos) + 1; 207} 208 209void nx_disp_top_clkgen_set_clock_divisor_enable(u32 module_index, int enable) 210{ 211 register struct nx_disptop_clkgen_register_set *pregister; 212 register u32 read_value; 213 const u32 clkgenenb_pos = 2; 214 const u32 clkgenenb_mask = 1ul << clkgenenb_pos; 215 216 pregister = __g_module_variables[module_index].__g_pregister; 217 218 read_value = pregister->clkenb; 219 read_value &= ~clkgenenb_mask; 220 read_value |= (u32)enable << clkgenenb_pos; 221 222 writel(read_value, &pregister->clkenb); 223} 224 225int nx_disp_top_clkgen_get_clock_divisor_enable(u32 module_index) 226{ 227 register struct nx_disptop_clkgen_register_set *pregister; 228 const u32 clkgenenb_pos = 2; 229 const u32 clkgenenb_mask = 1ul << clkgenenb_pos; 230 231 pregister = __g_module_variables[module_index].__g_pregister; 232 233 return (int)((pregister->clkenb & 234 clkgenenb_mask) >> clkgenenb_pos); 235} 236 237void nx_disp_top_clkgen_set_clock_out_inv(u32 module_index, u32 index, 238 int out_clk_inv) 239{ 240 register struct nx_disptop_clkgen_register_set *pregister; 241 register u32 read_value; 242 const u32 outclkinv_pos = 1; 243 const u32 outclkinv_mask = 1ul << outclkinv_pos; 244 245 pregister = __g_module_variables[module_index].__g_pregister; 246 247 read_value = pregister->CLKGEN[index << 1]; 248 read_value &= ~outclkinv_mask; 249 read_value |= out_clk_inv << outclkinv_pos; 250 251 writel(read_value, &pregister->CLKGEN[index << 1]); 252} 253 254int nx_disp_top_clkgen_get_clock_out_inv(u32 module_index, u32 index) 255{ 256 register struct nx_disptop_clkgen_register_set *pregister; 257 const u32 outclkinv_pos = 1; 258 const u32 outclkinv_mask = 1ul << outclkinv_pos; 259 260 pregister = __g_module_variables[module_index].__g_pregister; 261 262 return (int)((pregister->CLKGEN[index << 1] & 263 outclkinv_mask) >> outclkinv_pos); 264} 265 266int nx_disp_top_clkgen_set_input_inv(u32 module_index, 267 u32 index, int in_clk_inv) 268{ 269 register struct nx_disptop_clkgen_register_set *pregister; 270 register u32 read_value; 271 const u32 inclkinv_pos = 4 + index; 272 const u32 inclkinv_mask = 1ul << inclkinv_pos; 273 274 pregister = __g_module_variables[module_index].__g_pregister; 275 276 read_value = pregister->clkenb; 277 read_value &= ~inclkinv_mask; 278 read_value |= in_clk_inv << inclkinv_pos; 279 280 writel(read_value, &pregister->clkenb); 281 return true; 282} 283 284int nx_disp_top_clkgen_get_input_inv(u32 module_index, u32 index) 285{ 286 register struct nx_disptop_clkgen_register_set *pregister; 287 const u32 inclkinv_pos = 4 + index; 288 const u32 inclkinv_mask = 1ul << inclkinv_pos; 289 290 pregister = __g_module_variables[module_index].__g_pregister; 291 292 return (int)((pregister->clkenb & 293 inclkinv_mask) >> inclkinv_pos); 294} 295 296void nx_disp_top_clkgen_set_clock_out_select(u32 module_index, u32 index, 297 int bbypass) 298{ 299 register struct nx_disptop_clkgen_register_set *pregister; 300 register u32 read_value; 301 302 pregister = __g_module_variables[module_index].__g_pregister; 303 304 read_value = pregister->CLKGEN[index << 1]; 305 read_value = read_value & (~0x01); 306 read_value = read_value | bbypass; 307 308 writel(read_value, &pregister->CLKGEN[index << 1]); 309} 310