/* * $Id: sapmc.c,v 1.2 2008/07/25 16:09:19 nbrk Exp $ */ /* * StrongARM 11x0 Power Management Controller. */ #include #include #include "sapmc_reg.h" int sapmc_init(void); int sapmc_ioctl(device_t, int, u_long); void sapmc_setfreq(int mode); uint32_t sapmc_getfreq(void); /* * Driver structure */ struct driver sapmc_drv = { /* name */ "SA-11x0 PMC", /* order */ 1, /* init */sapmc_init, }; struct devio sapmc_io = { /* open */ NULL, /* close */ NULL, /* read */ NULL, /* write */ NULL, /* ioctl */ sapmc_ioctl, /* event */ NULL, }; device_t sapmc_dev; /* * XXX PLL controlled Core Clock Frequencies with 3686400 Hz oscillator. */ #define SAPMC_NFREQMODES 12 uint32_t sapmc_ccfmodes[SAPMC_NFREQMODES] = { /* 0 */ 59000000, /* 1 */ 73700000, /* 2 */ 88500000, /* 3 */ 103200000, 118000000, 132700000, 147500000, 162200000, 176900000, 191700000, 206400000, 221200000 }; int sapmc_init(void) { /* register device */ sapmc_dev = device_create(&sapmc_io, "sapmc", DF_CHR); return(0); } int sapmc_ioctl(device_t dev, int cmd, u_long arg) { /* * ioctl() arg is a CCF mode (see datasheet). */ uint32_t freq; switch(cmd) { case CPUIOC_SET_FREQ: umem_copyin((uint32_t *)arg, &freq, sizeof(uint32_t)); if (freq > SAPMC_NFREQMODES) return(EINVAL); sapmc_setfreq(freq); break; case CPUIOC_GET_FREQ: freq = sapmc_getfreq(); umem_copyout(&freq, (uint32_t *)arg, sizeof(uint32_t)); break; } return(0); } void sapmc_setfreq(int mode) { *(volatile uint32_t *)(SAPMC_BASE + SAPMC_PPCR) = (mode & CCF); } uint32_t sapmc_getfreq(void) { int mode; mode = *(volatile uint32_t *)(SAPMC_BASE + SAPMC_PPCR); return(sapmc_ccfmodes[mode]); }