Commit e396ecd1 authored by Alexandre Courbot's avatar Alexandre Courbot Committed by Ben Skeggs

drm/nouveau/platform: allow to specify the IOMMU bit

Current Tegra code taking advantage of the IOMMU assumes a hardcoded
value for the IOMMU bit. Make it a platform property instead for
flexibility.

v2 (Ben Skeggs): remove nvkm dependence on drm structures
Signed-off-by: default avatarAlexandre Courbot <acourbot@nvidia.com>
Signed-off-by: default avatarBen Skeggs <bskeggs@redhat.com>
parent 69c49382
...@@ -27,6 +27,7 @@ ...@@ -27,6 +27,7 @@
#include <linux/agp_backend.h> #include <linux/agp_backend.h>
#include <linux/reset.h> #include <linux/reset.h>
#include <linux/iommu.h> #include <linux/iommu.h>
#include <linux/of_device.h>
#include <asm/unaligned.h> #include <asm/unaligned.h>
......
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
#include <core/mm.h> #include <core/mm.h>
struct nvkm_device_tegra { struct nvkm_device_tegra {
const struct nvkm_device_tegra_func *func;
struct nvkm_device device; struct nvkm_device device;
struct platform_device *pdev; struct platform_device *pdev;
int irq; int irq;
...@@ -28,7 +29,17 @@ struct nvkm_device_tegra { ...@@ -28,7 +29,17 @@ struct nvkm_device_tegra {
int gpu_speedo; int gpu_speedo;
}; };
int nvkm_device_tegra_new(struct platform_device *, struct nvkm_device_tegra_func {
/*
* If an IOMMU is used, indicates which address bit will trigger a
* IOMMU translation when set (when this bit is not set, IOMMU is
* bypassed). A value of 0 means an IOMMU is never used.
*/
u8 iommu_bit;
};
int nvkm_device_tegra_new(const struct nvkm_device_tegra_func *,
struct platform_device *,
const char *cfg, const char *dbg, const char *cfg, const char *dbg,
bool detect, bool mmio, u64 subdev_mask, bool detect, bool mmio, u64 subdev_mask,
struct nvkm_device **); struct nvkm_device **);
......
...@@ -1028,13 +1028,14 @@ nouveau_drm_pci_driver = { ...@@ -1028,13 +1028,14 @@ nouveau_drm_pci_driver = {
}; };
struct drm_device * struct drm_device *
nouveau_platform_device_create(struct platform_device *pdev, nouveau_platform_device_create(const struct nvkm_device_tegra_func *func,
struct platform_device *pdev,
struct nvkm_device **pdevice) struct nvkm_device **pdevice)
{ {
struct drm_device *drm; struct drm_device *drm;
int err; int err;
err = nvkm_device_tegra_new(pdev, nouveau_config, nouveau_debug, err = nvkm_device_tegra_new(func, pdev, nouveau_config, nouveau_debug,
true, true, ~0ULL, pdevice); true, true, ~0ULL, pdevice);
if (err) if (err)
goto err_free; goto err_free;
......
...@@ -178,8 +178,11 @@ nouveau_drm(struct drm_device *dev) ...@@ -178,8 +178,11 @@ nouveau_drm(struct drm_device *dev)
int nouveau_pmops_suspend(struct device *); int nouveau_pmops_suspend(struct device *);
int nouveau_pmops_resume(struct device *); int nouveau_pmops_resume(struct device *);
#include <nvkm/core/tegra.h>
struct drm_device * struct drm_device *
nouveau_platform_device_create(struct platform_device *, struct nvkm_device **); nouveau_platform_device_create(const struct nvkm_device_tegra_func *,
struct platform_device *, struct nvkm_device **);
void nouveau_drm_device_remove(struct drm_device *dev); void nouveau_drm_device_remove(struct drm_device *dev);
#define NV_PRINTK(l,c,f,a...) do { \ #define NV_PRINTK(l,c,f,a...) do { \
......
...@@ -23,11 +23,14 @@ ...@@ -23,11 +23,14 @@
static int nouveau_platform_probe(struct platform_device *pdev) static int nouveau_platform_probe(struct platform_device *pdev)
{ {
const struct nvkm_device_tegra_func *func;
struct nvkm_device *device; struct nvkm_device *device;
struct drm_device *drm; struct drm_device *drm;
int ret; int ret;
drm = nouveau_platform_device_create(pdev, &device); func = of_device_get_match_data(&pdev->dev);
drm = nouveau_platform_device_create(func, pdev, &device);
if (IS_ERR(drm)) if (IS_ERR(drm))
return PTR_ERR(drm); return PTR_ERR(drm);
...@@ -48,9 +51,19 @@ static int nouveau_platform_remove(struct platform_device *pdev) ...@@ -48,9 +51,19 @@ static int nouveau_platform_remove(struct platform_device *pdev)
} }
#if IS_ENABLED(CONFIG_OF) #if IS_ENABLED(CONFIG_OF)
static const struct nvkm_device_tegra_func gk20a_platform_data = {
.iommu_bit = 34,
};
static const struct of_device_id nouveau_platform_match[] = { static const struct of_device_id nouveau_platform_match[] = {
{ .compatible = "nvidia,gk20a" }, {
{ .compatible = "nvidia,gm20b" }, .compatible = "nvidia,gk20a",
.data = &gk20a_platform_data,
},
{
.compatible = "nvidia,gm20b",
.data = &gk20a_platform_data,
},
{ } { }
}; };
......
...@@ -85,6 +85,9 @@ nvkm_device_tegra_probe_iommu(struct nvkm_device_tegra *tdev) ...@@ -85,6 +85,9 @@ nvkm_device_tegra_probe_iommu(struct nvkm_device_tegra *tdev)
unsigned long pgsize_bitmap; unsigned long pgsize_bitmap;
int ret; int ret;
if (!tdev->func->iommu_bit)
return;
mutex_init(&tdev->iommu.mutex); mutex_init(&tdev->iommu.mutex);
if (iommu_present(&platform_bus_type)) { if (iommu_present(&platform_bus_type)) {
...@@ -114,7 +117,8 @@ nvkm_device_tegra_probe_iommu(struct nvkm_device_tegra *tdev) ...@@ -114,7 +117,8 @@ nvkm_device_tegra_probe_iommu(struct nvkm_device_tegra *tdev)
goto free_domain; goto free_domain;
ret = nvkm_mm_init(&tdev->iommu.mm, 0, ret = nvkm_mm_init(&tdev->iommu.mm, 0,
(1ULL << 40) >> tdev->iommu.pgshift, 1); (1ULL << tdev->func->iommu_bit) >>
tdev->iommu.pgshift, 1);
if (ret) if (ret)
goto detach_device; goto detach_device;
} }
...@@ -237,7 +241,8 @@ nvkm_device_tegra_func = { ...@@ -237,7 +241,8 @@ nvkm_device_tegra_func = {
}; };
int int
nvkm_device_tegra_new(struct platform_device *pdev, nvkm_device_tegra_new(const struct nvkm_device_tegra_func *func,
struct platform_device *pdev,
const char *cfg, const char *dbg, const char *cfg, const char *dbg,
bool detect, bool mmio, u64 subdev_mask, bool detect, bool mmio, u64 subdev_mask,
struct nvkm_device **pdevice) struct nvkm_device **pdevice)
...@@ -248,6 +253,7 @@ nvkm_device_tegra_new(struct platform_device *pdev, ...@@ -248,6 +253,7 @@ nvkm_device_tegra_new(struct platform_device *pdev,
if (!(tdev = kzalloc(sizeof(*tdev), GFP_KERNEL))) if (!(tdev = kzalloc(sizeof(*tdev), GFP_KERNEL)))
return -ENOMEM; return -ENOMEM;
*pdevice = &tdev->device; *pdevice = &tdev->device;
tdev->func = func;
tdev->pdev = pdev; tdev->pdev = pdev;
tdev->irq = -1; tdev->irq = -1;
...@@ -285,7 +291,8 @@ nvkm_device_tegra_new(struct platform_device *pdev, ...@@ -285,7 +291,8 @@ nvkm_device_tegra_new(struct platform_device *pdev,
} }
#else #else
int int
nvkm_device_tegra_new(struct platform_device *pdev, nvkm_device_tegra_new(const struct nvkm_device_tegra_func *func,
struct platform_device *pdev,
const char *cfg, const char *dbg, const char *cfg, const char *dbg,
bool detect, bool mmio, u64 subdev_mask, bool detect, bool mmio, u64 subdev_mask,
struct nvkm_device **pdevice) struct nvkm_device **pdevice)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment