root/drivers/ide/icside.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. icside_irqenable_arcin_v5
  2. icside_irqdisable_arcin_v5
  3. icside_irqenable_arcin_v6
  4. icside_irqdisable_arcin_v6
  5. icside_irqpending_arcin_v6
  6. icside_maskproc
  7. icside_set_dma_mode
  8. icside_dma_host_set
  9. icside_dma_end
  10. icside_dma_start
  11. icside_dma_setup
  12. icside_dma_test_irq
  13. icside_dma_init
  14. icside_dma_off_init
  15. icside_setup_ports
  16. icside_register_v5
  17. icside_register_v6
  18. icside_probe
  19. icside_remove
  20. icside_shutdown
  21. icside_init
  22. icside_exit

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * Copyright (c) 1996-2004 Russell King.
   4  *
   5  * Please note that this platform does not support 32-bit IDE IO.
   6  */
   7 
   8 #include <linux/string.h>
   9 #include <linux/module.h>
  10 #include <linux/ioport.h>
  11 #include <linux/slab.h>
  12 #include <linux/blkdev.h>
  13 #include <linux/errno.h>
  14 #include <linux/ide.h>
  15 #include <linux/dma-mapping.h>
  16 #include <linux/device.h>
  17 #include <linux/init.h>
  18 #include <linux/scatterlist.h>
  19 #include <linux/io.h>
  20 
  21 #include <asm/dma.h>
  22 #include <asm/ecard.h>
  23 
  24 #define DRV_NAME "icside"
  25 
  26 #define ICS_IDENT_OFFSET                0x2280
  27 
  28 #define ICS_ARCIN_V5_INTRSTAT           0x0000
  29 #define ICS_ARCIN_V5_INTROFFSET         0x0004
  30 #define ICS_ARCIN_V5_IDEOFFSET          0x2800
  31 #define ICS_ARCIN_V5_IDEALTOFFSET       0x2b80
  32 #define ICS_ARCIN_V5_IDESTEPPING        6
  33 
  34 #define ICS_ARCIN_V6_IDEOFFSET_1        0x2000
  35 #define ICS_ARCIN_V6_INTROFFSET_1       0x2200
  36 #define ICS_ARCIN_V6_INTRSTAT_1         0x2290
  37 #define ICS_ARCIN_V6_IDEALTOFFSET_1     0x2380
  38 #define ICS_ARCIN_V6_IDEOFFSET_2        0x3000
  39 #define ICS_ARCIN_V6_INTROFFSET_2       0x3200
  40 #define ICS_ARCIN_V6_INTRSTAT_2         0x3290
  41 #define ICS_ARCIN_V6_IDEALTOFFSET_2     0x3380
  42 #define ICS_ARCIN_V6_IDESTEPPING        6
  43 
  44 struct cardinfo {
  45         unsigned int dataoffset;
  46         unsigned int ctrloffset;
  47         unsigned int stepping;
  48 };
  49 
  50 static struct cardinfo icside_cardinfo_v5 = {
  51         .dataoffset     = ICS_ARCIN_V5_IDEOFFSET,
  52         .ctrloffset     = ICS_ARCIN_V5_IDEALTOFFSET,
  53         .stepping       = ICS_ARCIN_V5_IDESTEPPING,
  54 };
  55 
  56 static struct cardinfo icside_cardinfo_v6_1 = {
  57         .dataoffset     = ICS_ARCIN_V6_IDEOFFSET_1,
  58         .ctrloffset     = ICS_ARCIN_V6_IDEALTOFFSET_1,
  59         .stepping       = ICS_ARCIN_V6_IDESTEPPING,
  60 };
  61 
  62 static struct cardinfo icside_cardinfo_v6_2 = {
  63         .dataoffset     = ICS_ARCIN_V6_IDEOFFSET_2,
  64         .ctrloffset     = ICS_ARCIN_V6_IDEALTOFFSET_2,
  65         .stepping       = ICS_ARCIN_V6_IDESTEPPING,
  66 };
  67 
  68 struct icside_state {
  69         unsigned int channel;
  70         unsigned int enabled;
  71         void __iomem *irq_port;
  72         void __iomem *ioc_base;
  73         unsigned int sel;
  74         unsigned int type;
  75         struct ide_host *host;
  76 };
  77 
  78 #define ICS_TYPE_A3IN   0
  79 #define ICS_TYPE_A3USER 1
  80 #define ICS_TYPE_V6     3
  81 #define ICS_TYPE_V5     15
  82 #define ICS_TYPE_NOTYPE ((unsigned int)-1)
  83 
  84 /* ---------------- Version 5 PCB Support Functions --------------------- */
  85 /* Prototype: icside_irqenable_arcin_v5 (struct expansion_card *ec, int irqnr)
  86  * Purpose  : enable interrupts from card
  87  */
  88 static void icside_irqenable_arcin_v5 (struct expansion_card *ec, int irqnr)
  89 {
  90         struct icside_state *state = ec->irq_data;
  91 
  92         writeb(0, state->irq_port + ICS_ARCIN_V5_INTROFFSET);
  93 }
  94 
  95 /* Prototype: icside_irqdisable_arcin_v5 (struct expansion_card *ec, int irqnr)
  96  * Purpose  : disable interrupts from card
  97  */
  98 static void icside_irqdisable_arcin_v5 (struct expansion_card *ec, int irqnr)
  99 {
 100         struct icside_state *state = ec->irq_data;
 101 
 102         readb(state->irq_port + ICS_ARCIN_V5_INTROFFSET);
 103 }
 104 
 105 static const expansioncard_ops_t icside_ops_arcin_v5 = {
 106         .irqenable      = icside_irqenable_arcin_v5,
 107         .irqdisable     = icside_irqdisable_arcin_v5,
 108 };
 109 
 110 
 111 /* ---------------- Version 6 PCB Support Functions --------------------- */
 112 /* Prototype: icside_irqenable_arcin_v6 (struct expansion_card *ec, int irqnr)
 113  * Purpose  : enable interrupts from card
 114  */
 115 static void icside_irqenable_arcin_v6 (struct expansion_card *ec, int irqnr)
 116 {
 117         struct icside_state *state = ec->irq_data;
 118         void __iomem *base = state->irq_port;
 119 
 120         state->enabled = 1;
 121 
 122         switch (state->channel) {
 123         case 0:
 124                 writeb(0, base + ICS_ARCIN_V6_INTROFFSET_1);
 125                 readb(base + ICS_ARCIN_V6_INTROFFSET_2);
 126                 break;
 127         case 1:
 128                 writeb(0, base + ICS_ARCIN_V6_INTROFFSET_2);
 129                 readb(base + ICS_ARCIN_V6_INTROFFSET_1);
 130                 break;
 131         }
 132 }
 133 
 134 /* Prototype: icside_irqdisable_arcin_v6 (struct expansion_card *ec, int irqnr)
 135  * Purpose  : disable interrupts from card
 136  */
 137 static void icside_irqdisable_arcin_v6 (struct expansion_card *ec, int irqnr)
 138 {
 139         struct icside_state *state = ec->irq_data;
 140 
 141         state->enabled = 0;
 142 
 143         readb(state->irq_port + ICS_ARCIN_V6_INTROFFSET_1);
 144         readb(state->irq_port + ICS_ARCIN_V6_INTROFFSET_2);
 145 }
 146 
 147 /* Prototype: icside_irqprobe(struct expansion_card *ec)
 148  * Purpose  : detect an active interrupt from card
 149  */
 150 static int icside_irqpending_arcin_v6(struct expansion_card *ec)
 151 {
 152         struct icside_state *state = ec->irq_data;
 153 
 154         return readb(state->irq_port + ICS_ARCIN_V6_INTRSTAT_1) & 1 ||
 155                readb(state->irq_port + ICS_ARCIN_V6_INTRSTAT_2) & 1;
 156 }
 157 
 158 static const expansioncard_ops_t icside_ops_arcin_v6 = {
 159         .irqenable      = icside_irqenable_arcin_v6,
 160         .irqdisable     = icside_irqdisable_arcin_v6,
 161         .irqpending     = icside_irqpending_arcin_v6,
 162 };
 163 
 164 /*
 165  * Handle routing of interrupts.  This is called before
 166  * we write the command to the drive.
 167  */
 168 static void icside_maskproc(ide_drive_t *drive, int mask)
 169 {
 170         ide_hwif_t *hwif = drive->hwif;
 171         struct expansion_card *ec = ECARD_DEV(hwif->dev);
 172         struct icside_state *state = ecard_get_drvdata(ec);
 173         unsigned long flags;
 174 
 175         local_irq_save(flags);
 176 
 177         state->channel = hwif->channel;
 178 
 179         if (state->enabled && !mask) {
 180                 switch (hwif->channel) {
 181                 case 0:
 182                         writeb(0, state->irq_port + ICS_ARCIN_V6_INTROFFSET_1);
 183                         readb(state->irq_port + ICS_ARCIN_V6_INTROFFSET_2);
 184                         break;
 185                 case 1:
 186                         writeb(0, state->irq_port + ICS_ARCIN_V6_INTROFFSET_2);
 187                         readb(state->irq_port + ICS_ARCIN_V6_INTROFFSET_1);
 188                         break;
 189                 }
 190         } else {
 191                 readb(state->irq_port + ICS_ARCIN_V6_INTROFFSET_2);
 192                 readb(state->irq_port + ICS_ARCIN_V6_INTROFFSET_1);
 193         }
 194 
 195         local_irq_restore(flags);
 196 }
 197 
 198 static const struct ide_port_ops icside_v6_no_dma_port_ops = {
 199         .maskproc               = icside_maskproc,
 200 };
 201 
 202 #ifdef CONFIG_BLK_DEV_IDEDMA_ICS
 203 /*
 204  * SG-DMA support.
 205  *
 206  * Similar to the BM-DMA, but we use the RiscPCs IOMD DMA controllers.
 207  * There is only one DMA controller per card, which means that only
 208  * one drive can be accessed at one time.  NOTE! We do not enforce that
 209  * here, but we rely on the main IDE driver spotting that both
 210  * interfaces use the same IRQ, which should guarantee this.
 211  */
 212 
 213 /*
 214  * Configure the IOMD to give the appropriate timings for the transfer
 215  * mode being requested.  We take the advice of the ATA standards, and
 216  * calculate the cycle time based on the transfer mode, and the EIDE
 217  * MW DMA specs that the drive provides in the IDENTIFY command.
 218  *
 219  * We have the following IOMD DMA modes to choose from:
 220  *
 221  *      Type    Active          Recovery        Cycle
 222  *      A       250 (250)       312 (550)       562 (800)
 223  *      B       187             250             437
 224  *      C       125 (125)       125 (375)       250 (500)
 225  *      D       62              125             187
 226  *
 227  * (figures in brackets are actual measured timings)
 228  *
 229  * However, we also need to take care of the read/write active and
 230  * recovery timings:
 231  *
 232  *                      Read    Write
 233  *      Mode    Active  -- Recovery --  Cycle   IOMD type
 234  *      MW0     215     50      215     480     A
 235  *      MW1     80      50      50      150     C
 236  *      MW2     70      25      25      120     C
 237  */
 238 static void icside_set_dma_mode(ide_hwif_t *hwif, ide_drive_t *drive)
 239 {
 240         unsigned long cycle_time = 0;
 241         int use_dma_info = 0;
 242         const u8 xfer_mode = drive->dma_mode;
 243 
 244         switch (xfer_mode) {
 245         case XFER_MW_DMA_2:
 246                 cycle_time = 250;
 247                 use_dma_info = 1;
 248                 break;
 249 
 250         case XFER_MW_DMA_1:
 251                 cycle_time = 250;
 252                 use_dma_info = 1;
 253                 break;
 254 
 255         case XFER_MW_DMA_0:
 256                 cycle_time = 480;
 257                 break;
 258 
 259         case XFER_SW_DMA_2:
 260         case XFER_SW_DMA_1:
 261         case XFER_SW_DMA_0:
 262                 cycle_time = 480;
 263                 break;
 264         }
 265 
 266         /*
 267          * If we're going to be doing MW_DMA_1 or MW_DMA_2, we should
 268          * take care to note the values in the ID...
 269          */
 270         if (use_dma_info && drive->id[ATA_ID_EIDE_DMA_TIME] > cycle_time)
 271                 cycle_time = drive->id[ATA_ID_EIDE_DMA_TIME];
 272 
 273         ide_set_drivedata(drive, (void *)cycle_time);
 274 
 275         printk(KERN_INFO "%s: %s selected (peak %luMB/s)\n",
 276                drive->name, ide_xfer_verbose(xfer_mode),
 277                2000 / (cycle_time ? cycle_time : (unsigned long) -1));
 278 }
 279 
 280 static const struct ide_port_ops icside_v6_port_ops = {
 281         .set_dma_mode           = icside_set_dma_mode,
 282         .maskproc               = icside_maskproc,
 283 };
 284 
 285 static void icside_dma_host_set(ide_drive_t *drive, int on)
 286 {
 287 }
 288 
 289 static int icside_dma_end(ide_drive_t *drive)
 290 {
 291         ide_hwif_t *hwif = drive->hwif;
 292         struct expansion_card *ec = ECARD_DEV(hwif->dev);
 293 
 294         disable_dma(ec->dma);
 295 
 296         return get_dma_residue(ec->dma) != 0;
 297 }
 298 
 299 static void icside_dma_start(ide_drive_t *drive)
 300 {
 301         ide_hwif_t *hwif = drive->hwif;
 302         struct expansion_card *ec = ECARD_DEV(hwif->dev);
 303 
 304         /* We can not enable DMA on both channels simultaneously. */
 305         BUG_ON(dma_channel_active(ec->dma));
 306         enable_dma(ec->dma);
 307 }
 308 
 309 static int icside_dma_setup(ide_drive_t *drive, struct ide_cmd *cmd)
 310 {
 311         ide_hwif_t *hwif = drive->hwif;
 312         struct expansion_card *ec = ECARD_DEV(hwif->dev);
 313         struct icside_state *state = ecard_get_drvdata(ec);
 314         unsigned int dma_mode;
 315 
 316         if (cmd->tf_flags & IDE_TFLAG_WRITE)
 317                 dma_mode = DMA_MODE_WRITE;
 318         else
 319                 dma_mode = DMA_MODE_READ;
 320 
 321         /*
 322          * We can not enable DMA on both channels.
 323          */
 324         BUG_ON(dma_channel_active(ec->dma));
 325 
 326         /*
 327          * Ensure that we have the right interrupt routed.
 328          */
 329         icside_maskproc(drive, 0);
 330 
 331         /*
 332          * Route the DMA signals to the correct interface.
 333          */
 334         writeb(state->sel | hwif->channel, state->ioc_base);
 335 
 336         /*
 337          * Select the correct timing for this drive.
 338          */
 339         set_dma_speed(ec->dma, (unsigned long)ide_get_drivedata(drive));
 340 
 341         /*
 342          * Tell the DMA engine about the SG table and
 343          * data direction.
 344          */
 345         set_dma_sg(ec->dma, hwif->sg_table, cmd->sg_nents);
 346         set_dma_mode(ec->dma, dma_mode);
 347 
 348         return 0;
 349 }
 350 
 351 static int icside_dma_test_irq(ide_drive_t *drive)
 352 {
 353         ide_hwif_t *hwif = drive->hwif;
 354         struct expansion_card *ec = ECARD_DEV(hwif->dev);
 355         struct icside_state *state = ecard_get_drvdata(ec);
 356 
 357         return readb(state->irq_port +
 358                      (hwif->channel ?
 359                         ICS_ARCIN_V6_INTRSTAT_2 :
 360                         ICS_ARCIN_V6_INTRSTAT_1)) & 1;
 361 }
 362 
 363 static int icside_dma_init(ide_hwif_t *hwif, const struct ide_port_info *d)
 364 {
 365         hwif->dmatable_cpu      = NULL;
 366         hwif->dmatable_dma      = 0;
 367 
 368         return 0;
 369 }
 370 
 371 static const struct ide_dma_ops icside_v6_dma_ops = {
 372         .dma_host_set           = icside_dma_host_set,
 373         .dma_setup              = icside_dma_setup,
 374         .dma_start              = icside_dma_start,
 375         .dma_end                = icside_dma_end,
 376         .dma_test_irq           = icside_dma_test_irq,
 377         .dma_lost_irq           = ide_dma_lost_irq,
 378 };
 379 #endif
 380 
 381 static int icside_dma_off_init(ide_hwif_t *hwif, const struct ide_port_info *d)
 382 {
 383         return -EOPNOTSUPP;
 384 }
 385 
 386 static void icside_setup_ports(struct ide_hw *hw, void __iomem *base,
 387                                struct cardinfo *info, struct expansion_card *ec)
 388 {
 389         unsigned long port = (unsigned long)base + info->dataoffset;
 390 
 391         hw->io_ports.data_addr   = port;
 392         hw->io_ports.error_addr  = port + (1 << info->stepping);
 393         hw->io_ports.nsect_addr  = port + (2 << info->stepping);
 394         hw->io_ports.lbal_addr   = port + (3 << info->stepping);
 395         hw->io_ports.lbam_addr   = port + (4 << info->stepping);
 396         hw->io_ports.lbah_addr   = port + (5 << info->stepping);
 397         hw->io_ports.device_addr = port + (6 << info->stepping);
 398         hw->io_ports.status_addr = port + (7 << info->stepping);
 399         hw->io_ports.ctl_addr    = (unsigned long)base + info->ctrloffset;
 400 
 401         hw->irq = ec->irq;
 402         hw->dev = &ec->dev;
 403 }
 404 
 405 static const struct ide_port_info icside_v5_port_info = {
 406         .host_flags             = IDE_HFLAG_NO_DMA,
 407         .chipset                = ide_acorn,
 408 };
 409 
 410 static int icside_register_v5(struct icside_state *state,
 411                               struct expansion_card *ec)
 412 {
 413         void __iomem *base;
 414         struct ide_host *host;
 415         struct ide_hw hw, *hws[] = { &hw };
 416         int ret;
 417 
 418         base = ecardm_iomap(ec, ECARD_RES_MEMC, 0, 0);
 419         if (!base)
 420                 return -ENOMEM;
 421 
 422         state->irq_port = base;
 423 
 424         ec->irqaddr  = base + ICS_ARCIN_V5_INTRSTAT;
 425         ec->irqmask  = 1;
 426 
 427         ecard_setirq(ec, &icside_ops_arcin_v5, state);
 428 
 429         /*
 430          * Be on the safe side - disable interrupts
 431          */
 432         icside_irqdisable_arcin_v5(ec, 0);
 433 
 434         icside_setup_ports(&hw, base, &icside_cardinfo_v5, ec);
 435 
 436         host = ide_host_alloc(&icside_v5_port_info, hws, 1);
 437         if (host == NULL)
 438                 return -ENODEV;
 439 
 440         state->host = host;
 441 
 442         ecard_set_drvdata(ec, state);
 443 
 444         ret = ide_host_register(host, &icside_v5_port_info, hws);
 445         if (ret)
 446                 goto err_free;
 447 
 448         return 0;
 449 err_free:
 450         ide_host_free(host);
 451         ecard_set_drvdata(ec, NULL);
 452         return ret;
 453 }
 454 
 455 static const struct ide_port_info icside_v6_port_info = {
 456         .init_dma               = icside_dma_off_init,
 457         .port_ops               = &icside_v6_no_dma_port_ops,
 458         .host_flags             = IDE_HFLAG_SERIALIZE | IDE_HFLAG_MMIO,
 459         .mwdma_mask             = ATA_MWDMA2,
 460         .swdma_mask             = ATA_SWDMA2,
 461         .chipset                = ide_acorn,
 462 };
 463 
 464 static int icside_register_v6(struct icside_state *state,
 465                               struct expansion_card *ec)
 466 {
 467         void __iomem *ioc_base, *easi_base;
 468         struct ide_host *host;
 469         unsigned int sel = 0;
 470         int ret;
 471         struct ide_hw hw[2], *hws[] = { &hw[0], &hw[1] };
 472         struct ide_port_info d = icside_v6_port_info;
 473 
 474         ioc_base = ecardm_iomap(ec, ECARD_RES_IOCFAST, 0, 0);
 475         if (!ioc_base) {
 476                 ret = -ENOMEM;
 477                 goto out;
 478         }
 479 
 480         easi_base = ioc_base;
 481 
 482         if (ecard_resource_flags(ec, ECARD_RES_EASI)) {
 483                 easi_base = ecardm_iomap(ec, ECARD_RES_EASI, 0, 0);
 484                 if (!easi_base) {
 485                         ret = -ENOMEM;
 486                         goto out;
 487                 }
 488 
 489                 /*
 490                  * Enable access to the EASI region.
 491                  */
 492                 sel = 1 << 5;
 493         }
 494 
 495         writeb(sel, ioc_base);
 496 
 497         ecard_setirq(ec, &icside_ops_arcin_v6, state);
 498 
 499         state->irq_port   = easi_base;
 500         state->ioc_base   = ioc_base;
 501         state->sel        = sel;
 502 
 503         /*
 504          * Be on the safe side - disable interrupts
 505          */
 506         icside_irqdisable_arcin_v6(ec, 0);
 507 
 508         icside_setup_ports(&hw[0], easi_base, &icside_cardinfo_v6_1, ec);
 509         icside_setup_ports(&hw[1], easi_base, &icside_cardinfo_v6_2, ec);
 510 
 511         host = ide_host_alloc(&d, hws, 2);
 512         if (host == NULL)
 513                 return -ENODEV;
 514 
 515         state->host = host;
 516 
 517         ecard_set_drvdata(ec, state);
 518 
 519 #ifdef CONFIG_BLK_DEV_IDEDMA_ICS
 520         if (ec->dma != NO_DMA && !request_dma(ec->dma, DRV_NAME)) {
 521                 d.init_dma = icside_dma_init;
 522                 d.port_ops = &icside_v6_port_ops;
 523                 d.dma_ops  = &icside_v6_dma_ops;
 524         }
 525 #endif
 526 
 527         ret = ide_host_register(host, &d, hws);
 528         if (ret)
 529                 goto err_free;
 530 
 531         return 0;
 532 err_free:
 533         ide_host_free(host);
 534         if (d.dma_ops)
 535                 free_dma(ec->dma);
 536         ecard_set_drvdata(ec, NULL);
 537 out:
 538         return ret;
 539 }
 540 
 541 static int icside_probe(struct expansion_card *ec, const struct ecard_id *id)
 542 {
 543         struct icside_state *state;
 544         void __iomem *idmem;
 545         int ret;
 546 
 547         ret = ecard_request_resources(ec);
 548         if (ret)
 549                 goto out;
 550 
 551         state = kzalloc(sizeof(struct icside_state), GFP_KERNEL);
 552         if (!state) {
 553                 ret = -ENOMEM;
 554                 goto release;
 555         }
 556 
 557         state->type     = ICS_TYPE_NOTYPE;
 558 
 559         idmem = ecardm_iomap(ec, ECARD_RES_IOCFAST, 0, 0);
 560         if (idmem) {
 561                 unsigned int type;
 562 
 563                 type = readb(idmem + ICS_IDENT_OFFSET) & 1;
 564                 type |= (readb(idmem + ICS_IDENT_OFFSET + 4) & 1) << 1;
 565                 type |= (readb(idmem + ICS_IDENT_OFFSET + 8) & 1) << 2;
 566                 type |= (readb(idmem + ICS_IDENT_OFFSET + 12) & 1) << 3;
 567                 ecardm_iounmap(ec, idmem);
 568 
 569                 state->type = type;
 570         }
 571 
 572         switch (state->type) {
 573         case ICS_TYPE_A3IN:
 574                 dev_warn(&ec->dev, "A3IN unsupported\n");
 575                 ret = -ENODEV;
 576                 break;
 577 
 578         case ICS_TYPE_A3USER:
 579                 dev_warn(&ec->dev, "A3USER unsupported\n");
 580                 ret = -ENODEV;
 581                 break;
 582 
 583         case ICS_TYPE_V5:
 584                 ret = icside_register_v5(state, ec);
 585                 break;
 586 
 587         case ICS_TYPE_V6:
 588                 ret = icside_register_v6(state, ec);
 589                 break;
 590 
 591         default:
 592                 dev_warn(&ec->dev, "unknown interface type\n");
 593                 ret = -ENODEV;
 594                 break;
 595         }
 596 
 597         if (ret == 0)
 598                 goto out;
 599 
 600         kfree(state);
 601  release:
 602         ecard_release_resources(ec);
 603  out:
 604         return ret;
 605 }
 606 
 607 static void icside_remove(struct expansion_card *ec)
 608 {
 609         struct icside_state *state = ecard_get_drvdata(ec);
 610 
 611         switch (state->type) {
 612         case ICS_TYPE_V5:
 613                 /* FIXME: tell IDE to stop using the interface */
 614 
 615                 /* Disable interrupts */
 616                 icside_irqdisable_arcin_v5(ec, 0);
 617                 break;
 618 
 619         case ICS_TYPE_V6:
 620                 /* FIXME: tell IDE to stop using the interface */
 621                 if (ec->dma != NO_DMA)
 622                         free_dma(ec->dma);
 623 
 624                 /* Disable interrupts */
 625                 icside_irqdisable_arcin_v6(ec, 0);
 626 
 627                 /* Reset the ROM pointer/EASI selection */
 628                 writeb(0, state->ioc_base);
 629                 break;
 630         }
 631 
 632         ecard_set_drvdata(ec, NULL);
 633 
 634         kfree(state);
 635         ecard_release_resources(ec);
 636 }
 637 
 638 static void icside_shutdown(struct expansion_card *ec)
 639 {
 640         struct icside_state *state = ecard_get_drvdata(ec);
 641         unsigned long flags;
 642 
 643         /*
 644          * Disable interrupts from this card.  We need to do
 645          * this before disabling EASI since we may be accessing
 646          * this register via that region.
 647          */
 648         local_irq_save(flags);
 649         ec->ops->irqdisable(ec, 0);
 650         local_irq_restore(flags);
 651 
 652         /*
 653          * Reset the ROM pointer so that we can read the ROM
 654          * after a soft reboot.  This also disables access to
 655          * the IDE taskfile via the EASI region.
 656          */
 657         if (state->ioc_base)
 658                 writeb(0, state->ioc_base);
 659 }
 660 
 661 static const struct ecard_id icside_ids[] = {
 662         { MANU_ICS,  PROD_ICS_IDE  },
 663         { MANU_ICS2, PROD_ICS2_IDE },
 664         { 0xffff, 0xffff }
 665 };
 666 
 667 static struct ecard_driver icside_driver = {
 668         .probe          = icside_probe,
 669         .remove         = icside_remove,
 670         .shutdown       = icside_shutdown,
 671         .id_table       = icside_ids,
 672         .drv = {
 673                 .name   = "icside",
 674         },
 675 };
 676 
 677 static int __init icside_init(void)
 678 {
 679         return ecard_register_driver(&icside_driver);
 680 }
 681 
 682 static void __exit icside_exit(void)
 683 {
 684         ecard_remove_driver(&icside_driver);
 685 }
 686 
 687 MODULE_AUTHOR("Russell King <rmk@arm.linux.org.uk>");
 688 MODULE_LICENSE("GPL");
 689 MODULE_DESCRIPTION("ICS IDE driver");
 690 
 691 module_init(icside_init);
 692 module_exit(icside_exit);

/* [<][>][^][v][top][bottom][index][help] */