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