diff options
author | Chanho Park <chanho61.park@samsung.com> | 2016-11-09 04:39:36 +0900 |
---|---|---|
committer | Chanho Park <chanho61.park@samsung.com> | 2016-11-09 05:36:40 +0900 |
commit | ca2917c547c5edeec72d2831d003a1420158dda1 (patch) | |
tree | bcf35fdb37c4a5e2794470eccb7783c7ba96617b | |
parent | ce3b790afccaf9dae6e79658f388b1ab2b722141 (diff) | |
download | linux-artik7-ca2917c547c5edeec72d2831d003a1420158dda1.tar.gz linux-artik7-ca2917c547c5edeec72d2831d003a1420158dda1.tar.bz2 linux-artik7-ca2917c547c5edeec72d2831d003a1420158dda1.zip |
clk: nexell: consolidate s5p6818 and s5p4418 pll clock
This patch consolidates s5p4418 and s5p6818 pll clock
to reduce duplicated codes and to maintain more easily.
Change-Id: I3b55a9dab71a93bba6b9e4f31108fc921e1a0de4
Signed-off-by: Chanho Park <chanho61.park@samsung.com>
-rw-r--r-- | Documentation/devicetree/bindings/clock/nexell-pll.txt | 10 | ||||
-rw-r--r-- | drivers/clk/nexell/Makefile | 3 | ||||
-rw-r--r-- | drivers/clk/nexell/clk-s5p4418-pll.c | 704 | ||||
-rw-r--r-- | drivers/clk/nexell/clk-s5p6818-pll.h | 80 | ||||
-rw-r--r-- | drivers/clk/nexell/clk-s5pxx18-pll.c (renamed from drivers/clk/nexell/clk-s5p6818-pll.c) | 86 | ||||
-rw-r--r-- | drivers/clk/nexell/clk-s5pxx18-pll.h (renamed from drivers/clk/nexell/clk-s5p4418-pll.h) | 0 |
6 files changed, 90 insertions, 793 deletions
diff --git a/Documentation/devicetree/bindings/clock/nexell-pll.txt b/Documentation/devicetree/bindings/clock/nexell-pll.txt index 61d4b647fe84..d26b9a1f25f0 100644 --- a/Documentation/devicetree/bindings/clock/nexell-pll.txt +++ b/Documentation/devicetree/bindings/clock/nexell-pll.txt @@ -1,18 +1,18 @@ -* Nxell s5p16818 PLL Controller +* Nexell s5pxx18 PLL Controller -The S5p6818 PLL controller within the s5p6818 SoC. -S5p6818 support 5 PLLs (PLL0, 1, 2 ,3) +The S5pxx18 PLL controller within the s5p4418 and s5p6818 SoC. +S5pxx18 support 5 PLLs (PLL0, 1, 2 ,3) Required Properties: -- compatible: should be "nexell,s5p6818-pll". +- compatible: should be "nexell,s5pxx18-pll". - ref-freuecny: Input oscillator clock Hz. - reg: physical base address of the controller and length of memory mapped region. Example: An example of a clock controller node is listed below. refclk:oscillator { - compatible = "nexell,s5p6818,pll"; + compatible = "nexell,s5pxx18,pll"; ref-freuecny = <24000000>; }; diff --git a/drivers/clk/nexell/Makefile b/drivers/clk/nexell/Makefile index 4c2a08e98392..fb215eed3ae0 100644 --- a/drivers/clk/nexell/Makefile +++ b/drivers/clk/nexell/Makefile @@ -1,2 +1 @@ -obj-$(CONFIG_ARCH_S5P6818) += clk-s5pxx18.o clk-s5p6818-pll.o -obj-$(CONFIG_ARCH_S5P4418) += clk-s5pxx18.o clk-s5p4418-pll.o +obj-y += clk-s5pxx18.o clk-s5pxx18-pll.o diff --git a/drivers/clk/nexell/clk-s5p4418-pll.c b/drivers/clk/nexell/clk-s5p4418-pll.c deleted file mode 100644 index 790f0b9b3889..000000000000 --- a/drivers/clk/nexell/clk-s5p4418-pll.c +++ /dev/null @@ -1,704 +0,0 @@ -/* - * Copyright (C) 2016 Nexell Co., Ltd. - * Author: Youngbok, Park <ybpark@nexell.co.kr> - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#include <linux/clk.h> -#include <linux/clkdev.h> -#include <linux/clk-provider.h> -#include <linux/err.h> -#include <linux/delay.h> -#include <linux/io.h> -#include <linux/of.h> -#include <linux/of_address.h> -#include <asm/tlbflush.h> -#include "clk-s5pxx18.h" -#include "clk-s5p4418-pll.h" - -#define PLL_LOCKING_TIME 100 - -struct pll_pms { - long rate; /* unint Khz */ - int P; - int M; - int S; -}; - -struct clk_core { - const char *name; - int id, div, pll; - unsigned long rate; - struct clk_hw hw; - struct pll_pms pms; -}; - -/* PLL 0,1 */ -static struct pll_pms pll0_1_pms[] = { - [0] = { - .rate = 1200000, .P = 3, .M = 300, .S = 1, - }, - [1] = { - .rate = 1100000, .P = 3, .M = 275, .S = 1, - }, - [2] = { - .rate = 1000000, .P = 3, .M = 250, .S = 1, - }, - [3] = { - .rate = 900000, .P = 3, .M = 225, .S = 1, - }, - [4] = { - .rate = 800000, .P = 3, .M = 200, .S = 1, - }, - [5] = { - .rate = 700000, .P = 3, .M = 175, .S = 1, - }, - [6] = { - .rate = 600000, .P = 2, .M = 200, .S = 2, - }, - [7] = { - .rate = 500000, .P = 3, .M = 250, .S = 2, - }, - [8] = { - .rate = 400000, .P = 3, .M = 200, .S = 2, - }, - [9] = { - .rate = 300000, .P = 2, .M = 200, .S = 3, - }, - [10] = { - .rate = 200000, .P = 3, .M = 200, .S = 3, - }, - [11] = { - .rate = 100000, .P = 3, .M = 200, .S = 4, - }, -}; - -/* PLL 2,3 */ -static struct pll_pms pll2_3_pms[] = { - [0] = { - .rate = 1200000, .P = 3, .M = 300, .S = 1, - }, - [1] = { - .rate = 1100000, .P = 3, .M = 275, .S = 1, - }, - [2] = { - .rate = 1000000, .P = 3, .M = 250, .S = 1, - }, - [3] = { - .rate = 900000, .P = 3, .M = 225, .S = 1, - }, - [4] = { - .rate = 800000, .P = 3, .M = 200, .S = 1, - }, - [5] = { - .rate = 700000, .P = 3, .M = 175, .S = 1, - }, - [6] = { - .rate = 600000, .P = 3, .M = 150, .S = 1, - }, - [7] = { - .rate = 500000, .P = 3, .M = 250, .S = 2, - }, - [8] = { - .rate = 400000, .P = 3, .M = 200, .S = 2, - }, - [9] = { - .rate = 300000, .P = 3, .M = 150, .S = 2, - }, - [10] = { - .rate = 200000, .P = 3, .M = 200, .S = 3, - }, - [11] = { - .rate = 100000, .P = 3, .M = 200, .S = 4, - }, -}; - -#define PLL0_1_SIZE ARRAY_SIZE(pll0_1_pms) -#define PLL2_3_SIZE ARRAY_SIZE(pll2_3_pms) - -#define PMS_RATE(p, i) ((&p[i])->rate) -#define PMS_P(p, i) ((&p[i])->P) -#define PMS_M(p, i) ((&p[i])->M) -#define PMS_S(p, i) ((&p[i])->S) - -#define PLL_S_BITPOS 0 -#define PLL_M_BITPOS 8 -#define PLL_P_BITPOS 18 - -static void *ref_clk_base; -static spinlock_t pll_lock = __SPIN_LOCK_UNLOCKED(pll_lock); - -static void pll_set_rate(int PLL, int P, int M, int S) -{ - struct reg_clkpwr *reg = ref_clk_base; - unsigned long flags; - - spin_lock_irqsave(&pll_lock, flags); - - /* - * 1. change PLL0 clock to Oscillator Clock - */ - reg->PLLSETREG[PLL] &= ~(1 << 28); /* pll bypass on, xtal clock use */ - reg->CLKMODEREG0 = (1 << PLL); /* update pll */ - - while (readl(®->CLKMODEREG0) & (1 << 31)) - ;/* wait for change update pll*/ - - /* - * 2. PLL Power Down & PMS value setting - */ - reg->PLLSETREG[PLL] = - ((1UL << 29 | /* power down */ - (0UL << 28) | /* clock bypass on, xtal clock use */ - (S << PLL_S_BITPOS) | - (M << PLL_M_BITPOS) | - (P << PLL_P_BITPOS))); - reg->CLKMODEREG0 = (1 << PLL); /* update pll */ - - while (readl(®->CLKMODEREG0) & (1 << 31)) - ; /* wait for change update pll */ - - udelay(10); - - /* - * 3. Update PLL & wait PLL locking - */ - reg->PLLSETREG[PLL] &= ~((u32)(1UL << 29));/* pll power up */ - reg->CLKMODEREG0 = (1 << PLL); /* update pll */ - - while (readl(®->CLKMODEREG0) & (1 << 31)) - ;/* wait for change update pll */ - - udelay(PLL_LOCKING_TIME);/* 1000us */ - - /* - * 4. Change to PLL clock - */ - reg->PLLSETREG[PLL] |= (1 << 28);/* pll bypass off, pll clock use */ - reg->CLKMODEREG0 = (1 << PLL); /* update pll */ - - while (readl(®->CLKMODEREG0) & (1 << 31)) - ;/* wait for change update pll */ - spin_unlock_irqrestore(&pll_lock, flags); -} - -static unsigned long pll_round_rate(int pllno, unsigned long rate, int *p, - int *m, int *s) -{ - struct pll_pms *pms; - int len, idx = 0, n = 0, l = 0; - long freq = 0; - - rate /= 1000; - pr_debug("PLL.%d, %ld", pllno, rate); - - switch (pllno) { - case 0: - case 1: - pms = pll0_1_pms; - len = PLL0_1_SIZE; - break; - case 2: - case 3: - pms = pll2_3_pms; - len = PLL2_3_SIZE; - break; - default: - pr_info("Not support pll.%d (0~3)\n", pllno); - return 0; - } - - /* array index so -1 */ - idx = (len / 2) - 1; - - while (1) { - l = n + idx; - freq = PMS_RATE(pms, l); - if (freq == rate) - break; - - if (rate > freq) - len -= idx, idx >>= 1; - else - n += idx, idx = (len - n - 1) >> 1; - - if (0 == idx) { - int k = l; - - if (abs(rate - freq) > abs(rate - PMS_RATE(pms, k + 1))) - k += 1; - - if (abs(rate - PMS_RATE(pms, k)) >= - abs(rate - PMS_RATE(pms, k - 1))) - k -= 1; - - l = k; - break; - } - } - - if (p) - *p = PMS_P(pms, l); - if (m) - *m = PMS_M(pms, l); - if (s) - *s = PMS_S(pms, l); - - pr_debug("(real %ld Khz, P=%d ,M=%3d, S=%d)\n", PMS_RATE(pms, l), - PMS_P(pms, l), PMS_M(pms, l), PMS_S(pms, l)); - - return (PMS_RATE(pms, l) * 1000); -} - -static unsigned long ref_clk = 24000000UL; - -#define getquotient(v, d) (v / d) - -#define DIV_CPUG0 0 -#define DIV_BUS 1 -#define DIV_MEM 2 -#define DIV_G3D 3 -#define DIV_VPU 4 -#define DIV_DISP 5 -#define DIV_HDMI 6 -#define DIV_CPUG1 7 -#define DIV_CCI4 8 - -#define DVO0 3 -#define DVO1 9 -#define DVO2 15 -#define DVO3 21 - -static inline unsigned int pll_rate(unsigned int pllN, unsigned int xtal) -{ - struct reg_clkpwr *reg = ref_clk_base; - unsigned int val, val1, nP, nM, nS, nK; - unsigned int temp = 0; - - val = reg->PLLSETREG[pllN]; - val1 = reg->PLLSETREG_SSCG[pllN]; - xtal /= 1000; /* Unit Khz */ - - nP = (val >> 18) & 0x03F; - nM = (val >> 8) & 0x3FF; - nS = (val >> 0) & 0x0FF; - nK = (val1 >> 16) & 0xFFFF; - - if ((pllN > 1) && nK) - temp = (unsigned int)( - getquotient((getquotient((nK * 1000), 65536) * xtal), - nP) >> nS); - - return (unsigned int)((getquotient((nM * xtal), nP) >> nS) * 1000) + - temp; -} - -static inline unsigned int pll_dvo(int dvo) -{ - struct reg_clkpwr *reg = ref_clk_base; - - return (reg->DVOREG[dvo] & 0x7); -} - -static inline unsigned int pll_div(int dvo) -{ - struct reg_clkpwr *reg = ref_clk_base; - unsigned int val = reg->DVOREG[dvo]; - - return ((((val >> DVO3) & 0x3F) + 1) << 24) | - ((((val >> DVO2) & 0x3F) + 1) << 16) | - ((((val >> DVO1) & 0x3F) + 1) << 8) | - ((((val >> DVO0) & 0x3F) + 1) << 0); -} - -#define PLLN_RATE(n) (pll_rate(n, ref_clk)) /* 0~ 3 */ -#define CPU_FCLK_RATE(n) \ - (pll_rate(pll_dvo(n), ref_clk) / ((pll_div(n) >> 0) & 0x3F)) -#define CPU_HCLK_RATE(n) \ - (pll_rate(pll_dvo(n), ref_clk) / ((pll_div(n) >> 0) & 0x3F) / \ - ((pll_div(n) >> 8) & 0x3F)) -#define MEM_FCLK_RATE() \ - (pll_rate(pll_dvo(DIV_MEM), ref_clk) / \ - ((pll_div(DIV_MEM) >> 0) & 0x3F) / ((pll_div(DIV_MEM) >> 8) & 0x3F)) -#define MEM_DCLK_RATE() \ - (pll_rate(pll_dvo(DIV_MEM), ref_clk) / ((pll_div(DIV_MEM) >> 0) & 0x3F)) -#define MEM_BCLK_RATE() \ - (pll_rate(pll_dvo(DIV_MEM), ref_clk) / \ - ((pll_div(DIV_MEM) >> 0) & 0x3F) / ((pll_div(DIV_MEM) >> 8) & 0x3F) / \ - ((pll_div(DIV_MEM) >> 16) & 0x3F)) -#define MEM_PCLK_RATE() \ - (pll_rate(pll_dvo(DIV_MEM), ref_clk) / \ - ((pll_div(DIV_MEM) >> 0) & 0x3F) / ((pll_div(DIV_MEM) >> 8) & 0x3F) / \ - ((pll_div(DIV_MEM) >> 16) & 0x3F) / \ - ((pll_div(DIV_MEM) >> 24) & 0x3F)) -#define BUS_BCLK_RATE() \ - (pll_rate(pll_dvo(DIV_BUS), ref_clk) / ((pll_div(DIV_BUS) >> 0) & 0x3F)) -#define BUS_PCLK_RATE() \ - (pll_rate(pll_dvo(DIV_BUS), ref_clk) / \ - ((pll_div(DIV_BUS) >> 0) & 0x3F) / ((pll_div(DIV_BUS) >> 8) & 0x3F)) -#define G3D_BCLK_RATE() \ - (pll_rate(pll_dvo(DIV_G3D), ref_clk) / ((pll_div(DIV_G3D) >> 0) & 0x3F)) -#define VPU_BCLK_RATE() \ - (pll_rate(pll_dvo(DIV_VPU), ref_clk) / ((pll_div(DIV_VPU) >> 0) & 0x3F)) -#define VPU_PCLK_RATE() \ - (pll_rate(pll_dvo(DIV_VPU), ref_clk) / \ - ((pll_div(DIV_VPU) >> 0) & 0x3F) / ((pll_div(DIV_VPU) >> 8) & 0x3F)) -#define DIS_BCLK_RATE() \ - (pll_rate(pll_dvo(DIV_DISP), ref_clk) / \ - ((pll_div(DIV_DISP) >> 0) & 0x3F)) -#define DIS_PCLK_RATE() \ - (pll_rate(pll_dvo(DIV_DISP), ref_clk) / \ - ((pll_div(DIV_DISP) >> 0) & 0x3F) / \ - ((pll_div(DIV_DISP) >> 8) & 0x3F)) -#define HDMI_PCLK_RATE() \ - (pll_rate(pll_dvo(DIV_HDMI), ref_clk) / \ - ((pll_div(DIV_HDMI) >> 0) & 0x3F)) -#define CCI_BCLK_RATE() \ - (pll_rate(pll_dvo(DIV_CCI4), ref_clk) / \ - ((pll_div(DIV_CCI4) >> 0) & 0x3F)) -#define CCI_PCLK_RATE() \ - (pll_rate(pll_dvo(DIV_CCI4), ref_clk) / \ - ((pll_div(DIV_CCI4) >> 0) & 0x3F) / \ - ((pll_div(DIV_CCI4) >> 8) & 0x3F)) - -/* - * core frequency clk interface - */ -static struct clk_core clk_pll_dev[] = { - [ID_CPU_PLL0] = { - .id = ID_CPU_PLL0, .name = CLK_CPU_PLL0, - }, - [ID_CPU_PLL1] = { - .id = ID_CPU_PLL1, .name = CLK_CPU_PLL1, - }, - [ID_CPU_PLL2] = { - .id = ID_CPU_PLL2, .name = CLK_CPU_PLL2, - }, - [ID_CPU_PLL3] = { - .id = ID_CPU_PLL3, .name = CLK_CPU_PLL3, - }, - [ID_CPU_FCLK] = {.id = ID_CPU_FCLK, - .name = CLK_CPU_FCLK, - .div = DIV_CPUG0}, - [ID_CPU_HCLK] = {.id = ID_CPU_HCLK, - .name = CLK_CPU_HCLK, - .div = DIV_CPUG0}, - [ID_MEM_FCLK] = {.id = ID_MEM_FCLK, - .name = CLK_MEM_FCLK, - .div = DIV_MEM}, - [ID_MEM_DCLK] = {.id = ID_MEM_DCLK, - .name = CLK_MEM_DCLK, - .div = DIV_MEM}, - [ID_MEM_BCLK] = {.id = ID_MEM_BCLK, - .name = CLK_MEM_BCLK, - .div = DIV_MEM}, - [ID_MEM_PCLK] = {.id = ID_MEM_PCLK, - .name = CLK_MEM_PCLK, - .div = DIV_MEM}, - [ID_BUS_BCLK] = {.id = ID_BUS_BCLK, - .name = CLK_BUS_BCLK, - .div = DIV_BUS}, - [ID_BUS_PCLK] = {.id = ID_BUS_PCLK, - .name = CLK_BUS_PCLK, - .div = DIV_BUS}, - [ID_VPU_BCLK] = {.id = ID_VPU_BCLK, - .name = CLK_VPU_BCLK, - .div = DIV_VPU}, - [ID_VPU_PCLK] = {.id = ID_VPU_PCLK, - .name = CLK_VPU_PCLK, - .div = DIV_VPU}, - [ID_DIS_BCLK] = {.id = ID_DIS_BCLK, - .name = CLK_DIS_BCLK, - .div = DIV_DISP}, - [ID_DIS_PCLK] = {.id = ID_DIS_PCLK, - .name = CLK_DIS_PCLK, - .div = DIV_DISP}, - [ID_CCI_BCLK] = {.id = ID_CCI_BCLK, - .name = CLK_CCI_BCLK, - .div = DIV_CCI4}, - [ID_CCI_PCLK] = {.id = ID_CCI_PCLK, - .name = CLK_CCI_PCLK, - .div = DIV_CCI4}, - [ID_G3D_BCLK] = {.id = ID_G3D_BCLK, - .name = CLK_G3D_BCLK, - .div = DIV_G3D}, -}; - -static unsigned long clk_pll_recalc_rate(struct clk_hw *hw, unsigned long rate) -{ - struct clk_core *clk_data = to_clk_core(hw); - int id = clk_data->id; - - switch (id) { - case ID_CPU_PLL0: - rate = PLLN_RATE(0); - break; - case ID_CPU_PLL1: - rate = PLLN_RATE(1); - break; - case ID_CPU_PLL2: - rate = PLLN_RATE(2); - break; - case ID_CPU_PLL3: - rate = PLLN_RATE(3); - break; - case ID_CPU_FCLK: - rate = CPU_FCLK_RATE(DIV_CPUG0); - break; - case ID_CPU_HCLK: - rate = CPU_HCLK_RATE(DIV_CPUG0); - break; - case ID_MEM_FCLK: - rate = MEM_FCLK_RATE(); - break; - case ID_BUS_BCLK: - rate = BUS_BCLK_RATE(); - break; - case ID_BUS_PCLK: - rate = BUS_PCLK_RATE(); - break; - case ID_MEM_DCLK: - rate = MEM_DCLK_RATE(); - break; - case ID_MEM_BCLK: - rate = MEM_BCLK_RATE(); - break; - case ID_MEM_PCLK: - rate = MEM_PCLK_RATE(); - break; - case ID_G3D_BCLK: - rate = G3D_BCLK_RATE(); - break; - case ID_VPU_BCLK: - rate = VPU_BCLK_RATE(); - break; - case ID_VPU_PCLK: - rate = VPU_PCLK_RATE(); - break; - case ID_DIS_BCLK: - rate = DIS_BCLK_RATE(); - break; - case ID_DIS_PCLK: - rate = DIS_PCLK_RATE(); - break; - case ID_CCI_BCLK: - rate = CCI_BCLK_RATE(); - break; - case ID_CCI_PCLK: - rate = CCI_PCLK_RATE(); - break; - default: - pr_info("Unknown clock ID [%d] ...\n", id); - break; - } - - pr_debug("%s: name %s id %d rate %ld\n", __func__, clk_data->name, - clk_data->id, rate); - return rate; -} - -static long clk_pll_round_rate(struct clk_hw *hw, unsigned long drate, - unsigned long *prate) -{ - struct clk_core *clk_data = to_clk_core(hw); - struct pll_pms *pms = &clk_data->pms; - int id = clk_data->id; - long rate = 0; - - /* clear P,M,S */ - pms->P = 0, pms->M = 0, pms->S = 0; - rate = pll_round_rate(id, drate, &pms->P, &pms->M, &pms->S); - - pr_debug("%s: name %s id %d (%lu, %lu) <%d,%d,%d>\n", __func__, - clk_data->name, id, drate, rate, pms->P, pms->M, pms->S); - return rate; -} - -static int clk_pll_set_rate(struct clk_hw *hw, unsigned long drate, - unsigned long prate) -{ - struct clk_core *clk_data = to_clk_core(hw); - struct pll_pms *pms = &clk_data->pms; - int id = clk_data->id; - long rate = drate; - - if (!pms->P && !pms->M && !pms->S) - rate = pll_round_rate(id, drate, &pms->P, &pms->M, &pms->S); - - pr_debug("%s: name %s id %d (%lu, %lu) <%d,%d,%d>\n", __func__, - clk_data->name, id, drate, rate, pms->P, pms->M, pms->S); - pll_set_rate(id, pms->P, pms->M, pms->S); - - /* clear P,M,S */ - pms->P = 0, pms->M = 0, pms->S = 0; - - return 0; -} - -static const struct clk_ops clk_pll_ops = { - .recalc_rate = clk_pll_recalc_rate, - .round_rate = clk_pll_round_rate, - .set_rate = clk_pll_set_rate, -}; - -static const struct clk_ops clk_dev_ops = { - .recalc_rate = clk_pll_recalc_rate, -}; - -static struct clk *clk_pll_clock_register(const char *name, - const char *parent_name, - struct clk_hw *hw, - const struct clk_ops *ops, - unsigned long flags) -{ - struct clk *clk; - struct clk_init_data init; - - init.name = name; - init.ops = ops; - init.flags = flags; - init.parent_names = (parent_name ? &parent_name : NULL); - init.num_parents = parent_name ? 1 : 0; - hw->init = &init; - - clk = clk_register(NULL, hw); - if (IS_ERR(clk)) { - pr_err("%s: failed to register pll clock %s\n", __func__, - init.name); - return NULL; - } - - if (clk_register_clkdev(clk, init.name, NULL)) - pr_err("%s: failed to register lookup for %s", __func__, - init.name); - - return clk; -} - -static void __init clk_pll_sysclk_setup(struct device_node *np) -{ - struct clk *clk; - unsigned long flags = CLK_IS_ROOT;/* | CLK_GET_RATE_NOCACHE; */ - unsigned long rate[ID_CPU_FCLK]; - int i; - - for (i = 0; i < ID_CPU_FCLK; i++) { - clk = clk_pll_clock_register(clk_pll_dev[i].name, NULL, - &clk_pll_dev[i].hw, &clk_pll_ops, - flags); - if (NULL == clk) - continue; - rate[i] = clk_get_rate(clk); - } - pr_info("PLL : [0] = %10lu, [1] = %10lu, [2] = %10lu, [3] = %10lu\n", - rate[0], rate[1], rate[2], rate[3]); -} - -static void __init clk_pll_of_clocks_setup(struct device_node *node) -{ - struct clk_core *clk_data = NULL; - struct clk *clk; - unsigned long flags = CLK_IS_BASIC; - const char *parent_name = NULL; - int i, div, pll; - - for (i = ID_CPU_FCLK; ID_END > i; i++) { - clk_data = &clk_pll_dev[i]; - div = clk_data->div; - pll = pll_dvo(div); - clk_data->pll = pll; - parent_name = clk_pll_dev[pll].name; - - clk = clk_pll_clock_register(clk_data->name, parent_name, - &clk_data->hw, &clk_dev_ops, flags); - if (clk) - clk_data->rate = clk_get_rate(clk); - } -} - -static void __init clk_pll_of_clocks_dump(struct device_node *np) -{ - struct clk_core *clk_data = clk_pll_dev; - int pll = pll_dvo(DIV_CPUG1); - - /* cpu 0, 1 : div 0, 7 */ - pr_info("(%d) PLL%d: CPU FCLK = %10lu, HCLK = %9lu (G0)\n", - clk_data[ID_CPU_FCLK].div, clk_data[ID_CPU_FCLK].pll, - clk_data[ID_CPU_FCLK].rate, clk_data[ID_CPU_HCLK].rate); - - pr_info("(%d) PLL%d: CPU FCLK = %10lu, HCLK = %9lu (G1)\n", DIV_CPUG1, - pll, (ulong)CPU_FCLK_RATE(DIV_CPUG1), - (ulong)CPU_HCLK_RATE(DIV_CPUG1)); - - /* memory */ - pr_info("(%d) PLL%d: MEM FCLK = %10lu, DCLK = %9lu, BCLK = %9lu,", - clk_data[ID_MEM_FCLK].div, clk_data[ID_MEM_FCLK].pll, - clk_data[ID_MEM_FCLK].rate, clk_data[ID_MEM_DCLK].rate, - clk_data[ID_MEM_BCLK].rate); - - pr_info("PCLK = %9lu\n", clk_data[ID_MEM_PCLK].rate); - - /* bus */ - pr_info("(%d) PLL%d: BUS BCLK = %10lu, PCLK = %9lu\n", - clk_data[ID_BUS_BCLK].div, clk_data[ID_BUS_BCLK].pll, - clk_data[ID_BUS_BCLK].rate, clk_data[ID_BUS_PCLK].rate); - - /* cci400 */ - pr_info("(%d) PLL%d: CCI4 BCLK = %10lu, PCLK = %9lu\n", - clk_data[ID_CCI_BCLK].div, clk_data[ID_CCI_BCLK].pll, - clk_data[ID_CCI_BCLK].rate, clk_data[ID_CCI_PCLK].rate); - - /* 3d graphic */ - pr_info("(%d) PLL%d: G3D BCLK = %10lu\n", clk_data[ID_G3D_BCLK].div, - clk_data[ID_G3D_BCLK].pll, clk_data[ID_G3D_BCLK].rate); - - /* coda (vpu) */ - pr_info("(%d) PLL%d: VPU BCLK = %10lu, PCLK = %9lu\n", - clk_data[ID_VPU_BCLK].div, clk_data[ID_VPU_BCLK].pll, - clk_data[ID_VPU_BCLK].rate, clk_data[ID_VPU_PCLK].rate); - - /* display */ - pr_info("(%d) PLL%d: DISP BCLK = %10lu, PCLK = %9lu\n", - clk_data[ID_DIS_BCLK].div, clk_data[ID_DIS_BCLK].pll, - clk_data[ID_DIS_BCLK].rate, clk_data[ID_DIS_PCLK].rate); -} - -static void __init clk_pll_of_setup(struct device_node *node) -{ - unsigned int pllin; - struct resource regs; - - if (of_address_to_resource(node, 0, ®s) < 0) { - pr_err("fail get clock pll regsister\n"); - return; - } - - ref_clk_base = ioremap(regs.start, resource_size(®s)); - if (ref_clk_base == NULL) { - pr_err("fail get Clock control base address\n"); - return; - } - if (0 == of_property_read_u32(node, "ref-freuecny", &pllin)) - ref_clk = pllin; - - clk_pll_sysclk_setup(node); - clk_pll_of_clocks_setup(node); - clk_pll_of_clocks_dump(node); - - pr_info("CPU REF HZ: %lu hz (0x%08x:0x%p)\n", ref_clk, 0xc0010000, - ref_clk_base); -} - -CLK_OF_DECLARE(s5pxx18, "nexell,s5p4418,pll", clk_pll_of_setup); diff --git a/drivers/clk/nexell/clk-s5p6818-pll.h b/drivers/clk/nexell/clk-s5p6818-pll.h deleted file mode 100644 index c7889884f5a3..000000000000 --- a/drivers/clk/nexell/clk-s5p6818-pll.h +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright (C) 2016 Nexell Co., Ltd. - * Author: Youngbok, Park <ybpark@nexell.co.kr> - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#ifndef _CLK_S5P6818_PLL_H -#define _CLK_S5P6818_PLL_H - -enum { ID_CPU_PLL0 = 0, - ID_CPU_PLL1, - ID_CPU_PLL2, - ID_CPU_PLL3, - ID_CPU_FCLK, - ID_CPU_HCLK, - ID_BUS_BCLK, - ID_BUS_PCLK, - ID_MEM_FCLK, - ID_MEM_DCLK, - ID_MEM_BCLK, - ID_MEM_PCLK, - ID_G3D_BCLK, - ID_VPU_BCLK, - ID_VPU_PCLK, - ID_DIS_BCLK, - ID_DIS_PCLK, - ID_CCI_BCLK, - ID_CCI_PCLK, - ID_END, -}; - -struct reg_clkpwr { - unsigned int CLKMODEREG0; - unsigned int __Reserved0; - unsigned int PLLSETREG[4]; - unsigned int __Reserved1[2]; - unsigned int DVOREG[9]; - unsigned int __Reserved2; - unsigned int PLLSETREG_SSCG[6]; - unsigned int __reserved3[8]; - unsigned char __Reserved4[0x200 - 0x80]; - unsigned int GPIOWAKEUPRISEENB; - unsigned int GPIOWAKEUPFALLENB; - unsigned int GPIORSTENB; - unsigned int GPIOWAKEUPENB; - unsigned int GPIOINTENB; - unsigned int GPIOINTPEND; - unsigned int RESETSTATUS; - unsigned int INTENABLE; - unsigned int INTPEND; - unsigned int PWRCONT; - unsigned int PWRMODE; - unsigned int __Reserved5; - unsigned int SCRATCH[3]; - unsigned int SYSRSTCONFIG; - unsigned char __Reserved6[0x2A0 - 0x240]; - unsigned int CPUPOWERDOWNREQ; - unsigned int CPUPOWERONREQ; - unsigned int CPURESETMODE; - unsigned int CPUWARMRESETREQ; - unsigned int __Reserved7; - unsigned int CPUSTATUS; - unsigned char __Reserved8[0x400 - 0x2B8]; -}; - -#define to_clk_core(_hw) container_of(_hw, struct clk_core, hw) - -#endif diff --git a/drivers/clk/nexell/clk-s5p6818-pll.c b/drivers/clk/nexell/clk-s5pxx18-pll.c index e90da3170646..c0b9d4adc5fd 100644 --- a/drivers/clk/nexell/clk-s5p6818-pll.c +++ b/drivers/clk/nexell/clk-s5pxx18-pll.c @@ -26,7 +26,7 @@ #include <linux/of_address.h> #include <asm/tlbflush.h> #include "clk-s5pxx18.h" -#include "clk-s5p6818-pll.h" +#include "clk-s5pxx18-pll.h" #define PLL_LOCKING_TIME 100 @@ -45,6 +45,87 @@ struct clk_core { struct pll_pms pms; }; +#ifdef CONFIG_ARCH_S5P4418 +/* PLL 0,1 */ +static struct pll_pms pll0_1_pms[] = { + [0] = { + .rate = 1200000, .P = 3, .M = 300, .S = 1, + }, + [1] = { + .rate = 1100000, .P = 3, .M = 275, .S = 1, + }, + [2] = { + .rate = 1000000, .P = 3, .M = 250, .S = 1, + }, + [3] = { + .rate = 900000, .P = 3, .M = 225, .S = 1, + }, + [4] = { + .rate = 800000, .P = 3, .M = 200, .S = 1, + }, + [5] = { + .rate = 700000, .P = 3, .M = 175, .S = 1, + }, + [6] = { + .rate = 600000, .P = 2, .M = 200, .S = 2, + }, + [7] = { + .rate = 500000, .P = 3, .M = 250, .S = 2, + }, + [8] = { + .rate = 400000, .P = 3, .M = 200, .S = 2, + }, + [9] = { + .rate = 300000, .P = 2, .M = 200, .S = 3, + }, + [10] = { + .rate = 200000, .P = 3, .M = 200, .S = 3, + }, + [11] = { + .rate = 100000, .P = 3, .M = 200, .S = 4, + }, +}; + +/* PLL 2,3 */ +static struct pll_pms pll2_3_pms[] = { + [0] = { + .rate = 1200000, .P = 3, .M = 300, .S = 1, + }, + [1] = { + .rate = 1100000, .P = 3, .M = 275, .S = 1, + }, + [2] = { + .rate = 1000000, .P = 3, .M = 250, .S = 1, + }, + [3] = { + .rate = 900000, .P = 3, .M = 225, .S = 1, + }, + [4] = { + .rate = 800000, .P = 3, .M = 200, .S = 1, + }, + [5] = { + .rate = 700000, .P = 3, .M = 175, .S = 1, + }, + [6] = { + .rate = 600000, .P = 3, .M = 150, .S = 1, + }, + [7] = { + .rate = 500000, .P = 3, .M = 250, .S = 2, + }, + [8] = { + .rate = 400000, .P = 3, .M = 200, .S = 2, + }, + [9] = { + .rate = 300000, .P = 3, .M = 150, .S = 2, + }, + [10] = { + .rate = 200000, .P = 3, .M = 200, .S = 3, + }, + [11] = { + .rate = 100000, .P = 3, .M = 200, .S = 4, + }, +}; +#else /* S5P6818 */ /* PLL 0,1 */ static struct pll_pms pll0_1_pms[] = { [0] = { @@ -148,6 +229,7 @@ static struct pll_pms pll2_3_pms[] = { .rate = 100000, .P = 3, .M = 200, .S = 4, }, }; +#endif #define PLL0_1_SIZE ARRAY_SIZE(pll0_1_pms) #define PLL2_3_SIZE ARRAY_SIZE(pll2_3_pms) @@ -727,4 +809,4 @@ static void __init clk_pll_of_setup(struct device_node *node) ref_clk_base); } -CLK_OF_DECLARE(s5pxx18, "nexell,s5p6818,pll", clk_pll_of_setup); +CLK_OF_DECLARE(s5pxx18, "nexell,s5pxx18,pll", clk_pll_of_setup); diff --git a/drivers/clk/nexell/clk-s5p4418-pll.h b/drivers/clk/nexell/clk-s5pxx18-pll.h index 329dc3a4de48..329dc3a4de48 100644 --- a/drivers/clk/nexell/clk-s5p4418-pll.h +++ b/drivers/clk/nexell/clk-s5pxx18-pll.h |