From: "Tham, Mun Yew" <mun.yew.t...@intel.com> commit 9d5cb4437f4e1182f03424b26eac2954687af777 from https://github.com/altera-opensource/linux-socfpga.git
This patch adds FEC driver for Intel FPGA E-tile Ethernet driver. Signed-off-by: Tham, Mun Yew <mun.yew.t...@intel.com> Signed-off-by: Wenlin Kang <wenlin.k...@windriver.com> --- .../ethernet/altera/intel_fpga_etile_fec.c | 212 ++++++++++++++++++ 1 file changed, 212 insertions(+) create mode 100644 drivers/net/ethernet/altera/intel_fpga_etile_fec.c diff --git a/drivers/net/ethernet/altera/intel_fpga_etile_fec.c b/drivers/net/ethernet/altera/intel_fpga_etile_fec.c new file mode 100644 index 000000000000..b1ca83a07985 --- /dev/null +++ b/drivers/net/ethernet/altera/intel_fpga_etile_fec.c @@ -0,0 +1,212 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Intel FPGA E-tile Forward Error Correction (FEC) Linux driver + * Copyright (C) 2020-2022 Intel Corporation. All rights reserved. + * + * Contributors: + * Joyce Ooi + */ + +#include <linux/bitops.h> +#include <linux/if_vlan.h> +#include <linux/kernel.h> +#include <linux/list.h> +#include <linux/module.h> +#include <linux/netdevice.h> +#include <linux/of_net.h> +#include <linux/of_platform.h> +#include <linux/phy.h> +#include <linux/platform_device.h> +#include <linux/ptp_clock_kernel.h> +#include <linux/phylink.h> + +#include "altera_eth_dma.h" +#include "altera_utils.h" +#include "intel_fpga_etile.h" + +#define MAX_COUNT_OFFSET 64000 + +/* Init FEC */ +int fec_init(struct platform_device *pdev, struct intel_fpga_etile_eth_private *priv) +{ + int ret; + + /* get FEC type from device tree */ + ret = of_property_read_string(pdev->dev.of_node, "fec-type", + &priv->fec_type); + if (ret < 0) { + dev_err(&pdev->dev, "cannot obtain fec-type\n"); + return ret; + } + dev_info(&pdev->dev, "\tFEC type is %s\n", priv->fec_type); + + /* get FEC channel from device tree */ + if (of_property_read_u32(pdev->dev.of_node, "fec-channel", + &priv->fec_channel)) { + dev_err(&pdev->dev, "cannot obtain fec-channel\n"); + return -ENXIO; + } + dev_info(&pdev->dev, "\tfec-channel is 0x%x\n", priv->fec_channel); + + return 0; +} + +/* Calculate Unit Interval Adjustments */ +void ui_adjustments(struct timer_list *t) +{ + struct intel_fpga_etile_eth_private *priv = from_timer(priv, t, fec_timer); + u32 tx_tam_l_initial, tx_tam_h_initial, tx_tam_count_initial; + u32 rx_tam_l_initial, rx_tam_h_initial, rx_tam_count_initial; + u32 tx_tam_l_nth, tx_tam_h_nth, tx_tam_count_nth; + u32 rx_tam_l_nth, rx_tam_h_nth, rx_tam_count_nth; + u64 tx_tam_initial, rx_tam_initial, tx_tam_nth, rx_tam_nth; + u32 tx_tam_interval = 0, rx_tam_interval = 0; + u32 tx_tam_count_est, rx_tam_count_est, ui_value, tx_tam_count, rx_tam_count; + u64 tx_tam_delta, rx_tam_delta; + u64 tx_ui, rx_ui; + u64 start_jiffies; + + start_jiffies = get_jiffies_64(); + /* Set tam_snapshot to 1 to take the first snapshot of the Time of + * Alignment marker (TAM) + */ + tse_set_bit(priv->mac_dev, eth_ptp_csroffs(tam_snapshot), + ETH_TAM_SNAPSHOT); + + /* Read snapshotted initial TX TAM and counter values */ + tx_tam_l_initial = csrrd32(priv->mac_dev, eth_ptp_csroffs(tx_tam_l)); + tx_tam_h_initial = csrrd32(priv->mac_dev, eth_ptp_csroffs(tx_tam_h)); + tx_tam_initial = ((u64)tx_tam_h_initial << 32) | tx_tam_l_initial; + tx_tam_count_initial = csrrd32(priv->mac_dev, eth_ptp_csroffs(tx_count)); + + /* Read snapshotted initial RX TAM and counter values */ + rx_tam_l_initial = csrrd32(priv->mac_dev, eth_ptp_csroffs(rx_tam_l)); + rx_tam_h_initial = csrrd32(priv->mac_dev, eth_ptp_csroffs(rx_tam_h)); + rx_tam_initial = ((u64)rx_tam_h_initial << 32) | rx_tam_l_initial; + rx_tam_count_initial = csrrd32(priv->mac_dev, eth_ptp_csroffs(rx_count)); + + /* Clear snapshot */ + tse_clear_bit(priv->mac_dev, eth_ptp_csroffs(tam_snapshot), + ETH_TAM_SNAPSHOT); + + /* Wait for a few TAM interval */ + udelay(210); + + /* Request snapshot of Nth TX TAM and RX TAM */ + tse_set_bit(priv->mac_dev, eth_ptp_csroffs(tam_snapshot), + ETH_TAM_SNAPSHOT); + + /* Read snapshotted of Nth TX TAM and counter values */ + tx_tam_l_nth = csrrd32(priv->mac_dev, eth_ptp_csroffs(tx_tam_l)); + tx_tam_h_nth = csrrd32(priv->mac_dev, eth_ptp_csroffs(tx_tam_h)); + tx_tam_nth = ((u64)tx_tam_h_nth << 32) | tx_tam_l_nth; + tx_tam_count_nth = csrrd32(priv->mac_dev, eth_ptp_csroffs(tx_count)); + + /* Read snapshotted of Nth RX TAM and counter values */ + rx_tam_l_nth = csrrd32(priv->mac_dev, eth_ptp_csroffs(rx_tam_l)); + rx_tam_h_nth = csrrd32(priv->mac_dev, eth_ptp_csroffs(rx_tam_h)); + rx_tam_nth = ((u64)rx_tam_h_nth << 32) | rx_tam_l_nth; + rx_tam_count_nth = csrrd32(priv->mac_dev, eth_ptp_csroffs(rx_count)); + + /* Clear snapshot */ + tse_clear_bit(priv->mac_dev, eth_ptp_csroffs(tam_snapshot), + ETH_TAM_SNAPSHOT); + if ((get_jiffies_64() - start_jiffies) > HZ) { + printk(KERN_ALERT "%s: 1st to Nth snapshot takes more than 1 second\n" + , __func__); + goto ui_restart; + } + + /* Calculate new UI value */ + /* Reference Time (TAM) interval = AM interval * Unit interval of serial bit + * AM interval for No FEC for 10/25GbE: TX = 5406720, RX = 6336 + * AM interval for KR-FEC for 25GbE: TX = 5406720, RX = 5406720 + * Unit interval of serial bit = 0.0387878 nanoseconds + */ + if (!strcasecmp(priv->fec_type, "kr-fec")) { + tx_tam_interval = 5406720; + rx_tam_interval = 5406720; + } else if (!strcasecmp(priv->fec_type, "no-fec")) { + tx_tam_interval = 5406720; + rx_tam_interval = 6336; + } + + /* Calculate time elapsed */ + if (tx_tam_nth <= tx_tam_initial) + tx_tam_delta = (tx_tam_nth + (int_pow(10, 9) << 16)) - tx_tam_initial; + else + tx_tam_delta = tx_tam_nth - tx_tam_initial; + + if (rx_tam_nth <= rx_tam_initial) + rx_tam_delta = (rx_tam_nth + (int_pow(10, 9) << 16)) - rx_tam_initial; + else + rx_tam_delta = rx_tam_nth - rx_tam_initial; + + switch (priv->phy_iface) { + case PHY_INTERFACE_MODE_10GKR: + case PHY_INTERFACE_MODE_10GBASER: + ui_value = INTEL_FPGA_ETILE_UI_VALUE_10G; + break; + case PHY_INTERFACE_MODE_25GKR: + ui_value = INTEL_FPGA_ETILE_UI_VALUE_25G; + break; + default: + ui_value = 0; //invalid value + } + + /* Calculate estimated count value */ + if (ui_value > 0) { + if (tx_tam_interval > 0) + tx_tam_count_est = tx_tam_delta / (tx_tam_interval * ui_value); + + if (rx_tam_interval > 0) + rx_tam_count_est = rx_tam_delta / (rx_tam_interval * ui_value); + } + + /* if estimated count value is more than 64000 (max count value with + * offset), discard the snapshot and repeat steps + */ + if (tx_tam_count_est > MAX_COUNT_OFFSET || + rx_tam_count_est > MAX_COUNT_OFFSET) { + printk(KERN_ALERT "%s: estimated count value (tx: %d, rx: %d)" + "is more than %d\n", __func__, tx_tam_count_est, + rx_tam_count_est, MAX_COUNT_OFFSET); + goto ui_restart; + } + + /* Calculate TAM count value */ + if (tx_tam_count_nth <= tx_tam_count_initial) + tx_tam_count = (tx_tam_count_nth + int_pow(2, 16)) - tx_tam_count_initial; + else + tx_tam_count = tx_tam_count_nth - tx_tam_count_initial; + + if (rx_tam_count_nth <= rx_tam_count_initial) + rx_tam_count = (rx_tam_count_nth + int_pow(2, 16)) - rx_tam_count_initial; + else + rx_tam_count = rx_tam_count_nth - rx_tam_count_initial; + + /* Calculate UI value */ + if (tx_tam_count > 0 && tx_tam_interval > 0) + tx_ui = (tx_tam_delta * int_pow(2, 8)) / (tx_tam_count * tx_tam_interval); + + if (rx_tam_count > 0 && rx_tam_interval > 0) + rx_ui = (rx_tam_delta * int_pow(2, 8)) / (rx_tam_count * rx_tam_interval); + + if (tx_ui > 0x9EE42 || tx_ui < 0x9EDC0) { + printk(KERN_ALERT "%s: TX UI value (0x%llx) is not within " + "0x9EDC0 to 0x9EE42 range\n", __func__, tx_ui); + goto ui_restart; + } + if (rx_ui > 0x9EE42 || rx_ui < 0x9EDC0) { + printk(KERN_ALERT "%s: RX UI value (0x%llx) is not within " + "0x9EDC0 to 0x9EE42 range\n", __func__, rx_ui); + goto ui_restart; + } + + csrwr32(tx_ui, priv->mac_dev, eth_ptp_csroffs(tx_ui_reg)); + csrwr32(rx_ui, priv->mac_dev, eth_ptp_csroffs(rx_ui_reg)); + +ui_restart: + mod_timer(&priv->fec_timer, jiffies + msecs_to_jiffies(1000)); +} + +MODULE_LICENSE("GPL"); -- 2.25.1
-=-=-=-=-=-=-=-=-=-=-=- Links: You receive all messages sent to this group. View/Reply Online (#12561): https://lists.yoctoproject.org/g/linux-yocto/message/12561 Mute This Topic: https://lists.yoctoproject.org/mt/98921476/21656 Group Owner: linux-yocto+ow...@lists.yoctoproject.org Unsubscribe: https://lists.yoctoproject.org/g/linux-yocto/unsub [arch...@mail-archive.com] -=-=-=-=-=-=-=-=-=-=-=-