gpu: nvgpu: Add GPCPLL DVFS state to debug prints
[linux-3.10.git] / drivers / gpu / nvgpu / gm20b / pmu_gm20b.c
1 /*
2  * GM20B PMU
3  *
4  * Copyright (c) 2014, NVIDIA CORPORATION.  All rights reserved.
5 *
6  * This program is free software; you can redistribute it and/or modify it
7  * under the terms and conditions of the GNU General Public License,
8  * version 2, as published by the Free Software Foundation.
9  *
10  * This program is distributed in the hope it will be useful, but WITHOUT
11  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
13  * more details.
14  */
15
16 #include <linux/delay.h>        /* for udelay */
17 #include "gk20a/gk20a.h"
18 #include "gk20a/pmu_gk20a.h"
19 #include "acr_gm20b.h"
20 #include "pmu_gm20b.h"
21
22 /*!
23  * Structure/object which single register write need to be done during PG init
24  * sequence to set PROD values.
25  */
26 struct pg_init_sequence_list {
27         u32 regaddr;
28         u32 writeval;
29 };
30
31 #define gm20b_dbg_pmu(fmt, arg...) \
32         gk20a_dbg(gpu_dbg_pmu, fmt, ##arg)
33
34
35 /* PROD settings for ELPG sequencing registers*/
36 static struct pg_init_sequence_list _pginitseq_gm20b[] = {
37                 { 0x0010ab10, 0x8180},
38                 { 0x0010e118, 0x81818080},
39                 { 0x0010e068, 0},
40                 { 0x0010e06c, 0x00000080},
41                 { 0x0010e06c, 0x00000080},
42                 { 0x0010e06c, 0x00000081},
43                 { 0x0010e06c, 0x00000081},
44                 { 0x0010e06c, 0x00000082},
45                 { 0x0010e06c, 0x00000083},
46                 { 0x0010e06c, 0x00000083},
47                 { 0x0010e06c, 0x00000083},
48                 { 0x0010e06c, 0x00000083},
49                 { 0x0010e06c, 0x00000083},
50                 { 0x0010e06c, 0x00000080},
51                 { 0x0010e06c, 0x00000080},
52                 { 0x0010e06c, 0x00000081},
53                 { 0x0010e06c, 0x00000081},
54                 { 0x0010e06c, 0x00000082},
55                 { 0x0010e06c, 0x00000083},
56                 { 0x0010e06c, 0x00000083},
57                 { 0x0010e06c, 0x00000083},
58                 { 0x0010e06c, 0x00000083},
59                 { 0x0010e06c, 0x00000083},
60                 { 0x0010e06c, 0x00000080},
61                 { 0x0010e06c, 0x00000080},
62                 { 0x0010e06c, 0x00000081},
63                 { 0x0010e06c, 0x00000081},
64                 { 0x0010e06c, 0x00000082},
65                 { 0x0010e06c, 0x00000083},
66                 { 0x0010e06c, 0x00000083},
67                 { 0x0010e06c, 0x00000083},
68                 { 0x0010e06c, 0x00000083},
69                 { 0x0010e06c, 0x00000083},
70                 { 0x0010e06c, 0x00000080},
71                 { 0x0010e06c, 0x00000080},
72                 { 0x0010e06c, 0x00000081},
73                 { 0x0010e06c, 0x00000081},
74                 { 0x0010e06c, 0x00000082},
75                 { 0x0010e06c, 0x00000083},
76                 { 0x0010e06c, 0x00000083},
77                 { 0x0010e06c, 0x00000083},
78                 { 0x0010e06c, 0x00000083},
79                 { 0x0010e06c, 0x00000083},
80                 { 0x0010e06c, 0x00000080},
81                 { 0x0010e06c, 0x00000080},
82                 { 0x0010e06c, 0x00000081},
83                 { 0x0010e06c, 0x00000081},
84                 { 0x0010e06c, 0x00000082},
85                 { 0x0010e06c, 0x00000083},
86                 { 0x0010e06c, 0x00000083},
87                 { 0x0010e06c, 0x00000083},
88                 { 0x0010e06c, 0x00000083},
89                 { 0x0010e06c, 0x00000083},
90                 { 0x0010e06c, 0x00000080},
91                 { 0x0010e06c, 0x00000080},
92                 { 0x0010e06c, 0x00000081},
93                 { 0x0010e06c, 0x00000081},
94                 { 0x0010e06c, 0x00000082},
95                 { 0x0010e06c, 0x00000083},
96                 { 0x0010e06c, 0x00000083},
97                 { 0x0010e06c, 0x00000083},
98                 { 0x0010e06c, 0x00000083},
99                 { 0x0010e06c, 0x00000083},
100                 { 0x0010e06c, 0x00000080},
101                 { 0x0010e06c, 0x00000080},
102                 { 0x0010e06c, 0x00000081},
103                 { 0x0010e06c, 0x00000081},
104                 { 0x0010e06c, 0x00000082},
105                 { 0x0010e06c, 0x00000083},
106                 { 0x0010ab14, 0x00000000},
107                 { 0x0010ab18, 0x00000000},
108                 { 0x0010e024, 0x00000000},
109                 { 0x0010e028, 0x00000000},
110                 { 0x0010e11c, 0x00000000},
111                 { 0x0010e120, 0x00000000},
112                 { 0x0010ab1c, 0x00010011},
113                 { 0x0010e020, 0x001C0011},
114                 { 0x0010e124, 0x00030011},
115                 { 0x0010ab20, 0xfedcba98},
116                 { 0x0010ab24, 0x00000000},
117                 { 0x0010e02c, 0xfedcba98},
118                 { 0x0010e030, 0x00000000},
119                 { 0x0010e128, 0xfedcba98},
120                 { 0x0010e12c, 0x00000000},
121                 { 0x0010ab28, 0x71111111},
122                 { 0x0010ab2c, 0x70000000},
123                 { 0x0010e034, 0x71111111},
124                 { 0x0010e038, 0x70000000},
125                 { 0x0010e130, 0x71111111},
126                 { 0x0010e134, 0x70000000},
127                 { 0x0010ab30, 0x00000000},
128                 { 0x0010ab34, 0x00000001},
129                 { 0x00020004, 0x00000000},
130                 { 0x0010e138, 0x00000000},
131                 { 0x0010e040, 0x00000000},
132 };
133
134 static int gm20b_pmu_setup_elpg(struct gk20a *g)
135 {
136         int ret = 0;
137         u32 reg_writes;
138         u32 index;
139
140         gk20a_dbg_fn("");
141
142         if (g->elpg_enabled) {
143                 reg_writes = ((sizeof(_pginitseq_gm20b) /
144                                 sizeof((_pginitseq_gm20b)[0])));
145                 /* Initialize registers with production values*/
146                 for (index = 0; index < reg_writes; index++) {
147                         gk20a_writel(g, _pginitseq_gm20b[index].regaddr,
148                                 _pginitseq_gm20b[index].writeval);
149                 }
150         }
151
152         gk20a_dbg_fn("done");
153         return ret;
154 }
155
156 static void pmu_handle_acr_init_wpr_msg(struct gk20a *g, struct pmu_msg *msg,
157                         void *param, u32 handle, u32 status)
158 {
159         gk20a_dbg_fn("");
160
161         gm20b_dbg_pmu("reply PMU_ACR_CMD_ID_INIT_WPR_REGION");
162
163         if (msg->msg.acr.acrmsg.errorcode == PMU_ACR_SUCCESS)
164                 g->ops.pmu.lspmuwprinitdone = true;
165         gk20a_dbg_fn("done");
166 }
167
168
169 static int gm20b_pmu_init_acr(struct gk20a *g)
170 {
171         struct pmu_gk20a *pmu = &g->pmu;
172         struct pmu_cmd cmd;
173         u32 seq;
174
175         gk20a_dbg_fn("");
176
177         /* init ACR */
178         memset(&cmd, 0, sizeof(struct pmu_cmd));
179         cmd.hdr.unit_id = PMU_UNIT_ACR;
180         cmd.hdr.size = PMU_CMD_HDR_SIZE +
181           sizeof(struct pmu_acr_cmd_init_wpr_details);
182         cmd.cmd.acr.init_wpr.cmd_type = PMU_ACR_CMD_ID_INIT_WPR_REGION;
183         cmd.cmd.acr.init_wpr.regionid = 0x01;
184         cmd.cmd.acr.init_wpr.wproffset = 0x00;
185         gm20b_dbg_pmu("cmd post PMU_ACR_CMD_ID_INIT_WPR_REGION");
186         gk20a_pmu_cmd_post(g, &cmd, NULL, NULL, PMU_COMMAND_QUEUE_HPQ,
187                         pmu_handle_acr_init_wpr_msg, pmu, &seq, ~0);
188
189         gk20a_dbg_fn("done");
190         return 0;
191 }
192
193 static void pmu_handle_fecs_boot_acr_msg(struct gk20a *g, struct pmu_msg *msg,
194                         void *param, u32 handle, u32 status)
195 {
196
197         gk20a_dbg_fn("");
198
199
200         if (msg->msg.acr.acrmsg.falconid == LSF_FALCON_ID_FECS)
201                 gm20b_dbg_pmu("reply PMU_ACR_CMD_ID_BOOTSTRAP_FALCON");
202
203         gm20b_dbg_pmu("response code = %x\n", msg->msg.acr.acrmsg.falconid);
204         gk20a_dbg_fn("done");
205 }
206
207 void gm20b_pmu_load_lsf(struct gk20a *g, u8 falcon_id)
208 {
209         struct pmu_gk20a *pmu = &g->pmu;
210         struct pmu_cmd cmd;
211         u32 seq;
212
213         gk20a_dbg_fn("");
214
215         gm20b_dbg_pmu("wprinit status = %x\n", g->ops.pmu.lspmuwprinitdone);
216         if (g->ops.pmu.lspmuwprinitdone && g->ops.pmu.fecsbootstrapdone) {
217                 /* send message to load FECS falcon */
218                 memset(&cmd, 0, sizeof(struct pmu_cmd));
219                 cmd.hdr.unit_id = PMU_UNIT_ACR;
220                 cmd.hdr.size = PMU_CMD_HDR_SIZE +
221                   sizeof(struct pmu_acr_cmd_bootstrap_falcon);
222                 cmd.cmd.acr.bootstrap_falcon.cmd_type =
223                   PMU_ACR_CMD_ID_BOOTSTRAP_FALCON;
224                 cmd.cmd.acr.bootstrap_falcon.flags =
225                   PMU_ACR_CMD_BOOTSTRAP_FALCON_FLAGS_RESET_YES;
226                 cmd.cmd.acr.bootstrap_falcon.falconid = falcon_id;
227                 gm20b_dbg_pmu("cmd post PMU_ACR_CMD_ID_BOOTSTRAP_FALCON");
228                 g->ops.pmu.fecsrecoveryinprogress = 1;
229                 gk20a_pmu_cmd_post(g, &cmd, NULL, NULL, PMU_COMMAND_QUEUE_HPQ,
230                                 pmu_handle_fecs_boot_acr_msg, pmu, &seq, ~0);
231         }
232
233         gk20a_dbg_fn("done");
234         return;
235 }
236
237 void gm20b_init_pmu_ops(struct gpu_ops *gops)
238 {
239         if (gops->privsecurity) {
240                 gm20b_init_secure_pmu(gops);
241                 gops->pmu.init_wpr_region = gm20b_pmu_init_acr;
242         } else {
243                 gk20a_init_pmu_ops(gops);
244                 gops->pmu.init_wpr_region = NULL;
245         }
246         gops->pmu.pmu_setup_elpg = gm20b_pmu_setup_elpg;
247         gops->pmu.lspmuwprinitdone = false;
248         gops->pmu.fecsbootstrapdone = false;
249         gops->pmu.fecsrecoveryinprogress = 0;
250 }