/**
 * Callback to setup calendar and miscellaneous settings before clock detection
 *
 * @interface: The identifier of the packet interface to configure and
 *                  use as a SPI interface.
 * @mode:      The operating mode for the SPI interface. The interface
 *                  can operate as a full duplex (both Tx and Rx data paths
 *                  active) or as a halfplex (either the Tx data path is
 *                  active or the Rx data path is active, but not both).
 * @num_ports: Number of ports to configure on SPI
 *
 * Returns Zero on success, non-zero error code on failure (will cause
 * SPI initialization to abort)
 */
int cvmx_spi_calendar_setup_cb(int interface, cvmx_spi_mode_t mode,
			       int num_ports)
{
	int port;
	int index;
	if (mode & CVMX_SPI_MODE_RX_HALFPLEX) {
		union cvmx_srxx_com_ctl srxx_com_ctl;
		union cvmx_srxx_spi4_stat srxx_spi4_stat;

		/* SRX0 number of Ports */
		srxx_com_ctl.u64 = 0;
		srxx_com_ctl.s.prts = num_ports - 1;
		srxx_com_ctl.s.st_en = 0;
		srxx_com_ctl.s.inf_en = 0;
		cvmx_write_csr(CVMX_SRXX_COM_CTL(interface), srxx_com_ctl.u64);

		/* SRX0 Calendar Table. This round robbins through all ports */
		port = 0;
		index = 0;
		while (port < num_ports) {
			union cvmx_srxx_spi4_calx srxx_spi4_calx;
			srxx_spi4_calx.u64 = 0;
			srxx_spi4_calx.s.prt0 = port++;
			srxx_spi4_calx.s.prt1 = port++;
			srxx_spi4_calx.s.prt2 = port++;
			srxx_spi4_calx.s.prt3 = port++;
			srxx_spi4_calx.s.oddpar =
			    ~(cvmx_dpop(srxx_spi4_calx.u64) & 1);
			cvmx_write_csr(CVMX_SRXX_SPI4_CALX(index, interface),
				       srxx_spi4_calx.u64);
			index++;
		}
		srxx_spi4_stat.u64 = 0;
		srxx_spi4_stat.s.len = num_ports;
		srxx_spi4_stat.s.m = 1;
		cvmx_write_csr(CVMX_SRXX_SPI4_STAT(interface),
			       srxx_spi4_stat.u64);
	}

	if (mode & CVMX_SPI_MODE_TX_HALFPLEX) {
		union cvmx_stxx_arb_ctl stxx_arb_ctl;
		union cvmx_gmxx_tx_spi_max gmxx_tx_spi_max;
		union cvmx_gmxx_tx_spi_thresh gmxx_tx_spi_thresh;
		union cvmx_gmxx_tx_spi_ctl gmxx_tx_spi_ctl;
		union cvmx_stxx_spi4_stat stxx_spi4_stat;
		union cvmx_stxx_spi4_dat stxx_spi4_dat;

		/* STX0 Config */
		stxx_arb_ctl.u64 = 0;
		stxx_arb_ctl.s.igntpa = 0;
		stxx_arb_ctl.s.mintrn = 0;
		cvmx_write_csr(CVMX_STXX_ARB_CTL(interface), stxx_arb_ctl.u64);

		gmxx_tx_spi_max.u64 = 0;
		gmxx_tx_spi_max.s.max1 = 8;
		gmxx_tx_spi_max.s.max2 = 4;
		gmxx_tx_spi_max.s.slice = 0;
		cvmx_write_csr(CVMX_GMXX_TX_SPI_MAX(interface),
			       gmxx_tx_spi_max.u64);

		gmxx_tx_spi_thresh.u64 = 0;
		gmxx_tx_spi_thresh.s.thresh = 4;
		cvmx_write_csr(CVMX_GMXX_TX_SPI_THRESH(interface),
			       gmxx_tx_spi_thresh.u64);

		gmxx_tx_spi_ctl.u64 = 0;
		gmxx_tx_spi_ctl.s.tpa_clr = 0;
		gmxx_tx_spi_ctl.s.cont_pkt = 0;
		cvmx_write_csr(CVMX_GMXX_TX_SPI_CTL(interface),
			       gmxx_tx_spi_ctl.u64);

		/* STX0 Training Control */
		stxx_spi4_dat.u64 = 0;
		/*Minimum needed by dynamic alignment */
		stxx_spi4_dat.s.alpha = 32;
		stxx_spi4_dat.s.max_t = 0xFFFF;	/*Minimum interval is 0x20 */
		cvmx_write_csr(CVMX_STXX_SPI4_DAT(interface),
			       stxx_spi4_dat.u64);

		/* STX0 Calendar Table. This round robbins through all ports */
		port = 0;
		index = 0;
		while (port < num_ports) {
			union cvmx_stxx_spi4_calx stxx_spi4_calx;
			stxx_spi4_calx.u64 = 0;
			stxx_spi4_calx.s.prt0 = port++;
			stxx_spi4_calx.s.prt1 = port++;
			stxx_spi4_calx.s.prt2 = port++;
			stxx_spi4_calx.s.prt3 = port++;
			stxx_spi4_calx.s.oddpar =
			    ~(cvmx_dpop(stxx_spi4_calx.u64) & 1);
			cvmx_write_csr(CVMX_STXX_SPI4_CALX(index, interface),
				       stxx_spi4_calx.u64);
			index++;
		}
		stxx_spi4_stat.u64 = 0;
		stxx_spi4_stat.s.len = num_ports;
		stxx_spi4_stat.s.m = 1;
		cvmx_write_csr(CVMX_STXX_SPI4_STAT(interface),
			       stxx_spi4_stat.u64);
	}

	return 0;
}
int cvmx_spi_calendar_setup_cb(int interface, cvmx_spi_mode_t mode,
                               int num_ports)
{
    int port;
    int index;
    if (mode & CVMX_SPI_MODE_RX_HALFPLEX) {
        union cvmx_srxx_com_ctl srxx_com_ctl;
        union cvmx_srxx_spi4_stat srxx_spi4_stat;


        srxx_com_ctl.u64 = 0;
        srxx_com_ctl.s.prts = num_ports - 1;
        srxx_com_ctl.s.st_en = 0;
        srxx_com_ctl.s.inf_en = 0;
        cvmx_write_csr(CVMX_SRXX_COM_CTL(interface), srxx_com_ctl.u64);


        port = 0;
        index = 0;
        while (port < num_ports) {
            union cvmx_srxx_spi4_calx srxx_spi4_calx;
            srxx_spi4_calx.u64 = 0;
            srxx_spi4_calx.s.prt0 = port++;
            srxx_spi4_calx.s.prt1 = port++;
            srxx_spi4_calx.s.prt2 = port++;
            srxx_spi4_calx.s.prt3 = port++;
            srxx_spi4_calx.s.oddpar =
                ~(cvmx_dpop(srxx_spi4_calx.u64) & 1);
            cvmx_write_csr(CVMX_SRXX_SPI4_CALX(index, interface),
                           srxx_spi4_calx.u64);
            index++;
        }
        srxx_spi4_stat.u64 = 0;
        srxx_spi4_stat.s.len = num_ports;
        srxx_spi4_stat.s.m = 1;
        cvmx_write_csr(CVMX_SRXX_SPI4_STAT(interface),
                       srxx_spi4_stat.u64);
    }

    if (mode & CVMX_SPI_MODE_TX_HALFPLEX) {
        union cvmx_stxx_arb_ctl stxx_arb_ctl;
        union cvmx_gmxx_tx_spi_max gmxx_tx_spi_max;
        union cvmx_gmxx_tx_spi_thresh gmxx_tx_spi_thresh;
        union cvmx_gmxx_tx_spi_ctl gmxx_tx_spi_ctl;
        union cvmx_stxx_spi4_stat stxx_spi4_stat;
        union cvmx_stxx_spi4_dat stxx_spi4_dat;


        stxx_arb_ctl.u64 = 0;
        stxx_arb_ctl.s.igntpa = 0;
        stxx_arb_ctl.s.mintrn = 0;
        cvmx_write_csr(CVMX_STXX_ARB_CTL(interface), stxx_arb_ctl.u64);

        gmxx_tx_spi_max.u64 = 0;
        gmxx_tx_spi_max.s.max1 = 8;
        gmxx_tx_spi_max.s.max2 = 4;
        gmxx_tx_spi_max.s.slice = 0;
        cvmx_write_csr(CVMX_GMXX_TX_SPI_MAX(interface),
                       gmxx_tx_spi_max.u64);

        gmxx_tx_spi_thresh.u64 = 0;
        gmxx_tx_spi_thresh.s.thresh = 4;
        cvmx_write_csr(CVMX_GMXX_TX_SPI_THRESH(interface),
                       gmxx_tx_spi_thresh.u64);

        gmxx_tx_spi_ctl.u64 = 0;
        gmxx_tx_spi_ctl.s.tpa_clr = 0;
        gmxx_tx_spi_ctl.s.cont_pkt = 0;
        cvmx_write_csr(CVMX_GMXX_TX_SPI_CTL(interface),
                       gmxx_tx_spi_ctl.u64);


        stxx_spi4_dat.u64 = 0;

        stxx_spi4_dat.s.alpha = 32;
        stxx_spi4_dat.s.max_t = 0xFFFF;
        cvmx_write_csr(CVMX_STXX_SPI4_DAT(interface),
                       stxx_spi4_dat.u64);


        port = 0;
        index = 0;
        while (port < num_ports) {
            union cvmx_stxx_spi4_calx stxx_spi4_calx;
            stxx_spi4_calx.u64 = 0;
            stxx_spi4_calx.s.prt0 = port++;
            stxx_spi4_calx.s.prt1 = port++;
            stxx_spi4_calx.s.prt2 = port++;
            stxx_spi4_calx.s.prt3 = port++;
            stxx_spi4_calx.s.oddpar =
                ~(cvmx_dpop(stxx_spi4_calx.u64) & 1);
            cvmx_write_csr(CVMX_STXX_SPI4_CALX(index, interface),
                           stxx_spi4_calx.u64);
            index++;
        }
        stxx_spi4_stat.u64 = 0;
        stxx_spi4_stat.s.len = num_ports;
        stxx_spi4_stat.s.m = 1;
        cvmx_write_csr(CVMX_STXX_SPI4_STAT(interface),
                       stxx_spi4_stat.u64);
    }

    return 0;
}