xref: /netbsd-src/sys/arch/hpcarm/dev/nbppcon.c (revision c7fb772b85b2b5d4cfb282f868f454b4701534fd)
1*c7fb772bSthorpej /*	$NetBSD: nbppcon.c,v 1.5 2021/08/07 16:18:53 thorpej Exp $ */
2587ef940Skiyohara /*
3587ef940Skiyohara  * Copyright (c) 2011 KIYOHARA Takashi
4587ef940Skiyohara  * All rights reserved.
5587ef940Skiyohara  *
6587ef940Skiyohara  * Redistribution and use in source and binary forms, with or without
7587ef940Skiyohara  * modification, are permitted provided that the following conditions
8587ef940Skiyohara  * are met:
9587ef940Skiyohara  * 1. Redistributions of source code must retain the above copyright
10587ef940Skiyohara  *    notice, this list of conditions and the following disclaimer.
11587ef940Skiyohara  * 2. Redistributions in binary form must reproduce the above copyright
12587ef940Skiyohara  *    notice, this list of conditions and the following disclaimer in the
13587ef940Skiyohara  *    documentation and/or other materials provided with the distribution.
14587ef940Skiyohara  *
15587ef940Skiyohara  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16587ef940Skiyohara  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17587ef940Skiyohara  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18587ef940Skiyohara  * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
19587ef940Skiyohara  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20587ef940Skiyohara  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21587ef940Skiyohara  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22587ef940Skiyohara  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
23587ef940Skiyohara  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
24587ef940Skiyohara  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25587ef940Skiyohara  * POSSIBILITY OF SUCH DAMAGE.
26587ef940Skiyohara  */
27587ef940Skiyohara #include <sys/cdefs.h>
28*c7fb772bSthorpej __KERNEL_RCSID(0, "$NetBSD: nbppcon.c,v 1.5 2021/08/07 16:18:53 thorpej Exp $");
29587ef940Skiyohara 
30587ef940Skiyohara #include <sys/param.h>
31587ef940Skiyohara #include <sys/device.h>
32587ef940Skiyohara #include <sys/errno.h>
33587ef940Skiyohara 
34587ef940Skiyohara #include <machine/platid.h>
35587ef940Skiyohara #include <machine/platid_mask.h>
36587ef940Skiyohara 
37587ef940Skiyohara #include <arm/xscale/pxa2x0_i2c.h>
38587ef940Skiyohara 
39587ef940Skiyohara #include <hpcarm/dev/nbppconvar.h>
40587ef940Skiyohara 
41587ef940Skiyohara #include <dev/i2c/i2cvar.h>
42587ef940Skiyohara #include <dev/i2c/at24cxxvar.h>
43587ef940Skiyohara 
44587ef940Skiyohara #include "locators.h"
45587ef940Skiyohara 
46587ef940Skiyohara #define NBPPCON_ADDR	0x13
47587ef940Skiyohara 
48587ef940Skiyohara 
49587ef940Skiyohara struct nbppcon_softc {
50587ef940Skiyohara 	device_t sc_dev;
51587ef940Skiyohara 	i2c_tag_t sc_tag;
52587ef940Skiyohara 	int sc_address;
53587ef940Skiyohara 
54587ef940Skiyohara 	struct callback {
55587ef940Skiyohara 		int cb_tag;
56587ef940Skiyohara 		int (*cb_func)(void *, int, char *);
57587ef940Skiyohara 		void *cb_arg;
58587ef940Skiyohara 	} sc_cbs[2];
59587ef940Skiyohara };
60587ef940Skiyohara 
61587ef940Skiyohara static int nbppcon_match(device_t, cfdata_t, void *);
62587ef940Skiyohara static void nbppcon_attach(device_t, device_t, void *);
63587ef940Skiyohara 
64587ef940Skiyohara static int nbppcon_search(device_t, cfdata_t, const int *, void *);
65587ef940Skiyohara static int nbppcon_print(void *aux, const char *pnp);
66587ef940Skiyohara 
67587ef940Skiyohara CFATTACH_DECL_NEW(nbppcon, sizeof(struct nbppcon_softc),
68587ef940Skiyohara     nbppcon_match, nbppcon_attach, NULL, NULL);
69587ef940Skiyohara 
70587ef940Skiyohara 
71587ef940Skiyohara /* ARGSUSED */
72587ef940Skiyohara static int
nbppcon_match(device_t parent,cfdata_t match,void * aux)73587ef940Skiyohara nbppcon_match(device_t parent, cfdata_t match, void *aux)
74587ef940Skiyohara {
75587ef940Skiyohara 	struct i2c_attach_args *ia = aux;
76587ef940Skiyohara 
77587ef940Skiyohara 	if (ia->ia_addr != NBPPCON_ADDR ||
78587ef940Skiyohara 	    !platid_match(&platid, &platid_mask_MACH_PSIONTEKLOGIX_NETBOOK_PRO))
79587ef940Skiyohara 		 return 0;
80587ef940Skiyohara 
81aa41e992Sthorpej 	return I2C_MATCH_ADDRESS_AND_PROBE;
82587ef940Skiyohara }
83587ef940Skiyohara 
84587ef940Skiyohara /* ARGSUSED */
85587ef940Skiyohara static void
nbppcon_attach(device_t parent,device_t self,void * aux)86587ef940Skiyohara nbppcon_attach(device_t parent, device_t self, void *aux)
87587ef940Skiyohara {
88587ef940Skiyohara 	struct nbppcon_softc *sc = device_private(self);
89587ef940Skiyohara 	struct i2c_attach_args *ia = aux;
90587ef940Skiyohara 	int rv;
91587ef940Skiyohara 	char buf[128];
92587ef940Skiyohara 
93587ef940Skiyohara 	sc->sc_dev = self;
94587ef940Skiyohara 	sc->sc_tag = ia->ia_tag;
95587ef940Skiyohara 	sc->sc_address = ia->ia_addr;
96587ef940Skiyohara 
97587ef940Skiyohara 	aprint_naive("\n");
98587ef940Skiyohara 	aprint_normal(": NETBOOK PRO PCon\n");
99587ef940Skiyohara 
100587ef940Skiyohara #define NVRAM_ADDR	0x53
101587ef940Skiyohara #define NVRAM_DATA_REV	0x14
102587ef940Skiyohara 	rv = seeprom_bootstrap_read(sc->sc_tag, NVRAM_ADDR, 0x00, 128,
103587ef940Skiyohara 	    buf, sizeof(buf));
104587ef940Skiyohara 	if (rv == 0)
105fbd7a1abSkiyohara 		aprint_normal_dev(self, "NETBOOK PRO Rev.%c\n",
106587ef940Skiyohara 		    buf[NVRAM_DATA_REV] - '0' + '@');
107587ef940Skiyohara 	else
108587ef940Skiyohara 		aprint_error_dev(self, "NVRAM read failed\n");
109587ef940Skiyohara 
1102685996bSthorpej 	config_search(self, NULL,
111*c7fb772bSthorpej 	    CFARGS(.search = nbppcon_search));
112587ef940Skiyohara }
113587ef940Skiyohara 
114587ef940Skiyohara /* ARGSUSED */
115587ef940Skiyohara static int
nbppcon_search(device_t self,cfdata_t cf,const int * ldesc,void * aux)116587ef940Skiyohara nbppcon_search(device_t self, cfdata_t cf, const int *ldesc, void *aux)
117587ef940Skiyohara {
118587ef940Skiyohara 	struct nbppcon_attach_args pcon;
119587ef940Skiyohara 
120587ef940Skiyohara 	pcon.aa_name = cf->cf_name;
121587ef940Skiyohara 	pcon.aa_tag = cf->cf_loc[NBPPCONCF_TAG];
122587ef940Skiyohara 
1232685996bSthorpej 	if (config_probe(self, cf, &pcon))
124*c7fb772bSthorpej 		config_attach(self, cf, &pcon, nbppcon_print, CFARGS_NONE);
125587ef940Skiyohara 
126587ef940Skiyohara 	return 0;
127587ef940Skiyohara }
128587ef940Skiyohara 
129587ef940Skiyohara /* ARGSUSED */
130587ef940Skiyohara static int
nbppcon_print(void * aux,const char * pnp)131587ef940Skiyohara nbppcon_print(void *aux, const char *pnp)
132587ef940Skiyohara {
133587ef940Skiyohara 
134587ef940Skiyohara 	if (pnp != NULL)
135587ef940Skiyohara 		aprint_normal("%s", pnp);
136587ef940Skiyohara 	return UNCONF;
137587ef940Skiyohara }
138587ef940Skiyohara 
139587ef940Skiyohara 
140587ef940Skiyohara void *
nbppcon_regist_callback(device_t self,int tag,int (* func)(void *,int,char *),void * arg)141587ef940Skiyohara nbppcon_regist_callback(device_t self,
142587ef940Skiyohara 			int tag, int (*func)(void *, int, char *), void *arg)
143587ef940Skiyohara {
144587ef940Skiyohara 	struct nbppcon_softc *sc = device_private(self);
145587ef940Skiyohara 	int i;
146587ef940Skiyohara 
147587ef940Skiyohara 	for (i = 0; i < __arraycount(sc->sc_cbs); i++)
148587ef940Skiyohara 		if (sc->sc_cbs[i].cb_func == NULL) {
149587ef940Skiyohara 			sc->sc_cbs[i].cb_tag = tag;
150587ef940Skiyohara 			sc->sc_cbs[i].cb_func = func;
151587ef940Skiyohara 			sc->sc_cbs[i].cb_arg = arg;
152587ef940Skiyohara 			return func;
153587ef940Skiyohara 		}
154587ef940Skiyohara 
155587ef940Skiyohara 	return NULL;
156587ef940Skiyohara }
157587ef940Skiyohara 
158587ef940Skiyohara int
nbppcon_intr(device_t self,int buflen,char * buf)159587ef940Skiyohara nbppcon_intr(device_t self, int buflen, char *buf)
160587ef940Skiyohara {
161587ef940Skiyohara 	struct nbppcon_softc *sc = device_private(self);
162587ef940Skiyohara 	struct callback *cb;
163587ef940Skiyohara 	int i;
164587ef940Skiyohara 
165587ef940Skiyohara 	for (i = 0; i < __arraycount(sc->sc_cbs); i++) {
166587ef940Skiyohara 		cb = &sc->sc_cbs[i];
167587ef940Skiyohara 		if (cb->cb_func != NULL &&
168587ef940Skiyohara 		    cb->cb_tag == buf[0])
169587ef940Skiyohara 			return cb->cb_func(cb->cb_arg, buflen, buf);
170587ef940Skiyohara 	}
171587ef940Skiyohara 	aprint_error_dev(sc->sc_dev, "unknown tag received: 0x%02x\n", buf[0]);
172587ef940Skiyohara 	return 0;
173587ef940Skiyohara }
174587ef940Skiyohara 
175587ef940Skiyohara int
nbppcon_poll(device_t self,int tag,int buflen,char * buf)176587ef940Skiyohara nbppcon_poll(device_t self, int tag, int buflen, char *buf)
177587ef940Skiyohara {
178587ef940Skiyohara 	struct nbppcon_softc *sc = device_private(self);
179587ef940Skiyohara 	int rv;
180587ef940Skiyohara 
181587ef940Skiyohara 	if (iic_acquire_bus(sc->sc_tag, I2C_F_POLL)) {
182587ef940Skiyohara 		aprint_error_dev(sc->sc_dev,
183587ef940Skiyohara 		    "%s: acquire bus failed\n", __func__);
184587ef940Skiyohara 		return -1;
185587ef940Skiyohara 	}
186587ef940Skiyohara 
187587ef940Skiyohara 	do {
188587ef940Skiyohara 		extern int nbpiic_poll(void *, int, char *);
189587ef940Skiyohara 
190587ef940Skiyohara 		rv = nbpiic_poll(sc->sc_tag->ic_cookie, buflen, buf);
191587ef940Skiyohara 		if (rv > 0 && buf[0] == tag)
192587ef940Skiyohara 			break;
193587ef940Skiyohara 	} while (rv == 0 || buf[0] != tag);
194587ef940Skiyohara 
195587ef940Skiyohara 	iic_release_bus(sc->sc_tag, I2C_F_POLL);
196587ef940Skiyohara 
197587ef940Skiyohara 	return rv;
198587ef940Skiyohara }
199587ef940Skiyohara 
200587ef940Skiyohara int
nbppcon_kbd_ready(device_t self)201587ef940Skiyohara nbppcon_kbd_ready(device_t self)
202587ef940Skiyohara {
203587ef940Skiyohara 	struct nbppcon_softc *sc = device_private(self);
204587ef940Skiyohara 	int rv;
205587ef940Skiyohara 	char cmd[1], data[1];
206587ef940Skiyohara 
207587ef940Skiyohara 	if (iic_acquire_bus(sc->sc_tag, I2C_F_POLL)) {
208587ef940Skiyohara 		aprint_error_dev(sc->sc_dev,
209587ef940Skiyohara 		    "%s: acquire bus failed\n", __func__);
210587ef940Skiyohara 		return -1;
211587ef940Skiyohara 	}
212587ef940Skiyohara 
213587ef940Skiyohara 	cmd[0] = 0x00;		/* Keyboard */
214587ef940Skiyohara 	data[0] = 0x00;		/* 0x00:Ready, 0x01:Busy? */
215587ef940Skiyohara 	rv = iic_exec(sc->sc_tag, I2C_OP_WRITE_WITH_STOP, sc->sc_address,
216587ef940Skiyohara 	    cmd, sizeof(cmd), data, sizeof(data), I2C_F_POLL);
217587ef940Skiyohara 
218587ef940Skiyohara 	cpu_dcache_wbinv_all();		/* XXXX: Why? */
219587ef940Skiyohara 
220587ef940Skiyohara 	iic_release_bus(sc->sc_tag, I2C_F_POLL);
221587ef940Skiyohara 
222587ef940Skiyohara 	return rv;
223587ef940Skiyohara }
224587ef940Skiyohara 
225587ef940Skiyohara int
nbppcon_pwr_hwreset(device_t self)226587ef940Skiyohara nbppcon_pwr_hwreset(device_t self)
227587ef940Skiyohara {
228587ef940Skiyohara 	struct nbppcon_softc *sc = device_private(self);
229587ef940Skiyohara 	int rv;
230587ef940Skiyohara 	char cmd[1], data[1];
231587ef940Skiyohara 
232587ef940Skiyohara 	if (iic_acquire_bus(sc->sc_tag, I2C_F_POLL)) {
233587ef940Skiyohara 		aprint_error_dev(sc->sc_dev,
234587ef940Skiyohara 		    "%s: acquire bus failed\n", __func__);
235587ef940Skiyohara 		return -1;
236587ef940Skiyohara 	}
237587ef940Skiyohara 
238587ef940Skiyohara 	cmd[0] = 0x05;		/* POWER */
239587ef940Skiyohara 	data[0] = 0x00;		/* HWReset */
240587ef940Skiyohara #if 0
241587ef940Skiyohara 	rv = iic_exec(sc->sc_tag, I2C_OP_WRITE_WITH_STOP, sc->sc_address,
242587ef940Skiyohara 	    cmd, sizeof(cmd), data, sizeof(data), I2C_F_POLL);
243587ef940Skiyohara #else	/* XXXX: Oops, ensure HWReset, ignore cmd and data. */
244587ef940Skiyohara 	rv = iic_exec(sc->sc_tag, I2C_OP_WRITE_WITH_STOP, sc->sc_address + 1,
245587ef940Skiyohara 	    cmd, sizeof(cmd), data, sizeof(data), I2C_F_POLL);
246587ef940Skiyohara #endif
247587ef940Skiyohara 
248587ef940Skiyohara 	iic_release_bus(sc->sc_tag, I2C_F_POLL);
249587ef940Skiyohara 
250587ef940Skiyohara 	return rv;
251587ef940Skiyohara }
252