Commit c28446c2 authored by David S. Miller's avatar David S. Miller

Merge branch 'smsc911x-acpi'

Jeremy Linton says:

====================
Enable smsc911x for use with ACPI

This set of patches enables the front Ethernet port on the
ARM Juno development platform when used with an ACPI enabled kernel.

These patches covert the of_property* calls in the driver to the
DT/ACPI agnostic device_property* calls, and add the arm hardware
id to the acpi_match_table.

To support the above changes I copied a couple routines from
of_net into the properties.c file, and modified them to
be ACPI/DT agnostic. I'm not 100% sure this is the correct location
for these functions. But I think they are required to avoid having
a dozen different implementations scattered across assorted Ethernet
adapters that are being enabled to use ACPI properties.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 5bbbcc00 0b50dc4f
......@@ -16,6 +16,8 @@
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/property.h>
#include <linux/etherdevice.h>
#include <linux/phy.h>
/**
* device_add_property_set - Add a collection of properties to a device object.
......@@ -533,3 +535,74 @@ bool device_dma_is_coherent(struct device *dev)
return coherent;
}
EXPORT_SYMBOL_GPL(device_dma_is_coherent);
/**
* device_get_phy_mode - Get phy mode for given device_node
* @dev: Pointer to the given device
*
* The function gets phy interface string from property 'phy-mode' or
* 'phy-connection-type', and return its index in phy_modes table, or errno in
* error case.
*/
int device_get_phy_mode(struct device *dev)
{
const char *pm;
int err, i;
err = device_property_read_string(dev, "phy-mode", &pm);
if (err < 0)
err = device_property_read_string(dev,
"phy-connection-type", &pm);
if (err < 0)
return err;
for (i = 0; i < PHY_INTERFACE_MODE_MAX; i++)
if (!strcasecmp(pm, phy_modes(i)))
return i;
return -ENODEV;
}
EXPORT_SYMBOL_GPL(device_get_phy_mode);
static void *device_get_mac_addr(struct device *dev,
const char *name, char *addr,
int alen)
{
int ret = device_property_read_u8_array(dev, name, addr, alen);
if (ret == 0 && is_valid_ether_addr(addr))
return addr;
return NULL;
}
/**
* Search the device tree for the best MAC address to use. 'mac-address' is
* checked first, because that is supposed to contain to "most recent" MAC
* address. If that isn't set, then 'local-mac-address' is checked next,
* because that is the default address. If that isn't set, then the obsolete
* 'address' is checked, just in case we're using an old device tree.
*
* Note that the 'address' property is supposed to contain a virtual address of
* the register set, but some DTS files have redefined that property to be the
* MAC address.
*
* All-zero MAC addresses are rejected, because those could be properties that
* exist in the device tree, but were not set by U-Boot. For example, the
* DTS could define 'mac-address' and 'local-mac-address', with zero MAC
* addresses. Some older U-Boots only initialized 'local-mac-address'. In
* this case, the real MAC is in 'local-mac-address', and 'mac-address' exists
* but is all zeros.
*/
void *device_get_mac_address(struct device *dev, char *addr, int alen)
{
addr = device_get_mac_addr(dev, "mac-address", addr, alen);
if (addr)
return addr;
addr = device_get_mac_addr(dev, "local-mac-address", addr, alen);
if (addr)
return addr;
return device_get_mac_addr(dev, "address", addr, alen);
}
EXPORT_SYMBOL(device_get_mac_address);
......@@ -59,7 +59,9 @@
#include <linux/of_device.h>
#include <linux/of_gpio.h>
#include <linux/of_net.h>
#include <linux/acpi.h>
#include <linux/pm_runtime.h>
#include <linux/property.h>
#include "smsc911x.h"
......@@ -2362,59 +2364,46 @@ static const struct smsc911x_ops shifted_smsc911x_ops = {
.tx_writefifo = smsc911x_tx_writefifo_shift,
};
#ifdef CONFIG_OF
static int smsc911x_probe_config_dt(struct smsc911x_platform_config *config,
struct device_node *np)
static int smsc911x_probe_config(struct smsc911x_platform_config *config,
struct device *dev)
{
const char *mac;
u32 width = 0;
if (!np)
if (!dev)
return -ENODEV;
config->phy_interface = of_get_phy_mode(np);
config->phy_interface = device_get_phy_mode(dev);
mac = of_get_mac_address(np);
if (mac)
memcpy(config->mac, mac, ETH_ALEN);
device_get_mac_address(dev, config->mac, ETH_ALEN);
of_property_read_u32(np, "reg-shift", &config->shift);
device_property_read_u32(dev, "reg-shift", &config->shift);
of_property_read_u32(np, "reg-io-width", &width);
device_property_read_u32(dev, "reg-io-width", &width);
if (width == 4)
config->flags |= SMSC911X_USE_32BIT;
else
config->flags |= SMSC911X_USE_16BIT;
if (of_get_property(np, "smsc,irq-active-high", NULL))
if (device_property_present(dev, "smsc,irq-active-high"))
config->irq_polarity = SMSC911X_IRQ_POLARITY_ACTIVE_HIGH;
if (of_get_property(np, "smsc,irq-push-pull", NULL))
if (device_property_present(dev, "smsc,irq-push-pull"))
config->irq_type = SMSC911X_IRQ_TYPE_PUSH_PULL;
if (of_get_property(np, "smsc,force-internal-phy", NULL))
if (device_property_present(dev, "smsc,force-internal-phy"))
config->flags |= SMSC911X_FORCE_INTERNAL_PHY;
if (of_get_property(np, "smsc,force-external-phy", NULL))
if (device_property_present(dev, "smsc,force-external-phy"))
config->flags |= SMSC911X_FORCE_EXTERNAL_PHY;
if (of_get_property(np, "smsc,save-mac-address", NULL))
if (device_property_present(dev, "smsc,save-mac-address"))
config->flags |= SMSC911X_SAVE_MAC_ADDRESS;
return 0;
}
#else
static inline int smsc911x_probe_config_dt(
struct smsc911x_platform_config *config,
struct device_node *np)
{
return -ENODEV;
}
#endif /* CONFIG_OF */
static int smsc911x_drv_probe(struct platform_device *pdev)
{
struct device_node *np = pdev->dev.of_node;
struct net_device *dev;
struct smsc911x_data *pdata;
struct smsc911x_platform_config *config = dev_get_platdata(&pdev->dev);
......@@ -2478,7 +2467,7 @@ static int smsc911x_drv_probe(struct platform_device *pdev)
goto out_disable_resources;
}
retval = smsc911x_probe_config_dt(&pdata->config, np);
retval = smsc911x_probe_config(&pdata->config, &pdev->dev);
if (retval && config) {
/* copy config parameters across to pdata */
memcpy(&pdata->config, config, sizeof(pdata->config));
......@@ -2654,6 +2643,12 @@ static const struct of_device_id smsc911x_dt_ids[] = {
MODULE_DEVICE_TABLE(of, smsc911x_dt_ids);
#endif
static const struct acpi_device_id smsc911x_acpi_match[] = {
{ "ARMH9118", 0 },
{ }
};
MODULE_DEVICE_TABLE(acpi, smsc911x_acpi_match);
static struct platform_driver smsc911x_driver = {
.probe = smsc911x_drv_probe,
.remove = smsc911x_drv_remove,
......@@ -2661,6 +2656,7 @@ static struct platform_driver smsc911x_driver = {
.name = SMSC_CHIPNAME,
.pm = SMSC911X_PM_OPS,
.of_match_table = of_match_ptr(smsc911x_dt_ids),
.acpi_match_table = ACPI_PTR(smsc911x_acpi_match),
},
};
......
......@@ -166,4 +166,8 @@ void device_add_property_set(struct device *dev, struct property_set *pset);
bool device_dma_is_coherent(struct device *dev);
int device_get_phy_mode(struct device *dev);
void *device_get_mac_address(struct device *dev, char *addr, int alen);
#endif /* _LINUX_PROPERTY_H_ */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment