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