blob: 38e0ff4dcc70f2a9a22a517dd8bed9350c4112f8 [file] [log] [blame]
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001/* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
2 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 */
12
13#include <linux/device.h>
14#include <mach/vreg.h>
15#include <linux/gpio.h>
16#include <mach/rpc_pmapp.h>
17#include <linux/err.h>
18#include <linux/qcomwlan7x27a_pwrif.h>
19
20#define WLAN_GPIO_EXT_POR_N 134
21
22static const char *id = "WLAN";
23
24enum {
25 WLAN_VREG_L17 = 0,
26 WLAN_VREG_S3,
27 WLAN_VREG_TCXO_L11,
28 WLAN_VREG_L19,
29 WLAN_VREG_L5,
30 WLAN_VREG_L6
31};
32
33struct wlan_vreg_info {
34 const char *vreg_id;
35 unsigned int vreg_level;
36 unsigned int pmapp_id;
37 unsigned int is_vreg_pin_controlled;
38 struct vreg *vreg;
39};
40
41
42static struct wlan_vreg_info vreg_info[] = {
Santosh Sajjan2370c642011-08-02 16:36:39 +053043 {"bt", 3050, 21, 1, NULL},
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070044 {"msme1", 1800, 2, 0, NULL},
45 {"wlan_tcx0", 1800, 53, 0, NULL},
Santosh Sajjan2370c642011-08-02 16:36:39 +053046 {"wlan4", 1200, 23, 0, NULL},
47 {"wlan2", 1350, 9, 1, NULL},
48 {"wlan3", 1200, 10, 1, NULL} };
49
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070050
51int chip_power_qrf6285(bool on)
52{
53 int rc = 0, index = 0;
54
55 if (on) {
56 rc = gpio_request(WLAN_GPIO_EXT_POR_N, "WLAN_DEEP_SLEEP_N");
57
58 if (rc) {
59 pr_err("WLAN reset GPIO %d request failed %d\n",
60 WLAN_GPIO_EXT_POR_N, rc);
61 goto fail;
62 }
63 rc = gpio_direction_output(WLAN_GPIO_EXT_POR_N, 1);
64 if (rc < 0) {
65 pr_err("WLAN reset GPIO %d set direction failed %d\n",
66 WLAN_GPIO_EXT_POR_N, rc);
67 goto fail_gpio_dir_out;
68 }
Santosh Sajjanecce5612011-08-08 19:05:51 +053069 rc = pmapp_clock_vote(id, PMAPP_CLOCK_ID_A0,
70 PMAPP_CLOCK_VOTE_ON);
71 if (rc) {
72 pr_err("%s: Configuring A0 to always"
73 " on failed %d\n", __func__, rc);
74 goto clock_vote_fail;
75 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070076 } else {
77 gpio_set_value_cansleep(WLAN_GPIO_EXT_POR_N, 0);
Santosh Sajjanecce5612011-08-08 19:05:51 +053078 rc = gpio_direction_input(WLAN_GPIO_EXT_POR_N);
79 if (rc) {
80 pr_err("WLAN reset GPIO %d set direction failed %d\n",
81 WLAN_GPIO_EXT_POR_N, rc);
82 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070083 gpio_free(WLAN_GPIO_EXT_POR_N);
Santosh Sajjanecce5612011-08-08 19:05:51 +053084 rc = pmapp_clock_vote(id, PMAPP_CLOCK_ID_A0,
85 PMAPP_CLOCK_VOTE_OFF);
86 if (rc) {
87 pr_err("%s: Configuring A0 to turn OFF"
88 " failed %d\n", __func__, rc);
89 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070090 }
91
92
93 for (index = 0; index < ARRAY_SIZE(vreg_info); index++) {
94 vreg_info[index].vreg = vreg_get(NULL,
95 vreg_info[index].vreg_id);
96 if (IS_ERR(vreg_info[index].vreg)) {
97 pr_err("%s:%s vreg get failed %ld\n",
98 __func__, vreg_info[index].vreg_id,
99 PTR_ERR(vreg_info[index].vreg));
100 rc = PTR_ERR(vreg_info[index].vreg);
101 if (on)
102 goto vreg_fail;
103 else
104 continue;
105 }
106 if (on) {
107 rc = vreg_set_level(vreg_info[index].vreg,
108 vreg_info[index].vreg_level);
109 if (rc) {
110 pr_err("%s:%s vreg set level failed %d\n",
111 __func__, vreg_info[index].vreg_id, rc);
112 goto vreg_fail;
113 }
114 if (vreg_info[index].is_vreg_pin_controlled) {
115 rc = pmapp_vreg_pincntrl_vote(id,
116 vreg_info[index].pmapp_id,
117 PMAPP_CLOCK_ID_A0, 1);
118 if (rc) {
119 pr_err("%s:%s pmapp_vreg_pincntrl_vote"
120 " for enable failed %d\n",
121 __func__,
122 vreg_info[index].vreg_id, rc);
123 goto vreg_fail;
124 }
125 } else {
126 rc = vreg_enable(vreg_info[index].vreg);
127 if (rc) {
128 pr_err("%s:%s vreg enable failed %d\n",
129 __func__,
130 vreg_info[index].vreg_id, rc);
131 goto vreg_fail;
132 }
133 }
134
Santosh Sajjan2370c642011-08-02 16:36:39 +0530135 /*At this point CLK_PWR_REQ is high*/
136 if (WLAN_VREG_L6 == index) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700137 /*
Santosh Sajjan2370c642011-08-02 16:36:39 +0530138 * Configure A0 clock to be slave to
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700139 * WLAN_CLK_PWR_REQ
140` */
141 rc = pmapp_clock_vote(id, PMAPP_CLOCK_ID_A0,
142 PMAPP_CLOCK_VOTE_PIN_CTRL);
143 if (rc) {
Santosh Sajjan2370c642011-08-02 16:36:39 +0530144 pr_err("%s: Configuring A0 to Pin"
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700145 " controllable failed %d\n",
146 __func__, rc);
147 goto vreg_clock_vote_fail;
148 }
149 }
150
151 } else {
152
153 if (vreg_info[index].is_vreg_pin_controlled) {
154 rc = pmapp_vreg_pincntrl_vote(id,
155 vreg_info[index].pmapp_id,
156 PMAPP_CLOCK_ID_A0, 0);
157 if (rc) {
158 pr_err("%s:%s pmapp_vreg_pincntrl_vote"
159 " for disable failed %d\n",
160 __func__,
161 vreg_info[index].vreg_id, rc);
162 }
163 } else {
164 rc = vreg_disable(vreg_info[index].vreg);
165 if (rc) {
166 pr_err("%s:%s vreg disable failed %d\n",
167 __func__,
168 vreg_info[index].vreg_id, rc);
169 }
170 }
171 }
172 }
173 return 0;
174vreg_fail:
175 index--;
176vreg_clock_vote_fail:
177 while (index > 0) {
178 rc = vreg_disable(vreg_info[index].vreg);
179 if (rc) {
180 pr_err("%s:%s vreg disable failed %d\n",
181 __func__, vreg_info[index].vreg_id, rc);
182 }
183 index--;
184 }
185 if (!on)
186 goto fail;
Santosh Sajjanecce5612011-08-08 19:05:51 +0530187clock_vote_fail:
188 gpio_set_value_cansleep(WLAN_GPIO_EXT_POR_N, 0);
189 rc = gpio_direction_input(WLAN_GPIO_EXT_POR_N);
190 if (rc) {
191 pr_err("WLAN reset GPIO %d set direction failed %d\n",
192 WLAN_GPIO_EXT_POR_N, rc);
193 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700194fail_gpio_dir_out:
195 gpio_free(WLAN_GPIO_EXT_POR_N);
196fail:
197 return rc;
198}
199EXPORT_SYMBOL(chip_power_qrf6285);