stmmac: Add device-tree support
This patch adds support to configure the STMMAC ethernet driver via device-tree instead of platform_data. Currently, only the properties needed on SPEAr600 are provided. All other properties should be added once needed on other platforms. Signed-off-by: Stefan Roese <sr@denx.de> Cc: Giuseppe Cavallaro <peppe.cavallaro@st.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
		
							parent
							
								
									06d6c10876
								
							
						
					
					
						commit
						6a228452d1
					
				
							
								
								
									
										28
									
								
								Documentation/devicetree/bindings/net/stmmac.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								Documentation/devicetree/bindings/net/stmmac.txt
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,28 @@ | |||||||
|  | * STMicroelectronics 10/100/1000 Ethernet driver (GMAC) | ||||||
|  | 
 | ||||||
|  | Required properties: | ||||||
|  | - compatible: Should be "st,spear600-gmac" | ||||||
|  | - reg: Address and length of the register set for the device | ||||||
|  | - interrupt-parent: Should be the phandle for the interrupt controller | ||||||
|  |   that services interrupts for this device | ||||||
|  | - interrupts: Should contain the STMMAC interrupts | ||||||
|  | - interrupt-names: Should contain the interrupt names "macirq" | ||||||
|  |   "eth_wake_irq" if this interrupt is supported in the "interrupts" | ||||||
|  |   property | ||||||
|  | - phy-mode: String, operation mode of the PHY interface. | ||||||
|  |   Supported values are: "mii", "rmii", "gmii", "rgmii". | ||||||
|  | 
 | ||||||
|  | Optional properties: | ||||||
|  | - mac-address: 6 bytes, mac address | ||||||
|  | 
 | ||||||
|  | Examples: | ||||||
|  | 
 | ||||||
|  | 	gmac0: ethernet@e0800000 { | ||||||
|  | 		compatible = "st,spear600-gmac"; | ||||||
|  | 		reg = <0xe0800000 0x8000>; | ||||||
|  | 		interrupt-parent = <&vic1>; | ||||||
|  | 		interrupts = <24 23>; | ||||||
|  | 		interrupt-names = "macirq", "eth_wake_irq"; | ||||||
|  | 		mac-address = [000000000000]; /* Filled in by U-Boot */ | ||||||
|  | 		phy-mode = "gmii"; | ||||||
|  | 	}; | ||||||
| @ -24,8 +24,48 @@ | |||||||
| 
 | 
 | ||||||
| #include <linux/platform_device.h> | #include <linux/platform_device.h> | ||||||
| #include <linux/io.h> | #include <linux/io.h> | ||||||
|  | #include <linux/of.h> | ||||||
|  | #include <linux/of_net.h> | ||||||
| #include "stmmac.h" | #include "stmmac.h" | ||||||
| 
 | 
 | ||||||
|  | #ifdef CONFIG_OF | ||||||
|  | static int __devinit stmmac_probe_config_dt(struct platform_device *pdev, | ||||||
|  | 					    struct plat_stmmacenet_data *plat, | ||||||
|  | 					    const char **mac) | ||||||
|  | { | ||||||
|  | 	struct device_node *np = pdev->dev.of_node; | ||||||
|  | 
 | ||||||
|  | 	if (!np) | ||||||
|  | 		return -ENODEV; | ||||||
|  | 
 | ||||||
|  | 	*mac = of_get_mac_address(np); | ||||||
|  | 	plat->interface = of_get_phy_mode(np); | ||||||
|  | 	plat->mdio_bus_data = devm_kzalloc(&pdev->dev, | ||||||
|  | 					   sizeof(struct stmmac_mdio_bus_data), | ||||||
|  | 					   GFP_KERNEL); | ||||||
|  | 
 | ||||||
|  | 	/*
 | ||||||
|  | 	 * Currently only the properties needed on SPEAr600 | ||||||
|  | 	 * are provided. All other properties should be added | ||||||
|  | 	 * once needed on other platforms. | ||||||
|  | 	 */ | ||||||
|  | 	if (of_device_is_compatible(np, "st,spear600-gmac")) { | ||||||
|  | 		plat->pbl = 8; | ||||||
|  | 		plat->has_gmac = 1; | ||||||
|  | 		plat->pmt = 1; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  | #else | ||||||
|  | static int __devinit stmmac_probe_config_dt(struct platform_device *pdev, | ||||||
|  | 					    struct plat_stmmacenet_data *plat, | ||||||
|  | 					    const char **mac) | ||||||
|  | { | ||||||
|  | 	return -ENOSYS; | ||||||
|  | } | ||||||
|  | #endif /* CONFIG_OF */ | ||||||
|  | 
 | ||||||
| /**
 | /**
 | ||||||
|  * stmmac_pltfr_probe |  * stmmac_pltfr_probe | ||||||
|  * @pdev: platform device pointer |  * @pdev: platform device pointer | ||||||
| @ -39,7 +79,8 @@ static int stmmac_pltfr_probe(struct platform_device *pdev) | |||||||
| 	struct resource *res; | 	struct resource *res; | ||||||
| 	void __iomem *addr = NULL; | 	void __iomem *addr = NULL; | ||||||
| 	struct stmmac_priv *priv = NULL; | 	struct stmmac_priv *priv = NULL; | ||||||
| 	struct plat_stmmacenet_data *plat_dat; | 	struct plat_stmmacenet_data *plat_dat = NULL; | ||||||
|  | 	const char *mac = NULL; | ||||||
| 
 | 
 | ||||||
| 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||||||
| 	if (!res) | 	if (!res) | ||||||
| @ -58,7 +99,25 @@ static int stmmac_pltfr_probe(struct platform_device *pdev) | |||||||
| 		ret = -ENOMEM; | 		ret = -ENOMEM; | ||||||
| 		goto out_release_region; | 		goto out_release_region; | ||||||
| 	} | 	} | ||||||
| 	plat_dat = pdev->dev.platform_data; | 
 | ||||||
|  | 	if (pdev->dev.of_node) { | ||||||
|  | 		plat_dat = devm_kzalloc(&pdev->dev, | ||||||
|  | 					sizeof(struct plat_stmmacenet_data), | ||||||
|  | 					GFP_KERNEL); | ||||||
|  | 		if (!plat_dat) { | ||||||
|  | 			pr_err("%s: ERROR: no memory", __func__); | ||||||
|  | 			ret = -ENOMEM; | ||||||
|  | 			goto out_unmap; | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		ret = stmmac_probe_config_dt(pdev, plat_dat, &mac); | ||||||
|  | 		if (ret) { | ||||||
|  | 			pr_err("%s: main dt probe failed", __func__); | ||||||
|  | 			goto out_unmap; | ||||||
|  | 		} | ||||||
|  | 	} else { | ||||||
|  | 		plat_dat = pdev->dev.platform_data; | ||||||
|  | 	} | ||||||
| 
 | 
 | ||||||
| 	/* Custom initialisation (if needed)*/ | 	/* Custom initialisation (if needed)*/ | ||||||
| 	if (plat_dat->init) { | 	if (plat_dat->init) { | ||||||
| @ -73,6 +132,10 @@ static int stmmac_pltfr_probe(struct platform_device *pdev) | |||||||
| 		goto out_unmap; | 		goto out_unmap; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	/* Get MAC address if available (DT) */ | ||||||
|  | 	if (mac) | ||||||
|  | 		memcpy(priv->dev->dev_addr, mac, ETH_ALEN); | ||||||
|  | 
 | ||||||
| 	/* Get the MAC information */ | 	/* Get the MAC information */ | ||||||
| 	priv->dev->irq = platform_get_irq_byname(pdev, "macirq"); | 	priv->dev->irq = platform_get_irq_byname(pdev, "macirq"); | ||||||
| 	if (priv->dev->irq == -ENXIO) { | 	if (priv->dev->irq == -ENXIO) { | ||||||
| @ -178,6 +241,12 @@ static const struct dev_pm_ops stmmac_pltfr_pm_ops = { | |||||||
| static const struct dev_pm_ops stmmac_pltfr_pm_ops; | static const struct dev_pm_ops stmmac_pltfr_pm_ops; | ||||||
| #endif /* CONFIG_PM */ | #endif /* CONFIG_PM */ | ||||||
| 
 | 
 | ||||||
|  | static const struct of_device_id stmmac_dt_ids[] = { | ||||||
|  | 	{ .compatible = "st,spear600-gmac", }, | ||||||
|  | 	{ /* sentinel */ } | ||||||
|  | }; | ||||||
|  | MODULE_DEVICE_TABLE(of, stmmac_dt_ids); | ||||||
|  | 
 | ||||||
| static struct platform_driver stmmac_driver = { | static struct platform_driver stmmac_driver = { | ||||||
| 	.probe = stmmac_pltfr_probe, | 	.probe = stmmac_pltfr_probe, | ||||||
| 	.remove = stmmac_pltfr_remove, | 	.remove = stmmac_pltfr_remove, | ||||||
| @ -185,6 +254,7 @@ static struct platform_driver stmmac_driver = { | |||||||
| 		   .name = STMMAC_RESOURCE_NAME, | 		   .name = STMMAC_RESOURCE_NAME, | ||||||
| 		   .owner = THIS_MODULE, | 		   .owner = THIS_MODULE, | ||||||
| 		   .pm = &stmmac_pltfr_pm_ops, | 		   .pm = &stmmac_pltfr_pm_ops, | ||||||
|  | 		   .of_match_table = of_match_ptr(stmmac_dt_ids), | ||||||
| 		   }, | 		   }, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user