Date: Sat, 12 Apr 2014 12:04:46 -0700 From: Tim Kientzle <kientzle@freebsd.org> To: Xuebing Wang <xbing6@gmail.com> Cc: freebsd-arm@freebsd.org Subject: Re: [BeagleBone Black Test PATCH 0/2] port latest u-boot Message-ID: <58844C09-01AD-4739-B865-C8E5FA24F9C1@freebsd.org> In-Reply-To: <1396962361.81853.409.camel@revolution.hippie.lan> References: <1396862732-4961-1-git-send-email-xbing6@gmail.com> <C38629E3-59AC-4100-8748-01FF3F4FBC69@freebsd.org> <1396962361.81853.409.camel@revolution.hippie.lan>
next in thread | previous in thread | raw e-mail | index | archive | help
On Apr 8, 2014, at 6:06 AM, Ian Lepore <ian@freebsd.org> wrote: > On Mon, 2014-04-07 at 18:41 -0700, Tim Kientzle wrote: >> On Apr 7, 2014, at 2:25 AM, Xuebing Wang <xbing6@gmail.com> wrote: >>=20 >>> Hi Tim and all, >>>=20 >>> This is for discussion only. Would you please advice? >>>=20 >>> This is motivated by trying to increase CPU frequency for BeagleBone = Black. >>>=20 >>> AM335x cpufreq is not supported yet. In order to achieve the goal to = increase >>> CPU freq, I am thinking of a 2-step approach: >>> 1) port latest u-boot, which have cpufreq better organized >>> 2) tweak u-boot opp/freq later >>=20 >> Setting the processor frequency after the OS is running >> is not difficult. The AM335x TRM shows exactly how to do it. >>=20 >> I would not change U-Boot but rather implement >> a FreeBSD driver that exposed a read/write sysctl >> to reprogram the CPU frequency. >>=20 >> Getting powerd to work with this should be straightforward. >>=20 >> Tim >>=20 >=20 > I agree with this, we should handle the frequency change in the kernel > rather than in u-boot. I don't have time to work on this right now, but I found some old code I wrote -- from back before FreeBSD was running on BeagleBone and I was experimenting with standalone code -- to set the MPU PLL. The following implements the sequence described in 8.1.6.9.1 of the AM335x TRM (www.ti.com/lit/ug/spruh73j/spruh73j.pdf=E2=80=8E) to set the CPU frequency: #define CM_WKUP(offset) \ ((volatile int32_t *)(((volatile char *)0x44e00400) + (offset))) void mpu_pll(void) { int desired =3D 500; /* 500 MHz requested */ int input_clk =3D 24; /* BeagleBone uses 24MHz master crystal */ int output_divider =3D 2; /* Range: 1 - 31 */ int input_divider =3D 24; /* Range: 1 - 128 */ int multiplier =3D desired * output_divider * input_divider / = input_clk; /* Range: 2 - 2047 */ *CM_WKUP(0x88) =3D 4; /* MPU PLL to bypass mode */ while ((*CM_WKUP(0x20) & 0x100) =3D=3D 0) /* Wait for bypass = mode. */ ; *CM_WKUP(0x2C) =3D (multiplier << 8) | (input_divider - 1); *CM_WKUP(0xA8) =3D output_divider; /* Set "M2 divider" */ *CM_WKUP(0x88) =3D 7; /* MPU PLL to lock mode */ while ((*CM_WKUP(0x20) & 1) =3D=3D 1) /* Wait for MPU PLL to = lock. */ ; /* Final result =3D input_clk * multiplier / input_divider / = output_divider */ } Of course, in the kernel, this would have to first set up the proper memory mapping to access the registers. I believe this is the foundation for an AM335x cpufreq driver that would allow powerd to dynamically adjust the CPU frequency, providing both low power when the system is idle and good performance when needed. Cheers, Tim P.S. Apparently, the M2 output divider can be changed on-the-fly without forcing the PLL into bypass mode and back. That may be more appropriate for handling the dev.cpu.0.freq sysctl. (That is, set the multiplier to 2000 and the input_divider to 24. Then output dividers of 2, 3, 4, 10, 31 give 1000MHz, 667MHz, 500MHz, 200MHz, 65MHz.) P.P.S. I have some comments in my original code that BeagleBone (White) needs to keep the clock below 500MHz when running from USB power instead of AC. Don't know if that's relevant for BBB or not.
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?58844C09-01AD-4739-B865-C8E5FA24F9C1>