[media] coda: add reset control support

On i.MX53 and i.MX6, the CODA VPU can be reset by the System Reset Controller.
We can use this to get out of dire situations, for example after a picture
run timeout.

Signed-off-by: Philipp Zabel <p.zabel@pengutronix.de>
Signed-off-by: Kamil Debski <k.debski@samsung.com>
Signed-off-by: Mauro Carvalho Chehab <m.chehab@samsung.com>
This commit is contained in:
Philipp Zabel 2014-07-11 06:36:35 -03:00 committed by Mauro Carvalho Chehab
parent 84e2365d7d
commit 8f45284c4e

View File

@ -27,6 +27,7 @@
#include <linux/videodev2.h> #include <linux/videodev2.h>
#include <linux/of.h> #include <linux/of.h>
#include <linux/platform_data/coda.h> #include <linux/platform_data/coda.h>
#include <linux/reset.h>
#include <media/v4l2-ctrls.h> #include <media/v4l2-ctrls.h>
#include <media/v4l2-device.h> #include <media/v4l2-device.h>
@ -138,6 +139,7 @@ struct coda_dev {
void __iomem *regs_base; void __iomem *regs_base;
struct clk *clk_per; struct clk *clk_per;
struct clk *clk_ahb; struct clk *clk_ahb;
struct reset_control *rstc;
struct coda_aux_buf codebuf; struct coda_aux_buf codebuf;
struct coda_aux_buf tempbuf; struct coda_aux_buf tempbuf;
@ -337,6 +339,39 @@ static int coda_command_sync(struct coda_ctx *ctx, int cmd)
return coda_wait_timeout(dev); return coda_wait_timeout(dev);
} }
static int coda_hw_reset(struct coda_ctx *ctx)
{
struct coda_dev *dev = ctx->dev;
unsigned long timeout;
unsigned int idx;
int ret;
if (!dev->rstc)
return -ENOENT;
idx = coda_read(dev, CODA_REG_BIT_RUN_INDEX);
timeout = jiffies + msecs_to_jiffies(100);
coda_write(dev, 0x11, CODA9_GDI_BUS_CTRL);
while (coda_read(dev, CODA9_GDI_BUS_STATUS) != 0x77) {
if (time_after(jiffies, timeout))
return -ETIME;
cpu_relax();
}
ret = reset_control_reset(dev->rstc);
if (ret < 0)
return ret;
coda_write(dev, 0x00, CODA9_GDI_BUS_CTRL);
coda_write(dev, CODA_REG_BIT_BUSY_FLAG, CODA_REG_BIT_BUSY);
coda_write(dev, CODA_REG_RUN_ENABLE, CODA_REG_BIT_CODE_RUN);
ret = coda_wait_timeout(dev);
coda_write(dev, idx, CODA_REG_BIT_RUN_INDEX);
return ret;
}
static struct coda_q_data *get_q_data(struct coda_ctx *ctx, static struct coda_q_data *get_q_data(struct coda_ctx *ctx,
enum v4l2_buf_type type) enum v4l2_buf_type type)
{ {
@ -1423,6 +1458,8 @@ static void coda_pic_run_work(struct work_struct *work)
dev_err(&dev->plat_dev->dev, "CODA PIC_RUN timeout\n"); dev_err(&dev->plat_dev->dev, "CODA PIC_RUN timeout\n");
ctx->hold = true; ctx->hold = true;
coda_hw_reset(ctx);
} else if (!ctx->aborting) { } else if (!ctx->aborting) {
if (ctx->inst_type == CODA_INST_DECODER) if (ctx->inst_type == CODA_INST_DECODER)
coda_finish_decode(ctx); coda_finish_decode(ctx);
@ -3333,6 +3370,9 @@ static int coda_hw_init(struct coda_dev *dev)
if (ret) if (ret)
goto err_clk_ahb; goto err_clk_ahb;
if (dev->rstc)
reset_control_reset(dev->rstc);
/* /*
* Copy the first CODA_ISRAM_SIZE in the internal SRAM. * Copy the first CODA_ISRAM_SIZE in the internal SRAM.
* The 16-bit chars in the code buffer are in memory access * The 16-bit chars in the code buffer are in memory access
@ -3691,6 +3731,17 @@ static int coda_probe(struct platform_device *pdev)
return -ENOENT; return -ENOENT;
} }
dev->rstc = devm_reset_control_get(&pdev->dev, NULL);
if (IS_ERR(dev->rstc)) {
ret = PTR_ERR(dev->rstc);
if (ret == -ENOENT) {
dev->rstc = NULL;
} else {
dev_err(&pdev->dev, "failed get reset control: %d\n", ret);
return ret;
}
}
/* Get IRAM pool from device tree or platform data */ /* Get IRAM pool from device tree or platform data */
pool = of_get_named_gen_pool(np, "iram", 0); pool = of_get_named_gen_pool(np, "iram", 0);
if (!pool && pdata) if (!pool && pdata)