aboutsummaryrefslogtreecommitdiff
path: root/drivers/net/phy/microchip_t1s.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2023-06-28 16:43:10 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2023-06-28 16:43:10 -0700
commit3a8a670eeeaa40d87bd38a587438952741980c18 (patch)
treed5546d311271503eadf75b45d87e12720e72899f /drivers/net/phy/microchip_t1s.c
parent6a8cbd9253abc1bd0df4d60c4c24fa555190376d (diff)
parentae230642190a51b85656d6da2df744d534d59544 (diff)
Merge tag 'net-next-6.5' of git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net-next
Pull networking changes from Jakub Kicinski: "WiFi 7 and sendpage changes are the biggest pieces of work for this release. The latter will definitely require fixes but I think that we got it to a reasonable point. Core: - Rework the sendpage & splice implementations Instead of feeding data into sockets page by page extend sendmsg handlers to support taking a reference on the data, controlled by a new flag called MSG_SPLICE_PAGES Rework the handling of unexpected-end-of-file to invoke an additional callback instead of trying to predict what the right combination of MORE/NOTLAST flags is Remove the MSG_SENDPAGE_NOTLAST flag completely - Implement SCM_PIDFD, a new type of CMSG type analogous to SCM_CREDENTIALS, but it contains pidfd instead of plain pid - Enable socket busy polling with CONFIG_RT - Improve reliability and efficiency of reporting for ref_tracker - Auto-generate a user space C library for various Netlink families Protocols: - Allow TCP to shrink the advertised window when necessary, prevent sk_rcvbuf auto-tuning from growing the window all the way up to tcp_rmem[2] - Use per-VMA locking for "page-flipping" TCP receive zerocopy - Prepare TCP for device-to-device data transfers, by making sure that payloads are always attached to skbs as page frags - Make the backoff time for the first N TCP SYN retransmissions linear. Exponential backoff is unnecessarily conservative - Create a new MPTCP getsockopt to retrieve all info (MPTCP_FULL_INFO) - Avoid waking up applications using TLS sockets until we have a full record - Allow using kernel memory for protocol ioctl callbacks, paving the way to issuing ioctls over io_uring - Add nolocalbypass option to VxLAN, forcing packets to be fully encapsulated even if they are destined for a local IP address - Make TCPv4 use consistent hash in TIME_WAIT and SYN_RECV. Ensure in-kernel ECMP implementation (e.g. Open vSwitch) select the same link for all packets. Support L4 symmetric hashing in Open vSwitch - PPPoE: make number of hash bits configurable - Allow DNS to be overwritten by DHCPACK in the in-kernel DHCP client (ipconfig) - Add layer 2 miss indication and filtering, allowing higher layers (e.g. ACL filters) to make forwarding decisions based on whether packet matched forwarding state in lower devices (bridge) - Support matching on Connectivity Fault Management (CFM) packets - Hide the "link becomes ready" IPv6 messages by demoting their printk level to debug - HSR: don't enable promiscuous mode if device offloads the proto - Support active scanning in IEEE 802.15.4 - Continue work on Multi-Link Operation for WiFi 7 BPF: - Add precision propagation for subprogs and callbacks. This allows maintaining verification efficiency when subprograms are used, or in fact passing the verifier at all for complex programs, especially those using open-coded iterators - Improve BPF's {g,s}setsockopt() length handling. Previously BPF assumed the length is always equal to the amount of written data. But some protos allow passing a NULL buffer to discover what the output buffer *should* be, without writing anything - Accept dynptr memory as memory arguments passed to helpers - Add routing table ID to bpf_fib_lookup BPF helper - Support O_PATH FDs in BPF_OBJ_PIN and BPF_OBJ_GET commands - Drop bpf_capable() check in BPF_MAP_FREEZE command (used to mark maps as read-only) - Show target_{obj,btf}_id in tracing link fdinfo - Addition of several new kfuncs (most of the names are self-explanatory): - Add a set of new dynptr kfuncs: bpf_dynptr_adjust(), bpf_dynptr_is_null(), bpf_dynptr_is_rdonly(), bpf_dynptr_size() and bpf_dynptr_clone(). - bpf_task_under_cgroup() - bpf_sock_destroy() - force closing sockets - bpf_cpumask_first_and(), rework bpf_cpumask_any*() kfuncs Netfilter: - Relax set/map validation checks in nf_tables. Allow checking presence of an entry in a map without using the value - Increase ip_vs_conn_tab_bits range for 64BIT builds - Allow updating size of a set - Improve NAT tuple selection when connection is closing Driver API: - Integrate netdev with LED subsystem, to allow configuring HW "offloaded" blinking of LEDs based on link state and activity (i.e. packets coming in and out) - Support configuring rate selection pins of SFP modules - Factor Clause 73 auto-negotiation code out of the drivers, provide common helper routines - Add more fool-proof helpers for managing lifetime of MDIO devices associated with the PCS layer - Allow drivers to report advanced statistics related to Time Aware scheduler offload (taprio) - Allow opting out of VF statistics in link dump, to allow more VFs to fit into the message - Split devlink instance and devlink port operations New hardware / drivers: - Ethernet: - Synopsys EMAC4 IP support (stmmac) - Marvell 88E6361 8 port (5x1GE + 3x2.5GE) switches - Marvell 88E6250 7 port switches - Microchip LAN8650/1 Rev.B0 PHYs - MediaTek MT7981/MT7988 built-in 1GE PHY driver - WiFi: - Realtek RTL8192FU, 2.4 GHz, b/g/n mode, 2T2R, 300 Mbps - Realtek RTL8723DS (SDIO variant) - Realtek RTL8851BE - CAN: - Fintek F81604 Drivers: - Ethernet NICs: - Intel (100G, ice): - support dynamic interrupt allocation - use meta data match instead of VF MAC addr on slow-path - nVidia/Mellanox: - extend link aggregation to handle 4, rather than just 2 ports - spawn sub-functions without any features by default - OcteonTX2: - support HTB (Tx scheduling/QoS) offload - make RSS hash generation configurable - support selecting Rx queue using TC filters - Wangxun (ngbe/txgbe): - add basic Tx/Rx packet offloads - add phylink support (SFP/PCS control) - Freescale/NXP (enetc): - report TAPRIO packet statistics - Solarflare/AMD: - support matching on IP ToS and UDP source port of outer header - VxLAN and GENEVE tunnel encapsulation over IPv4 or IPv6 - add devlink dev info support for EF10 - Virtual NICs: - Microsoft vNIC: - size the Rx indirection table based on requested configuration - support VLAN tagging - Amazon vNIC: - try to reuse Rx buffers if not fully consumed, useful for ARM servers running with 16kB pages - Google vNIC: - support TCP segmentation of >64kB frames - Ethernet embedded switches: - Marvell (mv88e6xxx): - enable USXGMII (88E6191X) - Microchip: - lan966x: add support for Egress Stage 0 ACL engine - lan966x: support mapping packet priority to internal switch priority (based on PCP or DSCP) - Ethernet PHYs: - Broadcom PHYs: - support for Wake-on-LAN for BCM54210E/B50212E - report LPI counter - Microsemi PHYs: support RGMII delay configuration (VSC85xx) - Micrel PHYs: receive timestamp in the frame (LAN8841) - Realtek PHYs: support optional external PHY clock - Altera TSE PCS: merge the driver into Lynx PCS which it is a variant of - CAN: Kvaser PCIEcan: - support packet timestamping - WiFi: - Intel (iwlwifi): - major update for new firmware and Multi-Link Operation (MLO) - configuration rework to drop test devices and split the different families - support for segmented PNVM images and power tables - new vendor entries for PPAG (platform antenna gain) feature - Qualcomm 802.11ax (ath11k): - Multiple Basic Service Set Identifier (MBSSID) and Enhanced MBSSID Advertisement (EMA) support in AP mode - support factory test mode - RealTek (rtw89): - add RSSI based antenna diversity - support U-NII-4 channels on 5 GHz band - RealTek (rtl8xxxu): - AP mode support for 8188f - support USB RX aggregation for the newer chips" * tag 'net-next-6.5' of git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net-next: (1602 commits) net: scm: introduce and use scm_recv_unix helper af_unix: Skip SCM_PIDFD if scm->pid is NULL. net: lan743x: Simplify comparison netlink: Add __sock_i_ino() for __netlink_diag_dump(). net: dsa: avoid suspicious RCU usage for synced VLAN-aware MAC addresses Revert "af_unix: Call scm_recv() only after scm_set_cred()." phylink: ReST-ify the phylink_pcs_neg_mode() kdoc libceph: Partially revert changes to support MSG_SPLICE_PAGES net: phy: mscc: fix packet loss due to RGMII delays net: mana: use vmalloc_array and vcalloc net: enetc: use vmalloc_array and vcalloc ionic: use vmalloc_array and vcalloc pds_core: use vmalloc_array and vcalloc gve: use vmalloc_array and vcalloc octeon_ep: use vmalloc_array and vcalloc net: usb: qmi_wwan: add u-blox 0x1312 composition perf trace: fix MSG_SPLICE_PAGES build error ipvlan: Fix return value of ipvlan_queue_xmit() netfilter: nf_tables: fix underflow in chain reference counter netfilter: nf_tables: unbind non-anonymous set if rule construction fails ...
Diffstat (limited to 'drivers/net/phy/microchip_t1s.c')
-rw-r--r--drivers/net/phy/microchip_t1s.c274
1 files changed, 221 insertions, 53 deletions
diff --git a/drivers/net/phy/microchip_t1s.c b/drivers/net/phy/microchip_t1s.c
index 094967b3c111..534ca7d1b061 100644
--- a/drivers/net/phy/microchip_t1s.c
+++ b/drivers/net/phy/microchip_t1s.c
@@ -1,19 +1,29 @@
// SPDX-License-Identifier: GPL-2.0+
/*
- * Driver for Microchip 10BASE-T1S LAN867X PHY
+ * Driver for Microchip 10BASE-T1S PHYs
*
* Support: Microchip Phys:
- * lan8670, lan8671, lan8672
+ * lan8670/1/2 Rev.B1
+ * lan8650/1 Rev.B0 Internal PHYs
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/phy.h>
-#define PHY_ID_LAN867X 0x0007C160
+#define PHY_ID_LAN867X_REVB1 0x0007C162
+#define PHY_ID_LAN865X_REVB0 0x0007C1B3
-#define LAN867X_REG_IRQ_1_CTL 0x001C
-#define LAN867X_REG_IRQ_2_CTL 0x001D
+#define LAN867X_REG_STS2 0x0019
+
+#define LAN867x_RESET_COMPLETE_STS BIT(11)
+
+#define LAN865X_REG_CFGPARAM_ADDR 0x00D8
+#define LAN865X_REG_CFGPARAM_DATA 0x00D9
+#define LAN865X_REG_CFGPARAM_CTRL 0x00DA
+#define LAN865X_REG_STS2 0x0019
+
+#define LAN865X_CFGPARAM_READ_ENABLE BIT(1)
/* The arrays below are pulled from the following table from AN1699
* Access MMD Address Value Mask
@@ -31,72 +41,219 @@
* W 0x1F 0x0099 0x7F80 ------
*/
-static const int lan867x_fixup_registers[12] = {
+static const u32 lan867x_revb1_fixup_registers[12] = {
0x00D0, 0x00D1, 0x0084, 0x0085,
0x008A, 0x0087, 0x0088, 0x008B,
0x0080, 0x00F1, 0x0096, 0x0099,
};
-static const int lan867x_fixup_values[12] = {
+static const u16 lan867x_revb1_fixup_values[12] = {
0x0002, 0x0000, 0x3380, 0x0006,
0xC000, 0x801C, 0x033F, 0x0404,
0x0600, 0x2400, 0x2000, 0x7F80,
};
-static const int lan867x_fixup_masks[12] = {
+static const u16 lan867x_revb1_fixup_masks[12] = {
0x0E03, 0x0300, 0xFFC0, 0x000F,
0xF800, 0x801C, 0x1FFF, 0xFFFF,
0x0600, 0x7F00, 0x2000, 0xFFFF,
};
-static int lan867x_config_init(struct phy_device *phydev)
+/* LAN865x Rev.B0 configuration parameters from AN1760 */
+static const u32 lan865x_revb0_fixup_registers[28] = {
+ 0x0091, 0x0081, 0x0043, 0x0044,
+ 0x0045, 0x0053, 0x0054, 0x0055,
+ 0x0040, 0x0050, 0x00D0, 0x00E9,
+ 0x00F5, 0x00F4, 0x00F8, 0x00F9,
+ 0x00B0, 0x00B1, 0x00B2, 0x00B3,
+ 0x00B4, 0x00B5, 0x00B6, 0x00B7,
+ 0x00B8, 0x00B9, 0x00BA, 0x00BB,
+};
+
+static const u16 lan865x_revb0_fixup_values[28] = {
+ 0x9660, 0x00C0, 0x00FF, 0xFFFF,
+ 0x0000, 0x00FF, 0xFFFF, 0x0000,
+ 0x0002, 0x0002, 0x5F21, 0x9E50,
+ 0x1CF8, 0xC020, 0x9B00, 0x4E53,
+ 0x0103, 0x0910, 0x1D26, 0x002A,
+ 0x0103, 0x070D, 0x1720, 0x0027,
+ 0x0509, 0x0E13, 0x1C25, 0x002B,
+};
+
+static const u16 lan865x_revb0_fixup_cfg_regs[5] = {
+ 0x0084, 0x008A, 0x00AD, 0x00AE, 0x00AF
+};
+
+/* Pulled from AN1760 describing 'indirect read'
+ *
+ * write_register(0x4, 0x00D8, addr)
+ * write_register(0x4, 0x00DA, 0x2)
+ * return (int8)(read_register(0x4, 0x00D9))
+ *
+ * 0x4 refers to memory map selector 4, which maps to MDIO_MMD_VEND2
+ */
+static int lan865x_revb0_indirect_read(struct phy_device *phydev, u16 addr)
+{
+ int ret;
+
+ ret = phy_write_mmd(phydev, MDIO_MMD_VEND2, LAN865X_REG_CFGPARAM_ADDR,
+ addr);
+ if (ret)
+ return ret;
+
+ ret = phy_write_mmd(phydev, MDIO_MMD_VEND2, LAN865X_REG_CFGPARAM_CTRL,
+ LAN865X_CFGPARAM_READ_ENABLE);
+ if (ret)
+ return ret;
+
+ return phy_read_mmd(phydev, MDIO_MMD_VEND2, LAN865X_REG_CFGPARAM_DATA);
+}
+
+/* This is pulled straight from AN1760 from 'calculation of offset 1' &
+ * 'calculation of offset 2'
+ */
+static int lan865x_generate_cfg_offsets(struct phy_device *phydev, s8 offsets[2])
+{
+ const u16 fixup_regs[2] = {0x0004, 0x0008};
+ int ret;
+
+ for (int i = 0; i < ARRAY_SIZE(fixup_regs); i++) {
+ ret = lan865x_revb0_indirect_read(phydev, fixup_regs[i]);
+ if (ret < 0)
+ return ret;
+ if (ret & BIT(4))
+ offsets[i] = ret | 0xE0;
+ else
+ offsets[i] = ret;
+ }
+
+ return 0;
+}
+
+static int lan865x_read_cfg_params(struct phy_device *phydev, u16 cfg_params[])
+{
+ int ret;
+
+ for (int i = 0; i < ARRAY_SIZE(lan865x_revb0_fixup_cfg_regs); i++) {
+ ret = phy_read_mmd(phydev, MDIO_MMD_VEND2,
+ lan865x_revb0_fixup_cfg_regs[i]);
+ if (ret < 0)
+ return ret;
+ cfg_params[i] = (u16)ret;
+ }
+
+ return 0;
+}
+
+static int lan865x_write_cfg_params(struct phy_device *phydev, u16 cfg_params[])
{
- /* HW quirk: Microchip states in the application note (AN1699) for the phy
- * that a set of read-modify-write (rmw) operations has to be performed
- * on a set of seemingly magic registers.
- * The result of these operations is just described as 'optimal performance'
- * Microchip gives no explanation as to what these mmd regs do,
- * in fact they are marked as reserved in the datasheet.
- * It is unclear if phy_modify_mmd would be safe to use or if a write
- * really has to happen to each register.
- * In order to exactly conform to what is stated in the AN phy_write_mmd is
- * used, which might then write the same value back as read + modified.
+ int ret;
+
+ for (int i = 0; i < ARRAY_SIZE(lan865x_revb0_fixup_cfg_regs); i++) {
+ ret = phy_write_mmd(phydev, MDIO_MMD_VEND2,
+ lan865x_revb0_fixup_cfg_regs[i],
+ cfg_params[i]);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+static int lan865x_setup_cfgparam(struct phy_device *phydev)
+{
+ u16 cfg_params[ARRAY_SIZE(lan865x_revb0_fixup_cfg_regs)];
+ u16 cfg_results[5];
+ s8 offsets[2];
+ int ret;
+
+ ret = lan865x_generate_cfg_offsets(phydev, offsets);
+ if (ret)
+ return ret;
+
+ ret = lan865x_read_cfg_params(phydev, cfg_params);
+ if (ret)
+ return ret;
+
+ cfg_results[0] = (cfg_params[0] & 0x000F) |
+ FIELD_PREP(GENMASK(15, 10), 9 + offsets[0]) |
+ FIELD_PREP(GENMASK(15, 4), 14 + offsets[0]);
+ cfg_results[1] = (cfg_params[1] & 0x03FF) |
+ FIELD_PREP(GENMASK(15, 10), 40 + offsets[1]);
+ cfg_results[2] = (cfg_params[2] & 0xC0C0) |
+ FIELD_PREP(GENMASK(15, 8), 5 + offsets[0]) |
+ (9 + offsets[0]);
+ cfg_results[3] = (cfg_params[3] & 0xC0C0) |
+ FIELD_PREP(GENMASK(15, 8), 9 + offsets[0]) |
+ (14 + offsets[0]);
+ cfg_results[4] = (cfg_params[4] & 0xC0C0) |
+ FIELD_PREP(GENMASK(15, 8), 17 + offsets[0]) |
+ (22 + offsets[0]);
+
+ return lan865x_write_cfg_params(phydev, cfg_results);
+}
+
+static int lan865x_revb0_config_init(struct phy_device *phydev)
+{
+ int ret;
+
+ /* Reference to AN1760
+ * https://ww1.microchip.com/downloads/aemDocuments/documents/AIS/ProductDocuments/SupportingCollateral/AN-LAN8650-1-Configuration-60001760.pdf
+ */
+ for (int i = 0; i < ARRAY_SIZE(lan865x_revb0_fixup_registers); i++) {
+ ret = phy_write_mmd(phydev, MDIO_MMD_VEND2,
+ lan865x_revb0_fixup_registers[i],
+ lan865x_revb0_fixup_values[i]);
+ if (ret)
+ return ret;
+ }
+ /* Function to calculate and write the configuration parameters in the
+ * 0x0084, 0x008A, 0x00AD, 0x00AE and 0x00AF registers (from AN1760)
*/
+ return lan865x_setup_cfgparam(phydev);
+}
- int reg_value;
+static int lan867x_revb1_config_init(struct phy_device *phydev)
+{
int err;
- int reg;
- /* Read-Modified Write Pseudocode (from AN1699)
- * current_val = read_register(mmd, addr) // Read current register value
- * new_val = current_val AND (NOT mask) // Clear bit fields to be written
- * new_val = new_val OR value // Set bits
- * write_register(mmd, addr, new_val) // Write back updated register value
+ /* The chip completes a reset in 3us, we might get here earlier than
+ * that, as an added margin we'll conditionally sleep 5us.
*/
- for (int i = 0; i < ARRAY_SIZE(lan867x_fixup_registers); i++) {
- reg = lan867x_fixup_registers[i];
- reg_value = phy_read_mmd(phydev, MDIO_MMD_VEND2, reg);
- reg_value &= ~lan867x_fixup_masks[i];
- reg_value |= lan867x_fixup_values[i];
- err = phy_write_mmd(phydev, MDIO_MMD_VEND2, reg, reg_value);
- if (err != 0)
+ err = phy_read_mmd(phydev, MDIO_MMD_VEND2, LAN867X_REG_STS2);
+ if (err < 0)
+ return err;
+
+ if (!(err & LAN867x_RESET_COMPLETE_STS)) {
+ udelay(5);
+ err = phy_read_mmd(phydev, MDIO_MMD_VEND2, LAN867X_REG_STS2);
+ if (err < 0)
return err;
+ if (!(err & LAN867x_RESET_COMPLETE_STS)) {
+ phydev_err(phydev, "PHY reset failed\n");
+ return -ENODEV;
+ }
}
- /* None of the interrupts in the lan867x phy seem relevant.
- * Other phys inspect the link status and call phy_trigger_machine
- * in the interrupt handler.
- * This phy does not support link status, and thus has no interrupt
- * for it either.
- * So we'll just disable all interrupts on the chip.
+ /* Reference to AN1699
+ * https://ww1.microchip.com/downloads/aemDocuments/documents/AIS/ProductDocuments/SupportingCollateral/AN-LAN8670-1-2-config-60001699.pdf
+ * AN1699 says Read, Modify, Write, but the Write is not required if the
+ * register already has the required value. So it is safe to use
+ * phy_modify_mmd here.
*/
- err = phy_write_mmd(phydev, MDIO_MMD_VEND2, LAN867X_REG_IRQ_1_CTL, 0xFFFF);
- if (err != 0)
- return err;
- return phy_write_mmd(phydev, MDIO_MMD_VEND2, LAN867X_REG_IRQ_2_CTL, 0xFFFF);
+ for (int i = 0; i < ARRAY_SIZE(lan867x_revb1_fixup_registers); i++) {
+ err = phy_modify_mmd(phydev, MDIO_MMD_VEND2,
+ lan867x_revb1_fixup_registers[i],
+ lan867x_revb1_fixup_masks[i],
+ lan867x_revb1_fixup_values[i]);
+ if (err)
+ return err;
+ }
+
+ return 0;
}
-static int lan867x_read_status(struct phy_device *phydev)
+static int lan86xx_read_status(struct phy_device *phydev)
{
/* The phy has some limitations, namely:
* - always reports link up
@@ -111,28 +268,39 @@ static int lan867x_read_status(struct phy_device *phydev)
return 0;
}
-static struct phy_driver lan867x_driver[] = {
+static struct phy_driver microchip_t1s_driver[] = {
{
- PHY_ID_MATCH_MODEL(PHY_ID_LAN867X),
- .name = "LAN867X",
+ PHY_ID_MATCH_EXACT(PHY_ID_LAN867X_REVB1),
+ .name = "LAN867X Rev.B1",
.features = PHY_BASIC_T1S_P2MP_FEATURES,
- .config_init = lan867x_config_init,
- .read_status = lan867x_read_status,
+ .config_init = lan867x_revb1_config_init,
+ .read_status = lan86xx_read_status,
.get_plca_cfg = genphy_c45_plca_get_cfg,
.set_plca_cfg = genphy_c45_plca_set_cfg,
.get_plca_status = genphy_c45_plca_get_status,
- }
+ },
+ {
+ PHY_ID_MATCH_EXACT(PHY_ID_LAN865X_REVB0),
+ .name = "LAN865X Rev.B0 Internal Phy",
+ .features = PHY_BASIC_T1S_P2MP_FEATURES,
+ .config_init = lan865x_revb0_config_init,
+ .read_status = lan86xx_read_status,
+ .get_plca_cfg = genphy_c45_plca_get_cfg,
+ .set_plca_cfg = genphy_c45_plca_set_cfg,
+ .get_plca_status = genphy_c45_plca_get_status,
+ },
};
-module_phy_driver(lan867x_driver);
+module_phy_driver(microchip_t1s_driver);
static struct mdio_device_id __maybe_unused tbl[] = {
- { PHY_ID_MATCH_MODEL(PHY_ID_LAN867X) },
+ { PHY_ID_MATCH_EXACT(PHY_ID_LAN867X_REVB1) },
+ { PHY_ID_MATCH_EXACT(PHY_ID_LAN865X_REVB0) },
{ }
};
MODULE_DEVICE_TABLE(mdio, tbl);
-MODULE_DESCRIPTION("Microchip 10BASE-T1S lan867x Phy driver");
+MODULE_DESCRIPTION("Microchip 10BASE-T1S PHYs driver");
MODULE_AUTHOR("Ramón Nordin Rodriguez");
MODULE_LICENSE("GPL");