brintos

brintos / linux-shallow public Read only

0
0
Text · 5.8 KiB · e6e130d Raw
250 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/* 10G controller driver for Samsung SoCs3 *4 * Copyright (C) 2013 Samsung Electronics Co., Ltd.5 *		http://www.samsung.com6 *7 * Author: Siva Reddy Kallam <siva.kallam@samsung.com>8 */9 10#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt11 12#include <linux/etherdevice.h>13#include <linux/io.h>14#include <linux/module.h>15#include <linux/netdevice.h>16#include <linux/of.h>17#include <linux/of_irq.h>18#include <linux/of_net.h>19#include <linux/phy.h>20#include <linux/platform_device.h>21#include <linux/sxgbe_platform.h>22 23#include "sxgbe_common.h"24#include "sxgbe_reg.h"25 26#ifdef CONFIG_OF27static int sxgbe_probe_config_dt(struct platform_device *pdev,28				 struct sxgbe_plat_data *plat)29{30	struct device_node *np = pdev->dev.of_node;31	struct sxgbe_dma_cfg *dma_cfg;32	int err;33 34	if (!np)35		return -ENODEV;36 37	err = of_get_phy_mode(np, &plat->interface);38	if (err && err != -ENODEV)39		return err;40 41	plat->bus_id = of_alias_get_id(np, "ethernet");42	if (plat->bus_id < 0)43		plat->bus_id = 0;44 45	plat->mdio_bus_data = devm_kzalloc(&pdev->dev,46					   sizeof(*plat->mdio_bus_data),47					   GFP_KERNEL);48	if (!plat->mdio_bus_data)49		return -ENOMEM;50 51	dma_cfg = devm_kzalloc(&pdev->dev, sizeof(*dma_cfg), GFP_KERNEL);52	if (!dma_cfg)53		return -ENOMEM;54 55	plat->dma_cfg = dma_cfg;56	of_property_read_u32(np, "samsung,pbl", &dma_cfg->pbl);57	if (of_property_read_u32(np, "samsung,burst-map", &dma_cfg->burst_map) == 0)58		dma_cfg->fixed_burst = true;59 60	return 0;61}62#else63static int sxgbe_probe_config_dt(struct platform_device *pdev,64				 struct sxgbe_plat_data *plat)65{66	return -ENOSYS;67}68#endif /* CONFIG_OF */69 70/**71 * sxgbe_platform_probe72 * @pdev: platform device pointer73 * Description: platform_device probe function. It allocates74 * the necessary resources and invokes the main to init75 * the net device, register the mdio bus etc.76 */77static int sxgbe_platform_probe(struct platform_device *pdev)78{79	int ret;80	int i, chan;81	struct device *dev = &pdev->dev;82	void __iomem *addr;83	struct sxgbe_priv_data *priv = NULL;84	struct sxgbe_plat_data *plat_dat = NULL;85	struct net_device *ndev = platform_get_drvdata(pdev);86	struct device_node *node = dev->of_node;87 88	/* Get memory resource */89	addr = devm_platform_ioremap_resource(pdev, 0);90	if (IS_ERR(addr))91		return PTR_ERR(addr);92 93	if (pdev->dev.of_node) {94		plat_dat = devm_kzalloc(&pdev->dev,95					sizeof(struct sxgbe_plat_data),96					GFP_KERNEL);97		if (!plat_dat)98			return  -ENOMEM;99 100		ret = sxgbe_probe_config_dt(pdev, plat_dat);101		if (ret) {102			pr_err("%s: main dt probe failed\n", __func__);103			return ret;104		}105	}106 107	priv = sxgbe_drv_probe(&(pdev->dev), plat_dat, addr);108	if (!priv) {109		pr_err("%s: main driver probe failed\n", __func__);110		goto err_out;111	}112 113	/* Get the SXGBE common INT information */114	priv->irq  = irq_of_parse_and_map(node, 0);115	if (priv->irq <= 0) {116		dev_err(dev, "sxgbe common irq parsing failed\n");117		goto err_drv_remove;118	}119 120	/* Get MAC address if available (DT) */121	of_get_ethdev_address(node, priv->dev);122 123	/* Get the TX/RX IRQ numbers */124	for (i = 0, chan = 1; i < SXGBE_TX_QUEUES; i++) {125		priv->txq[i]->irq_no = irq_of_parse_and_map(node, chan++);126		if (priv->txq[i]->irq_no <= 0) {127			dev_err(dev, "sxgbe tx irq parsing failed\n");128			goto err_tx_irq_unmap;129		}130	}131 132	for (i = 0; i < SXGBE_RX_QUEUES; i++) {133		priv->rxq[i]->irq_no = irq_of_parse_and_map(node, chan++);134		if (priv->rxq[i]->irq_no <= 0) {135			dev_err(dev, "sxgbe rx irq parsing failed\n");136			goto err_rx_irq_unmap;137		}138	}139 140	priv->lpi_irq = irq_of_parse_and_map(node, chan);141	if (priv->lpi_irq <= 0) {142		dev_err(dev, "sxgbe lpi irq parsing failed\n");143		goto err_rx_irq_unmap;144	}145 146	platform_set_drvdata(pdev, priv->dev);147 148	pr_debug("platform driver registration completed\n");149 150	return 0;151 152err_rx_irq_unmap:153	while (i--)154		irq_dispose_mapping(priv->rxq[i]->irq_no);155	i = SXGBE_TX_QUEUES;156err_tx_irq_unmap:157	while (i--)158		irq_dispose_mapping(priv->txq[i]->irq_no);159	irq_dispose_mapping(priv->irq);160err_drv_remove:161	sxgbe_drv_remove(ndev);162err_out:163	return -ENODEV;164}165 166/**167 * sxgbe_platform_remove168 * @pdev: platform device pointer169 * Description: this function calls the main to free the net resources170 * and calls the platforms hook and release the resources (e.g. mem).171 */172static void sxgbe_platform_remove(struct platform_device *pdev)173{174	struct net_device *ndev = platform_get_drvdata(pdev);175 176	sxgbe_drv_remove(ndev);177}178 179#ifdef CONFIG_PM180static int sxgbe_platform_suspend(struct device *dev)181{182	struct net_device *ndev = dev_get_drvdata(dev);183 184	return sxgbe_suspend(ndev);185}186 187static int sxgbe_platform_resume(struct device *dev)188{189	struct net_device *ndev = dev_get_drvdata(dev);190 191	return sxgbe_resume(ndev);192}193 194static int sxgbe_platform_freeze(struct device *dev)195{196	struct net_device *ndev = dev_get_drvdata(dev);197 198	return sxgbe_freeze(ndev);199}200 201static int sxgbe_platform_restore(struct device *dev)202{203	struct net_device *ndev = dev_get_drvdata(dev);204 205	return sxgbe_restore(ndev);206}207 208static const struct dev_pm_ops sxgbe_platform_pm_ops = {209	.suspend	= sxgbe_platform_suspend,210	.resume		= sxgbe_platform_resume,211	.freeze		= sxgbe_platform_freeze,212	.thaw		= sxgbe_platform_restore,213	.restore	= sxgbe_platform_restore,214};215#else216static const struct dev_pm_ops sxgbe_platform_pm_ops;217#endif /* CONFIG_PM */218 219static const struct of_device_id sxgbe_dt_ids[] = {220	{ .compatible = "samsung,sxgbe-v2.0a"},221	{ /* sentinel */ }222};223MODULE_DEVICE_TABLE(of, sxgbe_dt_ids);224 225static struct platform_driver sxgbe_platform_driver = {226	.probe	= sxgbe_platform_probe,227	.remove_new = sxgbe_platform_remove,228	.driver	= {229		.name		= SXGBE_RESOURCE_NAME,230		.pm		= &sxgbe_platform_pm_ops,231		.of_match_table	= sxgbe_dt_ids,232	},233};234 235int sxgbe_register_platform(void)236{237	int err;238 239	err = platform_driver_register(&sxgbe_platform_driver);240	if (err)241		pr_err("failed to register the platform driver\n");242 243	return err;244}245 246void sxgbe_unregister_platform(void)247{248	platform_driver_unregister(&sxgbe_platform_driver);249}250