wcnss: modularize wcnss power up sequence and debug logs
Modularize the wcnss power up sequence like wcnss voltage regulator enable/disable sequence and voltage regulator current and voltage level parsing method. Remove hack code from the power wcnss power process and enable/disable the power resource if it's defined in the wcnss device node. Update the debug logs to track the exact state of the power state during device bootup. Remove the unnecessary logging for the optional resource request fails during device bootup. CRs-Fixed: 2086414 Change-Id: I30b1e2196eb9d1c933275f3db34ca0ff5664ea3b Signed-off-by: Sarada Prasanna Garnayak <sgarna@codeaurora.org>
This commit is contained in:
parent
a49bb61510
commit
5eebfeaa9c
4 changed files with 176 additions and 156 deletions
|
@ -64,8 +64,6 @@ support for pronto hardware.
|
|||
to use for VBATT feature.
|
||||
- qcom,has-a2xb-split-reg: boolean flag to determine A2xb split timeout limit
|
||||
register is available or not.
|
||||
- qcom,wcn-external-gpio-support: boolean flag to determine 3.3v gpio support
|
||||
for pronto hardware for a target.
|
||||
|
||||
Example:
|
||||
|
||||
|
@ -87,7 +85,6 @@ Example:
|
|||
|
||||
gpios = <&msmgpio 36 0>, <&msmgpio 37 0>, <&msmgpio 38 0>,
|
||||
<&msmgpio 39 0>, <&msmgpio 40 0>;
|
||||
qcom,wcn-external-gpio-support;
|
||||
qcom,has-48mhz-xo;
|
||||
qcom,is-pronto-vt;
|
||||
qcom,wlan-rx-buff-count = <512>;
|
||||
|
|
|
@ -71,23 +71,33 @@ static int is_power_on;
|
|||
|
||||
struct vregs_info {
|
||||
const char * const name;
|
||||
const char * const curr;
|
||||
const char * const volt;
|
||||
int state;
|
||||
bool required;
|
||||
struct regulator *regulator;
|
||||
};
|
||||
|
||||
/* IRIS regulators for Pronto hardware */
|
||||
static struct vregs_info iris_vregs_pronto[] = {
|
||||
{"qcom,iris-vddxo", VREG_NULL_CONFIG, NULL},
|
||||
{"qcom,iris-vddrfa", VREG_NULL_CONFIG, NULL},
|
||||
{"qcom,iris-vddpa", VREG_NULL_CONFIG, NULL},
|
||||
{"qcom,iris-vdddig", VREG_NULL_CONFIG, NULL},
|
||||
static struct vregs_info iris_vregs[] = {
|
||||
{"qcom,iris-vddxo", "qcom,iris-vddxo-current",
|
||||
"qcom,iris-vddxo-voltage-level", VREG_NULL_CONFIG, true, NULL},
|
||||
{"qcom,iris-vddrfa", "qcom,iris-vddrfa-current",
|
||||
"qcom,iris-vddrfa-voltage-level", VREG_NULL_CONFIG, true, NULL},
|
||||
{"qcom,iris-vddpa", "qcom,iris-vddpa-current",
|
||||
"qcom,iris-vddpa-voltage-level", VREG_NULL_CONFIG, false, NULL},
|
||||
{"qcom,iris-vdddig", "qcom,iris-vdddig-current",
|
||||
"qcom,iris-vdddig-voltage-level", VREG_NULL_CONFIG, true, NULL},
|
||||
};
|
||||
|
||||
/* WCNSS regulators for Pronto hardware */
|
||||
static struct vregs_info pronto_vregs[] = {
|
||||
{"qcom,pronto-vddmx", VREG_NULL_CONFIG, NULL},
|
||||
{"qcom,pronto-vddcx", VREG_NULL_CONFIG, NULL},
|
||||
{"qcom,pronto-vddpx", VREG_NULL_CONFIG, NULL},
|
||||
{"qcom,pronto-vddmx", "qcom,pronto-vddmx-current",
|
||||
"qcom,vddmx-voltage-level", VREG_NULL_CONFIG, true, NULL},
|
||||
{"qcom,pronto-vddcx", "qcom,pronto-vddcx-current",
|
||||
"qcom,vddcx-voltage-level", VREG_NULL_CONFIG, true, NULL},
|
||||
{"qcom,pronto-vddpx", "qcom,pronto-vddpx-current",
|
||||
"qcom,vddpx-voltage-level", VREG_NULL_CONFIG, true, NULL},
|
||||
};
|
||||
|
||||
struct host_driver {
|
||||
|
@ -184,6 +194,129 @@ int validate_iris_chip_id(u32 reg)
|
|||
}
|
||||
}
|
||||
|
||||
static void wcnss_free_regulator(void)
|
||||
{
|
||||
int vreg_i;
|
||||
|
||||
/* Free pronto voltage regulators from device node */
|
||||
for (vreg_i = 0; vreg_i < PRONTO_REGULATORS; vreg_i++) {
|
||||
if (pronto_vregs[vreg_i].state) {
|
||||
regulator_put(pronto_vregs[vreg_i].regulator);
|
||||
pronto_vregs[vreg_i].state = VREG_NULL_CONFIG;
|
||||
}
|
||||
}
|
||||
|
||||
/* Free IRIS voltage regulators from device node */
|
||||
for (vreg_i = 0; vreg_i < IRIS_REGULATORS; vreg_i++) {
|
||||
if (iris_vregs[vreg_i].state) {
|
||||
regulator_put(iris_vregs[vreg_i].regulator);
|
||||
iris_vregs[vreg_i].state = VREG_NULL_CONFIG;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
wcnss_dt_parse_vreg_level(struct device *dev, int index,
|
||||
const char *current_vreg_name, const char *vreg_name,
|
||||
struct vregs_level *vlevel)
|
||||
{
|
||||
int ret = 0;
|
||||
/* array used to store nominal, low and high voltage values */
|
||||
u32 voltage_levels[3], current_vreg;
|
||||
|
||||
ret = of_property_read_u32_array(dev->of_node, vreg_name,
|
||||
voltage_levels,
|
||||
ARRAY_SIZE(voltage_levels));
|
||||
if (ret) {
|
||||
dev_err(dev, "error reading %s property\n", vreg_name);
|
||||
return ret;
|
||||
}
|
||||
|
||||
vlevel[index].nominal_min = voltage_levels[0];
|
||||
vlevel[index].low_power_min = voltage_levels[1];
|
||||
vlevel[index].max_voltage = voltage_levels[2];
|
||||
|
||||
ret = of_property_read_u32(dev->of_node, current_vreg_name,
|
||||
¤t_vreg);
|
||||
if (ret) {
|
||||
dev_err(dev, "error reading %s property\n", current_vreg_name);
|
||||
return ret;
|
||||
}
|
||||
|
||||
vlevel[index].uA_load = current_vreg;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
wcnss_parse_voltage_regulator(struct wcnss_wlan_config *wlan_config,
|
||||
struct device *dev)
|
||||
{
|
||||
int rc, vreg_i;
|
||||
|
||||
/* Parse pronto voltage regulators from device node */
|
||||
for (vreg_i = 0; vreg_i < PRONTO_REGULATORS; vreg_i++) {
|
||||
pronto_vregs[vreg_i].regulator =
|
||||
regulator_get(dev, pronto_vregs[vreg_i].name);
|
||||
if (IS_ERR(pronto_vregs[vreg_i].regulator)) {
|
||||
if (pronto_vregs[vreg_i].required) {
|
||||
rc = PTR_ERR(pronto_vregs[vreg_i].regulator);
|
||||
dev_err(dev, "regulator get of %s failed (%d)\n",
|
||||
pronto_vregs[vreg_i].name, rc);
|
||||
goto wcnss_vreg_get_err;
|
||||
} else {
|
||||
dev_dbg(dev, "Skip optional regulator configuration: %s\n",
|
||||
pronto_vregs[vreg_i].name);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
pronto_vregs[vreg_i].state |= VREG_GET_REGULATOR_MASK;
|
||||
rc = wcnss_dt_parse_vreg_level(dev, vreg_i,
|
||||
pronto_vregs[vreg_i].curr,
|
||||
pronto_vregs[vreg_i].volt,
|
||||
wlan_config->pronto_vlevel);
|
||||
if (rc) {
|
||||
dev_err(dev, "error reading voltage-level property\n");
|
||||
goto wcnss_vreg_get_err;
|
||||
}
|
||||
}
|
||||
|
||||
/* Parse iris voltage regulators from device node */
|
||||
for (vreg_i = 0; vreg_i < IRIS_REGULATORS; vreg_i++) {
|
||||
iris_vregs[vreg_i].regulator =
|
||||
regulator_get(dev, iris_vregs[vreg_i].name);
|
||||
if (IS_ERR(iris_vregs[vreg_i].regulator)) {
|
||||
if (iris_vregs[vreg_i].required) {
|
||||
rc = PTR_ERR(iris_vregs[vreg_i].regulator);
|
||||
dev_err(dev, "regulator get of %s failed (%d)\n",
|
||||
iris_vregs[vreg_i].name, rc);
|
||||
goto wcnss_vreg_get_err;
|
||||
} else {
|
||||
dev_dbg(dev, "Skip optional regulator configuration: %s\n",
|
||||
iris_vregs[vreg_i].name);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
iris_vregs[vreg_i].state |= VREG_GET_REGULATOR_MASK;
|
||||
rc = wcnss_dt_parse_vreg_level(dev, vreg_i,
|
||||
iris_vregs[vreg_i].curr,
|
||||
iris_vregs[vreg_i].volt,
|
||||
wlan_config->iris_vlevel);
|
||||
if (rc) {
|
||||
dev_err(dev, "error reading voltage-level property\n");
|
||||
goto wcnss_vreg_get_err;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
wcnss_vreg_get_err:
|
||||
wcnss_free_regulator();
|
||||
return rc;
|
||||
}
|
||||
|
||||
void wcnss_iris_reset(u32 reg, void __iomem *pmu_conf_reg)
|
||||
{
|
||||
/* Reset IRIS */
|
||||
|
@ -417,11 +550,6 @@ static void wcnss_vregs_off(struct vregs_info regulators[], uint size,
|
|||
if (regulators[i].state == VREG_NULL_CONFIG)
|
||||
continue;
|
||||
|
||||
if (cfg->wcn_external_gpio_support) {
|
||||
if (!memcmp(regulators[i].name, VDD_PA, sizeof(VDD_PA)))
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Remove PWM mode */
|
||||
if (regulators[i].state & VREG_OPTIMUM_MODE_MASK) {
|
||||
rc = regulator_set_load(regulators[i].regulator, 0);
|
||||
|
@ -483,23 +611,10 @@ static int wcnss_vregs_on(struct device *dev,
|
|||
}
|
||||
|
||||
for (i = 0; i < size; i++) {
|
||||
if (cfg->wcn_external_gpio_support) {
|
||||
if (!memcmp(regulators[i].name, VDD_PA, sizeof(VDD_PA)))
|
||||
continue;
|
||||
}
|
||||
if (regulators[i].state == VREG_NULL_CONFIG)
|
||||
continue;
|
||||
|
||||
/* Get regulator source */
|
||||
regulators[i].regulator =
|
||||
regulator_get(dev, regulators[i].name);
|
||||
if (IS_ERR(regulators[i].regulator)) {
|
||||
rc = PTR_ERR(regulators[i].regulator);
|
||||
pr_err("regulator get of %s failed (%d)\n",
|
||||
regulators[i].name, rc);
|
||||
goto fail;
|
||||
}
|
||||
regulators[i].state |= VREG_GET_REGULATOR_MASK;
|
||||
reg_cnt = regulator_count_voltages(regulators[i].regulator);
|
||||
|
||||
/* Set voltage to nominal. Exclude swtiches e.g. LVS */
|
||||
if ((voltage_level[i].nominal_min ||
|
||||
voltage_level[i].max_voltage) && (reg_cnt > 0)) {
|
||||
|
@ -561,8 +676,7 @@ static void wcnss_iris_vregs_off(enum wcnss_hw_type hw_type,
|
|||
{
|
||||
switch (hw_type) {
|
||||
case WCNSS_PRONTO_HW:
|
||||
wcnss_vregs_off(iris_vregs_pronto,
|
||||
ARRAY_SIZE(iris_vregs_pronto),
|
||||
wcnss_vregs_off(iris_vregs, ARRAY_SIZE(iris_vregs),
|
||||
cfg->iris_vlevel);
|
||||
break;
|
||||
default:
|
||||
|
@ -579,8 +693,7 @@ static int wcnss_iris_vregs_on(struct device *dev,
|
|||
|
||||
switch (hw_type) {
|
||||
case WCNSS_PRONTO_HW:
|
||||
ret = wcnss_vregs_on(dev, iris_vregs_pronto,
|
||||
ARRAY_SIZE(iris_vregs_pronto),
|
||||
ret = wcnss_vregs_on(dev, iris_vregs, ARRAY_SIZE(iris_vregs),
|
||||
cfg->iris_vlevel);
|
||||
break;
|
||||
default:
|
||||
|
|
|
@ -63,6 +63,21 @@
|
|||
#define WCNSS_CONFIG_UNSPECIFIED (-1)
|
||||
#define UINT32_MAX (0xFFFFFFFFU)
|
||||
|
||||
#define SUBSYS_NOTIF_MIN_INDEX 0
|
||||
#define SUBSYS_NOTIF_MAX_INDEX 9
|
||||
char *wcnss_subsys_notif_type[] = {
|
||||
"SUBSYS_BEFORE_SHUTDOWN",
|
||||
"SUBSYS_AFTER_SHUTDOWN",
|
||||
"SUBSYS_BEFORE_POWERUP",
|
||||
"SUBSYS_AFTER_POWERUP",
|
||||
"SUBSYS_RAMDUMP_NOTIFICATION",
|
||||
"SUBSYS_POWERUP_FAILURE",
|
||||
"SUBSYS_PROXY_VOTE",
|
||||
"SUBSYS_PROXY_UNVOTE",
|
||||
"SUBSYS_SOC_RESET",
|
||||
"SUBSYS_NOTIF_TYPE_COUNT"
|
||||
};
|
||||
|
||||
static int has_48mhz_xo = WCNSS_CONFIG_UNSPECIFIED;
|
||||
module_param(has_48mhz_xo, int, S_IWUSR | S_IRUGO);
|
||||
MODULE_PARM_DESC(has_48mhz_xo, "Is an external 48 MHz XO present");
|
||||
|
@ -2713,51 +2728,16 @@ static struct miscdevice wcnss_usr_ctrl = {
|
|||
.fops = &wcnss_ctrl_fops,
|
||||
};
|
||||
|
||||
static int
|
||||
wcnss_dt_parse_vreg_level(struct device *dev, int index,
|
||||
const char *current_vreg_name, const char *vreg_name,
|
||||
struct vregs_level *vlevel)
|
||||
{
|
||||
int ret = 0;
|
||||
/* array used to store nominal, low and high voltage values
|
||||
*/
|
||||
u32 voltage_levels[3], current_vreg;
|
||||
|
||||
ret = of_property_read_u32_array(dev->of_node, vreg_name,
|
||||
voltage_levels,
|
||||
ARRAY_SIZE(voltage_levels));
|
||||
if (ret) {
|
||||
dev_err(dev, "error reading %s property\n", vreg_name);
|
||||
return ret;
|
||||
}
|
||||
|
||||
vlevel[index].nominal_min = voltage_levels[0];
|
||||
vlevel[index].low_power_min = voltage_levels[1];
|
||||
vlevel[index].max_voltage = voltage_levels[2];
|
||||
|
||||
ret = of_property_read_u32(dev->of_node, current_vreg_name,
|
||||
¤t_vreg);
|
||||
if (ret) {
|
||||
dev_err(dev, "error reading %s property\n", current_vreg_name);
|
||||
return ret;
|
||||
}
|
||||
|
||||
vlevel[index].uA_load = current_vreg;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
wcnss_trigger_config(struct platform_device *pdev)
|
||||
{
|
||||
int ret;
|
||||
int rc, index = 0;
|
||||
int rc;
|
||||
struct qcom_wcnss_opts *pdata;
|
||||
struct resource *res;
|
||||
int is_pronto_vadc;
|
||||
int is_pronto_v3;
|
||||
int pil_retry = 0;
|
||||
struct wcnss_wlan_config *wlan_cfg = &penv->wlan_config;
|
||||
struct device_node *node = (&pdev->dev)->of_node;
|
||||
int has_pronto_hw = of_property_read_bool(node, "qcom,has-pronto-hw");
|
||||
|
||||
|
@ -2769,93 +2749,14 @@ wcnss_trigger_config(struct platform_device *pdev)
|
|||
penv->is_a2xb_split_reg =
|
||||
of_property_read_bool(node, "qcom,has-a2xb-split-reg");
|
||||
|
||||
wlan_cfg->wcn_external_gpio_support =
|
||||
of_property_read_bool(node, "qcom,wcn-external-gpio-support");
|
||||
|
||||
if (of_property_read_u32(node, "qcom,wlan-rx-buff-count",
|
||||
&penv->wlan_rx_buff_count)) {
|
||||
penv->wlan_rx_buff_count = WCNSS_DEF_WLAN_RX_BUFF_COUNT;
|
||||
}
|
||||
|
||||
ret = wcnss_dt_parse_vreg_level(&pdev->dev, index,
|
||||
"qcom,pronto-vddmx-current",
|
||||
"qcom,vddmx-voltage-level",
|
||||
penv->wlan_config.pronto_vlevel);
|
||||
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "error reading voltage-level property\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
index++;
|
||||
ret = wcnss_dt_parse_vreg_level(&pdev->dev, index,
|
||||
"qcom,pronto-vddcx-current",
|
||||
"qcom,vddcx-voltage-level",
|
||||
penv->wlan_config.pronto_vlevel);
|
||||
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "error reading voltage-level property\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
index++;
|
||||
ret = wcnss_dt_parse_vreg_level(&pdev->dev, index,
|
||||
"qcom,pronto-vddpx-current",
|
||||
"qcom,vddpx-voltage-level",
|
||||
penv->wlan_config.pronto_vlevel);
|
||||
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "error reading voltage-level property\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* assign 0 to index now onwards, index variable re used to
|
||||
* represent iris regulator index
|
||||
*/
|
||||
index = 0;
|
||||
ret = wcnss_dt_parse_vreg_level(&pdev->dev, index,
|
||||
"qcom,iris-vddxo-current",
|
||||
"qcom,iris-vddxo-voltage-level",
|
||||
penv->wlan_config.iris_vlevel);
|
||||
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "error reading voltage-level property\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
index++;
|
||||
ret = wcnss_dt_parse_vreg_level(&pdev->dev, index,
|
||||
"qcom,iris-vddrfa-current",
|
||||
"qcom,iris-vddrfa-voltage-level",
|
||||
penv->wlan_config.iris_vlevel);
|
||||
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "error reading voltage-level property\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!wlan_cfg->wcn_external_gpio_support) {
|
||||
index++;
|
||||
ret = wcnss_dt_parse_vreg_level(
|
||||
&pdev->dev, index,
|
||||
"qcom,iris-vddpa-current",
|
||||
"qcom,iris-vddpa-voltage-level",
|
||||
penv->wlan_config.iris_vlevel);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev,
|
||||
"error reading voltage-level property\n");
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
index++;
|
||||
ret = wcnss_dt_parse_vreg_level(&pdev->dev, index,
|
||||
"qcom,iris-vdddig-current",
|
||||
"qcom,iris-vdddig-voltage-level",
|
||||
penv->wlan_config.iris_vlevel);
|
||||
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "error reading voltage-level property\n");
|
||||
rc = wcnss_parse_voltage_regulator(&penv->wlan_config, &pdev->dev);
|
||||
if (rc) {
|
||||
dev_err(&pdev->dev, "Failed to parse voltage regulators\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
|
@ -3201,7 +3102,7 @@ wcnss_trigger_config(struct platform_device *pdev)
|
|||
penv->vadc_dev = qpnp_get_vadc(&penv->pdev->dev, "wcnss");
|
||||
|
||||
if (IS_ERR(penv->vadc_dev)) {
|
||||
pr_err("%s: vadc get failed\n", __func__);
|
||||
pr_debug("%s: vadc get failed\n", __func__);
|
||||
penv->vadc_dev = NULL;
|
||||
} else {
|
||||
rc = wcnss_get_battery_volt(&penv->wlan_config.vbatt);
|
||||
|
@ -3477,7 +3378,15 @@ static int wcnss_notif_cb(struct notifier_block *this, unsigned long code,
|
|||
struct notif_data *data = (struct notif_data *)ss_handle;
|
||||
int ret, xo_mode;
|
||||
|
||||
pr_info("%s: wcnss notification event: %lu\n", __func__, code);
|
||||
if (!(code >= SUBSYS_NOTIF_MIN_INDEX) &&
|
||||
(code <= SUBSYS_NOTIF_MAX_INDEX)) {
|
||||
pr_debug("%s: Invaild subsystem notification code: %lu\n",
|
||||
__func__, code);
|
||||
return NOTIFY_DONE;
|
||||
}
|
||||
|
||||
pr_debug("%s: wcnss notification event: %lu : %s\n",
|
||||
__func__, code, wcnss_subsys_notif_type[code]);
|
||||
|
||||
if (code == SUBSYS_PROXY_VOTE) {
|
||||
if (pdev && pwlanconfig) {
|
||||
|
|
|
@ -38,7 +38,6 @@ struct vregs_level {
|
|||
};
|
||||
|
||||
struct wcnss_wlan_config {
|
||||
bool wcn_external_gpio_support;
|
||||
int use_48mhz_xo;
|
||||
int is_pronto_vadc;
|
||||
int is_pronto_v3;
|
||||
|
@ -143,6 +142,8 @@ void wcnss_init_delayed_work(struct delayed_work *dwork , void *callbackptr);
|
|||
int wcnss_get_iris_name(char *iris_version);
|
||||
void wcnss_dump_stack(struct task_struct *task);
|
||||
void wcnss_snoc_vote(bool clk_chk_en);
|
||||
int wcnss_parse_voltage_regulator(struct wcnss_wlan_config *wlan_config,
|
||||
struct device *dev);
|
||||
|
||||
#ifdef CONFIG_WCNSS_REGISTER_DUMP_ON_BITE
|
||||
void wcnss_log_debug_regs_on_bite(void);
|
||||
|
|
Loading…
Add table
Reference in a new issue