diff options
author | codeworkx <daniel.hillenbrand@codeworkx.de> | 2012-06-02 13:09:29 +0200 |
---|---|---|
committer | codeworkx <daniel.hillenbrand@codeworkx.de> | 2012-06-02 13:09:29 +0200 |
commit | c6da2cfeb05178a11c6d062a06f8078150ee492f (patch) | |
tree | f3b4021d252c52d6463a9b3c1bb7245e399b009c /arch/arm/mach-exynos/asv-4x12.c | |
parent | c6d7c4dbff353eac7919342ae6b3299a378160a6 (diff) | |
download | kernel_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.c | 190 |
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; +} |