ramnve0.c revision 4cc6c3fe391b9a5869e3ca08f3619963064f079c
1aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs/*
2aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs * Copyright 2013 Red Hat Inc.
3aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs *
4aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs * Permission is hereby granted, free of charge, to any person obtaining a
5aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs * copy of this software and associated documentation files (the "Software"),
6aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs * to deal in the Software without restriction, including without limitation
7aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs * and/or sell copies of the Software, and to permit persons to whom the
9aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs * Software is furnished to do so, subject to the following conditions:
10aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs *
11aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs * The above copyright notice and this permission notice shall be included in
12aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs * all copies or substantial portions of the Software.
13aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs *
14aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
17aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs * OTHER DEALINGS IN THE SOFTWARE.
21aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs *
22aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs * Authors: Ben Skeggs
23aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs */
24aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs
25aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs#include <subdev/gpio.h>
26aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs
27aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs#include <subdev/bios.h>
28aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs#include <subdev/bios/pll.h>
29aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs#include <subdev/bios/init.h>
30aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs#include <subdev/bios/rammap.h>
31aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs#include <subdev/bios/timing.h>
32aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs
33aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs#include <subdev/clock.h>
34aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs#include <subdev/clock/pll.h>
35aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs
36aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs#include <subdev/timer.h>
37aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs
38aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs#include <core/option.h>
39aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs
40aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs#include "nvc0.h"
41aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs
42aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs#include "ramfuc.h"
43aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs
44db6735cab2b0f12a824f04b1d8fb4da2ea978c8dBen Skeggs/* binary driver only executes this path if the condition (a) is true
45db6735cab2b0f12a824f04b1d8fb4da2ea978c8dBen Skeggs * for any configuration (combination of rammap+ramcfg+timing) that
46db6735cab2b0f12a824f04b1d8fb4da2ea978c8dBen Skeggs * can be reached on a given card.  for now, we will execute the branch
47db6735cab2b0f12a824f04b1d8fb4da2ea978c8dBen Skeggs * unconditionally in the hope that a "false everywhere" in the bios
48db6735cab2b0f12a824f04b1d8fb4da2ea978c8dBen Skeggs * tables doesn't actually mean "don't touch this".
49db6735cab2b0f12a824f04b1d8fb4da2ea978c8dBen Skeggs */
50db6735cab2b0f12a824f04b1d8fb4da2ea978c8dBen Skeggs#define NOTE00(a) 1
51db6735cab2b0f12a824f04b1d8fb4da2ea978c8dBen Skeggs
52aae95ca708140307813e49af6d0d4a7205509129Ben Skeggsstruct nve0_ramfuc {
53aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	struct ramfuc base;
54aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs
55aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	struct nvbios_pll refpll;
56aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	struct nvbios_pll mempll;
57aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs
58aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	struct ramfuc_reg r_gpioMV;
59aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	u32 r_funcMV[2];
60aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	struct ramfuc_reg r_gpio2E;
61aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	u32 r_func2E[2];
62aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	struct ramfuc_reg r_gpiotrig;
63aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs
64aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	struct ramfuc_reg r_0x132020;
65aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	struct ramfuc_reg r_0x132028;
66aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	struct ramfuc_reg r_0x132024;
67aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	struct ramfuc_reg r_0x132030;
68aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	struct ramfuc_reg r_0x132034;
69aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	struct ramfuc_reg r_0x132000;
70aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	struct ramfuc_reg r_0x132004;
71aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	struct ramfuc_reg r_0x132040;
72aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs
73aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	struct ramfuc_reg r_0x10f248;
74aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	struct ramfuc_reg r_0x10f290;
75aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	struct ramfuc_reg r_0x10f294;
76aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	struct ramfuc_reg r_0x10f298;
77aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	struct ramfuc_reg r_0x10f29c;
78aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	struct ramfuc_reg r_0x10f2a0;
79aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	struct ramfuc_reg r_0x10f2a4;
80aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	struct ramfuc_reg r_0x10f2a8;
81aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	struct ramfuc_reg r_0x10f2ac;
82aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	struct ramfuc_reg r_0x10f2cc;
83aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	struct ramfuc_reg r_0x10f2e8;
84aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	struct ramfuc_reg r_0x10f250;
85aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	struct ramfuc_reg r_0x10f24c;
86aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	struct ramfuc_reg r_0x10fec4;
87aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	struct ramfuc_reg r_0x10fec8;
88aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	struct ramfuc_reg r_0x10f604;
89aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	struct ramfuc_reg r_0x10f614;
90aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	struct ramfuc_reg r_0x10f610;
91aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	struct ramfuc_reg r_0x100770;
92aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	struct ramfuc_reg r_0x100778;
93aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	struct ramfuc_reg r_0x10f224;
94aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs
95aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	struct ramfuc_reg r_0x10f870;
96aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	struct ramfuc_reg r_0x10f698;
97aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	struct ramfuc_reg r_0x10f694;
98aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	struct ramfuc_reg r_0x10f6b8;
99aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	struct ramfuc_reg r_0x10f808;
100aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	struct ramfuc_reg r_0x10f670;
101aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	struct ramfuc_reg r_0x10f60c;
102aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	struct ramfuc_reg r_0x10f830;
103aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	struct ramfuc_reg r_0x1373ec;
104aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	struct ramfuc_reg r_0x10f800;
105aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	struct ramfuc_reg r_0x10f82c;
106aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs
107aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	struct ramfuc_reg r_0x10f978;
108aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	struct ramfuc_reg r_0x10f910;
109aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	struct ramfuc_reg r_0x10f914;
110aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs
111aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	struct ramfuc_reg r_mr[16]; /* MR0 - MR8, MR15 */
112aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs
113aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	struct ramfuc_reg r_0x62c000;
114d394fb12eca4cb9f42f922d7ae2bc8d7e1ed9272Ben Skeggs
115aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	struct ramfuc_reg r_0x10f200;
116d394fb12eca4cb9f42f922d7ae2bc8d7e1ed9272Ben Skeggs
117aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	struct ramfuc_reg r_0x10f210;
118aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	struct ramfuc_reg r_0x10f310;
119aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	struct ramfuc_reg r_0x10f314;
120aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	struct ramfuc_reg r_0x10f318;
121aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	struct ramfuc_reg r_0x10f090;
122aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	struct ramfuc_reg r_0x10f69c;
123aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	struct ramfuc_reg r_0x10f824;
124aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	struct ramfuc_reg r_0x1373f0;
125aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	struct ramfuc_reg r_0x1373f4;
126aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	struct ramfuc_reg r_0x137320;
127aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	struct ramfuc_reg r_0x10f65c;
128aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	struct ramfuc_reg r_0x10f6bc;
129aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	struct ramfuc_reg r_0x100710;
130dd95c8f782a053db361855298778a7d31de04a48Ben Skeggs	struct ramfuc_reg r_0x100750;
131aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs};
132aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs
133aae95ca708140307813e49af6d0d4a7205509129Ben Skeggsstruct nve0_ram {
134aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	struct nouveau_ram base;
135aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	struct nve0_ramfuc fuc;
136d394fb12eca4cb9f42f922d7ae2bc8d7e1ed9272Ben Skeggs
137d394fb12eca4cb9f42f922d7ae2bc8d7e1ed9272Ben Skeggs	u32 parts;
138d394fb12eca4cb9f42f922d7ae2bc8d7e1ed9272Ben Skeggs	u32 pmask;
139d394fb12eca4cb9f42f922d7ae2bc8d7e1ed9272Ben Skeggs	u32 pnuts;
140d394fb12eca4cb9f42f922d7ae2bc8d7e1ed9272Ben Skeggs
141aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	int from;
142aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	int mode;
143aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	int N1, fN1, M1, P1;
144aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	int N2, M2, P2;
145aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs};
146aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs
147aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs/*******************************************************************************
148aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs * GDDR5
149aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs ******************************************************************************/
150aae95ca708140307813e49af6d0d4a7205509129Ben Skeggsstatic void
15101891690e8e0d1230b8b3d96a42810b3ab8b38c1Ben Skeggsnve0_ram_train(struct nve0_ramfuc *fuc, u32 mask, u32 data)
152aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs{
153aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	struct nve0_ram *ram = container_of(fuc, typeof(*ram), fuc);
154d394fb12eca4cb9f42f922d7ae2bc8d7e1ed9272Ben Skeggs	u32 addr = 0x110974, i;
155aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs
15601891690e8e0d1230b8b3d96a42810b3ab8b38c1Ben Skeggs	ram_mask(fuc, 0x10f910, mask, data);
15701891690e8e0d1230b8b3d96a42810b3ab8b38c1Ben Skeggs	ram_mask(fuc, 0x10f914, mask, data);
1585905439224043465309e9989bfd9369efb9220abBen Skeggs
15901891690e8e0d1230b8b3d96a42810b3ab8b38c1Ben Skeggs	for (i = 0; (data & 0x80000000) && i < ram->parts; addr += 0x1000, i++) {
160d394fb12eca4cb9f42f922d7ae2bc8d7e1ed9272Ben Skeggs		if (ram->pmask & (1 << i))
1615905439224043465309e9989bfd9369efb9220abBen Skeggs			continue;
162aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		ram_wait(fuc, addr, 0x0000000f, 0x00000000, 500000);
163aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	}
164aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs}
165aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs
166aae95ca708140307813e49af6d0d4a7205509129Ben Skeggsstatic void
167aae95ca708140307813e49af6d0d4a7205509129Ben Skeggsr1373f4_init(struct nve0_ramfuc *fuc)
168aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs{
169aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	struct nve0_ram *ram = container_of(fuc, typeof(*ram), fuc);
170aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	const u32 mcoef = ((--ram->P2 << 28) | (ram->N2 << 8) | ram->M2);
171aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	const u32 rcoef = ((  ram->P1 << 16) | (ram->N1 << 8) | ram->M1);
172aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	const u32 runk0 = ram->fN1 << 16;
173aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	const u32 runk1 = ram->fN1;
174aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs
175aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	if (ram->from == 2) {
176aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		ram_mask(fuc, 0x1373f4, 0x00000000, 0x00001100);
177aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		ram_mask(fuc, 0x1373f4, 0x00000000, 0x00000010);
178aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	} else {
179aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		ram_mask(fuc, 0x1373f4, 0x00000000, 0x00010010);
180aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	}
181aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs
182aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	ram_mask(fuc, 0x1373f4, 0x00000003, 0x00000000);
183aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	ram_mask(fuc, 0x1373f4, 0x00000010, 0x00000000);
184aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs
185aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	/* (re)program refpll, if required */
186aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	if ((ram_rd32(fuc, 0x132024) & 0xffffffff) != rcoef ||
187aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	    (ram_rd32(fuc, 0x132034) & 0x0000ffff) != runk1) {
188aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		ram_mask(fuc, 0x132000, 0x00000001, 0x00000000);
189aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		ram_mask(fuc, 0x132020, 0x00000001, 0x00000000);
190aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		ram_wr32(fuc, 0x137320, 0x00000000);
191aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		ram_mask(fuc, 0x132030, 0xffff0000, runk0);
192aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		ram_mask(fuc, 0x132034, 0x0000ffff, runk1);
193aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		ram_wr32(fuc, 0x132024, rcoef);
194aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		ram_mask(fuc, 0x132028, 0x00080000, 0x00080000);
195aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		ram_mask(fuc, 0x132020, 0x00000001, 0x00000001);
196aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		ram_wait(fuc, 0x137390, 0x00020000, 0x00020000, 64000);
197aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		ram_mask(fuc, 0x132028, 0x00080000, 0x00000000);
198aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	}
199aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs
200aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	/* (re)program mempll, if required */
201aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	if (ram->mode == 2) {
202aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		ram_mask(fuc, 0x1373f4, 0x00010000, 0x00000000);
203797a816221655d7204c6a5536d1400c022b01939Ben Skeggs		ram_mask(fuc, 0x132000, 0x80000000, 0x80000000);
204aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		ram_mask(fuc, 0x132000, 0x00000001, 0x00000000);
205aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		ram_mask(fuc, 0x132004, 0x103fffff, mcoef);
206aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		ram_mask(fuc, 0x132000, 0x00000001, 0x00000001);
207aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		ram_wait(fuc, 0x137390, 0x00000002, 0x00000002, 64000);
208aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		ram_mask(fuc, 0x1373f4, 0x00000000, 0x00001100);
209aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	} else {
210aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		ram_mask(fuc, 0x1373f4, 0x00000000, 0x00010100);
211aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	}
212aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs
213aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	ram_mask(fuc, 0x1373f4, 0x00000000, 0x00000010);
214aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs}
215aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs
216aae95ca708140307813e49af6d0d4a7205509129Ben Skeggsstatic void
217b655f2bb77b49a3dc69d13b3daa392ea641bec86Ben Skeggsr1373f4_fini(struct nve0_ramfuc *fuc)
218aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs{
219aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	struct nve0_ram *ram = container_of(fuc, typeof(*ram), fuc);
220b655f2bb77b49a3dc69d13b3daa392ea641bec86Ben Skeggs	struct nouveau_ram_data *next = ram->base.next;
221b655f2bb77b49a3dc69d13b3daa392ea641bec86Ben Skeggs	u8 v0 = next->bios.ramcfg_11_03_c0;
222b655f2bb77b49a3dc69d13b3daa392ea641bec86Ben Skeggs	u8 v1 = next->bios.ramcfg_11_03_30;
223aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	u32 tmp;
224aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs
225aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	tmp = ram_rd32(fuc, 0x1373ec) & ~0x00030000;
226aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	ram_wr32(fuc, 0x1373ec, tmp | (v1 << 16));
227aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	ram_mask(fuc, 0x1373f0, (~ram->mode & 3), 0x00000000);
228aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	if (ram->mode == 2) {
229aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		ram_mask(fuc, 0x1373f4, 0x00000003, 0x000000002);
230aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		ram_mask(fuc, 0x1373f4, 0x00001100, 0x000000000);
231aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	} else {
232aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		ram_mask(fuc, 0x1373f4, 0x00000003, 0x000000001);
233aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		ram_mask(fuc, 0x1373f4, 0x00010000, 0x000000000);
234aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	}
235aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	ram_mask(fuc, 0x10f800, 0x00000030, (v0 ^ v1) << 4);
236aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs}
237aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs
238d394fb12eca4cb9f42f922d7ae2bc8d7e1ed9272Ben Skeggsstatic void
239d394fb12eca4cb9f42f922d7ae2bc8d7e1ed9272Ben Skeggsnve0_ram_nuts(struct nve0_ram *ram, struct ramfuc_reg *reg,
240d394fb12eca4cb9f42f922d7ae2bc8d7e1ed9272Ben Skeggs	      u32 _mask, u32 _data, u32 _copy)
241d394fb12eca4cb9f42f922d7ae2bc8d7e1ed9272Ben Skeggs{
242d394fb12eca4cb9f42f922d7ae2bc8d7e1ed9272Ben Skeggs	struct nve0_fb_priv *priv = (void *)nouveau_fb(ram);
243d394fb12eca4cb9f42f922d7ae2bc8d7e1ed9272Ben Skeggs	struct ramfuc *fuc = &ram->fuc.base;
244d394fb12eca4cb9f42f922d7ae2bc8d7e1ed9272Ben Skeggs	u32 addr = 0x110000 + (reg->addr[0] & 0xfff);
245d394fb12eca4cb9f42f922d7ae2bc8d7e1ed9272Ben Skeggs	u32 mask = _mask | _copy;
246d394fb12eca4cb9f42f922d7ae2bc8d7e1ed9272Ben Skeggs	u32 data = (_data & _mask) | (reg->data & _copy);
247d394fb12eca4cb9f42f922d7ae2bc8d7e1ed9272Ben Skeggs	u32 i;
248d394fb12eca4cb9f42f922d7ae2bc8d7e1ed9272Ben Skeggs
249d394fb12eca4cb9f42f922d7ae2bc8d7e1ed9272Ben Skeggs	for (i = 0; i < 16; i++, addr += 0x1000) {
250d394fb12eca4cb9f42f922d7ae2bc8d7e1ed9272Ben Skeggs		if (ram->pnuts & (1 << i)) {
251d394fb12eca4cb9f42f922d7ae2bc8d7e1ed9272Ben Skeggs			u32 prev = nv_rd32(priv, addr);
252d394fb12eca4cb9f42f922d7ae2bc8d7e1ed9272Ben Skeggs			u32 next = (prev & ~mask) | data;
253d394fb12eca4cb9f42f922d7ae2bc8d7e1ed9272Ben Skeggs			nouveau_memx_wr32(fuc->memx, addr, next);
254d394fb12eca4cb9f42f922d7ae2bc8d7e1ed9272Ben Skeggs		}
255d394fb12eca4cb9f42f922d7ae2bc8d7e1ed9272Ben Skeggs	}
256d394fb12eca4cb9f42f922d7ae2bc8d7e1ed9272Ben Skeggs}
257d394fb12eca4cb9f42f922d7ae2bc8d7e1ed9272Ben Skeggs#define ram_nuts(s,r,m,d,c)                                                    \
258d394fb12eca4cb9f42f922d7ae2bc8d7e1ed9272Ben Skeggs	nve0_ram_nuts((s), &(s)->fuc.r_##r, (m), (d), (c))
259d394fb12eca4cb9f42f922d7ae2bc8d7e1ed9272Ben Skeggs
260aae95ca708140307813e49af6d0d4a7205509129Ben Skeggsstatic int
261aae95ca708140307813e49af6d0d4a7205509129Ben Skeggsnve0_ram_calc_gddr5(struct nouveau_fb *pfb, u32 freq)
262aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs{
263aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	struct nve0_ram *ram = (void *)pfb->ram;
264aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	struct nve0_ramfuc *fuc = &ram->fuc;
265b655f2bb77b49a3dc69d13b3daa392ea641bec86Ben Skeggs	struct nouveau_ram_data *next = ram->base.next;
26686899b39b53bfcfb0c01151c52d4b1272306fc92Ben Skeggs	int vc = !next->bios.ramcfg_11_02_08;
26786899b39b53bfcfb0c01151c52d4b1272306fc92Ben Skeggs	int mv = !next->bios.ramcfg_11_02_04;
268b655f2bb77b49a3dc69d13b3daa392ea641bec86Ben Skeggs	u32 mask, data;
269aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs
270aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	ram_mask(fuc, 0x10f808, 0x40000000, 0x40000000);
271aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	ram_wr32(fuc, 0x62c000, 0x0f0f0000);
272aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs
273aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	/* MR1: turn termination on early, for some reason.. */
274d394fb12eca4cb9f42f922d7ae2bc8d7e1ed9272Ben Skeggs	if ((ram->base.mr[1] & 0x03c) != 0x030) {
275aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		ram_mask(fuc, mr[1], 0x03c, ram->base.mr[1] & 0x03c);
276d394fb12eca4cb9f42f922d7ae2bc8d7e1ed9272Ben Skeggs		ram_nuts(ram, mr[1], 0x03c, ram->base.mr1_nuts & 0x03c, 0x000);
277d394fb12eca4cb9f42f922d7ae2bc8d7e1ed9272Ben Skeggs	}
278aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs
279aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	if (vc == 1 && ram_have(fuc, gpio2E)) {
280aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		u32 temp  = ram_mask(fuc, gpio2E, 0x3000, fuc->r_func2E[1]);
281aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		if (temp != ram_rd32(fuc, gpio2E)) {
282aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs			ram_wr32(fuc, gpiotrig, 1);
283aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs			ram_nsec(fuc, 20000);
284aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		}
285aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	}
286aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs
287aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	ram_mask(fuc, 0x10f200, 0x00000800, 0x00000000);
288aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs
28901891690e8e0d1230b8b3d96a42810b3ab8b38c1Ben Skeggs	nve0_ram_train(fuc, 0x01020000, 0x000c0000);
290aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs
291aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	ram_wr32(fuc, 0x10f210, 0x00000000); /* REFRESH_AUTO = 0 */
292aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	ram_nsec(fuc, 1000);
293aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	ram_wr32(fuc, 0x10f310, 0x00000001); /* REFRESH */
294aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	ram_nsec(fuc, 1000);
295aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs
296aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	ram_mask(fuc, 0x10f200, 0x80000000, 0x80000000);
297aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	ram_wr32(fuc, 0x10f314, 0x00000001); /* PRECHARGE */
298aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	ram_mask(fuc, 0x10f200, 0x80000000, 0x00000000);
299aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	ram_wr32(fuc, 0x10f090, 0x00000061);
300aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	ram_wr32(fuc, 0x10f090, 0xc000007f);
301aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	ram_nsec(fuc, 1000);
302aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs
303aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	ram_wr32(fuc, 0x10f698, 0x00000000);
304aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	ram_wr32(fuc, 0x10f69c, 0x00000000);
305aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs
306aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	/*XXX: there does appear to be some kind of condition here, simply
307aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	 *     modifying these bits in the vbios from the default pl0
308aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	 *     entries shows no change.  however, the data does appear to
309aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	 *     be correct and may be required for the transition back
310aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	 */
311aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	mask = 0x800f07e0;
312aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	data = 0x00030000;
313aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	if (ram_rd32(fuc, 0x10f978) & 0x00800000)
314aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		data |= 0x00040000;
315aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs
316aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	if (1) {
317aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		data |= 0x800807e0;
318b655f2bb77b49a3dc69d13b3daa392ea641bec86Ben Skeggs		switch (next->bios.ramcfg_11_03_c0) {
319b655f2bb77b49a3dc69d13b3daa392ea641bec86Ben Skeggs		case 3: data &= ~0x00000040; break;
320b655f2bb77b49a3dc69d13b3daa392ea641bec86Ben Skeggs		case 2: data &= ~0x00000100; break;
321b655f2bb77b49a3dc69d13b3daa392ea641bec86Ben Skeggs		case 1: data &= ~0x80000000; break;
322b655f2bb77b49a3dc69d13b3daa392ea641bec86Ben Skeggs		case 0: data &= ~0x00000400; break;
323aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		}
324aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs
325b655f2bb77b49a3dc69d13b3daa392ea641bec86Ben Skeggs		switch (next->bios.ramcfg_11_03_30) {
326b655f2bb77b49a3dc69d13b3daa392ea641bec86Ben Skeggs		case 3: data &= ~0x00000020; break;
327b655f2bb77b49a3dc69d13b3daa392ea641bec86Ben Skeggs		case 2: data &= ~0x00000080; break;
328b655f2bb77b49a3dc69d13b3daa392ea641bec86Ben Skeggs		case 1: data &= ~0x00080000; break;
329b655f2bb77b49a3dc69d13b3daa392ea641bec86Ben Skeggs		case 0: data &= ~0x00000200; break;
330aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		}
331aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	}
332aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs
333b655f2bb77b49a3dc69d13b3daa392ea641bec86Ben Skeggs	if (next->bios.ramcfg_11_02_80)
334aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		mask |= 0x03000000;
335b655f2bb77b49a3dc69d13b3daa392ea641bec86Ben Skeggs	if (next->bios.ramcfg_11_02_40)
336aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		mask |= 0x00002000;
337b655f2bb77b49a3dc69d13b3daa392ea641bec86Ben Skeggs	if (next->bios.ramcfg_11_07_10)
338aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		mask |= 0x00004000;
339b655f2bb77b49a3dc69d13b3daa392ea641bec86Ben Skeggs	if (next->bios.ramcfg_11_07_08)
340aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		mask |= 0x00000003;
341aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	else {
342aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		mask |= 0x34000000;
343aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		if (ram_rd32(fuc, 0x10f978) & 0x00800000)
344aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs			mask |= 0x40000000;
345aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	}
346aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	ram_mask(fuc, 0x10f824, mask, data);
347aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs
348aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	ram_mask(fuc, 0x132040, 0x00010000, 0x00000000);
349aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs
350aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	if (ram->from == 2 && ram->mode != 2) {
351aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		ram_mask(fuc, 0x10f808, 0x00080000, 0x00000000);
3527f39e597726774cb3fee71f4b605a5499f7c3a8aBen Skeggs		ram_mask(fuc, 0x10f200, 0x18008000, 0x00008000);
353aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		ram_mask(fuc, 0x10f800, 0x00000000, 0x00000004);
354aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		ram_mask(fuc, 0x10f830, 0x00008000, 0x01040010);
355aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		ram_mask(fuc, 0x10f830, 0x01000000, 0x00000000);
356aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		r1373f4_init(fuc);
357aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		ram_mask(fuc, 0x1373f0, 0x00000002, 0x00000001);
358b655f2bb77b49a3dc69d13b3daa392ea641bec86Ben Skeggs		r1373f4_fini(fuc);
359aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		ram_mask(fuc, 0x10f830, 0x00c00000, 0x00240001);
360aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	} else
361aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	if (ram->from != 2 && ram->mode != 2) {
362aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		r1373f4_init(fuc);
363b655f2bb77b49a3dc69d13b3daa392ea641bec86Ben Skeggs		r1373f4_fini(fuc);
364aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	}
365aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs
366aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	if (ram_have(fuc, gpioMV)) {
367aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		u32 temp  = ram_mask(fuc, gpioMV, 0x3000, fuc->r_funcMV[mv]);
368aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		if (temp != ram_rd32(fuc, gpioMV)) {
369aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs			ram_wr32(fuc, gpiotrig, 1);
370aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs			ram_nsec(fuc, 64000);
371aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		}
372aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	}
373aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs
37486899b39b53bfcfb0c01151c52d4b1272306fc92Ben Skeggs	if (next->bios.ramcfg_11_02_40 ||
37586899b39b53bfcfb0c01151c52d4b1272306fc92Ben Skeggs	    next->bios.ramcfg_11_07_10) {
376aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		ram_mask(fuc, 0x132040, 0x00010000, 0x00010000);
377aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		ram_nsec(fuc, 20000);
378aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	}
379aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs
380aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	if (ram->from != 2 && ram->mode == 2) {
3817f39e597726774cb3fee71f4b605a5499f7c3a8aBen Skeggs		if (0 /*XXX: Titan */)
3827f39e597726774cb3fee71f4b605a5499f7c3a8aBen Skeggs			ram_mask(fuc, 0x10f200, 0x18000000, 0x18000000);
383aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		ram_mask(fuc, 0x10f800, 0x00000004, 0x00000000);
384aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		ram_mask(fuc, 0x1373f0, 0x00000000, 0x00000002);
385aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		ram_mask(fuc, 0x10f830, 0x00800001, 0x00408010);
386aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		r1373f4_init(fuc);
387b655f2bb77b49a3dc69d13b3daa392ea641bec86Ben Skeggs		r1373f4_fini(fuc);
388aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		ram_mask(fuc, 0x10f808, 0x00000000, 0x00080000);
389aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		ram_mask(fuc, 0x10f200, 0x00808000, 0x00800000);
390aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	} else
391aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	if (ram->from == 2 && ram->mode == 2) {
392aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		ram_mask(fuc, 0x10f800, 0x00000004, 0x00000000);
393aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		r1373f4_init(fuc);
394b655f2bb77b49a3dc69d13b3daa392ea641bec86Ben Skeggs		r1373f4_fini(fuc);
395aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	}
396aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs
397aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	if (ram->mode != 2) /*XXX*/ {
398b655f2bb77b49a3dc69d13b3daa392ea641bec86Ben Skeggs		if (next->bios.ramcfg_11_07_40)
399aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs			ram_mask(fuc, 0x10f670, 0x80000000, 0x80000000);
400aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	}
401aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs
402b655f2bb77b49a3dc69d13b3daa392ea641bec86Ben Skeggs	ram_wr32(fuc, 0x10f65c, 0x00000011 * next->bios.rammap_11_11_0c);
403b655f2bb77b49a3dc69d13b3daa392ea641bec86Ben Skeggs	ram_wr32(fuc, 0x10f6b8, 0x01010101 * next->bios.ramcfg_11_09);
404b655f2bb77b49a3dc69d13b3daa392ea641bec86Ben Skeggs	ram_wr32(fuc, 0x10f6bc, 0x01010101 * next->bios.ramcfg_11_09);
405aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs
406a8ccbb7701d41a772d839acb3d81d7f9ac84c678Ben Skeggs	if (!next->bios.ramcfg_11_07_08 && !next->bios.ramcfg_11_07_04) {
407b655f2bb77b49a3dc69d13b3daa392ea641bec86Ben Skeggs		ram_wr32(fuc, 0x10f698, 0x01010101 * next->bios.ramcfg_11_04);
408b655f2bb77b49a3dc69d13b3daa392ea641bec86Ben Skeggs		ram_wr32(fuc, 0x10f69c, 0x01010101 * next->bios.ramcfg_11_04);
409a8ccbb7701d41a772d839acb3d81d7f9ac84c678Ben Skeggs	} else
410a8ccbb7701d41a772d839acb3d81d7f9ac84c678Ben Skeggs	if (!next->bios.ramcfg_11_07_08) {
411a8ccbb7701d41a772d839acb3d81d7f9ac84c678Ben Skeggs		ram_wr32(fuc, 0x10f698, 0x00000000);
412a8ccbb7701d41a772d839acb3d81d7f9ac84c678Ben Skeggs		ram_wr32(fuc, 0x10f69c, 0x00000000);
413aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	}
414aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs
415aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	if (ram->mode != 2) {
416b655f2bb77b49a3dc69d13b3daa392ea641bec86Ben Skeggs		u32 data = 0x01000100 * next->bios.ramcfg_11_04;
417b655f2bb77b49a3dc69d13b3daa392ea641bec86Ben Skeggs		ram_nuke(fuc, 0x10f694);
418b655f2bb77b49a3dc69d13b3daa392ea641bec86Ben Skeggs		ram_mask(fuc, 0x10f694, 0xff00ff00, data);
419aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	}
420aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs
42186899b39b53bfcfb0c01151c52d4b1272306fc92Ben Skeggs	if (ram->mode == 2 && next->bios.ramcfg_11_08_10)
422aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		data = 0x00000080;
423aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	else
424aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		data = 0x00000000;
425aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	ram_mask(fuc, 0x10f60c, 0x00000080, data);
426aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs
427aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	mask = 0x00070000;
428aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	data = 0x00000000;
42986899b39b53bfcfb0c01151c52d4b1272306fc92Ben Skeggs	if (!next->bios.ramcfg_11_02_80)
430aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		data |= 0x03000000;
43186899b39b53bfcfb0c01151c52d4b1272306fc92Ben Skeggs	if (!next->bios.ramcfg_11_02_40)
432aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		data |= 0x00002000;
43386899b39b53bfcfb0c01151c52d4b1272306fc92Ben Skeggs	if (!next->bios.ramcfg_11_07_10)
434aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		data |= 0x00004000;
43586899b39b53bfcfb0c01151c52d4b1272306fc92Ben Skeggs	if (!next->bios.ramcfg_11_07_08)
436aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		data |= 0x00000003;
437aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	else
438aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		data |= 0x74000000;
439aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	ram_mask(fuc, 0x10f824, mask, data);
440aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs
441b655f2bb77b49a3dc69d13b3daa392ea641bec86Ben Skeggs	if (next->bios.ramcfg_11_01_08)
442aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		data = 0x00000000;
443aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	else
444aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		data = 0x00001000;
445aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	ram_mask(fuc, 0x10f200, 0x00001000, data);
446aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs
447aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	if (ram_rd32(fuc, 0x10f670) & 0x80000000) {
448aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		ram_nsec(fuc, 10000);
449aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		ram_mask(fuc, 0x10f670, 0x80000000, 0x00000000);
450aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	}
451aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs
452b655f2bb77b49a3dc69d13b3daa392ea641bec86Ben Skeggs	if (next->bios.ramcfg_11_08_01)
453aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		data = 0x00100000;
454aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	else
455aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		data = 0x00000000;
456aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	ram_mask(fuc, 0x10f82c, 0x00100000, data);
457aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs
458aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	data = 0x00000000;
459b655f2bb77b49a3dc69d13b3daa392ea641bec86Ben Skeggs	if (next->bios.ramcfg_11_08_08)
460aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		data |= 0x00002000;
461b655f2bb77b49a3dc69d13b3daa392ea641bec86Ben Skeggs	if (next->bios.ramcfg_11_08_04)
462aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		data |= 0x00001000;
463b655f2bb77b49a3dc69d13b3daa392ea641bec86Ben Skeggs	if (next->bios.ramcfg_11_08_02)
464aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		data |= 0x00004000;
465aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	ram_mask(fuc, 0x10f830, 0x00007000, data);
466aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs
467aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	/* PFB timing */
468b655f2bb77b49a3dc69d13b3daa392ea641bec86Ben Skeggs	ram_mask(fuc, 0x10f248, 0xffffffff, next->bios.timing[10]);
469b655f2bb77b49a3dc69d13b3daa392ea641bec86Ben Skeggs	ram_mask(fuc, 0x10f290, 0xffffffff, next->bios.timing[0]);
470b655f2bb77b49a3dc69d13b3daa392ea641bec86Ben Skeggs	ram_mask(fuc, 0x10f294, 0xffffffff, next->bios.timing[1]);
471b655f2bb77b49a3dc69d13b3daa392ea641bec86Ben Skeggs	ram_mask(fuc, 0x10f298, 0xffffffff, next->bios.timing[2]);
472b655f2bb77b49a3dc69d13b3daa392ea641bec86Ben Skeggs	ram_mask(fuc, 0x10f29c, 0xffffffff, next->bios.timing[3]);
473b655f2bb77b49a3dc69d13b3daa392ea641bec86Ben Skeggs	ram_mask(fuc, 0x10f2a0, 0xffffffff, next->bios.timing[4]);
474b655f2bb77b49a3dc69d13b3daa392ea641bec86Ben Skeggs	ram_mask(fuc, 0x10f2a4, 0xffffffff, next->bios.timing[5]);
475b655f2bb77b49a3dc69d13b3daa392ea641bec86Ben Skeggs	ram_mask(fuc, 0x10f2a8, 0xffffffff, next->bios.timing[6]);
476b655f2bb77b49a3dc69d13b3daa392ea641bec86Ben Skeggs	ram_mask(fuc, 0x10f2ac, 0xffffffff, next->bios.timing[7]);
477b655f2bb77b49a3dc69d13b3daa392ea641bec86Ben Skeggs	ram_mask(fuc, 0x10f2cc, 0xffffffff, next->bios.timing[8]);
478b655f2bb77b49a3dc69d13b3daa392ea641bec86Ben Skeggs	ram_mask(fuc, 0x10f2e8, 0xffffffff, next->bios.timing[9]);
479aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs
480db6735cab2b0f12a824f04b1d8fb4da2ea978c8dBen Skeggs	data = mask = 0x00000000;
481b13d0e4a9323939c4051eda9e7d1623298bb2102Ben Skeggs	if (NOTE00(ramcfg_08_20)) {
482b13d0e4a9323939c4051eda9e7d1623298bb2102Ben Skeggs		if (next->bios.ramcfg_11_08_20)
483b13d0e4a9323939c4051eda9e7d1623298bb2102Ben Skeggs			data |= 0x01000000;
484b13d0e4a9323939c4051eda9e7d1623298bb2102Ben Skeggs		mask |= 0x01000000;
485b13d0e4a9323939c4051eda9e7d1623298bb2102Ben Skeggs	}
486b13d0e4a9323939c4051eda9e7d1623298bb2102Ben Skeggs	ram_mask(fuc, 0x10f200, mask, data);
487b13d0e4a9323939c4051eda9e7d1623298bb2102Ben Skeggs
488b13d0e4a9323939c4051eda9e7d1623298bb2102Ben Skeggs	data = mask = 0x00000000;
489db6735cab2b0f12a824f04b1d8fb4da2ea978c8dBen Skeggs	if (NOTE00(ramcfg_02_03 != 0)) {
49086899b39b53bfcfb0c01151c52d4b1272306fc92Ben Skeggs		data |= next->bios.ramcfg_11_02_03 << 8;
491db6735cab2b0f12a824f04b1d8fb4da2ea978c8dBen Skeggs		mask |= 0x00000300;
492db6735cab2b0f12a824f04b1d8fb4da2ea978c8dBen Skeggs	}
493db6735cab2b0f12a824f04b1d8fb4da2ea978c8dBen Skeggs	if (NOTE00(ramcfg_01_10)) {
494b655f2bb77b49a3dc69d13b3daa392ea641bec86Ben Skeggs		if (next->bios.ramcfg_11_01_10)
49509692e5b4efb1ed1d91b4e9e4c7a31b7dbe06f03Ben Skeggs			data |= 0x70000000;
496db6735cab2b0f12a824f04b1d8fb4da2ea978c8dBen Skeggs		mask |= 0x70000000;
497db6735cab2b0f12a824f04b1d8fb4da2ea978c8dBen Skeggs	}
498db6735cab2b0f12a824f04b1d8fb4da2ea978c8dBen Skeggs	ram_mask(fuc, 0x10f604, mask, data);
49909692e5b4efb1ed1d91b4e9e4c7a31b7dbe06f03Ben Skeggs
500db6735cab2b0f12a824f04b1d8fb4da2ea978c8dBen Skeggs	data = mask = 0x00000000;
501db6735cab2b0f12a824f04b1d8fb4da2ea978c8dBen Skeggs	if (NOTE00(timing_30_07 != 0)) {
50286899b39b53bfcfb0c01151c52d4b1272306fc92Ben Skeggs		data |= next->bios.timing_20_30_07 << 28;
503db6735cab2b0f12a824f04b1d8fb4da2ea978c8dBen Skeggs		mask |= 0x70000000;
504db6735cab2b0f12a824f04b1d8fb4da2ea978c8dBen Skeggs	}
505db6735cab2b0f12a824f04b1d8fb4da2ea978c8dBen Skeggs	if (NOTE00(ramcfg_01_01)) {
506b655f2bb77b49a3dc69d13b3daa392ea641bec86Ben Skeggs		if (next->bios.ramcfg_11_01_01)
50709692e5b4efb1ed1d91b4e9e4c7a31b7dbe06f03Ben Skeggs			data |= 0x00000100;
508db6735cab2b0f12a824f04b1d8fb4da2ea978c8dBen Skeggs		mask |= 0x00000100;
509db6735cab2b0f12a824f04b1d8fb4da2ea978c8dBen Skeggs	}
510db6735cab2b0f12a824f04b1d8fb4da2ea978c8dBen Skeggs	ram_mask(fuc, 0x10f614, mask, data);
51109692e5b4efb1ed1d91b4e9e4c7a31b7dbe06f03Ben Skeggs
512db6735cab2b0f12a824f04b1d8fb4da2ea978c8dBen Skeggs	data = mask = 0x00000000;
513db6735cab2b0f12a824f04b1d8fb4da2ea978c8dBen Skeggs	if (NOTE00(timing_30_07 != 0)) {
51486899b39b53bfcfb0c01151c52d4b1272306fc92Ben Skeggs		data |= next->bios.timing_20_30_07 << 28;
515db6735cab2b0f12a824f04b1d8fb4da2ea978c8dBen Skeggs		mask |= 0x70000000;
516db6735cab2b0f12a824f04b1d8fb4da2ea978c8dBen Skeggs	}
517db6735cab2b0f12a824f04b1d8fb4da2ea978c8dBen Skeggs	if (NOTE00(ramcfg_01_02)) {
518b655f2bb77b49a3dc69d13b3daa392ea641bec86Ben Skeggs		if (next->bios.ramcfg_11_01_02)
51909692e5b4efb1ed1d91b4e9e4c7a31b7dbe06f03Ben Skeggs			data |= 0x00000100;
520db6735cab2b0f12a824f04b1d8fb4da2ea978c8dBen Skeggs		mask |= 0x00000100;
52109692e5b4efb1ed1d91b4e9e4c7a31b7dbe06f03Ben Skeggs	}
522db6735cab2b0f12a824f04b1d8fb4da2ea978c8dBen Skeggs	ram_mask(fuc, 0x10f610, mask, data);
523aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs
524aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	mask = 0x33f00000;
525aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	data = 0x00000000;
52686899b39b53bfcfb0c01151c52d4b1272306fc92Ben Skeggs	if (!next->bios.ramcfg_11_01_04)
527aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		data |= 0x20200000;
52886899b39b53bfcfb0c01151c52d4b1272306fc92Ben Skeggs	if (!next->bios.ramcfg_11_07_80)
529aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		data |= 0x12800000;
530aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	/*XXX: see note above about there probably being some condition
531aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	 *     for the 10f824 stuff that uses ramcfg 3...
532aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	 */
53386899b39b53bfcfb0c01151c52d4b1272306fc92Ben Skeggs	if (next->bios.ramcfg_11_03_f0) {
534b655f2bb77b49a3dc69d13b3daa392ea641bec86Ben Skeggs		if (next->bios.rammap_11_08_0c) {
53586899b39b53bfcfb0c01151c52d4b1272306fc92Ben Skeggs			if (!next->bios.ramcfg_11_07_80)
536aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs				mask |= 0x00000020;
537aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs			else
538aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs				data |= 0x00000020;
539aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs			mask |= 0x00000004;
540aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		}
541aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	} else {
542aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		mask |= 0x40000020;
543aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		data |= 0x00000004;
544aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	}
545aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs
546aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	ram_mask(fuc, 0x10f808, mask, data);
547aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs
548b655f2bb77b49a3dc69d13b3daa392ea641bec86Ben Skeggs	ram_wr32(fuc, 0x10f870, 0x11111111 * next->bios.ramcfg_11_03_0f);
549aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs
550db6735cab2b0f12a824f04b1d8fb4da2ea978c8dBen Skeggs	data = mask = 0x00000000;
551db6735cab2b0f12a824f04b1d8fb4da2ea978c8dBen Skeggs	if (NOTE00(ramcfg_02_03 != 0)) {
552b655f2bb77b49a3dc69d13b3daa392ea641bec86Ben Skeggs		data |= next->bios.ramcfg_11_02_03;
553db6735cab2b0f12a824f04b1d8fb4da2ea978c8dBen Skeggs		mask |= 0x00000003;
554db6735cab2b0f12a824f04b1d8fb4da2ea978c8dBen Skeggs	}
555db6735cab2b0f12a824f04b1d8fb4da2ea978c8dBen Skeggs	if (NOTE00(ramcfg_01_10)) {
556b655f2bb77b49a3dc69d13b3daa392ea641bec86Ben Skeggs		if (next->bios.ramcfg_11_01_10)
557db6735cab2b0f12a824f04b1d8fb4da2ea978c8dBen Skeggs			data |= 0x00000004;
558db6735cab2b0f12a824f04b1d8fb4da2ea978c8dBen Skeggs		mask |= 0x00000004;
559db6735cab2b0f12a824f04b1d8fb4da2ea978c8dBen Skeggs	}
560db6735cab2b0f12a824f04b1d8fb4da2ea978c8dBen Skeggs
561db6735cab2b0f12a824f04b1d8fb4da2ea978c8dBen Skeggs	if ((ram_mask(fuc, 0x100770, mask, data) & mask & 4) != (data & 4)) {
562db6735cab2b0f12a824f04b1d8fb4da2ea978c8dBen Skeggs		ram_mask(fuc, 0x100750, 0x00000008, 0x00000008);
563aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		ram_wr32(fuc, 0x100710, 0x00000000);
564aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		ram_wait(fuc, 0x100710, 0x80000000, 0x80000000, 200000);
565aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	}
566aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs
56786899b39b53bfcfb0c01151c52d4b1272306fc92Ben Skeggs	data = next->bios.timing_20_30_07 << 8;
568b655f2bb77b49a3dc69d13b3daa392ea641bec86Ben Skeggs	if (next->bios.ramcfg_11_01_01)
569aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		data |= 0x80000000;
570aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	ram_mask(fuc, 0x100778, 0x00000700, data);
571aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs
572b655f2bb77b49a3dc69d13b3daa392ea641bec86Ben Skeggs	ram_mask(fuc, 0x10f250, 0x000003f0, next->bios.timing_20_2c_003f << 4);
573cb54dd2f8e88d39842c338ad0041d9d528dfd6eeBen Skeggs	data = (next->bios.timing[10] & 0x7f000000) >> 24;
574cb54dd2f8e88d39842c338ad0041d9d528dfd6eeBen Skeggs	if (data < next->bios.timing_20_2c_1fc0)
575cb54dd2f8e88d39842c338ad0041d9d528dfd6eeBen Skeggs		data = next->bios.timing_20_2c_1fc0;
576cb54dd2f8e88d39842c338ad0041d9d528dfd6eeBen Skeggs	ram_mask(fuc, 0x10f24c, 0x7f000000, data << 24);
577b655f2bb77b49a3dc69d13b3daa392ea641bec86Ben Skeggs	ram_mask(fuc, 0x10f224, 0x001f0000, next->bios.timing_20_30_f8 << 16);
578aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs
579b655f2bb77b49a3dc69d13b3daa392ea641bec86Ben Skeggs	ram_mask(fuc, 0x10fec4, 0x041e0f07, next->bios.timing_20_31_0800 << 26 |
580b655f2bb77b49a3dc69d13b3daa392ea641bec86Ben Skeggs					    next->bios.timing_20_31_0780 << 17 |
581b655f2bb77b49a3dc69d13b3daa392ea641bec86Ben Skeggs					    next->bios.timing_20_31_0078 << 8 |
582b655f2bb77b49a3dc69d13b3daa392ea641bec86Ben Skeggs					    next->bios.timing_20_31_0007);
583b655f2bb77b49a3dc69d13b3daa392ea641bec86Ben Skeggs	ram_mask(fuc, 0x10fec8, 0x00000027, next->bios.timing_20_31_8000 << 5 |
584b655f2bb77b49a3dc69d13b3daa392ea641bec86Ben Skeggs					    next->bios.timing_20_31_7000);
585aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs
586aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	ram_wr32(fuc, 0x10f090, 0x4000007e);
587f4aa2c6677be2f0046a7431f23d4c76baba5ecc8Ben Skeggs	ram_nsec(fuc, 2000);
588aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	ram_wr32(fuc, 0x10f314, 0x00000001); /* PRECHARGE */
589aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	ram_wr32(fuc, 0x10f310, 0x00000001); /* REFRESH */
590aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	ram_wr32(fuc, 0x10f210, 0x80000000); /* REFRESH_AUTO = 1 */
591aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs
59286899b39b53bfcfb0c01151c52d4b1272306fc92Ben Skeggs	if (next->bios.ramcfg_11_08_10 && (ram->mode == 2) /*XXX*/) {
593aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		u32 temp = ram_mask(fuc, 0x10f294, 0xff000000, 0x24000000);
59401891690e8e0d1230b8b3d96a42810b3ab8b38c1Ben Skeggs		nve0_ram_train(fuc, 0xbc0e0000, 0xa4010000); /*XXX*/
595aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		ram_nsec(fuc, 1000);
596aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		ram_wr32(fuc, 0x10f294, temp);
597aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	}
598aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs
599aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	ram_mask(fuc, mr[3], 0xfff, ram->base.mr[3]);
600aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	ram_wr32(fuc, mr[0], ram->base.mr[0]);
601aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	ram_mask(fuc, mr[8], 0xfff, ram->base.mr[8]);
602aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	ram_nsec(fuc, 1000);
603aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	ram_mask(fuc, mr[1], 0xfff, ram->base.mr[1]);
6042daaf5b0e4fbed1fa9524881272c9a956a0aaf78Ben Skeggs	ram_mask(fuc, mr[5], 0xfff, ram->base.mr[5] & ~0x004); /* LP3 later */
605aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	ram_mask(fuc, mr[6], 0xfff, ram->base.mr[6]);
606aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	ram_mask(fuc, mr[7], 0xfff, ram->base.mr[7]);
607aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs
608aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	if (vc == 0 && ram_have(fuc, gpio2E)) {
609aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		u32 temp  = ram_mask(fuc, gpio2E, 0x3000, fuc->r_func2E[0]);
610aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		if (temp != ram_rd32(fuc, gpio2E)) {
611aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs			ram_wr32(fuc, gpiotrig, 1);
612aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs			ram_nsec(fuc, 20000);
613aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		}
614aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	}
615aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs
616aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	ram_mask(fuc, 0x10f200, 0x80000000, 0x80000000);
617aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	ram_wr32(fuc, 0x10f318, 0x00000001); /* NOP? */
618aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	ram_mask(fuc, 0x10f200, 0x80000000, 0x00000000);
619aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	ram_nsec(fuc, 1000);
6207f39e597726774cb3fee71f4b605a5499f7c3a8aBen Skeggs	ram_nuts(ram, 0x10f200, 0x18808800, 0x00000000, 0x18808800);
621aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs
622aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	data  = ram_rd32(fuc, 0x10f978);
623aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	data &= ~0x00046144;
624aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	data |=  0x0000000b;
62586899b39b53bfcfb0c01151c52d4b1272306fc92Ben Skeggs	if (!next->bios.ramcfg_11_07_08) {
62686899b39b53bfcfb0c01151c52d4b1272306fc92Ben Skeggs		if (!next->bios.ramcfg_11_07_04)
627aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs			data |= 0x0000200c;
628aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		else
629aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs			data |= 0x00000000;
630aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	} else {
631aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		data |= 0x00040044;
632aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	}
633aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	ram_wr32(fuc, 0x10f978, data);
634aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs
635aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	if (ram->mode == 1) {
636aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		data = ram_rd32(fuc, 0x10f830) | 0x00000001;
637aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		ram_wr32(fuc, 0x10f830, data);
638aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	}
639aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs
64086899b39b53bfcfb0c01151c52d4b1272306fc92Ben Skeggs	if (!next->bios.ramcfg_11_07_08) {
641aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		data = 0x88020000;
64286899b39b53bfcfb0c01151c52d4b1272306fc92Ben Skeggs		if ( next->bios.ramcfg_11_07_04)
643aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs			data |= 0x10000000;
64486899b39b53bfcfb0c01151c52d4b1272306fc92Ben Skeggs		if (!next->bios.rammap_11_08_10)
645aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs			data |= 0x00080000;
646aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	} else {
647aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		data = 0xa40e0000;
648aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	}
649334565abfea84d424d7721d9c9f9ca1227d14bd8Ben Skeggs	nve0_ram_train(fuc, 0xbc0f0000, data);
650ea8b4a380d46795610d17afcdec1067b0ff5f1c3Ben Skeggs	if (1) /* XXX: not always? */
651ea8b4a380d46795610d17afcdec1067b0ff5f1c3Ben Skeggs		ram_nsec(fuc, 1000);
652aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs
653aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	if (ram->mode == 2) { /*XXX*/
654aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		ram_mask(fuc, 0x10f800, 0x00000004, 0x00000004);
655aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	}
656aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs
657ea8b4a380d46795610d17afcdec1067b0ff5f1c3Ben Skeggs	/* LP3 */
658ea8b4a380d46795610d17afcdec1067b0ff5f1c3Ben Skeggs	if (ram_mask(fuc, mr[5], 0x004, ram->base.mr[5]) != ram->base.mr[5])
659ea8b4a380d46795610d17afcdec1067b0ff5f1c3Ben Skeggs		ram_nsec(fuc, 1000);
660aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs
661aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	if (ram->mode != 2) {
662aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		ram_mask(fuc, 0x10f830, 0x01000000, 0x01000000);
663aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		ram_mask(fuc, 0x10f830, 0x01000000, 0x00000000);
664aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	}
665aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs
666b655f2bb77b49a3dc69d13b3daa392ea641bec86Ben Skeggs	if (next->bios.ramcfg_11_07_02)
66701891690e8e0d1230b8b3d96a42810b3ab8b38c1Ben Skeggs		nve0_ram_train(fuc, 0x80020000, 0x01000000);
668aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs
669aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	ram_wr32(fuc, 0x62c000, 0x0f0f0f00);
670aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs
671b655f2bb77b49a3dc69d13b3daa392ea641bec86Ben Skeggs	if (next->bios.rammap_11_08_01)
672aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		data = 0x00000800;
673aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	else
674aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		data = 0x00000000;
675aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	ram_mask(fuc, 0x10f200, 0x00000800, data);
6767f39e597726774cb3fee71f4b605a5499f7c3a8aBen Skeggs	ram_nuts(ram, 0x10f200, 0x18808800, data, 0x18808800);
677aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	return 0;
678aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs}
679aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs
680aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs/*******************************************************************************
681aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs * DDR3
682aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs ******************************************************************************/
683aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs
684aae95ca708140307813e49af6d0d4a7205509129Ben Skeggsstatic int
685aae95ca708140307813e49af6d0d4a7205509129Ben Skeggsnve0_ram_calc_sddr3(struct nouveau_fb *pfb, u32 freq)
686aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs{
687aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	struct nve0_ram *ram = (void *)pfb->ram;
688aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	struct nve0_ramfuc *fuc = &ram->fuc;
689aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	const u32 rcoef = ((  ram->P1 << 16) | (ram->N1 << 8) | ram->M1);
690aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	const u32 runk0 = ram->fN1 << 16;
691aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	const u32 runk1 = ram->fN1;
692b655f2bb77b49a3dc69d13b3daa392ea641bec86Ben Skeggs	struct nouveau_ram_data *next = ram->base.next;
69386899b39b53bfcfb0c01151c52d4b1272306fc92Ben Skeggs	int vc = !next->bios.ramcfg_11_02_08;
69486899b39b53bfcfb0c01151c52d4b1272306fc92Ben Skeggs	int mv = !next->bios.ramcfg_11_02_04;
695aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	u32 mask, data;
696aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs
697aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	ram_mask(fuc, 0x10f808, 0x40000000, 0x40000000);
698aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	ram_wr32(fuc, 0x62c000, 0x0f0f0000);
699aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs
700aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	if (vc == 1 && ram_have(fuc, gpio2E)) {
701aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		u32 temp  = ram_mask(fuc, gpio2E, 0x3000, fuc->r_func2E[1]);
702aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		if (temp != ram_rd32(fuc, gpio2E)) {
703aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs			ram_wr32(fuc, gpiotrig, 1);
704aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs			ram_nsec(fuc, 20000);
705aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		}
706aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	}
707aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs
708aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	ram_mask(fuc, 0x10f200, 0x00000800, 0x00000000);
70986899b39b53bfcfb0c01151c52d4b1272306fc92Ben Skeggs	if (next->bios.ramcfg_11_03_f0)
710aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		ram_mask(fuc, 0x10f808, 0x04000000, 0x04000000);
711aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs
712aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	ram_wr32(fuc, 0x10f314, 0x00000001); /* PRECHARGE */
713aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	ram_wr32(fuc, 0x10f210, 0x00000000); /* REFRESH_AUTO = 0 */
714aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	ram_wr32(fuc, 0x10f310, 0x00000001); /* REFRESH */
715aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	ram_mask(fuc, 0x10f200, 0x80000000, 0x80000000);
716aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	ram_wr32(fuc, 0x10f310, 0x00000001); /* REFRESH */
717aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	ram_mask(fuc, 0x10f200, 0x80000000, 0x00000000);
718aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	ram_nsec(fuc, 1000);
719aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs
720aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	ram_wr32(fuc, 0x10f090, 0x00000060);
721aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	ram_wr32(fuc, 0x10f090, 0xc000007e);
722aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs
723aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	/*XXX: there does appear to be some kind of condition here, simply
724aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	 *     modifying these bits in the vbios from the default pl0
725aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	 *     entries shows no change.  however, the data does appear to
726aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	 *     be correct and may be required for the transition back
727aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	 */
728aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	mask = 0x00010000;
729aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	data = 0x00010000;
730aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs
731aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	if (1) {
732aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		mask |= 0x800807e0;
733aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		data |= 0x800807e0;
734b655f2bb77b49a3dc69d13b3daa392ea641bec86Ben Skeggs		switch (next->bios.ramcfg_11_03_c0) {
735b655f2bb77b49a3dc69d13b3daa392ea641bec86Ben Skeggs		case 3: data &= ~0x00000040; break;
736b655f2bb77b49a3dc69d13b3daa392ea641bec86Ben Skeggs		case 2: data &= ~0x00000100; break;
737b655f2bb77b49a3dc69d13b3daa392ea641bec86Ben Skeggs		case 1: data &= ~0x80000000; break;
738b655f2bb77b49a3dc69d13b3daa392ea641bec86Ben Skeggs		case 0: data &= ~0x00000400; break;
739aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		}
740aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs
741b655f2bb77b49a3dc69d13b3daa392ea641bec86Ben Skeggs		switch (next->bios.ramcfg_11_03_30) {
742b655f2bb77b49a3dc69d13b3daa392ea641bec86Ben Skeggs		case 3: data &= ~0x00000020; break;
743b655f2bb77b49a3dc69d13b3daa392ea641bec86Ben Skeggs		case 2: data &= ~0x00000080; break;
744b655f2bb77b49a3dc69d13b3daa392ea641bec86Ben Skeggs		case 1: data &= ~0x00080000; break;
745b655f2bb77b49a3dc69d13b3daa392ea641bec86Ben Skeggs		case 0: data &= ~0x00000200; break;
746aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		}
747aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	}
748aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs
749b655f2bb77b49a3dc69d13b3daa392ea641bec86Ben Skeggs	if (next->bios.ramcfg_11_02_80)
750aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		mask |= 0x03000000;
751b655f2bb77b49a3dc69d13b3daa392ea641bec86Ben Skeggs	if (next->bios.ramcfg_11_02_40)
752aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		mask |= 0x00002000;
753b655f2bb77b49a3dc69d13b3daa392ea641bec86Ben Skeggs	if (next->bios.ramcfg_11_07_10)
754aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		mask |= 0x00004000;
755b655f2bb77b49a3dc69d13b3daa392ea641bec86Ben Skeggs	if (next->bios.ramcfg_11_07_08)
756aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		mask |= 0x00000003;
757aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	else
758aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		mask |= 0x14000000;
759aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	ram_mask(fuc, 0x10f824, mask, data);
760aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs
761aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	ram_mask(fuc, 0x132040, 0x00010000, 0x00000000);
762aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs
763aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	ram_mask(fuc, 0x1373f4, 0x00000000, 0x00010010);
764aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	data  = ram_rd32(fuc, 0x1373ec) & ~0x00030000;
76586899b39b53bfcfb0c01151c52d4b1272306fc92Ben Skeggs	data |= next->bios.ramcfg_11_03_30 << 16;
766aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	ram_wr32(fuc, 0x1373ec, data);
767aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	ram_mask(fuc, 0x1373f4, 0x00000003, 0x00000000);
768aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	ram_mask(fuc, 0x1373f4, 0x00000010, 0x00000000);
769aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs
770aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	/* (re)program refpll, if required */
771aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	if ((ram_rd32(fuc, 0x132024) & 0xffffffff) != rcoef ||
772aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	    (ram_rd32(fuc, 0x132034) & 0x0000ffff) != runk1) {
773aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		ram_mask(fuc, 0x132000, 0x00000001, 0x00000000);
774aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		ram_mask(fuc, 0x132020, 0x00000001, 0x00000000);
775aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		ram_wr32(fuc, 0x137320, 0x00000000);
776aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		ram_mask(fuc, 0x132030, 0xffff0000, runk0);
777aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		ram_mask(fuc, 0x132034, 0x0000ffff, runk1);
778aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		ram_wr32(fuc, 0x132024, rcoef);
779aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		ram_mask(fuc, 0x132028, 0x00080000, 0x00080000);
780aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		ram_mask(fuc, 0x132020, 0x00000001, 0x00000001);
781aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		ram_wait(fuc, 0x137390, 0x00020000, 0x00020000, 64000);
782aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		ram_mask(fuc, 0x132028, 0x00080000, 0x00000000);
783aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	}
784aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs
785aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	ram_mask(fuc, 0x1373f4, 0x00000010, 0x00000010);
786aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	ram_mask(fuc, 0x1373f4, 0x00000003, 0x00000001);
787aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	ram_mask(fuc, 0x1373f4, 0x00010000, 0x00000000);
788aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs
789aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	if (ram_have(fuc, gpioMV)) {
790aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		u32 temp  = ram_mask(fuc, gpioMV, 0x3000, fuc->r_funcMV[mv]);
791aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		if (temp != ram_rd32(fuc, gpioMV)) {
792aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs			ram_wr32(fuc, gpiotrig, 1);
793aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs			ram_nsec(fuc, 64000);
794aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		}
795aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	}
796aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs
79786899b39b53bfcfb0c01151c52d4b1272306fc92Ben Skeggs	if (next->bios.ramcfg_11_02_40 ||
79886899b39b53bfcfb0c01151c52d4b1272306fc92Ben Skeggs	    next->bios.ramcfg_11_07_10) {
799aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		ram_mask(fuc, 0x132040, 0x00010000, 0x00010000);
800aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		ram_nsec(fuc, 20000);
801aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	}
802aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs
803aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	if (ram->mode != 2) /*XXX*/ {
804b655f2bb77b49a3dc69d13b3daa392ea641bec86Ben Skeggs		if (next->bios.ramcfg_11_07_40)
805aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs			ram_mask(fuc, 0x10f670, 0x80000000, 0x80000000);
806aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	}
807aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs
808b655f2bb77b49a3dc69d13b3daa392ea641bec86Ben Skeggs	ram_wr32(fuc, 0x10f65c, 0x00000011 * next->bios.rammap_11_11_0c);
809b655f2bb77b49a3dc69d13b3daa392ea641bec86Ben Skeggs	ram_wr32(fuc, 0x10f6b8, 0x01010101 * next->bios.ramcfg_11_09);
810b655f2bb77b49a3dc69d13b3daa392ea641bec86Ben Skeggs	ram_wr32(fuc, 0x10f6bc, 0x01010101 * next->bios.ramcfg_11_09);
811aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs
812aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	mask = 0x00010000;
813aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	data = 0x00000000;
81486899b39b53bfcfb0c01151c52d4b1272306fc92Ben Skeggs	if (!next->bios.ramcfg_11_02_80)
815aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		data |= 0x03000000;
81686899b39b53bfcfb0c01151c52d4b1272306fc92Ben Skeggs	if (!next->bios.ramcfg_11_02_40)
817aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		data |= 0x00002000;
81886899b39b53bfcfb0c01151c52d4b1272306fc92Ben Skeggs	if (!next->bios.ramcfg_11_07_10)
819aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		data |= 0x00004000;
82086899b39b53bfcfb0c01151c52d4b1272306fc92Ben Skeggs	if (!next->bios.ramcfg_11_07_08)
821aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		data |= 0x00000003;
822aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	else
823aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		data |= 0x14000000;
824aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	ram_mask(fuc, 0x10f824, mask, data);
825aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	ram_nsec(fuc, 1000);
826aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs
827b655f2bb77b49a3dc69d13b3daa392ea641bec86Ben Skeggs	if (next->bios.ramcfg_11_08_01)
828aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		data = 0x00100000;
829aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	else
830aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		data = 0x00000000;
831aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	ram_mask(fuc, 0x10f82c, 0x00100000, data);
832aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs
833aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	/* PFB timing */
834b655f2bb77b49a3dc69d13b3daa392ea641bec86Ben Skeggs	ram_mask(fuc, 0x10f248, 0xffffffff, next->bios.timing[10]);
835b655f2bb77b49a3dc69d13b3daa392ea641bec86Ben Skeggs	ram_mask(fuc, 0x10f290, 0xffffffff, next->bios.timing[0]);
836b655f2bb77b49a3dc69d13b3daa392ea641bec86Ben Skeggs	ram_mask(fuc, 0x10f294, 0xffffffff, next->bios.timing[1]);
837b655f2bb77b49a3dc69d13b3daa392ea641bec86Ben Skeggs	ram_mask(fuc, 0x10f298, 0xffffffff, next->bios.timing[2]);
838b655f2bb77b49a3dc69d13b3daa392ea641bec86Ben Skeggs	ram_mask(fuc, 0x10f29c, 0xffffffff, next->bios.timing[3]);
839b655f2bb77b49a3dc69d13b3daa392ea641bec86Ben Skeggs	ram_mask(fuc, 0x10f2a0, 0xffffffff, next->bios.timing[4]);
840b655f2bb77b49a3dc69d13b3daa392ea641bec86Ben Skeggs	ram_mask(fuc, 0x10f2a4, 0xffffffff, next->bios.timing[5]);
841b655f2bb77b49a3dc69d13b3daa392ea641bec86Ben Skeggs	ram_mask(fuc, 0x10f2a8, 0xffffffff, next->bios.timing[6]);
842b655f2bb77b49a3dc69d13b3daa392ea641bec86Ben Skeggs	ram_mask(fuc, 0x10f2ac, 0xffffffff, next->bios.timing[7]);
843b655f2bb77b49a3dc69d13b3daa392ea641bec86Ben Skeggs	ram_mask(fuc, 0x10f2cc, 0xffffffff, next->bios.timing[8]);
844b655f2bb77b49a3dc69d13b3daa392ea641bec86Ben Skeggs	ram_mask(fuc, 0x10f2e8, 0xffffffff, next->bios.timing[9]);
845aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs
846aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	mask = 0x33f00000;
847aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	data = 0x00000000;
84886899b39b53bfcfb0c01151c52d4b1272306fc92Ben Skeggs	if (!next->bios.ramcfg_11_01_04)
849aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		data |= 0x20200000;
85086899b39b53bfcfb0c01151c52d4b1272306fc92Ben Skeggs	if (!next->bios.ramcfg_11_07_80)
851aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		data |= 0x12800000;
852aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	/*XXX: see note above about there probably being some condition
853aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	 *     for the 10f824 stuff that uses ramcfg 3...
854aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	 */
85586899b39b53bfcfb0c01151c52d4b1272306fc92Ben Skeggs	if (next->bios.ramcfg_11_03_f0) {
856b655f2bb77b49a3dc69d13b3daa392ea641bec86Ben Skeggs		if (next->bios.rammap_11_08_0c) {
85786899b39b53bfcfb0c01151c52d4b1272306fc92Ben Skeggs			if (!next->bios.ramcfg_11_07_80)
858aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs				mask |= 0x00000020;
859aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs			else
860aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs				data |= 0x00000020;
861aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs			mask |= 0x08000004;
862aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		}
863aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		data |= 0x04000000;
864aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	} else {
865aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		mask |= 0x44000020;
866aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		data |= 0x08000004;
867aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	}
868aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs
869aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	ram_mask(fuc, 0x10f808, mask, data);
870aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs
871b655f2bb77b49a3dc69d13b3daa392ea641bec86Ben Skeggs	ram_wr32(fuc, 0x10f870, 0x11111111 * next->bios.ramcfg_11_03_0f);
872aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs
873b655f2bb77b49a3dc69d13b3daa392ea641bec86Ben Skeggs	ram_mask(fuc, 0x10f250, 0x000003f0, next->bios.timing_20_2c_003f << 4);
874aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs
875b655f2bb77b49a3dc69d13b3daa392ea641bec86Ben Skeggs	data = (next->bios.timing[10] & 0x7f000000) >> 24;
876cb54dd2f8e88d39842c338ad0041d9d528dfd6eeBen Skeggs	if (data < next->bios.timing_20_2c_1fc0)
877b655f2bb77b49a3dc69d13b3daa392ea641bec86Ben Skeggs		data = next->bios.timing_20_2c_1fc0;
878aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	ram_mask(fuc, 0x10f24c, 0x7f000000, data << 24);
879aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs
88086899b39b53bfcfb0c01151c52d4b1272306fc92Ben Skeggs	ram_mask(fuc, 0x10f224, 0x001f0000, next->bios.timing_20_30_f8 << 16);
881aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs
882aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	ram_wr32(fuc, 0x10f090, 0x4000007f);
883aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	ram_nsec(fuc, 1000);
884aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs
885aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	ram_wr32(fuc, 0x10f314, 0x00000001); /* PRECHARGE */
886aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	ram_wr32(fuc, 0x10f310, 0x00000001); /* REFRESH */
887aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	ram_wr32(fuc, 0x10f210, 0x80000000); /* REFRESH_AUTO = 1 */
888aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	ram_nsec(fuc, 1000);
889aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs
890aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	ram_nuke(fuc, mr[0]);
891aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	ram_mask(fuc, mr[0], 0x100, 0x100);
892aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	ram_mask(fuc, mr[0], 0x100, 0x000);
893aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs
894aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	ram_mask(fuc, mr[2], 0xfff, ram->base.mr[2]);
895aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	ram_wr32(fuc, mr[0], ram->base.mr[0]);
896aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	ram_nsec(fuc, 1000);
897aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs
898aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	ram_nuke(fuc, mr[0]);
899aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	ram_mask(fuc, mr[0], 0x100, 0x100);
900aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	ram_mask(fuc, mr[0], 0x100, 0x000);
901aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs
902aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	if (vc == 0 && ram_have(fuc, gpio2E)) {
903aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		u32 temp  = ram_mask(fuc, gpio2E, 0x3000, fuc->r_func2E[0]);
904aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		if (temp != ram_rd32(fuc, gpio2E)) {
905aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs			ram_wr32(fuc, gpiotrig, 1);
906aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs			ram_nsec(fuc, 20000);
907aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		}
908aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	}
909aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs
910aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	if (ram->mode != 2) {
911aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		ram_mask(fuc, 0x10f830, 0x01000000, 0x01000000);
912aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		ram_mask(fuc, 0x10f830, 0x01000000, 0x00000000);
913aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	}
914aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs
915aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	ram_mask(fuc, 0x10f200, 0x80000000, 0x80000000);
916aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	ram_wr32(fuc, 0x10f318, 0x00000001); /* NOP? */
917aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	ram_mask(fuc, 0x10f200, 0x80000000, 0x00000000);
918aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	ram_nsec(fuc, 1000);
919aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs
920aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	ram_wr32(fuc, 0x62c000, 0x0f0f0f00);
921aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs
922b655f2bb77b49a3dc69d13b3daa392ea641bec86Ben Skeggs	if (next->bios.rammap_11_08_01)
923aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		data = 0x00000800;
924aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	else
925aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		data = 0x00000000;
926aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	ram_mask(fuc, 0x10f200, 0x00000800, data);
927aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	return 0;
928aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs}
929aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs
930aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs/*******************************************************************************
931aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs * main hooks
932aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs ******************************************************************************/
933aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs
934aae95ca708140307813e49af6d0d4a7205509129Ben Skeggsstatic int
93546bf1c389f7fb4f3d1bba1543088d66523670cacBen Skeggsnve0_ram_calc_data(struct nouveau_fb *pfb, u32 freq,
93646bf1c389f7fb4f3d1bba1543088d66523670cacBen Skeggs		   struct nouveau_ram_data *data)
937aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs{
938aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	struct nouveau_bios *bios = nouveau_bios(pfb);
939aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	struct nve0_ram *ram = (void *)pfb->ram;
94046bf1c389f7fb4f3d1bba1543088d66523670cacBen Skeggs	u8 strap, cnt, len;
941aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs
942aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	/* lookup memory config data relevant to the target frequency */
943b655f2bb77b49a3dc69d13b3daa392ea641bec86Ben Skeggs	ram->base.rammap.data = nvbios_rammapEp(bios, freq / 1000,
944b655f2bb77b49a3dc69d13b3daa392ea641bec86Ben Skeggs					       &ram->base.rammap.version,
945b655f2bb77b49a3dc69d13b3daa392ea641bec86Ben Skeggs					       &ram->base.rammap.size,
94646bf1c389f7fb4f3d1bba1543088d66523670cacBen Skeggs					       &cnt, &len, &data->bios);
947aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	if (!ram->base.rammap.data || ram->base.rammap.version != 0x11 ||
948aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	     ram->base.rammap.size < 0x09) {
949aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		nv_error(pfb, "invalid/missing rammap entry\n");
950aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		return -EINVAL;
951aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	}
952aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs
953aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	/* locate specific data set for the attached memory */
9540a8649f1c607d444b658061151ae5cdf648adcf2Ben Skeggs	strap = nvbios_ramcfg_index(nv_subdev(pfb));
955b655f2bb77b49a3dc69d13b3daa392ea641bec86Ben Skeggs	ram->base.ramcfg.data = nvbios_rammapSp(bios, ram->base.rammap.data,
956b655f2bb77b49a3dc69d13b3daa392ea641bec86Ben Skeggs						ram->base.rammap.version,
9570a8649f1c607d444b658061151ae5cdf648adcf2Ben Skeggs						ram->base.rammap.size,
9580a8649f1c607d444b658061151ae5cdf648adcf2Ben Skeggs						cnt, len, strap,
959b655f2bb77b49a3dc69d13b3daa392ea641bec86Ben Skeggs						&ram->base.ramcfg.version,
960b655f2bb77b49a3dc69d13b3daa392ea641bec86Ben Skeggs						&ram->base.ramcfg.size,
96146bf1c389f7fb4f3d1bba1543088d66523670cacBen Skeggs						&data->bios);
962aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	if (!ram->base.ramcfg.data || ram->base.ramcfg.version != 0x11 ||
963aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	     ram->base.ramcfg.size < 0x08) {
964aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		nv_error(pfb, "invalid/missing ramcfg entry\n");
965aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		return -EINVAL;
966aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	}
967aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs
968aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	/* lookup memory timings, if bios says they're present */
969aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	strap = nv_ro08(bios, ram->base.ramcfg.data + 0x00);
970aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	if (strap != 0xff) {
971aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		ram->base.timing.data =
972b655f2bb77b49a3dc69d13b3daa392ea641bec86Ben Skeggs			nvbios_timingEp(bios, strap, &ram->base.timing.version,
973b655f2bb77b49a3dc69d13b3daa392ea641bec86Ben Skeggs				       &ram->base.timing.size, &cnt, &len,
97446bf1c389f7fb4f3d1bba1543088d66523670cacBen Skeggs				       &data->bios);
975aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		if (!ram->base.timing.data ||
976aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		     ram->base.timing.version != 0x20 ||
977aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		     ram->base.timing.size < 0x33) {
978aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs			nv_error(pfb, "invalid/missing timing entry\n");
979aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs			return -EINVAL;
980aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		}
981aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	} else {
982aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		ram->base.timing.data = 0;
983aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	}
984aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs
98546bf1c389f7fb4f3d1bba1543088d66523670cacBen Skeggs	data->freq = freq;
98646bf1c389f7fb4f3d1bba1543088d66523670cacBen Skeggs	return 0;
98746bf1c389f7fb4f3d1bba1543088d66523670cacBen Skeggs}
98846bf1c389f7fb4f3d1bba1543088d66523670cacBen Skeggs
98946bf1c389f7fb4f3d1bba1543088d66523670cacBen Skeggsstatic int
99046bf1c389f7fb4f3d1bba1543088d66523670cacBen Skeggsnve0_ram_calc_xits(struct nouveau_fb *pfb, struct nouveau_ram_data *next)
99146bf1c389f7fb4f3d1bba1543088d66523670cacBen Skeggs{
99246bf1c389f7fb4f3d1bba1543088d66523670cacBen Skeggs	struct nve0_ram *ram = (void *)pfb->ram;
99346bf1c389f7fb4f3d1bba1543088d66523670cacBen Skeggs	struct nve0_ramfuc *fuc = &ram->fuc;
99446bf1c389f7fb4f3d1bba1543088d66523670cacBen Skeggs	int refclk, i;
99546bf1c389f7fb4f3d1bba1543088d66523670cacBen Skeggs	int ret;
996b655f2bb77b49a3dc69d13b3daa392ea641bec86Ben Skeggs
997aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	ret = ram_init(fuc, pfb);
998aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	if (ret)
999aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		return ret;
1000aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs
1001d93e996aed6e48c87dc5703a21b0e9368d4cc1f9Roy Spliet	ram_fb_disable(fuc);
1002d93e996aed6e48c87dc5703a21b0e9368d4cc1f9Roy Spliet
100346bf1c389f7fb4f3d1bba1543088d66523670cacBen Skeggs	ram->mode = (next->freq > fuc->refpll.vco1.max_freq) ? 2 : 1;
1004aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	ram->from = ram_rd32(fuc, 0x1373f4) & 0x0000000f;
1005aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs
1006aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	/* XXX: this is *not* what nvidia do.  on fermi nvidia generally
1007aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	 * select, based on some unknown condition, one of the two possible
1008aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	 * reference frequencies listed in the vbios table for mempll and
1009aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	 * program refpll to that frequency.
1010aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	 *
1011aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	 * so far, i've seen very weird values being chosen by nvidia on
1012aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	 * kepler boards, no idea how/why they're chosen.
1013aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	 */
101446bf1c389f7fb4f3d1bba1543088d66523670cacBen Skeggs	refclk = next->freq;
1015aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	if (ram->mode == 2)
1016aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		refclk = fuc->mempll.refclk;
1017aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs
1018aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	/* calculate refpll coefficients */
1019aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	ret = nva3_pll_calc(nv_subdev(pfb), &fuc->refpll, refclk, &ram->N1,
1020aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs			   &ram->fN1, &ram->M1, &ram->P1);
1021aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	fuc->mempll.refclk = ret;
1022aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	if (ret <= 0) {
1023aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		nv_error(pfb, "unable to calc refpll\n");
1024aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		return -EINVAL;
1025aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	}
1026aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs
1027aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	/* calculate mempll coefficients, if we're using it */
1028aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	if (ram->mode == 2) {
1029aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		/* post-divider doesn't work... the reg takes the values but
1030aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		 * appears to completely ignore it.  there *is* a bit at
1031aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		 * bit 28 that appears to divide the clock by 2 if set.
1032aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		 */
1033aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		fuc->mempll.min_p = 1;
1034aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		fuc->mempll.max_p = 2;
1035aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs
103646bf1c389f7fb4f3d1bba1543088d66523670cacBen Skeggs		ret = nva3_pll_calc(nv_subdev(pfb), &fuc->mempll, next->freq,
1037aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs				   &ram->N2, NULL, &ram->M2, &ram->P2);
1038aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		if (ret <= 0) {
1039aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs			nv_error(pfb, "unable to calc mempll\n");
1040aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs			return -EINVAL;
1041aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		}
1042aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	}
1043aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs
1044aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	for (i = 0; i < ARRAY_SIZE(fuc->r_mr); i++) {
1045aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		if (ram_have(fuc, mr[i]))
1046aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs			ram->base.mr[i] = ram_rd32(fuc, mr[i]);
1047aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	}
104846bf1c389f7fb4f3d1bba1543088d66523670cacBen Skeggs	ram->base.freq = next->freq;
1049aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs
1050aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	switch (ram->base.type) {
1051aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	case NV_MEM_TYPE_DDR3:
1052aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		ret = nouveau_sddr3_calc(&ram->base);
1053aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		if (ret == 0)
105446bf1c389f7fb4f3d1bba1543088d66523670cacBen Skeggs			ret = nve0_ram_calc_sddr3(pfb, next->freq);
1055aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		break;
1056aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	case NV_MEM_TYPE_GDDR5:
1057d394fb12eca4cb9f42f922d7ae2bc8d7e1ed9272Ben Skeggs		ret = nouveau_gddr5_calc(&ram->base, ram->pnuts != 0);
1058aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		if (ret == 0)
105946bf1c389f7fb4f3d1bba1543088d66523670cacBen Skeggs			ret = nve0_ram_calc_gddr5(pfb, next->freq);
1060aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		break;
1061aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	default:
1062aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		ret = -ENOSYS;
1063aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		break;
1064aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	}
1065aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs
1066d93e996aed6e48c87dc5703a21b0e9368d4cc1f9Roy Spliet	if (!ret)
1067d93e996aed6e48c87dc5703a21b0e9368d4cc1f9Roy Spliet		ram_fb_enable(fuc);
1068d93e996aed6e48c87dc5703a21b0e9368d4cc1f9Roy Spliet
1069aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	return ret;
1070aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs}
1071aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs
1072aae95ca708140307813e49af6d0d4a7205509129Ben Skeggsstatic int
107346bf1c389f7fb4f3d1bba1543088d66523670cacBen Skeggsnve0_ram_calc(struct nouveau_fb *pfb, u32 freq)
107446bf1c389f7fb4f3d1bba1543088d66523670cacBen Skeggs{
107546bf1c389f7fb4f3d1bba1543088d66523670cacBen Skeggs	struct nouveau_clock *clk = nouveau_clock(pfb);
107646bf1c389f7fb4f3d1bba1543088d66523670cacBen Skeggs	struct nve0_ram *ram = (void *)pfb->ram;
107746bf1c389f7fb4f3d1bba1543088d66523670cacBen Skeggs	struct nouveau_ram_data *xits = &ram->base.xition;
107846bf1c389f7fb4f3d1bba1543088d66523670cacBen Skeggs	struct nouveau_ram_data *copy;
107946bf1c389f7fb4f3d1bba1543088d66523670cacBen Skeggs	int ret;
108046bf1c389f7fb4f3d1bba1543088d66523670cacBen Skeggs
108146bf1c389f7fb4f3d1bba1543088d66523670cacBen Skeggs	if (ram->base.next == NULL) {
108246bf1c389f7fb4f3d1bba1543088d66523670cacBen Skeggs		ret = nve0_ram_calc_data(pfb, clk->read(clk, nv_clk_src_mem),
108346bf1c389f7fb4f3d1bba1543088d66523670cacBen Skeggs					&ram->base.former);
108446bf1c389f7fb4f3d1bba1543088d66523670cacBen Skeggs		if (ret)
108546bf1c389f7fb4f3d1bba1543088d66523670cacBen Skeggs			return ret;
108646bf1c389f7fb4f3d1bba1543088d66523670cacBen Skeggs
108746bf1c389f7fb4f3d1bba1543088d66523670cacBen Skeggs		ret = nve0_ram_calc_data(pfb, freq, &ram->base.target);
108846bf1c389f7fb4f3d1bba1543088d66523670cacBen Skeggs		if (ret)
108946bf1c389f7fb4f3d1bba1543088d66523670cacBen Skeggs			return ret;
109046bf1c389f7fb4f3d1bba1543088d66523670cacBen Skeggs
109146bf1c389f7fb4f3d1bba1543088d66523670cacBen Skeggs		if (ram->base.target.freq < ram->base.former.freq) {
109246bf1c389f7fb4f3d1bba1543088d66523670cacBen Skeggs			*xits = ram->base.target;
109346bf1c389f7fb4f3d1bba1543088d66523670cacBen Skeggs			copy = &ram->base.former;
109446bf1c389f7fb4f3d1bba1543088d66523670cacBen Skeggs		} else {
109546bf1c389f7fb4f3d1bba1543088d66523670cacBen Skeggs			*xits = ram->base.former;
109646bf1c389f7fb4f3d1bba1543088d66523670cacBen Skeggs			copy = &ram->base.target;
109746bf1c389f7fb4f3d1bba1543088d66523670cacBen Skeggs		}
109846bf1c389f7fb4f3d1bba1543088d66523670cacBen Skeggs
109946bf1c389f7fb4f3d1bba1543088d66523670cacBen Skeggs		xits->bios.ramcfg_11_02_04 = copy->bios.ramcfg_11_02_04;
110046bf1c389f7fb4f3d1bba1543088d66523670cacBen Skeggs		xits->bios.ramcfg_11_02_03 = copy->bios.ramcfg_11_02_03;
110146bf1c389f7fb4f3d1bba1543088d66523670cacBen Skeggs		xits->bios.timing_20_30_07 = copy->bios.timing_20_30_07;
110246bf1c389f7fb4f3d1bba1543088d66523670cacBen Skeggs
110346bf1c389f7fb4f3d1bba1543088d66523670cacBen Skeggs		ram->base.next = &ram->base.target;
110446bf1c389f7fb4f3d1bba1543088d66523670cacBen Skeggs		if (memcmp(xits, &ram->base.former, sizeof(xits->bios)))
110546bf1c389f7fb4f3d1bba1543088d66523670cacBen Skeggs			ram->base.next = &ram->base.xition;
110646bf1c389f7fb4f3d1bba1543088d66523670cacBen Skeggs	} else {
110746bf1c389f7fb4f3d1bba1543088d66523670cacBen Skeggs		BUG_ON(ram->base.next != &ram->base.xition);
110846bf1c389f7fb4f3d1bba1543088d66523670cacBen Skeggs		ram->base.next = &ram->base.target;
110946bf1c389f7fb4f3d1bba1543088d66523670cacBen Skeggs	}
111046bf1c389f7fb4f3d1bba1543088d66523670cacBen Skeggs
111146bf1c389f7fb4f3d1bba1543088d66523670cacBen Skeggs	return nve0_ram_calc_xits(pfb, ram->base.next);
111246bf1c389f7fb4f3d1bba1543088d66523670cacBen Skeggs}
111346bf1c389f7fb4f3d1bba1543088d66523670cacBen Skeggs
111446bf1c389f7fb4f3d1bba1543088d66523670cacBen Skeggsstatic int
1115aae95ca708140307813e49af6d0d4a7205509129Ben Skeggsnve0_ram_prog(struct nouveau_fb *pfb)
1116aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs{
1117aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	struct nouveau_device *device = nv_device(pfb);
1118aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	struct nve0_ram *ram = (void *)pfb->ram;
1119aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	struct nve0_ramfuc *fuc = &ram->fuc;
1120d2ed15b2314fc4954b5d4bc36d3230f7e73865a2Ilia Mirkin	ram_exec(fuc, nouveau_boolopt(device->cfgopt, "NvMemExec", true));
112146bf1c389f7fb4f3d1bba1543088d66523670cacBen Skeggs	return (ram->base.next == &ram->base.xition);
1122aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs}
1123aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs
1124aae95ca708140307813e49af6d0d4a7205509129Ben Skeggsstatic void
1125aae95ca708140307813e49af6d0d4a7205509129Ben Skeggsnve0_ram_tidy(struct nouveau_fb *pfb)
1126aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs{
1127aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	struct nve0_ram *ram = (void *)pfb->ram;
1128aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	struct nve0_ramfuc *fuc = &ram->fuc;
112946bf1c389f7fb4f3d1bba1543088d66523670cacBen Skeggs	ram->base.next = NULL;
1130aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	ram_exec(fuc, false);
1131aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs}
1132aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs
1133267dcb66437df958a6c2a30b3582ef76ba3bbb88Ben Skeggsint
1134aae95ca708140307813e49af6d0d4a7205509129Ben Skeggsnve0_ram_init(struct nouveau_object *object)
1135aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs{
1136aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	struct nouveau_fb *pfb = (void *)object->parent;
1137aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	struct nve0_ram *ram   = (void *)object;
1138aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	struct nouveau_bios *bios = nouveau_bios(pfb);
1139aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	static const u8  train0[] = {
1140aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		0x00, 0xff, 0xff, 0x00, 0xff, 0x00,
1141aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		0x00, 0xff, 0xff, 0x00, 0xff, 0x00,
1142aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	};
1143aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	static const u32 train1[] = {
1144aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		0x00000000, 0xffffffff,
1145aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		0x55555555, 0xaaaaaaaa,
1146aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		0x33333333, 0xcccccccc,
1147aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		0xf0f0f0f0, 0x0f0f0f0f,
1148aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		0x00ff00ff, 0xff00ff00,
1149aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		0x0000ffff, 0xffff0000,
1150aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	};
1151aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	u8  ver, hdr, cnt, len, snr, ssz;
1152aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	u32 data, save;
1153aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	int ret, i;
1154aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs
1155aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	ret = nouveau_ram_init(&ram->base);
1156aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	if (ret)
1157aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		return ret;
1158aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs
1159aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	/* run a bunch of tables from rammap table.  there's actually
1160aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	 * individual pointers for each rammap entry too, but, nvidia
1161aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	 * seem to just run the last two entries' scripts early on in
1162aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	 * their init, and never again.. we'll just run 'em all once
1163aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	 * for now.
1164aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	 *
1165aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	 * i strongly suspect that each script is for a separate mode
1166aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	 * (likely selected by 0x10f65c's lower bits?), and the
1167aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	 * binary driver skips the one that's already been setup by
1168aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	 * the init tables.
1169aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	 */
1170b655f2bb77b49a3dc69d13b3daa392ea641bec86Ben Skeggs	data = nvbios_rammapTe(bios, &ver, &hdr, &cnt, &len, &snr, &ssz);
1171aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	if (!data || hdr < 0x15)
1172aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		return -EINVAL;
1173aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs
1174aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	cnt  = nv_ro08(bios, data + 0x14); /* guess at count */
1175aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	data = nv_ro32(bios, data + 0x10); /* guess u32... */
11764cc6c3fe391b9a5869e3ca08f3619963064f079cBen Skeggs	save = nv_rd32(pfb, 0x10f65c) & 0x000000f0;
11774cc6c3fe391b9a5869e3ca08f3619963064f079cBen Skeggs	for (i = 0; i < cnt; i++, data += 4) {
11784cc6c3fe391b9a5869e3ca08f3619963064f079cBen Skeggs		if (i != save >> 4) {
11794cc6c3fe391b9a5869e3ca08f3619963064f079cBen Skeggs			nv_mask(pfb, 0x10f65c, 0x000000f0, i << 4);
11804cc6c3fe391b9a5869e3ca08f3619963064f079cBen Skeggs			nvbios_exec(&(struct nvbios_init) {
11814cc6c3fe391b9a5869e3ca08f3619963064f079cBen Skeggs					.subdev = nv_subdev(pfb),
11824cc6c3fe391b9a5869e3ca08f3619963064f079cBen Skeggs					.bios = bios,
11834cc6c3fe391b9a5869e3ca08f3619963064f079cBen Skeggs					.offset = nv_ro32(bios, data),
11844cc6c3fe391b9a5869e3ca08f3619963064f079cBen Skeggs					.execute = 1,
11854cc6c3fe391b9a5869e3ca08f3619963064f079cBen Skeggs				    });
11864cc6c3fe391b9a5869e3ca08f3619963064f079cBen Skeggs		}
1187aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	}
11884cc6c3fe391b9a5869e3ca08f3619963064f079cBen Skeggs	nv_mask(pfb, 0x10f65c, 0x000000f0, save);
118973216231caf184439c5f6163d01145bdbdfcd00bBen Skeggs	nv_mask(pfb, 0x10f584, 0x11000000, 0x00000000);
1190aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs
1191aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	switch (ram->base.type) {
1192aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	case NV_MEM_TYPE_GDDR5:
1193aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		for (i = 0; i < 0x30; i++) {
1194aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs			nv_wr32(pfb, 0x10f968, 0x00000000 | (i << 8));
1195aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs			nv_wr32(pfb, 0x10f920, 0x00000000 | train0[i % 12]);
1196aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs			nv_wr32(pfb, 0x10f918,              train1[i % 12]);
1197aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs			nv_wr32(pfb, 0x10f920, 0x00000100 | train0[i % 12]);
1198aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs			nv_wr32(pfb, 0x10f918,              train1[i % 12]);
1199aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs
1200aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs			nv_wr32(pfb, 0x10f96c, 0x00000000 | (i << 8));
1201aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs			nv_wr32(pfb, 0x10f924, 0x00000000 | train0[i % 12]);
1202aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs			nv_wr32(pfb, 0x10f91c,              train1[i % 12]);
1203aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs			nv_wr32(pfb, 0x10f924, 0x00000100 | train0[i % 12]);
1204aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs			nv_wr32(pfb, 0x10f91c,              train1[i % 12]);
1205aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		}
1206aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs
1207aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		for (i = 0; i < 0x100; i++) {
1208aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs			nv_wr32(pfb, 0x10f968, i);
1209aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs			nv_wr32(pfb, 0x10f900, train1[2 + (i & 1)]);
1210aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		}
1211aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs
1212aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		for (i = 0; i < 0x100; i++) {
1213aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs			nv_wr32(pfb, 0x10f96c, i);
1214aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs			nv_wr32(pfb, 0x10f900, train1[2 + (i & 1)]);
1215aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		}
1216aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		break;
1217aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	default:
1218aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		break;
1219aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	}
1220aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs
1221aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	return 0;
1222aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs}
1223aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs
1224aae95ca708140307813e49af6d0d4a7205509129Ben Skeggsstatic int
1225aae95ca708140307813e49af6d0d4a7205509129Ben Skeggsnve0_ram_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
1226aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	      struct nouveau_oclass *oclass, void *data, u32 size,
1227aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	      struct nouveau_object **pobject)
1228aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs{
1229aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	struct nouveau_fb *pfb = nouveau_fb(parent);
1230aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	struct nouveau_bios *bios = nouveau_bios(pfb);
1231aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	struct nouveau_gpio *gpio = nouveau_gpio(pfb);
1232aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	struct dcb_gpio_func func;
1233aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	struct nve0_ram *ram;
1234d394fb12eca4cb9f42f922d7ae2bc8d7e1ed9272Ben Skeggs	int ret, i;
1235d394fb12eca4cb9f42f922d7ae2bc8d7e1ed9272Ben Skeggs	u32 tmp;
1236aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs
1237267dcb66437df958a6c2a30b3582ef76ba3bbb88Ben Skeggs	ret = nvc0_ram_create(parent, engine, oclass, 0x022554, &ram);
1238aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	*pobject = nv_object(ram);
1239aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	if (ret)
1240aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		return ret;
1241aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs
1242aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	switch (ram->base.type) {
1243aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	case NV_MEM_TYPE_DDR3:
1244aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	case NV_MEM_TYPE_GDDR5:
1245aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		ram->base.calc = nve0_ram_calc;
1246aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		ram->base.prog = nve0_ram_prog;
1247aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		ram->base.tidy = nve0_ram_tidy;
1248aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		break;
1249aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	default:
1250aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		nv_warn(pfb, "reclocking of this RAM type is unsupported\n");
1251aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		break;
1252aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	}
1253aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs
1254d394fb12eca4cb9f42f922d7ae2bc8d7e1ed9272Ben Skeggs	/* calculate a mask of differently configured memory partitions,
1255d394fb12eca4cb9f42f922d7ae2bc8d7e1ed9272Ben Skeggs	 * because, of course reclocking wasn't complicated enough
1256d394fb12eca4cb9f42f922d7ae2bc8d7e1ed9272Ben Skeggs	 * already without having to treat some of them differently to
1257d394fb12eca4cb9f42f922d7ae2bc8d7e1ed9272Ben Skeggs	 * the others....
1258d394fb12eca4cb9f42f922d7ae2bc8d7e1ed9272Ben Skeggs	 */
1259d394fb12eca4cb9f42f922d7ae2bc8d7e1ed9272Ben Skeggs	ram->parts = nv_rd32(pfb, 0x022438);
1260d394fb12eca4cb9f42f922d7ae2bc8d7e1ed9272Ben Skeggs	ram->pmask = nv_rd32(pfb, 0x022554);
1261d394fb12eca4cb9f42f922d7ae2bc8d7e1ed9272Ben Skeggs	ram->pnuts = 0;
1262d394fb12eca4cb9f42f922d7ae2bc8d7e1ed9272Ben Skeggs	for (i = 0, tmp = 0; i < ram->parts; i++) {
1263d394fb12eca4cb9f42f922d7ae2bc8d7e1ed9272Ben Skeggs		if (!(ram->pmask & (1 << i))) {
1264d394fb12eca4cb9f42f922d7ae2bc8d7e1ed9272Ben Skeggs			u32 cfg1 = nv_rd32(pfb, 0x110204 + (i * 0x1000));
1265d394fb12eca4cb9f42f922d7ae2bc8d7e1ed9272Ben Skeggs			if (tmp && tmp != cfg1) {
1266d394fb12eca4cb9f42f922d7ae2bc8d7e1ed9272Ben Skeggs				ram->pnuts |= (1 << i);
1267d394fb12eca4cb9f42f922d7ae2bc8d7e1ed9272Ben Skeggs				continue;
1268d394fb12eca4cb9f42f922d7ae2bc8d7e1ed9272Ben Skeggs			}
1269d394fb12eca4cb9f42f922d7ae2bc8d7e1ed9272Ben Skeggs			tmp = cfg1;
1270d394fb12eca4cb9f42f922d7ae2bc8d7e1ed9272Ben Skeggs		}
1271d394fb12eca4cb9f42f922d7ae2bc8d7e1ed9272Ben Skeggs	}
1272d394fb12eca4cb9f42f922d7ae2bc8d7e1ed9272Ben Skeggs
1273aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	// parse bios data for both pll's
1274aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	ret = nvbios_pll_parse(bios, 0x0c, &ram->fuc.refpll);
1275aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	if (ret) {
1276aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		nv_error(pfb, "mclk refpll data not found\n");
1277aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		return ret;
1278aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	}
1279aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs
1280aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	ret = nvbios_pll_parse(bios, 0x04, &ram->fuc.mempll);
1281aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	if (ret) {
1282aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		nv_error(pfb, "mclk pll data not found\n");
1283aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		return ret;
1284aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	}
1285aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs
1286aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	ret = gpio->find(gpio, 0, 0x18, DCB_GPIO_UNUSED, &func);
1287aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	if (ret == 0) {
1288aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		ram->fuc.r_gpioMV = ramfuc_reg(0x00d610 + (func.line * 0x04));
1289aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		ram->fuc.r_funcMV[0] = (func.log[0] ^ 2) << 12;
1290aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		ram->fuc.r_funcMV[1] = (func.log[1] ^ 2) << 12;
1291aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	}
1292aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs
1293aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	ret = gpio->find(gpio, 0, 0x2e, DCB_GPIO_UNUSED, &func);
1294aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	if (ret == 0) {
1295aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		ram->fuc.r_gpio2E = ramfuc_reg(0x00d610 + (func.line * 0x04));
1296aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		ram->fuc.r_func2E[0] = (func.log[0] ^ 2) << 12;
1297aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		ram->fuc.r_func2E[1] = (func.log[1] ^ 2) << 12;
1298aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	}
1299aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs
1300aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	ram->fuc.r_gpiotrig = ramfuc_reg(0x00d604);
1301aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs
1302aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	ram->fuc.r_0x132020 = ramfuc_reg(0x132020);
1303aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	ram->fuc.r_0x132028 = ramfuc_reg(0x132028);
1304aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	ram->fuc.r_0x132024 = ramfuc_reg(0x132024);
1305aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	ram->fuc.r_0x132030 = ramfuc_reg(0x132030);
1306aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	ram->fuc.r_0x132034 = ramfuc_reg(0x132034);
1307aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	ram->fuc.r_0x132000 = ramfuc_reg(0x132000);
1308aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	ram->fuc.r_0x132004 = ramfuc_reg(0x132004);
1309aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	ram->fuc.r_0x132040 = ramfuc_reg(0x132040);
1310aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs
1311aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	ram->fuc.r_0x10f248 = ramfuc_reg(0x10f248);
1312aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	ram->fuc.r_0x10f290 = ramfuc_reg(0x10f290);
1313aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	ram->fuc.r_0x10f294 = ramfuc_reg(0x10f294);
1314aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	ram->fuc.r_0x10f298 = ramfuc_reg(0x10f298);
1315aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	ram->fuc.r_0x10f29c = ramfuc_reg(0x10f29c);
1316aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	ram->fuc.r_0x10f2a0 = ramfuc_reg(0x10f2a0);
1317aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	ram->fuc.r_0x10f2a4 = ramfuc_reg(0x10f2a4);
1318aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	ram->fuc.r_0x10f2a8 = ramfuc_reg(0x10f2a8);
1319aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	ram->fuc.r_0x10f2ac = ramfuc_reg(0x10f2ac);
1320aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	ram->fuc.r_0x10f2cc = ramfuc_reg(0x10f2cc);
1321aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	ram->fuc.r_0x10f2e8 = ramfuc_reg(0x10f2e8);
1322aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	ram->fuc.r_0x10f250 = ramfuc_reg(0x10f250);
1323aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	ram->fuc.r_0x10f24c = ramfuc_reg(0x10f24c);
1324aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	ram->fuc.r_0x10fec4 = ramfuc_reg(0x10fec4);
1325aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	ram->fuc.r_0x10fec8 = ramfuc_reg(0x10fec8);
1326aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	ram->fuc.r_0x10f604 = ramfuc_reg(0x10f604);
1327aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	ram->fuc.r_0x10f614 = ramfuc_reg(0x10f614);
1328aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	ram->fuc.r_0x10f610 = ramfuc_reg(0x10f610);
1329aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	ram->fuc.r_0x100770 = ramfuc_reg(0x100770);
1330aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	ram->fuc.r_0x100778 = ramfuc_reg(0x100778);
1331aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	ram->fuc.r_0x10f224 = ramfuc_reg(0x10f224);
1332aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs
1333aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	ram->fuc.r_0x10f870 = ramfuc_reg(0x10f870);
1334aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	ram->fuc.r_0x10f698 = ramfuc_reg(0x10f698);
1335aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	ram->fuc.r_0x10f694 = ramfuc_reg(0x10f694);
1336aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	ram->fuc.r_0x10f6b8 = ramfuc_reg(0x10f6b8);
1337aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	ram->fuc.r_0x10f808 = ramfuc_reg(0x10f808);
1338aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	ram->fuc.r_0x10f670 = ramfuc_reg(0x10f670);
1339aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	ram->fuc.r_0x10f60c = ramfuc_reg(0x10f60c);
1340aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	ram->fuc.r_0x10f830 = ramfuc_reg(0x10f830);
1341aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	ram->fuc.r_0x1373ec = ramfuc_reg(0x1373ec);
1342aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	ram->fuc.r_0x10f800 = ramfuc_reg(0x10f800);
1343aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	ram->fuc.r_0x10f82c = ramfuc_reg(0x10f82c);
1344aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs
1345aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	ram->fuc.r_0x10f978 = ramfuc_reg(0x10f978);
1346aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	ram->fuc.r_0x10f910 = ramfuc_reg(0x10f910);
1347aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	ram->fuc.r_0x10f914 = ramfuc_reg(0x10f914);
1348aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs
1349aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	switch (ram->base.type) {
1350aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	case NV_MEM_TYPE_GDDR5:
1351aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		ram->fuc.r_mr[0] = ramfuc_reg(0x10f300);
1352aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		ram->fuc.r_mr[1] = ramfuc_reg(0x10f330);
1353aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		ram->fuc.r_mr[2] = ramfuc_reg(0x10f334);
1354aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		ram->fuc.r_mr[3] = ramfuc_reg(0x10f338);
1355aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		ram->fuc.r_mr[4] = ramfuc_reg(0x10f33c);
1356aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		ram->fuc.r_mr[5] = ramfuc_reg(0x10f340);
1357aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		ram->fuc.r_mr[6] = ramfuc_reg(0x10f344);
1358aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		ram->fuc.r_mr[7] = ramfuc_reg(0x10f348);
1359aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		ram->fuc.r_mr[8] = ramfuc_reg(0x10f354);
1360aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		ram->fuc.r_mr[15] = ramfuc_reg(0x10f34c);
1361aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		break;
1362aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	case NV_MEM_TYPE_DDR3:
1363aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		ram->fuc.r_mr[0] = ramfuc_reg(0x10f300);
1364aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		ram->fuc.r_mr[2] = ramfuc_reg(0x10f320);
1365aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		break;
1366aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	default:
1367aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		break;
1368aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	}
1369aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs
1370aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	ram->fuc.r_0x62c000 = ramfuc_reg(0x62c000);
1371aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	ram->fuc.r_0x10f200 = ramfuc_reg(0x10f200);
1372aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	ram->fuc.r_0x10f210 = ramfuc_reg(0x10f210);
1373aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	ram->fuc.r_0x10f310 = ramfuc_reg(0x10f310);
1374aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	ram->fuc.r_0x10f314 = ramfuc_reg(0x10f314);
1375aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	ram->fuc.r_0x10f318 = ramfuc_reg(0x10f318);
1376aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	ram->fuc.r_0x10f090 = ramfuc_reg(0x10f090);
1377aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	ram->fuc.r_0x10f69c = ramfuc_reg(0x10f69c);
1378aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	ram->fuc.r_0x10f824 = ramfuc_reg(0x10f824);
1379aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	ram->fuc.r_0x1373f0 = ramfuc_reg(0x1373f0);
1380aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	ram->fuc.r_0x1373f4 = ramfuc_reg(0x1373f4);
1381aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	ram->fuc.r_0x137320 = ramfuc_reg(0x137320);
1382aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	ram->fuc.r_0x10f65c = ramfuc_reg(0x10f65c);
1383aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	ram->fuc.r_0x10f6bc = ramfuc_reg(0x10f6bc);
1384aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	ram->fuc.r_0x100710 = ramfuc_reg(0x100710);
1385dd95c8f782a053db361855298778a7d31de04a48Ben Skeggs	ram->fuc.r_0x100750 = ramfuc_reg(0x100750);
1386aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	return 0;
1387aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs}
1388aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs
1389aae95ca708140307813e49af6d0d4a7205509129Ben Skeggsstruct nouveau_oclass
1390aae95ca708140307813e49af6d0d4a7205509129Ben Skeggsnve0_ram_oclass = {
1391aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	.handle = 0,
1392aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	.ofuncs = &(struct nouveau_ofuncs) {
1393aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		.ctor = nve0_ram_ctor,
1394aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		.dtor = _nouveau_ram_dtor,
1395aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		.init = nve0_ram_init,
1396aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs		.fini = _nouveau_ram_fini,
1397aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs	}
1398aae95ca708140307813e49af6d0d4a7205509129Ben Skeggs};
1399