xref: /freebsd/sys/dev/smbus/smbconf.c (revision d70424edcbc5826900198fd3ecd4abe0a06887cd)
1d70424edSNicolas Souchu /*-
2d70424edSNicolas Souchu  * Copyright (c) 1998 Nicolas Souchu
3d70424edSNicolas Souchu  * All rights reserved.
4d70424edSNicolas Souchu  *
5d70424edSNicolas Souchu  * Redistribution and use in source and binary forms, with or without
6d70424edSNicolas Souchu  * modification, are permitted provided that the following conditions
7d70424edSNicolas Souchu  * are met:
8d70424edSNicolas Souchu  * 1. Redistributions of source code must retain the above copyright
9d70424edSNicolas Souchu  *    notice, this list of conditions and the following disclaimer.
10d70424edSNicolas Souchu  * 2. Redistributions in binary form must reproduce the above copyright
11d70424edSNicolas Souchu  *    notice, this list of conditions and the following disclaimer in the
12d70424edSNicolas Souchu  *    documentation and/or other materials provided with the distribution.
13d70424edSNicolas Souchu  *
14d70424edSNicolas Souchu  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15d70424edSNicolas Souchu  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16d70424edSNicolas Souchu  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17d70424edSNicolas Souchu  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18d70424edSNicolas Souchu  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19d70424edSNicolas Souchu  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20d70424edSNicolas Souchu  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21d70424edSNicolas Souchu  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22d70424edSNicolas Souchu  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23d70424edSNicolas Souchu  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24d70424edSNicolas Souchu  * SUCH DAMAGE.
25d70424edSNicolas Souchu  *
26d70424edSNicolas Souchu  *	$Id: smbconf.c,v 1.1.1.2 1998/08/13 15:16:57 son Exp $
27d70424edSNicolas Souchu  *
28d70424edSNicolas Souchu  */
29d70424edSNicolas Souchu #include <sys/param.h>
30d70424edSNicolas Souchu #include <sys/systm.h>
31d70424edSNicolas Souchu #include <sys/kernel.h>
32d70424edSNicolas Souchu #include <sys/malloc.h>
33d70424edSNicolas Souchu #include <sys/module.h>
34d70424edSNicolas Souchu #include <sys/bus.h>
35d70424edSNicolas Souchu 
36d70424edSNicolas Souchu #include <dev/smbus/smbconf.h>
37d70424edSNicolas Souchu #include <dev/smbus/smbus.h>
38d70424edSNicolas Souchu #include "smbus_if.h"
39d70424edSNicolas Souchu 
40d70424edSNicolas Souchu /*
41d70424edSNicolas Souchu  * smbus_intr()
42d70424edSNicolas Souchu  */
43d70424edSNicolas Souchu void
44d70424edSNicolas Souchu smbus_intr(device_t bus, u_char devaddr, char low, char high, int error)
45d70424edSNicolas Souchu {
46d70424edSNicolas Souchu 	struct smbus_softc *sc = (struct smbus_softc *)device_get_softc(bus);
47d70424edSNicolas Souchu 
48d70424edSNicolas Souchu 	/* call owner's intr routine */
49d70424edSNicolas Souchu 	if (sc->owner)
50d70424edSNicolas Souchu 		SMBUS_INTR(sc->owner, devaddr, low, high, error);
51d70424edSNicolas Souchu 
52d70424edSNicolas Souchu 	return;
53d70424edSNicolas Souchu }
54d70424edSNicolas Souchu 
55d70424edSNicolas Souchu /*
56d70424edSNicolas Souchu  * smbus_alloc_bus()
57d70424edSNicolas Souchu  *
58d70424edSNicolas Souchu  * Allocate a new bus connected to the given parent device
59d70424edSNicolas Souchu  */
60d70424edSNicolas Souchu device_t
61d70424edSNicolas Souchu smbus_alloc_bus(device_t parent)
62d70424edSNicolas Souchu {
63d70424edSNicolas Souchu 	device_t child;
64d70424edSNicolas Souchu 
65d70424edSNicolas Souchu 	/* add the bus to the parent */
66d70424edSNicolas Souchu 	child = device_add_child(parent, "smbus", -1, NULL);
67d70424edSNicolas Souchu 
68d70424edSNicolas Souchu 	if (child)
69d70424edSNicolas Souchu 		device_set_desc(child, "System Management Bus");
70d70424edSNicolas Souchu 
71d70424edSNicolas Souchu 	return (child);
72d70424edSNicolas Souchu }
73d70424edSNicolas Souchu 
74d70424edSNicolas Souchu /*
75d70424edSNicolas Souchu  * smbus_request_bus()
76d70424edSNicolas Souchu  *
77d70424edSNicolas Souchu  * Allocate the device to perform transfers.
78d70424edSNicolas Souchu  *
79d70424edSNicolas Souchu  * how	: SMB_WAIT or SMB_DONTWAIT
80d70424edSNicolas Souchu  */
81d70424edSNicolas Souchu int
82d70424edSNicolas Souchu smbus_request_bus(device_t bus, device_t dev, int how)
83d70424edSNicolas Souchu {
84d70424edSNicolas Souchu 	struct smbus_softc *sc = (struct smbus_softc *)device_get_softc(bus);
85d70424edSNicolas Souchu 	int s, error = 0;
86d70424edSNicolas Souchu 
87d70424edSNicolas Souchu 	while (!error) {
88d70424edSNicolas Souchu 		s = splhigh();
89d70424edSNicolas Souchu 		if (sc->owner) {
90d70424edSNicolas Souchu 			splx(s);
91d70424edSNicolas Souchu 
92d70424edSNicolas Souchu 			switch (how) {
93d70424edSNicolas Souchu 			case (SMB_WAIT | SMB_INTR):
94d70424edSNicolas Souchu 				error = tsleep(sc, SMBPRI|PCATCH, "smbreq", 0);
95d70424edSNicolas Souchu 				break;
96d70424edSNicolas Souchu 
97d70424edSNicolas Souchu 			case (SMB_WAIT | SMB_NOINTR):
98d70424edSNicolas Souchu 				error = tsleep(sc, SMBPRI, "smbreq", 0);
99d70424edSNicolas Souchu 				break;
100d70424edSNicolas Souchu 
101d70424edSNicolas Souchu 			default:
102d70424edSNicolas Souchu 				return (EWOULDBLOCK);
103d70424edSNicolas Souchu 				break;
104d70424edSNicolas Souchu 			}
105d70424edSNicolas Souchu 
106d70424edSNicolas Souchu 		} else {
107d70424edSNicolas Souchu 			sc->owner = dev;
108d70424edSNicolas Souchu 
109d70424edSNicolas Souchu 			splx(s);
110d70424edSNicolas Souchu 			return (0);
111d70424edSNicolas Souchu 		}
112d70424edSNicolas Souchu 	}
113d70424edSNicolas Souchu 
114d70424edSNicolas Souchu 	return (error);
115d70424edSNicolas Souchu }
116d70424edSNicolas Souchu 
117d70424edSNicolas Souchu /*
118d70424edSNicolas Souchu  * smbus_release_bus()
119d70424edSNicolas Souchu  *
120d70424edSNicolas Souchu  * Release the device allocated with smbus_request_dev()
121d70424edSNicolas Souchu  */
122d70424edSNicolas Souchu int
123d70424edSNicolas Souchu smbus_release_bus(device_t bus, device_t dev)
124d70424edSNicolas Souchu {
125d70424edSNicolas Souchu 	struct smbus_softc *sc = (struct smbus_softc *)device_get_softc(bus);
126d70424edSNicolas Souchu 	int s;
127d70424edSNicolas Souchu 
128d70424edSNicolas Souchu 	s = splhigh();
129d70424edSNicolas Souchu 	if (sc->owner != dev) {
130d70424edSNicolas Souchu 		splx(s);
131d70424edSNicolas Souchu 		return (EACCES);
132d70424edSNicolas Souchu 	}
133d70424edSNicolas Souchu 
134d70424edSNicolas Souchu 	sc->owner = 0;
135d70424edSNicolas Souchu 	splx(s);
136d70424edSNicolas Souchu 
137d70424edSNicolas Souchu 	/* wakeup waiting processes */
138d70424edSNicolas Souchu 	wakeup(sc);
139d70424edSNicolas Souchu 
140d70424edSNicolas Souchu 	return (0);
141d70424edSNicolas Souchu }
142d70424edSNicolas Souchu 
143d70424edSNicolas Souchu /*
144d70424edSNicolas Souchu  * smbus_get_addr()
145d70424edSNicolas Souchu  *
146d70424edSNicolas Souchu  * Get the I2C 7 bits address of the device
147d70424edSNicolas Souchu  */
148d70424edSNicolas Souchu u_char
149d70424edSNicolas Souchu smbus_get_addr(device_t dev)
150d70424edSNicolas Souchu {
151d70424edSNicolas Souchu 	u_long addr;
152d70424edSNicolas Souchu 	device_t parent = device_get_parent(dev);
153d70424edSNicolas Souchu 
154d70424edSNicolas Souchu 	BUS_READ_IVAR(parent, dev, SMBUS_IVAR_ADDR, &addr);
155d70424edSNicolas Souchu 
156d70424edSNicolas Souchu 	return ((u_char)addr);
157d70424edSNicolas Souchu }
158