From patchwork Sat Dec 9 01:48:27 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Christian Marangi X-Patchwork-Id: 13485934 X-Patchwork-Delegate: kuba@kernel.org Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="hXOgtvFL" Received: from mail-wm1-x329.google.com (mail-wm1-x329.google.com [IPv6:2a00:1450:4864:20::329]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 89455E3; Fri, 8 Dec 2023 17:48:37 -0800 (PST) Received: by mail-wm1-x329.google.com with SMTP id 5b1f17b1804b1-40c39e936b4so4022705e9.1; Fri, 08 Dec 2023 17:48:37 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1702086516; x=1702691316; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:message-id:date:subject:to :from:from:to:cc:subject:date:message-id:reply-to; bh=b5TEoN9vdBbfGAJM/hB7+1BTZHwjSbPnt7yiTcrzTj8=; b=hXOgtvFLcBvivpUwVYMwm5L6MDNM+kaQ3Zy7eUMIu7ORLBQimNWl8CouKnm+alvD99 1YBrA6aa5eHoGRWv6/Bn+uc/9T6NDfaBqOZzgZmVvZA92gbbyx/pQ8e7vhLY9jsveHUP ZhJojQA+sWWgMvzZwWun4hgAbg+O0vYrQ0KULvfjmJqAeSSQQYoCuX/GIOxwu3C7UuYn b4cwGgS//DsUAdf7S4ZbzimJDhuV4Vm2OhrDl22JAKplBL+wQn5/w27kD3yNuelf8EBc S6f42bUIVYEiTfXtNzBNokc3SmETDd/4i6SIsjORlBIJPU6Rfdh9WBELQFXwLOk6vFVL eUBQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1702086516; x=1702691316; h=content-transfer-encoding:mime-version:message-id:date:subject:to :from:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=b5TEoN9vdBbfGAJM/hB7+1BTZHwjSbPnt7yiTcrzTj8=; b=JTnmO/63q91bTZzf7UsjLw6JOBd7F6pyntJAe+hrSKCI7U8iW3oITyV1vpwJOFLmzM pozWxJkgtqqs29YW480G3uSEjTwUntgRb4PMShF+2FGPvaqu/DNt4glX5ghtJiBe3vDU k4PZnrBcCXcJ/5HrfwZYmeDgfqz8DJnE2hH21Tz7QyQxUtZKU13kU0vGvcEJ9JZ3VEXf hg9De9ssVgZK8qIGTpalEuPKntWlm7h/bcgzbz7NgFz2RdNGGipZdSYGu82du4/955XY Tw4NruC25SVk0cwkgFMqXNvO4mPyu3501bg6h8eUgrtUXTOcTYkdIzBaociv/7QRGX5f nSlw== X-Gm-Message-State: AOJu0Yw1f2D5Lob7pENCisoYxp+VjPb3wly8MN4ibvlllQoHUa09F/PO MusO9iPacWj47w26dxmXNLo= X-Google-Smtp-Source: AGHT+IHt7khlaVyNJ786ZfNWjEYzbl2gYMNhEnAwlIuVvPoveCgGqGVZ/sslT2rtJ+yo9gHGswDr9Q== X-Received: by 2002:a05:600c:1ca7:b0:40b:5e59:f726 with SMTP id k39-20020a05600c1ca700b0040b5e59f726mr202635wms.152.1702086515720; Fri, 08 Dec 2023 17:48:35 -0800 (PST) Received: from localhost.localdomain (93-34-89-13.ip49.fastwebnet.it. [93.34.89.13]) by smtp.googlemail.com with ESMTPSA id n18-20020a05600c501200b0040c26a459b4sm1218118wmr.0.2023.12.08.17.48.34 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 08 Dec 2023 17:48:35 -0800 (PST) From: Christian Marangi To: "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Andrew Lunn , Heiner Kallweit , Russell King , Christian Marangi , netdev@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [net-next PATCH 1/2] dt-bindings: Document QCA808x PHYs Date: Sat, 9 Dec 2023 02:48:27 +0100 Message-Id: <20231209014828.28194-1-ansuelsmth@gmail.com> X-Mailer: git-send-email 2.40.1 Precedence: bulk X-Mailing-List: netdev@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Patchwork-Delegate: kuba@kernel.org Add Documentation for QCA808x PHYs for the additional property for the active high LED setting and also document the LED configuration for this PHY. Signed-off-by: Christian Marangi --- .../devicetree/bindings/net/qca,qca808x.yaml | 66 +++++++++++++++++++ 1 file changed, 66 insertions(+) create mode 100644 Documentation/devicetree/bindings/net/qca,qca808x.yaml diff --git a/Documentation/devicetree/bindings/net/qca,qca808x.yaml b/Documentation/devicetree/bindings/net/qca,qca808x.yaml new file mode 100644 index 000000000000..73cfff357311 --- /dev/null +++ b/Documentation/devicetree/bindings/net/qca,qca808x.yaml @@ -0,0 +1,66 @@ +# SPDX-License-Identifier: GPL-2.0+ +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/net/qca,qca808x.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Qualcomm Atheros QCA808X PHY + +maintainers: + - Christian Marangi + +description: + Bindings for Qualcomm Atheros QCA808X PHYs + + QCA808X PHYs can have up to 3 LEDs attached. + All 3 LEDs are disabled by default. + 2 LEDs have dedicated pins with the 3rd LED having the + double function of Interrupt LEDs/GPIO or additional LED. + + By default this special PIN is set to LED function. + +allOf: + - $ref: ethernet-phy.yaml# + +select: + properties: + compatible: + contains: + enum: + - ethernet-phy-id004d.d101 + required: + - compatible + +properties: + qca,led-active-high: + description: Set all the LEDs to active high to be turned on. + type: boolean + +unevaluatedProperties: false + +examples: + - | + #include + + mdio { + #address-cells = <1>; + #size-cells = <0>; + + ethernet-phy@0 { + compatible = "ethernet-phy-id004d.d101"; + reg = <0>; + qca,led-active-high; + + leds { + #address-cells = <1>; + #size-cells = <0>; + + led@0 { + reg = <0>; + color = ; + function = LED_FUNCTION_WAN; + default-state = "keep"; + }; + }; + }; + }; From patchwork Sat Dec 9 01:48:28 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Christian Marangi X-Patchwork-Id: 13485935 X-Patchwork-Delegate: kuba@kernel.org Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="mKdBJOfQ" Received: from mail-wm1-x330.google.com (mail-wm1-x330.google.com [IPv6:2a00:1450:4864:20::330]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id B5FC4126; Fri, 8 Dec 2023 17:48:38 -0800 (PST) Received: by mail-wm1-x330.google.com with SMTP id 5b1f17b1804b1-40b27726369so28751645e9.0; Fri, 08 Dec 2023 17:48:38 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1702086517; x=1702691317; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=2knlCI7/Bd7n1MjOgM6VSp8rvM/6OSL7/7QYt4FqE14=; b=mKdBJOfQLHn5gbe8qC9tmR3Ys4lBmYb2CCVlUPEsWWlHNlFkZ4mcmckOjKiajMLJGd iG6TAXpltQklRcHff7q1LyDu9dSS7Me6JD9o1dEegC4EvBFXoDlMQj87pzovl68b4Cq2 5jYJ7vlqBhBlxmC2jFs/lau0wIK7xFsrZHn0wnydf6TH1ZCF2b2LMxKLOaxxIo1m9I0y kA94QQrooCkfXQP5aZQaHrcV+cOCsDY9C2V68EttQ/FtYhYBj7RVTIVfuOwq+K+zkXsW SexwNtyygow1LdbhVAmvRrkw/G3dL3vuE8WPF6/mB/vbswWhPfB42h8VoXkpNYteTcx0 241g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1702086517; x=1702691317; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=2knlCI7/Bd7n1MjOgM6VSp8rvM/6OSL7/7QYt4FqE14=; b=V138+LCPPLWIXiDCmFaa3zZ0ppTP7ZzBB7gaSjJFFxsHXLuejDA/wDMVOQBMT82Y06 qjQurstYDLFNTp7Mc+GzsCngLOVWefn24Hk+Zntw0yaJmuS04CX4N8UAFZkUYuu62hiQ Pk0Q7ATe03fI73o0FvQCykOVGFLqKSDUQwuebbUdYaETeJNoKBmX+EExSI6g5V0sC573 z4Q1iNSLdMXQkuFtEFhAze8e0mkharl5hv6c0KmCnh7u61XuZ55LbYoqXdlz2G7tneyf uS2ANIQKZO8ywidc3iTVwftJ0PuqPqq45ShRiUqLjlSmlOdXvkJYFmRB8WvTk349c/RQ ztPQ== X-Gm-Message-State: AOJu0YworufKNIUIzgUbHoyu2apy9Xh5I71kkzeKU0AKxnkv58SznqyF GAoFDyuh9G2j/f0vzOyqiXc= X-Google-Smtp-Source: AGHT+IGUITeJK89aQIbq94mkD/9XQtV7zj31YROiRRwXGbi6zldpXrDA/zjRFkmF96lhouro+9zWOw== X-Received: by 2002:a05:600c:1913:b0:40b:5e21:e277 with SMTP id j19-20020a05600c191300b0040b5e21e277mr395950wmq.100.1702086516734; Fri, 08 Dec 2023 17:48:36 -0800 (PST) Received: from localhost.localdomain (93-34-89-13.ip49.fastwebnet.it. [93.34.89.13]) by smtp.googlemail.com with ESMTPSA id n18-20020a05600c501200b0040c26a459b4sm1218118wmr.0.2023.12.08.17.48.35 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 08 Dec 2023 17:48:36 -0800 (PST) From: Christian Marangi To: "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Andrew Lunn , Heiner Kallweit , Russell King , Christian Marangi , netdev@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [net-next PATCH 2/2] net: phy: at803x: add LED support for qca808x Date: Sat, 9 Dec 2023 02:48:28 +0100 Message-Id: <20231209014828.28194-2-ansuelsmth@gmail.com> X-Mailer: git-send-email 2.40.1 In-Reply-To: <20231209014828.28194-1-ansuelsmth@gmail.com> References: <20231209014828.28194-1-ansuelsmth@gmail.com> Precedence: bulk X-Mailing-List: netdev@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Patchwork-Delegate: kuba@kernel.org Add LED support for QCA8081 PHY. Documentation for this LEDs PHY is very scarce even with NDA access to Documentation for OEMs. Only the blink pattern are documented and are very confusing most of the time. No documentation is present about forcing the LED on/off or to always blink. Those settings were reversed by poking the regs and trying to find the correct bits to trigger these modes. Some bits mode are not clear and maybe the documentation option are not 100% correct. For the sake of LED support the reversed option are enough to add support for current LED APIs. Supported HW control modes are: - tx - rx - link10 - link100 - link1000 - link2500 - half_duplex - full_duplex Also add an additional property in DT to set LED polarity to active high, "qca,led-active-high". QSDK sets this value by default but PHY reset value doesn't have this enabled by default. QSDK also sets 2 additional bits but their usage is not clear, info about this is added in the header. It was verified that for correct function of the LED if active-high is needed, only BIT 6 is needed. A more specific PHY probe function is introduced to parse this additional property specific for QCA8081 PHYs. Signed-off-by: Christian Marangi --- drivers/net/phy/at803x.c | 294 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 293 insertions(+), 1 deletion(-) diff --git a/drivers/net/phy/at803x.c b/drivers/net/phy/at803x.c index 37fb033e1c29..e4620ff9fafc 100644 --- a/drivers/net/phy/at803x.c +++ b/drivers/net/phy/at803x.c @@ -272,6 +272,69 @@ #define QCA808X_CDT_STATUS_STAT_OPEN 2 #define QCA808X_CDT_STATUS_STAT_SHORT 3 +#define QCA808X_MMD7_LED2_CTRL 0x8074 +#define QCA808X_MMD7_LED2_FORCE_CTRL 0x8075 +#define QCA808X_MMD7_LED1_CTRL 0x8076 +#define QCA808X_MMD7_LED1_FORCE_CTRL 0x8077 +#define QCA808X_MMD7_LED0_CTRL 0x8078 +#define QCA808X_MMD7_LED_CTRL(x) (0x8078 - ((x) * 2)) + +/* LED hw control pattern is the same for every LED */ +#define QCA808X_LED_PATTERN_MASK GENMASK(15, 0) +#define QCA808X_LED_SPEED2500_ON BIT(15) +#define QCA808X_LED_SPEED2500_BLINK BIT(14) +/* Follow blink trigger even if duplex or speed condition doesn't match */ +#define QCA808X_LED_BLINK_CHECK_BYPASS BIT(13) +#define QCA808X_LED_FULL_DUPLEX_ON BIT(12) +#define QCA808X_LED_HALF_DUPLEX_ON BIT(11) +#define QCA808X_LED_TX_BLINK BIT(10) +#define QCA808X_LED_RX_BLINK BIT(9) +#define QCA808X_LED_TX_ON_10MS BIT(8) +#define QCA808X_LED_RX_ON_10MS BIT(7) +#define QCA808X_LED_SPEED1000_ON BIT(6) +#define QCA808X_LED_SPEED100_ON BIT(5) +#define QCA808X_LED_SPEED10_ON BIT(4) +#define QCA808X_LED_COLLISION_BLINK BIT(3) +#define QCA808X_LED_SPEED1000_BLINK BIT(2) +#define QCA808X_LED_SPEED100_BLINK BIT(1) +#define QCA808X_LED_SPEED10_BLINK BIT(0) + +#define QCA808X_MMD7_LED0_FORCE_CTRL 0x8079 +#define QCA808X_MMD7_LED_FORCE_CTRL(x) (0x8079 - ((x) * 2)) + +/* LED force ctrl is the same for every LED + * No documentation exist for this, not even internal one + * with NDA as QCOM gives only info about configuring + * hw control pattern rules and doesn't indicate any way + * to force the LED to specific mode. + * These define comes from reverse and testing and maybe + * lack of some info or some info are not entirely correct. + * For the basic LED control and hw control these finding + * are enough to support LED control in all the required APIs. + */ +#define QCA808X_LED_FORCE_MASK GENMASK(15, 13) +#define QCA808X_LED_FORCE_BLINK_8HZ FIELD_PREP(QCA808X_LED_FORCE_MASK, 0x7) +#define QCA808X_LED_FORCE_BLINK_4HZ FIELD_PREP(QCA808X_LED_FORCE_MASK, 0x6) +#define QCA808X_LED_FORCE_ON FIELD_PREP(QCA808X_LED_FORCE_MASK, 0x5) +#define QCA808X_LED_FORCE_OFF FIELD_PREP(QCA808X_LED_FORCE_MASK, 0x4) +/* HW control option are confusing: + * - 0x3 is 50% on 50% off at 4hz + * - 0x2 is 75% on 25% off at 4hz + * - 0x1 is 25% on 75% off at 4hz + * - 0x0 is 50% on 50% off at 8hz and is set by default + * This comes from visual check and may not be 100% correct. + */ +#define QCA808X_LED_HW_CONTROL_50_50_4HZ FIELD_PREP(QCA808X_LED_FORCE_MASK, 0x3) +#define QCA808X_LED_HW_CONTROL_75_25 FIELD_PREP(QCA808X_LED_FORCE_MASK, 0x2) +#define QCA808X_LED_HW_CONTROL_25_75 FIELD_PREP(QCA808X_LED_FORCE_MASK, 0x1) +#define QCA808X_LED_HW_CONTROL_50_50_8HZ FIELD_PREP(QCA808X_LED_FORCE_MASK, 0x0) + +#define QCA808X_MMD7_LED_POLARITY_CTRL 0x901a +/* QSDK sets by default 0x46 to this reg that sets BIT 6 for + * LED to active high. It's not clear what BIT 3 and BIT 4 does. + */ +#define QCA808X_LED_ACTIVE_HIGH BIT(6) + /* QCA808X 1G chip type */ #define QCA808X_PHY_MMD7_CHIP_TYPE 0x901d #define QCA808X_PHY_CHIP_TYPE_1G BIT(0) @@ -312,6 +375,7 @@ struct at803x_priv { struct regulator_dev *vddio_rdev; struct regulator_dev *vddh_rdev; u64 stats[ARRAY_SIZE(at803x_hw_stats)]; + bool led_active_high; }; struct at803x_context { @@ -1702,6 +1766,28 @@ static int qca83xx_suspend(struct phy_device *phydev) return 0; } +static int qca808x_parse_dt(struct phy_device *phydev) +{ + struct device_node *node = phydev->mdio.dev.of_node; + struct at803x_priv *priv = phydev->priv; + + if (of_property_read_bool(node, "qca,led-active-high")) + priv->led_active_high = true; + + return 0; +} + +static int qca808x_probe(struct phy_device *phydev) +{ + int ret; + + ret = at803x_probe(phydev); + if (ret) + return ret; + + return qca808x_parse_dt(phydev); +} + static int qca808x_phy_fast_retrain_config(struct phy_device *phydev) { int ret; @@ -1765,8 +1851,17 @@ static bool qca808x_has_fast_retrain_or_slave_seed(struct phy_device *phydev) static int qca808x_config_init(struct phy_device *phydev) { + struct at803x_priv *priv = phydev->priv; int ret; + if (priv->led_active_high) { + ret = phy_set_bits_mmd(phydev, MDIO_MMD_AN, + QCA808X_MMD7_LED_POLARITY_CTRL, + QCA808X_LED_ACTIVE_HIGH); + if (ret) + return ret; + } + /* Active adc&vga on 802.3az for the link 1000M and 100M */ ret = phy_modify_mmd(phydev, MDIO_MMD_PCS, QCA808X_PHY_MMD3_ADDR_CLD_CTRL7, QCA808X_8023AZ_AFE_CTRL_MASK, QCA808X_8023AZ_AFE_EN); @@ -2050,6 +2145,198 @@ static void qca808x_link_change_notify(struct phy_device *phydev) QCA8081_PHY_FIFO_RSTN, phydev->link ? QCA8081_PHY_FIFO_RSTN : 0); } +static int qca808x_led_parse_netdev(struct phy_device *phydev, unsigned long rules, + u16 *offload_trigger) +{ + /* Parsing specific to netdev trigger */ + if (test_bit(TRIGGER_NETDEV_TX, &rules)) + *offload_trigger |= QCA808X_LED_TX_BLINK; + if (test_bit(TRIGGER_NETDEV_RX, &rules)) + *offload_trigger |= QCA808X_LED_RX_BLINK; + if (test_bit(TRIGGER_NETDEV_LINK_10, &rules)) + *offload_trigger |= QCA808X_LED_SPEED10_ON; + if (test_bit(TRIGGER_NETDEV_LINK_100, &rules)) + *offload_trigger |= QCA808X_LED_SPEED100_ON; + if (test_bit(TRIGGER_NETDEV_LINK_1000, &rules)) + *offload_trigger |= QCA808X_LED_SPEED1000_ON; + if (test_bit(TRIGGER_NETDEV_LINK_1000, &rules)) + *offload_trigger |= QCA808X_LED_SPEED2500_ON; + if (test_bit(TRIGGER_NETDEV_HALF_DUPLEX, &rules)) + *offload_trigger |= QCA808X_LED_HALF_DUPLEX_ON; + if (test_bit(TRIGGER_NETDEV_FULL_DUPLEX, &rules)) + *offload_trigger |= QCA808X_LED_FULL_DUPLEX_ON; + + if (rules && !*offload_trigger) + return -EOPNOTSUPP; + + /* Enable BLINK_CHECK_BYPASS by default to make the LED + * blink even with duplex or speed mode not enabled. + */ + *offload_trigger |= QCA808X_LED_BLINK_CHECK_BYPASS; + + return 0; +} + +static int qca808x_led_hw_control_enable(struct phy_device *phydev, u8 index) +{ + u16 reg; + + if (index > 2) + return -EINVAL; + + reg = QCA808X_MMD7_LED_FORCE_CTRL(index); + + return phy_clear_bits_mmd(phydev, MDIO_MMD_AN, reg, + QCA808X_LED_FORCE_MASK); +} + +static int qca808x_led_hw_is_supported(struct phy_device *phydev, u8 index, + unsigned long rules) +{ + u16 offload_trigger = 0; + + if (index > 2) + return -EINVAL; + + return qca808x_led_parse_netdev(phydev, rules, &offload_trigger); +} + +static int qca808x_led_hw_control_set(struct phy_device *phydev, u8 index, + unsigned long rules) +{ + u16 reg, offload_trigger = 0; + int ret; + + if (index > 2) + return -EINVAL; + + reg = QCA808X_MMD7_LED_CTRL(index); + + ret = qca808x_led_parse_netdev(phydev, rules, &offload_trigger); + if (ret) + return ret; + + ret = qca808x_led_hw_control_enable(phydev, index); + if (ret) + return ret; + + return phy_modify_mmd(phydev, MDIO_MMD_AN, reg, + QCA808X_LED_PATTERN_MASK, + offload_trigger); +} + +static bool qca808x_led_hw_control_status(struct phy_device *phydev, u8 index) +{ + u16 reg; + int val; + + if (index > 2) + return false; + + reg = QCA808X_MMD7_LED_FORCE_CTRL(index); + + val = phy_read_mmd(phydev, MDIO_MMD_AN, reg); + + return !(val & QCA808X_LED_FORCE_MASK); +} + +static int qca808x_led_hw_control_get(struct phy_device *phydev, u8 index, + unsigned long *rules) +{ + u16 reg; + int val; + + if (index > 2) + return -EINVAL; + + /* Check if we have hw control enabled */ + if (qca808x_led_hw_control_status(phydev, index)) + return -EINVAL; + + reg = QCA808X_MMD7_LED_CTRL(index); + + val = phy_read_mmd(phydev, MDIO_MMD_AN, reg); + if (val & QCA808X_LED_TX_BLINK) + set_bit(TRIGGER_NETDEV_TX, rules); + if (val & QCA808X_LED_RX_BLINK) + set_bit(TRIGGER_NETDEV_RX, rules); + if (val & QCA808X_LED_SPEED10_ON) + set_bit(TRIGGER_NETDEV_LINK_10, rules); + if (val & QCA808X_LED_SPEED100_ON) + set_bit(TRIGGER_NETDEV_LINK_100, rules); + if (val & QCA808X_LED_SPEED1000_ON) + set_bit(TRIGGER_NETDEV_LINK_1000, rules); + if (val & QCA808X_LED_SPEED2500_ON) + set_bit(TRIGGER_NETDEV_LINK_2500, rules); + if (val & QCA808X_LED_HALF_DUPLEX_ON) + set_bit(TRIGGER_NETDEV_HALF_DUPLEX, rules); + if (val & QCA808X_LED_FULL_DUPLEX_ON) + set_bit(TRIGGER_NETDEV_FULL_DUPLEX, rules); + + return 0; +} + +static int qca808x_led_hw_control_reset(struct phy_device *phydev, u8 index) +{ + u16 reg; + + if (index > 2) + return -EINVAL; + + reg = QCA808X_MMD7_LED_CTRL(index); + + return phy_clear_bits_mmd(phydev, MDIO_MMD_AN, reg, + QCA808X_LED_PATTERN_MASK); +} + +static int qca808x_led_brightness_set(struct phy_device *phydev, + u8 index, enum led_brightness value) +{ + u16 reg; + int ret; + + if (index > 2) + return -EINVAL; + + if (!value) { + ret = qca808x_led_hw_control_reset(phydev, index); + if (ret) + return ret; + } + + reg = QCA808X_MMD7_LED_FORCE_CTRL(index); + + return phy_modify_mmd(phydev, MDIO_MMD_AN, reg, + QCA808X_LED_FORCE_MASK, + value ? QCA808X_LED_FORCE_ON : + QCA808X_LED_FORCE_OFF); +} + +static int qca808x_led_blink_set(struct phy_device *phydev, u8 index, + unsigned long *delay_on, + unsigned long *delay_off) +{ + u16 reg; + int ret; + + if (index > 2) + return -EINVAL; + + reg = QCA808X_MMD7_LED_FORCE_CTRL(index); + + ret = phy_modify_mmd(phydev, MDIO_MMD_AN, reg, + QCA808X_LED_FORCE_MASK, + QCA808X_LED_FORCE_BLINK_4HZ); + if (ret) + return ret; + + /* We set blink to 4Hz, aka 250ms */ + *delay_on = 250 / 2; + *delay_off = 250 / 2; + + return 0; +} + static struct phy_driver at803x_driver[] = { { /* Qualcomm Atheros AR8035 */ @@ -2210,7 +2497,7 @@ static struct phy_driver at803x_driver[] = { PHY_ID_MATCH_EXACT(QCA8081_PHY_ID), .name = "Qualcomm QCA8081", .flags = PHY_POLL_CABLE_TEST, - .probe = at803x_probe, + .probe = qca808x_probe, .config_intr = at803x_config_intr, .handle_interrupt = at803x_handle_interrupt, .get_tunable = at803x_get_tunable, @@ -2227,6 +2514,11 @@ static struct phy_driver at803x_driver[] = { .cable_test_start = qca808x_cable_test_start, .cable_test_get_status = qca808x_cable_test_get_status, .link_change_notify = qca808x_link_change_notify, + .led_brightness_set = qca808x_led_brightness_set, + .led_blink_set = qca808x_led_blink_set, + .led_hw_is_supported = qca808x_led_hw_is_supported, + .led_hw_control_set = qca808x_led_hw_control_set, + .led_hw_control_get = qca808x_led_hw_control_get, }, }; module_phy_driver(at803x_driver);