root/drivers/net/ethernet/stmicro/stmmac/dwmac-oxnas.c

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

DEFINITIONS

This source file includes following definitions.
  1. oxnas_dwmac_init
  2. oxnas_dwmac_exit
  3. oxnas_dwmac_probe

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * Oxford Semiconductor OXNAS DWMAC glue layer
   4  *
   5  * Copyright (C) 2016 Neil Armstrong <narmstrong@baylibre.com>
   6  * Copyright (C) 2014 Daniel Golle <daniel@makrotopia.org>
   7  * Copyright (C) 2013 Ma Haijun <mahaijuns@gmail.com>
   8  * Copyright (C) 2012 John Crispin <blogic@openwrt.org>
   9  */
  10 
  11 #include <linux/device.h>
  12 #include <linux/io.h>
  13 #include <linux/module.h>
  14 #include <linux/of.h>
  15 #include <linux/platform_device.h>
  16 #include <linux/regmap.h>
  17 #include <linux/mfd/syscon.h>
  18 #include <linux/stmmac.h>
  19 
  20 #include "stmmac_platform.h"
  21 
  22 /* System Control regmap offsets */
  23 #define OXNAS_DWMAC_CTRL_REGOFFSET      0x78
  24 #define OXNAS_DWMAC_DELAY_REGOFFSET     0x100
  25 
  26 /* Control Register */
  27 #define DWMAC_CKEN_RX_IN        14
  28 #define DWMAC_CKEN_RXN_OUT      13
  29 #define DWMAC_CKEN_RX_OUT       12
  30 #define DWMAC_CKEN_TX_IN        10
  31 #define DWMAC_CKEN_TXN_OUT      9
  32 #define DWMAC_CKEN_TX_OUT       8
  33 #define DWMAC_RX_SOURCE         7
  34 #define DWMAC_TX_SOURCE         6
  35 #define DWMAC_LOW_TX_SOURCE     4
  36 #define DWMAC_AUTO_TX_SOURCE    3
  37 #define DWMAC_RGMII             2
  38 #define DWMAC_SIMPLE_MUX        1
  39 #define DWMAC_CKEN_GTX          0
  40 
  41 /* Delay register */
  42 #define DWMAC_TX_VARDELAY_SHIFT         0
  43 #define DWMAC_TXN_VARDELAY_SHIFT        8
  44 #define DWMAC_RX_VARDELAY_SHIFT         16
  45 #define DWMAC_RXN_VARDELAY_SHIFT        24
  46 #define DWMAC_TX_VARDELAY(d)            ((d) << DWMAC_TX_VARDELAY_SHIFT)
  47 #define DWMAC_TXN_VARDELAY(d)           ((d) << DWMAC_TXN_VARDELAY_SHIFT)
  48 #define DWMAC_RX_VARDELAY(d)            ((d) << DWMAC_RX_VARDELAY_SHIFT)
  49 #define DWMAC_RXN_VARDELAY(d)           ((d) << DWMAC_RXN_VARDELAY_SHIFT)
  50 
  51 struct oxnas_dwmac {
  52         struct device   *dev;
  53         struct clk      *clk;
  54         struct regmap   *regmap;
  55 };
  56 
  57 static int oxnas_dwmac_init(struct platform_device *pdev, void *priv)
  58 {
  59         struct oxnas_dwmac *dwmac = priv;
  60         unsigned int value;
  61         int ret;
  62 
  63         /* Reset HW here before changing the glue configuration */
  64         ret = device_reset(dwmac->dev);
  65         if (ret)
  66                 return ret;
  67 
  68         ret = clk_prepare_enable(dwmac->clk);
  69         if (ret)
  70                 return ret;
  71 
  72         ret = regmap_read(dwmac->regmap, OXNAS_DWMAC_CTRL_REGOFFSET, &value);
  73         if (ret < 0) {
  74                 clk_disable_unprepare(dwmac->clk);
  75                 return ret;
  76         }
  77 
  78         /* Enable GMII_GTXCLK to follow GMII_REFCLK, required for gigabit PHY */
  79         value |= BIT(DWMAC_CKEN_GTX)            |
  80                  /* Use simple mux for 25/125 Mhz clock switching */
  81                  BIT(DWMAC_SIMPLE_MUX)          |
  82                  /* set auto switch tx clock source */
  83                  BIT(DWMAC_AUTO_TX_SOURCE)      |
  84                  /* enable tx & rx vardelay */
  85                  BIT(DWMAC_CKEN_TX_OUT)         |
  86                  BIT(DWMAC_CKEN_TXN_OUT)        |
  87                  BIT(DWMAC_CKEN_TX_IN)          |
  88                  BIT(DWMAC_CKEN_RX_OUT)         |
  89                  BIT(DWMAC_CKEN_RXN_OUT)        |
  90                  BIT(DWMAC_CKEN_RX_IN);
  91         regmap_write(dwmac->regmap, OXNAS_DWMAC_CTRL_REGOFFSET, value);
  92 
  93         /* set tx & rx vardelay */
  94         value = DWMAC_TX_VARDELAY(4)    |
  95                 DWMAC_TXN_VARDELAY(2)   |
  96                 DWMAC_RX_VARDELAY(10)   |
  97                 DWMAC_RXN_VARDELAY(8);
  98         regmap_write(dwmac->regmap, OXNAS_DWMAC_DELAY_REGOFFSET, value);
  99 
 100         return 0;
 101 }
 102 
 103 static void oxnas_dwmac_exit(struct platform_device *pdev, void *priv)
 104 {
 105         struct oxnas_dwmac *dwmac = priv;
 106 
 107         clk_disable_unprepare(dwmac->clk);
 108 }
 109 
 110 static int oxnas_dwmac_probe(struct platform_device *pdev)
 111 {
 112         struct plat_stmmacenet_data *plat_dat;
 113         struct stmmac_resources stmmac_res;
 114         struct oxnas_dwmac *dwmac;
 115         int ret;
 116 
 117         ret = stmmac_get_platform_resources(pdev, &stmmac_res);
 118         if (ret)
 119                 return ret;
 120 
 121         plat_dat = stmmac_probe_config_dt(pdev, &stmmac_res.mac);
 122         if (IS_ERR(plat_dat))
 123                 return PTR_ERR(plat_dat);
 124 
 125         dwmac = devm_kzalloc(&pdev->dev, sizeof(*dwmac), GFP_KERNEL);
 126         if (!dwmac) {
 127                 ret = -ENOMEM;
 128                 goto err_remove_config_dt;
 129         }
 130 
 131         dwmac->dev = &pdev->dev;
 132         plat_dat->bsp_priv = dwmac;
 133         plat_dat->init = oxnas_dwmac_init;
 134         plat_dat->exit = oxnas_dwmac_exit;
 135 
 136         dwmac->regmap = syscon_regmap_lookup_by_phandle(pdev->dev.of_node,
 137                                                         "oxsemi,sys-ctrl");
 138         if (IS_ERR(dwmac->regmap)) {
 139                 dev_err(&pdev->dev, "failed to have sysctrl regmap\n");
 140                 ret = PTR_ERR(dwmac->regmap);
 141                 goto err_remove_config_dt;
 142         }
 143 
 144         dwmac->clk = devm_clk_get(&pdev->dev, "gmac");
 145         if (IS_ERR(dwmac->clk)) {
 146                 ret = PTR_ERR(dwmac->clk);
 147                 goto err_remove_config_dt;
 148         }
 149 
 150         ret = oxnas_dwmac_init(pdev, plat_dat->bsp_priv);
 151         if (ret)
 152                 goto err_remove_config_dt;
 153 
 154         ret = stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res);
 155         if (ret)
 156                 goto err_dwmac_exit;
 157 
 158 
 159         return 0;
 160 
 161 err_dwmac_exit:
 162         oxnas_dwmac_exit(pdev, plat_dat->bsp_priv);
 163 err_remove_config_dt:
 164         stmmac_remove_config_dt(pdev, plat_dat);
 165 
 166         return ret;
 167 }
 168 
 169 static const struct of_device_id oxnas_dwmac_match[] = {
 170         { .compatible = "oxsemi,ox820-dwmac" },
 171         { }
 172 };
 173 MODULE_DEVICE_TABLE(of, oxnas_dwmac_match);
 174 
 175 static struct platform_driver oxnas_dwmac_driver = {
 176         .probe  = oxnas_dwmac_probe,
 177         .remove = stmmac_pltfr_remove,
 178         .driver = {
 179                 .name           = "oxnas-dwmac",
 180                 .pm             = &stmmac_pltfr_pm_ops,
 181                 .of_match_table = oxnas_dwmac_match,
 182         },
 183 };
 184 module_platform_driver(oxnas_dwmac_driver);
 185 
 186 MODULE_AUTHOR("Neil Armstrong <narmstrong@baylibre.com>");
 187 MODULE_DESCRIPTION("Oxford Semiconductor OXNAS DWMAC glue layer");
 188 MODULE_LICENSE("GPL v2");

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