1 /* Copyright Altera Corporation (C) 2014. All rights reserved. 2 * 3 * This program is free software; you can redistribute it and/or modify 4 * it under the terms of the GNU General Public License, version 2, 5 * as published by the Free Software Foundation. 6 * 7 * This program is distributed in the hope that it will be useful, 8 * but WITHOUT ANY WARRANTY; without even the implied warranty of 9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 * GNU General Public License for more details. 11 * 12 * You should have received a copy of the GNU General Public License 13 * along with this program. If not, see <http://www.gnu.org/licenses/>. 14 * 15 * Adopted from dwmac-sti.c 16 */ 17 18 #include <linux/mfd/syscon.h> 19 #include <linux/of.h> 20 #include <linux/of_address.h> 21 #include <linux/of_net.h> 22 #include <linux/phy.h> 23 #include <linux/regmap.h> 24 #include <linux/reset.h> 25 #include <linux/stmmac.h> 26 27 #include "stmmac.h" 28 #include "stmmac_platform.h" 29 30 #define SYSMGR_EMACGRP_CTRL_PHYSEL_ENUM_GMII_MII 0x0 31 #define SYSMGR_EMACGRP_CTRL_PHYSEL_ENUM_RGMII 0x1 32 #define SYSMGR_EMACGRP_CTRL_PHYSEL_ENUM_RMII 0x2 33 #define SYSMGR_EMACGRP_CTRL_PHYSEL_WIDTH 2 34 #define SYSMGR_EMACGRP_CTRL_PHYSEL_MASK 0x00000003 35 #define SYSMGR_EMACGRP_CTRL_PTP_REF_CLK_MASK 0x00000010 36 37 #define SYSMGR_FPGAGRP_MODULE_REG 0x00000028 38 #define SYSMGR_FPGAGRP_MODULE_EMAC 0x00000004 39 40 #define EMAC_SPLITTER_CTRL_REG 0x0 41 #define EMAC_SPLITTER_CTRL_SPEED_MASK 0x3 42 #define EMAC_SPLITTER_CTRL_SPEED_10 0x2 43 #define EMAC_SPLITTER_CTRL_SPEED_100 0x3 44 #define EMAC_SPLITTER_CTRL_SPEED_1000 0x0 45 46 struct socfpga_dwmac { 47 int interface; 48 u32 reg_offset; 49 u32 reg_shift; 50 struct device *dev; 51 struct regmap *sys_mgr_base_addr; 52 void __iomem *splitter_base; 53 bool f2h_ptp_ref_clk; 54 }; 55 56 static void socfpga_dwmac_fix_mac_speed(void *priv, unsigned int speed) 57 { 58 struct socfpga_dwmac *dwmac = (struct socfpga_dwmac *)priv; 59 void __iomem *splitter_base = dwmac->splitter_base; 60 u32 val; 61 62 if (!splitter_base) 63 return; 64 65 val = readl(splitter_base + EMAC_SPLITTER_CTRL_REG); 66 val &= ~EMAC_SPLITTER_CTRL_SPEED_MASK; 67 68 switch (speed) { 69 case 1000: 70 val |= EMAC_SPLITTER_CTRL_SPEED_1000; 71 break; 72 case 100: 73 val |= EMAC_SPLITTER_CTRL_SPEED_100; 74 break; 75 case 10: 76 val |= EMAC_SPLITTER_CTRL_SPEED_10; 77 break; 78 default: 79 return; 80 } 81 82 writel(val, splitter_base + EMAC_SPLITTER_CTRL_REG); 83 } 84 85 static int socfpga_dwmac_parse_data(struct socfpga_dwmac *dwmac, struct device *dev) 86 { 87 struct device_node *np = dev->of_node; 88 struct regmap *sys_mgr_base_addr; 89 u32 reg_offset, reg_shift; 90 int ret; 91 struct device_node *np_splitter; 92 struct resource res_splitter; 93 94 dwmac->interface = of_get_phy_mode(np); 95 96 sys_mgr_base_addr = syscon_regmap_lookup_by_phandle(np, "altr,sysmgr-syscon"); 97 if (IS_ERR(sys_mgr_base_addr)) { 98 dev_info(dev, "No sysmgr-syscon node found\n"); 99 return PTR_ERR(sys_mgr_base_addr); 100 } 101 102 ret = of_property_read_u32_index(np, "altr,sysmgr-syscon", 1, ®_offset); 103 if (ret) { 104 dev_info(dev, "Could not read reg_offset from sysmgr-syscon!\n"); 105 return -EINVAL; 106 } 107 108 ret = of_property_read_u32_index(np, "altr,sysmgr-syscon", 2, ®_shift); 109 if (ret) { 110 dev_info(dev, "Could not read reg_shift from sysmgr-syscon!\n"); 111 return -EINVAL; 112 } 113 114 dwmac->f2h_ptp_ref_clk = of_property_read_bool(np, "altr,f2h_ptp_ref_clk"); 115 116 np_splitter = of_parse_phandle(np, "altr,emac-splitter", 0); 117 if (np_splitter) { 118 if (of_address_to_resource(np_splitter, 0, &res_splitter)) { 119 dev_info(dev, "Missing emac splitter address\n"); 120 return -EINVAL; 121 } 122 123 dwmac->splitter_base = devm_ioremap_resource(dev, &res_splitter); 124 if (IS_ERR(dwmac->splitter_base)) { 125 dev_info(dev, "Failed to mapping emac splitter\n"); 126 return PTR_ERR(dwmac->splitter_base); 127 } 128 } 129 130 dwmac->reg_offset = reg_offset; 131 dwmac->reg_shift = reg_shift; 132 dwmac->sys_mgr_base_addr = sys_mgr_base_addr; 133 dwmac->dev = dev; 134 135 return 0; 136 } 137 138 static int socfpga_dwmac_setup(struct socfpga_dwmac *dwmac) 139 { 140 struct regmap *sys_mgr_base_addr = dwmac->sys_mgr_base_addr; 141 int phymode = dwmac->interface; 142 u32 reg_offset = dwmac->reg_offset; 143 u32 reg_shift = dwmac->reg_shift; 144 u32 ctrl, val, module; 145 146 switch (phymode) { 147 case PHY_INTERFACE_MODE_RGMII: 148 case PHY_INTERFACE_MODE_RGMII_ID: 149 val = SYSMGR_EMACGRP_CTRL_PHYSEL_ENUM_RGMII; 150 break; 151 case PHY_INTERFACE_MODE_MII: 152 case PHY_INTERFACE_MODE_GMII: 153 val = SYSMGR_EMACGRP_CTRL_PHYSEL_ENUM_GMII_MII; 154 break; 155 default: 156 dev_err(dwmac->dev, "bad phy mode %d\n", phymode); 157 return -EINVAL; 158 } 159 160 /* Overwrite val to GMII if splitter core is enabled. The phymode here 161 * is the actual phy mode on phy hardware, but phy interface from 162 * EMAC core is GMII. 163 */ 164 if (dwmac->splitter_base) 165 val = SYSMGR_EMACGRP_CTRL_PHYSEL_ENUM_GMII_MII; 166 167 regmap_read(sys_mgr_base_addr, reg_offset, &ctrl); 168 ctrl &= ~(SYSMGR_EMACGRP_CTRL_PHYSEL_MASK << reg_shift); 169 ctrl |= val << reg_shift; 170 171 if (dwmac->f2h_ptp_ref_clk) { 172 ctrl |= SYSMGR_EMACGRP_CTRL_PTP_REF_CLK_MASK << (reg_shift / 2); 173 regmap_read(sys_mgr_base_addr, SYSMGR_FPGAGRP_MODULE_REG, 174 &module); 175 module |= (SYSMGR_FPGAGRP_MODULE_EMAC << (reg_shift / 2)); 176 regmap_write(sys_mgr_base_addr, SYSMGR_FPGAGRP_MODULE_REG, 177 module); 178 } else { 179 ctrl &= ~(SYSMGR_EMACGRP_CTRL_PTP_REF_CLK_MASK << (reg_shift / 2)); 180 } 181 182 regmap_write(sys_mgr_base_addr, reg_offset, ctrl); 183 184 return 0; 185 } 186 187 static int socfpga_dwmac_init(struct platform_device *pdev, void *priv) 188 { 189 struct socfpga_dwmac *dwmac = priv; 190 struct net_device *ndev = platform_get_drvdata(pdev); 191 struct stmmac_priv *stpriv = NULL; 192 int ret = 0; 193 194 if (!ndev) 195 return -EINVAL; 196 197 stpriv = netdev_priv(ndev); 198 if (!stpriv) 199 return -EINVAL; 200 201 /* Assert reset to the enet controller before changing the phy mode */ 202 if (stpriv->stmmac_rst) 203 reset_control_assert(stpriv->stmmac_rst); 204 205 /* Setup the phy mode in the system manager registers according to 206 * devicetree configuration 207 */ 208 ret = socfpga_dwmac_setup(dwmac); 209 210 /* Deassert reset for the phy configuration to be sampled by 211 * the enet controller, and operation to start in requested mode 212 */ 213 if (stpriv->stmmac_rst) 214 reset_control_deassert(stpriv->stmmac_rst); 215 216 /* Before the enet controller is suspended, the phy is suspended. 217 * This causes the phy clock to be gated. The enet controller is 218 * resumed before the phy, so the clock is still gated "off" when 219 * the enet controller is resumed. This code makes sure the phy 220 * is "resumed" before reinitializing the enet controller since 221 * the enet controller depends on an active phy clock to complete 222 * a DMA reset. A DMA reset will "time out" if executed 223 * with no phy clock input on the Synopsys enet controller. 224 * Verified through Synopsys Case #8000711656. 225 * 226 * Note that the phy clock is also gated when the phy is isolated. 227 * Phy "suspend" and "isolate" controls are located in phy basic 228 * control register 0, and can be modified by the phy driver 229 * framework. 230 */ 231 if (stpriv->phydev) 232 phy_resume(stpriv->phydev); 233 234 return ret; 235 } 236 237 static int socfpga_dwmac_probe(struct platform_device *pdev) 238 { 239 struct plat_stmmacenet_data *plat_dat; 240 struct stmmac_resources stmmac_res; 241 struct device *dev = &pdev->dev; 242 int ret; 243 struct socfpga_dwmac *dwmac; 244 245 ret = stmmac_get_platform_resources(pdev, &stmmac_res); 246 if (ret) 247 return ret; 248 249 plat_dat = stmmac_probe_config_dt(pdev, &stmmac_res.mac); 250 if (IS_ERR(plat_dat)) 251 return PTR_ERR(plat_dat); 252 253 dwmac = devm_kzalloc(dev, sizeof(*dwmac), GFP_KERNEL); 254 if (!dwmac) 255 return -ENOMEM; 256 257 ret = socfpga_dwmac_parse_data(dwmac, dev); 258 if (ret) { 259 dev_err(dev, "Unable to parse OF data\n"); 260 return ret; 261 } 262 263 plat_dat->bsp_priv = dwmac; 264 plat_dat->fix_mac_speed = socfpga_dwmac_fix_mac_speed; 265 266 ret = stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res); 267 if (!ret) 268 ret = socfpga_dwmac_init(pdev, dwmac); 269 270 return ret; 271 } 272 273 #ifdef CONFIG_PM_SLEEP 274 static int socfpga_dwmac_resume(struct device *dev) 275 { 276 struct platform_device *pdev = to_platform_device(dev); 277 struct net_device *ndev = dev_get_drvdata(dev); 278 struct stmmac_priv *priv = netdev_priv(ndev); 279 280 socfpga_dwmac_init(pdev, priv->plat->bsp_priv); 281 282 return stmmac_resume(dev); 283 } 284 #endif /* CONFIG_PM_SLEEP */ 285 286 SIMPLE_DEV_PM_OPS(socfpga_dwmac_pm_ops, stmmac_suspend, socfpga_dwmac_resume); 287 288 static const struct of_device_id socfpga_dwmac_match[] = { 289 { .compatible = "altr,socfpga-stmmac" }, 290 { } 291 }; 292 MODULE_DEVICE_TABLE(of, socfpga_dwmac_match); 293 294 static struct platform_driver socfpga_dwmac_driver = { 295 .probe = socfpga_dwmac_probe, 296 .remove = stmmac_pltfr_remove, 297 .driver = { 298 .name = "socfpga-dwmac", 299 .pm = &socfpga_dwmac_pm_ops, 300 .of_match_table = socfpga_dwmac_match, 301 }, 302 }; 303 module_platform_driver(socfpga_dwmac_driver); 304 305 MODULE_LICENSE("GPL v2"); 306