| @@ -1,14 +1,14 @@ | | | @@ -1,14 +1,14 @@ |
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. |
| @@ -16,44 +16,46 @@ | | | @@ -16,44 +16,46 @@ |
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 | |
53 | int pwmclock_intr(void *); | | 55 | int pwmclock_intr(void *); |
54 | | | 56 | |
55 | struct pwmclock_softc { | | 57 | struct 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; |
| @@ -129,43 +131,45 @@ pwmclock_attach(device_t parent, device_ | | | @@ -129,43 +131,45 @@ pwmclock_attach(device_t parent, device_ |
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, |