1 /* $NetBSD: optpoint.c,v 1.5 2006/11/12 19:00:42 plunky Exp $ */
4 * Copyright (c) 2005 HAMAJIMA Katsuomi. All rights reserved.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * OptOpint on Telios HC-AJ2
32 #include <sys/cdefs.h>
34 __KERNEL_RCSID(0, "$NetBSD: optpoint.c,v 1.5 2006/11/12 19:00:42 plunky Exp $");
36 #include <sys/param.h>
37 #include <sys/systm.h>
38 #include <sys/device.h>
39 #include <machine/bus.h>
40 #include <machine/config_hook.h>
41 #include <dev/hpc/hpciovar.h>
42 #include <dev/wscons/wsconsio.h>
43 #include <dev/wscons/wsmousevar.h>
44 #include <hpcmips/tx/tx39var.h>
45 #include <hpcmips/tx/tx39spivar.h>
46 #include <hpcmips/tx/tx39icureg.h>
51 #define DPRINTF(arg) printf arg
56 struct optpoint_softc
{
58 tx_chipset_tag_t sc_tc
;
59 struct tx39spi_softc
*sc_spi
;
60 struct hpcio_chip
*sc_hc
;
61 struct device
*sc_wsmousedev
;
62 void *sc_powerhook
; /* power management hook */
64 int index
; /* number of bytes received for this packet */
65 u_int buttons
; /* mouse button status */
69 static int optpoint_match(struct device
*, struct cfdata
*, void *);
70 static void optpoint_attach(struct device
*, struct device
*, void *);
71 static int optpoint_intr(void *);
72 static int optpoint_enable(void *);
73 static void optpoint_disable(void *);
74 static int optpoint_ioctl(void *, u_long
, void *, int, struct lwp
*);
75 static int optpoint_initialize(void *);
76 static void optpoint_send(struct optpoint_softc
*, int);
77 static int optpoint_recv(struct optpoint_softc
*);
78 static int optpoint_power(void *, int, long, void *);
83 #define TX39_INTRSTATUS4_OPTPOINTINT TX39_INTRSTATUS4_CARDIORDNEGINT
84 #define TX39_IO_MFIO_CARDREG 11
85 #define TX39_IO_MFIO_CARDIOWR 10
86 #define TX39_IO_MFIO_CARDIORD 9
87 #define TELIOS_MFIO_OPTP_T_RDY TX39_IO_MFIO_CARDREG
88 #define TELIOS_MFIO_OPTP_C_REQ TX39_IO_MFIO_CARDIOWR
89 #define TELIOS_MFIO_OPTP_S_ENB_N TX39_IO_MFIO_CARDIORD
91 CFATTACH_DECL(optpoint
, sizeof(struct optpoint_softc
),
92 optpoint_match
, optpoint_attach
, NULL
, NULL
);
94 const struct wsmouse_accessops optpoint_accessops
= {
101 optpoint_match(struct device
*parent
, struct cfdata
*cf
, void *aux
)
103 return (ATTACH_NORMAL
);
107 optpoint_attach(struct device
*parent
, struct device
*self
, void *aux
)
109 struct txspi_attach_args
*ta
= aux
;
110 struct optpoint_softc
*sc
= (void*)self
;
111 struct tx39spi_softc
*spi
= sc
->sc_spi
= (void*)parent
;
112 tx_chipset_tag_t tc
= sc
->sc_tc
= ta
->sa_tc
;
113 struct wsmousedev_attach_args wsmaa
;
115 sc
->sc_hc
= tc
->tc_iochip
[MFIO
];
118 /* Specific SPI settings for OptPoint of HC-AJ2 */
119 tx39spi_delayval(spi
, 0);
120 tx39spi_baudrate(spi
, 4); /* SPICLK Rate = 737.3 kHz */
121 tx39spi_word(spi
, 0); /* Use 8bits of data */
122 tx39spi_phapol(spi
, 0);
123 tx39spi_clkpol(spi
, 1);
124 tx39spi_lsb(spi
, 0); /* MSB first */
129 wsmaa
.accessops
= &optpoint_accessops
;
130 wsmaa
.accesscookie
= sc
;
131 /* attach the wsmouse */
132 sc
->sc_wsmousedev
= config_found(self
, &wsmaa
, wsmousedevprint
);
134 /* Add a hard power hook to power saving */
135 sc
->sc_powerhook
= config_hook(CONFIG_HOOK_PMEVENT
,
136 CONFIG_HOOK_PMEVENT_HARDPOWER
,
140 if (sc
->sc_powerhook
== 0)
141 printf("%s: unable to establish hard power hook",
142 sc
->sc_dev
.dv_xname
);
147 optpoint_intr(void *self
)
149 struct optpoint_softc
*sc
= (void*)self
;
150 tx_chipset_tag_t tc
= sc
->sc_tc
;
151 char data
= optpoint_recv(sc
) & 0xff;
155 printf("%s: Receive buffer overflow\n", sc
->sc_dev
.dv_xname
);
157 memset(sc
->packet
, 0, 3);
160 if ((sc
->index
== 1) && (data
& 0xcc) != 0x08){
161 DPRINTF(("%s: Bad second byte (0x%02x)\n",
162 sc
->sc_dev
.dv_xname
, data
));
163 tx_conf_write(tc
, TX39_INTRCLEAR4_REG
,
164 TX39_INTRSTATUS4_OPTPOINTINT
);
168 sc
->packet
[sc
->index
++] = data
;
170 u_int newbuttons
= ((sc
->packet
[1] & LBUTMASK
) ? 0x1 : 0)
171 | ((sc
->packet
[1] & RBUTMASK
) ? 0x2 : 0);
172 int dx
= sc
->packet
[2];
173 int dy
= sc
->packet
[0];
174 u_int changed
= (sc
->buttons
^ newbuttons
);
176 if (dx
|| dy
|| changed
){
177 DPRINTF(("%s: buttons=0x%x, dx=%d, dy=%d\n",
178 sc
->sc_dev
.dv_xname
, newbuttons
, dx
, dy
));
179 wsmouse_input(sc
->sc_wsmousedev
,
182 WSMOUSE_INPUT_DELTA
);
184 sc
->buttons
= newbuttons
;
186 memset(sc
->packet
, 0, 3);
188 tx_conf_write(tc
, TX39_INTRCLEAR4_REG
, TX39_INTRSTATUS4_OPTPOINTINT
);
194 optpoint_enable(void *self
)
196 struct optpoint_softc
*sc
= (void*)self
;
199 tx_chipset_tag_t tc
= sc
->sc_tc
;
200 struct hpcio_chip
*hc
= sc
->sc_hc
;
203 DPRINTF(("%s: enable\n", sc
->sc_dev
.dv_xname
));
208 sc
->packet
[0] = 0xf5; /* Disable */
209 sc
->packet
[1] = 0xf2; /* Set Stream Mode */
210 sc
->packet
[2] = 0xf8; /* Stanby */
211 sc
->packet
[3] = 0xf4; /* Enable */
213 tx39spi_enable(sc
->sc_spi
, 1);
214 tx_intr_establish(tc
, MAKEINTR(4, TX39_INTRSTATUS4_OPTPOINTINT
),
215 IST_EDGE
, IPL_TTY
, optpoint_initialize
, sc
);
216 (*hc
->hc_portwrite
)(hc
, TELIOS_MFIO_OPTP_C_REQ
, 1);
217 (*hc
->hc_portwrite
)(hc
, TELIOS_MFIO_OPTP_T_RDY
, 1);
225 optpoint_disable(void *self
)
227 struct optpoint_softc
*sc
= (void*)self
;
230 tx_chipset_tag_t tc
= sc
->sc_tc
;
231 struct hpcio_chip
*hc
= sc
->sc_hc
;
234 DPRINTF(("%s: disable\n", sc
->sc_dev
.dv_xname
));
237 (*hc
->hc_portwrite
)(hc
, TELIOS_MFIO_OPTP_C_REQ
, 0);
238 (*hc
->hc_portwrite
)(hc
, TELIOS_MFIO_OPTP_T_RDY
, 0);
239 tx_intr_disestablish(tc
,
240 (void *)MAKEINTR(4, TX39_INTRSTATUS4_OPTPOINTINT
));
241 tx39spi_enable(sc
->sc_spi
, 0);
247 optpoint_ioctl(void *self
, u_long cmd
, void *data
, int flag
, struct lwp
*l
)
250 case WSMOUSEIO_GTYPE
:
251 *(u_int
*)data
= WSMOUSE_TYPE_PS2
;
255 return (EPASSTHROUGH
);
261 optpoint_initialize(void *self
)
263 struct optpoint_softc
*sc
= (void*)self
;
264 struct hpcio_chip
*hc
= sc
->sc_hc
;
265 tx_chipset_tag_t tc
= sc
->sc_tc
;
268 optpoint_send(sc
, sc
->packet
[sc
->index
++]);
269 (*hc
->hc_portwrite
)(hc
, TELIOS_MFIO_OPTP_C_REQ
, 1);
270 (*hc
->hc_portwrite
)(hc
, TELIOS_MFIO_OPTP_T_RDY
, 1);
272 tx_intr_disestablish(tc
,
273 (void *)MAKEINTR(4, TX39_INTRSTATUS4_OPTPOINTINT
));
275 memset(sc
->packet
, 0, 3);
276 tx_intr_establish(tc
,
277 MAKEINTR(4, TX39_INTRSTATUS4_OPTPOINTINT
),
278 IST_EDGE
, IPL_TTY
, optpoint_intr
, sc
);
279 (*hc
->hc_portwrite
)(hc
, TELIOS_MFIO_OPTP_C_REQ
, 0);
280 (*hc
->hc_portwrite
)(hc
, TELIOS_MFIO_OPTP_T_RDY
, 1);
282 tx_conf_write(tc
, TX39_INTRCLEAR4_REG
, TX39_INTRSTATUS4_OPTPOINTINT
);
288 optpoint_send(struct optpoint_softc
*sc
, int data
)
290 struct hpcio_chip
*hc
= sc
->sc_hc
;
292 while ((*hc
->hc_portread
)(hc
, TELIOS_MFIO_OPTP_S_ENB_N
))
294 tx39spi_put_word(sc
->sc_spi
, data
& 0xff);
298 optpoint_recv(struct optpoint_softc
*sc
)
300 struct hpcio_chip
*hc
= sc
->sc_hc
;
302 optpoint_send(sc
, 0x00);
303 while ((*hc
->hc_portread
)(hc
, TELIOS_MFIO_OPTP_S_ENB_N
))
305 return tx39spi_get_word(sc
->sc_spi
) & 0xff;
309 optpoint_power(void *self
, int type
, long id
, void *msg
)
311 struct optpoint_softc
*sc
= (void *)self
;
323 optpoint_disable(sc
);