1/* $Id: parport.h,v 1.1.1.1 2007/08/03 18:53:36 Exp $ 2 * parport.h: sparc64 specific parport initialization and dma. 3 * 4 * Copyright (C) 1999 Eddie C. Dost (ecd@skynet.be) 5 */ 6 7#ifndef _ASM_SPARC64_PARPORT_H 8#define _ASM_SPARC64_PARPORT_H 1 9 10#include <asm/ebus.h> 11#include <asm/isa.h> 12#include <asm/ns87303.h> 13 14#define PARPORT_PC_MAX_PORTS PARPORT_MAX 15 16/* 17 * While sparc64 doesn't have an ISA DMA API, we provide something that looks 18 * close enough to make parport_pc happy 19 */ 20#define HAS_DMA 21 22static DEFINE_SPINLOCK(dma_spin_lock); 23 24#define claim_dma_lock() \ 25({ unsigned long flags; \ 26 spin_lock_irqsave(&dma_spin_lock, flags); \ 27 flags; \ 28}) 29 30#define release_dma_lock(__flags) \ 31 spin_unlock_irqrestore(&dma_spin_lock, __flags); 32 33static struct sparc_ebus_info { 34 struct ebus_dma_info info; 35 unsigned int addr; 36 unsigned int count; 37 int lock; 38} sparc_ebus_dmas[PARPORT_PC_MAX_PORTS]; 39 40static __inline__ int request_dma(unsigned int dmanr, const char *device_id) 41{ 42 if (dmanr >= PARPORT_PC_MAX_PORTS) 43 return -EINVAL; 44 if (xchg(&sparc_ebus_dmas[dmanr].lock, 1) != 0) 45 return -EBUSY; 46 return 0; 47} 48 49static __inline__ void free_dma(unsigned int dmanr) 50{ 51 if (dmanr >= PARPORT_PC_MAX_PORTS) { 52 printk(KERN_WARNING "Trying to free DMA%d\n", dmanr); 53 return; 54 } 55 if (xchg(&sparc_ebus_dmas[dmanr].lock, 0) == 0) { 56 printk(KERN_WARNING "Trying to free free DMA%d\n", dmanr); 57 return; 58 } 59} 60 61static __inline__ void enable_dma(unsigned int dmanr) 62{ 63 ebus_dma_enable(&sparc_ebus_dmas[dmanr].info, 1); 64 65 if (ebus_dma_request(&sparc_ebus_dmas[dmanr].info, 66 sparc_ebus_dmas[dmanr].addr, 67 sparc_ebus_dmas[dmanr].count)) 68 BUG(); 69} 70 71static __inline__ void disable_dma(unsigned int dmanr) 72{ 73 ebus_dma_enable(&sparc_ebus_dmas[dmanr].info, 0); 74} 75 76static __inline__ void clear_dma_ff(unsigned int dmanr) 77{ 78 /* nothing */ 79} 80 81static __inline__ void set_dma_mode(unsigned int dmanr, char mode) 82{ 83 ebus_dma_prepare(&sparc_ebus_dmas[dmanr].info, (mode != DMA_MODE_WRITE)); 84} 85 86static __inline__ void set_dma_addr(unsigned int dmanr, unsigned int addr) 87{ 88 sparc_ebus_dmas[dmanr].addr = addr; 89} 90 91static __inline__ void set_dma_count(unsigned int dmanr, unsigned int count) 92{ 93 sparc_ebus_dmas[dmanr].count = count; 94} 95 96static __inline__ unsigned int get_dma_residue(unsigned int dmanr) 97{ 98 return ebus_dma_residue(&sparc_ebus_dmas[dmanr].info); 99} 100 101static int ebus_ecpp_p(struct linux_ebus_device *edev) 102{ 103 if (!strcmp(edev->prom_node->name, "ecpp")) 104 return 1; 105 if (!strcmp(edev->prom_node->name, "parallel")) { 106 const char *compat; 107 108 compat = of_get_property(edev->prom_node, 109 "compatible", NULL); 110 if (compat && 111 (!strcmp(compat, "ecpp") || 112 !strcmp(compat, "ns87317-ecpp") || 113 !strcmp(compat + 13, "ecpp"))) 114 return 1; 115 } 116 return 0; 117} 118 119static int parport_isa_probe(int count) 120{ 121 struct sparc_isa_bridge *isa_br; 122 struct sparc_isa_device *isa_dev; 123 124 for_each_isa(isa_br) { 125 for_each_isadev(isa_dev, isa_br) { 126 struct sparc_isa_device *child; 127 unsigned long base; 128 129 if (strcmp(isa_dev->prom_node->name, "dma")) 130 continue; 131 132 child = isa_dev->child; 133 while (child) { 134 if (!strcmp(child->prom_node->name, "parallel")) 135 break; 136 child = child->next; 137 } 138 if (!child) 139 continue; 140 141 base = child->resource.start; 142 143 /* No DMA, see commentary in 144 * asm-sparc64/floppy.h:isa_floppy_init() 145 */ 146 if (parport_pc_probe_port(base, base + 0x400, 147 child->irq, PARPORT_DMA_NOFIFO, 148 &child->bus->self->dev)) 149 count++; 150 } 151 } 152 153 return count; 154} 155 156static int parport_pc_find_nonpci_ports (int autoirq, int autodma) 157{ 158 struct linux_ebus *ebus; 159 struct linux_ebus_device *edev; 160 int count = 0; 161 162 for_each_ebus(ebus) { 163 for_each_ebusdev(edev, ebus) { 164 if (ebus_ecpp_p(edev)) { 165 unsigned long base = edev->resource[0].start; 166 unsigned long config = edev->resource[1].start; 167 unsigned long d_base = edev->resource[2].start; 168 unsigned long d_len; 169 170 spin_lock_init(&sparc_ebus_dmas[count].info.lock); 171 d_len = (edev->resource[2].end - 172 d_base) + 1; 173 sparc_ebus_dmas[count].info.regs = 174 ioremap(d_base, d_len); 175 if (!sparc_ebus_dmas[count].info.regs) 176 continue; 177 sparc_ebus_dmas[count].info.flags = 0; 178 sparc_ebus_dmas[count].info.callback = NULL; 179 sparc_ebus_dmas[count].info.client_cookie = NULL; 180 sparc_ebus_dmas[count].info.irq = 0xdeadbeef; 181 strcpy(sparc_ebus_dmas[count].info.name, "parport"); 182 if (ebus_dma_register(&sparc_ebus_dmas[count].info)) 183 continue; 184 ebus_dma_irq_enable(&sparc_ebus_dmas[count].info, 1); 185 186 /* Configure IRQ to Push Pull, Level Low */ 187 /* Enable ECP, set bit 2 of the CTR first */ 188 outb(0x04, base + 0x02); 189 ns87303_modify(config, PCR, 190 PCR_EPP_ENABLE | 191 PCR_IRQ_ODRAIN, 192 PCR_ECP_ENABLE | 193 PCR_ECP_CLK_ENA | 194 PCR_IRQ_POLAR); 195 196 /* CTR bit 5 controls direction of port */ 197 ns87303_modify(config, PTR, 198 0, PTR_LPT_REG_DIR); 199 200 if (parport_pc_probe_port(base, base + 0x400, 201 edev->irqs[0], 202 count, 203 &ebus->self->dev)) 204 count++; 205 } 206 } 207 } 208 209 count = parport_isa_probe(count); 210 211 return count; 212} 213 214#endif /* !(_ASM_SPARC64_PARPORT_H */ 215