16e747b4bSRussell King /* 26e747b4bSRussell King * linux/arch/arm/kernel/ecard.c 36e747b4bSRussell King * 46e747b4bSRussell King * Copyright 1995-2001 Russell King 56e747b4bSRussell King * 66e747b4bSRussell King * This program is free software; you can redistribute it and/or modify 76e747b4bSRussell King * it under the terms of the GNU General Public License version 2 as 86e747b4bSRussell King * published by the Free Software Foundation. 96e747b4bSRussell King * 106e747b4bSRussell King * Find all installed expansion cards, and handle interrupts from them. 116e747b4bSRussell King * 126e747b4bSRussell King * Created from information from Acorns RiscOS3 PRMs 136e747b4bSRussell King * 146e747b4bSRussell King * 08-Dec-1996 RMK Added code for the 9'th expansion card - the ether 156e747b4bSRussell King * podule slot. 166e747b4bSRussell King * 06-May-1997 RMK Added blacklist for cards whose loader doesn't work. 176e747b4bSRussell King * 12-Sep-1997 RMK Created new handling of interrupt enables/disables 186e747b4bSRussell King * - cards can now register their own routine to control 196e747b4bSRussell King * interrupts (recommended). 206e747b4bSRussell King * 29-Sep-1997 RMK Expansion card interrupt hardware not being re-enabled 216e747b4bSRussell King * on reset from Linux. (Caused cards not to respond 226e747b4bSRussell King * under RiscOS without hard reset). 236e747b4bSRussell King * 15-Feb-1998 RMK Added DMA support 246e747b4bSRussell King * 12-Sep-1998 RMK Added EASI support 256e747b4bSRussell King * 10-Jan-1999 RMK Run loaders in a simulated RISC OS environment. 266e747b4bSRussell King * 17-Apr-1999 RMK Support for EASI Type C cycles. 276e747b4bSRussell King */ 286e747b4bSRussell King #define ECARD_C 296e747b4bSRussell King 306e747b4bSRussell King #include <linux/module.h> 316e747b4bSRussell King #include <linux/kernel.h> 326e747b4bSRussell King #include <linux/types.h> 336e747b4bSRussell King #include <linux/sched.h> 346e747b4bSRussell King #include <linux/interrupt.h> 356e747b4bSRussell King #include <linux/completion.h> 366e747b4bSRussell King #include <linux/reboot.h> 376e747b4bSRussell King #include <linux/mm.h> 386e747b4bSRussell King #include <linux/slab.h> 396e747b4bSRussell King #include <linux/proc_fs.h> 406e747b4bSRussell King #include <linux/seq_file.h> 416e747b4bSRussell King #include <linux/device.h> 426e747b4bSRussell King #include <linux/init.h> 436e747b4bSRussell King #include <linux/mutex.h> 446e747b4bSRussell King #include <linux/kthread.h> 45b4ac0849SRussell King #include <linux/irq.h> 466e747b4bSRussell King #include <linux/io.h> 476e747b4bSRussell King 486e747b4bSRussell King #include <asm/dma.h> 496e747b4bSRussell King #include <asm/ecard.h> 506e747b4bSRussell King #include <mach/hardware.h> 516e747b4bSRussell King #include <asm/irq.h> 526e747b4bSRussell King #include <asm/mmu_context.h> 536e747b4bSRussell King #include <asm/mach/irq.h> 546e747b4bSRussell King #include <asm/tlbflush.h> 556e747b4bSRussell King 566e747b4bSRussell King #include "ecard.h" 576e747b4bSRussell King 586e747b4bSRussell King struct ecard_request { 596e747b4bSRussell King void (*fn)(struct ecard_request *); 606e747b4bSRussell King ecard_t *ec; 616e747b4bSRussell King unsigned int address; 626e747b4bSRussell King unsigned int length; 636e747b4bSRussell King unsigned int use_loader; 646e747b4bSRussell King void *buffer; 656e747b4bSRussell King struct completion *complete; 666e747b4bSRussell King }; 676e747b4bSRussell King 686e747b4bSRussell King struct expcard_blacklist { 696e747b4bSRussell King unsigned short manufacturer; 706e747b4bSRussell King unsigned short product; 716e747b4bSRussell King const char *type; 726e747b4bSRussell King }; 736e747b4bSRussell King 746e747b4bSRussell King static ecard_t *cards; 756e747b4bSRussell King static ecard_t *slot_to_expcard[MAX_ECARDS]; 766e747b4bSRussell King static unsigned int ectcr; 776e747b4bSRussell King 786e747b4bSRussell King /* List of descriptions of cards which don't have an extended 796e747b4bSRussell King * identification, or chunk directories containing a description. 806e747b4bSRussell King */ 816e747b4bSRussell King static struct expcard_blacklist __initdata blacklist[] = { 826e747b4bSRussell King { MANU_ACORN, PROD_ACORN_ETHER1, "Acorn Ether1" } 836e747b4bSRussell King }; 846e747b4bSRussell King 856e747b4bSRussell King asmlinkage extern int 866e747b4bSRussell King ecard_loader_reset(unsigned long base, loader_t loader); 876e747b4bSRussell King asmlinkage extern int 886e747b4bSRussell King ecard_loader_read(int off, unsigned long base, loader_t loader); 896e747b4bSRussell King 906e747b4bSRussell King static inline unsigned short ecard_getu16(unsigned char *v) 916e747b4bSRussell King { 926e747b4bSRussell King return v[0] | v[1] << 8; 936e747b4bSRussell King } 946e747b4bSRussell King 956e747b4bSRussell King static inline signed long ecard_gets24(unsigned char *v) 966e747b4bSRussell King { 976e747b4bSRussell King return v[0] | v[1] << 8 | v[2] << 16 | ((v[2] & 0x80) ? 0xff000000 : 0); 986e747b4bSRussell King } 996e747b4bSRussell King 1006e747b4bSRussell King static inline ecard_t *slot_to_ecard(unsigned int slot) 1016e747b4bSRussell King { 1026e747b4bSRussell King return slot < MAX_ECARDS ? slot_to_expcard[slot] : NULL; 1036e747b4bSRussell King } 1046e747b4bSRussell King 1056e747b4bSRussell King /* ===================== Expansion card daemon ======================== */ 1066e747b4bSRussell King /* 1076e747b4bSRussell King * Since the loader programs on the expansion cards need to be run 1086e747b4bSRussell King * in a specific environment, create a separate task with this 1096e747b4bSRussell King * environment up, and pass requests to this task as and when we 1106e747b4bSRussell King * need to. 1116e747b4bSRussell King * 1126e747b4bSRussell King * This should allow 99% of loaders to be called from Linux. 1136e747b4bSRussell King * 1146e747b4bSRussell King * From a security standpoint, we trust the card vendors. This 1156e747b4bSRussell King * may be a misplaced trust. 1166e747b4bSRussell King */ 1176e747b4bSRussell King static void ecard_task_reset(struct ecard_request *req) 1186e747b4bSRussell King { 1196e747b4bSRussell King struct expansion_card *ec = req->ec; 1206e747b4bSRussell King struct resource *res; 1216e747b4bSRussell King 1226e747b4bSRussell King res = ec->slot_no == 8 1236e747b4bSRussell King ? &ec->resource[ECARD_RES_MEMC] 1246e747b4bSRussell King : ec->easi 1256e747b4bSRussell King ? &ec->resource[ECARD_RES_EASI] 1266e747b4bSRussell King : &ec->resource[ECARD_RES_IOCSYNC]; 1276e747b4bSRussell King 1286e747b4bSRussell King ecard_loader_reset(res->start, ec->loader); 1296e747b4bSRussell King } 1306e747b4bSRussell King 1316e747b4bSRussell King static void ecard_task_readbytes(struct ecard_request *req) 1326e747b4bSRussell King { 1336e747b4bSRussell King struct expansion_card *ec = req->ec; 1346e747b4bSRussell King unsigned char *buf = req->buffer; 1356e747b4bSRussell King unsigned int len = req->length; 1366e747b4bSRussell King unsigned int off = req->address; 1376e747b4bSRussell King 1386e747b4bSRussell King if (ec->slot_no == 8) { 1396e747b4bSRussell King void __iomem *base = (void __iomem *) 1406e747b4bSRussell King ec->resource[ECARD_RES_MEMC].start; 1416e747b4bSRussell King 1426e747b4bSRussell King /* 1436e747b4bSRussell King * The card maintains an index which increments the address 1446e747b4bSRussell King * into a 4096-byte page on each access. We need to keep 1456e747b4bSRussell King * track of the counter. 1466e747b4bSRussell King */ 1476e747b4bSRussell King static unsigned int index; 1486e747b4bSRussell King unsigned int page; 1496e747b4bSRussell King 1506e747b4bSRussell King page = (off >> 12) * 4; 1516e747b4bSRussell King if (page > 256 * 4) 1526e747b4bSRussell King return; 1536e747b4bSRussell King 1546e747b4bSRussell King off &= 4095; 1556e747b4bSRussell King 1566e747b4bSRussell King /* 1576e747b4bSRussell King * If we are reading offset 0, or our current index is 1586e747b4bSRussell King * greater than the offset, reset the hardware index counter. 1596e747b4bSRussell King */ 1606e747b4bSRussell King if (off == 0 || index > off) { 1616e747b4bSRussell King writeb(0, base); 1626e747b4bSRussell King index = 0; 1636e747b4bSRussell King } 1646e747b4bSRussell King 1656e747b4bSRussell King /* 1666e747b4bSRussell King * Increment the hardware index counter until we get to the 1676e747b4bSRussell King * required offset. The read bytes are discarded. 1686e747b4bSRussell King */ 1696e747b4bSRussell King while (index < off) { 1706e747b4bSRussell King readb(base + page); 1716e747b4bSRussell King index += 1; 1726e747b4bSRussell King } 1736e747b4bSRussell King 1746e747b4bSRussell King while (len--) { 1756e747b4bSRussell King *buf++ = readb(base + page); 1766e747b4bSRussell King index += 1; 1776e747b4bSRussell King } 1786e747b4bSRussell King } else { 1796e747b4bSRussell King unsigned long base = (ec->easi 1806e747b4bSRussell King ? &ec->resource[ECARD_RES_EASI] 1816e747b4bSRussell King : &ec->resource[ECARD_RES_IOCSYNC])->start; 1826e747b4bSRussell King void __iomem *pbase = (void __iomem *)base; 1836e747b4bSRussell King 1846e747b4bSRussell King if (!req->use_loader || !ec->loader) { 1856e747b4bSRussell King off *= 4; 1866e747b4bSRussell King while (len--) { 1876e747b4bSRussell King *buf++ = readb(pbase + off); 1886e747b4bSRussell King off += 4; 1896e747b4bSRussell King } 1906e747b4bSRussell King } else { 1916e747b4bSRussell King while(len--) { 1926e747b4bSRussell King /* 1936e747b4bSRussell King * The following is required by some 1946e747b4bSRussell King * expansion card loader programs. 1956e747b4bSRussell King */ 1966e747b4bSRussell King *(unsigned long *)0x108 = 0; 1976e747b4bSRussell King *buf++ = ecard_loader_read(off++, base, 1986e747b4bSRussell King ec->loader); 1996e747b4bSRussell King } 2006e747b4bSRussell King } 2016e747b4bSRussell King } 2026e747b4bSRussell King 2036e747b4bSRussell King } 2046e747b4bSRussell King 2056e747b4bSRussell King static DECLARE_WAIT_QUEUE_HEAD(ecard_wait); 2066e747b4bSRussell King static struct ecard_request *ecard_req; 2076e747b4bSRussell King static DEFINE_MUTEX(ecard_mutex); 2086e747b4bSRussell King 2096e747b4bSRussell King /* 2106e747b4bSRussell King * Set up the expansion card daemon's page tables. 2116e747b4bSRussell King */ 2126e747b4bSRussell King static void ecard_init_pgtables(struct mm_struct *mm) 2136e747b4bSRussell King { 2146e747b4bSRussell King struct vm_area_struct vma; 2156e747b4bSRussell King 2166e747b4bSRussell King /* We want to set up the page tables for the following mapping: 2176e747b4bSRussell King * Virtual Physical 2186e747b4bSRussell King * 0x03000000 0x03000000 2196e747b4bSRussell King * 0x03010000 unmapped 2206e747b4bSRussell King * 0x03210000 0x03210000 2216e747b4bSRussell King * 0x03400000 unmapped 2226e747b4bSRussell King * 0x08000000 0x08000000 2236e747b4bSRussell King * 0x10000000 unmapped 2246e747b4bSRussell King * 2256e747b4bSRussell King * FIXME: we don't follow this 100% yet. 2266e747b4bSRussell King */ 2276e747b4bSRussell King pgd_t *src_pgd, *dst_pgd; 2286e747b4bSRussell King 2296e747b4bSRussell King src_pgd = pgd_offset(mm, (unsigned long)IO_BASE); 2306e747b4bSRussell King dst_pgd = pgd_offset(mm, IO_START); 2316e747b4bSRussell King 2326e747b4bSRussell King memcpy(dst_pgd, src_pgd, sizeof(pgd_t) * (IO_SIZE / PGDIR_SIZE)); 2336e747b4bSRussell King 2346e747b4bSRussell King src_pgd = pgd_offset(mm, (unsigned long)EASI_BASE); 2356e747b4bSRussell King dst_pgd = pgd_offset(mm, EASI_START); 2366e747b4bSRussell King 2376e747b4bSRussell King memcpy(dst_pgd, src_pgd, sizeof(pgd_t) * (EASI_SIZE / PGDIR_SIZE)); 2386e747b4bSRussell King 2399e4db1c3SLinus Torvalds vma.vm_flags = VM_EXEC; 2406e747b4bSRussell King vma.vm_mm = mm; 2416e747b4bSRussell King 2426e747b4bSRussell King flush_tlb_range(&vma, IO_START, IO_START + IO_SIZE); 2436e747b4bSRussell King flush_tlb_range(&vma, EASI_START, EASI_START + EASI_SIZE); 2446e747b4bSRussell King } 2456e747b4bSRussell King 2466e747b4bSRussell King static int ecard_init_mm(void) 2476e747b4bSRussell King { 2486e747b4bSRussell King struct mm_struct * mm = mm_alloc(); 2496e747b4bSRussell King struct mm_struct *active_mm = current->active_mm; 2506e747b4bSRussell King 2516e747b4bSRussell King if (!mm) 2526e747b4bSRussell King return -ENOMEM; 2536e747b4bSRussell King 2546e747b4bSRussell King current->mm = mm; 2556e747b4bSRussell King current->active_mm = mm; 2566e747b4bSRussell King activate_mm(active_mm, mm); 2576e747b4bSRussell King mmdrop(active_mm); 2586e747b4bSRussell King ecard_init_pgtables(mm); 2596e747b4bSRussell King return 0; 2606e747b4bSRussell King } 2616e747b4bSRussell King 2626e747b4bSRussell King static int 2636e747b4bSRussell King ecard_task(void * unused) 2646e747b4bSRussell King { 2656e747b4bSRussell King /* 2666e747b4bSRussell King * Allocate a mm. We're not a lazy-TLB kernel task since we need 2676e747b4bSRussell King * to set page table entries where the user space would be. Note 2686e747b4bSRussell King * that this also creates the page tables. Failure is not an 2696e747b4bSRussell King * option here. 2706e747b4bSRussell King */ 2716e747b4bSRussell King if (ecard_init_mm()) 2726e747b4bSRussell King panic("kecardd: unable to alloc mm\n"); 2736e747b4bSRussell King 2746e747b4bSRussell King while (1) { 2756e747b4bSRussell King struct ecard_request *req; 2766e747b4bSRussell King 2776e747b4bSRussell King wait_event_interruptible(ecard_wait, ecard_req != NULL); 2786e747b4bSRussell King 2796e747b4bSRussell King req = xchg(&ecard_req, NULL); 2806e747b4bSRussell King if (req != NULL) { 2816e747b4bSRussell King req->fn(req); 2826e747b4bSRussell King complete(req->complete); 2836e747b4bSRussell King } 2846e747b4bSRussell King } 2856e747b4bSRussell King } 2866e747b4bSRussell King 2876e747b4bSRussell King /* 2886e747b4bSRussell King * Wake the expansion card daemon to action our request. 2896e747b4bSRussell King * 2906e747b4bSRussell King * FIXME: The test here is not sufficient to detect if the 2916e747b4bSRussell King * kcardd is running. 2926e747b4bSRussell King */ 2936e747b4bSRussell King static void ecard_call(struct ecard_request *req) 2946e747b4bSRussell King { 2956e747b4bSRussell King DECLARE_COMPLETION_ONSTACK(completion); 2966e747b4bSRussell King 2976e747b4bSRussell King req->complete = &completion; 2986e747b4bSRussell King 2996e747b4bSRussell King mutex_lock(&ecard_mutex); 3006e747b4bSRussell King ecard_req = req; 3016e747b4bSRussell King wake_up(&ecard_wait); 3026e747b4bSRussell King 3036e747b4bSRussell King /* 3046e747b4bSRussell King * Now wait for kecardd to run. 3056e747b4bSRussell King */ 3066e747b4bSRussell King wait_for_completion(&completion); 3076e747b4bSRussell King mutex_unlock(&ecard_mutex); 3086e747b4bSRussell King } 3096e747b4bSRussell King 3106e747b4bSRussell King /* ======================= Mid-level card control ===================== */ 3116e747b4bSRussell King 3126e747b4bSRussell King static void 3136e747b4bSRussell King ecard_readbytes(void *addr, ecard_t *ec, int off, int len, int useld) 3146e747b4bSRussell King { 3156e747b4bSRussell King struct ecard_request req; 3166e747b4bSRussell King 3176e747b4bSRussell King req.fn = ecard_task_readbytes; 3186e747b4bSRussell King req.ec = ec; 3196e747b4bSRussell King req.address = off; 3206e747b4bSRussell King req.length = len; 3216e747b4bSRussell King req.use_loader = useld; 3226e747b4bSRussell King req.buffer = addr; 3236e747b4bSRussell King 3246e747b4bSRussell King ecard_call(&req); 3256e747b4bSRussell King } 3266e747b4bSRussell King 3276e747b4bSRussell King int ecard_readchunk(struct in_chunk_dir *cd, ecard_t *ec, int id, int num) 3286e747b4bSRussell King { 3296e747b4bSRussell King struct ex_chunk_dir excd; 3306e747b4bSRussell King int index = 16; 3316e747b4bSRussell King int useld = 0; 3326e747b4bSRussell King 3336e747b4bSRussell King if (!ec->cid.cd) 3346e747b4bSRussell King return 0; 3356e747b4bSRussell King 3366e747b4bSRussell King while(1) { 3376e747b4bSRussell King ecard_readbytes(&excd, ec, index, 8, useld); 3386e747b4bSRussell King index += 8; 3396e747b4bSRussell King if (c_id(&excd) == 0) { 3406e747b4bSRussell King if (!useld && ec->loader) { 3416e747b4bSRussell King useld = 1; 3426e747b4bSRussell King index = 0; 3436e747b4bSRussell King continue; 3446e747b4bSRussell King } 3456e747b4bSRussell King return 0; 3466e747b4bSRussell King } 3476e747b4bSRussell King if (c_id(&excd) == 0xf0) { /* link */ 3486e747b4bSRussell King index = c_start(&excd); 3496e747b4bSRussell King continue; 3506e747b4bSRussell King } 3516e747b4bSRussell King if (c_id(&excd) == 0x80) { /* loader */ 3526e747b4bSRussell King if (!ec->loader) { 3536e747b4bSRussell King ec->loader = kmalloc(c_len(&excd), 3546e747b4bSRussell King GFP_KERNEL); 3556e747b4bSRussell King if (ec->loader) 3566e747b4bSRussell King ecard_readbytes(ec->loader, ec, 3576e747b4bSRussell King (int)c_start(&excd), 3586e747b4bSRussell King c_len(&excd), useld); 3596e747b4bSRussell King else 3606e747b4bSRussell King return 0; 3616e747b4bSRussell King } 3626e747b4bSRussell King continue; 3636e747b4bSRussell King } 3646e747b4bSRussell King if (c_id(&excd) == id && num-- == 0) 3656e747b4bSRussell King break; 3666e747b4bSRussell King } 3676e747b4bSRussell King 3686e747b4bSRussell King if (c_id(&excd) & 0x80) { 3696e747b4bSRussell King switch (c_id(&excd) & 0x70) { 3706e747b4bSRussell King case 0x70: 3716e747b4bSRussell King ecard_readbytes((unsigned char *)excd.d.string, ec, 3726e747b4bSRussell King (int)c_start(&excd), c_len(&excd), 3736e747b4bSRussell King useld); 3746e747b4bSRussell King break; 3756e747b4bSRussell King case 0x00: 3766e747b4bSRussell King break; 3776e747b4bSRussell King } 3786e747b4bSRussell King } 3796e747b4bSRussell King cd->start_offset = c_start(&excd); 3806e747b4bSRussell King memcpy(cd->d.string, excd.d.string, 256); 3816e747b4bSRussell King return 1; 3826e747b4bSRussell King } 3836e747b4bSRussell King 3846e747b4bSRussell King /* ======================= Interrupt control ============================ */ 3856e747b4bSRussell King 3866e747b4bSRussell King static void ecard_def_irq_enable(ecard_t *ec, int irqnr) 3876e747b4bSRussell King { 3886e747b4bSRussell King } 3896e747b4bSRussell King 3906e747b4bSRussell King static void ecard_def_irq_disable(ecard_t *ec, int irqnr) 3916e747b4bSRussell King { 3926e747b4bSRussell King } 3936e747b4bSRussell King 3946e747b4bSRussell King static int ecard_def_irq_pending(ecard_t *ec) 3956e747b4bSRussell King { 3966e747b4bSRussell King return !ec->irqmask || readb(ec->irqaddr) & ec->irqmask; 3976e747b4bSRussell King } 3986e747b4bSRussell King 3996e747b4bSRussell King static void ecard_def_fiq_enable(ecard_t *ec, int fiqnr) 4006e747b4bSRussell King { 4016e747b4bSRussell King panic("ecard_def_fiq_enable called - impossible"); 4026e747b4bSRussell King } 4036e747b4bSRussell King 4046e747b4bSRussell King static void ecard_def_fiq_disable(ecard_t *ec, int fiqnr) 4056e747b4bSRussell King { 4066e747b4bSRussell King panic("ecard_def_fiq_disable called - impossible"); 4076e747b4bSRussell King } 4086e747b4bSRussell King 4096e747b4bSRussell King static int ecard_def_fiq_pending(ecard_t *ec) 4106e747b4bSRussell King { 4116e747b4bSRussell King return !ec->fiqmask || readb(ec->fiqaddr) & ec->fiqmask; 4126e747b4bSRussell King } 4136e747b4bSRussell King 4146e747b4bSRussell King static expansioncard_ops_t ecard_default_ops = { 4156e747b4bSRussell King ecard_def_irq_enable, 4166e747b4bSRussell King ecard_def_irq_disable, 4176e747b4bSRussell King ecard_def_irq_pending, 4186e747b4bSRussell King ecard_def_fiq_enable, 4196e747b4bSRussell King ecard_def_fiq_disable, 4206e747b4bSRussell King ecard_def_fiq_pending 4216e747b4bSRussell King }; 4226e747b4bSRussell King 4236e747b4bSRussell King /* 4246e747b4bSRussell King * Enable and disable interrupts from expansion cards. 4256e747b4bSRussell King * (interrupts are disabled for these functions). 4266e747b4bSRussell King * 4276e747b4bSRussell King * They are not meant to be called directly, but via enable/disable_irq. 4286e747b4bSRussell King */ 4296e747b4bSRussell King static void ecard_irq_unmask(struct irq_data *d) 4306e747b4bSRussell King { 431c402c110SRussell King ecard_t *ec = irq_data_get_irq_chip_data(d); 4326e747b4bSRussell King 4336e747b4bSRussell King if (ec) { 4346e747b4bSRussell King if (!ec->ops) 4356e747b4bSRussell King ec->ops = &ecard_default_ops; 4366e747b4bSRussell King 4376e747b4bSRussell King if (ec->claimed && ec->ops->irqenable) 4386e747b4bSRussell King ec->ops->irqenable(ec, d->irq); 4396e747b4bSRussell King else 4406e747b4bSRussell King printk(KERN_ERR "ecard: rejecting request to " 4416e747b4bSRussell King "enable IRQs for %d\n", d->irq); 4426e747b4bSRussell King } 4436e747b4bSRussell King } 4446e747b4bSRussell King 4456e747b4bSRussell King static void ecard_irq_mask(struct irq_data *d) 4466e747b4bSRussell King { 447c402c110SRussell King ecard_t *ec = irq_data_get_irq_chip_data(d); 4486e747b4bSRussell King 4496e747b4bSRussell King if (ec) { 4506e747b4bSRussell King if (!ec->ops) 4516e747b4bSRussell King ec->ops = &ecard_default_ops; 4526e747b4bSRussell King 4536e747b4bSRussell King if (ec->ops && ec->ops->irqdisable) 4546e747b4bSRussell King ec->ops->irqdisable(ec, d->irq); 4556e747b4bSRussell King } 4566e747b4bSRussell King } 4576e747b4bSRussell King 4586e747b4bSRussell King static struct irq_chip ecard_chip = { 4596e747b4bSRussell King .name = "ECARD", 4606e747b4bSRussell King .irq_ack = ecard_irq_mask, 4616e747b4bSRussell King .irq_mask = ecard_irq_mask, 4626e747b4bSRussell King .irq_unmask = ecard_irq_unmask, 4636e747b4bSRussell King }; 4646e747b4bSRussell King 4656e747b4bSRussell King void ecard_enablefiq(unsigned int fiqnr) 4666e747b4bSRussell King { 4676e747b4bSRussell King ecard_t *ec = slot_to_ecard(fiqnr); 4686e747b4bSRussell King 4696e747b4bSRussell King if (ec) { 4706e747b4bSRussell King if (!ec->ops) 4716e747b4bSRussell King ec->ops = &ecard_default_ops; 4726e747b4bSRussell King 4736e747b4bSRussell King if (ec->claimed && ec->ops->fiqenable) 4746e747b4bSRussell King ec->ops->fiqenable(ec, fiqnr); 4756e747b4bSRussell King else 4766e747b4bSRussell King printk(KERN_ERR "ecard: rejecting request to " 4776e747b4bSRussell King "enable FIQs for %d\n", fiqnr); 4786e747b4bSRussell King } 4796e747b4bSRussell King } 4806e747b4bSRussell King 4816e747b4bSRussell King void ecard_disablefiq(unsigned int fiqnr) 4826e747b4bSRussell King { 4836e747b4bSRussell King ecard_t *ec = slot_to_ecard(fiqnr); 4846e747b4bSRussell King 4856e747b4bSRussell King if (ec) { 4866e747b4bSRussell King if (!ec->ops) 4876e747b4bSRussell King ec->ops = &ecard_default_ops; 4886e747b4bSRussell King 4896e747b4bSRussell King if (ec->ops->fiqdisable) 4906e747b4bSRussell King ec->ops->fiqdisable(ec, fiqnr); 4916e747b4bSRussell King } 4926e747b4bSRussell King } 4936e747b4bSRussell King 4946e747b4bSRussell King static void ecard_dump_irq_state(void) 4956e747b4bSRussell King { 4966e747b4bSRussell King ecard_t *ec; 4976e747b4bSRussell King 4986e747b4bSRussell King printk("Expansion card IRQ state:\n"); 4996e747b4bSRussell King 5006e747b4bSRussell King for (ec = cards; ec; ec = ec->next) { 5016e747b4bSRussell King if (ec->slot_no == 8) 5026e747b4bSRussell King continue; 5036e747b4bSRussell King 5046e747b4bSRussell King printk(" %d: %sclaimed, ", 5056e747b4bSRussell King ec->slot_no, ec->claimed ? "" : "not "); 5066e747b4bSRussell King 5076e747b4bSRussell King if (ec->ops && ec->ops->irqpending && 5086e747b4bSRussell King ec->ops != &ecard_default_ops) 5096e747b4bSRussell King printk("irq %spending\n", 5106e747b4bSRussell King ec->ops->irqpending(ec) ? "" : "not "); 5116e747b4bSRussell King else 5126e747b4bSRussell King printk("irqaddr %p, mask = %02X, status = %02X\n", 5136e747b4bSRussell King ec->irqaddr, ec->irqmask, readb(ec->irqaddr)); 5146e747b4bSRussell King } 5156e747b4bSRussell King } 5166e747b4bSRussell King 5176e747b4bSRussell King static void ecard_check_lockup(struct irq_desc *desc) 5186e747b4bSRussell King { 5196e747b4bSRussell King static unsigned long last; 5206e747b4bSRussell King static int lockup; 5216e747b4bSRussell King 5226e747b4bSRussell King /* 5236e747b4bSRussell King * If the timer interrupt has not run since the last million 5246e747b4bSRussell King * unrecognised expansion card interrupts, then there is 5256e747b4bSRussell King * something seriously wrong. Disable the expansion card 5266e747b4bSRussell King * interrupts so at least we can continue. 5276e747b4bSRussell King * 5286e747b4bSRussell King * Maybe we ought to start a timer to re-enable them some time 5296e747b4bSRussell King * later? 5306e747b4bSRussell King */ 5316e747b4bSRussell King if (last == jiffies) { 5326e747b4bSRussell King lockup += 1; 5336e747b4bSRussell King if (lockup > 1000000) { 5346e747b4bSRussell King printk(KERN_ERR "\nInterrupt lockup detected - " 5356e747b4bSRussell King "disabling all expansion card interrupts\n"); 5366e747b4bSRussell King 5376e747b4bSRussell King desc->irq_data.chip->irq_mask(&desc->irq_data); 5386e747b4bSRussell King ecard_dump_irq_state(); 5396e747b4bSRussell King } 5406e747b4bSRussell King } else 5416e747b4bSRussell King lockup = 0; 5426e747b4bSRussell King 5436e747b4bSRussell King /* 5446e747b4bSRussell King * If we did not recognise the source of this interrupt, 5456e747b4bSRussell King * warn the user, but don't flood the user with these messages. 5466e747b4bSRussell King */ 5476e747b4bSRussell King if (!last || time_after(jiffies, last + 5*HZ)) { 5486e747b4bSRussell King last = jiffies; 5496e747b4bSRussell King printk(KERN_WARNING "Unrecognised interrupt from backplane\n"); 5506e747b4bSRussell King ecard_dump_irq_state(); 5516e747b4bSRussell King } 5526e747b4bSRussell King } 5536e747b4bSRussell King 554bd0b9ac4SThomas Gleixner static void ecard_irq_handler(struct irq_desc *desc) 5556e747b4bSRussell King { 5566e747b4bSRussell King ecard_t *ec; 5576e747b4bSRussell King int called = 0; 5586e747b4bSRussell King 5596e747b4bSRussell King desc->irq_data.chip->irq_mask(&desc->irq_data); 5606e747b4bSRussell King for (ec = cards; ec; ec = ec->next) { 5616e747b4bSRussell King int pending; 5626e747b4bSRussell King 56341569e37SRussell King if (!ec->claimed || !ec->irq || ec->slot_no == 8) 5646e747b4bSRussell King continue; 5656e747b4bSRussell King 5666e747b4bSRussell King if (ec->ops && ec->ops->irqpending) 5676e747b4bSRussell King pending = ec->ops->irqpending(ec); 5686e747b4bSRussell King else 5696e747b4bSRussell King pending = ecard_default_ops.irqpending(ec); 5706e747b4bSRussell King 5716e747b4bSRussell King if (pending) { 5726e747b4bSRussell King generic_handle_irq(ec->irq); 5736e747b4bSRussell King called ++; 5746e747b4bSRussell King } 5756e747b4bSRussell King } 5766e747b4bSRussell King desc->irq_data.chip->irq_unmask(&desc->irq_data); 5776e747b4bSRussell King 5786e747b4bSRussell King if (called == 0) 5796e747b4bSRussell King ecard_check_lockup(desc); 5806e747b4bSRussell King } 5816e747b4bSRussell King 5826e747b4bSRussell King static void __iomem *__ecard_address(ecard_t *ec, card_type_t type, card_speed_t speed) 5836e747b4bSRussell King { 5846e747b4bSRussell King void __iomem *address = NULL; 5856e747b4bSRussell King int slot = ec->slot_no; 5866e747b4bSRussell King 5876e747b4bSRussell King if (ec->slot_no == 8) 5886e747b4bSRussell King return ECARD_MEMC8_BASE; 5896e747b4bSRussell King 5906e747b4bSRussell King ectcr &= ~(1 << slot); 5916e747b4bSRussell King 5926e747b4bSRussell King switch (type) { 5936e747b4bSRussell King case ECARD_MEMC: 5946e747b4bSRussell King if (slot < 4) 5956e747b4bSRussell King address = ECARD_MEMC_BASE + (slot << 14); 5966e747b4bSRussell King break; 5976e747b4bSRussell King 5986e747b4bSRussell King case ECARD_IOC: 5996e747b4bSRussell King if (slot < 4) 6006e747b4bSRussell King address = ECARD_IOC_BASE + (slot << 14); 6016e747b4bSRussell King else 6026e747b4bSRussell King address = ECARD_IOC4_BASE + ((slot - 4) << 14); 6036e747b4bSRussell King if (address) 6046e747b4bSRussell King address += speed << 19; 6056e747b4bSRussell King break; 6066e747b4bSRussell King 6076e747b4bSRussell King case ECARD_EASI: 6086e747b4bSRussell King address = ECARD_EASI_BASE + (slot << 24); 6096e747b4bSRussell King if (speed == ECARD_FAST) 6106e747b4bSRussell King ectcr |= 1 << slot; 6116e747b4bSRussell King break; 6126e747b4bSRussell King 6136e747b4bSRussell King default: 6146e747b4bSRussell King break; 6156e747b4bSRussell King } 6166e747b4bSRussell King 6176e747b4bSRussell King #ifdef IOMD_ECTCR 6186e747b4bSRussell King iomd_writeb(ectcr, IOMD_ECTCR); 6196e747b4bSRussell King #endif 6206e747b4bSRussell King return address; 6216e747b4bSRussell King } 6226e747b4bSRussell King 6236e747b4bSRussell King static int ecard_prints(struct seq_file *m, ecard_t *ec) 6246e747b4bSRussell King { 6256e747b4bSRussell King seq_printf(m, " %d: %s ", ec->slot_no, ec->easi ? "EASI" : " "); 6266e747b4bSRussell King 6276e747b4bSRussell King if (ec->cid.id == 0) { 6286e747b4bSRussell King struct in_chunk_dir incd; 6296e747b4bSRussell King 6306e747b4bSRussell King seq_printf(m, "[%04X:%04X] ", 6316e747b4bSRussell King ec->cid.manufacturer, ec->cid.product); 6326e747b4bSRussell King 6336e747b4bSRussell King if (!ec->card_desc && ec->cid.cd && 6346e747b4bSRussell King ecard_readchunk(&incd, ec, 0xf5, 0)) { 6356e747b4bSRussell King ec->card_desc = kmalloc(strlen(incd.d.string)+1, GFP_KERNEL); 6366e747b4bSRussell King 6376e747b4bSRussell King if (ec->card_desc) 6386e747b4bSRussell King strcpy((char *)ec->card_desc, incd.d.string); 6396e747b4bSRussell King } 6406e747b4bSRussell King 6416e747b4bSRussell King seq_printf(m, "%s\n", ec->card_desc ? ec->card_desc : "*unknown*"); 6426e747b4bSRussell King } else 6436e747b4bSRussell King seq_printf(m, "Simple card %d\n", ec->cid.id); 6446e747b4bSRussell King 6456e747b4bSRussell King return 0; 6466e747b4bSRussell King } 6476e747b4bSRussell King 6486e747b4bSRussell King static int ecard_devices_proc_show(struct seq_file *m, void *v) 6496e747b4bSRussell King { 6506e747b4bSRussell King ecard_t *ec = cards; 6516e747b4bSRussell King 6526e747b4bSRussell King while (ec) { 6536e747b4bSRussell King ecard_prints(m, ec); 6546e747b4bSRussell King ec = ec->next; 6556e747b4bSRussell King } 6566e747b4bSRussell King return 0; 6576e747b4bSRussell King } 6586e747b4bSRussell King 6596e747b4bSRussell King static int ecard_devices_proc_open(struct inode *inode, struct file *file) 6606e747b4bSRussell King { 6616e747b4bSRussell King return single_open(file, ecard_devices_proc_show, NULL); 6626e747b4bSRussell King } 6636e747b4bSRussell King 6646e747b4bSRussell King static const struct file_operations bus_ecard_proc_fops = { 6656e747b4bSRussell King .owner = THIS_MODULE, 6666e747b4bSRussell King .open = ecard_devices_proc_open, 6676e747b4bSRussell King .read = seq_read, 6686e747b4bSRussell King .llseek = seq_lseek, 6696e747b4bSRussell King .release = single_release, 6706e747b4bSRussell King }; 6716e747b4bSRussell King 6726e747b4bSRussell King static struct proc_dir_entry *proc_bus_ecard_dir = NULL; 6736e747b4bSRussell King 6746e747b4bSRussell King static void ecard_proc_init(void) 6756e747b4bSRussell King { 6766e747b4bSRussell King proc_bus_ecard_dir = proc_mkdir("bus/ecard", NULL); 6776e747b4bSRussell King proc_create("devices", 0, proc_bus_ecard_dir, &bus_ecard_proc_fops); 6786e747b4bSRussell King } 6796e747b4bSRussell King 6806e747b4bSRussell King #define ec_set_resource(ec,nr,st,sz) \ 6816e747b4bSRussell King do { \ 6826e747b4bSRussell King (ec)->resource[nr].name = dev_name(&ec->dev); \ 6836e747b4bSRussell King (ec)->resource[nr].start = st; \ 6846e747b4bSRussell King (ec)->resource[nr].end = (st) + (sz) - 1; \ 6856e747b4bSRussell King (ec)->resource[nr].flags = IORESOURCE_MEM; \ 6866e747b4bSRussell King } while (0) 6876e747b4bSRussell King 6886e747b4bSRussell King static void __init ecard_free_card(struct expansion_card *ec) 6896e747b4bSRussell King { 6906e747b4bSRussell King int i; 6916e747b4bSRussell King 6926e747b4bSRussell King for (i = 0; i < ECARD_NUM_RESOURCES; i++) 6936e747b4bSRussell King if (ec->resource[i].flags) 6946e747b4bSRussell King release_resource(&ec->resource[i]); 6956e747b4bSRussell King 6966e747b4bSRussell King kfree(ec); 6976e747b4bSRussell King } 6986e747b4bSRussell King 6996e747b4bSRussell King static struct expansion_card *__init ecard_alloc_card(int type, int slot) 7006e747b4bSRussell King { 7016e747b4bSRussell King struct expansion_card *ec; 7026e747b4bSRussell King unsigned long base; 7036e747b4bSRussell King int i; 7046e747b4bSRussell King 7056e747b4bSRussell King ec = kzalloc(sizeof(ecard_t), GFP_KERNEL); 7066e747b4bSRussell King if (!ec) { 7076e747b4bSRussell King ec = ERR_PTR(-ENOMEM); 7086e747b4bSRussell King goto nomem; 7096e747b4bSRussell King } 7106e747b4bSRussell King 7116e747b4bSRussell King ec->slot_no = slot; 7126e747b4bSRussell King ec->easi = type == ECARD_EASI; 71341569e37SRussell King ec->irq = 0; 71441569e37SRussell King ec->fiq = 0; 7156e747b4bSRussell King ec->dma = NO_DMA; 7166e747b4bSRussell King ec->ops = &ecard_default_ops; 7176e747b4bSRussell King 7186e747b4bSRussell King dev_set_name(&ec->dev, "ecard%d", slot); 7196e747b4bSRussell King ec->dev.parent = NULL; 7206e747b4bSRussell King ec->dev.bus = &ecard_bus_type; 7216e747b4bSRussell King ec->dev.dma_mask = &ec->dma_mask; 7226e747b4bSRussell King ec->dma_mask = (u64)0xffffffff; 7236e747b4bSRussell King ec->dev.coherent_dma_mask = ec->dma_mask; 7246e747b4bSRussell King 7256e747b4bSRussell King if (slot < 4) { 7266e747b4bSRussell King ec_set_resource(ec, ECARD_RES_MEMC, 7276e747b4bSRussell King PODSLOT_MEMC_BASE + (slot << 14), 7286e747b4bSRussell King PODSLOT_MEMC_SIZE); 7296e747b4bSRussell King base = PODSLOT_IOC0_BASE + (slot << 14); 7306e747b4bSRussell King } else 7316e747b4bSRussell King base = PODSLOT_IOC4_BASE + ((slot - 4) << 14); 7326e747b4bSRussell King 7336e747b4bSRussell King #ifdef CONFIG_ARCH_RPC 7346e747b4bSRussell King if (slot < 8) { 7356e747b4bSRussell King ec_set_resource(ec, ECARD_RES_EASI, 7366e747b4bSRussell King PODSLOT_EASI_BASE + (slot << 24), 7376e747b4bSRussell King PODSLOT_EASI_SIZE); 7386e747b4bSRussell King } 7396e747b4bSRussell King 7406e747b4bSRussell King if (slot == 8) { 7416e747b4bSRussell King ec_set_resource(ec, ECARD_RES_MEMC, NETSLOT_BASE, NETSLOT_SIZE); 7426e747b4bSRussell King } else 7436e747b4bSRussell King #endif 7446e747b4bSRussell King 7456e747b4bSRussell King for (i = 0; i <= ECARD_RES_IOCSYNC - ECARD_RES_IOCSLOW; i++) 7466e747b4bSRussell King ec_set_resource(ec, i + ECARD_RES_IOCSLOW, 7476e747b4bSRussell King base + (i << 19), PODSLOT_IOC_SIZE); 7486e747b4bSRussell King 7496e747b4bSRussell King for (i = 0; i < ECARD_NUM_RESOURCES; i++) { 7506e747b4bSRussell King if (ec->resource[i].flags && 7516e747b4bSRussell King request_resource(&iomem_resource, &ec->resource[i])) { 7526e747b4bSRussell King dev_err(&ec->dev, "resource(s) not available\n"); 7536e747b4bSRussell King ec->resource[i].end -= ec->resource[i].start; 7546e747b4bSRussell King ec->resource[i].start = 0; 7556e747b4bSRussell King ec->resource[i].flags = 0; 7566e747b4bSRussell King } 7576e747b4bSRussell King } 7586e747b4bSRussell King 7596e747b4bSRussell King nomem: 7606e747b4bSRussell King return ec; 7616e747b4bSRussell King } 7626e747b4bSRussell King 7636e747b4bSRussell King static ssize_t ecard_show_irq(struct device *dev, struct device_attribute *attr, char *buf) 7646e747b4bSRussell King { 7656e747b4bSRussell King struct expansion_card *ec = ECARD_DEV(dev); 7666e747b4bSRussell King return sprintf(buf, "%u\n", ec->irq); 7676e747b4bSRussell King } 7686e747b4bSRussell King 7696e747b4bSRussell King static ssize_t ecard_show_dma(struct device *dev, struct device_attribute *attr, char *buf) 7706e747b4bSRussell King { 7716e747b4bSRussell King struct expansion_card *ec = ECARD_DEV(dev); 7726e747b4bSRussell King return sprintf(buf, "%u\n", ec->dma); 7736e747b4bSRussell King } 7746e747b4bSRussell King 7756e747b4bSRussell King static ssize_t ecard_show_resources(struct device *dev, struct device_attribute *attr, char *buf) 7766e747b4bSRussell King { 7776e747b4bSRussell King struct expansion_card *ec = ECARD_DEV(dev); 7786e747b4bSRussell King char *str = buf; 7796e747b4bSRussell King int i; 7806e747b4bSRussell King 7816e747b4bSRussell King for (i = 0; i < ECARD_NUM_RESOURCES; i++) 7826e747b4bSRussell King str += sprintf(str, "%08x %08x %08lx\n", 7836e747b4bSRussell King ec->resource[i].start, 7846e747b4bSRussell King ec->resource[i].end, 7856e747b4bSRussell King ec->resource[i].flags); 7866e747b4bSRussell King 7876e747b4bSRussell King return str - buf; 7886e747b4bSRussell King } 7896e747b4bSRussell King 7906e747b4bSRussell King static ssize_t ecard_show_vendor(struct device *dev, struct device_attribute *attr, char *buf) 7916e747b4bSRussell King { 7926e747b4bSRussell King struct expansion_card *ec = ECARD_DEV(dev); 7936e747b4bSRussell King return sprintf(buf, "%u\n", ec->cid.manufacturer); 7946e747b4bSRussell King } 7956e747b4bSRussell King 7966e747b4bSRussell King static ssize_t ecard_show_device(struct device *dev, struct device_attribute *attr, char *buf) 7976e747b4bSRussell King { 7986e747b4bSRussell King struct expansion_card *ec = ECARD_DEV(dev); 7996e747b4bSRussell King return sprintf(buf, "%u\n", ec->cid.product); 8006e747b4bSRussell King } 8016e747b4bSRussell King 8026e747b4bSRussell King static ssize_t ecard_show_type(struct device *dev, struct device_attribute *attr, char *buf) 8036e747b4bSRussell King { 8046e747b4bSRussell King struct expansion_card *ec = ECARD_DEV(dev); 8056e747b4bSRussell King return sprintf(buf, "%s\n", ec->easi ? "EASI" : "IOC"); 8066e747b4bSRussell King } 8076e747b4bSRussell King 8086e747b4bSRussell King static struct device_attribute ecard_dev_attrs[] = { 8096e747b4bSRussell King __ATTR(device, S_IRUGO, ecard_show_device, NULL), 8106e747b4bSRussell King __ATTR(dma, S_IRUGO, ecard_show_dma, NULL), 8116e747b4bSRussell King __ATTR(irq, S_IRUGO, ecard_show_irq, NULL), 8126e747b4bSRussell King __ATTR(resource, S_IRUGO, ecard_show_resources, NULL), 8136e747b4bSRussell King __ATTR(type, S_IRUGO, ecard_show_type, NULL), 8146e747b4bSRussell King __ATTR(vendor, S_IRUGO, ecard_show_vendor, NULL), 8156e747b4bSRussell King __ATTR_NULL, 8166e747b4bSRussell King }; 8176e747b4bSRussell King 8186e747b4bSRussell King 8196e747b4bSRussell King int ecard_request_resources(struct expansion_card *ec) 8206e747b4bSRussell King { 8216e747b4bSRussell King int i, err = 0; 8226e747b4bSRussell King 8236e747b4bSRussell King for (i = 0; i < ECARD_NUM_RESOURCES; i++) { 8246e747b4bSRussell King if (ecard_resource_end(ec, i) && 8256e747b4bSRussell King !request_mem_region(ecard_resource_start(ec, i), 8266e747b4bSRussell King ecard_resource_len(ec, i), 8276e747b4bSRussell King ec->dev.driver->name)) { 8286e747b4bSRussell King err = -EBUSY; 8296e747b4bSRussell King break; 8306e747b4bSRussell King } 8316e747b4bSRussell King } 8326e747b4bSRussell King 8336e747b4bSRussell King if (err) { 8346e747b4bSRussell King while (i--) 8356e747b4bSRussell King if (ecard_resource_end(ec, i)) 8366e747b4bSRussell King release_mem_region(ecard_resource_start(ec, i), 8376e747b4bSRussell King ecard_resource_len(ec, i)); 8386e747b4bSRussell King } 8396e747b4bSRussell King return err; 8406e747b4bSRussell King } 8416e747b4bSRussell King EXPORT_SYMBOL(ecard_request_resources); 8426e747b4bSRussell King 8436e747b4bSRussell King void ecard_release_resources(struct expansion_card *ec) 8446e747b4bSRussell King { 8456e747b4bSRussell King int i; 8466e747b4bSRussell King 8476e747b4bSRussell King for (i = 0; i < ECARD_NUM_RESOURCES; i++) 8486e747b4bSRussell King if (ecard_resource_end(ec, i)) 8496e747b4bSRussell King release_mem_region(ecard_resource_start(ec, i), 8506e747b4bSRussell King ecard_resource_len(ec, i)); 8516e747b4bSRussell King } 8526e747b4bSRussell King EXPORT_SYMBOL(ecard_release_resources); 8536e747b4bSRussell King 8546e747b4bSRussell King void ecard_setirq(struct expansion_card *ec, const struct expansion_card_ops *ops, void *irq_data) 8556e747b4bSRussell King { 8566e747b4bSRussell King ec->irq_data = irq_data; 8576e747b4bSRussell King barrier(); 8586e747b4bSRussell King ec->ops = ops; 8596e747b4bSRussell King } 8606e747b4bSRussell King EXPORT_SYMBOL(ecard_setirq); 8616e747b4bSRussell King 8626e747b4bSRussell King void __iomem *ecardm_iomap(struct expansion_card *ec, unsigned int res, 8636e747b4bSRussell King unsigned long offset, unsigned long maxsize) 8646e747b4bSRussell King { 8656e747b4bSRussell King unsigned long start = ecard_resource_start(ec, res); 8666e747b4bSRussell King unsigned long end = ecard_resource_end(ec, res); 8676e747b4bSRussell King 8686e747b4bSRussell King if (offset > (end - start)) 8696e747b4bSRussell King return NULL; 8706e747b4bSRussell King 8716e747b4bSRussell King start += offset; 8726e747b4bSRussell King if (maxsize && end - start > maxsize) 8736e747b4bSRussell King end = start + maxsize; 8746e747b4bSRussell King 8756e747b4bSRussell King return devm_ioremap(&ec->dev, start, end - start); 8766e747b4bSRussell King } 8776e747b4bSRussell King EXPORT_SYMBOL(ecardm_iomap); 8786e747b4bSRussell King 8796e747b4bSRussell King /* 8806e747b4bSRussell King * Probe for an expansion card. 8816e747b4bSRussell King * 8826e747b4bSRussell King * If bit 1 of the first byte of the card is set, then the 8836e747b4bSRussell King * card does not exist. 8846e747b4bSRussell King */ 885b4ac0849SRussell King static int __init ecard_probe(int slot, unsigned irq, card_type_t type) 8866e747b4bSRussell King { 8876e747b4bSRussell King ecard_t **ecp; 8886e747b4bSRussell King ecard_t *ec; 8896e747b4bSRussell King struct ex_ecid cid; 8906e747b4bSRussell King void __iomem *addr; 8916e747b4bSRussell King int i, rc; 8926e747b4bSRussell King 8936e747b4bSRussell King ec = ecard_alloc_card(type, slot); 8946e747b4bSRussell King if (IS_ERR(ec)) { 8956e747b4bSRussell King rc = PTR_ERR(ec); 8966e747b4bSRussell King goto nomem; 8976e747b4bSRussell King } 8986e747b4bSRussell King 8996e747b4bSRussell King rc = -ENODEV; 9006e747b4bSRussell King if ((addr = __ecard_address(ec, type, ECARD_SYNC)) == NULL) 9016e747b4bSRussell King goto nodev; 9026e747b4bSRussell King 9036e747b4bSRussell King cid.r_zero = 1; 9046e747b4bSRussell King ecard_readbytes(&cid, ec, 0, 16, 0); 9056e747b4bSRussell King if (cid.r_zero) 9066e747b4bSRussell King goto nodev; 9076e747b4bSRussell King 9086e747b4bSRussell King ec->cid.id = cid.r_id; 9096e747b4bSRussell King ec->cid.cd = cid.r_cd; 9106e747b4bSRussell King ec->cid.is = cid.r_is; 9116e747b4bSRussell King ec->cid.w = cid.r_w; 9126e747b4bSRussell King ec->cid.manufacturer = ecard_getu16(cid.r_manu); 9136e747b4bSRussell King ec->cid.product = ecard_getu16(cid.r_prod); 9146e747b4bSRussell King ec->cid.country = cid.r_country; 9156e747b4bSRussell King ec->cid.irqmask = cid.r_irqmask; 9166e747b4bSRussell King ec->cid.irqoff = ecard_gets24(cid.r_irqoff); 9176e747b4bSRussell King ec->cid.fiqmask = cid.r_fiqmask; 9186e747b4bSRussell King ec->cid.fiqoff = ecard_gets24(cid.r_fiqoff); 9196e747b4bSRussell King ec->fiqaddr = 9206e747b4bSRussell King ec->irqaddr = addr; 9216e747b4bSRussell King 9226e747b4bSRussell King if (ec->cid.is) { 9236e747b4bSRussell King ec->irqmask = ec->cid.irqmask; 9246e747b4bSRussell King ec->irqaddr += ec->cid.irqoff; 9256e747b4bSRussell King ec->fiqmask = ec->cid.fiqmask; 9266e747b4bSRussell King ec->fiqaddr += ec->cid.fiqoff; 9276e747b4bSRussell King } else { 9286e747b4bSRussell King ec->irqmask = 1; 9296e747b4bSRussell King ec->fiqmask = 4; 9306e747b4bSRussell King } 9316e747b4bSRussell King 9326e747b4bSRussell King for (i = 0; i < ARRAY_SIZE(blacklist); i++) 9336e747b4bSRussell King if (blacklist[i].manufacturer == ec->cid.manufacturer && 9346e747b4bSRussell King blacklist[i].product == ec->cid.product) { 9356e747b4bSRussell King ec->card_desc = blacklist[i].type; 9366e747b4bSRussell King break; 9376e747b4bSRussell King } 9386e747b4bSRussell King 939b4ac0849SRussell King ec->irq = irq; 940b4ac0849SRussell King 9416e747b4bSRussell King /* 9426e747b4bSRussell King * hook the interrupt handlers 9436e747b4bSRussell King */ 9446e747b4bSRussell King if (slot < 8) { 9456e747b4bSRussell King irq_set_chip_and_handler(ec->irq, &ecard_chip, 9466e747b4bSRussell King handle_level_irq); 947c402c110SRussell King irq_set_chip_data(ec->irq, ec); 948e8d36d5dSRob Herring irq_clear_status_flags(ec->irq, IRQ_NOREQUEST); 9496e747b4bSRussell King } 9506e747b4bSRussell King 9516e747b4bSRussell King #ifdef CONFIG_ARCH_RPC 9526e747b4bSRussell King /* On RiscPC, only first two slots have DMA capability */ 9536e747b4bSRussell King if (slot < 2) 9546e747b4bSRussell King ec->dma = 2 + slot; 9556e747b4bSRussell King #endif 9566e747b4bSRussell King 9576e747b4bSRussell King for (ecp = &cards; *ecp; ecp = &(*ecp)->next); 9586e747b4bSRussell King 9596e747b4bSRussell King *ecp = ec; 9606e747b4bSRussell King slot_to_expcard[slot] = ec; 9616e747b4bSRussell King 9625f07809eSArnd Bergmann rc = device_register(&ec->dev); 9635f07809eSArnd Bergmann if (rc) 9645f07809eSArnd Bergmann goto nodev; 9656e747b4bSRussell King 9666e747b4bSRussell King return 0; 9676e747b4bSRussell King 9686e747b4bSRussell King nodev: 9696e747b4bSRussell King ecard_free_card(ec); 9706e747b4bSRussell King nomem: 9716e747b4bSRussell King return rc; 9726e747b4bSRussell King } 9736e747b4bSRussell King 9746e747b4bSRussell King /* 9756e747b4bSRussell King * Initialise the expansion card system. 9766e747b4bSRussell King * Locate all hardware - interrupt management and 9776e747b4bSRussell King * actual cards. 9786e747b4bSRussell King */ 9796e747b4bSRussell King static int __init ecard_init(void) 9806e747b4bSRussell King { 9816e747b4bSRussell King struct task_struct *task; 982530c2eaaSRussell King int slot, irqbase; 983b4ac0849SRussell King 984b4ac0849SRussell King irqbase = irq_alloc_descs(-1, 0, 8, -1); 985b4ac0849SRussell King if (irqbase < 0) 986b4ac0849SRussell King return irqbase; 9876e747b4bSRussell King 9886e747b4bSRussell King task = kthread_run(ecard_task, NULL, "kecardd"); 9896e747b4bSRussell King if (IS_ERR(task)) { 9906e747b4bSRussell King printk(KERN_ERR "Ecard: unable to create kernel thread: %ld\n", 9916e747b4bSRussell King PTR_ERR(task)); 992b4ac0849SRussell King irq_free_descs(irqbase, 8); 9936e747b4bSRussell King return PTR_ERR(task); 9946e747b4bSRussell King } 9956e747b4bSRussell King 9966e747b4bSRussell King printk("Probing expansion cards\n"); 9976e747b4bSRussell King 9986e747b4bSRussell King for (slot = 0; slot < 8; slot ++) { 999b4ac0849SRussell King if (ecard_probe(slot, irqbase + slot, ECARD_EASI) == -ENODEV) 1000b4ac0849SRussell King ecard_probe(slot, irqbase + slot, ECARD_IOC); 10016e747b4bSRussell King } 10026e747b4bSRussell King 1003b4ac0849SRussell King ecard_probe(8, 11, ECARD_IOC); 10046e747b4bSRussell King 1005530c2eaaSRussell King irq_set_chained_handler(IRQ_EXPANSIONCARD, ecard_irq_handler); 10066e747b4bSRussell King 10076e747b4bSRussell King ecard_proc_init(); 10086e747b4bSRussell King 10096e747b4bSRussell King return 0; 10106e747b4bSRussell King } 10116e747b4bSRussell King 10126e747b4bSRussell King subsys_initcall(ecard_init); 10136e747b4bSRussell King 10146e747b4bSRussell King /* 10156e747b4bSRussell King * ECARD "bus" 10166e747b4bSRussell King */ 10176e747b4bSRussell King static const struct ecard_id * 10186e747b4bSRussell King ecard_match_device(const struct ecard_id *ids, struct expansion_card *ec) 10196e747b4bSRussell King { 10206e747b4bSRussell King int i; 10216e747b4bSRussell King 10226e747b4bSRussell King for (i = 0; ids[i].manufacturer != 65535; i++) 10236e747b4bSRussell King if (ec->cid.manufacturer == ids[i].manufacturer && 10246e747b4bSRussell King ec->cid.product == ids[i].product) 10256e747b4bSRussell King return ids + i; 10266e747b4bSRussell King 10276e747b4bSRussell King return NULL; 10286e747b4bSRussell King } 10296e747b4bSRussell King 10306e747b4bSRussell King static int ecard_drv_probe(struct device *dev) 10316e747b4bSRussell King { 10326e747b4bSRussell King struct expansion_card *ec = ECARD_DEV(dev); 10336e747b4bSRussell King struct ecard_driver *drv = ECARD_DRV(dev->driver); 10346e747b4bSRussell King const struct ecard_id *id; 10356e747b4bSRussell King int ret; 10366e747b4bSRussell King 10376e747b4bSRussell King id = ecard_match_device(drv->id_table, ec); 10386e747b4bSRussell King 10396e747b4bSRussell King ec->claimed = 1; 10406e747b4bSRussell King ret = drv->probe(ec, id); 10416e747b4bSRussell King if (ret) 10426e747b4bSRussell King ec->claimed = 0; 10436e747b4bSRussell King return ret; 10446e747b4bSRussell King } 10456e747b4bSRussell King 10466e747b4bSRussell King static int ecard_drv_remove(struct device *dev) 10476e747b4bSRussell King { 10486e747b4bSRussell King struct expansion_card *ec = ECARD_DEV(dev); 10496e747b4bSRussell King struct ecard_driver *drv = ECARD_DRV(dev->driver); 10506e747b4bSRussell King 10516e747b4bSRussell King drv->remove(ec); 10526e747b4bSRussell King ec->claimed = 0; 10536e747b4bSRussell King 10546e747b4bSRussell King /* 10556e747b4bSRussell King * Restore the default operations. We ensure that the 10566e747b4bSRussell King * ops are set before we change the data. 10576e747b4bSRussell King */ 10586e747b4bSRussell King ec->ops = &ecard_default_ops; 10596e747b4bSRussell King barrier(); 10606e747b4bSRussell King ec->irq_data = NULL; 10616e747b4bSRussell King 10626e747b4bSRussell King return 0; 10636e747b4bSRussell King } 10646e747b4bSRussell King 10656e747b4bSRussell King /* 10666e747b4bSRussell King * Before rebooting, we must make sure that the expansion card is in a 10676e747b4bSRussell King * sensible state, so it can be re-detected. This means that the first 10686e747b4bSRussell King * page of the ROM must be visible. We call the expansion cards reset 10696e747b4bSRussell King * handler, if any. 10706e747b4bSRussell King */ 10716e747b4bSRussell King static void ecard_drv_shutdown(struct device *dev) 10726e747b4bSRussell King { 10736e747b4bSRussell King struct expansion_card *ec = ECARD_DEV(dev); 10746e747b4bSRussell King struct ecard_driver *drv = ECARD_DRV(dev->driver); 10756e747b4bSRussell King struct ecard_request req; 10766e747b4bSRussell King 10776e747b4bSRussell King if (dev->driver) { 10786e747b4bSRussell King if (drv->shutdown) 10796e747b4bSRussell King drv->shutdown(ec); 10806e747b4bSRussell King ec->claimed = 0; 10816e747b4bSRussell King } 10826e747b4bSRussell King 10836e747b4bSRussell King /* 10846e747b4bSRussell King * If this card has a loader, call the reset handler. 10856e747b4bSRussell King */ 10866e747b4bSRussell King if (ec->loader) { 10876e747b4bSRussell King req.fn = ecard_task_reset; 10886e747b4bSRussell King req.ec = ec; 10896e747b4bSRussell King ecard_call(&req); 10906e747b4bSRussell King } 10916e747b4bSRussell King } 10926e747b4bSRussell King 10936e747b4bSRussell King int ecard_register_driver(struct ecard_driver *drv) 10946e747b4bSRussell King { 10956e747b4bSRussell King drv->drv.bus = &ecard_bus_type; 10966e747b4bSRussell King 10976e747b4bSRussell King return driver_register(&drv->drv); 10986e747b4bSRussell King } 10996e747b4bSRussell King 11006e747b4bSRussell King void ecard_remove_driver(struct ecard_driver *drv) 11016e747b4bSRussell King { 11026e747b4bSRussell King driver_unregister(&drv->drv); 11036e747b4bSRussell King } 11046e747b4bSRussell King 11056e747b4bSRussell King static int ecard_match(struct device *_dev, struct device_driver *_drv) 11066e747b4bSRussell King { 11076e747b4bSRussell King struct expansion_card *ec = ECARD_DEV(_dev); 11086e747b4bSRussell King struct ecard_driver *drv = ECARD_DRV(_drv); 11096e747b4bSRussell King int ret; 11106e747b4bSRussell King 11116e747b4bSRussell King if (drv->id_table) { 11126e747b4bSRussell King ret = ecard_match_device(drv->id_table, ec) != NULL; 11136e747b4bSRussell King } else { 11146e747b4bSRussell King ret = ec->cid.id == drv->id; 11156e747b4bSRussell King } 11166e747b4bSRussell King 11176e747b4bSRussell King return ret; 11186e747b4bSRussell King } 11196e747b4bSRussell King 11206e747b4bSRussell King struct bus_type ecard_bus_type = { 11216e747b4bSRussell King .name = "ecard", 11226e747b4bSRussell King .dev_attrs = ecard_dev_attrs, 11236e747b4bSRussell King .match = ecard_match, 11246e747b4bSRussell King .probe = ecard_drv_probe, 11256e747b4bSRussell King .remove = ecard_drv_remove, 11266e747b4bSRussell King .shutdown = ecard_drv_shutdown, 11276e747b4bSRussell King }; 11286e747b4bSRussell King 11296e747b4bSRussell King static int ecard_bus_init(void) 11306e747b4bSRussell King { 11316e747b4bSRussell King return bus_register(&ecard_bus_type); 11326e747b4bSRussell King } 11336e747b4bSRussell King 11346e747b4bSRussell King postcore_initcall(ecard_bus_init); 11356e747b4bSRussell King 11366e747b4bSRussell King EXPORT_SYMBOL(ecard_readchunk); 11376e747b4bSRussell King EXPORT_SYMBOL(ecard_register_driver); 11386e747b4bSRussell King EXPORT_SYMBOL(ecard_remove_driver); 11396e747b4bSRussell King EXPORT_SYMBOL(ecard_bus_type); 1140