Linux Audio

Check our new training course

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