[adm5120] new experimental driver for the CF slot on the RouterBOARD 153
authorGabor Juhos <juhosg@openwrt.org>
Tue, 11 Dec 2007 09:00:06 +0000 (09:00 +0000)
committerGabor Juhos <juhosg@openwrt.org>
Tue, 11 Dec 2007 09:00:06 +0000 (09:00 +0000)
SVN-Revision: 9707

package/kernel/modules/block.mk
target/linux/adm5120/files/arch/mips/adm5120/boards/mikrotik.c
target/linux/adm5120/files/drivers/ata/pata_rb153_cf.c [new file with mode: 0644]
target/linux/adm5120/files/include/asm-mips/mach-adm5120/adm5120_defs.h
target/linux/adm5120/patches-2.6.23/120-rb153_cf_driver.patch [new file with mode: 0644]
target/linux/adm5120/router_le/profiles/RB1xx.mk

index 29bc799082939b58534d3355bf4e550b0f982eee..cace16a94036cc5b3f02c8486dce9844a32405d3 100644 (file)
@@ -46,7 +46,7 @@ define KernelPackage/ata-piix
 endef
 
 define KernelPackage/ata-piix/description
- SATA support for Intel ICH5/6/7/8 series host controllers and 
+ SATA support for Intel ICH5/6/7/8 series host controllers and
  PATA support for Intel ESB/ICH/PIIX3/PIIX4 series host controllers.
 endef
 
@@ -95,7 +95,7 @@ define KernelPackage/ide-aec62xx
   SUBMENU:=$(BLOCK_MENU)
   TITLE:=Acard AEC62xx IDE driver
   DEPENDS:=@PCI_SUPPORT +kmod-ide-core
-  KCONFIG:=CONFIG_BLK_DEV_AEC62XX 
+  KCONFIG:=CONFIG_BLK_DEV_AEC62XX
   FILES:=$(LINUX_DIR)/drivers/ide/pci/aec62xx.$(LINUX_KMOD_SUFFIX)
   AUTOLOAD:=$(call AutoLoad,30,aec62xx)
 endef
@@ -117,7 +117,7 @@ define KernelPackage/ide-pdc202xx
 endef
 
 define KernelPackage/ide-pdc202xx/description
- Support for the Promise Ultra 33/66/100 (PDC202{46|62|65|67|68}) IDE 
+ Support for the Promise Ultra 33/66/100 (PDC202{46|62|65|67|68}) IDE
  controllers.
 endef
 
@@ -184,16 +184,17 @@ endef
 $(eval $(call KernelPackage,nbd))
 
 
-define KernelPackage/rb153-cf
+define KernelPackage/pata-rb153-cf
   SUBMENU:=$(BLOCK_MENU)
-  TITLE:=RouterBoard 153 CF Slot
-  KCONFIG:=CONFIG_BLK_DEV_CF_MIPS
-  FILES:=$(LINUX_DIR)/drivers/block/rb1xx/rb153-cf.$(LINUX_KMOD_SUFFIX)
-  AUTOLOAD:=$(call AutoLoad,30,rb153-cf)
+  DEPENDS:=kmod-ata-core @TARGET_adm5120_router_le
+  TITLE:=RouterBOARD 153 CF Slot support
+  KCONFIG:=CONFIG_PATA_RB153_CF
+  FILES:=$(LINUX_DIR)/drivers/ata/pata_rb153_cf.$(LINUX_KMOD_SUFFIX)
+  AUTOLOAD:=$(call AutoLoad,30,pata_rb153_cf)
 endef
 
-define KernelPackage/rb153-cf/description
-  Kernel module for the RouterBoard 153 CF slot
+define KernelPackage/pata-rb153-cf/description
+  Kernel support for the RouterBoard 153 CF slot.
 endef
 
-$(eval $(call KernelPackage,rb153-cf))
+$(eval $(call KernelPackage,pata-rb153-cf))
index 1ca151412b7677ddef96eb70a0e12690661bc63d..102fa5615779cfadbedd48dc6e7eab26c9b7a1ac 100644 (file)
@@ -42,8 +42,8 @@
 #include <adm5120_nand.h>
 #include <adm5120_board.h>
 #include <adm5120_platform.h>
-#include <adm5120_cf.h>
 #include <adm5120_info.h>
+
 #include <prom/routerboot.h>
 
 #define RB1XX_NAND_CHIP_DELAY  25
@@ -127,8 +127,8 @@ static struct resource rb150_nand_resource[] = {
 static struct resource rb153_cf_resources[] = {
        {
                .name   = "cf_membase",
-               .start  = ADM5120_EXTIO0_BASE,
-               .end    = ADM5120_EXTIO0_BASE + ADM5120_MPMC_SIZE-1 ,
+               .start  = ADM5120_EXTIO1_BASE,
+               .end    = ADM5120_EXTIO1_BASE + ADM5120_EXTIO1_SIZE-1 ,
                .flags  = IORESOURCE_MEM
        }, {
                .name   = "cf_irq",
@@ -138,16 +138,11 @@ static struct resource rb153_cf_resources[] = {
        }
 };
 
-static struct cf_device rb153_cf_data = {
-       .gpio_pin = ADM5120_GPIO_PIN4
-};
-
 static struct platform_device rb153_cf_device = {
-       .name           = "rb153-cf",
+       .name           = "pata-rb153-cf",
        .id             = -1,
        .resource       = rb153_cf_resources,
        .num_resources  = ARRAY_SIZE(rb153_cf_resources),
-       .dev.platform_data = &rb153_cf_data,
 };
 
 static struct platform_device *rb153_devices[] __initdata = {
@@ -223,7 +218,7 @@ static void rb150_nand_cmd_ctrl(struct mtd_info *mtd, int cmd,
 static void __init rb1xx_mac_setup(void)
 {
        int i, j;
-       
+
        for (i = 0; i < rb_hs.mac_count; i++) {
                for (j = 0; j < RB_MAC_SIZE; j++)
                        adm5120_eth_macs[i][j] = rb_hs.macs[i][j];
@@ -247,6 +242,9 @@ static void __init rb1xx_flash_setup(void)
 
 static void __init rb153_cf_setup(void)
 {
+       /* enable CSX1:INTX1 on GPIO 3:4 for the CF slot */
+       adm5120_gpio_csx1_enable();
+
        gpio_request(RB153_GPIO_CF_RDY, "cf-ready");
        gpio_direction_input(RB153_GPIO_CF_RDY);
        gpio_request(RB153_GPIO_CF_WT, "cf-wait");
diff --git a/target/linux/adm5120/files/drivers/ata/pata_rb153_cf.c b/target/linux/adm5120/files/drivers/ata/pata_rb153_cf.c
new file mode 100644 (file)
index 0000000..16ec676
--- /dev/null
@@ -0,0 +1,303 @@
+/*
+ *  A low-level PATA driver to handle a Compact Flash connected on the
+ *  Mikrotik's RouterBoard 153 board.
+ *
+ *  Copyright (C) 2007 Gabor Juhos <juhosg at openwrt.org>
+ *
+ *  This file was based on: drivers/ata/pata_ixp4xx_cf.c
+ *     Copyright (C) 2006-07 Tower Technologies
+ *     Author: Alessandro Zummo <a.zummo@towertech.it>
+ *
+ *  Also was based on the driver for Linux 2.4.xx published by Mikrotik for
+ *  their RouterBoard 1xx and 5xx series devices. The original Mikrotik code
+ *  seems not to have a license.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+
+#include <linux/io.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+
+#include <linux/libata.h>
+#include <scsi/scsi_host.h>
+
+#include <asm/gpio.h>
+
+#define DRV_NAME       "pata-rb153-cf"
+#define DRV_VERSION    "0.1"
+#define DRV_DESC       "PATA driver for RouterBOARD 153 Compact Flash"
+
+#define RB153_CF_MAXPORTS      1
+#define RB153_CF_IO_DELAY      100
+
+#define RB153_CF_REG_CMD       0x0800
+#define RB153_CF_REG_CTRL      0x080E
+#define RB153_CF_REG_DATA      0x0C00
+
+struct rb153_cf_info {
+       void __iomem    *iobase;
+       unsigned int    gpio_line;
+       int             error;
+};
+
+/* ------------------------------------------------------------------------ */
+
+static inline void rb153_pata_finish_io(struct ata_port *ap)
+{
+       struct ata_host *ah = ap->host;
+
+       ata_altstatus(ap);
+       ndelay(RB153_CF_IO_DELAY);
+
+       set_irq_type(ah->irq, IRQ_TYPE_LEVEL_HIGH);
+}
+
+static void rb153_pata_exec_command(struct ata_port *ap,
+                               const struct ata_taskfile *tf)
+{
+       writeb(tf->command, ap->ioaddr.command_addr);
+       rb153_pata_finish_io(ap);
+}
+
+static void rb153_pata_data_xfer(struct ata_device *adev, unsigned char *buf,
+                               unsigned int buflen, int write_data)
+{
+       struct ata_port *ap = adev->ap;
+       unsigned int i;
+
+       if (write_data) {
+               for (i = 0; i < buflen; i++)
+                       writeb(buf[i], ap->ioaddr.data_addr);
+       } else {
+               for (; buflen > 0; buflen--)
+                       buf[i] = readb(ap->ioaddr.data_addr);
+       }
+
+       rb153_pata_finish_io(ap);
+}
+
+static void rb153_pata_thaw(struct ata_port *ap)
+{
+       struct rb153_cf_info *info = ap->host->private_data;
+
+       info->error = 0;
+}
+
+static irqreturn_t rb153_pata_irq_handler(int irq, void *dev_instance)
+{
+       struct ata_host *ah = dev_instance;
+       struct rb153_cf_info *info = ah->private_data;
+
+       if (gpio_get_value(info->gpio_line)) {
+               set_irq_type(ah->irq, IRQ_TYPE_LEVEL_LOW);
+               if (!info->error)
+                       ata_interrupt(irq, dev_instance);
+       } else {
+               set_irq_type(ah->irq, IRQ_TYPE_LEVEL_HIGH);
+       }
+
+       return IRQ_HANDLED;
+}
+
+static void rb153_pata_irq_clear(struct ata_port *ap)
+{
+}
+
+static int rb153_pata_port_start(struct ata_port *ap)
+{
+       return 0;
+}
+
+static struct ata_port_operations rb153_pata_port_ops = {
+       .port_disable           = ata_port_disable,
+
+       .tf_load                = ata_tf_load,
+       .tf_read                = ata_tf_read,
+
+       .exec_command           = rb153_pata_exec_command,
+       .check_status           = ata_check_status,
+       .dev_select             = ata_std_dev_select,
+
+       .data_xfer              = rb153_pata_data_xfer,
+
+       .qc_prep                = ata_qc_prep,
+       .qc_issue               = ata_qc_issue_prot,
+
+       .thaw                   = rb153_pata_thaw,
+       .error_handler          = ata_bmdma_error_handler,
+
+       .irq_handler            = rb153_pata_irq_handler,
+       .irq_clear              = rb153_pata_irq_clear,
+       .irq_on                 = ata_irq_on,
+
+       .port_start             = rb153_pata_port_start,
+};
+
+/* ------------------------------------------------------------------------ */
+
+static struct scsi_host_template rb153_pata_sht = {
+       .module                 = THIS_MODULE,
+       .name                   = DRV_NAME,
+       .ioctl                  = ata_scsi_ioctl,
+       .queuecommand           = ata_scsi_queuecmd,
+       .slave_configure        = ata_scsi_slave_config,
+       .slave_destroy          = ata_scsi_slave_destroy,
+       .bios_param             = ata_std_bios_param,
+       .proc_name              = DRV_NAME,
+
+       .can_queue              = ATA_DEF_QUEUE,
+       .this_id                = ATA_SHT_THIS_ID,
+       .sg_tablesize           = LIBATA_MAX_PRD,
+       .dma_boundary           = ATA_DMA_BOUNDARY,
+       .cmd_per_lun            = ATA_SHT_CMD_PER_LUN,
+       .emulated               = ATA_SHT_EMULATED,
+       .use_clustering         = ATA_SHT_USE_CLUSTERING,
+};
+
+/* ------------------------------------------------------------------------ */
+
+static void rb153_pata_setup_ports(struct ata_host *ah)
+{
+       struct rb153_cf_info *info = ah->private_data;
+       struct ata_port *ap;
+       struct ata_ioports *iop;
+
+       ap = ah->ports[0];
+       iop = &ap->ioaddr;
+
+       ap->ops         = &rb153_pata_port_ops;
+       ap->pio_mask    = 0x1f; /* PIO4 */
+       ap->flags       |= ATA_FLAG_MMIO | ATA_FLAG_NO_LEGACY;
+
+       iop->cmd_addr           = info->iobase + RB153_CF_REG_CMD;
+       iop->ctl_addr           = info->iobase + RB153_CF_REG_CTRL;
+       iop->altstatus_addr     = info->iobase + RB153_CF_REG_CTRL;
+       iop->data_addr          = info->iobase + RB153_CF_REG_DATA;
+
+       ata_std_ports(iop);
+}
+
+static __devinit int rb153_pata_driver_probe(struct platform_device *pdev)
+{
+       unsigned int irq;
+       int gpio;
+       struct resource *res;
+       struct ata_host *ah;
+       struct rb153_cf_info *info;
+       int ret;
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (!res) {
+               dev_err(&pdev->dev, "no IOMEM resource found\n");
+               return -EINVAL;
+       }
+
+       irq = platform_get_irq(pdev, 0);
+       if (irq <= 0) {
+               dev_err(&pdev->dev, "no IRQ resource found\n");
+               return -ENOENT;
+       }
+
+       gpio = irq_to_gpio(irq);
+       if (gpio < 0) {
+               dev_err(&pdev->dev, "no GPIO found for irq%d\n", irq);
+               return -ENOENT;
+       }
+
+       ret = gpio_request(gpio, DRV_NAME);
+       if (ret) {
+               dev_err(&pdev->dev, "GPIO request failed\n");
+               return ret;
+       }
+
+       /* allocate host */
+       ah = ata_host_alloc(&pdev->dev, RB153_CF_MAXPORTS);
+       if (!ah)
+               return -ENOMEM;
+
+       platform_set_drvdata(pdev, ah);
+
+       info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
+       if (!info)
+               return -ENOMEM;
+
+       ah->private_data = info;
+
+       info->iobase = devm_ioremap_nocache(&pdev->dev, res->start,
+                               res->end - res->start + 1);
+       if (!info->iobase)
+               return -ENOMEM;
+
+       ret = gpio_direction_input(gpio);
+       if (ret) {
+               dev_err(&pdev->dev, "unable to set GPIO direction, err=%d\n",
+                               ret);
+               goto err_free_gpio;
+       }
+
+       rb153_pata_setup_ports(ah);
+
+       ret = ata_host_activate(ah, irq, ata_interrupt, IRQF_TRIGGER_HIGH,
+                               &rb153_pata_sht);
+       if (ret)
+               goto err_free_gpio;
+
+       return 0;
+
+err_free_gpio:
+       gpio_free(gpio);
+
+       return ret;
+}
+
+static __devexit int rb153_pata_driver_remove(struct platform_device *pdev)
+{
+       struct ata_host *ah = platform_get_drvdata(pdev);
+       struct rb153_cf_info *info = ah->private_data;
+
+       ata_host_detach(ah);
+       gpio_free(info->gpio_line);
+
+       return 0;
+}
+
+static struct platform_driver rb153_pata_platform_driver = {
+       .probe          = rb153_pata_driver_probe,
+       .remove         = __devexit_p(rb153_pata_driver_remove),
+       .driver  = {
+               .name   = DRV_NAME,
+               .owner  = THIS_MODULE,
+       },
+};
+
+/* ------------------------------------------------------------------------ */
+
+#define DRV_INFO DRV_DESC " version " DRV_VERSION
+
+static int __init rb153_pata_module_init(void)
+{
+       printk(KERN_INFO DRV_INFO "\n");
+
+       return platform_driver_register(&rb153_pata_platform_driver);
+}
+
+static void __exit rb153_pata_module_exit(void)
+{
+       platform_driver_unregister(&rb153_pata_platform_driver);
+}
+
+MODULE_AUTHOR("Gabor Juhos <juhosg at openwrt.org>");
+MODULE_DESCRIPTION(DRV_DESC);
+MODULE_VERSION(DRV_VERSION);
+MODULE_LICENSE("GPL");
+
+module_init(rb153_pata_module_init);
+module_exit(rb153_pata_module_exit);
index 2f92a4564a70b52d63c8cb3205f23cab9cb2b1e8..42e9513792663677f228abea25f98f768e43ca6a 100644 (file)
 #define ADM5120_SDRAM0_BASE    0x00000000
 #define ADM5120_SDRAM1_BASE    0x01000000
 #define ADM5120_SRAM1_BASE     0x10000000
-#define ADM5120_NAND_BASE      ADM5120_SRAM1_BASE
 #define ADM5120_EXTIO0_BASE    0x10C00000
+#define ADM5120_EXTIO0_SIZE    0x00200000
+#define ADM5120_EXTIO1_BASE    0x10E00000
+#define ADM5120_EXTIO1_SIZE    0x00200000
 #define ADM5120_MPMC_BASE      0x11000000
+#define ADM5120_MPMC_SIZE      0x00200000
 #define ADM5120_USBC_BASE      0x11200000
+#define ADM5120_USBC_SIZE      0x00200000
 #define ADM5120_PCIMEM_BASE    0x11400000
+#define ADM5120_PCIMEM_SIZE    0x00100000
 #define ADM5120_PCIIO_BASE     0x11500000
+#define ADM5120_PCIIO_SIZE     0x000FFFF0
 #define ADM5120_PCICFG_ADDR    0x115FFFF0
 #define ADM5120_PCICFG_DATA    0x115FFFF8
+#define ADM5120_PCICFG_SIZE    0x00000010
 #define ADM5120_SWITCH_BASE    0x12000000
+#define ADM5120_SWITCH_SIZE    0x00200000
 #define ADM5120_INTC_BASE      0x12200000
+#define ADM5120_INTC_SIZE      0x00200000
 #define ADM5120_UART0_BASE     0x12600000
 #define ADM5120_UART1_BASE     0x12800000
+#define ADM5120_UART_SIZE      0x00200000
 #define ADM5120_SRAM0_BASE     0x1FC00000
 
+#define ADM5120_NAND_BASE      ADM5120_SRAM1_BASE
 #define ADM5120_NAND_SIZE      0xB
-#define ADM5120_MPMC_SIZE      0x1000
-#define ADM5120_USBC_SIZE      0x84
-#define ADM5120_PCIMEM_SIZE    (ADM5120_PCIIO_BASE - ADM5120_PCIMEM_BASE)
-#define ADM5120_PCIIO_SIZE     (ADM5120_PCICFG_ADDR - ADM5120_PCIIO_BASE)
-#define ADM5120_PCICFG_SIZE    0x10
-#define ADM5120_SWITCH_SIZE    0x114
-#define ADM5120_INTC_SIZE      0x28
-#define ADM5120_UART_SIZE      0x20
 
 #define ADM5120_CLK_175                175000000
 #define ADM5120_CLK_200                200000000
diff --git a/target/linux/adm5120/patches-2.6.23/120-rb153_cf_driver.patch b/target/linux/adm5120/patches-2.6.23/120-rb153_cf_driver.patch
new file mode 100644 (file)
index 0000000..6bd6110
--- /dev/null
@@ -0,0 +1,26 @@
+--- linux-2.6.23.9/drivers/ata/Makefile.orig   2007-11-26 18:51:43.000000000 +0100
++++ linux-2.6.23.9/drivers/ata/Makefile        2007-12-08 18:15:07.000000000 +0100
+@@ -63,6 +63,7 @@
+ obj-$(CONFIG_PATA_SCC)                += pata_scc.o
+ obj-$(CONFIG_PATA_PLATFORM)   += pata_platform.o
+ obj-$(CONFIG_PATA_ICSIDE)     += pata_icside.o
++obj-$(CONFIG_PATA_RB153_CF)   += pata_rb153_cf.o
+ # Should be last but one libata driver
+ obj-$(CONFIG_ATA_GENERIC)     += ata_generic.o
+ # Should be last libata driver
+--- linux-2.6.23.9/drivers/ata/Kconfig.orig    2007-11-26 18:51:43.000000000 +0100
++++ linux-2.6.23.9/drivers/ata/Kconfig 2007-12-08 18:16:43.000000000 +0100
+@@ -596,4 +596,13 @@
+         If unsure, say N.
++config PATA_RB153_CF
++      tristate "RouterBOARD 153 Compact Flash support"
++      depends on MIPS_ADM5120
++      help
++        This option enables support for a Compact Flash connected on
++        the RouterBOARD 153.
++
++        If unsure, say N.
++
+ endif # ATA
index fddcb639610490565d5470eef38dae731b7a9282..fdeed0a6ace5cc9bc9ce8d1b58ecc30a9309adf7 100644 (file)
@@ -7,7 +7,7 @@
 
 define Profile/RouterBoard
        NAME:=Mikrotik RouterBoard 1xx family
-       PACKAGES:=kmod-madwifi kmod-rb153-cf
+       PACKAGES:=kmod-madwifi kmod-pata-rb153-cf
 endef
 
 define Profile/RouterBoard/Description