aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ethernet/freescale/fman/fman_tgec.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/ethernet/freescale/fman/fman_tgec.c')
-rw-r--r--drivers/net/ethernet/freescale/fman/fman_tgec.c130
1 files changed, 58 insertions, 72 deletions
diff --git a/drivers/net/ethernet/freescale/fman/fman_tgec.c b/drivers/net/ethernet/freescale/fman/fman_tgec.c
index 5a4be54ad45911..c2261d26db5b93 100644
--- a/drivers/net/ethernet/freescale/fman/fman_tgec.c
+++ b/drivers/net/ethernet/freescale/fman/fman_tgec.c
@@ -13,6 +13,7 @@
#include <linux/bitrev.h>
#include <linux/io.h>
#include <linux/crc32.h>
+#include <linux/netdevice.h>
/* Transmit Inter-Packet Gap Length Register (TX_IPG_LENGTH) */
#define TGEC_TX_IPG_LENGTH_MASK 0x000003ff
@@ -243,10 +244,6 @@ static int init(struct tgec_regs __iomem *regs, struct tgec_cfg *cfg,
static int check_init_parameters(struct fman_mac *tgec)
{
- if (tgec->max_speed < SPEED_10000) {
- pr_err("10G MAC driver only support 10G speed\n");
- return -EINVAL;
- }
if (!tgec->exception_cb) {
pr_err("uninitialized exception_cb\n");
return -EINVAL;
@@ -384,40 +381,13 @@ static void free_init_resources(struct fman_mac *tgec)
tgec->unicast_addr_hash = NULL;
}
-static bool is_init_done(struct tgec_cfg *cfg)
-{
- /* Checks if tGEC driver parameters were initialized */
- if (!cfg)
- return true;
-
- return false;
-}
-
static int tgec_enable(struct fman_mac *tgec)
{
- struct tgec_regs __iomem *regs = tgec->regs;
- u32 tmp;
-
- if (!is_init_done(tgec->cfg))
- return -EINVAL;
-
- tmp = ioread32be(&regs->command_config);
- tmp |= CMD_CFG_RX_EN | CMD_CFG_TX_EN;
- iowrite32be(tmp, &regs->command_config);
-
return 0;
}
static void tgec_disable(struct fman_mac *tgec)
{
- struct tgec_regs __iomem *regs = tgec->regs;
- u32 tmp;
-
- WARN_ON_ONCE(!is_init_done(tgec->cfg));
-
- tmp = ioread32be(&regs->command_config);
- tmp &= ~(CMD_CFG_RX_EN | CMD_CFG_TX_EN);
- iowrite32be(tmp, &regs->command_config);
}
static int tgec_set_promiscuous(struct fman_mac *tgec, bool new_val)
@@ -425,9 +395,6 @@ static int tgec_set_promiscuous(struct fman_mac *tgec, bool new_val)
struct tgec_regs __iomem *regs = tgec->regs;
u32 tmp;
- if (!is_init_done(tgec->cfg))
- return -EINVAL;
-
tmp = ioread32be(&regs->command_config);
if (new_val)
tmp |= CMD_CFG_PROMIS_EN;
@@ -444,9 +411,6 @@ static int tgec_set_tx_pause_frames(struct fman_mac *tgec,
{
struct tgec_regs __iomem *regs = tgec->regs;
- if (!is_init_done(tgec->cfg))
- return -EINVAL;
-
iowrite32be((u32)pause_time, &regs->pause_quant);
return 0;
@@ -457,9 +421,6 @@ static int tgec_accept_rx_pause_frames(struct fman_mac *tgec, bool en)
struct tgec_regs __iomem *regs = tgec->regs;
u32 tmp;
- if (!is_init_done(tgec->cfg))
- return -EINVAL;
-
tmp = ioread32be(&regs->command_config);
if (!en)
tmp |= CMD_CFG_PAUSE_IGNORE;
@@ -470,12 +431,52 @@ static int tgec_accept_rx_pause_frames(struct fman_mac *tgec, bool en)
return 0;
}
+static void tgec_mac_config(struct phylink_config *config, unsigned int mode,
+ const struct phylink_link_state *state)
+{
+}
+
+static void tgec_link_up(struct phylink_config *config, struct phy_device *phy,
+ unsigned int mode, phy_interface_t interface,
+ int speed, int duplex, bool tx_pause, bool rx_pause)
+{
+ struct mac_device *mac_dev = fman_config_to_mac(config);
+ struct fman_mac *tgec = mac_dev->fman_mac;
+ struct tgec_regs __iomem *regs = tgec->regs;
+ u16 pause_time = tx_pause ? FSL_FM_PAUSE_TIME_ENABLE :
+ FSL_FM_PAUSE_TIME_DISABLE;
+ u32 tmp;
+
+ tgec_set_tx_pause_frames(tgec, 0, pause_time, 0);
+ tgec_accept_rx_pause_frames(tgec, rx_pause);
+ mac_dev->update_speed(mac_dev, speed);
+
+ tmp = ioread32be(&regs->command_config);
+ tmp |= CMD_CFG_RX_EN | CMD_CFG_TX_EN;
+ iowrite32be(tmp, &regs->command_config);
+}
+
+static void tgec_link_down(struct phylink_config *config, unsigned int mode,
+ phy_interface_t interface)
+{
+ struct fman_mac *tgec = fman_config_to_mac(config)->fman_mac;
+ struct tgec_regs __iomem *regs = tgec->regs;
+ u32 tmp;
+
+ tmp = ioread32be(&regs->command_config);
+ tmp &= ~(CMD_CFG_RX_EN | CMD_CFG_TX_EN);
+ iowrite32be(tmp, &regs->command_config);
+}
+
+static const struct phylink_mac_ops tgec_mac_ops = {
+ .mac_config = tgec_mac_config,
+ .mac_link_up = tgec_link_up,
+ .mac_link_down = tgec_link_down,
+};
+
static int tgec_modify_mac_address(struct fman_mac *tgec,
const enet_addr_t *p_enet_addr)
{
- if (!is_init_done(tgec->cfg))
- return -EINVAL;
-
tgec->addr = ENET_ADDR_TO_UINT64(*p_enet_addr);
set_mac_address(tgec->regs, (const u8 *)(*p_enet_addr));
@@ -490,9 +491,6 @@ static int tgec_add_hash_mac_address(struct fman_mac *tgec,
u32 crc = 0xFFFFFFFF, hash;
u64 addr;
- if (!is_init_done(tgec->cfg))
- return -EINVAL;
-
addr = ENET_ADDR_TO_UINT64(*eth_addr);
if (!(addr & GROUP_ADDRESS)) {
@@ -525,9 +523,6 @@ static int tgec_set_allmulti(struct fman_mac *tgec, bool enable)
u32 entry;
struct tgec_regs __iomem *regs = tgec->regs;
- if (!is_init_done(tgec->cfg))
- return -EINVAL;
-
if (enable) {
for (entry = 0; entry < TGEC_HASH_TABLE_SIZE; entry++)
iowrite32be(entry | TGEC_HASH_MCAST_EN,
@@ -548,9 +543,6 @@ static int tgec_set_tstamp(struct fman_mac *tgec, bool enable)
struct tgec_regs __iomem *regs = tgec->regs;
u32 tmp;
- if (!is_init_done(tgec->cfg))
- return -EINVAL;
-
tmp = ioread32be(&regs->command_config);
if (enable)
@@ -572,9 +564,6 @@ static int tgec_del_hash_mac_address(struct fman_mac *tgec,
u32 crc = 0xFFFFFFFF, hash;
u64 addr;
- if (!is_init_done(tgec->cfg))
- return -EINVAL;
-
addr = ((*(u64 *)eth_addr) >> 16);
/* CRC calculation */
@@ -601,22 +590,12 @@ static int tgec_del_hash_mac_address(struct fman_mac *tgec,
return 0;
}
-static void tgec_adjust_link(struct mac_device *mac_dev)
-{
- struct phy_device *phy_dev = mac_dev->phy_dev;
-
- mac_dev->update_speed(mac_dev, phy_dev->speed);
-}
-
static int tgec_set_exception(struct fman_mac *tgec,
enum fman_mac_exceptions exception, bool enable)
{
struct tgec_regs __iomem *regs = tgec->regs;
u32 bit_mask = 0;
- if (!is_init_done(tgec->cfg))
- return -EINVAL;
-
bit_mask = get_exception_flag(exception);
if (bit_mask) {
if (enable)
@@ -641,9 +620,6 @@ static int tgec_init(struct fman_mac *tgec)
enet_addr_t eth_addr;
int err;
- if (is_init_done(tgec->cfg))
- return -EINVAL;
-
if (DEFAULT_RESET_ON_INIT &&
(fman_reset_mac(tgec->fm, tgec->mac_id) != 0)) {
pr_err("Can't reset MAC!\n");
@@ -753,7 +729,6 @@ static struct fman_mac *tgec_config(struct mac_device *mac_dev,
tgec->regs = mac_dev->vaddr;
tgec->addr = ENET_ADDR_TO_UINT64(mac_dev->addr);
- tgec->max_speed = params->max_speed;
tgec->mac_id = params->mac_id;
tgec->exceptions = (TGEC_IMASK_MDIO_SCAN_EVENT |
TGEC_IMASK_REM_FAULT |
@@ -788,17 +763,15 @@ int tgec_initialization(struct mac_device *mac_dev,
int err;
struct fman_mac *tgec;
+ mac_dev->phylink_ops = &tgec_mac_ops;
mac_dev->set_promisc = tgec_set_promiscuous;
mac_dev->change_addr = tgec_modify_mac_address;
mac_dev->add_hash_mac_addr = tgec_add_hash_mac_address;
mac_dev->remove_hash_mac_addr = tgec_del_hash_mac_address;
- mac_dev->set_tx_pause = tgec_set_tx_pause_frames;
- mac_dev->set_rx_pause = tgec_accept_rx_pause_frames;
mac_dev->set_exception = tgec_set_exception;
mac_dev->set_allmulti = tgec_set_allmulti;
mac_dev->set_tstamp = tgec_set_tstamp;
mac_dev->set_multi = fman_set_multi;
- mac_dev->adjust_link = tgec_adjust_link;
mac_dev->enable = tgec_enable;
mac_dev->disable = tgec_disable;
@@ -808,6 +781,19 @@ int tgec_initialization(struct mac_device *mac_dev,
goto _return;
}
+ /* The internal connection to the serdes is XGMII, but this isn't
+ * really correct for the phy mode (which is the external connection).
+ * However, this is how all older device trees say that they want
+ * XAUI, so just convert it for them.
+ */
+ if (mac_dev->phy_if == PHY_INTERFACE_MODE_XGMII)
+ mac_dev->phy_if = PHY_INTERFACE_MODE_XAUI;
+
+ __set_bit(PHY_INTERFACE_MODE_XAUI,
+ mac_dev->phylink_config.supported_interfaces);
+ mac_dev->phylink_config.mac_capabilities =
+ MAC_SYM_PAUSE | MAC_ASYM_PAUSE | MAC_10000FD;
+
tgec = mac_dev->fman_mac;
tgec->cfg->max_frame_length = fman_get_max_frm();
err = tgec_init(tgec);