initial SPI support for OMAP3
authorJuha Riihimäki <juhriihi@esdhcp035159.research.nokia.com>
Mon, 23 Mar 2009 13:56:04 +0000 (15:56 +0200)
committerJuha Riihimäki <juhriihi@esdhcp035159.research.nokia.com>
Mon, 23 Mar 2009 13:56:04 +0000 (15:56 +0200)
hw/omap.h
hw/omap2.c
hw/omap3.c
hw/omap_clk.c
hw/omap_dma.c
hw/soc_dma.c
hw/soc_dma.h

index 055a112..1f79ea4 100644 (file)
--- a/hw/omap.h
+++ b/hw/omap.h
@@ -441,9 +441,9 @@ void omap_gpmc_attach(struct omap_gpmc_s *s, int cs, int iomemtype,
 #define OMAP_INT_3XXX_BENCH         3  /* MPU emulation */
 #define OMAP_INT_3XXX_MCBSP2_ST_IRQ 4  /* Sidetone MCBSP2 overflow */
 #define OMAP_INT_3XXX_MCBSP3_ST_IRQ 5  /* Sidetone MCBSP3 overflow */
-/* IRQ6 is reserved */
+#define OMAP_INT_3XXX_SSM_ABORT_IRQ 6
 #define OMAP_INT_3XXX_SYS_NIRQ      7  /* External source (active low) */
-/* IRQ8 is reserved */
+#define OMAP_INT_3XXX_D2D_FW_IRQ    8
 #define OMAP_INT_3XXX_SMX_DBG_IRQ   9  /* L3 interconnect error for debug */
 #define OMAP_INT_3XXX_SMX_APP_IRQ   10 /* L3 interconnect error for application */
 #define OMAP_INT_3XXX_PRCM_MPU_IRQ  11 /* PRCM module IRQ */
@@ -470,7 +470,7 @@ void omap_gpmc_attach(struct omap_gpmc_s *s, int cs, int iomemtype,
 #define OMAP_INT_3XXX_GPIO4_MPU_IRQ 32 /* GPIO module 4 */
 #define OMAP_INT_3XXX_GPIO5_MPU_IRQ 33 /* GPIO module 5 */
 #define OMAP_INT_3XXX_GPIO6_MPU_IRQ 34 /* GPIO module 6 */
-/* IRQ35 is reserved */
+#define OMAP_INT_3XXX_USIM_IRQ      35
 #define OMAP_INT_3XXX_WDT3_IRQ      36 /* Watchdog timer module 3 overflow */
 #define OMAP_INT_3XXX_GPT1_IRQ      37 /* General-purpose timer module 1 */
 #define OMAP_INT_3XXX_GPT2_IRQ      38 /* General-purpose timer module 2 */
@@ -483,11 +483,11 @@ void omap_gpmc_attach(struct omap_gpmc_s *s, int cs, int iomemtype,
 #define OMAP_INT_3XXX_GPT9_IRQ      45 /* General-purpose timer module 9 */
 #define OMAP_INT_3XXX_GPT10_IRQ     46 /* General-purpose timer module 10 */
 #define OMAP_INT_3XXX_GPT11_IRQ     47 /* General-purpose timer module 11 */
-#define OMAP_INT_3XXX_SPI4_IRQ      48 /* MCSPI module 4 */
-/* IRQ49 is reserved */
-/* IRQ50 is reserved */
-/* IRQ51 is reserved */
-/* IRQ52 is reserved */
+#define OMAP_INT_3XXX_MCSPI4_IRQ    48 /* MCSPI module 4 */
+#define OMAP_INT_3XXX_SHA1MD52_IRQ  49
+#define OMAP_INT_3XXX_FPKA_READY    50
+#define OMAP_INT_3XXX_SHA1MD51_IRQ  51
+#define OMAP_INT_3XXX_RNG_IRQ       52
 #define OMAP_INT_3XXX_MG_IRQ        53
 #define OMAP_INT_3XXX_MCBSP4_IRQ_TX 54 /* MCBSP module 4 transmit */
 #define OMAP_INT_3XXX_MCBSP4_IRQ_RX 55 /* MCBSP module 4 receive */
@@ -499,7 +499,7 @@ void omap_gpmc_attach(struct omap_gpmc_s *s, int cs, int iomemtype,
 #define OMAP_INT_3XXX_I2C3_IRQ      61 /* I2C module 3 */
 #define OMAP_INT_3XXX_MCBSP2_IRQ_TX 62 /* MCBSP module 2 transmit */
 #define OMAP_INT_3XXX_MCBSP2_IRQ_RX 63 /* MCBSP module 2 receive */
-/* IRQ64 is reserved */
+#define OMAP_INT_3XXX_FPKA_ERROR    64
 #define OMAP_INT_3XXX_MCSPI1_IRQ    65 /* MCSPI module 1 */
 #define OMAP_INT_3XXX_MCSPI2_IRQ    66 /* MCSPI module 2 */
 /* IRQ67 is reserved */
@@ -547,6 +547,10 @@ struct soc_dma_s *omap_dma_init(target_phys_addr_t base, qemu_irq *irqs,
 struct soc_dma_s *omap_dma4_init(target_phys_addr_t base, qemu_irq *irqs,
                 struct omap_mpu_state_s *mpu, int fifo,
                 int chans, omap_clk iclk, omap_clk fclk);
+struct soc_dma_s *omap3_dma4_init(struct omap_target_agent_s *ta,
+                                  struct omap_mpu_state_s *mpu,
+                                  qemu_irq *irqs, int chans,
+                                  omap_clk iclk, omap_clk fclk);
 void omap_dma_reset(struct soc_dma_s *s);
 
 struct dma_irq_map {
@@ -794,7 +798,7 @@ struct omap_dma_lcd_channel_s {
 #define OMAP3XXX_DMA_SPI1_TX2         39
 #define OMAP3XXX_DMA_SPI1_RX2         40
 #define OMAP3XXX_DMA_SPI1_TX3         41
-#define OMAP3XXX_DMA_SPI1_RX4         42
+#define OMAP3XXX_DMA_SPI1_RX3         42
 #define OMAP3XXX_DMA_SPI2_TX0         43
 #define OMAP3XXX_DMA_SPI2_RX0         44
 #define OMAP3XXX_DMA_SPI2_TX1         45
@@ -812,7 +816,11 @@ struct omap_dma_lcd_channel_s {
 #define OMAP3XXX_DMA_MMC1_RX          62
 #define OMAP3XXX_DMA_MS               63
 #define OMAP3XXX_DMA_EXT_DMAREQ3      64
-
+#define OMAP3XXX_DMA_AES2_TX          65
+#define OMAP3XXX_DMA_AES2_RX          66
+#define OMAP3XXX_DMA_DES2_TX          67
+#define OMAP3XXX_DMA_DES2_RX          68
+#define OMAP3XXX_DMA_SHA1MD5_RX       69
 #define OMAP3XXX_DMA_SPI4_TX0         70
 #define OMAP3XXX_DMA_SPI4_RX0         71
 #define OMAP3XXX_DMA_DSS0             72
@@ -822,6 +830,8 @@ struct omap_dma_lcd_channel_s {
 
 #define OMAP3XXX_DMA_MMC3_TX          77
 #define OMAP3XXX_DMA_MMC3_RX          78
+#define OMAP3XXX_DMA_USIM_TX          79
+#define OMAP3XXX_DMA_USIM_RX          80
 
 
 /* omap[123].c */
@@ -1180,7 +1190,7 @@ struct omap_mpu_state_s {
 
     struct omap_gpif_s *gpif;
 
-    struct omap_mcspi_s *mcspi[2];
+    struct omap_mcspi_s *mcspi[4];
 
     struct omap_dss_s *dss;
 
index 91abefe..bd79236 100644 (file)
@@ -1441,7 +1441,7 @@ static void omap_mcspi_reset(struct omap_mcspi_s *s)
     s->wken = 0;
     s->control = 4;
 
-    for (ch = 0; ch < 4; ch ++) {
+    for (ch = 0; ch < s->chnum; ch ++) {
         s->ch[ch].config = 0x060000;
         s->ch[ch].status = 2;                          /* TXS */
         s->ch[ch].control = 0;
index 6685a9d..ab0cf8e 100644 (file)
@@ -1212,7 +1212,12 @@ typedef enum {
     L4A_TAP,
     L4A_USBHS_OTG,
     L4A_USBHS_HOST,
-    L4A_USBHS_TLL
+    L4A_USBHS_TLL,
+    L4A_MCSPI1,
+    L4A_MCSPI2,
+    L4A_MCSPI3,
+    L4A_MCSPI4,
+    L4A_SDMA
 } omap3_l4_agent_info_id_t;
 
 struct omap3_l4_agent_info_s {
@@ -1237,16 +1242,16 @@ static const struct omap3_l4_agent_info_s omap3_l4_agent_info[] = {
     /* TODO: McBSP5 */
     {L4A_GPTIMER10,  L4ID_GPTIMER10, 2},
     {L4A_GPTIMER11,  L4ID_GPTIMER11, 2},
-    /* TODO: SPI1 */
-    /* TODO: SPI2 */
+    {L4A_MCSPI1,     L4ID_MCSPI1,    2},
+    {L4A_MCSPI2,     L4ID_MCSPI2,    2},
     {L4A_MMC1,       L4ID_MMCSDIO1,  2},
     {L4A_MMC2,       L4ID_MMCSDIO2,  2},
     {L4A_MMC3,       L4ID_MMCSDIO3,  2},
     /* TODO: HDQ/1-Wire */
     /* TODO: Mailbox */
-    /* TODO: SPI3 */
-    /* TODO: SPI4 */
-    /* TODO: SDMA */
+    {L4A_MCSPI3,     L4ID_MCSPI3,    2},
+    {L4A_MCSPI4,     L4ID_MCSPI4,    2},
+    {L4A_SDMA,       L4ID_SDMA,      2},
     {L4A_CM,         L4ID_CM_A,      3},
     {L4A_SCM,        L4ID_SCM,       2},
     {L4A_TAP,        L4ID_TAP,       2},
@@ -4434,7 +4439,7 @@ struct omap_mpu_state_s *omap3530_mpu_init(unsigned long sdram_size,
         qemu_mallocz(sizeof(struct omap_mpu_state_s));
     ram_addr_t sram_base, q2_base, bootrom_base;
     qemu_irq *cpu_irq;
-    qemu_irq dma_irqs[4];
+    qemu_irq drqs[4];
     int i;
 
     s->mpu_model = omap3530;
@@ -4476,14 +4481,11 @@ struct omap_mpu_state_s *omap3530_mpu_init(unsigned long sdram_size,
                                omap_findclk(s, "omap3_mpu_intc_iclk"));
 
     for (i = 0; i < 4; i++)
-        dma_irqs[i] =
-            s->irq[omap3_dma_irq_map[i].ih][omap3_dma_irq_map[i].intr];
-    s->dma = omap_dma4_init(0x48056000, dma_irqs, s, 256, 32,
-                            omap_findclk(s, "omap3_sdma_fclk"),
-                            omap_findclk(s, "omap3_sdma_iclk"));
+        drqs[i] = s->irq[omap3_dma_irq_map[i].ih][omap3_dma_irq_map[i].intr];
+    s->dma = omap3_dma4_init(omap3_l4ta_init(s->l4, L4A_SDMA), s, drqs, 32,
+                             omap_findclk(s, "omap3_sdma_fclk"),
+                             omap_findclk(s, "omap3_sdma_iclk"));
     s->port->addr_valid = omap3_validate_addr;
-
-    /* Register SDRAM and SRAM ports for fast DMA transfers.  */
     soc_dma_port_add_mem_ram(s->dma, q2_base, OMAP2_Q2_BASE, s->sdram_size);
     soc_dma_port_add_mem_ram(s->dma, sram_base, OMAP2_SRAM_BASE, s->sram_size);
 
@@ -4659,5 +4661,31 @@ struct omap_mpu_state_s *omap3530_mpu_init(unsigned long sdram_size,
                                     s->irq[0][OMAP_INT_3XXX_OHCI_IRQ],
                                     s->irq[0][OMAP_INT_3XXX_EHCI_IRQ],
                                     s->irq[0][OMAP_INT_3XXX_TLL_IRQ]);
+
+    s->mcspi[0] = omap_mcspi_init(omap3_l4ta_init(s->l4, L4A_MCSPI1), 4,
+                                  s->irq[0][OMAP_INT_3XXX_MCSPI1_IRQ],
+                                  &s->drq[OMAP3XXX_DMA_SPI1_TX0],
+                                  omap_findclk(s, "omap3_spi1_fclk"),
+                                  omap_findclk(s, "omap3_spi1_iclk"));
+    s->mcspi[1] = omap_mcspi_init(omap3_l4ta_init(s->l4, L4A_MCSPI2), 2,
+                                  s->irq[0][OMAP_INT_3XXX_MCSPI2_IRQ],
+                                  &s->drq[OMAP3XXX_DMA_SPI2_TX0],
+                                  omap_findclk(s, "omap3_spi2_fclk"),
+                                  omap_findclk(s, "omap3_spi2_iclk"));
+    drqs[0] = s->drq[OMAP3XXX_DMA_SPI3_TX0];
+    drqs[1] = s->drq[OMAP3XXX_DMA_SPI3_RX0];
+    drqs[2] = s->drq[OMAP3XXX_DMA_SPI3_TX1];
+    drqs[3] = s->drq[OMAP3XXX_DMA_SPI3_RX1];
+    s->mcspi[2] = omap_mcspi_init(omap3_l4ta_init(s->l4, L4A_MCSPI3), 2,
+                                  s->irq[0][OMAP_INT_3XXX_MCSPI3_IRQ],
+                                  drqs,
+                                  omap_findclk(s, "omap3_spi3_fclk"),
+                                  omap_findclk(s, "omap3_spi3_iclk"));
+    s->mcspi[3] = omap_mcspi_init(omap3_l4ta_init(s->l4, L4A_MCSPI4), 1,
+                                  s->irq[0][OMAP_INT_3XXX_MCSPI4_IRQ],
+                                  &s->drq[OMAP3XXX_DMA_SPI4_TX0],
+                                  omap_findclk(s, "omap3_spi4_fclk"),
+                                  omap_findclk(s, "omap3_spi4_iclk"));
+    
     return s;
 }
index d99f5ed..f4d20bc 100644 (file)
@@ -1481,7 +1481,56 @@ static struct clk omap3_i2c3_fclk = {
 static struct clk omap3_i2c3_iclk = {
     .name      = "omap3_i2c3_iclk",
     .flags     = CLOCK_IN_OMAP3XXX ,
-    .parent    = &omap3_core_l4_iclk,       
+    .parent    = &omap3_core_l4_iclk,
+};
+
+/* SPI clocks */
+static struct clk omap3_spi1_fclk = {
+    .name   = "omap3_spi1_fclk",
+    .flags  = CLOCK_IN_OMAP3XXX,
+    .parent = &omap3_core_48m_fclk,
+};
+
+static struct clk omap3_spi1_iclk = {
+    .name   = "omap3_spi1_iclk",
+    .flags  = CLOCK_IN_OMAP3XXX,
+    .parent = &omap3_core_l4_iclk,
+};
+
+static struct clk omap3_spi2_fclk = {
+    .name   = "omap3_spi2_fclk",
+    .flags  = CLOCK_IN_OMAP3XXX,
+    .parent = &omap3_core_48m_fclk,
+};
+
+static struct clk omap3_spi2_iclk = {
+    .name   = "omap3_spi2_iclk",
+    .flags  = CLOCK_IN_OMAP3XXX,
+    .parent = &omap3_core_l4_iclk,
+};
+
+static struct clk omap3_spi3_fclk = {
+    .name   = "omap3_spi3_fclk",
+    .flags  = CLOCK_IN_OMAP3XXX,
+    .parent = &omap3_core_48m_fclk,
+};
+
+static struct clk omap3_spi3_iclk = {
+    .name   = "omap3_spi3_iclk",
+    .flags  = CLOCK_IN_OMAP3XXX,
+    .parent = &omap3_core_l4_iclk,
+};
+
+static struct clk omap3_spi4_fclk = {
+    .name   = "omap3_spi4_fclk",
+    .flags  = CLOCK_IN_OMAP3XXX,
+    .parent = &omap3_core_48m_fclk,
+};
+
+static struct clk omap3_spi4_iclk = {
+    .name   = "omap3_spi4_iclk",
+    .flags  = CLOCK_IN_OMAP3XXX,
+    .parent = &omap3_core_l4_iclk,
 };
 
 
@@ -1706,6 +1755,14 @@ static struct clk *onchip_clks[] = {
     &omap3_i2c2_iclk,
     &omap3_i2c3_fclk,
     &omap3_i2c3_iclk,
+    &omap3_spi1_fclk,
+    &omap3_spi1_iclk,
+    &omap3_spi2_fclk,
+    &omap3_spi2_iclk,
+    &omap3_spi3_fclk,
+    &omap3_spi3_iclk,
+    &omap3_spi4_fclk,
+    &omap3_spi4_iclk,
 
     0
 };
index fea0e91..0497988 100644 (file)
@@ -257,7 +257,7 @@ static void omap_dma_deactivate_channel(struct omap_dma_s *s,
 
     /* Don't deactive the channel if it is synchronized and the DMA request is
        active */
-    if (ch->sync && ch->enable && (s->dma->drqbmp & (1 << ch->sync)))
+    if (ch->sync && ch->enable && s->dma->drqst[ch->sync])
         return;
 
     if (ch->active) {
@@ -275,9 +275,9 @@ static void omap_dma_enable_channel(struct omap_dma_s *s,
         ch->waiting_end_prog = 0;
         omap_dma_channel_load(ch);
         /* TODO: theoretically if ch->sync && ch->prefetch &&
-         * !s->dma->drqbmp[ch->sync], we should also activate and fetch
+         * !s->dma->drqst[ch->sync], we should also activate and fetch
          * from source and then stall until signalled.  */
-        if ((!ch->sync) || (s->dma->drqbmp & (1 << ch->sync)))
+        if ((!ch->sync) || s->dma->drqst[ch->sync])
             omap_dma_activate_channel(s, ch);
     }
 }
@@ -1554,12 +1554,12 @@ static void omap_dma_request(void *opaque, int drq, int req)
     struct omap_dma_s *s = (struct omap_dma_s *) opaque;
     /* The request pins are level triggered in QEMU.  */
     if (req) {
-        if (~s->dma->drqbmp & (1 << drq)) {
-            s->dma->drqbmp |= 1 << drq;
+        if (!s->dma->drqst[drq]) {
+            s->dma->drqst[drq] = 1;
             omap_dma_process_request(s, drq);
         }
     } else
-        s->dma->drqbmp &= ~(1 << drq);
+        s->dma->drqst[drq] = 0;
 }
 
 /* XXX: this won't be needed once soc_dma knows about clocks.  */
@@ -2231,48 +2231,71 @@ static int omap_dma4_load_state(QEMUFile *f, void *opaque, int version_id)
     
     return 0;
 }
-    
-struct soc_dma_s *omap_dma4_init(target_phys_addr_t base, qemu_irq *irqs,
-                struct omap_mpu_state_s *mpu, int fifo,
-                int chans, omap_clk iclk, omap_clk fclk)
+
+static struct omap_dma_s *omap_dma4_init_internal(struct omap_mpu_state_s *mpu,
+                                                  qemu_irq *irqs,
+                                                  int chans, int drq_count,
+                                                  omap_clk iclk, omap_clk fclk)
 {
-    int iomemtype, i;
+    int i;
     struct omap_dma_s *s = (struct omap_dma_s *)
-            qemu_mallocz(sizeof(struct omap_dma_s));
-
+        qemu_mallocz(sizeof(struct omap_dma_s));
+    
     s->model = omap_dma_4;
     s->chans = chans;
     s->mpu = mpu;
     s->clk = fclk;
-
+    
     s->dma = soc_dma_init(s->chans);
     s->dma->freq = omap_clk_getrate(fclk);
     s->dma->transfer_fn = omap_dma_transfer_generic;
     s->dma->setup_fn = omap_dma_transfer_setup;
-    s->dma->drq = qemu_allocate_irqs(omap_dma_request, s, 64);
+    s->dma->drq = qemu_allocate_irqs(omap_dma_request, s, drq_count);
     s->dma->opaque = s;
     for (i = 0; i < s->chans; i ++) {
         s->ch[i].dma = &s->dma->ch[i];
         s->dma->ch[i].opaque = &s->ch[i];
     }
-
+    
     memcpy(&s->irq, irqs, sizeof(s->irq));
     s->intr_update = omap_dma_interrupts_4_update;
-
+    
     omap_dma_setcaps(s);
     omap_clk_adduser(s->clk, qemu_allocate_irqs(omap_dma_clk_update, s, 1)[0]);
     omap_dma_reset(s->dma);
     omap_dma_clk_update(s, 0, !!s->dma->freq);
 
-    iomemtype = cpu_register_io_memory(0, omap_dma4_readfn,
-                    omap_dma4_writefn, s);
-    cpu_register_physical_memory(base, 0x1000, iomemtype);
-
     mpu->drq = s->dma->drq;
-
+    
     register_savevm("omap_dma4", -1, 0,
                     omap_dma4_save_state, omap_dma4_load_state, s);
+    return s;
+}
     
+struct soc_dma_s *omap_dma4_init(target_phys_addr_t base, qemu_irq *irqs,
+                struct omap_mpu_state_s *mpu, int fifo,
+                int chans, omap_clk iclk, omap_clk fclk)
+{
+    int iomemtype;
+    struct omap_dma_s *s = omap_dma4_init_internal(mpu, irqs, chans, 64,
+                                                   iclk, fclk);
+
+    iomemtype = cpu_register_io_memory(0, omap_dma4_readfn,
+                    omap_dma4_writefn, s);
+    cpu_register_physical_memory(base, 0x1000, iomemtype);
+    
+    return s->dma;
+}
+
+struct soc_dma_s *omap3_dma4_init(struct omap_target_agent_s *ta,
+                                  struct omap_mpu_state_s *mpu,
+                                  qemu_irq *irqs, int chans,
+                                  omap_clk iclk, omap_clk fclk)
+{
+    struct omap_dma_s *s = omap_dma4_init_internal(mpu, irqs, chans, 96,
+                                                   iclk, fclk);
+    omap_l4_attach(ta, 0, cpu_register_io_memory(0, omap_dma4_readfn,
+                                                 omap_dma4_writefn, s));
     return s->dma;
 }
 
index 0fef249..c66cf7b 100644 (file)
@@ -230,7 +230,7 @@ void soc_dma_reset(struct soc_dma_s *soc)
 {
     struct dma_s *s = (struct dma_s *) soc;
 
-    s->soc.drqbmp = 0;
+    memset(s->soc.drqst, 0, sizeof(s->soc.drqst));
     s->ch_enable_mask = 0;
     s->enabled_count = 0;
     soc_dma_ch_freq_update(s);
@@ -241,7 +241,7 @@ static void soc_dma_save_state(QEMUFile *f, void *opaque)
     struct dma_s *s = (struct dma_s *)opaque;
     int i;
     
-    qemu_put_be64(f, s->soc.drqbmp);
+    qemu_put_buffer(f, s->soc.drqst, sizeof(s->soc.drqst));
     qemu_put_sbe64(f, s->soc.freq);
     qemu_put_be64(f, s->ch_enable_mask);
     qemu_put_sbe64(f, s->channel_freq);
@@ -274,7 +274,7 @@ static int soc_dma_load_state(QEMUFile *f, void *opaque, int version_id)
     if (version_id)
         return -EINVAL;
     
-    s->soc.drqbmp = qemu_get_be64(f);
+    qemu_get_buffer(f, s->soc.drqst, sizeof(s->soc.drqst));
     s->soc.freq = qemu_get_sbe64(f);
     s->ch_enable_mask = qemu_get_be64(f);
     s->channel_freq = qemu_get_sbe64(f);
index 47bc4ea..1977773 100644 (file)
@@ -19,6 +19,8 @@
  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  */
 
+#define DMA_MAX_DRQ 96
+
 struct soc_dma_s;
 struct soc_dma_ch_s;
 typedef void (*soc_dma_io_t)(void *opaque, uint8_t *buf, int len);
@@ -66,7 +68,7 @@ struct soc_dma_ch_s {
 struct soc_dma_s {
     /* Following fields are set by the SoC DMA module and can be used
      * by anybody.  */
-    uint64_t drqbmp;   /* Is zeroed by soc_dma_reset() */
+    uint8_t drqst[DMA_MAX_DRQ]; /* Is zeroed by soc_dma_reset() */
     qemu_irq *drq;
     void *opaque;
     int64_t freq;