Matt Wagantall | e9b715a | 2012-01-04 18:16:14 -0800 | [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 | #ifndef __ARCH_ARM_MACH_MSM_ACPUCLOCK_KRAIT_H |
| 15 | #define __ARCH_ARM_MACH_MSM_ACPUCLOCK_KRAIT_H |
| 16 | |
Matt Wagantall | 600ea50 | 2012-06-08 18:49:53 -0700 | [diff] [blame] | 17 | #define L2(x) (x) |
Matt Wagantall | e9b715a | 2012-01-04 18:16:14 -0800 | [diff] [blame] | 18 | #define BW_MBPS(_bw) \ |
| 19 | { \ |
| 20 | .vectors = (struct msm_bus_vectors[]){ \ |
| 21 | {\ |
| 22 | .src = MSM_BUS_MASTER_AMPSS_M0, \ |
| 23 | .dst = MSM_BUS_SLAVE_EBI_CH0, \ |
Gagan Mac | b2372ae | 2012-08-20 19:24:32 -0600 | [diff] [blame^] | 24 | .ib = (_bw) * 1000000ULL, \ |
Matt Wagantall | e9b715a | 2012-01-04 18:16:14 -0800 | [diff] [blame] | 25 | }, \ |
| 26 | { \ |
| 27 | .src = MSM_BUS_MASTER_AMPSS_M1, \ |
| 28 | .dst = MSM_BUS_SLAVE_EBI_CH0, \ |
Gagan Mac | b2372ae | 2012-08-20 19:24:32 -0600 | [diff] [blame^] | 29 | .ib = (_bw) * 1000000ULL, \ |
Matt Wagantall | e9b715a | 2012-01-04 18:16:14 -0800 | [diff] [blame] | 30 | }, \ |
| 31 | }, \ |
| 32 | .num_paths = 2, \ |
| 33 | } |
| 34 | |
| 35 | /** |
| 36 | * src_id - Clock source IDs. |
| 37 | */ |
| 38 | enum src_id { |
| 39 | PLL_0 = 0, |
| 40 | HFPLL, |
Matt Wagantall | 06e4a1f | 2012-06-07 18:38:13 -0700 | [diff] [blame] | 41 | PLL_8, |
Matt Wagantall | 488bef3 | 2012-07-13 19:42:11 -0700 | [diff] [blame] | 42 | NUM_SRC_ID |
Matt Wagantall | e9b715a | 2012-01-04 18:16:14 -0800 | [diff] [blame] | 43 | }; |
| 44 | |
| 45 | /** |
| 46 | * enum pvs - IDs to distinguish between CPU frequency tables. |
| 47 | */ |
| 48 | enum pvs { |
| 49 | PVS_SLOW = 0, |
Patrick Daly | 18d2d48 | 2012-08-24 14:22:06 -0700 | [diff] [blame] | 50 | PVS_NOMINAL = 1, |
| 51 | PVS_FAST = 3, |
| 52 | PVS_FASTER = 4, |
| 53 | NUM_PVS = 7 |
Matt Wagantall | e9b715a | 2012-01-04 18:16:14 -0800 | [diff] [blame] | 54 | }; |
| 55 | |
| 56 | /** |
Patrick Daly | 18d2d48 | 2012-08-24 14:22:06 -0700 | [diff] [blame] | 57 | * The maximum number of speed bins. |
| 58 | */ |
| 59 | #define NUM_SPEED_BINS (16) |
| 60 | |
| 61 | /** |
Matt Wagantall | e9b715a | 2012-01-04 18:16:14 -0800 | [diff] [blame] | 62 | * enum scalables - IDs of frequency scalable hardware blocks. |
| 63 | */ |
| 64 | enum scalables { |
| 65 | CPU0 = 0, |
| 66 | CPU1, |
| 67 | CPU2, |
| 68 | CPU3, |
| 69 | L2, |
Matt Wagantall | 488bef3 | 2012-07-13 19:42:11 -0700 | [diff] [blame] | 70 | MAX_SCALABLES |
Matt Wagantall | e9b715a | 2012-01-04 18:16:14 -0800 | [diff] [blame] | 71 | }; |
| 72 | |
| 73 | |
| 74 | /** |
| 75 | * enum hfpll_vdd_level - IDs of HFPLL voltage levels. |
| 76 | */ |
| 77 | enum hfpll_vdd_levels { |
| 78 | HFPLL_VDD_NONE, |
| 79 | HFPLL_VDD_LOW, |
| 80 | HFPLL_VDD_NOM, |
Matt Wagantall | 87465f5 | 2012-07-23 22:03:06 -0700 | [diff] [blame] | 81 | HFPLL_VDD_HIGH, |
Matt Wagantall | e9b715a | 2012-01-04 18:16:14 -0800 | [diff] [blame] | 82 | NUM_HFPLL_VDD |
| 83 | }; |
| 84 | |
| 85 | /** |
| 86 | * enum vregs - IDs of voltage regulators. |
| 87 | */ |
| 88 | enum vregs { |
| 89 | VREG_CORE, |
| 90 | VREG_MEM, |
| 91 | VREG_DIG, |
| 92 | VREG_HFPLL_A, |
| 93 | VREG_HFPLL_B, |
| 94 | NUM_VREG |
| 95 | }; |
| 96 | |
| 97 | /** |
| 98 | * struct vreg - Voltage regulator data. |
| 99 | * @name: Name of requlator. |
| 100 | * @max_vdd: Limit the maximum-settable voltage. |
Matt Wagantall | e9b715a | 2012-01-04 18:16:14 -0800 | [diff] [blame] | 101 | * @reg: Regulator handle. |
Matt Wagantall | 75473eb | 2012-05-31 15:23:22 -0700 | [diff] [blame] | 102 | * @rpm_reg: RPM Regulator handle. |
Matt Wagantall | e9b715a | 2012-01-04 18:16:14 -0800 | [diff] [blame] | 103 | * @cur_vdd: Last-set voltage in uV. |
Matt Wagantall | 6d9c416 | 2012-07-16 18:58:16 -0700 | [diff] [blame] | 104 | * @cur_ua: Last-set current in uA. |
Matt Wagantall | e9b715a | 2012-01-04 18:16:14 -0800 | [diff] [blame] | 105 | */ |
| 106 | struct vreg { |
Matt Wagantall | 75473eb | 2012-05-31 15:23:22 -0700 | [diff] [blame] | 107 | const char *name; |
Matt Wagantall | e9b715a | 2012-01-04 18:16:14 -0800 | [diff] [blame] | 108 | const int max_vdd; |
Matt Wagantall | e9b715a | 2012-01-04 18:16:14 -0800 | [diff] [blame] | 109 | struct regulator *reg; |
Matt Wagantall | 75473eb | 2012-05-31 15:23:22 -0700 | [diff] [blame] | 110 | struct rpm_regulator *rpm_reg; |
Matt Wagantall | e9b715a | 2012-01-04 18:16:14 -0800 | [diff] [blame] | 111 | int cur_vdd; |
Matt Wagantall | 6d9c416 | 2012-07-16 18:58:16 -0700 | [diff] [blame] | 112 | int cur_ua; |
Matt Wagantall | e9b715a | 2012-01-04 18:16:14 -0800 | [diff] [blame] | 113 | }; |
| 114 | |
| 115 | /** |
| 116 | * struct core_speed - Clock tree and configuration parameters. |
| 117 | * @khz: Clock rate in KHz. |
| 118 | * @src: Clock source ID. |
| 119 | * @pri_src_sel: Input to select on the primary MUX. |
Matt Wagantall | e9b715a | 2012-01-04 18:16:14 -0800 | [diff] [blame] | 120 | * @pll_l_val: HFPLL "L" value to be applied when an HFPLL source is selected. |
| 121 | */ |
| 122 | struct core_speed { |
Matt Wagantall | 9c8cb6e | 2012-07-13 19:39:15 -0700 | [diff] [blame] | 123 | unsigned long khz; |
| 124 | int src; |
| 125 | u32 pri_src_sel; |
Matt Wagantall | 9c8cb6e | 2012-07-13 19:39:15 -0700 | [diff] [blame] | 126 | u32 pll_l_val; |
Matt Wagantall | e9b715a | 2012-01-04 18:16:14 -0800 | [diff] [blame] | 127 | }; |
| 128 | |
| 129 | /** |
| 130 | * struct l2_level - L2 clock rate and associated voltage and b/w requirements. |
| 131 | * @speed: L2 clock configuration. |
| 132 | * @vdd_dig: vdd_dig voltage in uV. |
| 133 | * @vdd_mem: vdd_mem voltage in uV. |
| 134 | * @bw_level: Bandwidth performance level number. |
| 135 | */ |
| 136 | struct l2_level { |
| 137 | const struct core_speed speed; |
| 138 | const int vdd_dig; |
| 139 | const int vdd_mem; |
| 140 | const unsigned int bw_level; |
| 141 | }; |
| 142 | |
| 143 | /** |
| 144 | * struct acpu_level - CPU clock rate and L2 rate and voltage requirements. |
| 145 | * @use_for_scaling: Flag indicating whether or not the level should be used. |
| 146 | * @speed: CPU clock configuration. |
| 147 | * @l2_level: L2 configuration to use. |
| 148 | * @vdd_core: CPU core voltage in uV. |
Matt Wagantall | 6d9c416 | 2012-07-16 18:58:16 -0700 | [diff] [blame] | 149 | * @ua_core: CPU core current consumption in uA. |
Stephen Boyd | a86214a | 2012-09-14 11:25:34 -0700 | [diff] [blame] | 150 | * @avsdscr_setting: AVS DSCR configuration. |
Matt Wagantall | e9b715a | 2012-01-04 18:16:14 -0800 | [diff] [blame] | 151 | */ |
| 152 | struct acpu_level { |
| 153 | const int use_for_scaling; |
| 154 | const struct core_speed speed; |
Matt Wagantall | 600ea50 | 2012-06-08 18:49:53 -0700 | [diff] [blame] | 155 | const unsigned int l2_level; |
Matt Wagantall | 06e4a1f | 2012-06-07 18:38:13 -0700 | [diff] [blame] | 156 | int vdd_core; |
Matt Wagantall | 6d9c416 | 2012-07-16 18:58:16 -0700 | [diff] [blame] | 157 | int ua_core; |
Stephen Boyd | a86214a | 2012-09-14 11:25:34 -0700 | [diff] [blame] | 158 | unsigned int avsdscr_setting; |
Matt Wagantall | e9b715a | 2012-01-04 18:16:14 -0800 | [diff] [blame] | 159 | }; |
| 160 | |
| 161 | /** |
| 162 | * struct hfpll_data - Descriptive data of HFPLL hardware. |
| 163 | * @mode_offset: Mode register offset from base address. |
| 164 | * @l_offset: "L" value register offset from base address. |
| 165 | * @m_offset: "M" value register offset from base address. |
| 166 | * @n_offset: "N" value register offset from base address. |
| 167 | * @config_offset: Configuration register offset from base address. |
| 168 | * @config_val: Value to initialize the @config_offset register to. |
Matt Wagantall | a77b7f3 | 2012-07-18 16:32:01 -0700 | [diff] [blame] | 169 | * @has_user_reg: Indicates the presence of an addition config register. |
| 170 | * @user_offset: User register offset from base address, if applicable. |
| 171 | * @user_val: Value to initialize the @user_offset register to. |
| 172 | * @user_vco_mask: Bit in the @user_offset to enable high-frequency VCO mode. |
Matt Wagantall | 06e4a1f | 2012-06-07 18:38:13 -0700 | [diff] [blame] | 173 | * @has_droop_ctl: Indicates the presence of a voltage droop controller. |
| 174 | * @droop_offset: Droop controller register offset from base address. |
| 175 | * @droop_val: Value to initialize the @config_offset register to. |
| 176 | * @low_vdd_l_max: Maximum "L" value supported at HFPLL_VDD_LOW. |
Matt Wagantall | 87465f5 | 2012-07-23 22:03:06 -0700 | [diff] [blame] | 177 | * @nom_vdd_l_max: Maximum "L" value supported at HFPLL_VDD_NOM. |
Matt Wagantall | a77b7f3 | 2012-07-18 16:32:01 -0700 | [diff] [blame] | 178 | * @low_vco_l_max: Maximum "L" value supported in low-frequency VCO mode. |
Matt Wagantall | 1f3762d | 2012-06-08 19:08:48 -0700 | [diff] [blame] | 179 | * @vdd: voltage requirements for each VDD level for the L2 PLL. |
Matt Wagantall | e9b715a | 2012-01-04 18:16:14 -0800 | [diff] [blame] | 180 | */ |
| 181 | struct hfpll_data { |
| 182 | const u32 mode_offset; |
| 183 | const u32 l_offset; |
| 184 | const u32 m_offset; |
| 185 | const u32 n_offset; |
| 186 | const u32 config_offset; |
| 187 | const u32 config_val; |
Matt Wagantall | a77b7f3 | 2012-07-18 16:32:01 -0700 | [diff] [blame] | 188 | const bool has_user_reg; |
| 189 | const u32 user_offset; |
| 190 | const u32 user_val; |
| 191 | const u32 user_vco_mask; |
Matt Wagantall | 06e4a1f | 2012-06-07 18:38:13 -0700 | [diff] [blame] | 192 | const bool has_droop_ctl; |
| 193 | const u32 droop_offset; |
| 194 | const u32 droop_val; |
Patrick Daly | 18d2d48 | 2012-08-24 14:22:06 -0700 | [diff] [blame] | 195 | u32 low_vdd_l_max; |
| 196 | u32 nom_vdd_l_max; |
Matt Wagantall | a77b7f3 | 2012-07-18 16:32:01 -0700 | [diff] [blame] | 197 | const u32 low_vco_l_max; |
Matt Wagantall | e9b715a | 2012-01-04 18:16:14 -0800 | [diff] [blame] | 198 | const int vdd[NUM_HFPLL_VDD]; |
| 199 | }; |
| 200 | |
| 201 | /** |
| 202 | * struct scalable - Register locations and state associated with a scalable HW. |
| 203 | * @hfpll_phys_base: Physical base address of HFPLL register. |
| 204 | * @hfpll_base: Virtual base address of HFPLL registers. |
Matt Wagantall | 06e4a1f | 2012-06-07 18:38:13 -0700 | [diff] [blame] | 205 | * @aux_clk_sel_phys: Physical address of auxiliary MUX. |
Matt Wagantall | e9b715a | 2012-01-04 18:16:14 -0800 | [diff] [blame] | 206 | * @aux_clk_sel: Auxiliary mux input to select at boot. |
Matt Wagantall | 6cd5d75 | 2012-09-27 19:56:57 -0700 | [diff] [blame] | 207 | * @sec_clk_sel: Secondary mux input to select at boot. |
Matt Wagantall | e9b715a | 2012-01-04 18:16:14 -0800 | [diff] [blame] | 208 | * @l2cpmr_iaddr: Indirect address of the CPMR MUX/divider CP15 register. |
Matt Wagantall | e9b715a | 2012-01-04 18:16:14 -0800 | [diff] [blame] | 209 | * @cur_speed: Pointer to currently-set speed. |
| 210 | * @l2_vote: L2 performance level vote associate with the current CPU speed. |
| 211 | * @vreg: Array of voltage regulators needed by the scalable. |
Matt Wagantall | 754ee27 | 2012-06-18 13:40:26 -0700 | [diff] [blame] | 212 | * @initialized: Flag set to true when per_cpu_init() has been called. |
Stephen Boyd | a86214a | 2012-09-14 11:25:34 -0700 | [diff] [blame] | 213 | * @avs_enabled: True if avs is enabled for the scalabale. False otherwise. |
Matt Wagantall | e9b715a | 2012-01-04 18:16:14 -0800 | [diff] [blame] | 214 | */ |
| 215 | struct scalable { |
Matt Wagantall | 06e4a1f | 2012-06-07 18:38:13 -0700 | [diff] [blame] | 216 | const phys_addr_t hfpll_phys_base; |
Matt Wagantall | e9b715a | 2012-01-04 18:16:14 -0800 | [diff] [blame] | 217 | void __iomem *hfpll_base; |
Matt Wagantall | 06e4a1f | 2012-06-07 18:38:13 -0700 | [diff] [blame] | 218 | const phys_addr_t aux_clk_sel_phys; |
Matt Wagantall | e9b715a | 2012-01-04 18:16:14 -0800 | [diff] [blame] | 219 | const u32 aux_clk_sel; |
Matt Wagantall | 6cd5d75 | 2012-09-27 19:56:57 -0700 | [diff] [blame] | 220 | const u32 sec_clk_sel; |
Matt Wagantall | e9b715a | 2012-01-04 18:16:14 -0800 | [diff] [blame] | 221 | const u32 l2cpmr_iaddr; |
Matt Wagantall | e9b715a | 2012-01-04 18:16:14 -0800 | [diff] [blame] | 222 | const struct core_speed *cur_speed; |
Matt Wagantall | 600ea50 | 2012-06-08 18:49:53 -0700 | [diff] [blame] | 223 | unsigned int l2_vote; |
Matt Wagantall | e9b715a | 2012-01-04 18:16:14 -0800 | [diff] [blame] | 224 | struct vreg vreg[NUM_VREG]; |
Matt Wagantall | 754ee27 | 2012-06-18 13:40:26 -0700 | [diff] [blame] | 225 | bool initialized; |
Stephen Boyd | a86214a | 2012-09-14 11:25:34 -0700 | [diff] [blame] | 226 | bool avs_enabled; |
Matt Wagantall | e9b715a | 2012-01-04 18:16:14 -0800 | [diff] [blame] | 227 | }; |
| 228 | |
| 229 | /** |
Matt Wagantall | 1f3762d | 2012-06-08 19:08:48 -0700 | [diff] [blame] | 230 | * struct pvs_table - CPU performance level table and size. |
| 231 | * @table: CPU performance level table |
| 232 | * @size: sizeof(@table) |
Matt Wagantall | 9515bc2 | 2012-07-19 18:13:40 -0700 | [diff] [blame] | 233 | * @boost_uv: Voltage boost amount |
Matt Wagantall | 1f3762d | 2012-06-08 19:08:48 -0700 | [diff] [blame] | 234 | */ |
| 235 | struct pvs_table { |
| 236 | struct acpu_level *table; |
| 237 | size_t size; |
Matt Wagantall | 9515bc2 | 2012-07-19 18:13:40 -0700 | [diff] [blame] | 238 | int boost_uv; |
Matt Wagantall | 1f3762d | 2012-06-08 19:08:48 -0700 | [diff] [blame] | 239 | }; |
| 240 | |
| 241 | /** |
Matt Wagantall | e9b715a | 2012-01-04 18:16:14 -0800 | [diff] [blame] | 242 | * struct acpuclk_krait_params - SoC specific driver parameters. |
| 243 | * @scalable: Array of scalables. |
Matt Wagantall | 1f3762d | 2012-06-08 19:08:48 -0700 | [diff] [blame] | 244 | * @scalable_size: Size of @scalable. |
| 245 | * @hfpll_data: HFPLL configuration data. |
Patrick Daly | 18d2d48 | 2012-08-24 14:22:06 -0700 | [diff] [blame] | 246 | * @pvs_tables: 2D array of CPU frequency tables. |
Matt Wagantall | e9b715a | 2012-01-04 18:16:14 -0800 | [diff] [blame] | 247 | * @l2_freq_tbl: L2 frequency table. |
Matt Wagantall | 1f3762d | 2012-06-08 19:08:48 -0700 | [diff] [blame] | 248 | * @l2_freq_tbl_size: Size of @l2_freq_tbl. |
Matt Wagantall | ee2b437 | 2012-09-17 17:51:06 -0700 | [diff] [blame] | 249 | * @pte_efuse_phys: Physical address of PTE EFUSE. |
Matt Wagantall | 1f3762d | 2012-06-08 19:08:48 -0700 | [diff] [blame] | 250 | * @bus_scale: MSM bus driver parameters. |
Matt Wagantall | b7c231b | 2012-07-24 18:40:17 -0700 | [diff] [blame] | 251 | * @stby_khz: KHz value corresponding to an always-on clock source. |
Matt Wagantall | e9b715a | 2012-01-04 18:16:14 -0800 | [diff] [blame] | 252 | */ |
| 253 | struct acpuclk_krait_params { |
| 254 | struct scalable *scalable; |
Matt Wagantall | 1f3762d | 2012-06-08 19:08:48 -0700 | [diff] [blame] | 255 | size_t scalable_size; |
| 256 | struct hfpll_data *hfpll_data; |
Patrick Daly | 18d2d48 | 2012-08-24 14:22:06 -0700 | [diff] [blame] | 257 | struct pvs_table (*pvs_tables)[NUM_PVS]; |
Matt Wagantall | 1f3762d | 2012-06-08 19:08:48 -0700 | [diff] [blame] | 258 | struct l2_level *l2_freq_tbl; |
| 259 | size_t l2_freq_tbl_size; |
Matt Wagantall | ee2b437 | 2012-09-17 17:51:06 -0700 | [diff] [blame] | 260 | phys_addr_t pte_efuse_phys; |
Matt Wagantall | 1f3762d | 2012-06-08 19:08:48 -0700 | [diff] [blame] | 261 | struct msm_bus_scale_pdata *bus_scale; |
Matt Wagantall | b7c231b | 2012-07-24 18:40:17 -0700 | [diff] [blame] | 262 | unsigned long stby_khz; |
Matt Wagantall | e9b715a | 2012-01-04 18:16:14 -0800 | [diff] [blame] | 263 | }; |
| 264 | |
| 265 | /** |
Matt Wagantall | 488bef3 | 2012-07-13 19:42:11 -0700 | [diff] [blame] | 266 | * struct drv_data - Driver state |
| 267 | * @acpu_freq_tbl: CPU frequency table. |
| 268 | * @l2_freq_tbl: L2 frequency table. |
| 269 | * @scalable: Array of scalables (CPUs and L2). |
| 270 | * @hfpll_data: High-frequency PLL data. |
| 271 | * @bus_perf_client: Bus driver client handle. |
| 272 | * @bus_scale: Bus driver scaling data. |
| 273 | * @boost_uv: Voltage boost amount |
| 274 | * @speed_bin: Speed bin ID. |
| 275 | * @pvs_bin: PVS bin ID. |
| 276 | * @dev: Device. |
| 277 | */ |
| 278 | struct drv_data { |
| 279 | struct acpu_level *acpu_freq_tbl; |
| 280 | const struct l2_level *l2_freq_tbl; |
| 281 | struct scalable *scalable; |
| 282 | struct hfpll_data *hfpll_data; |
| 283 | u32 bus_perf_client; |
| 284 | struct msm_bus_scale_pdata *bus_scale; |
| 285 | int boost_uv; |
| 286 | int speed_bin; |
| 287 | int pvs_bin; |
| 288 | struct device *dev; |
| 289 | }; |
| 290 | |
| 291 | /** |
Patrick Daly | 037d491 | 2012-08-28 13:36:31 -0700 | [diff] [blame] | 292 | * struct acpuclk_platform_data - PMIC configuration data. |
| 293 | * @uses_pm8917: Boolean indicates presence of pm8917. |
| 294 | */ |
| 295 | struct acpuclk_platform_data { |
| 296 | bool uses_pm8917; |
| 297 | }; |
| 298 | |
| 299 | /** |
Matt Wagantall | e9b715a | 2012-01-04 18:16:14 -0800 | [diff] [blame] | 300 | * acpuclk_krait_init - Initialize the Krait CPU clock driver give SoC params. |
| 301 | */ |
| 302 | extern int acpuclk_krait_init(struct device *dev, |
| 303 | const struct acpuclk_krait_params *params); |
Matt Wagantall | 488bef3 | 2012-07-13 19:42:11 -0700 | [diff] [blame] | 304 | |
| 305 | #ifdef CONFIG_DEBUG_FS |
| 306 | /** |
| 307 | * acpuclk_krait_debug_init - Initialize debugfs interface. |
| 308 | */ |
| 309 | extern void __init acpuclk_krait_debug_init(struct drv_data *drv); |
| 310 | #else |
| 311 | static inline void acpuclk_krait_debug_init(void) { } |
| 312 | #endif |
| 313 | |
Matt Wagantall | e9b715a | 2012-01-04 18:16:14 -0800 | [diff] [blame] | 314 | #endif |