summaryrefslogtreecommitdiff
path: root/drivers/clk/davinci/pll-dm365.c
blob: 2d29712753a37641ddb9e8e311d4f44e05df42ef (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
// SPDX-License-Identifier: GPL-2.0
/*
 * PLL clock descriptions for TI DM365
 *
 * Copyright (C) 2018 David Lechner <david@lechnology.com>
 */

#include <linux/bitops.h>
#include <linux/clkdev.h>
#include <linux/clk/davinci.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/types.h>

#include "pll.h"

#define OCSEL_OCSRC_ENABLE	0

static const struct davinci_pll_clk_info dm365_pll1_info = {
	.name = "pll1",
	.pllm_mask = GENMASK(9, 0),
	.pllm_min = 1,
	.pllm_max = 1023,
	.flags = PLL_HAS_CLKMODE | PLL_HAS_PREDIV | PLL_HAS_POSTDIV |
		 PLL_POSTDIV_ALWAYS_ENABLED | PLL_PLLM_2X,
};

SYSCLK(1, pll1_sysclk1, pll1_pllen, 5, SYSCLK_ALWAYS_ENABLED);
SYSCLK(2, pll1_sysclk2, pll1_pllen, 5, SYSCLK_ALWAYS_ENABLED);
SYSCLK(3, pll1_sysclk3, pll1_pllen, 5, SYSCLK_ALWAYS_ENABLED);
SYSCLK(4, pll1_sysclk4, pll1_pllen, 5, SYSCLK_ALWAYS_ENABLED);
SYSCLK(5, pll1_sysclk5, pll1_pllen, 5, SYSCLK_ALWAYS_ENABLED);
SYSCLK(6, pll1_sysclk6, pll1_pllen, 5, SYSCLK_ALWAYS_ENABLED);
SYSCLK(7, pll1_sysclk7, pll1_pllen, 5, SYSCLK_ALWAYS_ENABLED);
SYSCLK(8, pll1_sysclk8, pll1_pllen, 5, SYSCLK_ALWAYS_ENABLED);
SYSCLK(9, pll1_sysclk9, pll1_pllen, 5, SYSCLK_ALWAYS_ENABLED);

/*
 * This is a bit of a hack to make OCSEL[OCSRC] on DM365 look like OCSEL[OCSRC]
 * on DA850. On DM365, OCSEL[OCSRC] is just an enable/disable bit instead of a
 * multiplexer. By modeling it as a single parent mux clock, the clock code will
 * still do the right thing in this case.
 */
static const char * const dm365_pll_obsclk_parent_names[] = {
	"oscin",
};

static u32 dm365_pll_obsclk_table[] = {
	OCSEL_OCSRC_ENABLE,
};

static const struct davinci_pll_obsclk_info dm365_pll1_obsclk_info = {
	.name = "pll1_obsclk",
	.parent_names = dm365_pll_obsclk_parent_names,
	.num_parents = ARRAY_SIZE(dm365_pll_obsclk_parent_names),
	.table = dm365_pll_obsclk_table,
	.ocsrc_mask = BIT(4),
};

int dm365_pll1_init(struct device *dev, void __iomem *base, struct regmap *cfgchip)
{
	struct clk *clk;

	davinci_pll_clk_register(dev, &dm365_pll1_info, "ref_clk", base, cfgchip);

	clk = davinci_pll_sysclk_register(dev, &pll1_sysclk1, base);
	clk_register_clkdev(clk, "pll1_sysclk1", "dm365-psc");

	clk = davinci_pll_sysclk_register(dev, &pll1_sysclk2, base);
	clk_register_clkdev(clk, "pll1_sysclk2", "dm365-psc");

	clk = davinci_pll_sysclk_register(dev, &pll1_sysclk3, base);
	clk_register_clkdev(clk, "pll1_sysclk3", "dm365-psc");

	clk = davinci_pll_sysclk_register(dev, &pll1_sysclk4, base);
	clk_register_clkdev(clk, "pll1_sysclk4", "dm365-psc");

	clk = davinci_pll_sysclk_register(dev, &pll1_sysclk5, base);
	clk_register_clkdev(clk, "pll1_sysclk5", "dm365-psc");

	davinci_pll_sysclk_register(dev, &pll1_sysclk6, base);

	davinci_pll_sysclk_register(dev, &pll1_sysclk7, base);

	clk = davinci_pll_sysclk_register(dev, &pll1_sysclk8, base);
	clk_register_clkdev(clk, "pll1_sysclk8", "dm365-psc");

	davinci_pll_sysclk_register(dev, &pll1_sysclk9, base);

	clk = davinci_pll_auxclk_register(dev, "pll1_auxclk", base);
	clk_register_clkdev(clk, "pll1_auxclk", "dm355-psc");

	davinci_pll_sysclkbp_clk_register(dev, "pll1_sysclkbp", base);

	davinci_pll_obsclk_register(dev, &dm365_pll1_obsclk_info, base);

	return 0;
}

static const struct davinci_pll_clk_info dm365_pll2_info = {
	.name = "pll2",
	.pllm_mask = GENMASK(9, 0),
	.pllm_min = 1,
	.pllm_max = 1023,
	.flags = PLL_HAS_PREDIV | PLL_HAS_POSTDIV | PLL_POSTDIV_ALWAYS_ENABLED |
		 PLL_PLLM_2X,
};

SYSCLK(1, pll2_sysclk1, pll2_pllen, 5, SYSCLK_ALWAYS_ENABLED);
SYSCLK(2, pll2_sysclk2, pll2_pllen, 5, SYSCLK_ALWAYS_ENABLED);
SYSCLK(3, pll2_sysclk3, pll2_pllen, 5, SYSCLK_ALWAYS_ENABLED);
SYSCLK(4, pll2_sysclk4, pll2_pllen, 5, SYSCLK_ALWAYS_ENABLED);
SYSCLK(5, pll2_sysclk5, pll2_pllen, 5, SYSCLK_ALWAYS_ENABLED);

static const struct davinci_pll_obsclk_info dm365_pll2_obsclk_info = {
	.name = "pll2_obsclk",
	.parent_names = dm365_pll_obsclk_parent_names,
	.num_parents = ARRAY_SIZE(dm365_pll_obsclk_parent_names),
	.table = dm365_pll_obsclk_table,
	.ocsrc_mask = BIT(4),
};

int dm365_pll2_init(struct device *dev, void __iomem *base, struct regmap *cfgchip)
{
	struct clk *clk;

	davinci_pll_clk_register(dev, &dm365_pll2_info, "oscin", base, cfgchip);

	davinci_pll_sysclk_register(dev, &pll2_sysclk1, base);

	clk = davinci_pll_sysclk_register(dev, &pll2_sysclk2, base);
	clk_register_clkdev(clk, "pll1_sysclk2", "dm365-psc");

	davinci_pll_sysclk_register(dev, &pll2_sysclk3, base);

	clk = davinci_pll_sysclk_register(dev, &pll2_sysclk4, base);
	clk_register_clkdev(clk, "pll1_sysclk4", "dm365-psc");

	davinci_pll_sysclk_register(dev, &pll2_sysclk5, base);

	davinci_pll_auxclk_register(dev, "pll2_auxclk", base);

	davinci_pll_obsclk_register(dev, &dm365_pll2_obsclk_info, base);

	return 0;
}