root/drivers/net/ethernet/broadcom/bgmac-platform.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. platform_bgmac_read
  2. platform_bgmac_write
  3. platform_bgmac_idm_read
  4. platform_bgmac_idm_write
  5. platform_bgmac_clk_enabled
  6. platform_bgmac_clk_enable
  7. platform_bgmac_cco_ctl_maskset
  8. platform_bgmac_get_bus_clock
  9. platform_bgmac_cmn_maskset32
  10. bgmac_nicpm_speed_set
  11. platform_phy_connect
  12. bgmac_probe
  13. bgmac_remove
  14. bgmac_suspend
  15. bgmac_resume

   1 /*
   2  * Copyright (C) 2016 Broadcom
   3  *
   4  * This program is free software; you can redistribute it and/or
   5  * modify it under the terms of the GNU General Public License as
   6  * published by the Free Software Foundation version 2.
   7  *
   8  * This program is distributed "as is" WITHOUT ANY WARRANTY of any
   9  * kind, whether express or implied; without even the implied warranty
  10  * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  11  * GNU General Public License for more details.
  12  */
  13 
  14 #define pr_fmt(fmt)             KBUILD_MODNAME ": " fmt
  15 
  16 #include <linux/bcma/bcma.h>
  17 #include <linux/brcmphy.h>
  18 #include <linux/etherdevice.h>
  19 #include <linux/of_address.h>
  20 #include <linux/of_mdio.h>
  21 #include <linux/of_net.h>
  22 #include "bgmac.h"
  23 
  24 #define NICPM_PADRING_CFG               0x00000004
  25 #define NICPM_IOMUX_CTRL                0x00000008
  26 
  27 #define NICPM_PADRING_CFG_INIT_VAL      0x74000000
  28 #define NICPM_IOMUX_CTRL_INIT_VAL_AX    0x21880000
  29 
  30 #define NICPM_IOMUX_CTRL_INIT_VAL       0x3196e000
  31 #define NICPM_IOMUX_CTRL_SPD_SHIFT      10
  32 #define NICPM_IOMUX_CTRL_SPD_10M        0
  33 #define NICPM_IOMUX_CTRL_SPD_100M       1
  34 #define NICPM_IOMUX_CTRL_SPD_1000M      2
  35 
  36 static u32 platform_bgmac_read(struct bgmac *bgmac, u16 offset)
  37 {
  38         return readl(bgmac->plat.base + offset);
  39 }
  40 
  41 static void platform_bgmac_write(struct bgmac *bgmac, u16 offset, u32 value)
  42 {
  43         writel(value, bgmac->plat.base + offset);
  44 }
  45 
  46 static u32 platform_bgmac_idm_read(struct bgmac *bgmac, u16 offset)
  47 {
  48         return readl(bgmac->plat.idm_base + offset);
  49 }
  50 
  51 static void platform_bgmac_idm_write(struct bgmac *bgmac, u16 offset, u32 value)
  52 {
  53         writel(value, bgmac->plat.idm_base + offset);
  54 }
  55 
  56 static bool platform_bgmac_clk_enabled(struct bgmac *bgmac)
  57 {
  58         if (!bgmac->plat.idm_base)
  59                 return true;
  60 
  61         if ((bgmac_idm_read(bgmac, BCMA_IOCTL) & BGMAC_CLK_EN) != BGMAC_CLK_EN)
  62                 return false;
  63         if (bgmac_idm_read(bgmac, BCMA_RESET_CTL) & BCMA_RESET_CTL_RESET)
  64                 return false;
  65         return true;
  66 }
  67 
  68 static void platform_bgmac_clk_enable(struct bgmac *bgmac, u32 flags)
  69 {
  70         u32 val;
  71 
  72         if (!bgmac->plat.idm_base)
  73                 return;
  74 
  75         /* The Reset Control register only contains a single bit to show if the
  76          * controller is currently in reset.  Do a sanity check here, just in
  77          * case the bootloader happened to leave the device in reset.
  78          */
  79         val = bgmac_idm_read(bgmac, BCMA_RESET_CTL);
  80         if (val) {
  81                 bgmac_idm_write(bgmac, BCMA_RESET_CTL, 0);
  82                 bgmac_idm_read(bgmac, BCMA_RESET_CTL);
  83                 udelay(1);
  84         }
  85 
  86         val = bgmac_idm_read(bgmac, BCMA_IOCTL);
  87         /* Some bits of BCMA_IOCTL set by HW/ATF and should not change */
  88         val |= flags & ~(BGMAC_AWCACHE | BGMAC_ARCACHE | BGMAC_AWUSER |
  89                          BGMAC_ARUSER);
  90         val |= BGMAC_CLK_EN;
  91         bgmac_idm_write(bgmac, BCMA_IOCTL, val);
  92         bgmac_idm_read(bgmac, BCMA_IOCTL);
  93         udelay(1);
  94 }
  95 
  96 static void platform_bgmac_cco_ctl_maskset(struct bgmac *bgmac, u32 offset,
  97                                            u32 mask, u32 set)
  98 {
  99         /* This shouldn't be encountered */
 100         WARN_ON(1);
 101 }
 102 
 103 static u32 platform_bgmac_get_bus_clock(struct bgmac *bgmac)
 104 {
 105         /* This shouldn't be encountered */
 106         WARN_ON(1);
 107 
 108         return 0;
 109 }
 110 
 111 static void platform_bgmac_cmn_maskset32(struct bgmac *bgmac, u16 offset,
 112                                          u32 mask, u32 set)
 113 {
 114         /* This shouldn't be encountered */
 115         WARN_ON(1);
 116 }
 117 
 118 static void bgmac_nicpm_speed_set(struct net_device *net_dev)
 119 {
 120         struct bgmac *bgmac = netdev_priv(net_dev);
 121         u32 val;
 122 
 123         if (!bgmac->plat.nicpm_base)
 124                 return;
 125 
 126         /* SET RGMII IO CONFIG */
 127         writel(NICPM_PADRING_CFG_INIT_VAL,
 128                bgmac->plat.nicpm_base + NICPM_PADRING_CFG);
 129 
 130         val = NICPM_IOMUX_CTRL_INIT_VAL;
 131         switch (bgmac->net_dev->phydev->speed) {
 132         default:
 133                 netdev_err(net_dev, "Unsupported speed. Defaulting to 1000Mb\n");
 134                 /* fall through */
 135         case SPEED_1000:
 136                 val |= NICPM_IOMUX_CTRL_SPD_1000M << NICPM_IOMUX_CTRL_SPD_SHIFT;
 137                 break;
 138         case SPEED_100:
 139                 val |= NICPM_IOMUX_CTRL_SPD_100M << NICPM_IOMUX_CTRL_SPD_SHIFT;
 140                 break;
 141         case SPEED_10:
 142                 val |= NICPM_IOMUX_CTRL_SPD_10M << NICPM_IOMUX_CTRL_SPD_SHIFT;
 143                 break;
 144         }
 145 
 146         writel(val, bgmac->plat.nicpm_base + NICPM_IOMUX_CTRL);
 147 
 148         bgmac_adjust_link(bgmac->net_dev);
 149 }
 150 
 151 static int platform_phy_connect(struct bgmac *bgmac)
 152 {
 153         struct phy_device *phy_dev;
 154 
 155         if (bgmac->plat.nicpm_base)
 156                 phy_dev = of_phy_get_and_connect(bgmac->net_dev,
 157                                                  bgmac->dev->of_node,
 158                                                  bgmac_nicpm_speed_set);
 159         else
 160                 phy_dev = of_phy_get_and_connect(bgmac->net_dev,
 161                                                  bgmac->dev->of_node,
 162                                                  bgmac_adjust_link);
 163         if (!phy_dev) {
 164                 dev_err(bgmac->dev, "PHY connection failed\n");
 165                 return -ENODEV;
 166         }
 167 
 168         return 0;
 169 }
 170 
 171 static int bgmac_probe(struct platform_device *pdev)
 172 {
 173         struct device_node *np = pdev->dev.of_node;
 174         struct bgmac *bgmac;
 175         struct resource *regs;
 176         const u8 *mac_addr;
 177 
 178         bgmac = bgmac_alloc(&pdev->dev);
 179         if (!bgmac)
 180                 return -ENOMEM;
 181 
 182         platform_set_drvdata(pdev, bgmac);
 183 
 184         /* Set the features of the 4707 family */
 185         bgmac->feature_flags |= BGMAC_FEAT_CLKCTLST;
 186         bgmac->feature_flags |= BGMAC_FEAT_NO_RESET;
 187         bgmac->feature_flags |= BGMAC_FEAT_CMDCFG_SR_REV4;
 188         bgmac->feature_flags |= BGMAC_FEAT_TX_MASK_SETUP;
 189         bgmac->feature_flags |= BGMAC_FEAT_RX_MASK_SETUP;
 190         bgmac->feature_flags |= BGMAC_FEAT_IDM_MASK;
 191 
 192         bgmac->dev = &pdev->dev;
 193         bgmac->dma_dev = &pdev->dev;
 194 
 195         mac_addr = of_get_mac_address(np);
 196         if (!IS_ERR(mac_addr))
 197                 ether_addr_copy(bgmac->net_dev->dev_addr, mac_addr);
 198         else
 199                 dev_warn(&pdev->dev, "MAC address not present in device tree\n");
 200 
 201         bgmac->irq = platform_get_irq(pdev, 0);
 202         if (bgmac->irq < 0)
 203                 return bgmac->irq;
 204 
 205         regs = platform_get_resource_byname(pdev, IORESOURCE_MEM, "amac_base");
 206         if (!regs) {
 207                 dev_err(&pdev->dev, "Unable to obtain base resource\n");
 208                 return -EINVAL;
 209         }
 210 
 211         bgmac->plat.base = devm_ioremap_resource(&pdev->dev, regs);
 212         if (IS_ERR(bgmac->plat.base))
 213                 return PTR_ERR(bgmac->plat.base);
 214 
 215         regs = platform_get_resource_byname(pdev, IORESOURCE_MEM, "idm_base");
 216         if (regs) {
 217                 bgmac->plat.idm_base = devm_ioremap_resource(&pdev->dev, regs);
 218                 if (IS_ERR(bgmac->plat.idm_base))
 219                         return PTR_ERR(bgmac->plat.idm_base);
 220                 bgmac->feature_flags &= ~BGMAC_FEAT_IDM_MASK;
 221         }
 222 
 223         regs = platform_get_resource_byname(pdev, IORESOURCE_MEM, "nicpm_base");
 224         if (regs) {
 225                 bgmac->plat.nicpm_base = devm_ioremap_resource(&pdev->dev,
 226                                                                regs);
 227                 if (IS_ERR(bgmac->plat.nicpm_base))
 228                         return PTR_ERR(bgmac->plat.nicpm_base);
 229         }
 230 
 231         bgmac->read = platform_bgmac_read;
 232         bgmac->write = platform_bgmac_write;
 233         bgmac->idm_read = platform_bgmac_idm_read;
 234         bgmac->idm_write = platform_bgmac_idm_write;
 235         bgmac->clk_enabled = platform_bgmac_clk_enabled;
 236         bgmac->clk_enable = platform_bgmac_clk_enable;
 237         bgmac->cco_ctl_maskset = platform_bgmac_cco_ctl_maskset;
 238         bgmac->get_bus_clock = platform_bgmac_get_bus_clock;
 239         bgmac->cmn_maskset32 = platform_bgmac_cmn_maskset32;
 240         if (of_parse_phandle(np, "phy-handle", 0)) {
 241                 bgmac->phy_connect = platform_phy_connect;
 242         } else {
 243                 bgmac->phy_connect = bgmac_phy_connect_direct;
 244                 bgmac->feature_flags |= BGMAC_FEAT_FORCE_SPEED_2500;
 245         }
 246 
 247         return bgmac_enet_probe(bgmac);
 248 }
 249 
 250 static int bgmac_remove(struct platform_device *pdev)
 251 {
 252         struct bgmac *bgmac = platform_get_drvdata(pdev);
 253 
 254         bgmac_enet_remove(bgmac);
 255 
 256         return 0;
 257 }
 258 
 259 #ifdef CONFIG_PM
 260 static int bgmac_suspend(struct device *dev)
 261 {
 262         struct bgmac *bgmac = dev_get_drvdata(dev);
 263 
 264         return bgmac_enet_suspend(bgmac);
 265 }
 266 
 267 static int bgmac_resume(struct device *dev)
 268 {
 269         struct bgmac *bgmac = dev_get_drvdata(dev);
 270 
 271         return bgmac_enet_resume(bgmac);
 272 }
 273 
 274 static const struct dev_pm_ops bgmac_pm_ops = {
 275         .suspend = bgmac_suspend,
 276         .resume = bgmac_resume
 277 };
 278 
 279 #define BGMAC_PM_OPS (&bgmac_pm_ops)
 280 #else
 281 #define BGMAC_PM_OPS NULL
 282 #endif /* CONFIG_PM */
 283 
 284 static const struct of_device_id bgmac_of_enet_match[] = {
 285         {.compatible = "brcm,amac",},
 286         {.compatible = "brcm,nsp-amac",},
 287         {.compatible = "brcm,ns2-amac",},
 288         {},
 289 };
 290 
 291 MODULE_DEVICE_TABLE(of, bgmac_of_enet_match);
 292 
 293 static struct platform_driver bgmac_enet_driver = {
 294         .driver = {
 295                 .name  = "bgmac-enet",
 296                 .of_match_table = bgmac_of_enet_match,
 297                 .pm = BGMAC_PM_OPS
 298         },
 299         .probe = bgmac_probe,
 300         .remove = bgmac_remove,
 301 };
 302 
 303 module_platform_driver(bgmac_enet_driver);
 304 MODULE_LICENSE("GPL");

/* [<][>][^][v][top][bottom][index][help] */