[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <1465040728-4904-4-git-send-email-hauke@hauke-m.de>
Date: Sat, 4 Jun 2016 13:45:28 +0200
From: Hauke Mehrtens <hauke@...ke-m.de>
To: f.fainelli@...il.com
Cc: alexander.stein@...tec-electronic.com, netdev@...r.kernel.org,
andrew@...n.ch, john@...ozen.org, openwrt@...sin.me,
hauke.mehrtens@...el.com, daniel.schwierzeck@...il.com,
eckert.florian@...glemail.com, devicetree@...r.kernel.org,
Hauke Mehrtens <hauke@...ke-m.de>
Subject: [RFC v3 3/3] NET: PHY: Intel XWAY: add LED configuration support
This makes it possible to configure the behavior of the LEDs connected
to a PHY. The LEDs are controlled by the chip, this makes it possible
to configure the behavior when the hardware should activate and
deactivate the LEDs.
Signed-off-by: Hauke Mehrtens <hauke@...ke-m.de>
---
.../devicetree/bindings/phy/intel-xway.txt | 77 +++++++++++
drivers/net/phy/intel-xway.c | 152 +++++++++++++++++++++
2 files changed, 229 insertions(+)
create mode 100644 Documentation/devicetree/bindings/phy/intel-xway.txt
diff --git a/Documentation/devicetree/bindings/phy/intel-xway.txt b/Documentation/devicetree/bindings/phy/intel-xway.txt
new file mode 100644
index 0000000..02891c4
--- /dev/null
+++ b/Documentation/devicetree/bindings/phy/intel-xway.txt
@@ -0,0 +1,77 @@
+Intel XWAY Ethernet PHY binding
+------------------------------
+
+This supports the Intel XWAY (former Lantiq) 11G and 22E PHYs. These
+PHYs are also named PEF 7061, PEF 7071 and PEF 7072.
+
+Required properties:
+ - compatible: should be "ethernet-phy-ieee802.3-c22"
+ - reg: MDIO address of this PHY
+
+
+LEDs:
+The PEF 7071 PHY supports 3 LEDs, the PEF 7072 PHY supports 4 LEDs. Use
+one subnode for each LED. By default the LEDs 0, 1 and 2 are switched
+to be constant on when a 10MBit/s, 100MBit/s or 1000MBit/s link is
+detected and they blink when TX or RX traffic is detected. All 3 LEDs
+are doing the same as most known devices only have one LED.
+
+To change the behavior create a subnode with the following attributes:
+
+Required properties:
+ - compatible: should be: "phy,led"
+ - reg: led number
+
+optional properties:
+ - led-const-on: Conditions when being constant on
+ Possible options are one of these:
+ LED_LINK10, LED_LINK100 and LED_LINK1000, or
+ some of these 3 values connected with OR.
+ PHY_LED_PDOWN, PHY_LED_EEE, PHY_LED_ANEG,
+ PHY_LED_ABIST, PHY_LED_CDIAG, PHY_LED_COPPER,
+ PHY_LED_FIBER.
+ - led-pulse: Conditions when led is pulsed
+ The following values can be connected with OR:
+ PHY_LED_TXACT, PHY_LED_RXACT, PHY_LED_COL
+ - led-blink-slow: Conditions when led should blink with 2Hz:
+ Possible options are one of these:
+ LED_LINK10, LED_LINK100 and LED_LINK1000, or
+ some of these 3 values connected with OR.
+ PHY_LED_PDOWN, PHY_LED_EEE, PHY_LED_ANEG,
+ PHY_LED_ABIST, PHY_LED_CDIAG.
+ - led-blink-fast: Conditions when led should blink with 16Hz:
+ Possible options are one of these:
+ LED_LINK10, LED_LINK100 and LED_LINK1000, or
+ some of these 3 values connected with OR.
+ PHY_LED_PDOWN, PHY_LED_EEE, PHY_LED_ANEG,
+ PHY_LED_ABIST, PHY_LED_CDIAG.
+
+When multiple properties are set they are applied with the following priority:
+ 1. led-pulse
+ 2. led-blink-fast
+ 3. led-blink-slow
+ 4. led-const-on
+ 5. off
+
+
+Example:
+
+#include <dt-bindings/phy/phy-leds.h>
+phy@0 {
+ compatible = "intel,phy11g", "ethernet-phy-ieee802.3-c22";
+ reg = <0x0>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ led@0 {
+ compatible = "phy,led";
+ reg = <0>;
+ led-const-on = <(PHY_LED_LINK10 | PHY_LED_LINK100 | PHY_LED_LINK1000)>;
+ led-pulse = <(PHY_LED_TXACT | PHY_LED_RXACT)>;
+ };
+ led@2 {
+ compatible = "phy,led";
+ reg = <2>;
+ led-blink-slow = <PHY_LED_EEE>;
+ led-blink-fast = <PHY_LED_PDOWN>;
+ };
+};
diff --git a/drivers/net/phy/intel-xway.c b/drivers/net/phy/intel-xway.c
index c789462..0c707b6 100644
--- a/drivers/net/phy/intel-xway.c
+++ b/drivers/net/phy/intel-xway.c
@@ -17,6 +17,7 @@
#include <linux/module.h>
#include <linux/phy.h>
#include <linux/of.h>
+#include <dt-bindings/phy/phy-leds.h>
#define XWAY_MDIO_IMASK 0x19 /* interrupt mask */
#define XWAY_MDIO_ISTAT 0x1A /* interrupt status */
@@ -152,11 +153,158 @@
#define PHY_ID_PHY11G_VR9 0xD565A409
#define PHY_ID_PHY22F_VR9 0xD565A419
+static void xway_gphy_config_led(struct phy_device *phydev,
+ struct device_node *led_np)
+{
+ const __be32 *addr, *blink_fast_p, *const_on_p, *pulse_p, *blink_slow_p;
+ u32 num, blink_fast, const_on, pulse, blink_slow;
+ u32 ledxl;
+ u32 ledxh;
+
+ addr = of_get_property(led_np, "reg", NULL);
+ if (!addr)
+ return;
+ num = be32_to_cpu(*addr);
+
+ if (num < 0 || num > 3)
+ return;
+
+ ledxh = XWAY_MMD_LEDxH_BLINKF_NONE | XWAY_MMD_LEDxH_CON_LINK10XX;
+ blink_fast_p = of_get_property(led_np, "led-blink-fast", NULL);
+ if (blink_fast_p) {
+ ledxh &= ~XWAY_MMD_LEDxH_BLINKF_MASK;
+ blink_fast = be32_to_cpu(*blink_fast_p);
+ if ((blink_fast & PHY_LED_LINK10) &&
+ (blink_fast & PHY_LED_LINK100) &&
+ (blink_fast & PHY_LED_LINK1000)) {
+ ledxh |= XWAY_MMD_LEDxH_BLINKF_LINK10XX;
+ } else if ((blink_fast & PHY_LED_LINK10) &&
+ (blink_fast & PHY_LED_LINK1000)) {
+ ledxh |= XWAY_MMD_LEDxH_BLINKF_LINK10_0;
+ } else if ((blink_fast & PHY_LED_LINK10) &&
+ (blink_fast & PHY_LED_LINK100)) {
+ ledxh |= XWAY_MMD_LEDxH_BLINKF_LINK10X;
+ } else if ((blink_fast & PHY_LED_LINK100) &&
+ (blink_fast & PHY_LED_LINK1000)) {
+ ledxh |= XWAY_MMD_LEDxH_BLINKF_LINK100X;
+ } else if (blink_fast & PHY_LED_LINK10) {
+ ledxh |= XWAY_MMD_LEDxH_BLINKF_LINK10;
+ } else if (blink_fast & PHY_LED_LINK100) {
+ ledxh |= XWAY_MMD_LEDxH_BLINKF_LINK100;
+ } else if (blink_fast & PHY_LED_LINK1000) {
+ ledxh |= XWAY_MMD_LEDxH_BLINKF_LINK1000;
+ } else if (blink_fast & PHY_LED_PDOWN) {
+ ledxh |= XWAY_MMD_LEDxH_BLINKF_PDOWN;
+ } else if (blink_fast & PHY_LED_EEE) {
+ ledxh |= XWAY_MMD_LEDxH_BLINKF_EEE;
+ } else if (blink_fast & PHY_LED_ANEG) {
+ ledxh |= XWAY_MMD_LEDxH_BLINKF_ANEG;
+ } else if (blink_fast & PHY_LED_ABIST) {
+ ledxh |= XWAY_MMD_LEDxH_BLINKF_ABIST;
+ } else if (blink_fast & PHY_LED_CDIAG) {
+ ledxh |= XWAY_MMD_LEDxH_BLINKF_CDIAG;
+ }
+ }
+ const_on_p = of_get_property(led_np, "led-const-on", NULL);
+ if (const_on_p) {
+ ledxh &= ~XWAY_MMD_LEDxH_CON_MASK;
+ const_on = be32_to_cpu(*const_on_p);
+ if ((const_on & PHY_LED_LINK10) &&
+ (const_on & PHY_LED_LINK100) &&
+ (const_on & PHY_LED_LINK1000)) {
+ ledxh |= XWAY_MMD_LEDxH_CON_LINK10XX;
+ } else if ((const_on & PHY_LED_LINK10) &&
+ (const_on & PHY_LED_LINK1000)) {
+ ledxh |= XWAY_MMD_LEDxH_CON_LINK10_0;
+ } else if ((const_on & PHY_LED_LINK10) &&
+ (const_on & PHY_LED_LINK100)) {
+ ledxh |= XWAY_MMD_LEDxH_CON_LINK10X;
+ } else if ((const_on & PHY_LED_LINK100) &&
+ (const_on & PHY_LED_LINK1000)) {
+ ledxh |= XWAY_MMD_LEDxH_CON_LINK100X;
+ } else if (const_on & PHY_LED_LINK10) {
+ ledxh |= XWAY_MMD_LEDxH_CON_LINK10;
+ } else if (const_on & PHY_LED_LINK100) {
+ ledxh |= XWAY_MMD_LEDxH_CON_LINK100;
+ } else if (const_on & PHY_LED_LINK1000) {
+ ledxh |= XWAY_MMD_LEDxH_CON_LINK1000;
+ } else if (const_on & PHY_LED_PDOWN) {
+ ledxh |= XWAY_MMD_LEDxH_CON_PDOWN;
+ } else if (const_on & PHY_LED_EEE) {
+ ledxh |= XWAY_MMD_LEDxH_CON_EEE;
+ } else if (const_on & PHY_LED_ANEG) {
+ ledxh |= XWAY_MMD_LEDxH_CON_ANEG;
+ } else if (const_on & PHY_LED_ABIST) {
+ ledxh |= XWAY_MMD_LEDxH_CON_ABIST;
+ } else if (const_on & PHY_LED_CDIAG) {
+ ledxh |= XWAY_MMD_LEDxH_CON_CDIAG;
+ } else if (const_on & PHY_LED_COPPER) {
+ ledxh |= XWAY_MMD_LEDxH_CON_COPPER;
+ } else if (const_on & PHY_LED_FIBER) {
+ ledxh |= XWAY_MMD_LEDxH_CON_FIBER;
+ }
+ }
+ phy_write_mmd_indirect(phydev, XWAY_MMD_LED0H + (num * 2),
+ MDIO_MMD_VEND2, ledxh);
+
+ ledxl = XWAY_MMD_LEDxL_PULSE_TXACT | XWAY_MMD_LEDxL_PULSE_RXACT |
+ XWAY_MMD_LEDxL_BLINKS_NONE;
+ pulse_p = of_get_property(led_np, "led-pulse", NULL);
+ if (pulse_p) {
+ ledxl &= ~XWAY_MMD_LEDxL_PULSE_MASK;
+ pulse = be32_to_cpu(*pulse_p);
+ if (pulse & PHY_LED_TXACT)
+ ledxl |= XWAY_MMD_LEDxL_PULSE_TXACT;
+ if (pulse & PHY_LED_RXACT)
+ ledxl |= XWAY_MMD_LEDxL_PULSE_RXACT;
+ if (pulse & PHY_LED_COL)
+ ledxl |= XWAY_MMD_LEDxL_PULSE_COL;
+ }
+ blink_slow_p = of_get_property(led_np, "led-blink-slow", NULL);
+ if (blink_slow_p) {
+ ledxl &= ~XWAY_MMD_LEDxL_BLINKS_MASK;
+ blink_slow = be32_to_cpu(*blink_slow_p);
+ if ((blink_slow & PHY_LED_LINK10) &&
+ (blink_slow & PHY_LED_LINK100) &&
+ (blink_slow & PHY_LED_LINK1000)) {
+ ledxl |= XWAY_MMD_LEDxL_BLINKS_LINK10XX;
+ } else if ((blink_slow & PHY_LED_LINK10) &&
+ (blink_slow & PHY_LED_LINK1000)) {
+ ledxl |= XWAY_MMD_LEDxL_BLINKS_LINK10_0;
+ } else if ((blink_slow & PHY_LED_LINK10) &&
+ (blink_slow & PHY_LED_LINK100)) {
+ ledxl |= XWAY_MMD_LEDxL_BLINKS_LINK10X;
+ } else if ((blink_slow & PHY_LED_LINK100) &&
+ (blink_slow & PHY_LED_LINK1000)) {
+ ledxl |= XWAY_MMD_LEDxL_BLINKS_LINK100X;
+ } else if (blink_slow & PHY_LED_LINK10) {
+ ledxl |= XWAY_MMD_LEDxL_BLINKS_LINK10;
+ } else if (blink_slow & PHY_LED_LINK100) {
+ ledxl |= XWAY_MMD_LEDxL_BLINKS_LINK100;
+ } else if (blink_slow & PHY_LED_LINK1000) {
+ ledxl |= XWAY_MMD_LEDxL_BLINKS_LINK1000;
+ } else if (blink_slow & PHY_LED_PDOWN) {
+ ledxl |= XWAY_MMD_LEDxL_BLINKS_PDOWN;
+ } else if (blink_slow & PHY_LED_EEE) {
+ ledxl |= XWAY_MMD_LEDxL_BLINKS_EEE;
+ } else if (blink_slow & PHY_LED_ANEG) {
+ ledxl |= XWAY_MMD_LEDxL_BLINKS_ANEG;
+ } else if (blink_slow & PHY_LED_ABIST) {
+ ledxl |= XWAY_MMD_LEDxL_BLINKS_ABIST;
+ } else if (blink_slow & PHY_LED_CDIAG) {
+ ledxl |= XWAY_MMD_LEDxL_BLINKS_CDIAG;
+ }
+ }
+ phy_write_mmd_indirect(phydev, XWAY_MMD_LED0L + (num * 2),
+ MDIO_MMD_VEND2, ledxl);
+}
+
static int xway_gphy_config_init(struct phy_device *phydev)
{
int err;
u32 ledxh;
u32 ledxl;
+ struct device_node *led_np;
/* Mask all interrupts */
err = phy_write(phydev, XWAY_MDIO_IMASK, 0);
@@ -190,6 +338,10 @@ static int xway_gphy_config_init(struct phy_device *phydev)
phy_write_mmd_indirect(phydev, XWAY_MMD_LED2H, MDIO_MMD_VEND2, ledxh);
phy_write_mmd_indirect(phydev, XWAY_MMD_LED2L, MDIO_MMD_VEND2, ledxl);
+ for_each_child_of_node(phydev->mdio.dev.of_node, led_np)
+ if (of_device_is_compatible(led_np, "phy,led"))
+ xway_gphy_config_led(phydev, led_np);
+
return 0;
}
--
2.8.1
Powered by blists - more mailing lists