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/gpio.h> 24 #include <linux/irq.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 #include <mach/board-ams-delta.h> 32 33 #include <mach/ams-delta-fiq.h> 34 35 #define DRIVER_NAME "ams-delta-serio" 36 37 MODULE_AUTHOR("Matt Callow"); 38 MODULE_DESCRIPTION("AMS Delta (E3) keyboard port driver"); 39 MODULE_LICENSE("GPL"); 40 41 struct ams_delta_serio { 42 struct serio *serio; 43 struct regulator *vcc; 44 }; 45 46 static int check_data(struct serio *serio, int data) 47 { 48 int i, parity = 0; 49 50 /* check valid stop bit */ 51 if (!(data & 0x400)) { 52 dev_warn(&serio->dev, "invalid stop bit, data=0x%X\n", data); 53 return SERIO_FRAME; 54 } 55 /* calculate the parity */ 56 for (i = 1; i < 10; i++) { 57 if (data & (1 << i)) 58 parity++; 59 } 60 /* it should be odd */ 61 if (!(parity & 0x01)) { 62 dev_warn(&serio->dev, 63 "parity check failed, data=0x%X parity=0x%X\n", data, 64 parity); 65 return SERIO_PARITY; 66 } 67 return 0; 68 } 69 70 static irqreturn_t ams_delta_serio_interrupt(int irq, void *dev_id) 71 { 72 struct ams_delta_serio *priv = dev_id; 73 int *circ_buff = &fiq_buffer[FIQ_CIRC_BUFF]; 74 int data, dfl; 75 u8 scancode; 76 77 fiq_buffer[FIQ_IRQ_PEND] = 0; 78 79 /* 80 * Read data from the circular buffer, check it 81 * and then pass it on the serio 82 */ 83 while (fiq_buffer[FIQ_KEYS_CNT] > 0) { 84 85 data = circ_buff[fiq_buffer[FIQ_HEAD_OFFSET]++]; 86 fiq_buffer[FIQ_KEYS_CNT]--; 87 if (fiq_buffer[FIQ_HEAD_OFFSET] == fiq_buffer[FIQ_BUF_LEN]) 88 fiq_buffer[FIQ_HEAD_OFFSET] = 0; 89 90 dfl = check_data(priv->serio, data); 91 scancode = (u8) (data >> 1) & 0xFF; 92 serio_interrupt(priv->serio, scancode, dfl); 93 } 94 return IRQ_HANDLED; 95 } 96 97 static int ams_delta_serio_open(struct serio *serio) 98 { 99 struct ams_delta_serio *priv = serio->port_data; 100 101 /* enable keyboard */ 102 return regulator_enable(priv->vcc); 103 } 104 105 static void ams_delta_serio_close(struct serio *serio) 106 { 107 struct ams_delta_serio *priv = serio->port_data; 108 109 /* disable keyboard */ 110 regulator_disable(priv->vcc); 111 } 112 113 static const struct gpio ams_delta_gpios[] __initconst_or_module = { 114 { 115 .gpio = AMS_DELTA_GPIO_PIN_KEYBRD_DATA, 116 .flags = GPIOF_DIR_IN, 117 .label = "serio-data", 118 }, 119 { 120 .gpio = AMS_DELTA_GPIO_PIN_KEYBRD_CLK, 121 .flags = GPIOF_DIR_IN, 122 .label = "serio-clock", 123 }, 124 { 125 .gpio = AMS_DELTA_GPIO_PIN_KEYBRD_DATAOUT, 126 .flags = GPIOF_OUT_INIT_LOW, 127 .label = "serio-dataout", 128 }, 129 }; 130 131 static int ams_delta_serio_init(struct platform_device *pdev) 132 { 133 struct ams_delta_serio *priv; 134 struct serio *serio; 135 int err; 136 137 priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); 138 if (!priv) 139 return -ENOMEM; 140 141 err = gpio_request_array(ams_delta_gpios, 142 ARRAY_SIZE(ams_delta_gpios)); 143 if (err) { 144 dev_err(&pdev->dev, "Couldn't request gpio pins\n"); 145 goto serio; 146 } 147 148 priv->vcc = devm_regulator_get(&pdev->dev, "vcc"); 149 if (IS_ERR(priv->vcc)) { 150 err = PTR_ERR(priv->vcc); 151 dev_err(&pdev->dev, "regulator request failed (%d)\n", err); 152 /* 153 * When running on a non-dt platform and requested regulator 154 * is not available, devm_regulator_get() never returns 155 * -EPROBE_DEFER as it is not able to justify if the regulator 156 * may still appear later. On the other hand, the board can 157 * still set full constriants flag at late_initcall in order 158 * to instruct devm_regulator_get() to returnn a dummy one 159 * if sufficient. Hence, if we get -ENODEV here, let's convert 160 * it to -EPROBE_DEFER and wait for the board to decide or 161 * let Deferred Probe infrastructure handle this error. 162 */ 163 if (err == -ENODEV) 164 err = -EPROBE_DEFER; 165 goto gpio; 166 } 167 168 err = request_irq(gpio_to_irq(AMS_DELTA_GPIO_PIN_KEYBRD_CLK), 169 ams_delta_serio_interrupt, IRQ_TYPE_EDGE_RISING, 170 DRIVER_NAME, priv); 171 if (err < 0) { 172 dev_err(&pdev->dev, "IRQ request failed (%d)\n", err); 173 goto gpio; 174 } 175 /* 176 * Since GPIO register handling for keyboard clock pin is performed 177 * at FIQ level, switch back from edge to simple interrupt handler 178 * to avoid bad interaction. 179 */ 180 irq_set_handler(gpio_to_irq(AMS_DELTA_GPIO_PIN_KEYBRD_CLK), 181 handle_simple_irq); 182 183 serio = kzalloc(sizeof(*serio), GFP_KERNEL); 184 if (!serio) { 185 err = -ENOMEM; 186 goto irq; 187 } 188 189 priv->serio = serio; 190 191 serio->id.type = SERIO_8042; 192 serio->open = ams_delta_serio_open; 193 serio->close = ams_delta_serio_close; 194 strlcpy(serio->name, "AMS DELTA keyboard adapter", sizeof(serio->name)); 195 strlcpy(serio->phys, dev_name(&pdev->dev), sizeof(serio->phys)); 196 serio->dev.parent = &pdev->dev; 197 serio->port_data = priv; 198 199 serio_register_port(serio); 200 201 platform_set_drvdata(pdev, priv); 202 203 dev_info(&serio->dev, "%s\n", serio->name); 204 205 return 0; 206 207 irq: 208 free_irq(gpio_to_irq(AMS_DELTA_GPIO_PIN_KEYBRD_CLK), priv); 209 gpio: 210 gpio_free_array(ams_delta_gpios, 211 ARRAY_SIZE(ams_delta_gpios)); 212 serio: 213 return err; 214 } 215 216 static int ams_delta_serio_exit(struct platform_device *pdev) 217 { 218 struct ams_delta_serio *priv = platform_get_drvdata(pdev); 219 220 serio_unregister_port(priv->serio); 221 free_irq(gpio_to_irq(AMS_DELTA_GPIO_PIN_KEYBRD_CLK), 0); 222 gpio_free_array(ams_delta_gpios, 223 ARRAY_SIZE(ams_delta_gpios)); 224 225 return 0; 226 } 227 228 static struct platform_driver ams_delta_serio_driver = { 229 .probe = ams_delta_serio_init, 230 .remove = ams_delta_serio_exit, 231 .driver = { 232 .name = DRIVER_NAME 233 }, 234 }; 235 module_platform_driver(ams_delta_serio_driver); 236