* [PATCH v2 0/3] phy: Realtek Otto SerDes: add new driver
@ 2024-10-07 16:36 Markus Stockhausen
2024-10-07 16:36 ` [PATCH v2 1/3] dt-bindings: phy: add realtek,otto-serdes PHY binding Markus Stockhausen
` (2 more replies)
0 siblings, 3 replies; 22+ messages in thread
From: Markus Stockhausen @ 2024-10-07 16:36 UTC (permalink / raw)
To: linux-phy, chris.packham, devicetree, krzk; +Cc: Markus Stockhausen
This patch series adds support for the SerDes in the Realtek Otto platform.
These are 8-52 port switch SoCs of the RTL83xx and RTL93xx series with MIPS
cores. The ports are based on 1-8 port PHYs (e.g. RTL8218D) that are connected
via multiple SerDes.
The driver is based on the GPL source drops from the different switch vendors.
It supports all 4 SoC series and was developed and tested on the following
devices:
RTL838x - codename maple - Linksys LGS310C
RTL839x - codename cypress - Zyxel GS1920-24
RTL930x - codename langon - Zyxel XGS1210-10
RTL931x - codename mango - Linksys LGS352C
Due to very little information and fundamentally different I/O handling and
port ranges of the devices the driver assumes and translates some handling
to provide a common consistent interface.
Currently only provide the most basic operations for mode set and device
reset as well as some debugging information if enabled. The strength lies in
the fact that the driver can run patch sequences for the SerDes registers at
certain events, e.g. during setup. This allows to run configuration
operations to get the SerDes up and running. For now provide setup sequences
for RTL838x and RTL839x devices.
For more information see:
https://svanheule.net/switches/gpl_source_drops
https://svanheule.net/realtek/
^ permalink raw reply [flat|nested] 22+ messages in thread
* [PATCH v2 1/3] dt-bindings: phy: add realtek,otto-serdes PHY binding
2024-10-07 16:36 [PATCH v2 0/3] phy: Realtek Otto SerDes: add new driver Markus Stockhausen
@ 2024-10-07 16:36 ` Markus Stockhausen
2024-10-07 18:17 ` Rob Herring (Arm)
` (4 more replies)
2024-10-07 16:36 ` [PATCH v2 2/3] phy: Realtek Otto SerDes driver Markus Stockhausen
2024-10-07 16:36 ` [PATCH v2 3/3] phy: Integrate Realtek Otto SerDes driver into build system Markus Stockhausen
2 siblings, 5 replies; 22+ messages in thread
From: Markus Stockhausen @ 2024-10-07 16:36 UTC (permalink / raw)
To: linux-phy, chris.packham, devicetree, krzk; +Cc: Markus Stockhausen
Add bindings for the SerDes of the Realtek Otto platform. These are
network Switch SoCs with up to 52 ports divided into four different
model lines.
Changes in v2:
- new subject
- removed patch command sequences
- renamed parameter controlled-ports to realtek,controlled-ports
Signed-off-by: Markus Stockhausen <markus.stockhausen@gmx.de>
---
.../bindings/phy/realtek,otto-serdes.yaml | 95 +++++++++++++++++++
1 file changed, 95 insertions(+)
create mode 100644 Documentation/devicetree/bindings/phy/realtek,otto-serdes.yaml
diff --git a/Documentation/devicetree/bindings/phy/realtek,otto-serdes.yaml b/Documentation/devicetree/bindings/phy/realtek,otto-serdes.yaml
new file mode 100644
index 000000000000..a72ac206b35f
--- /dev/null
+++ b/Documentation/devicetree/bindings/phy/realtek,otto-serdes.yaml
@@ -0,0 +1,95 @@
+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/phy/realtek,otto-serdes.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Realtek Otto SerDes controller
+
+maintainers:
+ - Markus Stockhausen <markus.stockhausen@gmx.de>
+
+description:
+ The MIPS based Realtek Switch SoCs of the Realtek RTL838x, RTL839x, RTL930x and RTL931x series
+ have multiple SerDes built in. They are linked to single, quad or octa PHYs like the RTL8218B,
+ RTL8218D or RTL8214FC and are one of the integral part of the up-to-52-port switch architecture.
+
+ Although these SerDes controllers have common basics they behave differently on the SoC families
+ and rely on heavy register magic. To keep the driver clean it can load patch sequences from
+ devictree and execute them during the controller actions like phy_init(), ...
+
+ The driver exposes the SerDes registers different from the hardware but instead gives a
+ consistent view and programming interface. So the RTL838x series has 6 ports and 4 pages, the
+ RTL839x has 14 ports and 12 pages, the RTL930x has 12 ports and 64 pages and the RTL931x has
+ 14 ports and 192 pages.
+
+properties:
+ $nodename:
+ pattern: "^serdes@[0-9a-f]+$"
+
+ compatible:
+ items:
+ - enum:
+ - realtek,rtl8380-serdes
+ - realtek,rtl8390-serdes
+ - realtek,rtl9300-serdes
+ - realtek,rtl9310-serdes
+
+ reg:
+ items:
+ description:
+ The primary SerDes paged register memory location. Other SerDes control and management
+ registers are distributed all over the I/O memory space and are identified by the driver.
+
+ "#phy-cells":
+ const: 4
+ description:
+ The first number defines the SerDes to use. The second number a linked SerDes. E.g. if a octa
+ 1G PHY is attached to two QSGMII SerDes. The third number is the first switch port this
+ SerDes is working for, the fourth number is the last switch port the SerDes is working for.
+
+ realtek,controlled-ports:
+ $ref: /schemas/types.yaml#/definitions/uint32
+ description:
+ A bit mask defining the ports that are actively controlled by the driver. In case a bit is
+ not set the driver will only process read operations on the SerDes. This is just in case the
+ SerDes has been setup by U-Boot correctly and the driver malfunctions. If not set the driver
+ will control all SerDes.
+
+reguired:
+ - compatible
+ - reg
+ - "#phy-cells"
+
+additionalProperties:
+ false
+
+examples:
+ - |
+ serdes: serdes@1b00e780 {
+ compatible = "realtek,rtl8380-serdes", "realtek,otto-serdes";
+ reg = <0x1b00e780 0x1200>;
+ controlled-ports = <0x003f>;
+ #phy-cells = <4>;
+ };
+ - |
+ serdes: serdes@1b00a000 {
+ compatible = "realtek,rtl8390-serdes", "realtek,otto-serdes";
+ reg = <0x1b00a000 0x1c00>;
+ controlled-ports = <0x3fff>;
+ #phy-cells = <4>;
+ };
+ - |
+ serdes: serdes@1b0003b0 {
+ compatible = "realtek,rtl9300-serdes", "realtek,otto-serdes";
+ reg = <0x1b0003b0 0x8>;
+ controlled-ports = <0x0fff>;
+ #phy-cells = <4>;
+ };
+ - |
+ serdes: serdes@1b005638 {
+ compatible = "realtek,rtl9310-serdes", "realtek,otto-serdes";
+ reg = <0x1b005638 0x8>;
+ controlled-ports = <0x3fff>;
+ #phy-cells = <4>;
+ };
--
2.46.2
^ permalink raw reply related [flat|nested] 22+ messages in thread
* [PATCH v2 2/3] phy: Realtek Otto SerDes driver
2024-10-07 16:36 [PATCH v2 0/3] phy: Realtek Otto SerDes: add new driver Markus Stockhausen
2024-10-07 16:36 ` [PATCH v2 1/3] dt-bindings: phy: add realtek,otto-serdes PHY binding Markus Stockhausen
@ 2024-10-07 16:36 ` Markus Stockhausen
2024-10-07 19:32 ` Krzysztof Kozlowski
2024-10-07 16:36 ` [PATCH v2 3/3] phy: Integrate Realtek Otto SerDes driver into build system Markus Stockhausen
2 siblings, 1 reply; 22+ messages in thread
From: Markus Stockhausen @ 2024-10-07 16:36 UTC (permalink / raw)
To: linux-phy, chris.packham, devicetree, krzk; +Cc: Markus Stockhausen
The Realtek Otto platform is a series of 4 different MIPS32 based network
switch SoCs. They consist of:
- RTL838x: 500MHz single core, up to 28 ports 20GBps switching capacity
- RTL839x: 700MHz single core, up to 52 ports 100GBps switching capacity
- RTL930x: 700MHz single core, up to 28 ports 120GBps switching capacity
- RTL931x: 1.4GHz dual core, up to 52 ports 170GBps switching capacity
The SoCs have 6-14 SerDes that provide the interconnect between several
one, quad or octa port attached PHYs like the RTL8218D or RTL8214FC.
This driver builts on top of several GPL source drops from different switch
vendors and harmonizes the different programming models. The common basics
are:
- Each SerDes is controlled through registers that are organized into pages
- A page consists of 32x 16 bit registers that cover various functions
- Registers are either accessed through I/O addresses or an MDIO style bus
- The SerDes operate on different MII variants (mostly QSGMII & XGMII)
The SerDes rely on heavy register modifications with lots of undocumented
features. Provide a patching sequence feature that allows to configure
the system.
Changes in v2:
- switched logic to internal patch sequences
- added setup sequences for RTL838x and RTL839x
- moved includes from header to source file
- added helpers for better readability
- minor fixes from checkpatch
Signed-off-by: Markus Stockhausen <markus.stockhausen@gmx.de>
---
drivers/phy/realtek/phy-rtk-otto-serdes.c | 1312 +++++++++++++++++++++
drivers/phy/realtek/phy-rtk-otto-serdes.h | 117 ++
2 files changed, 1429 insertions(+)
create mode 100644 drivers/phy/realtek/phy-rtk-otto-serdes.c
create mode 100644 drivers/phy/realtek/phy-rtk-otto-serdes.h
diff --git a/drivers/phy/realtek/phy-rtk-otto-serdes.c b/drivers/phy/realtek/phy-rtk-otto-serdes.c
new file mode 100644
index 000000000000..34715ee3ea37
--- /dev/null
+++ b/drivers/phy/realtek/phy-rtk-otto-serdes.c
@@ -0,0 +1,1312 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Realtek RTL838x, RTL839x, RTL930x & RTL931x SerDes PHY driver
+ * Copyright (c) 2024 Markus Stockhausen <markus.stockhausen@gmx.de>
+ */
+
+#include <linux/debugfs.h>
+#include <linux/delay.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/phy.h>
+#include <linux/phy/phy.h>
+#include <linux/platform_device.h>
+
+#include "phy-rtk-otto-serdes.h"
+
+/* common helpers */
+
+static inline bool rtsds_invalid_reg(struct rtsds_ctrl *ctrl, u32 sid, u32 page, u32 reg)
+{
+ return (sid >= ctrl->conf->sds_cnt || page >= ctrl->conf->page_cnt || reg > 31);
+}
+
+static inline bool rtsds_invalid_sds(struct rtsds_ctrl *ctrl, u32 sid)
+{
+ return (sid >= ctrl->conf->sds_cnt);
+}
+
+static inline bool rtsds_readonly(struct rtsds_ctrl *ctrl, u32 sid)
+{
+ return !(ctrl->sds_mask & BIT(sid));
+}
+
+static int rtsds_hwmode_to_phymode(struct rtsds_ctrl *ctrl, int hwmode)
+{
+ for (int m = 0; m < PHY_INTERFACE_MODE_MAX; m++)
+ if (ctrl->conf->mode_map[m] == hwmode)
+ return m;
+
+ return PHY_INTERFACE_MODE_MAX;
+}
+
+static const char *rtsds_events[RTSDS_EVENT_CNT] = {
+ [RTSDS_EVENT_SETUP] = "setup",
+};
+
+static int rtsds_run_event(struct rtsds_ctrl *ctrl, u32 sid, int evt)
+{
+ struct rtsds_seq *seq;
+ int ret, step = 1, delay = 0;
+
+ if (evt >= RTSDS_EVENT_CNT || sid >= ctrl->conf->sds_cnt)
+ return -EINVAL;
+
+ seq = ctrl->conf->sequence[evt];
+
+ if (!seq)
+ return 0;
+
+ while (seq->action != RTSDS_SEQ_STOP) {
+ if (!(seq->ports & BIT(sid)) ||
+ ((seq->mode != PHY_INTERFACE_MODE_NA) &&
+ (seq->mode != ctrl->sds[sid].mode))) {
+ step++; seq++;
+ continue;
+ }
+
+ if (seq->action == RTSDS_SEQ_WAIT)
+ delay = seq->val;
+
+ if (delay)
+ usleep_range(delay << 10, (delay << 10) + 1000);
+
+ if (seq->action == RTSDS_SEQ_MASK) {
+ ret = ctrl->conf->mask(ctrl, sid, seq->page,
+ seq->reg, seq->val, seq->mask);
+ if (ret) {
+ dev_err(ctrl->dev, "sequence %s failed at step %d",
+ rtsds_events[evt], step);
+ return -EIO;
+ }
+ }
+
+ step++; seq++;
+ }
+
+ return 0;
+}
+
+/* common RTL838x and RTL839x helpers */
+
+static void rtsds_83xx_digital_reset(struct rtsds_ctrl *ctrl, u32 sid, u32 cnt)
+{
+ /* software reset */
+ for (u32 i = sid; i <= sid + cnt; i++)
+ ctrl->conf->mask(ctrl, i, RTSDS_PAGE_SDS,
+ 0x03, RTSDS_BITS_SOFT_RST, RTSDS_BITS_SOFT_RST);
+ usleep_range(100000, 101000);
+ for (u32 i = sid; i <= sid + cnt; i++)
+ ctrl->conf->mask(ctrl, i, RTSDS_PAGE_SDS,
+ 0x03, 0x0000, RTSDS_BITS_SOFT_RST);
+ /* RX/TX reset */
+ for (u32 i = sid; i <= sid + cnt; i++) {
+ ctrl->conf->mask(ctrl, i, RTSDS_PAGE_SDS,
+ 0x00, 0x0000, RTSDS_BITS_SDS_EN);
+ ctrl->conf->mask(ctrl, i, RTSDS_PAGE_SDS,
+ 0x00, RTSDS_BITS_SDS_EN, RTSDS_BITS_SDS_EN);
+ }
+}
+
+/* common RTL930x and RTL931x helpers */
+
+static int rtsds_93xx_read(struct rtsds_ctrl *ctrl, u32 sid, u32 page, u32 reg)
+{
+ int cnt = 100, cmd = (sid << 2) | (page << 7) | (reg << 13) | RTSDS_93XX_SDS_READ;
+
+ iowrite32(cmd, ctrl->base);
+ while (--cnt && (ioread32(ctrl->base) & RTSDS_93XX_SDS_BUSY))
+ usleep_range(50, 60);
+
+ return cnt ? ioread32(ctrl->base + 4) & 0xffff : -EIO;
+}
+
+static int rtsds_93xx_mask(struct rtsds_ctrl *ctrl, u32 sid, u32 page, u32 reg, u32 val, u32 mask)
+{
+ int oldval, cnt = 100, cmd = (sid << 2) | (page << 7) | (reg << 13) | RTSDS_93XX_SDS_WRITE;
+
+ if (mask != 0xffff) {
+ oldval = rtsds_93xx_read(ctrl, sid, page, reg);
+ if (oldval < 0)
+ return -EIO;
+ oldval &= ~mask;
+ val |= oldval;
+ }
+
+ iowrite32(val, ctrl->base + 4);
+ iowrite32(cmd, ctrl->base);
+
+ while (--cnt && (ioread32(ctrl->base) & RTSDS_93XX_SDS_BUSY))
+ usleep_range(50, 60);
+
+ return cnt ? 0 : -EIO;
+}
+
+/*
+ * The RTL838x has 6 SerDes. The 16 bit registers start at 0xbb00e780 and are mapped directly into
+ * 32 bit memory addresses. High 16 bits are always empty. A "lower memory block serves pages 0/3
+ * a higher one pages 1/2.
+ */
+
+static int rtsds_838x_reg_offset(u32 sid, u32 page, u32 reg)
+{
+ if (page == 0 || page == 3)
+ return (sid << 9) + (page << 7) + (reg << 2);
+ else
+ return 0xb80 + (sid << 8) + (page << 7) + (reg << 2);
+}
+
+static int rtsds_838x_read(struct rtsds_ctrl *ctrl, u32 sid, u32 page, u32 reg)
+{
+ int offs;
+
+ if (rtsds_invalid_reg(ctrl, sid, page, reg))
+ return -EINVAL;
+
+ offs = rtsds_838x_reg_offset(sid, page, reg);
+
+ /* read twice for link status latch */
+ if (page == RTSDS_PAGE_FIB && reg == 1)
+ ioread32(ctrl->base + offs);
+
+ return ioread32(ctrl->base + offs);
+}
+
+static int rtsds_838x_mask(struct rtsds_ctrl *ctrl, u32 sid, u32 page, u32 reg, u32 val, u32 mask)
+{
+ int offs;
+
+ if (rtsds_invalid_reg(ctrl, sid, page, reg))
+ return -EINVAL;
+
+ offs = rtsds_838x_reg_offset(sid, page, reg);
+
+ /* read twice for link status latch */
+ if (page == RTSDS_PAGE_FIB && reg == 1)
+ ioread32(ctrl->base + offs);
+
+ iomask32(mask, val, ctrl->base + offs);
+
+ return 0;
+}
+
+static void rtsds_838x_rx_reset(struct rtsds_ctrl *ctrl, u32 sid)
+{
+ /* reset with a selftest by enabling/disabling RX_EN_SELF */
+ rtsds_838x_mask(ctrl, sid, 0x01, 0x09, 0x0200, 0x0200);
+ usleep_range(100000, 101000);
+ rtsds_838x_mask(ctrl, sid, 0x01, 0x09, 0x0000, 0x0200);
+}
+
+static void rtsds_838x_cmu_reset(struct rtsds_ctrl *ctrl, u32 sid)
+{
+ rtsds_838x_mask(ctrl, sid, 0x01, 0x00, 0x4040, 0xffff);
+ rtsds_838x_mask(ctrl, sid, 0x01, 0x00, 0x4740, 0xffff);
+ rtsds_838x_mask(ctrl, sid, 0x01, 0x00, 0x47c0, 0xffff);
+ rtsds_838x_mask(ctrl, sid, 0x01, 0x00, 0x4000, 0xffff);
+}
+
+static int rtsds_838x_reset(struct rtsds_ctrl *ctrl, u32 sid)
+{
+ if (rtsds_invalid_sds(ctrl, sid))
+ return -EINVAL;
+
+ rtsds_838x_rx_reset(ctrl, sid);
+ rtsds_838x_cmu_reset(ctrl, sid);
+ rtsds_83xx_digital_reset(ctrl, sid, 1);
+
+ return 0;
+}
+
+static int rtsds_838x_set_mode(struct rtsds_ctrl *ctrl, u32 sid, int combomode)
+{
+ int shift, mode = RTSDS_MODE(combomode), submode = RTSDS_SUBMODE(combomode);
+
+ if (rtsds_invalid_sds(ctrl, sid))
+ return -EINVAL;
+
+ if (sid >= 4) {
+ shift = (sid - 4) * 3;
+ iomask32(0x7 << shift, (submode & 0x7) << shift, RTSDS_838X_INT_MODE_CTRL);
+ } else if (submode != 0)
+ return -EINVAL;
+
+ shift = 25 - sid * 5;
+ iomask32(0x1f << shift, (mode & 0x1f) << shift, RTSDS_838X_SDS_MODE_SEL);
+
+ return 0;
+}
+
+static int rtsds_838x_get_mode(struct rtsds_ctrl *ctrl, u32 sid)
+{
+ int shift, mode, submode = 0;
+
+ if (rtsds_invalid_sds(ctrl, sid))
+ return -EINVAL;
+
+ if (sid >= 4) {
+ shift = (sid - 4) * 3;
+ submode = (ioread32(RTSDS_838X_INT_MODE_CTRL) >> shift) & 0x7;
+ }
+
+ shift = 25 - sid * 5;
+ mode = (ioread32(RTSDS_838X_SDS_MODE_SEL) >> shift) & 0x1f;
+
+ return RTSDS_COMBOMODE(mode, submode);
+}
+
+/*
+ * The RLT839x has 14 SerDes starting at 0xbb00a000. 0-7, 10, 11 are 5GBit, 8, 9, 12, 13 are
+ * 10GIt. Two adjacent SerDes are tightly coupled and share a 1024 bytes register area. Per 32 bit
+ * address two registers are stored. The first register is stored in the lower 2 bytes ("on the
+ * right" due to big endian) and the second register in the upper 2 bytes. We know the following
+ * register areas:
+ *
+ * - XSG0 (4 pages @ offset 0x000): for even SerDes
+ * - XSG1 (4 pages @ offset 0x100): for odd SerDes
+ * - TGRX (4 pages @ offset 0x200): for even 10G SerDes
+ * - ANA_RG (2 pages @ offset 0x300): for even 5G SerDes
+ * - ANA_RG (2 pages @ offset 0x380): for odd 5G SerDes
+ * - ANA_TG (2 pages @ offset 0x300): for even 10G SerDes
+ * - ANA_TG (2 pages @ offset 0x380): for odd 10G SerDes
+ *
+ * The most consistent mapping that aligns to the RTL93xx devices is:
+ *
+ * even 5G SerDes odd 5G SerDes even 10G SerDes odd 10G SerDes
+ * Page 0: XSG0/0 XSG1/0 XSG0/0 XSG1/0
+ * Page 1: XSG0/1 XSG1/1 XSG0/1 XSG1/1
+ * Page 2: XSG0/2 XSG1/2 XSG0/2 XSG1/2
+ * Page 3: XSG0/3 XSG1/3 XSG0/3 XSG1/3
+ * Page 4: <zero> <zero> TGRX/0 <zero>
+ * Page 5: <zero> <zero> TGRX/1 <zero>
+ * Page 6: <zero> <zero> TGRX/2 <zero>
+ * Page 7: <zero> <zero> TGRX/3 <zero>
+ * Page 8: ANA_RG ANA_RG <zero> <zero>
+ * Page 9: ANA_RG_EXT ANA_RG_EXT <zero> <zero>
+ * Page 10: <zero> <zero> ANA_TG ANA_TG
+ * Page 11: <zero> <zero> ANA_TG_EXT ANA_TG_EXT
+ */
+
+static int rtsds_839x_reg_offset(u32 sid, u32 page, u32 reg)
+{
+ int offs = ((sid & 0xfe) << 9) + ((reg & 0xfe) << 1);
+
+ if (page < 4) {
+ offs += ((sid & 1) << 8) + (page << 6);
+ } else if (page < 8) {
+ if (sid != 8 && sid != 12)
+ return -1;
+ offs += 0x100 + (page << 6);
+ } else if (page < 10) {
+ if (sid == 8 || sid == 9 || sid == 12 || sid == 13)
+ return -1;
+ offs += 0x100 + ((sid & 1) << 7) + (page << 6);
+ } else {
+ if (sid != 8 && sid != 9 && sid != 12 && sid != 13)
+ return -1;
+ offs += 0x100 + ((sid & 1) << 7) + ((page - 2) << 6);
+ }
+
+ return offs;
+}
+
+static int rtsds_839x_read(struct rtsds_ctrl *ctrl, u32 sid, u32 page, u32 reg)
+{
+ int offs, shift = (reg << 4) & 0x10;
+
+ if (rtsds_invalid_reg(ctrl, sid, page, reg))
+ return -EINVAL;
+
+ offs = rtsds_839x_reg_offset(sid, page, reg);
+ if (offs < 0)
+ return 0;
+
+ /* read twice for link status latch */
+ if (page == RTSDS_PAGE_FIB && reg == 1)
+ ioread32(ctrl->base + offs);
+
+ return (ioread32(ctrl->base + offs) >> shift) & 0xffff;
+}
+
+static int rtsds_839x_mask(struct rtsds_ctrl *ctrl, u32 sid, u32 page, u32 reg, u32 val, u32 mask)
+{
+ int oldval, offs;
+
+ if (rtsds_invalid_reg(ctrl, sid, page, reg))
+ return -EINVAL;
+
+ offs = rtsds_839x_reg_offset(sid, page, reg);
+ if (offs < 0)
+ return 0;
+
+ /* read twice for link status latch */
+ if (page == RTSDS_PAGE_FIB && reg == 1)
+ ioread32(ctrl->base + offs);
+
+ oldval = ioread32(ctrl->base + offs);
+ val = reg & 1 ? (oldval & ~(mask << 16)) | (val << 16) : (oldval & ~mask) | val;
+ iowrite32(val, ctrl->base + offs);
+
+ return 0;
+}
+
+static int rtsds_839x_set_mode(struct rtsds_ctrl *ctrl, u32 sid, int combomode)
+{
+ int shift = (sid & 7) << 2, offs = (sid >> 1) & ~3;
+ int mode = RTSDS_MODE(combomode), submode = RTSDS_SUBMODE(combomode);
+
+ if (rtsds_invalid_sds(ctrl, sid))
+ return -EINVAL;
+
+ rtsds_839x_mask(ctrl, sid, RTSDS_PAGE_SDS, 0x04, (submode << 12) & 0xf000, 0xf000);
+ iomask32(0xf << shift, (mode & 0xf) << shift, RTSDS_839X_MAC_SERDES_IF_CTRL + offs);
+
+ return 0;
+}
+
+static int rtsds_839x_get_mode(struct rtsds_ctrl *ctrl, u32 sid)
+{
+ int mode, submode, shift = (sid & 7) << 2, offs = (sid >> 1) & ~3;
+
+ if (rtsds_invalid_sds(ctrl, sid))
+ return -EINVAL;
+
+ submode = (rtsds_839x_read(ctrl, sid, RTSDS_PAGE_SDS, 0x04) >> 12) & 0xf;
+ mode = (ioread32(RTSDS_839X_MAC_SERDES_IF_CTRL + offs) >> shift) & 0xf;
+
+ return RTSDS_COMBOMODE(mode, submode);
+}
+
+static void rtsds_839x_rx_reset(struct rtsds_ctrl *ctrl, u32 sid)
+{
+ u32 i, page, reg, pre, post, mask, lo = sid & ~1, hi = sid | 1;
+
+ /* reset with a selftest by enabling/disabling RX_EN_SELF */
+ if (lo < 8 || lo == 10) {
+ page = 0x08; reg = 0x14; pre = 0x0200; post = 0x0000; mask = 0x0201;
+ } else {
+ page = 0x0b; reg = 0x00; pre = 0x8000; post = 0x0000; mask = 0x8008;
+ }
+
+ for (i = lo; i <= hi; i++)
+ rtsds_839x_mask(ctrl, i, page, reg, pre, mask);
+ usleep_range(100000, 101000);
+ for (i = lo; i <= hi; i++)
+ rtsds_839x_mask(ctrl, i, page, reg, post, mask);
+}
+
+static void rtsds_839x_cmu_reset(struct rtsds_ctrl *ctrl, u32 sid)
+{
+ int hi = sid | 1;
+
+ if (hi == 9 || hi == 13)
+ return;
+
+ rtsds_839x_mask(ctrl, hi, 0x09, 0x01, 0x0050, 0xffff);
+ rtsds_839x_mask(ctrl, hi, 0x09, 0x01, 0x00f0, 0xffff);
+ rtsds_839x_mask(ctrl, hi, 0x09, 0x01, 0x0000, 0xffff);
+}
+
+static int rtsds_839x_reset(struct rtsds_ctrl *ctrl, u32 sid)
+{
+ int lo = sid & ~1;
+
+ if (rtsds_invalid_sds(ctrl, sid))
+ return -EINVAL;
+
+ /* Registers are shared between adjacent SerDes. Reset both. */
+ rtsds_839x_cmu_reset(ctrl, sid);
+ rtsds_839x_rx_reset(ctrl, sid);
+ rtsds_83xx_digital_reset(ctrl, lo, 2);
+
+ return 0;
+}
+
+/*
+ * The RTL930x family has 12 SerdDes. They are accessed through two IO registers at 0xbb0003b0
+ * which simulate commands to an internal MDIO bus. From the current observation there are 3 types
+ * of SerDes:
+ *
+ * - SerDes 0,1 exist on the RLT9301 and 9302B and are QSGMII capable
+ * - SerDes 2-9 are USXGMII capabable with either quad or single configuration
+ * - SerDes 10-11 are 10GBase-R capable
+ */
+
+static int rtsds_930x_read(struct rtsds_ctrl *ctrl, u32 sid, u32 page, u32 reg)
+{
+ if (rtsds_invalid_reg(ctrl, sid, page, reg))
+ return -EINVAL;
+
+ return rtsds_93xx_read(ctrl, sid, page, reg);
+}
+
+static int rtsds_930x_mask(struct rtsds_ctrl *ctrl, u32 sid, u32 page, u32 reg, u32 val, u32 mask)
+{
+ if (rtsds_invalid_reg(ctrl, sid, page, reg))
+ return -EINVAL;
+
+ return rtsds_93xx_mask(ctrl, sid, page, reg, val, mask);
+}
+
+static void rtsds_930x_mode_offset(int sid,
+ void __iomem __force **modereg, int *modeshift,
+ void __iomem __force **subreg, int *subshift)
+{
+ if (sid > 3) {
+ *subreg = RTSDS_930X_SDS_SUBMODE_CTRL1;
+ *subshift = (sid - 4) * 5;
+ } else {
+ *subreg = RTSDS_930X_SDS_SUBMODE_CTRL0;
+ *subshift = (sid - 2) * 5;
+ }
+
+ if (sid < 4) {
+ *modeshift = sid * 6;
+ *modereg = RTSDS_930X_SDS_MODE_SEL_0;
+ } else if (sid < 8) {
+ *modeshift = (sid - 4) * 6;
+ *modereg = RTSDS_930X_SDS_MODE_SEL_1;
+ } else if (sid < 10) {
+ *modeshift = (sid - 8) * 6;
+ *modereg = RTSDS_930X_SDS_MODE_SEL_2;
+ } else {
+ *modeshift = (sid - 10) * 6;
+ *modereg = RTSDS_930X_SDS_MODE_SEL_3;
+ }
+}
+
+static int rtsds_930x_set_mode(struct rtsds_ctrl *ctrl, u32 sid, int combomode)
+{
+ int modeshift, subshift;
+ int mode = RTSDS_MODE(combomode);
+ int submode = RTSDS_SUBMODE(combomode);
+ void __iomem __force *modereg;
+ void __iomem __force *subreg;
+
+ if (rtsds_invalid_sds(ctrl, sid))
+ return -EINVAL;
+
+ rtsds_930x_mode_offset(sid, &modereg, &modeshift, &subreg, &subshift);
+ if (sid >= 2 || sid <= 9)
+ iomask32(0x1f << subshift, (submode & 0x1f) << subshift, subreg);
+ else if (submode != 0)
+ return -EINVAL;
+ iomask32(0x1f << modeshift, (mode & 0x1f) << modeshift, modereg);
+
+ return 0;
+}
+
+static int rtsds_930x_get_mode(struct rtsds_ctrl *ctrl, u32 sid)
+{
+ int modeshift, subshift, mode, submode = 0;
+ void __iomem __force *modereg;
+ void __iomem __force *subreg;
+
+ if (rtsds_invalid_sds(ctrl, sid))
+ return -EINVAL;
+
+ rtsds_930x_mode_offset(sid, &modereg, &modeshift, &subreg, &subshift);
+ if (sid >= 2 || sid <= 9)
+ submode = (ioread32(subreg) >> subshift) & 0x1f;
+ mode = ioread32(modereg) >> modeshift & 0x1f;
+
+ return RTSDS_COMBOMODE(mode, submode);
+}
+
+static int rtsds_930x_reset(struct rtsds_ctrl *ctrl, u32 sid)
+{
+ int modecur, modeoff = ctrl->conf->mode_map[PHY_INTERFACE_MODE_NA];
+
+ if (rtsds_invalid_sds(ctrl, sid))
+ return -EINVAL;
+
+ modecur = rtsds_930x_get_mode(ctrl, sid);
+
+ /* It is enough to power off SerDes and set to old mode again */
+ if (modecur != modeoff) {
+ rtsds_930x_set_mode(ctrl, sid, modeoff);
+ rtsds_930x_set_mode(ctrl, sid, modecur);
+ }
+
+ return 0;
+}
+
+/*
+ * The RTL931x family has 14 "frontend" SerDes that are cascaded. All operations (e.g. reset) work
+ * on this frontend view while their registers are distributed over a total of 32 background
+ * SerDes. Two types of SerDes have been identified:
+ *
+ * A "even" SerDes with numbers 0, 1, 2, 4, 6, 8, 10, 12 works on two background SerDes. 64 analog
+ * and 64 XGMII data pages are coming from a first background SerDes while another 64 XGMII pages
+ * are served from a second SerDes.
+ *
+ * The "odd" SerDes with numbers 3, 5, 7, 9, 11 & 13 SerDes consist of a total of 3 background
+ * SerDes (one analog and two XGMII) each with an own page/register set.
+ *
+ * To align this and improve readability the driver will simulate a total of 576 pages and mix
+ * them as follows.
+ *
+ * frontend page "even" frontend SerDes "odd" frontend SerDes
+ * page 0-63 (analog): back SDS page 0-63 back SDS page 0-63
+ * page 64-127 (XGMII1): back SDS page 0-63 back SDS+1 page 0-63
+ * page 128-191 (XGMII2): back SDS+1 page 0-63 back SDS+2 page 0-63
+ */
+
+static int rtsds_931x_reg_offset(u32 sid, u32 page)
+{
+ int map[] = {0, 1, 2, 3, 6, 7, 10, 11, 14, 15, 18, 19, 22, 23};
+ int offs = map[sid];
+
+ if ((sid & 1) && (sid != 1))
+ offs += (page >> 6); /* distribute "odd" to 3 background SerDes */
+ else if (page >= 128)
+ offs += 1; /* "distribute "even" to 2 background SerDes */
+
+ return offs;
+}
+
+static int rtsds_931x_read(struct rtsds_ctrl *ctrl, u32 sid, u32 page, u32 reg)
+{
+ int offs;
+
+ if (rtsds_invalid_reg(ctrl, sid, page, reg))
+ return -EINVAL;
+
+ offs = rtsds_931x_reg_offset(sid, page);
+ if (offs < 0)
+ return 0;
+
+ return rtsds_93xx_read(ctrl, offs, page, reg);
+}
+
+static int rtsds_931x_mask(struct rtsds_ctrl *ctrl, u32 sid, u32 page, u32 reg, u32 val, u32 mask)
+{
+ int offs;
+
+ if (rtsds_invalid_reg(ctrl, sid, page, reg))
+ return -EINVAL;
+
+ offs = rtsds_931x_reg_offset(sid, page);
+ if (offs < 0)
+ return 0;
+
+ return rtsds_93xx_mask(ctrl, offs, page, reg, val, mask);
+}
+
+static int rtsds_931x_set_mode(struct rtsds_ctrl *ctrl, u32 sid, int combomode)
+{
+ int shift = (sid & 3) << 3, offs = sid & ~3;
+ int mode = RTSDS_MODE(combomode);
+ int submode = RTSDS_SUBMODE(combomode);
+
+ if (rtsds_invalid_sds(ctrl, sid))
+ return -EINVAL;
+
+ rtsds_931x_mask(ctrl, sid, 0x1f, 0x09, (submode & 0x3f << 6), 0x0fc0);
+ iomask32(0xff << shift, ((mode | RTSDS_931X_SDS_FORCE_SETUP) & 0xff) << shift,
+ RTSDS_931X_SERDES_MODE_CTRL + offs);
+
+ return 0;
+}
+
+static int rtsds_931x_get_mode(struct rtsds_ctrl *ctrl, u32 sid)
+{
+ int mode, submode, shift = (sid & 3) << 3, offs = sid & ~3;
+
+ if (rtsds_invalid_sds(ctrl, sid))
+ return -EINVAL;
+
+ submode = (rtsds_931x_read(ctrl, sid, 0x1f, 0x09) >> 6) & 0x3f;
+ mode = (ioread32(RTSDS_931X_SERDES_MODE_CTRL + offs) >> shift) & 0x1f;
+
+ return RTSDS_COMBOMODE(mode, submode);
+}
+
+static int rtsds_931x_reset(struct rtsds_ctrl *ctrl, u32 sid)
+{
+ int pwr, modecur, modeoff = ctrl->conf->mode_map[PHY_INTERFACE_MODE_NA];
+
+ if (rtsds_invalid_sds(ctrl, sid))
+ return -EINVAL;
+
+ modecur = rtsds_931x_get_mode(ctrl, sid);
+
+ if (modecur != modeoff) {
+ /* reset with mode switch cycle while being powered off */
+ pwr = ioread32(RTSDS_931X_PS_SERDES_OFF_MODE_CTRL);
+ iowrite32(pwr | BIT(sid), RTSDS_931X_PS_SERDES_OFF_MODE_CTRL);
+ rtsds_931x_set_mode(ctrl, sid, modeoff);
+ rtsds_931x_set_mode(ctrl, sid, modecur);
+ iowrite32(pwr, RTSDS_931X_PS_SERDES_OFF_MODE_CTRL);
+ }
+
+ return 0;
+}
+
+int rtsds_read(struct phy *phy, u32 page, u32 reg)
+{
+ struct rtsds_macro *macro = phy_get_drvdata(phy);
+ struct rtsds_ctrl *ctrl = macro->ctrl;
+ u32 sid = macro->sid;
+
+ return ctrl->conf->read(ctrl, sid, page, reg);
+}
+
+int rtsds_mask(struct phy *phy, u32 page, u32 reg, u32 val, u32 mask)
+{
+ struct rtsds_macro *macro = phy_get_drvdata(phy);
+ struct rtsds_ctrl *ctrl = macro->ctrl;
+ u32 sid = macro->sid;
+
+ if (rtsds_readonly(ctrl, sid))
+ return 0;
+
+ return ctrl->conf->mask(ctrl, sid, page, reg, val, mask);
+}
+
+int rtsds_write(struct phy *phy, u32 page, u32 reg, u32 val)
+{
+ return rtsds_mask(phy, page, reg, val, 0xffff);
+}
+
+static int rtsds_phy_init(struct phy *phy)
+{
+ struct rtsds_macro *macro = phy_get_drvdata(phy);
+ struct rtsds_ctrl *ctrl = macro->ctrl;
+ u32 sid = macro->sid;
+ int ret;
+
+ if (rtsds_readonly(ctrl, sid))
+ return 0;
+
+ mutex_lock(&ctrl->lock);
+// ret = rtsds_run_event(ctrl, sid, RTSDS_EVENT_INIT);
+ mutex_unlock(&ctrl->lock);
+
+ if (ret)
+ dev_err(ctrl->dev, "init failed for SerDes %d\n", sid);
+
+ return ret;
+}
+
+static int rtsds_phy_power_on(struct phy *phy)
+{
+ struct rtsds_macro *macro = phy_get_drvdata(phy);
+ struct rtsds_ctrl *ctrl = macro->ctrl;
+ u32 sid = macro->sid;
+ int ret;
+
+ if (rtsds_readonly(ctrl, sid))
+ return 0;
+
+ mutex_lock(&ctrl->lock);
+// ret = rtsds_run_event(ctrl, sid, RTSDS_EVENT_POWER_ON);
+ mutex_unlock(&ctrl->lock);
+
+ if (ret)
+ dev_err(ctrl->dev, "power on failed for SerDes %d\n", sid);
+
+ return ret;
+}
+
+static int rtsds_phy_power_off(struct phy *phy)
+{
+ struct rtsds_macro *macro = phy_get_drvdata(phy);
+ struct rtsds_ctrl *ctrl = macro->ctrl;
+ u32 sid = macro->sid;
+ int ret;
+
+ if (rtsds_readonly(ctrl, sid))
+ return 0;
+
+ mutex_lock(&ctrl->lock);
+ if (!ret)
+ ret = ctrl->conf->set_mode(ctrl, sid, ctrl->conf->mode_map[PHY_INTERFACE_MODE_NA]);
+ mutex_unlock(&ctrl->lock);
+
+ if (ret)
+ dev_err(ctrl->dev, "power off failed for SerDes %d\n", sid);
+
+ return ret;
+}
+
+static int rtsds_phy_set_mode_int(struct rtsds_ctrl *ctrl, u32 sid, int phymode, int hwmode)
+{
+ int ret;
+
+ mutex_lock(&ctrl->lock);
+ ret = ctrl->conf->set_mode(ctrl, sid, hwmode);
+ if (!ret)
+ ctrl->sds[sid].mode = phymode;
+ mutex_unlock(&ctrl->lock);
+
+ if (ret)
+ dev_err(ctrl->dev, "set mode failed for SerDes %d\n", sid);
+
+ return ret;
+}
+
+static int rtsds_phy_set_mode(struct phy *phy, enum phy_mode mode, int submode)
+{
+ struct rtsds_macro *macro = phy_get_drvdata(phy);
+ struct rtsds_ctrl *ctrl = macro->ctrl;
+ u32 sid = macro->sid;
+
+ if (rtsds_readonly(ctrl, sid))
+ return 0;
+
+ if (mode != PHY_MODE_ETHERNET)
+ return -EINVAL;
+
+ return rtsds_phy_set_mode_int(ctrl, sid, submode, ctrl->conf->mode_map[submode]);
+}
+
+static int rtsds_phy_reset_int(struct rtsds_ctrl *ctrl, u32 sid)
+{
+ int ret;
+
+ mutex_lock(&ctrl->lock);
+ ret = ctrl->conf->reset(ctrl, sid);
+ mutex_unlock(&ctrl->lock);
+
+ if (ret)
+ dev_err(ctrl->dev, "reset failed for SerDes %d\n", sid);
+
+ return ret;
+}
+
+static int rtsds_phy_reset(struct phy *phy)
+{
+ struct rtsds_macro *macro = phy_get_drvdata(phy);
+ struct rtsds_ctrl *ctrl = macro->ctrl;
+ u32 sid = macro->sid;
+
+ if (rtsds_readonly(ctrl, sid))
+ return 0;
+
+ return rtsds_phy_reset_int(ctrl, sid);
+}
+
+static const struct phy_ops rtsds_phy_ops = {
+ .init = rtsds_phy_init,
+ .power_on = rtsds_phy_power_on,
+ .power_off = rtsds_phy_power_off,
+ .reset = rtsds_phy_reset,
+ .set_mode = rtsds_phy_set_mode,
+ .owner = THIS_MODULE,
+};
+
+/*
+ * The SerDes offer a lot of magic that sill needs to be uncovered. To help further development
+ * provide some basic debugging about registers, modes and polarity. The mode can be changed on
+ * the fly and executes the normal setter including events.
+ */
+
+#ifdef CONFIG_DEBUG_FS
+
+#define RTSDS_PAGE_NAMES 48
+
+static const char *rtsds_page_name[RTSDS_PAGE_NAMES] = {
+ [0] = "SDS", [1] = "SDS_EXT",
+ [2] = "FIB", [3] = "FIB_EXT",
+ [4] = "DTE", [5] = "DTE_EXT",
+ [6] = "TGX", [7] = "TGX_EXT",
+ [8] = "ANA_RG", [9] = "ANA_RG_EXT",
+ [10] = "ANA_TG", [11] = "ANA_TG_EXT",
+ [31] = "ANA_WDIG",
+ [32] = "ANA_MISC", [33] = "ANA_COM",
+ [34] = "ANA_SP", [35] = "ANA_SP_EXT",
+ [36] = "ANA_1G", [37] = "ANA_1G_EXT",
+ [38] = "ANA_2G", [39] = "ANA_2G_EXT",
+ [40] = "ANA_3G", [41] = "ANA_3G_EXT",
+ [42] = "ANA_5G", [43] = "ANA_5G_EXT",
+ [44] = "ANA_6G", [45] = "ANA_6G_EXT",
+ [46] = "ANA_10G", [47] = "ANA_10G_EXT",
+};
+
+static ssize_t rtsds_dbg_mode_show(struct seq_file *seqf, void *unused)
+{
+ struct rtsds_macro *macro = dev_get_drvdata(seqf->private);
+ struct rtsds_ctrl *ctrl = macro->ctrl;
+ int mode, sid = macro->sid;
+
+ mutex_lock(&ctrl->lock);
+ mode = ctrl->conf->get_mode(ctrl, sid);
+ mutex_unlock(&ctrl->lock);
+
+ seq_printf(seqf, "hw mode: 0x%X\n", mode);
+ seq_puts(seqf, "phy mode: ");
+
+ if (ctrl->sds[sid].mode == PHY_INTERFACE_MODE_NA)
+ seq_puts(seqf, "off\n");
+ else
+ seq_printf(seqf, "%s\n", phy_modes(ctrl->sds[sid].mode));
+
+ return 0;
+}
+
+static ssize_t rtsds_dbg_mode_write(struct file *file, const char __user *userbuf,
+ size_t count, loff_t *ppos)
+{
+ struct seq_file *seqf = file->private_data;
+ struct rtsds_macro *macro = dev_get_drvdata(seqf->private);
+ struct rtsds_ctrl *ctrl = macro->ctrl;
+ int ret, hwmode, phymode, sid = macro->sid;
+
+ ret = kstrtou32_from_user(userbuf, count, 16, &hwmode);
+ if (ret)
+ return ret;
+ /*
+ * Allow to set arbitrary modes into the SerDes to improve error analysis. Accept that
+ * this might confuse the internal state tracking.
+ */
+ phymode = rtsds_hwmode_to_phymode(ctrl, hwmode);
+ rtsds_phy_set_mode_int(ctrl, sid, phymode, hwmode);
+
+ return count;
+}
+DEFINE_SHOW_STORE_ATTRIBUTE(rtsds_dbg_mode);
+
+static ssize_t rtsds_dbg_reset_show(struct seq_file *seqf, void *unused)
+{
+ return 0;
+}
+
+static ssize_t rtsds_dbg_reset_write(struct file *file, const char __user *userbuf,
+ size_t count, loff_t *ppos)
+{
+ struct seq_file *seqf = file->private_data;
+ struct rtsds_macro *macro = dev_get_drvdata(seqf->private);
+ struct rtsds_ctrl *ctrl = macro->ctrl;
+ int ret, reset, sid = macro->sid;
+
+ ret = kstrtou32_from_user(userbuf, count, 10, &reset);
+ if (ret || reset != 1)
+ return ret;
+
+ rtsds_phy_reset_int(ctrl, sid);
+
+ return count;
+}
+DEFINE_SHOW_STORE_ATTRIBUTE(rtsds_dbg_reset);
+
+static int rtsds_dbg_registers_show(struct seq_file *seqf, void *unused)
+{
+ struct rtsds_macro *macro = dev_get_drvdata(seqf->private);
+ struct rtsds_ctrl *ctrl = macro->ctrl;
+ u32 page = 0, reg, sid = macro->sid;
+
+ seq_printf(seqf, "%*s", 12, "");
+ for (int i = 0; i < 32; i++)
+ seq_printf(seqf, " %02X", i);
+
+ while (page < ctrl->conf->page_cnt) {
+ if (page < RTSDS_PAGE_NAMES && rtsds_page_name[page])
+ seq_printf(seqf, "\n%*s: ", -11, rtsds_page_name[page]);
+ else if (page == 64 || page == 128)
+ seq_printf(seqf, "\n\nXGMII_%d : ", page >> 8);
+ else
+ seq_printf(seqf, "\nPAGE_%03d : ", page);
+ for (reg = 0; reg < 32; reg++)
+ seq_printf(seqf, "%04X ", ctrl->conf->read(ctrl, sid, page, reg));
+
+ page++;
+ }
+ seq_puts(seqf, "\n");
+
+ return 0;
+}
+DEFINE_SHOW_ATTRIBUTE(rtsds_dbg_registers);
+
+static int rtsds_dbg_polarity_show(struct seq_file *seqf, void *unused)
+{
+ struct rtsds_macro *macro = dev_get_drvdata(seqf->private);
+ struct rtsds_ctrl *ctrl = macro->ctrl;
+ u32 reg, sid = macro->sid;
+
+ reg = ctrl->conf->read(ctrl, sid, RTSDS_PAGE_SDS, 0);
+
+ seq_puts(seqf, "tx polarity: ");
+ seq_puts(seqf, reg & RTSDS_BITS_INV_HSO ? "inverse" : "normal");
+ seq_puts(seqf, "\nrx polarity: ");
+ seq_puts(seqf, reg & RTSDS_BITS_INV_HSI ? "inverse" : "normal");
+ seq_puts(seqf, "\n");
+
+ return 0;
+}
+DEFINE_SHOW_ATTRIBUTE(rtsds_dbg_polarity);
+
+static void rtsds_dbg_init(struct rtsds_ctrl *ctrl, u32 sid)
+{
+ debugfs_create_file("mode", 0600, ctrl->sds[sid].phy->debugfs,
+ &ctrl->sds[sid].phy->dev, &rtsds_dbg_mode_fops);
+
+ debugfs_create_file("reset", 0200, ctrl->sds[sid].phy->debugfs,
+ &ctrl->sds[sid].phy->dev, &rtsds_dbg_reset_fops);
+
+ debugfs_create_file("polarity", 0400, ctrl->sds[sid].phy->debugfs,
+ &ctrl->sds[sid].phy->dev, &rtsds_dbg_polarity_fops);
+
+ debugfs_create_file("registers", 0400, ctrl->sds[sid].phy->debugfs,
+ &ctrl->sds[sid].phy->dev, &rtsds_dbg_registers_fops);
+}
+#endif /* CONFIG_DEBUG_FS */
+
+static void rtsds_setup(struct rtsds_ctrl *ctrl)
+{
+ int hwmode, ret;
+
+ for (u32 sid = 0; sid < ctrl->conf->sds_cnt; sid++) {
+ if (ctrl->sds_mask & BIT(sid)) {
+ /* power off controlled SerDes */
+ hwmode = ctrl->conf->mode_map[PHY_INTERFACE_MODE_NA];
+ ret = ctrl->conf->set_mode(ctrl, sid, hwmode);
+ if (!ret)
+ ret = rtsds_run_event(ctrl, sid, RTSDS_EVENT_SETUP);
+ if (ret)
+ dev_err(ctrl->dev, "setup failed for SerDes %d\n", sid);
+ }
+ /* in any case sync back hardware status */
+ hwmode = ctrl->conf->get_mode(ctrl, sid);
+ ctrl->sds[sid].mode = rtsds_hwmode_to_phymode(ctrl, hwmode);
+ }
+}
+
+static struct phy *rtsds_simple_xlate(struct device *dev,
+ const struct of_phandle_args *args)
+{
+ struct rtsds_ctrl *ctrl = dev_get_drvdata(dev);
+ int sid, sid2, min_port, max_port;
+
+ /*
+ * Some Realtek Ethernet transceivers (e.g. RLT8218B) will be attached via a bonded 2x
+ * QSGMII link to two SerDes. Others (e.g. RTL8218D) allow to make use of single XGMII or
+ * dual QSGMII links. When a switch port tries to lookup the SerDes it is attached to
+ * honour that by an enhanced mapping. Allow two possible configuration options. Either
+ * standalone or linked to another. E.g.
+ *
+ * Single: port@24 { phys = <&serdes 4 -1 MinPort MaxPort>; };
+ * Dual: port@24 { phys = <&serdes 4 5 MinPort MaxPort>; };
+ *
+ * This function will return the primary PHY of the link. The secondary can be identified
+ * later on by the link attribute in the controller structure.
+ */
+
+ if (args->args_count != 4)
+ return ERR_PTR(-EINVAL);
+
+ sid = args->args[0];
+ if (sid < 0 || sid >= ctrl->conf->sds_cnt)
+ return ERR_PTR(-EINVAL);
+
+ sid2 = args->args[1];
+ if (sid2 < -1 || sid2 >= ctrl->conf->sds_cnt)
+ return ERR_PTR(-EINVAL);
+
+ /*
+ * Additionally to a linked SerDes also get the ports whose traffic is going through this
+ * SerDes. As of now the driver does not care about that but later on it will be helpful.
+ */
+
+ min_port = args->args[2];
+ if (min_port < 0)
+ return ERR_PTR(-EINVAL);
+
+ max_port = args->args[3];
+ if (max_port < min_port)
+ return ERR_PTR(-EINVAL);
+
+ ctrl->sds[sid].link = sid2;
+ if (sid2 >= 0)
+ ctrl->sds[sid2].link = sid;
+
+ ctrl->sds[sid].min_port = min_port;
+ ctrl->sds[sid].max_port = max_port;
+
+ return ctrl->sds[sid].phy;
+}
+
+static int rtsds_phy_create(struct rtsds_ctrl *ctrl, u32 sid)
+{
+ struct rtsds_macro *macro;
+
+ ctrl->sds[sid].phy = devm_phy_create(ctrl->dev, NULL, &rtsds_phy_ops);
+ if (IS_ERR(ctrl->sds[sid].phy))
+ return PTR_ERR(ctrl->sds[sid].phy);
+
+ macro = devm_kzalloc(ctrl->dev, sizeof(*macro), GFP_KERNEL);
+ if (!macro)
+ return -ENOMEM;
+
+ macro->sid = sid;
+ macro->ctrl = ctrl;
+ phy_set_drvdata(ctrl->sds[sid].phy, macro);
+
+ ctrl->sds[sid].link = -1;
+ ctrl->sds[sid].min_port = -1;
+ ctrl->sds[sid].max_port = -1;
+
+#ifdef CONFIG_DEBUG_FS
+ rtsds_dbg_init(ctrl, sid);
+#endif
+ return 0;
+}
+
+static int rtsds_probe(struct platform_device *pdev)
+{
+ struct device_node *np = pdev->dev.of_node;
+ struct device *dev = &pdev->dev;
+ struct phy_provider *provider;
+ struct rtsds_ctrl *ctrl;
+ int ret;
+
+ if (!np)
+ return -EINVAL;
+
+ ctrl = devm_kzalloc(dev, sizeof(*ctrl), GFP_KERNEL);
+ if (!ctrl)
+ return -ENOMEM;
+
+ ctrl->base = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(ctrl->base)) {
+ dev_err(dev, "failed to map SerDes memory\n");
+ return PTR_ERR(ctrl->base);
+ }
+
+ ctrl->dev = dev;
+ ctrl->conf = (struct rtsds_conf *)of_device_get_match_data(dev);
+
+ ret = of_property_read_u32(np, "realtek,controlled-ports", &ctrl->sds_mask);
+ if (ret)
+ ctrl->sds_mask = GENMASK(ctrl->conf->sds_cnt, 0);
+
+ for (u32 sid = 0; sid < ctrl->conf->sds_cnt; sid++) {
+ ret = rtsds_phy_create(ctrl, sid);
+ if (ret) {
+ dev_err(dev, "failed to create PHY for SerDes %d\n", sid);
+ return ret;
+ }
+ }
+
+ mutex_init(&ctrl->lock);
+ dev_set_drvdata(dev, ctrl);
+ provider = devm_of_phy_provider_register(dev, rtsds_simple_xlate);
+ rtsds_setup(ctrl);
+ dev_info(dev, "initialized (%d SerDes, %d pages, 32 registers, mask 0x%04x)",
+ ctrl->conf->sds_cnt, ctrl->conf->page_cnt, ctrl->sds_mask);
+
+ return PTR_ERR_OR_ZERO(provider);
+}
+
+#define MSK_ALL(a, b, c, d, e) { RTSDS_SEQ_MASK, PHY_INTERFACE_MODE_NA, a, b, c, d, e }
+#define MSK_QSG(a, b, c, d, e) { RTSDS_SEQ_MASK, PHY_INTERFACE_MODE_QSGMII, a, b, c, d, e }
+#define WAIT_MS(v) { RTSDS_SEQ_WAIT, 0, 0, 0, 0, v, 0 }
+#define END_SEQ { RTSDS_SEQ_STOP, 0, 0, 0, 0, 0, 0 }
+
+static struct rtsds_seq rtsds_838x_seq_setup[] = {
+ WAIT_MS(1),
+ /* all ports */
+ MSK_ALL(0x003f, 0x02, 0x19, 0x0303, 0xffff), MSK_ALL(0x003f, 0x01, 0x02, 0x85fa, 0xffff),
+ /* ports 0-3 */
+ MSK_ALL(0x0005, 0x01, 0x11, 0xb7c9, 0xffff), MSK_ALL(0x000a, 0x01, 0x11, 0x4208, 0xffff),
+ MSK_ALL(0x0005, 0x01, 0x12, 0xab8e, 0xffff), MSK_ALL(0x000a, 0x01, 0x12, 0xc208, 0xffff),
+ MSK_ALL(0x0005, 0x01, 0x13, 0x24ab, 0xffff), MSK_ALL(0x0001, 0x01, 0x03, 0xf46f, 0xffff),
+ MSK_ALL(0x0002, 0x01, 0x0a, 0x80c7, 0xffff), MSK_ALL(0x0004, 0x01, 0x03, 0xf46d, 0xffff),
+ MSK_ALL(0x000f, 0x01, 0x0b, 0x0482, 0xffff), MSK_ALL(0x000f, 0x01, 0x0e, 0xfcc2, 0xffff),
+ MSK_ALL(0x000f, 0x00, 0x01, 0x0f00, 0xffff), MSK_ALL(0x000f, 0x00, 0x02, 0x7060, 0xffff),
+ MSK_ALL(0x000f, 0x01, 0x06, 0x20d8, 0xffff),
+ /* port 4 */
+ MSK_ALL(0x0010, 0x01, 0x06, 0x20d8, 0xffff), MSK_ALL(0x0010, 0x01, 0x0a, 0x00c3, 0xffff),
+ MSK_ALL(0x0010, 0x01, 0x0b, 0x1482, 0xffff), MSK_ALL(0x0010, 0x01, 0x0e, 0xfcc2, 0xffff),
+ MSK_ALL(0x0010, 0x01, 0x11, 0xb7c9, 0xffff), MSK_ALL(0x0010, 0x01, 0x12, 0xab8e, 0xffff),
+ /* port 5 */
+ MSK_ALL(0x0020, 0x01, 0x03, 0x0000, 0xffff), MSK_ALL(0x0020, 0x01, 0x04, 0xdccc, 0xffff),
+ MSK_ALL(0x0020, 0x01, 0x05, 0x0000, 0xffff), MSK_ALL(0x0020, 0x01, 0x06, 0x3600, 0xffff),
+ MSK_ALL(0x0020, 0x01, 0x07, 0x0003, 0xffff), MSK_ALL(0x0020, 0x01, 0x08, 0x79aa, 0xffff),
+ MSK_ALL(0x0020, 0x01, 0x09, 0x8c64, 0xffff), MSK_ALL(0x0020, 0x01, 0x0a, 0x00c3, 0xffff),
+ MSK_ALL(0x0020, 0x01, 0x0b, 0x1482, 0xffff), MSK_ALL(0x0020, 0x01, 0x0e, 0xf002, 0xffff),
+ MSK_ALL(0x0020, 0x02, 0x1b, 0x04bf, 0xffff), MSK_ALL(0x0020, 0x02, 0x18, 0x14aa, 0xffff),
+ MSK_ALL(0x0020, 0x02, 0x1b, 0x04bf, 0xffff), END_SEQ,
+};
+
+static struct rtsds_seq rtsds_839x_seq_setup[] = {
+ /* ports 0-7, 10-11 (5G) */
+ MSK_ALL(0x0cff, 0x08, 0x11, 0x0000, 0x8000), MSK_ALL(0x0cff, 0x08, 0x11, 0x1000, 0x7000),
+ MSK_ALL(0x0cff, 0x08, 0x11, 0x0400, 0x0e00), MSK_ALL(0x0cff, 0x08, 0x11, 0x00c0, 0x01c0),
+ MSK_ALL(0x0cff, 0x08, 0x16, 0x0000, 0x8000), MSK_ALL(0x0cff, 0x08, 0x08, 0x0000, 0x0008),
+ MSK_ALL(0x0cff, 0x08, 0x07, 0x0000, 0x0200), MSK_ALL(0x0cff, 0x08, 0x07, 0x0000, 0x0100),
+ MSK_ALL(0x0cff, 0x08, 0x14, 0x0002, 0x0002), MSK_ALL(0x0cff, 0x08, 0x15, 0xc000, 0xf000),
+ MSK_ALL(0x0cff, 0x08, 0x16, 0x0000, 0x1000), MSK_ALL(0x0cff, 0x08, 0x18, 0x0006, 0x003f),
+ MSK_ALL(0x0cff, 0x08, 0x08, 0x0000, 0x0040), MSK_ALL(0x0cff, 0x08, 0x08, 0x0000, 0x0800),
+ MSK_ALL(0x0cff, 0x08, 0x08, 0x8000, 0xf000), MSK_ALL(0x0cff, 0x08, 0x08, 0x0400, 0x0780),
+ /* ports 10-11 (clock edge) ports 4, 10 (full swing)) */
+ MSK_ALL(0x0c00, 0x00, 0x07, 0x4000, 0x4000), MSK_ALL(0x0410, 0x08, 0x08, 0x8c6a, 0xffff),
+ /* ports 8-9, 12-13 (10G digital patch) */
+ MSK_ALL(0x3300, 0x0a, 0x00, 0x5800, 0xffff), MSK_ALL(0x3300, 0x0a, 0x01, 0x4000, 0xffff),
+ MSK_ALL(0x1100, 0x0a, 0x02, 0x5400, 0xffff), MSK_ALL(0x2200, 0x0a, 0x02, 0x5000, 0xffff),
+ MSK_ALL(0x3300, 0x0a, 0x03, 0x0000, 0xffff), MSK_ALL(0x3300, 0x0a, 0x04, 0x0000, 0xffff),
+ MSK_ALL(0x3300, 0x0a, 0x05, 0x4000, 0xffff), MSK_ALL(0x3300, 0x0a, 0x06, 0x4000, 0xffff),
+ MSK_ALL(0x3300, 0x0a, 0x07, 0xffff, 0xffff), MSK_ALL(0x3300, 0x0a, 0x08, 0xffff, 0xffff),
+ MSK_ALL(0x3300, 0x0a, 0x09, 0x806f, 0xffff), MSK_ALL(0x3300, 0x0a, 0x0a, 0x0004, 0xffff),
+ MSK_ALL(0x3300, 0x0a, 0x0b, 0x0000, 0xffff), MSK_ALL(0x3300, 0x0a, 0x0c, 0x0000, 0xffff),
+ MSK_ALL(0x3300, 0x0a, 0x0d, 0x0000, 0xffff), MSK_ALL(0x3300, 0x0a, 0x0e, 0x0a00, 0xffff),
+ MSK_ALL(0x3300, 0x0a, 0x0f, 0x2000, 0xffff), MSK_ALL(0x3300, 0x0a, 0x10, 0xf00e, 0xffff),
+ MSK_ALL(0x1100, 0x0a, 0x11, 0xf04a, 0xffff), MSK_ALL(0x2200, 0x0a, 0x11, 0xfdab, 0xffff),
+ MSK_ALL(0x1100, 0x0a, 0x12, 0x97b3, 0xffff), MSK_ALL(0x2200, 0x0a, 0x12, 0x96ea, 0xffff),
+ MSK_ALL(0x3300, 0x0a, 0x13, 0x5318, 0xffff), MSK_ALL(0x3300, 0x0a, 0x14, 0x0f03, 0xffff),
+ MSK_ALL(0x3300, 0x0a, 0x15, 0x0000, 0xffff), MSK_ALL(0x3300, 0x0a, 0x16, 0x0000, 0xffff),
+ MSK_ALL(0x3300, 0x0a, 0x17, 0x0000, 0xffff), MSK_ALL(0x3300, 0x0a, 0x18, 0x0000, 0xffff),
+ MSK_ALL(0x3300, 0x0a, 0x19, 0x0000, 0xffff), MSK_ALL(0x3300, 0x0a, 0x1a, 0xffff, 0xffff),
+ MSK_ALL(0x3300, 0x0a, 0x1b, 0x0000, 0xffff), MSK_ALL(0x3300, 0x0a, 0x1c, 0x1203, 0xffff),
+ MSK_ALL(0x3300, 0x0a, 0x1d, 0x0000, 0xffff), MSK_ALL(0x3300, 0x0a, 0x1e, 0xa052, 0xffff),
+ MSK_ALL(0x3300, 0x0a, 0x1f, 0x9a00, 0xffff), MSK_ALL(0x3300, 0x0b, 0x00, 0x00f5, 0xffff),
+ MSK_ALL(0x3300, 0x0b, 0x01, 0xf000, 0xffff), MSK_ALL(0x1100, 0x0b, 0x02, 0x41ff, 0xffff),
+ MSK_ALL(0x2200, 0x0b, 0x02, 0x4079, 0xffff), MSK_ALL(0x3300, 0x0b, 0x03, 0x0000, 0xffff),
+ MSK_ALL(0x1100, 0x0b, 0x04, 0x39ff, 0xffff), MSK_ALL(0x2200, 0x0b, 0x04, 0x93fa, 0xffff),
+ MSK_ALL(0x3300, 0x0b, 0x05, 0x3340, 0xffff), MSK_ALL(0x1100, 0x0b, 0x06, 0x40aa, 0xffff),
+ MSK_ALL(0x2200, 0x0b, 0x06, 0x4280, 0xffff), MSK_ALL(0x3300, 0x0b, 0x07, 0x0000, 0xffff),
+ MSK_ALL(0x3300, 0x0b, 0x08, 0x801f, 0xffff), MSK_ALL(0x3300, 0x0b, 0x09, 0x0000, 0xffff),
+ MSK_ALL(0x3300, 0x0b, 0x0a, 0x619c, 0xffff), MSK_ALL(0x3300, 0x0b, 0x0b, 0xffed, 0xffff),
+ MSK_ALL(0x3300, 0x0b, 0x0c, 0x29ff, 0xffff), MSK_ALL(0x3300, 0x0b, 0x0d, 0x29ff, 0xffff),
+ MSK_ALL(0x1100, 0x0b, 0x0e, 0x4e10, 0xffff), MSK_ALL(0x2200, 0x0b, 0x0e, 0x4c50, 0xffff),
+ MSK_ALL(0x1100, 0x0b, 0x0f, 0x4e10, 0xffff), MSK_ALL(0x2200, 0x0b, 0x0f, 0x4c50, 0xffff),
+ MSK_ALL(0x3300, 0x0b, 0x10, 0x0000, 0xffff), MSK_ALL(0x3300, 0x0b, 0x11, 0x0000, 0xffff),
+ MSK_ALL(0x3300, 0x00, 0x0c, 0x08ec, 0xffff), MSK_ALL(0x2200, 0x0b, 0x1f, 0x003f, 0xffff),
+ MSK_ALL(0x3300, 0x00, 0x07, 0x4000, 0x4000),
+ /* ports 8-9, 12-13 (10G analog patch) */
+ MSK_ALL(0x3300, 0x0b, 0x09, 0x417f, 0xffff), MSK_ALL(0x3300, 0x0a, 0x1c, 0x0000, 0x0200),
+ MSK_ALL(0x3300, 0x0a, 0x1c, 0x0000, 0x1c00), MSK_ALL(0x3300, 0x0a, 0x1c, 0x0028, 0x0038),
+ MSK_ALL(0x3300, 0x0a, 0x1c, 0x0000, 0x01c0), MSK_ALL(0x3300, 0x0a, 0x1c, 0x0002, 0x0007),
+ MSK_ALL(0x3300, 0x0b, 0x01, 0xc440, 0xffff), MSK_ALL(0x1100, 0x0b, 0x06, 0x0000, 0x0008),
+ MSK_ALL(0x3300, 0x0a, 0x05, 0x8000, 0xffff), MSK_ALL(0x3300, 0x0a, 0x06, 0x8000, 0xffff),
+ MSK_ALL(0x3300, 0x0a, 0x0a, 0x0000, 0xffff), MSK_ALL(0x3300, 0x0a, 0x1e, 0x0002, 0xffff),
+ MSK_ALL(0x3300, 0x0a, 0x1f, 0xbe00, 0xffff), MSK_ALL(0x1100, 0x0b, 0x0e, 0x0000, 0x0400),
+ MSK_ALL(0x1100, 0x0b, 0x0f, 0x0000, 0x0400), MSK_ALL(0x1100, 0x0b, 0x0e, 0x0000, 0x4000),
+ MSK_ALL(0x1100, 0x0b, 0x0f, 0x0000, 0x4000), MSK_ALL(0x3300, 0x0a, 0x10, 0x0000, 0x0020),
+ MSK_ALL(0x3300, 0x0b, 0x09, 0x0000, 0x0100), MSK_ALL(0x3300, 0x0a, 0x03, 0xf000, 0xf000),
+ MSK_ALL(0x3300, 0x0a, 0x1f, 0x3000, 0x3000), MSK_ALL(0x3300, 0x0a, 0x1f, 0x0e00, 0x0e00),
+ MSK_ALL(0x3300, 0x0b, 0x01, 0x8000, 0x8000), MSK_ALL(0x3300, 0x0b, 0x01, 0x4000, 0x4000),
+ MSK_ALL(0x3300, 0x0b, 0x01, 0x0000, 0x2000), MSK_ALL(0x3300, 0x0b, 0x01, 0x0000, 0x1000),
+ MSK_ALL(0x3300, 0x0b, 0x01, 0x0400, 0x0e00), MSK_ALL(0x3300, 0x0b, 0x01, 0x0080, 0x01c0),
+ MSK_ALL(0x3300, 0x0b, 0x01, 0x0000, 0x0038), MSK_ALL(0x3300, 0x0b, 0x01, 0x0000, 0x0007),
+ MSK_ALL(0x3300, 0x0b, 0x0c, 0x0200, 0x0200), MSK_ALL(0x3300, 0x0b, 0x0d, 0x0200, 0x0200),
+ MSK_ALL(0x3300, 0x0b, 0x08, 0x0020, 0x0020), MSK_ALL(0x3300, 0x0b, 0x08, 0x0000, 0x0040),
+ MSK_ALL(0x3300, 0x0a, 0x1c, 0x0000, 0x8000), MSK_ALL(0x3300, 0x0a, 0x10, 0x0000, 0xf000),
+ MSK_ALL(0x3300, 0x0a, 0x13, 0x0000, 0x0010), MSK_ALL(0x3300, 0x0a, 0x13, 0x0000, 0x0200),
+ MSK_ALL(0x3300, 0x0a, 0x13, 0x0008, 0x000f), MSK_ALL(0x3300, 0x0a, 0x13, 0x0100, 0x01e0),
+ END_SEQ,
+};
+
+static const struct rtsds_conf rtsds_838x_conf = {
+ .sds_cnt = RTSDS_838X_SDS_CNT,
+ .page_cnt = RTSDS_838X_PAGE_CNT,
+ .mask = rtsds_838x_mask,
+ .read = rtsds_838x_read,
+ .reset = rtsds_838x_reset,
+ .set_mode = rtsds_838x_set_mode,
+ .get_mode = rtsds_838x_get_mode,
+ .mode_map = {
+ [PHY_INTERFACE_MODE_NA] = RTSDS_COMBOMODE(0x00, 0x00),
+ [PHY_INTERFACE_MODE_1000BASEX] = RTSDS_COMBOMODE(0x04, 0x01),
+ [PHY_INTERFACE_MODE_100BASEX] = RTSDS_COMBOMODE(0x05, 0x01),
+ [PHY_INTERFACE_MODE_QSGMII] = RTSDS_COMBOMODE(0x06, 0x00),
+ },
+ .sequence = {
+ [RTSDS_EVENT_SETUP] = rtsds_838x_seq_setup,
+ }
+};
+
+static const struct rtsds_conf rtsds_839x_conf = {
+ .sds_cnt = RTSDS_839X_SDS_CNT,
+ .page_cnt = RTSDS_839X_PAGE_CNT,
+ .mask = rtsds_839x_mask,
+ .read = rtsds_839x_read,
+ .reset = rtsds_839x_reset,
+ .set_mode = rtsds_839x_set_mode,
+ .get_mode = rtsds_839x_get_mode,
+ .mode_map = {
+ [PHY_INTERFACE_MODE_NA] = RTSDS_COMBOMODE(0x00, 0x00),
+ [PHY_INTERFACE_MODE_10GBASER] = RTSDS_COMBOMODE(0x01, 0x00),
+ [PHY_INTERFACE_MODE_1000BASEX] = RTSDS_COMBOMODE(0x07, 0x00),
+ [PHY_INTERFACE_MODE_100BASEX] = RTSDS_COMBOMODE(0x08, 0x00),
+ [PHY_INTERFACE_MODE_QSGMII] = RTSDS_COMBOMODE(0x06, 0x00),
+ [PHY_INTERFACE_MODE_SGMII] = RTSDS_COMBOMODE(0x07, 0x05),
+ },
+ .sequence = {
+ [RTSDS_EVENT_SETUP] = rtsds_839x_seq_setup,
+ }
+};
+
+static const struct rtsds_conf rtsds_930x_conf = {
+ .sds_cnt = RTSDS_930X_SDS_CNT,
+ .page_cnt = RTSDS_930X_PAGE_CNT,
+ .mask = rtsds_930x_mask,
+ .read = rtsds_930x_read,
+ .reset = rtsds_930x_reset,
+ .set_mode = rtsds_930x_set_mode,
+ .get_mode = rtsds_930x_get_mode,
+ .mode_map = {
+ [PHY_INTERFACE_MODE_NA] = RTSDS_COMBOMODE(0x1f, 0x00),
+ [PHY_INTERFACE_MODE_10GBASER] = RTSDS_COMBOMODE(0x1a, 0x00),
+ [PHY_INTERFACE_MODE_2500BASEX] = RTSDS_COMBOMODE(0x16, 0x00),
+ [PHY_INTERFACE_MODE_1000BASEX] = RTSDS_COMBOMODE(0x04, 0x00),
+ [PHY_INTERFACE_MODE_USXGMII] = RTSDS_COMBOMODE(0x0d, 0x00),
+ [PHY_INTERFACE_MODE_QUSGMII] = RTSDS_COMBOMODE(0x0d, 0x02),
+ [PHY_INTERFACE_MODE_QSGMII] = RTSDS_COMBOMODE(0x06, 0x00),
+ },
+ .sequence = {
+ [RTSDS_EVENT_SETUP] = NULL,
+ }
+};
+
+static const struct rtsds_conf rtsds_931x_conf = {
+ .sds_cnt = RTSDS_931X_SDS_CNT,
+ .page_cnt = RTSDS_931X_PAGE_CNT,
+ .mask = rtsds_931x_mask,
+ .read = rtsds_931x_read,
+ .reset = rtsds_931x_reset,
+ .set_mode = rtsds_931x_set_mode,
+ .get_mode = rtsds_931x_get_mode,
+ .mode_map = {
+ [PHY_INTERFACE_MODE_NA] = RTSDS_COMBOMODE(0x1f, 0x3f),
+ [PHY_INTERFACE_MODE_10GBASER] = RTSDS_COMBOMODE(0x1f, 0x35),
+ [PHY_INTERFACE_MODE_1000BASEX] = RTSDS_COMBOMODE(0x1f, 0x39),
+ [PHY_INTERFACE_MODE_USXGMII] = RTSDS_COMBOMODE(0x0d, 0x00),
+ [PHY_INTERFACE_MODE_XGMII] = RTSDS_COMBOMODE(0x0a, 0x00),
+ [PHY_INTERFACE_MODE_QSGMII] = RTSDS_COMBOMODE(0x06, 0x00),
+ },
+ .sequence = {
+ [RTSDS_EVENT_SETUP] = NULL,
+ }
+};
+
+static const struct of_device_id rtsds_compatible_ids[] = {
+ { .compatible = "realtek,rtl8380-serdes",
+ .data = &rtsds_838x_conf,
+ },
+ { .compatible = "realtek,rtl8390-serdes",
+ .data = &rtsds_839x_conf,
+ },
+ { .compatible = "realtek,rtl9300-serdes",
+ .data = &rtsds_930x_conf,
+ },
+ { .compatible = "realtek,rtl9310-serdes",
+ .data = &rtsds_931x_conf,
+ },
+ {},
+};
+MODULE_DEVICE_TABLE(of, rtsds_compatible_ids);
+
+static struct platform_driver rtsds_platform_driver = {
+ .probe = rtsds_probe,
+ .driver = {
+ .name = "realtek,otto-serdes",
+ .of_match_table = of_match_ptr(rtsds_compatible_ids),
+ },
+};
+
+module_platform_driver(rtsds_platform_driver);
+
+MODULE_AUTHOR("Markus Stockhausen <markus.stockhausen@gmx.de>");
+MODULE_DESCRIPTION("SerDes driver for Realtek RTL83xx, RTL93xx switch SoCs");
+MODULE_LICENSE("GPL");
diff --git a/drivers/phy/realtek/phy-rtk-otto-serdes.h b/drivers/phy/realtek/phy-rtk-otto-serdes.h
new file mode 100644
index 000000000000..f1566d9393c6
--- /dev/null
+++ b/drivers/phy/realtek/phy-rtk-otto-serdes.h
@@ -0,0 +1,117 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Realtek RTL838x, RTL839x, RTL930x & RTL931x SerDes PHY driver
+ * Copyright (c) 2024 Markus Stockhausen <markus.stockhausen@gmx.de>
+ */
+
+#ifndef _PHY_RTK_OTTO_SERDES_H
+#define _PHY_RTK_OTTO_SERDES_H
+
+#define RTSDS_SWITCH_ADDR_BASE (0xbb000000)
+#define RTSDS_REG(x) ((void __iomem __force *)RTSDS_SWITCH_ADDR_BASE + (x))
+#define iomask32(mask, value, addr) iowrite32((ioread32(addr) & ~(mask)) | (value), addr)
+
+#define RTSDS_PAGE_SDS 0x00
+#define RTSDS_PAGE_SDS_EXT 0x01
+#define RTSDS_PAGE_FIB 0x02
+#define RTSDS_PAGE_FIB_EXT 0x03
+
+#define RTSDS_BITS_INV_HSO BIT(8)
+#define RTSDS_BITS_INV_HSI BIT(9)
+#define RTSDS_BITS_SOFT_RST BIT(6)
+#define RTSDS_BITS_SDS_EN GENMASK(1, 0)
+
+#define RTSDS_EVENT_SETUP 0
+#define RTSDS_EVENT_CNT 1
+
+#define RTSDS_SEQ_STOP 0
+#define RTSDS_SEQ_MASK 1
+#define RTSDS_SEQ_WAIT 2
+
+#define RTSDS_838X_SDS_CNT 6
+#define RTSDS_838X_PAGE_CNT 4
+#define RTSDS_838X_SDS_MODE_SEL RTSDS_REG(0x0028)
+#define RTSDS_838X_INT_MODE_CTRL RTSDS_REG(0x005c)
+
+#define RTSDS_839X_SDS_CNT 14
+#define RTSDS_839X_PAGE_CNT 12
+#define RTSDS_839X_MAC_SERDES_IF_CTRL RTSDS_REG(0x0008)
+
+#define RTSDS_930X_SDS_CNT 12
+#define RTSDS_930X_PAGE_CNT 64
+#define RTSDS_930X_SDS_MODE_SEL_0 RTSDS_REG(0x0194)
+#define RTSDS_930X_SDS_MODE_SEL_1 RTSDS_REG(0x02a0)
+#define RTSDS_930X_SDS_MODE_SEL_2 RTSDS_REG(0x02a4)
+#define RTSDS_930X_SDS_MODE_SEL_3 RTSDS_REG(0x0198)
+#define RTSDS_930X_SDS_SUBMODE_CTRL0 RTSDS_REG(0x01cc)
+#define RTSDS_930X_SDS_SUBMODE_CTRL1 RTSDS_REG(0x02d8)
+
+#define RTSDS_931X_SDS_CNT 14
+#define RTSDS_931X_PAGE_CNT 192
+#define RTSDS_931X_SERDES_MODE_CTRL RTSDS_REG(0x13cc)
+#define RTSDS_931X_PS_SERDES_OFF_MODE_CTRL RTSDS_REG(0x13f4)
+#define RTSDS_931X_SDS_FORCE_SETUP 0x80
+
+#define RTSDS_93XX_SDS_READ 0x1
+#define RTSDS_93XX_SDS_WRITE 0x3
+#define RTSDS_93XX_SDS_BUSY 0x1
+
+#define RTSDS_COMBOMODE(mode, submode) (0x10000 | (mode << 8) | submode)
+#define RTSDS_MODE(combomode) ((combomode >> 8) & 0xff)
+#define RTSDS_SUBMODE(combomode) (combomode & 0xff)
+
+struct __packed rtsds_seq {
+ u8 action;
+ u8 mode;
+ u16 ports;
+ u16 page;
+ u16 reg;
+ u16 val;
+ u16 mask;
+};
+
+struct rtsds_sds {
+ struct phy *phy;
+ int mode;
+ int link;
+ int min_port;
+ int max_port;
+};
+
+struct rtsds_ctrl {
+ struct device *dev;
+ void __iomem *base;
+ struct mutex lock;
+ u32 sds_mask;
+ struct rtsds_conf *conf;
+ struct rtsds_sds sds[RTSDS_931X_SDS_CNT];
+ struct rtsds_seq *sequence[RTSDS_EVENT_CNT];
+};
+
+struct rtsds_macro {
+ struct rtsds_ctrl *ctrl;
+ u32 sid;
+};
+
+struct rtsds_conf {
+ u32 sds_cnt;
+ u32 page_cnt;
+ int (*read)(struct rtsds_ctrl *ctrl, u32 idx, u32 page, u32 reg);
+ int (*mask)(struct rtsds_ctrl *ctrl, u32 idx, u32 page, u32 reg, u32 val, u32 mask);
+ int (*reset)(struct rtsds_ctrl *ctrl, u32 idx);
+ int (*set_mode)(struct rtsds_ctrl *ctrl, u32 idx, int mode);
+ int (*get_mode)(struct rtsds_ctrl *ctrl, u32 idx);
+ int mode_map[PHY_INTERFACE_MODE_MAX];
+ struct rtsds_seq *sequence[RTSDS_EVENT_CNT];
+};
+
+/*
+ * This SerDes module should be written in quite a clean way so that direct calls are
+ * not needed. The following functions are provided just in case ...
+ */
+
+int rtsds_read(struct phy *phy, u32 page, u32 reg);
+int rtsds_write(struct phy *phy, u32 page, u32 reg, u32 val);
+int rtsds_mask(struct phy *phy, u32 page, u32 reg, u32 val, u32 mask);
+
+#endif /* _PHY_RTK_OTTO_SERDES_H */
--
2.46.2
^ permalink raw reply related [flat|nested] 22+ messages in thread
* [PATCH v2 3/3] phy: Integrate Realtek Otto SerDes driver into build system
2024-10-07 16:36 [PATCH v2 0/3] phy: Realtek Otto SerDes: add new driver Markus Stockhausen
2024-10-07 16:36 ` [PATCH v2 1/3] dt-bindings: phy: add realtek,otto-serdes PHY binding Markus Stockhausen
2024-10-07 16:36 ` [PATCH v2 2/3] phy: Realtek Otto SerDes driver Markus Stockhausen
@ 2024-10-07 16:36 ` Markus Stockhausen
2024-10-07 19:27 ` Krzysztof Kozlowski
` (3 more replies)
2 siblings, 4 replies; 22+ messages in thread
From: Markus Stockhausen @ 2024-10-07 16:36 UTC (permalink / raw)
To: linux-phy, chris.packham, devicetree, krzk; +Cc: Markus Stockhausen
Add the driver to the build system. The Otto platform currently has
only some drivers upstream and is missing a lot of platform bits.
Use only the bare minimum of dependencies.
Changes in v2:
- Change naming convention
- Add more help text
Signed-off-by: Markus Stockhausen <markus.stockhausen@gmx.de>
---
drivers/phy/realtek/Kconfig | 10 ++++++++++
drivers/phy/realtek/Makefile | 1 +
2 files changed, 11 insertions(+)
diff --git a/drivers/phy/realtek/Kconfig b/drivers/phy/realtek/Kconfig
index 75ac7e7c31ae..021b4c4e700a 100644
--- a/drivers/phy/realtek/Kconfig
+++ b/drivers/phy/realtek/Kconfig
@@ -30,3 +30,13 @@ config PHY_RTK_RTD_USB3PHY
of the parameters.
endif # ARCH_REALTEK || COMPILE_TEST
+
+config PHY_RTK_OTTO_SERDES
+ tristate "SerDes driver for the Realtek Otto platform"
+ depends on OF
+ select GENERIC_PHY
+ help
+ Enable this to support Realtek SerDes in the RTL83xx and
+ RTL93xx network SoCs. These are based on MIPS32 architecture
+ and the SerDes connect to one to octa transceivers to build
+ up switches with up to 52 ports.
diff --git a/drivers/phy/realtek/Makefile b/drivers/phy/realtek/Makefile
index ed7b47ff8a26..34e607f33961 100644
--- a/drivers/phy/realtek/Makefile
+++ b/drivers/phy/realtek/Makefile
@@ -1,3 +1,4 @@
# SPDX-License-Identifier: GPL-2.0
obj-$(CONFIG_PHY_RTK_RTD_USB2PHY) += phy-rtk-usb2.o
obj-$(CONFIG_PHY_RTK_RTD_USB3PHY) += phy-rtk-usb3.o
+obj-$(CONFIG_PHY_RTK_OTTO_SERDES) += phy-rtk-otto-serdes.o
--
2.46.2
^ permalink raw reply related [flat|nested] 22+ messages in thread
* Re: [PATCH v2 1/3] dt-bindings: phy: add realtek,otto-serdes PHY binding
2024-10-07 16:36 ` [PATCH v2 1/3] dt-bindings: phy: add realtek,otto-serdes PHY binding Markus Stockhausen
@ 2024-10-07 18:17 ` Rob Herring (Arm)
2024-10-07 19:26 ` Krzysztof Kozlowski
` (3 subsequent siblings)
4 siblings, 0 replies; 22+ messages in thread
From: Rob Herring (Arm) @ 2024-10-07 18:17 UTC (permalink / raw)
To: Markus Stockhausen; +Cc: chris.packham, devicetree, linux-phy, krzk
On Mon, 07 Oct 2024 12:36:21 -0400, Markus Stockhausen wrote:
> Add bindings for the SerDes of the Realtek Otto platform. These are
> network Switch SoCs with up to 52 ports divided into four different
> model lines.
>
> Changes in v2:
> - new subject
> - removed patch command sequences
> - renamed parameter controlled-ports to realtek,controlled-ports
>
> Signed-off-by: Markus Stockhausen <markus.stockhausen@gmx.de>
> ---
> .../bindings/phy/realtek,otto-serdes.yaml | 95 +++++++++++++++++++
> 1 file changed, 95 insertions(+)
> create mode 100644 Documentation/devicetree/bindings/phy/realtek,otto-serdes.yaml
>
My bot found errors running 'make dt_binding_check' on your patch:
yamllint warnings/errors:
dtschema/dtc warnings/errors:
/builds/robherring/dt-review-ci/linux/Documentation/devicetree/bindings/phy/realtek,otto-serdes.yaml: 'reguired' is not one of ['$id', '$schema', 'title', 'description', 'examples', 'required', 'allOf', 'anyOf', 'oneOf', 'definitions', '$defs', 'additionalProperties', 'dependencies', 'dependentRequired', 'dependentSchemas', 'patternProperties', 'properties', 'not', 'if', 'then', 'else', 'unevaluatedProperties', 'deprecated', 'maintainers', 'select', '$ref']
from schema $id: http://devicetree.org/meta-schemas/base.yaml#
Documentation/devicetree/bindings/phy/realtek,otto-serdes.example.dts:41.33-46.11: ERROR (duplicate_label): /example-1/serdes@1b00a000: Duplicate label 'serdes' on /example-1/serdes@1b00a000 and /example-0/serdes@1b00e780
Documentation/devicetree/bindings/phy/realtek,otto-serdes.example.dts:64.33-69.11: ERROR (duplicate_label): /example-2/serdes@1b0003b0: Duplicate label 'serdes' on /example-2/serdes@1b0003b0 and /example-0/serdes@1b00e780
Documentation/devicetree/bindings/phy/realtek,otto-serdes.example.dts:87.33-92.11: ERROR (duplicate_label): /example-3/serdes@1b005638: Duplicate label 'serdes' on /example-3/serdes@1b005638 and /example-0/serdes@1b00e780
ERROR: Input tree has errors, aborting (use -f to force output)
make[2]: *** [scripts/Makefile.dtbs:129: Documentation/devicetree/bindings/phy/realtek,otto-serdes.example.dtb] Error 2
make[2]: *** Waiting for unfinished jobs....
make[1]: *** [/builds/robherring/dt-review-ci/linux/Makefile:1442: dt_binding_check] Error 2
make: *** [Makefile:224: __sub-make] Error 2
doc reference errors (make refcheckdocs):
See https://patchwork.ozlabs.org/project/devicetree-bindings/patch/20241007163623.3274510-2-markus.stockhausen@gmx.de
The base for the series is generally the latest rc1. A different dependency
should be noted in *this* patch.
If you already ran 'make dt_binding_check' and didn't see the above
error(s), then make sure 'yamllint' is installed and dt-schema is up to
date:
pip3 install dtschema --upgrade
Please check and re-submit after running the above command yourself. Note
that DT_SCHEMA_FILES can be set to your schema file to speed up checking
your schema. However, it must be unset to test all examples with your schema.
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH v2 1/3] dt-bindings: phy: add realtek,otto-serdes PHY binding
2024-10-07 16:36 ` [PATCH v2 1/3] dt-bindings: phy: add realtek,otto-serdes PHY binding Markus Stockhausen
2024-10-07 18:17 ` Rob Herring (Arm)
@ 2024-10-07 19:26 ` Krzysztof Kozlowski
2024-10-08 5:38 ` AW: " markus.stockhausen
2024-10-16 15:30 ` markus.stockhausen
2024-10-07 19:30 ` Rob Herring
` (2 subsequent siblings)
4 siblings, 2 replies; 22+ messages in thread
From: Krzysztof Kozlowski @ 2024-10-07 19:26 UTC (permalink / raw)
To: Markus Stockhausen, linux-phy, chris.packham, devicetree
On 07/10/2024 18:36, Markus Stockhausen wrote:
> Add bindings for the SerDes of the Realtek Otto platform. These are
> network Switch SoCs with up to 52 ports divided into four different
> model lines.
>
> Changes in v2:
> - new subject
> - removed patch command sequences
> - renamed parameter controlled-ports to realtek,controlled-ports
Changelog goes under ---.
>
> Signed-off-by: Markus Stockhausen <markus.stockhausen@gmx.de>
> ---
> .../bindings/phy/realtek,otto-serdes.yaml | 95 +++++++++++++++++++
> 1 file changed, 95 insertions(+)
> create mode 100644 Documentation/devicetree/bindings/phy/realtek,otto-serdes.yaml
>
> diff --git a/Documentation/devicetree/bindings/phy/realtek,otto-serdes.yaml b/Documentation/devicetree/bindings/phy/realtek,otto-serdes.yaml
> new file mode 100644
> index 000000000000..a72ac206b35f
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/phy/realtek,otto-serdes.yaml
Nothing improved.
> @@ -0,0 +1,95 @@
> +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/phy/realtek,otto-serdes.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: Realtek Otto SerDes controller
> +
> +maintainers:
> + - Markus Stockhausen <markus.stockhausen@gmx.de>
> +
> +description:
> + The MIPS based Realtek Switch SoCs of the Realtek RTL838x, RTL839x, RTL930x and RTL931x series
> + have multiple SerDes built in. They are linked to single, quad or octa PHYs like the RTL8218B,
> + RTL8218D or RTL8214FC and are one of the integral part of the up-to-52-port switch architecture.
> +
> + Although these SerDes controllers have common basics they behave differently on the SoC families
> + and rely on heavy register magic. To keep the driver clean it can load patch sequences from
> + devictree and execute them during the controller actions like phy_init(), ...
> +
> + The driver exposes the SerDes registers different from the hardware but instead gives a
> + consistent view and programming interface. So the RTL838x series has 6 ports and 4 pages, the
> + RTL839x has 14 ports and 12 pages, the RTL930x has 12 ports and 64 pages and the RTL931x has
> + 14 ports and 192 pages.
Totally messed wrapping. Please wrap your code as Linux coding style.
> +
> +properties:
> + $nodename:
> + pattern: "^serdes@[0-9a-f]+$"
> +
> + compatible:
> + items:
> + - enum:
> + - realtek,rtl8380-serdes
> + - realtek,rtl8390-serdes
> + - realtek,rtl9300-serdes
> + - realtek,rtl9310-serdes
> +
> + reg:
> + items:
> + description:
> + The primary SerDes paged register memory location. Other SerDes control and management
> + registers are distributed all over the I/O memory space and are identified by the driver.
What happened here? I asked only about |. Why are you adding unrelated
changes?
Anyway, still not tested and still does not look any other binding.
> +
> + "#phy-cells":
> + const: 4
> + description:
> + The first number defines the SerDes to use. The second number a linked SerDes. E.g. if a octa
> + 1G PHY is attached to two QSGMII SerDes. The third number is the first switch port this
> + SerDes is working for, the fourth number is the last switch port the SerDes is working for.
> +
> + realtek,controlled-ports:
> + $ref: /schemas/types.yaml#/definitions/uint32
> + description:
> + A bit mask defining the ports that are actively controlled by the driver. In case a bit is
Driver? Bindings are not about drivers. Drop.
I don't think you implemented my feedback.
> + not set the driver will only process read operations on the SerDes. This is just in case the
> + SerDes has been setup by U-Boot correctly and the driver malfunctions. If not set the driver
> + will control all SerDes.
> +
> +reguired:
> + - compatible
> + - reg
> + - "#phy-cells"
> +
> +additionalProperties:
> + false
Please open any existing binding and do it like there. Or start from
scratch from example-schema.
> +
> +examples:
> + - |
> + serdes: serdes@1b00e780 {
> + compatible = "realtek,rtl8380-serdes", "realtek,otto-serdes";
> + reg = <0x1b00e780 0x1200>;
> + controlled-ports = <0x003f>;
> + #phy-cells = <4>;
> + };
One example is enough.
... and still not tested. Sending untested code is waste of our time.
Best regards,
Krzysztof
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH v2 3/3] phy: Integrate Realtek Otto SerDes driver into build system
2024-10-07 16:36 ` [PATCH v2 3/3] phy: Integrate Realtek Otto SerDes driver into build system Markus Stockhausen
@ 2024-10-07 19:27 ` Krzysztof Kozlowski
2024-10-08 6:38 ` kernel test robot
` (2 subsequent siblings)
3 siblings, 0 replies; 22+ messages in thread
From: Krzysztof Kozlowski @ 2024-10-07 19:27 UTC (permalink / raw)
To: Markus Stockhausen, linux-phy, chris.packham, devicetree
On 07/10/2024 18:36, Markus Stockhausen wrote:
> Add the driver to the build system. The Otto platform currently has
> only some drivers upstream and is missing a lot of platform bits.
> Use only the bare minimum of dependencies.
>
> Changes in v2:
> - Change naming convention
> - Add more help text
>
> Signed-off-by: Markus Stockhausen <markus.stockhausen@gmx.de>
> ---
> drivers/phy/realtek/Kconfig | 10 ++++++++++
> drivers/phy/realtek/Makefile | 1 +
> 2 files changed, 11 insertions(+)
Still no point in splitting this.
<form letter>
This is a friendly reminder during the review process.
It seems my or other reviewer's previous comments were not fully
addressed. Maybe the feedback got lost between the quotes, maybe you
just forgot to apply it. Please go back to the previous discussion and
either implement all requested changes or keep discussing them.
Thank you.
</form letter>
Best regards,
Krzysztof
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH v2 1/3] dt-bindings: phy: add realtek,otto-serdes PHY binding
2024-10-07 16:36 ` [PATCH v2 1/3] dt-bindings: phy: add realtek,otto-serdes PHY binding Markus Stockhausen
2024-10-07 18:17 ` Rob Herring (Arm)
2024-10-07 19:26 ` Krzysztof Kozlowski
@ 2024-10-07 19:30 ` Rob Herring
2024-10-08 12:27 ` AW: " markus.stockhausen
2024-10-08 7:04 ` Krzysztof Kozlowski
2024-10-08 7:06 ` Krzysztof Kozlowski
4 siblings, 1 reply; 22+ messages in thread
From: Rob Herring @ 2024-10-07 19:30 UTC (permalink / raw)
To: Markus Stockhausen; +Cc: linux-phy, chris.packham, devicetree, krzk
On Mon, Oct 07, 2024 at 12:36:21PM -0400, Markus Stockhausen wrote:
> Add bindings for the SerDes of the Realtek Otto platform. These are
> network Switch SoCs with up to 52 ports divided into four different
> model lines.
>
> Changes in v2:
> - new subject
> - removed patch command sequences
> - renamed parameter controlled-ports to realtek,controlled-ports
>
> Signed-off-by: Markus Stockhausen <markus.stockhausen@gmx.de>
> ---
> .../bindings/phy/realtek,otto-serdes.yaml | 95 +++++++++++++++++++
> 1 file changed, 95 insertions(+)
> create mode 100644 Documentation/devicetree/bindings/phy/realtek,otto-serdes.yaml
>
> diff --git a/Documentation/devicetree/bindings/phy/realtek,otto-serdes.yaml b/Documentation/devicetree/bindings/phy/realtek,otto-serdes.yaml
> new file mode 100644
> index 000000000000..a72ac206b35f
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/phy/realtek,otto-serdes.yaml
> @@ -0,0 +1,95 @@
> +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/phy/realtek,otto-serdes.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: Realtek Otto SerDes controller
> +
> +maintainers:
> + - Markus Stockhausen <markus.stockhausen@gmx.de>
> +
> +description:
You need '>' on the end if you want to preserve paragraphs.
> + The MIPS based Realtek Switch SoCs of the Realtek RTL838x, RTL839x, RTL930x and RTL931x series
> + have multiple SerDes built in. They are linked to single, quad or octa PHYs like the RTL8218B,
> + RTL8218D or RTL8214FC and are one of the integral part of the up-to-52-port switch architecture.
> +
> + Although these SerDes controllers have common basics they behave differently on the SoC families
> + and rely on heavy register magic. To keep the driver clean it can load patch sequences from
> + devictree and execute them during the controller actions like phy_init(), ...
> +
> + The driver exposes the SerDes registers different from the hardware but instead gives a
> + consistent view and programming interface. So the RTL838x series has 6 ports and 4 pages, the
> + RTL839x has 14 ports and 12 pages, the RTL930x has 12 ports and 64 pages and the RTL931x has
> + 14 ports and 192 pages.
> +
> +properties:
> + $nodename:
> + pattern: "^serdes@[0-9a-f]+$"
The node name for phy providers is 'phy'.
> +
> + compatible:
> + items:
> + - enum:
> + - realtek,rtl8380-serdes
> + - realtek,rtl8390-serdes
> + - realtek,rtl9300-serdes
> + - realtek,rtl9310-serdes
> +
> + reg:
> + items:
> + description:
> + The primary SerDes paged register memory location. Other SerDes control and management
> + registers are distributed all over the I/O memory space and are identified by the driver.
> +
> + "#phy-cells":
> + const: 4
> + description:
> + The first number defines the SerDes to use. The second number a linked SerDes. E.g. if a octa
> + 1G PHY is attached to two QSGMII SerDes. The third number is the first switch port this
> + SerDes is working for, the fourth number is the last switch port the SerDes is working for.
> +
> + realtek,controlled-ports:
> + $ref: /schemas/types.yaml#/definitions/uint32
> + description:
> + A bit mask defining the ports that are actively controlled by the driver. In case a bit is
> + not set the driver will only process read operations on the SerDes. This is just in case the
> + SerDes has been setup by U-Boot correctly and the driver malfunctions. If not set the driver
> + will control all SerDes.
> +
> +reguired:
> + - compatible
> + - reg
> + - "#phy-cells"
> +
> +additionalProperties:
> + false
One line like *everywhere* else.
> +
> +examples:
> + - |
> + serdes: serdes@1b00e780 {
Drop unused labels.
> + compatible = "realtek,rtl8380-serdes", "realtek,otto-serdes";
> + reg = <0x1b00e780 0x1200>;
> + controlled-ports = <0x003f>;
> + #phy-cells = <4>;
> + };
> + - |
> + serdes: serdes@1b00a000 {
> + compatible = "realtek,rtl8390-serdes", "realtek,otto-serdes";
> + reg = <0x1b00a000 0x1c00>;
> + controlled-ports = <0x3fff>;
> + #phy-cells = <4>;
> + };
> + - |
> + serdes: serdes@1b0003b0 {
> + compatible = "realtek,rtl9300-serdes", "realtek,otto-serdes";
> + reg = <0x1b0003b0 0x8>;
> + controlled-ports = <0x0fff>;
> + #phy-cells = <4>;
> + };
> + - |
> + serdes: serdes@1b005638 {
> + compatible = "realtek,rtl9310-serdes", "realtek,otto-serdes";
> + reg = <0x1b005638 0x8>;
> + controlled-ports = <0x3fff>;
> + #phy-cells = <4>;
> + };
You don't need 4 examples that are essentially the same.
> --
> 2.46.2
>
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH v2 2/3] phy: Realtek Otto SerDes driver
2024-10-07 16:36 ` [PATCH v2 2/3] phy: Realtek Otto SerDes driver Markus Stockhausen
@ 2024-10-07 19:32 ` Krzysztof Kozlowski
0 siblings, 0 replies; 22+ messages in thread
From: Krzysztof Kozlowski @ 2024-10-07 19:32 UTC (permalink / raw)
To: Markus Stockhausen, linux-phy, chris.packham, devicetree
On 07/10/2024 18:36, Markus Stockhausen wrote:
> The Realtek Otto platform is a series of 4 different MIPS32 based network
> switch SoCs. They consist of:
>
> - RTL838x: 500MHz single core, up to 28 ports 20GBps switching capacity
> - RTL839x: 700MHz single core, up to 52 ports 100GBps switching capacity
> - RTL930x: 700MHz single core, up to 28 ports 120GBps switching capacity
> - RTL931x: 1.4GHz dual core, up to 52 ports 170GBps switching capacity
>
...
> +
> +static int rtsds_phy_power_on(struct phy *phy)
> +{
> + struct rtsds_macro *macro = phy_get_drvdata(phy);
> + struct rtsds_ctrl *ctrl = macro->ctrl;
> + u32 sid = macro->sid;
> + int ret;
> +
> + if (rtsds_readonly(ctrl, sid))
> + return 0;
> +
> + mutex_lock(&ctrl->lock);
> +// ret = rtsds_run_event(ctrl, sid, RTSDS_EVENT_POWER_ON);
Dead code? What is the point of this?
> + mutex_unlock(&ctrl->lock);
> +
> + if (ret)
> + dev_err(ctrl->dev, "power on failed for SerDes %d\n", sid);
> +
> + return ret;
> +}
> +
...
> +
> +static ssize_t rtsds_dbg_mode_write(struct file *file, const char __user *userbuf,
> + size_t count, loff_t *ppos)
> +{
> + struct seq_file *seqf = file->private_data;
> + struct rtsds_macro *macro = dev_get_drvdata(seqf->private);
> + struct rtsds_ctrl *ctrl = macro->ctrl;
> + int ret, hwmode, phymode, sid = macro->sid;
> +
> + ret = kstrtou32_from_user(userbuf, count, 16, &hwmode);
> + if (ret)
> + return ret;
> + /*
> + * Allow to set arbitrary modes into the SerDes to improve error analysis. Accept that
> + * this might confuse the internal state tracking.
> + */
> + phymode = rtsds_hwmode_to_phymode(ctrl, hwmode);
> + rtsds_phy_set_mode_int(ctrl, sid, phymode, hwmode);
Interfasce which confuses internal state is a bad interface. Drop.
> +
> + return count;
> +}
> +DEFINE_SHOW_STORE_ATTRIBUTE(rtsds_dbg_mode);
> +
> +static ssize_t rtsds_dbg_reset_show(struct seq_file *seqf, void *unused)
> +{
> + return 0;
> +}
> +
> +static ssize_t rtsds_dbg_reset_write(struct file *file, const char __user *userbuf,
> + size_t count, loff_t *ppos)
> +{
> + struct seq_file *seqf = file->private_data;
> + struct rtsds_macro *macro = dev_get_drvdata(seqf->private);
> + struct rtsds_ctrl *ctrl = macro->ctrl;
> + int ret, reset, sid = macro->sid;
> +
> + ret = kstrtou32_from_user(userbuf, count, 10, &reset);
> + if (ret || reset != 1)
> + return ret;
> +
> + rtsds_phy_reset_int(ctrl, sid);
> +
> + return count;
> +}
> +DEFINE_SHOW_STORE_ATTRIBUTE(rtsds_dbg_reset);
That's not a debugfs interface. Drop reset.
> +
> +static int rtsds_dbg_registers_show(struct seq_file *seqf, void *unused)
> +{
> + struct rtsds_macro *macro = dev_get_drvdata(seqf->private);
> + struct rtsds_ctrl *ctrl = macro->ctrl;
> + u32 page = 0, reg, sid = macro->sid;
> +
> + seq_printf(seqf, "%*s", 12, "");
> + for (int i = 0; i < 32; i++)
> + seq_printf(seqf, " %02X", i);
> +
> + while (page < ctrl->conf->page_cnt) {
> + if (page < RTSDS_PAGE_NAMES && rtsds_page_name[page])
> + seq_printf(seqf, "\n%*s: ", -11, rtsds_page_name[page]);
> + else if (page == 64 || page == 128)
> + seq_printf(seqf, "\n\nXGMII_%d : ", page >> 8);
> + else
> + seq_printf(seqf, "\nPAGE_%03d : ", page);
> + for (reg = 0; reg < 32; reg++)
> + seq_printf(seqf, "%04X ", ctrl->conf->read(ctrl, sid, page, reg));
> +
> + page++;
> + }
> + seq_puts(seqf, "\n");
> +
> + return 0;
> +}
> +DEFINE_SHOW_ATTRIBUTE(rtsds_dbg_registers);
> +
> +static int rtsds_dbg_polarity_show(struct seq_file *seqf, void *unused)
> +{
> + struct rtsds_macro *macro = dev_get_drvdata(seqf->private);
> + struct rtsds_ctrl *ctrl = macro->ctrl;
> + u32 reg, sid = macro->sid;
> +
> + reg = ctrl->conf->read(ctrl, sid, RTSDS_PAGE_SDS, 0);
> +
> + seq_puts(seqf, "tx polarity: ");
> + seq_puts(seqf, reg & RTSDS_BITS_INV_HSO ? "inverse" : "normal");
> + seq_puts(seqf, "\nrx polarity: ");
> + seq_puts(seqf, reg & RTSDS_BITS_INV_HSI ? "inverse" : "normal");
> + seq_puts(seqf, "\n");
> +
> + return 0;
> +}
> +DEFINE_SHOW_ATTRIBUTE(rtsds_dbg_polarity);
> +
> +static void rtsds_dbg_init(struct rtsds_ctrl *ctrl, u32 sid)
> +{
> + debugfs_create_file("mode", 0600, ctrl->sds[sid].phy->debugfs,
> + &ctrl->sds[sid].phy->dev, &rtsds_dbg_mode_fops);
> +
> + debugfs_create_file("reset", 0200, ctrl->sds[sid].phy->debugfs,
> + &ctrl->sds[sid].phy->dev, &rtsds_dbg_reset_fops);
> +
> + debugfs_create_file("polarity", 0400, ctrl->sds[sid].phy->debugfs,
> + &ctrl->sds[sid].phy->dev, &rtsds_dbg_polarity_fops);
> +
> + debugfs_create_file("registers", 0400, ctrl->sds[sid].phy->debugfs,
> + &ctrl->sds[sid].phy->dev, &rtsds_dbg_registers_fops);
> +}
> +#endif /* CONFIG_DEBUG_FS */
> +
> +
> +static int rtsds_probe(struct platform_device *pdev)
> +{
> + struct device_node *np = pdev->dev.of_node;
> + struct device *dev = &pdev->dev;
> + struct phy_provider *provider;
> + struct rtsds_ctrl *ctrl;
> + int ret;
> +
> + if (!np)
> + return -EINVAL;
How is this possible? Drop.
> +
> + ctrl = devm_kzalloc(dev, sizeof(*ctrl), GFP_KERNEL);
> + if (!ctrl)
> + return -ENOMEM;
> +
> + ctrl->base = devm_platform_ioremap_resource(pdev, 0);
> + if (IS_ERR(ctrl->base)) {
> + dev_err(dev, "failed to map SerDes memory\n");
> + return PTR_ERR(ctrl->base);
> + }
> +
> + ctrl->dev = dev;
> + ctrl->conf = (struct rtsds_conf *)of_device_get_match_data(dev);
> +
> + ret = of_property_read_u32(np, "realtek,controlled-ports", &ctrl->sds_mask);
> + if (ret)
> + ctrl->sds_mask = GENMASK(ctrl->conf->sds_cnt, 0);
> +
> + for (u32 sid = 0; sid < ctrl->conf->sds_cnt; sid++) {
> + ret = rtsds_phy_create(ctrl, sid);
> + if (ret) {
> + dev_err(dev, "failed to create PHY for SerDes %d\n", sid);
> + return ret;
> + }
> + }
> +
> + mutex_init(&ctrl->lock);
> + dev_set_drvdata(dev, ctrl);
> + provider = devm_of_phy_provider_register(dev, rtsds_simple_xlate);
> + rtsds_setup(ctrl);
> + dev_info(dev, "initialized (%d SerDes, %d pages, 32 registers, mask 0x%04x)",
> + ctrl->conf->sds_cnt, ctrl->conf->page_cnt, ctrl->sds_mask);
> +
> + return PTR_ERR_OR_ZERO(provider);
> +}
> +
...
> +static const struct of_device_id rtsds_compatible_ids[] = {
> + { .compatible = "realtek,rtl8380-serdes",
> + .data = &rtsds_838x_conf,
> + },
> + { .compatible = "realtek,rtl8390-serdes",
> + .data = &rtsds_839x_conf,
> + },
> + { .compatible = "realtek,rtl9300-serdes",
> + .data = &rtsds_930x_conf,
> + },
> + { .compatible = "realtek,rtl9310-serdes",
> + .data = &rtsds_931x_conf,
> + },
> + {},
> +};
> +MODULE_DEVICE_TABLE(of, rtsds_compatible_ids);
> +
> +static struct platform_driver rtsds_platform_driver = {
> + .probe = rtsds_probe,
> + .driver = {
> + .name = "realtek,otto-serdes",
> + .of_match_table = of_match_ptr(rtsds_compatible_ids),
Drop of_match_ptr, you have warning because of it.
> + },
> +};
> +
> +module_platform_driver(rtsds_platform_driver);
> +
> +MODULE_AUTHOR("Markus Stockhausen <markus.stockhausen@gmx.de>");
> +MODULE_DESCRIPTION("SerDes driver for Realtek RTL83xx, RTL93xx switch SoCs");
> +MODULE_LICENSE("GPL");
...
> +
> +struct rtsds_macro {
> + struct rtsds_ctrl *ctrl;
> + u32 sid;
> +};
> +
> +struct rtsds_conf {
> + u32 sds_cnt;
> + u32 page_cnt;
> + int (*read)(struct rtsds_ctrl *ctrl, u32 idx, u32 page, u32 reg);
> + int (*mask)(struct rtsds_ctrl *ctrl, u32 idx, u32 page, u32 reg, u32 val, u32 mask);
> + int (*reset)(struct rtsds_ctrl *ctrl, u32 idx);
> + int (*set_mode)(struct rtsds_ctrl *ctrl, u32 idx, int mode);
> + int (*get_mode)(struct rtsds_ctrl *ctrl, u32 idx);
> + int mode_map[PHY_INTERFACE_MODE_MAX];
> + struct rtsds_seq *sequence[RTSDS_EVENT_CNT];
> +};
> +
> +/*
> + * This SerDes module should be written in quite a clean way so that direct calls are
> + * not needed. The following functions are provided just in case ...
> + */
Drop code "just in case".
Best regards,
Krzysztof
^ permalink raw reply [flat|nested] 22+ messages in thread
* AW: [PATCH v2 1/3] dt-bindings: phy: add realtek,otto-serdes PHY binding
2024-10-07 19:26 ` Krzysztof Kozlowski
@ 2024-10-08 5:38 ` markus.stockhausen
2024-10-08 6:17 ` Krzysztof Kozlowski
2024-10-16 15:30 ` markus.stockhausen
1 sibling, 1 reply; 22+ messages in thread
From: markus.stockhausen @ 2024-10-08 5:38 UTC (permalink / raw)
To: 'Krzysztof Kozlowski', linux-phy, chris.packham,
devicetree
> -----Ursprüngliche Nachricht-----
> Von: Krzysztof Kozlowski <krzk@kernel.org>
> Gesendet: Montag, 7. Oktober 2024 21:26
> An: Markus Stockhausen <markus.stockhausen@gmx.de>; linux-phy@lists.infradead.org; chris.packham@alliedtelesis.co.nz; devicetree@vger.kernel.org
> Betreff: Re: [PATCH v2 1/3] dt-bindings: phy: add realtek,otto-serdes PHY binding
>
> ... and still not tested. Sending untested code is waste of our time.
Hi Krzysztof,
appreciate your feedback and I do not want to waste your time. My fixes where a mix
of your feedback and some half-baked "make dt_binding_check" feedbacks (because
packages where missing). My fault and sorry fort he noise.
To get next version in better shape two questions regarding your feedback:
1. "Messed wrapping": According to checkpatch 100 chars/line are accepted.
So I designed the comments in the driver. Does devicetree differ from that?
2 "Bindings vs drivers". The idea about controlled ports came from other bindings.
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/Documentation/devicetree/bindings/interrupt-controller/st,stih407-irq-syscfg.yaml?h=v6.12-rc2
E.g. st,invert-ext. Something like this will be needed in the future because the
SerDes allow to swap polarity which must be changed depending on the switch
design. How to do this?
Best regards.
Markus
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: AW: [PATCH v2 1/3] dt-bindings: phy: add realtek,otto-serdes PHY binding
2024-10-08 5:38 ` AW: " markus.stockhausen
@ 2024-10-08 6:17 ` Krzysztof Kozlowski
2024-10-08 6:56 ` AW: " markus.stockhausen
0 siblings, 1 reply; 22+ messages in thread
From: Krzysztof Kozlowski @ 2024-10-08 6:17 UTC (permalink / raw)
To: markus.stockhausen, linux-phy, chris.packham, devicetree
On 08/10/2024 07:38, markus.stockhausen@gmx.de wrote:
>> -----Ursprüngliche Nachricht-----
>> Von: Krzysztof Kozlowski <krzk@kernel.org>
>> Gesendet: Montag, 7. Oktober 2024 21:26
>> An: Markus Stockhausen <markus.stockhausen@gmx.de>; linux-phy@lists.infradead.org; chris.packham@alliedtelesis.co.nz; devicetree@vger.kernel.org
>> Betreff: Re: [PATCH v2 1/3] dt-bindings: phy: add realtek,otto-serdes PHY binding
>>
>> ... and still not tested. Sending untested code is waste of our time.
>
> Hi Krzysztof,
>
> appreciate your feedback and I do not want to waste your time. My fixes where a mix
> of your feedback and some half-baked "make dt_binding_check" feedbacks (because
> packages where missing). My fault and sorry fort he noise.
>
> To get next version in better shape two questions regarding your feedback:
>
> 1. "Messed wrapping": According to checkpatch 100 chars/line are accepted.
> So I designed the comments in the driver. Does devicetree differ from that?
checkpatch is not a coding style. I asked to follow coding style, please
read entire document in Documentation/process.
>
> 2 "Bindings vs drivers". The idea about controlled ports came from other bindings.
Entire property description speaks about driver, not bindings.
> https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/Documentation/devicetree/bindings/interrupt-controller/st,stih407-irq-syscfg.yaml?h=v6.12-rc2
stih is rather poor example to use. The property was added in 2015 (!)
without review (!!!).
> E.g. st,invert-ext. Something like this will be needed in the future because the
> SerDes allow to swap polarity which must be changed depending on the switch
> design. How to do this?
I do not understand the hardware aspect discussed in the property
description... probably because there is no hardware description at all,
but instead you speak about driver.
I do not understand how polarity has anything to do with U-Boot
configuring serdes.
Best regards,
Krzysztof
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH v2 3/3] phy: Integrate Realtek Otto SerDes driver into build system
2024-10-07 16:36 ` [PATCH v2 3/3] phy: Integrate Realtek Otto SerDes driver into build system Markus Stockhausen
2024-10-07 19:27 ` Krzysztof Kozlowski
@ 2024-10-08 6:38 ` kernel test robot
2024-10-08 7:20 ` kernel test robot
2024-10-08 8:21 ` kernel test robot
3 siblings, 0 replies; 22+ messages in thread
From: kernel test robot @ 2024-10-08 6:38 UTC (permalink / raw)
To: Markus Stockhausen, linux-phy, chris.packham, devicetree, krzk
Cc: llvm, oe-kbuild-all, Markus Stockhausen
Hi Markus,
kernel test robot noticed the following build warnings:
[auto build test WARNING on robh/for-next]
[also build test WARNING on krzk-dt/for-next linus/master v6.12-rc2 next-20241004]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]
url: https://github.com/intel-lab-lkp/linux/commits/Markus-Stockhausen/dt-bindings-phy-add-realtek-otto-serdes-PHY-binding/20241008-003929
base: https://git.kernel.org/pub/scm/linux/kernel/git/robh/linux.git for-next
patch link: https://lore.kernel.org/r/20241007163623.3274510-4-markus.stockhausen%40gmx.de
patch subject: [PATCH v2 3/3] phy: Integrate Realtek Otto SerDes driver into build system
config: hexagon-allmodconfig (https://download.01.org/0day-ci/archive/20241008/202410081436.fFz8vjTK-lkp@intel.com/config)
compiler: clang version 20.0.0git (https://github.com/llvm/llvm-project fef3566a25ff0e34fb87339ba5e13eca17cec00f)
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20241008/202410081436.fFz8vjTK-lkp@intel.com/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202410081436.fFz8vjTK-lkp@intel.com/
All warnings (new ones prefixed by >>):
In file included from drivers/phy/realtek/phy-rtk-otto-serdes.c:11:
In file included from include/linux/phy.h:16:
In file included from include/linux/ethtool.h:18:
In file included from include/linux/if_ether.h:19:
In file included from include/linux/skbuff.h:17:
In file included from include/linux/bvec.h:10:
In file included from include/linux/highmem.h:10:
In file included from include/linux/mm.h:2213:
include/linux/vmstat.h:518:36: warning: arithmetic between different enumeration types ('enum node_stat_item' and 'enum lru_list') [-Wenum-enum-conversion]
518 | return node_stat_name(NR_LRU_BASE + lru) + 3; // skip "nr_"
| ~~~~~~~~~~~ ^ ~~~
In file included from drivers/phy/realtek/phy-rtk-otto-serdes.c:11:
In file included from include/linux/phy.h:16:
In file included from include/linux/ethtool.h:18:
In file included from include/linux/if_ether.h:19:
In file included from include/linux/skbuff.h:17:
In file included from include/linux/bvec.h:10:
In file included from include/linux/highmem.h:12:
In file included from include/linux/hardirq.h:11:
In file included from ./arch/hexagon/include/generated/asm/hardirq.h:1:
In file included from include/asm-generic/hardirq.h:17:
In file included from include/linux/irq.h:20:
In file included from include/linux/io.h:14:
In file included from arch/hexagon/include/asm/io.h:328:
include/asm-generic/io.h:548:31: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
548 | val = __raw_readb(PCI_IOBASE + addr);
| ~~~~~~~~~~ ^
include/asm-generic/io.h:561:61: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
561 | val = __le16_to_cpu((__le16 __force)__raw_readw(PCI_IOBASE + addr));
| ~~~~~~~~~~ ^
include/uapi/linux/byteorder/little_endian.h:37:51: note: expanded from macro '__le16_to_cpu'
37 | #define __le16_to_cpu(x) ((__force __u16)(__le16)(x))
| ^
In file included from drivers/phy/realtek/phy-rtk-otto-serdes.c:11:
In file included from include/linux/phy.h:16:
In file included from include/linux/ethtool.h:18:
In file included from include/linux/if_ether.h:19:
In file included from include/linux/skbuff.h:17:
In file included from include/linux/bvec.h:10:
In file included from include/linux/highmem.h:12:
In file included from include/linux/hardirq.h:11:
In file included from ./arch/hexagon/include/generated/asm/hardirq.h:1:
In file included from include/asm-generic/hardirq.h:17:
In file included from include/linux/irq.h:20:
In file included from include/linux/io.h:14:
In file included from arch/hexagon/include/asm/io.h:328:
include/asm-generic/io.h:574:61: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
574 | val = __le32_to_cpu((__le32 __force)__raw_readl(PCI_IOBASE + addr));
| ~~~~~~~~~~ ^
include/uapi/linux/byteorder/little_endian.h:35:51: note: expanded from macro '__le32_to_cpu'
35 | #define __le32_to_cpu(x) ((__force __u32)(__le32)(x))
| ^
In file included from drivers/phy/realtek/phy-rtk-otto-serdes.c:11:
In file included from include/linux/phy.h:16:
In file included from include/linux/ethtool.h:18:
In file included from include/linux/if_ether.h:19:
In file included from include/linux/skbuff.h:17:
In file included from include/linux/bvec.h:10:
In file included from include/linux/highmem.h:12:
In file included from include/linux/hardirq.h:11:
In file included from ./arch/hexagon/include/generated/asm/hardirq.h:1:
In file included from include/asm-generic/hardirq.h:17:
In file included from include/linux/irq.h:20:
In file included from include/linux/io.h:14:
In file included from arch/hexagon/include/asm/io.h:328:
include/asm-generic/io.h:585:33: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
585 | __raw_writeb(value, PCI_IOBASE + addr);
| ~~~~~~~~~~ ^
include/asm-generic/io.h:595:59: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
595 | __raw_writew((u16 __force)cpu_to_le16(value), PCI_IOBASE + addr);
| ~~~~~~~~~~ ^
include/asm-generic/io.h:605:59: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
605 | __raw_writel((u32 __force)cpu_to_le32(value), PCI_IOBASE + addr);
| ~~~~~~~~~~ ^
>> drivers/phy/realtek/phy-rtk-otto-serdes.c:490:15: warning: overlapping comparisons always evaluate to true [-Wtautological-overlap-compare]
490 | if (sid >= 2 || sid <= 9)
| ~~~~~~~~~^~~~~~~~~~~
drivers/phy/realtek/phy-rtk-otto-serdes.c:509:15: warning: overlapping comparisons always evaluate to true [-Wtautological-overlap-compare]
509 | if (sid >= 2 || sid <= 9)
| ~~~~~~~~~^~~~~~~~~~~
>> drivers/phy/realtek/phy-rtk-otto-serdes.c:686:6: warning: variable 'ret' is uninitialized when used here [-Wuninitialized]
686 | if (ret)
| ^~~
drivers/phy/realtek/phy-rtk-otto-serdes.c:677:9: note: initialize the variable 'ret' to silence this warning
677 | int ret;
| ^
| = 0
drivers/phy/realtek/phy-rtk-otto-serdes.c:706:6: warning: variable 'ret' is uninitialized when used here [-Wuninitialized]
706 | if (ret)
| ^~~
drivers/phy/realtek/phy-rtk-otto-serdes.c:697:9: note: initialize the variable 'ret' to silence this warning
697 | int ret;
| ^
| = 0
drivers/phy/realtek/phy-rtk-otto-serdes.c:723:7: warning: variable 'ret' is uninitialized when used here [-Wuninitialized]
723 | if (!ret)
| ^~~
drivers/phy/realtek/phy-rtk-otto-serdes.c:717:9: note: initialize the variable 'ret' to silence this warning
717 | int ret;
| ^
| = 0
12 warnings generated.
Kconfig warnings: (for reference only)
WARNING: unmet direct dependencies detected for MODVERSIONS
Depends on [n]: MODULES [=y] && !COMPILE_TEST [=y]
Selected by [y]:
- RANDSTRUCT_FULL [=y] && (CC_HAS_RANDSTRUCT [=y] || GCC_PLUGINS [=n]) && MODULES [=y]
WARNING: unmet direct dependencies detected for GET_FREE_REGION
Depends on [n]: SPARSEMEM [=n]
Selected by [m]:
- RESOURCE_KUNIT_TEST [=m] && RUNTIME_TESTING_MENU [=y] && KUNIT [=m]
vim +490 drivers/phy/realtek/phy-rtk-otto-serdes.c
40f1aea80b53b8 Markus Stockhausen 2024-10-07 477
40f1aea80b53b8 Markus Stockhausen 2024-10-07 478 static int rtsds_930x_set_mode(struct rtsds_ctrl *ctrl, u32 sid, int combomode)
40f1aea80b53b8 Markus Stockhausen 2024-10-07 479 {
40f1aea80b53b8 Markus Stockhausen 2024-10-07 480 int modeshift, subshift;
40f1aea80b53b8 Markus Stockhausen 2024-10-07 481 int mode = RTSDS_MODE(combomode);
40f1aea80b53b8 Markus Stockhausen 2024-10-07 482 int submode = RTSDS_SUBMODE(combomode);
40f1aea80b53b8 Markus Stockhausen 2024-10-07 483 void __iomem __force *modereg;
40f1aea80b53b8 Markus Stockhausen 2024-10-07 484 void __iomem __force *subreg;
40f1aea80b53b8 Markus Stockhausen 2024-10-07 485
40f1aea80b53b8 Markus Stockhausen 2024-10-07 486 if (rtsds_invalid_sds(ctrl, sid))
40f1aea80b53b8 Markus Stockhausen 2024-10-07 487 return -EINVAL;
40f1aea80b53b8 Markus Stockhausen 2024-10-07 488
40f1aea80b53b8 Markus Stockhausen 2024-10-07 489 rtsds_930x_mode_offset(sid, &modereg, &modeshift, &subreg, &subshift);
40f1aea80b53b8 Markus Stockhausen 2024-10-07 @490 if (sid >= 2 || sid <= 9)
40f1aea80b53b8 Markus Stockhausen 2024-10-07 491 iomask32(0x1f << subshift, (submode & 0x1f) << subshift, subreg);
40f1aea80b53b8 Markus Stockhausen 2024-10-07 492 else if (submode != 0)
40f1aea80b53b8 Markus Stockhausen 2024-10-07 493 return -EINVAL;
40f1aea80b53b8 Markus Stockhausen 2024-10-07 494 iomask32(0x1f << modeshift, (mode & 0x1f) << modeshift, modereg);
40f1aea80b53b8 Markus Stockhausen 2024-10-07 495
40f1aea80b53b8 Markus Stockhausen 2024-10-07 496 return 0;
40f1aea80b53b8 Markus Stockhausen 2024-10-07 497 }
40f1aea80b53b8 Markus Stockhausen 2024-10-07 498
40f1aea80b53b8 Markus Stockhausen 2024-10-07 499 static int rtsds_930x_get_mode(struct rtsds_ctrl *ctrl, u32 sid)
40f1aea80b53b8 Markus Stockhausen 2024-10-07 500 {
40f1aea80b53b8 Markus Stockhausen 2024-10-07 501 int modeshift, subshift, mode, submode = 0;
40f1aea80b53b8 Markus Stockhausen 2024-10-07 502 void __iomem __force *modereg;
40f1aea80b53b8 Markus Stockhausen 2024-10-07 503 void __iomem __force *subreg;
40f1aea80b53b8 Markus Stockhausen 2024-10-07 504
40f1aea80b53b8 Markus Stockhausen 2024-10-07 505 if (rtsds_invalid_sds(ctrl, sid))
40f1aea80b53b8 Markus Stockhausen 2024-10-07 506 return -EINVAL;
40f1aea80b53b8 Markus Stockhausen 2024-10-07 507
40f1aea80b53b8 Markus Stockhausen 2024-10-07 508 rtsds_930x_mode_offset(sid, &modereg, &modeshift, &subreg, &subshift);
40f1aea80b53b8 Markus Stockhausen 2024-10-07 509 if (sid >= 2 || sid <= 9)
40f1aea80b53b8 Markus Stockhausen 2024-10-07 510 submode = (ioread32(subreg) >> subshift) & 0x1f;
40f1aea80b53b8 Markus Stockhausen 2024-10-07 511 mode = ioread32(modereg) >> modeshift & 0x1f;
40f1aea80b53b8 Markus Stockhausen 2024-10-07 512
40f1aea80b53b8 Markus Stockhausen 2024-10-07 513 return RTSDS_COMBOMODE(mode, submode);
40f1aea80b53b8 Markus Stockhausen 2024-10-07 514 }
40f1aea80b53b8 Markus Stockhausen 2024-10-07 515
40f1aea80b53b8 Markus Stockhausen 2024-10-07 516 static int rtsds_930x_reset(struct rtsds_ctrl *ctrl, u32 sid)
40f1aea80b53b8 Markus Stockhausen 2024-10-07 517 {
40f1aea80b53b8 Markus Stockhausen 2024-10-07 518 int modecur, modeoff = ctrl->conf->mode_map[PHY_INTERFACE_MODE_NA];
40f1aea80b53b8 Markus Stockhausen 2024-10-07 519
40f1aea80b53b8 Markus Stockhausen 2024-10-07 520 if (rtsds_invalid_sds(ctrl, sid))
40f1aea80b53b8 Markus Stockhausen 2024-10-07 521 return -EINVAL;
40f1aea80b53b8 Markus Stockhausen 2024-10-07 522
40f1aea80b53b8 Markus Stockhausen 2024-10-07 523 modecur = rtsds_930x_get_mode(ctrl, sid);
40f1aea80b53b8 Markus Stockhausen 2024-10-07 524
40f1aea80b53b8 Markus Stockhausen 2024-10-07 525 /* It is enough to power off SerDes and set to old mode again */
40f1aea80b53b8 Markus Stockhausen 2024-10-07 526 if (modecur != modeoff) {
40f1aea80b53b8 Markus Stockhausen 2024-10-07 527 rtsds_930x_set_mode(ctrl, sid, modeoff);
40f1aea80b53b8 Markus Stockhausen 2024-10-07 528 rtsds_930x_set_mode(ctrl, sid, modecur);
40f1aea80b53b8 Markus Stockhausen 2024-10-07 529 }
40f1aea80b53b8 Markus Stockhausen 2024-10-07 530
40f1aea80b53b8 Markus Stockhausen 2024-10-07 531 return 0;
40f1aea80b53b8 Markus Stockhausen 2024-10-07 532 }
40f1aea80b53b8 Markus Stockhausen 2024-10-07 533
40f1aea80b53b8 Markus Stockhausen 2024-10-07 534 /*
40f1aea80b53b8 Markus Stockhausen 2024-10-07 535 * The RTL931x family has 14 "frontend" SerDes that are cascaded. All operations (e.g. reset) work
40f1aea80b53b8 Markus Stockhausen 2024-10-07 536 * on this frontend view while their registers are distributed over a total of 32 background
40f1aea80b53b8 Markus Stockhausen 2024-10-07 537 * SerDes. Two types of SerDes have been identified:
40f1aea80b53b8 Markus Stockhausen 2024-10-07 538 *
40f1aea80b53b8 Markus Stockhausen 2024-10-07 539 * A "even" SerDes with numbers 0, 1, 2, 4, 6, 8, 10, 12 works on two background SerDes. 64 analog
40f1aea80b53b8 Markus Stockhausen 2024-10-07 540 * and 64 XGMII data pages are coming from a first background SerDes while another 64 XGMII pages
40f1aea80b53b8 Markus Stockhausen 2024-10-07 541 * are served from a second SerDes.
40f1aea80b53b8 Markus Stockhausen 2024-10-07 542 *
40f1aea80b53b8 Markus Stockhausen 2024-10-07 543 * The "odd" SerDes with numbers 3, 5, 7, 9, 11 & 13 SerDes consist of a total of 3 background
40f1aea80b53b8 Markus Stockhausen 2024-10-07 544 * SerDes (one analog and two XGMII) each with an own page/register set.
40f1aea80b53b8 Markus Stockhausen 2024-10-07 545 *
40f1aea80b53b8 Markus Stockhausen 2024-10-07 546 * To align this and improve readability the driver will simulate a total of 576 pages and mix
40f1aea80b53b8 Markus Stockhausen 2024-10-07 547 * them as follows.
40f1aea80b53b8 Markus Stockhausen 2024-10-07 548 *
40f1aea80b53b8 Markus Stockhausen 2024-10-07 549 * frontend page "even" frontend SerDes "odd" frontend SerDes
40f1aea80b53b8 Markus Stockhausen 2024-10-07 550 * page 0-63 (analog): back SDS page 0-63 back SDS page 0-63
40f1aea80b53b8 Markus Stockhausen 2024-10-07 551 * page 64-127 (XGMII1): back SDS page 0-63 back SDS+1 page 0-63
40f1aea80b53b8 Markus Stockhausen 2024-10-07 552 * page 128-191 (XGMII2): back SDS+1 page 0-63 back SDS+2 page 0-63
40f1aea80b53b8 Markus Stockhausen 2024-10-07 553 */
40f1aea80b53b8 Markus Stockhausen 2024-10-07 554
40f1aea80b53b8 Markus Stockhausen 2024-10-07 555 static int rtsds_931x_reg_offset(u32 sid, u32 page)
40f1aea80b53b8 Markus Stockhausen 2024-10-07 556 {
40f1aea80b53b8 Markus Stockhausen 2024-10-07 557 int map[] = {0, 1, 2, 3, 6, 7, 10, 11, 14, 15, 18, 19, 22, 23};
40f1aea80b53b8 Markus Stockhausen 2024-10-07 558 int offs = map[sid];
40f1aea80b53b8 Markus Stockhausen 2024-10-07 559
40f1aea80b53b8 Markus Stockhausen 2024-10-07 560 if ((sid & 1) && (sid != 1))
40f1aea80b53b8 Markus Stockhausen 2024-10-07 561 offs += (page >> 6); /* distribute "odd" to 3 background SerDes */
40f1aea80b53b8 Markus Stockhausen 2024-10-07 562 else if (page >= 128)
40f1aea80b53b8 Markus Stockhausen 2024-10-07 563 offs += 1; /* "distribute "even" to 2 background SerDes */
40f1aea80b53b8 Markus Stockhausen 2024-10-07 564
40f1aea80b53b8 Markus Stockhausen 2024-10-07 565 return offs;
40f1aea80b53b8 Markus Stockhausen 2024-10-07 566 }
40f1aea80b53b8 Markus Stockhausen 2024-10-07 567
40f1aea80b53b8 Markus Stockhausen 2024-10-07 568 static int rtsds_931x_read(struct rtsds_ctrl *ctrl, u32 sid, u32 page, u32 reg)
40f1aea80b53b8 Markus Stockhausen 2024-10-07 569 {
40f1aea80b53b8 Markus Stockhausen 2024-10-07 570 int offs;
40f1aea80b53b8 Markus Stockhausen 2024-10-07 571
40f1aea80b53b8 Markus Stockhausen 2024-10-07 572 if (rtsds_invalid_reg(ctrl, sid, page, reg))
40f1aea80b53b8 Markus Stockhausen 2024-10-07 573 return -EINVAL;
40f1aea80b53b8 Markus Stockhausen 2024-10-07 574
40f1aea80b53b8 Markus Stockhausen 2024-10-07 575 offs = rtsds_931x_reg_offset(sid, page);
40f1aea80b53b8 Markus Stockhausen 2024-10-07 576 if (offs < 0)
40f1aea80b53b8 Markus Stockhausen 2024-10-07 577 return 0;
40f1aea80b53b8 Markus Stockhausen 2024-10-07 578
40f1aea80b53b8 Markus Stockhausen 2024-10-07 579 return rtsds_93xx_read(ctrl, offs, page, reg);
40f1aea80b53b8 Markus Stockhausen 2024-10-07 580 }
40f1aea80b53b8 Markus Stockhausen 2024-10-07 581
40f1aea80b53b8 Markus Stockhausen 2024-10-07 582 static int rtsds_931x_mask(struct rtsds_ctrl *ctrl, u32 sid, u32 page, u32 reg, u32 val, u32 mask)
40f1aea80b53b8 Markus Stockhausen 2024-10-07 583 {
40f1aea80b53b8 Markus Stockhausen 2024-10-07 584 int offs;
40f1aea80b53b8 Markus Stockhausen 2024-10-07 585
40f1aea80b53b8 Markus Stockhausen 2024-10-07 586 if (rtsds_invalid_reg(ctrl, sid, page, reg))
40f1aea80b53b8 Markus Stockhausen 2024-10-07 587 return -EINVAL;
40f1aea80b53b8 Markus Stockhausen 2024-10-07 588
40f1aea80b53b8 Markus Stockhausen 2024-10-07 589 offs = rtsds_931x_reg_offset(sid, page);
40f1aea80b53b8 Markus Stockhausen 2024-10-07 590 if (offs < 0)
40f1aea80b53b8 Markus Stockhausen 2024-10-07 591 return 0;
40f1aea80b53b8 Markus Stockhausen 2024-10-07 592
40f1aea80b53b8 Markus Stockhausen 2024-10-07 593 return rtsds_93xx_mask(ctrl, offs, page, reg, val, mask);
40f1aea80b53b8 Markus Stockhausen 2024-10-07 594 }
40f1aea80b53b8 Markus Stockhausen 2024-10-07 595
40f1aea80b53b8 Markus Stockhausen 2024-10-07 596 static int rtsds_931x_set_mode(struct rtsds_ctrl *ctrl, u32 sid, int combomode)
40f1aea80b53b8 Markus Stockhausen 2024-10-07 597 {
40f1aea80b53b8 Markus Stockhausen 2024-10-07 598 int shift = (sid & 3) << 3, offs = sid & ~3;
40f1aea80b53b8 Markus Stockhausen 2024-10-07 599 int mode = RTSDS_MODE(combomode);
40f1aea80b53b8 Markus Stockhausen 2024-10-07 600 int submode = RTSDS_SUBMODE(combomode);
40f1aea80b53b8 Markus Stockhausen 2024-10-07 601
40f1aea80b53b8 Markus Stockhausen 2024-10-07 602 if (rtsds_invalid_sds(ctrl, sid))
40f1aea80b53b8 Markus Stockhausen 2024-10-07 603 return -EINVAL;
40f1aea80b53b8 Markus Stockhausen 2024-10-07 604
40f1aea80b53b8 Markus Stockhausen 2024-10-07 605 rtsds_931x_mask(ctrl, sid, 0x1f, 0x09, (submode & 0x3f << 6), 0x0fc0);
40f1aea80b53b8 Markus Stockhausen 2024-10-07 606 iomask32(0xff << shift, ((mode | RTSDS_931X_SDS_FORCE_SETUP) & 0xff) << shift,
40f1aea80b53b8 Markus Stockhausen 2024-10-07 607 RTSDS_931X_SERDES_MODE_CTRL + offs);
40f1aea80b53b8 Markus Stockhausen 2024-10-07 608
40f1aea80b53b8 Markus Stockhausen 2024-10-07 609 return 0;
40f1aea80b53b8 Markus Stockhausen 2024-10-07 610 }
40f1aea80b53b8 Markus Stockhausen 2024-10-07 611
40f1aea80b53b8 Markus Stockhausen 2024-10-07 612 static int rtsds_931x_get_mode(struct rtsds_ctrl *ctrl, u32 sid)
40f1aea80b53b8 Markus Stockhausen 2024-10-07 613 {
40f1aea80b53b8 Markus Stockhausen 2024-10-07 614 int mode, submode, shift = (sid & 3) << 3, offs = sid & ~3;
40f1aea80b53b8 Markus Stockhausen 2024-10-07 615
40f1aea80b53b8 Markus Stockhausen 2024-10-07 616 if (rtsds_invalid_sds(ctrl, sid))
40f1aea80b53b8 Markus Stockhausen 2024-10-07 617 return -EINVAL;
40f1aea80b53b8 Markus Stockhausen 2024-10-07 618
40f1aea80b53b8 Markus Stockhausen 2024-10-07 619 submode = (rtsds_931x_read(ctrl, sid, 0x1f, 0x09) >> 6) & 0x3f;
40f1aea80b53b8 Markus Stockhausen 2024-10-07 620 mode = (ioread32(RTSDS_931X_SERDES_MODE_CTRL + offs) >> shift) & 0x1f;
40f1aea80b53b8 Markus Stockhausen 2024-10-07 621
40f1aea80b53b8 Markus Stockhausen 2024-10-07 622 return RTSDS_COMBOMODE(mode, submode);
40f1aea80b53b8 Markus Stockhausen 2024-10-07 623 }
40f1aea80b53b8 Markus Stockhausen 2024-10-07 624
40f1aea80b53b8 Markus Stockhausen 2024-10-07 625 static int rtsds_931x_reset(struct rtsds_ctrl *ctrl, u32 sid)
40f1aea80b53b8 Markus Stockhausen 2024-10-07 626 {
40f1aea80b53b8 Markus Stockhausen 2024-10-07 627 int pwr, modecur, modeoff = ctrl->conf->mode_map[PHY_INTERFACE_MODE_NA];
40f1aea80b53b8 Markus Stockhausen 2024-10-07 628
40f1aea80b53b8 Markus Stockhausen 2024-10-07 629 if (rtsds_invalid_sds(ctrl, sid))
40f1aea80b53b8 Markus Stockhausen 2024-10-07 630 return -EINVAL;
40f1aea80b53b8 Markus Stockhausen 2024-10-07 631
40f1aea80b53b8 Markus Stockhausen 2024-10-07 632 modecur = rtsds_931x_get_mode(ctrl, sid);
40f1aea80b53b8 Markus Stockhausen 2024-10-07 633
40f1aea80b53b8 Markus Stockhausen 2024-10-07 634 if (modecur != modeoff) {
40f1aea80b53b8 Markus Stockhausen 2024-10-07 635 /* reset with mode switch cycle while being powered off */
40f1aea80b53b8 Markus Stockhausen 2024-10-07 636 pwr = ioread32(RTSDS_931X_PS_SERDES_OFF_MODE_CTRL);
40f1aea80b53b8 Markus Stockhausen 2024-10-07 637 iowrite32(pwr | BIT(sid), RTSDS_931X_PS_SERDES_OFF_MODE_CTRL);
40f1aea80b53b8 Markus Stockhausen 2024-10-07 638 rtsds_931x_set_mode(ctrl, sid, modeoff);
40f1aea80b53b8 Markus Stockhausen 2024-10-07 639 rtsds_931x_set_mode(ctrl, sid, modecur);
40f1aea80b53b8 Markus Stockhausen 2024-10-07 640 iowrite32(pwr, RTSDS_931X_PS_SERDES_OFF_MODE_CTRL);
40f1aea80b53b8 Markus Stockhausen 2024-10-07 641 }
40f1aea80b53b8 Markus Stockhausen 2024-10-07 642
40f1aea80b53b8 Markus Stockhausen 2024-10-07 643 return 0;
40f1aea80b53b8 Markus Stockhausen 2024-10-07 644 }
40f1aea80b53b8 Markus Stockhausen 2024-10-07 645
40f1aea80b53b8 Markus Stockhausen 2024-10-07 646 int rtsds_read(struct phy *phy, u32 page, u32 reg)
40f1aea80b53b8 Markus Stockhausen 2024-10-07 647 {
40f1aea80b53b8 Markus Stockhausen 2024-10-07 648 struct rtsds_macro *macro = phy_get_drvdata(phy);
40f1aea80b53b8 Markus Stockhausen 2024-10-07 649 struct rtsds_ctrl *ctrl = macro->ctrl;
40f1aea80b53b8 Markus Stockhausen 2024-10-07 650 u32 sid = macro->sid;
40f1aea80b53b8 Markus Stockhausen 2024-10-07 651
40f1aea80b53b8 Markus Stockhausen 2024-10-07 652 return ctrl->conf->read(ctrl, sid, page, reg);
40f1aea80b53b8 Markus Stockhausen 2024-10-07 653 }
40f1aea80b53b8 Markus Stockhausen 2024-10-07 654
40f1aea80b53b8 Markus Stockhausen 2024-10-07 655 int rtsds_mask(struct phy *phy, u32 page, u32 reg, u32 val, u32 mask)
40f1aea80b53b8 Markus Stockhausen 2024-10-07 656 {
40f1aea80b53b8 Markus Stockhausen 2024-10-07 657 struct rtsds_macro *macro = phy_get_drvdata(phy);
40f1aea80b53b8 Markus Stockhausen 2024-10-07 658 struct rtsds_ctrl *ctrl = macro->ctrl;
40f1aea80b53b8 Markus Stockhausen 2024-10-07 659 u32 sid = macro->sid;
40f1aea80b53b8 Markus Stockhausen 2024-10-07 660
40f1aea80b53b8 Markus Stockhausen 2024-10-07 661 if (rtsds_readonly(ctrl, sid))
40f1aea80b53b8 Markus Stockhausen 2024-10-07 662 return 0;
40f1aea80b53b8 Markus Stockhausen 2024-10-07 663
40f1aea80b53b8 Markus Stockhausen 2024-10-07 664 return ctrl->conf->mask(ctrl, sid, page, reg, val, mask);
40f1aea80b53b8 Markus Stockhausen 2024-10-07 665 }
40f1aea80b53b8 Markus Stockhausen 2024-10-07 666
40f1aea80b53b8 Markus Stockhausen 2024-10-07 667 int rtsds_write(struct phy *phy, u32 page, u32 reg, u32 val)
40f1aea80b53b8 Markus Stockhausen 2024-10-07 668 {
40f1aea80b53b8 Markus Stockhausen 2024-10-07 669 return rtsds_mask(phy, page, reg, val, 0xffff);
40f1aea80b53b8 Markus Stockhausen 2024-10-07 670 }
40f1aea80b53b8 Markus Stockhausen 2024-10-07 671
40f1aea80b53b8 Markus Stockhausen 2024-10-07 672 static int rtsds_phy_init(struct phy *phy)
40f1aea80b53b8 Markus Stockhausen 2024-10-07 673 {
40f1aea80b53b8 Markus Stockhausen 2024-10-07 674 struct rtsds_macro *macro = phy_get_drvdata(phy);
40f1aea80b53b8 Markus Stockhausen 2024-10-07 675 struct rtsds_ctrl *ctrl = macro->ctrl;
40f1aea80b53b8 Markus Stockhausen 2024-10-07 676 u32 sid = macro->sid;
40f1aea80b53b8 Markus Stockhausen 2024-10-07 677 int ret;
40f1aea80b53b8 Markus Stockhausen 2024-10-07 678
40f1aea80b53b8 Markus Stockhausen 2024-10-07 679 if (rtsds_readonly(ctrl, sid))
40f1aea80b53b8 Markus Stockhausen 2024-10-07 680 return 0;
40f1aea80b53b8 Markus Stockhausen 2024-10-07 681
40f1aea80b53b8 Markus Stockhausen 2024-10-07 682 mutex_lock(&ctrl->lock);
40f1aea80b53b8 Markus Stockhausen 2024-10-07 683 // ret = rtsds_run_event(ctrl, sid, RTSDS_EVENT_INIT);
40f1aea80b53b8 Markus Stockhausen 2024-10-07 684 mutex_unlock(&ctrl->lock);
40f1aea80b53b8 Markus Stockhausen 2024-10-07 685
40f1aea80b53b8 Markus Stockhausen 2024-10-07 @686 if (ret)
40f1aea80b53b8 Markus Stockhausen 2024-10-07 687 dev_err(ctrl->dev, "init failed for SerDes %d\n", sid);
40f1aea80b53b8 Markus Stockhausen 2024-10-07 688
40f1aea80b53b8 Markus Stockhausen 2024-10-07 689 return ret;
40f1aea80b53b8 Markus Stockhausen 2024-10-07 690 }
40f1aea80b53b8 Markus Stockhausen 2024-10-07 691
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
^ permalink raw reply [flat|nested] 22+ messages in thread
* AW: AW: [PATCH v2 1/3] dt-bindings: phy: add realtek,otto-serdes PHY binding
2024-10-08 6:17 ` Krzysztof Kozlowski
@ 2024-10-08 6:56 ` markus.stockhausen
2024-10-08 8:32 ` Krzysztof Kozlowski
0 siblings, 1 reply; 22+ messages in thread
From: markus.stockhausen @ 2024-10-08 6:56 UTC (permalink / raw)
To: 'Krzysztof Kozlowski', linux-phy, chris.packham,
devicetree
> -----Ursprüngliche Nachricht-----
> Von: Krzysztof Kozlowski <krzk@kernel.org>
> Gesendet: Dienstag, 8. Oktober 2024 08:17
> An: markus.stockhausen@gmx.de; linux-phy@lists.infradead.org; chris.packham@alliedtelesis.co.nz; devicetree@vger.kernel.org
> Betreff: Re: AW: [PATCH v2 1/3] dt-bindings: phy: add realtek,otto-serdes PHY binding
>
> On 08/10/2024 07:38, markus.stockhausen@gmx.de wrote:
> >> -----Ursprüngliche Nachricht-----
> >> Von: Krzysztof Kozlowski <krzk@kernel.org>
> >> Gesendet: Montag, 7. Oktober 2024 21:26
> >> An: Markus Stockhausen <markus.stockhausen@gmx.de>;
> >> linux-phy@lists.infradead.org; chris.packham@alliedtelesis.co.nz;
> >> devicetree@vger.kernel.org
> >> Betreff: Re: [PATCH v2 1/3] dt-bindings: phy: add realtek,otto-serdes
> >> PHY binding
> >>
> >> ... and still not tested. Sending untested code is waste of our time.
> >
> > Hi Krzysztof,
> >
> > appreciate your feedback and I do not want to waste your time. My
> > fixes where a mix of your feedback and some half-baked "make
> > dt_binding_check" feedbacks (because packages where missing). My fault and sorry fort he noise.
> >
> > To get next version in better shape two questions regarding your feedback:
> >
> > 1. "Messed wrapping": According to checkpatch 100 chars/line are accepted.
> > So I designed the comments in the driver. Does devicetree differ from that?
>
> checkpatch is not a coding style. I asked to follow coding style, please read entire document in Documentation/process.
Understood.
> >
> > 2 "Bindings vs drivers". The idea about controlled ports came from other bindings.
>
> Entire property description speaks about driver, not bindings.
>
> > https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tre
> > e/Documentation/devicetree/bindings/interrupt-controller/st,stih407-ir
> > q-syscfg.yaml?h=v6.12-rc2
>
> stih is rather poor example to use. The property was added in 2015 (!) without review (!!!).
>
>
> > E.g. st,invert-ext. Something like this will be needed in the future
> > because the SerDes allow to swap polarity which must be changed
> > depending on the switch design. How to do this?
>
> I do not understand the hardware aspect discussed in the property description... probably because there is no hardware description at all, but instead you speak about driver.
>
> I do not understand how polarity has anything to do with U-Boot configuring serdes.
Maybe my lack of knowledge in platform driver programming or the naming
conventions leads to confusion. I'm searching for knobs to control the behaviour
of the SerDes depending on the hardware. Two examples are (more may come):
- "ignore SerDes X": because the provided patch sequence confuses the SerDes
and overwrites registers with wrong values that vendor patched U-Boot has setup
correctly before.
- "reverse polarity of SerDes X": same goes here. Some boards need inverted
signalling on some of the SerDes to work properly. This must be configurable
somehow.
Looking at some more modern implementation/documentation I need soemthing
like in realtek,usb2phy.yaml - e.g. realtek,driving-level-compensate.
Should I just leave "driver" out of the description?
Best regards.
Markus
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH v2 1/3] dt-bindings: phy: add realtek,otto-serdes PHY binding
2024-10-07 16:36 ` [PATCH v2 1/3] dt-bindings: phy: add realtek,otto-serdes PHY binding Markus Stockhausen
` (2 preceding siblings ...)
2024-10-07 19:30 ` Rob Herring
@ 2024-10-08 7:04 ` Krzysztof Kozlowski
2024-10-08 7:06 ` Krzysztof Kozlowski
4 siblings, 0 replies; 22+ messages in thread
From: Krzysztof Kozlowski @ 2024-10-08 7:04 UTC (permalink / raw)
To: Markus Stockhausen, linux-phy, chris.packham, devicetree
On 07/10/2024 18:36, Markus Stockhausen wrote:
> Add bindings for the SerDes of the Realtek Otto platform. These are
> network Switch SoCs with up to 52 ports divided into four different
> model lines.
>
> Changes in v2:
> - new subject
> - removed patch command sequences
> - renamed parameter controlled-ports to realtek,controlled-ports
<form letter>
Please use scripts/get_maintainers.pl to get a list of necessary people
and lists to CC (and consider --no-git-fallback argument, so you will
not CC people just because they made one commit years ago). It might
happen, that command when run on an older kernel, gives you outdated
entries. Therefore please be sure you base your patches on recent Linux
kernel.
Tools like b4 or scripts/get_maintainer.pl provide you proper list of
people, so fix your workflow. Tools might also fail if you work on some
ancient tree (don't, instead use mainline) or work on fork of kernel
(don't, instead use mainline). Just use b4 and everything should be
fine, although remember about `b4 prep --auto-to-cc` if you added new
patches to the patchset.
</form letter>
I already commented on this. The Cc list is still wrong. Please start
using tools which do it automatically and you do not have to perform any
choice of addresses.
Best regards,
Krzysztof
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH v2 1/3] dt-bindings: phy: add realtek,otto-serdes PHY binding
2024-10-07 16:36 ` [PATCH v2 1/3] dt-bindings: phy: add realtek,otto-serdes PHY binding Markus Stockhausen
` (3 preceding siblings ...)
2024-10-08 7:04 ` Krzysztof Kozlowski
@ 2024-10-08 7:06 ` Krzysztof Kozlowski
4 siblings, 0 replies; 22+ messages in thread
From: Krzysztof Kozlowski @ 2024-10-08 7:06 UTC (permalink / raw)
To: Markus Stockhausen, linux-phy, chris.packham, devicetree
On 07/10/2024 18:36, Markus Stockhausen wrote:
> + compatible:
> + items:
> + - enum:
> + - realtek,rtl8380-serdes
> + - realtek,rtl8390-serdes
> + - realtek,rtl9300-serdes
It turns out there is no chip like 9300. Align with Chris Packham,
because it is not a superposition-SoC (exists and does not exist the
same time, unless you check in given binding).
Best regards,
Krzysztof
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH v2 3/3] phy: Integrate Realtek Otto SerDes driver into build system
2024-10-07 16:36 ` [PATCH v2 3/3] phy: Integrate Realtek Otto SerDes driver into build system Markus Stockhausen
2024-10-07 19:27 ` Krzysztof Kozlowski
2024-10-08 6:38 ` kernel test robot
@ 2024-10-08 7:20 ` kernel test robot
2024-10-08 8:21 ` kernel test robot
3 siblings, 0 replies; 22+ messages in thread
From: kernel test robot @ 2024-10-08 7:20 UTC (permalink / raw)
To: Markus Stockhausen, linux-phy, chris.packham, devicetree, krzk
Cc: oe-kbuild-all, Markus Stockhausen
Hi Markus,
kernel test robot noticed the following build errors:
[auto build test ERROR on robh/for-next]
[also build test ERROR on krzk-dt/for-next linus/master v6.12-rc2 next-20241004]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]
url: https://github.com/intel-lab-lkp/linux/commits/Markus-Stockhausen/dt-bindings-phy-add-realtek-otto-serdes-PHY-binding/20241008-003929
base: https://git.kernel.org/pub/scm/linux/kernel/git/robh/linux.git for-next
patch link: https://lore.kernel.org/r/20241007163623.3274510-4-markus.stockhausen%40gmx.de
patch subject: [PATCH v2 3/3] phy: Integrate Realtek Otto SerDes driver into build system
config: alpha-allyesconfig (https://download.01.org/0day-ci/archive/20241008/202410081449.rLWpQtUj-lkp@intel.com/config)
compiler: alpha-linux-gcc (GCC) 13.3.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20241008/202410081449.rLWpQtUj-lkp@intel.com/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202410081449.rLWpQtUj-lkp@intel.com/
All errors (new ones prefixed by >>):
In file included from include/linux/debugfs.h:16,
from drivers/phy/realtek/phy-rtk-otto-serdes.c:7:
drivers/phy/realtek/phy-rtk-otto-serdes.c: In function 'rtsds_dbg_mode_open':
>> drivers/phy/realtek/phy-rtk-otto-serdes.c:868:29: error: passing argument 2 of 'single_open' from incompatible pointer type [-Werror=incompatible-pointer-types]
868 | DEFINE_SHOW_STORE_ATTRIBUTE(rtsds_dbg_mode);
| ^~~~~~~~~~~~~~
| |
| ssize_t (*)(struct seq_file *, void *) {aka long int (*)(struct seq_file *, void *)}
include/linux/seq_file.h:223:34: note: in definition of macro 'DEFINE_SHOW_STORE_ATTRIBUTE'
223 | return single_open(file, __name ## _show, inode->i_private); \
| ^~~~~~
include/linux/seq_file.h:176:32: note: expected 'int (*)(struct seq_file *, void *)' but argument is of type 'ssize_t (*)(struct seq_file *, void *)' {aka 'long int (*)(struct seq_file *, void *)'}
176 | int single_open(struct file *, int (*)(struct seq_file *, void *), void *);
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
drivers/phy/realtek/phy-rtk-otto-serdes.c: In function 'rtsds_dbg_reset_open':
drivers/phy/realtek/phy-rtk-otto-serdes.c:891:29: error: passing argument 2 of 'single_open' from incompatible pointer type [-Werror=incompatible-pointer-types]
891 | DEFINE_SHOW_STORE_ATTRIBUTE(rtsds_dbg_reset);
| ^~~~~~~~~~~~~~~
| |
| ssize_t (*)(struct seq_file *, void *) {aka long int (*)(struct seq_file *, void *)}
include/linux/seq_file.h:223:34: note: in definition of macro 'DEFINE_SHOW_STORE_ATTRIBUTE'
223 | return single_open(file, __name ## _show, inode->i_private); \
| ^~~~~~
include/linux/seq_file.h:176:32: note: expected 'int (*)(struct seq_file *, void *)' but argument is of type 'ssize_t (*)(struct seq_file *, void *)' {aka 'long int (*)(struct seq_file *, void *)'}
176 | int single_open(struct file *, int (*)(struct seq_file *, void *), void *);
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
cc1: some warnings being treated as errors
vim +/single_open +868 drivers/phy/realtek/phy-rtk-otto-serdes.c
40f1aea80b53b8 Markus Stockhausen 2024-10-07 847
40f1aea80b53b8 Markus Stockhausen 2024-10-07 848 static ssize_t rtsds_dbg_mode_write(struct file *file, const char __user *userbuf,
40f1aea80b53b8 Markus Stockhausen 2024-10-07 849 size_t count, loff_t *ppos)
40f1aea80b53b8 Markus Stockhausen 2024-10-07 850 {
40f1aea80b53b8 Markus Stockhausen 2024-10-07 851 struct seq_file *seqf = file->private_data;
40f1aea80b53b8 Markus Stockhausen 2024-10-07 852 struct rtsds_macro *macro = dev_get_drvdata(seqf->private);
40f1aea80b53b8 Markus Stockhausen 2024-10-07 853 struct rtsds_ctrl *ctrl = macro->ctrl;
40f1aea80b53b8 Markus Stockhausen 2024-10-07 854 int ret, hwmode, phymode, sid = macro->sid;
40f1aea80b53b8 Markus Stockhausen 2024-10-07 855
40f1aea80b53b8 Markus Stockhausen 2024-10-07 856 ret = kstrtou32_from_user(userbuf, count, 16, &hwmode);
40f1aea80b53b8 Markus Stockhausen 2024-10-07 857 if (ret)
40f1aea80b53b8 Markus Stockhausen 2024-10-07 858 return ret;
40f1aea80b53b8 Markus Stockhausen 2024-10-07 859 /*
40f1aea80b53b8 Markus Stockhausen 2024-10-07 860 * Allow to set arbitrary modes into the SerDes to improve error analysis. Accept that
40f1aea80b53b8 Markus Stockhausen 2024-10-07 861 * this might confuse the internal state tracking.
40f1aea80b53b8 Markus Stockhausen 2024-10-07 862 */
40f1aea80b53b8 Markus Stockhausen 2024-10-07 863 phymode = rtsds_hwmode_to_phymode(ctrl, hwmode);
40f1aea80b53b8 Markus Stockhausen 2024-10-07 864 rtsds_phy_set_mode_int(ctrl, sid, phymode, hwmode);
40f1aea80b53b8 Markus Stockhausen 2024-10-07 865
40f1aea80b53b8 Markus Stockhausen 2024-10-07 866 return count;
40f1aea80b53b8 Markus Stockhausen 2024-10-07 867 }
40f1aea80b53b8 Markus Stockhausen 2024-10-07 @868 DEFINE_SHOW_STORE_ATTRIBUTE(rtsds_dbg_mode);
40f1aea80b53b8 Markus Stockhausen 2024-10-07 869
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH v2 3/3] phy: Integrate Realtek Otto SerDes driver into build system
2024-10-07 16:36 ` [PATCH v2 3/3] phy: Integrate Realtek Otto SerDes driver into build system Markus Stockhausen
` (2 preceding siblings ...)
2024-10-08 7:20 ` kernel test robot
@ 2024-10-08 8:21 ` kernel test robot
3 siblings, 0 replies; 22+ messages in thread
From: kernel test robot @ 2024-10-08 8:21 UTC (permalink / raw)
To: Markus Stockhausen, linux-phy, chris.packham, devicetree, krzk
Cc: llvm, oe-kbuild-all, Markus Stockhausen
Hi Markus,
kernel test robot noticed the following build errors:
[auto build test ERROR on robh/for-next]
[also build test ERROR on krzk-dt/for-next linus/master v6.12-rc2 next-20241004]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]
url: https://github.com/intel-lab-lkp/linux/commits/Markus-Stockhausen/dt-bindings-phy-add-realtek-otto-serdes-PHY-binding/20241008-003929
base: https://git.kernel.org/pub/scm/linux/kernel/git/robh/linux.git for-next
patch link: https://lore.kernel.org/r/20241007163623.3274510-4-markus.stockhausen%40gmx.de
patch subject: [PATCH v2 3/3] phy: Integrate Realtek Otto SerDes driver into build system
config: x86_64-allyesconfig (https://download.01.org/0day-ci/archive/20241008/202410081607.EKE62jfx-lkp@intel.com/config)
compiler: clang version 18.1.8 (https://github.com/llvm/llvm-project 3b5b5c1ec4a3095ab096dd780e84d7ab81f3d7ff)
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20241008/202410081607.EKE62jfx-lkp@intel.com/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202410081607.EKE62jfx-lkp@intel.com/
All errors (new ones prefixed by >>):
drivers/phy/realtek/phy-rtk-otto-serdes.c:490:15: warning: overlapping comparisons always evaluate to true [-Wtautological-overlap-compare]
490 | if (sid >= 2 || sid <= 9)
| ~~~~~~~~~^~~~~~~~~~~
drivers/phy/realtek/phy-rtk-otto-serdes.c:509:15: warning: overlapping comparisons always evaluate to true [-Wtautological-overlap-compare]
509 | if (sid >= 2 || sid <= 9)
| ~~~~~~~~~^~~~~~~~~~~
drivers/phy/realtek/phy-rtk-otto-serdes.c:686:6: warning: variable 'ret' is uninitialized when used here [-Wuninitialized]
686 | if (ret)
| ^~~
drivers/phy/realtek/phy-rtk-otto-serdes.c:677:9: note: initialize the variable 'ret' to silence this warning
677 | int ret;
| ^
| = 0
drivers/phy/realtek/phy-rtk-otto-serdes.c:706:6: warning: variable 'ret' is uninitialized when used here [-Wuninitialized]
706 | if (ret)
| ^~~
drivers/phy/realtek/phy-rtk-otto-serdes.c:697:9: note: initialize the variable 'ret' to silence this warning
697 | int ret;
| ^
| = 0
drivers/phy/realtek/phy-rtk-otto-serdes.c:723:7: warning: variable 'ret' is uninitialized when used here [-Wuninitialized]
723 | if (!ret)
| ^~~
drivers/phy/realtek/phy-rtk-otto-serdes.c:717:9: note: initialize the variable 'ret' to silence this warning
717 | int ret;
| ^
| = 0
>> drivers/phy/realtek/phy-rtk-otto-serdes.c:868:1: error: incompatible function pointer types passing 'ssize_t (struct seq_file *, void *)' (aka 'long (struct seq_file *, void *)') to parameter of type 'int (*)(struct seq_file *, void *)' [-Wincompatible-function-pointer-types]
868 | DEFINE_SHOW_STORE_ATTRIBUTE(rtsds_dbg_mode);
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
include/linux/seq_file.h:223:27: note: expanded from macro 'DEFINE_SHOW_STORE_ATTRIBUTE'
223 | return single_open(file, __name ## _show, inode->i_private); \
| ^~~~~~~~~~~~~~~
<scratch space>:49:1: note: expanded from here
49 | rtsds_dbg_mode_show
| ^~~~~~~~~~~~~~~~~~~
include/linux/seq_file.h:176:38: note: passing argument to parameter here
176 | int single_open(struct file *, int (*)(struct seq_file *, void *), void *);
| ^
drivers/phy/realtek/phy-rtk-otto-serdes.c:891:1: error: incompatible function pointer types passing 'ssize_t (struct seq_file *, void *)' (aka 'long (struct seq_file *, void *)') to parameter of type 'int (*)(struct seq_file *, void *)' [-Wincompatible-function-pointer-types]
891 | DEFINE_SHOW_STORE_ATTRIBUTE(rtsds_dbg_reset);
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
include/linux/seq_file.h:223:27: note: expanded from macro 'DEFINE_SHOW_STORE_ATTRIBUTE'
223 | return single_open(file, __name ## _show, inode->i_private); \
| ^~~~~~~~~~~~~~~
<scratch space>:54:1: note: expanded from here
54 | rtsds_dbg_reset_show
| ^~~~~~~~~~~~~~~~~~~~
include/linux/seq_file.h:176:38: note: passing argument to parameter here
176 | int single_open(struct file *, int (*)(struct seq_file *, void *), void *);
| ^
5 warnings and 2 errors generated.
Kconfig warnings: (for reference only)
WARNING: unmet direct dependencies detected for MODVERSIONS
Depends on [n]: MODULES [=y] && !COMPILE_TEST [=y]
Selected by [y]:
- RANDSTRUCT_FULL [=y] && (CC_HAS_RANDSTRUCT [=y] || GCC_PLUGINS [=n]) && MODULES [=y]
vim +868 drivers/phy/realtek/phy-rtk-otto-serdes.c
40f1aea80b53b8 Markus Stockhausen 2024-10-07 847
40f1aea80b53b8 Markus Stockhausen 2024-10-07 848 static ssize_t rtsds_dbg_mode_write(struct file *file, const char __user *userbuf,
40f1aea80b53b8 Markus Stockhausen 2024-10-07 849 size_t count, loff_t *ppos)
40f1aea80b53b8 Markus Stockhausen 2024-10-07 850 {
40f1aea80b53b8 Markus Stockhausen 2024-10-07 851 struct seq_file *seqf = file->private_data;
40f1aea80b53b8 Markus Stockhausen 2024-10-07 852 struct rtsds_macro *macro = dev_get_drvdata(seqf->private);
40f1aea80b53b8 Markus Stockhausen 2024-10-07 853 struct rtsds_ctrl *ctrl = macro->ctrl;
40f1aea80b53b8 Markus Stockhausen 2024-10-07 854 int ret, hwmode, phymode, sid = macro->sid;
40f1aea80b53b8 Markus Stockhausen 2024-10-07 855
40f1aea80b53b8 Markus Stockhausen 2024-10-07 856 ret = kstrtou32_from_user(userbuf, count, 16, &hwmode);
40f1aea80b53b8 Markus Stockhausen 2024-10-07 857 if (ret)
40f1aea80b53b8 Markus Stockhausen 2024-10-07 858 return ret;
40f1aea80b53b8 Markus Stockhausen 2024-10-07 859 /*
40f1aea80b53b8 Markus Stockhausen 2024-10-07 860 * Allow to set arbitrary modes into the SerDes to improve error analysis. Accept that
40f1aea80b53b8 Markus Stockhausen 2024-10-07 861 * this might confuse the internal state tracking.
40f1aea80b53b8 Markus Stockhausen 2024-10-07 862 */
40f1aea80b53b8 Markus Stockhausen 2024-10-07 863 phymode = rtsds_hwmode_to_phymode(ctrl, hwmode);
40f1aea80b53b8 Markus Stockhausen 2024-10-07 864 rtsds_phy_set_mode_int(ctrl, sid, phymode, hwmode);
40f1aea80b53b8 Markus Stockhausen 2024-10-07 865
40f1aea80b53b8 Markus Stockhausen 2024-10-07 866 return count;
40f1aea80b53b8 Markus Stockhausen 2024-10-07 867 }
40f1aea80b53b8 Markus Stockhausen 2024-10-07 @868 DEFINE_SHOW_STORE_ATTRIBUTE(rtsds_dbg_mode);
40f1aea80b53b8 Markus Stockhausen 2024-10-07 869
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: AW: AW: [PATCH v2 1/3] dt-bindings: phy: add realtek,otto-serdes PHY binding
2024-10-08 6:56 ` AW: " markus.stockhausen
@ 2024-10-08 8:32 ` Krzysztof Kozlowski
2024-10-08 9:27 ` AW: " markus.stockhausen
0 siblings, 1 reply; 22+ messages in thread
From: Krzysztof Kozlowski @ 2024-10-08 8:32 UTC (permalink / raw)
To: markus.stockhausen, linux-phy, chris.packham, devicetree
On 08/10/2024 08:56, markus.stockhausen@gmx.de wrote:
>>
>>> E.g. st,invert-ext. Something like this will be needed in the future
>>> because the SerDes allow to swap polarity which must be changed
>>> depending on the switch design. How to do this?
>>
>> I do not understand the hardware aspect discussed in the property description... probably because there is no hardware description at all, but instead you speak about driver.
>>
>> I do not understand how polarity has anything to do with U-Boot configuring serdes.
>
> Maybe my lack of knowledge in platform driver programming or the naming
> conventions leads to confusion. I'm searching for knobs to control the behaviour
> of the SerDes depending on the hardware. Two examples are (more may come):
>
> - "ignore SerDes X": because the provided patch sequence confuses the SerDes
> and overwrites registers with wrong values that vendor patched U-Boot has setup
> correctly before.
And if someone updates the bootloader to a bit different one, the DTS
becomes wrong? How do you handle then same board with two different
bootloaders requiring two different DTS? DTS is software-independent
description of the hardware, so this does not look like DTS property.
>
> - "reverse polarity of SerDes X": same goes here. Some boards need inverted
> signalling on some of the SerDes to work properly. This must be configurable
> somehow.
I do not see how this is related to "control ports" property. There are
few bindings which already do this, so look at them.
Best regards,
Krzysztof
^ permalink raw reply [flat|nested] 22+ messages in thread
* AW: AW: AW: [PATCH v2 1/3] dt-bindings: phy: add realtek,otto-serdes PHY binding
2024-10-08 8:32 ` Krzysztof Kozlowski
@ 2024-10-08 9:27 ` markus.stockhausen
0 siblings, 0 replies; 22+ messages in thread
From: markus.stockhausen @ 2024-10-08 9:27 UTC (permalink / raw)
To: 'Krzysztof Kozlowski', linux-phy, chris.packham,
devicetree
> -----Ursprüngliche Nachricht-----
> Von: Krzysztof Kozlowski <krzk@kernel.org>
> Gesendet: Dienstag, 8. Oktober 2024 10:32
> An: markus.stockhausen@gmx.de; linux-phy@lists.infradead.org; chris.packham@alliedtelesis.co.nz; devicetree@vger.kernel.org
> Betreff: Re: AW: AW: [PATCH v2 1/3] dt-bindings: phy: add realtek,otto-serdes PHY binding
>
> On 08/10/2024 08:56, markus.stockhausen@gmx.de wrote:
> >>
> >>> E.g. st,invert-ext. Something like this will be needed in the future
> >>> because the SerDes allow to swap polarity which must be changed
> >>> depending on the switch design. How to do this?
> >>
> >> I do not understand the hardware aspect discussed in the property description... probably because there is no hardware description at all, but instead you speak about driver.
> >>
> >> I do not understand how polarity has anything to do with U-Boot configuring serdes.
> >
> > Maybe my lack of knowledge in platform driver programming or the
> > naming conventions leads to confusion. I'm searching for knobs to
> > control the behaviour of the SerDes depending on the hardware. Two examples are (more may come):
> >
> > - "ignore SerDes X": because the provided patch sequence confuses the
> > SerDes and overwrites registers with wrong values that vendor patched
> > U-Boot has setup correctly before.
>
> And if someone updates the bootloader to a bit different one, the DTS
> becomes wrong? How do you handle then same board with two different
> bootloaders requiring two different DTS? DTS is software-independent
> description of the hardware, so this does not look like DTS property.
Good point. So the initial idea to provide dynamic patch sequences was
the right direction but storing in devicetree is wrong. Like Chris mentioned
I would change the code to make use of a dynamically loaded firmware file.
- if exist: run sequences from there
- if not exist: keep registers as is.
Reasonable idea?
Best regards.
Markus
^ permalink raw reply [flat|nested] 22+ messages in thread
* AW: [PATCH v2 1/3] dt-bindings: phy: add realtek,otto-serdes PHY binding
2024-10-07 19:30 ` Rob Herring
@ 2024-10-08 12:27 ` markus.stockhausen
0 siblings, 0 replies; 22+ messages in thread
From: markus.stockhausen @ 2024-10-08 12:27 UTC (permalink / raw)
To: 'Rob Herring'; +Cc: linux-phy, chris.packham, devicetree, krzk
> -----Ursprüngliche Nachricht-----
> Von: Rob Herring <robh@kernel.org>
> Gesendet: Montag, 7. Oktober 2024 21:31
> An: Markus Stockhausen <markus.stockhausen@gmx.de>
> Cc: linux-phy@lists.infradead.org; chris.packham@alliedtelesis.co.nz;
devicetree@vger.kernel.org; krzk@kernel.org
> Betreff: Re: [PATCH v2 1/3] dt-bindings: phy: add realtek,otto-serdes PHY
binding
> ...
> > +
> > +properties:
> > + $nodename:
> > + pattern: "^serdes@[0-9a-f]+$"
>
> The node name for phy providers is 'phy'.
Hi Rob,
I found different configs in other files. E.g.
- torrent-phy@f0fb500000
- serdes: serdes@e2004010
- serdes_phy: phy@8901000
Do I understand correctly that I should go with "serdes: phy@1b00e780"?
If yes, adapt the $nodename pattern accordingly or drop it as in most other
files?
Best regards.
Markus
^ permalink raw reply [flat|nested] 22+ messages in thread
* AW: [PATCH v2 1/3] dt-bindings: phy: add realtek,otto-serdes PHY binding
2024-10-07 19:26 ` Krzysztof Kozlowski
2024-10-08 5:38 ` AW: " markus.stockhausen
@ 2024-10-16 15:30 ` markus.stockhausen
2024-10-17 6:15 ` Krzysztof Kozlowski
1 sibling, 1 reply; 22+ messages in thread
From: markus.stockhausen @ 2024-10-16 15:30 UTC (permalink / raw)
To: 'Krzysztof Kozlowski', linux-phy, chris.packham,
devicetree
Hi Krzysztof,
with your feedback on the latest version I will take up the issues from
v2 once again. To be sure that I do not miss anything in upcoming v5
I will comment on all your feedback.
> > ....
> > Changes in v2:
> > - new subject
> > - removed patch command sequences
> > - renamed parameter controlled-ports to realtek,controlled-ports
>
> Changelog goes under ---.
After reading this another 4 times now I think I understand. You mean
"put changelog below signed-off-by". Will do with next patch.
> > ....
> > diff --git
> > a/Documentation/devicetree/bindings/phy/realtek,otto-serdes.yaml
> > b/Documentation/devicetree/bindings/phy/realtek,otto-serdes.yaml
> > new file mode 100644
> > index 000000000000..a72ac206b35f
> > --- /dev/null
> > +++ b/Documentation/devicetree/bindings/phy/realtek,otto-serdes.yaml
>
> Nothing improved.
In between renamed to compatible "realtek,rtl8380m-serdes.yaml". I hope
that fits the requested naming convention.
> > + The driver exposes the SerDes registers different from the hardware
> > + but instead gives a consistent view and programming interface. So
> > + the RTL838x series has 6 ports and 4 pages, the RTL839x has 14
> > + ports and 12 pages, the RTL930x has 12 ports and 64 pages and the
> > + RTL931x has
> > + 14 ports and 192 pages.
>
> Totally messed wrapping. Please wrap your code as Linux coding style.
Was restyled in between. If this is still an issue in latest version, please advise.
> > + reg:
> > + items:
> > + description:
> > + The primary SerDes paged register memory location. Other SerDes control and management
> > + registers are distributed all over the I/O memory space and are identified by the driver.
>
> What happened here? I asked only about |. Why are you adding unrelated changes?
>
> Anyway, still not tested and still does not look any other binding.
Has been tested in between with "make dt_binding_check".
> > + realtek,controlled-ports:
> > + $ref: /schemas/types.yaml#/definitions/uint32
> > + description:
> > + A bit mask defining the ports that are actively controlled by
> > + the driver. In case a bit is
>
> Driver? Bindings are not about drivers. Drop.
>
> I don't think you implemented my feedback.
All these have been removed.
> > +additionalProperties:
> > + false
>
> Please open any existing binding and do it like there. Or start from scratch from example-schema.
Was converted to one line.
> > +
> > +examples:
> > + - |
> > + serdes: serdes@1b00e780 {
> > + compatible = "realtek,rtl8380-serdes", "realtek,otto-serdes";
> > + reg = <0x1b00e780 0x1200>;
> > + controlled-ports = <0x003f>;
> > + #phy-cells = <4>;
> > + };
>
> One example is enough.
Only one example left.
Best regards.
Markus
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: AW: [PATCH v2 1/3] dt-bindings: phy: add realtek,otto-serdes PHY binding
2024-10-16 15:30 ` markus.stockhausen
@ 2024-10-17 6:15 ` Krzysztof Kozlowski
0 siblings, 0 replies; 22+ messages in thread
From: Krzysztof Kozlowski @ 2024-10-17 6:15 UTC (permalink / raw)
To: markus.stockhausen, linux-phy, chris.packham, devicetree
On 16/10/2024 17:30, markus.stockhausen@gmx.de wrote:
> Hi Krzysztof,
>
> with your feedback on the latest version I will take up the issues from
> v2 once again. To be sure that I do not miss anything in upcoming v5
> I will comment on all your feedback.
>
>>> ....
>>> Changes in v2:
>>> - new subject
>>> - removed patch command sequences
>>> - renamed parameter controlled-ports to realtek,controlled-ports
>>
>> Changelog goes under ---.
>
> After reading this another 4 times now I think I understand. You mean
> "put changelog below signed-off-by". Will do with next patch.
--- is under Signed-off-by, so yes, but more importantly under ---.
>
>>> ....
>>> diff --git
>>> a/Documentation/devicetree/bindings/phy/realtek,otto-serdes.yaml
>>> b/Documentation/devicetree/bindings/phy/realtek,otto-serdes.yaml
>>> new file mode 100644
>>> index 000000000000..a72ac206b35f
>>> --- /dev/null
>>> +++ b/Documentation/devicetree/bindings/phy/realtek,otto-serdes.yaml
>>
>> Nothing improved.
>
> In between renamed to compatible "realtek,rtl8380m-serdes.yaml". I hope
> that fits the requested naming convention.
Yes.
>
>>> + The driver exposes the SerDes registers different from the hardware
>>> + but instead gives a consistent view and programming interface. So
>>> + the RTL838x series has 6 ports and 4 pages, the RTL839x has 14
>>> + ports and 12 pages, the RTL930x has 12 ports and 64 pages and the
>>> + RTL931x has
>>> + 14 ports and 192 pages.
>>
>> Totally messed wrapping. Please wrap your code as Linux coding style.
>
> Was restyled in between. If this is still an issue in latest version, please advise.
It's ok, the rest as well.
Best regards,
Krzysztof
^ permalink raw reply [flat|nested] 22+ messages in thread
end of thread, other threads:[~2024-10-17 6:15 UTC | newest]
Thread overview: 22+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-10-07 16:36 [PATCH v2 0/3] phy: Realtek Otto SerDes: add new driver Markus Stockhausen
2024-10-07 16:36 ` [PATCH v2 1/3] dt-bindings: phy: add realtek,otto-serdes PHY binding Markus Stockhausen
2024-10-07 18:17 ` Rob Herring (Arm)
2024-10-07 19:26 ` Krzysztof Kozlowski
2024-10-08 5:38 ` AW: " markus.stockhausen
2024-10-08 6:17 ` Krzysztof Kozlowski
2024-10-08 6:56 ` AW: " markus.stockhausen
2024-10-08 8:32 ` Krzysztof Kozlowski
2024-10-08 9:27 ` AW: " markus.stockhausen
2024-10-16 15:30 ` markus.stockhausen
2024-10-17 6:15 ` Krzysztof Kozlowski
2024-10-07 19:30 ` Rob Herring
2024-10-08 12:27 ` AW: " markus.stockhausen
2024-10-08 7:04 ` Krzysztof Kozlowski
2024-10-08 7:06 ` Krzysztof Kozlowski
2024-10-07 16:36 ` [PATCH v2 2/3] phy: Realtek Otto SerDes driver Markus Stockhausen
2024-10-07 19:32 ` Krzysztof Kozlowski
2024-10-07 16:36 ` [PATCH v2 3/3] phy: Integrate Realtek Otto SerDes driver into build system Markus Stockhausen
2024-10-07 19:27 ` Krzysztof Kozlowski
2024-10-08 6:38 ` kernel test robot
2024-10-08 7:20 ` kernel test robot
2024-10-08 8:21 ` kernel test robot
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).