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

Merge branch 'mvpp2-Armada-7k-8k-PP2-ACPI-support'

Marcin Wojtas says:

====================
Armada 7k/8k PP2 ACPI support

I quickly resend the series, thanks to Antoine Tenart's remark,
who spotted !CONFIG_ACPI compilation issue after introducing
the new fwnode_irq_get() routine. Please see the details in the changelog
below and the 3/7 commit log.

mvpp2 driver can work with the ACPI representation, as exposed
on a public branch:
https://github.com/MarvellEmbeddedProcessors/edk2-open-platform/commits/marvell-armada-wip
It was compiled together with the most recent Tianocore EDK2 revision.
Please refer to the firmware build instruction on MacchiatoBin board:
http://wiki.macchiatobin.net/tiki-index.php?page=Build+from+source+-+UEFI+EDK+II

ACPI representation of PP2 controllers (withouth PHY support) can
be viewed in the github:
* MacchiatoBin:
https://github.com/MarvellEmbeddedProcessors/edk2-open-platform/blob/71ae395da1661374b0f07d1602afb1eee56e9794/Platforms/Marvell/Armada/AcpiTables/Armada80x0McBin/Dsdt.asl#L201

* Armada 7040 DB:
https://github.com/MarvellEmbeddedProcessors/edk2-open-platform/blob/71ae395da1661374b0f07d1602afb1eee56e9794/Platforms/Marvell/Armada/AcpiTables/Armada70x0/Dsdt.asl#L131

I will appreciate any comments or remarks.

Best regards,
Marcin

Changelog:
v3 -> v4:
* 3/7
    - add new macro (ACPI_HANDLE_FWNODE) and fix
      compilation with !CONFIG_ACPI
    - extend commit log and mention usability of fwnode_irq_get
      for the child nodes as well

v2 -> v3:
* 1/7, 2/7
    - Add Rafael's Acked-by's
* 3/7, 4/7
    - New patches
* 6/7, 7/7
    - Update driver with new helper routines usage
    - Improve commit log.

v1 -> v2:
* Remove MDIO patches
* Use PP2 ports only with link interrupts
* Release second region resources in mvpp2 driver (code moved from
  mvmdio), as explained in details in 5/5 commit message.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents e0b4ed01 a75edc7c
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
#include <linux/of.h> #include <linux/of.h>
#include <linux/of_address.h> #include <linux/of_address.h>
#include <linux/of_graph.h> #include <linux/of_graph.h>
#include <linux/of_irq.h>
#include <linux/property.h> #include <linux/property.h>
#include <linux/etherdevice.h> #include <linux/etherdevice.h>
#include <linux/phy.h> #include <linux/phy.h>
...@@ -996,6 +997,32 @@ fwnode_get_next_child_node(const struct fwnode_handle *fwnode, ...@@ -996,6 +997,32 @@ fwnode_get_next_child_node(const struct fwnode_handle *fwnode,
} }
EXPORT_SYMBOL_GPL(fwnode_get_next_child_node); EXPORT_SYMBOL_GPL(fwnode_get_next_child_node);
/**
* fwnode_get_next_available_child_node - Return the next
* available child node handle for a node
* @fwnode: Firmware node to find the next child node for.
* @child: Handle to one of the node's child nodes or a %NULL handle.
*/
struct fwnode_handle *
fwnode_get_next_available_child_node(const struct fwnode_handle *fwnode,
struct fwnode_handle *child)
{
struct fwnode_handle *next_child = child;
if (!fwnode)
return NULL;
do {
next_child = fwnode_get_next_child_node(fwnode, next_child);
if (!next_child || fwnode_device_is_available(next_child))
break;
} while (next_child);
return next_child;
}
EXPORT_SYMBOL_GPL(fwnode_get_next_available_child_node);
/** /**
* device_get_next_child_node - Return the next child node handle for a device * device_get_next_child_node - Return the next child node handle for a device
* @dev: Device to find the next child node for. * @dev: Device to find the next child node for.
...@@ -1126,21 +1153,21 @@ enum dev_dma_attr device_get_dma_attr(struct device *dev) ...@@ -1126,21 +1153,21 @@ enum dev_dma_attr device_get_dma_attr(struct device *dev)
EXPORT_SYMBOL_GPL(device_get_dma_attr); EXPORT_SYMBOL_GPL(device_get_dma_attr);
/** /**
* device_get_phy_mode - Get phy mode for given device * fwnode_get_phy_mode - Get phy mode for given firmware node
* @dev: Pointer to the given device * @fwnode: Pointer to the given node
* *
* The function gets phy interface string from property 'phy-mode' or * 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 * 'phy-connection-type', and return its index in phy_modes table, or errno in
* error case. * error case.
*/ */
int device_get_phy_mode(struct device *dev) int fwnode_get_phy_mode(struct fwnode_handle *fwnode)
{ {
const char *pm; const char *pm;
int err, i; int err, i;
err = device_property_read_string(dev, "phy-mode", &pm); err = fwnode_property_read_string(fwnode, "phy-mode", &pm);
if (err < 0) if (err < 0)
err = device_property_read_string(dev, err = fwnode_property_read_string(fwnode,
"phy-connection-type", &pm); "phy-connection-type", &pm);
if (err < 0) if (err < 0)
return err; return err;
...@@ -1151,13 +1178,27 @@ int device_get_phy_mode(struct device *dev) ...@@ -1151,13 +1178,27 @@ int device_get_phy_mode(struct device *dev)
return -ENODEV; return -ENODEV;
} }
EXPORT_SYMBOL_GPL(fwnode_get_phy_mode);
/**
* device_get_phy_mode - Get phy mode for given device
* @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)
{
return fwnode_get_phy_mode(dev_fwnode(dev));
}
EXPORT_SYMBOL_GPL(device_get_phy_mode); EXPORT_SYMBOL_GPL(device_get_phy_mode);
static void *device_get_mac_addr(struct device *dev, static void *fwnode_get_mac_addr(struct fwnode_handle *fwnode,
const char *name, char *addr, const char *name, char *addr,
int alen) int alen)
{ {
int ret = device_property_read_u8_array(dev, name, addr, alen); int ret = fwnode_property_read_u8_array(fwnode, name, addr, alen);
if (ret == 0 && alen == ETH_ALEN && is_valid_ether_addr(addr)) if (ret == 0 && alen == ETH_ALEN && is_valid_ether_addr(addr))
return addr; return addr;
...@@ -1165,8 +1206,8 @@ static void *device_get_mac_addr(struct device *dev, ...@@ -1165,8 +1206,8 @@ static void *device_get_mac_addr(struct device *dev,
} }
/** /**
* device_get_mac_address - Get the MAC for a given device * fwnode_get_mac_address - Get the MAC from the firmware node
* @dev: Pointer to the device * @fwnode: Pointer to the firmware node
* @addr: Address of buffer to store the MAC in * @addr: Address of buffer to store the MAC in
* @alen: Length of the buffer pointed to by addr, should be ETH_ALEN * @alen: Length of the buffer pointed to by addr, should be ETH_ALEN
* *
...@@ -1187,22 +1228,59 @@ static void *device_get_mac_addr(struct device *dev, ...@@ -1187,22 +1228,59 @@ static void *device_get_mac_addr(struct device *dev,
* In this case, the real MAC is in 'local-mac-address', and 'mac-address' * In this case, the real MAC is in 'local-mac-address', and 'mac-address'
* exists but is all zeros. * exists but is all zeros.
*/ */
void *device_get_mac_address(struct device *dev, char *addr, int alen) void *fwnode_get_mac_address(struct fwnode_handle *fwnode, char *addr, int alen)
{ {
char *res; char *res;
res = device_get_mac_addr(dev, "mac-address", addr, alen); res = fwnode_get_mac_addr(fwnode, "mac-address", addr, alen);
if (res) if (res)
return res; return res;
res = device_get_mac_addr(dev, "local-mac-address", addr, alen); res = fwnode_get_mac_addr(fwnode, "local-mac-address", addr, alen);
if (res) if (res)
return res; return res;
return device_get_mac_addr(dev, "address", addr, alen); return fwnode_get_mac_addr(fwnode, "address", addr, alen);
}
EXPORT_SYMBOL(fwnode_get_mac_address);
/**
* device_get_mac_address - Get the MAC for a given device
* @dev: Pointer to the device
* @addr: Address of buffer to store the MAC in
* @alen: Length of the buffer pointed to by addr, should be ETH_ALEN
*/
void *device_get_mac_address(struct device *dev, char *addr, int alen)
{
return fwnode_get_mac_address(dev_fwnode(dev), addr, alen);
} }
EXPORT_SYMBOL(device_get_mac_address); EXPORT_SYMBOL(device_get_mac_address);
/**
* fwnode_irq_get - Get IRQ directly from a fwnode
* @fwnode: Pointer to the firmware node
* @index: Zero-based index of the IRQ
*
* Returns Linux IRQ number on success. Other values are determined
* accordingly to acpi_/of_ irq_get() operation.
*/
int fwnode_irq_get(struct fwnode_handle *fwnode, unsigned int index)
{
struct device_node *of_node = to_of_node(fwnode);
struct resource res;
int ret;
if (IS_ENABLED(CONFIG_OF) && of_node)
return of_irq_get(of_node, index);
ret = acpi_irq_get(ACPI_HANDLE_FWNODE(fwnode), index, &res);
if (ret)
return ret;
return res.start;
}
EXPORT_SYMBOL(fwnode_irq_get);
/** /**
* device_graph_get_next_endpoint - Get next endpoint firmware node * device_graph_get_next_endpoint - Get next endpoint firmware node
* @fwnode: Pointer to the parent firmware node * @fwnode: Pointer to the parent firmware node
......
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
* warranty of any kind, whether express or implied. * warranty of any kind, whether express or implied.
*/ */
#include <linux/acpi.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/netdevice.h> #include <linux/netdevice.h>
#include <linux/etherdevice.h> #include <linux/etherdevice.h>
...@@ -865,7 +866,7 @@ struct mvpp2 { ...@@ -865,7 +866,7 @@ struct mvpp2 {
/* List of pointers to port structures */ /* List of pointers to port structures */
int port_count; int port_count;
struct mvpp2_port **port_list; struct mvpp2_port *port_list[MVPP2_MAX_PORTS];
/* Aggregated TXQs */ /* Aggregated TXQs */
struct mvpp2_tx_queue *aggr_txqs; struct mvpp2_tx_queue *aggr_txqs;
...@@ -932,6 +933,9 @@ struct mvpp2_port { ...@@ -932,6 +933,9 @@ struct mvpp2_port {
struct mvpp2 *priv; struct mvpp2 *priv;
/* Firmware node associated to the port */
struct fwnode_handle *fwnode;
/* Per-port registers' base address */ /* Per-port registers' base address */
void __iomem *base; void __iomem *base;
void __iomem *stats_base; void __iomem *stats_base;
...@@ -7499,7 +7503,10 @@ static int mvpp2_multi_queue_vectors_init(struct mvpp2_port *port, ...@@ -7499,7 +7503,10 @@ static int mvpp2_multi_queue_vectors_init(struct mvpp2_port *port,
strncpy(irqname, "rx-shared", sizeof(irqname)); strncpy(irqname, "rx-shared", sizeof(irqname));
} }
if (port_node)
v->irq = of_irq_get_byname(port_node, irqname); v->irq = of_irq_get_byname(port_node, irqname);
else
v->irq = fwnode_irq_get(port->fwnode, i);
if (v->irq <= 0) { if (v->irq <= 0) {
ret = -EINVAL; ret = -EINVAL;
goto err; goto err;
...@@ -7711,17 +7718,16 @@ static bool mvpp2_port_has_tx_irqs(struct mvpp2 *priv, ...@@ -7711,17 +7718,16 @@ static bool mvpp2_port_has_tx_irqs(struct mvpp2 *priv,
} }
static void mvpp2_port_copy_mac_addr(struct net_device *dev, struct mvpp2 *priv, static void mvpp2_port_copy_mac_addr(struct net_device *dev, struct mvpp2 *priv,
struct device_node *port_node, struct fwnode_handle *fwnode,
char **mac_from) char **mac_from)
{ {
struct mvpp2_port *port = netdev_priv(dev); struct mvpp2_port *port = netdev_priv(dev);
char hw_mac_addr[ETH_ALEN] = {0}; char hw_mac_addr[ETH_ALEN] = {0};
const char *dt_mac_addr; char fw_mac_addr[ETH_ALEN];
dt_mac_addr = of_get_mac_address(port_node); if (fwnode_get_mac_address(fwnode, fw_mac_addr, ETH_ALEN)) {
if (dt_mac_addr && is_valid_ether_addr(dt_mac_addr)) { *mac_from = "firmware node";
*mac_from = "device tree"; ether_addr_copy(dev->dev_addr, fw_mac_addr);
ether_addr_copy(dev->dev_addr, dt_mac_addr);
return; return;
} }
...@@ -7740,13 +7746,14 @@ static void mvpp2_port_copy_mac_addr(struct net_device *dev, struct mvpp2 *priv, ...@@ -7740,13 +7746,14 @@ static void mvpp2_port_copy_mac_addr(struct net_device *dev, struct mvpp2 *priv,
/* Ports initialization */ /* Ports initialization */
static int mvpp2_port_probe(struct platform_device *pdev, static int mvpp2_port_probe(struct platform_device *pdev,
struct device_node *port_node, struct fwnode_handle *port_fwnode,
struct mvpp2 *priv, int index) struct mvpp2 *priv)
{ {
struct device_node *phy_node; struct device_node *phy_node;
struct phy *comphy; struct phy *comphy = NULL;
struct mvpp2_port *port; struct mvpp2_port *port;
struct mvpp2_port_pcpu *port_pcpu; struct mvpp2_port_pcpu *port_pcpu;
struct device_node *port_node = to_of_node(port_fwnode);
struct net_device *dev; struct net_device *dev;
struct resource *res; struct resource *res;
char *mac_from = ""; char *mac_from = "";
...@@ -7757,7 +7764,12 @@ static int mvpp2_port_probe(struct platform_device *pdev, ...@@ -7757,7 +7764,12 @@ static int mvpp2_port_probe(struct platform_device *pdev,
int phy_mode; int phy_mode;
int err, i, cpu; int err, i, cpu;
if (port_node) {
has_tx_irqs = mvpp2_port_has_tx_irqs(priv, port_node); has_tx_irqs = mvpp2_port_has_tx_irqs(priv, port_node);
} else {
has_tx_irqs = true;
queue_mode = MVPP2_QDIST_MULTI_MODE;
}
if (!has_tx_irqs) if (!has_tx_irqs)
queue_mode = MVPP2_QDIST_SINGLE_MODE; queue_mode = MVPP2_QDIST_SINGLE_MODE;
...@@ -7772,14 +7784,19 @@ static int mvpp2_port_probe(struct platform_device *pdev, ...@@ -7772,14 +7784,19 @@ static int mvpp2_port_probe(struct platform_device *pdev,
if (!dev) if (!dev)
return -ENOMEM; return -ENOMEM;
if (port_node)
phy_node = of_parse_phandle(port_node, "phy", 0); phy_node = of_parse_phandle(port_node, "phy", 0);
phy_mode = of_get_phy_mode(port_node); else
phy_node = NULL;
phy_mode = fwnode_get_phy_mode(port_fwnode);
if (phy_mode < 0) { if (phy_mode < 0) {
dev_err(&pdev->dev, "incorrect phy mode\n"); dev_err(&pdev->dev, "incorrect phy mode\n");
err = phy_mode; err = phy_mode;
goto err_free_netdev; goto err_free_netdev;
} }
if (port_node) {
comphy = devm_of_phy_get(&pdev->dev, port_node, NULL); comphy = devm_of_phy_get(&pdev->dev, port_node, NULL);
if (IS_ERR(comphy)) { if (IS_ERR(comphy)) {
if (PTR_ERR(comphy) == -EPROBE_DEFER) { if (PTR_ERR(comphy) == -EPROBE_DEFER) {
...@@ -7788,8 +7805,9 @@ static int mvpp2_port_probe(struct platform_device *pdev, ...@@ -7788,8 +7805,9 @@ static int mvpp2_port_probe(struct platform_device *pdev,
} }
comphy = NULL; comphy = NULL;
} }
}
if (of_property_read_u32(port_node, "port-id", &id)) { if (fwnode_property_read_u32(port_fwnode, "port-id", &id)) {
err = -EINVAL; err = -EINVAL;
dev_err(&pdev->dev, "missing port-id value\n"); dev_err(&pdev->dev, "missing port-id value\n");
goto err_free_netdev; goto err_free_netdev;
...@@ -7802,6 +7820,7 @@ static int mvpp2_port_probe(struct platform_device *pdev, ...@@ -7802,6 +7820,7 @@ static int mvpp2_port_probe(struct platform_device *pdev,
port = netdev_priv(dev); port = netdev_priv(dev);
port->dev = dev; port->dev = dev;
port->fwnode = port_fwnode;
port->ntxqs = ntxqs; port->ntxqs = ntxqs;
port->nrxqs = nrxqs; port->nrxqs = nrxqs;
port->priv = priv; port->priv = priv;
...@@ -7811,7 +7830,10 @@ static int mvpp2_port_probe(struct platform_device *pdev, ...@@ -7811,7 +7830,10 @@ static int mvpp2_port_probe(struct platform_device *pdev,
if (err) if (err)
goto err_free_netdev; goto err_free_netdev;
if (port_node)
port->link_irq = of_irq_get_byname(port_node, "link"); port->link_irq = of_irq_get_byname(port_node, "link");
else
port->link_irq = fwnode_irq_get(port_fwnode, port->nqvecs + 1);
if (port->link_irq == -EPROBE_DEFER) { if (port->link_irq == -EPROBE_DEFER) {
err = -EPROBE_DEFER; err = -EPROBE_DEFER;
goto err_deinit_qvecs; goto err_deinit_qvecs;
...@@ -7820,7 +7842,7 @@ static int mvpp2_port_probe(struct platform_device *pdev, ...@@ -7820,7 +7842,7 @@ static int mvpp2_port_probe(struct platform_device *pdev,
/* the link irq is optional */ /* the link irq is optional */
port->link_irq = 0; port->link_irq = 0;
if (of_property_read_bool(port_node, "marvell,loopback")) if (fwnode_property_read_bool(port_fwnode, "marvell,loopback"))
port->flags |= MVPP2_F_LOOPBACK; port->flags |= MVPP2_F_LOOPBACK;
port->id = id; port->id = id;
...@@ -7845,7 +7867,7 @@ static int mvpp2_port_probe(struct platform_device *pdev, ...@@ -7845,7 +7867,7 @@ static int mvpp2_port_probe(struct platform_device *pdev,
MVPP21_MIB_COUNTERS_OFFSET + MVPP21_MIB_COUNTERS_OFFSET +
port->gop_id * MVPP21_MIB_COUNTERS_PORT_SZ; port->gop_id * MVPP21_MIB_COUNTERS_PORT_SZ;
} else { } else {
if (of_property_read_u32(port_node, "gop-port-id", if (fwnode_property_read_u32(port_fwnode, "gop-port-id",
&port->gop_id)) { &port->gop_id)) {
err = -EINVAL; err = -EINVAL;
dev_err(&pdev->dev, "missing gop-port-id value\n"); dev_err(&pdev->dev, "missing gop-port-id value\n");
...@@ -7876,7 +7898,7 @@ static int mvpp2_port_probe(struct platform_device *pdev, ...@@ -7876,7 +7898,7 @@ static int mvpp2_port_probe(struct platform_device *pdev,
mutex_init(&port->gather_stats_lock); mutex_init(&port->gather_stats_lock);
INIT_DELAYED_WORK(&port->stats_work, mvpp2_gather_hw_statistics); INIT_DELAYED_WORK(&port->stats_work, mvpp2_gather_hw_statistics);
mvpp2_port_copy_mac_addr(dev, priv, port_node, &mac_from); mvpp2_port_copy_mac_addr(dev, priv, port_fwnode, &mac_from);
port->tx_ring_size = MVPP2_MAX_TXD_DFLT; port->tx_ring_size = MVPP2_MAX_TXD_DFLT;
port->rx_ring_size = MVPP2_MAX_RXD_DFLT; port->rx_ring_size = MVPP2_MAX_RXD_DFLT;
...@@ -7934,7 +7956,8 @@ static int mvpp2_port_probe(struct platform_device *pdev, ...@@ -7934,7 +7956,8 @@ static int mvpp2_port_probe(struct platform_device *pdev,
} }
netdev_info(dev, "Using %s mac address %pM\n", mac_from, dev->dev_addr); netdev_info(dev, "Using %s mac address %pM\n", mac_from, dev->dev_addr);
priv->port_list[index] = port; priv->port_list[priv->port_count++] = port;
return 0; return 0;
err_free_port_pcpu: err_free_port_pcpu:
...@@ -8193,8 +8216,9 @@ static int mvpp2_init(struct platform_device *pdev, struct mvpp2 *priv) ...@@ -8193,8 +8216,9 @@ static int mvpp2_init(struct platform_device *pdev, struct mvpp2 *priv)
static int mvpp2_probe(struct platform_device *pdev) static int mvpp2_probe(struct platform_device *pdev)
{ {
struct device_node *dn = pdev->dev.of_node; const struct acpi_device_id *acpi_id;
struct device_node *port_node; struct fwnode_handle *fwnode = pdev->dev.fwnode;
struct fwnode_handle *port_fwnode;
struct mvpp2 *priv; struct mvpp2 *priv;
struct resource *res; struct resource *res;
void __iomem *base; void __iomem *base;
...@@ -8205,8 +8229,14 @@ static int mvpp2_probe(struct platform_device *pdev) ...@@ -8205,8 +8229,14 @@ static int mvpp2_probe(struct platform_device *pdev)
if (!priv) if (!priv)
return -ENOMEM; return -ENOMEM;
if (has_acpi_companion(&pdev->dev)) {
acpi_id = acpi_match_device(pdev->dev.driver->acpi_match_table,
&pdev->dev);
priv->hw_version = (unsigned long)acpi_id->driver_data;
} else {
priv->hw_version = priv->hw_version =
(unsigned long)of_device_get_match_data(&pdev->dev); (unsigned long)of_device_get_match_data(&pdev->dev);
}
res = platform_get_resource(pdev, IORESOURCE_MEM, 0); res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
base = devm_ioremap_resource(&pdev->dev, res); base = devm_ioremap_resource(&pdev->dev, res);
...@@ -8220,10 +8250,23 @@ static int mvpp2_probe(struct platform_device *pdev) ...@@ -8220,10 +8250,23 @@ static int mvpp2_probe(struct platform_device *pdev)
return PTR_ERR(priv->lms_base); return PTR_ERR(priv->lms_base);
} else { } else {
res = platform_get_resource(pdev, IORESOURCE_MEM, 1); res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
if (has_acpi_companion(&pdev->dev)) {
/* In case the MDIO memory region is declared in
* the ACPI, it can already appear as 'in-use'
* in the OS. Because it is overlapped by second
* region of the network controller, make
* sure it is released, before requesting it again.
* The care is taken by mvpp2 driver to avoid
* concurrent access to this memory region.
*/
release_resource(res);
}
priv->iface_base = devm_ioremap_resource(&pdev->dev, res); priv->iface_base = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(priv->iface_base)) if (IS_ERR(priv->iface_base))
return PTR_ERR(priv->iface_base); return PTR_ERR(priv->iface_base);
}
if (priv->hw_version == MVPP22 && dev_of_node(&pdev->dev)) {
priv->sysctrl_base = priv->sysctrl_base =
syscon_regmap_lookup_by_phandle(pdev->dev.of_node, syscon_regmap_lookup_by_phandle(pdev->dev.of_node,
"marvell,system-controller"); "marvell,system-controller");
...@@ -8249,6 +8292,7 @@ static int mvpp2_probe(struct platform_device *pdev) ...@@ -8249,6 +8292,7 @@ static int mvpp2_probe(struct platform_device *pdev)
else else
priv->max_port_rxqs = 32; priv->max_port_rxqs = 32;
if (dev_of_node(&pdev->dev)) {
priv->pp_clk = devm_clk_get(&pdev->dev, "pp_clk"); priv->pp_clk = devm_clk_get(&pdev->dev, "pp_clk");
if (IS_ERR(priv->pp_clk)) if (IS_ERR(priv->pp_clk))
return PTR_ERR(priv->pp_clk); return PTR_ERR(priv->pp_clk);
...@@ -8275,6 +8319,7 @@ static int mvpp2_probe(struct platform_device *pdev) ...@@ -8275,6 +8319,7 @@ static int mvpp2_probe(struct platform_device *pdev)
err = clk_prepare_enable(priv->mg_clk); err = clk_prepare_enable(priv->mg_clk);
if (err < 0) if (err < 0)
goto err_gop_clk; goto err_gop_clk;
}
priv->axi_clk = devm_clk_get(&pdev->dev, "axi_clk"); priv->axi_clk = devm_clk_get(&pdev->dev, "axi_clk");
if (IS_ERR(priv->axi_clk)) { if (IS_ERR(priv->axi_clk)) {
...@@ -8287,10 +8332,14 @@ static int mvpp2_probe(struct platform_device *pdev) ...@@ -8287,10 +8332,14 @@ static int mvpp2_probe(struct platform_device *pdev)
if (err < 0) if (err < 0)
goto err_gop_clk; goto err_gop_clk;
} }
}
/* Get system's tclk rate */ /* Get system's tclk rate */
priv->tclk = clk_get_rate(priv->pp_clk); priv->tclk = clk_get_rate(priv->pp_clk);
} else if (device_property_read_u32(&pdev->dev, "clock-frequency",
&priv->tclk)) {
dev_err(&pdev->dev, "missing clock-frequency value\n");
return -EINVAL;
}
if (priv->hw_version == MVPP22) { if (priv->hw_version == MVPP22) {
err = dma_set_mask(&pdev->dev, DMA_BIT_MASK(40)); err = dma_set_mask(&pdev->dev, DMA_BIT_MASK(40));
...@@ -8313,30 +8362,19 @@ static int mvpp2_probe(struct platform_device *pdev) ...@@ -8313,30 +8362,19 @@ static int mvpp2_probe(struct platform_device *pdev)
goto err_mg_clk; goto err_mg_clk;
} }
priv->port_count = of_get_available_child_count(dn); /* Initialize ports */
fwnode_for_each_available_child_node(fwnode, port_fwnode) {
err = mvpp2_port_probe(pdev, port_fwnode, priv);
if (err < 0)
goto err_port_probe;
}
if (priv->port_count == 0) { if (priv->port_count == 0) {
dev_err(&pdev->dev, "no ports enabled\n"); dev_err(&pdev->dev, "no ports enabled\n");
err = -ENODEV; err = -ENODEV;
goto err_mg_clk; goto err_mg_clk;
} }
priv->port_list = devm_kcalloc(&pdev->dev, priv->port_count,
sizeof(*priv->port_list),
GFP_KERNEL);
if (!priv->port_list) {
err = -ENOMEM;
goto err_mg_clk;
}
/* Initialize ports */
i = 0;
for_each_available_child_of_node(dn, port_node) {
err = mvpp2_port_probe(pdev, port_node, priv, i);
if (err < 0)
goto err_port_probe;
i++;
}
/* Statistics must be gathered regularly because some of them (like /* Statistics must be gathered regularly because some of them (like
* packets counters) are 32-bit registers and could overflow quite * packets counters) are 32-bit registers and could overflow quite
* quickly. For instance, a 10Gb link used at full bandwidth with the * quickly. For instance, a 10Gb link used at full bandwidth with the
...@@ -8357,7 +8395,7 @@ static int mvpp2_probe(struct platform_device *pdev) ...@@ -8357,7 +8395,7 @@ static int mvpp2_probe(struct platform_device *pdev)
err_port_probe: err_port_probe:
i = 0; i = 0;
for_each_available_child_of_node(dn, port_node) { fwnode_for_each_available_child_node(fwnode, port_fwnode) {
if (priv->port_list[i]) if (priv->port_list[i])
mvpp2_port_remove(priv->port_list[i]); mvpp2_port_remove(priv->port_list[i]);
i++; i++;
...@@ -8376,14 +8414,14 @@ static int mvpp2_probe(struct platform_device *pdev) ...@@ -8376,14 +8414,14 @@ static int mvpp2_probe(struct platform_device *pdev)
static int mvpp2_remove(struct platform_device *pdev) static int mvpp2_remove(struct platform_device *pdev)
{ {
struct mvpp2 *priv = platform_get_drvdata(pdev); struct mvpp2 *priv = platform_get_drvdata(pdev);
struct device_node *dn = pdev->dev.of_node; struct fwnode_handle *fwnode = pdev->dev.fwnode;
struct device_node *port_node; struct fwnode_handle *port_fwnode;
int i = 0; int i = 0;
flush_workqueue(priv->stats_queue); flush_workqueue(priv->stats_queue);
destroy_workqueue(priv->stats_queue); destroy_workqueue(priv->stats_queue);
for_each_available_child_of_node(dn, port_node) { fwnode_for_each_available_child_node(fwnode, port_fwnode) {
if (priv->port_list[i]) { if (priv->port_list[i]) {
mutex_destroy(&priv->port_list[i]->gather_stats_lock); mutex_destroy(&priv->port_list[i]->gather_stats_lock);
mvpp2_port_remove(priv->port_list[i]); mvpp2_port_remove(priv->port_list[i]);
...@@ -8406,6 +8444,9 @@ static int mvpp2_remove(struct platform_device *pdev) ...@@ -8406,6 +8444,9 @@ static int mvpp2_remove(struct platform_device *pdev)
aggr_txq->descs_dma); aggr_txq->descs_dma);
} }
if (is_acpi_node(port_fwnode))
return 0;
clk_disable_unprepare(priv->axi_clk); clk_disable_unprepare(priv->axi_clk);
clk_disable_unprepare(priv->mg_clk); clk_disable_unprepare(priv->mg_clk);
clk_disable_unprepare(priv->pp_clk); clk_disable_unprepare(priv->pp_clk);
...@@ -8427,12 +8468,19 @@ static const struct of_device_id mvpp2_match[] = { ...@@ -8427,12 +8468,19 @@ static const struct of_device_id mvpp2_match[] = {
}; };
MODULE_DEVICE_TABLE(of, mvpp2_match); MODULE_DEVICE_TABLE(of, mvpp2_match);
static const struct acpi_device_id mvpp2_acpi_match[] = {
{ "MRVL0110", MVPP22 },
{ },
};
MODULE_DEVICE_TABLE(acpi, mvpp2_acpi_match);
static struct platform_driver mvpp2_driver = { static struct platform_driver mvpp2_driver = {
.probe = mvpp2_probe, .probe = mvpp2_probe,
.remove = mvpp2_remove, .remove = mvpp2_remove,
.driver = { .driver = {
.name = MVPP2_DRIVER_NAME, .name = MVPP2_DRIVER_NAME,
.of_match_table = mvpp2_match, .of_match_table = mvpp2_match,
.acpi_match_table = ACPI_PTR(mvpp2_acpi_match),
}, },
}; };
......
...@@ -56,6 +56,8 @@ static inline acpi_handle acpi_device_handle(struct acpi_device *adev) ...@@ -56,6 +56,8 @@ static inline acpi_handle acpi_device_handle(struct acpi_device *adev)
#define ACPI_COMPANION_SET(dev, adev) set_primary_fwnode(dev, (adev) ? \ #define ACPI_COMPANION_SET(dev, adev) set_primary_fwnode(dev, (adev) ? \
acpi_fwnode_handle(adev) : NULL) acpi_fwnode_handle(adev) : NULL)
#define ACPI_HANDLE(dev) acpi_device_handle(ACPI_COMPANION(dev)) #define ACPI_HANDLE(dev) acpi_device_handle(ACPI_COMPANION(dev))
#define ACPI_HANDLE_FWNODE(fwnode) \
acpi_device_handle(to_acpi_device_node(fwnode))
static inline struct fwnode_handle *acpi_alloc_fwnode_static(void) static inline struct fwnode_handle *acpi_alloc_fwnode_static(void)
{ {
...@@ -626,6 +628,7 @@ int acpi_arch_timer_mem_init(struct arch_timer_mem *timer_mem, int *timer_count) ...@@ -626,6 +628,7 @@ int acpi_arch_timer_mem_init(struct arch_timer_mem *timer_mem, int *timer_count)
#define ACPI_COMPANION(dev) (NULL) #define ACPI_COMPANION(dev) (NULL)
#define ACPI_COMPANION_SET(dev, adev) do { } while (0) #define ACPI_COMPANION_SET(dev, adev) do { } while (0)
#define ACPI_HANDLE(dev) (NULL) #define ACPI_HANDLE(dev) (NULL)
#define ACPI_HANDLE_FWNODE(fwnode) (NULL)
#define ACPI_DEVICE_CLASS(_cls, _msk) .cls = (0), .cls_msk = (0), #define ACPI_DEVICE_CLASS(_cls, _msk) .cls = (0), .cls_msk = (0),
struct fwnode_handle; struct fwnode_handle;
......
...@@ -83,11 +83,17 @@ struct fwnode_handle *fwnode_get_next_parent( ...@@ -83,11 +83,17 @@ struct fwnode_handle *fwnode_get_next_parent(
struct fwnode_handle *fwnode); struct fwnode_handle *fwnode);
struct fwnode_handle *fwnode_get_next_child_node( struct fwnode_handle *fwnode_get_next_child_node(
const struct fwnode_handle *fwnode, struct fwnode_handle *child); const struct fwnode_handle *fwnode, struct fwnode_handle *child);
struct fwnode_handle *fwnode_get_next_available_child_node(
const struct fwnode_handle *fwnode, struct fwnode_handle *child);
#define fwnode_for_each_child_node(fwnode, child) \ #define fwnode_for_each_child_node(fwnode, child) \
for (child = fwnode_get_next_child_node(fwnode, NULL); child; \ for (child = fwnode_get_next_child_node(fwnode, NULL); child; \
child = fwnode_get_next_child_node(fwnode, child)) child = fwnode_get_next_child_node(fwnode, child))
#define fwnode_for_each_available_child_node(fwnode, child) \
for (child = fwnode_get_next_available_child_node(fwnode, NULL); child;\
child = fwnode_get_next_available_child_node(fwnode, child))
struct fwnode_handle *device_get_next_child_node( struct fwnode_handle *device_get_next_child_node(
struct device *dev, struct fwnode_handle *child); struct device *dev, struct fwnode_handle *child);
...@@ -103,6 +109,8 @@ struct fwnode_handle *device_get_named_child_node(struct device *dev, ...@@ -103,6 +109,8 @@ struct fwnode_handle *device_get_named_child_node(struct device *dev,
struct fwnode_handle *fwnode_handle_get(struct fwnode_handle *fwnode); struct fwnode_handle *fwnode_handle_get(struct fwnode_handle *fwnode);
void fwnode_handle_put(struct fwnode_handle *fwnode); void fwnode_handle_put(struct fwnode_handle *fwnode);
int fwnode_irq_get(struct fwnode_handle *fwnode, unsigned int index);
unsigned int device_get_child_node_count(struct device *dev); unsigned int device_get_child_node_count(struct device *dev);
static inline bool device_property_read_bool(struct device *dev, static inline bool device_property_read_bool(struct device *dev,
...@@ -279,6 +287,9 @@ int device_get_phy_mode(struct device *dev); ...@@ -279,6 +287,9 @@ int device_get_phy_mode(struct device *dev);
void *device_get_mac_address(struct device *dev, char *addr, int alen); void *device_get_mac_address(struct device *dev, char *addr, int alen);
int fwnode_get_phy_mode(struct fwnode_handle *fwnode);
void *fwnode_get_mac_address(struct fwnode_handle *fwnode,
char *addr, int alen);
struct fwnode_handle *fwnode_graph_get_next_endpoint( struct fwnode_handle *fwnode_graph_get_next_endpoint(
const struct fwnode_handle *fwnode, struct fwnode_handle *prev); const struct fwnode_handle *fwnode, struct fwnode_handle *prev);
struct fwnode_handle * struct fwnode_handle *
......
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