[Blackfin] arch: Functional power management support: Add CPU and platform voltage...
authorMichael Hennerich <michael.hennerich@analog.com>
Wed, 7 May 2008 03:41:26 +0000 (11:41 +0800)
committerBryan Wu <cooloney@kernel.org>
Wed, 7 May 2008 03:41:26 +0000 (11:41 +0800)
Signed-off-by: Michael Hennerich <michael.hennerich@analog.com>
Signed-off-by: Bryan Wu <cooloney@kernel.org>
16 files changed:
arch/blackfin/Kconfig
arch/blackfin/mach-bf527/boards/ezkit.c
arch/blackfin/mach-bf533/boards/cm_bf533.c
arch/blackfin/mach-bf533/boards/ezkit.c
arch/blackfin/mach-bf533/boards/stamp.c
arch/blackfin/mach-bf537/boards/cm_bf537.c
arch/blackfin/mach-bf537/boards/stamp.c
arch/blackfin/mach-bf548/boards/cm_bf548.c
arch/blackfin/mach-bf548/boards/ezkit.c
arch/blackfin/mach-bf561/boards/cm_bf561.c
arch/blackfin/mach-bf561/boards/ezkit.c
arch/blackfin/mach-common/Makefile
arch/blackfin/mach-common/dpmc.S [deleted file]
arch/blackfin/mach-common/dpmc.c [new file with mode: 0644]
arch/blackfin/mach-common/dpmc_modes.S [new file with mode: 0644]
include/asm-blackfin/dpmc.h

index 7f1ab80..c8def1c 100644 (file)
@@ -967,6 +967,17 @@ menu "CPU Frequency scaling"
 
 source "drivers/cpufreq/Kconfig"
 
+config CPU_VOLTAGE
+       bool "CPU Voltage scaling"
+       depends on EXPERIMENTAL 
+       depends on CPU_FREQ
+       default n
+       help
+         Say Y here if you want CPU voltage scaling according to the CPU frequency.
+         This option violates the PLL BYPASS recommendation in the Blackfin Processor
+         manuals. There is a theoretical risk that during VDDINT transitions 
+         the PLL may unlock.
+
 endmenu
 
 source "net/Kconfig"
index 583d538..90dd086 100644 (file)
@@ -50,6 +50,7 @@
 #include <asm/reboot.h>
 #include <asm/nand.h>
 #include <asm/portmux.h>
+#include <asm/dpmc.h>
 #include <linux/spi/ad7877.h>
 
 /*
@@ -839,7 +840,32 @@ static struct platform_device bfin_gpios_device = {
        .resource = &bfin_gpios_resources,
 };
 
+static const unsigned int cclk_vlev_datasheet[] =
+{
+       VRPAIR(VLEV_100, 400000000),
+       VRPAIR(VLEV_105, 426000000),
+       VRPAIR(VLEV_110, 500000000),
+       VRPAIR(VLEV_115, 533000000),
+       VRPAIR(VLEV_120, 600000000),
+};
+
+static struct bfin_dpmc_platform_data bfin_dmpc_vreg_data = {
+       .tuple_tab = cclk_vlev_datasheet,
+       .tabsize = ARRAY_SIZE(cclk_vlev_datasheet),
+       .vr_settling_time = 25 /* us */,
+};
+
+static struct platform_device bfin_dpmc = {
+       .name = "bfin dpmc",
+       .dev = {
+               .platform_data = &bfin_dmpc_vreg_data,
+       },
+};
+
 static struct platform_device *stamp_devices[] __initdata = {
+
+       &bfin_dpmc,
+
 #if defined(CONFIG_MTD_NAND_BF5XX) || defined(CONFIG_MTD_NAND_BF5XX_MODULE)
        &bf5xx_nand_device,
 #endif
index a03149c..170ab57 100644 (file)
@@ -39,6 +39,7 @@
 #include <asm/dma.h>
 #include <asm/bfin5xx_spi.h>
 #include <asm/portmux.h>
+#include <asm/dpmc.h>
 
 /*
  * Name the Board for the /proc/cpuinfo
@@ -341,7 +342,37 @@ static struct platform_device bfin_pata_device = {
 };
 #endif
 
+static const unsigned int cclk_vlev_datasheet[] =
+{
+       VRPAIR(VLEV_085, 250000000),
+       VRPAIR(VLEV_090, 376000000),
+       VRPAIR(VLEV_095, 426000000),
+       VRPAIR(VLEV_100, 426000000),
+       VRPAIR(VLEV_105, 476000000),
+       VRPAIR(VLEV_110, 476000000),
+       VRPAIR(VLEV_115, 476000000),
+       VRPAIR(VLEV_120, 600000000),
+       VRPAIR(VLEV_125, 600000000),
+       VRPAIR(VLEV_130, 600000000),
+};
+
+static struct bfin_dpmc_platform_data bfin_dmpc_vreg_data = {
+       .tuple_tab = cclk_vlev_datasheet,
+       .tabsize = ARRAY_SIZE(cclk_vlev_datasheet),
+       .vr_settling_time = 25 /* us */,
+};
+
+static struct platform_device bfin_dpmc = {
+       .name = "bfin dpmc",
+       .dev = {
+               .platform_data = &bfin_dmpc_vreg_data,
+       },
+};
+
 static struct platform_device *cm_bf533_devices[] __initdata = {
+
+       &bfin_dpmc,
+
 #if defined(CONFIG_SERIAL_BFIN) || defined(CONFIG_SERIAL_BFIN_MODULE)
        &bfin_uart_device,
 #endif
index 08a7943..9d28415 100644 (file)
@@ -42,6 +42,7 @@
 #include <asm/dma.h>
 #include <asm/bfin5xx_spi.h>
 #include <asm/portmux.h>
+#include <asm/dpmc.h>
 
 /*
  * Name the Board for the /proc/cpuinfo
@@ -350,7 +351,37 @@ static struct platform_device i2c_gpio_device = {
 };
 #endif
 
+static const unsigned int cclk_vlev_datasheet[] =
+{
+       VRPAIR(VLEV_085, 250000000),
+       VRPAIR(VLEV_090, 376000000),
+       VRPAIR(VLEV_095, 426000000),
+       VRPAIR(VLEV_100, 426000000),
+       VRPAIR(VLEV_105, 476000000),
+       VRPAIR(VLEV_110, 476000000),
+       VRPAIR(VLEV_115, 476000000),
+       VRPAIR(VLEV_120, 600000000),
+       VRPAIR(VLEV_125, 600000000),
+       VRPAIR(VLEV_130, 600000000),
+};
+
+static struct bfin_dpmc_platform_data bfin_dmpc_vreg_data = {
+       .tuple_tab = cclk_vlev_datasheet,
+       .tabsize = ARRAY_SIZE(cclk_vlev_datasheet),
+       .vr_settling_time = 25 /* us */,
+};
+
+static struct platform_device bfin_dpmc = {
+       .name = "bfin dpmc",
+       .dev = {
+               .platform_data = &bfin_dmpc_vreg_data,
+       },
+};
+
 static struct platform_device *ezkit_devices[] __initdata = {
+
+       &bfin_dpmc,
+
 #if defined(CONFIG_SMC91X) || defined(CONFIG_SMC91X_MODULE)
        &smc91x_device,
 #endif
index 024f418..7fd35fb 100644 (file)
@@ -45,6 +45,7 @@
 #include <asm/bfin5xx_spi.h>
 #include <asm/reboot.h>
 #include <asm/portmux.h>
+#include <asm/dpmc.h>
 
 /*
  * Name the Board for the /proc/cpuinfo
@@ -516,7 +517,37 @@ static struct i2c_board_info __initdata bfin_i2c_board_info[] = {
 };
 #endif
 
+static const unsigned int cclk_vlev_datasheet[] =
+{
+       VRPAIR(VLEV_085, 250000000),
+       VRPAIR(VLEV_090, 376000000),
+       VRPAIR(VLEV_095, 426000000),
+       VRPAIR(VLEV_100, 426000000),
+       VRPAIR(VLEV_105, 476000000),
+       VRPAIR(VLEV_110, 476000000),
+       VRPAIR(VLEV_115, 476000000),
+       VRPAIR(VLEV_120, 600000000),
+       VRPAIR(VLEV_125, 600000000),
+       VRPAIR(VLEV_130, 600000000),
+};
+
+static struct bfin_dpmc_platform_data bfin_dmpc_vreg_data = {
+       .tuple_tab = cclk_vlev_datasheet,
+       .tabsize = ARRAY_SIZE(cclk_vlev_datasheet),
+       .vr_settling_time = 25 /* us */,
+};
+
+static struct platform_device bfin_dpmc = {
+       .name = "bfin dpmc",
+       .dev = {
+               .platform_data = &bfin_dmpc_vreg_data,
+       },
+};
+
 static struct platform_device *stamp_devices[] __initdata = {
+
+       &bfin_dpmc,
+
 #if defined(CONFIG_RTC_DRV_BFIN) || defined(CONFIG_RTC_DRV_BFIN_MODULE)
        &rtc_device,
 #endif
index d8a23cd..706e1a5 100644 (file)
@@ -41,6 +41,7 @@
 #include <asm/dma.h>
 #include <asm/bfin5xx_spi.h>
 #include <asm/portmux.h>
+#include <asm/dpmc.h>
 
 /*
  * Name the Board for the /proc/cpuinfo
@@ -428,7 +429,37 @@ static struct platform_device bfin_pata_device = {
 };
 #endif
 
+static const unsigned int cclk_vlev_datasheet[] =
+{
+       VRPAIR(VLEV_085, 250000000),
+       VRPAIR(VLEV_090, 376000000),
+       VRPAIR(VLEV_095, 426000000),
+       VRPAIR(VLEV_100, 426000000),
+       VRPAIR(VLEV_105, 476000000),
+       VRPAIR(VLEV_110, 476000000),
+       VRPAIR(VLEV_115, 476000000),
+       VRPAIR(VLEV_120, 500000000),
+       VRPAIR(VLEV_125, 533000000),
+       VRPAIR(VLEV_130, 600000000),
+};
+
+static struct bfin_dpmc_platform_data bfin_dmpc_vreg_data = {
+       .tuple_tab = cclk_vlev_datasheet,
+       .tabsize = ARRAY_SIZE(cclk_vlev_datasheet),
+       .vr_settling_time = 25 /* us */,
+};
+
+static struct platform_device bfin_dpmc = {
+       .name = "bfin dpmc",
+       .dev = {
+               .platform_data = &bfin_dmpc_vreg_data,
+       },
+};
+
 static struct platform_device *cm_bf537_devices[] __initdata = {
+
+       &bfin_dpmc,
+
 #if defined(CONFIG_FB_HITACHI_TX09) || defined(CONFIG_FB_HITACHI_TX09_MODULE)
        &hitachi_fb_device,
 #endif
index d3727b7..9a756d1 100644 (file)
@@ -47,6 +47,7 @@
 #include <asm/bfin5xx_spi.h>
 #include <asm/reboot.h>
 #include <asm/portmux.h>
+#include <asm/dpmc.h>
 #include <linux/spi/ad7877.h>
 
 /*
@@ -817,7 +818,37 @@ static struct platform_device bfin_pata_device = {
 };
 #endif
 
+static const unsigned int cclk_vlev_datasheet[] =
+{
+       VRPAIR(VLEV_085, 250000000),
+       VRPAIR(VLEV_090, 376000000),
+       VRPAIR(VLEV_095, 426000000),
+       VRPAIR(VLEV_100, 426000000),
+       VRPAIR(VLEV_105, 476000000),
+       VRPAIR(VLEV_110, 476000000),
+       VRPAIR(VLEV_115, 476000000),
+       VRPAIR(VLEV_120, 500000000),
+       VRPAIR(VLEV_125, 533000000),
+       VRPAIR(VLEV_130, 600000000),
+};
+
+static struct bfin_dpmc_platform_data bfin_dmpc_vreg_data = {
+       .tuple_tab = cclk_vlev_datasheet,
+       .tabsize = ARRAY_SIZE(cclk_vlev_datasheet),
+       .vr_settling_time = 25 /* us */,
+};
+
+static struct platform_device bfin_dpmc = {
+       .name = "bfin dpmc",
+       .dev = {
+               .platform_data = &bfin_dmpc_vreg_data,
+       },
+};
+
 static struct platform_device *stamp_devices[] __initdata = {
+
+       &bfin_dpmc,
+
 #if defined(CONFIG_BFIN_CFPCMCIA) || defined(CONFIG_BFIN_CFPCMCIA_MODULE)
        &bfin_pcmcia_cf_device,
 #endif
index e3e8479..40504ee 100644 (file)
@@ -44,6 +44,7 @@
 #include <asm/nand.h>
 #include <asm/portmux.h>
 #include <asm/mach/bf54x_keys.h>
+#include <asm/dpmc.h>
 #include <linux/input.h>
 #include <linux/spi/ad7877.h>
 
@@ -590,7 +591,38 @@ static struct platform_device bfin_device_gpiokeys = {
 };
 #endif
 
+static const unsigned int cclk_vlev_datasheet[] =
+{
+/*
+ * Internal VLEV BF54XSBBC1533
+ ****temporarily using these values until data sheet is updated
+ */
+       VRPAIR(VLEV_085, 150000000),
+       VRPAIR(VLEV_090, 250000000),
+       VRPAIR(VLEV_110, 276000000),
+       VRPAIR(VLEV_115, 301000000),
+       VRPAIR(VLEV_120, 525000000),
+       VRPAIR(VLEV_125, 550000000),
+       VRPAIR(VLEV_130, 600000000),
+};
+
+static struct bfin_dpmc_platform_data bfin_dmpc_vreg_data = {
+       .tuple_tab = cclk_vlev_datasheet,
+       .tabsize = ARRAY_SIZE(cclk_vlev_datasheet),
+       .vr_settling_time = 25 /* us */,
+};
+
+static struct platform_device bfin_dpmc = {
+       .name = "bfin dpmc",
+       .dev = {
+               .platform_data = &bfin_dmpc_vreg_data,
+       },
+};
+
 static struct platform_device *cm_bf548_devices[] __initdata = {
+
+       &bfin_dpmc,
+
 #if defined(CONFIG_RTC_DRV_BFIN) || defined(CONFIG_RTC_DRV_BFIN_MODULE)
        &rtc_device,
 #endif
index b00f68a..d1682bb 100644 (file)
@@ -46,6 +46,7 @@
 #include <asm/dma.h>
 #include <asm/gpio.h>
 #include <asm/nand.h>
+#include <asm/dpmc.h>
 #include <asm/portmux.h>
 #include <asm/mach/bf54x_keys.h>
 #include <linux/input.h>
@@ -689,7 +690,38 @@ static struct platform_device bfin_gpios_device = {
        .resource = &bfin_gpios_resources,
 };
 
+static const unsigned int cclk_vlev_datasheet[] =
+{
+/*
+ * Internal VLEV BF54XSBBC1533
+ ****temporarily using these values until data sheet is updated
+ */
+       VRPAIR(VLEV_085, 150000000),
+       VRPAIR(VLEV_090, 250000000),
+       VRPAIR(VLEV_110, 276000000),
+       VRPAIR(VLEV_115, 301000000),
+       VRPAIR(VLEV_120, 525000000),
+       VRPAIR(VLEV_125, 550000000),
+       VRPAIR(VLEV_130, 600000000),
+};
+
+static struct bfin_dpmc_platform_data bfin_dmpc_vreg_data = {
+       .tuple_tab = cclk_vlev_datasheet,
+       .tabsize = ARRAY_SIZE(cclk_vlev_datasheet),
+       .vr_settling_time = 25 /* us */,
+};
+
+static struct platform_device bfin_dpmc = {
+       .name = "bfin dpmc",
+       .dev = {
+               .platform_data = &bfin_dmpc_vreg_data,
+       },
+};
+
 static struct platform_device *ezkit_devices[] __initdata = {
+
+       &bfin_dpmc,
+
 #if defined(CONFIG_RTC_DRV_BFIN) || defined(CONFIG_RTC_DRV_BFIN_MODULE)
        &rtc_device,
 #endif
index 9fd5809..4075daf 100644 (file)
@@ -39,6 +39,7 @@
 #include <asm/dma.h>
 #include <asm/bfin5xx_spi.h>
 #include <asm/portmux.h>
+#include <asm/dpmc.h>
 
 /*
  * Name the Board for the /proc/cpuinfo
@@ -339,8 +340,37 @@ static struct platform_device bfin_pata_device = {
 };
 #endif
 
+static const unsigned int cclk_vlev_datasheet[] =
+{
+       VRPAIR(VLEV_085, 250000000),
+       VRPAIR(VLEV_090, 300000000),
+       VRPAIR(VLEV_095, 313000000),
+       VRPAIR(VLEV_100, 350000000),
+       VRPAIR(VLEV_105, 400000000),
+       VRPAIR(VLEV_110, 444000000),
+       VRPAIR(VLEV_115, 450000000),
+       VRPAIR(VLEV_120, 475000000),
+       VRPAIR(VLEV_125, 500000000),
+       VRPAIR(VLEV_130, 600000000),
+};
+
+static struct bfin_dpmc_platform_data bfin_dmpc_vreg_data = {
+       .tuple_tab = cclk_vlev_datasheet,
+       .tabsize = ARRAY_SIZE(cclk_vlev_datasheet),
+       .vr_settling_time = 25 /* us */,
+};
+
+static struct platform_device bfin_dpmc = {
+       .name = "bfin dpmc",
+       .dev = {
+               .platform_data = &bfin_dmpc_vreg_data,
+       },
+};
+
 static struct platform_device *cm_bf561_devices[] __initdata = {
 
+       &bfin_dpmc,
+
 #if defined(CONFIG_FB_HITACHI_TX09) || defined(CONFIG_FB_HITACHI_TX09_MODULE)
        &hitachi_fb_device,
 #endif
index 0d74b7d..61d8f76 100644 (file)
@@ -39,6 +39,7 @@
 #include <asm/dma.h>
 #include <asm/bfin5xx_spi.h>
 #include <asm/portmux.h>
+#include <asm/dpmc.h>
 
 /*
  * Name the Board for the /proc/cpuinfo
@@ -443,7 +444,37 @@ static struct platform_device i2c_gpio_device = {
 };
 #endif
 
+static const unsigned int cclk_vlev_datasheet[] =
+{
+       VRPAIR(VLEV_085, 250000000),
+       VRPAIR(VLEV_090, 300000000),
+       VRPAIR(VLEV_095, 313000000),
+       VRPAIR(VLEV_100, 350000000),
+       VRPAIR(VLEV_105, 400000000),
+       VRPAIR(VLEV_110, 444000000),
+       VRPAIR(VLEV_115, 450000000),
+       VRPAIR(VLEV_120, 475000000),
+       VRPAIR(VLEV_125, 500000000),
+       VRPAIR(VLEV_130, 600000000),
+};
+
+static struct bfin_dpmc_platform_data bfin_dmpc_vreg_data = {
+       .tuple_tab = cclk_vlev_datasheet,
+       .tabsize = ARRAY_SIZE(cclk_vlev_datasheet),
+       .vr_settling_time = 25 /* us */,
+};
+
+static struct platform_device bfin_dpmc = {
+       .name = "bfin dpmc",
+       .dev = {
+               .platform_data = &bfin_dmpc_vreg_data,
+       },
+};
+
 static struct platform_device *ezkit_devices[] __initdata = {
+
+       &bfin_dpmc,
+
 #if defined(CONFIG_SMC91X) || defined(CONFIG_SMC91X_MODULE)
        &smc91x_device,
 #endif
index 393081e..422bfee 100644 (file)
@@ -6,5 +6,6 @@ obj-y := \
        cache.o cacheinit.o entry.o \
        interrupt.o lock.o irqpanic.o arch_checks.o ints-priority.o
 
-obj-$(CONFIG_PM)         += pm.o dpmc.o
-obj-$(CONFIG_CPU_FREQ)   += cpufreq.o
+obj-$(CONFIG_PM)          += pm.o dpmc_modes.o
+obj-$(CONFIG_CPU_FREQ)    += cpufreq.o
+obj-$(CONFIG_CPU_VOLTAGE) += dpmc.o
diff --git a/arch/blackfin/mach-common/dpmc.S b/arch/blackfin/mach-common/dpmc.S
deleted file mode 100644 (file)
index 9d45aa3..0000000
+++ /dev/null
@@ -1,343 +0,0 @@
-/*
- * File:         arch/blackfin/mach-common/dpmc.S
- * Based on:
- * Author:       LG Soft India
- *
- * Created:      ?
- * Description:  Watchdog Timer APIs
- *
- * Modified:
- *               Copyright 2004-2006 Analog Devices Inc.
- *
- * Bugs:         Enter bugs at http://blackfin.uclinux.org/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see the file COPYING, or write
- * to the Free Software Foundation, Inc.,
- * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- */
-
-#include <linux/linkage.h>
-#include <asm/blackfin.h>
-#include <asm/mach/irq.h>
-
-
-.section .l1.text
-
-ENTRY(_sleep_mode)
-       [--SP] = ( R7:0, P5:0 );
-       [--SP] =  RETS;
-
-       call _set_sic_iwr;
-
-       R0 = 0xFFFF (Z);
-       call _set_rtc_istat;
-
-       P0.H = hi(PLL_CTL);
-       P0.L = lo(PLL_CTL);
-       R1 = W[P0](z);
-       BITSET (R1, 3);
-       W[P0] = R1.L;
-
-       CLI R2;
-       SSYNC;
-       IDLE;
-       STI R2;
-
-       call _test_pll_locked;
-
-       R0 = IWR_ENABLE(0);
-       R1 = IWR_DISABLE_ALL;
-       R2 = IWR_DISABLE_ALL;
-
-       call _set_sic_iwr;
-
-       P0.H = hi(PLL_CTL);
-       P0.L = lo(PLL_CTL);
-       R7 = w[p0](z);
-       BITCLR (R7, 3);
-       BITCLR (R7, 5);
-       w[p0] = R7.L;
-       IDLE;
-       call _test_pll_locked;
-
-       RETS = [SP++];
-       ( R7:0, P5:0 ) = [SP++];
-       RTS;
-
-ENTRY(_hibernate_mode)
-       [--SP] = ( R7:0, P5:0 );
-       [--SP] =  RETS;
-
-       call _set_sic_iwr;
-
-       R0 = 0xFFFF (Z);
-       call _set_rtc_istat;
-
-       P0.H = hi(VR_CTL);
-       P0.L = lo(VR_CTL);
-       R1 = W[P0](z);
-       BITSET (R1, 8);
-       BITCLR (R1, 0);
-       BITCLR (R1, 1);
-       W[P0] = R1.L;
-       SSYNC;
-
-       CLI R2;
-       IDLE;
-
-       /* Actually, adding anything may not be necessary...SDRAM contents
-        * are lost
-        */
-
-ENTRY(_deep_sleep)
-       [--SP] = ( R7:0, P5:0 );
-       [--SP] =  RETS;
-
-       CLI R4;
-
-       R0 = IWR_ENABLE(0);
-       R1 = IWR_DISABLE_ALL;
-       R2 = IWR_DISABLE_ALL;
-
-       call _set_sic_iwr;
-
-       call _set_dram_srfs;
-
-       /* Clear all the interrupts,bits sticky */
-       R0 = 0xFFFF (Z);
-       call _set_rtc_istat
-
-       P0.H = hi(PLL_CTL);
-       P0.L = lo(PLL_CTL);
-       R0 = W[P0](z);
-       BITSET (R0, 5);
-       W[P0] = R0.L;
-
-       call _test_pll_locked;
-
-       SSYNC;
-       IDLE;
-
-       call _unset_dram_srfs;
-
-       call _test_pll_locked;
-
-       R0 = IWR_ENABLE(0);
-       R1 = IWR_DISABLE_ALL;
-       R2 = IWR_DISABLE_ALL;
-
-       call _set_sic_iwr;
-
-       P0.H = hi(PLL_CTL);
-       P0.L = lo(PLL_CTL);
-       R0 = w[p0](z);
-       BITCLR (R0, 3);
-       BITCLR (R0, 5);
-       BITCLR (R0, 8);
-       w[p0] = R0;
-       IDLE;
-       call _test_pll_locked;
-
-       STI R4;
-
-       RETS = [SP++];
-       ( R7:0, P5:0 ) = [SP++];
-       RTS;
-
-ENTRY(_sleep_deeper)
-       [--SP] = ( R7:0, P5:0 );
-       [--SP] =  RETS;
-
-       CLI R4;
-
-       P3 = R0;
-       P4 = R1;
-       P5 = R2;
-
-       R0 = IWR_ENABLE(0);
-       R1 = IWR_DISABLE_ALL;
-       R2 = IWR_DISABLE_ALL;
-
-       call _set_sic_iwr;
-       call _set_dram_srfs;    /* Set SDRAM Self Refresh */
-
-       /* Clear all the interrupts,bits sticky */
-       R0 = 0xFFFF (Z);
-       call _set_rtc_istat;
-       P0.H = hi(PLL_DIV);
-       P0.L = lo(PLL_DIV);
-       R6 = W[P0](z);
-       R0.L = 0xF;
-       W[P0] = R0.l;           /* Set Max VCO to SCLK divider */
-
-       P0.H = hi(PLL_CTL);
-       P0.L = lo(PLL_CTL);
-       R5 = W[P0](z);
-       R0.L = (CONFIG_MIN_VCO_HZ/CONFIG_CLKIN_HZ) << 9;
-       W[P0] = R0.l;           /* Set Min CLKIN to VCO multiplier */
-
-       SSYNC;
-       IDLE;
-
-       call _test_pll_locked;
-
-       P0.H = hi(VR_CTL);
-       P0.L = lo(VR_CTL);
-       R7 = W[P0](z);
-       R1 = 0x6;
-       R1 <<= 16;
-       R2 = 0x0404(Z);
-       R1 = R1|R2;
-
-       R2 = DEPOSIT(R7, R1);
-       W[P0] = R2;             /* Set Min Core Voltage */
-
-       SSYNC;
-       IDLE;
-
-       call _test_pll_locked;
-
-       R0 = P3;
-       R1 = P4;
-       R3 = P5;
-       call _set_sic_iwr;      /* Set Awake from IDLE */
-
-       P0.H = hi(PLL_CTL);
-       P0.L = lo(PLL_CTL);
-       R0 = W[P0](z);
-       BITSET (R0, 3);
-       W[P0] = R0.L;           /* Turn CCLK OFF */
-       SSYNC;
-       IDLE;
-
-       call _test_pll_locked;
-
-       R0 = IWR_ENABLE(0);
-       R1 = IWR_DISABLE_ALL;
-       R2 = IWR_DISABLE_ALL;
-
-       call _set_sic_iwr;      /* Set Awake from IDLE PLL */
-
-       P0.H = hi(VR_CTL);
-       P0.L = lo(VR_CTL);
-       W[P0]= R7;
-
-       SSYNC;
-       IDLE;
-
-       call _test_pll_locked;
-
-       P0.H = hi(PLL_DIV);
-       P0.L = lo(PLL_DIV);
-       W[P0]= R6;              /* Restore CCLK and SCLK divider */
-
-       P0.H = hi(PLL_CTL);
-       P0.L = lo(PLL_CTL);
-       w[p0] = R5;             /* Restore VCO multiplier */
-       IDLE;
-       call _test_pll_locked;
-
-       call _unset_dram_srfs;  /* SDRAM Self Refresh Off */
-
-       STI R4;
-
-       RETS = [SP++];
-       ( R7:0, P5:0 ) = [SP++];
-       RTS;
-
-ENTRY(_set_dram_srfs)
-       /*  set the dram to self refresh mode */
-#if defined(CONFIG_BF54x)
-       P0.H = hi(EBIU_RSTCTL);
-       P0.L = lo(EBIU_RSTCTL);
-       R2 = [P0];
-       R3.H = hi(SRREQ);
-       R3.L = lo(SRREQ);
-#else
-       P0.H = hi(EBIU_SDGCTL);
-       P0.L = lo(EBIU_SDGCTL);
-       R2 = [P0];
-       R3.H = hi(SRFS);
-       R3.L = lo(SRFS);
-#endif
-       R2 = R2|R3;
-       [P0] = R2;
-       ssync;
-#if defined(CONFIG_BF54x)
-.LSRR_MODE:
-       R2 = [P0];
-       CC = BITTST(R2, 4);
-       if !CC JUMP .LSRR_MODE;
-#endif
-       RTS;
-
-ENTRY(_unset_dram_srfs)
-       /*  set the dram out of self refresh mode */
-#if defined(CONFIG_BF54x)
-       P0.H = hi(EBIU_RSTCTL);
-       P0.L = lo(EBIU_RSTCTL);
-       R2 = [P0];
-       R3.H = hi(SRREQ);
-       R3.L = lo(SRREQ);
-#else
-       P0.H = hi(EBIU_SDGCTL);
-       P0.L = lo(EBIU_SDGCTL);
-       R2 = [P0];
-       R3.H = hi(SRFS);
-       R3.L = lo(SRFS);
-#endif
-       R3 = ~R3;
-       R2 = R2&R3;
-       [P0] = R2;
-       ssync;
-       RTS;
-
-ENTRY(_set_sic_iwr)
-#if defined(CONFIG_BF54x) || defined(CONFIG_BF52x)  || defined(CONFIG_BF561)
-       P0.H = hi(SIC_IWR0);
-       P0.L = lo(SIC_IWR0);
-       P1.H = hi(SIC_IWR1);
-       P1.L = lo(SIC_IWR1);
-       [P1] = R1;
-#if defined(CONFIG_BF54x)
-       P1.H = hi(SIC_IWR2);
-       P1.L = lo(SIC_IWR2);
-       [P1] = R2;
-#endif
-#else
-       P0.H = hi(SIC_IWR);
-       P0.L = lo(SIC_IWR);
-#endif
-       [P0] = R0;
-
-       SSYNC;
-       RTS;
-
-ENTRY(_set_rtc_istat)
-#ifndef CONFIG_BF561
-       P0.H = hi(RTC_ISTAT);
-       P0.L = lo(RTC_ISTAT);
-       w[P0] = R0.L;
-       SSYNC;
-#endif
-       RTS;
-
-ENTRY(_test_pll_locked)
-       P0.H = hi(PLL_STAT);
-       P0.L = lo(PLL_STAT);
-1:
-       R0 = W[P0] (Z);
-       CC = BITTST(R0,5);
-       IF !CC JUMP 1b;
-       RTS;
diff --git a/arch/blackfin/mach-common/dpmc.c b/arch/blackfin/mach-common/dpmc.c
new file mode 100644 (file)
index 0000000..02c7efd
--- /dev/null
@@ -0,0 +1,137 @@
+/*
+ * Copyright 2008 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
+#include <linux/cdev.h>
+#include <linux/device.h>
+#include <linux/errno.h>
+#include <linux/fs.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/types.h>
+#include <linux/cpufreq.h>
+
+#include <asm/delay.h>
+#include <asm/dpmc.h>
+
+#define DRIVER_NAME "bfin dpmc"
+
+#define dprintk(msg...) \
+       cpufreq_debug_printk(CPUFREQ_DEBUG_DRIVER, DRIVER_NAME, msg)
+
+struct bfin_dpmc_platform_data *pdata;
+
+/**
+ *     bfin_set_vlev - Update VLEV field in VR_CTL Reg.
+ *                     Avoid BYPASS sequence
+ */
+static void bfin_set_vlev(unsigned int vlev)
+{
+       unsigned pll_lcnt;
+
+       pll_lcnt = bfin_read_PLL_LOCKCNT();
+
+       bfin_write_PLL_LOCKCNT(1);
+       bfin_write_VR_CTL((bfin_read_VR_CTL() & ~VLEV) | vlev);
+       bfin_write_PLL_LOCKCNT(pll_lcnt);
+}
+
+/**
+ *     bfin_get_vlev - Get CPU specific VLEV from platform device data
+ */
+static unsigned int bfin_get_vlev(unsigned int freq)
+{
+       int i;
+
+       if (!pdata)
+               goto err_out;
+
+       freq >>= 16;
+
+       for (i = 0; i < pdata->tabsize; i++)
+               if (freq <= (pdata->tuple_tab[i] & 0xFFFF))
+                       return pdata->tuple_tab[i] >> 16;
+
+err_out:
+       printk(KERN_WARNING "DPMC: No suitable CCLK VDDINT voltage pair found\n");
+       return VLEV_120;
+}
+
+#ifdef CONFIG_CPU_FREQ
+static int
+vreg_cpufreq_notifier(struct notifier_block *nb, unsigned long val, void *data)
+{
+       struct cpufreq_freqs *freq = data;
+
+       if (val == CPUFREQ_PRECHANGE && freq->old < freq->new) {
+               bfin_set_vlev(bfin_get_vlev(freq->new));
+               udelay(pdata->vr_settling_time); /* Wait until Volatge settled */
+
+       } else if (val == CPUFREQ_POSTCHANGE && freq->old > freq->new)
+               bfin_set_vlev(bfin_get_vlev(freq->new));
+
+       return 0;
+}
+
+static struct notifier_block vreg_cpufreq_notifier_block = {
+       .notifier_call  = vreg_cpufreq_notifier
+};
+#endif /* CONFIG_CPU_FREQ */
+
+/**
+ *     bfin_dpmc_probe -
+ *
+ */
+static int __devinit bfin_dpmc_probe(struct platform_device *pdev)
+{
+       if (pdev->dev.platform_data)
+               pdata = pdev->dev.platform_data;
+       else
+               return -EINVAL;
+
+       return cpufreq_register_notifier(&vreg_cpufreq_notifier_block,
+                                        CPUFREQ_TRANSITION_NOTIFIER);
+}
+
+/**
+ *     bfin_dpmc_remove -
+ */
+static int __devexit bfin_dpmc_remove(struct platform_device *pdev)
+{
+       pdata = NULL;
+       return cpufreq_unregister_notifier(&vreg_cpufreq_notifier_block,
+                                        CPUFREQ_TRANSITION_NOTIFIER);
+}
+
+struct platform_driver bfin_dpmc_device_driver = {
+       .probe   = bfin_dpmc_probe,
+       .remove  = __devexit_p(bfin_dpmc_remove),
+       .driver  = {
+               .name = DRIVER_NAME,
+       }
+};
+
+/**
+ *     bfin_dpmc_init - Init driver
+ */
+static int __init bfin_dpmc_init(void)
+{
+       return platform_driver_register(&bfin_dpmc_device_driver);
+}
+module_init(bfin_dpmc_init);
+
+/**
+ *     bfin_dpmc_exit - break down driver
+ */
+static void __exit bfin_dpmc_exit(void)
+{
+       platform_driver_unregister(&bfin_dpmc_device_driver);
+}
+module_exit(bfin_dpmc_exit);
+
+MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>");
+MODULE_DESCRIPTION("cpu power management driver for Blackfin");
+MODULE_LICENSE("GPL");
diff --git a/arch/blackfin/mach-common/dpmc_modes.S b/arch/blackfin/mach-common/dpmc_modes.S
new file mode 100644 (file)
index 0000000..b7981d3
--- /dev/null
@@ -0,0 +1,320 @@
+/*
+ * Copyright 2004-2008 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
+#include <linux/linkage.h>
+#include <asm/blackfin.h>
+#include <asm/mach/irq.h>
+
+
+.section .l1.text
+
+ENTRY(_sleep_mode)
+       [--SP] = ( R7:0, P5:0 );
+       [--SP] =  RETS;
+
+       call _set_sic_iwr;
+
+       R0 = 0xFFFF (Z);
+       call _set_rtc_istat;
+
+       P0.H = hi(PLL_CTL);
+       P0.L = lo(PLL_CTL);
+       R1 = W[P0](z);
+       BITSET (R1, 3);
+       W[P0] = R1.L;
+
+       CLI R2;
+       SSYNC;
+       IDLE;
+       STI R2;
+
+       call _test_pll_locked;
+
+       R0 = IWR_ENABLE(0);
+       R1 = IWR_DISABLE_ALL;
+       R2 = IWR_DISABLE_ALL;
+
+       call _set_sic_iwr;
+
+       P0.H = hi(PLL_CTL);
+       P0.L = lo(PLL_CTL);
+       R7 = w[p0](z);
+       BITCLR (R7, 3);
+       BITCLR (R7, 5);
+       w[p0] = R7.L;
+       IDLE;
+       call _test_pll_locked;
+
+       RETS = [SP++];
+       ( R7:0, P5:0 ) = [SP++];
+       RTS;
+
+ENTRY(_hibernate_mode)
+       [--SP] = ( R7:0, P5:0 );
+       [--SP] =  RETS;
+
+       call _set_sic_iwr;
+
+       R0 = 0xFFFF (Z);
+       call _set_rtc_istat;
+
+       P0.H = hi(VR_CTL);
+       P0.L = lo(VR_CTL);
+       R1 = W[P0](z);
+       BITSET (R1, 8);
+       BITCLR (R1, 0);
+       BITCLR (R1, 1);
+       W[P0] = R1.L;
+       SSYNC;
+
+       CLI R2;
+       IDLE;
+
+       /* Actually, adding anything may not be necessary...SDRAM contents
+        * are lost
+        */
+
+ENTRY(_deep_sleep)
+       [--SP] = ( R7:0, P5:0 );
+       [--SP] =  RETS;
+
+       CLI R4;
+
+       R0 = IWR_ENABLE(0);
+       R1 = IWR_DISABLE_ALL;
+       R2 = IWR_DISABLE_ALL;
+
+       call _set_sic_iwr;
+
+       call _set_dram_srfs;
+
+       /* Clear all the interrupts,bits sticky */
+       R0 = 0xFFFF (Z);
+       call _set_rtc_istat
+
+       P0.H = hi(PLL_CTL);
+       P0.L = lo(PLL_CTL);
+       R0 = W[P0](z);
+       BITSET (R0, 5);
+       W[P0] = R0.L;
+
+       call _test_pll_locked;
+
+       SSYNC;
+       IDLE;
+
+       call _unset_dram_srfs;
+
+       call _test_pll_locked;
+
+       R0 = IWR_ENABLE(0);
+       R1 = IWR_DISABLE_ALL;
+       R2 = IWR_DISABLE_ALL;
+
+       call _set_sic_iwr;
+
+       P0.H = hi(PLL_CTL);
+       P0.L = lo(PLL_CTL);
+       R0 = w[p0](z);
+       BITCLR (R0, 3);
+       BITCLR (R0, 5);
+       BITCLR (R0, 8);
+       w[p0] = R0;
+       IDLE;
+       call _test_pll_locked;
+
+       STI R4;
+
+       RETS = [SP++];
+       ( R7:0, P5:0 ) = [SP++];
+       RTS;
+
+ENTRY(_sleep_deeper)
+       [--SP] = ( R7:0, P5:0 );
+       [--SP] =  RETS;
+
+       CLI R4;
+
+       P3 = R0;
+       P4 = R1;
+       P5 = R2;
+
+       R0 = IWR_ENABLE(0);
+       R1 = IWR_DISABLE_ALL;
+       R2 = IWR_DISABLE_ALL;
+
+       call _set_sic_iwr;
+       call _set_dram_srfs;    /* Set SDRAM Self Refresh */
+
+       /* Clear all the interrupts,bits sticky */
+       R0 = 0xFFFF (Z);
+       call _set_rtc_istat;
+       P0.H = hi(PLL_DIV);
+       P0.L = lo(PLL_DIV);
+       R6 = W[P0](z);
+       R0.L = 0xF;
+       W[P0] = R0.l;           /* Set Max VCO to SCLK divider */
+
+       P0.H = hi(PLL_CTL);
+       P0.L = lo(PLL_CTL);
+       R5 = W[P0](z);
+       R0.L = (CONFIG_MIN_VCO_HZ/CONFIG_CLKIN_HZ) << 9;
+       W[P0] = R0.l;           /* Set Min CLKIN to VCO multiplier */
+
+       SSYNC;
+       IDLE;
+
+       call _test_pll_locked;
+
+       P0.H = hi(VR_CTL);
+       P0.L = lo(VR_CTL);
+       R7 = W[P0](z);
+       R1 = 0x6;
+       R1 <<= 16;
+       R2 = 0x0404(Z);
+       R1 = R1|R2;
+
+       R2 = DEPOSIT(R7, R1);
+       W[P0] = R2;             /* Set Min Core Voltage */
+
+       SSYNC;
+       IDLE;
+
+       call _test_pll_locked;
+
+       R0 = P3;
+       R1 = P4;
+       R3 = P5;
+       call _set_sic_iwr;      /* Set Awake from IDLE */
+
+       P0.H = hi(PLL_CTL);
+       P0.L = lo(PLL_CTL);
+       R0 = W[P0](z);
+       BITSET (R0, 3);
+       W[P0] = R0.L;           /* Turn CCLK OFF */
+       SSYNC;
+       IDLE;
+
+       call _test_pll_locked;
+
+       R0 = IWR_ENABLE(0);
+       R1 = IWR_DISABLE_ALL;
+       R2 = IWR_DISABLE_ALL;
+
+       call _set_sic_iwr;      /* Set Awake from IDLE PLL */
+
+       P0.H = hi(VR_CTL);
+       P0.L = lo(VR_CTL);
+       W[P0]= R7;
+
+       SSYNC;
+       IDLE;
+
+       call _test_pll_locked;
+
+       P0.H = hi(PLL_DIV);
+       P0.L = lo(PLL_DIV);
+       W[P0]= R6;              /* Restore CCLK and SCLK divider */
+
+       P0.H = hi(PLL_CTL);
+       P0.L = lo(PLL_CTL);
+       w[p0] = R5;             /* Restore VCO multiplier */
+       IDLE;
+       call _test_pll_locked;
+
+       call _unset_dram_srfs;  /* SDRAM Self Refresh Off */
+
+       STI R4;
+
+       RETS = [SP++];
+       ( R7:0, P5:0 ) = [SP++];
+       RTS;
+
+ENTRY(_set_dram_srfs)
+       /*  set the dram to self refresh mode */
+#if defined(CONFIG_BF54x)
+       P0.H = hi(EBIU_RSTCTL);
+       P0.L = lo(EBIU_RSTCTL);
+       R2 = [P0];
+       R3.H = hi(SRREQ);
+       R3.L = lo(SRREQ);
+#else
+       P0.H = hi(EBIU_SDGCTL);
+       P0.L = lo(EBIU_SDGCTL);
+       R2 = [P0];
+       R3.H = hi(SRFS);
+       R3.L = lo(SRFS);
+#endif
+       R2 = R2|R3;
+       [P0] = R2;
+       ssync;
+#if defined(CONFIG_BF54x)
+.LSRR_MODE:
+       R2 = [P0];
+       CC = BITTST(R2, 4);
+       if !CC JUMP .LSRR_MODE;
+#endif
+       RTS;
+
+ENTRY(_unset_dram_srfs)
+       /*  set the dram out of self refresh mode */
+#if defined(CONFIG_BF54x)
+       P0.H = hi(EBIU_RSTCTL);
+       P0.L = lo(EBIU_RSTCTL);
+       R2 = [P0];
+       R3.H = hi(SRREQ);
+       R3.L = lo(SRREQ);
+#else
+       P0.H = hi(EBIU_SDGCTL);
+       P0.L = lo(EBIU_SDGCTL);
+       R2 = [P0];
+       R3.H = hi(SRFS);
+       R3.L = lo(SRFS);
+#endif
+       R3 = ~R3;
+       R2 = R2&R3;
+       [P0] = R2;
+       ssync;
+       RTS;
+
+ENTRY(_set_sic_iwr)
+#if defined(CONFIG_BF54x) || defined(CONFIG_BF52x)  || defined(CONFIG_BF561)
+       P0.H = hi(SIC_IWR0);
+       P0.L = lo(SIC_IWR0);
+       P1.H = hi(SIC_IWR1);
+       P1.L = lo(SIC_IWR1);
+       [P1] = R1;
+#if defined(CONFIG_BF54x)
+       P1.H = hi(SIC_IWR2);
+       P1.L = lo(SIC_IWR2);
+       [P1] = R2;
+#endif
+#else
+       P0.H = hi(SIC_IWR);
+       P0.L = lo(SIC_IWR);
+#endif
+       [P0] = R0;
+
+       SSYNC;
+       RTS;
+
+ENTRY(_set_rtc_istat)
+#ifndef CONFIG_BF561
+       P0.H = hi(RTC_ISTAT);
+       P0.L = lo(RTC_ISTAT);
+       w[P0] = R0.L;
+       SSYNC;
+#endif
+       RTS;
+
+ENTRY(_test_pll_locked)
+       P0.H = hi(PLL_STAT);
+       P0.L = lo(PLL_STAT);
+1:
+       R0 = W[P0] (Z);
+       CC = BITTST(R0,5);
+       IF !CC JUMP 1b;
+       RTS;
index 686cf83..7f34cd3 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * include/asm-blackfin/dpmc.h -  Miscellaneous IOCTL commands for Dynamic Power
  *                             Management Controller Driver.
- * Copyright (C) 2004 Analog Device Inc.
+ * Copyright (C) 2004-2008 Analog Device Inc.
  *
  */
 #ifndef _BLACKFIN_DPMC_H_
@@ -65,6 +65,14 @@ void disable_wdog_timer(void);
 extern unsigned long get_cclk(void);
 extern unsigned long get_sclk(void);
 
+struct bfin_dpmc_platform_data {
+       const unsigned int *tuple_tab;
+       unsigned short tabsize;
+       unsigned short vr_settling_time; /* in us */
+};
+
+#define VRPAIR(vlev, freq) (((vlev) << 16) | ((freq) >> 16))
+
 #endif /* __KERNEL__ */
 
 #endif /*_BLACKFIN_DPMC_H_*/