浏览代码

rtc: imxdi: use the security violation interrupt

The DryIce chipset has a dedicated security violation interrupt that is
triggered for security violations (if configured to do so).  According
to the publicly available imx258 reference manual, irq 56 is used for
this interrupt.

If an irq number is provided for the security violation interrupt,
install the same handler that we're already using for the "normal"
interrupt.

imxdi->irq is used only in the probe function, make it a local variable.

Signed-off-by: Martin Kaiser <martin@kaiser.cx>
Signed-off-by: Alexandre Belloni <alexandre.belloni@free-electrons.com>
Martin Kaiser 8 年之前
父节点
当前提交
fef1eeb1a7
共有 1 个文件被更改,包括 22 次插入9 次删除
  1. 22 9
      drivers/rtc/rtc-imxdi.c

+ 22 - 9
drivers/rtc/rtc-imxdi.c

@@ -108,7 +108,6 @@
  * @pdev: pionter to platform dev
  * @pdev: pionter to platform dev
  * @rtc: pointer to rtc struct
  * @rtc: pointer to rtc struct
  * @ioaddr: IO registers pointer
  * @ioaddr: IO registers pointer
- * @irq: dryice normal interrupt
  * @clk: input reference clock
  * @clk: input reference clock
  * @dsr: copy of the DSR register
  * @dsr: copy of the DSR register
  * @irq_lock: interrupt enable register (DIER) lock
  * @irq_lock: interrupt enable register (DIER) lock
@@ -120,7 +119,6 @@ struct imxdi_dev {
 	struct platform_device *pdev;
 	struct platform_device *pdev;
 	struct rtc_device *rtc;
 	struct rtc_device *rtc;
 	void __iomem *ioaddr;
 	void __iomem *ioaddr;
-	int irq;
 	struct clk *clk;
 	struct clk *clk;
 	u32 dsr;
 	u32 dsr;
 	spinlock_t irq_lock;
 	spinlock_t irq_lock;
@@ -677,9 +675,9 @@ static struct rtc_class_ops dryice_rtc_ops = {
 };
 };
 
 
 /*
 /*
- * dryice "normal" interrupt handler
+ * interrupt handler for dryice "normal" and security violation interrupt
  */
  */
-static irqreturn_t dryice_norm_irq(int irq, void *dev_id)
+static irqreturn_t dryice_irq(int irq, void *dev_id)
 {
 {
 	struct imxdi_dev *imxdi = dev_id;
 	struct imxdi_dev *imxdi = dev_id;
 	u32 dsr, dier;
 	u32 dsr, dier;
@@ -765,6 +763,7 @@ static int __init dryice_rtc_probe(struct platform_device *pdev)
 {
 {
 	struct resource *res;
 	struct resource *res;
 	struct imxdi_dev *imxdi;
 	struct imxdi_dev *imxdi;
+	int norm_irq, sec_irq;
 	int rc;
 	int rc;
 
 
 	imxdi = devm_kzalloc(&pdev->dev, sizeof(*imxdi), GFP_KERNEL);
 	imxdi = devm_kzalloc(&pdev->dev, sizeof(*imxdi), GFP_KERNEL);
@@ -780,9 +779,16 @@ static int __init dryice_rtc_probe(struct platform_device *pdev)
 
 
 	spin_lock_init(&imxdi->irq_lock);
 	spin_lock_init(&imxdi->irq_lock);
 
 
-	imxdi->irq = platform_get_irq(pdev, 0);
-	if (imxdi->irq < 0)
-		return imxdi->irq;
+	norm_irq = platform_get_irq(pdev, 0);
+	if (norm_irq < 0)
+		return norm_irq;
+
+	/* the 2nd irq is the security violation irq
+	 * make this optional, don't break the device tree ABI
+	 */
+	sec_irq = platform_get_irq(pdev, 1);
+	if (sec_irq <= 0)
+		sec_irq = IRQ_NOTCONNECTED;
 
 
 	init_waitqueue_head(&imxdi->write_wait);
 	init_waitqueue_head(&imxdi->write_wait);
 
 
@@ -808,13 +814,20 @@ static int __init dryice_rtc_probe(struct platform_device *pdev)
 	if (rc != 0)
 	if (rc != 0)
 		goto err;
 		goto err;
 
 
-	rc = devm_request_irq(&pdev->dev, imxdi->irq, dryice_norm_irq,
-			IRQF_SHARED, pdev->name, imxdi);
+	rc = devm_request_irq(&pdev->dev, norm_irq, dryice_irq,
+			      IRQF_SHARED, pdev->name, imxdi);
 	if (rc) {
 	if (rc) {
 		dev_warn(&pdev->dev, "interrupt not available.\n");
 		dev_warn(&pdev->dev, "interrupt not available.\n");
 		goto err;
 		goto err;
 	}
 	}
 
 
+	rc = devm_request_irq(&pdev->dev, sec_irq, dryice_irq,
+			      IRQF_SHARED, pdev->name, imxdi);
+	if (rc) {
+		dev_warn(&pdev->dev, "security violation interrupt not available.\n");
+		/* this is not an error, see above */
+	}
+
 	platform_set_drvdata(pdev, imxdi);
 	platform_set_drvdata(pdev, imxdi);
 	imxdi->rtc = devm_rtc_device_register(&pdev->dev, pdev->name,
 	imxdi->rtc = devm_rtc_device_register(&pdev->dev, pdev->name,
 				  &dryice_rtc_ops, THIS_MODULE);
 				  &dryice_rtc_ops, THIS_MODULE);