Blame view

drivers/clk/clk-oxnas.c 6.52 KB
9952f6918   Thomas Gleixner   treewide: Replace...
1
  // SPDX-License-Identifier: GPL-2.0-only
0bbd72b4c   Neil Armstrong   clk: Add Oxford S...
2
3
4
5
  /*
   * Copyright (C) 2010 Broadcom
   * Copyright (C) 2012 Stephen Warren
   * Copyright (C) 2016 Neil Armstrong <narmstrong@baylibre.com>
0bbd72b4c   Neil Armstrong   clk: Add Oxford S...
6
7
8
9
   */
  
  #include <linux/clk-provider.h>
  #include <linux/kernel.h>
80c6397c3   Paul Gortmaker   clk: oxnas: make ...
10
  #include <linux/init.h>
0bbd72b4c   Neil Armstrong   clk: Add Oxford S...
11
  #include <linux/of.h>
5a9e54a81   Neil Armstrong   clk: oxnas: Refac...
12
  #include <linux/of_device.h>
0bbd72b4c   Neil Armstrong   clk: Add Oxford S...
13
14
15
16
  #include <linux/platform_device.h>
  #include <linux/stringify.h>
  #include <linux/regmap.h>
  #include <linux/mfd/syscon.h>
5a9e54a81   Neil Armstrong   clk: oxnas: Refac...
17
  #include <dt-bindings/clock/oxsemi,ox810se.h>
6df4393da   Neil Armstrong   clk: oxnas: Add O...
18
  #include <dt-bindings/clock/oxsemi,ox820.h>
5a9e54a81   Neil Armstrong   clk: oxnas: Refac...
19

0bbd72b4c   Neil Armstrong   clk: Add Oxford S...
20
  /* Standard regmap gate clocks */
1a2cfd007   Neil Armstrong   clk: oxnas: Renam...
21
  struct clk_oxnas_gate {
0bbd72b4c   Neil Armstrong   clk: Add Oxford S...
22
  	struct clk_hw hw;
5a9e54a81   Neil Armstrong   clk: oxnas: Refac...
23
  	unsigned int bit;
0bbd72b4c   Neil Armstrong   clk: Add Oxford S...
24
25
  	struct regmap *regmap;
  };
5a9e54a81   Neil Armstrong   clk: oxnas: Refac...
26
27
28
29
30
31
32
  struct oxnas_stdclk_data {
  	struct clk_hw_onecell_data *onecell_data;
  	struct clk_oxnas_gate **gates;
  	unsigned int ngates;
  	struct clk_oxnas_pll **plls;
  	unsigned int nplls;
  };
0bbd72b4c   Neil Armstrong   clk: Add Oxford S...
33
34
35
36
  /* Regmap offsets */
  #define CLK_STAT_REGOFFSET	0x24
  #define CLK_SET_REGOFFSET	0x2c
  #define CLK_CLR_REGOFFSET	0x30
1a2cfd007   Neil Armstrong   clk: oxnas: Renam...
37
  static inline struct clk_oxnas_gate *to_clk_oxnas_gate(struct clk_hw *hw)
0bbd72b4c   Neil Armstrong   clk: Add Oxford S...
38
  {
1a2cfd007   Neil Armstrong   clk: oxnas: Renam...
39
  	return container_of(hw, struct clk_oxnas_gate, hw);
0bbd72b4c   Neil Armstrong   clk: Add Oxford S...
40
  }
1a2cfd007   Neil Armstrong   clk: oxnas: Renam...
41
  static int oxnas_clk_gate_is_enabled(struct clk_hw *hw)
0bbd72b4c   Neil Armstrong   clk: Add Oxford S...
42
  {
1a2cfd007   Neil Armstrong   clk: oxnas: Renam...
43
  	struct clk_oxnas_gate *std = to_clk_oxnas_gate(hw);
0bbd72b4c   Neil Armstrong   clk: Add Oxford S...
44
45
46
47
48
49
50
51
52
  	int ret;
  	unsigned int val;
  
  	ret = regmap_read(std->regmap, CLK_STAT_REGOFFSET, &val);
  	if (ret < 0)
  		return ret;
  
  	return val & BIT(std->bit);
  }
1a2cfd007   Neil Armstrong   clk: oxnas: Renam...
53
  static int oxnas_clk_gate_enable(struct clk_hw *hw)
0bbd72b4c   Neil Armstrong   clk: Add Oxford S...
54
  {
1a2cfd007   Neil Armstrong   clk: oxnas: Renam...
55
  	struct clk_oxnas_gate *std = to_clk_oxnas_gate(hw);
0bbd72b4c   Neil Armstrong   clk: Add Oxford S...
56
57
58
59
60
  
  	regmap_write(std->regmap, CLK_SET_REGOFFSET, BIT(std->bit));
  
  	return 0;
  }
1a2cfd007   Neil Armstrong   clk: oxnas: Renam...
61
  static void oxnas_clk_gate_disable(struct clk_hw *hw)
0bbd72b4c   Neil Armstrong   clk: Add Oxford S...
62
  {
1a2cfd007   Neil Armstrong   clk: oxnas: Renam...
63
  	struct clk_oxnas_gate *std = to_clk_oxnas_gate(hw);
0bbd72b4c   Neil Armstrong   clk: Add Oxford S...
64
65
66
  
  	regmap_write(std->regmap, CLK_CLR_REGOFFSET, BIT(std->bit));
  }
1a2cfd007   Neil Armstrong   clk: oxnas: Renam...
67
68
69
70
  static const struct clk_ops oxnas_clk_gate_ops = {
  	.enable = oxnas_clk_gate_enable,
  	.disable = oxnas_clk_gate_disable,
  	.is_enabled = oxnas_clk_gate_is_enabled,
0bbd72b4c   Neil Armstrong   clk: Add Oxford S...
71
  };
5a9e54a81   Neil Armstrong   clk: oxnas: Refac...
72
  static const char *const osc_parents[] = {
0bbd72b4c   Neil Armstrong   clk: Add Oxford S...
73
74
75
76
77
78
  	"oscillator",
  };
  
  static const char *const eth_parents[] = {
  	"gmacclk",
  };
5a9e54a81   Neil Armstrong   clk: oxnas: Refac...
79
80
81
82
83
84
85
86
87
88
  #define OXNAS_GATE(_name, _bit, _parents)				\
  struct clk_oxnas_gate _name = {						\
  	.bit = (_bit),							\
  	.hw.init = &(struct clk_init_data) {				\
  		.name = #_name,						\
  		.ops = &oxnas_clk_gate_ops,				\
  		.parent_names = _parents,				\
  		.num_parents = ARRAY_SIZE(_parents),			\
  		.flags = (CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED),	\
  	},								\
0bbd72b4c   Neil Armstrong   clk: Add Oxford S...
89
  }
5a9e54a81   Neil Armstrong   clk: oxnas: Refac...
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
  static OXNAS_GATE(ox810se_leon, 0, osc_parents);
  static OXNAS_GATE(ox810se_dma_sgdma, 1, osc_parents);
  static OXNAS_GATE(ox810se_cipher, 2, osc_parents);
  static OXNAS_GATE(ox810se_sata, 4, osc_parents);
  static OXNAS_GATE(ox810se_audio, 5, osc_parents);
  static OXNAS_GATE(ox810se_usbmph, 6, osc_parents);
  static OXNAS_GATE(ox810se_etha, 7, eth_parents);
  static OXNAS_GATE(ox810se_pciea, 8, osc_parents);
  static OXNAS_GATE(ox810se_nand, 9, osc_parents);
  
  static struct clk_oxnas_gate *ox810se_gates[] = {
  	&ox810se_leon,
  	&ox810se_dma_sgdma,
  	&ox810se_cipher,
  	&ox810se_sata,
  	&ox810se_audio,
  	&ox810se_usbmph,
  	&ox810se_etha,
  	&ox810se_pciea,
  	&ox810se_nand,
  };
0bbd72b4c   Neil Armstrong   clk: Add Oxford S...
111

6df4393da   Neil Armstrong   clk: oxnas: Add O...
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
  static OXNAS_GATE(ox820_leon, 0, osc_parents);
  static OXNAS_GATE(ox820_dma_sgdma, 1, osc_parents);
  static OXNAS_GATE(ox820_cipher, 2, osc_parents);
  static OXNAS_GATE(ox820_sd, 3, osc_parents);
  static OXNAS_GATE(ox820_sata, 4, osc_parents);
  static OXNAS_GATE(ox820_audio, 5, osc_parents);
  static OXNAS_GATE(ox820_usbmph, 6, osc_parents);
  static OXNAS_GATE(ox820_etha, 7, eth_parents);
  static OXNAS_GATE(ox820_pciea, 8, osc_parents);
  static OXNAS_GATE(ox820_nand, 9, osc_parents);
  static OXNAS_GATE(ox820_ethb, 10, eth_parents);
  static OXNAS_GATE(ox820_pcieb, 11, osc_parents);
  static OXNAS_GATE(ox820_ref600, 12, osc_parents);
  static OXNAS_GATE(ox820_usbdev, 13, osc_parents);
  
  static struct clk_oxnas_gate *ox820_gates[] = {
  	&ox820_leon,
  	&ox820_dma_sgdma,
  	&ox820_cipher,
  	&ox820_sd,
  	&ox820_sata,
  	&ox820_audio,
  	&ox820_usbmph,
  	&ox820_etha,
  	&ox820_pciea,
  	&ox820_nand,
  	&ox820_etha,
  	&ox820_pciea,
  	&ox820_ref600,
  	&ox820_usbdev,
  };
5a9e54a81   Neil Armstrong   clk: oxnas: Refac...
143
144
145
146
147
148
149
150
151
152
153
154
155
  static struct clk_hw_onecell_data ox810se_hw_onecell_data = {
  	.hws = {
  		[CLK_810_LEON]	= &ox810se_leon.hw,
  		[CLK_810_DMA_SGDMA]	= &ox810se_dma_sgdma.hw,
  		[CLK_810_CIPHER]	= &ox810se_cipher.hw,
  		[CLK_810_SATA]	= &ox810se_sata.hw,
  		[CLK_810_AUDIO]	= &ox810se_audio.hw,
  		[CLK_810_USBMPH]	= &ox810se_usbmph.hw,
  		[CLK_810_ETHA]	= &ox810se_etha.hw,
  		[CLK_810_PCIEA]	= &ox810se_pciea.hw,
  		[CLK_810_NAND]	= &ox810se_nand.hw,
  	},
  	.num = ARRAY_SIZE(ox810se_gates),
0bbd72b4c   Neil Armstrong   clk: Add Oxford S...
156
  };
6df4393da   Neil Armstrong   clk: oxnas: Add O...
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
  static struct clk_hw_onecell_data ox820_hw_onecell_data = {
  	.hws = {
  		[CLK_820_LEON]	= &ox820_leon.hw,
  		[CLK_820_DMA_SGDMA]	= &ox820_dma_sgdma.hw,
  		[CLK_820_CIPHER]	= &ox820_cipher.hw,
  		[CLK_820_SD]	= &ox820_sd.hw,
  		[CLK_820_SATA]	= &ox820_sata.hw,
  		[CLK_820_AUDIO]	= &ox820_audio.hw,
  		[CLK_820_USBMPH]	= &ox820_usbmph.hw,
  		[CLK_820_ETHA]	= &ox820_etha.hw,
  		[CLK_820_PCIEA]	= &ox820_pciea.hw,
  		[CLK_820_NAND]	= &ox820_nand.hw,
  		[CLK_820_ETHB]	= &ox820_ethb.hw,
  		[CLK_820_PCIEB]	= &ox820_pcieb.hw,
  		[CLK_820_REF600]	= &ox820_ref600.hw,
  		[CLK_820_USBDEV]	= &ox820_usbdev.hw,
  	},
  	.num = ARRAY_SIZE(ox820_gates),
  };
5a9e54a81   Neil Armstrong   clk: oxnas: Refac...
176
177
178
179
180
  
  static struct oxnas_stdclk_data ox810se_stdclk_data = {
  	.onecell_data = &ox810se_hw_onecell_data,
  	.gates = ox810se_gates,
  	.ngates = ARRAY_SIZE(ox810se_gates),
0bbd72b4c   Neil Armstrong   clk: Add Oxford S...
181
  };
6df4393da   Neil Armstrong   clk: oxnas: Add O...
182
183
184
185
186
  static struct oxnas_stdclk_data ox820_stdclk_data = {
  	.onecell_data = &ox820_hw_onecell_data,
  	.gates = ox820_gates,
  	.ngates = ARRAY_SIZE(ox820_gates),
  };
5a9e54a81   Neil Armstrong   clk: oxnas: Refac...
187
188
189
  
  static const struct of_device_id oxnas_stdclk_dt_ids[] = {
  	{ .compatible = "oxsemi,ox810se-stdclk", &ox810se_stdclk_data },
6df4393da   Neil Armstrong   clk: oxnas: Add O...
190
  	{ .compatible = "oxsemi,ox820-stdclk", &ox820_stdclk_data },
5a9e54a81   Neil Armstrong   clk: oxnas: Refac...
191
  	{ }
0bbd72b4c   Neil Armstrong   clk: Add Oxford S...
192
193
194
195
196
  };
  
  static int oxnas_stdclk_probe(struct platform_device *pdev)
  {
  	struct device_node *np = pdev->dev.of_node;
5a9e54a81   Neil Armstrong   clk: oxnas: Refac...
197
198
  	const struct oxnas_stdclk_data *data;
  	const struct of_device_id *id;
0bbd72b4c   Neil Armstrong   clk: Add Oxford S...
199
  	struct regmap *regmap;
5a9e54a81   Neil Armstrong   clk: oxnas: Refac...
200
  	int ret;
0bbd72b4c   Neil Armstrong   clk: Add Oxford S...
201
  	int i;
5a9e54a81   Neil Armstrong   clk: oxnas: Refac...
202
203
204
205
  	id = of_match_device(oxnas_stdclk_dt_ids, &pdev->dev);
  	if (!id)
  		return -ENODEV;
  	data = id->data;
0bbd72b4c   Neil Armstrong   clk: Add Oxford S...
206
207
  
  	regmap = syscon_node_to_regmap(of_get_parent(np));
a5e9b85a6   Wei Yongjun   clk: Fix return v...
208
  	if (IS_ERR(regmap)) {
0bbd72b4c   Neil Armstrong   clk: Add Oxford S...
209
210
  		dev_err(&pdev->dev, "failed to have parent regmap
  ");
a5e9b85a6   Wei Yongjun   clk: Fix return v...
211
  		return PTR_ERR(regmap);
0bbd72b4c   Neil Armstrong   clk: Add Oxford S...
212
  	}
5a9e54a81   Neil Armstrong   clk: oxnas: Refac...
213
214
  	for (i = 0 ; i < data->ngates ; ++i)
  		data->gates[i]->regmap = regmap;
0bbd72b4c   Neil Armstrong   clk: Add Oxford S...
215

5a9e54a81   Neil Armstrong   clk: oxnas: Refac...
216
217
218
  	for (i = 0; i < data->onecell_data->num; i++) {
  		if (!data->onecell_data->hws[i])
  			continue;
0bbd72b4c   Neil Armstrong   clk: Add Oxford S...
219

5a9e54a81   Neil Armstrong   clk: oxnas: Refac...
220
221
222
223
  		ret = devm_clk_hw_register(&pdev->dev,
  					   data->onecell_data->hws[i]);
  		if (ret)
  			return ret;
0bbd72b4c   Neil Armstrong   clk: Add Oxford S...
224
  	}
5a9e54a81   Neil Armstrong   clk: oxnas: Refac...
225
226
  	return of_clk_add_hw_provider(np, of_clk_hw_onecell_get,
  				      data->onecell_data);
0bbd72b4c   Neil Armstrong   clk: Add Oxford S...
227
  }
0bbd72b4c   Neil Armstrong   clk: Add Oxford S...
228
229
  static struct platform_driver oxnas_stdclk_driver = {
  	.probe = oxnas_stdclk_probe,
0bbd72b4c   Neil Armstrong   clk: Add Oxford S...
230
231
  	.driver	= {
  		.name = "oxnas-stdclk",
80c6397c3   Paul Gortmaker   clk: oxnas: make ...
232
  		.suppress_bind_attrs = true,
0bbd72b4c   Neil Armstrong   clk: Add Oxford S...
233
234
235
  		.of_match_table = oxnas_stdclk_dt_ids,
  	},
  };
80c6397c3   Paul Gortmaker   clk: oxnas: make ...
236
  builtin_platform_driver(oxnas_stdclk_driver);