Thread (10 messages) 10 messages, 3 authors, 2020-01-02

Re: [PATCH 2/2] reset: Add Broadcom STB RESCAL reset controller

From: Florian Fainelli <f.fainelli@gmail.com>
Date: 2019-12-11 18:12:19
Also in: linux-devicetree, lkml


On 12/11/2019 1:48 AM, Philipp Zabel wrote:
quoted
+#define BRCM_RESCAL_START	0
+#define	BRCM_RESCAL_START_BIT	BIT(0)
+#define BRCM_RESCAL_CTRL	4
+#define BRCM_RESCAL_STATUS	8
+#define BRCM_RESCAL_STATUS_BIT	BIT(0)
Is there any reason the start bit is indented but the status bit is not?
This is a convention we have tried to adopt to denote the definition
from a register word address/offset versus the definition for bits
within that register word.
quoted
+
+struct brcm_rescal_reset {
+	void __iomem	*base;
+	struct device *dev;
+	struct reset_controller_dev rcdev;
+};
+
+static int brcm_rescal_reset_assert(struct reset_controller_dev *rcdev,
+				      unsigned long id)
+{
+	return 0;
+}
Please do not implement the assert operation if it doesn't cause a reset
line to be asserted afterwards.
The reset core will return 0 from reset_control_assert() for shared
reset controls if .assert is not implemented.
OK, will drop it.
quoted
+
+static int brcm_rescal_reset_deassert(struct reset_controller_dev *rcdev,
+				      unsigned long id)
+{
+	struct brcm_rescal_reset *data =
+		container_of(rcdev, struct brcm_rescal_reset, rcdev);
+	void __iomem *base = data->base;
+	const int NUM_RETRIES = 10;
+	u32 reg;
+	int i;
+
+	reg = readl(base + BRCM_RESCAL_START);
+	writel(reg | BRCM_RESCAL_START_BIT, base + BRCM_RESCAL_START);
+	reg = readl(base + BRCM_RESCAL_START);
Are there any other fields beside the START_BIT in this register?
This is the only bit actually.
quoted
+	if (!(reg & BRCM_RESCAL_START_BIT)) {
+		dev_err(data->dev, "failed to start sata/pcie rescal\n");
+		return -EIO;
+	}
+
+	reg = readl(base + BRCM_RESCAL_STATUS);
+	for (i = NUM_RETRIES; i >= 0 &&  !(reg & BRCM_RESCAL_STATUS_BIT); i--) {
+		udelay(100);
+		reg = readl(base + BRCM_RESCAL_STATUS);
+	}
This timeout loop should be replaced by a single readl_poll_timeout().
At 100 µs waits per iteration this could use the sleeping variant.
OK, will do.
quoted
+	if (!(reg & BRCM_RESCAL_STATUS_BIT)) {
+		dev_err(data->dev, "timedout on sata/pcie rescal\n");
+		return -ETIMEDOUT;
+	}
+
+	reg = readl(base + BRCM_RESCAL_START);
+	writel(reg ^ BRCM_RESCAL_START_BIT, base + BRCM_RESCAL_START);
Please use &= ~BRCM_RESCAL_START_BIT instead.
I think the idea was to avoid unconditionally clearing it, but based on
the documentation, I don't see this being harmful, Jim?
quoted
+	reg = readl(base + BRCM_RESCAL_START);
+	dev_dbg(data->dev, "sata/pcie rescal success\n");
+
+	return 0;
+}
This whole function looks a lot like it doesn't just deassert a reset
line, but actually issues a complete reset procedure of some kind. Do
you have some insight on what actually happens in the hardware when the
start bit is triggered? I suspect this should be implemented with the
.reset operation.
This hardware block is controlling the reset and calibration process of
the SATA/PCIe combo PHY analog front end, but is not technically part of
the PCIe or SATA PHY proper, it stands on its own, both functionally and
from a register space perspective. The motivation for modelling this as
a reset controller is that it does a reset (and a calibration) and this
is a shared reset line among 2/3 instances of another block. If you
think we should model this differently, please let us know.
-- 
Florian

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help