| /* Board specific functions for those embedded 8xx boards that do | |
| * not have boot monitor support for board information. | |
| * | |
| * This program is free software; you can redistribute it and/or modify it | |
| * under the terms of the GNU General Public License as published by the | |
| * Free Software Foundation; either version 2 of the License, or (at your | |
| * option) any later version. | |
| */ | |
| #include <linux/types.h> | |
| #include <linux/string.h> | |
| #include <asm/reg.h> | |
| #ifdef CONFIG_8xx | |
| #include <asm/mpc8xx.h> | |
| #endif | |
| #ifdef CONFIG_8260 | |
| #include <asm/mpc8260.h> | |
| #include <asm/immap_cpm2.h> | |
| #endif | |
| #ifdef CONFIG_40x | |
| #include <asm/io.h> | |
| #endif | |
| #ifdef CONFIG_XILINX_VIRTEX | |
| #include <platforms/4xx/xparameters/xparameters.h> | |
| #endif | |
| extern unsigned long timebase_period_ns; | |
| /* For those boards that don't provide one. | |
| */ | |
| #if !defined(CONFIG_MBX) | |
| static bd_t bdinfo; | |
| #endif | |
| /* IIC functions. | |
| * These are just the basic master read/write operations so we can | |
| * examine serial EEPROM. | |
| */ | |
| extern void iic_read(uint devaddr, u_char *buf, uint offset, uint count); | |
| /* Supply a default Ethernet address for those eval boards that don't | |
| * ship with one. This is an address from the MBX board I have, so | |
| * it is unlikely you will find it on your network. | |
| */ | |
| static ushort def_enet_addr[] = { 0x0800, 0x3e26, 0x1559 }; | |
| #if defined(CONFIG_MBX) | |
| /* The MBX hands us a pretty much ready to go board descriptor. This | |
| * is where the idea started in the first place. | |
| */ | |
| void | |
| embed_config(bd_t **bdp) | |
| { | |
| u_char *mp; | |
| u_char eebuf[128]; | |
| int i = 8; | |
| bd_t *bd; | |
| bd = *bdp; | |
| /* Read the first 128 bytes of the EEPROM. There is more, | |
| * but this is all we need. | |
| */ | |
| iic_read(0xa4, eebuf, 0, 128); | |
| /* All we are looking for is the Ethernet MAC address. The | |
| * first 8 bytes are 'MOTOROLA', so check for part of that. | |
| * Next, the VPD describes a MAC 'packet' as being of type 08 | |
| * and size 06. So we look for that and the MAC must follow. | |
| * If there are more than one, we still only care about the first. | |
| * If it's there, assume we have a valid MAC address. If not, | |
| * grab our default one. | |
| */ | |
| if ((*(uint *)eebuf) == 0x4d4f544f) { | |
| while (i < 127 && !(eebuf[i] == 0x08 && eebuf[i + 1] == 0x06)) | |
| i += eebuf[i + 1] + 2; /* skip this packet */ | |
| if (i == 127) /* Couldn't find. */ | |
| mp = (u_char *)def_enet_addr; | |
| else | |
| mp = &eebuf[i + 2]; | |
| } | |
| else | |
| mp = (u_char *)def_enet_addr; | |
| for (i=0; i<6; i++) | |
| bd->bi_enetaddr[i] = *mp++; | |
| /* The boot rom passes these to us in MHz. Linux now expects | |
| * them to be in Hz. | |
| */ | |
| bd->bi_intfreq *= 1000000; | |
| bd->bi_busfreq *= 1000000; | |
| /* Stuff a baud rate here as well. | |
| */ | |
| bd->bi_baudrate = 9600; | |
| } | |
| #endif /* CONFIG_MBX */ | |
| #if defined(CONFIG_RPXLITE) || defined(CONFIG_RPXCLASSIC) || \ | |
| defined(CONFIG_RPX8260) || defined(CONFIG_EP405) | |
| /* Helper functions for Embedded Planet boards. | |
| */ | |
| /* Because I didn't find anything that would do this....... | |
| */ | |
| u_char | |
| aschex_to_byte(u_char *cp) | |
| { | |
| u_char byte, c; | |
| c = *cp++; | |
| if ((c >= 'A') && (c <= 'F')) { | |
| c -= 'A'; | |
| c += 10; | |
| } else if ((c >= 'a') && (c <= 'f')) { | |
| c -= 'a'; | |
| c += 10; | |
| } else | |
| c -= '0'; | |
| byte = c * 16; | |
| c = *cp; | |
| if ((c >= 'A') && (c <= 'F')) { | |
| c -= 'A'; | |
| c += 10; | |
| } else if ((c >= 'a') && (c <= 'f')) { | |
| c -= 'a'; | |
| c += 10; | |
| } else | |
| c -= '0'; | |
| byte += c; | |
| return(byte); | |
| } | |
| static void | |
| rpx_eth(bd_t *bd, u_char *cp) | |
| { | |
| int i; | |
| for (i=0; i<6; i++) { | |
| bd->bi_enetaddr[i] = aschex_to_byte(cp); | |
| cp += 2; | |
| } | |
| } | |
| #ifdef CONFIG_RPX8260 | |
| static uint | |
| rpx_baseten(u_char *cp) | |
| { | |
| uint retval; | |
| retval = 0; | |
| while (*cp != '\n') { | |
| retval *= 10; | |
| retval += (*cp) - '0'; | |
| cp++; | |
| } | |
| return(retval); | |
| } | |
| #endif | |
| #if defined(CONFIG_RPXLITE) || defined(CONFIG_RPXCLASSIC) | |
| static void | |
| rpx_brate(bd_t *bd, u_char *cp) | |
| { | |
| uint rate; | |
| rate = 0; | |
| while (*cp != '\n') { | |
| rate *= 10; | |
| rate += (*cp) - '0'; | |
| cp++; | |
| } | |
| bd->bi_baudrate = rate * 100; | |
| } | |
| static void | |
| rpx_cpuspeed(bd_t *bd, u_char *cp) | |
| { | |
| uint num, den; | |
| num = den = 0; | |
| while (*cp != '\n') { | |
| num *= 10; | |
| num += (*cp) - '0'; | |
| cp++; | |
| if (*cp == '/') { | |
| cp++; | |
| den = (*cp) - '0'; | |
| break; | |
| } | |
| } | |
| /* I don't know why the RPX just can't state the actual | |
| * CPU speed..... | |
| */ | |
| if (den) { | |
| num /= den; | |
| num *= den; | |
| } | |
| bd->bi_intfreq = bd->bi_busfreq = num * 1000000; | |
| /* The 8xx can only run a maximum 50 MHz bus speed (until | |
| * Motorola changes this :-). Greater than 50 MHz parts | |
| * run internal/2 for bus speed. | |
| */ | |
| if (num > 50) | |
| bd->bi_busfreq /= 2; | |
| } | |
| #endif | |
| #if defined(CONFIG_RPXLITE) || defined(CONFIG_RPXCLASSIC) || defined(CONFIG_EP405) | |
| static void | |
| rpx_memsize(bd_t *bd, u_char *cp) | |
| { | |
| uint size; | |
| size = 0; | |
| while (*cp != '\n') { | |
| size *= 10; | |
| size += (*cp) - '0'; | |
| cp++; | |
| } | |
| bd->bi_memsize = size * 1024 * 1024; | |
| } | |
| #endif /* LITE || CLASSIC || EP405 */ | |
| #if defined(CONFIG_EP405) | |
| static void | |
| rpx_nvramsize(bd_t *bd, u_char *cp) | |
| { | |
| uint size; | |
| size = 0; | |
| while (*cp != '\n') { | |
| size *= 10; | |
| size += (*cp) - '0'; | |
| cp++; | |
| } | |
| bd->bi_nvramsize = size * 1024; | |
| } | |
| #endif /* CONFIG_EP405 */ | |
| #endif /* Embedded Planet boards */ | |
| #if defined(CONFIG_RPXLITE) || defined(CONFIG_RPXCLASSIC) | |
| /* Read the EEPROM on the RPX-Lite board. | |
| */ | |
| void | |
| embed_config(bd_t **bdp) | |
| { | |
| u_char eebuf[256], *cp; | |
| bd_t *bd; | |
| /* Read the first 256 bytes of the EEPROM. I think this | |
| * is really all there is, and I hope if it gets bigger the | |
| * info we want is still up front. | |
| */ | |
| bd = &bdinfo; | |
| *bdp = bd; | |
| #if 1 | |
| iic_read(0xa8, eebuf, 0, 128); | |
| iic_read(0xa8, &eebuf[128], 128, 128); | |
| /* We look for two things, the Ethernet address and the | |
| * serial baud rate. The records are separated by | |
| * newlines. | |
| */ | |
| cp = eebuf; | |
| for (;;) { | |
| if (*cp == 'E') { | |
| cp++; | |
| if (*cp == 'A') { | |
| cp += 2; | |
| rpx_eth(bd, cp); | |
| } | |
| } | |
| if (*cp == 'S') { | |
| cp++; | |
| if (*cp == 'B') { | |
| cp += 2; | |
| rpx_brate(bd, cp); | |
| } | |
| } | |
| if (*cp == 'D') { | |
| cp++; | |
| if (*cp == '1') { | |
| cp += 2; | |
| rpx_memsize(bd, cp); | |
| } | |
| } | |
| if (*cp == 'H') { | |
| cp++; | |
| if (*cp == 'Z') { | |
| cp += 2; | |
| rpx_cpuspeed(bd, cp); | |
| } | |
| } | |
| /* Scan to the end of the record. | |
| */ | |
| while ((*cp != '\n') && (*cp != 0xff)) | |
| cp++; | |
| /* If the next character is a 0 or ff, we are done. | |
| */ | |
| cp++; | |
| if ((*cp == 0) || (*cp == 0xff)) | |
| break; | |
| } | |
| bd->bi_memstart = 0; | |
| #else | |
| /* For boards without initialized EEPROM. | |
| */ | |
| bd->bi_memstart = 0; | |
| bd->bi_memsize = (8 * 1024 * 1024); | |
| bd->bi_intfreq = 48000000; | |
| bd->bi_busfreq = 48000000; | |
| bd->bi_baudrate = 9600; | |
| #endif | |
| } | |
| #endif /* RPXLITE || RPXCLASSIC */ | |
| #ifdef CONFIG_BSEIP | |
| /* Build a board information structure for the BSE ip-Engine. | |
| * There is more to come since we will add some environment | |
| * variables and a function to read them. | |
| */ | |
| void | |
| embed_config(bd_t **bdp) | |
| { | |
| u_char *cp; | |
| int i; | |
| bd_t *bd; | |
| bd = &bdinfo; | |
| *bdp = bd; | |
| /* Baud rate and processor speed will eventually come | |
| * from the environment variables. | |
| */ | |
| bd->bi_baudrate = 9600; | |
| /* Get the Ethernet station address from the Flash ROM. | |
| */ | |
| cp = (u_char *)0xfe003ffa; | |
| for (i=0; i<6; i++) { | |
| bd->bi_enetaddr[i] = *cp++; | |
| } | |
| /* The rest of this should come from the environment as well. | |
| */ | |
| bd->bi_memstart = 0; | |
| bd->bi_memsize = (16 * 1024 * 1024); | |
| bd->bi_intfreq = 48000000; | |
| bd->bi_busfreq = 48000000; | |
| } | |
| #endif /* BSEIP */ | |
| #ifdef CONFIG_FADS | |
| /* Build a board information structure for the FADS. | |
| */ | |
| void | |
| embed_config(bd_t **bdp) | |
| { | |
| u_char *cp; | |
| int i; | |
| bd_t *bd; | |
| bd = &bdinfo; | |
| *bdp = bd; | |
| /* Just fill in some known values. | |
| */ | |
| bd->bi_baudrate = 9600; | |
| /* Use default enet. | |
| */ | |
| cp = (u_char *)def_enet_addr; | |
| for (i=0; i<6; i++) { | |
| bd->bi_enetaddr[i] = *cp++; | |
| } | |
| bd->bi_memstart = 0; | |
| bd->bi_memsize = (8 * 1024 * 1024); | |
| bd->bi_intfreq = 40000000; | |
| bd->bi_busfreq = 40000000; | |
| } | |
| #endif /* FADS */ | |
| #ifdef CONFIG_8260 | |
| /* Compute 8260 clock values if the rom doesn't provide them. | |
| */ | |
| static unsigned char bus2core_8260[] = { | |
| /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */ | |
| 3, 2, 2, 2, 4, 4, 5, 9, 6, 11, 8, 10, 3, 12, 7, 2, | |
| 6, 5, 13, 2, 14, 4, 15, 2, 3, 11, 8, 10, 16, 12, 7, 2, | |
| }; | |
| static void | |
| clk_8260(bd_t *bd) | |
| { | |
| uint scmr, vco_out, clkin; | |
| uint plldf, pllmf, corecnf; | |
| volatile cpm2_map_t *ip; | |
| ip = (cpm2_map_t *)CPM_MAP_ADDR; | |
| scmr = ip->im_clkrst.car_scmr; | |
| /* The clkin is always bus frequency. | |
| */ | |
| clkin = bd->bi_busfreq; | |
| /* Collect the bits from the scmr. | |
| */ | |
| plldf = (scmr >> 12) & 1; | |
| pllmf = scmr & 0xfff; | |
| corecnf = (scmr >> 24) &0x1f; | |
| /* This is arithmetic from the 8260 manual. | |
| */ | |
| vco_out = clkin / (plldf + 1); | |
| vco_out *= 2 * (pllmf + 1); | |
| bd->bi_vco = vco_out; /* Save for later */ | |
| bd->bi_cpmfreq = vco_out / 2; /* CPM Freq, in MHz */ | |
| bd->bi_intfreq = bd->bi_busfreq * bus2core_8260[corecnf] / 2; | |
| /* Set Baud rate divisor. The power up default is divide by 16, | |
| * but we set it again here in case it was changed. | |
| */ | |
| ip->im_clkrst.car_sccr = 1; /* DIV 16 BRG */ | |
| bd->bi_brgfreq = vco_out / 16; | |
| } | |
| static unsigned char bus2core_8280[] = { | |
| /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */ | |
| 3, 2, 2, 2, 4, 4, 5, 9, 6, 11, 8, 10, 3, 12, 7, 2, | |
| 6, 5, 13, 2, 14, 2, 15, 2, 3, 2, 2, 2, 16, 2, 2, 2, | |
| }; | |
| static void | |
| clk_8280(bd_t *bd) | |
| { | |
| uint scmr, main_clk, clkin; | |
| uint pllmf, corecnf; | |
| volatile cpm2_map_t *ip; | |
| ip = (cpm2_map_t *)CPM_MAP_ADDR; | |
| scmr = ip->im_clkrst.car_scmr; | |
| /* The clkin is always bus frequency. | |
| */ | |
| clkin = bd->bi_busfreq; | |
| /* Collect the bits from the scmr. | |
| */ | |
| pllmf = scmr & 0xf; | |
| corecnf = (scmr >> 24) & 0x1f; | |
| /* This is arithmetic from the 8280 manual. | |
| */ | |
| main_clk = clkin * (pllmf + 1); | |
| bd->bi_cpmfreq = main_clk / 2; /* CPM Freq, in MHz */ | |
| bd->bi_intfreq = bd->bi_busfreq * bus2core_8280[corecnf] / 2; | |
| /* Set Baud rate divisor. The power up default is divide by 16, | |
| * but we set it again here in case it was changed. | |
| */ | |
| ip->im_clkrst.car_sccr = (ip->im_clkrst.car_sccr & 0x3) | 0x1; | |
| bd->bi_brgfreq = main_clk / 16; | |
| } | |
| #endif | |
| #ifdef CONFIG_SBC82xx | |
| void | |
| embed_config(bd_t **bdp) | |
| { | |
| u_char *cp; | |
| int i; | |
| bd_t *bd; | |
| unsigned long pvr; | |
| bd = *bdp; | |
| bd = &bdinfo; | |
| *bdp = bd; | |
| bd->bi_baudrate = 9600; | |
| bd->bi_memsize = 256 * 1024 * 1024; /* just a guess */ | |
| cp = (void*)SBC82xx_MACADDR_NVRAM_SCC1; | |
| memcpy(bd->bi_enetaddr, cp, 6); | |
| /* can busfreq be calculated? */ | |
| pvr = mfspr(SPRN_PVR); | |
| if ((pvr & 0xffff0000) == 0x80820000) { | |
| bd->bi_busfreq = 100000000; | |
| clk_8280(bd); | |
| } else { | |
| bd->bi_busfreq = 66000000; | |
| clk_8260(bd); | |
| } | |
| } | |
| #endif /* SBC82xx */ | |
| #if defined(CONFIG_EST8260) || defined(CONFIG_TQM8260) | |
| void | |
| embed_config(bd_t **bdp) | |
| { | |
| u_char *cp; | |
| int i; | |
| bd_t *bd; | |
| bd = *bdp; | |
| #if 0 | |
| /* This is actually provided by my boot rom. I have it | |
| * here for those people that may load the kernel with | |
| * a JTAG/COP tool and not the rom monitor. | |
| */ | |
| bd->bi_baudrate = 115200; | |
| bd->bi_intfreq = 200000000; | |
| bd->bi_busfreq = 66666666; | |
| bd->bi_cpmfreq = 66666666; | |
| bd->bi_brgfreq = 33333333; | |
| bd->bi_memsize = 16 * 1024 * 1024; | |
| #else | |
| /* The boot rom passes these to us in MHz. Linux now expects | |
| * them to be in Hz. | |
| */ | |
| bd->bi_intfreq *= 1000000; | |
| bd->bi_busfreq *= 1000000; | |
| bd->bi_cpmfreq *= 1000000; | |
| bd->bi_brgfreq *= 1000000; | |
| #endif | |
| cp = (u_char *)def_enet_addr; | |
| for (i=0; i<6; i++) { | |
| bd->bi_enetaddr[i] = *cp++; | |
| } | |
| } | |
| #endif /* EST8260 */ | |
| #ifdef CONFIG_SBS8260 | |
| void | |
| embed_config(bd_t **bdp) | |
| { | |
| u_char *cp; | |
| int i; | |
| bd_t *bd; | |
| /* This should provided by the boot rom. | |
| */ | |
| bd = &bdinfo; | |
| *bdp = bd; | |
| bd->bi_baudrate = 9600; | |
| bd->bi_memsize = 64 * 1024 * 1024; | |
| /* Set all of the clocks. We have to know the speed of the | |
| * external clock. The development board had 66 MHz. | |
| */ | |
| bd->bi_busfreq = 66666666; | |
| clk_8260(bd); | |
| /* I don't know how to compute this yet. | |
| */ | |
| bd->bi_intfreq = 133000000; | |
| cp = (u_char *)def_enet_addr; | |
| for (i=0; i<6; i++) { | |
| bd->bi_enetaddr[i] = *cp++; | |
| } | |
| } | |
| #endif /* SBS8260 */ | |
| #ifdef CONFIG_RPX8260 | |
| void | |
| embed_config(bd_t **bdp) | |
| { | |
| u_char *cp, *keyvals; | |
| int i; | |
| bd_t *bd; | |
| keyvals = (u_char *)*bdp; | |
| bd = &bdinfo; | |
| *bdp = bd; | |
| /* This is almost identical to the RPX-Lite/Classic functions | |
| * on the 8xx boards. It would be nice to have a key lookup | |
| * function in a string, but the format of all of the fields | |
| * is slightly different. | |
| */ | |
| cp = keyvals; | |
| for (;;) { | |
| if (*cp == 'E') { | |
| cp++; | |
| if (*cp == 'A') { | |
| cp += 2; | |
| rpx_eth(bd, cp); | |
| } | |
| } | |
| if (*cp == 'S') { | |
| cp++; | |
| if (*cp == 'B') { | |
| cp += 2; | |
| bd->bi_baudrate = rpx_baseten(cp); | |
| } | |
| } | |
| if (*cp == 'D') { | |
| cp++; | |
| if (*cp == '1') { | |
| cp += 2; | |
| bd->bi_memsize = rpx_baseten(cp) * 1024 * 1024; | |
| } | |
| } | |
| if (*cp == 'X') { | |
| cp++; | |
| if (*cp == 'T') { | |
| cp += 2; | |
| bd->bi_busfreq = rpx_baseten(cp); | |
| } | |
| } | |
| if (*cp == 'N') { | |
| cp++; | |
| if (*cp == 'V') { | |
| cp += 2; | |
| bd->bi_nvsize = rpx_baseten(cp) * 1024 * 1024; | |
| } | |
| } | |
| /* Scan to the end of the record. | |
| */ | |
| while ((*cp != '\n') && (*cp != 0xff)) | |
| cp++; | |
| /* If the next character is a 0 or ff, we are done. | |
| */ | |
| cp++; | |
| if ((*cp == 0) || (*cp == 0xff)) | |
| break; | |
| } | |
| bd->bi_memstart = 0; | |
| /* The memory size includes both the 60x and local bus DRAM. | |
| * I don't want to use the local bus DRAM for real memory, | |
| * so subtract it out. It would be nice if they were separate | |
| * keys. | |
| */ | |
| bd->bi_memsize -= 32 * 1024 * 1024; | |
| /* Set all of the clocks. We have to know the speed of the | |
| * external clock. | |
| */ | |
| clk_8260(bd); | |
| /* I don't know how to compute this yet. | |
| */ | |
| bd->bi_intfreq = 200000000; | |
| } | |
| #endif /* RPX6 for testing */ | |
| #ifdef CONFIG_ADS8260 | |
| void | |
| embed_config(bd_t **bdp) | |
| { | |
| u_char *cp; | |
| int i; | |
| bd_t *bd; | |
| /* This should provided by the boot rom. | |
| */ | |
| bd = &bdinfo; | |
| *bdp = bd; | |
| bd->bi_baudrate = 9600; | |
| bd->bi_memsize = 16 * 1024 * 1024; | |
| /* Set all of the clocks. We have to know the speed of the | |
| * external clock. The development board had 66 MHz. | |
| */ | |
| bd->bi_busfreq = 66666666; | |
| clk_8260(bd); | |
| /* I don't know how to compute this yet. | |
| */ | |
| bd->bi_intfreq = 200000000; | |
| cp = (u_char *)def_enet_addr; | |
| for (i=0; i<6; i++) { | |
| bd->bi_enetaddr[i] = *cp++; | |
| } | |
| } | |
| #endif /* ADS8260 */ | |
| #ifdef CONFIG_WILLOW | |
| void | |
| embed_config(bd_t **bdp) | |
| { | |
| u_char *cp; | |
| int i; | |
| bd_t *bd; | |
| /* Willow has Open Firmware....I should learn how to get this | |
| * information from it. | |
| */ | |
| bd = &bdinfo; | |
| *bdp = bd; | |
| bd->bi_baudrate = 9600; | |
| bd->bi_memsize = 32 * 1024 * 1024; | |
| /* Set all of the clocks. We have to know the speed of the | |
| * external clock. The development board had 66 MHz. | |
| */ | |
| bd->bi_busfreq = 66666666; | |
| clk_8260(bd); | |
| /* I don't know how to compute this yet. | |
| */ | |
| bd->bi_intfreq = 200000000; | |
| cp = (u_char *)def_enet_addr; | |
| for (i=0; i<6; i++) { | |
| bd->bi_enetaddr[i] = *cp++; | |
| } | |
| } | |
| #endif /* WILLOW */ | |
| #if defined(CONFIG_XILINX_ML300) || defined(CONFIG_XILINX_ML403) | |
| void | |
| embed_config(bd_t ** bdp) | |
| { | |
| static const unsigned long line_size = 32; | |
| static const unsigned long congruence_classes = 256; | |
| unsigned long addr; | |
| unsigned long dccr; | |
| bd_t *bd; | |
| /* | |
| * Invalidate the data cache if the data cache is turned off. | |
| * - The 405 core does not invalidate the data cache on power-up | |
| * or reset but does turn off the data cache. We cannot assume | |
| * that the cache contents are valid. | |
| * - If the data cache is turned on this must have been done by | |
| * a bootloader and we assume that the cache contents are | |
| * valid. | |
| */ | |
| __asm__("mfdccr %0": "=r" (dccr)); | |
| if (dccr == 0) { | |
| for (addr = 0; | |
| addr < (congruence_classes * line_size); | |
| addr += line_size) { | |
| __asm__("dccci 0,%0": :"b"(addr)); | |
| } | |
| } | |
| bd = &bdinfo; | |
| *bdp = bd; | |
| bd->bi_memsize = XPAR_DDR_0_SIZE; | |
| bd->bi_intfreq = XPAR_CORE_CLOCK_FREQ_HZ; | |
| bd->bi_busfreq = XPAR_PLB_CLOCK_FREQ_HZ; | |
| bd->bi_pci_busfreq = XPAR_PCI_0_CLOCK_FREQ_HZ; | |
| timebase_period_ns = 1000000000 / bd->bi_tbfreq; | |
| /* see bi_tbfreq definition in arch/ppc/platforms/4xx/xilinx_ml300.h */ | |
| } | |
| #endif /* CONFIG_XILINX_ML300 || CONFIG_XILINX_ML403 */ | |
| #ifdef CONFIG_IBM_OPENBIOS | |
| /* This could possibly work for all treeboot roms. | |
| */ | |
| #if defined(CONFIG_BUBINGA) | |
| #define BOARD_INFO_VECTOR 0xFFF80B50 /* openbios 1.19 moved this vector down - armin */ | |
| #else | |
| #define BOARD_INFO_VECTOR 0xFFFE0B50 | |
| #endif | |
| void | |
| embed_config(bd_t **bdp) | |
| { | |
| u_char *cp; | |
| int i; | |
| bd_t *bd, *treeboot_bd; | |
| bd_t *(*get_board_info)(void) = | |
| (bd_t *(*)(void))(*(unsigned long *)BOARD_INFO_VECTOR); | |
| #if !defined(CONFIG_STB03xxx) | |
| /* shut down the Ethernet controller that the boot rom | |
| * sometimes leaves running. | |
| */ | |
| mtdcr(DCRN_MALCR(DCRN_MAL_BASE), MALCR_MMSR); /* 1st reset MAL */ | |
| while (mfdcr(DCRN_MALCR(DCRN_MAL_BASE)) & MALCR_MMSR) {}; /* wait for the reset */ | |
| out_be32((volatile u32*)EMAC0_BASE,0x20000000); /* then reset EMAC */ | |
| #endif | |
| bd = &bdinfo; | |
| *bdp = bd; | |
| if ((treeboot_bd = get_board_info()) != NULL) { | |
| memcpy(bd, treeboot_bd, sizeof(bd_t)); | |
| } | |
| else { | |
| /* Hmmm...better try to stuff some defaults. | |
| */ | |
| bd->bi_memsize = 16 * 1024 * 1024; | |
| cp = (u_char *)def_enet_addr; | |
| for (i=0; i<6; i++) { | |
| /* I should probably put different ones here, | |
| * hopefully only one is used. | |
| */ | |
| bd->BD_EMAC_ADDR(0,i) = *cp; | |
| #ifdef CONFIG_PCI | |
| bd->bi_pci_enetaddr[i] = *cp++; | |
| #endif | |
| } | |
| bd->bi_tbfreq = 200 * 1000 * 1000; | |
| bd->bi_intfreq = 200000000; | |
| bd->bi_busfreq = 100000000; | |
| #ifdef CONFIG_PCI | |
| bd->bi_pci_busfreq = 66666666; | |
| #endif | |
| } | |
| /* Yeah, this look weird, but on Redwood 4 they are | |
| * different object in the structure. Sincr Redwwood 5 | |
| * and Redwood 6 use OpenBIOS, it requires a special value. | |
| */ | |
| #if defined(CONFIG_REDWOOD_5) || defined (CONFIG_REDWOOD_6) | |
| bd->bi_tbfreq = 27 * 1000 * 1000; | |
| #endif | |
| timebase_period_ns = 1000000000 / bd->bi_tbfreq; | |
| } | |
| #endif /* CONFIG_IBM_OPENBIOS */ | |
| #ifdef CONFIG_EP405 | |
| #include <linux/serial_reg.h> | |
| void | |
| embed_config(bd_t **bdp) | |
| { | |
| u32 chcr0; | |
| u_char *cp; | |
| bd_t *bd; | |
| /* Different versions of the PlanetCore firmware vary in how | |
| they set up the serial port - in particular whether they | |
| use the internal or external serial clock for UART0. Make | |
| sure the UART is in a known state. */ | |
| /* FIXME: We should use the board's 11.0592MHz external serial | |
| clock - it will be more accurate for serial rates. For | |
| now, however the baud rates in ep405.h are for the internal | |
| clock. */ | |
| chcr0 = mfdcr(DCRN_CHCR0); | |
| if ( (chcr0 & 0x1fff) != 0x103e ) { | |
| mtdcr(DCRN_CHCR0, (chcr0 & 0xffffe000) | 0x103e); | |
| /* The following tricks serial_init() into resetting the baud rate */ | |
| writeb(0, UART0_IO_BASE + UART_LCR); | |
| } | |
| /* We haven't seen actual problems with the EP405 leaving the | |
| * EMAC running (as we have on Walnut). But the registers | |
| * suggest it may not be left completely quiescent. Reset it | |
| * just to be sure. */ | |
| mtdcr(DCRN_MALCR(DCRN_MAL_BASE), MALCR_MMSR); /* 1st reset MAL */ | |
| while (mfdcr(DCRN_MALCR(DCRN_MAL_BASE)) & MALCR_MMSR) {}; /* wait for the reset */ | |
| out_be32((unsigned *)EMAC0_BASE,0x20000000); /* then reset EMAC */ | |
| bd = &bdinfo; | |
| *bdp = bd; | |
| #if 1 | |
| cp = (u_char *)0xF0000EE0; | |
| for (;;) { | |
| if (*cp == 'E') { | |
| cp++; | |
| if (*cp == 'A') { | |
| cp += 2; | |
| rpx_eth(bd, cp); | |
| } | |
| } | |
| if (*cp == 'D') { | |
| cp++; | |
| if (*cp == '1') { | |
| cp += 2; | |
| rpx_memsize(bd, cp); | |
| } | |
| } | |
| if (*cp == 'N') { | |
| cp++; | |
| if (*cp == 'V') { | |
| cp += 2; | |
| rpx_nvramsize(bd, cp); | |
| } | |
| } | |
| while ((*cp != '\n') && (*cp != 0xff)) | |
| cp++; | |
| cp++; | |
| if ((*cp == 0) || (*cp == 0xff)) | |
| break; | |
| } | |
| bd->bi_intfreq = 200000000; | |
| bd->bi_busfreq = 100000000; | |
| bd->bi_pci_busfreq= 33000000 ; | |
| #else | |
| bd->bi_memsize = 64000000; | |
| bd->bi_intfreq = 200000000; | |
| bd->bi_busfreq = 100000000; | |
| bd->bi_pci_busfreq= 33000000 ; | |
| #endif | |
| } | |
| #endif |