aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-exynos/asv-4x12.c
diff options
context:
space:
mode:
authorcodeworkx <daniel.hillenbrand@codeworkx.de>2012-06-02 13:09:29 +0200
committercodeworkx <daniel.hillenbrand@codeworkx.de>2012-06-02 13:09:29 +0200
commitc6da2cfeb05178a11c6d062a06f8078150ee492f (patch)
treef3b4021d252c52d6463a9b3c1bb7245e399b009c /arch/arm/mach-exynos/asv-4x12.c
parentc6d7c4dbff353eac7919342ae6b3299a378160a6 (diff)
downloadkernel_samsung_smdk4412-c6da2cfeb05178a11c6d062a06f8078150ee492f.zip
kernel_samsung_smdk4412-c6da2cfeb05178a11c6d062a06f8078150ee492f.tar.gz
kernel_samsung_smdk4412-c6da2cfeb05178a11c6d062a06f8078150ee492f.tar.bz2
samsung update 1
Diffstat (limited to 'arch/arm/mach-exynos/asv-4x12.c')
-rw-r--r--arch/arm/mach-exynos/asv-4x12.c190
1 files changed, 190 insertions, 0 deletions
diff --git a/arch/arm/mach-exynos/asv-4x12.c b/arch/arm/mach-exynos/asv-4x12.c
new file mode 100644
index 0000000..5eeaf20
--- /dev/null
+++ b/arch/arm/mach-exynos/asv-4x12.c
@@ -0,0 +1,190 @@
+/* linux/arch/arm/mach-exynos/asv-4x12.c
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com/
+ *
+ * EXYNOS4X12 - ASV(Adaptive Supply Voltage) driver
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/err.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+
+#include <mach/asv.h>
+#include <mach/map.h>
+#include <plat/cpu.h>
+
+/* ASV function for Fused Chip */
+#define IDS_ARM_OFFSET 24
+#define IDS_ARM_MASK 0xFF
+#define HPM_OFFSET 12
+#define HPM_MASK 0x1F
+
+#define FUSED_SG_OFFSET 3
+#define ORIG_SG_OFFSET 17
+#define ORIG_SG_MASK 0xF
+#define MOD_SG_OFFSET 21
+#define MOD_SG_MASK 0x7
+
+#define DEFAULT_ASV_GROUP 1
+
+#define CHIP_ID_REG (S5P_VA_CHIPID + 0x4)
+
+struct asv_judge_table exynos4x12_limit[] = {
+ /* HPM, IDS */
+ { 0, 0}, /* Reserved Group */
+ { 0, 0}, /* Reserved Group */
+ { 14, 9},
+ { 16, 14},
+ { 18, 17},
+ { 20, 20},
+ { 21, 24},
+ { 22, 30},
+ { 23, 34},
+ { 24, 39},
+ {100, 100},
+ {999, 999}, /* Reserved Group */
+};
+
+struct asv_judge_table exynos4212_limit[] = {
+ /* HPM, IDS */
+ { 0, 0}, /* Reserved Group */
+ { 17, 12},
+ { 18, 13},
+ { 20, 14},
+ { 22, 18},
+ { 24, 22},
+ { 25, 29},
+ { 26, 31},
+ { 27, 35},
+ { 28, 39},
+ {100, 100},
+ {999, 999}, /* Reserved Group */
+};
+
+static int exynos4x12_get_hpm(struct samsung_asv *asv_info)
+{
+ asv_info->hpm_result = (asv_info->pkg_id >> HPM_OFFSET) & HPM_MASK;
+
+ return 0;
+}
+
+static int exynos4x12_get_ids(struct samsung_asv *asv_info)
+{
+ asv_info->ids_result = (asv_info->pkg_id >> IDS_ARM_OFFSET) & IDS_ARM_MASK;
+
+ return 0;
+}
+
+static void exynos4x12_pre_set_abb(void)
+{
+ switch (exynos_result_of_asv) {
+ case 0:
+ case 1:
+ case 2:
+ case 3:
+ exynos4x12_set_abb(ABB_MODE_100V);
+ break;
+
+ default:
+ exynos4x12_set_abb(ABB_MODE_130V);
+ break;
+ }
+}
+
+static int exynos4x12_asv_store_result(struct samsung_asv *asv_info)
+{
+ unsigned int i;
+
+ if (soc_is_exynos4412()) {
+ for (i = 0; i < ARRAY_SIZE(exynos4x12_limit); i++) {
+ if ((asv_info->ids_result <= exynos4x12_limit[i].ids_limit) ||
+ (asv_info->hpm_result <= exynos4x12_limit[i].hpm_limit)) {
+ exynos_result_of_asv = i;
+ break;
+ }
+ }
+ } else {
+ for (i = 0; i < ARRAY_SIZE(exynos4212_limit); i++) {
+ if ((asv_info->ids_result <= exynos4212_limit[i].ids_limit) ||
+ (asv_info->hpm_result <= exynos4212_limit[i].hpm_limit)) {
+ exynos_result_of_asv = i;
+ break;
+ }
+ }
+
+ }
+
+ /*
+ * If ASV result value is lower than default value
+ * Fix with default value.
+ */
+ if (exynos_result_of_asv < DEFAULT_ASV_GROUP)
+ exynos_result_of_asv = DEFAULT_ASV_GROUP;
+
+ pr_info("EXYNOS4X12(NO SG): IDS : %d HPM : %d RESULT : %d\n",
+ asv_info->ids_result, asv_info->hpm_result, exynos_result_of_asv);
+
+ exynos4x12_pre_set_abb();
+
+ return 0;
+}
+
+int exynos4x12_asv_init(struct samsung_asv *asv_info)
+{
+ unsigned int tmp;
+ unsigned int exynos_orig_sp;
+ unsigned int exynos_mod_sp;
+ int exynos_cal_asv;
+
+ exynos_result_of_asv = 0;
+
+ pr_info("EXYNOS4X12: Adaptive Support Voltage init\n");
+
+ tmp = __raw_readl(CHIP_ID_REG);
+
+ /* Store PKG_ID */
+ asv_info->pkg_id = tmp;
+
+ /* If Speed group is fused, get speed group from */
+ if ((tmp >> FUSED_SG_OFFSET) & 0x1) {
+ exynos_orig_sp = (tmp >> ORIG_SG_OFFSET) & ORIG_SG_MASK;
+ exynos_mod_sp = (tmp >> MOD_SG_OFFSET) & MOD_SG_MASK;
+
+ exynos_cal_asv = exynos_orig_sp - exynos_mod_sp;
+
+ /*
+ * If There is no origin speed group,
+ * store 1 asv group into exynos_result_of_asv.
+ */
+ if (!exynos_orig_sp) {
+ pr_info("EXYNOS4X12: No Origin speed Group\n");
+ exynos_result_of_asv = DEFAULT_ASV_GROUP;
+ } else {
+ if (exynos_cal_asv < DEFAULT_ASV_GROUP)
+ exynos_result_of_asv = DEFAULT_ASV_GROUP;
+ else
+ exynos_result_of_asv = exynos_cal_asv;
+ }
+
+ pr_info("EXYNOS4X12(SG): ORIG : %d MOD : %d RESULT : %d\n",
+ exynos_orig_sp, exynos_mod_sp, exynos_result_of_asv);
+
+ exynos4x12_pre_set_abb();
+
+ return -EEXIST;
+ }
+
+ asv_info->get_ids = exynos4x12_get_ids;
+ asv_info->get_hpm = exynos4x12_get_hpm;
+ asv_info->store_result = exynos4x12_asv_store_result;
+
+ return 0;
+}