Annotation of sys/arch/arm/xscale/pxa2x0_apm.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: pxa2x0_apm.c,v 1.28 2007/03/29 18:42:38 uwe Exp $ */
2:
3: /*-
4: * Copyright (c) 2001 Alexander Guy. All rights reserved.
5: * Copyright (c) 1998-2001 Michael Shalayeff. All rights reserved.
6: * Copyright (c) 1995 John T. Kohl. All rights reserved.
7: *
8: * Redistribution and use in source and binary forms, with or without
9: * modification, are permitted provided that the following conditions
10: * are met:
11: * 1. Redistributions of source code must retain the above copyright
12: * notice, this list of conditions and the following disclaimer.
13: * 2. Redistributions in binary form must reproduce the above copyright
14: * notice, this list of conditions and the following disclaimer in the
15: * documentation and/or other materials provided with the distribution.
16: * 3. All advertising materials mentioning features or use of this software
17: * must display the following acknowledgement:
18: * This product includes software developed by the University of
19: * California, Berkeley and its contributors.
20: * 4. Neither the name of the University nor the names of its contributors
21: * may be used to endorse or promote products derived from this software
22: * without specific prior written permission.
23: *
24: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30: * OR SERVICES; LOSS OF MIND, USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34: * SUCH DAMAGE.
35: *
36: */
37:
38: #include <sys/param.h>
39: #include <sys/systm.h>
40: #include <sys/kernel.h>
41: #include <sys/kthread.h>
42: #include <sys/lock.h>
43: #include <sys/mount.h> /* for vfs_syncwait() */
44: #include <sys/proc.h>
45: #include <sys/device.h>
46: #include <sys/fcntl.h>
47: #include <sys/ioctl.h>
48: #include <sys/event.h>
49:
50: #include <machine/conf.h>
51: #include <machine/cpu.h>
52: #include <machine/apmvar.h>
53:
54: #include <arm/xscale/pxa2x0reg.h>
55: #include <arm/xscale/pxa2x0var.h>
56: #include <arm/xscale/pxa2x0_apm.h>
57: #include <arm/xscale/pxa2x0_gpio.h>
58:
59: #if defined(APMDEBUG)
60: #define DPRINTF(x) printf x
61: #else
62: #define DPRINTF(x) /**/
63: #endif
64:
65: #define APM_LOCK(sc) lockmgr(&(sc)->sc_lock, LK_EXCLUSIVE, NULL)
66: #define APM_UNLOCK(sc) lockmgr(&(sc)->sc_lock, LK_RELEASE, NULL)
67:
68: struct cfdriver apm_cd = {
69: NULL, "apm", DV_DULL
70: };
71:
72: #define APMUNIT(dev) (minor(dev)&0xf0)
73: #define APMDEV(dev) (minor(dev)&0x0f)
74: #define APMDEV_NORMAL 0
75: #define APMDEV_CTL 8
76:
77: int apm_userstandbys;
78: int apm_suspends;
79: int apm_battlow;
80:
81: /* battery percentage at which we get verbose in our warnings. This
82: value can be changed using sysctl(8), value machdep.apmwarn.
83: Setting it to zero kills all warnings */
84: int cpu_apmwarn = 10;
85:
86: void apm_power_print(struct pxa2x0_apm_softc *, struct apm_power_info *);
87: void apm_power_info(struct pxa2x0_apm_softc *, struct apm_power_info *);
88: void apm_suspend(struct pxa2x0_apm_softc *);
89: void apm_resume(struct pxa2x0_apm_softc *);
90: int apm_get_event(struct pxa2x0_apm_softc *, u_int *);
91: int apm_handle_event(struct pxa2x0_apm_softc *, u_int);
92: void apm_thread_create(void *);
93: void apm_thread(void *);
94:
95: extern int perflevel;
96: int freq;
97: void pxa2x0_setperf(int speed);
98: int pxa2x0_cpuspeed(int *speed);
99:
100: int apm_record_event(struct pxa2x0_apm_softc *, u_int);
101: void filt_apmrdetach(struct knote *kn);
102: int filt_apmread(struct knote *kn, long hint);
103: int apmkqfilter(dev_t dev, struct knote *kn);
104:
105: struct filterops apmread_filtops =
106: { 1, NULL, filt_apmrdetach, filt_apmread};
107:
108: /*
109: * Flags to control kernel display
110: * SCFLAG_NOPRINT: do not output APM power messages due to
111: * a power change event.
112: *
113: * SCFLAG_PCTPRINT: do not output APM power messages due to
114: * to a power change event unless the battery
115: * percentage changes.
116: */
117:
118: #define SCFLAG_NOPRINT 0x0008000
119: #define SCFLAG_PCTPRINT 0x0004000
120: #define SCFLAG_PRINT (SCFLAG_NOPRINT|SCFLAG_PCTPRINT)
121:
122: #define SCFLAG_OREAD (1 << 0)
123: #define SCFLAG_OWRITE (1 << 1)
124: #define SCFLAG_OPEN (SCFLAG_OREAD|SCFLAG_OWRITE)
125:
126: /* This structure must be kept in sync with pxa2x0_apm_asm.S. */
127: struct pxa2x0_memcfg {
128: /* SDRAM refresh */
129: u_int32_t mdrefr_high; /* 0x00 */
130: u_int32_t mdrefr_low; /* 0x04 */
131: u_int32_t mdrefr_low2; /* 0x08 */
132: /* Synchronous, static, or VLIO interfaces */
133: u_int32_t msc_high[3]; /* 0x0c */
134: u_int32_t msc_low[3]; /* 0x18 */
135: /* XXX move up */
136: u_int32_t mdrefr_91; /* 0x24 */
137: };
138:
139: /* XXX */
140: #define MDREFR_C3000 (MDREFR_K0DB2 | MDREFR_E1PIN | MDREFR_K1RUN | \
141: MDREFR_K1DB2 | MDREFR_K2DB2 | MDREFR_APD)
142: #define MSC0_HIGH \
143: ( 7 << MSC_RRR_SHIFT << 16) | \
144: (15 << MSC_RDN_SHIFT << 16) | \
145: (15 << MSC_RDF_SHIFT << 16) | \
146: (MSC_RT_NONBURST << 16) | \
147: ( 2 << MSC_RRR_SHIFT) | \
148: (13 << MSC_RDN_SHIFT) | \
149: (13 << MSC_RDF_SHIFT) | \
150: MSC_RBW /* PXA271 */ | \
151: MSC_RT_NONBURST
152: #define MSC1_HIGH \
153: ( 7 << MSC_RRR_SHIFT << 16) | \
154: (15 << MSC_RDN_SHIFT << 16) | \
155: (15 << MSC_RDF_SHIFT << 16) | \
156: (MSC_RT_VLIO << 16) | \
157: ( 3 << MSC_RRR_SHIFT) | \
158: ( 4 << MSC_RDN_SHIFT) | \
159: (13 << MSC_RDF_SHIFT) | \
160: MSC_RT_VLIO
161: #define MSC2_HIGH \
162: ( 7 << MSC_RRR_SHIFT << 16) | \
163: (15 << MSC_RDN_SHIFT << 16) | \
164: (15 << MSC_RDF_SHIFT << 16) | \
165: (MSC_RT_NONBURST << 16) | \
166: ( 3 << MSC_RRR_SHIFT) | \
167: ( 4 << MSC_RDN_SHIFT) | \
168: (13 << MSC_RDF_SHIFT) | \
169: MSC_RT_VLIO
170: #define MSC0_LOW \
171: ( 7 << MSC_RRR_SHIFT << 16) | \
172: (15 << MSC_RDN_SHIFT << 16) | \
173: (15 << MSC_RDF_SHIFT << 16) | \
174: (MSC_RT_NONBURST << 16) | \
175: ( 1 << MSC_RRR_SHIFT) | \
176: ( 8 << MSC_RDN_SHIFT) | \
177: ( 8 << MSC_RDF_SHIFT) | \
178: MSC_RBW /* PXA271 */ | \
179: MSC_RT_NONBURST
180: #define MSC1_LOW \
181: ( 7 << MSC_RRR_SHIFT << 16) | \
182: (15 << MSC_RDN_SHIFT << 16) | \
183: (15 << MSC_RDF_SHIFT << 16) | \
184: (MSC_RT_VLIO << 16) | \
185: ( 1 << MSC_RRR_SHIFT) | \
186: ( 2 << MSC_RDN_SHIFT) | \
187: ( 6 << MSC_RDF_SHIFT) | \
188: MSC_RT_VLIO
189: #define MSC2_LOW \
190: ( 7 << MSC_RRR_SHIFT << 16) | \
191: (15 << MSC_RDN_SHIFT << 16) | \
192: (15 << MSC_RDF_SHIFT << 16) | \
193: (MSC_RT_NONBURST << 16) | \
194: ( 1 << MSC_RRR_SHIFT) | \
195: ( 2 << MSC_RDN_SHIFT) | \
196: ( 6 << MSC_RDF_SHIFT) | \
197: MSC_RT_VLIO
198: struct pxa2x0_memcfg pxa2x0_memcfg = {
199: (MDREFR_C3000 | 0x030),
200: (MDREFR_C3000 | 0x00b),
201: (MDREFR_C3000 | 0x017),
202: { MSC0_HIGH, MSC1_HIGH, MSC2_HIGH },
203: { MSC1_LOW, MSC1_LOW, MSC2_LOW },
204: (MDREFR_C3000 | 0x013)
205: };
206:
207: #define PI2C_RETRY_COUNT 10
208: /* XXX varies depending on voltage regulator IC. */
209: #define PI2C_VOLTAGE_LOW 0x13 /* 1.00V */
210: #define PI2C_VOLTAGE_HIGH 0x1a /* 1.35V */
211:
212: void pxa2x0_pi2c_open(bus_space_tag_t, bus_space_handle_t);
213: void pxa2x0_pi2c_close(bus_space_tag_t, bus_space_handle_t);
214: int pxa2x0_pi2c_read(bus_space_tag_t, bus_space_handle_t, u_char, u_char *);
215: int pxa2x0_pi2c_write(bus_space_tag_t, bus_space_handle_t, u_char, u_char);
216: int pxa2x0_pi2c_getvoltage(bus_space_tag_t, bus_space_handle_t, u_char *);
217: int pxa2x0_pi2c_setvoltage(bus_space_tag_t, bus_space_handle_t, u_char);
218: #if 0
219: void pxa2x0_pi2c_print(struct pxa2x0_apm_softc *);
220: #endif
221:
222: /* XXX used in pxa2x0_apm_asm.S */
223: bus_space_handle_t pxa2x0_gpio_ioh;
224: bus_space_handle_t pxa2x0_clkman_ioh;
225: bus_space_handle_t pxa2x0_memctl_ioh;
226:
227: /* pxa2x0_apm_asm.S */
228: void pxa27x_run_mode(void);
229: void pxa27x_fastbus_run_mode(int, u_int32_t);
230: void pxa27x_frequency_change(int, int, struct pxa2x0_memcfg *);
231: void pxa2x0_cpu_suspend(void);
232: void pxa2x0_cpu_resume(void);
233: void pxa27x_cpu_speed_high(void);
234: void pxa27x_cpu_speed_low(void);
235: void pxa27x_cpu_speed_91(void);
236: void pxa27x_cpu_speed_208(void);
237:
238: void
239: apm_power_print(struct pxa2x0_apm_softc *sc, struct apm_power_info *powerp)
240: {
241:
242: if (powerp->battery_life != APM_BATT_LIFE_UNKNOWN)
243: printf("%s: battery life expectancy %d%%\n",
244: sc->sc_dev.dv_xname, powerp->battery_life);
245:
246: printf("%s: AC ", sc->sc_dev.dv_xname);
247: switch (powerp->ac_state) {
248: case APM_AC_OFF:
249: printf("off,");
250: break;
251: case APM_AC_ON:
252: printf("on,");
253: break;
254: case APM_AC_BACKUP:
255: printf("backup power,");
256: break;
257: default:
258: case APM_AC_UNKNOWN:
259: printf("unknown,");
260: break;
261: }
262:
263: printf(" battery is ");
264: switch (powerp->battery_state) {
265: case APM_BATT_HIGH:
266: printf("high");
267: break;
268: case APM_BATT_LOW:
269: printf("low");
270: break;
271: case APM_BATT_CRITICAL:
272: printf("CRITICAL");
273: break;
274: case APM_BATT_CHARGING:
275: printf("charging");
276: break;
277: case APM_BATT_UNKNOWN:
278: printf("unknown");
279: break;
280: default:
281: printf("undecoded (%x)", powerp->battery_state);
282: break;
283: }
284:
285: printf("\n");
286: }
287:
288: void
289: apm_power_info(struct pxa2x0_apm_softc *sc,
290: struct apm_power_info *power)
291: {
292:
293: power->ac_state = APM_AC_UNKNOWN;
294: power->battery_state = APM_BATT_UNKNOWN;
295: power->battery_life = 0 /* APM_BATT_LIFE_UNKNOWN */;
296: power->minutes_left = 0;
297:
298: if (sc->sc_power_info != NULL)
299: sc->sc_power_info(sc, power);
300: }
301:
302: void
303: apm_suspend(struct pxa2x0_apm_softc *sc)
304: {
305:
306: resettodr();
307:
308: dopowerhooks(PWR_SUSPEND);
309:
310: if (cold)
311: vfs_syncwait(0);
312:
313: if (sc->sc_suspend == NULL)
314: pxa2x0_wakeup_config(PXA2X0_WAKEUP_ALL, 1);
315: else
316: sc->sc_suspend(sc);
317:
318: pxa2x0_apm_sleep(sc);
319: }
320:
321: void
322: apm_resume(struct pxa2x0_apm_softc *sc)
323: {
324:
325: dopowerhooks(PWR_RESUME);
326:
327: inittodr(0);
328:
329: /*
330: * Clear the OTG Peripheral hold after running the pxaudc and pxaohci
331: * powerhooks to re-enable their operation. See 3.8.1.2
332: */
333: /* XXX ifdef NPXAUDC > 0 */
334: bus_space_write_4(sc->sc_iot, sc->sc_pm_ioh, POWMAN_PSSR, PSSR_OTGPH);
335: }
336:
337: int
338: apm_get_event(struct pxa2x0_apm_softc *sc, u_int *typep)
339: {
340:
341: if (sc->sc_get_event != NULL)
342: return (sc->sc_get_event(sc, typep));
343:
344: *typep = APM_NOEVENT;
345: return (1);
346: }
347:
348: int
349: apm_handle_event(struct pxa2x0_apm_softc *sc, u_int type)
350: {
351: struct apm_power_info power;
352: int ret = 0;
353:
354: switch (type) {
355: case APM_NOEVENT:
356: ret = 1;
357: break;
358: case APM_CRIT_SUSPEND_REQ:
359: DPRINTF(("suspend required immediately\n"));
360: #if 0
361: /* XXX apmd would make us suspend again after resume. */
362: (void)apm_record_event(sc, type);
363: #endif
364: /*
365: * We ignore APM_CRIT_RESUME and just suspend here as usual
366: * to simplify the actual apm_get_event() implementation.
367: */
368: apm_suspends++;
369: ret = 1;
370: break;
371: case APM_USER_SUSPEND_REQ:
372: case APM_SUSPEND_REQ:
373: DPRINTF(("suspend requested\n"));
374: if (apm_record_event(sc, type)) {
375: DPRINTF(("suspend ourselves\n"));
376: apm_suspends++;
377: }
378: break;
379: case APM_POWER_CHANGE:
380: DPRINTF(("power status change\n"));
381: apm_power_info(sc, &power);
382: if (power.battery_life != APM_BATT_LIFE_UNKNOWN &&
383: power.battery_life < cpu_apmwarn &&
384: (sc->sc_flags & SCFLAG_PRINT) != SCFLAG_NOPRINT &&
385: ((sc->sc_flags & SCFLAG_PRINT) != SCFLAG_PCTPRINT ||
386: sc->sc_batt_life != power.battery_life)) {
387: sc->sc_batt_life = power.battery_life;
388: apm_power_print(sc, &power);
389: }
390: apm_record_event(sc, type);
391: break;
392: case APM_BATTERY_LOW:
393: DPRINTF(("Battery low!\n"));
394: apm_battlow++;
395: apm_record_event(sc, type);
396: break;
397: default:
398: DPRINTF(("apm_handle_event: unsupported event, code %d\n",
399: type));
400: }
401:
402: return (ret);
403: }
404:
405: void
406: apm_thread_create(void *v)
407: {
408: struct pxa2x0_apm_softc *sc = v;
409:
410: if (kthread_create(apm_thread, sc, &sc->sc_thread,
411: "%s", sc->sc_dev.dv_xname)) {
412: /* apm_disconnect(sc); */
413: printf("%s: failed to create kernel thread, disabled",
414: sc->sc_dev.dv_xname);
415: }
416: }
417:
418: void
419: apm_thread(void *v)
420: {
421: struct pxa2x0_apm_softc *sc = v;
422: u_int type;
423:
424: for (;;) {
425: APM_LOCK(sc);
426:
427: while (1) {
428: if (apm_get_event(sc, &type) != 0)
429: break;
430: if (apm_handle_event(sc, type) != 0)
431: break;
432: }
433: if (apm_suspends || apm_userstandbys /* || apm_battlow*/) {
434: apm_suspend(sc);
435: apm_resume(sc);
436: }
437: apm_battlow = apm_suspends = apm_userstandbys = 0;
438:
439: APM_UNLOCK(sc);
440: tsleep(&lbolt, PWAIT, "apmev", 0);
441: }
442: }
443:
444: int
445: apmopen(dev_t dev, int flag, int mode, struct proc *p)
446: {
447: struct pxa2x0_apm_softc *sc;
448: int error = 0;
449:
450: /* apm0 only */
451: if (!apm_cd.cd_ndevs || APMUNIT(dev) != 0 ||
452: !(sc = apm_cd.cd_devs[APMUNIT(dev)]))
453: return (ENXIO);
454:
455: DPRINTF(("apmopen: dev %d pid %d flag %x mode %x\n",
456: APMDEV(dev), p->p_pid, flag, mode));
457:
458: switch (APMDEV(dev)) {
459: case APMDEV_CTL:
460: if (!(flag & FWRITE)) {
461: error = EINVAL;
462: break;
463: }
464: if (sc->sc_flags & SCFLAG_OWRITE) {
465: error = EBUSY;
466: break;
467: }
468: sc->sc_flags |= SCFLAG_OWRITE;
469: break;
470: case APMDEV_NORMAL:
471: if (!(flag & FREAD) || (flag & FWRITE)) {
472: error = EINVAL;
473: break;
474: }
475: sc->sc_flags |= SCFLAG_OREAD;
476: break;
477: default:
478: error = ENXIO;
479: break;
480: }
481: return (error);
482: }
483:
484: int
485: apmclose(dev_t dev, int flag, int mode, struct proc *p)
486: {
487: struct pxa2x0_apm_softc *sc;
488:
489: /* apm0 only */
490: if (!apm_cd.cd_ndevs || APMUNIT(dev) != 0 ||
491: !(sc = apm_cd.cd_devs[APMUNIT(dev)]))
492: return (ENXIO);
493:
494: DPRINTF(("apmclose: pid %d flag %x mode %x\n", p->p_pid, flag, mode));
495:
496: switch (APMDEV(dev)) {
497: case APMDEV_CTL:
498: sc->sc_flags &= ~SCFLAG_OWRITE;
499: break;
500: case APMDEV_NORMAL:
501: sc->sc_flags &= ~SCFLAG_OREAD;
502: break;
503: }
504: return (0);
505: }
506:
507: int
508: apmioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
509: {
510: struct pxa2x0_apm_softc *sc;
511: struct apm_power_info *power;
512: int error = 0;
513:
514: /* apm0 only */
515: if (!apm_cd.cd_ndevs || APMUNIT(dev) != 0 ||
516: !(sc = apm_cd.cd_devs[APMUNIT(dev)]))
517: return (ENXIO);
518:
519: switch (cmd) {
520: /* some ioctl names from linux */
521: case APM_IOC_STANDBY:
522: if ((flag & FWRITE) == 0)
523: error = EBADF;
524: else
525: apm_userstandbys++;
526: break;
527: case APM_IOC_SUSPEND:
528: if ((flag & FWRITE) == 0)
529: error = EBADF;
530: else
531: apm_suspends++; /* XXX */
532: break;
533: case APM_IOC_PRN_CTL:
534: if ((flag & FWRITE) == 0)
535: error = EBADF;
536: else {
537: int flag = *(int *)data;
538: DPRINTF(( "APM_IOC_PRN_CTL: %d\n", flag ));
539: switch (flag) {
540: case APM_PRINT_ON: /* enable printing */
541: sc->sc_flags &= ~SCFLAG_PRINT;
542: break;
543: case APM_PRINT_OFF: /* disable printing */
544: sc->sc_flags &= ~SCFLAG_PRINT;
545: sc->sc_flags |= SCFLAG_NOPRINT;
546: break;
547: case APM_PRINT_PCT: /* disable some printing */
548: sc->sc_flags &= ~SCFLAG_PRINT;
549: sc->sc_flags |= SCFLAG_PCTPRINT;
550: break;
551: default:
552: error = EINVAL;
553: break;
554: }
555: }
556: break;
557: case APM_IOC_DEV_CTL:
558: if ((flag & FWRITE) == 0)
559: error = EBADF;
560: break;
561: case APM_IOC_GETPOWER:
562: power = (struct apm_power_info *)data;
563: apm_power_info(sc, power);
564: break;
565:
566: default:
567: error = ENOTTY;
568: }
569:
570: return (error);
571: }
572:
573: int
574: apm_record_event(struct pxa2x0_apm_softc *sc, u_int type)
575: {
576: static int apm_evindex;
577:
578: /* skip if no user waiting */
579: if ((sc->sc_flags & SCFLAG_OPEN) == 0)
580: return (1);
581:
582: apm_evindex++;
583: KNOTE(&sc->sc_note, APM_EVENT_COMPOSE(type, apm_evindex));
584:
585: return (0);
586: }
587:
588: void
589: filt_apmrdetach(struct knote *kn)
590: {
591: struct pxa2x0_apm_softc *sc =
592: (struct pxa2x0_apm_softc *)kn->kn_hook;
593:
594: SLIST_REMOVE(&sc->sc_note, kn, knote, kn_selnext);
595: }
596:
597: int
598: filt_apmread(struct knote *kn, long hint)
599: {
600: /* XXX weird kqueue_scan() semantics */
601: if (hint && !kn->kn_data)
602: kn->kn_data = (int)hint;
603:
604: return (1);
605: }
606:
607: int
608: apmkqfilter(dev_t dev, struct knote *kn)
609: {
610: struct pxa2x0_apm_softc *sc;
611:
612: /* apm0 only */
613: if (!apm_cd.cd_ndevs || APMUNIT(dev) != 0 ||
614: !(sc = apm_cd.cd_devs[APMUNIT(dev)]))
615: return (ENXIO);
616:
617: switch (kn->kn_filter) {
618: case EVFILT_READ:
619: kn->kn_fop = &apmread_filtops;
620: break;
621: default:
622: return (1);
623: }
624:
625: kn->kn_hook = (caddr_t)sc;
626: SLIST_INSERT_HEAD(&sc->sc_note, kn, kn_selnext);
627:
628: return (0);
629: }
630:
631: void
632: pxa2x0_apm_attach_sub(struct pxa2x0_apm_softc *sc)
633: {
634:
635: sc->sc_iot = &pxa2x0_bs_tag;
636:
637: if (bus_space_map(sc->sc_iot, PXA2X0_POWMAN_BASE,
638: PXA2X0_POWMAN_SIZE, 0, &sc->sc_pm_ioh)) {
639: printf("pxa2x0_apm_attach_sub: failed to map POWMAN\n");
640: return;
641: }
642:
643: lockinit(&sc->sc_lock, PWAIT, "apmlk", 0, 0);
644:
645: kthread_create_deferred(apm_thread_create, sc);
646:
647: printf("\n");
648:
649: if (bus_space_map(sc->sc_iot, PXA2X0_CLKMAN_BASE, PXA2X0_CLKMAN_SIZE,
650: 0, &pxa2x0_clkman_ioh)) {
651: printf("%s: failed to map CLKMAN\n", sc->sc_dev.dv_xname);
652: return;
653: }
654:
655: if (bus_space_map(sc->sc_iot, PXA2X0_MEMCTL_BASE, PXA2X0_MEMCTL_SIZE,
656: 0, &pxa2x0_memctl_ioh)) {
657: printf("%s: failed to map MEMCTL\n", sc->sc_dev.dv_xname);
658: return;
659: }
660: sc->sc_memctl_ioh = pxa2x0_memctl_ioh;
661:
662: if (bus_space_map(sc->sc_iot, PXA2X0_GPIO_BASE, PXA2X0_GPIO_SIZE,
663: 0, &pxa2x0_gpio_ioh)) {
664: printf("%s: can't map GPIO\n", sc->sc_dev.dv_xname);
665: return;
666: }
667:
668: /* Clear all reset status flags. */
669: bus_space_write_4(sc->sc_iot, sc->sc_pm_ioh, POWMAN_RCSR,
670: RCSR_GPR | RCSR_SMR | RCSR_WDR | RCSR_HWR);
671: }
672:
673: void
674: pxa2x0_wakeup_config(u_int wsrc, int enable)
675: {
676: struct pxa2x0_apm_softc *sc;
677: u_int32_t prer;
678: u_int32_t pfer;
679: u_int32_t pkwr;
680:
681: if (apm_cd.cd_ndevs < 1 || apm_cd.cd_devs[0] == NULL)
682: return;
683: sc = apm_cd.cd_devs[0];
684:
685: prer = pfer = pkwr = 0;
686:
687: if ((wsrc & PXA2X0_WAKEUP_POWERON) != 0) {
688: prer |= (1<<0);
689: pfer |= (1<<0);
690: pkwr |= (1<<12); /* XXX */
691: }
692:
693: if ((wsrc & PXA2X0_WAKEUP_GPIORST) != 0)
694: pfer |= (1<<1);
695: if ((wsrc & PXA2X0_WAKEUP_SD) != 0)
696: prer |= (1<<9);
697: if ((wsrc & PXA2X0_WAKEUP_RC) != 0)
698: prer |= (1<<13);
699: if ((wsrc & PXA2X0_WAKEUP_SYNC) != 0)
700: pkwr |= (1<<1);
701: if ((wsrc & PXA2X0_WAKEUP_KEYNS0) != 0)
702: prer |= (1<<12);
703: if ((wsrc & PXA2X0_WAKEUP_KEYNS1) != 0)
704: pkwr |= (1<<2);
705: if ((wsrc & PXA2X0_WAKEUP_KEYNS2) != 0)
706: pkwr |= (1<<9);
707: if ((wsrc & PXA2X0_WAKEUP_KEYNS3) != 0)
708: pkwr |= (1<<3);
709: if ((wsrc & PXA2X0_WAKEUP_KEYNS4) != 0)
710: pkwr |= (1<<4);
711: if ((wsrc & PXA2X0_WAKEUP_KEYNS5) != 0)
712: pkwr |= (1<<6);
713: if ((wsrc & PXA2X0_WAKEUP_KEYNS6) != 0)
714: pkwr |= (1<<7);
715: if ((wsrc & PXA2X0_WAKEUP_CF0) != 0)
716: pkwr |= (1<<11);
717: if ((wsrc & PXA2X0_WAKEUP_CF1) != 0)
718: pkwr |= (1<<10);
719: if ((wsrc & PXA2X0_WAKEUP_USBD) != 0)
720: prer |= (1<<24);
721:
722: if ((wsrc & PXA2X0_WAKEUP_LOCKSW) != 0) {
723: prer |= (1<<15);
724: pfer |= (1<<15);
725: }
726:
727: if ((wsrc & PXA2X0_WAKEUP_JACKIN) != 0) {
728: prer |= (1<<23);
729: pfer |= (1<<23);
730: }
731:
732: if ((wsrc & PXA2X0_WAKEUP_CHRGFULL) != 0)
733: pkwr |= (1<<18);
734: if ((wsrc & PXA2X0_WAKEUP_RTC) != 0)
735: prer |= (1<<31);
736:
737: if (enable) {
738: sc->sc_wakeon |= wsrc;
739: prer |= bus_space_read_4(sc->sc_iot, sc->sc_pm_ioh,
740: POWMAN_PRER);
741: pfer |= bus_space_read_4(sc->sc_iot, sc->sc_pm_ioh,
742: POWMAN_PFER);
743: pkwr |= bus_space_read_4(sc->sc_iot, sc->sc_pm_ioh,
744: POWMAN_PKWR);
745: } else {
746: sc->sc_wakeon &= ~wsrc;
747: prer = bus_space_read_4(sc->sc_iot, sc->sc_pm_ioh,
748: POWMAN_PRER) & ~prer;
749: pfer = bus_space_read_4(sc->sc_iot, sc->sc_pm_ioh,
750: POWMAN_PFER) & ~pfer;
751: pkwr = bus_space_read_4(sc->sc_iot, sc->sc_pm_ioh,
752: POWMAN_PKWR) & ~pkwr;
753: }
754:
755: bus_space_write_4(sc->sc_iot, sc->sc_pm_ioh, POWMAN_PKWR, pkwr);
756: bus_space_write_4(sc->sc_iot, sc->sc_pm_ioh, POWMAN_PRER, prer);
757: bus_space_write_4(sc->sc_iot, sc->sc_pm_ioh, POWMAN_PFER, pfer);
758: bus_space_write_4(sc->sc_iot, sc->sc_pm_ioh, POWMAN_PWER,
759: prer | pfer);
760: }
761:
762: u_int
763: pxa2x0_wakeup_status(void)
764: {
765: struct pxa2x0_apm_softc *sc;
766: u_int32_t rv;
767: u_int wsrc;
768:
769: if (apm_cd.cd_ndevs < 1 || apm_cd.cd_devs[0] == NULL)
770: return (0);
771:
772: sc = apm_cd.cd_devs[0];
773: wsrc = 0;
774:
775: rv = bus_space_read_4(sc->sc_iot, sc->sc_pm_ioh, POWMAN_PEDR);
776: if ((rv & (1<<0)) != 0)
777: wsrc |= PXA2X0_WAKEUP_POWERON;
778: if ((rv & (1<<1)) != 0)
779: wsrc |= PXA2X0_WAKEUP_GPIORST;
780: if ((rv & (1<<9)) != 0)
781: wsrc |= PXA2X0_WAKEUP_SD;
782: if ((rv & (1<<12)) != 0)
783: wsrc |= PXA2X0_WAKEUP_KEYNS0;
784: if ((rv & (1<<13)) != 0)
785: wsrc |= PXA2X0_WAKEUP_RC;
786: if ((rv & (1<<15)) != 0)
787: wsrc |= PXA2X0_WAKEUP_LOCKSW;
788: if ((rv & (1<<23)) != 0)
789: wsrc |= PXA2X0_WAKEUP_JACKIN;
790: if ((rv & (1<<24)) != 0)
791: wsrc |= PXA2X0_WAKEUP_USBD;
792: if ((rv & (1<<31)) != 0)
793: wsrc |= PXA2X0_WAKEUP_RTC;
794:
795: rv = bus_space_read_4(sc->sc_iot, sc->sc_pm_ioh, POWMAN_PKSR);
796: if ((rv & (1<<1)) != 0)
797: wsrc |= PXA2X0_WAKEUP_SYNC;
798: if ((rv & (1<<2)) != 0)
799: wsrc |= PXA2X0_WAKEUP_KEYNS1;
800: if ((rv & (1<<9)) != 0)
801: wsrc |= PXA2X0_WAKEUP_KEYNS2;
802: if ((rv & (1<<3)) != 0)
803: wsrc |= PXA2X0_WAKEUP_KEYNS3;
804: if ((rv & (1<<4)) != 0)
805: wsrc |= PXA2X0_WAKEUP_KEYNS4;
806: if ((rv & (1<<6)) != 0)
807: wsrc |= PXA2X0_WAKEUP_KEYNS5;
808: if ((rv & (1<<7)) != 0)
809: wsrc |= PXA2X0_WAKEUP_KEYNS6;
810: if ((rv & (1<<10)) != 0)
811: wsrc |= PXA2X0_WAKEUP_CF1;
812: if ((rv & (1<<11)) != 0)
813: wsrc |= PXA2X0_WAKEUP_CF0;
814: if ((rv & (1<<12)) != 0)
815: wsrc |= PXA2X0_WAKEUP_POWERON;
816: if ((rv & (1<<18)) != 0)
817: wsrc |= PXA2X0_WAKEUP_CHRGFULL;
818:
819: return (wsrc);
820: }
821:
822: struct pxa2x0_sleep_data {
823: /* OS timer registers */
824: u_int32_t sd_osmr0, sd_osmr1, sd_osmr2, sd_osmr3;
825: u_int32_t sd_oscr0;
826: u_int32_t sd_osmr4, sd_osmr5;
827: u_int32_t sd_oscr4;
828: u_int32_t sd_omcr4, sd_omcr5;
829: u_int32_t sd_oier;
830: /* GPIO registers */
831: u_int32_t sd_gpdr0, sd_gpdr1, sd_gpdr2, sd_gpdr3;
832: u_int32_t sd_grer0, sd_grer1, sd_grer2, sd_grer3;
833: u_int32_t sd_gfer0, sd_gfer1, sd_gfer2, sd_gfer3;
834: u_int32_t sd_gafr0_l, sd_gafr1_l, sd_gafr2_l, sd_gafr3_l;
835: u_int32_t sd_gafr0_u, sd_gafr1_u, sd_gafr2_u, sd_gafr3_u;
836: u_int32_t sd_gplr0, sd_gplr1, sd_gplr2, sd_gplr3;
837: /* Interrupt controller registers */
838: u_int32_t sd_iclr;
839: u_int32_t sd_icmr;
840: u_int32_t sd_iccr;
841: /* Memory controller registers */
842: u_int32_t sd_mecr;
843: u_int32_t sd_mcmem0, sd_mcmem1;
844: u_int32_t sd_mcatt0, sd_mcatt1;
845: u_int32_t sd_mcio0, sd_mcio1;
846: /* Clocks manager registers */
847: u_int32_t sd_cken;
848: };
849:
850: void
851: pxa2x0_apm_sleep(struct pxa2x0_apm_softc *sc)
852: {
853: struct pxa2x0_sleep_data sd;
854: bus_space_handle_t ost_ioh;
855: int save;
856: u_int32_t rv;
857:
858: ost_ioh = (bus_space_handle_t)0;
859: if (bus_space_map(sc->sc_iot, PXA2X0_OST_BASE, PXA2X0_OST_SIZE, 0,
860: &ost_ioh)) {
861: printf("pxa2x0_apm_sleep: can't map OST\n");
862: goto out;
863: }
864:
865: save = disable_interrupts(I32_bit|F32_bit);
866:
867: sd.sd_oscr0 = bus_space_read_4(sc->sc_iot, ost_ioh, OST_OSCR0);
868: sd.sd_oscr4 = bus_space_read_4(sc->sc_iot, ost_ioh, OST_OSCR4);
869: sd.sd_omcr4 = bus_space_read_4(sc->sc_iot, ost_ioh, OST_OMCR4);
870: sd.sd_omcr5 = bus_space_read_4(sc->sc_iot, ost_ioh, OST_OMCR5);
871: sd.sd_osmr0 = bus_space_read_4(sc->sc_iot, ost_ioh, OST_OSMR0);
872: sd.sd_osmr1 = bus_space_read_4(sc->sc_iot, ost_ioh, OST_OSMR1);
873: sd.sd_osmr2 = bus_space_read_4(sc->sc_iot, ost_ioh, OST_OSMR2);
874: sd.sd_osmr3 = bus_space_read_4(sc->sc_iot, ost_ioh, OST_OSMR3);
875: sd.sd_osmr4 = bus_space_read_4(sc->sc_iot, ost_ioh, OST_OSMR4);
876: sd.sd_osmr5 = bus_space_read_4(sc->sc_iot, ost_ioh, OST_OSMR5);
877: sd.sd_oier = bus_space_read_4(sc->sc_iot, ost_ioh, OST_OIER);
878:
879: /* Bring the PXA27x into 416MHz turbo mode. */
880: if ((cputype & ~CPU_ID_XSCALE_COREREV_MASK) == CPU_ID_PXA27X &&
881: bus_space_read_4(sc->sc_iot, pxa2x0_clkman_ioh, CLKMAN_CCCR) !=
882: (CCCR_A | CCCR_TURBO_X2 | CCCR_RUN_X16)) {
883: #if 0
884: pxa27x_cpu_speed_high();
885: #else
886: #define CLKCFG_T (1<<0) /* turbo */
887: #define CLKCFG_F (1<<1) /* frequency change */
888: #define CLKCFG_B (1<<3) /* fast-bus */
889: pxa27x_frequency_change(CCCR_A | CCCR_TURBO_X2 |
890: CCCR_RUN_X16, CLKCFG_B | CLKCFG_F | CLKCFG_T,
891: &pxa2x0_memcfg);
892: #endif
893: delay(500000); /* XXX */
894: }
895:
896: suspend_again:
897: /* Clear wake-up status. */
898: bus_space_write_4(sc->sc_iot, sc->sc_pm_ioh, POWMAN_PEDR,
899: 0xffffffff);
900: bus_space_write_4(sc->sc_iot, sc->sc_pm_ioh, POWMAN_PKSR,
901: 0xffffffff);
902:
903: /* XXX control battery charging in sleep mode. */
904:
905: /* XXX schedule RTC alarm to check the battery, or schedule
906: XXX wake-up shortly before an already programmed alarm? */
907:
908: pxa27x_run_mode();
909: #define MDREFR_LOW (MDREFR_C3000 | 0x00b)
910: pxa27x_fastbus_run_mode(0, MDREFR_LOW);
911: delay(1);
912: #if 1
913: pxa27x_cpu_speed_91();
914: #else
915: pxa27x_frequency_change(CCCR_TURBO_X1 | CCCR_RUN_X7, CLKCFG_F,
916: &pxa2x0_memcfg);
917: #endif
918: pxa2x0_pi2c_setvoltage(sc->sc_iot, sc->sc_pm_ioh, PI2C_VOLTAGE_LOW);
919:
920: sd.sd_gpdr0 = bus_space_read_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GPDR0);
921: sd.sd_gpdr1 = bus_space_read_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GPDR1);
922: sd.sd_gpdr2 = bus_space_read_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GPDR2);
923: sd.sd_gpdr3 = bus_space_read_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GPDR3);
924:
925: sd.sd_grer0 = bus_space_read_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GRER0);
926: sd.sd_grer1 = bus_space_read_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GRER1);
927: sd.sd_grer2 = bus_space_read_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GRER2);
928: sd.sd_grer3 = bus_space_read_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GRER3);
929:
930: sd.sd_gfer0 = bus_space_read_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GFER0);
931: sd.sd_gfer1 = bus_space_read_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GFER1);
932: sd.sd_gfer2 = bus_space_read_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GFER2);
933: sd.sd_gfer3 = bus_space_read_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GFER3);
934:
935: sd.sd_gafr0_l = bus_space_read_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GAFR0_L);
936: sd.sd_gafr1_l = bus_space_read_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GAFR1_L);
937: sd.sd_gafr2_l = bus_space_read_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GAFR2_L);
938: sd.sd_gafr3_l = bus_space_read_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GAFR3_L);
939:
940: sd.sd_gafr0_u = bus_space_read_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GAFR0_U);
941: sd.sd_gafr1_u = bus_space_read_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GAFR1_U);
942: sd.sd_gafr2_u = bus_space_read_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GAFR2_U);
943: sd.sd_gafr3_u = bus_space_read_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GAFR3_U);
944:
945: sd.sd_gplr0 = bus_space_read_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GPLR0);
946: sd.sd_gplr1 = bus_space_read_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GPLR1);
947: sd.sd_gplr2 = bus_space_read_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GPLR2);
948: sd.sd_gplr3 = bus_space_read_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GPLR3);
949:
950: sd.sd_iclr = read_icu(INTCTL_ICLR);
951: sd.sd_icmr = read_icu(INTCTL_ICMR);
952: sd.sd_iccr = read_icu(INTCTL_ICCR);
953: write_icu(INTCTL_ICMR, 0);
954:
955: sd.sd_mecr = bus_space_read_4(sc->sc_iot, pxa2x0_memctl_ioh,
956: MEMCTL_MECR);
957: sd.sd_mcmem0 = bus_space_read_4(sc->sc_iot, pxa2x0_memctl_ioh,
958: MEMCTL_MCMEM(0));
959: sd.sd_mcmem1 = bus_space_read_4(sc->sc_iot, pxa2x0_memctl_ioh,
960: MEMCTL_MCMEM(1));
961: sd.sd_mcatt0 = bus_space_read_4(sc->sc_iot, pxa2x0_memctl_ioh,
962: MEMCTL_MCATT(0));
963: sd.sd_mcatt1 = bus_space_read_4(sc->sc_iot, pxa2x0_memctl_ioh,
964: MEMCTL_MCATT(1));
965: sd.sd_mcio0 = bus_space_read_4(sc->sc_iot, pxa2x0_memctl_ioh,
966: MEMCTL_MCIO(0));
967: sd.sd_mcio1 = bus_space_read_4(sc->sc_iot, pxa2x0_memctl_ioh,
968: MEMCTL_MCIO(1));
969:
970: sd.sd_cken = bus_space_read_4(sc->sc_iot, pxa2x0_clkman_ioh,
971: CLKMAN_CKEN);
972:
973: /*
974: * Stop clocks to all units except to the memory controller, and
975: * to the keypad controller if it is enabled as a wake-up source.
976: */
977: rv = CKEN_MEM;
978: if ((sc->sc_wakeon & PXA2X0_WAKEUP_KEYNS_ALL) != 0)
979: rv |= CKEN_KEY;
980: bus_space_write_4(sc->sc_iot, pxa2x0_clkman_ioh, CLKMAN_CKEN, rv);
981:
982: /* Disable nRESET_OUT. */
983: rv = bus_space_read_4(sc->sc_iot, sc->sc_pm_ioh, POWMAN_PSLR);
984: #define PSLR_SL_ROD (1<<20)
985: bus_space_write_4(sc->sc_iot, sc->sc_pm_ioh, POWMAN_PSLR,
986: rv | PSLR_SL_ROD);
987:
988: /* Clear all reset status flags. */
989: bus_space_write_4(sc->sc_iot, sc->sc_pm_ioh, POWMAN_RCSR,
990: RCSR_GPR | RCSR_SMR | RCSR_WDR | RCSR_HWR);
991:
992: /* Stop 3/13MHz oscillator; do not float PCMCIA and chip-selects. */
993: rv = PCFR_OPDE;
994: if ((cputype & ~CPU_ID_XSCALE_COREREV_MASK) == CPU_ID_PXA27X)
995: /* Enable nRESET_GPIO as a GPIO reset input. */
996: rv |= PCFR_GPR_EN;
997: bus_space_write_4(sc->sc_iot, sc->sc_pm_ioh, POWMAN_PCFR, rv);
998:
999: /* XXX C3000 */
1000: #define GPIO_G0_STROBE_BIT 0x0f800000
1001: #define GPIO_G1_STROBE_BIT 0x00100000
1002: #define GPIO_G2_STROBE_BIT 0x01000000
1003: #define GPIO_G3_STROBE_BIT 0x00041880
1004: #define GPIO_KEY_STROBE0 88
1005: bus_space_write_4(sc->sc_iot, sc->sc_pm_ioh, POWMAN_PGSR0,
1006: 0x00144018);
1007: bus_space_write_4(sc->sc_iot, sc->sc_pm_ioh, POWMAN_PGSR1,
1008: 0x00ef0000);
1009: bus_space_write_4(sc->sc_iot, sc->sc_pm_ioh, POWMAN_PGSR2,
1010: 0x0121c000);
1011: bus_space_write_4(sc->sc_iot, sc->sc_pm_ioh, POWMAN_PGSR3,
1012: 0x00600000);
1013: bus_space_write_4(sc->sc_iot, sc->sc_pm_ioh, POWMAN_PGSR0,
1014: 0x00144018 & ~GPIO_G0_STROBE_BIT);
1015: bus_space_write_4(sc->sc_iot, sc->sc_pm_ioh, POWMAN_PGSR1,
1016: 0x00ef0000 & ~GPIO_G1_STROBE_BIT);
1017: bus_space_write_4(sc->sc_iot, sc->sc_pm_ioh, POWMAN_PGSR2,
1018: 0x0121c000 & ~GPIO_G2_STROBE_BIT);
1019: bus_space_write_4(sc->sc_iot, sc->sc_pm_ioh, POWMAN_PGSR3,
1020: 0x00600000 & ~GPIO_G3_STROBE_BIT);
1021: bus_space_write_4(sc->sc_iot, sc->sc_pm_ioh, POWMAN_PGSR2,
1022: (0x0121c000 & ~GPIO_G2_STROBE_BIT) |
1023: GPIO_BIT(GPIO_KEY_STROBE0));
1024:
1025: /* C3000 */
1026: #define GPIO_EXT_BUS_READY 18
1027: pxa2x0_gpio_set_function(GPIO_EXT_BUS_READY, GPIO_SET | GPIO_OUT);
1028: bus_space_write_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GPDR0, 0xd01c4418);
1029: bus_space_write_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GPDR1, 0xfcefbd21);
1030: bus_space_write_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GPDR2, 0x13a5ffff);
1031: bus_space_write_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GPDR3, 0x01e3e10c);
1032:
1033: bus_space_write_4(sc->sc_iot, sc->sc_pm_ioh, POWMAN_PSPR,
1034: (u_int32_t)&pxa2x0_cpu_resume - 0xc0200000 + 0xa0200000);
1035:
1036: pxa2x0_cpu_suspend();
1037:
1038: bus_space_write_4(sc->sc_iot, sc->sc_pm_ioh, POWMAN_PSPR, 0);
1039:
1040: pxa2x0_clkman_config(CKEN_SSP|CKEN_PWM0|CKEN_PWM1, 1);
1041: pxa2x0_clkman_config(CKEN_KEY, 0);
1042:
1043: #if 1
1044: /* Clear all GPIO interrupt sources. */
1045: bus_space_write_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GEDR0, 0xffffffff);
1046: bus_space_write_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GEDR1, 0xffffffff);
1047: bus_space_write_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GEDR2, 0xffffffff);
1048: #endif
1049:
1050: bus_space_write_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GPDR0, sd.sd_gpdr0);
1051: bus_space_write_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GPDR1, sd.sd_gpdr1);
1052: bus_space_write_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GPDR2, sd.sd_gpdr2);
1053: bus_space_write_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GRER0, sd.sd_grer0);
1054: bus_space_write_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GRER1, sd.sd_grer1);
1055: bus_space_write_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GRER2, sd.sd_grer2);
1056: bus_space_write_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GFER0, sd.sd_gfer0);
1057: bus_space_write_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GFER1, sd.sd_gfer1);
1058: bus_space_write_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GFER2, sd.sd_gfer2);
1059: bus_space_write_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GAFR0_L, sd.sd_gafr0_l);
1060: bus_space_write_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GAFR1_L, sd.sd_gafr1_l);
1061: bus_space_write_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GAFR2_L, sd.sd_gafr2_l);
1062: bus_space_write_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GAFR0_U, sd.sd_gafr0_u);
1063: bus_space_write_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GAFR1_U, sd.sd_gafr1_u);
1064: bus_space_write_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GAFR2_U, sd.sd_gafr2_u);
1065: bus_space_write_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GPSR0, sd.sd_gplr0 &
1066: sd.sd_gpdr0);
1067: bus_space_write_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GPSR1, sd.sd_gplr1 &
1068: sd.sd_gpdr1);
1069: bus_space_write_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GPSR2, sd.sd_gplr2 &
1070: sd.sd_gpdr2);
1071: bus_space_write_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GPCR0, ~sd.sd_gplr0 &
1072: sd.sd_gpdr0);
1073: bus_space_write_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GPCR1, ~sd.sd_gplr1 &
1074: sd.sd_gpdr1);
1075: bus_space_write_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GPCR2, ~sd.sd_gplr2 &
1076: sd.sd_gpdr2);
1077:
1078: /* PXA27x */
1079: #if 0
1080: bus_space_write_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GEDR3, 0xffffffff);
1081: #endif
1082: bus_space_write_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GPDR3, sd.sd_gpdr3);
1083: bus_space_write_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GRER3, sd.sd_grer3);
1084: bus_space_write_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GFER3, sd.sd_gfer3);
1085: bus_space_write_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GAFR3_L, sd.sd_gafr3_l);
1086: bus_space_write_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GAFR3_U, sd.sd_gafr3_u);
1087: bus_space_write_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GPSR3, sd.sd_gplr3 &
1088: sd.sd_gpdr3);
1089: bus_space_write_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GPCR3, ~sd.sd_gplr3 &
1090: sd.sd_gpdr3);
1091:
1092: bus_space_write_4(sc->sc_iot, pxa2x0_memctl_ioh, MEMCTL_MECR,
1093: sd.sd_mecr);
1094: bus_space_write_4(sc->sc_iot, pxa2x0_memctl_ioh, MEMCTL_MCMEM(0),
1095: sd.sd_mcmem0);
1096: bus_space_write_4(sc->sc_iot, pxa2x0_memctl_ioh, MEMCTL_MCMEM(1),
1097: sd.sd_mcmem1);
1098: bus_space_write_4(sc->sc_iot, pxa2x0_memctl_ioh, MEMCTL_MCATT(0),
1099: sd.sd_mcatt0);
1100: bus_space_write_4(sc->sc_iot, pxa2x0_memctl_ioh, MEMCTL_MCATT(1),
1101: sd.sd_mcatt1);
1102: bus_space_write_4(sc->sc_iot, pxa2x0_memctl_ioh, MEMCTL_MCIO(0),
1103: sd.sd_mcio0);
1104: bus_space_write_4(sc->sc_iot, pxa2x0_memctl_ioh, MEMCTL_MCIO(1),
1105: sd.sd_mcio1);
1106:
1107: bus_space_write_4(sc->sc_iot, pxa2x0_clkman_ioh, CLKMAN_CKEN,
1108: sd.sd_cken);
1109:
1110: write_icu(INTCTL_ICLR, sd.sd_iclr);
1111: write_icu(INTCTL_ICCR, sd.sd_iccr);
1112: write_icu(INTCTL_ICMR, sd.sd_icmr);
1113:
1114: if ((read_icu(INTCTL_ICIP) & 0x1) != 0)
1115: bus_space_write_4(sc->sc_iot, sc->sc_pm_ioh, POWMAN_PEDR, 0x1);
1116:
1117: bus_space_write_4(sc->sc_iot, ost_ioh, OST_OSMR0, sd.sd_osmr0);
1118: bus_space_write_4(sc->sc_iot, ost_ioh, OST_OSMR1, sd.sd_osmr1);
1119: bus_space_write_4(sc->sc_iot, ost_ioh, OST_OSMR2, sd.sd_osmr2);
1120: bus_space_write_4(sc->sc_iot, ost_ioh, OST_OSMR3, sd.sd_osmr3);
1121: bus_space_write_4(sc->sc_iot, ost_ioh, OST_OSMR4, sd.sd_osmr4);
1122: bus_space_write_4(sc->sc_iot, ost_ioh, OST_OSMR5, sd.sd_osmr5);
1123: bus_space_write_4(sc->sc_iot, ost_ioh, OST_OMCR4, sd.sd_omcr4);
1124: bus_space_write_4(sc->sc_iot, ost_ioh, OST_OMCR5, sd.sd_omcr5);
1125: bus_space_write_4(sc->sc_iot, ost_ioh, OST_OSCR0, sd.sd_oscr0);
1126: bus_space_write_4(sc->sc_iot, ost_ioh, OST_OSCR4, sd.sd_oscr4);
1127: bus_space_write_4(sc->sc_iot, ost_ioh, OST_OIER, sd.sd_oier);
1128:
1129: pxa2x0_pi2c_setvoltage(sc->sc_iot, sc->sc_pm_ioh, PI2C_VOLTAGE_HIGH);
1130:
1131: /* Change to 208MHz run mode with fast-bus still disabled. */
1132: pxa27x_frequency_change(CCCR_A | CCCR_TURBO_X2 | CCCR_RUN_X16,
1133: CLKCFG_F, &pxa2x0_memcfg);
1134: delay(1); /* XXX is the delay long enough, and necessary at all? */
1135: pxa27x_fastbus_run_mode(1, pxa2x0_memcfg.mdrefr_high);
1136:
1137: /* Change to 416MHz turbo mode with fast-bus enabled. */
1138: pxa27x_frequency_change(CCCR_A | CCCR_TURBO_X2 | CCCR_RUN_X16,
1139: CLKCFG_B | CLKCFG_F | CLKCFG_T, &pxa2x0_memcfg);
1140:
1141: if (sc->sc_resume != NULL) {
1142: if (!sc->sc_resume(sc))
1143: goto suspend_again;
1144: }
1145:
1146: /*
1147: * Allow immediate entry into deep-sleep mode if power fails.
1148: * Resume from immediate deep-sleep is not implemented yet.
1149: */
1150: bus_space_write_4(sc->sc_iot, sc->sc_pm_ioh, POWMAN_PMCR, 0);
1151:
1152:
1153: restore_interrupts(save);
1154:
1155: pxa2x0_setperf(perflevel);
1156:
1157: out:
1158: if (ost_ioh != (bus_space_handle_t)0)
1159: bus_space_unmap(sc->sc_iot, ost_ioh, PXA2X0_OST_SIZE);
1160: }
1161:
1162: void
1163: pxa2x0_pi2c_open(bus_space_tag_t iot, bus_space_handle_t ioh)
1164: {
1165: u_int32_t rv;
1166:
1167: /* Enable the I2C unit, and disable automatic voltage change. */
1168: rv = bus_space_read_4(iot, ioh, POWMAN_PCFR);
1169: bus_space_write_4(iot, ioh, POWMAN_PCFR, rv | PCFR_PI2C_EN);
1170: rv = bus_space_read_4(iot, ioh, POWMAN_PCFR);
1171: bus_space_write_4(iot, ioh, POWMAN_PCFR, rv & ~PCFR_FVC);
1172: delay(1);
1173:
1174: /* Enable the clock to the power manager I2C unit. */
1175: pxa2x0_clkman_config(CKEN_PI2C, 1);
1176: delay(1);
1177: }
1178:
1179: void
1180: pxa2x0_pi2c_close(bus_space_tag_t iot, bus_space_handle_t ioh)
1181: {
1182: u_int32_t rv;
1183:
1184: bus_space_write_4(iot, ioh, POWMAN_PICR, PICR_UR);
1185: bus_space_write_4(iot, ioh, POWMAN_PISAR, 0);
1186: delay(1);
1187:
1188: /* Disable the clock to the power manager I2C unit. */
1189: pxa2x0_clkman_config(CKEN_PI2C, 0);
1190: delay(1);
1191:
1192: /* Disable the I2C unit, and disable automatic voltage change. */
1193: rv = bus_space_read_4(iot, ioh, POWMAN_PCFR);
1194: bus_space_write_4(iot, ioh, POWMAN_PCFR,
1195: rv & ~(PCFR_PI2C_EN | PCFR_FVC));
1196: delay(1);
1197: }
1198:
1199: int
1200: pxa2x0_pi2c_read(bus_space_tag_t iot, bus_space_handle_t ioh,
1201: u_char slave, u_char *valuep)
1202: {
1203: u_int32_t rv;
1204: int timeout;
1205: int tries = PI2C_RETRY_COUNT;
1206:
1207: retry:
1208:
1209: bus_space_write_4(iot, ioh, POWMAN_PICR, PICR_UR);
1210: bus_space_write_4(iot, ioh, POWMAN_PISAR, 0x00);
1211: delay(1);
1212: bus_space_write_4(iot, ioh, POWMAN_PICR, PICR_IUE | PICR_SCLE);
1213:
1214: /* Write slave device address. */
1215: bus_space_write_4(iot, ioh, POWMAN_PIDBR, (slave<<1) | 0x1);
1216: rv = bus_space_read_4(iot, ioh, POWMAN_PICR);
1217: bus_space_write_4(iot, ioh, POWMAN_PICR, rv | PICR_START);
1218: rv = bus_space_read_4(iot, ioh, POWMAN_PICR);
1219: bus_space_write_4(iot, ioh, POWMAN_PICR, rv & ~PICR_STOP);
1220: rv = bus_space_read_4(iot, ioh, POWMAN_PICR);
1221: bus_space_write_4(iot, ioh, POWMAN_PICR, rv | PICR_TB);
1222:
1223: timeout = 10000;
1224: while ((bus_space_read_4(iot, ioh, POWMAN_PISR) & PISR_ITE) == 0) {
1225: if (timeout-- == 0) {
1226: bus_space_write_4(iot, ioh, POWMAN_PISR, PISR_ITE);
1227: goto err;
1228: }
1229: delay(1);
1230: }
1231:
1232: bus_space_write_4(iot, ioh, POWMAN_PISR, PISR_ITE);
1233:
1234: rv = bus_space_read_4(iot, ioh, POWMAN_PICR);
1235: bus_space_write_4(iot, ioh, POWMAN_PICR, rv & ~PICR_START);
1236:
1237: /* Read data value. */
1238: rv = bus_space_read_4(iot, ioh, POWMAN_PICR);
1239: bus_space_write_4(iot, ioh, POWMAN_PICR, rv |
1240: (PICR_STOP | PICR_ACKNAK));
1241: rv = bus_space_read_4(iot, ioh, POWMAN_PICR);
1242: bus_space_write_4(iot, ioh, POWMAN_PICR, rv | PICR_TB);
1243:
1244: timeout = 10000;
1245: while ((bus_space_read_4(iot, ioh, POWMAN_PISR) & PISR_IRF) == 0) {
1246: if (timeout-- == 0) {
1247: bus_space_write_4(iot, ioh, POWMAN_PISR, PISR_IRF);
1248: goto err;
1249: }
1250: delay(1);
1251: }
1252:
1253: bus_space_write_4(iot, ioh, POWMAN_PISR, PISR_IRF);
1254: rv = bus_space_read_4(iot, ioh, POWMAN_PIDBR);
1255: *valuep = (u_char)rv;
1256: rv = bus_space_read_4(iot, ioh, POWMAN_PICR);
1257: bus_space_write_4(iot, ioh, POWMAN_PICR, rv &
1258: ~(PICR_STOP | PICR_ACKNAK));
1259:
1260: return (0);
1261: err:
1262: if (tries-- >= 0)
1263: goto retry;
1264:
1265: bus_space_write_4(iot, ioh, POWMAN_PICR, PICR_UR);
1266: bus_space_write_4(iot, ioh, POWMAN_PISAR, 0x00);
1267: bus_space_write_4(iot, ioh, POWMAN_PICR, PICR_IUE | PICR_SCLE);
1268:
1269: return (-EIO);
1270: }
1271:
1272: int
1273: pxa2x0_pi2c_write(bus_space_tag_t iot, bus_space_handle_t ioh,
1274: u_char slave, u_char value)
1275: {
1276: u_int32_t rv;
1277: int timeout;
1278: int tries = PI2C_RETRY_COUNT;
1279:
1280: retry:
1281:
1282: bus_space_write_4(iot, ioh, POWMAN_PICR, PICR_UR);
1283: bus_space_write_4(iot, ioh, POWMAN_PISAR, 0x00);
1284: delay(1);
1285: bus_space_write_4(iot, ioh, POWMAN_PICR, PICR_IUE | PICR_SCLE);
1286:
1287: /* Write slave device address. */
1288: bus_space_write_4(iot, ioh, POWMAN_PIDBR, (slave<<1));
1289: rv = bus_space_read_4(iot, ioh, POWMAN_PICR);
1290: bus_space_write_4(iot, ioh, POWMAN_PICR, rv | PICR_START);
1291: rv = bus_space_read_4(iot, ioh, POWMAN_PICR);
1292: bus_space_write_4(iot, ioh, POWMAN_PICR, rv & ~PICR_STOP);
1293: rv = bus_space_read_4(iot, ioh, POWMAN_PICR);
1294: bus_space_write_4(iot, ioh, POWMAN_PICR, rv | PICR_TB);
1295:
1296: timeout = 10000;
1297: while ((bus_space_read_4(iot, ioh, POWMAN_PISR) & PISR_ITE) == 0) {
1298: if (timeout-- == 0) {
1299: bus_space_write_4(iot, ioh, POWMAN_PISR, PISR_ITE);
1300: goto err;
1301: }
1302: delay(1);
1303: }
1304: if ((bus_space_read_4(iot, ioh, POWMAN_PISR) & PISR_ACKNAK) != 0)
1305: goto err;
1306: bus_space_write_4(iot, ioh, POWMAN_PISR, PISR_ITE);
1307:
1308: /* Write data. */
1309: rv = bus_space_read_4(iot, ioh, POWMAN_PICR);
1310: bus_space_write_4(iot, ioh, POWMAN_PICR, rv & ~PICR_START);
1311: rv = bus_space_read_4(iot, ioh, POWMAN_PICR);
1312: bus_space_write_4(iot, ioh, POWMAN_PICR, rv | PICR_STOP);
1313: bus_space_write_4(iot, ioh, POWMAN_PIDBR, value);
1314: rv = bus_space_read_4(iot, ioh, POWMAN_PICR);
1315: bus_space_write_4(iot, ioh, POWMAN_PICR, rv | PICR_TB);
1316:
1317: timeout = 10000;
1318: while ((bus_space_read_4(iot, ioh, POWMAN_PISR) & PISR_ITE) == 0) {
1319: if (timeout-- == 0) {
1320: #if 0
1321: bus_space_write_4(iot, ioh, POWMAN_PISR, PISR_ITE);
1322: #endif
1323: goto err;
1324: }
1325: delay(1);
1326: }
1327: if ((bus_space_read_4(iot, ioh, POWMAN_PISR) & PISR_ACKNAK) != 0)
1328: goto err;
1329: bus_space_write_4(iot, ioh, POWMAN_PISR, PISR_ITE);
1330:
1331: rv = bus_space_read_4(iot, ioh, POWMAN_PICR);
1332: bus_space_write_4(iot, ioh, POWMAN_PICR, rv & ~PICR_STOP);
1333:
1334: return (0);
1335: err:
1336: bus_space_write_4(iot, ioh, POWMAN_PISR, PISR_ITE);
1337: if (tries-- >= 0)
1338: goto retry;
1339:
1340: bus_space_write_4(iot, ioh, POWMAN_PICR, PICR_UR);
1341: bus_space_write_4(iot, ioh, POWMAN_PISAR, 0x00);
1342: bus_space_write_4(iot, ioh, POWMAN_PICR, PICR_IUE | PICR_SCLE);
1343:
1344: return (-EIO);
1345: }
1346:
1347: int
1348: pxa2x0_pi2c_getvoltage(bus_space_tag_t iot, bus_space_handle_t ioh,
1349: u_char *valuep)
1350: {
1351: int res;
1352:
1353: pxa2x0_pi2c_open(iot, ioh);
1354: res = pxa2x0_pi2c_read(iot, ioh, 0x0c, valuep);
1355: pxa2x0_pi2c_close(iot, ioh);
1356: return (res);
1357: }
1358:
1359: int
1360: pxa2x0_pi2c_setvoltage(bus_space_tag_t iot, bus_space_handle_t ioh,
1361: u_char value)
1362: {
1363: int res;
1364:
1365: pxa2x0_pi2c_open(iot, ioh);
1366: res = pxa2x0_pi2c_write(iot, ioh, 0x0c, value);
1367: pxa2x0_pi2c_close(iot, ioh);
1368: return (res);
1369: }
1370:
1371: #if 0
1372: void
1373: pxa2x0_pi2c_print(struct pxa2x0_apm_softc *sc)
1374: {
1375: u_char value = 0;
1376:
1377: (void)pxa2x0_pi2c_getvoltage(sc->sc_iot, sc->sc_pm_ioh, &value);
1378: printf("xscale core voltage: %s\n", value == PI2C_VOLTAGE_HIGH ?
1379: "high" : (value == PI2C_VOLTAGE_LOW ? "low" : "unknown"));
1380: }
1381: #endif
1382:
1383: struct {
1384: int maxspeed;
1385: int numspeeds;
1386: int hz [6];
1387: int rate [6]; /* could this be simplfied by not having 100% in table? */
1388: }
1389: speedtables[] = {
1390: { 91, 1, { 91 }, { 100 }},
1391: { 208, 2, { 91, 208}, {50, 100}},
1392: { 416, 3, { 91, 208, 416}, {25, 50, 100}},
1393: { 520, 4, { 91, 208, 416, 520}, {18, 40 ,80, 100}},
1394: { 624, 5, { 91, 208, 416, 520, 624}, {15, 34, 67, 82, 100}},
1395: { 0 }
1396: };
1397: int xscale_maxspeed = 416; /* XXX */
1398:
1399: int speed_to_freq(int speed);
1400:
1401: int
1402: speed_to_freq(int speed)
1403: {
1404: int i, j;
1405: int newspeed = 0;
1406: int numspeeds;
1407: for (i = 0; speedtables[i].maxspeed != 0; i++) {
1408: if (speedtables[i].maxspeed != xscale_maxspeed)
1409: continue;
1410:
1411: if (speed <= speedtables[i].rate[0]) {
1412: return speedtables[i].hz[0];
1413:
1414: }
1415: numspeeds = speedtables[i].numspeeds;
1416: if (speed == speedtables[i].rate[numspeeds-1]) {
1417: return speedtables[i].hz[numspeeds-1];
1418: }
1419: for (j = 1; j < numspeeds; j++) {
1420: if (speed < speedtables[i].rate[j]) {
1421: return speedtables[i].hz[j-1];
1422: }
1423: }
1424: }
1425: return newspeed;
1426: }
1427:
1428:
1429: void
1430: pxa2x0_setperf(int speed)
1431: {
1432: struct pxa2x0_apm_softc *sc;
1433: int s;
1434: int newfreq;
1435:
1436: sc = apm_cd.cd_devs[0];
1437:
1438: newfreq = speed_to_freq(speed);
1439:
1440: if (newfreq == 0) {
1441: printf("bogus new frequency 0 for rate %d maxclock %d\n",
1442: speed, xscale_maxspeed);
1443: }
1444:
1445: DPRINTF(("setperf speed %d newfreq %d, maxfreq %d\n",
1446: speed, newfreq, xscale_maxspeed));
1447:
1448: s = disable_interrupts(I32_bit|F32_bit);
1449:
1450: if (newfreq == 91) {
1451: if (freq > 91) {
1452: pxa27x_run_mode();
1453: pxa27x_fastbus_run_mode(0, MDREFR_LOW);
1454: pxa27x_cpu_speed_91();
1455: pxa2x0_pi2c_setvoltage(sc->sc_iot, sc->sc_pm_ioh,
1456: PI2C_VOLTAGE_LOW);
1457: freq = 91;
1458: }
1459: } else if (newfreq == 208) {
1460: if (freq < 208)
1461: pxa2x0_pi2c_setvoltage(sc->sc_iot, sc->sc_pm_ioh,
1462: PI2C_VOLTAGE_HIGH);
1463: if (freq != 208) {
1464: pxa27x_frequency_change(CCCR_A | CCCR_TURBO_X2 |
1465: CCCR_RUN_X16, CLKCFG_F, &pxa2x0_memcfg);
1466: pxa27x_fastbus_run_mode(1, pxa2x0_memcfg.mdrefr_high);
1467: freq = 208;
1468: }
1469: } else if (newfreq == 416) {
1470: if (freq < 208) {
1471: pxa2x0_pi2c_setvoltage(sc->sc_iot, sc->sc_pm_ioh,
1472: PI2C_VOLTAGE_HIGH);
1473: pxa27x_frequency_change(CCCR_A | CCCR_TURBO_X2 |
1474: CCCR_RUN_X16, CLKCFG_F, &pxa2x0_memcfg);
1475: pxa27x_fastbus_run_mode(1, pxa2x0_memcfg.mdrefr_high);
1476: }
1477: if (freq != 416) {
1478: pxa27x_frequency_change(CCCR_A | CCCR_TURBO_X2 |
1479: CCCR_RUN_X16, CLKCFG_B | CLKCFG_F | CLKCFG_T,
1480: &pxa2x0_memcfg);
1481: freq = 416;
1482: }
1483: } else if (newfreq == 520) {
1484: if (freq < 208) {
1485: pxa2x0_pi2c_setvoltage(sc->sc_iot, sc->sc_pm_ioh,
1486: PI2C_VOLTAGE_HIGH);
1487: pxa27x_frequency_change(CCCR_A | CCCR_TURBO_X2 |
1488: CCCR_RUN_X16, CLKCFG_F, &pxa2x0_memcfg);
1489: pxa27x_fastbus_run_mode(1, pxa2x0_memcfg.mdrefr_high);
1490: }
1491: if (freq != 520) {
1492: pxa27x_frequency_change(CCCR_A | CCCR_TURBO_X25 |
1493: CCCR_RUN_X16, CLKCFG_B | CLKCFG_F | CLKCFG_T,
1494: &pxa2x0_memcfg);
1495: freq = 520;
1496: }
1497: } else if (newfreq == 624) {
1498: if (freq < 208) {
1499: pxa2x0_pi2c_setvoltage(sc->sc_iot, sc->sc_pm_ioh,
1500: PI2C_VOLTAGE_HIGH);
1501: pxa27x_frequency_change(CCCR_A | CCCR_TURBO_X2 |
1502: CCCR_RUN_X16, CLKCFG_F, &pxa2x0_memcfg);
1503: pxa27x_fastbus_run_mode(1, pxa2x0_memcfg.mdrefr_high);
1504: }
1505: if (freq != 624) {
1506: pxa27x_frequency_change(CCCR_A | CCCR_TURBO_X3 |
1507: CCCR_RUN_X16, CLKCFG_B | CLKCFG_F | CLKCFG_T,
1508: &pxa2x0_memcfg);
1509: freq = 624;
1510: }
1511: }
1512:
1513: restore_interrupts(s);
1514: }
1515:
1516: int
1517: pxa2x0_cpuspeed(int *freqp)
1518: {
1519: *freqp = freq;
1520: return 0;
1521: }
1522:
1523: void pxa2x0_maxspeed(int *speedp);
1524:
1525: void
1526: pxa2x0_maxspeed(int *speedp)
1527: {
1528: /* XXX assumes a pxa270 */
1529:
1530: if (*speedp < 207) {
1531: *speedp = 91;
1532: } else if (*speedp < 415) {
1533: *speedp = 208;
1534: } else if (*speedp < 519) {
1535: *speedp = 416;
1536: } else if (*speedp < 624) {
1537: *speedp = 520;
1538: #if 0
1539: } else if (*speedp < 651) {
1540: *speedp = 624;
1541: #endif
1542: } else {
1543: *speedp = 520; /* hope this is safe. */
1544: }
1545: xscale_maxspeed = *speedp;
1546: pxa2x0_setperf(perflevel);
1547: }
CVSweb