Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * Copyright (C) 2016 Broadcom
0003  *
0004  * This program is free software; you can redistribute it and/or
0005  * modify it under the terms of the GNU General Public License as
0006  * published by the Free Software Foundation version 2.
0007  *
0008  * This program is distributed "as is" WITHOUT ANY WARRANTY of any
0009  * kind, whether express or implied; without even the implied warranty
0010  * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
0011  * GNU General Public License for more details.
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     /* The Reset Control register only contains a single bit to show if the
0076      * controller is currently in reset.  Do a sanity check here, just in
0077      * case the bootloader happened to leave the device in reset.
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     /* Some bits of BCMA_IOCTL set by HW/ATF and should not change */
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     /* This shouldn't be encountered */
0100     WARN_ON(1);
0101 }
0102 
0103 static u32 platform_bgmac_get_bus_clock(struct bgmac *bgmac)
0104 {
0105     /* This shouldn't be encountered */
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     /* This shouldn't be encountered */
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     /* SET RGMII IO CONFIG */
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     /* Set the features of the 4707 family */
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     /* The idm_base resource is optional for some platforms */
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     /* The nicpm_base resource is optional for some platforms */
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 /* CONFIG_PM */
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");