Commit fb422950 authored by Dave Airlie's avatar Dave Airlie
Browse files

Merge branch 'linux-4.9' of git://github.com/skeggsb/linux into drm-next

Karol's work which greatly improves volt/clock changes on a
heap of boards, nothing too exciting beyond a random collection of fixes.

* 'linux-4.9' of git://github.com/skeggsb/linux: (33 commits)
  drm/nouveau/fb/nv50: defer DMA mapping of scratch page to oneinit() hook
  drm/nouveau/fb/gf100: defer DMA mapping of scratch page to oneinit() hook
  drm/nouveau/pci: set streaming DMA mask early
  drm/nouveau/kms: add Maxwell to backlight initialization
  drm/nouveau/bar/nv50: fix bar2 vm size
  drm/nouveau/disp: remove unused function in sorg94.c
  drm/nouveau/volt: use kernel's 64-bit signed division function
  drm/nouveau/core: add missing header dependencies
  drm/nouveau/gr/nv3x: add 0x0597 kelvin 3d class support
  drm/nouveau/drm/nouveau: add a LED driver for the NVIDIA logo
  drm/nouveau/fb/ram: Use Kepler implementation on Maxwell
  drm/nouveau/volt: Make use of cvb coefficients
  drm/nouveau/volt/gf100-: Add speedo
  drm/nouveau/volt: Add implementation for gf100
  drm/nouveau/bios/vmap: unk0 field is the mode
  drm/nouveau/volt: Don't require perfect fit
  drm/nouveau/clk: Allow boosting only when NvBoost is set
  drm/nouveau/bios: Add parsing of VPSTATE table
  drm/nouveau/clk: Respect voltage limits in nvkm_cstate_prog
  drm/nouveau/clk: Fixup cstate selection
  ...
parents 220196b3 2ecf7c43
......@@ -124,6 +124,7 @@ nv35_gr = {
{ -1, -1, 0x038a, &nv04_gr_object }, /* ifc (nv30) */
{ -1, -1, 0x039e, &nv04_gr_object }, /* swzsurf (nv30) */
{ -1, -1, 0x0497, &nv04_gr_object }, /* rankine */
{ -1, -1, 0x0597, &nv04_gr_object }, /* kelvin */
{}
}
};
......
......@@ -84,7 +84,7 @@ nv50_bar_oneinit(struct nvkm_bar *base)
start = 0x0100000000ULL;
limit = start + device->func->resource_size(device, 3);
ret = nvkm_vm_new(device, start, limit, start, &bar3_lock, &vm);
ret = nvkm_vm_new(device, start, limit - start, start, &bar3_lock, &vm);
if (ret)
return ret;
......@@ -117,7 +117,7 @@ nv50_bar_oneinit(struct nvkm_bar *base)
start = 0x0000000000ULL;
limit = start + device->func->resource_size(device, 1);
ret = nvkm_vm_new(device, start, limit--, start, &bar1_lock, &vm);
ret = nvkm_vm_new(device, start, limit-- - start, start, &bar1_lock, &vm);
if (ret)
return ret;
......
......@@ -31,6 +31,7 @@ nvkm-y += nvkm/subdev/bios/timing.o
nvkm-y += nvkm/subdev/bios/therm.o
nvkm-y += nvkm/subdev/bios/vmap.o
nvkm-y += nvkm/subdev/bios/volt.o
nvkm-y += nvkm/subdev/bios/vpstate.o
nvkm-y += nvkm/subdev/bios/xpio.o
nvkm-y += nvkm/subdev/bios/M0203.o
nvkm-y += nvkm/subdev/bios/M0205.o
......
......@@ -23,6 +23,7 @@
*/
#include <subdev/bios.h>
#include <subdev/bios/bit.h>
#include <subdev/bios/extdev.h>
#include <subdev/bios/iccsense.h>
static u16
......@@ -77,23 +78,47 @@ nvbios_iccsense_parse(struct nvkm_bios *bios, struct nvbios_iccsense *iccsense)
return -ENOMEM;
for (i = 0; i < cnt; ++i) {
struct nvbios_extdev_func extdev;
struct pwr_rail_t *rail = &iccsense->rail[i];
u8 res_start = 0;
int r;
entry = table + hdr + i * len;
switch(ver) {
case 0x10:
rail->mode = nvbios_rd08(bios, entry + 0x1);
rail->extdev_id = nvbios_rd08(bios, entry + 0x2);
rail->resistor_mohm = nvbios_rd08(bios, entry + 0x3);
rail->rail = nvbios_rd08(bios, entry + 0x4);
res_start = 0x3;
break;
case 0x20:
rail->mode = nvbios_rd08(bios, entry);
rail->extdev_id = nvbios_rd08(bios, entry + 0x1);
rail->resistor_mohm = nvbios_rd08(bios, entry + 0x5);
rail->rail = nvbios_rd08(bios, entry + 0x6);
res_start = 0x5;
break;
};
if (nvbios_extdev_parse(bios, rail->extdev_id, &extdev))
continue;
switch (extdev.type) {
case NVBIOS_EXTDEV_INA209:
case NVBIOS_EXTDEV_INA219:
rail->resistor_count = 1;
break;
case NVBIOS_EXTDEV_INA3221:
rail->resistor_count = 3;
break;
default:
rail->resistor_count = 0;
break;
};
for (r = 0; r < rail->resistor_count; ++r) {
rail->resistors[r].mohm = nvbios_rd08(bios, entry + res_start + r * 2);
rail->resistors[r].enabled = !(nvbios_rd08(bios, entry + res_start + r * 2 + 1) & 0x40);
}
rail->config = nvbios_rd16(bios, entry + res_start + rail->resistor_count * 2);
}
return 0;
......
......@@ -61,7 +61,17 @@ nvbios_vmap_parse(struct nvkm_bios *bios, u8 *ver, u8 *hdr, u8 *cnt, u8 *len,
memset(info, 0x00, sizeof(*info));
switch (!!vmap * *ver) {
case 0x10:
info->max0 = 0xff;
info->max1 = 0xff;
info->max2 = 0xff;
break;
case 0x20:
info->max0 = nvbios_rd08(bios, vmap + 0x7);
info->max1 = nvbios_rd08(bios, vmap + 0x8);
if (*len >= 0xc)
info->max2 = nvbios_rd08(bios, vmap + 0xc);
else
info->max2 = 0xff;
break;
}
return vmap;
......@@ -95,7 +105,7 @@ nvbios_vmap_entry_parse(struct nvkm_bios *bios, int idx, u8 *ver, u8 *len,
info->arg[2] = nvbios_rd32(bios, vmap + 0x10);
break;
case 0x20:
info->unk0 = nvbios_rd08(bios, vmap + 0x00);
info->mode = nvbios_rd08(bios, vmap + 0x00);
info->link = nvbios_rd08(bios, vmap + 0x01);
info->min = nvbios_rd32(bios, vmap + 0x02);
info->max = nvbios_rd32(bios, vmap + 0x06);
......
......@@ -75,20 +75,24 @@ nvbios_volt_parse(struct nvkm_bios *bios, u8 *ver, u8 *hdr, u8 *cnt, u8 *len,
case 0x12:
info->type = NVBIOS_VOLT_GPIO;
info->vidmask = nvbios_rd08(bios, volt + 0x04);
info->ranged = false;
break;
case 0x20:
info->type = NVBIOS_VOLT_GPIO;
info->vidmask = nvbios_rd08(bios, volt + 0x05);
info->ranged = false;
break;
case 0x30:
info->type = NVBIOS_VOLT_GPIO;
info->vidmask = nvbios_rd08(bios, volt + 0x04);
info->ranged = false;
break;
case 0x40:
info->type = NVBIOS_VOLT_GPIO;
info->base = nvbios_rd32(bios, volt + 0x04);
info->step = nvbios_rd16(bios, volt + 0x08);
info->vidmask = nvbios_rd08(bios, volt + 0x0b);
info->ranged = true; /* XXX: find the flag byte */
/*XXX*/
info->min = 0;
info->max = info->base;
......@@ -104,9 +108,11 @@ nvbios_volt_parse(struct nvkm_bios *bios, u8 *ver, u8 *hdr, u8 *cnt, u8 *len,
info->pwm_freq = nvbios_rd32(bios, volt + 0x5) / 1000;
info->pwm_range = nvbios_rd32(bios, volt + 0x16);
} else {
info->type = NVBIOS_VOLT_GPIO;
info->vidmask = nvbios_rd08(bios, volt + 0x06);
info->step = nvbios_rd16(bios, volt + 0x16);
info->type = NVBIOS_VOLT_GPIO;
info->vidmask = nvbios_rd08(bios, volt + 0x06);
info->step = nvbios_rd16(bios, volt + 0x16);
info->ranged =
!!(nvbios_rd08(bios, volt + 0x4) & 0x2);
}
break;
}
......@@ -142,7 +148,10 @@ nvbios_volt_entry_parse(struct nvkm_bios *bios, int idx, u8 *ver, u8 *len,
info->vid = nvbios_rd08(bios, volt + 0x01) >> 2;
break;
case 0x40:
break;
case 0x50:
info->voltage = nvbios_rd32(bios, volt) & 0x001fffff;
info->vid = (nvbios_rd32(bios, volt) >> 23) & 0xff;
break;
}
return volt;
......
/*
* Copyright 2016 Karol Herbst
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
* Authors: Karol Herbst
*/
#include <subdev/bios.h>
#include <subdev/bios/bit.h>
#include <subdev/bios/vpstate.h>
static u32
nvbios_vpstate_offset(struct nvkm_bios *b)
{
struct bit_entry bit_P;
if (!bit_entry(b, 'P', &bit_P)) {
if (bit_P.version == 2)
return nvbios_rd32(b, bit_P.offset + 0x38);
}
return 0x0000;
}
int
nvbios_vpstate_parse(struct nvkm_bios *b, struct nvbios_vpstate_header *h)
{
if (!h)
return -EINVAL;
h->offset = nvbios_vpstate_offset(b);
if (!h->offset)
return -ENODEV;
h->version = nvbios_rd08(b, h->offset);
switch (h->version) {
case 0x10:
h->hlen = nvbios_rd08(b, h->offset + 0x1);
h->elen = nvbios_rd08(b, h->offset + 0x2);
h->slen = nvbios_rd08(b, h->offset + 0x3);
h->scount = nvbios_rd08(b, h->offset + 0x4);
h->ecount = nvbios_rd08(b, h->offset + 0x5);
h->base_id = nvbios_rd08(b, h->offset + 0x0f);
h->boost_id = nvbios_rd08(b, h->offset + 0x10);
h->tdp_id = nvbios_rd08(b, h->offset + 0x11);
return 0;
default:
return -EINVAL;
}
}
int
nvbios_vpstate_entry(struct nvkm_bios *b, struct nvbios_vpstate_header *h,
u8 idx, struct nvbios_vpstate_entry *e)
{
u32 offset;
if (!e || !h || idx > h->ecount)
return -EINVAL;
offset = h->offset + h->hlen + idx * (h->elen + (h->slen * h->scount));
e->pstate = nvbios_rd08(b, offset);
e->clock_mhz = nvbios_rd16(b, offset + 0x5);
return 0;
}
......@@ -27,6 +27,7 @@
#include <subdev/bios/boost.h>
#include <subdev/bios/cstep.h>
#include <subdev/bios/perf.h>
#include <subdev/bios/vpstate.h>
#include <subdev/fb.h>
#include <subdev/therm.h>
#include <subdev/volt.h>
......@@ -74,6 +75,88 @@ nvkm_clk_adjust(struct nvkm_clk *clk, bool adjust,
/******************************************************************************
* C-States
*****************************************************************************/
static bool
nvkm_cstate_valid(struct nvkm_clk *clk, struct nvkm_cstate *cstate,
u32 max_volt, int temp)
{
const struct nvkm_domain *domain = clk->domains;
struct nvkm_volt *volt = clk->subdev.device->volt;
int voltage;
while (domain && domain->name != nv_clk_src_max) {
if (domain->flags & NVKM_CLK_DOM_FLAG_VPSTATE) {
u32 freq = cstate->domain[domain->name];
switch (clk->boost_mode) {
case NVKM_CLK_BOOST_NONE:
if (clk->base_khz && freq > clk->base_khz)
return false;
case NVKM_CLK_BOOST_BIOS:
if (clk->boost_khz && freq > clk->boost_khz)
return false;
}
}
domain++;
}
if (!volt)
return true;
voltage = nvkm_volt_map(volt, cstate->voltage, temp);
if (voltage < 0)
return false;
return voltage <= min(max_volt, volt->max_uv);
}
static struct nvkm_cstate *
nvkm_cstate_find_best(struct nvkm_clk *clk, struct nvkm_pstate *pstate,
struct nvkm_cstate *start)
{
struct nvkm_device *device = clk->subdev.device;
struct nvkm_volt *volt = device->volt;
struct nvkm_cstate *cstate;
int max_volt;
if (!pstate || !start)
return NULL;
if (!volt)
return start;
max_volt = volt->max_uv;
if (volt->max0_id != 0xff)
max_volt = min(max_volt,
nvkm_volt_map(volt, volt->max0_id, clk->temp));
if (volt->max1_id != 0xff)
max_volt = min(max_volt,
nvkm_volt_map(volt, volt->max1_id, clk->temp));
if (volt->max2_id != 0xff)
max_volt = min(max_volt,
nvkm_volt_map(volt, volt->max2_id, clk->temp));
for (cstate = start; &cstate->head != &pstate->list;
cstate = list_entry(cstate->head.prev, typeof(*cstate), head)) {
if (nvkm_cstate_valid(clk, cstate, max_volt, clk->temp))
break;
}
return cstate;
}
static struct nvkm_cstate *
nvkm_cstate_get(struct nvkm_clk *clk, struct nvkm_pstate *pstate, int cstatei)
{
struct nvkm_cstate *cstate;
if (cstatei == NVKM_CLK_CSTATE_HIGHEST)
return list_last_entry(&pstate->list, typeof(*cstate), head);
else {
list_for_each_entry(cstate, &pstate->list, head) {
if (cstate->id == cstatei)
return cstate;
}
}
return NULL;
}
static int
nvkm_cstate_prog(struct nvkm_clk *clk, struct nvkm_pstate *pstate, int cstatei)
{
......@@ -85,7 +168,8 @@ nvkm_cstate_prog(struct nvkm_clk *clk, struct nvkm_pstate *pstate, int cstatei)
int ret;
if (!list_empty(&pstate->list)) {
cstate = list_entry(pstate->list.prev, typeof(*cstate), head);
cstate = nvkm_cstate_get(clk, pstate, cstatei);
cstate = nvkm_cstate_find_best(clk, pstate, cstate);
} else {
cstate = &pstate->base;
}
......@@ -99,7 +183,8 @@ nvkm_cstate_prog(struct nvkm_clk *clk, struct nvkm_pstate *pstate, int cstatei)
}
if (volt) {
ret = nvkm_volt_set_id(volt, cstate->voltage, +1);
ret = nvkm_volt_set_id(volt, cstate->voltage,
pstate->base.voltage, clk->temp, +1);
if (ret && ret != -ENODEV) {
nvkm_error(subdev, "failed to raise voltage: %d\n", ret);
return ret;
......@@ -113,7 +198,8 @@ nvkm_cstate_prog(struct nvkm_clk *clk, struct nvkm_pstate *pstate, int cstatei)
}
if (volt) {
ret = nvkm_volt_set_id(volt, cstate->voltage, -1);
ret = nvkm_volt_set_id(volt, cstate->voltage,
pstate->base.voltage, clk->temp, -1);
if (ret && ret != -ENODEV)
nvkm_error(subdev, "failed to lower voltage: %d\n", ret);
}
......@@ -138,6 +224,7 @@ static int
nvkm_cstate_new(struct nvkm_clk *clk, int idx, struct nvkm_pstate *pstate)
{
struct nvkm_bios *bios = clk->subdev.device->bios;
struct nvkm_volt *volt = clk->subdev.device->volt;
const struct nvkm_domain *domain = clk->domains;
struct nvkm_cstate *cstate = NULL;
struct nvbios_cstepX cstepX;
......@@ -148,12 +235,16 @@ nvkm_cstate_new(struct nvkm_clk *clk, int idx, struct nvkm_pstate *pstate)
if (!data)
return -ENOENT;
if (volt && nvkm_volt_map_min(volt, cstepX.voltage) > volt->max_uv)
return -EINVAL;
cstate = kzalloc(sizeof(*cstate), GFP_KERNEL);
if (!cstate)
return -ENOMEM;
*cstate = pstate->base;
cstate->voltage = cstepX.voltage;
cstate->id = idx;
while (domain && domain->name != nv_clk_src_max) {
if (domain->flags & NVKM_CLK_DOM_FLAG_CORE) {
......@@ -175,7 +266,7 @@ static int
nvkm_pstate_prog(struct nvkm_clk *clk, int pstatei)
{
struct nvkm_subdev *subdev = &clk->subdev;
struct nvkm_ram *ram = subdev->device->fb->ram;
struct nvkm_fb *fb = subdev->device->fb;
struct nvkm_pci *pci = subdev->device->pci;
struct nvkm_pstate *pstate;
int ret, idx = 0;
......@@ -190,7 +281,8 @@ nvkm_pstate_prog(struct nvkm_clk *clk, int pstatei)
nvkm_pcie_set_link(pci, pstate->pcie_speed, pstate->pcie_width);
if (ram && ram->func->calc) {
if (fb && fb->ram && fb->ram->func->calc) {
struct nvkm_ram *ram = fb->ram;
int khz = pstate->base.domain[nv_clk_src_mem];
do {
ret = ram->func->calc(ram, khz);
......@@ -200,7 +292,7 @@ nvkm_pstate_prog(struct nvkm_clk *clk, int pstatei)
ram->func->tidy(ram);
}
return nvkm_cstate_prog(clk, pstate, 0);
return nvkm_cstate_prog(clk, pstate, NVKM_CLK_CSTATE_HIGHEST);
}
static void
......@@ -214,14 +306,14 @@ nvkm_pstate_work(struct work_struct *work)
return;
clk->pwrsrc = power_supply_is_system_supplied();
nvkm_trace(subdev, "P %d PWR %d U(AC) %d U(DC) %d A %d T %d D %d\n",
nvkm_trace(subdev, "P %d PWR %d U(AC) %d U(DC) %d A %d T %d°C D %d\n",
clk->pstate, clk->pwrsrc, clk->ustate_ac, clk->ustate_dc,
clk->astate, clk->tstate, clk->dstate);
clk->astate, clk->temp, clk->dstate);
pstate = clk->pwrsrc ? clk->ustate_ac : clk->ustate_dc;
if (clk->state_nr && pstate != -1) {
pstate = (pstate < 0) ? clk->astate : pstate;
pstate = min(pstate, clk->state_nr - 1 + clk->tstate);
pstate = min(pstate, clk->state_nr - 1);
pstate = max(pstate, clk->dstate);
} else {
pstate = clk->pstate = -1;
......@@ -448,13 +540,12 @@ nvkm_clk_astate(struct nvkm_clk *clk, int req, int rel, bool wait)
}
int
nvkm_clk_tstate(struct nvkm_clk *clk, int req, int rel)
nvkm_clk_tstate(struct nvkm_clk *clk, u8 temp)
{
if (!rel) clk->tstate = req;
if ( rel) clk->tstate += rel;
clk->tstate = min(clk->tstate, 0);
clk->tstate = max(clk->tstate, -(clk->state_nr - 1));
return nvkm_pstate_calc(clk, true);
if (clk->temp == temp)
return 0;
clk->temp = temp;
return nvkm_pstate_calc(clk, false);
}
int
......@@ -524,9 +615,9 @@ nvkm_clk_init(struct nvkm_subdev *subdev)
return clk->func->init(clk);
clk->astate = clk->state_nr - 1;
clk->tstate = 0;
clk->dstate = 0;
clk->pstate = -1;
clk->temp = 90; /* reasonable default value */
nvkm_pstate_calc(clk, true);
return 0;
}
......@@ -561,10 +652,22 @@ int
nvkm_clk_ctor(const struct nvkm_clk_func *func, struct nvkm_device *device,
int index, bool allow_reclock, struct nvkm_clk *clk)
{
struct nvkm_subdev *subdev = &clk->subdev;
struct nvkm_bios *bios = device->bios;
int ret, idx, arglen;
const char *mode;
struct nvbios_vpstate_header h;
nvkm_subdev_ctor(&nvkm_clk, device, index, subdev);
if (bios && !nvbios_vpstate_parse(bios, &h)) {
struct nvbios_vpstate_entry base, boost;
if (!nvbios_vpstate_entry(bios, &h, h.boost_id, &boost))
clk->boost_khz = boost.clock_mhz * 1000;
if (!nvbios_vpstate_entry(bios, &h, h.base_id, &base))
clk->base_khz = base.clock_mhz * 1000;
}
nvkm_subdev_ctor(&nvkm_clk, device, index, &clk->subdev);
clk->func = func;
INIT_LIST_HEAD(&clk->states);
clk->domains = func->domains;
......@@ -607,6 +710,8 @@ nvkm_clk_ctor(const struct nvkm_clk_func *func, struct nvkm_device *device,
if (mode)
clk->ustate_dc = nvkm_clk_nstate(clk, mode, arglen);
clk->boost_mode = nvkm_longopt(device->cfgopt, "NvBoost",
NVKM_CLK_BOOST_NONE);
return 0;
}
......
......@@ -457,7 +457,7 @@ gf100_clk = {
{ nv_clk_src_hubk06 , 0x00 },
{ nv_clk_src_hubk01 , 0x01 },
{ nv_clk_src_copy , 0x02 },
{ nv_clk_src_gpc , 0x03, 0, "core", 2000 },
{ nv_clk_src_gpc , 0x03, NVKM_CLK_DOM_FLAG_VPSTATE, "core", 2000 },
{ nv_clk_src_rop , 0x04 },
{ nv_clk_src_mem , 0x05, 0, "memory", 1000 },
{ nv_clk_src_vdec , 0x06 },
......
......@@ -491,7 +491,7 @@ gk104_clk = {
.domains = {
{ nv_clk_src_crystal, 0xff },
{ nv_clk_src_href , 0xff },
{ nv_clk_src_gpc , 0x00, NVKM_CLK_DOM_FLAG_CORE, "core", 2000 },
{ nv_clk_src_gpc , 0x00, NVKM_CLK_DOM_FLAG_CORE | NVKM_CLK_DOM_FLAG_VPSTATE, "core", 2000 },
{ nv_clk_src_hubk07 , 0x01, NVKM_CLK_DOM_FLAG_CORE },
{ nv_clk_src_rop , 0x02, NVKM_CLK_DOM_FLAG_CORE },
{ nv_clk_src_mem , 0x03, 0, "memory", 500 },
......
......@@ -50,24 +50,33 @@ gf100_fb_intr(struct nvkm_fb *base)
}
int
gf100_fb_oneinit(struct nvkm_fb *fb)
gf100_fb_oneinit(struct nvkm_fb *base)
{
struct nvkm_device *device = fb->subdev.device;
struct gf100_fb *fb = gf100_fb(base);
struct nvkm_device *device = fb->base.subdev.device;
int ret, size = 0x1000;
size = nvkm_longopt(device->cfgopt, "MmuDebugBufferSize", size);
size = min(size, 0x1000);
ret = nvkm_memory_new(device, NVKM_MEM_TARGET_INST, size, 0x1000,
false, &fb->mmu_rd);
false, &fb->base.mmu_rd);
if (ret)
return ret;
ret = nvkm_memory_new(device, NVKM_MEM_TARGET_INST, size, 0x1000,
false, &fb->mmu_wr);
false, &fb->base.mmu_wr);
if (ret)
return ret;
fb->r100c10_page = alloc_page(GFP_KERNEL | __GFP_ZERO);
if (fb->r100c10_page) {
fb->r100c10 = dma_map_page(device->dev, fb->r100c10_page, 0,
PAGE_SIZE, DMA_BIDIRECTIONAL);
if (dma_mapping_error(device->dev, fb->r100c10))
return -EFAULT;
}
return 0;
}
......@@ -123,14 +132,6 @@ gf100_fb_new_(const struct nvkm_fb_func *func, struct nvkm_device *device,
nvkm_fb_ctor(func, device, index, &fb->base);
*pfb = &fb->base;
fb->r100c10_page = alloc_page(GFP_KERNEL | __GFP_ZERO);
if (fb->r100c10_page) {
fb->r100c10 = dma_map_page(device->dev, fb->r100c10_page, 0,
PAGE_SIZE, DMA_BIDIRECTIONAL);
if (dma_mapping_error(device->dev, fb->r100c10))
return -EFAULT;
}
return 0;
}
......
......@@ -210,6 +210,23 @@ nv50_fb_intr(struct nvkm_fb *base)
nvkm_fifo_chan_put(fifo, flags, &chan);
}
static int
nv50_fb_oneinit(struct nvkm_fb *base)
{
struct nv50_fb *fb = nv50_fb(base);
struct nvkm_device *device = fb->base.subdev.device;
fb->r100c08_page = alloc_page(GFP_KERNEL | __GFP_ZERO);
if (fb->r100c08_page) {
fb->r100c08 = dma_map_page(device->dev, fb->r100c08_page, 0,
PAGE_SIZE, DMA_BIDIRECTIONAL);
if (dma_mapping_error(device->dev, fb->r100c08))
return -EFAULT;
}
return 0;
}
static void
nv50_fb_init(struct nvkm_fb *base)
{
......@@ -245,6 +262,7 @@ nv50_fb_dtor(struct nvkm_fb *base)
static const struct nvkm_fb_func
nv50_fb_ = {
.dtor = nv50_fb_dtor,
.oneinit = nv50_fb_oneinit,
.init = nv50_fb_init,
.intr = nv50_fb_intr,
.ram_new = nv50_fb_ram_new,
......@@ -263,16 +281,6 @@ nv50_fb_new_(const struct nv50_fb_func *func, struct nvkm_device *device,
fb->func = func;
*pfb = &fb->base;
fb->r100c08_page = alloc_page(GFP_KERNEL | __GFP_ZERO);
if (fb->r100c08_page) {
fb->r100c08 = dma_map_page(device->dev, fb->r100c08_page, 0,
PAGE_SIZE, DMA_BIDIRECTIONAL);
if (dma_mapping_error(device->dev, fb->r100c08))
return -EFAULT;
} else {
nvkm_warn(&fb->base.subdev, "failed 100c08 page alloc\n");
}
return 0;
}
......
......@@ -24,6 +24,7 @@ int gf100_ram_ctor(const struct nvkm_ram_func *, struct nvkm_fb *,
int gf100_ram_get(struct nvkm_ram *, u64, u32, u32, u32, struct nvkm_mem **);
void gf100_ram_put(struct nvkm_ram *, struct nvkm_mem **);
int gk104_ram_ctor(struct nvkm_fb *, struct nvkm_ram **, u32);
int gk104_ram_init(struct nvkm_ram *ram);
/* RAM type-specific MR calculation routines */
......
......@@ -259,7 +259,9 @@ gk104_ram_calc_gddr5(struct gk104_ram *ram, u32 freq)
ram_mask(fuc, 0x10f808, 0x40000000, 0x40000000);
ram_block(fuc);
ram_wr32(fuc, 0x62c000, 0x0f0f0000);
if (nvkm_device_engine(ram->base.fb->subdev.device, NVKM_ENGINE_DISP))
ram_wr32(fuc, 0x62c000, 0x0f0f0000);
/* MR1: turn termination on early, for some reason.. */
if ((ram->base.mr[1] & 0x03c) != 0x030) {
......@@ -658,7 +660,9 @@ gk104_ram_calc_gddr5(struct gk104_ram *ram, u32 freq)
gk104_ram_train(fuc, 0x80020000, 0x01000000);
ram_unblock(fuc);
ram_wr32(fuc, 0x62c000, 0x0f0f0f00);
if (nvkm_device_engine(ram->base.fb->subdev.device, NVKM_ENGINE_DISP))
ram_wr32(fuc, 0x62c000, 0x0f0f0f00);
if (next->bios.rammap_11_08_01)
data = 0x00000800;
......@@ -706,7 +710,9 @@ gk104_ram_calc_sddr3(struct gk104_ram *ram, u32 freq)
ram_mask(fuc, 0x10f808, 0x40000000, 0x40000000);
ram_block(fuc);
ram_wr32(fuc, 0x62c000, 0x0f0f0000);
if (nvkm_device_engine(ram->base.fb->subdev.device, NVKM_ENGINE_DISP))
ram_wr32(fuc, 0x62c000, 0x0f0f0000);
if (vc == 1 && ram_have(fuc, gpio2E)) {
u32 temp = ram_mask(fuc, gpio2E, 0x3000, fuc->r_func2E[1]);
......@@ -936,7 +942,9 @@ gk104_ram_calc_sddr3(struct gk104_ram *ram, u32 freq)
ram_nsec(fuc, 1000);
ram_unblock(fuc);
ram_wr32(fuc, 0x62c000, 0x0f0f0f00);
if (nvkm_device_engine(ram->base.fb->subdev.device, NVKM_ENGINE_DISP))
ram_wr32(fuc, 0x62c000, 0x0f0f0f00);
if (next->bios.rammap_11_08_01)
data = 0x00000800;
......@@ -1529,6 +1537,12 @@ gk104_ram_func = {
int
gk104_ram_new(struct nvkm_fb *fb, struct nvkm_ram **pram)
{
return gk104_ram_ctor(fb, pram, 0x022554);
}
int
gk104_ram_ctor(struct nvkm_fb *fb, struct nvkm_ram **pram, u32 maskaddr)
{
struct nvkm_subdev *subdev = &fb->subdev;
struct nvkm_device *device = subdev->device;
......@@ -1544,7 +1558,7 @@ gk104_ram_new(struct nvkm_fb *fb, struct nvkm_ram **pram)
return -ENOMEM;
*pram = &ram->base;
ret = gf100_ram_ctor(&gk104_ram_func, fb, 0x022554, &ram->base);
ret = gf100_ram_ctor(&gk104_ram_func, fb, maskaddr, &ram->base);
if (ret)
return ret;
......
......@@ -23,18 +23,8 @@
*/
#include "ram.h"
static const struct nvkm_ram_func
gm107_ram_func = {
.init = gk104_ram_init,
.get = gf100_ram_get,
.put = gf100_ram_put,
};
int
gm107_ram_new(struct nvkm_fb *fb, struct nvkm_ram **pram)
{
if (!(*pram = kzalloc(sizeof(**pram), GFP_KERNEL)))
return -ENOMEM;
return gf100_ram_ctor(&gm107_ram_func, fb, 0x021c14, *pram);
return gk104_ram_ctor(fb, pram, 0x021c14);
}
......@@ -29,7 +29,7 @@ gk20a_ibus_init_ibus_ring(struct nvkm_subdev *ibus)
nvkm_mask(device, 0x137250, 0x3f, 0);
nvkm_mask(device, 0x000200, 0x20, 0);
usleep_range(20, 30);
udelay(20);
nvkm_mask(device, 0x000200, 0x20, 0x20);
nvkm_wr32(device, 0x12004c, 0x4);
......
......@@ -95,61 +95,13 @@ nvkm_iccsense_ina3221_read(struct nvkm_iccsense *iccsense,
40 * 8);
}
static void
nvkm_iccsense_ina209_config(struct nvkm_iccsense *iccsense,
struct nvkm_iccsense_sensor *sensor)
{
struct nvkm_subdev *subdev = &iccsense->subdev;
/* configuration:
* 0x0007: 0x0007 shunt and bus continous
* 0x0078: 0x0078 128 samples shunt
* 0x0780: 0x0780 128 samples bus
* 0x1800: 0x0000 +-40 mV shunt range
* 0x2000: 0x0000 16V FSR
*/
u16 value = 0x07ff;
nvkm_debug(subdev, "config for sensor id %i: 0x%x\n", sensor->id, value);
nv_wr16i2cr(sensor->i2c, sensor->addr, 0x00, value);
}
static void
nvkm_iccsense_ina3221_config(struct nvkm_iccsense *iccsense,
struct nvkm_iccsense_sensor *sensor)
{
struct nvkm_subdev *subdev = &iccsense->subdev;
/* configuration:
* 0x0007: 0x0007 shunt and bus continous
* 0x0031: 0x0000 140 us conversion time shunt
* 0x01c0: 0x0000 140 us conversion time bus
* 0x0f00: 0x0f00 1024 samples
* 0x7000: 0x?000 channels
*/
u16 value = 0x0e07;
if (sensor->rail_mask & 0x1)
value |= 0x1 << 14;
if (sensor->rail_mask & 0x2)
value |= 0x1 << 13;
if (sensor->rail_mask & 0x4)
value |= 0x1 << 12;
nvkm_debug(subdev, "config for sensor id %i: 0x%x\n", sensor->id, value);
nv_wr16i2cr(sensor->i2c, sensor->addr, 0x00, value);
}
static void
nvkm_iccsense_sensor_config(struct nvkm_iccsense *iccsense,
struct nvkm_iccsense_sensor *sensor)
{
switch (sensor->type) {
case NVBIOS_EXTDEV_INA209:
case NVBIOS_EXTDEV_INA219:
nvkm_iccsense_ina209_config(iccsense, sensor);
break;
case NVBIOS_EXTDEV_INA3221:
nvkm_iccsense_ina3221_config(iccsense, sensor);
break;
default:
break;
}
struct nvkm_subdev *subdev = &iccsense->subdev;
nvkm_trace(subdev, "write config of extdev %i: 0x%04x\n", sensor->id, sensor->config);
nv_wr16i2cr(sensor->i2c, sensor->addr, 0x00, sensor->config);
}
int
......@@ -196,7 +148,6 @@ nvkm_iccsense_dtor(struct nvkm_subdev *subdev)
static struct nvkm_iccsense_sensor*
nvkm_iccsense_create_sensor(struct nvkm_iccsense *iccsense, u8 id)
{
struct nvkm_subdev *subdev = &iccsense->subdev;
struct nvkm_bios *bios = subdev->device->bios;
struct nvkm_i2c *i2c = subdev->device->i2c;
......@@ -245,7 +196,7 @@ nvkm_iccsense_create_sensor(struct nvkm_iccsense *iccsense, u8 id)
sensor->type = extdev.type;
sensor->i2c = &i2c_bus->i2c;
sensor->addr = addr;
sensor->rail_mask = 0x0;
sensor->config = 0x0;
return sensor;
}
......@@ -273,48 +224,56 @@ nvkm_iccsense_oneinit(struct nvkm_subdev *subdev)
iccsense->data_valid = true;
for (i = 0; i < stbl.nr_entry; ++i) {
struct pwr_rail_t *r = &stbl.rail[i];
struct nvkm_iccsense_rail *rail;
struct pwr_rail_t *pwr_rail = &stbl.rail[i];
struct nvkm_iccsense_sensor *sensor;
int (*read)(struct nvkm_iccsense *,
struct nvkm_iccsense_rail *);
int r;
if (!r->mode || r->resistor_mohm == 0)
if (pwr_rail->mode != 1 || !pwr_rail->resistor_count)
continue;
sensor = nvkm_iccsense_get_sensor(iccsense, r->extdev_id);
sensor = nvkm_iccsense_get_sensor(iccsense, pwr_rail->extdev_id);
if (!sensor)
continue;
switch (sensor->type) {
case NVBIOS_EXTDEV_INA209:
if (r->rail != 0)
continue;
read = nvkm_iccsense_ina209_read;
break;
case NVBIOS_EXTDEV_INA219:
if (r->rail != 0)
if (!sensor->config)
sensor->config = pwr_rail->config;
else if (sensor->config != pwr_rail->config)
nvkm_error(subdev, "config mismatch found for extdev %i\n", pwr_rail->extdev_id);
for (r = 0; r < pwr_rail->resistor_count; ++r) {
struct nvkm_iccsense_rail *rail;
struct pwr_rail_resistor_t *res = &pwr_rail->resistors[r];
int (*read)(struct nvkm_iccsense *,
struct nvkm_iccsense_rail *);
if (!res->mohm || !res->enabled)
continue;
read = nvkm_iccsense_ina219_read;
break;
case NVBIOS_EXTDEV_INA3221:
if (r->rail >= 3)
switch (sensor->type) {
case NVBIOS_EXTDEV_INA209:
read = nvkm_iccsense_ina209_read;
break;
case NVBIOS_EXTDEV_INA219:
read = nvkm_iccsense_ina219_read;
break;
case NVBIOS_EXTDEV_INA3221:
read = nvkm_iccsense_ina3221_read;
break;
default:
continue;
read = nvkm_iccsense_ina3221_read;
break;
default:
continue;
}
rail = kmalloc(sizeof(*rail), GFP_KERNEL);
if (!rail)
return -ENOMEM;
rail->read = read;
rail->sensor = sensor;
rail->idx = r;
rail->mohm = res->mohm;
nvkm_debug(subdev, "create rail for extdev %i: { idx: %i, mohm: %i }\n", pwr_rail->extdev_id, r, rail->mohm);
list_add_tail(&rail->head, &iccsense->rails);
}
rail = kmalloc(sizeof(*rail), GFP_KERNEL);
if (!rail)
return -ENOMEM;
sensor->rail_mask |= 1 << r->rail;
rail->read = read;
rail->sensor = sensor;
rail->idx = r->rail;
rail->mohm = r->resistor_mohm;
list_add_tail(&rail->head, &iccsense->rails);
}
return 0;
}
......
......@@ -10,7 +10,7 @@ struct nvkm_iccsense_sensor {
enum nvbios_extdev_type type;
struct i2c_adapter *i2c;
u8 addr;
u8 rail_mask;
u16 config;
};
struct nvkm_iccsense_rail {
......
......@@ -23,8 +23,8 @@
*/
#include "mxms.h"
#define ROM16(x) le16_to_cpu(*(u16 *)&(x))
#define ROM32(x) le32_to_cpu(*(u32 *)&(x))
#define ROM16(x) get_unaligned_le16(&(x))
#define ROM32(x) get_unaligned_le32(&(x))
static u8 *
mxms_data(struct nvkm_mxm *mxm)
......
nvkm-y += nvkm/subdev/volt/base.o
nvkm-y += nvkm/subdev/volt/gpio.o
nvkm-y += nvkm/subdev/volt/nv40.o
nvkm-y += nvkm/subdev/volt/gf100.o
nvkm-y += nvkm/subdev/volt/gk104.o
nvkm-y += nvkm/subdev/volt/gk20a.o
nvkm-y += nvkm/subdev/volt/gm20b.o
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment