Skip to content

Commit

Permalink
Merge branch 'smsc911x-acpi'
Browse files Browse the repository at this point in the history
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: David S. Miller <davem@davemloft.net>
  • Loading branch information
David S. Miller committed Aug 13, 2015
2 parents 5bbbcc0 + 0b50dc4 commit c28446c
Showing 3 changed files with 99 additions and 26 deletions.
73 changes: 73 additions & 0 deletions drivers/base/property.c
Original file line number Diff line number Diff line change
@@ -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);
48 changes: 22 additions & 26 deletions drivers/net/ethernet/smsc/smsc911x.c
Original file line number Diff line number Diff line change
@@ -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,13 +2643,20 @@ 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,
.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),
},
};

4 changes: 4 additions & 0 deletions include/linux/property.h
Original file line number Diff line number Diff line change
@@ -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_ */

0 comments on commit c28446c

Please sign in to comment.