| Tianyi Gou | 12370f1 | 2012-07-23 19:13:57 -0700 | [diff] [blame] | 1 | /* | 
|  | 2 | * Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved. | 
|  | 3 | * | 
|  | 4 | * This program is free software; you can redistribute it and/or modify | 
|  | 5 | * it under the terms of the GNU General Public License version 2 and | 
|  | 6 | * only version 2 as published by the Free Software Foundation. | 
|  | 7 | * | 
|  | 8 | * This program is distributed in the hope that it will be useful, | 
|  | 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | 
|  | 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
|  | 11 | * GNU General Public License for more details. | 
|  | 12 | */ | 
|  | 13 |  | 
|  | 14 | #include <linux/kernel.h> | 
|  | 15 | #include <linux/module.h> | 
|  | 16 | #include <linux/platform_device.h> | 
|  | 17 | #include <mach/rpm-regulator.h> | 
|  | 18 | #include <mach/msm_bus_board.h> | 
|  | 19 | #include <mach/msm_bus.h> | 
|  | 20 |  | 
|  | 21 | #include "acpuclock.h" | 
|  | 22 | #include "acpuclock-krait.h" | 
|  | 23 |  | 
|  | 24 | /* Corner type vreg VDD values */ | 
|  | 25 | #define LVL_NONE	RPM_VREG_CORNER_NONE | 
|  | 26 | #define LVL_LOW		RPM_VREG_CORNER_LOW | 
|  | 27 | #define LVL_NOM		RPM_VREG_CORNER_NOMINAL | 
|  | 28 | #define LVL_HIGH	RPM_VREG_CORNER_HIGH | 
|  | 29 |  | 
|  | 30 | static struct hfpll_data hfpll_data __initdata = { | 
|  | 31 | .mode_offset = 0x00, | 
|  | 32 | .l_offset = 0x08, | 
|  | 33 | .m_offset = 0x0C, | 
|  | 34 | .n_offset = 0x10, | 
|  | 35 | .config_offset = 0x04, | 
|  | 36 | .config_val = 0x7845C665, | 
|  | 37 | .has_droop_ctl = true, | 
|  | 38 | .droop_offset = 0x14, | 
|  | 39 | .droop_val = 0x0108C000, | 
| Matt Wagantall | 87465f5 | 2012-07-23 22:03:06 -0700 | [diff] [blame] | 40 | .low_vdd_l_max = 22, | 
|  | 41 | .nom_vdd_l_max = 42, | 
| Tianyi Gou | 12370f1 | 2012-07-23 19:13:57 -0700 | [diff] [blame] | 42 | .vdd[HFPLL_VDD_NONE] = LVL_NONE, | 
|  | 43 | .vdd[HFPLL_VDD_LOW]  = LVL_LOW, | 
|  | 44 | .vdd[HFPLL_VDD_NOM]  = LVL_NOM, | 
| Matt Wagantall | 87465f5 | 2012-07-23 22:03:06 -0700 | [diff] [blame] | 45 | .vdd[HFPLL_VDD_HIGH] = LVL_HIGH, | 
| Tianyi Gou | 12370f1 | 2012-07-23 19:13:57 -0700 | [diff] [blame] | 46 | }; | 
|  | 47 |  | 
|  | 48 | static struct scalable scalable[] __initdata = { | 
|  | 49 | [CPU0] = { | 
|  | 50 | .hfpll_phys_base = 0x00903200, | 
|  | 51 | .aux_clk_sel_phys = 0x02088014, | 
|  | 52 | .aux_clk_sel = 3, | 
|  | 53 | .l2cpmr_iaddr = 0x4501, | 
| Matt Wagantall | 6d9c416 | 2012-07-16 18:58:16 -0700 | [diff] [blame] | 54 | .vreg[VREG_CORE] = { "krait0", 1300000 }, | 
| Tianyi Gou | 12370f1 | 2012-07-23 19:13:57 -0700 | [diff] [blame] | 55 | .vreg[VREG_MEM]  = { "krait0_mem", 1150000 }, | 
|  | 56 | .vreg[VREG_DIG]  = { "krait0_dig", 1150000 }, | 
|  | 57 | .vreg[VREG_HFPLL_A] = { "krait0_hfpll", 1800000 }, | 
|  | 58 | }, | 
|  | 59 | [CPU1] = { | 
|  | 60 | .hfpll_phys_base = 0x00903300, | 
|  | 61 | .aux_clk_sel_phys = 0x02098014, | 
|  | 62 | .aux_clk_sel = 3, | 
|  | 63 | .l2cpmr_iaddr = 0x5501, | 
| Matt Wagantall | 6d9c416 | 2012-07-16 18:58:16 -0700 | [diff] [blame] | 64 | .vreg[VREG_CORE] = { "krait1", 1300000 }, | 
| Tianyi Gou | 12370f1 | 2012-07-23 19:13:57 -0700 | [diff] [blame] | 65 | .vreg[VREG_MEM]  = { "krait1_mem", 1150000 }, | 
|  | 66 | .vreg[VREG_DIG]  = { "krait1_dig", 1150000 }, | 
|  | 67 | .vreg[VREG_HFPLL_A] = { "krait1_hfpll", 1800000 }, | 
|  | 68 | }, | 
|  | 69 | [L2] = { | 
|  | 70 | .hfpll_phys_base = 0x00903400, | 
|  | 71 | .aux_clk_sel_phys = 0x02011028, | 
|  | 72 | .aux_clk_sel = 3, | 
|  | 73 | .l2cpmr_iaddr = 0x0500, | 
|  | 74 | .vreg[VREG_HFPLL_A] = { "l2_hfpll", 1800000 }, | 
|  | 75 | }, | 
|  | 76 | }; | 
|  | 77 |  | 
|  | 78 | static struct msm_bus_paths bw_level_tbl[] __initdata = { | 
|  | 79 | [0] =  BW_MBPS(640), /* At least  80 MHz on bus. */ | 
|  | 80 | [1] = BW_MBPS(1064), /* At least 133 MHz on bus. */ | 
|  | 81 | [2] = BW_MBPS(1600), /* At least 200 MHz on bus. */ | 
|  | 82 | [3] = BW_MBPS(2128), /* At least 266 MHz on bus. */ | 
|  | 83 | [4] = BW_MBPS(3200), /* At least 400 MHz on bus. */ | 
|  | 84 | [5] = BW_MBPS(3600), /* At least 450 MHz on bus. */ | 
|  | 85 | [6] = BW_MBPS(3936), /* At least 492 MHz on bus. */ | 
|  | 86 | [7] = BW_MBPS(4264), /* At least 533 MHz on bus. */ | 
|  | 87 | }; | 
|  | 88 |  | 
|  | 89 | static struct msm_bus_scale_pdata bus_scale_data __initdata = { | 
|  | 90 | .usecase = bw_level_tbl, | 
|  | 91 | .num_usecases = ARRAY_SIZE(bw_level_tbl), | 
|  | 92 | .active_only = 1, | 
|  | 93 | .name = "acpuclk-8930aa", | 
|  | 94 | }; | 
|  | 95 |  | 
|  | 96 | /* TODO: Update vdd_dig, vdd_mem and bw when data is available. */ | 
|  | 97 | static struct l2_level l2_freq_tbl[] __initdata = { | 
| Matt Wagantall | b7c231b | 2012-07-24 18:40:17 -0700 | [diff] [blame] | 98 | [0]  = { {  384000, PLL_8, 0, 2, 0x00 },  LVL_NOM, 1050000, 1 }, | 
|  | 99 | [1]  = { {  432000, HFPLL, 2, 0, 0x20 },  LVL_NOM, 1050000, 2 }, | 
|  | 100 | [2]  = { {  486000, HFPLL, 2, 0, 0x24 },  LVL_NOM, 1050000, 2 }, | 
|  | 101 | [3]  = { {  540000, HFPLL, 2, 0, 0x28 },  LVL_NOM, 1050000, 2 }, | 
|  | 102 | [4]  = { {  594000, HFPLL, 1, 0, 0x16 },  LVL_NOM, 1050000, 2 }, | 
|  | 103 | [5]  = { {  648000, HFPLL, 1, 0, 0x18 },  LVL_NOM, 1050000, 4 }, | 
|  | 104 | [6]  = { {  702000, HFPLL, 1, 0, 0x1A },  LVL_NOM, 1050000, 4 }, | 
|  | 105 | [7]  = { {  756000, HFPLL, 1, 0, 0x1C }, LVL_HIGH, 1150000, 4 }, | 
|  | 106 | [8]  = { {  810000, HFPLL, 1, 0, 0x1E }, LVL_HIGH, 1150000, 4 }, | 
|  | 107 | [9]  = { {  864000, HFPLL, 1, 0, 0x20 }, LVL_HIGH, 1150000, 4 }, | 
|  | 108 | [10] = { {  918000, HFPLL, 1, 0, 0x22 }, LVL_HIGH, 1150000, 7 }, | 
|  | 109 | [11] = { {  972000, HFPLL, 1, 0, 0x24 }, LVL_HIGH, 1150000, 7 }, | 
|  | 110 | [12] = { { 1026000, HFPLL, 1, 0, 0x26 }, LVL_HIGH, 1150000, 7 }, | 
|  | 111 | [13] = { { 1080000, HFPLL, 1, 0, 0x28 }, LVL_HIGH, 1150000, 7 }, | 
|  | 112 | [14] = { { 1134000, HFPLL, 1, 0, 0x2A }, LVL_HIGH, 1150000, 7 }, | 
|  | 113 | [15] = { { 1188000, HFPLL, 1, 0, 0x2C }, LVL_HIGH, 1150000, 7 }, | 
| Stephen Boyd | 2b73ee0 | 2012-09-11 21:08:13 -0700 | [diff] [blame^] | 114 | { } | 
| Tianyi Gou | 12370f1 | 2012-07-23 19:13:57 -0700 | [diff] [blame] | 115 | }; | 
|  | 116 |  | 
|  | 117 | static struct acpu_level acpu_freq_tbl_slow[] __initdata = { | 
| Matt Wagantall | b7c231b | 2012-07-24 18:40:17 -0700 | [diff] [blame] | 118 | { 1, {   384000, PLL_8, 0, 2, 0x00 }, L2(0),   950000 }, | 
|  | 119 | { 1, {   432000, HFPLL, 2, 0, 0x20 }, L2(5),   975000 }, | 
|  | 120 | { 1, {   486000, HFPLL, 2, 0, 0x24 }, L2(5),   975000 }, | 
|  | 121 | { 1, {   540000, HFPLL, 2, 0, 0x28 }, L2(5),  1000000 }, | 
|  | 122 | { 1, {   594000, HFPLL, 1, 0, 0x16 }, L2(5),  1000000 }, | 
|  | 123 | { 1, {   648000, HFPLL, 1, 0, 0x18 }, L2(5),  1025000 }, | 
|  | 124 | { 1, {   702000, HFPLL, 1, 0, 0x1A }, L2(5),  1025000 }, | 
|  | 125 | { 1, {   756000, HFPLL, 1, 0, 0x1C }, L2(10), 1075000 }, | 
|  | 126 | { 1, {   810000, HFPLL, 1, 0, 0x1E }, L2(10), 1075000 }, | 
|  | 127 | { 1, {   864000, HFPLL, 1, 0, 0x20 }, L2(10), 1100000 }, | 
|  | 128 | { 1, {   918000, HFPLL, 1, 0, 0x22 }, L2(10), 1100000 }, | 
|  | 129 | { 1, {   972000, HFPLL, 1, 0, 0x24 }, L2(10), 1125000 }, | 
|  | 130 | { 1, {  1026000, HFPLL, 1, 0, 0x26 }, L2(10), 1125000 }, | 
|  | 131 | { 1, {  1080000, HFPLL, 1, 0, 0x28 }, L2(15), 1175000 }, | 
|  | 132 | { 1, {  1134000, HFPLL, 1, 0, 0x2A }, L2(15), 1175000 }, | 
|  | 133 | { 1, {  1188000, HFPLL, 1, 0, 0x2C }, L2(15), 1200000 }, | 
|  | 134 | { 1, {  1242000, HFPLL, 1, 0, 0x2E }, L2(15), 1200000 }, | 
|  | 135 | { 1, {  1296000, HFPLL, 1, 0, 0x30 }, L2(15), 1225000 }, | 
|  | 136 | { 1, {  1350000, HFPLL, 1, 0, 0x32 }, L2(15), 1225000 }, | 
|  | 137 | { 1, {  1404000, HFPLL, 1, 0, 0x34 }, L2(15), 1237500 }, | 
| Tianyi Gou | 12370f1 | 2012-07-23 19:13:57 -0700 | [diff] [blame] | 138 | { 0, { 0 } } | 
|  | 139 | }; | 
|  | 140 |  | 
|  | 141 | static struct acpu_level acpu_freq_tbl_nom[] __initdata = { | 
| Matt Wagantall | b7c231b | 2012-07-24 18:40:17 -0700 | [diff] [blame] | 142 | { 1, {   384000, PLL_8, 0, 2, 0x00 }, L2(0),   925000 }, | 
|  | 143 | { 1, {   432000, HFPLL, 2, 0, 0x20 }, L2(5),   950000 }, | 
|  | 144 | { 1, {   486000, HFPLL, 2, 0, 0x24 }, L2(5),   950000 }, | 
|  | 145 | { 1, {   540000, HFPLL, 2, 0, 0x28 }, L2(5),   975000 }, | 
|  | 146 | { 1, {   594000, HFPLL, 1, 0, 0x16 }, L2(5),   975000 }, | 
|  | 147 | { 1, {   648000, HFPLL, 1, 0, 0x18 }, L2(5),  1000000 }, | 
|  | 148 | { 1, {   702000, HFPLL, 1, 0, 0x1A }, L2(5),  1000000 }, | 
|  | 149 | { 1, {   756000, HFPLL, 1, 0, 0x1C }, L2(10), 1050000 }, | 
|  | 150 | { 1, {   810000, HFPLL, 1, 0, 0x1E }, L2(10), 1050000 }, | 
|  | 151 | { 1, {   864000, HFPLL, 1, 0, 0x20 }, L2(10), 1075000 }, | 
|  | 152 | { 1, {   918000, HFPLL, 1, 0, 0x22 }, L2(10), 1075000 }, | 
|  | 153 | { 1, {   972000, HFPLL, 1, 0, 0x24 }, L2(10), 1100000 }, | 
|  | 154 | { 1, {  1026000, HFPLL, 1, 0, 0x26 }, L2(10), 1100000 }, | 
|  | 155 | { 1, {  1080000, HFPLL, 1, 0, 0x28 }, L2(15), 1150000 }, | 
|  | 156 | { 1, {  1134000, HFPLL, 1, 0, 0x2A }, L2(15), 1150000 }, | 
|  | 157 | { 1, {  1188000, HFPLL, 1, 0, 0x2C }, L2(15), 1175000 }, | 
|  | 158 | { 1, {  1242000, HFPLL, 1, 0, 0x2E }, L2(15), 1175000 }, | 
|  | 159 | { 1, {  1296000, HFPLL, 1, 0, 0x30 }, L2(15), 1200000 }, | 
|  | 160 | { 1, {  1350000, HFPLL, 1, 0, 0x32 }, L2(15), 1200000 }, | 
|  | 161 | { 1, {  1404000, HFPLL, 1, 0, 0x34 }, L2(15), 1212500 }, | 
| Tianyi Gou | 12370f1 | 2012-07-23 19:13:57 -0700 | [diff] [blame] | 162 | { 0, { 0 } } | 
|  | 163 | }; | 
|  | 164 |  | 
|  | 165 | static struct acpu_level acpu_freq_tbl_fast[] __initdata = { | 
| Matt Wagantall | b7c231b | 2012-07-24 18:40:17 -0700 | [diff] [blame] | 166 | { 1, {   384000, PLL_8, 0, 2, 0x00 }, L2(0),   900000 }, | 
|  | 167 | { 1, {   432000, HFPLL, 2, 0, 0x20 }, L2(5),   900000 }, | 
|  | 168 | { 1, {   486000, HFPLL, 2, 0, 0x24 }, L2(5),   900000 }, | 
|  | 169 | { 1, {   540000, HFPLL, 2, 0, 0x28 }, L2(5),   925000 }, | 
|  | 170 | { 1, {   594000, HFPLL, 1, 0, 0x16 }, L2(5),   925000 }, | 
|  | 171 | { 1, {   648000, HFPLL, 1, 0, 0x18 }, L2(5),   950000 }, | 
|  | 172 | { 1, {   702000, HFPLL, 1, 0, 0x1A }, L2(5),   950000 }, | 
|  | 173 | { 1, {   756000, HFPLL, 1, 0, 0x1C }, L2(10), 1000000 }, | 
|  | 174 | { 1, {   810000, HFPLL, 1, 0, 0x1E }, L2(10), 1000000 }, | 
|  | 175 | { 1, {   864000, HFPLL, 1, 0, 0x20 }, L2(10), 1025000 }, | 
|  | 176 | { 1, {   918000, HFPLL, 1, 0, 0x22 }, L2(10), 1025000 }, | 
|  | 177 | { 1, {   972000, HFPLL, 1, 0, 0x24 }, L2(10), 1050000 }, | 
|  | 178 | { 1, {  1026000, HFPLL, 1, 0, 0x26 }, L2(10), 1050000 }, | 
|  | 179 | { 1, {  1080000, HFPLL, 1, 0, 0x28 }, L2(15), 1100000 }, | 
|  | 180 | { 1, {  1134000, HFPLL, 1, 0, 0x2A }, L2(15), 1100000 }, | 
|  | 181 | { 1, {  1188000, HFPLL, 1, 0, 0x2C }, L2(15), 1125000 }, | 
|  | 182 | { 1, {  1242000, HFPLL, 1, 0, 0x2E }, L2(15), 1125000 }, | 
|  | 183 | { 1, {  1296000, HFPLL, 1, 0, 0x30 }, L2(15), 1150000 }, | 
|  | 184 | { 1, {  1350000, HFPLL, 1, 0, 0x32 }, L2(15), 1150000 }, | 
|  | 185 | { 1, {  1404000, HFPLL, 1, 0, 0x34 }, L2(15), 1162500 }, | 
| Tianyi Gou | 12370f1 | 2012-07-23 19:13:57 -0700 | [diff] [blame] | 186 | { 0, { 0 } } | 
|  | 187 | }; | 
|  | 188 |  | 
|  | 189 | static struct pvs_table pvs_tables[NUM_PVS] __initdata = { | 
| Matt Wagantall | 9515bc2 | 2012-07-19 18:13:40 -0700 | [diff] [blame] | 190 | [PVS_SLOW]    = { acpu_freq_tbl_slow, sizeof(acpu_freq_tbl_slow),     0 }, | 
|  | 191 | [PVS_NOMINAL] = { acpu_freq_tbl_nom,  sizeof(acpu_freq_tbl_nom),  25000 }, | 
|  | 192 | [PVS_FAST]    = { acpu_freq_tbl_fast, sizeof(acpu_freq_tbl_fast), 25000 }, | 
| Tianyi Gou | 12370f1 | 2012-07-23 19:13:57 -0700 | [diff] [blame] | 193 | }; | 
|  | 194 |  | 
|  | 195 | static struct acpuclk_krait_params acpuclk_8930aa_params __initdata = { | 
|  | 196 | .scalable = scalable, | 
|  | 197 | .scalable_size = sizeof(scalable), | 
|  | 198 | .hfpll_data = &hfpll_data, | 
|  | 199 | .pvs_tables = pvs_tables, | 
|  | 200 | .l2_freq_tbl = l2_freq_tbl, | 
|  | 201 | .l2_freq_tbl_size = sizeof(l2_freq_tbl), | 
|  | 202 | .bus_scale = &bus_scale_data, | 
|  | 203 | .qfprom_phys_base = 0x00700000, | 
| Matt Wagantall | b7c231b | 2012-07-24 18:40:17 -0700 | [diff] [blame] | 204 | .stby_khz = 384000, | 
| Tianyi Gou | 12370f1 | 2012-07-23 19:13:57 -0700 | [diff] [blame] | 205 | }; | 
|  | 206 |  | 
|  | 207 | static int __init acpuclk_8930aa_probe(struct platform_device *pdev) | 
|  | 208 | { | 
|  | 209 | return acpuclk_krait_init(&pdev->dev, &acpuclk_8930aa_params); | 
|  | 210 | } | 
|  | 211 |  | 
|  | 212 | static struct platform_driver acpuclk_8930aa_driver = { | 
|  | 213 | .driver = { | 
|  | 214 | .name = "acpuclk-8930aa", | 
|  | 215 | .owner = THIS_MODULE, | 
|  | 216 | }, | 
|  | 217 | }; | 
|  | 218 |  | 
|  | 219 | static int __init acpuclk_8930aa_init(void) | 
|  | 220 | { | 
|  | 221 | return platform_driver_probe(&acpuclk_8930aa_driver, | 
|  | 222 | acpuclk_8930aa_probe); | 
|  | 223 | } | 
|  | 224 | device_initcall(acpuclk_8930aa_init); |