]>
Commit | Line | Data |
---|---|---|
34f84b5b TT |
1 | /* |
2 | * P1022 RDK board specific routines | |
3 | * | |
4 | * Copyright 2012 Freescale Semiconductor, Inc. | |
5 | * | |
6 | * Author: Timur Tabi <timur@freescale.com> | |
7 | * | |
8 | * Based on p1022_ds.c | |
9 | * | |
10 | * This file is licensed under the terms of the GNU General Public License | |
11 | * version 2. This program is licensed "as is" without any warranty of any | |
12 | * kind, whether express or implied. | |
13 | */ | |
14 | ||
15 | #include <linux/pci.h> | |
16 | #include <linux/of_platform.h> | |
34f84b5b TT |
17 | #include <asm/div64.h> |
18 | #include <asm/mpic.h> | |
19 | #include <asm/swiotlb.h> | |
20 | ||
21 | #include <sysdev/fsl_soc.h> | |
22 | #include <sysdev/fsl_pci.h> | |
23 | #include <asm/udbg.h> | |
24 | #include <asm/fsl_guts.h> | |
25 | #include "smp.h" | |
26 | ||
27 | #include "mpc85xx.h" | |
28 | ||
29 | #if defined(CONFIG_FB_FSL_DIU) || defined(CONFIG_FB_FSL_DIU_MODULE) | |
30 | ||
31 | /* DIU Pixel Clock bits of the CLKDVDR Global Utilities register */ | |
32 | #define CLKDVDR_PXCKEN 0x80000000 | |
33 | #define CLKDVDR_PXCKINV 0x10000000 | |
34 | #define CLKDVDR_PXCKDLY 0x06000000 | |
35 | #define CLKDVDR_PXCLK_MASK 0x00FF0000 | |
36 | ||
37 | /** | |
38 | * p1022rdk_set_monitor_port: switch the output to a different monitor port | |
39 | */ | |
40 | static void p1022rdk_set_monitor_port(enum fsl_diu_monitor_port port) | |
41 | { | |
42 | if (port != FSL_DIU_PORT_DVI) { | |
43 | pr_err("p1022rdk: unsupported monitor port %i\n", port); | |
44 | return; | |
45 | } | |
46 | } | |
47 | ||
48 | /** | |
49 | * p1022rdk_set_pixel_clock: program the DIU's clock | |
50 | * | |
51 | * @pixclock: the wavelength, in picoseconds, of the clock | |
52 | */ | |
53 | void p1022rdk_set_pixel_clock(unsigned int pixclock) | |
54 | { | |
55 | struct device_node *guts_np = NULL; | |
56 | struct ccsr_guts __iomem *guts; | |
57 | unsigned long freq; | |
58 | u64 temp; | |
59 | u32 pxclk; | |
60 | ||
61 | /* Map the global utilities registers. */ | |
62 | guts_np = of_find_compatible_node(NULL, NULL, "fsl,p1022-guts"); | |
63 | if (!guts_np) { | |
64 | pr_err("p1022rdk: missing global utilties device node\n"); | |
65 | return; | |
66 | } | |
67 | ||
68 | guts = of_iomap(guts_np, 0); | |
69 | of_node_put(guts_np); | |
70 | if (!guts) { | |
71 | pr_err("p1022rdk: could not map global utilties device\n"); | |
72 | return; | |
73 | } | |
74 | ||
75 | /* Convert pixclock from a wavelength to a frequency */ | |
76 | temp = 1000000000000ULL; | |
77 | do_div(temp, pixclock); | |
78 | freq = temp; | |
79 | ||
80 | /* | |
81 | * 'pxclk' is the ratio of the platform clock to the pixel clock. | |
82 | * This number is programmed into the CLKDVDR register, and the valid | |
83 | * range of values is 2-255. | |
84 | */ | |
85 | pxclk = DIV_ROUND_CLOSEST(fsl_get_sys_freq(), freq); | |
86 | pxclk = clamp_t(u32, pxclk, 2, 255); | |
87 | ||
88 | /* Disable the pixel clock, and set it to non-inverted and no delay */ | |
89 | clrbits32(&guts->clkdvdr, | |
90 | CLKDVDR_PXCKEN | CLKDVDR_PXCKDLY | CLKDVDR_PXCLK_MASK); | |
91 | ||
92 | /* Enable the clock and set the pxclk */ | |
93 | setbits32(&guts->clkdvdr, CLKDVDR_PXCKEN | (pxclk << 16)); | |
94 | ||
95 | iounmap(guts); | |
96 | } | |
97 | ||
98 | /** | |
99 | * p1022rdk_valid_monitor_port: set the monitor port for sysfs | |
100 | */ | |
101 | enum fsl_diu_monitor_port | |
102 | p1022rdk_valid_monitor_port(enum fsl_diu_monitor_port port) | |
103 | { | |
104 | return FSL_DIU_PORT_DVI; | |
105 | } | |
106 | ||
107 | #endif | |
108 | ||
109 | void __init p1022_rdk_pic_init(void) | |
110 | { | |
111 | struct mpic *mpic = mpic_alloc(NULL, 0, MPIC_BIG_ENDIAN | | |
112 | MPIC_SINGLE_DEST_CPU, | |
113 | 0, 256, " OpenPIC "); | |
114 | BUG_ON(mpic == NULL); | |
115 | mpic_init(mpic); | |
116 | } | |
117 | ||
118 | /* | |
119 | * Setup the architecture | |
120 | */ | |
121 | static void __init p1022_rdk_setup_arch(void) | |
122 | { | |
34f84b5b TT |
123 | if (ppc_md.progress) |
124 | ppc_md.progress("p1022_rdk_setup_arch()", 0); | |
125 | ||
34f84b5b TT |
126 | #if defined(CONFIG_FB_FSL_DIU) || defined(CONFIG_FB_FSL_DIU_MODULE) |
127 | diu_ops.set_monitor_port = p1022rdk_set_monitor_port; | |
128 | diu_ops.set_pixel_clock = p1022rdk_set_pixel_clock; | |
129 | diu_ops.valid_monitor_port = p1022rdk_valid_monitor_port; | |
130 | #endif | |
131 | ||
132 | mpc85xx_smp_init(); | |
133 | ||
905e75c4 JH |
134 | fsl_pci_assign_primary(); |
135 | ||
136 | swiotlb_detect_4g(); | |
34f84b5b TT |
137 | |
138 | pr_info("Freescale / iVeia P1022 RDK reference board\n"); | |
139 | } | |
140 | ||
905e75c4 | 141 | machine_arch_initcall(p1022_rdk, mpc85xx_common_publish_devices); |
34f84b5b TT |
142 | |
143 | machine_arch_initcall(p1022_rdk, swiotlb_setup_bus_notifier); | |
144 | ||
145 | /* | |
146 | * Called very early, device-tree isn't unflattened | |
147 | */ | |
148 | static int __init p1022_rdk_probe(void) | |
149 | { | |
150 | unsigned long root = of_get_flat_dt_root(); | |
151 | ||
152 | return of_flat_dt_is_compatible(root, "fsl,p1022rdk"); | |
153 | } | |
154 | ||
155 | define_machine(p1022_rdk) { | |
156 | .name = "P1022 RDK", | |
157 | .probe = p1022_rdk_probe, | |
158 | .setup_arch = p1022_rdk_setup_arch, | |
159 | .init_IRQ = p1022_rdk_pic_init, | |
160 | #ifdef CONFIG_PCI | |
161 | .pcibios_fixup_bus = fsl_pcibios_fixup_bus, | |
162 | #endif | |
163 | .get_irq = mpic_get_irq, | |
164 | .restart = fsl_rstcr_restart, | |
165 | .calibrate_decr = generic_calibrate_decr, | |
166 | .progress = udbg_progress, | |
167 | }; |