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