mirror of
				https://github.com/smaeul/u-boot.git
				synced 2025-10-31 03:58:17 +00:00 
			
		
		
		
	As part of bringing the master branch back in to next, we need to allow for all of these changes to exist here. Reported-by: Jonas Karlman <jonas@kwiboo.se> Signed-off-by: Tom Rini <trini@konsulko.com>
		
			
				
	
	
		
			398 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			398 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| // SPDX-License-Identifier: GPL-2.0+
 | |
| /*
 | |
|  * Copyright (C) 2006-2023  CS GROUP France
 | |
|  */
 | |
| 
 | |
| #include <command.h>
 | |
| #include <dm.h>
 | |
| #include <env.h>
 | |
| #include <env_internal.h>
 | |
| #include <fdt_support.h>
 | |
| #include <hang.h>
 | |
| #include <ioports.h>
 | |
| #include <mpc83xx.h>
 | |
| #include <netdev.h>
 | |
| #include <spi.h>
 | |
| #include <stdarg.h>
 | |
| #include <stdlib.h>
 | |
| 
 | |
| #include <linux/delay.h>
 | |
| #include <linux/immap_qe.h>
 | |
| #include <linux/libfdt.h>
 | |
| #include <linux/log2.h>
 | |
| #include <linux/sizes.h>
 | |
| 
 | |
| #include <asm/io.h>
 | |
| #include <asm/global_data.h>
 | |
| #include <asm/mmu.h>
 | |
| 
 | |
| #include <u-boot/crc.h>
 | |
| 
 | |
| #include "../common/common.h"
 | |
| 
 | |
| DECLARE_GLOBAL_DATA_PTR;
 | |
| 
 | |
| #define ADDR_FPGA_BASE		((unsigned char __iomem *)CONFIG_CPLD_BASE)
 | |
| #define ADDR_FPGA_RESET_G	(ADDR_FPGA_BASE + 0x40)
 | |
| #define ADDR_FPGA_REG_ETAT	(ADDR_FPGA_BASE + 0x42)
 | |
| 
 | |
| #define R_ETAT_PRES_BASE	0x01
 | |
| #define RESET_G_OK		0x08
 | |
| 
 | |
| /* SPI EEPROM parameters */
 | |
| #define MAX_SPI_BYTES	0x28
 | |
| #define EE_OFF_MAC1	0x10
 | |
| #define EE_OFF_MAC2	0x16
 | |
| #define EE_OFF_MAC3	0x1C
 | |
| 
 | |
| static uint upma_table[] = {
 | |
| 	/* Read Single-Beat (RSS) */
 | |
| 	0x00AC0C00, 0x00FC1C40, 0x30FCE045, 0xFFFF0C00,
 | |
| 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
 | |
| 	/* Read Burst (RBS) */
 | |
| 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
 | |
| 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
 | |
| 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
 | |
| 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
 | |
| 	/* Write Single-Beat (WSS) */
 | |
| 	0x00A30C00, 0x00F31C40, 0x3FF3C045, 0xFFFF0C00,
 | |
| 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
 | |
| 	/* Write Burst (WBS) */
 | |
| 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
 | |
| 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
 | |
| 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
 | |
| 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
 | |
| 	/* Refresh Timer (RTS) */
 | |
| 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
 | |
| 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
 | |
| 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
 | |
| 	/* Exception Condition (EXS) */
 | |
| 	0xFFFF0C01, 0xFFFF0C01, 0xFFFF0C01, 0xFFFF0C01,
 | |
| };
 | |
| 
 | |
| const qe_iop_conf_t qe_iop_conf_tab[] = {
 | |
| 	/* ETH3 */
 | |
| 	{1,  0, 1, 0, 1}, /* TxD0 */
 | |
| 	{1,  1, 1, 0, 1}, /* TxD1 */
 | |
| 	{1,  2, 1, 0, 1}, /* TxD2 */
 | |
| 	{1,  3, 1, 0, 1}, /* TxD3 */
 | |
| 	{1,  9, 1, 0, 1}, /* TxER */
 | |
| 	{1, 12, 1, 0, 1}, /* TxEN */
 | |
| 	{3, 24, 2, 0, 1}, /* TxCLK->CLK10 */
 | |
| 
 | |
| 	{1,  4, 2, 0, 1}, /* RxD0 */
 | |
| 	{1,  5, 2, 0, 1}, /* RxD1 */
 | |
| 	{1,  6, 2, 0, 1}, /* RxD2 */
 | |
| 	{1,  7, 2, 0, 1}, /* RxD3 */
 | |
| 	{1,  8, 2, 0, 1}, /* RxER */
 | |
| 	{1, 10, 2, 0, 1}, /* RxDV */
 | |
| 	{0, 13, 2, 0, 1}, /* RxCLK->CLK9 */
 | |
| 	{1, 11, 2, 0, 1}, /* COL */
 | |
| 	{1, 13, 2, 0, 1}, /* CRS */
 | |
| 
 | |
| 	/* ETH4 */
 | |
| 	{1, 18, 1, 0, 1}, /* TxD0 */
 | |
| 	{1, 19, 1, 0, 1}, /* TxD1 */
 | |
| 	{1, 20, 1, 0, 1}, /* TxD2 */
 | |
| 	{1, 21, 1, 0, 1}, /* TxD3 */
 | |
| 	{1, 27, 1, 0, 1}, /* TxER */
 | |
| 	{1, 30, 1, 0, 1}, /* TxEN */
 | |
| 	{3,  6, 2, 0, 1}, /* TxCLK->CLK8 */
 | |
| 
 | |
| 	{1, 22, 2, 0, 1}, /* RxD0 */
 | |
| 	{1, 23, 2, 0, 1}, /* RxD1 */
 | |
| 	{1, 24, 2, 0, 1}, /* RxD2 */
 | |
| 	{1, 25, 2, 0, 1}, /* RxD3 */
 | |
| 	{1, 26, 1, 0, 1}, /* RxER */
 | |
| 	{1, 28, 2, 0, 1}, /* Rx_DV */
 | |
| 	{3, 31, 2, 0, 1}, /* RxCLK->CLK7 */
 | |
| 	{1, 29, 2, 0, 1}, /* COL */
 | |
| 	{1, 31, 2, 0, 1}, /* CRS */
 | |
| 
 | |
| 	{3,  4, 3, 0, 2}, /* MDIO */
 | |
| 	{3,  5, 1, 0, 2}, /* MDC */
 | |
| 
 | |
| 	{0,  0, 0, 0, QE_IOP_TAB_END}, /* END of table */
 | |
| };
 | |
| 
 | |
| void iop_setup_miae(void)
 | |
| {
 | |
| 	immap_t __iomem *im = (immap_t *)CONFIG_SYS_IMMR;
 | |
| 
 | |
| 	/* PORTA configuration */
 | |
| 	out_be32(&im->qepio.ioport[0].pdat, 0x00808000);
 | |
| 	out_be32(&im->qepio.ioport[0].podr, 0x00008000);
 | |
| 	out_be32(&im->qepio.ioport[0].dir1, 0x40800968);
 | |
| 	out_be32(&im->qepio.ioport[0].dir2, 0x650A0896);
 | |
| 	out_be32(&im->qepio.ioport[0].ppar1, 0x40400204);
 | |
| 	out_be32(&im->qepio.ioport[0].ppar2, 0x05050464);
 | |
| 
 | |
| 	/* PORTB configuration */
 | |
| 	out_be32(&im->qepio.ioport[1].pdat, 0x00018000);
 | |
| 	out_be32(&im->qepio.ioport[1].podr, 0x00000000);
 | |
| 	out_be32(&im->qepio.ioport[1].dir1, 0x50A08949);
 | |
| 	out_be32(&im->qepio.ioport[1].dir2, 0x5C0C6890);
 | |
| 	out_be32(&im->qepio.ioport[1].ppar1, 0x50504644);
 | |
| 	out_be32(&im->qepio.ioport[1].ppar2, 0x080800A0);
 | |
| 
 | |
| 	/* PORTC configuration */
 | |
| 	out_be32(&im->qepio.ioport[2].pdat, 0x3D000108);
 | |
| 	out_be32(&im->qepio.ioport[2].podr, 0x00000000);
 | |
| 	out_be32(&im->qepio.ioport[2].dir1, 0x45518000);
 | |
| 	out_be32(&im->qepio.ioport[2].dir2, 0xA8119561);
 | |
| 	out_be32(&im->qepio.ioport[2].ppar1, 0x80008000);
 | |
| 	out_be32(&im->qepio.ioport[2].ppar2, 0x00000000);
 | |
| 
 | |
| 	/* PORTD configuration */
 | |
| 	out_be32(&im->qepio.ioport[3].pdat, 0x1000E000);
 | |
| 	out_be32(&im->qepio.ioport[3].podr, 0x0000E000);
 | |
| 	out_be32(&im->qepio.ioport[3].dir1, 0xFDD20800);
 | |
| 	out_be32(&im->qepio.ioport[3].dir2, 0x54155228);
 | |
| 	out_be32(&im->qepio.ioport[3].ppar1, 0x54A30C00);
 | |
| 	out_be32(&im->qepio.ioport[3].ppar2, 0x00000100);
 | |
| }
 | |
| 
 | |
| void iop_setup_mcr(void)
 | |
| {
 | |
| 	immap_t __iomem *im = (immap_t *)CONFIG_SYS_IMMR;
 | |
| 
 | |
| 	/* PORTA configuration */
 | |
| 	out_be32(&im->qepio.ioport[0].pdat, 0x00808004);
 | |
| 	out_be32(&im->qepio.ioport[0].podr, 0x00000000);
 | |
| 	out_be32(&im->qepio.ioport[0].dir1, 0x40800A68);
 | |
| 	out_be32(&im->qepio.ioport[0].dir2, 0x650A0896);
 | |
| 	out_be32(&im->qepio.ioport[0].ppar1, 0x40400004);
 | |
| 	out_be32(&im->qepio.ioport[0].ppar2, 0x05050444);
 | |
| 
 | |
| 	/* PORTB configuration */
 | |
| 	out_be32(&im->qepio.ioport[1].pdat, 0x00008000);
 | |
| 	out_be32(&im->qepio.ioport[1].podr, 0x00000004);
 | |
| 	out_be32(&im->qepio.ioport[1].dir1, 0x50A08A4A);
 | |
| 	out_be32(&im->qepio.ioport[1].dir2, 0x5C0C6890);
 | |
| 	out_be32(&im->qepio.ioport[1].ppar1, 0x50504444);
 | |
| 	out_be32(&im->qepio.ioport[1].ppar2, 0x08080080);
 | |
| 
 | |
| 	/* PORTC configuration */
 | |
| 	out_be32(&im->qepio.ioport[2].pdat, 0x3D000018);
 | |
| 	out_be32(&im->qepio.ioport[2].podr, 0x00000400);
 | |
| 	out_be32(&im->qepio.ioport[2].dir1, 0x45518000);
 | |
| 	out_be32(&im->qepio.ioport[2].dir2, 0xA8129561);
 | |
| 	out_be32(&im->qepio.ioport[2].ppar1, 0x80008000);
 | |
| 	out_be32(&im->qepio.ioport[2].ppar2, 0x00000000);
 | |
| 
 | |
| 	/* PORTD configuration */
 | |
| 	out_be32(&im->qepio.ioport[3].pdat, 0x1000E000);
 | |
| 	out_be32(&im->qepio.ioport[3].podr, 0x0000E000);
 | |
| 	out_be32(&im->qepio.ioport[3].dir1, 0xFDD20800);
 | |
| 	out_be32(&im->qepio.ioport[3].dir2, 0x54155228);
 | |
| 	out_be32(&im->qepio.ioport[3].ppar1, 0x54A30C00);
 | |
| 	out_be32(&im->qepio.ioport[3].ppar2, 0x00000100);
 | |
| }
 | |
| 
 | |
| static void iop_setup_cmpcpro(void)
 | |
| {
 | |
| 	immap_t __iomem *im = (immap_t *)CONFIG_SYS_IMMR;
 | |
| 
 | |
| 	/* PORTA configuration */
 | |
| 	out_be32(&im->qepio.ioport[0].pdat, 0x00000000);
 | |
| 	out_be32(&im->qepio.ioport[0].podr, 0x00000000);
 | |
| 	out_be32(&im->qepio.ioport[0].dir1, 0x50A84020);
 | |
| 	out_be32(&im->qepio.ioport[0].dir2, 0x00000000);
 | |
| 	out_be32(&im->qepio.ioport[0].ppar1, 0xF0FCC000);
 | |
| 	out_be32(&im->qepio.ioport[0].ppar2, 0x00000000);
 | |
| 
 | |
| 	/* PORTB configuration */
 | |
| 	out_be32(&im->qepio.ioport[1].pdat, 0x00000000);
 | |
| 	out_be32(&im->qepio.ioport[1].podr, 0x00000000);
 | |
| 	out_be32(&im->qepio.ioport[1].dir1, 0x00000000);
 | |
| 	out_be32(&im->qepio.ioport[1].dir2, 0x00006800);
 | |
| 	out_be32(&im->qepio.ioport[1].ppar1, 0x00000000);
 | |
| 	out_be32(&im->qepio.ioport[1].ppar2, 0x00000000);
 | |
| 
 | |
| 	/* PORTC configuration */
 | |
| 	out_be32(&im->qepio.ioport[2].pdat, 0x19000000);
 | |
| 	out_be32(&im->qepio.ioport[2].podr, 0x00000000);
 | |
| 	out_be32(&im->qepio.ioport[2].dir1, 0x01410000);
 | |
| 	out_be32(&im->qepio.ioport[2].dir2, 0xA8009400);
 | |
| 	out_be32(&im->qepio.ioport[2].ppar1, 0x00000000);
 | |
| 	out_be32(&im->qepio.ioport[2].ppar2, 0x00000000);
 | |
| 
 | |
| 	/* PORTD configuration */
 | |
| 	out_be32(&im->qepio.ioport[3].pdat, 0x1000E000);
 | |
| 	out_be32(&im->qepio.ioport[3].podr, 0x0000E000);
 | |
| 	out_be32(&im->qepio.ioport[3].dir1, 0xFD020000);
 | |
| 	out_be32(&im->qepio.ioport[3].dir2, 0x54055000);
 | |
| 	out_be32(&im->qepio.ioport[3].ppar1, 0x54030000);
 | |
| 	out_be32(&im->qepio.ioport[3].ppar2, 0x00000000);
 | |
| }
 | |
| 
 | |
| int board_early_init_r(void)
 | |
| {
 | |
| 	immap_t __iomem *im = (immap_t *)CONFIG_SYS_IMMR;
 | |
| 	fsl_lbc_t *lbus = &im->im_lbc;
 | |
| 
 | |
| 	upmconfig(UPMA, upma_table, ARRAY_SIZE(upma_table));
 | |
| 
 | |
| 	out_be32(&lbus->mamr, 0x00044440);
 | |
| 
 | |
| 	/* configure LBCR register */
 | |
| 	out_be32(&lbus->lbcr, 0x00000500);
 | |
| 	sync();
 | |
| 
 | |
| 	if (in_8(ADDR_FPGA_REG_ETAT) & R_ETAT_PRES_BASE) {
 | |
| 		int i;
 | |
| 
 | |
| 		/* Initialize signal PROG_FPGA_FIRMWARE */
 | |
| 		setbits_be32(&im->qepio.ioport[0].pdat, 0x00008000);
 | |
| 		setbits_be32(&im->qepio.ioport[0].dir2, 0x60000002);
 | |
| 		setbits_be32(&im->qepio.ioport[0].podr, 0x00008000);
 | |
| 
 | |
| 		mdelay(1);
 | |
| 
 | |
| 		/* Now read CPDATA[31] to check if FPGA is loaded */
 | |
| 		if (!in_be32(&im->qepio.ioport[0].pdat) & 0x00000001) {
 | |
| 			printf("Reloading FPGA firmware.\n");
 | |
| 
 | |
| 			clrbits_be32(&im->qepio.ioport[0].pdat, 0x00008000);
 | |
| 			udelay(1);
 | |
| 			setbits_be32(&im->qepio.ioport[0].pdat, 0x00008000);
 | |
| 
 | |
| 			/* Wait 200 msec and check DONE_FPGA_FIRMWARE */
 | |
| 			mdelay(200);
 | |
| 			if (!(in_be32(&im->qepio.ioport[0].pdat) & 0x00000001)) {
 | |
| 				for (;;) {
 | |
| 					printf("error loading firmware.\n");
 | |
| 					mdelay(500);
 | |
| 				}
 | |
| 			}
 | |
| 
 | |
| 			/* Send a reset signal and wait for 20 msec */
 | |
| 			out_8(ADDR_FPGA_RESET_G, in_8(ADDR_FPGA_RESET_G) | RESET_G_OK);
 | |
| 			mdelay(20);
 | |
| 			out_8(ADDR_FPGA_RESET_G, in_8(ADDR_FPGA_RESET_G) & ~RESET_G_OK);
 | |
| 		}
 | |
| 
 | |
| 		/* Wait 300 msec and check the reset state */
 | |
| 		mdelay(300);
 | |
| 		for (i = 0; !(in_8(ADDR_FPGA_REG_ETAT) & RESET_G_OK); i++) {
 | |
| 			for (;;) {
 | |
| 				printf("Could not reset FPGA.\n");
 | |
| 				mdelay(500);
 | |
| 			}
 | |
| 		}
 | |
| 
 | |
| 		iop_setup_common();
 | |
| 
 | |
| 		/* clocks configuration */
 | |
| 		out_be32(&qe_immr->qmx.cmxsi1cr_l, 0x00040004);
 | |
| 		out_be32(&qe_immr->qmx.cmxsi1syr, 0x00000000);
 | |
| 	} else {
 | |
| 		iop_setup_cmpcpro();
 | |
| 	}
 | |
| 
 | |
| 	return 0;
 | |
| }
 | |
| 
 | |
| int dram_init(int board_type)
 | |
| {
 | |
| 	immap_t __iomem *im = (immap_t __iomem *)CONFIG_SYS_IMMR;
 | |
| 
 | |
| 	out_be32(&im->sysconf.ddrlaw[0].bar, CFG_SYS_DDR_SDRAM_BASE & LAWBAR_BAR);
 | |
| 	out_be32(&im->sysconf.ddrlaw[0].ar, LAWAR_EN | ((ilog2(SZ_512M) - 1) & LAWAR_SIZE));
 | |
| 
 | |
| 	out_be32(&im->ddr.sdram_clk_cntl, CFG_SYS_DDR_CLK_CNTL);
 | |
| 	out_be32(&im->ddr.csbnds[0].csbnds, CFG_SYS_DDR_CS0_BNDS);
 | |
| 	out_be32(&im->ddr.cs_config[0], CFG_SYS_DDR_CS0_CONFIG);
 | |
| 
 | |
| 	out_be32(&im->ddr.timing_cfg_0, CFG_SYS_DDR_TIMING_0);
 | |
| 	out_be32(&im->ddr.timing_cfg_1, CFG_SYS_DDR_TIMING_1);
 | |
| 	out_be32(&im->ddr.timing_cfg_2, CFG_SYS_DDR_TIMING_2);
 | |
| 	out_be32(&im->ddr.timing_cfg_3, CFG_SYS_DDR_TIMING_3);
 | |
| 	out_be32(&im->ddr.sdram_cfg, CFG_SYS_DDR_SDRAM_CFG);
 | |
| 	out_be32(&im->ddr.sdram_cfg2, CFG_SYS_DDR_SDRAM_CFG2);
 | |
| 	out_be32(&im->ddr.sdram_mode, CFG_SYS_DDR_MODE);
 | |
| 	out_be32(&im->ddr.sdram_mode2, CFG_SYS_DDR_MODE2);
 | |
| 	out_be32(&im->ddr.sdram_interval, CFG_SYS_DDR_INTERVAL);
 | |
| 	udelay(200);
 | |
| 
 | |
| 	setbits_be32(&im->ddr.sdram_cfg, SDRAM_CFG_MEM_EN);
 | |
| 
 | |
| 	gd->ram_size = SZ_512M;
 | |
| 
 | |
| 	return 0;
 | |
| }
 | |
| 
 | |
| int checkboard(void)
 | |
| {
 | |
| 	printf("Board: ");
 | |
| 
 | |
| 	/* Is a motherboard present ? */
 | |
| 	if (in_8(ADDR_FPGA_REG_ETAT) & R_ETAT_PRES_BASE)
 | |
| 		return checkboard_common();
 | |
| 
 | |
| 	printf("CMPCPRO (CS GROUP)\n");
 | |
| 
 | |
| 	return 0;
 | |
| }
 | |
| 
 | |
| /* Reads MAC addresses from SPI EEPROM */
 | |
| static int setup_mac(void)
 | |
| {
 | |
| 	uchar din[MAX_SPI_BYTES];
 | |
| 	int ret;
 | |
| 	unsigned long ident = 0x08005120;
 | |
| 
 | |
| 	ret = read_eeprom(din, sizeof(din));
 | |
| 	if (ret)
 | |
| 		return ret;
 | |
| 
 | |
| 	if (memcmp(din + EE_OFF_MAC1, &ident, sizeof(ident)) == 0) {
 | |
| 		eth_env_set_enetaddr("ethaddr", din + EE_OFF_MAC1);
 | |
| 		eth_env_set_enetaddr("eth3addr", din + EE_OFF_MAC1);
 | |
| 	}
 | |
| 
 | |
| 	if (memcmp(din + EE_OFF_MAC2, &ident, sizeof(ident)) == 0)
 | |
| 		eth_env_set_enetaddr("eth1addr", din + EE_OFF_MAC2);
 | |
| 
 | |
| 	if (memcmp(din + EE_OFF_MAC3, &ident, sizeof(ident)) == 0)
 | |
| 		eth_env_set_enetaddr("eth2addr", din + EE_OFF_MAC3);
 | |
| 
 | |
| 	return 0;
 | |
| }
 | |
| 
 | |
| int misc_init_r(void)
 | |
| {
 | |
| 	/* we do not modify environment variable area if CRC is false */
 | |
| 	/* Verify if mother board is present */
 | |
| 	if (in_8(ADDR_FPGA_REG_ETAT) & R_ETAT_PRES_BASE) {
 | |
| 		misc_init_r_common();
 | |
| 	} else {
 | |
| 		env_set("config", CFG_BOARD_CMPCXXX);
 | |
| 		env_set("hostname", CFG_BOARD_CMPCXXX);
 | |
| 	}
 | |
| 
 | |
| 	if (setup_mac())
 | |
| 		printf("Error retrieving mac addresses\n");
 | |
| 
 | |
| 	return 0;
 | |
| }
 | |
| 
 | |
| int ft_board_setup(void *blob, struct bd_info *bd)
 | |
| {
 | |
| 	ft_cpu_setup(blob, bd);
 | |
| 
 | |
| 	/* MIAE only */
 | |
| 	if (!(in_8(ADDR_FPGA_REG_ETAT) & R_ETAT_PRES_BASE))
 | |
| 		return 0;
 | |
| 
 | |
| 	return ft_board_setup_common(blob);
 | |
| }
 | |
| 
 | |
| void ft_board_setup_phy3(void)
 | |
| {
 | |
| 	/* switch to phy3 with gpio, we'll only use phy3 */
 | |
| 	immap_t *immr = (immap_t *)CONFIG_SYS_IMMR;
 | |
| 
 | |
| 	setbits_be32(&immr->qepio.ioport[2].pdat, 0x00000400);
 | |
| }
 |