Esempio n. 1
0
/**
 * Get clock rate based on the clock type.
 *
 * @param node  - CPU node number
 * @param clock - Enumeration of the clock type.
 * @return      - return the clock rate.
 */
uint64_t cvmx_clock_get_rate_node(int node, cvmx_clock_t clock)
{
	const uint64_t REF_CLOCK = 50000000;

#ifdef CVMX_BUILD_FOR_UBOOT
	uint64_t rate_eclk = 0;
	uint64_t rate_sclk = 0;
	uint64_t rate_dclk = 0;
#endif

	if (cvmx_unlikely(!rate_eclk)) {
		/* Note: The order of these checks is important.
		 ** octeon_has_feature(OCTEON_FEATURE_PCIE) is true for both 6XXX
		 ** and 52XX/56XX, so OCTEON_FEATURE_NPEI _must_ be checked first */
		if (octeon_has_feature(OCTEON_FEATURE_NPEI)) {
			cvmx_npei_dbg_data_t npei_dbg_data;
			npei_dbg_data.u64 = cvmx_read_csr(CVMX_PEXP_NPEI_DBG_DATA);
			rate_eclk = REF_CLOCK * npei_dbg_data.s.c_mul;
			rate_sclk = rate_eclk;
		} else if (OCTEON_IS_OCTEON3()) {
			cvmx_rst_boot_t rst_boot;
			rst_boot.u64 = cvmx_read_csr_node(node, CVMX_RST_BOOT);
			rate_eclk = REF_CLOCK * rst_boot.s.c_mul;
			rate_sclk = REF_CLOCK * rst_boot.s.pnr_mul;
		} else if (octeon_has_feature(OCTEON_FEATURE_PCIE)) {
			cvmx_mio_rst_boot_t mio_rst_boot;
			mio_rst_boot.u64 = cvmx_read_csr(CVMX_MIO_RST_BOOT);
			rate_eclk = REF_CLOCK * mio_rst_boot.s.c_mul;
			rate_sclk = REF_CLOCK * mio_rst_boot.s.pnr_mul;
		} else {
			cvmx_dbg_data_t dbg_data;
			dbg_data.u64 = cvmx_read_csr(CVMX_DBG_DATA);
			rate_eclk = REF_CLOCK * dbg_data.s.c_mul;
			rate_sclk = rate_eclk;
		}
	}

	switch (clock) {
	case CVMX_CLOCK_SCLK:
	case CVMX_CLOCK_TIM:
	case CVMX_CLOCK_IPD:
		return rate_sclk;

	case CVMX_CLOCK_RCLK:
	case CVMX_CLOCK_CORE:
		return rate_eclk;

	case CVMX_CLOCK_DDR:
#if !defined(CVMX_BUILD_FOR_LINUX_HOST) && !defined(CVMX_BUILD_FOR_TOOLCHAIN)
		if (cvmx_unlikely(!rate_dclk))
			rate_dclk = cvmx_sysinfo_get()->dram_data_rate_hz;
#endif
		return rate_dclk;
	}

	cvmx_dprintf("cvmx_clock_get_rate: Unknown clock type\n");
	return 0;
}
/*
 * Set MII/RGMII link based on mode.
 *
 * @param port   interface port to set the link.
 * @param link_info  Link status
 * @param mode   0 = MII, 1 = RGMII mode
 *
 * @return       0 on success and 1 on failure
 */
int cvmx_agl_link_set(int port, cvmx_helper_link_info_t link_info, int mode)
{
	cvmx_agl_gmx_prtx_cfg_t agl_gmx_prtx;

	/* Disable GMX before we make any changes. */
	agl_gmx_prtx.u64 = cvmx_read_csr(CVMX_AGL_GMX_PRTX_CFG(port));
	agl_gmx_prtx.s.en = 0;
	agl_gmx_prtx.s.tx_en = 0;
	agl_gmx_prtx.s.rx_en = 0;
	cvmx_write_csr(CVMX_AGL_GMX_PRTX_CFG(port), agl_gmx_prtx.u64);

	if (OCTEON_IS_MODEL(OCTEON_CN6XXX) || OCTEON_IS_OCTEON3()) {
		uint64_t one_second = cvmx_clock_get_rate(CVMX_CLOCK_CORE);
		/* Wait for GMX to be idle */
		if (CVMX_WAIT_FOR_FIELD64(CVMX_AGL_GMX_PRTX_CFG(port),
					  cvmx_agl_gmx_prtx_cfg_t, rx_idle,
					  ==, 1, one_second)
		    || CVMX_WAIT_FOR_FIELD64(CVMX_AGL_GMX_PRTX_CFG(port),
					     cvmx_agl_gmx_prtx_cfg_t, tx_idle,
					     ==, 1, one_second)) {
			cvmx_dprintf("AGL%d: Timeout waiting for GMX to be idle\n", port);
			return -1;
		}
	}
Esempio n. 3
0
/**
 * @INTERNAL
 * Probe a RGMII interface and determine the number of ports
 * connected to it. The RGMII interface should still be down
 * after this call.
 *
 * @param interface Interface to probe
 *
 * @return Number of ports on the interface. Zero to disable.
 */
int __cvmx_helper_agl_probe(int interface)
{
	int port = cvmx_helper_agl_get_port(interface);
	union cvmx_agl_gmx_bist gmx_bist;
	union cvmx_agl_gmx_prtx_cfg gmx_prtx_cfg;
	union cvmx_agl_prtx_ctl agl_prtx_ctl;
	uint64_t clock_scale;
	int result;

	result = __cvmx_helper_agl_enumerate(interface);
	if (result == 0)
		return 0;

	/* Check BIST status */
	gmx_bist.u64 = cvmx_read_csr(CVMX_AGL_GMX_BIST);
	if (gmx_bist.u64)
		cvmx_warn("Managment port AGL failed BIST (0x%016llx) on AGL%d\n",
			  CAST64(gmx_bist.u64), port);

	/* Disable the external input/output */
	gmx_prtx_cfg.u64 = cvmx_read_csr(CVMX_AGL_GMX_PRTX_CFG(port));
        gmx_prtx_cfg.s.en = 0;
	cvmx_write_csr(CVMX_AGL_GMX_PRTX_CFG(port), gmx_prtx_cfg.u64);

	/* Set the rgx_ref_clk MUX with AGL_PRTx_CTL[REFCLK_SEL]. Default value
	   is 0 (RGMII REFCLK). Recommended to use RGMII RXC(1) or sclk/4 (2)
	   to save cost.
	 */

	/* MII clocks counts are based on the 125Mhz reference, so our
	 * delays need to be scaled to match the core clock rate. The
	 * "+1" is to make sure rounding always waits a little too
	 * long. FIXME.
	 */
	clock_scale = cvmx_clock_get_rate(CVMX_CLOCK_CORE) / 125000000 + 1;

	agl_prtx_ctl.u64 = cvmx_read_csr(CVMX_AGL_PRTX_CTL(port));
	agl_prtx_ctl.s.clkrst = 0;
	agl_prtx_ctl.s.dllrst = 0;
	agl_prtx_ctl.s.clktx_byp = 0;


	if (OCTEON_IS_MODEL(OCTEON_CN70XX)) {
		agl_prtx_ctl.s.refclk_sel = 0;
		agl_prtx_ctl.s.clkrx_set =
			cvmx_helper_get_agl_rx_clock_skew(interface, port);
		agl_prtx_ctl.s.clkrx_byp =
			cvmx_helper_get_agl_rx_clock_delay_bypass(interface,
								  port);
	}
	cvmx_write_csr(CVMX_AGL_PRTX_CTL(port), agl_prtx_ctl.u64);
	/* Force write out before wait */
	cvmx_read_csr(CVMX_AGL_PRTX_CTL(port));
	/*
	 * Wait for the DLL to lock. External 125 MHz reference clock must be
	 * stable at this point.
	 */
	cvmx_wait(256 * clock_scale);

	/* Enable the componsation controller */
	agl_prtx_ctl.u64 = cvmx_read_csr(CVMX_AGL_PRTX_CTL(port));
	agl_prtx_ctl.s.drv_byp = 0;
	cvmx_write_csr(CVMX_AGL_PRTX_CTL(port), agl_prtx_ctl.u64);
	/* Force write out before wait */
	cvmx_read_csr(CVMX_AGL_PRTX_CTL(port));

	if (!OCTEON_IS_OCTEON3()) {
		/* Enable the interface */
		agl_prtx_ctl.u64 = cvmx_read_csr(CVMX_AGL_PRTX_CTL(port));
		agl_prtx_ctl.s.enable = 1;
		cvmx_write_csr(CVMX_AGL_PRTX_CTL(port), agl_prtx_ctl.u64);
		/* Read the value back to force the previous write */
		agl_prtx_ctl.u64 = cvmx_read_csr(CVMX_AGL_PRTX_CTL(port));
	}

	/* Enable the compensation controller */
	agl_prtx_ctl.u64 = cvmx_read_csr(CVMX_AGL_PRTX_CTL(port));
	agl_prtx_ctl.s.comp = 1;
	cvmx_write_csr(CVMX_AGL_PRTX_CTL(port), agl_prtx_ctl.u64);
	/* Force write out before wait */
	cvmx_read_csr(CVMX_AGL_PRTX_CTL(port));

	/* for componsation state to lock. */
	cvmx_wait(1024 * clock_scale);

	return result;
}
Esempio n. 4
0
/**
 * Initialize the QLM layer
 */
void cvmx_qlm_init(void)
{
	int qlm;
	int qlm_jtag_length;
	char *qlm_jtag_name = "cvmx_qlm_jtag";
	int qlm_jtag_size = CVMX_QLM_JTAG_UINT32 * 8 * sizeof(uint32_t);
	static uint64_t qlm_base = 0;
	const cvmx_bootmem_named_block_desc_t *desc;

	if (OCTEON_IS_OCTEON3())
		return;

#ifndef CVMX_BUILD_FOR_LINUX_HOST
	/* Skip actual JTAG accesses on simulator */
	if (cvmx_sysinfo_get()->board_type == CVMX_BOARD_TYPE_SIM)
		return;
#endif

	qlm_jtag_length = cvmx_qlm_jtag_get_length();

	if (sizeof(uint32_t) * qlm_jtag_length > (int)sizeof(__cvmx_qlm_jtag_xor_ref[0]) * 8) {
		cvmx_dprintf("ERROR: cvmx_qlm_init: JTAG chain larger than XOR ref size\n");
		return;
	}

	/* No need to initialize the initial JTAG state if cvmx_qlm_jtag
	   named block is already created. */
	if ((desc = cvmx_bootmem_find_named_block(qlm_jtag_name)) != NULL) {
#ifdef CVMX_BUILD_FOR_LINUX_HOST
		char buffer[qlm_jtag_size];

		octeon_remote_read_mem(buffer, desc->base_addr, qlm_jtag_size);
		memcpy(__cvmx_qlm_jtag_xor_ref, buffer, qlm_jtag_size);
#else
		__cvmx_qlm_jtag_xor_ref = cvmx_phys_to_ptr(desc->base_addr);
#endif
		/* Initialize the internal JTAG */
		cvmx_helper_qlm_jtag_init();
		return;
	}

	/* Create named block to store the initial JTAG state. */
	qlm_base = cvmx_bootmem_phy_named_block_alloc(qlm_jtag_size, 0, 0, 128, qlm_jtag_name, CVMX_BOOTMEM_FLAG_END_ALLOC);

	if (qlm_base == -1ull) {
		cvmx_dprintf("ERROR: cvmx_qlm_init: Error in creating %s named block\n", qlm_jtag_name);
		return;
	}
#ifndef CVMX_BUILD_FOR_LINUX_HOST
	__cvmx_qlm_jtag_xor_ref = cvmx_phys_to_ptr(qlm_base);
#endif
	memset(__cvmx_qlm_jtag_xor_ref, 0, qlm_jtag_size);

	/* Initialize the internal JTAG */
	cvmx_helper_qlm_jtag_init();

	/* Read the XOR defaults for the JTAG chain */
	for (qlm = 0; qlm < cvmx_qlm_get_num(); qlm++) {
		int i;
		int num_lanes = cvmx_qlm_get_lanes(qlm);
		/* Shift all zeros in the chain to make sure all fields are at
		   reset defaults */
		cvmx_helper_qlm_jtag_shift_zeros(qlm, qlm_jtag_length * num_lanes);
		cvmx_helper_qlm_jtag_update(qlm);

		/* Capture the reset defaults */
		cvmx_helper_qlm_jtag_capture(qlm);
		/* Save the reset defaults. This will shift out too much data, but
		   the extra zeros don't hurt anything */
		for (i = 0; i < CVMX_QLM_JTAG_UINT32; i++)
			__cvmx_qlm_jtag_xor_ref[qlm][i] = cvmx_helper_qlm_jtag_shift(qlm, 32, 0);
	}

#ifdef CVMX_BUILD_FOR_LINUX_HOST
	/* Update the initial state for oct-remote utils. */
	{
		char buffer[qlm_jtag_size];

		memcpy(buffer, &__cvmx_qlm_jtag_xor_ref, qlm_jtag_size);
		octeon_remote_write_mem(qlm_base, buffer, qlm_jtag_size);
	}
#endif

	/* Apply all QLM errata workarounds. */
	__cvmx_qlm_speed_tweak();
	__cvmx_qlm_pcie_idle_dac_tweak();
}
/* Version of octeon_model_get_string() that takes buffer as argument, as
** running early in u-boot static/global variables don't work when running from
** flash
*/
const char *octeon_model_get_string_buffer(uint32_t chip_id, char *buffer)
{
	const char *family;
	const char *core_model;
	char pass[4];
#ifndef CVMX_BUILD_FOR_UBOOT
	int clock_mhz;
#endif
	const char *suffix;
	cvmx_l2d_fus3_t fus3;
	int num_cores;
	cvmx_mio_fus_dat2_t fus_dat2;
	cvmx_mio_fus_dat3_t fus_dat3;
	char fuse_model[10];
	char fuse_suffix[4] = {0};
	uint64_t fuse_data = 0;

	fus3.u64 = 0;
	if (OCTEON_IS_MODEL(OCTEON_CN3XXX) || OCTEON_IS_MODEL(OCTEON_CN5XXX))
		fus3.u64 = cvmx_read_csr(CVMX_L2D_FUS3);
	fus_dat2.u64 = cvmx_read_csr(CVMX_MIO_FUS_DAT2);
	fus_dat3.u64 = cvmx_read_csr(CVMX_MIO_FUS_DAT3);
	if (OCTEON_IS_MODEL(OCTEON_CN78XX))
		num_cores = cvmx_pop(cvmx_read_csr(CVMX_CIU3_FUSE));
	else
		num_cores = cvmx_pop(cvmx_read_csr(CVMX_CIU_FUSE));

	/* Make sure the non existent devices look disabled */
	switch ((chip_id >> 8) & 0xff) {
	case 6:		/* CN50XX */
	case 2:		/* CN30XX */
		fus_dat3.s.nodfa_dte = 1;
		fus_dat3.s.nozip = 1;
		break;
	case 4:		/* CN57XX or CN56XX */
		fus_dat3.s.nodfa_dte = 1;
		break;
	default:
		break;
	}

	/* Make a guess at the suffix */
	/* NSP = everything */
	/* EXP = No crypto */
	/* SCP = No DFA, No zip */
	/* CP = No DFA, No crypto, No zip */
	if (fus_dat3.s.nodfa_dte) {
		if (fus_dat2.s.nocrypto)
			suffix = "CP";
		else
			suffix = "SCP";
	} else if (fus_dat2.s.nocrypto)
		suffix = "EXP";
	else
		suffix = "NSP";

	/* Assume pass number is encoded using <5:3><2:0>. Exceptions will be
	   fixed later */
	sprintf(pass, "%d.%d", (int)((chip_id >> 3) & 7) + 1, (int)chip_id & 7);

	/* Use the number of cores to determine the last 2 digits of the model
	   number. There are some exceptions that are fixed later */
	switch (num_cores) {
	case 32:
		core_model = "80";
		break;
	case 24:
		core_model = "70";
		break;
	case 16:
		core_model = "60";
		break;
	case 15:
		core_model = "58";
		break;
	case 14:
		core_model = "55";
		break;
	case 13:
		core_model = "52";
		break;
	case 12:
		core_model = "50";
		break;
	case 11:
		core_model = "48";
		break;
	case 10:
		core_model = "45";
		break;
	case 9:
		core_model = "42";
		break;
	case 8:
		core_model = "40";
		break;
	case 7:
		core_model = "38";
		break;
	case 6:
		core_model = "34";
		break;
	case 5:
		core_model = "32";
		break;
	case 4:
		core_model = "30";
		break;
	case 3:
		core_model = "25";
		break;
	case 2:
		core_model = "20";
		break;
	case 1:
		core_model = "10";
		break;
	default:
		core_model = "XX";
		break;
	}

	/* Now figure out the family, the first two digits */
	switch ((chip_id >> 8) & 0xff) {
	case 0:		/* CN38XX, CN37XX or CN36XX */
		if (fus3.cn38xx.crip_512k) {
			/* For some unknown reason, the 16 core one is called 37 instead of 36 */
			if (num_cores >= 16)
				family = "37";
			else
				family = "36";
		} else
			family = "38";
		/* This series of chips didn't follow the standard pass numbering */
		switch (chip_id & 0xf) {
		case 0:
			strcpy(pass, "1.X");
			break;
		case 1:
			strcpy(pass, "2.X");
			break;
		case 3:
			strcpy(pass, "3.X");
			break;
		default:
			strcpy(pass, "X.X");
			break;
		}
		break;
	case 1:		/* CN31XX or CN3020 */
		if ((chip_id & 0x10) || fus3.cn31xx.crip_128k)
			family = "30";
		else
			family = "31";
		/* This series of chips didn't follow the standard pass numbering */
		switch (chip_id & 0xf) {
		case 0:
			strcpy(pass, "1.0");
			break;
		case 2:
			strcpy(pass, "1.1");
			break;
		default:
			strcpy(pass, "X.X");
			break;
		}
		break;
	case 2:		/* CN3010 or CN3005 */
		family = "30";
		/* A chip with half cache is an 05 */
		if (fus3.cn30xx.crip_64k)
			core_model = "05";
		/* This series of chips didn't follow the standard pass numbering */
		switch (chip_id & 0xf) {
		case 0:
			strcpy(pass, "1.0");
			break;
		case 2:
			strcpy(pass, "1.1");
			break;
		default:
			strcpy(pass, "X.X");
			break;
		}
		break;
	case 3:		/* CN58XX */
		family = "58";
		/* Special case. 4 core, half cache (CP with half cache) */
		if ((num_cores == 4) && fus3.cn58xx.crip_1024k && !strncmp(suffix, "CP", 2))
			core_model = "29";

		/* Pass 1 uses different encodings for pass numbers */
		if ((chip_id & 0xFF) < 0x8) {
			switch (chip_id & 0x3) {
			case 0:
				strcpy(pass, "1.0");
				break;
			case 1:
				strcpy(pass, "1.1");
				break;
			case 3:
				strcpy(pass, "1.2");
				break;
			default:
				strcpy(pass, "1.X");
				break;
			}
		}
		break;
	case 4:		/* CN57XX, CN56XX, CN55XX, CN54XX */
		if (fus_dat2.cn56xx.raid_en) {
			if (fus3.cn56xx.crip_1024k)
				family = "55";
			else
				family = "57";
			if (fus_dat2.cn56xx.nocrypto)
				suffix = "SP";
			else
				suffix = "SSP";
		} else {
			if (fus_dat2.cn56xx.nocrypto)
				suffix = "CP";
			else {
				suffix = "NSP";
				if (fus_dat3.s.nozip)
					suffix = "SCP";

				if (fus_dat3.cn56xx.bar2_en)
					suffix = "NSPB2";
			}
			if (fus3.cn56xx.crip_1024k)
				family = "54";
			else
				family = "56";
		}
		break;
	case 6:		/* CN50XX */
		family = "50";
		break;
	case 7:		/* CN52XX */
		if (fus3.cn52xx.crip_256k)
			family = "51";
		else
			family = "52";
		break;
	case 0x93:		/* CN61XX/CN60XX */
		family = "61";
		if (fus_dat3.cn63xx.l2c_crip == 2)
			family = "60";
		if (fus_dat3.cn61xx.nozip)
			suffix = "SCP";
		else
			suffix = "AAP";
		break;
	case 0x90:		/* CN63XX/CN62XX */
		family = "63";
		if (fus_dat3.s.l2c_crip == 2)
			family = "62";
		if (num_cores == 6)	/* Other core counts match generic */
			core_model = "35";
		if (fus_dat2.cn63xx.nocrypto)
			suffix = "CP";
		else if (fus_dat2.cn63xx.dorm_crypto)
			suffix = "DAP";
		else if (fus_dat3.cn63xx.nozip)
			suffix = "SCP";
		else
			suffix = "AAP";
		break;
	case 0x92:		/* CN66XX */
		family = "66";
		if (num_cores == 6)	/* Other core counts match generic */
			core_model = "35";
		if (fus_dat2.cn66xx.nocrypto && fus_dat2.cn66xx.dorm_crypto)
			suffix = "AP";
		if (fus_dat2.cn66xx.nocrypto)
			suffix = "CP";
		else if (fus_dat2.cn66xx.dorm_crypto)
			suffix = "DAP";
		else if (fus_dat3.cn66xx.nozip && fus_dat2.cn66xx.raid_en)
			suffix = "SCP";
		else if (!fus_dat2.cn66xx.raid_en)
			suffix = "HAP";
		else
			suffix = "AAP";
		break;
	case 0x91:		/* CN68XX */
		family = "68";
		if (fus_dat2.cn68xx.nocrypto && fus_dat3.cn68xx.nozip)
			suffix = "CP";
		else if (fus_dat2.cn68xx.dorm_crypto)
			suffix = "DAP";
		else if (fus_dat3.cn68xx.nozip)
			suffix = "SCP";
		else if (fus_dat2.cn68xx.nocrypto)
			suffix = "SP";
		else if (!fus_dat2.cn68xx.raid_en)
			suffix = "HAP";
		else
			suffix = "AAP";
		break;
	case 0x94:		/* CNF71XX */
		family = "F71";
		if (fus_dat3.cnf71xx.nozip)
			suffix = "SCP";
		else
			suffix = "AAP";
		break;
	case 0x95:		/* CN78XX */
		family = "78";
		if (fus_dat3.cn70xx.nozip)
			suffix = "SCP";
		else
			suffix = "AAP";
		break;
	case 0x96:		/* CN70XX */
		family = "70";
		if (cvmx_read_csr(CVMX_MIO_FUS_PDF) & (0x1ULL << 32))
			family = "71";
		if (fus_dat2.cn70xx.nocrypto)
			suffix = "CP";
		else if (fus_dat3.cn70xx.nodfa_dte)
			suffix = "SCP";
		else
			suffix = "AAP";
		break;
	default:
		family = "XX";
		core_model = "XX";
		strcpy(pass, "X.X");
		suffix = "XXX";
		break;
	}

#ifndef CVMX_BUILD_FOR_UBOOT
	clock_mhz = cvmx_clock_get_rate(CVMX_CLOCK_RCLK) / 1000000;
#endif

	if (family[0] != '3') {
		if (OCTEON_IS_OCTEON1PLUS() || OCTEON_IS_OCTEON2()) {
			int fuse_base = 384 / 8;
			if (family[0] == '6' || OCTEON_IS_OCTEON3())
				fuse_base = 832 / 8;
			/* Check for model in fuses, overrides normal decode */
			/* This is _not_ valid for Octeon CN3XXX models */
			fuse_data |= cvmx_fuse_read_byte(fuse_base + 5);
			fuse_data = fuse_data << 8;
			fuse_data |= cvmx_fuse_read_byte(fuse_base + 4);
			fuse_data = fuse_data << 8;
			fuse_data |= cvmx_fuse_read_byte(fuse_base + 3);
			fuse_data = fuse_data << 8;
			fuse_data |= cvmx_fuse_read_byte(fuse_base + 2);
			fuse_data = fuse_data << 8;
			fuse_data |= cvmx_fuse_read_byte(fuse_base + 1);
			fuse_data = fuse_data << 8;
			fuse_data |= cvmx_fuse_read_byte(fuse_base);
			if (fuse_data & 0x7ffff) {
				int model = fuse_data & 0x3fff;
				int suffix = (fuse_data >> 14) & 0x1f;
				if (suffix && model) {      /* Have both number and suffix in fuses, so both */
					sprintf(fuse_model, "%d%c", model, 'A' + suffix - 1);
					core_model = "";
					family = fuse_model;
				} else if (suffix && !model) {      /* Only have suffix, so add suffix to 'normal' model number */
					sprintf(fuse_model, "%s%c", core_model, 'A' + suffix - 1);
					core_model = fuse_model;
				} else {    /* Don't have suffix, so just use model from fuses */

					sprintf(fuse_model, "%d", model);
					core_model = "";
					family = fuse_model;
				}
			}
		} else {
Esempio n. 6
0
void init_octeon_pcie(void)
{
	int first_busno;
	int i;
	int rc = 0;
	int node = cvmx_get_node_num();
	struct pci_controller *hose;
	int pcie_port;

	first_busno = OCTEON_FIRST_PCIE_BUSNO;
	memset(&hose_pcie[0], 0, sizeof(hose_pcie[0]) * num_pcie_ports);

	debug("Starting PCIE on node %d\n", node);

	for (i = 0; i < num_pcie_ports; i++) {
		pcie_port = ((node << 4) | i);

		rc = cvmx_pcie_rc_initialize(pcie_port);

		if (rc != 0)
			continue;

		mdelay(1000);	/* Should delay 1 second according to standard */

		hose = &hose_pcie[i];
		hose->priv_data = (void *)&oct_pcie_data[i];
		oct_pcie_data[i].pcie_port = pcie_port;;

		hose->config_table = pci_board_config_table;

		hose->first_busno = first_busno;
		hose->last_busno = 0xff;

		/* PCI I/O space (Sub-DID == 2) */
		pci_set_region(hose->regions + 0,
			       octeon_pcie_region_info[i].io_base,
			       octeon_pcie_region_info[i].io_base,
			       octeon_pcie_region_info[i].io_size,
			       PCI_REGION_IO);
		/* PCI memory space (Sub-DID == 3) */
		pci_set_region(hose->regions + 1,
			       octeon_pcie_region_info[i].mem_base,
			       octeon_pcie_region_info[i].mem_base,
			       octeon_pcie_region_info[i].mem_size,
			       PCI_REGION_MEM);

		hose->region_count = 2;

		pci_set_ops(hose,
			    octeon_pcie_read_config_byte,
			    octeon_pcie_read_config_word,
			    octeon_pcie_read_config_dword,
			    octeon_pcie_write_config_byte,
			    octeon_pcie_write_config_word,
			    octeon_pcie_write_config_dword);

		pci_register_hose(hose);

		hose->last_busno = pci_hose_scan(hose);

		debug("PCIe: port=%d, first_bus=%d, last_bus=%d,\n\t"
		      "mem_base=0x%x, mem_size=0x%x, io_base=0x%x, io_size=0x%x\n",
		      octeon_get_pcie_port(hose),
		      hose->first_busno, hose->last_busno,
		      octeon_pcie_region_info[i].mem_base,
		      octeon_pcie_region_info[i].mem_size,
		      octeon_pcie_region_info[i].io_base,
		      octeon_pcie_region_info[i].io_size);

		first_busno = hose->last_busno + 1;
#if CONFIG_OCTEON_PCI_ENABLE_32BIT_MAPPING
		if (OCTEON_IS_OCTEON2() || OCTEON_IS_OCTEON3()) {
			cvmx_pemx_bar_ctl_t bar_ctl;
			cvmx_pemx_bar1_indexx_t pemx_bar1_indexx;
			uint64_t bar_base;
			int j;
			/* Setup BAR1 to map bus address 0x0 to the base of
			 * u-boot's TLB mapping.  This allows us to have u-boot
			 * located anywhere in memory (including above 32 bit
			 * addressable space) and still have 32 bit PCI devices
			 * have access to memory that is statically allocated
			 * or malloced by u-boot, both of which are TLB mapped.
			 */
			cvmx_write_csr_node(node, CVMX_PEMX_P2N_BAR1_START(i), 0);

			/* Disable bar0/bar2, as we are not using them here */
			cvmx_write_csr_node(node, CVMX_PEMX_P2N_BAR0_START(i), -1);
			cvmx_write_csr_node(node, CVMX_PEMX_P2N_BAR2_START(i), -1);

			/* Select 64 MByte mapping size for bar 1 on
			 * all ports
			 */
			bar_ctl.u64 = cvmx_read_csr_node(node, CVMX_PEMX_BAR_CTL(i));
			bar_ctl.s.bar1_siz = 1;	/* 64MB */
			bar_ctl.s.bar2_enb = 0;
			cvmx_write_csr_node(node, CVMX_PEMX_BAR_CTL(i), bar_ctl.u64);
			/* Configure the regions in bar 1 to map to the
			 * DRAM used by u-boot.
			 */
			/* Round down to 4MByte boundary to meet BAR mapping
			 * requirements
			 */
			bar_base = gd->bd->bi_uboot_ram_addr & ~0x3fffffull;

			debug("pcie: port %d, setting BAR base to 0x%llx\n",
			      i, bar_base);

			pemx_bar1_indexx.u64 = 0;
			pemx_bar1_indexx.s.addr_v = 1;
			pemx_bar1_indexx.s.end_swp = 1;
			pemx_bar1_indexx.s.ca = 1;

			for (j = 0; j < 16; j++) {
				pemx_bar1_indexx.s.addr_idx =
					(bar_base + 4 * 1024 * 1024 * j) >> 22;
				cvmx_write64_uint64(CVMX_PEMX_BAR1_INDEXX(j, i),
						    pemx_bar1_indexx.u64);
			}
		}
#endif /* CONFIG_OCTEON_PCI_ENABLE_32BIT_MAPPING */
	}