sh_eth: add device tree support

Add support of the device tree probing for the Renesas SH-Mobile SoCs
documenting the device tree binding as necessary.

This work is loosely based on the original patch by Nobuhiro Iwamatsu
<nobuhiro.iwamatsu.yj@renesas.com>.

Signed-off-by: Sergei Shtylyov <sergei.shtylyov@cogentembedded.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
Sergei Shtylyov
2014-02-18 03:12:43 +03:00
committed by David S. Miller
parent e8f08ee0ad
commit b356e978e9
2 changed files with 121 additions and 3 deletions

View File

@@ -1,8 +1,8 @@
/* SuperH Ethernet device driver
*
* Copyright (C) 2006-2012 Nobuhiro Iwamatsu
* Copyright (C) 2008-2013 Renesas Solutions Corp.
* Copyright (C) 2013 Cogent Embedded, Inc.
* Copyright (C) 2008-2014 Renesas Solutions Corp.
* Copyright (C) 2013-2014 Cogent Embedded, Inc.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
@@ -27,6 +27,10 @@
#include <linux/platform_device.h>
#include <linux/mdio-bitbang.h>
#include <linux/netdevice.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/of_irq.h>
#include <linux/of_net.h>
#include <linux/phy.h>
#include <linux/cache.h>
#include <linux/io.h>
@@ -2710,6 +2714,54 @@ static const struct net_device_ops sh_eth_netdev_ops_tsu = {
.ndo_change_mtu = eth_change_mtu,
};
#ifdef CONFIG_OF
static struct sh_eth_plat_data *sh_eth_parse_dt(struct device *dev)
{
struct device_node *np = dev->of_node;
struct sh_eth_plat_data *pdata;
struct device_node *phy;
const char *mac_addr;
pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
if (!pdata)
return NULL;
pdata->phy_interface = of_get_phy_mode(np);
phy = of_parse_phandle(np, "phy-handle", 0);
if (of_property_read_u32(phy, "reg", &pdata->phy))
return NULL;
pdata->phy_irq = irq_of_parse_and_map(phy, 0);
mac_addr = of_get_mac_address(np);
if (mac_addr)
memcpy(pdata->mac_addr, mac_addr, ETH_ALEN);
pdata->no_ether_link =
of_property_read_bool(np, "renesas,no-ether-link");
pdata->ether_link_active_low =
of_property_read_bool(np, "renesas,ether-link-active-low");
return pdata;
}
static const struct of_device_id sh_eth_match_table[] = {
{ .compatible = "renesas,gether-r8a7740", .data = &r8a7740_data },
{ .compatible = "renesas,ether-r8a7778", .data = &r8a777x_data },
{ .compatible = "renesas,ether-r8a7779", .data = &r8a777x_data },
{ .compatible = "renesas,ether-r8a7790", .data = &r8a779x_data },
{ .compatible = "renesas,ether-r8a7791", .data = &r8a779x_data },
{ .compatible = "renesas,ether-r7s72100", .data = &r7s72100_data },
{ }
};
MODULE_DEVICE_TABLE(of, sh_eth_match_table);
#else
static inline struct sh_eth_plat_data *sh_eth_parse_dt(struct device *dev)
{
return NULL;
}
#endif
static int sh_eth_drv_probe(struct platform_device *pdev)
{
int ret, devno = 0;
@@ -2763,6 +2815,8 @@ static int sh_eth_drv_probe(struct platform_device *pdev)
pm_runtime_enable(&pdev->dev);
pm_runtime_resume(&pdev->dev);
if (pdev->dev.of_node)
pd = sh_eth_parse_dt(&pdev->dev);
if (!pd) {
dev_err(&pdev->dev, "no platform data\n");
ret = -EINVAL;
@@ -2778,7 +2832,15 @@ static int sh_eth_drv_probe(struct platform_device *pdev)
mdp->ether_link_active_low = pd->ether_link_active_low;
/* set cpu data */
mdp->cd = (struct sh_eth_cpu_data *)id->driver_data;
if (id) {
mdp->cd = (struct sh_eth_cpu_data *)id->driver_data;
} else {
const struct of_device_id *match;
match = of_match_device(of_match_ptr(sh_eth_match_table),
&pdev->dev);
mdp->cd = (struct sh_eth_cpu_data *)match->data;
}
mdp->reg_offset = sh_eth_get_register_offset(mdp->cd->register_type);
sh_eth_set_default_cpu_data(mdp->cd);
@@ -2920,6 +2982,7 @@ static struct platform_driver sh_eth_driver = {
.driver = {
.name = CARDNAME,
.pm = SH_ETH_PM_OPS,
.of_match_table = of_match_ptr(sh_eth_match_table),
},
};