Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 52ba992e authored by Sebastian Hesselbarth's avatar Sebastian Hesselbarth Committed by Jason Cooper
Browse files

PCI: mvebu: add support for reset on GPIO



This patch adds a check for DT passed reset-gpios property and deasserts/
asserts reset pin on probe/remove with configurable delay. Corresponding
binding documentation is also updated.

Signed-off-by: default avatarSebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
Signed-off-by: default avatarJason Cooper <jason@lakedaemon.net>
parent e5615c30
Loading
Loading
Loading
Loading
+6 −0
Original line number Original line Diff line number Diff line
@@ -76,6 +76,8 @@ and the following optional properties:
- marvell,pcie-lane: the physical PCIe lane number, for ports having
- marvell,pcie-lane: the physical PCIe lane number, for ports having
  multiple lanes. If this property is not found, we assume that the
  multiple lanes. If this property is not found, we assume that the
  value is 0.
  value is 0.
- reset-gpios: optional gpio to PERST#
- reset-delay-us: delay in us to wait after reset de-assertion


Example:
Example:


@@ -138,6 +140,10 @@ pcie-controller {
		interrupt-map = <0 0 0 0 &mpic 58>;
		interrupt-map = <0 0 0 0 &mpic 58>;
		marvell,pcie-port = <0>;
		marvell,pcie-port = <0>;
		marvell,pcie-lane = <0>;
		marvell,pcie-lane = <0>;
		/* low-active PERST# reset on GPIO 25 */
		reset-gpios = <&gpio0 25 1>;
		/* wait 20ms for device settle after reset deassertion */
		reset-delay-us = <20000>;
		clocks = <&gateclk 5>;
		clocks = <&gateclk 5>;
		status = "disabled";
		status = "disabled";
	};
	};
+32 −1
Original line number Original line Diff line number Diff line
@@ -9,14 +9,17 @@
#include <linux/kernel.h>
#include <linux/kernel.h>
#include <linux/pci.h>
#include <linux/pci.h>
#include <linux/clk.h>
#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/gpio.h>
#include <linux/module.h>
#include <linux/module.h>
#include <linux/mbus.h>
#include <linux/mbus.h>
#include <linux/msi.h>
#include <linux/msi.h>
#include <linux/slab.h>
#include <linux/slab.h>
#include <linux/platform_device.h>
#include <linux/platform_device.h>
#include <linux/of_address.h>
#include <linux/of_address.h>
#include <linux/of_pci.h>
#include <linux/of_irq.h>
#include <linux/of_irq.h>
#include <linux/of_gpio.h>
#include <linux/of_pci.h>
#include <linux/of_platform.h>
#include <linux/of_platform.h>


/*
/*
@@ -126,6 +129,9 @@ struct mvebu_pcie_port {
	unsigned int io_target;
	unsigned int io_target;
	unsigned int io_attr;
	unsigned int io_attr;
	struct clk *clk;
	struct clk *clk;
	int reset_gpio;
	int reset_active_low;
	char *reset_name;
	struct mvebu_sw_pci_bridge bridge;
	struct mvebu_sw_pci_bridge bridge;
	struct device_node *dn;
	struct device_node *dn;
	struct mvebu_pcie *pcie;
	struct mvebu_pcie *pcie;
@@ -857,6 +863,7 @@ static int mvebu_pcie_probe(struct platform_device *pdev)
	i = 0;
	i = 0;
	for_each_child_of_node(pdev->dev.of_node, child) {
	for_each_child_of_node(pdev->dev.of_node, child) {
		struct mvebu_pcie_port *port = &pcie->ports[i];
		struct mvebu_pcie_port *port = &pcie->ports[i];
		enum of_gpio_flags flags;


		if (!of_device_is_available(child))
		if (!of_device_is_available(child))
			continue;
			continue;
@@ -897,6 +904,30 @@ static int mvebu_pcie_probe(struct platform_device *pdev)
			continue;
			continue;
		}
		}


		port->reset_gpio = of_get_named_gpio_flags(child,
						   "reset-gpios", 0, &flags);
		if (gpio_is_valid(port->reset_gpio)) {
			u32 reset_udelay = 20000;

			port->reset_active_low = flags & OF_GPIO_ACTIVE_LOW;
			port->reset_name = kasprintf(GFP_KERNEL,
				     "pcie%d.%d-reset", port->port, port->lane);
			of_property_read_u32(child, "reset-delay-us",
					     &reset_udelay);

			ret = devm_gpio_request_one(&pdev->dev,
			    port->reset_gpio, GPIOF_DIR_OUT, port->reset_name);
			if (ret) {
				if (ret == -EPROBE_DEFER)
					return ret;
				continue;
			}

			gpio_set_value(port->reset_gpio,
				       (port->reset_active_low) ? 1 : 0);
			msleep(reset_udelay/1000);
		}

		port->clk = of_clk_get_by_name(child, NULL);
		port->clk = of_clk_get_by_name(child, NULL);
		if (IS_ERR(port->clk)) {
		if (IS_ERR(port->clk)) {
			dev_err(&pdev->dev, "PCIe%d.%d: cannot get clock\n",
			dev_err(&pdev->dev, "PCIe%d.%d: cannot get clock\n",