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