brintos

brintos / linux-shallow public Read only

0
0
Text · 3.6 KiB · 643ee6d Raw
150 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * Adaptrum Anarion DWMAC glue layer4 *5 * Copyright (C) 2017, Adaptrum, Inc.6 * (Written by Alexandru Gagniuc <alex.g at adaptrum.com> for Adaptrum, Inc.)7 */8 9#include <linux/io.h>10#include <linux/of.h>11#include <linux/of_net.h>12#include <linux/stmmac.h>13 14#include "stmmac.h"15#include "stmmac_platform.h"16 17#define GMAC_RESET_CONTROL_REG		018#define GMAC_SW_CONFIG_REG		419#define  GMAC_CONFIG_INTF_SEL_MASK	(0x7 << 0)20#define  GMAC_CONFIG_INTF_RGMII		(0x1 << 0)21 22struct anarion_gmac {23	void __iomem *ctl_block;24	uint32_t phy_intf_sel;25};26 27static uint32_t gmac_read_reg(struct anarion_gmac *gmac, uint8_t reg)28{29	return readl(gmac->ctl_block + reg);30};31 32static void gmac_write_reg(struct anarion_gmac *gmac, uint8_t reg, uint32_t val)33{34	writel(val, gmac->ctl_block + reg);35}36 37static int anarion_gmac_init(struct platform_device *pdev, void *priv)38{39	uint32_t sw_config;40	struct anarion_gmac *gmac = priv;41 42	/* Reset logic, configure interface mode, then release reset. SIMPLE! */43	gmac_write_reg(gmac, GMAC_RESET_CONTROL_REG, 1);44 45	sw_config = gmac_read_reg(gmac, GMAC_SW_CONFIG_REG);46	sw_config &= ~GMAC_CONFIG_INTF_SEL_MASK;47	sw_config |= (gmac->phy_intf_sel & GMAC_CONFIG_INTF_SEL_MASK);48	gmac_write_reg(gmac, GMAC_SW_CONFIG_REG, sw_config);49 50	gmac_write_reg(gmac, GMAC_RESET_CONTROL_REG, 0);51 52	return 0;53}54 55static void anarion_gmac_exit(struct platform_device *pdev, void *priv)56{57	struct anarion_gmac *gmac = priv;58 59	gmac_write_reg(gmac, GMAC_RESET_CONTROL_REG, 1);60}61 62static struct anarion_gmac *anarion_config_dt(struct platform_device *pdev)63{64	struct anarion_gmac *gmac;65	phy_interface_t phy_mode;66	void __iomem *ctl_block;67	int err;68 69	ctl_block = devm_platform_ioremap_resource(pdev, 1);70	if (IS_ERR(ctl_block)) {71		err = PTR_ERR(ctl_block);72		dev_err(&pdev->dev, "Cannot get reset region (%d)!\n", err);73		return ERR_PTR(err);74	}75 76	gmac = devm_kzalloc(&pdev->dev, sizeof(*gmac), GFP_KERNEL);77	if (!gmac)78		return ERR_PTR(-ENOMEM);79 80	gmac->ctl_block = ctl_block;81 82	err = of_get_phy_mode(pdev->dev.of_node, &phy_mode);83	if (err)84		return ERR_PTR(err);85 86	switch (phy_mode) {87	case PHY_INTERFACE_MODE_RGMII:88		fallthrough;89	case PHY_INTERFACE_MODE_RGMII_ID:90	case PHY_INTERFACE_MODE_RGMII_RXID:91	case PHY_INTERFACE_MODE_RGMII_TXID:92		gmac->phy_intf_sel = GMAC_CONFIG_INTF_RGMII;93		break;94	default:95		dev_err(&pdev->dev, "Unsupported phy-mode (%d)\n",96			phy_mode);97		return ERR_PTR(-ENOTSUPP);98	}99 100	return gmac;101}102 103static int anarion_dwmac_probe(struct platform_device *pdev)104{105	int ret;106	struct anarion_gmac *gmac;107	struct plat_stmmacenet_data *plat_dat;108	struct stmmac_resources stmmac_res;109 110	ret = stmmac_get_platform_resources(pdev, &stmmac_res);111	if (ret)112		return ret;113 114	gmac = anarion_config_dt(pdev);115	if (IS_ERR(gmac))116		return PTR_ERR(gmac);117 118	plat_dat = devm_stmmac_probe_config_dt(pdev, stmmac_res.mac);119	if (IS_ERR(plat_dat))120		return PTR_ERR(plat_dat);121 122	plat_dat->init = anarion_gmac_init;123	plat_dat->exit = anarion_gmac_exit;124	anarion_gmac_init(pdev, gmac);125	plat_dat->bsp_priv = gmac;126 127	return stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res);128}129 130static const struct of_device_id anarion_dwmac_match[] = {131	{ .compatible = "adaptrum,anarion-gmac" },132	{ }133};134MODULE_DEVICE_TABLE(of, anarion_dwmac_match);135 136static struct platform_driver anarion_dwmac_driver = {137	.probe  = anarion_dwmac_probe,138	.remove_new = stmmac_pltfr_remove,139	.driver = {140		.name           = "anarion-dwmac",141		.pm		= &stmmac_pltfr_pm_ops,142		.of_match_table = anarion_dwmac_match,143	},144};145module_platform_driver(anarion_dwmac_driver);146 147MODULE_DESCRIPTION("Adaptrum Anarion DWMAC specific glue layer");148MODULE_AUTHOR("Alexandru Gagniuc <mr.nuke.me@gmail.com>");149MODULE_LICENSE("GPL v2");150