Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/sparc
[linux-2.6-block.git] / drivers / gpu / drm / nouveau / nvkm / subdev / clk / gm20b.c
1 /*
2  * Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved.
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be included in
12  * all copies or substantial portions of the Software.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
17  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20  * DEALINGS IN THE SOFTWARE.
21  */
22
23 #include <subdev/clk.h>
24 #include <core/device.h>
25
26 #include "priv.h"
27 #include "gk20a.h"
28
29 #define KHZ (1000)
30 #define MHZ (KHZ * 1000)
31
32 #define MASK(w) ((1 << w) - 1)
33
34 #define BYPASSCTRL_SYS  (SYS_GPCPLL_CFG_BASE + 0x340)
35 #define BYPASSCTRL_SYS_GPCPLL_SHIFT     0
36 #define BYPASSCTRL_SYS_GPCPLL_WIDTH     1
37
38 static u32 pl_to_div(u32 pl)
39 {
40         return pl;
41 }
42
43 static u32 div_to_pl(u32 div)
44 {
45         return div;
46 }
47
48 static const struct gk20a_clk_pllg_params gm20b_pllg_params = {
49         .min_vco = 1300000, .max_vco = 2600000,
50         .min_u = 12000, .max_u = 38400,
51         .min_m = 1, .max_m = 255,
52         .min_n = 8, .max_n = 255,
53         .min_pl = 1, .max_pl = 31,
54 };
55
56 static struct nvkm_pstate
57 gm20b_pstates[] = {
58         {
59                 .base = {
60                         .domain[nv_clk_src_gpc] = 76800,
61                         .voltage = 0,
62                 },
63         },
64         {
65                 .base = {
66                         .domain[nv_clk_src_gpc] = 153600,
67                         .voltage = 1,
68                 },
69         },
70         {
71                 .base = {
72                         .domain[nv_clk_src_gpc] = 230400,
73                         .voltage = 2,
74                 },
75         },
76         {
77                 .base = {
78                         .domain[nv_clk_src_gpc] = 307200,
79                         .voltage = 3,
80                 },
81         },
82         {
83                 .base = {
84                         .domain[nv_clk_src_gpc] = 384000,
85                         .voltage = 4,
86                 },
87         },
88         {
89                 .base = {
90                         .domain[nv_clk_src_gpc] = 460800,
91                         .voltage = 5,
92                 },
93         },
94         {
95                 .base = {
96                         .domain[nv_clk_src_gpc] = 537600,
97                         .voltage = 6,
98                 },
99         },
100         {
101                 .base = {
102                         .domain[nv_clk_src_gpc] = 614400,
103                         .voltage = 7,
104                 },
105         },
106         {
107                 .base = {
108                         .domain[nv_clk_src_gpc] = 691200,
109                         .voltage = 8,
110                 },
111         },
112         {
113                 .base = {
114                         .domain[nv_clk_src_gpc] = 768000,
115                         .voltage = 9,
116                 },
117         },
118         {
119                 .base = {
120                         .domain[nv_clk_src_gpc] = 844800,
121                         .voltage = 10,
122                 },
123         },
124         {
125                 .base = {
126                         .domain[nv_clk_src_gpc] = 921600,
127                         .voltage = 11,
128                 },
129         },
130         {
131                 .base = {
132                         .domain[nv_clk_src_gpc] = 998400,
133                         .voltage = 12,
134                 },
135         },
136
137 };
138
139 static int
140 gm20b_clk_init(struct nvkm_clk *base)
141 {
142         struct gk20a_clk *clk = gk20a_clk(base);
143         struct nvkm_subdev *subdev = &clk->base.subdev;
144         struct nvkm_device *device = subdev->device;
145         int ret;
146
147         /* Set the global bypass control to VCO */
148         nvkm_mask(device, BYPASSCTRL_SYS,
149                MASK(BYPASSCTRL_SYS_GPCPLL_WIDTH) << BYPASSCTRL_SYS_GPCPLL_SHIFT,
150                0);
151
152         /* Start with lowest frequency */
153         base->func->calc(base, &base->func->pstates[0].base);
154         ret = base->func->prog(&clk->base);
155         if (ret) {
156                 nvkm_error(subdev, "cannot initialize clock\n");
157                 return ret;
158         }
159
160         return 0;
161 }
162
163 static const struct nvkm_clk_func
164 gm20b_clk_speedo0 = {
165         .init = gm20b_clk_init,
166         .fini = gk20a_clk_fini,
167         .read = gk20a_clk_read,
168         .calc = gk20a_clk_calc,
169         .prog = gk20a_clk_prog,
170         .tidy = gk20a_clk_tidy,
171         .pstates = gm20b_pstates,
172         .nr_pstates = ARRAY_SIZE(gm20b_pstates) - 1,
173         .domains = {
174                 { nv_clk_src_crystal, 0xff },
175                 { nv_clk_src_gpc, 0xff, 0, "core", GK20A_CLK_GPC_MDIV },
176                 { nv_clk_src_max },
177         },
178 };
179
180 int
181 gm20b_clk_new(struct nvkm_device *device, int index, struct nvkm_clk **pclk)
182 {
183         struct gk20a_clk *clk;
184         int ret;
185
186         clk = kzalloc(sizeof(*clk), GFP_KERNEL);
187         if (!clk)
188                 return -ENOMEM;
189         *pclk = &clk->base;
190
191         ret = _gk20a_clk_ctor(device, index, &gm20b_clk_speedo0,
192                               &gm20b_pllg_params, clk);
193
194         clk->pl_to_div = pl_to_div;
195         clk->div_to_pl = div_to_pl;
196
197         return ret;
198 }