xref: /openbsd-src/sys/arch/sparc64/dev/ofwi2c.c (revision 053384b22785905bb18b3fb3239d44c8c3e4e2a0)
1*053384b2Sderaadt /*	$OpenBSD: ofwi2c.c,v 1.9 2014/02/21 21:28:26 deraadt Exp $	*/
2e8379949Sderaadt 
3e8379949Sderaadt /*
4e8379949Sderaadt  * Copyright (c) 2006 Theo de Raadt
5e8379949Sderaadt  *
6e8379949Sderaadt  * Permission to use, copy, modify, and distribute this software for any
7e8379949Sderaadt  * purpose with or without fee is hereby granted, provided that the above
8e8379949Sderaadt  * copyright notice and this permission notice appear in all copies.
9e8379949Sderaadt  *
10e8379949Sderaadt  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11e8379949Sderaadt  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12e8379949Sderaadt  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13e8379949Sderaadt  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14e8379949Sderaadt  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15e8379949Sderaadt  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16e8379949Sderaadt  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17e8379949Sderaadt  */
18e8379949Sderaadt 
19e8379949Sderaadt #include <sys/param.h>
20e8379949Sderaadt #include <sys/systm.h>
21e8379949Sderaadt #include <sys/device.h>
22e8379949Sderaadt 
23e8379949Sderaadt #include <dev/i2c/i2cvar.h>
24e8379949Sderaadt #include <dev/ofw/openfirm.h>
25e8379949Sderaadt 
26e8379949Sderaadt #include <dev/pci/pcivar.h>
27e8379949Sderaadt #include <dev/pci/pcireg.h>
28e8379949Sderaadt #include <sparc64/pci_machdep.h>
29e8379949Sderaadt 
30e8379949Sderaadt #include <arch/sparc64/dev/ofwi2cvar.h>
31e8379949Sderaadt 
32e8379949Sderaadt void
ofwiic_pci_scan(struct device * self,struct i2cbus_attach_args * iba,void * aux)336e8deec5Sdlg ofwiic_pci_scan(struct device *self, struct i2cbus_attach_args *iba, void *aux)
34e8379949Sderaadt {
35e8379949Sderaadt 	struct pci_attach_args *pa = aux;
36e8379949Sderaadt 	pcitag_t tag = pa->pa_tag;
37e8379949Sderaadt 	int iba_node = PCITAG_NODE(tag);
386e8deec5Sdlg 	char name[32];
396e8deec5Sdlg 	int node;
406e8deec5Sdlg 
416e8deec5Sdlg 	for (node = OF_child(iba_node); node; node = OF_peer(node)) {
426e8deec5Sdlg 		memset(name, 0, sizeof(name));
436e8deec5Sdlg 
446e8deec5Sdlg 		if (OF_getprop(node, "compatible", name, sizeof(name)) == -1)
456e8deec5Sdlg 			continue;
466e8deec5Sdlg 		if (name[0] == '\0')
476e8deec5Sdlg 			continue;
486e8deec5Sdlg 
499c6a5656Sderaadt 		if (strcmp(name, "i2c-smbus") == 0 ||
509c6a5656Sderaadt 		    strcmp(name, "i2c") == 0)
516e8deec5Sdlg 			ofwiic_scan(self, iba, &node);
526e8deec5Sdlg 	}
536e8deec5Sdlg }
546e8deec5Sdlg 
556e8deec5Sdlg void
ofwiic_scan(struct device * self,struct i2cbus_attach_args * iba,void * aux)566e8deec5Sdlg ofwiic_scan(struct device *self, struct i2cbus_attach_args *iba, void *aux)
576e8deec5Sdlg {
586e8deec5Sdlg 	int iba_node = *(int *)aux;
59e8379949Sderaadt 	extern int iic_print(void *, const char *);
60e8379949Sderaadt 	struct i2c_attach_args ia;
61e8379949Sderaadt 	char name[32];
62e8379949Sderaadt 	u_int32_t reg[2];
63e8379949Sderaadt 	int node;
64e8379949Sderaadt 
65e8379949Sderaadt 	for (node = OF_child(iba_node); node; node = OF_peer(node)) {
666e8deec5Sdlg 		memset(name, 0, sizeof(name));
676e8deec5Sdlg 		memset(reg, 0, sizeof(reg));
68e8379949Sderaadt 
696e8deec5Sdlg 		if (OF_getprop(node, "compatible", name, sizeof(name)) == -1)
70e8379949Sderaadt 			continue;
716e8deec5Sdlg 		if (name[0] == '\0')
726e8deec5Sdlg 			continue;
736e8deec5Sdlg 
746e8deec5Sdlg 		if (OF_getprop(node, "reg", reg, sizeof(reg)) == -1)
756e8deec5Sdlg 			continue;
766e8deec5Sdlg 
776e8deec5Sdlg 		memset(&ia, 0, sizeof(ia));
786e8deec5Sdlg 		ia.ia_tag = iba->iba_tag;
799c6a5656Sderaadt 		ia.ia_addr = (reg[0] << 7) | (reg[1] >> 1);
806e8deec5Sdlg 		ia.ia_name = name;
816e8deec5Sdlg 		ia.ia_cookie = &node;
826e8deec5Sdlg 
836e8deec5Sdlg 		if (strncmp(ia.ia_name, "i2c-", strlen("i2c-")) == 0)
846e8deec5Sdlg 			ia.ia_name += strlen("i2c-");
856e8deec5Sdlg 
86cf78ad2fSkettenis 		/* Skip non-SPD EEPROMs.  */
87cf78ad2fSkettenis 		if (strcmp(ia.ia_name, "at24c64") == 0 ||
88cf78ad2fSkettenis 		    strcmp(ia.ia_name, "at34c02") == 0) {
89cf78ad2fSkettenis 			if (OF_getprop(node, "name", name, sizeof(name)) == -1)
90cf78ad2fSkettenis 				continue;
91cf78ad2fSkettenis 			if (strcmp(name, "dimm") == 0 ||
92cf78ad2fSkettenis 			    strcmp(name, "dimm-spd") == 0)
93cf78ad2fSkettenis 				ia.ia_name = "spd";
94cf78ad2fSkettenis 			else
95cf78ad2fSkettenis 				continue;
96cf78ad2fSkettenis 		}
97cf78ad2fSkettenis 
98ed197d5cSderaadt 		/*
99*053384b2Sderaadt 		 * XXX alipm crashes on some machines for an unknown reason
100*053384b2Sderaadt 		 * when doing the periodic i2c accesses things like sensors
101*053384b2Sderaadt 		 * need.  However, devices accessed only at boot are fine.
102ed197d5cSderaadt 		 */
103ed197d5cSderaadt 		if (strcmp(self->dv_parent->dv_xname, "alipm0") == 0 &&
104ed197d5cSderaadt 		    (ia.ia_addr < 0x50 || ia.ia_addr > 0x57)) {
105ed197d5cSderaadt 			iic_print(&ia, self->dv_parent->dv_xname);
106ed197d5cSderaadt 			printf(" skipped due to %s bugs\n",
107ed197d5cSderaadt 			    self->dv_parent->dv_xname);
108ed197d5cSderaadt 			continue;
109ed197d5cSderaadt 		}
110ed197d5cSderaadt 
111e8379949Sderaadt 		config_found(self, &ia, iic_print);
112e8379949Sderaadt 	}
113e8379949Sderaadt }
114