0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
0015
0016 #include <linux/bcma/bcma.h>
0017 #include <linux/brcmphy.h>
0018 #include <linux/etherdevice.h>
0019 #include <linux/of_address.h>
0020 #include <linux/of_mdio.h>
0021 #include <linux/of_net.h>
0022 #include "bgmac.h"
0023
0024 #define NICPM_PADRING_CFG 0x00000004
0025 #define NICPM_IOMUX_CTRL 0x00000008
0026
0027 #define NICPM_PADRING_CFG_INIT_VAL 0x74000000
0028 #define NICPM_IOMUX_CTRL_INIT_VAL_AX 0x21880000
0029
0030 #define NICPM_IOMUX_CTRL_INIT_VAL 0x3196e000
0031 #define NICPM_IOMUX_CTRL_SPD_SHIFT 10
0032 #define NICPM_IOMUX_CTRL_SPD_10M 0
0033 #define NICPM_IOMUX_CTRL_SPD_100M 1
0034 #define NICPM_IOMUX_CTRL_SPD_1000M 2
0035
0036 static u32 platform_bgmac_read(struct bgmac *bgmac, u16 offset)
0037 {
0038 return readl(bgmac->plat.base + offset);
0039 }
0040
0041 static void platform_bgmac_write(struct bgmac *bgmac, u16 offset, u32 value)
0042 {
0043 writel(value, bgmac->plat.base + offset);
0044 }
0045
0046 static u32 platform_bgmac_idm_read(struct bgmac *bgmac, u16 offset)
0047 {
0048 return readl(bgmac->plat.idm_base + offset);
0049 }
0050
0051 static void platform_bgmac_idm_write(struct bgmac *bgmac, u16 offset, u32 value)
0052 {
0053 writel(value, bgmac->plat.idm_base + offset);
0054 }
0055
0056 static bool platform_bgmac_clk_enabled(struct bgmac *bgmac)
0057 {
0058 if (!bgmac->plat.idm_base)
0059 return true;
0060
0061 if ((bgmac_idm_read(bgmac, BCMA_IOCTL) & BGMAC_CLK_EN) != BGMAC_CLK_EN)
0062 return false;
0063 if (bgmac_idm_read(bgmac, BCMA_RESET_CTL) & BCMA_RESET_CTL_RESET)
0064 return false;
0065 return true;
0066 }
0067
0068 static void platform_bgmac_clk_enable(struct bgmac *bgmac, u32 flags)
0069 {
0070 u32 val;
0071
0072 if (!bgmac->plat.idm_base)
0073 return;
0074
0075
0076
0077
0078
0079 val = bgmac_idm_read(bgmac, BCMA_RESET_CTL);
0080 if (val) {
0081 bgmac_idm_write(bgmac, BCMA_RESET_CTL, 0);
0082 bgmac_idm_read(bgmac, BCMA_RESET_CTL);
0083 udelay(1);
0084 }
0085
0086 val = bgmac_idm_read(bgmac, BCMA_IOCTL);
0087
0088 val |= flags & ~(BGMAC_AWCACHE | BGMAC_ARCACHE | BGMAC_AWUSER |
0089 BGMAC_ARUSER);
0090 val |= BGMAC_CLK_EN;
0091 bgmac_idm_write(bgmac, BCMA_IOCTL, val);
0092 bgmac_idm_read(bgmac, BCMA_IOCTL);
0093 udelay(1);
0094 }
0095
0096 static void platform_bgmac_cco_ctl_maskset(struct bgmac *bgmac, u32 offset,
0097 u32 mask, u32 set)
0098 {
0099
0100 WARN_ON(1);
0101 }
0102
0103 static u32 platform_bgmac_get_bus_clock(struct bgmac *bgmac)
0104 {
0105
0106 WARN_ON(1);
0107
0108 return 0;
0109 }
0110
0111 static void platform_bgmac_cmn_maskset32(struct bgmac *bgmac, u16 offset,
0112 u32 mask, u32 set)
0113 {
0114
0115 WARN_ON(1);
0116 }
0117
0118 static void bgmac_nicpm_speed_set(struct net_device *net_dev)
0119 {
0120 struct bgmac *bgmac = netdev_priv(net_dev);
0121 u32 val;
0122
0123 if (!bgmac->plat.nicpm_base)
0124 return;
0125
0126
0127 writel(NICPM_PADRING_CFG_INIT_VAL,
0128 bgmac->plat.nicpm_base + NICPM_PADRING_CFG);
0129
0130 val = NICPM_IOMUX_CTRL_INIT_VAL;
0131 switch (bgmac->net_dev->phydev->speed) {
0132 default:
0133 netdev_err(net_dev, "Unsupported speed. Defaulting to 1000Mb\n");
0134 fallthrough;
0135 case SPEED_1000:
0136 val |= NICPM_IOMUX_CTRL_SPD_1000M << NICPM_IOMUX_CTRL_SPD_SHIFT;
0137 break;
0138 case SPEED_100:
0139 val |= NICPM_IOMUX_CTRL_SPD_100M << NICPM_IOMUX_CTRL_SPD_SHIFT;
0140 break;
0141 case SPEED_10:
0142 val |= NICPM_IOMUX_CTRL_SPD_10M << NICPM_IOMUX_CTRL_SPD_SHIFT;
0143 break;
0144 }
0145
0146 writel(val, bgmac->plat.nicpm_base + NICPM_IOMUX_CTRL);
0147
0148 bgmac_adjust_link(bgmac->net_dev);
0149 }
0150
0151 static int platform_phy_connect(struct bgmac *bgmac)
0152 {
0153 struct phy_device *phy_dev;
0154
0155 if (bgmac->plat.nicpm_base)
0156 phy_dev = of_phy_get_and_connect(bgmac->net_dev,
0157 bgmac->dev->of_node,
0158 bgmac_nicpm_speed_set);
0159 else
0160 phy_dev = of_phy_get_and_connect(bgmac->net_dev,
0161 bgmac->dev->of_node,
0162 bgmac_adjust_link);
0163 if (!phy_dev) {
0164 dev_err(bgmac->dev, "PHY connection failed\n");
0165 return -ENODEV;
0166 }
0167
0168 return 0;
0169 }
0170
0171 static int bgmac_probe(struct platform_device *pdev)
0172 {
0173 struct device_node *np = pdev->dev.of_node;
0174 struct bgmac *bgmac;
0175 struct resource *regs;
0176 int ret;
0177
0178 bgmac = bgmac_alloc(&pdev->dev);
0179 if (!bgmac)
0180 return -ENOMEM;
0181
0182 platform_set_drvdata(pdev, bgmac);
0183
0184
0185 bgmac->feature_flags |= BGMAC_FEAT_CLKCTLST;
0186 bgmac->feature_flags |= BGMAC_FEAT_NO_RESET;
0187 bgmac->feature_flags |= BGMAC_FEAT_CMDCFG_SR_REV4;
0188 bgmac->feature_flags |= BGMAC_FEAT_TX_MASK_SETUP;
0189 bgmac->feature_flags |= BGMAC_FEAT_RX_MASK_SETUP;
0190 bgmac->feature_flags |= BGMAC_FEAT_IDM_MASK;
0191
0192 bgmac->dev = &pdev->dev;
0193 bgmac->dma_dev = &pdev->dev;
0194
0195 ret = of_get_ethdev_address(np, bgmac->net_dev);
0196 if (ret == -EPROBE_DEFER)
0197 return ret;
0198
0199 if (ret)
0200 dev_warn(&pdev->dev,
0201 "MAC address not present in device tree\n");
0202
0203 bgmac->irq = platform_get_irq(pdev, 0);
0204 if (bgmac->irq < 0)
0205 return bgmac->irq;
0206
0207 bgmac->plat.base =
0208 devm_platform_ioremap_resource_byname(pdev, "amac_base");
0209 if (IS_ERR(bgmac->plat.base))
0210 return PTR_ERR(bgmac->plat.base);
0211
0212
0213 regs = platform_get_resource_byname(pdev, IORESOURCE_MEM, "idm_base");
0214 if (regs) {
0215 bgmac->plat.idm_base = devm_ioremap_resource(&pdev->dev, regs);
0216 if (IS_ERR(bgmac->plat.idm_base))
0217 return PTR_ERR(bgmac->plat.idm_base);
0218 bgmac->feature_flags &= ~BGMAC_FEAT_IDM_MASK;
0219 }
0220
0221
0222 regs = platform_get_resource_byname(pdev, IORESOURCE_MEM, "nicpm_base");
0223 if (regs) {
0224 bgmac->plat.nicpm_base = devm_ioremap_resource(&pdev->dev,
0225 regs);
0226 if (IS_ERR(bgmac->plat.nicpm_base))
0227 return PTR_ERR(bgmac->plat.nicpm_base);
0228 }
0229
0230 bgmac->read = platform_bgmac_read;
0231 bgmac->write = platform_bgmac_write;
0232 bgmac->idm_read = platform_bgmac_idm_read;
0233 bgmac->idm_write = platform_bgmac_idm_write;
0234 bgmac->clk_enabled = platform_bgmac_clk_enabled;
0235 bgmac->clk_enable = platform_bgmac_clk_enable;
0236 bgmac->cco_ctl_maskset = platform_bgmac_cco_ctl_maskset;
0237 bgmac->get_bus_clock = platform_bgmac_get_bus_clock;
0238 bgmac->cmn_maskset32 = platform_bgmac_cmn_maskset32;
0239 if (of_parse_phandle(np, "phy-handle", 0)) {
0240 bgmac->phy_connect = platform_phy_connect;
0241 } else {
0242 bgmac->phy_connect = bgmac_phy_connect_direct;
0243 bgmac->feature_flags |= BGMAC_FEAT_FORCE_SPEED_2500;
0244 }
0245
0246 return bgmac_enet_probe(bgmac);
0247 }
0248
0249 static int bgmac_remove(struct platform_device *pdev)
0250 {
0251 struct bgmac *bgmac = platform_get_drvdata(pdev);
0252
0253 bgmac_enet_remove(bgmac);
0254
0255 return 0;
0256 }
0257
0258 #ifdef CONFIG_PM
0259 static int bgmac_suspend(struct device *dev)
0260 {
0261 struct bgmac *bgmac = dev_get_drvdata(dev);
0262
0263 return bgmac_enet_suspend(bgmac);
0264 }
0265
0266 static int bgmac_resume(struct device *dev)
0267 {
0268 struct bgmac *bgmac = dev_get_drvdata(dev);
0269
0270 return bgmac_enet_resume(bgmac);
0271 }
0272
0273 static const struct dev_pm_ops bgmac_pm_ops = {
0274 .suspend = bgmac_suspend,
0275 .resume = bgmac_resume
0276 };
0277
0278 #define BGMAC_PM_OPS (&bgmac_pm_ops)
0279 #else
0280 #define BGMAC_PM_OPS NULL
0281 #endif
0282
0283 static const struct of_device_id bgmac_of_enet_match[] = {
0284 {.compatible = "brcm,amac",},
0285 {.compatible = "brcm,nsp-amac",},
0286 {.compatible = "brcm,ns2-amac",},
0287 {},
0288 };
0289
0290 MODULE_DEVICE_TABLE(of, bgmac_of_enet_match);
0291
0292 static struct platform_driver bgmac_enet_driver = {
0293 .driver = {
0294 .name = "bgmac-enet",
0295 .of_match_table = bgmac_of_enet_match,
0296 .pm = BGMAC_PM_OPS
0297 },
0298 .probe = bgmac_probe,
0299 .remove = bgmac_remove,
0300 };
0301
0302 module_platform_driver(bgmac_enet_driver);
0303 MODULE_LICENSE("GPL");