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>
31 #define gk104_volt(p) container_of((p), struct gk104_volt, base)
33 struct nvkm_volt base
;
34 struct nvbios_volt bios
;
38 gk104_volt_get(struct nvkm_volt
*base
)
40 struct nvbios_volt
*bios
= &gk104_volt(base
)->bios
;
41 struct nvkm_device
*device
= base
->subdev
.device
;
44 div
= nvkm_rd32(device
, 0x20340);
45 duty
= nvkm_rd32(device
, 0x20344);
47 return bios
->base
+ bios
->pwm_range
* duty
/ div
;
51 gk104_volt_set(struct nvkm_volt
*base
, u32 uv
)
53 struct nvbios_volt
*bios
= &gk104_volt(base
)->bios
;
54 struct nvkm_device
*device
= base
->subdev
.device
;
57 /* the blob uses this crystal frequency, let's use it too. */
58 div
= 27648000 / bios
->pwm_freq
;
59 duty
= (uv
- bios
->base
) * div
/ bios
->pwm_range
;
61 nvkm_wr32(device
, 0x20340, div
);
62 nvkm_wr32(device
, 0x20344, 0x80000000 | duty
);
67 static const struct nvkm_volt_func
69 .volt_get
= gk104_volt_get
,
70 .volt_set
= gk104_volt_set
,
71 }, gk104_volt_gpio
= {
72 .vid_get
= nvkm_voltgpio_get
,
73 .vid_set
= nvkm_voltgpio_set
,
77 gk104_volt_new(struct nvkm_device
*device
, int index
, struct nvkm_volt
**pvolt
)
79 const struct nvkm_volt_func
*volt_func
= &gk104_volt_gpio
;
80 struct dcb_gpio_func gpio
;
81 struct nvbios_volt bios
;
82 struct gk104_volt
*volt
;
83 u8 ver
, hdr
, cnt
, len
;
86 if (!nvbios_volt_parse(device
->bios
, &ver
, &hdr
, &cnt
, &len
, &bios
))
89 if (!nvkm_gpio_find(device
->gpio
, 0, DCB_GPIO_VID_PWM
, 0xff, &gpio
) &&
90 bios
.type
== NVBIOS_VOLT_PWM
) {
91 volt_func
= &gk104_volt_pwm
;
94 if (!(volt
= kzalloc(sizeof(*volt
), GFP_KERNEL
)))
96 nvkm_volt_ctor(volt_func
, device
, index
, &volt
->base
);
100 /* now that we have a subdev, we can show an error if we found through
101 * the voltage table that we were supposed to use the PWN mode but we
102 * did not find the right GPIO for it.
104 if (bios
.type
== NVBIOS_VOLT_PWM
&& volt_func
!= &gk104_volt_pwm
) {
105 nvkm_error(&volt
->base
.subdev
,
106 "Type mismatch between the voltage table type and "
107 "the GPIO table. Fallback to GPIO mode.\n");
110 if (volt_func
== &gk104_volt_gpio
) {
111 nvkm_voltgpio_init(&volt
->base
);
116 nvkm_debug(&volt
->base
.subdev
, "Using %s mode\n", mode
);
This page took 0.058115 seconds and 5 git commands to generate.