|
@@ -10,6 +10,7 @@
|
|
|
* warranty of any kind, whether express or implied.
|
|
|
*/
|
|
|
|
|
|
+#include <linux/acpi.h>
|
|
|
#include <linux/kernel.h>
|
|
|
#include <linux/netdevice.h>
|
|
|
#include <linux/etherdevice.h>
|
|
@@ -7502,7 +7503,10 @@ static int mvpp2_multi_queue_vectors_init(struct mvpp2_port *port,
|
|
|
strncpy(irqname, "rx-shared", sizeof(irqname));
|
|
|
}
|
|
|
|
|
|
- v->irq = of_irq_get_byname(port_node, irqname);
|
|
|
+ if (port_node)
|
|
|
+ v->irq = of_irq_get_byname(port_node, irqname);
|
|
|
+ else
|
|
|
+ v->irq = fwnode_irq_get(port->fwnode, i);
|
|
|
if (v->irq <= 0) {
|
|
|
ret = -EINVAL;
|
|
|
goto err;
|
|
@@ -7746,7 +7750,7 @@ static int mvpp2_port_probe(struct platform_device *pdev,
|
|
|
struct mvpp2 *priv)
|
|
|
{
|
|
|
struct device_node *phy_node;
|
|
|
- struct phy *comphy;
|
|
|
+ struct phy *comphy = NULL;
|
|
|
struct mvpp2_port *port;
|
|
|
struct mvpp2_port_pcpu *port_pcpu;
|
|
|
struct device_node *port_node = to_of_node(port_fwnode);
|
|
@@ -7760,7 +7764,12 @@ static int mvpp2_port_probe(struct platform_device *pdev,
|
|
|
int phy_mode;
|
|
|
int err, i, cpu;
|
|
|
|
|
|
- has_tx_irqs = mvpp2_port_has_tx_irqs(priv, port_node);
|
|
|
+ if (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)
|
|
|
queue_mode = MVPP2_QDIST_SINGLE_MODE;
|
|
@@ -7775,7 +7784,11 @@ static int mvpp2_port_probe(struct platform_device *pdev,
|
|
|
if (!dev)
|
|
|
return -ENOMEM;
|
|
|
|
|
|
- phy_node = of_parse_phandle(port_node, "phy", 0);
|
|
|
+ if (port_node)
|
|
|
+ phy_node = of_parse_phandle(port_node, "phy", 0);
|
|
|
+ else
|
|
|
+ phy_node = NULL;
|
|
|
+
|
|
|
phy_mode = fwnode_get_phy_mode(port_fwnode);
|
|
|
if (phy_mode < 0) {
|
|
|
dev_err(&pdev->dev, "incorrect phy mode\n");
|
|
@@ -7783,13 +7796,15 @@ static int mvpp2_port_probe(struct platform_device *pdev,
|
|
|
goto err_free_netdev;
|
|
|
}
|
|
|
|
|
|
- comphy = devm_of_phy_get(&pdev->dev, port_node, NULL);
|
|
|
- if (IS_ERR(comphy)) {
|
|
|
- if (PTR_ERR(comphy) == -EPROBE_DEFER) {
|
|
|
- err = -EPROBE_DEFER;
|
|
|
- goto err_free_netdev;
|
|
|
+ if (port_node) {
|
|
|
+ comphy = devm_of_phy_get(&pdev->dev, port_node, NULL);
|
|
|
+ if (IS_ERR(comphy)) {
|
|
|
+ if (PTR_ERR(comphy) == -EPROBE_DEFER) {
|
|
|
+ err = -EPROBE_DEFER;
|
|
|
+ goto err_free_netdev;
|
|
|
+ }
|
|
|
+ comphy = NULL;
|
|
|
}
|
|
|
- comphy = NULL;
|
|
|
}
|
|
|
|
|
|
if (fwnode_property_read_u32(port_fwnode, "port-id", &id)) {
|
|
@@ -7805,6 +7820,7 @@ static int mvpp2_port_probe(struct platform_device *pdev,
|
|
|
|
|
|
port = netdev_priv(dev);
|
|
|
port->dev = dev;
|
|
|
+ port->fwnode = port_fwnode;
|
|
|
port->ntxqs = ntxqs;
|
|
|
port->nrxqs = nrxqs;
|
|
|
port->priv = priv;
|
|
@@ -7814,7 +7830,10 @@ static int mvpp2_port_probe(struct platform_device *pdev,
|
|
|
if (err)
|
|
|
goto err_free_netdev;
|
|
|
|
|
|
- port->link_irq = of_irq_get_byname(port_node, "link");
|
|
|
+ if (port_node)
|
|
|
+ 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) {
|
|
|
err = -EPROBE_DEFER;
|
|
|
goto err_deinit_qvecs;
|
|
@@ -8197,6 +8216,7 @@ static int mvpp2_init(struct platform_device *pdev, struct mvpp2 *priv)
|
|
|
|
|
|
static int mvpp2_probe(struct platform_device *pdev)
|
|
|
{
|
|
|
+ const struct acpi_device_id *acpi_id;
|
|
|
struct fwnode_handle *fwnode = pdev->dev.fwnode;
|
|
|
struct fwnode_handle *port_fwnode;
|
|
|
struct mvpp2 *priv;
|
|
@@ -8209,8 +8229,14 @@ static int mvpp2_probe(struct platform_device *pdev)
|
|
|
if (!priv)
|
|
|
return -ENOMEM;
|
|
|
|
|
|
- priv->hw_version =
|
|
|
- (unsigned long)of_device_get_match_data(&pdev->dev);
|
|
|
+ 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 =
|
|
|
+ (unsigned long)of_device_get_match_data(&pdev->dev);
|
|
|
+ }
|
|
|
|
|
|
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
|
|
base = devm_ioremap_resource(&pdev->dev, res);
|
|
@@ -8224,10 +8250,23 @@ static int mvpp2_probe(struct platform_device *pdev)
|
|
|
return PTR_ERR(priv->lms_base);
|
|
|
} else {
|
|
|
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);
|
|
|
if (IS_ERR(priv->iface_base))
|
|
|
return PTR_ERR(priv->iface_base);
|
|
|
+ }
|
|
|
|
|
|
+ if (priv->hw_version == MVPP22 && dev_of_node(&pdev->dev)) {
|
|
|
priv->sysctrl_base =
|
|
|
syscon_regmap_lookup_by_phandle(pdev->dev.of_node,
|
|
|
"marvell,system-controller");
|
|
@@ -8253,32 +8292,34 @@ static int mvpp2_probe(struct platform_device *pdev)
|
|
|
else
|
|
|
priv->max_port_rxqs = 32;
|
|
|
|
|
|
- priv->pp_clk = devm_clk_get(&pdev->dev, "pp_clk");
|
|
|
- if (IS_ERR(priv->pp_clk))
|
|
|
- return PTR_ERR(priv->pp_clk);
|
|
|
- err = clk_prepare_enable(priv->pp_clk);
|
|
|
- if (err < 0)
|
|
|
- return err;
|
|
|
-
|
|
|
- priv->gop_clk = devm_clk_get(&pdev->dev, "gop_clk");
|
|
|
- if (IS_ERR(priv->gop_clk)) {
|
|
|
- err = PTR_ERR(priv->gop_clk);
|
|
|
- goto err_pp_clk;
|
|
|
- }
|
|
|
- err = clk_prepare_enable(priv->gop_clk);
|
|
|
- if (err < 0)
|
|
|
- goto err_pp_clk;
|
|
|
+ if (dev_of_node(&pdev->dev)) {
|
|
|
+ priv->pp_clk = devm_clk_get(&pdev->dev, "pp_clk");
|
|
|
+ if (IS_ERR(priv->pp_clk))
|
|
|
+ return PTR_ERR(priv->pp_clk);
|
|
|
+ err = clk_prepare_enable(priv->pp_clk);
|
|
|
+ if (err < 0)
|
|
|
+ return err;
|
|
|
|
|
|
- if (priv->hw_version == MVPP22) {
|
|
|
- priv->mg_clk = devm_clk_get(&pdev->dev, "mg_clk");
|
|
|
- if (IS_ERR(priv->mg_clk)) {
|
|
|
- err = PTR_ERR(priv->mg_clk);
|
|
|
- goto err_gop_clk;
|
|
|
+ priv->gop_clk = devm_clk_get(&pdev->dev, "gop_clk");
|
|
|
+ if (IS_ERR(priv->gop_clk)) {
|
|
|
+ err = PTR_ERR(priv->gop_clk);
|
|
|
+ goto err_pp_clk;
|
|
|
}
|
|
|
-
|
|
|
- err = clk_prepare_enable(priv->mg_clk);
|
|
|
+ err = clk_prepare_enable(priv->gop_clk);
|
|
|
if (err < 0)
|
|
|
- goto err_gop_clk;
|
|
|
+ goto err_pp_clk;
|
|
|
+
|
|
|
+ if (priv->hw_version == MVPP22) {
|
|
|
+ priv->mg_clk = devm_clk_get(&pdev->dev, "mg_clk");
|
|
|
+ if (IS_ERR(priv->mg_clk)) {
|
|
|
+ err = PTR_ERR(priv->mg_clk);
|
|
|
+ goto err_gop_clk;
|
|
|
+ }
|
|
|
+
|
|
|
+ err = clk_prepare_enable(priv->mg_clk);
|
|
|
+ if (err < 0)
|
|
|
+ goto err_gop_clk;
|
|
|
+ }
|
|
|
|
|
|
priv->axi_clk = devm_clk_get(&pdev->dev, "axi_clk");
|
|
|
if (IS_ERR(priv->axi_clk)) {
|
|
@@ -8291,10 +8332,14 @@ static int mvpp2_probe(struct platform_device *pdev)
|
|
|
if (err < 0)
|
|
|
goto err_gop_clk;
|
|
|
}
|
|
|
- }
|
|
|
|
|
|
- /* Get system's tclk rate */
|
|
|
- priv->tclk = clk_get_rate(priv->pp_clk);
|
|
|
+ /* Get system's tclk rate */
|
|
|
+ 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) {
|
|
|
err = dma_set_mask(&pdev->dev, DMA_BIT_MASK(40));
|
|
@@ -8399,6 +8444,9 @@ static int mvpp2_remove(struct platform_device *pdev)
|
|
|
aggr_txq->descs_dma);
|
|
|
}
|
|
|
|
|
|
+ if (is_acpi_node(port_fwnode))
|
|
|
+ return 0;
|
|
|
+
|
|
|
clk_disable_unprepare(priv->axi_clk);
|
|
|
clk_disable_unprepare(priv->mg_clk);
|
|
|
clk_disable_unprepare(priv->pp_clk);
|
|
@@ -8420,12 +8468,19 @@ static const struct of_device_id 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 = {
|
|
|
.probe = mvpp2_probe,
|
|
|
.remove = mvpp2_remove,
|
|
|
.driver = {
|
|
|
.name = MVPP2_DRIVER_NAME,
|
|
|
.of_match_table = mvpp2_match,
|
|
|
+ .acpi_match_table = ACPI_PTR(mvpp2_acpi_match),
|
|
|
},
|
|
|
};
|
|
|
|