0001
0002
0003
0004
0005
0006
0007
0008 #include <linux/module.h>
0009 #include <linux/interrupt.h>
0010 #include <linux/serio.h>
0011 #include <linux/err.h>
0012 #include <linux/platform_device.h>
0013 #include <linux/io.h>
0014 #include <linux/of.h>
0015 #include <linux/slab.h>
0016 #include <linux/delay.h>
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033 #define SECURE_PROCESSOR_COMMAND 0x40
0034 #define COMMAND_RETURN_STATUS 0x80
0035 #define COMMAND_FIFO_STATUS 0xc4
0036 #define PJ_RST_INTERRUPT 0xc8
0037 #define PJ_INTERRUPT_MASK 0xcc
0038
0039
0040
0041
0042
0043
0044 #define PORT_MASK 0xff00
0045 #define DATA_MASK 0x00ff
0046 #define PORT_SHIFT 8
0047 #define KEYBOARD_PORT 0
0048 #define TOUCHPAD_PORT 1
0049
0050
0051 #define CMD_CNTR_MASK 0x7
0052 #define MAX_PENDING_CMDS 4
0053
0054
0055 #define SP_COMMAND_COMPLETE_RESET 0x1
0056
0057
0058 #define INT_0 (1 << 0)
0059
0060
0061 #define CMD_STS_MASK 0x100
0062
0063 struct olpc_apsp {
0064 struct device *dev;
0065 struct serio *kbio;
0066 struct serio *padio;
0067 void __iomem *base;
0068 int open_count;
0069 int irq;
0070 };
0071
0072 static int olpc_apsp_write(struct serio *port, unsigned char val)
0073 {
0074 struct olpc_apsp *priv = port->port_data;
0075 unsigned int i;
0076 u32 which = 0;
0077
0078 if (port == priv->padio)
0079 which = TOUCHPAD_PORT << PORT_SHIFT;
0080 else
0081 which = KEYBOARD_PORT << PORT_SHIFT;
0082
0083 dev_dbg(priv->dev, "olpc_apsp_write which=%x val=%x\n", which, val);
0084 for (i = 0; i < 50; i++) {
0085 u32 sts = readl(priv->base + COMMAND_FIFO_STATUS);
0086 if ((sts & CMD_CNTR_MASK) < MAX_PENDING_CMDS) {
0087 writel(which | val,
0088 priv->base + SECURE_PROCESSOR_COMMAND);
0089 return 0;
0090 }
0091
0092 mdelay(1);
0093 }
0094
0095 dev_dbg(priv->dev, "olpc_apsp_write timeout, status=%x\n",
0096 readl(priv->base + COMMAND_FIFO_STATUS));
0097
0098 return -ETIMEDOUT;
0099 }
0100
0101 static irqreturn_t olpc_apsp_rx(int irq, void *dev_id)
0102 {
0103 struct olpc_apsp *priv = dev_id;
0104 unsigned int w, tmp;
0105 struct serio *serio;
0106
0107
0108
0109
0110
0111 tmp = readl(priv->base + PJ_RST_INTERRUPT);
0112 if (!(tmp & SP_COMMAND_COMPLETE_RESET)) {
0113 dev_warn(priv->dev, "spurious interrupt?\n");
0114 return IRQ_NONE;
0115 }
0116
0117 w = readl(priv->base + COMMAND_RETURN_STATUS);
0118 dev_dbg(priv->dev, "olpc_apsp_rx %x\n", w);
0119
0120 if (w >> PORT_SHIFT == KEYBOARD_PORT)
0121 serio = priv->kbio;
0122 else
0123 serio = priv->padio;
0124
0125 serio_interrupt(serio, w & DATA_MASK, 0);
0126
0127
0128 writel(tmp | SP_COMMAND_COMPLETE_RESET, priv->base + PJ_RST_INTERRUPT);
0129 writel(PORT_MASK, priv->base + SECURE_PROCESSOR_COMMAND);
0130
0131 pm_wakeup_event(priv->dev, 1000);
0132 return IRQ_HANDLED;
0133 }
0134
0135 static int olpc_apsp_open(struct serio *port)
0136 {
0137 struct olpc_apsp *priv = port->port_data;
0138 unsigned int tmp;
0139 unsigned long l;
0140
0141 if (priv->open_count++ == 0) {
0142 l = readl(priv->base + COMMAND_FIFO_STATUS);
0143 if (!(l & CMD_STS_MASK)) {
0144 dev_err(priv->dev, "SP cannot accept commands.\n");
0145 return -EIO;
0146 }
0147
0148
0149 tmp = readl(priv->base + PJ_INTERRUPT_MASK);
0150 writel(tmp & ~INT_0, priv->base + PJ_INTERRUPT_MASK);
0151 }
0152
0153 return 0;
0154 }
0155
0156 static void olpc_apsp_close(struct serio *port)
0157 {
0158 struct olpc_apsp *priv = port->port_data;
0159 unsigned int tmp;
0160
0161 if (--priv->open_count == 0) {
0162
0163 tmp = readl(priv->base + PJ_INTERRUPT_MASK);
0164 writel(tmp | INT_0, priv->base + PJ_INTERRUPT_MASK);
0165 }
0166 }
0167
0168 static int olpc_apsp_probe(struct platform_device *pdev)
0169 {
0170 struct serio *kb_serio, *pad_serio;
0171 struct olpc_apsp *priv;
0172 struct resource *res;
0173 int error;
0174
0175 priv = devm_kzalloc(&pdev->dev, sizeof(struct olpc_apsp), GFP_KERNEL);
0176 if (!priv)
0177 return -ENOMEM;
0178
0179 priv->dev = &pdev->dev;
0180
0181 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
0182 priv->base = devm_ioremap_resource(&pdev->dev, res);
0183 if (IS_ERR(priv->base)) {
0184 dev_err(&pdev->dev, "Failed to map WTM registers\n");
0185 return PTR_ERR(priv->base);
0186 }
0187
0188 priv->irq = platform_get_irq(pdev, 0);
0189 if (priv->irq < 0)
0190 return priv->irq;
0191
0192
0193 kb_serio = kzalloc(sizeof(struct serio), GFP_KERNEL);
0194 if (!kb_serio)
0195 return -ENOMEM;
0196 kb_serio->id.type = SERIO_8042_XL;
0197 kb_serio->write = olpc_apsp_write;
0198 kb_serio->open = olpc_apsp_open;
0199 kb_serio->close = olpc_apsp_close;
0200 kb_serio->port_data = priv;
0201 kb_serio->dev.parent = &pdev->dev;
0202 strlcpy(kb_serio->name, "sp keyboard", sizeof(kb_serio->name));
0203 strlcpy(kb_serio->phys, "sp/serio0", sizeof(kb_serio->phys));
0204 priv->kbio = kb_serio;
0205 serio_register_port(kb_serio);
0206
0207
0208 pad_serio = kzalloc(sizeof(struct serio), GFP_KERNEL);
0209 if (!pad_serio) {
0210 error = -ENOMEM;
0211 goto err_pad;
0212 }
0213 pad_serio->id.type = SERIO_8042;
0214 pad_serio->write = olpc_apsp_write;
0215 pad_serio->open = olpc_apsp_open;
0216 pad_serio->close = olpc_apsp_close;
0217 pad_serio->port_data = priv;
0218 pad_serio->dev.parent = &pdev->dev;
0219 strlcpy(pad_serio->name, "sp touchpad", sizeof(pad_serio->name));
0220 strlcpy(pad_serio->phys, "sp/serio1", sizeof(pad_serio->phys));
0221 priv->padio = pad_serio;
0222 serio_register_port(pad_serio);
0223
0224 error = request_irq(priv->irq, olpc_apsp_rx, 0, "olpc-apsp", priv);
0225 if (error) {
0226 dev_err(&pdev->dev, "Failed to request IRQ\n");
0227 goto err_irq;
0228 }
0229
0230 device_init_wakeup(priv->dev, 1);
0231 platform_set_drvdata(pdev, priv);
0232
0233 dev_dbg(&pdev->dev, "probed successfully.\n");
0234 return 0;
0235
0236 err_irq:
0237 serio_unregister_port(pad_serio);
0238 err_pad:
0239 serio_unregister_port(kb_serio);
0240 return error;
0241 }
0242
0243 static int olpc_apsp_remove(struct platform_device *pdev)
0244 {
0245 struct olpc_apsp *priv = platform_get_drvdata(pdev);
0246
0247 free_irq(priv->irq, priv);
0248
0249 serio_unregister_port(priv->kbio);
0250 serio_unregister_port(priv->padio);
0251
0252 return 0;
0253 }
0254
0255 static const struct of_device_id olpc_apsp_dt_ids[] = {
0256 { .compatible = "olpc,ap-sp", },
0257 {}
0258 };
0259 MODULE_DEVICE_TABLE(of, olpc_apsp_dt_ids);
0260
0261 static struct platform_driver olpc_apsp_driver = {
0262 .probe = olpc_apsp_probe,
0263 .remove = olpc_apsp_remove,
0264 .driver = {
0265 .name = "olpc-apsp",
0266 .of_match_table = olpc_apsp_dt_ids,
0267 },
0268 };
0269
0270 MODULE_DESCRIPTION("OLPC AP-SP serio driver");
0271 MODULE_LICENSE("GPL");
0272 module_platform_driver(olpc_apsp_driver);