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