From: Christian Marangi <ansuelsmth@gmail.com>
To: Michal Kubiak <michal.kubiak@intel.com>
Cc: Andrew Lunn <andrew@lunn.ch>,
Florian Fainelli <f.fainelli@gmail.com>,
Vladimir Oltean <olteanv@gmail.com>,
"David S. Miller" <davem@davemloft.net>,
Eric Dumazet <edumazet@google.com>,
Jakub Kicinski <kuba@kernel.org>, Paolo Abeni <pabeni@redhat.com>,
Rob Herring <robh+dt@kernel.org>,
Krzysztof Kozlowski <krzysztof.kozlowski+dt@linaro.org>,
Heiner Kallweit <hkallweit1@gmail.com>,
Russell King <linux@armlinux.org.uk>,
Gregory Clement <gregory.clement@bootlin.com>,
Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>,
Andy Gross <agross@kernel.org>,
Bjorn Andersson <andersson@kernel.org>,
Konrad Dybcio <konrad.dybcio@linaro.org>,
John Crispin <john@phrozen.org>,
netdev@vger.kernel.org, devicetree@vger.kernel.org,
linux-kernel@vger.kernel.org,
linux-arm-kernel@lists.infradead.org,
linux-arm-msm@vger.kernel.org, Lee Jones <lee@kernel.org>,
linux-leds@vger.kernel.org
Subject: Re: [net-next PATCH v4 02/14] net: dsa: qca8k: add LEDs basic support
Date: Sat, 18 Mar 2023 19:54:03 +0100 [thread overview]
Message-ID: <64166129.1c0a0220.1cb2c.3308@mx.google.com> (raw)
In-Reply-To: <ZBSsBap/ThahJEt3@localhost.localdomain>
On Fri, Mar 17, 2023 at 07:05:57PM +0100, Michal Kubiak wrote:
> On Fri, Mar 17, 2023 at 03:01:28PM +0100, Christian Marangi wrote:
> > On Fri, Mar 17, 2023 at 12:24:23PM +0100, Michal Kubiak wrote:
> > > On Fri, Mar 17, 2023 at 03:31:13AM +0100, Christian Marangi wrote:
> > > > Add LEDs basic support for qca8k Switch Family by adding basic
> > > > brightness_set() support.
> > > >
> > > > Since these LEDs refelect port status, the default label is set to
> > > > ":port". DT binding should describe the color, function and number of
> > > > the leds using standard LEDs api.
> > > >
> > > > These LEDs supports only blocking variant of the brightness_set()
> > > > function since they can sleep during access of the switch leds to set
> > > > the brightness.
> > > >
> > > > While at it add to the qca8k header file each mode defined by the Switch
> > > > Documentation for future use.
> > > >
> > > > Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
> > >
> > > Hi Christian,
> > >
> > > Please find my comments inline.
> > >
> > > Thanks,
> > > Michal
> > >
> > > > ---
> > > > drivers/net/dsa/qca/Kconfig | 8 ++
> > > > drivers/net/dsa/qca/Makefile | 3 +
> > > > drivers/net/dsa/qca/qca8k-8xxx.c | 5 +
> > > > drivers/net/dsa/qca/qca8k-leds.c | 192 +++++++++++++++++++++++++++++++
> > > > drivers/net/dsa/qca/qca8k.h | 59 ++++++++++
> > > > drivers/net/dsa/qca/qca8k_leds.h | 16 +++
> > > > 6 files changed, 283 insertions(+)
> > > > create mode 100644 drivers/net/dsa/qca/qca8k-leds.c
> > > > create mode 100644 drivers/net/dsa/qca/qca8k_leds.h
> > > >
> > > > diff --git a/drivers/net/dsa/qca/Kconfig b/drivers/net/dsa/qca/Kconfig
> > > > index ba339747362c..7a86d6d6a246 100644
> > > > --- a/drivers/net/dsa/qca/Kconfig
> > > > +++ b/drivers/net/dsa/qca/Kconfig
> > > > @@ -15,3 +15,11 @@ config NET_DSA_QCA8K
> > > > help
> > > > This enables support for the Qualcomm Atheros QCA8K Ethernet
> > > > switch chips.
> > > > +
> > > > +config NET_DSA_QCA8K_LEDS_SUPPORT
> > > > + bool "Qualcomm Atheros QCA8K Ethernet switch family LEDs support"
> > > > + depends on NET_DSA_QCA8K
> > > > + depends on LEDS_CLASS
> > > > + help
> > > > + This enabled support for LEDs present on the Qualcomm Atheros
> > > > + QCA8K Ethernet switch chips.
> > > > diff --git a/drivers/net/dsa/qca/Makefile b/drivers/net/dsa/qca/Makefile
> > > > index 701f1d199e93..ce66b1984e5f 100644
> > > > --- a/drivers/net/dsa/qca/Makefile
> > > > +++ b/drivers/net/dsa/qca/Makefile
> > > > @@ -2,3 +2,6 @@
> > > > obj-$(CONFIG_NET_DSA_AR9331) += ar9331.o
> > > > obj-$(CONFIG_NET_DSA_QCA8K) += qca8k.o
> > > > qca8k-y += qca8k-common.o qca8k-8xxx.o
> > > > +ifdef CONFIG_NET_DSA_QCA8K_LEDS_SUPPORT
> > > > +qca8k-y += qca8k-leds.o
> > > > +endif
> > > > diff --git a/drivers/net/dsa/qca/qca8k-8xxx.c b/drivers/net/dsa/qca/qca8k-8xxx.c
> > > > index 8dfc5db84700..5decf6fe3832 100644
> > > > --- a/drivers/net/dsa/qca/qca8k-8xxx.c
> > > > +++ b/drivers/net/dsa/qca/qca8k-8xxx.c
> > > > @@ -22,6 +22,7 @@
> > > > #include <linux/dsa/tag_qca.h>
> > > >
> > > > #include "qca8k.h"
> > > > +#include "qca8k_leds.h"
> > > >
> > > > static void
> > > > qca8k_split_addr(u32 regaddr, u16 *r1, u16 *r2, u16 *page)
> > > > @@ -1727,6 +1728,10 @@ qca8k_setup(struct dsa_switch *ds)
> > > > if (ret)
> > > > return ret;
> > > >
> > > > + ret = qca8k_setup_led_ctrl(priv);
> > > > + if (ret)
> > > > + return ret;
> > > > +
> > > > qca8k_setup_pcs(priv, &priv->pcs_port_0, 0);
> > > > qca8k_setup_pcs(priv, &priv->pcs_port_6, 6);
> > > >
> > > > diff --git a/drivers/net/dsa/qca/qca8k-leds.c b/drivers/net/dsa/qca/qca8k-leds.c
> > > > new file mode 100644
> > > > index 000000000000..adbe7f6e2994
> > > > --- /dev/null
> > > > +++ b/drivers/net/dsa/qca/qca8k-leds.c
> > > > @@ -0,0 +1,192 @@
> > > > +// SPDX-License-Identifier: GPL-2.0
> > > > +#include <linux/regmap.h>
> > > > +#include <net/dsa.h>
> > > > +
> > > > +#include "qca8k.h"
> > > > +#include "qca8k_leds.h"
> > > > +
> > > > +static int
> > > > +qca8k_get_enable_led_reg(int port_num, int led_num, struct qca8k_led_pattern_en *reg_info)
> > > > +{
> > > > + switch (port_num) {
> > > > + case 0:
> > > > + reg_info->reg = QCA8K_LED_CTRL_REG(led_num);
> > > > + reg_info->shift = QCA8K_LED_PHY0123_CONTROL_RULE_SHIFT;
> > > > + break;
> > > > + case 1:
> > > > + case 2:
> > > > + case 3:
> > > > + /* Port 123 are controlled on a different reg */
> > > > + reg_info->reg = QCA8K_LED_CTRL_REG(3);
> > > > + reg_info->shift = QCA8K_LED_PHY123_PATTERN_EN_SHIFT(port_num, led_num);
> > > > + break;
> > > > + case 4:
> > > > + reg_info->reg = QCA8K_LED_CTRL_REG(led_num);
> > > > + reg_info->shift = QCA8K_LED_PHY4_CONTROL_RULE_SHIFT;
> > > > + break;
> > > > + default:
> > > > + return -EINVAL;
> > > > + }
> > > > +
> > > > + return 0;
> > > > +}
> > > > +
> > > > +static int
> > > > +qca8k_led_brightness_set(struct qca8k_led *led,
> > > > + enum led_brightness brightness)
> > > > +{
> > > > + struct qca8k_led_pattern_en reg_info;
> > > > + struct qca8k_priv *priv = led->priv;
> > > > + u32 mask, val = QCA8K_LED_ALWAYS_OFF;
> > >
> > > Nitpick: RCT
> > >
> > > > +
> > > > + qca8k_get_enable_led_reg(led->port_num, led->led_num, ®_info);
> > > > +
> > > > + if (brightness)
> > > > + val = QCA8K_LED_ALWAYS_ON;
> > > > +
> > > > + if (led->port_num == 0 || led->port_num == 4) {
> > > > + mask = QCA8K_LED_PATTERN_EN_MASK;
> > > > + val <<= QCA8K_LED_PATTERN_EN_SHIFT;
> > > > + } else {
> > > > + mask = QCA8K_LED_PHY123_PATTERN_EN_MASK;
> > > > + }
> > > > +
> > > > + return regmap_update_bits(priv->regmap, reg_info.reg,
> > > > + mask << reg_info.shift,
> > > > + val << reg_info.shift);
> > > > +}
> > > > +
> > > > +static int
> > > > +qca8k_cled_brightness_set_blocking(struct led_classdev *ldev,
> > > > + enum led_brightness brightness)
> > > > +{
> > > > + struct qca8k_led *led = container_of(ldev, struct qca8k_led, cdev);
> > > > +
> > > > + return qca8k_led_brightness_set(led, brightness);
> > > > +}
> > > > +
> > > > +static enum led_brightness
> > > > +qca8k_led_brightness_get(struct qca8k_led *led)
> > > > +{
> > > > + struct qca8k_led_pattern_en reg_info;
> > > > + struct qca8k_priv *priv = led->priv;
> > > > + u32 val;
> > > > + int ret;
> > > > +
> > > > + qca8k_get_enable_led_reg(led->port_num, led->led_num, ®_info);
> > > > +
> > > > + ret = regmap_read(priv->regmap, reg_info.reg, &val);
> > > > + if (ret)
> > > > + return 0;
> > > > +
> > > > + val >>= reg_info.shift;
> > > > +
> > > > + if (led->port_num == 0 || led->port_num == 4) {
> > > > + val &= QCA8K_LED_PATTERN_EN_MASK;
> > > > + val >>= QCA8K_LED_PATTERN_EN_SHIFT;
> > > > + } else {
> > > > + val &= QCA8K_LED_PHY123_PATTERN_EN_MASK;
> > > > + }
> > > > +
> > > > + /* Assume brightness ON only when the LED is set to always ON */
> > > > + return val == QCA8K_LED_ALWAYS_ON;
> > > > +}
> > > > +
> > > > +static int
> > > > +qca8k_parse_port_leds(struct qca8k_priv *priv, struct fwnode_handle *port, int port_num)
> > > > +{
> > > > + struct fwnode_handle *led = NULL, *leds = NULL;
> > > > + struct led_init_data init_data = { };
> > > > + enum led_default_state state;
> > > > + struct qca8k_led *port_led;
> > > > + int led_num, port_index;
> > > > + int ret;
> > > > +
> > > > + leds = fwnode_get_named_child_node(port, "leds");
> > > > + if (!leds) {
> > > > + dev_dbg(priv->dev, "No Leds node specified in device tree for port %d!\n",
> > > > + port_num);
> > > > + return 0;
> > > > + }
> > > > +
> > > > + fwnode_for_each_child_node(leds, led) {
> > > > + /* Reg represent the led number of the port.
> > > > + * Each port can have at least 3 leds attached
> > > > + * Commonly:
> > > > + * 1. is gigabit led
> > > > + * 2. is mbit led
> > > > + * 3. additional status led
> > > > + */
> > > > + if (fwnode_property_read_u32(led, "reg", &led_num))
> > > > + continue;
> > > > +
> > > > + if (led_num >= QCA8K_LED_PORT_COUNT) {
> > > > + dev_warn(priv->dev, "Invalid LED reg defined %d", port_num);
> > > > + continue;
> > > > + }
> > >
> > > In the comment above you say "each port can have AT LEAST 3 leds".
> > > However, now it seems that if the port has more than 3 leds, all the
> > > remaining leds are not initialized.
> > > Is this intentional? If so, maybe it is worth describing in the comment
> > > that for ports with more than 3 leds, only the first 3 leds are
> > > initialized?
> > >
> > > According to the code it looks like the port can have up to 3 leds.
> > >
> >
> > Think I should rework the comments and make them more direct/simple.
> >
> > qca8k switch have a max of 5 port.
> >
> > each port CAN have a max of 3 leds connected.
> >
> > It's really a limitation of pin on the switch chip and hw regs so the
> > situation can't happen.
>
> OK, so it looks like a misunderstanding.
> I interpreted the sentence:
> "each port can have AT LEAST 3 leds"
> as
> "each port can a MIN of 3 leds connected".
>
> Most likely it is just a typo and it is a matter of changing "at
> least" to "at most" in the comment :-).
>
Yep just that. Thanks a lot for poiting this out.
> >
> > > > +
> > > > + port_index = 3 * port_num + led_num;
> > >
> > > Can QCA8K_LED_PORT_COUNT be used instead of "3"? I guess it is the number
> > > of LEDs per port.
> > >
> >
> > This variable it's really to make it easier to reference the led in the
> > priv struct. If asked I can rework this to an array of array (one per
> > port and each port out of 3 possigle LED).
>
> I wasn't probably clear. I just wanted to ask if you can use the constant
> "QCA8K_LED_PORT_COUNT" instead of a raw number "3".
>
> BTW, I agree that "array of array" option seems too complex solution for
> a simple thing :-).
>
Decided to move the index calculation in the header.
> >
> > > > +
> > > > + port_led = &priv->ports_led[port_index];
> > >
> > > Also, the name of the "port_index" variable seems confusing to me. It is
> > > not an index of the port, but rather a unique index of the LED across
> > > all ports, right?
> > >
> >
> > As said above, they are unique index that comes from port and LED of the
> > port. Really something to represent the code easier internally.
>
> Got it. I was just sharing my impression of the name "port_index" itself.
> Maybe, "led_index" would be better because it actually indexes leds, not
> ports?
>
Funny enough I just started working on this and I just decided the same
name and then I read your suggestion. Anyway yep correct port_index
was very confusing.
> >
> > > > + port_led->port_num = port_num;
> > > > + port_led->led_num = led_num;
> > > > + port_led->priv = priv;
> > > > +
> > > > + state = led_init_default_state_get(led);
> > > > + switch (state) {
> > > > + case LEDS_DEFSTATE_ON:
> > > > + port_led->cdev.brightness = 1;
> > > > + qca8k_led_brightness_set(port_led, 1);
> > > > + break;
> > > > + case LEDS_DEFSTATE_KEEP:
> > > > + port_led->cdev.brightness =
> > > > + qca8k_led_brightness_get(port_led);
> > > > + break;
> > > > + default:
> > > > + port_led->cdev.brightness = 0;
> > > > + qca8k_led_brightness_set(port_led, 0);
> > > > + }
> > > > +
> > > > + port_led->cdev.max_brightness = 1;
> > > > + port_led->cdev.brightness_set_blocking = qca8k_cled_brightness_set_blocking;
> > > > + init_data.default_label = ":port";
> > > > + init_data.devicename = "qca8k";
> > > > + init_data.fwnode = led;
> > > > +
> > > > + ret = devm_led_classdev_register_ext(priv->dev, &port_led->cdev, &init_data);
> > > > + if (ret)
> > > > + dev_warn(priv->dev, "Failed to int led");
> > >
> > > Typo: "init".
> > > How about adding an index of the LED that could not be initialized?
> > >
> >
> > Ok will add more info in the port and led that failed to init.
>
> Thanks, but it's just my suggestion.
>
> >
> > > > + }
> > > > +
> > > > + return 0;
> > > > +}
> > > > +
> > > > +int
> > > > +qca8k_setup_led_ctrl(struct qca8k_priv *priv)
> > > > +{
> > > > + struct fwnode_handle *ports, *port;
> > > > + int port_num;
> > > > + int ret;
> > > > +
> > > > + ports = device_get_named_child_node(priv->dev, "ports");
> > > > + if (!ports) {
> > > > + dev_info(priv->dev, "No ports node specified in device tree!\n");
> > > > + return 0;
> > > > + }
> > > > +
> > > > + fwnode_for_each_child_node(ports, port) {
> > > > + if (fwnode_property_read_u32(port, "reg", &port_num))
> > > > + continue;
> > > > +
> > > > + /* Each port can have at least 3 different leds attached.
>
> "at least" -> "at most"
>
> > > > + * Switch port starts from 0 to 6, but port 0 and 6 are CPU
> > > > + * port. The port index needs to be decreased by one to identify
> > > > + * the correct port for LED setup.
> > > > + */
> > >
> > > Again, are there really "at least 3 different leds" per port?
> > > It's confusing a little bit, because QCA8K_LED_PORT_COUNT == 3, so I
> > > would say it cannot have more than 3.
> > >
> > > > + ret = qca8k_parse_port_leds(priv, port, qca8k_port_to_phy(port_num));
> > >
> > > As I checked, the function "qca8k_port_to_phy()" can return all 0xFFs
> > > for port_num == 0. Then, this value is implicitly casted to int (as the
> > > last parameter of "qca8k_parse_port_leds()"). Internally, in
> > > "qca8k_parse_port_leds()" this parameter can be used to do some
> > > computing - that looks dangerous.
> > > In summary, I think a special check for CPU port_num == 0 should be
> > > added.
> > > (I guess the LED configuration i only makes sense for non-CPU ports? It
> > > seems you want to configure up to 15 LEDs in total for 5 ports).
> > >
> >
> > IMHO for this, we can ignore handling this corner case. The hw doesn't
> > supports leds for port0 and port6 (the 2 CPU port) so the case won't
> > ever apply. But if asked I can add the case, not that it will cause any
> > problem in how the regs and shift are referenced in the code.
>
> OK, got it. So, as I understand, the previous call in this loop
> "fwnode_property_read_u32()" will never return port_num == 0 (or we fall
> into "continue")?
>
On a second check I got what you mean with this and I added a check to
skip LED init for port 0 and port 6. Thanks!
> >
> > > > + if (ret)
> > > > + return ret;
> > > > + }
> > > > +
> > > > + return 0;
> > > > +}
> > > > diff --git a/drivers/net/dsa/qca/qca8k.h b/drivers/net/dsa/qca/qca8k.h
> > > > index 4e48e4dd8b0f..3c3c072fa9c2 100644
> > > > --- a/drivers/net/dsa/qca/qca8k.h
> > > > +++ b/drivers/net/dsa/qca/qca8k.h
> > > > @@ -11,6 +11,7 @@
> > > > #include <linux/delay.h>
> > > > #include <linux/regmap.h>
> > > > #include <linux/gpio.h>
> > > > +#include <linux/leds.h>
> > > > #include <linux/dsa/tag_qca.h>
> > > >
> > > > #define QCA8K_ETHERNET_MDIO_PRIORITY 7
> > > > @@ -85,6 +86,50 @@
> > > > #define QCA8K_MDIO_MASTER_DATA(x) FIELD_PREP(QCA8K_MDIO_MASTER_DATA_MASK, x)
> > > > #define QCA8K_MDIO_MASTER_MAX_PORTS 5
> > > > #define QCA8K_MDIO_MASTER_MAX_REG 32
> > > > +
> > > > +/* LED control register */
> > > > +#define QCA8K_LED_COUNT 15
> > > > +#define QCA8K_LED_PORT_COUNT 3
> > > > +#define QCA8K_LED_RULE_COUNT 6
> > > > +#define QCA8K_LED_RULE_MAX 11
> > > > +
> > > > +#define QCA8K_LED_PHY123_PATTERN_EN_SHIFT(_phy, _led) ((((_phy) - 1) * 6) + 8 + (2 * (_led)))
> > > > +#define QCA8K_LED_PHY123_PATTERN_EN_MASK GENMASK(1, 0)
> > > > +
> > > > +#define QCA8K_LED_PHY0123_CONTROL_RULE_SHIFT 0
> > > > +#define QCA8K_LED_PHY4_CONTROL_RULE_SHIFT 16
> > > > +
> > > > +#define QCA8K_LED_CTRL_REG(_i) (0x050 + (_i) * 4)
> > > > +#define QCA8K_LED_CTRL0_REG 0x50
> > > > +#define QCA8K_LED_CTRL1_REG 0x54
> > > > +#define QCA8K_LED_CTRL2_REG 0x58
> > > > +#define QCA8K_LED_CTRL3_REG 0x5C
> > > > +#define QCA8K_LED_CTRL_SHIFT(_i) (((_i) % 2) * 16)
> > > > +#define QCA8K_LED_CTRL_MASK GENMASK(15, 0)
> > > > +#define QCA8K_LED_RULE_MASK GENMASK(13, 0)
> > > > +#define QCA8K_LED_BLINK_FREQ_MASK GENMASK(1, 0)
> > > > +#define QCA8K_LED_BLINK_FREQ_SHITF 0
> > > > +#define QCA8K_LED_BLINK_2HZ 0
> > > > +#define QCA8K_LED_BLINK_4HZ 1
> > > > +#define QCA8K_LED_BLINK_8HZ 2
> > > > +#define QCA8K_LED_BLINK_AUTO 3
> > > > +#define QCA8K_LED_LINKUP_OVER_MASK BIT(2)
> > > > +#define QCA8K_LED_TX_BLINK_MASK BIT(4)
> > > > +#define QCA8K_LED_RX_BLINK_MASK BIT(5)
> > > > +#define QCA8K_LED_COL_BLINK_MASK BIT(7)
> > > > +#define QCA8K_LED_LINK_10M_EN_MASK BIT(8)
> > > > +#define QCA8K_LED_LINK_100M_EN_MASK BIT(9)
> > > > +#define QCA8K_LED_LINK_1000M_EN_MASK BIT(10)
> > > > +#define QCA8K_LED_POWER_ON_LIGHT_MASK BIT(11)
> > > > +#define QCA8K_LED_HALF_DUPLEX_MASK BIT(12)
> > > > +#define QCA8K_LED_FULL_DUPLEX_MASK BIT(13)
> > > > +#define QCA8K_LED_PATTERN_EN_MASK GENMASK(15, 14)
> > > > +#define QCA8K_LED_PATTERN_EN_SHIFT 14
> > > > +#define QCA8K_LED_ALWAYS_OFF 0
> > > > +#define QCA8K_LED_ALWAYS_BLINK_4HZ 1
> > > > +#define QCA8K_LED_ALWAYS_ON 2
> > > > +#define QCA8K_LED_RULE_CONTROLLED 3
> > > > +
> > > > #define QCA8K_GOL_MAC_ADDR0 0x60
> > > > #define QCA8K_GOL_MAC_ADDR1 0x64
> > > > #define QCA8K_MAX_FRAME_SIZE 0x78
> > > > @@ -383,6 +428,19 @@ struct qca8k_pcs {
> > > > int port;
> > > > };
> > > >
> > > > +struct qca8k_led_pattern_en {
> > > > + u32 reg;
> > > > + u8 shift;
> > > > +};
> > > > +
> > > > +struct qca8k_led {
> > > > + u8 port_num;
> > > > + u8 led_num;
> > > > + u16 old_rule;
> > > > + struct qca8k_priv *priv;
> > > > + struct led_classdev cdev;
> > > > +};
> > > > +
> > > > struct qca8k_priv {
> > > > u8 switch_id;
> > > > u8 switch_revision;
> > > > @@ -407,6 +465,7 @@ struct qca8k_priv {
> > > > struct qca8k_pcs pcs_port_0;
> > > > struct qca8k_pcs pcs_port_6;
> > > > const struct qca8k_match_data *info;
> > > > + struct qca8k_led ports_led[QCA8K_LED_COUNT];
> > > > };
> > > >
> > > > struct qca8k_mib_desc {
> > > > diff --git a/drivers/net/dsa/qca/qca8k_leds.h b/drivers/net/dsa/qca/qca8k_leds.h
> > > > new file mode 100644
> > > > index 000000000000..ab367f05b173
> > > > --- /dev/null
> > > > +++ b/drivers/net/dsa/qca/qca8k_leds.h
> > > > @@ -0,0 +1,16 @@
> > > > +/* SPDX-License-Identifier: GPL-2.0-only */
> > > > +
> > > > +#ifndef __QCA8K_LEDS_H
> > > > +#define __QCA8K_LEDS_H
> > > > +
> > > > +/* Leds Support function */
> > > > +#ifdef CONFIG_NET_DSA_QCA8K_LEDS_SUPPORT
> > > > +int qca8k_setup_led_ctrl(struct qca8k_priv *priv);
> > > > +#else
> > > > +static inline int qca8k_setup_led_ctrl(struct qca8k_priv *priv)
> > > > +{
> > > > + return 0;
> > > > +}
> > > > +#endif
> > > > +
> > > > +#endif /* __QCA8K_LEDS_H */
> > > > --
> > > > 2.39.2
> > > >
> >
> > --
> > Ansuel
>
>
> Thanks,
> Michal
--
Ansuel
WARNING: multiple messages have this Message-ID (diff)
From: Christian Marangi <ansuelsmth@gmail.com>
To: Michal Kubiak <michal.kubiak@intel.com>
Cc: Andrew Lunn <andrew@lunn.ch>,
Florian Fainelli <f.fainelli@gmail.com>,
Vladimir Oltean <olteanv@gmail.com>,
"David S. Miller" <davem@davemloft.net>,
Eric Dumazet <edumazet@google.com>,
Jakub Kicinski <kuba@kernel.org>, Paolo Abeni <pabeni@redhat.com>,
Rob Herring <robh+dt@kernel.org>,
Krzysztof Kozlowski <krzysztof.kozlowski+dt@linaro.org>,
Heiner Kallweit <hkallweit1@gmail.com>,
Russell King <linux@armlinux.org.uk>,
Gregory Clement <gregory.clement@bootlin.com>,
Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>,
Andy Gross <agross@kernel.org>,
Bjorn Andersson <andersson@kernel.org>,
Konrad Dybcio <konrad.dybcio@linaro.org>,
John Crispin <john@phrozen.org>,
netdev@vger.kernel.org, devicetree@vger.kernel.org,
linux-kernel@vger.kernel.org,
linux-arm-kernel@lists.infradead.org,
linux-arm-msm@vger.kernel.org, Lee Jones <lee@kernel.org>,
linux-leds@vger.kernel.org
Subject: Re: [net-next PATCH v4 02/14] net: dsa: qca8k: add LEDs basic support
Date: Sat, 18 Mar 2023 19:54:03 +0100 [thread overview]
Message-ID: <64166129.1c0a0220.1cb2c.3308@mx.google.com> (raw)
In-Reply-To: <ZBSsBap/ThahJEt3@localhost.localdomain>
On Fri, Mar 17, 2023 at 07:05:57PM +0100, Michal Kubiak wrote:
> On Fri, Mar 17, 2023 at 03:01:28PM +0100, Christian Marangi wrote:
> > On Fri, Mar 17, 2023 at 12:24:23PM +0100, Michal Kubiak wrote:
> > > On Fri, Mar 17, 2023 at 03:31:13AM +0100, Christian Marangi wrote:
> > > > Add LEDs basic support for qca8k Switch Family by adding basic
> > > > brightness_set() support.
> > > >
> > > > Since these LEDs refelect port status, the default label is set to
> > > > ":port". DT binding should describe the color, function and number of
> > > > the leds using standard LEDs api.
> > > >
> > > > These LEDs supports only blocking variant of the brightness_set()
> > > > function since they can sleep during access of the switch leds to set
> > > > the brightness.
> > > >
> > > > While at it add to the qca8k header file each mode defined by the Switch
> > > > Documentation for future use.
> > > >
> > > > Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
> > >
> > > Hi Christian,
> > >
> > > Please find my comments inline.
> > >
> > > Thanks,
> > > Michal
> > >
> > > > ---
> > > > drivers/net/dsa/qca/Kconfig | 8 ++
> > > > drivers/net/dsa/qca/Makefile | 3 +
> > > > drivers/net/dsa/qca/qca8k-8xxx.c | 5 +
> > > > drivers/net/dsa/qca/qca8k-leds.c | 192 +++++++++++++++++++++++++++++++
> > > > drivers/net/dsa/qca/qca8k.h | 59 ++++++++++
> > > > drivers/net/dsa/qca/qca8k_leds.h | 16 +++
> > > > 6 files changed, 283 insertions(+)
> > > > create mode 100644 drivers/net/dsa/qca/qca8k-leds.c
> > > > create mode 100644 drivers/net/dsa/qca/qca8k_leds.h
> > > >
> > > > diff --git a/drivers/net/dsa/qca/Kconfig b/drivers/net/dsa/qca/Kconfig
> > > > index ba339747362c..7a86d6d6a246 100644
> > > > --- a/drivers/net/dsa/qca/Kconfig
> > > > +++ b/drivers/net/dsa/qca/Kconfig
> > > > @@ -15,3 +15,11 @@ config NET_DSA_QCA8K
> > > > help
> > > > This enables support for the Qualcomm Atheros QCA8K Ethernet
> > > > switch chips.
> > > > +
> > > > +config NET_DSA_QCA8K_LEDS_SUPPORT
> > > > + bool "Qualcomm Atheros QCA8K Ethernet switch family LEDs support"
> > > > + depends on NET_DSA_QCA8K
> > > > + depends on LEDS_CLASS
> > > > + help
> > > > + This enabled support for LEDs present on the Qualcomm Atheros
> > > > + QCA8K Ethernet switch chips.
> > > > diff --git a/drivers/net/dsa/qca/Makefile b/drivers/net/dsa/qca/Makefile
> > > > index 701f1d199e93..ce66b1984e5f 100644
> > > > --- a/drivers/net/dsa/qca/Makefile
> > > > +++ b/drivers/net/dsa/qca/Makefile
> > > > @@ -2,3 +2,6 @@
> > > > obj-$(CONFIG_NET_DSA_AR9331) += ar9331.o
> > > > obj-$(CONFIG_NET_DSA_QCA8K) += qca8k.o
> > > > qca8k-y += qca8k-common.o qca8k-8xxx.o
> > > > +ifdef CONFIG_NET_DSA_QCA8K_LEDS_SUPPORT
> > > > +qca8k-y += qca8k-leds.o
> > > > +endif
> > > > diff --git a/drivers/net/dsa/qca/qca8k-8xxx.c b/drivers/net/dsa/qca/qca8k-8xxx.c
> > > > index 8dfc5db84700..5decf6fe3832 100644
> > > > --- a/drivers/net/dsa/qca/qca8k-8xxx.c
> > > > +++ b/drivers/net/dsa/qca/qca8k-8xxx.c
> > > > @@ -22,6 +22,7 @@
> > > > #include <linux/dsa/tag_qca.h>
> > > >
> > > > #include "qca8k.h"
> > > > +#include "qca8k_leds.h"
> > > >
> > > > static void
> > > > qca8k_split_addr(u32 regaddr, u16 *r1, u16 *r2, u16 *page)
> > > > @@ -1727,6 +1728,10 @@ qca8k_setup(struct dsa_switch *ds)
> > > > if (ret)
> > > > return ret;
> > > >
> > > > + ret = qca8k_setup_led_ctrl(priv);
> > > > + if (ret)
> > > > + return ret;
> > > > +
> > > > qca8k_setup_pcs(priv, &priv->pcs_port_0, 0);
> > > > qca8k_setup_pcs(priv, &priv->pcs_port_6, 6);
> > > >
> > > > diff --git a/drivers/net/dsa/qca/qca8k-leds.c b/drivers/net/dsa/qca/qca8k-leds.c
> > > > new file mode 100644
> > > > index 000000000000..adbe7f6e2994
> > > > --- /dev/null
> > > > +++ b/drivers/net/dsa/qca/qca8k-leds.c
> > > > @@ -0,0 +1,192 @@
> > > > +// SPDX-License-Identifier: GPL-2.0
> > > > +#include <linux/regmap.h>
> > > > +#include <net/dsa.h>
> > > > +
> > > > +#include "qca8k.h"
> > > > +#include "qca8k_leds.h"
> > > > +
> > > > +static int
> > > > +qca8k_get_enable_led_reg(int port_num, int led_num, struct qca8k_led_pattern_en *reg_info)
> > > > +{
> > > > + switch (port_num) {
> > > > + case 0:
> > > > + reg_info->reg = QCA8K_LED_CTRL_REG(led_num);
> > > > + reg_info->shift = QCA8K_LED_PHY0123_CONTROL_RULE_SHIFT;
> > > > + break;
> > > > + case 1:
> > > > + case 2:
> > > > + case 3:
> > > > + /* Port 123 are controlled on a different reg */
> > > > + reg_info->reg = QCA8K_LED_CTRL_REG(3);
> > > > + reg_info->shift = QCA8K_LED_PHY123_PATTERN_EN_SHIFT(port_num, led_num);
> > > > + break;
> > > > + case 4:
> > > > + reg_info->reg = QCA8K_LED_CTRL_REG(led_num);
> > > > + reg_info->shift = QCA8K_LED_PHY4_CONTROL_RULE_SHIFT;
> > > > + break;
> > > > + default:
> > > > + return -EINVAL;
> > > > + }
> > > > +
> > > > + return 0;
> > > > +}
> > > > +
> > > > +static int
> > > > +qca8k_led_brightness_set(struct qca8k_led *led,
> > > > + enum led_brightness brightness)
> > > > +{
> > > > + struct qca8k_led_pattern_en reg_info;
> > > > + struct qca8k_priv *priv = led->priv;
> > > > + u32 mask, val = QCA8K_LED_ALWAYS_OFF;
> > >
> > > Nitpick: RCT
> > >
> > > > +
> > > > + qca8k_get_enable_led_reg(led->port_num, led->led_num, ®_info);
> > > > +
> > > > + if (brightness)
> > > > + val = QCA8K_LED_ALWAYS_ON;
> > > > +
> > > > + if (led->port_num == 0 || led->port_num == 4) {
> > > > + mask = QCA8K_LED_PATTERN_EN_MASK;
> > > > + val <<= QCA8K_LED_PATTERN_EN_SHIFT;
> > > > + } else {
> > > > + mask = QCA8K_LED_PHY123_PATTERN_EN_MASK;
> > > > + }
> > > > +
> > > > + return regmap_update_bits(priv->regmap, reg_info.reg,
> > > > + mask << reg_info.shift,
> > > > + val << reg_info.shift);
> > > > +}
> > > > +
> > > > +static int
> > > > +qca8k_cled_brightness_set_blocking(struct led_classdev *ldev,
> > > > + enum led_brightness brightness)
> > > > +{
> > > > + struct qca8k_led *led = container_of(ldev, struct qca8k_led, cdev);
> > > > +
> > > > + return qca8k_led_brightness_set(led, brightness);
> > > > +}
> > > > +
> > > > +static enum led_brightness
> > > > +qca8k_led_brightness_get(struct qca8k_led *led)
> > > > +{
> > > > + struct qca8k_led_pattern_en reg_info;
> > > > + struct qca8k_priv *priv = led->priv;
> > > > + u32 val;
> > > > + int ret;
> > > > +
> > > > + qca8k_get_enable_led_reg(led->port_num, led->led_num, ®_info);
> > > > +
> > > > + ret = regmap_read(priv->regmap, reg_info.reg, &val);
> > > > + if (ret)
> > > > + return 0;
> > > > +
> > > > + val >>= reg_info.shift;
> > > > +
> > > > + if (led->port_num == 0 || led->port_num == 4) {
> > > > + val &= QCA8K_LED_PATTERN_EN_MASK;
> > > > + val >>= QCA8K_LED_PATTERN_EN_SHIFT;
> > > > + } else {
> > > > + val &= QCA8K_LED_PHY123_PATTERN_EN_MASK;
> > > > + }
> > > > +
> > > > + /* Assume brightness ON only when the LED is set to always ON */
> > > > + return val == QCA8K_LED_ALWAYS_ON;
> > > > +}
> > > > +
> > > > +static int
> > > > +qca8k_parse_port_leds(struct qca8k_priv *priv, struct fwnode_handle *port, int port_num)
> > > > +{
> > > > + struct fwnode_handle *led = NULL, *leds = NULL;
> > > > + struct led_init_data init_data = { };
> > > > + enum led_default_state state;
> > > > + struct qca8k_led *port_led;
> > > > + int led_num, port_index;
> > > > + int ret;
> > > > +
> > > > + leds = fwnode_get_named_child_node(port, "leds");
> > > > + if (!leds) {
> > > > + dev_dbg(priv->dev, "No Leds node specified in device tree for port %d!\n",
> > > > + port_num);
> > > > + return 0;
> > > > + }
> > > > +
> > > > + fwnode_for_each_child_node(leds, led) {
> > > > + /* Reg represent the led number of the port.
> > > > + * Each port can have at least 3 leds attached
> > > > + * Commonly:
> > > > + * 1. is gigabit led
> > > > + * 2. is mbit led
> > > > + * 3. additional status led
> > > > + */
> > > > + if (fwnode_property_read_u32(led, "reg", &led_num))
> > > > + continue;
> > > > +
> > > > + if (led_num >= QCA8K_LED_PORT_COUNT) {
> > > > + dev_warn(priv->dev, "Invalid LED reg defined %d", port_num);
> > > > + continue;
> > > > + }
> > >
> > > In the comment above you say "each port can have AT LEAST 3 leds".
> > > However, now it seems that if the port has more than 3 leds, all the
> > > remaining leds are not initialized.
> > > Is this intentional? If so, maybe it is worth describing in the comment
> > > that for ports with more than 3 leds, only the first 3 leds are
> > > initialized?
> > >
> > > According to the code it looks like the port can have up to 3 leds.
> > >
> >
> > Think I should rework the comments and make them more direct/simple.
> >
> > qca8k switch have a max of 5 port.
> >
> > each port CAN have a max of 3 leds connected.
> >
> > It's really a limitation of pin on the switch chip and hw regs so the
> > situation can't happen.
>
> OK, so it looks like a misunderstanding.
> I interpreted the sentence:
> "each port can have AT LEAST 3 leds"
> as
> "each port can a MIN of 3 leds connected".
>
> Most likely it is just a typo and it is a matter of changing "at
> least" to "at most" in the comment :-).
>
Yep just that. Thanks a lot for poiting this out.
> >
> > > > +
> > > > + port_index = 3 * port_num + led_num;
> > >
> > > Can QCA8K_LED_PORT_COUNT be used instead of "3"? I guess it is the number
> > > of LEDs per port.
> > >
> >
> > This variable it's really to make it easier to reference the led in the
> > priv struct. If asked I can rework this to an array of array (one per
> > port and each port out of 3 possigle LED).
>
> I wasn't probably clear. I just wanted to ask if you can use the constant
> "QCA8K_LED_PORT_COUNT" instead of a raw number "3".
>
> BTW, I agree that "array of array" option seems too complex solution for
> a simple thing :-).
>
Decided to move the index calculation in the header.
> >
> > > > +
> > > > + port_led = &priv->ports_led[port_index];
> > >
> > > Also, the name of the "port_index" variable seems confusing to me. It is
> > > not an index of the port, but rather a unique index of the LED across
> > > all ports, right?
> > >
> >
> > As said above, they are unique index that comes from port and LED of the
> > port. Really something to represent the code easier internally.
>
> Got it. I was just sharing my impression of the name "port_index" itself.
> Maybe, "led_index" would be better because it actually indexes leds, not
> ports?
>
Funny enough I just started working on this and I just decided the same
name and then I read your suggestion. Anyway yep correct port_index
was very confusing.
> >
> > > > + port_led->port_num = port_num;
> > > > + port_led->led_num = led_num;
> > > > + port_led->priv = priv;
> > > > +
> > > > + state = led_init_default_state_get(led);
> > > > + switch (state) {
> > > > + case LEDS_DEFSTATE_ON:
> > > > + port_led->cdev.brightness = 1;
> > > > + qca8k_led_brightness_set(port_led, 1);
> > > > + break;
> > > > + case LEDS_DEFSTATE_KEEP:
> > > > + port_led->cdev.brightness =
> > > > + qca8k_led_brightness_get(port_led);
> > > > + break;
> > > > + default:
> > > > + port_led->cdev.brightness = 0;
> > > > + qca8k_led_brightness_set(port_led, 0);
> > > > + }
> > > > +
> > > > + port_led->cdev.max_brightness = 1;
> > > > + port_led->cdev.brightness_set_blocking = qca8k_cled_brightness_set_blocking;
> > > > + init_data.default_label = ":port";
> > > > + init_data.devicename = "qca8k";
> > > > + init_data.fwnode = led;
> > > > +
> > > > + ret = devm_led_classdev_register_ext(priv->dev, &port_led->cdev, &init_data);
> > > > + if (ret)
> > > > + dev_warn(priv->dev, "Failed to int led");
> > >
> > > Typo: "init".
> > > How about adding an index of the LED that could not be initialized?
> > >
> >
> > Ok will add more info in the port and led that failed to init.
>
> Thanks, but it's just my suggestion.
>
> >
> > > > + }
> > > > +
> > > > + return 0;
> > > > +}
> > > > +
> > > > +int
> > > > +qca8k_setup_led_ctrl(struct qca8k_priv *priv)
> > > > +{
> > > > + struct fwnode_handle *ports, *port;
> > > > + int port_num;
> > > > + int ret;
> > > > +
> > > > + ports = device_get_named_child_node(priv->dev, "ports");
> > > > + if (!ports) {
> > > > + dev_info(priv->dev, "No ports node specified in device tree!\n");
> > > > + return 0;
> > > > + }
> > > > +
> > > > + fwnode_for_each_child_node(ports, port) {
> > > > + if (fwnode_property_read_u32(port, "reg", &port_num))
> > > > + continue;
> > > > +
> > > > + /* Each port can have at least 3 different leds attached.
>
> "at least" -> "at most"
>
> > > > + * Switch port starts from 0 to 6, but port 0 and 6 are CPU
> > > > + * port. The port index needs to be decreased by one to identify
> > > > + * the correct port for LED setup.
> > > > + */
> > >
> > > Again, are there really "at least 3 different leds" per port?
> > > It's confusing a little bit, because QCA8K_LED_PORT_COUNT == 3, so I
> > > would say it cannot have more than 3.
> > >
> > > > + ret = qca8k_parse_port_leds(priv, port, qca8k_port_to_phy(port_num));
> > >
> > > As I checked, the function "qca8k_port_to_phy()" can return all 0xFFs
> > > for port_num == 0. Then, this value is implicitly casted to int (as the
> > > last parameter of "qca8k_parse_port_leds()"). Internally, in
> > > "qca8k_parse_port_leds()" this parameter can be used to do some
> > > computing - that looks dangerous.
> > > In summary, I think a special check for CPU port_num == 0 should be
> > > added.
> > > (I guess the LED configuration i only makes sense for non-CPU ports? It
> > > seems you want to configure up to 15 LEDs in total for 5 ports).
> > >
> >
> > IMHO for this, we can ignore handling this corner case. The hw doesn't
> > supports leds for port0 and port6 (the 2 CPU port) so the case won't
> > ever apply. But if asked I can add the case, not that it will cause any
> > problem in how the regs and shift are referenced in the code.
>
> OK, got it. So, as I understand, the previous call in this loop
> "fwnode_property_read_u32()" will never return port_num == 0 (or we fall
> into "continue")?
>
On a second check I got what you mean with this and I added a check to
skip LED init for port 0 and port 6. Thanks!
> >
> > > > + if (ret)
> > > > + return ret;
> > > > + }
> > > > +
> > > > + return 0;
> > > > +}
> > > > diff --git a/drivers/net/dsa/qca/qca8k.h b/drivers/net/dsa/qca/qca8k.h
> > > > index 4e48e4dd8b0f..3c3c072fa9c2 100644
> > > > --- a/drivers/net/dsa/qca/qca8k.h
> > > > +++ b/drivers/net/dsa/qca/qca8k.h
> > > > @@ -11,6 +11,7 @@
> > > > #include <linux/delay.h>
> > > > #include <linux/regmap.h>
> > > > #include <linux/gpio.h>
> > > > +#include <linux/leds.h>
> > > > #include <linux/dsa/tag_qca.h>
> > > >
> > > > #define QCA8K_ETHERNET_MDIO_PRIORITY 7
> > > > @@ -85,6 +86,50 @@
> > > > #define QCA8K_MDIO_MASTER_DATA(x) FIELD_PREP(QCA8K_MDIO_MASTER_DATA_MASK, x)
> > > > #define QCA8K_MDIO_MASTER_MAX_PORTS 5
> > > > #define QCA8K_MDIO_MASTER_MAX_REG 32
> > > > +
> > > > +/* LED control register */
> > > > +#define QCA8K_LED_COUNT 15
> > > > +#define QCA8K_LED_PORT_COUNT 3
> > > > +#define QCA8K_LED_RULE_COUNT 6
> > > > +#define QCA8K_LED_RULE_MAX 11
> > > > +
> > > > +#define QCA8K_LED_PHY123_PATTERN_EN_SHIFT(_phy, _led) ((((_phy) - 1) * 6) + 8 + (2 * (_led)))
> > > > +#define QCA8K_LED_PHY123_PATTERN_EN_MASK GENMASK(1, 0)
> > > > +
> > > > +#define QCA8K_LED_PHY0123_CONTROL_RULE_SHIFT 0
> > > > +#define QCA8K_LED_PHY4_CONTROL_RULE_SHIFT 16
> > > > +
> > > > +#define QCA8K_LED_CTRL_REG(_i) (0x050 + (_i) * 4)
> > > > +#define QCA8K_LED_CTRL0_REG 0x50
> > > > +#define QCA8K_LED_CTRL1_REG 0x54
> > > > +#define QCA8K_LED_CTRL2_REG 0x58
> > > > +#define QCA8K_LED_CTRL3_REG 0x5C
> > > > +#define QCA8K_LED_CTRL_SHIFT(_i) (((_i) % 2) * 16)
> > > > +#define QCA8K_LED_CTRL_MASK GENMASK(15, 0)
> > > > +#define QCA8K_LED_RULE_MASK GENMASK(13, 0)
> > > > +#define QCA8K_LED_BLINK_FREQ_MASK GENMASK(1, 0)
> > > > +#define QCA8K_LED_BLINK_FREQ_SHITF 0
> > > > +#define QCA8K_LED_BLINK_2HZ 0
> > > > +#define QCA8K_LED_BLINK_4HZ 1
> > > > +#define QCA8K_LED_BLINK_8HZ 2
> > > > +#define QCA8K_LED_BLINK_AUTO 3
> > > > +#define QCA8K_LED_LINKUP_OVER_MASK BIT(2)
> > > > +#define QCA8K_LED_TX_BLINK_MASK BIT(4)
> > > > +#define QCA8K_LED_RX_BLINK_MASK BIT(5)
> > > > +#define QCA8K_LED_COL_BLINK_MASK BIT(7)
> > > > +#define QCA8K_LED_LINK_10M_EN_MASK BIT(8)
> > > > +#define QCA8K_LED_LINK_100M_EN_MASK BIT(9)
> > > > +#define QCA8K_LED_LINK_1000M_EN_MASK BIT(10)
> > > > +#define QCA8K_LED_POWER_ON_LIGHT_MASK BIT(11)
> > > > +#define QCA8K_LED_HALF_DUPLEX_MASK BIT(12)
> > > > +#define QCA8K_LED_FULL_DUPLEX_MASK BIT(13)
> > > > +#define QCA8K_LED_PATTERN_EN_MASK GENMASK(15, 14)
> > > > +#define QCA8K_LED_PATTERN_EN_SHIFT 14
> > > > +#define QCA8K_LED_ALWAYS_OFF 0
> > > > +#define QCA8K_LED_ALWAYS_BLINK_4HZ 1
> > > > +#define QCA8K_LED_ALWAYS_ON 2
> > > > +#define QCA8K_LED_RULE_CONTROLLED 3
> > > > +
> > > > #define QCA8K_GOL_MAC_ADDR0 0x60
> > > > #define QCA8K_GOL_MAC_ADDR1 0x64
> > > > #define QCA8K_MAX_FRAME_SIZE 0x78
> > > > @@ -383,6 +428,19 @@ struct qca8k_pcs {
> > > > int port;
> > > > };
> > > >
> > > > +struct qca8k_led_pattern_en {
> > > > + u32 reg;
> > > > + u8 shift;
> > > > +};
> > > > +
> > > > +struct qca8k_led {
> > > > + u8 port_num;
> > > > + u8 led_num;
> > > > + u16 old_rule;
> > > > + struct qca8k_priv *priv;
> > > > + struct led_classdev cdev;
> > > > +};
> > > > +
> > > > struct qca8k_priv {
> > > > u8 switch_id;
> > > > u8 switch_revision;
> > > > @@ -407,6 +465,7 @@ struct qca8k_priv {
> > > > struct qca8k_pcs pcs_port_0;
> > > > struct qca8k_pcs pcs_port_6;
> > > > const struct qca8k_match_data *info;
> > > > + struct qca8k_led ports_led[QCA8K_LED_COUNT];
> > > > };
> > > >
> > > > struct qca8k_mib_desc {
> > > > diff --git a/drivers/net/dsa/qca/qca8k_leds.h b/drivers/net/dsa/qca/qca8k_leds.h
> > > > new file mode 100644
> > > > index 000000000000..ab367f05b173
> > > > --- /dev/null
> > > > +++ b/drivers/net/dsa/qca/qca8k_leds.h
> > > > @@ -0,0 +1,16 @@
> > > > +/* SPDX-License-Identifier: GPL-2.0-only */
> > > > +
> > > > +#ifndef __QCA8K_LEDS_H
> > > > +#define __QCA8K_LEDS_H
> > > > +
> > > > +/* Leds Support function */
> > > > +#ifdef CONFIG_NET_DSA_QCA8K_LEDS_SUPPORT
> > > > +int qca8k_setup_led_ctrl(struct qca8k_priv *priv);
> > > > +#else
> > > > +static inline int qca8k_setup_led_ctrl(struct qca8k_priv *priv)
> > > > +{
> > > > + return 0;
> > > > +}
> > > > +#endif
> > > > +
> > > > +#endif /* __QCA8K_LEDS_H */
> > > > --
> > > > 2.39.2
> > > >
> >
> > --
> > Ansuel
>
>
> Thanks,
> Michal
--
Ansuel
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
next prev parent reply other threads:[~2023-03-19 1:11 UTC|newest]
Thread overview: 72+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-03-17 2:31 [net-next PATCH v4 00/14] net: Add basic LED support for switch/phy Christian Marangi
2023-03-17 2:31 ` Christian Marangi
2023-03-17 2:31 ` [net-next PATCH v4 01/14] net: dsa: qca8k: move qca8k_port_to_phy() to header Christian Marangi
2023-03-17 2:31 ` Christian Marangi
2023-03-17 2:31 ` [net-next PATCH v4 02/14] net: dsa: qca8k: add LEDs basic support Christian Marangi
2023-03-17 2:31 ` Christian Marangi
2023-03-17 11:24 ` Michal Kubiak
2023-03-17 11:24 ` Michal Kubiak
2023-03-17 13:34 ` Andrew Lunn
2023-03-17 13:34 ` Andrew Lunn
2023-03-17 14:01 ` Christian Marangi
2023-03-17 14:01 ` Christian Marangi
2023-03-17 18:05 ` Michal Kubiak
2023-03-17 18:05 ` Michal Kubiak
2023-03-18 18:54 ` Christian Marangi [this message]
2023-03-18 18:54 ` Christian Marangi
2023-03-17 2:31 ` [net-next PATCH v4 03/14] net: dsa: qca8k: add LEDs blink_set() support Christian Marangi
2023-03-17 2:31 ` Christian Marangi
2023-03-17 11:54 ` Michal Kubiak
2023-03-17 11:54 ` Michal Kubiak
2023-03-17 14:03 ` Christian Marangi
2023-03-17 14:03 ` Christian Marangi
2023-03-18 19:14 ` Christian Marangi
2023-03-18 19:14 ` Christian Marangi
2023-03-17 2:31 ` [net-next PATCH v4 04/14] net: phy: Add a binding for PHY LEDs Christian Marangi
2023-03-17 2:31 ` Christian Marangi
2023-03-17 7:45 ` Marek Behún
2023-03-17 7:45 ` Marek Behún
2023-03-17 13:55 ` Andrew Lunn
2023-03-17 13:55 ` Andrew Lunn
2023-03-17 14:29 ` Marek Behún
2023-03-17 14:29 ` Marek Behún
2023-03-17 15:31 ` Andrew Lunn
2023-03-17 15:31 ` Andrew Lunn
2023-03-17 9:15 ` kernel test robot
2023-03-17 12:10 ` kernel test robot
2023-03-17 13:38 ` Michal Kubiak
2023-03-17 13:38 ` Michal Kubiak
2023-03-17 14:03 ` Andrew Lunn
2023-03-17 14:03 ` Andrew Lunn
2023-03-17 15:12 ` Michal Kubiak
2023-03-17 15:12 ` Michal Kubiak
2023-03-17 2:31 ` [net-next PATCH v4 05/14] net: phy: phy_device: Call into the PHY driver to set LED brightness Christian Marangi
2023-03-17 2:31 ` Christian Marangi
2023-03-17 14:01 ` Michal Kubiak
2023-03-17 14:01 ` Michal Kubiak
2023-03-17 2:31 ` [net-next PATCH v4 06/14] net: phy: marvell: Add software control of the LEDs Christian Marangi
2023-03-17 2:31 ` Christian Marangi
2023-03-17 2:31 ` [net-next PATCH v4 07/14] net: phy: phy_device: Call into the PHY driver to set LED blinking Christian Marangi
2023-03-17 2:31 ` Christian Marangi
2023-03-17 2:31 ` [net-next PATCH v4 08/14] net: phy: marvell: Implement led_blink_set() Christian Marangi
2023-03-17 2:31 ` Christian Marangi
2023-03-17 2:31 ` [net-next PATCH v4 09/14] dt-bindings: net: ethernet-controller: Document support for LEDs node Christian Marangi
2023-03-17 2:31 ` Christian Marangi
2023-03-17 2:31 ` [net-next PATCH v4 10/14] dt-bindings: net: dsa: qca8k: add LEDs definition example Christian Marangi
2023-03-17 2:31 ` Christian Marangi
2023-03-17 8:14 ` Marek Behún
2023-03-17 8:14 ` Marek Behún
2023-03-17 14:09 ` Christian Marangi
2023-03-17 14:09 ` Christian Marangi
2023-03-17 14:22 ` Andrew Lunn
2023-03-17 14:22 ` Andrew Lunn
2023-03-17 16:02 ` Andrew Lunn
2023-03-17 16:02 ` Andrew Lunn
2023-03-17 2:31 ` [net-next PATCH v4 11/14] arm: qcom: dt: Drop unevaluated properties in switch nodes for rb3011 Christian Marangi
2023-03-17 2:31 ` Christian Marangi
2023-03-17 2:31 ` [net-next PATCH v4 12/14] arm: qcom: dt: Add Switch LED for each port " Christian Marangi
2023-03-17 2:31 ` Christian Marangi
2023-03-17 2:31 ` [net-next PATCH v4 13/14] dt-bindings: net: phy: Document support for LEDs node Christian Marangi
2023-03-17 2:31 ` Christian Marangi
2023-03-17 2:31 ` [net-next PATCH v4 14/14] arm: mvebu: dt: Add PHY LED support for 370-rd WAN port Christian Marangi
2023-03-17 2:31 ` Christian Marangi
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=64166129.1c0a0220.1cb2c.3308@mx.google.com \
--to=ansuelsmth@gmail.com \
--cc=agross@kernel.org \
--cc=andersson@kernel.org \
--cc=andrew@lunn.ch \
--cc=davem@davemloft.net \
--cc=devicetree@vger.kernel.org \
--cc=edumazet@google.com \
--cc=f.fainelli@gmail.com \
--cc=gregory.clement@bootlin.com \
--cc=hkallweit1@gmail.com \
--cc=john@phrozen.org \
--cc=konrad.dybcio@linaro.org \
--cc=krzysztof.kozlowski+dt@linaro.org \
--cc=kuba@kernel.org \
--cc=lee@kernel.org \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-arm-msm@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-leds@vger.kernel.org \
--cc=linux@armlinux.org.uk \
--cc=michal.kubiak@intel.com \
--cc=netdev@vger.kernel.org \
--cc=olteanv@gmail.com \
--cc=pabeni@redhat.com \
--cc=robh+dt@kernel.org \
--cc=sebastian.hesselbarth@gmail.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.