blob: 67b8ee7c3e319e3665393640533a232929827077 [file] [log] [blame]
Tom Rini83d290c2018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Masahiro Yamada682e09f2016-09-17 03:33:11 +09002/*
3 * Copyright (C) 2016 Socionext Inc.
4 * Author: Masahiro Yamada <yamada.masahiro@socionext.com>
Masahiro Yamada682e09f2016-09-17 03:33:11 +09005 */
6
Masahiro Yamada7f8e7532017-12-06 14:16:34 +09007#include <linux/bitfield.h>
Masahiro Yamada682e09f2016-09-17 03:33:11 +09008#include <linux/bitops.h>
Masahiro Yamadad9a70362017-01-21 18:05:25 +09009#include <linux/delay.h>
Masahiro Yamadaf2ce50b2017-12-06 14:16:33 +090010#include <linux/kernel.h>
Masahiro Yamadad9a70362017-01-21 18:05:25 +090011#include <linux/errno.h>
Masahiro Yamada682e09f2016-09-17 03:33:11 +090012#include <linux/io.h>
13#include <linux/sizes.h>
14
15#include "pll.h"
16
17/* PLL type: SSC */
18#define SC_PLLCTRL_SSC_DK_MASK GENMASK(14, 0)
19#define SC_PLLCTRL_SSC_EN BIT(31)
20#define SC_PLLCTRL2_NRSTDS BIT(28)
21#define SC_PLLCTRL2_SSC_JK_MASK GENMASK(26, 0)
Masahiro Yamadabc647952017-02-21 23:00:35 +090022#define SC_PLLCTRL3_REGI_MASK GENMASK(19, 16)
Masahiro Yamada682e09f2016-09-17 03:33:11 +090023
24/* PLL type: VPLL27 */
25#define SC_VPLL27CTRL_WP BIT(0)
26#define SC_VPLL27CTRL3_K_LD BIT(28)
27
28/* PLL type: DSPLL */
29#define SC_DSPLLCTRL2_K_LD BIT(28)
30
31int uniphier_ld20_sscpll_init(unsigned long reg_base, unsigned int freq,
32 unsigned int ssc_rate, unsigned int divn)
33{
34 void __iomem *base;
35 u32 tmp;
36
37 base = ioremap(reg_base, SZ_16);
38 if (!base)
39 return -ENOMEM;
40
41 if (freq != UNIPHIER_PLL_FREQ_DEFAULT) {
42 tmp = readl(base); /* SSCPLLCTRL */
43 tmp &= ~SC_PLLCTRL_SSC_DK_MASK;
Masahiro Yamada7f8e7532017-12-06 14:16:34 +090044 tmp |= FIELD_PREP(SC_PLLCTRL_SSC_DK_MASK,
45 DIV_ROUND_CLOSEST(487UL * freq * ssc_rate,
46 divn * 512));
Masahiro Yamada682e09f2016-09-17 03:33:11 +090047 writel(tmp, base);
48
49 tmp = readl(base + 4);
50 tmp &= ~SC_PLLCTRL2_SSC_JK_MASK;
Masahiro Yamada7f8e7532017-12-06 14:16:34 +090051 tmp |= FIELD_PREP(SC_PLLCTRL2_SSC_JK_MASK,
52 DIV_ROUND_CLOSEST(21431887UL * freq,
53 divn * 512));
Dai Okamurac30c44e2017-12-06 14:16:32 +090054 writel(tmp, base + 4);
Masahiro Yamada682e09f2016-09-17 03:33:11 +090055
56 udelay(50);
57 }
58
59 tmp = readl(base + 4); /* SSCPLLCTRL2 */
60 tmp |= SC_PLLCTRL2_NRSTDS;
61 writel(tmp, base + 4);
62
63 iounmap(base);
64
65 return 0;
66}
67
68int uniphier_ld20_sscpll_ssc_en(unsigned long reg_base)
69{
70 void __iomem *base;
71 u32 tmp;
72
73 base = ioremap(reg_base, SZ_16);
74 if (!base)
75 return -ENOMEM;
76
Masahiro Yamada682e09f2016-09-17 03:33:11 +090077 tmp = readl(base); /* SSCPLLCTRL */
78 tmp |= SC_PLLCTRL_SSC_EN;
79 writel(tmp, base);
80
81 iounmap(base);
82
83 return 0;
84}
85
Masahiro Yamadabc647952017-02-21 23:00:35 +090086int uniphier_ld20_sscpll_set_regi(unsigned long reg_base, unsigned regi)
87{
88 void __iomem *base;
89 u32 tmp;
90
91 base = ioremap(reg_base, SZ_16);
92 if (!base)
93 return -ENOMEM;
94
Dai Okamura4013bbb2017-08-28 21:57:15 +090095 tmp = readl(base + 8); /* SSCPLLCTRL3 */
Masahiro Yamadabc647952017-02-21 23:00:35 +090096 tmp &= ~SC_PLLCTRL3_REGI_MASK;
Masahiro Yamada7f8e7532017-12-06 14:16:34 +090097 tmp |= FIELD_PREP(SC_PLLCTRL3_REGI_MASK, regi);
Masahiro Yamadabc647952017-02-21 23:00:35 +090098 writel(tmp, base + 8);
99
100 iounmap(base);
101
102 return 0;
103}
104
Masahiro Yamada682e09f2016-09-17 03:33:11 +0900105int uniphier_ld20_vpll27_init(unsigned long reg_base)
106{
107 void __iomem *base;
108 u32 tmp;
109
110 base = ioremap(reg_base, SZ_16);
111 if (!base)
112 return -ENOMEM;
113
114 tmp = readl(base); /* VPLL27CTRL */
115 tmp |= SC_VPLL27CTRL_WP; /* write protect off */
116 writel(tmp, base);
117
118 tmp = readl(base + 8); /* VPLL27CTRL3 */
119 tmp |= SC_VPLL27CTRL3_K_LD;
120 writel(tmp, base + 8);
121
122 tmp = readl(base); /* VPLL27CTRL */
123 tmp &= ~SC_VPLL27CTRL_WP; /* write protect on */
124 writel(tmp, base);
125
126 iounmap(base);
127
128 return 0;
129}
130
131int uniphier_ld20_dspll_init(unsigned long reg_base)
132{
133 void __iomem *base;
134 u32 tmp;
135
136 base = ioremap(reg_base, SZ_16);
137 if (!base)
138 return -ENOMEM;
139
Dai Okamura4013bbb2017-08-28 21:57:15 +0900140 tmp = readl(base + 4); /* DSPLLCTRL2 */
Masahiro Yamada682e09f2016-09-17 03:33:11 +0900141 tmp |= SC_DSPLLCTRL2_K_LD;
Dai Okamura4013bbb2017-08-28 21:57:15 +0900142 writel(tmp, base + 4);
Masahiro Yamada682e09f2016-09-17 03:33:11 +0900143
144 iounmap(base);
145
146 return 0;
147}