Linux Audio

Check our new training course

Open-source upstreaming

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