2.6.36 kernel BB-xM patch for 1 GHz (VDD1 voltage adjusting)

421 views
Skip to first unread message

Max Galemin

unread,
Nov 17, 2010, 6:53:23 PM11/17/10
to Beagle Board
Hi all,

I made a patch for 2.6.36 kernel (git://git.kernel.org/pub/scm/linux/
kernel/git/tmlind/linux-omap-2.6.git) that makes it possible to run
Beagleboard-xM on 1 GHz frequency. The main idea is adjusting
processor voltage VDD1 to the level of OPP1G (1.28..1.38V). Please
note that default processor voltage after boot is 1.2V according to
BOOT0 (=1) and BOOT1 (=0) pins on TPS65950 (see "Table 5-2. Boot
Modes" in SWCU050F, p.238). You can see processor voltage values for
different frequencies in "Table 4-20. Processor Clocks" in SPRS685B
document (p.144). In order to increase voltage there are three
options:

1) SmartReflex technology (implemented in kernel 2.6.32 from Arago,
also used in TI VDSDK and Beagleboard validation, I have no time for
merging all PM related functionality to the new kernel);

2) Setting voltage directly using VDDx_VSEL register in TPS65950;

3) Play with VFLOOR/VROOF registers in TPS65950 and toggling VMODE
input (which is grounded in BB-xM A3).

I implemented adjusting by changing VDD1_VSEL register value (VDDx =
VDDx_VSEL x 12.5mV + 0.6V, thus, for VDD1 = 1.35V VDD1_VSEL = 0x3C -
see "5.4.10.1.1 Direct Control" in SWCU050F, p.259).

It would be great if someone check this workaround by reviewing the
code. Thanks!

P.S. I made a couple of tests - the temperature of the chip is
slightly higher than with mpurate=800.

=====
diff -U20 -r a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-
omap2/board-omap3beagle.c
--- a/arch/arm/mach-omap2/board-omap3beagle.c 2010-11-10
16:59:39.000000000 +1100
+++ b/arch/arm/mach-omap2/board-omap3beagle.c 2010-11-18
09:35:16.634918998 +1100
@@ -315,40 +315,52 @@

static struct i2c_board_info __initdata beagle_i2c_boardinfo[] = {
{
I2C_BOARD_INFO("twl4030", 0x48),
.flags = I2C_CLIENT_WAKE,
.irq = INT_34XX_SYS_NIRQ,
.platform_data = &beagle_twldata,
},
};

static int __init omap3_beagle_i2c_init(void)
{
omap_register_i2c_bus(1, 2600, beagle_i2c_boardinfo,
ARRAY_SIZE(beagle_i2c_boardinfo));
/* Bus 3 is attached to the DVI port where devices like the
pico DLP
* projector don't work reliably with 400kHz */
omap_register_i2c_bus(3, 100, NULL, 0);
return 0;
}

+int beagle_set_opp1g_voltage(void)
+{
+#define SET_VDD1_VSEL_1_35_V 0x3C
+
+ /* See TPS65950 TRM (SWCU050F) "5.4.10.1.1 Direct Control" for
details. */
+ twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER,
+ SET_VDD1_VSEL_1_35_V,
+ TWL4030_VDD1_VSEL);
+
+ return 0;
+}
+
static struct gpio_led gpio_leds[] = {
{
.name = "beagleboard::usr0",
.default_trigger = "heartbeat",
.gpio = 150,
},
{
.name = "beagleboard::usr1",
.default_trigger = "mmc0",
.gpio = 149,
},
{
.name = "beagleboard::pmu_stat",
.gpio = -EINVAL, /* gets
replaced */
.active_low = true,
},
};

static struct gpio_led_platform_data gpio_led_info = {
.leds = gpio_leds,
diff -U20 -r a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/
pm34xx.c
--- a/arch/arm/mach-omap2/pm34xx.c 2010-11-10 16:59:39.000000000
+1100
+++ b/arch/arm/mach-omap2/pm34xx.c 2010-11-18 09:36:14.222916045
+1100
@@ -1043,40 +1043,54 @@
void omap_push_sram_idle(void)
{
_omap_sram_idle = omap_sram_push(omap34xx_cpu_suspend,
omap34xx_cpu_suspend_sz);
if (omap_type() != OMAP2_DEVICE_TYPE_GP)
_omap_save_secure_sram =
omap_sram_push(save_secure_ram_context,
save_secure_ram_context_sz);
}

static int __init omap3_pm_init(void)
{
struct power_state *pwrst, *tmp;
struct clockdomain *neon_clkdm, *per_clkdm, *mpu_clkdm,
*core_clkdm;
int ret;

if (!cpu_is_omap34xx())
return -ENODEV;

printk(KERN_ERR "Power Management for TI OMAP3.\n");

+#ifdef CONFIG_MACH_OMAP3_BEAGLE
+ {
+ extern int beagle_set_opp1g_voltage(void);
+
+ if (mpurate >= 1000000000) {
+ /**
+ * Adjust VDD1 MPU voltage for 1GHz clock. See
DM3730 description
+ * (SPRS685B) "Table 4-20. Processor Clocks"
for details.
+ */
+ beagle_set_opp1g_voltage();
+ }
+ }
+#endif /* CONFIG_MACH_OMAP3_BEAGLE */
+
/* XXX prcm_setup_regs needs to be before enabling hw
* supervised mode for powerdomains */
prcm_setup_regs();

ret = request_irq(INT_34XX_PRCM_MPU_IRQ,
(irq_handler_t)prcm_interrupt_handler,
IRQF_DISABLED, "prcm", NULL);
if (ret) {
printk(KERN_ERR "request_irq failed to register for 0x
%x\n",
INT_34XX_PRCM_MPU_IRQ);
goto err1;
}

ret = pwrdm_for_each(pwrdms_setup, NULL);
if (ret) {
printk(KERN_ERR "Failed to setup powerdomains\n");
goto err2;
}

(void) clkdm_for_each(clkdms_setup, NULL);
diff -U20 -r a/arch/arm/plat-omap/clock.c b/arch/arm/plat-omap/clock.c
--- a/arch/arm/plat-omap/clock.c 2010-05-25 13:52:41.000000000
+1000
+++ b/arch/arm/plat-omap/clock.c 2010-11-18 09:19:18.203016004
+1100
@@ -164,41 +164,41 @@
}
EXPORT_SYMBOL(clk_get_parent);

/*
* OMAP specific clock functions shared between omap1 and omap2
*/

int __initdata mpurate;

/*
* By default we use the rate set by the bootloader.
* You can override this with mpurate= cmdline option.
*/
static int __init omap_clk_setup(char *str)
{
get_option(&str, &mpurate);

if (!mpurate)
return 1;

- if (mpurate < 1000)
+ if (mpurate < 2000)
mpurate *= 1000000;

return 1;
}
__setup("mpurate=", omap_clk_setup);

/* Used for clocks that always have same value as the parent clock */
unsigned long followparent_recalc(struct clk *clk)
{
return clk->parent->rate;
}

/*
* Used for clocks that have the same value as the parent clock,
* divided by some factor
*/
unsigned long omap_fixed_divisor_recalc(struct clk *clk)
{
WARN_ON(!clk->fixed_div);

diff -U20 -r a/include/linux/i2c/twl.h b/include/linux/i2c/twl.h
--- a/include/linux/i2c/twl.h 2010-11-10 17:00:14.000000000 +1100
+++ b/include/linux/i2c/twl.h 2010-11-18 09:19:09.954896444 +1100
@@ -608,40 +608,42 @@
struct regulator_init_data *vpp;
struct regulator_init_data *vusim;
struct regulator_init_data *vana;
struct regulator_init_data *vcxio;
struct regulator_init_data *vusb;
};

/
*----------------------------------------------------------------------
*/

int twl4030_sih_setup(int module);

/* Offsets to Power Registers */
#define TWL4030_VDAC_DEV_GRP 0x3B
#define TWL4030_VDAC_DEDICATED 0x3E
#define TWL4030_VAUX1_DEV_GRP 0x17
#define TWL4030_VAUX1_DEDICATED 0x1A
#define TWL4030_VAUX2_DEV_GRP 0x1B
#define TWL4030_VAUX2_DEDICATED 0x1E
#define TWL4030_VAUX3_DEV_GRP 0x1F
#define TWL4030_VAUX3_DEDICATED 0x22
+#define TWL4030_VDD1_VSEL 0x5E
+#define TWL4030_VDD2_VSEL 0x6C

static inline int twl4030charger_usb_en(int enable) { return 0; }

/
*----------------------------------------------------------------------
*/

/* Linux-specific regulator identifiers ... for now, we only support
* the LDOs, and leave the three buck converters alone. VDD1 and
VDD2
* need to tie into hardware based voltage scaling (cpufreq etc),
while
* VIO is generally fixed.
*/

/* TWL4030 SMPS/LDO's */
/* EXTERNAL dc-to-dc buck converters */
#define TWL4030_REG_VDD1 0
#define TWL4030_REG_VDD2 1
#define TWL4030_REG_VIO 2

/* EXTERNAL LDOs */
#define TWL4030_REG_VDAC 3
#define TWL4030_REG_VPLL1 4

=====


Cheers,
Max.

aos...@gmail.com

unread,
Nov 17, 2010, 7:29:30 PM11/17/10
to beagl...@googlegroups.com
Very cool, well done I'll have a look at the code when I get home.

-Alex
--
You received this message because you are subscribed to the Google Groups "Beagle Board" group.
To post to this group, send email to beagl...@googlegroups.com.
To unsubscribe from this group, send email to beagleboard...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/beagleboard?hl=en.

Reply all
Reply to author
Forward
0 new messages