const char *octeon_model_get_string_buffer(uint32_t chip_id, char *buffer)
{
	const char *family;
	const char *core_model;
	char pass[4];
	int clock_mhz;
	const char *suffix;
	union cvmx_l2d_fus3 fus3;
	int num_cores;
	union cvmx_mio_fus_dat2 fus_dat2;
	union cvmx_mio_fus_dat3 fus_dat3;
	char fuse_model[10];
	uint32_t fuse_data = 0;

	fus3.u64 = 0;
	if (!OCTEON_IS_MODEL(OCTEON_CN6XXX))
		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);
	num_cores = cvmx_pop(cvmx_read_csr(CVMX_CIU_FUSE));

	/*                                                  */
	switch ((chip_id >> 8) & 0xff) {
	case 6:		/*        */
	case 2:		/*        */
		fus_dat3.s.nodfa_dte = 1;
		fus_dat3.s.nozip = 1;
		break;
	case 4:		/*                  */
		fus_dat3.s.nodfa_dte = 1;
		break;
	default:
		break;
	}

	/*                            */
	/*                  */
	/*                 */
	/*                      */
	/*                                */
	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";

	/*
                                                              
                        
  */
	sprintf(pass, "%d.%d", (int)((chip_id >> 3) & 7) + 1, (int)chip_id & 7);

	/*
                                                             
                                                              
          
  */
	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;
	}

	/*                                                 */
	switch ((chip_id >> 8) & 0xff) {
	case 0:		/*                          */
		if (fus3.cn38xx.crip_512k) {
			/*
                                                 
                              
    */
			if (num_cores >= 16)
				family = "37";
			else
				family = "36";
		} else
			family = "38";
		/*
                                                    
                    
   */
		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:		/*                  */
		if ((chip_id & 0x10) || fus3.cn31xx.crip_128k)
			family = "30";
		else
			family = "31";
		/*
                                                    
                    
   */
		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:		/*                  */
		family = "30";
		/*                                 */
		if (fus3.cn30xx.crip_64k)
			core_model = "05";
		/*
                                                    
                    
   */
		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:		/*        */
		family = "58";
		/*                                                       */
		if ((num_cores == 4) && fus3.cn58xx.crip_1024k && !strncmp(suffix, "CP", 2))
			core_model = "29";

		/*                                                  */
		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:		/*                                */
		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.s.bar2_en)
					suffix = "NSPB2";
			}
			if (fus3.cn56xx.crip_1024k)
				family = "54";
			else
				family = "56";
		}
		break;
	case 6:		/*        */
		family = "50";
		break;
	case 7:		/*        */
		if (fus3.cn52xx.crip_256k)
			family = "51";
		else
			family = "52";
		break;
	case 0x93:		/*        */
		family = "61";
		if (fus_dat2.cn61xx.nocrypto && fus_dat2.cn61xx.dorm_crypto)
			suffix = "AP";
		if (fus_dat2.cn61xx.nocrypto)
			suffix = "CP";
		else if (fus_dat2.cn61xx.dorm_crypto)
			suffix = "DAP";
		else if (fus_dat3.cn61xx.nozip)
			suffix = "SCP";
		break;
	case 0x90:		/*        */
		family = "63";
		if (fus_dat3.s.l2c_crip == 2)
			family = "62";
		if (num_cores == 6)	/*                                 */
			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:		/*        */
		family = "66";
		if (num_cores == 6)	/*                                 */
			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)
			suffix = "SCP";
		else
			suffix = "AAP";
		break;
	case 0x91:		/*        */
		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
			suffix = "AAP";
		break;
	default:
		family = "XX";
		core_model = "XX";
		strcpy(pass, "X.X");
		suffix = "XXX";
		break;
	}

	clock_mhz = octeon_get_clock_rate() / 1000000;
	if (family[0] != '3') {
		int fuse_base = 384 / 8;
		if (family[0] == '6')
			fuse_base = 832 / 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) {
				/*                                               */
				sprintf(fuse_model, "%d%c", model, 'A' + suffix - 1);
				core_model = "";
				family = fuse_model;
			} else if (suffix && !model) {
				/*                                                          */
				sprintf(fuse_model, "%s%c", core_model, 'A' + suffix - 1);
				core_model = fuse_model;
			} else {
				/*                                                 */
				sprintf(fuse_model, "%d", model);
				core_model = "";
				family = fuse_model;
			}
		}
Example #2
0
/* 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];
    uint32_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);
    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.s.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 */
            family = "61";
            if (fus_dat3.cn61xx.nozip)
                suffix = "SCP";
            else
                suffix = "AAP";
            break;
	case 0x90: /* CN63XX */
            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;
        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')
    {
        int fuse_base = 384/8;
        if (family[0] == '6')
            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 + 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;
            }
        }
Example #3
0
/**
 * @INTERNAL
 * Return the link state of an IPD/PKO port as returned by ILK link status.
 *
 * @param ipd_port IPD/PKO port to query
 *
 * @return Link state
 */
cvmx_helper_link_info_t __cvmx_helper_ilk_link_get(int ipd_port)
{
    cvmx_helper_link_info_t result;
    int interface = cvmx_helper_get_interface_num(ipd_port);
    int retry_count = 0;
    cvmx_ilk_rxx_cfg1_t ilk_rxx_cfg1;
    cvmx_ilk_rxx_int_t ilk_rxx_int;
    int lanes = 0;

    result.u64 = 0;
    interface -= CVMX_ILK_GBL_BASE;

retry:
    retry_count++;
    if (retry_count > 10)
        goto out;

    ilk_rxx_cfg1.u64 = cvmx_read_csr (CVMX_ILK_RXX_CFG1(interface));
    ilk_rxx_int.u64 = cvmx_read_csr (CVMX_ILK_RXX_INT(interface));

    /* Clear all RX status bits */
    if (ilk_rxx_int.u64)
        cvmx_write_csr(CVMX_ILK_RXX_INT(interface), ilk_rxx_int.u64);

    if (ilk_rxx_cfg1.s.rx_bdry_lock_ena == 0)
    {
        /* We need to start looking for work boundary lock */
        ilk_rxx_cfg1.s.rx_bdry_lock_ena = cvmx_ilk_get_intf_ln_msk(interface);
        ilk_rxx_cfg1.s.rx_align_ena = 0;
        cvmx_write_csr(CVMX_ILK_RXX_CFG1(interface), ilk_rxx_cfg1.u64);
        //cvmx_dprintf("ILK%d: Looking for word boundary lock\n", interface);
        goto retry;
    }

    if (ilk_rxx_cfg1.s.rx_align_ena == 0)
    {
        if (ilk_rxx_int.s.word_sync_done)
        {
            ilk_rxx_cfg1.s.rx_align_ena = 1;
            cvmx_write_csr(CVMX_ILK_RXX_CFG1(interface), ilk_rxx_cfg1.u64);
            //printf("ILK%d: Looking for lane alignment\n", interface);
            goto retry;
        }
        goto out;
    }

    if (ilk_rxx_int.s.lane_align_fail)
    {
        ilk_rxx_cfg1.s.rx_bdry_lock_ena = 0;
        ilk_rxx_cfg1.s.rx_align_ena = 0;
        cvmx_write_csr(CVMX_ILK_RXX_CFG1(interface), ilk_rxx_cfg1.u64);
        cvmx_dprintf("ILK%d: Lane alignment failed\n", interface);
        goto out;
    }

    if (ilk_rxx_int.s.lane_align_done)
    {
        //cvmx_dprintf("ILK%d: Lane alignment complete\n", interface);
    }

    lanes = cvmx_pop(ilk_rxx_cfg1.s.rx_bdry_lock_ena);

    result.s.link_up = 1;
    result.s.full_duplex = 1;
    result.s.speed = cvmx_qlm_get_gbaud_mhz(1+interface) * 64 / 67;
    result.s.speed *= lanes;

out:
    /* If the link is down we will force disable the RX path. If it up, we'll
        set it to match the TX state set by the if_enable call */
    if (result.s.link_up)
    {
        cvmx_ilk_txx_cfg1_t ilk_txx_cfg1;
        ilk_txx_cfg1.u64 = cvmx_read_csr(CVMX_ILK_TXX_CFG1(interface));
        ilk_rxx_cfg1.s.pkt_ena = ilk_txx_cfg1.s.pkt_ena;
        cvmx_write_csr(CVMX_ILK_RXX_CFG1(interface), ilk_rxx_cfg1.u64);
        //cvmx_dprintf("ILK%d: link up, %d Mbps, Full duplex mode, %d lanes\n", interface, result.s.speed, lanes);  
    }
    else
    {
        ilk_rxx_cfg1.s.pkt_ena = 0;
        cvmx_write_csr(CVMX_ILK_RXX_CFG1(interface), ilk_rxx_cfg1.u64);
        //cvmx_dprintf("ILK link down\n");
    }
    return result;
}