1 /* 2 * Amstrad E3 (Delta) keyboard port driver 3 * 4 * Copyright (c) 2006 Matt Callow 5 * Copyright (c) 2010 Janusz Krzysztofik 6 * 7 * This program is free software; you can redistribute it and/or modify it 8 * under the terms of the GNU General Public License version 2 as published by 9 * the Free Software Foundation. 10 * 11 * Thanks to Cliff Lawson for his help 12 * 13 * The Amstrad Delta keyboard (aka mailboard) uses normal PC-AT style serial 14 * transmission. The keyboard port is formed of two GPIO lines, for clock 15 * and data. Due to strict timing requirements of the interface, 16 * the serial data stream is read and processed by a FIQ handler. 17 * The resulting words are fetched by this driver from a circular buffer. 18 * 19 * Standard AT keyboard driver (atkbd) is used for handling the keyboard data. 20 * However, when used with the E3 mailboard that producecs non-standard 21 * scancodes, a custom key table must be prepared and loaded from userspace. 22 */ 23 #include <linux/irq.h> 24 #include <linux/platform_data/ams-delta-fiq.h> 25 #include <linux/platform_device.h> 26 #include <linux/regulator/consumer.h> 27 #include <linux/serio.h> 28 #include <linux/slab.h> 29 #include <linux/module.h> 30 31 #define DRIVER_NAME "ams-delta-serio" 32 33 MODULE_AUTHOR("Matt Callow"); 34 MODULE_DESCRIPTION("AMS Delta (E3) keyboard port driver"); 35 MODULE_LICENSE("GPL"); 36 37 struct ams_delta_serio { 38 struct serio *serio; 39 struct regulator *vcc; 40 unsigned int *fiq_buffer; 41 }; 42 43 static int check_data(struct serio *serio, int data) 44 { 45 int i, parity = 0; 46 47 /* check valid stop bit */ 48 if (!(data & 0x400)) { 49 dev_warn(&serio->dev, "invalid stop bit, data=0x%X\n", data); 50 return SERIO_FRAME; 51 } 52 /* calculate the parity */ 53 for (i = 1; i < 10; i++) { 54 if (data & (1 << i)) 55 parity++; 56 } 57 /* it should be odd */ 58 if (!(parity & 0x01)) { 59 dev_warn(&serio->dev, 60 "parity check failed, data=0x%X parity=0x%X\n", data, 61 parity); 62 return SERIO_PARITY; 63 } 64 return 0; 65 } 66 67 static irqreturn_t ams_delta_serio_interrupt(int irq, void *dev_id) 68 { 69 struct ams_delta_serio *priv = dev_id; 70 int *circ_buff = &priv->fiq_buffer[FIQ_CIRC_BUFF]; 71 int data, dfl; 72 u8 scancode; 73 74 priv->fiq_buffer[FIQ_IRQ_PEND] = 0; 75 76 /* 77 * Read data from the circular buffer, check it 78 * and then pass it on the serio 79 */ 80 while (priv->fiq_buffer[FIQ_KEYS_CNT] > 0) { 81 82 data = circ_buff[priv->fiq_buffer[FIQ_HEAD_OFFSET]++]; 83 priv->fiq_buffer[FIQ_KEYS_CNT]--; 84 if (priv->fiq_buffer[FIQ_HEAD_OFFSET] == 85 priv->fiq_buffer[FIQ_BUF_LEN]) 86 priv->fiq_buffer[FIQ_HEAD_OFFSET] = 0; 87 88 dfl = check_data(priv->serio, data); 89 scancode = (u8) (data >> 1) & 0xFF; 90 serio_interrupt(priv->serio, scancode, dfl); 91 } 92 return IRQ_HANDLED; 93 } 94 95 static int ams_delta_serio_open(struct serio *serio) 96 { 97 struct ams_delta_serio *priv = serio->port_data; 98 99 /* enable keyboard */ 100 return regulator_enable(priv->vcc); 101 } 102 103 static void ams_delta_serio_close(struct serio *serio) 104 { 105 struct ams_delta_serio *priv = serio->port_data; 106 107 /* disable keyboard */ 108 regulator_disable(priv->vcc); 109 } 110 111 static int ams_delta_serio_init(struct platform_device *pdev) 112 { 113 struct ams_delta_serio *priv; 114 struct serio *serio; 115 int irq, err; 116 117 priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); 118 if (!priv) 119 return -ENOMEM; 120 121 priv->fiq_buffer = pdev->dev.platform_data; 122 if (!priv->fiq_buffer) 123 return -EINVAL; 124 125 priv->vcc = devm_regulator_get(&pdev->dev, "vcc"); 126 if (IS_ERR(priv->vcc)) { 127 err = PTR_ERR(priv->vcc); 128 dev_err(&pdev->dev, "regulator request failed (%d)\n", err); 129 /* 130 * When running on a non-dt platform and requested regulator 131 * is not available, devm_regulator_get() never returns 132 * -EPROBE_DEFER as it is not able to justify if the regulator 133 * may still appear later. On the other hand, the board can 134 * still set full constriants flag at late_initcall in order 135 * to instruct devm_regulator_get() to returnn a dummy one 136 * if sufficient. Hence, if we get -ENODEV here, let's convert 137 * it to -EPROBE_DEFER and wait for the board to decide or 138 * let Deferred Probe infrastructure handle this error. 139 */ 140 if (err == -ENODEV) 141 err = -EPROBE_DEFER; 142 return err; 143 } 144 145 irq = platform_get_irq(pdev, 0); 146 if (irq < 0) 147 return -ENXIO; 148 149 err = devm_request_irq(&pdev->dev, irq, ams_delta_serio_interrupt, 150 IRQ_TYPE_EDGE_RISING, DRIVER_NAME, priv); 151 if (err < 0) { 152 dev_err(&pdev->dev, "IRQ request failed (%d)\n", err); 153 return err; 154 } 155 156 serio = kzalloc(sizeof(*serio), GFP_KERNEL); 157 if (!serio) 158 return -ENOMEM; 159 160 priv->serio = serio; 161 162 serio->id.type = SERIO_8042; 163 serio->open = ams_delta_serio_open; 164 serio->close = ams_delta_serio_close; 165 strlcpy(serio->name, "AMS DELTA keyboard adapter", sizeof(serio->name)); 166 strlcpy(serio->phys, dev_name(&pdev->dev), sizeof(serio->phys)); 167 serio->dev.parent = &pdev->dev; 168 serio->port_data = priv; 169 170 serio_register_port(serio); 171 172 platform_set_drvdata(pdev, priv); 173 174 dev_info(&serio->dev, "%s\n", serio->name); 175 176 return 0; 177 } 178 179 static int ams_delta_serio_exit(struct platform_device *pdev) 180 { 181 struct ams_delta_serio *priv = platform_get_drvdata(pdev); 182 183 serio_unregister_port(priv->serio); 184 185 return 0; 186 } 187 188 static struct platform_driver ams_delta_serio_driver = { 189 .probe = ams_delta_serio_init, 190 .remove = ams_delta_serio_exit, 191 .driver = { 192 .name = DRIVER_NAME 193 }, 194 }; 195 module_platform_driver(ams_delta_serio_driver); 196