aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNiklas Söderlund <niklas.soderlund+renesas@ragnatech.se>2019-04-11 16:30:58 -0400
committerMauro Carvalho Chehab <mchehab+samsung@kernel.org>2019-05-08 13:59:21 -0400
commit4ab44ff0841b9a825f9875623d24809d29e37a10 (patch)
tree6b3fda39cded5e45ca46c1b902269f91ae3788be
parentdd6e2a981bfe83aa4a493143fd8cf1edcda6c091 (diff)
media: rcar-csi2: restart CSI-2 link if error is detected
Restart the CSI-2 link if the CSI-2 receiver detects an error during reception. The driver did nothing when a link error happened and the data flow simply stopped without the user knowing why. Change the driver to try and recover from errors by restarting the link and informing the user that something is not right. For obvious reasons it's not possible to recover from all errors (video source disconnected for example) but in such cases the user is at least informed of the error and the same behavior of the stopped data flow is retained. Signed-off-by: Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se> Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl> Signed-off-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
-rw-r--r--drivers/media/platform/rcar-vin/rcar-csi2.c52
1 files changed, 51 insertions, 1 deletions
diff --git a/drivers/media/platform/rcar-vin/rcar-csi2.c b/drivers/media/platform/rcar-vin/rcar-csi2.c
index 799e526fd3df..96bdc626ccbf 100644
--- a/drivers/media/platform/rcar-vin/rcar-csi2.c
+++ b/drivers/media/platform/rcar-vin/rcar-csi2.c
@@ -84,6 +84,9 @@ struct rcar_csi2;
84 84
85/* Interrupt Enable */ 85/* Interrupt Enable */
86#define INTEN_REG 0x30 86#define INTEN_REG 0x30
87#define INTEN_INT_AFIFO_OF BIT(27)
88#define INTEN_INT_ERRSOTHS BIT(4)
89#define INTEN_INT_ERRSOTSYNCHS BIT(3)
87 90
88/* Interrupt Source Mask */ 91/* Interrupt Source Mask */
89#define INTCLOSE_REG 0x34 92#define INTCLOSE_REG 0x34
@@ -514,6 +517,10 @@ static int rcsi2_start_receiver(struct rcar_csi2 *priv)
514 if (mbps < 0) 517 if (mbps < 0)
515 return mbps; 518 return mbps;
516 519
520 /* Enable interrupts. */
521 rcsi2_write(priv, INTEN_REG, INTEN_INT_AFIFO_OF | INTEN_INT_ERRSOTHS
522 | INTEN_INT_ERRSOTSYNCHS);
523
517 /* Init */ 524 /* Init */
518 rcsi2_write(priv, TREF_REG, TREF_TREF); 525 rcsi2_write(priv, TREF_REG, TREF_TREF);
519 rcsi2_write(priv, PHTC_REG, 0); 526 rcsi2_write(priv, PHTC_REG, 0);
@@ -675,6 +682,43 @@ static const struct v4l2_subdev_ops rcar_csi2_subdev_ops = {
675 .pad = &rcar_csi2_pad_ops, 682 .pad = &rcar_csi2_pad_ops,
676}; 683};
677 684
685static irqreturn_t rcsi2_irq(int irq, void *data)
686{
687 struct rcar_csi2 *priv = data;
688 u32 status, err_status;
689
690 status = rcsi2_read(priv, INTSTATE_REG);
691 err_status = rcsi2_read(priv, INTERRSTATE_REG);
692
693 if (!status)
694 return IRQ_HANDLED;
695
696 rcsi2_write(priv, INTSTATE_REG, status);
697
698 if (!err_status)
699 return IRQ_HANDLED;
700
701 rcsi2_write(priv, INTERRSTATE_REG, err_status);
702
703 dev_info(priv->dev, "Transfer error, restarting CSI-2 receiver\n");
704
705 return IRQ_WAKE_THREAD;
706}
707
708static irqreturn_t rcsi2_irq_thread(int irq, void *data)
709{
710 struct rcar_csi2 *priv = data;
711
712 mutex_lock(&priv->lock);
713 rcsi2_stop(priv);
714 usleep_range(1000, 2000);
715 if (rcsi2_start(priv))
716 dev_warn(priv->dev, "Failed to restart CSI-2 receiver\n");
717 mutex_unlock(&priv->lock);
718
719 return IRQ_HANDLED;
720}
721
678/* ----------------------------------------------------------------------------- 722/* -----------------------------------------------------------------------------
679 * Async handling and registration of subdevices and links. 723 * Async handling and registration of subdevices and links.
680 */ 724 */
@@ -947,7 +991,7 @@ static int rcsi2_probe_resources(struct rcar_csi2 *priv,
947 struct platform_device *pdev) 991 struct platform_device *pdev)
948{ 992{
949 struct resource *res; 993 struct resource *res;
950 int irq; 994 int irq, ret;
951 995
952 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 996 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
953 priv->base = devm_ioremap_resource(&pdev->dev, res); 997 priv->base = devm_ioremap_resource(&pdev->dev, res);
@@ -958,6 +1002,12 @@ static int rcsi2_probe_resources(struct rcar_csi2 *priv,
958 if (irq < 0) 1002 if (irq < 0)
959 return irq; 1003 return irq;
960 1004
1005 ret = devm_request_threaded_irq(&pdev->dev, irq, rcsi2_irq,
1006 rcsi2_irq_thread, IRQF_SHARED,
1007 KBUILD_MODNAME, priv);
1008 if (ret)
1009 return ret;
1010
961 priv->rstc = devm_reset_control_get(&pdev->dev, NULL); 1011 priv->rstc = devm_reset_control_get(&pdev->dev, NULL);
962 if (IS_ERR(priv->rstc)) 1012 if (IS_ERR(priv->rstc))
963 return PTR_ERR(priv->rstc); 1013 return PTR_ERR(priv->rstc);