lpbb.c (185003) | lpbb.c (187576) |
---|---|
1/*- 2 * Copyright (c) 1998, 2001 Nicolas Souchu, Marc Bouget 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright --- 13 unchanged lines hidden (view full) --- 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 * 26 * 27 */ 28 29#include <sys/cdefs.h> | 1/*- 2 * Copyright (c) 1998, 2001 Nicolas Souchu, Marc Bouget 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright --- 13 unchanged lines hidden (view full) --- 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 * 26 * 27 */ 28 29#include <sys/cdefs.h> |
30__FBSDID("$FreeBSD: head/sys/dev/ppbus/lpbb.c 185003 2008-11-16 17:42:02Z jhb $"); | 30__FBSDID("$FreeBSD: head/sys/dev/ppbus/lpbb.c 187576 2009-01-21 23:10:06Z jhb $"); |
31 32/* 33 * I2C Bit-Banging over parallel port 34 * 35 * See the Official Philips interface description in lpbb(4) 36 */ 37 38#include <sys/param.h> --- 59 unchanged lines hidden (view full) --- 98 device_t ppbus = device_get_parent(dev); 99 int error = 0; 100 int how; 101 102 switch (index) { 103 case IIC_REQUEST_BUS: 104 /* request the ppbus */ 105 how = *(int *)data; | 31 32/* 33 * I2C Bit-Banging over parallel port 34 * 35 * See the Official Philips interface description in lpbb(4) 36 */ 37 38#include <sys/param.h> --- 59 unchanged lines hidden (view full) --- 98 device_t ppbus = device_get_parent(dev); 99 int error = 0; 100 int how; 101 102 switch (index) { 103 case IIC_REQUEST_BUS: 104 /* request the ppbus */ 105 how = *(int *)data; |
106 mtx_lock(&Giant); | 106 ppb_lock(ppbus); |
107 error = ppb_request_bus(ppbus, dev, how); | 107 error = ppb_request_bus(ppbus, dev, how); |
108 mtx_unlock(&Giant); | 108 ppb_unlock(ppbus); |
109 break; 110 111 case IIC_RELEASE_BUS: 112 /* release the ppbus */ | 109 break; 110 111 case IIC_RELEASE_BUS: 112 /* release the ppbus */ |
113 mtx_lock(&Giant); | 113 ppb_lock(ppbus); |
114 error = ppb_release_bus(ppbus, dev); | 114 error = ppb_release_bus(ppbus, dev); |
115 mtx_unlock(&Giant); | 115 ppb_unlock(ppbus); |
116 break; 117 118 default: 119 error = EINVAL; 120 } 121 122 return (error); 123} 124 125#define SDA_out 0x80 126#define SCL_out 0x08 127#define SDA_in 0x80 128#define SCL_in 0x08 129#define ALIM 0x20 130#define I2CKEY 0x50 131 | 116 break; 117 118 default: 119 error = EINVAL; 120 } 121 122 return (error); 123} 124 125#define SDA_out 0x80 126#define SCL_out 0x08 127#define SDA_in 0x80 128#define SCL_in 0x08 129#define ALIM 0x20 130#define I2CKEY 0x50 131 |
132/* Reset bus by setting SDA first and then SCL. */ 133static void 134lpbb_reset_bus(device_t dev) 135{ 136 device_t ppbus = device_get_parent(dev); 137 138 ppb_assert_locked(ppbus); 139 ppb_wdtr(ppbus, (u_char)~SDA_out); 140 ppb_wctr(ppbus, (u_char)(ppb_rctr(ppbus) | SCL_out)); 141} 142 |
|
132static int 133lpbb_getscl(device_t dev) 134{ | 143static int 144lpbb_getscl(device_t dev) 145{ |
146 device_t ppbus = device_get_parent(dev); |
|
135 int rval; 136 | 147 int rval; 148 |
137 mtx_lock(&Giant); 138 rval = ((ppb_rstr(device_get_parent(dev)) & SCL_in) == SCL_in); 139 mtx_unlock(&Giant); | 149 ppb_lock(ppbus); 150 rval = ((ppb_rstr(ppbus) & SCL_in) == SCL_in); 151 ppb_unlock(ppbus); |
140 return (rval); 141} 142 143static int 144lpbb_getsda(device_t dev) 145{ | 152 return (rval); 153} 154 155static int 156lpbb_getsda(device_t dev) 157{ |
158 device_t ppbus = device_get_parent(dev); |
|
146 int rval; 147 | 159 int rval; 160 |
148 mtx_lock(&Giant); 149 rval = ((ppb_rstr(device_get_parent(dev)) & SDA_in) == SDA_in); 150 mtx_unlock(&Giant); | 161 ppb_lock(ppbus); 162 rval = ((ppb_rstr(ppbus) & SDA_in) == SDA_in); 163 ppb_unlock(ppbus); |
151 return (rval); 152} 153 154static void 155lpbb_setsda(device_t dev, char val) 156{ 157 device_t ppbus = device_get_parent(dev); 158 | 164 return (rval); 165} 166 167static void 168lpbb_setsda(device_t dev, char val) 169{ 170 device_t ppbus = device_get_parent(dev); 171 |
159 mtx_lock(&Giant); | 172 ppb_lock(ppbus); |
160 if (val == 0) 161 ppb_wdtr(ppbus, (u_char)SDA_out); 162 else 163 ppb_wdtr(ppbus, (u_char)~SDA_out); | 173 if (val == 0) 174 ppb_wdtr(ppbus, (u_char)SDA_out); 175 else 176 ppb_wdtr(ppbus, (u_char)~SDA_out); |
164 mtx_unlock(&Giant); | 177 ppb_unlock(ppbus); |
165} 166 167static void 168lpbb_setscl(device_t dev, unsigned char val) 169{ 170 device_t ppbus = device_get_parent(dev); 171 | 178} 179 180static void 181lpbb_setscl(device_t dev, unsigned char val) 182{ 183 device_t ppbus = device_get_parent(dev); 184 |
172 mtx_lock(&Giant); | 185 ppb_lock(ppbus); |
173 if (val == 0) 174 ppb_wctr(ppbus, (u_char)(ppb_rctr(ppbus) & ~SCL_out)); 175 else 176 ppb_wctr(ppbus, (u_char)(ppb_rctr(ppbus) | SCL_out)); | 186 if (val == 0) 187 ppb_wctr(ppbus, (u_char)(ppb_rctr(ppbus) & ~SCL_out)); 188 else 189 ppb_wctr(ppbus, (u_char)(ppb_rctr(ppbus) | SCL_out)); |
177 mtx_unlock(&Giant); | 190 ppb_unlock(ppbus); |
178} 179 180static int 181lpbb_detect(device_t dev) 182{ 183 device_t ppbus = device_get_parent(dev); 184 | 191} 192 193static int 194lpbb_detect(device_t dev) 195{ 196 device_t ppbus = device_get_parent(dev); 197 |
198 ppb_lock(ppbus); |
|
185 if (ppb_request_bus(ppbus, dev, PPB_DONTWAIT)) { | 199 if (ppb_request_bus(ppbus, dev, PPB_DONTWAIT)) { |
200 ppb_unlock(ppbus); |
|
186 device_printf(dev, "can't allocate ppbus\n"); 187 return (0); 188 } 189 | 201 device_printf(dev, "can't allocate ppbus\n"); 202 return (0); 203 } 204 |
190 /* reset bus */ 191 lpbb_setsda(dev, 1); 192 lpbb_setscl(dev, 1); | 205 lpbb_reset_bus(dev); |
193 194 if ((ppb_rstr(ppbus) & I2CKEY) || 195 ((ppb_rstr(ppbus) & ALIM) != ALIM)) { | 206 207 if ((ppb_rstr(ppbus) & I2CKEY) || 208 ((ppb_rstr(ppbus) & ALIM) != ALIM)) { |
196 | |
197 ppb_release_bus(ppbus, dev); | 209 ppb_release_bus(ppbus, dev); |
210 ppb_unlock(ppbus); |
|
198 return (0); 199 } 200 201 ppb_release_bus(ppbus, dev); | 211 return (0); 212 } 213 214 ppb_release_bus(ppbus, dev); |
215 ppb_unlock(ppbus); |
|
202 203 return (1); 204} 205 206static int 207lpbb_reset(device_t dev, u_char speed, u_char addr, u_char * oldaddr) 208{ 209 device_t ppbus = device_get_parent(dev); 210 | 216 217 return (1); 218} 219 220static int 221lpbb_reset(device_t dev, u_char speed, u_char addr, u_char * oldaddr) 222{ 223 device_t ppbus = device_get_parent(dev); 224 |
211 mtx_lock(&Giant); | 225 ppb_lock(ppbus); |
212 if (ppb_request_bus(ppbus, dev, PPB_DONTWAIT)) { | 226 if (ppb_request_bus(ppbus, dev, PPB_DONTWAIT)) { |
227 ppb_unlock(ppbus); |
|
213 device_printf(dev, "can't allocate ppbus\n"); 214 return (0); 215 } 216 | 228 device_printf(dev, "can't allocate ppbus\n"); 229 return (0); 230 } 231 |
217 /* reset bus */ 218 lpbb_setsda(dev, 1); 219 lpbb_setscl(dev, 1); | 232 lpbb_reset_bus(dev); |
220 221 ppb_release_bus(ppbus, dev); | 233 234 ppb_release_bus(ppbus, dev); |
222 mtx_unlock(&Giant); | 235 ppb_unlock(ppbus); |
223 224 return (IIC_ENOADDR); 225} 226 227static devclass_t lpbb_devclass; 228 229static device_method_t lpbb_methods[] = { 230 /* device interface */ --- 29 unchanged lines hidden --- | 236 237 return (IIC_ENOADDR); 238} 239 240static devclass_t lpbb_devclass; 241 242static device_method_t lpbb_methods[] = { 243 /* device interface */ --- 29 unchanged lines hidden --- |