RE: [PATCH] PCI: Generic Configuration Access Mechanism support

2014-05-21 Thread Srikanth Thokala

> -Original Message-
> From: Arnd Bergmann [mailto:a...@arndb.de]
> Sent: Wednesday, May 21, 2014 1:23 PM
> To: Srikanth Thokala
> Cc: Bjorn Helgaas; will.dea...@arm.com; Michal Simek; linux-
> ker...@vger.kernel.org; linux-...@vger.kernel.org
> Subject: Re: [PATCH] PCI: Generic Configuration Access Mechanism support
>
> On Tuesday 20 May 2014 20:01:01 Srikanth Thokala wrote:
> > On Mon, May 19, 2014 at 10:33 PM, Arnd Bergmann 
> wrote:
> > > On Sunday 18 May 2014 19:38:45 Srikanth Thokala wrote:
> > >> +
> > >> + if (cfg->ops->is_valid_cfg_access) {
> > >> + if (!cfg->ops->is_valid_cfg_access(bus, devfn)) {
> > >> + *val = PCI_CFG_INVALID_DEVFN;
> > >> + return PCIBIOS_DEVICE_NOT_FOUND;
> > >> + }
> > >> + }
> > >
> > > Can you explain why this callback is needed? If the space for the
> > > bus is mapped, any access should just work.
> >
> > As I was explaining to Will, there are some controllers which doesn't
> > return FF's when a device is not found on the bus (as per the PCI
> > specification) and accessing such a device address from the kernel
> > results in an external abort.
> > So, I added this additional logic in my driver to bypass this and
> > return FF's. Our IP and even other controllers like Tegra, Renesas
> > have similar implementation.
> > We cant think of a better solution and please let you us know if you
> > have any inputs.
>
> Does your hardware need this? My first response would otherwise be to
> treat that as noncompliant and not handle this case in the generic
> implementation.

Yes, my hardware needs this additional logic.

Srikanth

>
>   Arnd


This email and any attachments are intended for the sole use of the named 
recipient(s) and contain(s) confidential information that may be proprietary, 
privileged or copyrighted under applicable law. If you are not the intended 
recipient, do not read, copy, or forward this email message or any attachments. 
Delete this email message and any attachments immediately.

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH] PCI: Generic Configuration Access Mechanism support

2014-05-21 Thread Arnd Bergmann
On Tuesday 20 May 2014 20:01:01 Srikanth Thokala wrote:
> On Mon, May 19, 2014 at 10:33 PM, Arnd Bergmann  wrote:
> > On Sunday 18 May 2014 19:38:45 Srikanth Thokala wrote:
> >> +
> >> + if (cfg->ops->is_valid_cfg_access) {
> >> + if (!cfg->ops->is_valid_cfg_access(bus, devfn)) {
> >> + *val = PCI_CFG_INVALID_DEVFN;
> >> + return PCIBIOS_DEVICE_NOT_FOUND;
> >> + }
> >> + }
> >
> > Can you explain why this callback is needed? If the space for the
> > bus is mapped, any access should just work.
> 
> As I was explaining to Will, there are some controllers which doesn't
> return FF's
> when a device is not found on the bus (as per the PCI specification) and
> accessing such a device address from the kernel results in an external abort.
> So, I added this additional logic in my driver to bypass this and
> return FF's. Our IP
> and even other controllers like Tegra, Renesas have similar implementation.
> We cant think of a better solution and please let you us know if you
> have any inputs.

Does your hardware need this? My first response would otherwise be to
treat that as noncompliant and not handle this case in the generic 
implementation.

Arnd
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH] PCI: Generic Configuration Access Mechanism support

2014-05-21 Thread Arnd Bergmann
On Tuesday 20 May 2014 20:01:01 Srikanth Thokala wrote:
 On Mon, May 19, 2014 at 10:33 PM, Arnd Bergmann a...@arndb.de wrote:
  On Sunday 18 May 2014 19:38:45 Srikanth Thokala wrote:
  +
  + if (cfg-ops-is_valid_cfg_access) {
  + if (!cfg-ops-is_valid_cfg_access(bus, devfn)) {
  + *val = PCI_CFG_INVALID_DEVFN;
  + return PCIBIOS_DEVICE_NOT_FOUND;
  + }
  + }
 
  Can you explain why this callback is needed? If the space for the
  bus is mapped, any access should just work.
 
 As I was explaining to Will, there are some controllers which doesn't
 return FF's
 when a device is not found on the bus (as per the PCI specification) and
 accessing such a device address from the kernel results in an external abort.
 So, I added this additional logic in my driver to bypass this and
 return FF's. Our IP
 and even other controllers like Tegra, Renesas have similar implementation.
 We cant think of a better solution and please let you us know if you
 have any inputs.

Does your hardware need this? My first response would otherwise be to
treat that as noncompliant and not handle this case in the generic 
implementation.

Arnd
--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


RE: [PATCH] PCI: Generic Configuration Access Mechanism support

2014-05-21 Thread Srikanth Thokala

 -Original Message-
 From: Arnd Bergmann [mailto:a...@arndb.de]
 Sent: Wednesday, May 21, 2014 1:23 PM
 To: Srikanth Thokala
 Cc: Bjorn Helgaas; will.dea...@arm.com; Michal Simek; linux-
 ker...@vger.kernel.org; linux-...@vger.kernel.org
 Subject: Re: [PATCH] PCI: Generic Configuration Access Mechanism support

 On Tuesday 20 May 2014 20:01:01 Srikanth Thokala wrote:
  On Mon, May 19, 2014 at 10:33 PM, Arnd Bergmann a...@arndb.de
 wrote:
   On Sunday 18 May 2014 19:38:45 Srikanth Thokala wrote:
   +
   + if (cfg-ops-is_valid_cfg_access) {
   + if (!cfg-ops-is_valid_cfg_access(bus, devfn)) {
   + *val = PCI_CFG_INVALID_DEVFN;
   + return PCIBIOS_DEVICE_NOT_FOUND;
   + }
   + }
  
   Can you explain why this callback is needed? If the space for the
   bus is mapped, any access should just work.
 
  As I was explaining to Will, there are some controllers which doesn't
  return FF's when a device is not found on the bus (as per the PCI
  specification) and accessing such a device address from the kernel
  results in an external abort.
  So, I added this additional logic in my driver to bypass this and
  return FF's. Our IP and even other controllers like Tegra, Renesas
  have similar implementation.
  We cant think of a better solution and please let you us know if you
  have any inputs.

 Does your hardware need this? My first response would otherwise be to
 treat that as noncompliant and not handle this case in the generic
 implementation.

Yes, my hardware needs this additional logic.

Srikanth


   Arnd


This email and any attachments are intended for the sole use of the named 
recipient(s) and contain(s) confidential information that may be proprietary, 
privileged or copyrighted under applicable law. If you are not the intended 
recipient, do not read, copy, or forward this email message or any attachments. 
Delete this email message and any attachments immediately.

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH] PCI: Generic Configuration Access Mechanism support

2014-05-20 Thread Srikanth Thokala
Hi Arnd,

On Mon, May 19, 2014 at 10:33 PM, Arnd Bergmann  wrote:
> On Sunday 18 May 2014 19:38:45 Srikanth Thokala wrote:
>> +
>> + if (cfg->ops->is_valid_cfg_access) {
>> + if (!cfg->ops->is_valid_cfg_access(bus, devfn)) {
>> + *val = PCI_CFG_INVALID_DEVFN;
>> + return PCIBIOS_DEVICE_NOT_FOUND;
>> + }
>> + }
>
> Can you explain why this callback is needed? If the space for the
> bus is mapped, any access should just work.

As I was explaining to Will, there are some controllers which doesn't
return FF's
when a device is not found on the bus (as per the PCI specification) and
accessing such a device address from the kernel results in an external abort.
So, I added this additional logic in my driver to bypass this and
return FF's. Our IP
and even other controllers like Tegra, Renesas have similar implementation.
We cant think of a better solution and please let you us know if you
have any inputs.

Thanks
Srikanth

>
>> +
>> +/* Generic PCI CAM/ECAM Configuration Bus Operations */
>> +
>> +struct pci_cfg_bus_ops pci_cfg_cam_bus_ops = {
>> + .bus_shift  = PCI_CFG_CAM_BUS_NUM,
>> + .map_bus= pci_cfg_map_bus_cam,
>> +};
>> +EXPORT_SYMBOL_GPL(pci_cfg_cam_bus_ops);
>> +
>> +struct pci_cfg_bus_ops pci_cfg_ecam_bus_ops = {
>> + .bus_shift  = PCI_CFG_ECAM_BUS_NUM,
>> + .map_bus= pci_cfg_map_bus_ecam,
>> +};
>> +EXPORT_SYMBOL_GPL(pci_cfg_ecam_bus_ops);
>> +
>> +struct pci_ops pci_cfg_ops = {
>> + .read   = pci_cfg_read,
>> + .write  = pci_cfg_write,
>> +};
>> +EXPORT_SYMBOL_GPL(pci_cfg_ops);
>
>
> If we can find a way to remove the is_valid_cfg_access() check, we're
> probably better off removing the cfg_bus_ops as well, and exporting
> two sets of pci_ops. There will be a little more duplication here, but
> also less complexity in this module, and more importantly in the drivers
> using it.
>
> Arnd
> --
> To unsubscribe from this list: send the line "unsubscribe linux-pci" in
> the body of a message to majord...@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH] PCI: Generic Configuration Access Mechanism support

2014-05-20 Thread Srikanth Thokala
Hi Arnd,

On Mon, May 19, 2014 at 10:33 PM, Arnd Bergmann a...@arndb.de wrote:
 On Sunday 18 May 2014 19:38:45 Srikanth Thokala wrote:
 +
 + if (cfg-ops-is_valid_cfg_access) {
 + if (!cfg-ops-is_valid_cfg_access(bus, devfn)) {
 + *val = PCI_CFG_INVALID_DEVFN;
 + return PCIBIOS_DEVICE_NOT_FOUND;
 + }
 + }

 Can you explain why this callback is needed? If the space for the
 bus is mapped, any access should just work.

As I was explaining to Will, there are some controllers which doesn't
return FF's
when a device is not found on the bus (as per the PCI specification) and
accessing such a device address from the kernel results in an external abort.
So, I added this additional logic in my driver to bypass this and
return FF's. Our IP
and even other controllers like Tegra, Renesas have similar implementation.
We cant think of a better solution and please let you us know if you
have any inputs.

Thanks
Srikanth


 +
 +/* Generic PCI CAM/ECAM Configuration Bus Operations */
 +
 +struct pci_cfg_bus_ops pci_cfg_cam_bus_ops = {
 + .bus_shift  = PCI_CFG_CAM_BUS_NUM,
 + .map_bus= pci_cfg_map_bus_cam,
 +};
 +EXPORT_SYMBOL_GPL(pci_cfg_cam_bus_ops);
 +
 +struct pci_cfg_bus_ops pci_cfg_ecam_bus_ops = {
 + .bus_shift  = PCI_CFG_ECAM_BUS_NUM,
 + .map_bus= pci_cfg_map_bus_ecam,
 +};
 +EXPORT_SYMBOL_GPL(pci_cfg_ecam_bus_ops);
 +
 +struct pci_ops pci_cfg_ops = {
 + .read   = pci_cfg_read,
 + .write  = pci_cfg_write,
 +};
 +EXPORT_SYMBOL_GPL(pci_cfg_ops);


 If we can find a way to remove the is_valid_cfg_access() check, we're
 probably better off removing the cfg_bus_ops as well, and exporting
 two sets of pci_ops. There will be a little more duplication here, but
 also less complexity in this module, and more importantly in the drivers
 using it.

 Arnd
 --
 To unsubscribe from this list: send the line unsubscribe linux-pci in
 the body of a message to majord...@vger.kernel.org
 More majordomo info at  http://vger.kernel.org/majordomo-info.html
--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH] PCI: Generic Configuration Access Mechanism support

2014-05-19 Thread Arnd Bergmann
On Sunday 18 May 2014 19:38:45 Srikanth Thokala wrote:
> +
> + if (cfg->ops->is_valid_cfg_access) {
> + if (!cfg->ops->is_valid_cfg_access(bus, devfn)) {
> + *val = PCI_CFG_INVALID_DEVFN;
> + return PCIBIOS_DEVICE_NOT_FOUND;
> + }
> + }

Can you explain why this callback is needed? If the space for the
bus is mapped, any access should just work.

> +
> +/* Generic PCI CAM/ECAM Configuration Bus Operations */
> +
> +struct pci_cfg_bus_ops pci_cfg_cam_bus_ops = {
> + .bus_shift  = PCI_CFG_CAM_BUS_NUM,
> + .map_bus= pci_cfg_map_bus_cam,
> +};
> +EXPORT_SYMBOL_GPL(pci_cfg_cam_bus_ops);
> +
> +struct pci_cfg_bus_ops pci_cfg_ecam_bus_ops = {
> + .bus_shift  = PCI_CFG_ECAM_BUS_NUM,
> + .map_bus= pci_cfg_map_bus_ecam,
> +};
> +EXPORT_SYMBOL_GPL(pci_cfg_ecam_bus_ops);
> +
> +struct pci_ops pci_cfg_ops = {
> + .read   = pci_cfg_read,
> + .write  = pci_cfg_write,
> +};
> +EXPORT_SYMBOL_GPL(pci_cfg_ops);


If we can find a way to remove the is_valid_cfg_access() check, we're
probably better off removing the cfg_bus_ops as well, and exporting
two sets of pci_ops. There will be a little more duplication here, but
also less complexity in this module, and more importantly in the drivers
using it.

Arnd
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH] PCI: Generic Configuration Access Mechanism support

2014-05-19 Thread Arnd Bergmann
On Monday 19 May 2014 17:32:23 Will Deacon wrote:
> On Sun, May 18, 2014 at 03:08:45PM +0100, Srikanth Thokala wrote:
> > This patch adds support for a generic CAM and ECAM configuration
> > space accesses.
> 
> Looks good to me, thanks Srikanth!
> 
> Arnd: is this the sort of thing you were expecting? The
> ->is_valid_cfg_access callback is a bit horrible, but I can't think of
> anything better.
> 
> I can include this in the next posting of my PCI patches.

Yes, this is roughly what I had in mind, thanks a lot!

I'll comment a bit more on the patch itself

Arnd
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH] PCI: Generic Configuration Access Mechanism support

2014-05-19 Thread Will Deacon
On Sun, May 18, 2014 at 03:08:45PM +0100, Srikanth Thokala wrote:
> This patch adds support for a generic CAM and ECAM configuration
> space accesses.

Looks good to me, thanks Srikanth!

Arnd: is this the sort of thing you were expecting? The
->is_valid_cfg_access callback is a bit horrible, but I can't think of
anything better.

I can include this in the next posting of my PCI patches.

Will
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH] PCI: Generic Configuration Access Mechanism support

2014-05-19 Thread Will Deacon
On Sun, May 18, 2014 at 03:08:45PM +0100, Srikanth Thokala wrote:
 This patch adds support for a generic CAM and ECAM configuration
 space accesses.

Looks good to me, thanks Srikanth!

Arnd: is this the sort of thing you were expecting? The
-is_valid_cfg_access callback is a bit horrible, but I can't think of
anything better.

I can include this in the next posting of my PCI patches.

Will
--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH] PCI: Generic Configuration Access Mechanism support

2014-05-19 Thread Arnd Bergmann
On Monday 19 May 2014 17:32:23 Will Deacon wrote:
 On Sun, May 18, 2014 at 03:08:45PM +0100, Srikanth Thokala wrote:
  This patch adds support for a generic CAM and ECAM configuration
  space accesses.
 
 Looks good to me, thanks Srikanth!
 
 Arnd: is this the sort of thing you were expecting? The
 -is_valid_cfg_access callback is a bit horrible, but I can't think of
 anything better.
 
 I can include this in the next posting of my PCI patches.

Yes, this is roughly what I had in mind, thanks a lot!

I'll comment a bit more on the patch itself

Arnd
--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH] PCI: Generic Configuration Access Mechanism support

2014-05-19 Thread Arnd Bergmann
On Sunday 18 May 2014 19:38:45 Srikanth Thokala wrote:
 +
 + if (cfg-ops-is_valid_cfg_access) {
 + if (!cfg-ops-is_valid_cfg_access(bus, devfn)) {
 + *val = PCI_CFG_INVALID_DEVFN;
 + return PCIBIOS_DEVICE_NOT_FOUND;
 + }
 + }

Can you explain why this callback is needed? If the space for the
bus is mapped, any access should just work.

 +
 +/* Generic PCI CAM/ECAM Configuration Bus Operations */
 +
 +struct pci_cfg_bus_ops pci_cfg_cam_bus_ops = {
 + .bus_shift  = PCI_CFG_CAM_BUS_NUM,
 + .map_bus= pci_cfg_map_bus_cam,
 +};
 +EXPORT_SYMBOL_GPL(pci_cfg_cam_bus_ops);
 +
 +struct pci_cfg_bus_ops pci_cfg_ecam_bus_ops = {
 + .bus_shift  = PCI_CFG_ECAM_BUS_NUM,
 + .map_bus= pci_cfg_map_bus_ecam,
 +};
 +EXPORT_SYMBOL_GPL(pci_cfg_ecam_bus_ops);
 +
 +struct pci_ops pci_cfg_ops = {
 + .read   = pci_cfg_read,
 + .write  = pci_cfg_write,
 +};
 +EXPORT_SYMBOL_GPL(pci_cfg_ops);


If we can find a way to remove the is_valid_cfg_access() check, we're
probably better off removing the cfg_bus_ops as well, and exporting
two sets of pci_ops. There will be a little more duplication here, but
also less complexity in this module, and more importantly in the drivers
using it.

Arnd
--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH] PCI: Generic Configuration Access Mechanism support

2014-05-18 Thread Srikanth Thokala
This patch adds support for a generic CAM and ECAM configuration
space accesses.

Signed-off-by: Srikanth Thokala 
---
This patch is created with reference from Will's patch series:
1/3 - "ARM: kconfig: allow PCI support to be selected with ARCH_MULTIPLATFORM"
2/3 - "PCI: ARM: add support for generic PCI host controller"
3/3 - "MAINTAINERS: add entry for generic PCI host controller driver"
---
 drivers/pci/Makefile  |2 +-
 drivers/pci/pci-cfg.c |  162 +
 include/linux/pci.h   |   34 +++
 3 files changed, 197 insertions(+), 1 deletion(-)
 create mode 100644 drivers/pci/pci-cfg.c

diff --git a/drivers/pci/Makefile b/drivers/pci/Makefile
index e04fe2d..37cfc33 100644
--- a/drivers/pci/Makefile
+++ b/drivers/pci/Makefile
@@ -4,7 +4,7 @@
 
 obj-y  += access.o bus.o probe.o host-bridge.o remove.o pci.o \
pci-driver.o search.o pci-sysfs.o rom.o setup-res.o \
-   irq.o vpd.o setup-bus.o vc.o
+   irq.o vpd.o setup-bus.o vc.o pci-cfg.o
 obj-$(CONFIG_PROC_FS) += proc.o
 obj-$(CONFIG_SYSFS) += slot.o
 
diff --git a/drivers/pci/pci-cfg.c b/drivers/pci/pci-cfg.c
new file mode 100644
index 000..2b15fe4
--- /dev/null
+++ b/drivers/pci/pci-cfg.c
@@ -0,0 +1,162 @@
+/*
+ * PCI generic configuration access mechanism
+ *
+ * Copyright (C) 2014 ARM Limited
+ * Copyright (c) 2014 Xilinx, Inc.
+ *
+ * Author: Will Deacon 
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include 
+
+/* CAM definitions */
+#define PCI_CFG_CAM_BUS_NUM16
+#define PCI_CFG_CAM_DEV_NUM8
+
+/* ECAM definitions */
+#define PCI_CFG_ECAM_BUS_NUM   20
+#define PCI_CFG_ECAM_DEV_NUM   12
+
+/* Invalid device/function value */
+#define PCI_CFG_INVALID_DEVFN  0x
+
+/**
+ * pci_cfg_map_bus_cam - Get the CAM based configuration space address
+ * @bus: PCI Bus pointer
+ * @devfn: Device/Function
+ * @where: Offset from base
+ *
+ * Return: Configuration Space address
+ */
+static void __iomem *pci_cfg_map_bus_cam(struct pci_bus *bus,
+unsigned int devfn,
+int where)
+{
+   struct pci_sys_data *sys = bus->sysdata;
+   struct pci_cfg_windows *cfg = sys->private_data;
+   resource_size_t idx = bus->number - cfg->bus_range.start;
+
+   return cfg->win[idx] + ((devfn << PCI_CFG_CAM_DEV_NUM) | where);
+}
+
+/**
+ * pci_cfg_map_bus_ecam - Get the ECAM based configuration space address
+ * @bus: PCI bus pointer
+ * @devfn: Device/Function
+ * @where: Offset from base
+ *
+ * Return: Configuration space address
+ */
+static void __iomem *pci_cfg_map_bus_ecam(struct pci_bus *bus,
+ unsigned int devfn,
+ int where)
+{
+   struct pci_sys_data *sys = bus->sysdata;
+   struct pci_cfg_windows *cfg = sys->private_data;
+   resource_size_t idx = bus->number - cfg->bus_range.start;
+
+   return cfg->win[idx] + ((devfn << PCI_CFG_ECAM_DEV_NUM) | where);
+}
+
+/**
+ * pci_cfg_read - Read configuration space
+ * @bus: PCI bus pointer
+ * @devfn: Device/function
+ * @where: Offset from base
+ * @size: Byte/word/dword
+ * @val: Value to be read
+ *
+ * Return: PCIBIOS_SUCCESSFUL on success
+ *PCIBIOS_DEVICE_NOT_FOUND on failure
+ */
+static int pci_cfg_read(struct pci_bus *bus, unsigned int devfn,
+   int where, int size, unsigned int *val)
+{
+   void __iomem *addr;
+   struct pci_sys_data *sys = bus->sysdata;
+   struct pci_cfg_windows *cfg = sys->private_data;
+
+   if (cfg->ops->is_valid_cfg_access) {
+   if (!cfg->ops->is_valid_cfg_access(bus, devfn)) {
+   *val = PCI_CFG_INVALID_DEVFN;
+   return PCIBIOS_DEVICE_NOT_FOUND;
+   }
+   }
+
+   addr = cfg->ops->map_bus(bus, devfn, where);
+
+   switch (size) {
+   case 1:
+   *val = readb(addr);
+   break;
+   case 2:
+   *val = readw(addr);
+   break;
+   default:
+   *val = readl(addr);
+   }
+
+   return PCIBIOS_SUCCESSFUL;
+}
+
+/**
+ * pci_cfg_write - Write configuration space
+ * @bus: PCI bus pointer
+ * @devfn: Device/function
+ * @where: Offset from base
+ * @size: Byte/word/dword
+ * @val: Value to write
+ *
+ * Return: PCIBIOS_SUCCESSFUL on success
+ *PCIBIOS_DEVICE_NOT_FOUND on failure
+ */
+static int pci_cfg_write(struct pci_bus *bus, unsigned int devfn,
+int where, int size, unsigned int val)
+{
+   void __iomem *addr;
+   struct pci_sys_data *sys = bus->sysdata;
+   struct pci_cfg_windows *cfg = sys->private_data;
+
+   if (cfg->ops->is_valid_cfg_access)
+   if 

[PATCH] PCI: Generic Configuration Access Mechanism support

2014-05-18 Thread Srikanth Thokala
This patch adds support for a generic CAM and ECAM configuration
space accesses.

Signed-off-by: Srikanth Thokala stho...@xilinx.com
---
This patch is created with reference from Will's patch series:
1/3 - ARM: kconfig: allow PCI support to be selected with ARCH_MULTIPLATFORM
2/3 - PCI: ARM: add support for generic PCI host controller
3/3 - MAINTAINERS: add entry for generic PCI host controller driver
---
 drivers/pci/Makefile  |2 +-
 drivers/pci/pci-cfg.c |  162 +
 include/linux/pci.h   |   34 +++
 3 files changed, 197 insertions(+), 1 deletion(-)
 create mode 100644 drivers/pci/pci-cfg.c

diff --git a/drivers/pci/Makefile b/drivers/pci/Makefile
index e04fe2d..37cfc33 100644
--- a/drivers/pci/Makefile
+++ b/drivers/pci/Makefile
@@ -4,7 +4,7 @@
 
 obj-y  += access.o bus.o probe.o host-bridge.o remove.o pci.o \
pci-driver.o search.o pci-sysfs.o rom.o setup-res.o \
-   irq.o vpd.o setup-bus.o vc.o
+   irq.o vpd.o setup-bus.o vc.o pci-cfg.o
 obj-$(CONFIG_PROC_FS) += proc.o
 obj-$(CONFIG_SYSFS) += slot.o
 
diff --git a/drivers/pci/pci-cfg.c b/drivers/pci/pci-cfg.c
new file mode 100644
index 000..2b15fe4
--- /dev/null
+++ b/drivers/pci/pci-cfg.c
@@ -0,0 +1,162 @@
+/*
+ * PCI generic configuration access mechanism
+ *
+ * Copyright (C) 2014 ARM Limited
+ * Copyright (c) 2014 Xilinx, Inc.
+ *
+ * Author: Will Deacon will.dea...@arm.com
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include linux/of_pci.h
+
+/* CAM definitions */
+#define PCI_CFG_CAM_BUS_NUM16
+#define PCI_CFG_CAM_DEV_NUM8
+
+/* ECAM definitions */
+#define PCI_CFG_ECAM_BUS_NUM   20
+#define PCI_CFG_ECAM_DEV_NUM   12
+
+/* Invalid device/function value */
+#define PCI_CFG_INVALID_DEVFN  0x
+
+/**
+ * pci_cfg_map_bus_cam - Get the CAM based configuration space address
+ * @bus: PCI Bus pointer
+ * @devfn: Device/Function
+ * @where: Offset from base
+ *
+ * Return: Configuration Space address
+ */
+static void __iomem *pci_cfg_map_bus_cam(struct pci_bus *bus,
+unsigned int devfn,
+int where)
+{
+   struct pci_sys_data *sys = bus-sysdata;
+   struct pci_cfg_windows *cfg = sys-private_data;
+   resource_size_t idx = bus-number - cfg-bus_range.start;
+
+   return cfg-win[idx] + ((devfn  PCI_CFG_CAM_DEV_NUM) | where);
+}
+
+/**
+ * pci_cfg_map_bus_ecam - Get the ECAM based configuration space address
+ * @bus: PCI bus pointer
+ * @devfn: Device/Function
+ * @where: Offset from base
+ *
+ * Return: Configuration space address
+ */
+static void __iomem *pci_cfg_map_bus_ecam(struct pci_bus *bus,
+ unsigned int devfn,
+ int where)
+{
+   struct pci_sys_data *sys = bus-sysdata;
+   struct pci_cfg_windows *cfg = sys-private_data;
+   resource_size_t idx = bus-number - cfg-bus_range.start;
+
+   return cfg-win[idx] + ((devfn  PCI_CFG_ECAM_DEV_NUM) | where);
+}
+
+/**
+ * pci_cfg_read - Read configuration space
+ * @bus: PCI bus pointer
+ * @devfn: Device/function
+ * @where: Offset from base
+ * @size: Byte/word/dword
+ * @val: Value to be read
+ *
+ * Return: PCIBIOS_SUCCESSFUL on success
+ *PCIBIOS_DEVICE_NOT_FOUND on failure
+ */
+static int pci_cfg_read(struct pci_bus *bus, unsigned int devfn,
+   int where, int size, unsigned int *val)
+{
+   void __iomem *addr;
+   struct pci_sys_data *sys = bus-sysdata;
+   struct pci_cfg_windows *cfg = sys-private_data;
+
+   if (cfg-ops-is_valid_cfg_access) {
+   if (!cfg-ops-is_valid_cfg_access(bus, devfn)) {
+   *val = PCI_CFG_INVALID_DEVFN;
+   return PCIBIOS_DEVICE_NOT_FOUND;
+   }
+   }
+
+   addr = cfg-ops-map_bus(bus, devfn, where);
+
+   switch (size) {
+   case 1:
+   *val = readb(addr);
+   break;
+   case 2:
+   *val = readw(addr);
+   break;
+   default:
+   *val = readl(addr);
+   }
+
+   return PCIBIOS_SUCCESSFUL;
+}
+
+/**
+ * pci_cfg_write - Write configuration space
+ * @bus: PCI bus pointer
+ * @devfn: Device/function
+ * @where: Offset from base
+ * @size: Byte/word/dword
+ * @val: Value to write
+ *
+ * Return: PCIBIOS_SUCCESSFUL on success
+ *PCIBIOS_DEVICE_NOT_FOUND on failure
+ */
+static int pci_cfg_write(struct pci_bus *bus, unsigned int devfn,
+int where, int size, unsigned int val)
+{
+   void __iomem *addr;
+   struct pci_sys_data *sys = bus-sysdata;
+   struct pci_cfg_windows *cfg = sys-private_data;
+
+   if (cfg-ops-is_valid_cfg_access)
+