1 /* 2 * Amlogic Meson6 and Meson8 DWMAC glue layer 3 * 4 * Copyright (C) 2014 Beniamino Galvani <b.galvani@gmail.com> 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License version 2 as 8 * published by the Free Software Foundation. 9 * 10 * You should have received a copy of the GNU General Public License 11 * along with this program. If not, see <http://www.gnu.org/licenses/>. 12 */ 13 14 #include <linux/device.h> 15 #include <linux/ethtool.h> 16 #include <linux/io.h> 17 #include <linux/ioport.h> 18 #include <linux/module.h> 19 #include <linux/platform_device.h> 20 #include <linux/stmmac.h> 21 22 #include "stmmac_platform.h" 23 24 #define ETHMAC_SPEED_100 BIT(1) 25 26 struct meson_dwmac { 27 struct device *dev; 28 void __iomem *reg; 29 }; 30 31 static void meson6_dwmac_fix_mac_speed(void *priv, unsigned int speed) 32 { 33 struct meson_dwmac *dwmac = priv; 34 unsigned int val; 35 36 val = readl(dwmac->reg); 37 38 switch (speed) { 39 case SPEED_10: 40 val &= ~ETHMAC_SPEED_100; 41 break; 42 case SPEED_100: 43 val |= ETHMAC_SPEED_100; 44 break; 45 } 46 47 writel(val, dwmac->reg); 48 } 49 50 static int meson6_dwmac_probe(struct platform_device *pdev) 51 { 52 struct plat_stmmacenet_data *plat_dat; 53 struct stmmac_resources stmmac_res; 54 struct meson_dwmac *dwmac; 55 struct resource *res; 56 int ret; 57 58 ret = stmmac_get_platform_resources(pdev, &stmmac_res); 59 if (ret) 60 return ret; 61 62 plat_dat = stmmac_probe_config_dt(pdev, &stmmac_res.mac); 63 if (IS_ERR(plat_dat)) 64 return PTR_ERR(plat_dat); 65 66 dwmac = devm_kzalloc(&pdev->dev, sizeof(*dwmac), GFP_KERNEL); 67 if (!dwmac) { 68 ret = -ENOMEM; 69 goto err_remove_config_dt; 70 } 71 72 res = platform_get_resource(pdev, IORESOURCE_MEM, 1); 73 dwmac->reg = devm_ioremap_resource(&pdev->dev, res); 74 if (IS_ERR(dwmac->reg)) { 75 ret = PTR_ERR(dwmac->reg); 76 goto err_remove_config_dt; 77 } 78 79 plat_dat->bsp_priv = dwmac; 80 plat_dat->fix_mac_speed = meson6_dwmac_fix_mac_speed; 81 82 ret = stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res); 83 if (ret) 84 goto err_remove_config_dt; 85 86 return 0; 87 88 err_remove_config_dt: 89 stmmac_remove_config_dt(pdev, plat_dat); 90 91 return ret; 92 } 93 94 static const struct of_device_id meson6_dwmac_match[] = { 95 { .compatible = "amlogic,meson6-dwmac" }, 96 { } 97 }; 98 MODULE_DEVICE_TABLE(of, meson6_dwmac_match); 99 100 static struct platform_driver meson6_dwmac_driver = { 101 .probe = meson6_dwmac_probe, 102 .remove = stmmac_pltfr_remove, 103 .driver = { 104 .name = "meson6-dwmac", 105 .pm = &stmmac_pltfr_pm_ops, 106 .of_match_table = meson6_dwmac_match, 107 }, 108 }; 109 module_platform_driver(meson6_dwmac_driver); 110 111 MODULE_AUTHOR("Beniamino Galvani <b.galvani@gmail.com>"); 112 MODULE_DESCRIPTION("Amlogic Meson6 and Meson8 DWMAC glue layer"); 113 MODULE_LICENSE("GPL v2"); 114