Wed Dec 7 09:08:00 2011 UTC ()
consolidate bit twiddling functions into one generic case and a bunch of
macros, use them


(macallan)
diff -r1.6 -r1.7 src/sys/dev/pci/voyager.c
diff -r1.3 -r1.4 src/sys/dev/pci/voyagervar.h

cvs diff -r1.6 -r1.7 src/sys/dev/pci/voyager.c (switch to unified diff)

--- src/sys/dev/pci/voyager.c 2011/10/20 22:04:10 1.6
+++ src/sys/dev/pci/voyager.c 2011/12/07 09:08:00 1.7
@@ -1,496 +1,489 @@ @@ -1,496 +1,489 @@
1/* $NetBSD: voyager.c,v 1.6 2011/10/20 22:04:10 macallan Exp $ */ 1/* $NetBSD: voyager.c,v 1.7 2011/12/07 09:08:00 macallan Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 2009, 2011 Michael Lorenz 4 * Copyright (c) 2009, 2011 Michael Lorenz
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * Redistribution and use in source and binary forms, with or without 7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions 8 * modification, are permitted provided that the following conditions
9 * are met: 9 * are met:
10 * 1. Redistributions of source code must retain the above copyright 10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer. 11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright 12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the 13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution. 14 * documentation and/or other materials provided with the distribution.
15 * 15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */ 26 */
27  27
28#include <sys/cdefs.h> 28#include <sys/cdefs.h>
29__KERNEL_RCSID(0, "$NetBSD: voyager.c,v 1.6 2011/10/20 22:04:10 macallan Exp $"); 29__KERNEL_RCSID(0, "$NetBSD: voyager.c,v 1.7 2011/12/07 09:08:00 macallan Exp $");
30 30
31#include <sys/param.h> 31#include <sys/param.h>
32#include <sys/systm.h> 32#include <sys/systm.h>
33#include <sys/kernel.h> 33#include <sys/kernel.h>
34#include <sys/device.h> 34#include <sys/device.h>
35#include <sys/malloc.h> 35#include <sys/malloc.h>
36#include <sys/lwp.h> 36#include <sys/lwp.h>
37#include <sys/kauth.h> 37#include <sys/kauth.h>
38 38
39#include <dev/pci/pcivar.h> 39#include <dev/pci/pcivar.h>
40#include <dev/pci/pcireg.h> 40#include <dev/pci/pcireg.h>
41#include <dev/pci/pcidevs.h> 41#include <dev/pci/pcidevs.h>
42#include <dev/pci/pciio.h> 42#include <dev/pci/pciio.h>
43#include <dev/ic/sm502reg.h> 43#include <dev/ic/sm502reg.h>
44#include <dev/i2c/i2cvar.h> 44#include <dev/i2c/i2cvar.h>
45#include <dev/i2c/i2c_bitbang.h> 45#include <dev/i2c/i2c_bitbang.h>
46 46
47#include <sys/evcnt.h> 47#include <sys/evcnt.h>
48#include <sys/bitops.h> 48#include <sys/bitops.h>
49 49
50#include <dev/pci/voyagervar.h> 50#include <dev/pci/voyagervar.h>
51 51
52#include "opt_voyager.h" 52#include "opt_voyager.h"
53 53
54#ifdef VOYAGER_DEBUG 54#ifdef VOYAGER_DEBUG
55#define DPRINTF aprint_normal 55#define DPRINTF aprint_normal
56#else 56#else
57#define DPRINTF while (0) printf 57#define DPRINTF while (0) printf
58#endif 58#endif
59 59
60/* interrupt stuff */ 60/* interrupt stuff */
61struct voyager_intr { 61struct voyager_intr {
62 int (*vih_func)(void *); 62 int (*vih_func)(void *);
63 void *vih_arg; 63 void *vih_arg;
64 struct evcnt vih_count; 64 struct evcnt vih_count;
65 char vih_name[32]; 65 char vih_name[32];
66}; 66};
67 67
68struct voyager_softc { 68struct voyager_softc {
69 device_t sc_dev; 69 device_t sc_dev;
70 70
71 pci_chipset_tag_t sc_pc; 71 pci_chipset_tag_t sc_pc;
72 pcitag_t sc_pcitag; 72 pcitag_t sc_pcitag;
73 73
74 bus_space_tag_t sc_memt; 74 bus_space_tag_t sc_memt;
75 bus_space_tag_t sc_iot; 75 bus_space_tag_t sc_iot;
76 76
77 bus_space_handle_t sc_fbh, sc_regh; 77 bus_space_handle_t sc_fbh, sc_regh;
78 bus_addr_t sc_fb, sc_reg; 78 bus_addr_t sc_fb, sc_reg;
79 bus_size_t sc_fbsize, sc_regsize; 79 bus_size_t sc_fbsize, sc_regsize;
80 80
81 struct i2c_controller sc_i2c; 81 struct i2c_controller sc_i2c;
82 kmutex_t sc_i2c_lock; 82 kmutex_t sc_i2c_lock;
83 83
84 /* interrupt dispatcher */ 84 /* interrupt dispatcher */
85 void *sc_ih; 85 void *sc_ih;
86 struct voyager_intr sc_intrs[32]; 86 struct voyager_intr sc_intrs[32];
87}; 87};
88 88
89static int voyager_match(device_t, cfdata_t, void *); 89static int voyager_match(device_t, cfdata_t, void *);
90static void voyager_attach(device_t, device_t, void *); 90static void voyager_attach(device_t, device_t, void *);
91static int voyager_print(void *, const char *); 91static int voyager_print(void *, const char *);
92static int voyager_intr(void *); 92static int voyager_intr(void *);
93 93
94CFATTACH_DECL_NEW(voyager, sizeof(struct voyager_softc), 94CFATTACH_DECL_NEW(voyager, sizeof(struct voyager_softc),
95 voyager_match, voyager_attach, NULL, NULL); 95 voyager_match, voyager_attach, NULL, NULL);
96  96
97/* I2C glue */ 97/* I2C glue */
98static int voyager_i2c_acquire_bus(void *, int); 98static int voyager_i2c_acquire_bus(void *, int);
99static void voyager_i2c_release_bus(void *, int); 99static void voyager_i2c_release_bus(void *, int);
100static int voyager_i2c_send_start(void *, int); 100static int voyager_i2c_send_start(void *, int);
101static int voyager_i2c_send_stop(void *, int); 101static int voyager_i2c_send_stop(void *, int);
102static int voyager_i2c_initiate_xfer(void *, i2c_addr_t, int); 102static int voyager_i2c_initiate_xfer(void *, i2c_addr_t, int);
103static int voyager_i2c_read_byte(void *, uint8_t *, int); 103static int voyager_i2c_read_byte(void *, uint8_t *, int);
104static int voyager_i2c_write_byte(void *, uint8_t, int); 104static int voyager_i2c_write_byte(void *, uint8_t, int);
105 105
106/* I2C bitbang glue */ 106/* I2C bitbang glue */
107static void voyager_i2cbb_set_bits(void *, uint32_t); 107static void voyager_i2cbb_set_bits(void *, uint32_t);
108static void voyager_i2cbb_set_dir(void *, uint32_t); 108static void voyager_i2cbb_set_dir(void *, uint32_t);
109static uint32_t voyager_i2cbb_read(void *); 109static uint32_t voyager_i2cbb_read(void *);
110 110
111static const struct i2c_bitbang_ops voyager_i2cbb_ops = { 111static const struct i2c_bitbang_ops voyager_i2cbb_ops = {
112 voyager_i2cbb_set_bits, 112 voyager_i2cbb_set_bits,
113 voyager_i2cbb_set_dir, 113 voyager_i2cbb_set_dir,
114 voyager_i2cbb_read, 114 voyager_i2cbb_read,
115 { 115 {
116 1 << 13, 116 1 << 13,
117 1 << 6, 117 1 << 6,
118 1 << 13, 118 1 << 13,
119 0 119 0
120 } 120 }
121}; 121};
122#define GPIO_I2C_BITS ((1 << 6) | (1 << 13)) 122#define GPIO_I2C_BITS ((1 << 6) | (1 << 13))
123 123
124#ifdef VOYAGER_DEBUG 124#ifdef VOYAGER_DEBUG
125static void voyager_print_pwm(struct voyager_softc *, int); 125static void voyager_print_pwm(struct voyager_softc *, int);
126#endif 126#endif
127 127
128static int 128static int
129voyager_match(device_t parent, cfdata_t match, void *aux) 129voyager_match(device_t parent, cfdata_t match, void *aux)
130{ 130{
131 struct pci_attach_args *pa = (struct pci_attach_args *)aux; 131 struct pci_attach_args *pa = (struct pci_attach_args *)aux;
132 132
133 if (PCI_CLASS(pa->pa_class) != PCI_CLASS_DISPLAY) 133 if (PCI_CLASS(pa->pa_class) != PCI_CLASS_DISPLAY)
134 return 0; 134 return 0;
135 if (PCI_VENDOR(pa->pa_id) != PCI_VENDOR_SILMOTION) 135 if (PCI_VENDOR(pa->pa_id) != PCI_VENDOR_SILMOTION)
136 return 0; 136 return 0;
137 137
138 /* only chip tested on so far - may need a list */ 138 /* only chip tested on so far - may need a list */
139 if (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_SILMOTION_SM502) 139 if (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_SILMOTION_SM502)
140 return 100; 140 return 100;
141 return (0); 141 return (0);
142} 142}
143 143
144static void 144static void
145voyager_attach(device_t parent, device_t self, void *aux) 145voyager_attach(device_t parent, device_t self, void *aux)
146{ 146{
147 struct voyager_softc *sc = device_private(self); 147 struct voyager_softc *sc = device_private(self);
148 struct pci_attach_args *pa = aux; 148 struct pci_attach_args *pa = aux;
149 pci_intr_handle_t ih; 149 pci_intr_handle_t ih;
150 char devinfo[256]; 150 char devinfo[256];
151 struct voyager_attach_args vaa; 151 struct voyager_attach_args vaa;
152 struct i2cbus_attach_args iba; 152 struct i2cbus_attach_args iba;
153 uint32_t reg; 153 uint32_t reg;
154 const char *intrstr; 154 const char *intrstr;
155 int i; 155 int i;
156 156
157 sc->sc_pc = pa->pa_pc; 157 sc->sc_pc = pa->pa_pc;
158 sc->sc_pcitag = pa->pa_tag; 158 sc->sc_pcitag = pa->pa_tag;
159 sc->sc_memt = pa->pa_memt; 159 sc->sc_memt = pa->pa_memt;
160 sc->sc_iot = pa->pa_iot; 160 sc->sc_iot = pa->pa_iot;
161 sc->sc_dev = self; 161 sc->sc_dev = self;
162 162
163 pci_devinfo(pa->pa_id, pa->pa_class, 0, devinfo, sizeof(devinfo)); 163 pci_devinfo(pa->pa_id, pa->pa_class, 0, devinfo, sizeof(devinfo));
164 aprint_normal(": %s\n", devinfo); 164 aprint_normal(": %s\n", devinfo);
165 165
166 if (pci_mapreg_map(pa, 0x14, PCI_MAPREG_TYPE_MEM, 0, 166 if (pci_mapreg_map(pa, 0x14, PCI_MAPREG_TYPE_MEM, 0,
167 &sc->sc_memt, &sc->sc_regh, &sc->sc_reg, &sc->sc_regsize)) { 167 &sc->sc_memt, &sc->sc_regh, &sc->sc_reg, &sc->sc_regsize)) {
168 aprint_error("%s: failed to map registers.\n", 168 aprint_error("%s: failed to map registers.\n",
169 device_xname(sc->sc_dev)); 169 device_xname(sc->sc_dev));
170 } 170 }
171 171
172 if (pci_mapreg_map(pa, 0x10, PCI_MAPREG_TYPE_MEM, 172 if (pci_mapreg_map(pa, 0x10, PCI_MAPREG_TYPE_MEM,
173 BUS_SPACE_MAP_LINEAR, 173 BUS_SPACE_MAP_LINEAR,
174 &sc->sc_memt, &sc->sc_fbh, &sc->sc_fb, &sc->sc_fbsize)) { 174 &sc->sc_memt, &sc->sc_fbh, &sc->sc_fb, &sc->sc_fbsize)) {
175 aprint_error("%s: failed to map the frame buffer.\n", 175 aprint_error("%s: failed to map the frame buffer.\n",
176 device_xname(sc->sc_dev)); 176 device_xname(sc->sc_dev));
177 } 177 }
178 178
179 /* disable all interrupts */ 179 /* disable all interrupts */
180 bus_space_write_4(sc->sc_memt, sc->sc_regh, SM502_INTR_MASK, 0); 180 bus_space_write_4(sc->sc_memt, sc->sc_regh, SM502_INTR_MASK, 0);
181  181
182 /* initialize handler list */ 182 /* initialize handler list */
183 for (i = 0; i < 32; i++) { 183 for (i = 0; i < 32; i++) {
184 sc->sc_intrs[i].vih_func = NULL; 184 sc->sc_intrs[i].vih_func = NULL;
185 snprintf(sc->sc_intrs[i].vih_name, 32, "int %d", i); 185 snprintf(sc->sc_intrs[i].vih_name, 32, "int %d", i);
186 evcnt_attach_dynamic(&sc->sc_intrs[i].vih_count, 186 evcnt_attach_dynamic(&sc->sc_intrs[i].vih_count,
187 EVCNT_TYPE_INTR, NULL, "voyager", sc->sc_intrs[i].vih_name); 187 EVCNT_TYPE_INTR, NULL, "voyager", sc->sc_intrs[i].vih_name);
188 } 188 }
189 189
190 /* Map and establish the interrupt. */ 190 /* Map and establish the interrupt. */
191 if (pci_intr_map(pa, &ih)) { 191 if (pci_intr_map(pa, &ih)) {
192 aprint_error_dev(self, "couldn't map interrupt\n"); 192 aprint_error_dev(self, "couldn't map interrupt\n");
193 return; 193 return;
194 } 194 }
195 195
196 intrstr = pci_intr_string(sc->sc_pc, ih); 196 intrstr = pci_intr_string(sc->sc_pc, ih);
197 sc->sc_ih = pci_intr_establish(sc->sc_pc, ih, IPL_AUDIO, voyager_intr, sc); 197 sc->sc_ih = pci_intr_establish(sc->sc_pc, ih, IPL_AUDIO, voyager_intr, sc);
198 if (sc->sc_ih == NULL) { 198 if (sc->sc_ih == NULL) {
199 aprint_error_dev(self, "couldn't establish interrupt"); 199 aprint_error_dev(self, "couldn't establish interrupt");
200 if (intrstr != NULL) 200 if (intrstr != NULL)
201 aprint_error(" at %s", intrstr); 201 aprint_error(" at %s", intrstr);
202 aprint_error("\n"); 202 aprint_error("\n");
203 return; 203 return;
204 } 204 }
205 aprint_normal_dev(self, "interrupting at %s\n", intrstr); 205 aprint_normal_dev(self, "interrupting at %s\n", intrstr);
206 206
207#ifdef VOYAGER_DEBUG 207#ifdef VOYAGER_DEBUG
208 voyager_print_pwm(sc, SM502_PWM0); 208 voyager_print_pwm(sc, SM502_PWM0);
209 voyager_print_pwm(sc, SM502_PWM1); 209 voyager_print_pwm(sc, SM502_PWM1);
210 voyager_print_pwm(sc, SM502_PWM2); 210 voyager_print_pwm(sc, SM502_PWM2);
211#endif 211#endif
212 212
213 /* attach the framebuffer driver */ 213 /* attach the framebuffer driver */
214 vaa.vaa_memh = sc->sc_fbh; 214 vaa.vaa_memh = sc->sc_fbh;
215 vaa.vaa_mem_pa = sc->sc_fb; 215 vaa.vaa_mem_pa = sc->sc_fb;
216 vaa.vaa_regh = sc->sc_regh; 216 vaa.vaa_regh = sc->sc_regh;
217 vaa.vaa_reg_pa = sc->sc_reg; 217 vaa.vaa_reg_pa = sc->sc_reg;
218 vaa.vaa_tag = sc->sc_memt; 218 vaa.vaa_tag = sc->sc_memt;
219 vaa.vaa_pc = sc->sc_pc; 219 vaa.vaa_pc = sc->sc_pc;
220 vaa.vaa_pcitag = sc->sc_pcitag; 220 vaa.vaa_pcitag = sc->sc_pcitag;
221 strcpy(vaa.vaa_name, "voyagerfb"); 221 strcpy(vaa.vaa_name, "voyagerfb");
222 config_found_ia(sc->sc_dev, "voyagerbus", &vaa, voyager_print); 222 config_found_ia(sc->sc_dev, "voyagerbus", &vaa, voyager_print);
223 strcpy(vaa.vaa_name, "pwmclock"); 223 strcpy(vaa.vaa_name, "pwmclock");
224 config_found_ia(sc->sc_dev, "voyagerbus", &vaa, voyager_print); 224 config_found_ia(sc->sc_dev, "voyagerbus", &vaa, voyager_print);
 225 strcpy(vaa.vaa_name, "vac");
 226 config_found_ia(sc->sc_dev, "voyagerbus", &vaa, voyager_print);
 227
 228 /* we use this mutex wether there's an i2c bus or not */
 229 mutex_init(&sc->sc_i2c_lock, MUTEX_DEFAULT, IPL_NONE);
225 230
 231 /*
 232 * see if the i2c pins are configured as gpio and if so, use them
 233 * should probably be a compile time option
 234 */
226 reg = bus_space_read_4(sc->sc_memt, sc->sc_regh, SM502_GPIO0_CONTROL); 235 reg = bus_space_read_4(sc->sc_memt, sc->sc_regh, SM502_GPIO0_CONTROL);
227 if ((reg & GPIO_I2C_BITS) == 0) { 236 if ((reg & GPIO_I2C_BITS) == 0) {
228 /* both bits as outputs */ 237 /* both bits as outputs */
229 reg = bus_space_read_4(sc->sc_memt, sc->sc_regh, SM502_GPIO_DIR0); 238 voyager_gpio_dir(sc, 0xffffffff, GPIO_I2C_BITS);
230 reg |= GPIO_I2C_BITS; 
231 bus_space_write_4(sc->sc_memt, sc->sc_regh, SM502_GPIO_DIR0, reg); 
232  239
233 /* Fill in the i2c tag */ 240 /* Fill in the i2c tag */
234 sc->sc_i2c.ic_cookie = sc; 241 sc->sc_i2c.ic_cookie = sc;
235 sc->sc_i2c.ic_acquire_bus = voyager_i2c_acquire_bus; 242 sc->sc_i2c.ic_acquire_bus = voyager_i2c_acquire_bus;
236 sc->sc_i2c.ic_release_bus = voyager_i2c_release_bus; 243 sc->sc_i2c.ic_release_bus = voyager_i2c_release_bus;
237 sc->sc_i2c.ic_send_start = voyager_i2c_send_start; 244 sc->sc_i2c.ic_send_start = voyager_i2c_send_start;
238 sc->sc_i2c.ic_send_stop = voyager_i2c_send_stop; 245 sc->sc_i2c.ic_send_stop = voyager_i2c_send_stop;
239 sc->sc_i2c.ic_initiate_xfer = voyager_i2c_initiate_xfer; 246 sc->sc_i2c.ic_initiate_xfer = voyager_i2c_initiate_xfer;
240 sc->sc_i2c.ic_read_byte = voyager_i2c_read_byte; 247 sc->sc_i2c.ic_read_byte = voyager_i2c_read_byte;
241 sc->sc_i2c.ic_write_byte = voyager_i2c_write_byte; 248 sc->sc_i2c.ic_write_byte = voyager_i2c_write_byte;
242 sc->sc_i2c.ic_exec = NULL; 249 sc->sc_i2c.ic_exec = NULL;
243 mutex_init(&sc->sc_i2c_lock, MUTEX_DEFAULT, IPL_NONE); 
244 iba.iba_tag = &sc->sc_i2c; 250 iba.iba_tag = &sc->sc_i2c;
245 config_found_ia(self, "i2cbus", &iba, iicbus_print); 251 config_found_ia(self, "i2cbus", &iba, iicbus_print);
246 } 252 }
 253 voyager_control_gpio(sc, ~(1 << 16), 0);
 254 voyager_gpio_dir(sc, 0xffffffff, 1 << 16);
 255 voyager_write_gpio(sc, 0xffffffff, 1 << 16);
247} 256}
248 257
249static int 258static int
250voyager_print(void *aux, const char *what) 259voyager_print(void *aux, const char *what)
251{ 260{
252 /*struct voyager_attach_args *vaa = aux;*/ 261 /*struct voyager_attach_args *vaa = aux;*/
253 262
254 if (what == NULL) 263 if (what == NULL)
255 return 0; 264 return 0;
256 265
257 printf("%s:", what); 266 printf("%s:", what);
258 267
259 return 0; 268 return 0;
260} 269}
261 270
262static void 271static void
263voyager_i2cbb_set_bits(void *cookie, uint32_t bits) 272voyager_i2cbb_set_bits(void *cookie, uint32_t bits)
264{ 273{
265 struct voyager_softc *sc = cookie; 274 struct voyager_softc *sc = cookie;
266 uint32_t reg; 275 uint32_t reg;
267 276
268 reg = bus_space_read_4(sc->sc_memt, sc->sc_regh, SM502_GPIO_DATA0); 277 reg = bus_space_read_4(sc->sc_memt, sc->sc_regh, SM502_GPIO_DATA0);
269 reg &= ~GPIO_I2C_BITS; 278 reg &= ~GPIO_I2C_BITS;
270 reg |= bits; 279 reg |= bits;
271 bus_space_write_4(sc->sc_memt, sc->sc_regh, SM502_GPIO_DATA0, reg); 280 bus_space_write_4(sc->sc_memt, sc->sc_regh, SM502_GPIO_DATA0, reg);
272} 281}
273 282
274static void 283static void
275voyager_i2cbb_set_dir(void *cookie, uint32_t bits) 284voyager_i2cbb_set_dir(void *cookie, uint32_t bits)
276{ 285{
277 struct voyager_softc *sc = cookie; 286 struct voyager_softc *sc = cookie;
278 uint32_t reg; 287 uint32_t reg;
279 288
280 reg = bus_space_read_4(sc->sc_memt, sc->sc_regh, SM502_GPIO_DIR0); 289 reg = bus_space_read_4(sc->sc_memt, sc->sc_regh, SM502_GPIO_DIR0);
281 reg &= ~(1 << 13); 290 reg &= ~(1 << 13);
282 reg |= bits; 291 reg |= bits;
283 bus_space_write_4(sc->sc_memt, sc->sc_regh, SM502_GPIO_DIR0, reg); 292 bus_space_write_4(sc->sc_memt, sc->sc_regh, SM502_GPIO_DIR0, reg);
284} 293}
285 294
286static uint32_t 295static uint32_t
287voyager_i2cbb_read(void *cookie) 296voyager_i2cbb_read(void *cookie)
288{ 297{
289 struct voyager_softc *sc = cookie; 298 struct voyager_softc *sc = cookie;
290 uint32_t reg; 299 uint32_t reg;
291 300
292 reg = bus_space_read_4(sc->sc_memt, sc->sc_regh, SM502_GPIO_DATA0); 301 reg = bus_space_read_4(sc->sc_memt, sc->sc_regh, SM502_GPIO_DATA0);
293 return reg; 302 return reg;
294} 303}
295 304
296/* higher level I2C stuff */ 305/* higher level I2C stuff */
297static int 306static int
298voyager_i2c_acquire_bus(void *cookie, int flags) 307voyager_i2c_acquire_bus(void *cookie, int flags)
299{ 308{
300 struct voyager_softc *sc = cookie; 309 struct voyager_softc *sc = cookie;
301 310
302 mutex_enter(&sc->sc_i2c_lock); 311 mutex_enter(&sc->sc_i2c_lock);
303 return 0; 312 return 0;
304} 313}
305 314
306static void 315static void
307voyager_i2c_release_bus(void *cookie, int flags) 316voyager_i2c_release_bus(void *cookie, int flags)
308{ 317{
309 struct voyager_softc *sc = cookie; 318 struct voyager_softc *sc = cookie;
310 319
311 mutex_exit(&sc->sc_i2c_lock); 320 mutex_exit(&sc->sc_i2c_lock);
312} 321}
313 322
314static int 323static int
315voyager_i2c_send_start(void *cookie, int flags) 324voyager_i2c_send_start(void *cookie, int flags)
316{ 325{
317 return (i2c_bitbang_send_start(cookie, flags, &voyager_i2cbb_ops)); 326 return (i2c_bitbang_send_start(cookie, flags, &voyager_i2cbb_ops));
318} 327}
319 328
320static int 329static int
321voyager_i2c_send_stop(void *cookie, int flags) 330voyager_i2c_send_stop(void *cookie, int flags)
322{ 331{
323 332
324 return (i2c_bitbang_send_stop(cookie, flags, &voyager_i2cbb_ops)); 333 return (i2c_bitbang_send_stop(cookie, flags, &voyager_i2cbb_ops));
325} 334}
326 335
327static int 336static int
328voyager_i2c_initiate_xfer(void *cookie, i2c_addr_t addr, int flags) 337voyager_i2c_initiate_xfer(void *cookie, i2c_addr_t addr, int flags)
329{ 338{
330 /* 339 /*
331 * for some reason i2c_bitbang_initiate_xfer left-shifts 340 * for some reason i2c_bitbang_initiate_xfer left-shifts
332 * the I2C-address and then sets the direction bit 341 * the I2C-address and then sets the direction bit
333 */ 342 */
334 return (i2c_bitbang_initiate_xfer(cookie, addr, flags,  343 return (i2c_bitbang_initiate_xfer(cookie, addr, flags,
335 &voyager_i2cbb_ops)); 344 &voyager_i2cbb_ops));
336} 345}
337 346
338static int 347static int
339voyager_i2c_read_byte(void *cookie, uint8_t *valp, int flags) 348voyager_i2c_read_byte(void *cookie, uint8_t *valp, int flags)
340{ 349{
341 int ret; 350 int ret;
342 351
343 ret = i2c_bitbang_read_byte(cookie, valp, flags, &voyager_i2cbb_ops); 352 ret = i2c_bitbang_read_byte(cookie, valp, flags, &voyager_i2cbb_ops);
344 return ret; 353 return ret;
345} 354}
346 355
347static int 356static int
348voyager_i2c_write_byte(void *cookie, uint8_t val, int flags) 357voyager_i2c_write_byte(void *cookie, uint8_t val, int flags)
349{ 358{
350 int ret; 359 int ret;
351 360
352 ret = i2c_bitbang_write_byte(cookie, val, flags, &voyager_i2cbb_ops); 361 ret = i2c_bitbang_write_byte(cookie, val, flags, &voyager_i2cbb_ops);
353 delay(500); 362 delay(500);
354 return ret; 363 return ret;
355} 364}
356 365
357/* gpio stuff */ 
358void 366void
359voyager_write_gpio(void *cookie, uint32_t mask, uint32_t bits) 367voyager_twiddle_bits(void *cookie, int regnum, uint32_t mask, uint32_t bits)
360{ 368{
361 struct voyager_softc *sc = cookie; 369 struct voyager_softc *sc = cookie;
362 uint32_t reg; 370 uint32_t reg;
363 371
364 /* don't interfere with i2c ops */ 372 /* don't interfere with i2c ops */
365 mutex_enter(&sc->sc_i2c_lock); 373 mutex_enter(&sc->sc_i2c_lock);
366 reg = bus_space_read_4(sc->sc_memt, sc->sc_regh, SM502_GPIO_DATA0); 374 reg = bus_space_read_4(sc->sc_memt, sc->sc_regh, regnum);
367 reg &= mask; 
368 reg |= bits; 
369 bus_space_write_4(sc->sc_memt, sc->sc_regh, SM502_GPIO_DATA0, reg); 
370 mutex_exit(&sc->sc_i2c_lock); 
371} 
372 
373void 
374voyager_control_gpio(void *cookie, uint32_t mask, uint32_t bits) 
375{ 
376 struct voyager_softc *sc = cookie; 
377 uint32_t reg; 
378 
379 /* don't interfere with i2c ops */ 
380 mutex_enter(&sc->sc_i2c_lock); 
381 reg = bus_space_read_4(sc->sc_memt, sc->sc_regh, SM502_GPIO0_CONTROL); 
382 reg &= mask; 375 reg &= mask;
383 reg |= bits; 376 reg |= bits;
384 bus_space_write_4(sc->sc_memt, sc->sc_regh, SM502_GPIO0_CONTROL, reg); 377 bus_space_write_4(sc->sc_memt, sc->sc_regh, regnum, reg);
385 mutex_exit(&sc->sc_i2c_lock); 378 mutex_exit(&sc->sc_i2c_lock);
386} 379}
387 380
388static int 381static int
389voyager_intr(void *cookie) 382voyager_intr(void *cookie)
390{ 383{
391 struct voyager_softc *sc = cookie; 384 struct voyager_softc *sc = cookie;
392 struct voyager_intr *ih; 385 struct voyager_intr *ih;
393 uint32_t intrs; 386 uint32_t intrs;
394 uint32_t mask, bit; 387 uint32_t mask, bit;
395 int num; 388 int num;
396 389
397 intrs = bus_space_read_4(sc->sc_memt, sc->sc_regh, SM502_INTR_STATUS); 390 intrs = bus_space_read_4(sc->sc_memt, sc->sc_regh, SM502_INTR_STATUS);
398 mask = bus_space_read_4(sc->sc_memt, sc->sc_regh, SM502_INTR_MASK); 391 mask = bus_space_read_4(sc->sc_memt, sc->sc_regh, SM502_INTR_MASK);
399 intrs &= mask; 392 intrs &= mask;
400 393
401 while (intrs != 0) { 394 while (intrs != 0) {
402 num = ffs32(intrs) - 1; 395 num = ffs32(intrs) - 1;
403 bit = 1 << num; 396 bit = 1 << num;
404 intrs &= ~bit; 397 intrs &= ~bit;
405 ih = &sc->sc_intrs[num]; 398 ih = &sc->sc_intrs[num];
406 if (ih->vih_func != NULL) { 399 if (ih->vih_func != NULL) {
407 ih->vih_func(ih->vih_arg); 400 ih->vih_func(ih->vih_arg);
408 } 401 }
409 ih->vih_count.ev_count++; 402 ih->vih_count.ev_count++;
410 } 403 }
411 return 0; 404 return 0;
412}  405}
413 406
414void * 407void *
415voyager_establish_intr(device_t dev, int bit, int (*handler)(void *), void *arg) 408voyager_establish_intr(device_t dev, int bit, int (*handler)(void *), void *arg)
416{ 409{
417 struct voyager_softc *sc = device_private(dev); 410 struct voyager_softc *sc = device_private(dev);
418 struct voyager_intr *ih; 411 struct voyager_intr *ih;
419 uint32_t reg; 412 uint32_t reg;
420 413
421 if ((bit < 0) || (bit > 31)) { 414 if ((bit < 0) || (bit > 31)) {
422 aprint_error_dev(dev, "bogus interrupt %d\n", bit); 415 aprint_error_dev(dev, "bogus interrupt %d\n", bit);
423 return NULL; 416 return NULL;
424 } 417 }
425 418
426 ih = &sc->sc_intrs[bit]; 419 ih = &sc->sc_intrs[bit];
427 if (ih->vih_func != NULL) { 420 if (ih->vih_func != NULL) {
428 aprint_error_dev(dev, "interrupt %d is already in use\n", bit); 421 aprint_error_dev(dev, "interrupt %d is already in use\n", bit);
429 return NULL; 422 return NULL;
430 } 423 }
431 ih->vih_func = handler; 424 ih->vih_func = handler;
432 ih->vih_arg = arg; 425 ih->vih_arg = arg;
433 reg = bus_space_read_4(sc->sc_memt, sc->sc_regh, SM502_INTR_MASK); 426 reg = bus_space_read_4(sc->sc_memt, sc->sc_regh, SM502_INTR_MASK);
434 reg |= 1 << bit; 427 reg |= 1 << bit;
435 bus_space_write_4(sc->sc_memt, sc->sc_regh, SM502_INTR_MASK, reg); 428 bus_space_write_4(sc->sc_memt, sc->sc_regh, SM502_INTR_MASK, reg);
436  429
437 return (void *)(uintptr_t)(0x80000000 | bit); 430 return (void *)(uintptr_t)(0x80000000 | bit);
438} 431}
439 432
440void 433void
441voyager_disestablish_intr(device_t dev, void *ih) 434voyager_disestablish_intr(device_t dev, void *ih)
442{ 435{
443} 436}
444 437
445/* timer */ 438/* timer */
446#ifdef VOYAGER_DEBUG 439#ifdef VOYAGER_DEBUG
447static void 440static void
448voyager_print_pwm(struct voyager_softc *sc, int pwmreg) 441voyager_print_pwm(struct voyager_softc *sc, int pwmreg)
449{ 442{
450 uint32_t reg; 443 uint32_t reg;
451 444
452 reg = bus_space_read_4(sc->sc_memt, sc->sc_regh, pwmreg); 445 reg = bus_space_read_4(sc->sc_memt, sc->sc_regh, pwmreg);
453 aprint_debug_dev(sc->sc_dev, "%08x: %08x = %d Hz, %d high, %d low\n",  446 aprint_debug_dev(sc->sc_dev, "%08x: %08x = %d Hz, %d high, %d low\n",
454 pwmreg, reg, 447 pwmreg, reg,
455 96000000 / (1 << ((reg & SM502_PWM_CLOCK_DIV_MASK) >> SM502_PWM_CLOCK_DIV_SHIFT)), 448 96000000 / (1 << ((reg & SM502_PWM_CLOCK_DIV_MASK) >> SM502_PWM_CLOCK_DIV_SHIFT)),
456 (reg & SM502_PWM_CLOCK_HIGH_MASK) >> SM502_PWM_CLOCK_HIGH_SHIFT, 449 (reg & SM502_PWM_CLOCK_HIGH_MASK) >> SM502_PWM_CLOCK_HIGH_SHIFT,
457 (reg & SM502_PWM_CLOCK_LOW_MASK) >> SM502_PWM_CLOCK_LOW_SHIFT); 450 (reg & SM502_PWM_CLOCK_LOW_MASK) >> SM502_PWM_CLOCK_LOW_SHIFT);
458} 451}
459#endif 452#endif
460 453
461uint32_t 454uint32_t
462voyager_set_pwm(int freq, int duty_cycle) 455voyager_set_pwm(int freq, int duty_cycle)
463{ 456{
464 int ifreq, factor, bit, steps; 457 int ifreq, factor, bit, steps;
465 uint32_t reg = 0, hi, lo; 458 uint32_t reg = 0, hi, lo;
466 459
467 /* 460 /*
468 * find the smallest divider that gets us within 4096 steps of the 461 * find the smallest divider that gets us within 4096 steps of the
469 * target frequency 462 * target frequency
470 */ 463 */
471 ifreq = freq * 4096; 464 ifreq = freq * 4096;
472 factor = 96000000 / ifreq; 465 factor = 96000000 / ifreq;
473 bit = fls32(factor); 466 bit = fls32(factor);
474 factor = 1 << bit; 467 factor = 1 << bit;
475 steps = 96000000 / (factor * freq); 468 steps = 96000000 / (factor * freq);
476 /* can't have it all off */ 469 /* can't have it all off */
477 if (duty_cycle < 1) 470 if (duty_cycle < 1)
478 duty_cycle = 1; 471 duty_cycle = 1;
479 /* can't be always on either */ 472 /* can't be always on either */
480 if (duty_cycle > 999) 473 if (duty_cycle > 999)
481 duty_cycle = 999; 474 duty_cycle = 999;
482 hi = steps * duty_cycle / 1000; 475 hi = steps * duty_cycle / 1000;
483 if (hi < 1) 476 if (hi < 1)
484 hi = 1; 477 hi = 1;
485 lo = steps - hi; 478 lo = steps - hi;
486 if (lo < 1) { 479 if (lo < 1) {
487 hi = steps - 1; 480 hi = steps - 1;
488 lo = 1; 481 lo = 1;
489 } 482 }
490 DPRINTF("%d hz -> %d, %d, %d / %d\n", freq, factor, steps, lo, hi); 483 DPRINTF("%d hz -> %d, %d, %d / %d\n", freq, factor, steps, lo, hi);
491 reg = ((hi - 1) & 0xfff) << SM502_PWM_CLOCK_HIGH_SHIFT; 484 reg = ((hi - 1) & 0xfff) << SM502_PWM_CLOCK_HIGH_SHIFT;
492 reg |= ((lo - 1) & 0xfff) << SM502_PWM_CLOCK_LOW_SHIFT; 485 reg |= ((lo - 1) & 0xfff) << SM502_PWM_CLOCK_LOW_SHIFT;
493 reg |= (bit & 0xf) << SM502_PWM_CLOCK_DIV_SHIFT; 486 reg |= (bit & 0xf) << SM502_PWM_CLOCK_DIV_SHIFT;
494 DPRINTF("reg: %08x\n", reg); 487 DPRINTF("reg: %08x\n", reg);
495 return reg; 488 return reg;
496} 489}

cvs diff -r1.3 -r1.4 src/sys/dev/pci/voyagervar.h (switch to unified diff)

--- src/sys/dev/pci/voyagervar.h 2011/10/18 17:57:40 1.3
+++ src/sys/dev/pci/voyagervar.h 2011/12/07 09:08:00 1.4
@@ -1,59 +1,68 @@ @@ -1,59 +1,68 @@
1/* $NetBSD: voyagervar.h,v 1.3 2011/10/18 17:57:40 macallan Exp $ */ 1/* $NetBSD: voyagervar.h,v 1.4 2011/12/07 09:08:00 macallan Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 2011 Michael Lorenz 4 * Copyright (c) 2011 Michael Lorenz
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * Redistribution and use in source and binary forms, with or without 7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions 8 * modification, are permitted provided that the following conditions
9 * are met: 9 * are met:
10 * 1. Redistributions of source code must retain the above copyright 10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer. 11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright 12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the 13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution. 14 * documentation and/or other materials provided with the distribution.
15 * 15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */ 26 */
27 27
28#include <sys/cdefs.h> 28#include <sys/cdefs.h>
29__KERNEL_RCSID(0, "$NetBSD: voyagervar.h,v 1.3 2011/10/18 17:57:40 macallan Exp $"); 29__KERNEL_RCSID(0, "$NetBSD: voyagervar.h,v 1.4 2011/12/07 09:08:00 macallan Exp $");
30 30
31#ifndef VOYAGERVAR_H 31#ifndef VOYAGERVAR_H
32#define VOYAGERVAR_H 32#define VOYAGERVAR_H
33 33
34#include <dev/pci/pcivar.h> 34#include <dev/pci/pcivar.h>
35#include <dev/pci/pcireg.h> 35#include <dev/pci/pcireg.h>
36 36
37struct voyager_attach_args { 37struct voyager_attach_args {
38 pci_chipset_tag_t vaa_pc; 38 pci_chipset_tag_t vaa_pc;
39 pcitag_t vaa_pcitag; 39 pcitag_t vaa_pcitag;
40 bus_space_tag_t vaa_tag; 40 bus_space_tag_t vaa_tag;
41 bus_space_handle_t vaa_regh; 41 bus_space_handle_t vaa_regh;
42 bus_space_handle_t vaa_memh; 42 bus_space_handle_t vaa_memh;
43 bus_addr_t vaa_reg_pa; 43 bus_addr_t vaa_reg_pa;
44 bus_addr_t vaa_mem_pa; 44 bus_addr_t vaa_mem_pa;
45 char vaa_name[32]; 45 char vaa_name[32];
46}; 46};
47 47
 48void voyager_twiddle_bits(void *, int, uint32_t, uint32_t);
 49
48/* set gpio bits - (register & param1) | param2 */ 50/* set gpio bits - (register & param1) | param2 */
49void voyager_write_gpio(void *, uint32_t, uint32_t); 51#define voyager_write_gpio(cookie, m_and, m_or) \
 52 voyager_twiddle_bits(cookie, SM502_GPIO_DATA0, m_and, m_or)
50/* control gpio pin usage - 0 is gpio, 1 is other stuff ( like PWM ) */ 53/* control gpio pin usage - 0 is gpio, 1 is other stuff ( like PWM ) */
51void voyager_control_gpio(void *, uint32_t, uint32_t); 54#define voyager_control_gpio(cookie, m_and, m_or) \
 55 voyager_twiddle_bits(cookie, SM502_GPIO0_CONTROL, m_and, m_or)
 56/* gpio direction - 1 is output */
 57#define voyager_gpio_dir(cookie, m_and, m_or) \
 58 voyager_twiddle_bits(cookie, SM502_GPIO_DIR0, m_and, m_or)
 59#define voyager_control_power_0(cookie, m_and, m_or) \
 60 voyager_twiddle_bits(cookie, SM502_POWER_MODE0_GATE, m_and, m_or)
52 61
53void *voyager_establish_intr(device_t, int, int (*)(void *), void *); 62void *voyager_establish_intr(device_t, int, int (*)(void *), void *);
54void voyager_disestablish_intr(device_t, void *); 63void voyager_disestablish_intr(device_t, void *);
55 64
56/* frequency in Hz, duty cycle in 1000ths */ 65/* frequency in Hz, duty cycle in 1000ths */
57uint32_t voyager_set_pwm(int, int); 66uint32_t voyager_set_pwm(int, int);
58 67
59#endif 68#endif