| David Collins | 6ef12bf | 2011-08-31 14:08:15 -0700 | [diff] [blame] | 1 | /* | 
|  | 2 | * Copyright (c) 2011, 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 | #define pr_fmt(fmt) "%s: " fmt, __func__ | 
|  | 15 |  | 
|  | 16 | #include "rpm-regulator-private.h" | 
|  | 17 |  | 
|  | 18 | /* RPM regulator request formats */ | 
|  | 19 | static struct rpm_vreg_parts ldo_parts = { | 
|  | 20 | .request_len	= 2, | 
|  | 21 | .uV		= REQUEST_MEMBER(0, 0x007FFFFF,  0), | 
|  | 22 | .pd		= REQUEST_MEMBER(0, 0x00800000, 23), | 
|  | 23 | .pc		= REQUEST_MEMBER(0, 0x0F000000, 24), | 
|  | 24 | .pf		= REQUEST_MEMBER(0, 0xF0000000, 28), | 
|  | 25 | .ip		= REQUEST_MEMBER(1, 0x000003FF,  0), | 
|  | 26 | .ia		= REQUEST_MEMBER(1, 0x000FFC00, 10), | 
|  | 27 | .fm		= REQUEST_MEMBER(1, 0x00700000, 20), | 
|  | 28 | }; | 
|  | 29 |  | 
|  | 30 | static struct rpm_vreg_parts smps_parts = { | 
|  | 31 | .request_len	= 2, | 
|  | 32 | .uV		= REQUEST_MEMBER(0, 0x007FFFFF,  0), | 
|  | 33 | .pd		= REQUEST_MEMBER(0, 0x00800000, 23), | 
|  | 34 | .pc		= REQUEST_MEMBER(0, 0x0F000000, 24), | 
|  | 35 | .pf		= REQUEST_MEMBER(0, 0xF0000000, 28), | 
|  | 36 | .ip		= REQUEST_MEMBER(1, 0x000003FF,  0), | 
|  | 37 | .ia		= REQUEST_MEMBER(1, 0x000FFC00, 10), | 
|  | 38 | .fm		= REQUEST_MEMBER(1, 0x00700000, 20), | 
|  | 39 | .pm		= REQUEST_MEMBER(1, 0x00800000, 23), | 
|  | 40 | .freq		= REQUEST_MEMBER(1, 0x1F000000, 24), | 
|  | 41 | .freq_clk_src	= REQUEST_MEMBER(1, 0x60000000, 29), | 
|  | 42 | }; | 
|  | 43 |  | 
|  | 44 | static struct rpm_vreg_parts switch_parts = { | 
|  | 45 | .request_len	= 1, | 
|  | 46 | .enable_state	= REQUEST_MEMBER(0, 0x00000001,  0), | 
|  | 47 | .pd		= REQUEST_MEMBER(0, 0x00000002,  1), | 
|  | 48 | .pc		= REQUEST_MEMBER(0, 0x0000003C,  2), | 
|  | 49 | .pf		= REQUEST_MEMBER(0, 0x000003C0,  6), | 
|  | 50 | .hpm		= REQUEST_MEMBER(0, 0x00000C00, 10), | 
|  | 51 | }; | 
|  | 52 |  | 
|  | 53 | /* Physically available PMIC regulator voltage setpoint ranges */ | 
|  | 54 | static struct vreg_range pldo_ranges[] = { | 
|  | 55 | VOLTAGE_RANGE( 750000, 1487500, 12500), | 
|  | 56 | VOLTAGE_RANGE(1500000, 3075000, 25000), | 
|  | 57 | VOLTAGE_RANGE(3100000, 4900000, 50000), | 
|  | 58 | }; | 
|  | 59 |  | 
|  | 60 | static struct vreg_range nldo_ranges[] = { | 
|  | 61 | VOLTAGE_RANGE( 750000, 1537500, 12500), | 
|  | 62 | }; | 
|  | 63 |  | 
|  | 64 | static struct vreg_range nldo1200_ranges[] = { | 
|  | 65 | VOLTAGE_RANGE( 375000,  743750,  6250), | 
|  | 66 | VOLTAGE_RANGE( 750000, 1537500, 12500), | 
|  | 67 | }; | 
|  | 68 |  | 
|  | 69 | static struct vreg_range smps_ranges[] = { | 
|  | 70 | VOLTAGE_RANGE( 375000,  737500, 12500), | 
|  | 71 | VOLTAGE_RANGE( 750000, 1487500, 12500), | 
|  | 72 | VOLTAGE_RANGE(1500000, 3075000, 25000), | 
|  | 73 | }; | 
|  | 74 |  | 
|  | 75 | static struct vreg_set_points pldo_set_points = SET_POINTS(pldo_ranges); | 
|  | 76 | static struct vreg_set_points nldo_set_points = SET_POINTS(nldo_ranges); | 
|  | 77 | static struct vreg_set_points nldo1200_set_points = SET_POINTS(nldo1200_ranges); | 
|  | 78 | static struct vreg_set_points smps_set_points = SET_POINTS(smps_ranges); | 
|  | 79 |  | 
|  | 80 | static struct vreg_set_points *all_set_points[] = { | 
|  | 81 | &pldo_set_points, | 
|  | 82 | &nldo_set_points, | 
|  | 83 | &nldo1200_set_points, | 
|  | 84 | &smps_set_points, | 
|  | 85 | }; | 
|  | 86 |  | 
|  | 87 | #define LDO(_id, _name, _name_pc, _ranges, _hpm_min_load) \ | 
|  | 88 | [RPM_VREG_ID_PM8018_##_id] = { \ | 
|  | 89 | .req = { \ | 
|  | 90 | [0] = { .id = MSM_RPM_ID_PM8018_##_id##_0, }, \ | 
|  | 91 | [1] = { .id = MSM_RPM_ID_PM8018_##_id##_1, }, \ | 
|  | 92 | }, \ | 
|  | 93 | .hpm_min_load  = RPM_VREG_9615_##_hpm_min_load##_HPM_MIN_LOAD, \ | 
|  | 94 | .type		 = RPM_REGULATOR_TYPE_LDO, \ | 
|  | 95 | .set_points	 = &_ranges##_set_points, \ | 
|  | 96 | .part		 = &ldo_parts, \ | 
|  | 97 | .id		 = RPM_VREG_ID_PM8018_##_id, \ | 
|  | 98 | .rdesc.name	 = _name, \ | 
|  | 99 | .rdesc_pc.name	 = _name_pc, \ | 
|  | 100 | } | 
|  | 101 |  | 
|  | 102 | #define SMPS(_id, _name, _name_pc, _ranges, _hpm_min_load) \ | 
|  | 103 | [RPM_VREG_ID_PM8018_##_id] = { \ | 
|  | 104 | .req = { \ | 
|  | 105 | [0] = { .id = MSM_RPM_ID_PM8018_##_id##_0, }, \ | 
|  | 106 | [1] = { .id = MSM_RPM_ID_PM8018_##_id##_1, }, \ | 
|  | 107 | }, \ | 
|  | 108 | .hpm_min_load  = RPM_VREG_9615_##_hpm_min_load##_HPM_MIN_LOAD, \ | 
|  | 109 | .type		 = RPM_REGULATOR_TYPE_SMPS, \ | 
|  | 110 | .set_points	 = &_ranges##_set_points, \ | 
|  | 111 | .part		 = &smps_parts, \ | 
|  | 112 | .id		 = RPM_VREG_ID_PM8018_##_id, \ | 
|  | 113 | .rdesc.name	 = _name, \ | 
|  | 114 | .rdesc_pc.name	 = _name_pc, \ | 
|  | 115 | } | 
|  | 116 |  | 
|  | 117 | #define LVS(_id, _name, _name_pc) \ | 
|  | 118 | [RPM_VREG_ID_PM8018_##_id] = { \ | 
|  | 119 | .req = { \ | 
|  | 120 | [0] = { .id = MSM_RPM_ID_PM8018_##_id, }, \ | 
|  | 121 | [1] = { .id = -1, }, \ | 
|  | 122 | }, \ | 
|  | 123 | .type		 = RPM_REGULATOR_TYPE_VS, \ | 
|  | 124 | .part		 = &switch_parts, \ | 
|  | 125 | .id		 = RPM_VREG_ID_PM8018_##_id, \ | 
|  | 126 | .rdesc.name	 = _name, \ | 
|  | 127 | .rdesc_pc.name	 = _name_pc, \ | 
|  | 128 | } | 
|  | 129 |  | 
|  | 130 | static struct vreg vregs[] = { | 
|  | 131 | LDO(L2,   "8018_l2",   "8018_l2_pc",  pldo,     LDO_50), | 
|  | 132 | LDO(L3,   "8018_l3",   "8018_l3_pc",  pldo,     LDO_50), | 
|  | 133 | LDO(L4,   "8018_l4",   "8018_l4_pc",  pldo,     LDO_300), | 
|  | 134 | LDO(L5,   "8018_l5",   "8018_l5_pc",  pldo,     LDO_150), | 
|  | 135 | LDO(L6,   "8018_l6",   "8018_l6_pc",  pldo,     LDO_150), | 
|  | 136 | LDO(L7,   "8018_l7",   "8018_l7_pc",  pldo,     LDO_300), | 
|  | 137 | LDO(L8,   "8018_l8",   "8018_l8_pc",  nldo,     LDO_150), | 
|  | 138 | LDO(L9,   "8018_l9",   NULL,          nldo1200, LDO_1200), | 
|  | 139 | LDO(L10,  "8018_l10",  NULL,          nldo1200, LDO_1200), | 
|  | 140 | LDO(L11,  "8018_l11",  NULL,          nldo1200, LDO_1200), | 
|  | 141 | LDO(L12,  "8018_l12",  NULL,          nldo1200, LDO_1200), | 
|  | 142 | LDO(L13,  "8018_l13",  "8018_l13_pc", pldo,     LDO_50), | 
|  | 143 | LDO(L14,  "8018_l14",  "8018_l14_pc", pldo,     LDO_50), | 
|  | 144 |  | 
|  | 145 | SMPS(S1,  "8018_s1",   "8018_s1_pc",  smps,     SMPS_1500), | 
|  | 146 | SMPS(S2,  "8018_s2",   "8018_s2_pc",  smps,     SMPS_1500), | 
|  | 147 | SMPS(S3,  "8018_s3",   "8018_s3_pc",  smps,     SMPS_1500), | 
|  | 148 | SMPS(S4,  "8018_s4",   "8018_s4_pc",  smps,     SMPS_1500), | 
|  | 149 | SMPS(S5,  "8018_s5",   "8018_s5_pc",  smps,     SMPS_1500), | 
|  | 150 |  | 
|  | 151 | LVS(LVS1, "8018_lvs1", "8018_lvs1_pc"), | 
|  | 152 | }; | 
|  | 153 |  | 
|  | 154 | static const char *pin_control_label[] = { | 
|  | 155 | " D1", | 
|  | 156 | " A0", | 
|  | 157 | " A1", | 
|  | 158 | " A2", | 
|  | 159 | }; | 
|  | 160 |  | 
|  | 161 | static const char *pin_func_label[] = { | 
|  | 162 | [RPM_VREG_PIN_FN_9615_DONT_CARE]	= "don't care", | 
|  | 163 | [RPM_VREG_PIN_FN_9615_ENABLE]		= "on/off", | 
|  | 164 | [RPM_VREG_PIN_FN_9615_MODE]		= "HPM/LPM", | 
|  | 165 | [RPM_VREG_PIN_FN_9615_SLEEP_B]		= "sleep_b", | 
|  | 166 | [RPM_VREG_PIN_FN_9615_NONE]		= "none", | 
|  | 167 | }; | 
|  | 168 |  | 
|  | 169 | static const char *force_mode_label[] = { | 
|  | 170 | [RPM_VREG_FORCE_MODE_9615_NONE]		= "none", | 
|  | 171 | [RPM_VREG_FORCE_MODE_9615_LPM]		= "LPM", | 
|  | 172 | [RPM_VREG_FORCE_MODE_9615_AUTO]		= "auto", | 
|  | 173 | [RPM_VREG_FORCE_MODE_9615_HPM]		= "HPM", | 
|  | 174 | [RPM_VREG_FORCE_MODE_9615_BYPASS]	= "BYP", | 
|  | 175 | }; | 
|  | 176 |  | 
|  | 177 | static const char *power_mode_label[] = { | 
|  | 178 | [RPM_VREG_POWER_MODE_9615_HYSTERETIC]	= "HYS", | 
|  | 179 | [RPM_VREG_POWER_MODE_9615_PWM]		= "PWM", | 
|  | 180 | }; | 
|  | 181 |  | 
|  | 182 | static int is_real_id(int id) | 
|  | 183 | { | 
|  | 184 | return (id >= 0) && (id <= RPM_VREG_ID_PM8018_MAX_REAL); | 
|  | 185 | } | 
|  | 186 |  | 
|  | 187 | static int pc_id_to_real_id(int id) | 
|  | 188 | { | 
|  | 189 | int real_id; | 
|  | 190 |  | 
|  | 191 | if (id >= RPM_VREG_ID_PM8018_L2_PC && id <= RPM_VREG_ID_PM8018_L8_PC) | 
|  | 192 | real_id = id - RPM_VREG_ID_PM8018_L2_PC + RPM_VREG_ID_PM8018_L2; | 
|  | 193 | else | 
|  | 194 | real_id = id - RPM_VREG_ID_PM8018_L13_PC | 
|  | 195 | + RPM_VREG_ID_PM8018_L13; | 
|  | 196 |  | 
|  | 197 | return real_id; | 
|  | 198 | } | 
|  | 199 |  | 
|  | 200 | static struct vreg_config config = { | 
|  | 201 | .vregs			= vregs, | 
|  | 202 | .vregs_len		= ARRAY_SIZE(vregs), | 
|  | 203 |  | 
|  | 204 | .vreg_id_min		= RPM_VREG_ID_PM8018_L2, | 
|  | 205 | .vreg_id_max		= RPM_VREG_ID_PM8018_MAX, | 
|  | 206 |  | 
|  | 207 | .pin_func_none		= RPM_VREG_PIN_FN_9615_NONE, | 
|  | 208 | .pin_func_sleep_b	= RPM_VREG_PIN_FN_9615_SLEEP_B, | 
|  | 209 |  | 
|  | 210 | .mode_lpm		= REGULATOR_MODE_IDLE, | 
|  | 211 | .mode_hpm		= REGULATOR_MODE_NORMAL, | 
|  | 212 |  | 
|  | 213 | .set_points		= all_set_points, | 
|  | 214 | .set_points_len		= ARRAY_SIZE(all_set_points), | 
|  | 215 |  | 
|  | 216 | .label_pin_ctrl		= pin_control_label, | 
|  | 217 | .label_pin_ctrl_len	= ARRAY_SIZE(pin_control_label), | 
|  | 218 | .label_pin_func		= pin_func_label, | 
|  | 219 | .label_pin_func_len	= ARRAY_SIZE(pin_func_label), | 
|  | 220 | .label_force_mode	= force_mode_label, | 
|  | 221 | .label_force_mode_len	= ARRAY_SIZE(force_mode_label), | 
|  | 222 | .label_power_mode	= power_mode_label, | 
|  | 223 | .label_power_mode_len	= ARRAY_SIZE(power_mode_label), | 
|  | 224 |  | 
|  | 225 | .is_real_id		= is_real_id, | 
|  | 226 | .pc_id_to_real_id	= pc_id_to_real_id, | 
|  | 227 | }; | 
|  | 228 |  | 
|  | 229 | struct vreg_config *get_config_9615(void) | 
|  | 230 | { | 
|  | 231 | return &config; | 
|  | 232 | } |