summaryrefslogtreecommitdiff
path: root/drivers/video/nexell/soc/s5pxx18_soc_disptop_clk.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/video/nexell/soc/s5pxx18_soc_disptop_clk.c')
-rw-r--r--drivers/video/nexell/soc/s5pxx18_soc_disptop_clk.c309
1 files changed, 309 insertions, 0 deletions
diff --git a/drivers/video/nexell/soc/s5pxx18_soc_disptop_clk.c b/drivers/video/nexell/soc/s5pxx18_soc_disptop_clk.c
new file mode 100644
index 0000000000..02361ba411
--- /dev/null
+++ b/drivers/video/nexell/soc/s5pxx18_soc_disptop_clk.c
@@ -0,0 +1,309 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2016 Nexell Co., Ltd.
+ *
+ * Author: junghyun, kim <jhkim@nexell.co.kr>
+ */
+
+#include <linux/types.h>
+#include <linux/io.h>
+
+#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]);
+}