예제 #1
0
static int
ar71xx_spi_transfer(device_t dev, device_t child, struct spi_command *cmd)
{
	struct ar71xx_spi_softc *sc;
	uint32_t cs;
	uint8_t *buf_in, *buf_out;
	int i;

	sc = device_get_softc(dev);

	spibus_get_cs(child, &cs);

	cs &= ~SPIBUS_CS_HIGH;

	ar71xx_spi_chip_activate(sc, cs);

	KASSERT(cmd->tx_cmd_sz == cmd->rx_cmd_sz, 
	    ("TX/RX command sizes should be equal"));
	KASSERT(cmd->tx_data_sz == cmd->rx_data_sz, 
	    ("TX/RX data sizes should be equal"));

	/*
	 * Transfer command
	 */
	buf_out = (uint8_t *)cmd->tx_cmd;
	buf_in = (uint8_t *)cmd->rx_cmd;
	for (i = 0; i < cmd->tx_cmd_sz; i++)
		buf_in[i] = ar71xx_spi_txrx(sc, cs, buf_out[i]);

	/*
	 * Receive/transmit data (depends on  command)
	 */
	buf_out = (uint8_t *)cmd->tx_data;
	buf_in = (uint8_t *)cmd->rx_data;
	for (i = 0; i < cmd->tx_data_sz; i++)
		buf_in[i] = ar71xx_spi_txrx(sc, cs, buf_out[i]);

	ar71xx_spi_chip_deactivate(sc, cs);

	return (0);
}
예제 #2
0
파일: vf_spi.c 프로젝트: Alkzndr/freebsd
static int
spi_transfer(device_t dev, device_t child, struct spi_command *cmd)
{
	struct spi_softc *sc;
	uint32_t cs;

	sc = device_get_softc(dev);

	KASSERT(cmd->tx_cmd_sz == cmd->rx_cmd_sz,
	    ("%s: TX/RX command sizes should be equal", __func__));
	KASSERT(cmd->tx_data_sz == cmd->rx_data_sz,
	    ("%s: TX/RX data sizes should be equal", __func__));

	/* get the proper chip select */
	spibus_get_cs(child, &cs);

	/* Command */
	spi_txrx(sc, cmd->tx_cmd, cmd->rx_cmd, cmd->tx_cmd_sz, cs);

	/* Data */
	spi_txrx(sc, cmd->tx_data, cmd->rx_data, cmd->tx_data_sz, cs);

	return (0);
}
예제 #3
0
static int
bcm_spi_transfer(device_t dev, device_t child, struct spi_command *cmd)
{
	struct bcm_spi_softc *sc;
	uint32_t cs;
	int err;

	sc = device_get_softc(dev);

	KASSERT(cmd->tx_cmd_sz == cmd->rx_cmd_sz, 
	    ("TX/RX command sizes should be equal"));
	KASSERT(cmd->tx_data_sz == cmd->rx_data_sz, 
	    ("TX/RX data sizes should be equal"));

	/* Get the proper chip select for this child. */
	spibus_get_cs(child, &cs);

	cs &= ~SPIBUS_CS_HIGH;

	if (cs > 2) {
		device_printf(dev,
		    "Invalid chip select %d requested by %s\n", cs,
		    device_get_nameunit(child));
		return (EINVAL);
	}

	BCM_SPI_LOCK(sc);

	/* If the controller is in use wait until it is available. */
	while (sc->sc_flags & BCM_SPI_BUSY)
		mtx_sleep(dev, &sc->sc_mtx, 0, "bcm_spi", 0);

	/* Now we have control over SPI controller. */
	sc->sc_flags = BCM_SPI_BUSY;

	/* Clear the FIFO. */
	bcm_spi_modifyreg(sc, SPI_CS,
	    SPI_CS_CLEAR_RXFIFO | SPI_CS_CLEAR_TXFIFO,
	    SPI_CS_CLEAR_RXFIFO | SPI_CS_CLEAR_TXFIFO);

	/* Save a pointer to the SPI command. */
	sc->sc_cmd = cmd;
	sc->sc_read = 0;
	sc->sc_written = 0;
	sc->sc_len = cmd->tx_cmd_sz + cmd->tx_data_sz;

	/*
	 * Set the CS for this transaction, enable interrupts and announce
	 * we're ready to tx.  This will kick off the first interrupt.
	 */
	bcm_spi_modifyreg(sc, SPI_CS,
	    SPI_CS_MASK | SPI_CS_TA | SPI_CS_INTR | SPI_CS_INTD,
	    cs | SPI_CS_TA | SPI_CS_INTR | SPI_CS_INTD);

	/* Wait for the transaction to complete. */
	err = mtx_sleep(dev, &sc->sc_mtx, 0, "bcm_spi", hz * 2);

	/* Make sure the SPI engine and interrupts are disabled. */
	bcm_spi_modifyreg(sc, SPI_CS, SPI_CS_TA | SPI_CS_INTR | SPI_CS_INTD, 0);

	/* Release the controller and wakeup the next thread waiting for it. */
	sc->sc_flags = 0;
	wakeup_one(dev);
	BCM_SPI_UNLOCK(sc);

	/*
	 * Check for transfer timeout.  The SPI controller doesn't
	 * return errors.
	 */
	if (err == EWOULDBLOCK) {
		device_printf(sc->sc_dev, "SPI error\n");
		err = EIO;
	}

	return (err);
}
예제 #4
0
static int
rt305x_spi_transfer(device_t dev, device_t child, struct spi_command *cmd)
{
	struct rt305x_spi_softc *sc;
	uint32_t cs;
	uint8_t *buf, byte, *tx_buf;
	int i, sz, error = 0, write = 0;

	sc = device_get_softc(dev);

	spibus_get_cs(child, &cs);

	if (cs != 0)
		/* Only 1 CS */
		return (ENXIO);

        /* There is always a command to transfer. */
        tx_buf = (uint8_t *)(cmd->tx_cmd);
        
        /* Perform some fixup because RT305X dont support duplex SPI */
        switch(tx_buf[0]) {
                case CMD_READ_IDENT:
                        cmd->tx_cmd_sz = 1;
                        cmd->rx_cmd_sz = 3;
                        break;
                case CMD_WRITE_ENABLE:
                case CMD_WRITE_DISABLE:
                        cmd->tx_cmd_sz = 1;
                        cmd->rx_cmd_sz = 0;
                        break;
                case CMD_READ_STATUS:
                        cmd->tx_cmd_sz = 1;
                        cmd->rx_cmd_sz = 1;
                        break;
                case CMD_READ:
                        cmd->tx_cmd_sz = 4;
                case CMD_FAST_READ:
                        cmd->tx_cmd_sz = 5;
                        cmd->rx_cmd_sz = cmd->tx_data_sz = 0;
                        break;
                case CMD_SECTOR_ERASE:
                        cmd->tx_cmd_sz = 4;
                        cmd->rx_cmd_sz = cmd->tx_data_sz = 0;
                        break;
                case CMD_PAGE_PROGRAM:
                        cmd->tx_cmd_sz = 4;
                        cmd->rx_cmd_sz = cmd->rx_data_sz = 0;
                        break;
        }      
        
	rt305x_spi_chip_activate(sc);

	if (cmd->tx_cmd_sz + cmd->rx_cmd_sz) {
		buf = (uint8_t *)(cmd->rx_cmd);
		tx_buf = (uint8_t *)(cmd->tx_cmd);
		sz = cmd->tx_cmd_sz + cmd->rx_cmd_sz;

		for (i = 0; i < sz; i++) {
                        if(i < cmd->tx_cmd_sz) {
			        byte = tx_buf[i];
        			error = rt305x_spi_txrx(sc, &byte,
		        	    RT305X_SPI_WRITE);
        			if (error)
        				goto rt305x_spi_transfer_fail;
                                continue;
                        }
                        error = rt305x_spi_txrx(sc, &byte,
		            RT305X_SPI_READ);
        		if (error)
        			goto rt305x_spi_transfer_fail;
			buf[i] = byte;
		}
	}
	
	/*
	 * Transfer/Receive data
	 */
	
	if (cmd->tx_data_sz + cmd->rx_data_sz) {
		write = (cmd->tx_data_sz > 0)?1:0;
		buf = (uint8_t *)(write ? cmd->tx_data : cmd->rx_data);
		sz = write ? cmd->tx_data_sz : cmd->rx_data_sz;

		for (i = 0; i < sz; i++) {
			byte = buf[i];
			error = rt305x_spi_txrx(sc, &byte,
			    write?RT305X_SPI_WRITE:RT305X_SPI_READ);
			if (error)
				goto rt305x_spi_transfer_fail;
			buf[i] = byte;
		}
	}
rt305x_spi_transfer_fail:
	rt305x_spi_chip_deactivate(sc);

	return (error);
}