Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

net/smsc911x: add device tree probe support

It adds device tree probe support for smsc911x driver.

Signed-off-by: Shawn Guo <shawn.guo@linaro.org>
Cc: Grant Likely <grant.likely@secretlab.ca>
Cc: Steve Glendinning <steve.glendinning@smsc.com>
Cc: David S. Miller <davem@davemloft.net>
Reviewed-by: Grant Likely <grant.likely@secretlab.ca>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Shawn Guo and committed by
David S. Miller
79f88ee9 ebdcc94b

+112 -11
+38
Documentation/devicetree/bindings/net/smsc911x.txt
··· 1 + * Smart Mixed-Signal Connectivity (SMSC) LAN911x/912x Controller 2 + 3 + Required properties: 4 + - compatible : Should be "smsc,lan<model>", "smsc,lan9115" 5 + - reg : Address and length of the io space for SMSC LAN 6 + - interrupts : Should contain SMSC LAN interrupt line 7 + - interrupt-parent : Should be the phandle for the interrupt controller 8 + that services interrupts for this device 9 + - phy-mode : String, operation mode of the PHY interface. 10 + Supported values are: "mii", "gmii", "sgmii", "tbi", "rmii", 11 + "rgmii", "rgmii-id", "rgmii-rxid", "rgmii-txid", "rtbi", "smii". 12 + 13 + Optional properties: 14 + - reg-shift : Specify the quantity to shift the register offsets by 15 + - reg-io-width : Specify the size (in bytes) of the IO accesses that 16 + should be performed on the device. Valid value for SMSC LAN is 17 + 2 or 4. If it's omitted or invalid, the size would be 2. 18 + - smsc,irq-active-high : Indicates the IRQ polarity is active-high 19 + - smsc,irq-push-pull : Indicates the IRQ type is push-pull 20 + - smsc,force-internal-phy : Forces SMSC LAN controller to use 21 + internal PHY 22 + - smsc,force-external-phy : Forces SMSC LAN controller to use 23 + external PHY 24 + - smsc,save-mac-address : Indicates that mac address needs to be saved 25 + before resetting the controller 26 + - local-mac-address : 6 bytes, mac address 27 + 28 + Examples: 29 + 30 + lan9220@f4000000 { 31 + compatible = "smsc,lan9220", "smsc,lan9115"; 32 + reg = <0xf4000000 0x2000000>; 33 + phy-mode = "mii"; 34 + interrupt-parent = <&gpio1>; 35 + interrupts = <31>; 36 + reg-io-width = <4>; 37 + smsc,irq-push-pull; 38 + };
+74 -11
drivers/net/smsc911x.c
··· 53 53 #include <linux/phy.h> 54 54 #include <linux/smsc911x.h> 55 55 #include <linux/device.h> 56 + #include <linux/of.h> 57 + #include <linux/of_device.h> 58 + #include <linux/of_gpio.h> 59 + #include <linux/of_net.h> 56 60 #include "smsc911x.h" 57 61 58 62 #define SMSC_CHIPNAME "smsc911x" ··· 2099 2095 .tx_writefifo = smsc911x_tx_writefifo_shift, 2100 2096 }; 2101 2097 2098 + #ifdef CONFIG_OF 2099 + static int __devinit smsc911x_probe_config_dt( 2100 + struct smsc911x_platform_config *config, 2101 + struct device_node *np) 2102 + { 2103 + const char *mac; 2104 + u32 width = 0; 2105 + 2106 + if (!np) 2107 + return -ENODEV; 2108 + 2109 + config->phy_interface = of_get_phy_mode(np); 2110 + 2111 + mac = of_get_mac_address(np); 2112 + if (mac) 2113 + memcpy(config->mac, mac, ETH_ALEN); 2114 + 2115 + of_property_read_u32(np, "reg-shift", &config->shift); 2116 + 2117 + of_property_read_u32(np, "reg-io-width", &width); 2118 + if (width == 4) 2119 + config->flags |= SMSC911X_USE_32BIT; 2120 + 2121 + if (of_get_property(np, "smsc,irq-active-high", NULL)) 2122 + config->irq_polarity = SMSC911X_IRQ_POLARITY_ACTIVE_HIGH; 2123 + 2124 + if (of_get_property(np, "smsc,irq-push-pull", NULL)) 2125 + config->irq_type = SMSC911X_IRQ_TYPE_PUSH_PULL; 2126 + 2127 + if (of_get_property(np, "smsc,force-internal-phy", NULL)) 2128 + config->flags |= SMSC911X_FORCE_INTERNAL_PHY; 2129 + 2130 + if (of_get_property(np, "smsc,force-external-phy", NULL)) 2131 + config->flags |= SMSC911X_FORCE_EXTERNAL_PHY; 2132 + 2133 + if (of_get_property(np, "smsc,save-mac-address", NULL)) 2134 + config->flags |= SMSC911X_SAVE_MAC_ADDRESS; 2135 + 2136 + return 0; 2137 + } 2138 + #else 2139 + static inline int smsc911x_probe_config_dt( 2140 + struct smsc911x_platform_config *config, 2141 + struct device_node *np) 2142 + { 2143 + return -ENODEV; 2144 + } 2145 + #endif /* CONFIG_OF */ 2146 + 2102 2147 static int __devinit smsc911x_drv_probe(struct platform_device *pdev) 2103 2148 { 2149 + struct device_node *np = pdev->dev.of_node; 2104 2150 struct net_device *dev; 2105 2151 struct smsc911x_data *pdata; 2106 2152 struct smsc911x_platform_config *config = pdev->dev.platform_data; ··· 2160 2106 int retval; 2161 2107 2162 2108 pr_info("Driver version %s\n", SMSC_DRV_VERSION); 2163 - 2164 - /* platform data specifies irq & dynamic bus configuration */ 2165 - if (!pdev->dev.platform_data) { 2166 - pr_warn("platform_data not provided\n"); 2167 - retval = -ENODEV; 2168 - goto out_0; 2169 - } 2170 2109 2171 2110 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, 2172 2111 "smsc911x-memory"); ··· 2199 2152 irq_flags = irq_res->flags & IRQF_TRIGGER_MASK; 2200 2153 pdata->ioaddr = ioremap_nocache(res->start, res_size); 2201 2154 2202 - /* copy config parameters across to pdata */ 2203 - memcpy(&pdata->config, config, sizeof(pdata->config)); 2204 - 2205 2155 pdata->dev = dev; 2206 2156 pdata->msg_enable = ((1 << debug) - 1); 2207 2157 ··· 2208 2164 goto out_free_netdev_2; 2209 2165 } 2210 2166 2167 + retval = smsc911x_probe_config_dt(&pdata->config, np); 2168 + if (retval && config) { 2169 + /* copy config parameters across to pdata */ 2170 + memcpy(&pdata->config, config, sizeof(pdata->config)); 2171 + retval = 0; 2172 + } 2173 + 2174 + if (retval) { 2175 + SMSC_WARN(pdata, probe, "Error smsc911x config not found"); 2176 + goto out_unmap_io_3; 2177 + } 2178 + 2211 2179 /* assume standard, non-shifted, access to HW registers */ 2212 2180 pdata->ops = &standard_smsc911x_ops; 2213 2181 /* apply the right access if shifting is needed */ 2214 - if (config->shift) 2182 + if (pdata->config.shift) 2215 2183 pdata->ops = &shifted_smsc911x_ops; 2216 2184 2217 2185 retval = smsc911x_init(dev); ··· 2370 2314 #define SMSC911X_PM_OPS NULL 2371 2315 #endif 2372 2316 2317 + static const struct of_device_id smsc911x_dt_ids[] = { 2318 + { .compatible = "smsc,lan9115", }, 2319 + { /* sentinel */ } 2320 + }; 2321 + MODULE_DEVICE_TABLE(of, smsc911x_dt_ids); 2322 + 2373 2323 static struct platform_driver smsc911x_driver = { 2374 2324 .probe = smsc911x_drv_probe, 2375 2325 .remove = __devexit_p(smsc911x_drv_remove), ··· 2383 2321 .name = SMSC_CHIPNAME, 2384 2322 .owner = THIS_MODULE, 2385 2323 .pm = SMSC911X_PM_OPS, 2324 + .of_match_table = smsc911x_dt_ids, 2386 2325 }, 2387 2326 }; 2388 2327