source: trunk/target/linux/ppc40x/patches/101-pata-magicbox-cf-driver.patch @ 27826

Last change on this file since 27826 was 27826, checked in by kaloz, 5 years ago

[ppc40x]: upgrade to 3.0 (magicbox ata and openrb usb is broken, but the current kernel didn't compile at all, so...)

File size: 11.8 KB
  • drivers/ata/Kconfig

    a b config PDC_ADMA 
    144144 
    145145          If unsure, say N. 
    146146 
     147config PATA_MAGICBOX_CF 
     148        tristate "Magicbox/OpenRB Compact Flash support" 
     149        depends on MAGICBOX || OPENRB 
     150        help 
     151          This option enables support for a Compact Flash conected on 
     152          the ppc405ep expansion bus. This driver had been written for 
     153          the Magicbox v2 and OpenRB boards. 
     154 
     155          If unsure, say N. 
     156 
    147157config PATA_OCTEON_CF 
    148158        tristate "OCTEON Boot Bus Compact Flash support" 
    149159        depends on CPU_CAVIUM_OCTEON 
  • drivers/ata/Makefile

    a b obj-$(CONFIG_PATA_AT91) += pata_at91.o 
    8080obj-$(CONFIG_PATA_CMD640_PCI)   += pata_cmd640.o 
    8181obj-$(CONFIG_PATA_ISAPNP)       += pata_isapnp.o 
    8282obj-$(CONFIG_PATA_IXP4XX_CF)    += pata_ixp4xx_cf.o 
     83obj-$(CONFIG_PATA_MAGICBOX_CF)  += pata_magicbox_cf.o 
    8384obj-$(CONFIG_PATA_MPIIX)        += pata_mpiix.o 
    8485obj-$(CONFIG_PATA_NS87410)      += pata_ns87410.o 
    8586obj-$(CONFIG_PATA_OPTI)         += pata_opti.o 
  • new file drivers/ata/pata_magicbox_cf.c

    - +  
     1/* 
     2 *  PATA/CompactFlash driver for the MagicBox v2/OpenRB boards. 
     3 * 
     4 *  Copyright (C) 2009 Gabor Juhos <juhosg@openwrt.org> 
     5 * 
     6 *  Based on the IDE driver by Wojtek Kaniewski <wojtekka@toxygen.net> 
     7 * 
     8 *  This program is free software; you can redistribute it and/or modify it 
     9 *  under the terms of the GNU General Public License version 2 as published 
     10 *  by the Free Software Foundation. 
     11 */ 
     12 
     13#include <linux/kernel.h> 
     14#include <linux/module.h> 
     15#include <linux/types.h> 
     16#include <linux/ioport.h> 
     17#include <linux/libata.h> 
     18#include <linux/irq.h> 
     19#include <linux/of.h> 
     20#include <linux/of_device.h> 
     21#include <linux/of_platform.h> 
     22#include <scsi/scsi_host.h> 
     23 
     24#define DRV_DESC        "PATA/CompactFlash driver for Magicbox/OpenRB boards" 
     25#define DRV_NAME        "pata_magicbox_cf" 
     26#define DRV_VERSION     "0.1.0" 
     27 
     28#define MAGICBOX_CF_REG_CMD             (2 * ATA_REG_CMD) 
     29#define MAGICBOX_CF_REG_DATA            (2 * ATA_REG_DATA) 
     30#define MAGICBOX_CF_REG_ERR             (2 * ATA_REG_ERR) 
     31#define MAGICBOX_CF_REG_FEATURE         (2 * ATA_REG_FEATURE) 
     32#define MAGICBOX_CF_REG_NSECT           (2 * ATA_REG_NSECT) 
     33#define MAGICBOX_CF_REG_LBAL            (2 * ATA_REG_LBAL) 
     34#define MAGICBOX_CF_REG_LBAM            (2 * ATA_REG_LBAM) 
     35#define MAGICBOX_CF_REG_LBAH            (2 * ATA_REG_LBAH) 
     36#define MAGICBOX_CF_REG_DEVICE          (2 * ATA_REG_DEVICE) 
     37#define MAGICBOX_CF_REG_STATUS          (2 * ATA_REG_STATUS) 
     38#define MAGICBOX_CF_REG_ALTSTATUS       (2 * 6) 
     39#define MAGICBOX_CF_REG_CTL             (2 * 6) 
     40 
     41#define MAGICBOX_CF_MAXPORTS    1 
     42 
     43struct magicbox_cf_info { 
     44        void __iomem    *base; 
     45        void __iomem    *ctrl; 
     46}; 
     47 
     48static inline u8 magicbox_cf_inb(void __iomem *port) 
     49{ 
     50        return (u8) (readw(port) >> 8) & 0xff; 
     51} 
     52 
     53static inline void magicbox_cf_outb(void __iomem *port, u8 value) 
     54{ 
     55        writew(value << 8, port); 
     56} 
     57 
     58static int magicbox_cf_set_mode(struct ata_link *link, 
     59                                struct ata_device **error) 
     60{ 
     61        struct ata_device *dev; 
     62 
     63        ata_for_each_dev(dev, link, ENABLED) { 
     64                ata_dev_printk(dev, KERN_INFO, "configured for PIO0\n"); 
     65                dev->pio_mode = XFER_PIO_0; 
     66                dev->xfer_mode = XFER_PIO_0; 
     67                dev->xfer_shift = ATA_SHIFT_PIO; 
     68                dev->flags |= ATA_DFLAG_PIO; 
     69        } 
     70 
     71        return 0; 
     72} 
     73 
     74static void magicbox_cf_exec_command(struct ata_port *ap, 
     75                                     const struct ata_taskfile *tf) 
     76{ 
     77        DPRINTK("ata%u: cmd 0x%X\n", ap->print_id, tf->command); 
     78 
     79        magicbox_cf_outb(ap->ioaddr.command_addr, tf->command); 
     80        ata_sff_pause(ap); 
     81} 
     82 
     83static u8 magicbox_cf_check_status(struct ata_port *ap) 
     84{ 
     85        u8 status; 
     86 
     87        status = magicbox_cf_inb(ap->ioaddr.status_addr); 
     88 
     89        DPRINTK("ata%u: status 0x%X, from %p\n", ap->print_id, status, 
     90                ap->ioaddr.status_addr); 
     91 
     92        return status; 
     93} 
     94 
     95static u8 magicbox_cf_check_altstatus(struct ata_port *ap) 
     96{ 
     97        u8 altstatus; 
     98 
     99        altstatus = magicbox_cf_inb(ap->ioaddr.altstatus_addr); 
     100 
     101        DPRINTK("ata%u: altstatus 0x%X, from %p\n", ap->print_id, 
     102                altstatus, ap->ioaddr.altstatus_addr); 
     103 
     104        return altstatus; 
     105} 
     106 
     107static void magicbox_cf_dev_select(struct ata_port *ap, unsigned int device) 
     108{ 
     109        /* Nothing to do. We are supporting one device only. */ 
     110} 
     111 
     112static void magicbox_cf_tf_load(struct ata_port *ap, 
     113                                const struct ata_taskfile *tf) 
     114{ 
     115        struct ata_ioports *ioaddr = &ap->ioaddr; 
     116        unsigned int is_addr = tf->flags & ATA_TFLAG_ISADDR; 
     117 
     118        if (tf->ctl != ap->last_ctl) { 
     119                magicbox_cf_outb(ioaddr->ctl_addr, tf->ctl); 
     120                ap->last_ctl = tf->ctl; 
     121                ata_wait_idle(ap); 
     122        } 
     123 
     124        if (is_addr && (tf->flags & ATA_TFLAG_LBA48)) { 
     125                magicbox_cf_outb(ioaddr->feature_addr, tf->hob_feature); 
     126                magicbox_cf_outb(ioaddr->nsect_addr, tf->hob_nsect); 
     127                magicbox_cf_outb(ioaddr->lbal_addr, tf->hob_lbal); 
     128                magicbox_cf_outb(ioaddr->lbam_addr, tf->hob_lbam); 
     129                magicbox_cf_outb(ioaddr->lbah_addr, tf->hob_lbah); 
     130                VPRINTK("hob: feat 0x%X nsect 0x%X, lba 0x%X 0x%X 0x%X\n", 
     131                        tf->hob_feature, 
     132                        tf->hob_nsect, 
     133                        tf->hob_lbal, 
     134                        tf->hob_lbam, 
     135                        tf->hob_lbah); 
     136        } 
     137 
     138        if (is_addr) { 
     139                magicbox_cf_outb(ioaddr->feature_addr, tf->feature); 
     140                magicbox_cf_outb(ioaddr->nsect_addr, tf->nsect); 
     141                magicbox_cf_outb(ioaddr->lbal_addr, tf->lbal); 
     142                magicbox_cf_outb(ioaddr->lbam_addr, tf->lbam); 
     143                magicbox_cf_outb(ioaddr->lbah_addr, tf->lbah); 
     144                VPRINTK("feat 0x%X nsect 0x%X lba 0x%X 0x%X 0x%X\n", 
     145                        tf->feature, 
     146                        tf->nsect, 
     147                        tf->lbal, 
     148                        tf->lbam, 
     149                        tf->lbah); 
     150        } 
     151 
     152        if (tf->flags & ATA_TFLAG_DEVICE) { 
     153                magicbox_cf_outb(ioaddr->device_addr, tf->device); 
     154                VPRINTK("device 0x%X\n", tf->device); 
     155        } 
     156 
     157        ata_wait_idle(ap); 
     158} 
     159 
     160static void magicbox_cf_tf_read(struct ata_port *ap, struct ata_taskfile *tf) 
     161{ 
     162        struct ata_ioports *ioaddr = &ap->ioaddr; 
     163 
     164        tf->command = magicbox_cf_inb(ap->ioaddr.status_addr); 
     165        tf->feature = magicbox_cf_inb(ioaddr->error_addr); 
     166        tf->nsect = magicbox_cf_inb(ioaddr->nsect_addr); 
     167        tf->lbal = magicbox_cf_inb(ioaddr->lbal_addr); 
     168        tf->lbam = magicbox_cf_inb(ioaddr->lbam_addr); 
     169        tf->lbah = magicbox_cf_inb(ioaddr->lbah_addr); 
     170        tf->device = magicbox_cf_inb(ioaddr->device_addr); 
     171        VPRINTK("feat 0x%X nsect 0x%X lba 0x%X 0x%X 0x%X\n", 
     172                tf->feature, 
     173                tf->nsect, 
     174                tf->lbal, 
     175                tf->lbam, 
     176                tf->lbah); 
     177 
     178        if (tf->flags & ATA_TFLAG_LBA48) { 
     179                magicbox_cf_outb(ioaddr->ctl_addr, tf->ctl | ATA_HOB); 
     180                tf->hob_feature = magicbox_cf_inb(ioaddr->error_addr); 
     181                tf->hob_nsect = magicbox_cf_inb(ioaddr->nsect_addr); 
     182                tf->hob_lbal = magicbox_cf_inb(ioaddr->lbal_addr); 
     183                tf->hob_lbam = magicbox_cf_inb(ioaddr->lbam_addr); 
     184                tf->hob_lbah = magicbox_cf_inb(ioaddr->lbah_addr); 
     185                magicbox_cf_outb(ioaddr->ctl_addr, tf->ctl); 
     186                ap->last_ctl = tf->ctl; 
     187                VPRINTK("hob: feat 0x%X nsect 0x%X lba 0x%X 0x%X 0x%X\n", 
     188                        tf->feature, 
     189                        tf->nsect, 
     190                        tf->lbal, 
     191                        tf->lbam, 
     192                        tf->lbah); 
     193        } 
     194} 
     195 
     196static unsigned int magicbox_cf_data_xfer(struct ata_device *dev, 
     197                                          unsigned char *buf, 
     198                                          unsigned int buflen, int rw) 
     199{ 
     200        struct ata_port *ap = dev->link->ap; 
     201        unsigned int words = buflen >> 1; 
     202        unsigned int i; 
     203        u16 *buf16 = (u16 *) buf; 
     204        void __iomem *mmio = ap->ioaddr.data_addr; 
     205 
     206        /* Transfer multiple of 2 bytes */ 
     207        if (rw == READ) 
     208                for (i = 0; i < words; i++) 
     209                        buf16[i] = readw(mmio); 
     210        else 
     211                for (i = 0; i < words; i++) 
     212                        writew(buf16[i], mmio); 
     213 
     214        /* Transfer trailing 1 byte, if any. */ 
     215        if (unlikely(buflen & 0x01)) { 
     216                u16 align_buf[1] = { 0 }; 
     217                unsigned char *trailing_buf = buf + buflen - 1; 
     218 
     219                if (rw == READ) { 
     220                        align_buf[0] = readw(mmio); 
     221                        memcpy(trailing_buf, align_buf, 1); 
     222                } else { 
     223                        memcpy(align_buf, trailing_buf, 1); 
     224                        writew(align_buf[0], mmio); 
     225                } 
     226                words++; 
     227        } 
     228 
     229        return words << 1; 
     230} 
     231 
     232static u8 magicbox_cf_irq_on(struct ata_port *ap) 
     233{ 
     234        /* Nothing to do. */ 
     235        return 0; 
     236} 
     237 
     238static void magicbox_cf_irq_clear(struct ata_port *ap) 
     239{ 
     240        /* Nothing to do. */ 
     241} 
     242 
     243static struct ata_port_operations magicbox_cf_port_ops = { 
     244        .inherits               = &ata_sff_port_ops, 
     245 
     246        .cable_detect           = ata_cable_40wire, 
     247        .set_mode               = magicbox_cf_set_mode, 
     248 
     249        .sff_exec_command       = magicbox_cf_exec_command, 
     250        .sff_check_status       = magicbox_cf_check_status, 
     251        .sff_check_altstatus    = magicbox_cf_check_altstatus, 
     252        .sff_dev_select         = magicbox_cf_dev_select, 
     253        .sff_tf_load            = magicbox_cf_tf_load, 
     254        .sff_tf_read            = magicbox_cf_tf_read, 
     255        .sff_data_xfer          = magicbox_cf_data_xfer, 
     256 
     257        .sff_irq_on             = magicbox_cf_irq_on, 
     258        .sff_irq_clear          = magicbox_cf_irq_clear, 
     259 
     260        .port_start             = ATA_OP_NULL, 
     261}; 
     262 
     263static struct scsi_host_template magicbox_cf_sht = { 
     264        ATA_PIO_SHT(DRV_NAME), 
     265}; 
     266 
     267static inline void magicbox_cf_setup_port(struct ata_host *host) 
     268{ 
     269        struct magicbox_cf_info *info = host->private_data; 
     270        struct ata_port *ap; 
     271 
     272        ap = host->ports[0]; 
     273 
     274        ap->ops = &magicbox_cf_port_ops; 
     275        ap->pio_mask = ATA_PIO4; 
     276        ap->flags |= ATA_FLAG_MMIO | ATA_FLAG_NO_LEGACY | ATA_FLAG_NO_ATAPI; 
     277 
     278        ap->ioaddr.cmd_addr = info->base + MAGICBOX_CF_REG_CMD; 
     279        ap->ioaddr.data_addr = info->base + MAGICBOX_CF_REG_DATA; 
     280        ap->ioaddr.error_addr = info->base + MAGICBOX_CF_REG_ERR; 
     281        ap->ioaddr.feature_addr = info->base + MAGICBOX_CF_REG_FEATURE; 
     282        ap->ioaddr.nsect_addr = info->base + MAGICBOX_CF_REG_NSECT; 
     283        ap->ioaddr.lbal_addr = info->base + MAGICBOX_CF_REG_LBAL; 
     284        ap->ioaddr.lbam_addr = info->base + MAGICBOX_CF_REG_LBAM; 
     285        ap->ioaddr.lbah_addr = info->base + MAGICBOX_CF_REG_LBAH; 
     286        ap->ioaddr.device_addr = info->base + MAGICBOX_CF_REG_DEVICE; 
     287        ap->ioaddr.status_addr = info->base + MAGICBOX_CF_REG_STATUS; 
     288        ap->ioaddr.command_addr = info->base + MAGICBOX_CF_REG_CMD; 
     289 
     290        ap->ioaddr.altstatus_addr = info->ctrl + MAGICBOX_CF_REG_ALTSTATUS; 
     291        ap->ioaddr.ctl_addr = info->ctrl + MAGICBOX_CF_REG_CTL; 
     292 
     293        ata_port_desc(ap, "cmd 0x%p ctl 0x%p", ap->ioaddr.cmd_addr, 
     294                      ap->ioaddr.ctl_addr); 
     295} 
     296 
     297static int __devinit magicbox_cf_of_probe(struct of_device *op, 
     298                                           const struct of_device_id *match) 
     299{ 
     300        struct magicbox_cf_info *info; 
     301        struct ata_host *host; 
     302        int irq; 
     303        int ret = 0; 
     304 
     305        info = kzalloc(sizeof(struct magicbox_cf_info), GFP_KERNEL); 
     306        if (info == NULL) { 
     307                ret = -ENOMEM; 
     308                goto err_exit; 
     309        } 
     310 
     311        irq = irq_of_parse_and_map(op->node, 0); 
     312        if (irq < 0) { 
     313                dev_err(&op->dev, "invalid irq\n"); 
     314                ret = -EINVAL; 
     315                goto err_free_info; 
     316        } 
     317 
     318        info->base = of_iomap(op->node, 0); 
     319        if (info->base == NULL) { 
     320                ret = -ENOMEM; 
     321                goto err_free_info; 
     322        } 
     323 
     324        info->ctrl = of_iomap(op->node, 1); 
     325        if (info->ctrl == NULL) { 
     326                ret = -ENOMEM; 
     327                goto err_unmap_base; 
     328        } 
     329 
     330        host = ata_host_alloc(&op->dev, MAGICBOX_CF_MAXPORTS); 
     331        if (host == NULL) { 
     332                ret = -ENOMEM; 
     333                goto err_unmap_ctrl; 
     334        } 
     335 
     336        host->private_data = info; 
     337        magicbox_cf_setup_port(host); 
     338 
     339        ret = ata_host_activate(host, irq, ata_sff_interrupt, 
     340                                IRQF_TRIGGER_RISING, &magicbox_cf_sht); 
     341        if (ret) 
     342                goto err_unmap_ctrl; 
     343 
     344        dev_set_drvdata(&op->dev, host); 
     345        return 0; 
     346 
     347 err_unmap_ctrl: 
     348        iounmap(info->ctrl); 
     349 err_unmap_base: 
     350        iounmap(info->base); 
     351 err_free_info: 
     352        kfree(info); 
     353 err_exit: 
     354        return ret; 
     355} 
     356 
     357static __devexit int magicbox_cf_of_remove(struct of_device *op) 
     358{ 
     359        struct ata_host *host = dev_get_drvdata(&op->dev); 
     360        struct magicbox_cf_info *info = host->private_data; 
     361 
     362        ata_host_detach(host); 
     363        iounmap(info->ctrl); 
     364        iounmap(info->base); 
     365        kfree(info); 
     366 
     367        return 0; 
     368} 
     369 
     370static struct of_device_id magicbox_cf_of_match[] = { 
     371        { .compatible = "pata-magicbox-cf", }, 
     372        {}, 
     373}; 
     374 
     375static struct of_platform_driver magicbox_cf_of_platform_driver = { 
     376        .owner          = THIS_MODULE, 
     377        .name           = DRV_NAME, 
     378        .match_table    = magicbox_cf_of_match, 
     379        .probe          = magicbox_cf_of_probe, 
     380        .remove         = __devexit_p(magicbox_cf_of_remove), 
     381        .driver         = { 
     382                .name   = DRV_NAME, 
     383                .owner  = THIS_MODULE, 
     384        }, 
     385}; 
     386 
     387static int __init magicbox_cf_init(void) 
     388{ 
     389        return of_register_platform_driver(&magicbox_cf_of_platform_driver); 
     390} 
     391 
     392static void __exit magicbox_cf_exit(void) 
     393{ 
     394        of_unregister_platform_driver(&magicbox_cf_of_platform_driver); 
     395} 
     396 
     397module_init(magicbox_cf_init); 
     398module_exit(magicbox_cf_exit); 
     399 
     400MODULE_DESCRIPTION(DRV_DESC); 
     401MODULE_AUTHOR("Gabor Juhos <juhosg@openwrt.org>"); 
     402MODULE_LICENSE("GPL v2"); 
     403MODULE_VERSION(DRV_VERSION); 
     404MODULE_DEVICE_TABLE(of, magicbox_cf_of_match); 
Note: See TracBrowser for help on using the repository browser.