* [PATCH V3] net: phy: tja11xx: Add TJA11xx PHY driver
@ 2018-12-21 23:35 Marek Vasut
2018-12-22 17:39 ` Heiner Kallweit
2018-12-22 20:51 ` Heiner Kallweit
0 siblings, 2 replies; 20+ messages in thread
From: Marek Vasut @ 2018-12-21 23:35 UTC (permalink / raw)
To: netdev; +Cc: Marek Vasut, Andrew Lunn, Florian Fainelli, Heiner Kallweit
Add driver for the NXP TJA1100 and TJA1101 PHYs. These PHYs are special
BroadRReach 100BaseT1 PHYs used in automotive.
Signed-off-by: Marek Vasut <marex@denx.de>
Cc: Andrew Lunn <andrew@lunn.ch>
Cc: Florian Fainelli <f.fainelli@gmail.com>
Cc: Heiner Kallweit <hkallweit1@gmail.com>
---
V2: - Use phy_modify(), phy_{set,clear}_bits()
- Drop enable argument of tja11xx_enable_link_control()
- Use PHY_BASIC_T1_FEATURES and dont modify supported/advertised
features in config_init callback
- Use genphy_soft_reset() instead of opencoding the reset sequence.
- Drop the aneg parts, since the PHY datasheet claims it does not
support aneg
V3: - Replace clr with mask
- Add hwmon support
- Check commstat in tja11xx_read_status() only if link is up
- Use PHY_ID_MATCH_MODEL()
---
drivers/net/phy/Kconfig | 6 +
drivers/net/phy/Makefile | 1 +
drivers/net/phy/nxp-tja11xx.c | 424 ++++++++++++++++++++++++++++++++++
3 files changed, 431 insertions(+)
create mode 100644 drivers/net/phy/nxp-tja11xx.c
diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig
index 3d187cd50eb0..88b462ef1274 100644
--- a/drivers/net/phy/Kconfig
+++ b/drivers/net/phy/Kconfig
@@ -389,6 +389,12 @@ config NATIONAL_PHY
---help---
Currently supports the DP83865 PHY.
+config NXP_TJA11XX_PHY
+ tristate "NXP TJA11xx PHYs support"
+ depends on HWMON
+ ---help---
+ Currently supports the NXP TJA1100 and TJA1101 PHY.
+
config QSEMI_PHY
tristate "Quality Semiconductor PHYs"
---help---
diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile
index 5805c0b7d60e..023e5db8c7cc 100644
--- a/drivers/net/phy/Makefile
+++ b/drivers/net/phy/Makefile
@@ -76,6 +76,7 @@ obj-$(CONFIG_MICROCHIP_PHY) += microchip.o
obj-$(CONFIG_MICROCHIP_T1_PHY) += microchip_t1.o
obj-$(CONFIG_MICROSEMI_PHY) += mscc.o
obj-$(CONFIG_NATIONAL_PHY) += national.o
+obj-$(CONFIG_NXP_TJA11XX_PHY) += nxp-tja11xx.o
obj-$(CONFIG_QSEMI_PHY) += qsemi.o
obj-$(CONFIG_REALTEK_PHY) += realtek.o
obj-$(CONFIG_RENESAS_PHY) += uPD60620.o
diff --git a/drivers/net/phy/nxp-tja11xx.c b/drivers/net/phy/nxp-tja11xx.c
new file mode 100644
index 000000000000..3b8d0917e2b0
--- /dev/null
+++ b/drivers/net/phy/nxp-tja11xx.c
@@ -0,0 +1,424 @@
+// SPDX-License-Identifier: GPL-2.0
+/* NXP TJA1100 BroadRReach PHY driver
+ *
+ * Copyright (C) 2018 Marek Vasut <marex@denx.de>
+ */
+#include <linux/delay.h>
+#include <linux/ethtool.h>
+#include <linux/kernel.h>
+#include <linux/mii.h>
+#include <linux/module.h>
+#include <linux/phy.h>
+#include <linux/hwmon.h>
+
+#define PHY_ID_MASK 0xfffffff0
+#define PHY_ID_TJA1100 0x0180dc40
+#define PHY_ID_TJA1101 0x0180dd00
+
+#define MII_ECTRL 17
+#define MII_ECTRL_LINK_CONTROL BIT(15)
+#define MII_ECTRL_POWER_MODE_MASK GENMASK(14, 11)
+#define MII_ECTRL_POWER_MODE_NO_CHANGE (0x0 << 11)
+#define MII_ECTRL_POWER_MODE_NORMAL (0x3 << 11)
+#define MII_ECTRL_POWER_MODE_STANDBY (0xc << 11)
+#define MII_ECTRL_CONFIG_EN BIT(2)
+#define MII_ECTRL_WAKE_REQUEST BIT(0)
+
+#define MII_CFG1 18
+#define MII_CFG1_AUTO_OP BIT(14)
+#define MII_CFG1_SLEEP_CONFIRM BIT(6)
+#define MII_CFG1_LED_MODE_MASK GENMASK(5, 4)
+#define MII_CFG1_LED_MODE_LINKUP 0
+#define MII_CFG1_LED_ENABLE BIT(3)
+
+#define MII_CFG2 19
+#define MII_CFG2_SLEEP_REQUEST_TO GENMASK(1, 0)
+#define MII_CFG2_SLEEP_REQUEST_TO_16MS 0x3
+
+#define MII_INTSRC 21
+#define MII_INTSRC_TEMP_ERR BIT(1)
+#define MII_INTSRC_UV_ERR BIT(3)
+
+#define MII_COMMSTAT 23
+#define MII_COMMSTAT_LINK_UP BIT(15)
+
+#define MII_GENSTAT 24
+#define MII_GENSTAT_PLL_LOCKED BIT(14)
+
+#define MII_COMMCFG 27
+#define MII_COMMCFG_AUTO_OP BIT(15)
+
+struct tja11xx_priv {
+ char *hwmon_name;
+ struct device *hwmon_dev;
+};
+
+struct tja11xx_phy_stats {
+ const char *string;
+ u8 reg;
+ u8 off;
+ u16 mask;
+};
+
+static struct tja11xx_phy_stats tja11xx_hw_stats[] = {
+ { "phy_symbol_error_count", 20, 0, 0xffff },
+ { "phy_polarity_detect", 25, 6, BIT(6) },
+ { "phy_open_detect", 25, 7, BIT(7) },
+ { "phy_short_detect", 25, 8, BIT(8) },
+ { "phy_rem_rcvr_count", 26, 0, 0xff },
+ { "phy_loc_rcvr_count", 26, 8, 0xff },
+};
+
+static int tja11xx_check(struct phy_device *phydev, u8 reg, u16 mask, u16 set)
+{
+ int i, ret;
+
+ for (i = 0; i < 200; i++) {
+ ret = phy_read(phydev, reg);
+ if (ret < 0)
+ return ret;
+
+ if ((ret & mask) == set)
+ return 0;
+
+ usleep_range(100, 150);
+ }
+
+ return -ETIMEDOUT;
+}
+
+static int phy_modify_check(struct phy_device *phydev, u8 reg,
+ u16 mask, u16 set)
+{
+ int ret;
+
+ ret = phy_modify(phydev, reg, mask, set);
+ if (ret)
+ return ret;
+
+ return tja11xx_check(phydev, reg, mask, set);
+}
+
+static int tja11xx_enable_reg_write(struct phy_device *phydev)
+{
+ return phy_set_bits(phydev, MII_ECTRL, MII_ECTRL_CONFIG_EN);
+}
+
+static int tja11xx_enable_link_control(struct phy_device *phydev)
+{
+ return phy_set_bits(phydev, MII_ECTRL, MII_ECTRL_LINK_CONTROL);
+}
+
+static int tja11xx_wakeup(struct phy_device *phydev)
+{
+ int ret;
+
+ ret = phy_read(phydev, MII_ECTRL);
+ if (ret < 0)
+ return ret;
+
+ switch (ret & MII_ECTRL_POWER_MODE_MASK) {
+ case MII_ECTRL_POWER_MODE_NO_CHANGE:
+ break;
+ case MII_ECTRL_POWER_MODE_NORMAL:
+ ret = phy_set_bits(phydev, MII_ECTRL, MII_ECTRL_WAKE_REQUEST);
+ if (ret)
+ return ret;
+
+ ret = phy_clear_bits(phydev, MII_ECTRL, MII_ECTRL_WAKE_REQUEST);
+ if (ret)
+ return ret;
+ break;
+ case MII_ECTRL_POWER_MODE_STANDBY:
+ ret = phy_modify_check(phydev, MII_ECTRL,
+ MII_ECTRL_POWER_MODE_MASK,
+ MII_ECTRL_POWER_MODE_STANDBY);
+ if (ret)
+ return ret;
+
+ ret = phy_modify(phydev, MII_ECTRL, MII_ECTRL_POWER_MODE_MASK,
+ MII_ECTRL_POWER_MODE_NORMAL);
+ if (ret)
+ return ret;
+
+ ret = phy_modify_check(phydev, MII_GENSTAT,
+ MII_GENSTAT_PLL_LOCKED,
+ MII_GENSTAT_PLL_LOCKED);
+ if (ret)
+ return ret;
+
+ return tja11xx_enable_link_control(phydev);
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+static int tja11xx_soft_reset(struct phy_device *phydev)
+{
+ int ret;
+
+ ret = tja11xx_enable_reg_write(phydev);
+ if (ret)
+ return ret;
+
+ return genphy_soft_reset(phydev);
+}
+
+static int tja11xx_config_init(struct phy_device *phydev)
+{
+ int ret;
+
+ ret = tja11xx_enable_reg_write(phydev);
+ if (ret)
+ return ret;
+
+ phydev->irq = PHY_POLL;
+ phydev->autoneg = AUTONEG_DISABLE;
+ phydev->speed = SPEED_100;
+ phydev->duplex = DUPLEX_FULL;
+ phydev->pause = 0;
+ phydev->asym_pause = 0;
+
+ switch (phydev->phy_id & PHY_ID_MASK) {
+ case PHY_ID_TJA1100:
+ ret = phy_modify(phydev, MII_CFG1,
+ MII_CFG1_AUTO_OP | MII_CFG1_LED_MODE_MASK |
+ MII_CFG1_LED_ENABLE,
+ MII_CFG1_AUTO_OP | MII_CFG1_LED_MODE_LINKUP |
+ MII_CFG1_LED_ENABLE);
+ if (ret)
+ return ret;
+ break;
+ case PHY_ID_TJA1101:
+ ret = phy_set_bits(phydev, MII_COMMCFG, MII_COMMCFG_AUTO_OP);
+ if (ret)
+ return ret;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ ret = phy_clear_bits(phydev, MII_CFG1, MII_CFG1_SLEEP_CONFIRM);
+ if (ret)
+ return ret;
+
+ ret = phy_modify(phydev, MII_CFG2, MII_CFG2_SLEEP_REQUEST_TO,
+ MII_CFG2_SLEEP_REQUEST_TO_16MS);
+ if (ret)
+ return ret;
+
+ ret = tja11xx_wakeup(phydev);
+ if (ret < 0)
+ return ret;
+
+ /* ACK interrupts by reading the status register */
+ ret = phy_read(phydev, MII_INTSRC);
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
+
+static int tja11xx_read_status(struct phy_device *phydev)
+{
+ int ret;
+
+ ret = genphy_update_link(phydev);
+ if (ret)
+ return ret;
+
+ if (phydev->link) {
+ ret = phy_read(phydev, MII_COMMSTAT);
+ if (ret < 0)
+ return ret;
+
+ if (!(ret & MII_COMMSTAT_LINK_UP))
+ phydev->link = 0;
+ }
+
+ return 0;
+}
+
+static int tja11xx_get_sset_count(struct phy_device *phydev)
+{
+ return ARRAY_SIZE(tja11xx_hw_stats);
+}
+
+static void tja11xx_get_strings(struct phy_device *phydev, u8 *data)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(tja11xx_hw_stats); i++) {
+ strncpy(data + i * ETH_GSTRING_LEN,
+ tja11xx_hw_stats[i].string, ETH_GSTRING_LEN);
+ }
+}
+
+static void tja11xx_get_stats(struct phy_device *phydev,
+ struct ethtool_stats *stats, u64 *data)
+{
+ int i, ret;
+
+ for (i = 0; i < ARRAY_SIZE(tja11xx_hw_stats); i++) {
+ ret = phy_read(phydev, tja11xx_hw_stats[i].reg);
+ if (ret < 0) {
+ data[i] = U64_MAX;
+ } else {
+ data[i] = ret & tja11xx_hw_stats[i].mask;
+ data[i] >>= tja11xx_hw_stats[i].off;
+ }
+ }
+}
+
+static int tja11xx_hwmon_read(struct device *dev,
+ enum hwmon_sensor_types type,
+ u32 attr, int channel, long *value)
+{
+ struct phy_device *phydev = dev_get_drvdata(dev);
+ int ret;
+
+ switch (attr) {
+ case hwmon_in_lcrit_alarm:
+ ret = phy_read(phydev, MII_INTSRC);
+ if (ret < 0)
+ return ret;
+
+ *value = !!(ret & MII_INTSRC_TEMP_ERR);
+ return 0;
+ case hwmon_temp_crit_alarm:
+ ret = phy_read(phydev, MII_INTSRC);
+ if (ret < 0)
+ return ret;
+
+ *value = !!(ret & MII_INTSRC_TEMP_ERR);
+ return 0;
+ default:
+ return -EOPNOTSUPP;
+ }
+}
+
+static umode_t tja11xx_hwmon_is_visible(const void *data,
+ enum hwmon_sensor_types type,
+ u32 attr, int channel)
+{
+ if (type == hwmon_in && attr == hwmon_in_lcrit_alarm)
+ return 0444;
+
+ if (type == hwmon_temp && attr == hwmon_temp_crit_alarm)
+ return 0444;
+
+ return 0;
+}
+
+static u32 tja11xx_hwmon_in_config[] = {
+ HWMON_I_LCRIT_ALARM,
+ 0
+};
+
+static const struct hwmon_channel_info tja11xx_hwmon_in = {
+ .type = hwmon_in,
+ .config = tja11xx_hwmon_in_config,
+};
+
+static u32 tja11xx_hwmon_temp_config[] = {
+ HWMON_T_CRIT_ALARM,
+ 0
+};
+
+static const struct hwmon_channel_info tja11xx_hwmon_temp = {
+ .type = hwmon_temp,
+ .config = tja11xx_hwmon_temp_config,
+};
+
+static const struct hwmon_channel_info *tja11xx_hwmon_info[] = {
+ &tja11xx_hwmon_in,
+ &tja11xx_hwmon_temp,
+ NULL
+};
+
+static const struct hwmon_ops tja11xx_hwmon_hwmon_ops = {
+ .is_visible = tja11xx_hwmon_is_visible,
+ .read = tja11xx_hwmon_read,
+};
+
+static const struct hwmon_chip_info tja11xx_hwmon_chip_info = {
+ .ops = &tja11xx_hwmon_hwmon_ops,
+ .info = tja11xx_hwmon_info,
+};
+
+static int tja11xx_probe(struct phy_device *phydev)
+{
+ struct device *dev = &phydev->mdio.dev;
+ struct tja11xx_priv *priv;
+ int i;
+
+ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ priv->hwmon_name = devm_kstrdup(dev, dev_name(dev), GFP_KERNEL);
+ if (!priv->hwmon_name)
+ return -ENODEV;
+
+ for (i = 0; priv->hwmon_name[i]; i++)
+ if (hwmon_is_bad_char(priv->hwmon_name[i]))
+ priv->hwmon_name[i] = '_';
+
+ priv->hwmon_dev =
+ devm_hwmon_device_register_with_info(dev, priv->hwmon_name,
+ phydev,
+ &tja11xx_hwmon_chip_info,
+ NULL);
+
+ return PTR_ERR_OR_ZERO(priv->hwmon_dev);
+}
+
+static struct phy_driver tja11xx_driver[] = {
+ {
+ PHY_ID_MATCH_MODEL(PHY_ID_TJA1100),
+ .name = "NXP TJA1100",
+ .features = PHY_BASIC_T1_FEATURES,
+ .probe = tja11xx_probe,
+ .soft_reset = tja11xx_soft_reset,
+ .config_init = tja11xx_config_init,
+ .read_status = tja11xx_read_status,
+ .suspend = genphy_suspend,
+ .resume = genphy_resume,
+ .set_loopback = genphy_loopback,
+ /* Statistics */
+ .get_sset_count = tja11xx_get_sset_count,
+ .get_strings = tja11xx_get_strings,
+ .get_stats = tja11xx_get_stats,
+ }, {
+ PHY_ID_MATCH_MODEL(PHY_ID_TJA1101),
+ .name = "NXP TJA1101",
+ .features = PHY_BASIC_T1_FEATURES,
+ .probe = tja11xx_probe,
+ .soft_reset = tja11xx_soft_reset,
+ .config_init = tja11xx_config_init,
+ .read_status = tja11xx_read_status,
+ .suspend = genphy_suspend,
+ .resume = genphy_resume,
+ .set_loopback = genphy_loopback,
+ /* Statistics */
+ .get_sset_count = tja11xx_get_sset_count,
+ .get_strings = tja11xx_get_strings,
+ .get_stats = tja11xx_get_stats,
+ }
+};
+
+module_phy_driver(tja11xx_driver);
+
+static struct mdio_device_id __maybe_unused tja11xx_tbl[] = {
+ { PHY_ID_MATCH_MODEL(PHY_ID_TJA1100) },
+ { PHY_ID_MATCH_MODEL(PHY_ID_TJA1101) },
+ { }
+};
+
+MODULE_DEVICE_TABLE(mdio, tja11xx_tbl);
+
+MODULE_AUTHOR("Marek Vasut <marex@denx.de>");
+MODULE_DESCRIPTION("NXP TJA11xx BoardR-Reach PHY driver");
+MODULE_LICENSE("GPL");
--
2.19.2
^ permalink raw reply related [flat|nested] 20+ messages in thread
* Re: [PATCH V3] net: phy: tja11xx: Add TJA11xx PHY driver
2018-12-21 23:35 [PATCH V3] net: phy: tja11xx: Add TJA11xx PHY driver Marek Vasut
@ 2018-12-22 17:39 ` Heiner Kallweit
2018-12-23 9:16 ` Marek Vasut
2018-12-22 20:51 ` Heiner Kallweit
1 sibling, 1 reply; 20+ messages in thread
From: Heiner Kallweit @ 2018-12-22 17:39 UTC (permalink / raw)
To: Marek Vasut, netdev; +Cc: Andrew Lunn, Florian Fainelli
On 22.12.2018 00:35, Marek Vasut wrote:
> Add driver for the NXP TJA1100 and TJA1101 PHYs. These PHYs are special
> BroadRReach 100BaseT1 PHYs used in automotive.
>
> Signed-off-by: Marek Vasut <marex@denx.de>
> Cc: Andrew Lunn <andrew@lunn.ch>
> Cc: Florian Fainelli <f.fainelli@gmail.com>
> Cc: Heiner Kallweit <hkallweit1@gmail.com>
> ---
> V2: - Use phy_modify(), phy_{set,clear}_bits()
> - Drop enable argument of tja11xx_enable_link_control()
> - Use PHY_BASIC_T1_FEATURES and dont modify supported/advertised
> features in config_init callback
> - Use genphy_soft_reset() instead of opencoding the reset sequence.
> - Drop the aneg parts, since the PHY datasheet claims it does not
> support aneg
> V3: - Replace clr with mask
> - Add hwmon support
> - Check commstat in tja11xx_read_status() only if link is up
> - Use PHY_ID_MATCH_MODEL()
> ---
> drivers/net/phy/Kconfig | 6 +
> drivers/net/phy/Makefile | 1 +
> drivers/net/phy/nxp-tja11xx.c | 424 ++++++++++++++++++++++++++++++++++
> 3 files changed, 431 insertions(+)
> create mode 100644 drivers/net/phy/nxp-tja11xx.c
>
[...]
> +
> +struct tja11xx_phy_stats {
> + const char *string;
> + u8 reg;
> + u8 off;
> + u16 mask;
> +};
> +
As written in my other mail, you could think of using
FIELD_GET() again. Things like
... n, BIT(n),
... m, BIT(m),
are simply redundant.
> +static struct tja11xx_phy_stats tja11xx_hw_stats[] = {
> + { "phy_symbol_error_count", 20, 0, 0xffff },
> + { "phy_polarity_detect", 25, 6, BIT(6) },
> + { "phy_open_detect", 25, 7, BIT(7) },
> + { "phy_short_detect", 25, 8, BIT(8) },
> + { "phy_rem_rcvr_count", 26, 0, 0xff },
> + { "phy_loc_rcvr_count", 26, 8, 0xff },
Shouldn't mask in the last line be 0xff00 ?
In the relevant code you do: val = (reg & mask) >> off
> +static int tja11xx_probe(struct phy_device *phydev)
> +{
> + struct device *dev = &phydev->mdio.dev;
> + struct tja11xx_priv *priv;
> + int i;
> +
> + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
> + if (!priv)
> + return -ENOMEM;
> +
> + priv->hwmon_name = devm_kstrdup(dev, dev_name(dev), GFP_KERNEL);
> + if (!priv->hwmon_name)
> + return -ENODEV;
Do you really need to make a copy of the device name?
Why not simply priv->hwmon_name = dev_name(dev) ?
And if devm_kstrdup fails, then most likely you have an out-of-memory
error, so why not return -ENOMEM as usual?
> +
> + for (i = 0; priv->hwmon_name[i]; i++)
> + if (hwmon_is_bad_char(priv->hwmon_name[i]))
> + priv->hwmon_name[i] = '_';
> +
> + priv->hwmon_dev =
> + devm_hwmon_device_register_with_info(dev, priv->hwmon_name,
> + phydev,
> + &tja11xx_hwmon_chip_info,
> + NULL);
> +
Prerequisite for this call is that HWMON is configured in the kernel and
it's reachable. Something like "IS_REACHABLE(CONFIG_HWMON)" would be
needed. You can see driver rtc-ds1307 for an example.
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH V3] net: phy: tja11xx: Add TJA11xx PHY driver
2018-12-21 23:35 [PATCH V3] net: phy: tja11xx: Add TJA11xx PHY driver Marek Vasut
2018-12-22 17:39 ` Heiner Kallweit
@ 2018-12-22 20:51 ` Heiner Kallweit
2018-12-23 9:13 ` Marek Vasut
2018-12-23 10:06 ` Andrew Lunn
1 sibling, 2 replies; 20+ messages in thread
From: Heiner Kallweit @ 2018-12-22 20:51 UTC (permalink / raw)
To: Marek Vasut, netdev; +Cc: Andrew Lunn, Florian Fainelli
On 22.12.2018 00:35, Marek Vasut wrote:
> Add driver for the NXP TJA1100 and TJA1101 PHYs. These PHYs are special
> BroadRReach 100BaseT1 PHYs used in automotive.
>
> Signed-off-by: Marek Vasut <marex@denx.de>
> Cc: Andrew Lunn <andrew@lunn.ch>
> Cc: Florian Fainelli <f.fainelli@gmail.com>
> Cc: Heiner Kallweit <hkallweit1@gmail.com>
> ---
> V2: - Use phy_modify(), phy_{set,clear}_bits()
> - Drop enable argument of tja11xx_enable_link_control()
> - Use PHY_BASIC_T1_FEATURES and dont modify supported/advertised
> features in config_init callback
> - Use genphy_soft_reset() instead of opencoding the reset sequence.
> - Drop the aneg parts, since the PHY datasheet claims it does not
> support aneg
> V3: - Replace clr with mask
> - Add hwmon support
> - Check commstat in tja11xx_read_status() only if link is up
> - Use PHY_ID_MATCH_MODEL()
> ---
> drivers/net/phy/Kconfig | 6 +
> drivers/net/phy/Makefile | 1 +
> drivers/net/phy/nxp-tja11xx.c | 424 ++++++++++++++++++++++++++++++++++
> 3 files changed, 431 insertions(+)
> create mode 100644 drivers/net/phy/nxp-tja11xx.c
[...]
> +static int tja11xx_hwmon_read(struct device *dev,
> + enum hwmon_sensor_types type,
> + u32 attr, int channel, long *value)
> +{
> + struct phy_device *phydev = dev_get_drvdata(dev);
> + int ret;
> +
> + switch (attr) {
> + case hwmon_in_lcrit_alarm:
> + ret = phy_read(phydev, MII_INTSRC);
> + if (ret < 0)
> + return ret;
> +
> + *value = !!(ret & MII_INTSRC_TEMP_ERR);
> + return 0;
> + case hwmon_temp_crit_alarm:
> + ret = phy_read(phydev, MII_INTSRC);
> + if (ret < 0)
> + return ret;
> +
> + *value = !!(ret & MII_INTSRC_TEMP_ERR);
> + return 0;
> + default:
> + return -EOPNOTSUPP;
> + }
> +}
This looks like a copy & paste error, in both cases you're doing the same.
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH V3] net: phy: tja11xx: Add TJA11xx PHY driver
2018-12-22 20:51 ` Heiner Kallweit
@ 2018-12-23 9:13 ` Marek Vasut
2018-12-23 10:06 ` Andrew Lunn
1 sibling, 0 replies; 20+ messages in thread
From: Marek Vasut @ 2018-12-23 9:13 UTC (permalink / raw)
To: Heiner Kallweit, netdev; +Cc: Andrew Lunn, Florian Fainelli
On 12/22/18 9:51 PM, Heiner Kallweit wrote:
> On 22.12.2018 00:35, Marek Vasut wrote:
>> Add driver for the NXP TJA1100 and TJA1101 PHYs. These PHYs are special
>> BroadRReach 100BaseT1 PHYs used in automotive.
>>
>> Signed-off-by: Marek Vasut <marex@denx.de>
>> Cc: Andrew Lunn <andrew@lunn.ch>
>> Cc: Florian Fainelli <f.fainelli@gmail.com>
>> Cc: Heiner Kallweit <hkallweit1@gmail.com>
>> ---
>> V2: - Use phy_modify(), phy_{set,clear}_bits()
>> - Drop enable argument of tja11xx_enable_link_control()
>> - Use PHY_BASIC_T1_FEATURES and dont modify supported/advertised
>> features in config_init callback
>> - Use genphy_soft_reset() instead of opencoding the reset sequence.
>> - Drop the aneg parts, since the PHY datasheet claims it does not
>> support aneg
>> V3: - Replace clr with mask
>> - Add hwmon support
>> - Check commstat in tja11xx_read_status() only if link is up
>> - Use PHY_ID_MATCH_MODEL()
>> ---
>> drivers/net/phy/Kconfig | 6 +
>> drivers/net/phy/Makefile | 1 +
>> drivers/net/phy/nxp-tja11xx.c | 424 ++++++++++++++++++++++++++++++++++
>> 3 files changed, 431 insertions(+)
>> create mode 100644 drivers/net/phy/nxp-tja11xx.c
> [...]
>> +static int tja11xx_hwmon_read(struct device *dev,
>> + enum hwmon_sensor_types type,
>> + u32 attr, int channel, long *value)
>> +{
>> + struct phy_device *phydev = dev_get_drvdata(dev);
>> + int ret;
>> +
>> + switch (attr) {
>> + case hwmon_in_lcrit_alarm:
>> + ret = phy_read(phydev, MII_INTSRC);
>> + if (ret < 0)
>> + return ret;
>> +
>> + *value = !!(ret & MII_INTSRC_TEMP_ERR);
>> + return 0;
>> + case hwmon_temp_crit_alarm:
>> + ret = phy_read(phydev, MII_INTSRC);
>> + if (ret < 0)
>> + return ret;
>> +
>> + *value = !!(ret & MII_INTSRC_TEMP_ERR);
>> + return 0;
>> + default:
>> + return -EOPNOTSUPP;
>> + }
>> +}
> This looks like a copy & paste error, in both cases you're doing the same.
Fixed, thanks. I'll send V4 once I can actually test this stuff.
--
Best regards,
Marek Vasut
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH V3] net: phy: tja11xx: Add TJA11xx PHY driver
2018-12-22 17:39 ` Heiner Kallweit
@ 2018-12-23 9:16 ` Marek Vasut
2018-12-23 9:41 ` Heiner Kallweit
2019-01-03 2:09 ` Marek Vasut
0 siblings, 2 replies; 20+ messages in thread
From: Marek Vasut @ 2018-12-23 9:16 UTC (permalink / raw)
To: Heiner Kallweit, netdev; +Cc: Andrew Lunn, Florian Fainelli
On 12/22/18 6:39 PM, Heiner Kallweit wrote:
> On 22.12.2018 00:35, Marek Vasut wrote:
>> Add driver for the NXP TJA1100 and TJA1101 PHYs. These PHYs are special
>> BroadRReach 100BaseT1 PHYs used in automotive.
>>
>> Signed-off-by: Marek Vasut <marex@denx.de>
>> Cc: Andrew Lunn <andrew@lunn.ch>
>> Cc: Florian Fainelli <f.fainelli@gmail.com>
>> Cc: Heiner Kallweit <hkallweit1@gmail.com>
>> ---
>> V2: - Use phy_modify(), phy_{set,clear}_bits()
>> - Drop enable argument of tja11xx_enable_link_control()
>> - Use PHY_BASIC_T1_FEATURES and dont modify supported/advertised
>> features in config_init callback
>> - Use genphy_soft_reset() instead of opencoding the reset sequence.
>> - Drop the aneg parts, since the PHY datasheet claims it does not
>> support aneg
>> V3: - Replace clr with mask
>> - Add hwmon support
>> - Check commstat in tja11xx_read_status() only if link is up
>> - Use PHY_ID_MATCH_MODEL()
>> ---
>> drivers/net/phy/Kconfig | 6 +
>> drivers/net/phy/Makefile | 1 +
>> drivers/net/phy/nxp-tja11xx.c | 424 ++++++++++++++++++++++++++++++++++
>> 3 files changed, 431 insertions(+)
>> create mode 100644 drivers/net/phy/nxp-tja11xx.c
>>
> [...]
>> +
>> +struct tja11xx_phy_stats {
>> + const char *string;
>> + u8 reg;
>> + u8 off;
>> + u16 mask;
>> +};
>> +
> As written in my other mail, you could think of using
> FIELD_GET() again. Things like
> ... n, BIT(n),
> ... m, BIT(m),
> are simply redundant.
Done
>> +static struct tja11xx_phy_stats tja11xx_hw_stats[] = {
>> + { "phy_symbol_error_count", 20, 0, 0xffff },
>> + { "phy_polarity_detect", 25, 6, BIT(6) },
>> + { "phy_open_detect", 25, 7, BIT(7) },
>> + { "phy_short_detect", 25, 8, BIT(8) },
>> + { "phy_rem_rcvr_count", 26, 0, 0xff },
>> + { "phy_loc_rcvr_count", 26, 8, 0xff },
>
> Shouldn't mask in the last line be 0xff00 ?
> In the relevant code you do: val = (reg & mask) >> off
Yes, fixed, thanks
>> +static int tja11xx_probe(struct phy_device *phydev)
>> +{
>> + struct device *dev = &phydev->mdio.dev;
>> + struct tja11xx_priv *priv;
>> + int i;
>> +
>> + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
>> + if (!priv)
>> + return -ENOMEM;
>> +
>> + priv->hwmon_name = devm_kstrdup(dev, dev_name(dev), GFP_KERNEL);
>> + if (!priv->hwmon_name)
>> + return -ENODEV;
>
> Do you really need to make a copy of the device name?
> Why not simply priv->hwmon_name = dev_name(dev) ?
Fine by me, but then maybe I don't quite understand why the other
drivers duplicate the name, eg. the sfp.c one.
> And if devm_kstrdup fails, then most likely you have an out-of-memory
> error, so why not return -ENOMEM as usual?
Fixed
>> +
>> + for (i = 0; priv->hwmon_name[i]; i++)
>> + if (hwmon_is_bad_char(priv->hwmon_name[i]))
>> + priv->hwmon_name[i] = '_';
>> +
>> + priv->hwmon_dev =
>> + devm_hwmon_device_register_with_info(dev, priv->hwmon_name,
>> + phydev,
>> + &tja11xx_hwmon_chip_info,
>> + NULL);
>> +
> Prerequisite for this call is that HWMON is configured in the kernel and
> it's reachable. Something like "IS_REACHABLE(CONFIG_HWMON)" would be
> needed. You can see driver rtc-ds1307 for an example.
The driver depends on HWMON, so that should be sufficient ?
--
Best regards,
Marek Vasut
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH V3] net: phy: tja11xx: Add TJA11xx PHY driver
2018-12-23 9:16 ` Marek Vasut
@ 2018-12-23 9:41 ` Heiner Kallweit
2018-12-23 9:59 ` Andrew Lunn
2018-12-23 10:21 ` Marek Vasut
2019-01-03 2:09 ` Marek Vasut
1 sibling, 2 replies; 20+ messages in thread
From: Heiner Kallweit @ 2018-12-23 9:41 UTC (permalink / raw)
To: Marek Vasut, netdev; +Cc: Andrew Lunn, Florian Fainelli
On 23.12.2018 10:16, Marek Vasut wrote:
> On 12/22/18 6:39 PM, Heiner Kallweit wrote:
>> On 22.12.2018 00:35, Marek Vasut wrote:
>>> Add driver for the NXP TJA1100 and TJA1101 PHYs. These PHYs are special
>>> BroadRReach 100BaseT1 PHYs used in automotive.
>>>
>>> Signed-off-by: Marek Vasut <marex@denx.de>
>>> Cc: Andrew Lunn <andrew@lunn.ch>
>>> Cc: Florian Fainelli <f.fainelli@gmail.com>
>>> Cc: Heiner Kallweit <hkallweit1@gmail.com>
>>> ---
>>> V2: - Use phy_modify(), phy_{set,clear}_bits()
>>> - Drop enable argument of tja11xx_enable_link_control()
>>> - Use PHY_BASIC_T1_FEATURES and dont modify supported/advertised
>>> features in config_init callback
>>> - Use genphy_soft_reset() instead of opencoding the reset sequence.
>>> - Drop the aneg parts, since the PHY datasheet claims it does not
>>> support aneg
>>> V3: - Replace clr with mask
>>> - Add hwmon support
>>> - Check commstat in tja11xx_read_status() only if link is up
>>> - Use PHY_ID_MATCH_MODEL()
>>> ---
>>> drivers/net/phy/Kconfig | 6 +
>>> drivers/net/phy/Makefile | 1 +
>>> drivers/net/phy/nxp-tja11xx.c | 424 ++++++++++++++++++++++++++++++++++
>>> 3 files changed, 431 insertions(+)
>>> create mode 100644 drivers/net/phy/nxp-tja11xx.c
>>>
>> [...]
>>> +
>>> +struct tja11xx_phy_stats {
>>> + const char *string;
>>> + u8 reg;
>>> + u8 off;
>>> + u16 mask;
>>> +};
>>> +
>> As written in my other mail, you could think of using
>> FIELD_GET() again. Things like
>> ... n, BIT(n),
>> ... m, BIT(m),
>> are simply redundant.
>
> Done
>
>>> +static struct tja11xx_phy_stats tja11xx_hw_stats[] = {
>>> + { "phy_symbol_error_count", 20, 0, 0xffff },
>>> + { "phy_polarity_detect", 25, 6, BIT(6) },
>>> + { "phy_open_detect", 25, 7, BIT(7) },
>>> + { "phy_short_detect", 25, 8, BIT(8) },
>>> + { "phy_rem_rcvr_count", 26, 0, 0xff },
>>> + { "phy_loc_rcvr_count", 26, 8, 0xff },
>>
>> Shouldn't mask in the last line be 0xff00 ?
>> In the relevant code you do: val = (reg & mask) >> off
>
> Yes, fixed, thanks
>
>>> +static int tja11xx_probe(struct phy_device *phydev)
>>> +{
>>> + struct device *dev = &phydev->mdio.dev;
>>> + struct tja11xx_priv *priv;
>>> + int i;
>>> +
>>> + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
>>> + if (!priv)
>>> + return -ENOMEM;
>>> +
>>> + priv->hwmon_name = devm_kstrdup(dev, dev_name(dev), GFP_KERNEL);
>>> + if (!priv->hwmon_name)
>>> + return -ENODEV;
>>
>> Do you really need to make a copy of the device name?
>> Why not simply priv->hwmon_name = dev_name(dev) ?
>
> Fine by me, but then maybe I don't quite understand why the other
> drivers duplicate the name, eg. the sfp.c one.
>
It's a question of object lifetime. If the original object can go away
before your object, then you need to make a copy of the name.
However in our case I don't think priv can live longer than dev.
>> And if devm_kstrdup fails, then most likely you have an out-of-memory
>> error, so why not return -ENOMEM as usual?
>
> Fixed
>
>>> +
>>> + for (i = 0; priv->hwmon_name[i]; i++)
>>> + if (hwmon_is_bad_char(priv->hwmon_name[i]))
>>> + priv->hwmon_name[i] = '_';
>>> +
>>> + priv->hwmon_dev =
>>> + devm_hwmon_device_register_with_info(dev, priv->hwmon_name,
>>> + phydev,
>>> + &tja11xx_hwmon_chip_info,
>>> + NULL);
>>> +
>> Prerequisite for this call is that HWMON is configured in the kernel and
>> it's reachable. Something like "IS_REACHABLE(CONFIG_HWMON)" would be
>> needed. You can see driver rtc-ds1307 for an example.
>
> The driver depends on HWMON, so that should be sufficient ?
>
Missed that, that's sufficient. Just something to think about:
Often HWMON is seen as an optional add-on feature. The driver itself would
work perfectly fine also w/o HWMON. In this case you don't want the hard
dependency. So it's up to you whether you want to allow that the driver is
used on systems w/o HWMON support.
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH V3] net: phy: tja11xx: Add TJA11xx PHY driver
2018-12-23 9:41 ` Heiner Kallweit
@ 2018-12-23 9:59 ` Andrew Lunn
2018-12-23 10:21 ` Marek Vasut
1 sibling, 0 replies; 20+ messages in thread
From: Andrew Lunn @ 2018-12-23 9:59 UTC (permalink / raw)
To: Heiner Kallweit; +Cc: Marek Vasut, netdev, Florian Fainelli
> >>> + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
> >>> + if (!priv)
> >>> + return -ENOMEM;
> >>> +
> >>> + priv->hwmon_name = devm_kstrdup(dev, dev_name(dev), GFP_KERNEL);
> >>> + if (!priv->hwmon_name)
> >>> + return -ENODEV;
> >>
> >> Do you really need to make a copy of the device name?
> >> Why not simply priv->hwmon_name = dev_name(dev) ?
> >
> > Fine by me, but then maybe I don't quite understand why the other
> > drivers duplicate the name, eg. the sfp.c one.
> >
> It's a question of object lifetime. If the original object can go away
> before your object, then you need to make a copy of the name.
> However in our case I don't think priv can live longer than dev.
>
> >> And if devm_kstrdup fails, then most likely you have an out-of-memory
> >> error, so why not return -ENOMEM as usual?
> >
> > Fixed
> >
> >>> +
> >>> + for (i = 0; priv->hwmon_name[i]; i++)
> >>> + if (hwmon_is_bad_char(priv->hwmon_name[i]))
> >>> + priv->hwmon_name[i] = '_';
This is one reason to make a copy. You don't want to apply that to
main name of the device.
> >>> +
> >>> + priv->hwmon_dev =
> >>> + devm_hwmon_device_register_with_info(dev, priv->hwmon_name,
> >>> + phydev,
> >>> + &tja11xx_hwmon_chip_info,
> >>> + NULL);
> >>> +
The second reason is priv is released before dev, but what about
hwmon, especially if somebody has one of the files open? Is the
unregister synchronous?
Andrew
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH V3] net: phy: tja11xx: Add TJA11xx PHY driver
2018-12-22 20:51 ` Heiner Kallweit
2018-12-23 9:13 ` Marek Vasut
@ 2018-12-23 10:06 ` Andrew Lunn
2018-12-23 10:49 ` Marek Vasut
1 sibling, 1 reply; 20+ messages in thread
From: Andrew Lunn @ 2018-12-23 10:06 UTC (permalink / raw)
To: Heiner Kallweit; +Cc: Marek Vasut, netdev, Florian Fainelli
> > + switch (attr) {
> > + case hwmon_in_lcrit_alarm:
> > + ret = phy_read(phydev, MII_INTSRC);
> > + if (ret < 0)
> > + return ret;
> > +
> > + *value = !!(ret & MII_INTSRC_TEMP_ERR);
> > + return 0;
> > + case hwmon_temp_crit_alarm:
> > + ret = phy_read(phydev, MII_INTSRC);
> > + if (ret < 0)
> > + return ret;
> > +
> > + *value = !!(ret & MII_INTSRC_TEMP_ERR);
> > + return 0;
> > + default:
> > + return -EOPNOTSUPP;
> > + }
> > +}
> This looks like a copy & paste error, in both cases you're doing the same.
You also should not do it like this. hwmon_temp_crit_alarm is in a
different set of enum's as hwmon_in_lcrit_alarm. hwmon_in_lcrit_alarm
= 14. hwmon_temp_max_alarm also is 14. You should have two different
switch statements to take account of this.
Andrew
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH V3] net: phy: tja11xx: Add TJA11xx PHY driver
2018-12-23 9:41 ` Heiner Kallweit
2018-12-23 9:59 ` Andrew Lunn
@ 2018-12-23 10:21 ` Marek Vasut
2018-12-23 10:35 ` Andrew Lunn
1 sibling, 1 reply; 20+ messages in thread
From: Marek Vasut @ 2018-12-23 10:21 UTC (permalink / raw)
To: Heiner Kallweit, netdev; +Cc: Andrew Lunn, Florian Fainelli
On 12/23/18 10:41 AM, Heiner Kallweit wrote:
> On 23.12.2018 10:16, Marek Vasut wrote:
>> On 12/22/18 6:39 PM, Heiner Kallweit wrote:
>>> On 22.12.2018 00:35, Marek Vasut wrote:
>>>> Add driver for the NXP TJA1100 and TJA1101 PHYs. These PHYs are special
>>>> BroadRReach 100BaseT1 PHYs used in automotive.
>>>>
>>>> Signed-off-by: Marek Vasut <marex@denx.de>
>>>> Cc: Andrew Lunn <andrew@lunn.ch>
>>>> Cc: Florian Fainelli <f.fainelli@gmail.com>
>>>> Cc: Heiner Kallweit <hkallweit1@gmail.com>
>>>> ---
>>>> V2: - Use phy_modify(), phy_{set,clear}_bits()
>>>> - Drop enable argument of tja11xx_enable_link_control()
>>>> - Use PHY_BASIC_T1_FEATURES and dont modify supported/advertised
>>>> features in config_init callback
>>>> - Use genphy_soft_reset() instead of opencoding the reset sequence.
>>>> - Drop the aneg parts, since the PHY datasheet claims it does not
>>>> support aneg
>>>> V3: - Replace clr with mask
>>>> - Add hwmon support
>>>> - Check commstat in tja11xx_read_status() only if link is up
>>>> - Use PHY_ID_MATCH_MODEL()
>>>> ---
>>>> drivers/net/phy/Kconfig | 6 +
>>>> drivers/net/phy/Makefile | 1 +
>>>> drivers/net/phy/nxp-tja11xx.c | 424 ++++++++++++++++++++++++++++++++++
>>>> 3 files changed, 431 insertions(+)
>>>> create mode 100644 drivers/net/phy/nxp-tja11xx.c
>>>>
>>> [...]
>>>> +
>>>> +struct tja11xx_phy_stats {
>>>> + const char *string;
>>>> + u8 reg;
>>>> + u8 off;
>>>> + u16 mask;
>>>> +};
>>>> +
>>> As written in my other mail, you could think of using
>>> FIELD_GET() again. Things like
>>> ... n, BIT(n),
>>> ... m, BIT(m),
>>> are simply redundant.
>>
>> Done
>>
>>>> +static struct tja11xx_phy_stats tja11xx_hw_stats[] = {
>>>> + { "phy_symbol_error_count", 20, 0, 0xffff },
>>>> + { "phy_polarity_detect", 25, 6, BIT(6) },
>>>> + { "phy_open_detect", 25, 7, BIT(7) },
>>>> + { "phy_short_detect", 25, 8, BIT(8) },
>>>> + { "phy_rem_rcvr_count", 26, 0, 0xff },
>>>> + { "phy_loc_rcvr_count", 26, 8, 0xff },
>>>
>>> Shouldn't mask in the last line be 0xff00 ?
>>> In the relevant code you do: val = (reg & mask) >> off
>>
>> Yes, fixed, thanks
>>
>>>> +static int tja11xx_probe(struct phy_device *phydev)
>>>> +{
>>>> + struct device *dev = &phydev->mdio.dev;
>>>> + struct tja11xx_priv *priv;
>>>> + int i;
>>>> +
>>>> + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
>>>> + if (!priv)
>>>> + return -ENOMEM;
>>>> +
>>>> + priv->hwmon_name = devm_kstrdup(dev, dev_name(dev), GFP_KERNEL);
>>>> + if (!priv->hwmon_name)
>>>> + return -ENODEV;
>>>
>>> Do you really need to make a copy of the device name?
>>> Why not simply priv->hwmon_name = dev_name(dev) ?
>>
>> Fine by me, but then maybe I don't quite understand why the other
>> drivers duplicate the name, eg. the sfp.c one.
>>
> It's a question of object lifetime. If the original object can go away
> before your object, then you need to make a copy of the name.
> However in our case I don't think priv can live longer than dev.
>
>>> And if devm_kstrdup fails, then most likely you have an out-of-memory
>>> error, so why not return -ENOMEM as usual?
>>
>> Fixed
>>
>>>> +
>>>> + for (i = 0; priv->hwmon_name[i]; i++)
>>>> + if (hwmon_is_bad_char(priv->hwmon_name[i]))
>>>> + priv->hwmon_name[i] = '_';
>>>> +
>>>> + priv->hwmon_dev =
>>>> + devm_hwmon_device_register_with_info(dev, priv->hwmon_name,
>>>> + phydev,
>>>> + &tja11xx_hwmon_chip_info,
>>>> + NULL);
>>>> +
>>> Prerequisite for this call is that HWMON is configured in the kernel and
>>> it's reachable. Something like "IS_REACHABLE(CONFIG_HWMON)" would be
>>> needed. You can see driver rtc-ds1307 for an example.
>>
>> The driver depends on HWMON, so that should be sufficient ?
>>
> Missed that, that's sufficient. Just something to think about:
> Often HWMON is seen as an optional add-on feature. The driver itself would
> work perfectly fine also w/o HWMON. In this case you don't want the hard
> dependency. So it's up to you whether you want to allow that the driver is
> used on systems w/o HWMON support.
Given that the HWMON indicates that the automotive device either
overheated or suffered undervolt, I presume it'd be safer not to make it
optional ?
--
Best regards,
Marek Vasut
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH V3] net: phy: tja11xx: Add TJA11xx PHY driver
2018-12-23 10:21 ` Marek Vasut
@ 2018-12-23 10:35 ` Andrew Lunn
2018-12-23 10:48 ` Marek Vasut
0 siblings, 1 reply; 20+ messages in thread
From: Andrew Lunn @ 2018-12-23 10:35 UTC (permalink / raw)
To: Marek Vasut; +Cc: Heiner Kallweit, netdev, Florian Fainelli
> Given that the HWMON indicates that the automotive device either
> overheated or suffered undervolt, I presume it'd be safer not to make it
> optional ?
Hi Marek
It is a niche device, where i expect a custom kernel configuration. Do
any of these devices exist on standard PCIe cards? Maybe a test PC
using a standard Linux Distribution? But then again, such
distributions turn on HWMON anyway.
Andrew
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH V3] net: phy: tja11xx: Add TJA11xx PHY driver
2018-12-23 10:35 ` Andrew Lunn
@ 2018-12-23 10:48 ` Marek Vasut
0 siblings, 0 replies; 20+ messages in thread
From: Marek Vasut @ 2018-12-23 10:48 UTC (permalink / raw)
To: Andrew Lunn; +Cc: Heiner Kallweit, netdev, Florian Fainelli
On 12/23/18 11:35 AM, Andrew Lunn wrote:
>> Given that the HWMON indicates that the automotive device either
>> overheated or suffered undervolt, I presume it'd be safer not to make it
>> optional ?
>
> Hi Marek
>
> It is a niche device, where i expect a custom kernel configuration. Do
> any of these devices exist on standard PCIe cards? Maybe a test PC
> using a standard Linux Distribution? But then again, such
> distributions turn on HWMON anyway.
Not to my knowledge. I have two on various embedded systems and one on
SMSC95xx USB-ethernet device (although, the SMSC95xx driver needs to be
fixed to support that, cfr. the other thread).
--
Best regards,
Marek Vasut
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH V3] net: phy: tja11xx: Add TJA11xx PHY driver
2018-12-23 10:06 ` Andrew Lunn
@ 2018-12-23 10:49 ` Marek Vasut
2018-12-23 10:58 ` Andrew Lunn
0 siblings, 1 reply; 20+ messages in thread
From: Marek Vasut @ 2018-12-23 10:49 UTC (permalink / raw)
To: Andrew Lunn, Heiner Kallweit; +Cc: netdev, Florian Fainelli
On 12/23/18 11:06 AM, Andrew Lunn wrote:
>>> + switch (attr) {
>>> + case hwmon_in_lcrit_alarm:
>>> + ret = phy_read(phydev, MII_INTSRC);
>>> + if (ret < 0)
>>> + return ret;
>>> +
>>> + *value = !!(ret & MII_INTSRC_TEMP_ERR);
>>> + return 0;
>>> + case hwmon_temp_crit_alarm:
>>> + ret = phy_read(phydev, MII_INTSRC);
>>> + if (ret < 0)
>>> + return ret;
>>> +
>>> + *value = !!(ret & MII_INTSRC_TEMP_ERR);
>>> + return 0;
>>> + default:
>>> + return -EOPNOTSUPP;
>>> + }
>>> +}
>> This looks like a copy & paste error, in both cases you're doing the same.
>
> You also should not do it like this. hwmon_temp_crit_alarm is in a
> different set of enum's as hwmon_in_lcrit_alarm. hwmon_in_lcrit_alarm
> = 14. hwmon_temp_max_alarm also is 14. You should have two different
> switch statements to take account of this.
I can also use a simple conditional, since I don't expect the number of
HWMON properties to grow, eg.
if (type == hwmon_in && attr == hwmon_in_lcrit_alarm) {...}
if (type == hwmon_temp && attr == hwmon_temp_crit_alarm) {...}
I think that's a bit more readable.
--
Best regards,
Marek Vasut
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH V3] net: phy: tja11xx: Add TJA11xx PHY driver
2018-12-23 10:49 ` Marek Vasut
@ 2018-12-23 10:58 ` Andrew Lunn
2018-12-23 11:00 ` Marek Vasut
0 siblings, 1 reply; 20+ messages in thread
From: Andrew Lunn @ 2018-12-23 10:58 UTC (permalink / raw)
To: Marek Vasut; +Cc: Heiner Kallweit, netdev, Florian Fainelli
> I can also use a simple conditional, since I don't expect the number of
> HWMON properties to grow, eg.
>
> if (type == hwmon_in && attr == hwmon_in_lcrit_alarm) {...}
> if (type == hwmon_temp && attr == hwmon_temp_crit_alarm) {...}
Yes, that is fine.
Please make sure you Cc: the HWMON maintainer on this patch.
Andrew
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH V3] net: phy: tja11xx: Add TJA11xx PHY driver
2018-12-23 10:58 ` Andrew Lunn
@ 2018-12-23 11:00 ` Marek Vasut
0 siblings, 0 replies; 20+ messages in thread
From: Marek Vasut @ 2018-12-23 11:00 UTC (permalink / raw)
To: Andrew Lunn; +Cc: Heiner Kallweit, netdev, Florian Fainelli
On 12/23/18 11:58 AM, Andrew Lunn wrote:
>> I can also use a simple conditional, since I don't expect the number of
>> HWMON properties to grow, eg.
>>
>> if (type == hwmon_in && attr == hwmon_in_lcrit_alarm) {...}
>> if (type == hwmon_temp && attr == hwmon_temp_crit_alarm) {...}
>
> Yes, that is fine.
>
> Please make sure you Cc: the HWMON maintainer on this patch.
Fine
--
Best regards,
Marek Vasut
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH V3] net: phy: tja11xx: Add TJA11xx PHY driver
2018-12-23 9:16 ` Marek Vasut
2018-12-23 9:41 ` Heiner Kallweit
@ 2019-01-03 2:09 ` Marek Vasut
2019-01-03 6:23 ` Heiner Kallweit
1 sibling, 1 reply; 20+ messages in thread
From: Marek Vasut @ 2019-01-03 2:09 UTC (permalink / raw)
To: Heiner Kallweit, netdev; +Cc: Andrew Lunn, Florian Fainelli
On 12/23/18 10:16 AM, Marek Vasut wrote:
> On 12/22/18 6:39 PM, Heiner Kallweit wrote:
>> On 22.12.2018 00:35, Marek Vasut wrote:
>>> Add driver for the NXP TJA1100 and TJA1101 PHYs. These PHYs are special
>>> BroadRReach 100BaseT1 PHYs used in automotive.
>>>
>>> Signed-off-by: Marek Vasut <marex@denx.de>
>>> Cc: Andrew Lunn <andrew@lunn.ch>
>>> Cc: Florian Fainelli <f.fainelli@gmail.com>
>>> Cc: Heiner Kallweit <hkallweit1@gmail.com>
>>> ---
>>> V2: - Use phy_modify(), phy_{set,clear}_bits()
>>> - Drop enable argument of tja11xx_enable_link_control()
>>> - Use PHY_BASIC_T1_FEATURES and dont modify supported/advertised
>>> features in config_init callback
>>> - Use genphy_soft_reset() instead of opencoding the reset sequence.
>>> - Drop the aneg parts, since the PHY datasheet claims it does not
>>> support aneg
>>> V3: - Replace clr with mask
>>> - Add hwmon support
>>> - Check commstat in tja11xx_read_status() only if link is up
>>> - Use PHY_ID_MATCH_MODEL()
>>> ---
>>> drivers/net/phy/Kconfig | 6 +
>>> drivers/net/phy/Makefile | 1 +
>>> drivers/net/phy/nxp-tja11xx.c | 424 ++++++++++++++++++++++++++++++++++
>>> 3 files changed, 431 insertions(+)
>>> create mode 100644 drivers/net/phy/nxp-tja11xx.c
>>>
>> [...]
>>> +
>>> +struct tja11xx_phy_stats {
>>> + const char *string;
>>> + u8 reg;
>>> + u8 off;
>>> + u16 mask;
>>> +};
>>> +
>> As written in my other mail, you could think of using
>> FIELD_GET() again. Things like
>> ... n, BIT(n),
>> ... m, BIT(m),
>> are simply redundant.
>
> Done
And undone, FIELD_GET() requires a mask that is compile-time constant.
That's not the case here.
Replicating what FIELD_GET() does at runtime is inefficient, so we can
as well encode the field and offset back into the table. Or is there a
better suggestion ?
--
Best regards,
Marek Vasut
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH V3] net: phy: tja11xx: Add TJA11xx PHY driver
2019-01-03 2:09 ` Marek Vasut
@ 2019-01-03 6:23 ` Heiner Kallweit
2019-01-04 2:19 ` Marek Vasut
0 siblings, 1 reply; 20+ messages in thread
From: Heiner Kallweit @ 2019-01-03 6:23 UTC (permalink / raw)
To: Marek Vasut, netdev; +Cc: Andrew Lunn, Florian Fainelli
On 03.01.2019 03:09, Marek Vasut wrote:
> On 12/23/18 10:16 AM, Marek Vasut wrote:
>> On 12/22/18 6:39 PM, Heiner Kallweit wrote:
>>> On 22.12.2018 00:35, Marek Vasut wrote:
>>>> Add driver for the NXP TJA1100 and TJA1101 PHYs. These PHYs are special
>>>> BroadRReach 100BaseT1 PHYs used in automotive.
>>>>
>>>> Signed-off-by: Marek Vasut <marex@denx.de>
>>>> Cc: Andrew Lunn <andrew@lunn.ch>
>>>> Cc: Florian Fainelli <f.fainelli@gmail.com>
>>>> Cc: Heiner Kallweit <hkallweit1@gmail.com>
>>>> ---
>>>> V2: - Use phy_modify(), phy_{set,clear}_bits()
>>>> - Drop enable argument of tja11xx_enable_link_control()
>>>> - Use PHY_BASIC_T1_FEATURES and dont modify supported/advertised
>>>> features in config_init callback
>>>> - Use genphy_soft_reset() instead of opencoding the reset sequence.
>>>> - Drop the aneg parts, since the PHY datasheet claims it does not
>>>> support aneg
>>>> V3: - Replace clr with mask
>>>> - Add hwmon support
>>>> - Check commstat in tja11xx_read_status() only if link is up
>>>> - Use PHY_ID_MATCH_MODEL()
>>>> ---
>>>> drivers/net/phy/Kconfig | 6 +
>>>> drivers/net/phy/Makefile | 1 +
>>>> drivers/net/phy/nxp-tja11xx.c | 424 ++++++++++++++++++++++++++++++++++
>>>> 3 files changed, 431 insertions(+)
>>>> create mode 100644 drivers/net/phy/nxp-tja11xx.c
>>>>
>>> [...]
>>>> +
>>>> +struct tja11xx_phy_stats {
>>>> + const char *string;
>>>> + u8 reg;
>>>> + u8 off;
>>>> + u16 mask;
>>>> +};
>>>> +
>>> As written in my other mail, you could think of using
>>> FIELD_GET() again. Things like
>>> ... n, BIT(n),
>>> ... m, BIT(m),
>>> are simply redundant.
>>
>> Done
>
> And undone, FIELD_GET() requires a mask that is compile-time constant.
> That's not the case here.
>
> Replicating what FIELD_GET() does at runtime is inefficient, so we can
> as well encode the field and offset back into the table. Or is there a
> better suggestion ?
>
You're right, FIELD_GET() requires a constant as mask. Then for the
case here I'm not aware of a better solution than having also the mask
in the table.
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH V3] net: phy: tja11xx: Add TJA11xx PHY driver
2019-01-03 6:23 ` Heiner Kallweit
@ 2019-01-04 2:19 ` Marek Vasut
2019-01-04 2:53 ` Marek Vasut
0 siblings, 1 reply; 20+ messages in thread
From: Marek Vasut @ 2019-01-04 2:19 UTC (permalink / raw)
To: Heiner Kallweit, netdev; +Cc: Andrew Lunn, Florian Fainelli
On 1/3/19 7:23 AM, Heiner Kallweit wrote:
> On 03.01.2019 03:09, Marek Vasut wrote:
>> On 12/23/18 10:16 AM, Marek Vasut wrote:
>>> On 12/22/18 6:39 PM, Heiner Kallweit wrote:
>>>> On 22.12.2018 00:35, Marek Vasut wrote:
>>>>> Add driver for the NXP TJA1100 and TJA1101 PHYs. These PHYs are special
>>>>> BroadRReach 100BaseT1 PHYs used in automotive.
>>>>>
>>>>> Signed-off-by: Marek Vasut <marex@denx.de>
>>>>> Cc: Andrew Lunn <andrew@lunn.ch>
>>>>> Cc: Florian Fainelli <f.fainelli@gmail.com>
>>>>> Cc: Heiner Kallweit <hkallweit1@gmail.com>
>>>>> ---
>>>>> V2: - Use phy_modify(), phy_{set,clear}_bits()
>>>>> - Drop enable argument of tja11xx_enable_link_control()
>>>>> - Use PHY_BASIC_T1_FEATURES and dont modify supported/advertised
>>>>> features in config_init callback
>>>>> - Use genphy_soft_reset() instead of opencoding the reset sequence.
>>>>> - Drop the aneg parts, since the PHY datasheet claims it does not
>>>>> support aneg
>>>>> V3: - Replace clr with mask
>>>>> - Add hwmon support
>>>>> - Check commstat in tja11xx_read_status() only if link is up
>>>>> - Use PHY_ID_MATCH_MODEL()
>>>>> ---
>>>>> drivers/net/phy/Kconfig | 6 +
>>>>> drivers/net/phy/Makefile | 1 +
>>>>> drivers/net/phy/nxp-tja11xx.c | 424 ++++++++++++++++++++++++++++++++++
>>>>> 3 files changed, 431 insertions(+)
>>>>> create mode 100644 drivers/net/phy/nxp-tja11xx.c
>>>>>
>>>> [...]
>>>>> +
>>>>> +struct tja11xx_phy_stats {
>>>>> + const char *string;
>>>>> + u8 reg;
>>>>> + u8 off;
>>>>> + u16 mask;
>>>>> +};
>>>>> +
>>>> As written in my other mail, you could think of using
>>>> FIELD_GET() again. Things like
>>>> ... n, BIT(n),
>>>> ... m, BIT(m),
>>>> are simply redundant.
>>>
>>> Done
>>
>> And undone, FIELD_GET() requires a mask that is compile-time constant.
>> That's not the case here.
>>
>> Replicating what FIELD_GET() does at runtime is inefficient, so we can
>> as well encode the field and offset back into the table. Or is there a
>> better suggestion ?
>>
> You're right, FIELD_GET() requires a constant as mask. Then for the
> case here I'm not aware of a better solution than having also the mask
> in the table.
V4 is out then.
--
Best regards,
Marek Vasut
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH V3] net: phy: tja11xx: Add TJA11xx PHY driver
2019-01-04 2:19 ` Marek Vasut
@ 2019-01-04 2:53 ` Marek Vasut
2019-01-04 2:57 ` Florian Fainelli
0 siblings, 1 reply; 20+ messages in thread
From: Marek Vasut @ 2019-01-04 2:53 UTC (permalink / raw)
To: Heiner Kallweit, netdev; +Cc: Andrew Lunn, Florian Fainelli
On 1/4/19 3:19 AM, Marek Vasut wrote:
[...]
On a separate note, I was pondering about the master/slave mode of the
TJA11xx PHY. Right now, the driver only operates in Automatic mode,
however the PHY can be force-configured as either master or slave.
Would using .set_tunable with a new tunable type be a good way to expose
this to userspace ? The ethtool can then configure the PHY mode.
--
Best regards,
Marek Vasut
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH V3] net: phy: tja11xx: Add TJA11xx PHY driver
2019-01-04 2:53 ` Marek Vasut
@ 2019-01-04 2:57 ` Florian Fainelli
2019-01-04 5:40 ` Marek Vasut
0 siblings, 1 reply; 20+ messages in thread
From: Florian Fainelli @ 2019-01-04 2:57 UTC (permalink / raw)
To: Marek Vasut, Heiner Kallweit, netdev; +Cc: Andrew Lunn
On 1/3/2019 6:53 PM, Marek Vasut wrote:
> On 1/4/19 3:19 AM, Marek Vasut wrote:
>
> [...]
>
> On a separate note, I was pondering about the master/slave mode of the
> TJA11xx PHY. Right now, the driver only operates in Automatic mode,
> however the PHY can be force-configured as either master or slave.
> Would using .set_tunable with a new tunable type be a good way to expose
> this to userspace ? The ethtool can then configure the PHY mode.
Using an ethtool u8 tunable would be fine, with something like:
0 -> automatic
1 -> force master
2 -> force slave
--
Florian
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH V3] net: phy: tja11xx: Add TJA11xx PHY driver
2019-01-04 2:57 ` Florian Fainelli
@ 2019-01-04 5:40 ` Marek Vasut
0 siblings, 0 replies; 20+ messages in thread
From: Marek Vasut @ 2019-01-04 5:40 UTC (permalink / raw)
To: Florian Fainelli, Heiner Kallweit, netdev; +Cc: Andrew Lunn
On 1/4/19 3:57 AM, Florian Fainelli wrote:
>
>
> On 1/3/2019 6:53 PM, Marek Vasut wrote:
>> On 1/4/19 3:19 AM, Marek Vasut wrote:
>>
>> [...]
>>
>> On a separate note, I was pondering about the master/slave mode of the
>> TJA11xx PHY. Right now, the driver only operates in Automatic mode,
>> however the PHY can be force-configured as either master or slave.
>> Would using .set_tunable with a new tunable type be a good way to expose
>> this to userspace ? The ethtool can then configure the PHY mode.
>
> Using an ethtool u8 tunable would be fine, with something like:
>
> 0 -> automatic
> 1 -> force master
> 2 -> force slave
Fine, however I'll send it as a separate patch later.
How does this name/macro sound for the tunable ?
[ETHTOOL_PHY_BRR_MODE] = "phy-broadrreach-mode",
--
Best regards,
Marek Vasut
^ permalink raw reply [flat|nested] 20+ messages in thread
end of thread, other threads:[~2019-01-04 5:40 UTC | newest]
Thread overview: 20+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-12-21 23:35 [PATCH V3] net: phy: tja11xx: Add TJA11xx PHY driver Marek Vasut
2018-12-22 17:39 ` Heiner Kallweit
2018-12-23 9:16 ` Marek Vasut
2018-12-23 9:41 ` Heiner Kallweit
2018-12-23 9:59 ` Andrew Lunn
2018-12-23 10:21 ` Marek Vasut
2018-12-23 10:35 ` Andrew Lunn
2018-12-23 10:48 ` Marek Vasut
2019-01-03 2:09 ` Marek Vasut
2019-01-03 6:23 ` Heiner Kallweit
2019-01-04 2:19 ` Marek Vasut
2019-01-04 2:53 ` Marek Vasut
2019-01-04 2:57 ` Florian Fainelli
2019-01-04 5:40 ` Marek Vasut
2018-12-22 20:51 ` Heiner Kallweit
2018-12-23 9:13 ` Marek Vasut
2018-12-23 10:06 ` Andrew Lunn
2018-12-23 10:49 ` Marek Vasut
2018-12-23 10:58 ` Andrew Lunn
2018-12-23 11:00 ` Marek Vasut
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).