| /* | |
| * Amlogic Meson6 and Meson8 DWMAC glue layer | |
| * | |
| * Copyright (C) 2014 Beniamino Galvani <b.galvani@gmail.com> | |
| * | |
| * This program is free software; you can redistribute it and/or modify | |
| * it under the terms of the GNU General Public License version 2 as | |
| * published by the Free Software Foundation. | |
| * | |
| * You should have received a copy of the GNU General Public License | |
| * along with this program. If not, see <http://www.gnu.org/licenses/>. | |
| */ | |
| #include <linux/device.h> | |
| #include <linux/ethtool.h> | |
| #include <linux/io.h> | |
| #include <linux/ioport.h> | |
| #include <linux/module.h> | |
| #include <linux/platform_device.h> | |
| #include <linux/stmmac.h> | |
| #include "stmmac_platform.h" | |
| #define ETHMAC_SPEED_100 BIT(1) | |
| struct meson_dwmac { | |
| struct device *dev; | |
| void __iomem *reg; | |
| }; | |
| static void meson6_dwmac_fix_mac_speed(void *priv, unsigned int speed) | |
| { | |
| struct meson_dwmac *dwmac = priv; | |
| unsigned int val; | |
| val = readl(dwmac->reg); | |
| switch (speed) { | |
| case SPEED_10: | |
| val &= ~ETHMAC_SPEED_100; | |
| break; | |
| case SPEED_100: | |
| val |= ETHMAC_SPEED_100; | |
| break; | |
| } | |
| writel(val, dwmac->reg); | |
| } | |
| static int meson6_dwmac_probe(struct platform_device *pdev) | |
| { | |
| struct plat_stmmacenet_data *plat_dat; | |
| struct stmmac_resources stmmac_res; | |
| struct meson_dwmac *dwmac; | |
| struct resource *res; | |
| int ret; | |
| ret = stmmac_get_platform_resources(pdev, &stmmac_res); | |
| if (ret) | |
| return ret; | |
| plat_dat = stmmac_probe_config_dt(pdev, &stmmac_res.mac); | |
| if (IS_ERR(plat_dat)) | |
| return PTR_ERR(plat_dat); | |
| dwmac = devm_kzalloc(&pdev->dev, sizeof(*dwmac), GFP_KERNEL); | |
| if (!dwmac) { | |
| ret = -ENOMEM; | |
| goto err_remove_config_dt; | |
| } | |
| res = platform_get_resource(pdev, IORESOURCE_MEM, 1); | |
| dwmac->reg = devm_ioremap_resource(&pdev->dev, res); | |
| if (IS_ERR(dwmac->reg)) { | |
| ret = PTR_ERR(dwmac->reg); | |
| goto err_remove_config_dt; | |
| } | |
| plat_dat->bsp_priv = dwmac; | |
| plat_dat->fix_mac_speed = meson6_dwmac_fix_mac_speed; | |
| ret = stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res); | |
| if (ret) | |
| goto err_remove_config_dt; | |
| return 0; | |
| err_remove_config_dt: | |
| stmmac_remove_config_dt(pdev, plat_dat); | |
| return ret; | |
| } | |
| static const struct of_device_id meson6_dwmac_match[] = { | |
| { .compatible = "amlogic,meson6-dwmac" }, | |
| { } | |
| }; | |
| MODULE_DEVICE_TABLE(of, meson6_dwmac_match); | |
| static struct platform_driver meson6_dwmac_driver = { | |
| .probe = meson6_dwmac_probe, | |
| .remove = stmmac_pltfr_remove, | |
| .driver = { | |
| .name = "meson6-dwmac", | |
| .pm = &stmmac_pltfr_pm_ops, | |
| .of_match_table = meson6_dwmac_match, | |
| }, | |
| }; | |
| module_platform_driver(meson6_dwmac_driver); | |
| MODULE_AUTHOR("Beniamino Galvani <b.galvani@gmail.com>"); | |
| MODULE_DESCRIPTION("Amlogic Meson6 and Meson8 DWMAC glue layer"); | |
| MODULE_LICENSE("GPL v2"); |