/*
 * Transfer (i.e. exchange) one "word" with selected SPI device.
 * Typically one word is 8-bits (an octet), but it does not need to be,
 * this function is word-width agnostic - when using the SSC.
 * However, for PIO bit-banging, then one word is explicitly
 * unconditionally assumed to be exactly 8-bits in length.
 *
 *	input:   "out" is word to be send to slave SPI device
 *	returns: one word read from the slave SPI device
 *
 * It is the caller's responsibility to ensure that the
 * chip select (SPI_NOTCS) is correctly asserted.
 */
static unsigned int spi_xfer_one_word(const unsigned int out)
{
	unsigned int in = 0;

#if defined(CONFIG_SOFT_SPI)		/* Use PIO Bit-Banging for SPI */
	signed int i;
	for(i=7; i>=0; i--)		/* for each bit in turn ... */
	{				/* do 8 bits, msb first */
		SPI_SCL(0);		/* SPI_CLK = low */
		SPI_SDA(out & (1u<<i));	/* output next bit on SPI_DOUT */
		SPI_DELAY;		/* clock low cycle */

		SPI_SCL(1);		/* SPI_CLK = high */
		SPI_DELAY;		/* sample on RISING clock edge */

		in <<= 1;		/* shift */
		in |= SPI_READ;		/* get next bit from SPI_DIN */
	}
#else					/* Use SSC for SPI */
	/* write out data 'out' */
	ssc_write(SSC_TBUF, out);

	/* wait for Receive Buffer Full flag to be asserted */
	while ((ssc_read(SSC_STAT) & SSC_STAT_RIR) == 0)
	{
		;	/* busy poll - do nothing */
	}

	/* read in data */
	in = ssc_read(SSC_RBUF);
#endif	/* CONFIG_SOFT_SPI */

	/* return exchanged data */
	return in;
}
예제 #2
0
/**
 * \brief Synchronous Serial Controller Handler.
 *
 */
void SSC_Handler(void)
{
	uint32_t ul_data;
	ssc_get_status(SSC);

	ssc_read(SSC, &ul_data);
	g_uc_rx_buff[g_uc_rx_index++] = ul_data;

	if (BUFFER_SIZE == g_uc_rx_index) {
		g_uc_rx_done = 1;
		ssc_disable_interrupt(SSC, SSC_IDR_RXRDY);
	}
}
/*
 * initialise the SSC to talk to the slave SPI device.
 */
extern void spi_init(void)
{
	//DECLARE_GLOBAL_DATA_PTR;
	spi_chipsel_type const chipsel = spi_chipsel[0];	/* SPI Device #0 */

#if !defined(CONFIG_SOFT_SPI)			/* Use SSC for SPI */
	unsigned long reg;
	const unsigned long bits_per_word = 8;	/* one word == 8-bits */
	const unsigned long mode = CFG_STM_SPI_MODE /* | SPI_LOOP */;
	//const unsigned long fcomms = gd->bd->bi_emifrq*1000*1000;
	const unsigned long hz = CFG_STM_SPI_FREQUENCY;
       //unsigned long sscbrg = fcomms/(2*hz);

#endif	/* CONFIG_SOFT_SPI */

      /*init pio15.0-pio15.3*/
      configSpi();

	/* de-assert SPI CS */
	(*chipsel)(0);

#if !defined(CONFIG_SOFT_SPI)			/* Use SSC for SPI */
	/* program the SSC's Baud-Rate Generator */
	if ((sscbrg < 0x07u) || (sscbrg > (0x1u << 16)))
	{
		printk("ERROR: Unable to set SSC buad-rate generator to 0x%04x\n",
			sscbrg);
		return;
	}
	/* TODO: program pre-scaler for slower baud rates */
	if (sscbrg == (0x1 << 16)) /* 16-bit counter wraps */
	{
		sscbrg = 0x0;	/* slowest possible clock frequency */
	}
	ssc_write(SSC_BRG,sscbrg);
#if 0	/* QQQ */
	printk("info: fcomms=%uMHz, SPI=%uHz, brg=0x%04x\n",
		fcomms/1000/1000, hz, sscbrg);
#endif

	/* Disable I2C sub-system */
	ssc_write( SSC_I2C, 0x0);

	/* Perform a S/W reset the SSC */
	reg = ssc_read( SSC_CON);
	reg |= SSC_CON_SR;		/* enable software reset */
	ssc_write( SSC_CON, reg);
	udelay(1);			/* let reset propagate */
	reg = ssc_read( SSC_CON);
	reg &= ~SSC_CON_SR;		/* disable software reset */
	ssc_write( SSC_CON, reg);

	/* Configure & enable the SSC's control register */
	reg = ssc_read(SSC_CON);
	reg |= SSC_CON_EN;		/* Enable the SSC */
	reg |= SSC_CON_MS;		/* set SSC as the SPI master */
	if (mode & SPI_CPOL)
		reg |= SSC_CON_PO;	/* Clock idles at logic 1 */
	else
		reg &= ~SSC_CON_PO;	/* Clock idles at logic 0 */
	if (mode & SPI_CPHA)
		reg |= SSC_CON_PH;	/* Pulse in first half-cycle */
	else
		reg &= ~SSC_CON_PH;	/* Pulse in second half-cycle */
	if (mode & SPI_LSB_FIRST)
		reg &= ~SSC_CON_HB;	/* LSB first */
	else
		reg |= SSC_CON_HB;	/* MSB first */
	if (mode & SPI_LOOP)
		reg |= SSC_CON_LPB;	/* put SSC in loop-back mode */
	else
		reg &= ~SSC_CON_LPB;	/* remove SSC from loop-back mode */
	reg &= ~0x0ful;			/* set bit width */
	reg |= (bits_per_word - 1ul);	/* set bit width */
	ssc_write(SSC_CON,reg);

	/* clear the status register */
	(void)ssc_read(SSC_RBUF);
#endif	/* CONFIG_SOFT_SPI */

	/* now probe the serial flash, to ensure it is the correct one */
	spi_probe_serial_flash(chipsel);
}