Linux Audio

Check our new training course

Yocto distribution development and maintenance

Need a Yocto distribution for your embedded project?
Loading...
v6.8
  1// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
  2/* Copyright 2019 NXP */
  3
  4#include <linux/fsl/enetc_mdio.h>
  5#include <linux/mdio.h>
  6#include <linux/of_mdio.h>
  7#include <linux/iopoll.h>
  8#include <linux/of.h>
  9
 10#include "enetc_pf.h"
 11
 12#define	ENETC_MDIO_CFG	0x0	/* MDIO configuration and status */
 13#define	ENETC_MDIO_CTL	0x4	/* MDIO control */
 14#define	ENETC_MDIO_DATA	0x8	/* MDIO data */
 15#define	ENETC_MDIO_ADDR	0xc	/* MDIO address */
 16
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 17#define MDIO_CFG_CLKDIV(x)	((((x) >> 1) & 0xff) << 8)
 18#define MDIO_CFG_BSY		BIT(0)
 19#define MDIO_CFG_RD_ER		BIT(1)
 20#define MDIO_CFG_HOLD(x)	(((x) << 2) & GENMASK(4, 2))
 21#define MDIO_CFG_ENC45		BIT(6)
 22 /* external MDIO only - driven on neg MDC edge */
 23#define MDIO_CFG_NEG		BIT(23)
 24
 25#define ENETC_EMDIO_CFG \
 26	(MDIO_CFG_HOLD(2) | \
 27	 MDIO_CFG_CLKDIV(258) | \
 28	 MDIO_CFG_NEG)
 29
 30#define MDIO_CTL_DEV_ADDR(x)	((x) & 0x1f)
 31#define MDIO_CTL_PORT_ADDR(x)	(((x) & 0x1f) << 5)
 32#define MDIO_CTL_READ		BIT(15)
 
 33
 34static inline u32 enetc_mdio_rd(struct enetc_mdio_priv *mdio_priv, int off)
 35{
 36	return enetc_port_rd_mdio(mdio_priv->hw, mdio_priv->mdio_base + off);
 37}
 38
 39static inline void enetc_mdio_wr(struct enetc_mdio_priv *mdio_priv, int off,
 40				 u32 val)
 41{
 42	enetc_port_wr_mdio(mdio_priv->hw, mdio_priv->mdio_base + off, val);
 43}
 44
 45static bool enetc_mdio_is_busy(struct enetc_mdio_priv *mdio_priv)
 46{
 47	return enetc_mdio_rd(mdio_priv, ENETC_MDIO_CFG) & MDIO_CFG_BSY;
 48}
 49
 50static int enetc_mdio_wait_complete(struct enetc_mdio_priv *mdio_priv)
 51{
 52	bool is_busy;
 53
 54	return readx_poll_timeout(enetc_mdio_is_busy, mdio_priv,
 55				  is_busy, !is_busy, 10, 10 * 1000);
 56}
 57
 58int enetc_mdio_write_c22(struct mii_bus *bus, int phy_id, int regnum,
 59			 u16 value)
 60{
 61	struct enetc_mdio_priv *mdio_priv = bus->priv;
 62	u32 mdio_ctl, mdio_cfg;
 63	u16 dev_addr;
 64	int ret;
 65
 66	mdio_cfg = ENETC_EMDIO_CFG;
 67	dev_addr = regnum & 0x1f;
 68	mdio_cfg &= ~MDIO_CFG_ENC45;
 69
 70	enetc_mdio_wr(mdio_priv, ENETC_MDIO_CFG, mdio_cfg);
 71
 72	ret = enetc_mdio_wait_complete(mdio_priv);
 73	if (ret)
 74		return ret;
 75
 76	/* set port and dev addr */
 77	mdio_ctl = MDIO_CTL_PORT_ADDR(phy_id) | MDIO_CTL_DEV_ADDR(dev_addr);
 78	enetc_mdio_wr(mdio_priv, ENETC_MDIO_CTL, mdio_ctl);
 79
 80	/* write the value */
 81	enetc_mdio_wr(mdio_priv, ENETC_MDIO_DATA, value);
 82
 83	ret = enetc_mdio_wait_complete(mdio_priv);
 84	if (ret)
 85		return ret;
 86
 87	return 0;
 88}
 89EXPORT_SYMBOL_GPL(enetc_mdio_write_c22);
 90
 91int enetc_mdio_write_c45(struct mii_bus *bus, int phy_id, int dev_addr,
 92			 int regnum, u16 value)
 93{
 94	struct enetc_mdio_priv *mdio_priv = bus->priv;
 95	u32 mdio_ctl, mdio_cfg;
 96	int ret;
 97
 98	mdio_cfg = ENETC_EMDIO_CFG;
 99	mdio_cfg |= MDIO_CFG_ENC45;
100
101	enetc_mdio_wr(mdio_priv, ENETC_MDIO_CFG, mdio_cfg);
102
103	ret = enetc_mdio_wait_complete(mdio_priv);
104	if (ret)
105		return ret;
106
107	/* set port and dev addr */
108	mdio_ctl = MDIO_CTL_PORT_ADDR(phy_id) | MDIO_CTL_DEV_ADDR(dev_addr);
109	enetc_mdio_wr(mdio_priv, ENETC_MDIO_CTL, mdio_ctl);
110
111	/* set the register address */
112	enetc_mdio_wr(mdio_priv, ENETC_MDIO_ADDR, regnum & 0xffff);
 
113
114	ret = enetc_mdio_wait_complete(mdio_priv);
115	if (ret)
116		return ret;
 
117
118	/* write the value */
119	enetc_mdio_wr(mdio_priv, ENETC_MDIO_DATA, value);
120
121	ret = enetc_mdio_wait_complete(mdio_priv);
122	if (ret)
123		return ret;
124
125	return 0;
126}
127EXPORT_SYMBOL_GPL(enetc_mdio_write_c45);
128
129int enetc_mdio_read_c22(struct mii_bus *bus, int phy_id, int regnum)
130{
131	struct enetc_mdio_priv *mdio_priv = bus->priv;
132	u32 mdio_ctl, mdio_cfg;
133	u16 dev_addr, value;
134	int ret;
135
136	mdio_cfg = ENETC_EMDIO_CFG;
137	dev_addr = regnum & 0x1f;
138	mdio_cfg &= ~MDIO_CFG_ENC45;
139
140	enetc_mdio_wr(mdio_priv, ENETC_MDIO_CFG, mdio_cfg);
141
142	ret = enetc_mdio_wait_complete(mdio_priv);
143	if (ret)
144		return ret;
145
146	/* set port and device addr */
147	mdio_ctl = MDIO_CTL_PORT_ADDR(phy_id) | MDIO_CTL_DEV_ADDR(dev_addr);
148	enetc_mdio_wr(mdio_priv, ENETC_MDIO_CTL, mdio_ctl);
149
150	/* initiate the read */
151	enetc_mdio_wr(mdio_priv, ENETC_MDIO_CTL, mdio_ctl | MDIO_CTL_READ);
152
153	ret = enetc_mdio_wait_complete(mdio_priv);
154	if (ret)
155		return ret;
156
157	/* return all Fs if nothing was there */
158	if (enetc_mdio_rd(mdio_priv, ENETC_MDIO_CFG) & MDIO_CFG_RD_ER) {
159		dev_dbg(&bus->dev,
160			"Error while reading PHY%d reg at %d.%d\n",
161			phy_id, dev_addr, regnum);
162		return 0xffff;
163	}
164
165	value = enetc_mdio_rd(mdio_priv, ENETC_MDIO_DATA) & 0xffff;
166
167	return value;
168}
169EXPORT_SYMBOL_GPL(enetc_mdio_read_c22);
170
171int enetc_mdio_read_c45(struct mii_bus *bus, int phy_id, int dev_addr,
172			int regnum)
173{
174	struct enetc_mdio_priv *mdio_priv = bus->priv;
175	u32 mdio_ctl, mdio_cfg;
176	u16 value;
177	int ret;
178
179	mdio_cfg = ENETC_EMDIO_CFG;
180	mdio_cfg |= MDIO_CFG_ENC45;
181
182	enetc_mdio_wr(mdio_priv, ENETC_MDIO_CFG, mdio_cfg);
183
184	ret = enetc_mdio_wait_complete(mdio_priv);
185	if (ret)
186		return ret;
187
188	/* set port and device addr */
189	mdio_ctl = MDIO_CTL_PORT_ADDR(phy_id) | MDIO_CTL_DEV_ADDR(dev_addr);
190	enetc_mdio_wr(mdio_priv, ENETC_MDIO_CTL, mdio_ctl);
191
192	/* set the register address */
193	enetc_mdio_wr(mdio_priv, ENETC_MDIO_ADDR, regnum & 0xffff);
 
194
195	ret = enetc_mdio_wait_complete(mdio_priv);
196	if (ret)
197		return ret;
 
198
199	/* initiate the read */
200	enetc_mdio_wr(mdio_priv, ENETC_MDIO_CTL, mdio_ctl | MDIO_CTL_READ);
201
202	ret = enetc_mdio_wait_complete(mdio_priv);
203	if (ret)
204		return ret;
205
206	/* return all Fs if nothing was there */
207	if (enetc_mdio_rd(mdio_priv, ENETC_MDIO_CFG) & MDIO_CFG_RD_ER) {
208		dev_dbg(&bus->dev,
209			"Error while reading PHY%d reg at %d.%d\n",
210			phy_id, dev_addr, regnum);
211		return 0xffff;
212	}
213
214	value = enetc_mdio_rd(mdio_priv, ENETC_MDIO_DATA) & 0xffff;
215
216	return value;
217}
218EXPORT_SYMBOL_GPL(enetc_mdio_read_c45);
219
220struct enetc_hw *enetc_hw_alloc(struct device *dev, void __iomem *port_regs)
221{
222	struct enetc_hw *hw;
223
224	hw = devm_kzalloc(dev, sizeof(*hw), GFP_KERNEL);
225	if (!hw)
226		return ERR_PTR(-ENOMEM);
227
228	hw->port = port_regs;
229
230	return hw;
231}
232EXPORT_SYMBOL_GPL(enetc_hw_alloc);
233
234/* Lock for MDIO access errata on LS1028A */
235DEFINE_RWLOCK(enetc_mdio_lock);
236EXPORT_SYMBOL_GPL(enetc_mdio_lock);
v5.9
  1// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
  2/* Copyright 2019 NXP */
  3
  4#include <linux/fsl/enetc_mdio.h>
  5#include <linux/mdio.h>
  6#include <linux/of_mdio.h>
  7#include <linux/iopoll.h>
  8#include <linux/of.h>
  9
 10#include "enetc_pf.h"
 11
 12#define	ENETC_MDIO_CFG	0x0	/* MDIO configuration and status */
 13#define	ENETC_MDIO_CTL	0x4	/* MDIO control */
 14#define	ENETC_MDIO_DATA	0x8	/* MDIO data */
 15#define	ENETC_MDIO_ADDR	0xc	/* MDIO address */
 16
 17static inline u32 _enetc_mdio_rd(struct enetc_mdio_priv *mdio_priv, int off)
 18{
 19	return enetc_port_rd(mdio_priv->hw, mdio_priv->mdio_base + off);
 20}
 21
 22static inline void _enetc_mdio_wr(struct enetc_mdio_priv *mdio_priv, int off,
 23				  u32 val)
 24{
 25	enetc_port_wr(mdio_priv->hw, mdio_priv->mdio_base + off, val);
 26}
 27
 28#define enetc_mdio_rd(mdio_priv, off) \
 29	_enetc_mdio_rd(mdio_priv, ENETC_##off)
 30#define enetc_mdio_wr(mdio_priv, off, val) \
 31	_enetc_mdio_wr(mdio_priv, ENETC_##off, val)
 32#define enetc_mdio_rd_reg(off)	enetc_mdio_rd(mdio_priv, off)
 33
 34#define MDIO_CFG_CLKDIV(x)	((((x) >> 1) & 0xff) << 8)
 35#define MDIO_CFG_BSY		BIT(0)
 36#define MDIO_CFG_RD_ER		BIT(1)
 37#define MDIO_CFG_HOLD(x)	(((x) << 2) & GENMASK(4, 2))
 38#define MDIO_CFG_ENC45		BIT(6)
 39 /* external MDIO only - driven on neg MDC edge */
 40#define MDIO_CFG_NEG		BIT(23)
 41
 42#define ENETC_EMDIO_CFG \
 43	(MDIO_CFG_HOLD(2) | \
 44	 MDIO_CFG_CLKDIV(258) | \
 45	 MDIO_CFG_NEG)
 46
 47#define MDIO_CTL_DEV_ADDR(x)	((x) & 0x1f)
 48#define MDIO_CTL_PORT_ADDR(x)	(((x) & 0x1f) << 5)
 49#define MDIO_CTL_READ		BIT(15)
 50#define MDIO_DATA(x)		((x) & 0xffff)
 51
 52#define TIMEOUT	1000
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 53static int enetc_mdio_wait_complete(struct enetc_mdio_priv *mdio_priv)
 54{
 55	u32 val;
 56
 57	return readx_poll_timeout(enetc_mdio_rd_reg, MDIO_CFG, val,
 58				  !(val & MDIO_CFG_BSY), 10, 10 * TIMEOUT);
 59}
 60
 61int enetc_mdio_write(struct mii_bus *bus, int phy_id, int regnum, u16 value)
 
 62{
 63	struct enetc_mdio_priv *mdio_priv = bus->priv;
 64	u32 mdio_ctl, mdio_cfg;
 65	u16 dev_addr;
 66	int ret;
 67
 68	mdio_cfg = ENETC_EMDIO_CFG;
 69	if (regnum & MII_ADDR_C45) {
 70		dev_addr = (regnum >> 16) & 0x1f;
 71		mdio_cfg |= MDIO_CFG_ENC45;
 72	} else {
 73		/* clause 22 (ie 1G) */
 74		dev_addr = regnum & 0x1f;
 75		mdio_cfg &= ~MDIO_CFG_ENC45;
 76	}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 77
 78	enetc_mdio_wr(mdio_priv, MDIO_CFG, mdio_cfg);
 79
 80	ret = enetc_mdio_wait_complete(mdio_priv);
 81	if (ret)
 82		return ret;
 83
 84	/* set port and dev addr */
 85	mdio_ctl = MDIO_CTL_PORT_ADDR(phy_id) | MDIO_CTL_DEV_ADDR(dev_addr);
 86	enetc_mdio_wr(mdio_priv, MDIO_CTL, mdio_ctl);
 87
 88	/* set the register address */
 89	if (regnum & MII_ADDR_C45) {
 90		enetc_mdio_wr(mdio_priv, MDIO_ADDR, regnum & 0xffff);
 91
 92		ret = enetc_mdio_wait_complete(mdio_priv);
 93		if (ret)
 94			return ret;
 95	}
 96
 97	/* write the value */
 98	enetc_mdio_wr(mdio_priv, MDIO_DATA, MDIO_DATA(value));
 99
100	ret = enetc_mdio_wait_complete(mdio_priv);
101	if (ret)
102		return ret;
103
104	return 0;
105}
106EXPORT_SYMBOL_GPL(enetc_mdio_write);
107
108int enetc_mdio_read(struct mii_bus *bus, int phy_id, int regnum)
109{
110	struct enetc_mdio_priv *mdio_priv = bus->priv;
111	u32 mdio_ctl, mdio_cfg;
112	u16 dev_addr, value;
113	int ret;
114
115	mdio_cfg = ENETC_EMDIO_CFG;
116	if (regnum & MII_ADDR_C45) {
117		dev_addr = (regnum >> 16) & 0x1f;
118		mdio_cfg |= MDIO_CFG_ENC45;
119	} else {
120		dev_addr = regnum & 0x1f;
121		mdio_cfg &= ~MDIO_CFG_ENC45;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
122	}
123
124	enetc_mdio_wr(mdio_priv, MDIO_CFG, mdio_cfg);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
125
126	ret = enetc_mdio_wait_complete(mdio_priv);
127	if (ret)
128		return ret;
129
130	/* set port and device addr */
131	mdio_ctl = MDIO_CTL_PORT_ADDR(phy_id) | MDIO_CTL_DEV_ADDR(dev_addr);
132	enetc_mdio_wr(mdio_priv, MDIO_CTL, mdio_ctl);
133
134	/* set the register address */
135	if (regnum & MII_ADDR_C45) {
136		enetc_mdio_wr(mdio_priv, MDIO_ADDR, regnum & 0xffff);
137
138		ret = enetc_mdio_wait_complete(mdio_priv);
139		if (ret)
140			return ret;
141	}
142
143	/* initiate the read */
144	enetc_mdio_wr(mdio_priv, MDIO_CTL, mdio_ctl | MDIO_CTL_READ);
145
146	ret = enetc_mdio_wait_complete(mdio_priv);
147	if (ret)
148		return ret;
149
150	/* return all Fs if nothing was there */
151	if (enetc_mdio_rd(mdio_priv, MDIO_CFG) & MDIO_CFG_RD_ER) {
152		dev_dbg(&bus->dev,
153			"Error while reading PHY%d reg at %d.%hhu\n",
154			phy_id, dev_addr, regnum);
155		return 0xffff;
156	}
157
158	value = enetc_mdio_rd(mdio_priv, MDIO_DATA) & 0xffff;
159
160	return value;
161}
162EXPORT_SYMBOL_GPL(enetc_mdio_read);
163
164struct enetc_hw *enetc_hw_alloc(struct device *dev, void __iomem *port_regs)
165{
166	struct enetc_hw *hw;
167
168	hw = devm_kzalloc(dev, sizeof(*hw), GFP_KERNEL);
169	if (!hw)
170		return ERR_PTR(-ENOMEM);
171
172	hw->port = port_regs;
173
174	return hw;
175}
176EXPORT_SYMBOL_GPL(enetc_hw_alloc);