1 /* 2 * Copyright 2015 Martin Peres 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 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. 21 * 22 * Authors: Martin Peres 23 */ 24 #include "priv.h" 25 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> 31 32 #define gk104_volt(p) container_of((p), struct gk104_volt, base) 33 struct gk104_volt { 34 struct nvkm_volt base; 35 struct nvbios_volt bios; 36 }; 37 38 static int 39 gk104_volt_get(struct nvkm_volt *base) 40 { 41 struct nvbios_volt *bios = &gk104_volt(base)->bios; 42 struct nvkm_device *device = base->subdev.device; 43 u32 div, duty; 44 45 div = nvkm_rd32(device, 0x20340); 46 duty = nvkm_rd32(device, 0x20344); 47 48 return bios->base + bios->pwm_range * duty / div; 49 } 50 51 static int 52 gk104_volt_set(struct nvkm_volt *base, u32 uv) 53 { 54 struct nvbios_volt *bios = &gk104_volt(base)->bios; 55 struct nvkm_device *device = base->subdev.device; 56 u32 div, duty; 57 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); 61 62 nvkm_wr32(device, 0x20340, div); 63 nvkm_wr32(device, 0x20344, 0x80000000 | duty); 64 65 return 0; 66 } 67 68 static int 69 gk104_volt_speedo_read(struct nvkm_volt *volt) 70 { 71 struct nvkm_device *device = volt->subdev.device; 72 struct nvkm_fuse *fuse = device->fuse; 73 int ret; 74 75 if (!fuse) 76 return -EINVAL; 77 78 nvkm_wr32(device, 0x122634, 0x0); 79 ret = nvkm_fuse_read(fuse, 0x3a8); 80 nvkm_wr32(device, 0x122634, 0x41); 81 return ret; 82 } 83 84 static const struct nvkm_volt_func 85 gk104_volt_pwm = { 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, 95 }; 96 97 int 98 gk104_volt_new(struct nvkm_device *device, int index, struct nvkm_volt **pvolt) 99 { 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; 105 const char *mode; 106 107 if (!nvbios_volt_parse(device->bios, &ver, &hdr, &cnt, &len, &bios)) 108 return 0; 109 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; 113 } 114 115 if (!(volt = kzalloc(sizeof(*volt), GFP_KERNEL))) 116 return -ENOMEM; 117 nvkm_volt_ctor(volt_func, device, index, &volt->base); 118 *pvolt = &volt->base; 119 volt->bios = bios; 120 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. 124 */ 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"); 129 } 130 131 if (volt_func == &gk104_volt_gpio) { 132 nvkm_voltgpio_init(&volt->base); 133 mode = "GPIO"; 134 } else 135 mode = "PWM"; 136 137 nvkm_debug(&volt->base.subdev, "Using %s mode\n", mode); 138 139 return 0; 140 } 141