diff options
Diffstat (limited to 'drivers/gpu/drm/vc4/vc4_v3d.c')
-rw-r--r-- | drivers/gpu/drm/vc4/vc4_v3d.c | 240 |
1 files changed, 131 insertions, 109 deletions
diff --git a/drivers/gpu/drm/vc4/vc4_v3d.c b/drivers/gpu/drm/vc4/vc4_v3d.c index e47e29426078..a4b6859e3af6 100644 --- a/drivers/gpu/drm/vc4/vc4_v3d.c +++ b/drivers/gpu/drm/vc4/vc4_v3d.c @@ -22,129 +22,145 @@ #include "vc4_drv.h" #include "vc4_regs.h" -#ifdef CONFIG_DEBUG_FS -#define REGDEF(reg) { reg, #reg } -static const struct { - uint32_t reg; - const char *name; -} vc4_reg_defs[] = { - REGDEF(V3D_IDENT0), - REGDEF(V3D_IDENT1), - REGDEF(V3D_IDENT2), - REGDEF(V3D_SCRATCH), - REGDEF(V3D_L2CACTL), - REGDEF(V3D_SLCACTL), - REGDEF(V3D_INTCTL), - REGDEF(V3D_INTENA), - REGDEF(V3D_INTDIS), - REGDEF(V3D_CT0CS), - REGDEF(V3D_CT1CS), - REGDEF(V3D_CT0EA), - REGDEF(V3D_CT1EA), - REGDEF(V3D_CT0CA), - REGDEF(V3D_CT1CA), - REGDEF(V3D_CT00RA0), - REGDEF(V3D_CT01RA0), - REGDEF(V3D_CT0LC), - REGDEF(V3D_CT1LC), - REGDEF(V3D_CT0PC), - REGDEF(V3D_CT1PC), - REGDEF(V3D_PCS), - REGDEF(V3D_BFC), - REGDEF(V3D_RFC), - REGDEF(V3D_BPCA), - REGDEF(V3D_BPCS), - REGDEF(V3D_BPOA), - REGDEF(V3D_BPOS), - REGDEF(V3D_BXCF), - REGDEF(V3D_SQRSV0), - REGDEF(V3D_SQRSV1), - REGDEF(V3D_SQCNTL), - REGDEF(V3D_SRQPC), - REGDEF(V3D_SRQUA), - REGDEF(V3D_SRQUL), - REGDEF(V3D_SRQCS), - REGDEF(V3D_VPACNTL), - REGDEF(V3D_VPMBASE), - REGDEF(V3D_PCTRC), - REGDEF(V3D_PCTRE), - REGDEF(V3D_PCTR(0)), - REGDEF(V3D_PCTRS(0)), - REGDEF(V3D_PCTR(1)), - REGDEF(V3D_PCTRS(1)), - REGDEF(V3D_PCTR(2)), - REGDEF(V3D_PCTRS(2)), - REGDEF(V3D_PCTR(3)), - REGDEF(V3D_PCTRS(3)), - REGDEF(V3D_PCTR(4)), - REGDEF(V3D_PCTRS(4)), - REGDEF(V3D_PCTR(5)), - REGDEF(V3D_PCTRS(5)), - REGDEF(V3D_PCTR(6)), - REGDEF(V3D_PCTRS(6)), - REGDEF(V3D_PCTR(7)), - REGDEF(V3D_PCTRS(7)), - REGDEF(V3D_PCTR(8)), - REGDEF(V3D_PCTRS(8)), - REGDEF(V3D_PCTR(9)), - REGDEF(V3D_PCTRS(9)), - REGDEF(V3D_PCTR(10)), - REGDEF(V3D_PCTRS(10)), - REGDEF(V3D_PCTR(11)), - REGDEF(V3D_PCTRS(11)), - REGDEF(V3D_PCTR(12)), - REGDEF(V3D_PCTRS(12)), - REGDEF(V3D_PCTR(13)), - REGDEF(V3D_PCTRS(13)), - REGDEF(V3D_PCTR(14)), - REGDEF(V3D_PCTRS(14)), - REGDEF(V3D_PCTR(15)), - REGDEF(V3D_PCTRS(15)), - REGDEF(V3D_DBGE), - REGDEF(V3D_FDBGO), - REGDEF(V3D_FDBGB), - REGDEF(V3D_FDBGR), - REGDEF(V3D_FDBGS), - REGDEF(V3D_ERRSTAT), +static const struct debugfs_reg32 v3d_regs[] = { + VC4_REG32(V3D_IDENT0), + VC4_REG32(V3D_IDENT1), + VC4_REG32(V3D_IDENT2), + VC4_REG32(V3D_SCRATCH), + VC4_REG32(V3D_L2CACTL), + VC4_REG32(V3D_SLCACTL), + VC4_REG32(V3D_INTCTL), + VC4_REG32(V3D_INTENA), + VC4_REG32(V3D_INTDIS), + VC4_REG32(V3D_CT0CS), + VC4_REG32(V3D_CT1CS), + VC4_REG32(V3D_CT0EA), + VC4_REG32(V3D_CT1EA), + VC4_REG32(V3D_CT0CA), + VC4_REG32(V3D_CT1CA), + VC4_REG32(V3D_CT00RA0), + VC4_REG32(V3D_CT01RA0), + VC4_REG32(V3D_CT0LC), + VC4_REG32(V3D_CT1LC), + VC4_REG32(V3D_CT0PC), + VC4_REG32(V3D_CT1PC), + VC4_REG32(V3D_PCS), + VC4_REG32(V3D_BFC), + VC4_REG32(V3D_RFC), + VC4_REG32(V3D_BPCA), + VC4_REG32(V3D_BPCS), + VC4_REG32(V3D_BPOA), + VC4_REG32(V3D_BPOS), + VC4_REG32(V3D_BXCF), + VC4_REG32(V3D_SQRSV0), + VC4_REG32(V3D_SQRSV1), + VC4_REG32(V3D_SQCNTL), + VC4_REG32(V3D_SRQPC), + VC4_REG32(V3D_SRQUA), + VC4_REG32(V3D_SRQUL), + VC4_REG32(V3D_SRQCS), + VC4_REG32(V3D_VPACNTL), + VC4_REG32(V3D_VPMBASE), + VC4_REG32(V3D_PCTRC), + VC4_REG32(V3D_PCTRE), + VC4_REG32(V3D_PCTR(0)), + VC4_REG32(V3D_PCTRS(0)), + VC4_REG32(V3D_PCTR(1)), + VC4_REG32(V3D_PCTRS(1)), + VC4_REG32(V3D_PCTR(2)), + VC4_REG32(V3D_PCTRS(2)), + VC4_REG32(V3D_PCTR(3)), + VC4_REG32(V3D_PCTRS(3)), + VC4_REG32(V3D_PCTR(4)), + VC4_REG32(V3D_PCTRS(4)), + VC4_REG32(V3D_PCTR(5)), + VC4_REG32(V3D_PCTRS(5)), + VC4_REG32(V3D_PCTR(6)), + VC4_REG32(V3D_PCTRS(6)), + VC4_REG32(V3D_PCTR(7)), + VC4_REG32(V3D_PCTRS(7)), + VC4_REG32(V3D_PCTR(8)), + VC4_REG32(V3D_PCTRS(8)), + VC4_REG32(V3D_PCTR(9)), + VC4_REG32(V3D_PCTRS(9)), + VC4_REG32(V3D_PCTR(10)), + VC4_REG32(V3D_PCTRS(10)), + VC4_REG32(V3D_PCTR(11)), + VC4_REG32(V3D_PCTRS(11)), + VC4_REG32(V3D_PCTR(12)), + VC4_REG32(V3D_PCTRS(12)), + VC4_REG32(V3D_PCTR(13)), + VC4_REG32(V3D_PCTRS(13)), + VC4_REG32(V3D_PCTR(14)), + VC4_REG32(V3D_PCTRS(14)), + VC4_REG32(V3D_PCTR(15)), + VC4_REG32(V3D_PCTRS(15)), + VC4_REG32(V3D_DBGE), + VC4_REG32(V3D_FDBGO), + VC4_REG32(V3D_FDBGB), + VC4_REG32(V3D_FDBGR), + VC4_REG32(V3D_FDBGS), + VC4_REG32(V3D_ERRSTAT), }; -int vc4_v3d_debugfs_regs(struct seq_file *m, void *unused) +static int vc4_v3d_debugfs_ident(struct seq_file *m, void *unused) { struct drm_info_node *node = (struct drm_info_node *)m->private; struct drm_device *dev = node->minor->dev; struct vc4_dev *vc4 = to_vc4_dev(dev); - int i; - - for (i = 0; i < ARRAY_SIZE(vc4_reg_defs); i++) { - seq_printf(m, "%s (0x%04x): 0x%08x\n", - vc4_reg_defs[i].name, vc4_reg_defs[i].reg, - V3D_READ(vc4_reg_defs[i].reg)); + int ret = vc4_v3d_pm_get(vc4); + + if (ret == 0) { + uint32_t ident1 = V3D_READ(V3D_IDENT1); + uint32_t nslc = VC4_GET_FIELD(ident1, V3D_IDENT1_NSLC); + uint32_t tups = VC4_GET_FIELD(ident1, V3D_IDENT1_TUPS); + uint32_t qups = VC4_GET_FIELD(ident1, V3D_IDENT1_QUPS); + + seq_printf(m, "Revision: %d\n", + VC4_GET_FIELD(ident1, V3D_IDENT1_REV)); + seq_printf(m, "Slices: %d\n", nslc); + seq_printf(m, "TMUs: %d\n", nslc * tups); + seq_printf(m, "QPUs: %d\n", nslc * qups); + seq_printf(m, "Semaphores: %d\n", + VC4_GET_FIELD(ident1, V3D_IDENT1_NSEM)); + vc4_v3d_pm_put(vc4); } return 0; } -int vc4_v3d_debugfs_ident(struct seq_file *m, void *unused) +/** + * Wraps pm_runtime_get_sync() in a refcount, so that we can reliably + * get the pm_runtime refcount to 0 in vc4_reset(). + */ +int +vc4_v3d_pm_get(struct vc4_dev *vc4) { - struct drm_info_node *node = (struct drm_info_node *)m->private; - struct drm_device *dev = node->minor->dev; - struct vc4_dev *vc4 = to_vc4_dev(dev); - uint32_t ident1 = V3D_READ(V3D_IDENT1); - uint32_t nslc = VC4_GET_FIELD(ident1, V3D_IDENT1_NSLC); - uint32_t tups = VC4_GET_FIELD(ident1, V3D_IDENT1_TUPS); - uint32_t qups = VC4_GET_FIELD(ident1, V3D_IDENT1_QUPS); - - seq_printf(m, "Revision: %d\n", - VC4_GET_FIELD(ident1, V3D_IDENT1_REV)); - seq_printf(m, "Slices: %d\n", nslc); - seq_printf(m, "TMUs: %d\n", nslc * tups); - seq_printf(m, "QPUs: %d\n", nslc * qups); - seq_printf(m, "Semaphores: %d\n", - VC4_GET_FIELD(ident1, V3D_IDENT1_NSEM)); + mutex_lock(&vc4->power_lock); + if (vc4->power_refcount++ == 0) { + int ret = pm_runtime_get_sync(&vc4->v3d->pdev->dev); + + if (ret < 0) { + vc4->power_refcount--; + mutex_unlock(&vc4->power_lock); + return ret; + } + } + mutex_unlock(&vc4->power_lock); return 0; } -#endif /* CONFIG_DEBUG_FS */ + +void +vc4_v3d_pm_put(struct vc4_dev *vc4) +{ + mutex_lock(&vc4->power_lock); + if (--vc4->power_refcount == 0) { + pm_runtime_mark_last_busy(&vc4->v3d->pdev->dev); + pm_runtime_put_autosuspend(&vc4->v3d->pdev->dev); + } + mutex_unlock(&vc4->power_lock); +} static void vc4_v3d_init_hw(struct drm_device *dev) { @@ -354,6 +370,9 @@ static int vc4_v3d_bind(struct device *dev, struct device *master, void *data) v3d->regs = vc4_ioremap_regs(pdev, 0); if (IS_ERR(v3d->regs)) return PTR_ERR(v3d->regs); + v3d->regset.base = v3d->regs; + v3d->regset.regs = v3d_regs; + v3d->regset.nregs = ARRAY_SIZE(v3d_regs); vc4->v3d = v3d; v3d->vc4 = vc4; @@ -409,6 +428,9 @@ static int vc4_v3d_bind(struct device *dev, struct device *master, void *data) pm_runtime_set_autosuspend_delay(dev, 40); /* a little over 2 frames. */ pm_runtime_enable(dev); + vc4_debugfs_add_file(drm, "v3d_ident", vc4_v3d_debugfs_ident, NULL); + vc4_debugfs_add_regset32(drm, "v3d_regs", &v3d->regset); + return 0; } @@ -452,7 +474,7 @@ static int vc4_v3d_dev_remove(struct platform_device *pdev) return 0; } -static const struct of_device_id vc4_v3d_dt_match[] = { +const struct of_device_id vc4_v3d_dt_match[] = { { .compatible = "brcm,bcm2835-v3d" }, { .compatible = "brcm,cygnus-v3d" }, { .compatible = "brcm,vc4-v3d" }, |