@@ -15,6 +15,16 @@ config DRM_ETNAVIV
help
DRM driver for Vivante GPUs.
+config DRM_ETNAVIV_PCI_DRIVER
+ bool "enable ETNAVIV PCI driver support"
+ depends on DRM_ETNAVIV
+ depends on PCI
+ default y
+ help
+ Compile in support for PCI GPUs of Vivante.
+ For example, the GC1000 in LS7A1000 and LS2K1000.
+ Say Y if you have such a hardware.
+
config DRM_ETNAVIV_THERMAL
bool "enable ETNAVIV thermal throttling"
depends on DRM_ETNAVIV
@@ -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
@@ -21,6 +21,7 @@
#include "etnaviv_gpu.h"
#include "etnaviv_gem.h"
#include "etnaviv_mmu.h"
+#include "etnaviv_pci_drv.h"
#include "etnaviv_perfmon.h"
/*
@@ -538,7 +539,7 @@ static const struct drm_driver etnaviv_drm_driver = {
static struct etnaviv_drm_private *etna_private_ptr;
-static int etnaviv_drm_bind(struct device *dev, bool component)
+int etnaviv_drm_bind(struct device *dev, bool component)
{
struct etnaviv_drm_private *priv;
struct drm_device *drm;
@@ -588,7 +589,7 @@ static int etnaviv_drm_bind(struct device *dev, bool component)
return ret;
}
-static void etnaviv_drm_unbind(struct device *dev, bool component)
+void etnaviv_drm_unbind(struct device *dev, bool component)
{
struct etnaviv_drm_private *priv = etna_private_ptr;
struct drm_device *drm = priv->drm;
@@ -746,6 +747,10 @@ static int __init etnaviv_init(void)
if (ret != 0)
goto unregister_gpu_driver;
+ ret = etnaviv_register_pci_driver();
+ if (ret != 0)
+ goto unregister_platform_driver;
+
/*
* If the DT contains at least one available GPU device, instantiate
* the DRM platform device.
@@ -763,7 +768,7 @@ static int __init etnaviv_init(void)
break;
}
- return 0;
+ return ret;
unregister_platform_driver:
platform_driver_unregister(&etnaviv_platform_driver);
@@ -778,6 +783,8 @@ static void __exit etnaviv_exit(void)
etnaviv_destroy_platform_device(&etnaviv_platform_device);
platform_driver_unregister(&etnaviv_platform_driver);
platform_driver_unregister(&etnaviv_gpu_driver);
+
+ etnaviv_unregister_pci_driver();
}
module_exit(etnaviv_exit);
@@ -83,6 +83,9 @@ bool etnaviv_cmd_validate_one(struct etnaviv_gpu *gpu,
u32 *stream, unsigned int size,
struct drm_etnaviv_gem_submit_reloc *relocs, unsigned int reloc_size);
+int etnaviv_drm_bind(struct device *dev, bool component);
+void etnaviv_drm_unbind(struct device *dev, bool component);
+
#ifdef CONFIG_DEBUG_FS
void etnaviv_gem_describe_objects(struct etnaviv_drm_private *priv,
struct seq_file *m);
@@ -1866,8 +1866,8 @@ static int etnaviv_gpu_register_irq(struct etnaviv_gpu *gpu, int irq)
/* platform independent */
-static int etnaviv_gpu_driver_create(struct device *dev, void __iomem *mmio,
- int irq, bool component, bool has_clk)
+int etnaviv_gpu_driver_create(struct device *dev, void __iomem *mmio,
+ int irq, bool component, bool has_clk)
{
struct etnaviv_gpu *gpu;
int err;
@@ -1916,7 +1916,7 @@ static int etnaviv_gpu_driver_create(struct device *dev, void __iomem *mmio,
return 0;
}
-static void etnaviv_gpu_driver_destroy(struct device *dev, bool component)
+void etnaviv_gpu_driver_destroy(struct device *dev, bool component)
{
if (component)
component_del(dev, &gpu_ops);
@@ -1967,7 +1967,7 @@ static int etnaviv_gpu_rpm_resume(struct device *dev)
return 0;
}
-static const struct dev_pm_ops etnaviv_gpu_pm_ops = {
+const struct dev_pm_ops etnaviv_gpu_pm_ops = {
RUNTIME_PM_OPS(etnaviv_gpu_rpm_suspend, etnaviv_gpu_rpm_resume, NULL)
};
@@ -209,6 +209,12 @@ void etnaviv_gpu_start_fe(struct etnaviv_gpu *gpu, u32 address, u16 prefetch);
int etnaviv_gpu_bind(struct device *dev, struct device *master, void *data);
void etnaviv_gpu_unbind(struct device *dev, struct device *master, void *data);
+int etnaviv_gpu_driver_create(struct device *dev, void __iomem *mmio,
+ int irq, bool component, bool has_clk);
+
+void etnaviv_gpu_driver_destroy(struct device *dev, bool component);
+
extern struct platform_driver etnaviv_gpu_driver;
+extern const struct dev_pm_ops etnaviv_gpu_pm_ops;
#endif /* __ETNAVIV_GPU_H__ */
new file mode 100644
@@ -0,0 +1,75 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#include <linux/pci.h>
+
+#include "etnaviv_drv.h"
+#include "etnaviv_gpu.h"
+#include "etnaviv_pci_drv.h"
+
+static int etnaviv_pci_probe(struct pci_dev *pdev,
+ const struct pci_device_id *ent)
+{
+ struct device *dev = &pdev->dev;
+ void __iomem *mmio;
+ int ret;
+
+ ret = pcim_enable_device(pdev);
+ if (ret) {
+ dev_err(dev, "failed to enable\n");
+ return ret;
+ }
+
+ pci_set_master(pdev);
+
+ ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32));
+ if (ret)
+ return ret;
+
+ /* Map registers, assume the PCI bar 0 contain the registers */
+ mmio = pcim_iomap(pdev, 0, 0);
+ if (IS_ERR(mmio))
+ return PTR_ERR(mmio);
+
+ ret = etnaviv_gpu_driver_create(dev, mmio, pdev->irq, false, false);
+ if (ret)
+ return ret;
+
+ return etnaviv_drm_bind(dev, false);
+}
+
+static void etnaviv_pci_remove(struct pci_dev *pdev)
+{
+ struct device *dev = &pdev->dev;
+
+ etnaviv_drm_unbind(dev, false);
+
+ etnaviv_gpu_driver_destroy(dev, false);
+
+ pci_clear_master(pdev);
+}
+
+static const struct pci_device_id etnaviv_pci_id_lists[] = {
+ {PCI_VDEVICE(LOONGSON, 0x7a15)},
+ {PCI_VDEVICE(LOONGSON, 0x7a05)},
+ { }
+};
+
+static struct pci_driver etnaviv_pci_driver = {
+ .name = "etnaviv",
+ .id_table = etnaviv_pci_id_lists,
+ .probe = etnaviv_pci_probe,
+ .remove = etnaviv_pci_remove,
+ .driver.pm = pm_ptr(&etnaviv_gpu_pm_ops),
+};
+
+int etnaviv_register_pci_driver(void)
+{
+ return pci_register_driver(&etnaviv_pci_driver);
+}
+
+void etnaviv_unregister_pci_driver(void)
+{
+ pci_unregister_driver(&etnaviv_pci_driver);
+}
+
+MODULE_DEVICE_TABLE(pci, etnaviv_pci_id_lists);
new file mode 100644
@@ -0,0 +1,18 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+#ifndef __ETNAVIV_PCI_DRV_H__
+#define __ETNAVIV_PCI_DRV_H__
+
+#ifdef CONFIG_DRM_ETNAVIV_PCI_DRIVER
+
+int etnaviv_register_pci_driver(void);
+void etnaviv_unregister_pci_driver(void);
+
+#else
+
+int etnaviv_register_pci_driver(void) { return 0; }
+void etnaviv_unregister_pci_driver(void) { }
+
+#endif
+
+#endif