Skip to content

Commit

Permalink
Input: sirfsoc_pwrc - add onkey input driver for CSR SiRFprimaII PWRC
Browse files Browse the repository at this point in the history
There is an embedded PWRC(power controller) in SiRFprimaII and SiRFatlasVI,
we have an ONKEY button which can generate interrupt to IRQ controller.
In a typical user scenarios, at the runtime, if users touch the key, we put
system to s2ram status.

Signed-off-by: Binghua Duan <Binghua.Duan@csr.com>
Signed-off-by: Xianglong Du <Xianglong.Du@csr.com>
Signed-off-by: Barry Song <Baohua.Song@csr.com>
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
  • Loading branch information
Binghua Duan authored and Dmitry Torokhov committed Jun 3, 2013
1 parent f6e63f8 commit 9b5f953
Show file tree
Hide file tree
Showing 3 changed files with 176 additions and 0 deletions.
10 changes: 10 additions & 0 deletions drivers/input/misc/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -637,4 +637,14 @@ config INPUT_XEN_KBDDEV_FRONTEND
To compile this driver as a module, choose M here: the
module will be called xen-kbdfront.

config INPUT_SIRFSOC_ONKEY
bool "CSR SiRFSoC power on/off/suspend key support"
depends on ARCH_SIRF && OF
default y
help
Say Y here if you want to support for the SiRFSoC power on/off/suspend key
in Linux, after you press the onkey, system will suspend.

If unsure, say N.

endif
1 change: 1 addition & 0 deletions drivers/input/misc/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ obj-$(CONFIG_INPUT_RB532_BUTTON) += rb532_button.o
obj-$(CONFIG_INPUT_RETU_PWRBUTTON) += retu-pwrbutton.o
obj-$(CONFIG_INPUT_GPIO_ROTARY_ENCODER) += rotary_encoder.o
obj-$(CONFIG_INPUT_SGI_BTNS) += sgi_btns.o
obj-$(CONFIG_INPUT_SIRFSOC_ONKEY) += sirfsoc-onkey.o
obj-$(CONFIG_INPUT_SPARCSPKR) += sparcspkr.o
obj-$(CONFIG_INPUT_TWL4030_PWRBUTTON) += twl4030-pwrbutton.o
obj-$(CONFIG_INPUT_TWL4030_VIBRA) += twl4030-vibra.o
Expand Down
165 changes: 165 additions & 0 deletions drivers/input/misc/sirfsoc-onkey.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
/*
* Power key driver for SiRF PrimaII
*
* Copyright (c) 2013 Cambridge Silicon Radio Limited, a CSR plc group company.
*
* Licensed under GPLv2 or later.
*/

#include <linux/module.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/delay.h>
#include <linux/platform_device.h>
#include <linux/input.h>
#include <linux/rtc/sirfsoc_rtciobrg.h>
#include <linux/of.h>

struct sirfsoc_pwrc_drvdata {
u32 pwrc_base;
struct input_dev *input;
};

#define PWRC_ON_KEY_BIT (1 << 0)

#define PWRC_INT_STATUS 0xc
#define PWRC_INT_MASK 0x10

static irqreturn_t sirfsoc_pwrc_isr(int irq, void *dev_id)
{
struct sirfsoc_pwrc_drvdata *pwrcdrv = dev_id;
u32 int_status;

int_status = sirfsoc_rtc_iobrg_readl(pwrcdrv->pwrc_base +
PWRC_INT_STATUS);
sirfsoc_rtc_iobrg_writel(int_status & ~PWRC_ON_KEY_BIT,
pwrcdrv->pwrc_base + PWRC_INT_STATUS);

/*
* For a typical Linux system, we report KEY_SUSPEND to trigger apm-power.c
* to queue a SUSPEND APM event
*/
input_event(pwrcdrv->input, EV_PWR, KEY_SUSPEND, 1);
input_sync(pwrcdrv->input);

/*
* Todo: report KEY_POWER event for Android platforms, Android PowerManager
* will handle the suspend and powerdown/hibernation
*/

return IRQ_HANDLED;
}

static const struct of_device_id sirfsoc_pwrc_of_match[] = {
{ .compatible = "sirf,prima2-pwrc" },
{},
}
MODULE_DEVICE_TABLE(of, sirfsoc_pwrc_of_match);

static int sirfsoc_pwrc_probe(struct platform_device *pdev)
{
struct device_node *np = pdev->dev.of_node;
struct sirfsoc_pwrc_drvdata *pwrcdrv;
int irq;
int error;

pwrcdrv = devm_kzalloc(&pdev->dev, sizeof(struct sirfsoc_pwrc_drvdata),
GFP_KERNEL);
if (!pwrcdrv) {
dev_info(&pdev->dev, "Not enough memory for the device data\n");
return -ENOMEM;
}

/*
* 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);
if (error) {
dev_err(&pdev->dev,
"unable to find base address of pwrc node in dtb\n");
return error;
}

pwrcdrv->input = devm_input_allocate_device(&pdev->dev);
if (!pwrcdrv->input)
return -ENOMEM;

pwrcdrv->input->name = "sirfsoc pwrckey";
pwrcdrv->input->phys = "pwrc/input0";
pwrcdrv->input->evbit[0] = BIT_MASK(EV_PWR);

irq = platform_get_irq(pdev, 0);
error = devm_request_irq(&pdev->dev, irq,
sirfsoc_pwrc_isr, IRQF_SHARED,
"sirfsoc_pwrc_int", pwrcdrv);
if (error) {
dev_err(&pdev->dev, "unable to claim irq %d, error: %d\n",
irq, error);
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,
"unable to register input device, error: %d\n",
error);
return error;
}

platform_set_drvdata(pdev, pwrcdrv);
device_init_wakeup(&pdev->dev, 1);

return 0;
}

static int sirfsoc_pwrc_remove(struct platform_device *pdev)
{
device_init_wakeup(&pdev->dev, 0);

return 0;
}

#ifdef CONFIG_PM_SLEEP
static int pwrc_resume(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
struct sirfsoc_pwrc_drvdata *pwrcdrv = platform_get_drvdata(pdev);

/*
* 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);

return 0;
}
#endif

static SIMPLE_DEV_PM_OPS(sirfsoc_pwrc_pm_ops, NULL, pwrc_resume);

static struct platform_driver sirfsoc_pwrc_driver = {
.probe = sirfsoc_pwrc_probe,
.remove = sirfsoc_pwrc_remove,
.driver = {
.name = "sirfsoc-pwrc",
.owner = THIS_MODULE,
.pm = &sirfsoc_pwrc_pm_ops,
.of_match_table = of_match_ptr(sirfsoc_pwrc_of_match),
}
};

module_platform_driver(sirfsoc_pwrc_driver);

MODULE_LICENSE("GPLv2");
MODULE_AUTHOR("Binghua Duan <Binghua.Duan@csr.com>, Xianglong Du <Xianglong.Du@csr.com>");
MODULE_DESCRIPTION("CSR Prima2 PWRC Driver");
MODULE_ALIAS("platform:sirfsoc-pwrc");

0 comments on commit 9b5f953

Please sign in to comment.