Linux Audio

Check our new training course

Loading...
Note: File does not exist in v4.17.
  1// SPDX-License-Identifier: GPL-2.0
  2/* Copyright (c) 2019 Baylibre, SAS.
  3 * Author: Jerome Brunet <jbrunet@baylibre.com>
  4 */
  5
  6#include <linux/bitfield.h>
  7#include <linux/clk.h>
  8#include <linux/clk-provider.h>
  9#include <linux/device.h>
 10#include <linux/io.h>
 11#include <linux/iopoll.h>
 12#include <linux/mdio-mux.h>
 13#include <linux/module.h>
 14#include <linux/phy.h>
 15#include <linux/platform_device.h>
 16
 17#define ETH_PLL_STS		0x40
 18#define ETH_PLL_CTL0		0x44
 19#define  PLL_CTL0_LOCK_DIG	BIT(30)
 20#define  PLL_CTL0_RST		BIT(29)
 21#define  PLL_CTL0_EN		BIT(28)
 22#define  PLL_CTL0_SEL		BIT(23)
 23#define  PLL_CTL0_N		GENMASK(14, 10)
 24#define  PLL_CTL0_M		GENMASK(8, 0)
 25#define  PLL_LOCK_TIMEOUT	1000000
 26#define  PLL_MUX_NUM_PARENT	2
 27#define ETH_PLL_CTL1		0x48
 28#define ETH_PLL_CTL2		0x4c
 29#define ETH_PLL_CTL3		0x50
 30#define ETH_PLL_CTL4		0x54
 31#define ETH_PLL_CTL5		0x58
 32#define ETH_PLL_CTL6		0x5c
 33#define ETH_PLL_CTL7		0x60
 34
 35#define ETH_PHY_CNTL0		0x80
 36#define   EPHY_G12A_ID		0x33010180
 37#define ETH_PHY_CNTL1		0x84
 38#define  PHY_CNTL1_ST_MODE	GENMASK(2, 0)
 39#define  PHY_CNTL1_ST_PHYADD	GENMASK(7, 3)
 40#define   EPHY_DFLT_ADD		8
 41#define  PHY_CNTL1_MII_MODE	GENMASK(15, 14)
 42#define   EPHY_MODE_RMII	0x1
 43#define  PHY_CNTL1_CLK_EN	BIT(16)
 44#define  PHY_CNTL1_CLKFREQ	BIT(17)
 45#define  PHY_CNTL1_PHY_ENB	BIT(18)
 46#define ETH_PHY_CNTL2		0x88
 47#define  PHY_CNTL2_USE_INTERNAL	BIT(5)
 48#define  PHY_CNTL2_SMI_SRC_MAC	BIT(6)
 49#define  PHY_CNTL2_RX_CLK_EPHY	BIT(9)
 50
 51#define MESON_G12A_MDIO_EXTERNAL_ID 0
 52#define MESON_G12A_MDIO_INTERNAL_ID 1
 53
 54struct g12a_mdio_mux {
 55	bool pll_is_enabled;
 56	void __iomem *regs;
 57	void *mux_handle;
 58	struct clk *pclk;
 59	struct clk *pll;
 60};
 61
 62struct g12a_ephy_pll {
 63	void __iomem *base;
 64	struct clk_hw hw;
 65};
 66
 67#define g12a_ephy_pll_to_dev(_hw)			\
 68	container_of(_hw, struct g12a_ephy_pll, hw)
 69
 70static unsigned long g12a_ephy_pll_recalc_rate(struct clk_hw *hw,
 71					       unsigned long parent_rate)
 72{
 73	struct g12a_ephy_pll *pll = g12a_ephy_pll_to_dev(hw);
 74	u32 val, m, n;
 75
 76	val = readl(pll->base + ETH_PLL_CTL0);
 77	m = FIELD_GET(PLL_CTL0_M, val);
 78	n = FIELD_GET(PLL_CTL0_N, val);
 79
 80	return parent_rate * m / n;
 81}
 82
 83static int g12a_ephy_pll_enable(struct clk_hw *hw)
 84{
 85	struct g12a_ephy_pll *pll = g12a_ephy_pll_to_dev(hw);
 86	u32 val = readl(pll->base + ETH_PLL_CTL0);
 87
 88	/* Apply both enable an reset */
 89	val |= PLL_CTL0_RST | PLL_CTL0_EN;
 90	writel(val, pll->base + ETH_PLL_CTL0);
 91
 92	/* Clear the reset to let PLL lock */
 93	val &= ~PLL_CTL0_RST;
 94	writel(val, pll->base + ETH_PLL_CTL0);
 95
 96	/* Poll on the digital lock instead of the usual analog lock
 97	 * This is done because bit 31 is unreliable on some SoC. Bit
 98	 * 31 may indicate that the PLL is not lock eventhough the clock
 99	 * is actually running
100	 */
101	return readl_poll_timeout(pll->base + ETH_PLL_CTL0, val,
102				  val & PLL_CTL0_LOCK_DIG, 0, PLL_LOCK_TIMEOUT);
103}
104
105static void g12a_ephy_pll_disable(struct clk_hw *hw)
106{
107	struct g12a_ephy_pll *pll = g12a_ephy_pll_to_dev(hw);
108	u32 val;
109
110	val = readl(pll->base + ETH_PLL_CTL0);
111	val &= ~PLL_CTL0_EN;
112	val |= PLL_CTL0_RST;
113	writel(val, pll->base + ETH_PLL_CTL0);
114}
115
116static int g12a_ephy_pll_is_enabled(struct clk_hw *hw)
117{
118	struct g12a_ephy_pll *pll = g12a_ephy_pll_to_dev(hw);
119	unsigned int val;
120
121	val = readl(pll->base + ETH_PLL_CTL0);
122
123	return (val & PLL_CTL0_LOCK_DIG) ? 1 : 0;
124}
125
126static int g12a_ephy_pll_init(struct clk_hw *hw)
127{
128	struct g12a_ephy_pll *pll = g12a_ephy_pll_to_dev(hw);
129
130	/* Apply PLL HW settings */
131	writel(0x29c0040a, pll->base + ETH_PLL_CTL0);
132	writel(0x927e0000, pll->base + ETH_PLL_CTL1);
133	writel(0xac5f49e5, pll->base + ETH_PLL_CTL2);
134	writel(0x00000000, pll->base + ETH_PLL_CTL3);
135	writel(0x00000000, pll->base + ETH_PLL_CTL4);
136	writel(0x20200000, pll->base + ETH_PLL_CTL5);
137	writel(0x0000c002, pll->base + ETH_PLL_CTL6);
138	writel(0x00000023, pll->base + ETH_PLL_CTL7);
139
140	return 0;
141}
142
143static const struct clk_ops g12a_ephy_pll_ops = {
144	.recalc_rate	= g12a_ephy_pll_recalc_rate,
145	.is_enabled	= g12a_ephy_pll_is_enabled,
146	.enable		= g12a_ephy_pll_enable,
147	.disable	= g12a_ephy_pll_disable,
148	.init		= g12a_ephy_pll_init,
149};
150
151static int g12a_enable_internal_mdio(struct g12a_mdio_mux *priv)
152{
153	int ret;
154
155	/* Enable the phy clock */
156	if (!priv->pll_is_enabled) {
157		ret = clk_prepare_enable(priv->pll);
158		if (ret)
159			return ret;
160	}
161
162	priv->pll_is_enabled = true;
163
164	/* Initialize ephy control */
165	writel(EPHY_G12A_ID, priv->regs + ETH_PHY_CNTL0);
166	writel(FIELD_PREP(PHY_CNTL1_ST_MODE, 3) |
167	       FIELD_PREP(PHY_CNTL1_ST_PHYADD, EPHY_DFLT_ADD) |
168	       FIELD_PREP(PHY_CNTL1_MII_MODE, EPHY_MODE_RMII) |
169	       PHY_CNTL1_CLK_EN |
170	       PHY_CNTL1_CLKFREQ |
171	       PHY_CNTL1_PHY_ENB,
172	       priv->regs + ETH_PHY_CNTL1);
173	writel(PHY_CNTL2_USE_INTERNAL |
174	       PHY_CNTL2_SMI_SRC_MAC |
175	       PHY_CNTL2_RX_CLK_EPHY,
176	       priv->regs + ETH_PHY_CNTL2);
177
178	return 0;
179}
180
181static int g12a_enable_external_mdio(struct g12a_mdio_mux *priv)
182{
183	/* Reset the mdio bus mux */
184	writel_relaxed(0x0, priv->regs + ETH_PHY_CNTL2);
185
186	/* Disable the phy clock if enabled */
187	if (priv->pll_is_enabled) {
188		clk_disable_unprepare(priv->pll);
189		priv->pll_is_enabled = false;
190	}
191
192	return 0;
193}
194
195static int g12a_mdio_switch_fn(int current_child, int desired_child,
196			       void *data)
197{
198	struct g12a_mdio_mux *priv = dev_get_drvdata(data);
199
200	if (current_child == desired_child)
201		return 0;
202
203	switch (desired_child) {
204	case MESON_G12A_MDIO_EXTERNAL_ID:
205		return g12a_enable_external_mdio(priv);
206	case MESON_G12A_MDIO_INTERNAL_ID:
207		return g12a_enable_internal_mdio(priv);
208	default:
209		return -EINVAL;
210	}
211}
212
213static const struct of_device_id g12a_mdio_mux_match[] = {
214	{ .compatible = "amlogic,g12a-mdio-mux", },
215	{},
216};
217MODULE_DEVICE_TABLE(of, g12a_mdio_mux_match);
218
219static int g12a_ephy_glue_clk_register(struct device *dev)
220{
221	struct g12a_mdio_mux *priv = dev_get_drvdata(dev);
222	const char *parent_names[PLL_MUX_NUM_PARENT];
223	struct clk_init_data init;
224	struct g12a_ephy_pll *pll;
225	struct clk_mux *mux;
226	struct clk *clk;
227	char *name;
228	int i;
229
230	/* get the mux parents */
231	for (i = 0; i < PLL_MUX_NUM_PARENT; i++) {
232		char in_name[8];
233
234		snprintf(in_name, sizeof(in_name), "clkin%d", i);
235		clk = devm_clk_get(dev, in_name);
236		if (IS_ERR(clk)) {
237			if (PTR_ERR(clk) != -EPROBE_DEFER)
238				dev_err(dev, "Missing clock %s\n", in_name);
239			return PTR_ERR(clk);
240		}
241
242		parent_names[i] = __clk_get_name(clk);
243	}
244
245	/* create the input mux */
246	mux = devm_kzalloc(dev, sizeof(*mux), GFP_KERNEL);
247	if (!mux)
248		return -ENOMEM;
249
250	name = kasprintf(GFP_KERNEL, "%s#mux", dev_name(dev));
251	if (!name)
252		return -ENOMEM;
253
254	init.name = name;
255	init.ops = &clk_mux_ro_ops;
256	init.flags = 0;
257	init.parent_names = parent_names;
258	init.num_parents = PLL_MUX_NUM_PARENT;
259
260	mux->reg = priv->regs + ETH_PLL_CTL0;
261	mux->shift = __ffs(PLL_CTL0_SEL);
262	mux->mask = PLL_CTL0_SEL >> mux->shift;
263	mux->hw.init = &init;
264
265	clk = devm_clk_register(dev, &mux->hw);
266	kfree(name);
267	if (IS_ERR(clk)) {
268		dev_err(dev, "failed to register input mux\n");
269		return PTR_ERR(clk);
270	}
271
272	/* create the pll */
273	pll = devm_kzalloc(dev, sizeof(*pll), GFP_KERNEL);
274	if (!pll)
275		return -ENOMEM;
276
277	name = kasprintf(GFP_KERNEL, "%s#pll", dev_name(dev));
278	if (!name)
279		return -ENOMEM;
280
281	init.name = name;
282	init.ops = &g12a_ephy_pll_ops;
283	init.flags = 0;
284	parent_names[0] = __clk_get_name(clk);
285	init.parent_names = parent_names;
286	init.num_parents = 1;
287
288	pll->base = priv->regs;
289	pll->hw.init = &init;
290
291	clk = devm_clk_register(dev, &pll->hw);
292	kfree(name);
293	if (IS_ERR(clk)) {
294		dev_err(dev, "failed to register input mux\n");
295		return PTR_ERR(clk);
296	}
297
298	priv->pll = clk;
299
300	return 0;
301}
302
303static int g12a_mdio_mux_probe(struct platform_device *pdev)
304{
305	struct device *dev = &pdev->dev;
306	struct g12a_mdio_mux *priv;
307	int ret;
308
309	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
310	if (!priv)
311		return -ENOMEM;
312
313	platform_set_drvdata(pdev, priv);
314
315	priv->regs = devm_platform_ioremap_resource(pdev, 0);
316	if (IS_ERR(priv->regs))
317		return PTR_ERR(priv->regs);
318
319	priv->pclk = devm_clk_get(dev, "pclk");
320	if (IS_ERR(priv->pclk)) {
321		ret = PTR_ERR(priv->pclk);
322		if (ret != -EPROBE_DEFER)
323			dev_err(dev, "failed to get peripheral clock\n");
324		return ret;
325	}
326
327	/* Make sure the device registers are clocked */
328	ret = clk_prepare_enable(priv->pclk);
329	if (ret) {
330		dev_err(dev, "failed to enable peripheral clock");
331		return ret;
332	}
333
334	/* Register PLL in CCF */
335	ret = g12a_ephy_glue_clk_register(dev);
336	if (ret)
337		goto err;
338
339	ret = mdio_mux_init(dev, dev->of_node, g12a_mdio_switch_fn,
340			    &priv->mux_handle, dev, NULL);
341	if (ret) {
342		if (ret != -EPROBE_DEFER)
343			dev_err(dev, "mdio multiplexer init failed: %d", ret);
344		goto err;
345	}
346
347	return 0;
348
349err:
350	clk_disable_unprepare(priv->pclk);
351	return ret;
352}
353
354static int g12a_mdio_mux_remove(struct platform_device *pdev)
355{
356	struct g12a_mdio_mux *priv = platform_get_drvdata(pdev);
357
358	mdio_mux_uninit(priv->mux_handle);
359
360	if (priv->pll_is_enabled)
361		clk_disable_unprepare(priv->pll);
362
363	clk_disable_unprepare(priv->pclk);
364
365	return 0;
366}
367
368static struct platform_driver g12a_mdio_mux_driver = {
369	.probe		= g12a_mdio_mux_probe,
370	.remove		= g12a_mdio_mux_remove,
371	.driver		= {
372		.name	= "g12a-mdio_mux",
373		.of_match_table = g12a_mdio_mux_match,
374	},
375};
376module_platform_driver(g12a_mdio_mux_driver);
377
378MODULE_DESCRIPTION("Amlogic G12a MDIO multiplexer driver");
379MODULE_AUTHOR("Jerome Brunet <jbrunet@baylibre.com>");
380MODULE_LICENSE("GPL v2");