c99 struct initializersdiff -r1.4 -r1.5 src/sys/arch/arm/xscale/pxa2x0_apm.c
(christos)
--- src/sys/arch/arm/xscale/pxa2x0_apm.c 2012/11/12 18:00:38 1.4
+++ src/sys/arch/arm/xscale/pxa2x0_apm.c 2020/10/30 22:20:38 1.5
@@ -1,1107 +1,1111 @@ | @@ -1,1107 +1,1111 @@ | |||
1 | /* $NetBSD: pxa2x0_apm.c,v 1.4 2012/11/12 18:00:38 skrll Exp $ */ | 1 | /* $NetBSD: pxa2x0_apm.c,v 1.5 2020/10/30 22:20:38 christos Exp $ */ | |
2 | /* $OpenBSD: pxa2x0_apm.c,v 1.28 2007/03/29 18:42:38 uwe Exp $ */ | 2 | /* $OpenBSD: pxa2x0_apm.c,v 1.28 2007/03/29 18:42:38 uwe Exp $ */ | |
3 | 3 | |||
4 | /*- | 4 | /*- | |
5 | * Copyright (c) 2001 Alexander Guy. All rights reserved. | 5 | * Copyright (c) 2001 Alexander Guy. All rights reserved. | |
6 | * Copyright (c) 1998-2001 Michael Shalayeff. All rights reserved. | 6 | * Copyright (c) 1998-2001 Michael Shalayeff. All rights reserved. | |
7 | * Copyright (c) 1995 John T. Kohl. All rights reserved. | 7 | * Copyright (c) 1995 John T. Kohl. All rights reserved. | |
8 | * | 8 | * | |
9 | * Redistribution and use in source and binary forms, with or without | 9 | * Redistribution and use in source and binary forms, with or without | |
10 | * modification, are permitted provided that the following conditions | 10 | * modification, are permitted provided that the following conditions | |
11 | * are met: | 11 | * are met: | |
12 | * 1. Redistributions of source code must retain the above copyright | 12 | * 1. Redistributions of source code must retain the above copyright | |
13 | * notice, this list of conditions and the following disclaimer. | 13 | * notice, this list of conditions and the following disclaimer. | |
14 | * 2. Redistributions in binary form must reproduce the above copyright | 14 | * 2. Redistributions in binary form must reproduce the above copyright | |
15 | * notice, this list of conditions and the following disclaimer in the | 15 | * notice, this list of conditions and the following disclaimer in the | |
16 | * documentation and/or other materials provided with the distribution. | 16 | * documentation and/or other materials provided with the distribution. | |
17 | * 3. All advertising materials mentioning features or use of this software | 17 | * 3. All advertising materials mentioning features or use of this software | |
18 | * must display the following acknowledgement: | 18 | * must display the following acknowledgement: | |
19 | * This product includes software developed by the University of | 19 | * This product includes software developed by the University of | |
20 | * California, Berkeley and its contributors. | 20 | * California, Berkeley and its contributors. | |
21 | * 4. Neither the name of the University nor the names of its contributors | 21 | * 4. Neither the name of the University nor the names of its contributors | |
22 | * may be used to endorse or promote products derived from this software | 22 | * may be used to endorse or promote products derived from this software | |
23 | * without specific prior written permission. | 23 | * without specific prior written permission. | |
24 | * | 24 | * | |
25 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND | 25 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND | |
26 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | 26 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
27 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | 27 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |
28 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | 28 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | |
29 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | 29 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
30 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | 30 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |
31 | * OR SERVICES; LOSS OF MIND, USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | 31 | * OR SERVICES; LOSS OF MIND, USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
32 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | 32 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |
33 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | 33 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |
34 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | 34 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |
35 | * SUCH DAMAGE. | 35 | * SUCH DAMAGE. | |
36 | * | 36 | * | |
37 | */ | 37 | */ | |
38 | 38 | |||
39 | #include <sys/param.h> | 39 | #include <sys/param.h> | |
40 | #include <sys/systm.h> | 40 | #include <sys/systm.h> | |
41 | #include <sys/kernel.h> | 41 | #include <sys/kernel.h> | |
42 | #include <sys/kthread.h> | 42 | #include <sys/kthread.h> | |
43 | #include <sys/lock.h> | 43 | #include <sys/lock.h> | |
44 | #include <sys/mount.h> /* for vfs_syncwait() */ | 44 | #include <sys/mount.h> /* for vfs_syncwait() */ | |
45 | #include <sys/proc.h> | 45 | #include <sys/proc.h> | |
46 | #include <sys/device.h> | 46 | #include <sys/device.h> | |
47 | #include <sys/fcntl.h> | 47 | #include <sys/fcntl.h> | |
48 | #include <sys/ioctl.h> | 48 | #include <sys/ioctl.h> | |
49 | #include <sys/event.h> | 49 | #include <sys/event.h> | |
50 | 50 | |||
51 | #include <machine/cpu.h> | 51 | #include <machine/cpu.h> | |
52 | #include <machine/apmvar.h> | 52 | #include <machine/apmvar.h> | |
53 | 53 | |||
54 | #include <arm/xscale/pxa2x0reg.h> | 54 | #include <arm/xscale/pxa2x0reg.h> | |
55 | #include <arm/xscale/pxa2x0var.h> | 55 | #include <arm/xscale/pxa2x0var.h> | |
56 | #include <arm/xscale/pxa2x0_apm.h> | 56 | #include <arm/xscale/pxa2x0_apm.h> | |
57 | #include <arm/xscale/pxa2x0_gpio.h> | 57 | #include <arm/xscale/pxa2x0_gpio.h> | |
58 | 58 | |||
59 | #if defined(APMDEBUG) | 59 | #if defined(APMDEBUG) | |
60 | #define DPRINTF(x) printf x | 60 | #define DPRINTF(x) printf x | |
61 | #else | 61 | #else | |
62 | #define DPRINTF(x) /**/ | 62 | #define DPRINTF(x) /**/ | |
63 | #endif | 63 | #endif | |
64 | 64 | |||
65 | #define APM_LOCK(sc) lockmgr(&(sc)->sc_lock, LK_EXCLUSIVE, NULL) | 65 | #define APM_LOCK(sc) lockmgr(&(sc)->sc_lock, LK_EXCLUSIVE, NULL) | |
66 | #define APM_UNLOCK(sc) lockmgr(&(sc)->sc_lock, LK_RELEASE, NULL) | 66 | #define APM_UNLOCK(sc) lockmgr(&(sc)->sc_lock, LK_RELEASE, NULL) | |
67 | 67 | |||
68 | #define APMUNIT(dev) (minor(dev)&0xf0) | 68 | #define APMUNIT(dev) (minor(dev)&0xf0) | |
69 | #define APMDEV(dev) (minor(dev)&0x0f) | 69 | #define APMDEV(dev) (minor(dev)&0x0f) | |
70 | #define APMDEV_NORMAL 0 | 70 | #define APMDEV_NORMAL 0 | |
71 | #define APMDEV_CTL 8 | 71 | #define APMDEV_CTL 8 | |
72 | 72 | |||
73 | int apm_userstandbys; | 73 | int apm_userstandbys; | |
74 | int apm_suspends; | 74 | int apm_suspends; | |
75 | int apm_battlow; | 75 | int apm_battlow; | |
76 | 76 | |||
77 | extern struct cfdriver zapm_cd; | 77 | extern struct cfdriver zapm_cd; | |
78 | 78 | |||
79 | /* battery percentage at which we get verbose in our warnings. This | 79 | /* battery percentage at which we get verbose in our warnings. This | |
80 | value can be changed using sysctl(8), value machdep.apmwarn. | 80 | value can be changed using sysctl(8), value machdep.apmwarn. | |
81 | Setting it to zero kills all warnings */ | 81 | Setting it to zero kills all warnings */ | |
82 | int cpu_apmwarn = 10; | 82 | int cpu_apmwarn = 10; | |
83 | 83 | |||
84 | void apm_power_print(struct pxa2x0_apm_softc *, struct apm_power_info *); | 84 | void apm_power_print(struct pxa2x0_apm_softc *, struct apm_power_info *); | |
85 | void apm_power_info(struct pxa2x0_apm_softc *, struct apm_power_info *); | 85 | void apm_power_info(struct pxa2x0_apm_softc *, struct apm_power_info *); | |
86 | void apm_suspend(struct pxa2x0_apm_softc *); | 86 | void apm_suspend(struct pxa2x0_apm_softc *); | |
87 | void apm_resume(struct pxa2x0_apm_softc *); | 87 | void apm_resume(struct pxa2x0_apm_softc *); | |
88 | int apm_get_event(struct pxa2x0_apm_softc *, u_int *); | 88 | int apm_get_event(struct pxa2x0_apm_softc *, u_int *); | |
89 | int apm_handle_event(struct pxa2x0_apm_softc *, u_int); | 89 | int apm_handle_event(struct pxa2x0_apm_softc *, u_int); | |
90 | void apm_thread_create(void *); | 90 | void apm_thread_create(void *); | |
91 | void apm_thread(void *); | 91 | void apm_thread(void *); | |
92 | 92 | |||
93 | #if 0 | 93 | #if 0 | |
94 | extern int perflevel; | 94 | extern int perflevel; | |
95 | #endif | 95 | #endif | |
96 | 96 | |||
97 | int freq; | 97 | int freq; | |
98 | void pxa2x0_setperf(int speed); | 98 | void pxa2x0_setperf(int speed); | |
99 | int pxa2x0_cpuspeed(int *speed); | 99 | int pxa2x0_cpuspeed(int *speed); | |
100 | 100 | |||
101 | int apm_record_event(struct pxa2x0_apm_softc *, u_int); | 101 | int apm_record_event(struct pxa2x0_apm_softc *, u_int); | |
102 | #if 0 | 102 | #if 0 | |
103 | void filt_apmrdetach(struct knote *kn); | 103 | void filt_apmrdetach(struct knote *kn); | |
104 | int filt_apmread(struct knote *kn, long hint); | 104 | int filt_apmread(struct knote *kn, long hint); | |
105 | int apmkqfilter(dev_t dev, struct knote *kn); | 105 | int apmkqfilter(dev_t dev, struct knote *kn); | |
106 | 106 | |||
107 | struct filterops apmread_filtops = | 107 | static const struct filterops apmread_filtops = { | |
108 | { 1, NULL, filt_apmrdetach, filt_apmread}; | 108 | .f_isfd = 1, | |
109 | .f_attach = NULL, | |||
110 | .f_detach = filt_apmrdetach, | |||
111 | .f_event = filt_apmread, | |||
112 | }; | |||
109 | #endif | 113 | #endif | |
110 | 114 | |||
111 | /* | 115 | /* | |
112 | * Flags to control kernel display | 116 | * Flags to control kernel display | |
113 | * SCFLAG_NOPRINT: do not output APM power messages due to | 117 | * SCFLAG_NOPRINT: do not output APM power messages due to | |
114 | * a power change event. | 118 | * a power change event. | |
115 | * | 119 | * | |
116 | * SCFLAG_PCTPRINT: do not output APM power messages due to | 120 | * SCFLAG_PCTPRINT: do not output APM power messages due to | |
117 | * to a power change event unless the battery | 121 | * to a power change event unless the battery | |
118 | * percentage changes. | 122 | * percentage changes. | |
119 | */ | 123 | */ | |
120 | 124 | |||
121 | #define SCFLAG_NOPRINT 0x0008000 | 125 | #define SCFLAG_NOPRINT 0x0008000 | |
122 | #define SCFLAG_PCTPRINT 0x0004000 | 126 | #define SCFLAG_PCTPRINT 0x0004000 | |
123 | #define SCFLAG_PRINT (SCFLAG_NOPRINT|SCFLAG_PCTPRINT) | 127 | #define SCFLAG_PRINT (SCFLAG_NOPRINT|SCFLAG_PCTPRINT) | |
124 | 128 | |||
125 | #define SCFLAG_OREAD (1 << 0) | 129 | #define SCFLAG_OREAD (1 << 0) | |
126 | #define SCFLAG_OWRITE (1 << 1) | 130 | #define SCFLAG_OWRITE (1 << 1) | |
127 | #define SCFLAG_OPEN (SCFLAG_OREAD|SCFLAG_OWRITE) | 131 | #define SCFLAG_OPEN (SCFLAG_OREAD|SCFLAG_OWRITE) | |
128 | 132 | |||
129 | /* This structure must be kept in sync with pxa2x0_apm_asm.S. */ | 133 | /* This structure must be kept in sync with pxa2x0_apm_asm.S. */ | |
130 | struct pxa2x0_memcfg { | 134 | struct pxa2x0_memcfg { | |
131 | /* SDRAM refresh */ | 135 | /* SDRAM refresh */ | |
132 | uint32_t mdrefr_high; /* 0x00 */ | 136 | uint32_t mdrefr_high; /* 0x00 */ | |
133 | uint32_t mdrefr_low; /* 0x04 */ | 137 | uint32_t mdrefr_low; /* 0x04 */ | |
134 | uint32_t mdrefr_low2; /* 0x08 */ | 138 | uint32_t mdrefr_low2; /* 0x08 */ | |
135 | /* Synchronous, static, or VLIO interfaces */ | 139 | /* Synchronous, static, or VLIO interfaces */ | |
136 | uint32_t msc_high[3]; /* 0x0c */ | 140 | uint32_t msc_high[3]; /* 0x0c */ | |
137 | uint32_t msc_low[3]; /* 0x18 */ | 141 | uint32_t msc_low[3]; /* 0x18 */ | |
138 | /* XXX move up */ | 142 | /* XXX move up */ | |
139 | uint32_t mdrefr_91; /* 0x24 */ | 143 | uint32_t mdrefr_91; /* 0x24 */ | |
140 | }; | 144 | }; | |
141 | 145 | |||
142 | /* XXX */ | 146 | /* XXX */ | |
143 | #define MDREFR_C3000 (MDREFR_K0DB2 | MDREFR_E1PIN | MDREFR_K1RUN | \ | 147 | #define MDREFR_C3000 (MDREFR_K0DB2 | MDREFR_E1PIN | MDREFR_K1RUN | \ | |
144 | MDREFR_K1DB2 | MDREFR_K2DB2 | MDREFR_APD) | 148 | MDREFR_K1DB2 | MDREFR_K2DB2 | MDREFR_APD) | |
145 | #define MSC0_HIGH \ | 149 | #define MSC0_HIGH \ | |
146 | ( 7 << MSC_RRR_SHIFT << 16) | \ | 150 | ( 7 << MSC_RRR_SHIFT << 16) | \ | |
147 | (15 << MSC_RDN_SHIFT << 16) | \ | 151 | (15 << MSC_RDN_SHIFT << 16) | \ | |
148 | (15 << MSC_RDF_SHIFT << 16) | \ | 152 | (15 << MSC_RDF_SHIFT << 16) | \ | |
149 | (MSC_RT_NONBURST << 16) | \ | 153 | (MSC_RT_NONBURST << 16) | \ | |
150 | ( 2 << MSC_RRR_SHIFT) | \ | 154 | ( 2 << MSC_RRR_SHIFT) | \ | |
151 | (13 << MSC_RDN_SHIFT) | \ | 155 | (13 << MSC_RDN_SHIFT) | \ | |
152 | (13 << MSC_RDF_SHIFT) | \ | 156 | (13 << MSC_RDF_SHIFT) | \ | |
153 | MSC_RBW /* PXA271 */ | \ | 157 | MSC_RBW /* PXA271 */ | \ | |
154 | MSC_RT_NONBURST | 158 | MSC_RT_NONBURST | |
155 | #define MSC1_HIGH \ | 159 | #define MSC1_HIGH \ | |
156 | ( 7 << MSC_RRR_SHIFT << 16) | \ | 160 | ( 7 << MSC_RRR_SHIFT << 16) | \ | |
157 | (15 << MSC_RDN_SHIFT << 16) | \ | 161 | (15 << MSC_RDN_SHIFT << 16) | \ | |
158 | (15 << MSC_RDF_SHIFT << 16) | \ | 162 | (15 << MSC_RDF_SHIFT << 16) | \ | |
159 | (MSC_RT_VLIO << 16) | \ | 163 | (MSC_RT_VLIO << 16) | \ | |
160 | ( 3 << MSC_RRR_SHIFT) | \ | 164 | ( 3 << MSC_RRR_SHIFT) | \ | |
161 | ( 4 << MSC_RDN_SHIFT) | \ | 165 | ( 4 << MSC_RDN_SHIFT) | \ | |
162 | (13 << MSC_RDF_SHIFT) | \ | 166 | (13 << MSC_RDF_SHIFT) | \ | |
163 | MSC_RT_VLIO | 167 | MSC_RT_VLIO | |
164 | #define MSC2_HIGH \ | 168 | #define MSC2_HIGH \ | |
165 | ( 7 << MSC_RRR_SHIFT << 16) | \ | 169 | ( 7 << MSC_RRR_SHIFT << 16) | \ | |
166 | (15 << MSC_RDN_SHIFT << 16) | \ | 170 | (15 << MSC_RDN_SHIFT << 16) | \ | |
167 | (15 << MSC_RDF_SHIFT << 16) | \ | 171 | (15 << MSC_RDF_SHIFT << 16) | \ | |
168 | (MSC_RT_NONBURST << 16) | \ | 172 | (MSC_RT_NONBURST << 16) | \ | |
169 | ( 3 << MSC_RRR_SHIFT) | \ | 173 | ( 3 << MSC_RRR_SHIFT) | \ | |
170 | ( 4 << MSC_RDN_SHIFT) | \ | 174 | ( 4 << MSC_RDN_SHIFT) | \ | |
171 | (13 << MSC_RDF_SHIFT) | \ | 175 | (13 << MSC_RDF_SHIFT) | \ | |
172 | MSC_RT_VLIO | 176 | MSC_RT_VLIO | |
173 | #define MSC0_LOW \ | 177 | #define MSC0_LOW \ | |
174 | ( 7 << MSC_RRR_SHIFT << 16) | \ | 178 | ( 7 << MSC_RRR_SHIFT << 16) | \ | |
175 | (15 << MSC_RDN_SHIFT << 16) | \ | 179 | (15 << MSC_RDN_SHIFT << 16) | \ | |
176 | (15 << MSC_RDF_SHIFT << 16) | \ | 180 | (15 << MSC_RDF_SHIFT << 16) | \ | |
177 | (MSC_RT_NONBURST << 16) | \ | 181 | (MSC_RT_NONBURST << 16) | \ | |
178 | ( 1 << MSC_RRR_SHIFT) | \ | 182 | ( 1 << MSC_RRR_SHIFT) | \ | |
179 | ( 8 << MSC_RDN_SHIFT) | \ | 183 | ( 8 << MSC_RDN_SHIFT) | \ | |
180 | ( 8 << MSC_RDF_SHIFT) | \ | 184 | ( 8 << MSC_RDF_SHIFT) | \ | |
181 | MSC_RBW /* PXA271 */ | \ | 185 | MSC_RBW /* PXA271 */ | \ | |
182 | MSC_RT_NONBURST | 186 | MSC_RT_NONBURST | |
183 | #define MSC1_LOW \ | 187 | #define MSC1_LOW \ | |
184 | ( 7 << MSC_RRR_SHIFT << 16) | \ | 188 | ( 7 << MSC_RRR_SHIFT << 16) | \ | |
185 | (15 << MSC_RDN_SHIFT << 16) | \ | 189 | (15 << MSC_RDN_SHIFT << 16) | \ | |
186 | (15 << MSC_RDF_SHIFT << 16) | \ | 190 | (15 << MSC_RDF_SHIFT << 16) | \ | |
187 | (MSC_RT_VLIO << 16) | \ | 191 | (MSC_RT_VLIO << 16) | \ | |
188 | ( 1 << MSC_RRR_SHIFT) | \ | 192 | ( 1 << MSC_RRR_SHIFT) | \ | |
189 | ( 2 << MSC_RDN_SHIFT) | \ | 193 | ( 2 << MSC_RDN_SHIFT) | \ | |
190 | ( 6 << MSC_RDF_SHIFT) | \ | 194 | ( 6 << MSC_RDF_SHIFT) | \ | |
191 | MSC_RT_VLIO | 195 | MSC_RT_VLIO | |
192 | #define MSC2_LOW \ | 196 | #define MSC2_LOW \ | |
193 | ( 7 << MSC_RRR_SHIFT << 16) | \ | 197 | ( 7 << MSC_RRR_SHIFT << 16) | \ | |
194 | (15 << MSC_RDN_SHIFT << 16) | \ | 198 | (15 << MSC_RDN_SHIFT << 16) | \ | |
195 | (15 << MSC_RDF_SHIFT << 16) | \ | 199 | (15 << MSC_RDF_SHIFT << 16) | \ | |
196 | (MSC_RT_NONBURST << 16) | \ | 200 | (MSC_RT_NONBURST << 16) | \ | |
197 | ( 1 << MSC_RRR_SHIFT) | \ | 201 | ( 1 << MSC_RRR_SHIFT) | \ | |
198 | ( 2 << MSC_RDN_SHIFT) | \ | 202 | ( 2 << MSC_RDN_SHIFT) | \ | |
199 | ( 6 << MSC_RDF_SHIFT) | \ | 203 | ( 6 << MSC_RDF_SHIFT) | \ | |
200 | MSC_RT_VLIO | 204 | MSC_RT_VLIO | |
201 | struct pxa2x0_memcfg pxa2x0_memcfg = { | 205 | struct pxa2x0_memcfg pxa2x0_memcfg = { | |
202 | (MDREFR_C3000 | 0x030), | 206 | (MDREFR_C3000 | 0x030), | |
203 | (MDREFR_C3000 | 0x00b), | 207 | (MDREFR_C3000 | 0x00b), | |
204 | (MDREFR_C3000 | 0x017), | 208 | (MDREFR_C3000 | 0x017), | |
205 | { MSC0_HIGH, MSC1_HIGH, MSC2_HIGH }, | 209 | { MSC0_HIGH, MSC1_HIGH, MSC2_HIGH }, | |
206 | { MSC1_LOW, MSC1_LOW, MSC2_LOW }, | 210 | { MSC1_LOW, MSC1_LOW, MSC2_LOW }, | |
207 | (MDREFR_C3000 | 0x013) | 211 | (MDREFR_C3000 | 0x013) | |
208 | }; | 212 | }; | |
209 | 213 | |||
210 | #define PI2C_RETRY_COUNT 10 | 214 | #define PI2C_RETRY_COUNT 10 | |
211 | /* XXX varies depending on voltage regulator IC. */ | 215 | /* XXX varies depending on voltage regulator IC. */ | |
212 | #define PI2C_VOLTAGE_LOW 0x13 /* 1.00V */ | 216 | #define PI2C_VOLTAGE_LOW 0x13 /* 1.00V */ | |
213 | #define PI2C_VOLTAGE_HIGH 0x1a /* 1.35V */ | 217 | #define PI2C_VOLTAGE_HIGH 0x1a /* 1.35V */ | |
214 | 218 | |||
215 | void pxa2x0_pi2c_open(bus_space_tag_t, bus_space_handle_t); | 219 | void pxa2x0_pi2c_open(bus_space_tag_t, bus_space_handle_t); | |
216 | void pxa2x0_pi2c_close(bus_space_tag_t, bus_space_handle_t); | 220 | void pxa2x0_pi2c_close(bus_space_tag_t, bus_space_handle_t); | |
217 | int pxa2x0_pi2c_read(bus_space_tag_t, bus_space_handle_t, u_char, u_char *); | 221 | int pxa2x0_pi2c_read(bus_space_tag_t, bus_space_handle_t, u_char, u_char *); | |
218 | int pxa2x0_pi2c_write(bus_space_tag_t, bus_space_handle_t, u_char, u_char); | 222 | int pxa2x0_pi2c_write(bus_space_tag_t, bus_space_handle_t, u_char, u_char); | |
219 | int pxa2x0_pi2c_getvoltage(bus_space_tag_t, bus_space_handle_t, u_char *); | 223 | int pxa2x0_pi2c_getvoltage(bus_space_tag_t, bus_space_handle_t, u_char *); | |
220 | int pxa2x0_pi2c_setvoltage(bus_space_tag_t, bus_space_handle_t, u_char); | 224 | int pxa2x0_pi2c_setvoltage(bus_space_tag_t, bus_space_handle_t, u_char); | |
221 | #if 0 | 225 | #if 0 | |
222 | void pxa2x0_pi2c_print(struct pxa2x0_apm_softc *); | 226 | void pxa2x0_pi2c_print(struct pxa2x0_apm_softc *); | |
223 | #endif | 227 | #endif | |
224 | 228 | |||
225 | /* XXX used in pxa2x0_apm_asm.S */ | 229 | /* XXX used in pxa2x0_apm_asm.S */ | |
226 | bus_space_handle_t pxa2x0_gpio_ioh; | 230 | bus_space_handle_t pxa2x0_gpio_ioh; | |
227 | bus_space_handle_t pxa2x0_clkman_ioh; | 231 | bus_space_handle_t pxa2x0_clkman_ioh; | |
228 | bus_space_handle_t pxa2x0_memctl_ioh; | 232 | bus_space_handle_t pxa2x0_memctl_ioh; | |
229 | 233 | |||
230 | /* pxa2x0_apm_asm.S */ | 234 | /* pxa2x0_apm_asm.S */ | |
231 | void pxa27x_run_mode(void); | 235 | void pxa27x_run_mode(void); | |
232 | void pxa27x_fastbus_run_mode(int, uint32_t); | 236 | void pxa27x_fastbus_run_mode(int, uint32_t); | |
233 | void pxa27x_frequency_change(int, int, struct pxa2x0_memcfg *); | 237 | void pxa27x_frequency_change(int, int, struct pxa2x0_memcfg *); | |
234 | void pxa2x0_cpu_suspend(void); | 238 | void pxa2x0_cpu_suspend(void); | |
235 | void pxa2x0_cpu_resume(void); | 239 | void pxa2x0_cpu_resume(void); | |
236 | void pxa27x_cpu_speed_high(void); | 240 | void pxa27x_cpu_speed_high(void); | |
237 | void pxa27x_cpu_speed_low(void); | 241 | void pxa27x_cpu_speed_low(void); | |
238 | void pxa27x_cpu_speed_91(void); | 242 | void pxa27x_cpu_speed_91(void); | |
239 | void pxa27x_cpu_speed_208(void); | 243 | void pxa27x_cpu_speed_208(void); | |
240 | 244 | |||
241 | void | 245 | void | |
242 | apm_power_print(struct pxa2x0_apm_softc *sc, struct apm_power_info *powerp) | 246 | apm_power_print(struct pxa2x0_apm_softc *sc, struct apm_power_info *powerp) | |
243 | { | 247 | { | |
244 | 248 | |||
245 | if (powerp->battery_life != APM_BATT_LIFE_UNKNOWN) | 249 | if (powerp->battery_life != APM_BATT_LIFE_UNKNOWN) | |
246 | printf("%s: battery life expectancy %d%%\n", | 250 | printf("%s: battery life expectancy %d%%\n", | |
247 | device_xname(sc->sc_dev), powerp->battery_life); | 251 | device_xname(sc->sc_dev), powerp->battery_life); | |
248 | 252 | |||
249 | printf("%s: AC ", device_xname(sc->sc_dev)); | 253 | printf("%s: AC ", device_xname(sc->sc_dev)); | |
250 | switch (powerp->ac_state) { | 254 | switch (powerp->ac_state) { | |
251 | case APM_AC_OFF: | 255 | case APM_AC_OFF: | |
252 | printf("off,"); | 256 | printf("off,"); | |
253 | break; | 257 | break; | |
254 | case APM_AC_ON: | 258 | case APM_AC_ON: | |
255 | printf("on,"); | 259 | printf("on,"); | |
256 | break; | 260 | break; | |
257 | case APM_AC_BACKUP: | 261 | case APM_AC_BACKUP: | |
258 | printf("backup power,"); | 262 | printf("backup power,"); | |
259 | break; | 263 | break; | |
260 | default: | 264 | default: | |
261 | case APM_AC_UNKNOWN: | 265 | case APM_AC_UNKNOWN: | |
262 | printf("unknown,"); | 266 | printf("unknown,"); | |
263 | break; | 267 | break; | |
264 | } | 268 | } | |
265 | 269 | |||
266 | printf(" battery is "); | 270 | printf(" battery is "); | |
267 | switch (powerp->battery_state) { | 271 | switch (powerp->battery_state) { | |
268 | case APM_BATT_HIGH: | 272 | case APM_BATT_HIGH: | |
269 | printf("high"); | 273 | printf("high"); | |
270 | break; | 274 | break; | |
271 | case APM_BATT_LOW: | 275 | case APM_BATT_LOW: | |
272 | printf("low"); | 276 | printf("low"); | |
273 | break; | 277 | break; | |
274 | case APM_BATT_CRITICAL: | 278 | case APM_BATT_CRITICAL: | |
275 | printf("CRITICAL"); | 279 | printf("CRITICAL"); | |
276 | break; | 280 | break; | |
277 | case APM_BATT_CHARGING: | 281 | case APM_BATT_CHARGING: | |
278 | printf("charging"); | 282 | printf("charging"); | |
279 | break; | 283 | break; | |
280 | case APM_BATT_UNKNOWN: | 284 | case APM_BATT_UNKNOWN: | |
281 | printf("unknown"); | 285 | printf("unknown"); | |
282 | break; | 286 | break; | |
283 | default: | 287 | default: | |
284 | printf("undecoded (%x)", powerp->battery_state); | 288 | printf("undecoded (%x)", powerp->battery_state); | |
285 | break; | 289 | break; | |
286 | } | 290 | } | |
287 | 291 | |||
288 | printf("\n"); | 292 | printf("\n"); | |
289 | } | 293 | } | |
290 | 294 | |||
291 | void | 295 | void | |
292 | apm_power_info(struct pxa2x0_apm_softc *sc, | 296 | apm_power_info(struct pxa2x0_apm_softc *sc, | |
293 | struct apm_power_info *power) | 297 | struct apm_power_info *power) | |
294 | { | 298 | { | |
295 | 299 | |||
296 | power->ac_state = APM_AC_UNKNOWN; | 300 | power->ac_state = APM_AC_UNKNOWN; | |
297 | power->battery_state = APM_BATT_UNKNOWN; | 301 | power->battery_state = APM_BATT_UNKNOWN; | |
298 | power->battery_life = 0 /* APM_BATT_LIFE_UNKNOWN */; | 302 | power->battery_life = 0 /* APM_BATT_LIFE_UNKNOWN */; | |
299 | power->minutes_left = 0; | 303 | power->minutes_left = 0; | |
300 | 304 | |||
301 | if (sc->sc_power_info != NULL) | 305 | if (sc->sc_power_info != NULL) | |
302 | sc->sc_power_info(sc, power); | 306 | sc->sc_power_info(sc, power); | |
303 | } | 307 | } | |
304 | 308 | |||
305 | void | 309 | void | |
306 | apm_suspend(struct pxa2x0_apm_softc *sc) | 310 | apm_suspend(struct pxa2x0_apm_softc *sc) | |
307 | { | 311 | { | |
308 | 312 | |||
309 | resettodr(); | 313 | resettodr(); | |
310 | 314 | |||
311 | dopowerhooks(PWR_SUSPEND); | 315 | dopowerhooks(PWR_SUSPEND); | |
312 | 316 | |||
313 | #if 0 | 317 | #if 0 | |
314 | if (cold) | 318 | if (cold) | |
315 | vfs_syncwait(0); | 319 | vfs_syncwait(0); | |
316 | #endif | 320 | #endif | |
317 | 321 | |||
318 | if (sc->sc_suspend == NULL) | 322 | if (sc->sc_suspend == NULL) | |
319 | pxa2x0_wakeup_config(PXA2X0_WAKEUP_ALL, 1); | 323 | pxa2x0_wakeup_config(PXA2X0_WAKEUP_ALL, 1); | |
320 | else | 324 | else | |
321 | sc->sc_suspend(sc); | 325 | sc->sc_suspend(sc); | |
322 | 326 | |||
323 | pxa2x0_apm_sleep(sc); | 327 | pxa2x0_apm_sleep(sc); | |
324 | } | 328 | } | |
325 | 329 | |||
326 | void | 330 | void | |
327 | apm_resume(struct pxa2x0_apm_softc *sc) | 331 | apm_resume(struct pxa2x0_apm_softc *sc) | |
328 | { | 332 | { | |
329 | 333 | |||
330 | dopowerhooks(PWR_RESUME); | 334 | dopowerhooks(PWR_RESUME); | |
331 | 335 | |||
332 | inittodr(0); | 336 | inittodr(0); | |
333 | 337 | |||
334 | /* | 338 | /* | |
335 | * Clear the OTG Peripheral hold after running the pxaudc and pxaohci | 339 | * Clear the OTG Peripheral hold after running the pxaudc and pxaohci | |
336 | * powerhooks to re-enable their operation. See 3.8.1.2 | 340 | * powerhooks to re-enable their operation. See 3.8.1.2 | |
337 | */ | 341 | */ | |
338 | /* XXX ifdef NPXAUDC > 0 */ | 342 | /* XXX ifdef NPXAUDC > 0 */ | |
339 | bus_space_write_4(sc->sc_iot, sc->sc_pm_ioh, POWMAN_PSSR, PSSR_OTGPH); | 343 | bus_space_write_4(sc->sc_iot, sc->sc_pm_ioh, POWMAN_PSSR, PSSR_OTGPH); | |
340 | } | 344 | } | |
341 | 345 | |||
342 | #if 0 | 346 | #if 0 | |
343 | int | 347 | int | |
344 | apm_get_event(struct pxa2x0_apm_softc *sc, u_int *typep) | 348 | apm_get_event(struct pxa2x0_apm_softc *sc, u_int *typep) | |
345 | { | 349 | { | |
346 | 350 | |||
347 | if (sc->sc_get_event != NULL) | 351 | if (sc->sc_get_event != NULL) | |
348 | return (sc->sc_get_event(sc, typep)); | 352 | return (sc->sc_get_event(sc, typep)); | |
349 | 353 | |||
350 | *typep = APM_NOEVENT; | 354 | *typep = APM_NOEVENT; | |
351 | return (1); | 355 | return (1); | |
352 | } | 356 | } | |
353 | 357 | |||
354 | int | 358 | int | |
355 | apm_handle_event(struct pxa2x0_apm_softc *sc, u_int type) | 359 | apm_handle_event(struct pxa2x0_apm_softc *sc, u_int type) | |
356 | { | 360 | { | |
357 | struct apm_power_info power; | 361 | struct apm_power_info power; | |
358 | int ret = 0; | 362 | int ret = 0; | |
359 | 363 | |||
360 | switch (type) { | 364 | switch (type) { | |
361 | case APM_NOEVENT: | 365 | case APM_NOEVENT: | |
362 | ret = 1; | 366 | ret = 1; | |
363 | break; | 367 | break; | |
364 | case APM_CRIT_SUSPEND_REQ: | 368 | case APM_CRIT_SUSPEND_REQ: | |
365 | DPRINTF(("suspend required immediately\n")); | 369 | DPRINTF(("suspend required immediately\n")); | |
366 | #if 0 | 370 | #if 0 | |
367 | /* XXX apmd would make us suspend again after resume. */ | 371 | /* XXX apmd would make us suspend again after resume. */ | |
368 | (void)apm_record_event(sc, type); | 372 | (void)apm_record_event(sc, type); | |
369 | #endif | 373 | #endif | |
370 | /* | 374 | /* | |
371 | * We ignore APM_CRIT_RESUME and just suspend here as usual | 375 | * We ignore APM_CRIT_RESUME and just suspend here as usual | |
372 | * to simplify the actual apm_get_event() implementation. | 376 | * to simplify the actual apm_get_event() implementation. | |
373 | */ | 377 | */ | |
374 | apm_suspends++; | 378 | apm_suspends++; | |
375 | ret = 1; | 379 | ret = 1; | |
376 | break; | 380 | break; | |
377 | case APM_USER_SUSPEND_REQ: | 381 | case APM_USER_SUSPEND_REQ: | |
378 | case APM_SUSPEND_REQ: | 382 | case APM_SUSPEND_REQ: | |
379 | DPRINTF(("suspend requested\n")); | 383 | DPRINTF(("suspend requested\n")); | |
380 | if (apm_record_event(sc, type)) { | 384 | if (apm_record_event(sc, type)) { | |
381 | DPRINTF(("suspend ourselves\n")); | 385 | DPRINTF(("suspend ourselves\n")); | |
382 | apm_suspends++; | 386 | apm_suspends++; | |
383 | } | 387 | } | |
384 | break; | 388 | break; | |
385 | case APM_POWER_CHANGE: | 389 | case APM_POWER_CHANGE: | |
386 | DPRINTF(("power status change\n")); | 390 | DPRINTF(("power status change\n")); | |
387 | apm_power_info(sc, &power); | 391 | apm_power_info(sc, &power); | |
388 | if (power.battery_life != APM_BATT_LIFE_UNKNOWN && | 392 | if (power.battery_life != APM_BATT_LIFE_UNKNOWN && | |
389 | power.battery_life < cpu_apmwarn && | 393 | power.battery_life < cpu_apmwarn && | |
390 | (sc->sc_flags & SCFLAG_PRINT) != SCFLAG_NOPRINT && | 394 | (sc->sc_flags & SCFLAG_PRINT) != SCFLAG_NOPRINT && | |
391 | ((sc->sc_flags & SCFLAG_PRINT) != SCFLAG_PCTPRINT || | 395 | ((sc->sc_flags & SCFLAG_PRINT) != SCFLAG_PCTPRINT || | |
392 | sc->sc_batt_life != power.battery_life)) { | 396 | sc->sc_batt_life != power.battery_life)) { | |
393 | sc->sc_batt_life = power.battery_life; | 397 | sc->sc_batt_life = power.battery_life; | |
394 | apm_power_print(sc, &power); | 398 | apm_power_print(sc, &power); | |
395 | } | 399 | } | |
396 | apm_record_event(sc, type); | 400 | apm_record_event(sc, type); | |
397 | break; | 401 | break; | |
398 | case APM_BATTERY_LOW: | 402 | case APM_BATTERY_LOW: | |
399 | DPRINTF(("Battery low!\n")); | 403 | DPRINTF(("Battery low!\n")); | |
400 | apm_battlow++; | 404 | apm_battlow++; | |
401 | apm_record_event(sc, type); | 405 | apm_record_event(sc, type); | |
402 | break; | 406 | break; | |
403 | default: | 407 | default: | |
404 | DPRINTF(("apm_handle_event: unsupported event, code %d\n", | 408 | DPRINTF(("apm_handle_event: unsupported event, code %d\n", | |
405 | type)); | 409 | type)); | |
406 | } | 410 | } | |
407 | 411 | |||
408 | return (ret); | 412 | return (ret); | |
409 | } | 413 | } | |
410 | 414 | |||
411 | void | 415 | void | |
412 | apm_thread_create(void *v) | 416 | apm_thread_create(void *v) | |
413 | { | 417 | { | |
414 | struct pxa2x0_apm_softc *sc = v; | 418 | struct pxa2x0_apm_softc *sc = v; | |
415 | 419 | |||
416 | if (kthread_create(apm_thread, sc, &sc->sc_thread, | 420 | if (kthread_create(apm_thread, sc, &sc->sc_thread, | |
417 | "%s", device_xname(sc->sc_dev))) { | 421 | "%s", device_xname(sc->sc_dev))) { | |
418 | /* apm_disconnect(sc); */ | 422 | /* apm_disconnect(sc); */ | |
419 | printf("%s: failed to create kernel thread, disabled", | 423 | printf("%s: failed to create kernel thread, disabled", | |
420 | device_xname(sc->sc_dev)); | 424 | device_xname(sc->sc_dev)); | |
421 | } | 425 | } | |
422 | } | 426 | } | |
423 | 427 | |||
424 | void | 428 | void | |
425 | apm_thread(void *v) | 429 | apm_thread(void *v) | |
426 | { | 430 | { | |
427 | struct pxa2x0_apm_softc *sc = v; | 431 | struct pxa2x0_apm_softc *sc = v; | |
428 | u_int type; | 432 | u_int type; | |
429 | 433 | |||
430 | for (;;) { | 434 | for (;;) { | |
431 | APM_LOCK(sc); | 435 | APM_LOCK(sc); | |
432 | 436 | |||
433 | while (1) { | 437 | while (1) { | |
434 | if (apm_get_event(sc, &type) != 0) | 438 | if (apm_get_event(sc, &type) != 0) | |
435 | break; | 439 | break; | |
436 | if (apm_handle_event(sc, type) != 0) | 440 | if (apm_handle_event(sc, type) != 0) | |
437 | break; | 441 | break; | |
438 | } | 442 | } | |
439 | if (apm_suspends || apm_userstandbys /* || apm_battlow*/) { | 443 | if (apm_suspends || apm_userstandbys /* || apm_battlow*/) { | |
440 | apm_suspend(sc); | 444 | apm_suspend(sc); | |
441 | apm_resume(sc); | 445 | apm_resume(sc); | |
442 | } | 446 | } | |
443 | apm_battlow = apm_suspends = apm_userstandbys = 0; | 447 | apm_battlow = apm_suspends = apm_userstandbys = 0; | |
444 | 448 | |||
445 | APM_UNLOCK(sc); | 449 | APM_UNLOCK(sc); | |
446 | kpause("apmev", false, hz, NULL); | 450 | kpause("apmev", false, hz, NULL); | |
447 | } | 451 | } | |
448 | } | 452 | } | |
449 | 453 | |||
450 | int | 454 | int | |
451 | apmopen(dev_t dev, int flag, int mode, struct proc *p) | 455 | apmopen(dev_t dev, int flag, int mode, struct proc *p) | |
452 | { | 456 | { | |
453 | struct pxa2x0_apm_softc *sc; | 457 | struct pxa2x0_apm_softc *sc; | |
454 | int error = 0; | 458 | int error = 0; | |
455 | 459 | |||
456 | /* apm0 only */ | 460 | /* apm0 only */ | |
457 | if (!zapm_cd.cd_ndevs || APMUNIT(dev) != 0 || | 461 | if (!zapm_cd.cd_ndevs || APMUNIT(dev) != 0 || | |
458 | !(sc = zapm_cd.cd_devs[APMUNIT(dev)])) | 462 | !(sc = zapm_cd.cd_devs[APMUNIT(dev)])) | |
459 | return (ENXIO); | 463 | return (ENXIO); | |
460 | 464 | |||
461 | DPRINTF(("apmopen: dev %d pid %d flag %x mode %x\n", | 465 | DPRINTF(("apmopen: dev %d pid %d flag %x mode %x\n", | |
462 | APMDEV(dev), p->p_pid, flag, mode)); | 466 | APMDEV(dev), p->p_pid, flag, mode)); | |
463 | 467 | |||
464 | switch (APMDEV(dev)) { | 468 | switch (APMDEV(dev)) { | |
465 | case APMDEV_CTL: | 469 | case APMDEV_CTL: | |
466 | if (!(flag & FWRITE)) { | 470 | if (!(flag & FWRITE)) { | |
467 | error = EINVAL; | 471 | error = EINVAL; | |
468 | break; | 472 | break; | |
469 | } | 473 | } | |
470 | if (sc->sc_flags & SCFLAG_OWRITE) { | 474 | if (sc->sc_flags & SCFLAG_OWRITE) { | |
471 | error = EBUSY; | 475 | error = EBUSY; | |
472 | break; | 476 | break; | |
473 | } | 477 | } | |
474 | sc->sc_flags |= SCFLAG_OWRITE; | 478 | sc->sc_flags |= SCFLAG_OWRITE; | |
475 | break; | 479 | break; | |
476 | case APMDEV_NORMAL: | 480 | case APMDEV_NORMAL: | |
477 | if (!(flag & FREAD) || (flag & FWRITE)) { | 481 | if (!(flag & FREAD) || (flag & FWRITE)) { | |
478 | error = EINVAL; | 482 | error = EINVAL; | |
479 | break; | 483 | break; | |
480 | } | 484 | } | |
481 | sc->sc_flags |= SCFLAG_OREAD; | 485 | sc->sc_flags |= SCFLAG_OREAD; | |
482 | break; | 486 | break; | |
483 | default: | 487 | default: | |
484 | error = ENXIO; | 488 | error = ENXIO; | |
485 | break; | 489 | break; | |
486 | } | 490 | } | |
487 | return (error); | 491 | return (error); | |
488 | } | 492 | } | |
489 | 493 | |||
490 | int | 494 | int | |
491 | apmclose(dev_t dev, int flag, int mode, struct proc *p) | 495 | apmclose(dev_t dev, int flag, int mode, struct proc *p) | |
492 | { | 496 | { | |
493 | struct pxa2x0_apm_softc *sc; | 497 | struct pxa2x0_apm_softc *sc; | |
494 | 498 | |||
495 | /* apm0 only */ | 499 | /* apm0 only */ | |
496 | if (!apm_cd.cd_ndevs || APMUNIT(dev) != 0 || | 500 | if (!apm_cd.cd_ndevs || APMUNIT(dev) != 0 || | |
497 | !(sc = apm_cd.cd_devs[APMUNIT(dev)])) | 501 | !(sc = apm_cd.cd_devs[APMUNIT(dev)])) | |
498 | return (ENXIO); | 502 | return (ENXIO); | |
499 | 503 | |||
500 | DPRINTF(("apmclose: pid %d flag %x mode %x\n", p->p_pid, flag, mode)); | 504 | DPRINTF(("apmclose: pid %d flag %x mode %x\n", p->p_pid, flag, mode)); | |
501 | 505 | |||
502 | switch (APMDEV(dev)) { | 506 | switch (APMDEV(dev)) { | |
503 | case APMDEV_CTL: | 507 | case APMDEV_CTL: | |
504 | sc->sc_flags &= ~SCFLAG_OWRITE; | 508 | sc->sc_flags &= ~SCFLAG_OWRITE; | |
505 | break; | 509 | break; | |
506 | case APMDEV_NORMAL: | 510 | case APMDEV_NORMAL: | |
507 | sc->sc_flags &= ~SCFLAG_OREAD; | 511 | sc->sc_flags &= ~SCFLAG_OREAD; | |
508 | break; | 512 | break; | |
509 | } | 513 | } | |
510 | return (0); | 514 | return (0); | |
511 | } | 515 | } | |
512 | 516 | |||
513 | int | 517 | int | |
514 | apmioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) | 518 | apmioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) | |
515 | { | 519 | { | |
516 | struct pxa2x0_apm_softc *sc; | 520 | struct pxa2x0_apm_softc *sc; | |
517 | struct apm_power_info *power; | 521 | struct apm_power_info *power; | |
518 | int error = 0; | 522 | int error = 0; | |
519 | 523 | |||
520 | /* apm0 only */ | 524 | /* apm0 only */ | |
521 | if (!apm_cd.cd_ndevs || APMUNIT(dev) != 0 || | 525 | if (!apm_cd.cd_ndevs || APMUNIT(dev) != 0 || | |
522 | !(sc = apm_cd.cd_devs[APMUNIT(dev)])) | 526 | !(sc = apm_cd.cd_devs[APMUNIT(dev)])) | |
523 | return (ENXIO); | 527 | return (ENXIO); | |
524 | 528 | |||
525 | switch (cmd) { | 529 | switch (cmd) { | |
526 | /* some ioctl names from linux */ | 530 | /* some ioctl names from linux */ | |
527 | case APM_IOC_STANDBY: | 531 | case APM_IOC_STANDBY: | |
528 | if ((flag & FWRITE) == 0) | 532 | if ((flag & FWRITE) == 0) | |
529 | error = EBADF; | 533 | error = EBADF; | |
530 | else | 534 | else | |
531 | apm_userstandbys++; | 535 | apm_userstandbys++; | |
532 | break; | 536 | break; | |
533 | case APM_IOC_SUSPEND: | 537 | case APM_IOC_SUSPEND: | |
534 | if ((flag & FWRITE) == 0) | 538 | if ((flag & FWRITE) == 0) | |
535 | error = EBADF; | 539 | error = EBADF; | |
536 | else | 540 | else | |
537 | apm_suspends++; /* XXX */ | 541 | apm_suspends++; /* XXX */ | |
538 | break; | 542 | break; | |
539 | case APM_IOC_PRN_CTL: | 543 | case APM_IOC_PRN_CTL: | |
540 | if ((flag & FWRITE) == 0) | 544 | if ((flag & FWRITE) == 0) | |
541 | error = EBADF; | 545 | error = EBADF; | |
542 | else { | 546 | else { | |
543 | int flag = *(int *)data; | 547 | int flag = *(int *)data; | |
544 | DPRINTF(( "APM_IOC_PRN_CTL: %d\n", flag )); | 548 | DPRINTF(( "APM_IOC_PRN_CTL: %d\n", flag )); | |
545 | switch (flag) { | 549 | switch (flag) { | |
546 | case APM_PRINT_ON: /* enable printing */ | 550 | case APM_PRINT_ON: /* enable printing */ | |
547 | sc->sc_flags &= ~SCFLAG_PRINT; | 551 | sc->sc_flags &= ~SCFLAG_PRINT; | |
548 | break; | 552 | break; | |
549 | case APM_PRINT_OFF: /* disable printing */ | 553 | case APM_PRINT_OFF: /* disable printing */ | |
550 | sc->sc_flags &= ~SCFLAG_PRINT; | 554 | sc->sc_flags &= ~SCFLAG_PRINT; | |
551 | sc->sc_flags |= SCFLAG_NOPRINT; | 555 | sc->sc_flags |= SCFLAG_NOPRINT; | |
552 | break; | 556 | break; | |
553 | case APM_PRINT_PCT: /* disable some printing */ | 557 | case APM_PRINT_PCT: /* disable some printing */ | |
554 | sc->sc_flags &= ~SCFLAG_PRINT; | 558 | sc->sc_flags &= ~SCFLAG_PRINT; | |
555 | sc->sc_flags |= SCFLAG_PCTPRINT; | 559 | sc->sc_flags |= SCFLAG_PCTPRINT; | |
556 | break; | 560 | break; | |
557 | default: | 561 | default: | |
558 | error = EINVAL; | 562 | error = EINVAL; | |
559 | break; | 563 | break; | |
560 | } | 564 | } | |
561 | } | 565 | } | |
562 | break; | 566 | break; | |
563 | case APM_IOC_DEV_CTL: | 567 | case APM_IOC_DEV_CTL: | |
564 | if ((flag & FWRITE) == 0) | 568 | if ((flag & FWRITE) == 0) | |
565 | error = EBADF; | 569 | error = EBADF; | |
566 | break; | 570 | break; | |
567 | case APM_IOC_GETPOWER: | 571 | case APM_IOC_GETPOWER: | |
568 | power = (struct apm_power_info *)data; | 572 | power = (struct apm_power_info *)data; | |
569 | apm_power_info(sc, power); | 573 | apm_power_info(sc, power); | |
570 | break; | 574 | break; | |
571 | 575 | |||
572 | default: | 576 | default: | |
573 | error = ENOTTY; | 577 | error = ENOTTY; | |
574 | } | 578 | } | |
575 | 579 | |||
576 | return (error); | 580 | return (error); | |
577 | } | 581 | } | |
578 | 582 | |||
579 | int | 583 | int | |
580 | apm_record_event(struct pxa2x0_apm_softc *sc, u_int type) | 584 | apm_record_event(struct pxa2x0_apm_softc *sc, u_int type) | |
581 | { | 585 | { | |
582 | static int apm_evindex; | 586 | static int apm_evindex; | |
583 | 587 | |||
584 | /* skip if no user waiting */ | 588 | /* skip if no user waiting */ | |
585 | if ((sc->sc_flags & SCFLAG_OPEN) == 0) | 589 | if ((sc->sc_flags & SCFLAG_OPEN) == 0) | |
586 | return (1); | 590 | return (1); | |
587 | 591 | |||
588 | apm_evindex++; | 592 | apm_evindex++; | |
589 | KNOTE(&sc->sc_note, APM_EVENT_COMPOSE(type, apm_evindex)); | 593 | KNOTE(&sc->sc_note, APM_EVENT_COMPOSE(type, apm_evindex)); | |
590 | 594 | |||
591 | return (0); | 595 | return (0); | |
592 | } | 596 | } | |
593 | 597 | |||
594 | void | 598 | void | |
595 | filt_apmrdetach(struct knote *kn) | 599 | filt_apmrdetach(struct knote *kn) | |
596 | { | 600 | { | |
597 | struct pxa2x0_apm_softc *sc = | 601 | struct pxa2x0_apm_softc *sc = | |
598 | (struct pxa2x0_apm_softc *)kn->kn_hook; | 602 | (struct pxa2x0_apm_softc *)kn->kn_hook; | |
599 | 603 | |||
600 | SLIST_REMOVE(&sc->sc_note, kn, knote, kn_selnext); | 604 | SLIST_REMOVE(&sc->sc_note, kn, knote, kn_selnext); | |
601 | } | 605 | } | |
602 | 606 | |||
603 | int | 607 | int | |
604 | filt_apmread(struct knote *kn, long hint) | 608 | filt_apmread(struct knote *kn, long hint) | |
605 | { | 609 | { | |
606 | /* XXX weird kqueue_scan() semantics */ | 610 | /* XXX weird kqueue_scan() semantics */ | |
607 | if (hint && !kn->kn_data) | 611 | if (hint && !kn->kn_data) | |
608 | kn->kn_data = (int)hint; | 612 | kn->kn_data = (int)hint; | |
609 | 613 | |||
610 | return (1); | 614 | return (1); | |
611 | } | 615 | } | |
612 | 616 | |||
613 | int | 617 | int | |
614 | apmkqfilter(dev_t dev, struct knote *kn) | 618 | apmkqfilter(dev_t dev, struct knote *kn) | |
615 | { | 619 | { | |
616 | struct pxa2x0_apm_softc *sc; | 620 | struct pxa2x0_apm_softc *sc; | |
617 | 621 | |||
618 | /* apm0 only */ | 622 | /* apm0 only */ | |
619 | if (!apm_cd.cd_ndevs || APMUNIT(dev) != 0 || | 623 | if (!apm_cd.cd_ndevs || APMUNIT(dev) != 0 || | |
620 | !(sc = apm_cd.cd_devs[APMUNIT(dev)])) | 624 | !(sc = apm_cd.cd_devs[APMUNIT(dev)])) | |
621 | return (ENXIO); | 625 | return (ENXIO); | |
622 | 626 | |||
623 | switch (kn->kn_filter) { | 627 | switch (kn->kn_filter) { | |
624 | case EVFILT_READ: | 628 | case EVFILT_READ: | |
625 | kn->kn_fop = &apmread_filtops; | 629 | kn->kn_fop = &apmread_filtops; | |
626 | break; | 630 | break; | |
627 | default: | 631 | default: | |
628 | return (1); | 632 | return (1); | |
629 | } | 633 | } | |
630 | 634 | |||
631 | kn->kn_hook = (caddr_t)sc; | 635 | kn->kn_hook = (caddr_t)sc; | |
632 | SLIST_INSERT_HEAD(&sc->sc_note, kn, kn_selnext); | 636 | SLIST_INSERT_HEAD(&sc->sc_note, kn, kn_selnext); | |
633 | 637 | |||
634 | return (0); | 638 | return (0); | |
635 | } | 639 | } | |
636 | 640 | |||
637 | void | 641 | void | |
638 | pxa2x0_apm_attach_sub(struct pxa2x0_apm_softc *sc) | 642 | pxa2x0_apm_attach_sub(struct pxa2x0_apm_softc *sc) | |
639 | { | 643 | { | |
640 | 644 | |||
641 | sc->sc_iot = &pxa2x0_bs_tag; | 645 | sc->sc_iot = &pxa2x0_bs_tag; | |
642 | 646 | |||
643 | if (bus_space_map(sc->sc_iot, PXA2X0_POWMAN_BASE, | 647 | if (bus_space_map(sc->sc_iot, PXA2X0_POWMAN_BASE, | |
644 | PXA2X0_POWMAN_SIZE, 0, &sc->sc_pm_ioh)) { | 648 | PXA2X0_POWMAN_SIZE, 0, &sc->sc_pm_ioh)) { | |
645 | printf("pxa2x0_apm_attach_sub: failed to map POWMAN\n"); | 649 | printf("pxa2x0_apm_attach_sub: failed to map POWMAN\n"); | |
646 | return; | 650 | return; | |
647 | } | 651 | } | |
648 | 652 | |||
649 | lockinit(&sc->sc_lock, PWAIT, "apmlk", 0, 0); | 653 | lockinit(&sc->sc_lock, PWAIT, "apmlk", 0, 0); | |
650 | 654 | |||
651 | kthread_create_deferred(apm_thread_create, sc); | 655 | kthread_create_deferred(apm_thread_create, sc); | |
652 | 656 | |||
653 | printf("\n"); | 657 | printf("\n"); | |
654 | 658 | |||
655 | if (bus_space_map(sc->sc_iot, PXA2X0_CLKMAN_BASE, PXA2X0_CLKMAN_SIZE, | 659 | if (bus_space_map(sc->sc_iot, PXA2X0_CLKMAN_BASE, PXA2X0_CLKMAN_SIZE, | |
656 | 0, &pxa2x0_clkman_ioh)) { | 660 | 0, &pxa2x0_clkman_ioh)) { | |
657 | printf("%s: failed to map CLKMAN\n", device_xname(sc->sc_dev)); | 661 | printf("%s: failed to map CLKMAN\n", device_xname(sc->sc_dev)); | |
658 | return; | 662 | return; | |
659 | } | 663 | } | |
660 | 664 | |||
661 | if (bus_space_map(sc->sc_iot, PXA2X0_MEMCTL_BASE, PXA2X0_MEMCTL_SIZE, | 665 | if (bus_space_map(sc->sc_iot, PXA2X0_MEMCTL_BASE, PXA2X0_MEMCTL_SIZE, | |
662 | 0, &pxa2x0_memctl_ioh)) { | 666 | 0, &pxa2x0_memctl_ioh)) { | |
663 | printf("%s: failed to map MEMCTL\n", device_xname(sc->sc_dev)); | 667 | printf("%s: failed to map MEMCTL\n", device_xname(sc->sc_dev)); | |
664 | return; | 668 | return; | |
665 | } | 669 | } | |
666 | sc->sc_memctl_ioh = pxa2x0_memctl_ioh; | 670 | sc->sc_memctl_ioh = pxa2x0_memctl_ioh; | |
667 | 671 | |||
668 | if (bus_space_map(sc->sc_iot, PXA2X0_GPIO_BASE, PXA2X0_GPIO_SIZE, | 672 | if (bus_space_map(sc->sc_iot, PXA2X0_GPIO_BASE, PXA2X0_GPIO_SIZE, | |
669 | 0, &pxa2x0_gpio_ioh)) { | 673 | 0, &pxa2x0_gpio_ioh)) { | |
670 | printf("%s: can't map GPIO\n", device_xname(sc->sc_dev)); | 674 | printf("%s: can't map GPIO\n", device_xname(sc->sc_dev)); | |
671 | return; | 675 | return; | |
672 | } | 676 | } | |
673 | 677 | |||
674 | /* Clear all reset status flags. */ | 678 | /* Clear all reset status flags. */ | |
675 | bus_space_write_4(sc->sc_iot, sc->sc_pm_ioh, POWMAN_RCSR, | 679 | bus_space_write_4(sc->sc_iot, sc->sc_pm_ioh, POWMAN_RCSR, | |
676 | RCSR_GPR | RCSR_SMR | RCSR_WDR | RCSR_HWR); | 680 | RCSR_GPR | RCSR_SMR | RCSR_WDR | RCSR_HWR); | |
677 | } | 681 | } | |
678 | #endif /* 0 */ | 682 | #endif /* 0 */ | |
679 | 683 | |||
680 | void | 684 | void | |
681 | pxa2x0_wakeup_config(u_int wsrc, int enable) | 685 | pxa2x0_wakeup_config(u_int wsrc, int enable) | |
682 | { | 686 | { | |
683 | struct pxa2x0_apm_softc *sc; | 687 | struct pxa2x0_apm_softc *sc; | |
684 | uint32_t prer; | 688 | uint32_t prer; | |
685 | uint32_t pfer; | 689 | uint32_t pfer; | |
686 | uint32_t pkwr; | 690 | uint32_t pkwr; | |
687 | 691 | |||
688 | if (zapm_cd.cd_ndevs < 1 || zapm_cd.cd_devs[0] == NULL) | 692 | if (zapm_cd.cd_ndevs < 1 || zapm_cd.cd_devs[0] == NULL) | |
689 | return; | 693 | return; | |
690 | sc = device_private(zapm_cd.cd_devs[0]); | 694 | sc = device_private(zapm_cd.cd_devs[0]); | |
691 | 695 | |||
692 | prer = pfer = pkwr = 0; | 696 | prer = pfer = pkwr = 0; | |
693 | 697 | |||
694 | if ((wsrc & PXA2X0_WAKEUP_POWERON) != 0) { | 698 | if ((wsrc & PXA2X0_WAKEUP_POWERON) != 0) { | |
695 | prer |= (1<<0); | 699 | prer |= (1<<0); | |
696 | pfer |= (1<<0); | 700 | pfer |= (1<<0); | |
697 | pkwr |= (1<<12); /* XXX */ | 701 | pkwr |= (1<<12); /* XXX */ | |
698 | } | 702 | } | |
699 | 703 | |||
700 | if ((wsrc & PXA2X0_WAKEUP_GPIORST) != 0) | 704 | if ((wsrc & PXA2X0_WAKEUP_GPIORST) != 0) | |
701 | pfer |= (1<<1); | 705 | pfer |= (1<<1); | |
702 | if ((wsrc & PXA2X0_WAKEUP_SD) != 0) | 706 | if ((wsrc & PXA2X0_WAKEUP_SD) != 0) | |
703 | prer |= (1<<9); | 707 | prer |= (1<<9); | |
704 | if ((wsrc & PXA2X0_WAKEUP_RC) != 0) | 708 | if ((wsrc & PXA2X0_WAKEUP_RC) != 0) | |
705 | prer |= (1<<13); | 709 | prer |= (1<<13); | |
706 | if ((wsrc & PXA2X0_WAKEUP_SYNC) != 0) | 710 | if ((wsrc & PXA2X0_WAKEUP_SYNC) != 0) | |
707 | pkwr |= (1<<1); | 711 | pkwr |= (1<<1); | |
708 | if ((wsrc & PXA2X0_WAKEUP_KEYNS0) != 0) | 712 | if ((wsrc & PXA2X0_WAKEUP_KEYNS0) != 0) | |
709 | prer |= (1<<12); | 713 | prer |= (1<<12); | |
710 | if ((wsrc & PXA2X0_WAKEUP_KEYNS1) != 0) | 714 | if ((wsrc & PXA2X0_WAKEUP_KEYNS1) != 0) | |
711 | pkwr |= (1<<2); | 715 | pkwr |= (1<<2); | |
712 | if ((wsrc & PXA2X0_WAKEUP_KEYNS2) != 0) | 716 | if ((wsrc & PXA2X0_WAKEUP_KEYNS2) != 0) | |
713 | pkwr |= (1<<9); | 717 | pkwr |= (1<<9); | |
714 | if ((wsrc & PXA2X0_WAKEUP_KEYNS3) != 0) | 718 | if ((wsrc & PXA2X0_WAKEUP_KEYNS3) != 0) | |
715 | pkwr |= (1<<3); | 719 | pkwr |= (1<<3); | |
716 | if ((wsrc & PXA2X0_WAKEUP_KEYNS4) != 0) | 720 | if ((wsrc & PXA2X0_WAKEUP_KEYNS4) != 0) | |
717 | pkwr |= (1<<4); | 721 | pkwr |= (1<<4); | |
718 | if ((wsrc & PXA2X0_WAKEUP_KEYNS5) != 0) | 722 | if ((wsrc & PXA2X0_WAKEUP_KEYNS5) != 0) | |
719 | pkwr |= (1<<6); | 723 | pkwr |= (1<<6); | |
720 | if ((wsrc & PXA2X0_WAKEUP_KEYNS6) != 0) | 724 | if ((wsrc & PXA2X0_WAKEUP_KEYNS6) != 0) | |
721 | pkwr |= (1<<7); | 725 | pkwr |= (1<<7); | |
722 | if ((wsrc & PXA2X0_WAKEUP_CF0) != 0) | 726 | if ((wsrc & PXA2X0_WAKEUP_CF0) != 0) | |
723 | pkwr |= (1<<11); | 727 | pkwr |= (1<<11); | |
724 | if ((wsrc & PXA2X0_WAKEUP_CF1) != 0) | 728 | if ((wsrc & PXA2X0_WAKEUP_CF1) != 0) | |
725 | pkwr |= (1<<10); | 729 | pkwr |= (1<<10); | |
726 | if ((wsrc & PXA2X0_WAKEUP_USBD) != 0) | 730 | if ((wsrc & PXA2X0_WAKEUP_USBD) != 0) | |
727 | prer |= (1<<24); | 731 | prer |= (1<<24); | |
728 | 732 | |||
729 | if ((wsrc & PXA2X0_WAKEUP_LOCKSW) != 0) { | 733 | if ((wsrc & PXA2X0_WAKEUP_LOCKSW) != 0) { | |
730 | prer |= (1<<15); | 734 | prer |= (1<<15); | |
731 | pfer |= (1<<15); | 735 | pfer |= (1<<15); | |
732 | } | 736 | } | |
733 | 737 | |||
734 | if ((wsrc & PXA2X0_WAKEUP_JACKIN) != 0) { | 738 | if ((wsrc & PXA2X0_WAKEUP_JACKIN) != 0) { | |
735 | prer |= (1<<23); | 739 | prer |= (1<<23); | |
736 | pfer |= (1<<23); | 740 | pfer |= (1<<23); | |
737 | } | 741 | } | |
738 | 742 | |||
739 | if ((wsrc & PXA2X0_WAKEUP_CHRGFULL) != 0) | 743 | if ((wsrc & PXA2X0_WAKEUP_CHRGFULL) != 0) | |
740 | pkwr |= (1<<18); | 744 | pkwr |= (1<<18); | |
741 | if ((wsrc & PXA2X0_WAKEUP_RTC) != 0) | 745 | if ((wsrc & PXA2X0_WAKEUP_RTC) != 0) | |
742 | prer |= (1<<31); | 746 | prer |= (1<<31); | |
743 | 747 | |||
744 | if (enable) { | 748 | if (enable) { | |
745 | sc->sc_wakeon |= wsrc; | 749 | sc->sc_wakeon |= wsrc; | |
746 | prer |= bus_space_read_4(sc->sc_iot, sc->sc_pm_ioh, | 750 | prer |= bus_space_read_4(sc->sc_iot, sc->sc_pm_ioh, | |
747 | POWMAN_PRER); | 751 | POWMAN_PRER); | |
748 | pfer |= bus_space_read_4(sc->sc_iot, sc->sc_pm_ioh, | 752 | pfer |= bus_space_read_4(sc->sc_iot, sc->sc_pm_ioh, | |
749 | POWMAN_PFER); | 753 | POWMAN_PFER); | |
750 | pkwr |= bus_space_read_4(sc->sc_iot, sc->sc_pm_ioh, | 754 | pkwr |= bus_space_read_4(sc->sc_iot, sc->sc_pm_ioh, | |
751 | POWMAN_PKWR); | 755 | POWMAN_PKWR); | |
752 | } else { | 756 | } else { | |
753 | sc->sc_wakeon &= ~wsrc; | 757 | sc->sc_wakeon &= ~wsrc; | |
754 | prer = bus_space_read_4(sc->sc_iot, sc->sc_pm_ioh, | 758 | prer = bus_space_read_4(sc->sc_iot, sc->sc_pm_ioh, | |
755 | POWMAN_PRER) & ~prer; | 759 | POWMAN_PRER) & ~prer; | |
756 | pfer = bus_space_read_4(sc->sc_iot, sc->sc_pm_ioh, | 760 | pfer = bus_space_read_4(sc->sc_iot, sc->sc_pm_ioh, | |
757 | POWMAN_PFER) & ~pfer; | 761 | POWMAN_PFER) & ~pfer; | |
758 | pkwr = bus_space_read_4(sc->sc_iot, sc->sc_pm_ioh, | 762 | pkwr = bus_space_read_4(sc->sc_iot, sc->sc_pm_ioh, | |
759 | POWMAN_PKWR) & ~pkwr; | 763 | POWMAN_PKWR) & ~pkwr; | |
760 | } | 764 | } | |
761 | 765 | |||
762 | bus_space_write_4(sc->sc_iot, sc->sc_pm_ioh, POWMAN_PKWR, pkwr); | 766 | bus_space_write_4(sc->sc_iot, sc->sc_pm_ioh, POWMAN_PKWR, pkwr); | |
763 | bus_space_write_4(sc->sc_iot, sc->sc_pm_ioh, POWMAN_PRER, prer); | 767 | bus_space_write_4(sc->sc_iot, sc->sc_pm_ioh, POWMAN_PRER, prer); | |
764 | bus_space_write_4(sc->sc_iot, sc->sc_pm_ioh, POWMAN_PFER, pfer); | 768 | bus_space_write_4(sc->sc_iot, sc->sc_pm_ioh, POWMAN_PFER, pfer); | |
765 | bus_space_write_4(sc->sc_iot, sc->sc_pm_ioh, POWMAN_PWER, | 769 | bus_space_write_4(sc->sc_iot, sc->sc_pm_ioh, POWMAN_PWER, | |
766 | prer | pfer); | 770 | prer | pfer); | |
767 | } | 771 | } | |
768 | 772 | |||
769 | u_int | 773 | u_int | |
770 | pxa2x0_wakeup_status(void) | 774 | pxa2x0_wakeup_status(void) | |
771 | { | 775 | { | |
772 | struct pxa2x0_apm_softc *sc; | 776 | struct pxa2x0_apm_softc *sc; | |
773 | uint32_t rv; | 777 | uint32_t rv; | |
774 | u_int wsrc; | 778 | u_int wsrc; | |
775 | 779 | |||
776 | if (zapm_cd.cd_ndevs < 1 || zapm_cd.cd_devs[0] == NULL) | 780 | if (zapm_cd.cd_ndevs < 1 || zapm_cd.cd_devs[0] == NULL) | |
777 | return (0); | 781 | return (0); | |
778 | 782 | |||
779 | sc = device_private(zapm_cd.cd_devs[0]); | 783 | sc = device_private(zapm_cd.cd_devs[0]); | |
780 | wsrc = 0; | 784 | wsrc = 0; | |
781 | 785 | |||
782 | rv = bus_space_read_4(sc->sc_iot, sc->sc_pm_ioh, POWMAN_PEDR); | 786 | rv = bus_space_read_4(sc->sc_iot, sc->sc_pm_ioh, POWMAN_PEDR); | |
783 | if ((rv & (1<<0)) != 0) | 787 | if ((rv & (1<<0)) != 0) | |
784 | wsrc |= PXA2X0_WAKEUP_POWERON; | 788 | wsrc |= PXA2X0_WAKEUP_POWERON; | |
785 | if ((rv & (1<<1)) != 0) | 789 | if ((rv & (1<<1)) != 0) | |
786 | wsrc |= PXA2X0_WAKEUP_GPIORST; | 790 | wsrc |= PXA2X0_WAKEUP_GPIORST; | |
787 | if ((rv & (1<<9)) != 0) | 791 | if ((rv & (1<<9)) != 0) | |
788 | wsrc |= PXA2X0_WAKEUP_SD; | 792 | wsrc |= PXA2X0_WAKEUP_SD; | |
789 | if ((rv & (1<<12)) != 0) | 793 | if ((rv & (1<<12)) != 0) | |
790 | wsrc |= PXA2X0_WAKEUP_KEYNS0; | 794 | wsrc |= PXA2X0_WAKEUP_KEYNS0; | |
791 | if ((rv & (1<<13)) != 0) | 795 | if ((rv & (1<<13)) != 0) | |
792 | wsrc |= PXA2X0_WAKEUP_RC; | 796 | wsrc |= PXA2X0_WAKEUP_RC; | |
793 | if ((rv & (1<<15)) != 0) | 797 | if ((rv & (1<<15)) != 0) | |
794 | wsrc |= PXA2X0_WAKEUP_LOCKSW; | 798 | wsrc |= PXA2X0_WAKEUP_LOCKSW; | |
795 | if ((rv & (1<<23)) != 0) | 799 | if ((rv & (1<<23)) != 0) | |
796 | wsrc |= PXA2X0_WAKEUP_JACKIN; | 800 | wsrc |= PXA2X0_WAKEUP_JACKIN; | |
797 | if ((rv & (1<<24)) != 0) | 801 | if ((rv & (1<<24)) != 0) | |
798 | wsrc |= PXA2X0_WAKEUP_USBD; | 802 | wsrc |= PXA2X0_WAKEUP_USBD; | |
799 | if ((rv & (1<<31)) != 0) | 803 | if ((rv & (1<<31)) != 0) | |
800 | wsrc |= PXA2X0_WAKEUP_RTC; | 804 | wsrc |= PXA2X0_WAKEUP_RTC; | |
801 | 805 | |||
802 | rv = bus_space_read_4(sc->sc_iot, sc->sc_pm_ioh, POWMAN_PKSR); | 806 | rv = bus_space_read_4(sc->sc_iot, sc->sc_pm_ioh, POWMAN_PKSR); | |
803 | if ((rv & (1<<1)) != 0) | 807 | if ((rv & (1<<1)) != 0) | |
804 | wsrc |= PXA2X0_WAKEUP_SYNC; | 808 | wsrc |= PXA2X0_WAKEUP_SYNC; | |
805 | if ((rv & (1<<2)) != 0) | 809 | if ((rv & (1<<2)) != 0) | |
806 | wsrc |= PXA2X0_WAKEUP_KEYNS1; | 810 | wsrc |= PXA2X0_WAKEUP_KEYNS1; | |
807 | if ((rv & (1<<9)) != 0) | 811 | if ((rv & (1<<9)) != 0) | |
808 | wsrc |= PXA2X0_WAKEUP_KEYNS2; | 812 | wsrc |= PXA2X0_WAKEUP_KEYNS2; | |
809 | if ((rv & (1<<3)) != 0) | 813 | if ((rv & (1<<3)) != 0) | |
810 | wsrc |= PXA2X0_WAKEUP_KEYNS3; | 814 | wsrc |= PXA2X0_WAKEUP_KEYNS3; | |
811 | if ((rv & (1<<4)) != 0) | 815 | if ((rv & (1<<4)) != 0) | |
812 | wsrc |= PXA2X0_WAKEUP_KEYNS4; | 816 | wsrc |= PXA2X0_WAKEUP_KEYNS4; | |
813 | if ((rv & (1<<6)) != 0) | 817 | if ((rv & (1<<6)) != 0) | |
814 | wsrc |= PXA2X0_WAKEUP_KEYNS5; | 818 | wsrc |= PXA2X0_WAKEUP_KEYNS5; | |
815 | if ((rv & (1<<7)) != 0) | 819 | if ((rv & (1<<7)) != 0) | |
816 | wsrc |= PXA2X0_WAKEUP_KEYNS6; | 820 | wsrc |= PXA2X0_WAKEUP_KEYNS6; | |
817 | if ((rv & (1<<10)) != 0) | 821 | if ((rv & (1<<10)) != 0) | |
818 | wsrc |= PXA2X0_WAKEUP_CF1; | 822 | wsrc |= PXA2X0_WAKEUP_CF1; | |
819 | if ((rv & (1<<11)) != 0) | 823 | if ((rv & (1<<11)) != 0) | |
820 | wsrc |= PXA2X0_WAKEUP_CF0; | 824 | wsrc |= PXA2X0_WAKEUP_CF0; | |
821 | if ((rv & (1<<12)) != 0) | 825 | if ((rv & (1<<12)) != 0) | |
822 | wsrc |= PXA2X0_WAKEUP_POWERON; | 826 | wsrc |= PXA2X0_WAKEUP_POWERON; | |
823 | if ((rv & (1<<18)) != 0) | 827 | if ((rv & (1<<18)) != 0) | |
824 | wsrc |= PXA2X0_WAKEUP_CHRGFULL; | 828 | wsrc |= PXA2X0_WAKEUP_CHRGFULL; | |
825 | 829 | |||
826 | return (wsrc); | 830 | return (wsrc); | |
827 | } | 831 | } | |
828 | 832 | |||
829 | struct pxa2x0_sleep_data { | 833 | struct pxa2x0_sleep_data { | |
830 | /* OS timer registers */ | 834 | /* OS timer registers */ | |
831 | uint32_t sd_osmr0, sd_osmr1, sd_osmr2, sd_osmr3; | 835 | uint32_t sd_osmr0, sd_osmr1, sd_osmr2, sd_osmr3; | |
832 | uint32_t sd_oscr0; | 836 | uint32_t sd_oscr0; | |
833 | uint32_t sd_osmr4, sd_osmr5; | 837 | uint32_t sd_osmr4, sd_osmr5; | |
834 | uint32_t sd_oscr4; | 838 | uint32_t sd_oscr4; | |
835 | uint32_t sd_omcr4, sd_omcr5; | 839 | uint32_t sd_omcr4, sd_omcr5; | |
836 | uint32_t sd_oier; | 840 | uint32_t sd_oier; | |
837 | /* GPIO registers */ | 841 | /* GPIO registers */ | |
838 | uint32_t sd_gpdr0, sd_gpdr1, sd_gpdr2, sd_gpdr3; | 842 | uint32_t sd_gpdr0, sd_gpdr1, sd_gpdr2, sd_gpdr3; | |
839 | uint32_t sd_grer0, sd_grer1, sd_grer2, sd_grer3; | 843 | uint32_t sd_grer0, sd_grer1, sd_grer2, sd_grer3; | |
840 | uint32_t sd_gfer0, sd_gfer1, sd_gfer2, sd_gfer3; | 844 | uint32_t sd_gfer0, sd_gfer1, sd_gfer2, sd_gfer3; | |
841 | uint32_t sd_gafr0_l, sd_gafr1_l, sd_gafr2_l, sd_gafr3_l; | 845 | uint32_t sd_gafr0_l, sd_gafr1_l, sd_gafr2_l, sd_gafr3_l; | |
842 | uint32_t sd_gafr0_u, sd_gafr1_u, sd_gafr2_u, sd_gafr3_u; | 846 | uint32_t sd_gafr0_u, sd_gafr1_u, sd_gafr2_u, sd_gafr3_u; | |
843 | uint32_t sd_gplr0, sd_gplr1, sd_gplr2, sd_gplr3; | 847 | uint32_t sd_gplr0, sd_gplr1, sd_gplr2, sd_gplr3; | |
844 | /* Interrupt controller registers */ | 848 | /* Interrupt controller registers */ | |
845 | uint32_t sd_iclr; | 849 | uint32_t sd_iclr; | |
846 | uint32_t sd_icmr; | 850 | uint32_t sd_icmr; | |
847 | uint32_t sd_iccr; | 851 | uint32_t sd_iccr; | |
848 | /* Memory controller registers */ | 852 | /* Memory controller registers */ | |
849 | uint32_t sd_mecr; | 853 | uint32_t sd_mecr; | |
850 | uint32_t sd_mcmem0, sd_mcmem1; | 854 | uint32_t sd_mcmem0, sd_mcmem1; | |
851 | uint32_t sd_mcatt0, sd_mcatt1; | 855 | uint32_t sd_mcatt0, sd_mcatt1; | |
852 | uint32_t sd_mcio0, sd_mcio1; | 856 | uint32_t sd_mcio0, sd_mcio1; | |
853 | /* Clocks manager registers */ | 857 | /* Clocks manager registers */ | |
854 | uint32_t sd_cken; | 858 | uint32_t sd_cken; | |
855 | }; | 859 | }; | |
856 | 860 | |||
857 | void | 861 | void | |
858 | pxa2x0_apm_sleep(struct pxa2x0_apm_softc *sc) | 862 | pxa2x0_apm_sleep(struct pxa2x0_apm_softc *sc) | |
859 | { | 863 | { | |
860 | struct pxa2x0_sleep_data sd; | 864 | struct pxa2x0_sleep_data sd; | |
861 | bus_space_handle_t ost_ioh; | 865 | bus_space_handle_t ost_ioh; | |
862 | int save; | 866 | int save; | |
863 | uint32_t rv; | 867 | uint32_t rv; | |
864 | 868 | |||
865 | ost_ioh = (bus_space_handle_t)0; | 869 | ost_ioh = (bus_space_handle_t)0; | |
866 | if (bus_space_map(sc->sc_iot, PXA2X0_OST_BASE, PXA2X0_OST_SIZE, 0, | 870 | if (bus_space_map(sc->sc_iot, PXA2X0_OST_BASE, PXA2X0_OST_SIZE, 0, | |
867 | &ost_ioh)) { | 871 | &ost_ioh)) { | |
868 | printf("pxa2x0_apm_sleep: can't map OST\n"); | 872 | printf("pxa2x0_apm_sleep: can't map OST\n"); | |
869 | goto out; | 873 | goto out; | |
870 | } | 874 | } | |
871 | 875 | |||
872 | save = disable_interrupts(I32_bit|F32_bit); | 876 | save = disable_interrupts(I32_bit|F32_bit); | |
873 | 877 | |||
874 | sd.sd_oscr0 = bus_space_read_4(sc->sc_iot, ost_ioh, OST_OSCR0); | 878 | sd.sd_oscr0 = bus_space_read_4(sc->sc_iot, ost_ioh, OST_OSCR0); | |
875 | sd.sd_oscr4 = bus_space_read_4(sc->sc_iot, ost_ioh, OST_OSCR4); | 879 | sd.sd_oscr4 = bus_space_read_4(sc->sc_iot, ost_ioh, OST_OSCR4); | |
876 | sd.sd_omcr4 = bus_space_read_4(sc->sc_iot, ost_ioh, OST_OMCR4); | 880 | sd.sd_omcr4 = bus_space_read_4(sc->sc_iot, ost_ioh, OST_OMCR4); | |
877 | sd.sd_omcr5 = bus_space_read_4(sc->sc_iot, ost_ioh, OST_OMCR5); | 881 | sd.sd_omcr5 = bus_space_read_4(sc->sc_iot, ost_ioh, OST_OMCR5); | |
878 | sd.sd_osmr0 = bus_space_read_4(sc->sc_iot, ost_ioh, OST_OSMR0); | 882 | sd.sd_osmr0 = bus_space_read_4(sc->sc_iot, ost_ioh, OST_OSMR0); | |
879 | sd.sd_osmr1 = bus_space_read_4(sc->sc_iot, ost_ioh, OST_OSMR1); | 883 | sd.sd_osmr1 = bus_space_read_4(sc->sc_iot, ost_ioh, OST_OSMR1); | |
880 | sd.sd_osmr2 = bus_space_read_4(sc->sc_iot, ost_ioh, OST_OSMR2); | 884 | sd.sd_osmr2 = bus_space_read_4(sc->sc_iot, ost_ioh, OST_OSMR2); | |
881 | sd.sd_osmr3 = bus_space_read_4(sc->sc_iot, ost_ioh, OST_OSMR3); | 885 | sd.sd_osmr3 = bus_space_read_4(sc->sc_iot, ost_ioh, OST_OSMR3); | |
882 | sd.sd_osmr4 = bus_space_read_4(sc->sc_iot, ost_ioh, OST_OSMR4); | 886 | sd.sd_osmr4 = bus_space_read_4(sc->sc_iot, ost_ioh, OST_OSMR4); | |
883 | sd.sd_osmr5 = bus_space_read_4(sc->sc_iot, ost_ioh, OST_OSMR5); | 887 | sd.sd_osmr5 = bus_space_read_4(sc->sc_iot, ost_ioh, OST_OSMR5); | |
884 | sd.sd_oier = bus_space_read_4(sc->sc_iot, ost_ioh, OST_OIER); | 888 | sd.sd_oier = bus_space_read_4(sc->sc_iot, ost_ioh, OST_OIER); | |
885 | 889 | |||
886 | /* Bring the PXA27x into 416MHz turbo mode. */ | 890 | /* Bring the PXA27x into 416MHz turbo mode. */ | |
887 | if ((cputype & ~CPU_ID_XSCALE_COREREV_MASK) == CPU_ID_PXA27X && | 891 | if ((cputype & ~CPU_ID_XSCALE_COREREV_MASK) == CPU_ID_PXA27X && | |
888 | bus_space_read_4(sc->sc_iot, pxa2x0_clkman_ioh, CLKMAN_CCCR) != | 892 | bus_space_read_4(sc->sc_iot, pxa2x0_clkman_ioh, CLKMAN_CCCR) != | |
889 | (CCCR_A | CCCR_TURBO_X2 | CCCR_RUN_X16)) { | 893 | (CCCR_A | CCCR_TURBO_X2 | CCCR_RUN_X16)) { | |
890 | #if 0 | 894 | #if 0 | |
891 | pxa27x_cpu_speed_high(); | 895 | pxa27x_cpu_speed_high(); | |
892 | #else | 896 | #else | |
893 | #define CLKCFG_T (1<<0) /* turbo */ | 897 | #define CLKCFG_T (1<<0) /* turbo */ | |
894 | #define CLKCFG_F (1<<1) /* frequency change */ | 898 | #define CLKCFG_F (1<<1) /* frequency change */ | |
895 | #define CLKCFG_B (1<<3) /* fast-bus */ | 899 | #define CLKCFG_B (1<<3) /* fast-bus */ | |
896 | pxa27x_frequency_change(CCCR_A | CCCR_TURBO_X2 | | 900 | pxa27x_frequency_change(CCCR_A | CCCR_TURBO_X2 | | |
897 | CCCR_RUN_X16, CLKCFG_B | CLKCFG_F | CLKCFG_T, | 901 | CCCR_RUN_X16, CLKCFG_B | CLKCFG_F | CLKCFG_T, | |
898 | &pxa2x0_memcfg); | 902 | &pxa2x0_memcfg); | |
899 | #endif | 903 | #endif | |
900 | delay(500000); /* XXX */ | 904 | delay(500000); /* XXX */ | |
901 | } | 905 | } | |
902 | 906 | |||
903 | suspend_again: | 907 | suspend_again: | |
904 | /* Clear wake-up status. */ | 908 | /* Clear wake-up status. */ | |
905 | bus_space_write_4(sc->sc_iot, sc->sc_pm_ioh, POWMAN_PEDR, | 909 | bus_space_write_4(sc->sc_iot, sc->sc_pm_ioh, POWMAN_PEDR, | |
906 | 0xffffffff); | 910 | 0xffffffff); | |
907 | bus_space_write_4(sc->sc_iot, sc->sc_pm_ioh, POWMAN_PKSR, | 911 | bus_space_write_4(sc->sc_iot, sc->sc_pm_ioh, POWMAN_PKSR, | |
908 | 0xffffffff); | 912 | 0xffffffff); | |
909 | 913 | |||
910 | /* XXX control battery charging in sleep mode. */ | 914 | /* XXX control battery charging in sleep mode. */ | |
911 | 915 | |||
912 | /* XXX schedule RTC alarm to check the battery, or schedule | 916 | /* XXX schedule RTC alarm to check the battery, or schedule | |
913 | XXX wake-up shortly before an already programmed alarm? */ | 917 | XXX wake-up shortly before an already programmed alarm? */ | |
914 | 918 | |||
915 | pxa27x_run_mode(); | 919 | pxa27x_run_mode(); | |
916 | #define MDREFR_LOW (MDREFR_C3000 | 0x00b) | 920 | #define MDREFR_LOW (MDREFR_C3000 | 0x00b) | |
917 | pxa27x_fastbus_run_mode(0, MDREFR_LOW); | 921 | pxa27x_fastbus_run_mode(0, MDREFR_LOW); | |
918 | delay(1); | 922 | delay(1); | |
919 | #if 1 | 923 | #if 1 | |
920 | pxa27x_cpu_speed_91(); | 924 | pxa27x_cpu_speed_91(); | |
921 | #else | 925 | #else | |
922 | pxa27x_frequency_change(CCCR_TURBO_X1 | CCCR_RUN_X7, CLKCFG_F, | 926 | pxa27x_frequency_change(CCCR_TURBO_X1 | CCCR_RUN_X7, CLKCFG_F, | |
923 | &pxa2x0_memcfg); | 927 | &pxa2x0_memcfg); | |
924 | #endif | 928 | #endif | |
925 | pxa2x0_pi2c_setvoltage(sc->sc_iot, sc->sc_pm_ioh, PI2C_VOLTAGE_LOW); | 929 | pxa2x0_pi2c_setvoltage(sc->sc_iot, sc->sc_pm_ioh, PI2C_VOLTAGE_LOW); | |
926 | 930 | |||
927 | sd.sd_gpdr0 = bus_space_read_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GPDR0); | 931 | sd.sd_gpdr0 = bus_space_read_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GPDR0); | |
928 | sd.sd_gpdr1 = bus_space_read_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GPDR1); | 932 | sd.sd_gpdr1 = bus_space_read_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GPDR1); | |
929 | sd.sd_gpdr2 = bus_space_read_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GPDR2); | 933 | sd.sd_gpdr2 = bus_space_read_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GPDR2); | |
930 | sd.sd_gpdr3 = bus_space_read_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GPDR3); | 934 | sd.sd_gpdr3 = bus_space_read_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GPDR3); | |
931 | 935 | |||
932 | sd.sd_grer0 = bus_space_read_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GRER0); | 936 | sd.sd_grer0 = bus_space_read_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GRER0); | |
933 | sd.sd_grer1 = bus_space_read_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GRER1); | 937 | sd.sd_grer1 = bus_space_read_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GRER1); | |
934 | sd.sd_grer2 = bus_space_read_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GRER2); | 938 | sd.sd_grer2 = bus_space_read_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GRER2); | |
935 | sd.sd_grer3 = bus_space_read_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GRER3); | 939 | sd.sd_grer3 = bus_space_read_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GRER3); | |
936 | 940 | |||
937 | sd.sd_gfer0 = bus_space_read_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GFER0); | 941 | sd.sd_gfer0 = bus_space_read_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GFER0); | |
938 | sd.sd_gfer1 = bus_space_read_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GFER1); | 942 | sd.sd_gfer1 = bus_space_read_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GFER1); | |
939 | sd.sd_gfer2 = bus_space_read_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GFER2); | 943 | sd.sd_gfer2 = bus_space_read_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GFER2); | |
940 | sd.sd_gfer3 = bus_space_read_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GFER3); | 944 | sd.sd_gfer3 = bus_space_read_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GFER3); | |
941 | 945 | |||
942 | sd.sd_gafr0_l = bus_space_read_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GAFR0_L); | 946 | sd.sd_gafr0_l = bus_space_read_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GAFR0_L); | |
943 | sd.sd_gafr1_l = bus_space_read_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GAFR1_L); | 947 | sd.sd_gafr1_l = bus_space_read_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GAFR1_L); | |
944 | sd.sd_gafr2_l = bus_space_read_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GAFR2_L); | 948 | sd.sd_gafr2_l = bus_space_read_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GAFR2_L); | |
945 | sd.sd_gafr3_l = bus_space_read_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GAFR3_L); | 949 | sd.sd_gafr3_l = bus_space_read_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GAFR3_L); | |
946 | 950 | |||
947 | sd.sd_gafr0_u = bus_space_read_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GAFR0_U); | 951 | sd.sd_gafr0_u = bus_space_read_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GAFR0_U); | |
948 | sd.sd_gafr1_u = bus_space_read_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GAFR1_U); | 952 | sd.sd_gafr1_u = bus_space_read_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GAFR1_U); | |
949 | sd.sd_gafr2_u = bus_space_read_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GAFR2_U); | 953 | sd.sd_gafr2_u = bus_space_read_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GAFR2_U); | |
950 | sd.sd_gafr3_u = bus_space_read_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GAFR3_U); | 954 | sd.sd_gafr3_u = bus_space_read_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GAFR3_U); | |
951 | 955 | |||
952 | sd.sd_gplr0 = bus_space_read_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GPLR0); | 956 | sd.sd_gplr0 = bus_space_read_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GPLR0); | |
953 | sd.sd_gplr1 = bus_space_read_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GPLR1); | 957 | sd.sd_gplr1 = bus_space_read_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GPLR1); | |
954 | sd.sd_gplr2 = bus_space_read_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GPLR2); | 958 | sd.sd_gplr2 = bus_space_read_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GPLR2); | |
955 | sd.sd_gplr3 = bus_space_read_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GPLR3); | 959 | sd.sd_gplr3 = bus_space_read_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GPLR3); | |
956 | 960 | |||
957 | sd.sd_iclr = read_icu(INTCTL_ICLR); | 961 | sd.sd_iclr = read_icu(INTCTL_ICLR); | |
958 | sd.sd_icmr = read_icu(INTCTL_ICMR); | 962 | sd.sd_icmr = read_icu(INTCTL_ICMR); | |
959 | sd.sd_iccr = read_icu(INTCTL_ICCR); | 963 | sd.sd_iccr = read_icu(INTCTL_ICCR); | |
960 | write_icu(INTCTL_ICMR, 0); | 964 | write_icu(INTCTL_ICMR, 0); | |
961 | 965 | |||
962 | sd.sd_mecr = bus_space_read_4(sc->sc_iot, pxa2x0_memctl_ioh, | 966 | sd.sd_mecr = bus_space_read_4(sc->sc_iot, pxa2x0_memctl_ioh, | |
963 | MEMCTL_MECR); | 967 | MEMCTL_MECR); | |
964 | sd.sd_mcmem0 = bus_space_read_4(sc->sc_iot, pxa2x0_memctl_ioh, | 968 | sd.sd_mcmem0 = bus_space_read_4(sc->sc_iot, pxa2x0_memctl_ioh, | |
965 | MEMCTL_MCMEM(0)); | 969 | MEMCTL_MCMEM(0)); | |
966 | sd.sd_mcmem1 = bus_space_read_4(sc->sc_iot, pxa2x0_memctl_ioh, | 970 | sd.sd_mcmem1 = bus_space_read_4(sc->sc_iot, pxa2x0_memctl_ioh, | |
967 | MEMCTL_MCMEM(1)); | 971 | MEMCTL_MCMEM(1)); | |
968 | sd.sd_mcatt0 = bus_space_read_4(sc->sc_iot, pxa2x0_memctl_ioh, | 972 | sd.sd_mcatt0 = bus_space_read_4(sc->sc_iot, pxa2x0_memctl_ioh, | |
969 | MEMCTL_MCATT(0)); | 973 | MEMCTL_MCATT(0)); | |
970 | sd.sd_mcatt1 = bus_space_read_4(sc->sc_iot, pxa2x0_memctl_ioh, | 974 | sd.sd_mcatt1 = bus_space_read_4(sc->sc_iot, pxa2x0_memctl_ioh, | |
971 | MEMCTL_MCATT(1)); | 975 | MEMCTL_MCATT(1)); | |
972 | sd.sd_mcio0 = bus_space_read_4(sc->sc_iot, pxa2x0_memctl_ioh, | 976 | sd.sd_mcio0 = bus_space_read_4(sc->sc_iot, pxa2x0_memctl_ioh, | |
973 | MEMCTL_MCIO(0)); | 977 | MEMCTL_MCIO(0)); | |
974 | sd.sd_mcio1 = bus_space_read_4(sc->sc_iot, pxa2x0_memctl_ioh, | 978 | sd.sd_mcio1 = bus_space_read_4(sc->sc_iot, pxa2x0_memctl_ioh, | |
975 | MEMCTL_MCIO(1)); | 979 | MEMCTL_MCIO(1)); | |
976 | 980 | |||
977 | sd.sd_cken = bus_space_read_4(sc->sc_iot, pxa2x0_clkman_ioh, | 981 | sd.sd_cken = bus_space_read_4(sc->sc_iot, pxa2x0_clkman_ioh, | |
978 | CLKMAN_CKEN); | 982 | CLKMAN_CKEN); | |
979 | 983 | |||
980 | /* | 984 | /* | |
981 | * Stop clocks to all units except to the memory controller, and | 985 | * Stop clocks to all units except to the memory controller, and | |
982 | * to the keypad controller if it is enabled as a wake-up source. | 986 | * to the keypad controller if it is enabled as a wake-up source. | |
983 | */ | 987 | */ | |
984 | rv = CKEN_MEM; | 988 | rv = CKEN_MEM; | |
985 | if ((sc->sc_wakeon & PXA2X0_WAKEUP_KEYNS_ALL) != 0) | 989 | if ((sc->sc_wakeon & PXA2X0_WAKEUP_KEYNS_ALL) != 0) | |
986 | rv |= CKEN_KEY; | 990 | rv |= CKEN_KEY; | |
987 | bus_space_write_4(sc->sc_iot, pxa2x0_clkman_ioh, CLKMAN_CKEN, rv); | 991 | bus_space_write_4(sc->sc_iot, pxa2x0_clkman_ioh, CLKMAN_CKEN, rv); | |
988 | 992 | |||
989 | /* Disable nRESET_OUT. */ | 993 | /* Disable nRESET_OUT. */ | |
990 | rv = bus_space_read_4(sc->sc_iot, sc->sc_pm_ioh, POWMAN_PSLR); | 994 | rv = bus_space_read_4(sc->sc_iot, sc->sc_pm_ioh, POWMAN_PSLR); | |
991 | #define PSLR_SL_ROD (1<<20) | 995 | #define PSLR_SL_ROD (1<<20) | |
992 | bus_space_write_4(sc->sc_iot, sc->sc_pm_ioh, POWMAN_PSLR, | 996 | bus_space_write_4(sc->sc_iot, sc->sc_pm_ioh, POWMAN_PSLR, | |
993 | rv | PSLR_SL_ROD); | 997 | rv | PSLR_SL_ROD); | |
994 | 998 | |||
995 | /* Clear all reset status flags. */ | 999 | /* Clear all reset status flags. */ | |
996 | bus_space_write_4(sc->sc_iot, sc->sc_pm_ioh, POWMAN_RCSR, | 1000 | bus_space_write_4(sc->sc_iot, sc->sc_pm_ioh, POWMAN_RCSR, | |
997 | RCSR_GPR | RCSR_SMR | RCSR_WDR | RCSR_HWR); | 1001 | RCSR_GPR | RCSR_SMR | RCSR_WDR | RCSR_HWR); | |
998 | 1002 | |||
999 | /* Stop 3/13MHz oscillator; do not float PCMCIA and chip-selects. */ | 1003 | /* Stop 3/13MHz oscillator; do not float PCMCIA and chip-selects. */ | |
1000 | rv = PCFR_OPDE; | 1004 | rv = PCFR_OPDE; | |
1001 | if ((cputype & ~CPU_ID_XSCALE_COREREV_MASK) == CPU_ID_PXA27X) | 1005 | if ((cputype & ~CPU_ID_XSCALE_COREREV_MASK) == CPU_ID_PXA27X) | |
1002 | /* Enable nRESET_GPIO as a GPIO reset input. */ | 1006 | /* Enable nRESET_GPIO as a GPIO reset input. */ | |
1003 | rv |= PCFR_GPR_EN; | 1007 | rv |= PCFR_GPR_EN; | |
1004 | bus_space_write_4(sc->sc_iot, sc->sc_pm_ioh, POWMAN_PCFR, rv); | 1008 | bus_space_write_4(sc->sc_iot, sc->sc_pm_ioh, POWMAN_PCFR, rv); | |
1005 | 1009 | |||
1006 | /* XXX C3000 */ | 1010 | /* XXX C3000 */ | |
1007 | #define GPIO_G0_STROBE_BIT 0x0f800000 | 1011 | #define GPIO_G0_STROBE_BIT 0x0f800000 | |
1008 | #define GPIO_G1_STROBE_BIT 0x00100000 | 1012 | #define GPIO_G1_STROBE_BIT 0x00100000 | |
1009 | #define GPIO_G2_STROBE_BIT 0x01000000 | 1013 | #define GPIO_G2_STROBE_BIT 0x01000000 | |
1010 | #define GPIO_G3_STROBE_BIT 0x00041880 | 1014 | #define GPIO_G3_STROBE_BIT 0x00041880 | |
1011 | #define GPIO_KEY_STROBE0 88 | 1015 | #define GPIO_KEY_STROBE0 88 | |
1012 | bus_space_write_4(sc->sc_iot, sc->sc_pm_ioh, POWMAN_PGSR0, | 1016 | bus_space_write_4(sc->sc_iot, sc->sc_pm_ioh, POWMAN_PGSR0, | |
1013 | 0x00144018); | 1017 | 0x00144018); | |
1014 | bus_space_write_4(sc->sc_iot, sc->sc_pm_ioh, POWMAN_PGSR1, | 1018 | bus_space_write_4(sc->sc_iot, sc->sc_pm_ioh, POWMAN_PGSR1, | |
1015 | 0x00ef0000); | 1019 | 0x00ef0000); | |
1016 | bus_space_write_4(sc->sc_iot, sc->sc_pm_ioh, POWMAN_PGSR2, | 1020 | bus_space_write_4(sc->sc_iot, sc->sc_pm_ioh, POWMAN_PGSR2, | |
1017 | 0x0121c000); | 1021 | 0x0121c000); | |
1018 | bus_space_write_4(sc->sc_iot, sc->sc_pm_ioh, POWMAN_PGSR3, | 1022 | bus_space_write_4(sc->sc_iot, sc->sc_pm_ioh, POWMAN_PGSR3, | |
1019 | 0x00600000); | 1023 | 0x00600000); | |
1020 | bus_space_write_4(sc->sc_iot, sc->sc_pm_ioh, POWMAN_PGSR0, | 1024 | bus_space_write_4(sc->sc_iot, sc->sc_pm_ioh, POWMAN_PGSR0, | |
1021 | 0x00144018 & ~GPIO_G0_STROBE_BIT); | 1025 | 0x00144018 & ~GPIO_G0_STROBE_BIT); | |
1022 | bus_space_write_4(sc->sc_iot, sc->sc_pm_ioh, POWMAN_PGSR1, | 1026 | bus_space_write_4(sc->sc_iot, sc->sc_pm_ioh, POWMAN_PGSR1, | |
1023 | 0x00ef0000 & ~GPIO_G1_STROBE_BIT); | 1027 | 0x00ef0000 & ~GPIO_G1_STROBE_BIT); | |
1024 | bus_space_write_4(sc->sc_iot, sc->sc_pm_ioh, POWMAN_PGSR2, | 1028 | bus_space_write_4(sc->sc_iot, sc->sc_pm_ioh, POWMAN_PGSR2, | |
1025 | 0x0121c000 & ~GPIO_G2_STROBE_BIT); | 1029 | 0x0121c000 & ~GPIO_G2_STROBE_BIT); | |
1026 | bus_space_write_4(sc->sc_iot, sc->sc_pm_ioh, POWMAN_PGSR3, | 1030 | bus_space_write_4(sc->sc_iot, sc->sc_pm_ioh, POWMAN_PGSR3, | |
1027 | 0x00600000 & ~GPIO_G3_STROBE_BIT); | 1031 | 0x00600000 & ~GPIO_G3_STROBE_BIT); | |
1028 | bus_space_write_4(sc->sc_iot, sc->sc_pm_ioh, POWMAN_PGSR2, | 1032 | bus_space_write_4(sc->sc_iot, sc->sc_pm_ioh, POWMAN_PGSR2, | |
1029 | (0x0121c000 & ~GPIO_G2_STROBE_BIT) | | 1033 | (0x0121c000 & ~GPIO_G2_STROBE_BIT) | | |
1030 | GPIO_BIT(GPIO_KEY_STROBE0)); | 1034 | GPIO_BIT(GPIO_KEY_STROBE0)); | |
1031 | 1035 | |||
1032 | /* C3000 */ | 1036 | /* C3000 */ | |
1033 | #define GPIO_EXT_BUS_READY 18 | 1037 | #define GPIO_EXT_BUS_READY 18 | |
1034 | pxa2x0_gpio_set_function(GPIO_EXT_BUS_READY, GPIO_SET | GPIO_OUT); | 1038 | pxa2x0_gpio_set_function(GPIO_EXT_BUS_READY, GPIO_SET | GPIO_OUT); | |
1035 | bus_space_write_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GPDR0, 0xd01c4418); | 1039 | bus_space_write_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GPDR0, 0xd01c4418); | |
1036 | bus_space_write_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GPDR1, 0xfcefbd21); | 1040 | bus_space_write_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GPDR1, 0xfcefbd21); | |
1037 | bus_space_write_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GPDR2, 0x13a5ffff); | 1041 | bus_space_write_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GPDR2, 0x13a5ffff); | |
1038 | bus_space_write_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GPDR3, 0x01e3e10c); | 1042 | bus_space_write_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GPDR3, 0x01e3e10c); | |
1039 | 1043 | |||
1040 | bus_space_write_4(sc->sc_iot, sc->sc_pm_ioh, POWMAN_PSPR, | 1044 | bus_space_write_4(sc->sc_iot, sc->sc_pm_ioh, POWMAN_PSPR, | |
1041 | (uint32_t)&pxa2x0_cpu_resume - 0xc0200000 + 0xa0200000); | 1045 | (uint32_t)&pxa2x0_cpu_resume - 0xc0200000 + 0xa0200000); | |
1042 | 1046 | |||
1043 | pxa2x0_cpu_suspend(); | 1047 | pxa2x0_cpu_suspend(); | |
1044 | 1048 | |||
1045 | bus_space_write_4(sc->sc_iot, sc->sc_pm_ioh, POWMAN_PSPR, 0); | 1049 | bus_space_write_4(sc->sc_iot, sc->sc_pm_ioh, POWMAN_PSPR, 0); | |
1046 | 1050 | |||
1047 | pxa2x0_clkman_config(CKEN_SSP|CKEN_PWM0|CKEN_PWM1, 1); | 1051 | pxa2x0_clkman_config(CKEN_SSP|CKEN_PWM0|CKEN_PWM1, 1); | |
1048 | pxa2x0_clkman_config(CKEN_KEY, 0); | 1052 | pxa2x0_clkman_config(CKEN_KEY, 0); | |
1049 | 1053 | |||
1050 | #if 1 | 1054 | #if 1 | |
1051 | /* Clear all GPIO interrupt sources. */ | 1055 | /* Clear all GPIO interrupt sources. */ | |
1052 | bus_space_write_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GEDR0, 0xffffffff); | 1056 | bus_space_write_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GEDR0, 0xffffffff); | |
1053 | bus_space_write_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GEDR1, 0xffffffff); | 1057 | bus_space_write_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GEDR1, 0xffffffff); | |
1054 | bus_space_write_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GEDR2, 0xffffffff); | 1058 | bus_space_write_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GEDR2, 0xffffffff); | |
1055 | #endif | 1059 | #endif | |
1056 | 1060 | |||
1057 | bus_space_write_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GPDR0, sd.sd_gpdr0); | 1061 | bus_space_write_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GPDR0, sd.sd_gpdr0); | |
1058 | bus_space_write_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GPDR1, sd.sd_gpdr1); | 1062 | bus_space_write_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GPDR1, sd.sd_gpdr1); | |
1059 | bus_space_write_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GPDR2, sd.sd_gpdr2); | 1063 | bus_space_write_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GPDR2, sd.sd_gpdr2); | |
1060 | bus_space_write_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GRER0, sd.sd_grer0); | 1064 | bus_space_write_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GRER0, sd.sd_grer0); | |
1061 | bus_space_write_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GRER1, sd.sd_grer1); | 1065 | bus_space_write_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GRER1, sd.sd_grer1); | |
1062 | bus_space_write_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GRER2, sd.sd_grer2); | 1066 | bus_space_write_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GRER2, sd.sd_grer2); | |
1063 | bus_space_write_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GFER0, sd.sd_gfer0); | 1067 | bus_space_write_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GFER0, sd.sd_gfer0); | |
1064 | bus_space_write_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GFER1, sd.sd_gfer1); | 1068 | bus_space_write_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GFER1, sd.sd_gfer1); | |
1065 | bus_space_write_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GFER2, sd.sd_gfer2); | 1069 | bus_space_write_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GFER2, sd.sd_gfer2); | |
1066 | bus_space_write_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GAFR0_L, sd.sd_gafr0_l); | 1070 | bus_space_write_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GAFR0_L, sd.sd_gafr0_l); | |
1067 | bus_space_write_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GAFR1_L, sd.sd_gafr1_l); | 1071 | bus_space_write_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GAFR1_L, sd.sd_gafr1_l); | |
1068 | bus_space_write_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GAFR2_L, sd.sd_gafr2_l); | 1072 | bus_space_write_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GAFR2_L, sd.sd_gafr2_l); | |
1069 | bus_space_write_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GAFR0_U, sd.sd_gafr0_u); | 1073 | bus_space_write_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GAFR0_U, sd.sd_gafr0_u); | |
1070 | bus_space_write_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GAFR1_U, sd.sd_gafr1_u); | 1074 | bus_space_write_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GAFR1_U, sd.sd_gafr1_u); | |
1071 | bus_space_write_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GAFR2_U, sd.sd_gafr2_u); | 1075 | bus_space_write_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GAFR2_U, sd.sd_gafr2_u); | |
1072 | bus_space_write_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GPSR0, sd.sd_gplr0 & | 1076 | bus_space_write_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GPSR0, sd.sd_gplr0 & | |
1073 | sd.sd_gpdr0); | 1077 | sd.sd_gpdr0); | |
1074 | bus_space_write_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GPSR1, sd.sd_gplr1 & | 1078 | bus_space_write_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GPSR1, sd.sd_gplr1 & | |
1075 | sd.sd_gpdr1); | 1079 | sd.sd_gpdr1); | |
1076 | bus_space_write_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GPSR2, sd.sd_gplr2 & | 1080 | bus_space_write_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GPSR2, sd.sd_gplr2 & | |
1077 | sd.sd_gpdr2); | 1081 | sd.sd_gpdr2); | |
1078 | bus_space_write_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GPCR0, ~sd.sd_gplr0 & | 1082 | bus_space_write_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GPCR0, ~sd.sd_gplr0 & | |
1079 | sd.sd_gpdr0); | 1083 | sd.sd_gpdr0); | |
1080 | bus_space_write_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GPCR1, ~sd.sd_gplr1 & | 1084 | bus_space_write_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GPCR1, ~sd.sd_gplr1 & | |
1081 | sd.sd_gpdr1); | 1085 | sd.sd_gpdr1); | |
1082 | bus_space_write_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GPCR2, ~sd.sd_gplr2 & | 1086 | bus_space_write_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GPCR2, ~sd.sd_gplr2 & | |
1083 | sd.sd_gpdr2); | 1087 | sd.sd_gpdr2); | |
1084 | 1088 | |||
1085 | /* PXA27x */ | 1089 | /* PXA27x */ | |
1086 | #if 0 | 1090 | #if 0 | |
1087 | bus_space_write_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GEDR3, 0xffffffff); | 1091 | bus_space_write_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GEDR3, 0xffffffff); | |
1088 | #endif | 1092 | #endif | |
1089 | bus_space_write_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GPDR3, sd.sd_gpdr3); | 1093 | bus_space_write_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GPDR3, sd.sd_gpdr3); | |
1090 | bus_space_write_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GRER3, sd.sd_grer3); | 1094 | bus_space_write_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GRER3, sd.sd_grer3); | |
1091 | bus_space_write_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GFER3, sd.sd_gfer3); | 1095 | bus_space_write_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GFER3, sd.sd_gfer3); | |
1092 | bus_space_write_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GAFR3_L, sd.sd_gafr3_l); | 1096 | bus_space_write_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GAFR3_L, sd.sd_gafr3_l); | |
1093 | bus_space_write_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GAFR3_U, sd.sd_gafr3_u); | 1097 | bus_space_write_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GAFR3_U, sd.sd_gafr3_u); | |
1094 | bus_space_write_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GPSR3, sd.sd_gplr3 & | 1098 | bus_space_write_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GPSR3, sd.sd_gplr3 & | |
1095 | sd.sd_gpdr3); | 1099 | sd.sd_gpdr3); | |
1096 | bus_space_write_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GPCR3, ~sd.sd_gplr3 & | 1100 | bus_space_write_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GPCR3, ~sd.sd_gplr3 & | |
1097 | sd.sd_gpdr3); | 1101 | sd.sd_gpdr3); | |
1098 | 1102 | |||
1099 | bus_space_write_4(sc->sc_iot, pxa2x0_memctl_ioh, MEMCTL_MECR, | 1103 | bus_space_write_4(sc->sc_iot, pxa2x0_memctl_ioh, MEMCTL_MECR, | |
1100 | sd.sd_mecr); | 1104 | sd.sd_mecr); | |
1101 | bus_space_write_4(sc->sc_iot, pxa2x0_memctl_ioh, MEMCTL_MCMEM(0), | 1105 | bus_space_write_4(sc->sc_iot, pxa2x0_memctl_ioh, MEMCTL_MCMEM(0), | |
1102 | sd.sd_mcmem0); | 1106 | sd.sd_mcmem0); | |
1103 | bus_space_write_4(sc->sc_iot, pxa2x0_memctl_ioh, MEMCTL_MCMEM(1), | 1107 | bus_space_write_4(sc->sc_iot, pxa2x0_memctl_ioh, MEMCTL_MCMEM(1), | |
1104 | sd.sd_mcmem1); | 1108 | sd.sd_mcmem1); | |
1105 | bus_space_write_4(sc->sc_iot, pxa2x0_memctl_ioh, MEMCTL_MCATT(0), | 1109 | bus_space_write_4(sc->sc_iot, pxa2x0_memctl_ioh, MEMCTL_MCATT(0), | |
1106 | sd.sd_mcatt0); | 1110 | sd.sd_mcatt0); | |
1107 | bus_space_write_4(sc->sc_iot, pxa2x0_memctl_ioh, MEMCTL_MCATT(1), | 1111 | bus_space_write_4(sc->sc_iot, pxa2x0_memctl_ioh, MEMCTL_MCATT(1), |
--- src/sys/arch/macppc/dev/apm.c 2014/07/25 08:10:34 1.27
+++ src/sys/arch/macppc/dev/apm.c 2020/10/30 22:20:38 1.28
@@ -1,459 +1,463 @@ | @@ -1,459 +1,463 @@ | |||
1 | /* $NetBSD: apm.c,v 1.27 2014/07/25 08:10:34 dholland Exp $ */ | 1 | /* $NetBSD: apm.c,v 1.28 2020/10/30 22:20:38 christos Exp $ */ | |
2 | /* $OpenBSD: apm.c,v 1.5 2002/06/07 07:13:59 miod Exp $ */ | 2 | /* $OpenBSD: apm.c,v 1.5 2002/06/07 07:13:59 miod Exp $ */ | |
3 | 3 | |||
4 | /*- | 4 | /*- | |
5 | * Copyright (c) 2001 Alexander Guy. All rights reserved. | 5 | * Copyright (c) 2001 Alexander Guy. All rights reserved. | |
6 | * Copyright (c) 1998-2001 Michael Shalayeff. All rights reserved. | 6 | * Copyright (c) 1998-2001 Michael Shalayeff. All rights reserved. | |
7 | * Copyright (c) 1995 John T. Kohl. All rights reserved. | 7 | * Copyright (c) 1995 John T. Kohl. All rights reserved. | |
8 | * | 8 | * | |
9 | * Redistribution and use in source and binary forms, with or without | 9 | * Redistribution and use in source and binary forms, with or without | |
10 | * modification, are permitted provided that the following conditions | 10 | * modification, are permitted provided that the following conditions | |
11 | * are met: | 11 | * are met: | |
12 | * 1. Redistributions of source code must retain the above copyright | 12 | * 1. Redistributions of source code must retain the above copyright | |
13 | * notice, this list of conditions and the following disclaimer. | 13 | * notice, this list of conditions and the following disclaimer. | |
14 | * 2. Redistributions in binary form must reproduce the above copyright | 14 | * 2. Redistributions in binary form must reproduce the above copyright | |
15 | * notice, this list of conditions and the following disclaimer in the | 15 | * notice, this list of conditions and the following disclaimer in the | |
16 | * documentation and/or other materials provided with the distribution. | 16 | * documentation and/or other materials provided with the distribution. | |
17 | * 3. Neither the names of the authors nor the names of contributors | 17 | * 3. Neither the names of the authors nor the names of contributors | |
18 | * may be used to endorse or promote products derived from this software | 18 | * may be used to endorse or promote products derived from this software | |
19 | * without specific prior written permission. | 19 | * without specific prior written permission. | |
20 | * | 20 | * | |
21 | * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND | 21 | * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND | |
22 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | 22 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
23 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | 23 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |
24 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE | 24 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE | |
25 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | 25 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
26 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | 26 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |
27 | * OR SERVICES; LOSS OF MIND, USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | 27 | * OR SERVICES; LOSS OF MIND, USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
28 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | 28 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |
29 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | 29 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |
30 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | 30 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |
31 | * SUCH DAMAGE. | 31 | * SUCH DAMAGE. | |
32 | * | 32 | * | |
33 | */ | 33 | */ | |
34 | 34 | |||
35 | #include <sys/cdefs.h> | 35 | #include <sys/cdefs.h> | |
36 | __KERNEL_RCSID(0, "$NetBSD: apm.c,v 1.27 2014/07/25 08:10:34 dholland Exp $"); | 36 | __KERNEL_RCSID(0, "$NetBSD: apm.c,v 1.28 2020/10/30 22:20:38 christos Exp $"); | |
37 | 37 | |||
38 | #include "apm.h" | 38 | #include "apm.h" | |
39 | 39 | |||
40 | #if NAPM > 1 | 40 | #if NAPM > 1 | |
41 | #error only one APM emulation device may be configured | 41 | #error only one APM emulation device may be configured | |
42 | #endif | 42 | #endif | |
43 | 43 | |||
44 | #include <sys/param.h> | 44 | #include <sys/param.h> | |
45 | #include <sys/systm.h> | 45 | #include <sys/systm.h> | |
46 | #include <sys/kernel.h> | 46 | #include <sys/kernel.h> | |
47 | #include <sys/proc.h> | 47 | #include <sys/proc.h> | |
48 | #include <sys/device.h> | 48 | #include <sys/device.h> | |
49 | #include <sys/fcntl.h> | 49 | #include <sys/fcntl.h> | |
50 | #include <sys/ioctl.h> | 50 | #include <sys/ioctl.h> | |
51 | #include <sys/mutex.h> | 51 | #include <sys/mutex.h> | |
52 | #ifdef __OpenBSD__ | 52 | #ifdef __OpenBSD__ | |
53 | #include <sys/event.h> | 53 | #include <sys/event.h> | |
54 | #endif | 54 | #endif | |
55 | #ifdef __NetBSD__ | 55 | #ifdef __NetBSD__ | |
56 | #include <sys/select.h> | 56 | #include <sys/select.h> | |
57 | #include <sys/poll.h> | 57 | #include <sys/poll.h> | |
58 | #include <sys/conf.h> | 58 | #include <sys/conf.h> | |
59 | #endif | 59 | #endif | |
60 | 60 | |||
61 | #ifdef __OpenBSD__ | 61 | #ifdef __OpenBSD__ | |
62 | #include <machine/conf.h> | 62 | #include <machine/conf.h> | |
63 | #endif | 63 | #endif | |
64 | #include <machine/cpu.h> | 64 | #include <machine/cpu.h> | |
65 | #include <machine/apmvar.h> | 65 | #include <machine/apmvar.h> | |
66 | 66 | |||
67 | #include <macppc/dev/adbvar.h> | 67 | #include <macppc/dev/adbvar.h> | |
68 | #include <macppc/dev/pm_direct.h> | 68 | #include <macppc/dev/pm_direct.h> | |
69 | 69 | |||
70 | #if defined(APMDEBUG) | 70 | #if defined(APMDEBUG) | |
71 | #define DPRINTF(x) printf x | 71 | #define DPRINTF(x) printf x | |
72 | #else | 72 | #else | |
73 | #define DPRINTF(x) /**/ | 73 | #define DPRINTF(x) /**/ | |
74 | #endif | 74 | #endif | |
75 | 75 | |||
76 | #define APM_NEVENTS 16 | 76 | #define APM_NEVENTS 16 | |
77 | 77 | |||
78 | struct apm_softc { | 78 | struct apm_softc { | |
79 | struct selinfo sc_rsel; | 79 | struct selinfo sc_rsel; | |
80 | #ifdef __OpenBSD__ | 80 | #ifdef __OpenBSD__ | |
81 | struct klist sc_note; | 81 | struct klist sc_note; | |
82 | #endif | 82 | #endif | |
83 | int sc_flags; | 83 | int sc_flags; | |
84 | int event_count; | 84 | int event_count; | |
85 | int event_ptr; | 85 | int event_ptr; | |
86 | kmutex_t sc_lock; | 86 | kmutex_t sc_lock; | |
87 | struct apm_event_info event_list[APM_NEVENTS]; | 87 | struct apm_event_info event_list[APM_NEVENTS]; | |
88 | }; | 88 | }; | |
89 | 89 | |||
90 | /* | 90 | /* | |
91 | * A brief note on the locking protocol: it's very simple; we | 91 | * A brief note on the locking protocol: it's very simple; we | |
92 | * assert an exclusive lock any time thread context enters the | 92 | * assert an exclusive lock any time thread context enters the | |
93 | * APM module. This is both the APM thread itself, as well as | 93 | * APM module. This is both the APM thread itself, as well as | |
94 | * user context. | 94 | * user context. | |
95 | */ | 95 | */ | |
96 | #ifdef __NetBSD__ | 96 | #ifdef __NetBSD__ | |
97 | #define APM_LOCK(apmsc) mutex_enter(&(apmsc)->sc_lock) | 97 | #define APM_LOCK(apmsc) mutex_enter(&(apmsc)->sc_lock) | |
98 | #define APM_UNLOCK(apmsc) mutex_exit(&(apmsc)->sc_lock) | 98 | #define APM_UNLOCK(apmsc) mutex_exit(&(apmsc)->sc_lock) | |
99 | #else | 99 | #else | |
100 | #define APM_LOCK(apmsc) | 100 | #define APM_LOCK(apmsc) | |
101 | #define APM_UNLOCK(apmsc) | 101 | #define APM_UNLOCK(apmsc) | |
102 | #endif | 102 | #endif | |
103 | 103 | |||
104 | int apmmatch(device_t, cfdata_t, void *); | 104 | int apmmatch(device_t, cfdata_t, void *); | |
105 | void apmattach(device_t, device_t, void *); | 105 | void apmattach(device_t, device_t, void *); | |
106 | 106 | |||
107 | #ifdef __NetBSD__ | 107 | #ifdef __NetBSD__ | |
108 | #if 0 | 108 | #if 0 | |
109 | static int apm_record_event(struct apm_softc *, u_int); | 109 | static int apm_record_event(struct apm_softc *, u_int); | |
110 | #endif | 110 | #endif | |
111 | #endif | 111 | #endif | |
112 | 112 | |||
113 | CFATTACH_DECL_NEW(apm, sizeof(struct apm_softc), | 113 | CFATTACH_DECL_NEW(apm, sizeof(struct apm_softc), | |
114 | apmmatch, apmattach, NULL, NULL); | 114 | apmmatch, apmattach, NULL, NULL); | |
115 | 115 | |||
116 | #ifdef __OpenBSD__ | 116 | #ifdef __OpenBSD__ | |
117 | struct cfdriver apm_cd = { | 117 | struct cfdriver apm_cd = { | |
118 | NULL, "apm", DV_DULL | 118 | NULL, "apm", DV_DULL | |
119 | }; | 119 | }; | |
120 | #else | 120 | #else | |
121 | extern struct cfdriver apm_cd; | 121 | extern struct cfdriver apm_cd; | |
122 | 122 | |||
123 | dev_type_open(apmopen); | 123 | dev_type_open(apmopen); | |
124 | dev_type_close(apmclose); | 124 | dev_type_close(apmclose); | |
125 | dev_type_ioctl(apmioctl); | 125 | dev_type_ioctl(apmioctl); | |
126 | dev_type_poll(apmpoll); | 126 | dev_type_poll(apmpoll); | |
127 | dev_type_kqfilter(apmkqfilter); | 127 | dev_type_kqfilter(apmkqfilter); | |
128 | 128 | |||
129 | const struct cdevsw apm_cdevsw = { | 129 | const struct cdevsw apm_cdevsw = { | |
130 | .d_open = apmopen, | 130 | .d_open = apmopen, | |
131 | .d_close = apmclose, | 131 | .d_close = apmclose, | |
132 | .d_read = noread, | 132 | .d_read = noread, | |
133 | .d_write = nowrite, | 133 | .d_write = nowrite, | |
134 | .d_ioctl = apmioctl, | 134 | .d_ioctl = apmioctl, | |
135 | .d_stop = nostop, | 135 | .d_stop = nostop, | |
136 | .d_tty = notty, | 136 | .d_tty = notty, | |
137 | .d_poll = apmpoll, | 137 | .d_poll = apmpoll, | |
138 | .d_mmap = nommap, | 138 | .d_mmap = nommap, | |
139 | .d_kqfilter = apmkqfilter, | 139 | .d_kqfilter = apmkqfilter, | |
140 | .d_discard = nodiscard, | 140 | .d_discard = nodiscard, | |
141 | .d_flag = 0 | 141 | .d_flag = 0 | |
142 | }; | 142 | }; | |
143 | #endif | 143 | #endif | |
144 | 144 | |||
145 | int apm_evindex; | 145 | int apm_evindex; | |
146 | 146 | |||
147 | #define APMUNIT(dev) (minor(dev)&0xf0) | 147 | #define APMUNIT(dev) (minor(dev)&0xf0) | |
148 | #define APMDEV(dev) (minor(dev)&0x0f) | 148 | #define APMDEV(dev) (minor(dev)&0x0f) | |
149 | #define APMDEV_NORMAL 0 | 149 | #define APMDEV_NORMAL 0 | |
150 | #define APMDEV_CTL 8 | 150 | #define APMDEV_CTL 8 | |
151 | 151 | |||
152 | /* | 152 | /* | |
153 | * Flags to control kernel display | 153 | * Flags to control kernel display | |
154 | * SCFLAG_NOPRINT: do not output APM power messages due to | 154 | * SCFLAG_NOPRINT: do not output APM power messages due to | |
155 | * a power change event. | 155 | * a power change event. | |
156 | * | 156 | * | |
157 | * SCFLAG_PCTPRINT: do not output APM power messages due to | 157 | * SCFLAG_PCTPRINT: do not output APM power messages due to | |
158 | * to a power change event unless the battery | 158 | * to a power change event unless the battery | |
159 | * percentage changes. | 159 | * percentage changes. | |
160 | */ | 160 | */ | |
161 | 161 | |||
162 | #define SCFLAG_NOPRINT 0x0008000 | 162 | #define SCFLAG_NOPRINT 0x0008000 | |
163 | #define SCFLAG_PCTPRINT 0x0004000 | 163 | #define SCFLAG_PCTPRINT 0x0004000 | |
164 | #define SCFLAG_PRINT (SCFLAG_NOPRINT|SCFLAG_PCTPRINT) | 164 | #define SCFLAG_PRINT (SCFLAG_NOPRINT|SCFLAG_PCTPRINT) | |
165 | 165 | |||
166 | #define SCFLAG_OREAD (1 << 0) | 166 | #define SCFLAG_OREAD (1 << 0) | |
167 | #define SCFLAG_OWRITE (1 << 1) | 167 | #define SCFLAG_OWRITE (1 << 1) | |
168 | #define SCFLAG_OPEN (SCFLAG_OREAD|SCFLAG_OWRITE) | 168 | #define SCFLAG_OPEN (SCFLAG_OREAD|SCFLAG_OWRITE) | |
169 | 169 | |||
170 | 170 | |||
171 | int | 171 | int | |
172 | apmmatch(device_t parent, cfdata_t match, void *aux) | 172 | apmmatch(device_t parent, cfdata_t match, void *aux) | |
173 | { | 173 | { | |
174 | struct adb_attach_args *aa = (void *)aux; | 174 | struct adb_attach_args *aa = (void *)aux; | |
175 | if (aa->origaddr != ADBADDR_APM || | 175 | if (aa->origaddr != ADBADDR_APM || | |
176 | aa->handler_id != ADBADDR_APM || | 176 | aa->handler_id != ADBADDR_APM || | |
177 | aa->adbaddr != ADBADDR_APM) | 177 | aa->adbaddr != ADBADDR_APM) | |
178 | return 0; | 178 | return 0; | |
179 | 179 | |||
180 | if (adbHardware != ADB_HW_PMU) | 180 | if (adbHardware != ADB_HW_PMU) | |
181 | return 0; | 181 | return 0; | |
182 | 182 | |||
183 | return 1; | 183 | return 1; | |
184 | } | 184 | } | |
185 | 185 | |||
186 | void | 186 | void | |
187 | apmattach(device_t parent, device_t self, void *aux) | 187 | apmattach(device_t parent, device_t self, void *aux) | |
188 | { | 188 | { | |
189 | struct apm_softc *sc = device_private(self); | 189 | struct apm_softc *sc = device_private(self); | |
190 | struct pmu_battery_info info; | 190 | struct pmu_battery_info info; | |
191 | 191 | |||
192 | pm_battery_info(0, &info); | 192 | pm_battery_info(0, &info); | |
193 | 193 | |||
194 | printf(": battery flags 0x%X, ", info.flags); | 194 | printf(": battery flags 0x%X, ", info.flags); | |
195 | printf("%d%% charged\n", ((info.cur_charge * 100) / info.max_charge)); | 195 | printf("%d%% charged\n", ((info.cur_charge * 100) / info.max_charge)); | |
196 | 196 | |||
197 | sc->sc_flags = 0; | 197 | sc->sc_flags = 0; | |
198 | sc->event_ptr = 0; | 198 | sc->event_ptr = 0; | |
199 | sc->event_count = 0; | 199 | sc->event_count = 0; | |
200 | mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_NONE); | 200 | mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_NONE); | |
201 | selinit(&sc->sc_rsel); | 201 | selinit(&sc->sc_rsel); | |
202 | } | 202 | } | |
203 | 203 | |||
204 | int | 204 | int | |
205 | apmopen(dev_t dev, int flag, int mode, struct lwp *l) | 205 | apmopen(dev_t dev, int flag, int mode, struct lwp *l) | |
206 | { | 206 | { | |
207 | struct apm_softc *sc; | 207 | struct apm_softc *sc; | |
208 | int error = 0; | 208 | int error = 0; | |
209 | 209 | |||
210 | /* apm0 only */ | 210 | /* apm0 only */ | |
211 | sc = device_lookup_private(&apm_cd, APMUNIT(dev)); | 211 | sc = device_lookup_private(&apm_cd, APMUNIT(dev)); | |
212 | if (sc == NULL) | 212 | if (sc == NULL) | |
213 | return ENXIO; | 213 | return ENXIO; | |
214 | 214 | |||
215 | DPRINTF(("apmopen: dev %d pid %d flag %x mode %x\n", | 215 | DPRINTF(("apmopen: dev %d pid %d flag %x mode %x\n", | |
216 | APMDEV(dev), l->l_proc->p_pid, flag, mode)); | 216 | APMDEV(dev), l->l_proc->p_pid, flag, mode)); | |
217 | 217 | |||
218 | APM_LOCK(sc); | 218 | APM_LOCK(sc); | |
219 | switch (APMDEV(dev)) { | 219 | switch (APMDEV(dev)) { | |
220 | case APMDEV_CTL: | 220 | case APMDEV_CTL: | |
221 | if (!(flag & FWRITE)) { | 221 | if (!(flag & FWRITE)) { | |
222 | error = EINVAL; | 222 | error = EINVAL; | |
223 | break; | 223 | break; | |
224 | } | 224 | } | |
225 | if (sc->sc_flags & SCFLAG_OWRITE) { | 225 | if (sc->sc_flags & SCFLAG_OWRITE) { | |
226 | error = EBUSY; | 226 | error = EBUSY; | |
227 | break; | 227 | break; | |
228 | } | 228 | } | |
229 | sc->sc_flags |= SCFLAG_OWRITE; | 229 | sc->sc_flags |= SCFLAG_OWRITE; | |
230 | break; | 230 | break; | |
231 | case APMDEV_NORMAL: | 231 | case APMDEV_NORMAL: | |
232 | if (!(flag & FREAD) || (flag & FWRITE)) { | 232 | if (!(flag & FREAD) || (flag & FWRITE)) { | |
233 | error = EINVAL; | 233 | error = EINVAL; | |
234 | break; | 234 | break; | |
235 | } | 235 | } | |
236 | sc->sc_flags |= SCFLAG_OREAD; | 236 | sc->sc_flags |= SCFLAG_OREAD; | |
237 | break; | 237 | break; | |
238 | default: | 238 | default: | |
239 | error = ENXIO; | 239 | error = ENXIO; | |
240 | break; | 240 | break; | |
241 | } | 241 | } | |
242 | APM_UNLOCK(sc); | 242 | APM_UNLOCK(sc); | |
243 | return error; | 243 | return error; | |
244 | } | 244 | } | |
245 | 245 | |||
246 | int | 246 | int | |
247 | apmclose(dev_t dev, int flag, int mode, struct lwp *l) | 247 | apmclose(dev_t dev, int flag, int mode, struct lwp *l) | |
248 | { | 248 | { | |
249 | struct apm_softc *sc; | 249 | struct apm_softc *sc; | |
250 | 250 | |||
251 | /* apm0 only */ | 251 | /* apm0 only */ | |
252 | sc = device_lookup_private(&apm_cd, APMUNIT(dev)); | 252 | sc = device_lookup_private(&apm_cd, APMUNIT(dev)); | |
253 | if (sc == NULL) | 253 | if (sc == NULL) | |
254 | return ENXIO; | 254 | return ENXIO; | |
255 | 255 | |||
256 | DPRINTF(("apmclose: pid %d flag %x mode %x\n", l->l_proc->p_pid, flag, mode)); | 256 | DPRINTF(("apmclose: pid %d flag %x mode %x\n", l->l_proc->p_pid, flag, mode)); | |
257 | 257 | |||
258 | APM_LOCK(sc); | 258 | APM_LOCK(sc); | |
259 | switch (APMDEV(dev)) { | 259 | switch (APMDEV(dev)) { | |
260 | case APMDEV_CTL: | 260 | case APMDEV_CTL: | |
261 | sc->sc_flags &= ~SCFLAG_OWRITE; | 261 | sc->sc_flags &= ~SCFLAG_OWRITE; | |
262 | break; | 262 | break; | |
263 | case APMDEV_NORMAL: | 263 | case APMDEV_NORMAL: | |
264 | sc->sc_flags &= ~SCFLAG_OREAD; | 264 | sc->sc_flags &= ~SCFLAG_OREAD; | |
265 | break; | 265 | break; | |
266 | } | 266 | } | |
267 | APM_UNLOCK(sc); | 267 | APM_UNLOCK(sc); | |
268 | return 0; | 268 | return 0; | |
269 | } | 269 | } | |
270 | 270 | |||
271 | int | 271 | int | |
272 | apmioctl(dev_t dev, u_long cmd, void *data, int flag, struct lwp *l) | 272 | apmioctl(dev_t dev, u_long cmd, void *data, int flag, struct lwp *l) | |
273 | { | 273 | { | |
274 | struct apm_softc *sc; | 274 | struct apm_softc *sc; | |
275 | struct pmu_battery_info batt; | 275 | struct pmu_battery_info batt; | |
276 | struct apm_power_info *power; | 276 | struct apm_power_info *power; | |
277 | int error = 0; | 277 | int error = 0; | |
278 | 278 | |||
279 | /* apm0 only */ | 279 | /* apm0 only */ | |
280 | sc = device_lookup_private(&apm_cd, APMUNIT(dev)); | 280 | sc = device_lookup_private(&apm_cd, APMUNIT(dev)); | |
281 | if (sc == NULL) | 281 | if (sc == NULL) | |
282 | return ENXIO; | 282 | return ENXIO; | |
283 | 283 | |||
284 | APM_LOCK(sc); | 284 | APM_LOCK(sc); | |
285 | switch (cmd) { | 285 | switch (cmd) { | |
286 | /* some ioctl names from linux */ | 286 | /* some ioctl names from linux */ | |
287 | case APM_IOC_STANDBY: | 287 | case APM_IOC_STANDBY: | |
288 | if ((flag & FWRITE) == 0) | 288 | if ((flag & FWRITE) == 0) | |
289 | error = EBADF; | 289 | error = EBADF; | |
290 | case APM_IOC_SUSPEND: | 290 | case APM_IOC_SUSPEND: | |
291 | if ((flag & FWRITE) == 0) | 291 | if ((flag & FWRITE) == 0) | |
292 | error = EBADF; | 292 | error = EBADF; | |
293 | break; | 293 | break; | |
294 | case APM_IOC_PRN_CTL: | 294 | case APM_IOC_PRN_CTL: | |
295 | if ((flag & FWRITE) == 0) | 295 | if ((flag & FWRITE) == 0) | |
296 | error = EBADF; | 296 | error = EBADF; | |
297 | else { | 297 | else { | |
298 | int op = *(int *)data; | 298 | int op = *(int *)data; | |
299 | DPRINTF(( "APM_IOC_PRN_CTL: %d\n", op )); | 299 | DPRINTF(( "APM_IOC_PRN_CTL: %d\n", op )); | |
300 | switch (op) { | 300 | switch (op) { | |
301 | case APM_PRINT_ON: /* enable printing */ | 301 | case APM_PRINT_ON: /* enable printing */ | |
302 | sc->sc_flags &= ~SCFLAG_PRINT; | 302 | sc->sc_flags &= ~SCFLAG_PRINT; | |
303 | break; | 303 | break; | |
304 | case APM_PRINT_OFF: /* disable printing */ | 304 | case APM_PRINT_OFF: /* disable printing */ | |
305 | sc->sc_flags &= ~SCFLAG_PRINT; | 305 | sc->sc_flags &= ~SCFLAG_PRINT; | |
306 | sc->sc_flags |= SCFLAG_NOPRINT; | 306 | sc->sc_flags |= SCFLAG_NOPRINT; | |
307 | break; | 307 | break; | |
308 | case APM_PRINT_PCT: /* disable some printing */ | 308 | case APM_PRINT_PCT: /* disable some printing */ | |
309 | sc->sc_flags &= ~SCFLAG_PRINT; | 309 | sc->sc_flags &= ~SCFLAG_PRINT; | |
310 | sc->sc_flags |= SCFLAG_PCTPRINT; | 310 | sc->sc_flags |= SCFLAG_PCTPRINT; | |
311 | break; | 311 | break; | |
312 | default: | 312 | default: | |
313 | error = EINVAL; | 313 | error = EINVAL; | |
314 | break; | 314 | break; | |
315 | } | 315 | } | |
316 | } | 316 | } | |
317 | break; | 317 | break; | |
318 | case APM_IOC_DEV_CTL: | 318 | case APM_IOC_DEV_CTL: | |
319 | if ((flag & FWRITE) == 0) | 319 | if ((flag & FWRITE) == 0) | |
320 | error = EBADF; | 320 | error = EBADF; | |
321 | break; | 321 | break; | |
322 | case APM_IOC_GETPOWER: | 322 | case APM_IOC_GETPOWER: | |
323 | power = (struct apm_power_info *)data; | 323 | power = (struct apm_power_info *)data; | |
324 | 324 | |||
325 | pm_battery_info(0, &batt); | 325 | pm_battery_info(0, &batt); | |
326 | 326 | |||
327 | power->ac_state = ((batt.flags & PMU_PWR_AC_PRESENT) ? | 327 | power->ac_state = ((batt.flags & PMU_PWR_AC_PRESENT) ? | |
328 | APM_AC_ON : APM_AC_OFF); | 328 | APM_AC_ON : APM_AC_OFF); | |
329 | power->battery_life = | 329 | power->battery_life = | |
330 | ((batt.cur_charge * 100) / batt.max_charge); | 330 | ((batt.cur_charge * 100) / batt.max_charge); | |
331 | 331 | |||
332 | /* | 332 | /* | |
333 | * If the battery is charging, return the minutes left until | 333 | * If the battery is charging, return the minutes left until | |
334 | * charging is complete. apmd knows this. | 334 | * charging is complete. apmd knows this. | |
335 | */ | 335 | */ | |
336 | 336 | |||
337 | if (!(batt.flags & PMU_PWR_BATT_PRESENT)) { | 337 | if (!(batt.flags & PMU_PWR_BATT_PRESENT)) { | |
338 | power->battery_state = APM_BATT_UNKNOWN; | 338 | power->battery_state = APM_BATT_UNKNOWN; | |
339 | power->minutes_left = 0; | 339 | power->minutes_left = 0; | |
340 | power->battery_life = 0; | 340 | power->battery_life = 0; | |
341 | } else if ((power->ac_state == APM_AC_ON) && | 341 | } else if ((power->ac_state == APM_AC_ON) && | |
342 | (batt.draw > 0)) { | 342 | (batt.draw > 0)) { | |
343 | power->minutes_left = batt.secs_remaining / 60; | 343 | power->minutes_left = batt.secs_remaining / 60; | |
344 | power->battery_state = APM_BATT_CHARGING; | 344 | power->battery_state = APM_BATT_CHARGING; | |
345 | } else { | 345 | } else { | |
346 | power->minutes_left = batt.secs_remaining / 60; | 346 | power->minutes_left = batt.secs_remaining / 60; | |
347 | 347 | |||
348 | /* XXX - Arbitrary */ | 348 | /* XXX - Arbitrary */ | |
349 | if (power->battery_life > 60) { | 349 | if (power->battery_life > 60) { | |
350 | power->battery_state = APM_BATT_HIGH; | 350 | power->battery_state = APM_BATT_HIGH; | |
351 | } else if (power->battery_life < 10) { | 351 | } else if (power->battery_life < 10) { | |
352 | power->battery_state = APM_BATT_CRITICAL; | 352 | power->battery_state = APM_BATT_CRITICAL; | |
353 | } else { | 353 | } else { | |
354 | power->battery_state = APM_BATT_LOW; | 354 | power->battery_state = APM_BATT_LOW; | |
355 | } | 355 | } | |
356 | } | 356 | } | |
357 | 357 | |||
358 | break; | 358 | break; | |
359 | 359 | |||
360 | default: | 360 | default: | |
361 | error = ENOTTY; | 361 | error = ENOTTY; | |
362 | } | 362 | } | |
363 | APM_UNLOCK(sc); | 363 | APM_UNLOCK(sc); | |
364 | 364 | |||
365 | return error; | 365 | return error; | |
366 | } | 366 | } | |
367 | 367 | |||
368 | #ifdef __NetBSD__ | 368 | #ifdef __NetBSD__ | |
369 | #if 0 | 369 | #if 0 | |
370 | /* | 370 | /* | |
371 | * return 0 if the user will notice and handle the event, | 371 | * return 0 if the user will notice and handle the event, | |
372 | * return 1 if the kernel driver should do so. | 372 | * return 1 if the kernel driver should do so. | |
373 | */ | 373 | */ | |
374 | static int | 374 | static int | |
375 | apm_record_event(struct apm_softc *sc, u_int event_type) | 375 | apm_record_event(struct apm_softc *sc, u_int event_type) | |
376 | { | 376 | { | |
377 | struct apm_event_info *evp; | 377 | struct apm_event_info *evp; | |
378 | 378 | |||
379 | if ((sc->sc_flags & SCFLAG_OPEN) == 0) | 379 | if ((sc->sc_flags & SCFLAG_OPEN) == 0) | |
380 | return 1; /* no user waiting */ | 380 | return 1; /* no user waiting */ | |
381 | if (sc->event_count == APM_NEVENTS) { | 381 | if (sc->event_count == APM_NEVENTS) { | |
382 | DPRINTF(("apm_record_event: queue full!\n")); | 382 | DPRINTF(("apm_record_event: queue full!\n")); | |
383 | return 1; /* overflow */ | 383 | return 1; /* overflow */ | |
384 | } | 384 | } | |
385 | evp = &sc->event_list[sc->event_ptr]; | 385 | evp = &sc->event_list[sc->event_ptr]; | |
386 | sc->event_count++; | 386 | sc->event_count++; | |
387 | sc->event_ptr++; | 387 | sc->event_ptr++; | |
388 | sc->event_ptr %= APM_NEVENTS; | 388 | sc->event_ptr %= APM_NEVENTS; | |
389 | evp->type = event_type; | 389 | evp->type = event_type; | |
390 | evp->index = ++apm_evindex; | 390 | evp->index = ++apm_evindex; | |
391 | selnotify(&sc->sc_rsel, 0, 0); | 391 | selnotify(&sc->sc_rsel, 0, 0); | |
392 | return (sc->sc_flags & SCFLAG_OWRITE) ? 0 : 1; /* user may handle */ | 392 | return (sc->sc_flags & SCFLAG_OWRITE) ? 0 : 1; /* user may handle */ | |
393 | } | 393 | } | |
394 | #endif | 394 | #endif | |
395 | 395 | |||
396 | int | 396 | int | |
397 | apmpoll(dev_t dev, int events, struct lwp *l) | 397 | apmpoll(dev_t dev, int events, struct lwp *l) | |
398 | { | 398 | { | |
399 | struct apm_softc *sc = device_lookup_private(&apm_cd,APMUNIT(dev)); | 399 | struct apm_softc *sc = device_lookup_private(&apm_cd,APMUNIT(dev)); | |
400 | int revents = 0; | 400 | int revents = 0; | |
401 | 401 | |||
402 | APM_LOCK(sc); | 402 | APM_LOCK(sc); | |
403 | if (events & (POLLIN | POLLRDNORM)) { | 403 | if (events & (POLLIN | POLLRDNORM)) { | |
404 | if (sc->event_count) | 404 | if (sc->event_count) | |
405 | revents |= events & (POLLIN | POLLRDNORM); | 405 | revents |= events & (POLLIN | POLLRDNORM); | |
406 | else | 406 | else | |
407 | selrecord(l, &sc->sc_rsel); | 407 | selrecord(l, &sc->sc_rsel); | |
408 | } | 408 | } | |
409 | APM_UNLOCK(sc); | 409 | APM_UNLOCK(sc); | |
410 | 410 | |||
411 | return (revents); | 411 | return (revents); | |
412 | } | 412 | } | |
413 | #endif | 413 | #endif | |
414 | 414 | |||
415 | static void | 415 | static void | |
416 | filt_apmrdetach(struct knote *kn) | 416 | filt_apmrdetach(struct knote *kn) | |
417 | { | 417 | { | |
418 | struct apm_softc *sc = (struct apm_softc *)kn->kn_hook; | 418 | struct apm_softc *sc = (struct apm_softc *)kn->kn_hook; | |
419 | 419 | |||
420 | APM_LOCK(sc); | 420 | APM_LOCK(sc); | |
421 | SLIST_REMOVE(&sc->sc_rsel.sel_klist, kn, knote, kn_selnext); | 421 | SLIST_REMOVE(&sc->sc_rsel.sel_klist, kn, knote, kn_selnext); | |
422 | APM_UNLOCK(sc); | 422 | APM_UNLOCK(sc); | |
423 | } | 423 | } | |
424 | 424 | |||
425 | static int | 425 | static int | |
426 | filt_apmread(struct knote *kn, long hint) | 426 | filt_apmread(struct knote *kn, long hint) | |
427 | { | 427 | { | |
428 | struct apm_softc *sc = kn->kn_hook; | 428 | struct apm_softc *sc = kn->kn_hook; | |
429 | 429 | |||
430 | kn->kn_data = sc->event_count; | 430 | kn->kn_data = sc->event_count; | |
431 | return (kn->kn_data > 0); | 431 | return (kn->kn_data > 0); | |
432 | } | 432 | } | |
433 | 433 | |||
434 | static struct filterops apmread_filtops = | 434 | static struct filterops apmread_filtops = { | |
435 | { 1, NULL, filt_apmrdetach, filt_apmread}; | 435 | .f_isfd = 1, | |
436 | .f_attach = NULL, | |||
437 | .f_detach = filt_apmrdetach, | |||
438 | .f_event = filt_apmread, | |||
439 | }; | |||
436 | 440 | |||
437 | int | 441 | int | |
438 | apmkqfilter(dev_t dev, struct knote *kn) | 442 | apmkqfilter(dev_t dev, struct knote *kn) | |
439 | { | 443 | { | |
440 | struct apm_softc *sc = device_lookup_private(&apm_cd,APMUNIT(dev)); | 444 | struct apm_softc *sc = device_lookup_private(&apm_cd,APMUNIT(dev)); | |
441 | struct klist *klist; | 445 | struct klist *klist; | |
442 | 446 | |||
443 | switch (kn->kn_filter) { | 447 | switch (kn->kn_filter) { | |
444 | case EVFILT_READ: | 448 | case EVFILT_READ: | |
445 | klist = &sc->sc_rsel.sel_klist; | 449 | klist = &sc->sc_rsel.sel_klist; | |
446 | kn->kn_fop = &apmread_filtops; | 450 | kn->kn_fop = &apmread_filtops; | |
447 | break; | 451 | break; | |
448 | default: | 452 | default: | |
449 | return (1); | 453 | return (1); | |
450 | } | 454 | } | |
451 | 455 | |||
452 | kn->kn_hook = sc; | 456 | kn->kn_hook = sc; | |
453 | 457 | |||
454 | APM_LOCK(sc); | 458 | APM_LOCK(sc); | |
455 | SLIST_INSERT_HEAD(klist, kn, kn_selnext); | 459 | SLIST_INSERT_HEAD(klist, kn, kn_selnext); | |
456 | APM_UNLOCK(sc); | 460 | APM_UNLOCK(sc); | |
457 | 461 | |||
458 | return (0); | 462 | return (0); | |
459 | } | 463 | } |
--- src/sys/arch/mips/ralink/ralink_gpio.c 2020/03/10 11:07:39 1.8
+++ src/sys/arch/mips/ralink/ralink_gpio.c 2020/10/30 22:20:38 1.9
@@ -1,1500 +1,1500 @@ | @@ -1,1500 +1,1500 @@ | |||
1 | /* $NetBSD: ralink_gpio.c,v 1.8 2020/03/10 11:07:39 martin Exp $ */ | 1 | /* $NetBSD: ralink_gpio.c,v 1.9 2020/10/30 22:20:38 christos Exp $ */ | |
2 | /*- | 2 | /*- | |
3 | * Copyright (c) 2011 CradlePoint Technology, Inc. | 3 | * Copyright (c) 2011 CradlePoint Technology, Inc. | |
4 | * All rights reserved. | 4 | * All rights reserved. | |
5 | * | 5 | * | |
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 CRADLEPOINT TECHNOLOGY, INC. AND CONTRIBUTORS | 16 | * THIS SOFTWARE IS PROVIDED BY CRADLEPOINT TECHNOLOGY, INC. AND CONTRIBUTORS | |
17 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | 17 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | |
18 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | 18 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |
19 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS | 19 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS | |
20 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | 20 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | |
21 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | 21 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | |
22 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | 22 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | |
23 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | 23 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | |
24 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | 24 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |
25 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | 25 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
26 | * POSSIBILITY OF SUCH DAMAGE. | 26 | * POSSIBILITY OF SUCH DAMAGE. | |
27 | */ | 27 | */ | |
28 | 28 | |||
29 | /* ra_gpio.c -- Ralink 3052 gpio driver */ | 29 | /* ra_gpio.c -- Ralink 3052 gpio driver */ | |
30 | 30 | |||
31 | #include <sys/cdefs.h> | 31 | #include <sys/cdefs.h> | |
32 | __KERNEL_RCSID(0, "$NetBSD: ralink_gpio.c,v 1.8 2020/03/10 11:07:39 martin Exp $"); | 32 | __KERNEL_RCSID(0, "$NetBSD: ralink_gpio.c,v 1.9 2020/10/30 22:20:38 christos Exp $"); | |
33 | 33 | |||
34 | #include <sys/param.h> | 34 | #include <sys/param.h> | |
35 | #include <sys/bus.h> | 35 | #include <sys/bus.h> | |
36 | #include <sys/callout.h> | 36 | #include <sys/callout.h> | |
37 | #include <sys/device.h> | 37 | #include <sys/device.h> | |
38 | #include <sys/event.h> | 38 | #include <sys/event.h> | |
39 | #include <sys/intr.h> | 39 | #include <sys/intr.h> | |
40 | #include <sys/kernel.h> | 40 | #include <sys/kernel.h> | |
41 | #include <sys/systm.h> | 41 | #include <sys/systm.h> | |
42 | 42 | |||
43 | #include <dev/cons.h> | 43 | #include <dev/cons.h> | |
44 | 44 | |||
45 | #include <mips/cpuregs.h> | 45 | #include <mips/cpuregs.h> | |
46 | #include <sys/gpio.h> | 46 | #include <sys/gpio.h> | |
47 | #include <dev/gpio/gpiovar.h> | 47 | #include <dev/gpio/gpiovar.h> | |
48 | 48 | |||
49 | #include <mips/ralink/ralink_reg.h> | 49 | #include <mips/ralink/ralink_reg.h> | |
50 | #include <mips/ralink/ralink_var.h> | 50 | #include <mips/ralink/ralink_var.h> | |
51 | 51 | |||
52 | #if !defined(MT7628) | 52 | #if !defined(MT7628) | |
53 | #define SLICKROCK | 53 | #define SLICKROCK | |
54 | #endif | 54 | #endif | |
55 | #include <mips/ralink/ralink_gpio.h> | 55 | #include <mips/ralink/ralink_gpio.h> | |
56 | 56 | |||
57 | #if 0 | 57 | #if 0 | |
58 | #define ENABLE_RALINK_DEBUG_ERROR 1 | 58 | #define ENABLE_RALINK_DEBUG_ERROR 1 | |
59 | #define ENABLE_RALINK_DEBUG_MISC 1 | 59 | #define ENABLE_RALINK_DEBUG_MISC 1 | |
60 | #define ENABLE_RALINK_DEBUG_INFO 1 | 60 | #define ENABLE_RALINK_DEBUG_INFO 1 | |
61 | #define ENABLE_RALINK_DEBUG_FORCE 1 | 61 | #define ENABLE_RALINK_DEBUG_FORCE 1 | |
62 | #define ENABLE_RALINK_DEBUG_FUNC 1 | 62 | #define ENABLE_RALINK_DEBUG_FUNC 1 | |
63 | #endif | 63 | #endif | |
64 | 64 | |||
65 | #include <mips/ralink/ralink_debug.h> | 65 | #include <mips/ralink/ralink_debug.h> | |
66 | 66 | |||
67 | /* | 67 | /* | |
68 | * From the RT3052 datasheet, the GPIO pins are | 68 | * From the RT3052 datasheet, the GPIO pins are | |
69 | * shared with a number of other functions. Not | 69 | * shared with a number of other functions. Not | |
70 | * all will be available for GPIO. To make sure | 70 | * all will be available for GPIO. To make sure | |
71 | * pins are in GPIO mode, the GPIOMODE purpose | 71 | * pins are in GPIO mode, the GPIOMODE purpose | |
72 | * select register must be set (reset defaults all pins | 72 | * select register must be set (reset defaults all pins | |
73 | * as GPIO except for JTAG) | 73 | * as GPIO except for JTAG) | |
74 | * | 74 | * | |
75 | * Note, GPIO0 is not shared, it is the single dedicated | 75 | * Note, GPIO0 is not shared, it is the single dedicated | |
76 | * GPIO pin. | 76 | * GPIO pin. | |
77 | * | 77 | * | |
78 | * 52 pins: | 78 | * 52 pins: | |
79 | * | 79 | * | |
80 | * 40 - 51 RGMII (GE0_* pins) | 80 | * 40 - 51 RGMII (GE0_* pins) | |
81 | * 24 - 39 SDRAM (MD31:MD16 pins) | 81 | * 24 - 39 SDRAM (MD31:MD16 pins) | |
82 | * 22 - 23 MDIO (MDC/MDIO pins) | 82 | * 22 - 23 MDIO (MDC/MDIO pins) | |
83 | * 17 - 21 JTAG (JTAG_* pins) | 83 | * 17 - 21 JTAG (JTAG_* pins) | |
84 | * 15 - 16 UART Light (RXD2/TXD2 pins) | 84 | * 15 - 16 UART Light (RXD2/TXD2 pins) | |
85 | * 7 - 14 UART Full (8 pins) | 85 | * 7 - 14 UART Full (8 pins) | |
86 | * (7 - 14) UARTF_7 (3'b111 in Share mode reg) | 86 | * (7 - 14) UARTF_7 (3'b111 in Share mode reg) | |
87 | * (11 - 14) UARTF_5 (3'b110 in Share mode reg, same with 6) | 87 | * (11 - 14) UARTF_5 (3'b110 in Share mode reg, same with 6) | |
88 | * (7 - 9) UARTF_4 (3'b100 in Share mode reg) | 88 | * (7 - 9) UARTF_4 (3'b100 in Share mode reg) | |
89 | * 3 - 6 SPI (SPI_* pins) | 89 | * 3 - 6 SPI (SPI_* pins) | |
90 | * 1 - 2 I2C (I2C_SCLK/I2C_SD pins) | 90 | * 1 - 2 I2C (I2C_SCLK/I2C_SD pins) | |
91 | */ | 91 | */ | |
92 | 92 | |||
93 | #ifdef MT7628 | 93 | #ifdef MT7628 | |
94 | #define GPIO_PINS 96 | 94 | #define GPIO_PINS 96 | |
95 | #define SPECIAL_COMMANDS 0 | 95 | #define SPECIAL_COMMANDS 0 | |
96 | #else | 96 | #else | |
97 | #if defined(SLICKROCK) | 97 | #if defined(SLICKROCK) | |
98 | #define GPIO_PINS 96 | 98 | #define GPIO_PINS 96 | |
99 | #else | 99 | #else | |
100 | #define GPIO_PINS 52 | 100 | #define GPIO_PINS 52 | |
101 | #endif | 101 | #endif | |
102 | 102 | |||
103 | /* | 103 | /* | |
104 | * Special commands are pseudo pin numbers used to pass data to bootloader, | 104 | * Special commands are pseudo pin numbers used to pass data to bootloader, | |
105 | */ | 105 | */ | |
106 | #define BOOT_COUNT GPIO_PINS | 106 | #define BOOT_COUNT GPIO_PINS | |
107 | #define UPGRADE (BOOT_COUNT + 1) | 107 | #define UPGRADE (BOOT_COUNT + 1) | |
108 | #define SPECIAL_COMMANDS (UPGRADE + 1 - GPIO_PINS) | 108 | #define SPECIAL_COMMANDS (UPGRADE + 1 - GPIO_PINS) | |
109 | #endif | 109 | #endif | |
110 | 110 | |||
111 | 111 | |||
112 | /* | 112 | /* | |
113 | * The pin_share array maps to the highest pin used for each of the 10 | 113 | * The pin_share array maps to the highest pin used for each of the 10 | |
114 | * GPIO mode bit settings. | 114 | * GPIO mode bit settings. | |
115 | */ | 115 | */ | |
116 | #if defined(MT7628) | 116 | #if defined(MT7628) | |
117 | const static struct { | 117 | const static struct { | |
118 | int pin_start; | 118 | int pin_start; | |
119 | int pin_end; | 119 | int pin_end; | |
120 | uint32_t sysreg; | 120 | uint32_t sysreg; | |
121 | uint32_t regmask; | 121 | uint32_t regmask; | |
122 | uint32_t mode; | 122 | uint32_t mode; | |
123 | } gpio_mux_map[] = { | 123 | } gpio_mux_map[] = { | |
124 | { 0, 3, RA_SYSCTL_GPIO1MODE, GPIO1MODE_I2S, 1 }, | 124 | { 0, 3, RA_SYSCTL_GPIO1MODE, GPIO1MODE_I2S, 1 }, | |
125 | { 4, 5, RA_SYSCTL_GPIO1MODE, GPIO1MODE_I2C, 1 }, | 125 | { 4, 5, RA_SYSCTL_GPIO1MODE, GPIO1MODE_I2C, 1 }, | |
126 | { 6, 6, RA_SYSCTL_GPIO1MODE, GPIO1MODE_SPI_CS1, 1 }, | 126 | { 6, 6, RA_SYSCTL_GPIO1MODE, GPIO1MODE_SPI_CS1, 1 }, | |
127 | { 7, 10, RA_SYSCTL_GPIO1MODE, GPIO1MODE_SPI, 1 }, | 127 | { 7, 10, RA_SYSCTL_GPIO1MODE, GPIO1MODE_SPI, 1 }, | |
128 | { 11, 11, RA_SYSCTL_GPIO1MODE, GPIO1MODE_GPIO, 1 }, | 128 | { 11, 11, RA_SYSCTL_GPIO1MODE, GPIO1MODE_GPIO, 1 }, | |
129 | { 12, 13, RA_SYSCTL_GPIO1MODE, GPIO1MODE_UART0, 1 }, | 129 | { 12, 13, RA_SYSCTL_GPIO1MODE, GPIO1MODE_UART0, 1 }, | |
130 | { 14, 17, RA_SYSCTL_GPIO1MODE, GPIO1MODE_SPIS, 1 }, | 130 | { 14, 17, RA_SYSCTL_GPIO1MODE, GPIO1MODE_SPIS, 1 }, | |
131 | { 18, 18, RA_SYSCTL_GPIO1MODE, GPIO1MODE_PWM0, 1 }, | 131 | { 18, 18, RA_SYSCTL_GPIO1MODE, GPIO1MODE_PWM0, 1 }, | |
132 | { 19, 19, RA_SYSCTL_GPIO1MODE, GPIO1MODE_PWM1, 1 }, | 132 | { 19, 19, RA_SYSCTL_GPIO1MODE, GPIO1MODE_PWM1, 1 }, | |
133 | { 20, 21, RA_SYSCTL_GPIO1MODE, GPIO1MODE_UART2, 1 }, | 133 | { 20, 21, RA_SYSCTL_GPIO1MODE, GPIO1MODE_UART2, 1 }, | |
134 | { 22, 29, RA_SYSCTL_GPIO1MODE, GPIO1MODE_SD, 1 }, | 134 | { 22, 29, RA_SYSCTL_GPIO1MODE, GPIO1MODE_SD, 1 }, | |
135 | { 30, 30, RA_SYSCTL_GPIO2MODE, GPIO2MODE_P4_LED_KN, 1 }, | 135 | { 30, 30, RA_SYSCTL_GPIO2MODE, GPIO2MODE_P4_LED_KN, 1 }, | |
136 | { 31, 31, RA_SYSCTL_GPIO2MODE, GPIO2MODE_P3_LED_KN, 1 }, | 136 | { 31, 31, RA_SYSCTL_GPIO2MODE, GPIO2MODE_P3_LED_KN, 1 }, | |
137 | { 32, 32, RA_SYSCTL_GPIO2MODE, GPIO2MODE_P2_LED_KN, 1 }, | 137 | { 32, 32, RA_SYSCTL_GPIO2MODE, GPIO2MODE_P2_LED_KN, 1 }, | |
138 | { 33, 33, RA_SYSCTL_GPIO2MODE, GPIO2MODE_P1_LED_KN, 1 }, | 138 | { 33, 33, RA_SYSCTL_GPIO2MODE, GPIO2MODE_P1_LED_KN, 1 }, | |
139 | { 34, 34, RA_SYSCTL_GPIO2MODE, GPIO2MODE_P0_LED_KN, 1 }, | 139 | { 34, 34, RA_SYSCTL_GPIO2MODE, GPIO2MODE_P0_LED_KN, 1 }, | |
140 | { 35, 35, RA_SYSCTL_GPIO2MODE, GPIO2MODE_WLED_KN, 1 }, | 140 | { 35, 35, RA_SYSCTL_GPIO2MODE, GPIO2MODE_WLED_KN, 1 }, | |
141 | { 36, 36, RA_SYSCTL_GPIO1MODE, GPIO1MODE_PERST, 1 }, | 141 | { 36, 36, RA_SYSCTL_GPIO1MODE, GPIO1MODE_PERST, 1 }, | |
142 | { 37, 37, RA_SYSCTL_GPIO1MODE, GPIO1MODE_REFCLK, 1 }, | 142 | { 37, 37, RA_SYSCTL_GPIO1MODE, GPIO1MODE_REFCLK, 1 }, | |
143 | { 38, 38, RA_SYSCTL_GPIO1MODE, GPIO1MODE_WDT, 1 }, | 143 | { 38, 38, RA_SYSCTL_GPIO1MODE, GPIO1MODE_WDT, 1 }, | |
144 | { 39, 39, RA_SYSCTL_GPIO2MODE, GPIO2MODE_P4_LED_AN, 1 }, | 144 | { 39, 39, RA_SYSCTL_GPIO2MODE, GPIO2MODE_P4_LED_AN, 1 }, | |
145 | { 40, 40, RA_SYSCTL_GPIO2MODE, GPIO2MODE_P3_LED_AN, 1 }, | 145 | { 40, 40, RA_SYSCTL_GPIO2MODE, GPIO2MODE_P3_LED_AN, 1 }, | |
146 | { 41, 41, RA_SYSCTL_GPIO2MODE, GPIO2MODE_P2_LED_AN, 1 }, | 146 | { 41, 41, RA_SYSCTL_GPIO2MODE, GPIO2MODE_P2_LED_AN, 1 }, | |
147 | { 42, 42, RA_SYSCTL_GPIO2MODE, GPIO2MODE_P1_LED_AN, 1 }, | 147 | { 42, 42, RA_SYSCTL_GPIO2MODE, GPIO2MODE_P1_LED_AN, 1 }, | |
148 | { 43, 43, RA_SYSCTL_GPIO2MODE, GPIO2MODE_P0_LED_AN, 1 }, | 148 | { 43, 43, RA_SYSCTL_GPIO2MODE, GPIO2MODE_P0_LED_AN, 1 }, | |
149 | { 44, 44, RA_SYSCTL_GPIO2MODE, GPIO2MODE_WLED_AN, 1 }, | 149 | { 44, 44, RA_SYSCTL_GPIO2MODE, GPIO2MODE_WLED_AN, 1 }, | |
150 | { 45, 45, RA_SYSCTL_GPIO1MODE, GPIO1MODE_UART1, 1 }, | 150 | { 45, 45, RA_SYSCTL_GPIO1MODE, GPIO1MODE_UART1, 1 }, | |
151 | { 46, 46, RA_SYSCTL_GPIO1MODE, GPIO1MODE_UART1, 1 }, | 151 | { 46, 46, RA_SYSCTL_GPIO1MODE, GPIO1MODE_UART1, 1 }, | |
152 | }; | 152 | }; | |
153 | #else | 153 | #else | |
154 | #if defined(SLICKROCK) | 154 | #if defined(SLICKROCK) | |
155 | #define SR_GPIO_MODE 0xc1c1f | 155 | #define SR_GPIO_MODE 0xc1c1f | |
156 | #else | 156 | #else | |
157 | const static u_int8_t pin_share[] = { | 157 | const static u_int8_t pin_share[] = { | |
158 | 2, 6, 9, 14, 14, 16, 21, 23, 39, 51 | 158 | 2, 6, 9, 14, 14, 16, 21, 23, 39, 51 | |
159 | }; | 159 | }; | |
160 | #endif | 160 | #endif | |
161 | #endif /* MT7628 */ | 161 | #endif /* MT7628 */ | |
162 | 162 | |||
163 | #define DEBOUNCE_TIME 150 /* Milliseconds */ | 163 | #define DEBOUNCE_TIME 150 /* Milliseconds */ | |
164 | 164 | |||
165 | #if defined(TABLEROCK) || defined(SPOT2) || defined(PUCK) || defined(MOAB) | 165 | #if defined(TABLEROCK) || defined(SPOT2) || defined(PUCK) || defined(MOAB) | |
166 | 166 | |||
167 | static const u_int32_t debounce_pin[DEBOUNCED_PINS] = { | 167 | static const u_int32_t debounce_pin[DEBOUNCED_PINS] = { | |
168 | WPS_BUTTON, | 168 | WPS_BUTTON, | |
169 | POWER_OFF_BUTTON, | 169 | POWER_OFF_BUTTON, | |
170 | DOCK_SENSE, | 170 | DOCK_SENSE, | |
171 | IN_5V, | 171 | IN_5V, | |
172 | LAN_WAN_SW | 172 | LAN_WAN_SW | |
173 | }; | 173 | }; | |
174 | static struct timeval debounce_time[DEBOUNCED_PINS]; | 174 | static struct timeval debounce_time[DEBOUNCED_PINS]; | |
175 | 175 | |||
176 | /* LED defines for display during boot */ | 176 | /* LED defines for display during boot */ | |
177 | static const char led_array1[] = { | 177 | static const char led_array1[] = { | |
178 | LED_BATT_7, | 178 | LED_BATT_7, | |
179 | LED_BATT_8, | 179 | LED_BATT_8, | |
180 | LED_BATT_9, | 180 | LED_BATT_9, | |
181 | LED_BATT_10, | 181 | LED_BATT_10, | |
182 | LED_SS_11, | 182 | LED_SS_11, | |
183 | LED_SS_12, | 183 | LED_SS_12, | |
184 | LED_SS_13, | 184 | LED_SS_13, | |
185 | LED_SS_14 | 185 | LED_SS_14 | |
186 | }; | 186 | }; | |
187 | 187 | |||
188 | #define SET_SS_LED_REG RA_PIO_24_39_SET_BIT | 188 | #define SET_SS_LED_REG RA_PIO_24_39_SET_BIT | |
189 | #define CLEAR_SS_LED_REG RA_PIO_24_39_CLR_BIT | 189 | #define CLEAR_SS_LED_REG RA_PIO_24_39_CLR_BIT | |
190 | #define SS_OFFSET 24 | 190 | #define SS_OFFSET 24 | |
191 | #define BOOT_LED_TIMING 3000 | 191 | #define BOOT_LED_TIMING 3000 | |
192 | 192 | |||
193 | #endif /* TABLEROCK || SPOT2 || PUCK || MOAB */ | 193 | #endif /* TABLEROCK || SPOT2 || PUCK || MOAB */ | |
194 | 194 | |||
195 | #if defined(PEBBLES500) || defined (PEBBLES35) | 195 | #if defined(PEBBLES500) || defined (PEBBLES35) | |
196 | 196 | |||
197 | static const u_int32_t debounce_pin[DEBOUNCED_PINS] = { | 197 | static const u_int32_t debounce_pin[DEBOUNCED_PINS] = { | |
198 | WPS_BUTTON, | 198 | WPS_BUTTON, | |
199 | SOFT_RST_IN_BUTTON, | 199 | SOFT_RST_IN_BUTTON, | |
200 | CURRENT_LIMIT_FLAG1_3_3v, | 200 | CURRENT_LIMIT_FLAG1_3_3v, | |
201 | CURRENT_LIMIT_FLAG_USB1, | 201 | CURRENT_LIMIT_FLAG_USB1, | |
202 | CURRENT_LIMIT_FLAG1_1_5v, | 202 | CURRENT_LIMIT_FLAG1_1_5v, | |
203 | EXCARD_ATTACH | 203 | EXCARD_ATTACH | |
204 | }; | 204 | }; | |
205 | static struct timeval debounce_time[DEBOUNCED_PINS]; | 205 | static struct timeval debounce_time[DEBOUNCED_PINS]; | |
206 | 206 | |||
207 | /* LED defines for display during boot */ | 207 | /* LED defines for display during boot */ | |
208 | #if defined(PEBBLES500) | 208 | #if defined(PEBBLES500) | |
209 | static const char led_array1[] = { | 209 | static const char led_array1[] = { | |
210 | LED_SS_13, | 210 | LED_SS_13, | |
211 | LED_SS_12, | 211 | LED_SS_12, | |
212 | LED_SS_11, | 212 | LED_SS_11, | |
213 | LED_SS_10 | 213 | LED_SS_10 | |
214 | }; | 214 | }; | |
215 | #else | 215 | #else | |
216 | static const char led_array1[] = {}; | 216 | static const char led_array1[] = {}; | |
217 | #endif | 217 | #endif | |
218 | 218 | |||
219 | #define SET_SS_LED_REG RA_PIO_40_51_SET_BIT | 219 | #define SET_SS_LED_REG RA_PIO_40_51_SET_BIT | |
220 | #define CLEAR_SS_LED_REG RA_PIO_40_51_CLR_BIT | 220 | #define CLEAR_SS_LED_REG RA_PIO_40_51_CLR_BIT | |
221 | #define SS_OFFSET 40 | 221 | #define SS_OFFSET 40 | |
222 | #define BOOT_LED_TIMING 5500 | 222 | #define BOOT_LED_TIMING 5500 | |
223 | 223 | |||
224 | #endif /* PEBBLES500 || PEBBLES35 */ | 224 | #endif /* PEBBLES500 || PEBBLES35 */ | |
225 | 225 | |||
226 | 226 | |||
227 | #if defined(SLICKROCK) | 227 | #if defined(SLICKROCK) | |
228 | 228 | |||
229 | static const u_int32_t debounce_pin[DEBOUNCED_PINS] = { | 229 | static const u_int32_t debounce_pin[DEBOUNCED_PINS] = { | |
230 | WPS_BUTTON, | 230 | WPS_BUTTON, | |
231 | SOFT_RST_IN_BUTTON, | 231 | SOFT_RST_IN_BUTTON, | |
232 | SS_BUTTON, | 232 | SS_BUTTON, | |
233 | CURRENT_LIMIT_FLAG_USB1, | 233 | CURRENT_LIMIT_FLAG_USB1, | |
234 | CURRENT_LIMIT_FLAG_USB2, | 234 | CURRENT_LIMIT_FLAG_USB2, | |
235 | CURRENT_LIMIT_FLAG_USB3, | 235 | CURRENT_LIMIT_FLAG_USB3, | |
236 | CURRENT_LIMIT_FLAG_EX1, | 236 | CURRENT_LIMIT_FLAG_EX1, | |
237 | CURRENT_LIMIT_FLAG_EX2, | 237 | CURRENT_LIMIT_FLAG_EX2, | |
238 | WIFI_ENABLE | 238 | WIFI_ENABLE | |
239 | }; | 239 | }; | |
240 | static struct timeval debounce_time[DEBOUNCED_PINS]; | 240 | static struct timeval debounce_time[DEBOUNCED_PINS]; | |
241 | 241 | |||
242 | /* LED defines for display during boot */ | 242 | /* LED defines for display during boot */ | |
243 | static const char led_array1[] = { | 243 | static const char led_array1[] = { | |
244 | LED_SS_13, | 244 | LED_SS_13, | |
245 | LED_SS_12, | 245 | LED_SS_12, | |
246 | LED_SS_11, | 246 | LED_SS_11, | |
247 | LED_SS_10 | 247 | LED_SS_10 | |
248 | }; | 248 | }; | |
249 | 249 | |||
250 | #define SET_SS_LED_REG RA_PIO_40_51_SET_BIT | 250 | #define SET_SS_LED_REG RA_PIO_40_51_SET_BIT | |
251 | #define CLEAR_SS_LED_REG RA_PIO_40_51_CLR_BIT | 251 | #define CLEAR_SS_LED_REG RA_PIO_40_51_CLR_BIT | |
252 | #define SS_OFFSET 40 | 252 | #define SS_OFFSET 40 | |
253 | #define BOOT_LED_TIMING 3250 | 253 | #define BOOT_LED_TIMING 3250 | |
254 | 254 | |||
255 | #endif /* SLICKROCK */ | 255 | #endif /* SLICKROCK */ | |
256 | 256 | |||
257 | #ifndef DEBOUNCED_PINS | 257 | #ifndef DEBOUNCED_PINS | |
258 | static const u_int32_t debounce_pin[] = {}; | 258 | static const u_int32_t debounce_pin[] = {}; | |
259 | static struct timeval debounce_time[] = {}; | 259 | static struct timeval debounce_time[] = {}; | |
260 | #endif | 260 | #endif | |
261 | #ifndef BOOT_LED_TIMING | 261 | #ifndef BOOT_LED_TIMING | |
262 | static const char led_array1[] = {}; | 262 | static const char led_array1[] = {}; | |
263 | #endif | 263 | #endif | |
264 | 264 | |||
265 | #define RA_GPIO_PIN_INIT(sc, var, pin, ptp, regname) \ | 265 | #define RA_GPIO_PIN_INIT(sc, var, pin, ptp, regname) \ | |
266 | do { \ | 266 | do { \ | |
267 | const u_int _reg_bit = 1 << (pin - ptp->pin_reg_base); \ | 267 | const u_int _reg_bit = 1 << (pin - ptp->pin_reg_base); \ | |
268 | const u_int _mask_bit = 1 << (pin - ptp->pin_mask_base);\ | 268 | const u_int _mask_bit = 1 << (pin - ptp->pin_mask_base);\ | |
269 | var = gp_read(sc, ptp->regname.reg); \ | 269 | var = gp_read(sc, ptp->regname.reg); \ | |
270 | if ((ptp->regname.mask & _mask_bit) != 0) { \ | 270 | if ((ptp->regname.mask & _mask_bit) != 0) { \ | |
271 | var |= _reg_bit; \ | 271 | var |= _reg_bit; \ | |
272 | } else { \ | 272 | } else { \ | |
273 | var &= ~_reg_bit; \ | 273 | var &= ~_reg_bit; \ | |
274 | } \ | 274 | } \ | |
275 | gp_write(sc, ptp->regname.reg, var); \ | 275 | gp_write(sc, ptp->regname.reg, var); \ | |
276 | } while (0) | 276 | } while (0) | |
277 | 277 | |||
278 | #define RA_GPIO_PIN_INIT_DIR(sc, var, pin, ptp) \ | 278 | #define RA_GPIO_PIN_INIT_DIR(sc, var, pin, ptp) \ | |
279 | do { \ | 279 | do { \ | |
280 | const u_int _reg_bit = 1 << (pin - ptp->pin_reg_base); \ | 280 | const u_int _reg_bit = 1 << (pin - ptp->pin_reg_base); \ | |
281 | const u_int _mask_bit = 1 << (pin - ptp->pin_mask_base);\ | 281 | const u_int _mask_bit = 1 << (pin - ptp->pin_mask_base);\ | |
282 | var = gp_read(sc, ptp->pin_dir.reg); \ | 282 | var = gp_read(sc, ptp->pin_dir.reg); \ | |
283 | if ((ptp->pin_dir.mask & _mask_bit) != 0) { \ | 283 | if ((ptp->pin_dir.mask & _mask_bit) != 0) { \ | |
284 | var |= _reg_bit; \ | 284 | var |= _reg_bit; \ | |
285 | sc->sc_pins[pin].pin_flags = GPIO_PIN_OUTPUT; \ | 285 | sc->sc_pins[pin].pin_flags = GPIO_PIN_OUTPUT; \ | |
286 | } else { \ | 286 | } else { \ | |
287 | var &= ~_reg_bit; \ | 287 | var &= ~_reg_bit; \ | |
288 | sc->sc_pins[pin].pin_flags = GPIO_PIN_INPUT; \ | 288 | sc->sc_pins[pin].pin_flags = GPIO_PIN_INPUT; \ | |
289 | } \ | 289 | } \ | |
290 | gp_write(sc, ptp->pin_dir.reg, var); \ | 290 | gp_write(sc, ptp->pin_dir.reg, var); \ | |
291 | } while (0) | 291 | } while (0) | |
292 | 292 | |||
293 | 293 | |||
294 | 294 | |||
295 | typedef struct ra_gpio_softc { | 295 | typedef struct ra_gpio_softc { | |
296 | device_t sc_dev; | 296 | device_t sc_dev; | |
297 | struct gpio_chipset_tag sc_gc; | 297 | struct gpio_chipset_tag sc_gc; | |
298 | gpio_pin_t sc_pins[GPIO_PINS + SPECIAL_COMMANDS]; | 298 | gpio_pin_t sc_pins[GPIO_PINS + SPECIAL_COMMANDS]; | |
299 | 299 | |||
300 | bus_space_tag_t sc_memt; /* bus space tag */ | 300 | bus_space_tag_t sc_memt; /* bus space tag */ | |
301 | 301 | |||
302 | bus_space_handle_t sc_sy_memh; /* Sysctl bus space handle */ | 302 | bus_space_handle_t sc_sy_memh; /* Sysctl bus space handle */ | |
303 | int sc_sy_size; /* size of Sysctl register space */ | 303 | int sc_sy_size; /* size of Sysctl register space */ | |
304 | 304 | |||
305 | bus_space_handle_t sc_gp_memh; /* PIO bus space handle */ | 305 | bus_space_handle_t sc_gp_memh; /* PIO bus space handle */ | |
306 | int sc_gp_size; /* size of PIO register space */ | 306 | int sc_gp_size; /* size of PIO register space */ | |
307 | 307 | |||
308 | void *sc_ih; /* interrupt handle */ | 308 | void *sc_ih; /* interrupt handle */ | |
309 | void *sc_si; /* softintr handle */ | 309 | void *sc_si; /* softintr handle */ | |
310 | 310 | |||
311 | struct callout sc_tick_callout; /* For debouncing inputs */ | 311 | struct callout sc_tick_callout; /* For debouncing inputs */ | |
312 | 312 | |||
313 | /* | 313 | /* | |
314 | * These track gpio pins that have interrupted | 314 | * These track gpio pins that have interrupted | |
315 | */ | 315 | */ | |
316 | #if defined(MT7628) | 316 | #if defined(MT7628) | |
317 | uint32_t sc_intr_status00_31; | 317 | uint32_t sc_intr_status00_31; | |
318 | uint32_t sc_intr_status32_63; | 318 | uint32_t sc_intr_status32_63; | |
319 | uint32_t sc_intr_status64_95; | 319 | uint32_t sc_intr_status64_95; | |
320 | #else | 320 | #else | |
321 | uint32_t sc_intr_status00_23; | 321 | uint32_t sc_intr_status00_23; | |
322 | uint32_t sc_intr_status24_39; | 322 | uint32_t sc_intr_status24_39; | |
323 | uint32_t sc_intr_status40_51; | 323 | uint32_t sc_intr_status40_51; | |
324 | uint32_t sc_intr_status72_95; | 324 | uint32_t sc_intr_status72_95; | |
325 | #endif | 325 | #endif | |
326 | 326 | |||
327 | } ra_gpio_softc_t; | 327 | } ra_gpio_softc_t; | |
328 | 328 | |||
329 | static int ra_gpio_match(device_t, cfdata_t , void *); | 329 | static int ra_gpio_match(device_t, cfdata_t , void *); | |
330 | static void ra_gpio_attach(device_t, device_t, void *); | 330 | static void ra_gpio_attach(device_t, device_t, void *); | |
331 | #ifdef NOTYET | 331 | #ifdef NOTYET | |
332 | static int ra_gpio_open(void *, device_t); | 332 | static int ra_gpio_open(void *, device_t); | |
333 | static int ra_gpio_close(void *, device_t); | 333 | static int ra_gpio_close(void *, device_t); | |
334 | #endif | 334 | #endif | |
335 | static void ra_gpio_pin_init(ra_gpio_softc_t *, int); | 335 | static void ra_gpio_pin_init(ra_gpio_softc_t *, int); | |
336 | static void ra_gpio_pin_ctl(void *, int, int); | 336 | static void ra_gpio_pin_ctl(void *, int, int); | |
337 | 337 | |||
338 | static int ra_gpio_intr(void *); | 338 | static int ra_gpio_intr(void *); | |
339 | static void ra_gpio_softintr(void *); | 339 | static void ra_gpio_softintr(void *); | |
340 | static void ra_gpio_debounce_process(void *); | 340 | static void ra_gpio_debounce_process(void *); | |
341 | static void ra_gpio_debounce_setup(ra_gpio_softc_t *); | 341 | static void ra_gpio_debounce_setup(ra_gpio_softc_t *); | |
342 | 342 | |||
343 | static void disable_gpio_interrupt(ra_gpio_softc_t *, int); | 343 | static void disable_gpio_interrupt(ra_gpio_softc_t *, int); | |
344 | static void enable_gpio_interrupt(ra_gpio_softc_t *, int); | 344 | static void enable_gpio_interrupt(ra_gpio_softc_t *, int); | |
345 | 345 | |||
346 | static void gpio_reset_registers(ra_gpio_softc_t *); | 346 | static void gpio_reset_registers(ra_gpio_softc_t *); | |
347 | #if 0 | 347 | #if 0 | |
348 | static void gpio_register_dump(ra_gpio_softc_t *); | 348 | static void gpio_register_dump(ra_gpio_softc_t *); | |
349 | #endif | 349 | #endif | |
350 | 350 | |||
351 | typedef struct pin_reg { | 351 | typedef struct pin_reg { | |
352 | u_int mask; | 352 | u_int mask; | |
353 | u_int reg; | 353 | u_int reg; | |
354 | } pin_reg_t; | 354 | } pin_reg_t; | |
355 | 355 | |||
356 | typedef struct pin_tab { | 356 | typedef struct pin_tab { | |
357 | int pin_reg_base; | 357 | int pin_reg_base; | |
358 | int pin_reg_limit; | 358 | int pin_reg_limit; | |
359 | int pin_mask_base; | 359 | int pin_mask_base; | |
360 | u_int pin_enabled; | 360 | u_int pin_enabled; | |
361 | u_int pin_input; | 361 | u_int pin_input; | |
362 | u_int pin_output_clr; | 362 | u_int pin_output_clr; | |
363 | u_int pin_output_set; | 363 | u_int pin_output_set; | |
364 | pin_reg_t pin_dir; | 364 | pin_reg_t pin_dir; | |
365 | pin_reg_t pin_rise; | 365 | pin_reg_t pin_rise; | |
366 | pin_reg_t pin_fall; | 366 | pin_reg_t pin_fall; | |
367 | pin_reg_t pin_pol; | 367 | pin_reg_t pin_pol; | |
368 | } pin_tab_t; | 368 | } pin_tab_t; | |
369 | 369 | |||
370 | /* | 370 | /* | |
371 | * use pin_tab[] in conjunction with pin_tab_index[] | 371 | * use pin_tab[] in conjunction with pin_tab_index[] | |
372 | * to look up register offsets, masks, etc. for a given GPIO pin, | 372 | * to look up register offsets, masks, etc. for a given GPIO pin, | |
373 | * instead of lots of if/then/else test & branching | 373 | * instead of lots of if/then/else test & branching | |
374 | */ | 374 | */ | |
375 | static const pin_tab_t pin_tab[] = { | 375 | static const pin_tab_t pin_tab[] = { | |
376 | #if defined(MT7628) | 376 | #if defined(MT7628) | |
377 | { | 377 | { | |
378 | 0, 31, 0, 0xffffffff, | 378 | 0, 31, 0, 0xffffffff, | |
379 | RA_PIO_00_31_DATA, | 379 | RA_PIO_00_31_DATA, | |
380 | RA_PIO_00_31_CLR_BIT, | 380 | RA_PIO_00_31_CLR_BIT, | |
381 | RA_PIO_00_31_SET_BIT, | 381 | RA_PIO_00_31_SET_BIT, | |
382 | { 0xffffffff, RA_PIO_00_31_DIR }, | 382 | { 0xffffffff, RA_PIO_00_31_DIR }, | |
383 | { 0xffffffff, RA_PIO_00_31_INT_RISE_EN }, | 383 | { 0xffffffff, RA_PIO_00_31_INT_RISE_EN }, | |
384 | { 0xffffffff, RA_PIO_00_31_INT_FALL_EN }, | 384 | { 0xffffffff, RA_PIO_00_31_INT_FALL_EN }, | |
385 | { 0xffffffff, RA_PIO_00_31_POLARITY } | 385 | { 0xffffffff, RA_PIO_00_31_POLARITY } | |
386 | }, | 386 | }, | |
387 | { | 387 | { | |
388 | 32, 63, 32, 0xffffffff, | 388 | 32, 63, 32, 0xffffffff, | |
389 | RA_PIO_32_63_DATA, | 389 | RA_PIO_32_63_DATA, | |
390 | RA_PIO_32_63_CLR_BIT, | 390 | RA_PIO_32_63_CLR_BIT, | |
391 | RA_PIO_32_63_SET_BIT, | 391 | RA_PIO_32_63_SET_BIT, | |
392 | { 0xffffffff, RA_PIO_32_63_DIR }, | 392 | { 0xffffffff, RA_PIO_32_63_DIR }, | |
393 | { 0xffffffff, RA_PIO_32_63_INT_RISE_EN }, | 393 | { 0xffffffff, RA_PIO_32_63_INT_RISE_EN }, | |
394 | { 0xffffffff, RA_PIO_32_63_INT_FALL_EN }, | 394 | { 0xffffffff, RA_PIO_32_63_INT_FALL_EN }, | |
395 | { 0xffffffff, RA_PIO_32_63_POLARITY } | 395 | { 0xffffffff, RA_PIO_32_63_POLARITY } | |
396 | }, | 396 | }, | |
397 | { | 397 | { | |
398 | 64, 95, 64, 0xffffffff, | 398 | 64, 95, 64, 0xffffffff, | |
399 | RA_PIO_64_95_DATA, | 399 | RA_PIO_64_95_DATA, | |
400 | RA_PIO_64_95_CLR_BIT, | 400 | RA_PIO_64_95_CLR_BIT, | |
401 | RA_PIO_64_95_SET_BIT, | 401 | RA_PIO_64_95_SET_BIT, | |
402 | { 0xffffffff, RA_PIO_64_95_DIR }, | 402 | { 0xffffffff, RA_PIO_64_95_DIR }, | |
403 | { 0xffffffff, RA_PIO_64_95_INT_RISE_EN }, | 403 | { 0xffffffff, RA_PIO_64_95_INT_RISE_EN }, | |
404 | { 0xffffffff, RA_PIO_64_95_INT_FALL_EN }, | 404 | { 0xffffffff, RA_PIO_64_95_INT_FALL_EN }, | |
405 | { 0xffffffff, RA_PIO_64_95_POLARITY } | 405 | { 0xffffffff, RA_PIO_64_95_POLARITY } | |
406 | } | 406 | } | |
407 | #else | 407 | #else | |
408 | { | 408 | { | |
409 | 0, 24, 0, GPIO_PIN_MASK, | 409 | 0, 24, 0, GPIO_PIN_MASK, | |
410 | RA_PIO_00_23_DATA, | 410 | RA_PIO_00_23_DATA, | |
411 | RA_PIO_00_23_CLR_BIT, | 411 | RA_PIO_00_23_CLR_BIT, | |
412 | RA_PIO_00_23_SET_BIT, | 412 | RA_PIO_00_23_SET_BIT, | |
413 | { GPIO_OUTPUT_PIN_MASK, RA_PIO_00_23_DIR, }, | 413 | { GPIO_OUTPUT_PIN_MASK, RA_PIO_00_23_DIR, }, | |
414 | { GPIO_INT_PIN_MASK, RA_PIO_00_23_INT_RISE_EN, }, | 414 | { GPIO_INT_PIN_MASK, RA_PIO_00_23_INT_RISE_EN, }, | |
415 | { GPIO_INT_FEDGE_PIN_MASK, RA_PIO_00_23_INT_RISE_EN, }, | 415 | { GPIO_INT_FEDGE_PIN_MASK, RA_PIO_00_23_INT_RISE_EN, }, | |
416 | { GPIO_POL_MASK, RA_PIO_00_23_POLARITY, }, | 416 | { GPIO_POL_MASK, RA_PIO_00_23_POLARITY, }, | |
417 | }, | 417 | }, | |
418 | { | 418 | { | |
419 | 24, 40, 24, GPIO_PIN_MASK_24_51, | 419 | 24, 40, 24, GPIO_PIN_MASK_24_51, | |
420 | RA_PIO_24_39_DATA, | 420 | RA_PIO_24_39_DATA, | |
421 | RA_PIO_24_39_CLR_BIT, | 421 | RA_PIO_24_39_CLR_BIT, | |
422 | RA_PIO_24_39_SET_BIT, | 422 | RA_PIO_24_39_SET_BIT, | |
423 | { GPIO_OUTPUT_PIN_MASK_24_51, RA_PIO_24_39_DIR, }, | 423 | { GPIO_OUTPUT_PIN_MASK_24_51, RA_PIO_24_39_DIR, }, | |
424 | { GPIO_INT_PIN_MASK_24_51, RA_PIO_24_39_INT_RISE_EN, }, | 424 | { GPIO_INT_PIN_MASK_24_51, RA_PIO_24_39_INT_RISE_EN, }, | |
425 | { GPIO_INT_FEDGE_PIN_MASK_24_51, RA_PIO_24_39_INT_FALL_EN, }, | 425 | { GPIO_INT_FEDGE_PIN_MASK_24_51, RA_PIO_24_39_INT_FALL_EN, }, | |
426 | { GPIO_POL_MASK_24_51, RA_PIO_24_39_POLARITY, }, | 426 | { GPIO_POL_MASK_24_51, RA_PIO_24_39_POLARITY, }, | |
427 | }, | 427 | }, | |
428 | { | 428 | { | |
429 | 40, 52, 24, GPIO_PIN_MASK_24_51, | 429 | 40, 52, 24, GPIO_PIN_MASK_24_51, | |
430 | RA_PIO_40_51_DATA, | 430 | RA_PIO_40_51_DATA, | |
431 | RA_PIO_40_51_CLR_BIT, | 431 | RA_PIO_40_51_CLR_BIT, | |
432 | RA_PIO_40_51_SET_BIT, | 432 | RA_PIO_40_51_SET_BIT, | |
433 | { GPIO_OUTPUT_PIN_MASK_24_51, RA_PIO_40_51_DIR, }, | 433 | { GPIO_OUTPUT_PIN_MASK_24_51, RA_PIO_40_51_DIR, }, | |
434 | { GPIO_INT_PIN_MASK_24_51, RA_PIO_40_51_INT_RISE_EN, }, | 434 | { GPIO_INT_PIN_MASK_24_51, RA_PIO_40_51_INT_RISE_EN, }, | |
435 | { GPIO_INT_FEDGE_PIN_MASK_24_51, RA_PIO_40_51_INT_FALL_EN, }, | 435 | { GPIO_INT_FEDGE_PIN_MASK_24_51, RA_PIO_40_51_INT_FALL_EN, }, | |
436 | { GPIO_POL_MASK_24_51, RA_PIO_40_51_POLARITY, }, | 436 | { GPIO_POL_MASK_24_51, RA_PIO_40_51_POLARITY, }, | |
437 | }, | 437 | }, | |
438 | #if defined(SLICKROCK) | 438 | #if defined(SLICKROCK) | |
439 | { | 439 | { | |
440 | 72, 96, 72, GPIO_PIN_MASK_72_95, | 440 | 72, 96, 72, GPIO_PIN_MASK_72_95, | |
441 | RA_PIO_72_95_DATA, | 441 | RA_PIO_72_95_DATA, | |
442 | RA_PIO_72_95_CLR_BIT, | 442 | RA_PIO_72_95_CLR_BIT, | |
443 | RA_PIO_72_95_SET_BIT, | 443 | RA_PIO_72_95_SET_BIT, | |
444 | { GPIO_OUTPUT_PIN_MASK_72_95, RA_PIO_72_95_DIR, }, | 444 | { GPIO_OUTPUT_PIN_MASK_72_95, RA_PIO_72_95_DIR, }, | |
445 | { GPIO_INT_PIN_MASK_72_95, RA_PIO_72_95_INT_RISE_EN, }, | 445 | { GPIO_INT_PIN_MASK_72_95, RA_PIO_72_95_INT_RISE_EN, }, | |
446 | { GPIO_INT_FEDGE_PIN_MASK_72_95, RA_PIO_72_95_INT_FALL_EN, }, | 446 | { GPIO_INT_FEDGE_PIN_MASK_72_95, RA_PIO_72_95_INT_FALL_EN, }, | |
447 | { GPIO_POL_MASK_72_95, RA_PIO_72_95_POLARITY, }, | 447 | { GPIO_POL_MASK_72_95, RA_PIO_72_95_POLARITY, }, | |
448 | }, | 448 | }, | |
449 | #endif | 449 | #endif | |
450 | #endif | 450 | #endif | |
451 | }; | 451 | }; | |
452 | 452 | |||
453 | /* | 453 | /* | |
454 | * use pin_tab_index[] to determine index in pin_tab[] | 454 | * use pin_tab_index[] to determine index in pin_tab[] | |
455 | * for a given pin. -1 means there is no pin there. | 455 | * for a given pin. -1 means there is no pin there. | |
456 | */ | 456 | */ | |
457 | static const int pin_tab_index[GPIO_PINS] = { | 457 | static const int pin_tab_index[GPIO_PINS] = { | |
458 | #if defined(MT7628) | 458 | #if defined(MT7628) | |
459 | /* 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 */ | 459 | /* 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 */ | |
460 | /* 0 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | 460 | /* 0 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |
461 | /* 16 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | 461 | /* 16 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |
462 | /* 32 */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, | 462 | /* 32 */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, | |
463 | /* 48 */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, | 463 | /* 48 */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, | |
464 | /* 64 */ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, | 464 | /* 64 */ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, | |
465 | /* 80 */ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 | 465 | /* 80 */ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 | |
466 | #else /* !MT7628 */ | 466 | #else /* !MT7628 */ | |
467 | /* 0 1 2 3 4 5 6 7 8 9 */ | 467 | /* 0 1 2 3 4 5 6 7 8 9 */ | |
468 | /* 0 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | 468 | /* 0 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |
469 | /* 10 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | 469 | /* 10 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |
470 | /* 20 */ 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, | 470 | /* 20 */ 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, | |
471 | /* 30 */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, | 471 | /* 30 */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, | |
472 | /* 40 */ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, | 472 | /* 40 */ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, | |
473 | /* 50 */ 2, 2, | 473 | /* 50 */ 2, 2, | |
474 | #if defined(SLICKROCK) | 474 | #if defined(SLICKROCK) | |
475 | /* 50 */ -1, -1, -1, -1, -1, -1, -1, -1, | 475 | /* 50 */ -1, -1, -1, -1, -1, -1, -1, -1, | |
476 | /* 60 */ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, | 476 | /* 60 */ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, | |
477 | /* 70 */ -1, -1, | 477 | /* 70 */ -1, -1, | |
478 | /* 72 */ 3, 3, 3, 3, 3, 3, 3, 3, | 478 | /* 72 */ 3, 3, 3, 3, 3, 3, 3, 3, | |
479 | /* 80 */ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, | 479 | /* 80 */ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, | |
480 | /* 90 */ 3, 3, 3, 3, 3, 3 | 480 | /* 90 */ 3, 3, 3, 3, 3, 3 | |
481 | #endif | 481 | #endif | |
482 | #endif /* !MT7628 */ | 482 | #endif /* !MT7628 */ | |
483 | }; | 483 | }; | |
484 | 484 | |||
485 | CFATTACH_DECL_NEW(rgpio, sizeof(struct ra_gpio_softc), ra_gpio_match, | 485 | CFATTACH_DECL_NEW(rgpio, sizeof(struct ra_gpio_softc), ra_gpio_match, | |
486 | ra_gpio_attach, NULL, NULL); | 486 | ra_gpio_attach, NULL, NULL); | |
487 | 487 | |||
488 | /* | 488 | /* | |
489 | * Event handler calls and structures | 489 | * Event handler calls and structures | |
490 | */ | 490 | */ | |
491 | static int gpio_event_app_user_attach(struct knote *); | 491 | static int gpio_event_app_user_attach(struct knote *); | |
492 | static void gpio_event_app_user_detach(struct knote *); | 492 | static void gpio_event_app_user_detach(struct knote *); | |
493 | static int gpio_event_app_user_event(struct knote *, long); | 493 | static int gpio_event_app_user_event(struct knote *, long); | |
494 | 494 | |||
495 | static struct klist knotes; | 495 | static struct klist knotes; | |
496 | static int app_filter_id; | 496 | static int app_filter_id; | |
497 | static struct filterops app_fops = { | 497 | static struct filterops app_fops = { | |
498 | 0, | 498 | .f_isfd = 0, | |
499 | gpio_event_app_user_attach, | 499 | .f_attach = gpio_event_app_user_attach, | |
500 | gpio_event_app_user_detach, | 500 | .f_detach = gpio_event_app_user_detach, | |
501 | gpio_event_app_user_event | 501 | .f_event = gpio_event_app_user_event, | |
502 | }; | 502 | }; | |
503 | static struct callout led_tick_callout; | 503 | static struct callout led_tick_callout; | |
504 | static int gpio_driver_blink_leds = 1; | 504 | static int gpio_driver_blink_leds = 1; | |
505 | 505 | |||
506 | static inline uint32_t | 506 | static inline uint32_t | |
507 | sy_read(ra_gpio_softc_t *sc, bus_size_t off) | 507 | sy_read(ra_gpio_softc_t *sc, bus_size_t off) | |
508 | { | 508 | { | |
509 | KASSERTMSG((off & 3) == 0, "%s: unaligned off=%#" PRIxBUSSIZE "\n", | 509 | KASSERTMSG((off & 3) == 0, "%s: unaligned off=%#" PRIxBUSSIZE "\n", | |
510 | __func__, off); | 510 | __func__, off); | |
511 | return bus_space_read_4(sc->sc_memt, sc->sc_sy_memh, off); | 511 | return bus_space_read_4(sc->sc_memt, sc->sc_sy_memh, off); | |
512 | } | 512 | } | |
513 | 513 | |||
514 | static inline void | 514 | static inline void | |
515 | sy_write(ra_gpio_softc_t *sc, bus_size_t off, uint32_t val) | 515 | sy_write(ra_gpio_softc_t *sc, bus_size_t off, uint32_t val) | |
516 | { | 516 | { | |
517 | KASSERTMSG((off & 3) == 0, "%s: unaligned off=%#" PRIxBUSSIZE "\n", | 517 | KASSERTMSG((off & 3) == 0, "%s: unaligned off=%#" PRIxBUSSIZE "\n", | |
518 | __func__, off); | 518 | __func__, off); | |
519 | bus_space_write_4(sc->sc_memt, sc->sc_sy_memh, off, val); | 519 | bus_space_write_4(sc->sc_memt, sc->sc_sy_memh, off, val); | |
520 | } | 520 | } | |
521 | 521 | |||
522 | static inline uint32_t | 522 | static inline uint32_t | |
523 | gp_read(ra_gpio_softc_t *sc, bus_size_t off) | 523 | gp_read(ra_gpio_softc_t *sc, bus_size_t off) | |
524 | { | 524 | { | |
525 | KASSERTMSG((off & 3) == 0, "%s: unaligned off=%#" PRIxBUSSIZE "\n", | 525 | KASSERTMSG((off & 3) == 0, "%s: unaligned off=%#" PRIxBUSSIZE "\n", | |
526 | __func__, off); | 526 | __func__, off); | |
527 | return bus_space_read_4(sc->sc_memt, sc->sc_gp_memh, off); | 527 | return bus_space_read_4(sc->sc_memt, sc->sc_gp_memh, off); | |
528 | } | 528 | } | |
529 | 529 | |||
530 | static inline void | 530 | static inline void | |
531 | gp_write(ra_gpio_softc_t *sc, bus_size_t off, uint32_t val) | 531 | gp_write(ra_gpio_softc_t *sc, bus_size_t off, uint32_t val) | |
532 | { | 532 | { | |
533 | KASSERTMSG((off & 3) == 0, "%s: unaligned off=%#" PRIxBUSSIZE "\n", | 533 | KASSERTMSG((off & 3) == 0, "%s: unaligned off=%#" PRIxBUSSIZE "\n", | |
534 | __func__, off); | 534 | __func__, off); | |
535 | bus_space_write_4(sc->sc_memt, sc->sc_gp_memh, off, val); | 535 | bus_space_write_4(sc->sc_memt, sc->sc_gp_memh, off, val); | |
536 | } | 536 | } | |
537 | 537 | |||
538 | /* | 538 | /* | |
539 | * Basic debug function, dump all PIO registers | 539 | * Basic debug function, dump all PIO registers | |
540 | */ | 540 | */ | |
541 | #if 0 | 541 | #if 0 | |
542 | static void | 542 | static void | |
543 | gpio_register_dump(ra_gpio_softc_t *sc) | 543 | gpio_register_dump(ra_gpio_softc_t *sc) | |
544 | { | 544 | { | |
545 | for (int i=0; i < 0xb0; i+=4) | 545 | for (int i=0; i < 0xb0; i+=4) | |
546 | RALINK_DEBUG(RALINK_DEBUG_INFO, "Reg: 0x%x, Value: 0x%x\n", | 546 | RALINK_DEBUG(RALINK_DEBUG_INFO, "Reg: 0x%x, Value: 0x%x\n", | |
547 | (RA_PIO_BASE + i), gp_read(sc, i)); | 547 | (RA_PIO_BASE + i), gp_read(sc, i)); | |
548 | } | 548 | } | |
549 | #endif | 549 | #endif | |
550 | 550 | |||
551 | static void | 551 | static void | |
552 | gpio_reset_registers(ra_gpio_softc_t *sc) | 552 | gpio_reset_registers(ra_gpio_softc_t *sc) | |
553 | { | 553 | { | |
554 | #if 0 | 554 | #if 0 | |
555 | for (int i=0; i < 0x88; i+=4) | 555 | for (int i=0; i < 0x88; i+=4) | |
556 | gp_write(sc, i, 0); | 556 | gp_write(sc, i, 0); | |
557 | #endif | 557 | #endif | |
558 | } | 558 | } | |
559 | 559 | |||
560 | 560 | |||
561 | static int | 561 | static int | |
562 | ra_gpio_match(device_t parent, cfdata_t cf, void *aux) | 562 | ra_gpio_match(device_t parent, cfdata_t cf, void *aux) | |
563 | { | 563 | { | |
564 | RALINK_DEBUG_FUNC_ENTRY(); | 564 | RALINK_DEBUG_FUNC_ENTRY(); | |
565 | 565 | |||
566 | return 1; | 566 | return 1; | |
567 | } | 567 | } | |
568 | 568 | |||
569 | static void | 569 | static void | |
570 | ra_gpio_attach(device_t parent, device_t self, void *aux) | 570 | ra_gpio_attach(device_t parent, device_t self, void *aux) | |
571 | { | 571 | { | |
572 | 572 | |||
573 | struct gpiobus_attach_args gba; | 573 | struct gpiobus_attach_args gba; | |
574 | ra_gpio_softc_t * const sc = device_private(self); | 574 | ra_gpio_softc_t * const sc = device_private(self); | |
575 | const struct mainbus_attach_args *ma = aux; | 575 | const struct mainbus_attach_args *ma = aux; | |
576 | int error; | 576 | int error; | |
577 | 577 | |||
578 | aprint_naive(": Ralink GPIO controller\n"); | 578 | aprint_naive(": Ralink GPIO controller\n"); | |
579 | aprint_normal(": Ralink GPIO controller\n"); | 579 | aprint_normal(": Ralink GPIO controller\n"); | |
580 | 580 | |||
581 | sc->sc_dev = self; | 581 | sc->sc_dev = self; | |
582 | sc->sc_memt = ma->ma_memt; | 582 | sc->sc_memt = ma->ma_memt; | |
583 | sc->sc_sy_size = 0x10000; | 583 | sc->sc_sy_size = 0x10000; | |
584 | sc->sc_gp_size = 0x1000; | 584 | sc->sc_gp_size = 0x1000; | |
585 | 585 | |||
586 | /* | 586 | /* | |
587 | * map the registers | 587 | * map the registers | |
588 | * | 588 | * | |
589 | * we map the Sysctl, and PIO registers separately so we can use the | 589 | * we map the Sysctl, and PIO registers separately so we can use the | |
590 | * defined register offsets sanely; just use the correct corresponding | 590 | * defined register offsets sanely; just use the correct corresponding | |
591 | * bus_space_handle | 591 | * bus_space_handle | |
592 | */ | 592 | */ | |
593 | 593 | |||
594 | if ((error = bus_space_map(sc->sc_memt, RA_SYSCTL_BASE, | 594 | if ((error = bus_space_map(sc->sc_memt, RA_SYSCTL_BASE, | |
595 | sc->sc_sy_size, 0, &sc->sc_sy_memh)) != 0) { | 595 | sc->sc_sy_size, 0, &sc->sc_sy_memh)) != 0) { | |
596 | aprint_error_dev(sc->sc_dev, | 596 | aprint_error_dev(sc->sc_dev, | |
597 | "unable to map Sysctl registers, error=%d\n", error); | 597 | "unable to map Sysctl registers, error=%d\n", error); | |
598 | goto fail_0; | 598 | goto fail_0; | |
599 | } | 599 | } | |
600 | 600 | |||
601 | if ((error = bus_space_map(sc->sc_memt, RA_PIO_BASE, | 601 | if ((error = bus_space_map(sc->sc_memt, RA_PIO_BASE, | |
602 | sc->sc_gp_size, 0, &sc->sc_gp_memh)) != 0) { | 602 | sc->sc_gp_size, 0, &sc->sc_gp_memh)) != 0) { | |
603 | aprint_error_dev(sc->sc_dev, | 603 | aprint_error_dev(sc->sc_dev, | |
604 | "unable to map PIO registers, error=%d\n", error); | 604 | "unable to map PIO registers, error=%d\n", error); | |
605 | goto fail_1; | 605 | goto fail_1; | |
606 | } | 606 | } | |
607 | 607 | |||
608 | /* Reset some registers */ | 608 | /* Reset some registers */ | |
609 | #if defined(MT7628) | 609 | #if defined(MT7628) | |
610 | gp_write(sc, RA_PIO_00_31_INT_RISE_EN, 0xffffffff); | 610 | gp_write(sc, RA_PIO_00_31_INT_RISE_EN, 0xffffffff); | |
611 | gp_write(sc, RA_PIO_00_31_INT_FALL_EN, 0xffffffff); | 611 | gp_write(sc, RA_PIO_00_31_INT_FALL_EN, 0xffffffff); | |
612 | gp_write(sc, RA_PIO_00_31_INT_HIGH_EN, 0); | 612 | gp_write(sc, RA_PIO_00_31_INT_HIGH_EN, 0); | |
613 | gp_write(sc, RA_PIO_00_31_INT_LOW_EN, 0); | 613 | gp_write(sc, RA_PIO_00_31_INT_LOW_EN, 0); | |
614 | 614 | |||
615 | gp_write(sc, RA_PIO_32_63_INT_RISE_EN, 0xffffffff); | 615 | gp_write(sc, RA_PIO_32_63_INT_RISE_EN, 0xffffffff); | |
616 | gp_write(sc, RA_PIO_32_63_INT_FALL_EN, 0xffffffff); | 616 | gp_write(sc, RA_PIO_32_63_INT_FALL_EN, 0xffffffff); | |
617 | gp_write(sc, RA_PIO_32_63_INT_HIGH_EN, 0); | 617 | gp_write(sc, RA_PIO_32_63_INT_HIGH_EN, 0); | |
618 | gp_write(sc, RA_PIO_32_63_INT_LOW_EN, 0); | 618 | gp_write(sc, RA_PIO_32_63_INT_LOW_EN, 0); | |
619 | 619 | |||
620 | gp_write(sc, RA_PIO_64_95_INT_RISE_EN, 0xffffffff); | 620 | gp_write(sc, RA_PIO_64_95_INT_RISE_EN, 0xffffffff); | |
621 | gp_write(sc, RA_PIO_64_95_INT_FALL_EN, 0xffffffff); | 621 | gp_write(sc, RA_PIO_64_95_INT_FALL_EN, 0xffffffff); | |
622 | gp_write(sc, RA_PIO_64_95_INT_HIGH_EN, 0); | 622 | gp_write(sc, RA_PIO_64_95_INT_HIGH_EN, 0); | |
623 | gp_write(sc, RA_PIO_64_95_INT_LOW_EN, 0); | 623 | gp_write(sc, RA_PIO_64_95_INT_LOW_EN, 0); | |
624 | 624 | |||
625 | gp_write(sc, RA_PIO_00_31_POLARITY, 0); | 625 | gp_write(sc, RA_PIO_00_31_POLARITY, 0); | |
626 | gp_write(sc, RA_PIO_32_63_POLARITY, 0); | 626 | gp_write(sc, RA_PIO_32_63_POLARITY, 0); | |
627 | gp_write(sc, RA_PIO_64_95_POLARITY, 0); | 627 | gp_write(sc, RA_PIO_64_95_POLARITY, 0); | |
628 | 628 | |||
629 | #else | 629 | #else | |
630 | gp_write(sc, RA_PIO_00_23_INT, 0xffffff); | 630 | gp_write(sc, RA_PIO_00_23_INT, 0xffffff); | |
631 | gp_write(sc, RA_PIO_00_23_EDGE_INT, 0xffffff); | 631 | gp_write(sc, RA_PIO_00_23_EDGE_INT, 0xffffff); | |
632 | gp_write(sc, RA_PIO_24_39_INT, 0xffff); | 632 | gp_write(sc, RA_PIO_24_39_INT, 0xffff); | |
633 | gp_write(sc, RA_PIO_24_39_EDGE_INT, 0xffff); | 633 | gp_write(sc, RA_PIO_24_39_EDGE_INT, 0xffff); | |
634 | gp_write(sc, RA_PIO_40_51_INT, 0xfff); | 634 | gp_write(sc, RA_PIO_40_51_INT, 0xfff); | |
635 | gp_write(sc, RA_PIO_40_51_EDGE_INT, 0xfff); | 635 | gp_write(sc, RA_PIO_40_51_EDGE_INT, 0xfff); | |
636 | gp_write(sc, RA_PIO_00_23_POLARITY, 0); | 636 | gp_write(sc, RA_PIO_00_23_POLARITY, 0); | |
637 | #if defined(SLICKROCK) | 637 | #if defined(SLICKROCK) | |
638 | gp_write(sc, RA_PIO_72_95_INT, 0xffffff); | 638 | gp_write(sc, RA_PIO_72_95_INT, 0xffffff); | |
639 | gp_write(sc, RA_PIO_72_95_EDGE_INT, 0xffffff); | 639 | gp_write(sc, RA_PIO_72_95_EDGE_INT, 0xffffff); | |
640 | #endif | 640 | #endif | |
641 | #endif | 641 | #endif | |
642 | 642 | |||
643 | /* Set up for interrupt handling, low priority interrupt queue */ | 643 | /* Set up for interrupt handling, low priority interrupt queue */ | |
644 | sc->sc_ih = ra_intr_establish(RA_IRQ_PIO, | 644 | sc->sc_ih = ra_intr_establish(RA_IRQ_PIO, | |
645 | ra_gpio_intr, sc, 0); | 645 | ra_gpio_intr, sc, 0); | |
646 | if (sc->sc_ih == NULL) { | 646 | if (sc->sc_ih == NULL) { | |
647 | RALINK_DEBUG(RALINK_DEBUG_ERROR, | 647 | RALINK_DEBUG(RALINK_DEBUG_ERROR, | |
648 | "%s: unable to establish interrupt\n", | 648 | "%s: unable to establish interrupt\n", | |
649 | device_xname(sc->sc_dev)); | 649 | device_xname(sc->sc_dev)); | |
650 | goto fail_2; | 650 | goto fail_2; | |
651 | } | 651 | } | |
652 | 652 | |||
653 | /* Soft int setup */ | 653 | /* Soft int setup */ | |
654 | sc->sc_si = softint_establish(SOFTINT_BIO, ra_gpio_softintr, sc); | 654 | sc->sc_si = softint_establish(SOFTINT_BIO, ra_gpio_softintr, sc); | |
655 | if (sc->sc_si == NULL) { | 655 | if (sc->sc_si == NULL) { | |
656 | ra_intr_disestablish(sc->sc_ih); | 656 | ra_intr_disestablish(sc->sc_ih); | |
657 | RALINK_DEBUG(RALINK_DEBUG_ERROR, | 657 | RALINK_DEBUG(RALINK_DEBUG_ERROR, | |
658 | "%s: unable to establish soft interrupt\n", | 658 | "%s: unable to establish soft interrupt\n", | |
659 | device_xname(sc->sc_dev)); | 659 | device_xname(sc->sc_dev)); | |
660 | goto fail_3; | 660 | goto fail_3; | |
661 | } | 661 | } | |
662 | 662 | |||
663 | SLIST_INIT(&knotes); | 663 | SLIST_INIT(&knotes); | |
664 | if (kfilter_register("CP_GPIO_EVENT", &app_fops, &app_filter_id) != 0) { | 664 | if (kfilter_register("CP_GPIO_EVENT", &app_fops, &app_filter_id) != 0) { | |
665 | RALINK_DEBUG(RALINK_DEBUG_ERROR, | 665 | RALINK_DEBUG(RALINK_DEBUG_ERROR, | |
666 | "%s: kfilter_register for CP_GPIO_EVENT failed\n", | 666 | "%s: kfilter_register for CP_GPIO_EVENT failed\n", | |
667 | __func__); | 667 | __func__); | |
668 | goto fail_4; | 668 | goto fail_4; | |
669 | } | 669 | } | |
670 | 670 | |||
671 | sc->sc_gc.gp_cookie = sc; | 671 | sc->sc_gc.gp_cookie = sc; | |
672 | sc->sc_gc.gp_pin_read = ra_gpio_pin_read; | 672 | sc->sc_gc.gp_pin_read = ra_gpio_pin_read; | |
673 | sc->sc_gc.gp_pin_write = ra_gpio_pin_write; | 673 | sc->sc_gc.gp_pin_write = ra_gpio_pin_write; | |
674 | sc->sc_gc.gp_pin_ctl = ra_gpio_pin_ctl; | 674 | sc->sc_gc.gp_pin_ctl = ra_gpio_pin_ctl; | |
675 | 675 | |||
676 | #if 0 | 676 | #if 0 | |
677 | gpio_register_dump(sc); | 677 | gpio_register_dump(sc); | |
678 | #endif | 678 | #endif | |
679 | gpio_reset_registers(sc); | 679 | gpio_reset_registers(sc); | |
680 | 680 | |||
681 | /* Initialize the GPIO pins */ | 681 | /* Initialize the GPIO pins */ | |
682 | for (int pin = 0; pin < GPIO_PINS; pin++) | 682 | for (int pin = 0; pin < GPIO_PINS; pin++) | |
683 | ra_gpio_pin_init(sc, pin); | 683 | ra_gpio_pin_init(sc, pin); | |
684 | 684 | |||
685 | #if 0 | 685 | #if 0 | |
686 | /* debug check */ | 686 | /* debug check */ | |
687 | KASSERT((sy_read(sc, RA_SYSCTL_GPIOMODE) == 0x31c) != 0); | 687 | KASSERT((sy_read(sc, RA_SYSCTL_GPIOMODE) == 0x31c) != 0); | |
688 | RALINK_DEBUG(RALINK_DEBUG_INFO, "SYSCTL_GPIOMODE = 0x%x\n", | 688 | RALINK_DEBUG(RALINK_DEBUG_INFO, "SYSCTL_GPIOMODE = 0x%x\n", | |
689 | sy_read(sc, RA_SYSCTL_GPIOMODE)); | 689 | sy_read(sc, RA_SYSCTL_GPIOMODE)); | |
690 | #endif | 690 | #endif | |
691 | 691 | |||
692 | /* | 692 | /* | |
693 | * Some simple board setup actions: | 693 | * Some simple board setup actions: | |
694 | * Check if we're attached to the dock. If so, enable dock power. | 694 | * Check if we're attached to the dock. If so, enable dock power. | |
695 | * BIG NOTE: Dock power is dependent on USB5V_EN! | 695 | * BIG NOTE: Dock power is dependent on USB5V_EN! | |
696 | */ | 696 | */ | |
697 | #if defined(PEBBLES500) || defined (PEBBLES35) | 697 | #if defined(PEBBLES500) || defined (PEBBLES35) | |
698 | RALINK_DEBUG(RALINK_DEBUG_INFO, "Enabling USB power\n"); | 698 | RALINK_DEBUG(RALINK_DEBUG_INFO, "Enabling USB power\n"); | |
699 | ra_gpio_pin_write(sc, VBUS_EN, 1); | 699 | ra_gpio_pin_write(sc, VBUS_EN, 1); | |
700 | ra_gpio_pin_write(sc, POWER_EN_USB, 1); | 700 | ra_gpio_pin_write(sc, POWER_EN_USB, 1); | |
701 | #if defined(PEBBLES500) | 701 | #if defined(PEBBLES500) | |
702 | /* | 702 | /* | |
703 | * Is an express card attached? Enable power if it is | 703 | * Is an express card attached? Enable power if it is | |
704 | * or it isn't | 704 | * or it isn't | |
705 | */ | 705 | */ | |
706 | #if 0 | 706 | #if 0 | |
707 | if (ra_gpio_pin_read(sc, EXCARD_ATTACH) == 0) { | 707 | if (ra_gpio_pin_read(sc, EXCARD_ATTACH) == 0) { | |
708 | #endif | 708 | #endif | |
709 | ra_gpio_pin_write(sc, POWER_EN_EXCARD1_3_3v, 1); | 709 | ra_gpio_pin_write(sc, POWER_EN_EXCARD1_3_3v, 1); | |
710 | ra_gpio_pin_write(sc, POWER_EN_EXCARD1_1_5v, 1); | 710 | ra_gpio_pin_write(sc, POWER_EN_EXCARD1_1_5v, 1); | |
711 | #if 0 | 711 | #if 0 | |
712 | } | 712 | } | |
713 | #endif /* 0 */ | 713 | #endif /* 0 */ | |
714 | #endif /* PEBBLES500 */ | 714 | #endif /* PEBBLES500 */ | |
715 | #endif /* PEBBLES500 || PEBBLES35 */ | 715 | #endif /* PEBBLES500 || PEBBLES35 */ | |
716 | 716 | |||
717 | #if defined(TABLEROCK) || defined(SPOT2) || defined(PUCK) || defined(MOAB) | 717 | #if defined(TABLEROCK) || defined(SPOT2) || defined(PUCK) || defined(MOAB) | |
718 | /* CHARGER_OFF pin matches the IN_5V */ | 718 | /* CHARGER_OFF pin matches the IN_5V */ | |
719 | if (ra_gpio_pin_read(sc, IN_5V) == 0) { | 719 | if (ra_gpio_pin_read(sc, IN_5V) == 0) { | |
720 | ra_gpio_pin_write(sc, CHARGER_OFF, 0); | 720 | ra_gpio_pin_write(sc, CHARGER_OFF, 0); | |
721 | } else { | 721 | } else { | |
722 | ra_gpio_pin_write(sc, CHARGER_OFF, 1); | 722 | ra_gpio_pin_write(sc, CHARGER_OFF, 1); | |
723 | } | 723 | } | |
724 | #endif | 724 | #endif | |
725 | 725 | |||
726 | #if defined(SLICKROCK) | 726 | #if defined(SLICKROCK) | |
727 | /* Enable all modem slots */ | 727 | /* Enable all modem slots */ | |
728 | ra_gpio_pin_write(sc, POWER_EN_USB1, 1); | 728 | ra_gpio_pin_write(sc, POWER_EN_USB1, 1); | |
729 | ra_gpio_pin_write(sc, POWER_EN_USB2, 1); | 729 | ra_gpio_pin_write(sc, POWER_EN_USB2, 1); | |
730 | ra_gpio_pin_write(sc, POWER_EN_USB3, 1); | 730 | ra_gpio_pin_write(sc, POWER_EN_USB3, 1); | |
731 | ra_gpio_pin_write(sc, POWER_EN_EX1, 1); | 731 | ra_gpio_pin_write(sc, POWER_EN_EX1, 1); | |
732 | ra_gpio_pin_write(sc, EX1_CPUSB_RST, 0); | 732 | ra_gpio_pin_write(sc, EX1_CPUSB_RST, 0); | |
733 | ra_gpio_pin_write(sc, POWER_EN_EX2, 1); | 733 | ra_gpio_pin_write(sc, POWER_EN_EX2, 1); | |
734 | ra_gpio_pin_write(sc, EX2_CPUSB_RST, 0); | 734 | ra_gpio_pin_write(sc, EX2_CPUSB_RST, 0); | |
735 | 735 | |||
736 | /* Wake up with an overcurrent on EX1. Try to shut it down. */ | 736 | /* Wake up with an overcurrent on EX1. Try to shut it down. */ | |
737 | gp_write(sc, RA_PIO_72_95_INT, 0xffffff); | 737 | gp_write(sc, RA_PIO_72_95_INT, 0xffffff); | |
738 | gp_write(sc, RA_PIO_72_95_EDGE_INT, 0xffffff); | 738 | gp_write(sc, RA_PIO_72_95_EDGE_INT, 0xffffff); | |
739 | #endif | 739 | #endif | |
740 | 740 | |||
741 | #ifdef BOOT_COUNT | 741 | #ifdef BOOT_COUNT | |
742 | sc->sc_pins[BOOT_COUNT].pin_flags = GPIO_PIN_OUTPUT; | 742 | sc->sc_pins[BOOT_COUNT].pin_flags = GPIO_PIN_OUTPUT; | |
743 | sc->sc_pins[BOOT_COUNT].pin_mapped = 0; | 743 | sc->sc_pins[BOOT_COUNT].pin_mapped = 0; | |
744 | #endif | 744 | #endif | |
745 | #ifdef UPGRADE | 745 | #ifdef UPGRADE | |
746 | sc->sc_pins[UPGRADE].pin_flags = GPIO_PIN_OUTPUT; | 746 | sc->sc_pins[UPGRADE].pin_flags = GPIO_PIN_OUTPUT; | |
747 | sc->sc_pins[UPGRADE].pin_mapped = 0; | 747 | sc->sc_pins[UPGRADE].pin_mapped = 0; | |
748 | #endif | 748 | #endif | |
749 | gba.gba_gc = &sc->sc_gc; | 749 | gba.gba_gc = &sc->sc_gc; | |
750 | gba.gba_pins = sc->sc_pins; | 750 | gba.gba_pins = sc->sc_pins; | |
751 | 751 | |||
752 | /* Note, > 52nd pin isn't a gpio, it is a special command */ | 752 | /* Note, > 52nd pin isn't a gpio, it is a special command */ | |
753 | gba.gba_npins = (GPIO_PINS + SPECIAL_COMMANDS); | 753 | gba.gba_npins = (GPIO_PINS + SPECIAL_COMMANDS); | |
754 | 754 | |||
755 | config_found_ia(sc->sc_dev, "gpiobus", &gba, gpiobus_print); | 755 | config_found_ia(sc->sc_dev, "gpiobus", &gba, gpiobus_print); | |
756 | 756 | |||
757 | #if 0 | 757 | #if 0 | |
758 | gpio_register_dump(sc); | 758 | gpio_register_dump(sc); | |
759 | #endif | 759 | #endif | |
760 | 760 | |||
761 | /* init our gpio debounce */ | 761 | /* init our gpio debounce */ | |
762 | callout_init(&sc->sc_tick_callout, 0); | 762 | callout_init(&sc->sc_tick_callout, 0); | |
763 | callout_setfunc(&sc->sc_tick_callout, ra_gpio_debounce_process, sc); | 763 | callout_setfunc(&sc->sc_tick_callout, ra_gpio_debounce_process, sc); | |
764 | 764 | |||
765 | /* LED blinking during boot */ | 765 | /* LED blinking during boot */ | |
766 | callout_init(&led_tick_callout, 0); | 766 | callout_init(&led_tick_callout, 0); | |
767 | 767 | |||
768 | ra_gpio_toggle_LED(sc); | 768 | ra_gpio_toggle_LED(sc); | |
769 | return; | 769 | return; | |
770 | 770 | |||
771 | fail_4: | 771 | fail_4: | |
772 | softint_disestablish(sc->sc_si); | 772 | softint_disestablish(sc->sc_si); | |
773 | fail_3: | 773 | fail_3: | |
774 | ra_intr_disestablish(sc->sc_ih); | 774 | ra_intr_disestablish(sc->sc_ih); | |
775 | fail_2: | 775 | fail_2: | |
776 | bus_space_unmap(sc->sc_memt, sc->sc_gp_memh, sc->sc_sy_size); | 776 | bus_space_unmap(sc->sc_memt, sc->sc_gp_memh, sc->sc_sy_size); | |
777 | fail_1: | 777 | fail_1: | |
778 | bus_space_unmap(sc->sc_memt, sc->sc_sy_memh, sc->sc_sy_size); | 778 | bus_space_unmap(sc->sc_memt, sc->sc_sy_memh, sc->sc_sy_size); | |
779 | fail_0: | 779 | fail_0: | |
780 | return; | 780 | return; | |
781 | } | 781 | } | |
782 | 782 | |||
783 | /* | 783 | /* | |
784 | * ra_gpio_pin_init - initialize the given gpio pin | 784 | * ra_gpio_pin_init - initialize the given gpio pin | |
785 | */ | 785 | */ | |
786 | static void | 786 | static void | |
787 | ra_gpio_pin_init(ra_gpio_softc_t *sc, int pin) | 787 | ra_gpio_pin_init(ra_gpio_softc_t *sc, int pin) | |
788 | { | 788 | { | |
789 | uint32_t r; | 789 | uint32_t r; | |
790 | 790 | |||
791 | sc->sc_pins[pin].pin_caps = 0; | 791 | sc->sc_pins[pin].pin_caps = 0; | |
792 | sc->sc_pins[pin].pin_flags = 0; | 792 | sc->sc_pins[pin].pin_flags = 0; | |
793 | sc->sc_pins[pin].pin_state = 0; | 793 | sc->sc_pins[pin].pin_state = 0; | |
794 | sc->sc_pins[pin].pin_mapped = 0; | 794 | sc->sc_pins[pin].pin_mapped = 0; | |
795 | 795 | |||
796 | /* ensure pin number is in range */ | 796 | /* ensure pin number is in range */ | |
797 | KASSERT(pin < GPIO_PINS); | 797 | KASSERT(pin < GPIO_PINS); | |
798 | if (pin >= GPIO_PINS) | 798 | if (pin >= GPIO_PINS) | |
799 | return; | 799 | return; | |
800 | 800 | |||
801 | /* if pin number is in a gap in the range, just return */ | 801 | /* if pin number is in a gap in the range, just return */ | |
802 | const int index = pin_tab_index[pin]; | 802 | const int index = pin_tab_index[pin]; | |
803 | if (index == -1) | 803 | if (index == -1) | |
804 | return; | 804 | return; | |
805 | 805 | |||
806 | /* if pin is not enabled, just return */ | 806 | /* if pin is not enabled, just return */ | |
807 | const pin_tab_t * const ptp = &pin_tab[index]; | 807 | const pin_tab_t * const ptp = &pin_tab[index]; | |
808 | const u_int mask_bit = 1 << (pin - ptp->pin_mask_base); | 808 | const u_int mask_bit = 1 << (pin - ptp->pin_mask_base); | |
809 | if ((ptp->pin_enabled & mask_bit) == 0) | 809 | if ((ptp->pin_enabled & mask_bit) == 0) | |
810 | return; | 810 | return; | |
811 | 811 | |||
812 | sc->sc_pins[pin].pin_caps = GPIO_PIN_INPUT | GPIO_PIN_OUTPUT | | 812 | sc->sc_pins[pin].pin_caps = GPIO_PIN_INPUT | GPIO_PIN_OUTPUT | | |
813 | GPIO_PIN_INVIN | GPIO_PIN_INVOUT; | 813 | GPIO_PIN_INVIN | GPIO_PIN_INVOUT; | |
814 | sc->sc_pins[pin].pin_state = GPIO_PIN_INPUT; | 814 | sc->sc_pins[pin].pin_state = GPIO_PIN_INPUT; | |
815 | 815 | |||
816 | #if defined(MT7628) | 816 | #if defined(MT7628) | |
817 | /* | 817 | /* | |
818 | * Set the SYSCTL_GPIO{1,2}MODE register | 818 | * Set the SYSCTL_GPIO{1,2}MODE register | |
819 | * for the PIO block of any mapped GPIO | 819 | * for the PIO block of any mapped GPIO | |
820 | */ | 820 | */ | |
821 | for (int i = 0; i < __arraycount(gpio_mux_map); i++) { | 821 | for (int i = 0; i < __arraycount(gpio_mux_map); i++) { | |
822 | if ((pin >= gpio_mux_map[i].pin_start) && | 822 | if ((pin >= gpio_mux_map[i].pin_start) && | |
823 | (pin >= gpio_mux_map[i].pin_end)) { | 823 | (pin >= gpio_mux_map[i].pin_end)) { | |
824 | r = sy_read(sc, gpio_mux_map[i].sysreg); | 824 | r = sy_read(sc, gpio_mux_map[i].sysreg); | |
825 | r &= ~gpio_mux_map[i].regmask; | 825 | r &= ~gpio_mux_map[i].regmask; | |
826 | r |= __SHIFTIN(gpio_mux_map[i].mode, | 826 | r |= __SHIFTIN(gpio_mux_map[i].mode, | |
827 | gpio_mux_map[i].regmask); | 827 | gpio_mux_map[i].regmask); | |
828 | sy_write(sc, gpio_mux_map[i].sysreg, r); | 828 | sy_write(sc, gpio_mux_map[i].sysreg, r); | |
829 | break; | 829 | break; | |
830 | } | 830 | } | |
831 | } | 831 | } | |
832 | #else | 832 | #else | |
833 | #if defined(SLICKROCK) | 833 | #if defined(SLICKROCK) | |
834 | r = sy_read(sc, RA_SYSCTL_GPIOMODE); | 834 | r = sy_read(sc, RA_SYSCTL_GPIOMODE); | |
835 | r |= SR_GPIO_MODE; | 835 | r |= SR_GPIO_MODE; | |
836 | sy_write(sc, RA_SYSCTL_GPIOMODE, r); | 836 | sy_write(sc, RA_SYSCTL_GPIOMODE, r); | |
837 | #else | 837 | #else | |
838 | /* | 838 | /* | |
839 | * Set the SYSCTL_GPIOMODE register to 1 for | 839 | * Set the SYSCTL_GPIOMODE register to 1 for | |
840 | * the PIO block of any mapped GPIO | 840 | * the PIO block of any mapped GPIO | |
841 | * (most have reset defaults of 1 already). | 841 | * (most have reset defaults of 1 already). | |
842 | * GPIO0 doesn't have an associated MODE register. | 842 | * GPIO0 doesn't have an associated MODE register. | |
843 | */ | 843 | */ | |
844 | if (pin != 0) { | 844 | if (pin != 0) { | |
845 | u_int gpio_mode; | 845 | u_int gpio_mode; | |
846 | 846 | |||
847 | for (gpio_mode = 0; gpio_mode < __arraycount(pin_share); | 847 | for (gpio_mode = 0; gpio_mode < __arraycount(pin_share); | |
848 | gpio_mode++) { | 848 | gpio_mode++) { | |
849 | if (pin <= pin_share[gpio_mode]) { | 849 | if (pin <= pin_share[gpio_mode]) { | |
850 | r = sy_read(sc, RA_SYSCTL_GPIOMODE); | 850 | r = sy_read(sc, RA_SYSCTL_GPIOMODE); | |
851 | if (10 == pin) { | 851 | if (10 == pin) { | |
852 | /* | 852 | /* | |
853 | * Special case: | 853 | * Special case: | |
854 | * GPIO 10 requires GPIOMODE_UARTF0-2 | 854 | * GPIO 10 requires GPIOMODE_UARTF0-2 | |
855 | */ | 855 | */ | |
856 | r |= GPIOMODE_UARTF_0_2; | 856 | r |= GPIOMODE_UARTF_0_2; | |
857 | } else { | 857 | } else { | |
858 | /* standard case */ | 858 | /* standard case */ | |
859 | r |= (1 << gpio_mode); | 859 | r |= (1 << gpio_mode); | |
860 | } | 860 | } | |
861 | sy_write(sc, RA_SYSCTL_GPIOMODE, r); | 861 | sy_write(sc, RA_SYSCTL_GPIOMODE, r); | |
862 | break; | 862 | break; | |
863 | } | 863 | } | |
864 | } | 864 | } | |
865 | } | 865 | } | |
866 | #endif /* SLICKROCK */ | 866 | #endif /* SLICKROCK */ | |
867 | #endif /* !MT7628 */ | 867 | #endif /* !MT7628 */ | |
868 | 868 | |||
869 | /* set direction */ | 869 | /* set direction */ | |
870 | RA_GPIO_PIN_INIT_DIR(sc, r, pin, ptp); | 870 | RA_GPIO_PIN_INIT_DIR(sc, r, pin, ptp); | |
871 | 871 | |||
872 | /* rising edge interrupt */ | 872 | /* rising edge interrupt */ | |
873 | RA_GPIO_PIN_INIT(sc, r, pin, ptp, pin_rise); | 873 | RA_GPIO_PIN_INIT(sc, r, pin, ptp, pin_rise); | |
874 | 874 | |||
875 | /* falling edge interrupt */ | 875 | /* falling edge interrupt */ | |
876 | RA_GPIO_PIN_INIT(sc, r, pin, ptp, pin_fall); | 876 | RA_GPIO_PIN_INIT(sc, r, pin, ptp, pin_fall); | |
877 | 877 | |||
878 | /* polarirty */ | 878 | /* polarirty */ | |
879 | RA_GPIO_PIN_INIT(sc, r, pin, ptp, pin_pol); | 879 | RA_GPIO_PIN_INIT(sc, r, pin, ptp, pin_pol); | |
880 | } | 880 | } | |
881 | 881 | |||
882 | /* | 882 | /* | |
883 | * Note: This has special hacks in it. If pseudo-pin BOOT_COUNT | 883 | * Note: This has special hacks in it. If pseudo-pin BOOT_COUNT | |
884 | * is requested, it is a signal check the memo register for a special key | 884 | * is requested, it is a signal check the memo register for a special key | |
885 | * that means run Wi-Fi in no security mode. | 885 | * that means run Wi-Fi in no security mode. | |
886 | */ | 886 | */ | |
887 | int | 887 | int | |
888 | ra_gpio_pin_read(void *arg, int pin) | 888 | ra_gpio_pin_read(void *arg, int pin) | |
889 | { | 889 | { | |
890 | RALINK_DEBUG_FUNC_ENTRY(); | 890 | RALINK_DEBUG_FUNC_ENTRY(); | |
891 | const ra_gpio_softc_t * const sc = arg; | 891 | const ra_gpio_softc_t * const sc = arg; | |
892 | int rv; | 892 | int rv; | |
893 | 893 | |||
894 | KASSERT(sc != NULL); | 894 | KASSERT(sc != NULL); | |
895 | 895 | |||
896 | if (pin < GPIO_PINS) { | 896 | if (pin < GPIO_PINS) { | |
897 | /* | 897 | /* | |
898 | * normal case: a regular GPIO pin | 898 | * normal case: a regular GPIO pin | |
899 | * if pin number is in a gap in the range, | 899 | * if pin number is in a gap in the range, | |
900 | * then warn and return 0 | 900 | * then warn and return 0 | |
901 | */ | 901 | */ | |
902 | const int index = pin_tab_index[pin]; | 902 | const int index = pin_tab_index[pin]; | |
903 | KASSERTMSG(index != -1, "%s: non-existant pin=%d\n", | 903 | KASSERTMSG(index != -1, "%s: non-existant pin=%d\n", | |
904 | __func__, pin); | 904 | __func__, pin); | |
905 | if (index == -1) { | 905 | if (index == -1) { | |
906 | rv = 0; | 906 | rv = 0; | |
907 | } else { | 907 | } else { | |
908 | const pin_tab_t * const ptp = &pin_tab[index]; | 908 | const pin_tab_t * const ptp = &pin_tab[index]; | |
909 | const uint32_t reg_bit = 1 << (pin - ptp->pin_reg_base); | 909 | const uint32_t reg_bit = 1 << (pin - ptp->pin_reg_base); | |
910 | const bus_size_t off = ptp->pin_input; | 910 | const bus_size_t off = ptp->pin_input; | |
911 | uint32_t r; | 911 | uint32_t r; | |
912 | 912 | |||
913 | r = bus_space_read_4(sc->sc_memt, sc->sc_gp_memh, off); | 913 | r = bus_space_read_4(sc->sc_memt, sc->sc_gp_memh, off); | |
914 | rv = ((r & (1 << reg_bit)) != 0); | 914 | rv = ((r & (1 << reg_bit)) != 0); | |
915 | } | 915 | } | |
916 | } else { | 916 | } else { | |
917 | /* | 917 | /* | |
918 | * Special hack: a pseudo-pin used for signaling | 918 | * Special hack: a pseudo-pin used for signaling | |
919 | */ | 919 | */ | |
920 | rv = 0; | 920 | rv = 0; | |
921 | switch (pin) { | 921 | switch (pin) { | |
922 | #ifdef BOOT_COUNT | 922 | #ifdef BOOT_COUNT | |
923 | case BOOT_COUNT: | 923 | case BOOT_COUNT: | |
924 | if (1 == ra_check_memo_reg(NO_SECURITY)) | 924 | if (1 == ra_check_memo_reg(NO_SECURITY)) | |
925 | rv = 1; | 925 | rv = 1; | |
926 | break; | 926 | break; | |
927 | #endif | 927 | #endif | |
928 | default: | 928 | default: | |
929 | #ifdef DIAGNOSTIC | 929 | #ifdef DIAGNOSTIC | |
930 | aprint_normal_dev(sc->sc_dev, "%s: bad pin=%d\n", | 930 | aprint_normal_dev(sc->sc_dev, "%s: bad pin=%d\n", | |
931 | __func__, pin); | 931 | __func__, pin); | |
932 | #endif | 932 | #endif | |
933 | break; | 933 | break; | |
934 | } | 934 | } | |
935 | } | 935 | } | |
936 | 936 | |||
937 | RALINK_DEBUG_0(RALINK_DEBUG_INFO, "pin %d, value %x\n", pin, rv); | 937 | RALINK_DEBUG_0(RALINK_DEBUG_INFO, "pin %d, value %x\n", pin, rv); | |
938 | return rv; | 938 | return rv; | |
939 | } | 939 | } | |
940 | 940 | |||
941 | /* | 941 | /* | |
942 | * There are three ways to change the value of a pin. | 942 | * There are three ways to change the value of a pin. | |
943 | * You can write to the DATA register, which will set | 943 | * You can write to the DATA register, which will set | |
944 | * or reset a pin. But you need to store it locally and | 944 | * or reset a pin. But you need to store it locally and | |
945 | * read/mask/set it, which is potentially racy without locks. | 945 | * read/mask/set it, which is potentially racy without locks. | |
946 | * There are also SET and RESET registers, which allow you to write | 946 | * There are also SET and RESET registers, which allow you to write | |
947 | * a value to a single pin and not affect any other pins | 947 | * a value to a single pin and not affect any other pins | |
948 | * by accident. | 948 | * by accident. | |
949 | * | 949 | * | |
950 | * NOTE: This has special hacks in it. If pin 52 (which does not exist) | 950 | * NOTE: This has special hacks in it. If pin 52 (which does not exist) | |
951 | * is written, it is a signal to clear the boot count register. If pin | 951 | * is written, it is a signal to clear the boot count register. If pin | |
952 | * 53 is written, it is a upgrade signal to the bootloader. | 952 | * 53 is written, it is a upgrade signal to the bootloader. | |
953 | * | 953 | * | |
954 | */ | 954 | */ | |
955 | #define MAGIC 0x27051956 | 955 | #define MAGIC 0x27051956 | |
956 | #define UPGRADE_MAGIC 0x27051957 | 956 | #define UPGRADE_MAGIC 0x27051957 | |
957 | void | 957 | void | |
958 | ra_gpio_pin_write(void *arg, int pin, int value) | 958 | ra_gpio_pin_write(void *arg, int pin, int value) | |
959 | { | 959 | { | |
960 | RALINK_DEBUG_FUNC_ENTRY(); | 960 | RALINK_DEBUG_FUNC_ENTRY(); | |
961 | ra_gpio_softc_t * const sc = arg; | 961 | ra_gpio_softc_t * const sc = arg; | |
962 | #if defined(BOOT_COUNT) || defined(UPGRADE) | 962 | #if defined(BOOT_COUNT) || defined(UPGRADE) | |
963 | uint32_t r; | 963 | uint32_t r; | |
964 | #endif | 964 | #endif | |
965 | 965 | |||
966 | KASSERT(sc != NULL); | 966 | KASSERT(sc != NULL); | |
967 | RALINK_DEBUG(RALINK_DEBUG_INFO, "pin %d, val %d\n", pin, value); | 967 | RALINK_DEBUG(RALINK_DEBUG_INFO, "pin %d, val %d\n", pin, value); | |
968 | 968 | |||
969 | if (pin >= GPIO_PINS) { | 969 | if (pin >= GPIO_PINS) { | |
970 | /* | 970 | /* | |
971 | * Special hack: a pseudo-pin used for signaling | 971 | * Special hack: a pseudo-pin used for signaling | |
972 | */ | 972 | */ | |
973 | switch(pin) { | 973 | switch(pin) { | |
974 | #ifdef BOOT_COUNT | 974 | #ifdef BOOT_COUNT | |
975 | case BOOT_COUNT: | 975 | case BOOT_COUNT: | |
976 | /* Reset boot count */ | 976 | /* Reset boot count */ | |
977 | r = sy_read(sc, RA_SYSCTL_MEMO0); | 977 | r = sy_read(sc, RA_SYSCTL_MEMO0); | |
978 | if (r == MAGIC) | 978 | if (r == MAGIC) | |
979 | sy_write(sc, RA_SYSCTL_MEMO1, 0); | 979 | sy_write(sc, RA_SYSCTL_MEMO1, 0); | |
980 | break; | 980 | break; | |
981 | #endif | 981 | #endif | |
982 | #ifdef UPGRADE | 982 | #ifdef UPGRADE | |
983 | case UPGRADE: | 983 | case UPGRADE: | |
984 | /* Set upgrade flag */ | 984 | /* Set upgrade flag */ | |
985 | sy_write(sc, RA_SYSCTL_MEMO0, UPGRADE_MAGIC); | 985 | sy_write(sc, RA_SYSCTL_MEMO0, UPGRADE_MAGIC); | |
986 | sy_write(sc, RA_SYSCTL_MEMO1, UPGRADE_MAGIC); | 986 | sy_write(sc, RA_SYSCTL_MEMO1, UPGRADE_MAGIC); | |
987 | break; | 987 | break; | |
988 | #endif | 988 | #endif | |
989 | default: | 989 | default: | |
990 | #ifdef DIAGNOSTIC | 990 | #ifdef DIAGNOSTIC | |
991 | aprint_normal_dev(sc->sc_dev, "%s: bad pin=%d\n", | 991 | aprint_normal_dev(sc->sc_dev, "%s: bad pin=%d\n", | |
992 | __func__, pin); | 992 | __func__, pin); | |
993 | #endif | 993 | #endif | |
994 | } | 994 | } | |
995 | return; | 995 | return; | |
996 | } | 996 | } | |
997 | 997 | |||
998 | /* | 998 | /* | |
999 | * normal case: a regular GPIO pin | 999 | * normal case: a regular GPIO pin | |
1000 | * if pin number is in a gap in the range, | 1000 | * if pin number is in a gap in the range, | |
1001 | * then warn and return | 1001 | * then warn and return | |
1002 | */ | 1002 | */ | |
1003 | const int index = pin_tab_index[pin]; | 1003 | const int index = pin_tab_index[pin]; | |
1004 | KASSERTMSG(index != -1, "%s: non-existant pin=%d\n", __func__, pin); | 1004 | KASSERTMSG(index != -1, "%s: non-existant pin=%d\n", __func__, pin); | |
1005 | if (index == -1) | 1005 | if (index == -1) | |
1006 | return; | 1006 | return; | |
1007 | 1007 | |||
1008 | const pin_tab_t * const ptp = &pin_tab[index]; | 1008 | const pin_tab_t * const ptp = &pin_tab[index]; | |
1009 | const u_int mask_bit = 1 << (pin - ptp->pin_mask_base); | 1009 | const u_int mask_bit = 1 << (pin - ptp->pin_mask_base); | |
1010 | const uint32_t reg_bit = 1 << (pin - ptp->pin_reg_base); | 1010 | const uint32_t reg_bit = 1 << (pin - ptp->pin_reg_base); | |
1011 | const bus_size_t off = (value == 0) ? | 1011 | const bus_size_t off = (value == 0) ? | |
1012 | ptp->pin_output_clr : ptp->pin_output_set; | 1012 | ptp->pin_output_clr : ptp->pin_output_set; | |
1013 | 1013 | |||
1014 | if ((ptp->pin_dir.mask & mask_bit) == 0) { | 1014 | if ((ptp->pin_dir.mask & mask_bit) == 0) { | |
1015 | #ifdef DIAGNOSTIC | 1015 | #ifdef DIAGNOSTIC | |
1016 | aprint_normal_dev(sc->sc_dev, | 1016 | aprint_normal_dev(sc->sc_dev, | |
1017 | "%s: Writing non-output pin: %d\n", __func__, pin); | 1017 | "%s: Writing non-output pin: %d\n", __func__, pin); | |
1018 | #endif | 1018 | #endif | |
1019 | return; | 1019 | return; | |
1020 | } | 1020 | } | |
1021 | 1021 | |||
1022 | bus_space_write_4(sc->sc_memt, sc->sc_gp_memh, off, reg_bit); | 1022 | bus_space_write_4(sc->sc_memt, sc->sc_gp_memh, off, reg_bit); | |
1023 | } | 1023 | } | |
1024 | 1024 | |||
1025 | static void | 1025 | static void | |
1026 | ra_gpio_pin_ctl(void *arg, int pin, int flags) | 1026 | ra_gpio_pin_ctl(void *arg, int pin, int flags) | |
1027 | { | 1027 | { | |
1028 | RALINK_DEBUG_FUNC_ENTRY(); | 1028 | RALINK_DEBUG_FUNC_ENTRY(); | |
1029 | 1029 | |||
1030 | /* | 1030 | /* | |
1031 | * For now, this lets us know that user-space is using the GPIOs | 1031 | * For now, this lets us know that user-space is using the GPIOs | |
1032 | * and the kernel shouldn't blink LEDs any more | 1032 | * and the kernel shouldn't blink LEDs any more | |
1033 | */ | 1033 | */ | |
1034 | gpio_driver_blink_leds = 0; | 1034 | gpio_driver_blink_leds = 0; | |
1035 | } | 1035 | } | |
1036 | 1036 | |||
1037 | /* | 1037 | /* | |
1038 | * Check the three interrupt registers and ack them | 1038 | * Check the three interrupt registers and ack them | |
1039 | * immediately. If a button is pushed, use the | 1039 | * immediately. If a button is pushed, use the | |
1040 | * handle_key_press call to debounce it. Otherwise, | 1040 | * handle_key_press call to debounce it. Otherwise, | |
1041 | * call the softint handler to send any necessary | 1041 | * call the softint handler to send any necessary | |
1042 | * events. | 1042 | * events. | |
1043 | */ | 1043 | */ | |
1044 | static int | 1044 | static int | |
1045 | ra_gpio_intr(void *arg) | 1045 | ra_gpio_intr(void *arg) | |
1046 | { | 1046 | { | |
1047 | RALINK_DEBUG_FUNC_ENTRY(); | 1047 | RALINK_DEBUG_FUNC_ENTRY(); | |
1048 | ra_gpio_softc_t * const sc = arg; | 1048 | ra_gpio_softc_t * const sc = arg; | |
1049 | 1049 | |||
1050 | #if 0 | 1050 | #if 0 | |
1051 | /* Read the 3 interrupt registers */ | 1051 | /* Read the 3 interrupt registers */ | |
1052 | #if defined(MT7628) | 1052 | #if defined(MT7628) | |
1053 | if (sc->sc_intr_status00_31 || sc->sc_intr_status32_63 || | 1053 | if (sc->sc_intr_status00_31 || sc->sc_intr_status32_63 || | |
1054 | sc->sc_intr_status64_95) { | 1054 | sc->sc_intr_status64_95) { | |
1055 | printf("\n0-31 %x, 32-63 %x, 64_95 %x\n", | 1055 | printf("\n0-31 %x, 32-63 %x, 64_95 %x\n", | |
1056 | sc->sc_intr_status00_31, | 1056 | sc->sc_intr_status00_31, | |
1057 | sc->sc_intr_status32_63, | 1057 | sc->sc_intr_status32_63, | |
1058 | sc->sc_intr_status64_95); | 1058 | sc->sc_intr_status64_95); | |
1059 | } | 1059 | } | |
1060 | #else | 1060 | #else | |
1061 | if (sc->sc_intr_status00_23 || sc->sc_intr_status24_39 || | 1061 | if (sc->sc_intr_status00_23 || sc->sc_intr_status24_39 || | |
1062 | sc->sc_intr_status40_51) { | 1062 | sc->sc_intr_status40_51) { | |
1063 | printf("\n0-23 %x, 24-39 %x, 40_51 %x\n", | 1063 | printf("\n0-23 %x, 24-39 %x, 40_51 %x\n", | |
1064 | sc->sc_intr_status00_23, | 1064 | sc->sc_intr_status00_23, | |
1065 | sc->sc_intr_status24_39, | 1065 | sc->sc_intr_status24_39, | |
1066 | sc->sc_intr_status40_51); | 1066 | sc->sc_intr_status40_51); | |
1067 | } | 1067 | } | |
1068 | #endif | 1068 | #endif | |
1069 | #endif | 1069 | #endif | |
1070 | 1070 | |||
1071 | #if defined(MT7628) | 1071 | #if defined(MT7628) | |
1072 | sc->sc_intr_status00_31 |= gp_read(sc, RA_PIO_00_31_INT_STAT); | 1072 | sc->sc_intr_status00_31 |= gp_read(sc, RA_PIO_00_31_INT_STAT); | |
1073 | sc->sc_intr_status32_63 |= gp_read(sc, RA_PIO_32_63_INT_STAT); | 1073 | sc->sc_intr_status32_63 |= gp_read(sc, RA_PIO_32_63_INT_STAT); | |
1074 | sc->sc_intr_status64_95 |= gp_read(sc, RA_PIO_64_95_INT_STAT); | 1074 | sc->sc_intr_status64_95 |= gp_read(sc, RA_PIO_64_95_INT_STAT); | |
1075 | #else | 1075 | #else | |
1076 | sc->sc_intr_status00_23 |= gp_read(sc, RA_PIO_00_23_INT); | 1076 | sc->sc_intr_status00_23 |= gp_read(sc, RA_PIO_00_23_INT); | |
1077 | sc->sc_intr_status24_39 |= gp_read(sc, RA_PIO_24_39_INT); | 1077 | sc->sc_intr_status24_39 |= gp_read(sc, RA_PIO_24_39_INT); | |
1078 | sc->sc_intr_status40_51 |= gp_read(sc, RA_PIO_40_51_INT); | 1078 | sc->sc_intr_status40_51 |= gp_read(sc, RA_PIO_40_51_INT); | |
1079 | #if defined(SLICKROCK) | 1079 | #if defined(SLICKROCK) | |
1080 | sc->sc_intr_status72_95 |= gp_read(sc, RA_PIO_72_95_INT); | 1080 | sc->sc_intr_status72_95 |= gp_read(sc, RA_PIO_72_95_INT); | |
1081 | #endif | 1081 | #endif | |
1082 | #endif | 1082 | #endif | |
1083 | 1083 | |||
1084 | #if 0 | 1084 | #if 0 | |
1085 | /* Trivial error checking, some interrupt had to have fired */ | 1085 | /* Trivial error checking, some interrupt had to have fired */ | |
1086 | #if defined(MT7628) | 1086 | #if defined(MT7628) | |
1087 | KASSERT((sc->sc_intr_status00_31 | sc->sc_intr_status32_64 | | 1087 | KASSERT((sc->sc_intr_status00_31 | sc->sc_intr_status32_64 | | |
1088 | sc->sc_intr_status64_95) != 0); | 1088 | sc->sc_intr_status64_95) != 0); | |
1089 | #else | 1089 | #else | |
1090 | KASSERT((sc->sc_intr_status00_23 | sc->sc_intr_status24_39 | | 1090 | KASSERT((sc->sc_intr_status00_23 | sc->sc_intr_status24_39 | | |
1091 | sc->sc_intr_status40_51) != 0); | 1091 | sc->sc_intr_status40_51) != 0); | |
1092 | #endif | 1092 | #endif | |
1093 | #endif | 1093 | #endif | |
1094 | 1094 | |||
1095 | /* Debounce interrupt */ | 1095 | /* Debounce interrupt */ | |
1096 | ra_gpio_debounce_setup(sc); | 1096 | ra_gpio_debounce_setup(sc); | |
1097 | 1097 | |||
1098 | /* | 1098 | /* | |
1099 | * and ACK the interrupt. | 1099 | * and ACK the interrupt. | |
1100 | * OR the values in case the softint handler hasn't | 1100 | * OR the values in case the softint handler hasn't | |
1101 | * been scheduled and handled any previous int | 1101 | * been scheduled and handled any previous int | |
1102 | * I don't know if resetting the EDGE register is | 1102 | * I don't know if resetting the EDGE register is | |
1103 | * necessary, but the Ralink Linux driver does it. | 1103 | * necessary, but the Ralink Linux driver does it. | |
1104 | */ | 1104 | */ | |
1105 | #if defined(MT7628) | 1105 | #if defined(MT7628) | |
1106 | gp_write(sc, RA_PIO_00_31_INT_STAT, sc->sc_intr_status00_31); | 1106 | gp_write(sc, RA_PIO_00_31_INT_STAT, sc->sc_intr_status00_31); | |
1107 | gp_write(sc, RA_PIO_00_31_INT_STAT_EDGE, sc->sc_intr_status00_31); | 1107 | gp_write(sc, RA_PIO_00_31_INT_STAT_EDGE, sc->sc_intr_status00_31); | |
1108 | gp_write(sc, RA_PIO_32_63_INT_STAT, sc->sc_intr_status32_63); | 1108 | gp_write(sc, RA_PIO_32_63_INT_STAT, sc->sc_intr_status32_63); | |
1109 | gp_write(sc, RA_PIO_32_63_INT_STAT_EDGE, sc->sc_intr_status32_63); | 1109 | gp_write(sc, RA_PIO_32_63_INT_STAT_EDGE, sc->sc_intr_status32_63); | |
1110 | gp_write(sc, RA_PIO_64_95_INT_STAT, sc->sc_intr_status64_95); | 1110 | gp_write(sc, RA_PIO_64_95_INT_STAT, sc->sc_intr_status64_95); | |
1111 | gp_write(sc, RA_PIO_64_95_INT_STAT_EDGE, sc->sc_intr_status64_95); | 1111 | gp_write(sc, RA_PIO_64_95_INT_STAT_EDGE, sc->sc_intr_status64_95); | |
1112 | 1112 | |||
1113 | /* Reset until next time */ | 1113 | /* Reset until next time */ | |
1114 | sc->sc_intr_status00_31 = 0; | 1114 | sc->sc_intr_status00_31 = 0; | |
1115 | sc->sc_intr_status32_63 = 0; | 1115 | sc->sc_intr_status32_63 = 0; | |
1116 | sc->sc_intr_status64_95 = 0; | 1116 | sc->sc_intr_status64_95 = 0; | |
1117 | #else | 1117 | #else | |
1118 | gp_write(sc, RA_PIO_00_23_INT, sc->sc_intr_status00_23); | 1118 | gp_write(sc, RA_PIO_00_23_INT, sc->sc_intr_status00_23); | |
1119 | gp_write(sc, RA_PIO_00_23_EDGE_INT, sc->sc_intr_status00_23); | 1119 | gp_write(sc, RA_PIO_00_23_EDGE_INT, sc->sc_intr_status00_23); | |
1120 | gp_write(sc, RA_PIO_24_39_INT, sc->sc_intr_status24_39); | 1120 | gp_write(sc, RA_PIO_24_39_INT, sc->sc_intr_status24_39); | |
1121 | gp_write(sc, RA_PIO_24_39_EDGE_INT, sc->sc_intr_status24_39); | 1121 | gp_write(sc, RA_PIO_24_39_EDGE_INT, sc->sc_intr_status24_39); | |
1122 | gp_write(sc, RA_PIO_40_51_INT, sc->sc_intr_status40_51); | 1122 | gp_write(sc, RA_PIO_40_51_INT, sc->sc_intr_status40_51); | |
1123 | gp_write(sc, RA_PIO_40_51_EDGE_INT, sc->sc_intr_status40_51); | 1123 | gp_write(sc, RA_PIO_40_51_EDGE_INT, sc->sc_intr_status40_51); | |
1124 | #if defined(SLICKROCK) | 1124 | #if defined(SLICKROCK) | |
1125 | gp_write(sc, RA_PIO_72_95_INT, sc->sc_intr_status72_95); | 1125 | gp_write(sc, RA_PIO_72_95_INT, sc->sc_intr_status72_95); | |
1126 | gp_write(sc, RA_PIO_72_95_EDGE_INT, sc->sc_intr_status72_95); | 1126 | gp_write(sc, RA_PIO_72_95_EDGE_INT, sc->sc_intr_status72_95); | |
1127 | #endif | 1127 | #endif | |
1128 | 1128 | |||
1129 | /* Reset until next time */ | 1129 | /* Reset until next time */ | |
1130 | sc->sc_intr_status00_23 = 0; | 1130 | sc->sc_intr_status00_23 = 0; | |
1131 | sc->sc_intr_status24_39 = 0; | 1131 | sc->sc_intr_status24_39 = 0; | |
1132 | sc->sc_intr_status40_51 = 0; | 1132 | sc->sc_intr_status40_51 = 0; | |
1133 | sc->sc_intr_status72_95 = 0; | 1133 | sc->sc_intr_status72_95 = 0; | |
1134 | #endif /* MT7628 */ | 1134 | #endif /* MT7628 */ | |
1135 | 1135 | |||
1136 | return 1; | 1136 | return 1; | |
1137 | } | 1137 | } | |
1138 | 1138 | |||
1139 | /* | 1139 | /* | |
1140 | * Handle key debouncing for the given pin | 1140 | * Handle key debouncing for the given pin | |
1141 | */ | 1141 | */ | |
1142 | static bool | 1142 | static bool | |
1143 | ra_gpio_debounce_pin(ra_gpio_softc_t *sc, struct timeval *tv, u_int pin) | 1143 | ra_gpio_debounce_pin(ra_gpio_softc_t *sc, struct timeval *tv, u_int pin) | |
1144 | { | 1144 | { | |
1145 | RALINK_DEBUG_FUNC_ENTRY(); | 1145 | RALINK_DEBUG_FUNC_ENTRY(); | |
1146 | 1146 | |||
1147 | /* | 1147 | /* | |
1148 | * If a pin has a time set, it is waiting for | 1148 | * If a pin has a time set, it is waiting for | |
1149 | * a debounce period. Check if it is ready | 1149 | * a debounce period. Check if it is ready | |
1150 | * to send its event and clean up. Otherwise, | 1150 | * to send its event and clean up. Otherwise, | |
1151 | * reschedule 10mSec and try again later. | 1151 | * reschedule 10mSec and try again later. | |
1152 | */ | 1152 | */ | |
1153 | if (0 != debounce_time[pin].tv_sec) { | 1153 | if (0 != debounce_time[pin].tv_sec) { | |
1154 | if (timercmp(tv, &debounce_time[pin], <)) { | 1154 | if (timercmp(tv, &debounce_time[pin], <)) { | |
1155 | /* | 1155 | /* | |
1156 | * Haven't hit debounce time, | 1156 | * Haven't hit debounce time, | |
1157 | * need to reschedule | 1157 | * need to reschedule | |
1158 | */ | 1158 | */ | |
1159 | return true; | 1159 | return true; | |
1160 | } | 1160 | } | |
1161 | #if defined(SLICKROCK) | 1161 | #if defined(SLICKROCK) | |
1162 | switch (debounce_pin[pin]) { | 1162 | switch (debounce_pin[pin]) { | |
1163 | case SOFT_RST_IN_BUTTON: | 1163 | case SOFT_RST_IN_BUTTON: | |
1164 | KNOTE(&knotes, RESET_BUTTON_EVT); | 1164 | KNOTE(&knotes, RESET_BUTTON_EVT); | |
1165 | break; | 1165 | break; | |
1166 | 1166 | |||
1167 | case SS_BUTTON: | 1167 | case SS_BUTTON: | |
1168 | KNOTE(&knotes, SS_BUTTON_EVT); | 1168 | KNOTE(&knotes, SS_BUTTON_EVT); | |
1169 | break; | 1169 | break; | |
1170 | 1170 | |||
1171 | case WPS_BUTTON: | 1171 | case WPS_BUTTON: | |
1172 | KNOTE(&knotes, WPS_BUTTON_EVT); | 1172 | KNOTE(&knotes, WPS_BUTTON_EVT); | |
1173 | break; | 1173 | break; | |
1174 | 1174 | |||
1175 | case WIFI_ENABLE: | 1175 | case WIFI_ENABLE: | |
1176 | KNOTE(&knotes, WIFI_ENABLE_EVT); | 1176 | KNOTE(&knotes, WIFI_ENABLE_EVT); | |
1177 | break; | 1177 | break; | |
1178 | 1178 | |||
1179 | /* | 1179 | /* | |
1180 | * These events are in case of overcurrent | 1180 | * These events are in case of overcurrent | |
1181 | * on USB/ExpressCard devices. | 1181 | * on USB/ExpressCard devices. | |
1182 | * If we receive an overcurrent signal, | 1182 | * If we receive an overcurrent signal, | |
1183 | * turn off power to the device and | 1183 | * turn off power to the device and | |
1184 | * let the USB driver know. | 1184 | * let the USB driver know. | |
1185 | */ | 1185 | */ | |
1186 | case CURRENT_LIMIT_FLAG_USB1: | 1186 | case CURRENT_LIMIT_FLAG_USB1: | |
1187 | ra_gpio_pin_write(sc, POWER_EN_USB1, 0); | 1187 | ra_gpio_pin_write(sc, POWER_EN_USB1, 0); | |
1188 | KNOTE(&knotes, CURRENT_LIMIT_EVT); | 1188 | KNOTE(&knotes, CURRENT_LIMIT_EVT); | |
1189 | #if 0 | 1189 | #if 0 | |
1190 | cpusb_overcurrent_occurred(CURRENT_LIMIT_FLAG_USB1); | 1190 | cpusb_overcurrent_occurred(CURRENT_LIMIT_FLAG_USB1); | |
1191 | #endif | 1191 | #endif | |
1192 | printf("\nUSB1 current limit received!\n"); | 1192 | printf("\nUSB1 current limit received!\n"); | |
1193 | break; | 1193 | break; | |
1194 | 1194 | |||
1195 | case CURRENT_LIMIT_FLAG_USB2: | 1195 | case CURRENT_LIMIT_FLAG_USB2: | |
1196 | ra_gpio_pin_write(sc, POWER_EN_USB2, 0); | 1196 | ra_gpio_pin_write(sc, POWER_EN_USB2, 0); | |
1197 | KNOTE(&knotes, CURRENT_LIMIT_EVT); | 1197 | KNOTE(&knotes, CURRENT_LIMIT_EVT); | |
1198 | #if 0 | 1198 | #if 0 | |
1199 | cpusb_overcurrent_occurred(CURRENT_LIMIT_FLAG_USB2); | 1199 | cpusb_overcurrent_occurred(CURRENT_LIMIT_FLAG_USB2); | |
1200 | #endif | 1200 | #endif | |
1201 | printf("\nUSB2 current limit received!\n"); | 1201 | printf("\nUSB2 current limit received!\n"); | |
1202 | break; | 1202 | break; | |
1203 | 1203 | |||
1204 | case CURRENT_LIMIT_FLAG_USB3: | 1204 | case CURRENT_LIMIT_FLAG_USB3: | |
1205 | ra_gpio_pin_write(sc, POWER_EN_USB3, 0); | 1205 | ra_gpio_pin_write(sc, POWER_EN_USB3, 0); | |
1206 | KNOTE(&knotes, CURRENT_LIMIT_EVT); | 1206 | KNOTE(&knotes, CURRENT_LIMIT_EVT); | |
1207 | #if 0 | 1207 | #if 0 | |
1208 | cpusb_overcurrent_occurred(CURRENT_LIMIT_FLAG_USB3); | 1208 | cpusb_overcurrent_occurred(CURRENT_LIMIT_FLAG_USB3); | |
1209 | #endif | 1209 | #endif | |
1210 | printf("\nUSB3 current limit received!\n"); | 1210 | printf("\nUSB3 current limit received!\n"); | |
1211 | break; | 1211 | break; | |
1212 | 1212 | |||
1213 | case CURRENT_LIMIT_FLAG_EX1: | 1213 | case CURRENT_LIMIT_FLAG_EX1: | |
1214 | ra_gpio_pin_write(sc, POWER_EN_EX1, 0); | 1214 | ra_gpio_pin_write(sc, POWER_EN_EX1, 0); | |
1215 | KNOTE(&knotes, CURRENT_LIMIT_EVT); | 1215 | KNOTE(&knotes, CURRENT_LIMIT_EVT); | |
1216 | #if 0 | 1216 | #if 0 | |
1217 | cpusb_overcurrent_occurred(debounce_pin[pin]); | 1217 | cpusb_overcurrent_occurred(debounce_pin[pin]); | |
1218 | #endif | 1218 | #endif | |
1219 | printf("\nExpressCard1 current limit received!\n"); | 1219 | printf("\nExpressCard1 current limit received!\n"); | |
1220 | break; | 1220 | break; | |
1221 | 1221 | |||
1222 | case CURRENT_LIMIT_FLAG_EX2: | 1222 | case CURRENT_LIMIT_FLAG_EX2: | |
1223 | ra_gpio_pin_write(sc, POWER_EN_EX2, 0); | 1223 | ra_gpio_pin_write(sc, POWER_EN_EX2, 0); | |
1224 | KNOTE(&knotes, CURRENT_LIMIT_EVT); | 1224 | KNOTE(&knotes, CURRENT_LIMIT_EVT); | |
1225 | #if 0 | 1225 | #if 0 | |
1226 | cpusb_overcurrent_occurred(debounce_pin[pin]); | 1226 | cpusb_overcurrent_occurred(debounce_pin[pin]); | |
1227 | #endif | 1227 | #endif | |
1228 | printf("\nExpressCard2 current limit received!\n"); | 1228 | printf("\nExpressCard2 current limit received!\n"); | |
1229 | break; | 1229 | break; | |
1230 | 1230 | |||
1231 | default: | 1231 | default: | |
1232 | printf("\nUnknown debounce pin %d received.\n", | 1232 | printf("\nUnknown debounce pin %d received.\n", | |
1233 | debounce_pin[pin]); | 1233 | debounce_pin[pin]); | |
1234 | } | 1234 | } | |
1235 | #endif/* SLICKROCK */ | 1235 | #endif/* SLICKROCK */ | |
1236 | #if defined(PEBBLES500) || defined(PEBBLES35) | 1236 | #if defined(PEBBLES500) || defined(PEBBLES35) | |
1237 | switch (debounce_pin[pin]) { | 1237 | switch (debounce_pin[pin]) { | |
1238 | case SOFT_RST_IN_BUTTON: | 1238 | case SOFT_RST_IN_BUTTON: | |
1239 | KNOTE(&knotes, RESET_BUTTON_EVT); | 1239 | KNOTE(&knotes, RESET_BUTTON_EVT); | |
1240 | break; | 1240 | break; | |
1241 | 1241 | |||
1242 | case WPS_BUTTON: | 1242 | case WPS_BUTTON: | |
1243 | KNOTE(&knotes, WPS_BUTTON_EVT); | 1243 | KNOTE(&knotes, WPS_BUTTON_EVT); | |
1244 | break; | 1244 | break; | |
1245 | 1245 | |||
1246 | case EXCARD_ATTACH: | 1246 | case EXCARD_ATTACH: | |
1247 | KNOTE(&knotes, EXCARD_ATTACH_EVT); | 1247 | KNOTE(&knotes, EXCARD_ATTACH_EVT); | |
1248 | break; | 1248 | break; | |
1249 | 1249 | |||
1250 | /* | 1250 | /* | |
1251 | * These events are in case of overcurrent | 1251 | * These events are in case of overcurrent | |
1252 | * on USB/ExpressCard devices. | 1252 | * on USB/ExpressCard devices. | |
1253 | * If we receive an overcurrent signal, | 1253 | * If we receive an overcurrent signal, | |
1254 | * turn off power to the device and | 1254 | * turn off power to the device and | |
1255 | * let the USB driver know. | 1255 | * let the USB driver know. | |
1256 | */ | 1256 | */ | |
1257 | case CURRENT_LIMIT_FLAG_USB1: | 1257 | case CURRENT_LIMIT_FLAG_USB1: | |
1258 | ra_gpio_pin_write(sc, POWER_EN_USB, 0); | 1258 | ra_gpio_pin_write(sc, POWER_EN_USB, 0); | |
1259 | KNOTE(&knotes, CURRENT_LIMIT_EVT); | 1259 | KNOTE(&knotes, CURRENT_LIMIT_EVT); | |
1260 | cpusb_overcurrent_occurred(CURRENT_LIMIT_FLAG_USB1); | 1260 | cpusb_overcurrent_occurred(CURRENT_LIMIT_FLAG_USB1); | |
1261 | printf("\nUSB current limit received!\n"); | 1261 | printf("\nUSB current limit received!\n"); | |
1262 | break; | 1262 | break; | |
1263 | 1263 | |||
1264 | /* | 1264 | /* | |
1265 | * If either voltage is over current, | 1265 | * If either voltage is over current, | |
1266 | * turn off all ExpressCard power | 1266 | * turn off all ExpressCard power | |
1267 | */ | 1267 | */ | |
1268 | case CURRENT_LIMIT_FLAG1_3_3v: | 1268 | case CURRENT_LIMIT_FLAG1_3_3v: | |
1269 | case CURRENT_LIMIT_FLAG1_1_5v: | 1269 | case CURRENT_LIMIT_FLAG1_1_5v: | |
1270 | ra_gpio_pin_write(sc, POWER_EN_EXCARD1_3_3v, 0); | 1270 | ra_gpio_pin_write(sc, POWER_EN_EXCARD1_3_3v, 0); | |
1271 | ra_gpio_pin_write(sc, POWER_EN_EXCARD1_1_5v, 0); | 1271 | ra_gpio_pin_write(sc, POWER_EN_EXCARD1_1_5v, 0); | |
1272 | KNOTE(&knotes, CURRENT_LIMIT_EVT); | 1272 | KNOTE(&knotes, CURRENT_LIMIT_EVT); | |
1273 | cpusb_overcurrent_occurred(debounce_pin[pin]); | 1273 | cpusb_overcurrent_occurred(debounce_pin[pin]); | |
1274 | printf("\nExpressCard current limit received!\n"); | 1274 | printf("\nExpressCard current limit received!\n"); | |
1275 | break; | 1275 | break; | |
1276 | 1276 | |||
1277 | default: | 1277 | default: | |
1278 | printf("\nUnknown debounce pin received.\n"); | 1278 | printf("\nUnknown debounce pin received.\n"); | |
1279 | } | 1279 | } | |
1280 | #endif/* PEBBLES500 || PEBBLES35 */ | 1280 | #endif/* PEBBLES500 || PEBBLES35 */ | |
1281 | #if defined(TABLEROCK) || defined(SPOT2) || defined(PUCK) || defined(MOAB) | 1281 | #if defined(TABLEROCK) || defined(SPOT2) || defined(PUCK) || defined(MOAB) | |
1282 | if (POWER_OFF_BUTTON == debounce_pin[pin]) { | 1282 | if (POWER_OFF_BUTTON == debounce_pin[pin]) { | |
1283 | KNOTE(&knotes, POWER_BUTTON_EVT); | 1283 | KNOTE(&knotes, POWER_BUTTON_EVT); | |
1284 | } | 1284 | } | |
1285 | if (LAN_WAN_SW == debounce_pin[pin]) { | 1285 | if (LAN_WAN_SW == debounce_pin[pin]) { | |
1286 | KNOTE(&knotes, LAN_WAN_SW_EVT); | 1286 | KNOTE(&knotes, LAN_WAN_SW_EVT); | |
1287 | } | 1287 | } | |
1288 | if (DOCK_SENSE == debounce_pin[pin]) { | 1288 | if (DOCK_SENSE == debounce_pin[pin]) { | |
1289 | KNOTE(&knotes, DOCK_SENSE_EVT); | 1289 | KNOTE(&knotes, DOCK_SENSE_EVT); | |
1290 | } | 1290 | } | |
1291 | if (WPS_BUTTON == debounce_pin[pin]) { | 1291 | if (WPS_BUTTON == debounce_pin[pin]) { | |
1292 | KNOTE(&knotes, WPS_BUTTON_EVT); | 1292 | KNOTE(&knotes, WPS_BUTTON_EVT); | |
1293 | } | 1293 | } | |
1294 | if (IN_5V == debounce_pin[pin]) { | 1294 | if (IN_5V == debounce_pin[pin]) { | |
1295 | /* Set the charger to match the in 5V line */ | 1295 | /* Set the charger to match the in 5V line */ | |
1296 | if (ra_gpio_pin_read(sc, IN_5V) == 0) { | 1296 | if (ra_gpio_pin_read(sc, IN_5V) == 0) { | |
1297 | ra_gpio_pin_write(sc, CHARGER_OFF, 0); | 1297 | ra_gpio_pin_write(sc, CHARGER_OFF, 0); | |
1298 | } else { | 1298 | } else { | |
1299 | ra_gpio_pin_write(sc, CHARGER_OFF, 1); | 1299 | ra_gpio_pin_write(sc, CHARGER_OFF, 1); | |
1300 | } | 1300 | } | |
1301 | KNOTE(&knotes, IN_5V_EVT); | 1301 | KNOTE(&knotes, IN_5V_EVT); | |
1302 | } | 1302 | } | |
1303 | #endif/* TABLEROCK || SPOT2 || PUCK || MOAB */ | 1303 | #endif/* TABLEROCK || SPOT2 || PUCK || MOAB */ | |
1304 | /* Re-enable interrupt and reset time */ | 1304 | /* Re-enable interrupt and reset time */ | |
1305 | enable_gpio_interrupt(sc, debounce_pin[pin]); | 1305 | enable_gpio_interrupt(sc, debounce_pin[pin]); | |
1306 | debounce_time[pin].tv_sec = 0; | 1306 | debounce_time[pin].tv_sec = 0; | |
1307 | 1307 | |||
1308 | } | 1308 | } | |
1309 | return false; | 1309 | return false; | |
1310 | } | 1310 | } | |
1311 | 1311 | |||
1312 | /* | 1312 | /* | |
1313 | * Handle key debouncing. | 1313 | * Handle key debouncing. | |
1314 | * Re-enable the key interrupt after DEBOUNCE_TIME | 1314 | * Re-enable the key interrupt after DEBOUNCE_TIME | |
1315 | */ | 1315 | */ | |
1316 | static void | 1316 | static void | |
1317 | ra_gpio_debounce_process(void *arg) | 1317 | ra_gpio_debounce_process(void *arg) | |
1318 | { | 1318 | { | |
1319 | RALINK_DEBUG_FUNC_ENTRY(); | 1319 | RALINK_DEBUG_FUNC_ENTRY(); | |
1320 | ra_gpio_softc_t * const sc = arg; | 1320 | ra_gpio_softc_t * const sc = arg; | |
1321 | bool reschedule = false; | 1321 | bool reschedule = false; | |
1322 | struct timeval now; | 1322 | struct timeval now; | |
1323 | 1323 | |||
1324 | microtime(&now); | 1324 | microtime(&now); | |
1325 | 1325 | |||
1326 | for (u_int pin=0; pin < __arraycount(debounce_pin); pin++) | 1326 | for (u_int pin=0; pin < __arraycount(debounce_pin); pin++) | |
1327 | if (ra_gpio_debounce_pin(sc, &now, pin)) | 1327 | if (ra_gpio_debounce_pin(sc, &now, pin)) | |
1328 | reschedule = true; | 1328 | reschedule = true; | |
1329 | 1329 | |||
1330 | if (reschedule) | 1330 | if (reschedule) | |
1331 | callout_schedule(&sc->sc_tick_callout, MS_TO_HZ(10)); | 1331 | callout_schedule(&sc->sc_tick_callout, MS_TO_HZ(10)); | |
1332 | } | 1332 | } | |
1333 | 1333 | |||
1334 | /* | 1334 | /* | |
1335 | * Handle key and other interrupt debouncing. | 1335 | * Handle key and other interrupt debouncing. | |
1336 | */ | 1336 | */ | |
1337 | static void | 1337 | static void | |
1338 | ra_gpio_debounce_setup(ra_gpio_softc_t *sc) | 1338 | ra_gpio_debounce_setup(ra_gpio_softc_t *sc) | |
1339 | { | 1339 | { | |
1340 | RALINK_DEBUG_FUNC_ENTRY(); | 1340 | RALINK_DEBUG_FUNC_ENTRY(); | |
1341 | u_int32_t pin; | 1341 | u_int32_t pin; | |
1342 | struct timeval now; | 1342 | struct timeval now; | |
1343 | struct timeval wait = { | 1343 | struct timeval wait = { | |
1344 | .tv_sec = 0, | 1344 | .tv_sec = 0, | |
1345 | .tv_usec = (DEBOUNCE_TIME * 1000) | 1345 | .tv_usec = (DEBOUNCE_TIME * 1000) | |
1346 | }; | 1346 | }; | |
1347 | 1347 | |||
1348 | /* | 1348 | /* | |
1349 | * The 371/372 series are a bit more complex. They have | 1349 | * The 371/372 series are a bit more complex. They have | |
1350 | * interrupt sources across all three interrupt | 1350 | * interrupt sources across all three interrupt | |
1351 | * registers. | 1351 | * registers. | |
1352 | */ | 1352 | */ | |
1353 | for (int i = 0; i < __arraycount(debounce_pin); i++) { | 1353 | for (int i = 0; i < __arraycount(debounce_pin); i++) { | |
1354 | u_int32_t *intr_status; | 1354 | u_int32_t *intr_status; | |
1355 | int offset; | 1355 | int offset; | |
1356 | #if defined(MT7628) | 1356 | #if defined(MT7628) | |
1357 | if (debounce_pin[i] < 32) { | 1357 | if (debounce_pin[i] < 32) { | |
1358 | intr_status = &sc->sc_intr_status00_31; | 1358 | intr_status = &sc->sc_intr_status00_31; | |
1359 | offset = 0; | 1359 | offset = 0; | |
1360 | } else if (debounce_pin[i] < 64) { | 1360 | } else if (debounce_pin[i] < 64) { | |
1361 | intr_status = &sc->sc_intr_status32_63; | 1361 | intr_status = &sc->sc_intr_status32_63; | |
1362 | offset = 32; | 1362 | offset = 32; | |
1363 | } else { | 1363 | } else { | |
1364 | intr_status = &sc->sc_intr_status64_95; | 1364 | intr_status = &sc->sc_intr_status64_95; | |
1365 | offset = 64; | 1365 | offset = 64; | |
1366 | } | 1366 | } | |
1367 | #else /* !MT7628 */ | 1367 | #else /* !MT7628 */ | |
1368 | if (debounce_pin[i] < 24) { | 1368 | if (debounce_pin[i] < 24) { | |
1369 | intr_status = &sc->sc_intr_status00_23; | 1369 | intr_status = &sc->sc_intr_status00_23; | |
1370 | offset = 0; | 1370 | offset = 0; | |
1371 | } else if (debounce_pin[i] < 40) { | 1371 | } else if (debounce_pin[i] < 40) { | |
1372 | intr_status = &sc->sc_intr_status24_39; | 1372 | intr_status = &sc->sc_intr_status24_39; | |
1373 | offset = 24; | 1373 | offset = 24; | |
1374 | } else if (debounce_pin[i] < 71) { | 1374 | } else if (debounce_pin[i] < 71) { | |
1375 | intr_status = &sc->sc_intr_status40_51; | 1375 | intr_status = &sc->sc_intr_status40_51; | |
1376 | offset = 40; | 1376 | offset = 40; | |
1377 | } else { | 1377 | } else { | |
1378 | intr_status = &sc->sc_intr_status72_95; | 1378 | intr_status = &sc->sc_intr_status72_95; | |
1379 | offset = 72; | 1379 | offset = 72; | |
1380 | } | 1380 | } | |
1381 | #endif /* !MT7628 */ | 1381 | #endif /* !MT7628 */ | |
1382 | if (*intr_status & (1 << (debounce_pin[i] - offset))) { | 1382 | if (*intr_status & (1 << (debounce_pin[i] - offset))) { | |
1383 | pin = debounce_pin[i]; | 1383 | pin = debounce_pin[i]; | |
1384 | 1384 | |||
1385 | #ifdef ENABLE_RALINK_DEBUG_INFO | 1385 | #ifdef ENABLE_RALINK_DEBUG_INFO | |
1386 | if (ra_gpio_pin_read(sc, pin)) { | 1386 | if (ra_gpio_pin_read(sc, pin)) { | |
1387 | RALINK_DEBUG(RALINK_DEBUG_INFO, | 1387 | RALINK_DEBUG(RALINK_DEBUG_INFO, | |
1388 | "%s() button 0x%x, pin %d released\n", | 1388 | "%s() button 0x%x, pin %d released\n", | |
1389 | __func__, *intr_status, pin); | 1389 | __func__, *intr_status, pin); | |
1390 | } else { | 1390 | } else { | |
1391 | RALINK_DEBUG(RALINK_DEBUG_INFO, | 1391 | RALINK_DEBUG(RALINK_DEBUG_INFO, | |
1392 | "%s() button 0x%x, pin %d pressed\n", | 1392 | "%s() button 0x%x, pin %d pressed\n", | |
1393 | __func__, *intr_status, pin); | 1393 | __func__, *intr_status, pin); | |
1394 | } | 1394 | } | |
1395 | #endif | 1395 | #endif | |
1396 | 1396 | |||
1397 | #if 0 | 1397 | #if 0 | |
1398 | /* Mask pin that is being handled */ | 1398 | /* Mask pin that is being handled */ | |
1399 | *intr_status &= ~((1 << (debounce_pin[i] - offset))); | 1399 | *intr_status &= ~((1 << (debounce_pin[i] - offset))); | |
1400 | #endif | 1400 | #endif | |
1401 | 1401 | |||
1402 | /* Handle debouncing. */ | 1402 | /* Handle debouncing. */ | |
1403 | disable_gpio_interrupt(sc, pin); | 1403 | disable_gpio_interrupt(sc, pin); | |
1404 | microtime(&now); | 1404 | microtime(&now); | |
1405 | 1405 | |||
1406 | #if defined(TABLEROCK) | 1406 | #if defined(TABLEROCK) | |
1407 | /* | 1407 | /* | |
1408 | * The dock's LAN_WAN switch can cause a fire of | 1408 | * The dock's LAN_WAN switch can cause a fire of | |
1409 | * interrupts if it sticks in the half-way position. | 1409 | * interrupts if it sticks in the half-way position. | |
1410 | * Ignore it for longer than other buttons. | 1410 | * Ignore it for longer than other buttons. | |
1411 | */ | 1411 | */ | |
1412 | if (pin == LAN_WAN_SW) { | 1412 | if (pin == LAN_WAN_SW) { | |
1413 | wait.tv_usec *= 2; | 1413 | wait.tv_usec *= 2; | |
1414 | } | 1414 | } | |
1415 | #endif | 1415 | #endif | |
1416 | 1416 | |||
1417 | timeradd(&now, &wait, &debounce_time[i]); | 1417 | timeradd(&now, &wait, &debounce_time[i]); | |
1418 | } | 1418 | } | |
1419 | } | 1419 | } | |
1420 | 1420 | |||
1421 | /* If the debounce callout hasn't been scheduled, start it up. */ | 1421 | /* If the debounce callout hasn't been scheduled, start it up. */ | |
1422 | if (FALSE == callout_pending(&sc->sc_tick_callout)) { | 1422 | if (FALSE == callout_pending(&sc->sc_tick_callout)) { | |
1423 | callout_schedule(&sc->sc_tick_callout, MS_TO_HZ(DEBOUNCE_TIME)); | 1423 | callout_schedule(&sc->sc_tick_callout, MS_TO_HZ(DEBOUNCE_TIME)); | |
1424 | } | 1424 | } | |
1425 | } | 1425 | } | |
1426 | 1426 | |||
1427 | /* | 1427 | /* | |
1428 | * Disable both rising and falling | 1428 | * Disable both rising and falling | |
1429 | */ | 1429 | */ | |
1430 | static void | 1430 | static void | |
1431 | disable_gpio_interrupt(ra_gpio_softc_t *sc, int pin) | 1431 | disable_gpio_interrupt(ra_gpio_softc_t *sc, int pin) | |
1432 | { | 1432 | { | |
1433 | RALINK_DEBUG_FUNC_ENTRY(); | 1433 | RALINK_DEBUG_FUNC_ENTRY(); | |
1434 | const int index = pin_tab_index[pin]; | 1434 | const int index = pin_tab_index[pin]; | |
1435 | KASSERTMSG(index != -1, "%s: non-existant pin=%d\n", __func__, pin); | 1435 | KASSERTMSG(index != -1, "%s: non-existant pin=%d\n", __func__, pin); | |
1436 | if (index == -1) | 1436 | if (index == -1) | |
1437 | return; | 1437 | return; | |
1438 | 1438 | |||
1439 | const pin_tab_t * const ptp = &pin_tab[index]; | 1439 | const pin_tab_t * const ptp = &pin_tab[index]; | |
1440 | const uint32_t reg_bit = 1 << (pin - ptp->pin_reg_base); | 1440 | const uint32_t reg_bit = 1 << (pin - ptp->pin_reg_base); | |
1441 | uint32_t r; | 1441 | uint32_t r; | |
1442 | 1442 | |||
1443 | r = gp_read(sc, ptp->pin_rise.reg); | 1443 | r = gp_read(sc, ptp->pin_rise.reg); | |
1444 | r &= ~reg_bit; | 1444 | r &= ~reg_bit; | |
1445 | gp_write(sc, ptp->pin_rise.reg, r); | 1445 | gp_write(sc, ptp->pin_rise.reg, r); | |
1446 | 1446 | |||
1447 | r = gp_read(sc, ptp->pin_fall.reg); | 1447 | r = gp_read(sc, ptp->pin_fall.reg); | |
1448 | r &= ~reg_bit; | 1448 | r &= ~reg_bit; | |
1449 | gp_write(sc, ptp->pin_fall.reg, r); | 1449 | gp_write(sc, ptp->pin_fall.reg, r); | |
1450 | } | 1450 | } | |
1451 | 1451 | |||
1452 | /* | 1452 | /* | |
1453 | * Restore GPIO interrupt setting | 1453 | * Restore GPIO interrupt setting | |
1454 | */ | 1454 | */ | |
1455 | static void | 1455 | static void | |
1456 | enable_gpio_interrupt(ra_gpio_softc_t *sc, int pin) | 1456 | enable_gpio_interrupt(ra_gpio_softc_t *sc, int pin) | |
1457 | { | 1457 | { | |
1458 | const int index = pin_tab_index[pin]; | 1458 | const int index = pin_tab_index[pin]; | |
1459 | KASSERTMSG(index != -1, "%s: non-existant pin=%d\n", __func__, pin); | 1459 | KASSERTMSG(index != -1, "%s: non-existant pin=%d\n", __func__, pin); | |
1460 | if (index == -1) | 1460 | if (index == -1) | |
1461 | return; | 1461 | return; | |
1462 | 1462 | |||
1463 | const pin_tab_t * const ptp = &pin_tab[index]; | 1463 | const pin_tab_t * const ptp = &pin_tab[index]; | |
1464 | const uint32_t mask_bit = 1 << (pin - ptp->pin_mask_base); | 1464 | const uint32_t mask_bit = 1 << (pin - ptp->pin_mask_base); | |
1465 | const uint32_t reg_bit = 1 << (pin - ptp->pin_reg_base); | 1465 | const uint32_t reg_bit = 1 << (pin - ptp->pin_reg_base); | |
1466 | uint32_t r; | 1466 | uint32_t r; | |
1467 | 1467 | |||
1468 | if (ptp->pin_rise.mask & mask_bit) { | 1468 | if (ptp->pin_rise.mask & mask_bit) { | |
1469 | r = gp_read(sc, ptp->pin_rise.reg); | 1469 | r = gp_read(sc, ptp->pin_rise.reg); | |
1470 | r |= reg_bit; | 1470 | r |= reg_bit; | |
1471 | gp_write(sc, ptp->pin_rise.reg, r); | 1471 | gp_write(sc, ptp->pin_rise.reg, r); | |
1472 | } | 1472 | } | |
1473 | 1473 | |||
1474 | if (ptp->pin_fall.mask & mask_bit) { | 1474 | if (ptp->pin_fall.mask & mask_bit) { | |
1475 | r = gp_read(sc, ptp->pin_fall.reg); | 1475 | r = gp_read(sc, ptp->pin_fall.reg); | |
1476 | r |= reg_bit; | 1476 | r |= reg_bit; | |
1477 | gp_write(sc, ptp->pin_fall.reg, r); | 1477 | gp_write(sc, ptp->pin_fall.reg, r); | |
1478 | } | 1478 | } | |
1479 | } | 1479 | } | |
1480 | 1480 | |||
1481 | /* | 1481 | /* | |
1482 | * XXX this function is obsolete/unused? XXX | 1482 | * XXX this function is obsolete/unused? XXX | |
1483 | * | 1483 | * | |
1484 | * Go through each of the interrupts and send the appropriate | 1484 | * Go through each of the interrupts and send the appropriate | |
1485 | * event. | 1485 | * event. | |
1486 | */ | 1486 | */ | |
1487 | static void | 1487 | static void | |
1488 | ra_gpio_softintr(void *arg) | 1488 | ra_gpio_softintr(void *arg) | |
1489 | { | 1489 | { | |
1490 | #if defined(MT7628) | 1490 | #if defined(MT7628) | |
1491 | RALINK_DEBUG(RALINK_DEBUG_INFO, | 1491 | RALINK_DEBUG(RALINK_DEBUG_INFO, | |
1492 | "gpio softintr called with 0x%x, 0x%x, 0x%x\n", | 1492 | "gpio softintr called with 0x%x, 0x%x, 0x%x\n", | |
1493 | sc->sc_intr_status00_31, sc->sc_intr_status32_63, | 1493 | sc->sc_intr_status00_31, sc->sc_intr_status32_63, | |
1494 | sc->sc_intr_status64_95); | 1494 | sc->sc_intr_status64_95); | |
1495 | #else | 1495 | #else | |
1496 | RALINK_DEBUG(RALINK_DEBUG_INFO, | 1496 | RALINK_DEBUG(RALINK_DEBUG_INFO, | |
1497 | "gpio softintr called with 0x%x, 0x%x, 0x%x, 0x%x\n", | 1497 | "gpio softintr called with 0x%x, 0x%x, 0x%x, 0x%x\n", | |
1498 | sc->sc_intr_status00_23, sc->sc_intr_status24_39, | 1498 | sc->sc_intr_status00_23, sc->sc_intr_status24_39, | |
1499 | sc->sc_intr_status40_51, sc->sc_intr_status72_95); | 1499 | sc->sc_intr_status40_51, sc->sc_intr_status72_95); | |
1500 | #endif | 1500 | #endif |