lm3s1968: generic KFile-compliant SSI bus implementation.
[bertos.git] / bertos / cpu / cortex-m3 / drv / ssi_lm3s.h
index 901f62885bb6e06bc8059df0c97123d6c23d7cf7..1bbceee36e2f129793ae5575e4cbe35f0fc5c9c7 100644 (file)
@@ -37,6 +37,8 @@
 #define SSI_LM3S_H
 
 #include <cpu/power.h> /* cpu_relax() */
+#include <kern/kfile.h> /* KFile */
+#include <io/lm3s.h>
 
 /**
  * LM3S1968 SSI frame format
 #define SSI_MODE_SLAVE_OD       0x00000002  //< SSI slave with output disabled
 /*\}*/
 
-int lm3s_ssi_init(uint32_t base, uint32_t frame, int mode,
-                   unsigned int bitrate, unsigned int data_width);
-void lm3s_ssi_enable(uint32_t base);
-void lm3s_ssi_disable(uint32_t base);
-void lm3s_ssi_write_frame(uint32_t base, uint32_t val);
-int lm3s_ssi_write_frame_nonblocking(uint32_t base, uint32_t val);
-void lm3s_ssi_read_frame(uint32_t base, uint32_t *val);
-int lm3s_ssi_read_frame_nonblocking(uint32_t base, uint32_t *val);
-bool lm3s_ssi_txdone(uint32_t base);
-
-INLINE void lm3s_ssi_wait_txdone(uint32_t base)
+/* LM3S SSI handle properties */
+enum
 {
-       while (!lm3s_ssi_txdone(base))
+       /* Non-blocking I/O */
+       LM3S_SSI_NONBLOCK = 1,
+};
+
+/** LM3S1968 SSI handle structure */
+typedef struct LM3SSSI
+{
+       /* SSI Kfile structure */
+       KFile fd;
+
+       /* Handle properties */
+       uint32_t flags;
+
+       /* SSI port address */
+       uint32_t addr;
+} LM3SSSI;
+
+/**
+ * ID for LM3S SSI.
+ */
+#define KFT_LM3SSSI MAKE_ID('L', 'S', 'S', 'I')
+
+INLINE LM3SSSI *LM3SSSI_CAST(KFile *fd)
+{
+       ASSERT(fd->_type == KFT_LM3SSSI);
+       return (LM3SSSI *)fd;
+}
+
+/* KFile interface to LM3S SSI */
+void lm3s_ssiInit(struct LM3SSSI *fds, uint32_t addr, uint32_t frame, int mode,
+                       int bitrate, uint32_t data_width);
+
+/* Raw interface to LM3S SSI */
+int lm3s_ssiOpen(uint32_t addr, uint32_t frame, int mode,
+                       int bitrate, uint32_t data_width);
+
+/*
+ * Check if the SSI transmitter is busy or not
+ *
+ * This allows to determine whether the TX FIFO have been cleared by the
+ * hardware, so the transmission can be safely considered completed.
+ */
+INLINE bool lm3s_ssiTxDone(uint32_t base)
+{
+       return (HWREG(base + SSI_O_SR) & SSI_SR_BSY) ? true : false;
+}
+
+/*
+ * Check if the SSI TX FIFO is full
+ */
+INLINE bool lm3s_ssiTxReady(uint32_t base)
+{
+       return (HWREG(base + SSI_O_SR) & SSI_SR_TNF) ? true : false;
+}
+
+/*
+ * Check for data available in the RX FIFO
+ */
+INLINE bool lm3s_ssiRxReady(uint32_t base)
+{
+       return (HWREG(base + SSI_O_SR) & SSI_SR_RNE) ? true : false;
+}
+
+/*
+ * Get a frame into the SSI receive FIFO without blocking.
+ *
+ * Return the number of frames read from the RX FIFO.
+ */
+INLINE int lm3s_ssiReadFrameNonBlocking(uint32_t base, uint32_t *val)
+{
+       /* Check for data available in the RX FIFO */
+       if (!lm3s_ssiRxReady(base))
+               return 0;
+       /* Read data from SSI RX FIFO */
+       *val = HWREG(base + SSI_O_DR);
+       return 1;
+}
+
+/*
+ * Get a frame from the SSI receive FIFO.
+ */
+INLINE void lm3s_ssiReadFrame(uint32_t base, uint32_t *val)
+{
+       /* Wait for data available in the RX FIFO */
+       while (!lm3s_ssiRxReady(base))
+               cpu_relax();
+       /* Read data from SSI RX FIFO */
+       *val = HWREG(base + SSI_O_DR);
+}
+
+/*
+ * Put a frame into the SSI transmit FIFO without blocking.
+ *
+ * NOTE: the upper bits of the frame will be automatically discarded by the
+ * hardware according to the frame data width.
+ *
+ * Return the number of frames written to the TX FIFO.
+ */
+INLINE int lm3s_ssiWriteFrameNonBlocking(uint32_t base, uint32_t val)
+{
+       /* Check for available space in the TX FIFO */
+       if (!lm3s_ssiTxReady(base))
+               return 0;
+       /* Enqueue data to the TX FIFO */
+       HWREG(base + SSI_O_DR) = val;
+       return 1;
+}
+
+/*
+ * Put a frame into the SSI transmit FIFO.
+ *
+ * NOTE: the upper bits of the frame will be automatically discarded by the
+ * hardware according to the frame data width.
+ */
+INLINE void lm3s_ssiWriteFrame(uint32_t base, uint32_t val)
+{
+       /* Wait for available space in the TX FIFO */
+       while (!lm3s_ssiTxReady(base))
                cpu_relax();
+       /* Enqueue data to the TX FIFO */
+       HWREG(base + SSI_O_DR) = val;
 }
 
 #endif /* SSI_LM3S_H */