lkml.org 
[lkml]   [2022]   [Apr]   [4]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
From
Subject[PATCH 3/3] drm/etnaviv: add pci device driver support
Date
  There is a Vivante GC1000(V5037)in LS2K1000 and LS7A1000,
the gpu in these chips is a PCI device. This patch provide PCI
device driver support.
__ AMDGPU
LS7A1000 Bridge Chip |__________
+------+ +----------------------------------+ | *** |
| DDR4 | | +---------------+ PCIe Bridge | |--____--_|
+------+ | | PCIe Root Bus |--------------------++++++++-->
|| MC0 | +--+--------+---+ Gen 2.2 x 8 | PCIe x8 Slot
|| | | ______________________ |
+----------+ HT 3.0 | || 0x7a06 | |
| LS3A4000 |<-------->| +---++---+ +------+ +---------+ +------+
| CPU |<-------->| | GC1000 | | LSDC |<->| DDR3 MC |<->| VRAM |
+----------+ | +--------+ +-+--+-+ +---------+ +------+
|| | 0x7a15 | | |
|| MC1 +---------------|--|---------------+
+------+ | |
| DDR4 | +---------+ DVO0 | | DVO1 +--------+
+------+ VGA <--| GM7123C |<------+ +------>| LT8618 |---> HDMI
+---------+ +--------+

LS7A1000 is a bridge chip, this bridge chip typically use
with LS3A4000 (4 core 1.8gHz, Mips64r5) and LS3A5000 (4 core
loongarch 2.5Ghz). While LS2K1000 is a double core 1.0Ghz
Mips64r2 SoC.

LS7A1000/LS2K1000 has a display controller integrated, named lsdc.
After apply this patch, the etnaviv driver can be used on our mips
platform.

Signed-off-by: Sui Jingfeng <15330273260@189.cn>
---
drivers/gpu/drm/etnaviv/Kconfig | 10 +++
drivers/gpu/drm/etnaviv/Makefile | 2 +
drivers/gpu/drm/etnaviv/etnaviv_drv.c | 30 ++++++--
drivers/gpu/drm/etnaviv/etnaviv_gpu.c | 65 ++++++++++++------
drivers/gpu/drm/etnaviv/etnaviv_gpu.h | 4 ++
drivers/gpu/drm/etnaviv/etnaviv_pci_drv.c | 83 +++++++++++++++++++++++
drivers/gpu/drm/etnaviv/etnaviv_pci_drv.h | 15 ++++
7 files changed, 182 insertions(+), 27 deletions(-)
create mode 100644 drivers/gpu/drm/etnaviv/etnaviv_pci_drv.c
create mode 100644 drivers/gpu/drm/etnaviv/etnaviv_pci_drv.h

diff --git a/drivers/gpu/drm/etnaviv/Kconfig b/drivers/gpu/drm/etnaviv/Kconfig
index faa7fc68b009..4b7f630bb990 100644
--- a/drivers/gpu/drm/etnaviv/Kconfig
+++ b/drivers/gpu/drm/etnaviv/Kconfig
@@ -15,6 +15,16 @@ config DRM_ETNAVIV
help
DRM driver for Vivante GPUs.

+config DRM_ETNAVIV_PCI_DRIVER
+ bool "Enable support for PCI GPU core In LS7A1000/LS2K1000"
+ depends on DRM_ETNAVIV
+ depends on PCI
+ depends on MACH_LOONGSON64
+ default y
+ help
+ DRM PCI driver for Vivante GC1000 GPU in LS7A1000 bridge chip
+ and LS2K1000 SoC. If in doubt, say "n".
+
config DRM_ETNAVIV_THERMAL
bool "enable ETNAVIV thermal throttling"
depends on DRM_ETNAVIV
diff --git a/drivers/gpu/drm/etnaviv/Makefile b/drivers/gpu/drm/etnaviv/Makefile
index 46e5ffad69a6..6829e1ebf2db 100644
--- a/drivers/gpu/drm/etnaviv/Makefile
+++ b/drivers/gpu/drm/etnaviv/Makefile
@@ -16,4 +16,6 @@ etnaviv-y := \
etnaviv_perfmon.o \
etnaviv_sched.o

+etnaviv-$(CONFIG_DRM_ETNAVIV_PCI_DRIVER) += etnaviv_pci_drv.o
+
obj-$(CONFIG_DRM_ETNAVIV) += etnaviv.o
diff --git a/drivers/gpu/drm/etnaviv/etnaviv_drv.c b/drivers/gpu/drm/etnaviv/etnaviv_drv.c
index 69d879e623b8..3f612e1a56ff 100644
--- a/drivers/gpu/drm/etnaviv/etnaviv_drv.c
+++ b/drivers/gpu/drm/etnaviv/etnaviv_drv.c
@@ -23,6 +23,10 @@
#include "etnaviv_mmu.h"
#include "etnaviv_perfmon.h"

+#ifdef CONFIG_DRM_ETNAVIV_PCI_DRIVER
+#include "etnaviv_pci_drv.h"
+#endif
+
/*
* DRM operations:
*/
@@ -606,11 +610,13 @@ static int etnaviv_pdev_probe(struct platform_device *pdev)
compare_of, core_node);
}
} else {
- char **names = dev->platform_data;
+ char **names = (char **)dev->platform_data;
unsigned i;

- for (i = 0; names[i]; i++)
+ for (i = 0; names[i]; i++) {
component_match_add(dev, &match, compare_str, names[i]);
+ dev_info(dev, "component match %s added\n", names[i]);
+ }
}

/*
@@ -625,9 +631,9 @@ static int etnaviv_pdev_probe(struct platform_device *pdev)
* bit to make sure we are allocating the command buffers and
* TLBs in the lower 4 GiB address space.
*/
- if (dma_set_mask(&pdev->dev, DMA_BIT_MASK(40)) ||
- dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32))) {
- dev_dbg(&pdev->dev, "No suitable DMA available\n");
+ if (dma_set_mask(dev, DMA_BIT_MASK(40)) ||
+ dma_set_coherent_mask(dev, DMA_BIT_MASK(32))) {
+ dev_dbg(dev, "No suitable DMA available\n");
return -ENODEV;
}

@@ -637,7 +643,7 @@ static int etnaviv_pdev_probe(struct platform_device *pdev)
* GPUs in the system share the same DMA constraints.
*/
if (first_node)
- of_dma_configure(&pdev->dev, first_node, true);
+ of_dma_configure(dev, first_node, true);

return component_master_add_with_match(dev, &etnaviv_master_ops, match);
}
@@ -704,6 +710,12 @@ static int __init etnaviv_init(void)
if (ret != 0)
goto unregister_gpu_driver;

+#ifdef CONFIG_DRM_ETNAVIV_PCI_DRIVER
+ ret = pci_register_driver(&etnaviv_pci_driver);
+ if (ret != 0)
+ goto unregister_platform_driver;
+#endif
+
/*
* If the DT contains at least one available GPU device, instantiate
* the DRM platform device.
@@ -724,6 +736,9 @@ static int __init etnaviv_init(void)
return 0;

unregister_platform_driver:
+#ifdef CONFIG_DRM_ETNAVIV_PCI_DRIVER
+ pci_unregister_driver(&etnaviv_pci_driver);
+#endif
platform_driver_unregister(&etnaviv_platform_driver);
unregister_gpu_driver:
platform_driver_unregister(&etnaviv_gpu_driver);
@@ -734,6 +749,9 @@ module_init(etnaviv_init);
static void __exit etnaviv_exit(void)
{
platform_device_unregister(etnaviv_drm);
+#ifdef CONFIG_DRM_ETNAVIV_PCI_DRIVER
+ pci_unregister_driver(&etnaviv_pci_driver);
+#endif
platform_driver_unregister(&etnaviv_platform_driver);
platform_driver_unregister(&etnaviv_gpu_driver);
}
diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gpu.c b/drivers/gpu/drm/etnaviv/etnaviv_gpu.c
index d607be474aeb..d8ea8c3eea19 100644
--- a/drivers/gpu/drm/etnaviv/etnaviv_gpu.c
+++ b/drivers/gpu/drm/etnaviv/etnaviv_gpu.c
@@ -1800,19 +1800,10 @@ static const struct of_device_id etnaviv_gpu_match[] = {
};
MODULE_DEVICE_TABLE(of, etnaviv_gpu_match);

-static int etnaviv_gpu_platform_probe(struct platform_device *pdev)
+static int etnaviv_gpu_platform_constructor(struct etnaviv_gpu *gpu,
+ struct device *dev)
{
- struct device *dev = &pdev->dev;
- struct etnaviv_gpu *gpu;
- int err;
-
- gpu = devm_kzalloc(dev, sizeof(*gpu), GFP_KERNEL);
- if (!gpu)
- return -ENOMEM;
-
- gpu->dev = &pdev->dev;
- mutex_init(&gpu->lock);
- mutex_init(&gpu->fence_lock);
+ struct platform_device *pdev = to_platform_device(dev);

/* Map registers: */
gpu->mmio = devm_platform_ioremap_resource(pdev, 0);
@@ -1824,7 +1815,28 @@ static int etnaviv_gpu_platform_probe(struct platform_device *pdev)
if (gpu->irq < 0)
return gpu->irq;

- err = devm_request_irq(&pdev->dev, gpu->irq, irq_handler, 0,
+ return 0;
+}
+
+int etnaviv_gpu_probe(struct device *dev,
+ int (*pfn)(struct etnaviv_gpu *gpu, struct device *dev))
+{
+ struct etnaviv_gpu *gpu;
+ int err;
+
+ gpu = devm_kzalloc(dev, sizeof(*gpu), GFP_KERNEL);
+ if (!gpu)
+ return -ENOMEM;
+
+ gpu->dev = dev;
+ mutex_init(&gpu->lock);
+ mutex_init(&gpu->fence_lock);
+
+ err = pfn(gpu, dev);
+ if (err)
+ return err;
+
+ err = devm_request_irq(dev, gpu->irq, irq_handler, 0,
dev_name(gpu->dev), gpu);
if (err) {
dev_err(dev, "failed to request IRQ%u: %d\n", gpu->irq, err);
@@ -1842,26 +1854,37 @@ static int etnaviv_gpu_platform_probe(struct platform_device *pdev)
* autosuspend delay is rather arbitary: no measurements have
* yet been performed to determine an appropriate value.
*/
- pm_runtime_use_autosuspend(gpu->dev);
- pm_runtime_set_autosuspend_delay(gpu->dev, 200);
- pm_runtime_enable(gpu->dev);
+ pm_runtime_use_autosuspend(dev);
+ pm_runtime_set_autosuspend_delay(dev, 200);
+ pm_runtime_enable(dev);

- err = component_add(&pdev->dev, &gpu_ops);
+ err = component_add(dev, &gpu_ops);
if (err < 0) {
- dev_err(&pdev->dev, "failed to register component: %d\n", err);
+ dev_err(dev, "failed to register component: %d\n", err);
return err;
}

return 0;
}

-static int etnaviv_gpu_platform_remove(struct platform_device *pdev)
+static int etnaviv_gpu_platform_probe(struct platform_device *pdev)
{
- component_del(&pdev->dev, &gpu_ops);
- pm_runtime_disable(&pdev->dev);
+ return etnaviv_gpu_probe(&pdev->dev, etnaviv_gpu_platform_constructor);
+}
+
+int etnaviv_gpu_remove(struct device *dev)
+{
+ component_del(dev, &gpu_ops);
+ pm_runtime_disable(dev);
+
return 0;
}

+static int etnaviv_gpu_platform_remove(struct platform_device *pdev)
+{
+ return etnaviv_gpu_remove(&pdev->dev);
+}
+
#ifdef CONFIG_PM
static int etnaviv_gpu_rpm_suspend(struct device *dev)
{
diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gpu.h b/drivers/gpu/drm/etnaviv/etnaviv_gpu.h
index 85eddd492774..4d0554cc1945 100644
--- a/drivers/gpu/drm/etnaviv/etnaviv_gpu.h
+++ b/drivers/gpu/drm/etnaviv/etnaviv_gpu.h
@@ -181,6 +181,10 @@ void etnaviv_gpu_pm_put(struct etnaviv_gpu *gpu);
int etnaviv_gpu_wait_idle(struct etnaviv_gpu *gpu, unsigned int timeout_ms);
void etnaviv_gpu_start_fe(struct etnaviv_gpu *gpu, u32 address, u16 prefetch);

+int etnaviv_gpu_probe(struct device *dev,
+ int (*pfn)(struct etnaviv_gpu *gpu, struct device *dev));
+int etnaviv_gpu_remove(struct device *dev);
+
extern struct platform_driver etnaviv_gpu_driver;

#endif /* __ETNAVIV_GPU_H__ */
diff --git a/drivers/gpu/drm/etnaviv/etnaviv_pci_drv.c b/drivers/gpu/drm/etnaviv/etnaviv_pci_drv.c
new file mode 100644
index 000000000000..8843edd0597b
--- /dev/null
+++ b/drivers/gpu/drm/etnaviv/etnaviv_pci_drv.c
@@ -0,0 +1,83 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2015-2018 Etnaviv Project
+ */
+
+#include <linux/pci.h>
+
+#include "etnaviv_drv.h"
+#include "etnaviv_gpu.h"
+#include "etnaviv_pci_drv.h"
+
+static const char *gpu_device_names[] = {
+ 0,
+ 0, /* MUST end with a NULL here */
+};
+
+static int etnaviv_gpu_pci_constructor(struct etnaviv_gpu *gpu,
+ struct device *dev)
+{
+ struct pci_dev *pdev = to_pci_dev(dev);
+
+ /* gpu bar 0 contain registers */
+ gpu->mmio = devm_ioremap_resource(dev, &pdev->resource[0]);
+ if (IS_ERR(gpu->mmio))
+ return PTR_ERR(gpu->mmio);
+
+ gpu->irq = pdev->irq;
+
+ dev_info(&pdev->dev, "%s:irq=%d\n", __func__, gpu->irq);
+
+ return 0;
+}
+
+static int etnaviv_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+{
+ struct device * const dev = &pdev->dev;
+ int ret;
+
+ ret = pcim_enable_device(pdev);
+ if (ret) {
+ dev_err(dev, "failed to enable this PCI device\n");
+ return ret;
+ }
+
+ pci_set_master(pdev);
+
+ ret = etnaviv_gpu_probe(dev, etnaviv_gpu_pci_constructor);
+ if (ret) {
+ dev_err(dev, "failed to create GPU instance\n");
+ return ret;
+ }
+
+ /* It's 0000:00:06.0 for GC1000 in LS7A1000 */
+ dev_dbg(dev, "name = %s\n", dev_name(dev));
+
+ /* It seems that we have only one gpu core */
+ gpu_device_names[0] = dev_name(dev);
+
+ /* Instantiate the DRM platform device */
+ return etnaviv_create_platform_device("etnaviv",
+ gpu_device_names,
+ ARRAY_SIZE(gpu_device_names));
+}
+
+static void etnaviv_pci_remove(struct pci_dev *pdev)
+{
+ etnaviv_gpu_remove(&pdev->dev);
+}
+
+static const struct pci_device_id etnaviv_pci_id_lists[] = {
+ {0x0014, 0x7a15, PCI_ANY_ID, PCI_ANY_ID, 0, 0, GC1000_IN_LS7A1000},
+ {0x0014, 0x7a05, PCI_ANY_ID, PCI_ANY_ID, 0, 0, GC1000_IN_LS2K1000},
+ {0, 0, 0, 0, 0, 0, 0}
+};
+
+struct pci_driver etnaviv_pci_driver = {
+ .name = "etnaviv",
+ .id_table = etnaviv_pci_id_lists,
+ .probe = etnaviv_pci_probe,
+ .remove = etnaviv_pci_remove,
+};
+
+MODULE_DEVICE_TABLE(pci, etnaviv_pci_id_lists);
diff --git a/drivers/gpu/drm/etnaviv/etnaviv_pci_drv.h b/drivers/gpu/drm/etnaviv/etnaviv_pci_drv.h
new file mode 100644
index 000000000000..5aa54340bff3
--- /dev/null
+++ b/drivers/gpu/drm/etnaviv/etnaviv_pci_drv.h
@@ -0,0 +1,15 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+#ifndef __ETNAVIV_PCI_DRV_H__
+#define __ETNAVIV_PCI_DRV_H__
+
+#include <linux/pci.h>
+
+enum vivante_pci_gpu_family {
+ GC1000_IN_LS7A1000 = 0,
+ GC1000_IN_LS2K1000 = 1,
+ CHIP_LAST,
+};
+
+extern struct pci_driver etnaviv_pci_driver;
+#endif
--
2.25.1
\
 
 \ /
  Last update: 2022-04-04 12:32    [W:0.047 / U:0.548 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site