0001
0002
0003
0004
0005
0006
0007
0008 #include <linux/device.h>
0009 #include <linux/gfp.h>
0010 #include <linux/input.h>
0011 #include <linux/interrupt.h>
0012 #include <linux/mod_devicetable.h>
0013 #include <linux/module.h>
0014 #include <linux/spi/spi.h>
0015
0016 #define RESP_COUNTER(response) (response.header & 0x3)
0017 #define RESP_SIZE(response) ((response.header >> 2) & 0x3)
0018 #define RESP_TYPE(response) ((response.header >> 4) & 0xf)
0019
0020 struct ec_input_response {
0021 u8 reserved;
0022 u8 header;
0023 u8 data[3];
0024 } __packed;
0025
0026 struct ariel_pwrbutton {
0027 struct spi_device *client;
0028 struct input_dev *input;
0029 u8 msg_counter;
0030 };
0031
0032 static int ec_input_read(struct ariel_pwrbutton *priv,
0033 struct ec_input_response *response)
0034 {
0035 u8 read_request[] = { 0x00, 0x5a, 0xa5, 0x00, 0x00 };
0036 struct spi_device *spi = priv->client;
0037 struct spi_transfer t = {
0038 .tx_buf = read_request,
0039 .rx_buf = response,
0040 .len = sizeof(read_request),
0041 };
0042
0043 compiletime_assert(sizeof(read_request) == sizeof(*response),
0044 "SPI xfer request/response size mismatch");
0045
0046 return spi_sync_transfer(spi, &t, 1);
0047 }
0048
0049 static irqreturn_t ec_input_interrupt(int irq, void *dev_id)
0050 {
0051 struct ariel_pwrbutton *priv = dev_id;
0052 struct spi_device *spi = priv->client;
0053 struct ec_input_response response;
0054 int error;
0055 int i;
0056
0057 error = ec_input_read(priv, &response);
0058 if (error < 0) {
0059 dev_err(&spi->dev, "EC read failed: %d\n", error);
0060 goto out;
0061 }
0062
0063 if (priv->msg_counter == RESP_COUNTER(response)) {
0064 dev_warn(&spi->dev, "No new data to read?\n");
0065 goto out;
0066 }
0067
0068 priv->msg_counter = RESP_COUNTER(response);
0069
0070 if (RESP_TYPE(response) != 0x3 && RESP_TYPE(response) != 0xc) {
0071 dev_dbg(&spi->dev, "Ignoring message that's not kbd data\n");
0072 goto out;
0073 }
0074
0075 for (i = 0; i < RESP_SIZE(response); i++) {
0076 switch (response.data[i]) {
0077 case 0x74:
0078 input_report_key(priv->input, KEY_POWER, 1);
0079 input_sync(priv->input);
0080 break;
0081 case 0xf4:
0082 input_report_key(priv->input, KEY_POWER, 0);
0083 input_sync(priv->input);
0084 break;
0085 default:
0086 dev_dbg(&spi->dev, "Unknown scan code: %02x\n",
0087 response.data[i]);
0088 }
0089 }
0090
0091 out:
0092 return IRQ_HANDLED;
0093 }
0094
0095 static int ariel_pwrbutton_probe(struct spi_device *spi)
0096 {
0097 struct ec_input_response response;
0098 struct ariel_pwrbutton *priv;
0099 int error;
0100
0101 if (!spi->irq) {
0102 dev_err(&spi->dev, "Missing IRQ.\n");
0103 return -EINVAL;
0104 }
0105
0106 priv = devm_kzalloc(&spi->dev, sizeof(*priv), GFP_KERNEL);
0107 if (!priv)
0108 return -ENOMEM;
0109
0110 priv->client = spi;
0111 spi_set_drvdata(spi, priv);
0112
0113 priv->input = devm_input_allocate_device(&spi->dev);
0114 if (!priv->input)
0115 return -ENOMEM;
0116 priv->input->name = "Power Button";
0117 priv->input->dev.parent = &spi->dev;
0118 input_set_capability(priv->input, EV_KEY, KEY_POWER);
0119 error = input_register_device(priv->input);
0120 if (error) {
0121 dev_err(&spi->dev, "error registering input device: %d\n", error);
0122 return error;
0123 }
0124
0125 error = ec_input_read(priv, &response);
0126 if (error < 0) {
0127 dev_err(&spi->dev, "EC read failed: %d\n", error);
0128 return error;
0129 }
0130 priv->msg_counter = RESP_COUNTER(response);
0131
0132 error = devm_request_threaded_irq(&spi->dev, spi->irq, NULL,
0133 ec_input_interrupt,
0134 IRQF_ONESHOT,
0135 "Ariel EC Input", priv);
0136
0137 if (error) {
0138 dev_err(&spi->dev, "Failed to request IRQ %d: %d\n",
0139 spi->irq, error);
0140 return error;
0141 }
0142
0143 return 0;
0144 }
0145
0146 static const struct of_device_id ariel_pwrbutton_of_match[] = {
0147 { .compatible = "dell,wyse-ariel-ec-input" },
0148 { }
0149 };
0150 MODULE_DEVICE_TABLE(of, ariel_pwrbutton_of_match);
0151
0152 static const struct spi_device_id ariel_pwrbutton_spi_ids[] = {
0153 { .name = "wyse-ariel-ec-input" },
0154 { }
0155 };
0156 MODULE_DEVICE_TABLE(spi, ariel_pwrbutton_spi_ids);
0157
0158 static struct spi_driver ariel_pwrbutton_driver = {
0159 .driver = {
0160 .name = "dell-wyse-ariel-ec-input",
0161 .of_match_table = ariel_pwrbutton_of_match,
0162 },
0163 .probe = ariel_pwrbutton_probe,
0164 .id_table = ariel_pwrbutton_spi_ids,
0165 };
0166 module_spi_driver(ariel_pwrbutton_driver);
0167
0168 MODULE_AUTHOR("Lubomir Rintel <lkundrak@v3.sk>");
0169 MODULE_DESCRIPTION("Dell Wyse 3020 Power Button Input Driver");
0170 MODULE_LICENSE("Dual BSD/GPL");