diff options
author | Alexandre Courbot <acourbot@nvidia.com> | 2016-02-12 00:38:18 -0500 |
---|---|---|
committer | Ben Skeggs <bskeggs@redhat.com> | 2016-03-13 20:13:56 -0400 |
commit | 52829d4fabaf71748f16126d421dbefbfcf1319a (patch) | |
tree | 0c4cf14f0040458e0ca9b850f906c832563729a1 | |
parent | 42d6e16787106f3506a95f24d231c37a5ef14772 (diff) |
drm/nouveau/clk/gm20b: add basic driver
Add a basic clock driver that reuses the GK20A logic.
Signed-off-by: Alexandre Courbot <acourbot@nvidia.com>
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
-rw-r--r-- | drivers/gpu/drm/nouveau/include/nvkm/subdev/clk.h | 1 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nvkm/engine/device/base.c | 1 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nvkm/subdev/clk/Kbuild | 1 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nvkm/subdev/clk/gm20b.c | 198 |
4 files changed, 201 insertions, 0 deletions
diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/clk.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/clk.h index 6b33bc058924..fb54417bc458 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/clk.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/clk.h | |||
@@ -121,4 +121,5 @@ int gt215_clk_new(struct nvkm_device *, int, struct nvkm_clk **); | |||
121 | int gf100_clk_new(struct nvkm_device *, int, struct nvkm_clk **); | 121 | int gf100_clk_new(struct nvkm_device *, int, struct nvkm_clk **); |
122 | int gk104_clk_new(struct nvkm_device *, int, struct nvkm_clk **); | 122 | int gk104_clk_new(struct nvkm_device *, int, struct nvkm_clk **); |
123 | int gk20a_clk_new(struct nvkm_device *, int, struct nvkm_clk **); | 123 | int gk20a_clk_new(struct nvkm_device *, int, struct nvkm_clk **); |
124 | int gm20b_clk_new(struct nvkm_device *, int, struct nvkm_clk **); | ||
124 | #endif | 125 | #endif |
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c b/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c index bfe2f4f17f87..9f32c8739254 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c | |||
@@ -2083,6 +2083,7 @@ nv12b_chipset = { | |||
2083 | .name = "GM20B", | 2083 | .name = "GM20B", |
2084 | .bar = gk20a_bar_new, | 2084 | .bar = gk20a_bar_new, |
2085 | .bus = gf100_bus_new, | 2085 | .bus = gf100_bus_new, |
2086 | .clk = gm20b_clk_new, | ||
2086 | .fb = gk20a_fb_new, | 2087 | .fb = gk20a_fb_new, |
2087 | .fuse = gm107_fuse_new, | 2088 | .fuse = gm107_fuse_new, |
2088 | .ibus = gk20a_ibus_new, | 2089 | .ibus = gk20a_ibus_new, |
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/clk/Kbuild b/drivers/gpu/drm/nouveau/nvkm/subdev/clk/Kbuild index ed7717bcc3a1..87d94883f790 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/clk/Kbuild +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/clk/Kbuild | |||
@@ -8,6 +8,7 @@ nvkm-y += nvkm/subdev/clk/mcp77.o | |||
8 | nvkm-y += nvkm/subdev/clk/gf100.o | 8 | nvkm-y += nvkm/subdev/clk/gf100.o |
9 | nvkm-y += nvkm/subdev/clk/gk104.o | 9 | nvkm-y += nvkm/subdev/clk/gk104.o |
10 | nvkm-y += nvkm/subdev/clk/gk20a.o | 10 | nvkm-y += nvkm/subdev/clk/gk20a.o |
11 | nvkm-y += nvkm/subdev/clk/gm20b.o | ||
11 | 12 | ||
12 | nvkm-y += nvkm/subdev/clk/pllnv04.o | 13 | nvkm-y += nvkm/subdev/clk/pllnv04.o |
13 | nvkm-y += nvkm/subdev/clk/pllgt215.o | 14 | nvkm-y += nvkm/subdev/clk/pllgt215.o |
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/clk/gm20b.c b/drivers/gpu/drm/nouveau/nvkm/subdev/clk/gm20b.c new file mode 100644 index 000000000000..71b2bbb61973 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/clk/gm20b.c | |||
@@ -0,0 +1,198 @@ | |||
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 | } | ||