| /* SPDX-License-Identifier: GPL-2.0-only */ |
| /* |
| * Copyright (c) 2015-2020, The Linux Foundation. All rights reserved. |
| */ |
| |
| #ifndef __REGULATOR_CPR3_REGULATOR_H__ |
| #define __REGULATOR_CPR3_REGULATOR_H__ |
| |
| #include <linux/clk.h> |
| #include <linux/mutex.h> |
| #include <linux/of.h> |
| #include <linux/platform_device.h> |
| #include <linux/types.h> |
| #include <soc/qcom/apm.h> |
| #include <linux/regulator/driver.h> |
| #include <linux/regulator/msm-ldo-regulator.h> |
| |
| struct cpr3_controller; |
| struct cpr3_thread; |
| |
| /** |
| * struct cpr3_fuse_param - defines one contiguous segment of a fuse parameter |
| * that is contained within a given row. |
| * @row: Fuse row number |
| * @bit_start: The first bit within the row of the fuse parameter segment |
| * @bit_end: The last bit within the row of the fuse parameter segment |
| * |
| * Each fuse row is 64 bits in length. bit_start and bit_end may take values |
| * from 0 to 63. bit_start must be less than or equal to bit_end. |
| */ |
| struct cpr3_fuse_param { |
| unsigned int row; |
| unsigned int bit_start; |
| unsigned int bit_end; |
| }; |
| |
| /* Each CPR3 sensor has 16 ring oscillators */ |
| #define CPR3_RO_COUNT 16 |
| |
| /* The maximum number of sensors that can be present on a single CPR loop. */ |
| #define CPR3_MAX_SENSOR_COUNT 256 |
| |
| /* This constant is used when allocating array printing buffers. */ |
| #define MAX_CHARS_PER_INT 10 |
| |
| /** |
| * struct cpr4_sdelta - CPR4 controller specific data structure for the sdelta |
| * adjustment table which is used to adjust the VDD supply |
| * voltage automatically based upon the temperature and/or |
| * the number of online CPU cores. |
| * @allow_core_count_adj: Core count adjustments are allowed. |
| * @allow_temp_adj: Temperature based adjustments are allowed. |
| * @max_core_count: Maximum number of cores considered for core count |
| * adjustment logic. |
| * @temp_band_count: Number of temperature bands considered for temperature |
| * based adjustment logic. |
| * @cap_volt: CAP in uV to apply to SDELTA margins with multiple |
| * cpr3-regulators defined for single controller. |
| * @table: SDELTA table with per-online-core and temperature based |
| * adjustments of size (max_core_count * temp_band_count) |
| * Outer: core count |
| * Inner: temperature band |
| * Each element has units of VDD supply steps. Positive |
| * values correspond to a reduction in voltage and negative |
| * value correspond to an increase (this follows the SDELTA |
| * register semantics). |
| * @allow_boost: Voltage boost allowed. |
| * @boost_num_cores: The number of online cores at which the boost voltage |
| * adjustments will be applied |
| * @boost_table: SDELTA table with boost voltage adjustments of size |
| * temp_band_count. Each element has units of VDD supply |
| * steps. Positive values correspond to a reduction in |
| * voltage and negative value correspond to an increase |
| * (this follows the SDELTA register semantics). |
| */ |
| struct cpr4_sdelta { |
| bool allow_core_count_adj; |
| bool allow_temp_adj; |
| int max_core_count; |
| int temp_band_count; |
| int cap_volt; |
| int *table; |
| bool allow_boost; |
| int boost_num_cores; |
| int *boost_table; |
| }; |
| |
| /** |
| * struct cpr3_corner - CPR3 virtual voltage corner data structure |
| * @floor_volt: CPR closed-loop floor voltage in microvolts |
| * @ceiling_volt: CPR closed-loop ceiling voltage in microvolts |
| * @open_loop_volt: CPR open-loop voltage (i.e. initial voltage) in |
| * microvolts |
| * @last_volt: Last known settled CPR closed-loop voltage which is used |
| * when switching to a new corner |
| * @abs_ceiling_volt: The absolute CPR closed-loop ceiling voltage in |
| * microvolts. This is used to limit the ceiling_volt |
| * value when it is increased as a result of aging |
| * adjustment. |
| * @unaged_floor_volt: The CPR closed-loop floor voltage in microvolts before |
| * any aging adjustment is performed |
| * @unaged_ceiling_volt: The CPR closed-loop ceiling voltage in microvolts |
| * before any aging adjustment is performed |
| * @unaged_open_loop_volt: The CPR open-loop voltage (i.e. initial voltage) in |
| * microvolts before any aging adjusment is performed |
| * @system_volt: The system-supply voltage in microvolts or corners or |
| * levels |
| * @mem_acc_volt: The mem-acc-supply voltage in corners |
| * @proc_freq: Processor frequency in Hertz. For CPR rev. 3 and 4 |
| * conrollers, this field is only used by platform specific |
| * CPR3 driver for interpolation. For CPRh-compliant |
| * controllers, this frequency is also utilized by the |
| * clock driver to determine the corner to CPU clock |
| * frequency mappings. |
| * @cpr_fuse_corner: Fused corner index associated with this virtual corner |
| * (only used by platform specific CPR3 driver for |
| * mapping purposes) |
| * @target_quot: Array of target quotient values to use for each ring |
| * oscillator (RO) for this corner. A value of 0 should be |
| * specified as the target quotient for each RO that is |
| * unused by this corner. |
| * @ro_scale: Array of CPR ring oscillator (RO) scaling factors. The |
| * scaling factor for each RO is defined from RO0 to RO15 |
| * with units of QUOT/V. A value of 0 may be specified for |
| * an RO that is unused. |
| * @ro_mask: Bitmap where each of the 16 LSBs indicate if the |
| * corresponding ROs should be masked for this corner |
| * @irq_en: Bitmap of the CPR interrupts to enable for this corner |
| * @aging_derate: The amount to derate the aging voltage adjustment |
| * determined for the reference corner in units of uV/mV. |
| * E.g. a value of 900 would imply that the adjustment for |
| * this corner should be 90% (900/1000) of that for the |
| * reference corner. |
| * @use_open_loop: Boolean indicating that open-loop (i.e CPR disabled) as |
| * opposed to closed-loop operation must be used for this |
| * corner on CPRh controllers. |
| * @ldo_mode_allowed: Boolean which indicates if LDO mode is allowed for this |
| * corner. This field is applicable for CPR4 controllers |
| * that manage LDO300 supply regulator. |
| * @sdelta: The CPR4 controller specific data for this corner. This |
| * field is applicable for CPR4 controllers. |
| * |
| * The value of last_volt is initialized inside of the cpr3_regulator_register() |
| * call with the open_loop_volt value. It can later be updated to the settled |
| * VDD supply voltage. The values for unaged_floor_volt, unaged_ceiling_volt, |
| * and unaged_open_loop_volt are initialized inside of cpr3_regulator_register() |
| * if ctrl->aging_required == true. These three values must be pre-initialized |
| * if cpr3_regulator_register() is called with ctrl->aging_required == false and |
| * ctrl->aging_succeeded == true. |
| * |
| * The values of ro_mask and irq_en are initialized inside of the |
| * cpr3_regulator_register() call. |
| */ |
| struct cpr3_corner { |
| int floor_volt; |
| int ceiling_volt; |
| int open_loop_volt; |
| int last_volt; |
| int abs_ceiling_volt; |
| int unaged_floor_volt; |
| int unaged_ceiling_volt; |
| int unaged_open_loop_volt; |
| int system_volt; |
| int mem_acc_volt; |
| u32 proc_freq; |
| int cpr_fuse_corner; |
| u32 target_quot[CPR3_RO_COUNT]; |
| u32 ro_scale[CPR3_RO_COUNT]; |
| u32 ro_mask; |
| u32 irq_en; |
| int aging_derate; |
| bool use_open_loop; |
| bool ldo_mode_allowed; |
| struct cpr4_sdelta *sdelta; |
| }; |
| |
| /** |
| * struct cprh_corner_band - CPRh controller specific data structure which |
| * encapsulates the range of corners and the SDELTA |
| * adjustment table to be applied to the corners within |
| * the min and max bounds of the corner band. |
| * @corner: Corner number which defines the corner band boundary |
| * @sdelta: The SDELTA adjustment table which contains core-count |
| * and temp based margin adjustments that are applicable |
| * to the corner band. |
| */ |
| struct cprh_corner_band { |
| int corner; |
| struct cpr4_sdelta *sdelta; |
| }; |
| |
| /** |
| * enum cpr3_ldo_type - Constants which define the LDO supply regulator |
| * types used to manage the subsystem component rail voltage. |
| * %CPR3_LDO_KRYO: Kryo LDO regulator used to sub-regulate the HMSS |
| * per-cluster voltage. |
| * %CPR3_LDO300: LDO regulator used to sub-regulate the GFX voltage. |
| */ |
| enum cpr3_ldo_type { |
| CPR3_LDO_KRYO = 0, |
| CPR3_LDO300 = 1, |
| }; |
| |
| /** |
| * struct cpr3_regulator - CPR3 logical regulator instance associated with a |
| * given CPR3 hardware thread |
| * @of_node: Device node associated with the device tree child node |
| * of this CPR3 regulator |
| * @thread: Pointer to the CPR3 thread which manages this CPR3 |
| * regulator |
| * @name: Unique name for this CPR3 regulator which is filled |
| * using the device tree regulator-name property |
| * @rdesc: Regulator description for this CPR3 regulator |
| * @rdev: Regulator device pointer for the regulator registered |
| * for this CPR3 regulator |
| * @mem_acc_regulator: Pointer to the optional mem-acc supply regulator used |
| * to manage memory circuitry settings based upon CPR3 |
| * regulator output voltage. |
| * @ldo_regulator: Pointer to the LDO supply regulator used to manage |
| * per-cluster LDO voltage and bypass state |
| * @ldo_regulator_bypass: Cached copy of the LDO regulator bypass state |
| * @ldo_ret_regulator: Pointer to the LDO retention supply regulator used to |
| * manage LDO retention bypass state |
| * @corner: Array of all corners supported by this CPR3 regulator |
| * @corner_count: The number of elements in the corner array |
| * @corner_band: Array of all corner bands supported by CPRh compatible |
| * controllers |
| * @corner_band_count: The number of elements in the corner band array |
| * @platform_fuses: Pointer to platform specific CPR fuse data (only used by |
| * platform specific CPR3 driver) |
| * @speed_bin_fuse: Value read from the speed bin fuse parameter |
| * @speed_bins_supported: The number of speed bins supported by the device tree |
| * configuration for this CPR3 regulator |
| * @cpr_rev_fuse: Value read from the CPR fusing revision fuse parameter |
| * @fuse_combo: Platform specific enum value identifying the specific |
| * combination of fuse values found on a given chip |
| * @fuse_combos_supported: The number of fuse combinations supported by the |
| * device tree configuration for this CPR3 regulator |
| * @fuse_corner_count: Number of corners defined by fuse parameters |
| * @fuse_corner_map: Array of length fuse_corner_count which specifies the |
| * highest corner associated with each fuse corner. Note |
| * that each element must correspond to a valid corner |
| * and that element values must be strictly increasing. |
| * Also, it is acceptable for the lowest fuse corner to map |
| * to a corner other than the lowest. Likewise, it is |
| * acceptable for the highest fuse corner to map to a |
| * corner other than the highest. |
| * @fuse_combo_corner_sum: The sum of the corner counts across all fuse combos |
| * @fuse_combo_offset: The device tree property array offset for the selected |
| * fuse combo |
| * @speed_bin_corner_sum: The sum of the corner counts across all speed bins |
| * This may be specified as 0 if per speed bin parsing |
| * support is not required. |
| * @speed_bin_offset: The device tree property array offset for the selected |
| * speed bin |
| * @fuse_combo_corner_band_sum: The sum of the corner band counts across all |
| * fuse combos |
| * @fuse_combo_corner_band_offset: The device tree property array offset for |
| * the corner band count corresponding to the selected |
| * fuse combo |
| * @speed_bin_corner_band_sum: The sum of the corner band counts across all |
| * speed bins. This may be specified as 0 if per speed bin |
| * parsing support is not required |
| * @speed_bin_corner_band_offset: The device tree property array offset for the |
| * corner band count corresponding to the selected speed |
| * bin |
| * @pd_bypass_mask: Bit mask of power domains associated with this CPR3 |
| * regulator |
| * @dynamic_floor_corner: Index identifying the voltage corner for the CPR3 |
| * regulator whose last_volt value should be used as the |
| * global CPR floor voltage if all of the power domains |
| * associated with this CPR3 regulator are bypassed |
| * @uses_dynamic_floor: Boolean flag indicating that dynamic_floor_corner should |
| * be utilized for the CPR3 regulator |
| * @current_corner: Index identifying the currently selected voltage corner |
| * for the CPR3 regulator or less than 0 if no corner has |
| * been requested |
| * @last_closed_loop_corner: Index identifying the last voltage corner for the |
| * CPR3 regulator which was configured when operating in |
| * CPR closed-loop mode or less than 0 if no corner has |
| * been requested. CPR registers are only written to when |
| * using closed-loop mode. |
| * @aggregated: Boolean flag indicating that this CPR3 regulator |
| * participated in the last aggregation event |
| * @debug_corner: Index identifying voltage corner used for displaying |
| * corner configuration values in debugfs |
| * @ldo_type: LDO regulator type. |
| * @ldo_min_headroom_volt: Minimum voltage difference in microvolts required |
| * between the VDD supply voltage and the LDO output in |
| * order for the LDO operate |
| * @ldo_max_headroom_volt: Maximum voltage difference in microvolts between |
| * the input and output of the active LDO hardware to |
| * maintain optimum operability. |
| * @ldo_adjust_volt: Voltage in microvolts used to offset margin assigned |
| * to IR drop between PMIC and CPU |
| * @ldo_ret_volt: The lowest supported CPU retention voltage in |
| * microvolts. This voltage may vary part-to-part based |
| * upon the value of hardware fuses. |
| * @ldo_max_volt: The maximum physically supported LDO voltage in |
| * microvolts |
| * @ldo_mode_allowed: Boolean which indicates if LDO mode is allowed for this |
| * CPR3 regulator |
| * @vreg_enabled: Boolean defining the enable state of the CPR3 |
| * regulator's regulator within the regulator framework. |
| * @aging_allowed: Boolean defining if CPR aging adjustments are allowed |
| * for this CPR3 regulator given the fuse combo of the |
| * device |
| * @aging_allow_open_loop_adj: Boolean defining if the open-loop voltage of each |
| * corner of this regulator should be adjusted as a result |
| * of an aging measurement. This flag can be set to false |
| * when the open-loop voltage adjustments have been |
| * specified such that they include the maximum possible |
| * aging adjustment. This flag is only used if |
| * aging_allowed == true. |
| * @aging_corner: The corner that should be configured for this regulator |
| * when an aging measurement is performed. |
| * @aging_max_adjust_volt: The maximum aging voltage margin in microvolts that |
| * may be added to the target quotients of this regulator. |
| * A value of 0 may be specified if this regulator does not |
| * require any aging adjustment. |
| * @allow_core_count_adj: Core count adjustments are allowed for this regulator. |
| * @allow_temp_adj: Temperature based adjustments are allowed for this |
| * regulator. |
| * @max_core_count: Maximum number of cores considered for core count |
| * adjustment logic. |
| * @allow_boost: Voltage boost allowed for this regulator. |
| * |
| * This structure contains both configuration and runtime state data. The |
| * elements current_corner, last_closed_loop_corner, aggregated, debug_corner, |
| * ldo_mode_allowed, and vreg_enabled are state variables. |
| */ |
| struct cpr3_regulator { |
| struct device_node *of_node; |
| struct cpr3_thread *thread; |
| const char *name; |
| struct regulator_desc rdesc; |
| struct regulator_dev *rdev; |
| struct regulator *mem_acc_regulator; |
| struct regulator *ldo_regulator; |
| enum msm_ldo_supply_mode ldo_regulator_bypass; |
| struct regulator *ldo_ret_regulator; |
| struct cpr3_corner *corner; |
| int corner_count; |
| struct cprh_corner_band *corner_band; |
| u32 corner_band_count; |
| |
| void *platform_fuses; |
| int speed_bin_fuse; |
| int speed_bins_supported; |
| int cpr_rev_fuse; |
| int fuse_combo; |
| int fuse_combos_supported; |
| int fuse_corner_count; |
| int *fuse_corner_map; |
| int fuse_combo_corner_sum; |
| int fuse_combo_offset; |
| int speed_bin_corner_sum; |
| int speed_bin_offset; |
| int fuse_combo_corner_band_sum; |
| int fuse_combo_corner_band_offset; |
| int speed_bin_corner_band_sum; |
| int speed_bin_corner_band_offset; |
| u32 pd_bypass_mask; |
| int dynamic_floor_corner; |
| bool uses_dynamic_floor; |
| |
| int current_corner; |
| int last_closed_loop_corner; |
| bool aggregated; |
| int debug_corner; |
| enum cpr3_ldo_type ldo_type; |
| int ldo_min_headroom_volt; |
| int ldo_max_headroom_volt; |
| int ldo_adjust_volt; |
| int ldo_ret_volt; |
| int ldo_max_volt; |
| bool ldo_mode_allowed; |
| bool vreg_enabled; |
| |
| bool aging_allowed; |
| bool aging_allow_open_loop_adj; |
| int aging_corner; |
| int aging_max_adjust_volt; |
| |
| bool allow_core_count_adj; |
| bool allow_temp_adj; |
| int max_core_count; |
| bool allow_boost; |
| }; |
| |
| /** |
| * struct cpr3_thread - CPR3 hardware thread data structure |
| * @thread_id: Hardware thread ID |
| * @of_node: Device node associated with the device tree child node |
| * of this CPR3 thread |
| * @ctrl: Pointer to the CPR3 controller which manages this thread |
| * @vreg: Array of CPR3 regulators handled by the CPR3 thread |
| * @vreg_count: Number of elements in the vreg array |
| * @aggr_corner: CPR corner containing the in process aggregated voltage |
| * and target quotient configurations which will be applied |
| * @last_closed_loop_aggr_corner: CPR corner containing the most recent |
| * configurations which were written into hardware |
| * registers when operating in closed loop mode (i.e. with |
| * CPR enabled) |
| * @consecutive_up: The number of consecutive CPR step up events needed to |
| * to trigger an up interrupt |
| * @consecutive_down: The number of consecutive CPR step down events needed to |
| * to trigger a down interrupt |
| * @up_threshold: The number CPR error steps required to generate an up |
| * event |
| * @down_threshold: The number CPR error steps required to generate a down |
| * event |
| * |
| * This structure contains both configuration and runtime state data. The |
| * elements aggr_corner and last_closed_loop_aggr_corner are state variables. |
| */ |
| struct cpr3_thread { |
| u32 thread_id; |
| struct device_node *of_node; |
| struct cpr3_controller *ctrl; |
| struct cpr3_regulator *vreg; |
| int vreg_count; |
| struct cpr3_corner aggr_corner; |
| struct cpr3_corner last_closed_loop_aggr_corner; |
| |
| u32 consecutive_up; |
| u32 consecutive_down; |
| u32 up_threshold; |
| u32 down_threshold; |
| }; |
| |
| /* Per CPR controller data */ |
| /** |
| * enum cpr3_mem_acc_corners - Constants which define the number of mem-acc |
| * regulator corners available in the mem-acc corner map array. |
| * %CPR3_MEM_ACC_LOW_CORNER: Index in mem-acc corner map array mapping to the |
| * mem-acc regulator corner |
| * to be used for low voltage vdd supply |
| * %CPR3_MEM_ACC_HIGH_CORNER: Index in mem-acc corner map array mapping to the |
| * mem-acc regulator corner to be used for high |
| * voltage vdd supply |
| * %CPR3_MEM_ACC_CORNERS: Number of elements in the mem-acc corner map |
| * array |
| */ |
| enum cpr3_mem_acc_corners { |
| CPR3_MEM_ACC_LOW_CORNER = 0, |
| CPR3_MEM_ACC_HIGH_CORNER = 1, |
| CPR3_MEM_ACC_CORNERS = 2, |
| }; |
| |
| /** |
| * enum cpr3_count_mode - CPR3 controller count mode which defines the |
| * method that CPR sensor data is acquired |
| * %CPR3_COUNT_MODE_ALL_AT_ONCE_MIN: Capture all CPR sensor readings |
| * simultaneously and report the minimum |
| * value seen in successive measurements |
| * %CPR3_COUNT_MODE_ALL_AT_ONCE_MAX: Capture all CPR sensor readings |
| * simultaneously and report the maximum |
| * value seen in successive measurements |
| * %CPR3_COUNT_MODE_STAGGERED: Read one sensor at a time in a |
| * sequential fashion |
| * %CPR3_COUNT_MODE_ALL_AT_ONCE_AGE: Capture all CPR aging sensor readings |
| * simultaneously. |
| */ |
| enum cpr3_count_mode { |
| CPR3_COUNT_MODE_ALL_AT_ONCE_MIN = 0, |
| CPR3_COUNT_MODE_ALL_AT_ONCE_MAX = 1, |
| CPR3_COUNT_MODE_STAGGERED = 2, |
| CPR3_COUNT_MODE_ALL_AT_ONCE_AGE = 3, |
| }; |
| |
| /** |
| * enum cpr_controller_type - supported CPR controller hardware types |
| * %CPR_CTRL_TYPE_CPR3: HW has CPR3 controller |
| * %CPR_CTRL_TYPE_CPR4: HW has CPR4 controller |
| * %CPR_CTRL_TYPE_CPRH: HW has CPRh controller |
| */ |
| enum cpr_controller_type { |
| CPR_CTRL_TYPE_CPR3, |
| CPR_CTRL_TYPE_CPR4, |
| CPR_CTRL_TYPE_CPRH, |
| }; |
| |
| /** |
| * struct cpr3_aging_sensor_info - CPR3 aging sensor information |
| * @sensor_id The index of the CPR3 sensor to be used in the aging |
| * measurement. |
| * @ro_scale The CPR ring oscillator (RO) scaling factor for the |
| * aging sensor with units of QUOT/V. |
| * @init_quot_diff: The fused quotient difference between aged and un-aged |
| * paths that was measured at manufacturing time. |
| * @measured_quot_diff: The quotient difference measured at runtime. |
| * @bypass_mask: Bit mask of the CPR sensors that must be bypassed during |
| * the aging measurement for this sensor |
| * |
| * This structure contains both configuration and runtime state data. The |
| * element measured_quot_diff is a state variable. |
| */ |
| struct cpr3_aging_sensor_info { |
| u32 sensor_id; |
| u32 ro_scale; |
| int init_quot_diff; |
| int measured_quot_diff; |
| u32 bypass_mask[CPR3_MAX_SENSOR_COUNT / 32]; |
| }; |
| |
| /** |
| * struct cpr3_reg_info - Register information data structure |
| * @name: Register name |
| * @addr: Register physical address |
| * @value: Register content |
| * @virt_addr: Register virtual address |
| * |
| * This data structure is used to dump some critical register contents |
| * when the device crashes due to a kernel panic. |
| */ |
| struct cpr3_reg_info { |
| const char *name; |
| u32 addr; |
| u32 value; |
| void __iomem *virt_addr; |
| }; |
| |
| /** |
| * struct cpr3_panic_regs_info - Data structure to dump critical register |
| * contents. |
| * @reg_count: Number of elements in the regs array |
| * @regs: Array of critical registers information |
| * |
| * This data structure is used to dump critical register contents when |
| * the device crashes due to a kernel panic. |
| */ |
| struct cpr3_panic_regs_info { |
| int reg_count; |
| struct cpr3_reg_info *regs; |
| }; |
| |
| /** |
| * struct cpr3_controller - CPR3 controller data structure |
| * @dev: Device pointer for the CPR3 controller device |
| * @name: Unique name for the CPR3 controller |
| * @ctrl_id: Controller ID corresponding to the VDD supply number |
| * that this CPR3 controller manages. |
| * @cpr_ctrl_base: Virtual address of the CPR3 controller base register |
| * @fuse_base: Virtual address of fuse row 0 |
| * @aging_possible_reg: Virtual address of an optional platform-specific |
| * register that must be ready to determine if it is |
| * possible to perform an aging measurement. |
| * @list: list head used in a global cpr3-regulator list so that |
| * cpr3-regulator structs can be found easily in RAM dumps |
| * @thread: Array of CPR3 threads managed by the CPR3 controller |
| * @thread_count: Number of elements in the thread array |
| * @sensor_owner: Array of thread IDs indicating which thread owns a given |
| * CPR sensor |
| * @sensor_count: The number of CPR sensors found on the CPR loop managed |
| * by this CPR controller. Must be equal to the number of |
| * elements in the sensor_owner array |
| * @soc_revision: Revision number of the SoC. This may be unused by |
| * platforms that do not have different behavior for |
| * different SoC revisions. |
| * @lock: Mutex lock used to ensure mutual exclusion between |
| * all of the threads associated with the controller |
| * @vdd_regulator: Pointer to the VDD supply regulator which this CPR3 |
| * controller manages |
| * @system_regulator: Pointer to the optional system-supply regulator upon |
| * which the VDD supply regulator depends. |
| * @mem_acc_regulator: Pointer to the optional mem-acc supply regulator used |
| * to manage memory circuitry settings based upon the |
| * VDD supply output voltage. |
| * @vdd_limit_regulator: Pointer to the VDD supply limit regulator which is used |
| * for hardware closed-loop in order specify ceiling and |
| * floor voltage limits (platform specific) |
| * @system_supply_max_volt: Voltage in microvolts which corresponds to the |
| * absolute ceiling voltage of the system-supply |
| * @mem_acc_threshold_volt: mem-acc threshold voltage in microvolts |
| * @mem_acc_corner_map: mem-acc regulator corners mapping to low and high |
| * voltage mem-acc settings for the memories powered by |
| * this CPR3 controller and its associated CPR3 regulators |
| * @mem_acc_crossover_volt: Voltage in microvolts corresponding to the voltage |
| * that the VDD supply must be set to while a MEM ACC |
| * switch is in progress. This element must be initialized |
| * for CPRh controllers when a MEM ACC threshold voltage is |
| * defined. |
| * @core_clk: Pointer to the CPR3 controller core clock |
| * @iface_clk: Pointer to the CPR3 interface clock (platform specific) |
| * @bus_clk: Pointer to the CPR3 bus clock (platform specific) |
| * @irq: CPR interrupt number |
| * @irq_affinity_mask: The cpumask for the CPUs which the CPR interrupt should |
| * have affinity for |
| * @cpu_hotplug_notifier: CPU hotplug notifier used to reset IRQ affinity when a |
| * CPU is brought back online |
| * @ceiling_irq: Interrupt number for the interrupt that is triggered |
| * when hardware closed-loop attempts to exceed the ceiling |
| * voltage |
| * @apm: Handle to the array power mux (APM) |
| * @apm_threshold_volt: Voltage in microvolts which defines the threshold |
| * voltage to determine the APM supply selection for |
| * each corner |
| * @apm_crossover_volt: Voltage in microvolts corresponding to the voltage that |
| * the VDD supply must be set to while an APM switch is in |
| * progress. This element must be initialized for CPRh |
| * controllers when an APM threshold voltage is defined |
| * @apm_adj_volt: Minimum difference between APM threshold voltage and |
| * open-loop voltage which allows the APM threshold voltage |
| * to be used as a ceiling |
| * @apm_high_supply: APM supply to configure if VDD voltage is greater than |
| * or equal to the APM threshold voltage |
| * @apm_low_supply: APM supply to configure if the VDD voltage is less than |
| * the APM threshold voltage |
| * @base_volt: Minimum voltage in microvolts supported by the VDD |
| * supply managed by this CPR controller |
| * @corner_switch_delay_time: The delay time in nanoseconds used by the CPR |
| * controller to wait for voltage settling before |
| * acknowledging the OSM block after corner changes |
| * @cpr_clock_rate: CPR reference clock frequency in Hz. |
| * @sensor_time: The time in nanoseconds that each sensor takes to |
| * perform a measurement. |
| * @loop_time: The time in nanoseconds between consecutive CPR |
| * measurements. |
| * @up_down_delay_time: The time to delay in nanoseconds between consecutive CPR |
| * measurements when the last measurement recommended |
| * increasing or decreasing the vdd-supply voltage. |
| * (platform specific) |
| * @idle_clocks: Number of CPR reference clock ticks that the CPR |
| * controller waits in transitional states. |
| * @step_quot_init_min: The default minimum CPR step quotient value. The step |
| * quotient is the number of additional ring oscillator |
| * ticks observed when increasing one step in vdd-supply |
| * output voltage. |
| * @step_quot_init_max: The default maximum CPR step quotient value. |
| * @step_volt: Step size in microvolts between available set points |
| * of the VDD supply |
| * @down_error_step_limit: CPR4 hardware closed-loop down error step limit which |
| * defines the maximum number of VDD supply regulator steps |
| * that the voltage may be reduced as the result of a |
| * single CPR measurement. |
| * @up_error_step_limit: CPR4 hardware closed-loop up error step limit which |
| * defines the maximum number of VDD supply regulator steps |
| * that the voltage may be increased as the result of a |
| * single CPR measurement. |
| * @count_mode: CPR controller count mode |
| * @count_repeat: Number of times to perform consecutive sensor |
| * measurements when using all-at-once count modes. |
| * @proc_clock_throttle: Defines the processor clock frequency throttling |
| * register value to use. This can be used to reduce the |
| * clock frequency when a power domain exits a low power |
| * mode until CPR settles at a new voltage. |
| * (platform specific) |
| * @cpr_allowed_hw: Boolean which indicates if closed-loop CPR operation is |
| * permitted for a given chip based upon hardware fuse |
| * values |
| * @cpr_allowed_sw: Boolean which indicates if closed-loop CPR operation is |
| * permitted based upon software policies |
| * @supports_hw_closed_loop: Boolean which indicates if this CPR3/4 controller |
| * physically supports hardware closed-loop CPR operation |
| * @use_hw_closed_loop: Boolean which indicates that this controller will be |
| * using hardware closed-loop operation in place of |
| * software closed-loop operation. |
| * @ctrl_type: CPR controller type |
| * @saw_use_unit_mV: Boolean which indicates the unit used in SAW PVC |
| * interface is mV. |
| * @aggr_corner: CPR corner containing the most recently aggregated |
| * voltage configurations which are being used currently |
| * @cpr_enabled: Boolean which indicates that the CPR controller is |
| * enabled and operating in closed-loop mode. CPR clocks |
| * have been prepared and enabled whenever this flag is |
| * true. |
| * @last_corner_was_closed_loop: Boolean indicating if the last known corners |
| * were updated during closed loop operation. |
| * @cpr_suspended: Boolean which indicates that CPR has been temporarily |
| * disabled while enterring system suspend. |
| * @debugfs: Pointer to the debugfs directory of this CPR3 controller |
| * @aging_ref_volt: Reference voltage in microvolts to configure when |
| * performing CPR aging measurements. |
| * @aging_vdd_mode: vdd-supply regulator mode to configure before performing |
| * a CPR aging measurement. It should be one of |
| * REGULATOR_MODE_*. |
| * @aging_complete_vdd_mode: vdd-supply regulator mode to configure after |
| * performing a CPR aging measurement. It should be one of |
| * REGULATOR_MODE_*. |
| * @aging_ref_adjust_volt: The reference aging voltage margin in microvolts that |
| * should be added to the target quotients of the |
| * regulators managed by this controller after derating. |
| * @aging_required: Flag which indicates that a CPR aging measurement still |
| * needs to be performed for this CPR3 controller. |
| * @aging_succeeded: Flag which indicates that a CPR aging measurement has |
| * completed successfully. |
| * @aging_failed: Flag which indicates that a CPR aging measurement has |
| * failed to complete successfully. |
| * @aging_sensor: Array of CPR3 aging sensors which are used to perform |
| * aging measurements at a runtime. |
| * @aging_sensor_count: Number of elements in the aging_sensor array |
| * @aging_possible_mask: Optional bitmask used to mask off the |
| * aging_possible_reg register. |
| * @aging_possible_val: Optional value that the masked aging_possible_reg |
| * register must have in order for a CPR aging measurement |
| * to be possible. |
| * @aging_gcnt_scaling_factor: The scaling factor used to derive the gate count |
| * used for aging measurements. This value is divided by |
| * 1000 when used as shown in the below equation: |
| * Aging_GCNT = GCNT_REF * scaling_factor / 1000. |
| * For example, a value of 1500 specifies that the gate |
| * count (GCNT) used for aging measurement should be 1.5 |
| * times of reference gate count (GCNT_REF). |
| * @step_quot_fixed: Fixed step quotient value used for target quotient |
| * adjustment if use_dynamic_step_quot is not set. |
| * This parameter is only relevant for CPR4 controllers |
| * when using the per-online-core or per-temperature |
| * adjustments. |
| * @initial_temp_band: Temperature band used for calculation of base-line |
| * target quotients (fused). |
| * @use_dynamic_step_quot: Boolean value which indicates that margin adjustment |
| * of target quotient will be based on the step quotient |
| * calculated dynamically in hardware for each RO. |
| * @allow_core_count_adj: Core count adjustments are allowed for this controller |
| * @allow_temp_adj: Temperature based adjustments are allowed for |
| * this controller |
| * @allow_boost: Voltage boost allowed for this controller. |
| * @temp_band_count: Number of temperature bands used for temperature based |
| * adjustment logic |
| * @temp_points: Array of temperature points in decidegrees Celsius used |
| * to specify the ranges for selected temperature bands. |
| * The array must have (temp_band_count - 1) elements |
| * allocated. |
| * @temp_sensor_id_start: Start ID of temperature sensors used for temperature |
| * based adjustments. |
| * @temp_sensor_id_end: End ID of temperature sensors used for temperature |
| * based adjustments. |
| * @voltage_settling_time: The time in nanoseconds that it takes for the |
| * VDD supply voltage to settle after being increased or |
| * decreased by step_volt microvolts which is used when |
| * SDELTA voltage margin adjustments are applied. |
| * @panic_regs_info: Array of panic registers information which provides the |
| * list of registers to dump when the device crashes. |
| * @panic_notifier: Notifier block registered to global panic notifier list. |
| * @support_ldo300_vreg: Boolean value which indicates that this CPR controller |
| * manages an underlying LDO regulator of type LDO300. |
| * @reset_step_quot_loop_en: Boolean value which indicates that this CPR |
| * controller should be configured to reset step_quot on |
| * each loop_en = 0 transition. This configuration allows |
| * the CPR controller to first use the default step_quot |
| * and then later switch to the run-time calibrated |
| * step_quot. |
| * |
| * This structure contains both configuration and runtime state data. The |
| * elements cpr_allowed_sw, use_hw_closed_loop, aggr_corner, cpr_enabled, |
| * last_corner_was_closed_loop, cpr_suspended, aging_ref_adjust_volt, |
| * aging_required, aging_succeeded, and aging_failed are state variables. |
| * |
| * The apm* elements do not need to be initialized if the VDD supply managed by |
| * the CPR3 controller does not utilize an APM. |
| * |
| * The elements step_quot_fixed, initial_temp_band, allow_core_count_adj, |
| * allow_temp_adj and temp* need to be initialized for CPR4 controllers which |
| * are using per-online-core or per-temperature adjustments. |
| */ |
| struct cpr3_controller { |
| struct device *dev; |
| const char *name; |
| int ctrl_id; |
| void __iomem *cpr_ctrl_base; |
| void __iomem *fuse_base; |
| void __iomem *aging_possible_reg; |
| struct list_head list; |
| struct cpr3_thread *thread; |
| int thread_count; |
| u8 *sensor_owner; |
| int sensor_count; |
| int soc_revision; |
| struct mutex lock; |
| struct regulator *vdd_regulator; |
| struct regulator *system_regulator; |
| struct regulator *mem_acc_regulator; |
| struct regulator *vdd_limit_regulator; |
| int system_supply_max_volt; |
| int mem_acc_threshold_volt; |
| int mem_acc_corner_map[CPR3_MEM_ACC_CORNERS]; |
| int mem_acc_crossover_volt; |
| struct clk *core_clk; |
| struct clk *iface_clk; |
| struct clk *bus_clk; |
| int irq; |
| struct cpumask irq_affinity_mask; |
| struct notifier_block cpu_hotplug_notifier; |
| int ceiling_irq; |
| struct msm_apm_ctrl_dev *apm; |
| int apm_threshold_volt; |
| int apm_crossover_volt; |
| int apm_adj_volt; |
| enum msm_apm_supply apm_high_supply; |
| enum msm_apm_supply apm_low_supply; |
| int base_volt; |
| u32 corner_switch_delay_time; |
| u32 cpr_clock_rate; |
| u32 sensor_time; |
| u32 loop_time; |
| u32 up_down_delay_time; |
| u32 idle_clocks; |
| u32 step_quot_init_min; |
| u32 step_quot_init_max; |
| int step_volt; |
| u32 down_error_step_limit; |
| u32 up_error_step_limit; |
| enum cpr3_count_mode count_mode; |
| u32 count_repeat; |
| u32 proc_clock_throttle; |
| bool cpr_allowed_hw; |
| bool cpr_allowed_sw; |
| bool supports_hw_closed_loop; |
| bool use_hw_closed_loop; |
| enum cpr_controller_type ctrl_type; |
| bool saw_use_unit_mV; |
| struct cpr3_corner aggr_corner; |
| bool cpr_enabled; |
| bool last_corner_was_closed_loop; |
| bool cpr_suspended; |
| struct dentry *debugfs; |
| |
| int aging_ref_volt; |
| unsigned int aging_vdd_mode; |
| unsigned int aging_complete_vdd_mode; |
| int aging_ref_adjust_volt; |
| bool aging_required; |
| bool aging_succeeded; |
| bool aging_failed; |
| struct cpr3_aging_sensor_info *aging_sensor; |
| int aging_sensor_count; |
| u32 aging_possible_mask; |
| u32 aging_possible_val; |
| u32 aging_gcnt_scaling_factor; |
| |
| u32 step_quot_fixed; |
| u32 initial_temp_band; |
| bool use_dynamic_step_quot; |
| bool allow_core_count_adj; |
| bool allow_temp_adj; |
| bool allow_boost; |
| int temp_band_count; |
| int *temp_points; |
| u32 temp_sensor_id_start; |
| u32 temp_sensor_id_end; |
| u32 voltage_settling_time; |
| struct cpr3_panic_regs_info *panic_regs_info; |
| struct notifier_block panic_notifier; |
| bool support_ldo300_vreg; |
| bool reset_step_quot_loop_en; |
| }; |
| |
| /* Used for rounding voltages to the closest physically available set point. */ |
| #define CPR3_ROUND(n, d) (DIV_ROUND_UP(n, d) * (d)) |
| |
| #define cpr3_err(cpr3_thread, message, ...) \ |
| pr_err("%s: " message, (cpr3_thread)->name, ##__VA_ARGS__) |
| #define cpr3_info(cpr3_thread, message, ...) \ |
| pr_info("%s: " message, (cpr3_thread)->name, ##__VA_ARGS__) |
| #define cpr3_debug(cpr3_thread, message, ...) \ |
| pr_debug("%s: " message, (cpr3_thread)->name, ##__VA_ARGS__) |
| |
| /* |
| * Offset subtracted from voltage corner values passed in from the regulator |
| * framework in order to get internal voltage corner values. This is needed |
| * since the regulator framework treats 0 as an error value at regulator |
| * registration time. |
| */ |
| #define CPR3_CORNER_OFFSET 1 |
| |
| #ifdef CONFIG_REGULATOR_CPR3 |
| |
| int cpr3_regulator_register(struct platform_device *pdev, |
| struct cpr3_controller *ctrl); |
| int cpr3_regulator_unregister(struct cpr3_controller *ctrl); |
| int cpr3_regulator_suspend(struct cpr3_controller *ctrl); |
| int cpr3_regulator_resume(struct cpr3_controller *ctrl); |
| |
| int cpr3_allocate_threads(struct cpr3_controller *ctrl, u32 min_thread_id, |
| u32 max_thread_id); |
| int cpr3_map_fuse_base(struct cpr3_controller *ctrl, |
| struct platform_device *pdev); |
| int cpr3_read_fuse_param(void __iomem *fuse_base_addr, |
| const struct cpr3_fuse_param *param, u64 *param_value); |
| int cpr3_convert_open_loop_voltage_fuse(int ref_volt, int step_volt, u32 fuse, |
| int fuse_len); |
| u64 cpr3_interpolate(u64 x1, u64 y1, u64 x2, u64 y2, u64 x); |
| int cpr3_parse_array_property(struct cpr3_regulator *vreg, |
| const char *prop_name, int tuple_size, u32 *out); |
| int cpr3_parse_corner_array_property(struct cpr3_regulator *vreg, |
| const char *prop_name, int tuple_size, u32 *out); |
| int cpr3_parse_corner_band_array_property(struct cpr3_regulator *vreg, |
| const char *prop_name, int tuple_size, u32 *out); |
| int cpr3_parse_common_corner_data(struct cpr3_regulator *vreg); |
| int cpr3_parse_thread_u32(struct cpr3_thread *thread, const char *propname, |
| u32 *out_value, u32 value_min, u32 value_max); |
| int cpr3_parse_ctrl_u32(struct cpr3_controller *ctrl, const char *propname, |
| u32 *out_value, u32 value_min, u32 value_max); |
| int cpr3_parse_common_thread_data(struct cpr3_thread *thread); |
| int cpr3_parse_common_ctrl_data(struct cpr3_controller *ctrl); |
| int cpr3_limit_open_loop_voltages(struct cpr3_regulator *vreg); |
| void cpr3_open_loop_voltage_as_ceiling(struct cpr3_regulator *vreg); |
| int cpr3_limit_floor_voltages(struct cpr3_regulator *vreg); |
| void cpr3_print_quots(struct cpr3_regulator *vreg); |
| int cpr3_adjust_fused_open_loop_voltages(struct cpr3_regulator *vreg, |
| int *fuse_volt); |
| int cpr3_adjust_open_loop_voltages(struct cpr3_regulator *vreg); |
| int cpr3_quot_adjustment(int ro_scale, int volt_adjust); |
| int cpr3_voltage_adjustment(int ro_scale, int quot_adjust); |
| int cpr3_parse_closed_loop_voltage_adjustments(struct cpr3_regulator *vreg, |
| u64 *ro_sel, int *volt_adjust, |
| int *volt_adjust_fuse, int *ro_scale); |
| int cpr4_parse_core_count_temp_voltage_adj(struct cpr3_regulator *vreg, |
| bool use_corner_band); |
| int cpr3_apm_init(struct cpr3_controller *ctrl); |
| int cpr3_mem_acc_init(struct cpr3_regulator *vreg); |
| void cprh_adjust_voltages_for_apm(struct cpr3_regulator *vreg); |
| void cprh_adjust_voltages_for_mem_acc(struct cpr3_regulator *vreg); |
| int cpr3_adjust_target_quotients(struct cpr3_regulator *vreg, |
| int *fuse_volt_adjust); |
| |
| #else |
| |
| static inline int cpr3_regulator_register(struct platform_device *pdev, |
| struct cpr3_controller *ctrl) |
| { |
| return -ENXIO; |
| } |
| |
| static inline int cpr3_regulator_unregister(struct cpr3_controller *ctrl) |
| { |
| return -ENXIO; |
| } |
| |
| static inline int cpr3_regulator_suspend(struct cpr3_controller *ctrl) |
| { |
| return -ENXIO; |
| } |
| |
| static inline int cpr3_regulator_resume(struct cpr3_controller *ctrl) |
| { |
| return -ENXIO; |
| } |
| |
| static inline int cpr3_get_thread_name(struct cpr3_thread *thread, |
| struct device_node *thread_node) |
| { |
| return -EPERM; |
| } |
| |
| static inline int cpr3_allocate_threads(struct cpr3_controller *ctrl, |
| u32 min_thread_id, u32 max_thread_id) |
| { |
| return -EPERM; |
| } |
| |
| static inline int cpr3_map_fuse_base(struct cpr3_controller *ctrl, |
| struct platform_device *pdev) |
| { |
| return -ENXIO; |
| } |
| |
| static inline int cpr3_read_fuse_param(void __iomem *fuse_base_addr, |
| const struct cpr3_fuse_param *param, u64 *param_value) |
| { |
| return -EPERM; |
| } |
| |
| static inline int cpr3_convert_open_loop_voltage_fuse(int ref_volt, |
| int step_volt, u32 fuse, int fuse_len) |
| { |
| return -EPERM; |
| } |
| |
| static inline u64 cpr3_interpolate(u64 x1, u64 y1, u64 x2, u64 y2, u64 x) |
| { |
| return 0; |
| } |
| |
| static inline int cpr3_parse_array_property(struct cpr3_regulator *vreg, |
| const char *prop_name, int tuple_size, u32 *out) |
| { |
| return -EPERM; |
| } |
| |
| static inline int cpr3_parse_corner_array_property(struct cpr3_regulator *vreg, |
| const char *prop_name, int tuple_size, u32 *out) |
| { |
| return -EPERM; |
| } |
| |
| static inline int cpr3_parse_corner_band_array_property( |
| struct cpr3_regulator *vreg, const char *prop_name, |
| int tuple_size, u32 *out) |
| { |
| return -EPERM; |
| } |
| |
| static inline int cpr3_parse_common_corner_data(struct cpr3_regulator *vreg) |
| { |
| return -EPERM; |
| } |
| |
| static inline int cpr3_parse_thread_u32(struct cpr3_thread *thread, |
| const char *propname, u32 *out_value, u32 value_min, |
| u32 value_max) |
| { |
| return -EPERM; |
| } |
| |
| static inline int cpr3_parse_ctrl_u32(struct cpr3_controller *ctrl, |
| const char *propname, u32 *out_value, u32 value_min, |
| u32 value_max) |
| { |
| return -EPERM; |
| } |
| |
| static inline int cpr3_parse_common_thread_data(struct cpr3_thread *thread) |
| { |
| return -EPERM; |
| } |
| |
| static inline int cpr3_parse_common_ctrl_data(struct cpr3_controller *ctrl) |
| { |
| return -EPERM; |
| } |
| |
| static inline int cpr3_limit_open_loop_voltages(struct cpr3_regulator *vreg) |
| { |
| return -EPERM; |
| } |
| |
| static inline void cpr3_open_loop_voltage_as_ceiling( |
| struct cpr3_regulator *vreg) |
| { |
| } |
| |
| static inline int cpr3_limit_floor_voltages(struct cpr3_regulator *vreg) |
| { |
| return -EPERM; |
| } |
| |
| static inline void cpr3_print_quots(struct cpr3_regulator *vreg) |
| { |
| } |
| |
| static inline int cpr3_adjust_fused_open_loop_voltages( |
| struct cpr3_regulator *vreg, int *fuse_volt) |
| { |
| return -EPERM; |
| } |
| |
| static inline int cpr3_adjust_open_loop_voltages(struct cpr3_regulator *vreg) |
| { |
| return -EPERM; |
| } |
| |
| static inline int cpr3_quot_adjustment(int ro_scale, int volt_adjust) |
| { |
| return 0; |
| } |
| |
| static inline int cpr3_voltage_adjustment(int ro_scale, int quot_adjust) |
| { |
| return 0; |
| } |
| |
| static inline int cpr3_parse_closed_loop_voltage_adjustments( |
| struct cpr3_regulator *vreg, u64 *ro_sel, |
| int *volt_adjust, int *volt_adjust_fuse, int *ro_scale) |
| { |
| return 0; |
| } |
| |
| static inline int cpr4_parse_core_count_temp_voltage_adj( |
| struct cpr3_regulator *vreg, bool use_corner_band) |
| { |
| return 0; |
| } |
| |
| static inline int cpr3_apm_init(struct cpr3_controller *ctrl) |
| { |
| return 0; |
| } |
| |
| static inline int cpr3_mem_acc_init(struct cpr3_regulator *vreg) |
| { |
| return 0; |
| } |
| |
| static inline void cprh_adjust_voltages_for_apm(struct cpr3_regulator *vreg) |
| { |
| } |
| |
| static inline void cprh_adjust_voltages_for_mem_acc(struct cpr3_regulator *vreg) |
| { |
| } |
| |
| static inline int cpr3_adjust_target_quotients(struct cpr3_regulator *vreg, |
| int *fuse_volt_adjust) |
| { |
| return 0; |
| } |
| |
| #endif /* CONFIG_REGULATOR_CPR3 */ |
| |
| #endif /* __REGULATOR_CPR_REGULATOR_H__ */ |