xref: /openbmc/linux/drivers/net/ethernet/samsung/sxgbe/sxgbe_platform.c (revision 1ac731c529cd4d6adbce134754b51ff7d822b145)
1d2912cb1SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
21edb9ca6SSiva Reddy /* 10G controller driver for Samsung SoCs
31edb9ca6SSiva Reddy  *
41edb9ca6SSiva Reddy  * Copyright (C) 2013 Samsung Electronics Co., Ltd.
51edb9ca6SSiva Reddy  *		http://www.samsung.com
61edb9ca6SSiva Reddy  *
71edb9ca6SSiva Reddy  * Author: Siva Reddy Kallam <siva.kallam@samsung.com>
81edb9ca6SSiva Reddy  */
91edb9ca6SSiva Reddy 
101edb9ca6SSiva Reddy #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
111edb9ca6SSiva Reddy 
121edb9ca6SSiva Reddy #include <linux/etherdevice.h>
131edb9ca6SSiva Reddy #include <linux/io.h>
141edb9ca6SSiva Reddy #include <linux/module.h>
151edb9ca6SSiva Reddy #include <linux/netdevice.h>
161edb9ca6SSiva Reddy #include <linux/of.h>
171edb9ca6SSiva Reddy #include <linux/of_irq.h>
181edb9ca6SSiva Reddy #include <linux/of_net.h>
191edb9ca6SSiva Reddy #include <linux/phy.h>
201edb9ca6SSiva Reddy #include <linux/platform_device.h>
211edb9ca6SSiva Reddy #include <linux/sxgbe_platform.h>
221edb9ca6SSiva Reddy 
231edb9ca6SSiva Reddy #include "sxgbe_common.h"
241edb9ca6SSiva Reddy #include "sxgbe_reg.h"
251edb9ca6SSiva Reddy 
261edb9ca6SSiva Reddy #ifdef CONFIG_OF
sxgbe_probe_config_dt(struct platform_device * pdev,struct sxgbe_plat_data * plat)271edb9ca6SSiva Reddy static int sxgbe_probe_config_dt(struct platform_device *pdev,
2883216e39SMichael Walle 				 struct sxgbe_plat_data *plat)
291edb9ca6SSiva Reddy {
301edb9ca6SSiva Reddy 	struct device_node *np = pdev->dev.of_node;
311edb9ca6SSiva Reddy 	struct sxgbe_dma_cfg *dma_cfg;
320c65b2b9SAndrew Lunn 	int err;
331edb9ca6SSiva Reddy 
341edb9ca6SSiva Reddy 	if (!np)
351edb9ca6SSiva Reddy 		return -ENODEV;
361edb9ca6SSiva Reddy 
370c65b2b9SAndrew Lunn 	err = of_get_phy_mode(np, &plat->interface);
380c65b2b9SAndrew Lunn 	if (err && err != -ENODEV)
390c65b2b9SAndrew Lunn 		return err;
401edb9ca6SSiva Reddy 
411edb9ca6SSiva Reddy 	plat->bus_id = of_alias_get_id(np, "ethernet");
421edb9ca6SSiva Reddy 	if (plat->bus_id < 0)
431edb9ca6SSiva Reddy 		plat->bus_id = 0;
441edb9ca6SSiva Reddy 
451edb9ca6SSiva Reddy 	plat->mdio_bus_data = devm_kzalloc(&pdev->dev,
461edb9ca6SSiva Reddy 					   sizeof(*plat->mdio_bus_data),
471edb9ca6SSiva Reddy 					   GFP_KERNEL);
482207d182SChristophe Jaillet 	if (!plat->mdio_bus_data)
492207d182SChristophe Jaillet 		return -ENOMEM;
501edb9ca6SSiva Reddy 
511edb9ca6SSiva Reddy 	dma_cfg = devm_kzalloc(&pdev->dev, sizeof(*dma_cfg), GFP_KERNEL);
521edb9ca6SSiva Reddy 	if (!dma_cfg)
531edb9ca6SSiva Reddy 		return -ENOMEM;
541edb9ca6SSiva Reddy 
551edb9ca6SSiva Reddy 	plat->dma_cfg = dma_cfg;
561edb9ca6SSiva Reddy 	of_property_read_u32(np, "samsung,pbl", &dma_cfg->pbl);
571edb9ca6SSiva Reddy 	if (of_property_read_u32(np, "samsung,burst-map", &dma_cfg->burst_map) == 0)
581edb9ca6SSiva Reddy 		dma_cfg->fixed_burst = true;
591edb9ca6SSiva Reddy 
601edb9ca6SSiva Reddy 	return 0;
611edb9ca6SSiva Reddy }
621edb9ca6SSiva Reddy #else
sxgbe_probe_config_dt(struct platform_device * pdev,struct sxgbe_plat_data * plat)631edb9ca6SSiva Reddy static int sxgbe_probe_config_dt(struct platform_device *pdev,
6483216e39SMichael Walle 				 struct sxgbe_plat_data *plat)
651edb9ca6SSiva Reddy {
661edb9ca6SSiva Reddy 	return -ENOSYS;
671edb9ca6SSiva Reddy }
681edb9ca6SSiva Reddy #endif /* CONFIG_OF */
691edb9ca6SSiva Reddy 
701edb9ca6SSiva Reddy /**
711edb9ca6SSiva Reddy  * sxgbe_platform_probe
721edb9ca6SSiva Reddy  * @pdev: platform device pointer
731edb9ca6SSiva Reddy  * Description: platform_device probe function. It allocates
741edb9ca6SSiva Reddy  * the necessary resources and invokes the main to init
751edb9ca6SSiva Reddy  * the net device, register the mdio bus etc.
761edb9ca6SSiva Reddy  */
sxgbe_platform_probe(struct platform_device * pdev)771edb9ca6SSiva Reddy static int sxgbe_platform_probe(struct platform_device *pdev)
781edb9ca6SSiva Reddy {
791edb9ca6SSiva Reddy 	int ret;
801edb9ca6SSiva Reddy 	int i, chan;
811edb9ca6SSiva Reddy 	struct device *dev = &pdev->dev;
821edb9ca6SSiva Reddy 	void __iomem *addr;
831edb9ca6SSiva Reddy 	struct sxgbe_priv_data *priv = NULL;
841edb9ca6SSiva Reddy 	struct sxgbe_plat_data *plat_dat = NULL;
851edb9ca6SSiva Reddy 	struct net_device *ndev = platform_get_drvdata(pdev);
861edb9ca6SSiva Reddy 	struct device_node *node = dev->of_node;
871edb9ca6SSiva Reddy 
881edb9ca6SSiva Reddy 	/* Get memory resource */
89ffb36a10SYueHaibing 	addr = devm_platform_ioremap_resource(pdev, 0);
901edb9ca6SSiva Reddy 	if (IS_ERR(addr))
911edb9ca6SSiva Reddy 		return PTR_ERR(addr);
921edb9ca6SSiva Reddy 
931edb9ca6SSiva Reddy 	if (pdev->dev.of_node) {
941edb9ca6SSiva Reddy 		plat_dat = devm_kzalloc(&pdev->dev,
951edb9ca6SSiva Reddy 					sizeof(struct sxgbe_plat_data),
961edb9ca6SSiva Reddy 					GFP_KERNEL);
971edb9ca6SSiva Reddy 		if (!plat_dat)
981edb9ca6SSiva Reddy 			return  -ENOMEM;
991edb9ca6SSiva Reddy 
10083216e39SMichael Walle 		ret = sxgbe_probe_config_dt(pdev, plat_dat);
1011edb9ca6SSiva Reddy 		if (ret) {
1021edb9ca6SSiva Reddy 			pr_err("%s: main dt probe failed\n", __func__);
1031edb9ca6SSiva Reddy 			return ret;
1041edb9ca6SSiva Reddy 		}
1051edb9ca6SSiva Reddy 	}
1061edb9ca6SSiva Reddy 
1071edb9ca6SSiva Reddy 	priv = sxgbe_drv_probe(&(pdev->dev), plat_dat, addr);
1081edb9ca6SSiva Reddy 	if (!priv) {
1091edb9ca6SSiva Reddy 		pr_err("%s: main driver probe failed\n", __func__);
1101edb9ca6SSiva Reddy 		goto err_out;
1111edb9ca6SSiva Reddy 	}
1121edb9ca6SSiva Reddy 
1131edb9ca6SSiva Reddy 	/* Get the SXGBE common INT information */
1141edb9ca6SSiva Reddy 	priv->irq  = irq_of_parse_and_map(node, 0);
1151edb9ca6SSiva Reddy 	if (priv->irq <= 0) {
1161edb9ca6SSiva Reddy 		dev_err(dev, "sxgbe common irq parsing failed\n");
1171edb9ca6SSiva Reddy 		goto err_drv_remove;
1181edb9ca6SSiva Reddy 	}
1191edb9ca6SSiva Reddy 
1201c1832c7SGirish K.S 	/* Get MAC address if available (DT) */
1219ca01b25SJakub Kicinski 	of_get_ethdev_address(node, priv->dev);
1221c1832c7SGirish K.S 
1231edb9ca6SSiva Reddy 	/* Get the TX/RX IRQ numbers */
1241edb9ca6SSiva Reddy 	for (i = 0, chan = 1; i < SXGBE_TX_QUEUES; i++) {
1251edb9ca6SSiva Reddy 		priv->txq[i]->irq_no = irq_of_parse_and_map(node, chan++);
1261edb9ca6SSiva Reddy 		if (priv->txq[i]->irq_no <= 0) {
1271edb9ca6SSiva Reddy 			dev_err(dev, "sxgbe tx irq parsing failed\n");
1281edb9ca6SSiva Reddy 			goto err_tx_irq_unmap;
1291edb9ca6SSiva Reddy 		}
1301edb9ca6SSiva Reddy 	}
1311edb9ca6SSiva Reddy 
1321edb9ca6SSiva Reddy 	for (i = 0; i < SXGBE_RX_QUEUES; i++) {
1331edb9ca6SSiva Reddy 		priv->rxq[i]->irq_no = irq_of_parse_and_map(node, chan++);
1341edb9ca6SSiva Reddy 		if (priv->rxq[i]->irq_no <= 0) {
1351edb9ca6SSiva Reddy 			dev_err(dev, "sxgbe rx irq parsing failed\n");
1361edb9ca6SSiva Reddy 			goto err_rx_irq_unmap;
1371edb9ca6SSiva Reddy 		}
1381edb9ca6SSiva Reddy 	}
1391edb9ca6SSiva Reddy 
140acc18c14SGirish K S 	priv->lpi_irq = irq_of_parse_and_map(node, chan);
141acc18c14SGirish K S 	if (priv->lpi_irq <= 0) {
142acc18c14SGirish K S 		dev_err(dev, "sxgbe lpi irq parsing failed\n");
143acc18c14SGirish K S 		goto err_rx_irq_unmap;
144acc18c14SGirish K S 	}
145acc18c14SGirish K S 
1461edb9ca6SSiva Reddy 	platform_set_drvdata(pdev, priv->dev);
1471edb9ca6SSiva Reddy 
1481edb9ca6SSiva Reddy 	pr_debug("platform driver registration completed\n");
1491edb9ca6SSiva Reddy 
1501edb9ca6SSiva Reddy 	return 0;
1511edb9ca6SSiva Reddy 
1521edb9ca6SSiva Reddy err_rx_irq_unmap:
15379c13423SRasmus Villemoes 	while (i--)
1541edb9ca6SSiva Reddy 		irq_dispose_mapping(priv->rxq[i]->irq_no);
1551edb9ca6SSiva Reddy 	i = SXGBE_TX_QUEUES;
1561edb9ca6SSiva Reddy err_tx_irq_unmap:
15779c13423SRasmus Villemoes 	while (i--)
1581edb9ca6SSiva Reddy 		irq_dispose_mapping(priv->txq[i]->irq_no);
1591edb9ca6SSiva Reddy 	irq_dispose_mapping(priv->irq);
1601edb9ca6SSiva Reddy err_drv_remove:
1611edb9ca6SSiva Reddy 	sxgbe_drv_remove(ndev);
1621edb9ca6SSiva Reddy err_out:
1631edb9ca6SSiva Reddy 	return -ENODEV;
1641edb9ca6SSiva Reddy }
1651edb9ca6SSiva Reddy 
1661edb9ca6SSiva Reddy /**
1671edb9ca6SSiva Reddy  * sxgbe_platform_remove
1681edb9ca6SSiva Reddy  * @pdev: platform device pointer
1691edb9ca6SSiva Reddy  * Description: this function calls the main to free the net resources
1701edb9ca6SSiva Reddy  * and calls the platforms hook and release the resources (e.g. mem).
1711edb9ca6SSiva Reddy  */
sxgbe_platform_remove(struct platform_device * pdev)1721edb9ca6SSiva Reddy static int sxgbe_platform_remove(struct platform_device *pdev)
1731edb9ca6SSiva Reddy {
1741edb9ca6SSiva Reddy 	struct net_device *ndev = platform_get_drvdata(pdev);
1751edb9ca6SSiva Reddy 
1761edb9ca6SSiva Reddy 	sxgbe_drv_remove(ndev);
1771edb9ca6SSiva Reddy 
1781edb9ca6SSiva Reddy 	return 0;
1791edb9ca6SSiva Reddy }
1801edb9ca6SSiva Reddy 
1811edb9ca6SSiva Reddy #ifdef CONFIG_PM
sxgbe_platform_suspend(struct device * dev)1821edb9ca6SSiva Reddy static int sxgbe_platform_suspend(struct device *dev)
1831edb9ca6SSiva Reddy {
1841edb9ca6SSiva Reddy 	struct net_device *ndev = dev_get_drvdata(dev);
1851edb9ca6SSiva Reddy 
1861edb9ca6SSiva Reddy 	return sxgbe_suspend(ndev);
1871edb9ca6SSiva Reddy }
1881edb9ca6SSiva Reddy 
sxgbe_platform_resume(struct device * dev)1891edb9ca6SSiva Reddy static int sxgbe_platform_resume(struct device *dev)
1901edb9ca6SSiva Reddy {
1911edb9ca6SSiva Reddy 	struct net_device *ndev = dev_get_drvdata(dev);
1921edb9ca6SSiva Reddy 
1931edb9ca6SSiva Reddy 	return sxgbe_resume(ndev);
1941edb9ca6SSiva Reddy }
19540b92cadSByungho An 
sxgbe_platform_freeze(struct device * dev)1961edb9ca6SSiva Reddy static int sxgbe_platform_freeze(struct device *dev)
1971edb9ca6SSiva Reddy {
1981edb9ca6SSiva Reddy 	struct net_device *ndev = dev_get_drvdata(dev);
1991edb9ca6SSiva Reddy 
2001edb9ca6SSiva Reddy 	return sxgbe_freeze(ndev);
2011edb9ca6SSiva Reddy }
20240b92cadSByungho An 
sxgbe_platform_restore(struct device * dev)2031edb9ca6SSiva Reddy static int sxgbe_platform_restore(struct device *dev)
2041edb9ca6SSiva Reddy {
2051edb9ca6SSiva Reddy 	struct net_device *ndev = dev_get_drvdata(dev);
2061edb9ca6SSiva Reddy 
2071edb9ca6SSiva Reddy 	return sxgbe_restore(ndev);
2081edb9ca6SSiva Reddy }
2091edb9ca6SSiva Reddy 
2101edb9ca6SSiva Reddy static const struct dev_pm_ops sxgbe_platform_pm_ops = {
2111edb9ca6SSiva Reddy 	.suspend	= sxgbe_platform_suspend,
2121edb9ca6SSiva Reddy 	.resume		= sxgbe_platform_resume,
2131edb9ca6SSiva Reddy 	.freeze		= sxgbe_platform_freeze,
2141edb9ca6SSiva Reddy 	.thaw		= sxgbe_platform_restore,
2151edb9ca6SSiva Reddy 	.restore	= sxgbe_platform_restore,
2161edb9ca6SSiva Reddy };
2171edb9ca6SSiva Reddy #else
2181edb9ca6SSiva Reddy static const struct dev_pm_ops sxgbe_platform_pm_ops;
2191edb9ca6SSiva Reddy #endif /* CONFIG_PM */
2201edb9ca6SSiva Reddy 
2211edb9ca6SSiva Reddy static const struct of_device_id sxgbe_dt_ids[] = {
2221edb9ca6SSiva Reddy 	{ .compatible = "samsung,sxgbe-v2.0a"},
2231edb9ca6SSiva Reddy 	{ /* sentinel */ }
2241edb9ca6SSiva Reddy };
2251edb9ca6SSiva Reddy MODULE_DEVICE_TABLE(of, sxgbe_dt_ids);
22640b92cadSByungho An 
2271edb9ca6SSiva Reddy static struct platform_driver sxgbe_platform_driver = {
2281edb9ca6SSiva Reddy 	.probe	= sxgbe_platform_probe,
2291edb9ca6SSiva Reddy 	.remove	= sxgbe_platform_remove,
2301edb9ca6SSiva Reddy 	.driver	= {
2311edb9ca6SSiva Reddy 		.name		= SXGBE_RESOURCE_NAME,
232*7f319fe4SKrzysztof Kozlowski 		.pm		= &sxgbe_platform_pm_ops,
2331edb9ca6SSiva Reddy 		.of_match_table	= sxgbe_dt_ids,
2341edb9ca6SSiva Reddy 	},
2351edb9ca6SSiva Reddy };
2361edb9ca6SSiva Reddy 
sxgbe_register_platform(void)2371edb9ca6SSiva Reddy int sxgbe_register_platform(void)
2381edb9ca6SSiva Reddy {
2391edb9ca6SSiva Reddy 	int err;
2401edb9ca6SSiva Reddy 
2411edb9ca6SSiva Reddy 	err = platform_driver_register(&sxgbe_platform_driver);
2421edb9ca6SSiva Reddy 	if (err)
2431edb9ca6SSiva Reddy 		pr_err("failed to register the platform driver\n");
2441edb9ca6SSiva Reddy 
2451edb9ca6SSiva Reddy 	return err;
2461edb9ca6SSiva Reddy }
2471edb9ca6SSiva Reddy 
sxgbe_unregister_platform(void)2481edb9ca6SSiva Reddy void sxgbe_unregister_platform(void)
2491edb9ca6SSiva Reddy {
2501edb9ca6SSiva Reddy 	platform_driver_unregister(&sxgbe_platform_driver);
251 }
252