[ppc40x] backport Magicbox CF driver to 2.6.28
authorGabor Juhos <juhosg@openwrt.org>
Sun, 19 Jul 2009 17:46:07 +0000 (17:46 +0000)
committerGabor Juhos <juhosg@openwrt.org>
Sun, 19 Jul 2009 17:46:07 +0000 (17:46 +0000)
SVN-Revision: 16923

target/linux/ppc40x/patches/100-magicbox-ide-driver.patch [new file with mode: 0644]
target/linux/ppc40x/patches/101-powerpc-add-EBC_BXCR_BW-defines.patch [new file with mode: 0644]
target/linux/ppc40x/patches/102-openrb-light-cf-card-fixup.patch [new file with mode: 0644]
target/linux/ppc40x/patches/103-openrb-light-add-cf-card-to-dts.patch [new file with mode: 0644]
target/linux/ppc40x/patches/104-magicboxv2-cf-card-fixup.patch [new file with mode: 0644]
target/linux/ppc40x/patches/105-magicboxv2-add-cf-card-to-dts.patch [new file with mode: 0644]

diff --git a/target/linux/ppc40x/patches/100-magicbox-ide-driver.patch b/target/linux/ppc40x/patches/100-magicbox-ide-driver.patch
new file mode 100644 (file)
index 0000000..eca26a9
--- /dev/null
@@ -0,0 +1,359 @@
+--- a/drivers/ide/Kconfig
++++ b/drivers/ide/Kconfig
+@@ -712,6 +712,11 @@ config BLK_DEV_IDE_AU1XXX_SEQTS_PER_RQ
+        default "128"
+        depends on BLK_DEV_IDE_AU1XXX
++config BLK_DEV_IDE_MAGICBOX
++      tristate "Magicbox CF card support"
++      depends on MAGICBOXV2 || OPENRB_LIGHT
++      select IDE_XFER_MODE
++
+ config BLK_DEV_IDE_TX4938
+       tristate "TX4938 internal IDE support"
+       depends on SOC_TX4938
+--- a/drivers/ide/Makefile
++++ b/drivers/ide/Makefile
+@@ -110,6 +110,7 @@ obj-$(CONFIG_BLK_DEV_IDE_RAPIDE)   += rapi
+ obj-$(CONFIG_BLK_DEV_PALMCHIP_BK3710) += palm_bk3710.o
+ obj-$(CONFIG_BLK_DEV_IDE_AU1XXX)      += au1xxx-ide.o
++obj-$(CONFIG_BLK_DEV_IDE_MAGICBOX)    += magicbox_ide.o
+ obj-$(CONFIG_BLK_DEV_IDE_TX4938)      += tx4938ide.o
+ obj-$(CONFIG_BLK_DEV_IDE_TX4939)      += tx4939ide.o
+--- /dev/null
++++ b/drivers/ide/magicbox_ide.c
+@@ -0,0 +1,332 @@
++/*
++ *  IDE driver for the MagicBox 2.0 onboard CompactFlash slot.
++ *
++ *  Copyright (C) 2009 Gabor Juhos <juhosg@openwrt.org>
++ *
++ *  Based on the original driver by Wojtek Kaniewski <wojtekka@toxygen.net>
++ *
++ *  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/types.h>
++#include <linux/ioport.h>
++#include <linux/of.h>
++#include <linux/of_device.h>
++#include <linux/of_platform.h>
++#include <linux/ide.h>
++
++#define DRV_DESC      "IDE driver for Magicbox 2.0 onboard CF slot"
++#define DRV_NAME      "magicbox_cf"
++
++static u8 magicbox_ide_inb(unsigned long port)
++{
++      return (u8) (readw((void __iomem *) port) >> 8) & 0xff;
++}
++
++static void magicbox_ide_outb(u8 value, unsigned long port)
++{
++      writew(value << 8, (void __iomem *) port);
++}
++
++static inline void magicbox_ide_insw(unsigned long port, void *addr, u32 count)
++{
++      u16 *ptr;
++
++      for (ptr = addr; count--; ptr++)
++              *ptr = readw((void __iomem *) port);
++}
++
++static inline void magicbox_ide_insl(unsigned long port, void *addr, u32 count)
++{
++      u32 *ptr;
++
++      for (ptr = addr; count--; ptr++)
++              *ptr = readl((void __iomem *) port);
++}
++
++static inline void magicbox_ide_outsw(unsigned long port, void *addr,
++                                      u32 count)
++{
++      u16 *ptr;
++
++      for (ptr = addr; count--; ptr++)
++              writew(*ptr, (void __iomem *) port);
++}
++
++static inline void magicbox_ide_outsl(unsigned long port, void *addr,
++                                      u32 count)
++{
++      u32 *ptr;
++
++      for (ptr = addr; count--; ptr++)
++              writel(*ptr, (void __iomem *) port);
++}
++
++static void magicbox_ide_exec_command(ide_hwif_t *hwif, u8 cmd)
++{
++      magicbox_ide_outb(cmd, hwif->io_ports.command_addr);
++}
++
++static u8 magicbox_ide_read_status(ide_hwif_t *hwif)
++{
++      return magicbox_ide_inb(hwif->io_ports.status_addr);
++}
++
++static u8 magicbox_ide_read_altstatus(ide_hwif_t *hwif)
++{
++      return magicbox_ide_inb(hwif->io_ports.ctl_addr);
++}
++
++static void magicbox_ide_tf_load(ide_drive_t *drive, ide_task_t *task)
++{
++      struct ide_io_ports *io_ports = &drive->hwif->io_ports;
++      struct ide_taskfile *tf = &task->tf;
++      u8 HIHI = (task->tf_flags & IDE_TFLAG_LBA48) ? 0xE0 : 0xEF;
++
++      if (task->tf_flags & IDE_TFLAG_FLAGGED)
++              HIHI = 0xFF;
++
++      if (task->tf_flags & IDE_TFLAG_OUT_DATA)
++              writel((tf->hob_data << 8) | tf->data,
++                      (void __iomem *) io_ports->data_addr);
++
++      if (task->tf_flags & IDE_TFLAG_OUT_HOB_FEATURE)
++              magicbox_ide_outb(tf->hob_feature, io_ports->feature_addr);
++      if (task->tf_flags & IDE_TFLAG_OUT_HOB_NSECT)
++              magicbox_ide_outb(tf->hob_nsect, io_ports->nsect_addr);
++      if (task->tf_flags & IDE_TFLAG_OUT_HOB_LBAL)
++              magicbox_ide_outb(tf->hob_lbal, io_ports->lbal_addr);
++      if (task->tf_flags & IDE_TFLAG_OUT_HOB_LBAM)
++              magicbox_ide_outb(tf->hob_lbam, io_ports->lbam_addr);
++      if (task->tf_flags & IDE_TFLAG_OUT_HOB_LBAH)
++              magicbox_ide_outb(tf->hob_lbah, io_ports->lbah_addr);
++
++      if (task->tf_flags & IDE_TFLAG_OUT_FEATURE)
++              magicbox_ide_outb(tf->feature, io_ports->feature_addr);
++      if (task->tf_flags & IDE_TFLAG_OUT_NSECT)
++              magicbox_ide_outb(tf->nsect, io_ports->nsect_addr);
++      if (task->tf_flags & IDE_TFLAG_OUT_LBAL)
++              magicbox_ide_outb(tf->lbal, io_ports->lbal_addr);
++      if (task->tf_flags & IDE_TFLAG_OUT_LBAM)
++              magicbox_ide_outb(tf->lbam, io_ports->lbam_addr);
++      if (task->tf_flags & IDE_TFLAG_OUT_LBAH)
++              magicbox_ide_outb(tf->lbah, io_ports->lbah_addr);
++
++      if (task->tf_flags & IDE_TFLAG_OUT_DEVICE)
++              magicbox_ide_outb((tf->device & HIHI) | drive->select,
++                           io_ports->device_addr);
++}
++
++static void magicbox_ide_tf_read(ide_drive_t *drive, ide_task_t *task)
++{
++      struct ide_io_ports *io_ports = &drive->hwif->io_ports;
++      struct ide_taskfile *tf = &task->tf;
++
++      if (task->tf_flags & IDE_TFLAG_IN_DATA) {
++              u16 data = (u16) readl((void __iomem *) io_ports->data_addr);
++
++              tf->data = data & 0xff;
++              tf->hob_data = (data >> 8) & 0xff;
++      }
++
++      /* be sure we're looking at the low order bits */
++      magicbox_ide_outb(ATA_DEVCTL_OBS & ~0x80, io_ports->ctl_addr);
++
++      if (task->tf_flags & IDE_TFLAG_IN_NSECT)
++              tf->nsect  = magicbox_ide_inb(io_ports->nsect_addr);
++      if (task->tf_flags & IDE_TFLAG_IN_LBAL)
++              tf->lbal   = magicbox_ide_inb(io_ports->lbal_addr);
++      if (task->tf_flags & IDE_TFLAG_IN_LBAM)
++              tf->lbam   = magicbox_ide_inb(io_ports->lbam_addr);
++      if (task->tf_flags & IDE_TFLAG_IN_LBAH)
++              tf->lbah   = magicbox_ide_inb(io_ports->lbah_addr);
++      if (task->tf_flags & IDE_TFLAG_IN_DEVICE)
++              tf->device = magicbox_ide_inb(io_ports->device_addr);
++
++      if (task->tf_flags & IDE_TFLAG_LBA48) {
++              magicbox_ide_outb(ATA_DEVCTL_OBS | 0x80, io_ports->ctl_addr);
++
++              if (task->tf_flags & IDE_TFLAG_IN_HOB_FEATURE)
++                      tf->hob_feature = magicbox_ide_inb(io_ports->feature_addr);
++              if (task->tf_flags & IDE_TFLAG_IN_HOB_NSECT)
++                      tf->hob_nsect   = magicbox_ide_inb(io_ports->nsect_addr);
++              if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAL)
++                      tf->hob_lbal    = magicbox_ide_inb(io_ports->lbal_addr);
++              if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAM)
++                      tf->hob_lbam    = magicbox_ide_inb(io_ports->lbam_addr);
++              if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAH)
++                      tf->hob_lbah    = magicbox_ide_inb(io_ports->lbah_addr);
++      }
++}
++
++static void magicbox_ide_input_data(ide_drive_t *drive, struct request *rq,
++                         void *buf, unsigned int len)
++{
++      unsigned long port = drive->hwif->io_ports.data_addr;
++
++      len++;
++
++      if (drive->io_32bit) {
++              magicbox_ide_insl(port, buf, len / 4);
++
++              if ((len & 3) >= 2)
++                      magicbox_ide_insw(port, (u8 *)buf + (len & ~3), 1);
++      } else
++              magicbox_ide_insw(port, buf, len / 2);
++}
++
++static void magicbox_ide_output_data(ide_drive_t *drive,  struct request *rq,
++                          void *buf, unsigned int len)
++{
++      unsigned long port = drive->hwif->io_ports.data_addr;
++
++      len++;
++
++      if (drive->io_32bit) {
++              magicbox_ide_outsl(port, buf, len / 4);
++
++              if ((len & 3) >= 2)
++                      magicbox_ide_outsw(port, (u8 *)buf + (len & ~3), 1);
++      } else
++              magicbox_ide_outsw(port, buf, len / 2);
++}
++
++static void magicbox_ide_set_pio_mode(ide_drive_t *drive, const u8 pio)
++{
++}
++
++static u8 magicbox_ide_cable_detect(ide_hwif_t *hwif)
++{
++      return ATA_CBL_PATA40;
++}
++
++static const struct ide_tp_ops magicbox_ide_tp_ops = {
++      .exec_command   = magicbox_ide_exec_command,
++      .read_status    = magicbox_ide_read_status,
++      .read_altstatus = magicbox_ide_read_altstatus,
++
++      .set_irq        = ide_set_irq,
++      .tf_load        = magicbox_ide_tf_load,
++      .tf_read        = magicbox_ide_tf_read,
++
++      .input_data     = magicbox_ide_input_data,
++      .output_data    = magicbox_ide_output_data,
++};
++
++static const struct ide_port_ops magicbox_ide_port_ops = {
++      .set_pio_mode   = magicbox_ide_set_pio_mode,
++      .cable_detect   = magicbox_ide_cable_detect,
++};
++
++static const struct ide_port_info magicbox_ide_port_info = {
++      .name           = DRV_NAME,
++      .chipset        = ide_generic,
++      .tp_ops         = &magicbox_ide_tp_ops,
++      .port_ops       = &magicbox_ide_port_ops,
++      .host_flags     = IDE_HFLAG_SINGLE |
++                        IDE_HFLAG_NO_DMA |
++                        IDE_HFLAG_MMIO |
++                        IDE_HFLAG_UNMASK_IRQS,
++      .pio_mask       = ATA_PIO4,
++};
++
++static inline void magicbox_ide_setup_hw(hw_regs_t *hw, u16 __iomem *base,
++                                       u16 __iomem *ctrl, int irq)
++{
++      unsigned long port = (unsigned long) base;
++      int i;
++
++      memset(hw, 0, sizeof(*hw));
++      for (i = 0; i <= 7; i++)
++              hw->io_ports_array[i] = port + i * 2;
++
++      /*
++       * the IDE control register is at ATA address 6,
++       * with CS1 active instead of CS0
++       */
++      hw->io_ports.ctl_addr = (unsigned long)ctrl + (6 * 2);
++
++      hw->irq = irq;
++      hw->chipset = ide_generic;
++      hw->ack_intr = NULL;
++}
++
++static int __devinit magicbox_ide_of_probe(struct of_device *op,
++                                         const struct of_device_id *match)
++{
++      hw_regs_t hw;
++      hw_regs_t *hws[] = { &hw, NULL, NULL, NULL };
++      struct ide_host *host;
++      u16 __iomem *base;
++      u16 __iomem *ctrl;
++      int irq;
++      int ret = 0;
++
++      irq = irq_of_parse_and_map(op->node, 0);
++      if (irq < 0) {
++              dev_err(&op->dev, "invalid irq\n");
++              ret = -EINVAL;
++              goto err_exit;
++      }
++
++      base = of_iomap(op->node, 0);
++      if (base == NULL) {
++              ret = -ENOMEM;
++              goto err_exit;
++      }
++
++      ctrl = of_iomap(op->node, 1);
++      if (ctrl == NULL) {
++              ret = -ENOMEM;
++              goto err_unmap_base;
++      }
++
++      magicbox_ide_setup_hw(&hw, base, ctrl, irq);
++
++      hw.dev = &op->dev;
++
++      ret = ide_host_add(&magicbox_ide_port_info, hws, &host);
++      if (ret)
++              goto err_unmap_ctrl;
++
++      dev_set_drvdata(&op->dev, host);
++
++      return 0;
++
++ err_unmap_ctrl:
++      iounmap(ctrl);
++ err_unmap_base:
++      iounmap(base);
++ err_exit:
++      return ret;
++}
++
++static struct of_device_id magicbox_ide_of_match[] = {
++      { .compatible = "magicbox-cf", },
++      {},
++};
++
++static struct of_platform_driver magicbox_ide_of_platform_driver = {
++      .owner          = THIS_MODULE,
++      .name           = DRV_NAME,
++      .match_table    = magicbox_ide_of_match,
++      .probe          = magicbox_ide_of_probe,
++      .driver         = {
++              .name   = DRV_NAME,
++              .owner  = THIS_MODULE,
++      },
++};
++
++static int __init magicbox_ide_init(void)
++{
++      return of_register_platform_driver(&magicbox_ide_of_platform_driver);
++}
++
++module_init(magicbox_ide_init);
++
++MODULE_DESCRIPTION(DRV_DESC);
++MODULE_AUTHOR("Gabor Juhos <juhosg@openwrt.org>");
++MODULE_LICENSE("GPL v2");
++MODULE_DEVICE_TABLE(of, magicbox_ide_of_match);
diff --git a/target/linux/ppc40x/patches/101-powerpc-add-EBC_BXCR_BW-defines.patch b/target/linux/ppc40x/patches/101-powerpc-add-EBC_BXCR_BW-defines.patch
new file mode 100644 (file)
index 0000000..8e380c1
--- /dev/null
@@ -0,0 +1,12 @@
+--- a/arch/powerpc/boot/dcr.h
++++ b/arch/powerpc/boot/dcr.h
+@@ -57,6 +57,9 @@ static const unsigned long sdram_bxcr[] 
+ #define             EBC_BXCR_BU_WO                                  0x00010000
+ #define             EBC_BXCR_BU_RW                                  0x00018000
+ #define           EBC_BXCR_BW                                     0x00006000
++#define             EBC_BXCR_BW_8                                   0x00000000
++#define             EBC_BXCR_BW_16                                  0x00002000
++#define             EBC_BXCR_BW_32                                  0x00006000
+ #define   EBC_B0AP                                      0x10
+ #define   EBC_B1AP                                      0x11
+ #define   EBC_B2AP                                      0x12
diff --git a/target/linux/ppc40x/patches/102-openrb-light-cf-card-fixup.patch b/target/linux/ppc40x/patches/102-openrb-light-cf-card-fixup.patch
new file mode 100644 (file)
index 0000000..7e8d2ef
--- /dev/null
@@ -0,0 +1,39 @@
+--- a/arch/powerpc/boot/cuboot-openrb-light.c
++++ b/arch/powerpc/boot/cuboot-openrb-light.c
+@@ -22,8 +22,36 @@
+ static bd_t bd;
++static void fixup_cf_card(void)
++{
++#define DCRN_CPC0_PCI_BASE    0xf9
++#define CF_CS0_BASE           0xff100000
++#define CF_CS1_BASE           0xff200000
++
++      /* Turn on PerWE instead of PCIsomething */
++      mtdcr(DCRN_CPC0_PCI_BASE,
++            mfdcr(DCRN_CPC0_PCI_BASE) | (0x80000000L >> 27));
++
++      /* PerCS1 (CF's CS0): base 0xff100000, 16-bit, rw */
++      mtdcr(DCRN_EBC0_CFGADDR, EBC_B1CR);
++      mtdcr(DCRN_EBC0_CFGDATA, CF_CS0_BASE | EBC_BXCR_BU_RW | EBC_BXCR_BW_16);
++      mtdcr(DCRN_EBC0_CFGADDR, EBC_B1AP);
++      mtdcr(DCRN_EBC0_CFGDATA, 0x080bd800);
++
++      /* PerCS2 (CF's CS1): base 0xff200000, 16-bit, rw */
++      mtdcr(DCRN_EBC0_CFGADDR, EBC_B2CR);
++      mtdcr(DCRN_EBC0_CFGDATA, CF_CS1_BASE | EBC_BXCR_BU_RW | EBC_BXCR_BW_16);
++      mtdcr(DCRN_EBC0_CFGADDR, EBC_B2AP);
++      mtdcr(DCRN_EBC0_CFGDATA, 0x080bd800);
++
++#undef DCRN_CPC0_PCI_BASE
++#undef CF_CS0_BASE
++#undef CF_CS1_BASE
++}
++
+ static void openrb_light_fixups(void)
+ {
++      fixup_cf_card();
+       ibm405ep_fixup_clocks(33333000);
+       ibm4xx_sdram_fixup_memsize();
+       dt_fixup_mac_addresses(&bd.bi_enetaddr, &bd.bi_enet1addr);
diff --git a/target/linux/ppc40x/patches/103-openrb-light-add-cf-card-to-dts.patch b/target/linux/ppc40x/patches/103-openrb-light-add-cf-card-to-dts.patch
new file mode 100644 (file)
index 0000000..ee49aa1
--- /dev/null
@@ -0,0 +1,17 @@
+--- a/arch/powerpc/boot/dts/openrb-light.dts
++++ b/arch/powerpc/boot/dts/openrb-light.dts
+@@ -177,6 +177,14 @@
+                        */
+                       clock-frequency = <0>; /* Filled in by zImage */
++                      cf_card@ff100000 {
++                              compatible = "magicbox-cf";
++                              reg = <0x00000000 0xff100000 0x00001000
++                                     0x00000000 0xff200000 0x00001000>;
++                              interrupt-parent = <&UIC0>;
++                              interrupts = <0x19 0x1 /* IRQ_TYPE_EDGE_RISING */ >;
++                      };
++
+                       nor_flash@ff800000 {
+                               compatible = "cfi-flash";
+                               bank-width = <2>;
diff --git a/target/linux/ppc40x/patches/104-magicboxv2-cf-card-fixup.patch b/target/linux/ppc40x/patches/104-magicboxv2-cf-card-fixup.patch
new file mode 100644 (file)
index 0000000..56e337c
--- /dev/null
@@ -0,0 +1,47 @@
+--- a/arch/powerpc/boot/cuboot-magicboxv2.c
++++ b/arch/powerpc/boot/cuboot-magicboxv2.c
+@@ -2,6 +2,7 @@
+  * Old U-boot compatibility for Magicbox v2
+  *
+  * Author: Imre Kaloz <kaloz@openwrt.org>
++ *         Gabor Juhos <juhosg@openwrt.org>
+  *
+  * 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
+@@ -22,8 +23,36 @@
+ static bd_t bd;
++static void fixup_cf_card(void)
++{
++#define DCRN_CPC0_PCI_BASE    0xf9
++#define CF_CS0_BASE   0xff100000
++#define CF_CS1_BASE   0xff200000
++
++      /* Turn on PerWE instead of PCIsomething */
++      mtdcr(DCRN_CPC0_PCI_BASE,
++            mfdcr(DCRN_CPC0_PCI_BASE) | (0x80000000L >> 27));
++
++      /* PerCS1 (CF's CS0): base 0xff100000, 16-bit, rw */
++      mtdcr(DCRN_EBC0_CFGADDR, EBC_B1CR);
++      mtdcr(DCRN_EBC0_CFGDATA, CF_CS0_BASE | EBC_BXCR_BU_RW | EBC_BXCR_BW_16);
++      mtdcr(DCRN_EBC0_CFGADDR, EBC_B1AP);
++      mtdcr(DCRN_EBC0_CFGDATA, 0x080bd800);
++
++      /* PerCS2 (CF's CS1): base 0xff200000, 16-bit, rw */
++      mtdcr(DCRN_EBC0_CFGADDR, EBC_B2CR);
++      mtdcr(DCRN_EBC0_CFGDATA, CF_CS1_BASE | EBC_BXCR_BU_RW | EBC_BXCR_BW_16);
++      mtdcr(DCRN_EBC0_CFGADDR, EBC_B2AP);
++      mtdcr(DCRN_EBC0_CFGDATA, 0x080bd800);
++
++#undef DCRN_CPC0_PCI_BASE
++#undef CF_CS0_BASE
++#undef CF_CS1_BASE
++}
++
+ static void magicboxv2_fixups(void)
+ {
++      fixup_cf_card();
+       ibm405ep_fixup_clocks(25000000);
+       ibm4xx_sdram_fixup_memsize();
+       dt_fixup_mac_addresses(&bd.bi_enetaddr, &bd.bi_enet1addr);
diff --git a/target/linux/ppc40x/patches/105-magicboxv2-add-cf-card-to-dts.patch b/target/linux/ppc40x/patches/105-magicboxv2-add-cf-card-to-dts.patch
new file mode 100644 (file)
index 0000000..9799090
--- /dev/null
@@ -0,0 +1,25 @@
+--- a/arch/powerpc/boot/dts/magicboxv2.dts
++++ b/arch/powerpc/boot/dts/magicboxv2.dts
+@@ -2,6 +2,7 @@
+  * Device Tree Source for Magicbox v2
+  *
+  * Copyright 2008 Imre Kaloz <kaloz@openwrt.org>
++ * Copyright 2009 Gabor Juhos <juhosg@openwrt.org>
+  *
+  * Based on walnut.dts
+  *
+@@ -183,6 +184,14 @@
+                        */
+                       clock-frequency = <0>; /* Filled in by zImage */
++                      cf_card@ff100000 {
++                              compatible = "magicbox-cf";
++                              reg = <0x00000000 0xff100000 0x00001000
++                                     0x00000000 0xff200000 0x00001000>;
++                              interrupt-parent = <&UIC0>;
++                              interrupts = <0x19 0x1 /* IRQ_TYPE_EDGE_RISING */ >;
++                      };
++
+                       nor_flash@ffc00000 {
+                               compatible = "cfi-flash";
+                               bank-width = <2>;