qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [PATCH 13/18] hw: add QEMU model for Faraday multi-function


From: Dante
Subject: [Qemu-devel] [PATCH 13/18] hw: add QEMU model for Faraday multi-function SSP controller: SPI and I2S
Date: Fri, 18 Jan 2013 14:32:09 +0800

Signed-off-by: Kuo-Jung Su <address@hidden>
---
 hw/ftssp010.c |  526 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 hw/ftssp010.h |  103 +++++++++++
 2 files changed, 629 insertions(+)
 create mode 100644 hw/ftssp010.c
 create mode 100644 hw/ftssp010.h

diff --git a/hw/ftssp010.c b/hw/ftssp010.c
new file mode 100644
index 0000000..61ce495
--- /dev/null
+++ b/hw/ftssp010.c
@@ -0,0 +1,526 @@
+/*
+ * QEMU model of the FTSSP010 Controller
+ *
+ * Copyright (C) 2012 Faraday Technology
+ * Copyright (C) 2012 Dante Su <address@hidden>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to 
deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "sysbus.h"
+#include "sysemu/sysemu.h"
+#include "fifo.h"
+#include "i2c.h"
+#include "ssi.h"
+#include "ftssp010.h"
+
+#define CFG_FIFO_DEPTH    16
+
+typedef struct {
+    SysBusDevice busdev;
+    MemoryRegion mmio;
+
+    qemu_irq irq;
+    SSIBus *spi;
+    
+    uint8_t num_cs;
+    qemu_irq *cs_lines;
+    
+    Fifo8 rx_fifo;
+    Fifo8 tx_fifo;
+
+    uint8_t tx_thres;
+    uint8_t rx_thres;
+    
+    int busy;
+    uint8_t bw;
+    
+    /* I2S */
+    void *codec_i2c;
+    char *codec_name;
+    uint8_t codec_addr;
+    void *codec;
+    void (*codec_out)(void *, uint32_t);
+    uint32_t (*codec_in)(void *);
+
+    /* DMA hardware handshake */
+    qemu_irq req[2];    /* 0 - Tx, 1 - Rx */
+
+    /* HW register caches */
+
+    uint32_t cr0;
+    uint32_t cr1;
+    uint32_t cr2;    
+    uint32_t icr;    /* interrupt control register */
+    uint32_t isr;    /* interrupt status register */
+
+} ftssp010_state;
+
+/* Update interrupts.  */
+static void ftssp010_update(ftssp010_state *s)
+{
+    if (!(s->cr2 & CR2_SSPEN))
+        return;
+
+    /* tx fifo status update */
+    if ((s->tx_fifo.num / (s->bw >> 3)) <= s->tx_thres) {
+        s->isr |=  ISR_TFTHI;
+        if (s->icr & ICR_TFDMA)
+            qemu_set_irq(s->req[0], 1);
+    } else {
+        s->isr &= ~ISR_TFTHI;
+    }
+
+    /* rx fifo status update */
+    switch(s->cr0 & 0x00007000) {
+    case CR0_FFMT_SPI:
+        s->isr |=  ISR_RFTHI;
+        if (s->icr & ICR_RFDMA)
+            qemu_set_irq(s->req[1], 1);
+        break;
+    default:
+        if ((s->rx_fifo.num / (s->bw >> 3)) >= s->rx_thres) {
+            s->isr |=  ISR_RFTHI;
+            if (s->icr & ICR_RFDMA)
+                qemu_set_irq(s->req[1], 1);
+        } else {
+            s->isr &= ~ISR_RFTHI;
+        }
+        break;
+    }
+
+    /* update the interrupt signal */
+    if ((s->icr & s->isr) & 0x0f)
+        qemu_set_irq(s->irq, 1);
+    else
+        qemu_set_irq(s->irq, 0);
+}
+
+static void ftssp010_handle_ack(void *opaque, int line, int level)
+{
+    ftssp010_state *s = (ftssp010_state *)opaque;
+
+    switch(line) {
+    case 0:    /* Tx */
+        if (s->icr & ICR_TFDMA) {
+            if (level)
+                qemu_set_irq(s->req[0], 0);
+            if ((s->tx_fifo.num / (s->bw >> 3)) <= s->tx_thres)
+                qemu_set_irq(s->req[0], 1);
+        }
+        break;
+    case 1:    /* Rx */
+        if (s->icr & ICR_RFDMA) {
+            if (level)
+                qemu_set_irq(s->req[1], 0);
+            switch(s->cr0 & 0x00007000) {
+            case CR0_FFMT_SPI:
+                qemu_set_irq(s->req[1], 1);
+                break;
+            default:
+                if ((s->rx_fifo.num / (s->bw >> 3)) >= s->rx_thres)
+                    qemu_set_irq(s->req[1], 1);
+                break;
+            }
+        }
+        break;
+    default:
+        break;
+    }
+}
+
+static void ftssp010_i2s_data_req(void *opaque, int tx, int rx)
+{
+    int len;
+    uint32_t sample;
+    ftssp010_state *s = opaque;
+
+    if (!(s->cr2 & CR2_SSPEN))
+        return;
+
+    if ((s->cr0 & 0x00007000) != CR0_FFMT_I2S)
+        return;
+
+    s->busy = 1;
+
+    if ((s->cr2 & (CR2_TXEN | CR2_TXDOE)) == (CR2_TXEN | CR2_TXDOE)) {
+        len = tx * (s->bw / 8);
+        while (!fifo8_is_empty(&s->tx_fifo) && len > 0) {
+            sample = fifo8_pop(&s->tx_fifo) << 0;
+            --len;
+            if (s->bw > 8) {
+                sample |= fifo8_pop(&s->tx_fifo) << 8;
+                --len;
+            }
+            if (s->bw > 16) {
+                sample |= fifo8_pop(&s->tx_fifo) << 16;
+                --len;
+            }
+            if (s->bw > 24) {
+                sample |= fifo8_pop(&s->tx_fifo) << 24;
+                --len;
+            }
+            s->codec_out(s->codec, sample);
+        }
+
+        if (fifo8_is_empty(&s->tx_fifo) && len > 0)
+            s->isr |= ISR_TFURI;
+    }
+
+    if (s->cr2 & CR2_RXEN) {
+        len = rx * (s->bw / 8);
+        while (!fifo8_is_full(&s->rx_fifo) && len > 0) {
+            sample = s->codec_in(s->codec);
+            fifo8_push(&s->rx_fifo, (sample >>  0) & 0xff);
+            --len;
+            if (s->bw > 8) {
+                fifo8_push(&s->rx_fifo, (sample >>  8) & 0xff);
+                --len;
+            }
+            if (s->bw > 16) {
+                fifo8_push(&s->rx_fifo, (sample >> 16) & 0xff);
+                --len;
+            }
+            if (s->bw > 24) {
+                fifo8_push(&s->rx_fifo, (sample >> 24) & 0xff);
+                --len;
+            }
+        }
+        
+        if (fifo8_is_full(&s->rx_fifo) && len > 0)
+            s->isr |= ISR_RFORI;
+    }
+    
+    s->busy = 0;
+    
+    ftssp010_update(s);
+}
+
+static void ftssp010_spi_tx(ftssp010_state *s)
+{
+    if (!(s->cr2 & CR2_TXEN))
+        return;
+
+    s->busy = 1;
+
+    if (fifo8_is_empty(&s->tx_fifo))
+        s->isr |= ISR_TFURI;
+
+    while(!fifo8_is_empty(&s->tx_fifo))
+        ssi_transfer(s->spi, fifo8_pop(&s->tx_fifo));
+
+    s->busy = 0;
+}
+
+
+static uint64_t ftssp010_mem_read(void *opaque, hwaddr addr, unsigned int size)
+{
+    ftssp010_state *s = opaque;
+    uint32_t rc = 0;
+
+    switch (addr) {
+    case REG_CR0:    /* Control Register 0 */
+        return s->cr0;
+    case REG_CR1:    /* Control Register 1 */
+        return s->cr1;
+    case REG_CR2:    /* Control Register 2 */
+        return s->cr2;
+    case REG_STR:    /* Status Register */
+        rc |= s->busy ? 0x04 : 0x00;
+        /* tx fifo status */
+        rc |= STR_TFVE(s->tx_fifo.num / (s->bw >> 3));
+        if (!fifo8_is_full(&s->tx_fifo))
+            rc |= STR_TFNF;
+        /* rx fifo status */
+        switch(s->cr0 & 0x00007000) {
+        case CR0_FFMT_SPI:
+            rc |= STR_RFF | STR_RFVE(CFG_FIFO_DEPTH);
+            break;
+        case CR0_FFMT_I2S:
+            rc |= STR_RFVE(s->rx_fifo.num / (s->bw >> 3));
+            if (fifo8_is_full(&s->rx_fifo))
+                rc |= STR_RFF;
+            break;
+        default:
+            break;
+        }
+        break;
+    case REG_ICR:    /* Interrupt Control Register */
+        return s->icr;
+    case REG_ISR:    /* Interrupt Status Register */
+        rc = s->isr;
+        s->isr &= 0xffffffec;    /* Clear BIT0, BIT1, BIT4 */
+        ftssp010_update(s);
+        break;
+    case REG_DTR:    /* Data Register */
+        if (!(s->cr2 & CR2_SSPEN))
+            break;
+        if (!(s->cr2 & CR2_RXEN))
+            break;
+        switch(s->cr0 & 0x00007000) {
+        case CR0_FFMT_SPI:
+            rc |= (uint32_t)(ssi_transfer(s->spi, 0x00) & 0xff) << 0;
+            if (s->bw > 8)
+                rc |= (uint32_t)(ssi_transfer(s->spi, 0x00) & 0xff) << 8;
+            if (s->bw > 16)
+                rc |= (uint32_t)(ssi_transfer(s->spi, 0x00) & 0xff) << 16;
+            if (s->bw > 24)
+                rc |= (uint32_t)(ssi_transfer(s->spi, 0x00) & 0xff) << 24;
+            break;
+        case CR0_FFMT_I2S:
+            if (!fifo8_is_empty(&s->rx_fifo))
+                rc |= fifo8_pop(&s->rx_fifo);
+            if (!fifo8_is_empty(&s->rx_fifo) && s->bw > 8)
+                rc |= fifo8_pop(&s->rx_fifo) << 8;
+            if (!fifo8_is_empty(&s->rx_fifo) && s->bw > 16)
+                rc |= fifo8_pop(&s->rx_fifo) << 16;
+            if (!fifo8_is_empty(&s->rx_fifo) && s->bw > 24)
+                rc |= fifo8_pop(&s->rx_fifo) << 24;
+            break;
+        default:
+            break;
+        }
+        ftssp010_update(s);
+        break;
+    case REG_VER:
+        return 0x00011901;    /* ver. 1.19.1 */
+    case REG_FEA:
+        return 0x660f0f1f;    /* SPI+I2S, FIFO=16 */
+    default:
+        break;
+    }
+
+    return rc;
+}
+
+static void ftssp010_mem_write(void *opaque, hwaddr addr, uint64_t val, 
unsigned int size)
+{
+    ftssp010_state *s = opaque;
+    
+    switch (addr) {
+    case REG_CR0:    /* Control Register 0 */
+        s->cr0 = (uint32_t)val;
+        break;
+    case REG_CR1:    /* Control Register 1 */
+        s->cr1 = (uint32_t)val;
+        s->bw  = ((s->cr1 >> 16) & 0x3f) + 1;
+        break;
+    case REG_CR2:    /* Control Register 2 */
+        s->cr2 = (uint32_t)val;
+        if (s->cr2 & CR2_SSPRST) {
+            fifo8_reset(&s->tx_fifo);
+            fifo8_reset(&s->rx_fifo);
+            s->busy = 0;
+            s->cr2 &= ~(CR2_SSPRST | CR2_TXFCLR | CR2_RXFCLR);
+            if (s->cr0 & CR0_FLASH) {
+                int cs = (s->cr2 >> 10) & 0x03;
+                qemu_set_irq(s->cs_lines[cs], 1);
+                s->cr2 |= CR2_FS;
+            };
+        }
+        if (s->cr2 & CR2_TXFCLR) {
+            fifo8_reset(&s->tx_fifo);
+            s->cr2 &= ~CR2_TXFCLR;
+        }
+        if (s->cr2 & CR2_RXFCLR) {
+            fifo8_reset(&s->rx_fifo);
+            s->cr2 &= ~CR2_RXFCLR;
+        }
+        if (s->cr0 & CR0_FLASH) {
+            int cs = (s->cr2 >> 10) & 0x03;
+            qemu_set_irq(s->cs_lines[cs], (s->cr2 & CR2_FS) ? 1 : 0);
+        }
+        if (s->cr2 & CR2_SSPEN) {
+            switch(s->cr0 & 0x00007000) {
+            case CR0_FFMT_SPI:
+                ftssp010_spi_tx(s);
+                break;
+            default:
+                break;
+            }
+        }
+        ftssp010_update(s);
+        break;
+    case REG_ICR:    /* Interrupt Control Register */
+        s->icr = (uint32_t)val;
+        s->tx_thres = (s->icr >> 12) & 0x1f;
+        s->rx_thres = (s->icr >>  7) & 0x1f;
+        break;
+    case REG_DTR:    /* Data Register */
+        if (!(s->cr2 & CR2_SSPEN))
+            break;
+        if (!fifo8_is_full(&s->tx_fifo))
+            fifo8_push(&s->tx_fifo, (uint8_t)val);
+        if (!fifo8_is_full(&s->tx_fifo) && s->bw > 8)
+            fifo8_push(&s->tx_fifo, (uint8_t)(val >> 8));
+        if (!fifo8_is_full(&s->tx_fifo) && s->bw > 16)
+            fifo8_push(&s->tx_fifo, (uint8_t)(val >> 16));
+        if (!fifo8_is_full(&s->tx_fifo) && s->bw > 24)
+            fifo8_push(&s->tx_fifo, (uint8_t)(val >> 24));
+        switch(s->cr0 & 0x00007000) {
+        case CR0_FFMT_SPI:
+            ftssp010_spi_tx(s);
+            break;
+        default:
+            break;
+        }
+        ftssp010_update(s);
+        break;
+    default:
+        break;
+    }
+}
+
+static const MemoryRegionOps spi_ops = {
+    .read  = ftssp010_mem_read,
+    .write = ftssp010_mem_write,
+    .endianness = DEVICE_LITTLE_ENDIAN,
+    .valid = {
+        .min_access_size = 1,
+        .max_access_size = 4
+    }
+};
+
+static void ftssp010_reset(DeviceState *d)
+{
+    ftssp010_state *s = DO_UPCAST(ftssp010_state, busdev.qdev, d);
+
+    s->busy = 0;
+    s->bw   = 8;
+    
+    s->cr0 = 0;
+    s->cr1 = 0;
+    s->cr2 = 0;
+    s->icr = 0x00002200;
+    s->isr = 0x00000008;
+
+    s->tx_thres = 0;
+    s->rx_thres = 0;
+
+    fifo8_reset(&s->tx_fifo);
+    fifo8_reset(&s->rx_fifo);
+    
+    ftssp010_update(s);        
+}
+
+static int ftssp010_init(SysBusDevice *dev)
+{
+    int i;
+    ftssp010_state *s = FROM_SYSBUS(typeof(*s), dev);
+
+    s->spi = ssi_create_bus(&dev->qdev, "spi");
+
+    fifo8_create(&s->tx_fifo, CFG_FIFO_DEPTH * 4);
+    fifo8_create(&s->rx_fifo, CFG_FIFO_DEPTH * 4);
+
+    memory_region_init_io(&s->mmio, &spi_ops, s, "ftssp010", 0x1000);
+    sysbus_init_mmio(dev, &s->mmio);
+    sysbus_init_irq(dev, &s->irq);
+
+    s->num_cs = 4;
+    s->cs_lines = g_new(qemu_irq, s->num_cs);
+    ssi_auto_connect_slaves(DEVICE(s), s->cs_lines, s->spi);
+    for (i = 0; i < s->num_cs; ++i) {
+        sysbus_init_irq(dev, &s->cs_lines[i]);
+    }
+    
+    /* DMA hardware handshake */
+    qdev_init_gpio_in (&s->busdev.qdev, ftssp010_handle_ack, 2);
+    qdev_init_gpio_out(&s->busdev.qdev, s->req, 2);
+
+    /* I2S */
+    if (s->codec_i2c) {
+        DeviceState *wm;
+        const char *id = "wm8731";
+        
+        if (s->codec_name)
+            id = s->codec_name;
+
+        printf("[qemu] ftssp010: i2c bus registered, connecting 
codec[%s:0x%x]...\n",
+               id, s->codec_addr);
+
+        /* Attach a codec to the bus */
+        wm = i2c_create_slave(s->codec_i2c, id, s->codec_addr);
+        s->codec = wm;
+        if (!strcmp(id, "wm8731")) {
+            s->codec_out = wm8731_dac_dat;
+            s->codec_in  = wm8731_adc_dat;
+            wm8731_data_req_set(wm, ftssp010_i2s_data_req, s);
+        } else if (!strcmp(id, "wm8750")) {
+            s->codec_out = wm8750_dac_dat;
+            s->codec_in  = wm8750_adc_dat;
+            wm8750_data_req_set(wm, ftssp010_i2s_data_req, s);
+        } else {
+            printf("[qemu] ftssp010: unknown codec [%s] ?\n", id);
+            return -1;
+        }
+    }
+
+    return 0;
+}
+
+static Property ftssp010_properties[] = {
+    DEFINE_PROP_PTR   ("codec_i2c",  ftssp010_state, codec_i2c),
+    DEFINE_PROP_STRING("codec_name", ftssp010_state, codec_name),
+    DEFINE_PROP_UINT8 ("codec_addr", ftssp010_state, codec_addr, 0x1B),
+    DEFINE_PROP_END_OF_LIST(),
+};
+
+static const VMStateDescription vmstate_ftssp010 = {
+    .name = "ftssp010",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 1,
+    .fields = (VMStateField[]) {
+        VMSTATE_UINT32(cr0, ftssp010_state),
+        VMSTATE_UINT32(cr1, ftssp010_state),
+        VMSTATE_UINT32(cr2, ftssp010_state),
+        VMSTATE_UINT32(icr, ftssp010_state),
+        VMSTATE_UINT32(isr, ftssp010_state),
+        VMSTATE_FIFO8(tx_fifo, ftssp010_state),
+        VMSTATE_FIFO8(rx_fifo, ftssp010_state),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static void ftssp010_class_init(ObjectClass *klass, void *data)
+{
+    SysBusDeviceClass *sdc = SYS_BUS_DEVICE_CLASS(klass);
+    DeviceClass *k = DEVICE_CLASS(klass);    
+
+    sdc->init = ftssp010_init;
+    k->vmsd   = &vmstate_ftssp010;
+    k->props  = ftssp010_properties;
+    k->reset  = ftssp010_reset;
+    k->no_user= 1;
+}
+
+static TypeInfo ftssp010_info = {
+    .name           = "ftssp010",
+    .parent         = TYPE_SYS_BUS_DEVICE,
+    .instance_size  = sizeof(ftssp010_state),
+    .class_init     = ftssp010_class_init,
+};
+
+static void ftssp010_register_types(void)
+{
+    type_register_static(&ftssp010_info);
+}
+
+type_init(ftssp010_register_types)
diff --git a/hw/ftssp010.h b/hw/ftssp010.h
new file mode 100644
index 0000000..df1f27e
--- /dev/null
+++ b/hw/ftssp010.h
@@ -0,0 +1,103 @@
+/*
+ * (C) Copyright 2010
+ * Faraday Technology Inc. <www.faraday-tech.com>
+ * Dante Su <address@hidden>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#ifndef FTSSP010_H
+#define FTSSP010_H
+
+/* FTSSP010: Registers */
+#define REG_CR0            0x00
+#define REG_CR1            0x04
+#define REG_CR2            0x08
+#define REG_STR            0x0C
+#define REG_ICR            0X10
+#define REG_ISR            0x14
+#define REG_DTR            0x18
+#define REG_VER            0x60
+#define REG_FEA            0x64
+
+/* Control register 0  */
+
+#define CR0_FFMT_SSP                (0 << 12)
+#define CR0_FFMT_SPI                (1 << 12)
+#define CR0_FFMT_MICROWIRE            (2 << 12)
+#define CR0_FFMT_I2S                (3 << 12)
+#define CR0_FFMT_AC97                (4 << 12)
+#define CR0_FLASH                    (1 << 11)
+#define CR0_FSDIST(x)                (((x) & 0x03) << 8)
+#define CR0_LBM                        (1 << 7)  /* Loopback mode */
+#define CR0_LSB                        (1 << 6)  /* LSB first */
+#define CR0_FSPO                    (1 << 5)  /* Frame sync atcive low */
+#define CR0_FSJUSTIFY                (1 << 4)  /* Data padding in front of 
serial data */
+#define CR0_OPM_SLAVE                (0 << 2)
+#define CR0_OPM_MASTER                (3 << 2)
+#define CR0_OPM_I2S_MSST            (3 << 2)  /* Master stereo mode */
+#define CR0_OPM_I2S_MSMO            (2 << 2)  /* Master mono mode */
+#define CR0_OPM_I2S_SLST            (1 << 2)  /* Slave stereo mode */
+#define CR0_OPM_I2S_SLMO            (0 << 2)  /* Slave mono mode */
+#define CR0_SCLKPO                    (1 << 1)  /* SCLK Remain HIGH */
+#define CR0_SCLKPH                    (1 << 0)  /* Half CLK cycle */
+
+/* Control Register 1 */
+
+#define CR1_PDL(x)                    (((x) & 0xff) << 24)        /* padding 
data length */
+#define CR1_SDL(x)                    ((((x) - 1) & 0x1f) << 16)    /* serial 
data length(actual data length-1) */
+#define CR1_CLKDIV(x)                ((x) & 0xffff)                /*  clk 
divider */
+
+/* Control Register 2 */
+#define CR2_FSOS(x)                    (((x) & 0x03) << 10)        /* FS/CS 
Select */
+#define CR2_FS                        (1 << 9)    /* FS/CS Signal Level */
+#define CR2_TXEN                    (1 << 8)    /* Tx Enable */
+#define CR2_RXEN                    (1 << 7)    /* Rx Enable */
+#define CR2_SSPRST                    (1 << 6)    /* SSP reset */
+#define CR2_TXFCLR                    (1 << 3)    /* TX FIFO Clear */
+#define CR2_RXFCLR                    (1 << 2)    /* RX FIFO Clear */
+#define CR2_TXDOE                    (1 << 1)    /* TX Data Output Enable */
+#define CR2_SSPEN                    (1 << 0)    /* SSP Enable */
+
+/*
+ * Status Register
+ */
+#define STR_TFVE(reg)                (((reg) & 0x1F) << 12)
+#define STR_RFVE(reg)                (((reg) & 0x1F) << 4)
+#define STR_BUSY                    (1 << 2)
+#define STR_TFNF                    (1 << 1)    /* Tx FIFO Not Full */
+#define STR_RFF                        (1 << 0)    /* Rx FIFO Full */
+
+/* Interrupr Control Register */
+#define ICR_TFTHOD(x)                (((x) & 0x0f) << 12)    /* TX FIFO 
Threshold */
+#define ICR_RFTHOD(x)                (((x) & 0x0f) << 8)        /* RX FIFO 
Threshold */
+#define ICR_TFDMA                    0x20      /* TX DMA Enable */
+#define ICR_RFDMA                    0x10      /* RX DMA Enable */
+#define ICR_TFTHI                    0x08      /* TX FIFO Int Enable */
+#define ICR_RFTHI                    0x04      /* RX FIFO Int Enable */
+#define ICR_TFURI                    0x02      /* TX FIFO Underrun int enable 
*/
+#define ICR_RFORI                    0x01      /* RX FIFO Overrun int enable */
+
+/* Interrupr Status Register */
+#define ISR_TFTHI                    0x08      /* TX FIFO Int Enable */
+#define ISR_RFTHI                    0x04      /* RX FIFO Int Enable */
+#define ISR_TFURI                    0x02      /* TX FIFO Underrun int enable 
*/
+#define ISR_RFORI                    0x01      /* RX FIFO Overrun int enable */
+
+#endif
-- 
1.7.9.5


********************* Confidentiality Notice ************************
This electronic message and any attachments may contain
confidential and legally privileged information or
information which is otherwise protected from disclosure.
If you are not the intended recipient,please do not disclose
the contents, either in whole or in part, to anyone,and
immediately delete the message and any attachments from
your computer system and destroy all hard copies.
Thank you for your cooperation.
***********************************************************************




reply via email to

[Prev in Thread] Current Thread [Next in Thread]