^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) /* SPDX-License-Identifier: GPL-2.0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) #ifndef _I8042_SPARCIO_H
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) #define _I8042_SPARCIO_H
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) #include <linux/of_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) #include <asm/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <asm/oplib.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <asm/prom.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) static int i8042_kbd_irq = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) static int i8042_aux_irq = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #define I8042_KBD_IRQ i8042_kbd_irq
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #define I8042_AUX_IRQ i8042_aux_irq
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #define I8042_KBD_PHYS_DESC "sparcps2/serio0"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #define I8042_AUX_PHYS_DESC "sparcps2/serio1"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #define I8042_MUX_PHYS_DESC "sparcps2/serio%d"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) static void __iomem *kbd_iobase;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #define I8042_COMMAND_REG (kbd_iobase + 0x64UL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #define I8042_DATA_REG (kbd_iobase + 0x60UL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) static inline int i8042_read_data(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) return readb(kbd_iobase + 0x60UL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) static inline int i8042_read_status(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) return readb(kbd_iobase + 0x64UL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) static inline void i8042_write_data(int val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) writeb(val, kbd_iobase + 0x60UL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) static inline void i8042_write_command(int val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) writeb(val, kbd_iobase + 0x64UL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) #ifdef CONFIG_PCI
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) static struct resource *kbd_res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) #define OBP_PS2KBD_NAME1 "kb_ps2"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) #define OBP_PS2KBD_NAME2 "keyboard"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) #define OBP_PS2MS_NAME1 "kdmouse"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) #define OBP_PS2MS_NAME2 "mouse"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) static int sparc_i8042_probe(struct platform_device *op)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) struct device_node *dp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) for_each_child_of_node(op->dev.of_node, dp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) if (of_node_name_eq(dp, OBP_PS2KBD_NAME1) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) of_node_name_eq(dp, OBP_PS2KBD_NAME2)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) struct platform_device *kbd = of_find_device_by_node(dp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) unsigned int irq = kbd->archdata.irqs[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) if (irq == 0xffffffff)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) irq = op->archdata.irqs[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) i8042_kbd_irq = irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) kbd_iobase = of_ioremap(&kbd->resource[0],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) 0, 8, "kbd");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) kbd_res = &kbd->resource[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) } else if (of_node_name_eq(dp, OBP_PS2MS_NAME1) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) of_node_name_eq(dp, OBP_PS2MS_NAME2)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) struct platform_device *ms = of_find_device_by_node(dp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) unsigned int irq = ms->archdata.irqs[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) if (irq == 0xffffffff)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) irq = op->archdata.irqs[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) i8042_aux_irq = irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) static int sparc_i8042_remove(struct platform_device *op)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) of_iounmap(kbd_res, kbd_iobase, 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) static const struct of_device_id sparc_i8042_match[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) .name = "8042",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) {},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) MODULE_DEVICE_TABLE(of, sparc_i8042_match);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) static struct platform_driver sparc_i8042_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) .name = "i8042",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) .of_match_table = sparc_i8042_match,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) .probe = sparc_i8042_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) .remove = sparc_i8042_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) static int __init i8042_platform_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) struct device_node *root = of_find_node_by_path("/");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) const char *name = of_get_property(root, "name", NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) if (name && !strcmp(name, "SUNW,JavaStation-1")) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) /* Hardcoded values for MrCoffee. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) i8042_kbd_irq = i8042_aux_irq = 13 | 0x20;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) kbd_iobase = ioremap(0x71300060, 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) if (!kbd_iobase)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) int err = platform_driver_register(&sparc_i8042_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) if (i8042_kbd_irq == -1 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) i8042_aux_irq == -1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) if (kbd_iobase) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) of_iounmap(kbd_res, kbd_iobase, 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) kbd_iobase = (void __iomem *) NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) i8042_reset = I8042_RESET_ALWAYS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) static inline void i8042_platform_exit(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) struct device_node *root = of_find_node_by_path("/");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) const char *name = of_get_property(root, "name", NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) if (!name || strcmp(name, "SUNW,JavaStation-1"))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) platform_driver_unregister(&sparc_i8042_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) #else /* !CONFIG_PCI */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) static int __init i8042_platform_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) static inline void i8042_platform_exit(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) #endif /* !CONFIG_PCI */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) #endif /* _I8042_SPARCIO_H */