2 * Copyright 2015 Martin Peres
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:
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
22 * Authors: Martin Peres
26 #include <subdev/volt.h>
27 #include <subdev/gpio.h>
28 #include <subdev/bios.h>
29 #include <subdev/bios/volt.h>
30 #include <subdev/fuse.h>
32 #define gk104_volt(p) container_of((p), struct gk104_volt, base)
34 struct nvkm_volt base
;
35 struct nvbios_volt bios
;
39 gk104_volt_get(struct nvkm_volt
*base
)
41 struct nvbios_volt
*bios
= &gk104_volt(base
)->bios
;
42 struct nvkm_device
*device
= base
->subdev
.device
;
45 div
= nvkm_rd32(device
, 0x20340);
46 duty
= nvkm_rd32(device
, 0x20344);
48 return bios
->base
+ bios
->pwm_range
* duty
/ div
;
52 gk104_volt_set(struct nvkm_volt
*base
, u32 uv
)
54 struct nvbios_volt
*bios
= &gk104_volt(base
)->bios
;
55 struct nvkm_device
*device
= base
->subdev
.device
;
58 /* the blob uses this crystal frequency, let's use it too. */
59 div
= 27648000 / bios
->pwm_freq
;
60 duty
= DIV_ROUND_UP((uv
- bios
->base
) * div
, bios
->pwm_range
);
62 nvkm_wr32(device
, 0x20340, div
);
63 nvkm_wr32(device
, 0x20344, 0x80000000 | duty
);
69 gk104_volt_speedo_read(struct nvkm_volt
*volt
)
71 struct nvkm_device
*device
= volt
->subdev
.device
;
72 struct nvkm_fuse
*fuse
= device
->fuse
;
78 nvkm_wr32(device
, 0x122634, 0x0);
79 ret
= nvkm_fuse_read(fuse
, 0x3a8);
80 nvkm_wr32(device
, 0x122634, 0x41);
84 static const struct nvkm_volt_func
86 .oneinit
= gf100_volt_oneinit
,
87 .volt_get
= gk104_volt_get
,
88 .volt_set
= gk104_volt_set
,
89 .speedo_read
= gk104_volt_speedo_read
,
90 }, gk104_volt_gpio
= {
91 .oneinit
= gf100_volt_oneinit
,
92 .vid_get
= nvkm_voltgpio_get
,
93 .vid_set
= nvkm_voltgpio_set
,
94 .speedo_read
= gk104_volt_speedo_read
,
98 gk104_volt_new(struct nvkm_device
*device
, int index
, struct nvkm_volt
**pvolt
)
100 const struct nvkm_volt_func
*volt_func
= &gk104_volt_gpio
;
101 struct dcb_gpio_func gpio
;
102 struct nvbios_volt bios
;
103 struct gk104_volt
*volt
;
104 u8 ver
, hdr
, cnt
, len
;
107 if (!nvbios_volt_parse(device
->bios
, &ver
, &hdr
, &cnt
, &len
, &bios
))
110 if (!nvkm_gpio_find(device
->gpio
, 0, DCB_GPIO_VID_PWM
, 0xff, &gpio
) &&
111 bios
.type
== NVBIOS_VOLT_PWM
) {
112 volt_func
= &gk104_volt_pwm
;
115 if (!(volt
= kzalloc(sizeof(*volt
), GFP_KERNEL
)))
117 nvkm_volt_ctor(volt_func
, device
, index
, &volt
->base
);
118 *pvolt
= &volt
->base
;
121 /* now that we have a subdev, we can show an error if we found through
122 * the voltage table that we were supposed to use the PWN mode but we
123 * did not find the right GPIO for it.
125 if (bios
.type
== NVBIOS_VOLT_PWM
&& volt_func
!= &gk104_volt_pwm
) {
126 nvkm_error(&volt
->base
.subdev
,
127 "Type mismatch between the voltage table type and "
128 "the GPIO table. Fallback to GPIO mode.\n");
131 if (volt_func
== &gk104_volt_gpio
) {
132 nvkm_voltgpio_init(&volt
->base
);
137 nvkm_debug(&volt
->base
.subdev
, "Using %s mode\n", mode
);