|
|
@@ -49,6 +49,35 @@ static irqreturn_t sirfsoc_pwrc_isr(int irq, void *dev_id)
|
|
|
return IRQ_HANDLED;
|
|
|
}
|
|
|
|
|
|
+static void sirfsoc_pwrc_toggle_interrupts(struct sirfsoc_pwrc_drvdata *pwrcdrv,
|
|
|
+ bool enable)
|
|
|
+{
|
|
|
+ u32 int_mask;
|
|
|
+
|
|
|
+ int_mask = sirfsoc_rtc_iobrg_readl(pwrcdrv->pwrc_base + PWRC_INT_MASK);
|
|
|
+ if (enable)
|
|
|
+ int_mask |= PWRC_ON_KEY_BIT;
|
|
|
+ else
|
|
|
+ int_mask &= ~PWRC_ON_KEY_BIT;
|
|
|
+ sirfsoc_rtc_iobrg_writel(int_mask, pwrcdrv->pwrc_base + PWRC_INT_MASK);
|
|
|
+}
|
|
|
+
|
|
|
+static int sirfsoc_pwrc_open(struct input_dev *input)
|
|
|
+{
|
|
|
+ struct sirfsoc_pwrc_drvdata *pwrcdrv = input_get_drvdata(input);
|
|
|
+
|
|
|
+ sirfsoc_pwrc_toggle_interrupts(pwrcdrv, true);
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+static void sirfsoc_pwrc_close(struct input_dev *input)
|
|
|
+{
|
|
|
+ struct sirfsoc_pwrc_drvdata *pwrcdrv = input_get_drvdata(input);
|
|
|
+
|
|
|
+ sirfsoc_pwrc_toggle_interrupts(pwrcdrv, false);
|
|
|
+}
|
|
|
+
|
|
|
static const struct of_device_id sirfsoc_pwrc_of_match[] = {
|
|
|
{ .compatible = "sirf,prima2-pwrc" },
|
|
|
{},
|
|
|
@@ -70,7 +99,7 @@ static int sirfsoc_pwrc_probe(struct platform_device *pdev)
|
|
|
}
|
|
|
|
|
|
/*
|
|
|
- * we can't use of_iomap because pwrc is not mapped in memory,
|
|
|
+ * We can't use of_iomap because pwrc is not mapped in memory,
|
|
|
* the so-called base address is only offset in rtciobrg
|
|
|
*/
|
|
|
error = of_property_read_u32(np, "reg", &pwrcdrv->pwrc_base);
|
|
|
@@ -88,6 +117,14 @@ static int sirfsoc_pwrc_probe(struct platform_device *pdev)
|
|
|
pwrcdrv->input->phys = "pwrc/input0";
|
|
|
pwrcdrv->input->evbit[0] = BIT_MASK(EV_PWR);
|
|
|
|
|
|
+ pwrcdrv->input->open = sirfsoc_pwrc_open;
|
|
|
+ pwrcdrv->input->close = sirfsoc_pwrc_close;
|
|
|
+
|
|
|
+ input_set_drvdata(pwrcdrv->input, pwrcdrv);
|
|
|
+
|
|
|
+ /* Make sure the device is quiesced */
|
|
|
+ sirfsoc_pwrc_toggle_interrupts(pwrcdrv, false);
|
|
|
+
|
|
|
irq = platform_get_irq(pdev, 0);
|
|
|
error = devm_request_irq(&pdev->dev, irq,
|
|
|
sirfsoc_pwrc_isr, IRQF_SHARED,
|
|
|
@@ -98,11 +135,6 @@ static int sirfsoc_pwrc_probe(struct platform_device *pdev)
|
|
|
return error;
|
|
|
}
|
|
|
|
|
|
- sirfsoc_rtc_iobrg_writel(
|
|
|
- sirfsoc_rtc_iobrg_readl(pwrcdrv->pwrc_base + PWRC_INT_MASK) |
|
|
|
- PWRC_ON_KEY_BIT,
|
|
|
- pwrcdrv->pwrc_base + PWRC_INT_MASK);
|
|
|
-
|
|
|
error = input_register_device(pwrcdrv->input);
|
|
|
if (error) {
|
|
|
dev_err(&pdev->dev,
|
|
|
@@ -129,15 +161,16 @@ static int pwrc_resume(struct device *dev)
|
|
|
{
|
|
|
struct platform_device *pdev = to_platform_device(dev);
|
|
|
struct sirfsoc_pwrc_drvdata *pwrcdrv = platform_get_drvdata(pdev);
|
|
|
+ struct input_dev *input = pwrcdrv->input;
|
|
|
|
|
|
/*
|
|
|
* Do not mask pwrc interrupt as we want pwrc work as a wakeup source
|
|
|
* if users touch X_ONKEY_B, see arch/arm/mach-prima2/pm.c
|
|
|
*/
|
|
|
- sirfsoc_rtc_iobrg_writel(
|
|
|
- sirfsoc_rtc_iobrg_readl(
|
|
|
- pwrcdrv->pwrc_base + PWRC_INT_MASK) | PWRC_ON_KEY_BIT,
|
|
|
- pwrcdrv->pwrc_base + PWRC_INT_MASK);
|
|
|
+ mutex_lock(&input->mutex);
|
|
|
+ if (input->users)
|
|
|
+ sirfsoc_pwrc_toggle_interrupts(pwrcdrv, true);
|
|
|
+ mutex_unlock(&input->mutex);
|
|
|
|
|
|
return 0;
|
|
|
}
|