Merge Official Source

Signed-off-by: Tianling Shen <cnsztl@immortalwrt.org>
This commit is contained in:
Tianling Shen 2023-03-28 15:51:22 +08:00
commit 62b1521045
No known key found for this signature in database
GPG Key ID: 6850B6345C862176
76 changed files with 8529 additions and 271 deletions

View File

@ -363,7 +363,7 @@ config KERNEL_DEBUG_INFO
config KERNEL_DEBUG_INFO_BTF
bool "Enable additional BTF type information"
default y if TARGET_armvirt || TARGET_bcm27xx || TARGET_ipq807x || TARGET_mediatek_filogic || TARGET_mvebu || TARGET_rockchip || TARGET_sunxi || TARGET_x86
default y if TARGET_bcm27xx || TARGET_ipq807x || TARGET_mediatek_filogic || TARGET_mvebu_cortexa53 || TARGET_mvebu_cortexa72 || TARGET_rockchip || TARGET_sunxi || TARGET_x86
depends on !HOST_OS_MACOS
depends on KERNEL_DEBUG_INFO && !KERNEL_DEBUG_INFO_REDUCED
select DWARVES
@ -376,7 +376,7 @@ config KERNEL_DEBUG_INFO_BTF
config KERNEL_DEBUG_INFO_REDUCED
bool "Reduce debugging information"
default y if !(TARGET_armvirt || TARGET_bcm27xx || TARGET_ipq807x || TARGET_mediatek_filogic || TARGET_mvebu || TARGET_rockchip || TARGET_sunxi || TARGET_x86)
default y if !(TARGET_bcm27xx || TARGET_ipq807x || TARGET_mediatek_filogic || TARGET_mvebu_cortexa53 || TARGET_mvebu_cortexa72 || TARGET_rockchip || TARGET_sunxi || TARGET_x86)
depends on KERNEL_DEBUG_INFO
help
If you say Y here gcc is instructed to generate less debugging

View File

@ -6,9 +6,9 @@ PKG_RELEASE:=1
PKG_SOURCE_PROTO:=git
PKG_SOURCE_URL=$(PROJECT_GIT)/project/firmware/qca-wireless.git
PKG_SOURCE_DATE:=2023-03-20
PKG_SOURCE_VERSION:=f9cece02724b8ca2c1a166a46f0afa89e632d431
PKG_MIRROR_HASH:=89c20798c7ec83114aa69467f2467fe32cbb74ebeca277c60a033af960ca6c04
PKG_SOURCE_DATE:=2023-03-27
PKG_SOURCE_VERSION:=ccd7e460cc798d90148a10539b6d94a5fd761004
PKG_MIRROR_HASH:=e51d28c741aeb0867493a7bfc801b8b1977c942ed5d51d62c1aa8729c91cce32
PKG_FLAGS:=nonshared

View File

@ -25,7 +25,7 @@ Signed-off-by: Naushir Patuck <naush@raspberrypi.com>
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -17530,6 +17530,14 @@ T: git git://linuxtv.org/media_tree.git
@@ -17538,6 +17538,14 @@ T: git git://linuxtv.org/media_tree.git
F: Documentation/devicetree/bindings/media/i2c/sony,imx412.yaml
F: drivers/media/i2c/imx412.c

View File

@ -132,7 +132,7 @@ Signed-off-by: David Plowman <david.plowman@raspberrypi.com>
+...
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -17544,6 +17544,7 @@ M: Raspberry Pi Kernel Maintenance <kern
@@ -17552,6 +17552,7 @@ M: Raspberry Pi Kernel Maintenance <kern
L: linux-media@vger.kernel.org
S: Maintained
T: git git://linuxtv.org/media_tree.git

View File

@ -132,7 +132,7 @@ Signed-off-by: Lee Jackson <info@arducam.com>
+...
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -17548,6 +17548,14 @@ F: Documentation/devicetree/bindings/med
@@ -17556,6 +17556,14 @@ F: Documentation/devicetree/bindings/med
F: Documentation/devicetree/bindings/media/i2c/imx477.yaml
F: drivers/media/i2c/imx477.c

View File

@ -0,0 +1,90 @@
From 86fc59ef818beb0e1945d17f8e734898baba7e4e Mon Sep 17 00:00:00 2001
From: Colin Foster <colin.foster@in-advantage.com>
Date: Sun, 13 Mar 2022 15:45:23 -0700
Subject: [PATCH 1/2] regmap: add configurable downshift for addresses
Add an additional reg_downshift to be applied to register addresses before
any register accesses. An example of a device that uses this is a VSC7514
chip, which require each register address to be downshifted by two if the
access is performed over a SPI bus.
Signed-off-by: Colin Foster <colin.foster@in-advantage.com>
Link: https://lore.kernel.org/r/20220313224524.399947-2-colin.foster@in-advantage.com
Signed-off-by: Mark Brown <broonie@kernel.org>
---
drivers/base/regmap/internal.h | 1 +
drivers/base/regmap/regmap.c | 5 +++++
include/linux/regmap.h | 3 +++
3 files changed, 9 insertions(+)
--- a/drivers/base/regmap/internal.h
+++ b/drivers/base/regmap/internal.h
@@ -31,6 +31,7 @@ struct regmap_format {
size_t buf_size;
size_t reg_bytes;
size_t pad_bytes;
+ size_t reg_downshift;
size_t val_bytes;
void (*format_write)(struct regmap *map,
unsigned int reg, unsigned int val);
--- a/drivers/base/regmap/regmap.c
+++ b/drivers/base/regmap/regmap.c
@@ -823,6 +823,7 @@ struct regmap *__regmap_init(struct devi
map->format.reg_bytes = DIV_ROUND_UP(config->reg_bits, 8);
map->format.pad_bytes = config->pad_bits / 8;
+ map->format.reg_downshift = config->reg_downshift;
map->format.val_bytes = DIV_ROUND_UP(config->val_bits, 8);
map->format.buf_size = DIV_ROUND_UP(config->reg_bits +
config->val_bits + config->pad_bits, 8);
@@ -1735,6 +1736,7 @@ static int _regmap_raw_write_impl(struct
return ret;
}
+ reg >>= map->format.reg_downshift;
map->format.format_reg(map->work_buf, reg, map->reg_shift);
regmap_set_work_buf_flag_mask(map, map->format.reg_bytes,
map->write_flag_mask);
@@ -1905,6 +1907,7 @@ static int _regmap_bus_formatted_write(v
return ret;
}
+ reg >>= map->format.reg_downshift;
map->format.format_write(map, reg, val);
trace_regmap_hw_write_start(map, reg, 1);
@@ -2346,6 +2349,7 @@ static int _regmap_raw_multi_reg_write(s
unsigned int reg = regs[i].reg;
unsigned int val = regs[i].def;
trace_regmap_hw_write_start(map, reg, 1);
+ reg >>= map->format.reg_downshift;
map->format.format_reg(u8, reg, map->reg_shift);
u8 += reg_bytes + pad_bytes;
map->format.format_val(u8, val, 0);
@@ -2673,6 +2677,7 @@ static int _regmap_raw_read(struct regma
return ret;
}
+ reg >>= map->format.reg_downshift;
map->format.format_reg(map->work_buf, reg, map->reg_shift);
regmap_set_work_buf_flag_mask(map, map->format.reg_bytes,
map->read_flag_mask);
--- a/include/linux/regmap.h
+++ b/include/linux/regmap.h
@@ -237,6 +237,8 @@ typedef void (*regmap_unlock)(void *);
* @reg_stride: The register address stride. Valid register addresses are a
* multiple of this value. If set to 0, a value of 1 will be
* used.
+ * @reg_downshift: The number of bits to downshift the register before
+ * performing any operations.
* @pad_bits: Number of bits of padding between register and value.
* @val_bits: Number of bits in a register value, mandatory.
*
@@ -360,6 +362,7 @@ struct regmap_config {
int reg_bits;
int reg_stride;
+ int reg_downshift;
int pad_bits;
int val_bits;

View File

@ -0,0 +1,95 @@
From 0074f3f2b1e43d3cedd97e47fb6980db6d2ba79e Mon Sep 17 00:00:00 2001
From: Colin Foster <colin.foster@in-advantage.com>
Date: Sun, 13 Mar 2022 15:45:24 -0700
Subject: [PATCH 2/2] regmap: allow a defined reg_base to be added to every
address
There's an inconsistency that arises when a register set can be accessed
internally via MMIO, or externally via SPI. The VSC7514 chip allows both
modes of operation. When internally accessed, the system utilizes __iomem,
devm_ioremap_resource, and devm_regmap_init_mmio.
For SPI it isn't possible to utilize memory-mapped IO. To properly operate,
the resource base must be added to the register before every operation.
Signed-off-by: Colin Foster <colin.foster@in-advantage.com>
Link: https://lore.kernel.org/r/20220313224524.399947-3-colin.foster@in-advantage.com
Signed-off-by: Mark Brown <broonie@kernel.org>
---
drivers/base/regmap/internal.h | 1 +
drivers/base/regmap/regmap.c | 6 ++++++
include/linux/regmap.h | 3 +++
3 files changed, 10 insertions(+)
--- a/drivers/base/regmap/internal.h
+++ b/drivers/base/regmap/internal.h
@@ -63,6 +63,7 @@ struct regmap {
regmap_unlock unlock;
void *lock_arg; /* This is passed to lock/unlock functions */
gfp_t alloc_flags;
+ unsigned int reg_base;
struct device *dev; /* Device we do I/O on */
void *work_buf; /* Scratch buffer used to format I/O */
--- a/drivers/base/regmap/regmap.c
+++ b/drivers/base/regmap/regmap.c
@@ -821,6 +821,8 @@ struct regmap *__regmap_init(struct devi
else
map->alloc_flags = GFP_KERNEL;
+ map->reg_base = config->reg_base;
+
map->format.reg_bytes = DIV_ROUND_UP(config->reg_bits, 8);
map->format.pad_bytes = config->pad_bits / 8;
map->format.reg_downshift = config->reg_downshift;
@@ -1736,6 +1738,7 @@ static int _regmap_raw_write_impl(struct
return ret;
}
+ reg += map->reg_base;
reg >>= map->format.reg_downshift;
map->format.format_reg(map->work_buf, reg, map->reg_shift);
regmap_set_work_buf_flag_mask(map, map->format.reg_bytes,
@@ -1907,6 +1910,7 @@ static int _regmap_bus_formatted_write(v
return ret;
}
+ reg += map->reg_base;
reg >>= map->format.reg_downshift;
map->format.format_write(map, reg, val);
@@ -2349,6 +2353,7 @@ static int _regmap_raw_multi_reg_write(s
unsigned int reg = regs[i].reg;
unsigned int val = regs[i].def;
trace_regmap_hw_write_start(map, reg, 1);
+ reg += map->reg_base;
reg >>= map->format.reg_downshift;
map->format.format_reg(u8, reg, map->reg_shift);
u8 += reg_bytes + pad_bytes;
@@ -2677,6 +2682,7 @@ static int _regmap_raw_read(struct regma
return ret;
}
+ reg += map->reg_base;
reg >>= map->format.reg_downshift;
map->format.format_reg(map->work_buf, reg, map->reg_shift);
regmap_set_work_buf_flag_mask(map, map->format.reg_bytes,
--- a/include/linux/regmap.h
+++ b/include/linux/regmap.h
@@ -239,6 +239,8 @@ typedef void (*regmap_unlock)(void *);
* used.
* @reg_downshift: The number of bits to downshift the register before
* performing any operations.
+ * @reg_base: Value to be added to every register address before performing any
+ * operation.
* @pad_bits: Number of bits of padding between register and value.
* @val_bits: Number of bits in a register value, mandatory.
*
@@ -363,6 +365,7 @@ struct regmap_config {
int reg_bits;
int reg_stride;
int reg_downshift;
+ unsigned int reg_base;
int pad_bits;
int val_bits;

View File

@ -0,0 +1,57 @@
From 697c3892d825fb78f42ec8e53bed065dd728db3e Mon Sep 17 00:00:00 2001
From: Daniel Golle <daniel@makrotopia.org>
Date: Mon, 30 Jan 2023 02:04:57 +0000
Subject: [PATCH] regmap: apply reg_base and reg_downshift for single register
ops
reg_base and reg_downshift currently don't have any effect if used with
a regmap_bus or regmap_config which only offers single register
operations (ie. reg_read, reg_write and optionally reg_update_bits).
Fix that and take them into account also for regmap_bus with only
reg_read and read_write operations by applying reg_base and
reg_downshift in _regmap_bus_reg_write, _regmap_bus_reg_read.
Also apply reg_base and reg_downshift in _regmap_update_bits, but only
in case the operation is carried out with a reg_update_bits call
defined in either regmap_bus or regmap_config.
Fixes: 0074f3f2b1e43d ("regmap: allow a defined reg_base to be added to every address")
Fixes: 86fc59ef818beb ("regmap: add configurable downshift for addresses")
Signed-off-by: Daniel Golle <daniel@makrotopia.org>
Tested-by: Colin Foster <colin.foster@in-advantage.com>
Link: https://lore.kernel.org/r/Y9clyVS3tQEHlUhA@makrotopia.org
Signed-off-by: Mark Brown <broonie@kernel.org>
---
drivers/base/regmap/regmap.c | 6 ++++++
1 file changed, 6 insertions(+)
--- a/drivers/base/regmap/regmap.c
+++ b/drivers/base/regmap/regmap.c
@@ -1929,6 +1929,8 @@ static int _regmap_bus_reg_write(void *c
{
struct regmap *map = context;
+ reg += map->reg_base;
+ reg >>= map->format.reg_downshift;
return map->bus->reg_write(map->bus_context, reg, val);
}
@@ -2703,6 +2705,8 @@ static int _regmap_bus_reg_read(void *co
{
struct regmap *map = context;
+ reg += map->reg_base;
+ reg >>= map->format.reg_downshift;
return map->bus->reg_read(map->bus_context, reg, val);
}
@@ -3078,6 +3082,8 @@ static int _regmap_update_bits(struct re
*change = false;
if (regmap_volatile(map, reg) && map->reg_update_bits) {
+ reg += map->reg_base;
+ reg >>= map->format.reg_downshift;
ret = map->reg_update_bits(map->bus_context, reg, mask, val);
if (ret == 0 && change)
*change = true;

View File

@ -0,0 +1,35 @@
From ebed787a0becb9354f0a23620a5130cccd6c730c Mon Sep 17 00:00:00 2001
From: Daniel Golle <daniel@makrotopia.org>
Date: Thu, 19 Jan 2023 03:45:43 +0000
Subject: [PATCH] mtd: spinand: macronix: use scratch buffer for DMA operation
The mx35lf1ge4ab_get_eccsr() function uses an SPI DMA operation to
read the eccsr, hence the buffer should not be on stack. Since commit
380583227c0c7f ("spi: spi-mem: Add extra sanity checks on the op param")
the kernel emmits a warning and blocks such operations.
Use the scratch buffer to get eccsr instead of trying to directly read
into a stack-allocated variable.
Signed-off-by: Daniel Golle <daniel@makrotopia.org>
Reviewed-by: Dhruva Gole <d-gole@ti.com>
Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
Link: https://lore.kernel.org/linux-mtd/Y8i85zM0u4XdM46z@makrotopia.org
---
drivers/mtd/nand/spi/macronix.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
--- a/drivers/mtd/nand/spi/macronix.c
+++ b/drivers/mtd/nand/spi/macronix.c
@@ -83,9 +83,10 @@ static int mx35lf1ge4ab_ecc_get_status(s
* in order to avoid forcing the wear-leveling layer to move
* data around if it's not necessary.
*/
- if (mx35lf1ge4ab_get_eccsr(spinand, &eccsr))
+ if (mx35lf1ge4ab_get_eccsr(spinand, spinand->scratchbuf))
return nanddev_get_ecc_conf(nand)->strength;
+ eccsr = *spinand->scratchbuf;
if (WARN_ON(eccsr > nanddev_get_ecc_conf(nand)->strength ||
!eccsr))
return nanddev_get_ecc_conf(nand)->strength;

View File

@ -0,0 +1,394 @@
From 4765a9722e09765866e131ec31f7b9cf4c1f4854 Mon Sep 17 00:00:00 2001
From: Daniel Golle <daniel@makrotopia.org>
Date: Sun, 19 Mar 2023 12:57:50 +0000
Subject: [PATCH] net: pcs: add driver for MediaTek SGMII PCS
The SGMII core found in several MediaTek SoCs is identical to what can
also be found in MediaTek's MT7531 Ethernet switch IC.
As this has not always been clear, both drivers developed different
implementations to deal with the PCS.
Recently Alexander Couzens pointed out this fact which lead to the
development of this shared driver.
Add a dedicated driver, mostly by copying the code now found in the
Ethernet driver. The now redundant code will be removed by a follow-up
commit.
Suggested-by: Alexander Couzens <lynxis@fe80.eu>
Suggested-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
Signed-off-by: Daniel Golle <daniel@makrotopia.org>
Tested-by: Frank Wunderlich <frank-w@public-files.de>
Reviewed-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
---
MAINTAINERS | 8 +
drivers/net/pcs/Kconfig | 7 +
drivers/net/pcs/Makefile | 1 +
drivers/net/pcs/pcs-mtk-lynxi.c | 305 ++++++++++++++++++++++++++++++
include/linux/pcs/pcs-mtk-lynxi.h | 13 ++
5 files changed, 334 insertions(+)
create mode 100644 drivers/net/pcs/pcs-mtk-lynxi.c
create mode 100644 include/linux/pcs/pcs-mtk-lynxi.h
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -11790,6 +11790,14 @@ L: netdev@vger.kernel.org
S: Maintained
F: drivers/net/ethernet/mediatek/
+MEDIATEK ETHERNET PCS DRIVER
+M: Alexander Couzens <lynxis@fe80.eu>
+M: Daniel Golle <daniel@makrotopia.org>
+L: netdev@vger.kernel.org
+S: Maintained
+F: drivers/net/pcs/pcs-mtk-lynxi.c
+F: include/linux/pcs/pcs-mtk-lynxi.h
+
MEDIATEK I2C CONTROLLER DRIVER
M: Qii Wang <qii.wang@mediatek.com>
L: linux-i2c@vger.kernel.org
--- a/drivers/net/pcs/Kconfig
+++ b/drivers/net/pcs/Kconfig
@@ -18,4 +18,11 @@ config PCS_LYNX
This module provides helpers to phylink for managing the Lynx PCS
which is part of the Layerscape and QorIQ Ethernet SERDES.
+config PCS_MTK_LYNXI
+ tristate
+ select REGMAP
+ help
+ This module provides helpers to phylink for managing the LynxI PCS
+ which is part of MediaTek's SoC and Ethernet switch ICs.
+
endmenu
--- a/drivers/net/pcs/Makefile
+++ b/drivers/net/pcs/Makefile
@@ -5,3 +5,4 @@ pcs_xpcs-$(CONFIG_PCS_XPCS) := pcs-xpcs.
obj-$(CONFIG_PCS_XPCS) += pcs_xpcs.o
obj-$(CONFIG_PCS_LYNX) += pcs-lynx.o
+obj-$(CONFIG_PCS_MTK_LYNXI) += pcs-mtk-lynxi.o
--- /dev/null
+++ b/drivers/net/pcs/pcs-mtk-lynxi.c
@@ -0,0 +1,305 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (c) 2018-2019 MediaTek Inc.
+/* A library for MediaTek SGMII circuit
+ *
+ * Author: Sean Wang <sean.wang@mediatek.com>
+ * Author: Alexander Couzens <lynxis@fe80.eu>
+ * Author: Daniel Golle <daniel@makrotopia.org>
+ *
+ */
+
+#include <linux/mdio.h>
+#include <linux/of.h>
+#include <linux/pcs/pcs-mtk-lynxi.h>
+#include <linux/phylink.h>
+#include <linux/regmap.h>
+
+/* SGMII subsystem config registers */
+/* BMCR (low 16) BMSR (high 16) */
+#define SGMSYS_PCS_CONTROL_1 0x0
+#define SGMII_BMCR GENMASK(15, 0)
+#define SGMII_BMSR GENMASK(31, 16)
+
+#define SGMSYS_PCS_DEVICE_ID 0x4
+#define SGMII_LYNXI_DEV_ID 0x4d544950
+
+#define SGMSYS_PCS_ADVERTISE 0x8
+#define SGMII_ADVERTISE GENMASK(15, 0)
+#define SGMII_LPA GENMASK(31, 16)
+
+#define SGMSYS_PCS_SCRATCH 0x14
+#define SGMII_DEV_VERSION GENMASK(31, 16)
+
+/* Register to programmable link timer, the unit in 2 * 8ns */
+#define SGMSYS_PCS_LINK_TIMER 0x18
+#define SGMII_LINK_TIMER_MASK GENMASK(19, 0)
+#define SGMII_LINK_TIMER_VAL(ns) FIELD_PREP(SGMII_LINK_TIMER_MASK, \
+ ((ns) / 2 / 8))
+
+/* Register to control remote fault */
+#define SGMSYS_SGMII_MODE 0x20
+#define SGMII_IF_MODE_SGMII BIT(0)
+#define SGMII_SPEED_DUPLEX_AN BIT(1)
+#define SGMII_SPEED_MASK GENMASK(3, 2)
+#define SGMII_SPEED_10 FIELD_PREP(SGMII_SPEED_MASK, 0)
+#define SGMII_SPEED_100 FIELD_PREP(SGMII_SPEED_MASK, 1)
+#define SGMII_SPEED_1000 FIELD_PREP(SGMII_SPEED_MASK, 2)
+#define SGMII_DUPLEX_HALF BIT(4)
+#define SGMII_REMOTE_FAULT_DIS BIT(8)
+
+/* Register to reset SGMII design */
+#define SGMSYS_RESERVED_0 0x34
+#define SGMII_SW_RESET BIT(0)
+
+/* Register to set SGMII speed, ANA RG_ Control Signals III */
+#define SGMII_PHY_SPEED_MASK GENMASK(3, 2)
+#define SGMII_PHY_SPEED_1_25G FIELD_PREP(SGMII_PHY_SPEED_MASK, 0)
+#define SGMII_PHY_SPEED_3_125G FIELD_PREP(SGMII_PHY_SPEED_MASK, 1)
+
+/* Register to power up QPHY */
+#define SGMSYS_QPHY_PWR_STATE_CTRL 0xe8
+#define SGMII_PHYA_PWD BIT(4)
+
+/* Register to QPHY wrapper control */
+#define SGMSYS_QPHY_WRAP_CTRL 0xec
+#define SGMII_PN_SWAP_MASK GENMASK(1, 0)
+#define SGMII_PN_SWAP_TX_RX (BIT(0) | BIT(1))
+
+/* struct mtk_pcs_lynxi - This structure holds each sgmii regmap andassociated
+ * data
+ * @regmap: The register map pointing at the range used to setup
+ * SGMII modes
+ * @dev: Pointer to device owning the PCS
+ * @ana_rgc3: The offset of register ANA_RGC3 relative to regmap
+ * @interface: Currently configured interface mode
+ * @pcs: Phylink PCS structure
+ * @flags: Flags indicating hardware properties
+ */
+struct mtk_pcs_lynxi {
+ struct regmap *regmap;
+ u32 ana_rgc3;
+ phy_interface_t interface;
+ struct phylink_pcs pcs;
+ u32 flags;
+};
+
+static struct mtk_pcs_lynxi *pcs_to_mtk_pcs_lynxi(struct phylink_pcs *pcs)
+{
+ return container_of(pcs, struct mtk_pcs_lynxi, pcs);
+}
+
+static void mtk_pcs_lynxi_get_state(struct phylink_pcs *pcs,
+ struct phylink_link_state *state)
+{
+ struct mtk_pcs_lynxi *mpcs = pcs_to_mtk_pcs_lynxi(pcs);
+ unsigned int bm, adv;
+
+ /* Read the BMSR and LPA */
+ regmap_read(mpcs->regmap, SGMSYS_PCS_CONTROL_1, &bm);
+ regmap_read(mpcs->regmap, SGMSYS_PCS_ADVERTISE, &adv);
+
+ phylink_mii_c22_pcs_decode_state(state, FIELD_GET(SGMII_BMSR, bm),
+ FIELD_GET(SGMII_LPA, adv));
+}
+
+static int mtk_pcs_lynxi_config(struct phylink_pcs *pcs, unsigned int mode,
+ phy_interface_t interface,
+ const unsigned long *advertising,
+ bool permit_pause_to_mac)
+{
+ struct mtk_pcs_lynxi *mpcs = pcs_to_mtk_pcs_lynxi(pcs);
+ bool mode_changed = false, changed, use_an;
+ unsigned int rgc3, sgm_mode, bmcr;
+ int advertise, link_timer;
+
+ advertise = phylink_mii_c22_pcs_encode_advertisement(interface,
+ advertising);
+ if (advertise < 0)
+ return advertise;
+
+ /* Clearing IF_MODE_BIT0 switches the PCS to BASE-X mode, and
+ * we assume that fixes it's speed at bitrate = line rate (in
+ * other words, 1000Mbps or 2500Mbps).
+ */
+ if (interface == PHY_INTERFACE_MODE_SGMII) {
+ sgm_mode = SGMII_IF_MODE_SGMII;
+ if (phylink_autoneg_inband(mode)) {
+ sgm_mode |= SGMII_REMOTE_FAULT_DIS |
+ SGMII_SPEED_DUPLEX_AN;
+ use_an = true;
+ } else {
+ use_an = false;
+ }
+ } else if (phylink_autoneg_inband(mode)) {
+ /* 1000base-X or 2500base-X autoneg */
+ sgm_mode = SGMII_REMOTE_FAULT_DIS;
+ use_an = linkmode_test_bit(ETHTOOL_LINK_MODE_Autoneg_BIT,
+ advertising);
+ } else {
+ /* 1000base-X or 2500base-X without autoneg */
+ sgm_mode = 0;
+ use_an = false;
+ }
+
+ if (use_an)
+ bmcr = BMCR_ANENABLE;
+ else
+ bmcr = 0;
+
+ if (mpcs->interface != interface) {
+ link_timer = phylink_get_link_timer_ns(interface);
+ if (link_timer < 0)
+ return link_timer;
+
+ /* PHYA power down */
+ regmap_set_bits(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL,
+ SGMII_PHYA_PWD);
+
+ /* Reset SGMII PCS state */
+ regmap_set_bits(mpcs->regmap, SGMSYS_RESERVED_0,
+ SGMII_SW_RESET);
+
+ if (mpcs->flags & MTK_SGMII_FLAG_PN_SWAP)
+ regmap_update_bits(mpcs->regmap, SGMSYS_QPHY_WRAP_CTRL,
+ SGMII_PN_SWAP_MASK,
+ SGMII_PN_SWAP_TX_RX);
+
+ if (interface == PHY_INTERFACE_MODE_2500BASEX)
+ rgc3 = SGMII_PHY_SPEED_3_125G;
+ else
+ rgc3 = SGMII_PHY_SPEED_1_25G;
+
+ /* Configure the underlying interface speed */
+ regmap_update_bits(mpcs->regmap, mpcs->ana_rgc3,
+ SGMII_PHY_SPEED_MASK, rgc3);
+
+ /* Setup the link timer */
+ regmap_write(mpcs->regmap, SGMSYS_PCS_LINK_TIMER,
+ SGMII_LINK_TIMER_VAL(link_timer));
+
+ mpcs->interface = interface;
+ mode_changed = true;
+ }
+
+ /* Update the advertisement, noting whether it has changed */
+ regmap_update_bits_check(mpcs->regmap, SGMSYS_PCS_ADVERTISE,
+ SGMII_ADVERTISE, advertise, &changed);
+
+ /* Update the sgmsys mode register */
+ regmap_update_bits(mpcs->regmap, SGMSYS_SGMII_MODE,
+ SGMII_REMOTE_FAULT_DIS | SGMII_SPEED_DUPLEX_AN |
+ SGMII_IF_MODE_SGMII, sgm_mode);
+
+ /* Update the BMCR */
+ regmap_update_bits(mpcs->regmap, SGMSYS_PCS_CONTROL_1,
+ BMCR_ANENABLE, bmcr);
+
+ /* Release PHYA power down state
+ * Only removing bit SGMII_PHYA_PWD isn't enough.
+ * There are cases when the SGMII_PHYA_PWD register contains 0x9 which
+ * prevents SGMII from working. The SGMII still shows link but no traffic
+ * can flow. Writing 0x0 to the PHYA_PWD register fix the issue. 0x0 was
+ * taken from a good working state of the SGMII interface.
+ * Unknown how much the QPHY needs but it is racy without a sleep.
+ * Tested on mt7622 & mt7986.
+ */
+ usleep_range(50, 100);
+ regmap_write(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL, 0);
+
+ return changed || mode_changed;
+}
+
+static void mtk_pcs_lynxi_restart_an(struct phylink_pcs *pcs)
+{
+ struct mtk_pcs_lynxi *mpcs = pcs_to_mtk_pcs_lynxi(pcs);
+
+ regmap_set_bits(mpcs->regmap, SGMSYS_PCS_CONTROL_1, BMCR_ANRESTART);
+}
+
+static void mtk_pcs_lynxi_link_up(struct phylink_pcs *pcs, unsigned int mode,
+ phy_interface_t interface, int speed,
+ int duplex)
+{
+ struct mtk_pcs_lynxi *mpcs = pcs_to_mtk_pcs_lynxi(pcs);
+ unsigned int sgm_mode;
+
+ if (!phylink_autoneg_inband(mode)) {
+ /* Force the speed and duplex setting */
+ if (speed == SPEED_10)
+ sgm_mode = SGMII_SPEED_10;
+ else if (speed == SPEED_100)
+ sgm_mode = SGMII_SPEED_100;
+ else
+ sgm_mode = SGMII_SPEED_1000;
+
+ if (duplex != DUPLEX_FULL)
+ sgm_mode |= SGMII_DUPLEX_HALF;
+
+ regmap_update_bits(mpcs->regmap, SGMSYS_SGMII_MODE,
+ SGMII_DUPLEX_HALF | SGMII_SPEED_MASK,
+ sgm_mode);
+ }
+}
+
+static const struct phylink_pcs_ops mtk_pcs_lynxi_ops = {
+ .pcs_get_state = mtk_pcs_lynxi_get_state,
+ .pcs_config = mtk_pcs_lynxi_config,
+ .pcs_an_restart = mtk_pcs_lynxi_restart_an,
+ .pcs_link_up = mtk_pcs_lynxi_link_up,
+};
+
+struct phylink_pcs *mtk_pcs_lynxi_create(struct device *dev,
+ struct regmap *regmap, u32 ana_rgc3,
+ u32 flags)
+{
+ struct mtk_pcs_lynxi *mpcs;
+ u32 id, ver;
+ int ret;
+
+ ret = regmap_read(regmap, SGMSYS_PCS_DEVICE_ID, &id);
+ if (ret < 0)
+ return NULL;
+
+ if (id != SGMII_LYNXI_DEV_ID) {
+ dev_err(dev, "unknown PCS device id %08x\n", id);
+ return NULL;
+ }
+
+ ret = regmap_read(regmap, SGMSYS_PCS_SCRATCH, &ver);
+ if (ret < 0)
+ return NULL;
+
+ ver = FIELD_GET(SGMII_DEV_VERSION, ver);
+ if (ver != 0x1) {
+ dev_err(dev, "unknown PCS device version %04x\n", ver);
+ return NULL;
+ }
+
+ dev_dbg(dev, "MediaTek LynxI SGMII PCS (id 0x%08x, ver 0x%04x)\n", id,
+ ver);
+
+ mpcs = kzalloc(sizeof(*mpcs), GFP_KERNEL);
+ if (!mpcs)
+ return NULL;
+
+ mpcs->ana_rgc3 = ana_rgc3;
+ mpcs->regmap = regmap;
+ mpcs->flags = flags;
+ mpcs->pcs.ops = &mtk_pcs_lynxi_ops;
+ mpcs->pcs.poll = true;
+ mpcs->interface = PHY_INTERFACE_MODE_NA;
+
+ return &mpcs->pcs;
+}
+EXPORT_SYMBOL(mtk_pcs_lynxi_create);
+
+void mtk_pcs_lynxi_destroy(struct phylink_pcs *pcs)
+{
+ if (!pcs)
+ return;
+
+ kfree(pcs_to_mtk_pcs_lynxi(pcs));
+}
+EXPORT_SYMBOL(mtk_pcs_lynxi_destroy);
+
+MODULE_LICENSE("GPL");
--- /dev/null
+++ b/include/linux/pcs/pcs-mtk-lynxi.h
@@ -0,0 +1,13 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __LINUX_PCS_MTK_LYNXI_H
+#define __LINUX_PCS_MTK_LYNXI_H
+
+#include <linux/phylink.h>
+#include <linux/regmap.h>
+
+#define MTK_SGMII_FLAG_PN_SWAP BIT(0)
+struct phylink_pcs *mtk_pcs_lynxi_create(struct device *dev,
+ struct regmap *regmap,
+ u32 ana_rgc3, u32 flags);
+void mtk_pcs_lynxi_destroy(struct phylink_pcs *pcs);
+#endif

View File

@ -0,0 +1,55 @@
From b6a709cb51f7bdc55c01cec886098a9753ce8c28 Mon Sep 17 00:00:00 2001
From: "Russell King (Oracle)" <rmk+kernel@armlinux.org.uk>
Date: Thu, 27 Oct 2022 14:10:42 +0100
Subject: [PATCH 01/10] net: mtk_eth_soc: add definitions for PCS
As a result of help from Frank Wunderlich to investigate and test, we
know a bit more about the PCS on the Mediatek platforms. Update the
definitions from this investigation.
This PCS appears similar, but not identical to the Lynx PCS.
Although not included in this patch, but for future reference, the PHY
ID registers at offset 4 read as 0x4d544950 'MTIP'.
Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
---
drivers/net/ethernet/mediatek/mtk_eth_soc.h | 13 ++++++++++---
1 file changed, 10 insertions(+), 3 deletions(-)
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
@@ -501,8 +501,10 @@
#define ETHSYS_DMA_AG_MAP_PPE BIT(2)
/* SGMII subsystem config registers */
-/* Register to auto-negotiation restart */
+/* BMCR (low 16) BMSR (high 16) */
#define SGMSYS_PCS_CONTROL_1 0x0
+#define SGMII_BMCR GENMASK(15, 0)
+#define SGMII_BMSR GENMASK(31, 16)
#define SGMII_AN_RESTART BIT(9)
#define SGMII_ISOLATE BIT(10)
#define SGMII_AN_ENABLE BIT(12)
@@ -512,13 +514,18 @@
#define SGMII_PCS_FAULT BIT(23)
#define SGMII_AN_EXPANSION_CLR BIT(30)
+#define SGMSYS_PCS_ADVERTISE 0x8
+#define SGMII_ADVERTISE GENMASK(15, 0)
+#define SGMII_LPA GENMASK(31, 16)
+
/* Register to programmable link timer, the unit in 2 * 8ns */
#define SGMSYS_PCS_LINK_TIMER 0x18
-#define SGMII_LINK_TIMER_DEFAULT (0x186a0 & GENMASK(19, 0))
+#define SGMII_LINK_TIMER_MASK GENMASK(19, 0)
+#define SGMII_LINK_TIMER_DEFAULT (0x186a0 & SGMII_LINK_TIMER_MASK)
/* Register to control remote fault */
#define SGMSYS_SGMII_MODE 0x20
-#define SGMII_IF_MODE_BIT0 BIT(0)
+#define SGMII_IF_MODE_SGMII BIT(0)
#define SGMII_SPEED_DUPLEX_AN BIT(1)
#define SGMII_SPEED_MASK GENMASK(3, 2)
#define SGMII_SPEED_10 FIELD_PREP(SGMII_SPEED_MASK, 0)

View File

@ -0,0 +1,74 @@
From 5cf7797526ee81bea0f627bccaa3d887f48f53e0 Mon Sep 17 00:00:00 2001
From: "Russell King (Oracle)" <rmk+kernel@armlinux.org.uk>
Date: Thu, 27 Oct 2022 14:10:47 +0100
Subject: [PATCH 02/10] net: mtk_eth_soc: eliminate unnecessary error handling
The functions called by the pcs_config() method always return zero, so
there is no point trying to handle an error from these functions. Make
these functions void, eliminate the "err" variable and simply return
zero from the pcs_config() function itself.
Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
---
drivers/net/ethernet/mediatek/mtk_sgmii.c | 18 ++++++------------
1 file changed, 6 insertions(+), 12 deletions(-)
--- a/drivers/net/ethernet/mediatek/mtk_sgmii.c
+++ b/drivers/net/ethernet/mediatek/mtk_sgmii.c
@@ -20,7 +20,7 @@ static struct mtk_pcs *pcs_to_mtk_pcs(st
}
/* For SGMII interface mode */
-static int mtk_pcs_setup_mode_an(struct mtk_pcs *mpcs)
+static void mtk_pcs_setup_mode_an(struct mtk_pcs *mpcs)
{
unsigned int val;
@@ -39,16 +39,13 @@ static int mtk_pcs_setup_mode_an(struct
regmap_read(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL, &val);
val &= ~SGMII_PHYA_PWD;
regmap_write(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL, val);
-
- return 0;
-
}
/* For 1000BASE-X and 2500BASE-X interface modes, which operate at a
* fixed speed.
*/
-static int mtk_pcs_setup_mode_force(struct mtk_pcs *mpcs,
- phy_interface_t interface)
+static void mtk_pcs_setup_mode_force(struct mtk_pcs *mpcs,
+ phy_interface_t interface)
{
unsigned int val;
@@ -73,8 +70,6 @@ static int mtk_pcs_setup_mode_force(stru
regmap_read(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL, &val);
val &= ~SGMII_PHYA_PWD;
regmap_write(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL, val);
-
- return 0;
}
static int mtk_pcs_config(struct phylink_pcs *pcs, unsigned int mode,
@@ -83,15 +78,14 @@ static int mtk_pcs_config(struct phylink
bool permit_pause_to_mac)
{
struct mtk_pcs *mpcs = pcs_to_mtk_pcs(pcs);
- int err = 0;
/* Setup SGMIISYS with the determined property */
if (interface != PHY_INTERFACE_MODE_SGMII)
- err = mtk_pcs_setup_mode_force(mpcs, interface);
+ mtk_pcs_setup_mode_force(mpcs, interface);
else if (phylink_autoneg_inband(mode))
- err = mtk_pcs_setup_mode_an(mpcs);
+ mtk_pcs_setup_mode_an(mpcs);
- return err;
+ return 0;
}
static void mtk_pcs_restart_an(struct phylink_pcs *pcs)

View File

@ -0,0 +1,46 @@
From c000dca098002da193b98099df051c9ead0cacb4 Mon Sep 17 00:00:00 2001
From: "Russell King (Oracle)" <rmk+kernel@armlinux.org.uk>
Date: Thu, 27 Oct 2022 14:10:52 +0100
Subject: [PATCH 03/10] net: mtk_eth_soc: add pcs_get_state() implementation
Add a pcs_get_state() implementation which uses the advertisements
to compute the resulting link modes, and BMSR contents to determine
negotiation and link status.
Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
---
drivers/net/ethernet/mediatek/mtk_sgmii.c | 15 +++++++++++++++
1 file changed, 15 insertions(+)
--- a/drivers/net/ethernet/mediatek/mtk_sgmii.c
+++ b/drivers/net/ethernet/mediatek/mtk_sgmii.c
@@ -19,6 +19,20 @@ static struct mtk_pcs *pcs_to_mtk_pcs(st
return container_of(pcs, struct mtk_pcs, pcs);
}
+static void mtk_pcs_get_state(struct phylink_pcs *pcs,
+ struct phylink_link_state *state)
+{
+ struct mtk_pcs *mpcs = pcs_to_mtk_pcs(pcs);
+ unsigned int bm, adv;
+
+ /* Read the BMSR and LPA */
+ regmap_read(mpcs->regmap, SGMSYS_PCS_CONTROL_1, &bm);
+ regmap_read(mpcs->regmap, SGMSYS_PCS_ADVERTISE, &adv);
+
+ phylink_mii_c22_pcs_decode_state(state, FIELD_GET(SGMII_BMSR, bm),
+ FIELD_GET(SGMII_LPA, adv));
+}
+
/* For SGMII interface mode */
static void mtk_pcs_setup_mode_an(struct mtk_pcs *mpcs)
{
@@ -117,6 +131,7 @@ static void mtk_pcs_link_up(struct phyli
}
static const struct phylink_pcs_ops mtk_pcs_ops = {
+ .pcs_get_state = mtk_pcs_get_state,
.pcs_config = mtk_pcs_config,
.pcs_an_restart = mtk_pcs_restart_an,
.pcs_link_up = mtk_pcs_link_up,

View File

@ -0,0 +1,130 @@
From 0d2351dc2768061689abd4de1529fa206bbd574e Mon Sep 17 00:00:00 2001
From: "Russell King (Oracle)" <rmk+kernel@armlinux.org.uk>
Date: Thu, 27 Oct 2022 14:10:58 +0100
Subject: [PATCH 04/10] net: mtk_eth_soc: convert mtk_sgmii to use
regmap_update_bits()
mtk_sgmii does a lot of read-modify-write operations, for which there
is a specific regmap function. Use this function instead of open-coding
the operations.
Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
---
drivers/net/ethernet/mediatek/mtk_sgmii.c | 61 ++++++++++-------------
1 file changed, 26 insertions(+), 35 deletions(-)
--- a/drivers/net/ethernet/mediatek/mtk_sgmii.c
+++ b/drivers/net/ethernet/mediatek/mtk_sgmii.c
@@ -36,23 +36,18 @@ static void mtk_pcs_get_state(struct phy
/* For SGMII interface mode */
static void mtk_pcs_setup_mode_an(struct mtk_pcs *mpcs)
{
- unsigned int val;
-
/* Setup the link timer and QPHY power up inside SGMIISYS */
regmap_write(mpcs->regmap, SGMSYS_PCS_LINK_TIMER,
SGMII_LINK_TIMER_DEFAULT);
- regmap_read(mpcs->regmap, SGMSYS_SGMII_MODE, &val);
- val |= SGMII_REMOTE_FAULT_DIS;
- regmap_write(mpcs->regmap, SGMSYS_SGMII_MODE, val);
-
- regmap_read(mpcs->regmap, SGMSYS_PCS_CONTROL_1, &val);
- val |= SGMII_AN_RESTART;
- regmap_write(mpcs->regmap, SGMSYS_PCS_CONTROL_1, val);
-
- regmap_read(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL, &val);
- val &= ~SGMII_PHYA_PWD;
- regmap_write(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL, val);
+ regmap_update_bits(mpcs->regmap, SGMSYS_SGMII_MODE,
+ SGMII_REMOTE_FAULT_DIS, SGMII_REMOTE_FAULT_DIS);
+
+ regmap_update_bits(mpcs->regmap, SGMSYS_PCS_CONTROL_1,
+ SGMII_AN_RESTART, SGMII_AN_RESTART);
+
+ regmap_update_bits(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL,
+ SGMII_PHYA_PWD, 0);
}
/* For 1000BASE-X and 2500BASE-X interface modes, which operate at a
@@ -61,29 +56,26 @@ static void mtk_pcs_setup_mode_an(struct
static void mtk_pcs_setup_mode_force(struct mtk_pcs *mpcs,
phy_interface_t interface)
{
- unsigned int val;
+ unsigned int rgc3;
- regmap_read(mpcs->regmap, mpcs->ana_rgc3, &val);
- val &= ~RG_PHY_SPEED_MASK;
if (interface == PHY_INTERFACE_MODE_2500BASEX)
- val |= RG_PHY_SPEED_3_125G;
- regmap_write(mpcs->regmap, mpcs->ana_rgc3, val);
+ rgc3 = RG_PHY_SPEED_3_125G;
+
+ regmap_update_bits(mpcs->regmap, mpcs->ana_rgc3,
+ RG_PHY_SPEED_3_125G, rgc3);
/* Disable SGMII AN */
- regmap_read(mpcs->regmap, SGMSYS_PCS_CONTROL_1, &val);
- val &= ~SGMII_AN_ENABLE;
- regmap_write(mpcs->regmap, SGMSYS_PCS_CONTROL_1, val);
+ regmap_update_bits(mpcs->regmap, SGMSYS_PCS_CONTROL_1,
+ SGMII_AN_ENABLE, 0);
/* Set the speed etc but leave the duplex unchanged */
- regmap_read(mpcs->regmap, SGMSYS_SGMII_MODE, &val);
- val &= SGMII_DUPLEX_FULL | ~SGMII_IF_MODE_MASK;
- val |= SGMII_SPEED_1000;
- regmap_write(mpcs->regmap, SGMSYS_SGMII_MODE, val);
+ regmap_update_bits(mpcs->regmap, SGMSYS_SGMII_MODE,
+ SGMII_IF_MODE_MASK & ~SGMII_DUPLEX_FULL,
+ SGMII_SPEED_1000);
/* Release PHYA power down state */
- regmap_read(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL, &val);
- val &= ~SGMII_PHYA_PWD;
- regmap_write(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL, val);
+ regmap_update_bits(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL,
+ SGMII_PHYA_PWD, 0);
}
static int mtk_pcs_config(struct phylink_pcs *pcs, unsigned int mode,
@@ -105,29 +97,28 @@ static int mtk_pcs_config(struct phylink
static void mtk_pcs_restart_an(struct phylink_pcs *pcs)
{
struct mtk_pcs *mpcs = pcs_to_mtk_pcs(pcs);
- unsigned int val;
- regmap_read(mpcs->regmap, SGMSYS_PCS_CONTROL_1, &val);
- val |= SGMII_AN_RESTART;
- regmap_write(mpcs->regmap, SGMSYS_PCS_CONTROL_1, val);
+ regmap_update_bits(mpcs->regmap, SGMSYS_PCS_CONTROL_1,
+ SGMII_AN_RESTART, SGMII_AN_RESTART);
}
static void mtk_pcs_link_up(struct phylink_pcs *pcs, unsigned int mode,
phy_interface_t interface, int speed, int duplex)
{
struct mtk_pcs *mpcs = pcs_to_mtk_pcs(pcs);
- unsigned int val;
+ unsigned int sgm_mode;
if (!phy_interface_mode_is_8023z(interface))
return;
/* SGMII force duplex setting */
- regmap_read(mpcs->regmap, SGMSYS_SGMII_MODE, &val);
- val &= ~SGMII_DUPLEX_FULL;
if (duplex == DUPLEX_FULL)
- val |= SGMII_DUPLEX_FULL;
+ sgm_mode = SGMII_DUPLEX_FULL;
+ else
+ sgm_mode = 0;
- regmap_write(mpcs->regmap, SGMSYS_SGMII_MODE, val);
+ regmap_update_bits(mpcs->regmap, SGMSYS_SGMII_MODE,
+ SGMII_DUPLEX_FULL, sgm_mode);
}
static const struct phylink_pcs_ops mtk_pcs_ops = {

View File

@ -0,0 +1,52 @@
From 12198c3a410fe69843e335c1bbf6d4c2a4d48e4e Mon Sep 17 00:00:00 2001
From: "Russell King (Oracle)" <rmk+kernel@armlinux.org.uk>
Date: Thu, 27 Oct 2022 14:11:03 +0100
Subject: [PATCH 05/10] net: mtk_eth_soc: add out of band forcing of speed and
duplex in pcs_link_up
Add support for forcing the link speed and duplex setting in the
pcs_link_up() method for out of band modes, which will be useful when
we finish converting the pcs_config() method. Until then, we still have
to force duplex for 802.3z modes to work correctly.
Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
---
drivers/net/ethernet/mediatek/mtk_sgmii.c | 28 ++++++++++++++---------
1 file changed, 17 insertions(+), 11 deletions(-)
--- a/drivers/net/ethernet/mediatek/mtk_sgmii.c
+++ b/drivers/net/ethernet/mediatek/mtk_sgmii.c
@@ -108,17 +108,23 @@ static void mtk_pcs_link_up(struct phyli
struct mtk_pcs *mpcs = pcs_to_mtk_pcs(pcs);
unsigned int sgm_mode;
- if (!phy_interface_mode_is_8023z(interface))
- return;
+ if (!phylink_autoneg_inband(mode) ||
+ phy_interface_mode_is_8023z(interface)) {
+ /* Force the speed and duplex setting */
+ if (speed == SPEED_10)
+ sgm_mode = SGMII_SPEED_10;
+ else if (speed == SPEED_100)
+ sgm_mode = SGMII_SPEED_100;
+ else
+ sgm_mode = SGMII_SPEED_1000;
- /* SGMII force duplex setting */
- if (duplex == DUPLEX_FULL)
- sgm_mode = SGMII_DUPLEX_FULL;
- else
- sgm_mode = 0;
+ if (duplex == DUPLEX_FULL)
+ sgm_mode |= SGMII_DUPLEX_FULL;
- regmap_update_bits(mpcs->regmap, SGMSYS_SGMII_MODE,
- SGMII_DUPLEX_FULL, sgm_mode);
+ regmap_update_bits(mpcs->regmap, SGMSYS_SGMII_MODE,
+ SGMII_DUPLEX_FULL | SGMII_SPEED_MASK,
+ sgm_mode);
+ }
}
static const struct phylink_pcs_ops mtk_pcs_ops = {

View File

@ -0,0 +1,48 @@
From 6f38fffe2179dd29612aea2c67c46ed6682b4e46 Mon Sep 17 00:00:00 2001
From: "Russell King (Oracle)" <rmk+kernel@armlinux.org.uk>
Date: Thu, 27 Oct 2022 14:11:08 +0100
Subject: [PATCH 06/10] net: mtk_eth_soc: move PHY power up
The PHY power up is common to both configuration paths, so move it into
the parent function. We need to do this for all serdes modes.
Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
---
drivers/net/ethernet/mediatek/mtk_sgmii.c | 11 ++++-------
1 file changed, 4 insertions(+), 7 deletions(-)
--- a/drivers/net/ethernet/mediatek/mtk_sgmii.c
+++ b/drivers/net/ethernet/mediatek/mtk_sgmii.c
@@ -45,9 +45,6 @@ static void mtk_pcs_setup_mode_an(struct
regmap_update_bits(mpcs->regmap, SGMSYS_PCS_CONTROL_1,
SGMII_AN_RESTART, SGMII_AN_RESTART);
-
- regmap_update_bits(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL,
- SGMII_PHYA_PWD, 0);
}
/* For 1000BASE-X and 2500BASE-X interface modes, which operate at a
@@ -72,10 +69,6 @@ static void mtk_pcs_setup_mode_force(str
regmap_update_bits(mpcs->regmap, SGMSYS_SGMII_MODE,
SGMII_IF_MODE_MASK & ~SGMII_DUPLEX_FULL,
SGMII_SPEED_1000);
-
- /* Release PHYA power down state */
- regmap_update_bits(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL,
- SGMII_PHYA_PWD, 0);
}
static int mtk_pcs_config(struct phylink_pcs *pcs, unsigned int mode,
@@ -91,6 +84,10 @@ static int mtk_pcs_config(struct phylink
else if (phylink_autoneg_inband(mode))
mtk_pcs_setup_mode_an(mpcs);
+ /* Release PHYA power down state */
+ regmap_update_bits(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL,
+ SGMII_PHYA_PWD, 0);
+
return 0;
}

View File

@ -0,0 +1,48 @@
From f752c0df13dfeb721c11d3debb79f08cf437344f Mon Sep 17 00:00:00 2001
From: "Russell King (Oracle)" <rmk+kernel@armlinux.org.uk>
Date: Thu, 27 Oct 2022 14:11:13 +0100
Subject: [PATCH 07/10] net: mtk_eth_soc: move interface speed selection
Move the selection of the underlying interface speed to the pcs_config
function, so we always program the interface speed.
Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
---
drivers/net/ethernet/mediatek/mtk_sgmii.c | 18 ++++++++++--------
1 file changed, 10 insertions(+), 8 deletions(-)
--- a/drivers/net/ethernet/mediatek/mtk_sgmii.c
+++ b/drivers/net/ethernet/mediatek/mtk_sgmii.c
@@ -53,14 +53,6 @@ static void mtk_pcs_setup_mode_an(struct
static void mtk_pcs_setup_mode_force(struct mtk_pcs *mpcs,
phy_interface_t interface)
{
- unsigned int rgc3;
-
- if (interface == PHY_INTERFACE_MODE_2500BASEX)
- rgc3 = RG_PHY_SPEED_3_125G;
-
- regmap_update_bits(mpcs->regmap, mpcs->ana_rgc3,
- RG_PHY_SPEED_3_125G, rgc3);
-
/* Disable SGMII AN */
regmap_update_bits(mpcs->regmap, SGMSYS_PCS_CONTROL_1,
SGMII_AN_ENABLE, 0);
@@ -77,6 +69,16 @@ static int mtk_pcs_config(struct phylink
bool permit_pause_to_mac)
{
struct mtk_pcs *mpcs = pcs_to_mtk_pcs(pcs);
+ unsigned int rgc3;
+
+ if (interface == PHY_INTERFACE_MODE_2500BASEX)
+ rgc3 = RG_PHY_SPEED_3_125G;
+ else
+ rgc3 = 0;
+
+ /* Configure the underlying interface speed */
+ regmap_update_bits(mpcs->regmap, mpcs->ana_rgc3,
+ RG_PHY_SPEED_3_125G, rgc3);
/* Setup SGMIISYS with the determined property */
if (interface != PHY_INTERFACE_MODE_SGMII)

View File

@ -0,0 +1,52 @@
From c125c66ea71b9377ae2478c4f1b87b180cc5c6ef Mon Sep 17 00:00:00 2001
From: "Russell King (Oracle)" <rmk+kernel@armlinux.org.uk>
Date: Thu, 27 Oct 2022 14:11:18 +0100
Subject: [PATCH 08/10] net: mtk_eth_soc: add advertisement programming
Program the advertisement into the mtk PCS block.
Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
---
drivers/net/ethernet/mediatek/mtk_sgmii.c | 13 ++++++++++++-
1 file changed, 12 insertions(+), 1 deletion(-)
--- a/drivers/net/ethernet/mediatek/mtk_sgmii.c
+++ b/drivers/net/ethernet/mediatek/mtk_sgmii.c
@@ -70,16 +70,27 @@ static int mtk_pcs_config(struct phylink
{
struct mtk_pcs *mpcs = pcs_to_mtk_pcs(pcs);
unsigned int rgc3;
+ int advertise;
+ bool changed;
if (interface == PHY_INTERFACE_MODE_2500BASEX)
rgc3 = RG_PHY_SPEED_3_125G;
else
rgc3 = 0;
+ advertise = phylink_mii_c22_pcs_encode_advertisement(interface,
+ advertising);
+ if (advertise < 0)
+ return advertise;
+
/* Configure the underlying interface speed */
regmap_update_bits(mpcs->regmap, mpcs->ana_rgc3,
RG_PHY_SPEED_3_125G, rgc3);
+ /* Update the advertisement, noting whether it has changed */
+ regmap_update_bits_check(mpcs->regmap, SGMSYS_PCS_ADVERTISE,
+ SGMII_ADVERTISE, advertise, &changed);
+
/* Setup SGMIISYS with the determined property */
if (interface != PHY_INTERFACE_MODE_SGMII)
mtk_pcs_setup_mode_force(mpcs, interface);
@@ -90,7 +101,7 @@ static int mtk_pcs_config(struct phylink
regmap_update_bits(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL,
SGMII_PHYA_PWD, 0);
- return 0;
+ return changed;
}
static void mtk_pcs_restart_an(struct phylink_pcs *pcs)

View File

@ -0,0 +1,63 @@
From 3027d89f87707e7f3e5b683e0d37a32afb5bde96 Mon Sep 17 00:00:00 2001
From: "Russell King (Oracle)" <rmk+kernel@armlinux.org.uk>
Date: Thu, 27 Oct 2022 14:11:23 +0100
Subject: [PATCH 09/10] net: mtk_eth_soc: move and correct link timer
programming
Program the link timer appropriately for the interface mode being
used, using the newly introduced phylink helper that provides the
nanosecond link timer interval.
The intervals are 1.6ms for SGMII based protocols and 10ms for
802.3z based protocols.
Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
---
drivers/net/ethernet/mediatek/mtk_sgmii.c | 13 ++++++++-----
1 file changed, 8 insertions(+), 5 deletions(-)
--- a/drivers/net/ethernet/mediatek/mtk_sgmii.c
+++ b/drivers/net/ethernet/mediatek/mtk_sgmii.c
@@ -36,10 +36,6 @@ static void mtk_pcs_get_state(struct phy
/* For SGMII interface mode */
static void mtk_pcs_setup_mode_an(struct mtk_pcs *mpcs)
{
- /* Setup the link timer and QPHY power up inside SGMIISYS */
- regmap_write(mpcs->regmap, SGMSYS_PCS_LINK_TIMER,
- SGMII_LINK_TIMER_DEFAULT);
-
regmap_update_bits(mpcs->regmap, SGMSYS_SGMII_MODE,
SGMII_REMOTE_FAULT_DIS, SGMII_REMOTE_FAULT_DIS);
@@ -69,8 +65,8 @@ static int mtk_pcs_config(struct phylink
bool permit_pause_to_mac)
{
struct mtk_pcs *mpcs = pcs_to_mtk_pcs(pcs);
+ int advertise, link_timer;
unsigned int rgc3;
- int advertise;
bool changed;
if (interface == PHY_INTERFACE_MODE_2500BASEX)
@@ -83,6 +79,10 @@ static int mtk_pcs_config(struct phylink
if (advertise < 0)
return advertise;
+ link_timer = phylink_get_link_timer_ns(interface);
+ if (link_timer < 0)
+ return link_timer;
+
/* Configure the underlying interface speed */
regmap_update_bits(mpcs->regmap, mpcs->ana_rgc3,
RG_PHY_SPEED_3_125G, rgc3);
@@ -91,6 +91,9 @@ static int mtk_pcs_config(struct phylink
regmap_update_bits_check(mpcs->regmap, SGMSYS_PCS_ADVERTISE,
SGMII_ADVERTISE, advertise, &changed);
+ /* Setup the link timer and QPHY power up inside SGMIISYS */
+ regmap_write(mpcs->regmap, SGMSYS_PCS_LINK_TIMER, link_timer / 2 / 8);
+
/* Setup SGMIISYS with the determined property */
if (interface != PHY_INTERFACE_MODE_SGMII)
mtk_pcs_setup_mode_force(mpcs, interface);

View File

@ -0,0 +1,132 @@
From 81b0f12a2a8a1699a7d49c3995e5f71e4ec018e6 Mon Sep 17 00:00:00 2001
From: "Russell King (Oracle)" <rmk+kernel@armlinux.org.uk>
Date: Thu, 27 Oct 2022 14:11:28 +0100
Subject: [PATCH 10/10] net: mtk_eth_soc: add support for in-band 802.3z
negotiation
As a result of help from Frank Wunderlich to investigate and test, we
now know how to program this PCS for in-band 802.3z negotiation. Add
support for this by moving the contents of the two functions into the
common mtk_pcs_config() function and adding the register settings for
802.3z negotiation.
Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
---
drivers/net/ethernet/mediatek/mtk_sgmii.c | 77 ++++++++++++-----------
1 file changed, 42 insertions(+), 35 deletions(-)
--- a/drivers/net/ethernet/mediatek/mtk_sgmii.c
+++ b/drivers/net/ethernet/mediatek/mtk_sgmii.c
@@ -33,41 +33,15 @@ static void mtk_pcs_get_state(struct phy
FIELD_GET(SGMII_LPA, adv));
}
-/* For SGMII interface mode */
-static void mtk_pcs_setup_mode_an(struct mtk_pcs *mpcs)
-{
- regmap_update_bits(mpcs->regmap, SGMSYS_SGMII_MODE,
- SGMII_REMOTE_FAULT_DIS, SGMII_REMOTE_FAULT_DIS);
-
- regmap_update_bits(mpcs->regmap, SGMSYS_PCS_CONTROL_1,
- SGMII_AN_RESTART, SGMII_AN_RESTART);
-}
-
-/* For 1000BASE-X and 2500BASE-X interface modes, which operate at a
- * fixed speed.
- */
-static void mtk_pcs_setup_mode_force(struct mtk_pcs *mpcs,
- phy_interface_t interface)
-{
- /* Disable SGMII AN */
- regmap_update_bits(mpcs->regmap, SGMSYS_PCS_CONTROL_1,
- SGMII_AN_ENABLE, 0);
-
- /* Set the speed etc but leave the duplex unchanged */
- regmap_update_bits(mpcs->regmap, SGMSYS_SGMII_MODE,
- SGMII_IF_MODE_MASK & ~SGMII_DUPLEX_FULL,
- SGMII_SPEED_1000);
-}
-
static int mtk_pcs_config(struct phylink_pcs *pcs, unsigned int mode,
phy_interface_t interface,
const unsigned long *advertising,
bool permit_pause_to_mac)
{
struct mtk_pcs *mpcs = pcs_to_mtk_pcs(pcs);
+ unsigned int rgc3, sgm_mode, bmcr;
int advertise, link_timer;
- unsigned int rgc3;
- bool changed;
+ bool changed, use_an;
if (interface == PHY_INTERFACE_MODE_2500BASEX)
rgc3 = RG_PHY_SPEED_3_125G;
@@ -83,6 +57,37 @@ static int mtk_pcs_config(struct phylink
if (link_timer < 0)
return link_timer;
+ /* Clearing IF_MODE_BIT0 switches the PCS to BASE-X mode, and
+ * we assume that fixes it's speed at bitrate = line rate (in
+ * other words, 1000Mbps or 2500Mbps).
+ */
+ if (interface == PHY_INTERFACE_MODE_SGMII) {
+ sgm_mode = SGMII_IF_MODE_SGMII;
+ if (phylink_autoneg_inband(mode)) {
+ sgm_mode |= SGMII_REMOTE_FAULT_DIS |
+ SGMII_SPEED_DUPLEX_AN;
+ use_an = true;
+ } else {
+ use_an = false;
+ }
+ } else if (phylink_autoneg_inband(mode)) {
+ /* 1000base-X or 2500base-X autoneg */
+ sgm_mode = SGMII_REMOTE_FAULT_DIS;
+ use_an = linkmode_test_bit(ETHTOOL_LINK_MODE_Autoneg_BIT,
+ advertising);
+ } else {
+ /* 1000base-X or 2500base-X without autoneg */
+ sgm_mode = 0;
+ use_an = false;
+ }
+
+ if (use_an) {
+ /* FIXME: Do we need to set AN_RESTART here? */
+ bmcr = SGMII_AN_RESTART | SGMII_AN_ENABLE;
+ } else {
+ bmcr = 0;
+ }
+
/* Configure the underlying interface speed */
regmap_update_bits(mpcs->regmap, mpcs->ana_rgc3,
RG_PHY_SPEED_3_125G, rgc3);
@@ -94,11 +99,14 @@ static int mtk_pcs_config(struct phylink
/* Setup the link timer and QPHY power up inside SGMIISYS */
regmap_write(mpcs->regmap, SGMSYS_PCS_LINK_TIMER, link_timer / 2 / 8);
- /* Setup SGMIISYS with the determined property */
- if (interface != PHY_INTERFACE_MODE_SGMII)
- mtk_pcs_setup_mode_force(mpcs, interface);
- else if (phylink_autoneg_inband(mode))
- mtk_pcs_setup_mode_an(mpcs);
+ /* Update the sgmsys mode register */
+ regmap_update_bits(mpcs->regmap, SGMSYS_SGMII_MODE,
+ SGMII_REMOTE_FAULT_DIS | SGMII_SPEED_DUPLEX_AN |
+ SGMII_IF_MODE_SGMII, sgm_mode);
+
+ /* Update the BMCR */
+ regmap_update_bits(mpcs->regmap, SGMSYS_PCS_CONTROL_1,
+ SGMII_AN_RESTART | SGMII_AN_ENABLE, bmcr);
/* Release PHYA power down state */
regmap_update_bits(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL,
@@ -121,8 +129,7 @@ static void mtk_pcs_link_up(struct phyli
struct mtk_pcs *mpcs = pcs_to_mtk_pcs(pcs);
unsigned int sgm_mode;
- if (!phylink_autoneg_inband(mode) ||
- phy_interface_mode_is_8023z(interface)) {
+ if (!phylink_autoneg_inband(mode)) {
/* Force the speed and duplex setting */
if (speed == SPEED_10)
sgm_mode = SGMII_SPEED_10;

View File

@ -1,8 +1,8 @@
From 7ff82416de8295c61423ef6fd75f052d3837d2f7 Mon Sep 17 00:00:00 2001
From: Alexander Couzens <lynxis@fe80.eu>
Date: Wed, 1 Feb 2023 19:23:29 +0100
Subject: [PATCH] net: mediatek: sgmii: ensure the SGMII PHY is powered down on
configuration
Subject: [PATCH 11/13] net: mediatek: sgmii: ensure the SGMII PHY is powered
down on configuration
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
@ -34,7 +34,7 @@ Signed-off-by: Jakub Kicinski <kuba@kernel.org>
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
@@ -1063,11 +1063,13 @@ struct mtk_soc_data {
@@ -1070,11 +1070,13 @@ struct mtk_soc_data {
* @regmap: The register map pointing at the range used to setup
* SGMII modes
* @ana_rgc3: The offset refers to register ANA_RGC3 related to regmap
@ -50,57 +50,51 @@ Signed-off-by: Jakub Kicinski <kuba@kernel.org>
--- a/drivers/net/ethernet/mediatek/mtk_sgmii.c
+++ b/drivers/net/ethernet/mediatek/mtk_sgmii.c
@@ -24,6 +24,10 @@ static int mtk_pcs_setup_mode_an(struct
{
unsigned int val;
@@ -43,11 +43,6 @@ static int mtk_pcs_config(struct phylink
int advertise, link_timer;
bool changed, use_an;
+ regmap_read(mpcs->regmap, mpcs->ana_rgc3, &val);
+ val &= ~RG_PHY_SPEED_MASK;
+ regmap_write(mpcs->regmap, mpcs->ana_rgc3, val);
+
/* Setup the link timer and QPHY power up inside SGMIISYS */
regmap_write(mpcs->regmap, SGMSYS_PCS_LINK_TIMER,
SGMII_LINK_TIMER_DEFAULT);
@@ -36,9 +40,6 @@ static int mtk_pcs_setup_mode_an(struct
val |= SGMII_AN_RESTART;
regmap_write(mpcs->regmap, SGMSYS_PCS_CONTROL_1, val);
- regmap_read(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL, &val);
- val &= ~SGMII_PHYA_PWD;
- regmap_write(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL, val);
return 0;
@@ -69,11 +70,6 @@ static int mtk_pcs_setup_mode_force(stru
val |= SGMII_SPEED_1000;
regmap_write(mpcs->regmap, SGMSYS_SGMII_MODE, val);
- /* Release PHYA power down state */
- regmap_read(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL, &val);
- val &= ~SGMII_PHYA_PWD;
- regmap_write(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL, val);
- if (interface == PHY_INTERFACE_MODE_2500BASEX)
- rgc3 = RG_PHY_SPEED_3_125G;
- else
- rgc3 = 0;
-
return 0;
}
@@ -85,12 +81,32 @@ static int mtk_pcs_config(struct phylink
struct mtk_pcs *mpcs = pcs_to_mtk_pcs(pcs);
int err = 0;
advertise = phylink_mii_c22_pcs_encode_advertisement(interface,
advertising);
if (advertise < 0)
@@ -88,9 +83,22 @@ static int mtk_pcs_config(struct phylink
bmcr = 0;
}
- /* Configure the underlying interface speed */
- regmap_update_bits(mpcs->regmap, mpcs->ana_rgc3,
- RG_PHY_SPEED_3_125G, rgc3);
+ if (mpcs->interface != interface) {
+ /* PHYA power down */
+ regmap_update_bits(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL,
+ SGMII_PHYA_PWD, SGMII_PHYA_PWD);
+
+ if (interface == PHY_INTERFACE_MODE_2500BASEX)
+ rgc3 = RG_PHY_SPEED_3_125G;
+ else
+ rgc3 = 0;
+
+ /* Configure the underlying interface speed */
+ regmap_update_bits(mpcs->regmap, mpcs->ana_rgc3,
+ RG_PHY_SPEED_3_125G, rgc3);
+
+ mpcs->interface = interface;
+ }
+
/* Setup SGMIISYS with the determined property */
if (interface != PHY_INTERFACE_MODE_SGMII)
err = mtk_pcs_setup_mode_force(mpcs, interface);
else if (phylink_autoneg_inband(mode))
err = mtk_pcs_setup_mode_an(mpcs);
/* Update the advertisement, noting whether it has changed */
regmap_update_bits_check(mpcs->regmap, SGMSYS_PCS_ADVERTISE,
@@ -108,9 +116,17 @@ static int mtk_pcs_config(struct phylink
regmap_update_bits(mpcs->regmap, SGMSYS_PCS_CONTROL_1,
SGMII_AN_RESTART | SGMII_AN_ENABLE, bmcr);
- /* Release PHYA power down state */
- regmap_update_bits(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL,
- SGMII_PHYA_PWD, 0);
+ /* Release PHYA power down state
+ * Only removing bit SGMII_PHYA_PWD isn't enough.
+ * There are cases when the SGMII_PHYA_PWD register contains 0x9 which
@ -112,11 +106,10 @@ Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+ */
+ usleep_range(50, 100);
+ regmap_write(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL, 0);
+
return err;
}
@@ -145,6 +161,7 @@ int mtk_sgmii_init(struct mtk_sgmii *ss,
return changed;
}
@@ -171,6 +187,7 @@ int mtk_sgmii_init(struct mtk_sgmii *ss,
return PTR_ERR(ss->pcs[i].regmap);
ss->pcs[i].pcs.ops = &mtk_pcs_ops;

View File

@ -1,7 +1,7 @@
From 9d32637122de88f1ef614c29703f0e050cad342e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Bj=C3=B8rn=20Mork?= <bjorn@mork.no>
Date: Wed, 1 Feb 2023 19:23:30 +0100
Subject: [PATCH] net: mediatek: sgmii: fix duplex configuration
Subject: [PATCH 12/13] net: mediatek: sgmii: fix duplex configuration
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
@ -24,7 +24,7 @@ Signed-off-by: Jakub Kicinski <kuba@kernel.org>
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
@@ -524,7 +524,7 @@
@@ -531,7 +531,7 @@
#define SGMII_SPEED_10 FIELD_PREP(SGMII_SPEED_MASK, 0)
#define SGMII_SPEED_100 FIELD_PREP(SGMII_SPEED_MASK, 1)
#define SGMII_SPEED_1000 FIELD_PREP(SGMII_SPEED_MASK, 2)
@ -35,26 +35,18 @@ Signed-off-by: Jakub Kicinski <kuba@kernel.org>
#define SGMII_CODE_SYNC_SET_VAL BIT(9)
--- a/drivers/net/ethernet/mediatek/mtk_sgmii.c
+++ b/drivers/net/ethernet/mediatek/mtk_sgmii.c
@@ -66,7 +66,7 @@ static int mtk_pcs_setup_mode_force(stru
@@ -154,11 +154,11 @@ static void mtk_pcs_link_up(struct phyli
else
sgm_mode = SGMII_SPEED_1000;
/* Set the speed etc but leave the duplex unchanged */
regmap_read(mpcs->regmap, SGMSYS_SGMII_MODE, &val);
- val &= SGMII_DUPLEX_FULL | ~SGMII_IF_MODE_MASK;
+ val &= SGMII_DUPLEX_HALF | ~SGMII_IF_MODE_MASK;
val |= SGMII_SPEED_1000;
regmap_write(mpcs->regmap, SGMSYS_SGMII_MODE, val);
- if (duplex == DUPLEX_FULL)
- sgm_mode |= SGMII_DUPLEX_FULL;
+ if (duplex != DUPLEX_FULL)
+ sgm_mode |= SGMII_DUPLEX_HALF;
@@ -131,9 +131,10 @@ static void mtk_pcs_link_up(struct phyli
/* SGMII force duplex setting */
regmap_read(mpcs->regmap, SGMSYS_SGMII_MODE, &val);
- val &= ~SGMII_DUPLEX_FULL;
- if (duplex == DUPLEX_FULL)
- val |= SGMII_DUPLEX_FULL;
+
+ val &= ~SGMII_DUPLEX_HALF;
+ if (duplex != DUPLEX_FULL)
+ val |= SGMII_DUPLEX_HALF;
regmap_write(mpcs->regmap, SGMSYS_SGMII_MODE, val);
regmap_update_bits(mpcs->regmap, SGMSYS_SGMII_MODE,
- SGMII_DUPLEX_FULL | SGMII_SPEED_MASK,
+ SGMII_DUPLEX_HALF | SGMII_SPEED_MASK,
sgm_mode);
}
}

View File

@ -1,7 +1,7 @@
From 3337a6e04ddf2923a1bdcf3d31b3b52412bf82dd Mon Sep 17 00:00:00 2001
From: Alexander Couzens <lynxis@fe80.eu>
Date: Wed, 1 Feb 2023 19:23:31 +0100
Subject: [PATCH] mtk_sgmii: enable PCS polling to allow SFP work
Subject: [PATCH 13/13] mtk_sgmii: enable PCS polling to allow SFP work
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
@ -23,7 +23,7 @@ Signed-off-by: Jakub Kicinski <kuba@kernel.org>
--- a/drivers/net/ethernet/mediatek/mtk_sgmii.c
+++ b/drivers/net/ethernet/mediatek/mtk_sgmii.c
@@ -162,6 +162,7 @@ int mtk_sgmii_init(struct mtk_sgmii *ss,
@@ -187,6 +187,7 @@ int mtk_sgmii_init(struct mtk_sgmii *ss,
return PTR_ERR(ss->pcs[i].regmap);
ss->pcs[i].pcs.ops = &mtk_pcs_ops;

View File

@ -1,16 +1,20 @@
From b66105968b8c37c26a75b9da9281cbc1c8f73594 Mon Sep 17 00:00:00 2001
From 611e2dabb4b3243d176739fd6a5a34d007fa3f86 Mon Sep 17 00:00:00 2001
From: Daniel Golle <daniel@makrotopia.org>
Date: Sun, 22 Jan 2023 23:58:36 +0000
Subject: [PATCH] net: ethernet: mtk_eth_soc: reset PCS state
Date: Tue, 14 Mar 2023 00:34:26 +0000
Subject: [PATCH 1/2] net: ethernet: mtk_eth_soc: reset PCS state
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Reset PCS state when changing interface mode.
Reset the internal PCS state machine when changing interface mode.
This prevents confusing the state machine when changing interface
modes, e.g. from SGMII to 2500Base-X or vice-versa.
Fixes: 7e538372694b ("net: ethernet: mediatek: Re-add support SGMII")
Reviewed-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
Tested-by: Bjørn Mork <bjorn@mork.no>
Signed-off-by: Daniel Golle <daniel@makrotopia.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
---
drivers/net/ethernet/mediatek/mtk_eth_soc.h | 4 ++++
drivers/net/ethernet/mediatek/mtk_sgmii.c | 4 ++++
@ -18,7 +22,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
@@ -530,6 +530,10 @@
@@ -539,6 +539,10 @@
#define SGMII_SEND_AN_ERROR_EN BIT(11)
#define SGMII_IF_MODE_MASK GENMASK(5, 1)
@ -31,7 +35,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
#define RG_PHY_SPEED_MASK (BIT(2) | BIT(3))
--- a/drivers/net/ethernet/mediatek/mtk_sgmii.c
+++ b/drivers/net/ethernet/mediatek/mtk_sgmii.c
@@ -90,6 +90,10 @@ static int mtk_pcs_config(struct phylink
@@ -88,6 +88,10 @@ static int mtk_pcs_config(struct phylink
regmap_update_bits(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL,
SGMII_PHYA_PWD, SGMII_PHYA_PWD);
@ -39,6 +43,6 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
+ regmap_update_bits(mpcs->regmap, SGMII_RESERVED_0,
+ SGMII_SW_RESET, SGMII_SW_RESET);
+
mpcs->interface = interface;
}
if (interface == PHY_INTERFACE_MODE_2500BASEX)
rgc3 = RG_PHY_SPEED_3_125G;
else

View File

@ -0,0 +1,103 @@
From 6e933a804c7db8be64f367f33e63cd7dcc302ebb Mon Sep 17 00:00:00 2001
From: Daniel Golle <daniel@makrotopia.org>
Date: Tue, 14 Mar 2023 00:34:45 +0000
Subject: [PATCH 2/2] net: ethernet: mtk_eth_soc: only write values if needed
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Only restart auto-negotiation and write link timer if actually
necessary. This prevents losing the link in case of minor
changes.
Fixes: 7e538372694b ("net: ethernet: mediatek: Re-add support SGMII")
Reviewed-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
Tested-by: Bjørn Mork <bjorn@mork.no>
Signed-off-by: Daniel Golle <daniel@makrotopia.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
---
drivers/net/ethernet/mediatek/mtk_sgmii.c | 24 +++++++++++------------
1 file changed, 12 insertions(+), 12 deletions(-)
--- a/drivers/net/ethernet/mediatek/mtk_sgmii.c
+++ b/drivers/net/ethernet/mediatek/mtk_sgmii.c
@@ -38,20 +38,16 @@ static int mtk_pcs_config(struct phylink
const unsigned long *advertising,
bool permit_pause_to_mac)
{
+ bool mode_changed = false, changed, use_an;
struct mtk_pcs *mpcs = pcs_to_mtk_pcs(pcs);
unsigned int rgc3, sgm_mode, bmcr;
int advertise, link_timer;
- bool changed, use_an;
advertise = phylink_mii_c22_pcs_encode_advertisement(interface,
advertising);
if (advertise < 0)
return advertise;
- link_timer = phylink_get_link_timer_ns(interface);
- if (link_timer < 0)
- return link_timer;
-
/* Clearing IF_MODE_BIT0 switches the PCS to BASE-X mode, and
* we assume that fixes it's speed at bitrate = line rate (in
* other words, 1000Mbps or 2500Mbps).
@@ -77,13 +73,16 @@ static int mtk_pcs_config(struct phylink
}
if (use_an) {
- /* FIXME: Do we need to set AN_RESTART here? */
- bmcr = SGMII_AN_RESTART | SGMII_AN_ENABLE;
+ bmcr = SGMII_AN_ENABLE;
} else {
bmcr = 0;
}
if (mpcs->interface != interface) {
+ link_timer = phylink_get_link_timer_ns(interface);
+ if (link_timer < 0)
+ return link_timer;
+
/* PHYA power down */
regmap_update_bits(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL,
SGMII_PHYA_PWD, SGMII_PHYA_PWD);
@@ -101,16 +100,17 @@ static int mtk_pcs_config(struct phylink
regmap_update_bits(mpcs->regmap, mpcs->ana_rgc3,
RG_PHY_SPEED_3_125G, rgc3);
+ /* Setup the link timer */
+ regmap_write(mpcs->regmap, SGMSYS_PCS_LINK_TIMER, link_timer / 2 / 8);
+
mpcs->interface = interface;
+ mode_changed = true;
}
/* Update the advertisement, noting whether it has changed */
regmap_update_bits_check(mpcs->regmap, SGMSYS_PCS_ADVERTISE,
SGMII_ADVERTISE, advertise, &changed);
- /* Setup the link timer and QPHY power up inside SGMIISYS */
- regmap_write(mpcs->regmap, SGMSYS_PCS_LINK_TIMER, link_timer / 2 / 8);
-
/* Update the sgmsys mode register */
regmap_update_bits(mpcs->regmap, SGMSYS_SGMII_MODE,
SGMII_REMOTE_FAULT_DIS | SGMII_SPEED_DUPLEX_AN |
@@ -118,7 +118,7 @@ static int mtk_pcs_config(struct phylink
/* Update the BMCR */
regmap_update_bits(mpcs->regmap, SGMSYS_PCS_CONTROL_1,
- SGMII_AN_RESTART | SGMII_AN_ENABLE, bmcr);
+ SGMII_AN_ENABLE, bmcr);
/* Release PHYA power down state
* Only removing bit SGMII_PHYA_PWD isn't enough.
@@ -132,7 +132,7 @@ static int mtk_pcs_config(struct phylink
usleep_range(50, 100);
regmap_write(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL, 0);
- return changed;
+ return changed || mode_changed;
}
static void mtk_pcs_restart_an(struct phylink_pcs *pcs)

View File

@ -0,0 +1,183 @@
--- a/drivers/net/ethernet/mediatek/mtk_eth_path.c
+++ b/drivers/net/ethernet/mediatek/mtk_eth_path.c
@@ -96,12 +96,20 @@ static int set_mux_gmac2_gmac0_to_gephy(
static int set_mux_u3_gmac2_to_qphy(struct mtk_eth *eth, int path)
{
- unsigned int val = 0;
+ unsigned int val = 0, mask = 0, reg = 0;
bool updated = true;
switch (path) {
case MTK_ETH_PATH_GMAC2_SGMII:
- val = CO_QPHY_SEL;
+ if (MTK_HAS_CAPS(eth->soc->caps, MTK_U3_COPHY_V2)) {
+ reg = USB_PHY_SWITCH_REG;
+ val = SGMII_QPHY_SEL;
+ mask = QPHY_SEL_MASK;
+ } else {
+ reg = INFRA_MISC2;
+ val = CO_QPHY_SEL;
+ mask = val;
+ }
break;
default:
updated = false;
@@ -109,7 +117,7 @@ static int set_mux_u3_gmac2_to_qphy(stru
}
if (updated)
- regmap_update_bits(eth->infra, INFRA_MISC2, CO_QPHY_SEL, val);
+ regmap_update_bits(eth->infra, reg, mask, val);
dev_dbg(eth->dev, "path %s in %s updated = %d\n",
mtk_eth_path_name(path), __func__, updated);
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -4757,6 +4757,26 @@ static const struct mtk_soc_data mt7629_
},
};
+static const struct mtk_soc_data mt7981_data = {
+ .reg_map = &mt7986_reg_map,
+ .ana_rgc3 = 0x128,
+ .caps = MT7981_CAPS,
+ .hw_features = MTK_HW_FEATURES,
+ .required_clks = MT7981_CLKS_BITMAP,
+ .required_pctl = false,
+ .offload_version = 2,
+ .hash_offset = 4,
+ .foe_entry_size = sizeof(struct mtk_foe_entry),
+ .txrx = {
+ .txd_size = sizeof(struct mtk_tx_dma_v2),
+ .rxd_size = sizeof(struct mtk_rx_dma_v2),
+ .rx_irq_done_mask = MTK_RX_DONE_INT_V2,
+ .rx_dma_l4_valid = RX_DMA_L4_VALID_V2,
+ .dma_max_len = MTK_TX_DMA_BUF_LEN_V2,
+ .dma_len_offset = 8,
+ },
+};
+
static const struct mtk_soc_data mt7986_data = {
.reg_map = &mt7986_reg_map,
.ana_rgc3 = 0x128,
@@ -4799,6 +4819,7 @@ const struct of_device_id of_mtk_match[]
{ .compatible = "mediatek,mt7622-eth", .data = &mt7622_data},
{ .compatible = "mediatek,mt7623-eth", .data = &mt7623_data},
{ .compatible = "mediatek,mt7629-eth", .data = &mt7629_data},
+ { .compatible = "mediatek,mt7981-eth", .data = &mt7981_data},
{ .compatible = "mediatek,mt7986-eth", .data = &mt7986_data},
{ .compatible = "ralink,rt5350-eth", .data = &rt5350_data},
{},
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
@@ -553,11 +553,22 @@
#define SGMSYS_QPHY_PWR_STATE_CTRL 0xe8
#define SGMII_PHYA_PWD BIT(4)
+/* Register to QPHY wrapper control */
+#define SGMSYS_QPHY_WRAP_CTRL 0xec
+#define SGMII_PN_SWAP_MASK GENMASK(1, 0)
+#define SGMII_PN_SWAP_TX_RX (BIT(0) | BIT(1))
+#define MTK_SGMII_FLAG_PN_SWAP BIT(0)
+
/* Infrasys subsystem config registers */
#define INFRA_MISC2 0x70c
#define CO_QPHY_SEL BIT(0)
#define GEPHY_MAC_SEL BIT(1)
+/* Top misc registers */
+#define USB_PHY_SWITCH_REG 0x218
+#define QPHY_SEL_MASK GENMASK(1, 0)
+#define SGMII_QPHY_SEL 0x2
+
/* MT7628/88 specific stuff */
#define MT7628_PDMA_OFFSET 0x0800
#define MT7628_SDM_OFFSET 0x0c00
@@ -738,6 +749,17 @@ enum mtk_clks_map {
BIT(MTK_CLK_SGMII2_CDR_FB) | \
BIT(MTK_CLK_SGMII_CK) | \
BIT(MTK_CLK_ETH2PLL) | BIT(MTK_CLK_SGMIITOP))
+#define MT7981_CLKS_BITMAP (BIT(MTK_CLK_FE) | BIT(MTK_CLK_GP2) | BIT(MTK_CLK_GP1) | \
+ BIT(MTK_CLK_WOCPU0) | \
+ BIT(MTK_CLK_SGMII_TX_250M) | \
+ BIT(MTK_CLK_SGMII_RX_250M) | \
+ BIT(MTK_CLK_SGMII_CDR_REF) | \
+ BIT(MTK_CLK_SGMII_CDR_FB) | \
+ BIT(MTK_CLK_SGMII2_TX_250M) | \
+ BIT(MTK_CLK_SGMII2_RX_250M) | \
+ BIT(MTK_CLK_SGMII2_CDR_REF) | \
+ BIT(MTK_CLK_SGMII2_CDR_FB) | \
+ BIT(MTK_CLK_SGMII_CK))
#define MT7986_CLKS_BITMAP (BIT(MTK_CLK_FE) | BIT(MTK_CLK_GP2) | BIT(MTK_CLK_GP1) | \
BIT(MTK_CLK_WOCPU1) | BIT(MTK_CLK_WOCPU0) | \
BIT(MTK_CLK_SGMII_TX_250M) | \
@@ -851,6 +873,7 @@ enum mkt_eth_capabilities {
MTK_NETSYS_V2_BIT,
MTK_SOC_MT7628_BIT,
MTK_RSTCTRL_PPE1_BIT,
+ MTK_U3_COPHY_V2_BIT,
/* MUX BITS*/
MTK_ETH_MUX_GDM1_TO_GMAC1_ESW_BIT,
@@ -885,6 +908,7 @@ enum mkt_eth_capabilities {
#define MTK_NETSYS_V2 BIT(MTK_NETSYS_V2_BIT)
#define MTK_SOC_MT7628 BIT(MTK_SOC_MT7628_BIT)
#define MTK_RSTCTRL_PPE1 BIT(MTK_RSTCTRL_PPE1_BIT)
+#define MTK_U3_COPHY_V2 BIT(MTK_U3_COPHY_V2_BIT)
#define MTK_ETH_MUX_GDM1_TO_GMAC1_ESW \
BIT(MTK_ETH_MUX_GDM1_TO_GMAC1_ESW_BIT)
@@ -963,6 +987,11 @@ enum mkt_eth_capabilities {
MTK_MUX_U3_GMAC2_TO_QPHY | \
MTK_MUX_GMAC12_TO_GEPHY_SGMII | MTK_QDMA)
+#define MT7981_CAPS (MTK_GMAC1_SGMII | MTK_GMAC2_SGMII | MTK_GMAC2_GEPHY | \
+ MTK_MUX_GMAC12_TO_GEPHY_SGMII | MTK_QDMA | \
+ MTK_MUX_U3_GMAC2_TO_QPHY | MTK_U3_COPHY_V2 | \
+ MTK_NETSYS_V2 | MTK_RSTCTRL_PPE1)
+
#define MT7986_CAPS (MTK_GMAC1_SGMII | MTK_GMAC2_SGMII | \
MTK_MUX_GMAC12_TO_GEPHY_SGMII | MTK_QDMA | \
MTK_NETSYS_V2 | MTK_RSTCTRL_PPE1)
@@ -1076,12 +1105,14 @@ struct mtk_soc_data {
* @ana_rgc3: The offset refers to register ANA_RGC3 related to regmap
* @interface: Currently configured interface mode
* @pcs: Phylink PCS structure
+ * @flags: Flags indicating hardware properties
*/
struct mtk_pcs {
struct regmap *regmap;
u32 ana_rgc3;
phy_interface_t interface;
struct phylink_pcs pcs;
+ u32 flags;
};
/* struct mtk_sgmii - This is the structure holding sgmii regmap and its
--- a/drivers/net/ethernet/mediatek/mtk_sgmii.c
+++ b/drivers/net/ethernet/mediatek/mtk_sgmii.c
@@ -87,6 +87,11 @@ static int mtk_pcs_config(struct phylink
regmap_update_bits(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL,
SGMII_PHYA_PWD, SGMII_PHYA_PWD);
+ if (mpcs->flags & MTK_SGMII_FLAG_PN_SWAP)
+ regmap_update_bits(mpcs->regmap, SGMSYS_QPHY_WRAP_CTRL,
+ SGMII_PN_SWAP_MASK,
+ SGMII_PN_SWAP_TX_RX);
+
/* Reset SGMII PCS state */
regmap_update_bits(mpcs->regmap, SGMII_RESERVED_0,
SGMII_SW_RESET, SGMII_SW_RESET);
@@ -186,6 +191,11 @@ int mtk_sgmii_init(struct mtk_sgmii *ss,
ss->pcs[i].ana_rgc3 = ana_rgc3;
ss->pcs[i].regmap = syscon_node_to_regmap(np);
+
+ ss->pcs[i].flags = 0;
+ if (of_property_read_bool(np, "mediatek,pnswap"))
+ ss->pcs[i].flags |= MTK_SGMII_FLAG_PN_SWAP;
+
of_node_put(np);
if (IS_ERR(ss->pcs[i].regmap))
return PTR_ERR(ss->pcs[i].regmap);

View File

@ -0,0 +1,76 @@
From c0a440031d4314d1023c1b87f43a4233634eebdb Mon Sep 17 00:00:00 2001
From: Daniel Golle <daniel@makrotopia.org>
Date: Sun, 19 Mar 2023 12:57:15 +0000
Subject: [PATCH] net: ethernet: mtk_eth_soc: set MDIO bus clock frequency
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Set MDIO bus clock frequency and allow setting a custom maximum
frequency from device tree.
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
Tested-by: Bjørn Mork <bjorn@mork.no>
Signed-off-by: Daniel Golle <daniel@makrotopia.org>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
---
drivers/net/ethernet/mediatek/mtk_eth_soc.c | 21 +++++++++++++++++++++
drivers/net/ethernet/mediatek/mtk_eth_soc.h | 7 +++++++
2 files changed, 28 insertions(+)
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -704,8 +704,10 @@ static const struct phylink_mac_ops mtk_
static int mtk_mdio_init(struct mtk_eth *eth)
{
+ unsigned int max_clk = 2500000, divider;
struct device_node *mii_np;
int ret;
+ u32 val;
mii_np = of_get_child_by_name(eth->dev->of_node, "mdio-bus");
if (!mii_np) {
@@ -731,6 +733,25 @@ static int mtk_mdio_init(struct mtk_eth
eth->mii_bus->parent = eth->dev;
snprintf(eth->mii_bus->id, MII_BUS_ID_SIZE, "%pOFn", mii_np);
+
+ if (!of_property_read_u32(mii_np, "clock-frequency", &val)) {
+ if (val > MDC_MAX_FREQ || val < MDC_MAX_FREQ / MDC_MAX_DIVIDER) {
+ dev_err(eth->dev, "MDIO clock frequency out of range");
+ ret = -EINVAL;
+ goto err_put_node;
+ }
+ max_clk = val;
+ }
+ divider = min_t(unsigned int, DIV_ROUND_UP(MDC_MAX_FREQ, max_clk), 63);
+
+ /* Configure MDC Divider */
+ val = mtk_r32(eth, MTK_PPSC);
+ val &= ~PPSC_MDC_CFG;
+ val |= FIELD_PREP(PPSC_MDC_CFG, divider) | PPSC_MDC_TURBO;
+ mtk_w32(eth, val, MTK_PPSC);
+
+ dev_dbg(eth->dev, "MDC is running on %d Hz\n", MDC_MAX_FREQ / divider);
+
ret = of_mdiobus_register(eth->mii_bus, mii_np);
err_put_node:
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
@@ -363,6 +363,13 @@
#define RX_DMA_VTAG_V2 BIT(0)
#define RX_DMA_L4_VALID_V2 BIT(2)
+/* PHY Polling and SMI Master Control registers */
+#define MTK_PPSC 0x10000
+#define PPSC_MDC_CFG GENMASK(29, 24)
+#define PPSC_MDC_TURBO BIT(20)
+#define MDC_MAX_FREQ 25000000
+#define MDC_MAX_DIVIDER 63
+
/* PHY Indirect Access Control registers */
#define MTK_PHY_IAC 0x10004
#define PHY_IAC_ACCESS BIT(31)

View File

@ -0,0 +1,512 @@
From 2a3ec7ae313310c1092e4256208cc04d1958e469 Mon Sep 17 00:00:00 2001
From: Daniel Golle <daniel@makrotopia.org>
Date: Sun, 19 Mar 2023 12:58:02 +0000
Subject: [PATCH] net: ethernet: mtk_eth_soc: switch to external PCS driver
Now that we got a PCS driver, use it and remove the now redundant
PCS code and it's header macros from the Ethernet driver.
Signed-off-by: Daniel Golle <daniel@makrotopia.org>
Tested-by: Frank Wunderlich <frank-w@public-files.de>
Reviewed-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
---
drivers/net/ethernet/mediatek/Kconfig | 2 +
drivers/net/ethernet/mediatek/Makefile | 2 +-
drivers/net/ethernet/mediatek/mtk_eth_soc.c | 61 +++++-
drivers/net/ethernet/mediatek/mtk_eth_soc.h | 93 +--------
drivers/net/ethernet/mediatek/mtk_sgmii.c | 217 --------------------
5 files changed, 56 insertions(+), 319 deletions(-)
delete mode 100644 drivers/net/ethernet/mediatek/mtk_sgmii.c
--- a/drivers/net/ethernet/mediatek/Kconfig
+++ b/drivers/net/ethernet/mediatek/Kconfig
@@ -18,6 +18,8 @@ config NET_MEDIATEK_SOC
select DIMLIB
select PAGE_POOL
select PAGE_POOL_STATS
+ select PCS_MTK_LYNXI
+ select REGMAP_MMIO
help
This driver supports the gigabit ethernet MACs in the
MediaTek SoC family.
--- a/drivers/net/ethernet/mediatek/Makefile
+++ b/drivers/net/ethernet/mediatek/Makefile
@@ -4,7 +4,7 @@
#
obj-$(CONFIG_NET_MEDIATEK_SOC) += mtk_eth.o
-mtk_eth-y := mtk_eth_soc.o mtk_sgmii.o mtk_eth_path.o mtk_ppe.o mtk_ppe_debugfs.o mtk_ppe_offload.o
+mtk_eth-y := mtk_eth_soc.o mtk_eth_path.o mtk_ppe.o mtk_ppe_debugfs.o mtk_ppe_offload.o
mtk_eth-$(CONFIG_NET_MEDIATEK_SOC_WED) += mtk_wed.o mtk_wed_mcu.o mtk_wed_wo.o
ifdef CONFIG_DEBUG_FS
mtk_eth-$(CONFIG_NET_MEDIATEK_SOC_WED) += mtk_wed_debugfs.o
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -20,6 +20,7 @@
#include <linux/interrupt.h>
#include <linux/pinctrl/devinfo.h>
#include <linux/phylink.h>
+#include <linux/pcs/pcs-mtk-lynxi.h>
#include <linux/jhash.h>
#include <linux/bitfield.h>
#include <net/dsa.h>
@@ -357,7 +358,7 @@ static struct phylink_pcs *mtk_mac_selec
sid = (MTK_HAS_CAPS(eth->soc->caps, MTK_SHARED_SGMII)) ?
0 : mac->id;
- return mtk_sgmii_select_pcs(eth->sgmii, sid);
+ return eth->sgmii_pcs[sid];
}
return NULL;
@@ -3979,8 +3980,17 @@ static int mtk_unreg_dev(struct mtk_eth
return 0;
}
+static void mtk_sgmii_destroy(struct mtk_eth *eth)
+{
+ int i;
+
+ for (i = 0; i < MTK_MAX_DEVS; i++)
+ mtk_pcs_lynxi_destroy(eth->sgmii_pcs[i]);
+}
+
static int mtk_cleanup(struct mtk_eth *eth)
{
+ mtk_sgmii_destroy(eth);
mtk_unreg_dev(eth);
mtk_free_dev(eth);
cancel_work_sync(&eth->pending_work);
@@ -4410,6 +4420,36 @@ void mtk_eth_set_dma_device(struct mtk_e
rtnl_unlock();
}
+static int mtk_sgmii_init(struct mtk_eth *eth)
+{
+ struct device_node *np;
+ struct regmap *regmap;
+ u32 flags;
+ int i;
+
+ for (i = 0; i < MTK_MAX_DEVS; i++) {
+ np = of_parse_phandle(eth->dev->of_node, "mediatek,sgmiisys", i);
+ if (!np)
+ break;
+
+ regmap = syscon_node_to_regmap(np);
+ flags = 0;
+ if (of_property_read_bool(np, "mediatek,pnswap"))
+ flags |= MTK_SGMII_FLAG_PN_SWAP;
+
+ of_node_put(np);
+
+ if (IS_ERR(regmap))
+ return PTR_ERR(regmap);
+
+ eth->sgmii_pcs[i] = mtk_pcs_lynxi_create(eth->dev, regmap,
+ eth->soc->ana_rgc3,
+ flags);
+ }
+
+ return 0;
+}
+
static int mtk_probe(struct platform_device *pdev)
{
struct resource *res = NULL;
@@ -4473,13 +4513,7 @@ static int mtk_probe(struct platform_dev
}
if (MTK_HAS_CAPS(eth->soc->caps, MTK_SGMII)) {
- eth->sgmii = devm_kzalloc(eth->dev, sizeof(*eth->sgmii),
- GFP_KERNEL);
- if (!eth->sgmii)
- return -ENOMEM;
-
- err = mtk_sgmii_init(eth->sgmii, pdev->dev.of_node,
- eth->soc->ana_rgc3);
+ err = mtk_sgmii_init(eth);
if (err)
return err;
@@ -4490,14 +4524,17 @@ static int mtk_probe(struct platform_dev
"mediatek,pctl");
if (IS_ERR(eth->pctl)) {
dev_err(&pdev->dev, "no pctl regmap found\n");
- return PTR_ERR(eth->pctl);
+ err = PTR_ERR(eth->pctl);
+ goto err_destroy_sgmii;
}
}
if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) {
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!res)
- return -EINVAL;
+ if (!res) {
+ err = -EINVAL;
+ goto err_destroy_sgmii;
+ }
}
if (eth->soc->offload_version) {
@@ -4657,6 +4694,8 @@ err_deinit_hw:
mtk_hw_deinit(eth);
err_wed_exit:
mtk_wed_exit();
+err_destroy_sgmii:
+ mtk_sgmii_destroy(eth);
return err;
}
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
@@ -507,65 +507,6 @@
#define ETHSYS_DMA_AG_MAP_QDMA BIT(1)
#define ETHSYS_DMA_AG_MAP_PPE BIT(2)
-/* SGMII subsystem config registers */
-/* BMCR (low 16) BMSR (high 16) */
-#define SGMSYS_PCS_CONTROL_1 0x0
-#define SGMII_BMCR GENMASK(15, 0)
-#define SGMII_BMSR GENMASK(31, 16)
-#define SGMII_AN_RESTART BIT(9)
-#define SGMII_ISOLATE BIT(10)
-#define SGMII_AN_ENABLE BIT(12)
-#define SGMII_LINK_STATYS BIT(18)
-#define SGMII_AN_ABILITY BIT(19)
-#define SGMII_AN_COMPLETE BIT(21)
-#define SGMII_PCS_FAULT BIT(23)
-#define SGMII_AN_EXPANSION_CLR BIT(30)
-
-#define SGMSYS_PCS_ADVERTISE 0x8
-#define SGMII_ADVERTISE GENMASK(15, 0)
-#define SGMII_LPA GENMASK(31, 16)
-
-/* Register to programmable link timer, the unit in 2 * 8ns */
-#define SGMSYS_PCS_LINK_TIMER 0x18
-#define SGMII_LINK_TIMER_MASK GENMASK(19, 0)
-#define SGMII_LINK_TIMER_DEFAULT (0x186a0 & SGMII_LINK_TIMER_MASK)
-
-/* Register to control remote fault */
-#define SGMSYS_SGMII_MODE 0x20
-#define SGMII_IF_MODE_SGMII BIT(0)
-#define SGMII_SPEED_DUPLEX_AN BIT(1)
-#define SGMII_SPEED_MASK GENMASK(3, 2)
-#define SGMII_SPEED_10 FIELD_PREP(SGMII_SPEED_MASK, 0)
-#define SGMII_SPEED_100 FIELD_PREP(SGMII_SPEED_MASK, 1)
-#define SGMII_SPEED_1000 FIELD_PREP(SGMII_SPEED_MASK, 2)
-#define SGMII_DUPLEX_HALF BIT(4)
-#define SGMII_IF_MODE_BIT5 BIT(5)
-#define SGMII_REMOTE_FAULT_DIS BIT(8)
-#define SGMII_CODE_SYNC_SET_VAL BIT(9)
-#define SGMII_CODE_SYNC_SET_EN BIT(10)
-#define SGMII_SEND_AN_ERROR_EN BIT(11)
-#define SGMII_IF_MODE_MASK GENMASK(5, 1)
-
-/* Register to reset SGMII design */
-#define SGMII_RESERVED_0 0x34
-#define SGMII_SW_RESET BIT(0)
-
-/* Register to set SGMII speed, ANA RG_ Control Signals III*/
-#define SGMSYS_ANA_RG_CS3 0x2028
-#define RG_PHY_SPEED_MASK (BIT(2) | BIT(3))
-#define RG_PHY_SPEED_1_25G 0x0
-#define RG_PHY_SPEED_3_125G BIT(2)
-
-/* Register to power up QPHY */
-#define SGMSYS_QPHY_PWR_STATE_CTRL 0xe8
-#define SGMII_PHYA_PWD BIT(4)
-
-/* Register to QPHY wrapper control */
-#define SGMSYS_QPHY_WRAP_CTRL 0xec
-#define SGMII_PN_SWAP_MASK GENMASK(1, 0)
-#define SGMII_PN_SWAP_TX_RX (BIT(0) | BIT(1))
-#define MTK_SGMII_FLAG_PN_SWAP BIT(0)
-
/* Infrasys subsystem config registers */
#define INFRA_MISC2 0x70c
#define CO_QPHY_SEL BIT(0)
@@ -1105,31 +1046,6 @@ struct mtk_soc_data {
/* currently no SoC has more than 2 macs */
#define MTK_MAX_DEVS 2
-/* struct mtk_pcs - This structure holds each sgmii regmap and associated
- * data
- * @regmap: The register map pointing at the range used to setup
- * SGMII modes
- * @ana_rgc3: The offset refers to register ANA_RGC3 related to regmap
- * @interface: Currently configured interface mode
- * @pcs: Phylink PCS structure
- * @flags: Flags indicating hardware properties
- */
-struct mtk_pcs {
- struct regmap *regmap;
- u32 ana_rgc3;
- phy_interface_t interface;
- struct phylink_pcs pcs;
- u32 flags;
-};
-
-/* struct mtk_sgmii - This is the structure holding sgmii regmap and its
- * characteristics
- * @pcs Array of individual PCS structures
- */
-struct mtk_sgmii {
- struct mtk_pcs pcs[MTK_MAX_DEVS];
-};
-
/* struct mtk_eth - This is the main datasructure for holding the state
* of the driver
* @dev: The device pointer
@@ -1149,6 +1065,7 @@ struct mtk_sgmii {
* MII modes
* @infra: The register map pointing at the range used to setup
* SGMII and GePHY path
+ * @sgmii_pcs: Pointers to mtk-pcs-lynxi phylink_pcs instances
* @pctl: The register map pointing at the range used to setup
* GMAC port drive/slew values
* @dma_refcnt: track how many netdevs are using the DMA engine
@@ -1189,8 +1106,8 @@ struct mtk_eth {
u32 msg_enable;
unsigned long sysclk;
struct regmap *ethsys;
- struct regmap *infra;
- struct mtk_sgmii *sgmii;
+ struct regmap *infra;
+ struct phylink_pcs *sgmii_pcs[MTK_MAX_DEVS];
struct regmap *pctl;
bool hwlro;
refcount_t dma_refcnt;
@@ -1352,10 +1269,6 @@ void mtk_stats_update_mac(struct mtk_mac
void mtk_w32(struct mtk_eth *eth, u32 val, unsigned reg);
u32 mtk_r32(struct mtk_eth *eth, unsigned reg);
-struct phylink_pcs *mtk_sgmii_select_pcs(struct mtk_sgmii *ss, int id);
-int mtk_sgmii_init(struct mtk_sgmii *ss, struct device_node *np,
- u32 ana_rgc3);
-
int mtk_gmac_sgmii_path_setup(struct mtk_eth *eth, int mac_id);
int mtk_gmac_gephy_path_setup(struct mtk_eth *eth, int mac_id);
int mtk_gmac_rgmii_path_setup(struct mtk_eth *eth, int mac_id);
--- a/drivers/net/ethernet/mediatek/mtk_sgmii.c
+++ /dev/null
@@ -1,217 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-// Copyright (c) 2018-2019 MediaTek Inc.
-
-/* A library for MediaTek SGMII circuit
- *
- * Author: Sean Wang <sean.wang@mediatek.com>
- *
- */
-
-#include <linux/mfd/syscon.h>
-#include <linux/of.h>
-#include <linux/phylink.h>
-#include <linux/regmap.h>
-
-#include "mtk_eth_soc.h"
-
-static struct mtk_pcs *pcs_to_mtk_pcs(struct phylink_pcs *pcs)
-{
- return container_of(pcs, struct mtk_pcs, pcs);
-}
-
-static void mtk_pcs_get_state(struct phylink_pcs *pcs,
- struct phylink_link_state *state)
-{
- struct mtk_pcs *mpcs = pcs_to_mtk_pcs(pcs);
- unsigned int bm, adv;
-
- /* Read the BMSR and LPA */
- regmap_read(mpcs->regmap, SGMSYS_PCS_CONTROL_1, &bm);
- regmap_read(mpcs->regmap, SGMSYS_PCS_ADVERTISE, &adv);
-
- phylink_mii_c22_pcs_decode_state(state, FIELD_GET(SGMII_BMSR, bm),
- FIELD_GET(SGMII_LPA, adv));
-}
-
-static int mtk_pcs_config(struct phylink_pcs *pcs, unsigned int mode,
- phy_interface_t interface,
- const unsigned long *advertising,
- bool permit_pause_to_mac)
-{
- bool mode_changed = false, changed, use_an;
- struct mtk_pcs *mpcs = pcs_to_mtk_pcs(pcs);
- unsigned int rgc3, sgm_mode, bmcr;
- int advertise, link_timer;
-
- advertise = phylink_mii_c22_pcs_encode_advertisement(interface,
- advertising);
- if (advertise < 0)
- return advertise;
-
- /* Clearing IF_MODE_BIT0 switches the PCS to BASE-X mode, and
- * we assume that fixes it's speed at bitrate = line rate (in
- * other words, 1000Mbps or 2500Mbps).
- */
- if (interface == PHY_INTERFACE_MODE_SGMII) {
- sgm_mode = SGMII_IF_MODE_SGMII;
- if (phylink_autoneg_inband(mode)) {
- sgm_mode |= SGMII_REMOTE_FAULT_DIS |
- SGMII_SPEED_DUPLEX_AN;
- use_an = true;
- } else {
- use_an = false;
- }
- } else if (phylink_autoneg_inband(mode)) {
- /* 1000base-X or 2500base-X autoneg */
- sgm_mode = SGMII_REMOTE_FAULT_DIS;
- use_an = linkmode_test_bit(ETHTOOL_LINK_MODE_Autoneg_BIT,
- advertising);
- } else {
- /* 1000base-X or 2500base-X without autoneg */
- sgm_mode = 0;
- use_an = false;
- }
-
- if (use_an) {
- bmcr = SGMII_AN_ENABLE;
- } else {
- bmcr = 0;
- }
-
- if (mpcs->interface != interface) {
- link_timer = phylink_get_link_timer_ns(interface);
- if (link_timer < 0)
- return link_timer;
-
- /* PHYA power down */
- regmap_update_bits(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL,
- SGMII_PHYA_PWD, SGMII_PHYA_PWD);
-
- if (mpcs->flags & MTK_SGMII_FLAG_PN_SWAP)
- regmap_update_bits(mpcs->regmap, SGMSYS_QPHY_WRAP_CTRL,
- SGMII_PN_SWAP_MASK,
- SGMII_PN_SWAP_TX_RX);
-
- /* Reset SGMII PCS state */
- regmap_update_bits(mpcs->regmap, SGMII_RESERVED_0,
- SGMII_SW_RESET, SGMII_SW_RESET);
-
- if (interface == PHY_INTERFACE_MODE_2500BASEX)
- rgc3 = RG_PHY_SPEED_3_125G;
- else
- rgc3 = 0;
-
- /* Configure the underlying interface speed */
- regmap_update_bits(mpcs->regmap, mpcs->ana_rgc3,
- RG_PHY_SPEED_3_125G, rgc3);
-
- /* Setup the link timer */
- regmap_write(mpcs->regmap, SGMSYS_PCS_LINK_TIMER, link_timer / 2 / 8);
-
- mpcs->interface = interface;
- mode_changed = true;
- }
-
- /* Update the advertisement, noting whether it has changed */
- regmap_update_bits_check(mpcs->regmap, SGMSYS_PCS_ADVERTISE,
- SGMII_ADVERTISE, advertise, &changed);
-
- /* Update the sgmsys mode register */
- regmap_update_bits(mpcs->regmap, SGMSYS_SGMII_MODE,
- SGMII_REMOTE_FAULT_DIS | SGMII_SPEED_DUPLEX_AN |
- SGMII_IF_MODE_SGMII, sgm_mode);
-
- /* Update the BMCR */
- regmap_update_bits(mpcs->regmap, SGMSYS_PCS_CONTROL_1,
- SGMII_AN_ENABLE, bmcr);
-
- /* Release PHYA power down state
- * Only removing bit SGMII_PHYA_PWD isn't enough.
- * There are cases when the SGMII_PHYA_PWD register contains 0x9 which
- * prevents SGMII from working. The SGMII still shows link but no traffic
- * can flow. Writing 0x0 to the PHYA_PWD register fix the issue. 0x0 was
- * taken from a good working state of the SGMII interface.
- * Unknown how much the QPHY needs but it is racy without a sleep.
- * Tested on mt7622 & mt7986.
- */
- usleep_range(50, 100);
- regmap_write(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL, 0);
-
- return changed || mode_changed;
-}
-
-static void mtk_pcs_restart_an(struct phylink_pcs *pcs)
-{
- struct mtk_pcs *mpcs = pcs_to_mtk_pcs(pcs);
-
- regmap_update_bits(mpcs->regmap, SGMSYS_PCS_CONTROL_1,
- SGMII_AN_RESTART, SGMII_AN_RESTART);
-}
-
-static void mtk_pcs_link_up(struct phylink_pcs *pcs, unsigned int mode,
- phy_interface_t interface, int speed, int duplex)
-{
- struct mtk_pcs *mpcs = pcs_to_mtk_pcs(pcs);
- unsigned int sgm_mode;
-
- if (!phylink_autoneg_inband(mode)) {
- /* Force the speed and duplex setting */
- if (speed == SPEED_10)
- sgm_mode = SGMII_SPEED_10;
- else if (speed == SPEED_100)
- sgm_mode = SGMII_SPEED_100;
- else
- sgm_mode = SGMII_SPEED_1000;
-
- if (duplex != DUPLEX_FULL)
- sgm_mode |= SGMII_DUPLEX_HALF;
-
- regmap_update_bits(mpcs->regmap, SGMSYS_SGMII_MODE,
- SGMII_DUPLEX_HALF | SGMII_SPEED_MASK,
- sgm_mode);
- }
-}
-
-static const struct phylink_pcs_ops mtk_pcs_ops = {
- .pcs_get_state = mtk_pcs_get_state,
- .pcs_config = mtk_pcs_config,
- .pcs_an_restart = mtk_pcs_restart_an,
- .pcs_link_up = mtk_pcs_link_up,
-};
-
-int mtk_sgmii_init(struct mtk_sgmii *ss, struct device_node *r, u32 ana_rgc3)
-{
- struct device_node *np;
- int i;
-
- for (i = 0; i < MTK_MAX_DEVS; i++) {
- np = of_parse_phandle(r, "mediatek,sgmiisys", i);
- if (!np)
- break;
-
- ss->pcs[i].ana_rgc3 = ana_rgc3;
- ss->pcs[i].regmap = syscon_node_to_regmap(np);
-
- ss->pcs[i].flags = 0;
- if (of_property_read_bool(np, "mediatek,pnswap"))
- ss->pcs[i].flags |= MTK_SGMII_FLAG_PN_SWAP;
-
- of_node_put(np);
- if (IS_ERR(ss->pcs[i].regmap))
- return PTR_ERR(ss->pcs[i].regmap);
-
- ss->pcs[i].pcs.ops = &mtk_pcs_ops;
- ss->pcs[i].pcs.poll = true;
- ss->pcs[i].interface = PHY_INTERFACE_MODE_NA;
- }
-
- return 0;
-}
-
-struct phylink_pcs *mtk_sgmii_select_pcs(struct mtk_sgmii *ss, int id)
-{
- if (!ss->pcs[id].regmap)
- return NULL;
-
- return &ss->pcs[id].pcs;
-}

View File

@ -0,0 +1,514 @@
From patchwork Thu Mar 9 10:57:44 2023
Content-Type: text/plain; charset="utf-8"
MIME-Version: 1.0
Content-Transfer-Encoding: 8bit
X-Patchwork-Submitter: Daniel Golle <daniel@makrotopia.org>
X-Patchwork-Id: 13167235
X-Patchwork-Delegate: kuba@kernel.org
Return-Path: <netdev-owner@vger.kernel.org>
Date: Thu, 9 Mar 2023 10:57:44 +0000
From: Daniel Golle <daniel@makrotopia.org>
To: netdev@vger.kernel.org, linux-mediatek@lists.infradead.org,
linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org,
Russell King <linux@armlinux.org.uk>,
Heiner Kallweit <hkallweit1@gmail.com>,
Lorenzo Bianconi <lorenzo@kernel.org>,
Mark Lee <Mark-MC.Lee@mediatek.com>,
John Crispin <john@phrozen.org>, Felix Fietkau <nbd@nbd.name>,
AngeloGioacchino Del Regno
<angelogioacchino.delregno@collabora.com>,
Matthias Brugger <matthias.bgg@gmail.com>,
DENG Qingfang <dqfext@gmail.com>,
Landen Chao <Landen.Chao@mediatek.com>,
Sean Wang <sean.wang@mediatek.com>,
Paolo Abeni <pabeni@redhat.com>,
Jakub Kicinski <kuba@kernel.org>,
Eric Dumazet <edumazet@google.com>,
"David S. Miller" <davem@davemloft.net>,
Vladimir Oltean <olteanv@gmail.com>,
Florian Fainelli <f.fainelli@gmail.com>,
Andrew Lunn <andrew@lunn.ch>,
Vladimir Oltean <vladimir.oltean@nxp.com>
Cc: =?iso-8859-1?q?Bj=F8rn?= Mork <bjorn@mork.no>,
Frank Wunderlich <frank-w@public-files.de>,
Alexander Couzens <lynxis@fe80.eu>
Subject: [PATCH net-next v13 11/16] net: dsa: mt7530: use external PCS driver
Message-ID:
<2ac2ee40d3b0e705461b50613fda6a7edfdbc4b3.1678357225.git.daniel@makrotopia.org>
References: <cover.1678357225.git.daniel@makrotopia.org>
MIME-Version: 1.0
Content-Disposition: inline
In-Reply-To: <cover.1678357225.git.daniel@makrotopia.org>
Precedence: bulk
List-ID: <netdev.vger.kernel.org>
X-Mailing-List: netdev@vger.kernel.org
X-Patchwork-Delegate: kuba@kernel.org
Implement regmap access wrappers, for now only to be used by the
pcs-mtk driver.
Make use of external PCS driver and drop the reduntant implementation
in mt7530.c.
As a nice side effect the SGMII registers can now also more easily be
inspected for debugging via /sys/kernel/debug/regmap.
Reviewed-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
Tested-by: Bjørn Mork <bjorn@mork.no>
Signed-off-by: Daniel Golle <daniel@makrotopia.org>
Tested-by: Frank Wunderlich <frank-w@public-files.de>
---
drivers/net/dsa/Kconfig | 1 +
drivers/net/dsa/mt7530.c | 277 ++++++++++-----------------------------
drivers/net/dsa/mt7530.h | 47 +------
3 files changed, 71 insertions(+), 254 deletions(-)
--- a/drivers/net/dsa/Kconfig
+++ b/drivers/net/dsa/Kconfig
@@ -37,6 +37,7 @@ config NET_DSA_MT7530
tristate "MediaTek MT753x and MT7621 Ethernet switch support"
select NET_DSA_TAG_MTK
select MEDIATEK_GE_PHY
+ select PCS_MTK_LYNXI
help
This enables support for the MediaTek MT7530, MT7531, and MT7621
Ethernet switch chips.
--- a/drivers/net/dsa/mt7530.c
+++ b/drivers/net/dsa/mt7530.c
@@ -14,6 +14,7 @@
#include <linux/of_mdio.h>
#include <linux/of_net.h>
#include <linux/of_platform.h>
+#include <linux/pcs/pcs-mtk-lynxi.h>
#include <linux/phylink.h>
#include <linux/regmap.h>
#include <linux/regulator/consumer.h>
@@ -2568,128 +2569,11 @@ static int mt7531_rgmii_setup(struct mt7
return 0;
}
-static void mt7531_pcs_link_up(struct phylink_pcs *pcs, unsigned int mode,
- phy_interface_t interface, int speed, int duplex)
-{
- struct mt7530_priv *priv = pcs_to_mt753x_pcs(pcs)->priv;
- int port = pcs_to_mt753x_pcs(pcs)->port;
- unsigned int val;
-
- /* For adjusting speed and duplex of SGMII force mode. */
- if (interface != PHY_INTERFACE_MODE_SGMII ||
- phylink_autoneg_inband(mode))
- return;
-
- /* SGMII force mode setting */
- val = mt7530_read(priv, MT7531_SGMII_MODE(port));
- val &= ~MT7531_SGMII_IF_MODE_MASK;
-
- switch (speed) {
- case SPEED_10:
- val |= MT7531_SGMII_FORCE_SPEED_10;
- break;
- case SPEED_100:
- val |= MT7531_SGMII_FORCE_SPEED_100;
- break;
- case SPEED_1000:
- val |= MT7531_SGMII_FORCE_SPEED_1000;
- break;
- }
-
- /* MT7531 SGMII 1G force mode can only work in full duplex mode,
- * no matter MT7531_SGMII_FORCE_HALF_DUPLEX is set or not.
- *
- * The speed check is unnecessary as the MAC capabilities apply
- * this restriction. --rmk
- */
- if ((speed == SPEED_10 || speed == SPEED_100) &&
- duplex != DUPLEX_FULL)
- val |= MT7531_SGMII_FORCE_HALF_DUPLEX;
-
- mt7530_write(priv, MT7531_SGMII_MODE(port), val);
-}
-
static bool mt753x_is_mac_port(u32 port)
{
return (port == 5 || port == 6);
}
-static int mt7531_sgmii_setup_mode_force(struct mt7530_priv *priv, u32 port,
- phy_interface_t interface)
-{
- u32 val;
-
- if (!mt753x_is_mac_port(port))
- return -EINVAL;
-
- mt7530_set(priv, MT7531_QPHY_PWR_STATE_CTRL(port),
- MT7531_SGMII_PHYA_PWD);
-
- val = mt7530_read(priv, MT7531_PHYA_CTRL_SIGNAL3(port));
- val &= ~MT7531_RG_TPHY_SPEED_MASK;
- /* Setup 2.5 times faster clock for 2.5Gbps data speeds with 10B/8B
- * encoding.
- */
- val |= (interface == PHY_INTERFACE_MODE_2500BASEX) ?
- MT7531_RG_TPHY_SPEED_3_125G : MT7531_RG_TPHY_SPEED_1_25G;
- mt7530_write(priv, MT7531_PHYA_CTRL_SIGNAL3(port), val);
-
- mt7530_clear(priv, MT7531_PCS_CONTROL_1(port), MT7531_SGMII_AN_ENABLE);
-
- /* MT7531 SGMII 1G and 2.5G force mode can only work in full duplex
- * mode, no matter MT7531_SGMII_FORCE_HALF_DUPLEX is set or not.
- */
- mt7530_rmw(priv, MT7531_SGMII_MODE(port),
- MT7531_SGMII_IF_MODE_MASK | MT7531_SGMII_REMOTE_FAULT_DIS,
- MT7531_SGMII_FORCE_SPEED_1000);
-
- mt7530_write(priv, MT7531_QPHY_PWR_STATE_CTRL(port), 0);
-
- return 0;
-}
-
-static int mt7531_sgmii_setup_mode_an(struct mt7530_priv *priv, int port,
- phy_interface_t interface)
-{
- if (!mt753x_is_mac_port(port))
- return -EINVAL;
-
- mt7530_set(priv, MT7531_QPHY_PWR_STATE_CTRL(port),
- MT7531_SGMII_PHYA_PWD);
-
- mt7530_rmw(priv, MT7531_PHYA_CTRL_SIGNAL3(port),
- MT7531_RG_TPHY_SPEED_MASK, MT7531_RG_TPHY_SPEED_1_25G);
-
- mt7530_set(priv, MT7531_SGMII_MODE(port),
- MT7531_SGMII_REMOTE_FAULT_DIS |
- MT7531_SGMII_SPEED_DUPLEX_AN);
-
- mt7530_rmw(priv, MT7531_PCS_SPEED_ABILITY(port),
- MT7531_SGMII_TX_CONFIG_MASK, 1);
-
- mt7530_set(priv, MT7531_PCS_CONTROL_1(port), MT7531_SGMII_AN_ENABLE);
-
- mt7530_set(priv, MT7531_PCS_CONTROL_1(port), MT7531_SGMII_AN_RESTART);
-
- mt7530_write(priv, MT7531_QPHY_PWR_STATE_CTRL(port), 0);
-
- return 0;
-}
-
-static void mt7531_pcs_an_restart(struct phylink_pcs *pcs)
-{
- struct mt7530_priv *priv = pcs_to_mt753x_pcs(pcs)->priv;
- int port = pcs_to_mt753x_pcs(pcs)->port;
- u32 val;
-
- /* Only restart AN when AN is enabled */
- val = mt7530_read(priv, MT7531_PCS_CONTROL_1(port));
- if (val & MT7531_SGMII_AN_ENABLE) {
- val |= MT7531_SGMII_AN_RESTART;
- mt7530_write(priv, MT7531_PCS_CONTROL_1(port), val);
- }
-}
-
static int
mt7531_mac_config(struct dsa_switch *ds, int port, unsigned int mode,
phy_interface_t interface)
@@ -2712,11 +2596,11 @@ mt7531_mac_config(struct dsa_switch *ds,
phydev = dp->slave->phydev;
return mt7531_rgmii_setup(priv, port, interface, phydev);
case PHY_INTERFACE_MODE_SGMII:
- return mt7531_sgmii_setup_mode_an(priv, port, interface);
case PHY_INTERFACE_MODE_NA:
case PHY_INTERFACE_MODE_1000BASEX:
case PHY_INTERFACE_MODE_2500BASEX:
- return mt7531_sgmii_setup_mode_force(priv, port, interface);
+ /* handled in SGMII PCS driver */
+ return 0;
default:
return -EINVAL;
}
@@ -2741,11 +2625,11 @@ mt753x_phylink_mac_select_pcs(struct dsa
switch (interface) {
case PHY_INTERFACE_MODE_TRGMII:
+ return &priv->pcs[port].pcs;
case PHY_INTERFACE_MODE_SGMII:
case PHY_INTERFACE_MODE_1000BASEX:
case PHY_INTERFACE_MODE_2500BASEX:
- return &priv->pcs[port].pcs;
-
+ return priv->ports[port].sgmii_pcs;
default:
return NULL;
}
@@ -2986,86 +2870,6 @@ static void mt7530_pcs_get_state(struct
state->pause |= MLO_PAUSE_TX;
}
-static int
-mt7531_sgmii_pcs_get_state_an(struct mt7530_priv *priv, int port,
- struct phylink_link_state *state)
-{
- u32 status, val;
- u16 config_reg;
-
- status = mt7530_read(priv, MT7531_PCS_CONTROL_1(port));
- state->link = !!(status & MT7531_SGMII_LINK_STATUS);
- state->an_complete = !!(status & MT7531_SGMII_AN_COMPLETE);
- if (state->interface == PHY_INTERFACE_MODE_SGMII &&
- (status & MT7531_SGMII_AN_ENABLE)) {
- val = mt7530_read(priv, MT7531_PCS_SPEED_ABILITY(port));
- config_reg = val >> 16;
-
- switch (config_reg & LPA_SGMII_SPD_MASK) {
- case LPA_SGMII_1000:
- state->speed = SPEED_1000;
- break;
- case LPA_SGMII_100:
- state->speed = SPEED_100;
- break;
- case LPA_SGMII_10:
- state->speed = SPEED_10;
- break;
- default:
- dev_err(priv->dev, "invalid sgmii PHY speed\n");
- state->link = false;
- return -EINVAL;
- }
-
- if (config_reg & LPA_SGMII_FULL_DUPLEX)
- state->duplex = DUPLEX_FULL;
- else
- state->duplex = DUPLEX_HALF;
- }
-
- return 0;
-}
-
-static void
-mt7531_sgmii_pcs_get_state_inband(struct mt7530_priv *priv, int port,
- struct phylink_link_state *state)
-{
- unsigned int val;
-
- val = mt7530_read(priv, MT7531_PCS_CONTROL_1(port));
- state->link = !!(val & MT7531_SGMII_LINK_STATUS);
- if (!state->link)
- return;
-
- state->an_complete = state->link;
-
- if (state->interface == PHY_INTERFACE_MODE_2500BASEX)
- state->speed = SPEED_2500;
- else
- state->speed = SPEED_1000;
-
- state->duplex = DUPLEX_FULL;
- state->pause = MLO_PAUSE_NONE;
-}
-
-static void mt7531_pcs_get_state(struct phylink_pcs *pcs,
- struct phylink_link_state *state)
-{
- struct mt7530_priv *priv = pcs_to_mt753x_pcs(pcs)->priv;
- int port = pcs_to_mt753x_pcs(pcs)->port;
-
- if (state->interface == PHY_INTERFACE_MODE_SGMII) {
- mt7531_sgmii_pcs_get_state_an(priv, port, state);
- return;
- } else if ((state->interface == PHY_INTERFACE_MODE_1000BASEX) ||
- (state->interface == PHY_INTERFACE_MODE_2500BASEX)) {
- mt7531_sgmii_pcs_get_state_inband(priv, port, state);
- return;
- }
-
- state->link = false;
-}
-
static int mt753x_pcs_config(struct phylink_pcs *pcs, unsigned int mode,
phy_interface_t interface,
const unsigned long *advertising,
@@ -3085,18 +2889,57 @@ static const struct phylink_pcs_ops mt75
.pcs_an_restart = mt7530_pcs_an_restart,
};
-static const struct phylink_pcs_ops mt7531_pcs_ops = {
- .pcs_validate = mt753x_pcs_validate,
- .pcs_get_state = mt7531_pcs_get_state,
- .pcs_config = mt753x_pcs_config,
- .pcs_an_restart = mt7531_pcs_an_restart,
- .pcs_link_up = mt7531_pcs_link_up,
+static int mt7530_regmap_read(void *context, unsigned int reg, unsigned int *val)
+{
+ struct mt7530_priv *priv = context;
+
+ *val = mt7530_read(priv, reg);
+ return 0;
+};
+
+static int mt7530_regmap_write(void *context, unsigned int reg, unsigned int val)
+{
+ struct mt7530_priv *priv = context;
+
+ mt7530_write(priv, reg, val);
+ return 0;
+};
+
+static int mt7530_regmap_update_bits(void *context, unsigned int reg,
+ unsigned int mask, unsigned int val)
+{
+ struct mt7530_priv *priv = context;
+
+ mt7530_rmw(priv, reg, mask, val);
+ return 0;
+};
+
+static const struct regmap_bus mt7531_regmap_bus = {
+ .reg_write = mt7530_regmap_write,
+ .reg_read = mt7530_regmap_read,
+ .reg_update_bits = mt7530_regmap_update_bits,
+};
+
+#define MT7531_PCS_REGMAP_CONFIG(_name, _reg_base) \
+ { \
+ .name = _name, \
+ .reg_bits = 16, \
+ .val_bits = 32, \
+ .reg_stride = 4, \
+ .reg_base = _reg_base, \
+ .max_register = 0x17c, \
+ }
+
+static const struct regmap_config mt7531_pcs_config[] = {
+ MT7531_PCS_REGMAP_CONFIG("port5", MT7531_SGMII_REG_BASE(5)),
+ MT7531_PCS_REGMAP_CONFIG("port6", MT7531_SGMII_REG_BASE(6)),
};
static int
mt753x_setup(struct dsa_switch *ds)
{
struct mt7530_priv *priv = ds->priv;
+ struct regmap *regmap;
int i, ret;
/* Initialise the PCS devices */
@@ -3104,8 +2947,6 @@ mt753x_setup(struct dsa_switch *ds)
priv->pcs[i].pcs.ops = priv->info->pcs_ops;
priv->pcs[i].priv = priv;
priv->pcs[i].port = i;
- if (mt753x_is_mac_port(i))
- priv->pcs[i].pcs.poll = 1;
}
ret = priv->info->sw_setup(ds);
@@ -3120,6 +2961,16 @@ mt753x_setup(struct dsa_switch *ds)
if (ret && priv->irq)
mt7530_free_irq_common(priv);
+ if (priv->id == ID_MT7531)
+ for (i = 0; i < 2; i++) {
+ regmap = devm_regmap_init(ds->dev,
+ &mt7531_regmap_bus, priv,
+ &mt7531_pcs_config[i]);
+ priv->ports[5 + i].sgmii_pcs =
+ mtk_pcs_lynxi_create(ds->dev, regmap,
+ MT7531_PHYA_CTRL_SIGNAL3, 0);
+ }
+
return ret;
}
@@ -3211,7 +3062,7 @@ static const struct mt753x_info mt753x_t
},
[ID_MT7531] = {
.id = ID_MT7531,
- .pcs_ops = &mt7531_pcs_ops,
+ .pcs_ops = &mt7530_pcs_ops,
.sw_setup = mt7531_setup,
.phy_read = mt7531_ind_phy_read,
.phy_write = mt7531_ind_phy_write,
@@ -3319,7 +3170,7 @@ static void
mt7530_remove(struct mdio_device *mdiodev)
{
struct mt7530_priv *priv = dev_get_drvdata(&mdiodev->dev);
- int ret = 0;
+ int ret = 0, i;
if (!priv)
return;
@@ -3338,6 +3189,10 @@ mt7530_remove(struct mdio_device *mdiode
mt7530_free_irq(priv);
dsa_unregister_switch(priv->ds);
+
+ for (i = 0; i < 2; ++i)
+ mtk_pcs_lynxi_destroy(priv->ports[5 + i].sgmii_pcs);
+
mutex_destroy(&priv->reg_mutex);
dev_set_drvdata(&mdiodev->dev, NULL);
--- a/drivers/net/dsa/mt7530.h
+++ b/drivers/net/dsa/mt7530.h
@@ -364,47 +364,8 @@ enum mt7530_vlan_port_acc_frm {
CCR_TX_OCT_CNT_BAD)
/* MT7531 SGMII register group */
-#define MT7531_SGMII_REG_BASE 0x5000
-#define MT7531_SGMII_REG(p, r) (MT7531_SGMII_REG_BASE + \
- ((p) - 5) * 0x1000 + (r))
-
-/* Register forSGMII PCS_CONTROL_1 */
-#define MT7531_PCS_CONTROL_1(p) MT7531_SGMII_REG(p, 0x00)
-#define MT7531_SGMII_LINK_STATUS BIT(18)
-#define MT7531_SGMII_AN_ENABLE BIT(12)
-#define MT7531_SGMII_AN_RESTART BIT(9)
-#define MT7531_SGMII_AN_COMPLETE BIT(21)
-
-/* Register for SGMII PCS_SPPED_ABILITY */
-#define MT7531_PCS_SPEED_ABILITY(p) MT7531_SGMII_REG(p, 0x08)
-#define MT7531_SGMII_TX_CONFIG_MASK GENMASK(15, 0)
-#define MT7531_SGMII_TX_CONFIG BIT(0)
-
-/* Register for SGMII_MODE */
-#define MT7531_SGMII_MODE(p) MT7531_SGMII_REG(p, 0x20)
-#define MT7531_SGMII_REMOTE_FAULT_DIS BIT(8)
-#define MT7531_SGMII_IF_MODE_MASK GENMASK(5, 1)
-#define MT7531_SGMII_FORCE_DUPLEX BIT(4)
-#define MT7531_SGMII_FORCE_SPEED_MASK GENMASK(3, 2)
-#define MT7531_SGMII_FORCE_SPEED_1000 BIT(3)
-#define MT7531_SGMII_FORCE_SPEED_100 BIT(2)
-#define MT7531_SGMII_FORCE_SPEED_10 0
-#define MT7531_SGMII_SPEED_DUPLEX_AN BIT(1)
-
-enum mt7531_sgmii_force_duplex {
- MT7531_SGMII_FORCE_FULL_DUPLEX = 0,
- MT7531_SGMII_FORCE_HALF_DUPLEX = 0x10,
-};
-
-/* Fields of QPHY_PWR_STATE_CTRL */
-#define MT7531_QPHY_PWR_STATE_CTRL(p) MT7531_SGMII_REG(p, 0xe8)
-#define MT7531_SGMII_PHYA_PWD BIT(4)
-
-/* Values of SGMII SPEED */
-#define MT7531_PHYA_CTRL_SIGNAL3(p) MT7531_SGMII_REG(p, 0x128)
-#define MT7531_RG_TPHY_SPEED_MASK (BIT(2) | BIT(3))
-#define MT7531_RG_TPHY_SPEED_1_25G 0x0
-#define MT7531_RG_TPHY_SPEED_3_125G BIT(2)
+#define MT7531_SGMII_REG_BASE(p) (0x5000 + ((p) - 5) * 0x1000)
+#define MT7531_PHYA_CTRL_SIGNAL3 0x128
/* Register for system reset */
#define MT7530_SYS_CTRL 0x7000
@@ -703,13 +664,13 @@ struct mt7530_fdb {
* @pm: The matrix used to show all connections with the port.
* @pvid: The VLAN specified is to be considered a PVID at ingress. Any
* untagged frames will be assigned to the related VLAN.
- * @vlan_filtering: The flags indicating whether the port that can recognize
- * VLAN-tagged frames.
+ * @sgmii_pcs: Pointer to PCS instance for SerDes ports
*/
struct mt7530_port {
bool enable;
u32 pm;
u16 pvid;
+ struct phylink_pcs *sgmii_pcs;
};
/* Port 5 interface select definitions */

View File

@ -19,7 +19,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -17954,6 +17954,11 @@ L: netdev@vger.kernel.org
@@ -17962,6 +17962,11 @@ L: netdev@vger.kernel.org
S: Maintained
F: drivers/net/ethernet/dlink/sundance.c

View File

@ -57,7 +57,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -12354,6 +12354,14 @@ S: Supported
@@ -12362,6 +12362,14 @@ S: Supported
F: Documentation/devicetree/bindings/mtd/atmel-nand.txt
F: drivers/mtd/nand/raw/atmel/*

View File

@ -125,7 +125,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
#include <linux/mutex.h>
#include <linux/err.h>
#include <linux/property.h>
@@ -3341,3 +3342,5 @@ static int __init regmap_initcall(void)
@@ -3358,3 +3359,5 @@ static int __init regmap_initcall(void)
return 0;
}
postcore_initcall(regmap_initcall);

View File

@ -0,0 +1,40 @@
--- a/drivers/net/pcs/pcs-mtk-lynxi.c
+++ b/drivers/net/pcs/pcs-mtk-lynxi.c
@@ -92,14 +92,23 @@ static void mtk_pcs_lynxi_get_state(stru
struct phylink_link_state *state)
{
struct mtk_pcs_lynxi *mpcs = pcs_to_mtk_pcs_lynxi(pcs);
- unsigned int bm, adv;
+ unsigned int bm, bmsr, adv;
/* Read the BMSR and LPA */
regmap_read(mpcs->regmap, SGMSYS_PCS_CONTROL_1, &bm);
- regmap_read(mpcs->regmap, SGMSYS_PCS_ADVERTISE, &adv);
+ bmsr = FIELD_GET(SGMII_BMSR, bm);
+
+ if (state->interface == PHY_INTERFACE_MODE_2500BASEX) {
+ state->link = !!(bmsr & BMSR_LSTATUS);
+ state->an_complete = !!(bmsr & BMSR_ANEGCOMPLETE);
+ state->speed = SPEED_2500;
+ state->duplex = DUPLEX_FULL;
- phylink_mii_c22_pcs_decode_state(state, FIELD_GET(SGMII_BMSR, bm),
- FIELD_GET(SGMII_LPA, adv));
+ return;
+ }
+
+ regmap_read(mpcs->regmap, SGMSYS_PCS_ADVERTISE, &adv);
+ phylink_mii_c22_pcs_decode_state(state, bmsr, FIELD_GET(SGMII_LPA, adv));
}
static int mtk_pcs_lynxi_config(struct phylink_pcs *pcs, unsigned int mode,
@@ -134,7 +143,8 @@ static int mtk_pcs_lynxi_config(struct p
/* 1000base-X or 2500base-X autoneg */
sgm_mode = SGMII_REMOTE_FAULT_DIS;
use_an = linkmode_test_bit(ETHTOOL_LINK_MODE_Autoneg_BIT,
- advertising);
+ advertising) &&
+ !(interface == PHY_INTERFACE_MODE_2500BASEX);
} else {
/* 1000base-X or 2500base-X without autoneg */
sgm_mode = 0;

View File

@ -0,0 +1,150 @@
--- a/include/linux/phylink.h
+++ b/include/linux/phylink.h
@@ -584,10 +584,37 @@ int phylink_speed_up(struct phylink *pl)
#define phylink_test(bm, mode) __phylink_do_bit(test_bit, bm, mode)
void phylink_set_port_modes(unsigned long *bits);
+
+/**
+ * phylink_get_link_timer_ns - return the PCS link timer value
+ * @interface: link &typedef phy_interface_t mode
+ *
+ * Return the PCS link timer setting in nanoseconds for the PHY @interface
+ * mode, or -EINVAL if not appropriate.
+ */
+static inline int phylink_get_link_timer_ns(phy_interface_t interface)
+{
+ switch (interface) {
+ case PHY_INTERFACE_MODE_SGMII:
+ return 1600000;
+
+ case PHY_INTERFACE_MODE_1000BASEX:
+ case PHY_INTERFACE_MODE_2500BASEX:
+ return 10000000;
+
+ default:
+ return -EINVAL;
+ }
+}
+
void phylink_helper_basex_speed(struct phylink_link_state *state);
+void phylink_mii_c22_pcs_decode_state(struct phylink_link_state *state,
+ u16 bmsr, u16 lpa);
void phylink_mii_c22_pcs_get_state(struct mdio_device *pcs,
struct phylink_link_state *state);
+int phylink_mii_c22_pcs_encode_advertisement(phy_interface_t interface,
+ const unsigned long *advertising);
int phylink_mii_c22_pcs_set_advertisement(struct mdio_device *pcs,
phy_interface_t interface,
const unsigned long *advertising);
--- a/drivers/net/phy/phylink.c
+++ b/drivers/net/phy/phylink.c
@@ -885,7 +885,6 @@ static int phylink_change_inband_advert(
return 0;
}
-
static void phylink_mac_pcs_get_state(struct phylink *pl,
struct phylink_link_state *state)
{
@@ -2966,6 +2965,52 @@ void phylink_mii_c22_pcs_get_state(struc
EXPORT_SYMBOL_GPL(phylink_mii_c22_pcs_get_state);
/**
+ * phylink_mii_c22_pcs_decode_state() - Decode MAC PCS state from MII registers
+ * @state: a pointer to a &struct phylink_link_state.
+ * @bmsr: The value of the %MII_BMSR register
+ * @lpa: The value of the %MII_LPA register
+ *
+ * Helper for MAC PCS supporting the 802.3 clause 22 register set for
+ * clause 37 negotiation and/or SGMII control.
+ *
+ * Parse the Clause 37 or Cisco SGMII link partner negotiation word into
+ * the phylink @state structure. This is suitable to be used for implementing
+ * the mac_pcs_get_state() member of the struct phylink_mac_ops structure if
+ * accessing @bmsr and @lpa cannot be done with MDIO directly.
+ */
+void phylink_mii_c22_pcs_decode_state(struct phylink_link_state *state,
+ u16 bmsr, u16 lpa)
+{
+ state->link = !!(bmsr & BMSR_LSTATUS);
+ state->an_complete = !!(bmsr & BMSR_ANEGCOMPLETE);
+ /* If there is no link or autonegotiation is disabled, the LP advertisement
+ * data is not meaningful, so don't go any further.
+ */
+ if (!state->link || !state->an_enabled)
+ return;
+
+ switch (state->interface) {
+ case PHY_INTERFACE_MODE_1000BASEX:
+ phylink_decode_c37_word(state, lpa, SPEED_1000);
+ break;
+
+ case PHY_INTERFACE_MODE_2500BASEX:
+ phylink_decode_c37_word(state, lpa, SPEED_2500);
+ break;
+
+ case PHY_INTERFACE_MODE_SGMII:
+ case PHY_INTERFACE_MODE_QSGMII:
+ phylink_decode_sgmii_word(state, lpa);
+ break;
+
+ default:
+ state->link = false;
+ break;
+ }
+}
+EXPORT_SYMBOL_GPL(phylink_mii_c22_pcs_decode_state);
+
+/**
* phylink_mii_c22_pcs_set_advertisement() - configure the clause 37 PCS
* advertisement
* @pcs: a pointer to a &struct mdio_device.
@@ -3037,6 +3082,46 @@ int phylink_mii_c22_pcs_set_advertisemen
EXPORT_SYMBOL_GPL(phylink_mii_c22_pcs_set_advertisement);
/**
+ * phylink_mii_c22_pcs_encode_advertisement() - configure the clause 37 PCS
+ * advertisement
+ * @interface: the PHY interface mode being configured
+ * @advertising: the ethtool advertisement mask
+ *
+ * Helper for MAC PCS supporting the 802.3 clause 22 register set for
+ * clause 37 negotiation and/or SGMII control.
+ *
+ * Encode the clause 37 PCS advertisement as specified by @interface and
+ * @advertising.
+ *
+ * Return: The new value for @adv, or ``-EINVAL`` if it should not be changed.
+ */
+int phylink_mii_c22_pcs_encode_advertisement(phy_interface_t interface,
+ const unsigned long *advertising)
+{
+ u16 adv;
+
+ switch (interface) {
+ case PHY_INTERFACE_MODE_1000BASEX:
+ case PHY_INTERFACE_MODE_2500BASEX:
+ adv = ADVERTISE_1000XFULL;
+ if (linkmode_test_bit(ETHTOOL_LINK_MODE_Pause_BIT,
+ advertising))
+ adv |= ADVERTISE_1000XPAUSE;
+ if (linkmode_test_bit(ETHTOOL_LINK_MODE_Asym_Pause_BIT,
+ advertising))
+ adv |= ADVERTISE_1000XPSE_ASYM;
+ return adv;
+ case PHY_INTERFACE_MODE_SGMII:
+ case PHY_INTERFACE_MODE_QSGMII:
+ return 0x0001;
+ default:
+ /* Nothing to do for other modes */
+ return -EINVAL;
+ }
+}
+EXPORT_SYMBOL_GPL(phylink_mii_c22_pcs_encode_advertisement);
+
+/**
* phylink_mii_c22_pcs_config() - configure clause 22 PCS
* @pcs: a pointer to a &struct mdio_device.
* @mode: link autonegotiation mode

View File

@ -10,7 +10,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -2972,8 +2972,8 @@ static irqreturn_t mtk_handle_irq_rx(int
@@ -2994,8 +2994,8 @@ static irqreturn_t mtk_handle_irq_rx(int
eth->rx_events++;
if (likely(napi_schedule_prep(&eth->rx_napi))) {
@ -20,7 +20,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
}
return IRQ_HANDLED;
@@ -2985,8 +2985,8 @@ static irqreturn_t mtk_handle_irq_tx(int
@@ -3007,8 +3007,8 @@ static irqreturn_t mtk_handle_irq_tx(int
eth->tx_events++;
if (likely(napi_schedule_prep(&eth->tx_napi))) {
@ -30,7 +30,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
}
return IRQ_HANDLED;
@@ -4617,6 +4617,8 @@ static int mtk_probe(struct platform_dev
@@ -4675,6 +4675,8 @@ static int mtk_probe(struct platform_dev
* for NAPI to work
*/
init_dummy_netdev(&eth->dummy_dev);

View File

@ -15,7 +15,7 @@ Signed-off-by: Alexander Couzens <lynxis@fe80.eu>
--- a/drivers/net/dsa/mt7530.c
+++ b/drivers/net/dsa/mt7530.c
@@ -2341,6 +2341,10 @@ mt7531_setup(struct dsa_switch *ds)
@@ -2342,6 +2342,10 @@ mt7531_setup(struct dsa_switch *ds)
return -ENODEV;
}

View File

@ -1,46 +0,0 @@
From cbfed00575d15eafd85efd9619b7ecc0836a4aa7 Mon Sep 17 00:00:00 2001
From: Alexander Couzens <lynxis@fe80.eu>
Date: Sat, 13 Aug 2022 14:42:12 +0200
Subject: [PATCH 04/10] net: mtk_sgmii: implement mtk_pcs_ops
Implement mtk_pcs_ops for the SGMII pcs to read the current state
of the hardware.
Signed-off-by: Alexander Couzens <lynxis@fe80.eu>
[added DUPLEX_FULL]
Signed-off-by: Daniel Golle <daniel@makrotopia.org>
---
drivers/net/ethernet/mediatek/mtk_sgmii.c | 15 +++++++++++++++
1 file changed, 15 insertions(+)
--- a/drivers/net/ethernet/mediatek/mtk_sgmii.c
+++ b/drivers/net/ethernet/mediatek/mtk_sgmii.c
@@ -139,10 +139,28 @@ static void mtk_pcs_link_up(struct phyli
regmap_write(mpcs->regmap, SGMSYS_SGMII_MODE, val);
}
+static void mtk_pcs_get_state(struct phylink_pcs *pcs, struct phylink_link_state *state)
+{
+ struct mtk_pcs *mpcs = pcs_to_mtk_pcs(pcs);
+ unsigned int val;
+
+ regmap_read(mpcs->regmap, SGMSYS_PCS_CONTROL_1, &val);
+ state->an_complete = !!(val & SGMII_AN_COMPLETE);
+ state->link = !!(val & SGMII_LINK_STATYS);
+ if (!state->link)
+ return;
+
+ regmap_read(mpcs->regmap, mpcs->ana_rgc3, &val);
+ state->speed = val & RG_PHY_SPEED_3_125G ? SPEED_2500 : SPEED_1000;
+ state->duplex = DUPLEX_FULL;
+ state->pause = 0;
+}
+
static const struct phylink_pcs_ops mtk_pcs_ops = {
.pcs_config = mtk_pcs_config,
.pcs_an_restart = mtk_pcs_restart_an,
.pcs_link_up = mtk_pcs_link_up,
+ .pcs_get_state = mtk_pcs_get_state,
};
int mtk_sgmii_init(struct mtk_sgmii *ss, struct device_node *r, u32 ana_rgc3)

View File

@ -1,31 +0,0 @@
From e4dca7affb8c03438b63bdb5fddefd6ad2431cfd Mon Sep 17 00:00:00 2001
From: Alexander Couzens <lynxis@fe80.eu>
Date: Mon, 15 Aug 2022 14:59:29 +0200
Subject: [PATCH 07/10] net: mtk_sgmii: mtk_pcs_setup_mode_an: don't rely on
register defaults
Ensure autonegotiation is enabled.
Signed-off-by: Alexander Couzens <lynxis@fe80.eu>
---
drivers/net/ethernet/mediatek/mtk_sgmii.c | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
--- a/drivers/net/ethernet/mediatek/mtk_sgmii.c
+++ b/drivers/net/ethernet/mediatek/mtk_sgmii.c
@@ -32,12 +32,13 @@ static int mtk_pcs_setup_mode_an(struct
regmap_write(mpcs->regmap, SGMSYS_PCS_LINK_TIMER,
SGMII_LINK_TIMER_DEFAULT);
+ /* disable remote fault & enable auto neg */
regmap_read(mpcs->regmap, SGMSYS_SGMII_MODE, &val);
- val |= SGMII_REMOTE_FAULT_DIS;
+ val |= SGMII_REMOTE_FAULT_DIS | SGMII_SPEED_DUPLEX_AN;
regmap_write(mpcs->regmap, SGMSYS_SGMII_MODE, val);
regmap_read(mpcs->regmap, SGMSYS_PCS_CONTROL_1, &val);
- val |= SGMII_AN_RESTART;
+ val |= SGMII_AN_RESTART | SGMII_AN_ENABLE;
regmap_write(mpcs->regmap, SGMSYS_PCS_CONTROL_1, val);

View File

@ -1,41 +0,0 @@
From 952b64575613d26163a5afa5ff8bfdb57840091b Mon Sep 17 00:00:00 2001
From: Alexander Couzens <lynxis@fe80.eu>
Date: Mon, 15 Aug 2022 15:00:14 +0200
Subject: [PATCH 08/10] net: mtk_sgmii: set the speed according to the phy
interface in AN
The non auto-negotioting code path is setting the correct speed for the
interface. Ensure auto-negotiation code path is doing it as well.
Signed-off-by: Alexander Couzens <lynxis@fe80.eu>
---
drivers/net/ethernet/mediatek/mtk_sgmii.c | 11 +++++++++--
1 file changed, 9 insertions(+), 2 deletions(-)
--- a/drivers/net/ethernet/mediatek/mtk_sgmii.c
+++ b/drivers/net/ethernet/mediatek/mtk_sgmii.c
@@ -20,12 +20,14 @@ static struct mtk_pcs *pcs_to_mtk_pcs(st
}
/* For SGMII interface mode */
-static int mtk_pcs_setup_mode_an(struct mtk_pcs *mpcs)
+static int mtk_pcs_setup_mode_an(struct mtk_pcs *mpcs, phy_interface_t interface)
{
unsigned int val;
regmap_read(mpcs->regmap, mpcs->ana_rgc3, &val);
val &= ~RG_PHY_SPEED_MASK;
+ if (interface == PHY_INTERFACE_MODE_2500BASEX)
+ val |= RG_PHY_SPEED_3_125G;
regmap_write(mpcs->regmap, mpcs->ana_rgc3, val);
/* Setup the link timer and QPHY power up inside SGMIISYS */
@@ -94,7 +96,7 @@ static int mtk_pcs_config(struct phylink
if (interface != PHY_INTERFACE_MODE_SGMII)
err = mtk_pcs_setup_mode_force(mpcs, interface);
else if (phylink_autoneg_inband(mode))
- err = mtk_pcs_setup_mode_an(mpcs);
+ err = mtk_pcs_setup_mode_an(mpcs, interface);
/* Release PHYA power down state
* Only removing bit SGMII_PHYA_PWD isn't enough.

View File

@ -1,22 +0,0 @@
From 06773f19cffd6c9d34dcbc8320169afef5ab60ba Mon Sep 17 00:00:00 2001
From: Alexander Couzens <lynxis@fe80.eu>
Date: Mon, 15 Aug 2022 13:58:07 +0200
Subject: [PATCH 09/10] net: mtk_eth_soc: improve comment
Signed-off-by: Alexander Couzens <lynxis@fe80.eu>
---
drivers/net/ethernet/mediatek/mtk_sgmii.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
--- a/drivers/net/ethernet/mediatek/mtk_sgmii.c
+++ b/drivers/net/ethernet/mediatek/mtk_sgmii.c
@@ -67,7 +67,8 @@ static int mtk_pcs_setup_mode_force(stru
val &= ~SGMII_AN_ENABLE;
regmap_write(mpcs->regmap, SGMSYS_PCS_CONTROL_1, val);
- /* Set the speed etc but leave the duplex unchanged */
+ /* Set the speed etc but leave the duplex unchanged.
+ * The SGMII mode for 2.5gbit is the same as for 1gbit, expect the speed in ANA_RGC3 */
regmap_read(mpcs->regmap, SGMSYS_SGMII_MODE, &val);
val &= SGMII_DUPLEX_HALF | ~SGMII_IF_MODE_MASK;
val |= SGMII_SPEED_1000;

View File

@ -53,7 +53,7 @@ v2: fix wrong variable name in return value check spotted by Denis Kirjanov
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -4586,8 +4586,8 @@ static int mtk_probe(struct platform_dev
@@ -4644,8 +4644,8 @@ static int mtk_probe(struct platform_dev
for (i = 0; i < num_ppe; i++) {
u32 ppe_addr = eth->soc->reg_map->ppe_base + i * 0x400;
@ -64,7 +64,7 @@ v2: fix wrong variable name in return value check spotted by Denis Kirjanov
if (!eth->ppe[i]) {
err = -ENOMEM;
goto err_free_dev;
@@ -4712,6 +4712,7 @@ static const struct mtk_soc_data mt7622_
@@ -4772,6 +4772,7 @@ static const struct mtk_soc_data mt7622_
.required_pctl = false,
.offload_version = 2,
.hash_offset = 2,
@ -72,7 +72,7 @@ v2: fix wrong variable name in return value check spotted by Denis Kirjanov
.foe_entry_size = sizeof(struct mtk_foe_entry) - 16,
.txrx = {
.txd_size = sizeof(struct mtk_tx_dma),
@@ -4749,6 +4750,7 @@ static const struct mtk_soc_data mt7629_
@@ -4809,6 +4810,7 @@ static const struct mtk_soc_data mt7629_
.hw_features = MTK_HW_FEATURES,
.required_clks = MT7629_CLKS_BITMAP,
.required_pctl = false,
@ -80,7 +80,7 @@ v2: fix wrong variable name in return value check spotted by Denis Kirjanov
.txrx = {
.txd_size = sizeof(struct mtk_tx_dma),
.rxd_size = sizeof(struct mtk_rx_dma),
@@ -4769,6 +4771,7 @@ static const struct mtk_soc_data mt7986_
@@ -4829,6 +4831,7 @@ static const struct mtk_soc_data mt7981_
.offload_version = 2,
.hash_offset = 4,
.foe_entry_size = sizeof(struct mtk_foe_entry),
@ -90,7 +90,7 @@ v2: fix wrong variable name in return value check spotted by Denis Kirjanov
.rxd_size = sizeof(struct mtk_rx_dma_v2),
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
@@ -1026,6 +1026,8 @@ struct mtk_reg_map {
@@ -1014,6 +1014,8 @@ struct mtk_reg_map {
* the extra setup for those pins used by GMAC.
* @hash_offset Flow table hash offset.
* @foe_entry_size Foe table entry size.
@ -99,7 +99,7 @@ v2: fix wrong variable name in return value check spotted by Denis Kirjanov
* @txd_size Tx DMA descriptor size.
* @rxd_size Rx DMA descriptor size.
* @rx_irq_done_mask Rx irq done register mask.
@@ -1043,6 +1045,7 @@ struct mtk_soc_data {
@@ -1031,6 +1033,7 @@ struct mtk_soc_data {
u8 hash_offset;
u16 foe_entry_size;
netdev_features_t hw_features;

View File

@ -17,7 +17,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -1830,9 +1830,7 @@ static int mtk_poll_rx(struct napi_struc
@@ -1852,9 +1852,7 @@ static int mtk_poll_rx(struct napi_struc
while (done < budget) {
unsigned int pktlen, *rxdcsum;
@ -27,7 +27,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
dma_addr_t dma_addr;
u32 hash, reason;
int mac = 0;
@@ -1967,36 +1965,21 @@ static int mtk_poll_rx(struct napi_struc
@@ -1989,36 +1987,21 @@ static int mtk_poll_rx(struct napi_struc
skb_checksum_none_assert(skb);
skb->protocol = eth_type_trans(skb, netdev);
@ -70,7 +70,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
skb_record_rx_queue(skb, 0);
napi_gro_receive(napi, skb);
@@ -2811,29 +2794,11 @@ static netdev_features_t mtk_fix_feature
@@ -2833,29 +2816,11 @@ static netdev_features_t mtk_fix_feature
static int mtk_set_features(struct net_device *dev, netdev_features_t features)
{
@ -100,7 +100,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
return 0;
}
@@ -3147,30 +3112,6 @@ static int mtk_open(struct net_device *d
@@ -3169,30 +3134,6 @@ static int mtk_open(struct net_device *d
struct mtk_eth *eth = mac->hw;
int i, err;
@ -131,7 +131,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
err = phylink_of_phy_connect(mac->phylink, mac->of_node, 0);
if (err) {
netdev_err(dev, "%s: could not attach PHY: %d\n", __func__,
@@ -3211,6 +3152,35 @@ static int mtk_open(struct net_device *d
@@ -3233,6 +3174,35 @@ static int mtk_open(struct net_device *d
phylink_start(mac->phylink);
netif_tx_start_all_queues(dev);
@ -167,7 +167,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
return 0;
}
@@ -3695,10 +3665,9 @@ static int mtk_hw_init(struct mtk_eth *e
@@ -3717,10 +3687,9 @@ static int mtk_hw_init(struct mtk_eth *e
if (!MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) {
val = mtk_r32(eth, MTK_CDMP_IG_CTRL);
mtk_w32(eth, val | MTK_CDMP_STAG_EN, MTK_CDMP_IG_CTRL);
@ -180,7 +180,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
/* set interrupt delays based on current Net DIM sample */
mtk_dim_rx(&eth->rx_dim.work);
@@ -4336,7 +4305,7 @@ static int mtk_add_mac(struct mtk_eth *e
@@ -4367,7 +4336,7 @@ static int mtk_add_mac(struct mtk_eth *e
eth->netdev[id]->hw_features |= NETIF_F_LRO;
eth->netdev[id]->vlan_features = eth->soc->hw_features &

View File

@ -16,7 +16,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -1403,12 +1403,28 @@ static void mtk_wake_queue(struct mtk_et
@@ -1425,12 +1425,28 @@ static void mtk_wake_queue(struct mtk_et
}
}
@ -45,7 +45,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
bool gso = false;
int tx_num;
@@ -1430,6 +1446,18 @@ static netdev_tx_t mtk_start_xmit(struct
@@ -1452,6 +1468,18 @@ static netdev_tx_t mtk_start_xmit(struct
return NETDEV_TX_BUSY;
}
@ -64,7 +64,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
/* TSO: fill MSS info in tcp checksum field */
if (skb_is_gso(skb)) {
if (skb_cow_head(skb, 0)) {
@@ -1445,8 +1473,14 @@ static netdev_tx_t mtk_start_xmit(struct
@@ -1467,8 +1495,14 @@ static netdev_tx_t mtk_start_xmit(struct
}
}

View File

@ -14,7 +14,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
@@ -1319,6 +1319,9 @@ int mtk_gmac_rgmii_path_setup(struct mtk
@@ -1277,6 +1277,9 @@ int mtk_gmac_rgmii_path_setup(struct mtk
int mtk_eth_offload_init(struct mtk_eth *eth);
int mtk_eth_setup_tc(struct net_device *dev, enum tc_setup_type type,
void *type_data);

View File

@ -0,0 +1,766 @@
// SPDX-License-Identifier: (GPL-2.0 OR MIT)
/*
* Copyright (c) 2020 MediaTek Inc.
* Author: Sam.Shih <sam.shih@mediatek.com>
* Author: Jianhui Zhao <zhaojh329@gmail.com>
*/
#include <dt-bindings/interrupt-controller/irq.h>
#include <dt-bindings/interrupt-controller/arm-gic.h>
#include <dt-bindings/phy/phy.h>
#include <dt-bindings/clock/mediatek,mt7981-clk.h>
#include <dt-bindings/reset/mt7986-resets.h>
#include <dt-bindings/pinctrl/mt65xx.h>
#include <dt-bindings/input/linux-event-codes.h>
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/mux/mux.h>
/ {
compatible = "mediatek,mt7981";
interrupt-parent = <&gic>;
#address-cells = <2>;
#size-cells = <2>;
cpus {
#address-cells = <1>;
#size-cells = <0>;
cpu@0 {
device_type = "cpu";
compatible = "arm,cortex-a53";
enable-method = "psci";
reg = <0x0>;
};
cpu@1 {
device_type = "cpu";
compatible = "arm,cortex-a53";
enable-method = "psci";
reg = <0x1>;
};
};
pwm: pwm@10048000 {
compatible = "mediatek,mt7981-pwm";
reg = <0 0x10048000 0 0x1000>;
#pwm-cells = <2>;
clocks = <&infracfg CLK_INFRA_PWM_STA>,
<&infracfg CLK_INFRA_PWM_HCK>,
<&infracfg CLK_INFRA_PWM1_CK>,
<&infracfg CLK_INFRA_PWM2_CK>,
<&infracfg CLK_INFRA_PWM3_CK>;
clock-names = "top", "main", "pwm1", "pwm2", "pwm3";
};
fan: pwm-fan {
compatible = "pwm-fan";
/* cooling level (0, 1, 2, 3) : (0% duty, 50% duty, 75% duty, 100% duty) */
cooling-levels = <0 128 192 255>;
#cooling-cells = <2>;
status = "disabled";
};
thermal-zones {
cpu_thermal: cpu-thermal {
polling-delay-passive = <1000>;
polling-delay = <1000>;
thermal-sensors = <&thermal 0>;
trips {
cpu_trip_crit: crit {
temperature = <125000>;
hysteresis = <2000>;
type = "critical";
};
cpu_trip_hot: hot {
temperature = <120000>;
hysteresis = <2000>;
type = "hot";
};
cpu_trip_active_high: active-high {
temperature = <115000>;
hysteresis = <2000>;
type = "active";
};
cpu_trip_active_med: active-med {
temperature = <85000>;
hysteresis = <2000>;
type = "active";
};
cpu_trip_active_low: active-low {
temperature = <60000>;
hysteresis = <2000>;
type = "active";
};
};
cooling-maps {
cpu-active-high {
/* active: set fan to cooling level 3 */
cooling-device = <&fan 3 3>;
trip = <&cpu_trip_active_high>;
};
cpu-active-med {
/* active: set fan to cooling level 2 */
cooling-device = <&fan 2 2>;
trip = <&cpu_trip_active_med>;
};
cpu-active-low {
/* passive: set fan to cooling level 1 */
cooling-device = <&fan 1 1>;
trip = <&cpu_trip_active_low>;
};
};
};
};
thermal: thermal@1100c800 {
#thermal-sensor-cells = <1>;
compatible = "mediatek,mt7981-thermal", "mediatek,mt7986-thermal";
reg = <0 0x1100c800 0 0x800>;
interrupts = <GIC_SPI 138 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&infracfg CLK_INFRA_THERM_CK>,
<&infracfg CLK_INFRA_ADC_26M_CK>;
clock-names = "therm", "auxadc";
mediatek,auxadc = <&auxadc>;
mediatek,apmixedsys = <&apmixedsys>;
nvmem-cells = <&thermal_calibration>;
nvmem-cell-names = "calibration-data";
};
auxadc: adc@1100d000 {
compatible = "mediatek,mt7981-auxadc",
"mediatek,mt7986-auxadc",
"mediatek,mt7622-auxadc";
reg = <0 0x1100d000 0 0x1000>;
clocks = <&infracfg CLK_INFRA_ADC_26M_CK>,
<&infracfg CLK_INFRA_ADC_FRC_CK>;
clock-names = "main", "32k";
#io-channel-cells = <1>;
};
wdma: wdma@15104800 {
compatible = "mediatek,wed-wdma";
reg = <0 0x15104800 0 0x400>,
<0 0x15104c00 0 0x400>;
};
ap2woccif: ap2woccif@151a5000 {
compatible = "mediatek,ap2woccif";
reg = <0 0x151a5000 0 0x1000>,
<0 0x151ad000 0 0x1000>;
interrupt-parent = <&gic>;
interrupts = <GIC_SPI 211 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 212 IRQ_TYPE_LEVEL_HIGH>;
};
reserved-memory {
#address-cells = <2>;
#size-cells = <2>;
ranges;
/* 192 KiB reserved for ARM Trusted Firmware (BL31) */
secmon_reserved: secmon@43000000 {
reg = <0 0x43000000 0 0x30000>;
no-map;
};
wmcpu_emi: wmcpu-reserved@47c80000 {
reg = <0 0x47c80000 0 0x100000>;
no-map;
};
wo_emi0: wo-emi@47d80000 {
reg = <0 0x47d80000 0 0x40000>;
no-map;
};
wo_data: wo-data@47dc0000 {
reg = <0 0x47dc0000 0 0x240000>;
no-map;
};
wo_ilm0: wo-ilm@151e0000 {
reg = <0 0x151e0000 0 0x8000>;
no-map;
};
wo_dlm0: wo-dlm@151e8000 {
reg = <0 0x151e8000 0 0x2000>;
no-map;
};
wo_boot: wo-boot@15194000 {
reg = <0 0x15194000 0 0x1000>;
no-map;
};
};
psci {
compatible = "arm,psci-0.2";
method = "smc";
};
trng {
compatible = "mediatek,mt7981-rng";
};
clk40m: oscillator@0 {
compatible = "fixed-clock";
#clock-cells = <0>;
clock-frequency = <40000000>;
clock-output-names = "clkxtal";
};
infracfg: infracfg@10001000 {
compatible = "mediatek,mt7981-infracfg", "syscon";
reg = <0 0x10001000 0 0x1000>;
#clock-cells = <1>;
};
topckgen: topckgen@1001B000 {
compatible = "mediatek,mt7981-topckgen", "syscon";
reg = <0 0x1001B000 0 0x1000>;
#clock-cells = <1>;
};
apmixedsys: apmixedsys@1001E000 {
compatible = "mediatek,mt7981-apmixedsys", "mediatek,mt7986-apmixedsys", "syscon";
reg = <0 0x1001E000 0 0x1000>;
#clock-cells = <1>;
};
timer {
compatible = "arm,armv8-timer";
interrupt-parent = <&gic>;
clock-frequency = <13000000>;
interrupts = <GIC_PPI 13 IRQ_TYPE_LEVEL_LOW>,
<GIC_PPI 14 IRQ_TYPE_LEVEL_LOW>,
<GIC_PPI 11 IRQ_TYPE_LEVEL_LOW>,
<GIC_PPI 10 IRQ_TYPE_LEVEL_LOW>;
};
watchdog: watchdog@1001c000 {
compatible = "mediatek,mt7986-wdt",
"mediatek,mt6589-wdt";
reg = <0 0x1001c000 0 0x1000>;
interrupts = <GIC_SPI 110 IRQ_TYPE_LEVEL_HIGH>;
#reset-cells = <1>;
status = "disabled";
};
gic: interrupt-controller@c000000 {
compatible = "arm,gic-v3";
#interrupt-cells = <3>;
interrupt-parent = <&gic>;
interrupt-controller;
reg = <0 0x0c000000 0 0x40000>, /* GICD */
<0 0x0c080000 0 0x200000>; /* GICR */
interrupts = <GIC_PPI 9 IRQ_TYPE_LEVEL_HIGH>;
};
uart0: serial@11002000 {
compatible = "mediatek,mt6577-uart";
reg = <0 0x11002000 0 0x400>;
interrupts = <GIC_SPI 123 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&infracfg CLK_INFRA_UART0_SEL>,
<&infracfg CLK_INFRA_UART0_CK>;
clock-names = "baud", "bus";
assigned-clocks = <&topckgen CLK_TOP_UART_SEL>,
<&infracfg CLK_INFRA_UART0_SEL>;
assigned-clock-parents = <&topckgen CLK_TOP_CB_CKSQ_40M>,
<&topckgen CLK_TOP_UART_SEL>;
pinctrl-0 = <&uart0_pins>;
pinctrl-names = "default";
status = "disabled";
};
uart1: serial@11003000 {
compatible = "mediatek,mt6577-uart";
reg = <0 0x11003000 0 0x400>;
interrupts = <GIC_SPI 124 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&infracfg CLK_INFRA_UART1_SEL>,
<&infracfg CLK_INFRA_UART1_CK>;
clock-names = "baud", "bus";
assigned-clocks = <&topckgen CLK_TOP_UART_SEL>,
<&infracfg CLK_INFRA_UART1_SEL>;
assigned-clock-parents = <&topckgen CLK_TOP_CB_CKSQ_40M>,
<&topckgen CLK_TOP_UART_SEL>;
status = "disabled";
};
uart2: serial@11004000 {
compatible = "mediatek,mt6577-uart";
reg = <0 0x11004000 0 0x400>;
interrupts = <GIC_SPI 125 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&infracfg CLK_INFRA_UART2_SEL>,
<&infracfg CLK_INFRA_UART2_CK>;
clock-names = "baud", "bus";
assigned-clocks = <&topckgen CLK_TOP_UART_SEL>,
<&infracfg CLK_INFRA_UART2_SEL>;
assigned-clock-parents = <&topckgen CLK_TOP_CB_CKSQ_40M>,
<&topckgen CLK_TOP_UART_SEL>;
status = "disabled";
};
i2c0: i2c@11007000 {
compatible = "mediatek,mt7981-i2c";
reg = <0 0x11007000 0 0x1000>,
<0 0x10217080 0 0x80>;
interrupts = <GIC_SPI 136 IRQ_TYPE_LEVEL_HIGH>;
clock-div = <1>;
clocks = <&infracfg CLK_INFRA_I2C0_CK>,
<&infracfg CLK_INFRA_AP_DMA_CK>;
clock-names = "main", "dma";
#address-cells = <1>;
#size-cells = <0>;
status = "disabled";
};
pcie: pcie@11280000 {
compatible = "mediatek,mt7981-pcie",
"mediatek,mt7986-pcie";
device_type = "pci";
reg = <0 0x11280000 0 0x4000>;
reg-names = "pcie-mac";
#address-cells = <3>;
#size-cells = <2>;
interrupts = <GIC_SPI 168 IRQ_TYPE_LEVEL_HIGH>;
bus-range = <0x00 0xff>;
ranges = <0x82000000 0 0x20000000
0x0 0x20000000 0 0x10000000>;
status = "disabled";
clocks = <&infracfg CLK_INFRA_IPCIE_CK>,
<&infracfg CLK_INFRA_IPCIE_PIPE_CK>,
<&infracfg CLK_INFRA_IPCIER_CK>,
<&infracfg CLK_INFRA_IPCIEB_CK>;
phys = <&u3port0 PHY_TYPE_PCIE>;
phy-names = "pcie-phy";
#interrupt-cells = <1>;
interrupt-map-mask = <0 0 0 7>;
interrupt-map = <0 0 0 1 &pcie_intc 0>,
<0 0 0 2 &pcie_intc 1>,
<0 0 0 3 &pcie_intc 2>,
<0 0 0 4 &pcie_intc 3>;
pcie_intc: interrupt-controller {
interrupt-controller;
#address-cells = <0>;
#interrupt-cells = <1>;
};
};
crypto: crypto@10320000 {
compatible = "inside-secure,safexcel-eip97";
reg = <0 0x10320000 0 0x40000>;
interrupts = <GIC_SPI 116 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 117 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 118 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 119 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "ring0", "ring1", "ring2", "ring3";
clocks = <&topckgen CLK_TOP_EIP97B>;
clock-names = "top_eip97_ck";
assigned-clocks = <&topckgen CLK_TOP_EIP97B_SEL>;
assigned-clock-parents = <&topckgen CLK_TOP_CB_NET1_D5>;
};
pio: pinctrl@11d00000 {
compatible = "mediatek,mt7981-pinctrl";
reg = <0 0x11d00000 0 0x1000>,
<0 0x11c00000 0 0x1000>,
<0 0x11c10000 0 0x1000>,
<0 0x11d20000 0 0x1000>,
<0 0x11e00000 0 0x1000>,
<0 0x11e20000 0 0x1000>,
<0 0x11f00000 0 0x1000>,
<0 0x11f10000 0 0x1000>,
<0 0x1000b000 0 0x1000>;
reg-names = "gpio", "iocfg_rt", "iocfg_rm",
"iocfg_rb", "iocfg_lb", "iocfg_bl",
"iocfg_tm", "iocfg_tl", "eint";
gpio-controller;
#gpio-cells = <2>;
gpio-ranges = <&pio 0 0 56>;
interrupt-controller;
interrupts = <GIC_SPI 225 IRQ_TYPE_LEVEL_HIGH>;
interrupt-parent = <&gic>;
#interrupt-cells = <2>;
mdio_pins: mdc-mdio-pins {
mux {
function = "eth";
groups = "smi_mdc_mdio";
};
};
uart0_pins: uart0-pins {
mux {
function = "uart";
groups = "uart0";
};
};
wifi_dbdc_pins: wifi-dbdc-pins {
mux {
function = "eth";
groups = "wf0_mode1";
};
conf {
pins = "WF_HB1", "WF_HB2", "WF_HB3", "WF_HB4",
"WF_HB0", "WF_HB0_B", "WF_HB5", "WF_HB6",
"WF_HB7", "WF_HB8", "WF_HB9", "WF_HB10",
"WF_TOP_CLK", "WF_TOP_DATA", "WF_XO_REQ",
"WF_CBA_RESETB", "WF_DIG_RESETB";
drive-strength = <4>;
};
};
};
ethsys: syscon@15000000 {
#address-cells = <1>;
#size-cells = <1>;
compatible = "mediatek,mt7981-ethsys",
"mediatek,mt7986-ethsys",
"syscon";
reg = <0 0x15000000 0 0x1000>;
#clock-cells = <1>;
#reset-cells = <1>;
};
wed: wed@15010000 {
compatible = "mediatek,mt7981-wed",
"mediatek,mt7986-wed",
"syscon";
reg = <0 0x15010000 0 0x1000>;
interrupt-parent = <&gic>;
interrupts = <GIC_SPI 205 IRQ_TYPE_LEVEL_HIGH>;
memory-region = <&wo_emi0>, <&wo_ilm0>, <&wo_dlm0>,
<&wo_data>, <&wo_boot>;
memory-region-names = "wo-emi", "wo-ilm", "wo-dlm",
"wo-data", "wo-boot";
mediatek,wo-ccif = <&wo_ccif0>;
};
eth: ethernet@15100000 {
compatible = "mediatek,mt7981-eth";
reg = <0 0x15100000 0 0x80000>;
interrupts = <GIC_SPI 196 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 197 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 198 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 199 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&ethsys CLK_ETH_FE_EN>,
<&ethsys CLK_ETH_GP2_EN>,
<&ethsys CLK_ETH_GP1_EN>,
<&ethsys CLK_ETH_WOCPU0_EN>,
<&sgmiisys0 CLK_SGM0_TX_EN>,
<&sgmiisys0 CLK_SGM0_RX_EN>,
<&sgmiisys0 CLK_SGM0_CK0_EN>,
<&sgmiisys0 CLK_SGM0_CDR_CK0_EN>,
<&sgmiisys1 CLK_SGM1_TX_EN>,
<&sgmiisys1 CLK_SGM1_RX_EN>,
<&sgmiisys1 CLK_SGM1_CK1_EN>,
<&sgmiisys1 CLK_SGM1_CDR_CK1_EN>,
<&topckgen CLK_TOP_SGM_REG>,
<&topckgen CLK_TOP_NETSYS_SEL>,
<&topckgen CLK_TOP_NETSYS_500M_SEL>;
clock-names = "fe", "gp2", "gp1", "wocpu0",
"sgmii_tx250m", "sgmii_rx250m",
"sgmii_cdr_ref", "sgmii_cdr_fb",
"sgmii2_tx250m", "sgmii2_rx250m",
"sgmii2_cdr_ref", "sgmii2_cdr_fb",
"sgmii_ck", "netsys0", "netsys1";
assigned-clocks = <&topckgen CLK_TOP_NETSYS_2X_SEL>,
<&topckgen CLK_TOP_SGM_325M_SEL>;
assigned-clock-parents = <&topckgen CLK_TOP_CB_NET2_800M>,
<&topckgen CLK_TOP_CB_SGM_325M>;
mediatek,ethsys = <&ethsys>;
mediatek,sgmiisys = <&sgmiisys0>, <&sgmiisys1>;
mediatek,infracfg = <&topmisc>;
mediatek,wed = <&wed>;
#reset-cells = <1>;
#address-cells = <1>;
#size-cells = <0>;
status = "disabled";
mdio_bus: mdio-bus {
#address-cells = <1>;
#size-cells = <0>;
int_gbe_phy: ethernet-phy@0 {
reg = <0>;
compatible = "ethernet-phy-ieee802.3-c22";
phy-mode = "gmii";
phy-is-integrated;
nvmem-cells = <&phy_calibration>;
nvmem-cell-names = "phy-cal-data";
};
};
};
wo_ccif0: syscon@151a5000 {
compatible = "mediatek,mt7986-wo-ccif", "syscon";
reg = <0 0x151a5000 0 0x1000>;
interrupt-parent = <&gic>;
interrupts = <GIC_SPI 211 IRQ_TYPE_LEVEL_HIGH>;
};
sgmiisys0: syscon@10060000 {
compatible = "mediatek,mt7981-sgmiisys_0", "mediatek,mt7986-sgmiisys_0", "syscon";
reg = <0 0x10060000 0 0x1000>;
mediatek,pnswap;
#clock-cells = <1>;
};
sgmiisys1: syscon@10070000 {
compatible = "mediatek,mt7981-sgmiisys_1", "mediatek,mt7986-sgmiisys_1", "syscon";
reg = <0 0x10070000 0 0x1000>;
#clock-cells = <1>;
};
topmisc: topmisc@11d10000 {
compatible = "mediatek,mt7981-topmisc", "syscon";
reg = <0 0x11d10000 0 0x10000>;
#clock-cells = <1>;
};
snand: snfi@11005000 {
compatible = "mediatek,mt7986-snand";
reg = <0 0x11005000 0 0x1000>, <0 0x11006000 0 0x1000>;
reg-names = "nfi", "ecc";
interrupts = <GIC_SPI 121 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&infracfg CLK_INFRA_SPINFI1_CK>,
<&infracfg CLK_INFRA_NFI1_CK>,
<&infracfg CLK_INFRA_NFI_HCK_CK>;
clock-names = "pad_clk", "nfi_clk", "nfi_hclk";
assigned-clocks = <&topckgen CLK_TOP_SPINFI_SEL>,
<&topckgen CLK_TOP_NFI1X_SEL>;
assigned-clock-parents = <&topckgen CLK_TOP_CB_M_D8>,
<&topckgen CLK_TOP_CB_M_D8>;
#address-cells = <1>;
#size-cells = <0>;
status = "disabled";
};
mmc0: mmc@11230000 {
compatible = "mediatek,mt7986-mmc",
"mediatek,mt7981-mmc";
reg = <0 0x11230000 0 0x1000>, <0 0x11c20000 0 0x1000>;
interrupts = <GIC_SPI 143 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&topckgen CLK_TOP_EMMC_208M>,
<&topckgen CLK_TOP_EMMC_400M>,
<&infracfg CLK_INFRA_MSDC_CK>;
assigned-clocks = <&topckgen CLK_TOP_EMMC_208M_SEL>,
<&topckgen CLK_TOP_EMMC_400M_SEL>;
assigned-clock-parents = <&topckgen CLK_TOP_CB_M_D2>,
<&topckgen CLK_TOP_CB_NET2_D2>;
clock-names = "source", "hclk", "source_cg";
status = "disabled";
};
wed_pcie: wed_pcie@10003000 {
compatible = "mediatek,wed_pcie";
reg = <0 0x10003000 0 0x10>;
};
spi0: spi@1100a000 {
compatible = "mediatek,mt7986-spi-ipm", "mediatek,spi-ipm";
#address-cells = <1>;
#size-cells = <0>;
reg = <0 0x1100a000 0 0x100>;
interrupts = <GIC_SPI 140 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&topckgen CLK_TOP_CB_M_D2>,
<&topckgen CLK_TOP_SPI_SEL>,
<&infracfg CLK_INFRA_SPI0_CK>,
<&infracfg CLK_INFRA_SPI0_HCK_CK>;
clock-names = "parent-clk", "sel-clk", "spi-clk", "hclk";
status = "disabled";
};
spi1: spi@1100b000 {
compatible = "mediatek,mt7986-spi-ipm", "mediatek,spi-ipm";
#address-cells = <1>;
#size-cells = <0>;
reg = <0 0x1100b000 0 0x100>;
interrupts = <GIC_SPI 141 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&topckgen CLK_TOP_CB_M_D2>,
<&topckgen CLK_TOP_SPIM_MST_SEL>,
<&infracfg CLK_INFRA_SPI1_CK>,
<&infracfg CLK_INFRA_SPI1_HCK_CK>;
clock-names = "parent-clk", "sel-clk", "spi-clk", "hclk";
status = "disabled";
};
spi2: spi@11009000 {
compatible = "mediatek,mt7986-spi-ipm", "mediatek,spi-ipm";
#address-cells = <1>;
#size-cells = <0>;
reg = <0 0x11009000 0 0x100>;
interrupts = <GIC_SPI 142 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&topckgen CLK_TOP_CB_M_D2>,
<&topckgen CLK_TOP_SPI_SEL>,
<&infracfg CLK_INFRA_SPI2_CK>,
<&infracfg CLK_INFRA_SPI2_HCK_CK>;
clock-names = "parent-clk", "sel-clk", "spi-clk", "hclk";
status = "disabled";
};
consys: consys@10000000 {
compatible = "mediatek,mt7981-consys";
reg = <0 0x10000000 0 0x8600000>;
memory-region = <&wmcpu_emi>;
};
xhci: usb@11200000 {
compatible = "mediatek,mt7986-xhci",
"mediatek,mtk-xhci";
reg = <0 0x11200000 0 0x2e00>,
<0 0x11203e00 0 0x0100>;
reg-names = "mac", "ippc";
interrupts = <GIC_SPI 173 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&infracfg CLK_INFRA_IUSB_SYS_CK>,
<&infracfg CLK_INFRA_IUSB_CK>,
<&infracfg CLK_INFRA_IUSB_133_CK>,
<&infracfg CLK_INFRA_IUSB_66M_CK>,
<&topckgen CLK_TOP_U2U3_XHCI_SEL>;
clock-names = "sys_ck",
"ref_ck",
"mcu_ck",
"dma_ck",
"xhci_ck";
phys = <&u2port0 PHY_TYPE_USB2>,
<&u3port0 PHY_TYPE_USB3>;
vusb33-supply = <&reg_3p3v>;
mediatek,u3p-dis-msk = <0x01>;
status = "disabled";
};
usb_phy: usb-phy@11e10000 {
compatible = "mediatek,mt7981",
"mediatek,generic-tphy-v2";
#address-cells = <1>;
#size-cells = <1>;
ranges = <0 0 0x11e10000 0x1700>;
status = "disabled";
u2port0: usb-phy@0 {
reg = <0x0 0x700>;
clocks = <&topckgen CLK_TOP_USB_FRMCNT_SEL>;
clock-names = "ref";
#phy-cells = <1>;
};
u3port0: usb-phy@700 {
reg = <0x700 0x900>;
clocks = <&topckgen CLK_TOP_USB3_PHY_SEL>;
clock-names = "ref";
#phy-cells = <1>;
mediatek,syscon-type = <&topmisc 0x218 0>;
status = "okay";
};
};
reg_3p3v: regulator-3p3v {
compatible = "regulator-fixed";
regulator-name = "fixed-3.3V";
regulator-min-microvolt = <3300000>;
regulator-max-microvolt = <3300000>;
regulator-boot-on;
regulator-always-on;
};
efuse: efuse@11f20000 {
compatible = "mediatek,mt7981-efuse",
"mediatek,efuse";
reg = <0 0x11f20000 0 0x1000>;
#address-cells = <1>;
#size-cells = <1>;
status = "okay";
thermal_calibration: thermal-calib@274 {
reg = <0x274 0xc>;
};
phy_calibration: phy-calib@8dc {
reg = <0x8dc 0x10>;
};
comb_rx_imp_p0: usb3-rx-imp@8c8 {
reg = <0x8c8 1>;
bits = <0 5>;
};
comb_tx_imp_p0: usb3-tx-imp@8c8 {
reg = <0x8c8 2>;
bits = <5 5>;
};
comb_intr_p0: usb3-intr@8c9 {
reg = <0x8c9 1>;
bits = <2 6>;
};
};
afe: audio-controller@11210000 {
compatible = "mediatek,mt79xx-audio";
reg = <0 0x11210000 0 0x9000>;
interrupts = <GIC_SPI 106 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&infracfg CLK_INFRA_AUD_BUS_CK>,
<&infracfg CLK_INFRA_AUD_26M_CK>,
<&infracfg CLK_INFRA_AUD_L_CK>,
<&infracfg CLK_INFRA_AUD_AUD_CK>,
<&infracfg CLK_INFRA_AUD_EG2_CK>,
<&topckgen CLK_TOP_AUD_SEL>;
clock-names = "aud_bus_ck",
"aud_26m_ck",
"aud_l_ck",
"aud_aud_ck",
"aud_eg2_ck",
"aud_sel";
assigned-clocks = <&topckgen CLK_TOP_AUD_SEL>,
<&topckgen CLK_TOP_A1SYS_SEL>,
<&topckgen CLK_TOP_AUD_L_SEL>,
<&topckgen CLK_TOP_A_TUNER_SEL>;
assigned-clock-parents = <&topckgen CLK_TOP_CB_APLL2_196M>,
<&topckgen CLK_TOP_APLL2_D4>,
<&topckgen CLK_TOP_CB_APLL2_196M>,
<&topckgen CLK_TOP_APLL2_D4>;
status = "disabled";
};
ice: ice_debug {
compatible = "mediatek,mt7981-ice_debug",
"mediatek,mt2701-ice_debug";
clocks = <&infracfg CLK_INFRA_DBG_CK>;
clock-names = "ice_dbg";
};
wifi: wifi@18000000 {
compatible = "mediatek,mt7981-wmac";
resets = <&watchdog MT7986_TOPRGU_CONSYS_RST>;
reset-names = "consys";
pinctrl-0 = <&wifi_dbdc_pins>;
pinctrl-names = "dbdc";
clocks = <&topckgen CLK_TOP_NETSYS_MCU_SEL>,
<&topckgen CLK_TOP_AP2CNN_HOST_SEL>;
clock-names = "mcu", "ap2conn";
reg = <0 0x18000000 0 0x1000000>,
<0 0x10003000 0 0x1000>,
<0 0x11d10000 0 0x1000>;
interrupts = <GIC_SPI 213 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 214 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 215 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 216 IRQ_TYPE_LEVEL_HIGH>;
memory-region = <&wmcpu_emi>;
status = "disabled";
};
};

View File

@ -0,0 +1,102 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2021 MediaTek Inc.
* Author: Sam Shih <sam.shih@mediatek.com>
* Author: Wenzhen Yu <wenzhen.yu@mediatek.com>
* Author: Jianhui Zhao <zhaojh329@gmail.com>
* Author: Daniel Golle <daniel@makrotopia.org>
*/
#include <linux/clk-provider.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/of_device.h>
#include <linux/platform_device.h>
#include "clk-mtk.h"
#include "clk-gate.h"
#include "clk-mux.h"
#include <dt-bindings/clock/mediatek,mt7981-clk.h>
#include <linux/clk.h>
#define MT7981_PLL_FMAX (2500UL * MHZ)
#define CON0_MT7981_RST_BAR BIT(27)
#define PLL_xtal(_id, _name, _reg, _pwr_reg, _en_mask, _flags, _pcwbits, \
_pd_reg, _pd_shift, _tuner_reg, _pcw_reg, _pcw_shift, \
_div_table, _parent_name) \
{ \
.id = _id, .name = _name, .reg = _reg, .pwr_reg = _pwr_reg, \
.en_mask = _en_mask, .flags = _flags, \
.rst_bar_mask = CON0_MT7981_RST_BAR, .fmax = MT7981_PLL_FMAX, \
.pcwbits = _pcwbits, .pd_reg = _pd_reg, .pd_shift = _pd_shift, \
.tuner_reg = _tuner_reg, .pcw_reg = _pcw_reg, \
.pcw_shift = _pcw_shift, .div_table = _div_table, \
.parent_name = _parent_name, \
}
#define PLL(_id, _name, _reg, _pwr_reg, _en_mask, _flags, _pcwbits, _pd_reg, \
_pd_shift, _tuner_reg, _pcw_reg, _pcw_shift) \
PLL_xtal(_id, _name, _reg, _pwr_reg, _en_mask, _flags, _pcwbits, \
_pd_reg, _pd_shift, _tuner_reg, _pcw_reg, _pcw_shift, NULL, \
"clkxtal")
static const struct mtk_pll_data plls[] = {
PLL(CLK_APMIXED_ARMPLL, "armpll", 0x0200, 0x020C, 0x00000001, PLL_AO,
32, 0x0200, 4, 0, 0x0204, 0),
PLL(CLK_APMIXED_NET2PLL, "net2pll", 0x0210, 0x021C, 0x00000001, 0, 32,
0x0210, 4, 0, 0x0214, 0),
PLL(CLK_APMIXED_MMPLL, "mmpll", 0x0220, 0x022C, 0x00000001, 0, 32,
0x0220, 4, 0, 0x0224, 0),
PLL(CLK_APMIXED_SGMPLL, "sgmpll", 0x0230, 0x023C, 0x00000001, 0, 32,
0x0230, 4, 0, 0x0234, 0),
PLL(CLK_APMIXED_WEDMCUPLL, "wedmcupll", 0x0240, 0x024C, 0x00000001, 0, 32,
0x0240, 4, 0, 0x0244, 0),
PLL(CLK_APMIXED_NET1PLL, "net1pll", 0x0250, 0x025C, 0x00000001, 0, 32,
0x0250, 4, 0, 0x0254, 0),
PLL(CLK_APMIXED_MPLL, "mpll", 0x0260, 0x0270, 0x00000001, 0, 32,
0x0260, 4, 0, 0x0264, 0),
PLL(CLK_APMIXED_APLL2, "apll2", 0x0278, 0x0288, 0x00000001, 0, 32,
0x0278, 4, 0, 0x027C, 0),
};
static const struct of_device_id of_match_clk_mt7981_apmixed[] = {
{ .compatible = "mediatek,mt7981-apmixedsys", },
{}
};
static int clk_mt7981_apmixed_probe(struct platform_device *pdev)
{
struct clk_onecell_data *clk_data;
struct device_node *node = pdev->dev.of_node;
int r;
clk_data = mtk_alloc_clk_data(ARRAY_SIZE(plls));
if (!clk_data)
return -ENOMEM;
mtk_clk_register_plls(node, plls, ARRAY_SIZE(plls), clk_data);
clk_prepare_enable(clk_data->clks[CLK_APMIXED_ARMPLL]);
r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
if (r) {
pr_err("%s(): could not register clock provider: %d\n",
__func__, r);
goto free_apmixed_data;
}
return r;
free_apmixed_data:
mtk_free_clk_data(clk_data);
return r;
}
static struct platform_driver clk_mt7981_apmixed_drv = {
.probe = clk_mt7981_apmixed_probe,
.driver = {
.name = "clk-mt7981-apmixed",
.of_match_table = of_match_clk_mt7981_apmixed,
},
};
builtin_platform_driver(clk_mt7981_apmixed_drv);

View File

@ -0,0 +1,139 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2021 MediaTek Inc.
* Author: Sam Shih <sam.shih@mediatek.com>
* Author: Wenzhen Yu <wenzhen.yu@mediatek.com>
* Author: Jianhui Zhao <zhaojh329@gmail.com>
* Author: Daniel Golle <daniel@makrotopia.org>
*/
#include <linux/clk-provider.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/of_device.h>
#include <linux/platform_device.h>
#include "clk-mtk.h"
#include "clk-gate.h"
#include <dt-bindings/clock/mediatek,mt7981-clk.h>
static const struct mtk_gate_regs sgmii0_cg_regs = {
.set_ofs = 0xE4,
.clr_ofs = 0xE4,
.sta_ofs = 0xE4,
};
#define GATE_SGMII0(_id, _name, _parent, _shift) { \
.id = _id, \
.name = _name, \
.parent_name = _parent, \
.regs = &sgmii0_cg_regs, \
.shift = _shift, \
.ops = &mtk_clk_gate_ops_no_setclr_inv, \
}
static const struct mtk_gate sgmii0_clks[] __initconst = {
GATE_SGMII0(CLK_SGM0_TX_EN, "sgm0_tx_en", "usb_tx250m", 2),
GATE_SGMII0(CLK_SGM0_RX_EN, "sgm0_rx_en", "usb_eq_rx250m", 3),
GATE_SGMII0(CLK_SGM0_CK0_EN, "sgm0_ck0_en", "usb_ln0", 4),
GATE_SGMII0(CLK_SGM0_CDR_CK0_EN, "sgm0_cdr_ck0_en", "usb_cdr", 5),
};
static const struct mtk_gate_regs sgmii1_cg_regs = {
.set_ofs = 0xE4,
.clr_ofs = 0xE4,
.sta_ofs = 0xE4,
};
#define GATE_SGMII1(_id, _name, _parent, _shift) { \
.id = _id, \
.name = _name, \
.parent_name = _parent, \
.regs = &sgmii1_cg_regs, \
.shift = _shift, \
.ops = &mtk_clk_gate_ops_no_setclr_inv, \
}
static const struct mtk_gate sgmii1_clks[] __initconst = {
GATE_SGMII1(CLK_SGM1_TX_EN, "sgm1_tx_en", "usb_tx250m", 2),
GATE_SGMII1(CLK_SGM1_RX_EN, "sgm1_rx_en", "usb_eq_rx250m", 3),
GATE_SGMII1(CLK_SGM1_CK1_EN, "sgm1_ck1_en", "usb_ln0", 4),
GATE_SGMII1(CLK_SGM1_CDR_CK1_EN, "sgm1_cdr_ck1_en", "usb_cdr", 5),
};
static const struct mtk_gate_regs eth_cg_regs = {
.set_ofs = 0x30,
.clr_ofs = 0x30,
.sta_ofs = 0x30,
};
#define GATE_ETH(_id, _name, _parent, _shift) { \
.id = _id, \
.name = _name, \
.parent_name = _parent, \
.regs = &eth_cg_regs, \
.shift = _shift, \
.ops = &mtk_clk_gate_ops_no_setclr_inv, \
}
static const struct mtk_gate eth_clks[] __initconst = {
GATE_ETH(CLK_ETH_FE_EN, "eth_fe_en", "netsys_2x", 6),
GATE_ETH(CLK_ETH_GP2_EN, "eth_gp2_en", "sgm_325m", 7),
GATE_ETH(CLK_ETH_GP1_EN, "eth_gp1_en", "sgm_325m", 8),
GATE_ETH(CLK_ETH_WOCPU0_EN, "eth_wocpu0_en", "netsys_wed_mcu", 15),
};
static void __init mtk_sgmiisys_0_init(struct device_node *node)
{
struct clk_onecell_data *clk_data;
int r;
clk_data = mtk_alloc_clk_data(ARRAY_SIZE(sgmii0_clks));
mtk_clk_register_gates(node, sgmii0_clks, ARRAY_SIZE(sgmii0_clks),
clk_data);
r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
if (r)
pr_err("%s(): could not register clock provider: %d\n",
__func__, r);
}
CLK_OF_DECLARE(mtk_sgmiisys_0, "mediatek,mt7981-sgmiisys_0",
mtk_sgmiisys_0_init);
static void __init mtk_sgmiisys_1_init(struct device_node *node)
{
struct clk_onecell_data *clk_data;
int r;
clk_data = mtk_alloc_clk_data(ARRAY_SIZE(sgmii1_clks));
mtk_clk_register_gates(node, sgmii1_clks, ARRAY_SIZE(sgmii1_clks),
clk_data);
r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
if (r)
pr_err("%s(): could not register clock provider: %d\n",
__func__, r);
}
CLK_OF_DECLARE(mtk_sgmiisys_1, "mediatek,mt7981-sgmiisys_1",
mtk_sgmiisys_1_init);
static void __init mtk_ethsys_init(struct device_node *node)
{
struct clk_onecell_data *clk_data;
int r;
clk_data = mtk_alloc_clk_data(ARRAY_SIZE(eth_clks));
mtk_clk_register_gates(node, eth_clks, ARRAY_SIZE(eth_clks), clk_data);
r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
if (r)
pr_err("%s(): could not register clock provider: %d\n",
__func__, r);
}
CLK_OF_DECLARE(mtk_ethsys, "mediatek,mt7981-ethsys", mtk_ethsys_init);

View File

@ -0,0 +1,235 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2021 MediaTek Inc.
* Author: Sam Shih <sam.shih@mediatek.com>
* Author: Wenzhen Yu <wenzhen.yu@mediatek.com>
* Author: Jianhui Zhao <zhaojh329@gmail.com>
* Author: Daniel Golle <daniel@makrotopia.org>
*/
#include <linux/clk-provider.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/of_device.h>
#include <linux/platform_device.h>
#include "clk-mtk.h"
#include "clk-gate.h"
#include "clk-mux.h"
#include <dt-bindings/clock/mediatek,mt7981-clk.h>
#include <linux/clk.h>
static DEFINE_SPINLOCK(mt7981_clk_lock);
static const struct mtk_fixed_factor infra_divs[] = {
FACTOR(CLK_INFRA_66M_MCK, "infra_66m_mck", "sysaxi_sel", 1, 2),
};
static const char *const infra_uart_parent[] __initconst = { "csw_f26m_sel",
"uart_sel" };
static const char *const infra_spi0_parents[] __initconst = { "i2c_sel",
"spi_sel" };
static const char *const infra_spi1_parents[] __initconst = { "i2c_sel",
"spim_mst_sel" };
static const char *const infra_pwm1_parents[] __initconst = { "pwm_sel" };
static const char *const infra_pwm_bsel_parents[] __initconst = {
"cb_rtc_32p7k", "csw_f26m_sel", "infra_66m_mck", "pwm_sel"
};
static const char *const infra_pcie_parents[] __initconst = {
"cb_rtc_32p7k", "csw_f26m_sel", "cb_cksq_40m", "pextp_tl_ck_sel"
};
static const struct mtk_mux infra_muxes[] = {
/* MODULE_CLK_SEL_0 */
MUX_GATE_CLR_SET_UPD(CLK_INFRA_UART0_SEL, "infra_uart0_sel",
infra_uart_parent, 0x0018, 0x0010, 0x0014, 0, 1,
-1, -1, -1),
MUX_GATE_CLR_SET_UPD(CLK_INFRA_UART1_SEL, "infra_uart1_sel",
infra_uart_parent, 0x0018, 0x0010, 0x0014, 1, 1,
-1, -1, -1),
MUX_GATE_CLR_SET_UPD(CLK_INFRA_UART2_SEL, "infra_uart2_sel",
infra_uart_parent, 0x0018, 0x0010, 0x0014, 2, 1,
-1, -1, -1),
MUX_GATE_CLR_SET_UPD(CLK_INFRA_SPI0_SEL, "infra_spi0_sel",
infra_spi0_parents, 0x0018, 0x0010, 0x0014, 4, 1,
-1, -1, -1),
MUX_GATE_CLR_SET_UPD(CLK_INFRA_SPI1_SEL, "infra_spi1_sel",
infra_spi1_parents, 0x0018, 0x0010, 0x0014, 5, 1,
-1, -1, -1),
MUX_GATE_CLR_SET_UPD(CLK_INFRA_SPI2_SEL, "infra_spi2_sel",
infra_spi0_parents, 0x0018, 0x0010, 0x0014, 6, 1,
-1, -1, -1),
MUX_GATE_CLR_SET_UPD(CLK_INFRA_PWM1_SEL, "infra_pwm1_sel",
infra_pwm1_parents, 0x0018, 0x0010, 0x0014, 9, 1,
-1, -1, -1),
MUX_GATE_CLR_SET_UPD(CLK_INFRA_PWM2_SEL, "infra_pwm2_sel",
infra_pwm1_parents, 0x0018, 0x0010, 0x0014, 11, 1,
-1, -1, -1),
MUX_GATE_CLR_SET_UPD(CLK_INFRA_PWM3_SEL, "infra_pwm3_sel",
infra_pwm1_parents, 0x0018, 0x0010, 0x0014, 15, 1,
-1, -1, -1),
MUX_GATE_CLR_SET_UPD(CLK_INFRA_PWM_BSEL, "infra_pwm_bsel",
infra_pwm_bsel_parents, 0x0018, 0x0010, 0x0014, 13,
2, -1, -1, -1),
/* MODULE_CLK_SEL_1 */
MUX_GATE_CLR_SET_UPD(CLK_INFRA_PCIE_SEL, "infra_pcie_sel",
infra_pcie_parents, 0x0028, 0x0020, 0x0024, 0, 2,
-1, -1, -1),
};
static const struct mtk_gate_regs infra0_cg_regs = {
.set_ofs = 0x40,
.clr_ofs = 0x44,
.sta_ofs = 0x48,
};
static const struct mtk_gate_regs infra1_cg_regs = {
.set_ofs = 0x50,
.clr_ofs = 0x54,
.sta_ofs = 0x58,
};
static const struct mtk_gate_regs infra2_cg_regs = {
.set_ofs = 0x60,
.clr_ofs = 0x64,
.sta_ofs = 0x68,
};
#define GATE_INFRA0(_id, _name, _parent, _shift) \
{ \
.id = _id, .name = _name, .parent_name = _parent, \
.regs = &infra0_cg_regs, .shift = _shift, \
.ops = &mtk_clk_gate_ops_setclr, \
}
#define GATE_INFRA1(_id, _name, _parent, _shift) \
{ \
.id = _id, .name = _name, .parent_name = _parent, \
.regs = &infra1_cg_regs, .shift = _shift, \
.ops = &mtk_clk_gate_ops_setclr, \
}
#define GATE_INFRA2(_id, _name, _parent, _shift) \
{ \
.id = _id, .name = _name, .parent_name = _parent, \
.regs = &infra2_cg_regs, .shift = _shift, \
.ops = &mtk_clk_gate_ops_setclr, \
}
static const struct mtk_gate infra_clks[] = {
/* INFRA0 */
GATE_INFRA0(CLK_INFRA_GPT_STA, "infra_gpt_sta", "infra_66m_mck", 0),
GATE_INFRA0(CLK_INFRA_PWM_HCK, "infra_pwm_hck", "infra_66m_mck", 1),
GATE_INFRA0(CLK_INFRA_PWM_STA, "infra_pwm_sta", "infra_pwm_bsel", 2),
GATE_INFRA0(CLK_INFRA_PWM1_CK, "infra_pwm1", "infra_pwm1_sel", 3),
GATE_INFRA0(CLK_INFRA_PWM2_CK, "infra_pwm2", "infra_pwm2_sel", 4),
GATE_INFRA0(CLK_INFRA_CQ_DMA_CK, "infra_cq_dma", "sysaxi", 6),
GATE_INFRA0(CLK_INFRA_AUD_BUS_CK, "infra_aud_bus", "sysaxi", 8),
GATE_INFRA0(CLK_INFRA_AUD_26M_CK, "infra_aud_26m", "csw_f26m_sel", 9),
GATE_INFRA0(CLK_INFRA_AUD_L_CK, "infra_aud_l", "aud_l", 10),
GATE_INFRA0(CLK_INFRA_AUD_AUD_CK, "infra_aud_aud", "a1sys", 11),
GATE_INFRA0(CLK_INFRA_AUD_EG2_CK, "infra_aud_eg2", "a_tuner", 13),
GATE_INFRA0(CLK_INFRA_DRAMC_26M_CK, "infra_dramc_26m", "csw_f26m_sel",
14),
GATE_INFRA0(CLK_INFRA_DBG_CK, "infra_dbg", "infra_66m_mck", 15),
GATE_INFRA0(CLK_INFRA_AP_DMA_CK, "infra_ap_dma", "infra_66m_mck", 16),
GATE_INFRA0(CLK_INFRA_SEJ_CK, "infra_sej", "infra_66m_mck", 24),
GATE_INFRA0(CLK_INFRA_SEJ_13M_CK, "infra_sej_13m", "csw_f26m_sel", 25),
GATE_INFRA0(CLK_INFRA_PWM3_CK, "infra_pwm3", "infra_pwm3_sel", 27),
/* INFRA1 */
GATE_INFRA1(CLK_INFRA_THERM_CK, "infra_therm", "csw_f26m_sel", 0),
GATE_INFRA1(CLK_INFRA_I2C0_CK, "infra_i2c0", "i2c_bck", 1),
GATE_INFRA1(CLK_INFRA_UART0_CK, "infra_uart0", "infra_uart0_sel", 2),
GATE_INFRA1(CLK_INFRA_UART1_CK, "infra_uart1", "infra_uart1_sel", 3),
GATE_INFRA1(CLK_INFRA_UART2_CK, "infra_uart2", "infra_uart2_sel", 4),
GATE_INFRA1(CLK_INFRA_SPI2_CK, "infra_spi2", "infra_spi2_sel", 6),
GATE_INFRA1(CLK_INFRA_SPI2_HCK_CK, "infra_spi2_hck", "infra_66m_mck", 7),
GATE_INFRA1(CLK_INFRA_NFI1_CK, "infra_nfi1", "nfi1x", 8),
GATE_INFRA1(CLK_INFRA_SPINFI1_CK, "infra_spinfi1", "spinfi_bck", 9),
GATE_INFRA1(CLK_INFRA_NFI_HCK_CK, "infra_nfi_hck", "infra_66m_mck", 10),
GATE_INFRA1(CLK_INFRA_SPI0_CK, "infra_spi0", "infra_spi0_sel", 11),
GATE_INFRA1(CLK_INFRA_SPI1_CK, "infra_spi1", "infra_spi1_sel", 12),
GATE_INFRA1(CLK_INFRA_SPI0_HCK_CK, "infra_spi0_hck", "infra_66m_mck",
13),
GATE_INFRA1(CLK_INFRA_SPI1_HCK_CK, "infra_spi1_hck", "infra_66m_mck",
14),
GATE_INFRA1(CLK_INFRA_FRTC_CK, "infra_frtc", "cb_rtc_32k", 15),
GATE_INFRA1(CLK_INFRA_MSDC_CK, "infra_msdc", "emmc_400m", 16),
GATE_INFRA1(CLK_INFRA_MSDC_HCK_CK, "infra_msdc_hck", "emmc_208m", 17),
GATE_INFRA1(CLK_INFRA_MSDC_133M_CK, "infra_msdc_133m", "sysaxi", 18),
GATE_INFRA1(CLK_INFRA_MSDC_66M_CK, "infra_msdc_66m", "sysaxi", 19),
GATE_INFRA1(CLK_INFRA_ADC_26M_CK, "infra_adc_26m", "infra_adc_frc", 20),
GATE_INFRA1(CLK_INFRA_ADC_FRC_CK, "infra_adc_frc", "csw_f26m", 21),
GATE_INFRA1(CLK_INFRA_FBIST2FPC_CK, "infra_fbist2fpc", "nfi1x", 23),
GATE_INFRA1(CLK_INFRA_I2C_MCK_CK, "infra_i2c_mck", "sysaxi", 25),
GATE_INFRA1(CLK_INFRA_I2C_PCK_CK, "infra_i2c_pck", "infra_66m_mck", 26),
/* INFRA2 */
GATE_INFRA2(CLK_INFRA_IUSB_133_CK, "infra_iusb_133", "sysaxi", 0),
GATE_INFRA2(CLK_INFRA_IUSB_66M_CK, "infra_iusb_66m", "sysaxi", 1),
GATE_INFRA2(CLK_INFRA_IUSB_SYS_CK, "infra_iusb_sys", "u2u3_sys", 2),
GATE_INFRA2(CLK_INFRA_IUSB_CK, "infra_iusb", "u2u3_ref", 3),
GATE_INFRA2(CLK_INFRA_IPCIE_CK, "infra_ipcie", "pextp_tl", 12),
GATE_INFRA2(CLK_INFRA_IPCIE_PIPE_CK, "infra_ipcie_pipe", "cb_cksq_40m",
13),
GATE_INFRA2(CLK_INFRA_IPCIER_CK, "infra_ipcier", "csw_f26m", 14),
GATE_INFRA2(CLK_INFRA_IPCIEB_CK, "infra_ipcieb", "sysaxi", 15),
};
static int clk_mt7981_infracfg_probe(struct platform_device *pdev)
{
struct clk_onecell_data *clk_data;
struct device_node *node = pdev->dev.of_node;
int r;
void __iomem *base;
int nr = ARRAY_SIZE(infra_divs) + ARRAY_SIZE(infra_muxes) +
ARRAY_SIZE(infra_clks);
base = of_iomap(node, 0);
if (!base) {
pr_err("%s(): ioremap failed\n", __func__);
return -ENOMEM;
}
clk_data = mtk_alloc_clk_data(nr);
if (!clk_data)
return -ENOMEM;
mtk_clk_register_factors(infra_divs, ARRAY_SIZE(infra_divs), clk_data);
mtk_clk_register_muxes(infra_muxes, ARRAY_SIZE(infra_muxes), node,
&mt7981_clk_lock, clk_data);
mtk_clk_register_gates(node, infra_clks, ARRAY_SIZE(infra_clks),
clk_data);
r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
if (r) {
pr_err("%s(): could not register clock provider: %d\n",
__func__, r);
goto free_infracfg_data;
}
return r;
free_infracfg_data:
mtk_free_clk_data(clk_data);
return r;
}
static const struct of_device_id of_match_clk_mt7981_infracfg[] = {
{ .compatible = "mediatek,mt7981-infracfg", },
{}
};
static struct platform_driver clk_mt7981_infracfg_drv = {
.probe = clk_mt7981_infracfg_probe,
.driver = {
.name = "clk-mt7981-infracfg",
.of_match_table = of_match_clk_mt7981_infracfg,
},
};
builtin_platform_driver(clk_mt7981_infracfg_drv);

View File

@ -0,0 +1,450 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2021 MediaTek Inc.
* Author: Sam Shih <sam.shih@mediatek.com>
* Author: Wenzhen Yu <wenzhen.yu@mediatek.com>
* Author: Jianhui Zhao <zhaojh329@gmail.com>
*/
#include <linux/clk-provider.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/of_device.h>
#include <linux/platform_device.h>
#include "clk-mtk.h"
#include "clk-gate.h"
#include "clk-mux.h"
#include <dt-bindings/clock/mediatek,mt7981-clk.h>
#include <linux/clk.h>
static DEFINE_SPINLOCK(mt7981_clk_lock);
static const struct mtk_fixed_factor top_divs[] = {
FACTOR(CLK_TOP_CB_CKSQ_40M, "cb_cksq_40m", "clkxtal", 1, 1),
FACTOR(CLK_TOP_CB_M_416M, "cb_m_416m", "mpll", 1, 1),
FACTOR(CLK_TOP_CB_M_D2, "cb_m_d2", "mpll", 1, 2),
FACTOR(CLK_TOP_CB_M_D3, "cb_m_d3", "mpll", 1, 3),
FACTOR(CLK_TOP_M_D3_D2, "m_d3_d2", "mpll", 1, 2),
FACTOR(CLK_TOP_CB_M_D4, "cb_m_d4", "mpll", 1, 4),
FACTOR(CLK_TOP_CB_M_D8, "cb_m_d8", "mpll", 1, 8),
FACTOR(CLK_TOP_M_D8_D2, "m_d8_d2", "mpll", 1, 16),
FACTOR(CLK_TOP_CB_MM_720M, "cb_mm_720m", "mmpll", 1, 1),
FACTOR(CLK_TOP_CB_MM_D2, "cb_mm_d2", "mmpll", 1, 2),
FACTOR(CLK_TOP_CB_MM_D3, "cb_mm_d3", "mmpll", 1, 3),
FACTOR(CLK_TOP_CB_MM_D3_D5, "cb_mm_d3_d5", "mmpll", 1, 15),
FACTOR(CLK_TOP_CB_MM_D4, "cb_mm_d4", "mmpll", 1, 4),
FACTOR(CLK_TOP_CB_MM_D6, "cb_mm_d6", "mmpll", 1, 6),
FACTOR(CLK_TOP_MM_D6_D2, "mm_d6_d2", "mmpll", 1, 12),
FACTOR(CLK_TOP_CB_MM_D8, "cb_mm_d8", "mmpll", 1, 8),
FACTOR(CLK_TOP_CB_APLL2_196M, "cb_apll2_196m", "apll2", 1, 1),
FACTOR(CLK_TOP_APLL2_D2, "apll2_d2", "apll2", 1, 2),
FACTOR(CLK_TOP_APLL2_D4, "apll2_d4", "apll2", 1, 4),
FACTOR(CLK_TOP_NET1_2500M, "net1_2500m", "net1pll", 1, 1),
FACTOR(CLK_TOP_CB_NET1_D4, "cb_net1_d4", "net1pll", 1, 4),
FACTOR(CLK_TOP_CB_NET1_D5, "cb_net1_d5", "net1pll", 1, 5),
FACTOR(CLK_TOP_NET1_D5_D2, "net1_d5_d2", "net1pll", 1, 10),
FACTOR(CLK_TOP_NET1_D5_D4, "net1_d5_d4", "net1pll", 1, 20),
FACTOR(CLK_TOP_CB_NET1_D8, "cb_net1_d8", "net1pll", 1, 8),
FACTOR(CLK_TOP_NET1_D8_D2, "net1_d8_d2", "net1pll", 1, 16),
FACTOR(CLK_TOP_NET1_D8_D4, "net1_d8_d4", "net1pll", 1, 32),
FACTOR(CLK_TOP_CB_NET2_800M, "cb_net2_800m", "net2pll", 1, 1),
FACTOR(CLK_TOP_CB_NET2_D2, "cb_net2_d2", "net2pll", 1, 2),
FACTOR(CLK_TOP_CB_NET2_D4, "cb_net2_d4", "net2pll", 1, 4),
FACTOR(CLK_TOP_NET2_D4_D2, "net2_d4_d2", "net2pll", 1, 8),
FACTOR(CLK_TOP_NET2_D4_D4, "net2_d4_d4", "net2pll", 1, 16),
FACTOR(CLK_TOP_CB_NET2_D6, "cb_net2_d6", "net2pll", 1, 6),
FACTOR(CLK_TOP_CB_WEDMCU_208M, "cb_wedmcu_208m", "wedmcupll", 1, 1),
FACTOR(CLK_TOP_CB_SGM_325M, "cb_sgm_325m", "sgmpll", 1, 1),
FACTOR(CLK_TOP_CKSQ_40M_D2, "cksq_40m_d2", "cb_cksq_40m", 1, 2),
FACTOR(CLK_TOP_CB_RTC_32K, "cb_rtc_32k", "cb_cksq_40m", 1, 1250),
FACTOR(CLK_TOP_CB_RTC_32P7K, "cb_rtc_32p7k", "cb_cksq_40m", 1, 1220),
FACTOR(CLK_TOP_USB_TX250M, "usb_tx250m", "cb_cksq_40m", 1, 1),
FACTOR(CLK_TOP_FAUD, "faud", "aud_sel", 1, 1),
FACTOR(CLK_TOP_NFI1X, "nfi1x", "nfi1x_sel", 1, 1),
FACTOR(CLK_TOP_USB_EQ_RX250M, "usb_eq_rx250m", "cb_cksq_40m", 1, 1),
FACTOR(CLK_TOP_USB_CDR_CK, "usb_cdr", "cb_cksq_40m", 1, 1),
FACTOR(CLK_TOP_USB_LN0_CK, "usb_ln0", "cb_cksq_40m", 1, 1),
FACTOR(CLK_TOP_SPINFI_BCK, "spinfi_bck", "spinfi_sel", 1, 1),
FACTOR(CLK_TOP_SPI, "spi", "spi_sel", 1, 1),
FACTOR(CLK_TOP_SPIM_MST, "spim_mst", "spim_mst_sel", 1, 1),
FACTOR(CLK_TOP_UART_BCK, "uart_bck", "uart_sel", 1, 1),
FACTOR(CLK_TOP_PWM_BCK, "pwm_bck", "pwm_sel", 1, 1),
FACTOR(CLK_TOP_I2C_BCK, "i2c_bck", "i2c_sel", 1, 1),
FACTOR(CLK_TOP_PEXTP_TL, "pextp_tl", "pextp_tl_ck_sel", 1, 1),
FACTOR(CLK_TOP_EMMC_208M, "emmc_208m", "emmc_208m_sel", 1, 1),
FACTOR(CLK_TOP_EMMC_400M, "emmc_400m", "emmc_400m_sel", 1, 1),
FACTOR(CLK_TOP_DRAMC_REF, "dramc_ref", "dramc_sel", 1, 1),
FACTOR(CLK_TOP_DRAMC_MD32, "dramc_md32", "dramc_md32_sel", 1, 1),
FACTOR(CLK_TOP_SYSAXI, "sysaxi", "sysaxi_sel", 1, 1),
FACTOR(CLK_TOP_SYSAPB, "sysapb", "sysapb_sel", 1, 1),
FACTOR(CLK_TOP_ARM_DB_MAIN, "arm_db_main", "arm_db_main_sel", 1, 1),
FACTOR(CLK_TOP_AP2CNN_HOST, "ap2cnn_host", "ap2cnn_host_sel", 1, 1),
FACTOR(CLK_TOP_NETSYS, "netsys", "netsys_sel", 1, 1),
FACTOR(CLK_TOP_NETSYS_500M, "netsys_500m", "netsys_500m_sel", 1, 1),
FACTOR(CLK_TOP_NETSYS_WED_MCU, "netsys_wed_mcu", "netsys_mcu_sel", 1, 1),
FACTOR(CLK_TOP_NETSYS_2X, "netsys_2x", "netsys_2x_sel", 1, 1),
FACTOR(CLK_TOP_SGM_325M, "sgm_325m", "sgm_325m_sel", 1, 1),
FACTOR(CLK_TOP_SGM_REG, "sgm_reg", "sgm_reg_sel", 1, 1),
FACTOR(CLK_TOP_F26M, "csw_f26m", "csw_f26m_sel", 1, 1),
FACTOR(CLK_TOP_EIP97B, "eip97b", "eip97b_sel", 1, 1),
FACTOR(CLK_TOP_USB3_PHY, "usb3_phy", "usb3_phy_sel", 1, 1),
FACTOR(CLK_TOP_AUD, "aud", "faud", 1, 1),
FACTOR(CLK_TOP_A1SYS, "a1sys", "a1sys_sel", 1, 1),
FACTOR(CLK_TOP_AUD_L, "aud_l", "aud_l_sel", 1, 1),
FACTOR(CLK_TOP_A_TUNER, "a_tuner", "a_tuner_sel", 1, 1),
FACTOR(CLK_TOP_U2U3_REF, "u2u3_ref", "u2u3_sel", 1, 1),
FACTOR(CLK_TOP_U2U3_SYS, "u2u3_sys", "u2u3_sys_sel", 1, 1),
FACTOR(CLK_TOP_U2U3_XHCI, "u2u3_xhci", "u2u3_xhci_sel", 1, 1),
FACTOR(CLK_TOP_USB_FRMCNT, "usb_frmcnt", "usb_frmcnt_sel", 1, 1),
};
static const char * const nfi1x_parents[] __initconst = {
"cb_cksq_40m",
"cb_mm_d4",
"net1_d8_d2",
"cb_net2_d6",
"cb_m_d4",
"cb_mm_d8",
"net1_d8_d4",
"cb_m_d8"
};
static const char * const spinfi_parents[] __initconst = {
"cksq_40m_d2",
"cb_cksq_40m",
"net1_d5_d4",
"cb_m_d4",
"cb_mm_d8",
"net1_d8_d4",
"mm_d6_d2",
"cb_m_d8"
};
static const char * const spi_parents[] __initconst = {
"cb_cksq_40m",
"cb_m_d2",
"cb_mm_d4",
"net1_d8_d2",
"cb_net2_d6",
"net1_d5_d4",
"cb_m_d4",
"net1_d8_d4"
};
static const char * const uart_parents[] __initconst = {
"cb_cksq_40m",
"cb_m_d8",
"m_d8_d2"
};
static const char * const pwm_parents[] __initconst = {
"cb_cksq_40m",
"net1_d8_d2",
"net1_d5_d4",
"cb_m_d4",
"m_d8_d2",
"cb_rtc_32k"
};
static const char * const i2c_parents[] __initconst = {
"cb_cksq_40m",
"net1_d5_d4",
"cb_m_d4",
"net1_d8_d4"
};
static const char * const pextp_tl_ck_parents[] __initconst = {
"cb_cksq_40m",
"net1_d5_d4",
"cb_m_d4",
"cb_rtc_32k"
};
static const char * const emmc_208m_parents[] __initconst = {
"cb_cksq_40m",
"cb_m_d2",
"cb_net2_d4",
"cb_apll2_196m",
"cb_mm_d4",
"net1_d8_d2",
"cb_mm_d6"
};
static const char * const emmc_400m_parents[] __initconst = {
"cb_cksq_40m",
"cb_net2_d2",
"cb_mm_d2",
"cb_net2_d2"
};
static const char * const csw_f26m_parents[] __initconst = {
"cksq_40m_d2",
"m_d8_d2"
};
static const char * const dramc_md32_parents[] __initconst = {
"cb_cksq_40m",
"cb_m_d2",
"cb_wedmcu_208m"
};
static const char * const sysaxi_parents[] __initconst = {
"cb_cksq_40m",
"net1_d8_d2"
};
static const char * const sysapb_parents[] __initconst = {
"cb_cksq_40m",
"m_d3_d2"
};
static const char * const arm_db_main_parents[] __initconst = {
"cb_cksq_40m",
"cb_net2_d6"
};
static const char * const ap2cnn_host_parents[] __initconst = {
"cb_cksq_40m",
"net1_d8_d4"
};
static const char * const netsys_parents[] __initconst = {
"cb_cksq_40m",
"cb_mm_d2"
};
static const char * const netsys_500m_parents[] __initconst = {
"cb_cksq_40m",
"cb_net1_d5"
};
static const char * const netsys_mcu_parents[] __initconst = {
"cb_cksq_40m",
"cb_mm_720m",
"cb_net1_d4",
"cb_net1_d5",
"cb_m_416m"
};
static const char * const netsys_2x_parents[] __initconst = {
"cb_cksq_40m",
"cb_net2_800m",
"cb_mm_720m"
};
static const char * const sgm_325m_parents[] __initconst = {
"cb_cksq_40m",
"cb_sgm_325m"
};
static const char * const sgm_reg_parents[] __initconst = {
"cb_cksq_40m",
"cb_net2_d4"
};
static const char * const eip97b_parents[] __initconst = {
"cb_cksq_40m",
"cb_net1_d5",
"cb_m_416m",
"cb_mm_d2",
"net1_d5_d2"
};
static const char * const aud_parents[] __initconst = {
"cb_cksq_40m",
"cb_apll2_196m"
};
static const char * const a1sys_parents[] __initconst = {
"cb_cksq_40m",
"apll2_d4"
};
static const char * const aud_l_parents[] __initconst = {
"cb_cksq_40m",
"cb_apll2_196m",
"m_d8_d2"
};
static const char * const a_tuner_parents[] __initconst = {
"cb_cksq_40m",
"apll2_d4",
"m_d8_d2"
};
static const char * const u2u3_parents[] __initconst = {
"cb_cksq_40m",
"m_d8_d2"
};
static const char * const u2u3_sys_parents[] __initconst = {
"cb_cksq_40m",
"net1_d5_d4"
};
static const char * const usb_frmcnt_parents[] __initconst = {
"cb_cksq_40m",
"cb_mm_d3_d5"
};
static const struct mtk_mux top_muxes[] = {
/* CLK_CFG_0 */
MUX_GATE_CLR_SET_UPD(CLK_TOP_NFI1X_SEL, "nfi1x_sel", nfi1x_parents,
0x000, 0x004, 0x008, 0, 3, 7, 0x1C0, 0),
MUX_GATE_CLR_SET_UPD(CLK_TOP_SPINFI_SEL, "spinfi_sel", spinfi_parents,
0x000, 0x004, 0x008, 8, 3, 15, 0x1C0, 1),
MUX_GATE_CLR_SET_UPD(CLK_TOP_SPI_SEL, "spi_sel", spi_parents,
0x000, 0x004, 0x008, 16, 3, 23, 0x1C0, 2),
MUX_GATE_CLR_SET_UPD(CLK_TOP_SPIM_MST_SEL, "spim_mst_sel", spi_parents,
0x000, 0x004, 0x008, 24, 3, 31, 0x1C0, 3),
/* CLK_CFG_1 */
MUX_GATE_CLR_SET_UPD(CLK_TOP_UART_SEL, "uart_sel", uart_parents,
0x010, 0x014, 0x018, 0, 2, 7, 0x1C0, 4),
MUX_GATE_CLR_SET_UPD(CLK_TOP_PWM_SEL, "pwm_sel", pwm_parents,
0x010, 0x014, 0x018, 8, 3, 15, 0x1C0, 5),
MUX_GATE_CLR_SET_UPD(CLK_TOP_I2C_SEL, "i2c_sel", i2c_parents,
0x010, 0x014, 0x018, 16, 2, 23, 0x1C0, 6),
MUX_GATE_CLR_SET_UPD(CLK_TOP_PEXTP_TL_SEL, "pextp_tl_ck_sel",
pextp_tl_ck_parents, 0x010, 0x014, 0x018, 24, 2, 31,
0x1C0, 7),
/* CLK_CFG_2 */
MUX_GATE_CLR_SET_UPD(CLK_TOP_EMMC_208M_SEL, "emmc_208m_sel",
emmc_208m_parents, 0x020, 0x024, 0x028, 0, 3, 7,
0x1C0, 8),
MUX_GATE_CLR_SET_UPD(CLK_TOP_EMMC_400M_SEL, "emmc_400m_sel",
emmc_400m_parents, 0x020, 0x024, 0x028, 8, 2, 15,
0x1C0, 9),
MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_F26M_SEL, "csw_f26m_sel",
csw_f26m_parents, 0x020, 0x024, 0x028, 16, 1, 23,
0x1C0, 10,
CLK_IS_CRITICAL | CLK_SET_RATE_PARENT),
MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_DRAMC_SEL, "dramc_sel",
csw_f26m_parents, 0x020, 0x024, 0x028, 24, 1,
31, 0x1C0, 11,
CLK_IS_CRITICAL | CLK_SET_RATE_PARENT),
/* CLK_CFG_3 */
MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_DRAMC_MD32_SEL, "dramc_md32_sel",
dramc_md32_parents, 0x030, 0x034, 0x038, 0, 2,
7, 0x1C0, 12,
CLK_IS_CRITICAL | CLK_SET_RATE_PARENT),
MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_SYSAXI_SEL, "sysaxi_sel",
sysaxi_parents, 0x030, 0x034, 0x038, 8, 1, 15,
0x1C0, 13,
CLK_IS_CRITICAL | CLK_SET_RATE_PARENT),
MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_SYSAPB_SEL, "sysapb_sel",
sysapb_parents, 0x030, 0x034, 0x038, 16, 1,
23, 0x1C0, 14,
CLK_IS_CRITICAL | CLK_SET_RATE_PARENT),
MUX_GATE_CLR_SET_UPD(CLK_TOP_ARM_DB_MAIN_SEL, "arm_db_main_sel",
arm_db_main_parents, 0x030, 0x034, 0x038, 24, 1, 31,
0x1C0, 15),
/* CLK_CFG_4 */
MUX_GATE_CLR_SET_UPD(CLK_TOP_AP2CNN_HOST_SEL, "ap2cnn_host_sel",
ap2cnn_host_parents, 0x040, 0x044, 0x048, 0, 1, 7,
0x1C0, 16),
MUX_GATE_CLR_SET_UPD(CLK_TOP_NETSYS_SEL, "netsys_sel", netsys_parents,
0x040, 0x044, 0x048, 8, 1, 15, 0x1C0, 17),
MUX_GATE_CLR_SET_UPD(CLK_TOP_NETSYS_500M_SEL, "netsys_500m_sel",
netsys_500m_parents, 0x040, 0x044, 0x048, 16, 1, 23,
0x1C0, 18),
MUX_GATE_CLR_SET_UPD(CLK_TOP_NETSYS_MCU_SEL, "netsys_mcu_sel",
netsys_mcu_parents, 0x040, 0x044, 0x048, 24, 3, 31,
0x1C0, 19),
/* CLK_CFG_5 */
MUX_GATE_CLR_SET_UPD(CLK_TOP_NETSYS_2X_SEL, "netsys_2x_sel",
netsys_2x_parents, 0x050, 0x054, 0x058, 0, 2, 7,
0x1C0, 20),
MUX_GATE_CLR_SET_UPD(CLK_TOP_SGM_325M_SEL, "sgm_325m_sel",
sgm_325m_parents, 0x050, 0x054, 0x058, 8, 1, 15,
0x1C0, 21),
MUX_GATE_CLR_SET_UPD(CLK_TOP_SGM_REG_SEL, "sgm_reg_sel", sgm_reg_parents,
0x050, 0x054, 0x058, 16, 1, 23, 0x1C0, 22),
MUX_GATE_CLR_SET_UPD(CLK_TOP_EIP97B_SEL, "eip97b_sel", eip97b_parents,
0x050, 0x054, 0x058, 24, 3, 31, 0x1C0, 23),
/* CLK_CFG_6 */
MUX_GATE_CLR_SET_UPD(CLK_TOP_USB3_PHY_SEL, "usb3_phy_sel",
csw_f26m_parents, 0x060, 0x064, 0x068, 0, 1,
7, 0x1C0, 24),
MUX_GATE_CLR_SET_UPD(CLK_TOP_AUD_SEL, "aud_sel", aud_parents, 0x060,
0x064, 0x068, 8, 1, 15, 0x1C0, 25),
MUX_GATE_CLR_SET_UPD(CLK_TOP_A1SYS_SEL, "a1sys_sel", a1sys_parents,
0x060, 0x064, 0x068, 16, 1, 23, 0x1C0, 26),
MUX_GATE_CLR_SET_UPD(CLK_TOP_AUD_L_SEL, "aud_l_sel", aud_l_parents,
0x060, 0x064, 0x068, 24, 2, 31, 0x1C0, 27),
/* CLK_CFG_7 */
MUX_GATE_CLR_SET_UPD(CLK_TOP_A_TUNER_SEL, "a_tuner_sel",
a_tuner_parents, 0x070, 0x074, 0x078, 0, 2, 7,
0x1C0, 28),
MUX_GATE_CLR_SET_UPD(CLK_TOP_U2U3_SEL, "u2u3_sel", u2u3_parents, 0x070,
0x074, 0x078, 8, 1, 15, 0x1C0, 29),
MUX_GATE_CLR_SET_UPD(CLK_TOP_U2U3_SYS_SEL, "u2u3_sys_sel",
u2u3_sys_parents, 0x070, 0x074, 0x078, 16, 1, 23,
0x1C0, 30),
MUX_GATE_CLR_SET_UPD(CLK_TOP_U2U3_XHCI_SEL, "u2u3_xhci_sel",
u2u3_sys_parents, 0x070, 0x074, 0x078, 24, 1, 31,
0x1C4, 0),
/* CLK_CFG_8 */
MUX_GATE_CLR_SET_UPD(CLK_TOP_USB_FRMCNT_SEL, "usb_frmcnt_sel",
usb_frmcnt_parents, 0x080, 0x084, 0x088, 0, 1, 7,
0x1C4, 1),
};
static struct mtk_composite top_aud_divs[] = {
DIV_GATE(CLK_TOP_AUD_I2S_M, "aud_i2s_m", "aud",
0x0420, 0, 0x0420, 8, 8),
};
static int clk_mt7981_topckgen_probe(struct platform_device *pdev)
{
struct clk_onecell_data *clk_data;
struct device_node *node = pdev->dev.of_node;
int r;
void __iomem *base;
int nr = ARRAY_SIZE(top_divs) + ARRAY_SIZE(top_muxes) +
ARRAY_SIZE(top_aud_divs);
base = of_iomap(node, 0);
if (!base) {
pr_err("%s(): ioremap failed\n", __func__);
return -ENOMEM;
}
clk_data = mtk_alloc_clk_data(nr);
if (!clk_data)
return -ENOMEM;
mtk_clk_register_factors(top_divs, ARRAY_SIZE(top_divs), clk_data);
mtk_clk_register_muxes(top_muxes, ARRAY_SIZE(top_muxes), node,
&mt7981_clk_lock, clk_data);
mtk_clk_register_composites(top_aud_divs, ARRAY_SIZE(top_aud_divs), base,
&mt7981_clk_lock, clk_data);
r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
if (r) {
pr_err("%s(): could not register clock provider: %d\n",
__func__, r);
goto free_topckgen_data;
}
return r;
free_topckgen_data:
mtk_free_clk_data(clk_data);
return r;
}
static const struct of_device_id of_match_clk_mt7981_topckgen[] = {
{ .compatible = "mediatek,mt7981-topckgen", },
{}
};
static struct platform_driver clk_mt7981_topckgen_drv = {
.probe = clk_mt7981_topckgen_probe,
.driver = {
.name = "clk-mt7981-topckgen",
.of_match_table = of_match_clk_mt7981_topckgen,
},
};
builtin_platform_driver(clk_mt7981_topckgen_drv);

View File

@ -0,0 +1,993 @@
// SPDX-License-Identifier: GPL-2.0
/*
* The MT7981 driver based on Linux generic pinctrl binding.
*
* Copyright (C) 2020 MediaTek Inc.
* Author: Sam Shih <sam.shih@mediatek.com>
*/
#include "pinctrl-moore.h"
#define MT7981_PIN(_number, _name) \
MTK_PIN(_number, _name, 0, _number, DRV_GRP4)
#define PIN_FIELD_BASE(_s_pin, _e_pin, _i_base, _s_addr, _x_addrs, _s_bit, _x_bits) \
PIN_FIELD_CALC(_s_pin, _e_pin, _i_base, _s_addr, _x_addrs, _s_bit, \
_x_bits, 32, 0)
#define PINS_FIELD_BASE(_s_pin, _e_pin, _i_base, _s_addr, _x_addrs, _s_bit, _x_bits) \
PIN_FIELD_CALC(_s_pin, _e_pin, _i_base, _s_addr, _x_addrs, _s_bit, \
_x_bits, 32, 1)
static const struct mtk_pin_field_calc mt7981_pin_mode_range[] = {
PIN_FIELD(0, 56, 0x300, 0x10, 0, 4),
};
static const struct mtk_pin_field_calc mt7981_pin_dir_range[] = {
PIN_FIELD(0, 56, 0x0, 0x10, 0, 1),
};
static const struct mtk_pin_field_calc mt7981_pin_di_range[] = {
PIN_FIELD(0, 56, 0x200, 0x10, 0, 1),
};
static const struct mtk_pin_field_calc mt7981_pin_do_range[] = {
PIN_FIELD(0, 56, 0x100, 0x10, 0, 1),
};
static const struct mtk_pin_field_calc mt7981_pin_ies_range[] = {
PIN_FIELD_BASE(0, 0, 1, 0x10, 0x10, 1, 1),
PIN_FIELD_BASE(1, 1, 1, 0x10, 0x10, 0, 1),
PIN_FIELD_BASE(2, 2, 5, 0x20, 0x10, 6, 1),
PIN_FIELD_BASE(3, 3, 4, 0x20, 0x10, 6, 1),
PIN_FIELD_BASE(4, 4, 4, 0x20, 0x10, 2, 1),
PIN_FIELD_BASE(5, 5, 4, 0x20, 0x10, 1, 1),
PIN_FIELD_BASE(6, 6, 4, 0x20, 0x10, 3, 1),
PIN_FIELD_BASE(7, 7, 4, 0x20, 0x10, 0, 1),
PIN_FIELD_BASE(8, 8, 4, 0x20, 0x10, 4, 1),
PIN_FIELD_BASE(9, 9, 5, 0x20, 0x10, 9, 1),
PIN_FIELD_BASE(10, 10, 5, 0x20, 0x10, 8, 1),
PIN_FIELD_BASE(11, 11, 5, 0x40, 0x10, 10, 1),
PIN_FIELD_BASE(12, 12, 5, 0x20, 0x10, 7, 1),
PIN_FIELD_BASE(13, 13, 5, 0x20, 0x10, 11, 1),
PIN_FIELD_BASE(14, 14, 4, 0x20, 0x10, 8, 1),
PIN_FIELD_BASE(15, 15, 2, 0x20, 0x10, 0, 1),
PIN_FIELD_BASE(16, 16, 2, 0x20, 0x10, 1, 1),
PIN_FIELD_BASE(17, 17, 2, 0x20, 0x10, 5, 1),
PIN_FIELD_BASE(18, 18, 2, 0x20, 0x10, 4, 1),
PIN_FIELD_BASE(19, 19, 2, 0x20, 0x10, 2, 1),
PIN_FIELD_BASE(20, 20, 2, 0x20, 0x10, 3, 1),
PIN_FIELD_BASE(21, 21, 2, 0x20, 0x10, 6, 1),
PIN_FIELD_BASE(22, 22, 2, 0x20, 0x10, 7, 1),
PIN_FIELD_BASE(23, 23, 2, 0x20, 0x10, 10, 1),
PIN_FIELD_BASE(24, 24, 2, 0x20, 0x10, 9, 1),
PIN_FIELD_BASE(25, 25, 2, 0x20, 0x10, 8, 1),
PIN_FIELD_BASE(26, 26, 5, 0x20, 0x10, 0, 1),
PIN_FIELD_BASE(27, 27, 5, 0x20, 0x10, 4, 1),
PIN_FIELD_BASE(28, 28, 5, 0x20, 0x10, 3, 1),
PIN_FIELD_BASE(29, 29, 5, 0x20, 0x10, 1, 1),
PIN_FIELD_BASE(30, 30, 5, 0x20, 0x10, 2, 1),
PIN_FIELD_BASE(31, 31, 5, 0x20, 0x10, 5, 1),
PIN_FIELD_BASE(32, 32, 1, 0x10, 0x10, 2, 1),
PIN_FIELD_BASE(33, 33, 1, 0x10, 0x10, 3, 1),
PIN_FIELD_BASE(34, 34, 4, 0x20, 0x10, 5, 1),
PIN_FIELD_BASE(35, 35, 4, 0x20, 0x10, 7, 1),
PIN_FIELD_BASE(36, 36, 3, 0x10, 0x10, 2, 1),
PIN_FIELD_BASE(37, 37, 3, 0x10, 0x10, 3, 1),
PIN_FIELD_BASE(38, 38, 3, 0x10, 0x10, 0, 1),
PIN_FIELD_BASE(39, 39, 3, 0x10, 0x10, 1, 1),
PIN_FIELD_BASE(40, 40, 7, 0x30, 0x10, 1, 1),
PIN_FIELD_BASE(41, 41, 7, 0x30, 0x10, 0, 1),
PIN_FIELD_BASE(42, 42, 7, 0x30, 0x10, 9, 1),
PIN_FIELD_BASE(43, 43, 7, 0x30, 0x10, 7, 1),
PIN_FIELD_BASE(44, 44, 7, 0x30, 0x10, 8, 1),
PIN_FIELD_BASE(45, 45, 7, 0x30, 0x10, 3, 1),
PIN_FIELD_BASE(46, 46, 7, 0x30, 0x10, 4, 1),
PIN_FIELD_BASE(47, 47, 7, 0x30, 0x10, 5, 1),
PIN_FIELD_BASE(48, 48, 7, 0x30, 0x10, 6, 1),
PIN_FIELD_BASE(49, 49, 7, 0x30, 0x10, 2, 1),
PIN_FIELD_BASE(50, 50, 6, 0x10, 0x10, 0, 1),
PIN_FIELD_BASE(51, 51, 6, 0x10, 0x10, 2, 1),
PIN_FIELD_BASE(52, 52, 6, 0x10, 0x10, 3, 1),
PIN_FIELD_BASE(53, 53, 6, 0x10, 0x10, 4, 1),
PIN_FIELD_BASE(54, 54, 6, 0x10, 0x10, 5, 1),
PIN_FIELD_BASE(55, 55, 6, 0x10, 0x10, 6, 1),
PIN_FIELD_BASE(56, 56, 6, 0x10, 0x10, 1, 1),
};
static const struct mtk_pin_field_calc mt7981_pin_smt_range[] = {
PIN_FIELD_BASE(0, 0, 1, 0x60, 0x10, 1, 1),
PIN_FIELD_BASE(1, 1, 1, 0x60, 0x10, 0, 1),
PIN_FIELD_BASE(2, 2, 5, 0x90, 0x10, 6, 1),
PIN_FIELD_BASE(3, 3, 4, 0x80, 0x10, 6, 1),
PIN_FIELD_BASE(4, 4, 4, 0x80, 0x10, 2, 1),
PIN_FIELD_BASE(5, 5, 4, 0x80, 0x10, 1, 1),
PIN_FIELD_BASE(6, 6, 4, 0x80, 0x10, 3, 1),
PIN_FIELD_BASE(7, 7, 4, 0x80, 0x10, 0, 1),
PIN_FIELD_BASE(8, 8, 4, 0x80, 0x10, 4, 1),
PIN_FIELD_BASE(9, 9, 5, 0x90, 0x10, 9, 1),
PIN_FIELD_BASE(10, 10, 5, 0x90, 0x10, 8, 1),
PIN_FIELD_BASE(11, 11, 5, 0x90, 0x10, 10, 1),
PIN_FIELD_BASE(12, 12, 5, 0x90, 0x10, 7, 1),
PIN_FIELD_BASE(13, 13, 5, 0x90, 0x10, 11, 1),
PIN_FIELD_BASE(14, 14, 4, 0x80, 0x10, 8, 1),
PIN_FIELD_BASE(15, 15, 2, 0x90, 0x10, 0, 1),
PIN_FIELD_BASE(16, 16, 2, 0x90, 0x10, 1, 1),
PIN_FIELD_BASE(17, 17, 2, 0x90, 0x10, 5, 1),
PIN_FIELD_BASE(18, 18, 2, 0x90, 0x10, 4, 1),
PIN_FIELD_BASE(19, 19, 2, 0x90, 0x10, 2, 1),
PIN_FIELD_BASE(20, 20, 2, 0x90, 0x10, 3, 1),
PIN_FIELD_BASE(21, 21, 2, 0x90, 0x10, 6, 1),
PIN_FIELD_BASE(22, 22, 2, 0x90, 0x10, 7, 1),
PIN_FIELD_BASE(23, 23, 2, 0x90, 0x10, 10, 1),
PIN_FIELD_BASE(24, 24, 2, 0x90, 0x10, 9, 1),
PIN_FIELD_BASE(25, 25, 2, 0x90, 0x10, 8, 1),
PIN_FIELD_BASE(26, 26, 5, 0x90, 0x10, 0, 1),
PIN_FIELD_BASE(27, 27, 5, 0x90, 0x10, 4, 1),
PIN_FIELD_BASE(28, 28, 5, 0x90, 0x10, 3, 1),
PIN_FIELD_BASE(29, 29, 5, 0x90, 0x10, 1, 1),
PIN_FIELD_BASE(30, 30, 5, 0x90, 0x10, 2, 1),
PIN_FIELD_BASE(31, 31, 5, 0x90, 0x10, 5, 1),
PIN_FIELD_BASE(32, 32, 1, 0x60, 0x10, 2, 1),
PIN_FIELD_BASE(33, 33, 1, 0x60, 0x10, 3, 1),
PIN_FIELD_BASE(34, 34, 4, 0x80, 0x10, 5, 1),
PIN_FIELD_BASE(35, 35, 4, 0x80, 0x10, 7, 1),
PIN_FIELD_BASE(36, 36, 3, 0x60, 0x10, 2, 1),
PIN_FIELD_BASE(37, 37, 3, 0x60, 0x10, 3, 1),
PIN_FIELD_BASE(38, 38, 3, 0x60, 0x10, 0, 1),
PIN_FIELD_BASE(39, 39, 3, 0x60, 0x10, 1, 1),
PIN_FIELD_BASE(40, 40, 7, 0x70, 0x10, 1, 1),
PIN_FIELD_BASE(41, 41, 7, 0x70, 0x10, 0, 1),
PIN_FIELD_BASE(42, 42, 7, 0x70, 0x10, 9, 1),
PIN_FIELD_BASE(43, 43, 7, 0x70, 0x10, 7, 1),
PIN_FIELD_BASE(44, 44, 7, 0x30, 0x10, 8, 1),
PIN_FIELD_BASE(45, 45, 7, 0x70, 0x10, 3, 1),
PIN_FIELD_BASE(46, 46, 7, 0x70, 0x10, 4, 1),
PIN_FIELD_BASE(47, 47, 7, 0x70, 0x10, 5, 1),
PIN_FIELD_BASE(48, 48, 7, 0x70, 0x10, 6, 1),
PIN_FIELD_BASE(49, 49, 7, 0x70, 0x10, 2, 1),
PIN_FIELD_BASE(50, 50, 6, 0x50, 0x10, 0, 1),
PIN_FIELD_BASE(51, 51, 6, 0x50, 0x10, 2, 1),
PIN_FIELD_BASE(52, 52, 6, 0x50, 0x10, 3, 1),
PIN_FIELD_BASE(53, 53, 6, 0x50, 0x10, 4, 1),
PIN_FIELD_BASE(54, 54, 6, 0x50, 0x10, 5, 1),
PIN_FIELD_BASE(55, 55, 6, 0x50, 0x10, 6, 1),
PIN_FIELD_BASE(56, 56, 6, 0x50, 0x10, 1, 1),
};
static const struct mtk_pin_field_calc mt7981_pin_pu_range[] = {
PIN_FIELD_BASE(40, 40, 7, 0x50, 0x10, 1, 1),
PIN_FIELD_BASE(41, 41, 7, 0x50, 0x10, 0, 1),
PIN_FIELD_BASE(42, 42, 7, 0x50, 0x10, 9, 1),
PIN_FIELD_BASE(43, 43, 7, 0x50, 0x10, 7, 1),
PIN_FIELD_BASE(44, 44, 7, 0x50, 0x10, 8, 1),
PIN_FIELD_BASE(45, 45, 7, 0x50, 0x10, 3, 1),
PIN_FIELD_BASE(46, 46, 7, 0x50, 0x10, 4, 1),
PIN_FIELD_BASE(47, 47, 7, 0x50, 0x10, 5, 1),
PIN_FIELD_BASE(48, 48, 7, 0x50, 0x10, 6, 1),
PIN_FIELD_BASE(49, 49, 7, 0x50, 0x10, 2, 1),
PIN_FIELD_BASE(50, 50, 6, 0x30, 0x10, 0, 1),
PIN_FIELD_BASE(51, 51, 6, 0x30, 0x10, 2, 1),
PIN_FIELD_BASE(52, 52, 6, 0x30, 0x10, 3, 1),
PIN_FIELD_BASE(53, 53, 6, 0x30, 0x10, 4, 1),
PIN_FIELD_BASE(54, 54, 6, 0x30, 0x10, 5, 1),
PIN_FIELD_BASE(55, 55, 6, 0x30, 0x10, 6, 1),
PIN_FIELD_BASE(56, 56, 6, 0x30, 0x10, 1, 1),
};
static const struct mtk_pin_field_calc mt7981_pin_pd_range[] = {
PIN_FIELD_BASE(40, 40, 7, 0x40, 0x10, 1, 1),
PIN_FIELD_BASE(41, 41, 7, 0x40, 0x10, 0, 1),
PIN_FIELD_BASE(42, 42, 7, 0x40, 0x10, 9, 1),
PIN_FIELD_BASE(43, 43, 7, 0x40, 0x10, 7, 1),
PIN_FIELD_BASE(44, 44, 7, 0x40, 0x10, 8, 1),
PIN_FIELD_BASE(45, 45, 7, 0x40, 0x10, 3, 1),
PIN_FIELD_BASE(46, 46, 7, 0x40, 0x10, 4, 1),
PIN_FIELD_BASE(47, 47, 7, 0x40, 0x10, 5, 1),
PIN_FIELD_BASE(48, 48, 7, 0x40, 0x10, 6, 1),
PIN_FIELD_BASE(49, 49, 7, 0x40, 0x10, 2, 1),
PIN_FIELD_BASE(50, 50, 6, 0x20, 0x10, 0, 1),
PIN_FIELD_BASE(51, 51, 6, 0x20, 0x10, 2, 1),
PIN_FIELD_BASE(52, 52, 6, 0x20, 0x10, 3, 1),
PIN_FIELD_BASE(53, 53, 6, 0x20, 0x10, 4, 1),
PIN_FIELD_BASE(54, 54, 6, 0x20, 0x10, 5, 1),
PIN_FIELD_BASE(55, 55, 6, 0x20, 0x10, 6, 1),
PIN_FIELD_BASE(56, 56, 6, 0x20, 0x10, 1, 1),
};
static const struct mtk_pin_field_calc mt7981_pin_drv_range[] = {
PIN_FIELD_BASE(0, 0, 1, 0x00, 0x10, 3, 3),
PIN_FIELD_BASE(1, 1, 1, 0x00, 0x10, 0, 3),
PIN_FIELD_BASE(2, 2, 5, 0x00, 0x10, 18, 3),
PIN_FIELD_BASE(3, 3, 4, 0x00, 0x10, 18, 1),
PIN_FIELD_BASE(4, 4, 4, 0x00, 0x10, 6, 1),
PIN_FIELD_BASE(5, 5, 4, 0x00, 0x10, 3, 3),
PIN_FIELD_BASE(6, 6, 4, 0x00, 0x10, 9, 3),
PIN_FIELD_BASE(7, 7, 4, 0x00, 0x10, 0, 3),
PIN_FIELD_BASE(8, 8, 4, 0x00, 0x10, 12, 3),
PIN_FIELD_BASE(9, 9, 5, 0x00, 0x10, 27, 3),
PIN_FIELD_BASE(10, 10, 5, 0x00, 0x10, 24, 3),
PIN_FIELD_BASE(11, 11, 5, 0x00, 0x10, 0, 3),
PIN_FIELD_BASE(12, 12, 5, 0x00, 0x10, 21, 3),
PIN_FIELD_BASE(13, 13, 5, 0x00, 0x10, 3, 3),
PIN_FIELD_BASE(14, 14, 4, 0x00, 0x10, 27, 3),
PIN_FIELD_BASE(15, 15, 2, 0x00, 0x10, 0, 3),
PIN_FIELD_BASE(16, 16, 2, 0x00, 0x10, 3, 3),
PIN_FIELD_BASE(17, 17, 2, 0x00, 0x10, 15, 3),
PIN_FIELD_BASE(18, 18, 2, 0x00, 0x10, 12, 3),
PIN_FIELD_BASE(19, 19, 2, 0x00, 0x10, 6, 3),
PIN_FIELD_BASE(20, 20, 2, 0x00, 0x10, 9, 3),
PIN_FIELD_BASE(21, 21, 2, 0x00, 0x10, 18, 3),
PIN_FIELD_BASE(22, 22, 2, 0x00, 0x10, 21, 3),
PIN_FIELD_BASE(23, 23, 2, 0x00, 0x10, 0, 3),
PIN_FIELD_BASE(24, 24, 2, 0x00, 0x10, 27, 3),
PIN_FIELD_BASE(25, 25, 2, 0x00, 0x10, 24, 3),
PIN_FIELD_BASE(26, 26, 5, 0x00, 0x10, 0, 3),
PIN_FIELD_BASE(27, 27, 5, 0x00, 0x10, 12, 3),
PIN_FIELD_BASE(28, 28, 5, 0x00, 0x10, 9, 3),
PIN_FIELD_BASE(29, 29, 5, 0x00, 0x10, 3, 3),
PIN_FIELD_BASE(30, 30, 5, 0x00, 0x10, 6, 3),
PIN_FIELD_BASE(31, 31, 5, 0x00, 0x10, 15, 3),
PIN_FIELD_BASE(32, 32, 1, 0x00, 0x10, 9, 3),
PIN_FIELD_BASE(33, 33, 1, 0x00, 0x10, 12, 3),
PIN_FIELD_BASE(34, 34, 4, 0x00, 0x10, 15, 3),
PIN_FIELD_BASE(35, 35, 4, 0x00, 0x10, 21, 3),
PIN_FIELD_BASE(36, 36, 3, 0x00, 0x10, 6, 3),
PIN_FIELD_BASE(37, 37, 3, 0x00, 0x10, 9, 3),
PIN_FIELD_BASE(38, 38, 3, 0x00, 0x10, 0, 3),
PIN_FIELD_BASE(39, 39, 3, 0x00, 0x10, 3, 3),
PIN_FIELD_BASE(40, 40, 7, 0x00, 0x10, 3, 3),
PIN_FIELD_BASE(41, 41, 7, 0x00, 0x10, 0, 3),
PIN_FIELD_BASE(42, 42, 7, 0x00, 0x10, 27, 3),
PIN_FIELD_BASE(43, 43, 7, 0x00, 0x10, 21, 3),
PIN_FIELD_BASE(44, 44, 7, 0x00, 0x10, 24, 3),
PIN_FIELD_BASE(45, 45, 7, 0x00, 0x10, 9, 3),
PIN_FIELD_BASE(46, 46, 7, 0x00, 0x10, 12, 3),
PIN_FIELD_BASE(47, 47, 7, 0x00, 0x10, 15, 3),
PIN_FIELD_BASE(48, 48, 7, 0x00, 0x10, 18, 3),
PIN_FIELD_BASE(49, 49, 7, 0x00, 0x10, 6, 3),
PIN_FIELD_BASE(50, 50, 6, 0x00, 0x10, 0, 3),
PIN_FIELD_BASE(51, 51, 6, 0x00, 0x10, 6, 3),
PIN_FIELD_BASE(52, 52, 6, 0x00, 0x10, 9, 3),
PIN_FIELD_BASE(53, 53, 6, 0x00, 0x10, 12, 3),
PIN_FIELD_BASE(54, 54, 6, 0x00, 0x10, 15, 3),
PIN_FIELD_BASE(55, 55, 6, 0x00, 0x10, 18, 3),
PIN_FIELD_BASE(56, 56, 6, 0x00, 0x10, 3, 3),
};
static const struct mtk_pin_field_calc mt7981_pin_pupd_range[] = {
PIN_FIELD_BASE(0, 0, 1, 0x20, 0x10, 1, 1),
PIN_FIELD_BASE(1, 1, 1, 0x20, 0x10, 0, 1),
PIN_FIELD_BASE(2, 2, 5, 0x30, 0x10, 6, 1),
PIN_FIELD_BASE(3, 3, 4, 0x30, 0x10, 6, 1),
PIN_FIELD_BASE(4, 4, 4, 0x30, 0x10, 2, 1),
PIN_FIELD_BASE(5, 5, 4, 0x30, 0x10, 1, 1),
PIN_FIELD_BASE(6, 6, 4, 0x30, 0x10, 3, 1),
PIN_FIELD_BASE(7, 7, 4, 0x30, 0x10, 0, 1),
PIN_FIELD_BASE(8, 8, 4, 0x30, 0x10, 4, 1),
PIN_FIELD_BASE(9, 9, 5, 0x30, 0x10, 9, 1),
PIN_FIELD_BASE(10, 10, 5, 0x30, 0x10, 8, 1),
PIN_FIELD_BASE(11, 11, 5, 0x30, 0x10, 10, 1),
PIN_FIELD_BASE(12, 12, 5, 0x30, 0x10, 7, 1),
PIN_FIELD_BASE(13, 13, 5, 0x30, 0x10, 11, 1),
PIN_FIELD_BASE(14, 14, 4, 0x30, 0x10, 8, 1),
PIN_FIELD_BASE(15, 15, 2, 0x30, 0x10, 0, 1),
PIN_FIELD_BASE(16, 16, 2, 0x30, 0x10, 1, 1),
PIN_FIELD_BASE(17, 17, 2, 0x30, 0x10, 5, 1),
PIN_FIELD_BASE(18, 18, 2, 0x30, 0x10, 4, 1),
PIN_FIELD_BASE(19, 19, 2, 0x30, 0x10, 2, 1),
PIN_FIELD_BASE(20, 20, 2, 0x90, 0x10, 3, 1),
PIN_FIELD_BASE(21, 21, 2, 0x30, 0x10, 6, 1),
PIN_FIELD_BASE(22, 22, 2, 0x30, 0x10, 7, 1),
PIN_FIELD_BASE(23, 23, 2, 0x30, 0x10, 10, 1),
PIN_FIELD_BASE(24, 24, 2, 0x30, 0x10, 9, 1),
PIN_FIELD_BASE(25, 25, 2, 0x30, 0x10, 8, 1),
PIN_FIELD_BASE(26, 26, 5, 0x30, 0x10, 0, 1),
PIN_FIELD_BASE(27, 27, 5, 0x30, 0x10, 4, 1),
PIN_FIELD_BASE(28, 28, 5, 0x30, 0x10, 3, 1),
PIN_FIELD_BASE(29, 29, 5, 0x30, 0x10, 1, 1),
PIN_FIELD_BASE(30, 30, 5, 0x30, 0x10, 2, 1),
PIN_FIELD_BASE(31, 31, 5, 0x30, 0x10, 5, 1),
PIN_FIELD_BASE(32, 32, 1, 0x20, 0x10, 2, 1),
PIN_FIELD_BASE(33, 33, 1, 0x20, 0x10, 3, 1),
PIN_FIELD_BASE(34, 34, 4, 0x30, 0x10, 5, 1),
PIN_FIELD_BASE(35, 35, 4, 0x30, 0x10, 7, 1),
PIN_FIELD_BASE(36, 36, 3, 0x20, 0x10, 2, 1),
PIN_FIELD_BASE(37, 37, 3, 0x20, 0x10, 3, 1),
PIN_FIELD_BASE(38, 38, 3, 0x20, 0x10, 0, 1),
PIN_FIELD_BASE(39, 39, 3, 0x20, 0x10, 1, 1),
};
static const struct mtk_pin_field_calc mt7981_pin_r0_range[] = {
PIN_FIELD_BASE(0, 0, 1, 0x30, 0x10, 1, 1),
PIN_FIELD_BASE(1, 1, 1, 0x30, 0x10, 0, 1),
PIN_FIELD_BASE(2, 2, 5, 0x40, 0x10, 6, 1),
PIN_FIELD_BASE(3, 3, 4, 0x40, 0x10, 6, 1),
PIN_FIELD_BASE(4, 4, 4, 0x40, 0x10, 2, 1),
PIN_FIELD_BASE(5, 5, 4, 0x40, 0x10, 1, 1),
PIN_FIELD_BASE(6, 6, 4, 0x40, 0x10, 3, 1),
PIN_FIELD_BASE(7, 7, 4, 0x40, 0x10, 0, 1),
PIN_FIELD_BASE(8, 8, 4, 0x40, 0x10, 4, 1),
PIN_FIELD_BASE(9, 9, 5, 0x40, 0x10, 9, 1),
PIN_FIELD_BASE(10, 10, 5, 0x40, 0x10, 8, 1),
PIN_FIELD_BASE(11, 11, 5, 0x40, 0x10, 10, 1),
PIN_FIELD_BASE(12, 12, 5, 0x40, 0x10, 7, 1),
PIN_FIELD_BASE(13, 13, 5, 0x40, 0x10, 11, 1),
PIN_FIELD_BASE(14, 14, 4, 0x40, 0x10, 8, 1),
PIN_FIELD_BASE(15, 15, 2, 0x40, 0x10, 0, 1),
PIN_FIELD_BASE(16, 16, 2, 0x40, 0x10, 1, 1),
PIN_FIELD_BASE(17, 17, 2, 0x40, 0x10, 5, 1),
PIN_FIELD_BASE(18, 18, 2, 0x40, 0x10, 4, 1),
PIN_FIELD_BASE(19, 19, 2, 0x40, 0x10, 2, 1),
PIN_FIELD_BASE(20, 20, 2, 0x40, 0x10, 3, 1),
PIN_FIELD_BASE(21, 21, 2, 0x40, 0x10, 6, 1),
PIN_FIELD_BASE(22, 22, 2, 0x40, 0x10, 7, 1),
PIN_FIELD_BASE(23, 23, 2, 0x40, 0x10, 10, 1),
PIN_FIELD_BASE(24, 24, 2, 0x40, 0x10, 9, 1),
PIN_FIELD_BASE(25, 25, 2, 0x40, 0x10, 8, 1),
PIN_FIELD_BASE(26, 26, 5, 0x40, 0x10, 0, 1),
PIN_FIELD_BASE(27, 27, 5, 0x40, 0x10, 4, 1),
PIN_FIELD_BASE(28, 28, 5, 0x40, 0x10, 3, 1),
PIN_FIELD_BASE(29, 29, 5, 0x40, 0x10, 1, 1),
PIN_FIELD_BASE(30, 30, 5, 0x40, 0x10, 2, 1),
PIN_FIELD_BASE(31, 31, 5, 0x40, 0x10, 5, 1),
PIN_FIELD_BASE(32, 32, 1, 0x30, 0x10, 2, 1),
PIN_FIELD_BASE(33, 33, 1, 0x30, 0x10, 3, 1),
PIN_FIELD_BASE(34, 34, 4, 0x40, 0x10, 5, 1),
PIN_FIELD_BASE(35, 35, 4, 0x40, 0x10, 7, 1),
PIN_FIELD_BASE(36, 36, 3, 0x30, 0x10, 2, 1),
PIN_FIELD_BASE(37, 37, 3, 0x30, 0x10, 3, 1),
PIN_FIELD_BASE(38, 38, 3, 0x30, 0x10, 0, 1),
PIN_FIELD_BASE(39, 39, 3, 0x30, 0x10, 1, 1),
};
static const struct mtk_pin_field_calc mt7981_pin_r1_range[] = {
PIN_FIELD_BASE(0, 0, 1, 0x40, 0x10, 1, 1),
PIN_FIELD_BASE(1, 1, 1, 0x40, 0x10, 0, 1),
PIN_FIELD_BASE(2, 2, 5, 0x50, 0x10, 6, 1),
PIN_FIELD_BASE(3, 3, 4, 0x50, 0x10, 6, 1),
PIN_FIELD_BASE(4, 4, 4, 0x50, 0x10, 2, 1),
PIN_FIELD_BASE(5, 5, 4, 0x50, 0x10, 1, 1),
PIN_FIELD_BASE(6, 6, 4, 0x50, 0x10, 3, 1),
PIN_FIELD_BASE(7, 7, 4, 0x50, 0x10, 0, 1),
PIN_FIELD_BASE(8, 8, 4, 0x50, 0x10, 4, 1),
PIN_FIELD_BASE(9, 9, 5, 0x50, 0x10, 9, 1),
PIN_FIELD_BASE(10, 10, 5, 0x50, 0x10, 8, 1),
PIN_FIELD_BASE(11, 11, 5, 0x50, 0x10, 10, 1),
PIN_FIELD_BASE(12, 12, 5, 0x50, 0x10, 7, 1),
PIN_FIELD_BASE(13, 13, 5, 0x50, 0x10, 11, 1),
PIN_FIELD_BASE(14, 14, 4, 0x50, 0x10, 8, 1),
PIN_FIELD_BASE(15, 15, 2, 0x50, 0x10, 0, 1),
PIN_FIELD_BASE(16, 16, 2, 0x50, 0x10, 1, 1),
PIN_FIELD_BASE(17, 17, 2, 0x50, 0x10, 5, 1),
PIN_FIELD_BASE(18, 18, 2, 0x50, 0x10, 4, 1),
PIN_FIELD_BASE(19, 19, 2, 0x50, 0x10, 2, 1),
PIN_FIELD_BASE(20, 20, 2, 0x50, 0x10, 3, 1),
PIN_FIELD_BASE(21, 21, 2, 0x50, 0x10, 6, 1),
PIN_FIELD_BASE(22, 22, 2, 0x50, 0x10, 7, 1),
PIN_FIELD_BASE(23, 23, 2, 0x50, 0x10, 10, 1),
PIN_FIELD_BASE(24, 24, 2, 0x50, 0x10, 9, 1),
PIN_FIELD_BASE(25, 25, 2, 0x50, 0x10, 8, 1),
PIN_FIELD_BASE(26, 26, 5, 0x50, 0x10, 0, 1),
PIN_FIELD_BASE(27, 27, 5, 0x50, 0x10, 4, 1),
PIN_FIELD_BASE(28, 28, 5, 0x50, 0x10, 3, 1),
PIN_FIELD_BASE(29, 29, 5, 0x50, 0x10, 1, 1),
PIN_FIELD_BASE(30, 30, 5, 0x50, 0x10, 2, 1),
PIN_FIELD_BASE(31, 31, 5, 0x50, 0x10, 5, 1),
PIN_FIELD_BASE(32, 32, 1, 0x40, 0x10, 2, 1),
PIN_FIELD_BASE(33, 33, 1, 0x40, 0x10, 3, 1),
PIN_FIELD_BASE(34, 34, 4, 0x50, 0x10, 5, 1),
PIN_FIELD_BASE(35, 35, 4, 0x50, 0x10, 7, 1),
PIN_FIELD_BASE(36, 36, 3, 0x40, 0x10, 2, 1),
PIN_FIELD_BASE(37, 37, 3, 0x40, 0x10, 3, 1),
PIN_FIELD_BASE(38, 38, 3, 0x40, 0x10, 0, 1),
PIN_FIELD_BASE(39, 39, 3, 0x40, 0x10, 1, 1),
};
static const struct mtk_pin_reg_calc mt7981_reg_cals[] = {
[PINCTRL_PIN_REG_MODE] = MTK_RANGE(mt7981_pin_mode_range),
[PINCTRL_PIN_REG_DIR] = MTK_RANGE(mt7981_pin_dir_range),
[PINCTRL_PIN_REG_DI] = MTK_RANGE(mt7981_pin_di_range),
[PINCTRL_PIN_REG_DO] = MTK_RANGE(mt7981_pin_do_range),
[PINCTRL_PIN_REG_SMT] = MTK_RANGE(mt7981_pin_smt_range),
[PINCTRL_PIN_REG_IES] = MTK_RANGE(mt7981_pin_ies_range),
[PINCTRL_PIN_REG_PU] = MTK_RANGE(mt7981_pin_pu_range),
[PINCTRL_PIN_REG_PD] = MTK_RANGE(mt7981_pin_pd_range),
[PINCTRL_PIN_REG_DRV] = MTK_RANGE(mt7981_pin_drv_range),
[PINCTRL_PIN_REG_PUPD] = MTK_RANGE(mt7981_pin_pupd_range),
[PINCTRL_PIN_REG_R0] = MTK_RANGE(mt7981_pin_r0_range),
[PINCTRL_PIN_REG_R1] = MTK_RANGE(mt7981_pin_r1_range),
};
static const struct mtk_pin_desc mt7981_pins[] = {
MT7981_PIN(0, "GPIO_WPS"),
MT7981_PIN(1, "GPIO_RESET"),
MT7981_PIN(2, "SYS_WATCHDOG"),
MT7981_PIN(3, "PCIE_PERESET_N"),
MT7981_PIN(4, "JTAG_JTDO"),
MT7981_PIN(5, "JTAG_JTDI"),
MT7981_PIN(6, "JTAG_JTMS"),
MT7981_PIN(7, "JTAG_JTCLK"),
MT7981_PIN(8, "JTAG_JTRST_N"),
MT7981_PIN(9, "WO_JTAG_JTDO"),
MT7981_PIN(10, "WO_JTAG_JTDI"),
MT7981_PIN(11, "WO_JTAG_JTMS"),
MT7981_PIN(12, "WO_JTAG_JTCLK"),
MT7981_PIN(13, "WO_JTAG_JTRST_N"),
MT7981_PIN(14, "USB_VBUS"),
MT7981_PIN(15, "PWM0"),
MT7981_PIN(16, "SPI0_CLK"),
MT7981_PIN(17, "SPI0_MOSI"),
MT7981_PIN(18, "SPI0_MISO"),
MT7981_PIN(19, "SPI0_CS"),
MT7981_PIN(20, "SPI0_HOLD"),
MT7981_PIN(21, "SPI0_WP"),
MT7981_PIN(22, "SPI1_CLK"),
MT7981_PIN(23, "SPI1_MOSI"),
MT7981_PIN(24, "SPI1_MISO"),
MT7981_PIN(25, "SPI1_CS"),
MT7981_PIN(26, "SPI2_CLK"),
MT7981_PIN(27, "SPI2_MOSI"),
MT7981_PIN(28, "SPI2_MISO"),
MT7981_PIN(29, "SPI2_CS"),
MT7981_PIN(30, "SPI2_HOLD"),
MT7981_PIN(31, "SPI2_WP"),
MT7981_PIN(32, "UART0_RXD"),
MT7981_PIN(33, "UART0_TXD"),
MT7981_PIN(34, "PCIE_CLK_REQ"),
MT7981_PIN(35, "PCIE_WAKE_N"),
MT7981_PIN(36, "SMI_MDC"),
MT7981_PIN(37, "SMI_MDIO"),
MT7981_PIN(38, "GBE_INT"),
MT7981_PIN(39, "GBE_RESET"),
MT7981_PIN(40, "WF_DIG_RESETB"),
MT7981_PIN(41, "WF_CBA_RESETB"),
MT7981_PIN(42, "WF_XO_REQ"),
MT7981_PIN(43, "WF_TOP_CLK"),
MT7981_PIN(44, "WF_TOP_DATA"),
MT7981_PIN(45, "WF_HB1"),
MT7981_PIN(46, "WF_HB2"),
MT7981_PIN(47, "WF_HB3"),
MT7981_PIN(48, "WF_HB4"),
MT7981_PIN(49, "WF_HB0"),
MT7981_PIN(50, "WF_HB0_B"),
MT7981_PIN(51, "WF_HB5"),
MT7981_PIN(52, "WF_HB6"),
MT7981_PIN(53, "WF_HB7"),
MT7981_PIN(54, "WF_HB8"),
MT7981_PIN(55, "WF_HB9"),
MT7981_PIN(56, "WF_HB10"),
};
/* List all groups consisting of these pins dedicated to the enablement of
* certain hardware block and the corresponding mode for all of the pins.
* The hardware probably has multiple combinations of these pinouts.
*/
/* WA_AICE */
static int mt7981_wa_aice1_pins[] = { 0, 1, };
static int mt7981_wa_aice1_funcs[] = { 2, 2, };
static int mt7981_wa_aice2_pins[] = { 0, 1, };
static int mt7981_wa_aice2_funcs[] = { 3, 3, };
static int mt7981_wa_aice3_pins[] = { 28, 29, };
static int mt7981_wa_aice3_funcs[] = { 3, 3, };
static int mt7981_wm_aice1_pins[] = { 9, 10, };
static int mt7981_wm_aice1_funcs[] = { 2, 2, };
static int mt7981_wm_aice2_pins[] = { 30, 31, };
static int mt7981_wm_aice2_funcs[] = { 5, 5, };
/* WM_UART */
static int mt7981_wm_uart_0_pins[] = { 0, 1, };
static int mt7981_wm_uart_0_funcs[] = { 5, 5, };
static int mt7981_wm_uart_1_pins[] = { 20, 21, };
static int mt7981_wm_uart_1_funcs[] = { 4, 4, };
static int mt7981_wm_uart_2_pins[] = { 30, 31, };
static int mt7981_wm_uart_2_funcs[] = { 3, 3, };
/* DFD */
static int mt7981_dfd_pins[] = { 0, 1, 4, 5, };
static int mt7981_dfd_funcs[] = { 5, 5, 6, 6, };
/* SYS_WATCHDOG */
static int mt7981_watchdog_pins[] = { 2, };
static int mt7981_watchdog_funcs[] = { 1, };
static int mt7981_watchdog1_pins[] = { 13, };
static int mt7981_watchdog1_funcs[] = { 5, };
/* PCIE_PERESET_N */
static int mt7981_pcie_pereset_pins[] = { 3, };
static int mt7981_pcie_pereset_funcs[] = { 1, };
/* JTAG */
static int mt7981_jtag_pins[] = { 4, 5, 6, 7, 8, };
static int mt7981_jtag_funcs[] = { 1, 1, 1, 1, 1, };
/* WM_JTAG */
static int mt7981_wm_jtag_0_pins[] = { 4, 5, 6, 7, 8, };
static int mt7981_wm_jtag_0_funcs[] = { 2, 2, 2, 2, 2, };
static int mt7981_wm_jtag_1_pins[] = { 20, 21, 22, 23, 24, };
static int mt7981_wm_jtag_1_funcs[] = { 5, 5, 5, 5, 5, };
/* WO0_JTAG */
static int mt7981_wo0_jtag_0_pins[] = { 9, 10, 11, 12, 13, };
static int mt7981_wo0_jtag_0_funcs[] = { 1, 1, 1, 1, 1, };
static int mt7981_wo0_jtag_1_pins[] = { 25, 26, 27, 28, 29, };
static int mt7981_wo0_jtag_1_funcs[] = { 5, 5, 5, 5, 5, };
/* UART2 */
static int mt7981_uart2_0_pins[] = { 4, 5, 6, 7, };
static int mt7981_uart2_0_funcs[] = { 3, 3, 3, 3, };
/* GBE_LED0 */
static int mt7981_gbe_led0_pins[] = { 8, };
static int mt7981_gbe_led0_funcs[] = { 3, };
/* PTA_EXT */
static int mt7981_pta_ext_0_pins[] = { 4, 5, 6, };
static int mt7981_pta_ext_0_funcs[] = { 4, 4, 4, };
static int mt7981_pta_ext_1_pins[] = { 22, 23, 24, };
static int mt7981_pta_ext_1_funcs[] = { 4, 4, 4, };
/* PWM2 */
static int mt7981_pwm2_pins[] = { 7, };
static int mt7981_pwm2_funcs[] = { 4, };
/* NET_WO0_UART_TXD */
static int mt7981_net_wo0_uart_txd_0_pins[] = { 8, };
static int mt7981_net_wo0_uart_txd_0_funcs[] = { 4, };
static int mt7981_net_wo0_uart_txd_1_pins[] = { 14, };
static int mt7981_net_wo0_uart_txd_1_funcs[] = { 3, };
static int mt7981_net_wo0_uart_txd_2_pins[] = { 15, };
static int mt7981_net_wo0_uart_txd_2_funcs[] = { 4, };
/* SPI1 */
static int mt7981_spi1_0_pins[] = { 4, 5, 6, 7, };
static int mt7981_spi1_0_funcs[] = { 5, 5, 5, 5, };
/* I2C */
static int mt7981_i2c0_0_pins[] = { 6, 7, };
static int mt7981_i2c0_0_funcs[] = { 6, 6, };
static int mt7981_i2c0_1_pins[] = { 30, 31, };
static int mt7981_i2c0_1_funcs[] = { 4, 4, };
static int mt7981_i2c0_2_pins[] = { 36, 37, };
static int mt7981_i2c0_2_funcs[] = { 2, 2, };
static int mt7981_u2_phy_i2c_pins[] = { 30, 31, };
static int mt7981_u2_phy_i2c_funcs[] = { 6, 6, };
static int mt7981_u3_phy_i2c_pins[] = { 32, 33, };
static int mt7981_u3_phy_i2c_funcs[] = { 3, 3, };
static int mt7981_sgmii1_phy_i2c_pins[] = { 32, 33, };
static int mt7981_sgmii1_phy_i2c_funcs[] = { 2, 2, };
static int mt7981_sgmii0_phy_i2c_pins[] = { 32, 33, };
static int mt7981_sgmii0_phy_i2c_funcs[] = { 5, 5, };
/* DFD_NTRST */
static int mt7981_dfd_ntrst_pins[] = { 8, };
static int mt7981_dfd_ntrst_funcs[] = { 6, };
/* PWM0 */
static int mt7981_pwm0_0_pins[] = { 13, };
static int mt7981_pwm0_0_funcs[] = { 2, };
static int mt7981_pwm0_1_pins[] = { 15, };
static int mt7981_pwm0_1_funcs[] = { 1, };
/* PWM1 */
static int mt7981_pwm1_0_pins[] = { 14, };
static int mt7981_pwm1_0_funcs[] = { 2, };
static int mt7981_pwm1_1_pins[] = { 15, };
static int mt7981_pwm1_1_funcs[] = { 3, };
/* GBE_LED1 */
static int mt7981_gbe_led1_pins[] = { 13, };
static int mt7981_gbe_led1_funcs[] = { 3, };
/* PCM */
static int mt7981_pcm_pins[] = { 9, 10, 11, 12, 13, 25 };
static int mt7981_pcm_funcs[] = { 4, 4, 4, 4, 4, 4, };
/* UDI */
static int mt7981_udi_pins[] = { 9, 10, 11, 12, 13, };
static int mt7981_udi_funcs[] = { 6, 6, 6, 6, 6, };
/* DRV_VBUS */
static int mt7981_drv_vbus_pins[] = { 14, };
static int mt7981_drv_vbus_funcs[] = { 1, };
/* EMMC */
static int mt7981_emmc_45_pins[] = { 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, };
static int mt7981_emmc_45_funcs[] = { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, };
/* SNFI */
static int mt7981_snfi_pins[] = { 16, 17, 18, 19, 20, 21, };
static int mt7981_snfi_funcs[] = { 3, 3, 3, 3, 3, 3, };
/* SPI0 */
static int mt7981_spi0_pins[] = { 16, 17, 18, 19, };
static int mt7981_spi0_funcs[] = { 1, 1, 1, 1, };
/* SPI0 */
static int mt7981_spi0_wp_hold_pins[] = { 20, 21, };
static int mt7981_spi0_wp_hold_funcs[] = { 1, 1, };
/* SPI1 */
static int mt7981_spi1_1_pins[] = { 22, 23, 24, 25, };
static int mt7981_spi1_1_funcs[] = { 1, 1, 1, 1, };
/* SPI2 */
static int mt7981_spi2_pins[] = { 26, 27, 28, 29, };
static int mt7981_spi2_funcs[] = { 1, 1, 1, 1, };
/* SPI2 */
static int mt7981_spi2_wp_hold_pins[] = { 30, 31, };
static int mt7981_spi2_wp_hold_funcs[] = { 1, 1, };
/* UART1 */
static int mt7981_uart1_0_pins[] = { 16, 17, 18, 19, };
static int mt7981_uart1_0_funcs[] = { 4, 4, 4, 4, };
static int mt7981_uart1_1_pins[] = { 26, 27, 28, 29, };
static int mt7981_uart1_1_funcs[] = { 2, 2, 2, 2, };
/* UART2 */
static int mt7981_uart2_1_pins[] = { 22, 23, 24, 25, };
static int mt7981_uart2_1_funcs[] = { 3, 3, 3, 3, };
/* UART0 */
static int mt7981_uart0_pins[] = { 32, 33, };
static int mt7981_uart0_funcs[] = { 1, 1, };
/* PCIE_CLK_REQ */
static int mt7981_pcie_clk_pins[] = { 34, };
static int mt7981_pcie_clk_funcs[] = { 2, };
/* PCIE_WAKE_N */
static int mt7981_pcie_wake_pins[] = { 35, };
static int mt7981_pcie_wake_funcs[] = { 2, };
/* MDC_MDIO */
static int mt7981_smi_mdc_mdio_pins[] = { 36, 37, };
static int mt7981_smi_mdc_mdio_funcs[] = { 1, 1, };
static int mt7981_gbe_ext_mdc_mdio_pins[] = { 36, 37, };
static int mt7981_gbe_ext_mdc_mdio_funcs[] = { 3, 3, };
/* WF0_MODE1 */
static int mt7981_wf0_mode1_pins[] = { 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56 };
static int mt7981_wf0_mode1_funcs[] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 };
/* WF0_MODE3 */
static int mt7981_wf0_mode3_pins[] = { 45, 46, 47, 48, 49, 51 };
static int mt7981_wf0_mode3_funcs[] = { 2, 2, 2, 2, 2, 2 };
/* WF2G_LED */
static int mt7981_wf2g_led0_pins[] = { 30, };
static int mt7981_wf2g_led0_funcs[] = { 2, };
static int mt7981_wf2g_led1_pins[] = { 34, };
static int mt7981_wf2g_led1_funcs[] = { 1, };
/* WF5G_LED */
static int mt7981_wf5g_led0_pins[] = { 31, };
static int mt7981_wf5g_led0_funcs[] = { 2, };
static int mt7981_wf5g_led1_pins[] = { 35, };
static int mt7981_wf5g_led1_funcs[] = { 1, };
/* MT7531_INT */
static int mt7981_mt7531_int_pins[] = { 38, };
static int mt7981_mt7531_int_funcs[] = { 1, };
/* ANT_SEL */
static int mt7981_ant_sel_pins[] = { 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 34, 35 };
static int mt7981_ant_sel_funcs[] = { 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6 };
static const struct group_desc mt7981_groups[] = {
/* @GPIO(0,1): WA_AICE(2) */
PINCTRL_PIN_GROUP("wa_aice1", mt7981_wa_aice1),
/* @GPIO(0,1): WA_AICE(3) */
PINCTRL_PIN_GROUP("wa_aice2", mt7981_wa_aice2),
/* @GPIO(0,1): WM_UART(5) */
PINCTRL_PIN_GROUP("wm_uart_0", mt7981_wm_uart_0),
/* @GPIO(0,1,4,5): DFD(6) */
PINCTRL_PIN_GROUP("dfd", mt7981_dfd),
/* @GPIO(2): SYS_WATCHDOG(1) */
PINCTRL_PIN_GROUP("watchdog", mt7981_watchdog),
/* @GPIO(3): PCIE_PERESET_N(1) */
PINCTRL_PIN_GROUP("pcie_pereset", mt7981_pcie_pereset),
/* @GPIO(4,8) JTAG(1) */
PINCTRL_PIN_GROUP("jtag", mt7981_jtag),
/* @GPIO(4,8) WM_JTAG(2) */
PINCTRL_PIN_GROUP("wm_jtag_0", mt7981_wm_jtag_0),
/* @GPIO(9,13) WO0_JTAG(1) */
PINCTRL_PIN_GROUP("wo0_jtag_0", mt7981_wo0_jtag_0),
/* @GPIO(4,7) WM_JTAG(3) */
PINCTRL_PIN_GROUP("uart2_0", mt7981_uart2_0),
/* @GPIO(8) GBE_LED0(3) */
PINCTRL_PIN_GROUP("gbe_led0", mt7981_gbe_led0),
/* @GPIO(4,6) PTA_EXT(4) */
PINCTRL_PIN_GROUP("pta_ext_0", mt7981_pta_ext_0),
/* @GPIO(7) PWM2(4) */
PINCTRL_PIN_GROUP("pwm2", mt7981_pwm2),
/* @GPIO(8) NET_WO0_UART_TXD(4) */
PINCTRL_PIN_GROUP("net_wo0_uart_txd_0", mt7981_net_wo0_uart_txd_0),
/* @GPIO(4,7) SPI1(5) */
PINCTRL_PIN_GROUP("spi1_0", mt7981_spi1_0),
/* @GPIO(6,7) I2C(5) */
PINCTRL_PIN_GROUP("i2c0_0", mt7981_i2c0_0),
/* @GPIO(0,1,4,5): DFD_NTRST(6) */
PINCTRL_PIN_GROUP("dfd_ntrst", mt7981_dfd_ntrst),
/* @GPIO(9,10): WM_AICE(2) */
PINCTRL_PIN_GROUP("wm_aice1", mt7981_wm_aice1),
/* @GPIO(13): PWM0(2) */
PINCTRL_PIN_GROUP("pwm0_0", mt7981_pwm0_0),
/* @GPIO(15): PWM0(1) */
PINCTRL_PIN_GROUP("pwm0_1", mt7981_pwm0_1),
/* @GPIO(14): PWM1(2) */
PINCTRL_PIN_GROUP("pwm1_0", mt7981_pwm1_0),
/* @GPIO(15): PWM1(3) */
PINCTRL_PIN_GROUP("pwm1_1", mt7981_pwm1_1),
/* @GPIO(14) NET_WO0_UART_TXD(3) */
PINCTRL_PIN_GROUP("net_wo0_uart_txd_1", mt7981_net_wo0_uart_txd_1),
/* @GPIO(15) NET_WO0_UART_TXD(4) */
PINCTRL_PIN_GROUP("net_wo0_uart_txd_2", mt7981_net_wo0_uart_txd_2),
/* @GPIO(13) GBE_LED0(3) */
PINCTRL_PIN_GROUP("gbe_led1", mt7981_gbe_led1),
/* @GPIO(9,13) PCM(4) */
PINCTRL_PIN_GROUP("pcm", mt7981_pcm),
/* @GPIO(13): SYS_WATCHDOG1(5) */
PINCTRL_PIN_GROUP("watchdog1", mt7981_watchdog1),
/* @GPIO(9,13) UDI(4) */
PINCTRL_PIN_GROUP("udi", mt7981_udi),
/* @GPIO(14) DRV_VBUS(1) */
PINCTRL_PIN_GROUP("drv_vbus", mt7981_drv_vbus),
/* @GPIO(15,25): EMMC(2) */
PINCTRL_PIN_GROUP("emmc_45", mt7981_emmc_45),
/* @GPIO(16,21): SNFI(3) */
PINCTRL_PIN_GROUP("snfi", mt7981_snfi),
/* @GPIO(16,19): SPI0(1) */
PINCTRL_PIN_GROUP("spi0", mt7981_spi0),
/* @GPIO(20,21): SPI0(1) */
PINCTRL_PIN_GROUP("spi0_wp_hold", mt7981_spi0_wp_hold),
/* @GPIO(22,25) SPI1(1) */
PINCTRL_PIN_GROUP("spi1_1", mt7981_spi1_1),
/* @GPIO(26,29): SPI2(1) */
PINCTRL_PIN_GROUP("spi2", mt7981_spi2),
/* @GPIO(30,31): SPI0(1) */
PINCTRL_PIN_GROUP("spi2_wp_hold", mt7981_spi2_wp_hold),
/* @GPIO(16,19): UART1(4) */
PINCTRL_PIN_GROUP("uart1_0", mt7981_uart1_0),
/* @GPIO(26,29): UART1(2) */
PINCTRL_PIN_GROUP("uart1_1", mt7981_uart1_1),
/* @GPIO(22,25): UART1(3) */
PINCTRL_PIN_GROUP("uart2_1", mt7981_uart2_1),
/* @GPIO(22,24) PTA_EXT(4) */
PINCTRL_PIN_GROUP("pta_ext_1", mt7981_pta_ext_1),
/* @GPIO(20,21): WM_UART(4) */
PINCTRL_PIN_GROUP("wm_aurt_1", mt7981_wm_uart_1),
/* @GPIO(30,31): WM_UART(3) */
PINCTRL_PIN_GROUP("wm_aurt_2", mt7981_wm_uart_2),
/* @GPIO(20,24) WM_JTAG(5) */
PINCTRL_PIN_GROUP("wm_jtag_1", mt7981_wm_jtag_1),
/* @GPIO(25,29) WO0_JTAG(5) */
PINCTRL_PIN_GROUP("wo0_jtag_1", mt7981_wo0_jtag_1),
/* @GPIO(28,29): WA_AICE(3) */
PINCTRL_PIN_GROUP("wa_aice3", mt7981_wa_aice3),
/* @GPIO(30,31): WM_AICE(5) */
PINCTRL_PIN_GROUP("wm_aice2", mt7981_wm_aice2),
/* @GPIO(30,31): I2C(4) */
PINCTRL_PIN_GROUP("i2c0_1", mt7981_i2c0_1),
/* @GPIO(30,31): I2C(6) */
PINCTRL_PIN_GROUP("u2_phy_i2c", mt7981_u2_phy_i2c),
/* @GPIO(32,33): I2C(1) */
PINCTRL_PIN_GROUP("uart0", mt7981_uart0),
/* @GPIO(32,33): I2C(2) */
PINCTRL_PIN_GROUP("sgmii1_phy_i2c", mt7981_sgmii1_phy_i2c),
/* @GPIO(32,33): I2C(3) */
PINCTRL_PIN_GROUP("u3_phy_i2c", mt7981_u3_phy_i2c),
/* @GPIO(32,33): I2C(5) */
PINCTRL_PIN_GROUP("sgmii0_phy_i2c", mt7981_sgmii0_phy_i2c),
/* @GPIO(34): PCIE_CLK_REQ(2) */
PINCTRL_PIN_GROUP("pcie_clk", mt7981_pcie_clk),
/* @GPIO(35): PCIE_WAKE_N(2) */
PINCTRL_PIN_GROUP("pcie_wake", mt7981_pcie_wake),
/* @GPIO(36,37): I2C(2) */
PINCTRL_PIN_GROUP("i2c0_2", mt7981_i2c0_2),
/* @GPIO(36,37): MDC_MDIO(1) */
PINCTRL_PIN_GROUP("smi_mdc_mdio", mt7981_smi_mdc_mdio),
/* @GPIO(36,37): MDC_MDIO(3) */
PINCTRL_PIN_GROUP("gbe_ext_mdc_mdio", mt7981_gbe_ext_mdc_mdio),
/* @GPIO(69,85): WF0_MODE1(1) */
PINCTRL_PIN_GROUP("wf0_mode1", mt7981_wf0_mode1),
/* @GPIO(74,80): WF0_MODE3(3) */
PINCTRL_PIN_GROUP("wf0_mode3", mt7981_wf0_mode3),
/* @GPIO(30): WF2G_LED(2) */
PINCTRL_PIN_GROUP("wf2g_led0", mt7981_wf2g_led0),
/* @GPIO(34): WF2G_LED(1) */
PINCTRL_PIN_GROUP("wf2g_led1", mt7981_wf2g_led1),
/* @GPIO(31): WF5G_LED(2) */
PINCTRL_PIN_GROUP("wf5g_led0", mt7981_wf5g_led0),
/* @GPIO(35): WF5G_LED(1) */
PINCTRL_PIN_GROUP("wf5g_led1", mt7981_wf5g_led1),
/* @GPIO(38): MT7531_INT(1) */
PINCTRL_PIN_GROUP("mt7531_int", mt7981_mt7531_int),
/* @GPIO(14,15,26,17,18,19,20,21,22,23,24,25,34,35): ANT_SEL(1) */
PINCTRL_PIN_GROUP("ant_sel", mt7981_ant_sel),
};
/* Joint those groups owning the same capability in user point of view which
* allows that people tend to use through the device tree.
*/
static const char *mt7981_wa_aice_groups[] = { "wa_aice1", "wa_aice2", "wm_aice1_1",
"wa_aice3", "wm_aice1_2", };
static const char *mt7981_uart_groups[] = { "wm_uart_0", "uart2_0",
"net_wo0_uart_txd_0", "net_wo0_uart_txd_1", "net_wo0_uart_txd_2",
"uart1_0", "uart1_1", "uart2_1", "wm_aurt_1", "wm_aurt_2", "uart0", };
static const char *mt7981_dfd_groups[] = { "dfd", "dfd_ntrst", };
static const char *mt7981_wdt_groups[] = { "watchdog", "watchdog1", };
static const char *mt7981_pcie_groups[] = { "pcie_pereset", "pcie_clk", "pcie_wake", };
static const char *mt7981_jtag_groups[] = { "jtag", "wm_jtag_0", "wo0_jtag_0",
"wo0_jtag_1", "wm_jtag_1", };
static const char *mt7981_led_groups[] = { "gbe_led0", "gbe_led1", "wf2g_led0",
"wf2g_led1", "wf5g_led0", "wf5g_led1", };
static const char *mt7981_pta_groups[] = { "pta_ext_0", "pta_ext_1", };
static const char *mt7981_pwm_groups[] = { "pwm2", "pwm0_0", "pwm0_1",
"pwm1_0", "pwm1_1", };
static const char *mt7981_spi_groups[] = { "spi1_0", "spi0", "spi0_wp_hold", "spi1_1", "spi2",
"spi2_wp_hold", };
static const char *mt7981_i2c_groups[] = { "i2c0_0", "i2c0_1", "u2_phy_i2c",
"sgmii1_phy_i2c", "u3_phy_i2c", "sgmii0_phy_i2c", "i2c0_2", };
static const char *mt7981_pcm_groups[] = { "pcm", };
static const char *mt7981_udi_groups[] = { "udi", };
static const char *mt7981_usb_groups[] = { "drv_vbus", };
static const char *mt7981_flash_groups[] = { "emmc_45", "snfi", };
static const char *mt7981_ethernet_groups[] = { "smi_mdc_mdio", "gbe_ext_mdc_mdio",
"wf0_mode1", "wf0_mode3", "mt7531_int", };
static const char *mt7981_ant_groups[] = { "ant_sel", };
static const struct function_desc mt7981_functions[] = {
{"wa_aice", mt7981_wa_aice_groups, ARRAY_SIZE(mt7981_wa_aice_groups)},
{"dfd", mt7981_dfd_groups, ARRAY_SIZE(mt7981_dfd_groups)},
{"jtag", mt7981_jtag_groups, ARRAY_SIZE(mt7981_jtag_groups)},
{"pta", mt7981_pta_groups, ARRAY_SIZE(mt7981_pta_groups)},
{"pcm", mt7981_pcm_groups, ARRAY_SIZE(mt7981_pcm_groups)},
{"udi", mt7981_udi_groups, ARRAY_SIZE(mt7981_udi_groups)},
{"usb", mt7981_usb_groups, ARRAY_SIZE(mt7981_usb_groups)},
{"ant", mt7981_ant_groups, ARRAY_SIZE(mt7981_ant_groups)},
{"eth", mt7981_ethernet_groups, ARRAY_SIZE(mt7981_ethernet_groups)},
{"i2c", mt7981_i2c_groups, ARRAY_SIZE(mt7981_i2c_groups)},
{"led", mt7981_led_groups, ARRAY_SIZE(mt7981_led_groups)},
{"pwm", mt7981_pwm_groups, ARRAY_SIZE(mt7981_pwm_groups)},
{"spi", mt7981_spi_groups, ARRAY_SIZE(mt7981_spi_groups)},
{"uart", mt7981_uart_groups, ARRAY_SIZE(mt7981_uart_groups)},
{"watchdog", mt7981_wdt_groups, ARRAY_SIZE(mt7981_wdt_groups)},
{"flash", mt7981_flash_groups, ARRAY_SIZE(mt7981_flash_groups)},
{"pcie", mt7981_pcie_groups, ARRAY_SIZE(mt7981_pcie_groups)},
};
static const struct mtk_eint_hw mt7981_eint_hw = {
.port_mask = 7,
.ports = 7,
.ap_num = ARRAY_SIZE(mt7981_pins),
.db_cnt = 16,
};
static const char * const mt7981_pinctrl_register_base_names[] = {
"gpio", "iocfg_rt", "iocfg_rm", "iocfg_rb",
"iocfg_lb", "iocfg_bl", "iocfg_tm", "iocfg_tl",
};
static struct mtk_pin_soc mt7981_data = {
.reg_cal = mt7981_reg_cals,
.pins = mt7981_pins,
.npins = ARRAY_SIZE(mt7981_pins),
.grps = mt7981_groups,
.ngrps = ARRAY_SIZE(mt7981_groups),
.funcs = mt7981_functions,
.nfuncs = ARRAY_SIZE(mt7981_functions),
.eint_hw = &mt7981_eint_hw,
.gpio_m = 0,
.ies_present = false,
.base_names = mt7981_pinctrl_register_base_names,
.nbase_names = ARRAY_SIZE(mt7981_pinctrl_register_base_names),
.bias_set_combo = mtk_pinconf_bias_set_combo,
.bias_get_combo = mtk_pinconf_bias_get_combo,
.drive_set = mtk_pinconf_drive_set_rev1,
.drive_get = mtk_pinconf_drive_get_rev1,
.adv_pull_get = mtk_pinconf_adv_pull_get,
.adv_pull_set = mtk_pinconf_adv_pull_set,
};
static const struct of_device_id mt7981_pinctrl_of_match[] = {
{ .compatible = "mediatek,mt7981-pinctrl", },
{}
};
static int mt7981_pinctrl_probe(struct platform_device *pdev)
{
return mtk_moore_pinctrl_probe(pdev, &mt7981_data);
}
static struct platform_driver mt7981_pinctrl_driver = {
.driver = {
.name = "mt7981-pinctrl",
.of_match_table = mt7981_pinctrl_of_match,
},
.probe = mt7981_pinctrl_probe,
};
static int __init mt7981_pinctrl_init(void)
{
return platform_driver_register(&mt7981_pinctrl_driver);
}
arch_initcall(mt7981_pinctrl_init);

View File

@ -0,0 +1,215 @@
/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */
/*
* Copyright (c) 2021 MediaTek Inc.
* Author: Wenzhen.Yu <wenzhen.yu@mediatek.com>
* Author: Jianhui Zhao <zhaojh329@gmail.com>
* Author: Daniel Golle <daniel@makrotopia.org>
*/
#ifndef _DT_BINDINGS_CLK_MT7981_H
#define _DT_BINDINGS_CLK_MT7981_H
/* TOPCKGEN */
#define CLK_TOP_CB_CKSQ_40M 0
#define CLK_TOP_CB_M_416M 1
#define CLK_TOP_CB_M_D2 2
#define CLK_TOP_CB_M_D3 3
#define CLK_TOP_M_D3_D2 4
#define CLK_TOP_CB_M_D4 5
#define CLK_TOP_CB_M_D8 6
#define CLK_TOP_M_D8_D2 7
#define CLK_TOP_CB_MM_720M 8
#define CLK_TOP_CB_MM_D2 9
#define CLK_TOP_CB_MM_D3 10
#define CLK_TOP_CB_MM_D3_D5 11
#define CLK_TOP_CB_MM_D4 12
#define CLK_TOP_CB_MM_D6 13
#define CLK_TOP_MM_D6_D2 14
#define CLK_TOP_CB_MM_D8 15
#define CLK_TOP_CB_APLL2_196M 16
#define CLK_TOP_APLL2_D2 17
#define CLK_TOP_APLL2_D4 18
#define CLK_TOP_NET1_2500M 19
#define CLK_TOP_CB_NET1_D4 20
#define CLK_TOP_CB_NET1_D5 21
#define CLK_TOP_NET1_D5_D2 22
#define CLK_TOP_NET1_D5_D4 23
#define CLK_TOP_CB_NET1_D8 24
#define CLK_TOP_NET1_D8_D2 25
#define CLK_TOP_NET1_D8_D4 26
#define CLK_TOP_CB_NET2_800M 27
#define CLK_TOP_CB_NET2_D2 28
#define CLK_TOP_CB_NET2_D4 29
#define CLK_TOP_NET2_D4_D2 30
#define CLK_TOP_NET2_D4_D4 31
#define CLK_TOP_CB_NET2_D6 32
#define CLK_TOP_CB_WEDMCU_208M 33
#define CLK_TOP_CB_SGM_325M 34
#define CLK_TOP_CKSQ_40M_D2 35
#define CLK_TOP_CB_RTC_32K 36
#define CLK_TOP_CB_RTC_32P7K 37
#define CLK_TOP_USB_TX250M 38
#define CLK_TOP_FAUD 39
#define CLK_TOP_NFI1X 40
#define CLK_TOP_USB_EQ_RX250M 41
#define CLK_TOP_USB_CDR_CK 42
#define CLK_TOP_USB_LN0_CK 43
#define CLK_TOP_SPINFI_BCK 44
#define CLK_TOP_SPI 45
#define CLK_TOP_SPIM_MST 46
#define CLK_TOP_UART_BCK 47
#define CLK_TOP_PWM_BCK 48
#define CLK_TOP_I2C_BCK 49
#define CLK_TOP_PEXTP_TL 50
#define CLK_TOP_EMMC_208M 51
#define CLK_TOP_EMMC_400M 52
#define CLK_TOP_DRAMC_REF 53
#define CLK_TOP_DRAMC_MD32 54
#define CLK_TOP_SYSAXI 55
#define CLK_TOP_SYSAPB 56
#define CLK_TOP_ARM_DB_MAIN 57
#define CLK_TOP_AP2CNN_HOST 58
#define CLK_TOP_NETSYS 59
#define CLK_TOP_NETSYS_500M 60
#define CLK_TOP_NETSYS_WED_MCU 61
#define CLK_TOP_NETSYS_2X 62
#define CLK_TOP_SGM_325M 63
#define CLK_TOP_SGM_REG 64
#define CLK_TOP_F26M 65
#define CLK_TOP_EIP97B 66
#define CLK_TOP_USB3_PHY 67
#define CLK_TOP_AUD 68
#define CLK_TOP_A1SYS 69
#define CLK_TOP_AUD_L 70
#define CLK_TOP_A_TUNER 71
#define CLK_TOP_U2U3_REF 72
#define CLK_TOP_U2U3_SYS 73
#define CLK_TOP_U2U3_XHCI 74
#define CLK_TOP_USB_FRMCNT 75
#define CLK_TOP_NFI1X_SEL 76
#define CLK_TOP_SPINFI_SEL 77
#define CLK_TOP_SPI_SEL 78
#define CLK_TOP_SPIM_MST_SEL 79
#define CLK_TOP_UART_SEL 80
#define CLK_TOP_PWM_SEL 81
#define CLK_TOP_I2C_SEL 82
#define CLK_TOP_PEXTP_TL_SEL 83
#define CLK_TOP_EMMC_208M_SEL 84
#define CLK_TOP_EMMC_400M_SEL 85
#define CLK_TOP_F26M_SEL 86
#define CLK_TOP_DRAMC_SEL 87
#define CLK_TOP_DRAMC_MD32_SEL 88
#define CLK_TOP_SYSAXI_SEL 89
#define CLK_TOP_SYSAPB_SEL 90
#define CLK_TOP_ARM_DB_MAIN_SEL 91
#define CLK_TOP_AP2CNN_HOST_SEL 92
#define CLK_TOP_NETSYS_SEL 93
#define CLK_TOP_NETSYS_500M_SEL 94
#define CLK_TOP_NETSYS_MCU_SEL 95
#define CLK_TOP_NETSYS_2X_SEL 96
#define CLK_TOP_SGM_325M_SEL 97
#define CLK_TOP_SGM_REG_SEL 98
#define CLK_TOP_EIP97B_SEL 99
#define CLK_TOP_USB3_PHY_SEL 100
#define CLK_TOP_AUD_SEL 101
#define CLK_TOP_A1SYS_SEL 102
#define CLK_TOP_AUD_L_SEL 103
#define CLK_TOP_A_TUNER_SEL 104
#define CLK_TOP_U2U3_SEL 105
#define CLK_TOP_U2U3_SYS_SEL 106
#define CLK_TOP_U2U3_XHCI_SEL 107
#define CLK_TOP_USB_FRMCNT_SEL 108
#define CLK_TOP_AUD_I2S_M 109
/* INFRACFG */
#define CLK_INFRA_66M_MCK 0
#define CLK_INFRA_UART0_SEL 1
#define CLK_INFRA_UART1_SEL 2
#define CLK_INFRA_UART2_SEL 3
#define CLK_INFRA_SPI0_SEL 4
#define CLK_INFRA_SPI1_SEL 5
#define CLK_INFRA_SPI2_SEL 6
#define CLK_INFRA_PWM1_SEL 7
#define CLK_INFRA_PWM2_SEL 8
#define CLK_INFRA_PWM3_SEL 9
#define CLK_INFRA_PWM_BSEL 10
#define CLK_INFRA_PCIE_SEL 11
#define CLK_INFRA_GPT_STA 12
#define CLK_INFRA_PWM_HCK 13
#define CLK_INFRA_PWM_STA 14
#define CLK_INFRA_PWM1_CK 15
#define CLK_INFRA_PWM2_CK 16
#define CLK_INFRA_PWM3_CK 17
#define CLK_INFRA_CQ_DMA_CK 18
#define CLK_INFRA_AUD_BUS_CK 19
#define CLK_INFRA_AUD_26M_CK 20
#define CLK_INFRA_AUD_L_CK 21
#define CLK_INFRA_AUD_AUD_CK 22
#define CLK_INFRA_AUD_EG2_CK 23
#define CLK_INFRA_DRAMC_26M_CK 24
#define CLK_INFRA_DBG_CK 25
#define CLK_INFRA_AP_DMA_CK 26
#define CLK_INFRA_SEJ_CK 27
#define CLK_INFRA_SEJ_13M_CK 28
#define CLK_INFRA_THERM_CK 29
#define CLK_INFRA_I2C0_CK 30
#define CLK_INFRA_UART0_CK 31
#define CLK_INFRA_UART1_CK 32
#define CLK_INFRA_UART2_CK 33
#define CLK_INFRA_SPI2_CK 34
#define CLK_INFRA_SPI2_HCK_CK 35
#define CLK_INFRA_NFI1_CK 36
#define CLK_INFRA_SPINFI1_CK 37
#define CLK_INFRA_NFI_HCK_CK 38
#define CLK_INFRA_SPI0_CK 39
#define CLK_INFRA_SPI1_CK 40
#define CLK_INFRA_SPI0_HCK_CK 41
#define CLK_INFRA_SPI1_HCK_CK 42
#define CLK_INFRA_FRTC_CK 43
#define CLK_INFRA_MSDC_CK 44
#define CLK_INFRA_MSDC_HCK_CK 45
#define CLK_INFRA_MSDC_133M_CK 46
#define CLK_INFRA_MSDC_66M_CK 47
#define CLK_INFRA_ADC_26M_CK 48
#define CLK_INFRA_ADC_FRC_CK 49
#define CLK_INFRA_FBIST2FPC_CK 50
#define CLK_INFRA_I2C_MCK_CK 51
#define CLK_INFRA_I2C_PCK_CK 52
#define CLK_INFRA_IUSB_133_CK 53
#define CLK_INFRA_IUSB_66M_CK 54
#define CLK_INFRA_IUSB_SYS_CK 55
#define CLK_INFRA_IUSB_CK 56
#define CLK_INFRA_IPCIE_CK 57
#define CLK_INFRA_IPCIE_PIPE_CK 58
#define CLK_INFRA_IPCIER_CK 59
#define CLK_INFRA_IPCIEB_CK 60
/* APMIXEDSYS */
#define CLK_APMIXED_ARMPLL 0
#define CLK_APMIXED_NET2PLL 1
#define CLK_APMIXED_MMPLL 2
#define CLK_APMIXED_SGMPLL 3
#define CLK_APMIXED_WEDMCUPLL 4
#define CLK_APMIXED_NET1PLL 5
#define CLK_APMIXED_MPLL 6
#define CLK_APMIXED_APLL2 7
/* SGMIISYS_0 */
#define CLK_SGM0_TX_EN 0
#define CLK_SGM0_RX_EN 1
#define CLK_SGM0_CK0_EN 2
#define CLK_SGM0_CDR_CK0_EN 3
/* SGMIISYS_1 */
#define CLK_SGM1_TX_EN 0
#define CLK_SGM1_RX_EN 1
#define CLK_SGM1_CK1_EN 2
#define CLK_SGM1_CDR_CK1_EN 3
/* ETHSYS */
#define CLK_ETH_FE_EN 0
#define CLK_ETH_GP2_EN 1
#define CLK_ETH_GP1_EN 2
#define CLK_ETH_WOCPU0_EN 3
#endif /* _DT_BINDINGS_CLK_MT7981_H */

View File

@ -57,6 +57,8 @@ CONFIG_COMMON_CLK_MEDIATEK=y
# CONFIG_COMMON_CLK_MT6779 is not set
# CONFIG_COMMON_CLK_MT6797 is not set
# CONFIG_COMMON_CLK_MT7622 is not set
CONFIG_COMMON_CLK_MT7981=y
CONFIG_COMMON_CLK_MT7981_ETHSYS=y
CONFIG_COMMON_CLK_MT7986=y
CONFIG_COMMON_CLK_MT7986_ETHSYS=y
# CONFIG_COMMON_CLK_MT8173 is not set
@ -205,6 +207,7 @@ CONFIG_MDIO_BUS=y
CONFIG_MDIO_DEVICE=y
CONFIG_MDIO_DEVRES=y
CONFIG_MEDIATEK_GE_PHY=y
CONFIG_MEDIATEK_GE_PHY_SOC=y
CONFIG_MEDIATEK_WATCHDOG=y
CONFIG_MEMFD_CREATE=y
CONFIG_MESSAGE_LOGLEVEL_DEFAULT=7
@ -307,6 +310,7 @@ CONFIG_PINCTRL=y
# CONFIG_PINCTRL_MT6765 is not set
# CONFIG_PINCTRL_MT6797 is not set
# CONFIG_PINCTRL_MT7622 is not set
CONFIG_PINCTRL_MT7981=y
CONFIG_PINCTRL_MT7986=y
# CONFIG_PINCTRL_MT8173 is not set
# CONFIG_PINCTRL_MT8183 is not set

View File

@ -1,8 +1,8 @@
ARCH:=aarch64
SUBTARGET:=filogic
BOARDNAME:=Filogic 830 (MT7986)
BOARDNAME:=Filogic 8x0 (MT798x)
CPU_TYPE:=cortex-a53
DEFAULT_PACKAGES += kmod-crypto-hw-safexcel kmod-mt7915e kmod-mt7986-firmware wpad-basic-openssl uboot-envtools mt7986-wo-firmware
DEFAULT_PACKAGES += kmod-crypto-hw-safexcel kmod-mt7915e wpad-basic-openssl uboot-envtools
KERNELNAME:=Image dtbs
define Target/Description

View File

@ -63,7 +63,7 @@ define Device/bananapi_bpi-r3
DEVICE_DTS_CONFIG := config-mt7986a-bananapi-bpi-r3
DEVICE_DTS_OVERLAY:= mt7986a-bananapi-bpi-r3-nor mt7986a-bananapi-bpi-r3-emmc-nor mt7986a-bananapi-bpi-r3-emmc-snand mt7986a-bananapi-bpi-r3-snand
DEVICE_DTS_DIR := ../dts
DEVICE_PACKAGES := kmod-hwmon-pwmfan kmod-i2c-gpio kmod-sfp kmod-usb3 e2fsprogs f2fsck mkf2fs
DEVICE_PACKAGES := kmod-hwmon-pwmfan kmod-i2c-gpio kmod-mt7986-firmware kmod-sfp kmod-usb3 e2fsprogs f2fsck mkf2fs mt7986-wo-firmware
IMAGES := sysupgrade.itb
KERNEL_INITRAMFS_SUFFIX := -recovery.itb
ARTIFACTS := \
@ -107,6 +107,7 @@ define Device/mediatek_mt7986a-rfb-nand
DEVICE_MODEL := MT7986 rfba AP (NAND)
DEVICE_DTS := mt7986a-rfb-spim-nand
DEVICE_DTS_DIR := $(DTS_DIR)/
DEVICE_PACKAGES := kmod-mt7986-firmware mt7986-wo-firmware
KERNEL_LOADADDR := 0x48000000
SUPPORTED_DEVICES := mediatek,mt7986a-rfb-snand
UBINIZE_OPTS := -E 5
@ -130,6 +131,7 @@ define Device/mediatek_mt7986b-rfb
DEVICE_MODEL := MTK7986 rfbb AP
DEVICE_DTS := mt7986b-rfb
DEVICE_DTS_DIR := $(DTS_DIR)/
DEVICE_PACKAGES := kmod-mt7986-firmware mt7986-wo-firmware
KERNEL_LOADADDR := 0x48000000
SUPPORTED_DEVICES := mediatek,mt7986b-rfb
UBINIZE_OPTS := -E 5
@ -163,7 +165,7 @@ define Device/xiaomi_redmi-router-ax6000-stock
DEVICE_MODEL := Redmi Router AX6000 (stock layout)
DEVICE_DTS := mt7986a-xiaomi-redmi-router-ax6000-stock
DEVICE_DTS_DIR := ../dts
DEVICE_PACKAGES := kmod-leds-ws2812b
DEVICE_PACKAGES := kmod-leds-ws2812b kmod-mt7986-firmware mt7986-wo-firmware
KERNEL_LOADADDR := 0x48000000
UBINIZE_OPTS := -E 5
BLOCKSIZE := 128k
@ -181,7 +183,7 @@ define Device/xiaomi_redmi-router-ax6000-ubootmod
DEVICE_MODEL := Redmi Router AX6000 (OpenWrt U-Boot layout)
DEVICE_DTS := mt7986a-xiaomi-redmi-router-ax6000-ubootmod
DEVICE_DTS_DIR := ../dts
DEVICE_PACKAGES := kmod-leds-ws2812b
DEVICE_PACKAGES := kmod-leds-ws2812b kmod-mt7986-firmware mt7986-wo-firmware
KERNEL_INITRAMFS_SUFFIX := -recovery.itb
IMAGES := sysupgrade.itb
KERNEL_LOADADDR := 0x48000000

View File

@ -71,6 +71,7 @@ CONFIG_COMMON_CLK_MT7622=y
CONFIG_COMMON_CLK_MT7622_AUDSYS=y
CONFIG_COMMON_CLK_MT7622_ETHSYS=y
CONFIG_COMMON_CLK_MT7622_HIFSYS=y
# CONFIG_COMMON_CLK_MT7981 is not set
# CONFIG_COMMON_CLK_MT7986 is not set
# CONFIG_COMMON_CLK_MT8173 is not set
# CONFIG_COMMON_CLK_MT8183 is not set
@ -232,6 +233,7 @@ CONFIG_MDIO_BUS=y
CONFIG_MDIO_DEVICE=y
CONFIG_MDIO_DEVRES=y
CONFIG_MEDIATEK_GE_PHY=y
# CONFIG_MEDIATEK_GE_PHY_SOC is not set
CONFIG_MEDIATEK_WATCHDOG=y
CONFIG_MEMFD_CREATE=y
CONFIG_MESSAGE_LOGLEVEL_DEFAULT=7
@ -333,6 +335,7 @@ CONFIG_PINCTRL=y
# CONFIG_PINCTRL_MT6765 is not set
# CONFIG_PINCTRL_MT6797 is not set
CONFIG_PINCTRL_MT7622=y
# CONFIG_PINCTRL_MT7981 is not set
# CONFIG_PINCTRL_MT7986 is not set
# CONFIG_PINCTRL_MT8173 is not set
# CONFIG_PINCTRL_MT8183 is not set

View File

@ -68,6 +68,7 @@ CONFIG_COMMON_CLK_MT2701_MMSYS=y
CONFIG_COMMON_CLK_MT2701_VDECSYS=y
# CONFIG_COMMON_CLK_MT7622 is not set
# CONFIG_COMMON_CLK_MT7629 is not set
# CONFIG_COMMON_CLK_MT7981 is not set
# CONFIG_COMMON_CLK_MT7986 is not set
# CONFIG_COMMON_CLK_MT8135 is not set
# CONFIG_COMMON_CLK_MT8173 is not set
@ -321,6 +322,7 @@ CONFIG_MDIO_DEVICE=y
CONFIG_MDIO_DEVRES=y
CONFIG_MDIO_GPIO=y
CONFIG_MEDIATEK_GE_PHY=y
# CONFIG_MEDIATEK_GE_PHY_SOC is not set
CONFIG_MEDIATEK_MT6577_AUXADC=y
CONFIG_MEDIATEK_WATCHDOG=y
CONFIG_MEMFD_CREATE=y

View File

@ -52,6 +52,7 @@ CONFIG_COMMON_CLK_MEDIATEK=y
CONFIG_COMMON_CLK_MT7629=y
CONFIG_COMMON_CLK_MT7629_ETHSYS=y
CONFIG_COMMON_CLK_MT7629_HIFSYS=y
# CONFIG_COMMON_CLK_MT7981 is not set
# CONFIG_COMMON_CLK_MT7986 is not set
# CONFIG_COMMON_CLK_MT8135 is not set
# CONFIG_COMMON_CLK_MT8173 is not set

View File

@ -0,0 +1,39 @@
--- a/drivers/clk/mediatek/Kconfig
+++ b/drivers/clk/mediatek/Kconfig
@@ -344,6 +344,23 @@ config COMMON_CLK_MT7629_HIFSYS
This driver supports MediaTek MT7629 HIFSYS clocks providing
to PCI-E and USB.
+config COMMON_CLK_MT7981
+ bool "Clock driver for MediaTek MT7981"
+ depends on ARCH_MEDIATEK || COMPILE_TEST
+ select COMMON_CLK_MEDIATEK
+ default ARCH_MEDIATEK
+ help
+ This driver supports MediaTek MT7981 basic clocks and clocks
+ required for various periperals found on MediaTek.
+
+config COMMON_CLK_MT7981_ETHSYS
+ bool "Clock driver for MediaTek MT7981 ETHSYS"
+ depends on COMMON_CLK_MT7981
+ default COMMON_CLK_MT7981
+ help
+ This driver add support for clocks for Ethernet and SGMII
+ required on MediaTek MT7981 SoC.
+
config COMMON_CLK_MT7986
bool "Clock driver for MediaTek MT7986"
depends on ARCH_MEDIATEK || COMPILE_TEST
--- a/drivers/clk/mediatek/Makefile
+++ b/drivers/clk/mediatek/Makefile
@@ -46,6 +46,10 @@ obj-$(CONFIG_COMMON_CLK_MT7622_AUDSYS) +
obj-$(CONFIG_COMMON_CLK_MT7629) += clk-mt7629.o
obj-$(CONFIG_COMMON_CLK_MT7629_ETHSYS) += clk-mt7629-eth.o
obj-$(CONFIG_COMMON_CLK_MT7629_HIFSYS) += clk-mt7629-hif.o
+obj-$(CONFIG_COMMON_CLK_MT7981) += clk-mt7981-apmixed.o
+obj-$(CONFIG_COMMON_CLK_MT7981) += clk-mt7981-topckgen.o
+obj-$(CONFIG_COMMON_CLK_MT7981) += clk-mt7981-infracfg.o
+obj-$(CONFIG_COMMON_CLK_MT7981_ETHSYS) += clk-mt7981-eth.o
obj-$(CONFIG_COMMON_CLK_MT7986) += clk-mt7986-apmixed.o
obj-$(CONFIG_COMMON_CLK_MT7986) += clk-mt7986-topckgen.o
obj-$(CONFIG_COMMON_CLK_MT7986) += clk-mt7986-infracfg.o

View File

@ -0,0 +1,26 @@
--- a/drivers/pinctrl/mediatek/Kconfig
+++ b/drivers/pinctrl/mediatek/Kconfig
@@ -120,6 +120,13 @@ config PINCTRL_MT7622
default ARM64 && ARCH_MEDIATEK
select PINCTRL_MTK_MOORE
+config PINCTRL_MT7981
+ bool "Mediatek MT7981 pin control"
+ depends on OF
+ depends on ARM64 || COMPILE_TEST
+ default ARM64 && ARCH_MEDIATEK
+ select PINCTRL_MTK_MOORE
+
config PINCTRL_MT7986
bool "Mediatek MT7986 pin control"
depends on OF
--- a/drivers/pinctrl/mediatek/Makefile
+++ b/drivers/pinctrl/mediatek/Makefile
@@ -17,6 +17,7 @@ obj-$(CONFIG_PINCTRL_MT6797) += pinctrl-
obj-$(CONFIG_PINCTRL_MT7622) += pinctrl-mt7622.o
obj-$(CONFIG_PINCTRL_MT7623) += pinctrl-mt7623.o
obj-$(CONFIG_PINCTRL_MT7629) += pinctrl-mt7629.o
+obj-$(CONFIG_PINCTRL_MT7986) += pinctrl-mt7981.o
obj-$(CONFIG_PINCTRL_MT7986) += pinctrl-mt7986.o
obj-$(CONFIG_PINCTRL_MT8167) += pinctrl-mt8167.o
obj-$(CONFIG_PINCTRL_MT8173) += pinctrl-mt8173.o

View File

@ -0,0 +1,130 @@
From bfd3acc428085742d754a6d328d1a93ebf9451df Mon Sep 17 00:00:00 2001
From: "SkyLake.Huang" <skylake.huang@mediatek.com>
Date: Thu, 23 Jun 2022 18:29:51 +0800
Subject: [PATCH 1/6] drivers: spi-mt65xx: Move chip_config to driver's private
data
Signed-off-by: SkyLake.Huang <skylake.huang@mediatek.com>
---
drivers/spi/spi-mt65xx.c | 29 +++++++++---------------
include/linux/platform_data/spi-mt65xx.h | 17 --------------
2 files changed, 11 insertions(+), 35 deletions(-)
delete mode 100644 include/linux/platform_data/spi-mt65xx.h
--- a/drivers/spi/spi-mt65xx.c
+++ b/drivers/spi/spi-mt65xx.c
@@ -14,7 +14,6 @@
#include <linux/of.h>
#include <linux/gpio/consumer.h>
#include <linux/platform_device.h>
-#include <linux/platform_data/spi-mt65xx.h>
#include <linux/pm_runtime.h>
#include <linux/spi/spi.h>
#include <linux/spi/spi-mem.h>
@@ -142,6 +141,8 @@ struct mtk_spi {
struct device *dev;
dma_addr_t tx_dma;
dma_addr_t rx_dma;
+ u32 sample_sel;
+ u32 get_tick_dly;
};
static const struct mtk_spi_compatible mtk_common_compat;
@@ -187,15 +188,6 @@ static const struct mtk_spi_compatible m
.no_need_unprepare = true,
};
-/*
- * A piece of default chip info unless the platform
- * supplies it.
- */
-static const struct mtk_chip_config mtk_default_chip_info = {
- .sample_sel = 0,
- .tick_delay = 0,
-};
-
static const struct of_device_id mtk_spi_of_match[] = {
{ .compatible = "mediatek,spi-ipm",
.data = (void *)&mtk_ipm_compat,
@@ -323,7 +315,6 @@ static int mtk_spi_hw_init(struct spi_ma
{
u16 cpha, cpol;
u32 reg_val;
- struct mtk_chip_config *chip_config = spi->controller_data;
struct mtk_spi *mdata = spi_master_get_devdata(master);
cpha = spi->mode & SPI_CPHA ? 1 : 0;
@@ -373,7 +364,7 @@ static int mtk_spi_hw_init(struct spi_ma
else
reg_val &= ~SPI_CMD_CS_POL;
- if (chip_config->sample_sel)
+ if (mdata->sample_sel)
reg_val |= SPI_CMD_SAMPLE_SEL;
else
reg_val &= ~SPI_CMD_SAMPLE_SEL;
@@ -400,20 +391,20 @@ static int mtk_spi_hw_init(struct spi_ma
if (mdata->dev_comp->ipm_design) {
reg_val = readl(mdata->base + SPI_CMD_REG);
reg_val &= ~SPI_CMD_IPM_GET_TICKDLY_MASK;
- reg_val |= ((chip_config->tick_delay & 0x7)
+ reg_val |= ((mdata->get_tick_dly & 0x7)
<< SPI_CMD_IPM_GET_TICKDLY_OFFSET);
writel(reg_val, mdata->base + SPI_CMD_REG);
} else {
reg_val = readl(mdata->base + SPI_CFG1_REG);
reg_val &= ~SPI_CFG1_GET_TICK_DLY_MASK;
- reg_val |= ((chip_config->tick_delay & 0x7)
+ reg_val |= ((mdata->get_tick_dly & 0x7)
<< SPI_CFG1_GET_TICK_DLY_OFFSET);
writel(reg_val, mdata->base + SPI_CFG1_REG);
}
} else {
reg_val = readl(mdata->base + SPI_CFG1_REG);
reg_val &= ~SPI_CFG1_GET_TICK_DLY_MASK_V1;
- reg_val |= ((chip_config->tick_delay & 0x3)
+ reg_val |= ((mdata->get_tick_dly & 0x3)
<< SPI_CFG1_GET_TICK_DLY_OFFSET_V1);
writel(reg_val, mdata->base + SPI_CFG1_REG);
}
@@ -700,9 +691,6 @@ static int mtk_spi_setup(struct spi_devi
{
struct mtk_spi *mdata = spi_master_get_devdata(spi->master);
- if (!spi->controller_data)
- spi->controller_data = (void *)&mtk_default_chip_info;
-
if (mdata->dev_comp->need_pad_sel && spi->cs_gpiod)
/* CS de-asserted, gpiolib will handle inversion */
gpiod_direction_output(spi->cs_gpiod, 0);
@@ -1115,6 +1103,10 @@ static int mtk_spi_probe(struct platform
mdata = spi_master_get_devdata(master);
mdata->dev_comp = of_id->data;
+ /* Set device configs to default first. Calibrate it later. */
+ mdata->sample_sel = 0;
+ mdata->get_tick_dly = 2;
+
if (mdata->dev_comp->enhance_timing)
master->mode_bits |= SPI_CS_HIGH;
--- a/include/linux/platform_data/spi-mt65xx.h
+++ /dev/null
@@ -1,17 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * MTK SPI bus driver definitions
- *
- * Copyright (c) 2015 MediaTek Inc.
- * Author: Leilk Liu <leilk.liu@mediatek.com>
- */
-
-#ifndef ____LINUX_PLATFORM_DATA_SPI_MTK_H
-#define ____LINUX_PLATFORM_DATA_SPI_MTK_H
-
-/* Board specific platform_data */
-struct mtk_chip_config {
- u32 sample_sel;
- u32 tick_delay;
-};
-#endif

View File

@ -0,0 +1,236 @@
From 2ade0172154e50c8a2bfd8634c6eff943cffea29 Mon Sep 17 00:00:00 2001
From: "SkyLake.Huang" <skylake.huang@mediatek.com>
Date: Thu, 23 Jun 2022 18:35:52 +0800
Subject: [PATCH 2/6] drivers: spi: Add support for dynamic calibration
Signed-off-by: SkyLake.Huang <skylake.huang@mediatek.com>
---
drivers/spi/spi.c | 137 ++++++++++++++++++++++++++++++++++++++++
include/linux/spi/spi.h | 42 ++++++++++++
2 files changed, 179 insertions(+)
--- a/drivers/spi/spi.c
+++ b/drivers/spi/spi.c
@@ -1234,6 +1234,70 @@ static int spi_transfer_wait(struct spi_
return 0;
}
+int spi_do_calibration(struct spi_controller *ctlr, struct spi_device *spi,
+ int (*cal_read)(void *priv, u32 *addr, int addrlen, u8 *buf, int readlen), void *drv_priv)
+{
+ int datalen = ctlr->cal_rule->datalen;
+ int addrlen = ctlr->cal_rule->addrlen;
+ u8 *buf;
+ int ret;
+ int i;
+ struct list_head *cal_head, *listptr;
+ struct spi_cal_target *target;
+
+ /* Calculate calibration result */
+ int hit_val, total_hit, origin;
+ bool hit;
+
+ /* Make sure we can start calibration */
+ if(!ctlr->cal_target || !ctlr->cal_rule || !ctlr->append_caldata)
+ return 0;
+
+ buf = kzalloc(datalen * sizeof(u8), GFP_KERNEL);
+ if(!buf)
+ return -ENOMEM;
+
+ ret = ctlr->append_caldata(ctlr);
+ if (ret)
+ goto cal_end;
+
+ cal_head = ctlr->cal_target;
+ list_for_each(listptr, cal_head) {
+ target = list_entry(listptr, struct spi_cal_target, list);
+
+ hit = false;
+ hit_val = 0;
+ total_hit = 0;
+ origin = *target->cal_item;
+
+ for(i=target->cal_min; i<=target->cal_max; i+=target->step) {
+ *target->cal_item = i;
+ ret = (*cal_read)(drv_priv, ctlr->cal_rule->addr, addrlen, buf, datalen);
+ if(ret)
+ break;
+ dev_dbg(&spi->dev, "controller cal item value: 0x%x\n", i);
+ if(memcmp(ctlr->cal_rule->match_data, buf, datalen * sizeof(u8)) == 0) {
+ hit = true;
+ hit_val += i;
+ total_hit++;
+ dev_dbg(&spi->dev, "golden data matches data read!\n");
+ }
+ }
+ if(hit) {
+ *target->cal_item = DIV_ROUND_CLOSEST(hit_val, total_hit);
+ dev_info(&spi->dev, "calibration result: 0x%x", *target->cal_item);
+ } else {
+ *target->cal_item = origin;
+ dev_warn(&spi->dev, "calibration failed, fallback to default: 0x%x", origin);
+ }
+ }
+
+cal_end:
+ kfree(buf);
+ return ret? ret: 0;
+}
+EXPORT_SYMBOL_GPL(spi_do_calibration);
+
static void _spi_transfer_delay_ns(u32 ns)
{
if (!ns)
@@ -2021,6 +2085,75 @@ void spi_flush_queue(struct spi_controll
/*-------------------------------------------------------------------------*/
#if defined(CONFIG_OF)
+static inline void alloc_cal_data(struct list_head **cal_target,
+ struct spi_cal_rule **cal_rule, bool enable)
+{
+ if(enable) {
+ *cal_target = kmalloc(sizeof(struct list_head), GFP_KERNEL);
+ INIT_LIST_HEAD(*cal_target);
+ *cal_rule = kmalloc(sizeof(struct spi_cal_rule), GFP_KERNEL);
+ } else {
+ kfree(*cal_target);
+ kfree(*cal_rule);
+ }
+}
+
+static int of_spi_parse_cal_dt(struct spi_controller *ctlr, struct spi_device *spi,
+ struct device_node *nc)
+{
+ u32 value;
+ int rc;
+ const char *cal_mode;
+
+ rc = of_property_read_bool(nc, "spi-cal-enable");
+ if (rc)
+ alloc_cal_data(&ctlr->cal_target, &ctlr->cal_rule, true);
+ else
+ return 0;
+
+ rc = of_property_read_string(nc, "spi-cal-mode", &cal_mode);
+ if(!rc) {
+ if(strcmp("read-data", cal_mode) == 0){
+ ctlr->cal_rule->mode = SPI_CAL_READ_DATA;
+ } else if(strcmp("read-pp", cal_mode) == 0) {
+ ctlr->cal_rule->mode = SPI_CAL_READ_PP;
+ return 0;
+ } else if(strcmp("read-sfdp", cal_mode) == 0){
+ ctlr->cal_rule->mode = SPI_CAL_READ_SFDP;
+ return 0;
+ }
+ } else
+ goto err;
+
+ ctlr->cal_rule->datalen = 0;
+ rc = of_property_read_u32(nc, "spi-cal-datalen", &value);
+ if(!rc && value > 0) {
+ ctlr->cal_rule->datalen = value;
+
+ ctlr->cal_rule->match_data = kzalloc(value * sizeof(u8), GFP_KERNEL);
+ rc = of_property_read_u8_array(nc, "spi-cal-data",
+ ctlr->cal_rule->match_data, value);
+ if(rc)
+ kfree(ctlr->cal_rule->match_data);
+ }
+
+ rc = of_property_read_u32(nc, "spi-cal-addrlen", &value);
+ if(!rc && value > 0) {
+ ctlr->cal_rule->addrlen = value;
+
+ ctlr->cal_rule->addr = kzalloc(value * sizeof(u32), GFP_KERNEL);
+ rc = of_property_read_u32_array(nc, "spi-cal-addr",
+ ctlr->cal_rule->addr, value);
+ if(rc)
+ kfree(ctlr->cal_rule->addr);
+ }
+ return 0;
+
+err:
+ alloc_cal_data(&ctlr->cal_target, &ctlr->cal_rule, false);
+ return 0;
+}
+
static int of_spi_parse_dt(struct spi_controller *ctlr, struct spi_device *spi,
struct device_node *nc)
{
@@ -2139,6 +2272,10 @@ of_register_spi_device(struct spi_contro
if (rc)
goto err_out;
+ rc = of_spi_parse_cal_dt(ctlr, spi, nc);
+ if (rc)
+ goto err_out;
+
/* Store a pointer to the node in the device structure */
of_node_get(nc);
spi->dev.of_node = nc;
--- a/include/linux/spi/spi.h
+++ b/include/linux/spi/spi.h
@@ -290,6 +290,40 @@ struct spi_driver {
struct device_driver driver;
};
+enum {
+ SPI_CAL_READ_DATA = 0,
+ SPI_CAL_READ_PP = 1, /* only for SPI-NAND */
+ SPI_CAL_READ_SFDP = 2, /* only for SPI-NOR */
+};
+
+struct nand_addr {
+ unsigned int lun;
+ unsigned int plane;
+ unsigned int eraseblock;
+ unsigned int page;
+ unsigned int dataoffs;
+};
+
+/**
+ * Read calibration rule from device dts node.
+ * Once calibration result matches the rule, we regard is as success.
+ */
+struct spi_cal_rule {
+ int datalen;
+ u8 *match_data;
+ int addrlen;
+ u32 *addr;
+ int mode;
+};
+
+struct spi_cal_target {
+ u32 *cal_item;
+ int cal_min; /* min of cal_item */
+ int cal_max; /* max of cal_item */
+ int step; /* Increase/decrease cal_item */
+ struct list_head list;
+};
+
static inline struct spi_driver *to_spi_driver(struct device_driver *drv)
{
return drv ? container_of(drv, struct spi_driver, driver) : NULL;
@@ -665,6 +699,11 @@ struct spi_controller {
void *dummy_rx;
void *dummy_tx;
+ /* For calibration */
+ int (*append_caldata)(struct spi_controller *ctlr);
+ struct list_head *cal_target;
+ struct spi_cal_rule *cal_rule;
+
int (*fw_translate_cs)(struct spi_controller *ctlr, unsigned cs);
/*
@@ -1477,6 +1516,9 @@ spi_register_board_info(struct spi_board
{ return 0; }
#endif
+extern int spi_do_calibration(struct spi_controller *ctlr,
+ struct spi_device *spi, int (*cal_read)(void *, u32 *, int, u8 *, int), void *drv_priv);
+
/* If you're hotplugging an adapter with devices (parport, usb, etc)
* use spi_new_device() to describe each device. You can also call
* spi_unregister_device() to start making that device vanish, but

View File

@ -0,0 +1,41 @@
From 06640a5da2973318c06e516da16a5b579622e7c5 Mon Sep 17 00:00:00 2001
From: "SkyLake.Huang" <skylake.huang@mediatek.com>
Date: Thu, 23 Jun 2022 18:37:55 +0800
Subject: [PATCH 3/6] drivers: spi-mem: Add spi calibration hook
Signed-off-by: SkyLake.Huang <skylake.huang@mediatek.com>
---
drivers/spi/spi-mem.c | 8 ++++++++
include/linux/spi/spi-mem.h | 4 ++++
2 files changed, 12 insertions(+)
--- a/drivers/spi/spi-mem.c
+++ b/drivers/spi/spi-mem.c
@@ -410,6 +410,14 @@ int spi_mem_exec_op(struct spi_mem *mem,
}
EXPORT_SYMBOL_GPL(spi_mem_exec_op);
+int spi_mem_do_calibration(struct spi_mem *mem,
+ int (*cal_read)(void *priv, u32 *addr, int addrlen, u8 *buf, int readlen),
+ void *priv)
+{
+ return spi_do_calibration(mem->spi->controller, mem->spi, cal_read, priv);
+}
+EXPORT_SYMBOL_GPL(spi_mem_do_calibration);
+
/**
* spi_mem_get_name() - Return the SPI mem device name to be used by the
* upper layer if necessary
--- a/include/linux/spi/spi-mem.h
+++ b/include/linux/spi/spi-mem.h
@@ -366,6 +366,10 @@ bool spi_mem_supports_op(struct spi_mem
int spi_mem_exec_op(struct spi_mem *mem,
const struct spi_mem_op *op);
+int spi_mem_do_calibration(struct spi_mem *mem,
+ int (*cal_read)(void *, u32 *, int, u8 *, int),
+ void *priv);
+
const char *spi_mem_get_name(struct spi_mem *mem);
struct spi_mem_dirmap_desc *

View File

@ -0,0 +1,43 @@
From d278c7a0bf730318a7ccf8d0a8b434c813e23fd0 Mon Sep 17 00:00:00 2001
From: "SkyLake.Huang" <skylake.huang@mediatek.com>
Date: Thu, 23 Jun 2022 18:39:03 +0800
Subject: [PATCH 4/6] drivers: spi-mt65xx: Add controller's calibration
paramter
Signed-off-by: SkyLake.Huang <skylake.huang@mediatek.com>
---
drivers/spi/spi-mt65xx.c | 16 ++++++++++++++++
1 file changed, 16 insertions(+)
--- a/drivers/spi/spi-mt65xx.c
+++ b/drivers/spi/spi-mt65xx.c
@@ -800,6 +800,21 @@ static irqreturn_t mtk_spi_interrupt(int
return IRQ_HANDLED;
}
+static int mtk_spi_append_caldata(struct spi_controller *ctlr)
+{
+ struct spi_cal_target *cal_target = kmalloc(sizeof(*cal_target), GFP_KERNEL);
+ struct mtk_spi *mdata = spi_master_get_devdata(ctlr);
+
+ cal_target->cal_item = &mdata->get_tick_dly;
+ cal_target->cal_min = 0;
+ cal_target->cal_max = 7;
+ cal_target->step = 1;
+
+ list_add(&cal_target->list, ctlr->cal_target);
+
+ return 0;
+}
+
static int mtk_spi_mem_adjust_op_size(struct spi_mem *mem,
struct spi_mem_op *op)
{
@@ -1092,6 +1107,7 @@ static int mtk_spi_probe(struct platform
master->setup = mtk_spi_setup;
master->set_cs_timing = mtk_spi_set_hw_cs_timing;
master->use_gpio_descriptors = true;
+ master->append_caldata = mtk_spi_append_caldata;
of_id = of_match_node(mtk_spi_of_match, pdev->dev.of_node);
if (!of_id) {

View File

@ -0,0 +1,81 @@
From 7670ec4a14891a1a182b98a9c403ffbf6b49e4b1 Mon Sep 17 00:00:00 2001
From: "SkyLake.Huang" <skylake.huang@mediatek.com>
Date: Thu, 23 Jun 2022 18:39:56 +0800
Subject: [PATCH 5/6] drivers: mtd: spinand: Add calibration support for
spinand
Signed-off-by: SkyLake.Huang <skylake.huang@mediatek.com>
---
drivers/mtd/nand/spi/core.c | 54 +++++++++++++++++++++++++++++++++++++
1 file changed, 54 insertions(+)
--- a/drivers/mtd/nand/spi/core.c
+++ b/drivers/mtd/nand/spi/core.c
@@ -967,6 +967,56 @@ static int spinand_manufacturer_match(st
return -ENOTSUPP;
}
+int spinand_cal_read(void *priv, u32 *addr, int addrlen, u8 *buf, int readlen) {
+ struct spinand_device *spinand = (struct spinand_device *)priv;
+ struct device *dev = &spinand->spimem->spi->dev;
+ struct spi_mem_op op = SPINAND_PAGE_READ_FROM_CACHE_OP(false, 0, 1, buf, readlen);
+ struct nand_pos pos;
+ struct nand_page_io_req req;
+ u8 status;
+ int ret;
+
+ if(addrlen != sizeof(struct nand_addr)/sizeof(unsigned int)) {
+ dev_err(dev, "Must provide correct addr(length) for spinand calibration\n");
+ return -EINVAL;
+ }
+
+ ret = spinand_reset_op(spinand);
+ if (ret)
+ return ret;
+
+ /* We should store our golden data in first target because
+ * we can't switch target at this moment.
+ */
+ pos = (struct nand_pos){
+ .target = 0,
+ .lun = *addr,
+ .plane = *(addr+1),
+ .eraseblock = *(addr+2),
+ .page = *(addr+3),
+ };
+
+ req = (struct nand_page_io_req){
+ .pos = pos,
+ .dataoffs = *(addr+4),
+ .datalen = readlen,
+ .databuf.in = buf,
+ .mode = MTD_OPS_AUTO_OOB,
+ };
+
+ ret = spinand_load_page_op(spinand, &req);
+ if (ret)
+ return ret;
+
+ ret = spinand_wait(spinand, &status);
+ if (ret < 0)
+ return ret;
+
+ ret = spi_mem_exec_op(spinand->spimem, &op);
+
+ return 0;
+}
+
static int spinand_id_detect(struct spinand_device *spinand)
{
u8 *id = spinand->id.data;
@@ -1217,6 +1267,10 @@ static int spinand_init(struct spinand_d
if (!spinand->scratchbuf)
return -ENOMEM;
+ ret = spi_mem_do_calibration(spinand->spimem, spinand_cal_read, spinand);
+ if (ret)
+ dev_err(dev, "Failed to calibrate SPI-NAND (err = %d)\n", ret);
+
ret = spinand_detect(spinand);
if (ret)
goto err_free_bufs;

View File

@ -0,0 +1,57 @@
From f3fe3b15eca7908eaac57f9b8387a5dbc45ec5b2 Mon Sep 17 00:00:00 2001
From: "SkyLake.Huang" <skylake.huang@mediatek.com>
Date: Thu, 23 Jun 2022 18:40:59 +0800
Subject: [PATCH 6/6] drivers: mtd: spi-nor: Add calibration support for
spi-nor
Signed-off-by: SkyLake.Huang <skylake.huang@mediatek.com>
---
drivers/mtd/nand/spi/core.c | 5 ++++-
drivers/mtd/spi-nor/core.c | 15 +++++++++++++++
2 files changed, 19 insertions(+), 1 deletion(-)
--- a/drivers/mtd/nand/spi/core.c
+++ b/drivers/mtd/nand/spi/core.c
@@ -1008,7 +1008,10 @@ int spinand_cal_read(void *priv, u32 *ad
if (ret)
return ret;
- ret = spinand_wait(spinand, &status);
+ ret = spinand_wait(spinand,
+ SPINAND_READ_INITIAL_DELAY_US,
+ SPINAND_READ_POLL_DELAY_US,
+ &status);
if (ret < 0)
return ret;
--- a/drivers/mtd/spi-nor/core.c
+++ b/drivers/mtd/spi-nor/core.c
@@ -3060,6 +3060,18 @@ static void spi_nor_debugfs_init(struct
info->id_len, info->id);
}
+static int spi_nor_cal_read(void *priv, u32 *addr, int addrlen, u8 *buf, int readlen)
+{
+ struct spi_nor *nor = (struct spi_nor *)priv;
+
+ nor->reg_proto = SNOR_PROTO_1_1_1;
+ nor->read_proto = SNOR_PROTO_1_1_1;
+ nor->read_opcode = SPINOR_OP_READ;
+ nor->read_dummy = 0;
+
+ return nor->controller_ops->read(nor, *addr, readlen, buf);
+}
+
static const struct flash_info *spi_nor_get_flash_info(struct spi_nor *nor,
const char *name)
{
@@ -3133,6 +3145,9 @@ int spi_nor_scan(struct spi_nor *nor, co
if (!nor->bouncebuf)
return -ENOMEM;
+ if(nor->spimem)
+ spi_mem_do_calibration(nor->spimem, spi_nor_cal_read, nor);
+
info = spi_nor_get_flash_info(nor, name);
if (IS_ERR(info))
return PTR_ERR(info);

View File

@ -20,7 +20,7 @@ Signed-off-by: David S. Miller <davem@davemloft.net>
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -230,13 +230,35 @@ static int _mtk_mdio_write(struct mtk_et
@@ -231,13 +231,35 @@ static int _mtk_mdio_write(struct mtk_et
if (ret < 0)
return ret;
@ -63,7 +63,7 @@ Signed-off-by: David S. Miller <davem@davemloft.net>
ret = mtk_mdio_busy_wait(eth);
if (ret < 0)
@@ -253,12 +275,33 @@ static int _mtk_mdio_read(struct mtk_eth
@@ -254,12 +276,33 @@ static int _mtk_mdio_read(struct mtk_eth
if (ret < 0)
return ret;
@ -103,7 +103,7 @@ Signed-off-by: David S. Miller <davem@davemloft.net>
ret = mtk_mdio_busy_wait(eth);
if (ret < 0)
@@ -727,6 +770,7 @@ static int mtk_mdio_init(struct mtk_eth
@@ -730,6 +773,7 @@ static int mtk_mdio_init(struct mtk_eth
eth->mii_bus->name = "mdio";
eth->mii_bus->read = mtk_mdio_read;
eth->mii_bus->write = mtk_mdio_write;
@ -113,7 +113,7 @@ Signed-off-by: David S. Miller <davem@davemloft.net>
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
@@ -369,9 +369,12 @@
@@ -376,9 +376,12 @@
#define PHY_IAC_ADDR_MASK GENMASK(24, 20)
#define PHY_IAC_ADDR(x) FIELD_PREP(PHY_IAC_ADDR_MASK, (x))
#define PHY_IAC_CMD_MASK GENMASK(19, 18)

View File

@ -0,0 +1,166 @@
--- a/drivers/net/phy/mxl-gpy.c
+++ b/drivers/net/phy/mxl-gpy.c
@@ -126,6 +126,12 @@ static int gpy_config_init(struct phy_de
if (ret < 0)
return ret;
+ /* Disable SGMII auto-negotiation */
+ ret = phy_modify_mmd(phydev, MDIO_MMD_VEND1, VSPEC1_SGMII_CTRL,
+ VSPEC1_SGMII_CTRL_ANEN, 0);
+ if (ret < 0)
+ return ret;
+
return gpy_led_write(phydev);
}
@@ -151,65 +157,6 @@ static int gpy_probe(struct phy_device *
return 0;
}
-static bool gpy_sgmii_need_reaneg(struct phy_device *phydev)
-{
- int fw_ver, fw_type, fw_minor;
- size_t i;
-
- fw_ver = phy_read(phydev, PHY_FWV);
- if (fw_ver < 0)
- return true;
-
- fw_type = FIELD_GET(PHY_FWV_TYPE_MASK, fw_ver);
- fw_minor = FIELD_GET(PHY_FWV_MINOR_MASK, fw_ver);
-
- for (i = 0; i < ARRAY_SIZE(ver_need_sgmii_reaneg); i++) {
- if (fw_type != ver_need_sgmii_reaneg[i].type)
- continue;
- if (fw_minor < ver_need_sgmii_reaneg[i].minor)
- return true;
- break;
- }
-
- return false;
-}
-
-static bool gpy_2500basex_chk(struct phy_device *phydev)
-{
- int ret;
-
- ret = phy_read(phydev, PHY_MIISTAT);
- if (ret < 0) {
- phydev_err(phydev, "Error: MDIO register access failed: %d\n",
- ret);
- return false;
- }
-
- if (!(ret & PHY_MIISTAT_LS) ||
- FIELD_GET(PHY_MIISTAT_SPD_MASK, ret) != PHY_MIISTAT_SPD_2500)
- return false;
-
- phydev->speed = SPEED_2500;
- phydev->interface = PHY_INTERFACE_MODE_2500BASEX;
- phy_modify_mmd(phydev, MDIO_MMD_VEND1, VSPEC1_SGMII_CTRL,
- VSPEC1_SGMII_CTRL_ANEN, 0);
- return true;
-}
-
-static bool gpy_sgmii_aneg_en(struct phy_device *phydev)
-{
- int ret;
-
- ret = phy_read_mmd(phydev, MDIO_MMD_VEND1, VSPEC1_SGMII_CTRL);
- if (ret < 0) {
- phydev_err(phydev, "Error: MMD register access failed: %d\n",
- ret);
- return true;
- }
-
- return (ret & VSPEC1_SGMII_CTRL_ANEN) ? true : false;
-}
-
static int gpy_config_aneg(struct phy_device *phydev)
{
bool changed = false;
@@ -248,53 +195,11 @@ static int gpy_config_aneg(struct phy_de
phydev->interface == PHY_INTERFACE_MODE_INTERNAL)
return 0;
- /* No need to trigger re-ANEG if link speed is 2.5G or SGMII ANEG is
- * disabled.
- */
- if (!gpy_sgmii_need_reaneg(phydev) || gpy_2500basex_chk(phydev) ||
- !gpy_sgmii_aneg_en(phydev))
- return 0;
-
- /* There is a design constraint in GPY2xx device where SGMII AN is
- * only triggered when there is change of speed. If, PHY link
- * partner`s speed is still same even after PHY TPI is down and up
- * again, SGMII AN is not triggered and hence no new in-band message
- * from GPY to MAC side SGMII.
- * This could cause an issue during power up, when PHY is up prior to
- * MAC. At this condition, once MAC side SGMII is up, MAC side SGMII
- * wouldn`t receive new in-band message from GPY with correct link
- * status, speed and duplex info.
- *
- * 1) If PHY is already up and TPI link status is still down (such as
- * hard reboot), TPI link status is polled for 4 seconds before
- * retriggerring SGMII AN.
- * 2) If PHY is already up and TPI link status is also up (such as soft
- * reboot), polling of TPI link status is not needed and SGMII AN is
- * immediately retriggered.
- * 3) Other conditions such as PHY is down, speed change etc, skip
- * retriggering SGMII AN. Note: in case of speed change, GPY FW will
- * initiate SGMII AN.
- */
-
- if (phydev->state != PHY_UP)
- return 0;
-
- ret = phy_read_poll_timeout(phydev, MII_BMSR, ret, ret & BMSR_LSTATUS,
- 20000, 4000000, false);
- if (ret == -ETIMEDOUT)
- return 0;
- else if (ret < 0)
- return ret;
-
- /* Trigger SGMII AN. */
- return phy_modify_mmd(phydev, MDIO_MMD_VEND1, VSPEC1_SGMII_CTRL,
- VSPEC1_SGMII_CTRL_ANRS, VSPEC1_SGMII_CTRL_ANRS);
+ return 0;
}
static void gpy_update_interface(struct phy_device *phydev)
{
- int ret;
-
/* Interface mode is fixed for USXGMII and integrated PHY */
if (phydev->interface == PHY_INTERFACE_MODE_USXGMII ||
phydev->interface == PHY_INTERFACE_MODE_INTERNAL)
@@ -306,29 +211,11 @@ static void gpy_update_interface(struct
switch (phydev->speed) {
case SPEED_2500:
phydev->interface = PHY_INTERFACE_MODE_2500BASEX;
- ret = phy_modify_mmd(phydev, MDIO_MMD_VEND1, VSPEC1_SGMII_CTRL,
- VSPEC1_SGMII_CTRL_ANEN, 0);
- if (ret < 0)
- phydev_err(phydev,
- "Error: Disable of SGMII ANEG failed: %d\n",
- ret);
break;
case SPEED_1000:
case SPEED_100:
case SPEED_10:
phydev->interface = PHY_INTERFACE_MODE_SGMII;
- if (gpy_sgmii_aneg_en(phydev))
- break;
- /* Enable and restart SGMII ANEG for 10/100/1000Mbps link speed
- * if ANEG is disabled (in 2500-BaseX mode).
- */
- ret = phy_modify_mmd(phydev, MDIO_MMD_VEND1, VSPEC1_SGMII_CTRL,
- VSPEC1_SGMII_ANEN_ANRS,
- VSPEC1_SGMII_ANEN_ANRS);
- if (ret < 0)
- phydev_err(phydev,
- "Error: Enable of SGMII ANEG failed: %d\n",
- ret);
break;
}
}

View File

@ -0,0 +1,74 @@
From bd4f7dae6a1f2fd65bb2112783c92ffe0839bc77 Mon Sep 17 00:00:00 2001
From: Daniel Golle <daniel@makrotopia.org>
Date: Tue, 28 Feb 2023 23:53:56 +0000
Subject: [PATCH] i2c: mediatek: add support for MT7981 SoC
Signed-off-by: Daniel Golle <daniel@makrotopia.org>
---
drivers/i2c/busses/i2c-mt65xx.c | 13 +++++++++++++
1 file changed, 13 insertions(+)
--- a/drivers/i2c/busses/i2c-mt65xx.c
+++ b/drivers/i2c/busses/i2c-mt65xx.c
@@ -202,6 +202,34 @@ static const u16 mt_i2c_regs_v2[] = {
[OFFSET_DCM_EN] = 0xf88,
};
+static const u16 mt_i2c_regs_v3[] = {
+ [OFFSET_DATA_PORT] = 0x0,
+ [OFFSET_INTR_MASK] = 0x8,
+ [OFFSET_INTR_STAT] = 0xc,
+ [OFFSET_CONTROL] = 0x10,
+ [OFFSET_TRANSFER_LEN] = 0x14,
+ [OFFSET_TRANSAC_LEN] = 0x18,
+ [OFFSET_DELAY_LEN] = 0x1c,
+ [OFFSET_TIMING] = 0x20,
+ [OFFSET_START] = 0x24,
+ [OFFSET_EXT_CONF] = 0x28,
+ [OFFSET_LTIMING] = 0x2c,
+ [OFFSET_HS] = 0x30,
+ [OFFSET_IO_CONFIG] = 0x34,
+ [OFFSET_FIFO_ADDR_CLR] = 0x38,
+ [OFFSET_SDA_TIMING] = 0x3c,
+ [OFFSET_TRANSFER_LEN_AUX] = 0x44,
+ [OFFSET_CLOCK_DIV] = 0x48,
+ [OFFSET_SOFTRESET] = 0x50,
+ [OFFSET_SCL_MIS_COMP_POINT] = 0x90,
+ [OFFSET_SLAVE_ADDR] = 0x94,
+ [OFFSET_DEBUGSTAT] = 0xe4,
+ [OFFSET_DEBUGCTRL] = 0xe8,
+ [OFFSET_FIFO_STAT] = 0xf4,
+ [OFFSET_FIFO_THRESH] = 0xf8,
+ [OFFSET_DCM_EN] = 0xf88,
+};
+
struct mtk_i2c_compatible {
const struct i2c_adapter_quirks *quirks;
const u16 *regs;
@@ -365,6 +393,18 @@ static const struct mtk_i2c_compatible m
.max_dma_support = 32,
};
+static const struct mtk_i2c_compatible mt7981_compat = {
+ .regs = mt_i2c_regs_v3,
+ .pmic_i2c = 0,
+ .dcm = 0,
+ .auto_restart = 1,
+ .aux_len_reg = 1,
+ .timing_adjust = 1,
+ .dma_sync = 1,
+ .ltiming_adjust = 1,
+ .max_dma_support = 33
+};
+
static const struct mtk_i2c_compatible mt7986_compat = {
.quirks = &mt7622_i2c_quirks,
.regs = mt_i2c_regs_v1,
@@ -424,6 +464,7 @@ static const struct of_device_id mtk_i2c
{ .compatible = "mediatek,mt6577-i2c", .data = &mt6577_compat },
{ .compatible = "mediatek,mt6589-i2c", .data = &mt6589_compat },
{ .compatible = "mediatek,mt7622-i2c", .data = &mt7622_compat },
+ { .compatible = "mediatek,mt7981-i2c", .data = &mt7981_compat },
{ .compatible = "mediatek,mt7986-i2c", .data = &mt7986_compat },
{ .compatible = "mediatek,mt8173-i2c", .data = &mt8173_compat },
{ .compatible = "mediatek,mt8183-i2c", .data = &mt8183_compat },

View File

@ -0,0 +1,212 @@
From 947b535ebfe161e1725f1030a09de10d1460371c Mon Sep 17 00:00:00 2001
From: Daniel Golle <daniel@makrotopia.org>
Date: Mon, 23 Jan 2023 20:47:34 +0000
Subject: [PATCH] pwm: mediatek: Add support for MT7981
The PWM unit on MT7981 uses different register offsets than previous
MediaTek PWM units. Add support for these new offsets and add support
for PWM on MT7981 which has 3 PWM channels, one of them is typically
used for a temperature controlled fan.
Signed-off-by: Daniel Golle <daniel@makrotopia.org>
---
drivers/pwm/pwm-mediatek.c | 54 ++++++++++++++++++++++++++++++++------
1 file changed, 46 insertions(+), 8 deletions(-)
--- a/drivers/pwm/pwm-mediatek.c
+++ b/drivers/pwm/pwm-mediatek.c
@@ -34,10 +34,14 @@
#define PWM_CLK_DIV_MAX 7
+#define REG_V1 1
+#define REG_V2 2
+
struct pwm_mediatek_of_data {
unsigned int num_pwms;
bool pwm45_fixup;
bool has_ck_26m_sel;
+ u8 reg_ver;
};
/**
@@ -59,10 +63,14 @@ struct pwm_mediatek_chip {
const struct pwm_mediatek_of_data *soc;
};
-static const unsigned int pwm_mediatek_reg_offset[] = {
+static const unsigned int mtk_pwm_reg_offset_v1[] = {
0x0010, 0x0050, 0x0090, 0x00d0, 0x0110, 0x0150, 0x0190, 0x0220
};
+static const unsigned int mtk_pwm_reg_offset_v2[] = {
+ 0x0080, 0x00c0, 0x0100, 0x0140, 0x0180, 0x1c0, 0x200, 0x0240
+};
+
static inline struct pwm_mediatek_chip *
to_pwm_mediatek_chip(struct pwm_chip *chip)
{
@@ -111,7 +119,19 @@ static inline void pwm_mediatek_writel(s
unsigned int num, unsigned int offset,
u32 value)
{
- writel(value, chip->regs + pwm_mediatek_reg_offset[num] + offset);
+ u32 pwm_offset;
+
+ switch (chip->soc->reg_ver) {
+ case REG_V2:
+ pwm_offset = mtk_pwm_reg_offset_v2[num];
+ break;
+
+ case REG_V1:
+ default:
+ pwm_offset = mtk_pwm_reg_offset_v1[num];
+ }
+
+ writel(value, chip->regs + pwm_offset + offset);
}
static int pwm_mediatek_config(struct pwm_chip *chip, struct pwm_device *pwm,
@@ -146,7 +166,7 @@ static int pwm_mediatek_config(struct pw
if (clkdiv > PWM_CLK_DIV_MAX) {
pwm_mediatek_clk_disable(chip, pwm);
- dev_err(chip->dev, "period %d not supported\n", period_ns);
+ dev_err(chip->dev, "period of %d ns not supported\n", period_ns);
return -EINVAL;
}
@@ -221,24 +241,20 @@ static int pwm_mediatek_probe(struct pla
if (IS_ERR(pc->regs))
return PTR_ERR(pc->regs);
- pc->clk_pwms = devm_kcalloc(&pdev->dev, pc->soc->num_pwms,
+ pc->clk_pwms = devm_kmalloc_array(&pdev->dev, pc->soc->num_pwms,
sizeof(*pc->clk_pwms), GFP_KERNEL);
if (!pc->clk_pwms)
return -ENOMEM;
pc->clk_top = devm_clk_get(&pdev->dev, "top");
- if (IS_ERR(pc->clk_top)) {
- dev_err(&pdev->dev, "clock: top fail: %ld\n",
- PTR_ERR(pc->clk_top));
- return PTR_ERR(pc->clk_top);
- }
+ if (IS_ERR(pc->clk_top))
+ return dev_err_probe(&pdev->dev, PTR_ERR(pc->clk_top),
+ "Failed to get top clock\n");
pc->clk_main = devm_clk_get(&pdev->dev, "main");
- if (IS_ERR(pc->clk_main)) {
- dev_err(&pdev->dev, "clock: main fail: %ld\n",
- PTR_ERR(pc->clk_main));
- return PTR_ERR(pc->clk_main);
- }
+ if (IS_ERR(pc->clk_main))
+ return dev_err_probe(&pdev->dev, PTR_ERR(pc->clk_main),
+ "Failed to get main clock\n");
for (i = 0; i < pc->soc->num_pwms; i++) {
char name[8];
@@ -246,11 +262,9 @@ static int pwm_mediatek_probe(struct pla
snprintf(name, sizeof(name), "pwm%d", i + 1);
pc->clk_pwms[i] = devm_clk_get(&pdev->dev, name);
- if (IS_ERR(pc->clk_pwms[i])) {
- dev_err(&pdev->dev, "clock: %s fail: %ld\n",
- name, PTR_ERR(pc->clk_pwms[i]));
- return PTR_ERR(pc->clk_pwms[i]);
- }
+ if (IS_ERR(pc->clk_pwms[i]))
+ return dev_err_probe(&pdev->dev, PTR_ERR(pc->clk_pwms[i]),
+ "Failed to get %s clock\n", name);
}
pc->chip.dev = &pdev->dev;
@@ -258,10 +272,8 @@ static int pwm_mediatek_probe(struct pla
pc->chip.npwm = pc->soc->num_pwms;
ret = devm_pwmchip_add(&pdev->dev, &pc->chip);
- if (ret < 0) {
- dev_err(&pdev->dev, "pwmchip_add() failed: %d\n", ret);
- return ret;
- }
+ if (ret < 0)
+ return dev_err_probe(&pdev->dev, ret, "pwmchip_add() failed\n");
return 0;
}
@@ -270,48 +282,63 @@ static const struct pwm_mediatek_of_data
.num_pwms = 8,
.pwm45_fixup = false,
.has_ck_26m_sel = false,
+ .reg_ver = REG_V1,
};
static const struct pwm_mediatek_of_data mt7622_pwm_data = {
.num_pwms = 6,
.pwm45_fixup = false,
.has_ck_26m_sel = true,
+ .reg_ver = REG_V1,
};
static const struct pwm_mediatek_of_data mt7623_pwm_data = {
.num_pwms = 5,
.pwm45_fixup = true,
.has_ck_26m_sel = false,
+ .reg_ver = REG_V1,
};
static const struct pwm_mediatek_of_data mt7628_pwm_data = {
.num_pwms = 4,
.pwm45_fixup = true,
.has_ck_26m_sel = false,
+ .reg_ver = REG_V1,
};
static const struct pwm_mediatek_of_data mt7629_pwm_data = {
.num_pwms = 1,
.pwm45_fixup = false,
.has_ck_26m_sel = false,
+ .reg_ver = REG_V1,
};
-static const struct pwm_mediatek_of_data mt8183_pwm_data = {
- .num_pwms = 4,
+static const struct pwm_mediatek_of_data mt7981_pwm_data = {
+ .num_pwms = 3,
.pwm45_fixup = false,
.has_ck_26m_sel = true,
+ .reg_ver = REG_V2,
};
static const struct pwm_mediatek_of_data mt7986_pwm_data = {
.num_pwms = 2,
.pwm45_fixup = false,
.has_ck_26m_sel = true,
+ .reg_ver = REG_V1,
+};
+
+static const struct pwm_mediatek_of_data mt8183_pwm_data = {
+ .num_pwms = 4,
+ .pwm45_fixup = false,
+ .has_ck_26m_sel = true,
+ .reg_ver = REG_V1,
};
static const struct pwm_mediatek_of_data mt8516_pwm_data = {
.num_pwms = 5,
.pwm45_fixup = false,
.has_ck_26m_sel = true,
+ .reg_ver = REG_V1,
};
static const struct of_device_id pwm_mediatek_of_match[] = {
@@ -320,6 +347,7 @@ static const struct of_device_id pwm_med
{ .compatible = "mediatek,mt7623-pwm", .data = &mt7623_pwm_data },
{ .compatible = "mediatek,mt7628-pwm", .data = &mt7628_pwm_data },
{ .compatible = "mediatek,mt7629-pwm", .data = &mt7629_pwm_data },
+ { .compatible = "mediatek,mt7981-pwm", .data = &mt7981_pwm_data },
{ .compatible = "mediatek,mt7986-pwm", .data = &mt7986_pwm_data },
{ .compatible = "mediatek,mt8183-pwm", .data = &mt8183_pwm_data },
{ .compatible = "mediatek,mt8516-pwm", .data = &mt8516_pwm_data },

View File

@ -1,6 +1,6 @@
--- a/drivers/spi/spi-mt65xx.c
+++ b/drivers/spi/spi-mt65xx.c
@@ -1223,10 +1223,16 @@ static int mtk_spi_probe(struct platform
@@ -1231,10 +1231,16 @@ static int mtk_spi_probe(struct platform
goto err_disable_spi_hclk;
}
@ -18,7 +18,7 @@
}
mdata->spi_clk_hz = clk_get_rate(mdata->spi_clk);
@@ -1277,6 +1283,8 @@ static int mtk_spi_probe(struct platform
@@ -1285,6 +1291,8 @@ static int mtk_spi_probe(struct platform
err_disable_runtime_pm:
pm_runtime_disable(&pdev->dev);

View File

@ -14,7 +14,7 @@ Signed-off-by: René van Dorst <opensource@vdorst.com>
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -4228,6 +4228,7 @@ static const struct net_device_ops mtk_n
@@ -4259,6 +4259,7 @@ static const struct net_device_ops mtk_n
static int mtk_add_mac(struct mtk_eth *eth, struct device_node *np)
{
@ -22,7 +22,7 @@ Signed-off-by: René van Dorst <opensource@vdorst.com>
const __be32 *_id = of_get_property(np, "reg", NULL);
phy_interface_t phy_mode;
struct phylink *phylink;
@@ -4356,6 +4357,9 @@ static int mtk_add_mac(struct mtk_eth *e
@@ -4387,6 +4388,9 @@ static int mtk_add_mac(struct mtk_eth *e
register_netdevice_notifier(&mac->device_notifier);
}

View File

@ -95,7 +95,7 @@ still required by target/linux/ramips/files/drivers/net/ethernet/ralink/mdio.c
phydev->mii_ts->link_state(phydev->mii_ts, phydev);
--- a/drivers/net/phy/phylink.c
+++ b/drivers/net/phy/phylink.c
@@ -1323,7 +1323,8 @@ void phylink_destroy(struct phylink *pl)
@@ -1322,7 +1322,8 @@ void phylink_destroy(struct phylink *pl)
}
EXPORT_SYMBOL_GPL(phylink_destroy);

View File

@ -32,7 +32,7 @@ Signed-off-by: Guenter Roeck <linux@roeck-us.net>
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -15891,6 +15891,13 @@ S: Maintained
@@ -15899,6 +15899,13 @@ S: Maintained
F: include/sound/rt*.h
F: sound/soc/codecs/rt*

View File

@ -22,7 +22,7 @@ Submitted-by: John Crispin <john@phrozen.org>
--- a/drivers/net/dsa/Kconfig
+++ b/drivers/net/dsa/Kconfig
@@ -60,6 +60,8 @@ source "drivers/net/dsa/sja1105/Kconfig"
@@ -61,6 +61,8 @@ source "drivers/net/dsa/sja1105/Kconfig"
source "drivers/net/dsa/xrs700x/Kconfig"

View File

@ -21,7 +21,7 @@ Submitted-by: John Crispin <john@phrozen.org>
--- a/drivers/net/phy/phylink.c
+++ b/drivers/net/phy/phylink.c
@@ -1943,6 +1943,11 @@ int phylink_ethtool_ksettings_set(struct
@@ -1942,6 +1942,11 @@ int phylink_ethtool_ksettings_set(struct
* the presence of a PHY, this should not be changed as that
* should be determined from the media side advertisement.
*/
@ -33,7 +33,7 @@ Submitted-by: John Crispin <john@phrozen.org>
return phy_ethtool_ksettings_set(pl->phydev, kset);
}
@@ -2246,8 +2251,11 @@ int phylink_ethtool_get_eee(struct phyli
@@ -2245,8 +2250,11 @@ int phylink_ethtool_get_eee(struct phyli
ASSERT_RTNL();
@ -46,7 +46,7 @@ Submitted-by: John Crispin <john@phrozen.org>
return ret;
}
@@ -2264,8 +2272,11 @@ int phylink_ethtool_set_eee(struct phyli
@@ -2263,8 +2271,11 @@ int phylink_ethtool_set_eee(struct phyli
ASSERT_RTNL();