diff options
author | Shawn Guo <shawn.guo@linaro.org> | 2011-07-30 04:26:00 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2011-08-01 21:01:33 -0400 |
commit | 79f88ee9836d482891ba41b1a553e2baacf31b02 (patch) | |
tree | 216f52c4d2e6e11c90cf05d71a79bb1fea39117b /drivers/net/smsc911x.c | |
parent | ebdcc94b4b03212a1f715c39526c9b9578bba0b0 (diff) |
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>
Diffstat (limited to 'drivers/net/smsc911x.c')
-rw-r--r-- | drivers/net/smsc911x.c | 85 |
1 files changed, 74 insertions, 11 deletions
diff --git a/drivers/net/smsc911x.c b/drivers/net/smsc911x.c index b9016a30cdc5..75c08a55582c 100644 --- a/drivers/net/smsc911x.c +++ b/drivers/net/smsc911x.c | |||
@@ -53,6 +53,10 @@ | |||
53 | #include <linux/phy.h> | 53 | #include <linux/phy.h> |
54 | #include <linux/smsc911x.h> | 54 | #include <linux/smsc911x.h> |
55 | #include <linux/device.h> | 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 | #include "smsc911x.h" | 60 | #include "smsc911x.h" |
57 | 61 | ||
58 | #define SMSC_CHIPNAME "smsc911x" | 62 | #define SMSC_CHIPNAME "smsc911x" |
@@ -2095,8 +2099,58 @@ static const struct smsc911x_ops shifted_smsc911x_ops = { | |||
2095 | .tx_writefifo = smsc911x_tx_writefifo_shift, | 2099 | .tx_writefifo = smsc911x_tx_writefifo_shift, |
2096 | }; | 2100 | }; |
2097 | 2101 | ||
2102 | #ifdef CONFIG_OF | ||
2103 | static int __devinit smsc911x_probe_config_dt( | ||
2104 | struct smsc911x_platform_config *config, | ||
2105 | struct device_node *np) | ||
2106 | { | ||
2107 | const char *mac; | ||
2108 | u32 width = 0; | ||
2109 | |||
2110 | if (!np) | ||
2111 | return -ENODEV; | ||
2112 | |||
2113 | config->phy_interface = of_get_phy_mode(np); | ||
2114 | |||
2115 | mac = of_get_mac_address(np); | ||
2116 | if (mac) | ||
2117 | memcpy(config->mac, mac, ETH_ALEN); | ||
2118 | |||
2119 | of_property_read_u32(np, "reg-shift", &config->shift); | ||
2120 | |||
2121 | of_property_read_u32(np, "reg-io-width", &width); | ||
2122 | if (width == 4) | ||
2123 | config->flags |= SMSC911X_USE_32BIT; | ||
2124 | |||
2125 | if (of_get_property(np, "smsc,irq-active-high", NULL)) | ||
2126 | config->irq_polarity = SMSC911X_IRQ_POLARITY_ACTIVE_HIGH; | ||
2127 | |||
2128 | if (of_get_property(np, "smsc,irq-push-pull", NULL)) | ||
2129 | config->irq_type = SMSC911X_IRQ_TYPE_PUSH_PULL; | ||
2130 | |||
2131 | if (of_get_property(np, "smsc,force-internal-phy", NULL)) | ||
2132 | config->flags |= SMSC911X_FORCE_INTERNAL_PHY; | ||
2133 | |||
2134 | if (of_get_property(np, "smsc,force-external-phy", NULL)) | ||
2135 | config->flags |= SMSC911X_FORCE_EXTERNAL_PHY; | ||
2136 | |||
2137 | if (of_get_property(np, "smsc,save-mac-address", NULL)) | ||
2138 | config->flags |= SMSC911X_SAVE_MAC_ADDRESS; | ||
2139 | |||
2140 | return 0; | ||
2141 | } | ||
2142 | #else | ||
2143 | static inline int smsc911x_probe_config_dt( | ||
2144 | struct smsc911x_platform_config *config, | ||
2145 | struct device_node *np) | ||
2146 | { | ||
2147 | return -ENODEV; | ||
2148 | } | ||
2149 | #endif /* CONFIG_OF */ | ||
2150 | |||
2098 | static int __devinit smsc911x_drv_probe(struct platform_device *pdev) | 2151 | static int __devinit smsc911x_drv_probe(struct platform_device *pdev) |
2099 | { | 2152 | { |
2153 | struct device_node *np = pdev->dev.of_node; | ||
2100 | struct net_device *dev; | 2154 | struct net_device *dev; |
2101 | struct smsc911x_data *pdata; | 2155 | struct smsc911x_data *pdata; |
2102 | struct smsc911x_platform_config *config = pdev->dev.platform_data; | 2156 | struct smsc911x_platform_config *config = pdev->dev.platform_data; |
@@ -2107,13 +2161,6 @@ static int __devinit smsc911x_drv_probe(struct platform_device *pdev) | |||
2107 | 2161 | ||
2108 | pr_info("Driver version %s\n", SMSC_DRV_VERSION); | 2162 | pr_info("Driver version %s\n", SMSC_DRV_VERSION); |
2109 | 2163 | ||
2110 | /* platform data specifies irq & dynamic bus configuration */ | ||
2111 | if (!pdev->dev.platform_data) { | ||
2112 | pr_warn("platform_data not provided\n"); | ||
2113 | retval = -ENODEV; | ||
2114 | goto out_0; | ||
2115 | } | ||
2116 | |||
2117 | res = platform_get_resource_byname(pdev, IORESOURCE_MEM, | 2164 | res = platform_get_resource_byname(pdev, IORESOURCE_MEM, |
2118 | "smsc911x-memory"); | 2165 | "smsc911x-memory"); |
2119 | if (!res) | 2166 | if (!res) |
@@ -2152,9 +2199,6 @@ static int __devinit smsc911x_drv_probe(struct platform_device *pdev) | |||
2152 | irq_flags = irq_res->flags & IRQF_TRIGGER_MASK; | 2199 | irq_flags = irq_res->flags & IRQF_TRIGGER_MASK; |
2153 | pdata->ioaddr = ioremap_nocache(res->start, res_size); | 2200 | pdata->ioaddr = ioremap_nocache(res->start, res_size); |
2154 | 2201 | ||
2155 | /* copy config parameters across to pdata */ | ||
2156 | memcpy(&pdata->config, config, sizeof(pdata->config)); | ||
2157 | |||
2158 | pdata->dev = dev; | 2202 | pdata->dev = dev; |
2159 | pdata->msg_enable = ((1 << debug) - 1); | 2203 | pdata->msg_enable = ((1 << debug) - 1); |
2160 | 2204 | ||
@@ -2164,10 +2208,22 @@ static int __devinit smsc911x_drv_probe(struct platform_device *pdev) | |||
2164 | goto out_free_netdev_2; | 2208 | goto out_free_netdev_2; |
2165 | } | 2209 | } |
2166 | 2210 | ||
2211 | retval = smsc911x_probe_config_dt(&pdata->config, np); | ||
2212 | if (retval && config) { | ||
2213 | /* copy config parameters across to pdata */ | ||
2214 | memcpy(&pdata->config, config, sizeof(pdata->config)); | ||
2215 | retval = 0; | ||
2216 | } | ||
2217 | |||
2218 | if (retval) { | ||
2219 | SMSC_WARN(pdata, probe, "Error smsc911x config not found"); | ||
2220 | goto out_unmap_io_3; | ||
2221 | } | ||
2222 | |||
2167 | /* assume standard, non-shifted, access to HW registers */ | 2223 | /* assume standard, non-shifted, access to HW registers */ |
2168 | pdata->ops = &standard_smsc911x_ops; | 2224 | pdata->ops = &standard_smsc911x_ops; |
2169 | /* apply the right access if shifting is needed */ | 2225 | /* apply the right access if shifting is needed */ |
2170 | if (config->shift) | 2226 | if (pdata->config.shift) |
2171 | pdata->ops = &shifted_smsc911x_ops; | 2227 | pdata->ops = &shifted_smsc911x_ops; |
2172 | 2228 | ||
2173 | retval = smsc911x_init(dev); | 2229 | retval = smsc911x_init(dev); |
@@ -2314,6 +2370,12 @@ static const struct dev_pm_ops smsc911x_pm_ops = { | |||
2314 | #define SMSC911X_PM_OPS NULL | 2370 | #define SMSC911X_PM_OPS NULL |
2315 | #endif | 2371 | #endif |
2316 | 2372 | ||
2373 | static const struct of_device_id smsc911x_dt_ids[] = { | ||
2374 | { .compatible = "smsc,lan9115", }, | ||
2375 | { /* sentinel */ } | ||
2376 | }; | ||
2377 | MODULE_DEVICE_TABLE(of, smsc911x_dt_ids); | ||
2378 | |||
2317 | static struct platform_driver smsc911x_driver = { | 2379 | static struct platform_driver smsc911x_driver = { |
2318 | .probe = smsc911x_drv_probe, | 2380 | .probe = smsc911x_drv_probe, |
2319 | .remove = __devexit_p(smsc911x_drv_remove), | 2381 | .remove = __devexit_p(smsc911x_drv_remove), |
@@ -2321,6 +2383,7 @@ static struct platform_driver smsc911x_driver = { | |||
2321 | .name = SMSC_CHIPNAME, | 2383 | .name = SMSC_CHIPNAME, |
2322 | .owner = THIS_MODULE, | 2384 | .owner = THIS_MODULE, |
2323 | .pm = SMSC911X_PM_OPS, | 2385 | .pm = SMSC911X_PM_OPS, |
2386 | .of_match_table = smsc911x_dt_ids, | ||
2324 | }, | 2387 | }, |
2325 | }; | 2388 | }; |
2326 | 2389 | ||