13c910ecbSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
20ad5adcdSBeniamino Galvani /*
3466fd24bSMartin Blumenstingl * Amlogic Meson6 and Meson8 DWMAC glue layer
40ad5adcdSBeniamino Galvani *
50ad5adcdSBeniamino Galvani * Copyright (C) 2014 Beniamino Galvani <b.galvani@gmail.com>
60ad5adcdSBeniamino Galvani */
70ad5adcdSBeniamino Galvani
80ad5adcdSBeniamino Galvani #include <linux/device.h>
90ad5adcdSBeniamino Galvani #include <linux/ethtool.h>
100ad5adcdSBeniamino Galvani #include <linux/io.h>
110ad5adcdSBeniamino Galvani #include <linux/ioport.h>
1240e6b0baSJoachim Eastwood #include <linux/module.h>
130ad5adcdSBeniamino Galvani #include <linux/platform_device.h>
140ad5adcdSBeniamino Galvani #include <linux/stmmac.h>
150ad5adcdSBeniamino Galvani
16f10f9fb2SAndy Shevchenko #include "stmmac_platform.h"
17f10f9fb2SAndy Shevchenko
180ad5adcdSBeniamino Galvani #define ETHMAC_SPEED_100 BIT(1)
190ad5adcdSBeniamino Galvani
200ad5adcdSBeniamino Galvani struct meson_dwmac {
210ad5adcdSBeniamino Galvani struct device *dev;
220ad5adcdSBeniamino Galvani void __iomem *reg;
230ad5adcdSBeniamino Galvani };
240ad5adcdSBeniamino Galvani
meson6_dwmac_fix_mac_speed(void * priv,unsigned int speed,unsigned int mode)25*1fc04a0bSShenwei Wang static void meson6_dwmac_fix_mac_speed(void *priv, unsigned int speed, unsigned int mode)
260ad5adcdSBeniamino Galvani {
270ad5adcdSBeniamino Galvani struct meson_dwmac *dwmac = priv;
280ad5adcdSBeniamino Galvani unsigned int val;
290ad5adcdSBeniamino Galvani
300ad5adcdSBeniamino Galvani val = readl(dwmac->reg);
310ad5adcdSBeniamino Galvani
320ad5adcdSBeniamino Galvani switch (speed) {
330ad5adcdSBeniamino Galvani case SPEED_10:
340ad5adcdSBeniamino Galvani val &= ~ETHMAC_SPEED_100;
350ad5adcdSBeniamino Galvani break;
360ad5adcdSBeniamino Galvani case SPEED_100:
370ad5adcdSBeniamino Galvani val |= ETHMAC_SPEED_100;
380ad5adcdSBeniamino Galvani break;
390ad5adcdSBeniamino Galvani }
400ad5adcdSBeniamino Galvani
410ad5adcdSBeniamino Galvani writel(val, dwmac->reg);
420ad5adcdSBeniamino Galvani }
430ad5adcdSBeniamino Galvani
meson6_dwmac_probe(struct platform_device * pdev)441734befdSJoachim Eastwood static int meson6_dwmac_probe(struct platform_device *pdev)
450ad5adcdSBeniamino Galvani {
461734befdSJoachim Eastwood struct plat_stmmacenet_data *plat_dat;
471734befdSJoachim Eastwood struct stmmac_resources stmmac_res;
480ad5adcdSBeniamino Galvani struct meson_dwmac *dwmac;
491734befdSJoachim Eastwood int ret;
501734befdSJoachim Eastwood
511734befdSJoachim Eastwood ret = stmmac_get_platform_resources(pdev, &stmmac_res);
521734befdSJoachim Eastwood if (ret)
531734befdSJoachim Eastwood return ret;
541734befdSJoachim Eastwood
5583216e39SMichael Walle plat_dat = stmmac_probe_config_dt(pdev, stmmac_res.mac);
561734befdSJoachim Eastwood if (IS_ERR(plat_dat))
571734befdSJoachim Eastwood return PTR_ERR(plat_dat);
580ad5adcdSBeniamino Galvani
590ad5adcdSBeniamino Galvani dwmac = devm_kzalloc(&pdev->dev, sizeof(*dwmac), GFP_KERNEL);
60d2ed0a77SJohan Hovold if (!dwmac) {
61d2ed0a77SJohan Hovold ret = -ENOMEM;
62d2ed0a77SJohan Hovold goto err_remove_config_dt;
63d2ed0a77SJohan Hovold }
640ad5adcdSBeniamino Galvani
65f33bf6b0SYueHaibing dwmac->reg = devm_platform_ioremap_resource(pdev, 1);
66d2ed0a77SJohan Hovold if (IS_ERR(dwmac->reg)) {
67d2ed0a77SJohan Hovold ret = PTR_ERR(dwmac->reg);
68d2ed0a77SJohan Hovold goto err_remove_config_dt;
69d2ed0a77SJohan Hovold }
700ad5adcdSBeniamino Galvani
711734befdSJoachim Eastwood plat_dat->bsp_priv = dwmac;
721734befdSJoachim Eastwood plat_dat->fix_mac_speed = meson6_dwmac_fix_mac_speed;
731734befdSJoachim Eastwood
74d2ed0a77SJohan Hovold ret = stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res);
75d2ed0a77SJohan Hovold if (ret)
76d2ed0a77SJohan Hovold goto err_remove_config_dt;
77d2ed0a77SJohan Hovold
78d2ed0a77SJohan Hovold return 0;
79d2ed0a77SJohan Hovold
80d2ed0a77SJohan Hovold err_remove_config_dt:
81d2ed0a77SJohan Hovold stmmac_remove_config_dt(pdev, plat_dat);
82d2ed0a77SJohan Hovold
83d2ed0a77SJohan Hovold return ret;
840ad5adcdSBeniamino Galvani }
850ad5adcdSBeniamino Galvani
8640e6b0baSJoachim Eastwood static const struct of_device_id meson6_dwmac_match[] = {
871734befdSJoachim Eastwood { .compatible = "amlogic,meson6-dwmac" },
8840e6b0baSJoachim Eastwood { }
8940e6b0baSJoachim Eastwood };
9040e6b0baSJoachim Eastwood MODULE_DEVICE_TABLE(of, meson6_dwmac_match);
9140e6b0baSJoachim Eastwood
9240e6b0baSJoachim Eastwood static struct platform_driver meson6_dwmac_driver = {
931734befdSJoachim Eastwood .probe = meson6_dwmac_probe,
943246627fSUwe Kleine-König .remove_new = stmmac_pltfr_remove,
9540e6b0baSJoachim Eastwood .driver = {
9640e6b0baSJoachim Eastwood .name = "meson6-dwmac",
9740e6b0baSJoachim Eastwood .pm = &stmmac_pltfr_pm_ops,
9840e6b0baSJoachim Eastwood .of_match_table = meson6_dwmac_match,
9940e6b0baSJoachim Eastwood },
10040e6b0baSJoachim Eastwood };
10140e6b0baSJoachim Eastwood module_platform_driver(meson6_dwmac_driver);
10240e6b0baSJoachim Eastwood
10340e6b0baSJoachim Eastwood MODULE_AUTHOR("Beniamino Galvani <b.galvani@gmail.com>");
104466fd24bSMartin Blumenstingl MODULE_DESCRIPTION("Amlogic Meson6 and Meson8 DWMAC glue layer");
10540e6b0baSJoachim Eastwood MODULE_LICENSE("GPL v2");
106