Linux Audio

Check our new training course

Loading...
Note: File does not exist in v3.5.6.
  1// SPDX-License-Identifier: GPL-2.0-only
  2
  3#include <linux/delay.h>
  4#include <linux/clk-provider.h>
  5#include <linux/of.h>
  6#include <linux/of_address.h>
  7#include <linux/of_device.h>
  8#include <linux/platform_device.h>
  9#include <dt-bindings/clock/en7523-clk.h>
 10
 11#define REG_PCI_CONTROL			0x88
 12#define   REG_PCI_CONTROL_PERSTOUT	BIT(29)
 13#define   REG_PCI_CONTROL_PERSTOUT1	BIT(26)
 14#define   REG_PCI_CONTROL_REFCLK_EN1	BIT(22)
 15#define REG_GSW_CLK_DIV_SEL		0x1b4
 16#define REG_EMI_CLK_DIV_SEL		0x1b8
 17#define REG_BUS_CLK_DIV_SEL		0x1bc
 18#define REG_SPI_CLK_DIV_SEL		0x1c4
 19#define REG_SPI_CLK_FREQ_SEL		0x1c8
 20#define REG_NPU_CLK_DIV_SEL		0x1fc
 21#define REG_CRYPTO_CLKSRC		0x200
 22#define REG_RESET_CONTROL		0x834
 23#define   REG_RESET_CONTROL_PCIEHB	BIT(29)
 24#define   REG_RESET_CONTROL_PCIE1	BIT(27)
 25#define   REG_RESET_CONTROL_PCIE2	BIT(26)
 26
 27struct en_clk_desc {
 28	int id;
 29	const char *name;
 30	u32 base_reg;
 31	u8 base_bits;
 32	u8 base_shift;
 33	union {
 34		const unsigned int *base_values;
 35		unsigned int base_value;
 36	};
 37	size_t n_base_values;
 38
 39	u16 div_reg;
 40	u8 div_bits;
 41	u8 div_shift;
 42	u16 div_val0;
 43	u8 div_step;
 44};
 45
 46struct en_clk_gate {
 47	void __iomem *base;
 48	struct clk_hw hw;
 49};
 50
 51static const u32 gsw_base[] = { 400000000, 500000000 };
 52static const u32 emi_base[] = { 333000000, 400000000 };
 53static const u32 bus_base[] = { 500000000, 540000000 };
 54static const u32 slic_base[] = { 100000000, 3125000 };
 55static const u32 npu_base[] = { 333000000, 400000000, 500000000 };
 56
 57static const struct en_clk_desc en7523_base_clks[] = {
 58	{
 59		.id = EN7523_CLK_GSW,
 60		.name = "gsw",
 61
 62		.base_reg = REG_GSW_CLK_DIV_SEL,
 63		.base_bits = 1,
 64		.base_shift = 8,
 65		.base_values = gsw_base,
 66		.n_base_values = ARRAY_SIZE(gsw_base),
 67
 68		.div_bits = 3,
 69		.div_shift = 0,
 70		.div_step = 1,
 71	}, {
 72		.id = EN7523_CLK_EMI,
 73		.name = "emi",
 74
 75		.base_reg = REG_EMI_CLK_DIV_SEL,
 76		.base_bits = 1,
 77		.base_shift = 8,
 78		.base_values = emi_base,
 79		.n_base_values = ARRAY_SIZE(emi_base),
 80
 81		.div_bits = 3,
 82		.div_shift = 0,
 83		.div_step = 1,
 84	}, {
 85		.id = EN7523_CLK_BUS,
 86		.name = "bus",
 87
 88		.base_reg = REG_BUS_CLK_DIV_SEL,
 89		.base_bits = 1,
 90		.base_shift = 8,
 91		.base_values = bus_base,
 92		.n_base_values = ARRAY_SIZE(bus_base),
 93
 94		.div_bits = 3,
 95		.div_shift = 0,
 96		.div_step = 1,
 97	}, {
 98		.id = EN7523_CLK_SLIC,
 99		.name = "slic",
100
101		.base_reg = REG_SPI_CLK_FREQ_SEL,
102		.base_bits = 1,
103		.base_shift = 0,
104		.base_values = slic_base,
105		.n_base_values = ARRAY_SIZE(slic_base),
106
107		.div_reg = REG_SPI_CLK_DIV_SEL,
108		.div_bits = 5,
109		.div_shift = 24,
110		.div_val0 = 20,
111		.div_step = 2,
112	}, {
113		.id = EN7523_CLK_SPI,
114		.name = "spi",
115
116		.base_reg = REG_SPI_CLK_DIV_SEL,
117
118		.base_value = 400000000,
119
120		.div_bits = 5,
121		.div_shift = 8,
122		.div_val0 = 40,
123		.div_step = 2,
124	}, {
125		.id = EN7523_CLK_NPU,
126		.name = "npu",
127
128		.base_reg = REG_NPU_CLK_DIV_SEL,
129		.base_bits = 2,
130		.base_shift = 8,
131		.base_values = npu_base,
132		.n_base_values = ARRAY_SIZE(npu_base),
133
134		.div_bits = 3,
135		.div_shift = 0,
136		.div_step = 1,
137	}, {
138		.id = EN7523_CLK_CRYPTO,
139		.name = "crypto",
140
141		.base_reg = REG_CRYPTO_CLKSRC,
142		.base_bits = 1,
143		.base_shift = 8,
144		.base_values = emi_base,
145		.n_base_values = ARRAY_SIZE(emi_base),
146	}
147};
148
149static const struct of_device_id of_match_clk_en7523[] = {
150	{ .compatible = "airoha,en7523-scu", },
151	{ /* sentinel */ }
152};
153
154static unsigned int en7523_get_base_rate(void __iomem *base, unsigned int i)
155{
156	const struct en_clk_desc *desc = &en7523_base_clks[i];
157	u32 val;
158
159	if (!desc->base_bits)
160		return desc->base_value;
161
162	val = readl(base + desc->base_reg);
163	val >>= desc->base_shift;
164	val &= (1 << desc->base_bits) - 1;
165
166	if (val >= desc->n_base_values)
167		return 0;
168
169	return desc->base_values[val];
170}
171
172static u32 en7523_get_div(void __iomem *base, int i)
173{
174	const struct en_clk_desc *desc = &en7523_base_clks[i];
175	u32 reg, val;
176
177	if (!desc->div_bits)
178		return 1;
179
180	reg = desc->div_reg ? desc->div_reg : desc->base_reg;
181	val = readl(base + reg);
182	val >>= desc->div_shift;
183	val &= (1 << desc->div_bits) - 1;
184
185	if (!val && desc->div_val0)
186		return desc->div_val0;
187
188	return (val + 1) * desc->div_step;
189}
190
191static int en7523_pci_is_enabled(struct clk_hw *hw)
192{
193	struct en_clk_gate *cg = container_of(hw, struct en_clk_gate, hw);
194
195	return !!(readl(cg->base + REG_PCI_CONTROL) & REG_PCI_CONTROL_REFCLK_EN1);
196}
197
198static int en7523_pci_prepare(struct clk_hw *hw)
199{
200	struct en_clk_gate *cg = container_of(hw, struct en_clk_gate, hw);
201	void __iomem *np_base = cg->base;
202	u32 val, mask;
203
204	/* Need to pull device low before reset */
205	val = readl(np_base + REG_PCI_CONTROL);
206	val &= ~(REG_PCI_CONTROL_PERSTOUT1 | REG_PCI_CONTROL_PERSTOUT);
207	writel(val, np_base + REG_PCI_CONTROL);
208	usleep_range(1000, 2000);
209
210	/* Enable PCIe port 1 */
211	val |= REG_PCI_CONTROL_REFCLK_EN1;
212	writel(val, np_base + REG_PCI_CONTROL);
213	usleep_range(1000, 2000);
214
215	/* Reset to default */
216	val = readl(np_base + REG_RESET_CONTROL);
217	mask = REG_RESET_CONTROL_PCIE1 | REG_RESET_CONTROL_PCIE2 |
218	       REG_RESET_CONTROL_PCIEHB;
219	writel(val & ~mask, np_base + REG_RESET_CONTROL);
220	usleep_range(1000, 2000);
221	writel(val | mask, np_base + REG_RESET_CONTROL);
222	msleep(100);
223	writel(val & ~mask, np_base + REG_RESET_CONTROL);
224	usleep_range(5000, 10000);
225
226	/* Release device */
227	mask = REG_PCI_CONTROL_PERSTOUT1 | REG_PCI_CONTROL_PERSTOUT;
228	val = readl(np_base + REG_PCI_CONTROL);
229	writel(val & ~mask, np_base + REG_PCI_CONTROL);
230	usleep_range(1000, 2000);
231	writel(val | mask, np_base + REG_PCI_CONTROL);
232	msleep(250);
233
234	return 0;
235}
236
237static void en7523_pci_unprepare(struct clk_hw *hw)
238{
239	struct en_clk_gate *cg = container_of(hw, struct en_clk_gate, hw);
240	void __iomem *np_base = cg->base;
241	u32 val;
242
243	val = readl(np_base + REG_PCI_CONTROL);
244	val &= ~REG_PCI_CONTROL_REFCLK_EN1;
245	writel(val, np_base + REG_PCI_CONTROL);
246}
247
248static struct clk_hw *en7523_register_pcie_clk(struct device *dev,
249					       void __iomem *np_base)
250{
251	static const struct clk_ops pcie_gate_ops = {
252		.is_enabled = en7523_pci_is_enabled,
253		.prepare = en7523_pci_prepare,
254		.unprepare = en7523_pci_unprepare,
255	};
256	struct clk_init_data init = {
257		.name = "pcie",
258		.ops = &pcie_gate_ops,
259	};
260	struct en_clk_gate *cg;
261
262	cg = devm_kzalloc(dev, sizeof(*cg), GFP_KERNEL);
263	if (!cg)
264		return NULL;
265
266	cg->base = np_base;
267	cg->hw.init = &init;
268	en7523_pci_unprepare(&cg->hw);
269
270	if (clk_hw_register(dev, &cg->hw))
271		return NULL;
272
273	return &cg->hw;
274}
275
276static void en7523_register_clocks(struct device *dev, struct clk_hw_onecell_data *clk_data,
277				   void __iomem *base, void __iomem *np_base)
278{
279	struct clk_hw *hw;
280	u32 rate;
281	int i;
282
283	for (i = 0; i < ARRAY_SIZE(en7523_base_clks); i++) {
284		const struct en_clk_desc *desc = &en7523_base_clks[i];
285
286		rate = en7523_get_base_rate(base, i);
287		rate /= en7523_get_div(base, i);
288
289		hw = clk_hw_register_fixed_rate(dev, desc->name, NULL, 0, rate);
290		if (IS_ERR(hw)) {
291			pr_err("Failed to register clk %s: %ld\n",
292			       desc->name, PTR_ERR(hw));
293			continue;
294		}
295
296		clk_data->hws[desc->id] = hw;
297	}
298
299	hw = en7523_register_pcie_clk(dev, np_base);
300	clk_data->hws[EN7523_CLK_PCIE] = hw;
301
302	clk_data->num = EN7523_NUM_CLOCKS;
303}
304
305static int en7523_clk_probe(struct platform_device *pdev)
306{
307	struct device_node *node = pdev->dev.of_node;
308	struct clk_hw_onecell_data *clk_data;
309	void __iomem *base, *np_base;
310	int r;
311
312	base = devm_platform_ioremap_resource(pdev, 0);
313	if (IS_ERR(base))
314		return PTR_ERR(base);
315
316	np_base = devm_platform_ioremap_resource(pdev, 1);
317	if (IS_ERR(np_base))
318		return PTR_ERR(np_base);
319
320	clk_data = devm_kzalloc(&pdev->dev,
321				struct_size(clk_data, hws, EN7523_NUM_CLOCKS),
322				GFP_KERNEL);
323	if (!clk_data)
324		return -ENOMEM;
325
326	en7523_register_clocks(&pdev->dev, clk_data, base, np_base);
327
328	r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data);
329	if (r)
330		dev_err(&pdev->dev,
331			"could not register clock provider: %s: %d\n",
332			pdev->name, r);
333
334	return r;
335}
336
337static struct platform_driver clk_en7523_drv = {
338	.probe = en7523_clk_probe,
339	.driver = {
340		.name = "clk-en7523",
341		.of_match_table = of_match_clk_en7523,
342		.suppress_bind_attrs = true,
343	},
344};
345
346static int __init clk_en7523_init(void)
347{
348	return platform_driver_register(&clk_en7523_drv);
349}
350
351arch_initcall(clk_en7523_init);