summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSerge Semin <fancer.lancer@gmail.com>2025-09-11 15:12:37 +0300
committerSerge Semin <fancer.lancer@gmail.com>2026-08-13 20:36:54 +0300
commit8d149a427127d12b7ed259c824641968e705b231 (patch)
tree14051a6b44c0bc983db74ec4a866cc128e66a2d0
parent223d668bdffc91eb82ac267586a58de603e8e61c (diff)
downloadlinux-8d149a427127d12b7ed259c824641968e705b231.tar.gz
linux-8d149a427127d12b7ed259c824641968e705b231.zip
net: stmmac: Add GPIO low-level infrastructure
Synopsys DesignWare Ethernet controllers can be synthesized with General-Purpose IOs support. In general these GPIOs can be used for anything (but most likely for the network-specific stuff). Thus the subsequent commits will add the STMMAC sub-module registering a respective GPIO-chip. But before it's done the STMMAC low-level programming interface must be extended. First of all the GPIO data accessors is added. Even though all DW *MAC GPIOs are semantically equivalent their CSR-wise implementation might be different. That is the GPI type set/get, GPI IRQ en/dis, GPI get and GPO set/get functions are either exposed via a single CSR (DW GMAC v3.7x case) or as two control/status registers (DW QoS/XGMAC/etc case). So in order to implement a generic GPIO-chip sub-module in the STMMAC driver these differences will be abstracted out by the stmmac_gpio_ops accessors. Secondly there is an issue connected with the controller resets. The GPIOs embedded into the DW MACs are a subject of the reset-related actions. That is if any hard- or soft-reset of the controller is performed the GPIO settings will be reset as well. If the hard-reset is happening on the device probing stage the soft-reset is executed on each network device open. So should the GPIOs support is added as is to the driver, their hardware implementation will be reset on each network device open cycle. This is definitely not how generic GPIO-chip supposed to work. The only way to fix that is to avoid the soft-reset procedure anyhow. But the rest of the driver code relies on the controller being in a default state on each device opening. Thus the best approach to solve the denoted issue is to replace the controller soft-reset with a proper device cleanup procedure. That's what the second part of the change about - to provide such infrastructure. So the provided programming interface is dedicated to solve the denoted issues above and to prepare the driver for further GPIO-related extensions. It's left unused for now up until the DW MAC GPIO-chip support is added to the driver. Signed-off-by: Serge Semin <fancer.lancer@gmail.com>
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/common.h1
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/hwif.c2
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/hwif.h25
3 files changed, 28 insertions, 0 deletions
diff --git a/drivers/net/ethernet/stmicro/stmmac/common.h b/drivers/net/ethernet/stmicro/stmmac/common.h
index 4a811516474b..ce383f012220 100644
--- a/drivers/net/ethernet/stmicro/stmmac/common.h
+++ b/drivers/net/ethernet/stmicro/stmmac/common.h
@@ -645,6 +645,7 @@ struct mac_device_info {
const struct stmmac_mmc_ops *mmc;
const struct stmmac_est_ops *est;
const struct stmmac_vlan_ops *vlan;
+ const struct stmmac_gpio_ops *gpio;
struct dw_xpcs *xpcs;
struct phylink_pcs *phylink_pcs;
struct mii_regs mii; /* MII register Addresses */
diff --git a/drivers/net/ethernet/stmicro/stmmac/hwif.c b/drivers/net/ethernet/stmicro/stmmac/hwif.c
index 46b8cf7345a8..7d443c274950 100644
--- a/drivers/net/ethernet/stmicro/stmmac/hwif.c
+++ b/drivers/net/ethernet/stmicro/stmmac/hwif.c
@@ -111,6 +111,7 @@ static const struct stmmac_hwif_entry {
const void *mmc;
const void *est;
const void *vlan;
+ const void *gpio;
int (*setup)(struct stmmac_priv *priv);
int (*quirks)(struct stmmac_priv *priv);
} stmmac_hw[] = {
@@ -358,6 +359,7 @@ int stmmac_hwif_init(struct stmmac_priv *priv)
mac->mmc = mac->mmc ? : entry->mmc;
mac->est = mac->est ? : entry->est;
mac->vlan = mac->vlan ? : entry->vlan;
+ mac->gpio = mac->gpio ? : entry->gpio;
priv->hw = mac;
priv->fpe_cfg.reg = entry->regs.fpe_reg;
diff --git a/drivers/net/ethernet/stmicro/stmmac/hwif.h b/drivers/net/ethernet/stmicro/stmmac/hwif.h
index a7f73b039fdf..c8b64b6d47ea 100644
--- a/drivers/net/ethernet/stmicro/stmmac/hwif.h
+++ b/drivers/net/ethernet/stmicro/stmmac/hwif.h
@@ -198,6 +198,8 @@ struct stmmac_dma_ops {
void (*init_tx_chan)(struct stmmac_priv *priv, void __iomem *ioaddr,
struct stmmac_dma_cfg *dma_cfg,
dma_addr_t phy, u32 chan);
+ /* DMA core cleanup */
+ void (*clean)(struct stmmac_priv *priv, void __iomem *ioaddr);
/* Configure the AXI Bus Mode Register */
void (*axi)(void __iomem *ioaddr, struct stmmac_axi *axi);
/* Dump DMA registers */
@@ -262,6 +264,8 @@ struct stmmac_dma_ops {
stmmac_do_void_callback(__priv, dma, init_rx_chan, __priv, __args)
#define stmmac_init_tx_chan(__priv, __args...) \
stmmac_do_void_callback(__priv, dma, init_tx_chan, __priv, __args)
+#define stmmac_dma_clean(__priv, __args...) \
+ stmmac_do_void_callback(__priv, dma, clean, __priv, __args)
#define stmmac_axi(__priv, __args...) \
stmmac_do_void_callback(__priv, dma, axi, __args)
#define stmmac_dump_dma_regs(__priv, __args...) \
@@ -332,6 +336,10 @@ struct stmmac_ops {
int (*pcs_init)(struct stmmac_priv *priv);
/* MAC core initialization */
void (*core_init)(struct mac_device_info *hw, struct net_device *dev);
+ /* MAC core stop */
+ int (*core_stop)(struct mac_device_info *hw);
+ /* MAC core cleanup */
+ void (*core_clean)(struct mac_device_info *hw);
/* Update MAC capabilities */
void (*update_caps)(struct stmmac_priv *priv);
/* Change the interrupt enable setting. Enable takes precedence. */
@@ -439,6 +447,10 @@ struct stmmac_ops {
stmmac_do_callback(__priv, mac, pcs_init, __priv)
#define stmmac_core_init(__priv, __args...) \
stmmac_do_void_callback(__priv, mac, core_init, __args)
+#define stmmac_core_stop(__priv, __args...) \
+ stmmac_do_callback(__priv, mac, core_stop, __args)
+#define stmmac_core_clean(__priv, __args...) \
+ stmmac_do_void_callback(__priv, mac, core_clean, __args)
#define stmmac_mac_update_caps(__priv) \
stmmac_do_void_callback(__priv, mac, update_caps, __priv)
#define stmmac_mac_irq_modify(__priv, __args...) \
@@ -662,6 +674,19 @@ struct stmmac_vlan_ops {
#define stmmac_restore_hw_vlan_rx_fltr(__priv, __args...) \
stmmac_do_void_callback(__priv, vlan, restore_hw_vlan_rx_fltr, __args)
+struct stmmac_gpio_ops {
+ void (*set_ctrl)(struct stmmac_priv *priv, u32 gpie, u32 gpit, u32 gpo);
+ void (*get_ctrl)(struct stmmac_priv *priv, u32 *gpie, u32 *gpit, u32 *gpo);
+ int (*get_gpis)(struct stmmac_priv *priv);
+};
+
+#define stmmac_gpio_set_ctrl(__priv, __args...) \
+ stmmac_do_void_callback(__priv, gpio, set_ctrl, __priv, __args)
+#define stmmac_gpio_get_ctrl(__priv, __args...) \
+ stmmac_do_void_callback(__priv, gpio, get_ctrl, __priv, __args)
+#define stmmac_gpio_get_gpis(__priv) \
+ stmmac_do_callback(__priv, gpio, get_gpis, __priv)
+
struct stmmac_regs_off {
const struct stmmac_fpe_reg *fpe_reg;
u32 ptp_off;