[PATCH 1/4] phy: Realtek Otto SerDes: add header file
Chris Packham
chris.packham at alliedtelesis.co.nz
Sun Oct 6 14:33:10 PDT 2024
On 5/10/24 08:56, Markus Stockhausen wrote:
> This adds the header file for the new Otto SerDes driver.
> ---
> drivers/phy/realtek/phy-rtl-otto-serdes.h | 126 ++++++++++++++++++++++
> 1 file changed, 126 insertions(+)
> create mode 100644 drivers/phy/realtek/phy-rtl-otto-serdes.h
>
> diff --git a/drivers/phy/realtek/phy-rtl-otto-serdes.h b/drivers/phy/realtek/phy-rtl-otto-serdes.h
> new file mode 100644
> index 000000000000..4d951731c02c
> --- /dev/null
> +++ b/drivers/phy/realtek/phy-rtl-otto-serdes.h
> @@ -0,0 +1,126 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Realtek RTL838x, RTL839x, RTL930x & RTL931x SerDes PHY driver
> + * Copyright (c) 2024 Markus Stockhausen <markus.stockhausen at gmx.de>
> + */
> +
> +#ifndef _PHY_RTL_OTTO_SERDES_H
> +#define _PHY_RTL_OTTO_SERDES_H
> +
> +#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>
> +
> +#define RTSDS_PAGE_SDS 0
> +#define RTSDS_PAGE_SDS_EXT 1
> +#define RTSDS_PAGE_FIB 2
> +#define RTSDS_PAGE_FIB_EXT 3
> +#define RTSDS_PAGE_NAMES 48
> +
> +#define RTSDS_INV_HSO 0x100
> +#define RTSDS_INV_HSI 0x200
> +
> +#define RTSDS_EVENT_SETUP 0
> +#define RTSDS_EVENT_INIT 1
> +#define RTSDS_EVENT_POWER_ON 2
> +#define RTSDS_EVENT_PRE_SET_MODE 3
> +#define RTSDS_EVENT_POST_SET_MODE 4
> +#define RTSDS_EVENT_PRE_RESET 5
> +#define RTSDS_EVENT_POST_RESET 6
> +#define RTSDS_EVENT_PRE_POWER_OFF 7
> +#define RTSDS_EVENT_POST_POWER_OFF 8
> +#define RTSDS_EVENT_MAX 8
> +
> +#define RTSDS_SEQ_STOP 0
> +#define RTSDS_SEQ_MASK 1
> +#define RTSDS_SEQ_WAIT 2
> +
> +#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)
I've started the process of adding the switch block as a syscon device.
I've only done a dts change for the rtl930x but I'm guessing the
RTL838x/839x are similar.
https://lore.kernel.org/lkml/20240925215847.3594898-5-chris.packham@alliedtelesis.co.nz/
These devices can also be run in a core disabled mode in which case the
registers are accessed via a SPI interface. It would probably make sense
to lean on regmap to allow for MMIO or SPI to be used.
> +
> +#define RTSDS_838X_MAX_SDS 5
> +#define RTSDS_838X_MAX_PAGE 3
> +#define RTSDS_838X_SDS_MODE_SEL RTSDS_REG(0x0028)
> +#define RTSDS_838X_INT_MODE_CTRL RTSDS_REG(0x005c)
> +
> +#define RTSDS_839X_MAX_SDS 13
> +#define RTSDS_839X_MAX_PAGE 11
> +#define RTSDS_839X_MAC_SERDES_IF_CTRL RTSDS_REG(0x0008)
> +
> +#define RTSDS_930X_MAX_SDS 11
> +#define RTSDS_930X_MAX_PAGE 63
> +#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_MAX_SDS 13
> +#define RTSDS_931X_MAX_PAGE 191
> +#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_COMBOMODE(mode, submode) (0x10000 | (mode << 8) | submode)
> +#define RTSDS_MODE(combomode) ((combomode >> 8) & 0xff)
> +#define RTSDS_SUBMODE(combomode) (combomode & 0xff)
> +
> +struct __attribute__ ((__packed__)) rtsds_seq {
> + u16 action;
> + 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_930X_MAX_SDS + 1];
> + struct rtsds_seq *sequence[RTSDS_EVENT_MAX + 1];
> +};
> +
> +struct rtsds_macro {
> + struct rtsds_ctrl *ctrl;
> + u32 sid;
> +};
> +
> +struct rtsds_conf {
> + u32 max_sds;
> + u32 max_page;
> + 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];
> +};
> +
> +/*
> + * 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_RTL_OTTO_SERDES_H */
> --
> 2.44.0
>
More information about the linux-phy
mailing list