blob: acc3fbd691a2c7b5bbf1ba0a2a60b6cd2967bdd9 [file] [log] [blame]
Joel Stanleye50183f2017-02-28 12:17:46 +10301From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
2From: Russell Currey <ruscur@russell.cc>
3Date: Fri, 17 Feb 2017 14:33:01 +1100
4Subject: [PATCH 04/15] drm/ast: Handle configuration without P2A bridge
5
6The ast driver configures a window to enable access into BMC
7memory space in order to read some configuration registers.
8
9If this window is disabled, which it can be from the BMC side,
10the ast driver can't function.
11
12Closing this window is a necessity for security if a machine's
13host side and BMC side are controlled by different parties;
14i.e. a cloud provider offering machines "bare metal".
15
16A recent patch went in to try to check if that window is open
17but it does so by trying to access the registers in question
18and testing if the result is 0xffffffff.
19
20This method will trigger a PCIe error when the window is closed
21which on some systems will be fatal (it will trigger an EEH
22for example on POWER which will take out the device).
23
24This patch improves this in two ways:
25
26 - First, if the firmware has put properties in the device-tree
27containing the relevant configuration information, we use these.
28
29 - Otherwise, a bit in one of the SCU scratch registers (which
30are readable via the VGA register space and writeable by the BMC)
31will indicate if the BMC has closed the window. This bit has been
32defined by Y.C Chen from Aspeed.
33
34If the window is closed and the configuration isn't available from
35the device-tree, some sane defaults are used. Those defaults are
36hopefully sufficient for standard video modes used on a server.
37
38Signed-off-by: Russell Currey <ruscur@russell.cc>
39Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
40--
41
42v2. [BenH]
43 - Reworked on top of Aspeed P2A patch
44 - Cleanup overall detection via a "config_mode" and log the
45 selected mode for diagnostics purposes
46 - Add a property for the SCU straps
47
48v3. [BenH]
49 - Moved the config mode detection to a separate functionn
50 - Add reading of SCU 0x40 D[12] to detect the window is
51 closed as to not trigger a bus error by just "trying".
52 (change provided by Y.C. Chen)
53v4. [BenH]
54 - Only devices with the AST2000 PCI ID have a P2A bridge
55 - Update the P2A presence test to account for VGA only
56 mode as provided by Y.C. Chen.
57v5. [BenH]
58 - Fixup prefix of OF properties based on Joel Stanley
59 review comments.
60
61Signed-off-by: Joel Stanley <joel@jms.id.au>
62---
63 drivers/gpu/drm/ast/ast_drv.h | 6 +-
64 drivers/gpu/drm/ast/ast_main.c | 264 +++++++++++++++++++++++++----------------
65 drivers/gpu/drm/ast/ast_post.c | 7 +-
66 3 files changed, 168 insertions(+), 109 deletions(-)
67
68diff --git a/drivers/gpu/drm/ast/ast_drv.h b/drivers/gpu/drm/ast/ast_drv.h
69index 7abda94fc2cf..3bedcf7ddd2a 100644
70--- a/drivers/gpu/drm/ast/ast_drv.h
71+++ b/drivers/gpu/drm/ast/ast_drv.h
72@@ -113,7 +113,11 @@ struct ast_private {
73 struct ttm_bo_kmap_obj cache_kmap;
74 int next_cursor;
75 bool support_wide_screen;
76- bool DisableP2A;
77+ enum {
78+ ast_use_p2a,
79+ ast_use_dt,
80+ ast_use_defaults
81+ } config_mode;
82
83 enum ast_tx_chip tx_chip_type;
84 u8 dp501_maxclk;
85diff --git a/drivers/gpu/drm/ast/ast_main.c b/drivers/gpu/drm/ast/ast_main.c
86index 533e762d036d..fb9976254224 100644
87--- a/drivers/gpu/drm/ast/ast_main.c
88+++ b/drivers/gpu/drm/ast/ast_main.c
89@@ -62,13 +62,84 @@ uint8_t ast_get_index_reg_mask(struct ast_private *ast,
90 return ret;
91 }
92
93+static void ast_detect_config_mode(struct drm_device *dev, u32 *scu_rev)
94+{
95+ struct device_node *np = dev->pdev->dev.of_node;
96+ struct ast_private *ast = dev->dev_private;
97+ uint32_t data, jregd0, jregd1;
98+
99+ /* Defaults */
100+ ast->config_mode = ast_use_defaults;
101+ *scu_rev = 0xffffffff;
102+
103+ /* Check if we have device-tree properties */
104+ if (np && !of_property_read_u32(np, "aspeed,scu-revision-id",
105+ scu_rev)) {
106+ /* We do, disable P2A access */
107+ ast->config_mode = ast_use_dt;
108+ DRM_INFO("Using device-tree for configuration\n");
109+ return;
110+ }
111+
112+ /* Not all families have a P2A bridge */
113+ if (dev->pdev->device != PCI_CHIP_AST2000)
114+ return;
115+
116+ /*
117+ * The BMC will set SCU 0x40 D[12] to 1 if the P2 bridge
118+ * is disabled. We force using P2A if VGA only mode bit
119+ * is set D[7]
120+ */
121+ jregd0 = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xd0, 0xff);
122+ jregd1 = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xd1, 0xff);
123+ if (!(jregd0 & 0x80) || !(jregd1 & 0x10)) {
124+ /* Double check it's actually working */
125+ data = ast_read32(ast, 0xf004);
126+ if (data != 0xFFFFFFFF) {
127+ /* P2A works, grab silicon revision */
128+ ast->config_mode = ast_use_p2a;
129+
130+ DRM_INFO("Using P2A bridge for configuration\n");
131+
132+ /* Read SCU7c (silicon revision register) */
133+ ast_write32(ast, 0xf004, 0x1e6e0000);
134+ ast_write32(ast, 0xf000, 0x1);
135+ *scu_rev = ast_read32(ast, 0x1207c);
136+ return;
137+ }
138+ }
139+
140+ /* We have a P2A bridge but it's disabled */
141+ DRM_INFO("P2A bridge disabled, using default configuration\n");
142+}
143
144 static int ast_detect_chip(struct drm_device *dev, bool *need_post)
145 {
146 struct ast_private *ast = dev->dev_private;
147- uint32_t data, jreg;
148+ uint32_t jreg, scu_rev;
149+
150+ /*
151+ * If VGA isn't enabled, we need to enable now or subsequent
152+ * access to the scratch registers will fail. We also inform
153+ * our caller that it needs to POST the chip
154+ * (Assumption: VGA not enabled -> need to POST)
155+ */
156+ if (!ast_is_vga_enabled(dev)) {
157+ ast_enable_vga(dev);
158+ DRM_INFO("VGA not enabled on entry, requesting chip POST\n");
159+ *need_post = true;
160+ } else
161+ *need_post = false;
162+
163+
164+ /* Enable extended register access */
165+ ast_enable_mmio(dev);
166 ast_open_key(ast);
167
168+ /* Find out whether P2A works or whether to use device-tree */
169+ ast_detect_config_mode(dev, &scu_rev);
170+
171+ /* Identify chipset */
172 if (dev->pdev->device == PCI_CHIP_AST1180) {
173 ast->chip = AST1100;
174 DRM_INFO("AST 1180 detected\n");
175@@ -80,12 +151,7 @@ static int ast_detect_chip(struct drm_device *dev, bool *need_post)
176 ast->chip = AST2300;
177 DRM_INFO("AST 2300 detected\n");
178 } else if (dev->pdev->revision >= 0x10) {
179- uint32_t data;
180- ast_write32(ast, 0xf004, 0x1e6e0000);
181- ast_write32(ast, 0xf000, 0x1);
182-
183- data = ast_read32(ast, 0x1207c);
184- switch (data & 0x0300) {
185+ switch (scu_rev & 0x0300) {
186 case 0x0200:
187 ast->chip = AST1100;
188 DRM_INFO("AST 1100 detected\n");
189@@ -110,26 +176,6 @@ static int ast_detect_chip(struct drm_device *dev, bool *need_post)
190 }
191 }
192
193- /*
194- * If VGA isn't enabled, we need to enable now or subsequent
195- * access to the scratch registers will fail. We also inform
196- * our caller that it needs to POST the chip
197- * (Assumption: VGA not enabled -> need to POST)
198- */
199- if (!ast_is_vga_enabled(dev)) {
200- ast_enable_vga(dev);
201- ast_enable_mmio(dev);
202- DRM_INFO("VGA not enabled on entry, requesting chip POST\n");
203- *need_post = true;
204- } else
205- *need_post = false;
206-
207- /* Check P2A Access */
208- ast->DisableP2A = true;
209- data = ast_read32(ast, 0xf004);
210- if (data != 0xFFFFFFFF)
211- ast->DisableP2A = false;
212-
213 /* Check if we support wide screen */
214 switch (ast->chip) {
215 case AST1180:
216@@ -146,17 +192,12 @@ static int ast_detect_chip(struct drm_device *dev, bool *need_post)
217 ast->support_wide_screen = true;
218 else {
219 ast->support_wide_screen = false;
220- if (ast->DisableP2A == false) {
221- /* Read SCU7c (silicon revision register) */
222- ast_write32(ast, 0xf004, 0x1e6e0000);
223- ast_write32(ast, 0xf000, 0x1);
224- data = ast_read32(ast, 0x1207c);
225- data &= 0x300;
226- if (ast->chip == AST2300 && data == 0x0) /* ast1300 */
227- ast->support_wide_screen = true;
228- if (ast->chip == AST2400 && data == 0x100) /* ast1400 */
229- ast->support_wide_screen = true;
230- }
231+ if (ast->chip == AST2300 &&
232+ (scu_rev & 0x300) == 0x0) /* ast1300 */
233+ ast->support_wide_screen = true;
234+ if (ast->chip == AST2400 &&
235+ (scu_rev & 0x300) == 0x100) /* ast1400 */
236+ ast->support_wide_screen = true;
237 }
238 break;
239 }
240@@ -220,85 +261,102 @@ static int ast_detect_chip(struct drm_device *dev, bool *need_post)
241
242 static int ast_get_dram_info(struct drm_device *dev)
243 {
244+ struct device_node *np = dev->pdev->dev.of_node;
245 struct ast_private *ast = dev->dev_private;
246- uint32_t data, data2;
247- uint32_t denum, num, div, ref_pll;
248+ uint32_t mcr_cfg, mcr_scu_mpll, mcr_scu_strap;
249+ uint32_t denum, num, div, ref_pll, dsel;
250
251- if (ast->DisableP2A)
252- {
253+ switch (ast->config_mode) {
254+ case ast_use_dt:
255+ /*
256+ * If some properties are missing, use reasonable
257+ * defaults for AST2400
258+ */
259+ if (of_property_read_u32(np, "aspeed,mcr-configuration",
260+ &mcr_cfg))
261+ mcr_cfg = 0x00000577;
262+ if (of_property_read_u32(np, "aspeed,mcr-scu-mpll",
263+ &mcr_scu_mpll))
264+ mcr_scu_mpll = 0x000050C0;
265+ if (of_property_read_u32(np, "aspeed,mcr-scu-strap",
266+ &mcr_scu_strap))
267+ mcr_scu_strap = 0;
268+ break;
269+ case ast_use_p2a:
270+ ast_write32(ast, 0xf004, 0x1e6e0000);
271+ ast_write32(ast, 0xf000, 0x1);
272+ mcr_cfg = ast_read32(ast, 0x10004);
273+ mcr_scu_mpll = ast_read32(ast, 0x10120);
274+ mcr_scu_strap = ast_read32(ast, 0x10170);
275+ break;
276+ case ast_use_defaults:
277+ default:
278 ast->dram_bus_width = 16;
279 ast->dram_type = AST_DRAM_1Gx16;
280 ast->mclk = 396;
281+ return 0;
282 }
283- else
284- {
285- ast_write32(ast, 0xf004, 0x1e6e0000);
286- ast_write32(ast, 0xf000, 0x1);
287- data = ast_read32(ast, 0x10004);
288-
289- if (data & 0x40)
290- ast->dram_bus_width = 16;
291- else
292- ast->dram_bus_width = 32;
293
294- if (ast->chip == AST2300 || ast->chip == AST2400) {
295- switch (data & 0x03) {
296- case 0:
297- ast->dram_type = AST_DRAM_512Mx16;
298- break;
299- default:
300- case 1:
301- ast->dram_type = AST_DRAM_1Gx16;
302- break;
303- case 2:
304- ast->dram_type = AST_DRAM_2Gx16;
305- break;
306- case 3:
307- ast->dram_type = AST_DRAM_4Gx16;
308- break;
309- }
310- } else {
311- switch (data & 0x0c) {
312- case 0:
313- case 4:
314- ast->dram_type = AST_DRAM_512Mx16;
315- break;
316- case 8:
317- if (data & 0x40)
318- ast->dram_type = AST_DRAM_1Gx16;
319- else
320- ast->dram_type = AST_DRAM_512Mx32;
321- break;
322- case 0xc:
323- ast->dram_type = AST_DRAM_1Gx32;
324- break;
325- }
326- }
327+ if (mcr_cfg & 0x40)
328+ ast->dram_bus_width = 16;
329+ else
330+ ast->dram_bus_width = 32;
331
332- data = ast_read32(ast, 0x10120);
333- data2 = ast_read32(ast, 0x10170);
334- if (data2 & 0x2000)
335- ref_pll = 14318;
336- else
337- ref_pll = 12000;
338-
339- denum = data & 0x1f;
340- num = (data & 0x3fe0) >> 5;
341- data = (data & 0xc000) >> 14;
342- switch (data) {
343- case 3:
344- div = 0x4;
345+ if (ast->chip == AST2300 || ast->chip == AST2400) {
346+ switch (mcr_cfg & 0x03) {
347+ case 0:
348+ ast->dram_type = AST_DRAM_512Mx16;
349 break;
350- case 2:
351+ default:
352 case 1:
353- div = 0x2;
354+ ast->dram_type = AST_DRAM_1Gx16;
355 break;
356- default:
357- div = 0x1;
358+ case 2:
359+ ast->dram_type = AST_DRAM_2Gx16;
360+ break;
361+ case 3:
362+ ast->dram_type = AST_DRAM_4Gx16;
363+ break;
364+ }
365+ } else {
366+ switch (mcr_cfg & 0x0c) {
367+ case 0:
368+ case 4:
369+ ast->dram_type = AST_DRAM_512Mx16;
370+ break;
371+ case 8:
372+ if (mcr_cfg & 0x40)
373+ ast->dram_type = AST_DRAM_1Gx16;
374+ else
375+ ast->dram_type = AST_DRAM_512Mx32;
376+ break;
377+ case 0xc:
378+ ast->dram_type = AST_DRAM_1Gx32;
379 break;
380 }
381- ast->mclk = ref_pll * (num + 2) / (denum + 2) * (div * 1000);
382 }
383+
384+ if (mcr_scu_strap & 0x2000)
385+ ref_pll = 14318;
386+ else
387+ ref_pll = 12000;
388+
389+ denum = mcr_scu_mpll & 0x1f;
390+ num = (mcr_scu_mpll & 0x3fe0) >> 5;
391+ dsel = (mcr_scu_mpll & 0xc000) >> 14;
392+ switch (dsel) {
393+ case 3:
394+ div = 0x4;
395+ break;
396+ case 2:
397+ case 1:
398+ div = 0x2;
399+ break;
400+ default:
401+ div = 0x1;
402+ break;
403+ }
404+ ast->mclk = ref_pll * (num + 2) / (denum + 2) * (div * 1000);
405 return 0;
406 }
407
408diff --git a/drivers/gpu/drm/ast/ast_post.c b/drivers/gpu/drm/ast/ast_post.c
409index 6c5391cb90eb..64549cebcc5b 100644
410--- a/drivers/gpu/drm/ast/ast_post.c
411+++ b/drivers/gpu/drm/ast/ast_post.c
412@@ -379,17 +379,14 @@ void ast_post_gpu(struct drm_device *dev)
413 ast_open_key(ast);
414 ast_set_def_ext_reg(dev);
415
416- if (ast->DisableP2A == false)
417- {
418+ if (ast->config_mode == ast_use_p2a) {
419 if (ast->chip == AST2300 || ast->chip == AST2400)
420 ast_init_dram_2300(dev);
421 else
422 ast_init_dram_reg(dev);
423
424 ast_init_3rdtx(dev);
425- }
426- else
427- {
428+ } else {
429 if (ast->tx_chip_type != AST_TX_NONE)
430 ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xa3, 0xcf, 0x80); /* Enable DVO */
431 }
432--
4332.11.0
434