RE: [PATCH v10] PCI: Xilinx-NWL-PCIe: Added support for Xilinx NWL PCIe Host Controller

2015-11-28 Thread Bharat Kumar Gogada
> Subject: Re: [PATCH v10] PCI: Xilinx-NWL-PCIe: Added support for Xilinx NWL
> PCIe Host Controller
> 
> On Friday 27 November 2015 20:32:03 Bharat Kumar Gogada wrote:
> > +   do {
> > +   err = nwl_pcie_link_up(pcie, PHY_RDY_LINKUP);
> > +   if (err != 1) {
> > +   check_link_up++;
> > +   if (check_link_up > LINKUP_ITER_CHECK)
> > +   return -ENODEV;
> > +   mdelay(1000);
> > +   }
> > +   } while (!err);
> 
> mdelay(1000) is not something anyone should do. Why can't you call a
> sleeping function here?
> 
Agreed will use sleep function, will address it in next patch.

Regards,
Bharat

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


RE: [PATCH v10] PCI: Xilinx-NWL-PCIe: Added support for Xilinx NWL PCIe Host Controller

2015-11-28 Thread Bharat Kumar Gogada
> Subject: Re: [PATCH v10] PCI: Xilinx-NWL-PCIe: Added support for Xilinx NWL
> PCIe Host Controller
> 
> On 27/11/15 15:02, Bharat Kumar Gogada wrote:
> > Adding PCIe Root Port driver for Xilinx PCIe NWL bridge IP.
> >
> > Signed-off-by: Bharat Kumar Gogada 
> > Signed-off-by: Ravi Kiran Gummaluri 
> > Acked-by: Rob Herring 
> > ---
> > Changes for v10:
> > -> Changed MSI address to PCIe controller base.
> > -> Removed nwl_check_hwirq function, instead using
> > -> bitmap_find_next_zero_area
> >API to do the same.
> > ---
> >  .../devicetree/bindings/pci/xilinx-nwl-pcie.txt|   68 ++
> >  drivers/pci/host/Kconfig   |   10 +
> >  drivers/pci/host/Makefile  |1 +
> >  drivers/pci/host/pcie-xilinx-nwl.c | 1068 
> > 
> >  4 files changed, 1147 insertions(+)
> >  create mode 100644
> > Documentation/devicetree/bindings/pci/xilinx-nwl-pcie.txt
> >  create mode 100644 drivers/pci/host/pcie-xilinx-nwl.c
> >
> > diff --git a/drivers/pci/host/pcie-xilinx-nwl.c
> > b/drivers/pci/host/pcie-xilinx-nwl.c
> > new file mode 100644
> > index 000..d070344
> > --- /dev/null
> > +++ b/drivers/pci/host/pcie-xilinx-nwl.c
> 
> [...]
> 
> > +#define MSI_ADDRESS0xFD48
> > +
> 
> Really? Why do you bother having DT support then? You might as well
> hardcode everything, while you're at it.
> 
> /me felling depressed now.
Agreed, I'm already having this parameter in nwl_pcie structure, will use it. 
> 
> > +struct nwl_msi {   /* MSI information */
> > +   struct irq_domain *msi_domain;
> > +   unsigned long *bitmap;
> > +   struct irq_domain *dev_domain;
> > +   struct mutex lock;  /* protect bitmap variable */
> > +   int irq_msi0;
> > +   int irq_msi1;
> > +};
> > +
> > +struct nwl_pcie {
> > +   struct device *dev;
> > +   void __iomem *breg_base;
> > +   void __iomem *pcireg_base;
> > +   void __iomem *ecam_base;
> > +   u32 phys_breg_base; /* Physical Bridge Register Base */
> > +   u32 phys_pcie_reg_base; /* Physical PCIe Controller
> Base */
> > +   u32 phys_ecam_base; /* Physical Configuration Base */
> 
> All these u32 should be phys_addr_t. Not all the world is 32bit, fortunately.
Agreed will address it next patch.
> 
> > +   u32 breg_size;
> [...]
> 
> 
> > +static int nwl_pcie_bridge_init(struct nwl_pcie *pcie) {
> > +   struct platform_device *pdev = to_platform_device(pcie->dev);
> > +   u32 breg_val, ecam_val, first_busno = 0;
> > +   int err;
> > +   int check_link_up = 0;
> > +
> > +   /* Check for BREG present bit */
> > +   breg_val = nwl_bridge_readl(pcie, E_BREG_CAPABILITIES) &
> BREG_PRESENT;
> > +   if (!breg_val) {
> > +   dev_err(pcie->dev, "BREG is not present\n");
> > +   return breg_val;
> > +   }
> > +   /* Write bridge_off to breg base */
> > +   nwl_bridge_writel(pcie, (u32)(pcie->phys_breg_base),
> > + E_BREG_BASE_LO);
> > +
> 
> I love the casting of a u32 to a u32. You have to program E_BREG_BASE_HI as
> well, once you've fixed the data type.
> Agreed, will address this in next patch.
> > +   /* Enable BREG */
> > +   nwl_bridge_writel(pcie, ~BREG_ENABLE_FORCE & BREG_ENABLE,
> > + E_BREG_CONTROL);
> > +   /* Check for ECAM present bit */
> > +   ecam_val = nwl_bridge_readl(pcie, E_ECAM_CAPABILITIES) &
> E_ECAM_PRESENT;
> > +   if (!ecam_val) {
> > +   dev_err(pcie->dev, "ECAM is not present\n");
> > +   return ecam_val;
> > +   }
> |
> > +   /* Write phy_reg_base to ecam base */
> > +   nwl_bridge_writel(pcie, (u32)pcie->phys_ecam_base,
> E_ECAM_BASE_LO);
> 
> Same here.
> Agreed, will address this in next patch.

Regards,
Bharat

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v10] PCI: Xilinx-NWL-PCIe: Added support for Xilinx NWL PCIe Host Controller

2015-11-27 Thread Arnd Bergmann
On Friday 27 November 2015 20:32:03 Bharat Kumar Gogada wrote:
> +   do {
> +   err = nwl_pcie_link_up(pcie, PHY_RDY_LINKUP);
> +   if (err != 1) {
> +   check_link_up++;
> +   if (check_link_up > LINKUP_ITER_CHECK)
> +   return -ENODEV;
> +   mdelay(1000);
> +   }
> +   } while (!err);

mdelay(1000) is not something anyone should do. Why can't you call
a sleeping function here?

Arnd
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v10] PCI: Xilinx-NWL-PCIe: Added support for Xilinx NWL PCIe Host Controller

2015-11-27 Thread Marc Zyngier
On 27/11/15 15:02, Bharat Kumar Gogada wrote:
> Adding PCIe Root Port driver for Xilinx PCIe NWL bridge IP.
> 
> Signed-off-by: Bharat Kumar Gogada 
> Signed-off-by: Ravi Kiran Gummaluri 
> Acked-by: Rob Herring 
> ---
> Changes for v10:
> -> Changed MSI address to PCIe controller base.
> -> Removed nwl_check_hwirq function, instead using bitmap_find_next_zero_area
>API to do the same.
> ---
>  .../devicetree/bindings/pci/xilinx-nwl-pcie.txt|   68 ++
>  drivers/pci/host/Kconfig   |   10 +
>  drivers/pci/host/Makefile  |1 +
>  drivers/pci/host/pcie-xilinx-nwl.c | 1068 
> 
>  4 files changed, 1147 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/pci/xilinx-nwl-pcie.txt
>  create mode 100644 drivers/pci/host/pcie-xilinx-nwl.c
> 
> diff --git a/drivers/pci/host/pcie-xilinx-nwl.c 
> b/drivers/pci/host/pcie-xilinx-nwl.c
> new file mode 100644
> index 000..d070344
> --- /dev/null
> +++ b/drivers/pci/host/pcie-xilinx-nwl.c

[...]

> +#define MSI_ADDRESS  0xFD48
> +

Really? Why do you bother having DT support then? You might as well
hardcode everything, while you're at it.

/me felling depressed now.

> +struct nwl_msi { /* MSI information */
> + struct irq_domain *msi_domain;
> + unsigned long *bitmap;
> + struct irq_domain *dev_domain;
> + struct mutex lock;  /* protect bitmap variable */
> + int irq_msi0;
> + int irq_msi1;
> +};
> +
> +struct nwl_pcie {
> + struct device *dev;
> + void __iomem *breg_base;
> + void __iomem *pcireg_base;
> + void __iomem *ecam_base;
> + u32 phys_breg_base; /* Physical Bridge Register Base */
> + u32 phys_pcie_reg_base; /* Physical PCIe Controller Base */
> + u32 phys_ecam_base; /* Physical Configuration Base */

All these u32 should be phys_addr_t. Not all the world is 32bit,
fortunately.

> + u32 breg_size;
> + u32 pcie_reg_size;
> + u32 ecam_size;
> + int irq_intx;
> + int irq_misc;
> + u32 ecam_value;
> + u8 last_busno;
> + u8 root_busno;
> + u8 link_up;
> + struct nwl_msi msi;
> + struct irq_domain *legacy_irq_domain;
> +};

[...]

> +static void nwl_compose_msi_msg(struct irq_data *data, struct msi_msg *msg)
> +{
> + phys_addr_t msi_addr = MSI_ADDRESS;

Fix this.

> +
> + msg->address_lo = lower_32_bits(msi_addr);
> + msg->address_hi = upper_32_bits(msi_addr);
> + msg->data = data->hwirq;
> +}

[...]

> +static int nwl_pcie_bridge_init(struct nwl_pcie *pcie)
> +{
> + struct platform_device *pdev = to_platform_device(pcie->dev);
> + u32 breg_val, ecam_val, first_busno = 0;
> + int err;
> + int check_link_up = 0;
> +
> + /* Check for BREG present bit */
> + breg_val = nwl_bridge_readl(pcie, E_BREG_CAPABILITIES) & BREG_PRESENT;
> + if (!breg_val) {
> + dev_err(pcie->dev, "BREG is not present\n");
> + return breg_val;
> + }
> + /* Write bridge_off to breg base */
> + nwl_bridge_writel(pcie, (u32)(pcie->phys_breg_base),
> +   E_BREG_BASE_LO);
> +

I love the casting of a u32 to a u32. You have to program E_BREG_BASE_HI
as well, once you've fixed the data type.

> + /* Enable BREG */
> + nwl_bridge_writel(pcie, ~BREG_ENABLE_FORCE & BREG_ENABLE,
> +   E_BREG_CONTROL);
> +
> + /* Disable DMA channel registers */
> + nwl_bridge_writel(pcie, nwl_bridge_readl(pcie, BRCFG_PCIE_RX0) |
> +   CFG_DMA_REG_BAR, BRCFG_PCIE_RX0);
> +
> + /* Enable the bridge config interrupt */
> + nwl_bridge_writel(pcie, nwl_bridge_readl(pcie, BRCFG_INTERRUPT) |
> +   BRCFG_INTERRUPT_MASK, BRCFG_INTERRUPT);
> + /* Enable Ingress subtractive decode translation */
> + nwl_bridge_writel(pcie, SET_ISUB_CONTROL, I_ISUB_CONTROL);
> +
> + /* Enable msg filtering details */
> + nwl_bridge_writel(pcie, CFG_ENABLE_MSG_FILTER_MASK,
> +   BRCFG_PCIE_RX_MSG_FILTER);
> + do {
> + err = nwl_pcie_link_up(pcie, PHY_RDY_LINKUP);
> + if (err != 1) {
> + check_link_up++;
> + if (check_link_up > LINKUP_ITER_CHECK)
> + return -ENODEV;
> + mdelay(1000);
> + }
> + } while (!err);
> +
> + /* Check for ECAM present bit */
> + ecam_val = nwl_bridge_readl(pcie, E_ECAM_CAPABILITIES) & E_ECAM_PRESENT;
> + if (!ecam_val) {
> + dev_err(pcie->dev, "ECAM is not present\n");
> + return ecam_val;
> + }
> +
> + /* Enable ECAM */
> + nwl_bridge_writel(pcie, nwl_bridge_readl(pcie, E_ECAM_CONTROL) |
> +   E_ECAM_CR_ENABLE, E_ECAM_CONTROL);
> + /* Write ecam_value on ecam_control */
> + nwl_bridge_writel(pcie, nwl_bridge_readl

[PATCH v10] PCI: Xilinx-NWL-PCIe: Added support for Xilinx NWL PCIe Host Controller

2015-11-27 Thread Bharat Kumar Gogada
Adding PCIe Root Port driver for Xilinx PCIe NWL bridge IP.

Signed-off-by: Bharat Kumar Gogada 
Signed-off-by: Ravi Kiran Gummaluri 
Acked-by: Rob Herring 
---
Changes for v10:
-> Changed MSI address to PCIe controller base.
-> Removed nwl_check_hwirq function, instead using bitmap_find_next_zero_area
   API to do the same.
---
 .../devicetree/bindings/pci/xilinx-nwl-pcie.txt|   68 ++
 drivers/pci/host/Kconfig   |   10 +
 drivers/pci/host/Makefile  |1 +
 drivers/pci/host/pcie-xilinx-nwl.c | 1068 
 4 files changed, 1147 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/pci/xilinx-nwl-pcie.txt
 create mode 100644 drivers/pci/host/pcie-xilinx-nwl.c

diff --git a/Documentation/devicetree/bindings/pci/xilinx-nwl-pcie.txt 
b/Documentation/devicetree/bindings/pci/xilinx-nwl-pcie.txt
new file mode 100644
index 000..3b2a9ad
--- /dev/null
+++ b/Documentation/devicetree/bindings/pci/xilinx-nwl-pcie.txt
@@ -0,0 +1,68 @@
+* Xilinx NWL PCIe Root Port Bridge DT description
+
+Required properties:
+- compatible: Should contain "xlnx,nwl-pcie-2.11"
+- #address-cells: Address representation for root ports, set to <3>
+- #size-cells: Size representation for root ports, set to <2>
+- #interrupt-cells: specifies the number of cells needed to encode an
+   interrupt source. The value must be 1.
+- reg: Should contain Bridge, PCIe Controller registers location,
+   configuration sapce, and length
+- reg-names: Must include the following entries:
+   "breg": bridge registers
+   "pcireg": PCIe controller registers
+   "cfg": configuration space region
+- device_type: must be "pci"
+- interrupts: Should contain NWL PCIe interrupt
+- interrupt-names: Must include the following entries:
+   "msi1, msi0": interrupt asserted when msi is received
+   "intx": interrupt that is asserted when an legacy interrupt is received
+   "misc": interrupt asserted when miscellaneous is received
+- interrupt-map-mask and interrupt-map: standard PCI properties to define the
+   mapping of the PCI interface to interrupt numbers.
+- ranges: ranges for the PCI memory regions (I/O space region is not
+   supported by hardware)
+   Please refer to the standard PCI bus binding document for a more
+   detailed explanation
+- msi-controller: indicates that this is MSI controller node
+- msi-parent:  MSI parent of the root complex itself
+- legacy-interrupt-controller: Interrupt controller device node for Legacy 
interrupts
+   - interrupt-controller: identifies the node as an interrupt controller
+   - #interrupt-cells: should be set to 1
+   - #address-cells: specifies the number of cells needed to encode an
+   address. The value must be 0.
+
+
+Example:
+
+
+nwl_pcie: pcie@fd0e {
+   #address-cells = <3>;
+   #size-cells = <2>;
+   compatible = "xlnx,nwl-pcie-2.11";
+   #interrupt-cells = <1>;
+   msi-controller;
+   device_type = "pci";
+   interrupt-parent = <&gic>;
+   interrupts = <0 114 4>, <0 115 4>, <0 116 4>, <0 117 4>, <0 118 4>;
+   interrupt-names = "msi0", "msi1", "intx", "dummy", "misc";
+   interrupt-map-mask = <0x0 0x0 0x0 0x7>;
+   interrupt-map = <0x0 0x0 0x0 0x1 &pcie_intc 0x1>,
+   <0x0 0x0 0x0 0x2 &pcie_intc 0x2>,
+   <0x0 0x0 0x0 0x3 &pcie_intc 0x3>,
+   <0x0 0x0 0x0 0x4 &pcie_intc 0x4>;
+
+   msi-parent = <&nwl_pcie>;
+   reg = <0x0 0xfd0e 0x1000>,
+ <0x0 0xfd48 0x1000>,
+ <0x0 0xe000 0x100>;
+   reg-names = "breg", "pcireg", "cfg";
+   ranges = <0x0200 0x 0xe100 0x 0xe100 0 
0x0f00>;
+
+   pcie_intc: legacy-interrupt-controller {
+   interrupt-controller;
+   #address-cells = <0>;
+   #interrupt-cells = <1>;
+   };
+
+};
diff --git a/drivers/pci/host/Kconfig b/drivers/pci/host/Kconfig
index d5e58ba..24cbcba 100644
--- a/drivers/pci/host/Kconfig
+++ b/drivers/pci/host/Kconfig
@@ -15,6 +15,16 @@ config PCI_MVEBU
depends on ARCH_MVEBU || ARCH_DOVE
depends on OF
 
+config PCIE_XILINX_NWL
+   bool "NWL PCIe Core"
+   depends on ARCH_ZYNQMP
+   select PCI_MSI_IRQ_DOMAIN if PCI_MSI
+   help
+Say 'Y' here if you want kernel to support for Xilinx
+NWL PCIe controller. The controller can act as Root Port
+or End Point. The current option selection will only
+support root port enabling.
+
 config PCIE_DW
bool
 
diff --git a/drivers/pci/host/Makefile b/drivers/pci/host/Makefile
index 140d66f..6a56df7 100644
--- a/drivers/pci/host/Makefile
+++ b/drivers/pci/host/Makefile
@@ -10,6 +10,7 @@ obj-$(CONFIG_PCI_HOST_GENERIC) += pci-host-generic.o
 obj-$(CONFIG_PCIE_SPEAR13XX) += pcie-spear13xx.o
 obj-$(CONFIG_PCI_KEYSTONE) += pci-keystone-dw.o pci-keysto