162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */ 262306a36Sopenharmony_ci#ifndef _I8042_SPARCIO_H 362306a36Sopenharmony_ci#define _I8042_SPARCIO_H 462306a36Sopenharmony_ci 562306a36Sopenharmony_ci#include <linux/of.h> 662306a36Sopenharmony_ci#include <linux/of_platform.h> 762306a36Sopenharmony_ci#include <linux/platform_device.h> 862306a36Sopenharmony_ci#include <linux/types.h> 962306a36Sopenharmony_ci 1062306a36Sopenharmony_ci#include <asm/io.h> 1162306a36Sopenharmony_ci#include <asm/oplib.h> 1262306a36Sopenharmony_ci#include <asm/prom.h> 1362306a36Sopenharmony_ci 1462306a36Sopenharmony_cistatic int i8042_kbd_irq = -1; 1562306a36Sopenharmony_cistatic int i8042_aux_irq = -1; 1662306a36Sopenharmony_ci#define I8042_KBD_IRQ i8042_kbd_irq 1762306a36Sopenharmony_ci#define I8042_AUX_IRQ i8042_aux_irq 1862306a36Sopenharmony_ci 1962306a36Sopenharmony_ci#define I8042_KBD_PHYS_DESC "sparcps2/serio0" 2062306a36Sopenharmony_ci#define I8042_AUX_PHYS_DESC "sparcps2/serio1" 2162306a36Sopenharmony_ci#define I8042_MUX_PHYS_DESC "sparcps2/serio%d" 2262306a36Sopenharmony_ci 2362306a36Sopenharmony_cistatic void __iomem *kbd_iobase; 2462306a36Sopenharmony_ci 2562306a36Sopenharmony_ci#define I8042_COMMAND_REG (kbd_iobase + 0x64UL) 2662306a36Sopenharmony_ci#define I8042_DATA_REG (kbd_iobase + 0x60UL) 2762306a36Sopenharmony_ci 2862306a36Sopenharmony_cistatic inline int i8042_read_data(void) 2962306a36Sopenharmony_ci{ 3062306a36Sopenharmony_ci return readb(kbd_iobase + 0x60UL); 3162306a36Sopenharmony_ci} 3262306a36Sopenharmony_ci 3362306a36Sopenharmony_cistatic inline int i8042_read_status(void) 3462306a36Sopenharmony_ci{ 3562306a36Sopenharmony_ci return readb(kbd_iobase + 0x64UL); 3662306a36Sopenharmony_ci} 3762306a36Sopenharmony_ci 3862306a36Sopenharmony_cistatic inline void i8042_write_data(int val) 3962306a36Sopenharmony_ci{ 4062306a36Sopenharmony_ci writeb(val, kbd_iobase + 0x60UL); 4162306a36Sopenharmony_ci} 4262306a36Sopenharmony_ci 4362306a36Sopenharmony_cistatic inline void i8042_write_command(int val) 4462306a36Sopenharmony_ci{ 4562306a36Sopenharmony_ci writeb(val, kbd_iobase + 0x64UL); 4662306a36Sopenharmony_ci} 4762306a36Sopenharmony_ci 4862306a36Sopenharmony_ci#ifdef CONFIG_PCI 4962306a36Sopenharmony_ci 5062306a36Sopenharmony_cistatic struct resource *kbd_res; 5162306a36Sopenharmony_ci 5262306a36Sopenharmony_ci#define OBP_PS2KBD_NAME1 "kb_ps2" 5362306a36Sopenharmony_ci#define OBP_PS2KBD_NAME2 "keyboard" 5462306a36Sopenharmony_ci#define OBP_PS2MS_NAME1 "kdmouse" 5562306a36Sopenharmony_ci#define OBP_PS2MS_NAME2 "mouse" 5662306a36Sopenharmony_ci 5762306a36Sopenharmony_cistatic int sparc_i8042_probe(struct platform_device *op) 5862306a36Sopenharmony_ci{ 5962306a36Sopenharmony_ci struct device_node *dp; 6062306a36Sopenharmony_ci 6162306a36Sopenharmony_ci for_each_child_of_node(op->dev.of_node, dp) { 6262306a36Sopenharmony_ci if (of_node_name_eq(dp, OBP_PS2KBD_NAME1) || 6362306a36Sopenharmony_ci of_node_name_eq(dp, OBP_PS2KBD_NAME2)) { 6462306a36Sopenharmony_ci struct platform_device *kbd = of_find_device_by_node(dp); 6562306a36Sopenharmony_ci unsigned int irq = kbd->archdata.irqs[0]; 6662306a36Sopenharmony_ci if (irq == 0xffffffff) 6762306a36Sopenharmony_ci irq = op->archdata.irqs[0]; 6862306a36Sopenharmony_ci i8042_kbd_irq = irq; 6962306a36Sopenharmony_ci kbd_iobase = of_ioremap(&kbd->resource[0], 7062306a36Sopenharmony_ci 0, 8, "kbd"); 7162306a36Sopenharmony_ci kbd_res = &kbd->resource[0]; 7262306a36Sopenharmony_ci } else if (of_node_name_eq(dp, OBP_PS2MS_NAME1) || 7362306a36Sopenharmony_ci of_node_name_eq(dp, OBP_PS2MS_NAME2)) { 7462306a36Sopenharmony_ci struct platform_device *ms = of_find_device_by_node(dp); 7562306a36Sopenharmony_ci unsigned int irq = ms->archdata.irqs[0]; 7662306a36Sopenharmony_ci if (irq == 0xffffffff) 7762306a36Sopenharmony_ci irq = op->archdata.irqs[0]; 7862306a36Sopenharmony_ci i8042_aux_irq = irq; 7962306a36Sopenharmony_ci } 8062306a36Sopenharmony_ci } 8162306a36Sopenharmony_ci 8262306a36Sopenharmony_ci return 0; 8362306a36Sopenharmony_ci} 8462306a36Sopenharmony_ci 8562306a36Sopenharmony_cistatic int sparc_i8042_remove(struct platform_device *op) 8662306a36Sopenharmony_ci{ 8762306a36Sopenharmony_ci of_iounmap(kbd_res, kbd_iobase, 8); 8862306a36Sopenharmony_ci 8962306a36Sopenharmony_ci return 0; 9062306a36Sopenharmony_ci} 9162306a36Sopenharmony_ci 9262306a36Sopenharmony_cistatic const struct of_device_id sparc_i8042_match[] = { 9362306a36Sopenharmony_ci { 9462306a36Sopenharmony_ci .name = "8042", 9562306a36Sopenharmony_ci }, 9662306a36Sopenharmony_ci {}, 9762306a36Sopenharmony_ci}; 9862306a36Sopenharmony_ciMODULE_DEVICE_TABLE(of, sparc_i8042_match); 9962306a36Sopenharmony_ci 10062306a36Sopenharmony_cistatic struct platform_driver sparc_i8042_driver = { 10162306a36Sopenharmony_ci .driver = { 10262306a36Sopenharmony_ci .name = "i8042", 10362306a36Sopenharmony_ci .of_match_table = sparc_i8042_match, 10462306a36Sopenharmony_ci }, 10562306a36Sopenharmony_ci .probe = sparc_i8042_probe, 10662306a36Sopenharmony_ci .remove = sparc_i8042_remove, 10762306a36Sopenharmony_ci}; 10862306a36Sopenharmony_ci 10962306a36Sopenharmony_cistatic bool i8042_is_mr_coffee(void) 11062306a36Sopenharmony_ci{ 11162306a36Sopenharmony_ci struct device_node *root; 11262306a36Sopenharmony_ci const char *name; 11362306a36Sopenharmony_ci bool is_mr_coffee; 11462306a36Sopenharmony_ci 11562306a36Sopenharmony_ci root = of_find_node_by_path("/"); 11662306a36Sopenharmony_ci 11762306a36Sopenharmony_ci name = of_get_property(root, "name", NULL); 11862306a36Sopenharmony_ci is_mr_coffee = name && !strcmp(name, "SUNW,JavaStation-1"); 11962306a36Sopenharmony_ci 12062306a36Sopenharmony_ci of_node_put(root); 12162306a36Sopenharmony_ci 12262306a36Sopenharmony_ci return is_mr_coffee; 12362306a36Sopenharmony_ci} 12462306a36Sopenharmony_ci 12562306a36Sopenharmony_cistatic int __init i8042_platform_init(void) 12662306a36Sopenharmony_ci{ 12762306a36Sopenharmony_ci if (i8042_is_mr_coffee()) { 12862306a36Sopenharmony_ci /* Hardcoded values for MrCoffee. */ 12962306a36Sopenharmony_ci i8042_kbd_irq = i8042_aux_irq = 13 | 0x20; 13062306a36Sopenharmony_ci kbd_iobase = ioremap(0x71300060, 8); 13162306a36Sopenharmony_ci if (!kbd_iobase) 13262306a36Sopenharmony_ci return -ENODEV; 13362306a36Sopenharmony_ci } else { 13462306a36Sopenharmony_ci int err = platform_driver_register(&sparc_i8042_driver); 13562306a36Sopenharmony_ci if (err) 13662306a36Sopenharmony_ci return err; 13762306a36Sopenharmony_ci 13862306a36Sopenharmony_ci if (i8042_kbd_irq == -1 || 13962306a36Sopenharmony_ci i8042_aux_irq == -1) { 14062306a36Sopenharmony_ci if (kbd_iobase) { 14162306a36Sopenharmony_ci of_iounmap(kbd_res, kbd_iobase, 8); 14262306a36Sopenharmony_ci kbd_iobase = (void __iomem *) NULL; 14362306a36Sopenharmony_ci } 14462306a36Sopenharmony_ci return -ENODEV; 14562306a36Sopenharmony_ci } 14662306a36Sopenharmony_ci } 14762306a36Sopenharmony_ci 14862306a36Sopenharmony_ci i8042_reset = I8042_RESET_ALWAYS; 14962306a36Sopenharmony_ci 15062306a36Sopenharmony_ci return 0; 15162306a36Sopenharmony_ci} 15262306a36Sopenharmony_ci 15362306a36Sopenharmony_cistatic inline void i8042_platform_exit(void) 15462306a36Sopenharmony_ci{ 15562306a36Sopenharmony_ci if (!i8042_is_mr_coffee()) 15662306a36Sopenharmony_ci platform_driver_unregister(&sparc_i8042_driver); 15762306a36Sopenharmony_ci} 15862306a36Sopenharmony_ci 15962306a36Sopenharmony_ci#else /* !CONFIG_PCI */ 16062306a36Sopenharmony_cistatic int __init i8042_platform_init(void) 16162306a36Sopenharmony_ci{ 16262306a36Sopenharmony_ci return -ENODEV; 16362306a36Sopenharmony_ci} 16462306a36Sopenharmony_ci 16562306a36Sopenharmony_cistatic inline void i8042_platform_exit(void) 16662306a36Sopenharmony_ci{ 16762306a36Sopenharmony_ci} 16862306a36Sopenharmony_ci#endif /* !CONFIG_PCI */ 16962306a36Sopenharmony_ci 17062306a36Sopenharmony_ci#endif /* _I8042_SPARCIO_H */ 171