summaryrefslogtreecommitdiff
path: root/drivers/input/serio/i8042-sparcio.h
blob: 5071af2c06040f3032d85f4f44be9be5f0202319 (plain) (blame)
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
147
148
149
150
151
152
153
154
155
#ifndef _I8042_SPARCIO_H
#define _I8042_SPARCIO_H

#include <linux/of_device.h>

#include <asm/io.h>
#include <asm/oplib.h>
#include <asm/prom.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;
static struct resource *kbd_res;

#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);
}

#ifdef CONFIG_PCI

#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");
			kbd_res = &kbd->resource[0];
		} 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_res, kbd_iobase, 8);

	return 0;
}

static const struct of_device_id sparc_i8042_match[] = {
	{
		.name = "8042",
	},
	{},
};
MODULE_DEVICE_TABLE(of, sparc_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)
{
	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_res, kbd_iobase, 8);
				kbd_iobase = (void __iomem *) NULL;
			}
			return -ENODEV;
		}
	}

	i8042_reset = 1;

	return 0;
}

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

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

#else /* !CONFIG_PCI */
static int __init i8042_platform_init(void)
{
	return -ENODEV;
}

static inline void i8042_platform_exit(void)
{
}
#endif /* !CONFIG_PCI */

#endif /* _I8042_SPARCIO_H */