1// SPDX-License-Identifier: GPL-2.0+
2/*
3 * Copyright (C) 2013-2014 Panasonic Corporation
4 * Copyright (C) 2015-2016 Socionext Inc.
5 */
6
7#include <linux/delay.h>
8#include <linux/io.h>
9
10#include "../init.h"
11#include "../sc-regs.h"
12#include "../sg-regs.h"
13#include "pll.h"
14
15static void upll_init(void)
16{
17	u32 tmp, clk_mode_upll, clk_mode_axosel;
18
19	tmp = readl(sg_base + SG_PINMON0);
20	clk_mode_upll   = tmp & SG_PINMON0_CLK_MODE_UPLLSRC_MASK;
21	clk_mode_axosel = tmp & SG_PINMON0_CLK_MODE_AXOSEL_MASK;
22
23	/* set 0 to SNRT(UPLLCTRL.bit28) and K_LD(UPLLCTRL.bit[27]) */
24	tmp = readl(sc_base + SC_UPLLCTRL);
25	tmp &= ~0x18000000;
26	writel(tmp, sc_base + SC_UPLLCTRL);
27
28	if (clk_mode_upll == SG_PINMON0_CLK_MODE_UPLLSRC_DEFAULT) {
29		if (clk_mode_axosel == SG_PINMON0_CLK_MODE_AXOSEL_25000KHZ_U ||
30		    clk_mode_axosel == SG_PINMON0_CLK_MODE_AXOSEL_25000KHZ_A) {
31			/* AXO: 25MHz */
32			tmp &= ~0x07ffffff;
33			tmp |= 0x0228f5c0;
34		} else {
35			/* AXO: default 24.576MHz */
36			tmp &= ~0x07ffffff;
37			tmp |= 0x02328000;
38		}
39	}
40
41	writel(tmp, sc_base + SC_UPLLCTRL);
42
43	/* set 1 to K_LD(UPLLCTRL.bit[27]) */
44	tmp |= 0x08000000;
45	writel(tmp, sc_base + SC_UPLLCTRL);
46
47	/* wait 10 usec */
48	udelay(10);
49
50	/* set 1 to SNRT(UPLLCTRL.bit[28]) */
51	tmp |= 0x10000000;
52	writel(tmp, sc_base + SC_UPLLCTRL);
53}
54
55static void vpll_init(void)
56{
57	u32 tmp, clk_mode_axosel;
58
59	tmp = readl(sg_base + SG_PINMON0);
60	clk_mode_axosel = tmp & SG_PINMON0_CLK_MODE_AXOSEL_MASK;
61
62	/* set 1 to VPLA27WP and VPLA27WP */
63	tmp = readl(sc_base + SC_VPLL27ACTRL);
64	tmp |= 0x00000001;
65	writel(tmp, sc_base + SC_VPLL27ACTRL);
66	tmp = readl(sc_base + SC_VPLL27BCTRL);
67	tmp |= 0x00000001;
68	writel(tmp, sc_base + SC_VPLL27BCTRL);
69
70	/* Set 0 to VPLA_K_LD and VPLB_K_LD */
71	tmp = readl(sc_base + SC_VPLL27ACTRL3);
72	tmp &= ~0x10000000;
73	writel(tmp, sc_base + SC_VPLL27ACTRL3);
74	tmp = readl(sc_base + SC_VPLL27BCTRL3);
75	tmp &= ~0x10000000;
76	writel(tmp, sc_base + SC_VPLL27BCTRL3);
77
78	/* Set 0 to VPLA_SNRST and VPLB_SNRST */
79	tmp = readl(sc_base + SC_VPLL27ACTRL2);
80	tmp &= ~0x10000000;
81	writel(tmp, sc_base + SC_VPLL27ACTRL2);
82	tmp = readl(sc_base + SC_VPLL27BCTRL2);
83	tmp &= ~0x10000000;
84	writel(tmp, sc_base + SC_VPLL27BCTRL2);
85
86	/* Set 0x20 to VPLA_SNRST and VPLB_SNRST */
87	tmp = readl(sc_base + SC_VPLL27ACTRL2);
88	tmp &= ~0x0000007f;
89	tmp |= 0x00000020;
90	writel(tmp, sc_base + SC_VPLL27ACTRL2);
91	tmp = readl(sc_base + SC_VPLL27BCTRL2);
92	tmp &= ~0x0000007f;
93	tmp |= 0x00000020;
94	writel(tmp, sc_base + SC_VPLL27BCTRL2);
95
96	if (clk_mode_axosel == SG_PINMON0_CLK_MODE_AXOSEL_25000KHZ_U ||
97	    clk_mode_axosel == SG_PINMON0_CLK_MODE_AXOSEL_25000KHZ_A) {
98		/* AXO: 25MHz */
99		tmp = readl(sc_base + SC_VPLL27ACTRL3);
100		tmp &= ~0x000fffff;
101		tmp |= 0x00066664;
102		writel(tmp, sc_base + SC_VPLL27ACTRL3);
103		tmp = readl(sc_base + SC_VPLL27BCTRL3);
104		tmp &= ~0x000fffff;
105		tmp |= 0x00066664;
106		writel(tmp, sc_base + SC_VPLL27BCTRL3);
107	} else {
108		/* AXO: default 24.576MHz */
109		tmp = readl(sc_base + SC_VPLL27ACTRL3);
110		tmp &= ~0x000fffff;
111		tmp |= 0x000f5800;
112		writel(tmp, sc_base + SC_VPLL27ACTRL3);
113		tmp = readl(sc_base + SC_VPLL27BCTRL3);
114		tmp &= ~0x000fffff;
115		tmp |= 0x000f5800;
116		writel(tmp, sc_base + SC_VPLL27BCTRL3);
117	}
118
119	/* Set 1 to VPLA_K_LD and VPLB_K_LD */
120	tmp = readl(sc_base + SC_VPLL27ACTRL3);
121	tmp |= 0x10000000;
122	writel(tmp, sc_base + SC_VPLL27ACTRL3);
123	tmp = readl(sc_base + SC_VPLL27BCTRL3);
124	tmp |= 0x10000000;
125	writel(tmp, sc_base + SC_VPLL27BCTRL3);
126
127	/* wait 10 usec */
128	udelay(10);
129
130	/* Set 0 to VPLA_SNRST and VPLB_SNRST */
131	tmp = readl(sc_base + SC_VPLL27ACTRL2);
132	tmp |= 0x10000000;
133	writel(tmp, sc_base + SC_VPLL27ACTRL2);
134	tmp = readl(sc_base + SC_VPLL27BCTRL2);
135	tmp |= 0x10000000;
136	writel(tmp, sc_base + SC_VPLL27BCTRL2);
137
138	/* set 0 to VPLA27WP and VPLA27WP */
139	tmp = readl(sc_base + SC_VPLL27ACTRL);
140	tmp &= ~0x00000001;
141	writel(tmp, sc_base + SC_VPLL27ACTRL);
142	tmp = readl(sc_base + SC_VPLL27BCTRL);
143	tmp |= ~0x00000001;
144	writel(tmp, sc_base + SC_VPLL27BCTRL);
145}
146
147void uniphier_ld4_pll_init(void)
148{
149	upll_init();
150	vpll_init();
151	uniphier_ld4_dpll_ssc_en();
152}
153