blob: 45fdf0a3226c376066b64d5cfb803f00f733305f [file] [log] [blame]
Masahiro Yamadad11b0b72016-09-17 03:33:11 +09001/*
2 * Copyright (C) 2016 Socionext Inc.
3 * Author: Masahiro Yamada <yamada.masahiro@socionext.com>
4 *
5 * SPDX-License-Identifier: GPL-2.0+
6 */
7
Masahiro Yamadad11b0b72016-09-17 03:33:11 +09008#include <linux/bitops.h>
Masahiro Yamadaeb6aeca2017-01-21 18:05:25 +09009#include <linux/delay.h>
10#include <linux/errno.h>
Masahiro Yamadad11b0b72016-09-17 03:33:11 +090011#include <linux/io.h>
12#include <linux/sizes.h>
13
14#include "pll.h"
15
16/* PLL type: SSC */
17#define SC_PLLCTRL_SSC_DK_MASK GENMASK(14, 0)
18#define SC_PLLCTRL_SSC_EN BIT(31)
19#define SC_PLLCTRL2_NRSTDS BIT(28)
20#define SC_PLLCTRL2_SSC_JK_MASK GENMASK(26, 0)
Masahiro Yamadaf366d382017-02-21 23:00:35 +090021#define SC_PLLCTRL3_REGI_SHIFT 16
22#define SC_PLLCTRL3_REGI_MASK GENMASK(19, 16)
Masahiro Yamadad11b0b72016-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;
44 tmp |= (487 * freq * ssc_rate / divn / 512) &
45 SC_PLLCTRL_SSC_DK_MASK;
46 writel(tmp, base);
47
48 tmp = readl(base + 4);
49 tmp &= ~SC_PLLCTRL2_SSC_JK_MASK;
50 tmp |= (41859 * freq / divn) & SC_PLLCTRL2_SSC_JK_MASK;
Dai Okamura652c4c92017-12-06 14:16:32 +090051 writel(tmp, base + 4);
Masahiro Yamadad11b0b72016-09-17 03:33:11 +090052
53 udelay(50);
54 }
55
56 tmp = readl(base + 4); /* SSCPLLCTRL2 */
57 tmp |= SC_PLLCTRL2_NRSTDS;
58 writel(tmp, base + 4);
59
60 iounmap(base);
61
62 return 0;
63}
64
65int uniphier_ld20_sscpll_ssc_en(unsigned long reg_base)
66{
67 void __iomem *base;
68 u32 tmp;
69
70 base = ioremap(reg_base, SZ_16);
71 if (!base)
72 return -ENOMEM;
73
Masahiro Yamadad11b0b72016-09-17 03:33:11 +090074 tmp = readl(base); /* SSCPLLCTRL */
75 tmp |= SC_PLLCTRL_SSC_EN;
76 writel(tmp, base);
77
78 iounmap(base);
79
80 return 0;
81}
82
Masahiro Yamadaf366d382017-02-21 23:00:35 +090083int uniphier_ld20_sscpll_set_regi(unsigned long reg_base, unsigned regi)
84{
85 void __iomem *base;
86 u32 tmp;
87
88 base = ioremap(reg_base, SZ_16);
89 if (!base)
90 return -ENOMEM;
91
Dai Okamura1f43c7b2017-08-28 21:57:15 +090092 tmp = readl(base + 8); /* SSCPLLCTRL3 */
Masahiro Yamadaf366d382017-02-21 23:00:35 +090093 tmp &= ~SC_PLLCTRL3_REGI_MASK;
94 tmp |= regi << SC_PLLCTRL3_REGI_SHIFT;
95 writel(tmp, base + 8);
96
97 iounmap(base);
98
99 return 0;
100}
101
Masahiro Yamadad11b0b72016-09-17 03:33:11 +0900102int uniphier_ld20_vpll27_init(unsigned long reg_base)
103{
104 void __iomem *base;
105 u32 tmp;
106
107 base = ioremap(reg_base, SZ_16);
108 if (!base)
109 return -ENOMEM;
110
111 tmp = readl(base); /* VPLL27CTRL */
112 tmp |= SC_VPLL27CTRL_WP; /* write protect off */
113 writel(tmp, base);
114
115 tmp = readl(base + 8); /* VPLL27CTRL3 */
116 tmp |= SC_VPLL27CTRL3_K_LD;
117 writel(tmp, base + 8);
118
119 tmp = readl(base); /* VPLL27CTRL */
120 tmp &= ~SC_VPLL27CTRL_WP; /* write protect on */
121 writel(tmp, base);
122
123 iounmap(base);
124
125 return 0;
126}
127
128int uniphier_ld20_dspll_init(unsigned long reg_base)
129{
130 void __iomem *base;
131 u32 tmp;
132
133 base = ioremap(reg_base, SZ_16);
134 if (!base)
135 return -ENOMEM;
136
Dai Okamura1f43c7b2017-08-28 21:57:15 +0900137 tmp = readl(base + 4); /* DSPLLCTRL2 */
Masahiro Yamadad11b0b72016-09-17 03:33:11 +0900138 tmp |= SC_DSPLLCTRL2_K_LD;
Dai Okamura1f43c7b2017-08-28 21:57:15 +0900139 writel(tmp, base + 4);
Masahiro Yamadad11b0b72016-09-17 03:33:11 +0900140
141 iounmap(base);
142
143 return 0;
144}