Tue Dec 13 14:46:07 2011 UTC ()
define and use PWMCLOCK_DEBUG


(macallan)
diff -r1.2 -r1.3 src/sys/dev/pci/voyager/files.voyager
diff -r1.1 -r1.2 src/sys/dev/pci/voyager/pwmclock.c

cvs diff -r1.2 -r1.3 src/sys/dev/pci/voyager/files.voyager (switch to unified diff)

--- src/sys/dev/pci/voyager/files.voyager 2011/12/13 14:39:37 1.2
+++ src/sys/dev/pci/voyager/files.voyager 2011/12/13 14:46:07 1.3
@@ -1,19 +1,20 @@ @@ -1,19 +1,20 @@
1# Silicon Motion SM502 / Voyager GX 1# Silicon Motion SM502 / Voyager GX
2 2
3define voyagerbus {} 3define voyagerbus {}
4 4
5# the graphics part 5# the graphics part
6device voyagerfb: wsemuldisplaydev, rasops8, rasops16, vcons, videomode, iic, i2c_bitbang 6device voyagerfb: wsemuldisplaydev, rasops8, rasops16, vcons, videomode, iic, i2c_bitbang
7attach voyagerfb at voyagerbus 7attach voyagerfb at voyagerbus
8file dev/pci/voyager/voyagerfb.c voyagerfb needs-flag 8file dev/pci/voyager/voyagerfb.c voyagerfb needs-flag
9defflag opt_voyagerfb.h VOYAGERFB_DEBUG 9defflag opt_voyagerfb.h VOYAGERFB_DEBUG
10 10
11# a clock timer 11# a clock timer
 12defflag opt_pwmclock.h PWMCLOCK_DEBUG
12device pwmclock 13device pwmclock
13attach pwmclock at voyagerbus 14attach pwmclock at voyagerbus
14file dev/pci/voyager/pwmclock.c pwmclock needs-flag 15file dev/pci/voyager/pwmclock.c pwmclock needs-flag
15 16
16# the audio part 17# the audio part
17device vac: audiobus, auconv, mulaw 18device vac: audiobus, auconv, mulaw
18attach vac at voyagerbus 19attach vac at voyagerbus
19file dev/pci/voyager/vac.c vac needs-flag 20file dev/pci/voyager/vac.c vac needs-flag

cvs diff -r1.1 -r1.2 src/sys/dev/pci/voyager/pwmclock.c (switch to unified diff)

--- src/sys/dev/pci/voyager/pwmclock.c 2011/12/13 14:39:37 1.1
+++ src/sys/dev/pci/voyager/pwmclock.c 2011/12/13 14:46:07 1.2
@@ -1,355 +1,359 @@ @@ -1,355 +1,359 @@
1/* $NetBSD: pwmclock.c,v 1.1 2011/12/13 14:39:37 macallan Exp $ */ 1/* $NetBSD: pwmclock.c,v 1.2 2011/12/13 14:46:07 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: pwmclock.c,v 1.1 2011/12/13 14:39:37 macallan Exp $"); 29__KERNEL_RCSID(0, "$NetBSD: pwmclock.c,v 1.2 2011/12/13 14:46:07 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/cpu.h> 35#include <sys/cpu.h>
36#include <sys/timetc.h> 36#include <sys/timetc.h>
37#include <sys/sysctl.h> 37#include <sys/sysctl.h>
38 38
39#include <dev/pci/voyagervar.h> 39#include <dev/pci/voyagervar.h>
40#include <dev/ic/sm502reg.h> 40#include <dev/ic/sm502reg.h>
41 41
42#include <mips/mips3_clock.h> 42#include <mips/mips3_clock.h>
43#include <mips/locore.h> 43#include <mips/locore.h>
44#include <mips/bonito/bonitoreg.h> 44#include <mips/bonito/bonitoreg.h>
45#include <mips/bonito/bonitovar.h> 45#include <mips/bonito/bonitovar.h>
46 46
 47#include "opt_pwmclock.h"
 48
47#ifdef PWMCLOCK_DEBUG 49#ifdef PWMCLOCK_DEBUG
48#define DPRINTF aprint_error 50#define DPRINTF aprint_error
49#else 51#else
50#define DPRINTF while (0) printf 52#define DPRINTF while (0) printf
51#endif 53#endif
52 54
53int pwmclock_intr(void *); 55int pwmclock_intr(void *);
54 56
55struct pwmclock_softc { 57struct pwmclock_softc {
56 device_t sc_dev; 58 device_t sc_dev;
57 bus_space_tag_t sc_memt; 59 bus_space_tag_t sc_memt;
58 bus_space_handle_t sc_regh; 60 bus_space_handle_t sc_regh;
59 uint32_t sc_reg, sc_last; 61 uint32_t sc_reg, sc_last;
60 uint32_t sc_scale[8]; 62 uint32_t sc_scale[8];
61 uint32_t sc_count; /* should probably be 64 bit */ 63 uint32_t sc_count; /* should probably be 64 bit */
62 int sc_step; 64 int sc_step;
63 int sc_step_wanted; 65 int sc_step_wanted;
64}; 66};
65 67
66static int pwmclock_match(device_t, cfdata_t, void *); 68static int pwmclock_match(device_t, cfdata_t, void *);
67static void pwmclock_attach(device_t, device_t, void *); 69static void pwmclock_attach(device_t, device_t, void *);
68 70
69CFATTACH_DECL_NEW(pwmclock, sizeof(struct pwmclock_softc), 71CFATTACH_DECL_NEW(pwmclock, sizeof(struct pwmclock_softc),
70 pwmclock_match, pwmclock_attach, NULL, NULL); 72 pwmclock_match, pwmclock_attach, NULL, NULL);
71 73
72static void pwmclock_start(void); 74static void pwmclock_start(void);
73static u_int get_pwmclock_timecount(struct timecounter *); 75static u_int get_pwmclock_timecount(struct timecounter *);
74 76
75struct pwmclock_softc *pwmclock; 77struct pwmclock_softc *pwmclock;
76extern void (*initclocks_ptr)(void); 78extern void (*initclocks_ptr)(void);
77extern struct clockframe cf; 79extern struct clockframe cf;
78 80
79/* 0, 1/4, 3/8, 1/2, 5/8, 3/4, 7/8, 1 */ 81/* 0, 1/4, 3/8, 1/2, 5/8, 3/4, 7/8, 1 */
80static int scale_m[] = {1, 1, 3, 1, 5, 3, 7, 1}; 82static int scale_m[] = {1, 1, 3, 1, 5, 3, 7, 1};
81static int scale_d[] = {0, 4, 8, 2, 8, 4, 8, 1}; 83static int scale_d[] = {0, 4, 8, 2, 8, 4, 8, 1};
82 84
83#define scale(x, f) (x * scale_d[f] / scale_m[f]) 85#define scale(x, f) (x * scale_d[f] / scale_m[f])
84 86
85void pwmclock_set_speed(struct pwmclock_softc *, int); 87void pwmclock_set_speed(struct pwmclock_softc *, int);
86static int pwmclock_cpuspeed_temp(SYSCTLFN_ARGS); 88static int pwmclock_cpuspeed_temp(SYSCTLFN_ARGS);
87static int pwmclock_cpuspeed_cur(SYSCTLFN_ARGS); 89static int pwmclock_cpuspeed_cur(SYSCTLFN_ARGS);
88static int pwmclock_cpuspeed_available(SYSCTLFN_ARGS); 90static int pwmclock_cpuspeed_available(SYSCTLFN_ARGS);
89 91
90static struct timecounter pwmclock_timecounter = { 92static struct timecounter pwmclock_timecounter = {
91 get_pwmclock_timecount, /* get_timecount */ 93 get_pwmclock_timecount, /* get_timecount */
92 0, /* no poll_pps */ 94 0, /* no poll_pps */
93 0xffffffff, /* counter_mask */ 95 0xffffffff, /* counter_mask */
94 0, /* frequency */ 96 0, /* frequency */
95 "pwm", /* name */ 97 "pwm", /* name */
96 100, /* quality */ 98 100, /* quality */
97 NULL, /* tc_priv */ 99 NULL, /* tc_priv */
98 NULL /* tc_next */ 100 NULL /* tc_next */
99}; 101};
100 102
101static int 103static int
102pwmclock_match(device_t parent, cfdata_t match, void *aux) 104pwmclock_match(device_t parent, cfdata_t match, void *aux)
103{ 105{
104 struct voyager_attach_args *vaa = (struct voyager_attach_args *)aux; 106 struct voyager_attach_args *vaa = (struct voyager_attach_args *)aux;
105 107
106 if (strcmp(vaa->vaa_name, "pwmclock") == 0) return 100; 108 if (strcmp(vaa->vaa_name, "pwmclock") == 0) return 100;
107 return 0; 109 return 0;
108} 110}
109 111
110static uint32_t 112static uint32_t
111pwmclock_wait_edge(struct pwmclock_softc *sc) 113pwmclock_wait_edge(struct pwmclock_softc *sc)
112{ 114{
113 /* clear interrupt */ 115 /* clear interrupt */
114 bus_space_write_4(sc->sc_memt, sc->sc_regh, SM502_PWM1, sc->sc_reg); 116 bus_space_write_4(sc->sc_memt, sc->sc_regh, SM502_PWM1, sc->sc_reg);
115 while ((bus_space_read_4(sc->sc_memt, sc->sc_regh, SM502_PWM1) & SM502_PWM_INTR_PENDING) == 0); 117 while ((bus_space_read_4(sc->sc_memt, sc->sc_regh, SM502_PWM1) & SM502_PWM_INTR_PENDING) == 0);
116 return mips3_cp0_count_read(); 118 return mips3_cp0_count_read();
117} 119}
118 120
119static void 121static void
120pwmclock_attach(device_t parent, device_t self, void *aux) 122pwmclock_attach(device_t parent, device_t self, void *aux)
121{ 123{
122 struct pwmclock_softc *sc = device_private(self); 124 struct pwmclock_softc *sc = device_private(self);
123 struct voyager_attach_args *vaa = aux; 125 struct voyager_attach_args *vaa = aux;
124 const struct sysctlnode *sysctl_node, *me, *freq; 126 const struct sysctlnode *sysctl_node, *me, *freq;
125 uint32_t reg, last, curr, diff, acc; 127 uint32_t reg, last, curr, diff, acc;
126 int i, clk; 128 int i, clk;
127 129
128 sc->sc_dev = self; 130 sc->sc_dev = self;
129 sc->sc_memt = vaa->vaa_tag; 131 sc->sc_memt = vaa->vaa_tag;
130 sc->sc_regh = vaa->vaa_regh; 132 sc->sc_regh = vaa->vaa_regh;
131 133
132 aprint_normal("\n"); 134 aprint_normal("\n");
133 135
134 voyager_establish_intr(parent, 22, pwmclock_intr, sc); 136 voyager_establish_intr(parent, 22, pwmclock_intr, sc);
135 reg = voyager_set_pwm(100, 100); /* 100Hz, 10% duty cycle */ 137 reg = voyager_set_pwm(100, 100); /* 100Hz, 10% duty cycle */
136 reg |= SM502_PWM_ENABLE | SM502_PWM_ENABLE_INTR | SM502_PWM_INTR_PENDING; 138 reg |= SM502_PWM_ENABLE | SM502_PWM_ENABLE_INTR | SM502_PWM_INTR_PENDING;
137 sc->sc_reg = reg; 139 sc->sc_reg = reg;
138 pwmclock = sc; 140 pwmclock = sc;
139 initclocks_ptr = pwmclock_start; 141 initclocks_ptr = pwmclock_start;
140 142
141 /* ok, let's see how far the cycle counter gets between interrupts */ 143 /* ok, let's see how far the cycle counter gets between interrupts */
142 aprint_normal_dev(sc->sc_dev, "calibrating CPU timer...\n"); 144 DPRINTF("calibrating CPU timer...\n");
143 for (clk = 1; clk < 8; clk++) { 145 for (clk = 1; clk < 8; clk++) {
144 REGVAL(LS2F_CHIPCFG0) = (REGVAL(LS2F_CHIPCFG0) & ~LS2FCFG_FREQSCALE_MASK) | clk; 146 REGVAL(LS2F_CHIPCFG0) = (REGVAL(LS2F_CHIPCFG0) & ~LS2FCFG_FREQSCALE_MASK) | clk;
145 bus_space_write_4(sc->sc_memt, sc->sc_regh, SM502_PWM1, sc->sc_reg); 147 bus_space_write_4(sc->sc_memt, sc->sc_regh, SM502_PWM1, sc->sc_reg);
146 acc = 0; 148 acc = 0;
147 last = pwmclock_wait_edge(sc); 149 last = pwmclock_wait_edge(sc);
148 for (i = 0; i < 16; i++) { 150 for (i = 0; i < 16; i++) {
149 curr = pwmclock_wait_edge(sc); 151 curr = pwmclock_wait_edge(sc);
150 diff = curr - last; 152 diff = curr - last;
151 acc += diff; 153 acc += diff;
152 last = curr; 154 last = curr;
153 } 155 }
154 sc->sc_scale[clk] = (acc >> 4) / 5000; 156 sc->sc_scale[clk] = (acc >> 4) / 5000;
155 } 157 }
 158#ifdef PWMCLOCK_DEBUG
156 for (clk = 1; clk < 8; clk++) { 159 for (clk = 1; clk < 8; clk++) {
157 aprint_normal_dev(sc->sc_dev, "%d/8: %d\n", clk + 1, sc->sc_scale[clk]); 160 aprint_normal_dev(sc->sc_dev, "%d/8: %d\n", clk + 1, sc->sc_scale[clk]);
158 } 161 }
 162#endif
159 sc->sc_step = 7; 163 sc->sc_step = 7;
160 sc->sc_step_wanted = 7; 164 sc->sc_step_wanted = 7;
161 165
162 /* now setup sysctl */ 166 /* now setup sysctl */
163 if (sysctl_createv(NULL, 0, NULL,  167 if (sysctl_createv(NULL, 0, NULL,
164 &me,  168 &me,
165 CTLFLAG_READWRITE, CTLTYPE_NODE, "loongson", NULL, NULL, 169 CTLFLAG_READWRITE, CTLTYPE_NODE, "loongson", NULL, NULL,
166 0, NULL, 0, CTL_MACHDEP, CTL_CREATE, CTL_EOL) != 0) 170 0, NULL, 0, CTL_MACHDEP, CTL_CREATE, CTL_EOL) != 0)
167 aprint_error_dev(sc->sc_dev, "couldn't create 'loongson' node\n"); 171 aprint_error_dev(sc->sc_dev, "couldn't create 'loongson' node\n");
168  172
169 if (sysctl_createv(NULL, 0, NULL,  173 if (sysctl_createv(NULL, 0, NULL,
170 &freq,  174 &freq,
171 CTLFLAG_READWRITE, CTLTYPE_NODE, "frequency", NULL, NULL, 175 CTLFLAG_READWRITE, CTLTYPE_NODE, "frequency", NULL, NULL,
172 0, NULL, 0, CTL_MACHDEP, me->sysctl_num, CTL_CREATE, CTL_EOL) != 0) 176 0, NULL, 0, CTL_MACHDEP, me->sysctl_num, CTL_CREATE, CTL_EOL) != 0)
173 aprint_error_dev(sc->sc_dev, "couldn't create 'frequency' node\n"); 177 aprint_error_dev(sc->sc_dev, "couldn't create 'frequency' node\n");
174 178
175 if (sysctl_createv(NULL, 0, NULL,  179 if (sysctl_createv(NULL, 0, NULL,
176 &sysctl_node,  180 &sysctl_node,
177 CTLFLAG_READWRITE | CTLFLAG_OWNDESC, 181 CTLFLAG_READWRITE | CTLFLAG_OWNDESC,
178 CTLTYPE_INT, "target", "CPU speed", pwmclock_cpuspeed_temp,  182 CTLTYPE_INT, "target", "CPU speed", pwmclock_cpuspeed_temp,
179 0, sc, 0, CTL_MACHDEP, me->sysctl_num, freq->sysctl_num,  183 0, sc, 0, CTL_MACHDEP, me->sysctl_num, freq->sysctl_num,
180 CTL_CREATE, CTL_EOL) == 0) { 184 CTL_CREATE, CTL_EOL) == 0) {
181 } else 185 } else
182 aprint_error_dev(sc->sc_dev, "couldn't create 'target' node\n"); 186 aprint_error_dev(sc->sc_dev, "couldn't create 'target' node\n");
183 187
184 if (sysctl_createv(NULL, 0, NULL,  188 if (sysctl_createv(NULL, 0, NULL,
185 &sysctl_node,  189 &sysctl_node,
186 CTLFLAG_READWRITE, 190 CTLFLAG_READWRITE,
187 CTLTYPE_INT, "current", NULL, pwmclock_cpuspeed_cur,  191 CTLTYPE_INT, "current", NULL, pwmclock_cpuspeed_cur,
188 1, sc, 0, CTL_MACHDEP, me->sysctl_num, freq->sysctl_num,  192 1, sc, 0, CTL_MACHDEP, me->sysctl_num, freq->sysctl_num,
189 CTL_CREATE, CTL_EOL) == 0) { 193 CTL_CREATE, CTL_EOL) == 0) {
190 } else 194 } else
191 aprint_error_dev(sc->sc_dev, "couldn't create 'current' node\n"); 195 aprint_error_dev(sc->sc_dev, "couldn't create 'current' node\n");
192 196
193 if (sysctl_createv(NULL, 0, NULL,  197 if (sysctl_createv(NULL, 0, NULL,
194 &sysctl_node,  198 &sysctl_node,
195 CTLFLAG_READWRITE, 199 CTLFLAG_READWRITE,
196 CTLTYPE_STRING, "available", NULL, pwmclock_cpuspeed_available,  200 CTLTYPE_STRING, "available", NULL, pwmclock_cpuspeed_available,
197 2, sc, 0, CTL_MACHDEP, me->sysctl_num, freq->sysctl_num,  201 2, sc, 0, CTL_MACHDEP, me->sysctl_num, freq->sysctl_num,
198 CTL_CREATE, CTL_EOL) == 0) { 202 CTL_CREATE, CTL_EOL) == 0) {
199 } else 203 } else
200 aprint_error_dev(sc->sc_dev, "couldn't create 'available' node\n"); 204 aprint_error_dev(sc->sc_dev, "couldn't create 'available' node\n");
201} 205}
202 206
203void 207void
204pwmclock_set_speed(struct pwmclock_softc *sc, int speed) 208pwmclock_set_speed(struct pwmclock_softc *sc, int speed)
205{ 209{
206 210
207 if ((speed < 1) || (speed > 7)) 211 if ((speed < 1) || (speed > 7))
208 return; 212 return;
209 sc->sc_step_wanted = speed; 213 sc->sc_step_wanted = speed;
210 DPRINTF("%s: %d\n", __func__, speed); 214 DPRINTF("%s: %d\n", __func__, speed);
211} 215}
212 216
213/* 217/*
214 * the PWM interrupt handler 218 * the PWM interrupt handler
215 * we don't have a CPU clock independent, high resolution counter so we're 219 * we don't have a CPU clock independent, high resolution counter so we're
216 * stuck with a PWM that can't count and a CP0 counter that slows down or 220 * stuck with a PWM that can't count and a CP0 counter that slows down or
217 * speeds up with the actual CPU speed. In order to still get halfway 221 * speeds up with the actual CPU speed. In order to still get halfway
218 * accurate time we do the following: 222 * accurate time we do the following:
219 * - only change CPU speed in the timer interrupt 223 * - only change CPU speed in the timer interrupt
220 * - each timer interrupt we measure how many CP0 cycles passed since last 224 * - each timer interrupt we measure how many CP0 cycles passed since last
221 * time, adjust for CPU speed since we can be sure it didn't change, use 225 * time, adjust for CPU speed since we can be sure it didn't change, use
222 * that to update a separate counter 226 * that to update a separate counter
223 * - when reading the time counter we take the number of CP0 ticks since  227 * - when reading the time counter we take the number of CP0 ticks since
224 * the last timer interrupt, scale it to CPU clock, return that plus the 228 * the last timer interrupt, scale it to CPU clock, return that plus the
225 * interrupt updated counter mentioned above to get something close to 229 * interrupt updated counter mentioned above to get something close to
226 * CP0 running at full speed  230 * CP0 running at full speed
227 * - when changing CPU speed do it as close to taking the time from CP0 as 231 * - when changing CPU speed do it as close to taking the time from CP0 as
228 * possible to keep the period of time we spend with CP0 running at the 232 * possible to keep the period of time we spend with CP0 running at the
229 * wrong frequency as short as possible - hopefully short enough to stay 233 * wrong frequency as short as possible - hopefully short enough to stay
230 * insignificant compared to other noise since switching speeds isn't 234 * insignificant compared to other noise since switching speeds isn't
231 * going to happen all that often 235 * going to happen all that often
232 */ 236 */
233 237
234int 238int
235pwmclock_intr(void *cookie) 239pwmclock_intr(void *cookie)
236{ 240{
237 struct pwmclock_softc *sc = cookie; 241 struct pwmclock_softc *sc = cookie;
238 uint32_t reg, now, diff; 242 uint32_t reg, now, diff;
239 243
240 /* is it us? */ 244 /* is it us? */
241 reg = bus_space_read_4(sc->sc_memt, sc->sc_regh, SM502_PWM1); 245 reg = bus_space_read_4(sc->sc_memt, sc->sc_regh, SM502_PWM1);
242 if ((reg & SM502_PWM_INTR_PENDING) == 0) 246 if ((reg & SM502_PWM_INTR_PENDING) == 0)
243 return 0; 247 return 0;
244 248
245 /* yes, it's us, so clear the interrupt */ 249 /* yes, it's us, so clear the interrupt */
246 bus_space_write_4(sc->sc_memt, sc->sc_regh, SM502_PWM1, sc->sc_reg); 250 bus_space_write_4(sc->sc_memt, sc->sc_regh, SM502_PWM1, sc->sc_reg);
247 251
248 /* 252 /*
249 * this looks kinda funny but what we want here is this: 253 * this looks kinda funny but what we want here is this:
250 * - reading the counter and changing the CPU clock should be as 254 * - reading the counter and changing the CPU clock should be as
251 * close together as possible in order to remain halfway accurate 255 * close together as possible in order to remain halfway accurate
252 * - we need to use the previous sc_step in order to scale the 256 * - we need to use the previous sc_step in order to scale the
253 * interval passed since the last clock interrupt correctly, so 257 * interval passed since the last clock interrupt correctly, so
254 * we only change sc_step after doing that 258 * we only change sc_step after doing that
255 */ 259 */
256 if (sc->sc_step_wanted != sc->sc_step) { 260 if (sc->sc_step_wanted != sc->sc_step) {
257 REGVAL(LS2F_CHIPCFG0) = 261 REGVAL(LS2F_CHIPCFG0) =
258 (REGVAL(LS2F_CHIPCFG0) & ~LS2FCFG_FREQSCALE_MASK) | 262 (REGVAL(LS2F_CHIPCFG0) & ~LS2FCFG_FREQSCALE_MASK) |
259 sc->sc_step_wanted; 263 sc->sc_step_wanted;
260 } 264 }
261 265
262 now = mips3_cp0_count_read();  266 now = mips3_cp0_count_read();
263 diff = now - sc->sc_last; 267 diff = now - sc->sc_last;
264 sc->sc_count += scale(diff, sc->sc_step); 268 sc->sc_count += scale(diff, sc->sc_step);
265 sc->sc_last = now; 269 sc->sc_last = now;
266 if (sc->sc_step_wanted != sc->sc_step) { 270 if (sc->sc_step_wanted != sc->sc_step) {
267 sc->sc_step = sc->sc_step_wanted; 271 sc->sc_step = sc->sc_step_wanted;
268 } 272 }
269 hardclock(&cf); 273 hardclock(&cf);
270 274
271 return 1; 275 return 1;
272} 276}
273 277
274static void 278static void
275pwmclock_start() 279pwmclock_start()
276{ 280{
277 struct pwmclock_softc *sc = pwmclock; 281 struct pwmclock_softc *sc = pwmclock;
278 sc->sc_count = 0; 282 sc->sc_count = 0;
279 sc->sc_last = mips3_cp0_count_read(); 283 sc->sc_last = mips3_cp0_count_read();
280 pwmclock_timecounter.tc_frequency = curcpu()->ci_cpu_freq / 2; 284 pwmclock_timecounter.tc_frequency = curcpu()->ci_cpu_freq / 2;
281 tc_init(&pwmclock_timecounter); 285 tc_init(&pwmclock_timecounter);
282 bus_space_write_4(sc->sc_memt, sc->sc_regh, SM502_PWM1, sc->sc_reg); 286 bus_space_write_4(sc->sc_memt, sc->sc_regh, SM502_PWM1, sc->sc_reg);
283} 287}
284 288
285static u_int 289static u_int
286get_pwmclock_timecount(struct timecounter *tc) 290get_pwmclock_timecount(struct timecounter *tc)
287{ 291{
288 struct pwmclock_softc *sc = pwmclock; 292 struct pwmclock_softc *sc = pwmclock;
289 uint32_t now, diff; 293 uint32_t now, diff;
290 294
291 now = mips3_cp0_count_read(); 295 now = mips3_cp0_count_read();
292 diff = now - sc->sc_last; 296 diff = now - sc->sc_last;
293 return sc->sc_count + scale(diff, sc->sc_step); 297 return sc->sc_count + scale(diff, sc->sc_step);
294} 298}
295 299
296static int 300static int
297pwmclock_cpuspeed_temp(SYSCTLFN_ARGS) 301pwmclock_cpuspeed_temp(SYSCTLFN_ARGS)
298{ 302{
299 struct sysctlnode node = *rnode; 303 struct sysctlnode node = *rnode;
300 struct pwmclock_softc *sc = node.sysctl_data; 304 struct pwmclock_softc *sc = node.sysctl_data;
301 int mhz, i; 305 int mhz, i;
302 306
303 mhz = sc->sc_scale[sc->sc_step_wanted]; 307 mhz = sc->sc_scale[sc->sc_step_wanted];
304 308
305 node.sysctl_data = &mhz; 309 node.sysctl_data = &mhz;
306 if (sysctl_lookup(SYSCTLFN_CALL(&node)) == 0) { 310 if (sysctl_lookup(SYSCTLFN_CALL(&node)) == 0) {
307 int new_reg; 311 int new_reg;
308 312
309 new_reg = *(int *)node.sysctl_data; 313 new_reg = *(int *)node.sysctl_data;
310 i = 1; 314 i = 1;
311 while ((i < 8) && (sc->sc_scale[i] != new_reg)) 315 while ((i < 8) && (sc->sc_scale[i] != new_reg))
312 i++; 316 i++;
313 if (i > 7) 317 if (i > 7)
314 return EINVAL; 318 return EINVAL;
315 pwmclock_set_speed(sc, i); 319 pwmclock_set_speed(sc, i);
316 return 0; 320 return 0;
317 } 321 }
318 return EINVAL; 322 return EINVAL;
319} 323}
320 324
321static int 325static int
322pwmclock_cpuspeed_cur(SYSCTLFN_ARGS) 326pwmclock_cpuspeed_cur(SYSCTLFN_ARGS)
323{ 327{
324 struct sysctlnode node = *rnode; 328 struct sysctlnode node = *rnode;
325 struct pwmclock_softc *sc = node.sysctl_data; 329 struct pwmclock_softc *sc = node.sysctl_data;
326 int mhz; 330 int mhz;
327 331
328 mhz = sc->sc_scale[sc->sc_step]; 332 mhz = sc->sc_scale[sc->sc_step];
329 node.sysctl_data = &mhz; 333 node.sysctl_data = &mhz;
330 return sysctl_lookup(SYSCTLFN_CALL(&node)); 334 return sysctl_lookup(SYSCTLFN_CALL(&node));
331} 335}
332 336
333static int 337static int
334pwmclock_cpuspeed_available(SYSCTLFN_ARGS) 338pwmclock_cpuspeed_available(SYSCTLFN_ARGS)
335{ 339{
336 struct sysctlnode node = *rnode; 340 struct sysctlnode node = *rnode;
337 struct pwmclock_softc *sc = node.sysctl_data; 341 struct pwmclock_softc *sc = node.sysctl_data;
338 char buf[128]; 342 char buf[128];
339 343
340 snprintf(buf, 128, "%d %d %d %d %d %d %d", sc->sc_scale[1], 344 snprintf(buf, 128, "%d %d %d %d %d %d %d", sc->sc_scale[1],
341 sc->sc_scale[2], sc->sc_scale[3], sc->sc_scale[4], 345 sc->sc_scale[2], sc->sc_scale[3], sc->sc_scale[4],
342 sc->sc_scale[5], sc->sc_scale[6], sc->sc_scale[7]); 346 sc->sc_scale[5], sc->sc_scale[6], sc->sc_scale[7]);
343 node.sysctl_data = buf; 347 node.sysctl_data = buf;
344 return(sysctl_lookup(SYSCTLFN_CALL(&node))); 348 return(sysctl_lookup(SYSCTLFN_CALL(&node)));
345} 349}
346 350
347SYSCTL_SETUP(sysctl_ams_setup, "sysctl obio subtree setup") 351SYSCTL_SETUP(sysctl_ams_setup, "sysctl obio subtree setup")
348{ 352{
349 353
350 sysctl_createv(NULL, 0, NULL, NULL, 354 sysctl_createv(NULL, 0, NULL, NULL,
351 CTLFLAG_PERMANENT, 355 CTLFLAG_PERMANENT,
352 CTLTYPE_NODE, "machdep", NULL, 356 CTLTYPE_NODE, "machdep", NULL,
353 NULL, 0, NULL, 0, 357 NULL, 0, NULL, 0,
354 CTL_MACHDEP, CTL_EOL); 358 CTL_MACHDEP, CTL_EOL);
355} 359}