1
2
3
4
5
6
7
8
9
10#include "ops.h"
11#include "io.h"
12#include "dcr.h"
13#include "stdio.h"
14#include "4xx.h"
15#include "44x.h"
16#include "cuboot.h"
17
18#define TARGET_4xx
19#include "ppcboot.h"
20
21static bd_t bd;
22
23#define CPR_PERD0_SPIDV_MASK 0x000F0000
24
25#define PLLC_SRC_MASK 0x20000000
26
27#define PLLD_FBDV_MASK 0x1F000000
28#define PLLD_FWDVA_MASK 0x000F0000
29#define PLLD_FWDVB_MASK 0x00000700
30
31#define PRIMAD_CPUDV_MASK 0x0F000000
32#define PRIMAD_PLBDV_MASK 0x000F0000
33#define PRIMAD_OPBDV_MASK 0x00000F00
34#define PRIMAD_EBCDV_MASK 0x0000000F
35
36#define PERD0_PWMDV_MASK 0xFF000000
37#define PERD0_SPIDV_MASK 0x000F0000
38#define PERD0_U0DV_MASK 0x0000FF00
39#define PERD0_U1DV_MASK 0x000000FF
40
41static void get_clocks(void)
42{
43 unsigned long sysclk, cpr_plld, cpr_pllc, cpr_primad, plloutb, i;
44 unsigned long pllFwdDiv, pllFwdDivB, pllFbkDiv, pllPlbDiv, pllExtBusDiv;
45 unsigned long pllOpbDiv, freqEBC, freqUART, freqOPB;
46 unsigned long div;
47 unsigned long umin;
48 unsigned short diff;
49 unsigned long udiv;
50 unsigned short idiff;
51 unsigned short ibdiv;
52 unsigned long est;
53 unsigned long baud;
54 void *np;
55
56
57 sysclk = (in_8((unsigned char *)0x80000000) == 0xc) ? 66666666 : 33333000;
58
59
60
61
62 cpr_plld = CPR0_READ(DCRN_CPR0_PLLD);
63 cpr_pllc = CPR0_READ(DCRN_CPR0_PLLC);
64
65
66
67
68 pllFwdDiv = ((cpr_plld & PLLD_FWDVA_MASK) >> 16);
69
70
71
72
73 pllFwdDivB = ((cpr_plld & PLLD_FWDVB_MASK) >> 8);
74 if (pllFwdDivB == 0)
75 pllFwdDivB = 8;
76
77
78
79
80 pllFbkDiv = ((cpr_plld & PLLD_FBDV_MASK) >> 24);
81 if (pllFbkDiv == 0)
82 pllFbkDiv = 256;
83
84
85
86
87 cpr_primad = CPR0_READ(DCRN_CPR0_PRIMAD);
88
89
90
91
92 pllPlbDiv = ((cpr_primad & PRIMAD_PLBDV_MASK) >> 16);
93 if (pllPlbDiv == 0)
94 pllPlbDiv = 16;
95
96
97
98
99 pllExtBusDiv = (cpr_primad & PRIMAD_EBCDV_MASK);
100 if (pllExtBusDiv == 0)
101 pllExtBusDiv = 16;
102
103
104
105
106 pllOpbDiv = ((cpr_primad & PRIMAD_OPBDV_MASK) >> 8);
107 if (pllOpbDiv == 0)
108 pllOpbDiv = 16;
109
110
111
112
113
114 freqOPB = (sysclk *pllFbkDiv) /pllOpbDiv;
115
116 freqEBC = (sysclk * pllFbkDiv) / pllExtBusDiv;
117
118 plloutb = ((sysclk * ((cpr_pllc & PLLC_SRC_MASK) ?
119 pllFwdDivB : pllFwdDiv) *
120 pllFbkDiv) / pllFwdDivB);
121
122 np = find_node_by_alias("serial0");
123 if (getprop(np, "current-speed", &baud, sizeof(baud)) != sizeof(baud))
124 fatal("no current-speed property\n\r");
125
126 udiv = 256;
127 div = plloutb / (16 * baud);
128 umin = (plloutb / freqOPB) << 1;
129 diff = 256;
130
131
132
133
134
135 for (i = 256; i > umin; i--) {
136 ibdiv = div / i;
137 est = i * ibdiv;
138 idiff = (est > div) ? (est-div) : (div-est);
139 if (idiff == 0) {
140 udiv = i;
141 break;
142 } else if (idiff < diff) {
143 udiv = i;
144 diff = idiff;
145 }
146 }
147 freqUART = plloutb / udiv;
148
149 dt_fixup_cpu_clocks(bd.bi_procfreq, bd.bi_intfreq, bd.bi_plb_busfreq);
150 dt_fixup_clock("/plb/ebc", freqEBC);
151 dt_fixup_clock("/plb/opb", freqOPB);
152 dt_fixup_clock("/plb/opb/serial@ef600300", freqUART);
153 dt_fixup_clock("/plb/opb/serial@ef600400", freqUART);
154}
155
156static void acadia_fixups(void)
157{
158 dt_fixup_memory(bd.bi_memstart, bd.bi_memsize);
159 get_clocks();
160 dt_fixup_mac_address_by_alias("ethernet0", bd.bi_enetaddr);
161}
162
163void platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
164 unsigned long r6, unsigned long r7)
165{
166 CUBOOT_INIT();
167 platform_ops.fixups = acadia_fixups;
168 platform_ops.exit = ibm40x_dbcr_reset;
169 fdt_init(_dtb_start);
170 serial_console_init();
171}
172