Skip site navigation (1)Skip section navigation (2)
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>