aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichal Meloun <mmel@FreeBSD.org>2021-02-03 08:51:45 +0000
committerMichal Meloun <mmel@FreeBSD.org>2023-01-03 09:19:29 +0000
commite4ef4c5d66c3680ed32a8b77f960c728ecf2a1b7 (patch)
treedd2abb6862586c6d9d8e09c8a317069de4596d83
parent2ce3ef55035093cac7839e71e9ff91f5562ebc29 (diff)
downloadsrc-e4ef4c5d66c3680ed32a8b77f960c728ecf2a1b7.tar.gz
src-e4ef4c5d66c3680ed32a8b77f960c728ecf2a1b7.zip
extres/phy: Add mode setting function.
Modern multi-protocol phys are capable of supporting multiple different protocols. Add a method for mode (and/or its variants) setting. Discused with: ganbold, manu, andrew MFC after: 3 weeks
-rw-r--r--sys/dev/extres/phy/phy.c34
-rw-r--r--sys/dev/extres/phy/phy.h66
-rw-r--r--sys/dev/extres/phy/phynode_if.m14
3 files changed, 105 insertions, 9 deletions
diff --git a/sys/dev/extres/phy/phy.c b/sys/dev/extres/phy/phy.c
index 0ed633ffbe41..8861102b8508 100644
--- a/sys/dev/extres/phy/phy.c
+++ b/sys/dev/extres/phy/phy.c
@@ -1,6 +1,5 @@
/*-
* Copyright 2016 Michal Meloun <mmel@FreeBSD.org>
- * All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -25,7 +24,6 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
#include "opt_platform.h"
#include <sys/param.h>
@@ -271,6 +269,22 @@ phynode_disable(struct phynode *phynode)
return (0);
}
+/*
+ * Set phy mode (protocol and its variant).
+ */
+int
+phynode_set_mode(struct phynode *phynode, phy_mode_t mode,
+ phy_submode_t submode)
+{
+ int rv;
+
+ PHY_TOPO_ASSERT();
+
+ PHYNODE_XLOCK(phynode);
+ rv = PHYNODE_SET_MODE(phynode, mode, submode);
+ PHYNODE_UNLOCK(phynode);
+ return (rv);
+}
/*
* Get phy status. (PHY_STATUS_*)
@@ -354,6 +368,22 @@ phy_disable(phy_t phy)
}
int
+phy_set_mode(phy_t phy, phy_mode_t mode, phy_submode_t submode)
+{
+ int rv;
+ struct phynode *phynode;
+
+ phynode = phy->phynode;
+ KASSERT(phynode->ref_cnt > 0,
+ ("Attempt to access unreferenced phy.\n"));
+
+ PHY_TOPO_SLOCK();
+ rv = phynode_set_mode(phynode, mode, submode);
+ PHY_TOPO_UNLOCK();
+ return (rv);
+}
+
+int
phy_status(phy_t phy, int *status)
{
int rv;
diff --git a/sys/dev/extres/phy/phy.h b/sys/dev/extres/phy/phy.h
index b0e5249e4246..a72904a10e2b 100644
--- a/sys/dev/extres/phy/phy.h
+++ b/sys/dev/extres/phy/phy.h
@@ -1,6 +1,5 @@
/*-
* Copyright 2016 Michal Meloun <mmel@FreeBSD.org>
- * All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -22,7 +21,6 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
- * $FreeBSD$
*/
#ifndef DEV_EXTRES_PHY_H
@@ -33,10 +31,66 @@
#ifdef FDT
#include <dev/ofw/ofw_bus.h>
#endif
-#include "phynode_if.h"
#define PHY_STATUS_ENABLED 0x00000001
+typedef enum phy_mode {
+ PHY_MODE_INVALID,
+ PHY_MODE_USB_HOST,
+ PHY_MODE_USB_DEVICE,
+ PHY_MODE_USB_OTG,
+ PHY_MODE_UFS,
+ PHY_MODE_PCIE,
+ PHY_MODE_ETHERNET,
+ PHY_MODE_MIPI_DPHY,
+ PHY_MODE_SATA,
+ PHY_MODE_LVDS,
+ PHY_MODE_DP
+} phy_mode_t ;
+
+typedef enum phy_submode {
+ /* Common */
+ PHY_SUBMODE_NA = 0, /* Not applicable */
+ PHY_SUBMODE_INTERNAL,
+
+ /* Ethernet */
+ PHY_SUBMODE_ETH_MII = 1000,
+ PHY_SUBMODE_ETH_GMII,
+ PHY_SUBMODE_ETH_SGMII,
+ PHY_SUBMODE_ETH_TBI,
+ PHY_SUBMODE_ETH_REVMII,
+ PHY_SUBMODE_ETH_RMII,
+ PHY_SUBMODE_ETH_RGMII,
+ PHY_SUBMODE_ETH_RGMII_ID,
+ PHY_SUBMODE_ETH_RGMII_RXID,
+ PHY_SUBMODE_ETH_RGMII_TXID,
+ PHY_SUBMODE_ETH_RTBI,
+ PHY_SUBMODE_ETH_SMII,
+ PHY_SUBMODE_ETH_XGMII,
+ PHY_SUBMODE_ETH_XLGMII,
+ PHY_SUBMODE_ETH_MOCA,
+ PHY_SUBMODE_ETH_QSGMII,
+ PHY_SUBMODE_ETH_TRGMII,
+ PHY_SUBMODE_ETH_1000BASEX,
+ PHY_SUBMODE_ETH_2500BASEX,
+ PHY_SUBMODE_ETH_RXAUI,
+ PHY_SUBMODE_ETH_XAUI,
+ PHY_SUBMODE_ETH_10GBASER,
+ PHY_SUBMODE_ETH_USXGMII,
+ PHY_SUBMODE_ETH_10GKR,
+
+ /* USB */
+ PHY_SUBMODE_USB_LS = 2000,
+ PHY_SUBMODE_USB_FS,
+ PHY_SUBMODE_USB_HS,
+ PHY_SUBMODE_USB_SS,
+
+ /* UFS */
+ PHY_SUBMODE_UFS_HS_A = 3000,
+ PHY_SUBMODE_UFS_HS_B,
+
+} phy_submode_t;
+
typedef struct phy *phy_t;
/* Initialization parameters. */
@@ -47,6 +101,8 @@ struct phynode_init_def {
#endif
};
+#include "phynode_if.h"
+
/*
* Shorthands for constructing method tables.
*/
@@ -67,6 +123,8 @@ device_t phynode_get_device(struct phynode *phynode);
intptr_t phynode_get_id(struct phynode *phynode);
int phynode_enable(struct phynode *phynode);
int phynode_disable(struct phynode *phynode);
+int phynode_set_mode(struct phynode *phynode, phy_mode_t mode,
+ phy_submode_t submode);
int phynode_status(struct phynode *phynode, int *status);
#ifdef FDT
phandle_t phynode_get_ofw_node(struct phynode *phynode);
@@ -80,8 +138,8 @@ int phy_get_by_id(device_t consumer_dev, device_t provider_dev, intptr_t id,
void phy_release(phy_t phy);
int phy_enable(phy_t phy);
int phy_disable(phy_t phy);
+int phy_set_mode(phy_t phy, phy_mode_t mode, phy_submode_t submode);
int phy_status(phy_t phy, int *value);
-
#ifdef FDT
int phy_get_by_ofw_name(device_t consumer, phandle_t node, char *name,
phy_t *phy);
diff --git a/sys/dev/extres/phy/phynode_if.m b/sys/dev/extres/phy/phynode_if.m
index cebfb9a5a163..18b798227109 100644
--- a/sys/dev/extres/phy/phynode_if.m
+++ b/sys/dev/extres/phy/phynode_if.m
@@ -1,6 +1,5 @@
#-
# Copyright 2016 Michal Meloun <mmel@FreeBSD.org>
-# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
@@ -23,12 +22,12 @@
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
# SUCH DAMAGE.
#
-# $FreeBSD$
-#
INTERFACE phynode;
HEADER {
+ #include <dev/extres/phy/phy.h>
+
struct phynode;
}
@@ -59,3 +58,12 @@ METHOD int status {
};
+#
+# Set mode/submode for multiprotocol phy
+# Returns 0 on success or a standard errno value.
+#
+METHOD int set_mode {
+ struct phynode *phynode;
+ phy_mode_t mode;
+ phy_submode_t submode;
+};