[v8,6/8] drm/etnaviv: add driver support for the PCI devices
Commit Message
From: Sui Jingfeng <suijingfeng@loongson.cn>
This patch adds PCI driver support on top of what we already have. Take
the GC1000 in LS7A1000/LS2K1000 as the first instance of the PCI device
driver. There is only one GPU core for the GC1000 in the LS7A1000 and
LS2K1000. Therefore, component frameworks can be avoided.
Cc: Lucas Stach <l.stach@pengutronix.de>
Cc: Christian Gmeiner <christian.gmeiner@gmail.com>
Cc: Philipp Zabel <p.zabel@pengutronix.de>
Cc: Bjorn Helgaas <bhelgaas@google.com>
Cc: Daniel Vetter <daniel@ffwll.ch>
Signed-off-by: Sui Jingfeng <suijingfeng@loongson.cn>
---
drivers/gpu/drm/etnaviv/Kconfig | 10 +++
drivers/gpu/drm/etnaviv/Makefile | 2 +
drivers/gpu/drm/etnaviv/etnaviv_drv.c | 20 +++++-
drivers/gpu/drm/etnaviv/etnaviv_drv.h | 3 +
drivers/gpu/drm/etnaviv/etnaviv_gpu.c | 8 +--
drivers/gpu/drm/etnaviv/etnaviv_gpu.h | 6 ++
drivers/gpu/drm/etnaviv/etnaviv_pci_drv.c | 75 +++++++++++++++++++++++
drivers/gpu/drm/etnaviv/etnaviv_pci_drv.h | 9 +++
8 files changed, 126 insertions(+), 7 deletions(-)
create mode 100644 drivers/gpu/drm/etnaviv/etnaviv_pci_drv.c
create mode 100644 drivers/gpu/drm/etnaviv/etnaviv_pci_drv.h
Comments
On Wed, Jun 07, 2023 at 06:55:49PM +0800, Sui Jingfeng wrote:
> From: Sui Jingfeng <suijingfeng@loongson.cn>
>
> This patch adds PCI driver support on top of what we already have. Take
> the GC1000 in LS7A1000/LS2K1000 as the first instance of the PCI device
> driver. There is only one GPU core for the GC1000 in the LS7A1000 and
> LS2K1000. Therefore, component frameworks can be avoided.
> +#ifdef CONFIG_DRM_ETNAVIV_PCI_DRIVER
> +#include "etnaviv_pci_drv.h"
> +#endif
With trivial stubs for etnaviv_register_pci_driver() and
etnaviv_unregister_pci_driver(), I think you could get rid of all
these #ifdefs.
> +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 +750,12 @@ static int __init etnaviv_init(void)
> if (ret != 0)
> goto unregister_gpu_driver;
>
> +#ifdef CONFIG_DRM_ETNAVIV_PCI_DRIVER
> + ret = etnaviv_register_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.
> @@ -763,7 +773,7 @@ static int __init etnaviv_init(void)
> break;
> }
>
> - return 0;
> + return ret;
>
> unregister_platform_driver:
> platform_driver_unregister(&etnaviv_platform_driver);
> @@ -778,6 +788,10 @@ 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);
> +
> +#ifdef CONFIG_DRM_ETNAVIV_PCI_DRIVER
> + etnaviv_unregister_pci_driver();
> +#endif
> +static const struct pci_device_id etnaviv_pci_id_lists[] = {
> + {PCI_VENDOR_ID_LOONGSON, 0x7a15, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
> + {PCI_VENDOR_ID_LOONGSON, 0x7a05, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
PCI_VDEVICE()
Bjorn
Hi,
On 2023/6/9 01:32, Bjorn Helgaas wrote:
> On Wed, Jun 07, 2023 at 06:55:49PM +0800, Sui Jingfeng wrote:
>> From: Sui Jingfeng <suijingfeng@loongson.cn>
>>
>> This patch adds PCI driver support on top of what we already have. Take
>> the GC1000 in LS7A1000/LS2K1000 as the first instance of the PCI device
>> driver. There is only one GPU core for the GC1000 in the LS7A1000 and
>> LS2K1000. Therefore, component frameworks can be avoided.
>> +#ifdef CONFIG_DRM_ETNAVIV_PCI_DRIVER
>> +#include "etnaviv_pci_drv.h"
>> +#endif
> With trivial stubs for etnaviv_register_pci_driver() and
> etnaviv_unregister_pci_driver(), I think you could get rid of all
> these #ifdefs.
OK, then, I will try to add dummy implement at etnaviv_pci_drv.h,
Thanks.
>> +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 +750,12 @@ static int __init etnaviv_init(void)
>> if (ret != 0)
>> goto unregister_gpu_driver;
>>
>> +#ifdef CONFIG_DRM_ETNAVIV_PCI_DRIVER
>> + ret = etnaviv_register_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.
>> @@ -763,7 +773,7 @@ static int __init etnaviv_init(void)
>> break;
>> }
>>
>> - return 0;
>> + return ret;
>>
>> unregister_platform_driver:
>> platform_driver_unregister(&etnaviv_platform_driver);
>> @@ -778,6 +788,10 @@ 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);
>> +
>> +#ifdef CONFIG_DRM_ETNAVIV_PCI_DRIVER
>> + etnaviv_unregister_pci_driver();
>> +#endif
>> +static const struct pci_device_id etnaviv_pci_id_lists[] = {
>> + {PCI_VENDOR_ID_LOONGSON, 0x7a15, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
>> + {PCI_VENDOR_ID_LOONGSON, 0x7a05, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
> PCI_VDEVICE()
This make it impossible to hook device-specific data in the future.
But currently there no device specific data associated with the 0x7a05 and 0x7a15,
so it's acceptable for now. Thanks.
> Bjorn
On Fri, Jun 09, 2023 at 09:37:02AM +0800, Sui Jingfeng wrote:
> On 2023/6/9 01:32, Bjorn Helgaas wrote:
> > On Wed, Jun 07, 2023 at 06:55:49PM +0800, Sui Jingfeng wrote:
> > > From: Sui Jingfeng <suijingfeng@loongson.cn>
> > >
> > > This patch adds PCI driver support on top of what we already have. Take
> > > the GC1000 in LS7A1000/LS2K1000 as the first instance of the PCI device
> > > driver. There is only one GPU core for the GC1000 in the LS7A1000 and
> > > LS2K1000. Therefore, component frameworks can be avoided.
> > > + {PCI_VENDOR_ID_LOONGSON, 0x7a15, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
> > > + {PCI_VENDOR_ID_LOONGSON, 0x7a05, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
> >
> > PCI_VDEVICE()
>
> This make it impossible to hook device-specific data in the future.
>
> But currently there no device specific data associated with the
> 0x7a05 and 0x7a15,
>
> so it's acceptable for now. Thanks.
Haha, ISTR having this conversation before, sorry for repeating it.
Indeed, it's fine as-is. But PCI_VDEVICE() actually *does* allow for
vendor-specific data because it doesn't include the data element,
which defaults to zero if you don't specify it.
So for example, drivers/net/ethernet/realtek/r8169_main.c has this:
{ PCI_VDEVICE(REALTEK, 0x8129) },
{ PCI_VDEVICE(REALTEK, 0x8136), RTL_CFG_NO_GBIT },
where 0x8129 has no driver_data (it defaults to zero), but 0x8136
does.
Bjorn
@@ -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
@@ -23,6 +23,10 @@
#include "etnaviv_mmu.h"
#include "etnaviv_perfmon.h"
+#ifdef CONFIG_DRM_ETNAVIV_PCI_DRIVER
+#include "etnaviv_pci_drv.h"
+#endif
+
/*
* etnaviv private data construction and destructions:
*/
@@ -538,7 +542,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 +592,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 +750,12 @@ static int __init etnaviv_init(void)
if (ret != 0)
goto unregister_gpu_driver;
+#ifdef CONFIG_DRM_ETNAVIV_PCI_DRIVER
+ ret = etnaviv_register_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.
@@ -763,7 +773,7 @@ static int __init etnaviv_init(void)
break;
}
- return 0;
+ return ret;
unregister_platform_driver:
platform_driver_unregister(&etnaviv_platform_driver);
@@ -778,6 +788,10 @@ 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);
+
+#ifdef CONFIG_DRM_ETNAVIV_PCI_DRIVER
+ etnaviv_unregister_pci_driver();
+#endif
}
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);
@@ -1868,8 +1868,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;
@@ -1918,7 +1918,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);
@@ -1969,7 +1969,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_VENDOR_ID_LOONGSON, 0x7a15, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_LOONGSON, 0x7a05, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ { }
+};
+
+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,9 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+#ifndef __ETNAVIV_PCI_DRV_H__
+#define __ETNAVIV_PCI_DRV_H__
+
+int etnaviv_register_pci_driver(void);
+void etnaviv_unregister_pci_driver(void);
+
+#endif