home *** CD-ROM | disk | FTP | other *** search
/ Mac Easy 2010 May / Mac Life Ubuntu.iso / casper / filesystem.squashfs / usr / src / linux-headers-2.6.28-15 / arch / sparc / include / asm / parport.h < prev    next >
Encoding:
C/C++ Source or Header  |  2008-12-24  |  5.6 KB  |  248 lines

  1. /* parport.h: sparc64 specific parport initialization and dma.
  2.  *
  3.  * Copyright (C) 1999  Eddie C. Dost  (ecd@skynet.be)
  4.  */
  5.  
  6. #ifndef _ASM_SPARC64_PARPORT_H
  7. #define _ASM_SPARC64_PARPORT_H 1
  8.  
  9. #include <linux/of_device.h>
  10.  
  11. #include <asm/ebus_dma.h>
  12. #include <asm/ns87303.h>
  13. #include <asm/prom.h>
  14.  
  15. #define PARPORT_PC_MAX_PORTS    PARPORT_MAX
  16.  
  17. /*
  18.  * While sparc64 doesn't have an ISA DMA API, we provide something that looks
  19.  * close enough to make parport_pc happy
  20.  */
  21. #define HAS_DMA
  22.  
  23. static DEFINE_SPINLOCK(dma_spin_lock);
  24.  
  25. #define claim_dma_lock() \
  26. ({    unsigned long flags; \
  27.     spin_lock_irqsave(&dma_spin_lock, flags); \
  28.     flags; \
  29. })
  30.  
  31. #define release_dma_lock(__flags) \
  32.     spin_unlock_irqrestore(&dma_spin_lock, __flags);
  33.  
  34. static struct sparc_ebus_info {
  35.     struct ebus_dma_info info;
  36.     unsigned int addr;
  37.     unsigned int count;
  38.     int lock;
  39.  
  40.     struct parport *port;
  41. } sparc_ebus_dmas[PARPORT_PC_MAX_PORTS];
  42.  
  43. static DECLARE_BITMAP(dma_slot_map, PARPORT_PC_MAX_PORTS);
  44.  
  45. static inline int request_dma(unsigned int dmanr, const char *device_id)
  46. {
  47.     if (dmanr >= PARPORT_PC_MAX_PORTS)
  48.         return -EINVAL;
  49.     if (xchg(&sparc_ebus_dmas[dmanr].lock, 1) != 0)
  50.         return -EBUSY;
  51.     return 0;
  52. }
  53.  
  54. static inline void free_dma(unsigned int dmanr)
  55. {
  56.     if (dmanr >= PARPORT_PC_MAX_PORTS) {
  57.         printk(KERN_WARNING "Trying to free DMA%d\n", dmanr);
  58.         return;
  59.     }
  60.     if (xchg(&sparc_ebus_dmas[dmanr].lock, 0) == 0) {
  61.         printk(KERN_WARNING "Trying to free free DMA%d\n", dmanr);
  62.         return;
  63.     }
  64. }
  65.  
  66. static inline void enable_dma(unsigned int dmanr)
  67. {
  68.     ebus_dma_enable(&sparc_ebus_dmas[dmanr].info, 1);
  69.  
  70.     if (ebus_dma_request(&sparc_ebus_dmas[dmanr].info,
  71.                  sparc_ebus_dmas[dmanr].addr,
  72.                  sparc_ebus_dmas[dmanr].count))
  73.         BUG();
  74. }
  75.  
  76. static inline void disable_dma(unsigned int dmanr)
  77. {
  78.     ebus_dma_enable(&sparc_ebus_dmas[dmanr].info, 0);
  79. }
  80.  
  81. static inline void clear_dma_ff(unsigned int dmanr)
  82. {
  83.     /* nothing */
  84. }
  85.  
  86. static inline void set_dma_mode(unsigned int dmanr, char mode)
  87. {
  88.     ebus_dma_prepare(&sparc_ebus_dmas[dmanr].info, (mode != DMA_MODE_WRITE));
  89. }
  90.  
  91. static inline void set_dma_addr(unsigned int dmanr, unsigned int addr)
  92. {
  93.     sparc_ebus_dmas[dmanr].addr = addr;
  94. }
  95.  
  96. static inline void set_dma_count(unsigned int dmanr, unsigned int count)
  97. {
  98.     sparc_ebus_dmas[dmanr].count = count;
  99. }
  100.  
  101. static inline unsigned int get_dma_residue(unsigned int dmanr)
  102. {
  103.     return ebus_dma_residue(&sparc_ebus_dmas[dmanr].info);
  104. }
  105.  
  106. static int __devinit ecpp_probe(struct of_device *op, const struct of_device_id *match)
  107. {
  108.     unsigned long base = op->resource[0].start;
  109.     unsigned long config = op->resource[1].start;
  110.     unsigned long d_base = op->resource[2].start;
  111.     unsigned long d_len;
  112.     struct device_node *parent;
  113.     struct parport *p;
  114.     int slot, err;
  115.  
  116.     parent = op->node->parent;
  117.     if (!strcmp(parent->name, "dma")) {
  118.         p = parport_pc_probe_port(base, base + 0x400,
  119.                       op->irqs[0], PARPORT_DMA_NOFIFO,
  120.                       op->dev.parent->parent);
  121.         if (!p)
  122.             return -ENOMEM;
  123.         dev_set_drvdata(&op->dev, p);
  124.         return 0;
  125.     }
  126.  
  127.     for (slot = 0; slot < PARPORT_PC_MAX_PORTS; slot++) {
  128.         if (!test_and_set_bit(slot, dma_slot_map))
  129.             break;
  130.     }
  131.     err = -ENODEV;
  132.     if (slot >= PARPORT_PC_MAX_PORTS)
  133.         goto out_err;
  134.  
  135.     spin_lock_init(&sparc_ebus_dmas[slot].info.lock);
  136.  
  137.     d_len = (op->resource[2].end - d_base) + 1UL;
  138.     sparc_ebus_dmas[slot].info.regs =
  139.         of_ioremap(&op->resource[2], 0, d_len, "ECPP DMA");
  140.  
  141.     if (!sparc_ebus_dmas[slot].info.regs)
  142.         goto out_clear_map;
  143.  
  144.     sparc_ebus_dmas[slot].info.flags = 0;
  145.     sparc_ebus_dmas[slot].info.callback = NULL;
  146.     sparc_ebus_dmas[slot].info.client_cookie = NULL;
  147.     sparc_ebus_dmas[slot].info.irq = 0xdeadbeef;
  148.     strcpy(sparc_ebus_dmas[slot].info.name, "parport");
  149.     if (ebus_dma_register(&sparc_ebus_dmas[slot].info))
  150.         goto out_unmap_regs;
  151.  
  152.     ebus_dma_irq_enable(&sparc_ebus_dmas[slot].info, 1);
  153.  
  154.     /* Configure IRQ to Push Pull, Level Low */
  155.     /* Enable ECP, set bit 2 of the CTR first */
  156.     outb(0x04, base + 0x02);
  157.     ns87303_modify(config, PCR,
  158.                PCR_EPP_ENABLE |
  159.                PCR_IRQ_ODRAIN,
  160.                PCR_ECP_ENABLE |
  161.                PCR_ECP_CLK_ENA |
  162.                PCR_IRQ_POLAR);
  163.  
  164.     /* CTR bit 5 controls direction of port */
  165.     ns87303_modify(config, PTR,
  166.                0, PTR_LPT_REG_DIR);
  167.  
  168.     p = parport_pc_probe_port(base, base + 0x400,
  169.                   op->irqs[0],
  170.                   slot,
  171.                   op->dev.parent);
  172.     err = -ENOMEM;
  173.     if (!p)
  174.         goto out_disable_irq;
  175.  
  176.     dev_set_drvdata(&op->dev, p);
  177.  
  178.     return 0;
  179.  
  180. out_disable_irq:
  181.     ebus_dma_irq_enable(&sparc_ebus_dmas[slot].info, 0);
  182.     ebus_dma_unregister(&sparc_ebus_dmas[slot].info);
  183.  
  184. out_unmap_regs:
  185.     of_iounmap(&op->resource[2], sparc_ebus_dmas[slot].info.regs, d_len);
  186.  
  187. out_clear_map:
  188.     clear_bit(slot, dma_slot_map);
  189.  
  190. out_err:
  191.     return err;
  192. }
  193.  
  194. static int __devexit ecpp_remove(struct of_device *op)
  195. {
  196.     struct parport *p = dev_get_drvdata(&op->dev);
  197.     int slot = p->dma;
  198.  
  199.     parport_pc_unregister_port(p);
  200.  
  201.     if (slot != PARPORT_DMA_NOFIFO) {
  202.         unsigned long d_base = op->resource[2].start;
  203.         unsigned long d_len;
  204.  
  205.         d_len = (op->resource[2].end - d_base) + 1UL;
  206.  
  207.         ebus_dma_irq_enable(&sparc_ebus_dmas[slot].info, 0);
  208.         ebus_dma_unregister(&sparc_ebus_dmas[slot].info);
  209.         of_iounmap(&op->resource[2],
  210.                sparc_ebus_dmas[slot].info.regs,
  211.                d_len);
  212.         clear_bit(slot, dma_slot_map);
  213.     }
  214.  
  215.     return 0;
  216. }
  217.  
  218. static const struct of_device_id ecpp_match[] = {
  219.     {
  220.         .name = "ecpp",
  221.     },
  222.     {
  223.         .name = "parallel",
  224.         .compatible = "ecpp",
  225.     },
  226.     {
  227.         .name = "parallel",
  228.         .compatible = "ns87317-ecpp",
  229.     },
  230.     {},
  231. };
  232.  
  233. static struct of_platform_driver ecpp_driver = {
  234.     .name            = "ecpp",
  235.     .match_table        = ecpp_match,
  236.     .probe            = ecpp_probe,
  237.     .remove            = __devexit_p(ecpp_remove),
  238. };
  239.  
  240. static int parport_pc_find_nonpci_ports(int autoirq, int autodma)
  241. {
  242.     of_register_driver(&ecpp_driver, &of_bus_type);
  243.  
  244.     return 0;
  245. }
  246.  
  247. #endif /* !(_ASM_SPARC64_PARPORT_H */
  248.