[PATCH v2 2/2] phy: Renesas R-Car gen3 PCIe PHY driver

2018-06-10 Thread Sergei Shtylyov
This PHY is  still  mostly undocumented -- the only documented registers
exist on R-Car V3H (R8A77980) SoC where this PHY stays in a powered-down
state after a reset and thus  we  must power it up for PCIe to work...

Signed-off-by: Sergei Shtylyov 

---
Changes in version 2:
- split the bindings into their own patch;
- fixed the PHY name in the heading comment;
- removed 'rcar_gen3_phy_pcie_ops' and the generic R-Car gen3 PCIe PHY entry in
  rcar_gen3_phy_pcie_match_table[];
- replaced the 'of_device_id::data' initializer with an explicit argument to
  devm_phy_create();
- uppercased the acronym in the comment;
- cleaned up the patch description.

 drivers/phy/renesas/Kconfig  |7 +
 drivers/phy/renesas/Makefile |1 
 drivers/phy/renesas/phy-rcar-gen3-pcie.c |  151 +++
 3 files changed, 159 insertions(+)

Index: linux-phy/drivers/phy/renesas/Kconfig
===
--- linux-phy.orig/drivers/phy/renesas/Kconfig
+++ linux-phy/drivers/phy/renesas/Kconfig
@@ -8,6 +8,13 @@ config PHY_RCAR_GEN2
help
  Support for USB PHY found on Renesas R-Car generation 2 SoCs.
 
+config PHY_RCAR_GEN3_PCIE
+   tristate "Renesas R-Car generation 3 PCIe PHY driver"
+   depends on ARCH_RENESAS
+   select GENERIC_PHY
+   help
+ Support for the PCIe PHY found on Renesas R-Car generation 3 SoCs.
+
 config PHY_RCAR_GEN3_USB2
tristate "Renesas R-Car generation 3 USB 2.0 PHY driver"
depends on ARCH_RENESAS
Index: linux-phy/drivers/phy/renesas/Makefile
===
--- linux-phy.orig/drivers/phy/renesas/Makefile
+++ linux-phy/drivers/phy/renesas/Makefile
@@ -1,3 +1,4 @@
 obj-$(CONFIG_PHY_RCAR_GEN2)+= phy-rcar-gen2.o
+obj-$(CONFIG_PHY_RCAR_GEN3_PCIE)   += phy-rcar-gen3-pcie.o
 obj-$(CONFIG_PHY_RCAR_GEN3_USB2)   += phy-rcar-gen3-usb2.o
 obj-$(CONFIG_PHY_RCAR_GEN3_USB3)   += phy-rcar-gen3-usb3.o
Index: linux-phy/drivers/phy/renesas/phy-rcar-gen3-pcie.c
===
--- /dev/null
+++ linux-phy/drivers/phy/renesas/phy-rcar-gen3-pcie.c
@@ -0,0 +1,151 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Renesas R-Car Gen3 PCIe PHY driver
+ *
+ * Copyright (C) 2018 Cogent Embedded, Inc.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define PHY_CTRL   0x4000  /* R8A77980 only */
+
+/* PHY control register (PHY_CTRL) */
+#define PHY_CTRL_PHY_PWDN  0x0004
+
+struct rcar_gen3_phy {
+   struct phy *phy;
+   spinlock_t lock;
+   void __iomem *base;
+};
+
+static void rcar_gen3_phy_pcie_modify_reg(struct phy *p, unsigned int reg,
+ u32 clear, u32 set)
+{
+   struct rcar_gen3_phy *phy = phy_get_drvdata(p);
+   void __iomem *base = phy->base;
+   unsigned long flags;
+   u32 value;
+
+   spin_lock_irqsave(>lock, flags);
+
+   value = readl(base + reg);
+   value &= ~clear;
+   value |= set;
+   writel(value, base + reg);
+
+   spin_unlock_irqrestore(>lock, flags);
+}
+
+static int r8a77980_phy_pcie_power_on(struct phy *p)
+{
+   /* Power on the PCIe PHY */
+   rcar_gen3_phy_pcie_modify_reg(p, PHY_CTRL, PHY_CTRL_PHY_PWDN, 0);
+
+   return 0;
+}
+
+static int r8a77980_phy_pcie_power_off(struct phy *p)
+{
+   /* Power off the PCIe PHY */
+   rcar_gen3_phy_pcie_modify_reg(p, PHY_CTRL, 0, PHY_CTRL_PHY_PWDN);
+
+   return 0;
+}
+
+static const struct phy_ops r8a77980_phy_pcie_ops = {
+   .power_on   = r8a77980_phy_pcie_power_on,
+   .power_off  = r8a77980_phy_pcie_power_off,
+   .owner  = THIS_MODULE,
+};
+
+static const struct of_device_id rcar_gen3_phy_pcie_match_table[] = {
+   { .compatible = "renesas,r8a77980-pcie-phy" },
+   { }
+};
+MODULE_DEVICE_TABLE(of, rcar_gen3_phy_pcie_match_table);
+
+static int rcar_gen3_phy_pcie_probe(struct platform_device *pdev)
+{
+   struct device *dev = >dev;
+   struct phy_provider *provider;
+   struct rcar_gen3_phy *phy;
+   struct resource *res;
+   void __iomem *base;
+   int error;
+
+   if (!dev->of_node) {
+   dev_err(dev,
+   "This driver must only be instantiated from the device 
tree\n");
+   return -EINVAL;
+   }
+
+   res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+   base = devm_ioremap_resource(dev, res);
+   if (IS_ERR(base))
+   return PTR_ERR(base);
+
+   phy = devm_kzalloc(dev, sizeof(*phy), GFP_KERNEL);
+   if (!phy)
+   return -ENOMEM;
+
+   spin_lock_init(>lock);
+
+   phy->base = base;
+
+   /*
+* devm_phy_create() will call pm_runtime_enable(>dev);
+* And then, phy-core will manage runtime PM for this device.
+*/
+  

[PATCH v2 1/2] dt-bindings: phy: Renesas R-Car Gen3 PCIe PHY bindings

2018-06-10 Thread Sergei Shtylyov
This PHY is  still  mostly undocumented --  the only documented registers
exist on R-Car V3H (R8A77980) SoC.  Add the corresponding device tree
bindings.

Signed-off-by: Sergei Shtylyov 

---
Changes in version 2:
- split from the big driver/bindings patch;
- got rid of the generic R-Car gen3 "compatible" prop value.

 Documentation/devicetree/bindings/phy/rcar-gen3-phy-pcie.txt |   24 +++
 1 file changed, 24 insertions(+)

Index: linux-phy/Documentation/devicetree/bindings/phy/rcar-gen3-phy-pcie.txt
===
--- /dev/null
+++ linux-phy/Documentation/devicetree/bindings/phy/rcar-gen3-phy-pcie.txt
@@ -0,0 +1,24 @@
+* Renesas R-Car generation 3 PCIe PHY
+
+This file provides information on what the device node for the R-Car
+generation 3 PCIe PHY contains.
+
+Required properties:
+- compatible: "renesas,r8a77980-pcie-phy" if the device is a part of the
+ R8A77980 SoC.
+- reg: offset and length of the register block.
+- clocks: clock phandle and specifier pair.
+- power-domains: power domain phandle and specifier pair.
+- resets: reset phandle and specifier pair.
+- #phy-cells: see phy-bindings.txt in the same directory, must be <0>.
+
+Example (R-Car V3H):
+
+   pcie-phy@e65d {
+   compatible = "renesas,r8a77980-pcie-phy";
+   reg = <0 0xe65d 0 0x8000>;
+   #phy-cells = <0>;
+   clocks = < CPG_MOD 319>;
+   power-domains = < 32>;
+   resets = < 319>;
+   };


[PATCH v2 0/2] Renesas R-Car gen3 PCIe PHY driver/bindings

2018-06-10 Thread Sergei Shtylyov
Hello!

Here's the set of 2 patches against Kishon Vijay Abraham's 'linux.git' repo's
'next' branch. We're adding the Renesas R-Car gen3 (namely R-Car V3H) PCIe PHY
driver and the device tree bindings for it...

[1/2] dt-bindings: phy: Renesas R-Car Gen3 PCIe PHY bindings
[2/2] phy: Renesas R-Car gen3 PCIe PHY driver

MBR, Sergei


Re: [PATCH V2 4/5] PCI: rcar: Support runtime PM, link state L1 handling

2018-06-10 Thread Marek Vasut
On 11/17/2017 06:49 PM, Lorenzo Pieralisi wrote:
> Hi Marek,

Hi,

> On Fri, Nov 10, 2017 at 10:58:42PM +0100, Marek Vasut wrote:
>> From: Phil Edworthy 
>>
>> Most PCIe host controllers support L0s and L1 power states via ASPM.
>> The R-Car hardware only supports L0s, so when the system suspends and
>> resumes we have to manually handle L1.
>> When the system suspends, cards can put themselves into L1 and send a
> 
> I assumed L1 entry has to be negotiated depending upon the PCIe
> hierarchy capabilities, I would appreciate if you can explain to
> me what's the root cause of the issue please.

You should probably ignore the suspend/resume part altogether. The issue
here is that the cards can enter L1 state, while the controller won't do
that automatically, it can only detect that the link went into L1 state.
If that happens,the driver must manually put the controller to L1 state.
The controller can transition out of L1 state automatically though.

>> PM_ENTER_L1 DLLP to the host controller. At this point, we can no longer
>> access the card's config registers.
>>
>> The R-Car host controller will handle taking cards out of L1 as long as
>> the host controller has also been transitioned to L1 link state.
> 
> I wonder why this can't be done in a PM restore hook but that's not
> really where my question is.

I suspect because the link can be in L1 during startup too?

>> Ideally, we would detect the PM_ENTER_L1 DLLP using an interrupt and
>> transition the host to L1 immediately. However, this patch just ensures
>> that we can talk to cards after they have gone into L1.
> 
>> When attempting a config access, it checks to see if the card has gone
>> into L1, and if so, does the same for the host controller.
>>
>> This is based on a patch by Hien Dang 
>>
>> Signed-off-by: Phil Edworthy 
>> Signed-off-by: Marek Vasut 
>> Cc: Geert Uytterhoeven 
>> Cc: Phil Edworthy 
>> Cc: Simon Horman 
>> Cc: Wolfram Sang 
>> Cc: linux-renesas-soc@vger.kernel.org
>> ---
>> V2: - Drop extra parenthesis
>> - Use GENMASK()
>> - Fix comment "The HW will handle coming of of L1.", s/of of/out of/
>> ---
>>  drivers/pci/host/pcie-rcar.c | 24 
>>  1 file changed, 24 insertions(+)
>>
>> diff --git a/drivers/pci/host/pcie-rcar.c b/drivers/pci/host/pcie-rcar.c
>> index ab61829db389..068bf9067ec1 100644
>> --- a/drivers/pci/host/pcie-rcar.c
>> +++ b/drivers/pci/host/pcie-rcar.c
>> @@ -92,6 +92,13 @@
>>  #define MACCTLR 0x011058
>>  #define  SPEED_CHANGE   BIT(24)
>>  #define  SCRAMBLE_DISABLE   BIT(27)
>> +#define PMSR0x01105c
>> +#define  L1FAEG BIT(31)
>> +#define  PM_ENTER_L1RX  BIT(23)
>> +#define  PMSTATEGENMASK(18, 16)
>> +#define  PMSTATE_L1 GENMASK(17, 16)
>> +#define PMCTLR  0x011060
>> +#define  L1_INITBIT(31)
>>  #define MACS2R  0x011078
>>  #define MACCGSPSETR 0x011084
>>  #define  SPCNGRSN   BIT(31)
>> @@ -191,6 +198,7 @@ static int rcar_pcie_config_access(struct rcar_pcie 
>> *pcie,
>>  unsigned int devfn, int where, u32 *data)
>>  {
>>  int dev, func, reg, index;
>> +u32 val;
>>  
>>  dev = PCI_SLOT(devfn);
>>  func = PCI_FUNC(devfn);
>> @@ -232,6 +240,22 @@ static int rcar_pcie_config_access(struct rcar_pcie 
>> *pcie,
>>  if (pcie->root_bus_nr < 0)
>>  return PCIBIOS_DEVICE_NOT_FOUND;
>>  
>> +/*
>> + * If we are not in L1 link state and we have received PM_ENTER_L1 DLLP,
>> + * transition to L1 link state. The HW will handle coming out of L1.
>> + */
>> +val = rcar_pci_read_reg(pcie, PMSR);
>> +if (val & PM_ENTER_L1RX && (val & PMSTATE) != PMSTATE_L1) {
>> +rcar_pci_write_reg(pcie, L1_INIT, PMCTLR);
>> +
>> +/* Wait until we are in L1 */
>> +while (!(val & L1FAEG))
>> +val = rcar_pci_read_reg(pcie, PMSR);
>> +
>> +/* Clear flags indicating link has transitioned to L1 */
>> +rcar_pci_write_reg(pcie, L1FAEG | PM_ENTER_L1RX, PMSR);
>> +}
> 
> I do not get why you need to add the DLLP check for _every_ given config
> access and how/why it is just related to suspend/resume and not eg cold
> boot (I supposed it is because devices can enter L1 upon suspend(?)), I
> would ask you please to provide a thorough explanation so that I can
> actually review this patch (the commit log must be rewritten nonetheless,
> I do not think it is clear, at least it is not for me).

See above

-- 
Best regards,
Marek Vasut