From: Tomasz Jankowski <tomasz1.jankow...@intel.com>

Setup MMU in the driver with a new memory component.

Signed-off-by: Tomasz Jankowski <tomasz1.jankow...@intel.com>
Tested-by: Mikolaj Grzybowski <mikolajx.grzybow...@intel.com>
Co-developed-by: Jianxun Zhang <jianxun.zh...@linux.intel.com>
Signed-off-by: Jianxun Zhang <jianxun.zh...@linux.intel.com>
Co-developed-by: Maciej Kwapulinski <maciej.kwapulin...@linux.intel.com>
Signed-off-by: Maciej Kwapulinski <maciej.kwapulin...@linux.intel.com>
---
 drivers/gpu/drm/gna/Kbuild       |  2 +-
 drivers/gpu/drm/gna/gna_device.c |  7 +++
 drivers/gpu/drm/gna/gna_device.h |  8 ++++
 drivers/gpu/drm/gna/gna_hw.h     | 53 ++++++++++++++++++++++
 drivers/gpu/drm/gna/gna_mem.c    | 78 ++++++++++++++++++++++++++++++++
 drivers/gpu/drm/gna/gna_mem.h    | 50 ++++++++++++++++++++
 drivers/gpu/drm/gna/gna_pci.c    | 70 ++++++++++++++++++++++++++++
 7 files changed, 267 insertions(+), 1 deletion(-)
 create mode 100644 drivers/gpu/drm/gna/gna_mem.c
 create mode 100644 drivers/gpu/drm/gna/gna_mem.h

diff --git a/drivers/gpu/drm/gna/Kbuild b/drivers/gpu/drm/gna/Kbuild
index 00e8d6a2c49c..2bda61c61f45 100644
--- a/drivers/gpu/drm/gna/Kbuild
+++ b/drivers/gpu/drm/gna/Kbuild
@@ -1,5 +1,5 @@
 # SPDX-License-Identifier: GPL-2.0-only
 
-gna-y := gna_device.o gna_pci.o
+gna-y := gna_device.o gna_mem.o gna_pci.o
 
 obj-$(CONFIG_DRM_GNA) += gna.o
diff --git a/drivers/gpu/drm/gna/gna_device.c b/drivers/gpu/drm/gna/gna_device.c
index 1f357221a603..f1724cbe3963 100644
--- a/drivers/gpu/drm/gna/gna_device.c
+++ b/drivers/gpu/drm/gna/gna_device.c
@@ -63,6 +63,13 @@ int gna_probe(struct device *parent, struct gna_dev_info 
*dev_info, void __iomem
        bld_reg = gna_reg_read(gna_priv, GNA_MMIO_IBUFFS);
        gna_priv->hw_info.in_buf_s = bld_reg & GENMASK(7, 0);
 
+       err = gna_mmu_init(gna_priv);
+       if (err)
+               return err;
+
+       dev_dbg(parent, "maximum memory size %llu num pd %d\n",
+               gna_priv->info.max_hw_mem, gna_priv->info.num_pagetables);
+
        dev_set_drvdata(parent, drm_dev);
 
        err = gna_drm_dev_init(drm_dev);
diff --git a/drivers/gpu/drm/gna/gna_device.h b/drivers/gpu/drm/gna/gna_device.h
index e42f167b62a0..d2357954b245 100644
--- a/drivers/gpu/drm/gna/gna_device.h
+++ b/drivers/gpu/drm/gna/gna_device.h
@@ -10,6 +10,7 @@
 #include <linux/types.h>
 
 #include "gna_hw.h"
+#include "gna_mem.h"
 
 #define DRIVER_NAME            "gna"
 #define DRIVER_DESC            "Intel(R) Gaussian & Neural Accelerator 
(Intel(R) GNA)"
@@ -28,6 +29,8 @@ struct gna_device {
        void __iomem *iobase;
        struct gna_dev_info info;
        struct gna_hw_info hw_info;
+
+       struct gna_mmu_object mmu;
 };
 
 int gna_probe(struct device *parent, struct gna_dev_info *dev_info, void 
__iomem *iobase);
@@ -36,4 +39,9 @@ static inline u32 gna_reg_read(struct gna_device *gna_priv, 
u32 reg)
        return readl(gna_priv->iobase + reg);
 }
 
+static inline struct device *gna_dev(struct gna_device *gna_priv)
+{
+       return gna_priv->drm.dev;
+}
+
 #endif /* __GNA_DEVICE_H__ */
diff --git a/drivers/gpu/drm/gna/gna_hw.h b/drivers/gpu/drm/gna/gna_hw.h
index e858b76606fc..514166a87c4d 100644
--- a/drivers/gpu/drm/gna/gna_hw.h
+++ b/drivers/gpu/drm/gna/gna_hw.h
@@ -6,9 +6,60 @@
 
 #include <linux/mm_types.h>
 
+#define GNA_FEATURES                                           \
+       .max_hw_mem = 256 * 1024 * 1024,                        \
+               .num_pagetables = 64,                           \
+               .num_page_entries = PAGE_SIZE / sizeof(u32),    \
+               /* desc_info all in bytes */                    \
+               .desc_info = {                                  \
+               .rsvd_size = 256,                               \
+               .cfg_size = 256,                                \
+               .desc_size = 784,                               \
+               .mmu_info = {                                   \
+                       .vamax_size = 4,                        \
+                       .rsvd_size = 12,                        \
+                       .pd_size = 4 * 64,                      \
+               },                                              \
+       }
+
+#define GNA_GEN1_FEATURES                      \
+       GNA_FEATURES,                           \
+               .max_layer_count = 1024
+
+#define GNA_GEN2_FEATURES                      \
+       GNA_FEATURES,                           \
+               .max_layer_count = 4096
+
+#define GNA_DEV_HWID_CNL       0x5A11
+#define GNA_DEV_HWID_EHL       0x4511
+#define GNA_DEV_HWID_GLK       0x3190
+#define GNA_DEV_HWID_ICL       0x8A11
+#define GNA_DEV_HWID_JSL       0x4E11
+#define GNA_DEV_HWID_TGL       0x9A11
+#define GNA_DEV_HWID_RKL       0x4C11
+#define GNA_DEV_HWID_ADL       0x464F
+#define GNA_DEV_HWID_RPL       0xA74F
+#define GNA_DEV_HWID_MTL       0x7E4C
+
 /* GNA MMIO registers */
 #define GNA_MMIO_IBUFFS                0xB4
 
+#define GNA_PGDIRN_LEN                 64
+#define GNA_PGDIR_INVALID              1
+
+struct gna_mmu_info {
+       u32 vamax_size;
+       u32 rsvd_size;
+       u32 pd_size;
+};
+
+struct gna_desc_info {
+       u32 rsvd_size;
+       u32 cfg_size;
+       u32 desc_size;
+       struct gna_mmu_info mmu_info;
+};
+
 struct gna_hw_info {
        u8 in_buf_s;
 };
@@ -19,6 +70,8 @@ struct gna_dev_info {
        u32 num_page_entries;
        u32 max_layer_count;
        u64 max_hw_mem;
+
+       struct gna_desc_info desc_info;
 };
 
 #endif // __GNA_HW_H__
diff --git a/drivers/gpu/drm/gna/gna_mem.c b/drivers/gpu/drm/gna/gna_mem.c
new file mode 100644
index 000000000000..21e266583e27
--- /dev/null
+++ b/drivers/gpu/drm/gna/gna_mem.c
@@ -0,0 +1,78 @@
+// SPDX-License-Identifier: GPL-2.0-only
+// Copyright(c) 2017-2022 Intel Corporation
+
+#include <drm/drm_managed.h>
+
+#include <linux/device.h>
+#include <linux/dma-mapping.h>
+#include <linux/math.h>
+#include <linux/mm.h>
+
+#include "gna_device.h"
+#include "gna_mem.h"
+
+static void gna_mmu_set(struct gna_device *gna_priv)
+{
+       struct gna_mmu_object *mmu;
+       dma_addr_t pagetable_dma;
+       u32 *pgdirn;
+       int i;
+
+       mmu = &gna_priv->mmu;
+
+       pgdirn = mmu->hwdesc->mmu.pagedir_n;
+
+       for (i = 0; i < mmu->num_pagetables; i++) {
+               pagetable_dma = mmu->pagetables_dma[i];
+               pgdirn[i] = pagetable_dma >> PAGE_SHIFT;
+       }
+
+       for (; i < GNA_PGDIRN_LEN; i++)
+               pgdirn[i] = GNA_PGDIR_INVALID;
+}
+
+/* descriptor and page tables allocation */
+int gna_mmu_init(struct gna_device *gna_priv)
+{
+       struct device *parent = gna_dev(gna_priv);
+       struct gna_mmu_object *mmu;
+       int desc_size;
+       int i;
+
+       if (gna_priv->info.num_pagetables > GNA_PGDIRN_LEN) {
+               dev_dbg(gna_dev(gna_priv), "number of pagetables requested too 
large: %u\n", gna_priv->info.num_pagetables);
+               return -EINVAL;
+       }
+
+       mmu = &gna_priv->mmu;
+
+       desc_size = round_up(gna_priv->info.desc_info.desc_size, PAGE_SIZE);
+
+       mmu->hwdesc = dmam_alloc_coherent(parent, desc_size, &mmu->hwdesc_dma,
+                                       GFP_KERNEL);
+       if (!mmu->hwdesc)
+               return -ENOMEM;
+
+       mmu->num_pagetables = gna_priv->info.num_pagetables;
+
+       mmu->pagetables_dma = drmm_kmalloc_array(&gna_priv->drm, 
mmu->num_pagetables, sizeof(*mmu->pagetables_dma),
+                                               GFP_KERNEL);
+       if (!mmu->pagetables_dma)
+               return -ENOMEM;
+
+       mmu->pagetables = drmm_kmalloc_array(&gna_priv->drm, 
mmu->num_pagetables, sizeof(*mmu->pagetables), GFP_KERNEL);
+
+       if (!mmu->pagetables)
+               return -ENOMEM;
+
+       for (i = 0; i < mmu->num_pagetables; i++) {
+               mmu->pagetables[i] = dmam_alloc_coherent(parent, PAGE_SIZE,
+                                                       
&mmu->pagetables_dma[i], GFP_KERNEL);
+               if (!mmu->pagetables[i])
+                       return -ENOMEM;
+       }
+
+       gna_mmu_set(gna_priv);
+
+       return 0;
+}
diff --git a/drivers/gpu/drm/gna/gna_mem.h b/drivers/gpu/drm/gna/gna_mem.h
new file mode 100644
index 000000000000..f9b8dcb1399f
--- /dev/null
+++ b/drivers/gpu/drm/gna/gna_mem.h
@@ -0,0 +1,50 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/* Copyright(c) 2017-2022 Intel Corporation */
+
+#ifndef __GNA_MEM_H__
+#define __GNA_MEM_H__
+
+#include <linux/types.h>
+
+#include "gna_hw.h"
+
+struct gna_gem_object;
+struct work_struct;
+struct gna_device;
+
+struct gna_xnn_descriptor {
+       u32 labase;
+       u16 lacount;
+       u16 _rsvd;
+};
+
+struct gna_mmu {
+       u32 vamaxaddr;
+       u8 __res_204[12];
+       u32 pagedir_n[GNA_PGDIRN_LEN];
+};
+
+struct gna_hw_descriptor {
+       u8 __res_0000[256];
+       struct gna_xnn_descriptor xnn_config;
+       u8 __unused[248];
+       struct gna_mmu mmu;
+};
+
+struct gna_mmu_object {
+       struct gna_hw_descriptor *hwdesc;
+
+       dma_addr_t hwdesc_dma;
+
+       u32 **pagetables;
+       dma_addr_t *pagetables_dma;
+
+       u32 num_pagetables;
+
+       u32 filled_pts;
+       u32 filled_pages;
+};
+
+int gna_mmu_init(struct gna_device *gna_priv);
+
+#endif // __GNA_MEM_H__
diff --git a/drivers/gpu/drm/gna/gna_pci.c b/drivers/gpu/drm/gna/gna_pci.c
index 14f8b34e5f5c..9a6c82362e32 100644
--- a/drivers/gpu/drm/gna/gna_pci.c
+++ b/drivers/gpu/drm/gna/gna_pci.c
@@ -8,6 +8,73 @@
 #include "gna_hw.h"
 #include "gna_pci.h"
 
+static const struct gna_dev_info cnl_dev_info = {
+       .hwid = GNA_DEV_HWID_CNL,
+       GNA_GEN1_FEATURES
+};
+
+static const struct gna_dev_info glk_dev_info = {
+       .hwid = GNA_DEV_HWID_GLK,
+       GNA_GEN1_FEATURES
+};
+
+static const struct gna_dev_info ehl_dev_info = {
+       .hwid = GNA_DEV_HWID_EHL,
+       GNA_GEN1_FEATURES
+};
+
+static const struct gna_dev_info icl_dev_info = {
+       .hwid = GNA_DEV_HWID_ICL,
+       GNA_GEN1_FEATURES
+};
+
+static const struct gna_dev_info jsl_dev_info = {
+       .hwid = GNA_DEV_HWID_JSL,
+       GNA_GEN2_FEATURES
+};
+
+static const struct gna_dev_info tgl_dev_info = {
+       .hwid = GNA_DEV_HWID_TGL,
+       GNA_GEN2_FEATURES
+};
+
+static const struct gna_dev_info rkl_dev_info = {
+       .hwid = GNA_DEV_HWID_RKL,
+       GNA_GEN2_FEATURES
+};
+
+static const struct gna_dev_info adl_dev_info = {
+       .hwid = GNA_DEV_HWID_ADL,
+       GNA_GEN2_FEATURES
+};
+
+static const struct gna_dev_info rpl_dev_info = {
+       .hwid = GNA_DEV_HWID_RPL,
+       GNA_GEN2_FEATURES
+};
+
+static const struct gna_dev_info mtl_dev_info = {
+       .hwid = GNA_DEV_HWID_MTL,
+       GNA_GEN2_FEATURES
+};
+
+#define INTEL_GNA_DEVICE(hwid, info)                           \
+       { PCI_VDEVICE(INTEL, hwid), (kernel_ulong_t)(info) }
+
+static const struct pci_device_id gna_pci_ids[] = {
+       INTEL_GNA_DEVICE(GNA_DEV_HWID_CNL, &cnl_dev_info),
+       INTEL_GNA_DEVICE(GNA_DEV_HWID_EHL, &ehl_dev_info),
+       INTEL_GNA_DEVICE(GNA_DEV_HWID_GLK, &glk_dev_info),
+       INTEL_GNA_DEVICE(GNA_DEV_HWID_ICL, &icl_dev_info),
+       INTEL_GNA_DEVICE(GNA_DEV_HWID_JSL, &jsl_dev_info),
+       INTEL_GNA_DEVICE(GNA_DEV_HWID_TGL, &tgl_dev_info),
+       INTEL_GNA_DEVICE(GNA_DEV_HWID_RKL, &rkl_dev_info),
+       INTEL_GNA_DEVICE(GNA_DEV_HWID_ADL, &adl_dev_info),
+       INTEL_GNA_DEVICE(GNA_DEV_HWID_RPL, &rpl_dev_info),
+       INTEL_GNA_DEVICE(GNA_DEV_HWID_MTL, &mtl_dev_info),
+       { }
+};
+
 int gna_pci_probe(struct pci_dev *pcidev, const struct pci_device_id *pci_id)
 {
        struct gna_dev_info *dev_info;
@@ -37,7 +104,10 @@ int gna_pci_probe(struct pci_dev *pcidev, const struct 
pci_device_id *pci_id)
 
 static struct pci_driver gna_pci_driver = {
        .name = DRIVER_NAME,
+       .id_table = gna_pci_ids,
        .probe = gna_pci_probe,
 };
 
 module_pci_driver(gna_pci_driver);
+
+MODULE_DEVICE_TABLE(pci, gna_pci_ids);
-- 
2.25.1

Reply via email to