mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2025-01-27 00:04:47 +08:00
net: stmmac: add fix_mac_speed support for socfpga
This patch adds fix_mac_speed() support for Altera socfpga Ethernet controller. Emac splitter is a soft IP core in FPGA system that converts GMII interface from Synopsys mac to RGMII/SGMII interface. This splitter core is an optional IP if user would like to use RGMII/SGMII interface in their system. Software needs to update a register in splitter core when there is speed change. Signed-off-by: Ley Foon Tan <lftan@altera.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
6e1d0b8988
commit
b4834c86e1
@ -12,6 +12,10 @@ Required properties:
|
||||
- altr,sysmgr-syscon : Should be the phandle to the system manager node that
|
||||
encompasses the glue register, the register offset, and the register shift.
|
||||
|
||||
Optional properties:
|
||||
altr,emac-splitter: Should be the phandle to the emac splitter soft IP node if
|
||||
DWMAC controller is connected emac splitter.
|
||||
|
||||
Example:
|
||||
|
||||
gmac0: ethernet@ff700000 {
|
||||
|
@ -17,6 +17,7 @@
|
||||
|
||||
#include <linux/mfd/syscon.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/of_net.h>
|
||||
#include <linux/phy.h>
|
||||
#include <linux/regmap.h>
|
||||
@ -30,6 +31,12 @@
|
||||
#define SYSMGR_EMACGRP_CTRL_PHYSEL_WIDTH 2
|
||||
#define SYSMGR_EMACGRP_CTRL_PHYSEL_MASK 0x00000003
|
||||
|
||||
#define EMAC_SPLITTER_CTRL_REG 0x0
|
||||
#define EMAC_SPLITTER_CTRL_SPEED_MASK 0x3
|
||||
#define EMAC_SPLITTER_CTRL_SPEED_10 0x2
|
||||
#define EMAC_SPLITTER_CTRL_SPEED_100 0x3
|
||||
#define EMAC_SPLITTER_CTRL_SPEED_1000 0x0
|
||||
|
||||
struct socfpga_dwmac {
|
||||
int interface;
|
||||
u32 reg_offset;
|
||||
@ -37,14 +44,46 @@ struct socfpga_dwmac {
|
||||
struct device *dev;
|
||||
struct regmap *sys_mgr_base_addr;
|
||||
struct reset_control *stmmac_rst;
|
||||
void __iomem *splitter_base;
|
||||
};
|
||||
|
||||
static void socfpga_dwmac_fix_mac_speed(void *priv, unsigned int speed)
|
||||
{
|
||||
struct socfpga_dwmac *dwmac = (struct socfpga_dwmac *)priv;
|
||||
void __iomem *splitter_base = dwmac->splitter_base;
|
||||
u32 val;
|
||||
|
||||
if (!splitter_base)
|
||||
return;
|
||||
|
||||
val = readl(splitter_base + EMAC_SPLITTER_CTRL_REG);
|
||||
val &= ~EMAC_SPLITTER_CTRL_SPEED_MASK;
|
||||
|
||||
switch (speed) {
|
||||
case 1000:
|
||||
val |= EMAC_SPLITTER_CTRL_SPEED_1000;
|
||||
break;
|
||||
case 100:
|
||||
val |= EMAC_SPLITTER_CTRL_SPEED_100;
|
||||
break;
|
||||
case 10:
|
||||
val |= EMAC_SPLITTER_CTRL_SPEED_10;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
writel(val, splitter_base + EMAC_SPLITTER_CTRL_REG);
|
||||
}
|
||||
|
||||
static int socfpga_dwmac_parse_data(struct socfpga_dwmac *dwmac, struct device *dev)
|
||||
{
|
||||
struct device_node *np = dev->of_node;
|
||||
struct regmap *sys_mgr_base_addr;
|
||||
u32 reg_offset, reg_shift;
|
||||
int ret;
|
||||
struct device_node *np_splitter;
|
||||
struct resource res_splitter;
|
||||
|
||||
dwmac->stmmac_rst = devm_reset_control_get(dev,
|
||||
STMMAC_RESOURCE_NAME);
|
||||
@ -73,6 +112,21 @@ static int socfpga_dwmac_parse_data(struct socfpga_dwmac *dwmac, struct device *
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
np_splitter = of_parse_phandle(np, "altr,emac-splitter", 0);
|
||||
if (np_splitter) {
|
||||
if (of_address_to_resource(np_splitter, 0, &res_splitter)) {
|
||||
dev_info(dev, "Missing emac splitter address\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
dwmac->splitter_base = (void *)devm_ioremap_resource(dev,
|
||||
&res_splitter);
|
||||
if (!dwmac->splitter_base) {
|
||||
dev_info(dev, "Failed to mapping emac splitter\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
dwmac->reg_offset = reg_offset;
|
||||
dwmac->reg_shift = reg_shift;
|
||||
dwmac->sys_mgr_base_addr = sys_mgr_base_addr;
|
||||
@ -91,6 +145,7 @@ static int socfpga_dwmac_setup(struct socfpga_dwmac *dwmac)
|
||||
|
||||
switch (phymode) {
|
||||
case PHY_INTERFACE_MODE_RGMII:
|
||||
case PHY_INTERFACE_MODE_RGMII_ID:
|
||||
val = SYSMGR_EMACGRP_CTRL_PHYSEL_ENUM_RGMII;
|
||||
break;
|
||||
case PHY_INTERFACE_MODE_MII:
|
||||
@ -102,6 +157,13 @@ static int socfpga_dwmac_setup(struct socfpga_dwmac *dwmac)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Overwrite val to GMII if splitter core is enabled. The phymode here
|
||||
* is the actual phy mode on phy hardware, but phy interface from
|
||||
* EMAC core is GMII.
|
||||
*/
|
||||
if (dwmac->splitter_base)
|
||||
val = SYSMGR_EMACGRP_CTRL_PHYSEL_ENUM_GMII_MII;
|
||||
|
||||
regmap_read(sys_mgr_base_addr, reg_offset, &ctrl);
|
||||
ctrl &= ~(SYSMGR_EMACGRP_CTRL_PHYSEL_MASK << reg_shift);
|
||||
ctrl |= val << reg_shift;
|
||||
@ -196,4 +258,5 @@ const struct stmmac_of_data socfpga_gmac_data = {
|
||||
.setup = socfpga_dwmac_probe,
|
||||
.init = socfpga_dwmac_init,
|
||||
.exit = socfpga_dwmac_exit,
|
||||
.fix_mac_speed = socfpga_dwmac_fix_mac_speed,
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user