diff options
Diffstat (limited to 'arch/mips/netlogic/xlp/nlm_hal.c')
-rw-r--r-- | arch/mips/netlogic/xlp/nlm_hal.c | 237 |
1 files changed, 202 insertions, 35 deletions
diff --git a/arch/mips/netlogic/xlp/nlm_hal.c b/arch/mips/netlogic/xlp/nlm_hal.c index 87560e4db35f..56c50ba43c9b 100644 --- a/arch/mips/netlogic/xlp/nlm_hal.c +++ b/arch/mips/netlogic/xlp/nlm_hal.c | |||
@@ -44,6 +44,7 @@ | |||
44 | #include <asm/netlogic/haldefs.h> | 44 | #include <asm/netlogic/haldefs.h> |
45 | #include <asm/netlogic/xlp-hal/iomap.h> | 45 | #include <asm/netlogic/xlp-hal/iomap.h> |
46 | #include <asm/netlogic/xlp-hal/xlp.h> | 46 | #include <asm/netlogic/xlp-hal/xlp.h> |
47 | #include <asm/netlogic/xlp-hal/bridge.h> | ||
47 | #include <asm/netlogic/xlp-hal/pic.h> | 48 | #include <asm/netlogic/xlp-hal/pic.h> |
48 | #include <asm/netlogic/xlp-hal/sys.h> | 49 | #include <asm/netlogic/xlp-hal/sys.h> |
49 | 50 | ||
@@ -64,6 +65,7 @@ int nlm_irq_to_irt(int irq) | |||
64 | uint64_t pcibase; | 65 | uint64_t pcibase; |
65 | int devoff, irt; | 66 | int devoff, irt; |
66 | 67 | ||
68 | devoff = 0; | ||
67 | switch (irq) { | 69 | switch (irq) { |
68 | case PIC_UART_0_IRQ: | 70 | case PIC_UART_0_IRQ: |
69 | devoff = XLP_IO_UART0_OFFSET(0); | 71 | devoff = XLP_IO_UART0_OFFSET(0); |
@@ -71,44 +73,68 @@ int nlm_irq_to_irt(int irq) | |||
71 | case PIC_UART_1_IRQ: | 73 | case PIC_UART_1_IRQ: |
72 | devoff = XLP_IO_UART1_OFFSET(0); | 74 | devoff = XLP_IO_UART1_OFFSET(0); |
73 | break; | 75 | break; |
74 | case PIC_EHCI_0_IRQ: | ||
75 | devoff = XLP_IO_USB_EHCI0_OFFSET(0); | ||
76 | break; | ||
77 | case PIC_EHCI_1_IRQ: | ||
78 | devoff = XLP_IO_USB_EHCI1_OFFSET(0); | ||
79 | break; | ||
80 | case PIC_OHCI_0_IRQ: | ||
81 | devoff = XLP_IO_USB_OHCI0_OFFSET(0); | ||
82 | break; | ||
83 | case PIC_OHCI_1_IRQ: | ||
84 | devoff = XLP_IO_USB_OHCI1_OFFSET(0); | ||
85 | break; | ||
86 | case PIC_OHCI_2_IRQ: | ||
87 | devoff = XLP_IO_USB_OHCI2_OFFSET(0); | ||
88 | break; | ||
89 | case PIC_OHCI_3_IRQ: | ||
90 | devoff = XLP_IO_USB_OHCI3_OFFSET(0); | ||
91 | break; | ||
92 | case PIC_MMC_IRQ: | 76 | case PIC_MMC_IRQ: |
93 | devoff = XLP_IO_SD_OFFSET(0); | 77 | devoff = XLP_IO_SD_OFFSET(0); |
94 | break; | 78 | break; |
95 | case PIC_I2C_0_IRQ: | 79 | case PIC_I2C_0_IRQ: /* I2C will be fixed up */ |
96 | devoff = XLP_IO_I2C0_OFFSET(0); | ||
97 | break; | ||
98 | case PIC_I2C_1_IRQ: | 80 | case PIC_I2C_1_IRQ: |
99 | devoff = XLP_IO_I2C1_OFFSET(0); | 81 | case PIC_I2C_2_IRQ: |
82 | case PIC_I2C_3_IRQ: | ||
83 | if (cpu_is_xlpii()) | ||
84 | devoff = XLP2XX_IO_I2C_OFFSET(0); | ||
85 | else | ||
86 | devoff = XLP_IO_I2C0_OFFSET(0); | ||
100 | break; | 87 | break; |
101 | default: | 88 | default: |
102 | devoff = 0; | 89 | if (cpu_is_xlpii()) { |
103 | break; | 90 | switch (irq) { |
91 | /* XLP2XX has three XHCI USB controller */ | ||
92 | case PIC_2XX_XHCI_0_IRQ: | ||
93 | devoff = XLP2XX_IO_USB_XHCI0_OFFSET(0); | ||
94 | break; | ||
95 | case PIC_2XX_XHCI_1_IRQ: | ||
96 | devoff = XLP2XX_IO_USB_XHCI1_OFFSET(0); | ||
97 | break; | ||
98 | case PIC_2XX_XHCI_2_IRQ: | ||
99 | devoff = XLP2XX_IO_USB_XHCI2_OFFSET(0); | ||
100 | break; | ||
101 | } | ||
102 | } else { | ||
103 | switch (irq) { | ||
104 | case PIC_EHCI_0_IRQ: | ||
105 | devoff = XLP_IO_USB_EHCI0_OFFSET(0); | ||
106 | break; | ||
107 | case PIC_EHCI_1_IRQ: | ||
108 | devoff = XLP_IO_USB_EHCI1_OFFSET(0); | ||
109 | break; | ||
110 | case PIC_OHCI_0_IRQ: | ||
111 | devoff = XLP_IO_USB_OHCI0_OFFSET(0); | ||
112 | break; | ||
113 | case PIC_OHCI_1_IRQ: | ||
114 | devoff = XLP_IO_USB_OHCI1_OFFSET(0); | ||
115 | break; | ||
116 | case PIC_OHCI_2_IRQ: | ||
117 | devoff = XLP_IO_USB_OHCI2_OFFSET(0); | ||
118 | break; | ||
119 | case PIC_OHCI_3_IRQ: | ||
120 | devoff = XLP_IO_USB_OHCI3_OFFSET(0); | ||
121 | break; | ||
122 | } | ||
123 | } | ||
104 | } | 124 | } |
105 | 125 | ||
106 | if (devoff != 0) { | 126 | if (devoff != 0) { |
107 | pcibase = nlm_pcicfg_base(devoff); | 127 | pcibase = nlm_pcicfg_base(devoff); |
108 | irt = nlm_read_reg(pcibase, XLP_PCI_IRTINFO_REG) & 0xffff; | 128 | irt = nlm_read_reg(pcibase, XLP_PCI_IRTINFO_REG) & 0xffff; |
109 | /* HW bug, I2C 1 irt entry is off by one */ | 129 | /* HW weirdness, I2C IRT entry has to be fixed up */ |
110 | if (irq == PIC_I2C_1_IRQ) | 130 | switch (irq) { |
111 | irt = irt + 1; | 131 | case PIC_I2C_1_IRQ: |
132 | irt = irt + 1; break; | ||
133 | case PIC_I2C_2_IRQ: | ||
134 | irt = irt + 2; break; | ||
135 | case PIC_I2C_3_IRQ: | ||
136 | irt = irt + 3; break; | ||
137 | } | ||
112 | } else if (irq >= PIC_PCIE_LINK_0_IRQ && irq <= PIC_PCIE_LINK_3_IRQ) { | 138 | } else if (irq >= PIC_PCIE_LINK_0_IRQ && irq <= PIC_PCIE_LINK_3_IRQ) { |
113 | /* HW bug, PCI IRT entries are bad on early silicon, fix */ | 139 | /* HW bug, PCI IRT entries are bad on early silicon, fix */ |
114 | irt = PIC_IRT_PCIE_LINK_INDEX(irq - PIC_PCIE_LINK_0_IRQ); | 140 | irt = PIC_IRT_PCIE_LINK_INDEX(irq - PIC_PCIE_LINK_0_IRQ); |
@@ -126,19 +152,160 @@ unsigned int nlm_get_core_frequency(int node, int core) | |||
126 | 152 | ||
127 | sysbase = nlm_get_node(node)->sysbase; | 153 | sysbase = nlm_get_node(node)->sysbase; |
128 | rstval = nlm_read_sys_reg(sysbase, SYS_POWER_ON_RESET_CFG); | 154 | rstval = nlm_read_sys_reg(sysbase, SYS_POWER_ON_RESET_CFG); |
129 | dfsval = nlm_read_sys_reg(sysbase, SYS_CORE_DFS_DIV_VALUE); | 155 | if (cpu_is_xlpii()) { |
130 | pll_divf = ((rstval >> 10) & 0x7f) + 1; | 156 | num = 1000000ULL * (400 * 3 + 100 * (rstval >> 26)); |
131 | pll_divr = ((rstval >> 8) & 0x3) + 1; | 157 | denom = 3; |
132 | ext_div = ((rstval >> 30) & 0x3) + 1; | 158 | } else { |
133 | dfs_div = ((dfsval >> (core * 4)) & 0xf) + 1; | 159 | dfsval = nlm_read_sys_reg(sysbase, SYS_CORE_DFS_DIV_VALUE); |
134 | 160 | pll_divf = ((rstval >> 10) & 0x7f) + 1; | |
135 | num = 800000000ULL * pll_divf; | 161 | pll_divr = ((rstval >> 8) & 0x3) + 1; |
136 | denom = 3 * pll_divr * ext_div * dfs_div; | 162 | ext_div = ((rstval >> 30) & 0x3) + 1; |
163 | dfs_div = ((dfsval >> (core * 4)) & 0xf) + 1; | ||
164 | |||
165 | num = 800000000ULL * pll_divf; | ||
166 | denom = 3 * pll_divr * ext_div * dfs_div; | ||
167 | } | ||
137 | do_div(num, denom); | 168 | do_div(num, denom); |
138 | return (unsigned int)num; | 169 | return (unsigned int)num; |
139 | } | 170 | } |
140 | 171 | ||
172 | /* Calculate Frequency to the PIC from PLL. | ||
173 | * freq_out = ( ref_freq/2 * (6 + ctrl2[7:0]) + ctrl2[20:8]/2^13 ) / | ||
174 | * ((2^ctrl0[7:5]) * Table(ctrl0[26:24])) | ||
175 | */ | ||
176 | static unsigned int nlm_2xx_get_pic_frequency(int node) | ||
177 | { | ||
178 | u32 ctrl_val0, ctrl_val2, vco_post_div, pll_post_div; | ||
179 | u32 mdiv, fdiv, pll_out_freq_den, reg_select, ref_div, pic_div; | ||
180 | u64 ref_clk, sysbase, pll_out_freq_num, ref_clk_select; | ||
181 | |||
182 | sysbase = nlm_get_node(node)->sysbase; | ||
183 | |||
184 | /* Find ref_clk_base */ | ||
185 | ref_clk_select = | ||
186 | (nlm_read_sys_reg(sysbase, SYS_POWER_ON_RESET_CFG) >> 18) & 0x3; | ||
187 | switch (ref_clk_select) { | ||
188 | case 0: | ||
189 | ref_clk = 200000000ULL; | ||
190 | ref_div = 3; | ||
191 | break; | ||
192 | case 1: | ||
193 | ref_clk = 100000000ULL; | ||
194 | ref_div = 1; | ||
195 | break; | ||
196 | case 2: | ||
197 | ref_clk = 125000000ULL; | ||
198 | ref_div = 1; | ||
199 | break; | ||
200 | case 3: | ||
201 | ref_clk = 400000000ULL; | ||
202 | ref_div = 3; | ||
203 | break; | ||
204 | } | ||
205 | |||
206 | /* Find the clock source PLL device for PIC */ | ||
207 | reg_select = (nlm_read_sys_reg(sysbase, SYS_CLK_DEV_SEL) >> 22) & 0x3; | ||
208 | switch (reg_select) { | ||
209 | case 0: | ||
210 | ctrl_val0 = nlm_read_sys_reg(sysbase, SYS_PLL_CTRL0); | ||
211 | ctrl_val2 = nlm_read_sys_reg(sysbase, SYS_PLL_CTRL2); | ||
212 | break; | ||
213 | case 1: | ||
214 | ctrl_val0 = nlm_read_sys_reg(sysbase, SYS_PLL_CTRL0_DEVX(0)); | ||
215 | ctrl_val2 = nlm_read_sys_reg(sysbase, SYS_PLL_CTRL2_DEVX(0)); | ||
216 | break; | ||
217 | case 2: | ||
218 | ctrl_val0 = nlm_read_sys_reg(sysbase, SYS_PLL_CTRL0_DEVX(1)); | ||
219 | ctrl_val2 = nlm_read_sys_reg(sysbase, SYS_PLL_CTRL2_DEVX(1)); | ||
220 | break; | ||
221 | case 3: | ||
222 | ctrl_val0 = nlm_read_sys_reg(sysbase, SYS_PLL_CTRL0_DEVX(2)); | ||
223 | ctrl_val2 = nlm_read_sys_reg(sysbase, SYS_PLL_CTRL2_DEVX(2)); | ||
224 | break; | ||
225 | } | ||
226 | |||
227 | vco_post_div = (ctrl_val0 >> 5) & 0x7; | ||
228 | pll_post_div = (ctrl_val0 >> 24) & 0x7; | ||
229 | mdiv = ctrl_val2 & 0xff; | ||
230 | fdiv = (ctrl_val2 >> 8) & 0xfff; | ||
231 | |||
232 | /* Find PLL post divider value */ | ||
233 | switch (pll_post_div) { | ||
234 | case 1: | ||
235 | pll_post_div = 2; | ||
236 | break; | ||
237 | case 3: | ||
238 | pll_post_div = 4; | ||
239 | break; | ||
240 | case 7: | ||
241 | pll_post_div = 8; | ||
242 | break; | ||
243 | case 6: | ||
244 | pll_post_div = 16; | ||
245 | break; | ||
246 | case 0: | ||
247 | default: | ||
248 | pll_post_div = 1; | ||
249 | break; | ||
250 | } | ||
251 | |||
252 | fdiv = fdiv/(1 << 13); | ||
253 | pll_out_freq_num = ((ref_clk >> 1) * (6 + mdiv)) + fdiv; | ||
254 | pll_out_freq_den = (1 << vco_post_div) * pll_post_div * 3; | ||
255 | |||
256 | if (pll_out_freq_den > 0) | ||
257 | do_div(pll_out_freq_num, pll_out_freq_den); | ||
258 | |||
259 | /* PIC post divider, which happens after PLL */ | ||
260 | pic_div = (nlm_read_sys_reg(sysbase, SYS_CLK_DEV_DIV) >> 22) & 0x3; | ||
261 | do_div(pll_out_freq_num, 1 << pic_div); | ||
262 | |||
263 | return pll_out_freq_num; | ||
264 | } | ||
265 | |||
266 | unsigned int nlm_get_pic_frequency(int node) | ||
267 | { | ||
268 | if (cpu_is_xlpii()) | ||
269 | return nlm_2xx_get_pic_frequency(node); | ||
270 | else | ||
271 | return 133333333; | ||
272 | } | ||
273 | |||
141 | unsigned int nlm_get_cpu_frequency(void) | 274 | unsigned int nlm_get_cpu_frequency(void) |
142 | { | 275 | { |
143 | return nlm_get_core_frequency(0, 0); | 276 | return nlm_get_core_frequency(0, 0); |
144 | } | 277 | } |
278 | |||
279 | /* | ||
280 | * Fills upto 8 pairs of entries containing the DRAM map of a node | ||
281 | * if n < 0, get dram map for all nodes | ||
282 | */ | ||
283 | int xlp_get_dram_map(int n, uint64_t *dram_map) | ||
284 | { | ||
285 | uint64_t bridgebase, base, lim; | ||
286 | uint32_t val; | ||
287 | int i, node, rv; | ||
288 | |||
289 | /* Look only at mapping on Node 0, we don't handle crazy configs */ | ||
290 | bridgebase = nlm_get_bridge_regbase(0); | ||
291 | rv = 0; | ||
292 | for (i = 0; i < 8; i++) { | ||
293 | val = nlm_read_bridge_reg(bridgebase, | ||
294 | BRIDGE_DRAM_NODE_TRANSLN(i)); | ||
295 | node = (val >> 1) & 0x3; | ||
296 | if (n >= 0 && n != node) | ||
297 | continue; | ||
298 | val = nlm_read_bridge_reg(bridgebase, BRIDGE_DRAM_BAR(i)); | ||
299 | val = (val >> 12) & 0xfffff; | ||
300 | base = (uint64_t) val << 20; | ||
301 | val = nlm_read_bridge_reg(bridgebase, BRIDGE_DRAM_LIMIT(i)); | ||
302 | val = (val >> 12) & 0xfffff; | ||
303 | if (val == 0) /* BAR not used */ | ||
304 | continue; | ||
305 | lim = ((uint64_t)val + 1) << 20; | ||
306 | dram_map[rv] = base; | ||
307 | dram_map[rv + 1] = lim; | ||
308 | rv += 2; | ||
309 | } | ||
310 | return rv; | ||
311 | } | ||