123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360 |
- /* Copyright (c) 2010-2012, The Linux Foundation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- */
- #include <linux/qcomwlan_pwrif.h>
- #include <linux/export.h>
- #define GPIO_WLAN_DEEP_SLEEP_N 230
- #define GPIO_WLAN_DEEP_SLEEP_N_DRAGON 82
- #define WLAN_RESET_OUT 1
- #define WLAN_RESET 0
- static const char *id = "WLAN";
- /**
- * vos_chip_power_qrf8615() - WLAN Power Up Seq for WCN1314 rev 2.0 on QRF 8615
- * @on - Turn WLAN ON/OFF (1 or 0)
- *
- * Power up/down WLAN by turning on/off various regs and asserting/deasserting
- * Power-on-reset pin. Also, put XO A0 buffer as slave to wlan_clk_pwr_req while
- * turning ON WLAN and vice-versa.
- *
- * This function returns 0 on success or a non-zero value on failure.
- */
- int vos_chip_power_qrf8615(int on)
- {
- static char wlan_on;
- static const char *vregs_qwlan_name[] = {
- "8058_l20",
- "8058_l8",
- "8901_s4",
- "8901_lvs1",
- "8901_l0",
- "8058_s2",
- "8058_s1",
- };
- static const char *vregs_qwlan_pc_name[] = {
- "8058_l20_pc",
- "8058_l8_pc",
- NULL,
- NULL,
- "8901_l0_pc",
- "8058_s2_pc",
- NULL,
- };
- static const int vregs_qwlan_val_min[] = {
- 1800000,
- 3050000,
- 1225000,
- 0,
- 1200000,
- 1300000,
- 500000,
- };
- static const int vregs_qwlan_val_max[] = {
- 1800000,
- 3050000,
- 1225000,
- 0,
- 1200000,
- 1300000,
- 1250000,
- };
- static const int vregs_qwlan_peek_current[] = {
- 4000,
- 150000,
- 60000,
- 0,
- 32000,
- 130000,
- 0,
- };
- static const bool vregs_is_pin_controlled_default[] = {
- 1,
- 1,
- 0,
- 0,
- 1,
- 1,
- 0,
- };
- static const bool vregs_is_pin_controlled_dragon[] = {
- 0,
- 0,
- 0,
- 0,
- 0,
- 1,
- 0,
- };
- bool const *vregs_is_pin_controlled;
- static struct regulator *vregs_qwlan[ARRAY_SIZE(vregs_qwlan_name)];
- static struct regulator *vregs_pc_qwlan[ARRAY_SIZE(vregs_qwlan_name)];
- static struct msm_xo_voter *wlan_clock;
- int ret, i, rc = 0;
- unsigned wlan_gpio_deep_sleep = GPIO_WLAN_DEEP_SLEEP_N;
- vregs_is_pin_controlled = vregs_is_pin_controlled_default;
- if (machine_is_msm8x60_dragon()) {
- wlan_gpio_deep_sleep = GPIO_WLAN_DEEP_SLEEP_N_DRAGON;
- vregs_is_pin_controlled = vregs_is_pin_controlled_dragon;
- }
- /* WLAN RESET and CLK settings */
- if (on && !wlan_on) {
- /*
- * Program U12 GPIO expander pin IO1 to de-assert (drive 0)
- * WLAN_EXT_POR_N to put WLAN in reset
- */
- rc = gpio_request(wlan_gpio_deep_sleep, "WLAN_DEEP_SLEEP_N");
- if (rc) {
- pr_err("WLAN reset GPIO %d request failed\n",
- wlan_gpio_deep_sleep);
- goto fail;
- }
- rc = gpio_direction_output(wlan_gpio_deep_sleep,
- WLAN_RESET);
- if (rc < 0) {
- pr_err("WLAN reset GPIO %d set output direction failed",
- wlan_gpio_deep_sleep);
- goto fail_gpio_dir_out;
- }
- /* Configure TCXO to be slave to WLAN_CLK_PWR_REQ */
- if (wlan_clock == NULL) {
- wlan_clock = msm_xo_get(MSM_XO_TCXO_A0, id);
- if (IS_ERR(wlan_clock)) {
- pr_err("Failed to get TCXO_A0 voter (%ld)\n",
- PTR_ERR(wlan_clock));
- goto fail_gpio_dir_out;
- }
- }
- rc = msm_xo_mode_vote(wlan_clock, MSM_XO_MODE_PIN_CTRL);
- if (rc < 0) {
- pr_err("Configuring TCXO to Pin controllable failed"
- "(%d)\n", rc);
- goto fail_xo_mode_vote;
- }
- } else if (!on && wlan_on) {
- if (wlan_clock != NULL)
- msm_xo_mode_vote(wlan_clock, MSM_XO_MODE_OFF);
- gpio_set_value_cansleep(wlan_gpio_deep_sleep, WLAN_RESET);
- gpio_free(wlan_gpio_deep_sleep);
- }
- /* WLAN VREG settings */
- for (i = 0; i < ARRAY_SIZE(vregs_qwlan_name); i++) {
- if (on && !wlan_on) {
- vregs_qwlan[i] = regulator_get(NULL,
- vregs_qwlan_name[i]);
- if (IS_ERR(vregs_qwlan[i])) {
- pr_err("regulator get of %s failed (%ld)\n",
- vregs_qwlan_name[i],
- PTR_ERR(vregs_qwlan[i]));
- rc = PTR_ERR(vregs_qwlan[i]);
- goto vreg_get_fail;
- }
- if (vregs_qwlan_val_min[i] || vregs_qwlan_val_max[i]) {
- rc = regulator_set_voltage(vregs_qwlan[i],
- vregs_qwlan_val_min[i],
- vregs_qwlan_val_max[i]);
- if (rc) {
- pr_err("regulator_set_voltage(%s) failed\n",
- vregs_qwlan_name[i]);
- goto vreg_fail;
- }
- }
- /* vote for pin control (if needed) */
- if (vregs_is_pin_controlled[i]) {
- vregs_pc_qwlan[i] = regulator_get(NULL,
- vregs_qwlan_pc_name[i]);
- if (IS_ERR(vregs_pc_qwlan[i])) {
- pr_err("regulator get of %s failed "
- "(%ld)\n",
- vregs_qwlan_pc_name[i],
- PTR_ERR(vregs_pc_qwlan[i]));
- rc = PTR_ERR(vregs_pc_qwlan[i]);
- goto vreg_fail;
- }
- }
- if (vregs_qwlan_peek_current[i]) {
- rc = regulator_set_optimum_mode(vregs_qwlan[i],
- vregs_qwlan_peek_current[i]);
- if (rc < 0)
- pr_err("vreg %s set optimum mode"
- " failed to %d (%d)\n",
- vregs_qwlan_name[i], rc,
- vregs_qwlan_peek_current[i]);
- }
- rc = regulator_enable(vregs_qwlan[i]);
- if (rc < 0) {
- pr_err("vreg %s enable failed (%d)\n",
- vregs_qwlan_name[i], rc);
- goto vreg_fail;
- }
- if (vregs_is_pin_controlled[i]) {
- rc = regulator_enable(vregs_pc_qwlan[i]);
- if (rc < 0) {
- pr_err("vreg %s enable failed (%d)\n",
- vregs_qwlan_pc_name[i], rc);
- goto vreg_fail;
- }
- }
- } else if (!on && wlan_on) {
- if (vregs_qwlan_peek_current[i]) {
- /* For legacy reasons we pass 1mA current to
- * put regulator in LPM mode.
- */
- rc = regulator_set_optimum_mode(vregs_qwlan[i],
- 1000);
- if (rc < 0)
- pr_info("vreg %s set optimum mode"
- "failed (%d)\n",
- vregs_qwlan_name[i], rc);
- rc = regulator_set_voltage(vregs_qwlan[i], 0 ,
- vregs_qwlan_val_max[i]);
- if (rc)
- pr_err("regulator_set_voltage(%s)"
- "failed (%d)\n",
- vregs_qwlan_name[i], rc);
- }
- if (vregs_is_pin_controlled[i]) {
- rc = regulator_disable(vregs_pc_qwlan[i]);
- if (rc < 0) {
- pr_err("vreg %s disable failed (%d)\n",
- vregs_qwlan_pc_name[i], rc);
- goto vreg_fail;
- }
- regulator_put(vregs_pc_qwlan[i]);
- }
- rc = regulator_disable(vregs_qwlan[i]);
- if (rc < 0) {
- pr_err("vreg %s disable failed (%d)\n",
- vregs_qwlan_name[i], rc);
- goto vreg_fail;
- }
- regulator_put(vregs_qwlan[i]);
- }
- }
- if (on) {
- gpio_set_value_cansleep(wlan_gpio_deep_sleep, WLAN_RESET_OUT);
- wlan_on = true;
- }
- else
- wlan_on = false;
- return 0;
- vreg_fail:
- regulator_put(vregs_qwlan[i]);
- if (vregs_is_pin_controlled[i])
- regulator_put(vregs_pc_qwlan[i]);
- vreg_get_fail:
- i--;
- while (i >= 0) {
- ret = !on ? regulator_enable(vregs_qwlan[i]) :
- regulator_disable(vregs_qwlan[i]);
- if (ret < 0) {
- pr_err("vreg %s %s failed (%d) in err path\n",
- vregs_qwlan_name[i],
- !on ? "enable" : "disable", ret);
- }
- if (vregs_is_pin_controlled[i]) {
- ret = !on ? regulator_enable(vregs_pc_qwlan[i]) :
- regulator_disable(vregs_pc_qwlan[i]);
- if (ret < 0) {
- pr_err("vreg %s %s failed (%d) in err path\n",
- vregs_qwlan_pc_name[i],
- !on ? "enable" : "disable", ret);
- }
- }
- regulator_put(vregs_qwlan[i]);
- if (vregs_is_pin_controlled[i])
- regulator_put(vregs_pc_qwlan[i]);
- i--;
- }
- if (!on)
- goto fail;
- fail_xo_mode_vote:
- msm_xo_put(wlan_clock);
- fail_gpio_dir_out:
- gpio_free(wlan_gpio_deep_sleep);
- fail:
- return rc;
- }
- EXPORT_SYMBOL(vos_chip_power_qrf8615);
- /**
- * qcomwlan_pmic_xo_core_force_enable() - Force XO Core of PMIC to be ALWAYS ON
- * @on - Force XO Core ON/OFF (1 or 0)
- *
- * The XO_CORE controls the XO feeding the TCXO buffers (A0, A1, etc.). WLAN
- * wants to keep the XO core on even though our buffer A0 is in pin control
- * because it can take a long time turn the XO back on and warm up the buffers.
- * This helps in optimizing power in BMPS (power save) mode of WLAN.
- * The WLAN driver wrapper function takes care that this API is not called
- * consecutively.
- *
- * This function returns 0 on success or a non-zero value on failure.
- */
- int qcomwlan_pmic_xo_core_force_enable(int on)
- {
- static struct msm_xo_voter *wlan_ps;
- int rc = 0;
- if (wlan_ps == NULL) {
- wlan_ps = msm_xo_get(MSM_XO_CORE, id);
- if (IS_ERR(wlan_ps)) {
- pr_err("Failed to get XO CORE voter (%ld)\n",
- PTR_ERR(wlan_ps));
- goto fail;
- }
- }
- if (on)
- rc = msm_xo_mode_vote(wlan_ps, MSM_XO_MODE_ON);
- else
- rc = msm_xo_mode_vote(wlan_ps, MSM_XO_MODE_OFF);
- if (rc < 0) {
- pr_err("XO Core %s failed (%d)\n",
- on ? "enable" : "disable", rc);
- goto fail_xo_mode_vote;
- }
- return 0;
- fail_xo_mode_vote:
- msm_xo_put(wlan_ps);
- fail:
- return rc;
- }
- EXPORT_SYMBOL(qcomwlan_pmic_xo_core_force_enable);
- /**
- * qcomwlan_freq_change_1p3v_supply() - function to change the freq for 1.3V RF supply.
- * @freq - freq of the 1.3V Supply
- *
- * This function returns 0 on success or a non-zero value on failure.
- */
- int qcomwlan_freq_change_1p3v_supply(enum rpm_vreg_freq freq)
- {
- return rpm_vreg_set_frequency(RPM_VREG_ID_PM8058_S2, freq);
- }
- EXPORT_SYMBOL(qcomwlan_freq_change_1p3v_supply);
|