0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #include <linux/module.h>
0012 #include <linux/input.h>
0013 #include <linux/serio.h>
0014 #include <linux/interrupt.h>
0015 #include <linux/platform_device.h>
0016 #include <linux/io.h>
0017 #include <linux/slab.h>
0018 #include <linux/of.h>
0019
0020 #define DRV_NAME "altera_ps2"
0021
0022 struct ps2if {
0023 struct serio *io;
0024 void __iomem *base;
0025 };
0026
0027
0028
0029
0030
0031 static irqreturn_t altera_ps2_rxint(int irq, void *dev_id)
0032 {
0033 struct ps2if *ps2if = dev_id;
0034 unsigned int status;
0035 irqreturn_t handled = IRQ_NONE;
0036
0037 while ((status = readl(ps2if->base)) & 0xffff0000) {
0038 serio_interrupt(ps2if->io, status & 0xff, 0);
0039 handled = IRQ_HANDLED;
0040 }
0041
0042 return handled;
0043 }
0044
0045
0046
0047
0048 static int altera_ps2_write(struct serio *io, unsigned char val)
0049 {
0050 struct ps2if *ps2if = io->port_data;
0051
0052 writel(val, ps2if->base);
0053 return 0;
0054 }
0055
0056 static int altera_ps2_open(struct serio *io)
0057 {
0058 struct ps2if *ps2if = io->port_data;
0059
0060
0061 while (readl(ps2if->base) & 0xffff0000)
0062 ;
0063
0064 writel(1, ps2if->base + 4);
0065 return 0;
0066 }
0067
0068 static void altera_ps2_close(struct serio *io)
0069 {
0070 struct ps2if *ps2if = io->port_data;
0071
0072 writel(0, ps2if->base + 4);
0073 }
0074
0075
0076
0077
0078 static int altera_ps2_probe(struct platform_device *pdev)
0079 {
0080 struct ps2if *ps2if;
0081 struct resource *res;
0082 struct serio *serio;
0083 int error, irq;
0084
0085 ps2if = devm_kzalloc(&pdev->dev, sizeof(struct ps2if), GFP_KERNEL);
0086 if (!ps2if)
0087 return -ENOMEM;
0088
0089 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
0090 ps2if->base = devm_ioremap_resource(&pdev->dev, res);
0091 if (IS_ERR(ps2if->base))
0092 return PTR_ERR(ps2if->base);
0093
0094 irq = platform_get_irq(pdev, 0);
0095 if (irq < 0)
0096 return -ENXIO;
0097
0098 error = devm_request_irq(&pdev->dev, irq, altera_ps2_rxint, 0,
0099 pdev->name, ps2if);
0100 if (error) {
0101 dev_err(&pdev->dev, "could not request IRQ %d\n", irq);
0102 return error;
0103 }
0104
0105 serio = kzalloc(sizeof(struct serio), GFP_KERNEL);
0106 if (!serio)
0107 return -ENOMEM;
0108
0109 serio->id.type = SERIO_8042;
0110 serio->write = altera_ps2_write;
0111 serio->open = altera_ps2_open;
0112 serio->close = altera_ps2_close;
0113 strlcpy(serio->name, dev_name(&pdev->dev), sizeof(serio->name));
0114 strlcpy(serio->phys, dev_name(&pdev->dev), sizeof(serio->phys));
0115 serio->port_data = ps2if;
0116 serio->dev.parent = &pdev->dev;
0117 ps2if->io = serio;
0118
0119 dev_info(&pdev->dev, "base %p, irq %d\n", ps2if->base, irq);
0120
0121 serio_register_port(ps2if->io);
0122 platform_set_drvdata(pdev, ps2if);
0123
0124 return 0;
0125 }
0126
0127
0128
0129
0130 static int altera_ps2_remove(struct platform_device *pdev)
0131 {
0132 struct ps2if *ps2if = platform_get_drvdata(pdev);
0133
0134 serio_unregister_port(ps2if->io);
0135
0136 return 0;
0137 }
0138
0139 #ifdef CONFIG_OF
0140 static const struct of_device_id altera_ps2_match[] = {
0141 { .compatible = "ALTR,ps2-1.0", },
0142 { .compatible = "altr,ps2-1.0", },
0143 {},
0144 };
0145 MODULE_DEVICE_TABLE(of, altera_ps2_match);
0146 #endif
0147
0148
0149
0150
0151 static struct platform_driver altera_ps2_driver = {
0152 .probe = altera_ps2_probe,
0153 .remove = altera_ps2_remove,
0154 .driver = {
0155 .name = DRV_NAME,
0156 .of_match_table = of_match_ptr(altera_ps2_match),
0157 },
0158 };
0159 module_platform_driver(altera_ps2_driver);
0160
0161 MODULE_DESCRIPTION("Altera University Program PS2 controller driver");
0162 MODULE_AUTHOR("Thomas Chou <thomas@wytron.com.tw>");
0163 MODULE_LICENSE("GPL");
0164 MODULE_ALIAS("platform:" DRV_NAME);