summaryrefslogtreecommitdiffstats
path: root/drivers/input/serio/i8042-sparcio.h
blob: 9cad197a4e685f8f4ade42abe1bcb28a4100e8bc (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
#ifndef _I8042_SPARCIO_H
#define _I8042_SPARCIO_H

#include <linux/config.h>
#include <asm/io.h>
#include <asm/oplib.h>
#include <asm/prom.h>
#include <asm/of_device.h>

static int i8042_kbd_irq = -1;
static int i8042_aux_irq = -1;
#define I8042_KBD_IRQ i8042_kbd_irq
#define I8042_AUX_IRQ i8042_aux_irq

#define I8042_KBD_PHYS_DESC "sparcps2/serio0"
#define I8042_AUX_PHYS_DESC "sparcps2/serio1"
#define I8042_MUX_PHYS_DESC "sparcps2/serio%d"

static void __iomem *kbd_iobase;

#define I8042_COMMAND_REG	(kbd_iobase + 0x64UL)
#define I8042_DATA_REG		(kbd_iobase + 0x60UL)

static inline int i8042_read_data(void)
{
	return readb(kbd_iobase + 0x60UL);
}

static inline int i8042_read_status(void)
{
	return readb(kbd_iobase + 0x64UL);
}

static inline void i8042_write_data(int val)
{
	writeb(val, kbd_iobase + 0x60UL);
}

static inline void i8042_write_command(int val)
{
	writeb(val, kbd_iobase + 0x64UL);
}

#define OBP_PS2KBD_NAME1	"kb_ps2"
#define OBP_PS2KBD_NAME2	"keyboard"
#define OBP_PS2MS_NAME1		"kdmouse"
#define OBP_PS2MS_NAME2		"mouse"

static int __devinit sparc_i8042_probe(struct of_device *op, const struct of_device_id *match)
{
	struct device_node *dp = op->node;

	dp = dp->child;
	while (dp) {
		if (!strcmp(dp->name, OBP_PS2KBD_NAME1) ||
		    !strcmp(dp->name, OBP_PS2KBD_NAME2)) {
			struct of_device *kbd = of_find_device_by_node(dp);
			unsigned int irq = kbd->irqs[0];
			if (irq == 0xffffffff)
				irq = op->irqs[0];
			i8042_kbd_irq = irq;
			kbd_iobase = of_ioremap(&kbd->resource[0],
						0, 8, "kbd");
		} else if (!strcmp(dp->name, OBP_PS2MS_NAME1) ||
			   !strcmp(dp->name, OBP_PS2MS_NAME2)) {
			struct of_device *ms = of_find_device_by_node(dp);
			unsigned int irq = ms->irqs[0];
			if (irq == 0xffffffff)
				irq = op->irqs[0];
			i8042_aux_irq = irq;
		}

		dp = dp->sibling;
	}

	return 0;
}

static int __devexit sparc_i8042_remove(struct of_device *op)
{
	of_iounmap(kbd_iobase, 8);

	return 0;
}

static struct of_device_id sparc_i8042_match[] = {
	{
		.name = "8042",
	},
	{},
};
MODULE_DEVICE_TABLE(of, i8042_match);

static struct of_platform_driver sparc_i8042_driver = {
	.name		= "i8042",
	.match_table	= sparc_i8042_match,
	.probe		= sparc_i8042_probe,
	.remove		= __devexit_p(sparc_i8042_remove),
};

static int __init i8042_platform_init(void)
{
#ifndef CONFIG_PCI
	return -ENODEV;
#else
	struct device_node *root = of_find_node_by_path("/");

	if (!strcmp(root->name, "SUNW,JavaStation-1")) {
		/* Hardcoded values for MrCoffee.  */
		i8042_kbd_irq = i8042_aux_irq = 13 | 0x20;
		kbd_iobase = ioremap(0x71300060, 8);
		if (!kbd_iobase)
			return -ENODEV;
	} else {
		int err = of_register_driver(&sparc_i8042_driver,
					     &of_bus_type);
		if (err)
			return err;

		if (i8042_kbd_irq == -1 ||
		    i8042_aux_irq == -1) {
			if (kbd_iobase) {
				of_iounmap(kbd_iobase, 8);
				kbd_iobase = (void __iomem *) NULL;
			}
			return -ENODEV;
		}
	}

	i8042_reset = 1;

	return 0;
#endif /* CONFIG_PCI */
}

static inline void i8042_platform_exit(void)
{
#ifdef CONFIG_PCI
	struct device_node *root = of_find_node_by_path("/");

	if (strcmp(root->name, "SUNW,JavaStation-1"))
		of_unregister_driver(&sparc_i8042_driver);
#endif
}

#endif /* _I8042_SPARCIO_H */