[RFC 02/16] drm/nouveau: basic support for platform devices

2014-01-31 Thread Alexandre Courbot
The T124 generation of Tegra GPUs uses the Kepler architecture and can
thus be driven by Nouveau. However, they are declared as platform
devices using the Device Tree, and Nouveau has a very strong dependency
on PCI. This patch makes Nouveau core able to handle platform devices as
well as PCI devices.

Commonly-used PCI functions include resource range query and page
mapping. These functions are abstracted so the correct bus type is used
to perform them. Some PCI-dependent code is also disabled when probing a
non-PCI device.

Signed-off-by: Alexandre Courbot 
---
 drivers/gpu/drm/nouveau/core/engine/device/base.c  | 58 +-
 drivers/gpu/drm/nouveau/core/include/core/device.h | 27 ++
 drivers/gpu/drm/nouveau/core/os.h  |  1 +
 drivers/gpu/drm/nouveau/nouveau_abi16.c| 13 -
 drivers/gpu/drm/nouveau/nouveau_bo.c   | 22 
 drivers/gpu/drm/nouveau/nouveau_display.c  |  3 +-
 drivers/gpu/drm/nouveau/nouveau_drm.c  | 53 ++--
 drivers/gpu/drm/nouveau/nouveau_sysfs.c|  8 +--
 drivers/gpu/drm/nouveau/nouveau_ttm.c  | 31 +++-
 9 files changed, 170 insertions(+), 46 deletions(-)

diff --git a/drivers/gpu/drm/nouveau/core/engine/device/base.c 
b/drivers/gpu/drm/nouveau/core/engine/device/base.c
index dd01c6c..a6abb51 100644
--- a/drivers/gpu/drm/nouveau/core/engine/device/base.c
+++ b/drivers/gpu/drm/nouveau/core/engine/device/base.c
@@ -131,8 +131,8 @@ nouveau_devobj_ctor(struct nouveau_object *parent,
if (ret)
return ret;
 
-   mmio_base = pci_resource_start(device->pdev, 0);
-   mmio_size = pci_resource_len(device->pdev, 0);
+   mmio_base = nv_device_resource_start(device, 0);
+   mmio_size = nv_device_resource_len(device, 0);
 
/* translate api disable mask into internal mapping */
disable = args->debug0;
@@ -446,6 +446,60 @@ nouveau_device_dtor(struct nouveau_object *object)
nouveau_engine_destroy(>base);
 }
 
+resource_size_t
+nv_device_resource_start(struct nouveau_device *device, unsigned int bar)
+{
+   if (nv_device_is_pci(device)) {
+   return pci_resource_start(device->pdev, bar);
+   } else {
+   struct resource *res;
+   res = platform_get_resource(device->platformdev,
+   IORESOURCE_MEM, bar);
+   if (!res)
+   return 0;
+   return res->start;
+   }
+}
+
+resource_size_t
+nv_device_resource_len(struct nouveau_device *device, unsigned int bar)
+{
+   if (nv_device_is_pci(device)) {
+   return pci_resource_len(device->pdev, bar);
+   } else {
+   struct resource *res;
+   res = platform_get_resource(device->platformdev,
+   IORESOURCE_MEM, bar);
+   if (!res)
+   return 0;
+   return resource_size(res);
+   }
+}
+
+dma_addr_t
+nv_device_map_page(struct nouveau_device *device, struct page *page) {
+   dma_addr_t ret;
+
+   if (nv_device_is_pci(device)) {
+   ret = pci_map_page(device->pdev, page, 0, PAGE_SIZE,
+  PCI_DMA_BIDIRECTIONAL);
+   if (pci_dma_mapping_error(device->pdev, ret))
+   ret = 0;
+   } else {
+   ret = page_to_phys(page);
+   }
+
+   return ret;
+}
+
+void
+nv_device_unmap_page(struct nouveau_device *device, dma_addr_t addr)
+{
+   if (nv_device_is_pci(device))
+   pci_unmap_page(device->pdev, addr, PAGE_SIZE,
+  PCI_DMA_BIDIRECTIONAL);
+}
+
 static struct nouveau_oclass
 nouveau_device_oclass = {
.handle = NV_ENGINE(DEVICE, 0x00),
diff --git a/drivers/gpu/drm/nouveau/core/include/core/device.h 
b/drivers/gpu/drm/nouveau/core/include/core/device.h
index 7b8ea22..23f4a25 100644
--- a/drivers/gpu/drm/nouveau/core/include/core/device.h
+++ b/drivers/gpu/drm/nouveau/core/include/core/device.h
@@ -65,6 +65,7 @@ struct nouveau_device {
struct list_head head;
 
struct pci_dev *pdev;
+   struct platform_device *platformdev;
u64 handle;
 
const char *cfgopt;
@@ -140,4 +141,30 @@ nv_device_match(struct nouveau_object *object, u16 dev, 
u16 ven, u16 sub)
   device->pdev->subsystem_device == sub;
 }
 
+static inline bool
+nv_device_is_pci(struct nouveau_device *device)
+{
+   return device->pdev != NULL;
+}
+
+static inline struct device *
+nv_device_base(struct nouveau_device *device)
+{
+   return nv_device_is_pci(device) ? >pdev->dev :
+ >platformdev->dev;
+}
+
+resource_size_t
+nv_device_resource_start(struct nouveau_device *device, unsigned int bar);
+
+resource_size_t
+nv_device_resource_len(struct nouveau_device *device, unsigned int bar);
+
+dma_addr_t

[RFC 02/16] drm/nouveau: basic support for platform devices

2014-01-31 Thread Alexandre Courbot
The T124 generation of Tegra GPUs uses the Kepler architecture and can
thus be driven by Nouveau. However, they are declared as platform
devices using the Device Tree, and Nouveau has a very strong dependency
on PCI. This patch makes Nouveau core able to handle platform devices as
well as PCI devices.

Commonly-used PCI functions include resource range query and page
mapping. These functions are abstracted so the correct bus type is used
to perform them. Some PCI-dependent code is also disabled when probing a
non-PCI device.

Signed-off-by: Alexandre Courbot acour...@nvidia.com
---
 drivers/gpu/drm/nouveau/core/engine/device/base.c  | 58 +-
 drivers/gpu/drm/nouveau/core/include/core/device.h | 27 ++
 drivers/gpu/drm/nouveau/core/os.h  |  1 +
 drivers/gpu/drm/nouveau/nouveau_abi16.c| 13 -
 drivers/gpu/drm/nouveau/nouveau_bo.c   | 22 
 drivers/gpu/drm/nouveau/nouveau_display.c  |  3 +-
 drivers/gpu/drm/nouveau/nouveau_drm.c  | 53 ++--
 drivers/gpu/drm/nouveau/nouveau_sysfs.c|  8 +--
 drivers/gpu/drm/nouveau/nouveau_ttm.c  | 31 +++-
 9 files changed, 170 insertions(+), 46 deletions(-)

diff --git a/drivers/gpu/drm/nouveau/core/engine/device/base.c 
b/drivers/gpu/drm/nouveau/core/engine/device/base.c
index dd01c6c..a6abb51 100644
--- a/drivers/gpu/drm/nouveau/core/engine/device/base.c
+++ b/drivers/gpu/drm/nouveau/core/engine/device/base.c
@@ -131,8 +131,8 @@ nouveau_devobj_ctor(struct nouveau_object *parent,
if (ret)
return ret;
 
-   mmio_base = pci_resource_start(device-pdev, 0);
-   mmio_size = pci_resource_len(device-pdev, 0);
+   mmio_base = nv_device_resource_start(device, 0);
+   mmio_size = nv_device_resource_len(device, 0);
 
/* translate api disable mask into internal mapping */
disable = args-debug0;
@@ -446,6 +446,60 @@ nouveau_device_dtor(struct nouveau_object *object)
nouveau_engine_destroy(device-base);
 }
 
+resource_size_t
+nv_device_resource_start(struct nouveau_device *device, unsigned int bar)
+{
+   if (nv_device_is_pci(device)) {
+   return pci_resource_start(device-pdev, bar);
+   } else {
+   struct resource *res;
+   res = platform_get_resource(device-platformdev,
+   IORESOURCE_MEM, bar);
+   if (!res)
+   return 0;
+   return res-start;
+   }
+}
+
+resource_size_t
+nv_device_resource_len(struct nouveau_device *device, unsigned int bar)
+{
+   if (nv_device_is_pci(device)) {
+   return pci_resource_len(device-pdev, bar);
+   } else {
+   struct resource *res;
+   res = platform_get_resource(device-platformdev,
+   IORESOURCE_MEM, bar);
+   if (!res)
+   return 0;
+   return resource_size(res);
+   }
+}
+
+dma_addr_t
+nv_device_map_page(struct nouveau_device *device, struct page *page) {
+   dma_addr_t ret;
+
+   if (nv_device_is_pci(device)) {
+   ret = pci_map_page(device-pdev, page, 0, PAGE_SIZE,
+  PCI_DMA_BIDIRECTIONAL);
+   if (pci_dma_mapping_error(device-pdev, ret))
+   ret = 0;
+   } else {
+   ret = page_to_phys(page);
+   }
+
+   return ret;
+}
+
+void
+nv_device_unmap_page(struct nouveau_device *device, dma_addr_t addr)
+{
+   if (nv_device_is_pci(device))
+   pci_unmap_page(device-pdev, addr, PAGE_SIZE,
+  PCI_DMA_BIDIRECTIONAL);
+}
+
 static struct nouveau_oclass
 nouveau_device_oclass = {
.handle = NV_ENGINE(DEVICE, 0x00),
diff --git a/drivers/gpu/drm/nouveau/core/include/core/device.h 
b/drivers/gpu/drm/nouveau/core/include/core/device.h
index 7b8ea22..23f4a25 100644
--- a/drivers/gpu/drm/nouveau/core/include/core/device.h
+++ b/drivers/gpu/drm/nouveau/core/include/core/device.h
@@ -65,6 +65,7 @@ struct nouveau_device {
struct list_head head;
 
struct pci_dev *pdev;
+   struct platform_device *platformdev;
u64 handle;
 
const char *cfgopt;
@@ -140,4 +141,30 @@ nv_device_match(struct nouveau_object *object, u16 dev, 
u16 ven, u16 sub)
   device-pdev-subsystem_device == sub;
 }
 
+static inline bool
+nv_device_is_pci(struct nouveau_device *device)
+{
+   return device-pdev != NULL;
+}
+
+static inline struct device *
+nv_device_base(struct nouveau_device *device)
+{
+   return nv_device_is_pci(device) ? device-pdev-dev :
+ device-platformdev-dev;
+}
+
+resource_size_t
+nv_device_resource_start(struct nouveau_device *device, unsigned int bar);
+
+resource_size_t
+nv_device_resource_len(struct nouveau_device *device, unsigned int bar);
+
+dma_addr_t