|
@@ -31,22 +31,87 @@
|
|
|
#define SPI_MODE_1 (0|SPI_CPHA)
|
|
|
#define SPI_MODE_2 (SPI_CPOL|0)
|
|
|
#define SPI_MODE_3 (SPI_CPOL|SPI_CPHA)
|
|
|
-#define SPI_CS_HIGH 0x04 /* chipselect active high? */
|
|
|
+#define SPI_CS_HIGH 0x04 /* CS active high */
|
|
|
#define SPI_LSB_FIRST 0x08 /* per-word bits-on-wire */
|
|
|
#define SPI_3WIRE 0x10 /* SI/SO signals shared */
|
|
|
#define SPI_LOOP 0x20 /* loopback mode */
|
|
|
|
|
|
-/*
|
|
|
- * The function call pointer type used to drive the chip select.
|
|
|
- */
|
|
|
-typedef void (*spi_chipsel_type)(int cs);
|
|
|
+/* SPI transfer flags */
|
|
|
+#define SPI_XFER_BEGIN 0x01 /* Assert CS before transfer */
|
|
|
+#define SPI_XFER_END 0x02 /* Deassert CS after transfer */
|
|
|
|
|
|
+/*-----------------------------------------------------------------------
|
|
|
+ * Representation of a SPI slave, i.e. what we're communicating with.
|
|
|
+ *
|
|
|
+ * Drivers are expected to extend this with controller-specific data.
|
|
|
+ *
|
|
|
+ * bus: ID of the bus that the slave is attached to.
|
|
|
+ * cs: ID of the chip select connected to the slave.
|
|
|
+ */
|
|
|
+struct spi_slave {
|
|
|
+ unsigned int bus;
|
|
|
+ unsigned int cs;
|
|
|
+};
|
|
|
|
|
|
/*-----------------------------------------------------------------------
|
|
|
* Initialization, must be called once on start up.
|
|
|
+ *
|
|
|
+ * TODO: I don't think we really need this.
|
|
|
*/
|
|
|
void spi_init(void);
|
|
|
|
|
|
+/*-----------------------------------------------------------------------
|
|
|
+ * Set up communications parameters for a SPI slave.
|
|
|
+ *
|
|
|
+ * This must be called once for each slave. Note that this function
|
|
|
+ * usually doesn't touch any actual hardware, it only initializes the
|
|
|
+ * contents of spi_slave so that the hardware can be easily
|
|
|
+ * initialized later.
|
|
|
+ *
|
|
|
+ * bus: Bus ID of the slave chip.
|
|
|
+ * cs: Chip select ID of the slave chip on the specified bus.
|
|
|
+ * max_hz: Maximum SCK rate in Hz.
|
|
|
+ * mode: Clock polarity, clock phase and other parameters.
|
|
|
+ *
|
|
|
+ * Returns: A spi_slave reference that can be used in subsequent SPI
|
|
|
+ * calls, or NULL if one or more of the parameters are not supported.
|
|
|
+ */
|
|
|
+struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
|
|
|
+ unsigned int max_hz, unsigned int mode);
|
|
|
+
|
|
|
+/*-----------------------------------------------------------------------
|
|
|
+ * Free any memory associated with a SPI slave.
|
|
|
+ *
|
|
|
+ * slave: The SPI slave
|
|
|
+ */
|
|
|
+void spi_free_slave(struct spi_slave *slave);
|
|
|
+
|
|
|
+/*-----------------------------------------------------------------------
|
|
|
+ * Claim the bus and prepare it for communication with a given slave.
|
|
|
+ *
|
|
|
+ * This must be called before doing any transfers with a SPI slave. It
|
|
|
+ * will enable and initialize any SPI hardware as necessary, and make
|
|
|
+ * sure that the SCK line is in the correct idle state. It is not
|
|
|
+ * allowed to claim the same bus for several slaves without releasing
|
|
|
+ * the bus in between.
|
|
|
+ *
|
|
|
+ * slave: The SPI slave
|
|
|
+ *
|
|
|
+ * Returns: 0 if the bus was claimed successfully, or a negative value
|
|
|
+ * if it wasn't.
|
|
|
+ */
|
|
|
+int spi_claim_bus(struct spi_slave *slave);
|
|
|
+
|
|
|
+/*-----------------------------------------------------------------------
|
|
|
+ * Release the SPI bus
|
|
|
+ *
|
|
|
+ * This must be called once for every call to spi_claim_bus() after
|
|
|
+ * all transfers have finished. It may disable any SPI hardware as
|
|
|
+ * appropriate.
|
|
|
+ *
|
|
|
+ * slave: The SPI slave
|
|
|
+ */
|
|
|
+void spi_release_bus(struct spi_slave *slave);
|
|
|
|
|
|
/*-----------------------------------------------------------------------
|
|
|
* SPI transfer
|
|
@@ -60,28 +125,67 @@ void spi_init(void);
|
|
|
* input data overwrites the output data (since both are buffered by
|
|
|
* temporary variables, this is OK).
|
|
|
*
|
|
|
- * If the chipsel() function is not NULL, it is called with a parameter
|
|
|
- * of '1' (chip select active) at the start of the transfer and again with
|
|
|
- * a parameter of '0' at the end of the transfer.
|
|
|
- *
|
|
|
- * If the chipsel() function _is_ NULL, it the responsibility of the
|
|
|
- * caller to make the appropriate chip select active before calling
|
|
|
- * spi_xfer() and making it inactive after spi_xfer() returns.
|
|
|
- *
|
|
|
* spi_xfer() interface:
|
|
|
- * chipsel: Routine to call to set/clear the chip select:
|
|
|
- * if chipsel is NULL, it is not used.
|
|
|
- * if(cs), make the chip select active (typically '0').
|
|
|
- * if(!cs), make the chip select inactive (typically '1').
|
|
|
- * dout: Pointer to a string of bits to send out. The bits are
|
|
|
- * held in a byte array and are sent MSB first.
|
|
|
- * din: Pointer to a string of bits that will be filled in.
|
|
|
- * bitlen: How many bits to write and read.
|
|
|
+ * slave: The SPI slave which will be sending/receiving the data.
|
|
|
+ * bitlen: How many bits to write and read.
|
|
|
+ * dout: Pointer to a string of bits to send out. The bits are
|
|
|
+ * held in a byte array and are sent MSB first.
|
|
|
+ * din: Pointer to a string of bits that will be filled in.
|
|
|
+ * flags: A bitwise combination of SPI_XFER_* flags.
|
|
|
*
|
|
|
* Returns: 0 on success, not 0 on failure
|
|
|
*/
|
|
|
-int spi_xfer(spi_chipsel_type chipsel, int bitlen, uchar *dout, uchar *din);
|
|
|
+int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *dout,
|
|
|
+ void *din, unsigned long flags);
|
|
|
+
|
|
|
+/*-----------------------------------------------------------------------
|
|
|
+ * Determine if a SPI chipselect is valid.
|
|
|
+ * This function is provided by the board if the low-level SPI driver
|
|
|
+ * needs it to determine if a given chipselect is actually valid.
|
|
|
+ *
|
|
|
+ * Returns: 1 if bus:cs identifies a valid chip on this board, 0
|
|
|
+ * otherwise.
|
|
|
+ */
|
|
|
+int spi_cs_is_valid(unsigned int bus, unsigned int cs);
|
|
|
+
|
|
|
+/*-----------------------------------------------------------------------
|
|
|
+ * Activate a SPI chipselect.
|
|
|
+ * This function is provided by the board code when using a driver
|
|
|
+ * that can't control its chipselects automatically (e.g.
|
|
|
+ * common/soft_spi.c). When called, it should activate the chip select
|
|
|
+ * to the device identified by "slave".
|
|
|
+ */
|
|
|
+void spi_cs_activate(struct spi_slave *slave);
|
|
|
+
|
|
|
+/*-----------------------------------------------------------------------
|
|
|
+ * Deactivate a SPI chipselect.
|
|
|
+ * This function is provided by the board code when using a driver
|
|
|
+ * that can't control its chipselects automatically (e.g.
|
|
|
+ * common/soft_spi.c). When called, it should deactivate the chip
|
|
|
+ * select to the device identified by "slave".
|
|
|
+ */
|
|
|
+void spi_cs_deactivate(struct spi_slave *slave);
|
|
|
+
|
|
|
+/*-----------------------------------------------------------------------
|
|
|
+ * Write 8 bits, then read 8 bits.
|
|
|
+ * slave: The SPI slave we're communicating with
|
|
|
+ * byte: Byte to be written
|
|
|
+ *
|
|
|
+ * Returns: The value that was read, or a negative value on error.
|
|
|
+ *
|
|
|
+ * TODO: This function probably shouldn't be inlined.
|
|
|
+ */
|
|
|
+static inline int spi_w8r8(struct spi_slave *slave, unsigned char byte)
|
|
|
+{
|
|
|
+ unsigned char dout[2];
|
|
|
+ unsigned char din[2];
|
|
|
+ int ret;
|
|
|
+
|
|
|
+ dout[0] = byte;
|
|
|
+ dout[1] = 0;
|
|
|
|
|
|
-int spi_select(unsigned int bus, unsigned int dev, unsigned long mode);
|
|
|
+ ret = spi_xfer(slave, 16, dout, din, SPI_XFER_BEGIN | SPI_XFER_END);
|
|
|
+ return ret < 0 ? ret : din[1];
|
|
|
+}
|
|
|
|
|
|
#endif /* _SPI_H_ */
|