Linux Audio

Check our new training course

Yocto distribution development and maintenance

Need a Yocto distribution for your embedded project?
Loading...
Note: File does not exist in v3.1.
  1// SPDX-License-Identifier: GPL-2.0
  2/* NXP TJA1100 BroadRReach PHY driver
  3 *
  4 * Copyright (C) 2018 Marek Vasut <marex@denx.de>
  5 */
  6#include <linux/delay.h>
  7#include <linux/ethtool.h>
  8#include <linux/kernel.h>
  9#include <linux/mii.h>
 10#include <linux/module.h>
 11#include <linux/phy.h>
 12#include <linux/hwmon.h>
 13#include <linux/bitfield.h>
 14
 15#define PHY_ID_MASK			0xfffffff0
 16#define PHY_ID_TJA1100			0x0180dc40
 17#define PHY_ID_TJA1101			0x0180dd00
 18
 19#define MII_ECTRL			17
 20#define MII_ECTRL_LINK_CONTROL		BIT(15)
 21#define MII_ECTRL_POWER_MODE_MASK	GENMASK(14, 11)
 22#define MII_ECTRL_POWER_MODE_NO_CHANGE	(0x0 << 11)
 23#define MII_ECTRL_POWER_MODE_NORMAL	(0x3 << 11)
 24#define MII_ECTRL_POWER_MODE_STANDBY	(0xc << 11)
 25#define MII_ECTRL_CONFIG_EN		BIT(2)
 26#define MII_ECTRL_WAKE_REQUEST		BIT(0)
 27
 28#define MII_CFG1			18
 29#define MII_CFG1_AUTO_OP		BIT(14)
 30#define MII_CFG1_SLEEP_CONFIRM		BIT(6)
 31#define MII_CFG1_LED_MODE_MASK		GENMASK(5, 4)
 32#define MII_CFG1_LED_MODE_LINKUP	0
 33#define MII_CFG1_LED_ENABLE		BIT(3)
 34
 35#define MII_CFG2			19
 36#define MII_CFG2_SLEEP_REQUEST_TO	GENMASK(1, 0)
 37#define MII_CFG2_SLEEP_REQUEST_TO_16MS	0x3
 38
 39#define MII_INTSRC			21
 40#define MII_INTSRC_TEMP_ERR		BIT(1)
 41#define MII_INTSRC_UV_ERR		BIT(3)
 42
 43#define MII_COMMSTAT			23
 44#define MII_COMMSTAT_LINK_UP		BIT(15)
 45
 46#define MII_GENSTAT			24
 47#define MII_GENSTAT_PLL_LOCKED		BIT(14)
 48
 49#define MII_COMMCFG			27
 50#define MII_COMMCFG_AUTO_OP		BIT(15)
 51
 52struct tja11xx_priv {
 53	char		*hwmon_name;
 54	struct device	*hwmon_dev;
 55};
 56
 57struct tja11xx_phy_stats {
 58	const char	*string;
 59	u8		reg;
 60	u8		off;
 61	u16		mask;
 62};
 63
 64static struct tja11xx_phy_stats tja11xx_hw_stats[] = {
 65	{ "phy_symbol_error_count", 20, 0, GENMASK(15, 0) },
 66	{ "phy_polarity_detect", 25, 6, BIT(6) },
 67	{ "phy_open_detect", 25, 7, BIT(7) },
 68	{ "phy_short_detect", 25, 8, BIT(8) },
 69	{ "phy_rem_rcvr_count", 26, 0, GENMASK(7, 0) },
 70	{ "phy_loc_rcvr_count", 26, 8, GENMASK(15, 8) },
 71};
 72
 73static int tja11xx_check(struct phy_device *phydev, u8 reg, u16 mask, u16 set)
 74{
 75	int i, ret;
 76
 77	for (i = 0; i < 200; i++) {
 78		ret = phy_read(phydev, reg);
 79		if (ret < 0)
 80			return ret;
 81
 82		if ((ret & mask) == set)
 83			return 0;
 84
 85		usleep_range(100, 150);
 86	}
 87
 88	return -ETIMEDOUT;
 89}
 90
 91static int phy_modify_check(struct phy_device *phydev, u8 reg,
 92			    u16 mask, u16 set)
 93{
 94	int ret;
 95
 96	ret = phy_modify(phydev, reg, mask, set);
 97	if (ret)
 98		return ret;
 99
100	return tja11xx_check(phydev, reg, mask, set);
101}
102
103static int tja11xx_enable_reg_write(struct phy_device *phydev)
104{
105	return phy_set_bits(phydev, MII_ECTRL, MII_ECTRL_CONFIG_EN);
106}
107
108static int tja11xx_enable_link_control(struct phy_device *phydev)
109{
110	return phy_set_bits(phydev, MII_ECTRL, MII_ECTRL_LINK_CONTROL);
111}
112
113static int tja11xx_wakeup(struct phy_device *phydev)
114{
115	int ret;
116
117	ret = phy_read(phydev, MII_ECTRL);
118	if (ret < 0)
119		return ret;
120
121	switch (ret & MII_ECTRL_POWER_MODE_MASK) {
122	case MII_ECTRL_POWER_MODE_NO_CHANGE:
123		break;
124	case MII_ECTRL_POWER_MODE_NORMAL:
125		ret = phy_set_bits(phydev, MII_ECTRL, MII_ECTRL_WAKE_REQUEST);
126		if (ret)
127			return ret;
128
129		ret = phy_clear_bits(phydev, MII_ECTRL, MII_ECTRL_WAKE_REQUEST);
130		if (ret)
131			return ret;
132		break;
133	case MII_ECTRL_POWER_MODE_STANDBY:
134		ret = phy_modify_check(phydev, MII_ECTRL,
135				       MII_ECTRL_POWER_MODE_MASK,
136				       MII_ECTRL_POWER_MODE_STANDBY);
137		if (ret)
138			return ret;
139
140		ret = phy_modify(phydev, MII_ECTRL, MII_ECTRL_POWER_MODE_MASK,
141				 MII_ECTRL_POWER_MODE_NORMAL);
142		if (ret)
143			return ret;
144
145		ret = phy_modify_check(phydev, MII_GENSTAT,
146				       MII_GENSTAT_PLL_LOCKED,
147				       MII_GENSTAT_PLL_LOCKED);
148		if (ret)
149			return ret;
150
151		return tja11xx_enable_link_control(phydev);
152	default:
153		break;
154	}
155
156	return 0;
157}
158
159static int tja11xx_soft_reset(struct phy_device *phydev)
160{
161	int ret;
162
163	ret = tja11xx_enable_reg_write(phydev);
164	if (ret)
165		return ret;
166
167	return genphy_soft_reset(phydev);
168}
169
170static int tja11xx_config_init(struct phy_device *phydev)
171{
172	int ret;
173
174	ret = tja11xx_enable_reg_write(phydev);
175	if (ret)
176		return ret;
177
178	phydev->autoneg = AUTONEG_DISABLE;
179	phydev->speed = SPEED_100;
180	phydev->duplex = DUPLEX_FULL;
181
182	switch (phydev->phy_id & PHY_ID_MASK) {
183	case PHY_ID_TJA1100:
184		ret = phy_modify(phydev, MII_CFG1,
185				 MII_CFG1_AUTO_OP | MII_CFG1_LED_MODE_MASK |
186				 MII_CFG1_LED_ENABLE,
187				 MII_CFG1_AUTO_OP | MII_CFG1_LED_MODE_LINKUP |
188				 MII_CFG1_LED_ENABLE);
189		if (ret)
190			return ret;
191		break;
192	case PHY_ID_TJA1101:
193		ret = phy_set_bits(phydev, MII_COMMCFG, MII_COMMCFG_AUTO_OP);
194		if (ret)
195			return ret;
196		break;
197	default:
198		return -EINVAL;
199	}
200
201	ret = phy_clear_bits(phydev, MII_CFG1, MII_CFG1_SLEEP_CONFIRM);
202	if (ret)
203		return ret;
204
205	ret = phy_modify(phydev, MII_CFG2, MII_CFG2_SLEEP_REQUEST_TO,
206			 MII_CFG2_SLEEP_REQUEST_TO_16MS);
207	if (ret)
208		return ret;
209
210	ret = tja11xx_wakeup(phydev);
211	if (ret < 0)
212		return ret;
213
214	/* ACK interrupts by reading the status register */
215	ret = phy_read(phydev, MII_INTSRC);
216	if (ret < 0)
217		return ret;
218
219	return 0;
220}
221
222static int tja11xx_read_status(struct phy_device *phydev)
223{
224	int ret;
225
226	ret = genphy_update_link(phydev);
227	if (ret)
228		return ret;
229
230	if (phydev->link) {
231		ret = phy_read(phydev, MII_COMMSTAT);
232		if (ret < 0)
233			return ret;
234
235		if (!(ret & MII_COMMSTAT_LINK_UP))
236			phydev->link = 0;
237	}
238
239	return 0;
240}
241
242static int tja11xx_get_sset_count(struct phy_device *phydev)
243{
244	return ARRAY_SIZE(tja11xx_hw_stats);
245}
246
247static void tja11xx_get_strings(struct phy_device *phydev, u8 *data)
248{
249	int i;
250
251	for (i = 0; i < ARRAY_SIZE(tja11xx_hw_stats); i++) {
252		strncpy(data + i * ETH_GSTRING_LEN,
253			tja11xx_hw_stats[i].string, ETH_GSTRING_LEN);
254	}
255}
256
257static void tja11xx_get_stats(struct phy_device *phydev,
258			      struct ethtool_stats *stats, u64 *data)
259{
260	int i, ret;
261
262	for (i = 0; i < ARRAY_SIZE(tja11xx_hw_stats); i++) {
263		ret = phy_read(phydev, tja11xx_hw_stats[i].reg);
264		if (ret < 0)
265			data[i] = U64_MAX;
266		else {
267			data[i] = ret & tja11xx_hw_stats[i].mask;
268			data[i] >>= tja11xx_hw_stats[i].off;
269		}
270	}
271}
272
273static int tja11xx_hwmon_read(struct device *dev,
274			      enum hwmon_sensor_types type,
275			      u32 attr, int channel, long *value)
276{
277	struct phy_device *phydev = dev_get_drvdata(dev);
278	int ret;
279
280	if (type == hwmon_in && attr == hwmon_in_lcrit_alarm) {
281		ret = phy_read(phydev, MII_INTSRC);
282		if (ret < 0)
283			return ret;
284
285		*value = !!(ret & MII_INTSRC_TEMP_ERR);
286		return 0;
287	}
288
289	if (type == hwmon_temp && attr == hwmon_temp_crit_alarm) {
290		ret = phy_read(phydev, MII_INTSRC);
291		if (ret < 0)
292			return ret;
293
294		*value = !!(ret & MII_INTSRC_UV_ERR);
295		return 0;
296	}
297
298	return -EOPNOTSUPP;
299}
300
301static umode_t tja11xx_hwmon_is_visible(const void *data,
302					enum hwmon_sensor_types type,
303					u32 attr, int channel)
304{
305	if (type == hwmon_in && attr == hwmon_in_lcrit_alarm)
306		return 0444;
307
308	if (type == hwmon_temp && attr == hwmon_temp_crit_alarm)
309		return 0444;
310
311	return 0;
312}
313
314static const struct hwmon_channel_info *tja11xx_hwmon_info[] = {
315	HWMON_CHANNEL_INFO(in, HWMON_I_LCRIT_ALARM),
316	HWMON_CHANNEL_INFO(temp, HWMON_T_CRIT_ALARM),
317	NULL
318};
319
320static const struct hwmon_ops tja11xx_hwmon_hwmon_ops = {
321	.is_visible	= tja11xx_hwmon_is_visible,
322	.read		= tja11xx_hwmon_read,
323};
324
325static const struct hwmon_chip_info tja11xx_hwmon_chip_info = {
326	.ops		= &tja11xx_hwmon_hwmon_ops,
327	.info		= tja11xx_hwmon_info,
328};
329
330static int tja11xx_probe(struct phy_device *phydev)
331{
332	struct device *dev = &phydev->mdio.dev;
333	struct tja11xx_priv *priv;
334	int i;
335
336	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
337	if (!priv)
338		return -ENOMEM;
339
340	priv->hwmon_name = devm_kstrdup(dev, dev_name(dev), GFP_KERNEL);
341	if (!priv->hwmon_name)
342		return -ENOMEM;
343
344	for (i = 0; priv->hwmon_name[i]; i++)
345		if (hwmon_is_bad_char(priv->hwmon_name[i]))
346			priv->hwmon_name[i] = '_';
347
348	priv->hwmon_dev =
349		devm_hwmon_device_register_with_info(dev, priv->hwmon_name,
350						     phydev,
351						     &tja11xx_hwmon_chip_info,
352						     NULL);
353
354	return PTR_ERR_OR_ZERO(priv->hwmon_dev);
355}
356
357static struct phy_driver tja11xx_driver[] = {
358	{
359		PHY_ID_MATCH_MODEL(PHY_ID_TJA1100),
360		.name		= "NXP TJA1100",
361		.features       = PHY_BASIC_T1_FEATURES,
362		.probe		= tja11xx_probe,
363		.soft_reset	= tja11xx_soft_reset,
364		.config_init	= tja11xx_config_init,
365		.read_status	= tja11xx_read_status,
366		.suspend	= genphy_suspend,
367		.resume		= genphy_resume,
368		.set_loopback   = genphy_loopback,
369		/* Statistics */
370		.get_sset_count = tja11xx_get_sset_count,
371		.get_strings	= tja11xx_get_strings,
372		.get_stats	= tja11xx_get_stats,
373	}, {
374		PHY_ID_MATCH_MODEL(PHY_ID_TJA1101),
375		.name		= "NXP TJA1101",
376		.features       = PHY_BASIC_T1_FEATURES,
377		.probe		= tja11xx_probe,
378		.soft_reset	= tja11xx_soft_reset,
379		.config_init	= tja11xx_config_init,
380		.read_status	= tja11xx_read_status,
381		.suspend	= genphy_suspend,
382		.resume		= genphy_resume,
383		.set_loopback   = genphy_loopback,
384		/* Statistics */
385		.get_sset_count = tja11xx_get_sset_count,
386		.get_strings	= tja11xx_get_strings,
387		.get_stats	= tja11xx_get_stats,
388	}
389};
390
391module_phy_driver(tja11xx_driver);
392
393static struct mdio_device_id __maybe_unused tja11xx_tbl[] = {
394	{ PHY_ID_MATCH_MODEL(PHY_ID_TJA1100) },
395	{ PHY_ID_MATCH_MODEL(PHY_ID_TJA1101) },
396	{ }
397};
398
399MODULE_DEVICE_TABLE(mdio, tja11xx_tbl);
400
401MODULE_AUTHOR("Marek Vasut <marex@denx.de>");
402MODULE_DESCRIPTION("NXP TJA11xx BoardR-Reach PHY driver");
403MODULE_LICENSE("GPL");