xref: /openbmc/linux/arch/powerpc/platforms/85xx/p1022_ds.c (revision c900529f3d9161bfde5cca0754f83b4d3c3e0220)
1  /*
2   * P1022DS board specific routines
3   *
4   * Authors: Travis Wheatley <travis.wheatley@freescale.com>
5   *          Dave Liu <daveliu@freescale.com>
6   *          Timur Tabi <timur@freescale.com>
7   *
8   * Copyright 2010 Freescale Semiconductor, Inc.
9   *
10   * This file is taken from the Freescale P1022DS BSP, with modifications:
11   * 2) No AMP support
12   * 3) No PCI endpoint support
13   *
14   * This file is licensed under the terms of the GNU General Public License
15   * version 2.  This program is licensed "as is" without any warranty of any
16   * kind, whether express or implied.
17   */
18  
19  #include <linux/fsl/guts.h>
20  #include <linux/pci.h>
21  #include <linux/of.h>
22  #include <linux/of_address.h>
23  #include <asm/div64.h>
24  #include <asm/mpic.h>
25  #include <asm/swiotlb.h>
26  
27  #include <sysdev/fsl_soc.h>
28  #include <sysdev/fsl_pci.h>
29  #include <asm/udbg.h>
30  #include <asm/fsl_lbc.h>
31  #include "smp.h"
32  
33  #include "mpc85xx.h"
34  
35  #if defined(CONFIG_FB_FSL_DIU) || defined(CONFIG_FB_FSL_DIU_MODULE)
36  
37  #define PMUXCR_ELBCDIU_MASK	0xc0000000
38  #define PMUXCR_ELBCDIU_NOR16	0x80000000
39  #define PMUXCR_ELBCDIU_DIU	0x40000000
40  
41  /*
42   * Board-specific initialization of the DIU.  This code should probably be
43   * executed when the DIU is opened, rather than in arch code, but the DIU
44   * driver does not have a mechanism for this (yet).
45   *
46   * This is especially problematic on the P1022DS because the local bus (eLBC)
47   * and the DIU video signals share the same pins, which means that enabling the
48   * DIU will disable access to NOR flash.
49   */
50  
51  /* DIU Pixel Clock bits of the CLKDVDR Global Utilities register */
52  #define CLKDVDR_PXCKEN		0x80000000
53  #define CLKDVDR_PXCKINV		0x10000000
54  #define CLKDVDR_PXCKDLY		0x06000000
55  #define CLKDVDR_PXCLK_MASK	0x00FF0000
56  
57  /* Some ngPIXIS register definitions */
58  #define PX_CTL		3
59  #define PX_BRDCFG0	8
60  #define PX_BRDCFG1	9
61  
62  #define PX_BRDCFG0_ELBC_SPI_MASK	0xc0
63  #define PX_BRDCFG0_ELBC_SPI_ELBC	0x00
64  #define PX_BRDCFG0_ELBC_SPI_NULL	0xc0
65  #define PX_BRDCFG0_ELBC_DIU		0x02
66  
67  #define PX_BRDCFG1_DVIEN	0x80
68  #define PX_BRDCFG1_DFPEN	0x40
69  #define PX_BRDCFG1_BACKLIGHT	0x20
70  #define PX_BRDCFG1_DDCEN	0x10
71  
72  #define PX_CTL_ALTACC		0x80
73  
74  /*
75   * DIU Area Descriptor
76   *
77   * Note that we need to byte-swap the value before it's written to the AD
78   * register.  So even though the registers don't look like they're in the same
79   * bit positions as they are on the MPC8610, the same value is written to the
80   * AD register on the MPC8610 and on the P1022.
81   */
82  #define AD_BYTE_F		0x10000000
83  #define AD_ALPHA_C_MASK		0x0E000000
84  #define AD_ALPHA_C_SHIFT	25
85  #define AD_BLUE_C_MASK		0x01800000
86  #define AD_BLUE_C_SHIFT		23
87  #define AD_GREEN_C_MASK		0x00600000
88  #define AD_GREEN_C_SHIFT	21
89  #define AD_RED_C_MASK		0x00180000
90  #define AD_RED_C_SHIFT		19
91  #define AD_PALETTE		0x00040000
92  #define AD_PIXEL_S_MASK		0x00030000
93  #define AD_PIXEL_S_SHIFT	16
94  #define AD_COMP_3_MASK		0x0000F000
95  #define AD_COMP_3_SHIFT		12
96  #define AD_COMP_2_MASK		0x00000F00
97  #define AD_COMP_2_SHIFT		8
98  #define AD_COMP_1_MASK		0x000000F0
99  #define AD_COMP_1_SHIFT		4
100  #define AD_COMP_0_MASK		0x0000000F
101  #define AD_COMP_0_SHIFT		0
102  
103  #define MAKE_AD(alpha, red, blue, green, size, c0, c1, c2, c3) \
104  	cpu_to_le32(AD_BYTE_F | (alpha << AD_ALPHA_C_SHIFT) | \
105  	(blue << AD_BLUE_C_SHIFT) | (green << AD_GREEN_C_SHIFT) | \
106  	(red << AD_RED_C_SHIFT) | (c3 << AD_COMP_3_SHIFT) | \
107  	(c2 << AD_COMP_2_SHIFT) | (c1 << AD_COMP_1_SHIFT) | \
108  	(c0 << AD_COMP_0_SHIFT) | (size << AD_PIXEL_S_SHIFT))
109  
110  struct fsl_law {
111  	u32	lawbar;
112  	u32	reserved1;
113  	u32	lawar;
114  	u32	reserved[5];
115  };
116  
117  #define LAWBAR_MASK	0x00F00000
118  #define LAWBAR_SHIFT	12
119  
120  #define LAWAR_EN	0x80000000
121  #define LAWAR_TGT_MASK	0x01F00000
122  #define LAW_TRGT_IF_LBC	(0x04 << 20)
123  
124  #define LAWAR_MASK	(LAWAR_EN | LAWAR_TGT_MASK)
125  #define LAWAR_MATCH	(LAWAR_EN | LAW_TRGT_IF_LBC)
126  
127  #define BR_BA		0xFFFF8000
128  
129  /*
130   * Map a BRx value to a physical address
131   *
132   * The localbus BRx registers only store the lower 32 bits of the address.  To
133   * obtain the upper four bits, we need to scan the LAW table.  The entry which
134   * maps to the localbus will contain the upper four bits.
135   */
lbc_br_to_phys(const void * ecm,unsigned int count,u32 br)136  static phys_addr_t lbc_br_to_phys(const void *ecm, unsigned int count, u32 br)
137  {
138  #ifndef CONFIG_PHYS_64BIT
139  	/*
140  	 * If we only have 32-bit addressing, then the BRx address *is* the
141  	 * physical address.
142  	 */
143  	return br & BR_BA;
144  #else
145  	const struct fsl_law *law = ecm + 0xc08;
146  	unsigned int i;
147  
148  	for (i = 0; i < count; i++) {
149  		u64 lawbar = in_be32(&law[i].lawbar);
150  		u32 lawar = in_be32(&law[i].lawar);
151  
152  		if ((lawar & LAWAR_MASK) == LAWAR_MATCH)
153  			/* Extract the upper four bits */
154  			return (br & BR_BA) | ((lawbar & LAWBAR_MASK) << 12);
155  	}
156  
157  	return 0;
158  #endif
159  }
160  
161  /**
162   * p1022ds_set_monitor_port: switch the output to a different monitor port
163   */
p1022ds_set_monitor_port(enum fsl_diu_monitor_port port)164  static void p1022ds_set_monitor_port(enum fsl_diu_monitor_port port)
165  {
166  	struct device_node *guts_node;
167  	struct device_node *lbc_node = NULL;
168  	struct device_node *law_node = NULL;
169  	struct ccsr_guts __iomem *guts;
170  	struct fsl_lbc_regs *lbc = NULL;
171  	void *ecm = NULL;
172  	u8 __iomem *lbc_lcs0_ba = NULL;
173  	u8 __iomem *lbc_lcs1_ba = NULL;
174  	phys_addr_t cs0_addr, cs1_addr;
175  	u32 br0, or0, br1, or1;
176  	const __be32 *iprop;
177  	unsigned int num_laws;
178  	u8 b;
179  
180  	/* Map the global utilities registers. */
181  	guts_node = of_find_compatible_node(NULL, NULL, "fsl,p1022-guts");
182  	if (!guts_node) {
183  		pr_err("p1022ds: missing global utilities device node\n");
184  		return;
185  	}
186  
187  	guts = of_iomap(guts_node, 0);
188  	if (!guts) {
189  		pr_err("p1022ds: could not map global utilities device\n");
190  		goto exit;
191  	}
192  
193  	lbc_node = of_find_compatible_node(NULL, NULL, "fsl,p1022-elbc");
194  	if (!lbc_node) {
195  		pr_err("p1022ds: missing localbus node\n");
196  		goto exit;
197  	}
198  
199  	lbc = of_iomap(lbc_node, 0);
200  	if (!lbc) {
201  		pr_err("p1022ds: could not map localbus node\n");
202  		goto exit;
203  	}
204  
205  	law_node = of_find_compatible_node(NULL, NULL, "fsl,ecm-law");
206  	if (!law_node) {
207  		pr_err("p1022ds: missing local access window node\n");
208  		goto exit;
209  	}
210  
211  	ecm = of_iomap(law_node, 0);
212  	if (!ecm) {
213  		pr_err("p1022ds: could not map local access window node\n");
214  		goto exit;
215  	}
216  
217  	iprop = of_get_property(law_node, "fsl,num-laws", NULL);
218  	if (!iprop) {
219  		pr_err("p1022ds: LAW node is missing fsl,num-laws property\n");
220  		goto exit;
221  	}
222  	num_laws = be32_to_cpup(iprop);
223  
224  	/*
225  	 * Indirect mode requires both BR0 and BR1 to be set to "GPCM",
226  	 * otherwise writes to these addresses won't actually appear on the
227  	 * local bus, and so the PIXIS won't see them.
228  	 *
229  	 * In FCM mode, writes go to the NAND controller, which does not pass
230  	 * them to the localbus directly.  So we force BR0 and BR1 into GPCM
231  	 * mode, since we don't care about what's behind the localbus any
232  	 * more.
233  	 */
234  	br0 = in_be32(&lbc->bank[0].br);
235  	br1 = in_be32(&lbc->bank[1].br);
236  	or0 = in_be32(&lbc->bank[0].or);
237  	or1 = in_be32(&lbc->bank[1].or);
238  
239  	/* Make sure CS0 and CS1 are programmed */
240  	if (!(br0 & BR_V) || !(br1 & BR_V)) {
241  		pr_err("p1022ds: CS0 and/or CS1 is not programmed\n");
242  		goto exit;
243  	}
244  
245  	/*
246  	 * Use the existing BRx/ORx values if it's already GPCM. Otherwise,
247  	 * force the values to simple 32KB GPCM windows with the most
248  	 * conservative timing.
249  	 */
250  	if ((br0 & BR_MSEL) != BR_MS_GPCM) {
251  		br0 = (br0 & BR_BA) | BR_V;
252  		or0 = 0xFFFF8000 | 0xFF7;
253  		out_be32(&lbc->bank[0].br, br0);
254  		out_be32(&lbc->bank[0].or, or0);
255  	}
256  	if ((br1 & BR_MSEL) != BR_MS_GPCM) {
257  		br1 = (br1 & BR_BA) | BR_V;
258  		or1 = 0xFFFF8000 | 0xFF7;
259  		out_be32(&lbc->bank[1].br, br1);
260  		out_be32(&lbc->bank[1].or, or1);
261  	}
262  
263  	cs0_addr = lbc_br_to_phys(ecm, num_laws, br0);
264  	if (!cs0_addr) {
265  		pr_err("p1022ds: could not determine physical address for CS0"
266  		       " (BR0=%08x)\n", br0);
267  		goto exit;
268  	}
269  	cs1_addr = lbc_br_to_phys(ecm, num_laws, br1);
270  	if (!cs1_addr) {
271  		pr_err("p1022ds: could not determine physical address for CS1"
272  		       " (BR1=%08x)\n", br1);
273  		goto exit;
274  	}
275  
276  	lbc_lcs0_ba = ioremap(cs0_addr, 1);
277  	if (!lbc_lcs0_ba) {
278  		pr_err("p1022ds: could not ioremap CS0 address %llx\n",
279  		       (unsigned long long)cs0_addr);
280  		goto exit;
281  	}
282  	lbc_lcs1_ba = ioremap(cs1_addr, 1);
283  	if (!lbc_lcs1_ba) {
284  		pr_err("p1022ds: could not ioremap CS1 address %llx\n",
285  		       (unsigned long long)cs1_addr);
286  		goto exit;
287  	}
288  
289  	/* Make sure we're in indirect mode first. */
290  	if ((in_be32(&guts->pmuxcr) & PMUXCR_ELBCDIU_MASK) !=
291  	    PMUXCR_ELBCDIU_DIU) {
292  		struct device_node *pixis_node;
293  		void __iomem *pixis;
294  
295  		pixis_node =
296  			of_find_compatible_node(NULL, NULL, "fsl,p1022ds-fpga");
297  		if (!pixis_node) {
298  			pr_err("p1022ds: missing pixis node\n");
299  			goto exit;
300  		}
301  
302  		pixis = of_iomap(pixis_node, 0);
303  		of_node_put(pixis_node);
304  		if (!pixis) {
305  			pr_err("p1022ds: could not map pixis registers\n");
306  			goto exit;
307  		}
308  
309  		/* Enable indirect PIXIS mode.  */
310  		setbits8(pixis + PX_CTL, PX_CTL_ALTACC);
311  		iounmap(pixis);
312  
313  		/* Switch the board mux to the DIU */
314  		out_8(lbc_lcs0_ba, PX_BRDCFG0);	/* BRDCFG0 */
315  		b = in_8(lbc_lcs1_ba);
316  		b |= PX_BRDCFG0_ELBC_DIU;
317  		out_8(lbc_lcs1_ba, b);
318  
319  		/* Set the chip mux to DIU mode. */
320  		clrsetbits_be32(&guts->pmuxcr, PMUXCR_ELBCDIU_MASK,
321  				PMUXCR_ELBCDIU_DIU);
322  		in_be32(&guts->pmuxcr);
323  	}
324  
325  
326  	switch (port) {
327  	case FSL_DIU_PORT_DVI:
328  		/* Enable the DVI port, disable the DFP and the backlight */
329  		out_8(lbc_lcs0_ba, PX_BRDCFG1);
330  		b = in_8(lbc_lcs1_ba);
331  		b &= ~(PX_BRDCFG1_DFPEN | PX_BRDCFG1_BACKLIGHT);
332  		b |= PX_BRDCFG1_DVIEN;
333  		out_8(lbc_lcs1_ba, b);
334  		break;
335  	case FSL_DIU_PORT_LVDS:
336  		/*
337  		 * LVDS also needs backlight enabled, otherwise the display
338  		 * will be blank.
339  		 */
340  		/* Enable the DFP port, disable the DVI and the backlight */
341  		out_8(lbc_lcs0_ba, PX_BRDCFG1);
342  		b = in_8(lbc_lcs1_ba);
343  		b &= ~PX_BRDCFG1_DVIEN;
344  		b |= PX_BRDCFG1_DFPEN | PX_BRDCFG1_BACKLIGHT;
345  		out_8(lbc_lcs1_ba, b);
346  		break;
347  	default:
348  		pr_err("p1022ds: unsupported monitor port %i\n", port);
349  	}
350  
351  exit:
352  	if (lbc_lcs1_ba)
353  		iounmap(lbc_lcs1_ba);
354  	if (lbc_lcs0_ba)
355  		iounmap(lbc_lcs0_ba);
356  	if (lbc)
357  		iounmap(lbc);
358  	if (ecm)
359  		iounmap(ecm);
360  	if (guts)
361  		iounmap(guts);
362  
363  	of_node_put(law_node);
364  	of_node_put(lbc_node);
365  	of_node_put(guts_node);
366  }
367  
368  /**
369   * p1022ds_set_pixel_clock: program the DIU's clock
370   *
371   * @pixclock: the wavelength, in picoseconds, of the clock
372   */
p1022ds_set_pixel_clock(unsigned int pixclock)373  void p1022ds_set_pixel_clock(unsigned int pixclock)
374  {
375  	struct device_node *guts_np = NULL;
376  	struct ccsr_guts __iomem *guts;
377  	unsigned long freq;
378  	u64 temp;
379  	u32 pxclk;
380  
381  	/* Map the global utilities registers. */
382  	guts_np = of_find_compatible_node(NULL, NULL, "fsl,p1022-guts");
383  	if (!guts_np) {
384  		pr_err("p1022ds: missing global utilities device node\n");
385  		return;
386  	}
387  
388  	guts = of_iomap(guts_np, 0);
389  	of_node_put(guts_np);
390  	if (!guts) {
391  		pr_err("p1022ds: could not map global utilities device\n");
392  		return;
393  	}
394  
395  	/* Convert pixclock from a wavelength to a frequency */
396  	temp = 1000000000000ULL;
397  	do_div(temp, pixclock);
398  	freq = temp;
399  
400  	/*
401  	 * 'pxclk' is the ratio of the platform clock to the pixel clock.
402  	 * This number is programmed into the CLKDVDR register, and the valid
403  	 * range of values is 2-255.
404  	 */
405  	pxclk = DIV_ROUND_CLOSEST(fsl_get_sys_freq(), freq);
406  	pxclk = clamp_t(u32, pxclk, 2, 255);
407  
408  	/* Disable the pixel clock, and set it to non-inverted and no delay */
409  	clrbits32(&guts->clkdvdr,
410  		  CLKDVDR_PXCKEN | CLKDVDR_PXCKDLY | CLKDVDR_PXCLK_MASK);
411  
412  	/* Enable the clock and set the pxclk */
413  	setbits32(&guts->clkdvdr, CLKDVDR_PXCKEN | (pxclk << 16));
414  
415  	iounmap(guts);
416  }
417  
418  /**
419   * p1022ds_valid_monitor_port: set the monitor port for sysfs
420   */
421  enum fsl_diu_monitor_port
p1022ds_valid_monitor_port(enum fsl_diu_monitor_port port)422  p1022ds_valid_monitor_port(enum fsl_diu_monitor_port port)
423  {
424  	switch (port) {
425  	case FSL_DIU_PORT_DVI:
426  	case FSL_DIU_PORT_LVDS:
427  		return port;
428  	default:
429  		return FSL_DIU_PORT_DVI; /* Dual-link LVDS is not supported */
430  	}
431  }
432  
433  #endif
434  
p1022_ds_pic_init(void)435  void __init p1022_ds_pic_init(void)
436  {
437  	struct mpic *mpic = mpic_alloc(NULL, 0, MPIC_BIG_ENDIAN |
438  		MPIC_SINGLE_DEST_CPU,
439  		0, 256, " OpenPIC  ");
440  	BUG_ON(mpic == NULL);
441  	mpic_init(mpic);
442  }
443  
444  #if defined(CONFIG_FB_FSL_DIU) || defined(CONFIG_FB_FSL_DIU_MODULE)
445  
446  /* TRUE if there is a "video=fslfb" command-line parameter. */
447  static bool fslfb;
448  
449  /*
450   * Search for a "video=fslfb" command-line parameter, and set 'fslfb' to
451   * true if we find it.
452   *
453   * We need to use early_param() instead of __setup() because the normal
454   * __setup() gets called to late.  However, early_param() gets called very
455   * early, before the device tree is unflattened, so all we can do now is set a
456   * global variable.  Later on, p1022_ds_setup_arch() will use that variable
457   * to determine if we need to update the device tree.
458   */
early_video_setup(char * options)459  static int __init early_video_setup(char *options)
460  {
461  	fslfb = (strncmp(options, "fslfb:", 6) == 0);
462  
463  	return 0;
464  }
465  early_param("video", early_video_setup);
466  
467  #endif
468  
469  /*
470   * Setup the architecture
471   */
p1022_ds_setup_arch(void)472  static void __init p1022_ds_setup_arch(void)
473  {
474  	if (ppc_md.progress)
475  		ppc_md.progress("p1022_ds_setup_arch()", 0);
476  
477  #if defined(CONFIG_FB_FSL_DIU) || defined(CONFIG_FB_FSL_DIU_MODULE)
478  	diu_ops.set_monitor_port	= p1022ds_set_monitor_port;
479  	diu_ops.set_pixel_clock		= p1022ds_set_pixel_clock;
480  	diu_ops.valid_monitor_port	= p1022ds_valid_monitor_port;
481  
482  	/*
483  	 * Disable the NOR and NAND flash nodes if there is video=fslfb...
484  	 * command-line parameter.  When the DIU is active, the localbus is
485  	 * unavailable, so we have to disable these nodes before the MTD
486  	 * driver loads.
487  	 */
488  	if (fslfb) {
489  		struct device_node *np =
490  			of_find_compatible_node(NULL, NULL, "fsl,p1022-elbc");
491  
492  		if (np) {
493  			struct device_node *np2;
494  
495  			of_node_get(np);
496  			np2 = of_find_compatible_node(np, NULL, "cfi-flash");
497  			if (np2) {
498  				static struct property nor_status = {
499  					.name = "status",
500  					.value = "disabled",
501  					.length = sizeof("disabled"),
502  				};
503  
504  				/*
505  				 * of_update_property() is called before
506  				 * kmalloc() is available, so the 'new' object
507  				 * should be allocated in the global area.
508  				 * The easiest way is to do that is to
509  				 * allocate one static local variable for each
510  				 * call to this function.
511  				 */
512  				pr_info("p1022ds: disabling %pOF node",
513  					np2);
514  				of_update_property(np2, &nor_status);
515  				of_node_put(np2);
516  			}
517  
518  			of_node_get(np);
519  			np2 = of_find_compatible_node(np, NULL,
520  						      "fsl,elbc-fcm-nand");
521  			if (np2) {
522  				static struct property nand_status = {
523  					.name = "status",
524  					.value = "disabled",
525  					.length = sizeof("disabled"),
526  				};
527  
528  				pr_info("p1022ds: disabling %pOF node",
529  					np2);
530  				of_update_property(np2, &nand_status);
531  				of_node_put(np2);
532  			}
533  
534  			of_node_put(np);
535  		}
536  
537  	}
538  
539  #endif
540  
541  	mpc85xx_smp_init();
542  
543  	fsl_pci_assign_primary();
544  
545  	swiotlb_detect_4g();
546  
547  	pr_info("Freescale P1022 DS reference board\n");
548  }
549  
550  machine_arch_initcall(p1022_ds, mpc85xx_common_publish_devices);
551  
define_machine(p1022_ds)552  define_machine(p1022_ds) {
553  	.name			= "P1022 DS",
554  	.compatible		= "fsl,p1022ds",
555  	.setup_arch		= p1022_ds_setup_arch,
556  	.init_IRQ		= p1022_ds_pic_init,
557  #ifdef CONFIG_PCI
558  	.pcibios_fixup_bus	= fsl_pcibios_fixup_bus,
559  	.pcibios_fixup_phb	= fsl_pcibios_fixup_phb,
560  #endif
561  	.get_irq		= mpic_get_irq,
562  	.progress		= udbg_progress,
563  };
564