Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /* Copyright 2018 Marty E. Plummer <hanetzer@startmail.com> */
0003 /* Copyright 2019 Linaro, Ltd., Rob Herring <robh@kernel.org> */
0004 /* Copyright 2019 Collabora ltd. */
0005 #include <linux/bitfield.h>
0006 #include <linux/bitmap.h>
0007 #include <linux/delay.h>
0008 #include <linux/dma-mapping.h>
0009 #include <linux/interrupt.h>
0010 #include <linux/io.h>
0011 #include <linux/iopoll.h>
0012 #include <linux/platform_device.h>
0013 #include <linux/pm_runtime.h>
0014 
0015 #include "panfrost_device.h"
0016 #include "panfrost_features.h"
0017 #include "panfrost_issues.h"
0018 #include "panfrost_gpu.h"
0019 #include "panfrost_perfcnt.h"
0020 #include "panfrost_regs.h"
0021 
0022 static irqreturn_t panfrost_gpu_irq_handler(int irq, void *data)
0023 {
0024     struct panfrost_device *pfdev = data;
0025     u32 state = gpu_read(pfdev, GPU_INT_STAT);
0026     u32 fault_status = gpu_read(pfdev, GPU_FAULT_STATUS);
0027 
0028     if (!state)
0029         return IRQ_NONE;
0030 
0031     if (state & GPU_IRQ_MASK_ERROR) {
0032         u64 address = (u64) gpu_read(pfdev, GPU_FAULT_ADDRESS_HI) << 32;
0033         address |= gpu_read(pfdev, GPU_FAULT_ADDRESS_LO);
0034 
0035         dev_warn(pfdev->dev, "GPU Fault 0x%08x (%s) at 0x%016llx\n",
0036              fault_status, panfrost_exception_name(fault_status & 0xFF),
0037              address);
0038 
0039         if (state & GPU_IRQ_MULTIPLE_FAULT)
0040             dev_warn(pfdev->dev, "There were multiple GPU faults - some have not been reported\n");
0041 
0042         gpu_write(pfdev, GPU_INT_MASK, 0);
0043     }
0044 
0045     if (state & GPU_IRQ_PERFCNT_SAMPLE_COMPLETED)
0046         panfrost_perfcnt_sample_done(pfdev);
0047 
0048     if (state & GPU_IRQ_CLEAN_CACHES_COMPLETED)
0049         panfrost_perfcnt_clean_cache_done(pfdev);
0050 
0051     gpu_write(pfdev, GPU_INT_CLEAR, state);
0052 
0053     return IRQ_HANDLED;
0054 }
0055 
0056 int panfrost_gpu_soft_reset(struct panfrost_device *pfdev)
0057 {
0058     int ret;
0059     u32 val;
0060 
0061     gpu_write(pfdev, GPU_INT_MASK, 0);
0062     gpu_write(pfdev, GPU_INT_CLEAR, GPU_IRQ_RESET_COMPLETED);
0063     gpu_write(pfdev, GPU_CMD, GPU_CMD_SOFT_RESET);
0064 
0065     ret = readl_relaxed_poll_timeout(pfdev->iomem + GPU_INT_RAWSTAT,
0066         val, val & GPU_IRQ_RESET_COMPLETED, 100, 10000);
0067 
0068     if (ret) {
0069         dev_err(pfdev->dev, "gpu soft reset timed out\n");
0070         return ret;
0071     }
0072 
0073     gpu_write(pfdev, GPU_INT_CLEAR, GPU_IRQ_MASK_ALL);
0074     gpu_write(pfdev, GPU_INT_MASK, GPU_IRQ_MASK_ALL);
0075 
0076     return 0;
0077 }
0078 
0079 void panfrost_gpu_amlogic_quirk(struct panfrost_device *pfdev)
0080 {
0081     /*
0082      * The Amlogic integrated Mali-T820, Mali-G31 & Mali-G52 needs
0083      * these undocumented bits in GPU_PWR_OVERRIDE1 to be set in order
0084      * to operate correctly.
0085      */
0086     gpu_write(pfdev, GPU_PWR_KEY, GPU_PWR_KEY_UNLOCK);
0087     gpu_write(pfdev, GPU_PWR_OVERRIDE1, 0xfff | (0x20 << 16));
0088 }
0089 
0090 static void panfrost_gpu_init_quirks(struct panfrost_device *pfdev)
0091 {
0092     u32 quirks = 0;
0093 
0094     if (panfrost_has_hw_issue(pfdev, HW_ISSUE_8443) ||
0095         panfrost_has_hw_issue(pfdev, HW_ISSUE_11035))
0096         quirks |= SC_LS_PAUSEBUFFER_DISABLE;
0097 
0098     if (panfrost_has_hw_issue(pfdev, HW_ISSUE_10327))
0099         quirks |= SC_SDC_DISABLE_OQ_DISCARD;
0100 
0101     if (panfrost_has_hw_issue(pfdev, HW_ISSUE_10797))
0102         quirks |= SC_ENABLE_TEXGRD_FLAGS;
0103 
0104     if (!panfrost_has_hw_issue(pfdev, GPUCORE_1619)) {
0105         if (panfrost_model_cmp(pfdev, 0x750) < 0) /* T60x, T62x, T72x */
0106             quirks |= SC_LS_ATTR_CHECK_DISABLE;
0107         else if (panfrost_model_cmp(pfdev, 0x880) <= 0) /* T76x, T8xx */
0108             quirks |= SC_LS_ALLOW_ATTR_TYPES;
0109     }
0110 
0111     if (panfrost_has_hw_issue(pfdev, HW_ISSUE_TTRX_2968_TTRX_3162))
0112         quirks |= SC_VAR_ALGORITHM;
0113 
0114     if (panfrost_has_hw_feature(pfdev, HW_FEATURE_TLS_HASHING))
0115         quirks |= SC_TLS_HASH_ENABLE;
0116 
0117     if (quirks)
0118         gpu_write(pfdev, GPU_SHADER_CONFIG, quirks);
0119 
0120 
0121     quirks = gpu_read(pfdev, GPU_TILER_CONFIG);
0122 
0123     /* Set tiler clock gate override if required */
0124     if (panfrost_has_hw_issue(pfdev, HW_ISSUE_T76X_3953))
0125         quirks |= TC_CLOCK_GATE_OVERRIDE;
0126 
0127     gpu_write(pfdev, GPU_TILER_CONFIG, quirks);
0128 
0129 
0130     quirks = 0;
0131     if ((panfrost_model_eq(pfdev, 0x860) || panfrost_model_eq(pfdev, 0x880)) &&
0132         pfdev->features.revision >= 0x2000)
0133         quirks |= JM_MAX_JOB_THROTTLE_LIMIT << JM_JOB_THROTTLE_LIMIT_SHIFT;
0134     else if (panfrost_model_eq(pfdev, 0x6000) &&
0135          pfdev->features.coherency_features == COHERENCY_ACE)
0136         quirks |= (COHERENCY_ACE_LITE | COHERENCY_ACE) <<
0137                JM_FORCE_COHERENCY_FEATURES_SHIFT;
0138 
0139     if (panfrost_has_hw_feature(pfdev, HW_FEATURE_IDVS_GROUP_SIZE))
0140         quirks |= JM_DEFAULT_IDVS_GROUP_SIZE << JM_IDVS_GROUP_SIZE_SHIFT;
0141 
0142     if (quirks)
0143         gpu_write(pfdev, GPU_JM_CONFIG, quirks);
0144 
0145     /* Here goes platform specific quirks */
0146     if (pfdev->comp->vendor_quirk)
0147         pfdev->comp->vendor_quirk(pfdev);
0148 }
0149 
0150 #define MAX_HW_REVS 6
0151 
0152 struct panfrost_model {
0153     const char *name;
0154     u32 id;
0155     u32 id_mask;
0156     u64 features;
0157     u64 issues;
0158     struct {
0159         u32 revision;
0160         u64 issues;
0161     } revs[MAX_HW_REVS];
0162 };
0163 
0164 #define GPU_MODEL(_name, _id, ...) \
0165 {\
0166     .name = __stringify(_name),             \
0167     .id = _id,                      \
0168     .features = hw_features_##_name,            \
0169     .issues = hw_issues_##_name,                \
0170     .revs = { __VA_ARGS__ },                \
0171 }
0172 
0173 #define GPU_REV_EXT(name, _rev, _p, _s, stat) \
0174 {\
0175     .revision = (_rev) << 12 | (_p) << 4 | (_s),        \
0176     .issues = hw_issues_##name##_r##_rev##p##_p##stat,  \
0177 }
0178 #define GPU_REV(name, r, p) GPU_REV_EXT(name, r, p, 0, )
0179 
0180 static const struct panfrost_model gpu_models[] = {
0181     /* T60x has an oddball version */
0182     GPU_MODEL(t600, 0x600,
0183         GPU_REV_EXT(t600, 0, 0, 1, _15dev0)),
0184     GPU_MODEL(t620, 0x620,
0185         GPU_REV(t620, 0, 1), GPU_REV(t620, 1, 0)),
0186     GPU_MODEL(t720, 0x720),
0187     GPU_MODEL(t760, 0x750,
0188         GPU_REV(t760, 0, 0), GPU_REV(t760, 0, 1),
0189         GPU_REV_EXT(t760, 0, 1, 0, _50rel0),
0190         GPU_REV(t760, 0, 2), GPU_REV(t760, 0, 3)),
0191     GPU_MODEL(t820, 0x820),
0192     GPU_MODEL(t830, 0x830),
0193     GPU_MODEL(t860, 0x860),
0194     GPU_MODEL(t880, 0x880),
0195 
0196     GPU_MODEL(g71, 0x6000,
0197         GPU_REV_EXT(g71, 0, 0, 1, _05dev0)),
0198     GPU_MODEL(g72, 0x6001),
0199     GPU_MODEL(g51, 0x7000),
0200     GPU_MODEL(g76, 0x7001),
0201     GPU_MODEL(g52, 0x7002),
0202     GPU_MODEL(g31, 0x7003,
0203         GPU_REV(g31, 1, 0)),
0204 
0205     GPU_MODEL(g57, 0x9001,
0206         GPU_REV(g57, 0, 0)),
0207 };
0208 
0209 static void panfrost_gpu_init_features(struct panfrost_device *pfdev)
0210 {
0211     u32 gpu_id, num_js, major, minor, status, rev;
0212     const char *name = "unknown";
0213     u64 hw_feat = 0;
0214     u64 hw_issues = hw_issues_all;
0215     const struct panfrost_model *model;
0216     int i;
0217 
0218     pfdev->features.l2_features = gpu_read(pfdev, GPU_L2_FEATURES);
0219     pfdev->features.core_features = gpu_read(pfdev, GPU_CORE_FEATURES);
0220     pfdev->features.tiler_features = gpu_read(pfdev, GPU_TILER_FEATURES);
0221     pfdev->features.mem_features = gpu_read(pfdev, GPU_MEM_FEATURES);
0222     pfdev->features.mmu_features = gpu_read(pfdev, GPU_MMU_FEATURES);
0223     pfdev->features.thread_features = gpu_read(pfdev, GPU_THREAD_FEATURES);
0224     pfdev->features.max_threads = gpu_read(pfdev, GPU_THREAD_MAX_THREADS);
0225     pfdev->features.thread_max_workgroup_sz = gpu_read(pfdev, GPU_THREAD_MAX_WORKGROUP_SIZE);
0226     pfdev->features.thread_max_barrier_sz = gpu_read(pfdev, GPU_THREAD_MAX_BARRIER_SIZE);
0227     pfdev->features.coherency_features = gpu_read(pfdev, GPU_COHERENCY_FEATURES);
0228     pfdev->features.afbc_features = gpu_read(pfdev, GPU_AFBC_FEATURES);
0229     for (i = 0; i < 4; i++)
0230         pfdev->features.texture_features[i] = gpu_read(pfdev, GPU_TEXTURE_FEATURES(i));
0231 
0232     pfdev->features.as_present = gpu_read(pfdev, GPU_AS_PRESENT);
0233 
0234     pfdev->features.js_present = gpu_read(pfdev, GPU_JS_PRESENT);
0235     num_js = hweight32(pfdev->features.js_present);
0236     for (i = 0; i < num_js; i++)
0237         pfdev->features.js_features[i] = gpu_read(pfdev, GPU_JS_FEATURES(i));
0238 
0239     pfdev->features.shader_present = gpu_read(pfdev, GPU_SHADER_PRESENT_LO);
0240     pfdev->features.shader_present |= (u64)gpu_read(pfdev, GPU_SHADER_PRESENT_HI) << 32;
0241 
0242     pfdev->features.tiler_present = gpu_read(pfdev, GPU_TILER_PRESENT_LO);
0243     pfdev->features.tiler_present |= (u64)gpu_read(pfdev, GPU_TILER_PRESENT_HI) << 32;
0244 
0245     pfdev->features.l2_present = gpu_read(pfdev, GPU_L2_PRESENT_LO);
0246     pfdev->features.l2_present |= (u64)gpu_read(pfdev, GPU_L2_PRESENT_HI) << 32;
0247     pfdev->features.nr_core_groups = hweight64(pfdev->features.l2_present);
0248 
0249     pfdev->features.stack_present = gpu_read(pfdev, GPU_STACK_PRESENT_LO);
0250     pfdev->features.stack_present |= (u64)gpu_read(pfdev, GPU_STACK_PRESENT_HI) << 32;
0251 
0252     pfdev->features.thread_tls_alloc = gpu_read(pfdev, GPU_THREAD_TLS_ALLOC);
0253 
0254     gpu_id = gpu_read(pfdev, GPU_ID);
0255     pfdev->features.revision = gpu_id & 0xffff;
0256     pfdev->features.id = gpu_id >> 16;
0257 
0258     /* The T60x has an oddball ID value. Fix it up to the standard Midgard
0259      * format so we (and userspace) don't have to special case it.
0260      */
0261     if (pfdev->features.id == 0x6956)
0262         pfdev->features.id = 0x0600;
0263 
0264     major = (pfdev->features.revision >> 12) & 0xf;
0265     minor = (pfdev->features.revision >> 4) & 0xff;
0266     status = pfdev->features.revision & 0xf;
0267     rev = pfdev->features.revision;
0268 
0269     gpu_id = pfdev->features.id;
0270 
0271     for (model = gpu_models; model->name; model++) {
0272         int best = -1;
0273 
0274         if (!panfrost_model_eq(pfdev, model->id))
0275             continue;
0276 
0277         name = model->name;
0278         hw_feat = model->features;
0279         hw_issues |= model->issues;
0280         for (i = 0; i < MAX_HW_REVS; i++) {
0281             if (model->revs[i].revision == rev) {
0282                 best = i;
0283                 break;
0284             } else if (model->revs[i].revision == (rev & ~0xf))
0285                 best = i;
0286         }
0287 
0288         if (best >= 0)
0289             hw_issues |= model->revs[best].issues;
0290 
0291         break;
0292     }
0293 
0294     bitmap_from_u64(pfdev->features.hw_features, hw_feat);
0295     bitmap_from_u64(pfdev->features.hw_issues, hw_issues);
0296 
0297     dev_info(pfdev->dev, "mali-%s id 0x%x major 0x%x minor 0x%x status 0x%x",
0298          name, gpu_id, major, minor, status);
0299     dev_info(pfdev->dev, "features: %64pb, issues: %64pb",
0300          pfdev->features.hw_features,
0301          pfdev->features.hw_issues);
0302 
0303     dev_info(pfdev->dev, "Features: L2:0x%08x Shader:0x%08x Tiler:0x%08x Mem:0x%0x MMU:0x%08x AS:0x%x JS:0x%x",
0304          pfdev->features.l2_features,
0305          pfdev->features.core_features,
0306          pfdev->features.tiler_features,
0307          pfdev->features.mem_features,
0308          pfdev->features.mmu_features,
0309          pfdev->features.as_present,
0310          pfdev->features.js_present);
0311 
0312     dev_info(pfdev->dev, "shader_present=0x%0llx l2_present=0x%0llx",
0313          pfdev->features.shader_present, pfdev->features.l2_present);
0314 }
0315 
0316 void panfrost_gpu_power_on(struct panfrost_device *pfdev)
0317 {
0318     int ret;
0319     u32 val;
0320     u64 core_mask = U64_MAX;
0321 
0322     panfrost_gpu_init_quirks(pfdev);
0323 
0324     if (pfdev->features.l2_present != 1) {
0325         /*
0326          * Only support one core group now.
0327          * ~(l2_present - 1) unsets all bits in l2_present except
0328          * the bottom bit. (l2_present - 2) has all the bits in
0329          * the first core group set. AND them together to generate
0330          * a mask of cores in the first core group.
0331          */
0332         core_mask = ~(pfdev->features.l2_present - 1) &
0333                  (pfdev->features.l2_present - 2);
0334         dev_info_once(pfdev->dev, "using only 1st core group (%lu cores from %lu)\n",
0335                   hweight64(core_mask),
0336                   hweight64(pfdev->features.shader_present));
0337     }
0338     gpu_write(pfdev, L2_PWRON_LO, pfdev->features.l2_present & core_mask);
0339     ret = readl_relaxed_poll_timeout(pfdev->iomem + L2_READY_LO,
0340         val, val == (pfdev->features.l2_present & core_mask),
0341         100, 20000);
0342     if (ret)
0343         dev_err(pfdev->dev, "error powering up gpu L2");
0344 
0345     gpu_write(pfdev, SHADER_PWRON_LO,
0346           pfdev->features.shader_present & core_mask);
0347     ret = readl_relaxed_poll_timeout(pfdev->iomem + SHADER_READY_LO,
0348         val, val == (pfdev->features.shader_present & core_mask),
0349         100, 20000);
0350     if (ret)
0351         dev_err(pfdev->dev, "error powering up gpu shader");
0352 
0353     gpu_write(pfdev, TILER_PWRON_LO, pfdev->features.tiler_present);
0354     ret = readl_relaxed_poll_timeout(pfdev->iomem + TILER_READY_LO,
0355         val, val == pfdev->features.tiler_present, 100, 1000);
0356     if (ret)
0357         dev_err(pfdev->dev, "error powering up gpu tiler");
0358 }
0359 
0360 void panfrost_gpu_power_off(struct panfrost_device *pfdev)
0361 {
0362     gpu_write(pfdev, TILER_PWROFF_LO, 0);
0363     gpu_write(pfdev, SHADER_PWROFF_LO, 0);
0364     gpu_write(pfdev, L2_PWROFF_LO, 0);
0365 }
0366 
0367 int panfrost_gpu_init(struct panfrost_device *pfdev)
0368 {
0369     int err, irq;
0370 
0371     err = panfrost_gpu_soft_reset(pfdev);
0372     if (err)
0373         return err;
0374 
0375     panfrost_gpu_init_features(pfdev);
0376 
0377     err = dma_set_mask_and_coherent(pfdev->dev,
0378         DMA_BIT_MASK(FIELD_GET(0xff00, pfdev->features.mmu_features)));
0379     if (err)
0380         return err;
0381 
0382     dma_set_max_seg_size(pfdev->dev, UINT_MAX);
0383 
0384     irq = platform_get_irq_byname(to_platform_device(pfdev->dev), "gpu");
0385     if (irq <= 0)
0386         return -ENODEV;
0387 
0388     err = devm_request_irq(pfdev->dev, irq, panfrost_gpu_irq_handler,
0389                    IRQF_SHARED, KBUILD_MODNAME "-gpu", pfdev);
0390     if (err) {
0391         dev_err(pfdev->dev, "failed to request gpu irq");
0392         return err;
0393     }
0394 
0395     panfrost_gpu_power_on(pfdev);
0396 
0397     return 0;
0398 }
0399 
0400 void panfrost_gpu_fini(struct panfrost_device *pfdev)
0401 {
0402     panfrost_gpu_power_off(pfdev);
0403 }
0404 
0405 u32 panfrost_gpu_get_latest_flush_id(struct panfrost_device *pfdev)
0406 {
0407     u32 flush_id;
0408 
0409     if (panfrost_has_hw_feature(pfdev, HW_FEATURE_FLUSH_REDUCTION)) {
0410         /* Flush reduction only makes sense when the GPU is kept powered on between jobs */
0411         if (pm_runtime_get_if_in_use(pfdev->dev)) {
0412             flush_id = gpu_read(pfdev, GPU_LATEST_FLUSH_ID);
0413             pm_runtime_put(pfdev->dev);
0414             return flush_id;
0415         }
0416     }
0417 
0418     return 0;
0419 }