// SPDX-License-Identifier: GPL-2.0+ /* * Copyright (C) 2016 Nexell Co., Ltd. * * Author: junghyun, kim */ #include #include #include "s5pxx18_soc_disptop_clk.h" #include "s5pxx18_soc_disptop.h" static struct { struct nx_disptop_clkgen_register_set *__g_pregister; } __g_module_variables[NUMBER_OF_DISPTOP_CLKGEN_MODULE] = { { NULL,}, }; int nx_disp_top_clkgen_initialize(void) { static int binit; u32 i; if (binit == 0) { for (i = 0; i < NUMBER_OF_DISPTOP_CLKGEN_MODULE; i++) __g_module_variables[i].__g_pregister = NULL; binit = 1; } return 1; } u32 nx_disp_top_clkgen_get_number_of_module(void) { return NUMBER_OF_DISPTOP_CLKGEN_MODULE; } u32 nx_disp_top_clkgen_get_physical_address(u32 module_index) { static const u32 physical_addr[] = PHY_BASEADDR_DISPTOP_CLKGEN_LIST; return (u32)physical_addr[module_index]; } u32 nx_disp_top_clkgen_get_size_of_register_set(void) { return sizeof(struct nx_disptop_clkgen_register_set); } void nx_disp_top_clkgen_set_base_address(u32 module_index, void *base_address) { __g_module_variables[module_index].__g_pregister = (struct nx_disptop_clkgen_register_set *)base_address; } void *nx_disp_top_clkgen_get_base_address(u32 module_index) { return (void *)__g_module_variables[module_index].__g_pregister; } void nx_disp_top_clkgen_set_clock_bclk_mode(u32 module_index, enum nx_bclkmode mode) { register struct nx_disptop_clkgen_register_set *pregister; register u32 regvalue; u32 clkmode = 0; pregister = __g_module_variables[module_index].__g_pregister; switch (mode) { case nx_bclkmode_disable: clkmode = 0; case nx_bclkmode_dynamic: clkmode = 2; break; case nx_bclkmode_always: clkmode = 3; break; default: break; } regvalue = pregister->clkenb; regvalue &= ~3ul; regvalue |= (clkmode & 0x03); writel(regvalue, &pregister->clkenb); } enum nx_bclkmode nx_disp_top_clkgen_get_clock_bclk_mode(u32 module_index) { register struct nx_disptop_clkgen_register_set *pregister; u32 mode = 0; pregister = __g_module_variables[module_index].__g_pregister; mode = (pregister->clkenb & 3ul); switch (mode) { case 0: return nx_bclkmode_disable; case 2: return nx_bclkmode_dynamic; case 3: return nx_bclkmode_always; default: break; } return nx_bclkmode_disable; } void nx_disp_top_clkgen_set_clock_pclk_mode(u32 module_index, enum nx_pclkmode mode) { register struct nx_disptop_clkgen_register_set *pregister; register u32 regvalue; const u32 pclkmode_pos = 3; u32 clkmode = 0; pregister = __g_module_variables[module_index].__g_pregister; switch (mode) { case nx_pclkmode_dynamic: clkmode = 0; break; case nx_pclkmode_always: clkmode = 1; break; default: break; } regvalue = pregister->clkenb; regvalue &= ~(1ul << pclkmode_pos); regvalue |= (clkmode & 0x01) << pclkmode_pos; writel(regvalue, &pregister->clkenb); } enum nx_pclkmode nx_disp_top_clkgen_get_clock_pclk_mode(u32 module_index) { register struct nx_disptop_clkgen_register_set *pregister; const u32 pclkmode_pos = 3; pregister = __g_module_variables[module_index].__g_pregister; if (pregister->clkenb & (1ul << pclkmode_pos)) return nx_pclkmode_always; return nx_pclkmode_dynamic; } void nx_disp_top_clkgen_set_clock_source(u32 module_index, u32 index, u32 clk_src) { register struct nx_disptop_clkgen_register_set *pregister; register u32 read_value; const u32 clksrcsel_pos = 2; const u32 clksrcsel_mask = 0x07 << clksrcsel_pos; pregister = __g_module_variables[module_index].__g_pregister; read_value = pregister->CLKGEN[index << 1]; read_value &= ~clksrcsel_mask; read_value |= clk_src << clksrcsel_pos; writel(read_value, &pregister->CLKGEN[index << 1]); } u32 nx_disp_top_clkgen_get_clock_source(u32 module_index, u32 index) { register struct nx_disptop_clkgen_register_set *pregister; const u32 clksrcsel_pos = 2; const u32 clksrcsel_mask = 0x07 << clksrcsel_pos; pregister = __g_module_variables[module_index].__g_pregister; return (pregister->CLKGEN[index << 1] & clksrcsel_mask) >> clksrcsel_pos; } void nx_disp_top_clkgen_set_clock_divisor(u32 module_index, u32 index, u32 divisor) { register struct nx_disptop_clkgen_register_set *pregister; const u32 clkdiv_pos = 5; const u32 clkdiv_mask = 0xff << clkdiv_pos; register u32 read_value; pregister = __g_module_variables[module_index].__g_pregister; read_value = pregister->CLKGEN[index << 1]; read_value &= ~clkdiv_mask; read_value |= (divisor - 1) << clkdiv_pos; writel(read_value, &pregister->CLKGEN[index << 1]); } u32 nx_disp_top_clkgen_get_clock_divisor(u32 module_index, u32 index) { register struct nx_disptop_clkgen_register_set *pregister; const u32 clkdiv_pos = 5; const u32 clkdiv_mask = 0xff << clkdiv_pos; pregister = __g_module_variables[module_index].__g_pregister; return ((pregister->CLKGEN[index << 1] & clkdiv_mask) >> clkdiv_pos) + 1; } void nx_disp_top_clkgen_set_clock_divisor_enable(u32 module_index, int enable) { register struct nx_disptop_clkgen_register_set *pregister; register u32 read_value; const u32 clkgenenb_pos = 2; const u32 clkgenenb_mask = 1ul << clkgenenb_pos; pregister = __g_module_variables[module_index].__g_pregister; read_value = pregister->clkenb; read_value &= ~clkgenenb_mask; read_value |= (u32)enable << clkgenenb_pos; writel(read_value, &pregister->clkenb); } int nx_disp_top_clkgen_get_clock_divisor_enable(u32 module_index) { register struct nx_disptop_clkgen_register_set *pregister; const u32 clkgenenb_pos = 2; const u32 clkgenenb_mask = 1ul << clkgenenb_pos; pregister = __g_module_variables[module_index].__g_pregister; return (int)((pregister->clkenb & clkgenenb_mask) >> clkgenenb_pos); } void nx_disp_top_clkgen_set_clock_out_inv(u32 module_index, u32 index, int out_clk_inv) { register struct nx_disptop_clkgen_register_set *pregister; register u32 read_value; const u32 outclkinv_pos = 1; const u32 outclkinv_mask = 1ul << outclkinv_pos; pregister = __g_module_variables[module_index].__g_pregister; read_value = pregister->CLKGEN[index << 1]; read_value &= ~outclkinv_mask; read_value |= out_clk_inv << outclkinv_pos; writel(read_value, &pregister->CLKGEN[index << 1]); } int nx_disp_top_clkgen_get_clock_out_inv(u32 module_index, u32 index) { register struct nx_disptop_clkgen_register_set *pregister; const u32 outclkinv_pos = 1; const u32 outclkinv_mask = 1ul << outclkinv_pos; pregister = __g_module_variables[module_index].__g_pregister; return (int)((pregister->CLKGEN[index << 1] & outclkinv_mask) >> outclkinv_pos); } int nx_disp_top_clkgen_set_input_inv(u32 module_index, u32 index, int in_clk_inv) { register struct nx_disptop_clkgen_register_set *pregister; register u32 read_value; const u32 inclkinv_pos = 4 + index; const u32 inclkinv_mask = 1ul << inclkinv_pos; pregister = __g_module_variables[module_index].__g_pregister; read_value = pregister->clkenb; read_value &= ~inclkinv_mask; read_value |= in_clk_inv << inclkinv_pos; writel(read_value, &pregister->clkenb); return true; } int nx_disp_top_clkgen_get_input_inv(u32 module_index, u32 index) { register struct nx_disptop_clkgen_register_set *pregister; const u32 inclkinv_pos = 4 + index; const u32 inclkinv_mask = 1ul << inclkinv_pos; pregister = __g_module_variables[module_index].__g_pregister; return (int)((pregister->clkenb & inclkinv_mask) >> inclkinv_pos); } void nx_disp_top_clkgen_set_clock_out_select(u32 module_index, u32 index, int bbypass) { register struct nx_disptop_clkgen_register_set *pregister; register u32 read_value; pregister = __g_module_variables[module_index].__g_pregister; read_value = pregister->CLKGEN[index << 1]; read_value = read_value & (~0x01); read_value = read_value | bbypass; writel(read_value, &pregister->CLKGEN[index << 1]); }