Merge commit 'upstream/master'
authorHaavard Skinnemoen <haavard.skinnemoen@atmel.com>
Sun, 27 Jul 2008 11:54:08 +0000 (13:54 +0200)
committerHaavard Skinnemoen <haavard.skinnemoen@atmel.com>
Sun, 27 Jul 2008 11:54:08 +0000 (13:54 +0200)
1  2 
arch/avr32/mach-at32ap/at32ap700x.c
drivers/mmc/host/atmel-mci.c
include/asm-avr32/arch-at32ap/board.h

@@@ -7,6 -7,7 +7,7 @@@
   */
  #include <linux/clk.h>
  #include <linux/delay.h>
+ #include <linux/dw_dmac.h>
  #include <linux/fb.h>
  #include <linux/init.h>
  #include <linux/platform_device.h>
@@@ -594,6 -595,17 +595,17 @@@ static void __init genclk_init_parent(s
        clk->parent = parent;
  }
  
+ static struct dw_dma_platform_data dw_dmac0_data = {
+       .nr_channels    = 3,
+ };
+ static struct resource dw_dmac0_resource[] = {
+       PBMEM(0xff200000),
+       IRQ(2),
+ };
+ DEFINE_DEV_DATA(dw_dmac, 0);
+ DEV_CLK(hclk, dw_dmac0, hsb, 10);
  /* --------------------------------------------------------------------
   *  System peripherals
   * -------------------------------------------------------------------- */
@@@ -708,17 -720,6 +720,6 @@@ static struct clk pico_clk = 
        .users          = 1,
  };
  
- static struct resource dmaca0_resource[] = {
-       {
-               .start  = 0xff200000,
-               .end    = 0xff20ffff,
-               .flags  = IORESOURCE_MEM,
-       },
-       IRQ(2),
- };
- DEFINE_DEV(dmaca, 0);
- DEV_CLK(hclk, dmaca0, hsb, 10);
  /* --------------------------------------------------------------------
   * HMATRIX
   * -------------------------------------------------------------------- */
@@@ -831,7 -832,7 +832,7 @@@ void __init at32_add_system_devices(voi
        platform_device_register(&at32_eic0_device);
        platform_device_register(&smc0_device);
        platform_device_register(&pdc_device);
-       platform_device_register(&dmaca0_device);
+       platform_device_register(&dw_dmac0_device);
  
        platform_device_register(&at32_tcb0_device);
        platform_device_register(&at32_tcb1_device);
@@@ -1284,6 -1285,7 +1285,6 @@@ at32_add_device_mci(unsigned int id, st
  {
        struct mci_platform_data        _data;
        struct platform_device          *pdev;
 -      struct dw_dma_slave             *dws;
  
        if (id != 0)
                return NULL;
        if (!data) {
                data = &_data;
                memset(data, 0, sizeof(struct mci_platform_data));
 +              data->detect_pin = GPIO_PIN_NONE;
 +              data->wp_pin = GPIO_PIN_NONE;
        }
  
        if (platform_device_add_data(pdev, data,
        select_peripheral(PA(14), PERIPH_A, 0); /* DATA2 */
        select_peripheral(PA(15), PERIPH_A, 0); /* DATA3 */
  
 -      if (data) {
 -              if (data->detect_pin != GPIO_PIN_NONE)
 -                      at32_select_gpio(data->detect_pin, 0);
 -              if (data->wp_pin != GPIO_PIN_NONE)
 -                      at32_select_gpio(data->wp_pin, 0);
 -      }
 +      if (data->detect_pin != GPIO_PIN_NONE)
 +              at32_select_gpio(data->detect_pin, 0);
 +      if (data->wp_pin != GPIO_PIN_NONE)
 +              at32_select_gpio(data->wp_pin, 0);
  
        atmel_mci0_pclk.dev = &pdev->dev;
  
@@@ -1868,6 -1870,58 +1869,58 @@@ fail
  }
  #endif
  
+ /* --------------------------------------------------------------------
+  * NAND Flash / SmartMedia
+  * -------------------------------------------------------------------- */
+ static struct resource smc_cs3_resource[] __initdata = {
+       {
+               .start  = 0x0c000000,
+               .end    = 0x0fffffff,
+               .flags  = IORESOURCE_MEM,
+       }, {
+               .start  = 0xfff03c00,
+               .end    = 0xfff03fff,
+               .flags  = IORESOURCE_MEM,
+       },
+ };
+ struct platform_device *__init
+ at32_add_device_nand(unsigned int id, struct atmel_nand_data *data)
+ {
+       struct platform_device *pdev;
+       if (id != 0 || !data)
+               return NULL;
+       pdev = platform_device_alloc("atmel_nand", id);
+       if (!pdev)
+               goto fail;
+       if (platform_device_add_resources(pdev, smc_cs3_resource,
+                               ARRAY_SIZE(smc_cs3_resource)))
+               goto fail;
+       if (platform_device_add_data(pdev, data,
+                               sizeof(struct atmel_nand_data)))
+               goto fail;
+       set_ebi_sfr_bits(HMATRIX_BIT(CS3A));
+       if (data->enable_pin)
+               at32_select_gpio(data->enable_pin,
+                               AT32_GPIOF_OUTPUT | AT32_GPIOF_HIGH);
+       if (data->rdy_pin)
+               at32_select_gpio(data->rdy_pin, 0);
+       if (data->det_pin)
+               at32_select_gpio(data->det_pin, 0);
+       platform_device_add(pdev);
+       return pdev;
+ fail:
+       platform_device_put(pdev);
+       return NULL;
+ }
  /* --------------------------------------------------------------------
   * AC97C
   * -------------------------------------------------------------------- */
@@@ -1883,11 -1937,9 +1936,11 @@@ static struct clk atmel_ac97c0_pclk = 
        .index          = 10,
  };
  
 -struct platform_device *__init at32_add_device_ac97c(unsigned int id)
 +struct platform_device *__init
 +at32_add_device_ac97c(unsigned int id, struct ac97c_platform_data *data)
  {
        struct platform_device *pdev;
 +      struct ac97c_platform_data _data;
  
        if (id != 0)
                return NULL;
  
        if (platform_device_add_resources(pdev, atmel_ac97c0_resource,
                                ARRAY_SIZE(atmel_ac97c0_resource)))
 -              goto err_add_resources;
 +              goto fail;
 +
 +      if (!data) {
 +              data = &_data;
 +              memset(data, 0, sizeof(struct ac97c_platform_data));
 +              data->reset_pin = GPIO_PIN_NONE;
 +      }
  
 -      select_peripheral(PB(20), PERIPH_B, 0); /* SYNC */
 -      select_peripheral(PB(21), PERIPH_B, 0); /* SDO  */
 -      select_peripheral(PB(22), PERIPH_B, 0); /* SDI  */
 -      select_peripheral(PB(23), PERIPH_B, 0); /* SCLK */
 +      data->dma_rx_periph_id = 3;
 +      data->dma_tx_periph_id = 4;
 +      data->dma_controller_id = 0;
 +
 +      if (platform_device_add_data(pdev, data,
 +                              sizeof(struct ac97c_platform_data)))
 +              goto fail;
 +
 +      select_peripheral(PB(20), PERIPH_B, 0); /* SDO  */
 +      select_peripheral(PB(21), PERIPH_B, 0); /* SYNC */
 +      select_peripheral(PB(22), PERIPH_B, 0); /* SCLK */
 +      select_peripheral(PB(23), PERIPH_B, 0); /* SDI  */
 +
 +      /* TODO: gpio_is_valid(data->reset_pin) with kernel 2.6.26. */
 +      if (data->reset_pin != GPIO_PIN_NONE)
 +              at32_select_gpio(data->reset_pin, 0);
  
        atmel_ac97c0_pclk.dev = &pdev->dev;
  
        platform_device_add(pdev);
        return pdev;
  
 -err_add_resources:
 +fail:
        platform_device_put(pdev);
        return NULL;
  }
@@@ -2051,7 -2085,7 +2104,7 @@@ struct clk *at32_clock_list[] = 
        &smc0_mck,
        &pdc_hclk,
        &pdc_pclk,
-       &dmaca0_hclk,
+       &dw_dmac0_hclk,
        &pico_clk,
        &pio0_mck,
        &pio1_mck,
@@@ -9,14 -9,16 +9,17 @@@
   */
  #include <linux/blkdev.h>
  #include <linux/clk.h>
+ #include <linux/debugfs.h>
  #include <linux/device.h>
 +#include <linux/err.h>
  #include <linux/init.h>
  #include <linux/interrupt.h>
  #include <linux/ioport.h>
  #include <linux/module.h>
  #include <linux/platform_device.h>
  #include <linux/scatterlist.h>
+ #include <linux/seq_file.h>
+ #include <linux/stat.h>
  
  #include <linux/mmc/host.h>
  
@@@ -89,6 -91,188 +92,188 @@@ struct atmel_mci 
  #define atmci_clear_pending(host, event)                      \
        clear_bit(event, &host->pending_events)
  
+ /*
+  * The debugfs stuff below is mostly optimized away when
+  * CONFIG_DEBUG_FS is not set.
+  */
+ static int atmci_req_show(struct seq_file *s, void *v)
+ {
+       struct atmel_mci        *host = s->private;
+       struct mmc_request      *mrq = host->mrq;
+       struct mmc_command      *cmd;
+       struct mmc_command      *stop;
+       struct mmc_data         *data;
+       /* Make sure we get a consistent snapshot */
+       spin_lock_irq(&host->mmc->lock);
+       if (mrq) {
+               cmd = mrq->cmd;
+               data = mrq->data;
+               stop = mrq->stop;
+               if (cmd)
+                       seq_printf(s,
+                               "CMD%u(0x%x) flg %x rsp %x %x %x %x err %d\n",
+                               cmd->opcode, cmd->arg, cmd->flags,
+                               cmd->resp[0], cmd->resp[1], cmd->resp[2],
+                               cmd->resp[2], cmd->error);
+               if (data)
+                       seq_printf(s, "DATA %u / %u * %u flg %x err %d\n",
+                               data->bytes_xfered, data->blocks,
+                               data->blksz, data->flags, data->error);
+               if (stop)
+                       seq_printf(s,
+                               "CMD%u(0x%x) flg %x rsp %x %x %x %x err %d\n",
+                               stop->opcode, stop->arg, stop->flags,
+                               stop->resp[0], stop->resp[1], stop->resp[2],
+                               stop->resp[2], stop->error);
+       }
+       spin_unlock_irq(&host->mmc->lock);
+       return 0;
+ }
+ static int atmci_req_open(struct inode *inode, struct file *file)
+ {
+       return single_open(file, atmci_req_show, inode->i_private);
+ }
+ static const struct file_operations atmci_req_fops = {
+       .owner          = THIS_MODULE,
+       .open           = atmci_req_open,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+       .release        = single_release,
+ };
+ static void atmci_show_status_reg(struct seq_file *s,
+               const char *regname, u32 value)
+ {
+       static const char       *sr_bit[] = {
+               [0]     = "CMDRDY",
+               [1]     = "RXRDY",
+               [2]     = "TXRDY",
+               [3]     = "BLKE",
+               [4]     = "DTIP",
+               [5]     = "NOTBUSY",
+               [8]     = "SDIOIRQA",
+               [9]     = "SDIOIRQB",
+               [16]    = "RINDE",
+               [17]    = "RDIRE",
+               [18]    = "RCRCE",
+               [19]    = "RENDE",
+               [20]    = "RTOE",
+               [21]    = "DCRCE",
+               [22]    = "DTOE",
+               [30]    = "OVRE",
+               [31]    = "UNRE",
+       };
+       unsigned int            i;
+       seq_printf(s, "%s:\t0x%08x", regname, value);
+       for (i = 0; i < ARRAY_SIZE(sr_bit); i++) {
+               if (value & (1 << i)) {
+                       if (sr_bit[i])
+                               seq_printf(s, " %s", sr_bit[i]);
+                       else
+                               seq_puts(s, " UNKNOWN");
+               }
+       }
+       seq_putc(s, '\n');
+ }
+ static int atmci_regs_show(struct seq_file *s, void *v)
+ {
+       struct atmel_mci        *host = s->private;
+       u32                     *buf;
+       buf = kmalloc(MCI_REGS_SIZE, GFP_KERNEL);
+       if (!buf)
+               return -ENOMEM;
+       /* Grab a more or less consistent snapshot */
+       spin_lock_irq(&host->mmc->lock);
+       memcpy_fromio(buf, host->regs, MCI_REGS_SIZE);
+       spin_unlock_irq(&host->mmc->lock);
+       seq_printf(s, "MR:\t0x%08x%s%s CLKDIV=%u\n",
+                       buf[MCI_MR / 4],
+                       buf[MCI_MR / 4] & MCI_MR_RDPROOF ? " RDPROOF" : "",
+                       buf[MCI_MR / 4] & MCI_MR_WRPROOF ? " WRPROOF" : "",
+                       buf[MCI_MR / 4] & 0xff);
+       seq_printf(s, "DTOR:\t0x%08x\n", buf[MCI_DTOR / 4]);
+       seq_printf(s, "SDCR:\t0x%08x\n", buf[MCI_SDCR / 4]);
+       seq_printf(s, "ARGR:\t0x%08x\n", buf[MCI_ARGR / 4]);
+       seq_printf(s, "BLKR:\t0x%08x BCNT=%u BLKLEN=%u\n",
+                       buf[MCI_BLKR / 4],
+                       buf[MCI_BLKR / 4] & 0xffff,
+                       (buf[MCI_BLKR / 4] >> 16) & 0xffff);
+       /* Don't read RSPR and RDR; it will consume the data there */
+       atmci_show_status_reg(s, "SR", buf[MCI_SR / 4]);
+       atmci_show_status_reg(s, "IMR", buf[MCI_IMR / 4]);
+       return 0;
+ }
+ static int atmci_regs_open(struct inode *inode, struct file *file)
+ {
+       return single_open(file, atmci_regs_show, inode->i_private);
+ }
+ static const struct file_operations atmci_regs_fops = {
+       .owner          = THIS_MODULE,
+       .open           = atmci_regs_open,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+       .release        = single_release,
+ };
+ static void atmci_init_debugfs(struct atmel_mci *host)
+ {
+       struct mmc_host *mmc;
+       struct dentry   *root;
+       struct dentry   *node;
+       struct resource *res;
+       mmc = host->mmc;
+       root = mmc->debugfs_root;
+       if (!root)
+               return;
+       node = debugfs_create_file("regs", S_IRUSR, root, host,
+                       &atmci_regs_fops);
+       if (IS_ERR(node))
+               return;
+       if (!node)
+               goto err;
+       res = platform_get_resource(host->pdev, IORESOURCE_MEM, 0);
+       node->d_inode->i_size = res->end - res->start + 1;
+       node = debugfs_create_file("req", S_IRUSR, root, host, &atmci_req_fops);
+       if (!node)
+               goto err;
+       node = debugfs_create_x32("pending_events", S_IRUSR, root,
+                                    (u32 *)&host->pending_events);
+       if (!node)
+               goto err;
+       node = debugfs_create_x32("completed_events", S_IRUSR, root,
+                                    (u32 *)&host->completed_events);
+       if (!node)
+               goto err;
+       return;
+ err:
+       dev_err(&host->pdev->dev,
+               "failed to initialize debugfs for controller\n");
+ }
  
  static void atmci_enable(struct atmel_mci *host)
  {
@@@ -906,6 -1090,8 +1091,8 @@@ static int __init atmci_probe(struct pl
                        "Atmel MCI controller at 0x%08lx irq %d\n",
                        host->mapbase, irq);
  
+       atmci_init_debugfs(host);
        return 0;
  
  err_request_irq:
@@@ -924,6 -1110,8 +1111,8 @@@ static int __exit atmci_remove(struct p
        platform_set_drvdata(pdev, NULL);
  
        if (host) {
+               /* Debugfs stuff is cleaned up by mmc core */
                if (host->detect_pin >= 0) {
                        int pin = host->detect_pin;
  
@@@ -82,15 -82,7 +82,15 @@@ struct mci_platform_data
  struct platform_device *
  at32_add_device_mci(unsigned int id, struct mci_platform_data *data);
  
 -struct platform_device *at32_add_device_ac97c(unsigned int id);
 +struct ac97c_platform_data {
 +      unsigned short dma_rx_periph_id;
 +      unsigned short dma_tx_periph_id;
 +      unsigned short dma_controller_id;
 +      int reset_pin;
 +};
 +struct platform_device *
 +at32_add_device_ac97c(unsigned int id, struct ac97c_platform_data *data);
 +
  struct platform_device *at32_add_device_abdac(unsigned int id);
  struct platform_device *at32_add_device_psif(unsigned int id);
  
@@@ -105,4 -97,17 +105,17 @@@ struct platform_device 
  at32_add_device_cf(unsigned int id, unsigned int extint,
                struct cf_platform_data *data);
  
+ /* NAND / SmartMedia */
+ struct atmel_nand_data {
+       int     enable_pin;     /* chip enable */
+       int     det_pin;        /* card detect */
+       int     rdy_pin;        /* ready/busy */
+       u8      ale;            /* address line number connected to ALE */
+       u8      cle;            /* address line number connected to CLE */
+       u8      bus_width_16;   /* buswidth is 16 bit */
+       struct mtd_partition *(*partition_info)(int size, int *num_partitions);
+ };
+ struct platform_device *
+ at32_add_device_nand(unsigned int id, struct atmel_nand_data *data);
  #endif /* __ASM_ARCH_BOARD_H */