0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020 #include <linux/irq.h>
0021 #include <linux/platform_data/ams-delta-fiq.h>
0022 #include <linux/platform_device.h>
0023 #include <linux/regulator/consumer.h>
0024 #include <linux/serio.h>
0025 #include <linux/slab.h>
0026 #include <linux/module.h>
0027
0028 #define DRIVER_NAME "ams-delta-serio"
0029
0030 MODULE_AUTHOR("Matt Callow");
0031 MODULE_DESCRIPTION("AMS Delta (E3) keyboard port driver");
0032 MODULE_LICENSE("GPL");
0033
0034 struct ams_delta_serio {
0035 struct serio *serio;
0036 struct regulator *vcc;
0037 unsigned int *fiq_buffer;
0038 };
0039
0040 static int check_data(struct serio *serio, int data)
0041 {
0042 int i, parity = 0;
0043
0044
0045 if (!(data & 0x400)) {
0046 dev_warn(&serio->dev, "invalid stop bit, data=0x%X\n", data);
0047 return SERIO_FRAME;
0048 }
0049
0050 for (i = 1; i < 10; i++) {
0051 if (data & (1 << i))
0052 parity++;
0053 }
0054
0055 if (!(parity & 0x01)) {
0056 dev_warn(&serio->dev,
0057 "parity check failed, data=0x%X parity=0x%X\n", data,
0058 parity);
0059 return SERIO_PARITY;
0060 }
0061 return 0;
0062 }
0063
0064 static irqreturn_t ams_delta_serio_interrupt(int irq, void *dev_id)
0065 {
0066 struct ams_delta_serio *priv = dev_id;
0067 int *circ_buff = &priv->fiq_buffer[FIQ_CIRC_BUFF];
0068 int data, dfl;
0069 u8 scancode;
0070
0071 priv->fiq_buffer[FIQ_IRQ_PEND] = 0;
0072
0073
0074
0075
0076
0077 while (priv->fiq_buffer[FIQ_KEYS_CNT] > 0) {
0078
0079 data = circ_buff[priv->fiq_buffer[FIQ_HEAD_OFFSET]++];
0080 priv->fiq_buffer[FIQ_KEYS_CNT]--;
0081 if (priv->fiq_buffer[FIQ_HEAD_OFFSET] ==
0082 priv->fiq_buffer[FIQ_BUF_LEN])
0083 priv->fiq_buffer[FIQ_HEAD_OFFSET] = 0;
0084
0085 dfl = check_data(priv->serio, data);
0086 scancode = (u8) (data >> 1) & 0xFF;
0087 serio_interrupt(priv->serio, scancode, dfl);
0088 }
0089 return IRQ_HANDLED;
0090 }
0091
0092 static int ams_delta_serio_open(struct serio *serio)
0093 {
0094 struct ams_delta_serio *priv = serio->port_data;
0095
0096
0097 return regulator_enable(priv->vcc);
0098 }
0099
0100 static void ams_delta_serio_close(struct serio *serio)
0101 {
0102 struct ams_delta_serio *priv = serio->port_data;
0103
0104
0105 regulator_disable(priv->vcc);
0106 }
0107
0108 static int ams_delta_serio_init(struct platform_device *pdev)
0109 {
0110 struct ams_delta_serio *priv;
0111 struct serio *serio;
0112 int irq, err;
0113
0114 priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
0115 if (!priv)
0116 return -ENOMEM;
0117
0118 priv->fiq_buffer = pdev->dev.platform_data;
0119 if (!priv->fiq_buffer)
0120 return -EINVAL;
0121
0122 priv->vcc = devm_regulator_get(&pdev->dev, "vcc");
0123 if (IS_ERR(priv->vcc)) {
0124 err = PTR_ERR(priv->vcc);
0125 dev_err(&pdev->dev, "regulator request failed (%d)\n", err);
0126
0127
0128
0129
0130
0131
0132
0133
0134
0135
0136
0137 if (err == -ENODEV)
0138 err = -EPROBE_DEFER;
0139 return err;
0140 }
0141
0142 irq = platform_get_irq(pdev, 0);
0143 if (irq < 0)
0144 return -ENXIO;
0145
0146 err = devm_request_irq(&pdev->dev, irq, ams_delta_serio_interrupt,
0147 IRQ_TYPE_EDGE_RISING, DRIVER_NAME, priv);
0148 if (err < 0) {
0149 dev_err(&pdev->dev, "IRQ request failed (%d)\n", err);
0150 return err;
0151 }
0152
0153 serio = kzalloc(sizeof(*serio), GFP_KERNEL);
0154 if (!serio)
0155 return -ENOMEM;
0156
0157 priv->serio = serio;
0158
0159 serio->id.type = SERIO_8042;
0160 serio->open = ams_delta_serio_open;
0161 serio->close = ams_delta_serio_close;
0162 strlcpy(serio->name, "AMS DELTA keyboard adapter", sizeof(serio->name));
0163 strlcpy(serio->phys, dev_name(&pdev->dev), sizeof(serio->phys));
0164 serio->dev.parent = &pdev->dev;
0165 serio->port_data = priv;
0166
0167 serio_register_port(serio);
0168
0169 platform_set_drvdata(pdev, priv);
0170
0171 dev_info(&serio->dev, "%s\n", serio->name);
0172
0173 return 0;
0174 }
0175
0176 static int ams_delta_serio_exit(struct platform_device *pdev)
0177 {
0178 struct ams_delta_serio *priv = platform_get_drvdata(pdev);
0179
0180 serio_unregister_port(priv->serio);
0181
0182 return 0;
0183 }
0184
0185 static struct platform_driver ams_delta_serio_driver = {
0186 .probe = ams_delta_serio_init,
0187 .remove = ams_delta_serio_exit,
0188 .driver = {
0189 .name = DRIVER_NAME
0190 },
0191 };
0192 module_platform_driver(ams_delta_serio_driver);