1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155 |
- // SPDX-License-Identifier: GPL-2.0-only
- /*
- * Copyright (c) 2012-2015, 2018-2021, The Linux Foundation. All rights reserved.
- * Copyright (c) 2022-2023, Qualcomm Innovation Center, Inc. All rights reserved.
- */
- #define pr_fmt(fmt) "%s: " fmt, __func__
- #include <linux/module.h>
- #include <linux/err.h>
- #include <linux/kernel.h>
- #include <linux/init.h>
- #include <linux/slab.h>
- #include <linux/spinlock.h>
- #include <linux/string.h>
- #include <linux/of.h>
- #include <linux/of_device.h>
- #include <linux/platform_device.h>
- #include <linux/regulator/driver.h>
- #include <linux/regulator/debug-regulator.h>
- #include <linux/regulator/machine.h>
- #include <linux/regulator/of_regulator.h>
- #include <linux/regulator/rpm-smd-regulator.h>
- #include <linux/regulator/proxy-consumer.h>
- #include <dt-bindings/regulator/qcom,rpm-smd-regulator.h>
- #include <soc/qcom/rpm-smd.h>
- #include <linux/debugfs.h>
- #include <linux/limits.h>
- /* Debug Definitions */
- enum {
- RPM_VREG_DEBUG_REQUEST = BIT(0),
- RPM_VREG_DEBUG_FULL_REQUEST = BIT(1),
- RPM_VREG_DEBUG_DUPLICATE = BIT(2),
- };
- static int rpm_vreg_debug_mask;
- #ifdef CONFIG_DEBUG_FS
- static bool is_debugfs_created;
- #endif
- #define vreg_err(req, fmt, ...) \
- pr_err("%s: " fmt, req->rdesc.name, ##__VA_ARGS__)
- /* RPM regulator request types */
- enum rpm_regulator_type {
- RPM_REGULATOR_TYPE_LDO,
- RPM_REGULATOR_TYPE_SMPS,
- RPM_REGULATOR_TYPE_VS,
- RPM_REGULATOR_TYPE_NCP,
- RPM_REGULATOR_TYPE_BOB,
- RPM_REGULATOR_TYPE_MAX,
- };
- /* Supported PMIC regulator LDO and BOB types */
- enum rpm_regulator_hw_type {
- RPM_REGULATOR_HW_TYPE_UNKNOWN,
- RPM_REGULATOR_HW_TYPE_PMIC4_LDO,
- RPM_REGULATOR_HW_TYPE_PMIC5_LDO,
- RPM_REGULATOR_HW_TYPE_PMIC4_BOB,
- RPM_REGULATOR_HW_TYPE_PMIC5_BOB,
- RPM_REGULATOR_HW_TYPE_MAX,
- };
- /* RPM resource parameters */
- enum rpm_regulator_param_index {
- RPM_REGULATOR_PARAM_ENABLE,
- RPM_REGULATOR_PARAM_VOLTAGE,
- RPM_REGULATOR_PARAM_CURRENT,
- RPM_REGULATOR_PARAM_MODE_LDO,
- RPM_REGULATOR_PARAM_MODE_SMPS,
- RPM_REGULATOR_PARAM_PIN_CTRL_ENABLE,
- RPM_REGULATOR_PARAM_PIN_CTRL_MODE,
- RPM_REGULATOR_PARAM_FREQUENCY,
- RPM_REGULATOR_PARAM_HEAD_ROOM,
- RPM_REGULATOR_PARAM_QUIET_MODE,
- RPM_REGULATOR_PARAM_FREQ_REASON,
- RPM_REGULATOR_PARAM_CORNER,
- RPM_REGULATOR_PARAM_BYPASS,
- RPM_REGULATOR_PARAM_FLOOR_CORNER,
- RPM_REGULATOR_PARAM_LEVEL,
- RPM_REGULATOR_PARAM_FLOOR_LEVEL,
- RPM_REGULATOR_PARAM_MODE_BOB,
- RPM_REGULATOR_PARAM_PIN_CTRL_VOLTAGE1,
- RPM_REGULATOR_PARAM_PIN_CTRL_VOLTAGE2,
- RPM_REGULATOR_PARAM_PIN_CTRL_VOLTAGE3,
- RPM_REGULATOR_PARAM_MAX,
- };
- enum rpm_regulator_bob_mode_pmic4 {
- RPM_REGULATOR_PMIC4_BOB_MODE_PASS = 0,
- RPM_REGULATOR_PMIC4_BOB_MODE_PFM = 1,
- RPM_REGULATOR_PMIC4_BOB_MODE_AUTO = 2,
- RPM_REGULATOR_PMIC4_BOB_MODE_PWM = 3,
- };
- enum rpm_regulator_bob_mode_pmic5 {
- RPM_REGULATOR_PMIC5_BOB_MODE_PASS = 2,
- RPM_REGULATOR_PMIC5_BOB_MODE_PFM = 4,
- RPM_REGULATOR_PMIC5_BOB_MODE_AUTO = 6,
- RPM_REGULATOR_PMIC5_BOB_MODE_PWM = 7,
- };
- #define RPM_SET_CONFIG_ACTIVE BIT(0)
- #define RPM_SET_CONFIG_SLEEP BIT(1)
- #define RPM_SET_CONFIG_BOTH (RPM_SET_CONFIG_ACTIVE \
- | RPM_SET_CONFIG_SLEEP)
- struct rpm_regulator_param {
- char *name;
- char *property_name;
- u32 key;
- u32 min;
- u32 max;
- u32 supported_regulator_types;
- };
- #define PARAM(_idx, _support_ldo, _support_smps, _support_vs, _support_ncp, \
- _support_bob, _name, _min, _max, _property_name) \
- [RPM_REGULATOR_PARAM_##_idx] = { \
- .name = _name, \
- .property_name = _property_name, \
- .min = _min, \
- .max = _max, \
- .supported_regulator_types = \
- _support_ldo << RPM_REGULATOR_TYPE_LDO | \
- _support_smps << RPM_REGULATOR_TYPE_SMPS | \
- _support_vs << RPM_REGULATOR_TYPE_VS | \
- _support_ncp << RPM_REGULATOR_TYPE_NCP | \
- _support_bob << RPM_REGULATOR_TYPE_BOB, \
- }
- static struct rpm_regulator_param params[RPM_REGULATOR_PARAM_MAX] = {
- /* ID LDO SMPS VS NCP BOB name min max property-name */
- PARAM(ENABLE, 1, 1, 1, 1, 1, "swen", 0, 1, "qcom,init-enable"),
- PARAM(VOLTAGE, 1, 1, 0, 1, 1, "uv", 0, 0x7FFFFFF, "qcom,init-voltage"),
- PARAM(CURRENT, 0, 1, 0, 0, 0, "ma", 0, 0x1FFF, "qcom,init-current"),
- PARAM(MODE_LDO, 1, 0, 0, 0, 0, "lsmd", 0, 4, "qcom,init-ldo-mode"),
- PARAM(MODE_SMPS, 0, 1, 0, 0, 0, "ssmd", 0, 2, "qcom,init-smps-mode"),
- PARAM(PIN_CTRL_ENABLE, 1, 1, 1, 0, 0, "pcen", 0, 0xF, "qcom,init-pin-ctrl-enable"),
- PARAM(PIN_CTRL_MODE, 0, 1, 1, 0, 0, "pcmd", 0, 0x1F, "qcom,init-pin-ctrl-mode"),
- PARAM(FREQUENCY, 0, 1, 0, 1, 0, "freq", 0, 31, "qcom,init-frequency"),
- PARAM(HEAD_ROOM, 0, 0, 0, 1, 0, "hr", 0, 0x7FFFFFFF, "qcom,init-head-room"),
- PARAM(QUIET_MODE, 0, 1, 0, 0, 0, "qm", 0, 2, "qcom,init-quiet-mode"),
- PARAM(FREQ_REASON, 0, 1, 0, 1, 0, "resn", 0, 8, "qcom,init-freq-reason"),
- PARAM(CORNER, 0, 1, 0, 0, 0, "corn", 0, 6, "qcom,init-voltage-corner"),
- PARAM(BYPASS, 0, 0, 0, 0, 0, "bypa", 0, 1, "qcom,init-disallow-bypass"),
- PARAM(FLOOR_CORNER, 0, 1, 0, 0, 0, "vfc", 0, 6, "qcom,init-voltage-floor-corner"),
- PARAM(LEVEL, 0, 1, 0, 0, 0, "vlvl", 0, 0xFFFF, "qcom,init-voltage-level"),
- PARAM(FLOOR_LEVEL, 0, 1, 0, 0, 0, "vfl", 0, 0xFFFF, "qcom,init-voltage-floor-level"),
- PARAM(MODE_BOB, 0, 0, 0, 0, 1, "bobm", 0, 4, "qcom,init-bob-mode"),
- PARAM(PIN_CTRL_VOLTAGE1, 0, 0, 0, 0, 1, "pcv1", 0, 0x7FFFFFF, "qcom,init-pin-ctrl-voltage1"),
- PARAM(PIN_CTRL_VOLTAGE2, 0, 0, 0, 0, 1, "pcv2", 0, 0x7FFFFFF, "qcom,init-pin-ctrl-voltage2"),
- PARAM(PIN_CTRL_VOLTAGE3, 0, 0, 0, 0, 1, "pcv3", 0, 0x7FFFFFF, "qcom,init-pin-ctrl-voltage3"),
- };
- /* Indices for use with pin control enable via enable/disable feature. */
- #define RPM_VREG_PIN_CTRL_STATE_DISABLE 0
- #define RPM_VREG_PIN_CTRL_STATE_ENABLE 1
- #define RPM_VREG_PIN_CTRL_STATE_COUNT 2
- struct rpm_vreg_request {
- u32 param[RPM_REGULATOR_PARAM_MAX];
- u32 valid;
- u32 modified;
- };
- struct rpm_reg_mode_info {
- u32 mode;
- int min_load_ua;
- };
- struct rpm_vreg {
- struct rpm_vreg_request aggr_req_active;
- struct rpm_vreg_request aggr_req_sleep;
- struct list_head reg_list;
- const char *resource_name;
- u32 resource_id;
- bool allow_atomic;
- int regulator_type;
- int hpm_min_load;
- struct rpm_reg_mode_info *mode;
- int mode_count;
- int enable_time;
- spinlock_t slock;
- struct mutex mlock;
- unsigned long flags;
- bool sleep_request_sent;
- bool wait_for_ack_active;
- bool wait_for_ack_sleep;
- bool always_wait_for_ack;
- bool apps_only;
- struct msm_rpm_request *handle_active;
- struct msm_rpm_request *handle_sleep;
- enum rpm_regulator_hw_type regulator_hw_type;
- };
- struct rpm_regulator {
- struct regulator_desc rdesc;
- struct regulator_dev *rdev;
- struct rpm_vreg *rpm_vreg;
- struct dentry *dfs_root;
- struct list_head list;
- bool set_active;
- bool set_sleep;
- bool always_send_voltage;
- bool always_send_current;
- bool use_pin_ctrl_for_enable;
- struct rpm_vreg_request req;
- int system_load;
- int min_uV;
- int max_uV;
- u32 pin_ctrl_mask[RPM_VREG_PIN_CTRL_STATE_COUNT];
- enum rpm_regulator_param_index voltage_index;
- int voltage_offset;
- };
- /*
- * This voltage in uV is returned by get_voltage functions when there is no way
- * to determine the current voltage level. It is needed because the regulator
- * framework treats a 0 uV voltage as an error.
- */
- #define VOLTAGE_UNKNOWN 1
- /*
- * Regulator requests sent in the active set take effect immediately. Requests
- * sent in the sleep set take effect when the Apps processor transitions into
- * RPM assisted power collapse. For any given regulator, if an active set
- * request is present, but not a sleep set request, then the active set request
- * is used at all times, even when the Apps processor is power collapsed.
- *
- * The rpm-regulator-smd takes advantage of this default usage of the active set
- * request by only sending a sleep set request if it differs from the
- * corresponding active set request.
- */
- #define RPM_SET_ACTIVE MSM_RPM_CTX_ACTIVE_SET
- #define RPM_SET_SLEEP MSM_RPM_CTX_SLEEP_SET
- static u32 rpm_vreg_string_to_int(const u8 *str)
- {
- int i, len;
- u32 output = 0;
- len = strnlen(str, sizeof(u32));
- for (i = 0; i < len; i++)
- output |= str[i] << (i * 8);
- return output;
- }
- static inline void rpm_vreg_lock(struct rpm_vreg *rpm_vreg)
- {
- if (rpm_vreg->allow_atomic)
- spin_lock_irqsave(&rpm_vreg->slock, rpm_vreg->flags);
- else
- mutex_lock(&rpm_vreg->mlock);
- }
- static inline void rpm_vreg_unlock(struct rpm_vreg *rpm_vreg)
- {
- if (rpm_vreg->allow_atomic)
- spin_unlock_irqrestore(&rpm_vreg->slock, rpm_vreg->flags);
- else
- mutex_unlock(&rpm_vreg->mlock);
- }
- static inline bool rpm_vreg_active_or_sleep_enabled(struct rpm_vreg *rpm_vreg)
- {
- return (rpm_vreg->aggr_req_active.param[RPM_REGULATOR_PARAM_ENABLE]
- && (rpm_vreg->aggr_req_active.valid
- & BIT(RPM_REGULATOR_PARAM_ENABLE)))
- || ((rpm_vreg->aggr_req_sleep.param[RPM_REGULATOR_PARAM_ENABLE])
- && (rpm_vreg->aggr_req_sleep.valid
- & BIT(RPM_REGULATOR_PARAM_ENABLE)));
- }
- static inline bool rpm_vreg_shared_active_or_sleep_enabled_valid
- (struct rpm_vreg *rpm_vreg)
- {
- return !rpm_vreg->apps_only &&
- ((rpm_vreg->aggr_req_active.valid
- & BIT(RPM_REGULATOR_PARAM_ENABLE))
- || (rpm_vreg->aggr_req_sleep.valid
- & BIT(RPM_REGULATOR_PARAM_ENABLE)));
- }
- static const u32 power_level_params =
- BIT(RPM_REGULATOR_PARAM_ENABLE) |
- BIT(RPM_REGULATOR_PARAM_VOLTAGE) |
- BIT(RPM_REGULATOR_PARAM_CURRENT) |
- BIT(RPM_REGULATOR_PARAM_CORNER) |
- BIT(RPM_REGULATOR_PARAM_BYPASS) |
- BIT(RPM_REGULATOR_PARAM_FLOOR_CORNER) |
- BIT(RPM_REGULATOR_PARAM_LEVEL) |
- BIT(RPM_REGULATOR_PARAM_FLOOR_LEVEL);
- static bool rpm_vreg_ack_required(struct rpm_vreg *rpm_vreg, u32 set,
- const u32 *prev_param, const u32 *param,
- u32 prev_valid, u32 modified)
- {
- u32 mask;
- int i;
- if (rpm_vreg->always_wait_for_ack
- || (set == RPM_SET_ACTIVE && rpm_vreg->wait_for_ack_active)
- || (set == RPM_SET_SLEEP && rpm_vreg->wait_for_ack_sleep))
- return true;
- for (i = 0; i < RPM_REGULATOR_PARAM_MAX; i++) {
- mask = BIT(i);
- if (modified & mask) {
- if ((prev_valid & mask) && (power_level_params & mask)
- && (param[i] <= prev_param[i]))
- continue;
- else
- return true;
- }
- }
- return false;
- }
- static void rpm_vreg_check_param_max(struct rpm_regulator *regulator, int index,
- u32 new_max)
- {
- struct rpm_vreg *rpm_vreg = regulator->rpm_vreg;
- if (regulator->set_active
- && (rpm_vreg->aggr_req_active.valid & BIT(index))
- && rpm_vreg->aggr_req_active.param[index] > new_max)
- rpm_vreg->wait_for_ack_active = true;
- if (regulator->set_sleep
- && (rpm_vreg->aggr_req_sleep.valid & BIT(index))
- && rpm_vreg->aggr_req_sleep.param[index] > new_max)
- rpm_vreg->wait_for_ack_sleep = true;
- }
- /*
- * This is used when voting for LPM or HPM by subtracting or adding to the
- * hpm_min_load of a regulator. It has units of uA.
- */
- #define LOAD_THRESHOLD_STEP 1000
- static inline int rpm_vreg_hpm_min_uA(struct rpm_vreg *rpm_vreg)
- {
- return rpm_vreg->hpm_min_load;
- }
- static inline int rpm_vreg_lpm_max_uA(struct rpm_vreg *rpm_vreg)
- {
- return rpm_vreg->hpm_min_load - LOAD_THRESHOLD_STEP;
- }
- #define MICRO_TO_MILLI(uV) ((uV) / 1000)
- #define MILLI_TO_MICRO(uV) ((uV) * 1000)
- #define DEBUG_PRINT_BUFFER_SIZE 512
- #define REQ_SENT 0
- #define REQ_PREV 1
- #define REQ_CACHED 2
- #define REQ_TYPES 3
- static void rpm_regulator_req(struct rpm_regulator *regulator, int set,
- bool sent)
- {
- char buf[DEBUG_PRINT_BUFFER_SIZE];
- size_t buflen = DEBUG_PRINT_BUFFER_SIZE;
- struct rpm_vreg *rpm_vreg = regulator->rpm_vreg;
- struct rpm_vreg_request *aggr;
- bool first;
- u32 mask[REQ_TYPES] = {0, 0, 0};
- const char *req_names[REQ_TYPES] = {"sent", "prev", "cached"};
- int pos = 0;
- int i, j;
- aggr = (set == RPM_SET_ACTIVE)
- ? &rpm_vreg->aggr_req_active : &rpm_vreg->aggr_req_sleep;
- if (rpm_vreg_debug_mask & RPM_VREG_DEBUG_DUPLICATE) {
- mask[REQ_SENT] = aggr->modified;
- mask[REQ_PREV] = aggr->valid & ~aggr->modified;
- } else if (sent
- && (rpm_vreg_debug_mask & RPM_VREG_DEBUG_FULL_REQUEST)) {
- mask[REQ_SENT] = aggr->modified;
- mask[REQ_PREV] = aggr->valid & ~aggr->modified;
- } else if (sent && (rpm_vreg_debug_mask & RPM_VREG_DEBUG_REQUEST)) {
- mask[REQ_SENT] = aggr->modified;
- }
- if (!(mask[REQ_SENT] | mask[REQ_PREV]))
- return;
- if (set == RPM_SET_SLEEP && !rpm_vreg->sleep_request_sent) {
- mask[REQ_CACHED] = mask[REQ_SENT] | mask[REQ_PREV];
- mask[REQ_SENT] = 0;
- mask[REQ_PREV] = 0;
- }
- pos += scnprintf(buf + pos, buflen - pos, "%s%s: ",
- KERN_INFO, __func__);
- pos += scnprintf(buf + pos, buflen - pos, "%s %u (%s): s=%s",
- rpm_vreg->resource_name, rpm_vreg->resource_id,
- regulator->rdesc.name,
- (set == RPM_SET_ACTIVE ? "act" : "slp"));
- for (i = 0; i < REQ_TYPES; i++) {
- if (mask[i])
- pos += scnprintf(buf + pos, buflen - pos, "; %s: ",
- req_names[i]);
- first = true;
- for (j = 0; j < RPM_REGULATOR_PARAM_MAX; j++) {
- if (mask[i] & BIT(j)) {
- pos += scnprintf(buf + pos, buflen - pos,
- "%s%s=%u", (first ? "" : ", "),
- params[j].name, aggr->param[j]);
- first = false;
- }
- }
- }
- pos += scnprintf(buf + pos, buflen - pos, "\n");
- pr_info("%s\n", buf);
- }
- #define RPM_VREG_SET_PARAM(_regulator, _param, _val) \
- { \
- (_regulator)->req.param[RPM_REGULATOR_PARAM_##_param] = _val; \
- (_regulator)->req.modified |= BIT(RPM_REGULATOR_PARAM_##_param); \
- } \
- static int rpm_vreg_add_kvp_to_request(struct rpm_vreg *rpm_vreg,
- const u32 *param, int idx, u32 set)
- {
- struct msm_rpm_request *handle;
- handle = (set == RPM_SET_ACTIVE ? rpm_vreg->handle_active
- : rpm_vreg->handle_sleep);
- if (rpm_vreg->allow_atomic)
- return msm_rpm_add_kvp_data_noirq(handle, params[idx].key,
- (u8 *)¶m[idx], 4);
- else
- return msm_rpm_add_kvp_data(handle, params[idx].key,
- (u8 *)¶m[idx], 4);
- }
- static void rpm_vreg_check_modified_requests(const u32 *prev_param,
- const u32 *param, u32 prev_valid, u32 *modified)
- {
- u32 value_changed = 0;
- int i;
- for (i = 0; i < RPM_REGULATOR_PARAM_MAX; i++) {
- if (param[i] != prev_param[i])
- value_changed |= BIT(i);
- }
- /*
- * Only keep bits that are for changed parameters or previously
- * invalid parameters.
- */
- *modified &= value_changed | ~prev_valid;
- }
- static int rpm_vreg_add_modified_requests(struct rpm_regulator *regulator,
- u32 set, const u32 *param, u32 modified)
- {
- struct rpm_vreg *rpm_vreg = regulator->rpm_vreg;
- int rc = 0;
- int i;
- for (i = 0; i < RPM_REGULATOR_PARAM_MAX; i++) {
- /* Only send requests for modified parameters. */
- if (modified & BIT(i)) {
- rc = rpm_vreg_add_kvp_to_request(rpm_vreg, param, i,
- set);
- if (rc) {
- vreg_err(regulator,
- "add KVP failed: %s %u; %s, rc=%d\n",
- rpm_vreg->resource_name,
- rpm_vreg->resource_id, params[i].name,
- rc);
- return rc;
- }
- }
- }
- return rc;
- }
- static int rpm_vreg_send_request(struct rpm_regulator *regulator, u32 set,
- bool wait_for_ack)
- {
- struct rpm_vreg *rpm_vreg = regulator->rpm_vreg;
- struct msm_rpm_request *handle
- = (set == RPM_SET_ACTIVE ? rpm_vreg->handle_active
- : rpm_vreg->handle_sleep);
- int rc = 0;
- void *temp;
- if (unlikely(rpm_vreg->allow_atomic)) {
- rc = msm_rpm_wait_for_ack_noirq(msm_rpm_send_request_noirq(
- handle));
- } else if (wait_for_ack) {
- rc = msm_rpm_wait_for_ack(msm_rpm_send_request(handle));
- } else {
- temp = msm_rpm_send_request_noack(handle);
- if (IS_ERR(temp))
- rc = PTR_ERR(temp);
- }
- if (rc)
- vreg_err(regulator,
- "msm rpm send failed: %s %u; set=%s, rc=%d\n",
- rpm_vreg->resource_name,
- rpm_vreg->resource_id,
- (set == RPM_SET_ACTIVE ? "act" : "slp"), rc);
- return rc;
- }
- #define RPM_VREG_AGGR_MIN(_idx, _param_aggr, _param_reg) \
- { \
- _param_aggr[RPM_REGULATOR_PARAM_##_idx] \
- = min(_param_aggr[RPM_REGULATOR_PARAM_##_idx], \
- _param_reg[RPM_REGULATOR_PARAM_##_idx]); \
- }
- #define RPM_VREG_AGGR_MAX(_idx, _param_aggr, _param_reg) \
- { \
- _param_aggr[RPM_REGULATOR_PARAM_##_idx] \
- = max(_param_aggr[RPM_REGULATOR_PARAM_##_idx], \
- _param_reg[RPM_REGULATOR_PARAM_##_idx]); \
- }
- #define RPM_VREG_AGGR_SUM(_idx, _param_aggr, _param_reg) \
- { \
- _param_aggr[RPM_REGULATOR_PARAM_##_idx] \
- += _param_reg[RPM_REGULATOR_PARAM_##_idx]; \
- }
- #define RPM_VREG_AGGR_OR(_idx, _param_aggr, _param_reg) \
- { \
- _param_aggr[RPM_REGULATOR_PARAM_##_idx] \
- |= _param_reg[RPM_REGULATOR_PARAM_##_idx]; \
- }
- /*
- * Aggregation is performed on each parameter based on the way that the RPM
- * aggregates that type internally between RPM masters.
- */
- static void rpm_vreg_aggregate_params(u32 *param_aggr, const u32 *param_reg)
- {
- RPM_VREG_AGGR_MAX(ENABLE, param_aggr, param_reg);
- RPM_VREG_AGGR_MAX(VOLTAGE, param_aggr, param_reg);
- RPM_VREG_AGGR_SUM(CURRENT, param_aggr, param_reg);
- RPM_VREG_AGGR_MAX(MODE_LDO, param_aggr, param_reg);
- RPM_VREG_AGGR_MAX(MODE_SMPS, param_aggr, param_reg);
- RPM_VREG_AGGR_OR(PIN_CTRL_ENABLE, param_aggr, param_reg);
- RPM_VREG_AGGR_OR(PIN_CTRL_MODE, param_aggr, param_reg);
- RPM_VREG_AGGR_MIN(FREQUENCY, param_aggr, param_reg);
- RPM_VREG_AGGR_MAX(HEAD_ROOM, param_aggr, param_reg);
- RPM_VREG_AGGR_MAX(QUIET_MODE, param_aggr, param_reg);
- RPM_VREG_AGGR_MAX(FREQ_REASON, param_aggr, param_reg);
- RPM_VREG_AGGR_MAX(CORNER, param_aggr, param_reg);
- RPM_VREG_AGGR_MAX(BYPASS, param_aggr, param_reg);
- RPM_VREG_AGGR_MAX(FLOOR_CORNER, param_aggr, param_reg);
- RPM_VREG_AGGR_MAX(LEVEL, param_aggr, param_reg);
- RPM_VREG_AGGR_MAX(FLOOR_LEVEL, param_aggr, param_reg);
- RPM_VREG_AGGR_MAX(MODE_BOB, param_aggr, param_reg);
- RPM_VREG_AGGR_MAX(PIN_CTRL_VOLTAGE1, param_aggr, param_reg);
- RPM_VREG_AGGR_MAX(PIN_CTRL_VOLTAGE2, param_aggr, param_reg);
- RPM_VREG_AGGR_MAX(PIN_CTRL_VOLTAGE3, param_aggr, param_reg);
- }
- static int rpm_vreg_aggregate_requests(struct rpm_regulator *regulator)
- {
- struct rpm_vreg *rpm_vreg = regulator->rpm_vreg;
- u32 param_active[RPM_REGULATOR_PARAM_MAX];
- u32 param_sleep[RPM_REGULATOR_PARAM_MAX];
- u32 modified_active, modified_sleep;
- struct rpm_regulator *reg;
- bool sleep_set_differs = false;
- bool send_active = false;
- bool send_sleep = false;
- bool wait_for_ack;
- int rc = 0;
- int i;
- memset(param_active, 0, sizeof(param_active));
- memset(param_sleep, 0, sizeof(param_sleep));
- modified_active = rpm_vreg->aggr_req_active.modified;
- modified_sleep = rpm_vreg->aggr_req_sleep.modified;
- /*
- * Aggregate all of the requests for this regulator in both active
- * and sleep sets.
- */
- list_for_each_entry(reg, &rpm_vreg->reg_list, list) {
- if (reg->set_active) {
- rpm_vreg_aggregate_params(param_active, reg->req.param);
- modified_active |= reg->req.modified;
- }
- if (reg->set_sleep) {
- rpm_vreg_aggregate_params(param_sleep, reg->req.param);
- modified_sleep |= reg->req.modified;
- }
- }
- /*
- * Check if the aggregated sleep set parameter values differ from the
- * aggregated active set parameter values.
- */
- if (!rpm_vreg->sleep_request_sent) {
- for (i = 0; i < RPM_REGULATOR_PARAM_MAX; i++) {
- if ((param_active[i] != param_sleep[i])
- && (modified_sleep & BIT(i))) {
- sleep_set_differs = true;
- break;
- }
- }
- }
- /* Add KVPs to the active set RPM request if they have new values. */
- rpm_vreg_check_modified_requests(rpm_vreg->aggr_req_active.param,
- param_active, rpm_vreg->aggr_req_active.valid,
- &modified_active);
- rc = rpm_vreg_add_modified_requests(regulator, RPM_SET_ACTIVE,
- param_active, modified_active);
- if (rc)
- return rc;
- send_active = modified_active;
- /*
- * Sleep set configurations are only sent if they differ from the
- * active set values. This is because the active set values will take
- * effect during rpm assisted power collapse in the absence of sleep set
- * values.
- *
- * However, once a sleep set request is sent for a given regulator,
- * additional sleep set requests must be sent in the future even if they
- * match the corresponding active set requests.
- */
- if (rpm_vreg->sleep_request_sent || sleep_set_differs) {
- /* Add KVPs to the sleep set RPM request if they are new. */
- rpm_vreg_check_modified_requests(rpm_vreg->aggr_req_sleep.param,
- param_sleep, rpm_vreg->aggr_req_sleep.valid,
- &modified_sleep);
- rc = rpm_vreg_add_modified_requests(regulator, RPM_SET_SLEEP,
- param_sleep, modified_sleep);
- if (rc)
- return rc;
- send_sleep = modified_sleep;
- }
- /* Send active set request to the RPM if it contains new KVPs. */
- if (send_active) {
- wait_for_ack = rpm_vreg_ack_required(rpm_vreg, RPM_SET_ACTIVE,
- rpm_vreg->aggr_req_active.param,
- param_active,
- rpm_vreg->aggr_req_active.valid,
- modified_active);
- rc = rpm_vreg_send_request(regulator, RPM_SET_ACTIVE,
- wait_for_ack);
- if (rc)
- return rc;
- rpm_vreg->aggr_req_active.valid |= modified_active;
- rpm_vreg->wait_for_ack_active = false;
- }
- /* Store the results of the aggregation. */
- rpm_vreg->aggr_req_active.modified = modified_active;
- memcpy(rpm_vreg->aggr_req_active.param, param_active,
- sizeof(param_active));
- /* Handle debug printing of the active set request. */
- rpm_regulator_req(regulator, RPM_SET_ACTIVE, send_active);
- if (send_active)
- rpm_vreg->aggr_req_active.modified = 0;
- /* Send sleep set request to the RPM if it contains new KVPs. */
- if (send_sleep) {
- wait_for_ack = rpm_vreg_ack_required(rpm_vreg, RPM_SET_SLEEP,
- rpm_vreg->aggr_req_sleep.param,
- param_sleep,
- rpm_vreg->aggr_req_sleep.valid,
- modified_sleep);
- rc = rpm_vreg_send_request(regulator, RPM_SET_SLEEP,
- wait_for_ack);
- if (rc)
- return rc;
- rpm_vreg->sleep_request_sent = true;
- rpm_vreg->aggr_req_sleep.valid |= modified_sleep;
- rpm_vreg->wait_for_ack_sleep = false;
- }
- /* Store the results of the aggregation. */
- rpm_vreg->aggr_req_sleep.modified = modified_sleep;
- memcpy(rpm_vreg->aggr_req_sleep.param, param_sleep,
- sizeof(param_sleep));
- /* Handle debug printing of the sleep set request. */
- rpm_regulator_req(regulator, RPM_SET_SLEEP, send_sleep);
- if (send_sleep)
- rpm_vreg->aggr_req_sleep.modified = 0;
- /*
- * Loop over all requests for this regulator to update the valid and
- * modified values for use in future aggregation.
- */
- list_for_each_entry(reg, &rpm_vreg->reg_list, list) {
- reg->req.valid |= reg->req.modified;
- reg->req.modified = 0;
- }
- return rc;
- }
- static int rpm_vreg_is_enabled(struct regulator_dev *rdev)
- {
- struct rpm_regulator *reg = rdev_get_drvdata(rdev);
- if (likely(!reg->use_pin_ctrl_for_enable))
- return reg->req.param[RPM_REGULATOR_PARAM_ENABLE];
- else
- return reg->req.param[RPM_REGULATOR_PARAM_PIN_CTRL_ENABLE]
- == reg->pin_ctrl_mask[RPM_VREG_PIN_CTRL_STATE_ENABLE];
- }
- static int rpm_vreg_enable(struct regulator_dev *rdev)
- {
- struct rpm_regulator *reg = rdev_get_drvdata(rdev);
- int rc;
- u32 prev_enable;
- rpm_vreg_lock(reg->rpm_vreg);
- if (likely(!reg->use_pin_ctrl_for_enable)) {
- /* Enable using swen KVP. */
- prev_enable = reg->req.param[RPM_REGULATOR_PARAM_ENABLE];
- RPM_VREG_SET_PARAM(reg, ENABLE, 1);
- rc = rpm_vreg_aggregate_requests(reg);
- if (rc) {
- vreg_err(reg, "enable failed, rc=%d\n", rc);
- RPM_VREG_SET_PARAM(reg, ENABLE, prev_enable);
- }
- } else {
- /* Enable using pcen KVP. */
- prev_enable
- = reg->req.param[RPM_REGULATOR_PARAM_PIN_CTRL_ENABLE];
- RPM_VREG_SET_PARAM(reg, PIN_CTRL_ENABLE,
- reg->pin_ctrl_mask[RPM_VREG_PIN_CTRL_STATE_ENABLE]);
- rc = rpm_vreg_aggregate_requests(reg);
- if (rc) {
- vreg_err(reg, "enable failed, rc=%d\n", rc);
- RPM_VREG_SET_PARAM(reg, PIN_CTRL_ENABLE, prev_enable);
- }
- }
- rpm_vreg_unlock(reg->rpm_vreg);
- return rc;
- }
- static int rpm_vreg_disable(struct regulator_dev *rdev)
- {
- struct rpm_regulator *reg = rdev_get_drvdata(rdev);
- int rc;
- u32 prev_enable;
- rpm_vreg_lock(reg->rpm_vreg);
- if (likely(!reg->use_pin_ctrl_for_enable)) {
- /* Disable using swen KVP. */
- prev_enable = reg->req.param[RPM_REGULATOR_PARAM_ENABLE];
- RPM_VREG_SET_PARAM(reg, ENABLE, 0);
- rc = rpm_vreg_aggregate_requests(reg);
- if (rc) {
- vreg_err(reg, "disable failed, rc=%d\n", rc);
- RPM_VREG_SET_PARAM(reg, ENABLE, prev_enable);
- }
- } else {
- /* Disable using pcen KVP. */
- prev_enable
- = reg->req.param[RPM_REGULATOR_PARAM_PIN_CTRL_ENABLE];
- RPM_VREG_SET_PARAM(reg, PIN_CTRL_ENABLE,
- reg->pin_ctrl_mask[RPM_VREG_PIN_CTRL_STATE_DISABLE]);
- rc = rpm_vreg_aggregate_requests(reg);
- if (rc) {
- vreg_err(reg, "disable failed, rc=%d\n", rc);
- RPM_VREG_SET_PARAM(reg, PIN_CTRL_ENABLE, prev_enable);
- }
- }
- rpm_vreg_unlock(reg->rpm_vreg);
- return rc;
- }
- #define RPM_VREG_SET_VOLTAGE(_regulator, _val) \
- { \
- (_regulator)->req.param[(_regulator)->voltage_index] = _val; \
- (_regulator)->req.modified |= BIT((_regulator)->voltage_index); \
- } \
- static int rpm_vreg_set_voltage(struct regulator_dev *rdev, int min_uV,
- int max_uV, unsigned int *selector)
- {
- struct rpm_regulator *reg = rdev_get_drvdata(rdev);
- int rc = 0;
- int voltage;
- u32 prev_voltage;
- voltage = min_uV - reg->voltage_offset;
- if (voltage < params[reg->voltage_index].min
- || voltage > params[reg->voltage_index].max) {
- vreg_err(reg, "voltage=%d for key=%s is not within allowed range: [%u, %u]\n",
- voltage, params[reg->voltage_index].name,
- params[reg->voltage_index].min,
- params[reg->voltage_index].max);
- return -EINVAL;
- }
- rpm_vreg_lock(reg->rpm_vreg);
- prev_voltage = reg->req.param[reg->voltage_index];
- RPM_VREG_SET_VOLTAGE(reg, voltage);
- rpm_vreg_check_param_max(reg, reg->voltage_index,
- max_uV - reg->voltage_offset);
- /*
- * Only send a new voltage if the regulator is currently enabled or
- * if the regulator has been configured to always send voltage updates.
- */
- if (reg->always_send_voltage
- || rpm_vreg_active_or_sleep_enabled(reg->rpm_vreg)
- || rpm_vreg_shared_active_or_sleep_enabled_valid(reg->rpm_vreg))
- rc = rpm_vreg_aggregate_requests(reg);
- if (rc) {
- vreg_err(reg, "set voltage for key=%s failed, rc=%d\n",
- params[reg->voltage_index].name, rc);
- RPM_VREG_SET_VOLTAGE(reg, prev_voltage);
- }
- rpm_vreg_unlock(reg->rpm_vreg);
- return rc;
- }
- static int rpm_vreg_get_voltage(struct regulator_dev *rdev)
- {
- struct rpm_regulator *reg = rdev_get_drvdata(rdev);
- int uV;
- uV = reg->req.param[reg->voltage_index] + reg->voltage_offset;
- if (uV == 0)
- uV = VOLTAGE_UNKNOWN;
- return uV;
- }
- #define REGULATOR_MODE_PMIC4_LDO_LPM 0
- #define REGULATOR_MODE_PMIC4_LDO_HPM 1
- #define REGULATOR_MODE_PMIC5_LDO_RM 3
- #define REGULATOR_MODE_PMIC5_LDO_LPM 4
- #define REGULATOR_MODE_PMIC5_LDO_HPM 7
- static int _rpm_vreg_ldo_set_mode(struct regulator_dev *rdev, unsigned int mode)
- {
- struct rpm_regulator *reg = rdev_get_drvdata(rdev);
- u32 hw_mode;
- int rc = 0;
- switch (mode) {
- case REGULATOR_MODE_NORMAL:
- switch (reg->rpm_vreg->regulator_hw_type) {
- case RPM_REGULATOR_HW_TYPE_PMIC4_LDO:
- hw_mode = REGULATOR_MODE_PMIC4_LDO_HPM;
- break;
- case RPM_REGULATOR_HW_TYPE_PMIC5_LDO:
- hw_mode = REGULATOR_MODE_PMIC5_LDO_HPM;
- break;
- default:
- vreg_err(reg, "unsupported ldo hw type: %d\n",
- reg->rpm_vreg->regulator_hw_type);
- return -EINVAL;
- }
- break;
- case REGULATOR_MODE_IDLE:
- switch (reg->rpm_vreg->regulator_hw_type) {
- case RPM_REGULATOR_HW_TYPE_PMIC4_LDO:
- hw_mode = REGULATOR_MODE_PMIC4_LDO_LPM;
- break;
- case RPM_REGULATOR_HW_TYPE_PMIC5_LDO:
- hw_mode = REGULATOR_MODE_PMIC5_LDO_LPM;
- break;
- default:
- vreg_err(reg, "unsupported ldo hw type: %d\n",
- reg->rpm_vreg->regulator_hw_type);
- return -EINVAL;
- }
- break;
- case REGULATOR_MODE_STANDBY:
- switch (reg->rpm_vreg->regulator_hw_type) {
- case RPM_REGULATOR_HW_TYPE_PMIC5_LDO:
- hw_mode = REGULATOR_MODE_PMIC5_LDO_RM;
- /* This mode must be supported explicitly */
- if (!reg->rpm_vreg->mode_count) {
- vreg_err(reg, "unsupported mode: %u\n", mode);
- return -EINVAL;
- }
- break;
- default:
- vreg_err(reg, "unsupported ldo hw type: %d\n",
- reg->rpm_vreg->regulator_hw_type);
- return -EINVAL;
- }
- break;
- default:
- vreg_err(reg, "invalid mode: %u\n", mode);
- return -EINVAL;
- }
- RPM_VREG_SET_PARAM(reg, MODE_LDO, hw_mode);
- /*
- * Only send the mode if the regulator is currently enabled or if the
- * regulator has been configured to always send current updates.
- */
- if (reg->always_send_current
- || rpm_vreg_active_or_sleep_enabled(reg->rpm_vreg)
- || rpm_vreg_shared_active_or_sleep_enabled_valid(reg->rpm_vreg))
- rc = rpm_vreg_aggregate_requests(reg);
- if (rc)
- vreg_err(reg, "set mode failed, rc=%d\n", rc);
- return rc;
- }
- static int rpm_vreg_ldo_set_mode(struct regulator_dev *rdev, unsigned int mode)
- {
- struct rpm_regulator *reg = rdev_get_drvdata(rdev);
- int i, rc = 0;
- if (reg->rpm_vreg->mode_count && reg->rpm_vreg->regulator_hw_type ==
- RPM_REGULATOR_HW_TYPE_PMIC5_LDO) {
- /* Confirm requested mode is among those supported for PMIC5 LDO*/
- for (i = 0; i < reg->rpm_vreg->mode_count; i++)
- if (reg->rpm_vreg->mode[i].mode == mode)
- break;
- if (i == reg->rpm_vreg->mode_count) {
- vreg_err(reg, "unsupported LDO mode: %u\n", mode);
- return -EINVAL;
- }
- }
- rpm_vreg_lock(reg->rpm_vreg);
- rc = _rpm_vreg_ldo_set_mode(rdev, mode);
- rpm_vreg_unlock(reg->rpm_vreg);
- return rc;
- }
- static unsigned int rpm_vreg_ldo_get_mode(struct regulator_dev *rdev)
- {
- struct rpm_regulator *reg = rdev_get_drvdata(rdev);
- u32 hw_mode;
- hw_mode = reg->req.param[RPM_REGULATOR_PARAM_MODE_LDO];
- switch (hw_mode) {
- case REGULATOR_MODE_PMIC4_LDO_HPM:
- case REGULATOR_MODE_PMIC5_LDO_HPM:
- return REGULATOR_MODE_NORMAL;
- case REGULATOR_MODE_PMIC5_LDO_RM:
- return REGULATOR_MODE_STANDBY;
- case REGULATOR_MODE_PMIC4_LDO_LPM:
- case REGULATOR_MODE_PMIC5_LDO_LPM:
- default:
- return REGULATOR_MODE_IDLE;
- }
- }
- static int rpm_vreg_ldo_set_load(struct regulator_dev *rdev, int load_uA)
- {
- struct rpm_regulator *reg = rdev_get_drvdata(rdev);
- unsigned int mode;
- int rc = 0, i;
- rpm_vreg_lock(reg->rpm_vreg);
- /* Supported modes are retention, LPM and HPM. */
- if (reg->rpm_vreg->mode_count && reg->rpm_vreg->regulator_hw_type ==
- RPM_REGULATOR_HW_TYPE_PMIC5_LDO) {
- /* Confirm requested mode is among those supported for PMIC5 LDO*/
- for (i = reg->rpm_vreg->mode_count - 1; i > 0; i--)
- if (reg->rpm_vreg->mode[i].min_load_ua <= load_uA + reg->system_load)
- break;
- mode = reg->rpm_vreg->mode[i].mode;
- } else {
- mode = (load_uA + reg->system_load >= reg->rpm_vreg->hpm_min_load)
- ? REGULATOR_MODE_NORMAL : REGULATOR_MODE_IDLE;
- }
- rc = _rpm_vreg_ldo_set_mode(rdev, mode);
- rpm_vreg_unlock(reg->rpm_vreg);
- return rc;
- }
- static int rpm_vreg_set_mode(struct regulator_dev *rdev, unsigned int mode)
- {
- struct rpm_regulator *reg = rdev_get_drvdata(rdev);
- int rc = 0;
- u32 prev_current;
- int prev_uA;
- rpm_vreg_lock(reg->rpm_vreg);
- prev_current = reg->req.param[RPM_REGULATOR_PARAM_CURRENT];
- prev_uA = MILLI_TO_MICRO(prev_current);
- if (mode == REGULATOR_MODE_NORMAL) {
- /* Make sure that request current is in HPM range. */
- if (prev_uA < rpm_vreg_hpm_min_uA(reg->rpm_vreg))
- RPM_VREG_SET_PARAM(reg, CURRENT,
- MICRO_TO_MILLI(rpm_vreg_hpm_min_uA(reg->rpm_vreg)));
- } else if (REGULATOR_MODE_IDLE) {
- /* Make sure that request current is in LPM range. */
- if (prev_uA > rpm_vreg_lpm_max_uA(reg->rpm_vreg))
- RPM_VREG_SET_PARAM(reg, CURRENT,
- MICRO_TO_MILLI(rpm_vreg_lpm_max_uA(reg->rpm_vreg)));
- } else {
- vreg_err(reg, "invalid mode: %u\n", mode);
- rpm_vreg_unlock(reg->rpm_vreg);
- return -EINVAL;
- }
- /*
- * Only send a new load current value if the regulator is currently
- * enabled or if the regulator has been configured to always send
- * current updates.
- */
- if (reg->always_send_current
- || rpm_vreg_active_or_sleep_enabled(reg->rpm_vreg)
- || rpm_vreg_shared_active_or_sleep_enabled_valid(reg->rpm_vreg))
- rc = rpm_vreg_aggregate_requests(reg);
- if (rc) {
- vreg_err(reg, "set mode failed, rc=%d\n", rc);
- RPM_VREG_SET_PARAM(reg, CURRENT, prev_current);
- }
- rpm_vreg_unlock(reg->rpm_vreg);
- return rc;
- }
- static unsigned int rpm_vreg_get_mode(struct regulator_dev *rdev)
- {
- struct rpm_regulator *reg = rdev_get_drvdata(rdev);
- return (reg->req.param[RPM_REGULATOR_PARAM_CURRENT]
- >= MICRO_TO_MILLI(reg->rpm_vreg->hpm_min_load))
- ? REGULATOR_MODE_NORMAL : REGULATOR_MODE_IDLE;
- }
- static unsigned int rpm_vreg_get_optimum_mode(struct regulator_dev *rdev,
- int input_uV, int output_uV, int load_uA)
- {
- struct rpm_regulator *reg = rdev_get_drvdata(rdev);
- u32 load_mA;
- load_uA += reg->system_load;
- load_mA = MICRO_TO_MILLI(load_uA);
- if (load_mA > params[RPM_REGULATOR_PARAM_CURRENT].max)
- load_mA = params[RPM_REGULATOR_PARAM_CURRENT].max;
- rpm_vreg_lock(reg->rpm_vreg);
- RPM_VREG_SET_PARAM(reg, CURRENT, load_mA);
- rpm_vreg_unlock(reg->rpm_vreg);
- return (load_uA >= reg->rpm_vreg->hpm_min_load)
- ? REGULATOR_MODE_NORMAL : REGULATOR_MODE_IDLE;
- }
- static int rpm_vreg_set_bob_mode(struct regulator_dev *rdev, unsigned int mode)
- {
- struct rpm_regulator *reg = rdev_get_drvdata(rdev);
- int rc;
- u32 hw_mode, hw_type, prev_mode;
- rpm_vreg_lock(reg->rpm_vreg);
- prev_mode = reg->req.param[RPM_REGULATOR_PARAM_MODE_BOB];
- hw_type = reg->rpm_vreg->regulator_hw_type;
- if (hw_type == RPM_REGULATOR_HW_TYPE_PMIC4_BOB) {
- switch (mode) {
- case REGULATOR_MODE_FAST:
- hw_mode = RPM_REGULATOR_PMIC4_BOB_MODE_PWM;
- break;
- case REGULATOR_MODE_NORMAL:
- hw_mode = RPM_REGULATOR_PMIC4_BOB_MODE_AUTO;
- break;
- case REGULATOR_MODE_IDLE:
- hw_mode = RPM_REGULATOR_PMIC4_BOB_MODE_PFM;
- break;
- case REGULATOR_MODE_STANDBY:
- hw_mode = RPM_REGULATOR_PMIC4_BOB_MODE_PASS;
- break;
- default:
- vreg_err(reg, "invalid mode: %u\n", mode);
- rpm_vreg_unlock(reg->rpm_vreg);
- return -EINVAL;
- }
- } else if (hw_type == RPM_REGULATOR_HW_TYPE_PMIC5_BOB) {
- switch (mode) {
- case REGULATOR_MODE_FAST:
- hw_mode = RPM_REGULATOR_PMIC5_BOB_MODE_PWM;
- break;
- case REGULATOR_MODE_NORMAL:
- hw_mode = RPM_REGULATOR_PMIC5_BOB_MODE_AUTO;
- break;
- case REGULATOR_MODE_IDLE:
- hw_mode = RPM_REGULATOR_PMIC5_BOB_MODE_PFM;
- break;
- case REGULATOR_MODE_STANDBY:
- hw_mode = RPM_REGULATOR_PMIC5_BOB_MODE_PASS;
- break;
- default:
- vreg_err(reg, "invalid mode: %u\n", mode);
- rpm_vreg_unlock(reg->rpm_vreg);
- return -EINVAL;
- }
- } else {
- vreg_err(reg, "unsupported bob hw type: %d\n",
- reg->rpm_vreg->regulator_hw_type);
- rpm_vreg_unlock(reg->rpm_vreg);
- return -EINVAL;
- }
- RPM_VREG_SET_PARAM(reg, MODE_BOB, hw_mode);
- rc = rpm_vreg_aggregate_requests(reg);
- if (rc) {
- vreg_err(reg, "set BoB mode failed, rc=%d\n", rc);
- RPM_VREG_SET_PARAM(reg, MODE_BOB, prev_mode);
- }
- rpm_vreg_unlock(reg->rpm_vreg);
- return rc;
- }
- static unsigned int rpm_vreg_get_bob_mode(struct regulator_dev *rdev)
- {
- struct rpm_regulator *reg = rdev_get_drvdata(rdev);
- unsigned int mode = REGULATOR_MODE_NORMAL;
- u32 hw_type = reg->rpm_vreg->regulator_hw_type;
- if (hw_type == RPM_REGULATOR_HW_TYPE_PMIC4_BOB) {
- switch (reg->req.param[RPM_REGULATOR_PARAM_MODE_BOB]) {
- case RPM_REGULATOR_PMIC4_BOB_MODE_PWM:
- mode = REGULATOR_MODE_FAST;
- break;
- case RPM_REGULATOR_PMIC4_BOB_MODE_AUTO:
- mode = REGULATOR_MODE_NORMAL;
- break;
- case RPM_REGULATOR_PMIC4_BOB_MODE_PFM:
- mode = REGULATOR_MODE_IDLE;
- break;
- case RPM_REGULATOR_PMIC4_BOB_MODE_PASS:
- mode = REGULATOR_MODE_STANDBY;
- break;
- default:
- vreg_err(reg, "BoB mode unknown\n");
- }
- } else if (hw_type == RPM_REGULATOR_HW_TYPE_PMIC5_BOB) {
- switch (reg->req.param[RPM_REGULATOR_PARAM_MODE_BOB]) {
- case RPM_REGULATOR_PMIC5_BOB_MODE_PWM:
- mode = REGULATOR_MODE_FAST;
- break;
- case RPM_REGULATOR_PMIC5_BOB_MODE_AUTO:
- mode = REGULATOR_MODE_NORMAL;
- break;
- case RPM_REGULATOR_PMIC5_BOB_MODE_PFM:
- mode = REGULATOR_MODE_IDLE;
- break;
- case RPM_REGULATOR_PMIC5_BOB_MODE_PASS:
- mode = REGULATOR_MODE_STANDBY;
- break;
- default:
- vreg_err(reg, "BoB mode unknown\n");
- }
- }
- return mode;
- }
- #define RPM_SMD_REGULATOR_MAX_MODES 5
- static const int bob_supported_modes[RPM_SMD_REGULATOR_MAX_MODES] = {
- [RPM_SMD_REGULATOR_MODE_PASS] = REGULATOR_MODE_STANDBY,
- [RPM_SMD_REGULATOR_MODE_RET] = REGULATOR_MODE_INVALID,
- [RPM_SMD_REGULATOR_MODE_LPM] = REGULATOR_MODE_IDLE,
- [RPM_SMD_REGULATOR_MODE_AUTO] = REGULATOR_MODE_NORMAL,
- [RPM_SMD_REGULATOR_MODE_HPM] = REGULATOR_MODE_FAST,
- };
- static const int ldo5_supported_modes[RPM_SMD_REGULATOR_MAX_MODES] = {
- [RPM_SMD_REGULATOR_MODE_PASS] = REGULATOR_MODE_INVALID,
- [RPM_SMD_REGULATOR_MODE_RET] = REGULATOR_MODE_STANDBY,
- [RPM_SMD_REGULATOR_MODE_LPM] = REGULATOR_MODE_IDLE,
- [RPM_SMD_REGULATOR_MODE_AUTO] = REGULATOR_MODE_INVALID,
- [RPM_SMD_REGULATOR_MODE_HPM] = REGULATOR_MODE_NORMAL,
- };
- static int rpm_vreg_bob_set_load(struct regulator_dev *rdev, int load_ua)
- {
- struct rpm_regulator *reg = rdev_get_drvdata(rdev);
- int rc = 0, i;
- unsigned int mode;
- if (!reg->rpm_vreg->mode_count) {
- pr_err("No loads supported for BOB\n");
- return -EINVAL;
- }
- for (i = reg->rpm_vreg->mode_count - 1; i > 0; i--)
- if (reg->rpm_vreg->mode[i].min_load_ua <= load_ua + reg->system_load)
- break;
- mode = reg->rpm_vreg->mode[i].mode;
- rc = rpm_vreg_set_bob_mode(rdev, mode);
- return rc;
- }
- static u32 rpm_vreg_get_hw_mode(struct rpm_regulator *reg, unsigned int mode)
- {
- u32 hw_mode = U32_MAX, hw_type = reg->rpm_vreg->regulator_hw_type;
- switch (mode) {
- case RPM_SMD_REGULATOR_MODE_PASS:
- switch (hw_type) {
- case RPM_REGULATOR_HW_TYPE_PMIC4_BOB:
- hw_mode = RPM_REGULATOR_PMIC4_BOB_MODE_PASS;
- break;
- case RPM_REGULATOR_HW_TYPE_PMIC5_BOB:
- hw_mode = RPM_REGULATOR_PMIC5_BOB_MODE_PASS;
- break;
- case RPM_REGULATOR_HW_TYPE_PMIC4_LDO:
- case RPM_REGULATOR_HW_TYPE_PMIC5_LDO:
- default:
- break;
- }
- break;
- case RPM_SMD_REGULATOR_MODE_RET:
- switch (hw_type) {
- case RPM_REGULATOR_HW_TYPE_PMIC5_LDO:
- hw_mode = REGULATOR_MODE_PMIC5_LDO_RM;
- break;
- case RPM_REGULATOR_HW_TYPE_PMIC4_LDO:
- case RPM_REGULATOR_HW_TYPE_PMIC4_BOB:
- case RPM_REGULATOR_HW_TYPE_PMIC5_BOB:
- default:
- break;
- }
- break;
- case RPM_SMD_REGULATOR_MODE_LPM:
- switch (hw_type) {
- case RPM_REGULATOR_HW_TYPE_PMIC4_BOB:
- hw_mode = RPM_REGULATOR_PMIC4_BOB_MODE_PFM;
- break;
- case RPM_REGULATOR_HW_TYPE_PMIC5_BOB:
- hw_mode = RPM_REGULATOR_PMIC5_BOB_MODE_PFM;
- break;
- case RPM_REGULATOR_HW_TYPE_PMIC4_LDO:
- hw_mode = REGULATOR_MODE_PMIC4_LDO_LPM;
- break;
- case RPM_REGULATOR_HW_TYPE_PMIC5_LDO:
- hw_mode = REGULATOR_MODE_PMIC5_LDO_LPM;
- break;
- default:
- break;
- }
- break;
- case RPM_SMD_REGULATOR_MODE_AUTO:
- switch (hw_type) {
- case RPM_REGULATOR_HW_TYPE_PMIC4_BOB:
- hw_mode = RPM_REGULATOR_PMIC4_BOB_MODE_AUTO;
- break;
- case RPM_REGULATOR_HW_TYPE_PMIC5_BOB:
- hw_mode = RPM_REGULATOR_PMIC5_BOB_MODE_AUTO;
- break;
- case RPM_REGULATOR_HW_TYPE_PMIC4_LDO:
- case RPM_REGULATOR_HW_TYPE_PMIC5_LDO:
- default:
- break;
- }
- break;
- case RPM_SMD_REGULATOR_MODE_HPM:
- switch (hw_type) {
- case RPM_REGULATOR_HW_TYPE_PMIC4_BOB:
- hw_mode = RPM_REGULATOR_PMIC4_BOB_MODE_PWM;
- break;
- case RPM_REGULATOR_HW_TYPE_PMIC5_BOB:
- hw_mode = RPM_REGULATOR_PMIC5_BOB_MODE_PWM;
- break;
- case RPM_REGULATOR_HW_TYPE_PMIC4_LDO:
- hw_mode = REGULATOR_MODE_PMIC4_LDO_HPM;
- break;
- case RPM_REGULATOR_HW_TYPE_PMIC5_LDO:
- hw_mode = REGULATOR_MODE_PMIC5_LDO_HPM;
- break;
- default:
- break;
- }
- break;
- default:
- break;
- }
- if (hw_mode == U32_MAX)
- vreg_err(reg, "Mode %d not supported for regulator type:%d\n", mode, hw_type);
- return hw_mode;
- }
- static int rpm_vreg_enable_time(struct regulator_dev *rdev)
- {
- struct rpm_regulator *reg = rdev_get_drvdata(rdev);
- return reg->rpm_vreg->enable_time;
- }
- static int rpm_vreg_send_defaults(struct rpm_regulator *reg)
- {
- int rc;
- rpm_vreg_lock(reg->rpm_vreg);
- rc = rpm_vreg_aggregate_requests(reg);
- if (rc)
- vreg_err(reg, "RPM request failed, rc=%d", rc);
- rpm_vreg_unlock(reg->rpm_vreg);
- return rc;
- }
- static int rpm_vreg_configure_pin_control_enable(struct rpm_regulator *reg,
- struct device_node *node)
- {
- struct rpm_regulator_param *pcen_param =
- ¶ms[RPM_REGULATOR_PARAM_PIN_CTRL_ENABLE];
- int rc, i;
- if (!of_find_property(node, "qcom,enable-with-pin-ctrl", NULL))
- return 0;
- if (pcen_param->supported_regulator_types
- & BIT(reg->rpm_vreg->regulator_type)) {
- rc = of_property_read_u32_array(node,
- "qcom,enable-with-pin-ctrl", reg->pin_ctrl_mask,
- RPM_VREG_PIN_CTRL_STATE_COUNT);
- if (rc) {
- vreg_err(reg, "could not read qcom,enable-with-pin-ctrl, rc=%d\n",
- rc);
- return rc;
- }
- /* Verify that the mask values are valid. */
- for (i = 0; i < RPM_VREG_PIN_CTRL_STATE_COUNT; i++) {
- if (reg->pin_ctrl_mask[i] < pcen_param->min
- || reg->pin_ctrl_mask[i] > pcen_param->max) {
- vreg_err(reg, "device tree property: qcom,enable-with-pin-ctrl[%d]=%u is outside allowed range [%u, %u]\n",
- i, reg->pin_ctrl_mask[i],
- pcen_param->min, pcen_param->max);
- return -EINVAL;
- }
- }
- reg->use_pin_ctrl_for_enable = true;
- } else {
- pr_warn("%s: regulator type=%d does not support device tree property: qcom,enable-with-pin-ctrl\n",
- reg->rdesc.name, reg->rpm_vreg->regulator_type);
- }
- return 0;
- }
- static const struct regulator_ops ldo_ops = {
- .enable = rpm_vreg_enable,
- .disable = rpm_vreg_disable,
- .is_enabled = rpm_vreg_is_enabled,
- .set_voltage = rpm_vreg_set_voltage,
- .get_voltage = rpm_vreg_get_voltage,
- .set_load = rpm_vreg_ldo_set_load,
- .set_mode = rpm_vreg_ldo_set_mode,
- .get_mode = rpm_vreg_ldo_get_mode,
- .enable_time = rpm_vreg_enable_time,
- };
- static const struct regulator_ops smps_ops = {
- .enable = rpm_vreg_enable,
- .disable = rpm_vreg_disable,
- .is_enabled = rpm_vreg_is_enabled,
- .set_voltage = rpm_vreg_set_voltage,
- .get_voltage = rpm_vreg_get_voltage,
- .set_mode = rpm_vreg_set_mode,
- .get_mode = rpm_vreg_get_mode,
- .get_optimum_mode = rpm_vreg_get_optimum_mode,
- .enable_time = rpm_vreg_enable_time,
- };
- static const struct regulator_ops switch_ops = {
- .enable = rpm_vreg_enable,
- .disable = rpm_vreg_disable,
- .is_enabled = rpm_vreg_is_enabled,
- .enable_time = rpm_vreg_enable_time,
- };
- static const struct regulator_ops ncp_ops = {
- .enable = rpm_vreg_enable,
- .disable = rpm_vreg_disable,
- .is_enabled = rpm_vreg_is_enabled,
- .set_voltage = rpm_vreg_set_voltage,
- .get_voltage = rpm_vreg_get_voltage,
- .enable_time = rpm_vreg_enable_time,
- };
- static const struct regulator_ops bob_ops = {
- .enable = rpm_vreg_enable,
- .disable = rpm_vreg_disable,
- .is_enabled = rpm_vreg_is_enabled,
- .set_voltage = rpm_vreg_set_voltage,
- .get_voltage = rpm_vreg_get_voltage,
- .set_load = rpm_vreg_bob_set_load,
- .set_mode = rpm_vreg_set_bob_mode,
- .get_mode = rpm_vreg_get_bob_mode,
- .enable_time = rpm_vreg_enable_time,
- };
- static const struct regulator_ops *vreg_ops[] = {
- [RPM_REGULATOR_TYPE_LDO] = &ldo_ops,
- [RPM_REGULATOR_TYPE_SMPS] = &smps_ops,
- [RPM_REGULATOR_TYPE_VS] = &switch_ops,
- [RPM_REGULATOR_TYPE_NCP] = &ncp_ops,
- [RPM_REGULATOR_TYPE_BOB] = &bob_ops,
- };
- static int rpm_vreg_device_remove(struct platform_device *pdev)
- {
- struct device *dev = &pdev->dev;
- struct rpm_regulator *reg;
- struct rpm_vreg *rpm_vreg;
- reg = platform_get_drvdata(pdev);
- if (reg) {
- rpm_vreg = reg->rpm_vreg;
- rpm_vreg_lock(rpm_vreg);
- regulator_unregister(reg->rdev);
- devm_regulator_proxy_consumer_unregister(pdev->dev.parent);
- list_del(®->list);
- kfree(reg);
- rpm_vreg_unlock(rpm_vreg);
- } else {
- dev_err(dev, "%s: drvdata missing\n", __func__);
- return -EINVAL;
- }
- platform_set_drvdata(pdev, NULL);
- return 0;
- }
- static int rpm_vreg_resource_remove(struct platform_device *pdev)
- {
- struct device *dev = &pdev->dev;
- struct rpm_regulator *reg, *reg_temp;
- struct rpm_vreg *rpm_vreg;
- rpm_vreg = platform_get_drvdata(pdev);
- if (rpm_vreg) {
- rpm_vreg_lock(rpm_vreg);
- list_for_each_entry_safe(reg, reg_temp, &rpm_vreg->reg_list,
- list) {
- /* Only touch data for private consumers. */
- if (reg->rdev->desc == NULL) {
- list_del(®->list);
- kfree(reg->rdev);
- kfree(reg);
- } else {
- dev_err(dev, "%s: not all child devices have been removed\n",
- __func__);
- }
- }
- rpm_vreg_unlock(rpm_vreg);
- msm_rpm_free_request(rpm_vreg->handle_active);
- msm_rpm_free_request(rpm_vreg->handle_sleep);
- kfree(rpm_vreg);
- } else {
- dev_err(dev, "%s: drvdata missing\n", __func__);
- return -EINVAL;
- }
- platform_set_drvdata(pdev, NULL);
- return 0;
- }
- static int rpm_vreg_set_smps_ldo_voltage_index(struct device *dev,
- struct rpm_regulator *reg)
- {
- struct device_node *node = dev->of_node;
- int chosen = 0;
- if (of_property_read_bool(node, "qcom,use-voltage-corner")) {
- reg->voltage_index = RPM_REGULATOR_PARAM_CORNER;
- reg->voltage_offset = RPM_REGULATOR_CORNER_NONE;
- chosen++;
- }
- if (of_property_read_bool(node, "qcom,use-voltage-floor-corner")) {
- reg->voltage_index = RPM_REGULATOR_PARAM_FLOOR_CORNER;
- reg->voltage_offset = RPM_REGULATOR_CORNER_NONE;
- chosen++;
- }
- if (of_property_read_bool(node, "qcom,use-voltage-level")) {
- reg->voltage_index = RPM_REGULATOR_PARAM_LEVEL;
- chosen++;
- }
- if (of_property_read_bool(node, "qcom,use-voltage-floor-level")) {
- reg->voltage_index = RPM_REGULATOR_PARAM_FLOOR_LEVEL;
- chosen++;
- }
- if (chosen > 1) {
- dev_err(dev, "only one qcom,use-voltage-* may be specified\n");
- return -EINVAL;
- }
- return 0;
- }
- static int rpm_vreg_set_bob_voltage_index(struct device *dev,
- struct rpm_regulator *reg)
- {
- struct device_node *node = dev->of_node;
- int chosen = 0;
- if (of_property_read_bool(node, "qcom,use-pin-ctrl-voltage1")) {
- reg->voltage_index = RPM_REGULATOR_PARAM_PIN_CTRL_VOLTAGE1;
- chosen++;
- }
- if (of_property_read_bool(node, "qcom,use-pin-ctrl-voltage2")) {
- reg->voltage_index = RPM_REGULATOR_PARAM_PIN_CTRL_VOLTAGE2;
- chosen++;
- }
- if (of_property_read_bool(node, "qcom,use-pin-ctrl-voltage3")) {
- reg->voltage_index = RPM_REGULATOR_PARAM_PIN_CTRL_VOLTAGE3;
- chosen++;
- }
- if (chosen > 1) {
- dev_err(dev, "only one qcom,use-pin-ctrl-voltage* may be specified\n");
- return -EINVAL;
- }
- return 0;
- }
- static int rpm_vreg_device_set_voltage_index(struct device *dev,
- struct rpm_regulator *reg, int type)
- {
- int rc = 0;
- reg->voltage_index = RPM_REGULATOR_PARAM_VOLTAGE;
- switch (type) {
- case RPM_REGULATOR_TYPE_SMPS:
- case RPM_REGULATOR_TYPE_LDO:
- rc = rpm_vreg_set_smps_ldo_voltage_index(dev, reg);
- break;
- case RPM_REGULATOR_TYPE_BOB:
- rc = rpm_vreg_set_bob_voltage_index(dev, reg);
- break;
- }
- return rc;
- }
- #ifdef CONFIG_DEBUG_FS
- static void rpm_vreg_create_debugfs(struct rpm_regulator *reg)
- {
- if (!is_debugfs_created) {
- reg->dfs_root = debugfs_create_dir("rpm_vreg_debugfs", NULL);
- if (IS_ERR_OR_NULL(reg->dfs_root)) {
- pr_err("Failed to create debugfs directory rc=%ld\n",
- (long)reg->dfs_root);
- return;
- }
- debugfs_create_u32("debug_mask", 0600, reg->dfs_root,
- &rpm_vreg_debug_mask);
- is_debugfs_created = true;
- }
- }
- #endif
- /*
- * This probe is called for child rpm-regulator devices which have
- * properties which are required to configure individual regulator
- * framework regulators for a given RPM regulator resource.
- */
- static int rpm_vreg_device_probe(struct platform_device *pdev)
- {
- struct device *dev = &pdev->dev;
- struct device_node *node = dev->of_node;
- struct regulator_init_data *init_data;
- struct rpm_vreg *rpm_vreg;
- struct rpm_regulator *reg;
- struct regulator_config reg_config = {};
- int rc = 0;
- int i, regulator_type;
- u32 val;
- if (pdev->dev.parent == NULL) {
- dev_err(dev, "%s: parent device missing\n", __func__);
- return -ENODEV;
- }
- rpm_vreg = dev_get_drvdata(pdev->dev.parent);
- if (rpm_vreg == NULL) {
- dev_err(dev, "%s: rpm_vreg not found in parent device\n",
- __func__);
- return -ENODEV;
- }
- reg = kzalloc(sizeof(*reg), GFP_KERNEL);
- if (reg == NULL)
- return -ENOMEM;
- regulator_type = rpm_vreg->regulator_type;
- reg->rpm_vreg = rpm_vreg;
- reg->rdesc.owner = THIS_MODULE;
- reg->rdesc.type = REGULATOR_VOLTAGE;
- reg->rdesc.ops = vreg_ops[regulator_type];
- rc = rpm_vreg_device_set_voltage_index(dev, reg, regulator_type);
- if (rc)
- goto fail_free_reg;
- reg->always_send_voltage
- = of_property_read_bool(node, "qcom,always-send-voltage");
- reg->always_send_current
- = of_property_read_bool(node, "qcom,always-send-current");
- if (regulator_type == RPM_REGULATOR_TYPE_VS)
- reg->rdesc.n_voltages = 0;
- else
- reg->rdesc.n_voltages = 2;
- rc = of_property_read_u32(node, "qcom,set", &val);
- if (rc) {
- dev_err(dev, "%s: sleep set and/or active set must be configured via qcom,set property, rc=%d\n",
- __func__, rc);
- goto fail_free_reg;
- } else if (!(val & RPM_SET_CONFIG_BOTH)) {
- dev_err(dev, "%s: qcom,set=%u property is invalid\n", __func__,
- val);
- rc = -EINVAL;
- goto fail_free_reg;
- }
- reg->set_active = !!(val & RPM_SET_CONFIG_ACTIVE);
- reg->set_sleep = !!(val & RPM_SET_CONFIG_SLEEP);
- rc = of_property_read_u32(node, "qcom,min-dropout-voltage",
- &val);
- if (!rc)
- reg->rdesc.min_dropout_uV = val;
- init_data = of_get_regulator_init_data(dev, node, ®->rdesc);
- if (init_data == NULL) {
- dev_err(dev, "%s: failed to populate regulator_init_data\n",
- __func__);
- rc = -ENOMEM;
- goto fail_free_reg;
- }
- if (init_data->constraints.name == NULL) {
- dev_err(dev, "%s: regulator name not specified\n", __func__);
- rc = -EINVAL;
- goto fail_free_reg;
- }
- init_data->constraints.input_uV = init_data->constraints.max_uV;
- if (of_get_property(node, "parent-supply", NULL))
- init_data->supply_regulator = "parent";
- /*
- * Fill in ops and mode masks based on callbacks specified for
- * this type of regulator.
- */
- if (reg->rdesc.ops->enable)
- init_data->constraints.valid_ops_mask
- |= REGULATOR_CHANGE_STATUS;
- if (reg->rdesc.ops->get_voltage)
- init_data->constraints.valid_ops_mask
- |= REGULATOR_CHANGE_VOLTAGE;
- if (reg->rdesc.ops->get_mode) {
- init_data->constraints.valid_ops_mask
- |= REGULATOR_CHANGE_MODE | REGULATOR_CHANGE_DRMS;
- init_data->constraints.valid_modes_mask
- |= REGULATOR_MODE_NORMAL | REGULATOR_MODE_IDLE |
- REGULATOR_MODE_FAST | REGULATOR_MODE_STANDBY;
- }
- reg->rdesc.name = init_data->constraints.name;
- reg->min_uV = init_data->constraints.min_uV;
- reg->max_uV = init_data->constraints.max_uV;
- /* Initialize the param array based on optional properties. */
- for (i = 0; i < RPM_REGULATOR_PARAM_MAX; i++) {
- rc = of_property_read_u32(node, params[i].property_name, &val);
- if (rc == 0) {
- if (params[i].supported_regulator_types
- & BIT(regulator_type)) {
- if (val < params[i].min
- || val > params[i].max) {
- pr_warn("%s: device tree property: %s=%u is outsided allowed range [%u, %u]\n",
- reg->rdesc.name,
- params[i].property_name, val,
- params[i].min, params[i].max);
- continue;
- }
- if (i == RPM_REGULATOR_PARAM_MODE_LDO ||
- i == RPM_REGULATOR_PARAM_MODE_BOB) {
- val = rpm_vreg_get_hw_mode(reg, val);
- if (val == U32_MAX)
- continue;
- }
- reg->req.param[i] = val;
- reg->req.modified |= BIT(i);
- } else {
- pr_warn("%s: regulator type=%d does not support device tree property: %s\n",
- reg->rdesc.name, regulator_type,
- params[i].property_name);
- }
- }
- }
- of_property_read_u32(node, "qcom,system-load", ®->system_load);
- rc = rpm_vreg_configure_pin_control_enable(reg, node);
- if (rc) {
- vreg_err(reg, "could not configure pin control enable, rc=%d\n",
- rc);
- goto fail_free_reg;
- }
- rpm_vreg_lock(rpm_vreg);
- list_add(®->list, &rpm_vreg->reg_list);
- rpm_vreg_unlock(rpm_vreg);
- if (of_property_read_bool(node, "qcom,send-defaults")) {
- rc = rpm_vreg_send_defaults(reg);
- if (rc) {
- vreg_err(reg, "could not send defaults, rc=%d\n", rc);
- goto fail_remove_from_list;
- }
- }
- reg_config.dev = dev;
- reg_config.init_data = init_data;
- reg_config.of_node = node;
- reg_config.driver_data = reg;
- reg->rdev = devm_regulator_register(dev, ®->rdesc, ®_config);
- if (IS_ERR(reg->rdev)) {
- rc = PTR_ERR(reg->rdev);
- reg->rdev = NULL;
- pr_err("regulator_register failed: %s, rc=%d\n",
- reg->rdesc.name, rc);
- goto fail_remove_from_list;
- }
- rc = devm_regulator_proxy_consumer_register(dev, node);
- if (rc)
- vreg_err(reg, "failed to register proxy consumer, rc=%d\n", rc);
- platform_set_drvdata(pdev, reg);
- rpm_vreg_create_debugfs(reg);
- rc = devm_regulator_debug_register(dev, reg->rdev);
- if (rc)
- pr_err("Failed to register debug regulator, rc=%d\n", rc);
- pr_debug("successfully probed: %s\n", reg->rdesc.name);
- return 0;
- fail_remove_from_list:
- rpm_vreg_lock(rpm_vreg);
- list_del(®->list);
- rpm_vreg_unlock(rpm_vreg);
- fail_free_reg:
- kfree(reg);
- return rc;
- }
- int init_thresholds(struct device_node *node, struct device *dev,
- struct rpm_vreg *rpm_vreg, int len)
- {
- int rc, i;
- u32 *buf;
- const int *supported_modes;
- const char *prop = "qcom,supported-modes";
- switch (rpm_vreg->regulator_hw_type) {
- case RPM_REGULATOR_HW_TYPE_PMIC4_BOB:
- case RPM_REGULATOR_HW_TYPE_PMIC5_BOB:
- supported_modes = bob_supported_modes;
- break;
- case RPM_REGULATOR_HW_TYPE_PMIC5_LDO:
- supported_modes = ldo5_supported_modes;
- break;
- default:
- dev_err(dev, "Multiple modes unsupported for regulator hw type: %d\n",
- rpm_vreg->regulator_hw_type);
- return -EINVAL;
- }
- len /= sizeof(u32);
- rpm_vreg->mode = devm_kcalloc(dev, len,
- sizeof(*rpm_vreg->mode), GFP_KERNEL);
- if (!rpm_vreg->mode)
- return -ENOMEM;
- rpm_vreg->mode_count = len;
- buf = kcalloc(len, sizeof(*buf), GFP_KERNEL);
- if (!buf)
- return -ENOMEM;
- rc = of_property_read_u32_array(node, prop, buf, len);
- if (rc) {
- pr_err("unable to read %s, rc=%d\n",
- prop, rc);
- return rc;
- }
- for (i = 0; i < len; i++) {
- if (buf[i] < RPM_SMD_REGULATOR_MODE_PASS ||
- buf[i] > RPM_SMD_REGULATOR_MODE_HPM) {
- dev_err(dev, "element %d of %s = %u is invalid for BOB\n",
- i, prop, buf[i]);
- return -EINVAL;
- }
- rpm_vreg->mode[i].mode = supported_modes[buf[i]];
- if (i > 0 && buf[i] <= buf[i - 1]) {
- dev_err(dev, "%s elements are not in ascending order\n",
- prop);
- return -EINVAL;
- }
- }
- prop = "qcom,mode-threshold-currents";
- rc = of_property_read_u32_array(node, prop, buf, len);
- if (rc) {
- dev_err(dev, "unable to read %s, rc=%d\n",
- prop, rc);
- return rc;
- }
- for (i = 0; i < len; i++) {
- rpm_vreg->mode[i].min_load_ua = buf[i];
- if (i > 0 && rpm_vreg->mode[i].min_load_ua
- <= rpm_vreg->mode[i - 1].min_load_ua) {
- dev_err(dev, "%s elements are not in ascending order\n",
- prop);
- return -EINVAL;
- }
- }
- return 0;
- }
- /*
- * This probe is called for parent rpm-regulator devices which have
- * properties which are required to identify a given RPM resource.
- */
- static int rpm_vreg_resource_probe(struct platform_device *pdev)
- {
- struct device *dev = &pdev->dev;
- struct device_node *node = dev->of_node;
- struct rpm_vreg *rpm_vreg;
- const char *type = "";
- const char *prop;
- int val = 0;
- u32 resource_type;
- int rc, len;
- /* Create new rpm_vreg entry. */
- rpm_vreg = kzalloc(sizeof(*rpm_vreg), GFP_KERNEL);
- if (rpm_vreg == NULL)
- return -ENOMEM;
- /* Required device tree properties: */
- rc = of_property_read_string(node, "qcom,resource-name",
- &rpm_vreg->resource_name);
- if (rc) {
- dev_err(dev, "%s: qcom,resource-name missing in DT node\n",
- __func__);
- goto fail_free_vreg;
- }
- resource_type = rpm_vreg_string_to_int(rpm_vreg->resource_name);
- rc = of_property_read_u32(node, "qcom,resource-id",
- &rpm_vreg->resource_id);
- if (rc) {
- dev_err(dev, "%s: qcom,resource-id missing in DT node\n",
- __func__);
- goto fail_free_vreg;
- }
- rc = of_property_read_u32(node, "qcom,regulator-type",
- &rpm_vreg->regulator_type);
- if (rc) {
- dev_err(dev, "%s: qcom,regulator-type missing in DT node\n",
- __func__);
- goto fail_free_vreg;
- }
- if ((rpm_vreg->regulator_type < 0)
- || (rpm_vreg->regulator_type >= RPM_REGULATOR_TYPE_MAX)) {
- dev_err(dev, "%s: invalid regulator type: %d\n", __func__,
- rpm_vreg->regulator_type);
- rc = -EINVAL;
- goto fail_free_vreg;
- }
- if (rpm_vreg->regulator_type == RPM_REGULATOR_TYPE_LDO) {
- prop = "qcom,regulator-hw-type";
- rpm_vreg->regulator_hw_type = RPM_REGULATOR_HW_TYPE_UNKNOWN;
- rc = of_property_read_string(node, prop, &type);
- if (rc) {
- dev_err(dev, "%s is missing in DT node rc=%d\n",
- prop, rc);
- goto fail_free_vreg;
- }
- if (!strcmp(type, "pmic4-ldo")) {
- rpm_vreg->regulator_hw_type
- = RPM_REGULATOR_HW_TYPE_PMIC4_LDO;
- } else if (!strcmp(type, "pmic5-ldo")) {
- rpm_vreg->regulator_hw_type
- = RPM_REGULATOR_HW_TYPE_PMIC5_LDO;
- } else {
- dev_err(dev, "unknown %s = %s\n",
- prop, type);
- goto fail_free_vreg;
- }
- }
- if (rpm_vreg->regulator_type == RPM_REGULATOR_TYPE_BOB) {
- prop = "qcom,regulator-hw-type";
- rpm_vreg->regulator_hw_type = RPM_REGULATOR_HW_TYPE_UNKNOWN;
- rc = of_property_read_string(node, prop, &type);
- if (rc) {
- dev_err(dev, "%s is missing in DT node rc=%d\n",
- prop, rc);
- goto fail_free_vreg;
- }
- if (!strcmp(type, "pmic4-bob")) {
- rpm_vreg->regulator_hw_type
- = RPM_REGULATOR_HW_TYPE_PMIC4_BOB;
- } else if (!strcmp(type, "pmic5-bob")) {
- rpm_vreg->regulator_hw_type
- = RPM_REGULATOR_HW_TYPE_PMIC5_BOB;
- } else {
- dev_err(dev, "unknown %s = %s\n",
- prop, type);
- goto fail_free_vreg;
- }
- }
- /* Optional device tree properties: */
- of_property_read_u32(node, "qcom,allow-atomic", &val);
- rpm_vreg->allow_atomic = !!val;
- of_property_read_u32(node, "qcom,enable-time", &rpm_vreg->enable_time);
- of_property_read_u32(node, "qcom,hpm-min-load",
- &rpm_vreg->hpm_min_load);
- rpm_vreg->apps_only = of_property_read_bool(node, "qcom,apps-only");
- rpm_vreg->always_wait_for_ack
- = of_property_read_bool(node, "qcom,always-wait-for-ack");
- if (of_find_property(node, "qcom,supported-modes", &len)) {
- rc = init_thresholds(node, dev, rpm_vreg, len);
- if (rc < 0)
- goto fail_free_vreg;
- }
- rpm_vreg->handle_active = msm_rpm_create_request(RPM_SET_ACTIVE,
- resource_type, rpm_vreg->resource_id, RPM_REGULATOR_PARAM_MAX);
- if (rpm_vreg->handle_active == NULL
- || IS_ERR(rpm_vreg->handle_active)) {
- rc = PTR_ERR(rpm_vreg->handle_active);
- if (rc != -EPROBE_DEFER)
- dev_err(dev, "%s: failed to create active RPM handle, rc=%d\n",
- __func__, rc);
- goto fail_free_vreg;
- }
- rpm_vreg->handle_sleep = msm_rpm_create_request(RPM_SET_SLEEP,
- resource_type, rpm_vreg->resource_id, RPM_REGULATOR_PARAM_MAX);
- if (rpm_vreg->handle_sleep == NULL || IS_ERR(rpm_vreg->handle_sleep)) {
- rc = PTR_ERR(rpm_vreg->handle_sleep);
- if (rc != -EPROBE_DEFER)
- dev_err(dev, "%s: failed to create sleep RPM handle, rc=%d\n",
- __func__, rc);
- goto fail_free_handle_active;
- }
- INIT_LIST_HEAD(&rpm_vreg->reg_list);
- if (rpm_vreg->allow_atomic)
- spin_lock_init(&rpm_vreg->slock);
- else
- mutex_init(&rpm_vreg->mlock);
- platform_set_drvdata(pdev, rpm_vreg);
- rc = of_platform_populate(node, NULL, NULL, dev);
- if (rc) {
- dev_err(dev, "%s: failed to add child nodes, rc=%d\n", __func__,
- rc);
- goto fail_unset_drvdata;
- }
- pr_debug("successfully probed: %s (%08X) %u\n", rpm_vreg->resource_name,
- resource_type, rpm_vreg->resource_id);
- return rc;
- fail_unset_drvdata:
- platform_set_drvdata(pdev, NULL);
- msm_rpm_free_request(rpm_vreg->handle_sleep);
- fail_free_handle_active:
- msm_rpm_free_request(rpm_vreg->handle_active);
- fail_free_vreg:
- kfree(rpm_vreg);
- return rc;
- }
- static const struct of_device_id rpm_vreg_match_table_device[] = {
- { .compatible = "qcom,rpm-smd-regulator", },
- {}
- };
- static const struct of_device_id rpm_vreg_match_table_resource[] = {
- { .compatible = "qcom,rpm-smd-regulator-resource", },
- {}
- };
- static struct platform_driver rpm_vreg_device_driver = {
- .probe = rpm_vreg_device_probe,
- .remove = rpm_vreg_device_remove,
- .driver = {
- .name = "qcom,rpm-smd-regulator",
- .of_match_table = rpm_vreg_match_table_device,
- .sync_state = regulator_proxy_consumer_sync_state,
- },
- };
- static struct platform_driver rpm_vreg_resource_driver = {
- .probe = rpm_vreg_resource_probe,
- .remove = rpm_vreg_resource_remove,
- .driver = {
- .name = "qcom,rpm-smd-regulator-resource",
- .of_match_table = rpm_vreg_match_table_resource,
- },
- };
- /**
- * rpm_smd_regulator_driver_init() - initialize the RPM SMD regulator drivers
- *
- * This function registers the RPM SMD regulator platform drivers.
- *
- * Returns 0 on success or errno on failure.
- */
- static int __init rpm_smd_regulator_driver_init(void)
- {
- static bool initialized;
- int i, rc;
- if (initialized)
- return 0;
- initialized = true;
- /* Store parameter string names as integers */
- for (i = 0; i < RPM_REGULATOR_PARAM_MAX; i++)
- params[i].key = rpm_vreg_string_to_int(params[i].name);
- rc = platform_driver_register(&rpm_vreg_device_driver);
- if (rc)
- return rc;
- return platform_driver_register(&rpm_vreg_resource_driver);
- }
- static void __exit rpm_vreg_exit(void)
- {
- platform_driver_unregister(&rpm_vreg_device_driver);
- platform_driver_unregister(&rpm_vreg_resource_driver);
- }
- arch_initcall(rpm_smd_regulator_driver_init);
- module_exit(rpm_vreg_exit);
- MODULE_LICENSE("GPL v2");
- MODULE_DESCRIPTION("MSM RPM SMD regulator driver");
|