0001
0002
0003
0004
0005
0006 #include <linux/err.h>
0007 #include <linux/device.h>
0008 #include <linux/firmware/imx/sci.h>
0009 #include <linux/init.h>
0010 #include <linux/input.h>
0011 #include <linux/interrupt.h>
0012 #include <linux/jiffies.h>
0013 #include <linux/kernel.h>
0014 #include <linux/module.h>
0015 #include <linux/of.h>
0016 #include <linux/platform_device.h>
0017 #include <linux/property.h>
0018
0019 #define DEBOUNCE_TIME 30
0020 #define REPEAT_INTERVAL 60
0021
0022 #define SC_IRQ_BUTTON 1
0023 #define SC_IRQ_GROUP_WAKE 3
0024
0025 #define IMX_SC_MISC_FUNC_GET_BUTTON_STATUS 18
0026
0027 struct imx_key_drv_data {
0028 u32 keycode;
0029 bool keystate;
0030 struct delayed_work check_work;
0031 struct input_dev *input;
0032 struct imx_sc_ipc *key_ipc_handle;
0033 struct notifier_block key_notifier;
0034 };
0035
0036 struct imx_sc_msg_key {
0037 struct imx_sc_rpc_msg hdr;
0038 u32 state;
0039 };
0040
0041 static int imx_sc_key_notify(struct notifier_block *nb,
0042 unsigned long event, void *group)
0043 {
0044 struct imx_key_drv_data *priv =
0045 container_of(nb,
0046 struct imx_key_drv_data,
0047 key_notifier);
0048
0049 if ((event & SC_IRQ_BUTTON) && (*(u8 *)group == SC_IRQ_GROUP_WAKE)) {
0050 schedule_delayed_work(&priv->check_work,
0051 msecs_to_jiffies(DEBOUNCE_TIME));
0052 pm_wakeup_event(priv->input->dev.parent, 0);
0053 }
0054
0055 return 0;
0056 }
0057
0058 static void imx_sc_check_for_events(struct work_struct *work)
0059 {
0060 struct imx_key_drv_data *priv =
0061 container_of(work,
0062 struct imx_key_drv_data,
0063 check_work.work);
0064 struct input_dev *input = priv->input;
0065 struct imx_sc_msg_key msg;
0066 struct imx_sc_rpc_msg *hdr = &msg.hdr;
0067 bool state;
0068 int error;
0069
0070 hdr->ver = IMX_SC_RPC_VERSION;
0071 hdr->svc = IMX_SC_RPC_SVC_MISC;
0072 hdr->func = IMX_SC_MISC_FUNC_GET_BUTTON_STATUS;
0073 hdr->size = 1;
0074
0075 error = imx_scu_call_rpc(priv->key_ipc_handle, &msg, true);
0076 if (error) {
0077 dev_err(&input->dev, "read imx sc key failed, error %d\n", error);
0078 return;
0079 }
0080
0081
0082
0083
0084
0085
0086
0087 state = (bool)(msg.state & 0xff);
0088
0089 if (state ^ priv->keystate) {
0090 priv->keystate = state;
0091 input_event(input, EV_KEY, priv->keycode, state);
0092 input_sync(input);
0093 if (!priv->keystate)
0094 pm_relax(priv->input->dev.parent);
0095 }
0096
0097 if (state)
0098 schedule_delayed_work(&priv->check_work,
0099 msecs_to_jiffies(REPEAT_INTERVAL));
0100 }
0101
0102 static void imx_sc_key_action(void *data)
0103 {
0104 struct imx_key_drv_data *priv = data;
0105
0106 imx_scu_irq_group_enable(SC_IRQ_GROUP_WAKE, SC_IRQ_BUTTON, false);
0107 imx_scu_irq_unregister_notifier(&priv->key_notifier);
0108 cancel_delayed_work_sync(&priv->check_work);
0109 }
0110
0111 static int imx_sc_key_probe(struct platform_device *pdev)
0112 {
0113 struct imx_key_drv_data *priv;
0114 struct input_dev *input;
0115 int error;
0116
0117 priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
0118 if (!priv)
0119 return -ENOMEM;
0120
0121 error = imx_scu_get_handle(&priv->key_ipc_handle);
0122 if (error)
0123 return error;
0124
0125 if (device_property_read_u32(&pdev->dev, "linux,keycodes",
0126 &priv->keycode)) {
0127 dev_err(&pdev->dev, "missing linux,keycodes property\n");
0128 return -EINVAL;
0129 }
0130
0131 INIT_DELAYED_WORK(&priv->check_work, imx_sc_check_for_events);
0132
0133 input = devm_input_allocate_device(&pdev->dev);
0134 if (!input) {
0135 dev_err(&pdev->dev, "failed to allocate the input device\n");
0136 return -ENOMEM;
0137 }
0138
0139 input->name = pdev->name;
0140 input->phys = "imx-sc-key/input0";
0141 input->id.bustype = BUS_HOST;
0142
0143 input_set_capability(input, EV_KEY, priv->keycode);
0144
0145 error = input_register_device(input);
0146 if (error) {
0147 dev_err(&pdev->dev, "failed to register input device\n");
0148 return error;
0149 }
0150
0151 priv->input = input;
0152 platform_set_drvdata(pdev, priv);
0153
0154 error = imx_scu_irq_group_enable(SC_IRQ_GROUP_WAKE, SC_IRQ_BUTTON,
0155 true);
0156 if (error) {
0157 dev_err(&pdev->dev, "failed to enable scu group irq\n");
0158 return error;
0159 }
0160
0161 error = devm_add_action_or_reset(&pdev->dev, imx_sc_key_action, &priv);
0162 if (error)
0163 return error;
0164
0165 priv->key_notifier.notifier_call = imx_sc_key_notify;
0166 error = imx_scu_irq_register_notifier(&priv->key_notifier);
0167 if (error)
0168 dev_err(&pdev->dev, "failed to register scu notifier\n");
0169
0170 return error;
0171 }
0172
0173 static const struct of_device_id imx_sc_key_ids[] = {
0174 { .compatible = "fsl,imx-sc-key" },
0175 { }
0176 };
0177 MODULE_DEVICE_TABLE(of, imx_sc_key_ids);
0178
0179 static struct platform_driver imx_sc_key_driver = {
0180 .driver = {
0181 .name = "imx-sc-key",
0182 .of_match_table = imx_sc_key_ids,
0183 },
0184 .probe = imx_sc_key_probe,
0185 };
0186 module_platform_driver(imx_sc_key_driver);
0187
0188 MODULE_AUTHOR("Anson Huang <Anson.Huang@nxp.com>");
0189 MODULE_DESCRIPTION("i.MX System Controller Key Driver");
0190 MODULE_LICENSE("GPL v2");