| 2.6.36 kernel BB-xM patch for 1 GHz (VDD1 voltage adjusting) | Max Galemin | 17/11/10 15:53 | 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. |
| Re: [beagleboard] 2.6.36 kernel BB-xM patch for 1 GHz (VDD1 voltage adjusting) | aos...@gmail.com | 17/11/10 16:29 | 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. |