#include "config.h" #include #include #include #include /* Most of the code in this file is based on code from wiki.gp2x.org */ static volatile uint_32 *memregs32; static volatile uint_16 *memregs16; static int memfd; int gp2x_speed(int speed) { int m = 0; // Calculating the FPLL value from frequency is a bit complex // so we just use some known-to-work values instead. switch(speed) { case 250: m = 0x5D04; break; case 225: m = 0x5304; break; case 200: m = 0x4904; break; case 175: m = 0x3F04; break; case 150: m = 0x4901; break; case 125: m = 0x3c01; break; case 100: m = 0x6502; break; case 75: m = 0x4902; break; case 50: m = 0x6503; break; default: m = 0; break; } if(m) { // Get interupt flags unsigned int l = memregs32[0x808>>2]; // Turn off interrupts memregs32[0x808>>2] = 0xFF8FFFE7; // Set new clock frequency memregs16[0x910>>1]=m; // Wait for it to take while(memregs16[0x0902>>1] & 1); // Turn on interrupts again memregs32[0x808>>2] = l; } return m == 0 ? -1 : 0; } static uint_16 saved_clock = 0; void gp2x_save_clock(void) { saved_clock = memregs16[0x910 >> 1]; } void gp2x_restore_clock(void) { if (saved_clock) { // Get interupt flags unsigned int l = memregs32[0x808>>2]; // Turn off interrupts memregs32[0x808>>2] = 0xFF8FFFE7; // Set new clock frequency memregs16[0x910>>1] = saved_clock; // Wait for it to take while(memregs16[0x0902>>1] & 1); // Turn on interrupts again memregs32[0x808>>2] = l; } } void *trymmap (void *start, size_t length, int prot, int flags, int fd, off_t offset) { char *p; int aa; jzp_printf ("mmap(%X, %X, %X, %X, %X, %X) ... ", (unsigned int)start, length, prot, flags, fd, (unsigned int)offset); p = mmap (start, length, prot, flags, fd, offset); if (p == (char *)0xFFFFFFFF) { aa = errno; jzp_printf ("failed. errno = %d\n", aa); } else { jzp_printf ("OK! (%X)\n", (unsigned int)p); } return p; } unsigned char gp2x_init (void) { memfd = open("/dev/mem", O_RDWR); if (memfd == -1) { jzp_printf ("Open failed\n"); return 0; } jzp_printf ("/dev/mem opened successfully - fd = %d\n", memfd); memregs32 = trymmap(0, 0x10000, PROT_READ|PROT_WRITE, MAP_SHARED, memfd, 0xc0000000); if (memregs32 == (unsigned long *)0xFFFFFFFF) return 0; memregs16 = (unsigned short *)memregs32; gp2x_save_clock(); atexit(gp2x_restore_clock); return 1; }