diff options
-rw-r--r-- | drivers/net/ethernet/freescale/fman/mac.c | 356 | ||||
-rw-r--r-- | drivers/net/ethernet/freescale/fman/mac.h | 1 |
2 files changed, 165 insertions, 192 deletions
diff --git a/drivers/net/ethernet/freescale/fman/mac.c b/drivers/net/ethernet/freescale/fman/mac.c index 0af6f6c49284..8dd6a5b12922 100644 --- a/drivers/net/ethernet/freescale/fman/mac.c +++ b/drivers/net/ethernet/freescale/fman/mac.c @@ -88,159 +88,6 @@ static int set_fman_mac_params(struct mac_device *mac_dev, return 0; } -static int tgec_initialization(struct mac_device *mac_dev, - struct device_node *mac_node) -{ - int err; - struct mac_priv_s *priv; - struct fman_mac_params params; - u32 version; - - priv = mac_dev->priv; - - err = set_fman_mac_params(mac_dev, ¶ms); - if (err) - goto _return; - - mac_dev->fman_mac = tgec_config(¶ms); - if (!mac_dev->fman_mac) { - err = -EINVAL; - goto _return; - } - - err = tgec_cfg_max_frame_len(mac_dev->fman_mac, fman_get_max_frm()); - if (err < 0) - goto _return_fm_mac_free; - - err = tgec_init(mac_dev->fman_mac); - if (err < 0) - goto _return_fm_mac_free; - - /* For 10G MAC, disable Tx ECC exception */ - err = mac_dev->set_exception(mac_dev->fman_mac, - FM_MAC_EX_10G_TX_ECC_ER, false); - if (err < 0) - goto _return_fm_mac_free; - - err = tgec_get_version(mac_dev->fman_mac, &version); - if (err < 0) - goto _return_fm_mac_free; - - dev_info(priv->dev, "FMan XGEC version: 0x%08x\n", version); - - goto _return; - -_return_fm_mac_free: - tgec_free(mac_dev->fman_mac); - -_return: - return err; -} - -static int dtsec_initialization(struct mac_device *mac_dev, - struct device_node *mac_node) -{ - int err; - struct mac_priv_s *priv; - struct fman_mac_params params; - u32 version; - - priv = mac_dev->priv; - - err = set_fman_mac_params(mac_dev, ¶ms); - if (err) - goto _return; - params.internal_phy_node = of_parse_phandle(mac_node, "tbi-handle", 0); - - mac_dev->fman_mac = dtsec_config(¶ms); - if (!mac_dev->fman_mac) { - err = -EINVAL; - goto _return; - } - - err = dtsec_cfg_max_frame_len(mac_dev->fman_mac, fman_get_max_frm()); - if (err < 0) - goto _return_fm_mac_free; - - err = dtsec_cfg_pad_and_crc(mac_dev->fman_mac, true); - if (err < 0) - goto _return_fm_mac_free; - - err = dtsec_init(mac_dev->fman_mac); - if (err < 0) - goto _return_fm_mac_free; - - /* For 1G MAC, disable by default the MIB counters overflow interrupt */ - err = mac_dev->set_exception(mac_dev->fman_mac, - FM_MAC_EX_1G_RX_MIB_CNT_OVFL, false); - if (err < 0) - goto _return_fm_mac_free; - - err = dtsec_get_version(mac_dev->fman_mac, &version); - if (err < 0) - goto _return_fm_mac_free; - - dev_info(priv->dev, "FMan dTSEC version: 0x%08x\n", version); - - goto _return; - -_return_fm_mac_free: - dtsec_free(mac_dev->fman_mac); - -_return: - return err; -} - -static int memac_initialization(struct mac_device *mac_dev, - struct device_node *mac_node) -{ - int err; - struct mac_priv_s *priv; - struct fman_mac_params params; - - priv = mac_dev->priv; - - err = set_fman_mac_params(mac_dev, ¶ms); - if (err) - goto _return; - params.internal_phy_node = of_parse_phandle(mac_node, "pcsphy-handle", 0); - - if (priv->max_speed == SPEED_10000) - params.phy_if = PHY_INTERFACE_MODE_XGMII; - - mac_dev->fman_mac = memac_config(¶ms); - if (!mac_dev->fman_mac) { - err = -EINVAL; - goto _return; - } - - err = memac_cfg_max_frame_len(mac_dev->fman_mac, fman_get_max_frm()); - if (err < 0) - goto _return_fm_mac_free; - - err = memac_cfg_reset_on_init(mac_dev->fman_mac, true); - if (err < 0) - goto _return_fm_mac_free; - - err = memac_cfg_fixed_link(mac_dev->fman_mac, priv->fixed_link); - if (err < 0) - goto _return_fm_mac_free; - - err = memac_init(mac_dev->fman_mac); - if (err < 0) - goto _return_fm_mac_free; - - dev_info(priv->dev, "FMan MEMAC\n"); - - goto _return; - -_return_fm_mac_free: - memac_free(mac_dev->fman_mac); - -_return: - return err; -} - static int set_multi(struct net_device *net_dev, struct mac_device *mac_dev) { struct mac_priv_s *priv; @@ -418,27 +265,15 @@ static void adjust_link_memac(struct mac_device *mac_dev) err); } -static void setup_dtsec(struct mac_device *mac_dev) +static int tgec_initialization(struct mac_device *mac_dev, + struct device_node *mac_node) { - mac_dev->init = dtsec_initialization; - mac_dev->set_promisc = dtsec_set_promiscuous; - mac_dev->change_addr = dtsec_modify_mac_address; - mac_dev->add_hash_mac_addr = dtsec_add_hash_mac_address; - mac_dev->remove_hash_mac_addr = dtsec_del_hash_mac_address; - mac_dev->set_tx_pause = dtsec_set_tx_pause_frames; - mac_dev->set_rx_pause = dtsec_accept_rx_pause_frames; - mac_dev->set_exception = dtsec_set_exception; - mac_dev->set_allmulti = dtsec_set_allmulti; - mac_dev->set_tstamp = dtsec_set_tstamp; - mac_dev->set_multi = set_multi; - mac_dev->adjust_link = adjust_link_dtsec; - mac_dev->enable = dtsec_enable; - mac_dev->disable = dtsec_disable; -} + int err; + struct mac_priv_s *priv; + struct fman_mac_params params; + u32 version; -static void setup_tgec(struct mac_device *mac_dev) -{ - mac_dev->init = tgec_initialization; + priv = mac_dev->priv; 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; @@ -452,11 +287,121 @@ static void setup_tgec(struct mac_device *mac_dev) mac_dev->adjust_link = adjust_link_void; mac_dev->enable = tgec_enable; mac_dev->disable = tgec_disable; + + err = set_fman_mac_params(mac_dev, ¶ms); + if (err) + goto _return; + + mac_dev->fman_mac = tgec_config(¶ms); + if (!mac_dev->fman_mac) { + err = -EINVAL; + goto _return; + } + + err = tgec_cfg_max_frame_len(mac_dev->fman_mac, fman_get_max_frm()); + if (err < 0) + goto _return_fm_mac_free; + + err = tgec_init(mac_dev->fman_mac); + if (err < 0) + goto _return_fm_mac_free; + + /* For 10G MAC, disable Tx ECC exception */ + err = mac_dev->set_exception(mac_dev->fman_mac, + FM_MAC_EX_10G_TX_ECC_ER, false); + if (err < 0) + goto _return_fm_mac_free; + + err = tgec_get_version(mac_dev->fman_mac, &version); + if (err < 0) + goto _return_fm_mac_free; + + dev_info(priv->dev, "FMan XGEC version: 0x%08x\n", version); + + goto _return; + +_return_fm_mac_free: + tgec_free(mac_dev->fman_mac); + +_return: + return err; +} + +static int dtsec_initialization(struct mac_device *mac_dev, + struct device_node *mac_node) +{ + int err; + struct mac_priv_s *priv; + struct fman_mac_params params; + u32 version; + + priv = mac_dev->priv; + mac_dev->set_promisc = dtsec_set_promiscuous; + mac_dev->change_addr = dtsec_modify_mac_address; + mac_dev->add_hash_mac_addr = dtsec_add_hash_mac_address; + mac_dev->remove_hash_mac_addr = dtsec_del_hash_mac_address; + mac_dev->set_tx_pause = dtsec_set_tx_pause_frames; + mac_dev->set_rx_pause = dtsec_accept_rx_pause_frames; + mac_dev->set_exception = dtsec_set_exception; + mac_dev->set_allmulti = dtsec_set_allmulti; + mac_dev->set_tstamp = dtsec_set_tstamp; + mac_dev->set_multi = set_multi; + mac_dev->adjust_link = adjust_link_dtsec; + mac_dev->enable = dtsec_enable; + mac_dev->disable = dtsec_disable; + + err = set_fman_mac_params(mac_dev, ¶ms); + if (err) + goto _return; + params.internal_phy_node = of_parse_phandle(mac_node, "tbi-handle", 0); + + mac_dev->fman_mac = dtsec_config(¶ms); + if (!mac_dev->fman_mac) { + err = -EINVAL; + goto _return; + } + + err = dtsec_cfg_max_frame_len(mac_dev->fman_mac, fman_get_max_frm()); + if (err < 0) + goto _return_fm_mac_free; + + err = dtsec_cfg_pad_and_crc(mac_dev->fman_mac, true); + if (err < 0) + goto _return_fm_mac_free; + + err = dtsec_init(mac_dev->fman_mac); + if (err < 0) + goto _return_fm_mac_free; + + /* For 1G MAC, disable by default the MIB counters overflow interrupt */ + err = mac_dev->set_exception(mac_dev->fman_mac, + FM_MAC_EX_1G_RX_MIB_CNT_OVFL, false); + if (err < 0) + goto _return_fm_mac_free; + + err = dtsec_get_version(mac_dev->fman_mac, &version); + if (err < 0) + goto _return_fm_mac_free; + + dev_info(priv->dev, "FMan dTSEC version: 0x%08x\n", version); + + goto _return; + +_return_fm_mac_free: + dtsec_free(mac_dev->fman_mac); + +_return: + return err; } -static void setup_memac(struct mac_device *mac_dev) +static int memac_initialization(struct mac_device *mac_dev, + struct device_node *mac_node) { - mac_dev->init = memac_initialization; + int err; + struct mac_priv_s *priv; + struct fman_mac_params params; + + priv = mac_dev->priv; mac_dev->set_promisc = memac_set_promiscuous; mac_dev->change_addr = memac_modify_mac_address; mac_dev->add_hash_mac_addr = memac_add_hash_mac_address; @@ -470,6 +415,46 @@ static void setup_memac(struct mac_device *mac_dev) mac_dev->adjust_link = adjust_link_memac; mac_dev->enable = memac_enable; mac_dev->disable = memac_disable; + + err = set_fman_mac_params(mac_dev, ¶ms); + if (err) + goto _return; + params.internal_phy_node = of_parse_phandle(mac_node, "pcsphy-handle", 0); + + if (priv->max_speed == SPEED_10000) + params.phy_if = PHY_INTERFACE_MODE_XGMII; + + mac_dev->fman_mac = memac_config(¶ms); + if (!mac_dev->fman_mac) { + err = -EINVAL; + goto _return; + } + + err = memac_cfg_max_frame_len(mac_dev->fman_mac, fman_get_max_frm()); + if (err < 0) + goto _return_fm_mac_free; + + err = memac_cfg_reset_on_init(mac_dev->fman_mac, true); + if (err < 0) + goto _return_fm_mac_free; + + err = memac_cfg_fixed_link(mac_dev->fman_mac, priv->fixed_link); + if (err < 0) + goto _return_fm_mac_free; + + err = memac_init(mac_dev->fman_mac); + if (err < 0) + goto _return_fm_mac_free; + + dev_info(priv->dev, "FMan MEMAC\n"); + + goto _return; + +_return_fm_mac_free: + memac_free(mac_dev->fman_mac); + +_return: + return err; } #define DTSEC_SUPPORTED \ @@ -546,9 +531,9 @@ no_mem: } static const struct of_device_id mac_match[] = { - { .compatible = "fsl,fman-dtsec" }, - { .compatible = "fsl,fman-xgec" }, - { .compatible = "fsl,fman-memac" }, + { .compatible = "fsl,fman-dtsec", .data = dtsec_initialization }, + { .compatible = "fsl,fman-xgec", .data = tgec_initialization }, + { .compatible = "fsl,fman-memac", .data = memac_initialization }, {} }; MODULE_DEVICE_TABLE(of, mac_match); @@ -556,6 +541,7 @@ MODULE_DEVICE_TABLE(of, mac_match); static int mac_probe(struct platform_device *_of_dev) { int err, i, nph; + int (*init)(struct mac_device *mac_dev, struct device_node *mac_node); struct device *dev; struct device_node *mac_node, *dev_node; struct mac_device *mac_dev; @@ -568,6 +554,7 @@ static int mac_probe(struct platform_device *_of_dev) dev = &_of_dev->dev; mac_node = dev->of_node; + init = of_device_get_match_data(dev); mac_dev = devm_kzalloc(dev, sizeof(*mac_dev), GFP_KERNEL); if (!mac_dev) { @@ -584,19 +571,6 @@ static int mac_probe(struct platform_device *_of_dev) mac_dev->priv = priv; priv->dev = dev; - if (of_device_is_compatible(mac_node, "fsl,fman-dtsec")) { - setup_dtsec(mac_dev); - } else if (of_device_is_compatible(mac_node, "fsl,fman-xgec")) { - setup_tgec(mac_dev); - } else if (of_device_is_compatible(mac_node, "fsl,fman-memac")) { - setup_memac(mac_dev); - } else { - dev_err(dev, "MAC node (%pOF) contains unsupported MAC\n", - mac_node); - err = -EINVAL; - goto _return; - } - INIT_LIST_HEAD(&priv->mc_addr_list); /* Get the FM node */ @@ -782,7 +756,7 @@ static int mac_probe(struct platform_device *_of_dev) put_device(&phy->mdio.dev); } - err = mac_dev->init(mac_dev, mac_node); + err = init(mac_dev, mac_node); if (err < 0) { dev_err(dev, "mac_dev->init() = %d\n", err); of_node_put(mac_dev->phy_node); diff --git a/drivers/net/ethernet/freescale/fman/mac.h b/drivers/net/ethernet/freescale/fman/mac.h index e4329c7d5001..fed3835a8473 100644 --- a/drivers/net/ethernet/freescale/fman/mac.h +++ b/drivers/net/ethernet/freescale/fman/mac.h @@ -35,7 +35,6 @@ struct mac_device { bool promisc; bool allmulti; - int (*init)(struct mac_device *mac_dev, struct device_node *mac_node); int (*enable)(struct fman_mac *mac_dev); int (*disable)(struct fman_mac *mac_dev); void (*adjust_link)(struct mac_device *mac_dev); |