1/* $Id: telespci.c,v 1.1.1.1 2007/08/03 18:52:36 Exp $ 2 * 3 * low level stuff for Teles PCI isdn cards 4 * 5 * Author Ton van Rosmalen 6 * Karsten Keil 7 * Copyright by Ton van Rosmalen 8 * by Karsten Keil <keil@isdn4linux.de> 9 * 10 * This software may be used and distributed according to the terms 11 * of the GNU General Public License, incorporated herein by reference. 12 * 13 */ 14 15#include <linux/init.h> 16#include "hisax.h" 17#include "isac.h" 18#include "hscx.h" 19#include "isdnl1.h" 20#include <linux/pci.h> 21 22extern const char *CardType[]; 23static const char *telespci_revision = "$Revision: 1.1.1.1 $"; 24 25#define ZORAN_PO_RQ_PEN 0x02000000 26#define ZORAN_PO_WR 0x00800000 27#define ZORAN_PO_GID0 0x00000000 28#define ZORAN_PO_GID1 0x00100000 29#define ZORAN_PO_GREG0 0x00000000 30#define ZORAN_PO_GREG1 0x00010000 31#define ZORAN_PO_DMASK 0xFF 32 33#define WRITE_ADDR_ISAC (ZORAN_PO_WR | ZORAN_PO_GID0 | ZORAN_PO_GREG0) 34#define READ_DATA_ISAC (ZORAN_PO_GID0 | ZORAN_PO_GREG1) 35#define WRITE_DATA_ISAC (ZORAN_PO_WR | ZORAN_PO_GID0 | ZORAN_PO_GREG1) 36#define WRITE_ADDR_HSCX (ZORAN_PO_WR | ZORAN_PO_GID1 | ZORAN_PO_GREG0) 37#define READ_DATA_HSCX (ZORAN_PO_GID1 | ZORAN_PO_GREG1) 38#define WRITE_DATA_HSCX (ZORAN_PO_WR | ZORAN_PO_GID1 | ZORAN_PO_GREG1) 39 40#define ZORAN_WAIT_NOBUSY do { \ 41 portdata = readl(adr + 0x200); \ 42 } while (portdata & ZORAN_PO_RQ_PEN) 43 44static inline u_char 45readisac(void __iomem *adr, u_char off) 46{ 47 register unsigned int portdata; 48 49 ZORAN_WAIT_NOBUSY; 50 51 /* set address for ISAC */ 52 writel(WRITE_ADDR_ISAC | off, adr + 0x200); 53 ZORAN_WAIT_NOBUSY; 54 55 /* read data from ISAC */ 56 writel(READ_DATA_ISAC, adr + 0x200); 57 ZORAN_WAIT_NOBUSY; 58 return((u_char)(portdata & ZORAN_PO_DMASK)); 59} 60 61static inline void 62writeisac(void __iomem *adr, u_char off, u_char data) 63{ 64 register unsigned int portdata; 65 66 ZORAN_WAIT_NOBUSY; 67 68 /* set address for ISAC */ 69 writel(WRITE_ADDR_ISAC | off, adr + 0x200); 70 ZORAN_WAIT_NOBUSY; 71 72 /* write data to ISAC */ 73 writel(WRITE_DATA_ISAC | data, adr + 0x200); 74 ZORAN_WAIT_NOBUSY; 75} 76 77static inline u_char 78readhscx(void __iomem *adr, int hscx, u_char off) 79{ 80 register unsigned int portdata; 81 82 ZORAN_WAIT_NOBUSY; 83 /* set address for HSCX */ 84 writel(WRITE_ADDR_HSCX | ((hscx ? 0x40:0) + off), adr + 0x200); 85 ZORAN_WAIT_NOBUSY; 86 87 /* read data from HSCX */ 88 writel(READ_DATA_HSCX, adr + 0x200); 89 ZORAN_WAIT_NOBUSY; 90 return ((u_char)(portdata & ZORAN_PO_DMASK)); 91} 92 93static inline void 94writehscx(void __iomem *adr, int hscx, u_char off, u_char data) 95{ 96 register unsigned int portdata; 97 98 ZORAN_WAIT_NOBUSY; 99 /* set address for HSCX */ 100 writel(WRITE_ADDR_HSCX | ((hscx ? 0x40:0) + off), adr + 0x200); 101 ZORAN_WAIT_NOBUSY; 102 103 /* write data to HSCX */ 104 writel(WRITE_DATA_HSCX | data, adr + 0x200); 105 ZORAN_WAIT_NOBUSY; 106} 107 108static inline void 109read_fifo_isac(void __iomem *adr, u_char * data, int size) 110{ 111 register unsigned int portdata; 112 register int i; 113 114 ZORAN_WAIT_NOBUSY; 115 /* read data from ISAC */ 116 for (i = 0; i < size; i++) { 117 /* set address for ISAC fifo */ 118 writel(WRITE_ADDR_ISAC | 0x1E, adr + 0x200); 119 ZORAN_WAIT_NOBUSY; 120 writel(READ_DATA_ISAC, adr + 0x200); 121 ZORAN_WAIT_NOBUSY; 122 data[i] = (u_char)(portdata & ZORAN_PO_DMASK); 123 } 124} 125 126static void 127write_fifo_isac(void __iomem *adr, u_char * data, int size) 128{ 129 register unsigned int portdata; 130 register int i; 131 132 ZORAN_WAIT_NOBUSY; 133 /* write data to ISAC */ 134 for (i = 0; i < size; i++) { 135 /* set address for ISAC fifo */ 136 writel(WRITE_ADDR_ISAC | 0x1E, adr + 0x200); 137 ZORAN_WAIT_NOBUSY; 138 writel(WRITE_DATA_ISAC | data[i], adr + 0x200); 139 ZORAN_WAIT_NOBUSY; 140 } 141} 142 143static inline void 144read_fifo_hscx(void __iomem *adr, int hscx, u_char * data, int size) 145{ 146 register unsigned int portdata; 147 register int i; 148 149 ZORAN_WAIT_NOBUSY; 150 /* read data from HSCX */ 151 for (i = 0; i < size; i++) { 152 /* set address for HSCX fifo */ 153 writel(WRITE_ADDR_HSCX |(hscx ? 0x5F:0x1F), adr + 0x200); 154 ZORAN_WAIT_NOBUSY; 155 writel(READ_DATA_HSCX, adr + 0x200); 156 ZORAN_WAIT_NOBUSY; 157 data[i] = (u_char) (portdata & ZORAN_PO_DMASK); 158 } 159} 160 161static inline void 162write_fifo_hscx(void __iomem *adr, int hscx, u_char * data, int size) 163{ 164 unsigned int portdata; 165 register int i; 166 167 ZORAN_WAIT_NOBUSY; 168 /* write data to HSCX */ 169 for (i = 0; i < size; i++) { 170 /* set address for HSCX fifo */ 171 writel(WRITE_ADDR_HSCX |(hscx ? 0x5F:0x1F), adr + 0x200); 172 ZORAN_WAIT_NOBUSY; 173 writel(WRITE_DATA_HSCX | data[i], adr + 0x200); 174 ZORAN_WAIT_NOBUSY; 175 udelay(10); 176 } 177} 178 179/* Interface functions */ 180 181static u_char 182ReadISAC(struct IsdnCardState *cs, u_char offset) 183{ 184 return (readisac(cs->hw.teles0.membase, offset)); 185} 186 187static void 188WriteISAC(struct IsdnCardState *cs, u_char offset, u_char value) 189{ 190 writeisac(cs->hw.teles0.membase, offset, value); 191} 192 193static void 194ReadISACfifo(struct IsdnCardState *cs, u_char * data, int size) 195{ 196 read_fifo_isac(cs->hw.teles0.membase, data, size); 197} 198 199static void 200WriteISACfifo(struct IsdnCardState *cs, u_char * data, int size) 201{ 202 write_fifo_isac(cs->hw.teles0.membase, data, size); 203} 204 205static u_char 206ReadHSCX(struct IsdnCardState *cs, int hscx, u_char offset) 207{ 208 return (readhscx(cs->hw.teles0.membase, hscx, offset)); 209} 210 211static void 212WriteHSCX(struct IsdnCardState *cs, int hscx, u_char offset, u_char value) 213{ 214 writehscx(cs->hw.teles0.membase, hscx, offset, value); 215} 216 217/* 218 * fast interrupt HSCX stuff goes here 219 */ 220 221#define READHSCX(cs, nr, reg) readhscx(cs->hw.teles0.membase, nr, reg) 222#define WRITEHSCX(cs, nr, reg, data) writehscx(cs->hw.teles0.membase, nr, reg, data) 223#define READHSCXFIFO(cs, nr, ptr, cnt) read_fifo_hscx(cs->hw.teles0.membase, nr, ptr, cnt) 224#define WRITEHSCXFIFO(cs, nr, ptr, cnt) write_fifo_hscx(cs->hw.teles0.membase, nr, ptr, cnt) 225 226#include "hscx_irq.c" 227 228static irqreturn_t 229telespci_interrupt(int intno, void *dev_id) 230{ 231 struct IsdnCardState *cs = dev_id; 232 u_char hval, ival; 233 u_long flags; 234 235 spin_lock_irqsave(&cs->lock, flags); 236 hval = readhscx(cs->hw.teles0.membase, 1, HSCX_ISTA); 237 if (hval) 238 hscx_int_main(cs, hval); 239 ival = readisac(cs->hw.teles0.membase, ISAC_ISTA); 240 if ((hval | ival) == 0) { 241 spin_unlock_irqrestore(&cs->lock, flags); 242 return IRQ_NONE; 243 } 244 if (ival) 245 isac_interrupt(cs, ival); 246 /* Clear interrupt register for Zoran PCI controller */ 247 writel(0x70000000, cs->hw.teles0.membase + 0x3C); 248 249 writehscx(cs->hw.teles0.membase, 0, HSCX_MASK, 0xFF); 250 writehscx(cs->hw.teles0.membase, 1, HSCX_MASK, 0xFF); 251 writeisac(cs->hw.teles0.membase, ISAC_MASK, 0xFF); 252 writeisac(cs->hw.teles0.membase, ISAC_MASK, 0x0); 253 writehscx(cs->hw.teles0.membase, 0, HSCX_MASK, 0x0); 254 writehscx(cs->hw.teles0.membase, 1, HSCX_MASK, 0x0); 255 spin_unlock_irqrestore(&cs->lock, flags); 256 return IRQ_HANDLED; 257} 258 259static void 260release_io_telespci(struct IsdnCardState *cs) 261{ 262 iounmap(cs->hw.teles0.membase); 263} 264 265static int 266TelesPCI_card_msg(struct IsdnCardState *cs, int mt, void *arg) 267{ 268 u_long flags; 269 270 switch (mt) { 271 case CARD_RESET: 272 return(0); 273 case CARD_RELEASE: 274 release_io_telespci(cs); 275 return(0); 276 case CARD_INIT: 277 spin_lock_irqsave(&cs->lock, flags); 278 inithscxisac(cs, 3); 279 spin_unlock_irqrestore(&cs->lock, flags); 280 return(0); 281 case CARD_TEST: 282 return(0); 283 } 284 return(0); 285} 286 287static struct pci_dev *dev_tel __devinitdata = NULL; 288 289int __devinit 290setup_telespci(struct IsdnCard *card) 291{ 292 struct IsdnCardState *cs = card->cs; 293 char tmp[64]; 294 295#ifdef __BIG_ENDIAN 296#error "not running on big endian machines now" 297#endif 298 strcpy(tmp, telespci_revision); 299 printk(KERN_INFO "HiSax: Teles/PCI driver Rev. %s\n", HiSax_getrev(tmp)); 300 if (cs->typ != ISDN_CTYPE_TELESPCI) 301 return (0); 302#ifdef CONFIG_PCI 303 if ((dev_tel = pci_find_device (PCI_VENDOR_ID_ZORAN, PCI_DEVICE_ID_ZORAN_36120, dev_tel))) { 304 if (pci_enable_device(dev_tel)) 305 return(0); 306 cs->irq = dev_tel->irq; 307 if (!cs->irq) { 308 printk(KERN_WARNING "Teles: No IRQ for PCI card found\n"); 309 return(0); 310 } 311 cs->hw.teles0.membase = ioremap(pci_resource_start(dev_tel, 0), 312 PAGE_SIZE); 313 printk(KERN_INFO "Found: Zoran, base-address: 0x%llx, irq: 0x%x\n", 314 (unsigned long long)pci_resource_start(dev_tel, 0), 315 dev_tel->irq); 316 } else { 317 printk(KERN_WARNING "TelesPCI: No PCI card found\n"); 318 return(0); 319 } 320#else 321 printk(KERN_WARNING "HiSax: Teles/PCI and NO_PCI_BIOS\n"); 322 printk(KERN_WARNING "HiSax: Teles/PCI unable to config\n"); 323 return (0); 324#endif /* CONFIG_PCI */ 325 326 /* Initialize Zoran PCI controller */ 327 writel(0x00000000, cs->hw.teles0.membase + 0x28); 328 writel(0x01000000, cs->hw.teles0.membase + 0x28); 329 writel(0x01000000, cs->hw.teles0.membase + 0x28); 330 writel(0x7BFFFFFF, cs->hw.teles0.membase + 0x2C); 331 writel(0x70000000, cs->hw.teles0.membase + 0x3C); 332 writel(0x61000000, cs->hw.teles0.membase + 0x40); 333 /* writel(0x00800000, cs->hw.teles0.membase + 0x200); */ 334 335 printk(KERN_INFO 336 "HiSax: %s config irq:%d mem:%p\n", 337 CardType[cs->typ], cs->irq, 338 cs->hw.teles0.membase); 339 340 setup_isac(cs); 341 cs->readisac = &ReadISAC; 342 cs->writeisac = &WriteISAC; 343 cs->readisacfifo = &ReadISACfifo; 344 cs->writeisacfifo = &WriteISACfifo; 345 cs->BC_Read_Reg = &ReadHSCX; 346 cs->BC_Write_Reg = &WriteHSCX; 347 cs->BC_Send_Data = &hscx_fill_fifo; 348 cs->cardmsg = &TelesPCI_card_msg; 349 cs->irq_func = &telespci_interrupt; 350 cs->irq_flags |= IRQF_SHARED; 351 ISACVersion(cs, "TelesPCI:"); 352 if (HscxVersion(cs, "TelesPCI:")) { 353 printk(KERN_WARNING 354 "TelesPCI: wrong HSCX versions check IO/MEM addresses\n"); 355 release_io_telespci(cs); 356 return (0); 357 } 358 return (1); 359} 360