0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020 #include <linux/io.h>
0021 #include <linux/module.h>
0022 #include <linux/of_device.h>
0023 #include <linux/pci.h>
0024 #include <linux/platform_device.h>
0025 #include "enetc.h"
0026 #include "enetc_ierb.h"
0027
0028
0029 #define ENETC_IERB_TXMBAR(port) (((port) * 0x100) + 0x8080)
0030 #define ENETC_IERB_RXMBER(port) (((port) * 0x100) + 0x8090)
0031 #define ENETC_IERB_RXMBLR(port) (((port) * 0x100) + 0x8094)
0032 #define ENETC_IERB_RXBCR(port) (((port) * 0x100) + 0x80a0)
0033 #define ENETC_IERB_TXBCR(port) (((port) * 0x100) + 0x80a8)
0034 #define ENETC_IERB_FMBDTR 0xa000
0035
0036 #define ENETC_RESERVED_FOR_ICM 1024
0037
0038 struct enetc_ierb {
0039 void __iomem *regs;
0040 };
0041
0042 static void enetc_ierb_write(struct enetc_ierb *ierb, u32 offset, u32 val)
0043 {
0044 iowrite32(val, ierb->regs + offset);
0045 }
0046
0047 int enetc_ierb_register_pf(struct platform_device *pdev,
0048 struct pci_dev *pf_pdev)
0049 {
0050 struct enetc_ierb *ierb = platform_get_drvdata(pdev);
0051 int port = enetc_pf_to_port(pf_pdev);
0052 u16 tx_credit, rx_credit, tx_alloc;
0053
0054 if (port < 0)
0055 return -ENODEV;
0056
0057 if (!ierb)
0058 return -EPROBE_DEFER;
0059
0060
0061
0062
0063
0064
0065 tx_credit = roundup(1000 + ENETC_MAC_MAXFRM_SIZE / 2, 100);
0066
0067
0068
0069
0070
0071
0072
0073
0074
0075
0076
0077
0078
0079
0080
0081 tx_alloc = roundup(2 * tx_credit + 4 * ENETC_MAC_MAXFRM_SIZE + 64, 16);
0082
0083
0084
0085
0086
0087
0088
0089 rx_credit = DIV_ROUND_UP(ENETC_MAC_MAXFRM_SIZE * 2, 8);
0090
0091 enetc_ierb_write(ierb, ENETC_IERB_TXBCR(port), tx_credit);
0092 enetc_ierb_write(ierb, ENETC_IERB_TXMBAR(port), tx_alloc);
0093 enetc_ierb_write(ierb, ENETC_IERB_RXBCR(port), rx_credit);
0094
0095 return 0;
0096 }
0097 EXPORT_SYMBOL(enetc_ierb_register_pf);
0098
0099 static int enetc_ierb_probe(struct platform_device *pdev)
0100 {
0101 struct enetc_ierb *ierb;
0102 void __iomem *regs;
0103
0104 ierb = devm_kzalloc(&pdev->dev, sizeof(*ierb), GFP_KERNEL);
0105 if (!ierb)
0106 return -ENOMEM;
0107
0108 regs = devm_platform_get_and_ioremap_resource(pdev, 0, NULL);
0109 if (IS_ERR(regs))
0110 return PTR_ERR(regs);
0111
0112 ierb->regs = regs;
0113
0114
0115
0116
0117
0118
0119
0120
0121
0122
0123 enetc_ierb_write(ierb, ENETC_IERB_FMBDTR, ENETC_RESERVED_FOR_ICM);
0124
0125 platform_set_drvdata(pdev, ierb);
0126
0127 return 0;
0128 }
0129
0130 static int enetc_ierb_remove(struct platform_device *pdev)
0131 {
0132 return 0;
0133 }
0134
0135 static const struct of_device_id enetc_ierb_match[] = {
0136 { .compatible = "fsl,ls1028a-enetc-ierb", },
0137 {},
0138 };
0139 MODULE_DEVICE_TABLE(of, enetc_ierb_match);
0140
0141 static struct platform_driver enetc_ierb_driver = {
0142 .driver = {
0143 .name = "fsl-enetc-ierb",
0144 .of_match_table = enetc_ierb_match,
0145 },
0146 .probe = enetc_ierb_probe,
0147 .remove = enetc_ierb_remove,
0148 };
0149
0150 module_platform_driver(enetc_ierb_driver);
0151
0152 MODULE_DESCRIPTION("NXP ENETC IERB");
0153 MODULE_LICENSE("Dual BSD/GPL");